Netdev List
 help / color / mirror / Atom feed
* [PATCH 1/37] drivers/net/wireless/libertas: Use kmemdup
From: Julia Lawall @ 2010-05-15 21:12 UTC (permalink / raw)
  To: Dan Williams, John W. Linville,
	libertas-dev-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA, linux-kernel

From: Julia Lawall <julia-dAYI7NvHqcQ@public.gmane.org>

Use kmemdup when some other buffer is immediately copied into the
allocated region.

A simplified version of the semantic patch that makes this change is as
follows: (http://coccinelle.lip6.fr/)

// <smpl>
@@
expression from,to,size,flag;
statement S;
@@

-  to = \(kmalloc\|kzalloc\)(size,flag);
+  to = kmemdup(from,size,flag);
   if (to==NULL || ...) S
-  memcpy(to, from, size);
// </smpl>

Signed-off-by: Julia Lawall <julia-dAYI7NvHqcQ@public.gmane.org>

---
 drivers/net/wireless/libertas/if_usb.c |    6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff -u -p a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -618,16 +618,14 @@ static void if_usb_receive_fwload(struct
 		return;
 	}
 
-	syncfwheader = kmalloc(sizeof(struct fwsyncheader), GFP_ATOMIC);
+	syncfwheader = kmemdup(skb->data + IPFIELD_ALIGN_OFFSET,
+			       sizeof(struct fwsyncheader), GFP_ATOMIC);
 	if (!syncfwheader) {
 		lbs_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n");
 		kfree_skb(skb);
 		return;
 	}
 
-	memcpy(syncfwheader, skb->data + IPFIELD_ALIGN_OFFSET,
-	       sizeof(struct fwsyncheader));

^ permalink raw reply

* Re: [patch] pm_qos update fixing mmotm 2010-05-11 -dies in pm_qos_update_request()
From: Rafael J. Wysocki @ 2010-05-15 19:38 UTC (permalink / raw)
  To: markgross
  Cc: mgross, Valdis.Kletnieks, e1000-devel, netdev, linux-kernel,
	linux-pm, akpm, davem
In-Reply-To: <20100515021922.GA5041@thegnar.org>

On Saturday 15 May 2010, mgross wrote:
> I apologize for the goofy email address.  
> 
> The following is a fix for the crash reported by Valdis.
> 
> The problem was that the original pm_qos silently fails when a request
> update is passed to a parameter that has not been added to the list
> yet.  It seems that the e1000e is doing this.  This update restores this
> behavior.
> 
> I need to think about how to better handle such abuse, but for now this
> restores the original behavior.

Can you please post a signed-off incremental patch against

git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6.git for-llinus

that contains your original PM QOS update?

Thanks,
Rafael


> Signed-off-by: markgross <markgross@thegnar.org>
> --mgross
> 
> 
> From 66700dc26ab7582bc7351541ba2e6241cc4b4144 Mon Sep 17 00:00:00 2001
> From: mgross <mgross@mgross-desktop.(none)>
> Date: Fri, 14 May 2010 19:05:44 -0700
> Subject: [PATCH] PM QOS update
>  This patch changes the string based list management to a handle base
>  implementation to help with the hot path use of pm-qos, it also renames
>  much of the API to use "request" as opposed to "requirement" that was
>  used in the initial implementation.  I did this because request more
>  accurately represents what it actually does.
> 
> Also, I added a string based ABI for users wanting to use a string
> interface.  So if the user writes 0xDDDDDDDD formatted hex it will be
> accepted by the interface.  (someone asked me for it and I don't think
> it hurts anything.)
> 
> This patch updates some documentation input I got from Randy.
> 
> This version handles a use case where pm_qos update requests need to
> silently not fail if the update is being sent to a handle that is null.
> This is what happened in the initial version of pm-qos if you used a
> string that wasn't in the list.
> 
> Signed-off-by: markgross <mgross@linux.intel.com>
> ---
>  Documentation/power/pm_qos_interface.txt |   48 ++++---
>  drivers/acpi/processor_idle.c            |    2 +-
>  drivers/cpuidle/governors/ladder.c       |    2 +-
>  drivers/cpuidle/governors/menu.c         |    2 +-
>  drivers/net/e1000e/netdev.c              |   22 ++--
>  drivers/net/igbvf/netdev.c               |    6 +-
>  drivers/net/wireless/ipw2x00/ipw2100.c   |   11 +-
>  include/linux/netdevice.h                |    4 +
>  include/linux/pm_qos_params.h            |   14 +-
>  include/sound/pcm.h                      |    3 +-
>  kernel/pm_qos_params.c                   |  217 +++++++++++++++---------------
>  net/mac80211/mlme.c                      |    2 +-
>  sound/core/pcm.c                         |    3 -
>  sound/core/pcm_native.c                  |   14 +-
>  14 files changed, 179 insertions(+), 171 deletions(-)
> 
> diff --git a/Documentation/power/pm_qos_interface.txt b/Documentation/power/pm_qos_interface.txt
> index c40866e..bfed898 100644
> --- a/Documentation/power/pm_qos_interface.txt
> +++ b/Documentation/power/pm_qos_interface.txt
> @@ -18,44 +18,46 @@ and pm_qos_params.h.  This is done because having the available parameters
>  being runtime configurable or changeable from a driver was seen as too easy to
>  abuse.
>  
> -For each parameter a list of performance requirements is maintained along with
> +For each parameter a list of performance requests is maintained along with
>  an aggregated target value.  The aggregated target value is updated with
> -changes to the requirement list or elements of the list.  Typically the
> -aggregated target value is simply the max or min of the requirement values held
> +changes to the request list or elements of the list.  Typically the
> +aggregated target value is simply the max or min of the request values held
>  in the parameter list elements.
>  
>  From kernel mode the use of this interface is simple:
> -pm_qos_add_requirement(param_id, name, target_value):
> -Will insert a named element in the list for that identified PM_QOS parameter
> -with the target value.  Upon change to this list the new target is recomputed
> -and any registered notifiers are called only if the target value is now
> -different.
>  
> -pm_qos_update_requirement(param_id, name, new_target_value):
> -Will search the list identified by the param_id for the named list element and
> -then update its target value, calling the notification tree if the aggregated
> -target is changed.  with that name is already registered.
> +handle = pm_qos_add_request(param_class, target_value):
> +Will insert an element into the list for that identified PM_QOS class with the
> +target value.  Upon change to this list the new target is recomputed and any
> +registered notifiers are called only if the target value is now different.
> +Clients of pm_qos need to save the returned handle.
>  
> -pm_qos_remove_requirement(param_id, name):
> -Will search the identified list for the named element and remove it, after
> -removal it will update the aggregate target and call the notification tree if
> -the target was changed as a result of removing the named requirement.
> +void pm_qos_update_request(handle, new_target_value):
> +Will update the list element pointed to by the handle with the new target value
> +and recompute the new aggregated target, calling the notification tree if the
> +target is changed.
> +
> +void pm_qos_remove_request(handle):
> +Will remove the element.  After removal it will update the aggregate target and
> +call the notification tree if the target was changed as a result of removing
> +the request.
>  
>  
>  From user mode:
> -Only processes can register a pm_qos requirement.  To provide for automatic
> -cleanup for process the interface requires the process to register its
> -parameter requirements in the following way:
> +Only processes can register a pm_qos request.  To provide for automatic
> +cleanup of a process, the interface requires the process to register its
> +parameter requests in the following way:
>  
>  To register the default pm_qos target for the specific parameter, the process
>  must open one of /dev/[cpu_dma_latency, network_latency, network_throughput]
>  
>  As long as the device node is held open that process has a registered
> -requirement on the parameter.  The name of the requirement is "process_<PID>"
> -derived from the current->pid from within the open system call.
> +request on the parameter.
>  
> -To change the requested target value the process needs to write a s32 value to
> -the open device node.  This translates to a pm_qos_update_requirement call.
> +To change the requested target value the process needs to write an s32 value to
> +the open device node.  Alternatively the user mode program could write a hex
> +string for the value using 10 char long format e.g. "0x12345678".  This
> +translates to a pm_qos_update_request call.
>  
>  To remove the user mode request for a target value simply close the device
>  node.
> diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
> index 5939e7f..c3817e1 100644
> --- a/drivers/acpi/processor_idle.c
> +++ b/drivers/acpi/processor_idle.c
> @@ -698,7 +698,7 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
>  		   "max_cstate:              C%d\n"
>  		   "maximum allowed latency: %d usec\n",
>  		   pr->power.state ? pr->power.state - pr->power.states : 0,
> -		   max_cstate, pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY));
> +		   max_cstate, pm_qos_request(PM_QOS_CPU_DMA_LATENCY));
>  
>  	seq_puts(seq, "states:\n");
>  
> diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c
> index 1c1ceb4..12c9890 100644
> --- a/drivers/cpuidle/governors/ladder.c
> +++ b/drivers/cpuidle/governors/ladder.c
> @@ -67,7 +67,7 @@ static int ladder_select_state(struct cpuidle_device *dev)
>  	struct ladder_device *ldev = &__get_cpu_var(ladder_devices);
>  	struct ladder_device_state *last_state;
>  	int last_residency, last_idx = ldev->last_state_idx;
> -	int latency_req = pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY);
> +	int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
>  
>  	/* Special case when user has set very strict latency requirement */
>  	if (unlikely(latency_req == 0)) {
> diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
> index f8e57c6..b81ad9c 100644
> --- a/drivers/cpuidle/governors/menu.c
> +++ b/drivers/cpuidle/governors/menu.c
> @@ -182,7 +182,7 @@ static u64 div_round64(u64 dividend, u32 divisor)
>  static int menu_select(struct cpuidle_device *dev)
>  {
>  	struct menu_device *data = &__get_cpu_var(menu_devices);
> -	int latency_req = pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY);
> +	int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
>  	int i;
>  	int multiplier;
>  
> diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
> index dbf8178..d5d55c6 100644
> --- a/drivers/net/e1000e/netdev.c
> +++ b/drivers/net/e1000e/netdev.c
> @@ -2524,12 +2524,12 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
>  			 * excessive C-state transition latencies result in
>  			 * dropped transactions.
>  			 */
> -			pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY,
> -						  adapter->netdev->name, 55);
> +			pm_qos_update_request(
> +				adapter->netdev->pm_qos_req, 55);
>  		} else {
> -			pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY,
> -						  adapter->netdev->name,
> -						  PM_QOS_DEFAULT_VALUE);
> +			pm_qos_update_request(
> +				adapter->netdev->pm_qos_req,
> +				PM_QOS_DEFAULT_VALUE);
>  		}
>  	}
>  
> @@ -2824,8 +2824,8 @@ int e1000e_up(struct e1000_adapter *adapter)
>  
>  	/* DMA latency requirement to workaround early-receive/jumbo issue */
>  	if (adapter->flags & FLAG_HAS_ERT)
> -		pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY,
> -		                       adapter->netdev->name,
> +		adapter->netdev->pm_qos_req =
> +			pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
>  				       PM_QOS_DEFAULT_VALUE);
>  
>  	/* hardware has been reset, we need to reload some things */
> @@ -2887,9 +2887,11 @@ void e1000e_down(struct e1000_adapter *adapter)
>  	e1000_clean_tx_ring(adapter);
>  	e1000_clean_rx_ring(adapter);
>  
> -	if (adapter->flags & FLAG_HAS_ERT)
> -		pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
> -		                          adapter->netdev->name);
> +	if (adapter->flags & FLAG_HAS_ERT) {
> +		pm_qos_remove_request(
> +			      adapter->netdev->pm_qos_req);
> +		adapter->netdev->pm_qos_req = NULL;
> +	}
>  
>  	/*
>  	 * TODO: for power management, we could drop the link and
> diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c
> index 1b1edad..f16e981 100644
> --- a/drivers/net/igbvf/netdev.c
> +++ b/drivers/net/igbvf/netdev.c
> @@ -48,6 +48,7 @@
>  #define DRV_VERSION "1.0.0-k0"
>  char igbvf_driver_name[] = "igbvf";
>  const char igbvf_driver_version[] = DRV_VERSION;
> +struct pm_qos_request_list *igbvf_driver_pm_qos_req;
>  static const char igbvf_driver_string[] =
>  				"Intel(R) Virtual Function Network Driver";
>  static const char igbvf_copyright[] = "Copyright (c) 2009 Intel Corporation.";
> @@ -2899,7 +2900,7 @@ static int __init igbvf_init_module(void)
>  	printk(KERN_INFO "%s\n", igbvf_copyright);
>  
>  	ret = pci_register_driver(&igbvf_driver);
> -	pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, igbvf_driver_name,
> +	igbvf_driver_pm_qos_req = pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
>  	                       PM_QOS_DEFAULT_VALUE);
>  
>  	return ret;
> @@ -2915,7 +2916,8 @@ module_init(igbvf_init_module);
>  static void __exit igbvf_exit_module(void)
>  {
>  	pci_unregister_driver(&igbvf_driver);
> -	pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, igbvf_driver_name);
> +	pm_qos_remove_request(igbvf_driver_pm_qos_req);
> +	igbvf_driver_pm_qos_req = NULL;
>  }
>  module_exit(igbvf_exit_module);
>  
> diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
> index 9b72c45..2b05fe5 100644
> --- a/drivers/net/wireless/ipw2x00/ipw2100.c
> +++ b/drivers/net/wireless/ipw2x00/ipw2100.c
> @@ -174,6 +174,8 @@ that only one external action is invoked at a time.
>  #define DRV_DESCRIPTION	"Intel(R) PRO/Wireless 2100 Network Driver"
>  #define DRV_COPYRIGHT	"Copyright(c) 2003-2006 Intel Corporation"
>  
> +struct pm_qos_request_list *ipw2100_pm_qos_req;
> +
>  /* Debugging stuff */
>  #ifdef CONFIG_IPW2100_DEBUG
>  #define IPW2100_RX_DEBUG	/* Reception debugging */
> @@ -1739,7 +1741,7 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
>  	/* the ipw2100 hardware really doesn't want power management delays
>  	 * longer than 175usec
>  	 */
> -	pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100", 175);
> +	pm_qos_update_request(ipw2100_pm_qos_req, 175);
>  
>  	/* If the interrupt is enabled, turn it off... */
>  	spin_lock_irqsave(&priv->low_lock, flags);
> @@ -1887,8 +1889,7 @@ static void ipw2100_down(struct ipw2100_priv *priv)
>  	ipw2100_disable_interrupts(priv);
>  	spin_unlock_irqrestore(&priv->low_lock, flags);
>  
> -	pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100",
> -			PM_QOS_DEFAULT_VALUE);
> +	pm_qos_update_request(ipw2100_pm_qos_req, PM_QOS_DEFAULT_VALUE);
>  
>  	/* We have to signal any supplicant if we are disassociating */
>  	if (associated)
> @@ -6669,7 +6670,7 @@ static int __init ipw2100_init(void)
>  	if (ret)
>  		goto out;
>  
> -	pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100",
> +	ipw2100_pm_qos_req = pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
>  			PM_QOS_DEFAULT_VALUE);
>  #ifdef CONFIG_IPW2100_DEBUG
>  	ipw2100_debug_level = debug;
> @@ -6692,7 +6693,7 @@ static void __exit ipw2100_exit(void)
>  			   &driver_attr_debug_level);
>  #endif
>  	pci_unregister_driver(&ipw2100_pci_driver);
> -	pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100");
> +	pm_qos_remove_request(ipw2100_pm_qos_req);
>  }
>  
>  module_init(ipw2100_init);
> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> index fa8b476..3857517 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -31,6 +31,7 @@
>  #include <linux/if_link.h>
>  
>  #ifdef __KERNEL__
> +#include <linux/pm_qos_params.h>
>  #include <linux/timer.h>
>  #include <linux/delay.h>
>  #include <linux/mm.h>
> @@ -711,6 +712,9 @@ struct net_device {
>  	 * the interface.
>  	 */
>  	char			name[IFNAMSIZ];
> +
> +	struct pm_qos_request_list *pm_qos_req;
> +
>  	/* device name hash chain */
>  	struct hlist_node	name_hlist;
>  	/* snmp alias */
> diff --git a/include/linux/pm_qos_params.h b/include/linux/pm_qos_params.h
> index d74f75e..8ba440e 100644
> --- a/include/linux/pm_qos_params.h
> +++ b/include/linux/pm_qos_params.h
> @@ -14,12 +14,14 @@
>  #define PM_QOS_NUM_CLASSES 4
>  #define PM_QOS_DEFAULT_VALUE -1
>  
> -int pm_qos_add_requirement(int qos, char *name, s32 value);
> -int pm_qos_update_requirement(int qos, char *name, s32 new_value);
> -void pm_qos_remove_requirement(int qos, char *name);
> +struct pm_qos_request_list;
>  
> -int pm_qos_requirement(int qos);
> +struct pm_qos_request_list *pm_qos_add_request(int pm_qos_class, s32 value);
> +void pm_qos_update_request(struct pm_qos_request_list *pm_qos_req,
> +		s32 new_value);
> +void pm_qos_remove_request(struct pm_qos_request_list *pm_qos_req);
>  
> -int pm_qos_add_notifier(int qos, struct notifier_block *notifier);
> -int pm_qos_remove_notifier(int qos, struct notifier_block *notifier);
> +int pm_qos_request(int pm_qos_class);
> +int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier);
> +int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier);
>  
> diff --git a/include/sound/pcm.h b/include/sound/pcm.h
> index 8b611a5..dd76cde 100644
> --- a/include/sound/pcm.h
> +++ b/include/sound/pcm.h
> @@ -29,6 +29,7 @@
>  #include <linux/poll.h>
>  #include <linux/mm.h>
>  #include <linux/bitops.h>
> +#include <linux/pm_qos_params.h>
>  
>  #define snd_pcm_substream_chip(substream) ((substream)->private_data)
>  #define snd_pcm_chip(pcm) ((pcm)->private_data)
> @@ -365,7 +366,7 @@ struct snd_pcm_substream {
>  	int number;
>  	char name[32];			/* substream name */
>  	int stream;			/* stream (direction) */
> -	char latency_id[20];		/* latency identifier */
> +	struct pm_qos_request_list *latency_pm_qos_req; /* pm_qos request */
>  	size_t buffer_bytes_max;	/* limit ring buffer size */
>  	struct snd_dma_buffer dma_buffer;
>  	unsigned int dma_buf_id;
> diff --git a/kernel/pm_qos_params.c b/kernel/pm_qos_params.c
> index 3db49b9..dfa1425 100644
> --- a/kernel/pm_qos_params.c
> +++ b/kernel/pm_qos_params.c
> @@ -2,7 +2,7 @@
>   * This module exposes the interface to kernel space for specifying
>   * QoS dependencies.  It provides infrastructure for registration of:
>   *
> - * Dependents on a QoS value : register requirements
> + * Dependents on a QoS value : register requests
>   * Watchers of QoS value : get notified when target QoS value changes
>   *
>   * This QoS design is best effort based.  Dependents register their QoS needs.
> @@ -14,19 +14,21 @@
>   * timeout: usec <-- currently not used.
>   * throughput: kbs (kilo byte / sec)
>   *
> - * There are lists of pm_qos_objects each one wrapping requirements, notifiers
> + * There are lists of pm_qos_objects each one wrapping requests, notifiers
>   *
> - * User mode requirements on a QOS parameter register themselves to the
> + * User mode requests on a QOS parameter register themselves to the
>   * subsystem by opening the device node /dev/... and writing there request to
>   * the node.  As long as the process holds a file handle open to the node the
>   * client continues to be accounted for.  Upon file release the usermode
> - * requirement is removed and a new qos target is computed.  This way when the
> - * requirement that the application has is cleaned up when closes the file
> + * request is removed and a new qos target is computed.  This way when the
> + * request that the application has is cleaned up when closes the file
>   * pointer or exits the pm_qos_object will get an opportunity to clean up.
>   *
>   * Mark Gross <mgross@linux.intel.com>
>   */
>  
> +/*#define DEBUG*/
> +
>  #include <linux/pm_qos_params.h>
>  #include <linux/sched.h>
>  #include <linux/spinlock.h>
> @@ -42,25 +44,25 @@
>  #include <linux/uaccess.h>
>  
>  /*
> - * locking rule: all changes to requirements or notifiers lists
> + * locking rule: all changes to requests or notifiers lists
>   * or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock
>   * held, taken with _irqsave.  One lock to rule them all
>   */
> -struct requirement_list {
> +struct pm_qos_request_list {
>  	struct list_head list;
>  	union {
>  		s32 value;
>  		s32 usec;
>  		s32 kbps;
>  	};
> -	char *name;
> +	int pm_qos_class;
>  };
>  
>  static s32 max_compare(s32 v1, s32 v2);
>  static s32 min_compare(s32 v1, s32 v2);
>  
>  struct pm_qos_object {
> -	struct requirement_list requirements;
> +	struct pm_qos_request_list requests;
>  	struct blocking_notifier_head *notifiers;
>  	struct miscdevice pm_qos_power_miscdev;
>  	char *name;
> @@ -72,7 +74,7 @@ struct pm_qos_object {
>  static struct pm_qos_object null_pm_qos;
>  static BLOCKING_NOTIFIER_HEAD(cpu_dma_lat_notifier);
>  static struct pm_qos_object cpu_dma_pm_qos = {
> -	.requirements = {LIST_HEAD_INIT(cpu_dma_pm_qos.requirements.list)},
> +	.requests = {LIST_HEAD_INIT(cpu_dma_pm_qos.requests.list)},
>  	.notifiers = &cpu_dma_lat_notifier,
>  	.name = "cpu_dma_latency",
>  	.default_value = 2000 * USEC_PER_SEC,
> @@ -82,7 +84,7 @@ static struct pm_qos_object cpu_dma_pm_qos = {
>  
>  static BLOCKING_NOTIFIER_HEAD(network_lat_notifier);
>  static struct pm_qos_object network_lat_pm_qos = {
> -	.requirements = {LIST_HEAD_INIT(network_lat_pm_qos.requirements.list)},
> +	.requests = {LIST_HEAD_INIT(network_lat_pm_qos.requests.list)},
>  	.notifiers = &network_lat_notifier,
>  	.name = "network_latency",
>  	.default_value = 2000 * USEC_PER_SEC,
> @@ -93,8 +95,7 @@ static struct pm_qos_object network_lat_pm_qos = {
>  
>  static BLOCKING_NOTIFIER_HEAD(network_throughput_notifier);
>  static struct pm_qos_object network_throughput_pm_qos = {
> -	.requirements =
> -		{LIST_HEAD_INIT(network_throughput_pm_qos.requirements.list)},
> +	.requests = {LIST_HEAD_INIT(network_throughput_pm_qos.requests.list)},
>  	.notifiers = &network_throughput_notifier,
>  	.name = "network_throughput",
>  	.default_value = 0,
> @@ -135,31 +136,34 @@ static s32 min_compare(s32 v1, s32 v2)
>  }
>  
>  
> -static void update_target(int target)
> +static void update_target(int pm_qos_class)
>  {
>  	s32 extreme_value;
> -	struct requirement_list *node;
> +	struct pm_qos_request_list *node;
>  	unsigned long flags;
>  	int call_notifier = 0;
>  
>  	spin_lock_irqsave(&pm_qos_lock, flags);
> -	extreme_value = pm_qos_array[target]->default_value;
> +	extreme_value = pm_qos_array[pm_qos_class]->default_value;
>  	list_for_each_entry(node,
> -			&pm_qos_array[target]->requirements.list, list) {
> -		extreme_value = pm_qos_array[target]->comparitor(
> +			&pm_qos_array[pm_qos_class]->requests.list, list) {
> +		extreme_value = pm_qos_array[pm_qos_class]->comparitor(
>  				extreme_value, node->value);
>  	}
> -	if (atomic_read(&pm_qos_array[target]->target_value) != extreme_value) {
> +	if (atomic_read(&pm_qos_array[pm_qos_class]->target_value) !=
> +			extreme_value) {
>  		call_notifier = 1;
> -		atomic_set(&pm_qos_array[target]->target_value, extreme_value);
> -		pr_debug(KERN_ERR "new target for qos %d is %d\n", target,
> -			atomic_read(&pm_qos_array[target]->target_value));
> +		atomic_set(&pm_qos_array[pm_qos_class]->target_value,
> +				extreme_value);
> +		pr_debug(KERN_ERR "new target for qos %d is %d\n", pm_qos_class,
> +			atomic_read(&pm_qos_array[pm_qos_class]->target_value));
>  	}
>  	spin_unlock_irqrestore(&pm_qos_lock, flags);
>  
>  	if (call_notifier)
> -		blocking_notifier_call_chain(pm_qos_array[target]->notifiers,
> -			(unsigned long) extreme_value, NULL);
> +		blocking_notifier_call_chain(
> +				pm_qos_array[pm_qos_class]->notifiers,
> +					(unsigned long) extreme_value, NULL);
>  }
>  
>  static int register_pm_qos_misc(struct pm_qos_object *qos)
> @@ -185,125 +189,113 @@ static int find_pm_qos_object_by_minor(int minor)
>  }
>  
>  /**
> - * pm_qos_requirement - returns current system wide qos expectation
> + * pm_qos_request - returns current system wide qos expectation
>   * @pm_qos_class: identification of which qos value is requested
>   *
>   * This function returns the current target value in an atomic manner.
>   */
> -int pm_qos_requirement(int pm_qos_class)
> +int pm_qos_request(int pm_qos_class)
>  {
>  	return atomic_read(&pm_qos_array[pm_qos_class]->target_value);
>  }
> -EXPORT_SYMBOL_GPL(pm_qos_requirement);
> +EXPORT_SYMBOL_GPL(pm_qos_request);
>  
>  /**
> - * pm_qos_add_requirement - inserts new qos request into the list
> + * pm_qos_add_request - inserts new qos request into the list
>   * @pm_qos_class: identifies which list of qos request to us
> - * @name: identifies the request
>   * @value: defines the qos request
>   *
>   * This function inserts a new entry in the pm_qos_class list of requested qos
>   * performance characteristics.  It recomputes the aggregate QoS expectations
> - * for the pm_qos_class of parameters.
> + * for the pm_qos_class of parameters, and returns the pm_qos_request list
> + * element as a handle for use in updating and removal.  Call needs to save
> + * this handle for later use.
>   */
> -int pm_qos_add_requirement(int pm_qos_class, char *name, s32 value)
> +struct pm_qos_request_list *pm_qos_add_request(int pm_qos_class, s32 value)
>  {
> -	struct requirement_list *dep;
> +	struct pm_qos_request_list *dep;
>  	unsigned long flags;
>  
> -	dep = kzalloc(sizeof(struct requirement_list), GFP_KERNEL);
> +	dep = kzalloc(sizeof(struct pm_qos_request_list), GFP_KERNEL);
>  	if (dep) {
>  		if (value == PM_QOS_DEFAULT_VALUE)
>  			dep->value = pm_qos_array[pm_qos_class]->default_value;
>  		else
>  			dep->value = value;
> -		dep->name = kstrdup(name, GFP_KERNEL);
> -		if (!dep->name)
> -			goto cleanup;
> +		dep->pm_qos_class = pm_qos_class;
>  
>  		spin_lock_irqsave(&pm_qos_lock, flags);
>  		list_add(&dep->list,
> -			&pm_qos_array[pm_qos_class]->requirements.list);
> +			&pm_qos_array[pm_qos_class]->requests.list);
>  		spin_unlock_irqrestore(&pm_qos_lock, flags);
>  		update_target(pm_qos_class);
> -
> -		return 0;
>  	}
>  
> -cleanup:
> -	kfree(dep);
> -	return -ENOMEM;
> +	return dep;
>  }
> -EXPORT_SYMBOL_GPL(pm_qos_add_requirement);
> +EXPORT_SYMBOL_GPL(pm_qos_add_request);
>  
>  /**
> - * pm_qos_update_requirement - modifies an existing qos request
> - * @pm_qos_class: identifies which list of qos request to us
> - * @name: identifies the request
> + * pm_qos_update_request - modifies an existing qos request
> + * @pm_qos_req : handle to list element holding a pm_qos request to use
>   * @value: defines the qos request
>   *
> - * Updates an existing qos requirement for the pm_qos_class of parameters along
> + * Updates an existing qos request for the pm_qos_class of parameters along
>   * with updating the target pm_qos_class value.
>   *
> - * If the named request isn't in the list then no change is made.
> + * Attempts are made to make this code callable on hot code paths.
>   */
> -int pm_qos_update_requirement(int pm_qos_class, char *name, s32 new_value)
> +void pm_qos_update_request(struct pm_qos_request_list *pm_qos_req,
> +		s32 new_value)
>  {
>  	unsigned long flags;
> -	struct requirement_list *node;
>  	int pending_update = 0;
> +	s32 temp;
>  
> -	spin_lock_irqsave(&pm_qos_lock, flags);
> -	list_for_each_entry(node,
> -		&pm_qos_array[pm_qos_class]->requirements.list, list) {
> -		if (strcmp(node->name, name) == 0) {
> -			if (new_value == PM_QOS_DEFAULT_VALUE)
> -				node->value =
> -				pm_qos_array[pm_qos_class]->default_value;
> -			else
> -				node->value = new_value;
> +	if (pm_qos_req) { /*guard against callers passing in null */
> +		spin_lock_irqsave(&pm_qos_lock, flags);
> +		if (new_value == PM_QOS_DEFAULT_VALUE)
> +			temp = pm_qos_array[pm_qos_req->pm_qos_class]->
> +				default_value;
> +		else
> +			temp = new_value;
> +
> +		if (temp != pm_qos_req->value) {
>  			pending_update = 1;
> -			break;
> +			pm_qos_req->value = temp;
>  		}
> +		spin_unlock_irqrestore(&pm_qos_lock, flags);
>  	}
> -	spin_unlock_irqrestore(&pm_qos_lock, flags);
>  	if (pending_update)
> -		update_target(pm_qos_class);
> -
> -	return 0;
> +		update_target(pm_qos_req->pm_qos_class);
>  }
> -EXPORT_SYMBOL_GPL(pm_qos_update_requirement);
> +EXPORT_SYMBOL_GPL(pm_qos_update_request);
>  
>  /**
> - * pm_qos_remove_requirement - modifies an existing qos request
> - * @pm_qos_class: identifies which list of qos request to us
> - * @name: identifies the request
> + * pm_qos_remove_request - modifies an existing qos request
> + * @pm_qos_req: handle to request list element
>   *
> - * Will remove named qos request from pm_qos_class list of parameters and
> - * recompute the current target value for the pm_qos_class.
> + * Will remove pm qos request from the list of requests and
> + * recompute the current target value for the pm_qos_class.  Call this
> + * on slow code paths.
>   */
> -void pm_qos_remove_requirement(int pm_qos_class, char *name)
> +void pm_qos_remove_request(struct pm_qos_request_list *pm_qos_req)
>  {
>  	unsigned long flags;
> -	struct requirement_list *node;
> -	int pending_update = 0;
> +	int qos_class;
> +
> +	if (pm_qos_req == NULL)
> +		return;
> +		/* silent return to keep pcm code cleaner */
>  
> +	qos_class = pm_qos_req->pm_qos_class;
>  	spin_lock_irqsave(&pm_qos_lock, flags);
> -	list_for_each_entry(node,
> -		&pm_qos_array[pm_qos_class]->requirements.list, list) {
> -		if (strcmp(node->name, name) == 0) {
> -			kfree(node->name);
> -			list_del(&node->list);
> -			kfree(node);
> -			pending_update = 1;
> -			break;
> -		}
> -	}
> +	list_del(&pm_qos_req->list);
> +	kfree(pm_qos_req);
>  	spin_unlock_irqrestore(&pm_qos_lock, flags);
> -	if (pending_update)
> -		update_target(pm_qos_class);
> +	update_target(qos_class);
>  }
> -EXPORT_SYMBOL_GPL(pm_qos_remove_requirement);
> +EXPORT_SYMBOL_GPL(pm_qos_remove_request);
>  
>  /**
>   * pm_qos_add_notifier - sets notification entry for changes to target value
> @@ -313,7 +305,7 @@ EXPORT_SYMBOL_GPL(pm_qos_remove_requirement);
>   * will register the notifier into a notification chain that gets called
>   * upon changes to the pm_qos_class target value.
>   */
> - int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier)
> +int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier)
>  {
>  	int retval;
>  
> @@ -343,21 +335,16 @@ int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier)
>  }
>  EXPORT_SYMBOL_GPL(pm_qos_remove_notifier);
>  
> -#define PID_NAME_LEN 32
> -
>  static int pm_qos_power_open(struct inode *inode, struct file *filp)
>  {
> -	int ret;
>  	long pm_qos_class;
> -	char name[PID_NAME_LEN];
>  
>  	pm_qos_class = find_pm_qos_object_by_minor(iminor(inode));
>  	if (pm_qos_class >= 0) {
> -		filp->private_data = (void *)pm_qos_class;
> -		snprintf(name, PID_NAME_LEN, "process_%d", current->pid);
> -		ret = pm_qos_add_requirement(pm_qos_class, name,
> -					PM_QOS_DEFAULT_VALUE);
> -		if (ret >= 0)
> +		filp->private_data = (void *) pm_qos_add_request(pm_qos_class,
> +				PM_QOS_DEFAULT_VALUE);
> +
> +		if (filp->private_data)
>  			return 0;
>  	}
>  	return -EPERM;
> @@ -365,32 +352,40 @@ static int pm_qos_power_open(struct inode *inode, struct file *filp)
>  
>  static int pm_qos_power_release(struct inode *inode, struct file *filp)
>  {
> -	int pm_qos_class;
> -	char name[PID_NAME_LEN];
> +	struct pm_qos_request_list *req;
>  
> -	pm_qos_class = (long)filp->private_data;
> -	snprintf(name, PID_NAME_LEN, "process_%d", current->pid);
> -	pm_qos_remove_requirement(pm_qos_class, name);
> +	req = (struct pm_qos_request_list *)filp->private_data;
> +	pm_qos_remove_request(req);
>  
>  	return 0;
>  }
>  
> +
>  static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
>  		size_t count, loff_t *f_pos)
>  {
>  	s32 value;
> -	int pm_qos_class;
> -	char name[PID_NAME_LEN];
> -
> -	pm_qos_class = (long)filp->private_data;
> -	if (count != sizeof(s32))
> +	int x;
> +	char ascii_value[11];
> +	struct pm_qos_request_list *pm_qos_req;
> +
> +	if (count == sizeof(s32)) {
> +		if (copy_from_user(&value, buf, sizeof(s32)))
> +			return -EFAULT;
> +	} else if (count == 11) { /* len('0x12345678/0') */
> +		if (copy_from_user(ascii_value, buf, 11))
> +			return -EFAULT;
> +		x = sscanf(ascii_value, "%x", &value);
> +		if (x != 1)
> +			return -EINVAL;
> +		pr_debug(KERN_ERR "%s, %d, 0x%x\n", ascii_value, x, value);
> +	} else
>  		return -EINVAL;
> -	if (copy_from_user(&value, buf, sizeof(s32)))
> -		return -EFAULT;
> -	snprintf(name, PID_NAME_LEN, "process_%d", current->pid);
> -	pm_qos_update_requirement(pm_qos_class, name, value);
>  
> -	return  sizeof(s32);
> +	pm_qos_req = (struct pm_qos_request_list *)filp->private_data;
> +	pm_qos_update_request(pm_qos_req, value);
> +
> +	return count;
>  }
>  
>  
> diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
> index 875c8de..88f95e7 100644
> --- a/net/mac80211/mlme.c
> +++ b/net/mac80211/mlme.c
> @@ -495,7 +495,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
>  		s32 beaconint_us;
>  
>  		if (latency < 0)
> -			latency = pm_qos_requirement(PM_QOS_NETWORK_LATENCY);
> +			latency = pm_qos_request(PM_QOS_NETWORK_LATENCY);
>  
>  		beaconint_us = ieee80211_tu_to_usec(
>  					found->vif.bss_conf.beacon_int);
> diff --git a/sound/core/pcm.c b/sound/core/pcm.c
> index 0d428d0..cbe815d 100644
> --- a/sound/core/pcm.c
> +++ b/sound/core/pcm.c
> @@ -648,9 +648,6 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
>  		substream->number = idx;
>  		substream->stream = stream;
>  		sprintf(substream->name, "subdevice #%i", idx);
> -		snprintf(substream->latency_id, sizeof(substream->latency_id),
> -			 "ALSA-PCM%d-%d%c%d", pcm->card->number, pcm->device,
> -			 (stream ? 'c' : 'p'), idx);
>  		substream->buffer_bytes_max = UINT_MAX;
>  		if (prev == NULL)
>  			pstr->substream = substream;
> diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
> index 20b5982..192dd40 100644
> --- a/sound/core/pcm_native.c
> +++ b/sound/core/pcm_native.c
> @@ -484,11 +484,13 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
>  	snd_pcm_timer_resolution_change(substream);
>  	runtime->status->state = SNDRV_PCM_STATE_SETUP;
>  
> -	pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
> -				substream->latency_id);
> +	if (substream->latency_pm_qos_req) {
> +		pm_qos_remove_request(substream->latency_pm_qos_req);
> +		substream->latency_pm_qos_req = NULL;
> +	}
>  	if ((usecs = period_to_usecs(runtime)) >= 0)
> -		pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY,
> -					substream->latency_id, usecs);
> +		substream->latency_pm_qos_req = pm_qos_add_request(
> +					PM_QOS_CPU_DMA_LATENCY, usecs);
>  	return 0;
>   _error:
>  	/* hardware might be unuseable from this time,
> @@ -543,8 +545,8 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
>  	if (substream->ops->hw_free)
>  		result = substream->ops->hw_free(substream);
>  	runtime->status->state = SNDRV_PCM_STATE_OPEN;
> -	pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
> -		substream->latency_id);
> +	pm_qos_remove_request(substream->latency_pm_qos_req);
> +	substream->latency_pm_qos_req = NULL;
>  	return result;
>  }
>  
> 


------------------------------------------------------------------------------

_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel&#174; Ethernet, visit http://communities.intel.com/community/wired

^ permalink raw reply

* [PATCH 3/3] cxgb4i_v3: iscsi and libcxgbi library for handling common part
From: Rakesh Ranjan @ 2010-05-15 17:24 UTC (permalink / raw)
  To: NETDEVML, SCSIDEVML, OISCSIML
  Cc: LKML, Karen Xie, David Miller, James Bottomley, Mike Christie,
	Anish Bhatt, Rakesh Ranjan, Rakesh Ranjan
In-Reply-To: <1273944249-311-3-git-send-email-rakesh-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>

From: Rakesh Ranjan <rranjan-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>


Signed-off-by: Rakesh Ranjan <rakesh-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
---
 drivers/scsi/cxgb4i/cxgb4i_iscsi.c |  617 ++++++++++++++++++++++++++++++++++++
 drivers/scsi/cxgb4i/libcxgbi.c     |  589 ++++++++++++++++++++++++++++++++++
 drivers/scsi/cxgb4i/libcxgbi.h     |  430 +++++++++++++++++++++++++
 3 files changed, 1636 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/cxgb4i/cxgb4i_iscsi.c
 create mode 100644 drivers/scsi/cxgb4i/libcxgbi.c
 create mode 100644 drivers/scsi/cxgb4i/libcxgbi.h

diff --git a/drivers/scsi/cxgb4i/cxgb4i_iscsi.c b/drivers/scsi/cxgb4i/cxgb4i_iscsi.c
new file mode 100644
index 0000000..a10ab6d
--- /dev/null
+++ b/drivers/scsi/cxgb4i/cxgb4i_iscsi.c
@@ -0,0 +1,617 @@
+/*
+ * cxgb4i_iscsi.c: Chelsio T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Karen Xie (kxie-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ * Written by: Rakesh Ranjan (rranjan-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ */
+
+#include <linux/inet.h>
+#include <linux/crypto.h>
+#include <linux/if_vlan.h>
+#include <net/dst.h>
+#include <net/tcp.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi.h>
+#include <scsi/iscsi_proto.h>
+#include <scsi/libiscsi.h>
+#include <scsi/scsi_transport_iscsi.h>
+
+#include "cxgb4i.h"
+
+/*
+ * align pdu size to multiple of 512 for better performance
+ */
+#define cxgb4i_align_pdu_size(n) do { n = (n) & (~511); } while (0)
+
+static struct scsi_transport_template *cxgb4i_scsi_transport;
+static struct scsi_host_template cxgb4i_host_template;
+static struct iscsi_transport cxgb4i_iscsi_transport;
+
+struct cxgbi_hba *cxgb4i_hba_add(struct cxgb4i_snic *snic,
+					struct net_device *dev)
+{
+	struct cxgbi_hba *chba;
+	struct Scsi_Host *shost;
+	int err;
+
+	shost = iscsi_host_alloc(&cxgb4i_host_template, sizeof(*chba), 1);
+
+	if (!shost) {
+		cxgbi_log_info("snic 0x%p, ndev 0x%p, host alloc failed\n",
+				snic, dev);
+		return NULL;
+	}
+
+	shost->transportt = cxgb4i_scsi_transport;
+	shost->max_lun = CXGB4I_MAX_LUN;
+	shost->max_id = CXGB4I_MAX_TARGET;
+	shost->max_channel = 0;
+	shost->max_cmd_len = 16;
+
+	chba = iscsi_host_priv(shost);
+	cxgbi_log_debug("snic %p, cdev %p\n", snic, &snic->cdev);
+	chba->cdev = &snic->cdev;
+	chba->ndev = dev;
+	chba->shost = shost;
+
+	pci_dev_get(snic->lldi.pdev);
+	err = iscsi_host_add(shost, &snic->lldi.pdev->dev);
+	if (err) {
+		cxgbi_log_info("snic 0x%p, dev 0x%p, host add failed\n",
+				snic, dev);
+		goto pci_dev_put;
+	}
+
+	return chba;
+
+pci_dev_put:
+	pci_dev_put(snic->lldi.pdev);
+	scsi_host_put(shost);
+	return NULL;
+}
+
+void cxgb4i_hba_remove(struct cxgbi_hba *chba)
+{
+	iscsi_host_remove(chba->shost);
+	pci_dev_put(cxgb4i_get_snic(chba->cdev)->lldi.pdev);
+	iscsi_host_free(chba->shost);
+}
+
+static struct iscsi_endpoint *cxgb4i_ep_connect(struct Scsi_Host *shost,
+						struct sockaddr *dst_addr,
+						int non_blocking)
+{
+	struct iscsi_endpoint *iep;
+	struct cxgbi_endpoint *cep;
+	struct cxgbi_hba *hba = NULL;
+	struct cxgbi_sock *csk = NULL;
+	struct cxgb4i_snic *snic;
+	int err = 0;
+
+	if (shost)
+		hba = iscsi_host_priv(shost);
+
+	snic = cxgb4i_find_snic(hba ? hba->ndev : NULL,
+			((struct sockaddr_in *)dst_addr)->sin_addr.s_addr);
+	if (!snic) {
+		cxgbi_log_info("ep connect no snic\n");
+		err = -ENOSPC;
+		goto release_conn;
+	}
+
+	csk = cxgb4i_sock_create(snic);
+	if (!csk) {
+		cxgbi_log_info("ep connect OOM\n");
+		err = -ENOMEM;
+		goto release_conn;
+	}
+	err = cxgb4i_sock_connect(hba ? hba->ndev : NULL, csk,
+				(struct sockaddr_in *)dst_addr);
+	if (err < 0) {
+		cxgbi_log_info("ep connect failed\n");
+		goto release_conn;
+	}
+
+	hba = cxgb4i_hba_find_by_netdev(csk->dst->dev);
+	if (!hba) {
+		err = -ENOSPC;
+		cxgbi_log_info("Not going through cxgb4i device\n");
+		goto release_conn;
+	}
+
+	if (shost && hba != iscsi_host_priv(shost)) {
+		err = -ENOSPC;
+		cxgbi_log_info("Could not connect through request host %u\n",
+				shost->host_no);
+		goto release_conn;
+	}
+
+	if (cxgbi_sock_is_closing(csk)) {
+		err = -ENOSPC;
+		cxgbi_log_info("ep connect unable to connect\n");
+		goto release_conn;
+	}
+
+	iep = iscsi_create_endpoint(sizeof(*cep));
+	if (!iep) {
+		err = -ENOMEM;
+		cxgbi_log_info("iscsi alloc ep, OOM\n");
+		goto release_conn;
+	}
+
+	cep = iep->dd_data;
+	cep->csk = csk;
+	cep->chba = hba;
+
+	cxgbi_api_debug("iep 0x%p, cep 0x%p, csk 0x%p, hba 0x%p\n",
+			iep, cep, csk, hba);
+
+	return iep;
+
+release_conn:
+	cxgbi_api_debug("conn 0x%p failed, release\n", csk);
+	if (csk)
+		cxgb4i_sock_release(csk);
+
+	return ERR_PTR(err);
+}
+
+static int cxgb4i_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
+{
+	struct cxgbi_endpoint *cep = ep->dd_data;
+	struct cxgbi_sock *csk = cep->csk;
+
+	if (!cxgbi_sock_is_established(csk))
+		return 0;
+
+	return 1;
+}
+
+static void cxgb4i_ep_disconnect(struct iscsi_endpoint *ep)
+{
+	struct cxgbi_endpoint *cep = ep->dd_data;
+	struct cxgbi_conn *cconn = cep->cconn;
+
+	if (cconn && cconn->iconn) {
+		iscsi_suspend_tx(cconn->iconn);
+
+		write_lock_bh(&cep->csk->callback_lock);
+		cep->csk->user_data = NULL;
+		cconn->cep = NULL;
+		write_unlock_bh(&cep->csk->callback_lock);
+	}
+
+	cxgb4i_sock_release(cep->csk);
+	iscsi_destroy_endpoint(ep);
+}
+
+static struct iscsi_cls_session *
+cxgb4i_create_session(struct iscsi_endpoint *ep, u16 cmds_max, u16 qdepth,
+							u32 initial_cmdsn)
+{
+	struct cxgbi_endpoint *cep;
+	struct cxgbi_hba *chba;
+	struct Scsi_Host *shost;
+	struct iscsi_cls_session *cls_session;
+	struct iscsi_session *session;
+
+	if (!ep) {
+		cxgbi_log_error("missing endpoint\n");
+		return NULL;
+	}
+
+	cep = ep->dd_data;
+	chba = cep->chba;
+	shost = chba->shost;
+
+	BUG_ON(chba != iscsi_host_priv(shost));
+
+	cls_session = iscsi_session_setup(&cxgb4i_iscsi_transport, shost,
+					cmds_max, 0,
+					sizeof(struct iscsi_tcp_task) +
+					sizeof(struct cxgbi_task_data),
+					initial_cmdsn, ISCSI_MAX_TARGET);
+	if (!cls_session)
+		return NULL;
+
+	session = cls_session->dd_data;
+	if (iscsi_tcp_r2tpool_alloc(session))
+		goto remove_session;
+
+	return cls_session;
+
+remove_session:
+	iscsi_session_teardown(cls_session);
+	return NULL;
+}
+
+static void cxgb4i_destroy_session(struct iscsi_cls_session *cls_session)
+{
+	iscsi_tcp_r2tpool_free(cls_session->dd_data);
+	iscsi_session_teardown(cls_session);
+}
+
+static inline int cxgb4i_conn_max_xmit_dlength(struct iscsi_conn *conn)
+{
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	unsigned int max = max(512 * MAX_SKB_FRAGS, SKB_TX_HEADROOM);
+
+	max = min(cxgb4i_get_snic(cconn->chba->cdev)->tx_max_size, max);
+	if (conn->max_xmit_dlength)
+		conn->max_xmit_dlength = min(conn->max_xmit_dlength, max);
+	else
+		conn->max_xmit_dlength = max;
+	cxgb4i_align_pdu_size(conn->max_xmit_dlength);
+	return 0;
+}
+
+static inline int cxgb4i_conn_max_recv_dlength(struct iscsi_conn *conn)
+{
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	unsigned int max = cxgb4i_get_snic(cconn->chba->cdev)->rx_max_size;
+
+	cxgb4i_align_pdu_size(max);
+
+	if (conn->max_recv_dlength) {
+		if (conn->max_recv_dlength > max) {
+			cxgbi_log_error("MaxRecvDataSegmentLength %u too big."
+					" Need to be <= %u.\n",
+					conn->max_recv_dlength, max);
+			return -EINVAL;
+		}
+		conn->max_recv_dlength = min(conn->max_recv_dlength, max);
+		cxgb4i_align_pdu_size(conn->max_recv_dlength);
+	} else
+		conn->max_recv_dlength = max;
+
+	return 0;
+}
+
+static struct iscsi_cls_conn *
+cxgb4i_create_conn(struct iscsi_cls_session *cls_session, u32 cid)
+{
+	struct iscsi_cls_conn *cls_conn;
+	struct iscsi_conn *conn;
+	struct iscsi_tcp_conn *tcp_conn;
+	struct cxgbi_conn *cconn;
+
+	cls_conn = iscsi_tcp_conn_setup(cls_session, sizeof(*cconn), cid);
+	if (!cls_conn)
+		return NULL;
+
+	conn = cls_conn->dd_data;
+	tcp_conn = conn->dd_data;
+	cconn = tcp_conn->dd_data;
+
+	cconn->iconn = conn;
+	return cls_conn;
+}
+
+static int cxgb4i_bind_conn(struct iscsi_cls_session *cls_session,
+				struct iscsi_cls_conn *cls_conn,
+				u64 transport_eph, int is_leading)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct iscsi_endpoint *ep;
+	struct cxgbi_endpoint *cep;
+	struct cxgbi_sock *csk;
+	int err;
+
+	ep = iscsi_lookup_endpoint(transport_eph);
+	if (!ep)
+		return -EINVAL;
+
+	/*  setup ddp pagesize */
+	cep = ep->dd_data;
+	csk = cep->csk;
+	err = cxgb4i_ddp_setup_conn_host_pagesize(csk, csk->hwtid, 0);
+	if (err < 0)
+		return err;
+
+	err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
+	if (err)
+		return -EINVAL;
+
+	/*  calculate the tag idx bits needed for this conn based on cmds_max */
+	cconn->task_idx_bits = (__ilog2_u32(conn->session->cmds_max - 1)) + 1;
+
+	read_lock(&csk->callback_lock);
+	csk->user_data = conn;
+	cconn->chba = cep->chba;
+	cconn->cep = cep;
+	cep->cconn = cconn;
+	read_unlock(&csk->callback_lock);
+
+	cxgb4i_conn_max_xmit_dlength(conn);
+	cxgb4i_conn_max_recv_dlength(conn);
+
+	spin_lock_bh(&conn->session->lock);
+	sprintf(conn->portal_address, "%pI4", &csk->daddr.sin_addr.s_addr);
+	conn->portal_port = ntohs(csk->daddr.sin_port);
+	spin_unlock_bh(&conn->session->lock);
+
+	/*  init recv engine */
+	iscsi_tcp_hdr_recv_prep(tcp_conn);
+
+	return 0;
+}
+
+static int
+cxgb4i_get_conn_param(struct iscsi_cls_conn *cls_conn,
+			enum iscsi_param param, char *buff)
+{
+	struct iscsi_conn *iconn = cls_conn->dd_data;
+	int len;
+
+	switch (param) {
+	case ISCSI_PARAM_CONN_PORT:
+		spin_lock_bh(&iconn->session->lock);
+		len = sprintf(buff, "%hu\n", iconn->portal_port);
+		spin_unlock_bh(&iconn->session->lock);
+		break;
+	case ISCSI_PARAM_CONN_ADDRESS:
+		spin_lock_bh(&iconn->session->lock);
+		len = sprintf(buff, "%s\n", iconn->portal_address);
+		spin_unlock_bh(&iconn->session->lock);
+		break;
+	default:
+		return iscsi_conn_get_param(cls_conn, param, buff);
+	}
+	return len;
+}
+
+static int
+cxgb4i_set_conn_param(struct iscsi_cls_conn *cls_conn,
+			enum iscsi_param param, char *buf, int buflen)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+	struct iscsi_session *session = conn->session;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_sock *csk = cconn->cep->csk;
+	int value, err = 0;
+
+	switch (param) {
+	case ISCSI_PARAM_HDRDGST_EN:
+		err = iscsi_set_param(cls_conn, param, buf, buflen);
+		if (!err && conn->hdrdgst_en)
+			err = cxgb4i_ddp_setup_conn_digest(csk, csk->hwtid,
+							conn->hdrdgst_en,
+							conn->datadgst_en, 0);
+		break;
+	case ISCSI_PARAM_DATADGST_EN:
+		err = iscsi_set_param(cls_conn, param, buf, buflen);
+		if (!err && conn->datadgst_en)
+			err = cxgb4i_ddp_setup_conn_digest(csk, csk->hwtid,
+							conn->hdrdgst_en,
+							conn->datadgst_en, 0);
+		break;
+	case ISCSI_PARAM_MAX_R2T:
+		sscanf(buf, "%d", &value);
+		if (value <= 0 || !is_power_of_2(value))
+			return -EINVAL;
+		if (session->max_r2t == value)
+			break;
+		iscsi_tcp_r2tpool_free(session);
+		err = iscsi_set_param(cls_conn, param, buf, buflen);
+		if (!err && iscsi_tcp_r2tpool_alloc(session))
+			return -ENOMEM;
+	case ISCSI_PARAM_MAX_RECV_DLENGTH:
+		err = iscsi_set_param(cls_conn, param, buf, buflen);
+		if (!err)
+			err = cxgb4i_conn_max_recv_dlength(conn);
+		break;
+	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+		err = iscsi_set_param(cls_conn, param, buf, buflen);
+		if (!err)
+			err = cxgb4i_conn_max_xmit_dlength(conn);
+		break;
+	default:
+		return iscsi_set_param(cls_conn, param, buf, buflen);
+	}
+	return err;
+}
+
+static int
+cxgb4i_set_host_param(struct Scsi_Host *shost,
+			enum iscsi_host_param param, char *buff, int buflen)
+{
+	struct cxgbi_hba *chba = iscsi_host_priv(shost);
+
+	if (!chba->ndev) {
+		shost_printk(KERN_ERR, shost, "Could not set host param. "
+				"Netdev for host not set\n");
+		return -ENODEV;
+	}
+
+	cxgbi_api_debug("param %d, buff %s\n", param, buff);
+
+	switch (param) {
+	case ISCSI_HOST_PARAM_IPADDRESS:
+	{
+		__be32 addr = in_aton(buff);
+		cxgb4i_set_iscsi_ipv4(chba, addr);
+		return 0;
+	}
+
+	case ISCSI_HOST_PARAM_HWADDRESS:
+	case ISCSI_HOST_PARAM_NETDEV_NAME:
+		return 0;
+
+	default:
+		return iscsi_host_set_param(shost, param, buff, buflen);
+	}
+}
+
+static int
+cxgb4i_get_host_param(struct Scsi_Host *shost,
+			enum iscsi_host_param param, char *buff)
+{
+	struct cxgbi_hba *chba = iscsi_host_priv(shost);
+	int len = 0;
+
+	if (!chba->ndev) {
+		shost_printk(KERN_ERR, shost, "Could not set host param. "
+				"Netdev for host not set\n");
+		return -ENODEV;
+	}
+
+	cxgbi_api_debug("hba %s, param %d\n", chba->ndev->name, param);
+
+	switch (param) {
+	case ISCSI_HOST_PARAM_HWADDRESS:
+		len = sysfs_format_mac(buff, chba->ndev->dev_addr, 6);
+		break;
+	case ISCSI_HOST_PARAM_NETDEV_NAME:
+		len = sprintf(buff, "%s\n", chba->ndev->name);
+		break;
+	case ISCSI_HOST_PARAM_IPADDRESS:
+	{
+		__be32 addr;
+
+		addr = cxgb4i_get_iscsi_ipv4(chba);
+		len = sprintf(buff, "%pI4", &addr);
+		break;
+	}
+	default:
+		return iscsi_host_get_param(shost, param, buff);
+	}
+
+	return len;
+}
+
+static void cxgb4i_get_conn_stats(struct iscsi_cls_conn *cls_conn,
+				struct iscsi_stats *stats)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+
+	stats->txdata_octets = conn->txdata_octets;
+	stats->rxdata_octets = conn->rxdata_octets;
+	stats->scsicmd_pdus = conn->scsicmd_pdus_cnt;
+	stats->dataout_pdus = conn->dataout_pdus_cnt;
+	stats->scsirsp_pdus = conn->scsirsp_pdus_cnt;
+	stats->datain_pdus = conn->datain_pdus_cnt;
+	stats->r2t_pdus = conn->r2t_pdus_cnt;
+	stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
+	stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
+	stats->digest_err = 0;
+	stats->timeout_err = 0;
+	stats->custom_length = 1;
+	strcpy(stats->custom[0].desc, "eh_abort_cnt");
+	stats->custom[0].value = conn->eh_abort_cnt;
+}
+
+static struct scsi_host_template cxgb4i_host_template = {
+	.module				= THIS_MODULE,
+	.name				= "Chelsio T4 iSCSI initiator",
+	.proc_name			= "cxgb4i",
+	.queuecommand			= iscsi_queuecommand,
+	.change_queue_depth		= iscsi_change_queue_depth,
+	.can_queue			= CXGB4I_SCSI_HOST_QDEPTH,
+	.sg_tablesize			= SG_ALL,
+	.max_sectors			= 0xFFFF,
+	.cmd_per_lun			= ISCSI_DEF_CMD_PER_LUN,
+	.eh_abort_handler		= iscsi_eh_abort,
+	.eh_device_reset_handler	= iscsi_eh_device_reset,
+	.eh_target_reset_handler	= iscsi_eh_recover_target,
+	.target_alloc			= iscsi_target_alloc,
+	.use_clustering			= DISABLE_CLUSTERING,
+	.this_id			= -1,
+};
+
+#define	CXGB4I_CAPS	(CAP_RECOVERY_L0 | CAP_MULTI_R2T |	\
+			CAP_HDRDGST | CAP_DATADGST |		\
+			CAP_DIGEST_OFFLOAD | CAP_PADDING_OFFLOAD)
+#define	CXGB4I_PMASK	(ISCSI_MAX_RECV_DLENGTH | ISCSI_MAX_XMIT_DLENGTH | \
+			ISCSI_HDRDGST_EN | ISCSI_DATADGST_EN | \
+			ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T | \
+			ISCSI_IMM_DATA_EN | ISCSI_FIRST_BURST | \
+			ISCSI_MAX_BURST | ISCSI_PDU_INORDER_EN | \
+			ISCSI_DATASEQ_INORDER_EN | ISCSI_ERL | \
+			ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS | \
+			ISCSI_EXP_STATSN | ISCSI_PERSISTENT_PORT | \
+			ISCSI_PERSISTENT_ADDRESS | ISCSI_TARGET_NAME | \
+			ISCSI_TPGT | ISCSI_USERNAME | \
+			ISCSI_PASSWORD | ISCSI_USERNAME_IN | \
+			ISCSI_PASSWORD_IN | ISCSI_FAST_ABORT | \
+			ISCSI_ABORT_TMO | ISCSI_LU_RESET_TMO | \
+			ISCSI_TGT_RESET_TMO | ISCSI_PING_TMO | \
+			ISCSI_RECV_TMO | ISCSI_IFACE_NAME | \
+			ISCSI_INITIATOR_NAME)
+#define	CXGB4I_HPMASK	(ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS | \
+			ISCSI_HOST_INITIATOR_NAME | ISCSI_HOST_INITIATOR_NAME)
+
+static struct iscsi_transport cxgb4i_iscsi_transport = {
+	.owner				= THIS_MODULE,
+	.name				= "cxgb4i",
+	.caps				= CXGB4I_CAPS,
+	.param_mask			= CXGB4I_PMASK,
+	.host_param_mask		= CXGB4I_HPMASK,
+	.get_host_param			= cxgb4i_get_host_param,
+	.set_host_param			= cxgb4i_set_host_param,
+
+	.create_session			= cxgb4i_create_session,
+	.destroy_session		= cxgb4i_destroy_session,
+	.get_session_param		= iscsi_session_get_param,
+
+	.create_conn			= cxgb4i_create_conn,
+	.bind_conn			= cxgb4i_bind_conn,
+	.destroy_conn			= iscsi_tcp_conn_teardown,
+	.start_conn			= iscsi_conn_start,
+	.stop_conn			= iscsi_conn_stop,
+	.get_conn_param			= cxgb4i_get_conn_param,
+	.set_param			= cxgb4i_set_conn_param,
+	.get_stats			= cxgb4i_get_conn_stats,
+
+	.send_pdu			= iscsi_conn_send_pdu,
+
+	.init_task			= iscsi_tcp_task_init,
+	.xmit_task			= iscsi_tcp_task_xmit,
+	.cleanup_task			= cxgbi_cleanup_task,
+
+	.alloc_pdu			= cxgbi_conn_alloc_pdu,
+	.init_pdu			= cxgbi_conn_init_pdu,
+	.xmit_pdu			= cxgbi_conn_xmit_pdu,
+	.parse_pdu_itt			= cxgbi_parse_pdu_itt,
+
+	.ep_connect			= cxgb4i_ep_connect,
+	.ep_poll			= cxgb4i_ep_poll,
+	.ep_disconnect			= cxgb4i_ep_disconnect,
+
+	.session_recovery_timedout	= iscsi_session_recovery_timedout,
+};
+
+int cxgb4i_iscsi_init(void)
+{
+	cxgb4i_scsi_transport = iscsi_register_transport(
+					&cxgb4i_iscsi_transport);
+	if (!cxgb4i_scsi_transport) {
+		cxgbi_log_error("Could not register cxgb4i transport\n");
+		return -ENODATA;
+	}
+
+	return 0;
+}
+
+void cxgb4i_iscsi_cleanup(void)
+{
+	if (cxgb4i_scsi_transport) {
+		cxgbi_api_debug("cxgb4i transport 0x%p removed\n",
+				cxgb4i_scsi_transport);
+		iscsi_unregister_transport(&cxgb4i_iscsi_transport);
+	}
+}
+
diff --git a/drivers/scsi/cxgb4i/libcxgbi.c b/drivers/scsi/cxgb4i/libcxgbi.c
new file mode 100644
index 0000000..98f904b
--- /dev/null
+++ b/drivers/scsi/cxgb4i/libcxgbi.c
@@ -0,0 +1,589 @@
+/*
+ * libcxgbi.c: Chelsio common library for T3/T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Karen Xie (kxie-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ * Written by: Rakesh Ranjan (rranjan-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ */
+
+#include <linux/skbuff.h>
+#include <linux/crypto.h>
+#include <linux/scatterlist.h>
+#include <linux/pci.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_host.h>
+
+#include "libcxgbi.h"
+
+/* always allocate rooms for AHS */
+#define SKB_TX_PDU_HEADER_LEN	\
+	(sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE)
+
+/*
+ * pdu receive, interact with libiscsi_tcp
+ */
+static inline int read_pdu_skb(struct iscsi_conn *conn, struct sk_buff *skb,
+			       unsigned int offset, int offloaded)
+{
+	int status = 0;
+	int bytes_read;
+
+	bytes_read = iscsi_tcp_recv_skb(conn, skb, offset, offloaded, &status);
+	switch (status) {
+	case ISCSI_TCP_CONN_ERR:
+		return -EIO;
+	case ISCSI_TCP_SUSPENDED:
+		/* no transfer - just have caller flush queue */
+		return bytes_read;
+	case ISCSI_TCP_SKB_DONE:
+		/*
+		 * pdus should always fit in the skb and we should get
+		 * segment done notifcation.
+		 */
+		iscsi_conn_printk(KERN_ERR, conn, "Invalid pdu or skb.");
+		return -EFAULT;
+	case ISCSI_TCP_SEGMENT_DONE:
+		return bytes_read;
+	default:
+		iscsi_conn_printk(KERN_ERR, conn, "Invalid iscsi_tcp_recv_skb "
+				  "status %d\n", status);
+		return -EINVAL;
+	}
+}
+
+int cxgbi_conn_read_bhs_pdu_skb(struct iscsi_conn *conn,
+					struct sk_buff *skb)
+{
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_device *cdev = cconn->chba->cdev;
+
+	int rc;
+
+	cxgbi_rx_debug("conn 0x%p, skb 0x%p, len %u, flag 0x%x.\n",
+			conn, skb, skb->len, cdev->get_skb_ulp_mode(skb));
+
+	if (!iscsi_tcp_recv_segment_is_hdr(tcp_conn)) {
+		iscsi_conn_failure(conn, ISCSI_ERR_PROTO);
+		return -EIO;
+	}
+
+	if (conn->hdrdgst_en && (cdev->get_skb_ulp_mode(skb)
+				& ULP2_FLAG_HCRC_ERROR)) {
+		iscsi_conn_failure(conn, ISCSI_ERR_HDR_DGST);
+		return -EIO;
+	}
+
+	rc = read_pdu_skb(conn, skb, 0, 0);
+	if (rc <= 0)
+		return rc;
+
+	return 0;
+}
+
+int cxgbi_conn_read_data_pdu_skb(struct iscsi_conn *conn,
+				    struct sk_buff *skb)
+{
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_device *cdev = cconn->chba->cdev;
+	bool offloaded = 0;
+	unsigned int offset = 0;
+	int rc;
+
+	cxgbi_rx_debug("conn 0x%p, skb 0x%p, len %u, flag 0x%x.\n",
+			conn, skb, skb->len, cdev->get_skb_ulp_mode(skb));
+
+	if (conn->datadgst_en &&
+		(cdev->get_skb_ulp_mode(skb) & ULP2_FLAG_DCRC_ERROR)) {
+		iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST);
+		return -EIO;
+	}
+
+	if (iscsi_tcp_recv_segment_is_hdr(tcp_conn))
+		return 0;
+
+	if (conn->hdrdgst_en)
+		offset = ISCSI_DIGEST_SIZE;
+
+	if (cdev->get_skb_ulp_mode(skb) & ULP2_FLAG_DATA_DDPED) {
+		cxgbi_rx_debug("skb 0x%p, opcode 0x%x, data %u, ddp'ed, "
+				"itt 0x%x.\n",
+				skb,
+				tcp_conn->in.hdr->opcode & ISCSI_OPCODE_MASK,
+				tcp_conn->in.datalen,
+				ntohl(tcp_conn->in.hdr->itt));
+		offloaded = 1;
+	} else {
+		cxgbi_rx_debug("skb 0x%p, opcode 0x%x, data %u, NOT ddp'ed, "
+				"itt 0x%x.\n",
+				skb,
+				tcp_conn->in.hdr->opcode & ISCSI_OPCODE_MASK,
+				tcp_conn->in.datalen,
+				ntohl(tcp_conn->in.hdr->itt));
+	}
+
+	rc = read_pdu_skb(conn, skb, 0, offloaded);
+	if (rc < 0)
+		return rc;
+	else
+		return 0;
+}
+
+static int sgl_seek_offset(struct scatterlist *sgl, unsigned int sgcnt,
+				unsigned int offset, unsigned int *off,
+				struct scatterlist **sgp)
+{
+	int i;
+	struct scatterlist *sg;
+
+	for_each_sg(sgl, sg, sgcnt, i) {
+		if (offset < sg->length) {
+			*off = offset;
+			*sgp = sg;
+			return 0;
+		}
+		offset -= sg->length;
+	}
+	return -EFAULT;
+}
+
+static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset,
+				unsigned int dlen, skb_frag_t *frags,
+				int frag_max)
+{
+	unsigned int datalen = dlen;
+	unsigned int sglen = sg->length - sgoffset;
+	struct page *page = sg_page(sg);
+	int i;
+
+	i = 0;
+	do {
+		unsigned int copy;
+
+		if (!sglen) {
+			sg = sg_next(sg);
+			if (!sg) {
+				cxgbi_log_error("sg NULL, len %u/%u.\n",
+								datalen, dlen);
+				return -EINVAL;
+			}
+			sgoffset = 0;
+			sglen = sg->length;
+			page = sg_page(sg);
+
+		}
+		copy = min(datalen, sglen);
+		if (i && page == frags[i - 1].page &&
+		    sgoffset + sg->offset ==
+			frags[i - 1].page_offset + frags[i - 1].size) {
+			frags[i - 1].size += copy;
+		} else {
+			if (i >= frag_max) {
+				cxgbi_log_error("too many pages %u, "
+						 "dlen %u.\n", frag_max, dlen);
+				return -EINVAL;
+			}
+
+			frags[i].page = page;
+			frags[i].page_offset = sg->offset + sgoffset;
+			frags[i].size = copy;
+			i++;
+		}
+		datalen -= copy;
+		sgoffset += copy;
+		sglen -= copy;
+	} while (datalen);
+
+	return i;
+}
+
+int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 opcode)
+{
+	struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_device *cdev = cconn->chba->cdev;
+	struct iscsi_conn *conn = task->conn;
+	struct iscsi_tcp_task *tcp_task = task->dd_data;
+	struct cxgbi_task_data *tdata = task->dd_data + sizeof(*tcp_task);
+	struct scsi_cmnd *sc = task->sc;
+	int headroom = SKB_TX_PDU_HEADER_LEN;
+
+	tcp_task->dd_data = tdata;
+	task->hdr = NULL;
+
+	/* write command, need to send data pdus */
+	if (cdev->skb_extra_headroom && (opcode == ISCSI_OP_SCSI_DATA_OUT ||
+	    (opcode == ISCSI_OP_SCSI_CMD &&
+	    (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_TO_DEVICE))))
+		headroom += min(cdev->skb_extra_headroom,
+					conn->max_xmit_dlength);
+
+	tdata->skb = alloc_skb(cdev->skb_tx_headroom + headroom, GFP_ATOMIC);
+	if (!tdata->skb)
+		return -ENOMEM;
+	skb_reserve(tdata->skb, cdev->skb_tx_headroom);
+
+	cxgbi_tx_debug("task 0x%p, opcode 0x%x, skb 0x%p.\n",
+			task, opcode, tdata->skb);
+
+	task->hdr = (struct iscsi_hdr *)tdata->skb->data;
+	task->hdr_max = SKB_TX_PDU_HEADER_LEN;
+
+	/* data_out uses scsi_cmd's itt */
+	if (opcode != ISCSI_OP_SCSI_DATA_OUT)
+		cxgbi_reserve_itt(task, &task->hdr->itt);
+
+	return 0;
+}
+
+int cxgbi_conn_init_pdu(struct iscsi_task *task, unsigned int offset,
+			      unsigned int count)
+{
+	struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_device *cdev = cconn->chba->cdev;
+	struct iscsi_conn *conn = task->conn;
+	struct iscsi_tcp_task *tcp_task = task->dd_data;
+	struct cxgbi_task_data *tdata = tcp_task->dd_data;
+	struct sk_buff *skb = tdata->skb;
+	unsigned int datalen = count;
+	int i, padlen = iscsi_padding(count);
+	struct page *pg;
+
+	cxgbi_tx_debug("task 0x%p,0x%p, offset %u, count %u, skb 0x%p.\n",
+			task, task->sc, offset, count, skb);
+
+	skb_put(skb, task->hdr_len);
+	cdev->tx_skb_setmode(skb, conn->hdrdgst_en,
+				datalen ? conn->datadgst_en : 0);
+	if (!count)
+		return 0;
+
+	if (task->sc) {
+		struct scsi_data_buffer *sdb = scsi_out(task->sc);
+		struct scatterlist *sg = NULL;
+		int err;
+
+		tdata->offset = offset;
+		tdata->count = count;
+		err = sgl_seek_offset(sdb->table.sgl, sdb->table.nents,
+					tdata->offset, &tdata->sgoffset, &sg);
+		if (err < 0) {
+			cxgbi_log_warn("tpdu, sgl %u, bad offset %u/%u.\n",
+					sdb->table.nents, tdata->offset,
+					sdb->length);
+			return err;
+		}
+		err = sgl_read_to_frags(sg, tdata->sgoffset, tdata->count,
+					tdata->frags, MAX_PDU_FRAGS);
+		if (err < 0) {
+			cxgbi_log_warn("tpdu, sgl %u, bad offset %u + %u.\n",
+					sdb->table.nents, tdata->offset,
+					tdata->count);
+			return err;
+		}
+		tdata->nr_frags = err;
+
+		if (tdata->nr_frags > MAX_SKB_FRAGS ||
+		    (padlen && tdata->nr_frags == MAX_SKB_FRAGS)) {
+			char *dst = skb->data + task->hdr_len;
+			skb_frag_t *frag = tdata->frags;
+
+			/* data fits in the skb's headroom */
+			for (i = 0; i < tdata->nr_frags; i++, frag++) {
+				char *src = kmap_atomic(frag->page,
+							KM_SOFTIRQ0);
+
+				memcpy(dst, src+frag->page_offset, frag->size);
+				dst += frag->size;
+				kunmap_atomic(src, KM_SOFTIRQ0);
+			}
+			if (padlen) {
+				memset(dst, 0, padlen);
+				padlen = 0;
+			}
+			skb_put(skb, count + padlen);
+		} else {
+			/* data fit into frag_list */
+			for (i = 0; i < tdata->nr_frags; i++)
+				get_page(tdata->frags[i].page);
+
+			memcpy(skb_shinfo(skb)->frags, tdata->frags,
+				sizeof(skb_frag_t) * tdata->nr_frags);
+			skb_shinfo(skb)->nr_frags = tdata->nr_frags;
+			skb->len += count;
+			skb->data_len += count;
+			skb->truesize += count;
+		}
+
+	} else {
+		pg = virt_to_page(task->data);
+
+		get_page(pg);
+		skb_fill_page_desc(skb, 0, pg, offset_in_page(task->data),
+					count);
+		skb->len += count;
+		skb->data_len += count;
+		skb->truesize += count;
+	}
+
+	if (padlen) {
+		i = skb_shinfo(skb)->nr_frags;
+		get_page(cdev->pad_page);
+		skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
+					cdev->pad_page, 0, padlen);
+
+		skb->data_len += padlen;
+		skb->truesize += padlen;
+		skb->len += padlen;
+	}
+
+	return 0;
+}
+
+int cxgbi_conn_xmit_pdu(struct iscsi_task *task)
+{
+	struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_device *cdev = cconn->chba->cdev;
+	struct iscsi_tcp_task *tcp_task = task->dd_data;
+	struct cxgbi_task_data *tdata = tcp_task->dd_data;
+	struct sk_buff *skb = tdata->skb;
+	unsigned int datalen;
+	int err;
+
+	if (!skb)
+		return 0;
+
+	datalen = skb->data_len;
+	tdata->skb = NULL;
+	err = cdev->sock_send_pdus(cconn->cep->csk, skb);
+	if (err > 0) {
+		int pdulen = err;
+
+		cxgbi_tx_debug("task 0x%p, skb 0x%p, len %u/%u, rv %d.\n",
+				task, skb, skb->len, skb->data_len, err);
+
+		if (task->conn->hdrdgst_en)
+			pdulen += ISCSI_DIGEST_SIZE;
+		if (datalen && task->conn->datadgst_en)
+			pdulen += ISCSI_DIGEST_SIZE;
+
+		task->conn->txdata_octets += pdulen;
+		return 0;
+	}
+
+	if (err == -EAGAIN || err == -ENOBUFS) {
+		/* reset skb to send when we are called again */
+		tdata->skb = skb;
+		return err;
+	}
+
+	kfree_skb(skb);
+	cxgbi_tx_debug("itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n",
+			task->itt, skb, skb->len, skb->data_len, err);
+	iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err);
+	iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED);
+	return err;
+}
+
+int cxgbi_pdu_init(struct cxgbi_device *cdev)
+{
+	if (cdev->skb_tx_headroom > (512 * MAX_SKB_FRAGS))
+		cdev->skb_extra_headroom = cdev->skb_tx_headroom;
+	cdev->pad_page = alloc_page(GFP_KERNEL);
+	if (cdev->pad_page)
+		return -ENOMEM;
+	memset(page_address(cdev->pad_page), 0, PAGE_SIZE);
+	return 0;
+
+	/*
+	if (SKB_TX_HEADROOM > (512 * MAX_SKB_FRAGS))
+		skb_extra_headroom = SKB_TX_HEADROOM;
+	pad_page = alloc_page(GFP_KERNEL);
+	if (!pad_page)
+		return -ENOMEM;
+	memset(page_address(pad_page), 0, PAGE_SIZE);
+	return 0;*/
+}
+
+void cxgbi_pdu_cleanup(struct cxgbi_device *cdev)
+{
+	if (cdev->pad_page) {
+		__free_page(cdev->pad_page);
+		cdev->pad_page = NULL;
+	}
+}
+
+void cxgbi_conn_tx_open(struct cxgbi_sock *csk)
+{
+	struct iscsi_conn *conn = csk->user_data;
+
+	if (conn) {
+		cxgbi_tx_debug("cn 0x%p, cid %d.\n", csk, conn->id);
+		iscsi_conn_queue_work(conn);
+	}
+}
+
+int cxgbi_sock_get_port(struct cxgbi_sock *csk)
+{
+	unsigned int start;
+	int idx;
+
+	if (!csk->cdev->pmap)
+		goto error_out;
+
+	if (csk->saddr.sin_port) {
+		cxgbi_log_error("connect, sin_port none ZERO %u\n",
+				ntohs(csk->saddr.sin_port));
+		return -EADDRINUSE;
+	}
+
+	spin_lock_bh(&csk->cdev->pmap->lock);
+	start = idx = csk->cdev->pmap->next;
+
+	do {
+		if (++idx >= csk->cdev->pmap->max_connect)
+			idx = 0;
+		if (!csk->cdev->pmap->port_csk[idx]) {
+			csk->saddr.sin_port =
+				htons(csk->cdev->pmap->sport_base + idx);
+			csk->cdev->pmap->next = idx;
+			csk->cdev->pmap->port_csk[idx] = csk;
+			spin_unlock_bh(&csk->cdev->pmap->lock);
+
+			cxgbi_conn_debug("reserved port %u\n",
+					csk->cdev->pmap->sport_base + idx);
+
+			return 0;
+		}
+	} while (idx != start);
+	spin_unlock_bh(&csk->cdev->pmap->lock);
+
+error_out:
+	return -EADDRNOTAVAIL;
+}
+
+void cxgbi_sock_put_port(struct cxgbi_sock *csk)
+{
+	if (csk->saddr.sin_port) {
+		int idx = ntohs(csk->saddr.sin_port) -
+			csk->cdev->pmap->sport_base;
+
+		csk->saddr.sin_port = 0;
+		if (idx < 0 || idx >= csk->cdev->pmap->max_connect)
+			return;
+
+		spin_lock_bh(&csk->cdev->pmap->lock);
+		csk->cdev->pmap->port_csk[idx] = NULL;
+		spin_unlock_bh(&csk->cdev->pmap->lock);
+
+		cxgbi_conn_debug("released port %u\n",
+				csk->cdev->pmap->sport_base + idx);
+	}
+}
+
+void cxgbi_release_itt(struct iscsi_task *task, itt_t hdr_itt)
+{
+	struct scsi_cmnd *sc = task->sc;
+	struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_device *cdev = cconn->chba->cdev;
+	struct cxgbi_tag_format *tformat = &cdev->tag_format;
+	u32 tag = ntohl((__force u32)hdr_itt);
+
+	cxgbi_tag_debug("release tag 0x%x.\n", tag);
+
+	if (sc &&
+		(scsi_bidi_cmnd(sc) ||
+		 sc->sc_data_direction == DMA_FROM_DEVICE) &&
+			cxgbi_is_ddp_tag(tformat, tag))
+		cdev->ddp_tag_release(cdev, tag);
+}
+
+
+int cxgbi_reserve_itt(struct iscsi_task *task, itt_t *hdr_itt)
+{
+	struct scsi_cmnd *sc = task->sc;
+	struct iscsi_conn *conn = task->conn;
+	struct iscsi_session *sess = conn->session;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_device *cdev = cconn->chba->cdev;
+	struct cxgbi_tag_format *tformat = &cdev->tag_format;
+	u32 sw_tag = (sess->age << cconn->task_idx_bits) | task->itt;
+	u32 tag;
+	int err = -EINVAL;
+
+	if (sc &&
+		(scsi_bidi_cmnd(sc) ||
+		 sc->sc_data_direction == DMA_FROM_DEVICE) &&
+			cxgbi_sw_tag_usable(tformat, sw_tag)) {
+
+		struct cxgbi_sock *csk = cconn->cep->csk;
+		struct cxgbi_gather_list *gl;
+
+		gl = cdev->ddp_make_gl(scsi_in(sc)->length,
+					scsi_in(sc)->table.sgl,
+					scsi_in(sc)->table.nents,
+					cdev->pdev, GFP_ATOMIC);
+		if (gl) {
+			tag = sw_tag;
+			err = cdev->ddp_tag_reserve(cdev, csk->hwtid,
+							tformat, &tag,
+							gl, GFP_ATOMIC);
+			if (err < 0)
+				cdev->ddp_release_gl(gl, cdev->pdev);
+		}
+	}
+	if (err < 0)
+		tag = cxgbi_set_non_ddp_tag(tformat, sw_tag);
+	/*  the itt need to sent in big-endian order */
+	*hdr_itt = (__force itt_t)htonl(tag);
+
+	cxgbi_tag_debug("new sc 0x%p tag 0x%x/0x%x (itt 0x%x, age 0x%x).\n",
+			sc, tag, *hdr_itt, task->itt, sess->age);
+	return 0;
+}
+
+
+void cxgbi_parse_pdu_itt(struct iscsi_conn *conn, itt_t itt,
+				int *idx, int *age)
+{
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_device *cdev = cconn->chba->cdev;
+	u32 tag = ntohl((__force u32) itt);
+	u32 sw_bits;
+
+	sw_bits = cxgbi_tag_nonrsvd_bits(&cdev->tag_format, tag);
+	if (idx)
+		*idx = sw_bits & ((1 << cconn->task_idx_bits) - 1);
+	if (age)
+		*age = (sw_bits >> cconn->task_idx_bits) & ISCSI_AGE_MASK;
+
+	cxgbi_tag_debug("parse tag 0x%x/0x%x, sw 0x%x, itt 0x%x, age 0x%x.\n",
+			tag, itt, sw_bits, idx ? *idx : 0xFFFFF,
+			age ? *age : 0xFF);
+}
+
+void cxgbi_cleanup_task(struct iscsi_task *task)
+{
+	struct cxgbi_task_data *tdata = task->dd_data +
+				sizeof(struct iscsi_tcp_task);
+
+	/*  never reached the xmit task callout */
+	if (tdata->skb)
+		__kfree_skb(tdata->skb);
+	memset(tdata, 0, sizeof(*tdata));
+
+	cxgbi_release_itt(task, task->hdr_itt);
+	iscsi_tcp_cleanup_task(task);
+}
+
diff --git a/drivers/scsi/cxgb4i/libcxgbi.h b/drivers/scsi/cxgb4i/libcxgbi.h
new file mode 100644
index 0000000..058a9aa
--- /dev/null
+++ b/drivers/scsi/cxgb4i/libcxgbi.h
@@ -0,0 +1,430 @@
+/*
+ * libcxgbi.h: Chelsio common library for T3/T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Karen Xie (kxie-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ * Written by: Rakesh Ranjan (rranjan-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ */
+
+#ifndef	__LIBCXGBI_H__
+#define	__LIBCXGBI_H__
+
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/scatterlist.h>
+#include <linux/skbuff.h>
+#include <scsi/libiscsi_tcp.h>
+
+
+#define	cxgbi_log_error(fmt...)	printk(KERN_ERR "cxgbi: ERR! " fmt)
+#define cxgbi_log_warn(fmt...)	printk(KERN_WARNING "cxgbi: WARN! " fmt)
+#define cxgbi_log_info(fmt...)	printk(KERN_INFO "cxgbi: " fmt)
+#define cxgbi_debug_log(fmt, args...) \
+	printk(KERN_INFO "cxgbi: %s - " fmt, __func__ , ## args)
+
+
+#ifdef	__DEBUG_CXGB4I__
+#define	cxgbi_log_debug	cxgbi_debug_log
+#else
+#define cxgbi_log_debug(fmt...)
+#endif
+
+#ifdef __DEBUG_CXGB4I_TAG__
+#define cxgbi_tag_debug        cxgbi_log_debug
+#else
+#define cxgbi_tag_debug(fmt...)
+#endif
+
+#ifdef __DEBUG_CXGB4I_API__
+#define cxgbi_api_debug        cxgbi_log_debug
+#else
+#define cxgbi_api_debug(fmt...)
+#endif
+
+#ifdef __DEBUG_CXGB4I_CONN__
+#define cxgbi_conn_debug         cxgbi_log_debug
+#else
+#define cxgbi_conn_debug(fmt...)
+#endif
+
+#ifdef __DEBUG_CXGB4I_TX__
+#define cxgbi_tx_debug           cxgbi_log_debug
+#else
+#define cxgbi_tx_debug(fmt...)
+#endif
+
+#ifdef __DEBUG_CXGB4I_RX__
+#define cxgbi_rx_debug           cxgbi_log_debug
+#else
+#define cxgbi_rx_debug(fmt...)
+#endif
+
+#define	ISCSI_PDU_NONPAYLOAD_LEN	312 /* bhs(48) + ahs(256) + digest(8)*/
+#define ULP2_MAX_PKT_SIZE		16224
+#define ULP2_MAX_PDU_PAYLOAD	\
+	(ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_LEN)
+
+/* # of pages a pagepod can hold without needing another pagepod */
+#define PPOD_PAGES			4
+#define PPOD_PAGES_MAX			4
+#define PPOD_PAGES_SHIFT		2       /*  4 pages per pod */
+
+
+struct cxgbi_tag_format {
+	unsigned char sw_bits;
+	unsigned char rsvd_bits;
+	unsigned char rsvd_shift;
+	unsigned char filler[1];
+	unsigned int rsvd_mask;
+};
+
+struct cxgbi_gather_list {
+	unsigned int tag;
+	unsigned int length;
+	unsigned int offset;
+	unsigned int nelem;
+	struct page **pages;
+	dma_addr_t phys_addr[0];
+};
+
+struct cxgbi_sock {
+	struct net_device *egdev;
+	struct cxgbi_device *cdev;
+
+	unsigned long flags;
+	unsigned int qset;
+	unsigned int rss_qid;
+
+	unsigned int hwtid;
+	unsigned int atid;
+
+	unsigned int tx_chan;
+	unsigned int rx_chan;
+	unsigned int mss_idx;
+	unsigned int smac_idx;
+	unsigned char port_id;
+
+	void *l2t;
+
+	int wr_max_cred;
+	int wr_cred;
+	int wr_una_cred;
+
+	struct sk_buff *wr_pending_head;
+	struct sk_buff *wr_pending_tail;
+	struct sk_buff *cpl_close;
+	struct sk_buff *cpl_abort_req;
+	struct sk_buff *cpl_abort_rpl;
+	struct sk_buff *skb_ulp_lhdr;
+	spinlock_t lock;
+	atomic_t refcnt;
+	volatile unsigned int state;
+	struct sockaddr_in saddr;
+	struct sockaddr_in daddr;
+	struct dst_entry *dst;
+	struct sk_buff_head receive_queue;
+	struct sk_buff_head write_queue;
+	struct timer_list retry_timer;
+	int err;
+	rwlock_t callback_lock;
+	void *user_data;
+
+	u32 rcv_nxt;
+	u32 copied_seq;
+	u32 rcv_wup;
+	u32 snd_nxt;
+	u32 snd_una;
+	u32 write_seq;
+};
+
+enum cxgbi_sock_states{
+	CXGBI_CSK_ST_CONNECTING = 1,
+	CXGBI_CSK_ST_ESTABLISHED,
+	CXGBI_CSK_ST_ACTIVE_CLOSE,
+	CXGBI_CSK_ST_PASSIVE_CLOSE,
+	CXGBI_CSK_ST_CLOSE_WAIT_1,
+	CXGBI_CSK_ST_CLOSE_WAIT_2,
+	CXGBI_CSK_ST_ABORTING,
+	CXGBI_CSK_ST_CLOSED,
+};
+
+enum cxgbi_sock_flags {
+	CXGBI_CSK_FL_ABORT_RPL_RCVD,	/*received one ABORT_RPL_RSS message */
+	CXGBI_CSK_FL_ABORT_REQ_RCVD,	/*received one ABORT_REQ_RSS message */
+	CXGBI_CSK_FL_ABORT_RPL_PENDING,	/* expecting an abort reply */
+	CXGBI_CSK_FL_TX_DATA_SENT,	/* already sent a TX_DATA WR */
+	CXGBI_CSK_FL_ACTIVE_CLOSE_NEEDED,	/* need to be closed */
+	CXGBI_CSK_FL_OFFLOAD_DOWN,		/* offload function off */
+};
+
+static inline void cxgbi_sock_set_flag(struct cxgbi_sock *csk,
+					enum cxgbi_sock_flags flag)
+{
+	__set_bit(flag, &csk->flags);
+	cxgbi_conn_debug("csk 0x%p, set %d, state %u, flags 0x%lu\n",
+			csk, flag, csk->state, csk->flags);
+}
+
+static inline void cxgbi_sock_clear_flag(struct cxgbi_sock *csk,
+					enum cxgbi_sock_flags flag)
+{
+	__clear_bit(flag, &csk->flags);
+	cxgbi_conn_debug("csk 0x%p, clear %d, state %u, flags 0x%lu\n",
+			csk, flag, csk->state, csk->flags);
+}
+
+static inline int cxgbi_sock_flag(struct cxgbi_sock *csk,
+				enum cxgbi_sock_flags flag)
+{
+	if (csk == NULL)
+		return 0;
+
+	return test_bit(flag, &csk->flags);
+}
+
+static inline void cxgbi_sock_set_state(struct cxgbi_sock *csk, int state)
+{
+	csk->state = state;
+}
+
+static inline void cxgbi_sock_hold(struct cxgbi_sock *csk)
+{
+	atomic_inc(&csk->refcnt);
+}
+
+static inline void cxgbi_sock_put(struct cxgbi_sock *csk)
+{
+	if (atomic_dec_and_test(&csk->refcnt)) {
+		cxgbi_conn_debug("free csk 0x%p, state %u, flags 0x%lx\n",
+				csk, csk->state, csk->flags);
+		kfree(csk);
+	}
+}
+
+static inline unsigned int cxgbi_sock_is_closing(
+			const struct cxgbi_sock *csk)
+{
+	return csk->state >= CXGBI_CSK_ST_ACTIVE_CLOSE;
+}
+
+static inline unsigned int cxgbi_sock_is_established(
+				const struct cxgbi_sock *csk)
+{
+	return csk->state == CXGBI_CSK_ST_ESTABLISHED;
+}
+
+int cxgbi_sock_get_port(struct cxgbi_sock *);
+void cxgbi_sock_put_port(struct cxgbi_sock *);
+
+struct cxgbi_hba {
+	struct net_device *ndev;
+	struct Scsi_Host *shost;
+	struct cxgbi_device *cdev;
+	__be32 ipv4addr;
+};
+
+struct cxgbi_ports_map {
+	unsigned int max_connect;
+	unsigned short sport_base;
+	spinlock_t lock;
+	unsigned int next;
+	struct cxgbi_sock *port_csk[0];
+};
+
+struct cxgbi_device {
+	struct list_head list_head;
+	struct net_device *ndev;
+	struct pci_dev *pdev;
+	unsigned int skb_tx_headroom;
+	unsigned int skb_extra_headroom;
+	struct page *pad_page;
+
+	void (*tx_skb_setmode)(struct sk_buff *, int, int);
+	int (*sock_send_pdus)(struct cxgbi_sock *, struct sk_buff *);
+	int (*ddp_tag_reserve)(struct cxgbi_device *, unsigned int,
+				struct cxgbi_tag_format *, u32 *,
+				struct cxgbi_gather_list *, gfp_t);
+	void (*ddp_tag_release)(struct cxgbi_device *, u32);
+	struct cxgbi_gather_list* (*ddp_make_gl)(unsigned int,
+						struct scatterlist *,
+						unsigned int,
+						struct pci_dev *,
+						gfp_t);
+	void (*ddp_release_gl)(struct cxgbi_gather_list *, struct pci_dev *);
+	__u16 (*get_skb_ulp_mode)(struct sk_buff *);
+
+	struct cxgbi_tag_format tag_format;
+	struct cxgbi_ports_map *pmap;
+
+	void *dd_data;
+};
+
+struct cxgbi_conn {
+	struct list_head list_head;
+	struct cxgbi_endpoint *cep;
+	struct iscsi_conn *iconn;
+	struct cxgbi_hba *chba;
+	u32 task_idx_bits;
+};
+
+struct cxgbi_endpoint {
+	struct cxgbi_conn *cconn;
+	struct cxgbi_hba *chba;
+	struct cxgbi_sock *csk;
+};
+
+#define MAX_PDU_FRAGS	((ULP2_MAX_PDU_PAYLOAD + 512 - 1) / 512)
+struct cxgbi_task_data {
+	unsigned short nr_frags;
+	skb_frag_t frags[MAX_PDU_FRAGS];
+	struct sk_buff *skb;
+	unsigned int offset;
+	unsigned int count;
+	unsigned int sgoffset;
+};
+
+static inline int cxgbi_is_ddp_tag(struct cxgbi_tag_format *tformat, u32 tag)
+{
+	return !(tag & (1 << (tformat->rsvd_bits + tformat->rsvd_shift - 1)));
+}
+
+static inline int cxgbi_sw_tag_usable(struct cxgbi_tag_format *tformat,
+					u32 sw_tag)
+{
+	sw_tag >>= (32 - tformat->rsvd_bits);
+	return !sw_tag;
+}
+
+static inline u32 cxgbi_set_non_ddp_tag(struct cxgbi_tag_format *tformat,
+					u32 sw_tag)
+{
+	unsigned char shift = tformat->rsvd_bits + tformat->rsvd_shift - 1;
+
+	u32 mask = (1 << shift) - 1;
+
+	if (sw_tag && (sw_tag & ~mask)) {
+		u32 v1 = sw_tag & ((1 << shift) - 1);
+		u32 v2 = (sw_tag >> (shift - 1)) << shift;
+
+		return v2 | v1 | 1 << shift;
+	}
+
+	return sw_tag | 1 << shift;
+}
+
+static inline u32 cxgbi_ddp_tag_base(struct cxgbi_tag_format *tformat,
+					u32 sw_tag)
+{
+	u32 mask = (1 << tformat->rsvd_shift) - 1;
+
+	if (sw_tag && (sw_tag & ~mask)) {
+		u32 v1 = sw_tag & mask;
+		u32 v2 = sw_tag >> tformat->rsvd_shift;
+
+		v2 <<= tformat->rsvd_bits + tformat->rsvd_shift;
+
+		return v2 | v1;
+	}
+
+	return sw_tag;
+}
+
+static inline u32 cxgbi_tag_rsvd_bits(struct cxgbi_tag_format *tformat,
+					u32 tag)
+{
+	if (cxgbi_is_ddp_tag(tformat, tag))
+		return (tag >> tformat->rsvd_shift) & tformat->rsvd_mask;
+
+	return 0;
+}
+
+static inline u32 cxgbi_tag_nonrsvd_bits(struct cxgbi_tag_format *tformat,
+					u32 tag)
+{
+	unsigned char shift = tformat->rsvd_bits + tformat->rsvd_shift - 1;
+	u32 v1, v2;
+
+	if (cxgbi_is_ddp_tag(tformat, tag)) {
+		v1 = tag & ((1 << tformat->rsvd_shift) - 1);
+		v2 = (tag >> (shift + 1)) << tformat->rsvd_shift;
+	} else {
+		u32 mask = (1 << shift) - 1;
+		tag &= ~(1 << shift);
+		v1 = tag & mask;
+		v2 = (tag >> 1) & ~mask;
+	}
+	return v1 | v2;
+}
+
+static inline void *cxgbi_alloc_big_mem(unsigned int size,
+					gfp_t gfp)
+{
+	void *p = kmalloc(size, gfp);
+	if (!p)
+		p = vmalloc(size);
+	if (p)
+		memset(p, 0, size);
+	return p;
+}
+
+static inline void cxgbi_free_big_mem(void *addr)
+{
+	if (is_vmalloc_addr(addr))
+		vfree(addr);
+	else
+		kfree(addr);
+}
+
+#define RX_DDP_STATUS_IPP_SHIFT		27      /* invalid pagepod */
+#define RX_DDP_STATUS_TID_SHIFT		26      /* tid mismatch */
+#define RX_DDP_STATUS_COLOR_SHIFT	25      /* color mismatch */
+#define RX_DDP_STATUS_OFFSET_SHIFT	24      /* offset mismatch */
+#define RX_DDP_STATUS_ULIMIT_SHIFT	23      /* ulimit error */
+#define RX_DDP_STATUS_TAG_SHIFT		22      /* tag mismatch */
+#define RX_DDP_STATUS_DCRC_SHIFT	21      /* dcrc error */
+#define RX_DDP_STATUS_HCRC_SHIFT	20      /* hcrc error */
+#define RX_DDP_STATUS_PAD_SHIFT		19      /* pad error */
+#define RX_DDP_STATUS_PPP_SHIFT		18      /* pagepod parity error */
+#define RX_DDP_STATUS_LLIMIT_SHIFT	17      /* llimit error */
+#define RX_DDP_STATUS_DDP_SHIFT		16      /* ddp'able */
+#define RX_DDP_STATUS_PMM_SHIFT		15      /* pagepod mismatch */
+
+
+#define ULP2_FLAG_DATA_READY		0x1
+#define ULP2_FLAG_DATA_DDPED		0x2
+#define ULP2_FLAG_HCRC_ERROR		0x4
+#define ULP2_FLAG_DCRC_ERROR		0x8
+#define ULP2_FLAG_PAD_ERROR		0x10
+
+static inline void *cplhdr(struct sk_buff *skb)
+{
+	return skb->data;
+}
+
+int cxgbi_reserve_itt(struct iscsi_task *task, itt_t *hdr_itt);
+void cxgbi_release_itt(struct iscsi_task *task, itt_t hdr_itt);
+void cxgbi_parse_pdu_itt(struct iscsi_conn *conn, itt_t itt,
+				int *idx, int *age);
+void cxgbi_cleanup_task(struct iscsi_task *task);
+
+int cxgbi_conn_read_bhs_pdu_skb(struct iscsi_conn *, struct sk_buff *);
+int cxgbi_conn_read_data_pdu_skb(struct iscsi_conn *, struct sk_buff *);
+void cxgbi_conn_tx_open(struct cxgbi_sock *);
+int cxgbi_conn_init_pdu(struct iscsi_task *, unsigned int , unsigned int);
+int cxgbi_conn_alloc_pdu(struct iscsi_task *, u8);
+int cxgbi_conn_xmit_pdu(struct iscsi_task *);
+
+int cxgbi_pdu_init(struct cxgbi_device *);
+void cxgbi_pdu_cleanup(struct cxgbi_device *);
+
+
+#endif	/*__LIBCXGBI_H__*/
+
-- 
1.6.6.1

-- 
You received this message because you are subscribed to the Google Groups "open-iscsi" group.
To post to this group, send email to open-iscsi-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
To unsubscribe from this group, send email to open-iscsi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit this group at http://groups.google.com/group/open-iscsi?hl=en.

^ permalink raw reply related

* [PATCH 2/3] cxgb4i_v3: main driver files
From: Rakesh Ranjan @ 2010-05-15 17:24 UTC (permalink / raw)
  To: NETDEVML, SCSIDEVML, OISCSIML
  Cc: LKML, Karen Xie, David Miller, James Bottomley, Mike Christie,
	Anish Bhatt, Rakesh Ranjan, Rakesh Ranjan
In-Reply-To: <1273944249-311-2-git-send-email-rakesh-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>

From: Rakesh Ranjan <rranjan-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>


Signed-off-by: Rakesh Ranjan <rakesh-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
---
 drivers/scsi/cxgb4i/cxgb4i.h         |  101 ++
 drivers/scsi/cxgb4i/cxgb4i_ddp.c     |  678 +++++++++++++
 drivers/scsi/cxgb4i/cxgb4i_ddp.h     |  118 +++
 drivers/scsi/cxgb4i/cxgb4i_offload.c | 1846 ++++++++++++++++++++++++++++++++++
 drivers/scsi/cxgb4i/cxgb4i_offload.h |   91 ++
 drivers/scsi/cxgb4i/cxgb4i_snic.c    |  260 +++++
 6 files changed, 3094 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/cxgb4i/cxgb4i.h
 create mode 100644 drivers/scsi/cxgb4i/cxgb4i_ddp.c
 create mode 100644 drivers/scsi/cxgb4i/cxgb4i_ddp.h
 create mode 100644 drivers/scsi/cxgb4i/cxgb4i_offload.c
 create mode 100644 drivers/scsi/cxgb4i/cxgb4i_offload.h
 create mode 100644 drivers/scsi/cxgb4i/cxgb4i_snic.c

diff --git a/drivers/scsi/cxgb4i/cxgb4i.h b/drivers/scsi/cxgb4i/cxgb4i.h
new file mode 100644
index 0000000..fbf7699
--- /dev/null
+++ b/drivers/scsi/cxgb4i/cxgb4i.h
@@ -0,0 +1,101 @@
+/*
+ * cxgb4i.h: Chelsio T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Karen Xie (kxie-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ * Written by: Rakesh Ranjan (rranjan-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ */
+
+#ifndef	__CXGB4I_H__
+#define	__CXGB4I_H__
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/scatterlist.h>
+#include <linux/skbuff.h>
+#include <scsi/libiscsi_tcp.h>
+
+#include "t4fw_api.h"
+#include "t4_msg.h"
+#include "l2t.h"
+#include "cxgb4.h"
+#include "cxgb4_uld.h"
+
+#include "libcxgbi.h"
+#include "cxgb4i_ddp.h"
+#include "cxgb4i_offload.h"
+
+#define	CXGB4I_SCSI_HOST_QDEPTH	1024
+#define	CXGB4I_MAX_TARGET	CXGB4I_MAX_CONN
+#define	CXGB4I_MAX_LUN		512
+#define	ISCSI_PDU_NONPAYLOAD_MAX \
+	(sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE + \
+	 (2 * ISCSI_DIGEST_SIZE))
+
+struct cxgb4i_snic;
+struct cxgb4i_host;
+struct cxgb4i_endpoint;
+typedef int (*cxgb4i_cplhandler_func)(struct cxgb4i_snic *, struct sk_buff *);
+
+struct cxgb4i_snic {
+	struct list_head list_head;
+	spinlock_t lock;
+	struct cxgbi_device cdev;
+	struct cxgbi_hba *hba[MAX_NPORTS];
+	unsigned char hba_cnt;
+	unsigned int flags;
+	unsigned int tx_max_size;
+	unsigned int rx_max_size;
+	struct cxgb4_lld_info lldi;
+	struct cxgb4i_ddp_info *ddp;
+	cxgb4i_cplhandler_func *handlers;
+};
+
+int cxgb4i_ofld_init(struct cxgb4i_snic *);
+void cxgb4i_ofld_cleanup(struct cxgb4i_snic *);
+struct cxgb4i_snic *cxgb4i_find_snic(struct net_device *, __be32);
+struct cxgbi_hba *cxgb4i_hba_find_by_netdev(struct net_device *);
+struct cxgbi_hba *cxgb4i_hba_add(struct cxgb4i_snic *, struct net_device *);
+void cxgb4i_hba_remove(struct cxgbi_hba *);
+int cxgb4i_iscsi_init(void);
+void cxgb4i_iscsi_cleanup(void);
+
+static inline void cxgb4i_set_iscsi_ipv4(struct cxgbi_hba *chba, __be32 ipaddr)
+{
+	chba->ipv4addr = ipaddr;
+}
+
+static inline __be32 cxgb4i_get_iscsi_ipv4(struct cxgbi_hba *chba)
+{
+	return chba->ipv4addr;
+}
+
+static inline struct cxgb4i_snic *cxgb4i_get_snic(struct cxgbi_device *cdev)
+{
+	return (struct cxgb4i_snic *)cdev->dd_data;
+}
+
+
+#define W_TCB_ULP_TYPE          0
+#define TCB_ULP_TYPE_SHIFT      0
+#define TCB_ULP_TYPE_MASK       0xfULL
+#define TCB_ULP_TYPE(x)         ((x) << TCB_ULP_TYPE_SHIFT)
+
+#define W_TCB_ULP_RAW           0
+#define TCB_ULP_RAW_SHIFT       4
+#define TCB_ULP_RAW_MASK        0xffULL
+#define TCB_ULP_RAW(x)          ((x) << TCB_ULP_RAW_SHIFT)
+
+
+#endif	/* __CXGB4I_H__ */
+
diff --git a/drivers/scsi/cxgb4i/cxgb4i_ddp.c b/drivers/scsi/cxgb4i/cxgb4i_ddp.c
new file mode 100644
index 0000000..1e53c0e
--- /dev/null
+++ b/drivers/scsi/cxgb4i/cxgb4i_ddp.c
@@ -0,0 +1,678 @@
+/*
+ * cxgb4i_ddp.c: Chelsio T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Karen Xie (kxie-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ * Written by: Rakesh Ranjan (rranjan-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ */
+
+#include <linux/skbuff.h>
+#include <linux/scatterlist.h>
+
+
+#include "libcxgbi.h"
+#include "cxgb4i.h"
+#include "cxgb4i_ddp.h"
+
+#define DDP_PGIDX_MAX	4
+#define DDP_THRESHOLD	2048
+
+static unsigned char ddp_page_order[DDP_PGIDX_MAX] = {0, 1, 2, 4};
+static unsigned char ddp_page_shift[DDP_PGIDX_MAX] = {12, 13, 14, 16};
+static unsigned char page_idx = DDP_PGIDX_MAX;
+
+static unsigned char sw_tag_idx_bits;
+static unsigned char sw_tag_age_bits;
+
+
+static inline void cxgb4i_ddp_ppod_set(struct pagepod *ppod,
+					struct pagepod_hdr *hdr,
+					struct cxgbi_gather_list *gl,
+					unsigned int pidx)
+{
+	int i;
+
+	memcpy(ppod, hdr, sizeof(*hdr));
+	for (i = 0; i < (PPOD_PAGES_MAX + 1); i++, pidx++) {
+		ppod->addr[i] = pidx < gl->nelem ?
+			cpu_to_be64(gl->phys_addr[pidx]) : 0ULL;
+	}
+}
+
+static inline void cxgb4i_ddp_ppod_clear(struct pagepod *ppod)
+{
+	memset(ppod, 0, sizeof(*ppod));
+}
+
+static inline void cxgb4i_ddp_ulp_mem_io_set_hdr(struct ulp_mem_io *req,
+					unsigned int wr_len, unsigned int dlen,
+					unsigned int pm_addr)
+{
+	struct ulptx_sgl *sgl;
+
+	INIT_ULPTX_WR(req, wr_len, 0, 0);
+	req->cmd = htonl(ULPTX_CMD(ULP_TX_MEM_WRITE));
+	req->dlen = htonl(ULP_MEMIO_DATA_LEN(dlen >> 5));
+	req->len16 = htonl(DIV_ROUND_UP(wr_len - sizeof(req->wr), 16));
+	req->lock_addr = htonl(ULP_MEMIO_ADDR(pm_addr >> 5));
+
+	sgl = (struct ulptx_sgl *)(req + 1);
+	sgl->cmd_nsge = htonl(ULPTX_CMD(ULP_TX_SC_DSGL) | ULPTX_NSGE(1));
+	sgl->len0 = htonl(dlen);
+}
+
+static int cxgb4i_ddp_ppod_write_sgl(struct cxgb4i_ddp_info *ddp,
+					struct pagepod_hdr *hdr,
+					unsigned int idx,
+					unsigned int npods,
+					struct cxgbi_gather_list *gl,
+					unsigned int gl_pidx)
+{
+	unsigned int dlen = PPOD_SIZE * npods;
+	unsigned int pm_addr = idx * PPOD_SIZE + ddp->llimit;
+	unsigned int wr_len = roundup(sizeof(struct ulp_mem_io) +
+					sizeof(struct ulptx_sgl), 16);
+	struct sk_buff *skb = alloc_skb(wr_len + dlen, GFP_ATOMIC);
+	struct ulp_mem_io *req;
+	struct ulptx_sgl *sgl;
+	struct pagepod *ppod;
+	unsigned int i;
+
+	if (!skb) {
+		cxgbi_log_error("snic 0x%p, idx %u, npods %u, OOM\n",
+				ddp->snic, idx, npods);
+		return -ENOMEM;
+	}
+
+	memset(skb->data, 0, wr_len + dlen);
+	skb->queue_mapping = CPL_PRIORITY_CONTROL;
+
+	req = (struct ulp_mem_io *)__skb_put(skb, wr_len);
+	cxgb4i_ddp_ulp_mem_io_set_hdr(req, wr_len, dlen, pm_addr);
+	sgl = (struct ulptx_sgl *)(req + 1);
+	ppod = (struct pagepod *)(sgl + 1);
+	sgl->addr0 = cpu_to_be64(virt_to_phys(ppod));
+
+	for (i = 0; i < npods; i++, ppod++, gl_pidx += PPOD_PAGES_MAX) {
+		if (!hdr && !gl)
+			cxgb4i_ddp_ppod_clear(ppod);
+		else
+			cxgb4i_ddp_ppod_set(ppod, hdr, gl, gl_pidx);
+
+	}
+
+	cxgb4_ofld_send(ddp->snic->lldi.ports[0], skb);
+
+	return 0;
+}
+
+static int cxgb4i_ddp_set_map(struct cxgb4i_ddp_info *ddp,
+					struct pagepod_hdr *hdr,
+					unsigned int idx,
+					unsigned int npods,
+					struct cxgbi_gather_list *gl)
+{
+	unsigned int pidx = 0;
+	unsigned int w_npods = 0;
+	unsigned int cnt;
+	int err = 0;
+
+	for (; w_npods < npods; idx += cnt, w_npods += cnt,
+					pidx += PPOD_PAGES_MAX) {
+		cnt = npods - w_npods;
+		if (cnt > ULPMEM_DSGL_MAX_NPPODS)
+			cnt = ULPMEM_DSGL_MAX_NPPODS;
+		err = cxgb4i_ddp_ppod_write_sgl(ddp, hdr, idx, cnt, gl, pidx);
+
+		if (err < 0)
+			break;
+	}
+
+	return err;
+}
+
+static void cxgb4i_ddp_clear_map(struct cxgb4i_ddp_info *ddp,
+						unsigned int tag,
+						unsigned int idx,
+						unsigned int npods)
+{
+	int err;
+	unsigned int w_npods = 0;
+	unsigned int cnt;
+
+	for (; w_npods < npods; idx += cnt, w_npods += cnt) {
+		cnt = npods - w_npods;
+
+		if (cnt > ULPMEM_DSGL_MAX_NPPODS)
+			cnt = ULPMEM_DSGL_MAX_NPPODS;
+		err = cxgb4i_ddp_ppod_write_sgl(ddp, NULL, idx, cnt, NULL, 0);
+
+		if (err < 0)
+			break;
+	}
+}
+
+static inline int cxgb4i_ddp_find_unused_entries(struct cxgb4i_ddp_info *ddp,
+					unsigned int start, unsigned int max,
+					unsigned int count,
+					struct cxgbi_gather_list *gl)
+{
+	unsigned int i, j, k;
+
+	/*  not enough entries */
+	if ((max - start) < count)
+		return -EBUSY;
+
+	max -= count;
+	spin_lock(&ddp->map_lock);
+	for (i = start; i < max;) {
+		for (j = 0, k = i; j < count; j++, k++) {
+			if (ddp->gl_map[k])
+				break;
+		}
+		if (j == count) {
+			for (j = 0, k = i; j < count; j++, k++)
+				ddp->gl_map[k] = gl;
+			spin_unlock(&ddp->map_lock);
+			return i;
+		}
+		i += j + 1;
+	}
+	spin_unlock(&ddp->map_lock);
+	return -EBUSY;
+}
+
+static inline void cxgb4i_ddp_unmark_entries(struct cxgb4i_ddp_info *ddp,
+							int start, int count)
+{
+	spin_lock(&ddp->map_lock);
+	memset(&ddp->gl_map[start], 0,
+			count * sizeof(struct cxgbi_gather_list *));
+	spin_unlock(&ddp->map_lock);
+}
+
+static int cxgb4i_ddp_find_page_index(unsigned long pgsz)
+{
+	int i;
+
+	for (i = 0; i < DDP_PGIDX_MAX; i++) {
+		if (pgsz == (1UL << ddp_page_shift[i]))
+			return i;
+	}
+	cxgbi_log_debug("ddp page size 0x%lx not supported\n", pgsz);
+
+	return DDP_PGIDX_MAX;
+}
+
+static int cxgb4i_ddp_adjust_page_table(void)
+{
+	int i;
+	unsigned int base_order, order;
+
+	if (PAGE_SIZE < (1UL << ddp_page_shift[0])) {
+		cxgbi_log_info("PAGE_SIZE 0x%lx too small, min 0x%lx\n",
+				PAGE_SIZE, 1UL << ddp_page_shift[0]);
+		return -EINVAL;
+	}
+
+	base_order = get_order(1UL << ddp_page_shift[0]);
+	order = get_order(1UL << PAGE_SHIFT);
+
+	for (i = 0; i < DDP_PGIDX_MAX; i++) {
+		/* first is the kernel page size, then just doubling the size */
+		ddp_page_order[i] = order - base_order + i;
+		ddp_page_shift[i] = PAGE_SHIFT + i;
+	}
+
+	return 0;
+}
+
+static inline void cxgb4i_ddp_gl_unmap(struct pci_dev *pdev,
+					struct cxgbi_gather_list *gl)
+{
+	int i;
+
+	for (i = 0; i < gl->nelem; i++)
+		dma_unmap_page(&pdev->dev, gl->phys_addr[i], PAGE_SIZE,
+				PCI_DMA_FROMDEVICE);
+}
+
+static inline int cxgb4i_ddp_gl_map(struct pci_dev *pdev,
+				struct cxgbi_gather_list *gl)
+{
+	int i;
+
+	for (i = 0; i < gl->nelem; i++) {
+		gl->phys_addr[i] = dma_map_page(&pdev->dev, gl->pages[i], 0,
+						PAGE_SIZE,
+						PCI_DMA_FROMDEVICE);
+		if (unlikely(dma_mapping_error(&pdev->dev, gl->phys_addr[i])))
+			goto unmap;
+	}
+
+	return i;
+
+unmap:
+	if (i) {
+		unsigned int nelem = gl->nelem;
+
+		gl->nelem = i;
+		cxgb4i_ddp_gl_unmap(pdev, gl);
+		gl->nelem = nelem;
+	}
+	return -ENOMEM;
+}
+
+
+void cxgb4i_ddp_release_gl(struct cxgbi_gather_list *gl,
+				struct pci_dev *pdev)
+{
+	cxgb4i_ddp_gl_unmap(pdev, gl);
+	kfree(gl);
+}
+
+struct cxgbi_gather_list *cxgb4i_ddp_make_gl(unsigned int xferlen,
+						struct scatterlist *sgl,
+						unsigned int sgcnt,
+						struct pci_dev *pdev,
+						gfp_t gfp)
+{
+	struct cxgbi_gather_list *gl;
+	struct scatterlist *sg = sgl;
+	struct page *sgpage = sg_page(sg);
+	unsigned int sglen = sg->length;
+	unsigned int sgoffset = sg->offset;
+	unsigned int npages = (xferlen + sgoffset + PAGE_SIZE - 1) >>
+				PAGE_SHIFT;
+	int i = 1, j = 0;
+
+	if (xferlen < DDP_THRESHOLD) {
+		cxgbi_log_debug("xfer %u < threshold %u, no ddp.\n",
+				xferlen, DDP_THRESHOLD);
+		return NULL;
+	}
+
+	gl = kzalloc(sizeof(struct cxgbi_gather_list) +
+			npages * (sizeof(dma_addr_t) + sizeof(struct page *)),
+			gfp);
+	if (!gl)
+		return NULL;
+
+	gl->pages = (struct page **)&gl->phys_addr[npages];
+	gl->length = xferlen;
+	gl->offset = sgoffset;
+	gl->pages[0] = sgpage;
+
+	sg = sg_next(sg);
+	while (sg) {
+		struct page *page = sg_page(sg);
+
+		if (sgpage == page && sg->offset == sgoffset + sglen)
+			sglen += sg->length;
+		else {
+			/*  make sure the sgl is fit for ddp:
+			 *  each has the same page size, and
+			 *  all of the middle pages are used completely
+			 */
+			if ((j && sgoffset) || ((i != sgcnt - 1) &&
+					 ((sglen + sgoffset) & ~PAGE_MASK)))
+				goto error_out;
+
+			j++;
+			if (j == gl->nelem || sg->offset)
+				goto error_out;
+			gl->pages[j] = page;
+			sglen = sg->length;
+			sgoffset = sg->offset;
+			sgpage = page;
+		}
+		i++;
+		sg = sg_next(sg);
+	}
+	gl->nelem = ++j;
+
+	if (cxgb4i_ddp_gl_map(pdev, gl) < 0)
+		goto error_out;
+
+	return gl;
+
+error_out:
+	kfree(gl);
+	return NULL;
+}
+
+
+static void cxgb4i_ddp_tag_release(struct cxgbi_device *cdev, u32 tag)
+{
+	struct cxgb4i_snic *snic = cxgb4i_get_snic(cdev);
+	struct cxgb4i_ddp_info *ddp = snic->ddp;
+	u32 idx;
+
+	if (!ddp) {
+		cxgbi_log_error("release ddp tag 0x%x, ddp NULL.\n", tag);
+		return;
+	}
+
+	idx = (tag >> PPOD_IDX_SHIFT) & ddp->idx_mask;
+	if (idx < ddp->nppods) {
+		struct cxgbi_gather_list *gl = ddp->gl_map[idx];
+		unsigned int npods;
+
+		if (!gl || !gl->nelem) {
+			cxgbi_log_error("rel 0x%x, idx 0x%x, gl 0x%p, %u\n",
+					tag, idx, gl, gl ? gl->nelem : 0);
+			return;
+		}
+		npods = (gl->nelem + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT;
+		cxgbi_log_debug("ddp tag 0x%x, release idx 0x%x, npods %u.\n",
+				tag, idx, npods);
+		cxgb4i_ddp_clear_map(ddp, tag, idx, npods);
+		cxgb4i_ddp_unmark_entries(ddp, idx, npods);
+		cxgb4i_ddp_release_gl(gl, ddp->pdev);
+	} else
+		cxgbi_log_error("ddp tag 0x%x, idx 0x%x > max 0x%x.\n",
+				tag, idx, ddp->nppods);
+}
+
+static int cxgb4i_ddp_tag_reserve(struct cxgbi_device *cdev, unsigned int tid,
+				struct cxgbi_tag_format *tformat, u32 *tagp,
+				struct cxgbi_gather_list *gl, gfp_t gfp)
+{
+	struct cxgb4i_snic *snic = cxgb4i_get_snic(cdev);
+	struct cxgb4i_ddp_info *ddp = snic->ddp;
+	struct pagepod_hdr hdr;
+	unsigned int npods;
+	int idx = -1;
+	int err = -ENOMEM;
+	u32 sw_tag = *tagp;
+	u32 tag;
+
+	if (page_idx >= DDP_PGIDX_MAX || !ddp || !gl || !gl->nelem ||
+			gl->length < DDP_THRESHOLD) {
+		cxgbi_log_debug("pgidx %u, xfer %u/%u, NO ddp.\n",
+				page_idx, gl->length, DDP_THRESHOLD);
+		return -EINVAL;
+	}
+
+	npods = (gl->nelem + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT;
+
+	if (ddp->idx_last == ddp->nppods)
+		idx = cxgb4i_ddp_find_unused_entries(ddp, 0, ddp->nppods,
+							npods, gl);
+	else {
+		idx = cxgb4i_ddp_find_unused_entries(ddp, ddp->idx_last + 1,
+							ddp->nppods, npods,
+							gl);
+		if (idx < 0 && ddp->idx_last >= npods) {
+			idx = cxgb4i_ddp_find_unused_entries(ddp, 0,
+				min(ddp->idx_last + npods, ddp->nppods),
+							npods, gl);
+		}
+	}
+	if (idx < 0) {
+		cxgbi_log_debug("xferlen %u, gl %u, npods %u NO DDP.\n",
+				gl->length, gl->nelem, npods);
+		return idx;
+	}
+
+	tag = cxgbi_ddp_tag_base(tformat, sw_tag);
+	tag |= idx << PPOD_IDX_SHIFT;
+
+	hdr.rsvd = 0;
+	hdr.vld_tid = htonl(PPOD_VALID_FLAG | PPOD_TID(tid));
+	hdr.pgsz_tag_clr = htonl(tag & ddp->rsvd_tag_mask);
+	hdr.max_offset = htonl(gl->length);
+	hdr.page_offset = htonl(gl->offset);
+
+	err = cxgb4i_ddp_set_map(ddp, &hdr, idx, npods, gl);
+	if (err < 0)
+		goto unmark_entries;
+
+	ddp->idx_last = idx;
+	cxgbi_log_debug("xfer %u, gl %u,%u, tid 0x%x, 0x%x -> 0x%x(%u,%u).\n",
+			gl->length, gl->nelem, gl->offset, tid, sw_tag, tag,
+			idx, npods);
+	*tagp = tag;
+	return 0;
+
+unmark_entries:
+	cxgb4i_ddp_unmark_entries(ddp, idx, npods);
+	return err;
+}
+
+
+static int cxgb4i_ddp_setup_conn_pgidx(struct cxgbi_sock *csk,
+					unsigned int tid, int pg_idx,
+					bool reply)
+{
+	struct sk_buff *skb = alloc_skb(sizeof(struct cpl_set_tcb_field),
+					GFP_KERNEL);
+	struct cpl_set_tcb_field *req;
+	u64 val = pg_idx < DDP_PGIDX_MAX ? pg_idx : 0;
+
+	if (!skb)
+		return -ENOMEM;
+
+	/*  set up ulp submode and page size */
+	val = (val & 0x03) << 2;
+	val |= TCB_ULP_TYPE(ULP_MODE_ISCSI);
+	req = (struct cpl_set_tcb_field *)skb_put(skb, sizeof(*req));
+	INIT_TP_WR(req, tid);
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, csk->hwtid));
+	req->reply_ctrl = htons(NO_REPLY(reply) | QUEUENO(csk->rss_qid));
+	req->word_cookie = htons(TCB_WORD(W_TCB_ULP_RAW));
+	req->mask = cpu_to_be64(TCB_ULP_TYPE(TCB_ULP_TYPE_MASK));
+	req->val = cpu_to_be64(val);
+
+	skb->queue_mapping = CPL_PRIORITY_CONTROL;
+
+	cxgb4_ofld_send(cxgb4i_get_snic(csk->cdev)->lldi.ports[0], skb);
+	return 0;
+}
+
+int cxgb4i_ddp_setup_conn_host_pagesize(struct cxgbi_sock *csk,
+						unsigned int tid,
+						int reply)
+{
+	return cxgb4i_ddp_setup_conn_pgidx(csk, tid, page_idx, reply);
+}
+
+int cxgb4i_ddp_setup_conn_pagesize(struct cxgbi_sock *csk, unsigned int tid,
+					int reply, unsigned long pgsz)
+{
+	int pgidx = cxgb4i_ddp_find_page_index(pgsz);
+
+	return cxgb4i_ddp_setup_conn_pgidx(csk, tid, pgidx, reply);
+}
+
+int cxgb4i_ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
+				int hcrc, int dcrc, int reply)
+{
+	struct sk_buff *skb = alloc_skb(sizeof(struct cpl_set_tcb_field),
+					GFP_KERNEL);
+	struct cpl_set_tcb_field *req;
+	u64 val = (hcrc ? ULP_CRC_HEADER : 0) | (dcrc ? ULP_CRC_DATA : 0);
+	val = TCB_ULP_RAW(val);
+	val |= TCB_ULP_TYPE(ULP_MODE_ISCSI);
+
+	if (!skb)
+		return -ENOMEM;
+
+	/*  set up ulp submode and page size */
+	req = (struct cpl_set_tcb_field *)skb_put(skb, sizeof(*req));
+	INIT_TP_WR(req, tid);
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
+	req->reply_ctrl = htons(NO_REPLY(reply) | QUEUENO(csk->rss_qid));
+	req->word_cookie = htons(TCB_WORD(W_TCB_ULP_RAW));
+	req->mask = cpu_to_be64(TCB_ULP_RAW(TCB_ULP_RAW_MASK));
+	req->val = cpu_to_be64(val);
+
+	skb->queue_mapping = CPL_PRIORITY_CONTROL;
+
+	cxgb4_ofld_send(cxgb4i_get_snic(csk->cdev)->lldi.ports[0], skb);
+	return 0;
+}
+
+static void __cxgb4i_ddp_cleanup(struct kref *kref)
+{
+	int i = 0;
+	struct cxgb4i_ddp_info *ddp = container_of(kref,
+						struct cxgb4i_ddp_info,
+						refcnt);
+
+	cxgbi_log_info("kref release ddp 0x%p, snic 0x%p\n", ddp, ddp->snic);
+
+	ddp->snic->ddp = NULL;
+
+	while (i < ddp->nppods) {
+		struct cxgbi_gather_list *gl = ddp->gl_map[i];
+
+		if (gl) {
+			int npods = (gl->nelem + PPOD_PAGES_MAX - 1) >>
+							PPOD_PAGES_SHIFT;
+			cxgbi_log_info("snic 0x%p, ddp %d + %d\n",
+						ddp->snic, i, npods);
+			kfree(gl);
+			i += npods;
+		} else
+			i++;
+	}
+	cxgbi_free_big_mem(ddp);
+}
+
+
+static void __cxgb4i_ddp_init(struct cxgb4i_snic *snic)
+{
+	struct cxgb4i_ddp_info *ddp = snic->ddp;
+	unsigned int ppmax, bits, tagmask, pgsz_factor[4];
+	int i;
+
+	if (ddp) {
+		kref_get(&ddp->refcnt);
+		cxgbi_log_warn("snic 0x%p, ddp 0x%p already set up\n",
+				snic, snic->ddp);
+		return;
+	}
+
+	sw_tag_idx_bits = (__ilog2_u32(ISCSI_ITT_MASK)) + 1;
+	sw_tag_age_bits = (__ilog2_u32(ISCSI_AGE_MASK)) + 1;
+	snic->cdev.tag_format.sw_bits = sw_tag_idx_bits + sw_tag_age_bits;
+
+	cxgbi_log_info("tag itt 0x%x, %u bits, age 0x%x, %u bits\n",
+			ISCSI_ITT_MASK, sw_tag_idx_bits,
+			ISCSI_AGE_MASK, sw_tag_age_bits);
+
+	ppmax = (snic->lldi.vr->iscsi.size >> PPOD_SIZE_SHIFT);
+	bits = __ilog2_u32(ppmax) + 1;
+	if (bits > PPOD_IDX_MAX_SIZE)
+		bits = PPOD_IDX_MAX_SIZE;
+	ppmax = (1 << (bits - 1)) - 1;
+
+	ddp = cxgbi_alloc_big_mem(sizeof(struct cxgb4i_ddp_info) +
+			ppmax * (sizeof(struct cxgbi_gather_list *) +
+				sizeof(struct sk_buff *)),
+				GFP_KERNEL);
+	if (!ddp) {
+		cxgbi_log_warn("snic 0x%p unable to alloc ddp 0x%d, "
+			       "ddp disabled\n", snic, ppmax);
+		return;
+	}
+
+	ddp->gl_map = (struct cxgbi_gather_list **)(ddp + 1);
+	spin_lock_init(&ddp->map_lock);
+	kref_init(&ddp->refcnt);
+
+	ddp->snic = snic;
+	ddp->pdev = snic->lldi.pdev;
+	ddp->max_txsz = min_t(unsigned int,
+				snic->lldi.iscsi_iolen,
+				ULP2_MAX_PKT_SIZE);
+	ddp->max_rxsz = min_t(unsigned int,
+				snic->lldi.iscsi_iolen,
+				ULP2_MAX_PKT_SIZE);
+	ddp->llimit = snic->lldi.vr->iscsi.start;
+	ddp->ulimit = ddp->llimit + snic->lldi.vr->iscsi.size;
+	ddp->nppods = ppmax;
+	ddp->idx_last = ppmax;
+	ddp->idx_bits = bits;
+	ddp->idx_mask = (1 << bits) - 1;
+	ddp->rsvd_tag_mask = (1 << (bits + PPOD_IDX_SHIFT)) - 1;
+
+	tagmask = ddp->idx_mask << PPOD_IDX_SHIFT;
+	for (i = 0; i < DDP_PGIDX_MAX; i++)
+		pgsz_factor[i] = ddp_page_order[i];
+
+	cxgb4_iscsi_init(snic->lldi.ports[0], tagmask, pgsz_factor);
+	snic->ddp = ddp;
+
+	snic->cdev.tag_format.rsvd_bits = ddp->idx_bits;
+	snic->cdev.tag_format.rsvd_shift = PPOD_IDX_SHIFT;
+	snic->cdev.tag_format.rsvd_mask =
+		((1 << snic->cdev.tag_format.rsvd_bits) - 1);
+
+	cxgbi_log_info("tag format: sw %u, rsvd %u,%u, mask 0x%x.\n",
+			snic->cdev.tag_format.sw_bits,
+			snic->cdev.tag_format.rsvd_bits,
+			snic->cdev.tag_format.rsvd_shift,
+			snic->cdev.tag_format.rsvd_mask);
+
+	snic->tx_max_size = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
+				ddp->max_txsz - ISCSI_PDU_NONPAYLOAD_LEN);
+	snic->rx_max_size = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
+				ddp->max_rxsz - ISCSI_PDU_NONPAYLOAD_LEN);
+
+	cxgbi_log_info("max payload size: %u/%u, %u/%u.\n",
+			snic->tx_max_size, ddp->max_txsz,
+			snic->rx_max_size, ddp->max_rxsz);
+
+	cxgbi_log_info("snic 0x%p, nppods %u, bits %u, mask 0x%x,0x%x "
+			"pkt %u/%u, %u/%u\n",
+			snic, ppmax, ddp->idx_bits, ddp->idx_mask,
+			ddp->rsvd_tag_mask, ddp->max_txsz,
+			snic->lldi.iscsi_iolen,
+			ddp->max_rxsz, snic->lldi.iscsi_iolen);
+
+	return;
+}
+
+void cxgb4i_ddp_init(struct cxgb4i_snic *snic)
+{
+	if (page_idx == DDP_PGIDX_MAX) {
+		page_idx = cxgb4i_ddp_find_page_index(PAGE_SIZE);
+
+		if (page_idx == DDP_PGIDX_MAX) {
+			cxgbi_log_info("system PAGE_SIZE %lu, update hw\n",
+					PAGE_SIZE);
+
+			if (cxgb4i_ddp_adjust_page_table()) {
+				cxgbi_log_info("PAGE_SIZE %lu, ddp disabled\n",
+						PAGE_SIZE);
+				return;
+			}
+			page_idx = cxgb4i_ddp_find_page_index(PAGE_SIZE);
+		}
+		cxgbi_log_info("system PAGE_SIZE %lu, ddp idx %u\n",
+				PAGE_SIZE, page_idx);
+	}
+
+	__cxgb4i_ddp_init(snic);
+	snic->cdev.ddp_make_gl = cxgb4i_ddp_make_gl;
+	snic->cdev.ddp_release_gl = cxgb4i_ddp_release_gl;
+	snic->cdev.ddp_tag_reserve = cxgb4i_ddp_tag_reserve;
+	snic->cdev.ddp_tag_release = cxgb4i_ddp_tag_release;
+}
+
+void cxgb4i_ddp_cleanup(struct cxgb4i_snic *snic)
+{
+	struct cxgb4i_ddp_info *ddp = snic->ddp;
+
+	cxgbi_log_info("snic 0x%p, release ddp 0x%p\n", snic, ddp);
+	if (ddp)
+		kref_put(&ddp->refcnt, __cxgb4i_ddp_cleanup);
+}
+
diff --git a/drivers/scsi/cxgb4i/cxgb4i_ddp.h b/drivers/scsi/cxgb4i/cxgb4i_ddp.h
new file mode 100644
index 0000000..f51cb37
--- /dev/null
+++ b/drivers/scsi/cxgb4i/cxgb4i_ddp.h
@@ -0,0 +1,118 @@
+/*
+ * cxgb4i_ddp.h: Chelsio T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Karen Xie (kxie-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ * Written by: Rakesh Ranjan (rranjan-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ */
+
+#ifndef	__CXGB4I_DDP_H__
+#define	__CXGB4I_DDP_H__
+
+#include <linux/vmalloc.h>
+
+#include "libcxgbi.h"
+
+struct cxgbi_sock;
+
+struct cxgb4i_ddp_info {
+	struct list_head list;
+	struct kref refcnt;
+	struct cxgb4i_snic *snic;
+	struct pci_dev *pdev;
+	unsigned int max_txsz;
+	unsigned int max_rxsz;
+	unsigned int llimit;
+	unsigned int ulimit;
+	unsigned int nppods;
+	unsigned int idx_last;
+	unsigned char idx_bits;
+	unsigned char filler[3];
+	unsigned int idx_mask;
+	unsigned int rsvd_tag_mask;
+	spinlock_t map_lock;
+	struct cxgbi_gather_list **gl_map;
+};
+
+struct pagepod_hdr {
+	unsigned int vld_tid;
+	unsigned int pgsz_tag_clr;
+	unsigned int max_offset;
+	unsigned int page_offset;
+	unsigned long long rsvd;
+};
+
+struct pagepod {
+	struct pagepod_hdr hdr;
+	unsigned long long addr[PPOD_PAGES_MAX + 1];
+};
+
+struct cpl_rx_data_ddp {
+	union opcode_tid ot;
+	__be16 urg;
+	__be16 len;
+	__be32 seq;
+	union {
+		__be32 nxt_seq;
+		__be32 ddp_report;
+	};
+	__be32 ulp_crc;
+	__be32 ddpvld;
+};
+
+#define PPOD_SIZE               sizeof(struct pagepod)  /*  64 */
+#define PPOD_SIZE_SHIFT         6
+
+#define ULPMEM_DSGL_MAX_NPPODS	16	/*  1024/PPOD_SIZE */
+#define ULPMEM_IDATA_MAX_NPPODS	4	/*  256/PPOD_SIZE */
+#define PCIE_MEMWIN_MAX_NPPODS	16	/*  1024/PPOD_SIZE */
+
+#define PPOD_COLOR_SHIFT	0
+#define PPOD_COLOR_MASK		0x3F
+#define PPOD_COLOR_SIZE         6
+#define PPOD_COLOR(x)		((x) << PPOD_COLOR_SHIFT)
+
+#define PPOD_TAG_SHIFT	6
+#define PPOD_TAG_MASK	0xFFFFFF
+#define PPOD_TAG(x)	((x) << PPOD_TAG_SHIFT)
+
+#define PPOD_PGSZ_SHIFT	30
+#define PPOD_PGSZ_MASK	0x3
+#define PPOD_PGSZ(x)	((x) << PPOD_PGSZ_SHIFT)
+
+#define PPOD_TID_SHIFT	32
+#define PPOD_TID_MASK	0xFFFFFF
+#define PPOD_TID(x)	((__u64)(x) << PPOD_TID_SHIFT)
+
+#define PPOD_VALID_SHIFT	56
+#define PPOD_VALID(x)	((__u64)(x) << PPOD_VALID_SHIFT)
+#define PPOD_VALID_FLAG	PPOD_VALID(1ULL)
+
+#define PPOD_LEN_SHIFT	32
+#define PPOD_LEN_MASK	0xFFFFFFFF
+#define PPOD_LEN(x)	((__u64)(x) << PPOD_LEN_SHIFT)
+
+#define PPOD_OFST_SHIFT	0
+#define PPOD_OFST_MASK	0xFFFFFFFF
+#define PPOD_OFST(x)	((x) << PPOD_OFST_SHIFT)
+
+#define PPOD_IDX_SHIFT          PPOD_COLOR_SIZE
+#define PPOD_IDX_MAX_SIZE       24
+
+int cxgb4i_ddp_setup_conn_host_pagesize(struct cxgbi_sock*, unsigned int,
+					int);
+int cxgb4i_ddp_setup_conn_digest(struct cxgbi_sock *, unsigned int,
+				int, int, int);
+int cxgb4i_snic_ddp_info(struct cxgb4i_snic *, struct cxgbi_tag_format *,
+			unsigned int *, unsigned int *);
+
+void cxgb4i_ddp_init(struct cxgb4i_snic *);
+void cxgb4i_ddp_cleanup(struct cxgb4i_snic *);
+
+#endif	/* __CXGB4I_DDP_H__ */
+
diff --git a/drivers/scsi/cxgb4i/cxgb4i_offload.c b/drivers/scsi/cxgb4i/cxgb4i_offload.c
new file mode 100644
index 0000000..87edb14
--- /dev/null
+++ b/drivers/scsi/cxgb4i/cxgb4i_offload.c
@@ -0,0 +1,1846 @@
+/*
+ * cxgb4i_offload.c: Chelsio T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Karen Xie (kxie-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ * Written by: Rakesh Ranjan (rranjan-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ */
+
+#include <linux/if_vlan.h>
+#include <net/dst.h>
+#include <net/route.h>
+#include <net/tcp.h>
+
+#include "libcxgbi.h"
+#include "cxgb4i.h"
+#include "cxgb4i_offload.h"
+
+static int cxgb4i_rcv_win = 256 * 1024;
+module_param(cxgb4i_rcv_win, int, 0644);
+MODULE_PARM_DESC(cxgb4i_rcv_win, "TCP reveive window in bytes");
+
+static int cxgb4i_snd_win = 128 * 1024;
+module_param(cxgb4i_snd_win, int, 0644);
+MODULE_PARM_DESC(cxgb4i_snd_win, "TCP send window in bytes");
+
+static int cxgb4i_rx_credit_thres = 10 * 1024;
+module_param(cxgb4i_rx_credit_thres, int, 0644);
+MODULE_PARM_DESC(cxgb4i_rx_credit_thres,
+		"RX credits return threshold in bytes (default=10KB)");
+
+static unsigned int cxgb4i_max_connect = (8 * 1024);
+module_param(cxgb4i_max_connect, uint, 0644);
+MODULE_PARM_DESC(cxgb4i_max_connect, "Maximum number of connections");
+
+static unsigned short cxgb4i_sport_base = 20000;
+module_param(cxgb4i_sport_base, ushort, 0644);
+MODULE_PARM_DESC(cxgb4i_sport_base, "Starting port number (default 20000)");
+
+#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+#define RCV_BUFSIZ_MASK	0x3FFU
+
+static void cxgb4i_sock_release_offload_resources(struct cxgbi_sock *);
+static void cxgbi_sock_conn_closing(struct cxgbi_sock *);
+static int cxgb4i_sock_push_tx_frames(struct cxgbi_sock *, int);
+
+
+#define MAX_IMM_TX_PKT_LEN 128
+
+/*
+ * is_ofld_imm - check whether a packet can be sent as immediate data
+ * @skb: the packet
+ *
+ * Returns true if a packet can be sent as an offload WR with immediate
+ * data.  We currently use the same limit as for Ethernet packets.
+ */
+static inline int is_ofld_imm(const struct sk_buff *skb)
+{
+	return skb->len <= (MAX_IMM_TX_PKT_LEN -
+			sizeof(struct fw_ofld_tx_data_wr));
+}
+
+static void cxgbi_conn_pdu_ready(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb;
+	unsigned int read = 0;
+	struct iscsi_conn *conn = csk->user_data;
+	int err = 0;
+
+	cxgbi_rx_debug("csk 0x%p.\n", csk);
+
+	read_lock(&csk->callback_lock);
+	if (unlikely(!conn || conn->suspend_rx)) {
+		cxgbi_rx_debug("conn 0x%p, id %d, suspend_rx %lu!\n",
+				conn, conn ? conn->id : 0xFF,
+				conn ? conn->suspend_rx : 0xFF);
+		read_unlock(&csk->callback_lock);
+		return;
+	}
+	skb = skb_peek(&csk->receive_queue);
+	while (!err && skb) {
+		__skb_unlink(skb, &csk->receive_queue);
+		read += cxgb4i_skb_rx_pdulen(skb);
+		cxgbi_rx_debug("conn 0x%p, csk 0x%p, rx skb 0x%p, pdulen %u\n",
+				conn, csk, skb, cxgb4i_skb_rx_pdulen(skb));
+		if (cxgb4i_skb_flags(skb) & CXGB4I_SKCB_FLAG_HDR_RCVD)
+			err = cxgbi_conn_read_bhs_pdu_skb(conn, skb);
+		else if (cxgb4i_skb_flags(skb) == CXGB4I_SKCB_FLAG_DATA_RCVD)
+			err = cxgbi_conn_read_data_pdu_skb(conn, skb);
+		__kfree_skb(skb);
+		skb = skb_peek(&csk->receive_queue);
+	}
+	read_unlock(&csk->callback_lock);
+	csk->copied_seq += read;
+	cxgb4i_sock_rx_credits(csk, read);
+	conn->rxdata_octets += read;
+
+	if (err) {
+		cxgbi_log_info("conn 0x%p rx failed err %d.\n", conn, err);
+		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+	}
+}
+
+static void cxgb4i_sock_closed(struct cxgbi_sock *csk)
+{
+	cxgbi_conn_debug("csk 0x%p, state %u, flags 0x%lx\n",
+			csk, csk->state, csk->flags);
+
+	cxgbi_sock_put_port(csk);
+	cxgb4i_sock_release_offload_resources(csk);
+	cxgbi_sock_set_state(csk, CXGBI_CSK_ST_CLOSED);
+	cxgbi_sock_conn_closing(csk);
+}
+
+static unsigned int cxgb4i_find_best_mtu(struct cxgb4i_snic *snic,
+						unsigned short mtu)
+{
+	int i = 0;
+
+	while (i < NMTUS - 1 && snic->lldi.mtus[i + 1] <= mtu)
+		++i;
+
+	return i;
+}
+
+static unsigned int cxgb4i_select_mss(struct cxgbi_sock *csk,
+						unsigned int pmtu)
+{
+	unsigned int idx;
+	struct dst_entry *dst = csk->dst;
+	u16 advmss = dst_metric(dst, RTAX_ADVMSS);
+
+	if (advmss > pmtu - 40)
+		advmss = pmtu - 40;
+	if (advmss < cxgb4i_get_snic(csk->cdev)->lldi.mtus[0] - 40)
+		advmss = cxgb4i_get_snic(csk->cdev)->lldi.mtus[0] - 40;
+	idx = cxgb4i_find_best_mtu(cxgb4i_get_snic(csk->cdev), advmss + 40);
+
+	return idx;
+}
+
+static inline int cxgb4i_sock_compute_wscale(int win)
+{
+	int wscale = 0;
+
+	while (wscale < 14 && (65535 << wscale) < win)
+		wscale++;
+
+	return wscale;
+}
+
+static void cxgb4i_sock_make_act_open_req(struct cxgbi_sock *csk,
+					   struct sk_buff *skb,
+					   unsigned int qid_atid,
+					   struct l2t_entry *e)
+{
+	struct cpl_act_open_req *req;
+	unsigned long long opt0;
+	unsigned int opt2;
+	int wscale;
+
+	cxgbi_conn_debug("csk 0x%p, atid 0x%x\n", csk, qid_atid);
+
+	wscale = cxgb4i_sock_compute_wscale(csk->mss_idx);
+
+	opt0 = KEEP_ALIVE(1) |
+		WND_SCALE(wscale) |
+		MSS_IDX(csk->mss_idx) |
+		L2T_IDX(((struct l2t_entry *)csk->l2t)->idx) |
+		TX_CHAN(csk->tx_chan) |
+		SMAC_SEL(csk->smac_idx) |
+		RCV_BUFSIZ(cxgb4i_rcv_win >> 10);
+
+	opt2 = RX_CHANNEL(0) |
+		RSS_QUEUE_VALID |
+		RSS_QUEUE(csk->rss_qid);
+
+	skb->queue_mapping = CPL_PRIORITY_SETUP;
+	req = (struct cpl_act_open_req *)__skb_put(skb, sizeof(*req));
+	INIT_TP_WR(req, 0);
+	OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ,
+					qid_atid));
+	req->local_port = csk->saddr.sin_port;
+	req->peer_port = csk->daddr.sin_port;
+	req->local_ip = csk->saddr.sin_addr.s_addr;
+	req->peer_ip = csk->daddr.sin_addr.s_addr;
+	req->opt0 = cpu_to_be64(opt0);
+	req->params = 0;
+	req->opt2 = cpu_to_be32(opt2);
+}
+
+static void cxgb4i_fail_act_open(struct cxgbi_sock *csk, int errno)
+{
+	cxgbi_conn_debug("csk 0%p, state %u, flag 0x%lx\n", csk,
+			csk->state, csk->flags);
+	csk->err = errno;
+	cxgb4i_sock_closed(csk);
+}
+
+static void cxgb4i_act_open_req_arp_failure(void *handle, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk = (struct cxgbi_sock *)skb->sk;
+
+	cxgbi_sock_hold(csk);
+	spin_lock_bh(&csk->lock);
+	if (csk->state == CXGBI_CSK_ST_CONNECTING)
+		cxgb4i_fail_act_open(csk, -EHOSTUNREACH);
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+	__kfree_skb(skb);
+}
+
+static void cxgb4i_sock_skb_entail(struct cxgbi_sock *csk,
+					struct sk_buff *skb,
+					int flags)
+{
+	cxgb4i_skb_tcp_seq(skb) = csk->write_seq;
+	cxgb4i_skb_flags(skb) = flags;
+	__skb_queue_tail(&csk->write_queue, skb);
+}
+
+static void cxgb4i_sock_send_close_req(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb = csk->cpl_close;
+	struct cpl_close_con_req *req = (struct cpl_close_con_req *)skb->head;
+	unsigned int tid = csk->hwtid;
+
+	csk->cpl_close = NULL;
+
+	skb->queue_mapping = CPL_PRIORITY_DATA;
+	INIT_TP_WR(req, tid);
+
+	OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_CLOSE_CON_REQ, tid));
+	req->rsvd = 0;
+
+	cxgb4i_sock_skb_entail(csk, skb, CXGB4I_SKCB_FLAG_NO_APPEND);
+	if (csk->state != CXGBI_CSK_ST_CONNECTING)
+		cxgb4i_sock_push_tx_frames(csk, 1);
+}
+
+static void cxgb4i_sock_abort_arp_failure(void *handle, struct sk_buff *skb)
+{
+	struct cpl_abort_req *req = cplhdr(skb);
+	struct cxgbi_sock *csk = (struct cxgbi_sock *)handle;
+	struct cxgb4i_snic *snic = cxgb4i_get_snic(csk->cdev);
+
+	req->cmd = CPL_ABORT_NO_RST;
+	cxgb4_ofld_send(snic->lldi.ports[csk->port_id], skb);
+}
+
+static inline void cxgb4i_sock_purge_write_queue(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb;
+
+	while ((skb = __skb_dequeue(&csk->write_queue)))
+		__kfree_skb(skb);
+}
+
+static void cxgb4i_sock_send_abort_req(struct cxgbi_sock *csk)
+{
+	struct cpl_abort_req *req;
+	struct sk_buff *skb = csk->cpl_abort_req;
+	struct cxgb4i_snic *snic = cxgb4i_get_snic(csk->cdev);
+
+	if (unlikely(csk->state == CXGBI_CSK_ST_ABORTING) ||
+			!skb || !csk->cdev)
+		return;
+
+	cxgbi_sock_set_state(csk, CXGBI_CSK_ST_ABORTING);
+
+	cxgbi_conn_debug("csk 0x%p, flag ABORT_RPL + ABORT_SHUT\n", csk);
+
+	cxgbi_sock_set_state(csk, CXGBI_CSK_FL_ABORT_RPL_PENDING);
+
+	cxgb4i_sock_purge_write_queue(csk);
+
+	csk->cpl_abort_req = NULL;
+	req = (struct cpl_abort_req *)skb->head;
+
+	skb->queue_mapping = CPL_PRIORITY_DATA;
+	t4_set_arp_err_handler(skb, csk, cxgb4i_sock_abort_arp_failure);
+	INIT_TP_WR(req, csk->hwtid);
+	OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_REQ, csk->hwtid));
+	req->rsvd0 = htonl(csk->snd_nxt);
+	req->rsvd1 = !cxgbi_sock_flag(csk, CXGBI_CSK_FL_TX_DATA_SENT);
+	req->cmd = CPL_ABORT_SEND_RST;
+
+	cxgb4_l2t_send(snic->lldi.ports[csk->port_id], skb, csk->l2t);
+}
+
+static void cxgb4i_sock_send_abort_rpl(struct cxgbi_sock *csk, int rst_status)
+{
+	struct sk_buff *skb = csk->cpl_abort_rpl;
+	struct cpl_abort_rpl *rpl = (struct cpl_abort_rpl *)skb->head;
+	struct cxgb4i_snic *snic = cxgb4i_get_snic(csk->cdev);
+
+	csk->cpl_abort_rpl = NULL;
+
+	skb->queue_mapping = CPL_PRIORITY_DATA;
+	INIT_TP_WR(rpl, csk->hwtid);
+	OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_RPL, csk->hwtid));
+	rpl->cmd = rst_status;
+
+	cxgb4_ofld_send(snic->lldi.ports[csk->port_id], skb);
+}
+
+static u32 cxgb4i_csk_send_rx_credits(struct cxgbi_sock *csk, u32 credits)
+{
+	struct sk_buff *skb;
+	struct cpl_rx_data_ack *req;
+	int wrlen = roundup(sizeof(*req), 16);
+	struct cxgb4i_snic *snic = cxgb4i_get_snic(csk->cdev);
+
+	skb = alloc_skb(wrlen, GFP_ATOMIC);
+	if (!skb)
+		return 0;
+
+	req = (struct cpl_rx_data_ack *)__skb_put(skb, wrlen);
+	memset(req, 0, wrlen);
+	skb->queue_mapping = CPL_PRIORITY_ACK;
+	INIT_TP_WR(req, csk->hwtid);
+	OPCODE_TID(req) =
+		cpu_to_be32(MK_OPCODE_TID(CPL_RX_DATA_ACK, csk->hwtid));
+	req->credit_dack = cpu_to_be32(RX_CREDITS(credits) | RX_FORCE_ACK(1));
+	cxgb4_ofld_send(snic->lldi.ports[csk->port_id], skb);
+	return credits;
+}
+
+
+#define SKB_WR_LIST_SIZE	(MAX_SKB_FRAGS + 2)
+
+static const unsigned int cxgb4i_ulp_extra_len[] = { 0, 4, 4, 8 };
+static inline unsigned int ulp_extra_len(const struct sk_buff *skb)
+{
+	return cxgb4i_ulp_extra_len[cxgb4i_skb_ulp_mode(skb) & 3];
+}
+
+static inline void cxgb4i_sock_reset_wr_list(struct cxgbi_sock *csk)
+{
+	csk->wr_pending_head = csk->wr_pending_tail = NULL;
+}
+
+static inline void cxgb4i_sock_enqueue_wr(struct cxgbi_sock *csk,
+						struct sk_buff *skb)
+{
+	cxgb4i_skb_tx_wr_next(skb) = NULL;
+
+	/*
+	 * We want to take an extra reference since both us and the driver
+	 * need to free the packet before it's really freed. We know there's
+	 * just one user currently so we use atomic_set rather than skb_get
+	 * to avoid the atomic op.
+	 */
+	atomic_set(&skb->users, 2);
+
+	if (!csk->wr_pending_head)
+		csk->wr_pending_head = skb;
+
+	else
+		cxgb4i_skb_tx_wr_next(csk->wr_pending_tail) = skb;
+
+	csk->wr_pending_tail = skb;
+}
+
+static int cxgb4i_sock_count_pending_wrs(const struct cxgbi_sock *csk)
+{
+	int n = 0;
+	const struct sk_buff *skb = csk->wr_pending_head;
+
+	while (skb) {
+		n += skb->csum;
+		skb = cxgb4i_skb_tx_wr_next(skb);
+	}
+	return n;
+}
+
+static inline struct sk_buff *cxgb4i_sock_peek_wr(const struct cxgbi_sock *csk)
+{
+	return csk->wr_pending_head;
+}
+
+static inline void cxgb4i_sock_free_wr_skb(struct sk_buff *skb)
+{
+	kfree_skb(skb);
+}
+
+static inline struct sk_buff *cxgb4i_sock_dequeue_wr(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb = csk->wr_pending_head;
+
+	if (likely(skb)) {
+		csk->wr_pending_head = cxgb4i_skb_tx_wr_next(skb);
+		cxgb4i_skb_tx_wr_next(skb) = NULL;
+	}
+	return skb;
+}
+
+static void cxgb4i_sock_purge_wr_queue(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb;
+
+	while ((skb = cxgb4i_sock_dequeue_wr(csk)) != NULL)
+		cxgb4i_sock_free_wr_skb(skb);
+}
+
+/*
+ * sgl_len - calculates the size of an SGL of the given capacity
+ * @n: the number of SGL entries
+ * Calculates the number of flits needed for a scatter/gather list that
+ * can hold the given number of entries.
+ */
+static inline unsigned int sgl_len(unsigned int n)
+{
+	n--;
+	return (3 * n) / 2 + (n & 1) + 2;
+}
+
+/*
+ * calc_tx_flits_ofld - calculate # of flits for an offload packet
+ * @skb: the packet
+ *
+ * Returns the number of flits needed for the given offload packet.
+ * These packets are already fully constructed and no additional headers
+ * will be added.
+ */
+static inline unsigned int calc_tx_flits_ofld(const struct sk_buff *skb)
+{
+	unsigned int flits, cnt;
+
+	if (is_ofld_imm(skb))
+		return DIV_ROUND_UP(skb->len, 8);
+
+	flits = skb_transport_offset(skb) / 8;
+	cnt = skb_shinfo(skb)->nr_frags;
+	if (skb->tail != skb->transport_header)
+		cnt++;
+	return flits + sgl_len(cnt);
+}
+
+static inline void cxgb4i_sock_send_tx_flowc_wr(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb;
+	struct fw_flowc_wr *flowc;
+	int flowclen, i;
+	struct cxgb4i_snic *snic = cxgb4i_get_snic(csk->cdev);
+
+	flowclen = 80;
+	skb = alloc_skb(flowclen, GFP_ATOMIC);
+	flowc = (struct fw_flowc_wr *)__skb_put(skb, flowclen);
+
+	flowc->op_to_nparams =
+		htonl(FW_WR_OP(FW_FLOWC_WR) | FW_FLOWC_WR_NPARAMS(8));
+	flowc->flowid_len16 =
+		htonl(FW_WR_LEN16(DIV_ROUND_UP(72, 16)) |
+				FW_WR_FLOWID(csk->hwtid));
+
+	flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN;
+	flowc->mnemval[0].val = htonl(0);
+	flowc->mnemval[1].mnemonic = FW_FLOWC_MNEM_CH;
+	flowc->mnemval[1].val = htonl(csk->tx_chan);
+	flowc->mnemval[2].mnemonic = FW_FLOWC_MNEM_PORT;
+	flowc->mnemval[2].val = htonl(csk->tx_chan);
+	flowc->mnemval[3].mnemonic = FW_FLOWC_MNEM_IQID;
+	flowc->mnemval[3].val = htonl(csk->rss_qid);
+	flowc->mnemval[4].mnemonic = FW_FLOWC_MNEM_SNDNXT;
+	flowc->mnemval[4].val = htonl(csk->snd_nxt);
+	flowc->mnemval[5].mnemonic = FW_FLOWC_MNEM_RCVNXT;
+	flowc->mnemval[5].val = htonl(csk->rcv_nxt);
+	flowc->mnemval[6].mnemonic = FW_FLOWC_MNEM_SNDBUF;
+	flowc->mnemval[6].val = htonl(cxgb4i_snd_win);
+	flowc->mnemval[7].mnemonic = FW_FLOWC_MNEM_MSS;
+	flowc->mnemval[7].val = htonl(csk->mss_idx);
+	flowc->mnemval[8].mnemonic = 0;
+	flowc->mnemval[8].val = 0;
+	for (i = 0; i < 9; i++) {
+		flowc->mnemval[i].r4[0] = 0;
+		flowc->mnemval[i].r4[1] = 0;
+		flowc->mnemval[i].r4[2] = 0;
+	}
+
+	skb->queue_mapping = CPL_PRIORITY_DATA;
+
+	cxgb4_ofld_send(snic->lldi.ports[csk->port_id], skb);
+}
+
+static inline void cxgb4i_sock_make_tx_data_wr(struct cxgbi_sock *csk,
+						struct sk_buff *skb, int dlen,
+						int len, u32 credits,
+						int req_completion)
+{
+	struct fw_ofld_tx_data_wr *req;
+	unsigned int wr_ulp_mode;
+
+	if (is_ofld_imm(skb)) {
+			req = (struct fw_ofld_tx_data_wr *)
+				__skb_push(skb, sizeof(*req));
+			req->op_to_immdlen =
+				cpu_to_be32(FW_WR_OP(FW_OFLD_TX_DATA_WR) |
+					FW_WR_COMPL(req_completion) |
+					FW_WR_IMMDLEN(dlen));
+			req->flowid_len16 =
+				cpu_to_be32(FW_WR_FLOWID(csk->hwtid) |
+						FW_WR_LEN16(credits));
+	} else {
+		req = (struct fw_ofld_tx_data_wr *)
+			__skb_push(skb, sizeof(*req));
+		req->op_to_immdlen =
+			cpu_to_be32(FW_WR_OP(FW_OFLD_TX_DATA_WR) |
+					FW_WR_COMPL(req_completion) |
+					FW_WR_IMMDLEN(0));
+		req->flowid_len16 =
+			cpu_to_be32(FW_WR_FLOWID(csk->hwtid) |
+					FW_WR_LEN16(credits));
+	}
+
+	wr_ulp_mode =
+		FW_OFLD_TX_DATA_WR_ULPMODE(cxgb4i_skb_ulp_mode(skb) >> 4) |
+		FW_OFLD_TX_DATA_WR_ULPSUBMODE(cxgb4i_skb_ulp_mode(skb) & 3);
+
+	req->tunnel_to_proxy = cpu_to_be32(wr_ulp_mode) |
+		FW_OFLD_TX_DATA_WR_SHOVE(skb_peek(&csk->write_queue) ? 0 : 1);
+
+	req->plen = cpu_to_be32(len);
+
+	if (!cxgbi_sock_flag(csk, CXGBI_CSK_FL_TX_DATA_SENT))
+		cxgbi_sock_set_flag(csk, CXGBI_CSK_FL_TX_DATA_SENT);
+}
+
+static void cxgb4i_sock_arp_failure_discard(void *handle, struct sk_buff *skb)
+{
+	kfree_skb(skb);
+}
+
+static int cxgb4i_sock_push_tx_frames(struct cxgbi_sock *csk,
+						int req_completion)
+{
+	int total_size = 0;
+	struct sk_buff *skb;
+	struct cxgb4i_snic *snic;
+
+	if (unlikely(csk->state == CXGBI_CSK_ST_CONNECTING ||
+				csk->state == CXGBI_CSK_ST_CLOSE_WAIT_1 ||
+				csk->state >= CXGBI_CSK_ST_ABORTING)) {
+		cxgbi_tx_debug("csk 0x%p, in closing state %u.\n",
+				csk, csk->state);
+		return 0;
+	}
+
+	snic = cxgb4i_get_snic(csk->cdev);
+
+	while (csk->wr_cred
+			&& (skb = skb_peek(&csk->write_queue)) != NULL) {
+		int dlen;
+		int len;
+		unsigned int credits_needed;
+
+		dlen = len = skb->len;
+		skb_reset_transport_header(skb);
+
+		if (is_ofld_imm(skb))
+			credits_needed = DIV_ROUND_UP(dlen +
+					sizeof(struct fw_ofld_tx_data_wr), 16);
+		else
+			credits_needed = DIV_ROUND_UP(8 *
+					calc_tx_flits_ofld(skb)+
+					sizeof(struct fw_ofld_tx_data_wr), 16);
+
+		if (csk->wr_cred < credits_needed) {
+			cxgbi_tx_debug("csk 0x%p, skb len %u/%u, "
+					"wr %d < %u.\n",
+					csk, skb->len, skb->data_len,
+					credits_needed, csk->wr_cred);
+			break;
+		}
+
+		__skb_unlink(skb, &csk->write_queue);
+		skb->queue_mapping = CPL_PRIORITY_DATA;
+		skb->csum = credits_needed; /* remember this until the WR_ACK */
+		csk->wr_cred -= credits_needed;
+		csk->wr_una_cred += credits_needed;
+		cxgb4i_sock_enqueue_wr(csk, skb);
+
+		cxgbi_tx_debug("csk 0x%p, enqueue, skb len %u/%u, "
+				"wr %d, left %u, unack %u.\n",
+				csk, skb->len, skb->data_len,
+				credits_needed, csk->wr_cred,
+				csk->wr_una_cred);
+
+
+		if (likely(cxgb4i_skb_flags(skb) &
+					CXGB4I_SKCB_FLAG_NEED_HDR)) {
+			len += ulp_extra_len(skb);
+			if (!cxgbi_sock_flag(csk,
+						CXGBI_CSK_FL_TX_DATA_SENT)) {
+				cxgb4i_sock_send_tx_flowc_wr(csk);
+				skb->csum += 5;
+				csk->wr_cred -= 5;
+				csk->wr_una_cred += 5;
+			}
+
+			if ((req_completion &&
+				csk->wr_una_cred == credits_needed) ||
+				(cxgb4i_skb_flags(skb) &
+				  CXGB4I_SKCB_FLAG_COMPL) ||
+				csk->wr_una_cred >= csk->wr_max_cred / 2) {
+				req_completion = 1;
+				csk->wr_una_cred = 0;
+			}
+			cxgb4i_sock_make_tx_data_wr(csk, skb, dlen, len,
+							credits_needed,
+							req_completion);
+			csk->snd_nxt += len;
+
+			if (req_completion)
+				cxgb4i_skb_flags(skb) &=
+					~CXGB4I_SKCB_FLAG_NEED_HDR;
+		}
+
+		total_size += skb->truesize;
+		t4_set_arp_err_handler(skb, csk,
+					cxgb4i_sock_arp_failure_discard);
+		cxgb4_l2t_send(snic->lldi.ports[csk->port_id], skb, csk->l2t);
+	}
+	return total_size;
+}
+
+static inline void cxgb4i_sock_free_atid(struct cxgbi_sock *csk)
+{
+	cxgb4_free_atid(cxgb4i_get_snic(csk->cdev)->lldi.tids, csk->atid);
+	cxgbi_sock_put(csk);
+}
+
+static void cxgb4i_sock_established(struct cxgbi_sock *csk, u32 snd_isn,
+					unsigned int opt)
+{
+	cxgbi_conn_debug("csk 0x%p, state %u.\n", csk, csk->state);
+
+	csk->write_seq = csk->snd_nxt = csk->snd_una = snd_isn;
+
+	/*
+	 * Causes the first RX_DATA_ACK to supply any Rx credits we couldn't
+	 * pass through opt0.
+	 */
+	if (cxgb4i_rcv_win > (RCV_BUFSIZ_MASK << 10))
+		csk->rcv_wup -= cxgb4i_rcv_win - (RCV_BUFSIZ_MASK << 10);
+
+	dst_confirm(csk->dst);
+
+	smp_mb();
+
+	cxgbi_sock_set_state(csk, CXGBI_CSK_ST_ESTABLISHED);
+}
+
+static int cxgb4i_cpl_act_establish(struct cxgb4i_snic *snic,
+						struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_act_establish *req = cplhdr(skb);
+	unsigned int hwtid = GET_TID(req);
+	unsigned int atid = GET_TID_TID(ntohl(req->tos_atid));
+	struct tid_info *t = snic->lldi.tids;
+	u32 rcv_isn = be32_to_cpu(req->rcv_isn);
+
+	csk = lookup_atid(t, atid);
+
+	if (unlikely(!csk)) {
+		cxgbi_log_error("can't find connection for tid %u\n", hwtid);
+		return CPL_RET_UNKNOWN_TID;
+	}
+
+	cxgbi_conn_debug("csk 0x%p, state %u, flag 0x%lx\n",
+				csk, csk->state, csk->flags);
+	csk->hwtid = hwtid;
+	cxgbi_sock_hold(csk);
+	cxgb4_insert_tid(snic->lldi.tids, csk, hwtid);
+	cxgb4_free_atid(snic->lldi.tids, atid);
+
+	spin_lock_bh(&csk->lock);
+
+	if (unlikely(csk->state != CXGBI_CSK_ST_CONNECTING))
+		cxgbi_log_error("TID %u expected SYN_SENT, got EST., s %u\n",
+				csk->hwtid, csk->state);
+
+	csk->copied_seq = csk->rcv_wup = csk->rcv_nxt = rcv_isn;
+	cxgb4i_sock_established(csk, ntohl(req->snd_isn), ntohs(req->tcp_opt));
+
+	__kfree_skb(skb);
+
+	if (unlikely(cxgbi_sock_flag(csk, CXGBI_CSK_FL_ACTIVE_CLOSE_NEEDED)))
+		cxgb4i_sock_send_abort_req(csk);
+	else {
+		if (skb_queue_len(&csk->write_queue))
+			cxgb4i_sock_push_tx_frames(csk, 1);
+
+		cxgbi_conn_tx_open(csk);
+	}
+
+	spin_unlock_bh(&csk->lock);
+
+	return 0;
+}
+
+static int act_open_rpl_status_to_errno(int status)
+{
+	switch (status) {
+	case CPL_ERR_CONN_RESET:
+		return -ECONNREFUSED;
+	case CPL_ERR_ARP_MISS:
+		return -EHOSTUNREACH;
+	case CPL_ERR_CONN_TIMEDOUT:
+		return -ETIMEDOUT;
+	case CPL_ERR_TCAM_FULL:
+		return -ENOMEM;
+	case CPL_ERR_CONN_EXIST:
+		cxgbi_log_error("ACTIVE_OPEN_RPL: 4-tuple in use\n");
+		return -EADDRINUSE;
+	default:
+		return -EIO;
+	}
+}
+
+/*
+ * Return whether a failed active open has allocated a TID
+ */
+static inline int act_open_has_tid(int status)
+{
+	return status != CPL_ERR_TCAM_FULL && status != CPL_ERR_CONN_EXIST &&
+		status != CPL_ERR_ARP_MISS;
+}
+
+static void cxgb4i_sock_act_open_retry_timer(unsigned long data)
+{
+	struct sk_buff *skb;
+	struct cxgbi_sock *csk = (struct cxgbi_sock *)data;
+	struct cxgb4i_snic *snic = cxgb4i_get_snic(csk->cdev);
+
+	cxgbi_conn_debug("csk 0x%p, state %u.\n", csk, csk->state);
+
+	spin_lock_bh(&csk->lock);
+	skb = alloc_skb(sizeof(struct cpl_act_open_req), GFP_ATOMIC);
+	if (!skb)
+		cxgb4i_fail_act_open(csk, -ENOMEM);
+	else {
+		unsigned int qid_atid  = csk->rss_qid << 14;
+		qid_atid |= (unsigned int)csk->atid;
+		skb->sk = (struct sock *)csk;
+		t4_set_arp_err_handler(skb, csk,
+					cxgb4i_act_open_req_arp_failure);
+		cxgb4i_sock_make_act_open_req(csk, skb, qid_atid, csk->l2t);
+		cxgb4_l2t_send(snic->lldi.ports[csk->port_id], skb, csk->l2t);
+	}
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+}
+
+static int cxgb4i_cpl_act_open_rpl(struct cxgb4i_snic *snic,
+						struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_act_open_rpl *rpl = cplhdr(skb);
+	unsigned int atid =
+		GET_TID_TID(GET_AOPEN_ATID(be32_to_cpu(rpl->atid_status)));
+	struct tid_info *t = snic->lldi.tids;
+	unsigned int status = GET_AOPEN_STATUS(be32_to_cpu(rpl->atid_status));
+
+	csk = lookup_atid(t, atid);
+
+	if (unlikely(!csk)) {
+		cxgbi_log_error("can't find connection for tid %u\n", atid);
+		return CPL_RET_UNKNOWN_TID;
+	}
+
+	cxgbi_sock_hold(csk);
+	spin_lock_bh(&csk->lock);
+
+	cxgbi_conn_debug("rcv, status 0x%x, csk 0x%p, csk->state %u, "
+			"csk->flag 0x%lx, csk->atid %u.\n",
+			status, csk, csk->state, csk->flags, csk->hwtid);
+
+	if (status & act_open_has_tid(status))
+		cxgb4_remove_tid(snic->lldi.tids, csk->port_id, GET_TID(rpl));
+
+	if (status == CPL_ERR_CONN_EXIST &&
+			csk->retry_timer.function !=
+			cxgb4i_sock_act_open_retry_timer) {
+		csk->retry_timer.function = cxgb4i_sock_act_open_retry_timer;
+		if (!mod_timer(&csk->retry_timer, jiffies + HZ / 2))
+			cxgbi_sock_hold(csk);
+	} else
+
+		cxgb4i_fail_act_open(csk, act_open_rpl_status_to_errno(status));
+
+	__kfree_skb(skb);
+
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+
+	return 0;
+}
+
+static int cxgb4i_cpl_peer_close(struct cxgb4i_snic *snic, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_peer_close *req = cplhdr(skb);
+	unsigned int hwtid = GET_TID(req);
+	struct tid_info *t = snic->lldi.tids;
+
+	csk = lookup_tid(t, hwtid);
+
+	if (unlikely(!csk)) {
+		cxgbi_log_error("can't find connection for tid %u\n", hwtid);
+		return CPL_RET_UNKNOWN_TID;
+	}
+
+	cxgbi_sock_hold(csk);
+	spin_lock_bh(&csk->lock);
+
+	if (cxgbi_sock_flag(csk, CXGBI_CSK_FL_ABORT_RPL_PENDING))
+		goto out;
+
+	switch (csk->state) {
+	case CXGBI_CSK_ST_ESTABLISHED:
+		cxgbi_sock_set_state(csk, CXGBI_CSK_ST_PASSIVE_CLOSE);
+		break;
+	case CXGBI_CSK_ST_ACTIVE_CLOSE:
+		cxgbi_sock_set_state(csk, CXGBI_CSK_ST_CLOSE_WAIT_2);
+		break;
+	case CXGBI_CSK_ST_CLOSE_WAIT_1:
+		cxgb4i_sock_closed(csk);
+		break;
+	case CXGBI_CSK_ST_ABORTING:
+		break;
+	default:
+		cxgbi_log_error("peer close, TID %u in bad state %u\n",
+				csk->hwtid, csk->state);
+	}
+
+	cxgbi_sock_conn_closing(csk);
+
+out:
+	__kfree_skb(skb);
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+
+	return 0;
+}
+
+static int cxgb4i_cpl_close_con_rpl(struct cxgb4i_snic *snic,
+						struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_close_con_rpl *rpl = cplhdr(skb);
+	unsigned int hwtid = GET_TID(rpl);
+	struct tid_info *t = snic->lldi.tids;
+
+	csk = lookup_tid(t, hwtid);
+
+	if (unlikely(!csk)) {
+		cxgbi_log_error("can't find connection for tid %u\n", hwtid);
+		return CPL_RET_UNKNOWN_TID;
+	}
+
+	cxgbi_sock_hold(csk);
+	spin_lock_bh(&csk->lock);
+
+	cxgbi_conn_debug("csk 0x%p, state %u, flag 0x%lx.\n",
+			csk, csk->state, csk->flags);
+
+	csk->snd_una = ntohl(rpl->snd_nxt) - 1;
+
+	if (cxgbi_sock_flag(csk, CXGBI_CSK_FL_ABORT_RPL_PENDING))
+		goto out;
+
+	switch (csk->state) {
+	case CXGBI_CSK_ST_ACTIVE_CLOSE:
+		cxgbi_sock_set_state(csk, CXGBI_CSK_ST_CLOSE_WAIT_1);
+		break;
+	case CXGBI_CSK_ST_CLOSE_WAIT_1:
+	case CXGBI_CSK_ST_CLOSE_WAIT_2:
+		cxgb4i_sock_closed(csk);
+		break;
+	case CXGBI_CSK_ST_ABORTING:
+		break;
+	default:
+		cxgbi_log_error("close_rpl, TID %u in bad state %u\n",
+				csk->hwtid, csk->state);
+	}
+out:
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+	kfree_skb(skb);
+
+	return 0;
+}
+
+static int abort_status_to_errno(struct cxgbi_sock *csk, int abort_reason,
+								int *need_rst)
+{
+	switch (abort_reason) {
+	case CPL_ERR_BAD_SYN: /* fall through */
+	case CPL_ERR_CONN_RESET:
+		return csk->state > CXGBI_CSK_ST_ESTABLISHED ?
+			-EPIPE : -ECONNRESET;
+	case CPL_ERR_XMIT_TIMEDOUT:
+	case CPL_ERR_PERSIST_TIMEDOUT:
+	case CPL_ERR_FINWAIT2_TIMEDOUT:
+	case CPL_ERR_KEEPALIVE_TIMEDOUT:
+		return -ETIMEDOUT;
+	default:
+		return -EIO;
+	}
+}
+
+/*
+ * Returns whether an ABORT_REQ_RSS message is a negative advice.
+ */
+static inline int is_neg_adv_abort(unsigned int status)
+{
+	return status == CPL_ERR_RTX_NEG_ADVICE ||
+		status == CPL_ERR_PERSIST_NEG_ADVICE;
+}
+
+static int cxgb4i_cpl_abort_req_rss(struct cxgb4i_snic *snic,
+						struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_abort_req_rss *req = cplhdr(skb);
+	unsigned int hwtid = GET_TID(req);
+	struct tid_info *t = snic->lldi.tids;
+	int rst_status = CPL_ABORT_NO_RST;
+
+	csk = lookup_tid(t, hwtid);
+	if (unlikely(!csk)) {
+		cxgbi_log_error("can't find connection for tid %u\n", hwtid);
+		return CPL_RET_UNKNOWN_TID;
+	}
+
+	cxgbi_sock_hold(csk);
+	spin_lock_bh(&csk->lock);
+
+	if (is_neg_adv_abort(req->status)) {
+		__kfree_skb(skb);
+		return 0;
+	}
+
+	if (!cxgbi_sock_flag(csk, CXGBI_CSK_FL_ABORT_REQ_RCVD)) {
+		cxgbi_sock_set_flag(csk, CXGBI_CSK_FL_ABORT_REQ_RCVD);
+		cxgbi_sock_set_state(csk, CXGBI_CSK_ST_ABORTING);
+		__kfree_skb(skb);
+		return 0;
+	}
+
+	cxgbi_sock_clear_flag(csk, CXGBI_CSK_FL_ABORT_REQ_RCVD);
+	cxgb4i_sock_send_abort_rpl(csk, rst_status);
+
+	if (!cxgbi_sock_flag(csk, CXGBI_CSK_FL_ABORT_RPL_PENDING)) {
+		csk->err = abort_status_to_errno(csk, req->status,
+							&rst_status);
+		cxgb4i_sock_closed(csk);
+	}
+
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+
+	return 0;
+}
+
+static int cxgb4i_cpl_abort_rpl_rss(struct cxgb4i_snic *snic,
+						struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_abort_rpl_rss *rpl = cplhdr(skb);
+	unsigned int hwtid = GET_TID(rpl);
+	struct tid_info *t = snic->lldi.tids;
+
+	if (rpl->status == CPL_ERR_ABORT_FAILED)
+		goto out;
+
+	csk = lookup_tid(t, hwtid);
+	if (unlikely(!csk)) {
+		cxgbi_log_error("can't find connection for tid %u\n", hwtid);
+		goto out;
+	}
+
+	cxgbi_sock_hold(csk);
+	spin_lock_bh(&csk->lock);
+
+	if (cxgbi_sock_flag(csk, CXGBI_CSK_FL_ABORT_RPL_PENDING)) {
+		if (!cxgbi_sock_flag(csk, CXGBI_CSK_FL_ABORT_RPL_RCVD))
+			cxgbi_sock_set_flag(csk,
+						CXGBI_CSK_FL_ABORT_RPL_RCVD);
+		else {
+			cxgbi_sock_clear_flag(csk,
+						CXGBI_CSK_FL_ABORT_RPL_RCVD);
+			cxgbi_sock_clear_flag(csk,
+					CXGBI_CSK_FL_ABORT_RPL_PENDING);
+
+			if (cxgbi_sock_flag(csk,
+						CXGBI_CSK_FL_ABORT_REQ_RCVD))
+				cxgbi_log_error("tid %u, ABORT_RPL_RSS\n",
+						csk->hwtid);
+
+			cxgb4i_sock_closed(csk);
+		}
+	}
+
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+
+out:
+	__kfree_skb(skb);
+	return 0;
+}
+
+static int cxgb4i_cpl_iscsi_hdr(struct cxgb4i_snic *snic, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_iscsi_hdr *cpl = cplhdr(skb);
+	unsigned int hwtid = GET_TID(cpl);
+	struct tid_info *t = snic->lldi.tids;
+	struct sk_buff *lskb;
+
+	csk = lookup_tid(t, hwtid);
+
+	if (unlikely(!csk)) {
+		cxgbi_log_error("can't find connection for tid %u\n", hwtid);
+		return CPL_RET_UNKNOWN_TID;
+	}
+
+	spin_lock_bh(&csk->lock);
+
+	if (unlikely(csk->state >= CXGBI_CSK_ST_PASSIVE_CLOSE)) {
+		if (csk->state != CXGBI_CSK_ST_ABORTING)
+			goto abort_conn;
+	}
+
+	cxgb4i_skb_tcp_seq(skb) = ntohl(cpl->seq);
+	cxgb4i_skb_flags(skb) = 0;
+
+	skb_reset_transport_header(skb);
+	__skb_pull(skb, sizeof(*cpl));
+	__pskb_trim(skb, ntohs(cpl->len));
+
+	if (!csk->skb_ulp_lhdr) {
+		unsigned char *byte;
+		csk->skb_ulp_lhdr = skb;
+		lskb = csk->skb_ulp_lhdr;
+
+		cxgb4i_skb_flags(lskb) = CXGB4I_SKCB_FLAG_HDR_RCVD;
+
+		if (cxgb4i_skb_tcp_seq(lskb) != csk->rcv_nxt) {
+			cxgbi_log_error("tid 0x%x, CPL_ISCSI_HDR, bad seq got "
+					"0x%x, exp 0x%x\n",
+					csk->hwtid,
+					cxgb4i_skb_tcp_seq(lskb),
+					csk->rcv_nxt);
+		}
+
+		byte = skb->data;
+		cxgb4i_skb_rx_pdulen(skb) = ntohs(cpl->pdu_len_ddp) - 40;
+		csk->rcv_nxt += cxgb4i_skb_rx_pdulen(lskb);
+	} else {
+		lskb = csk->skb_ulp_lhdr;
+		cxgb4i_skb_flags(lskb) |= CXGB4I_SKCB_FLAG_DATA_RCVD;
+		cxgb4i_skb_flags(skb) = CXGB4I_SKCB_FLAG_DATA_RCVD;
+		cxgbi_log_debug("csk 0x%p, tid 0x%x skb 0x%p, pdu data, "
+				" header 0x%p.\n",
+				csk, csk->hwtid, skb, lskb);
+	}
+
+	__skb_queue_tail(&csk->receive_queue, skb);
+
+	spin_unlock_bh(&csk->lock);
+
+	return 0;
+
+abort_conn:
+	cxgb4i_sock_send_abort_req(csk);
+	__kfree_skb(skb);
+	spin_unlock_bh(&csk->lock);
+
+	return -EINVAL;
+}
+
+static int cxgb4i_cpl_rx_data_ddp(struct cxgb4i_snic *snic, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct sk_buff *lskb;
+	struct cpl_rx_data_ddp *rpl = cplhdr(skb);
+	unsigned int hwtid = GET_TID(rpl);
+	struct tid_info *t = snic->lldi.tids;
+	unsigned int status;
+
+	csk = lookup_tid(t, hwtid);
+
+	if (unlikely(!csk)) {
+		cxgbi_log_error("can't find connection for tid %u\n", hwtid);
+		return CPL_RET_UNKNOWN_TID;
+	}
+
+	spin_lock_bh(&csk->lock);
+
+	if (unlikely(csk->state >= CXGBI_CSK_ST_PASSIVE_CLOSE)) {
+		if (csk->state != CXGBI_CSK_ST_ABORTING)
+			goto abort_conn;
+	}
+
+	if (!csk->skb_ulp_lhdr) {
+		cxgbi_log_error("tid 0x%x, rcv RX_DATA_DDP w/o pdu header\n",
+				csk->hwtid);
+		goto abort_conn;
+	}
+
+	lskb = csk->skb_ulp_lhdr;
+	cxgb4i_skb_flags(lskb) |= CXGB4I_SKCB_FLAG_STATUS_RCVD;
+
+	if (ntohs(rpl->len) != cxgb4i_skb_rx_pdulen(lskb)) {
+		cxgbi_log_error("tid 0x%x, RX_DATA_DDP pdulen %u != %u.\n",
+				csk->hwtid, ntohs(rpl->len),
+				cxgb4i_skb_rx_pdulen(lskb));
+	}
+
+	cxgb4i_skb_rx_ddigest(lskb) = ntohl(rpl->ulp_crc);
+	status = ntohl(rpl->ddpvld);
+
+	if (status & (1 << RX_DDP_STATUS_HCRC_SHIFT))
+		cxgb4i_skb_ulp_mode(skb) |= ULP2_FLAG_HCRC_ERROR;
+	if (status & (1 << RX_DDP_STATUS_DCRC_SHIFT))
+		cxgb4i_skb_ulp_mode(skb) |= ULP2_FLAG_DCRC_ERROR;
+	if (status & (1 << RX_DDP_STATUS_PAD_SHIFT))
+		cxgb4i_skb_ulp_mode(skb) |= ULP2_FLAG_PAD_ERROR;
+	if ((cxgb4i_skb_flags(lskb) & ULP2_FLAG_DATA_READY))
+		cxgb4i_skb_ulp_mode(skb) |= ULP2_FLAG_DATA_DDPED;
+
+	csk->skb_ulp_lhdr = NULL;
+
+	__kfree_skb(skb);
+	cxgbi_conn_pdu_ready(csk);
+	spin_unlock_bh(&csk->lock);
+
+	return 0;
+
+abort_conn:
+	cxgb4i_sock_send_abort_req(csk);
+	__kfree_skb(skb);
+	spin_unlock_bh(&csk->lock);
+	return -EINVAL;
+}
+
+static void check_wr_invariants(const struct cxgbi_sock *csk)
+{
+	int pending = cxgb4i_sock_count_pending_wrs(csk);
+
+	if (unlikely(csk->wr_cred + pending != csk->wr_max_cred))
+		printk(KERN_ERR "TID %u: credit imbalance: avail %u, "
+				"pending %u, total should be %u\n",
+				csk->hwtid,
+				csk->wr_cred,
+				pending,
+				csk->wr_max_cred);
+}
+
+static int cxgb4i_cpl_fw4_ack(struct cxgb4i_snic *snic, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_fw4_ack *rpl = cplhdr(skb);
+	unsigned int hwtid = GET_TID(rpl);
+	struct tid_info *t = snic->lldi.tids;
+	unsigned char credits;
+	unsigned int snd_una;
+
+	csk = lookup_tid(t, hwtid);
+	if (unlikely(!csk)) {
+		cxgbi_log_error("can't find connection for tid %u\n", hwtid);
+		kfree_skb(skb);
+		return CPL_RET_UNKNOWN_TID;
+	}
+
+	cxgbi_sock_hold(csk);
+	spin_lock_bh(&csk->lock);
+
+	credits = rpl->credits;
+	snd_una = be32_to_cpu(rpl->snd_una);
+
+	cxgbi_tx_debug("%u WR credits, avail %u, unack %u, TID %u, state %u\n",
+				credits, csk->wr_cred, csk->wr_una_cred,
+						csk->hwtid, csk->state);
+
+	csk->wr_cred += credits;
+
+	if (csk->wr_una_cred > csk->wr_max_cred - csk->wr_cred)
+		csk->wr_una_cred = csk->wr_max_cred - csk->wr_cred;
+
+	while (credits) {
+		struct sk_buff *p = cxgb4i_sock_peek_wr(csk);
+
+		if (unlikely(!p)) {
+			cxgbi_log_error("%u WR_ACK credits for TID %u with "
+					"nothing pending, state %u\n",
+					credits, csk->hwtid, csk->state);
+			break;
+		}
+
+		if (unlikely(credits < p->csum)) {
+			p->csum -= credits;
+		} else {
+			cxgb4i_sock_dequeue_wr(csk);
+			credits -= p->csum;
+			cxgb4i_sock_free_wr_skb(p);
+		}
+	}
+
+	check_wr_invariants(csk);
+
+	if (rpl->seq_vld) {
+		if (unlikely(before(snd_una, csk->snd_una))) {
+			cxgbi_log_error("TID %u, unexpected sequence # %u "
+					"in WR_ACK snd_una %u\n",
+					csk->hwtid, snd_una, csk->snd_una);
+			goto out_free;
+		}
+	}
+
+	if (csk->snd_una != snd_una) {
+		csk->snd_una = snd_una;
+		dst_confirm(csk->dst);
+	}
+
+	if (skb_queue_len(&csk->write_queue)) {
+		if (cxgb4i_sock_push_tx_frames(csk, 0))
+			cxgbi_conn_tx_open(csk);
+	} else
+		cxgbi_conn_tx_open(csk);
+
+	goto out;
+
+out_free:
+
+	__kfree_skb(skb);
+
+out:
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+
+	return 0;
+}
+
+static int cxgb4i_cpl_set_tcb_rpl(struct cxgb4i_snic *snic, struct sk_buff *skb)
+{
+	struct cpl_set_tcb_rpl *rpl = cplhdr(skb);
+	unsigned int hwtid = GET_TID(rpl);
+	struct tid_info *t = snic->lldi.tids;
+	struct cxgbi_sock *csk;
+
+	csk = lookup_tid(t, hwtid);
+
+	if (!csk) {
+		cxgbi_log_error("can't find connection for tid %u\n", hwtid);
+		__kfree_skb(skb);
+		return CPL_RET_UNKNOWN_TID;
+	}
+
+	spin_lock_bh(&csk->lock);
+
+	if (rpl->status != CPL_ERR_NONE) {
+		cxgbi_log_error("Unexpected SET_TCB_RPL status %u "
+				 "for tid %u\n", rpl->status, GET_TID(rpl));
+	}
+
+	__kfree_skb(skb);
+	spin_unlock_bh(&csk->lock);
+
+	return 0;
+}
+
+static void cxgb4i_sock_free_cpl_skbs(struct cxgbi_sock *csk)
+{
+	if (csk->cpl_close)
+		kfree_skb(csk->cpl_close);
+	if (csk->cpl_abort_req)
+		kfree_skb(csk->cpl_abort_req);
+	if (csk->cpl_abort_rpl)
+		kfree_skb(csk->cpl_abort_rpl);
+}
+
+static int cxgb4i_alloc_cpl_skbs(struct cxgbi_sock *csk)
+{
+	csk->cpl_close = alloc_skb(sizeof(struct cpl_close_con_req),
+					GFP_KERNEL);
+	if (!csk->cpl_close)
+		return -ENOMEM;
+	skb_put(csk->cpl_close, sizeof(struct cpl_close_con_req));
+
+	csk->cpl_abort_req = alloc_skb(sizeof(struct cpl_abort_req),
+					GFP_KERNEL);
+	if (!csk->cpl_abort_req)
+		goto free_cpl_skbs;
+	skb_put(csk->cpl_abort_req, sizeof(struct cpl_abort_req));
+
+	csk->cpl_abort_rpl = alloc_skb(sizeof(struct cpl_abort_rpl),
+					GFP_KERNEL);
+	if (!csk->cpl_abort_rpl)
+		goto free_cpl_skbs;
+	skb_put(csk->cpl_abort_rpl, sizeof(struct cpl_abort_rpl));
+
+	return 0;
+
+free_cpl_skbs:
+	cxgb4i_sock_free_cpl_skbs(csk);
+	return -ENOMEM;
+}
+
+static void cxgb4i_sock_release_offload_resources(struct cxgbi_sock *csk)
+{
+
+	cxgb4i_sock_free_cpl_skbs(csk);
+
+	if (csk->wr_cred != csk->wr_max_cred) {
+		cxgb4i_sock_purge_wr_queue(csk);
+		cxgb4i_sock_reset_wr_list(csk);
+	}
+
+	if (csk->l2t) {
+		cxgb4_l2t_release(csk->l2t);
+		csk->l2t = NULL;
+	}
+
+	if (csk->state == CXGBI_CSK_ST_CONNECTING)
+		cxgb4i_sock_free_atid(csk);
+	else {
+		cxgb4_remove_tid(cxgb4i_get_snic(csk->cdev)->lldi.tids, 0,
+				csk->hwtid);
+		cxgbi_sock_put(csk);
+	}
+
+	csk->dst = NULL;
+	csk->cdev = NULL;
+}
+
+struct cxgbi_sock *cxgb4i_sock_create(struct cxgb4i_snic *snic)
+{
+	struct cxgbi_sock *csk = NULL;
+
+	csk = kzalloc(sizeof(*csk), GFP_KERNEL);
+	if (!csk)
+		return NULL;
+
+	if (cxgb4i_alloc_cpl_skbs(csk) < 0)
+		goto free_csk;
+
+	cxgbi_conn_debug("alloc csk: 0x%p\n", csk);
+
+	csk->flags = 0;
+	spin_lock_init(&csk->lock);
+	atomic_set(&csk->refcnt, 1);
+	skb_queue_head_init(&csk->receive_queue);
+	skb_queue_head_init(&csk->write_queue);
+	setup_timer(&csk->retry_timer, NULL, (unsigned long)csk);
+	rwlock_init(&csk->callback_lock);
+	csk->cdev = &snic->cdev;
+
+	return csk;
+
+free_csk:
+	cxgbi_api_debug("csk alloc failed %p, baling out\n", csk);
+	kfree(csk);
+	return NULL;
+}
+
+static void cxgb4i_sock_active_close(struct cxgbi_sock *csk)
+{
+	int data_lost;
+	int close_req = 0;
+
+	cxgbi_conn_debug("csk 0x%p, state %u, flags %lu\n",
+			csk, csk->state, csk->flags);
+
+	dst_confirm(csk->dst);
+
+	cxgbi_sock_hold(csk);
+	spin_lock_bh(&csk->lock);
+
+	data_lost = skb_queue_len(&csk->receive_queue);
+	__skb_queue_purge(&csk->receive_queue);
+
+	switch (csk->state) {
+	case CXGBI_CSK_ST_CLOSED:
+	case CXGBI_CSK_ST_ACTIVE_CLOSE:
+	case CXGBI_CSK_ST_CLOSE_WAIT_1:
+	case CXGBI_CSK_ST_CLOSE_WAIT_2:
+	case CXGBI_CSK_ST_ABORTING:
+		break;
+
+	case CXGBI_CSK_ST_CONNECTING:
+		cxgbi_sock_set_flag(csk, CXGBI_CSK_FL_ACTIVE_CLOSE_NEEDED);
+		break;
+	case CXGBI_CSK_ST_ESTABLISHED:
+		close_req = 1;
+		cxgbi_sock_set_flag(csk, CXGBI_CSK_ST_CLOSE_WAIT_2);
+		break;
+	}
+
+	if (close_req) {
+		if (data_lost)
+			cxgb4i_sock_send_abort_req(csk);
+		else
+			cxgb4i_sock_send_close_req(csk);
+	}
+
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+}
+
+void cxgb4i_sock_release(struct cxgbi_sock *csk)
+{
+	cxgbi_conn_debug("csk 0x%p, state %u, flags %lu\n",
+			csk, csk->state, csk->flags);
+
+	if (unlikely(csk->state == CXGBI_CSK_ST_CONNECTING))
+		cxgbi_sock_set_state(csk,
+				CXGBI_CSK_FL_ACTIVE_CLOSE_NEEDED);
+	else if (likely(csk->state != CXGBI_CSK_ST_CLOSED))
+		cxgb4i_sock_active_close(csk);
+
+	cxgbi_sock_put(csk);
+}
+
+static int is_cxgb4_dev(struct net_device *dev, struct cxgb4i_snic *snic)
+{
+	struct net_device *ndev = dev;
+	int i;
+
+	if (dev->priv_flags & IFF_802_1Q_VLAN)
+		ndev = vlan_dev_real_dev(dev);
+
+	for (i = 0; i < snic->lldi.nports; i++) {
+		if (ndev == snic->lldi.ports[i])
+			return 1;
+	}
+
+	return 0;
+}
+
+static struct net_device *cxgb4i_find_egress_dev(struct net_device *root_dev,
+						struct cxgb4i_snic *snic)
+{
+	while (root_dev) {
+		if (root_dev->priv_flags & IFF_802_1Q_VLAN)
+			root_dev = vlan_dev_real_dev(root_dev);
+		else if (is_cxgb4_dev(root_dev, snic))
+			return root_dev;
+		else
+			return NULL;
+	}
+
+	return NULL;
+}
+
+static struct rtable *find_route(struct net_device *dev,
+				__be32 saddr, __be32 daddr,
+				__be16 sport, __be16 dport,
+				u8 tos)
+{
+	struct rtable *rt;
+	struct flowi fl = {
+		.oif = dev ? dev->ifindex : 0,
+		.nl_u = {
+			.ip4_u = {
+				.daddr = daddr,
+				.saddr = saddr,
+				.tos = tos }
+			},
+		.proto = IPPROTO_TCP,
+		.uli_u = {
+			.ports = {
+				.sport = sport,
+				.dport = dport }
+			}
+	};
+
+	if (ip_route_output_flow(dev ? dev_net(dev) : &init_net,
+					&rt, &fl, NULL, 0))
+		return NULL;
+
+	return rt;
+}
+
+static int cxgb4i_init_act_open(struct cxgbi_sock *csk,
+					struct net_device *dev)
+{
+	struct dst_entry *dst = csk->dst;
+	struct sk_buff *skb;
+	struct port_info *pi = netdev_priv(dev);
+
+	cxgbi_conn_debug("csk 0x%p, state %u, flags 0x%lx\n",
+			csk, csk->state, csk->flags);
+
+	csk->atid = cxgb4_alloc_atid(cxgb4i_get_snic(csk->cdev)->lldi.tids,
+					csk);
+	if (csk->atid == -1) {
+		cxgbi_log_error("cannot alloc atid\n");
+		goto out_err;
+	}
+
+	csk->l2t = cxgb4_l2t_get(cxgb4i_get_snic(csk->cdev)->lldi.l2t,
+				csk->dst->neighbour, dev, 0);
+	if (!csk->l2t) {
+		cxgbi_log_error("cannot alloc l2t\n");
+		goto free_atid;
+	}
+
+	skb = alloc_skb(sizeof(struct cpl_act_open_req), GFP_KERNEL);
+	if (!skb)
+		goto free_l2t;
+
+	skb->sk = (struct sock *)csk;
+	t4_set_arp_err_handler(skb, csk, cxgb4i_act_open_req_arp_failure);
+
+	cxgbi_sock_hold(csk);
+
+	csk->wr_max_cred = csk->wr_cred =
+		cxgb4i_get_snic(csk->cdev)->lldi.wr_cred;
+	csk->port_id = pi->port_id;
+	csk->rss_qid = cxgb4i_get_snic(csk->cdev)->lldi.rxq_ids[csk->port_id];
+	csk->tx_chan = pi->tx_chan;
+	csk->smac_idx = csk->tx_chan << 1;
+	csk->wr_una_cred = 0;
+	csk->mss_idx = cxgb4i_select_mss(csk, dst_mtu(dst));
+	csk->err = 0;
+
+	cxgb4i_sock_reset_wr_list(csk);
+
+	cxgb4i_sock_make_act_open_req(csk, skb,
+					((csk->rss_qid << 14) |
+					 (csk->atid)), csk->l2t);
+	cxgb4_l2t_send(cxgb4i_get_snic(csk->cdev)->lldi.ports[csk->port_id],
+					skb, csk->l2t);
+	return 0;
+
+free_l2t:
+	cxgb4_l2t_release(csk->l2t);
+
+free_atid:
+	cxgb4_free_atid(cxgb4i_get_snic(csk->cdev)->lldi.tids, csk->atid);
+
+out_err:
+
+	return -EINVAL;;
+}
+
+static struct net_device *cxgb4i_find_dev(struct net_device *dev,
+							__be32 ipaddr)
+{
+	struct flowi fl;
+	struct rtable *rt;
+	int err;
+
+	memset(&fl, 0, sizeof(fl));
+	fl.nl_u.ip4_u.daddr = ipaddr;
+
+	err = ip_route_output_key(dev ? dev_net(dev) : &init_net, &rt, &fl);
+	if (!err)
+		return (&rt->u.dst)->dev;
+
+	return NULL;
+}
+
+int cxgb4i_sock_connect(struct net_device *dev, struct cxgbi_sock *csk,
+						struct sockaddr_in *sin)
+{
+	struct rtable *rt;
+	__be32 sipv4 = 0;
+	struct net_device *dstdev;
+	struct cxgbi_hba *chba = NULL;
+	int err;
+
+	cxgbi_conn_debug("csk 0x%p, dev 0x%p\n", csk, dev);
+
+	if (sin->sin_family != AF_INET)
+		return -EAFNOSUPPORT;
+
+	csk->daddr.sin_port = sin->sin_port;
+	csk->daddr.sin_addr.s_addr = sin->sin_addr.s_addr;
+
+	dstdev = cxgb4i_find_dev(dev, sin->sin_addr.s_addr);
+	if (!dstdev || !is_cxgb4_dev(dstdev, cxgb4i_get_snic(csk->cdev)))
+		return -ENETUNREACH;
+
+	if (dstdev->priv_flags & IFF_802_1Q_VLAN)
+		dev = dstdev;
+
+	rt = find_route(dev, csk->saddr.sin_addr.s_addr,
+			csk->daddr.sin_addr.s_addr,
+			csk->saddr.sin_port,
+			csk->daddr.sin_port,
+			0);
+	if (rt == NULL) {
+		cxgbi_conn_debug("no route to %pI4, port %u, dev %s, "
+					"snic 0x%p\n",
+					&csk->daddr.sin_addr.s_addr,
+					ntohs(csk->daddr.sin_port),
+					dev ? dev->name : "any",
+					csk->snic);
+		return -ENETUNREACH;
+	}
+
+	if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
+		cxgbi_conn_debug("multi-cast route to %pI4, port %u, "
+					"dev %s, snic 0x%p\n",
+					&csk->daddr.sin_addr.s_addr,
+					ntohs(csk->daddr.sin_port),
+					dev ? dev->name : "any",
+					csk->snic);
+		ip_rt_put(rt);
+		return -ENETUNREACH;
+	}
+
+	if (!csk->saddr.sin_addr.s_addr)
+		csk->saddr.sin_addr.s_addr = rt->rt_src;
+
+	csk->dst = &rt->u.dst;
+
+	dev = cxgb4i_find_egress_dev(csk->dst->dev,
+					cxgb4i_get_snic(csk->cdev));
+	if (dev == NULL) {
+		cxgbi_conn_debug("csk: 0x%p, egress dev NULL\n", csk);
+		return -ENETUNREACH;
+	}
+
+	err = cxgbi_sock_get_port(csk);
+	if (err)
+		return err;
+
+	cxgbi_conn_debug("csk: 0x%p get port: %u\n",
+			csk, ntohs(csk->saddr.sin_port));
+
+	chba = cxgb4i_hba_find_by_netdev(csk->dst->dev);
+
+	sipv4 = cxgb4i_get_iscsi_ipv4(chba);
+	if (!sipv4) {
+		cxgbi_conn_debug("csk: 0x%p, iscsi is not configured\n", csk);
+		sipv4 = csk->saddr.sin_addr.s_addr;
+		cxgb4i_set_iscsi_ipv4(chba, sipv4);
+	} else
+		csk->saddr.sin_addr.s_addr = sipv4;
+
+	cxgbi_conn_debug("csk: 0x%p, %pI4:[%u], %pI4:[%u] SYN_SENT\n",
+				csk,
+				&csk->saddr.sin_addr.s_addr,
+				ntohs(csk->saddr.sin_port),
+				&csk->daddr.sin_addr.s_addr,
+				ntohs(csk->daddr.sin_port));
+
+	cxgbi_sock_set_state(csk, CXGBI_CSK_ST_CONNECTING);
+
+	if (!cxgb4i_init_act_open(csk, dev))
+		return 0;
+
+	err = -ENOTSUPP;
+
+	cxgbi_conn_debug("csk 0x%p -> closed\n", csk);
+	cxgbi_sock_set_state(csk, CXGBI_CSK_ST_CLOSED);
+	ip_rt_put(rt);
+	cxgbi_sock_put_port(csk);
+
+	return err;
+}
+
+void cxgb4i_sock_rx_credits(struct cxgbi_sock *csk, int copied)
+{
+	int must_send;
+	u32 credits;
+
+	if (csk->state != CXGBI_CSK_ST_ESTABLISHED)
+		return;
+
+	credits = csk->copied_seq - csk->rcv_wup;
+	if (unlikely(!credits))
+		return;
+
+	if (unlikely(cxgb4i_rx_credit_thres == 0))
+		return;
+
+	must_send = credits + 16384 >= cxgb4i_rcv_win;
+
+	if (must_send || credits >= cxgb4i_rx_credit_thres)
+		csk->rcv_wup += cxgb4i_csk_send_rx_credits(csk, credits);
+}
+
+int cxgb4i_sock_send_pdus(struct cxgbi_sock *csk, struct sk_buff *skb)
+{
+	struct sk_buff *next;
+	int err, copied = 0;
+
+	spin_lock_bh(&csk->lock);
+
+	if (csk->state != CXGBI_CSK_ST_ESTABLISHED) {
+		cxgbi_tx_debug("csk 0x%p, not in est. state %u.\n",
+			      csk, csk->state);
+		err = -EAGAIN;
+		goto out_err;
+	}
+
+	if (csk->err) {
+		cxgbi_tx_debug("csk 0x%p, err %d.\n", csk, csk->err);
+		err = -EPIPE;
+		goto out_err;
+	}
+
+	if (csk->write_seq - csk->snd_una >= cxgb4i_snd_win) {
+		cxgbi_tx_debug("csk 0x%p, snd %u - %u > %u.\n",
+				csk, csk->write_seq, csk->snd_una,
+				cxgb4i_snd_win);
+		err = -ENOBUFS;
+		goto out_err;
+	}
+
+	while (skb) {
+		int frags = skb_shinfo(skb)->nr_frags +
+				(skb->len != skb->data_len);
+
+		if (unlikely(skb_headroom(skb) < CXGB4I_TX_HEADER_LEN)) {
+			cxgbi_tx_debug("csk 0x%p, skb head.\n", csk);
+			err = -EINVAL;
+			goto out_err;
+		}
+
+		if (frags >= SKB_WR_LIST_SIZE) {
+			cxgbi_log_error("csk 0x%p, tx frags %d, len %u,%u.\n",
+					 csk, skb_shinfo(skb)->nr_frags,
+					 skb->len, skb->data_len);
+			err = -EINVAL;
+			goto out_err;
+		}
+
+		next = skb->next;
+		skb->next = NULL;
+		cxgb4i_sock_skb_entail(csk, skb,
+				CXGB4I_SKCB_FLAG_NO_APPEND |
+				CXGB4I_SKCB_FLAG_NEED_HDR);
+		copied += skb->len;
+		csk->write_seq += skb->len + ulp_extra_len(skb);
+		skb = next;
+	}
+done:
+	if (likely(skb_queue_len(&csk->write_queue)))
+		cxgb4i_sock_push_tx_frames(csk, 1);
+	spin_unlock_bh(&csk->lock);
+	return copied;
+
+out_err:
+	if (copied == 0 && err == -EPIPE)
+		copied = csk->err ? csk->err : -EPIPE;
+	else
+		copied = err;
+	goto done;
+}
+
+static void cxgbi_sock_conn_closing(struct cxgbi_sock *csk)
+{
+	struct iscsi_conn *conn = csk->user_data;
+
+	read_lock(&csk->callback_lock);
+	if (conn && csk->state != CXGBI_CSK_ST_ESTABLISHED)
+		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+	read_unlock(&csk->callback_lock);
+}
+
+static void tx_skb_setmode(struct sk_buff *skb, int hcrc, int dcrc)
+{
+	u8 submode = 0;
+
+	if (hcrc)
+		submode |= 1;
+	if (dcrc)
+		submode |= 2;
+	cxgb4i_skb_ulp_mode(skb) = (ULP_MODE_ISCSI << 4) | submode;
+}
+
+static inline __u16 get_skb_ulp_mode(struct sk_buff *skb)
+{
+	return cxgb4i_skb_ulp_mode(skb);
+}
+
+static cxgb4i_cplhandler_func cxgb4i_cplhandlers[NUM_CPL_CMDS] = {
+	[CPL_ACT_ESTABLISH] = cxgb4i_cpl_act_establish,
+	[CPL_ACT_OPEN_RPL] = cxgb4i_cpl_act_open_rpl,
+	[CPL_PEER_CLOSE] = cxgb4i_cpl_peer_close,
+	[CPL_ABORT_REQ_RSS] = cxgb4i_cpl_abort_req_rss,
+	[CPL_ABORT_RPL_RSS] = cxgb4i_cpl_abort_rpl_rss,
+	[CPL_CLOSE_CON_RPL] = cxgb4i_cpl_close_con_rpl,
+	[CPL_FW4_ACK] = cxgb4i_cpl_fw4_ack,
+	[CPL_ISCSI_HDR] = cxgb4i_cpl_iscsi_hdr,
+	[CPL_SET_TCB_RPL] = cxgb4i_cpl_set_tcb_rpl,
+	[CPL_RX_DATA_DDP] = cxgb4i_cpl_rx_data_ddp
+};
+
+int cxgb4i_ofld_init(struct cxgb4i_snic *snic)
+{
+	struct cxgbi_ports_map *ports;
+	int mapsize;
+
+	if (cxgb4i_max_connect > CXGB4I_MAX_CONN)
+		cxgb4i_max_connect = CXGB4I_MAX_CONN;
+
+	mapsize = (cxgb4i_max_connect * sizeof(struct cxgbi_sock));
+	ports = cxgbi_alloc_big_mem(sizeof(*ports) + mapsize, GFP_KERNEL);
+	if (!ports)
+		return -ENOMEM;
+
+	spin_lock_init(&ports->lock);
+	snic->cdev.pmap = ports;
+	snic->cdev.pmap->max_connect = cxgb4i_max_connect;
+	snic->cdev.pmap->sport_base = cxgb4i_sport_base;
+
+	snic->cdev.tx_skb_setmode = tx_skb_setmode;
+	snic->cdev.sock_send_pdus = cxgb4i_sock_send_pdus;
+	snic->cdev.get_skb_ulp_mode = get_skb_ulp_mode;
+
+	snic->handlers = cxgb4i_cplhandlers;
+
+	return 0;
+}
+
+void cxgb4i_ofld_cleanup(struct cxgb4i_snic *snic)
+{
+	struct cxgbi_sock *csk;
+	int i;
+
+	for (i = 0; i < snic->cdev.pmap->max_connect; i++) {
+		if (snic->cdev.pmap->port_csk[i]) {
+			csk = snic->cdev.pmap->port_csk[i];
+			snic->cdev.pmap->port_csk[i] = NULL;
+
+			spin_lock_bh(&csk->lock);
+			cxgb4i_sock_closed(csk);
+			spin_unlock_bh(&csk->lock);
+		}
+	}
+	cxgbi_free_big_mem(snic->cdev.pmap);
+}
+
diff --git a/drivers/scsi/cxgb4i/cxgb4i_offload.h b/drivers/scsi/cxgb4i/cxgb4i_offload.h
new file mode 100644
index 0000000..afd50d9
--- /dev/null
+++ b/drivers/scsi/cxgb4i/cxgb4i_offload.h
@@ -0,0 +1,91 @@
+/*
+ * cxgb4i_offload.h: Chelsio T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Karen Xie (kxie-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ * Written by: Rakesh Ranjan (rranjan-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ */
+
+#ifndef	__CXGB4I_OFFLOAD_H__
+#define	__CXGB4I_OFFLOAD_H__
+
+#include <linux/skbuff.h>
+#include <linux/in.h>
+
+#include "libcxgbi.h"
+
+#define	CXGB4I_MAX_CONN	16384
+
+enum {
+	CPL_RET_BUF_DONE = 1,
+	CPL_RET_BAD_MSG = 2,
+	CPL_RET_UNKNOWN_TID = 4
+};
+
+struct cxgbi_sock *cxgb4i_sock_create(struct cxgb4i_snic *);
+void cxgb4i_sock_release(struct cxgbi_sock *);
+int cxgb4i_sock_connect(struct net_device *, struct cxgbi_sock *,
+			struct sockaddr_in *);
+void cxgb4i_sock_rx_credits(struct cxgbi_sock *, int);
+int cxgb4i_sock_send_pdus(struct cxgbi_sock *, struct sk_buff *);
+
+struct cxgb4i_skb_rx_cb {
+	__u32 ddigest;
+	__u32 pdulen;
+};
+
+struct cxgb4i_skb_tx_cb {
+	struct l2t_skb_cb l2t;
+	struct sk_buff *wr_next;
+};
+
+struct cxgb4i_skb_cb {
+	__u16 flags;
+	__u16 ulp_mode;
+	__u32 seq;
+
+	union {
+		struct cxgb4i_skb_rx_cb rx;
+		struct cxgb4i_skb_tx_cb tx;
+	};
+};
+
+#define CXGB4I_SKB_CB(skb)	((struct cxgb4i_skb_cb *)&((skb)->cb[0]))
+#define cxgb4i_skb_flags(skb)	(CXGB4I_SKB_CB(skb)->flags)
+#define cxgb4i_skb_ulp_mode(skb)	(CXGB4I_SKB_CB(skb)->ulp_mode)
+#define cxgb4i_skb_tcp_seq(skb)		(CXGB4I_SKB_CB(skb)->seq)
+#define cxgb4i_skb_rx_ddigest(skb)	(CXGB4I_SKB_CB(skb)->rx.ddigest)
+#define cxgb4i_skb_rx_pdulen(skb)	(CXGB4I_SKB_CB(skb)->rx.pdulen)
+#define cxgb4i_skb_tx_wr_next(skb)	(CXGB4I_SKB_CB(skb)->tx.wr_next)
+
+enum cxgb4i_skcb_flags {
+	CXGB4I_SKCB_FLAG_NEED_HDR = 1 << 0,	/* packet needs a header */
+	CXGB4I_SKCB_FLAG_NO_APPEND = 1 << 1,	/* don't grow this skb */
+	CXGB4I_SKCB_FLAG_COMPL = 1 << 2,	/* request WR completion */
+	CXGB4I_SKCB_FLAG_HDR_RCVD = 1 << 3,	/* recieved header pdu */
+	CXGB4I_SKCB_FLAG_DATA_RCVD = 1 << 4,	/*  recieved data pdu */
+	CXGB4I_SKCB_FLAG_STATUS_RCVD = 1 << 5,	/* recieved ddp status */
+};
+
+/*
+ * sge_opaque_hdr -
+ * Opaque version of structure the SGE stores at skb->head of TX_DATA packets
+ * and for which we must reserve space.
+ */
+struct sge_opaque_hdr {
+	void *dev;
+	dma_addr_t addr[MAX_SKB_FRAGS + 1];
+};
+
+/* for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */
+#define CXGB4I_TX_HEADER_LEN \
+	(sizeof(struct fw_ofld_tx_data_wr) + sizeof(struct sge_opaque_hdr))
+#define SKB_TX_HEADROOM	SKB_MAX_HEAD(CXGB4I_TX_HEADER_LEN)
+
+#endif	/* __CXGB4I_OFFLOAD_H__ */
+
diff --git a/drivers/scsi/cxgb4i/cxgb4i_snic.c b/drivers/scsi/cxgb4i/cxgb4i_snic.c
new file mode 100644
index 0000000..68cdae5
--- /dev/null
+++ b/drivers/scsi/cxgb4i/cxgb4i_snic.c
@@ -0,0 +1,260 @@
+/*
+ * cxgb4i_snic.c: Chelsio T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Karen Xie (kxie-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ * Written by: Rakesh Ranjan (rranjan-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ */
+
+#include <net/route.h>
+
+#include "cxgb4i.h"
+
+#define	DRV_MODULE_NAME		"cxgb4i"
+#define	DRV_MODULE_VERSION	"0.90"
+#define	DRV_MODULE_RELDATE	"04/08/2010"
+
+static char version[] =
+	"Chelsio T4 iSCSI driver " DRV_MODULE_NAME
+	" v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+
+MODULE_AUTHOR("Chelsio Communications");
+MODULE_DESCRIPTION("Chelsio T4 iSCSI driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+static LIST_HEAD(snic_list);
+static DEFINE_MUTEX(snic_rwlock);
+
+static void *cxgb4i_uld_add(const struct cxgb4_lld_info *linfo);
+static int cxgb4i_uld_rx_handler(void *handle, const __be64 *rsp,
+				const struct pkt_gl *pgl);
+static int cxgb4i_uld_state_change(void *handle, enum cxgb4_state state);
+
+static struct cxgb4i_snic *cxgb4i_snic_init(const struct cxgb4_lld_info *);
+static void cxgb4i_snic_cleanup(void);
+
+
+static struct cxgb4_uld_info cxgb4i_uld_info = {
+	.name = "cxgb4i",
+	.add = cxgb4i_uld_add,
+	.rx_handler = cxgb4i_uld_rx_handler,
+	.state_change = cxgb4i_uld_state_change,
+};
+
+
+struct cxgbi_hba *cxgb4i_hba_find_by_netdev(struct net_device *dev)
+{
+	int i;
+	struct cxgb4i_snic *snic = NULL;;
+
+	if (dev->priv_flags & IFF_802_1Q_VLAN)
+		dev = vlan_dev_real_dev(dev);
+
+	mutex_lock(&snic_rwlock);
+	list_for_each_entry(snic, &snic_list, list_head) {
+		for (i = 0; i < snic->hba_cnt; i++) {
+			if (snic->hba[i]->ndev == dev) {
+				mutex_unlock(&snic_rwlock);
+				return snic->hba[i];
+			}
+		}
+	}
+	mutex_unlock(&snic_rwlock);
+	return NULL;
+}
+
+struct cxgb4i_snic *cxgb4i_find_snic(struct net_device *dev, __be32 ipaddr)
+{
+	struct flowi fl;
+	struct rtable *rt;
+	struct net_device *sdev = NULL;
+	struct cxgb4i_snic *snic = NULL, *tmp;
+	int err, i;
+
+	memset(&fl, 0, sizeof(fl));
+	fl.nl_u.ip4_u.daddr = ipaddr;
+
+	err = ip_route_output_key(dev ? dev_net(dev) : &init_net, &rt, &fl);
+	if (err)
+		goto out;
+
+	sdev = (&rt->u.dst)->dev;
+	mutex_lock(&snic_rwlock);
+	list_for_each_entry_safe(snic, tmp, &snic_list, list_head) {
+		if (snic) {
+			for (i = 0; i < snic->lldi.nports; i++) {
+				if (sdev == snic->lldi.ports[i]) {
+					mutex_unlock(&snic_rwlock);
+					return snic;
+				}
+			}
+		}
+	}
+	mutex_unlock(&snic_rwlock);
+
+out:
+	snic = NULL;
+	return snic;
+}
+
+void cxgb4i_snic_add(struct list_head *list_head)
+{
+	mutex_lock(&snic_rwlock);
+	list_add_tail(list_head, &snic_list);
+	mutex_unlock(&snic_rwlock);
+}
+
+struct cxgb4i_snic *cxgb4i_snic_init(const struct cxgb4_lld_info *linfo)
+{
+	struct cxgb4i_snic *snic;
+	int i;
+
+	snic = kzalloc(sizeof(*snic), GFP_KERNEL);
+	if (snic) {
+
+		spin_lock_init(&snic->lock);
+		snic->lldi = *linfo;
+		snic->hba_cnt = snic->lldi.nports;
+		snic->cdev.dd_data = snic;
+		snic->cdev.pdev = snic->lldi.pdev;
+		snic->cdev.skb_tx_headroom = SKB_MAX_HEAD(CXGB4I_TX_HEADER_LEN);
+
+		cxgb4i_iscsi_init();
+		cxgbi_pdu_init(&snic->cdev);
+		cxgb4i_ddp_init(snic);
+		cxgb4i_ofld_init(snic);
+
+		for (i = 0; i < snic->hba_cnt; i++) {
+			snic->hba[i] = cxgb4i_hba_add(snic,
+						snic->lldi.ports[i]);
+			if (!snic->hba[i]) {
+				kfree(snic);
+				snic = ERR_PTR(-ENOMEM);
+				goto out;
+			}
+		}
+		cxgb4i_snic_add(&snic->list_head);
+	} else
+out :
+	snic = ERR_PTR(-ENOMEM);
+
+	return snic;
+}
+
+void cxgb4i_snic_cleanup(void)
+{
+	struct cxgb4i_snic *snic, *tmp;
+	int i;
+
+	mutex_lock(&snic_rwlock);
+	list_for_each_entry_safe(snic, tmp, &snic_list, list_head) {
+		list_del(&snic->list_head);
+
+		for (i = 0; i < snic->hba_cnt; i++) {
+			if (snic->hba[i]) {
+				cxgb4i_hba_remove(snic->hba[i]);
+				snic->hba[i] = NULL;
+			}
+		}
+		cxgb4i_ofld_cleanup(snic);
+		cxgb4i_ddp_cleanup(snic);
+		cxgbi_pdu_cleanup(&snic->cdev);
+		cxgbi_log_info("snic 0x%p, %u scsi hosts removed.\n",
+				snic, snic->hba_cnt);
+
+		kfree(snic);
+	}
+	mutex_unlock(&snic_rwlock);
+	cxgb4i_iscsi_cleanup();
+}
+
+static void *cxgb4i_uld_add(const struct cxgb4_lld_info *linfo)
+{
+	struct cxgb4i_snic *snic;
+
+	cxgbi_log_info("%s", version);
+
+	snic = cxgb4i_snic_init(linfo);
+	if (!snic)
+		goto out;
+out:
+	return snic;
+}
+
+static int cxgb4i_uld_rx_handler(void *handle, const __be64 *rsp,
+				const struct pkt_gl *pgl)
+{
+	struct cxgb4i_snic *snic = handle;
+	struct sk_buff *skb;
+	const struct cpl_act_establish *rpl;
+	unsigned int opcode;
+
+	if (pgl == NULL) {
+		unsigned int len = 64 - sizeof(struct rsp_ctrl) - 8;
+
+		skb = alloc_skb(256, GFP_ATOMIC);
+		if (!skb)
+			goto nomem;
+		__skb_put(skb, len);
+		skb_copy_to_linear_data(skb, &rsp[1], len);
+
+	} else if (pgl == CXGB4_MSG_AN) {
+
+		return 0;
+
+	} else {
+
+		skb = cxgb4_pktgl_to_skb(pgl, 256, 256);
+		if (unlikely(!skb))
+			goto nomem;
+	}
+
+	rpl = cplhdr(skb);
+	opcode = rpl->ot.opcode;
+
+	cxgbi_api_debug("snic %p, opcode 0x%x, skb %p\n",
+			 snic, opcode, skb);
+
+	BUG_ON(!snic->handlers[opcode]);
+
+	if (snic->handlers[opcode]) {
+		snic->handlers[opcode](snic, skb);
+	} else
+		cxgbi_log_error("No handler for opcode 0x%x\n",
+				opcode);
+
+	return 0;
+
+nomem:
+	cxgbi_api_debug("OOM bailing out\n");
+	return 1;
+}
+
+static int cxgb4i_uld_state_change(void *handle, enum cxgb4_state state)
+{
+	return 0;
+}
+
+static int __init cxgb4i_init_module(void)
+{
+	cxgb4_register_uld(CXGB4_ULD_ISCSI, &cxgb4i_uld_info);
+
+	return 0;
+}
+
+static void __exit cxgb4i_exit_module(void)
+{
+
+	cxgb4_unregister_uld(CXGB4_ULD_ISCSI);
+	cxgb4i_snic_cleanup();
+}
+
+module_init(cxgb4i_init_module);
+module_exit(cxgb4i_exit_module);
+
-- 
1.6.6.1

-- 
You received this message because you are subscribed to the Google Groups "open-iscsi" group.
To post to this group, send email to open-iscsi-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
To unsubscribe from this group, send email to open-iscsi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit this group at http://groups.google.com/group/open-iscsi?hl=en.

^ permalink raw reply related

* [PATCH 1/3] cxgb4i_v3: add build support
From: Rakesh Ranjan @ 2010-05-15 17:24 UTC (permalink / raw)
  To: NETDEVML, SCSIDEVML, OISCSIML
  Cc: LKML, Karen Xie, David Miller, James Bottomley, Mike Christie,
	Anish Bhatt, Rakesh Ranjan, Rakesh Ranjan
In-Reply-To: <1273944249-311-1-git-send-email-rakesh-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>

From: Rakesh Ranjan <rranjan-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>


Signed-off-by: Rakesh Ranjan <rakesh-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
---
 drivers/scsi/Kconfig        |    1 +
 drivers/scsi/Makefile       |    1 +
 drivers/scsi/cxgb4i/Kbuild  |    4 ++++
 drivers/scsi/cxgb4i/Kconfig |    7 +++++++
 4 files changed, 13 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/cxgb4i/Kbuild
 create mode 100644 drivers/scsi/cxgb4i/Kconfig

diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 75f2336..fc3810a 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -371,6 +371,7 @@ config ISCSI_TCP
 	 http://open-iscsi.org
 
 source "drivers/scsi/cxgb3i/Kconfig"
+source "drivers/scsi/cxgb4i/Kconfig"
 source "drivers/scsi/bnx2i/Kconfig"
 source "drivers/scsi/be2iscsi/Kconfig"
 
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 1c7ac49..46dcdc8 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -133,6 +133,7 @@ obj-$(CONFIG_SCSI_STEX)		+= stex.o
 obj-$(CONFIG_SCSI_MVSAS)	+= mvsas/
 obj-$(CONFIG_PS3_ROM)		+= ps3rom.o
 obj-$(CONFIG_SCSI_CXGB3_ISCSI)	+= libiscsi.o libiscsi_tcp.o cxgb3i/
+obj-$(CONFIG_SCSI_CXGB4_ISCSI)	+= libiscsi.o libiscsi_tcp.o cxgb4i/
 obj-$(CONFIG_SCSI_BNX2_ISCSI)	+= libiscsi.o bnx2i/
 obj-$(CONFIG_BE2ISCSI)		+= libiscsi.o be2iscsi/
 obj-$(CONFIG_SCSI_PMCRAID)	+= pmcraid.o
diff --git a/drivers/scsi/cxgb4i/Kbuild b/drivers/scsi/cxgb4i/Kbuild
new file mode 100644
index 0000000..1cb87b9
--- /dev/null
+++ b/drivers/scsi/cxgb4i/Kbuild
@@ -0,0 +1,4 @@
+EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb4
+
+cxgb4i-y := libcxgbi.o cxgb4i_snic.o cxgb4i_iscsi.o cxgb4i_offload.o cxgb4i_ddp.o
+obj-$(CONFIG_SCSI_CXGB4_ISCSI) += cxgb4i.o
diff --git a/drivers/scsi/cxgb4i/Kconfig b/drivers/scsi/cxgb4i/Kconfig
new file mode 100644
index 0000000..3f33dc2
--- /dev/null
+++ b/drivers/scsi/cxgb4i/Kconfig
@@ -0,0 +1,7 @@
+config SCSI_CXGB4_ISCSI
+	tristate "Chelsio T4 iSCSI support"
+	depends on CHELSIO_T4_DEPENDS
+	select CHELSIO_T4
+	select SCSI_ISCSI_ATTRS
+	---help---
+	This driver supports iSCSI offload for the Chelsio T4 series devices.
-- 
1.6.6.1

-- 
You received this message because you are subscribed to the Google Groups "open-iscsi" group.
To post to this group, send email to open-iscsi-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
To unsubscribe from this group, send email to open-iscsi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit this group at http://groups.google.com/group/open-iscsi?hl=en.

^ permalink raw reply related

* cxgb4i_v3.1 submission
From: Rakesh Ranjan @ 2010-05-15 17:24 UTC (permalink / raw)
  To: NETDEVML, SCSIDEVML, OISCSIML
  Cc: LKML, Karen Xie, David Miller, James Bottomley, Mike Christie,
	Anish Bhatt, Rakesh Ranjan


The following 3 patches add a new iscsi LLD driver cxgb4i to enable iscsi offload
support on Chelsio's new 1G and 10G cards. This is updated version of previous cxgb4i
patch. Please share you commnets after review.

Changes since cxgb4i_v3.1
1. Abastract libcxgbi library common part more properly.
2. Fixed few packet sequence calculation bugs.
3. compile-time initialization of cplhandlers
4. Removed the private mail address from patches from field


[PATCH 1/3] cxgb4i_v3: add build support
[PATCH 2/3] cxgb4i_v3: main driver files
[PATCH 3/3] cxgb4i_v3: iscsi and libcxgbi library for handling common part

Regards
Rakesh Ranjan

-- 
You received this message because you are subscribed to the Google Groups "open-iscsi" group.
To post to this group, send email to open-iscsi-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
To unsubscribe from this group, send email to open-iscsi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit this group at http://groups.google.com/group/open-iscsi?hl=en.

^ permalink raw reply

* [PATCH 3/3] cxgb4i_v3: iscsi and libcxgbi library for handling common part
From: Rakesh Ranjan @ 2010-05-15 17:15 UTC (permalink / raw)
  To: NETDEVML, SCSIDEVML, OISCSIML
  Cc: LKML, Karen Xie, David Miller, James Bottomley, Mike Christie,
	Anish Bhatt, Rakesh Ranjan, Rakesh Ranjan
In-Reply-To: <1273943752-32486-3-git-send-email-rakesh-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>

From: Rakesh Ranjan <rranjan-UJ4WrezqVcvwEYdC/TKypOqkaFVsf6Qi@public.gmane.org>


Signed-off-by: Rakesh Ranjan <rakesh-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
---
 drivers/scsi/cxgb4i/cxgb4i_iscsi.c |  617 ++++++++++++++++++++++++++++++++++++
 drivers/scsi/cxgb4i/libcxgbi.c     |  589 ++++++++++++++++++++++++++++++++++
 drivers/scsi/cxgb4i/libcxgbi.h     |  430 +++++++++++++++++++++++++
 3 files changed, 1636 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/cxgb4i/cxgb4i_iscsi.c
 create mode 100644 drivers/scsi/cxgb4i/libcxgbi.c
 create mode 100644 drivers/scsi/cxgb4i/libcxgbi.h

diff --git a/drivers/scsi/cxgb4i/cxgb4i_iscsi.c b/drivers/scsi/cxgb4i/cxgb4i_iscsi.c
new file mode 100644
index 0000000..a10ab6d
--- /dev/null
+++ b/drivers/scsi/cxgb4i/cxgb4i_iscsi.c
@@ -0,0 +1,617 @@
+/*
+ * cxgb4i_iscsi.c: Chelsio T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Karen Xie (kxie-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ * Written by: Rakesh Ranjan (rranjan-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ */
+
+#include <linux/inet.h>
+#include <linux/crypto.h>
+#include <linux/if_vlan.h>
+#include <net/dst.h>
+#include <net/tcp.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi.h>
+#include <scsi/iscsi_proto.h>
+#include <scsi/libiscsi.h>
+#include <scsi/scsi_transport_iscsi.h>
+
+#include "cxgb4i.h"
+
+/*
+ * align pdu size to multiple of 512 for better performance
+ */
+#define cxgb4i_align_pdu_size(n) do { n = (n) & (~511); } while (0)
+
+static struct scsi_transport_template *cxgb4i_scsi_transport;
+static struct scsi_host_template cxgb4i_host_template;
+static struct iscsi_transport cxgb4i_iscsi_transport;
+
+struct cxgbi_hba *cxgb4i_hba_add(struct cxgb4i_snic *snic,
+					struct net_device *dev)
+{
+	struct cxgbi_hba *chba;
+	struct Scsi_Host *shost;
+	int err;
+
+	shost = iscsi_host_alloc(&cxgb4i_host_template, sizeof(*chba), 1);
+
+	if (!shost) {
+		cxgbi_log_info("snic 0x%p, ndev 0x%p, host alloc failed\n",
+				snic, dev);
+		return NULL;
+	}
+
+	shost->transportt = cxgb4i_scsi_transport;
+	shost->max_lun = CXGB4I_MAX_LUN;
+	shost->max_id = CXGB4I_MAX_TARGET;
+	shost->max_channel = 0;
+	shost->max_cmd_len = 16;
+
+	chba = iscsi_host_priv(shost);
+	cxgbi_log_debug("snic %p, cdev %p\n", snic, &snic->cdev);
+	chba->cdev = &snic->cdev;
+	chba->ndev = dev;
+	chba->shost = shost;
+
+	pci_dev_get(snic->lldi.pdev);
+	err = iscsi_host_add(shost, &snic->lldi.pdev->dev);
+	if (err) {
+		cxgbi_log_info("snic 0x%p, dev 0x%p, host add failed\n",
+				snic, dev);
+		goto pci_dev_put;
+	}
+
+	return chba;
+
+pci_dev_put:
+	pci_dev_put(snic->lldi.pdev);
+	scsi_host_put(shost);
+	return NULL;
+}
+
+void cxgb4i_hba_remove(struct cxgbi_hba *chba)
+{
+	iscsi_host_remove(chba->shost);
+	pci_dev_put(cxgb4i_get_snic(chba->cdev)->lldi.pdev);
+	iscsi_host_free(chba->shost);
+}
+
+static struct iscsi_endpoint *cxgb4i_ep_connect(struct Scsi_Host *shost,
+						struct sockaddr *dst_addr,
+						int non_blocking)
+{
+	struct iscsi_endpoint *iep;
+	struct cxgbi_endpoint *cep;
+	struct cxgbi_hba *hba = NULL;
+	struct cxgbi_sock *csk = NULL;
+	struct cxgb4i_snic *snic;
+	int err = 0;
+
+	if (shost)
+		hba = iscsi_host_priv(shost);
+
+	snic = cxgb4i_find_snic(hba ? hba->ndev : NULL,
+			((struct sockaddr_in *)dst_addr)->sin_addr.s_addr);
+	if (!snic) {
+		cxgbi_log_info("ep connect no snic\n");
+		err = -ENOSPC;
+		goto release_conn;
+	}
+
+	csk = cxgb4i_sock_create(snic);
+	if (!csk) {
+		cxgbi_log_info("ep connect OOM\n");
+		err = -ENOMEM;
+		goto release_conn;
+	}
+	err = cxgb4i_sock_connect(hba ? hba->ndev : NULL, csk,
+				(struct sockaddr_in *)dst_addr);
+	if (err < 0) {
+		cxgbi_log_info("ep connect failed\n");
+		goto release_conn;
+	}
+
+	hba = cxgb4i_hba_find_by_netdev(csk->dst->dev);
+	if (!hba) {
+		err = -ENOSPC;
+		cxgbi_log_info("Not going through cxgb4i device\n");
+		goto release_conn;
+	}
+
+	if (shost && hba != iscsi_host_priv(shost)) {
+		err = -ENOSPC;
+		cxgbi_log_info("Could not connect through request host %u\n",
+				shost->host_no);
+		goto release_conn;
+	}
+
+	if (cxgbi_sock_is_closing(csk)) {
+		err = -ENOSPC;
+		cxgbi_log_info("ep connect unable to connect\n");
+		goto release_conn;
+	}
+
+	iep = iscsi_create_endpoint(sizeof(*cep));
+	if (!iep) {
+		err = -ENOMEM;
+		cxgbi_log_info("iscsi alloc ep, OOM\n");
+		goto release_conn;
+	}
+
+	cep = iep->dd_data;
+	cep->csk = csk;
+	cep->chba = hba;
+
+	cxgbi_api_debug("iep 0x%p, cep 0x%p, csk 0x%p, hba 0x%p\n",
+			iep, cep, csk, hba);
+
+	return iep;
+
+release_conn:
+	cxgbi_api_debug("conn 0x%p failed, release\n", csk);
+	if (csk)
+		cxgb4i_sock_release(csk);
+
+	return ERR_PTR(err);
+}
+
+static int cxgb4i_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
+{
+	struct cxgbi_endpoint *cep = ep->dd_data;
+	struct cxgbi_sock *csk = cep->csk;
+
+	if (!cxgbi_sock_is_established(csk))
+		return 0;
+
+	return 1;
+}
+
+static void cxgb4i_ep_disconnect(struct iscsi_endpoint *ep)
+{
+	struct cxgbi_endpoint *cep = ep->dd_data;
+	struct cxgbi_conn *cconn = cep->cconn;
+
+	if (cconn && cconn->iconn) {
+		iscsi_suspend_tx(cconn->iconn);
+
+		write_lock_bh(&cep->csk->callback_lock);
+		cep->csk->user_data = NULL;
+		cconn->cep = NULL;
+		write_unlock_bh(&cep->csk->callback_lock);
+	}
+
+	cxgb4i_sock_release(cep->csk);
+	iscsi_destroy_endpoint(ep);
+}
+
+static struct iscsi_cls_session *
+cxgb4i_create_session(struct iscsi_endpoint *ep, u16 cmds_max, u16 qdepth,
+							u32 initial_cmdsn)
+{
+	struct cxgbi_endpoint *cep;
+	struct cxgbi_hba *chba;
+	struct Scsi_Host *shost;
+	struct iscsi_cls_session *cls_session;
+	struct iscsi_session *session;
+
+	if (!ep) {
+		cxgbi_log_error("missing endpoint\n");
+		return NULL;
+	}
+
+	cep = ep->dd_data;
+	chba = cep->chba;
+	shost = chba->shost;
+
+	BUG_ON(chba != iscsi_host_priv(shost));
+
+	cls_session = iscsi_session_setup(&cxgb4i_iscsi_transport, shost,
+					cmds_max, 0,
+					sizeof(struct iscsi_tcp_task) +
+					sizeof(struct cxgbi_task_data),
+					initial_cmdsn, ISCSI_MAX_TARGET);
+	if (!cls_session)
+		return NULL;
+
+	session = cls_session->dd_data;
+	if (iscsi_tcp_r2tpool_alloc(session))
+		goto remove_session;
+
+	return cls_session;
+
+remove_session:
+	iscsi_session_teardown(cls_session);
+	return NULL;
+}
+
+static void cxgb4i_destroy_session(struct iscsi_cls_session *cls_session)
+{
+	iscsi_tcp_r2tpool_free(cls_session->dd_data);
+	iscsi_session_teardown(cls_session);
+}
+
+static inline int cxgb4i_conn_max_xmit_dlength(struct iscsi_conn *conn)
+{
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	unsigned int max = max(512 * MAX_SKB_FRAGS, SKB_TX_HEADROOM);
+
+	max = min(cxgb4i_get_snic(cconn->chba->cdev)->tx_max_size, max);
+	if (conn->max_xmit_dlength)
+		conn->max_xmit_dlength = min(conn->max_xmit_dlength, max);
+	else
+		conn->max_xmit_dlength = max;
+	cxgb4i_align_pdu_size(conn->max_xmit_dlength);
+	return 0;
+}
+
+static inline int cxgb4i_conn_max_recv_dlength(struct iscsi_conn *conn)
+{
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	unsigned int max = cxgb4i_get_snic(cconn->chba->cdev)->rx_max_size;
+
+	cxgb4i_align_pdu_size(max);
+
+	if (conn->max_recv_dlength) {
+		if (conn->max_recv_dlength > max) {
+			cxgbi_log_error("MaxRecvDataSegmentLength %u too big."
+					" Need to be <= %u.\n",
+					conn->max_recv_dlength, max);
+			return -EINVAL;
+		}
+		conn->max_recv_dlength = min(conn->max_recv_dlength, max);
+		cxgb4i_align_pdu_size(conn->max_recv_dlength);
+	} else
+		conn->max_recv_dlength = max;
+
+	return 0;
+}
+
+static struct iscsi_cls_conn *
+cxgb4i_create_conn(struct iscsi_cls_session *cls_session, u32 cid)
+{
+	struct iscsi_cls_conn *cls_conn;
+	struct iscsi_conn *conn;
+	struct iscsi_tcp_conn *tcp_conn;
+	struct cxgbi_conn *cconn;
+
+	cls_conn = iscsi_tcp_conn_setup(cls_session, sizeof(*cconn), cid);
+	if (!cls_conn)
+		return NULL;
+
+	conn = cls_conn->dd_data;
+	tcp_conn = conn->dd_data;
+	cconn = tcp_conn->dd_data;
+
+	cconn->iconn = conn;
+	return cls_conn;
+}
+
+static int cxgb4i_bind_conn(struct iscsi_cls_session *cls_session,
+				struct iscsi_cls_conn *cls_conn,
+				u64 transport_eph, int is_leading)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct iscsi_endpoint *ep;
+	struct cxgbi_endpoint *cep;
+	struct cxgbi_sock *csk;
+	int err;
+
+	ep = iscsi_lookup_endpoint(transport_eph);
+	if (!ep)
+		return -EINVAL;
+
+	/*  setup ddp pagesize */
+	cep = ep->dd_data;
+	csk = cep->csk;
+	err = cxgb4i_ddp_setup_conn_host_pagesize(csk, csk->hwtid, 0);
+	if (err < 0)
+		return err;
+
+	err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
+	if (err)
+		return -EINVAL;
+
+	/*  calculate the tag idx bits needed for this conn based on cmds_max */
+	cconn->task_idx_bits = (__ilog2_u32(conn->session->cmds_max - 1)) + 1;
+
+	read_lock(&csk->callback_lock);
+	csk->user_data = conn;
+	cconn->chba = cep->chba;
+	cconn->cep = cep;
+	cep->cconn = cconn;
+	read_unlock(&csk->callback_lock);
+
+	cxgb4i_conn_max_xmit_dlength(conn);
+	cxgb4i_conn_max_recv_dlength(conn);
+
+	spin_lock_bh(&conn->session->lock);
+	sprintf(conn->portal_address, "%pI4", &csk->daddr.sin_addr.s_addr);
+	conn->portal_port = ntohs(csk->daddr.sin_port);
+	spin_unlock_bh(&conn->session->lock);
+
+	/*  init recv engine */
+	iscsi_tcp_hdr_recv_prep(tcp_conn);
+
+	return 0;
+}
+
+static int
+cxgb4i_get_conn_param(struct iscsi_cls_conn *cls_conn,
+			enum iscsi_param param, char *buff)
+{
+	struct iscsi_conn *iconn = cls_conn->dd_data;
+	int len;
+
+	switch (param) {
+	case ISCSI_PARAM_CONN_PORT:
+		spin_lock_bh(&iconn->session->lock);
+		len = sprintf(buff, "%hu\n", iconn->portal_port);
+		spin_unlock_bh(&iconn->session->lock);
+		break;
+	case ISCSI_PARAM_CONN_ADDRESS:
+		spin_lock_bh(&iconn->session->lock);
+		len = sprintf(buff, "%s\n", iconn->portal_address);
+		spin_unlock_bh(&iconn->session->lock);
+		break;
+	default:
+		return iscsi_conn_get_param(cls_conn, param, buff);
+	}
+	return len;
+}
+
+static int
+cxgb4i_set_conn_param(struct iscsi_cls_conn *cls_conn,
+			enum iscsi_param param, char *buf, int buflen)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+	struct iscsi_session *session = conn->session;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_sock *csk = cconn->cep->csk;
+	int value, err = 0;
+
+	switch (param) {
+	case ISCSI_PARAM_HDRDGST_EN:
+		err = iscsi_set_param(cls_conn, param, buf, buflen);
+		if (!err && conn->hdrdgst_en)
+			err = cxgb4i_ddp_setup_conn_digest(csk, csk->hwtid,
+							conn->hdrdgst_en,
+							conn->datadgst_en, 0);
+		break;
+	case ISCSI_PARAM_DATADGST_EN:
+		err = iscsi_set_param(cls_conn, param, buf, buflen);
+		if (!err && conn->datadgst_en)
+			err = cxgb4i_ddp_setup_conn_digest(csk, csk->hwtid,
+							conn->hdrdgst_en,
+							conn->datadgst_en, 0);
+		break;
+	case ISCSI_PARAM_MAX_R2T:
+		sscanf(buf, "%d", &value);
+		if (value <= 0 || !is_power_of_2(value))
+			return -EINVAL;
+		if (session->max_r2t == value)
+			break;
+		iscsi_tcp_r2tpool_free(session);
+		err = iscsi_set_param(cls_conn, param, buf, buflen);
+		if (!err && iscsi_tcp_r2tpool_alloc(session))
+			return -ENOMEM;
+	case ISCSI_PARAM_MAX_RECV_DLENGTH:
+		err = iscsi_set_param(cls_conn, param, buf, buflen);
+		if (!err)
+			err = cxgb4i_conn_max_recv_dlength(conn);
+		break;
+	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+		err = iscsi_set_param(cls_conn, param, buf, buflen);
+		if (!err)
+			err = cxgb4i_conn_max_xmit_dlength(conn);
+		break;
+	default:
+		return iscsi_set_param(cls_conn, param, buf, buflen);
+	}
+	return err;
+}
+
+static int
+cxgb4i_set_host_param(struct Scsi_Host *shost,
+			enum iscsi_host_param param, char *buff, int buflen)
+{
+	struct cxgbi_hba *chba = iscsi_host_priv(shost);
+
+	if (!chba->ndev) {
+		shost_printk(KERN_ERR, shost, "Could not set host param. "
+				"Netdev for host not set\n");
+		return -ENODEV;
+	}
+
+	cxgbi_api_debug("param %d, buff %s\n", param, buff);
+
+	switch (param) {
+	case ISCSI_HOST_PARAM_IPADDRESS:
+	{
+		__be32 addr = in_aton(buff);
+		cxgb4i_set_iscsi_ipv4(chba, addr);
+		return 0;
+	}
+
+	case ISCSI_HOST_PARAM_HWADDRESS:
+	case ISCSI_HOST_PARAM_NETDEV_NAME:
+		return 0;
+
+	default:
+		return iscsi_host_set_param(shost, param, buff, buflen);
+	}
+}
+
+static int
+cxgb4i_get_host_param(struct Scsi_Host *shost,
+			enum iscsi_host_param param, char *buff)
+{
+	struct cxgbi_hba *chba = iscsi_host_priv(shost);
+	int len = 0;
+
+	if (!chba->ndev) {
+		shost_printk(KERN_ERR, shost, "Could not set host param. "
+				"Netdev for host not set\n");
+		return -ENODEV;
+	}
+
+	cxgbi_api_debug("hba %s, param %d\n", chba->ndev->name, param);
+
+	switch (param) {
+	case ISCSI_HOST_PARAM_HWADDRESS:
+		len = sysfs_format_mac(buff, chba->ndev->dev_addr, 6);
+		break;
+	case ISCSI_HOST_PARAM_NETDEV_NAME:
+		len = sprintf(buff, "%s\n", chba->ndev->name);
+		break;
+	case ISCSI_HOST_PARAM_IPADDRESS:
+	{
+		__be32 addr;
+
+		addr = cxgb4i_get_iscsi_ipv4(chba);
+		len = sprintf(buff, "%pI4", &addr);
+		break;
+	}
+	default:
+		return iscsi_host_get_param(shost, param, buff);
+	}
+
+	return len;
+}
+
+static void cxgb4i_get_conn_stats(struct iscsi_cls_conn *cls_conn,
+				struct iscsi_stats *stats)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+
+	stats->txdata_octets = conn->txdata_octets;
+	stats->rxdata_octets = conn->rxdata_octets;
+	stats->scsicmd_pdus = conn->scsicmd_pdus_cnt;
+	stats->dataout_pdus = conn->dataout_pdus_cnt;
+	stats->scsirsp_pdus = conn->scsirsp_pdus_cnt;
+	stats->datain_pdus = conn->datain_pdus_cnt;
+	stats->r2t_pdus = conn->r2t_pdus_cnt;
+	stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
+	stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
+	stats->digest_err = 0;
+	stats->timeout_err = 0;
+	stats->custom_length = 1;
+	strcpy(stats->custom[0].desc, "eh_abort_cnt");
+	stats->custom[0].value = conn->eh_abort_cnt;
+}
+
+static struct scsi_host_template cxgb4i_host_template = {
+	.module				= THIS_MODULE,
+	.name				= "Chelsio T4 iSCSI initiator",
+	.proc_name			= "cxgb4i",
+	.queuecommand			= iscsi_queuecommand,
+	.change_queue_depth		= iscsi_change_queue_depth,
+	.can_queue			= CXGB4I_SCSI_HOST_QDEPTH,
+	.sg_tablesize			= SG_ALL,
+	.max_sectors			= 0xFFFF,
+	.cmd_per_lun			= ISCSI_DEF_CMD_PER_LUN,
+	.eh_abort_handler		= iscsi_eh_abort,
+	.eh_device_reset_handler	= iscsi_eh_device_reset,
+	.eh_target_reset_handler	= iscsi_eh_recover_target,
+	.target_alloc			= iscsi_target_alloc,
+	.use_clustering			= DISABLE_CLUSTERING,
+	.this_id			= -1,
+};
+
+#define	CXGB4I_CAPS	(CAP_RECOVERY_L0 | CAP_MULTI_R2T |	\
+			CAP_HDRDGST | CAP_DATADGST |		\
+			CAP_DIGEST_OFFLOAD | CAP_PADDING_OFFLOAD)
+#define	CXGB4I_PMASK	(ISCSI_MAX_RECV_DLENGTH | ISCSI_MAX_XMIT_DLENGTH | \
+			ISCSI_HDRDGST_EN | ISCSI_DATADGST_EN | \
+			ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T | \
+			ISCSI_IMM_DATA_EN | ISCSI_FIRST_BURST | \
+			ISCSI_MAX_BURST | ISCSI_PDU_INORDER_EN | \
+			ISCSI_DATASEQ_INORDER_EN | ISCSI_ERL | \
+			ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS | \
+			ISCSI_EXP_STATSN | ISCSI_PERSISTENT_PORT | \
+			ISCSI_PERSISTENT_ADDRESS | ISCSI_TARGET_NAME | \
+			ISCSI_TPGT | ISCSI_USERNAME | \
+			ISCSI_PASSWORD | ISCSI_USERNAME_IN | \
+			ISCSI_PASSWORD_IN | ISCSI_FAST_ABORT | \
+			ISCSI_ABORT_TMO | ISCSI_LU_RESET_TMO | \
+			ISCSI_TGT_RESET_TMO | ISCSI_PING_TMO | \
+			ISCSI_RECV_TMO | ISCSI_IFACE_NAME | \
+			ISCSI_INITIATOR_NAME)
+#define	CXGB4I_HPMASK	(ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS | \
+			ISCSI_HOST_INITIATOR_NAME | ISCSI_HOST_INITIATOR_NAME)
+
+static struct iscsi_transport cxgb4i_iscsi_transport = {
+	.owner				= THIS_MODULE,
+	.name				= "cxgb4i",
+	.caps				= CXGB4I_CAPS,
+	.param_mask			= CXGB4I_PMASK,
+	.host_param_mask		= CXGB4I_HPMASK,
+	.get_host_param			= cxgb4i_get_host_param,
+	.set_host_param			= cxgb4i_set_host_param,
+
+	.create_session			= cxgb4i_create_session,
+	.destroy_session		= cxgb4i_destroy_session,
+	.get_session_param		= iscsi_session_get_param,
+
+	.create_conn			= cxgb4i_create_conn,
+	.bind_conn			= cxgb4i_bind_conn,
+	.destroy_conn			= iscsi_tcp_conn_teardown,
+	.start_conn			= iscsi_conn_start,
+	.stop_conn			= iscsi_conn_stop,
+	.get_conn_param			= cxgb4i_get_conn_param,
+	.set_param			= cxgb4i_set_conn_param,
+	.get_stats			= cxgb4i_get_conn_stats,
+
+	.send_pdu			= iscsi_conn_send_pdu,
+
+	.init_task			= iscsi_tcp_task_init,
+	.xmit_task			= iscsi_tcp_task_xmit,
+	.cleanup_task			= cxgbi_cleanup_task,
+
+	.alloc_pdu			= cxgbi_conn_alloc_pdu,
+	.init_pdu			= cxgbi_conn_init_pdu,
+	.xmit_pdu			= cxgbi_conn_xmit_pdu,
+	.parse_pdu_itt			= cxgbi_parse_pdu_itt,
+
+	.ep_connect			= cxgb4i_ep_connect,
+	.ep_poll			= cxgb4i_ep_poll,
+	.ep_disconnect			= cxgb4i_ep_disconnect,
+
+	.session_recovery_timedout	= iscsi_session_recovery_timedout,
+};
+
+int cxgb4i_iscsi_init(void)
+{
+	cxgb4i_scsi_transport = iscsi_register_transport(
+					&cxgb4i_iscsi_transport);
+	if (!cxgb4i_scsi_transport) {
+		cxgbi_log_error("Could not register cxgb4i transport\n");
+		return -ENODATA;
+	}
+
+	return 0;
+}
+
+void cxgb4i_iscsi_cleanup(void)
+{
+	if (cxgb4i_scsi_transport) {
+		cxgbi_api_debug("cxgb4i transport 0x%p removed\n",
+				cxgb4i_scsi_transport);
+		iscsi_unregister_transport(&cxgb4i_iscsi_transport);
+	}
+}
+
diff --git a/drivers/scsi/cxgb4i/libcxgbi.c b/drivers/scsi/cxgb4i/libcxgbi.c
new file mode 100644
index 0000000..98f904b
--- /dev/null
+++ b/drivers/scsi/cxgb4i/libcxgbi.c
@@ -0,0 +1,589 @@
+/*
+ * libcxgbi.c: Chelsio common library for T3/T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Karen Xie (kxie-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ * Written by: Rakesh Ranjan (rranjan-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ */
+
+#include <linux/skbuff.h>
+#include <linux/crypto.h>
+#include <linux/scatterlist.h>
+#include <linux/pci.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_host.h>
+
+#include "libcxgbi.h"
+
+/* always allocate rooms for AHS */
+#define SKB_TX_PDU_HEADER_LEN	\
+	(sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE)
+
+/*
+ * pdu receive, interact with libiscsi_tcp
+ */
+static inline int read_pdu_skb(struct iscsi_conn *conn, struct sk_buff *skb,
+			       unsigned int offset, int offloaded)
+{
+	int status = 0;
+	int bytes_read;
+
+	bytes_read = iscsi_tcp_recv_skb(conn, skb, offset, offloaded, &status);
+	switch (status) {
+	case ISCSI_TCP_CONN_ERR:
+		return -EIO;
+	case ISCSI_TCP_SUSPENDED:
+		/* no transfer - just have caller flush queue */
+		return bytes_read;
+	case ISCSI_TCP_SKB_DONE:
+		/*
+		 * pdus should always fit in the skb and we should get
+		 * segment done notifcation.
+		 */
+		iscsi_conn_printk(KERN_ERR, conn, "Invalid pdu or skb.");
+		return -EFAULT;
+	case ISCSI_TCP_SEGMENT_DONE:
+		return bytes_read;
+	default:
+		iscsi_conn_printk(KERN_ERR, conn, "Invalid iscsi_tcp_recv_skb "
+				  "status %d\n", status);
+		return -EINVAL;
+	}
+}
+
+int cxgbi_conn_read_bhs_pdu_skb(struct iscsi_conn *conn,
+					struct sk_buff *skb)
+{
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_device *cdev = cconn->chba->cdev;
+
+	int rc;
+
+	cxgbi_rx_debug("conn 0x%p, skb 0x%p, len %u, flag 0x%x.\n",
+			conn, skb, skb->len, cdev->get_skb_ulp_mode(skb));
+
+	if (!iscsi_tcp_recv_segment_is_hdr(tcp_conn)) {
+		iscsi_conn_failure(conn, ISCSI_ERR_PROTO);
+		return -EIO;
+	}
+
+	if (conn->hdrdgst_en && (cdev->get_skb_ulp_mode(skb)
+				& ULP2_FLAG_HCRC_ERROR)) {
+		iscsi_conn_failure(conn, ISCSI_ERR_HDR_DGST);
+		return -EIO;
+	}
+
+	rc = read_pdu_skb(conn, skb, 0, 0);
+	if (rc <= 0)
+		return rc;
+
+	return 0;
+}
+
+int cxgbi_conn_read_data_pdu_skb(struct iscsi_conn *conn,
+				    struct sk_buff *skb)
+{
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_device *cdev = cconn->chba->cdev;
+	bool offloaded = 0;
+	unsigned int offset = 0;
+	int rc;
+
+	cxgbi_rx_debug("conn 0x%p, skb 0x%p, len %u, flag 0x%x.\n",
+			conn, skb, skb->len, cdev->get_skb_ulp_mode(skb));
+
+	if (conn->datadgst_en &&
+		(cdev->get_skb_ulp_mode(skb) & ULP2_FLAG_DCRC_ERROR)) {
+		iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST);
+		return -EIO;
+	}
+
+	if (iscsi_tcp_recv_segment_is_hdr(tcp_conn))
+		return 0;
+
+	if (conn->hdrdgst_en)
+		offset = ISCSI_DIGEST_SIZE;
+
+	if (cdev->get_skb_ulp_mode(skb) & ULP2_FLAG_DATA_DDPED) {
+		cxgbi_rx_debug("skb 0x%p, opcode 0x%x, data %u, ddp'ed, "
+				"itt 0x%x.\n",
+				skb,
+				tcp_conn->in.hdr->opcode & ISCSI_OPCODE_MASK,
+				tcp_conn->in.datalen,
+				ntohl(tcp_conn->in.hdr->itt));
+		offloaded = 1;
+	} else {
+		cxgbi_rx_debug("skb 0x%p, opcode 0x%x, data %u, NOT ddp'ed, "
+				"itt 0x%x.\n",
+				skb,
+				tcp_conn->in.hdr->opcode & ISCSI_OPCODE_MASK,
+				tcp_conn->in.datalen,
+				ntohl(tcp_conn->in.hdr->itt));
+	}
+
+	rc = read_pdu_skb(conn, skb, 0, offloaded);
+	if (rc < 0)
+		return rc;
+	else
+		return 0;
+}
+
+static int sgl_seek_offset(struct scatterlist *sgl, unsigned int sgcnt,
+				unsigned int offset, unsigned int *off,
+				struct scatterlist **sgp)
+{
+	int i;
+	struct scatterlist *sg;
+
+	for_each_sg(sgl, sg, sgcnt, i) {
+		if (offset < sg->length) {
+			*off = offset;
+			*sgp = sg;
+			return 0;
+		}
+		offset -= sg->length;
+	}
+	return -EFAULT;
+}
+
+static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset,
+				unsigned int dlen, skb_frag_t *frags,
+				int frag_max)
+{
+	unsigned int datalen = dlen;
+	unsigned int sglen = sg->length - sgoffset;
+	struct page *page = sg_page(sg);
+	int i;
+
+	i = 0;
+	do {
+		unsigned int copy;
+
+		if (!sglen) {
+			sg = sg_next(sg);
+			if (!sg) {
+				cxgbi_log_error("sg NULL, len %u/%u.\n",
+								datalen, dlen);
+				return -EINVAL;
+			}
+			sgoffset = 0;
+			sglen = sg->length;
+			page = sg_page(sg);
+
+		}
+		copy = min(datalen, sglen);
+		if (i && page == frags[i - 1].page &&
+		    sgoffset + sg->offset ==
+			frags[i - 1].page_offset + frags[i - 1].size) {
+			frags[i - 1].size += copy;
+		} else {
+			if (i >= frag_max) {
+				cxgbi_log_error("too many pages %u, "
+						 "dlen %u.\n", frag_max, dlen);
+				return -EINVAL;
+			}
+
+			frags[i].page = page;
+			frags[i].page_offset = sg->offset + sgoffset;
+			frags[i].size = copy;
+			i++;
+		}
+		datalen -= copy;
+		sgoffset += copy;
+		sglen -= copy;
+	} while (datalen);
+
+	return i;
+}
+
+int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 opcode)
+{
+	struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_device *cdev = cconn->chba->cdev;
+	struct iscsi_conn *conn = task->conn;
+	struct iscsi_tcp_task *tcp_task = task->dd_data;
+	struct cxgbi_task_data *tdata = task->dd_data + sizeof(*tcp_task);
+	struct scsi_cmnd *sc = task->sc;
+	int headroom = SKB_TX_PDU_HEADER_LEN;
+
+	tcp_task->dd_data = tdata;
+	task->hdr = NULL;
+
+	/* write command, need to send data pdus */
+	if (cdev->skb_extra_headroom && (opcode == ISCSI_OP_SCSI_DATA_OUT ||
+	    (opcode == ISCSI_OP_SCSI_CMD &&
+	    (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_TO_DEVICE))))
+		headroom += min(cdev->skb_extra_headroom,
+					conn->max_xmit_dlength);
+
+	tdata->skb = alloc_skb(cdev->skb_tx_headroom + headroom, GFP_ATOMIC);
+	if (!tdata->skb)
+		return -ENOMEM;
+	skb_reserve(tdata->skb, cdev->skb_tx_headroom);
+
+	cxgbi_tx_debug("task 0x%p, opcode 0x%x, skb 0x%p.\n",
+			task, opcode, tdata->skb);
+
+	task->hdr = (struct iscsi_hdr *)tdata->skb->data;
+	task->hdr_max = SKB_TX_PDU_HEADER_LEN;
+
+	/* data_out uses scsi_cmd's itt */
+	if (opcode != ISCSI_OP_SCSI_DATA_OUT)
+		cxgbi_reserve_itt(task, &task->hdr->itt);
+
+	return 0;
+}
+
+int cxgbi_conn_init_pdu(struct iscsi_task *task, unsigned int offset,
+			      unsigned int count)
+{
+	struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_device *cdev = cconn->chba->cdev;
+	struct iscsi_conn *conn = task->conn;
+	struct iscsi_tcp_task *tcp_task = task->dd_data;
+	struct cxgbi_task_data *tdata = tcp_task->dd_data;
+	struct sk_buff *skb = tdata->skb;
+	unsigned int datalen = count;
+	int i, padlen = iscsi_padding(count);
+	struct page *pg;
+
+	cxgbi_tx_debug("task 0x%p,0x%p, offset %u, count %u, skb 0x%p.\n",
+			task, task->sc, offset, count, skb);
+
+	skb_put(skb, task->hdr_len);
+	cdev->tx_skb_setmode(skb, conn->hdrdgst_en,
+				datalen ? conn->datadgst_en : 0);
+	if (!count)
+		return 0;
+
+	if (task->sc) {
+		struct scsi_data_buffer *sdb = scsi_out(task->sc);
+		struct scatterlist *sg = NULL;
+		int err;
+
+		tdata->offset = offset;
+		tdata->count = count;
+		err = sgl_seek_offset(sdb->table.sgl, sdb->table.nents,
+					tdata->offset, &tdata->sgoffset, &sg);
+		if (err < 0) {
+			cxgbi_log_warn("tpdu, sgl %u, bad offset %u/%u.\n",
+					sdb->table.nents, tdata->offset,
+					sdb->length);
+			return err;
+		}
+		err = sgl_read_to_frags(sg, tdata->sgoffset, tdata->count,
+					tdata->frags, MAX_PDU_FRAGS);
+		if (err < 0) {
+			cxgbi_log_warn("tpdu, sgl %u, bad offset %u + %u.\n",
+					sdb->table.nents, tdata->offset,
+					tdata->count);
+			return err;
+		}
+		tdata->nr_frags = err;
+
+		if (tdata->nr_frags > MAX_SKB_FRAGS ||
+		    (padlen && tdata->nr_frags == MAX_SKB_FRAGS)) {
+			char *dst = skb->data + task->hdr_len;
+			skb_frag_t *frag = tdata->frags;
+
+			/* data fits in the skb's headroom */
+			for (i = 0; i < tdata->nr_frags; i++, frag++) {
+				char *src = kmap_atomic(frag->page,
+							KM_SOFTIRQ0);
+
+				memcpy(dst, src+frag->page_offset, frag->size);
+				dst += frag->size;
+				kunmap_atomic(src, KM_SOFTIRQ0);
+			}
+			if (padlen) {
+				memset(dst, 0, padlen);
+				padlen = 0;
+			}
+			skb_put(skb, count + padlen);
+		} else {
+			/* data fit into frag_list */
+			for (i = 0; i < tdata->nr_frags; i++)
+				get_page(tdata->frags[i].page);
+
+			memcpy(skb_shinfo(skb)->frags, tdata->frags,
+				sizeof(skb_frag_t) * tdata->nr_frags);
+			skb_shinfo(skb)->nr_frags = tdata->nr_frags;
+			skb->len += count;
+			skb->data_len += count;
+			skb->truesize += count;
+		}
+
+	} else {
+		pg = virt_to_page(task->data);
+
+		get_page(pg);
+		skb_fill_page_desc(skb, 0, pg, offset_in_page(task->data),
+					count);
+		skb->len += count;
+		skb->data_len += count;
+		skb->truesize += count;
+	}
+
+	if (padlen) {
+		i = skb_shinfo(skb)->nr_frags;
+		get_page(cdev->pad_page);
+		skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
+					cdev->pad_page, 0, padlen);
+
+		skb->data_len += padlen;
+		skb->truesize += padlen;
+		skb->len += padlen;
+	}
+
+	return 0;
+}
+
+int cxgbi_conn_xmit_pdu(struct iscsi_task *task)
+{
+	struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_device *cdev = cconn->chba->cdev;
+	struct iscsi_tcp_task *tcp_task = task->dd_data;
+	struct cxgbi_task_data *tdata = tcp_task->dd_data;
+	struct sk_buff *skb = tdata->skb;
+	unsigned int datalen;
+	int err;
+
+	if (!skb)
+		return 0;
+
+	datalen = skb->data_len;
+	tdata->skb = NULL;
+	err = cdev->sock_send_pdus(cconn->cep->csk, skb);
+	if (err > 0) {
+		int pdulen = err;
+
+		cxgbi_tx_debug("task 0x%p, skb 0x%p, len %u/%u, rv %d.\n",
+				task, skb, skb->len, skb->data_len, err);
+
+		if (task->conn->hdrdgst_en)
+			pdulen += ISCSI_DIGEST_SIZE;
+		if (datalen && task->conn->datadgst_en)
+			pdulen += ISCSI_DIGEST_SIZE;
+
+		task->conn->txdata_octets += pdulen;
+		return 0;
+	}
+
+	if (err == -EAGAIN || err == -ENOBUFS) {
+		/* reset skb to send when we are called again */
+		tdata->skb = skb;
+		return err;
+	}
+
+	kfree_skb(skb);
+	cxgbi_tx_debug("itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n",
+			task->itt, skb, skb->len, skb->data_len, err);
+	iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err);
+	iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED);
+	return err;
+}
+
+int cxgbi_pdu_init(struct cxgbi_device *cdev)
+{
+	if (cdev->skb_tx_headroom > (512 * MAX_SKB_FRAGS))
+		cdev->skb_extra_headroom = cdev->skb_tx_headroom;
+	cdev->pad_page = alloc_page(GFP_KERNEL);
+	if (cdev->pad_page)
+		return -ENOMEM;
+	memset(page_address(cdev->pad_page), 0, PAGE_SIZE);
+	return 0;
+
+	/*
+	if (SKB_TX_HEADROOM > (512 * MAX_SKB_FRAGS))
+		skb_extra_headroom = SKB_TX_HEADROOM;
+	pad_page = alloc_page(GFP_KERNEL);
+	if (!pad_page)
+		return -ENOMEM;
+	memset(page_address(pad_page), 0, PAGE_SIZE);
+	return 0;*/
+}
+
+void cxgbi_pdu_cleanup(struct cxgbi_device *cdev)
+{
+	if (cdev->pad_page) {
+		__free_page(cdev->pad_page);
+		cdev->pad_page = NULL;
+	}
+}
+
+void cxgbi_conn_tx_open(struct cxgbi_sock *csk)
+{
+	struct iscsi_conn *conn = csk->user_data;
+
+	if (conn) {
+		cxgbi_tx_debug("cn 0x%p, cid %d.\n", csk, conn->id);
+		iscsi_conn_queue_work(conn);
+	}
+}
+
+int cxgbi_sock_get_port(struct cxgbi_sock *csk)
+{
+	unsigned int start;
+	int idx;
+
+	if (!csk->cdev->pmap)
+		goto error_out;
+
+	if (csk->saddr.sin_port) {
+		cxgbi_log_error("connect, sin_port none ZERO %u\n",
+				ntohs(csk->saddr.sin_port));
+		return -EADDRINUSE;
+	}
+
+	spin_lock_bh(&csk->cdev->pmap->lock);
+	start = idx = csk->cdev->pmap->next;
+
+	do {
+		if (++idx >= csk->cdev->pmap->max_connect)
+			idx = 0;
+		if (!csk->cdev->pmap->port_csk[idx]) {
+			csk->saddr.sin_port =
+				htons(csk->cdev->pmap->sport_base + idx);
+			csk->cdev->pmap->next = idx;
+			csk->cdev->pmap->port_csk[idx] = csk;
+			spin_unlock_bh(&csk->cdev->pmap->lock);
+
+			cxgbi_conn_debug("reserved port %u\n",
+					csk->cdev->pmap->sport_base + idx);
+
+			return 0;
+		}
+	} while (idx != start);
+	spin_unlock_bh(&csk->cdev->pmap->lock);
+
+error_out:
+	return -EADDRNOTAVAIL;
+}
+
+void cxgbi_sock_put_port(struct cxgbi_sock *csk)
+{
+	if (csk->saddr.sin_port) {
+		int idx = ntohs(csk->saddr.sin_port) -
+			csk->cdev->pmap->sport_base;
+
+		csk->saddr.sin_port = 0;
+		if (idx < 0 || idx >= csk->cdev->pmap->max_connect)
+			return;
+
+		spin_lock_bh(&csk->cdev->pmap->lock);
+		csk->cdev->pmap->port_csk[idx] = NULL;
+		spin_unlock_bh(&csk->cdev->pmap->lock);
+
+		cxgbi_conn_debug("released port %u\n",
+				csk->cdev->pmap->sport_base + idx);
+	}
+}
+
+void cxgbi_release_itt(struct iscsi_task *task, itt_t hdr_itt)
+{
+	struct scsi_cmnd *sc = task->sc;
+	struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_device *cdev = cconn->chba->cdev;
+	struct cxgbi_tag_format *tformat = &cdev->tag_format;
+	u32 tag = ntohl((__force u32)hdr_itt);
+
+	cxgbi_tag_debug("release tag 0x%x.\n", tag);
+
+	if (sc &&
+		(scsi_bidi_cmnd(sc) ||
+		 sc->sc_data_direction == DMA_FROM_DEVICE) &&
+			cxgbi_is_ddp_tag(tformat, tag))
+		cdev->ddp_tag_release(cdev, tag);
+}
+
+
+int cxgbi_reserve_itt(struct iscsi_task *task, itt_t *hdr_itt)
+{
+	struct scsi_cmnd *sc = task->sc;
+	struct iscsi_conn *conn = task->conn;
+	struct iscsi_session *sess = conn->session;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_device *cdev = cconn->chba->cdev;
+	struct cxgbi_tag_format *tformat = &cdev->tag_format;
+	u32 sw_tag = (sess->age << cconn->task_idx_bits) | task->itt;
+	u32 tag;
+	int err = -EINVAL;
+
+	if (sc &&
+		(scsi_bidi_cmnd(sc) ||
+		 sc->sc_data_direction == DMA_FROM_DEVICE) &&
+			cxgbi_sw_tag_usable(tformat, sw_tag)) {
+
+		struct cxgbi_sock *csk = cconn->cep->csk;
+		struct cxgbi_gather_list *gl;
+
+		gl = cdev->ddp_make_gl(scsi_in(sc)->length,
+					scsi_in(sc)->table.sgl,
+					scsi_in(sc)->table.nents,
+					cdev->pdev, GFP_ATOMIC);
+		if (gl) {
+			tag = sw_tag;
+			err = cdev->ddp_tag_reserve(cdev, csk->hwtid,
+							tformat, &tag,
+							gl, GFP_ATOMIC);
+			if (err < 0)
+				cdev->ddp_release_gl(gl, cdev->pdev);
+		}
+	}
+	if (err < 0)
+		tag = cxgbi_set_non_ddp_tag(tformat, sw_tag);
+	/*  the itt need to sent in big-endian order */
+	*hdr_itt = (__force itt_t)htonl(tag);
+
+	cxgbi_tag_debug("new sc 0x%p tag 0x%x/0x%x (itt 0x%x, age 0x%x).\n",
+			sc, tag, *hdr_itt, task->itt, sess->age);
+	return 0;
+}
+
+
+void cxgbi_parse_pdu_itt(struct iscsi_conn *conn, itt_t itt,
+				int *idx, int *age)
+{
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct cxgbi_conn *cconn = tcp_conn->dd_data;
+	struct cxgbi_device *cdev = cconn->chba->cdev;
+	u32 tag = ntohl((__force u32) itt);
+	u32 sw_bits;
+
+	sw_bits = cxgbi_tag_nonrsvd_bits(&cdev->tag_format, tag);
+	if (idx)
+		*idx = sw_bits & ((1 << cconn->task_idx_bits) - 1);
+	if (age)
+		*age = (sw_bits >> cconn->task_idx_bits) & ISCSI_AGE_MASK;
+
+	cxgbi_tag_debug("parse tag 0x%x/0x%x, sw 0x%x, itt 0x%x, age 0x%x.\n",
+			tag, itt, sw_bits, idx ? *idx : 0xFFFFF,
+			age ? *age : 0xFF);
+}
+
+void cxgbi_cleanup_task(struct iscsi_task *task)
+{
+	struct cxgbi_task_data *tdata = task->dd_data +
+				sizeof(struct iscsi_tcp_task);
+
+	/*  never reached the xmit task callout */
+	if (tdata->skb)
+		__kfree_skb(tdata->skb);
+	memset(tdata, 0, sizeof(*tdata));
+
+	cxgbi_release_itt(task, task->hdr_itt);
+	iscsi_tcp_cleanup_task(task);
+}
+
diff --git a/drivers/scsi/cxgb4i/libcxgbi.h b/drivers/scsi/cxgb4i/libcxgbi.h
new file mode 100644
index 0000000..058a9aa
--- /dev/null
+++ b/drivers/scsi/cxgb4i/libcxgbi.h
@@ -0,0 +1,430 @@
+/*
+ * libcxgbi.h: Chelsio common library for T3/T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Karen Xie (kxie-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ * Written by: Rakesh Ranjan (rranjan-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ */
+
+#ifndef	__LIBCXGBI_H__
+#define	__LIBCXGBI_H__
+
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/scatterlist.h>
+#include <linux/skbuff.h>
+#include <scsi/libiscsi_tcp.h>
+
+
+#define	cxgbi_log_error(fmt...)	printk(KERN_ERR "cxgbi: ERR! " fmt)
+#define cxgbi_log_warn(fmt...)	printk(KERN_WARNING "cxgbi: WARN! " fmt)
+#define cxgbi_log_info(fmt...)	printk(KERN_INFO "cxgbi: " fmt)
+#define cxgbi_debug_log(fmt, args...) \
+	printk(KERN_INFO "cxgbi: %s - " fmt, __func__ , ## args)
+
+
+#ifdef	__DEBUG_CXGB4I__
+#define	cxgbi_log_debug	cxgbi_debug_log
+#else
+#define cxgbi_log_debug(fmt...)
+#endif
+
+#ifdef __DEBUG_CXGB4I_TAG__
+#define cxgbi_tag_debug        cxgbi_log_debug
+#else
+#define cxgbi_tag_debug(fmt...)
+#endif
+
+#ifdef __DEBUG_CXGB4I_API__
+#define cxgbi_api_debug        cxgbi_log_debug
+#else
+#define cxgbi_api_debug(fmt...)
+#endif
+
+#ifdef __DEBUG_CXGB4I_CONN__
+#define cxgbi_conn_debug         cxgbi_log_debug
+#else
+#define cxgbi_conn_debug(fmt...)
+#endif
+
+#ifdef __DEBUG_CXGB4I_TX__
+#define cxgbi_tx_debug           cxgbi_log_debug
+#else
+#define cxgbi_tx_debug(fmt...)
+#endif
+
+#ifdef __DEBUG_CXGB4I_RX__
+#define cxgbi_rx_debug           cxgbi_log_debug
+#else
+#define cxgbi_rx_debug(fmt...)
+#endif
+
+#define	ISCSI_PDU_NONPAYLOAD_LEN	312 /* bhs(48) + ahs(256) + digest(8)*/
+#define ULP2_MAX_PKT_SIZE		16224
+#define ULP2_MAX_PDU_PAYLOAD	\
+	(ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_LEN)
+
+/* # of pages a pagepod can hold without needing another pagepod */
+#define PPOD_PAGES			4
+#define PPOD_PAGES_MAX			4
+#define PPOD_PAGES_SHIFT		2       /*  4 pages per pod */
+
+
+struct cxgbi_tag_format {
+	unsigned char sw_bits;
+	unsigned char rsvd_bits;
+	unsigned char rsvd_shift;
+	unsigned char filler[1];
+	unsigned int rsvd_mask;
+};
+
+struct cxgbi_gather_list {
+	unsigned int tag;
+	unsigned int length;
+	unsigned int offset;
+	unsigned int nelem;
+	struct page **pages;
+	dma_addr_t phys_addr[0];
+};
+
+struct cxgbi_sock {
+	struct net_device *egdev;
+	struct cxgbi_device *cdev;
+
+	unsigned long flags;
+	unsigned int qset;
+	unsigned int rss_qid;
+
+	unsigned int hwtid;
+	unsigned int atid;
+
+	unsigned int tx_chan;
+	unsigned int rx_chan;
+	unsigned int mss_idx;
+	unsigned int smac_idx;
+	unsigned char port_id;
+
+	void *l2t;
+
+	int wr_max_cred;
+	int wr_cred;
+	int wr_una_cred;
+
+	struct sk_buff *wr_pending_head;
+	struct sk_buff *wr_pending_tail;
+	struct sk_buff *cpl_close;
+	struct sk_buff *cpl_abort_req;
+	struct sk_buff *cpl_abort_rpl;
+	struct sk_buff *skb_ulp_lhdr;
+	spinlock_t lock;
+	atomic_t refcnt;
+	volatile unsigned int state;
+	struct sockaddr_in saddr;
+	struct sockaddr_in daddr;
+	struct dst_entry *dst;
+	struct sk_buff_head receive_queue;
+	struct sk_buff_head write_queue;
+	struct timer_list retry_timer;
+	int err;
+	rwlock_t callback_lock;
+	void *user_data;
+
+	u32 rcv_nxt;
+	u32 copied_seq;
+	u32 rcv_wup;
+	u32 snd_nxt;
+	u32 snd_una;
+	u32 write_seq;
+};
+
+enum cxgbi_sock_states{
+	CXGBI_CSK_ST_CONNECTING = 1,
+	CXGBI_CSK_ST_ESTABLISHED,
+	CXGBI_CSK_ST_ACTIVE_CLOSE,
+	CXGBI_CSK_ST_PASSIVE_CLOSE,
+	CXGBI_CSK_ST_CLOSE_WAIT_1,
+	CXGBI_CSK_ST_CLOSE_WAIT_2,
+	CXGBI_CSK_ST_ABORTING,
+	CXGBI_CSK_ST_CLOSED,
+};
+
+enum cxgbi_sock_flags {
+	CXGBI_CSK_FL_ABORT_RPL_RCVD,	/*received one ABORT_RPL_RSS message */
+	CXGBI_CSK_FL_ABORT_REQ_RCVD,	/*received one ABORT_REQ_RSS message */
+	CXGBI_CSK_FL_ABORT_RPL_PENDING,	/* expecting an abort reply */
+	CXGBI_CSK_FL_TX_DATA_SENT,	/* already sent a TX_DATA WR */
+	CXGBI_CSK_FL_ACTIVE_CLOSE_NEEDED,	/* need to be closed */
+	CXGBI_CSK_FL_OFFLOAD_DOWN,		/* offload function off */
+};
+
+static inline void cxgbi_sock_set_flag(struct cxgbi_sock *csk,
+					enum cxgbi_sock_flags flag)
+{
+	__set_bit(flag, &csk->flags);
+	cxgbi_conn_debug("csk 0x%p, set %d, state %u, flags 0x%lu\n",
+			csk, flag, csk->state, csk->flags);
+}
+
+static inline void cxgbi_sock_clear_flag(struct cxgbi_sock *csk,
+					enum cxgbi_sock_flags flag)
+{
+	__clear_bit(flag, &csk->flags);
+	cxgbi_conn_debug("csk 0x%p, clear %d, state %u, flags 0x%lu\n",
+			csk, flag, csk->state, csk->flags);
+}
+
+static inline int cxgbi_sock_flag(struct cxgbi_sock *csk,
+				enum cxgbi_sock_flags flag)
+{
+	if (csk == NULL)
+		return 0;
+
+	return test_bit(flag, &csk->flags);
+}
+
+static inline void cxgbi_sock_set_state(struct cxgbi_sock *csk, int state)
+{
+	csk->state = state;
+}
+
+static inline void cxgbi_sock_hold(struct cxgbi_sock *csk)
+{
+	atomic_inc(&csk->refcnt);
+}
+
+static inline void cxgbi_sock_put(struct cxgbi_sock *csk)
+{
+	if (atomic_dec_and_test(&csk->refcnt)) {
+		cxgbi_conn_debug("free csk 0x%p, state %u, flags 0x%lx\n",
+				csk, csk->state, csk->flags);
+		kfree(csk);
+	}
+}
+
+static inline unsigned int cxgbi_sock_is_closing(
+			const struct cxgbi_sock *csk)
+{
+	return csk->state >= CXGBI_CSK_ST_ACTIVE_CLOSE;
+}
+
+static inline unsigned int cxgbi_sock_is_established(
+				const struct cxgbi_sock *csk)
+{
+	return csk->state == CXGBI_CSK_ST_ESTABLISHED;
+}
+
+int cxgbi_sock_get_port(struct cxgbi_sock *);
+void cxgbi_sock_put_port(struct cxgbi_sock *);
+
+struct cxgbi_hba {
+	struct net_device *ndev;
+	struct Scsi_Host *shost;
+	struct cxgbi_device *cdev;
+	__be32 ipv4addr;
+};
+
+struct cxgbi_ports_map {
+	unsigned int max_connect;
+	unsigned short sport_base;
+	spinlock_t lock;
+	unsigned int next;
+	struct cxgbi_sock *port_csk[0];
+};
+
+struct cxgbi_device {
+	struct list_head list_head;
+	struct net_device *ndev;
+	struct pci_dev *pdev;
+	unsigned int skb_tx_headroom;
+	unsigned int skb_extra_headroom;
+	struct page *pad_page;
+
+	void (*tx_skb_setmode)(struct sk_buff *, int, int);
+	int (*sock_send_pdus)(struct cxgbi_sock *, struct sk_buff *);
+	int (*ddp_tag_reserve)(struct cxgbi_device *, unsigned int,
+				struct cxgbi_tag_format *, u32 *,
+				struct cxgbi_gather_list *, gfp_t);
+	void (*ddp_tag_release)(struct cxgbi_device *, u32);
+	struct cxgbi_gather_list* (*ddp_make_gl)(unsigned int,
+						struct scatterlist *,
+						unsigned int,
+						struct pci_dev *,
+						gfp_t);
+	void (*ddp_release_gl)(struct cxgbi_gather_list *, struct pci_dev *);
+	__u16 (*get_skb_ulp_mode)(struct sk_buff *);
+
+	struct cxgbi_tag_format tag_format;
+	struct cxgbi_ports_map *pmap;
+
+	void *dd_data;
+};
+
+struct cxgbi_conn {
+	struct list_head list_head;
+	struct cxgbi_endpoint *cep;
+	struct iscsi_conn *iconn;
+	struct cxgbi_hba *chba;
+	u32 task_idx_bits;
+};
+
+struct cxgbi_endpoint {
+	struct cxgbi_conn *cconn;
+	struct cxgbi_hba *chba;
+	struct cxgbi_sock *csk;
+};
+
+#define MAX_PDU_FRAGS	((ULP2_MAX_PDU_PAYLOAD + 512 - 1) / 512)
+struct cxgbi_task_data {
+	unsigned short nr_frags;
+	skb_frag_t frags[MAX_PDU_FRAGS];
+	struct sk_buff *skb;
+	unsigned int offset;
+	unsigned int count;
+	unsigned int sgoffset;
+};
+
+static inline int cxgbi_is_ddp_tag(struct cxgbi_tag_format *tformat, u32 tag)
+{
+	return !(tag & (1 << (tformat->rsvd_bits + tformat->rsvd_shift - 1)));
+}
+
+static inline int cxgbi_sw_tag_usable(struct cxgbi_tag_format *tformat,
+					u32 sw_tag)
+{
+	sw_tag >>= (32 - tformat->rsvd_bits);
+	return !sw_tag;
+}
+
+static inline u32 cxgbi_set_non_ddp_tag(struct cxgbi_tag_format *tformat,
+					u32 sw_tag)
+{
+	unsigned char shift = tformat->rsvd_bits + tformat->rsvd_shift - 1;
+
+	u32 mask = (1 << shift) - 1;
+
+	if (sw_tag && (sw_tag & ~mask)) {
+		u32 v1 = sw_tag & ((1 << shift) - 1);
+		u32 v2 = (sw_tag >> (shift - 1)) << shift;
+
+		return v2 | v1 | 1 << shift;
+	}
+
+	return sw_tag | 1 << shift;
+}
+
+static inline u32 cxgbi_ddp_tag_base(struct cxgbi_tag_format *tformat,
+					u32 sw_tag)
+{
+	u32 mask = (1 << tformat->rsvd_shift) - 1;
+
+	if (sw_tag && (sw_tag & ~mask)) {
+		u32 v1 = sw_tag & mask;
+		u32 v2 = sw_tag >> tformat->rsvd_shift;
+
+		v2 <<= tformat->rsvd_bits + tformat->rsvd_shift;
+
+		return v2 | v1;
+	}
+
+	return sw_tag;
+}
+
+static inline u32 cxgbi_tag_rsvd_bits(struct cxgbi_tag_format *tformat,
+					u32 tag)
+{
+	if (cxgbi_is_ddp_tag(tformat, tag))
+		return (tag >> tformat->rsvd_shift) & tformat->rsvd_mask;
+
+	return 0;
+}
+
+static inline u32 cxgbi_tag_nonrsvd_bits(struct cxgbi_tag_format *tformat,
+					u32 tag)
+{
+	unsigned char shift = tformat->rsvd_bits + tformat->rsvd_shift - 1;
+	u32 v1, v2;
+
+	if (cxgbi_is_ddp_tag(tformat, tag)) {
+		v1 = tag & ((1 << tformat->rsvd_shift) - 1);
+		v2 = (tag >> (shift + 1)) << tformat->rsvd_shift;
+	} else {
+		u32 mask = (1 << shift) - 1;
+		tag &= ~(1 << shift);
+		v1 = tag & mask;
+		v2 = (tag >> 1) & ~mask;
+	}
+	return v1 | v2;
+}
+
+static inline void *cxgbi_alloc_big_mem(unsigned int size,
+					gfp_t gfp)
+{
+	void *p = kmalloc(size, gfp);
+	if (!p)
+		p = vmalloc(size);
+	if (p)
+		memset(p, 0, size);
+	return p;
+}
+
+static inline void cxgbi_free_big_mem(void *addr)
+{
+	if (is_vmalloc_addr(addr))
+		vfree(addr);
+	else
+		kfree(addr);
+}
+
+#define RX_DDP_STATUS_IPP_SHIFT		27      /* invalid pagepod */
+#define RX_DDP_STATUS_TID_SHIFT		26      /* tid mismatch */
+#define RX_DDP_STATUS_COLOR_SHIFT	25      /* color mismatch */
+#define RX_DDP_STATUS_OFFSET_SHIFT	24      /* offset mismatch */
+#define RX_DDP_STATUS_ULIMIT_SHIFT	23      /* ulimit error */
+#define RX_DDP_STATUS_TAG_SHIFT		22      /* tag mismatch */
+#define RX_DDP_STATUS_DCRC_SHIFT	21      /* dcrc error */
+#define RX_DDP_STATUS_HCRC_SHIFT	20      /* hcrc error */
+#define RX_DDP_STATUS_PAD_SHIFT		19      /* pad error */
+#define RX_DDP_STATUS_PPP_SHIFT		18      /* pagepod parity error */
+#define RX_DDP_STATUS_LLIMIT_SHIFT	17      /* llimit error */
+#define RX_DDP_STATUS_DDP_SHIFT		16      /* ddp'able */
+#define RX_DDP_STATUS_PMM_SHIFT		15      /* pagepod mismatch */
+
+
+#define ULP2_FLAG_DATA_READY		0x1
+#define ULP2_FLAG_DATA_DDPED		0x2
+#define ULP2_FLAG_HCRC_ERROR		0x4
+#define ULP2_FLAG_DCRC_ERROR		0x8
+#define ULP2_FLAG_PAD_ERROR		0x10
+
+static inline void *cplhdr(struct sk_buff *skb)
+{
+	return skb->data;
+}
+
+int cxgbi_reserve_itt(struct iscsi_task *task, itt_t *hdr_itt);
+void cxgbi_release_itt(struct iscsi_task *task, itt_t hdr_itt);
+void cxgbi_parse_pdu_itt(struct iscsi_conn *conn, itt_t itt,
+				int *idx, int *age);
+void cxgbi_cleanup_task(struct iscsi_task *task);
+
+int cxgbi_conn_read_bhs_pdu_skb(struct iscsi_conn *, struct sk_buff *);
+int cxgbi_conn_read_data_pdu_skb(struct iscsi_conn *, struct sk_buff *);
+void cxgbi_conn_tx_open(struct cxgbi_sock *);
+int cxgbi_conn_init_pdu(struct iscsi_task *, unsigned int , unsigned int);
+int cxgbi_conn_alloc_pdu(struct iscsi_task *, u8);
+int cxgbi_conn_xmit_pdu(struct iscsi_task *);
+
+int cxgbi_pdu_init(struct cxgbi_device *);
+void cxgbi_pdu_cleanup(struct cxgbi_device *);
+
+
+#endif	/*__LIBCXGBI_H__*/
+
-- 
1.6.6.1

-- 
You received this message because you are subscribed to the Google Groups "open-iscsi" group.
To post to this group, send email to open-iscsi-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
To unsubscribe from this group, send email to open-iscsi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit this group at http://groups.google.com/group/open-iscsi?hl=en.

^ permalink raw reply related

* [PATCH 2/3] cxgb4i_v3: main driver files
From: Rakesh Ranjan @ 2010-05-15 17:15 UTC (permalink / raw)
  To: NETDEVML, SCSIDEVML, OISCSIML
  Cc: LKML, Karen Xie, David Miller, James Bottomley, Mike Christie,
	Anish Bhatt, Rakesh Ranjan, Rakesh Ranjan
In-Reply-To: <1273943752-32486-2-git-send-email-rakesh-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>

From: Rakesh Ranjan <rranjan-UJ4WrezqVcvwEYdC/TKypOqkaFVsf6Qi@public.gmane.org>


Signed-off-by: Rakesh Ranjan <rakesh-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
---
 drivers/scsi/cxgb4i/cxgb4i.h         |  101 ++
 drivers/scsi/cxgb4i/cxgb4i_ddp.c     |  678 +++++++++++++
 drivers/scsi/cxgb4i/cxgb4i_ddp.h     |  118 +++
 drivers/scsi/cxgb4i/cxgb4i_offload.c | 1846 ++++++++++++++++++++++++++++++++++
 drivers/scsi/cxgb4i/cxgb4i_offload.h |   91 ++
 drivers/scsi/cxgb4i/cxgb4i_snic.c    |  260 +++++
 6 files changed, 3094 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/cxgb4i/cxgb4i.h
 create mode 100644 drivers/scsi/cxgb4i/cxgb4i_ddp.c
 create mode 100644 drivers/scsi/cxgb4i/cxgb4i_ddp.h
 create mode 100644 drivers/scsi/cxgb4i/cxgb4i_offload.c
 create mode 100644 drivers/scsi/cxgb4i/cxgb4i_offload.h
 create mode 100644 drivers/scsi/cxgb4i/cxgb4i_snic.c

diff --git a/drivers/scsi/cxgb4i/cxgb4i.h b/drivers/scsi/cxgb4i/cxgb4i.h
new file mode 100644
index 0000000..fbf7699
--- /dev/null
+++ b/drivers/scsi/cxgb4i/cxgb4i.h
@@ -0,0 +1,101 @@
+/*
+ * cxgb4i.h: Chelsio T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Karen Xie (kxie-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ * Written by: Rakesh Ranjan (rranjan-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ */
+
+#ifndef	__CXGB4I_H__
+#define	__CXGB4I_H__
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/scatterlist.h>
+#include <linux/skbuff.h>
+#include <scsi/libiscsi_tcp.h>
+
+#include "t4fw_api.h"
+#include "t4_msg.h"
+#include "l2t.h"
+#include "cxgb4.h"
+#include "cxgb4_uld.h"
+
+#include "libcxgbi.h"
+#include "cxgb4i_ddp.h"
+#include "cxgb4i_offload.h"
+
+#define	CXGB4I_SCSI_HOST_QDEPTH	1024
+#define	CXGB4I_MAX_TARGET	CXGB4I_MAX_CONN
+#define	CXGB4I_MAX_LUN		512
+#define	ISCSI_PDU_NONPAYLOAD_MAX \
+	(sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE + \
+	 (2 * ISCSI_DIGEST_SIZE))
+
+struct cxgb4i_snic;
+struct cxgb4i_host;
+struct cxgb4i_endpoint;
+typedef int (*cxgb4i_cplhandler_func)(struct cxgb4i_snic *, struct sk_buff *);
+
+struct cxgb4i_snic {
+	struct list_head list_head;
+	spinlock_t lock;
+	struct cxgbi_device cdev;
+	struct cxgbi_hba *hba[MAX_NPORTS];
+	unsigned char hba_cnt;
+	unsigned int flags;
+	unsigned int tx_max_size;
+	unsigned int rx_max_size;
+	struct cxgb4_lld_info lldi;
+	struct cxgb4i_ddp_info *ddp;
+	cxgb4i_cplhandler_func *handlers;
+};
+
+int cxgb4i_ofld_init(struct cxgb4i_snic *);
+void cxgb4i_ofld_cleanup(struct cxgb4i_snic *);
+struct cxgb4i_snic *cxgb4i_find_snic(struct net_device *, __be32);
+struct cxgbi_hba *cxgb4i_hba_find_by_netdev(struct net_device *);
+struct cxgbi_hba *cxgb4i_hba_add(struct cxgb4i_snic *, struct net_device *);
+void cxgb4i_hba_remove(struct cxgbi_hba *);
+int cxgb4i_iscsi_init(void);
+void cxgb4i_iscsi_cleanup(void);
+
+static inline void cxgb4i_set_iscsi_ipv4(struct cxgbi_hba *chba, __be32 ipaddr)
+{
+	chba->ipv4addr = ipaddr;
+}
+
+static inline __be32 cxgb4i_get_iscsi_ipv4(struct cxgbi_hba *chba)
+{
+	return chba->ipv4addr;
+}
+
+static inline struct cxgb4i_snic *cxgb4i_get_snic(struct cxgbi_device *cdev)
+{
+	return (struct cxgb4i_snic *)cdev->dd_data;
+}
+
+
+#define W_TCB_ULP_TYPE          0
+#define TCB_ULP_TYPE_SHIFT      0
+#define TCB_ULP_TYPE_MASK       0xfULL
+#define TCB_ULP_TYPE(x)         ((x) << TCB_ULP_TYPE_SHIFT)
+
+#define W_TCB_ULP_RAW           0
+#define TCB_ULP_RAW_SHIFT       4
+#define TCB_ULP_RAW_MASK        0xffULL
+#define TCB_ULP_RAW(x)          ((x) << TCB_ULP_RAW_SHIFT)
+
+
+#endif	/* __CXGB4I_H__ */
+
diff --git a/drivers/scsi/cxgb4i/cxgb4i_ddp.c b/drivers/scsi/cxgb4i/cxgb4i_ddp.c
new file mode 100644
index 0000000..1e53c0e
--- /dev/null
+++ b/drivers/scsi/cxgb4i/cxgb4i_ddp.c
@@ -0,0 +1,678 @@
+/*
+ * cxgb4i_ddp.c: Chelsio T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Karen Xie (kxie-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ * Written by: Rakesh Ranjan (rranjan-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ */
+
+#include <linux/skbuff.h>
+#include <linux/scatterlist.h>
+
+
+#include "libcxgbi.h"
+#include "cxgb4i.h"
+#include "cxgb4i_ddp.h"
+
+#define DDP_PGIDX_MAX	4
+#define DDP_THRESHOLD	2048
+
+static unsigned char ddp_page_order[DDP_PGIDX_MAX] = {0, 1, 2, 4};
+static unsigned char ddp_page_shift[DDP_PGIDX_MAX] = {12, 13, 14, 16};
+static unsigned char page_idx = DDP_PGIDX_MAX;
+
+static unsigned char sw_tag_idx_bits;
+static unsigned char sw_tag_age_bits;
+
+
+static inline void cxgb4i_ddp_ppod_set(struct pagepod *ppod,
+					struct pagepod_hdr *hdr,
+					struct cxgbi_gather_list *gl,
+					unsigned int pidx)
+{
+	int i;
+
+	memcpy(ppod, hdr, sizeof(*hdr));
+	for (i = 0; i < (PPOD_PAGES_MAX + 1); i++, pidx++) {
+		ppod->addr[i] = pidx < gl->nelem ?
+			cpu_to_be64(gl->phys_addr[pidx]) : 0ULL;
+	}
+}
+
+static inline void cxgb4i_ddp_ppod_clear(struct pagepod *ppod)
+{
+	memset(ppod, 0, sizeof(*ppod));
+}
+
+static inline void cxgb4i_ddp_ulp_mem_io_set_hdr(struct ulp_mem_io *req,
+					unsigned int wr_len, unsigned int dlen,
+					unsigned int pm_addr)
+{
+	struct ulptx_sgl *sgl;
+
+	INIT_ULPTX_WR(req, wr_len, 0, 0);
+	req->cmd = htonl(ULPTX_CMD(ULP_TX_MEM_WRITE));
+	req->dlen = htonl(ULP_MEMIO_DATA_LEN(dlen >> 5));
+	req->len16 = htonl(DIV_ROUND_UP(wr_len - sizeof(req->wr), 16));
+	req->lock_addr = htonl(ULP_MEMIO_ADDR(pm_addr >> 5));
+
+	sgl = (struct ulptx_sgl *)(req + 1);
+	sgl->cmd_nsge = htonl(ULPTX_CMD(ULP_TX_SC_DSGL) | ULPTX_NSGE(1));
+	sgl->len0 = htonl(dlen);
+}
+
+static int cxgb4i_ddp_ppod_write_sgl(struct cxgb4i_ddp_info *ddp,
+					struct pagepod_hdr *hdr,
+					unsigned int idx,
+					unsigned int npods,
+					struct cxgbi_gather_list *gl,
+					unsigned int gl_pidx)
+{
+	unsigned int dlen = PPOD_SIZE * npods;
+	unsigned int pm_addr = idx * PPOD_SIZE + ddp->llimit;
+	unsigned int wr_len = roundup(sizeof(struct ulp_mem_io) +
+					sizeof(struct ulptx_sgl), 16);
+	struct sk_buff *skb = alloc_skb(wr_len + dlen, GFP_ATOMIC);
+	struct ulp_mem_io *req;
+	struct ulptx_sgl *sgl;
+	struct pagepod *ppod;
+	unsigned int i;
+
+	if (!skb) {
+		cxgbi_log_error("snic 0x%p, idx %u, npods %u, OOM\n",
+				ddp->snic, idx, npods);
+		return -ENOMEM;
+	}
+
+	memset(skb->data, 0, wr_len + dlen);
+	skb->queue_mapping = CPL_PRIORITY_CONTROL;
+
+	req = (struct ulp_mem_io *)__skb_put(skb, wr_len);
+	cxgb4i_ddp_ulp_mem_io_set_hdr(req, wr_len, dlen, pm_addr);
+	sgl = (struct ulptx_sgl *)(req + 1);
+	ppod = (struct pagepod *)(sgl + 1);
+	sgl->addr0 = cpu_to_be64(virt_to_phys(ppod));
+
+	for (i = 0; i < npods; i++, ppod++, gl_pidx += PPOD_PAGES_MAX) {
+		if (!hdr && !gl)
+			cxgb4i_ddp_ppod_clear(ppod);
+		else
+			cxgb4i_ddp_ppod_set(ppod, hdr, gl, gl_pidx);
+
+	}
+
+	cxgb4_ofld_send(ddp->snic->lldi.ports[0], skb);
+
+	return 0;
+}
+
+static int cxgb4i_ddp_set_map(struct cxgb4i_ddp_info *ddp,
+					struct pagepod_hdr *hdr,
+					unsigned int idx,
+					unsigned int npods,
+					struct cxgbi_gather_list *gl)
+{
+	unsigned int pidx = 0;
+	unsigned int w_npods = 0;
+	unsigned int cnt;
+	int err = 0;
+
+	for (; w_npods < npods; idx += cnt, w_npods += cnt,
+					pidx += PPOD_PAGES_MAX) {
+		cnt = npods - w_npods;
+		if (cnt > ULPMEM_DSGL_MAX_NPPODS)
+			cnt = ULPMEM_DSGL_MAX_NPPODS;
+		err = cxgb4i_ddp_ppod_write_sgl(ddp, hdr, idx, cnt, gl, pidx);
+
+		if (err < 0)
+			break;
+	}
+
+	return err;
+}
+
+static void cxgb4i_ddp_clear_map(struct cxgb4i_ddp_info *ddp,
+						unsigned int tag,
+						unsigned int idx,
+						unsigned int npods)
+{
+	int err;
+	unsigned int w_npods = 0;
+	unsigned int cnt;
+
+	for (; w_npods < npods; idx += cnt, w_npods += cnt) {
+		cnt = npods - w_npods;
+
+		if (cnt > ULPMEM_DSGL_MAX_NPPODS)
+			cnt = ULPMEM_DSGL_MAX_NPPODS;
+		err = cxgb4i_ddp_ppod_write_sgl(ddp, NULL, idx, cnt, NULL, 0);
+
+		if (err < 0)
+			break;
+	}
+}
+
+static inline int cxgb4i_ddp_find_unused_entries(struct cxgb4i_ddp_info *ddp,
+					unsigned int start, unsigned int max,
+					unsigned int count,
+					struct cxgbi_gather_list *gl)
+{
+	unsigned int i, j, k;
+
+	/*  not enough entries */
+	if ((max - start) < count)
+		return -EBUSY;
+
+	max -= count;
+	spin_lock(&ddp->map_lock);
+	for (i = start; i < max;) {
+		for (j = 0, k = i; j < count; j++, k++) {
+			if (ddp->gl_map[k])
+				break;
+		}
+		if (j == count) {
+			for (j = 0, k = i; j < count; j++, k++)
+				ddp->gl_map[k] = gl;
+			spin_unlock(&ddp->map_lock);
+			return i;
+		}
+		i += j + 1;
+	}
+	spin_unlock(&ddp->map_lock);
+	return -EBUSY;
+}
+
+static inline void cxgb4i_ddp_unmark_entries(struct cxgb4i_ddp_info *ddp,
+							int start, int count)
+{
+	spin_lock(&ddp->map_lock);
+	memset(&ddp->gl_map[start], 0,
+			count * sizeof(struct cxgbi_gather_list *));
+	spin_unlock(&ddp->map_lock);
+}
+
+static int cxgb4i_ddp_find_page_index(unsigned long pgsz)
+{
+	int i;
+
+	for (i = 0; i < DDP_PGIDX_MAX; i++) {
+		if (pgsz == (1UL << ddp_page_shift[i]))
+			return i;
+	}
+	cxgbi_log_debug("ddp page size 0x%lx not supported\n", pgsz);
+
+	return DDP_PGIDX_MAX;
+}
+
+static int cxgb4i_ddp_adjust_page_table(void)
+{
+	int i;
+	unsigned int base_order, order;
+
+	if (PAGE_SIZE < (1UL << ddp_page_shift[0])) {
+		cxgbi_log_info("PAGE_SIZE 0x%lx too small, min 0x%lx\n",
+				PAGE_SIZE, 1UL << ddp_page_shift[0]);
+		return -EINVAL;
+	}
+
+	base_order = get_order(1UL << ddp_page_shift[0]);
+	order = get_order(1UL << PAGE_SHIFT);
+
+	for (i = 0; i < DDP_PGIDX_MAX; i++) {
+		/* first is the kernel page size, then just doubling the size */
+		ddp_page_order[i] = order - base_order + i;
+		ddp_page_shift[i] = PAGE_SHIFT + i;
+	}
+
+	return 0;
+}
+
+static inline void cxgb4i_ddp_gl_unmap(struct pci_dev *pdev,
+					struct cxgbi_gather_list *gl)
+{
+	int i;
+
+	for (i = 0; i < gl->nelem; i++)
+		dma_unmap_page(&pdev->dev, gl->phys_addr[i], PAGE_SIZE,
+				PCI_DMA_FROMDEVICE);
+}
+
+static inline int cxgb4i_ddp_gl_map(struct pci_dev *pdev,
+				struct cxgbi_gather_list *gl)
+{
+	int i;
+
+	for (i = 0; i < gl->nelem; i++) {
+		gl->phys_addr[i] = dma_map_page(&pdev->dev, gl->pages[i], 0,
+						PAGE_SIZE,
+						PCI_DMA_FROMDEVICE);
+		if (unlikely(dma_mapping_error(&pdev->dev, gl->phys_addr[i])))
+			goto unmap;
+	}
+
+	return i;
+
+unmap:
+	if (i) {
+		unsigned int nelem = gl->nelem;
+
+		gl->nelem = i;
+		cxgb4i_ddp_gl_unmap(pdev, gl);
+		gl->nelem = nelem;
+	}
+	return -ENOMEM;
+}
+
+
+void cxgb4i_ddp_release_gl(struct cxgbi_gather_list *gl,
+				struct pci_dev *pdev)
+{
+	cxgb4i_ddp_gl_unmap(pdev, gl);
+	kfree(gl);
+}
+
+struct cxgbi_gather_list *cxgb4i_ddp_make_gl(unsigned int xferlen,
+						struct scatterlist *sgl,
+						unsigned int sgcnt,
+						struct pci_dev *pdev,
+						gfp_t gfp)
+{
+	struct cxgbi_gather_list *gl;
+	struct scatterlist *sg = sgl;
+	struct page *sgpage = sg_page(sg);
+	unsigned int sglen = sg->length;
+	unsigned int sgoffset = sg->offset;
+	unsigned int npages = (xferlen + sgoffset + PAGE_SIZE - 1) >>
+				PAGE_SHIFT;
+	int i = 1, j = 0;
+
+	if (xferlen < DDP_THRESHOLD) {
+		cxgbi_log_debug("xfer %u < threshold %u, no ddp.\n",
+				xferlen, DDP_THRESHOLD);
+		return NULL;
+	}
+
+	gl = kzalloc(sizeof(struct cxgbi_gather_list) +
+			npages * (sizeof(dma_addr_t) + sizeof(struct page *)),
+			gfp);
+	if (!gl)
+		return NULL;
+
+	gl->pages = (struct page **)&gl->phys_addr[npages];
+	gl->length = xferlen;
+	gl->offset = sgoffset;
+	gl->pages[0] = sgpage;
+
+	sg = sg_next(sg);
+	while (sg) {
+		struct page *page = sg_page(sg);
+
+		if (sgpage == page && sg->offset == sgoffset + sglen)
+			sglen += sg->length;
+		else {
+			/*  make sure the sgl is fit for ddp:
+			 *  each has the same page size, and
+			 *  all of the middle pages are used completely
+			 */
+			if ((j && sgoffset) || ((i != sgcnt - 1) &&
+					 ((sglen + sgoffset) & ~PAGE_MASK)))
+				goto error_out;
+
+			j++;
+			if (j == gl->nelem || sg->offset)
+				goto error_out;
+			gl->pages[j] = page;
+			sglen = sg->length;
+			sgoffset = sg->offset;
+			sgpage = page;
+		}
+		i++;
+		sg = sg_next(sg);
+	}
+	gl->nelem = ++j;
+
+	if (cxgb4i_ddp_gl_map(pdev, gl) < 0)
+		goto error_out;
+
+	return gl;
+
+error_out:
+	kfree(gl);
+	return NULL;
+}
+
+
+static void cxgb4i_ddp_tag_release(struct cxgbi_device *cdev, u32 tag)
+{
+	struct cxgb4i_snic *snic = cxgb4i_get_snic(cdev);
+	struct cxgb4i_ddp_info *ddp = snic->ddp;
+	u32 idx;
+
+	if (!ddp) {
+		cxgbi_log_error("release ddp tag 0x%x, ddp NULL.\n", tag);
+		return;
+	}
+
+	idx = (tag >> PPOD_IDX_SHIFT) & ddp->idx_mask;
+	if (idx < ddp->nppods) {
+		struct cxgbi_gather_list *gl = ddp->gl_map[idx];
+		unsigned int npods;
+
+		if (!gl || !gl->nelem) {
+			cxgbi_log_error("rel 0x%x, idx 0x%x, gl 0x%p, %u\n",
+					tag, idx, gl, gl ? gl->nelem : 0);
+			return;
+		}
+		npods = (gl->nelem + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT;
+		cxgbi_log_debug("ddp tag 0x%x, release idx 0x%x, npods %u.\n",
+				tag, idx, npods);
+		cxgb4i_ddp_clear_map(ddp, tag, idx, npods);
+		cxgb4i_ddp_unmark_entries(ddp, idx, npods);
+		cxgb4i_ddp_release_gl(gl, ddp->pdev);
+	} else
+		cxgbi_log_error("ddp tag 0x%x, idx 0x%x > max 0x%x.\n",
+				tag, idx, ddp->nppods);
+}
+
+static int cxgb4i_ddp_tag_reserve(struct cxgbi_device *cdev, unsigned int tid,
+				struct cxgbi_tag_format *tformat, u32 *tagp,
+				struct cxgbi_gather_list *gl, gfp_t gfp)
+{
+	struct cxgb4i_snic *snic = cxgb4i_get_snic(cdev);
+	struct cxgb4i_ddp_info *ddp = snic->ddp;
+	struct pagepod_hdr hdr;
+	unsigned int npods;
+	int idx = -1;
+	int err = -ENOMEM;
+	u32 sw_tag = *tagp;
+	u32 tag;
+
+	if (page_idx >= DDP_PGIDX_MAX || !ddp || !gl || !gl->nelem ||
+			gl->length < DDP_THRESHOLD) {
+		cxgbi_log_debug("pgidx %u, xfer %u/%u, NO ddp.\n",
+				page_idx, gl->length, DDP_THRESHOLD);
+		return -EINVAL;
+	}
+
+	npods = (gl->nelem + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT;
+
+	if (ddp->idx_last == ddp->nppods)
+		idx = cxgb4i_ddp_find_unused_entries(ddp, 0, ddp->nppods,
+							npods, gl);
+	else {
+		idx = cxgb4i_ddp_find_unused_entries(ddp, ddp->idx_last + 1,
+							ddp->nppods, npods,
+							gl);
+		if (idx < 0 && ddp->idx_last >= npods) {
+			idx = cxgb4i_ddp_find_unused_entries(ddp, 0,
+				min(ddp->idx_last + npods, ddp->nppods),
+							npods, gl);
+		}
+	}
+	if (idx < 0) {
+		cxgbi_log_debug("xferlen %u, gl %u, npods %u NO DDP.\n",
+				gl->length, gl->nelem, npods);
+		return idx;
+	}
+
+	tag = cxgbi_ddp_tag_base(tformat, sw_tag);
+	tag |= idx << PPOD_IDX_SHIFT;
+
+	hdr.rsvd = 0;
+	hdr.vld_tid = htonl(PPOD_VALID_FLAG | PPOD_TID(tid));
+	hdr.pgsz_tag_clr = htonl(tag & ddp->rsvd_tag_mask);
+	hdr.max_offset = htonl(gl->length);
+	hdr.page_offset = htonl(gl->offset);
+
+	err = cxgb4i_ddp_set_map(ddp, &hdr, idx, npods, gl);
+	if (err < 0)
+		goto unmark_entries;
+
+	ddp->idx_last = idx;
+	cxgbi_log_debug("xfer %u, gl %u,%u, tid 0x%x, 0x%x -> 0x%x(%u,%u).\n",
+			gl->length, gl->nelem, gl->offset, tid, sw_tag, tag,
+			idx, npods);
+	*tagp = tag;
+	return 0;
+
+unmark_entries:
+	cxgb4i_ddp_unmark_entries(ddp, idx, npods);
+	return err;
+}
+
+
+static int cxgb4i_ddp_setup_conn_pgidx(struct cxgbi_sock *csk,
+					unsigned int tid, int pg_idx,
+					bool reply)
+{
+	struct sk_buff *skb = alloc_skb(sizeof(struct cpl_set_tcb_field),
+					GFP_KERNEL);
+	struct cpl_set_tcb_field *req;
+	u64 val = pg_idx < DDP_PGIDX_MAX ? pg_idx : 0;
+
+	if (!skb)
+		return -ENOMEM;
+
+	/*  set up ulp submode and page size */
+	val = (val & 0x03) << 2;
+	val |= TCB_ULP_TYPE(ULP_MODE_ISCSI);
+	req = (struct cpl_set_tcb_field *)skb_put(skb, sizeof(*req));
+	INIT_TP_WR(req, tid);
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, csk->hwtid));
+	req->reply_ctrl = htons(NO_REPLY(reply) | QUEUENO(csk->rss_qid));
+	req->word_cookie = htons(TCB_WORD(W_TCB_ULP_RAW));
+	req->mask = cpu_to_be64(TCB_ULP_TYPE(TCB_ULP_TYPE_MASK));
+	req->val = cpu_to_be64(val);
+
+	skb->queue_mapping = CPL_PRIORITY_CONTROL;
+
+	cxgb4_ofld_send(cxgb4i_get_snic(csk->cdev)->lldi.ports[0], skb);
+	return 0;
+}
+
+int cxgb4i_ddp_setup_conn_host_pagesize(struct cxgbi_sock *csk,
+						unsigned int tid,
+						int reply)
+{
+	return cxgb4i_ddp_setup_conn_pgidx(csk, tid, page_idx, reply);
+}
+
+int cxgb4i_ddp_setup_conn_pagesize(struct cxgbi_sock *csk, unsigned int tid,
+					int reply, unsigned long pgsz)
+{
+	int pgidx = cxgb4i_ddp_find_page_index(pgsz);
+
+	return cxgb4i_ddp_setup_conn_pgidx(csk, tid, pgidx, reply);
+}
+
+int cxgb4i_ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
+				int hcrc, int dcrc, int reply)
+{
+	struct sk_buff *skb = alloc_skb(sizeof(struct cpl_set_tcb_field),
+					GFP_KERNEL);
+	struct cpl_set_tcb_field *req;
+	u64 val = (hcrc ? ULP_CRC_HEADER : 0) | (dcrc ? ULP_CRC_DATA : 0);
+	val = TCB_ULP_RAW(val);
+	val |= TCB_ULP_TYPE(ULP_MODE_ISCSI);
+
+	if (!skb)
+		return -ENOMEM;
+
+	/*  set up ulp submode and page size */
+	req = (struct cpl_set_tcb_field *)skb_put(skb, sizeof(*req));
+	INIT_TP_WR(req, tid);
+	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
+	req->reply_ctrl = htons(NO_REPLY(reply) | QUEUENO(csk->rss_qid));
+	req->word_cookie = htons(TCB_WORD(W_TCB_ULP_RAW));
+	req->mask = cpu_to_be64(TCB_ULP_RAW(TCB_ULP_RAW_MASK));
+	req->val = cpu_to_be64(val);
+
+	skb->queue_mapping = CPL_PRIORITY_CONTROL;
+
+	cxgb4_ofld_send(cxgb4i_get_snic(csk->cdev)->lldi.ports[0], skb);
+	return 0;
+}
+
+static void __cxgb4i_ddp_cleanup(struct kref *kref)
+{
+	int i = 0;
+	struct cxgb4i_ddp_info *ddp = container_of(kref,
+						struct cxgb4i_ddp_info,
+						refcnt);
+
+	cxgbi_log_info("kref release ddp 0x%p, snic 0x%p\n", ddp, ddp->snic);
+
+	ddp->snic->ddp = NULL;
+
+	while (i < ddp->nppods) {
+		struct cxgbi_gather_list *gl = ddp->gl_map[i];
+
+		if (gl) {
+			int npods = (gl->nelem + PPOD_PAGES_MAX - 1) >>
+							PPOD_PAGES_SHIFT;
+			cxgbi_log_info("snic 0x%p, ddp %d + %d\n",
+						ddp->snic, i, npods);
+			kfree(gl);
+			i += npods;
+		} else
+			i++;
+	}
+	cxgbi_free_big_mem(ddp);
+}
+
+
+static void __cxgb4i_ddp_init(struct cxgb4i_snic *snic)
+{
+	struct cxgb4i_ddp_info *ddp = snic->ddp;
+	unsigned int ppmax, bits, tagmask, pgsz_factor[4];
+	int i;
+
+	if (ddp) {
+		kref_get(&ddp->refcnt);
+		cxgbi_log_warn("snic 0x%p, ddp 0x%p already set up\n",
+				snic, snic->ddp);
+		return;
+	}
+
+	sw_tag_idx_bits = (__ilog2_u32(ISCSI_ITT_MASK)) + 1;
+	sw_tag_age_bits = (__ilog2_u32(ISCSI_AGE_MASK)) + 1;
+	snic->cdev.tag_format.sw_bits = sw_tag_idx_bits + sw_tag_age_bits;
+
+	cxgbi_log_info("tag itt 0x%x, %u bits, age 0x%x, %u bits\n",
+			ISCSI_ITT_MASK, sw_tag_idx_bits,
+			ISCSI_AGE_MASK, sw_tag_age_bits);
+
+	ppmax = (snic->lldi.vr->iscsi.size >> PPOD_SIZE_SHIFT);
+	bits = __ilog2_u32(ppmax) + 1;
+	if (bits > PPOD_IDX_MAX_SIZE)
+		bits = PPOD_IDX_MAX_SIZE;
+	ppmax = (1 << (bits - 1)) - 1;
+
+	ddp = cxgbi_alloc_big_mem(sizeof(struct cxgb4i_ddp_info) +
+			ppmax * (sizeof(struct cxgbi_gather_list *) +
+				sizeof(struct sk_buff *)),
+				GFP_KERNEL);
+	if (!ddp) {
+		cxgbi_log_warn("snic 0x%p unable to alloc ddp 0x%d, "
+			       "ddp disabled\n", snic, ppmax);
+		return;
+	}
+
+	ddp->gl_map = (struct cxgbi_gather_list **)(ddp + 1);
+	spin_lock_init(&ddp->map_lock);
+	kref_init(&ddp->refcnt);
+
+	ddp->snic = snic;
+	ddp->pdev = snic->lldi.pdev;
+	ddp->max_txsz = min_t(unsigned int,
+				snic->lldi.iscsi_iolen,
+				ULP2_MAX_PKT_SIZE);
+	ddp->max_rxsz = min_t(unsigned int,
+				snic->lldi.iscsi_iolen,
+				ULP2_MAX_PKT_SIZE);
+	ddp->llimit = snic->lldi.vr->iscsi.start;
+	ddp->ulimit = ddp->llimit + snic->lldi.vr->iscsi.size;
+	ddp->nppods = ppmax;
+	ddp->idx_last = ppmax;
+	ddp->idx_bits = bits;
+	ddp->idx_mask = (1 << bits) - 1;
+	ddp->rsvd_tag_mask = (1 << (bits + PPOD_IDX_SHIFT)) - 1;
+
+	tagmask = ddp->idx_mask << PPOD_IDX_SHIFT;
+	for (i = 0; i < DDP_PGIDX_MAX; i++)
+		pgsz_factor[i] = ddp_page_order[i];
+
+	cxgb4_iscsi_init(snic->lldi.ports[0], tagmask, pgsz_factor);
+	snic->ddp = ddp;
+
+	snic->cdev.tag_format.rsvd_bits = ddp->idx_bits;
+	snic->cdev.tag_format.rsvd_shift = PPOD_IDX_SHIFT;
+	snic->cdev.tag_format.rsvd_mask =
+		((1 << snic->cdev.tag_format.rsvd_bits) - 1);
+
+	cxgbi_log_info("tag format: sw %u, rsvd %u,%u, mask 0x%x.\n",
+			snic->cdev.tag_format.sw_bits,
+			snic->cdev.tag_format.rsvd_bits,
+			snic->cdev.tag_format.rsvd_shift,
+			snic->cdev.tag_format.rsvd_mask);
+
+	snic->tx_max_size = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
+				ddp->max_txsz - ISCSI_PDU_NONPAYLOAD_LEN);
+	snic->rx_max_size = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
+				ddp->max_rxsz - ISCSI_PDU_NONPAYLOAD_LEN);
+
+	cxgbi_log_info("max payload size: %u/%u, %u/%u.\n",
+			snic->tx_max_size, ddp->max_txsz,
+			snic->rx_max_size, ddp->max_rxsz);
+
+	cxgbi_log_info("snic 0x%p, nppods %u, bits %u, mask 0x%x,0x%x "
+			"pkt %u/%u, %u/%u\n",
+			snic, ppmax, ddp->idx_bits, ddp->idx_mask,
+			ddp->rsvd_tag_mask, ddp->max_txsz,
+			snic->lldi.iscsi_iolen,
+			ddp->max_rxsz, snic->lldi.iscsi_iolen);
+
+	return;
+}
+
+void cxgb4i_ddp_init(struct cxgb4i_snic *snic)
+{
+	if (page_idx == DDP_PGIDX_MAX) {
+		page_idx = cxgb4i_ddp_find_page_index(PAGE_SIZE);
+
+		if (page_idx == DDP_PGIDX_MAX) {
+			cxgbi_log_info("system PAGE_SIZE %lu, update hw\n",
+					PAGE_SIZE);
+
+			if (cxgb4i_ddp_adjust_page_table()) {
+				cxgbi_log_info("PAGE_SIZE %lu, ddp disabled\n",
+						PAGE_SIZE);
+				return;
+			}
+			page_idx = cxgb4i_ddp_find_page_index(PAGE_SIZE);
+		}
+		cxgbi_log_info("system PAGE_SIZE %lu, ddp idx %u\n",
+				PAGE_SIZE, page_idx);
+	}
+
+	__cxgb4i_ddp_init(snic);
+	snic->cdev.ddp_make_gl = cxgb4i_ddp_make_gl;
+	snic->cdev.ddp_release_gl = cxgb4i_ddp_release_gl;
+	snic->cdev.ddp_tag_reserve = cxgb4i_ddp_tag_reserve;
+	snic->cdev.ddp_tag_release = cxgb4i_ddp_tag_release;
+}
+
+void cxgb4i_ddp_cleanup(struct cxgb4i_snic *snic)
+{
+	struct cxgb4i_ddp_info *ddp = snic->ddp;
+
+	cxgbi_log_info("snic 0x%p, release ddp 0x%p\n", snic, ddp);
+	if (ddp)
+		kref_put(&ddp->refcnt, __cxgb4i_ddp_cleanup);
+}
+
diff --git a/drivers/scsi/cxgb4i/cxgb4i_ddp.h b/drivers/scsi/cxgb4i/cxgb4i_ddp.h
new file mode 100644
index 0000000..f51cb37
--- /dev/null
+++ b/drivers/scsi/cxgb4i/cxgb4i_ddp.h
@@ -0,0 +1,118 @@
+/*
+ * cxgb4i_ddp.h: Chelsio T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Karen Xie (kxie-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ * Written by: Rakesh Ranjan (rranjan-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ */
+
+#ifndef	__CXGB4I_DDP_H__
+#define	__CXGB4I_DDP_H__
+
+#include <linux/vmalloc.h>
+
+#include "libcxgbi.h"
+
+struct cxgbi_sock;
+
+struct cxgb4i_ddp_info {
+	struct list_head list;
+	struct kref refcnt;
+	struct cxgb4i_snic *snic;
+	struct pci_dev *pdev;
+	unsigned int max_txsz;
+	unsigned int max_rxsz;
+	unsigned int llimit;
+	unsigned int ulimit;
+	unsigned int nppods;
+	unsigned int idx_last;
+	unsigned char idx_bits;
+	unsigned char filler[3];
+	unsigned int idx_mask;
+	unsigned int rsvd_tag_mask;
+	spinlock_t map_lock;
+	struct cxgbi_gather_list **gl_map;
+};
+
+struct pagepod_hdr {
+	unsigned int vld_tid;
+	unsigned int pgsz_tag_clr;
+	unsigned int max_offset;
+	unsigned int page_offset;
+	unsigned long long rsvd;
+};
+
+struct pagepod {
+	struct pagepod_hdr hdr;
+	unsigned long long addr[PPOD_PAGES_MAX + 1];
+};
+
+struct cpl_rx_data_ddp {
+	union opcode_tid ot;
+	__be16 urg;
+	__be16 len;
+	__be32 seq;
+	union {
+		__be32 nxt_seq;
+		__be32 ddp_report;
+	};
+	__be32 ulp_crc;
+	__be32 ddpvld;
+};
+
+#define PPOD_SIZE               sizeof(struct pagepod)  /*  64 */
+#define PPOD_SIZE_SHIFT         6
+
+#define ULPMEM_DSGL_MAX_NPPODS	16	/*  1024/PPOD_SIZE */
+#define ULPMEM_IDATA_MAX_NPPODS	4	/*  256/PPOD_SIZE */
+#define PCIE_MEMWIN_MAX_NPPODS	16	/*  1024/PPOD_SIZE */
+
+#define PPOD_COLOR_SHIFT	0
+#define PPOD_COLOR_MASK		0x3F
+#define PPOD_COLOR_SIZE         6
+#define PPOD_COLOR(x)		((x) << PPOD_COLOR_SHIFT)
+
+#define PPOD_TAG_SHIFT	6
+#define PPOD_TAG_MASK	0xFFFFFF
+#define PPOD_TAG(x)	((x) << PPOD_TAG_SHIFT)
+
+#define PPOD_PGSZ_SHIFT	30
+#define PPOD_PGSZ_MASK	0x3
+#define PPOD_PGSZ(x)	((x) << PPOD_PGSZ_SHIFT)
+
+#define PPOD_TID_SHIFT	32
+#define PPOD_TID_MASK	0xFFFFFF
+#define PPOD_TID(x)	((__u64)(x) << PPOD_TID_SHIFT)
+
+#define PPOD_VALID_SHIFT	56
+#define PPOD_VALID(x)	((__u64)(x) << PPOD_VALID_SHIFT)
+#define PPOD_VALID_FLAG	PPOD_VALID(1ULL)
+
+#define PPOD_LEN_SHIFT	32
+#define PPOD_LEN_MASK	0xFFFFFFFF
+#define PPOD_LEN(x)	((__u64)(x) << PPOD_LEN_SHIFT)
+
+#define PPOD_OFST_SHIFT	0
+#define PPOD_OFST_MASK	0xFFFFFFFF
+#define PPOD_OFST(x)	((x) << PPOD_OFST_SHIFT)
+
+#define PPOD_IDX_SHIFT          PPOD_COLOR_SIZE
+#define PPOD_IDX_MAX_SIZE       24
+
+int cxgb4i_ddp_setup_conn_host_pagesize(struct cxgbi_sock*, unsigned int,
+					int);
+int cxgb4i_ddp_setup_conn_digest(struct cxgbi_sock *, unsigned int,
+				int, int, int);
+int cxgb4i_snic_ddp_info(struct cxgb4i_snic *, struct cxgbi_tag_format *,
+			unsigned int *, unsigned int *);
+
+void cxgb4i_ddp_init(struct cxgb4i_snic *);
+void cxgb4i_ddp_cleanup(struct cxgb4i_snic *);
+
+#endif	/* __CXGB4I_DDP_H__ */
+
diff --git a/drivers/scsi/cxgb4i/cxgb4i_offload.c b/drivers/scsi/cxgb4i/cxgb4i_offload.c
new file mode 100644
index 0000000..87edb14
--- /dev/null
+++ b/drivers/scsi/cxgb4i/cxgb4i_offload.c
@@ -0,0 +1,1846 @@
+/*
+ * cxgb4i_offload.c: Chelsio T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Karen Xie (kxie-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ * Written by: Rakesh Ranjan (rranjan-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ */
+
+#include <linux/if_vlan.h>
+#include <net/dst.h>
+#include <net/route.h>
+#include <net/tcp.h>
+
+#include "libcxgbi.h"
+#include "cxgb4i.h"
+#include "cxgb4i_offload.h"
+
+static int cxgb4i_rcv_win = 256 * 1024;
+module_param(cxgb4i_rcv_win, int, 0644);
+MODULE_PARM_DESC(cxgb4i_rcv_win, "TCP reveive window in bytes");
+
+static int cxgb4i_snd_win = 128 * 1024;
+module_param(cxgb4i_snd_win, int, 0644);
+MODULE_PARM_DESC(cxgb4i_snd_win, "TCP send window in bytes");
+
+static int cxgb4i_rx_credit_thres = 10 * 1024;
+module_param(cxgb4i_rx_credit_thres, int, 0644);
+MODULE_PARM_DESC(cxgb4i_rx_credit_thres,
+		"RX credits return threshold in bytes (default=10KB)");
+
+static unsigned int cxgb4i_max_connect = (8 * 1024);
+module_param(cxgb4i_max_connect, uint, 0644);
+MODULE_PARM_DESC(cxgb4i_max_connect, "Maximum number of connections");
+
+static unsigned short cxgb4i_sport_base = 20000;
+module_param(cxgb4i_sport_base, ushort, 0644);
+MODULE_PARM_DESC(cxgb4i_sport_base, "Starting port number (default 20000)");
+
+#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+#define RCV_BUFSIZ_MASK	0x3FFU
+
+static void cxgb4i_sock_release_offload_resources(struct cxgbi_sock *);
+static void cxgbi_sock_conn_closing(struct cxgbi_sock *);
+static int cxgb4i_sock_push_tx_frames(struct cxgbi_sock *, int);
+
+
+#define MAX_IMM_TX_PKT_LEN 128
+
+/*
+ * is_ofld_imm - check whether a packet can be sent as immediate data
+ * @skb: the packet
+ *
+ * Returns true if a packet can be sent as an offload WR with immediate
+ * data.  We currently use the same limit as for Ethernet packets.
+ */
+static inline int is_ofld_imm(const struct sk_buff *skb)
+{
+	return skb->len <= (MAX_IMM_TX_PKT_LEN -
+			sizeof(struct fw_ofld_tx_data_wr));
+}
+
+static void cxgbi_conn_pdu_ready(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb;
+	unsigned int read = 0;
+	struct iscsi_conn *conn = csk->user_data;
+	int err = 0;
+
+	cxgbi_rx_debug("csk 0x%p.\n", csk);
+
+	read_lock(&csk->callback_lock);
+	if (unlikely(!conn || conn->suspend_rx)) {
+		cxgbi_rx_debug("conn 0x%p, id %d, suspend_rx %lu!\n",
+				conn, conn ? conn->id : 0xFF,
+				conn ? conn->suspend_rx : 0xFF);
+		read_unlock(&csk->callback_lock);
+		return;
+	}
+	skb = skb_peek(&csk->receive_queue);
+	while (!err && skb) {
+		__skb_unlink(skb, &csk->receive_queue);
+		read += cxgb4i_skb_rx_pdulen(skb);
+		cxgbi_rx_debug("conn 0x%p, csk 0x%p, rx skb 0x%p, pdulen %u\n",
+				conn, csk, skb, cxgb4i_skb_rx_pdulen(skb));
+		if (cxgb4i_skb_flags(skb) & CXGB4I_SKCB_FLAG_HDR_RCVD)
+			err = cxgbi_conn_read_bhs_pdu_skb(conn, skb);
+		else if (cxgb4i_skb_flags(skb) == CXGB4I_SKCB_FLAG_DATA_RCVD)
+			err = cxgbi_conn_read_data_pdu_skb(conn, skb);
+		__kfree_skb(skb);
+		skb = skb_peek(&csk->receive_queue);
+	}
+	read_unlock(&csk->callback_lock);
+	csk->copied_seq += read;
+	cxgb4i_sock_rx_credits(csk, read);
+	conn->rxdata_octets += read;
+
+	if (err) {
+		cxgbi_log_info("conn 0x%p rx failed err %d.\n", conn, err);
+		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+	}
+}
+
+static void cxgb4i_sock_closed(struct cxgbi_sock *csk)
+{
+	cxgbi_conn_debug("csk 0x%p, state %u, flags 0x%lx\n",
+			csk, csk->state, csk->flags);
+
+	cxgbi_sock_put_port(csk);
+	cxgb4i_sock_release_offload_resources(csk);
+	cxgbi_sock_set_state(csk, CXGBI_CSK_ST_CLOSED);
+	cxgbi_sock_conn_closing(csk);
+}
+
+static unsigned int cxgb4i_find_best_mtu(struct cxgb4i_snic *snic,
+						unsigned short mtu)
+{
+	int i = 0;
+
+	while (i < NMTUS - 1 && snic->lldi.mtus[i + 1] <= mtu)
+		++i;
+
+	return i;
+}
+
+static unsigned int cxgb4i_select_mss(struct cxgbi_sock *csk,
+						unsigned int pmtu)
+{
+	unsigned int idx;
+	struct dst_entry *dst = csk->dst;
+	u16 advmss = dst_metric(dst, RTAX_ADVMSS);
+
+	if (advmss > pmtu - 40)
+		advmss = pmtu - 40;
+	if (advmss < cxgb4i_get_snic(csk->cdev)->lldi.mtus[0] - 40)
+		advmss = cxgb4i_get_snic(csk->cdev)->lldi.mtus[0] - 40;
+	idx = cxgb4i_find_best_mtu(cxgb4i_get_snic(csk->cdev), advmss + 40);
+
+	return idx;
+}
+
+static inline int cxgb4i_sock_compute_wscale(int win)
+{
+	int wscale = 0;
+
+	while (wscale < 14 && (65535 << wscale) < win)
+		wscale++;
+
+	return wscale;
+}
+
+static void cxgb4i_sock_make_act_open_req(struct cxgbi_sock *csk,
+					   struct sk_buff *skb,
+					   unsigned int qid_atid,
+					   struct l2t_entry *e)
+{
+	struct cpl_act_open_req *req;
+	unsigned long long opt0;
+	unsigned int opt2;
+	int wscale;
+
+	cxgbi_conn_debug("csk 0x%p, atid 0x%x\n", csk, qid_atid);
+
+	wscale = cxgb4i_sock_compute_wscale(csk->mss_idx);
+
+	opt0 = KEEP_ALIVE(1) |
+		WND_SCALE(wscale) |
+		MSS_IDX(csk->mss_idx) |
+		L2T_IDX(((struct l2t_entry *)csk->l2t)->idx) |
+		TX_CHAN(csk->tx_chan) |
+		SMAC_SEL(csk->smac_idx) |
+		RCV_BUFSIZ(cxgb4i_rcv_win >> 10);
+
+	opt2 = RX_CHANNEL(0) |
+		RSS_QUEUE_VALID |
+		RSS_QUEUE(csk->rss_qid);
+
+	skb->queue_mapping = CPL_PRIORITY_SETUP;
+	req = (struct cpl_act_open_req *)__skb_put(skb, sizeof(*req));
+	INIT_TP_WR(req, 0);
+	OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ,
+					qid_atid));
+	req->local_port = csk->saddr.sin_port;
+	req->peer_port = csk->daddr.sin_port;
+	req->local_ip = csk->saddr.sin_addr.s_addr;
+	req->peer_ip = csk->daddr.sin_addr.s_addr;
+	req->opt0 = cpu_to_be64(opt0);
+	req->params = 0;
+	req->opt2 = cpu_to_be32(opt2);
+}
+
+static void cxgb4i_fail_act_open(struct cxgbi_sock *csk, int errno)
+{
+	cxgbi_conn_debug("csk 0%p, state %u, flag 0x%lx\n", csk,
+			csk->state, csk->flags);
+	csk->err = errno;
+	cxgb4i_sock_closed(csk);
+}
+
+static void cxgb4i_act_open_req_arp_failure(void *handle, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk = (struct cxgbi_sock *)skb->sk;
+
+	cxgbi_sock_hold(csk);
+	spin_lock_bh(&csk->lock);
+	if (csk->state == CXGBI_CSK_ST_CONNECTING)
+		cxgb4i_fail_act_open(csk, -EHOSTUNREACH);
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+	__kfree_skb(skb);
+}
+
+static void cxgb4i_sock_skb_entail(struct cxgbi_sock *csk,
+					struct sk_buff *skb,
+					int flags)
+{
+	cxgb4i_skb_tcp_seq(skb) = csk->write_seq;
+	cxgb4i_skb_flags(skb) = flags;
+	__skb_queue_tail(&csk->write_queue, skb);
+}
+
+static void cxgb4i_sock_send_close_req(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb = csk->cpl_close;
+	struct cpl_close_con_req *req = (struct cpl_close_con_req *)skb->head;
+	unsigned int tid = csk->hwtid;
+
+	csk->cpl_close = NULL;
+
+	skb->queue_mapping = CPL_PRIORITY_DATA;
+	INIT_TP_WR(req, tid);
+
+	OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_CLOSE_CON_REQ, tid));
+	req->rsvd = 0;
+
+	cxgb4i_sock_skb_entail(csk, skb, CXGB4I_SKCB_FLAG_NO_APPEND);
+	if (csk->state != CXGBI_CSK_ST_CONNECTING)
+		cxgb4i_sock_push_tx_frames(csk, 1);
+}
+
+static void cxgb4i_sock_abort_arp_failure(void *handle, struct sk_buff *skb)
+{
+	struct cpl_abort_req *req = cplhdr(skb);
+	struct cxgbi_sock *csk = (struct cxgbi_sock *)handle;
+	struct cxgb4i_snic *snic = cxgb4i_get_snic(csk->cdev);
+
+	req->cmd = CPL_ABORT_NO_RST;
+	cxgb4_ofld_send(snic->lldi.ports[csk->port_id], skb);
+}
+
+static inline void cxgb4i_sock_purge_write_queue(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb;
+
+	while ((skb = __skb_dequeue(&csk->write_queue)))
+		__kfree_skb(skb);
+}
+
+static void cxgb4i_sock_send_abort_req(struct cxgbi_sock *csk)
+{
+	struct cpl_abort_req *req;
+	struct sk_buff *skb = csk->cpl_abort_req;
+	struct cxgb4i_snic *snic = cxgb4i_get_snic(csk->cdev);
+
+	if (unlikely(csk->state == CXGBI_CSK_ST_ABORTING) ||
+			!skb || !csk->cdev)
+		return;
+
+	cxgbi_sock_set_state(csk, CXGBI_CSK_ST_ABORTING);
+
+	cxgbi_conn_debug("csk 0x%p, flag ABORT_RPL + ABORT_SHUT\n", csk);
+
+	cxgbi_sock_set_state(csk, CXGBI_CSK_FL_ABORT_RPL_PENDING);
+
+	cxgb4i_sock_purge_write_queue(csk);
+
+	csk->cpl_abort_req = NULL;
+	req = (struct cpl_abort_req *)skb->head;
+
+	skb->queue_mapping = CPL_PRIORITY_DATA;
+	t4_set_arp_err_handler(skb, csk, cxgb4i_sock_abort_arp_failure);
+	INIT_TP_WR(req, csk->hwtid);
+	OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_REQ, csk->hwtid));
+	req->rsvd0 = htonl(csk->snd_nxt);
+	req->rsvd1 = !cxgbi_sock_flag(csk, CXGBI_CSK_FL_TX_DATA_SENT);
+	req->cmd = CPL_ABORT_SEND_RST;
+
+	cxgb4_l2t_send(snic->lldi.ports[csk->port_id], skb, csk->l2t);
+}
+
+static void cxgb4i_sock_send_abort_rpl(struct cxgbi_sock *csk, int rst_status)
+{
+	struct sk_buff *skb = csk->cpl_abort_rpl;
+	struct cpl_abort_rpl *rpl = (struct cpl_abort_rpl *)skb->head;
+	struct cxgb4i_snic *snic = cxgb4i_get_snic(csk->cdev);
+
+	csk->cpl_abort_rpl = NULL;
+
+	skb->queue_mapping = CPL_PRIORITY_DATA;
+	INIT_TP_WR(rpl, csk->hwtid);
+	OPCODE_TID(rpl) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_RPL, csk->hwtid));
+	rpl->cmd = rst_status;
+
+	cxgb4_ofld_send(snic->lldi.ports[csk->port_id], skb);
+}
+
+static u32 cxgb4i_csk_send_rx_credits(struct cxgbi_sock *csk, u32 credits)
+{
+	struct sk_buff *skb;
+	struct cpl_rx_data_ack *req;
+	int wrlen = roundup(sizeof(*req), 16);
+	struct cxgb4i_snic *snic = cxgb4i_get_snic(csk->cdev);
+
+	skb = alloc_skb(wrlen, GFP_ATOMIC);
+	if (!skb)
+		return 0;
+
+	req = (struct cpl_rx_data_ack *)__skb_put(skb, wrlen);
+	memset(req, 0, wrlen);
+	skb->queue_mapping = CPL_PRIORITY_ACK;
+	INIT_TP_WR(req, csk->hwtid);
+	OPCODE_TID(req) =
+		cpu_to_be32(MK_OPCODE_TID(CPL_RX_DATA_ACK, csk->hwtid));
+	req->credit_dack = cpu_to_be32(RX_CREDITS(credits) | RX_FORCE_ACK(1));
+	cxgb4_ofld_send(snic->lldi.ports[csk->port_id], skb);
+	return credits;
+}
+
+
+#define SKB_WR_LIST_SIZE	(MAX_SKB_FRAGS + 2)
+
+static const unsigned int cxgb4i_ulp_extra_len[] = { 0, 4, 4, 8 };
+static inline unsigned int ulp_extra_len(const struct sk_buff *skb)
+{
+	return cxgb4i_ulp_extra_len[cxgb4i_skb_ulp_mode(skb) & 3];
+}
+
+static inline void cxgb4i_sock_reset_wr_list(struct cxgbi_sock *csk)
+{
+	csk->wr_pending_head = csk->wr_pending_tail = NULL;
+}
+
+static inline void cxgb4i_sock_enqueue_wr(struct cxgbi_sock *csk,
+						struct sk_buff *skb)
+{
+	cxgb4i_skb_tx_wr_next(skb) = NULL;
+
+	/*
+	 * We want to take an extra reference since both us and the driver
+	 * need to free the packet before it's really freed. We know there's
+	 * just one user currently so we use atomic_set rather than skb_get
+	 * to avoid the atomic op.
+	 */
+	atomic_set(&skb->users, 2);
+
+	if (!csk->wr_pending_head)
+		csk->wr_pending_head = skb;
+
+	else
+		cxgb4i_skb_tx_wr_next(csk->wr_pending_tail) = skb;
+
+	csk->wr_pending_tail = skb;
+}
+
+static int cxgb4i_sock_count_pending_wrs(const struct cxgbi_sock *csk)
+{
+	int n = 0;
+	const struct sk_buff *skb = csk->wr_pending_head;
+
+	while (skb) {
+		n += skb->csum;
+		skb = cxgb4i_skb_tx_wr_next(skb);
+	}
+	return n;
+}
+
+static inline struct sk_buff *cxgb4i_sock_peek_wr(const struct cxgbi_sock *csk)
+{
+	return csk->wr_pending_head;
+}
+
+static inline void cxgb4i_sock_free_wr_skb(struct sk_buff *skb)
+{
+	kfree_skb(skb);
+}
+
+static inline struct sk_buff *cxgb4i_sock_dequeue_wr(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb = csk->wr_pending_head;
+
+	if (likely(skb)) {
+		csk->wr_pending_head = cxgb4i_skb_tx_wr_next(skb);
+		cxgb4i_skb_tx_wr_next(skb) = NULL;
+	}
+	return skb;
+}
+
+static void cxgb4i_sock_purge_wr_queue(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb;
+
+	while ((skb = cxgb4i_sock_dequeue_wr(csk)) != NULL)
+		cxgb4i_sock_free_wr_skb(skb);
+}
+
+/*
+ * sgl_len - calculates the size of an SGL of the given capacity
+ * @n: the number of SGL entries
+ * Calculates the number of flits needed for a scatter/gather list that
+ * can hold the given number of entries.
+ */
+static inline unsigned int sgl_len(unsigned int n)
+{
+	n--;
+	return (3 * n) / 2 + (n & 1) + 2;
+}
+
+/*
+ * calc_tx_flits_ofld - calculate # of flits for an offload packet
+ * @skb: the packet
+ *
+ * Returns the number of flits needed for the given offload packet.
+ * These packets are already fully constructed and no additional headers
+ * will be added.
+ */
+static inline unsigned int calc_tx_flits_ofld(const struct sk_buff *skb)
+{
+	unsigned int flits, cnt;
+
+	if (is_ofld_imm(skb))
+		return DIV_ROUND_UP(skb->len, 8);
+
+	flits = skb_transport_offset(skb) / 8;
+	cnt = skb_shinfo(skb)->nr_frags;
+	if (skb->tail != skb->transport_header)
+		cnt++;
+	return flits + sgl_len(cnt);
+}
+
+static inline void cxgb4i_sock_send_tx_flowc_wr(struct cxgbi_sock *csk)
+{
+	struct sk_buff *skb;
+	struct fw_flowc_wr *flowc;
+	int flowclen, i;
+	struct cxgb4i_snic *snic = cxgb4i_get_snic(csk->cdev);
+
+	flowclen = 80;
+	skb = alloc_skb(flowclen, GFP_ATOMIC);
+	flowc = (struct fw_flowc_wr *)__skb_put(skb, flowclen);
+
+	flowc->op_to_nparams =
+		htonl(FW_WR_OP(FW_FLOWC_WR) | FW_FLOWC_WR_NPARAMS(8));
+	flowc->flowid_len16 =
+		htonl(FW_WR_LEN16(DIV_ROUND_UP(72, 16)) |
+				FW_WR_FLOWID(csk->hwtid));
+
+	flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN;
+	flowc->mnemval[0].val = htonl(0);
+	flowc->mnemval[1].mnemonic = FW_FLOWC_MNEM_CH;
+	flowc->mnemval[1].val = htonl(csk->tx_chan);
+	flowc->mnemval[2].mnemonic = FW_FLOWC_MNEM_PORT;
+	flowc->mnemval[2].val = htonl(csk->tx_chan);
+	flowc->mnemval[3].mnemonic = FW_FLOWC_MNEM_IQID;
+	flowc->mnemval[3].val = htonl(csk->rss_qid);
+	flowc->mnemval[4].mnemonic = FW_FLOWC_MNEM_SNDNXT;
+	flowc->mnemval[4].val = htonl(csk->snd_nxt);
+	flowc->mnemval[5].mnemonic = FW_FLOWC_MNEM_RCVNXT;
+	flowc->mnemval[5].val = htonl(csk->rcv_nxt);
+	flowc->mnemval[6].mnemonic = FW_FLOWC_MNEM_SNDBUF;
+	flowc->mnemval[6].val = htonl(cxgb4i_snd_win);
+	flowc->mnemval[7].mnemonic = FW_FLOWC_MNEM_MSS;
+	flowc->mnemval[7].val = htonl(csk->mss_idx);
+	flowc->mnemval[8].mnemonic = 0;
+	flowc->mnemval[8].val = 0;
+	for (i = 0; i < 9; i++) {
+		flowc->mnemval[i].r4[0] = 0;
+		flowc->mnemval[i].r4[1] = 0;
+		flowc->mnemval[i].r4[2] = 0;
+	}
+
+	skb->queue_mapping = CPL_PRIORITY_DATA;
+
+	cxgb4_ofld_send(snic->lldi.ports[csk->port_id], skb);
+}
+
+static inline void cxgb4i_sock_make_tx_data_wr(struct cxgbi_sock *csk,
+						struct sk_buff *skb, int dlen,
+						int len, u32 credits,
+						int req_completion)
+{
+	struct fw_ofld_tx_data_wr *req;
+	unsigned int wr_ulp_mode;
+
+	if (is_ofld_imm(skb)) {
+			req = (struct fw_ofld_tx_data_wr *)
+				__skb_push(skb, sizeof(*req));
+			req->op_to_immdlen =
+				cpu_to_be32(FW_WR_OP(FW_OFLD_TX_DATA_WR) |
+					FW_WR_COMPL(req_completion) |
+					FW_WR_IMMDLEN(dlen));
+			req->flowid_len16 =
+				cpu_to_be32(FW_WR_FLOWID(csk->hwtid) |
+						FW_WR_LEN16(credits));
+	} else {
+		req = (struct fw_ofld_tx_data_wr *)
+			__skb_push(skb, sizeof(*req));
+		req->op_to_immdlen =
+			cpu_to_be32(FW_WR_OP(FW_OFLD_TX_DATA_WR) |
+					FW_WR_COMPL(req_completion) |
+					FW_WR_IMMDLEN(0));
+		req->flowid_len16 =
+			cpu_to_be32(FW_WR_FLOWID(csk->hwtid) |
+					FW_WR_LEN16(credits));
+	}
+
+	wr_ulp_mode =
+		FW_OFLD_TX_DATA_WR_ULPMODE(cxgb4i_skb_ulp_mode(skb) >> 4) |
+		FW_OFLD_TX_DATA_WR_ULPSUBMODE(cxgb4i_skb_ulp_mode(skb) & 3);
+
+	req->tunnel_to_proxy = cpu_to_be32(wr_ulp_mode) |
+		FW_OFLD_TX_DATA_WR_SHOVE(skb_peek(&csk->write_queue) ? 0 : 1);
+
+	req->plen = cpu_to_be32(len);
+
+	if (!cxgbi_sock_flag(csk, CXGBI_CSK_FL_TX_DATA_SENT))
+		cxgbi_sock_set_flag(csk, CXGBI_CSK_FL_TX_DATA_SENT);
+}
+
+static void cxgb4i_sock_arp_failure_discard(void *handle, struct sk_buff *skb)
+{
+	kfree_skb(skb);
+}
+
+static int cxgb4i_sock_push_tx_frames(struct cxgbi_sock *csk,
+						int req_completion)
+{
+	int total_size = 0;
+	struct sk_buff *skb;
+	struct cxgb4i_snic *snic;
+
+	if (unlikely(csk->state == CXGBI_CSK_ST_CONNECTING ||
+				csk->state == CXGBI_CSK_ST_CLOSE_WAIT_1 ||
+				csk->state >= CXGBI_CSK_ST_ABORTING)) {
+		cxgbi_tx_debug("csk 0x%p, in closing state %u.\n",
+				csk, csk->state);
+		return 0;
+	}
+
+	snic = cxgb4i_get_snic(csk->cdev);
+
+	while (csk->wr_cred
+			&& (skb = skb_peek(&csk->write_queue)) != NULL) {
+		int dlen;
+		int len;
+		unsigned int credits_needed;
+
+		dlen = len = skb->len;
+		skb_reset_transport_header(skb);
+
+		if (is_ofld_imm(skb))
+			credits_needed = DIV_ROUND_UP(dlen +
+					sizeof(struct fw_ofld_tx_data_wr), 16);
+		else
+			credits_needed = DIV_ROUND_UP(8 *
+					calc_tx_flits_ofld(skb)+
+					sizeof(struct fw_ofld_tx_data_wr), 16);
+
+		if (csk->wr_cred < credits_needed) {
+			cxgbi_tx_debug("csk 0x%p, skb len %u/%u, "
+					"wr %d < %u.\n",
+					csk, skb->len, skb->data_len,
+					credits_needed, csk->wr_cred);
+			break;
+		}
+
+		__skb_unlink(skb, &csk->write_queue);
+		skb->queue_mapping = CPL_PRIORITY_DATA;
+		skb->csum = credits_needed; /* remember this until the WR_ACK */
+		csk->wr_cred -= credits_needed;
+		csk->wr_una_cred += credits_needed;
+		cxgb4i_sock_enqueue_wr(csk, skb);
+
+		cxgbi_tx_debug("csk 0x%p, enqueue, skb len %u/%u, "
+				"wr %d, left %u, unack %u.\n",
+				csk, skb->len, skb->data_len,
+				credits_needed, csk->wr_cred,
+				csk->wr_una_cred);
+
+
+		if (likely(cxgb4i_skb_flags(skb) &
+					CXGB4I_SKCB_FLAG_NEED_HDR)) {
+			len += ulp_extra_len(skb);
+			if (!cxgbi_sock_flag(csk,
+						CXGBI_CSK_FL_TX_DATA_SENT)) {
+				cxgb4i_sock_send_tx_flowc_wr(csk);
+				skb->csum += 5;
+				csk->wr_cred -= 5;
+				csk->wr_una_cred += 5;
+			}
+
+			if ((req_completion &&
+				csk->wr_una_cred == credits_needed) ||
+				(cxgb4i_skb_flags(skb) &
+				  CXGB4I_SKCB_FLAG_COMPL) ||
+				csk->wr_una_cred >= csk->wr_max_cred / 2) {
+				req_completion = 1;
+				csk->wr_una_cred = 0;
+			}
+			cxgb4i_sock_make_tx_data_wr(csk, skb, dlen, len,
+							credits_needed,
+							req_completion);
+			csk->snd_nxt += len;
+
+			if (req_completion)
+				cxgb4i_skb_flags(skb) &=
+					~CXGB4I_SKCB_FLAG_NEED_HDR;
+		}
+
+		total_size += skb->truesize;
+		t4_set_arp_err_handler(skb, csk,
+					cxgb4i_sock_arp_failure_discard);
+		cxgb4_l2t_send(snic->lldi.ports[csk->port_id], skb, csk->l2t);
+	}
+	return total_size;
+}
+
+static inline void cxgb4i_sock_free_atid(struct cxgbi_sock *csk)
+{
+	cxgb4_free_atid(cxgb4i_get_snic(csk->cdev)->lldi.tids, csk->atid);
+	cxgbi_sock_put(csk);
+}
+
+static void cxgb4i_sock_established(struct cxgbi_sock *csk, u32 snd_isn,
+					unsigned int opt)
+{
+	cxgbi_conn_debug("csk 0x%p, state %u.\n", csk, csk->state);
+
+	csk->write_seq = csk->snd_nxt = csk->snd_una = snd_isn;
+
+	/*
+	 * Causes the first RX_DATA_ACK to supply any Rx credits we couldn't
+	 * pass through opt0.
+	 */
+	if (cxgb4i_rcv_win > (RCV_BUFSIZ_MASK << 10))
+		csk->rcv_wup -= cxgb4i_rcv_win - (RCV_BUFSIZ_MASK << 10);
+
+	dst_confirm(csk->dst);
+
+	smp_mb();
+
+	cxgbi_sock_set_state(csk, CXGBI_CSK_ST_ESTABLISHED);
+}
+
+static int cxgb4i_cpl_act_establish(struct cxgb4i_snic *snic,
+						struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_act_establish *req = cplhdr(skb);
+	unsigned int hwtid = GET_TID(req);
+	unsigned int atid = GET_TID_TID(ntohl(req->tos_atid));
+	struct tid_info *t = snic->lldi.tids;
+	u32 rcv_isn = be32_to_cpu(req->rcv_isn);
+
+	csk = lookup_atid(t, atid);
+
+	if (unlikely(!csk)) {
+		cxgbi_log_error("can't find connection for tid %u\n", hwtid);
+		return CPL_RET_UNKNOWN_TID;
+	}
+
+	cxgbi_conn_debug("csk 0x%p, state %u, flag 0x%lx\n",
+				csk, csk->state, csk->flags);
+	csk->hwtid = hwtid;
+	cxgbi_sock_hold(csk);
+	cxgb4_insert_tid(snic->lldi.tids, csk, hwtid);
+	cxgb4_free_atid(snic->lldi.tids, atid);
+
+	spin_lock_bh(&csk->lock);
+
+	if (unlikely(csk->state != CXGBI_CSK_ST_CONNECTING))
+		cxgbi_log_error("TID %u expected SYN_SENT, got EST., s %u\n",
+				csk->hwtid, csk->state);
+
+	csk->copied_seq = csk->rcv_wup = csk->rcv_nxt = rcv_isn;
+	cxgb4i_sock_established(csk, ntohl(req->snd_isn), ntohs(req->tcp_opt));
+
+	__kfree_skb(skb);
+
+	if (unlikely(cxgbi_sock_flag(csk, CXGBI_CSK_FL_ACTIVE_CLOSE_NEEDED)))
+		cxgb4i_sock_send_abort_req(csk);
+	else {
+		if (skb_queue_len(&csk->write_queue))
+			cxgb4i_sock_push_tx_frames(csk, 1);
+
+		cxgbi_conn_tx_open(csk);
+	}
+
+	spin_unlock_bh(&csk->lock);
+
+	return 0;
+}
+
+static int act_open_rpl_status_to_errno(int status)
+{
+	switch (status) {
+	case CPL_ERR_CONN_RESET:
+		return -ECONNREFUSED;
+	case CPL_ERR_ARP_MISS:
+		return -EHOSTUNREACH;
+	case CPL_ERR_CONN_TIMEDOUT:
+		return -ETIMEDOUT;
+	case CPL_ERR_TCAM_FULL:
+		return -ENOMEM;
+	case CPL_ERR_CONN_EXIST:
+		cxgbi_log_error("ACTIVE_OPEN_RPL: 4-tuple in use\n");
+		return -EADDRINUSE;
+	default:
+		return -EIO;
+	}
+}
+
+/*
+ * Return whether a failed active open has allocated a TID
+ */
+static inline int act_open_has_tid(int status)
+{
+	return status != CPL_ERR_TCAM_FULL && status != CPL_ERR_CONN_EXIST &&
+		status != CPL_ERR_ARP_MISS;
+}
+
+static void cxgb4i_sock_act_open_retry_timer(unsigned long data)
+{
+	struct sk_buff *skb;
+	struct cxgbi_sock *csk = (struct cxgbi_sock *)data;
+	struct cxgb4i_snic *snic = cxgb4i_get_snic(csk->cdev);
+
+	cxgbi_conn_debug("csk 0x%p, state %u.\n", csk, csk->state);
+
+	spin_lock_bh(&csk->lock);
+	skb = alloc_skb(sizeof(struct cpl_act_open_req), GFP_ATOMIC);
+	if (!skb)
+		cxgb4i_fail_act_open(csk, -ENOMEM);
+	else {
+		unsigned int qid_atid  = csk->rss_qid << 14;
+		qid_atid |= (unsigned int)csk->atid;
+		skb->sk = (struct sock *)csk;
+		t4_set_arp_err_handler(skb, csk,
+					cxgb4i_act_open_req_arp_failure);
+		cxgb4i_sock_make_act_open_req(csk, skb, qid_atid, csk->l2t);
+		cxgb4_l2t_send(snic->lldi.ports[csk->port_id], skb, csk->l2t);
+	}
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+}
+
+static int cxgb4i_cpl_act_open_rpl(struct cxgb4i_snic *snic,
+						struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_act_open_rpl *rpl = cplhdr(skb);
+	unsigned int atid =
+		GET_TID_TID(GET_AOPEN_ATID(be32_to_cpu(rpl->atid_status)));
+	struct tid_info *t = snic->lldi.tids;
+	unsigned int status = GET_AOPEN_STATUS(be32_to_cpu(rpl->atid_status));
+
+	csk = lookup_atid(t, atid);
+
+	if (unlikely(!csk)) {
+		cxgbi_log_error("can't find connection for tid %u\n", atid);
+		return CPL_RET_UNKNOWN_TID;
+	}
+
+	cxgbi_sock_hold(csk);
+	spin_lock_bh(&csk->lock);
+
+	cxgbi_conn_debug("rcv, status 0x%x, csk 0x%p, csk->state %u, "
+			"csk->flag 0x%lx, csk->atid %u.\n",
+			status, csk, csk->state, csk->flags, csk->hwtid);
+
+	if (status & act_open_has_tid(status))
+		cxgb4_remove_tid(snic->lldi.tids, csk->port_id, GET_TID(rpl));
+
+	if (status == CPL_ERR_CONN_EXIST &&
+			csk->retry_timer.function !=
+			cxgb4i_sock_act_open_retry_timer) {
+		csk->retry_timer.function = cxgb4i_sock_act_open_retry_timer;
+		if (!mod_timer(&csk->retry_timer, jiffies + HZ / 2))
+			cxgbi_sock_hold(csk);
+	} else
+
+		cxgb4i_fail_act_open(csk, act_open_rpl_status_to_errno(status));
+
+	__kfree_skb(skb);
+
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+
+	return 0;
+}
+
+static int cxgb4i_cpl_peer_close(struct cxgb4i_snic *snic, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_peer_close *req = cplhdr(skb);
+	unsigned int hwtid = GET_TID(req);
+	struct tid_info *t = snic->lldi.tids;
+
+	csk = lookup_tid(t, hwtid);
+
+	if (unlikely(!csk)) {
+		cxgbi_log_error("can't find connection for tid %u\n", hwtid);
+		return CPL_RET_UNKNOWN_TID;
+	}
+
+	cxgbi_sock_hold(csk);
+	spin_lock_bh(&csk->lock);
+
+	if (cxgbi_sock_flag(csk, CXGBI_CSK_FL_ABORT_RPL_PENDING))
+		goto out;
+
+	switch (csk->state) {
+	case CXGBI_CSK_ST_ESTABLISHED:
+		cxgbi_sock_set_state(csk, CXGBI_CSK_ST_PASSIVE_CLOSE);
+		break;
+	case CXGBI_CSK_ST_ACTIVE_CLOSE:
+		cxgbi_sock_set_state(csk, CXGBI_CSK_ST_CLOSE_WAIT_2);
+		break;
+	case CXGBI_CSK_ST_CLOSE_WAIT_1:
+		cxgb4i_sock_closed(csk);
+		break;
+	case CXGBI_CSK_ST_ABORTING:
+		break;
+	default:
+		cxgbi_log_error("peer close, TID %u in bad state %u\n",
+				csk->hwtid, csk->state);
+	}
+
+	cxgbi_sock_conn_closing(csk);
+
+out:
+	__kfree_skb(skb);
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+
+	return 0;
+}
+
+static int cxgb4i_cpl_close_con_rpl(struct cxgb4i_snic *snic,
+						struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_close_con_rpl *rpl = cplhdr(skb);
+	unsigned int hwtid = GET_TID(rpl);
+	struct tid_info *t = snic->lldi.tids;
+
+	csk = lookup_tid(t, hwtid);
+
+	if (unlikely(!csk)) {
+		cxgbi_log_error("can't find connection for tid %u\n", hwtid);
+		return CPL_RET_UNKNOWN_TID;
+	}
+
+	cxgbi_sock_hold(csk);
+	spin_lock_bh(&csk->lock);
+
+	cxgbi_conn_debug("csk 0x%p, state %u, flag 0x%lx.\n",
+			csk, csk->state, csk->flags);
+
+	csk->snd_una = ntohl(rpl->snd_nxt) - 1;
+
+	if (cxgbi_sock_flag(csk, CXGBI_CSK_FL_ABORT_RPL_PENDING))
+		goto out;
+
+	switch (csk->state) {
+	case CXGBI_CSK_ST_ACTIVE_CLOSE:
+		cxgbi_sock_set_state(csk, CXGBI_CSK_ST_CLOSE_WAIT_1);
+		break;
+	case CXGBI_CSK_ST_CLOSE_WAIT_1:
+	case CXGBI_CSK_ST_CLOSE_WAIT_2:
+		cxgb4i_sock_closed(csk);
+		break;
+	case CXGBI_CSK_ST_ABORTING:
+		break;
+	default:
+		cxgbi_log_error("close_rpl, TID %u in bad state %u\n",
+				csk->hwtid, csk->state);
+	}
+out:
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+	kfree_skb(skb);
+
+	return 0;
+}
+
+static int abort_status_to_errno(struct cxgbi_sock *csk, int abort_reason,
+								int *need_rst)
+{
+	switch (abort_reason) {
+	case CPL_ERR_BAD_SYN: /* fall through */
+	case CPL_ERR_CONN_RESET:
+		return csk->state > CXGBI_CSK_ST_ESTABLISHED ?
+			-EPIPE : -ECONNRESET;
+	case CPL_ERR_XMIT_TIMEDOUT:
+	case CPL_ERR_PERSIST_TIMEDOUT:
+	case CPL_ERR_FINWAIT2_TIMEDOUT:
+	case CPL_ERR_KEEPALIVE_TIMEDOUT:
+		return -ETIMEDOUT;
+	default:
+		return -EIO;
+	}
+}
+
+/*
+ * Returns whether an ABORT_REQ_RSS message is a negative advice.
+ */
+static inline int is_neg_adv_abort(unsigned int status)
+{
+	return status == CPL_ERR_RTX_NEG_ADVICE ||
+		status == CPL_ERR_PERSIST_NEG_ADVICE;
+}
+
+static int cxgb4i_cpl_abort_req_rss(struct cxgb4i_snic *snic,
+						struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_abort_req_rss *req = cplhdr(skb);
+	unsigned int hwtid = GET_TID(req);
+	struct tid_info *t = snic->lldi.tids;
+	int rst_status = CPL_ABORT_NO_RST;
+
+	csk = lookup_tid(t, hwtid);
+	if (unlikely(!csk)) {
+		cxgbi_log_error("can't find connection for tid %u\n", hwtid);
+		return CPL_RET_UNKNOWN_TID;
+	}
+
+	cxgbi_sock_hold(csk);
+	spin_lock_bh(&csk->lock);
+
+	if (is_neg_adv_abort(req->status)) {
+		__kfree_skb(skb);
+		return 0;
+	}
+
+	if (!cxgbi_sock_flag(csk, CXGBI_CSK_FL_ABORT_REQ_RCVD)) {
+		cxgbi_sock_set_flag(csk, CXGBI_CSK_FL_ABORT_REQ_RCVD);
+		cxgbi_sock_set_state(csk, CXGBI_CSK_ST_ABORTING);
+		__kfree_skb(skb);
+		return 0;
+	}
+
+	cxgbi_sock_clear_flag(csk, CXGBI_CSK_FL_ABORT_REQ_RCVD);
+	cxgb4i_sock_send_abort_rpl(csk, rst_status);
+
+	if (!cxgbi_sock_flag(csk, CXGBI_CSK_FL_ABORT_RPL_PENDING)) {
+		csk->err = abort_status_to_errno(csk, req->status,
+							&rst_status);
+		cxgb4i_sock_closed(csk);
+	}
+
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+
+	return 0;
+}
+
+static int cxgb4i_cpl_abort_rpl_rss(struct cxgb4i_snic *snic,
+						struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_abort_rpl_rss *rpl = cplhdr(skb);
+	unsigned int hwtid = GET_TID(rpl);
+	struct tid_info *t = snic->lldi.tids;
+
+	if (rpl->status == CPL_ERR_ABORT_FAILED)
+		goto out;
+
+	csk = lookup_tid(t, hwtid);
+	if (unlikely(!csk)) {
+		cxgbi_log_error("can't find connection for tid %u\n", hwtid);
+		goto out;
+	}
+
+	cxgbi_sock_hold(csk);
+	spin_lock_bh(&csk->lock);
+
+	if (cxgbi_sock_flag(csk, CXGBI_CSK_FL_ABORT_RPL_PENDING)) {
+		if (!cxgbi_sock_flag(csk, CXGBI_CSK_FL_ABORT_RPL_RCVD))
+			cxgbi_sock_set_flag(csk,
+						CXGBI_CSK_FL_ABORT_RPL_RCVD);
+		else {
+			cxgbi_sock_clear_flag(csk,
+						CXGBI_CSK_FL_ABORT_RPL_RCVD);
+			cxgbi_sock_clear_flag(csk,
+					CXGBI_CSK_FL_ABORT_RPL_PENDING);
+
+			if (cxgbi_sock_flag(csk,
+						CXGBI_CSK_FL_ABORT_REQ_RCVD))
+				cxgbi_log_error("tid %u, ABORT_RPL_RSS\n",
+						csk->hwtid);
+
+			cxgb4i_sock_closed(csk);
+		}
+	}
+
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+
+out:
+	__kfree_skb(skb);
+	return 0;
+}
+
+static int cxgb4i_cpl_iscsi_hdr(struct cxgb4i_snic *snic, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_iscsi_hdr *cpl = cplhdr(skb);
+	unsigned int hwtid = GET_TID(cpl);
+	struct tid_info *t = snic->lldi.tids;
+	struct sk_buff *lskb;
+
+	csk = lookup_tid(t, hwtid);
+
+	if (unlikely(!csk)) {
+		cxgbi_log_error("can't find connection for tid %u\n", hwtid);
+		return CPL_RET_UNKNOWN_TID;
+	}
+
+	spin_lock_bh(&csk->lock);
+
+	if (unlikely(csk->state >= CXGBI_CSK_ST_PASSIVE_CLOSE)) {
+		if (csk->state != CXGBI_CSK_ST_ABORTING)
+			goto abort_conn;
+	}
+
+	cxgb4i_skb_tcp_seq(skb) = ntohl(cpl->seq);
+	cxgb4i_skb_flags(skb) = 0;
+
+	skb_reset_transport_header(skb);
+	__skb_pull(skb, sizeof(*cpl));
+	__pskb_trim(skb, ntohs(cpl->len));
+
+	if (!csk->skb_ulp_lhdr) {
+		unsigned char *byte;
+		csk->skb_ulp_lhdr = skb;
+		lskb = csk->skb_ulp_lhdr;
+
+		cxgb4i_skb_flags(lskb) = CXGB4I_SKCB_FLAG_HDR_RCVD;
+
+		if (cxgb4i_skb_tcp_seq(lskb) != csk->rcv_nxt) {
+			cxgbi_log_error("tid 0x%x, CPL_ISCSI_HDR, bad seq got "
+					"0x%x, exp 0x%x\n",
+					csk->hwtid,
+					cxgb4i_skb_tcp_seq(lskb),
+					csk->rcv_nxt);
+		}
+
+		byte = skb->data;
+		cxgb4i_skb_rx_pdulen(skb) = ntohs(cpl->pdu_len_ddp) - 40;
+		csk->rcv_nxt += cxgb4i_skb_rx_pdulen(lskb);
+	} else {
+		lskb = csk->skb_ulp_lhdr;
+		cxgb4i_skb_flags(lskb) |= CXGB4I_SKCB_FLAG_DATA_RCVD;
+		cxgb4i_skb_flags(skb) = CXGB4I_SKCB_FLAG_DATA_RCVD;
+		cxgbi_log_debug("csk 0x%p, tid 0x%x skb 0x%p, pdu data, "
+				" header 0x%p.\n",
+				csk, csk->hwtid, skb, lskb);
+	}
+
+	__skb_queue_tail(&csk->receive_queue, skb);
+
+	spin_unlock_bh(&csk->lock);
+
+	return 0;
+
+abort_conn:
+	cxgb4i_sock_send_abort_req(csk);
+	__kfree_skb(skb);
+	spin_unlock_bh(&csk->lock);
+
+	return -EINVAL;
+}
+
+static int cxgb4i_cpl_rx_data_ddp(struct cxgb4i_snic *snic, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct sk_buff *lskb;
+	struct cpl_rx_data_ddp *rpl = cplhdr(skb);
+	unsigned int hwtid = GET_TID(rpl);
+	struct tid_info *t = snic->lldi.tids;
+	unsigned int status;
+
+	csk = lookup_tid(t, hwtid);
+
+	if (unlikely(!csk)) {
+		cxgbi_log_error("can't find connection for tid %u\n", hwtid);
+		return CPL_RET_UNKNOWN_TID;
+	}
+
+	spin_lock_bh(&csk->lock);
+
+	if (unlikely(csk->state >= CXGBI_CSK_ST_PASSIVE_CLOSE)) {
+		if (csk->state != CXGBI_CSK_ST_ABORTING)
+			goto abort_conn;
+	}
+
+	if (!csk->skb_ulp_lhdr) {
+		cxgbi_log_error("tid 0x%x, rcv RX_DATA_DDP w/o pdu header\n",
+				csk->hwtid);
+		goto abort_conn;
+	}
+
+	lskb = csk->skb_ulp_lhdr;
+	cxgb4i_skb_flags(lskb) |= CXGB4I_SKCB_FLAG_STATUS_RCVD;
+
+	if (ntohs(rpl->len) != cxgb4i_skb_rx_pdulen(lskb)) {
+		cxgbi_log_error("tid 0x%x, RX_DATA_DDP pdulen %u != %u.\n",
+				csk->hwtid, ntohs(rpl->len),
+				cxgb4i_skb_rx_pdulen(lskb));
+	}
+
+	cxgb4i_skb_rx_ddigest(lskb) = ntohl(rpl->ulp_crc);
+	status = ntohl(rpl->ddpvld);
+
+	if (status & (1 << RX_DDP_STATUS_HCRC_SHIFT))
+		cxgb4i_skb_ulp_mode(skb) |= ULP2_FLAG_HCRC_ERROR;
+	if (status & (1 << RX_DDP_STATUS_DCRC_SHIFT))
+		cxgb4i_skb_ulp_mode(skb) |= ULP2_FLAG_DCRC_ERROR;
+	if (status & (1 << RX_DDP_STATUS_PAD_SHIFT))
+		cxgb4i_skb_ulp_mode(skb) |= ULP2_FLAG_PAD_ERROR;
+	if ((cxgb4i_skb_flags(lskb) & ULP2_FLAG_DATA_READY))
+		cxgb4i_skb_ulp_mode(skb) |= ULP2_FLAG_DATA_DDPED;
+
+	csk->skb_ulp_lhdr = NULL;
+
+	__kfree_skb(skb);
+	cxgbi_conn_pdu_ready(csk);
+	spin_unlock_bh(&csk->lock);
+
+	return 0;
+
+abort_conn:
+	cxgb4i_sock_send_abort_req(csk);
+	__kfree_skb(skb);
+	spin_unlock_bh(&csk->lock);
+	return -EINVAL;
+}
+
+static void check_wr_invariants(const struct cxgbi_sock *csk)
+{
+	int pending = cxgb4i_sock_count_pending_wrs(csk);
+
+	if (unlikely(csk->wr_cred + pending != csk->wr_max_cred))
+		printk(KERN_ERR "TID %u: credit imbalance: avail %u, "
+				"pending %u, total should be %u\n",
+				csk->hwtid,
+				csk->wr_cred,
+				pending,
+				csk->wr_max_cred);
+}
+
+static int cxgb4i_cpl_fw4_ack(struct cxgb4i_snic *snic, struct sk_buff *skb)
+{
+	struct cxgbi_sock *csk;
+	struct cpl_fw4_ack *rpl = cplhdr(skb);
+	unsigned int hwtid = GET_TID(rpl);
+	struct tid_info *t = snic->lldi.tids;
+	unsigned char credits;
+	unsigned int snd_una;
+
+	csk = lookup_tid(t, hwtid);
+	if (unlikely(!csk)) {
+		cxgbi_log_error("can't find connection for tid %u\n", hwtid);
+		kfree_skb(skb);
+		return CPL_RET_UNKNOWN_TID;
+	}
+
+	cxgbi_sock_hold(csk);
+	spin_lock_bh(&csk->lock);
+
+	credits = rpl->credits;
+	snd_una = be32_to_cpu(rpl->snd_una);
+
+	cxgbi_tx_debug("%u WR credits, avail %u, unack %u, TID %u, state %u\n",
+				credits, csk->wr_cred, csk->wr_una_cred,
+						csk->hwtid, csk->state);
+
+	csk->wr_cred += credits;
+
+	if (csk->wr_una_cred > csk->wr_max_cred - csk->wr_cred)
+		csk->wr_una_cred = csk->wr_max_cred - csk->wr_cred;
+
+	while (credits) {
+		struct sk_buff *p = cxgb4i_sock_peek_wr(csk);
+
+		if (unlikely(!p)) {
+			cxgbi_log_error("%u WR_ACK credits for TID %u with "
+					"nothing pending, state %u\n",
+					credits, csk->hwtid, csk->state);
+			break;
+		}
+
+		if (unlikely(credits < p->csum)) {
+			p->csum -= credits;
+		} else {
+			cxgb4i_sock_dequeue_wr(csk);
+			credits -= p->csum;
+			cxgb4i_sock_free_wr_skb(p);
+		}
+	}
+
+	check_wr_invariants(csk);
+
+	if (rpl->seq_vld) {
+		if (unlikely(before(snd_una, csk->snd_una))) {
+			cxgbi_log_error("TID %u, unexpected sequence # %u "
+					"in WR_ACK snd_una %u\n",
+					csk->hwtid, snd_una, csk->snd_una);
+			goto out_free;
+		}
+	}
+
+	if (csk->snd_una != snd_una) {
+		csk->snd_una = snd_una;
+		dst_confirm(csk->dst);
+	}
+
+	if (skb_queue_len(&csk->write_queue)) {
+		if (cxgb4i_sock_push_tx_frames(csk, 0))
+			cxgbi_conn_tx_open(csk);
+	} else
+		cxgbi_conn_tx_open(csk);
+
+	goto out;
+
+out_free:
+
+	__kfree_skb(skb);
+
+out:
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+
+	return 0;
+}
+
+static int cxgb4i_cpl_set_tcb_rpl(struct cxgb4i_snic *snic, struct sk_buff *skb)
+{
+	struct cpl_set_tcb_rpl *rpl = cplhdr(skb);
+	unsigned int hwtid = GET_TID(rpl);
+	struct tid_info *t = snic->lldi.tids;
+	struct cxgbi_sock *csk;
+
+	csk = lookup_tid(t, hwtid);
+
+	if (!csk) {
+		cxgbi_log_error("can't find connection for tid %u\n", hwtid);
+		__kfree_skb(skb);
+		return CPL_RET_UNKNOWN_TID;
+	}
+
+	spin_lock_bh(&csk->lock);
+
+	if (rpl->status != CPL_ERR_NONE) {
+		cxgbi_log_error("Unexpected SET_TCB_RPL status %u "
+				 "for tid %u\n", rpl->status, GET_TID(rpl));
+	}
+
+	__kfree_skb(skb);
+	spin_unlock_bh(&csk->lock);
+
+	return 0;
+}
+
+static void cxgb4i_sock_free_cpl_skbs(struct cxgbi_sock *csk)
+{
+	if (csk->cpl_close)
+		kfree_skb(csk->cpl_close);
+	if (csk->cpl_abort_req)
+		kfree_skb(csk->cpl_abort_req);
+	if (csk->cpl_abort_rpl)
+		kfree_skb(csk->cpl_abort_rpl);
+}
+
+static int cxgb4i_alloc_cpl_skbs(struct cxgbi_sock *csk)
+{
+	csk->cpl_close = alloc_skb(sizeof(struct cpl_close_con_req),
+					GFP_KERNEL);
+	if (!csk->cpl_close)
+		return -ENOMEM;
+	skb_put(csk->cpl_close, sizeof(struct cpl_close_con_req));
+
+	csk->cpl_abort_req = alloc_skb(sizeof(struct cpl_abort_req),
+					GFP_KERNEL);
+	if (!csk->cpl_abort_req)
+		goto free_cpl_skbs;
+	skb_put(csk->cpl_abort_req, sizeof(struct cpl_abort_req));
+
+	csk->cpl_abort_rpl = alloc_skb(sizeof(struct cpl_abort_rpl),
+					GFP_KERNEL);
+	if (!csk->cpl_abort_rpl)
+		goto free_cpl_skbs;
+	skb_put(csk->cpl_abort_rpl, sizeof(struct cpl_abort_rpl));
+
+	return 0;
+
+free_cpl_skbs:
+	cxgb4i_sock_free_cpl_skbs(csk);
+	return -ENOMEM;
+}
+
+static void cxgb4i_sock_release_offload_resources(struct cxgbi_sock *csk)
+{
+
+	cxgb4i_sock_free_cpl_skbs(csk);
+
+	if (csk->wr_cred != csk->wr_max_cred) {
+		cxgb4i_sock_purge_wr_queue(csk);
+		cxgb4i_sock_reset_wr_list(csk);
+	}
+
+	if (csk->l2t) {
+		cxgb4_l2t_release(csk->l2t);
+		csk->l2t = NULL;
+	}
+
+	if (csk->state == CXGBI_CSK_ST_CONNECTING)
+		cxgb4i_sock_free_atid(csk);
+	else {
+		cxgb4_remove_tid(cxgb4i_get_snic(csk->cdev)->lldi.tids, 0,
+				csk->hwtid);
+		cxgbi_sock_put(csk);
+	}
+
+	csk->dst = NULL;
+	csk->cdev = NULL;
+}
+
+struct cxgbi_sock *cxgb4i_sock_create(struct cxgb4i_snic *snic)
+{
+	struct cxgbi_sock *csk = NULL;
+
+	csk = kzalloc(sizeof(*csk), GFP_KERNEL);
+	if (!csk)
+		return NULL;
+
+	if (cxgb4i_alloc_cpl_skbs(csk) < 0)
+		goto free_csk;
+
+	cxgbi_conn_debug("alloc csk: 0x%p\n", csk);
+
+	csk->flags = 0;
+	spin_lock_init(&csk->lock);
+	atomic_set(&csk->refcnt, 1);
+	skb_queue_head_init(&csk->receive_queue);
+	skb_queue_head_init(&csk->write_queue);
+	setup_timer(&csk->retry_timer, NULL, (unsigned long)csk);
+	rwlock_init(&csk->callback_lock);
+	csk->cdev = &snic->cdev;
+
+	return csk;
+
+free_csk:
+	cxgbi_api_debug("csk alloc failed %p, baling out\n", csk);
+	kfree(csk);
+	return NULL;
+}
+
+static void cxgb4i_sock_active_close(struct cxgbi_sock *csk)
+{
+	int data_lost;
+	int close_req = 0;
+
+	cxgbi_conn_debug("csk 0x%p, state %u, flags %lu\n",
+			csk, csk->state, csk->flags);
+
+	dst_confirm(csk->dst);
+
+	cxgbi_sock_hold(csk);
+	spin_lock_bh(&csk->lock);
+
+	data_lost = skb_queue_len(&csk->receive_queue);
+	__skb_queue_purge(&csk->receive_queue);
+
+	switch (csk->state) {
+	case CXGBI_CSK_ST_CLOSED:
+	case CXGBI_CSK_ST_ACTIVE_CLOSE:
+	case CXGBI_CSK_ST_CLOSE_WAIT_1:
+	case CXGBI_CSK_ST_CLOSE_WAIT_2:
+	case CXGBI_CSK_ST_ABORTING:
+		break;
+
+	case CXGBI_CSK_ST_CONNECTING:
+		cxgbi_sock_set_flag(csk, CXGBI_CSK_FL_ACTIVE_CLOSE_NEEDED);
+		break;
+	case CXGBI_CSK_ST_ESTABLISHED:
+		close_req = 1;
+		cxgbi_sock_set_flag(csk, CXGBI_CSK_ST_CLOSE_WAIT_2);
+		break;
+	}
+
+	if (close_req) {
+		if (data_lost)
+			cxgb4i_sock_send_abort_req(csk);
+		else
+			cxgb4i_sock_send_close_req(csk);
+	}
+
+	spin_unlock_bh(&csk->lock);
+	cxgbi_sock_put(csk);
+}
+
+void cxgb4i_sock_release(struct cxgbi_sock *csk)
+{
+	cxgbi_conn_debug("csk 0x%p, state %u, flags %lu\n",
+			csk, csk->state, csk->flags);
+
+	if (unlikely(csk->state == CXGBI_CSK_ST_CONNECTING))
+		cxgbi_sock_set_state(csk,
+				CXGBI_CSK_FL_ACTIVE_CLOSE_NEEDED);
+	else if (likely(csk->state != CXGBI_CSK_ST_CLOSED))
+		cxgb4i_sock_active_close(csk);
+
+	cxgbi_sock_put(csk);
+}
+
+static int is_cxgb4_dev(struct net_device *dev, struct cxgb4i_snic *snic)
+{
+	struct net_device *ndev = dev;
+	int i;
+
+	if (dev->priv_flags & IFF_802_1Q_VLAN)
+		ndev = vlan_dev_real_dev(dev);
+
+	for (i = 0; i < snic->lldi.nports; i++) {
+		if (ndev == snic->lldi.ports[i])
+			return 1;
+	}
+
+	return 0;
+}
+
+static struct net_device *cxgb4i_find_egress_dev(struct net_device *root_dev,
+						struct cxgb4i_snic *snic)
+{
+	while (root_dev) {
+		if (root_dev->priv_flags & IFF_802_1Q_VLAN)
+			root_dev = vlan_dev_real_dev(root_dev);
+		else if (is_cxgb4_dev(root_dev, snic))
+			return root_dev;
+		else
+			return NULL;
+	}
+
+	return NULL;
+}
+
+static struct rtable *find_route(struct net_device *dev,
+				__be32 saddr, __be32 daddr,
+				__be16 sport, __be16 dport,
+				u8 tos)
+{
+	struct rtable *rt;
+	struct flowi fl = {
+		.oif = dev ? dev->ifindex : 0,
+		.nl_u = {
+			.ip4_u = {
+				.daddr = daddr,
+				.saddr = saddr,
+				.tos = tos }
+			},
+		.proto = IPPROTO_TCP,
+		.uli_u = {
+			.ports = {
+				.sport = sport,
+				.dport = dport }
+			}
+	};
+
+	if (ip_route_output_flow(dev ? dev_net(dev) : &init_net,
+					&rt, &fl, NULL, 0))
+		return NULL;
+
+	return rt;
+}
+
+static int cxgb4i_init_act_open(struct cxgbi_sock *csk,
+					struct net_device *dev)
+{
+	struct dst_entry *dst = csk->dst;
+	struct sk_buff *skb;
+	struct port_info *pi = netdev_priv(dev);
+
+	cxgbi_conn_debug("csk 0x%p, state %u, flags 0x%lx\n",
+			csk, csk->state, csk->flags);
+
+	csk->atid = cxgb4_alloc_atid(cxgb4i_get_snic(csk->cdev)->lldi.tids,
+					csk);
+	if (csk->atid == -1) {
+		cxgbi_log_error("cannot alloc atid\n");
+		goto out_err;
+	}
+
+	csk->l2t = cxgb4_l2t_get(cxgb4i_get_snic(csk->cdev)->lldi.l2t,
+				csk->dst->neighbour, dev, 0);
+	if (!csk->l2t) {
+		cxgbi_log_error("cannot alloc l2t\n");
+		goto free_atid;
+	}
+
+	skb = alloc_skb(sizeof(struct cpl_act_open_req), GFP_KERNEL);
+	if (!skb)
+		goto free_l2t;
+
+	skb->sk = (struct sock *)csk;
+	t4_set_arp_err_handler(skb, csk, cxgb4i_act_open_req_arp_failure);
+
+	cxgbi_sock_hold(csk);
+
+	csk->wr_max_cred = csk->wr_cred =
+		cxgb4i_get_snic(csk->cdev)->lldi.wr_cred;
+	csk->port_id = pi->port_id;
+	csk->rss_qid = cxgb4i_get_snic(csk->cdev)->lldi.rxq_ids[csk->port_id];
+	csk->tx_chan = pi->tx_chan;
+	csk->smac_idx = csk->tx_chan << 1;
+	csk->wr_una_cred = 0;
+	csk->mss_idx = cxgb4i_select_mss(csk, dst_mtu(dst));
+	csk->err = 0;
+
+	cxgb4i_sock_reset_wr_list(csk);
+
+	cxgb4i_sock_make_act_open_req(csk, skb,
+					((csk->rss_qid << 14) |
+					 (csk->atid)), csk->l2t);
+	cxgb4_l2t_send(cxgb4i_get_snic(csk->cdev)->lldi.ports[csk->port_id],
+					skb, csk->l2t);
+	return 0;
+
+free_l2t:
+	cxgb4_l2t_release(csk->l2t);
+
+free_atid:
+	cxgb4_free_atid(cxgb4i_get_snic(csk->cdev)->lldi.tids, csk->atid);
+
+out_err:
+
+	return -EINVAL;;
+}
+
+static struct net_device *cxgb4i_find_dev(struct net_device *dev,
+							__be32 ipaddr)
+{
+	struct flowi fl;
+	struct rtable *rt;
+	int err;
+
+	memset(&fl, 0, sizeof(fl));
+	fl.nl_u.ip4_u.daddr = ipaddr;
+
+	err = ip_route_output_key(dev ? dev_net(dev) : &init_net, &rt, &fl);
+	if (!err)
+		return (&rt->u.dst)->dev;
+
+	return NULL;
+}
+
+int cxgb4i_sock_connect(struct net_device *dev, struct cxgbi_sock *csk,
+						struct sockaddr_in *sin)
+{
+	struct rtable *rt;
+	__be32 sipv4 = 0;
+	struct net_device *dstdev;
+	struct cxgbi_hba *chba = NULL;
+	int err;
+
+	cxgbi_conn_debug("csk 0x%p, dev 0x%p\n", csk, dev);
+
+	if (sin->sin_family != AF_INET)
+		return -EAFNOSUPPORT;
+
+	csk->daddr.sin_port = sin->sin_port;
+	csk->daddr.sin_addr.s_addr = sin->sin_addr.s_addr;
+
+	dstdev = cxgb4i_find_dev(dev, sin->sin_addr.s_addr);
+	if (!dstdev || !is_cxgb4_dev(dstdev, cxgb4i_get_snic(csk->cdev)))
+		return -ENETUNREACH;
+
+	if (dstdev->priv_flags & IFF_802_1Q_VLAN)
+		dev = dstdev;
+
+	rt = find_route(dev, csk->saddr.sin_addr.s_addr,
+			csk->daddr.sin_addr.s_addr,
+			csk->saddr.sin_port,
+			csk->daddr.sin_port,
+			0);
+	if (rt == NULL) {
+		cxgbi_conn_debug("no route to %pI4, port %u, dev %s, "
+					"snic 0x%p\n",
+					&csk->daddr.sin_addr.s_addr,
+					ntohs(csk->daddr.sin_port),
+					dev ? dev->name : "any",
+					csk->snic);
+		return -ENETUNREACH;
+	}
+
+	if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
+		cxgbi_conn_debug("multi-cast route to %pI4, port %u, "
+					"dev %s, snic 0x%p\n",
+					&csk->daddr.sin_addr.s_addr,
+					ntohs(csk->daddr.sin_port),
+					dev ? dev->name : "any",
+					csk->snic);
+		ip_rt_put(rt);
+		return -ENETUNREACH;
+	}
+
+	if (!csk->saddr.sin_addr.s_addr)
+		csk->saddr.sin_addr.s_addr = rt->rt_src;
+
+	csk->dst = &rt->u.dst;
+
+	dev = cxgb4i_find_egress_dev(csk->dst->dev,
+					cxgb4i_get_snic(csk->cdev));
+	if (dev == NULL) {
+		cxgbi_conn_debug("csk: 0x%p, egress dev NULL\n", csk);
+		return -ENETUNREACH;
+	}
+
+	err = cxgbi_sock_get_port(csk);
+	if (err)
+		return err;
+
+	cxgbi_conn_debug("csk: 0x%p get port: %u\n",
+			csk, ntohs(csk->saddr.sin_port));
+
+	chba = cxgb4i_hba_find_by_netdev(csk->dst->dev);
+
+	sipv4 = cxgb4i_get_iscsi_ipv4(chba);
+	if (!sipv4) {
+		cxgbi_conn_debug("csk: 0x%p, iscsi is not configured\n", csk);
+		sipv4 = csk->saddr.sin_addr.s_addr;
+		cxgb4i_set_iscsi_ipv4(chba, sipv4);
+	} else
+		csk->saddr.sin_addr.s_addr = sipv4;
+
+	cxgbi_conn_debug("csk: 0x%p, %pI4:[%u], %pI4:[%u] SYN_SENT\n",
+				csk,
+				&csk->saddr.sin_addr.s_addr,
+				ntohs(csk->saddr.sin_port),
+				&csk->daddr.sin_addr.s_addr,
+				ntohs(csk->daddr.sin_port));
+
+	cxgbi_sock_set_state(csk, CXGBI_CSK_ST_CONNECTING);
+
+	if (!cxgb4i_init_act_open(csk, dev))
+		return 0;
+
+	err = -ENOTSUPP;
+
+	cxgbi_conn_debug("csk 0x%p -> closed\n", csk);
+	cxgbi_sock_set_state(csk, CXGBI_CSK_ST_CLOSED);
+	ip_rt_put(rt);
+	cxgbi_sock_put_port(csk);
+
+	return err;
+}
+
+void cxgb4i_sock_rx_credits(struct cxgbi_sock *csk, int copied)
+{
+	int must_send;
+	u32 credits;
+
+	if (csk->state != CXGBI_CSK_ST_ESTABLISHED)
+		return;
+
+	credits = csk->copied_seq - csk->rcv_wup;
+	if (unlikely(!credits))
+		return;
+
+	if (unlikely(cxgb4i_rx_credit_thres == 0))
+		return;
+
+	must_send = credits + 16384 >= cxgb4i_rcv_win;
+
+	if (must_send || credits >= cxgb4i_rx_credit_thres)
+		csk->rcv_wup += cxgb4i_csk_send_rx_credits(csk, credits);
+}
+
+int cxgb4i_sock_send_pdus(struct cxgbi_sock *csk, struct sk_buff *skb)
+{
+	struct sk_buff *next;
+	int err, copied = 0;
+
+	spin_lock_bh(&csk->lock);
+
+	if (csk->state != CXGBI_CSK_ST_ESTABLISHED) {
+		cxgbi_tx_debug("csk 0x%p, not in est. state %u.\n",
+			      csk, csk->state);
+		err = -EAGAIN;
+		goto out_err;
+	}
+
+	if (csk->err) {
+		cxgbi_tx_debug("csk 0x%p, err %d.\n", csk, csk->err);
+		err = -EPIPE;
+		goto out_err;
+	}
+
+	if (csk->write_seq - csk->snd_una >= cxgb4i_snd_win) {
+		cxgbi_tx_debug("csk 0x%p, snd %u - %u > %u.\n",
+				csk, csk->write_seq, csk->snd_una,
+				cxgb4i_snd_win);
+		err = -ENOBUFS;
+		goto out_err;
+	}
+
+	while (skb) {
+		int frags = skb_shinfo(skb)->nr_frags +
+				(skb->len != skb->data_len);
+
+		if (unlikely(skb_headroom(skb) < CXGB4I_TX_HEADER_LEN)) {
+			cxgbi_tx_debug("csk 0x%p, skb head.\n", csk);
+			err = -EINVAL;
+			goto out_err;
+		}
+
+		if (frags >= SKB_WR_LIST_SIZE) {
+			cxgbi_log_error("csk 0x%p, tx frags %d, len %u,%u.\n",
+					 csk, skb_shinfo(skb)->nr_frags,
+					 skb->len, skb->data_len);
+			err = -EINVAL;
+			goto out_err;
+		}
+
+		next = skb->next;
+		skb->next = NULL;
+		cxgb4i_sock_skb_entail(csk, skb,
+				CXGB4I_SKCB_FLAG_NO_APPEND |
+				CXGB4I_SKCB_FLAG_NEED_HDR);
+		copied += skb->len;
+		csk->write_seq += skb->len + ulp_extra_len(skb);
+		skb = next;
+	}
+done:
+	if (likely(skb_queue_len(&csk->write_queue)))
+		cxgb4i_sock_push_tx_frames(csk, 1);
+	spin_unlock_bh(&csk->lock);
+	return copied;
+
+out_err:
+	if (copied == 0 && err == -EPIPE)
+		copied = csk->err ? csk->err : -EPIPE;
+	else
+		copied = err;
+	goto done;
+}
+
+static void cxgbi_sock_conn_closing(struct cxgbi_sock *csk)
+{
+	struct iscsi_conn *conn = csk->user_data;
+
+	read_lock(&csk->callback_lock);
+	if (conn && csk->state != CXGBI_CSK_ST_ESTABLISHED)
+		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+	read_unlock(&csk->callback_lock);
+}
+
+static void tx_skb_setmode(struct sk_buff *skb, int hcrc, int dcrc)
+{
+	u8 submode = 0;
+
+	if (hcrc)
+		submode |= 1;
+	if (dcrc)
+		submode |= 2;
+	cxgb4i_skb_ulp_mode(skb) = (ULP_MODE_ISCSI << 4) | submode;
+}
+
+static inline __u16 get_skb_ulp_mode(struct sk_buff *skb)
+{
+	return cxgb4i_skb_ulp_mode(skb);
+}
+
+static cxgb4i_cplhandler_func cxgb4i_cplhandlers[NUM_CPL_CMDS] = {
+	[CPL_ACT_ESTABLISH] = cxgb4i_cpl_act_establish,
+	[CPL_ACT_OPEN_RPL] = cxgb4i_cpl_act_open_rpl,
+	[CPL_PEER_CLOSE] = cxgb4i_cpl_peer_close,
+	[CPL_ABORT_REQ_RSS] = cxgb4i_cpl_abort_req_rss,
+	[CPL_ABORT_RPL_RSS] = cxgb4i_cpl_abort_rpl_rss,
+	[CPL_CLOSE_CON_RPL] = cxgb4i_cpl_close_con_rpl,
+	[CPL_FW4_ACK] = cxgb4i_cpl_fw4_ack,
+	[CPL_ISCSI_HDR] = cxgb4i_cpl_iscsi_hdr,
+	[CPL_SET_TCB_RPL] = cxgb4i_cpl_set_tcb_rpl,
+	[CPL_RX_DATA_DDP] = cxgb4i_cpl_rx_data_ddp
+};
+
+int cxgb4i_ofld_init(struct cxgb4i_snic *snic)
+{
+	struct cxgbi_ports_map *ports;
+	int mapsize;
+
+	if (cxgb4i_max_connect > CXGB4I_MAX_CONN)
+		cxgb4i_max_connect = CXGB4I_MAX_CONN;
+
+	mapsize = (cxgb4i_max_connect * sizeof(struct cxgbi_sock));
+	ports = cxgbi_alloc_big_mem(sizeof(*ports) + mapsize, GFP_KERNEL);
+	if (!ports)
+		return -ENOMEM;
+
+	spin_lock_init(&ports->lock);
+	snic->cdev.pmap = ports;
+	snic->cdev.pmap->max_connect = cxgb4i_max_connect;
+	snic->cdev.pmap->sport_base = cxgb4i_sport_base;
+
+	snic->cdev.tx_skb_setmode = tx_skb_setmode;
+	snic->cdev.sock_send_pdus = cxgb4i_sock_send_pdus;
+	snic->cdev.get_skb_ulp_mode = get_skb_ulp_mode;
+
+	snic->handlers = cxgb4i_cplhandlers;
+
+	return 0;
+}
+
+void cxgb4i_ofld_cleanup(struct cxgb4i_snic *snic)
+{
+	struct cxgbi_sock *csk;
+	int i;
+
+	for (i = 0; i < snic->cdev.pmap->max_connect; i++) {
+		if (snic->cdev.pmap->port_csk[i]) {
+			csk = snic->cdev.pmap->port_csk[i];
+			snic->cdev.pmap->port_csk[i] = NULL;
+
+			spin_lock_bh(&csk->lock);
+			cxgb4i_sock_closed(csk);
+			spin_unlock_bh(&csk->lock);
+		}
+	}
+	cxgbi_free_big_mem(snic->cdev.pmap);
+}
+
diff --git a/drivers/scsi/cxgb4i/cxgb4i_offload.h b/drivers/scsi/cxgb4i/cxgb4i_offload.h
new file mode 100644
index 0000000..afd50d9
--- /dev/null
+++ b/drivers/scsi/cxgb4i/cxgb4i_offload.h
@@ -0,0 +1,91 @@
+/*
+ * cxgb4i_offload.h: Chelsio T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Karen Xie (kxie-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ * Written by: Rakesh Ranjan (rranjan-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ */
+
+#ifndef	__CXGB4I_OFFLOAD_H__
+#define	__CXGB4I_OFFLOAD_H__
+
+#include <linux/skbuff.h>
+#include <linux/in.h>
+
+#include "libcxgbi.h"
+
+#define	CXGB4I_MAX_CONN	16384
+
+enum {
+	CPL_RET_BUF_DONE = 1,
+	CPL_RET_BAD_MSG = 2,
+	CPL_RET_UNKNOWN_TID = 4
+};
+
+struct cxgbi_sock *cxgb4i_sock_create(struct cxgb4i_snic *);
+void cxgb4i_sock_release(struct cxgbi_sock *);
+int cxgb4i_sock_connect(struct net_device *, struct cxgbi_sock *,
+			struct sockaddr_in *);
+void cxgb4i_sock_rx_credits(struct cxgbi_sock *, int);
+int cxgb4i_sock_send_pdus(struct cxgbi_sock *, struct sk_buff *);
+
+struct cxgb4i_skb_rx_cb {
+	__u32 ddigest;
+	__u32 pdulen;
+};
+
+struct cxgb4i_skb_tx_cb {
+	struct l2t_skb_cb l2t;
+	struct sk_buff *wr_next;
+};
+
+struct cxgb4i_skb_cb {
+	__u16 flags;
+	__u16 ulp_mode;
+	__u32 seq;
+
+	union {
+		struct cxgb4i_skb_rx_cb rx;
+		struct cxgb4i_skb_tx_cb tx;
+	};
+};
+
+#define CXGB4I_SKB_CB(skb)	((struct cxgb4i_skb_cb *)&((skb)->cb[0]))
+#define cxgb4i_skb_flags(skb)	(CXGB4I_SKB_CB(skb)->flags)
+#define cxgb4i_skb_ulp_mode(skb)	(CXGB4I_SKB_CB(skb)->ulp_mode)
+#define cxgb4i_skb_tcp_seq(skb)		(CXGB4I_SKB_CB(skb)->seq)
+#define cxgb4i_skb_rx_ddigest(skb)	(CXGB4I_SKB_CB(skb)->rx.ddigest)
+#define cxgb4i_skb_rx_pdulen(skb)	(CXGB4I_SKB_CB(skb)->rx.pdulen)
+#define cxgb4i_skb_tx_wr_next(skb)	(CXGB4I_SKB_CB(skb)->tx.wr_next)
+
+enum cxgb4i_skcb_flags {
+	CXGB4I_SKCB_FLAG_NEED_HDR = 1 << 0,	/* packet needs a header */
+	CXGB4I_SKCB_FLAG_NO_APPEND = 1 << 1,	/* don't grow this skb */
+	CXGB4I_SKCB_FLAG_COMPL = 1 << 2,	/* request WR completion */
+	CXGB4I_SKCB_FLAG_HDR_RCVD = 1 << 3,	/* recieved header pdu */
+	CXGB4I_SKCB_FLAG_DATA_RCVD = 1 << 4,	/*  recieved data pdu */
+	CXGB4I_SKCB_FLAG_STATUS_RCVD = 1 << 5,	/* recieved ddp status */
+};
+
+/*
+ * sge_opaque_hdr -
+ * Opaque version of structure the SGE stores at skb->head of TX_DATA packets
+ * and for which we must reserve space.
+ */
+struct sge_opaque_hdr {
+	void *dev;
+	dma_addr_t addr[MAX_SKB_FRAGS + 1];
+};
+
+/* for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */
+#define CXGB4I_TX_HEADER_LEN \
+	(sizeof(struct fw_ofld_tx_data_wr) + sizeof(struct sge_opaque_hdr))
+#define SKB_TX_HEADROOM	SKB_MAX_HEAD(CXGB4I_TX_HEADER_LEN)
+
+#endif	/* __CXGB4I_OFFLOAD_H__ */
+
diff --git a/drivers/scsi/cxgb4i/cxgb4i_snic.c b/drivers/scsi/cxgb4i/cxgb4i_snic.c
new file mode 100644
index 0000000..68cdae5
--- /dev/null
+++ b/drivers/scsi/cxgb4i/cxgb4i_snic.c
@@ -0,0 +1,260 @@
+/*
+ * cxgb4i_snic.c: Chelsio T4 iSCSI driver.
+ *
+ * Copyright (c) 2010 Chelsio Communications, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Karen Xie (kxie-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ * Written by: Rakesh Ranjan (rranjan-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org)
+ */
+
+#include <net/route.h>
+
+#include "cxgb4i.h"
+
+#define	DRV_MODULE_NAME		"cxgb4i"
+#define	DRV_MODULE_VERSION	"0.90"
+#define	DRV_MODULE_RELDATE	"04/08/2010"
+
+static char version[] =
+	"Chelsio T4 iSCSI driver " DRV_MODULE_NAME
+	" v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+
+MODULE_AUTHOR("Chelsio Communications");
+MODULE_DESCRIPTION("Chelsio T4 iSCSI driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+static LIST_HEAD(snic_list);
+static DEFINE_MUTEX(snic_rwlock);
+
+static void *cxgb4i_uld_add(const struct cxgb4_lld_info *linfo);
+static int cxgb4i_uld_rx_handler(void *handle, const __be64 *rsp,
+				const struct pkt_gl *pgl);
+static int cxgb4i_uld_state_change(void *handle, enum cxgb4_state state);
+
+static struct cxgb4i_snic *cxgb4i_snic_init(const struct cxgb4_lld_info *);
+static void cxgb4i_snic_cleanup(void);
+
+
+static struct cxgb4_uld_info cxgb4i_uld_info = {
+	.name = "cxgb4i",
+	.add = cxgb4i_uld_add,
+	.rx_handler = cxgb4i_uld_rx_handler,
+	.state_change = cxgb4i_uld_state_change,
+};
+
+
+struct cxgbi_hba *cxgb4i_hba_find_by_netdev(struct net_device *dev)
+{
+	int i;
+	struct cxgb4i_snic *snic = NULL;;
+
+	if (dev->priv_flags & IFF_802_1Q_VLAN)
+		dev = vlan_dev_real_dev(dev);
+
+	mutex_lock(&snic_rwlock);
+	list_for_each_entry(snic, &snic_list, list_head) {
+		for (i = 0; i < snic->hba_cnt; i++) {
+			if (snic->hba[i]->ndev == dev) {
+				mutex_unlock(&snic_rwlock);
+				return snic->hba[i];
+			}
+		}
+	}
+	mutex_unlock(&snic_rwlock);
+	return NULL;
+}
+
+struct cxgb4i_snic *cxgb4i_find_snic(struct net_device *dev, __be32 ipaddr)
+{
+	struct flowi fl;
+	struct rtable *rt;
+	struct net_device *sdev = NULL;
+	struct cxgb4i_snic *snic = NULL, *tmp;
+	int err, i;
+
+	memset(&fl, 0, sizeof(fl));
+	fl.nl_u.ip4_u.daddr = ipaddr;
+
+	err = ip_route_output_key(dev ? dev_net(dev) : &init_net, &rt, &fl);
+	if (err)
+		goto out;
+
+	sdev = (&rt->u.dst)->dev;
+	mutex_lock(&snic_rwlock);
+	list_for_each_entry_safe(snic, tmp, &snic_list, list_head) {
+		if (snic) {
+			for (i = 0; i < snic->lldi.nports; i++) {
+				if (sdev == snic->lldi.ports[i]) {
+					mutex_unlock(&snic_rwlock);
+					return snic;
+				}
+			}
+		}
+	}
+	mutex_unlock(&snic_rwlock);
+
+out:
+	snic = NULL;
+	return snic;
+}
+
+void cxgb4i_snic_add(struct list_head *list_head)
+{
+	mutex_lock(&snic_rwlock);
+	list_add_tail(list_head, &snic_list);
+	mutex_unlock(&snic_rwlock);
+}
+
+struct cxgb4i_snic *cxgb4i_snic_init(const struct cxgb4_lld_info *linfo)
+{
+	struct cxgb4i_snic *snic;
+	int i;
+
+	snic = kzalloc(sizeof(*snic), GFP_KERNEL);
+	if (snic) {
+
+		spin_lock_init(&snic->lock);
+		snic->lldi = *linfo;
+		snic->hba_cnt = snic->lldi.nports;
+		snic->cdev.dd_data = snic;
+		snic->cdev.pdev = snic->lldi.pdev;
+		snic->cdev.skb_tx_headroom = SKB_MAX_HEAD(CXGB4I_TX_HEADER_LEN);
+
+		cxgb4i_iscsi_init();
+		cxgbi_pdu_init(&snic->cdev);
+		cxgb4i_ddp_init(snic);
+		cxgb4i_ofld_init(snic);
+
+		for (i = 0; i < snic->hba_cnt; i++) {
+			snic->hba[i] = cxgb4i_hba_add(snic,
+						snic->lldi.ports[i]);
+			if (!snic->hba[i]) {
+				kfree(snic);
+				snic = ERR_PTR(-ENOMEM);
+				goto out;
+			}
+		}
+		cxgb4i_snic_add(&snic->list_head);
+	} else
+out :
+	snic = ERR_PTR(-ENOMEM);
+
+	return snic;
+}
+
+void cxgb4i_snic_cleanup(void)
+{
+	struct cxgb4i_snic *snic, *tmp;
+	int i;
+
+	mutex_lock(&snic_rwlock);
+	list_for_each_entry_safe(snic, tmp, &snic_list, list_head) {
+		list_del(&snic->list_head);
+
+		for (i = 0; i < snic->hba_cnt; i++) {
+			if (snic->hba[i]) {
+				cxgb4i_hba_remove(snic->hba[i]);
+				snic->hba[i] = NULL;
+			}
+		}
+		cxgb4i_ofld_cleanup(snic);
+		cxgb4i_ddp_cleanup(snic);
+		cxgbi_pdu_cleanup(&snic->cdev);
+		cxgbi_log_info("snic 0x%p, %u scsi hosts removed.\n",
+				snic, snic->hba_cnt);
+
+		kfree(snic);
+	}
+	mutex_unlock(&snic_rwlock);
+	cxgb4i_iscsi_cleanup();
+}
+
+static void *cxgb4i_uld_add(const struct cxgb4_lld_info *linfo)
+{
+	struct cxgb4i_snic *snic;
+
+	cxgbi_log_info("%s", version);
+
+	snic = cxgb4i_snic_init(linfo);
+	if (!snic)
+		goto out;
+out:
+	return snic;
+}
+
+static int cxgb4i_uld_rx_handler(void *handle, const __be64 *rsp,
+				const struct pkt_gl *pgl)
+{
+	struct cxgb4i_snic *snic = handle;
+	struct sk_buff *skb;
+	const struct cpl_act_establish *rpl;
+	unsigned int opcode;
+
+	if (pgl == NULL) {
+		unsigned int len = 64 - sizeof(struct rsp_ctrl) - 8;
+
+		skb = alloc_skb(256, GFP_ATOMIC);
+		if (!skb)
+			goto nomem;
+		__skb_put(skb, len);
+		skb_copy_to_linear_data(skb, &rsp[1], len);
+
+	} else if (pgl == CXGB4_MSG_AN) {
+
+		return 0;
+
+	} else {
+
+		skb = cxgb4_pktgl_to_skb(pgl, 256, 256);
+		if (unlikely(!skb))
+			goto nomem;
+	}
+
+	rpl = cplhdr(skb);
+	opcode = rpl->ot.opcode;
+
+	cxgbi_api_debug("snic %p, opcode 0x%x, skb %p\n",
+			 snic, opcode, skb);
+
+	BUG_ON(!snic->handlers[opcode]);
+
+	if (snic->handlers[opcode]) {
+		snic->handlers[opcode](snic, skb);
+	} else
+		cxgbi_log_error("No handler for opcode 0x%x\n",
+				opcode);
+
+	return 0;
+
+nomem:
+	cxgbi_api_debug("OOM bailing out\n");
+	return 1;
+}
+
+static int cxgb4i_uld_state_change(void *handle, enum cxgb4_state state)
+{
+	return 0;
+}
+
+static int __init cxgb4i_init_module(void)
+{
+	cxgb4_register_uld(CXGB4_ULD_ISCSI, &cxgb4i_uld_info);
+
+	return 0;
+}
+
+static void __exit cxgb4i_exit_module(void)
+{
+
+	cxgb4_unregister_uld(CXGB4_ULD_ISCSI);
+	cxgb4i_snic_cleanup();
+}
+
+module_init(cxgb4i_init_module);
+module_exit(cxgb4i_exit_module);
+
-- 
1.6.6.1

-- 
You received this message because you are subscribed to the Google Groups "open-iscsi" group.
To post to this group, send email to open-iscsi-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
To unsubscribe from this group, send email to open-iscsi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit this group at http://groups.google.com/group/open-iscsi?hl=en.

^ permalink raw reply related

* [PATCH 1/3] cxgb4i_v3: add build support
From: Rakesh Ranjan @ 2010-05-15 17:15 UTC (permalink / raw)
  To: NETDEVML, SCSIDEVML, OISCSIML
  Cc: LKML, Karen Xie, David Miller, James Bottomley, Mike Christie,
	Anish Bhatt, Rakesh Ranjan, Rakesh Ranjan
In-Reply-To: <1273943752-32486-1-git-send-email-rakesh-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>

From: Rakesh Ranjan <rranjan-UJ4WrezqVcvwEYdC/TKypOqkaFVsf6Qi@public.gmane.org>


Signed-off-by: Rakesh Ranjan <rakesh-ut6Up61K2wZBDgjK7y7TUQ@public.gmane.org>
---
 drivers/scsi/Kconfig        |    1 +
 drivers/scsi/Makefile       |    1 +
 drivers/scsi/cxgb4i/Kbuild  |    4 ++++
 drivers/scsi/cxgb4i/Kconfig |    7 +++++++
 4 files changed, 13 insertions(+), 0 deletions(-)
 create mode 100644 drivers/scsi/cxgb4i/Kbuild
 create mode 100644 drivers/scsi/cxgb4i/Kconfig

diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 75f2336..fc3810a 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -371,6 +371,7 @@ config ISCSI_TCP
 	 http://open-iscsi.org
 
 source "drivers/scsi/cxgb3i/Kconfig"
+source "drivers/scsi/cxgb4i/Kconfig"
 source "drivers/scsi/bnx2i/Kconfig"
 source "drivers/scsi/be2iscsi/Kconfig"
 
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 1c7ac49..46dcdc8 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -133,6 +133,7 @@ obj-$(CONFIG_SCSI_STEX)		+= stex.o
 obj-$(CONFIG_SCSI_MVSAS)	+= mvsas/
 obj-$(CONFIG_PS3_ROM)		+= ps3rom.o
 obj-$(CONFIG_SCSI_CXGB3_ISCSI)	+= libiscsi.o libiscsi_tcp.o cxgb3i/
+obj-$(CONFIG_SCSI_CXGB4_ISCSI)	+= libiscsi.o libiscsi_tcp.o cxgb4i/
 obj-$(CONFIG_SCSI_BNX2_ISCSI)	+= libiscsi.o bnx2i/
 obj-$(CONFIG_BE2ISCSI)		+= libiscsi.o be2iscsi/
 obj-$(CONFIG_SCSI_PMCRAID)	+= pmcraid.o
diff --git a/drivers/scsi/cxgb4i/Kbuild b/drivers/scsi/cxgb4i/Kbuild
new file mode 100644
index 0000000..1cb87b9
--- /dev/null
+++ b/drivers/scsi/cxgb4i/Kbuild
@@ -0,0 +1,4 @@
+EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb4
+
+cxgb4i-y := libcxgbi.o cxgb4i_snic.o cxgb4i_iscsi.o cxgb4i_offload.o cxgb4i_ddp.o
+obj-$(CONFIG_SCSI_CXGB4_ISCSI) += cxgb4i.o
diff --git a/drivers/scsi/cxgb4i/Kconfig b/drivers/scsi/cxgb4i/Kconfig
new file mode 100644
index 0000000..3f33dc2
--- /dev/null
+++ b/drivers/scsi/cxgb4i/Kconfig
@@ -0,0 +1,7 @@
+config SCSI_CXGB4_ISCSI
+	tristate "Chelsio T4 iSCSI support"
+	depends on CHELSIO_T4_DEPENDS
+	select CHELSIO_T4
+	select SCSI_ISCSI_ATTRS
+	---help---
+	This driver supports iSCSI offload for the Chelsio T4 series devices.
-- 
1.6.6.1

-- 
You received this message because you are subscribed to the Google Groups "open-iscsi" group.
To post to this group, send email to open-iscsi-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
To unsubscribe from this group, send email to open-iscsi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit this group at http://groups.google.com/group/open-iscsi?hl=en.

^ permalink raw reply related

* cxgb4i_v3 submission
From: Rakesh Ranjan @ 2010-05-15 17:15 UTC (permalink / raw)
  To: NETDEVML, SCSIDEVML, OISCSIML
  Cc: LKML, Karen Xie, David Miller, James Bottomley, Mike Christie,
	Anish Bhatt, Rakesh Ranjan

Changes since cxgb4i_v2
1. Abastract libcxgbi library common part more properly.
2. Fixed few packet sequence calculation bugs.
3. compile-time initialization of cplhandlers

[PATCH 1/3] cxgb4i_v3: add build support
[PATCH 2/3] cxgb4i_v3: main driver files
[PATCH 3/3] cxgb4i_v3: iscsi and libcxgbi library for handling common part

Regards
Rakesh Ranjan

-- 
You received this message because you are subscribed to the Google Groups "open-iscsi" group.
To post to this group, send email to open-iscsi-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
To unsubscribe from this group, send email to open-iscsi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit this group at http://groups.google.com/group/open-iscsi?hl=en.

^ permalink raw reply

* RE: why get different number of MSI-X vector for broadcom bnx2x every time
From: Dmitry Kravkov @ 2010-05-15 16:17 UTC (permalink / raw)
  To: Jon Zhou, netdev
In-Reply-To: <4A6A2125329CFD4D8CC40C9E8ABCAB9F2497D752C9@MILEXCH2.ds.jdsu.net>

Hi Jon

I mean the kernel
It was able to setup (only) 4 MSI-X vectors for some reason: return value of pci_enable_msix() was 4 


Regards
Dmitry

-----Original Message-----
From: Jon Zhou [mailto:Jon.Zhou@jdsu.com] 
Sent: Saturday, May 15, 2010 6:13 AM
To: Dmitry Kravkov; netdev
Subject: RE: why get different number of MSI-X vector for broadcom bnx2x every time


hi Dmitry
the system,is the kernel(2.6.27) or the hardware?
thanks!
jon
________________________________________
From: Dmitry Kravkov [dmitry@broadcom.com]
Sent: Saturday, May 15, 2010 4:02 AM
To: Jon Zhou; netdev
Subject: RE: why get different number of MSI-X vector for broadcom bnx2x every time

Hi

Your system (from the log below) allowed bnx2x to use only 4 MSI-X vectors instead of 16 required by the driver.

Regards,
Dmitry

-----Original Message-----
From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org] On Behalf Of Jon Zhou
Sent: Friday, May 14, 2010 11:02 AM
To: netdev
Subject: why get different number of MSI-X vector for broadcom bnx2x every time

hi there:

bnx2x_enable_msix :

...
rc = pci_enable_msix(bp->pdev, &bp->msix_table[0],
                             BNX2X_NUM_QUEUES(bp) + offset);

        /*
         * reconfigure number of tx/rx queues according to available
         * MSI-X vectors
         */
        if (rc >= BNX2X_MIN_MSIX_VEC_CNT) {
                /* vectors available for FP */
                int fp_vec = rc - BNX2X_MSIX_VEC_FP_START;


sometimes I can run up the driver with 4 queues but most of time I can only get 2 queues
why?

May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_set_num_queues:8053(eth5)]set number of queues to 15
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7544(eth5)]msix_table[0].entry = 0 (slowpath)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7549(eth5)]msix_table[1].entry = 1 (CNIC)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[2].entry = 2 (fastpath #0)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[3].entry = 3 (fastpath #1)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[4].entry = 4 (fastpath #2)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[5].entry = 5 (fastpath #3)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[6].entry = 6 (fastpath #4)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[7].entry = 7 (fastpath #5)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[8].entry = 8 (fastpath #6)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[9].entry = 9 (fastpath #7)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[10].entry = 10 (fastpath #8)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[11].entry = 11 (fastpath #9)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[12].entry = 12 (fastpath #10)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[13].entry = 13 (fastpath #11)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[14].entry = 14 (fastpath #12)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[15].entry = 15 (fastpath #13)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[16].entry = 16 (fastpath #14)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7571(eth5)]Trying to use less MSI-X vectors: 4
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7584(eth5)]New queue configuration set: 2
May 14 01:40:16 ibm-bc-54 kernel: bnx2x: eth5: using MSI-X  IRQs: sp 4321  fp[0] 4319 ... fp[1] 4318
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_nic_init:6067(eth5)]queue[0]:  bnx2x_init_sb(ffff8803e6810780,ffff8803f9c4f000)  cl_id 0  sb 1  cos 0
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_nic_init:6067(eth5)]queue[1]:  bnx2x_init_sb(ffff8803e6810780,ffff8803fb006000)  cl_id 1  sb 2  cos 0
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_init_rx_rings:5305(eth5)]mtu 1500  rx_buf_size 1650

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply

* Re: [PATCH] rndis_host: Poll status channel before control channel
From: Ben Hutchings @ 2010-05-15 13:37 UTC (permalink / raw)
  To: David Miller; +Cc: dbrownell, john.carr, netdev, vzeeaxwl, herton
In-Reply-To: <20100512.234259.35058609.davem@davemloft.net>

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

On Wed, 2010-05-12 at 23:42 -0700, David Miller wrote:
> From: Ben Hutchings <ben@decadent.org.uk>
> Date: Tue, 20 Apr 2010 00:08:28 +0100
> 
> > Some RNDIS devices don't respond on the control channel until polled
> > on the status channel.  In particular, this was reported to be the
> > case for the 2Wire HomePortal 1000SW.
> > 
> > This is roughly based on a patch by John Carr <john.carr@unrouted.co.uk>
> > which is reported to be needed for use with some Windows Mobile devices
> > and which is currently applied by Mandriva.
> > 
> > Reported-by: Mark Glassberg <vzeeaxwl@myfairpoint.net>
> > Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
> > Tested-by: Mark Glassberg <vzeeaxwl@myfairpoint.net>
> > ---
> > Note that this change hasn't yet been tested with any other RNDIS
> > devices.  John, can you confirm whether this also handles the WinMob
> > devices?
> 
> Still waiting for this to get tested.  Is there really nobody in the
> world with RNDIS devices who can test this patch?  If so, maybe that's
> a good reason to not apply it :-))))

This has been in Debian unstable since 1 May and I haven't seen any
fall-out yet.  However I acknowledge that absence of evidence is not
evidence of absence.

Ben.

-- 
Ben Hutchings
Once a job is fouled up, anything done to improve it makes it worse.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply

* Re: TSC unstable due to TSC halts in idle?
From: Jesper Dangaard Brouer @ 2010-05-15  9:54 UTC (permalink / raw)
  To: Suresh Siddha
  Cc: john stultz, Thomas Gleixner, linux-kernel@vger.kernel.org,
	netdev, Brown, Len, Li, Shaohua, hawk@comx.dk
In-Reply-To: <1273878957.2825.175.camel@sbs-t61.sc.intel.com>


On Fri, 14 May 2010, Suresh Siddha wrote:
> On Fri, 2010-05-14 at 15:28 -0700, john stultz wrote:
>> On Fri, May 14, 2010 at 1:13 PM, Jesper Dangaard Brouer <hawk@diku.dk> wrote:
>>> I want to know, if its safe to enable the TSC clocksource, when the
>>> kernel reports:
>>>  "Marking TSC unstable due to TSC halts in idle"
>>>
>>> The system selects HPET (in current_clocksource), but I can still see
>>> TSC as an available clocksource (in
>>> /sys/devices/system/clocksource/clocksource0/available_clocksource).
>>>
>>> Is it safe to enable TSC manually (by changing current_clocksource)?
>>> (my workload is 10Git/s routing, cannot survive with a slow clock)
>>>
>>>
>>> Any trick to avoid this? (e.g. kernel config setting, or a /sys/ setting
>>> which changes the minimum P-state?)
>>
>> Might try booting with the max-cstate=1 option.
>
> Jesper mentioned that it is xeon 5550. TSC's for that processor doesn't
> stop in idle.

Thanks, then it should be safe to force using TSC, even on this older 
kernel.


> Perhaps he is using an older kernel which doesn't detect this fact. 
> Jesper, more recent kernels should be able to use TSC as the 
> clocksource.

Guess this it the problem. As I'm running a standard Debian compiled 
kernel 2.6.26-2-amd64 (which comes with Debian lenny).  I'm not going to 
run with this kernel in production, as it doesn't have multiqueue support 
and doesn't support the NICs I'm using.

I'm already annoyed with this old kernel, as it doesn't support any of the 
NICs in the machine, not even the build in NICs in the HP370 G6 server.

I'll boot a new kernel on the machine Monday, and I'll complain if it 
didn't solve the issue, else consider this issue solved "in a newer kernel 
version".

Cheers,
   Jesper Brouer

--
-------------------------------------------------------------------
MSc. Master of Computer Science
Dept. of Computer Science, University of Copenhagen
Author of http://www.adsl-optimizer.dk
-------------------------------------------------------------------

^ permalink raw reply

* Re: loosing IPMI-card by loading netconsole
From: Carsten Aulbert @ 2010-05-15  9:36 UTC (permalink / raw)
  To: Tejun Heo
  Cc: e1000-devel, netdev@vger.kernel.org, Allan, Bruce W,
	Brandeburg, Jesse, Henning Fehrmann, Ronciak, John,
	Kirsher, Jeffrey T, Matt Mackall
In-Reply-To: <4BEE650F.3080701@kernel.org>

[-- Attachment #1: Type: Text/Plain, Size: 676 bytes --]

On Saturday 15 May 2010 11:10:39 Tejun Heo wrote:

> > echo 1 > /sys/devices/pci0000:00/0000:00:1c.4/0000:0d:00.0/remove
> 
> echo 1 > /sys/devices/pci0000:00/0000:00:1c.4/rescan
> 

D'oh

Ok, IPMI does not work remotely, after removing it does and still after 
rescanning (netconsole not loaded for the time being). At this point I ran 
ethtool -S for both interfaces as well as ethreg (suffix afterRescan).

then I only ran dhclient:
dhclient3 -pf /var/run/dhclient.eth0.pid -lf 
/var/lib/dhcp3/dhclient.eth0.leases eth0

and afterwards the IPMI connectivity was gone again.

Status files after this are also attached, suffix afterDHClient

Does this help?

Cheers

Carsten

[-- Attachment #2: ethtool_S_eth0.afterRescan --]
[-- Type: text/plain, Size: 1178 bytes --]

NIC statistics:
     rx_packets: 0
     tx_packets: 0
     rx_bytes: 0
     tx_bytes: 0
     rx_broadcast: 0
     tx_broadcast: 0
     rx_multicast: 0
     tx_multicast: 0
     rx_errors: 0
     tx_errors: 0
     tx_dropped: 0
     multicast: 0
     collisions: 0
     rx_length_errors: 0
     rx_over_errors: 0
     rx_crc_errors: 0
     rx_frame_errors: 0
     rx_no_buffer_count: 0
     rx_missed_errors: 0
     tx_aborted_errors: 0
     tx_carrier_errors: 0
     tx_fifo_errors: 0
     tx_heartbeat_errors: 0
     tx_window_errors: 0
     tx_abort_late_coll: 0
     tx_deferred_ok: 0
     tx_single_coll_ok: 0
     tx_multi_coll_ok: 0
     tx_timeout_count: 0
     tx_restart_queue: 0
     rx_long_length_errors: 0
     rx_short_length_errors: 0
     rx_align_errors: 0
     tx_tcp_seg_good: 0
     tx_tcp_seg_failed: 0
     rx_flow_control_xon: 0
     rx_flow_control_xoff: 0
     tx_flow_control_xon: 0
     tx_flow_control_xoff: 0
     rx_long_byte_count: 0
     rx_csum_offload_good: 0
     rx_csum_offload_errors: 0
     rx_header_split: 0
     alloc_rx_buff_failed: 0
     tx_smbus: 0
     rx_smbus: 0
     dropped_smbus: 0
     rx_dma_failed: 0
     tx_dma_failed: 0

[-- Attachment #3: ethtool_S_eth1.afterRescan --]
[-- Type: text/plain, Size: 1230 bytes --]

NIC statistics:
     rx_packets: 757689
     tx_packets: 531099
     rx_bytes: 4817824750
     tx_bytes: 643044246
     rx_broadcast: 63896
     tx_broadcast: 40
     rx_multicast: 0
     tx_multicast: 0
     rx_errors: 0
     tx_errors: 0
     tx_dropped: 0
     multicast: 0
     collisions: 0
     rx_length_errors: 0
     rx_over_errors: 0
     rx_crc_errors: 0
     rx_frame_errors: 0
     rx_no_buffer_count: 0
     rx_missed_errors: 0
     tx_aborted_errors: 0
     tx_carrier_errors: 0
     tx_fifo_errors: 0
     tx_heartbeat_errors: 0
     tx_window_errors: 0
     tx_abort_late_coll: 0
     tx_deferred_ok: 0
     tx_single_coll_ok: 0
     tx_multi_coll_ok: 0
     tx_timeout_count: 0
     tx_restart_queue: 0
     rx_long_length_errors: 0
     rx_short_length_errors: 0
     rx_align_errors: 0
     tx_tcp_seg_good: 9097
     tx_tcp_seg_failed: 0
     rx_flow_control_xon: 0
     rx_flow_control_xoff: 0
     tx_flow_control_xon: 0
     tx_flow_control_xoff: 0
     rx_long_byte_count: 4817824750
     rx_csum_offload_good: 693784
     rx_csum_offload_errors: 0
     rx_header_split: 7139
     alloc_rx_buff_failed: 0
     tx_smbus: 0
     rx_smbus: 0
     dropped_smbus: 0
     rx_dma_failed: 0
     tx_dma_failed: 0

[-- Attachment #4: ethtool_S_eth0.afterDHClient --]
[-- Type: text/plain, Size: 1201 bytes --]

NIC statistics:
     rx_packets: 613
     tx_packets: 46
     rx_bytes: 44804
     tx_bytes: 4280
     rx_broadcast: 464
     tx_broadcast: 3
     rx_multicast: 0
     tx_multicast: 0
     rx_errors: 0
     tx_errors: 0
     tx_dropped: 0
     multicast: 0
     collisions: 0
     rx_length_errors: 0
     rx_over_errors: 0
     rx_crc_errors: 0
     rx_frame_errors: 0
     rx_no_buffer_count: 0
     rx_missed_errors: 127
     tx_aborted_errors: 0
     tx_carrier_errors: 0
     tx_fifo_errors: 0
     tx_heartbeat_errors: 0
     tx_window_errors: 0
     tx_abort_late_coll: 0
     tx_deferred_ok: 0
     tx_single_coll_ok: 0
     tx_multi_coll_ok: 0
     tx_timeout_count: 0
     tx_restart_queue: 0
     rx_long_length_errors: 0
     rx_short_length_errors: 0
     rx_align_errors: 0
     tx_tcp_seg_good: 0
     tx_tcp_seg_failed: 0
     rx_flow_control_xon: 0
     rx_flow_control_xoff: 0
     tx_flow_control_xon: 0
     tx_flow_control_xoff: 0
     rx_long_byte_count: 44804
     rx_csum_offload_good: 24
     rx_csum_offload_errors: 0
     rx_header_split: 0
     alloc_rx_buff_failed: 0
     tx_smbus: 123
     rx_smbus: 716
     dropped_smbus: 0
     rx_dma_failed: 0
     tx_dma_failed: 0

[-- Attachment #5: ethregs.afterRescan --]
[-- Type: text/plain, Size: 41597 bytes --]

0e:00.0 (8086:109a)
Intel Corporation 82573L Gigabit Ethernet Controller
	Name           Value
	~~~~           ~~~~~
	CTRL           00140248
	STATUS         80080783
	EECD           06008318
	EERD           f7460012
	CTRL_EXT       28780000
	FLA            00000608
	MDIC           182a3800
	FCAL           00c28001
	FCAH           00000100
	FCT            00008808
	VET            00008100
	ITR            000000c3
	ICS            00000000
	IMS            0000009d
	IMC            0000009d
	IAM            ffffffff
	RCTL           06078422
	FCTTV          00000680
	TCTL           3103f0fa
	TIPG           00602008
	AIT            00000000
	LEDCTL         00078406
	EXTCNF_CTRL    1000000a
	EXTCNF_SIZE    00000004
	PBA            0012000e
	PBS            00000020
	EEMNGCTL       80000000
	EEARBC         00000100
	FLASHT         00000002
	EEWR           00000002
	FLSWCTL        c0000000
	FLSWDATA       00000000
	FLSWCNT        00000000
	FLOP           0004db00
	ERT            00002100
	FCRTL          80002ff8
	FCRTH          00003000
	PSRCTL         04040401
	RDBAL          16b08000
	RDBAH          00000002
	RDLEN          00002000
	RDH            00000010
	RDT            0000000c
	RDTR           00000000
	RXDCTL         00010003
	RADV           00000008
	RDBAL1         00000000
	RDBAH1         00000200
	RDLEN1         00000000
	RDH1           00000000
	RDT1           00000000
	RSRPD          00000000
	RAID           00000000
	CPUVEC         00000000
	TDFH           000009f0
	TDFT           000009f0
	TDFHS          000009f0
	TDFTS          000009f0
	TDFPC          00000000
	TDBAL          06c8c000
	TDBAH          00000002
	TDLEN          00001000
	TDH            00000083
	TDT            00000083
	TIDV           00000008
	TXDCTL         01410000
	TADV           00000020
	TARC0          00000403
	TDBAL1         80400000
	TDBAH1         00000000
	TDLEN1         00000000
	TDH1           00000000
	TDT1           00000000
	TXDCTL1        00400000
	TARC1          00000403
	ICRXPTC        00000053
	ICRXATC        00000000
	ICTXPTC        0000000d
	ICTXATC        00000000
	ICTXQEC        00000000
	ICTXQMTC       00000000
	ICRXDMTC       00000000
	ICRXOC         00000000
	RXCSUM         00001300
	RFCTL          00038000
	MTA[0]         00000000
	MTA[1]         00000000
	MTA[2]         00000000
	MTA[3]         00000000
	MTA[4]         00000000
	MTA[5]         00000000
	MTA[6]         00000000
	MTA[7]         00000000
	MTA[8]         00000000
	MTA[9]         00000000
	MTA[10]        00000000
	MTA[11]        00000000
	MTA[12]        00000000
	MTA[13]        00000000
	MTA[14]        00000000
	MTA[15]        00000000
	MTA[16]        00000000
	MTA[17]        00000000
	MTA[18]        00000000
	MTA[19]        00000000
	MTA[20]        00000000
	MTA[21]        00000000
	MTA[22]        00000000
	MTA[23]        00000000
	MTA[24]        00000000
	MTA[25]        00000000
	MTA[26]        00000000
	MTA[27]        00000000
	MTA[28]        00000000
	MTA[29]        00000000
	MTA[30]        00000000
	MTA[31]        00000000
	MTA[32]        00000000
	MTA[33]        00000000
	MTA[34]        00000000
	MTA[35]        00000000
	MTA[36]        00000000
	MTA[37]        00000000
	MTA[38]        00000000
	MTA[39]        00000000
	MTA[40]        00000000
	MTA[41]        00000000
	MTA[42]        00000000
	MTA[43]        00000000
	MTA[44]        00000000
	MTA[45]        00000000
	MTA[46]        00000000
	MTA[47]        00000000
	MTA[48]        00000000
	MTA[49]        00000000
	MTA[50]        00000000
	MTA[51]        00000000
	MTA[52]        00000000
	MTA[53]        00000000
	MTA[54]        00000000
	MTA[55]        00000000
	MTA[56]        00000000
	MTA[57]        00000000
	MTA[58]        00000000
	MTA[59]        00000000
	MTA[60]        00000000
	MTA[61]        00000000
	MTA[62]        00000000
	MTA[63]        00000000
	MTA[64]        00000000
	MTA[65]        00000000
	MTA[66]        00000000
	MTA[67]        00000000
	MTA[68]        00000000
	MTA[69]        00000000
	MTA[70]        00000000
	MTA[71]        00000000
	MTA[72]        00000000
	MTA[73]        00000000
	MTA[74]        00000000
	MTA[75]        00000000
	MTA[76]        00000000
	MTA[77]        00000000
	MTA[78]        00000000
	MTA[79]        00000000
	MTA[80]        00000000
	MTA[81]        00000000
	MTA[82]        00000000
	MTA[83]        00000000
	MTA[84]        00000000
	MTA[85]        00000000
	MTA[86]        00000000
	MTA[87]        00000000
	MTA[88]        00000000
	MTA[89]        00000000
	MTA[90]        00000000
	MTA[91]        00000000
	MTA[92]        00000000
	MTA[93]        00000000
	MTA[94]        00000000
	MTA[95]        00000000
	MTA[96]        00000000
	MTA[97]        00000000
	MTA[98]        00000000
	MTA[99]        00000000
	MTA[100]       00000000
	MTA[101]       00000000
	MTA[102]       00000000
	MTA[103]       00000000
	MTA[104]       00000000
	MTA[105]       00000000
	MTA[106]       00000000
	MTA[107]       00000000
	MTA[108]       00000000
	MTA[109]       00000000
	MTA[110]       00000000
	MTA[111]       00000000
	MTA[112]       00000000
	MTA[113]       00000000
	MTA[114]       00000000
	MTA[115]       00000000
	MTA[116]       00000000
	MTA[117]       00000000
	MTA[118]       00000000
	MTA[119]       00000000
	MTA[120]       00000000
	MTA[121]       00000000
	MTA[122]       00000000
	MTA[123]       00000000
	MTA[124]       00000000
	MTA[125]       00000000
	MTA[126]       00000000
	MTA[127]       00000000
	RAL[0]         96483000
	RAH[0]         8000e3e1
	RAL[1]         005e0001
	RAH[1]         80000100
	RAL[2]         00000000
	RAH[2]         00000000
	RAL[3]         00000000
	RAH[3]         00000000
	RAL[4]         00000000
	RAH[4]         00000000
	RAL[5]         00000000
	RAH[5]         00000000
	RAL[6]         00000000
	RAH[6]         00000000
	RAL[7]         00000000
	RAH[7]         00000000
	RAL[8]         00000000
	RAH[8]         00000000
	RAL[9]         00000000
	RAH[9]         00000000
	RAL[10]        00000000
	RAH[10]        00000000
	RAL[11]        00000000
	RAH[11]        00000000
	RAL[12]        00000000
	RAH[12]        00000000
	RAL[13]        00000000
	RAH[13]        00000000
	RAL[14]        00000000
	RAH[14]        00000000
	RAL[15]        00000000
	RAH[15]        00020010
	VFTA[0]        00000000
	VFTA[1]        00000000
	VFTA[2]        00000000
	VFTA[3]        00000000
	VFTA[4]        00000000
	VFTA[5]        00000000
	VFTA[6]        00000000
	VFTA[7]        00000000
	VFTA[8]        00000000
	VFTA[9]        00000000
	VFTA[10]       00000000
	VFTA[11]       00000000
	VFTA[12]       00000000
	VFTA[13]       00000000
	VFTA[14]       00000000
	VFTA[15]       00000000
	VFTA[16]       00000000
	VFTA[17]       00000000
	VFTA[18]       00000000
	VFTA[19]       00000000
	VFTA[20]       00000000
	VFTA[21]       00000000
	VFTA[22]       00000000
	VFTA[23]       00000000
	VFTA[24]       00000000
	VFTA[25]       00000000
	VFTA[26]       00000000
	VFTA[27]       00000000
	VFTA[28]       00000000
	VFTA[29]       00000000
	VFTA[30]       00000000
	VFTA[31]       00000000
	VFTA[32]       00000000
	VFTA[33]       00000000
	VFTA[34]       00000000
	VFTA[35]       00000000
	VFTA[36]       00000000
	VFTA[37]       00000000
	VFTA[38]       00000000
	VFTA[39]       00000000
	VFTA[40]       00000000
	VFTA[41]       00000000
	VFTA[42]       00000000
	VFTA[43]       00000000
	VFTA[44]       00000000
	VFTA[45]       00000000
	VFTA[46]       00000000
	VFTA[47]       00000000
	VFTA[48]       00000000
	VFTA[49]       00000000
	VFTA[50]       00000000
	VFTA[51]       00000000
	VFTA[52]       00000000
	VFTA[53]       00000000
	VFTA[54]       00000000
	VFTA[55]       00000000
	VFTA[56]       00000000
	VFTA[57]       00000000
	VFTA[58]       00000000
	VFTA[59]       00000000
	VFTA[60]       00000000
	VFTA[61]       00000000
	VFTA[62]       00000000
	VFTA[63]       00000000
	VFTA[64]       00000000
	VFTA[65]       00000000
	VFTA[66]       00000000
	VFTA[67]       00000000
	VFTA[68]       00000000
	VFTA[69]       00000000
	VFTA[70]       00000000
	VFTA[71]       00000000
	VFTA[72]       00000000
	VFTA[73]       00000000
	VFTA[74]       00000000
	VFTA[75]       00000000
	VFTA[76]       00000000
	VFTA[77]       00000000
	VFTA[78]       00000000
	VFTA[79]       00000000
	VFTA[80]       00000000
	VFTA[81]       00000000
	VFTA[82]       00000000
	VFTA[83]       00000000
	VFTA[84]       00000000
	VFTA[85]       00000000
	VFTA[86]       00000000
	VFTA[87]       00000000
	VFTA[88]       00000000
	VFTA[89]       00000000
	VFTA[90]       00000000
	VFTA[91]       00000000
	VFTA[92]       00000000
	VFTA[93]       00000000
	VFTA[94]       00000000
	VFTA[95]       00000000
	VFTA[96]       00000000
	VFTA[97]       00000000
	VFTA[98]       00000000
	VFTA[99]       00000000
	VFTA[100]      00000000
	VFTA[101]      00000000
	VFTA[102]      00000000
	VFTA[103]      00000000
	VFTA[104]      00000000
	VFTA[105]      00000000
	VFTA[106]      00000000
	VFTA[107]      00000000
	VFTA[108]      00000000
	VFTA[109]      00000000
	VFTA[110]      00000000
	VFTA[111]      00000000
	VFTA[112]      00000000
	VFTA[113]      00000000
	VFTA[114]      00000000
	VFTA[115]      00000000
	VFTA[116]      00000000
	VFTA[117]      00000000
	VFTA[118]      00000000
	VFTA[119]      00000000
	VFTA[120]      00000000
	VFTA[121]      00000000
	VFTA[122]      00000000
	VFTA[123]      00000000
	VFTA[124]      00000000
	VFTA[125]      00000000
	VFTA[126]      00000000
	VFTA[127]      00000000
	WUC            00000000
	WUFC           00000000
	WUS            00000000
	MRQC           00000000
	MANC           00000100
	IPAV           00000000
	MANC2H         00000000
	RSSIM          00000000
	RSSIR          00000001
	WUPL           9ce201fa
	GCR            0e000000
	GSCL_1         00000000
	GSCL_2         00000000
	GSCL_3         00000000
	GSCL_4         00000000
	FACTPS         a1041046
	FWSM           00000000
	RETA[0]        00000015
	RETA[1]        0000006b
	RETA[2]        00000004
	RETA[3]        000000e2
	RETA[4]        00000070
	RETA[5]        00000077
	RETA[6]        00000018
	RETA[7]        00000001
	RETA[8]        00000029
	RETA[9]        00000069
	RETA[10]       00000004
	RETA[11]       00000081
	RETA[12]       00000040
	RETA[13]       0000001e
	RETA[14]       00000093
	RETA[15]       000000c3
	RETA[16]       0000001b
	RETA[17]       0000002f
	RETA[18]       00000002
	RETA[19]       000000f4
	RETA[20]       000000bd
	RETA[21]       000000b6
	RETA[22]       000000af
	RETA[23]       00000029
	RETA[24]       00000003
	RETA[25]       0000001e
	RETA[26]       00000011
	RETA[27]       000000a5
	RETA[28]       0000008f
	RETA[29]       0000000b
	RETA[30]       00000059
	RETA[31]       00000006
	RETA[32]       00000008
	RETA[33]       000000d8
	RETA[34]       00000099
	RETA[35]       000000fb
	RETA[36]       0000003c
	RETA[37]       0000006c
	RETA[38]       00000011
	RETA[39]       00000027
	RETA[40]       00000029
	RETA[41]       00000097
	RETA[42]       00000055
	RETA[43]       000000a2
	RETA[44]       00000019
	RETA[45]       0000006e
	RETA[46]       00000011
	RETA[47]       00000060
	RETA[48]       000000ef
	RETA[49]       000000c1
	RETA[50]       00000033
	RETA[51]       000000a2
	RETA[52]       00000007
	RETA[53]       0000008a
	RETA[54]       0000006c
	RETA[55]       000000c2
	RETA[56]       00000029
	RETA[57]       0000002e
	RETA[58]       0000008b
	RETA[59]       00000063
	RETA[60]       00000035
	RETA[61]       00000015
	RETA[62]       00000091
	RETA[63]       000000ec
	RETA[64]       00000045
	RETA[65]       0000003b
	RETA[66]       0000001d
	RETA[67]       00000040
	RETA[68]       000000c5
	RETA[69]       00000082
	RETA[70]       000000b3
	RETA[71]       000000b6
	RETA[72]       0000000a
	RETA[73]       0000009b
	RETA[74]       000000d2
	RETA[75]       000000d2
	RETA[76]       0000004a
	RETA[77]       0000004e
	RETA[78]       00000010
	RETA[79]       000000e0
	RETA[80]       0000003a
	RETA[81]       000000ae
	RETA[82]       0000000d
	RETA[83]       00000070
	RETA[84]       0000001a
	RETA[85]       000000e7
	RETA[86]       000000c7
	RETA[87]       000000a5
	RETA[88]       0000006d
	RETA[89]       0000002f
	RETA[90]       00000061
	RETA[91]       00000026
	RETA[92]       0000000f
	RETA[93]       0000001f
	RETA[94]       00000019
	RETA[95]       000000ed
	RETA[96]       00000059
	RETA[97]       00000003
	RETA[98]       00000058
	RETA[99]       000000c9
	RETA[100]      0000006d
	RETA[101]      000000aa
	RETA[102]      0000000b
	RETA[103]      00000063
	RETA[104]      000000cd
	RETA[105]      0000001f
	RETA[106]      00000018
	RETA[107]      00000042
	RETA[108]      00000079
	RETA[109]      0000000f
	RETA[110]      0000005b
	RETA[111]      00000042
	RETA[112]      00000049
	RETA[113]      0000006e
	RETA[114]      00000008
	RETA[115]      00000076
	RETA[116]      0000002d
	RETA[117]      00000059
	RETA[118]      00000047
	RETA[119]      000000a6
	RETA[120]      00000090
	RETA[121]      00000002
	RETA[122]      000000cb
	RETA[123]      00000049
	RETA[124]      00000093
	RETA[125]      00000009
	RETA[126]      00000016
	RETA[127]      000000f2
	RSSRK[0]       00000000
	RSSRK[1]       00000000
	RSSRK[2]       00000000
	RSSRK[3]       00000000
	RSSRK[4]       00000000
	RSSRK[5]       00000000
	RSSRK[6]       00000000
	RSSRK[7]       00000000
	RSSRK[8]       00000000
	RSSRK[9]       00000000
	RSSRK[10]      00000000
	RSSRK[11]      00000000
	RSSRK[12]      00000000
	RSSRK[13]      00000000
	RSSRK[14]      00000000
	RSSRK[15]      00000000
	RSSRK[16]      00000000
	RSSRK[17]      00000000
	RSSRK[18]      00000000
	RSSRK[19]      00000000
	RSSRK[20]      00000000
	RSSRK[21]      00000000
	RSSRK[22]      00000000
	RSSRK[23]      00000000
	RSSRK[24]      00000000
	RSSRK[25]      00000000
	RSSRK[26]      00000000
	RSSRK[27]      00000000
	RSSRK[28]      00000000
	RSSRK[29]      00000000
	RSSRK[30]      00000000
	RSSRK[31]      00000000
	RSSRK[32]      00000000
	RSSRK[33]      00000000
	RSSRK[34]      00000000
	RSSRK[35]      00000000
	RSSRK[36]      00000000
	RSSRK[37]      00000000
	RSSRK[38]      00000000
	RSSRK[39]      00000000
	FFLT[0]        00000000
	FFLT[1]        fffc0000
	FFLT[2]        00000000
	FFLT[3]        00000000
	FFLT[4]        00000000
	FFLT[5]        00000000
	FFLT[6]        00000000
	FFLT[7]        00000000
	FFLT[8]        00000080
	FFLT[9]        00000000
	FFLT[10]       00000002
	FFLT[11]       00000000
	HICR           00000000
	FFMT[0]        00000006
	FFMT[1]        00000006
	FFMT[2]        00000009
	FFMT[3]        00000009
	FFMT[4]        0000000e
	FFMT[5]        0000000e
	FFMT[6]        0000000d
	FFMT[7]        0000000d
	FFMT[8]        0000000b
	FFMT[9]        0000000b
	FFMT[10]       0000000d
	FFMT[11]       0000000d
	FFMT[12]       00000004
	FFMT[13]       00000004
	FFMT[14]       00000000
	FFMT[15]       00000000
	FFMT[16]       00000000
	FFMT[17]       00000000
	FFMT[18]       00000009
	FFMT[19]       00000009
	FFMT[20]       00000001
	FFMT[21]       00000001
	FFMT[22]       00000006
	FFMT[23]       00000006
	FFMT[24]       00000003
	FFMT[25]       00000003
	FFMT[26]       00000004
	FFMT[27]       00000004
	FFMT[28]       00000005
	FFMT[29]       00000005
	FFMT[30]       0000000c
	FFMT[31]       0000000c
	FFMT[32]       00000000
	FFMT[33]       00000000
	FFMT[34]       00000008
	FFMT[35]       00000008
	FFMT[36]       00000002
	FFMT[37]       00000002
	FFMT[38]       0000000e
	FFMT[39]       0000000e
	FFMT[40]       00000003
	FFMT[41]       00000003
	FFMT[42]       0000000b
	FFMT[43]       0000000b
	FFMT[44]       00000001
	FFMT[45]       00000001
	FFMT[46]       00000005
	FFMT[47]       00000005
	FFMT[48]       00000003
	FFMT[49]       00000003
	FFMT[50]       00000001
	FFMT[51]       00000001
	FFMT[52]       0000000a
	FFMT[53]       0000000a
	FFMT[54]       00000003
	FFMT[55]       00000003
	FFMT[56]       00000001
	FFMT[57]       00000001
	FFMT[58]       0000000d
	FFMT[59]       0000000d
	FFMT[60]       00000008
	FFMT[61]       00000008
	FFMT[62]       00000002
	FFMT[63]       00000002
	FFMT[64]       00000002
	FFMT[65]       00000002
	FFMT[66]       00000007
	FFMT[67]       00000007
	FFMT[68]       00000004
	FFMT[69]       00000004
	FFMT[70]       00000006
	FFMT[71]       00000006
	FFMT[72]       0000000e
	FFMT[73]       0000000e
	FFMT[74]       0000000e
	FFMT[75]       0000000e
	FFMT[76]       0000000f
	FFMT[77]       0000000f
	FFMT[78]       00000002
	FFMT[79]       00000002
	FFMT[80]       00000000
	FFMT[81]       00000000
	FFMT[82]       0000000b
	FFMT[83]       0000000b
	FFMT[84]       00000009
	FFMT[85]       00000009
	FFMT[86]       00000009
	FFMT[87]       00000009
	FFMT[88]       0000000a
	FFMT[89]       0000000a
	FFMT[90]       0000000d
	FFMT[91]       0000000d
	FFMT[92]       00000005
	FFMT[93]       00000005
	FFMT[94]       00000006
	FFMT[95]       00000006
	FFMT[96]       00000003
	FFMT[97]       00000003
	FFMT[98]       0000000d
	FFMT[99]       0000000d
	FFMT[100]      00000009
	FFMT[101]      00000009
	FFMT[102]      0000000d
	FFMT[103]      0000000d
	FFMT[104]      00000001
	FFMT[105]      00000001
	FFMT[106]      0000000e
	FFMT[107]      0000000e
	FFMT[108]      0000000b
	FFMT[109]      0000000b
	FFMT[110]      00000000
	FFMT[111]      00000000
	FFMT[112]      00000001
	FFMT[113]      00000001
	FFMT[114]      00000000
	FFMT[115]      00000000
	FFMT[116]      00000008
	FFMT[117]      00000008
	FFMT[118]      0000000a
	FFMT[119]      0000000a
	FFMT[120]      00000001
	FFMT[121]      00000001
	FFMT[122]      00000006
	FFMT[123]      00000006
	FFMT[124]      00000002
	FFMT[125]      00000002
	FFMT[126]      0000000f
	FFMT[127]      0000000f
	FFVT[0]        a6d21076
	FFVT[1]        a6d21076
	FFVT[2]        14fddf8e
	FFVT[3]        14fddf8e
	FFVT[4]        af998eff
	FFVT[5]        af998eff
	FFVT[6]        72ee35eb
	FFVT[7]        72ee35eb
	FFVT[8]        4595b5d0
	FFVT[9]        4595b5d0
	FFVT[10]       9ce2d272
	FFVT[11]       9ce2d272
	FFVT[12]       65ccdb20
	FFVT[13]       65ccdb20
	FFVT[14]       7a6d632f
	FFVT[15]       7a6d632f
	FFVT[16]       c9fd53bd
	FFVT[17]       c9fd53bd
	FFVT[18]       138adc2d
	FFVT[19]       138adc2d
	FFVT[20]       5a7c8912
	FFVT[21]       5a7c8912
	FFVT[22]       080da768
	FFVT[23]       080da768
	FFVT[24]       e00a93c6
	FFVT[25]       e00a93c6
	FFVT[26]       3d05bbe0
	FFVT[27]       3d05bbe0
	FFVT[28]       8dc0ad89
	FFVT[29]       8dc0ad89
	FFVT[30]       a0267e00
	FFVT[31]       a0267e00
	FFVT[32]       45f0b43f
	FFVT[33]       45f0b43f
	FFVT[34]       62120156
	FFVT[35]       62120156
	FFVT[36]       a6213b97
	FFVT[37]       a6213b97
	FFVT[38]       ea15b0b6
	FFVT[39]       ea15b0b6
	FFVT[40]       a4176212
	FFVT[41]       a4176212
	FFVT[42]       ae88d158
	FFVT[43]       ae88d158
	FFVT[44]       541de595
	FFVT[45]       541de595
	FFVT[46]       15d56ace
	FFVT[47]       15d56ace
	FFVT[48]       45824374
	FFVT[49]       45824374
	FFVT[50]       2ba17885
	FFVT[51]       2ba17885
	FFVT[52]       b63201ea
	FFVT[53]       b63201ea
	FFVT[54]       b1ff88da
	FFVT[55]       b1ff88da
	FFVT[56]       f24edcea
	FFVT[57]       f24edcea
	FFVT[58]       b068c2e7
	FFVT[59]       b068c2e7
	FFVT[60]       58a6584c
	FFVT[61]       58a6584c
	FFVT[62]       ca6624d0
	FFVT[63]       ca6624d0
	FFVT[64]       d66319d3
	FFVT[65]       d66319d3
	FFVT[66]       437f892f
	FFVT[67]       437f892f
	FFVT[68]       6298ced1
	FFVT[69]       6298ced1
	FFVT[70]       d8f20b8e
	FFVT[71]       d8f20b8e
	FFVT[72]       00a8562c
	FFVT[73]       00a8562c
	FFVT[74]       536016e4
	FFVT[75]       536016e4
	FFVT[76]       81723c11
	FFVT[77]       81723c11
	FFVT[78]       6baf812a
	FFVT[79]       6baf812a
	FFVT[80]       579813dc
	FFVT[81]       579813dc
	FFVT[82]       f1099664
	FFVT[83]       f1099664
	FFVT[84]       484724af
	FFVT[85]       484724af
	FFVT[86]       9473f82f
	FFVT[87]       9473f82f
	FFVT[88]       2086be8f
	FFVT[89]       2086be8f
	FFVT[90]       505baa7a
	FFVT[91]       505baa7a
	FFVT[92]       e106d4d4
	FFVT[93]       e106d4d4
	FFVT[94]       035cf124
	FFVT[95]       035cf124
	FFVT[96]       80e38b56
	FFVT[97]       80e38b56
	FFVT[98]       03ef854a
	FFVT[99]       03ef854a
	FFVT[100]      ece8d8c9
	FFVT[101]      ece8d8c9
	FFVT[102]      a1d4c1a9
	FFVT[103]      a1d4c1a9
	FFVT[104]      e800f0b6
	FFVT[105]      e800f0b6
	FFVT[106]      7019d873
	FFVT[107]      7019d873
	FFVT[108]      a45554ff
	FFVT[109]      a45554ff
	FFVT[110]      29f98242
	FFVT[111]      29f98242
	FFVT[112]      b517937f
	FFVT[113]      b517937f
	FFVT[114]      a4d35dd5
	FFVT[115]      a4d35dd5
	FFVT[116]      52328c1b
	FFVT[117]      52328c1b
	FFVT[118]      09f59e76
	FFVT[119]      09f59e76
	FFVT[120]      1968c620
	FFVT[121]      1968c620
	FFVT[122]      cba89964
	FFVT[123]      cba89964
	FFVT[124]      42dc73e1
	FFVT[125]      42dc73e1
	FFVT[126]      06efaa25
	FFVT[127]      06efaa25


0d:00.0 (8086:108c)
Intel Corporation 82573E Gigabit Ethernet Controller (Copper)
	Name           Value
	~~~~           ~~~~~
	CTRL           00140248
	STATUS         80080743
	EECD           02011b18
	EERD           ffff0026
	CTRL_EXT       00780000
	FLA            00000608
	MDIC           14390000
	FCAL           00c28001
	FCAH           00000100
	FCT            00008808
	VET            00008100
	ITR            00000000
	ICS            00000044
	IMS            00000000
	IMC            00000000
	IAM            00000000
	RCTL           00000000
	FCTTV          00000680
	TCTL           30000008
	TIPG           00602008
	AIT            00000000
	LEDCTL         00078406
	EXTCNF_CTRL    10000008
	EXTCNF_SIZE    00000000
	PBA            000c0014
	PBS            00000020
	EEMNGCTL       800000f7
	EEARBC         00080100
	FLASHT         00000002
	EEWR           00000002
	FLSWCTL        c0000000
	FLSWDATA       00000000
	FLSWCNT        00000000
	FLOP           00012000
	ERT            00000000
	FCRTL          800047f8
	FCRTH          00004800
	PSRCTL         00040402
	RDBAL          148a0000
	RDBAH          00000002
	RDLEN          00000000
	RDH            00000000
	RDT            00000000
	RDTR           00000000
	RXDCTL         00010000
	RADV           00000000
	RDBAL1         00000000
	RDBAH1         01200200
	RDLEN1         00000000
	RDH1           00000000
	RDT1           00000000
	RSRPD          00000000
	RAID           00000000
	CPUVEC         00000000
	TDFH           00000a00
	TDFT           00000a00
	TDFHS          00000a00
	TDFTS          00000a00
	TDFPC          00000000
	TDBAL          16a44000
	TDBAH          00000002
	TDLEN          00000000
	TDH            00000000
	TDT            00000000
	TIDV           00000000
	TXDCTL         01410000
	TADV           00000000
	TARC0          00000403
	TDBAL1         00800000
	TDBAH1         10000500
	TDLEN1         00000000
	TDH1           00000000
	TDT1           00000000
	TXDCTL1        00400000
	TARC1          00000403
	ICRXPTC        00000000
	ICRXATC        00000000
	ICTXPTC        00000000
	ICTXATC        00000000
	ICTXQEC        00000000
	ICTXQMTC       00000000
	ICRXDMTC       00000000
	ICRXOC         00000000
	RXCSUM         00000300
	RFCTL          00000000
	MTA[0]         00000000
	MTA[1]         00000000
	MTA[2]         00000000
	MTA[3]         00000000
	MTA[4]         00000000
	MTA[5]         00000000
	MTA[6]         00000000
	MTA[7]         00000000
	MTA[8]         00000000
	MTA[9]         00000000
	MTA[10]        00000000
	MTA[11]        00000000
	MTA[12]        00000000
	MTA[13]        00000000
	MTA[14]        00000000
	MTA[15]        00000000
	MTA[16]        00000000
	MTA[17]        00000000
	MTA[18]        00000000
	MTA[19]        00000000
	MTA[20]        00000000
	MTA[21]        00000000
	MTA[22]        00000000
	MTA[23]        00000000
	MTA[24]        00000000
	MTA[25]        00000000
	MTA[26]        00000000
	MTA[27]        00000000
	MTA[28]        00000000
	MTA[29]        00000000
	MTA[30]        00000000
	MTA[31]        00000000
	MTA[32]        00000000
	MTA[33]        00000000
	MTA[34]        00000000
	MTA[35]        00000000
	MTA[36]        00000000
	MTA[37]        00000000
	MTA[38]        00000000
	MTA[39]        00000000
	MTA[40]        00000000
	MTA[41]        00000000
	MTA[42]        00000000
	MTA[43]        00000000
	MTA[44]        00000000
	MTA[45]        00000000
	MTA[46]        00000000
	MTA[47]        00000000
	MTA[48]        00000000
	MTA[49]        00000000
	MTA[50]        00000000
	MTA[51]        00000000
	MTA[52]        00000000
	MTA[53]        00000000
	MTA[54]        00000000
	MTA[55]        00000000
	MTA[56]        00000000
	MTA[57]        00000000
	MTA[58]        00000000
	MTA[59]        00000000
	MTA[60]        00000000
	MTA[61]        00000000
	MTA[62]        00000000
	MTA[63]        00000000
	MTA[64]        00000000
	MTA[65]        00000000
	MTA[66]        00000000
	MTA[67]        00000000
	MTA[68]        00000000
	MTA[69]        00000000
	MTA[70]        00000000
	MTA[71]        00000000
	MTA[72]        00000000
	MTA[73]        00000000
	MTA[74]        00000000
	MTA[75]        00000000
	MTA[76]        00000000
	MTA[77]        00000000
	MTA[78]        00000000
	MTA[79]        00000000
	MTA[80]        00000000
	MTA[81]        00000000
	MTA[82]        00000000
	MTA[83]        00000000
	MTA[84]        00000000
	MTA[85]        00000000
	MTA[86]        00000000
	MTA[87]        00000000
	MTA[88]        00000000
	MTA[89]        00000000
	MTA[90]        00000000
	MTA[91]        00000000
	MTA[92]        00000000
	MTA[93]        00000000
	MTA[94]        00000000
	MTA[95]        00000000
	MTA[96]        00000000
	MTA[97]        00000000
	MTA[98]        00000000
	MTA[99]        00000000
	MTA[100]       00000000
	MTA[101]       00000000
	MTA[102]       00000000
	MTA[103]       00000000
	MTA[104]       00000000
	MTA[105]       00000000
	MTA[106]       00000000
	MTA[107]       00000000
	MTA[108]       00000000
	MTA[109]       00000000
	MTA[110]       00000000
	MTA[111]       00000000
	MTA[112]       00000000
	MTA[113]       00000000
	MTA[114]       00000000
	MTA[115]       00000000
	MTA[116]       00000000
	MTA[117]       00000000
	MTA[118]       00000000
	MTA[119]       00000000
	MTA[120]       00000000
	MTA[121]       00000000
	MTA[122]       00000000
	MTA[123]       00000000
	MTA[124]       00000000
	MTA[125]       00000000
	MTA[126]       00000000
	MTA[127]       00000000
	RAL[0]         96483000
	RAH[0]         8000e2e1
	RAL[1]         00000000
	RAH[1]         00000000
	RAL[2]         00000000
	RAH[2]         00000000
	RAL[3]         00000000
	RAH[3]         00000000
	RAL[4]         00000000
	RAH[4]         00000000
	RAL[5]         00000000
	RAH[5]         00000000
	RAL[6]         00000000
	RAH[6]         00000000
	RAL[7]         00000000
	RAH[7]         00000000
	RAL[8]         00000000
	RAH[8]         00000000
	RAL[9]         00000000
	RAH[9]         00000000
	RAL[10]        00000000
	RAH[10]        00000000
	RAL[11]        00000000
	RAH[11]        00000000
	RAL[12]        00000000
	RAH[12]        00000000
	RAL[13]        00000000
	RAH[13]        00000000
	RAL[14]        00000000
	RAH[14]        00000000
	RAL[15]        96483000
	RAH[15]        0000e2e1
	VFTA[0]        00000000
	VFTA[1]        00000000
	VFTA[2]        00000000
	VFTA[3]        00000000
	VFTA[4]        00000000
	VFTA[5]        00000000
	VFTA[6]        00000000
	VFTA[7]        00000000
	VFTA[8]        00000000
	VFTA[9]        00000000
	VFTA[10]       00000000
	VFTA[11]       00000000
	VFTA[12]       00000000
	VFTA[13]       00000000
	VFTA[14]       00000000
	VFTA[15]       00000000
	VFTA[16]       00000000
	VFTA[17]       00000000
	VFTA[18]       00000000
	VFTA[19]       00000000
	VFTA[20]       00000000
	VFTA[21]       00000000
	VFTA[22]       00000000
	VFTA[23]       00000000
	VFTA[24]       00000000
	VFTA[25]       00000000
	VFTA[26]       00000000
	VFTA[27]       00000000
	VFTA[28]       00000000
	VFTA[29]       00000000
	VFTA[30]       00000000
	VFTA[31]       00000000
	VFTA[32]       00000000
	VFTA[33]       00000000
	VFTA[34]       00000000
	VFTA[35]       00000000
	VFTA[36]       00000000
	VFTA[37]       00000000
	VFTA[38]       00000000
	VFTA[39]       00000000
	VFTA[40]       00000000
	VFTA[41]       00000000
	VFTA[42]       00000000
	VFTA[43]       00000000
	VFTA[44]       00000000
	VFTA[45]       00000000
	VFTA[46]       00000000
	VFTA[47]       00000000
	VFTA[48]       00000000
	VFTA[49]       00000000
	VFTA[50]       00000000
	VFTA[51]       00000000
	VFTA[52]       00000000
	VFTA[53]       00000000
	VFTA[54]       00000000
	VFTA[55]       00000000
	VFTA[56]       00000000
	VFTA[57]       00000000
	VFTA[58]       00000000
	VFTA[59]       00000000
	VFTA[60]       00000000
	VFTA[61]       00000000
	VFTA[62]       00000000
	VFTA[63]       00000000
	VFTA[64]       00000000
	VFTA[65]       00000000
	VFTA[66]       00000000
	VFTA[67]       00000000
	VFTA[68]       00000000
	VFTA[69]       00000000
	VFTA[70]       00000000
	VFTA[71]       00000000
	VFTA[72]       00000000
	VFTA[73]       00000000
	VFTA[74]       00000000
	VFTA[75]       00000000
	VFTA[76]       00000000
	VFTA[77]       00000000
	VFTA[78]       00000000
	VFTA[79]       00000000
	VFTA[80]       00000000
	VFTA[81]       00000000
	VFTA[82]       00000000
	VFTA[83]       00000000
	VFTA[84]       00000000
	VFTA[85]       00000000
	VFTA[86]       00000000
	VFTA[87]       00000000
	VFTA[88]       00000000
	VFTA[89]       00000000
	VFTA[90]       00000000
	VFTA[91]       00000000
	VFTA[92]       00000000
	VFTA[93]       00000000
	VFTA[94]       00000000
	VFTA[95]       00000000
	VFTA[96]       00000000
	VFTA[97]       00000000
	VFTA[98]       00000000
	VFTA[99]       00000000
	VFTA[100]      00000000
	VFTA[101]      00000000
	VFTA[102]      00000000
	VFTA[103]      00000000
	VFTA[104]      00000000
	VFTA[105]      00000000
	VFTA[106]      00000000
	VFTA[107]      00000000
	VFTA[108]      00000000
	VFTA[109]      00000000
	VFTA[110]      00000000
	VFTA[111]      00000000
	VFTA[112]      00000000
	VFTA[113]      00000000
	VFTA[114]      00000000
	VFTA[115]      00000000
	VFTA[116]      00000000
	VFTA[117]      00000000
	VFTA[118]      00000000
	VFTA[119]      00000000
	VFTA[120]      00000000
	VFTA[121]      00000000
	VFTA[122]      00000000
	VFTA[123]      00000000
	VFTA[124]      00000000
	VFTA[125]      00000000
	VFTA[126]      00000000
	VFTA[127]      00000000
	WUC            00000000
	WUFC           00000000
	WUS            00000000
	MRQC           00000000
	MANC           0022a300
	IPAV           00000000
	MANC2H         00000380
	RSSIM          00000000
	RSSIR          00000000
	WUPL           28167f49
	GCR            0e000000
	GSCL_1         00000000
	GSCL_2         00000000
	GSCL_3         00000000
	GSCL_4         00000000
	FACTPS         01041046
	FWSM           00018044
	RETA[0]        0000008c
	RETA[1]        0000001f
	RETA[2]        00000082
	RETA[3]        00000086
	RETA[4]        0000009f
	RETA[5]        00000066
	RETA[6]        0000005a
	RETA[7]        0000004b
	RETA[8]        0000001e
	RETA[9]        000000af
	RETA[10]       000000dc
	RETA[11]       000000e5
	RETA[12]       0000002d
	RETA[13]       000000aa
	RETA[14]       0000009b
	RETA[15]       0000001c
	RETA[16]       00000053
	RETA[17]       000000e6
	RETA[18]       00000096
	RETA[19]       00000084
	RETA[20]       000000b1
	RETA[21]       0000006b
	RETA[22]       000000b7
	RETA[23]       000000de
	RETA[24]       00000010
	RETA[25]       000000d4
	RETA[26]       000000ef
	RETA[27]       00000034
	RETA[28]       00000038
	RETA[29]       0000000e
	RETA[30]       00000012
	RETA[31]       0000001d
	RETA[32]       00000001
	RETA[33]       0000004b
	RETA[34]       000000e3
	RETA[35]       0000001e
	RETA[36]       0000001b
	RETA[37]       0000009b
	RETA[38]       0000008e
	RETA[39]       00000068
	RETA[40]       00000015
	RETA[41]       000000e2
	RETA[42]       000000c7
	RETA[43]       000000c6
	RETA[44]       00000034
	RETA[45]       0000007a
	RETA[46]       000000b6
	RETA[47]       00000014
	RETA[48]       000000aa
	RETA[49]       0000006f
	RETA[50]       000000fa
	RETA[51]       00000085
	RETA[52]       00000032
	RETA[53]       0000004e
	RETA[54]       0000003f
	RETA[55]       0000004c
	RETA[56]       00000099
	RETA[57]       0000003d
	RETA[58]       000000f2
	RETA[59]       000000ae
	RETA[60]       00000011
	RETA[61]       0000006f
	RETA[62]       000000b7
	RETA[63]       0000000b
	RETA[64]       0000009b
	RETA[65]       00000007
	RETA[66]       0000000a
	RETA[67]       0000009a
	RETA[68]       000000a3
	RETA[69]       00000020
	RETA[70]       000000f3
	RETA[71]       00000084
	RETA[72]       0000004d
	RETA[73]       00000048
	RETA[74]       0000008b
	RETA[75]       00000021
	RETA[76]       000000c7
	RETA[77]       00000053
	RETA[78]       000000a3
	RETA[79]       0000008b
	RETA[80]       000000d4
	RETA[81]       0000004a
	RETA[82]       000000c2
	RETA[83]       000000c0
	RETA[84]       0000003b
	RETA[85]       00000069
	RETA[86]       00000082
	RETA[87]       0000005e
	RETA[88]       00000098
	RETA[89]       0000007a
	RETA[90]       00000017
	RETA[91]       00000084
	RETA[92]       000000ab
	RETA[93]       0000004a
	RETA[94]       000000c7
	RETA[95]       00000014
	RETA[96]       0000001d
	RETA[97]       0000006a
	RETA[98]       00000077
	RETA[99]       00000014
	RETA[100]      000000b9
	RETA[101]      0000000a
	RETA[102]      000000c2
	RETA[103]      0000003d
	RETA[104]      00000055
	RETA[105]      000000aa
	RETA[106]      000000b4
	RETA[107]      00000004
	RETA[108]      00000047
	RETA[109]      00000053
	RETA[110]      000000f7
	RETA[111]      00000016
	RETA[112]      0000008b
	RETA[113]      000000d3
	RETA[114]      000000b2
	RETA[115]      00000074
	RETA[116]      0000003b
	RETA[117]      0000002b
	RETA[118]      0000009d
	RETA[119]      00000016
	RETA[120]      0000002b
	RETA[121]      000000ce
	RETA[122]      0000008e
	RETA[123]      00000044
	RETA[124]      00000027
	RETA[125]      0000004b
	RETA[126]      000000c2
	RETA[127]      00000086
	RSSRK[0]       00000000
	RSSRK[1]       00000000
	RSSRK[2]       00000000
	RSSRK[3]       00000000
	RSSRK[4]       00000000
	RSSRK[5]       00000000
	RSSRK[6]       00000000
	RSSRK[7]       00000000
	RSSRK[8]       00000000
	RSSRK[9]       00000000
	RSSRK[10]      00000000
	RSSRK[11]      00000000
	RSSRK[12]      00000000
	RSSRK[13]      00000000
	RSSRK[14]      00000000
	RSSRK[15]      00000000
	RSSRK[16]      00000000
	RSSRK[17]      00000000
	RSSRK[18]      00000000
	RSSRK[19]      00000000
	RSSRK[20]      00000000
	RSSRK[21]      00000000
	RSSRK[22]      00000000
	RSSRK[23]      00000000
	RSSRK[24]      00000000
	RSSRK[25]      00000000
	RSSRK[26]      00000000
	RSSRK[27]      00000000
	RSSRK[28]      00000000
	RSSRK[29]      00000000
	RSSRK[30]      00000000
	RSSRK[31]      00000000
	RSSRK[32]      00000000
	RSSRK[33]      00000000
	RSSRK[34]      00000000
	RSSRK[35]      00000000
	RSSRK[36]      00000000
	RSSRK[37]      00000000
	RSSRK[38]      00000000
	RSSRK[39]      00000000
	FFLT[0]        00000000
	FFLT[1]        fffc0000
	FFLT[2]        00000000
	FFLT[3]        00000000
	FFLT[4]        00000000
	FFLT[5]        00000000
	FFLT[6]        00000000
	FFLT[7]        00000000
	FFLT[8]        00000000
	FFLT[9]        00000000
	FFLT[10]       00000000
	FFLT[11]       00000000
	HICR           00000101
	FFMT[0]        0000000c
	FFMT[1]        0000000c
	FFMT[2]        0000000d
	FFMT[3]        0000000d
	FFMT[4]        0000000c
	FFMT[5]        0000000c
	FFMT[6]        0000000f
	FFMT[7]        0000000f
	FFMT[8]        00000001
	FFMT[9]        00000001
	FFMT[10]       00000006
	FFMT[11]       00000006
	FFMT[12]       00000004
	FFMT[13]       00000004
	FFMT[14]       0000000c
	FFMT[15]       0000000c
	FFMT[16]       0000000e
	FFMT[17]       0000000e
	FFMT[18]       00000001
	FFMT[19]       00000001
	FFMT[20]       00000001
	FFMT[21]       00000001
	FFMT[22]       00000001
	FFMT[23]       00000001
	FFMT[24]       00000000
	FFMT[25]       00000000
	FFMT[26]       00000001
	FFMT[27]       00000001
	FFMT[28]       00000002
	FFMT[29]       00000002
	FFMT[30]       0000000f
	FFMT[31]       0000000f
	FFMT[32]       00000001
	FFMT[33]       00000001
	FFMT[34]       00000003
	FFMT[35]       00000003
	FFMT[36]       0000000c
	FFMT[37]       0000000c
	FFMT[38]       00000002
	FFMT[39]       00000002
	FFMT[40]       00000008
	FFMT[41]       00000008
	FFMT[42]       0000000f
	FFMT[43]       0000000f
	FFMT[44]       00000008
	FFMT[45]       00000008
	FFMT[46]       00000004
	FFMT[47]       00000004
	FFMT[48]       00000006
	FFMT[49]       00000006
	FFMT[50]       00000007
	FFMT[51]       00000007
	FFMT[52]       00000002
	FFMT[53]       00000002
	FFMT[54]       0000000b
	FFMT[55]       0000000b
	FFMT[56]       00000008
	FFMT[57]       00000008
	FFMT[58]       00000003
	FFMT[59]       00000003
	FFMT[60]       00000004
	FFMT[61]       00000004
	FFMT[62]       00000000
	FFMT[63]       00000000
	FFMT[64]       00000001
	FFMT[65]       00000001
	FFMT[66]       0000000e
	FFMT[67]       0000000e
	FFMT[68]       00000007
	FFMT[69]       00000007
	FFMT[70]       0000000b
	FFMT[71]       0000000b
	FFMT[72]       00000006
	FFMT[73]       00000006
	FFMT[74]       00000009
	FFMT[75]       00000009
	FFMT[76]       00000009
	FFMT[77]       00000009
	FFMT[78]       00000009
	FFMT[79]       00000009
	FFMT[80]       0000000f
	FFMT[81]       0000000f
	FFMT[82]       00000009
	FFMT[83]       00000009
	FFMT[84]       0000000a
	FFMT[85]       0000000a
	FFMT[86]       00000000
	FFMT[87]       00000000
	FFMT[88]       0000000b
	FFMT[89]       0000000b
	FFMT[90]       00000003
	FFMT[91]       00000003
	FFMT[92]       00000001
	FFMT[93]       00000001
	FFMT[94]       00000004
	FFMT[95]       00000004
	FFMT[96]       0000000b
	FFMT[97]       0000000b
	FFMT[98]       0000000c
	FFMT[99]       0000000c
	FFMT[100]      0000000a
	FFMT[101]      0000000a
	FFMT[102]      00000009
	FFMT[103]      00000009
	FFMT[104]      00000000
	FFMT[105]      00000000
	FFMT[106]      00000003
	FFMT[107]      00000003
	FFMT[108]      00000006
	FFMT[109]      00000006
	FFMT[110]      00000008
	FFMT[111]      00000008
	FFMT[112]      0000000e
	FFMT[113]      0000000e
	FFMT[114]      00000007
	FFMT[115]      00000007
	FFMT[116]      0000000c
	FFMT[117]      0000000c
	FFMT[118]      00000007
	FFMT[119]      00000007
	FFMT[120]      00000009
	FFMT[121]      00000009
	FFMT[122]      00000001
	FFMT[123]      00000001
	FFMT[124]      00000001
	FFMT[125]      00000001
	FFMT[126]      0000000f
	FFMT[127]      0000000f
	FFVT[0]        69386efe
	FFVT[1]        69386efe
	FFVT[2]        47dac1bd
	FFVT[3]        47dac1bd
	FFVT[4]        0af977e3
	FFVT[5]        0af977e3
	FFVT[6]        0bf35fcd
	FFVT[7]        0bf35fcd
	FFVT[8]        396325cb
	FFVT[9]        396325cb
	FFVT[10]       45fb2966
	FFVT[11]       45fb2966
	FFVT[12]       85fe3e31
	FFVT[13]       85fe3e31
	FFVT[14]       e6b90940
	FFVT[15]       e6b90940
	FFVT[16]       fcf5c382
	FFVT[17]       fcf5c382
	FFVT[18]       68b90289
	FFVT[19]       68b90289
	FFVT[20]       0fada5ed
	FFVT[21]       0fada5ed
	FFVT[22]       67f87890
	FFVT[23]       67f87890
	FFVT[24]       2dd69d55
	FFVT[25]       2dd69d55
	FFVT[26]       0f78a7b0
	FFVT[27]       0f78a7b0
	FFVT[28]       138d13f7
	FFVT[29]       138d13f7
	FFVT[30]       e302400a
	FFVT[31]       e302400a
	FFVT[32]       bc8ebaf7
	FFVT[33]       bc8ebaf7
	FFVT[34]       96fe79fb
	FFVT[35]       96fe79fb
	FFVT[36]       df5aa33b
	FFVT[37]       df5aa33b
	FFVT[38]       91212c9e
	FFVT[39]       91212c9e
	FFVT[40]       71c517b4
	FFVT[41]       71c517b4
	FFVT[42]       0bb6697f
	FFVT[43]       0bb6697f
	FFVT[44]       63018c23
	FFVT[45]       63018c23
	FFVT[46]       48a35d54
	FFVT[47]       48a35d54
	FFVT[48]       95f4d375
	FFVT[49]       95f4d375
	FFVT[50]       4699c679
	FFVT[51]       4699c679
	FFVT[52]       06e7adde
	FFVT[53]       06e7adde
	FFVT[54]       e31f1b6d
	FFVT[55]       e31f1b6d
	FFVT[56]       888919d6
	FFVT[57]       888919d6
	FFVT[58]       4751a142
	FFVT[59]       4751a142
	FFVT[60]       676fef06
	FFVT[61]       676fef06
	FFVT[62]       792d0e82
	FFVT[63]       792d0e82
	FFVT[64]       1066713d
	FFVT[65]       1066713d
	FFVT[66]       8f55fa4d
	FFVT[67]       8f55fa4d
	FFVT[68]       5fe46f1a
	FFVT[69]       5fe46f1a
	FFVT[70]       cacbc51e
	FFVT[71]       cacbc51e
	FFVT[72]       04470301
	FFVT[73]       04470301
	FFVT[74]       6b3dfea9
	FFVT[75]       6b3dfea9
	FFVT[76]       bd00be00
	FFVT[77]       bd00be00
	FFVT[78]       7079cb0c
	FFVT[79]       7079cb0c
	FFVT[80]       e7180acc
	FFVT[81]       e7180acc
	FFVT[82]       25755bec
	FFVT[83]       25755bec
	FFVT[84]       bcdd8914
	FFVT[85]       bcdd8914
	FFVT[86]       9ed3128d
	FFVT[87]       9ed3128d
	FFVT[88]       dc48587b
	FFVT[89]       dc48587b
	FFVT[90]       e9755ebf
	FFVT[91]       e9755ebf
	FFVT[92]       9ff23883
	FFVT[93]       9ff23883
	FFVT[94]       52d8233d
	FFVT[95]       52d8233d
	FFVT[96]       cdcf21c0
	FFVT[97]       cdcf21c0
	FFVT[98]       9069a69f
	FFVT[99]       9069a69f
	FFVT[100]      b52c57f5
	FFVT[101]      b52c57f5
	FFVT[102]      42977681
	FFVT[103]      42977681
	FFVT[104]      ab8b671a
	FFVT[105]      ab8b671a
	FFVT[106]      4edc0c8b
	FFVT[107]      4edc0c8b
	FFVT[108]      f41c47f0
	FFVT[109]      f41c47f0
	FFVT[110]      ab4edb12
	FFVT[111]      ab4edb12
	FFVT[112]      c096a36f
	FFVT[113]      c096a36f
	FFVT[114]      ed46c26a
	FFVT[115]      ed46c26a
	FFVT[116]      aca39e0b
	FFVT[117]      aca39e0b
	FFVT[118]      e01ed8b5
	FFVT[119]      e01ed8b5
	FFVT[120]      604c1ef5
	FFVT[121]      604c1ef5
	FFVT[122]      0dbbfeae
	FFVT[123]      0dbbfeae
	FFVT[124]      9478dbb7
	FFVT[125]      9478dbb7
	FFVT[126]      f95cfa23
	FFVT[127]      f95cfa23



[-- Attachment #6: ethtool_S_eth1.afterDHClient --]
[-- Type: text/plain, Size: 1230 bytes --]

NIC statistics:
     rx_packets: 760292
     tx_packets: 531525
     rx_bytes: 4818013321
     tx_bytes: 643103670
     rx_broadcast: 65963
     tx_broadcast: 41
     rx_multicast: 0
     tx_multicast: 0
     rx_errors: 0
     tx_errors: 0
     tx_dropped: 0
     multicast: 0
     collisions: 0
     rx_length_errors: 0
     rx_over_errors: 0
     rx_crc_errors: 0
     rx_frame_errors: 0
     rx_no_buffer_count: 0
     rx_missed_errors: 0
     tx_aborted_errors: 0
     tx_carrier_errors: 0
     tx_fifo_errors: 0
     tx_heartbeat_errors: 0
     tx_window_errors: 0
     tx_abort_late_coll: 0
     tx_deferred_ok: 0
     tx_single_coll_ok: 0
     tx_multi_coll_ok: 0
     tx_timeout_count: 0
     tx_restart_queue: 0
     rx_long_length_errors: 0
     rx_short_length_errors: 0
     rx_align_errors: 0
     tx_tcp_seg_good: 9097
     tx_tcp_seg_failed: 0
     rx_flow_control_xon: 0
     rx_flow_control_xoff: 0
     tx_flow_control_xon: 0
     tx_flow_control_xoff: 0
     rx_long_byte_count: 4818013321
     rx_csum_offload_good: 694310
     rx_csum_offload_errors: 0
     rx_header_split: 7424
     alloc_rx_buff_failed: 0
     tx_smbus: 0
     rx_smbus: 0
     dropped_smbus: 0
     rx_dma_failed: 0
     tx_dma_failed: 0

[-- Attachment #7: ethregs.afterDHClient --]
[-- Type: text/plain, Size: 41597 bytes --]

0e:00.0 (8086:109a)
Intel Corporation 82573L Gigabit Ethernet Controller
	Name           Value
	~~~~           ~~~~~
	CTRL           00140248
	STATUS         80080783
	EECD           06008318
	EERD           f7460012
	CTRL_EXT       28780000
	FLA            00000608
	MDIC           182a3800
	FCAL           00c28001
	FCAH           00000100
	FCT            00008808
	VET            00008100
	ITR            000000c3
	ICS            00000000
	IMS            0000009d
	IMC            0000009d
	IAM            ffffffff
	RCTL           06078422
	FCTTV          00000680
	TCTL           3103f0fa
	TIPG           00602008
	AIT            00000000
	LEDCTL         00078406
	EXTCNF_CTRL    1000000a
	EXTCNF_SIZE    00000004
	PBA            0012000e
	PBS            00000020
	EEMNGCTL       80000000
	EEARBC         00000100
	FLASHT         00000002
	EEWR           00000002
	FLSWCTL        c0000000
	FLSWDATA       00000000
	FLSWCNT        00000000
	FLOP           0004db00
	ERT            00002100
	FCRTL          80002ff8
	FCRTH          00003000
	PSRCTL         04040401
	RDBAL          16b08000
	RDBAH          00000002
	RDLEN          00002000
	RDH            0000007a
	RDT            00000076
	RDTR           00000000
	RXDCTL         00010003
	RADV           00000008
	RDBAL1         00000000
	RDBAH1         00000200
	RDLEN1         00000000
	RDH1           00000000
	RDT1           00000000
	RSRPD          00000000
	RAID           00000000
	CPUVEC         00000000
	TDFH           00000968
	TDFT           00000968
	TDFHS          00000968
	TDFTS          00000968
	TDFPC          00000000
	TDBAL          06c8c000
	TDBAH          00000002
	TDLEN          00001000
	TDH            00000053
	TDT            00000053
	TIDV           00000008
	TXDCTL         01410000
	TADV           00000020
	TARC0          00000403
	TDBAL1         80400000
	TDBAH1         00000000
	TDLEN1         00000000
	TDH1           00000000
	TDT1           00000000
	TXDCTL1        00400000
	TARC1          00000403
	ICRXPTC        00000002
	ICRXATC        00000000
	ICTXPTC        00000000
	ICTXATC        00000000
	ICTXQEC        00000000
	ICTXQMTC       00000000
	ICRXDMTC       00000000
	ICRXOC         00000000
	RXCSUM         00001300
	RFCTL          00038000
	MTA[0]         00000000
	MTA[1]         00000000
	MTA[2]         00000000
	MTA[3]         00000000
	MTA[4]         00000000
	MTA[5]         00000000
	MTA[6]         00000000
	MTA[7]         00000000
	MTA[8]         00000000
	MTA[9]         00000000
	MTA[10]        00000000
	MTA[11]        00000000
	MTA[12]        00000000
	MTA[13]        00000000
	MTA[14]        00000000
	MTA[15]        00000000
	MTA[16]        00000000
	MTA[17]        00000000
	MTA[18]        00000000
	MTA[19]        00000000
	MTA[20]        00000000
	MTA[21]        00000000
	MTA[22]        00000000
	MTA[23]        00000000
	MTA[24]        00000000
	MTA[25]        00000000
	MTA[26]        00000000
	MTA[27]        00000000
	MTA[28]        00000000
	MTA[29]        00000000
	MTA[30]        00000000
	MTA[31]        00000000
	MTA[32]        00000000
	MTA[33]        00000000
	MTA[34]        00000000
	MTA[35]        00000000
	MTA[36]        00000000
	MTA[37]        00000000
	MTA[38]        00000000
	MTA[39]        00000000
	MTA[40]        00000000
	MTA[41]        00000000
	MTA[42]        00000000
	MTA[43]        00000000
	MTA[44]        00000000
	MTA[45]        00000000
	MTA[46]        00000000
	MTA[47]        00000000
	MTA[48]        00000000
	MTA[49]        00000000
	MTA[50]        00000000
	MTA[51]        00000000
	MTA[52]        00000000
	MTA[53]        00000000
	MTA[54]        00000000
	MTA[55]        00000000
	MTA[56]        00000000
	MTA[57]        00000000
	MTA[58]        00000000
	MTA[59]        00000000
	MTA[60]        00000000
	MTA[61]        00000000
	MTA[62]        00000000
	MTA[63]        00000000
	MTA[64]        00000000
	MTA[65]        00000000
	MTA[66]        00000000
	MTA[67]        00000000
	MTA[68]        00000000
	MTA[69]        00000000
	MTA[70]        00000000
	MTA[71]        00000000
	MTA[72]        00000000
	MTA[73]        00000000
	MTA[74]        00000000
	MTA[75]        00000000
	MTA[76]        00000000
	MTA[77]        00000000
	MTA[78]        00000000
	MTA[79]        00000000
	MTA[80]        00000000
	MTA[81]        00000000
	MTA[82]        00000000
	MTA[83]        00000000
	MTA[84]        00000000
	MTA[85]        00000000
	MTA[86]        00000000
	MTA[87]        00000000
	MTA[88]        00000000
	MTA[89]        00000000
	MTA[90]        00000000
	MTA[91]        00000000
	MTA[92]        00000000
	MTA[93]        00000000
	MTA[94]        00000000
	MTA[95]        00000000
	MTA[96]        00000000
	MTA[97]        00000000
	MTA[98]        00000000
	MTA[99]        00000000
	MTA[100]       00000000
	MTA[101]       00000000
	MTA[102]       00000000
	MTA[103]       00000000
	MTA[104]       00000000
	MTA[105]       00000000
	MTA[106]       00000000
	MTA[107]       00000000
	MTA[108]       00000000
	MTA[109]       00000000
	MTA[110]       00000000
	MTA[111]       00000000
	MTA[112]       00000000
	MTA[113]       00000000
	MTA[114]       00000000
	MTA[115]       00000000
	MTA[116]       00000000
	MTA[117]       00000000
	MTA[118]       00000000
	MTA[119]       00000000
	MTA[120]       00000000
	MTA[121]       00000000
	MTA[122]       00000000
	MTA[123]       00000000
	MTA[124]       00000000
	MTA[125]       00000000
	MTA[126]       00000000
	MTA[127]       00000000
	RAL[0]         96483000
	RAH[0]         8000e3e1
	RAL[1]         005e0001
	RAH[1]         80000100
	RAL[2]         00000000
	RAH[2]         00000000
	RAL[3]         00000000
	RAH[3]         00000000
	RAL[4]         00000000
	RAH[4]         00000000
	RAL[5]         00000000
	RAH[5]         00000000
	RAL[6]         00000000
	RAH[6]         00000000
	RAL[7]         00000000
	RAH[7]         00000000
	RAL[8]         00000000
	RAH[8]         00000000
	RAL[9]         00000000
	RAH[9]         00000000
	RAL[10]        00000000
	RAH[10]        00000000
	RAL[11]        00000000
	RAH[11]        00000000
	RAL[12]        00000000
	RAH[12]        00000000
	RAL[13]        00000000
	RAH[13]        00000000
	RAL[14]        00000000
	RAH[14]        00000000
	RAL[15]        00000000
	RAH[15]        00020010
	VFTA[0]        00000000
	VFTA[1]        00000000
	VFTA[2]        00000000
	VFTA[3]        00000000
	VFTA[4]        00000000
	VFTA[5]        00000000
	VFTA[6]        00000000
	VFTA[7]        00000000
	VFTA[8]        00000000
	VFTA[9]        00000000
	VFTA[10]       00000000
	VFTA[11]       00000000
	VFTA[12]       00000000
	VFTA[13]       00000000
	VFTA[14]       00000000
	VFTA[15]       00000000
	VFTA[16]       00000000
	VFTA[17]       00000000
	VFTA[18]       00000000
	VFTA[19]       00000000
	VFTA[20]       00000000
	VFTA[21]       00000000
	VFTA[22]       00000000
	VFTA[23]       00000000
	VFTA[24]       00000000
	VFTA[25]       00000000
	VFTA[26]       00000000
	VFTA[27]       00000000
	VFTA[28]       00000000
	VFTA[29]       00000000
	VFTA[30]       00000000
	VFTA[31]       00000000
	VFTA[32]       00000000
	VFTA[33]       00000000
	VFTA[34]       00000000
	VFTA[35]       00000000
	VFTA[36]       00000000
	VFTA[37]       00000000
	VFTA[38]       00000000
	VFTA[39]       00000000
	VFTA[40]       00000000
	VFTA[41]       00000000
	VFTA[42]       00000000
	VFTA[43]       00000000
	VFTA[44]       00000000
	VFTA[45]       00000000
	VFTA[46]       00000000
	VFTA[47]       00000000
	VFTA[48]       00000000
	VFTA[49]       00000000
	VFTA[50]       00000000
	VFTA[51]       00000000
	VFTA[52]       00000000
	VFTA[53]       00000000
	VFTA[54]       00000000
	VFTA[55]       00000000
	VFTA[56]       00000000
	VFTA[57]       00000000
	VFTA[58]       00000000
	VFTA[59]       00000000
	VFTA[60]       00000000
	VFTA[61]       00000000
	VFTA[62]       00000000
	VFTA[63]       00000000
	VFTA[64]       00000000
	VFTA[65]       00000000
	VFTA[66]       00000000
	VFTA[67]       00000000
	VFTA[68]       00000000
	VFTA[69]       00000000
	VFTA[70]       00000000
	VFTA[71]       00000000
	VFTA[72]       00000000
	VFTA[73]       00000000
	VFTA[74]       00000000
	VFTA[75]       00000000
	VFTA[76]       00000000
	VFTA[77]       00000000
	VFTA[78]       00000000
	VFTA[79]       00000000
	VFTA[80]       00000000
	VFTA[81]       00000000
	VFTA[82]       00000000
	VFTA[83]       00000000
	VFTA[84]       00000000
	VFTA[85]       00000000
	VFTA[86]       00000000
	VFTA[87]       00000000
	VFTA[88]       00000000
	VFTA[89]       00000000
	VFTA[90]       00000000
	VFTA[91]       00000000
	VFTA[92]       00000000
	VFTA[93]       00000000
	VFTA[94]       00000000
	VFTA[95]       00000000
	VFTA[96]       00000000
	VFTA[97]       00000000
	VFTA[98]       00000000
	VFTA[99]       00000000
	VFTA[100]      00000000
	VFTA[101]      00000000
	VFTA[102]      00000000
	VFTA[103]      00000000
	VFTA[104]      00000000
	VFTA[105]      00000000
	VFTA[106]      00000000
	VFTA[107]      00000000
	VFTA[108]      00000000
	VFTA[109]      00000000
	VFTA[110]      00000000
	VFTA[111]      00000000
	VFTA[112]      00000000
	VFTA[113]      00000000
	VFTA[114]      00000000
	VFTA[115]      00000000
	VFTA[116]      00000000
	VFTA[117]      00000000
	VFTA[118]      00000000
	VFTA[119]      00000000
	VFTA[120]      00000000
	VFTA[121]      00000000
	VFTA[122]      00000000
	VFTA[123]      00000000
	VFTA[124]      00000000
	VFTA[125]      00000000
	VFTA[126]      00000000
	VFTA[127]      00000000
	WUC            00000000
	WUFC           00000000
	WUS            00000000
	MRQC           00000000
	MANC           00000100
	IPAV           00000000
	MANC2H         00000000
	RSSIM          00000000
	RSSIR          00000001
	WUPL           9ce201fa
	GCR            0e000000
	GSCL_1         00000000
	GSCL_2         00000000
	GSCL_3         00000000
	GSCL_4         00000000
	FACTPS         21041046
	FWSM           00000000
	RETA[0]        00000015
	RETA[1]        0000006b
	RETA[2]        00000004
	RETA[3]        000000e2
	RETA[4]        00000070
	RETA[5]        00000077
	RETA[6]        00000018
	RETA[7]        00000001
	RETA[8]        00000029
	RETA[9]        00000069
	RETA[10]       00000004
	RETA[11]       00000081
	RETA[12]       00000040
	RETA[13]       0000001e
	RETA[14]       00000093
	RETA[15]       000000c3
	RETA[16]       0000001b
	RETA[17]       0000002f
	RETA[18]       00000002
	RETA[19]       000000f4
	RETA[20]       000000bd
	RETA[21]       000000b6
	RETA[22]       000000af
	RETA[23]       00000029
	RETA[24]       00000003
	RETA[25]       0000001e
	RETA[26]       00000011
	RETA[27]       000000a5
	RETA[28]       0000008f
	RETA[29]       0000000b
	RETA[30]       00000059
	RETA[31]       00000006
	RETA[32]       00000008
	RETA[33]       000000d8
	RETA[34]       00000099
	RETA[35]       000000fb
	RETA[36]       0000003c
	RETA[37]       0000006c
	RETA[38]       00000011
	RETA[39]       00000027
	RETA[40]       00000029
	RETA[41]       00000097
	RETA[42]       00000055
	RETA[43]       000000a2
	RETA[44]       00000019
	RETA[45]       0000006e
	RETA[46]       00000011
	RETA[47]       00000060
	RETA[48]       000000ef
	RETA[49]       000000c1
	RETA[50]       00000033
	RETA[51]       000000a2
	RETA[52]       00000007
	RETA[53]       0000008a
	RETA[54]       0000006c
	RETA[55]       000000c2
	RETA[56]       00000029
	RETA[57]       0000002e
	RETA[58]       0000008b
	RETA[59]       00000063
	RETA[60]       00000035
	RETA[61]       00000015
	RETA[62]       00000091
	RETA[63]       000000ec
	RETA[64]       00000045
	RETA[65]       0000003b
	RETA[66]       0000001d
	RETA[67]       00000040
	RETA[68]       000000c5
	RETA[69]       00000082
	RETA[70]       000000b3
	RETA[71]       000000b6
	RETA[72]       0000000a
	RETA[73]       0000009b
	RETA[74]       000000d2
	RETA[75]       000000d2
	RETA[76]       0000004a
	RETA[77]       0000004e
	RETA[78]       00000010
	RETA[79]       000000e0
	RETA[80]       0000003a
	RETA[81]       000000ae
	RETA[82]       0000000d
	RETA[83]       00000070
	RETA[84]       0000001a
	RETA[85]       000000e7
	RETA[86]       000000c7
	RETA[87]       000000a5
	RETA[88]       0000006d
	RETA[89]       0000002f
	RETA[90]       00000061
	RETA[91]       00000026
	RETA[92]       0000000f
	RETA[93]       0000001f
	RETA[94]       00000019
	RETA[95]       000000ed
	RETA[96]       00000059
	RETA[97]       00000003
	RETA[98]       00000058
	RETA[99]       000000c9
	RETA[100]      0000006d
	RETA[101]      000000aa
	RETA[102]      0000000b
	RETA[103]      00000063
	RETA[104]      000000cd
	RETA[105]      0000001f
	RETA[106]      00000018
	RETA[107]      00000042
	RETA[108]      00000079
	RETA[109]      0000000f
	RETA[110]      0000005b
	RETA[111]      00000042
	RETA[112]      00000049
	RETA[113]      0000006e
	RETA[114]      00000008
	RETA[115]      00000076
	RETA[116]      0000002d
	RETA[117]      00000059
	RETA[118]      00000047
	RETA[119]      000000a6
	RETA[120]      00000090
	RETA[121]      00000002
	RETA[122]      000000cb
	RETA[123]      00000049
	RETA[124]      00000093
	RETA[125]      00000009
	RETA[126]      00000016
	RETA[127]      000000f2
	RSSRK[0]       00000000
	RSSRK[1]       00000000
	RSSRK[2]       00000000
	RSSRK[3]       00000000
	RSSRK[4]       00000000
	RSSRK[5]       00000000
	RSSRK[6]       00000000
	RSSRK[7]       00000000
	RSSRK[8]       00000000
	RSSRK[9]       00000000
	RSSRK[10]      00000000
	RSSRK[11]      00000000
	RSSRK[12]      00000000
	RSSRK[13]      00000000
	RSSRK[14]      00000000
	RSSRK[15]      00000000
	RSSRK[16]      00000000
	RSSRK[17]      00000000
	RSSRK[18]      00000000
	RSSRK[19]      00000000
	RSSRK[20]      00000000
	RSSRK[21]      00000000
	RSSRK[22]      00000000
	RSSRK[23]      00000000
	RSSRK[24]      00000000
	RSSRK[25]      00000000
	RSSRK[26]      00000000
	RSSRK[27]      00000000
	RSSRK[28]      00000000
	RSSRK[29]      00000000
	RSSRK[30]      00000000
	RSSRK[31]      00000000
	RSSRK[32]      00000000
	RSSRK[33]      00000000
	RSSRK[34]      00000000
	RSSRK[35]      00000000
	RSSRK[36]      00000000
	RSSRK[37]      00000000
	RSSRK[38]      00000000
	RSSRK[39]      00000000
	FFLT[0]        00000000
	FFLT[1]        fffc0000
	FFLT[2]        00000000
	FFLT[3]        00000000
	FFLT[4]        00000000
	FFLT[5]        00000000
	FFLT[6]        00000000
	FFLT[7]        00000000
	FFLT[8]        00000080
	FFLT[9]        00000000
	FFLT[10]       00000002
	FFLT[11]       00000000
	HICR           00000000
	FFMT[0]        00000006
	FFMT[1]        00000006
	FFMT[2]        00000009
	FFMT[3]        00000009
	FFMT[4]        0000000e
	FFMT[5]        0000000e
	FFMT[6]        0000000d
	FFMT[7]        0000000d
	FFMT[8]        0000000b
	FFMT[9]        0000000b
	FFMT[10]       0000000d
	FFMT[11]       0000000d
	FFMT[12]       00000004
	FFMT[13]       00000004
	FFMT[14]       00000000
	FFMT[15]       00000000
	FFMT[16]       00000000
	FFMT[17]       00000000
	FFMT[18]       00000009
	FFMT[19]       00000009
	FFMT[20]       00000001
	FFMT[21]       00000001
	FFMT[22]       00000006
	FFMT[23]       00000006
	FFMT[24]       00000003
	FFMT[25]       00000003
	FFMT[26]       00000004
	FFMT[27]       00000004
	FFMT[28]       00000005
	FFMT[29]       00000005
	FFMT[30]       0000000c
	FFMT[31]       0000000c
	FFMT[32]       00000000
	FFMT[33]       00000000
	FFMT[34]       00000008
	FFMT[35]       00000008
	FFMT[36]       00000002
	FFMT[37]       00000002
	FFMT[38]       0000000e
	FFMT[39]       0000000e
	FFMT[40]       00000003
	FFMT[41]       00000003
	FFMT[42]       0000000b
	FFMT[43]       0000000b
	FFMT[44]       00000001
	FFMT[45]       00000001
	FFMT[46]       00000005
	FFMT[47]       00000005
	FFMT[48]       00000003
	FFMT[49]       00000003
	FFMT[50]       00000001
	FFMT[51]       00000001
	FFMT[52]       0000000a
	FFMT[53]       0000000a
	FFMT[54]       00000003
	FFMT[55]       00000003
	FFMT[56]       00000001
	FFMT[57]       00000001
	FFMT[58]       0000000d
	FFMT[59]       0000000d
	FFMT[60]       00000008
	FFMT[61]       00000008
	FFMT[62]       00000002
	FFMT[63]       00000002
	FFMT[64]       00000002
	FFMT[65]       00000002
	FFMT[66]       00000007
	FFMT[67]       00000007
	FFMT[68]       00000004
	FFMT[69]       00000004
	FFMT[70]       00000006
	FFMT[71]       00000006
	FFMT[72]       0000000e
	FFMT[73]       0000000e
	FFMT[74]       0000000e
	FFMT[75]       0000000e
	FFMT[76]       0000000f
	FFMT[77]       0000000f
	FFMT[78]       00000002
	FFMT[79]       00000002
	FFMT[80]       00000000
	FFMT[81]       00000000
	FFMT[82]       0000000b
	FFMT[83]       0000000b
	FFMT[84]       00000009
	FFMT[85]       00000009
	FFMT[86]       00000009
	FFMT[87]       00000009
	FFMT[88]       0000000a
	FFMT[89]       0000000a
	FFMT[90]       0000000d
	FFMT[91]       0000000d
	FFMT[92]       00000005
	FFMT[93]       00000005
	FFMT[94]       00000006
	FFMT[95]       00000006
	FFMT[96]       00000003
	FFMT[97]       00000003
	FFMT[98]       0000000d
	FFMT[99]       0000000d
	FFMT[100]      00000009
	FFMT[101]      00000009
	FFMT[102]      0000000d
	FFMT[103]      0000000d
	FFMT[104]      00000001
	FFMT[105]      00000001
	FFMT[106]      0000000e
	FFMT[107]      0000000e
	FFMT[108]      0000000b
	FFMT[109]      0000000b
	FFMT[110]      00000000
	FFMT[111]      00000000
	FFMT[112]      00000001
	FFMT[113]      00000001
	FFMT[114]      00000000
	FFMT[115]      00000000
	FFMT[116]      00000008
	FFMT[117]      00000008
	FFMT[118]      0000000a
	FFMT[119]      0000000a
	FFMT[120]      00000001
	FFMT[121]      00000001
	FFMT[122]      00000006
	FFMT[123]      00000006
	FFMT[124]      00000002
	FFMT[125]      00000002
	FFMT[126]      0000000f
	FFMT[127]      0000000f
	FFVT[0]        a6d21076
	FFVT[1]        a6d21076
	FFVT[2]        14fddf8e
	FFVT[3]        14fddf8e
	FFVT[4]        af998eff
	FFVT[5]        af998eff
	FFVT[6]        72ee35eb
	FFVT[7]        72ee35eb
	FFVT[8]        4595b5d0
	FFVT[9]        4595b5d0
	FFVT[10]       9ce2d272
	FFVT[11]       9ce2d272
	FFVT[12]       65ccdb20
	FFVT[13]       65ccdb20
	FFVT[14]       7a6d632f
	FFVT[15]       7a6d632f
	FFVT[16]       c9fd53bd
	FFVT[17]       c9fd53bd
	FFVT[18]       138adc2d
	FFVT[19]       138adc2d
	FFVT[20]       5a7c8912
	FFVT[21]       5a7c8912
	FFVT[22]       080da768
	FFVT[23]       080da768
	FFVT[24]       e00a93c6
	FFVT[25]       e00a93c6
	FFVT[26]       3d05bbe0
	FFVT[27]       3d05bbe0
	FFVT[28]       8dc0ad89
	FFVT[29]       8dc0ad89
	FFVT[30]       a0267e00
	FFVT[31]       a0267e00
	FFVT[32]       45f0b43f
	FFVT[33]       45f0b43f
	FFVT[34]       62120156
	FFVT[35]       62120156
	FFVT[36]       a6213b97
	FFVT[37]       a6213b97
	FFVT[38]       ea15b0b6
	FFVT[39]       ea15b0b6
	FFVT[40]       a4176212
	FFVT[41]       a4176212
	FFVT[42]       ae88d158
	FFVT[43]       ae88d158
	FFVT[44]       541de595
	FFVT[45]       541de595
	FFVT[46]       15d56ace
	FFVT[47]       15d56ace
	FFVT[48]       45824374
	FFVT[49]       45824374
	FFVT[50]       2ba17885
	FFVT[51]       2ba17885
	FFVT[52]       b63201ea
	FFVT[53]       b63201ea
	FFVT[54]       b1ff88da
	FFVT[55]       b1ff88da
	FFVT[56]       f24edcea
	FFVT[57]       f24edcea
	FFVT[58]       b068c2e7
	FFVT[59]       b068c2e7
	FFVT[60]       58a6584c
	FFVT[61]       58a6584c
	FFVT[62]       ca6624d0
	FFVT[63]       ca6624d0
	FFVT[64]       d66319d3
	FFVT[65]       d66319d3
	FFVT[66]       437f892f
	FFVT[67]       437f892f
	FFVT[68]       6298ced1
	FFVT[69]       6298ced1
	FFVT[70]       d8f20b8e
	FFVT[71]       d8f20b8e
	FFVT[72]       00a8562c
	FFVT[73]       00a8562c
	FFVT[74]       536016e4
	FFVT[75]       536016e4
	FFVT[76]       81723c11
	FFVT[77]       81723c11
	FFVT[78]       6baf812a
	FFVT[79]       6baf812a
	FFVT[80]       579813dc
	FFVT[81]       579813dc
	FFVT[82]       f1099664
	FFVT[83]       f1099664
	FFVT[84]       484724af
	FFVT[85]       484724af
	FFVT[86]       9473f82f
	FFVT[87]       9473f82f
	FFVT[88]       2086be8f
	FFVT[89]       2086be8f
	FFVT[90]       505baa7a
	FFVT[91]       505baa7a
	FFVT[92]       e106d4d4
	FFVT[93]       e106d4d4
	FFVT[94]       035cf124
	FFVT[95]       035cf124
	FFVT[96]       80e38b56
	FFVT[97]       80e38b56
	FFVT[98]       03ef854a
	FFVT[99]       03ef854a
	FFVT[100]      ece8d8c9
	FFVT[101]      ece8d8c9
	FFVT[102]      a1d4c1a9
	FFVT[103]      a1d4c1a9
	FFVT[104]      e800f0b6
	FFVT[105]      e800f0b6
	FFVT[106]      7019d873
	FFVT[107]      7019d873
	FFVT[108]      a45554ff
	FFVT[109]      a45554ff
	FFVT[110]      29f98242
	FFVT[111]      29f98242
	FFVT[112]      b517937f
	FFVT[113]      b517937f
	FFVT[114]      a4d35dd5
	FFVT[115]      a4d35dd5
	FFVT[116]      52328c1b
	FFVT[117]      52328c1b
	FFVT[118]      09f59e76
	FFVT[119]      09f59e76
	FFVT[120]      1968c620
	FFVT[121]      1968c620
	FFVT[122]      cba89964
	FFVT[123]      cba89964
	FFVT[124]      42dc73e1
	FFVT[125]      42dc73e1
	FFVT[126]      06efaa25
	FFVT[127]      06efaa25


0d:00.0 (8086:108c)
Intel Corporation 82573E Gigabit Ethernet Controller (Copper)
	Name           Value
	~~~~           ~~~~~
	CTRL           18140248
	STATUS         80080743
	EECD           02011b18
	EERD           ffff0026
	CTRL_EXT       28780000
	FLA            00000608
	MDIC           18316d4c
	FCAL           00c28001
	FCAH           00000100
	FCT            00008808
	VET            00008100
	ITR            000003d0
	ICS            00000000
	IMS            0000009d
	IMC            0000009d
	IAM            ffffffff
	RCTL           04048002
	FCTTV          00000680
	TCTL           3103f0fa
	TIPG           00602008
	AIT            00000000
	LEDCTL         00078406
	EXTCNF_CTRL    10000008
	EXTCNF_SIZE    00000000
	PBA            000c0014
	PBS            00000020
	EEMNGCTL       800000f7
	EEARBC         00080100
	FLASHT         00000002
	EEWR           00000002
	FLSWCTL        c0000000
	FLSWDATA       00000000
	FLSWCNT        00000000
	FLOP           00012000
	ERT            00000000
	FCRTL          800047f8
	FCRTH          00004800
	PSRCTL         00040402
	RDBAL          06d9e000
	RDBAH          00000002
	RDLEN          00001000
	RDH            000000fc
	RDT            000000fa
	RDTR           00000000
	RXDCTL         00010000
	RADV           00000008
	RDBAL1         00000000
	RDBAH1         01200200
	RDLEN1         00000000
	RDH1           00000000
	RDT1           00000000
	RSRPD          00000000
	RAID           00000000
	CPUVEC         00000000
	TDFH           00000cd0
	TDFT           00000cd0
	TDFHS          00000cd0
	TDFTS          00000cd0
	TDFPC          00000000
	TDBAL          f63f5000
	TDBAH          00000001
	TDLEN          00001000
	TDH            00000065
	TDT            00000065
	TIDV           00000008
	TXDCTL         01410000
	TADV           00000020
	TARC0          00000403
	TDBAL1         00800000
	TDBAH1         10000500
	TDLEN1         00000000
	TDH1           00000000
	TDT1           00000000
	TXDCTL1        00400000
	TARC1          00000403
	ICRXPTC        00000000
	ICRXATC        00000000
	ICTXPTC        00000000
	ICTXATC        00000000
	ICTXQEC        00000000
	ICTXQMTC       00000000
	ICRXDMTC       00000000
	ICRXOC         00000000
	RXCSUM         00000300
	RFCTL          00000000
	MTA[0]         00000000
	MTA[1]         00000000
	MTA[2]         00000000
	MTA[3]         00000000
	MTA[4]         00000000
	MTA[5]         00000000
	MTA[6]         00000000
	MTA[7]         00000000
	MTA[8]         00000000
	MTA[9]         00000000
	MTA[10]        00000000
	MTA[11]        00000000
	MTA[12]        00000000
	MTA[13]        00000000
	MTA[14]        00000000
	MTA[15]        00000000
	MTA[16]        00000000
	MTA[17]        00000000
	MTA[18]        00000000
	MTA[19]        00000000
	MTA[20]        00000000
	MTA[21]        00000000
	MTA[22]        00000000
	MTA[23]        00000000
	MTA[24]        00000000
	MTA[25]        00000000
	MTA[26]        00000000
	MTA[27]        00000000
	MTA[28]        00000000
	MTA[29]        00000000
	MTA[30]        00000000
	MTA[31]        00000000
	MTA[32]        00000000
	MTA[33]        00000000
	MTA[34]        00000000
	MTA[35]        00000000
	MTA[36]        00000000
	MTA[37]        00000000
	MTA[38]        00000000
	MTA[39]        00000000
	MTA[40]        00000000
	MTA[41]        00000000
	MTA[42]        00000000
	MTA[43]        00000000
	MTA[44]        00000000
	MTA[45]        00000000
	MTA[46]        00000000
	MTA[47]        00000000
	MTA[48]        00000000
	MTA[49]        00000000
	MTA[50]        00000000
	MTA[51]        00000000
	MTA[52]        00000000
	MTA[53]        00000000
	MTA[54]        00000000
	MTA[55]        00000000
	MTA[56]        00000000
	MTA[57]        00000000
	MTA[58]        00000000
	MTA[59]        00000000
	MTA[60]        00000000
	MTA[61]        00000000
	MTA[62]        00000000
	MTA[63]        00000000
	MTA[64]        00000000
	MTA[65]        00000000
	MTA[66]        00000000
	MTA[67]        00000000
	MTA[68]        00000000
	MTA[69]        00000000
	MTA[70]        00000000
	MTA[71]        00000000
	MTA[72]        00000000
	MTA[73]        00000000
	MTA[74]        00000000
	MTA[75]        00000000
	MTA[76]        00000000
	MTA[77]        00000000
	MTA[78]        00000000
	MTA[79]        00000000
	MTA[80]        00000000
	MTA[81]        00000000
	MTA[82]        00000000
	MTA[83]        00000000
	MTA[84]        00000000
	MTA[85]        00000000
	MTA[86]        00000000
	MTA[87]        00000000
	MTA[88]        00000000
	MTA[89]        00000000
	MTA[90]        00000000
	MTA[91]        00000000
	MTA[92]        00000000
	MTA[93]        00000000
	MTA[94]        00000000
	MTA[95]        00000000
	MTA[96]        00000000
	MTA[97]        00000000
	MTA[98]        00000000
	MTA[99]        00000000
	MTA[100]       00000000
	MTA[101]       00000000
	MTA[102]       00000000
	MTA[103]       00000000
	MTA[104]       00000000
	MTA[105]       00000000
	MTA[106]       00000000
	MTA[107]       00000000
	MTA[108]       00000000
	MTA[109]       00000000
	MTA[110]       00000000
	MTA[111]       00000000
	MTA[112]       00000000
	MTA[113]       00000000
	MTA[114]       00000000
	MTA[115]       00000000
	MTA[116]       00000000
	MTA[117]       00000000
	MTA[118]       00000000
	MTA[119]       00000000
	MTA[120]       00000000
	MTA[121]       00000000
	MTA[122]       00000000
	MTA[123]       00000000
	MTA[124]       00000000
	MTA[125]       00000000
	MTA[126]       00000000
	MTA[127]       00000000
	RAL[0]         96483000
	RAH[0]         8000e2e1
	RAL[1]         005e0001
	RAH[1]         80000100
	RAL[2]         00000000
	RAH[2]         00000000
	RAL[3]         00000000
	RAH[3]         00000000
	RAL[4]         00000000
	RAH[4]         00000000
	RAL[5]         00000000
	RAH[5]         00000000
	RAL[6]         00000000
	RAH[6]         00000000
	RAL[7]         00000000
	RAH[7]         00000000
	RAL[8]         00000000
	RAH[8]         00000000
	RAL[9]         00000000
	RAH[9]         00000000
	RAL[10]        00000000
	RAH[10]        00000000
	RAL[11]        00000000
	RAH[11]        00000000
	RAL[12]        00000000
	RAH[12]        00000000
	RAL[13]        00000000
	RAH[13]        00000000
	RAL[14]        00000000
	RAH[14]        00000000
	RAL[15]        96483000
	RAH[15]        0000e2e1
	VFTA[0]        00000000
	VFTA[1]        00000000
	VFTA[2]        00000000
	VFTA[3]        00000000
	VFTA[4]        00000000
	VFTA[5]        00000000
	VFTA[6]        00000000
	VFTA[7]        00000000
	VFTA[8]        00000000
	VFTA[9]        00000000
	VFTA[10]       00000000
	VFTA[11]       00000000
	VFTA[12]       00000000
	VFTA[13]       00000000
	VFTA[14]       00000000
	VFTA[15]       00000000
	VFTA[16]       00000000
	VFTA[17]       00000000
	VFTA[18]       00000000
	VFTA[19]       00000000
	VFTA[20]       00000000
	VFTA[21]       00000000
	VFTA[22]       00000000
	VFTA[23]       00000000
	VFTA[24]       00000000
	VFTA[25]       00000000
	VFTA[26]       00000000
	VFTA[27]       00000000
	VFTA[28]       00000000
	VFTA[29]       00000000
	VFTA[30]       00000000
	VFTA[31]       00000000
	VFTA[32]       00000000
	VFTA[33]       00000000
	VFTA[34]       00000000
	VFTA[35]       00000000
	VFTA[36]       00000000
	VFTA[37]       00000000
	VFTA[38]       00000000
	VFTA[39]       00000000
	VFTA[40]       00000000
	VFTA[41]       00000000
	VFTA[42]       00000000
	VFTA[43]       00000000
	VFTA[44]       00000000
	VFTA[45]       00000000
	VFTA[46]       00000000
	VFTA[47]       00000000
	VFTA[48]       00000000
	VFTA[49]       00000000
	VFTA[50]       00000000
	VFTA[51]       00000000
	VFTA[52]       00000000
	VFTA[53]       00000000
	VFTA[54]       00000000
	VFTA[55]       00000000
	VFTA[56]       00000000
	VFTA[57]       00000000
	VFTA[58]       00000000
	VFTA[59]       00000000
	VFTA[60]       00000000
	VFTA[61]       00000000
	VFTA[62]       00000000
	VFTA[63]       00000000
	VFTA[64]       00000000
	VFTA[65]       00000000
	VFTA[66]       00000000
	VFTA[67]       00000000
	VFTA[68]       00000000
	VFTA[69]       00000000
	VFTA[70]       00000000
	VFTA[71]       00000000
	VFTA[72]       00000000
	VFTA[73]       00000000
	VFTA[74]       00000000
	VFTA[75]       00000000
	VFTA[76]       00000000
	VFTA[77]       00000000
	VFTA[78]       00000000
	VFTA[79]       00000000
	VFTA[80]       00000000
	VFTA[81]       00000000
	VFTA[82]       00000000
	VFTA[83]       00000000
	VFTA[84]       00000000
	VFTA[85]       00000000
	VFTA[86]       00000000
	VFTA[87]       00000000
	VFTA[88]       00000000
	VFTA[89]       00000000
	VFTA[90]       00000000
	VFTA[91]       00000000
	VFTA[92]       00000000
	VFTA[93]       00000000
	VFTA[94]       00000000
	VFTA[95]       00000000
	VFTA[96]       00000000
	VFTA[97]       00000000
	VFTA[98]       00000000
	VFTA[99]       00000000
	VFTA[100]      00000000
	VFTA[101]      00000000
	VFTA[102]      00000000
	VFTA[103]      00000000
	VFTA[104]      00000000
	VFTA[105]      00000000
	VFTA[106]      00000000
	VFTA[107]      00000000
	VFTA[108]      00000000
	VFTA[109]      00000000
	VFTA[110]      00000000
	VFTA[111]      00000000
	VFTA[112]      00000000
	VFTA[113]      00000000
	VFTA[114]      00000000
	VFTA[115]      00000000
	VFTA[116]      00000000
	VFTA[117]      00000000
	VFTA[118]      00000000
	VFTA[119]      00000000
	VFTA[120]      00000000
	VFTA[121]      00000000
	VFTA[122]      00000000
	VFTA[123]      00000000
	VFTA[124]      00000000
	VFTA[125]      00000000
	VFTA[126]      00000000
	VFTA[127]      00000000
	WUC            00000000
	WUFC           00000000
	WUS            00000000
	MRQC           00000000
	MANC           0022a300
	IPAV           00000000
	MANC2H         00000380
	RSSIM          00000000
	RSSIR          00000000
	WUPL           28167f49
	GCR            0e000000
	GSCL_1         00000000
	GSCL_2         00000000
	GSCL_3         00000000
	GSCL_4         00000000
	FACTPS         01041046
	FWSM           00018044
	RETA[0]        0000008c
	RETA[1]        0000001f
	RETA[2]        00000082
	RETA[3]        00000086
	RETA[4]        0000009f
	RETA[5]        00000066
	RETA[6]        0000005a
	RETA[7]        0000004b
	RETA[8]        0000001e
	RETA[9]        000000af
	RETA[10]       000000dc
	RETA[11]       000000e5
	RETA[12]       0000002d
	RETA[13]       000000aa
	RETA[14]       0000009b
	RETA[15]       0000001c
	RETA[16]       00000053
	RETA[17]       000000e6
	RETA[18]       00000096
	RETA[19]       00000084
	RETA[20]       000000b1
	RETA[21]       0000006b
	RETA[22]       000000b7
	RETA[23]       000000de
	RETA[24]       00000010
	RETA[25]       000000d4
	RETA[26]       000000ef
	RETA[27]       00000034
	RETA[28]       00000038
	RETA[29]       0000000e
	RETA[30]       00000012
	RETA[31]       0000001d
	RETA[32]       00000001
	RETA[33]       0000004b
	RETA[34]       000000e3
	RETA[35]       0000001e
	RETA[36]       0000001b
	RETA[37]       0000009b
	RETA[38]       0000008e
	RETA[39]       00000068
	RETA[40]       00000015
	RETA[41]       000000e2
	RETA[42]       000000c7
	RETA[43]       000000c6
	RETA[44]       00000034
	RETA[45]       0000007a
	RETA[46]       000000b6
	RETA[47]       00000014
	RETA[48]       000000aa
	RETA[49]       0000006f
	RETA[50]       000000fa
	RETA[51]       00000085
	RETA[52]       00000032
	RETA[53]       0000004e
	RETA[54]       0000003f
	RETA[55]       0000004c
	RETA[56]       00000099
	RETA[57]       0000003d
	RETA[58]       000000f2
	RETA[59]       000000ae
	RETA[60]       00000011
	RETA[61]       0000006f
	RETA[62]       000000b7
	RETA[63]       0000000b
	RETA[64]       0000009b
	RETA[65]       00000007
	RETA[66]       0000000a
	RETA[67]       0000009a
	RETA[68]       000000a3
	RETA[69]       00000020
	RETA[70]       000000f3
	RETA[71]       00000084
	RETA[72]       0000004d
	RETA[73]       00000048
	RETA[74]       0000008b
	RETA[75]       00000021
	RETA[76]       000000c7
	RETA[77]       00000053
	RETA[78]       000000a3
	RETA[79]       0000008b
	RETA[80]       000000d4
	RETA[81]       0000004a
	RETA[82]       000000c2
	RETA[83]       000000c0
	RETA[84]       0000003b
	RETA[85]       00000069
	RETA[86]       00000082
	RETA[87]       0000005e
	RETA[88]       00000098
	RETA[89]       0000007a
	RETA[90]       00000017
	RETA[91]       00000084
	RETA[92]       000000ab
	RETA[93]       0000004a
	RETA[94]       000000c7
	RETA[95]       00000014
	RETA[96]       0000001d
	RETA[97]       0000006a
	RETA[98]       00000077
	RETA[99]       00000014
	RETA[100]      000000b9
	RETA[101]      0000000a
	RETA[102]      000000c2
	RETA[103]      0000003d
	RETA[104]      00000055
	RETA[105]      000000aa
	RETA[106]      000000b4
	RETA[107]      00000004
	RETA[108]      00000047
	RETA[109]      00000053
	RETA[110]      000000f7
	RETA[111]      00000016
	RETA[112]      0000008b
	RETA[113]      000000d3
	RETA[114]      000000b2
	RETA[115]      00000074
	RETA[116]      0000003b
	RETA[117]      0000002b
	RETA[118]      0000009d
	RETA[119]      00000016
	RETA[120]      0000002b
	RETA[121]      000000ce
	RETA[122]      0000008e
	RETA[123]      00000044
	RETA[124]      00000027
	RETA[125]      0000004b
	RETA[126]      000000c2
	RETA[127]      00000086
	RSSRK[0]       00000000
	RSSRK[1]       00000000
	RSSRK[2]       00000000
	RSSRK[3]       00000000
	RSSRK[4]       00000000
	RSSRK[5]       00000000
	RSSRK[6]       00000000
	RSSRK[7]       00000000
	RSSRK[8]       00000000
	RSSRK[9]       00000000
	RSSRK[10]      00000000
	RSSRK[11]      00000000
	RSSRK[12]      00000000
	RSSRK[13]      00000000
	RSSRK[14]      00000000
	RSSRK[15]      00000000
	RSSRK[16]      00000000
	RSSRK[17]      00000000
	RSSRK[18]      00000000
	RSSRK[19]      00000000
	RSSRK[20]      00000000
	RSSRK[21]      00000000
	RSSRK[22]      00000000
	RSSRK[23]      00000000
	RSSRK[24]      00000000
	RSSRK[25]      00000000
	RSSRK[26]      00000000
	RSSRK[27]      00000000
	RSSRK[28]      00000000
	RSSRK[29]      00000000
	RSSRK[30]      00000000
	RSSRK[31]      00000000
	RSSRK[32]      00000000
	RSSRK[33]      00000000
	RSSRK[34]      00000000
	RSSRK[35]      00000000
	RSSRK[36]      00000000
	RSSRK[37]      00000000
	RSSRK[38]      00000000
	RSSRK[39]      00000000
	FFLT[0]        00000000
	FFLT[1]        fffc0000
	FFLT[2]        00000000
	FFLT[3]        00000000
	FFLT[4]        00000000
	FFLT[5]        00000000
	FFLT[6]        00000000
	FFLT[7]        00000000
	FFLT[8]        00000000
	FFLT[9]        00000000
	FFLT[10]       00000000
	FFLT[11]       00000000
	HICR           00000109
	FFMT[0]        0000000c
	FFMT[1]        0000000c
	FFMT[2]        0000000d
	FFMT[3]        0000000d
	FFMT[4]        0000000c
	FFMT[5]        0000000c
	FFMT[6]        0000000f
	FFMT[7]        0000000f
	FFMT[8]        00000001
	FFMT[9]        00000001
	FFMT[10]       00000006
	FFMT[11]       00000006
	FFMT[12]       00000004
	FFMT[13]       00000004
	FFMT[14]       0000000c
	FFMT[15]       0000000c
	FFMT[16]       0000000e
	FFMT[17]       0000000e
	FFMT[18]       00000001
	FFMT[19]       00000001
	FFMT[20]       00000001
	FFMT[21]       00000001
	FFMT[22]       00000001
	FFMT[23]       00000001
	FFMT[24]       00000000
	FFMT[25]       00000000
	FFMT[26]       00000001
	FFMT[27]       00000001
	FFMT[28]       00000002
	FFMT[29]       00000002
	FFMT[30]       0000000f
	FFMT[31]       0000000f
	FFMT[32]       00000001
	FFMT[33]       00000001
	FFMT[34]       00000003
	FFMT[35]       00000003
	FFMT[36]       0000000c
	FFMT[37]       0000000c
	FFMT[38]       00000002
	FFMT[39]       00000002
	FFMT[40]       00000008
	FFMT[41]       00000008
	FFMT[42]       0000000f
	FFMT[43]       0000000f
	FFMT[44]       00000008
	FFMT[45]       00000008
	FFMT[46]       00000004
	FFMT[47]       00000004
	FFMT[48]       00000006
	FFMT[49]       00000006
	FFMT[50]       00000007
	FFMT[51]       00000007
	FFMT[52]       00000002
	FFMT[53]       00000002
	FFMT[54]       0000000b
	FFMT[55]       0000000b
	FFMT[56]       00000008
	FFMT[57]       00000008
	FFMT[58]       00000003
	FFMT[59]       00000003
	FFMT[60]       00000004
	FFMT[61]       00000004
	FFMT[62]       00000000
	FFMT[63]       00000000
	FFMT[64]       00000001
	FFMT[65]       00000001
	FFMT[66]       0000000e
	FFMT[67]       0000000e
	FFMT[68]       00000007
	FFMT[69]       00000007
	FFMT[70]       0000000b
	FFMT[71]       0000000b
	FFMT[72]       00000006
	FFMT[73]       00000006
	FFMT[74]       00000009
	FFMT[75]       00000009
	FFMT[76]       00000009
	FFMT[77]       00000009
	FFMT[78]       00000009
	FFMT[79]       00000009
	FFMT[80]       0000000f
	FFMT[81]       0000000f
	FFMT[82]       00000009
	FFMT[83]       00000009
	FFMT[84]       0000000a
	FFMT[85]       0000000a
	FFMT[86]       00000000
	FFMT[87]       00000000
	FFMT[88]       0000000b
	FFMT[89]       0000000b
	FFMT[90]       00000003
	FFMT[91]       00000003
	FFMT[92]       00000001
	FFMT[93]       00000001
	FFMT[94]       00000004
	FFMT[95]       00000004
	FFMT[96]       0000000b
	FFMT[97]       0000000b
	FFMT[98]       0000000c
	FFMT[99]       0000000c
	FFMT[100]      0000000a
	FFMT[101]      0000000a
	FFMT[102]      00000009
	FFMT[103]      00000009
	FFMT[104]      00000000
	FFMT[105]      00000000
	FFMT[106]      00000003
	FFMT[107]      00000003
	FFMT[108]      00000006
	FFMT[109]      00000006
	FFMT[110]      00000008
	FFMT[111]      00000008
	FFMT[112]      0000000e
	FFMT[113]      0000000e
	FFMT[114]      00000007
	FFMT[115]      00000007
	FFMT[116]      0000000c
	FFMT[117]      0000000c
	FFMT[118]      00000007
	FFMT[119]      00000007
	FFMT[120]      00000009
	FFMT[121]      00000009
	FFMT[122]      00000001
	FFMT[123]      00000001
	FFMT[124]      00000001
	FFMT[125]      00000001
	FFMT[126]      0000000f
	FFMT[127]      0000000f
	FFVT[0]        69386efe
	FFVT[1]        69386efe
	FFVT[2]        47dac1bd
	FFVT[3]        47dac1bd
	FFVT[4]        0af977e3
	FFVT[5]        0af977e3
	FFVT[6]        0bf35fcd
	FFVT[7]        0bf35fcd
	FFVT[8]        396325cb
	FFVT[9]        396325cb
	FFVT[10]       45fb2966
	FFVT[11]       45fb2966
	FFVT[12]       85fe3e31
	FFVT[13]       85fe3e31
	FFVT[14]       e6b90940
	FFVT[15]       e6b90940
	FFVT[16]       fcf5c382
	FFVT[17]       fcf5c382
	FFVT[18]       68b90289
	FFVT[19]       68b90289
	FFVT[20]       0fada5ed
	FFVT[21]       0fada5ed
	FFVT[22]       67f87890
	FFVT[23]       67f87890
	FFVT[24]       2dd69d55
	FFVT[25]       2dd69d55
	FFVT[26]       0f78a7b0
	FFVT[27]       0f78a7b0
	FFVT[28]       138d13f7
	FFVT[29]       138d13f7
	FFVT[30]       e302400a
	FFVT[31]       e302400a
	FFVT[32]       bc8ebaf7
	FFVT[33]       bc8ebaf7
	FFVT[34]       96fe79fb
	FFVT[35]       96fe79fb
	FFVT[36]       df5aa33b
	FFVT[37]       df5aa33b
	FFVT[38]       91212c9e
	FFVT[39]       91212c9e
	FFVT[40]       71c517b4
	FFVT[41]       71c517b4
	FFVT[42]       0bb6697f
	FFVT[43]       0bb6697f
	FFVT[44]       63018c23
	FFVT[45]       63018c23
	FFVT[46]       48a35d54
	FFVT[47]       48a35d54
	FFVT[48]       95f4d375
	FFVT[49]       95f4d375
	FFVT[50]       4699c679
	FFVT[51]       4699c679
	FFVT[52]       06e7adde
	FFVT[53]       06e7adde
	FFVT[54]       e31f1b6d
	FFVT[55]       e31f1b6d
	FFVT[56]       888919d6
	FFVT[57]       888919d6
	FFVT[58]       4751a142
	FFVT[59]       4751a142
	FFVT[60]       676fef06
	FFVT[61]       676fef06
	FFVT[62]       792d0e82
	FFVT[63]       792d0e82
	FFVT[64]       1066713d
	FFVT[65]       1066713d
	FFVT[66]       8f55fa4d
	FFVT[67]       8f55fa4d
	FFVT[68]       5fe46f1a
	FFVT[69]       5fe46f1a
	FFVT[70]       cacbc51e
	FFVT[71]       cacbc51e
	FFVT[72]       04470301
	FFVT[73]       04470301
	FFVT[74]       6b3dfea9
	FFVT[75]       6b3dfea9
	FFVT[76]       bd00be00
	FFVT[77]       bd00be00
	FFVT[78]       7079cb0c
	FFVT[79]       7079cb0c
	FFVT[80]       e7180acc
	FFVT[81]       e7180acc
	FFVT[82]       25755bec
	FFVT[83]       25755bec
	FFVT[84]       bcdd8914
	FFVT[85]       bcdd8914
	FFVT[86]       9ed3128d
	FFVT[87]       9ed3128d
	FFVT[88]       dc48587b
	FFVT[89]       dc48587b
	FFVT[90]       e9755ebf
	FFVT[91]       e9755ebf
	FFVT[92]       9ff23883
	FFVT[93]       9ff23883
	FFVT[94]       52d8233d
	FFVT[95]       52d8233d
	FFVT[96]       cdcf21c0
	FFVT[97]       cdcf21c0
	FFVT[98]       9069a69f
	FFVT[99]       9069a69f
	FFVT[100]      b52c57f5
	FFVT[101]      b52c57f5
	FFVT[102]      42977681
	FFVT[103]      42977681
	FFVT[104]      ab8b671a
	FFVT[105]      ab8b671a
	FFVT[106]      4edc0c8b
	FFVT[107]      4edc0c8b
	FFVT[108]      f41c47f0
	FFVT[109]      f41c47f0
	FFVT[110]      ab4edb12
	FFVT[111]      ab4edb12
	FFVT[112]      c096a36f
	FFVT[113]      c096a36f
	FFVT[114]      ed46c26a
	FFVT[115]      ed46c26a
	FFVT[116]      aca39e0b
	FFVT[117]      aca39e0b
	FFVT[118]      e01ed8b5
	FFVT[119]      e01ed8b5
	FFVT[120]      604c1ef5
	FFVT[121]      604c1ef5
	FFVT[122]      0dbbfeae
	FFVT[123]      0dbbfeae
	FFVT[124]      9478dbb7
	FFVT[125]      9478dbb7
	FFVT[126]      f95cfa23
	FFVT[127]      f95cfa23



[-- Attachment #8: Type: text/plain, Size: 80 bytes --]

------------------------------------------------------------------------------


[-- Attachment #9: Type: text/plain, Size: 257 bytes --]

_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel&#174; Ethernet, visit http://communities.intel.com/community/wired

^ permalink raw reply

* Re: loosing IPMI-card by loading netconsole
From: Tejun Heo @ 2010-05-15  9:10 UTC (permalink / raw)
  To: Carsten Aulbert
  Cc: e1000-devel, netdev@vger.kernel.org, Allan, Bruce W,
	Brandeburg, Jesse, Henning Fehrmann, Ronciak, John,
	Kirsher, Jeffrey T, Matt Mackall
In-Reply-To: <201005151026.20356.carsten.aulbert@aei.mpg.de>

On 05/15/2010 10:26 AM, Carsten Aulbert wrote:
> e.g. how can I re-enable the interface once I issued
> 
> echo 1 > /sys/devices/pci0000:00/0000:00:1c.4/0000:0d:00.0/remove

echo 1 > /sys/devices/pci0000:00/0000:00:1c.4/rescan

-- 
tejun

------------------------------------------------------------------------------

_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel&#174; Ethernet, visit http://communities.intel.com/community/wired

^ permalink raw reply

* Re: [net-next-2.6 V8 PATCH 1/2] Add netlink support for virtual port management (was iovnl)
From: Arnd Bergmann @ 2010-05-15  9:07 UTC (permalink / raw)
  To: Chris Wright; +Cc: Scott Feldman, davem, netdev, kaber
In-Reply-To: <20100515031130.GD5798@x200.localdomain>

On Saturday 15 May 2010 05:11:30 Chris Wright wrote:
> * Scott Feldman (scofeldm@cisco.com) wrote:
> > From: Scott Feldman <scofeldm@cisco.com>
> > 
> > Add new netdev ops ndo_{set|get}_vf_port to allow setting of
> > port-profile on a netdev interface.  Extends netlink socket RTM_SETLINK/
> > RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF
> > (added to end of IFLA_cmd list).  These are both nested atrtibutes
> > using this layout:
> > 
> >               [IFLA_NUM_VF]
> >               [IFLA_VF_PORTS]
> >                       [IFLA_VF_PORT]
> >                               [IFLA_PORT_*], ...
> >                       [IFLA_VF_PORT]
> >                               [IFLA_PORT_*], ...
> >                       ...
> >               [IFLA_PORT_SELF]
> >                       [IFLA_PORT_*], ...
> > 
> > These attributes are design to be set and get symmetrically.  VF_PORTS
> > is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV
> > device.  PORT_SELF is for the PF of the SR-IOV device, in case it wants
> > to also have a port-profile, or for the case where the VF==PF, like in
> > enic patch 2/2 of this patch set.
> > 
> > A port-profile is used to configure/enable the external switch virtual port
> > backing the netdev interface, not to configure the host-facing side of the
> > netdev.  A port-profile is an identifier known to the switch.  How port-
> > profiles are installed on the switch or how available port-profiles are
> > made know to the host is outside the scope of this patch.
> > 
> > There are two types of port-profiles specs in the netlink msg.  The first spec
> > is for 802.1Qbg (pre-)standard, VDP protocol.  The second spec is for devices
> > that run a similar protocol as VDP but in firmware, thus hiding the protocol
> > details.  In either case, the specs have much in common and makes sense to
> > define the netlink msg as the union of the two specs.  For example, both specs
> > have a notition of associating/deassociating a port-profile.  And both specs
> > require some information from the hypervisor manager, such as client port
> > instance ID.
> > 
> > The general flow is the port-profile is applied to a host netdev interface
> > using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the
> > switch, and the switch virtual port backing the host netdev interface is
> > configured/enabled based on the settings defined by the port-profile.  What
> > those settings comprise, and how those settings are managed is again
> > outside the scope of this patch, since this patch only deals with the
> > first step in the flow.
> > 
> > Signed-off-by: Scott Feldman <scofeldm@cisco.com>
> > Signed-off-by: Roopa Prabhu<roprabhu@cisco.com>
> 
> Assuming the SR-IOV VFINFO changes go in there will be some minor patch
> conflicts to be sorted out.

Right, I assume the best resolution then would be drop IFLA_VF_PORTS and
put the IFLA_VF_PORT attribute inside IFLA_VF_INFO, correct?

> Acked-by: Chris Wright <chrisw@redhat.com>

Acked-by: Arnd Bergmann <arnd@arndb.de>

^ permalink raw reply

* Re: [PATCH] rtnetlink: make SR-IOV VF interface symmetric
From: Arnd Bergmann @ 2010-05-15  9:04 UTC (permalink / raw)
  To: Chris Wright; +Cc: davem, kaber, mitch.a.williams, scofeldm, shemminger, netdev
In-Reply-To: <20100515031416.GE15313@sequoia.sous-sol.org>

On Saturday 15 May 2010 05:14:16 Chris Wright wrote:
> Now we have a set of nested attributes:
> 
>   IFLA_VFINFO_LIST (NESTED)
>     IFLA_VF_INFO (NESTED)
>       IFLA_VF_MAC
>       IFLA_VF_VLAN
>       IFLA_VF_TX_RATE
> 
> This allows a single set to operate on multiple attributes if desired.
> Among other things, it means a dump can be replayed to set state.
> 
> The current interface has yet to be released, so this seems like
> something to consider for 2.6.34.
> 
> Signed-off-by: Chris Wright <chrisw@sous-sol.org

Very nice! This would be the minimum change to make the ABI conform
to the general rules, so it would be really good to have that.

Acked-by: Arnd Bergmann <arnd@arndb.de>

It does make the interface a bit strange (less than before), since the
new IFLA_VF_INFO now contains three nested attributes that each contain their
own vf number field, and we don't require that they are identical or that
each of the nested attributes inside VF_INFO appears only once.

How about a second patch that splits out an IFLA_VF_NUMBER attribute
and makes do_setvfinfo use nla_parse_nested instead of nla_for_each_nested
in order to tighten the rules on this some more?

	Arnd

^ permalink raw reply

* Re: loosing IPMI-card by loading netconsole
From: Carsten Aulbert @ 2010-05-15  8:26 UTC (permalink / raw)
  To: "Brandeburg, Jesse"
  Cc: Tejun Heo, Ronciak, John, Henning Fehrmann, Kirsher, Jeffrey T,
	Allan, Bruce W, Waskiewicz Jr, Peter P, netdev@vger.kernel.org,
	Matt Mackall, e1000-devel
In-Reply-To: <1273857641.3057.20.camel@localhost.localdomain>

[-- Attachment #1: Type: Text/Plain, Size: 12411 bytes --]

Hi all,

I'll try to gather some information:

The system under question is Supermicro PSDML-LN2+ based, eth0 is a 82573E 
while eth1 is a 82573L. IPMI is piggy-bagged onto eth0, eth1 is our "data 
network" running with large jumbo frames:

# ifconfig
eth0      Link encap:Ethernet  HWaddr 00:30:48:96:e1:e2
          inet addr:172.26.1.26  Bcast:172.31.255.255  Mask:255.240.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:673128 errors:0 dropped:0 overruns:0 frame:0
          TX packets:104281 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100
          RX bytes:46271457 (44.1 MiB)  TX bytes:8238586 (7.8 MiB)
          Memory:ee100000-ee120000

eth1      Link encap:Ethernet  HWaddr 00:30:48:96:e1:e3
          inet addr:10.10.1.26  Bcast:10.255.255.255  Mask:255.0.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1
          RX packets:17660268 errors:0 dropped:72239 overruns:0 frame:0
          TX packets:10941117 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:86507558735 (80.5 GiB)  TX bytes:7011613344 (6.5 GiB)
          Memory:ee200000-ee220000



# ethtool -i eth0
driver: e1000e
version: 1.0.2-k2
firmware-version: 0.15-4
bus-info: 0000:0d:00.0

ethtool -i eth1
driver: e1000e
version: 1.0.2-k2
firmware-version: 0.5-7
bus-info: 0000:0e:00.0

lscpi:
0d:00.0 0200: 8086:108c (rev 03)
        Subsystem: 15d9:108c    
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- 
Stepping- SERR+ FastB2B- DisINTx+
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- 
<TAbort- <MAbort- >SERR- <PERR- INTx- 
        Latency: 0, Cache Line Size: 64 bytes                                                                
        Interrupt: pin A routed to IRQ 29                                                                    
        Region 0: Memory at ee100000 (32-bit, non-prefetchable) [size=128K]                                  
        Region 2: I/O ports at 4000 [size=32]                                                                
        Capabilities: [c8] Power Management version 2                                                        
                Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA 
PME(D0+,D1-,D2-,D3hot+,D3cold+)                   
                Status: D0 PME-Enable- DSel=0 DScale=1 PME-                                                  
        Capabilities: [d0] Message Signalled Interrupts: Mask- 64bit+ 
Queue=0/0 Enable+                      
                Address: 00000000fee0f00c  Data: 41c1                                                        
        Capabilities: [e0] Express (v1) Endpoint, MSI 00                                                     
                DevCap: MaxPayload 256 bytes, PhantFunc 0, Latency L0s <512ns, 
L1 <64us                      
                        ExtTag- AttnBtn- AttnInd- PwrInd- RBE- FLReset-                                      
                DevCtl: Report errors: Correctable+ Non-Fatal+ Fatal+ 
Unsupported+
                        RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+
                        MaxPayload 128 bytes, MaxReadReq 512 bytes
                DevSta: CorrErr- UncorrErr+ FatalErr- UnsuppReq+ AuxPwr+ 
TransPend-
                LnkCap: Port #0, Speed 2.5GT/s, Width x1, ASPM unknown, 
Latency L0 <128ns, L1 <64us
                        ClockPM- Suprise- LLActRep- BwNot-
                LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- 
CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 2.5GT/s, Width x1, TrErr- Train- SlotClk+ 
DLActive- BWMgmt- ABWMgmt-
        Capabilities: [100] Advanced Error Reporting <?>
        Capabilities: [140] Device Serial Number e2-e1-96-ff-ff-48-30-00
        Kernel driver in use: e1000e
        Kernel modules: e1000e

0e:00.0 0200: 8086:109a
        Subsystem: 15d9:109a
        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- 
Stepping- SERR+ FastB2B- DisINTx+
        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- 
<TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0, Cache Line Size: 64 bytes
        Interrupt: pin A routed to IRQ 30
        Region 0: Memory at ee200000 (32-bit, non-prefetchable) [size=128K]
        Region 2: I/O ports at 5000 [size=32]
        Capabilities: [c8] Power Management version 2
                Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA 
PME(D0+,D1-,D2-,D3hot+,D3cold+)
                Status: D0 PME-Enable- DSel=0 DScale=1 PME-
        Capabilities: [d0] Message Signalled Interrupts: Mask- 64bit+ 
Queue=0/0 Enable+
                Address: 00000000fee0f00c  Data: 41b1
        Capabilities: [e0] Express (v1) Endpoint, MSI 00
                DevCap: MaxPayload 256 bytes, PhantFunc 0, Latency L0s <512ns, 
L1 <64us
                        ExtTag- AttnBtn- AttnInd- PwrInd- RBE- FLReset-
                DevCtl: Report errors: Correctable+ Non-Fatal+ Fatal+ 
Unsupported+
                        RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+
                        MaxPayload 128 bytes, MaxReadReq 512 bytes
                DevSta: CorrErr- UncorrErr+ FatalErr- UnsuppReq+ AuxPwr+ 
TransPend-
                LnkCap: Port #0, Speed 2.5GT/s, Width x1, ASPM unknown, 
Latency L0 <128ns, L1 <64us
                        ClockPM+ Suprise- LLActRep- BwNot-
                LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- 
CommClk-
                        ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                LnkSta: Speed 2.5GT/s, Width x1, TrErr- Train- SlotClk+ 
DLActive- BWMgmt- ABWMgmt-
        Capabilities: [100] Advanced Error Reporting <?>
        Capabilities: [140] Device Serial Number e3-e1-96-ff-ff-48-30-00
        Kernel driver in use: e1000e
        Kernel modules: e1000e


***************************************************************************
OK, now the detailed parts:

IPMI is currently blocked, i.e. I can query the card locally via the kernel 
module, but not remotely. netconsole is loaded and working via eth1.

# ethtool -S eth0                                     
NIC statistics:                                                                 
     rx_packets: 673400                                                         
     tx_packets: 104323                                                         
     rx_bytes: 48982938                                                         
     tx_bytes: 8659194                                                          
     rx_broadcast: 619125                                                       
     tx_broadcast: 3                                                            
     rx_multicast: 2088                                                         
     tx_multicast: 0                                                            
     rx_errors: 0                                                               
     tx_errors: 0                                                               
     tx_dropped: 0                                                              
     multicast: 2088                                                            
     collisions: 0                                                              
     rx_length_errors: 0                                                        
     rx_over_errors: 0                                                          
     rx_crc_errors: 0                                                           
     rx_frame_errors: 0                                                         
     rx_no_buffer_count: 0                                                      
     rx_missed_errors: 0                                                        
     tx_aborted_errors: 0                                                       
     tx_carrier_errors: 0                                                       
     tx_fifo_errors: 0                                                          
     tx_heartbeat_errors: 0                                                     
     tx_window_errors: 0                                                        
     tx_abort_late_coll: 0                                                      
     tx_deferred_ok: 0                                                          
     tx_single_coll_ok: 0                                                       
     tx_multi_coll_ok: 0                                                        
     tx_timeout_count: 0                                                        
     tx_restart_queue: 0                                                        
     rx_long_length_errors: 0                                                   
     rx_short_length_errors: 0                                                  
     rx_align_errors: 0                                                         
     tx_tcp_seg_good: 0                                                         
     tx_tcp_seg_failed: 0                                                       
     rx_flow_control_xon: 0                                                     
     rx_flow_control_xoff: 0                                                    
     tx_flow_control_xon: 0                                                     
     tx_flow_control_xoff: 0                                                    
     rx_long_byte_count: 48982938                                               
     rx_csum_offload_good: 76752                                                
     rx_csum_offload_errors: 0                                                  
     rx_header_split: 0                                                         
     alloc_rx_buff_failed: 0                                                    
     tx_smbus: 2                                                                
     rx_smbus: 594496                                                           
     dropped_smbus: 0                                                           
     rx_dma_failed: 0                                                           
     tx_dma_failed: 0                                                           
n0126:/build/ethregs-1.7.2# ethtool -S eth1
NIC statistics:                            
     rx_packets: 17664653                  
     tx_packets: 10941353                  
     rx_bytes: 86578358008                 
     tx_bytes: 7055320722                  
     rx_broadcast: 4761580                 
     tx_broadcast: 1252
     rx_multicast: 0
     tx_multicast: 0
     rx_errors: 0
     tx_errors: 0
     tx_dropped: 0
     multicast: 0
     collisions: 0
     rx_length_errors: 0
     rx_over_errors: 0
     rx_crc_errors: 0
     rx_frame_errors: 0
     rx_no_buffer_count: 1985
     rx_missed_errors: 72239
     tx_aborted_errors: 0
     tx_carrier_errors: 0
     tx_fifo_errors: 0
     tx_heartbeat_errors: 0
     tx_window_errors: 0
     tx_abort_late_coll: 0
     tx_deferred_ok: 0
     tx_single_coll_ok: 0
     tx_multi_coll_ok: 0
     tx_timeout_count: 0
     tx_restart_queue: 1920
     rx_long_length_errors: 0
     rx_short_length_errors: 0
     rx_align_errors: 0
     tx_tcp_seg_good: 127295
     tx_tcp_seg_failed: 0
     rx_flow_control_xon: 0
     rx_flow_control_xoff: 0
     tx_flow_control_xon: 0
     tx_flow_control_xoff: 0
     rx_long_byte_count: 86578358008
     rx_csum_offload_good: 12907089
     rx_csum_offload_errors: 0
     rx_header_split: 750356
     alloc_rx_buff_failed: 0
     tx_smbus: 0
     rx_smbus: 0
     dropped_smbus: 0
     rx_dma_failed: 0
     tx_dma_failed: 0

ethreg result attached

******************************************************************************

After rebooting without netconsole the IPMI card was still not working, using 
the echo 1 > ... /remove command from Henning's original email suddenly made 
IPMI working again.

After that I rebooted the machine while watching the progress via ipmitool's 
sol activate, however during the boot sequence suddenly the kernel output 
slowed to a crawl. About 1-2 minutes later remote IPMI broke down again.

netconsole was NOT loaded, thus I don't think that this is really related.

OK, how to proceed?

e.g. how can I re-enable the interface once I issued

echo 1 > /sys/devices/pci0000:00/0000:00:1c.4/0000:0d:00.0/remove

Cheers

Carsten

[-- Attachment #2: ethregs.IPMInotworkingNOnetconsole --]
[-- Type: text/plain, Size: 41597 bytes --]

0e:00.0 (8086:109a)
Intel Corporation 82573L Gigabit Ethernet Controller
	Name           Value
	~~~~           ~~~~~
	CTRL           00140248
	STATUS         80080783
	EECD           06008318
	EERD           f7460012
	CTRL_EXT       28780000
	FLA            00000608
	MDIC           182a7800
	FCAL           00c28001
	FCAH           00000100
	FCT            00008808
	VET            00008100
	ITR            000000c3
	ICS            00000000
	IMS            0000009d
	IMC            0000009d
	IAM            ffffffff
	RCTL           06078422
	FCTTV          00000680
	TCTL           3103f0fa
	TIPG           00602008
	AIT            00000000
	LEDCTL         00078406
	EXTCNF_CTRL    1000000a
	EXTCNF_SIZE    00000004
	PBA            0012000e
	PBS            00000020
	EEMNGCTL       80000000
	EEARBC         00000100
	FLASHT         00000002
	EEWR           00000002
	FLSWCTL        c0000000
	FLSWDATA       00000000
	FLSWCNT        00000000
	FLOP           0004db00
	ERT            00002100
	FCRTL          80002ff8
	FCRTH          00003000
	PSRCTL         04040401
	RDBAL          00eb8000
	RDBAH          00000002
	RDLEN          00002000
	RDH            0000005e
	RDT            0000005a
	RDTR           00000000
	RXDCTL         00010003
	RADV           00000008
	RDBAL1         00000000
	RDBAH1         00000200
	RDLEN1         00000000
	RDH1           00000000
	RDT1           00000000
	RSRPD          00000000
	RAID           00000000
	CPUVEC         00000000
	TDFH           00000ae4
	TDFT           00000ae4
	TDFHS          00000ae4
	TDFTS          00000ae4
	TDFPC          00000000
	TDBAL          16bd1000
	TDBAH          00000002
	TDLEN          00001000
	TDH            00000076
	TDT            00000076
	TIDV           00000008
	TXDCTL         01410000
	TADV           00000020
	TARC0          00000403
	TDBAL1         80400000
	TDBAH1         00000000
	TDLEN1         00000000
	TDH1           00000000
	TDT1           00000000
	TXDCTL1        00400000
	TARC1          00000403
	ICRXPTC        00000000
	ICRXATC        00000000
	ICTXPTC        00000000
	ICTXATC        00000000
	ICTXQEC        00000000
	ICTXQMTC       00000000
	ICRXDMTC       00000000
	ICRXOC         00000000
	RXCSUM         00001300
	RFCTL          00038000
	MTA[0]         00000000
	MTA[1]         00000000
	MTA[2]         00000000
	MTA[3]         00000000
	MTA[4]         00000000
	MTA[5]         00000000
	MTA[6]         00000000
	MTA[7]         00000000
	MTA[8]         00000000
	MTA[9]         00000000
	MTA[10]        00000000
	MTA[11]        00000000
	MTA[12]        00000000
	MTA[13]        00000000
	MTA[14]        00000000
	MTA[15]        00000000
	MTA[16]        00000000
	MTA[17]        00000000
	MTA[18]        00000000
	MTA[19]        00000000
	MTA[20]        00000000
	MTA[21]        00000000
	MTA[22]        00000000
	MTA[23]        00000000
	MTA[24]        00000000
	MTA[25]        00000000
	MTA[26]        00000000
	MTA[27]        00000000
	MTA[28]        00000000
	MTA[29]        00000000
	MTA[30]        00000000
	MTA[31]        00000000
	MTA[32]        00000000
	MTA[33]        00000000
	MTA[34]        00000000
	MTA[35]        00000000
	MTA[36]        00000000
	MTA[37]        00000000
	MTA[38]        00000000
	MTA[39]        00000000
	MTA[40]        00000000
	MTA[41]        00000000
	MTA[42]        00000000
	MTA[43]        00000000
	MTA[44]        00000000
	MTA[45]        00000000
	MTA[46]        00000000
	MTA[47]        00000000
	MTA[48]        00000000
	MTA[49]        00000000
	MTA[50]        00000000
	MTA[51]        00000000
	MTA[52]        00000000
	MTA[53]        00000000
	MTA[54]        00000000
	MTA[55]        00000000
	MTA[56]        00000000
	MTA[57]        00000000
	MTA[58]        00000000
	MTA[59]        00000000
	MTA[60]        00000000
	MTA[61]        00000000
	MTA[62]        00000000
	MTA[63]        00000000
	MTA[64]        00000000
	MTA[65]        00000000
	MTA[66]        00000000
	MTA[67]        00000000
	MTA[68]        00000000
	MTA[69]        00000000
	MTA[70]        00000000
	MTA[71]        00000000
	MTA[72]        00000000
	MTA[73]        00000000
	MTA[74]        00000000
	MTA[75]        00000000
	MTA[76]        00000000
	MTA[77]        00000000
	MTA[78]        00000000
	MTA[79]        00000000
	MTA[80]        00000000
	MTA[81]        00000000
	MTA[82]        00000000
	MTA[83]        00000000
	MTA[84]        00000000
	MTA[85]        00000000
	MTA[86]        00000000
	MTA[87]        00000000
	MTA[88]        00000000
	MTA[89]        00000000
	MTA[90]        00000000
	MTA[91]        00000000
	MTA[92]        00000000
	MTA[93]        00000000
	MTA[94]        00000000
	MTA[95]        00000000
	MTA[96]        00000000
	MTA[97]        00000000
	MTA[98]        00000000
	MTA[99]        00000000
	MTA[100]       00000000
	MTA[101]       00000000
	MTA[102]       00000000
	MTA[103]       00000000
	MTA[104]       00000000
	MTA[105]       00000000
	MTA[106]       00000000
	MTA[107]       00000000
	MTA[108]       00000000
	MTA[109]       00000000
	MTA[110]       00000000
	MTA[111]       00000000
	MTA[112]       00000000
	MTA[113]       00000000
	MTA[114]       00000000
	MTA[115]       00000000
	MTA[116]       00000000
	MTA[117]       00000000
	MTA[118]       00000000
	MTA[119]       00000000
	MTA[120]       00000000
	MTA[121]       00000000
	MTA[122]       00000000
	MTA[123]       00000000
	MTA[124]       00000000
	MTA[125]       00000000
	MTA[126]       00000000
	MTA[127]       00000000
	RAL[0]         96483000
	RAH[0]         8000e3e1
	RAL[1]         005e0001
	RAH[1]         80000100
	RAL[2]         00000000
	RAH[2]         00000000
	RAL[3]         00000000
	RAH[3]         00000000
	RAL[4]         00000000
	RAH[4]         00000000
	RAL[5]         00000000
	RAH[5]         00000000
	RAL[6]         00000000
	RAH[6]         00000000
	RAL[7]         00000000
	RAH[7]         00000000
	RAL[8]         00000000
	RAH[8]         00000000
	RAL[9]         00000000
	RAH[9]         00000000
	RAL[10]        00000000
	RAH[10]        00000000
	RAL[11]        00000000
	RAH[11]        00000000
	RAL[12]        00000000
	RAH[12]        00000000
	RAL[13]        00000000
	RAH[13]        00000000
	RAL[14]        00000000
	RAH[14]        00000000
	RAL[15]        00000000
	RAH[15]        00020010
	VFTA[0]        00000000
	VFTA[1]        00000000
	VFTA[2]        00000000
	VFTA[3]        00000000
	VFTA[4]        00000000
	VFTA[5]        00000000
	VFTA[6]        00000000
	VFTA[7]        00000000
	VFTA[8]        00000000
	VFTA[9]        00000000
	VFTA[10]       00000000
	VFTA[11]       00000000
	VFTA[12]       00000000
	VFTA[13]       00000000
	VFTA[14]       00000000
	VFTA[15]       00000000
	VFTA[16]       00000000
	VFTA[17]       00000000
	VFTA[18]       00000000
	VFTA[19]       00000000
	VFTA[20]       00000000
	VFTA[21]       00000000
	VFTA[22]       00000000
	VFTA[23]       00000000
	VFTA[24]       00000000
	VFTA[25]       00000000
	VFTA[26]       00000000
	VFTA[27]       00000000
	VFTA[28]       00000000
	VFTA[29]       00000000
	VFTA[30]       00000000
	VFTA[31]       00000000
	VFTA[32]       00000000
	VFTA[33]       00000000
	VFTA[34]       00000000
	VFTA[35]       00000000
	VFTA[36]       00000000
	VFTA[37]       00000000
	VFTA[38]       00000000
	VFTA[39]       00000000
	VFTA[40]       00000000
	VFTA[41]       00000000
	VFTA[42]       00000000
	VFTA[43]       00000000
	VFTA[44]       00000000
	VFTA[45]       00000000
	VFTA[46]       00000000
	VFTA[47]       00000000
	VFTA[48]       00000000
	VFTA[49]       00000000
	VFTA[50]       00000000
	VFTA[51]       00000000
	VFTA[52]       00000000
	VFTA[53]       00000000
	VFTA[54]       00000000
	VFTA[55]       00000000
	VFTA[56]       00000000
	VFTA[57]       00000000
	VFTA[58]       00000000
	VFTA[59]       00000000
	VFTA[60]       00000000
	VFTA[61]       00000000
	VFTA[62]       00000000
	VFTA[63]       00000000
	VFTA[64]       00000000
	VFTA[65]       00000000
	VFTA[66]       00000000
	VFTA[67]       00000000
	VFTA[68]       00000000
	VFTA[69]       00000000
	VFTA[70]       00000000
	VFTA[71]       00000000
	VFTA[72]       00000000
	VFTA[73]       00000000
	VFTA[74]       00000000
	VFTA[75]       00000000
	VFTA[76]       00000000
	VFTA[77]       00000000
	VFTA[78]       00000000
	VFTA[79]       00000000
	VFTA[80]       00000000
	VFTA[81]       00000000
	VFTA[82]       00000000
	VFTA[83]       00000000
	VFTA[84]       00000000
	VFTA[85]       00000000
	VFTA[86]       00000000
	VFTA[87]       00000000
	VFTA[88]       00000000
	VFTA[89]       00000000
	VFTA[90]       00000000
	VFTA[91]       00000000
	VFTA[92]       00000000
	VFTA[93]       00000000
	VFTA[94]       00000000
	VFTA[95]       00000000
	VFTA[96]       00000000
	VFTA[97]       00000000
	VFTA[98]       00000000
	VFTA[99]       00000000
	VFTA[100]      00000000
	VFTA[101]      00000000
	VFTA[102]      00000000
	VFTA[103]      00000000
	VFTA[104]      00000000
	VFTA[105]      00000000
	VFTA[106]      00000000
	VFTA[107]      00000000
	VFTA[108]      00000000
	VFTA[109]      00000000
	VFTA[110]      00000000
	VFTA[111]      00000000
	VFTA[112]      00000000
	VFTA[113]      00000000
	VFTA[114]      00000000
	VFTA[115]      00000000
	VFTA[116]      00000000
	VFTA[117]      00000000
	VFTA[118]      00000000
	VFTA[119]      00000000
	VFTA[120]      00000000
	VFTA[121]      00000000
	VFTA[122]      00000000
	VFTA[123]      00000000
	VFTA[124]      00000000
	VFTA[125]      00000000
	VFTA[126]      00000000
	VFTA[127]      00000000
	WUC            00000000
	WUFC           00000000
	WUS            00000000
	MRQC           00000000
	MANC           00000100
	IPAV           00000000
	MANC2H         00000000
	RSSIM          00000000
	RSSIR          00000001
	WUPL           9ce201fa
	GCR            0e000000
	GSCL_1         00000000
	GSCL_2         00000000
	GSCL_3         00000000
	GSCL_4         00000000
	FACTPS         a1041046
	FWSM           00000000
	RETA[0]        00000015
	RETA[1]        0000006b
	RETA[2]        00000004
	RETA[3]        000000e2
	RETA[4]        00000070
	RETA[5]        00000077
	RETA[6]        00000018
	RETA[7]        00000001
	RETA[8]        00000029
	RETA[9]        00000069
	RETA[10]       00000004
	RETA[11]       00000081
	RETA[12]       00000040
	RETA[13]       0000001e
	RETA[14]       00000093
	RETA[15]       000000c3
	RETA[16]       0000001b
	RETA[17]       0000002f
	RETA[18]       00000002
	RETA[19]       000000f4
	RETA[20]       000000bd
	RETA[21]       000000b6
	RETA[22]       000000af
	RETA[23]       00000029
	RETA[24]       00000003
	RETA[25]       0000001e
	RETA[26]       00000011
	RETA[27]       000000a5
	RETA[28]       0000008f
	RETA[29]       0000000b
	RETA[30]       00000059
	RETA[31]       00000006
	RETA[32]       00000008
	RETA[33]       000000d8
	RETA[34]       00000099
	RETA[35]       000000fb
	RETA[36]       0000003c
	RETA[37]       0000006c
	RETA[38]       00000011
	RETA[39]       00000027
	RETA[40]       00000029
	RETA[41]       00000097
	RETA[42]       00000055
	RETA[43]       000000a2
	RETA[44]       00000019
	RETA[45]       0000006e
	RETA[46]       00000011
	RETA[47]       00000060
	RETA[48]       000000ef
	RETA[49]       000000c1
	RETA[50]       00000033
	RETA[51]       000000a2
	RETA[52]       00000007
	RETA[53]       0000008a
	RETA[54]       0000006c
	RETA[55]       000000c2
	RETA[56]       00000029
	RETA[57]       0000002e
	RETA[58]       0000008b
	RETA[59]       00000063
	RETA[60]       00000035
	RETA[61]       00000015
	RETA[62]       00000091
	RETA[63]       000000ec
	RETA[64]       00000045
	RETA[65]       0000003b
	RETA[66]       0000001d
	RETA[67]       00000040
	RETA[68]       000000c5
	RETA[69]       00000082
	RETA[70]       000000b3
	RETA[71]       000000b6
	RETA[72]       0000000a
	RETA[73]       0000009b
	RETA[74]       000000d2
	RETA[75]       000000d2
	RETA[76]       0000004a
	RETA[77]       0000004e
	RETA[78]       00000010
	RETA[79]       000000e0
	RETA[80]       0000003a
	RETA[81]       000000ae
	RETA[82]       0000000d
	RETA[83]       00000070
	RETA[84]       0000001a
	RETA[85]       000000e7
	RETA[86]       000000c7
	RETA[87]       000000a5
	RETA[88]       0000006d
	RETA[89]       0000002f
	RETA[90]       00000061
	RETA[91]       00000026
	RETA[92]       0000000f
	RETA[93]       0000001f
	RETA[94]       00000019
	RETA[95]       000000ed
	RETA[96]       00000059
	RETA[97]       00000003
	RETA[98]       00000058
	RETA[99]       000000c9
	RETA[100]      0000006d
	RETA[101]      000000aa
	RETA[102]      0000000b
	RETA[103]      00000063
	RETA[104]      000000cd
	RETA[105]      0000001f
	RETA[106]      00000018
	RETA[107]      00000042
	RETA[108]      00000079
	RETA[109]      0000000f
	RETA[110]      0000005b
	RETA[111]      00000042
	RETA[112]      00000049
	RETA[113]      0000006e
	RETA[114]      00000008
	RETA[115]      00000076
	RETA[116]      0000002d
	RETA[117]      00000059
	RETA[118]      00000047
	RETA[119]      000000a6
	RETA[120]      00000090
	RETA[121]      00000002
	RETA[122]      000000cb
	RETA[123]      00000049
	RETA[124]      00000093
	RETA[125]      00000009
	RETA[126]      00000016
	RETA[127]      000000f2
	RSSRK[0]       00000000
	RSSRK[1]       00000000
	RSSRK[2]       00000000
	RSSRK[3]       00000000
	RSSRK[4]       00000000
	RSSRK[5]       00000000
	RSSRK[6]       00000000
	RSSRK[7]       00000000
	RSSRK[8]       00000000
	RSSRK[9]       00000000
	RSSRK[10]      00000000
	RSSRK[11]      00000000
	RSSRK[12]      00000000
	RSSRK[13]      00000000
	RSSRK[14]      00000000
	RSSRK[15]      00000000
	RSSRK[16]      00000000
	RSSRK[17]      00000000
	RSSRK[18]      00000000
	RSSRK[19]      00000000
	RSSRK[20]      00000000
	RSSRK[21]      00000000
	RSSRK[22]      00000000
	RSSRK[23]      00000000
	RSSRK[24]      00000000
	RSSRK[25]      00000000
	RSSRK[26]      00000000
	RSSRK[27]      00000000
	RSSRK[28]      00000000
	RSSRK[29]      00000000
	RSSRK[30]      00000000
	RSSRK[31]      00000000
	RSSRK[32]      00000000
	RSSRK[33]      00000000
	RSSRK[34]      00000000
	RSSRK[35]      00000000
	RSSRK[36]      00000000
	RSSRK[37]      00000000
	RSSRK[38]      00000000
	RSSRK[39]      00000000
	FFLT[0]        00000000
	FFLT[1]        fffc0000
	FFLT[2]        00000000
	FFLT[3]        00000000
	FFLT[4]        00000000
	FFLT[5]        00000000
	FFLT[6]        00000000
	FFLT[7]        00000000
	FFLT[8]        00000080
	FFLT[9]        00000000
	FFLT[10]       00000002
	FFLT[11]       00000000
	HICR           00000000
	FFMT[0]        00000006
	FFMT[1]        00000006
	FFMT[2]        00000009
	FFMT[3]        00000009
	FFMT[4]        0000000e
	FFMT[5]        0000000e
	FFMT[6]        0000000d
	FFMT[7]        0000000d
	FFMT[8]        0000000b
	FFMT[9]        0000000b
	FFMT[10]       0000000d
	FFMT[11]       0000000d
	FFMT[12]       00000004
	FFMT[13]       00000004
	FFMT[14]       00000000
	FFMT[15]       00000000
	FFMT[16]       00000000
	FFMT[17]       00000000
	FFMT[18]       00000009
	FFMT[19]       00000009
	FFMT[20]       00000001
	FFMT[21]       00000001
	FFMT[22]       00000006
	FFMT[23]       00000006
	FFMT[24]       00000003
	FFMT[25]       00000003
	FFMT[26]       00000004
	FFMT[27]       00000004
	FFMT[28]       00000005
	FFMT[29]       00000005
	FFMT[30]       0000000c
	FFMT[31]       0000000c
	FFMT[32]       00000000
	FFMT[33]       00000000
	FFMT[34]       00000008
	FFMT[35]       00000008
	FFMT[36]       00000002
	FFMT[37]       00000002
	FFMT[38]       0000000e
	FFMT[39]       0000000e
	FFMT[40]       00000003
	FFMT[41]       00000003
	FFMT[42]       0000000b
	FFMT[43]       0000000b
	FFMT[44]       00000001
	FFMT[45]       00000001
	FFMT[46]       00000005
	FFMT[47]       00000005
	FFMT[48]       00000003
	FFMT[49]       00000003
	FFMT[50]       00000001
	FFMT[51]       00000001
	FFMT[52]       0000000a
	FFMT[53]       0000000a
	FFMT[54]       00000003
	FFMT[55]       00000003
	FFMT[56]       00000001
	FFMT[57]       00000001
	FFMT[58]       0000000d
	FFMT[59]       0000000d
	FFMT[60]       00000008
	FFMT[61]       00000008
	FFMT[62]       00000002
	FFMT[63]       00000002
	FFMT[64]       00000002
	FFMT[65]       00000002
	FFMT[66]       00000007
	FFMT[67]       00000007
	FFMT[68]       00000004
	FFMT[69]       00000004
	FFMT[70]       00000006
	FFMT[71]       00000006
	FFMT[72]       0000000e
	FFMT[73]       0000000e
	FFMT[74]       0000000e
	FFMT[75]       0000000e
	FFMT[76]       0000000f
	FFMT[77]       0000000f
	FFMT[78]       00000002
	FFMT[79]       00000002
	FFMT[80]       00000000
	FFMT[81]       00000000
	FFMT[82]       0000000b
	FFMT[83]       0000000b
	FFMT[84]       00000009
	FFMT[85]       00000009
	FFMT[86]       00000009
	FFMT[87]       00000009
	FFMT[88]       0000000a
	FFMT[89]       0000000a
	FFMT[90]       0000000d
	FFMT[91]       0000000d
	FFMT[92]       00000005
	FFMT[93]       00000005
	FFMT[94]       00000006
	FFMT[95]       00000006
	FFMT[96]       00000003
	FFMT[97]       00000003
	FFMT[98]       0000000d
	FFMT[99]       0000000d
	FFMT[100]      00000009
	FFMT[101]      00000009
	FFMT[102]      0000000d
	FFMT[103]      0000000d
	FFMT[104]      00000001
	FFMT[105]      00000001
	FFMT[106]      0000000e
	FFMT[107]      0000000e
	FFMT[108]      0000000b
	FFMT[109]      0000000b
	FFMT[110]      00000000
	FFMT[111]      00000000
	FFMT[112]      00000001
	FFMT[113]      00000001
	FFMT[114]      00000000
	FFMT[115]      00000000
	FFMT[116]      00000008
	FFMT[117]      00000008
	FFMT[118]      0000000a
	FFMT[119]      0000000a
	FFMT[120]      00000001
	FFMT[121]      00000001
	FFMT[122]      00000006
	FFMT[123]      00000006
	FFMT[124]      00000002
	FFMT[125]      00000002
	FFMT[126]      0000000f
	FFMT[127]      0000000f
	FFVT[0]        a6d21076
	FFVT[1]        a6d21076
	FFVT[2]        14fddf8e
	FFVT[3]        14fddf8e
	FFVT[4]        af998eff
	FFVT[5]        af998eff
	FFVT[6]        72ee35eb
	FFVT[7]        72ee35eb
	FFVT[8]        4595b5d0
	FFVT[9]        4595b5d0
	FFVT[10]       9ce2d272
	FFVT[11]       9ce2d272
	FFVT[12]       65ccdb20
	FFVT[13]       65ccdb20
	FFVT[14]       7a6d632f
	FFVT[15]       7a6d632f
	FFVT[16]       c9fd53bd
	FFVT[17]       c9fd53bd
	FFVT[18]       138adc2d
	FFVT[19]       138adc2d
	FFVT[20]       5a7c8912
	FFVT[21]       5a7c8912
	FFVT[22]       080da768
	FFVT[23]       080da768
	FFVT[24]       e00a93c6
	FFVT[25]       e00a93c6
	FFVT[26]       3d05bbe0
	FFVT[27]       3d05bbe0
	FFVT[28]       8dc0ad89
	FFVT[29]       8dc0ad89
	FFVT[30]       a0267e00
	FFVT[31]       a0267e00
	FFVT[32]       45f0b43f
	FFVT[33]       45f0b43f
	FFVT[34]       62120156
	FFVT[35]       62120156
	FFVT[36]       a6213b97
	FFVT[37]       a6213b97
	FFVT[38]       ea15b0b6
	FFVT[39]       ea15b0b6
	FFVT[40]       a4176212
	FFVT[41]       a4176212
	FFVT[42]       ae88d158
	FFVT[43]       ae88d158
	FFVT[44]       541de595
	FFVT[45]       541de595
	FFVT[46]       15d56ace
	FFVT[47]       15d56ace
	FFVT[48]       45824374
	FFVT[49]       45824374
	FFVT[50]       2ba17885
	FFVT[51]       2ba17885
	FFVT[52]       b63201ea
	FFVT[53]       b63201ea
	FFVT[54]       b1ff88da
	FFVT[55]       b1ff88da
	FFVT[56]       f24edcea
	FFVT[57]       f24edcea
	FFVT[58]       b068c2e7
	FFVT[59]       b068c2e7
	FFVT[60]       58a6584c
	FFVT[61]       58a6584c
	FFVT[62]       ca6624d0
	FFVT[63]       ca6624d0
	FFVT[64]       d66319d3
	FFVT[65]       d66319d3
	FFVT[66]       437f892f
	FFVT[67]       437f892f
	FFVT[68]       6298ced1
	FFVT[69]       6298ced1
	FFVT[70]       d8f20b8e
	FFVT[71]       d8f20b8e
	FFVT[72]       00a8562c
	FFVT[73]       00a8562c
	FFVT[74]       536016e4
	FFVT[75]       536016e4
	FFVT[76]       81723c11
	FFVT[77]       81723c11
	FFVT[78]       6baf812a
	FFVT[79]       6baf812a
	FFVT[80]       579813dc
	FFVT[81]       579813dc
	FFVT[82]       f1099664
	FFVT[83]       f1099664
	FFVT[84]       484724af
	FFVT[85]       484724af
	FFVT[86]       9473f82f
	FFVT[87]       9473f82f
	FFVT[88]       2086be8f
	FFVT[89]       2086be8f
	FFVT[90]       505baa7a
	FFVT[91]       505baa7a
	FFVT[92]       e106d4d4
	FFVT[93]       e106d4d4
	FFVT[94]       035cf124
	FFVT[95]       035cf124
	FFVT[96]       80e38b56
	FFVT[97]       80e38b56
	FFVT[98]       03ef854a
	FFVT[99]       03ef854a
	FFVT[100]      ece8d8c9
	FFVT[101]      ece8d8c9
	FFVT[102]      a1d4c1a9
	FFVT[103]      a1d4c1a9
	FFVT[104]      e800f0b6
	FFVT[105]      e800f0b6
	FFVT[106]      7019d873
	FFVT[107]      7019d873
	FFVT[108]      a45554ff
	FFVT[109]      a45554ff
	FFVT[110]      29f98242
	FFVT[111]      29f98242
	FFVT[112]      b517937f
	FFVT[113]      b517937f
	FFVT[114]      a4d35dd5
	FFVT[115]      a4d35dd5
	FFVT[116]      52328c1b
	FFVT[117]      52328c1b
	FFVT[118]      09f59e76
	FFVT[119]      09f59e76
	FFVT[120]      1968c620
	FFVT[121]      1968c620
	FFVT[122]      cba89964
	FFVT[123]      cba89964
	FFVT[124]      42dc73e1
	FFVT[125]      42dc73e1
	FFVT[126]      06efaa25
	FFVT[127]      06efaa25


0d:00.0 (8086:108c)
Intel Corporation 82573E Gigabit Ethernet Controller (Copper)
	Name           Value
	~~~~           ~~~~~
	CTRL           18140248
	STATUS         80080743
	EECD           02011b18
	EERD           ffff0026
	CTRL_EXT       28780000
	FLA            00000608
	MDIC           18316d4c
	FCAL           00c28001
	FCAH           00000100
	FCT            00008808
	VET            00008100
	ITR            000003d0
	ICS            00000000
	IMS            0000009d
	IMC            0000009d
	IAM            ffffffff
	RCTL           04048002
	FCTTV          00000680
	TCTL           3103f0fa
	TIPG           00602008
	AIT            00000000
	LEDCTL         00078406
	EXTCNF_CTRL    10000008
	EXTCNF_SIZE    00000000
	PBA            000c0014
	PBS            00000020
	EEMNGCTL       800000f7
	EEARBC         00080100
	FLASHT         00000002
	EEWR           00000002
	FLSWCTL        c0000000
	FLSWDATA       00000000
	FLSWCNT        00000000
	FLOP           00012000
	ERT            00000000
	FCRTL          800047f8
	FCRTH          00004800
	PSRCTL         00040402
	RDBAL          15b98000
	RDBAH          00000002
	RDLEN          00001000
	RDH            0000008d
	RDT            0000008b
	RDTR           00000000
	RXDCTL         00010000
	RADV           00000008
	RDBAL1         00000000
	RDBAH1         01200200
	RDLEN1         00000000
	RDH1           00000000
	RDT1           00000000
	RSRPD          00000000
	RAID           00000000
	CPUVEC         00000000
	TDFH           00000b16
	TDFT           00000b16
	TDFHS          00000b16
	TDFTS          00000b16
	TDFPC          00000000
	TDBAL          1602b000
	TDBAH          00000002
	TDLEN          00001000
	TDH            00000021
	TDT            00000021
	TIDV           00000008
	TXDCTL         01410000
	TADV           00000020
	TARC0          00000403
	TDBAL1         00800000
	TDBAH1         10000500
	TDLEN1         00000000
	TDH1           00000000
	TDT1           00000000
	TXDCTL1        00400000
	TARC1          00000403
	ICRXPTC        00000000
	ICRXATC        00000000
	ICTXPTC        00000000
	ICTXATC        00000000
	ICTXQEC        00000000
	ICTXQMTC       00000000
	ICRXDMTC       00000000
	ICRXOC         00000000
	RXCSUM         00000300
	RFCTL          00000000
	MTA[0]         00000000
	MTA[1]         00000000
	MTA[2]         00000000
	MTA[3]         00000000
	MTA[4]         00000000
	MTA[5]         00000000
	MTA[6]         00000000
	MTA[7]         00000000
	MTA[8]         00000000
	MTA[9]         00000000
	MTA[10]        00000000
	MTA[11]        00000000
	MTA[12]        00000000
	MTA[13]        00000000
	MTA[14]        00000000
	MTA[15]        00000000
	MTA[16]        00000000
	MTA[17]        00000000
	MTA[18]        00000000
	MTA[19]        00000000
	MTA[20]        00000000
	MTA[21]        00000000
	MTA[22]        00000000
	MTA[23]        00000000
	MTA[24]        00000000
	MTA[25]        00000000
	MTA[26]        00000000
	MTA[27]        00000000
	MTA[28]        00000000
	MTA[29]        00000000
	MTA[30]        00000000
	MTA[31]        00000000
	MTA[32]        00000000
	MTA[33]        00000000
	MTA[34]        00000000
	MTA[35]        00000000
	MTA[36]        00000000
	MTA[37]        00000000
	MTA[38]        00000000
	MTA[39]        00000000
	MTA[40]        00000000
	MTA[41]        00000000
	MTA[42]        00000000
	MTA[43]        00000000
	MTA[44]        00000000
	MTA[45]        00000000
	MTA[46]        00000000
	MTA[47]        00000000
	MTA[48]        00000000
	MTA[49]        00000000
	MTA[50]        00000000
	MTA[51]        00000000
	MTA[52]        00000000
	MTA[53]        00000000
	MTA[54]        00000000
	MTA[55]        00000000
	MTA[56]        00000000
	MTA[57]        00000000
	MTA[58]        00000000
	MTA[59]        00000000
	MTA[60]        00000000
	MTA[61]        00000000
	MTA[62]        00000000
	MTA[63]        00000000
	MTA[64]        00000000
	MTA[65]        00000000
	MTA[66]        00000000
	MTA[67]        00000000
	MTA[68]        00000000
	MTA[69]        00000000
	MTA[70]        00000000
	MTA[71]        00000000
	MTA[72]        00000000
	MTA[73]        00000000
	MTA[74]        00000000
	MTA[75]        00000000
	MTA[76]        00000000
	MTA[77]        00000000
	MTA[78]        00000000
	MTA[79]        00000000
	MTA[80]        00000000
	MTA[81]        00000000
	MTA[82]        00000000
	MTA[83]        00000000
	MTA[84]        00000000
	MTA[85]        00000000
	MTA[86]        00000000
	MTA[87]        00000000
	MTA[88]        00000000
	MTA[89]        00000000
	MTA[90]        00000000
	MTA[91]        00000000
	MTA[92]        00000000
	MTA[93]        00000000
	MTA[94]        00000000
	MTA[95]        00000000
	MTA[96]        00000000
	MTA[97]        00000000
	MTA[98]        00000000
	MTA[99]        00000000
	MTA[100]       00000000
	MTA[101]       00000000
	MTA[102]       00000000
	MTA[103]       00000000
	MTA[104]       00000000
	MTA[105]       00000000
	MTA[106]       00000000
	MTA[107]       00000000
	MTA[108]       00000000
	MTA[109]       00000000
	MTA[110]       00000000
	MTA[111]       00000000
	MTA[112]       00000000
	MTA[113]       00000000
	MTA[114]       00000000
	MTA[115]       00000000
	MTA[116]       00000000
	MTA[117]       00000000
	MTA[118]       00000000
	MTA[119]       00000000
	MTA[120]       00000000
	MTA[121]       00000000
	MTA[122]       00000000
	MTA[123]       00000000
	MTA[124]       00000000
	MTA[125]       00000000
	MTA[126]       00000000
	MTA[127]       00000000
	RAL[0]         96483000
	RAH[0]         8000e2e1
	RAL[1]         005e0001
	RAH[1]         80000100
	RAL[2]         00000000
	RAH[2]         00000000
	RAL[3]         00000000
	RAH[3]         00000000
	RAL[4]         00000000
	RAH[4]         00000000
	RAL[5]         00000000
	RAH[5]         00000000
	RAL[6]         00000000
	RAH[6]         00000000
	RAL[7]         00000000
	RAH[7]         00000000
	RAL[8]         00000000
	RAH[8]         00000000
	RAL[9]         00000000
	RAH[9]         00000000
	RAL[10]        00000000
	RAH[10]        00000000
	RAL[11]        00000000
	RAH[11]        00000000
	RAL[12]        00000000
	RAH[12]        00000000
	RAL[13]        00000000
	RAH[13]        00000000
	RAL[14]        00000000
	RAH[14]        00000000
	RAL[15]        96483000
	RAH[15]        0000e2e1
	VFTA[0]        00000000
	VFTA[1]        00000000
	VFTA[2]        00000000
	VFTA[3]        00000000
	VFTA[4]        00000000
	VFTA[5]        00000000
	VFTA[6]        00000000
	VFTA[7]        00000000
	VFTA[8]        00000000
	VFTA[9]        00000000
	VFTA[10]       00000000
	VFTA[11]       00000000
	VFTA[12]       00000000
	VFTA[13]       00000000
	VFTA[14]       00000000
	VFTA[15]       00000000
	VFTA[16]       00000000
	VFTA[17]       00000000
	VFTA[18]       00000000
	VFTA[19]       00000000
	VFTA[20]       00000000
	VFTA[21]       00000000
	VFTA[22]       00000000
	VFTA[23]       00000000
	VFTA[24]       00000000
	VFTA[25]       00000000
	VFTA[26]       00000000
	VFTA[27]       00000000
	VFTA[28]       00000000
	VFTA[29]       00000000
	VFTA[30]       00000000
	VFTA[31]       00000000
	VFTA[32]       00000000
	VFTA[33]       00000000
	VFTA[34]       00000000
	VFTA[35]       00000000
	VFTA[36]       00000000
	VFTA[37]       00000000
	VFTA[38]       00000000
	VFTA[39]       00000000
	VFTA[40]       00000000
	VFTA[41]       00000000
	VFTA[42]       00000000
	VFTA[43]       00000000
	VFTA[44]       00000000
	VFTA[45]       00000000
	VFTA[46]       00000000
	VFTA[47]       00000000
	VFTA[48]       00000000
	VFTA[49]       00000000
	VFTA[50]       00000000
	VFTA[51]       00000000
	VFTA[52]       00000000
	VFTA[53]       00000000
	VFTA[54]       00000000
	VFTA[55]       00000000
	VFTA[56]       00000000
	VFTA[57]       00000000
	VFTA[58]       00000000
	VFTA[59]       00000000
	VFTA[60]       00000000
	VFTA[61]       00000000
	VFTA[62]       00000000
	VFTA[63]       00000000
	VFTA[64]       00000000
	VFTA[65]       00000000
	VFTA[66]       00000000
	VFTA[67]       00000000
	VFTA[68]       00000000
	VFTA[69]       00000000
	VFTA[70]       00000000
	VFTA[71]       00000000
	VFTA[72]       00000000
	VFTA[73]       00000000
	VFTA[74]       00000000
	VFTA[75]       00000000
	VFTA[76]       00000000
	VFTA[77]       00000000
	VFTA[78]       00000000
	VFTA[79]       00000000
	VFTA[80]       00000000
	VFTA[81]       00000000
	VFTA[82]       00000000
	VFTA[83]       00000000
	VFTA[84]       00000000
	VFTA[85]       00000000
	VFTA[86]       00000000
	VFTA[87]       00000000
	VFTA[88]       00000000
	VFTA[89]       00000000
	VFTA[90]       00000000
	VFTA[91]       00000000
	VFTA[92]       00000000
	VFTA[93]       00000000
	VFTA[94]       00000000
	VFTA[95]       00000000
	VFTA[96]       00000000
	VFTA[97]       00000000
	VFTA[98]       00000000
	VFTA[99]       00000000
	VFTA[100]      00000000
	VFTA[101]      00000000
	VFTA[102]      00000000
	VFTA[103]      00000000
	VFTA[104]      00000000
	VFTA[105]      00000000
	VFTA[106]      00000000
	VFTA[107]      00000000
	VFTA[108]      00000000
	VFTA[109]      00000000
	VFTA[110]      00000000
	VFTA[111]      00000000
	VFTA[112]      00000000
	VFTA[113]      00000000
	VFTA[114]      00000000
	VFTA[115]      00000000
	VFTA[116]      00000000
	VFTA[117]      00000000
	VFTA[118]      00000000
	VFTA[119]      00000000
	VFTA[120]      00000000
	VFTA[121]      00000000
	VFTA[122]      00000000
	VFTA[123]      00000000
	VFTA[124]      00000000
	VFTA[125]      00000000
	VFTA[126]      00000000
	VFTA[127]      00000000
	WUC            00000000
	WUFC           00000000
	WUS            00000000
	MRQC           00000000
	MANC           0022a300
	IPAV           00000000
	MANC2H         00000380
	RSSIM          00000000
	RSSIR          00000000
	WUPL           28167f49
	GCR            0e000000
	GSCL_1         00000000
	GSCL_2         00000000
	GSCL_3         00000000
	GSCL_4         00000000
	FACTPS         01041046
	FWSM           00018044
	RETA[0]        0000008c
	RETA[1]        0000001f
	RETA[2]        00000082
	RETA[3]        00000086
	RETA[4]        0000009f
	RETA[5]        00000066
	RETA[6]        0000005a
	RETA[7]        0000004b
	RETA[8]        0000001e
	RETA[9]        000000af
	RETA[10]       000000dc
	RETA[11]       000000e5
	RETA[12]       0000002d
	RETA[13]       000000aa
	RETA[14]       0000009b
	RETA[15]       0000001c
	RETA[16]       00000053
	RETA[17]       000000e6
	RETA[18]       00000096
	RETA[19]       00000084
	RETA[20]       000000b1
	RETA[21]       0000006b
	RETA[22]       000000b7
	RETA[23]       000000de
	RETA[24]       00000010
	RETA[25]       000000d4
	RETA[26]       000000ef
	RETA[27]       00000034
	RETA[28]       00000038
	RETA[29]       0000000e
	RETA[30]       00000012
	RETA[31]       0000001d
	RETA[32]       00000001
	RETA[33]       0000004b
	RETA[34]       000000e3
	RETA[35]       0000001e
	RETA[36]       0000001b
	RETA[37]       0000009b
	RETA[38]       0000008e
	RETA[39]       00000068
	RETA[40]       00000015
	RETA[41]       000000e2
	RETA[42]       000000c7
	RETA[43]       000000c6
	RETA[44]       00000034
	RETA[45]       0000007a
	RETA[46]       000000b6
	RETA[47]       00000014
	RETA[48]       000000aa
	RETA[49]       0000006f
	RETA[50]       000000fa
	RETA[51]       00000085
	RETA[52]       00000032
	RETA[53]       0000004e
	RETA[54]       0000003f
	RETA[55]       0000004c
	RETA[56]       00000099
	RETA[57]       0000003d
	RETA[58]       000000f2
	RETA[59]       000000ae
	RETA[60]       00000011
	RETA[61]       0000006f
	RETA[62]       000000b7
	RETA[63]       0000000b
	RETA[64]       0000009b
	RETA[65]       00000007
	RETA[66]       0000000a
	RETA[67]       0000009a
	RETA[68]       000000a3
	RETA[69]       00000020
	RETA[70]       000000f3
	RETA[71]       00000084
	RETA[72]       0000004d
	RETA[73]       00000048
	RETA[74]       0000008b
	RETA[75]       00000021
	RETA[76]       000000c7
	RETA[77]       00000053
	RETA[78]       000000a3
	RETA[79]       0000008b
	RETA[80]       000000d4
	RETA[81]       0000004a
	RETA[82]       000000c2
	RETA[83]       000000c0
	RETA[84]       0000003b
	RETA[85]       00000069
	RETA[86]       00000082
	RETA[87]       0000005e
	RETA[88]       00000098
	RETA[89]       0000007a
	RETA[90]       00000017
	RETA[91]       00000084
	RETA[92]       000000ab
	RETA[93]       0000004a
	RETA[94]       000000c7
	RETA[95]       00000014
	RETA[96]       0000001d
	RETA[97]       0000006a
	RETA[98]       00000077
	RETA[99]       00000014
	RETA[100]      000000b9
	RETA[101]      0000000a
	RETA[102]      000000c2
	RETA[103]      0000003d
	RETA[104]      00000055
	RETA[105]      000000aa
	RETA[106]      000000b4
	RETA[107]      00000004
	RETA[108]      00000047
	RETA[109]      00000053
	RETA[110]      000000f7
	RETA[111]      00000016
	RETA[112]      0000008b
	RETA[113]      000000d3
	RETA[114]      000000b2
	RETA[115]      00000074
	RETA[116]      0000003b
	RETA[117]      0000002b
	RETA[118]      0000009d
	RETA[119]      00000016
	RETA[120]      0000002b
	RETA[121]      000000ce
	RETA[122]      0000008e
	RETA[123]      00000044
	RETA[124]      00000027
	RETA[125]      0000004b
	RETA[126]      000000c2
	RETA[127]      00000086
	RSSRK[0]       00000000
	RSSRK[1]       00000000
	RSSRK[2]       00000000
	RSSRK[3]       00000000
	RSSRK[4]       00000000
	RSSRK[5]       00000000
	RSSRK[6]       00000000
	RSSRK[7]       00000000
	RSSRK[8]       00000000
	RSSRK[9]       00000000
	RSSRK[10]      00000000
	RSSRK[11]      00000000
	RSSRK[12]      00000000
	RSSRK[13]      00000000
	RSSRK[14]      00000000
	RSSRK[15]      00000000
	RSSRK[16]      00000000
	RSSRK[17]      00000000
	RSSRK[18]      00000000
	RSSRK[19]      00000000
	RSSRK[20]      00000000
	RSSRK[21]      00000000
	RSSRK[22]      00000000
	RSSRK[23]      00000000
	RSSRK[24]      00000000
	RSSRK[25]      00000000
	RSSRK[26]      00000000
	RSSRK[27]      00000000
	RSSRK[28]      00000000
	RSSRK[29]      00000000
	RSSRK[30]      00000000
	RSSRK[31]      00000000
	RSSRK[32]      00000000
	RSSRK[33]      00000000
	RSSRK[34]      00000000
	RSSRK[35]      00000000
	RSSRK[36]      00000000
	RSSRK[37]      00000000
	RSSRK[38]      00000000
	RSSRK[39]      00000000
	FFLT[0]        00000000
	FFLT[1]        fffc0000
	FFLT[2]        00000000
	FFLT[3]        00000000
	FFLT[4]        00000000
	FFLT[5]        00000000
	FFLT[6]        00000000
	FFLT[7]        00000000
	FFLT[8]        00000000
	FFLT[9]        00000000
	FFLT[10]       00000000
	FFLT[11]       00000000
	HICR           00000101
	FFMT[0]        0000000c
	FFMT[1]        0000000c
	FFMT[2]        0000000d
	FFMT[3]        0000000d
	FFMT[4]        0000000c
	FFMT[5]        0000000c
	FFMT[6]        0000000f
	FFMT[7]        0000000f
	FFMT[8]        00000001
	FFMT[9]        00000001
	FFMT[10]       00000006
	FFMT[11]       00000006
	FFMT[12]       00000004
	FFMT[13]       00000004
	FFMT[14]       0000000c
	FFMT[15]       0000000c
	FFMT[16]       0000000e
	FFMT[17]       0000000e
	FFMT[18]       00000001
	FFMT[19]       00000001
	FFMT[20]       00000001
	FFMT[21]       00000001
	FFMT[22]       00000001
	FFMT[23]       00000001
	FFMT[24]       00000000
	FFMT[25]       00000000
	FFMT[26]       00000001
	FFMT[27]       00000001
	FFMT[28]       00000002
	FFMT[29]       00000002
	FFMT[30]       0000000f
	FFMT[31]       0000000f
	FFMT[32]       00000001
	FFMT[33]       00000001
	FFMT[34]       00000003
	FFMT[35]       00000003
	FFMT[36]       0000000c
	FFMT[37]       0000000c
	FFMT[38]       00000002
	FFMT[39]       00000002
	FFMT[40]       00000008
	FFMT[41]       00000008
	FFMT[42]       0000000f
	FFMT[43]       0000000f
	FFMT[44]       00000008
	FFMT[45]       00000008
	FFMT[46]       00000004
	FFMT[47]       00000004
	FFMT[48]       00000006
	FFMT[49]       00000006
	FFMT[50]       00000007
	FFMT[51]       00000007
	FFMT[52]       00000002
	FFMT[53]       00000002
	FFMT[54]       0000000b
	FFMT[55]       0000000b
	FFMT[56]       00000008
	FFMT[57]       00000008
	FFMT[58]       00000003
	FFMT[59]       00000003
	FFMT[60]       00000004
	FFMT[61]       00000004
	FFMT[62]       00000000
	FFMT[63]       00000000
	FFMT[64]       00000001
	FFMT[65]       00000001
	FFMT[66]       0000000e
	FFMT[67]       0000000e
	FFMT[68]       00000007
	FFMT[69]       00000007
	FFMT[70]       0000000b
	FFMT[71]       0000000b
	FFMT[72]       00000006
	FFMT[73]       00000006
	FFMT[74]       00000009
	FFMT[75]       00000009
	FFMT[76]       00000009
	FFMT[77]       00000009
	FFMT[78]       00000009
	FFMT[79]       00000009
	FFMT[80]       0000000f
	FFMT[81]       0000000f
	FFMT[82]       00000009
	FFMT[83]       00000009
	FFMT[84]       0000000a
	FFMT[85]       0000000a
	FFMT[86]       00000000
	FFMT[87]       00000000
	FFMT[88]       0000000b
	FFMT[89]       0000000b
	FFMT[90]       00000003
	FFMT[91]       00000003
	FFMT[92]       00000001
	FFMT[93]       00000001
	FFMT[94]       00000004
	FFMT[95]       00000004
	FFMT[96]       0000000b
	FFMT[97]       0000000b
	FFMT[98]       0000000c
	FFMT[99]       0000000c
	FFMT[100]      0000000a
	FFMT[101]      0000000a
	FFMT[102]      00000009
	FFMT[103]      00000009
	FFMT[104]      00000000
	FFMT[105]      00000000
	FFMT[106]      00000003
	FFMT[107]      00000003
	FFMT[108]      00000006
	FFMT[109]      00000006
	FFMT[110]      00000008
	FFMT[111]      00000008
	FFMT[112]      0000000e
	FFMT[113]      0000000e
	FFMT[114]      00000007
	FFMT[115]      00000007
	FFMT[116]      0000000c
	FFMT[117]      0000000c
	FFMT[118]      00000007
	FFMT[119]      00000007
	FFMT[120]      00000009
	FFMT[121]      00000009
	FFMT[122]      00000001
	FFMT[123]      00000001
	FFMT[124]      00000001
	FFMT[125]      00000001
	FFMT[126]      0000000f
	FFMT[127]      0000000f
	FFVT[0]        69386efe
	FFVT[1]        69386efe
	FFVT[2]        47dac1bd
	FFVT[3]        47dac1bd
	FFVT[4]        0af977e3
	FFVT[5]        0af977e3
	FFVT[6]        0bf35fcd
	FFVT[7]        0bf35fcd
	FFVT[8]        396325cb
	FFVT[9]        396325cb
	FFVT[10]       45fb2966
	FFVT[11]       45fb2966
	FFVT[12]       85fe3e31
	FFVT[13]       85fe3e31
	FFVT[14]       e6b90940
	FFVT[15]       e6b90940
	FFVT[16]       fcf5c382
	FFVT[17]       fcf5c382
	FFVT[18]       68b90289
	FFVT[19]       68b90289
	FFVT[20]       0fada5ed
	FFVT[21]       0fada5ed
	FFVT[22]       67f87890
	FFVT[23]       67f87890
	FFVT[24]       2dd69d55
	FFVT[25]       2dd69d55
	FFVT[26]       0f78a7b0
	FFVT[27]       0f78a7b0
	FFVT[28]       138d13f7
	FFVT[29]       138d13f7
	FFVT[30]       e302400a
	FFVT[31]       e302400a
	FFVT[32]       bc8ebaf7
	FFVT[33]       bc8ebaf7
	FFVT[34]       96fe79fb
	FFVT[35]       96fe79fb
	FFVT[36]       df5aa33b
	FFVT[37]       df5aa33b
	FFVT[38]       91212c9e
	FFVT[39]       91212c9e
	FFVT[40]       71c517b4
	FFVT[41]       71c517b4
	FFVT[42]       0bb6697f
	FFVT[43]       0bb6697f
	FFVT[44]       63018c23
	FFVT[45]       63018c23
	FFVT[46]       48a35d54
	FFVT[47]       48a35d54
	FFVT[48]       95f4d375
	FFVT[49]       95f4d375
	FFVT[50]       4699c679
	FFVT[51]       4699c679
	FFVT[52]       06e7adde
	FFVT[53]       06e7adde
	FFVT[54]       e31f1b6d
	FFVT[55]       e31f1b6d
	FFVT[56]       888919d6
	FFVT[57]       888919d6
	FFVT[58]       4751a142
	FFVT[59]       4751a142
	FFVT[60]       676fef06
	FFVT[61]       676fef06
	FFVT[62]       792d0e82
	FFVT[63]       792d0e82
	FFVT[64]       1066713d
	FFVT[65]       1066713d
	FFVT[66]       8f55fa4d
	FFVT[67]       8f55fa4d
	FFVT[68]       5fe46f1a
	FFVT[69]       5fe46f1a
	FFVT[70]       cacbc51e
	FFVT[71]       cacbc51e
	FFVT[72]       04470301
	FFVT[73]       04470301
	FFVT[74]       6b3dfea9
	FFVT[75]       6b3dfea9
	FFVT[76]       bd00be00
	FFVT[77]       bd00be00
	FFVT[78]       7079cb0c
	FFVT[79]       7079cb0c
	FFVT[80]       e7180acc
	FFVT[81]       e7180acc
	FFVT[82]       25755bec
	FFVT[83]       25755bec
	FFVT[84]       bcdd8914
	FFVT[85]       bcdd8914
	FFVT[86]       9ed3128d
	FFVT[87]       9ed3128d
	FFVT[88]       dc48587b
	FFVT[89]       dc48587b
	FFVT[90]       e9755ebf
	FFVT[91]       e9755ebf
	FFVT[92]       9ff23883
	FFVT[93]       9ff23883
	FFVT[94]       52d8233d
	FFVT[95]       52d8233d
	FFVT[96]       cdcf21c0
	FFVT[97]       cdcf21c0
	FFVT[98]       9069a69f
	FFVT[99]       9069a69f
	FFVT[100]      b52c57f5
	FFVT[101]      b52c57f5
	FFVT[102]      42977681
	FFVT[103]      42977681
	FFVT[104]      ab8b671a
	FFVT[105]      ab8b671a
	FFVT[106]      4edc0c8b
	FFVT[107]      4edc0c8b
	FFVT[108]      f41c47f0
	FFVT[109]      f41c47f0
	FFVT[110]      ab4edb12
	FFVT[111]      ab4edb12
	FFVT[112]      c096a36f
	FFVT[113]      c096a36f
	FFVT[114]      ed46c26a
	FFVT[115]      ed46c26a
	FFVT[116]      aca39e0b
	FFVT[117]      aca39e0b
	FFVT[118]      e01ed8b5
	FFVT[119]      e01ed8b5
	FFVT[120]      604c1ef5
	FFVT[121]      604c1ef5
	FFVT[122]      0dbbfeae
	FFVT[123]      0dbbfeae
	FFVT[124]      9478dbb7
	FFVT[125]      9478dbb7
	FFVT[126]      f95cfa23
	FFVT[127]      f95cfa23



[-- Attachment #3: ethregs.IPMInotworking --]
[-- Type: text/plain, Size: 41597 bytes --]

0e:00.0 (8086:109a)
Intel Corporation 82573L Gigabit Ethernet Controller
	Name           Value
	~~~~           ~~~~~
	CTRL           00140248
	STATUS         80080783
	EECD           06008318
	EERD           f7460012
	CTRL_EXT       28780000
	FLA            00000608
	MDIC           182a7800
	FCAL           00c28001
	FCAH           00000100
	FCT            00008808
	VET            00008100
	ITR            000000c3
	ICS            00000000
	IMS            0000009d
	IMC            0000009d
	IAM            ffffffff
	RCTL           06078422
	FCTTV          00000680
	TCTL           3103f0fa
	TIPG           00602008
	AIT            00000000
	LEDCTL         00078406
	EXTCNF_CTRL    1000000a
	EXTCNF_SIZE    00000004
	PBA            0012000e
	PBS            00000020
	EEMNGCTL       80000000
	EEARBC         00000100
	FLASHT         00000002
	EEWR           00000002
	FLSWCTL        c0000000
	FLSWDATA       00000000
	FLSWCNT        00000000
	FLOP           0004db00
	ERT            00002100
	FCRTL          80002ff8
	FCRTH          00003000
	PSRCTL         04040401
	RDBAL          13a7e000
	RDBAH          00000002
	RDLEN          00002000
	RDH            00000004
	RDT            00000000
	RDTR           00000000
	RXDCTL         00010003
	RADV           00000008
	RDBAL1         00000000
	RDBAH1         00000200
	RDLEN1         00000000
	RDH1           00000000
	RDT1           00000000
	RSRPD          00000000
	RAID           00000000
	CPUVEC         00000000
	TDFH           00000f8e
	TDFT           00000f8e
	TDFHS          00000f8e
	TDFTS          00000f8e
	TDFPC          00000000
	TDBAL          13986000
	TDBAH          00000002
	TDLEN          00001000
	TDH            000000bd
	TDT            000000bd
	TIDV           00000008
	TXDCTL         01410000
	TADV           00000020
	TARC0          00000403
	TDBAL1         80400000
	TDBAH1         00000000
	TDLEN1         00000000
	TDH1           00000000
	TDT1           00000000
	TXDCTL1        00400000
	TARC1          00000403
	ICRXPTC        00000000
	ICRXATC        00000000
	ICTXPTC        00000000
	ICTXATC        00000000
	ICTXQEC        00000000
	ICTXQMTC       00000000
	ICRXDMTC       00000000
	ICRXOC         00000000
	RXCSUM         00001300
	RFCTL          00038000
	MTA[0]         00000000
	MTA[1]         00000000
	MTA[2]         00000000
	MTA[3]         00000000
	MTA[4]         00000000
	MTA[5]         00000000
	MTA[6]         00000000
	MTA[7]         00000000
	MTA[8]         00000000
	MTA[9]         00000000
	MTA[10]        00000000
	MTA[11]        00000000
	MTA[12]        00000000
	MTA[13]        00000000
	MTA[14]        00000000
	MTA[15]        00000000
	MTA[16]        00000000
	MTA[17]        00000000
	MTA[18]        00000000
	MTA[19]        00000000
	MTA[20]        00000000
	MTA[21]        00000000
	MTA[22]        00000000
	MTA[23]        00000000
	MTA[24]        00000000
	MTA[25]        00000000
	MTA[26]        00000000
	MTA[27]        00000000
	MTA[28]        00000000
	MTA[29]        00000000
	MTA[30]        00000000
	MTA[31]        00000000
	MTA[32]        00000000
	MTA[33]        00000000
	MTA[34]        00000000
	MTA[35]        00000000
	MTA[36]        00000000
	MTA[37]        00000000
	MTA[38]        00000000
	MTA[39]        00000000
	MTA[40]        00000000
	MTA[41]        00000000
	MTA[42]        00000000
	MTA[43]        00000000
	MTA[44]        00000000
	MTA[45]        00000000
	MTA[46]        00000000
	MTA[47]        00000000
	MTA[48]        00000000
	MTA[49]        00000000
	MTA[50]        00000000
	MTA[51]        00000000
	MTA[52]        00000000
	MTA[53]        00000000
	MTA[54]        00000000
	MTA[55]        00000000
	MTA[56]        00000000
	MTA[57]        00000000
	MTA[58]        00000000
	MTA[59]        00000000
	MTA[60]        00000000
	MTA[61]        00000000
	MTA[62]        00000000
	MTA[63]        00000000
	MTA[64]        00000000
	MTA[65]        00000000
	MTA[66]        00000000
	MTA[67]        00000000
	MTA[68]        00000000
	MTA[69]        00000000
	MTA[70]        00000000
	MTA[71]        00000000
	MTA[72]        00000000
	MTA[73]        00000000
	MTA[74]        00000000
	MTA[75]        00000000
	MTA[76]        00000000
	MTA[77]        00000000
	MTA[78]        00000000
	MTA[79]        00000000
	MTA[80]        00000000
	MTA[81]        00000000
	MTA[82]        00000000
	MTA[83]        00000000
	MTA[84]        00000000
	MTA[85]        00000000
	MTA[86]        00000000
	MTA[87]        00000000
	MTA[88]        00000000
	MTA[89]        00000000
	MTA[90]        00000000
	MTA[91]        00000000
	MTA[92]        00000000
	MTA[93]        00000000
	MTA[94]        00000000
	MTA[95]        00000000
	MTA[96]        00000000
	MTA[97]        00000000
	MTA[98]        00000000
	MTA[99]        00000000
	MTA[100]       00000000
	MTA[101]       00000000
	MTA[102]       00000000
	MTA[103]       00000000
	MTA[104]       00000000
	MTA[105]       00000000
	MTA[106]       00000000
	MTA[107]       00000000
	MTA[108]       00000000
	MTA[109]       00000000
	MTA[110]       00000000
	MTA[111]       00000000
	MTA[112]       00000000
	MTA[113]       00000000
	MTA[114]       00000000
	MTA[115]       00000000
	MTA[116]       00000000
	MTA[117]       00000000
	MTA[118]       00000000
	MTA[119]       00000000
	MTA[120]       00000000
	MTA[121]       00000000
	MTA[122]       00000000
	MTA[123]       00000000
	MTA[124]       00000000
	MTA[125]       00000000
	MTA[126]       00000000
	MTA[127]       00000000
	RAL[0]         96483000
	RAH[0]         8000e3e1
	RAL[1]         005e0001
	RAH[1]         80000100
	RAL[2]         00000000
	RAH[2]         00000000
	RAL[3]         00000000
	RAH[3]         00000000
	RAL[4]         00000000
	RAH[4]         00000000
	RAL[5]         00000000
	RAH[5]         00000000
	RAL[6]         00000000
	RAH[6]         00000000
	RAL[7]         00000000
	RAH[7]         00000000
	RAL[8]         00000000
	RAH[8]         00000000
	RAL[9]         00000000
	RAH[9]         00000000
	RAL[10]        00000000
	RAH[10]        00000000
	RAL[11]        00000000
	RAH[11]        00000000
	RAL[12]        00000000
	RAH[12]        00000000
	RAL[13]        00000000
	RAH[13]        00000000
	RAL[14]        00000000
	RAH[14]        00000000
	RAL[15]        00000000
	RAH[15]        00020010
	VFTA[0]        00000000
	VFTA[1]        00000000
	VFTA[2]        00000000
	VFTA[3]        00000000
	VFTA[4]        00000000
	VFTA[5]        00000000
	VFTA[6]        00000000
	VFTA[7]        00000000
	VFTA[8]        00000000
	VFTA[9]        00000000
	VFTA[10]       00000000
	VFTA[11]       00000000
	VFTA[12]       00000000
	VFTA[13]       00000000
	VFTA[14]       00000000
	VFTA[15]       00000000
	VFTA[16]       00000000
	VFTA[17]       00000000
	VFTA[18]       00000000
	VFTA[19]       00000000
	VFTA[20]       00000000
	VFTA[21]       00000000
	VFTA[22]       00000000
	VFTA[23]       00000000
	VFTA[24]       00000000
	VFTA[25]       00000000
	VFTA[26]       00000000
	VFTA[27]       00000000
	VFTA[28]       00000000
	VFTA[29]       00000000
	VFTA[30]       00000000
	VFTA[31]       00000000
	VFTA[32]       00000000
	VFTA[33]       00000000
	VFTA[34]       00000000
	VFTA[35]       00000000
	VFTA[36]       00000000
	VFTA[37]       00000000
	VFTA[38]       00000000
	VFTA[39]       00000000
	VFTA[40]       00000000
	VFTA[41]       00000000
	VFTA[42]       00000000
	VFTA[43]       00000000
	VFTA[44]       00000000
	VFTA[45]       00000000
	VFTA[46]       00000000
	VFTA[47]       00000000
	VFTA[48]       00000000
	VFTA[49]       00000000
	VFTA[50]       00000000
	VFTA[51]       00000000
	VFTA[52]       00000000
	VFTA[53]       00000000
	VFTA[54]       00000000
	VFTA[55]       00000000
	VFTA[56]       00000000
	VFTA[57]       00000000
	VFTA[58]       00000000
	VFTA[59]       00000000
	VFTA[60]       00000000
	VFTA[61]       00000000
	VFTA[62]       00000000
	VFTA[63]       00000000
	VFTA[64]       00000000
	VFTA[65]       00000000
	VFTA[66]       00000000
	VFTA[67]       00000000
	VFTA[68]       00000000
	VFTA[69]       00000000
	VFTA[70]       00000000
	VFTA[71]       00000000
	VFTA[72]       00000000
	VFTA[73]       00000000
	VFTA[74]       00000000
	VFTA[75]       00000000
	VFTA[76]       00000000
	VFTA[77]       00000000
	VFTA[78]       00000000
	VFTA[79]       00000000
	VFTA[80]       00000000
	VFTA[81]       00000000
	VFTA[82]       00000000
	VFTA[83]       00000000
	VFTA[84]       00000000
	VFTA[85]       00000000
	VFTA[86]       00000000
	VFTA[87]       00000000
	VFTA[88]       00000000
	VFTA[89]       00000000
	VFTA[90]       00000000
	VFTA[91]       00000000
	VFTA[92]       00000000
	VFTA[93]       00000000
	VFTA[94]       00000000
	VFTA[95]       00000000
	VFTA[96]       00000000
	VFTA[97]       00000000
	VFTA[98]       00000000
	VFTA[99]       00000000
	VFTA[100]      00000000
	VFTA[101]      00000000
	VFTA[102]      00000000
	VFTA[103]      00000000
	VFTA[104]      00000000
	VFTA[105]      00000000
	VFTA[106]      00000000
	VFTA[107]      00000000
	VFTA[108]      00000000
	VFTA[109]      00000000
	VFTA[110]      00000000
	VFTA[111]      00000000
	VFTA[112]      00000000
	VFTA[113]      00000000
	VFTA[114]      00000000
	VFTA[115]      00000000
	VFTA[116]      00000000
	VFTA[117]      00000000
	VFTA[118]      00000000
	VFTA[119]      00000000
	VFTA[120]      00000000
	VFTA[121]      00000000
	VFTA[122]      00000000
	VFTA[123]      00000000
	VFTA[124]      00000000
	VFTA[125]      00000000
	VFTA[126]      00000000
	VFTA[127]      00000000
	WUC            00000000
	WUFC           00000000
	WUS            00000000
	MRQC           00000000
	MANC           00000100
	IPAV           00000000
	MANC2H         00000000
	RSSIM          00000000
	RSSIR          00000001
	WUPL           9ce201fa
	GCR            0e000000
	GSCL_1         00000000
	GSCL_2         00000000
	GSCL_3         00000000
	GSCL_4         00000000
	FACTPS         21041046
	FWSM           00000000
	RETA[0]        00000015
	RETA[1]        0000006b
	RETA[2]        00000004
	RETA[3]        000000e2
	RETA[4]        00000070
	RETA[5]        00000077
	RETA[6]        00000018
	RETA[7]        00000001
	RETA[8]        00000029
	RETA[9]        00000069
	RETA[10]       00000004
	RETA[11]       00000081
	RETA[12]       00000040
	RETA[13]       0000001e
	RETA[14]       00000093
	RETA[15]       000000c3
	RETA[16]       0000001b
	RETA[17]       0000002f
	RETA[18]       00000002
	RETA[19]       000000f4
	RETA[20]       000000bd
	RETA[21]       000000b6
	RETA[22]       000000af
	RETA[23]       00000029
	RETA[24]       00000003
	RETA[25]       0000001e
	RETA[26]       00000011
	RETA[27]       000000a5
	RETA[28]       0000008f
	RETA[29]       0000000b
	RETA[30]       00000059
	RETA[31]       00000006
	RETA[32]       00000008
	RETA[33]       000000d8
	RETA[34]       00000099
	RETA[35]       000000fb
	RETA[36]       0000003c
	RETA[37]       0000006c
	RETA[38]       00000011
	RETA[39]       00000027
	RETA[40]       00000029
	RETA[41]       00000097
	RETA[42]       00000055
	RETA[43]       000000a2
	RETA[44]       00000019
	RETA[45]       0000006e
	RETA[46]       00000011
	RETA[47]       00000060
	RETA[48]       000000ef
	RETA[49]       000000c1
	RETA[50]       00000033
	RETA[51]       000000a2
	RETA[52]       00000007
	RETA[53]       0000008a
	RETA[54]       0000006c
	RETA[55]       000000c2
	RETA[56]       00000029
	RETA[57]       0000002e
	RETA[58]       0000008b
	RETA[59]       00000063
	RETA[60]       00000035
	RETA[61]       00000015
	RETA[62]       00000091
	RETA[63]       000000ec
	RETA[64]       00000045
	RETA[65]       0000003b
	RETA[66]       0000001d
	RETA[67]       00000040
	RETA[68]       000000c5
	RETA[69]       00000082
	RETA[70]       000000b3
	RETA[71]       000000b6
	RETA[72]       0000000a
	RETA[73]       0000009b
	RETA[74]       000000d2
	RETA[75]       000000d2
	RETA[76]       0000004a
	RETA[77]       0000004e
	RETA[78]       00000010
	RETA[79]       000000e0
	RETA[80]       0000003a
	RETA[81]       000000ae
	RETA[82]       0000000d
	RETA[83]       00000070
	RETA[84]       0000001a
	RETA[85]       000000e7
	RETA[86]       000000c7
	RETA[87]       000000a5
	RETA[88]       0000006d
	RETA[89]       0000002f
	RETA[90]       00000061
	RETA[91]       00000026
	RETA[92]       0000000f
	RETA[93]       0000001f
	RETA[94]       00000019
	RETA[95]       000000ed
	RETA[96]       00000059
	RETA[97]       00000003
	RETA[98]       00000058
	RETA[99]       000000c9
	RETA[100]      0000006d
	RETA[101]      000000aa
	RETA[102]      0000000b
	RETA[103]      00000063
	RETA[104]      000000cd
	RETA[105]      0000001f
	RETA[106]      00000018
	RETA[107]      00000042
	RETA[108]      00000079
	RETA[109]      0000000f
	RETA[110]      0000005b
	RETA[111]      00000042
	RETA[112]      00000049
	RETA[113]      0000006e
	RETA[114]      00000008
	RETA[115]      00000076
	RETA[116]      0000002d
	RETA[117]      00000059
	RETA[118]      00000047
	RETA[119]      000000a6
	RETA[120]      00000090
	RETA[121]      00000002
	RETA[122]      000000cb
	RETA[123]      00000049
	RETA[124]      00000093
	RETA[125]      00000009
	RETA[126]      00000016
	RETA[127]      000000f2
	RSSRK[0]       00000000
	RSSRK[1]       00000000
	RSSRK[2]       00000000
	RSSRK[3]       00000000
	RSSRK[4]       00000000
	RSSRK[5]       00000000
	RSSRK[6]       00000000
	RSSRK[7]       00000000
	RSSRK[8]       00000000
	RSSRK[9]       00000000
	RSSRK[10]      00000000
	RSSRK[11]      00000000
	RSSRK[12]      00000000
	RSSRK[13]      00000000
	RSSRK[14]      00000000
	RSSRK[15]      00000000
	RSSRK[16]      00000000
	RSSRK[17]      00000000
	RSSRK[18]      00000000
	RSSRK[19]      00000000
	RSSRK[20]      00000000
	RSSRK[21]      00000000
	RSSRK[22]      00000000
	RSSRK[23]      00000000
	RSSRK[24]      00000000
	RSSRK[25]      00000000
	RSSRK[26]      00000000
	RSSRK[27]      00000000
	RSSRK[28]      00000000
	RSSRK[29]      00000000
	RSSRK[30]      00000000
	RSSRK[31]      00000000
	RSSRK[32]      00000000
	RSSRK[33]      00000000
	RSSRK[34]      00000000
	RSSRK[35]      00000000
	RSSRK[36]      00000000
	RSSRK[37]      00000000
	RSSRK[38]      00000000
	RSSRK[39]      00000000
	FFLT[0]        00000000
	FFLT[1]        fffc0000
	FFLT[2]        00000000
	FFLT[3]        00000000
	FFLT[4]        00000000
	FFLT[5]        00000000
	FFLT[6]        00000000
	FFLT[7]        00000000
	FFLT[8]        00000080
	FFLT[9]        00000000
	FFLT[10]       00000002
	FFLT[11]       00000000
	HICR           00000000
	FFMT[0]        00000006
	FFMT[1]        00000006
	FFMT[2]        00000009
	FFMT[3]        00000009
	FFMT[4]        0000000e
	FFMT[5]        0000000e
	FFMT[6]        0000000d
	FFMT[7]        0000000d
	FFMT[8]        0000000b
	FFMT[9]        0000000b
	FFMT[10]       0000000d
	FFMT[11]       0000000d
	FFMT[12]       00000004
	FFMT[13]       00000004
	FFMT[14]       00000000
	FFMT[15]       00000000
	FFMT[16]       00000000
	FFMT[17]       00000000
	FFMT[18]       00000009
	FFMT[19]       00000009
	FFMT[20]       00000001
	FFMT[21]       00000001
	FFMT[22]       00000006
	FFMT[23]       00000006
	FFMT[24]       00000003
	FFMT[25]       00000003
	FFMT[26]       00000004
	FFMT[27]       00000004
	FFMT[28]       00000005
	FFMT[29]       00000005
	FFMT[30]       0000000c
	FFMT[31]       0000000c
	FFMT[32]       00000000
	FFMT[33]       00000000
	FFMT[34]       00000008
	FFMT[35]       00000008
	FFMT[36]       00000002
	FFMT[37]       00000002
	FFMT[38]       0000000e
	FFMT[39]       0000000e
	FFMT[40]       00000003
	FFMT[41]       00000003
	FFMT[42]       0000000b
	FFMT[43]       0000000b
	FFMT[44]       00000001
	FFMT[45]       00000001
	FFMT[46]       00000005
	FFMT[47]       00000005
	FFMT[48]       00000003
	FFMT[49]       00000003
	FFMT[50]       00000001
	FFMT[51]       00000001
	FFMT[52]       0000000a
	FFMT[53]       0000000a
	FFMT[54]       00000003
	FFMT[55]       00000003
	FFMT[56]       00000001
	FFMT[57]       00000001
	FFMT[58]       0000000d
	FFMT[59]       0000000d
	FFMT[60]       00000008
	FFMT[61]       00000008
	FFMT[62]       00000002
	FFMT[63]       00000002
	FFMT[64]       00000002
	FFMT[65]       00000002
	FFMT[66]       00000007
	FFMT[67]       00000007
	FFMT[68]       00000004
	FFMT[69]       00000004
	FFMT[70]       00000006
	FFMT[71]       00000006
	FFMT[72]       0000000e
	FFMT[73]       0000000e
	FFMT[74]       0000000e
	FFMT[75]       0000000e
	FFMT[76]       0000000f
	FFMT[77]       0000000f
	FFMT[78]       00000002
	FFMT[79]       00000002
	FFMT[80]       00000000
	FFMT[81]       00000000
	FFMT[82]       0000000b
	FFMT[83]       0000000b
	FFMT[84]       00000009
	FFMT[85]       00000009
	FFMT[86]       00000009
	FFMT[87]       00000009
	FFMT[88]       0000000a
	FFMT[89]       0000000a
	FFMT[90]       0000000d
	FFMT[91]       0000000d
	FFMT[92]       00000005
	FFMT[93]       00000005
	FFMT[94]       00000006
	FFMT[95]       00000006
	FFMT[96]       00000003
	FFMT[97]       00000003
	FFMT[98]       0000000d
	FFMT[99]       0000000d
	FFMT[100]      00000009
	FFMT[101]      00000009
	FFMT[102]      0000000d
	FFMT[103]      0000000d
	FFMT[104]      00000001
	FFMT[105]      00000001
	FFMT[106]      0000000e
	FFMT[107]      0000000e
	FFMT[108]      0000000b
	FFMT[109]      0000000b
	FFMT[110]      00000000
	FFMT[111]      00000000
	FFMT[112]      00000001
	FFMT[113]      00000001
	FFMT[114]      00000000
	FFMT[115]      00000000
	FFMT[116]      00000008
	FFMT[117]      00000008
	FFMT[118]      0000000a
	FFMT[119]      0000000a
	FFMT[120]      00000001
	FFMT[121]      00000001
	FFMT[122]      00000006
	FFMT[123]      00000006
	FFMT[124]      00000002
	FFMT[125]      00000002
	FFMT[126]      0000000f
	FFMT[127]      0000000f
	FFVT[0]        a6d21076
	FFVT[1]        a6d21076
	FFVT[2]        14fddf8e
	FFVT[3]        14fddf8e
	FFVT[4]        af998eff
	FFVT[5]        af998eff
	FFVT[6]        72ee35eb
	FFVT[7]        72ee35eb
	FFVT[8]        4595b5d0
	FFVT[9]        4595b5d0
	FFVT[10]       9ce2d272
	FFVT[11]       9ce2d272
	FFVT[12]       65ccdb20
	FFVT[13]       65ccdb20
	FFVT[14]       7a6d632f
	FFVT[15]       7a6d632f
	FFVT[16]       c9fd53bd
	FFVT[17]       c9fd53bd
	FFVT[18]       138adc2d
	FFVT[19]       138adc2d
	FFVT[20]       5a7c8912
	FFVT[21]       5a7c8912
	FFVT[22]       080da768
	FFVT[23]       080da768
	FFVT[24]       e00a93c6
	FFVT[25]       e00a93c6
	FFVT[26]       3d05bbe0
	FFVT[27]       3d05bbe0
	FFVT[28]       8dc0ad89
	FFVT[29]       8dc0ad89
	FFVT[30]       a0267e00
	FFVT[31]       a0267e00
	FFVT[32]       45f0b43f
	FFVT[33]       45f0b43f
	FFVT[34]       62120156
	FFVT[35]       62120156
	FFVT[36]       a6213b97
	FFVT[37]       a6213b97
	FFVT[38]       ea15b0b6
	FFVT[39]       ea15b0b6
	FFVT[40]       a4176212
	FFVT[41]       a4176212
	FFVT[42]       ae88d158
	FFVT[43]       ae88d158
	FFVT[44]       541de595
	FFVT[45]       541de595
	FFVT[46]       15d56ace
	FFVT[47]       15d56ace
	FFVT[48]       45824374
	FFVT[49]       45824374
	FFVT[50]       2ba17885
	FFVT[51]       2ba17885
	FFVT[52]       b63201ea
	FFVT[53]       b63201ea
	FFVT[54]       b1ff88da
	FFVT[55]       b1ff88da
	FFVT[56]       f24edcea
	FFVT[57]       f24edcea
	FFVT[58]       b068c2e7
	FFVT[59]       b068c2e7
	FFVT[60]       58a6584c
	FFVT[61]       58a6584c
	FFVT[62]       ca6624d0
	FFVT[63]       ca6624d0
	FFVT[64]       d66319d3
	FFVT[65]       d66319d3
	FFVT[66]       437f892f
	FFVT[67]       437f892f
	FFVT[68]       6298ced1
	FFVT[69]       6298ced1
	FFVT[70]       d8f20b8e
	FFVT[71]       d8f20b8e
	FFVT[72]       00a8562c
	FFVT[73]       00a8562c
	FFVT[74]       536016e4
	FFVT[75]       536016e4
	FFVT[76]       81723c11
	FFVT[77]       81723c11
	FFVT[78]       6baf812a
	FFVT[79]       6baf812a
	FFVT[80]       579813dc
	FFVT[81]       579813dc
	FFVT[82]       f1099664
	FFVT[83]       f1099664
	FFVT[84]       484724af
	FFVT[85]       484724af
	FFVT[86]       9473f82f
	FFVT[87]       9473f82f
	FFVT[88]       2086be8f
	FFVT[89]       2086be8f
	FFVT[90]       505baa7a
	FFVT[91]       505baa7a
	FFVT[92]       e106d4d4
	FFVT[93]       e106d4d4
	FFVT[94]       035cf124
	FFVT[95]       035cf124
	FFVT[96]       80e38b56
	FFVT[97]       80e38b56
	FFVT[98]       03ef854a
	FFVT[99]       03ef854a
	FFVT[100]      ece8d8c9
	FFVT[101]      ece8d8c9
	FFVT[102]      a1d4c1a9
	FFVT[103]      a1d4c1a9
	FFVT[104]      e800f0b6
	FFVT[105]      e800f0b6
	FFVT[106]      7019d873
	FFVT[107]      7019d873
	FFVT[108]      a45554ff
	FFVT[109]      a45554ff
	FFVT[110]      29f98242
	FFVT[111]      29f98242
	FFVT[112]      b517937f
	FFVT[113]      b517937f
	FFVT[114]      a4d35dd5
	FFVT[115]      a4d35dd5
	FFVT[116]      52328c1b
	FFVT[117]      52328c1b
	FFVT[118]      09f59e76
	FFVT[119]      09f59e76
	FFVT[120]      1968c620
	FFVT[121]      1968c620
	FFVT[122]      cba89964
	FFVT[123]      cba89964
	FFVT[124]      42dc73e1
	FFVT[125]      42dc73e1
	FFVT[126]      06efaa25
	FFVT[127]      06efaa25


0d:00.0 (8086:108c)
Intel Corporation 82573E Gigabit Ethernet Controller (Copper)
	Name           Value
	~~~~           ~~~~~
	CTRL           18140248
	STATUS         80080743
	EECD           02011b18
	EERD           ffff0026
	CTRL_EXT       28780000
	FLA            00000608
	MDIC           18316d0c
	FCAL           00c28001
	FCAH           00000100
	FCT            00008808
	VET            00008100
	ITR            000003d0
	ICS            00000000
	IMS            0000009d
	IMC            0000009d
	IAM            ffffffff
	RCTL           04048002
	FCTTV          00000680
	TCTL           3103f0fa
	TIPG           00602008
	AIT            00000000
	LEDCTL         00078406
	EXTCNF_CTRL    10000008
	EXTCNF_SIZE    00000000
	PBA            000c0014
	PBS            00000020
	EEMNGCTL       800000f7
	EEARBC         00080100
	FLASHT         00000002
	EEWR           00000002
	FLSWCTL        c0000000
	FLSWDATA       00000000
	FLSWCNT        00000000
	FLOP           00012000
	ERT            00000000
	FCRTL          800047f8
	FCRTH          00004800
	PSRCTL         00040402
	RDBAL          1310c000
	RDBAH          00000002
	RDLEN          00001000
	RDH            0000007e
	RDT            0000007c
	RDTR           00000000
	RXDCTL         00010000
	RADV           00000008
	RDBAL1         00000000
	RDBAH1         01200200
	RDLEN1         00000000
	RDH1           00000000
	RDT1           00000000
	RSRPD          00000000
	RAID           00000000
	CPUVEC         00000000
	TDFH           00000bde
	TDFT           00000bde
	TDFHS          00000bde
	TDFTS          00000bde
	TDFPC          00000000
	TDBAL          16a50000
	TDBAH          00000002
	TDLEN          00001000
	TDH            00000086
	TDT            00000086
	TIDV           00000008
	TXDCTL         01410000
	TADV           00000020
	TARC0          00000403
	TDBAL1         00800000
	TDBAH1         10000500
	TDLEN1         00000000
	TDH1           00000000
	TDT1           00000000
	TXDCTL1        00400000
	TARC1          00000403
	ICRXPTC        00000000
	ICRXATC        00000000
	ICTXPTC        00000000
	ICTXATC        00000000
	ICTXQEC        00000000
	ICTXQMTC       00000000
	ICRXDMTC       00000000
	ICRXOC         00000000
	RXCSUM         00000300
	RFCTL          00000000
	MTA[0]         00000000
	MTA[1]         00000000
	MTA[2]         00000000
	MTA[3]         00000000
	MTA[4]         00000000
	MTA[5]         00000000
	MTA[6]         00000000
	MTA[7]         00000000
	MTA[8]         00000000
	MTA[9]         00000000
	MTA[10]        00000000
	MTA[11]        00000000
	MTA[12]        00000000
	MTA[13]        00000000
	MTA[14]        00000000
	MTA[15]        00000000
	MTA[16]        00000000
	MTA[17]        00000000
	MTA[18]        00000000
	MTA[19]        00000000
	MTA[20]        00000000
	MTA[21]        00000000
	MTA[22]        00000000
	MTA[23]        00000000
	MTA[24]        00000000
	MTA[25]        00000000
	MTA[26]        00000000
	MTA[27]        00000000
	MTA[28]        00000000
	MTA[29]        00000000
	MTA[30]        00000000
	MTA[31]        00000000
	MTA[32]        00000000
	MTA[33]        00000000
	MTA[34]        00000000
	MTA[35]        00000000
	MTA[36]        00000000
	MTA[37]        00000000
	MTA[38]        00000000
	MTA[39]        00000000
	MTA[40]        00000000
	MTA[41]        00000000
	MTA[42]        00000000
	MTA[43]        00000000
	MTA[44]        00000000
	MTA[45]        00000000
	MTA[46]        00000000
	MTA[47]        00000000
	MTA[48]        00000000
	MTA[49]        00000000
	MTA[50]        00000000
	MTA[51]        00000000
	MTA[52]        00000000
	MTA[53]        00000000
	MTA[54]        00000000
	MTA[55]        00000000
	MTA[56]        00000000
	MTA[57]        00000000
	MTA[58]        00000000
	MTA[59]        00000000
	MTA[60]        00000000
	MTA[61]        00000000
	MTA[62]        00000000
	MTA[63]        00000000
	MTA[64]        00000000
	MTA[65]        00000000
	MTA[66]        00000000
	MTA[67]        00000000
	MTA[68]        00000000
	MTA[69]        00000000
	MTA[70]        00000000
	MTA[71]        00000000
	MTA[72]        00000000
	MTA[73]        00000000
	MTA[74]        00000000
	MTA[75]        00000000
	MTA[76]        00000000
	MTA[77]        00000000
	MTA[78]        00000000
	MTA[79]        00000000
	MTA[80]        00000000
	MTA[81]        00000000
	MTA[82]        00000000
	MTA[83]        00000000
	MTA[84]        00000000
	MTA[85]        00000000
	MTA[86]        00000000
	MTA[87]        00000000
	MTA[88]        00000000
	MTA[89]        00000000
	MTA[90]        00000000
	MTA[91]        00000000
	MTA[92]        00000000
	MTA[93]        00000000
	MTA[94]        00000000
	MTA[95]        00000000
	MTA[96]        00000000
	MTA[97]        00000000
	MTA[98]        00000000
	MTA[99]        00000000
	MTA[100]       00000000
	MTA[101]       00000000
	MTA[102]       00000000
	MTA[103]       00000000
	MTA[104]       00000000
	MTA[105]       00000000
	MTA[106]       00000000
	MTA[107]       00000000
	MTA[108]       00000000
	MTA[109]       00000000
	MTA[110]       00000000
	MTA[111]       00000000
	MTA[112]       00000000
	MTA[113]       00000000
	MTA[114]       00000000
	MTA[115]       00000000
	MTA[116]       00000000
	MTA[117]       00000000
	MTA[118]       00000000
	MTA[119]       00000000
	MTA[120]       00000000
	MTA[121]       00000000
	MTA[122]       00000000
	MTA[123]       00000000
	MTA[124]       00000000
	MTA[125]       00000000
	MTA[126]       00000000
	MTA[127]       00000000
	RAL[0]         96483000
	RAH[0]         8000e2e1
	RAL[1]         005e0001
	RAH[1]         80000100
	RAL[2]         00000000
	RAH[2]         00000000
	RAL[3]         00000000
	RAH[3]         00000000
	RAL[4]         00000000
	RAH[4]         00000000
	RAL[5]         00000000
	RAH[5]         00000000
	RAL[6]         00000000
	RAH[6]         00000000
	RAL[7]         00000000
	RAH[7]         00000000
	RAL[8]         00000000
	RAH[8]         00000000
	RAL[9]         00000000
	RAH[9]         00000000
	RAL[10]        00000000
	RAH[10]        00000000
	RAL[11]        00000000
	RAH[11]        00000000
	RAL[12]        00000000
	RAH[12]        00000000
	RAL[13]        00000000
	RAH[13]        00000000
	RAL[14]        00000000
	RAH[14]        00000000
	RAL[15]        96483000
	RAH[15]        0000e2e1
	VFTA[0]        00000000
	VFTA[1]        00000000
	VFTA[2]        00000000
	VFTA[3]        00000000
	VFTA[4]        00000000
	VFTA[5]        00000000
	VFTA[6]        00000000
	VFTA[7]        00000000
	VFTA[8]        00000000
	VFTA[9]        00000000
	VFTA[10]       00000000
	VFTA[11]       00000000
	VFTA[12]       00000000
	VFTA[13]       00000000
	VFTA[14]       00000000
	VFTA[15]       00000000
	VFTA[16]       00000000
	VFTA[17]       00000000
	VFTA[18]       00000000
	VFTA[19]       00000000
	VFTA[20]       00000000
	VFTA[21]       00000000
	VFTA[22]       00000000
	VFTA[23]       00000000
	VFTA[24]       00000000
	VFTA[25]       00000000
	VFTA[26]       00000000
	VFTA[27]       00000000
	VFTA[28]       00000000
	VFTA[29]       00000000
	VFTA[30]       00000000
	VFTA[31]       00000000
	VFTA[32]       00000000
	VFTA[33]       00000000
	VFTA[34]       00000000
	VFTA[35]       00000000
	VFTA[36]       00000000
	VFTA[37]       00000000
	VFTA[38]       00000000
	VFTA[39]       00000000
	VFTA[40]       00000000
	VFTA[41]       00000000
	VFTA[42]       00000000
	VFTA[43]       00000000
	VFTA[44]       00000000
	VFTA[45]       00000000
	VFTA[46]       00000000
	VFTA[47]       00000000
	VFTA[48]       00000000
	VFTA[49]       00000000
	VFTA[50]       00000000
	VFTA[51]       00000000
	VFTA[52]       00000000
	VFTA[53]       00000000
	VFTA[54]       00000000
	VFTA[55]       00000000
	VFTA[56]       00000000
	VFTA[57]       00000000
	VFTA[58]       00000000
	VFTA[59]       00000000
	VFTA[60]       00000000
	VFTA[61]       00000000
	VFTA[62]       00000000
	VFTA[63]       00000000
	VFTA[64]       00000000
	VFTA[65]       00000000
	VFTA[66]       00000000
	VFTA[67]       00000000
	VFTA[68]       00000000
	VFTA[69]       00000000
	VFTA[70]       00000000
	VFTA[71]       00000000
	VFTA[72]       00000000
	VFTA[73]       00000000
	VFTA[74]       00000000
	VFTA[75]       00000000
	VFTA[76]       00000000
	VFTA[77]       00000000
	VFTA[78]       00000000
	VFTA[79]       00000000
	VFTA[80]       00000000
	VFTA[81]       00000000
	VFTA[82]       00000000
	VFTA[83]       00000000
	VFTA[84]       00000000
	VFTA[85]       00000000
	VFTA[86]       00000000
	VFTA[87]       00000000
	VFTA[88]       00000000
	VFTA[89]       00000000
	VFTA[90]       00000000
	VFTA[91]       00000000
	VFTA[92]       00000000
	VFTA[93]       00000000
	VFTA[94]       00000000
	VFTA[95]       00000000
	VFTA[96]       00000000
	VFTA[97]       00000000
	VFTA[98]       00000000
	VFTA[99]       00000000
	VFTA[100]      00000000
	VFTA[101]      00000000
	VFTA[102]      00000000
	VFTA[103]      00000000
	VFTA[104]      00000000
	VFTA[105]      00000000
	VFTA[106]      00000000
	VFTA[107]      00000000
	VFTA[108]      00000000
	VFTA[109]      00000000
	VFTA[110]      00000000
	VFTA[111]      00000000
	VFTA[112]      00000000
	VFTA[113]      00000000
	VFTA[114]      00000000
	VFTA[115]      00000000
	VFTA[116]      00000000
	VFTA[117]      00000000
	VFTA[118]      00000000
	VFTA[119]      00000000
	VFTA[120]      00000000
	VFTA[121]      00000000
	VFTA[122]      00000000
	VFTA[123]      00000000
	VFTA[124]      00000000
	VFTA[125]      00000000
	VFTA[126]      00000000
	VFTA[127]      00000000
	WUC            00000000
	WUFC           00000000
	WUS            00000000
	MRQC           00000000
	MANC           0022a300
	IPAV           00000000
	MANC2H         00000380
	RSSIM          00000000
	RSSIR          00000000
	WUPL           28167f49
	GCR            0e000000
	GSCL_1         00000000
	GSCL_2         00000000
	GSCL_3         00000000
	GSCL_4         00000000
	FACTPS         01041046
	FWSM           00018044
	RETA[0]        0000008c
	RETA[1]        0000001f
	RETA[2]        00000082
	RETA[3]        00000086
	RETA[4]        0000009f
	RETA[5]        00000066
	RETA[6]        0000005a
	RETA[7]        0000004b
	RETA[8]        0000001e
	RETA[9]        000000af
	RETA[10]       000000dc
	RETA[11]       000000e5
	RETA[12]       0000002d
	RETA[13]       000000aa
	RETA[14]       0000009b
	RETA[15]       0000001c
	RETA[16]       00000053
	RETA[17]       000000e6
	RETA[18]       00000096
	RETA[19]       00000084
	RETA[20]       000000b1
	RETA[21]       0000006b
	RETA[22]       000000b7
	RETA[23]       000000de
	RETA[24]       00000010
	RETA[25]       000000d4
	RETA[26]       000000ef
	RETA[27]       00000034
	RETA[28]       00000038
	RETA[29]       0000000e
	RETA[30]       00000012
	RETA[31]       0000001d
	RETA[32]       00000001
	RETA[33]       0000004b
	RETA[34]       000000e3
	RETA[35]       0000001e
	RETA[36]       0000001b
	RETA[37]       0000009b
	RETA[38]       0000008e
	RETA[39]       00000068
	RETA[40]       00000015
	RETA[41]       000000e2
	RETA[42]       000000c7
	RETA[43]       000000c6
	RETA[44]       00000034
	RETA[45]       0000007a
	RETA[46]       000000b6
	RETA[47]       00000014
	RETA[48]       000000aa
	RETA[49]       0000006f
	RETA[50]       000000fa
	RETA[51]       00000085
	RETA[52]       00000032
	RETA[53]       0000004e
	RETA[54]       0000003f
	RETA[55]       0000004c
	RETA[56]       00000099
	RETA[57]       0000003d
	RETA[58]       000000f2
	RETA[59]       000000ae
	RETA[60]       00000011
	RETA[61]       0000006f
	RETA[62]       000000b7
	RETA[63]       0000000b
	RETA[64]       0000009b
	RETA[65]       00000007
	RETA[66]       0000000a
	RETA[67]       0000009a
	RETA[68]       000000a3
	RETA[69]       00000020
	RETA[70]       000000f3
	RETA[71]       00000084
	RETA[72]       0000004d
	RETA[73]       00000048
	RETA[74]       0000008b
	RETA[75]       00000021
	RETA[76]       000000c7
	RETA[77]       00000053
	RETA[78]       000000a3
	RETA[79]       0000008b
	RETA[80]       000000d4
	RETA[81]       0000004a
	RETA[82]       000000c2
	RETA[83]       000000c0
	RETA[84]       0000003b
	RETA[85]       00000069
	RETA[86]       00000082
	RETA[87]       0000005e
	RETA[88]       00000098
	RETA[89]       0000007a
	RETA[90]       00000017
	RETA[91]       00000084
	RETA[92]       000000ab
	RETA[93]       0000004a
	RETA[94]       000000c7
	RETA[95]       00000014
	RETA[96]       0000001d
	RETA[97]       0000006a
	RETA[98]       00000077
	RETA[99]       00000014
	RETA[100]      000000b9
	RETA[101]      0000000a
	RETA[102]      000000c2
	RETA[103]      0000003d
	RETA[104]      00000055
	RETA[105]      000000aa
	RETA[106]      000000b4
	RETA[107]      00000004
	RETA[108]      00000047
	RETA[109]      00000053
	RETA[110]      000000f7
	RETA[111]      00000016
	RETA[112]      0000008b
	RETA[113]      000000d3
	RETA[114]      000000b2
	RETA[115]      00000074
	RETA[116]      0000003b
	RETA[117]      0000002b
	RETA[118]      0000009d
	RETA[119]      00000016
	RETA[120]      0000002b
	RETA[121]      000000ce
	RETA[122]      0000008e
	RETA[123]      00000044
	RETA[124]      00000027
	RETA[125]      0000004b
	RETA[126]      000000c2
	RETA[127]      00000086
	RSSRK[0]       00000000
	RSSRK[1]       00000000
	RSSRK[2]       00000000
	RSSRK[3]       00000000
	RSSRK[4]       00000000
	RSSRK[5]       00000000
	RSSRK[6]       00000000
	RSSRK[7]       00000000
	RSSRK[8]       00000000
	RSSRK[9]       00000000
	RSSRK[10]      00000000
	RSSRK[11]      00000000
	RSSRK[12]      00000000
	RSSRK[13]      00000000
	RSSRK[14]      00000000
	RSSRK[15]      00000000
	RSSRK[16]      00000000
	RSSRK[17]      00000000
	RSSRK[18]      00000000
	RSSRK[19]      00000000
	RSSRK[20]      00000000
	RSSRK[21]      00000000
	RSSRK[22]      00000000
	RSSRK[23]      00000000
	RSSRK[24]      00000000
	RSSRK[25]      00000000
	RSSRK[26]      00000000
	RSSRK[27]      00000000
	RSSRK[28]      00000000
	RSSRK[29]      00000000
	RSSRK[30]      00000000
	RSSRK[31]      00000000
	RSSRK[32]      00000000
	RSSRK[33]      00000000
	RSSRK[34]      00000000
	RSSRK[35]      00000000
	RSSRK[36]      00000000
	RSSRK[37]      00000000
	RSSRK[38]      00000000
	RSSRK[39]      00000000
	FFLT[0]        00000000
	FFLT[1]        fffc0000
	FFLT[2]        00000000
	FFLT[3]        00000000
	FFLT[4]        00000000
	FFLT[5]        00000000
	FFLT[6]        00000000
	FFLT[7]        00000000
	FFLT[8]        00000000
	FFLT[9]        00000000
	FFLT[10]       00000000
	FFLT[11]       00000000
	HICR           00000109
	FFMT[0]        0000000c
	FFMT[1]        0000000c
	FFMT[2]        0000000d
	FFMT[3]        0000000d
	FFMT[4]        0000000c
	FFMT[5]        0000000c
	FFMT[6]        0000000f
	FFMT[7]        0000000f
	FFMT[8]        00000001
	FFMT[9]        00000001
	FFMT[10]       00000006
	FFMT[11]       00000006
	FFMT[12]       00000004
	FFMT[13]       00000004
	FFMT[14]       0000000c
	FFMT[15]       0000000c
	FFMT[16]       0000000e
	FFMT[17]       0000000e
	FFMT[18]       00000001
	FFMT[19]       00000001
	FFMT[20]       00000001
	FFMT[21]       00000001
	FFMT[22]       00000001
	FFMT[23]       00000001
	FFMT[24]       00000000
	FFMT[25]       00000000
	FFMT[26]       00000001
	FFMT[27]       00000001
	FFMT[28]       00000002
	FFMT[29]       00000002
	FFMT[30]       0000000f
	FFMT[31]       0000000f
	FFMT[32]       00000001
	FFMT[33]       00000001
	FFMT[34]       00000003
	FFMT[35]       00000003
	FFMT[36]       0000000c
	FFMT[37]       0000000c
	FFMT[38]       00000002
	FFMT[39]       00000002
	FFMT[40]       00000008
	FFMT[41]       00000008
	FFMT[42]       0000000f
	FFMT[43]       0000000f
	FFMT[44]       00000008
	FFMT[45]       00000008
	FFMT[46]       00000004
	FFMT[47]       00000004
	FFMT[48]       00000006
	FFMT[49]       00000006
	FFMT[50]       00000007
	FFMT[51]       00000007
	FFMT[52]       00000002
	FFMT[53]       00000002
	FFMT[54]       0000000b
	FFMT[55]       0000000b
	FFMT[56]       00000008
	FFMT[57]       00000008
	FFMT[58]       00000003
	FFMT[59]       00000003
	FFMT[60]       00000004
	FFMT[61]       00000004
	FFMT[62]       00000000
	FFMT[63]       00000000
	FFMT[64]       00000001
	FFMT[65]       00000001
	FFMT[66]       0000000e
	FFMT[67]       0000000e
	FFMT[68]       00000007
	FFMT[69]       00000007
	FFMT[70]       0000000b
	FFMT[71]       0000000b
	FFMT[72]       00000006
	FFMT[73]       00000006
	FFMT[74]       00000009
	FFMT[75]       00000009
	FFMT[76]       00000009
	FFMT[77]       00000009
	FFMT[78]       00000009
	FFMT[79]       00000009
	FFMT[80]       0000000f
	FFMT[81]       0000000f
	FFMT[82]       00000009
	FFMT[83]       00000009
	FFMT[84]       0000000a
	FFMT[85]       0000000a
	FFMT[86]       00000000
	FFMT[87]       00000000
	FFMT[88]       0000000b
	FFMT[89]       0000000b
	FFMT[90]       00000003
	FFMT[91]       00000003
	FFMT[92]       00000001
	FFMT[93]       00000001
	FFMT[94]       00000004
	FFMT[95]       00000004
	FFMT[96]       0000000b
	FFMT[97]       0000000b
	FFMT[98]       0000000c
	FFMT[99]       0000000c
	FFMT[100]      0000000a
	FFMT[101]      0000000a
	FFMT[102]      00000009
	FFMT[103]      00000009
	FFMT[104]      00000000
	FFMT[105]      00000000
	FFMT[106]      00000003
	FFMT[107]      00000003
	FFMT[108]      00000006
	FFMT[109]      00000006
	FFMT[110]      00000008
	FFMT[111]      00000008
	FFMT[112]      0000000e
	FFMT[113]      0000000e
	FFMT[114]      00000007
	FFMT[115]      00000007
	FFMT[116]      0000000c
	FFMT[117]      0000000c
	FFMT[118]      00000007
	FFMT[119]      00000007
	FFMT[120]      00000009
	FFMT[121]      00000009
	FFMT[122]      00000001
	FFMT[123]      00000001
	FFMT[124]      00000001
	FFMT[125]      00000001
	FFMT[126]      0000000f
	FFMT[127]      0000000f
	FFVT[0]        69386efe
	FFVT[1]        69386efe
	FFVT[2]        47dac1bd
	FFVT[3]        47dac1bd
	FFVT[4]        0af977e3
	FFVT[5]        0af977e3
	FFVT[6]        0bf35fcd
	FFVT[7]        0bf35fcd
	FFVT[8]        396325cb
	FFVT[9]        396325cb
	FFVT[10]       45fb2966
	FFVT[11]       45fb2966
	FFVT[12]       85fe3e31
	FFVT[13]       85fe3e31
	FFVT[14]       e6b90940
	FFVT[15]       e6b90940
	FFVT[16]       fcf5c382
	FFVT[17]       fcf5c382
	FFVT[18]       68b90289
	FFVT[19]       68b90289
	FFVT[20]       0fada5ed
	FFVT[21]       0fada5ed
	FFVT[22]       67f87890
	FFVT[23]       67f87890
	FFVT[24]       2dd69d55
	FFVT[25]       2dd69d55
	FFVT[26]       0f78a7b0
	FFVT[27]       0f78a7b0
	FFVT[28]       138d13f7
	FFVT[29]       138d13f7
	FFVT[30]       e302400a
	FFVT[31]       e302400a
	FFVT[32]       bc8ebaf7
	FFVT[33]       bc8ebaf7
	FFVT[34]       96fe79fb
	FFVT[35]       96fe79fb
	FFVT[36]       df5aa33b
	FFVT[37]       df5aa33b
	FFVT[38]       91212c9e
	FFVT[39]       91212c9e
	FFVT[40]       71c517b4
	FFVT[41]       71c517b4
	FFVT[42]       0bb6697f
	FFVT[43]       0bb6697f
	FFVT[44]       63018c23
	FFVT[45]       63018c23
	FFVT[46]       48a35d54
	FFVT[47]       48a35d54
	FFVT[48]       95f4d375
	FFVT[49]       95f4d375
	FFVT[50]       4699c679
	FFVT[51]       4699c679
	FFVT[52]       06e7adde
	FFVT[53]       06e7adde
	FFVT[54]       e31f1b6d
	FFVT[55]       e31f1b6d
	FFVT[56]       888919d6
	FFVT[57]       888919d6
	FFVT[58]       4751a142
	FFVT[59]       4751a142
	FFVT[60]       676fef06
	FFVT[61]       676fef06
	FFVT[62]       792d0e82
	FFVT[63]       792d0e82
	FFVT[64]       1066713d
	FFVT[65]       1066713d
	FFVT[66]       8f55fa4d
	FFVT[67]       8f55fa4d
	FFVT[68]       5fe46f1a
	FFVT[69]       5fe46f1a
	FFVT[70]       cacbc51e
	FFVT[71]       cacbc51e
	FFVT[72]       04470301
	FFVT[73]       04470301
	FFVT[74]       6b3dfea9
	FFVT[75]       6b3dfea9
	FFVT[76]       bd00be00
	FFVT[77]       bd00be00
	FFVT[78]       7079cb0c
	FFVT[79]       7079cb0c
	FFVT[80]       e7180acc
	FFVT[81]       e7180acc
	FFVT[82]       25755bec
	FFVT[83]       25755bec
	FFVT[84]       bcdd8914
	FFVT[85]       bcdd8914
	FFVT[86]       9ed3128d
	FFVT[87]       9ed3128d
	FFVT[88]       dc48587b
	FFVT[89]       dc48587b
	FFVT[90]       e9755ebf
	FFVT[91]       e9755ebf
	FFVT[92]       9ff23883
	FFVT[93]       9ff23883
	FFVT[94]       52d8233d
	FFVT[95]       52d8233d
	FFVT[96]       cdcf21c0
	FFVT[97]       cdcf21c0
	FFVT[98]       9069a69f
	FFVT[99]       9069a69f
	FFVT[100]      b52c57f5
	FFVT[101]      b52c57f5
	FFVT[102]      42977681
	FFVT[103]      42977681
	FFVT[104]      ab8b671a
	FFVT[105]      ab8b671a
	FFVT[106]      4edc0c8b
	FFVT[107]      4edc0c8b
	FFVT[108]      f41c47f0
	FFVT[109]      f41c47f0
	FFVT[110]      ab4edb12
	FFVT[111]      ab4edb12
	FFVT[112]      c096a36f
	FFVT[113]      c096a36f
	FFVT[114]      ed46c26a
	FFVT[115]      ed46c26a
	FFVT[116]      aca39e0b
	FFVT[117]      aca39e0b
	FFVT[118]      e01ed8b5
	FFVT[119]      e01ed8b5
	FFVT[120]      604c1ef5
	FFVT[121]      604c1ef5
	FFVT[122]      0dbbfeae
	FFVT[123]      0dbbfeae
	FFVT[124]      9478dbb7
	FFVT[125]      9478dbb7
	FFVT[126]      f95cfa23
	FFVT[127]      f95cfa23



^ permalink raw reply

* [PATCH] rtnetlink: make SR-IOV VF interface symmetric
From: Chris Wright @ 2010-05-15  3:14 UTC (permalink / raw)
  To: davem, kaber, mitch.a.williams; +Cc: arnd, scofeldm, shemminger, netdev

Now we have a set of nested attributes:

  IFLA_VFINFO_LIST (NESTED)
    IFLA_VF_INFO (NESTED)
      IFLA_VF_MAC
      IFLA_VF_VLAN
      IFLA_VF_TX_RATE

This allows a single set to operate on multiple attributes if desired.
Among other things, it means a dump can be replayed to set state.

The current interface has yet to be released, so this seems like
something to consider for 2.6.34.

Signed-off-by: Chris Wright <chrisw@sous-sol.org
---

Stephen, I'll send the iproute2 update as well

 include/linux/if_link.h |   23 ++++++-
 net/core/rtnetlink.c    |  159 ++++++++++++++++++++++++++++++++--------------
 2 files changed, 129 insertions(+), 53 deletions(-)

diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index c9bf92c..d94963b 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -79,10 +79,7 @@ enum {
 	IFLA_NET_NS_PID,
 	IFLA_IFALIAS,
 	IFLA_NUM_VF,		/* Number of VFs if device is SR-IOV PF */
-	IFLA_VF_MAC,		/* Hardware queue specific attributes */
-	IFLA_VF_VLAN,
-	IFLA_VF_TX_RATE,	/* TX Bandwidth Allocation */
-	IFLA_VFINFO,
+	IFLA_VFINFO_LIST,
 	__IFLA_MAX
 };
 
@@ -203,6 +200,24 @@ enum macvlan_mode {
 
 /* SR-IOV virtual function managment section */
 
+enum {
+	IFLA_VF_INFO_UNSPEC,
+	IFLA_VF_INFO,
+	__IFLA_VF_INFO_MAX,
+};
+
+#define IFLA_VF_INFO_MAX (__IFLA_VF_INFO_MAX - 1)
+
+enum {
+	IFLA_VF_UNSPEC,
+	IFLA_VF_MAC,		/* Hardware queue specific attributes */
+	IFLA_VF_VLAN,
+	IFLA_VF_TX_RATE,	/* TX Bandwidth Allocation */
+	__IFLA_VF_MAX,
+};
+
+#define IFLA_VF_MAX (__IFLA_VF_MAX - 1)
+
 struct ifla_vf_mac {
 	__u32 vf;
 	__u8 mac[32]; /* MAX_ADDR_LEN */
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index fe776c9..074afcd 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -602,12 +602,19 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a,
 	a->tx_compressed = b->tx_compressed;
 };
 
+/* All VF info */
 static inline int rtnl_vfinfo_size(const struct net_device *dev)
 {
-	if (dev->dev.parent && dev_is_pci(dev->dev.parent))
-		return dev_num_vf(dev->dev.parent) *
-			sizeof(struct ifla_vf_info);
-	else
+	if (dev->dev.parent && dev_is_pci(dev->dev.parent)) {
+		
+		int num_vfs = dev_num_vf(dev->dev.parent);
+		size_t size = nlmsg_total_size(sizeof(struct nlattr));
+		size += nlmsg_total_size(num_vfs * sizeof(struct nlattr));
+		size += num_vfs * (sizeof(struct ifla_vf_mac) +
+				  sizeof(struct ifla_vf_vlan) +
+				  sizeof(struct ifla_vf_tx_rate));
+		return size;
+	} else
 		return 0;
 }
 
@@ -629,7 +636,7 @@ static inline size_t if_nlmsg_size(const struct net_device *dev)
 	       + nla_total_size(1) /* IFLA_OPERSTATE */
 	       + nla_total_size(1) /* IFLA_LINKMODE */
 	       + nla_total_size(4) /* IFLA_NUM_VF */
-	       + nla_total_size(rtnl_vfinfo_size(dev)) /* IFLA_VFINFO */
+	       + rtnl_vfinfo_size(dev) /* IFLA_VFINFO_LIST */
 	       + rtnl_link_get_size(dev); /* IFLA_LINKINFO */
 }
 
@@ -700,14 +707,37 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
 
 	if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) {
 		int i;
-		struct ifla_vf_info ivi;
 
-		NLA_PUT_U32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent));
-		for (i = 0; i < dev_num_vf(dev->dev.parent); i++) {
+		struct nlattr *vfinfo, *vf;
+		int num_vfs = dev_num_vf(dev->dev.parent);
+
+		NLA_PUT_U32(skb, IFLA_NUM_VF, num_vfs);
+		vfinfo = nla_nest_start(skb, IFLA_VFINFO_LIST);
+		if (!vfinfo)
+			goto nla_put_failure;
+		for (i = 0; i < num_vfs; i++) {
+			struct ifla_vf_info ivi;
+			struct ifla_vf_mac vf_mac;
+			struct ifla_vf_vlan vf_vlan;
+			struct ifla_vf_tx_rate vf_tx_rate;
 			if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi))
 				break;
-			NLA_PUT(skb, IFLA_VFINFO, sizeof(ivi), &ivi);
+			vf_mac.vf = vf_vlan.vf = vf_tx_rate.vf = ivi.vf;
+			memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac));
+			vf_vlan.vlan = ivi.vlan;
+			vf_vlan.qos = ivi.qos;
+			vf_tx_rate.rate = ivi.tx_rate;
+			vf = nla_nest_start(skb, IFLA_VF_INFO);
+			if (!vf) {
+				nla_nest_cancel(skb, vfinfo);
+				goto nla_put_failure;
+			}
+			NLA_PUT(skb, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac);
+			NLA_PUT(skb, IFLA_VF_VLAN, sizeof(vf_vlan), &vf_vlan);
+			NLA_PUT(skb, IFLA_VF_TX_RATE, sizeof(vf_tx_rate), &vf_tx_rate);
+			nla_nest_end(skb, vf);
 		}
+		nla_nest_end(skb, vfinfo);
 	}
 	if (dev->rtnl_link_ops) {
 		if (rtnl_link_fill(skb, dev) < 0)
@@ -769,12 +799,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
 	[IFLA_LINKINFO]		= { .type = NLA_NESTED },
 	[IFLA_NET_NS_PID]	= { .type = NLA_U32 },
 	[IFLA_IFALIAS]	        = { .type = NLA_STRING, .len = IFALIASZ-1 },
-	[IFLA_VF_MAC]		= { .type = NLA_BINARY,
-				    .len = sizeof(struct ifla_vf_mac) },
-	[IFLA_VF_VLAN]		= { .type = NLA_BINARY,
-				    .len = sizeof(struct ifla_vf_vlan) },
-	[IFLA_VF_TX_RATE]	= { .type = NLA_BINARY,
-				    .len = sizeof(struct ifla_vf_tx_rate) },
+	[IFLA_VFINFO_LIST]	= {. type = NLA_NESTED },
 };
 EXPORT_SYMBOL(ifla_policy);
 
@@ -783,6 +808,19 @@ static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
 	[IFLA_INFO_DATA]	= { .type = NLA_NESTED },
 };
 
+static const struct nla_policy ifla_vfinfo_policy[IFLA_VF_INFO_MAX+1] = {
+	[IFLA_VF_INFO]		= { .type = NLA_NESTED },
+};
+
+static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = {
+	[IFLA_VF_MAC]		= { .type = NLA_BINARY,
+				    .len = sizeof(struct ifla_vf_mac) },
+	[IFLA_VF_VLAN]		= { .type = NLA_BINARY,
+				    .len = sizeof(struct ifla_vf_vlan) },
+	[IFLA_VF_TX_RATE]	= { .type = NLA_BINARY,
+				    .len = sizeof(struct ifla_vf_tx_rate) },
+};
+
 struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[])
 {
 	struct net *net;
@@ -812,6 +850,52 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[])
 	return 0;
 }
 
+static int do_setvfinfo(struct net_device *dev, struct nlattr *attr)
+{
+	int rem, err = -EINVAL;
+	struct nlattr *vf;
+	const struct net_device_ops *ops = dev->netdev_ops;
+	
+	nla_for_each_nested(vf, attr, rem) {
+		switch (nla_type(vf)) {
+		case IFLA_VF_MAC: {
+			struct ifla_vf_mac *ivm;
+			ivm = nla_data(vf);
+			err = -EOPNOTSUPP;
+			if (ops->ndo_set_vf_mac)
+				err = ops->ndo_set_vf_mac(dev, ivm->vf,
+							  ivm->mac);
+			break;
+		}
+		case IFLA_VF_VLAN: {
+			struct ifla_vf_vlan *ivv;
+			ivv = nla_data(vf);
+			err = -EOPNOTSUPP;
+			if (ops->ndo_set_vf_vlan)
+				err = ops->ndo_set_vf_vlan(dev, ivv->vf,
+							   ivv->vlan,
+							   ivv->qos);
+			break;
+		}
+		case IFLA_VF_TX_RATE: {
+			struct ifla_vf_tx_rate *ivt;
+			ivt = nla_data(vf);
+			err = -EOPNOTSUPP;
+			if (ops->ndo_set_vf_tx_rate)
+				err = ops->ndo_set_vf_tx_rate(dev, ivt->vf,
+							      ivt->rate);
+			break;
+		}
+		default:
+			err = -EINVAL;
+			break;
+		}
+		if (err)
+			break;
+	}
+	return err;
+}
+
 static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
 		      struct nlattr **tb, char *ifname, int modified)
 {
@@ -942,40 +1026,17 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
 		write_unlock_bh(&dev_base_lock);
 	}
 
-	if (tb[IFLA_VF_MAC]) {
-		struct ifla_vf_mac *ivm;
-		ivm = nla_data(tb[IFLA_VF_MAC]);
-		err = -EOPNOTSUPP;
-		if (ops->ndo_set_vf_mac)
-			err = ops->ndo_set_vf_mac(dev, ivm->vf, ivm->mac);
-		if (err < 0)
-			goto errout;
-		modified = 1;
-	}
-
-	if (tb[IFLA_VF_VLAN]) {
-		struct ifla_vf_vlan *ivv;
-		ivv = nla_data(tb[IFLA_VF_VLAN]);
-		err = -EOPNOTSUPP;
-		if (ops->ndo_set_vf_vlan)
-			err = ops->ndo_set_vf_vlan(dev, ivv->vf,
-						   ivv->vlan,
-						   ivv->qos);
-		if (err < 0)
-			goto errout;
-		modified = 1;
-	}
-	err = 0;
-
-	if (tb[IFLA_VF_TX_RATE]) {
-		struct ifla_vf_tx_rate *ivt;
-		ivt = nla_data(tb[IFLA_VF_TX_RATE]);
-		err = -EOPNOTSUPP;
-		if (ops->ndo_set_vf_tx_rate)
-			err = ops->ndo_set_vf_tx_rate(dev, ivt->vf, ivt->rate);
-		if (err < 0)
-			goto errout;
-		modified = 1;
+	if (tb[IFLA_VFINFO_LIST]) {
+		struct nlattr *attr;
+		int rem;
+		nla_for_each_nested(attr, tb[IFLA_VFINFO_LIST], rem) {
+			if (nla_type(attr) != IFLA_VF_INFO)
+				goto errout;
+			err = do_setvfinfo(dev, attr);
+			if (err < 0)
+				goto errout;
+			modified = 1;
+		}
 	}
 	err = 0;
 
-- 
1.6.5.2


^ permalink raw reply related

* RE: why get different number of MSI-X vector for broadcom bnx2x every time
From: Jon Zhou @ 2010-05-15  3:12 UTC (permalink / raw)
  To: Dmitry Kravkov, netdev
In-Reply-To: <2DFD360E328B3941911E6D28B085D990107B83BB47@SJEXCHCCR01.corp.ad.broadcom.com>


hi Dmitry
the system,is the kernel(2.6.27) or the hardware?
thanks!
jon
________________________________________
From: Dmitry Kravkov [dmitry@broadcom.com]
Sent: Saturday, May 15, 2010 4:02 AM
To: Jon Zhou; netdev
Subject: RE: why get different number of MSI-X vector for broadcom bnx2x every time

Hi

Your system (from the log below) allowed bnx2x to use only 4 MSI-X vectors instead of 16 required by the driver.

Regards,
Dmitry

-----Original Message-----
From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org] On Behalf Of Jon Zhou
Sent: Friday, May 14, 2010 11:02 AM
To: netdev
Subject: why get different number of MSI-X vector for broadcom bnx2x every time

hi there:

bnx2x_enable_msix :

...
rc = pci_enable_msix(bp->pdev, &bp->msix_table[0],
                             BNX2X_NUM_QUEUES(bp) + offset);

        /*
         * reconfigure number of tx/rx queues according to available
         * MSI-X vectors
         */
        if (rc >= BNX2X_MIN_MSIX_VEC_CNT) {
                /* vectors available for FP */
                int fp_vec = rc - BNX2X_MSIX_VEC_FP_START;


sometimes I can run up the driver with 4 queues but most of time I can only get 2 queues
why?

May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_set_num_queues:8053(eth5)]set number of queues to 15
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7544(eth5)]msix_table[0].entry = 0 (slowpath)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7549(eth5)]msix_table[1].entry = 1 (CNIC)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[2].entry = 2 (fastpath #0)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[3].entry = 3 (fastpath #1)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[4].entry = 4 (fastpath #2)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[5].entry = 5 (fastpath #3)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[6].entry = 6 (fastpath #4)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[7].entry = 7 (fastpath #5)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[8].entry = 8 (fastpath #6)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[9].entry = 9 (fastpath #7)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[10].entry = 10 (fastpath #8)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[11].entry = 11 (fastpath #9)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[12].entry = 12 (fastpath #10)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[13].entry = 13 (fastpath #11)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[14].entry = 14 (fastpath #12)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[15].entry = 15 (fastpath #13)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7556(eth5)]msix_table[16].entry = 16 (fastpath #14)
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7571(eth5)]Trying to use less MSI-X vectors: 4
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_enable_msix:7584(eth5)]New queue configuration set: 2
May 14 01:40:16 ibm-bc-54 kernel: bnx2x: eth5: using MSI-X  IRQs: sp 4321  fp[0] 4319 ... fp[1] 4318
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_nic_init:6067(eth5)]queue[0]:  bnx2x_init_sb(ffff8803e6810780,ffff8803f9c4f000)  cl_id 0  sb 1  cos 0
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_nic_init:6067(eth5)]queue[1]:  bnx2x_init_sb(ffff8803e6810780,ffff8803fb006000)  cl_id 1  sb 2  cos 0
May 14 01:40:16 ibm-bc-54 kernel: [bnx2x_init_rx_rings:5305(eth5)]mtu 1500  rx_buf_size 1650

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [net-next-2.6 V8 PATCH 1/2] Add netlink support for virtual port management (was iovnl)
From: Chris Wright @ 2010-05-15  3:11 UTC (permalink / raw)
  To: Scott Feldman; +Cc: davem, netdev, chrisw, arnd, kaber
In-Reply-To: <20100515010429.21260.46950.stgit@savbu-pc100.cisco.com>

* Scott Feldman (scofeldm@cisco.com) wrote:
> From: Scott Feldman <scofeldm@cisco.com>
> 
> Add new netdev ops ndo_{set|get}_vf_port to allow setting of
> port-profile on a netdev interface.  Extends netlink socket RTM_SETLINK/
> RTM_GETLINK with two new sub msgs called IFLA_VF_PORTS and IFLA_PORT_SELF
> (added to end of IFLA_cmd list).  These are both nested atrtibutes
> using this layout:
> 
>               [IFLA_NUM_VF]
>               [IFLA_VF_PORTS]
>                       [IFLA_VF_PORT]
>                               [IFLA_PORT_*], ...
>                       [IFLA_VF_PORT]
>                               [IFLA_PORT_*], ...
>                       ...
>               [IFLA_PORT_SELF]
>                       [IFLA_PORT_*], ...
> 
> These attributes are design to be set and get symmetrically.  VF_PORTS
> is a list of VF_PORTs, one for each VF, when dealing with an SR-IOV
> device.  PORT_SELF is for the PF of the SR-IOV device, in case it wants
> to also have a port-profile, or for the case where the VF==PF, like in
> enic patch 2/2 of this patch set.
> 
> A port-profile is used to configure/enable the external switch virtual port
> backing the netdev interface, not to configure the host-facing side of the
> netdev.  A port-profile is an identifier known to the switch.  How port-
> profiles are installed on the switch or how available port-profiles are
> made know to the host is outside the scope of this patch.
> 
> There are two types of port-profiles specs in the netlink msg.  The first spec
> is for 802.1Qbg (pre-)standard, VDP protocol.  The second spec is for devices
> that run a similar protocol as VDP but in firmware, thus hiding the protocol
> details.  In either case, the specs have much in common and makes sense to
> define the netlink msg as the union of the two specs.  For example, both specs
> have a notition of associating/deassociating a port-profile.  And both specs
> require some information from the hypervisor manager, such as client port
> instance ID.
> 
> The general flow is the port-profile is applied to a host netdev interface
> using RTM_SETLINK, the receiver of the RTM_SETLINK msg communicates with the
> switch, and the switch virtual port backing the host netdev interface is
> configured/enabled based on the settings defined by the port-profile.  What
> those settings comprise, and how those settings are managed is again
> outside the scope of this patch, since this patch only deals with the
> first step in the flow.
> 
> Signed-off-by: Scott Feldman <scofeldm@cisco.com>
> Signed-off-by: Roopa Prabhu<roprabhu@cisco.com>

Assuming the SR-IOV VFINFO changes go in there will be some minor patch
conflicts to be sorted out.

Acked-by: Chris Wright <chrisw@redhat.com>

^ permalink raw reply

* [patch] pm_qos update fixing mmotm 2010-05-11 -dies in pm_qos_update_request()
From: mgross @ 2010-05-15  2:19 UTC (permalink / raw)
  To: rjw, Valdis.Kletnieks, mgross
  Cc: akpm, davem, linux-kernel, e1000-devel, netdev, linux-pm

I apologize for the goofy email address.  

The following is a fix for the crash reported by Valdis.

The problem was that the original pm_qos silently fails when a request
update is passed to a parameter that has not been added to the list
yet.  It seems that the e1000e is doing this.  This update restores this
behavior.

I need to think about how to better handle such abuse, but for now this
restores the original behavior.

Signed-off-by: markgross <markgross@thegnar.org>
--mgross


>From 66700dc26ab7582bc7351541ba2e6241cc4b4144 Mon Sep 17 00:00:00 2001
From: mgross <mgross@mgross-desktop.(none)>
Date: Fri, 14 May 2010 19:05:44 -0700
Subject: [PATCH] PM QOS update
 This patch changes the string based list management to a handle base
 implementation to help with the hot path use of pm-qos, it also renames
 much of the API to use "request" as opposed to "requirement" that was
 used in the initial implementation.  I did this because request more
 accurately represents what it actually does.

Also, I added a string based ABI for users wanting to use a string
interface.  So if the user writes 0xDDDDDDDD formatted hex it will be
accepted by the interface.  (someone asked me for it and I don't think
it hurts anything.)

This patch updates some documentation input I got from Randy.

This version handles a use case where pm_qos update requests need to
silently not fail if the update is being sent to a handle that is null.
This is what happened in the initial version of pm-qos if you used a
string that wasn't in the list.

Signed-off-by: markgross <mgross@linux.intel.com>
---
 Documentation/power/pm_qos_interface.txt |   48 ++++---
 drivers/acpi/processor_idle.c            |    2 +-
 drivers/cpuidle/governors/ladder.c       |    2 +-
 drivers/cpuidle/governors/menu.c         |    2 +-
 drivers/net/e1000e/netdev.c              |   22 ++--
 drivers/net/igbvf/netdev.c               |    6 +-
 drivers/net/wireless/ipw2x00/ipw2100.c   |   11 +-
 include/linux/netdevice.h                |    4 +
 include/linux/pm_qos_params.h            |   14 +-
 include/sound/pcm.h                      |    3 +-
 kernel/pm_qos_params.c                   |  217 +++++++++++++++---------------
 net/mac80211/mlme.c                      |    2 +-
 sound/core/pcm.c                         |    3 -
 sound/core/pcm_native.c                  |   14 +-
 14 files changed, 179 insertions(+), 171 deletions(-)

diff --git a/Documentation/power/pm_qos_interface.txt b/Documentation/power/pm_qos_interface.txt
index c40866e..bfed898 100644
--- a/Documentation/power/pm_qos_interface.txt
+++ b/Documentation/power/pm_qos_interface.txt
@@ -18,44 +18,46 @@ and pm_qos_params.h.  This is done because having the available parameters
 being runtime configurable or changeable from a driver was seen as too easy to
 abuse.
 
-For each parameter a list of performance requirements is maintained along with
+For each parameter a list of performance requests is maintained along with
 an aggregated target value.  The aggregated target value is updated with
-changes to the requirement list or elements of the list.  Typically the
-aggregated target value is simply the max or min of the requirement values held
+changes to the request list or elements of the list.  Typically the
+aggregated target value is simply the max or min of the request values held
 in the parameter list elements.
 
 From kernel mode the use of this interface is simple:
-pm_qos_add_requirement(param_id, name, target_value):
-Will insert a named element in the list for that identified PM_QOS parameter
-with the target value.  Upon change to this list the new target is recomputed
-and any registered notifiers are called only if the target value is now
-different.
 
-pm_qos_update_requirement(param_id, name, new_target_value):
-Will search the list identified by the param_id for the named list element and
-then update its target value, calling the notification tree if the aggregated
-target is changed.  with that name is already registered.
+handle = pm_qos_add_request(param_class, target_value):
+Will insert an element into the list for that identified PM_QOS class with the
+target value.  Upon change to this list the new target is recomputed and any
+registered notifiers are called only if the target value is now different.
+Clients of pm_qos need to save the returned handle.
 
-pm_qos_remove_requirement(param_id, name):
-Will search the identified list for the named element and remove it, after
-removal it will update the aggregate target and call the notification tree if
-the target was changed as a result of removing the named requirement.
+void pm_qos_update_request(handle, new_target_value):
+Will update the list element pointed to by the handle with the new target value
+and recompute the new aggregated target, calling the notification tree if the
+target is changed.
+
+void pm_qos_remove_request(handle):
+Will remove the element.  After removal it will update the aggregate target and
+call the notification tree if the target was changed as a result of removing
+the request.
 
 
 From user mode:
-Only processes can register a pm_qos requirement.  To provide for automatic
-cleanup for process the interface requires the process to register its
-parameter requirements in the following way:
+Only processes can register a pm_qos request.  To provide for automatic
+cleanup of a process, the interface requires the process to register its
+parameter requests in the following way:
 
 To register the default pm_qos target for the specific parameter, the process
 must open one of /dev/[cpu_dma_latency, network_latency, network_throughput]
 
 As long as the device node is held open that process has a registered
-requirement on the parameter.  The name of the requirement is "process_<PID>"
-derived from the current->pid from within the open system call.
+request on the parameter.
 
-To change the requested target value the process needs to write a s32 value to
-the open device node.  This translates to a pm_qos_update_requirement call.
+To change the requested target value the process needs to write an s32 value to
+the open device node.  Alternatively the user mode program could write a hex
+string for the value using 10 char long format e.g. "0x12345678".  This
+translates to a pm_qos_update_request call.
 
 To remove the user mode request for a target value simply close the device
 node.
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 5939e7f..c3817e1 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -698,7 +698,7 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
 		   "max_cstate:              C%d\n"
 		   "maximum allowed latency: %d usec\n",
 		   pr->power.state ? pr->power.state - pr->power.states : 0,
-		   max_cstate, pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY));
+		   max_cstate, pm_qos_request(PM_QOS_CPU_DMA_LATENCY));
 
 	seq_puts(seq, "states:\n");
 
diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c
index 1c1ceb4..12c9890 100644
--- a/drivers/cpuidle/governors/ladder.c
+++ b/drivers/cpuidle/governors/ladder.c
@@ -67,7 +67,7 @@ static int ladder_select_state(struct cpuidle_device *dev)
 	struct ladder_device *ldev = &__get_cpu_var(ladder_devices);
 	struct ladder_device_state *last_state;
 	int last_residency, last_idx = ldev->last_state_idx;
-	int latency_req = pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY);
+	int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
 
 	/* Special case when user has set very strict latency requirement */
 	if (unlikely(latency_req == 0)) {
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index f8e57c6..b81ad9c 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -182,7 +182,7 @@ static u64 div_round64(u64 dividend, u32 divisor)
 static int menu_select(struct cpuidle_device *dev)
 {
 	struct menu_device *data = &__get_cpu_var(menu_devices);
-	int latency_req = pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY);
+	int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
 	int i;
 	int multiplier;
 
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index dbf8178..d5d55c6 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -2524,12 +2524,12 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
 			 * excessive C-state transition latencies result in
 			 * dropped transactions.
 			 */
-			pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY,
-						  adapter->netdev->name, 55);
+			pm_qos_update_request(
+				adapter->netdev->pm_qos_req, 55);
 		} else {
-			pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY,
-						  adapter->netdev->name,
-						  PM_QOS_DEFAULT_VALUE);
+			pm_qos_update_request(
+				adapter->netdev->pm_qos_req,
+				PM_QOS_DEFAULT_VALUE);
 		}
 	}
 
@@ -2824,8 +2824,8 @@ int e1000e_up(struct e1000_adapter *adapter)
 
 	/* DMA latency requirement to workaround early-receive/jumbo issue */
 	if (adapter->flags & FLAG_HAS_ERT)
-		pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY,
-		                       adapter->netdev->name,
+		adapter->netdev->pm_qos_req =
+			pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
 				       PM_QOS_DEFAULT_VALUE);
 
 	/* hardware has been reset, we need to reload some things */
@@ -2887,9 +2887,11 @@ void e1000e_down(struct e1000_adapter *adapter)
 	e1000_clean_tx_ring(adapter);
 	e1000_clean_rx_ring(adapter);
 
-	if (adapter->flags & FLAG_HAS_ERT)
-		pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
-		                          adapter->netdev->name);
+	if (adapter->flags & FLAG_HAS_ERT) {
+		pm_qos_remove_request(
+			      adapter->netdev->pm_qos_req);
+		adapter->netdev->pm_qos_req = NULL;
+	}
 
 	/*
 	 * TODO: for power management, we could drop the link and
diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c
index 1b1edad..f16e981 100644
--- a/drivers/net/igbvf/netdev.c
+++ b/drivers/net/igbvf/netdev.c
@@ -48,6 +48,7 @@
 #define DRV_VERSION "1.0.0-k0"
 char igbvf_driver_name[] = "igbvf";
 const char igbvf_driver_version[] = DRV_VERSION;
+struct pm_qos_request_list *igbvf_driver_pm_qos_req;
 static const char igbvf_driver_string[] =
 				"Intel(R) Virtual Function Network Driver";
 static const char igbvf_copyright[] = "Copyright (c) 2009 Intel Corporation.";
@@ -2899,7 +2900,7 @@ static int __init igbvf_init_module(void)
 	printk(KERN_INFO "%s\n", igbvf_copyright);
 
 	ret = pci_register_driver(&igbvf_driver);
-	pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, igbvf_driver_name,
+	igbvf_driver_pm_qos_req = pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
 	                       PM_QOS_DEFAULT_VALUE);
 
 	return ret;
@@ -2915,7 +2916,8 @@ module_init(igbvf_init_module);
 static void __exit igbvf_exit_module(void)
 {
 	pci_unregister_driver(&igbvf_driver);
-	pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, igbvf_driver_name);
+	pm_qos_remove_request(igbvf_driver_pm_qos_req);
+	igbvf_driver_pm_qos_req = NULL;
 }
 module_exit(igbvf_exit_module);
 
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index 9b72c45..2b05fe5 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -174,6 +174,8 @@ that only one external action is invoked at a time.
 #define DRV_DESCRIPTION	"Intel(R) PRO/Wireless 2100 Network Driver"
 #define DRV_COPYRIGHT	"Copyright(c) 2003-2006 Intel Corporation"
 
+struct pm_qos_request_list *ipw2100_pm_qos_req;
+
 /* Debugging stuff */
 #ifdef CONFIG_IPW2100_DEBUG
 #define IPW2100_RX_DEBUG	/* Reception debugging */
@@ -1739,7 +1741,7 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
 	/* the ipw2100 hardware really doesn't want power management delays
 	 * longer than 175usec
 	 */
-	pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100", 175);
+	pm_qos_update_request(ipw2100_pm_qos_req, 175);
 
 	/* If the interrupt is enabled, turn it off... */
 	spin_lock_irqsave(&priv->low_lock, flags);
@@ -1887,8 +1889,7 @@ static void ipw2100_down(struct ipw2100_priv *priv)
 	ipw2100_disable_interrupts(priv);
 	spin_unlock_irqrestore(&priv->low_lock, flags);
 
-	pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100",
-			PM_QOS_DEFAULT_VALUE);
+	pm_qos_update_request(ipw2100_pm_qos_req, PM_QOS_DEFAULT_VALUE);
 
 	/* We have to signal any supplicant if we are disassociating */
 	if (associated)
@@ -6669,7 +6670,7 @@ static int __init ipw2100_init(void)
 	if (ret)
 		goto out;
 
-	pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100",
+	ipw2100_pm_qos_req = pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
 			PM_QOS_DEFAULT_VALUE);
 #ifdef CONFIG_IPW2100_DEBUG
 	ipw2100_debug_level = debug;
@@ -6692,7 +6693,7 @@ static void __exit ipw2100_exit(void)
 			   &driver_attr_debug_level);
 #endif
 	pci_unregister_driver(&ipw2100_pci_driver);
-	pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100");
+	pm_qos_remove_request(ipw2100_pm_qos_req);
 }
 
 module_init(ipw2100_init);
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index fa8b476..3857517 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -31,6 +31,7 @@
 #include <linux/if_link.h>
 
 #ifdef __KERNEL__
+#include <linux/pm_qos_params.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
 #include <linux/mm.h>
@@ -711,6 +712,9 @@ struct net_device {
 	 * the interface.
 	 */
 	char			name[IFNAMSIZ];
+
+	struct pm_qos_request_list *pm_qos_req;
+
 	/* device name hash chain */
 	struct hlist_node	name_hlist;
 	/* snmp alias */
diff --git a/include/linux/pm_qos_params.h b/include/linux/pm_qos_params.h
index d74f75e..8ba440e 100644
--- a/include/linux/pm_qos_params.h
+++ b/include/linux/pm_qos_params.h
@@ -14,12 +14,14 @@
 #define PM_QOS_NUM_CLASSES 4
 #define PM_QOS_DEFAULT_VALUE -1
 
-int pm_qos_add_requirement(int qos, char *name, s32 value);
-int pm_qos_update_requirement(int qos, char *name, s32 new_value);
-void pm_qos_remove_requirement(int qos, char *name);
+struct pm_qos_request_list;
 
-int pm_qos_requirement(int qos);
+struct pm_qos_request_list *pm_qos_add_request(int pm_qos_class, s32 value);
+void pm_qos_update_request(struct pm_qos_request_list *pm_qos_req,
+		s32 new_value);
+void pm_qos_remove_request(struct pm_qos_request_list *pm_qos_req);
 
-int pm_qos_add_notifier(int qos, struct notifier_block *notifier);
-int pm_qos_remove_notifier(int qos, struct notifier_block *notifier);
+int pm_qos_request(int pm_qos_class);
+int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier);
+int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier);
 
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 8b611a5..dd76cde 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -29,6 +29,7 @@
 #include <linux/poll.h>
 #include <linux/mm.h>
 #include <linux/bitops.h>
+#include <linux/pm_qos_params.h>
 
 #define snd_pcm_substream_chip(substream) ((substream)->private_data)
 #define snd_pcm_chip(pcm) ((pcm)->private_data)
@@ -365,7 +366,7 @@ struct snd_pcm_substream {
 	int number;
 	char name[32];			/* substream name */
 	int stream;			/* stream (direction) */
-	char latency_id[20];		/* latency identifier */
+	struct pm_qos_request_list *latency_pm_qos_req; /* pm_qos request */
 	size_t buffer_bytes_max;	/* limit ring buffer size */
 	struct snd_dma_buffer dma_buffer;
 	unsigned int dma_buf_id;
diff --git a/kernel/pm_qos_params.c b/kernel/pm_qos_params.c
index 3db49b9..dfa1425 100644
--- a/kernel/pm_qos_params.c
+++ b/kernel/pm_qos_params.c
@@ -2,7 +2,7 @@
  * This module exposes the interface to kernel space for specifying
  * QoS dependencies.  It provides infrastructure for registration of:
  *
- * Dependents on a QoS value : register requirements
+ * Dependents on a QoS value : register requests
  * Watchers of QoS value : get notified when target QoS value changes
  *
  * This QoS design is best effort based.  Dependents register their QoS needs.
@@ -14,19 +14,21 @@
  * timeout: usec <-- currently not used.
  * throughput: kbs (kilo byte / sec)
  *
- * There are lists of pm_qos_objects each one wrapping requirements, notifiers
+ * There are lists of pm_qos_objects each one wrapping requests, notifiers
  *
- * User mode requirements on a QOS parameter register themselves to the
+ * User mode requests on a QOS parameter register themselves to the
  * subsystem by opening the device node /dev/... and writing there request to
  * the node.  As long as the process holds a file handle open to the node the
  * client continues to be accounted for.  Upon file release the usermode
- * requirement is removed and a new qos target is computed.  This way when the
- * requirement that the application has is cleaned up when closes the file
+ * request is removed and a new qos target is computed.  This way when the
+ * request that the application has is cleaned up when closes the file
  * pointer or exits the pm_qos_object will get an opportunity to clean up.
  *
  * Mark Gross <mgross@linux.intel.com>
  */
 
+/*#define DEBUG*/
+
 #include <linux/pm_qos_params.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
@@ -42,25 +44,25 @@
 #include <linux/uaccess.h>
 
 /*
- * locking rule: all changes to requirements or notifiers lists
+ * locking rule: all changes to requests or notifiers lists
  * or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock
  * held, taken with _irqsave.  One lock to rule them all
  */
-struct requirement_list {
+struct pm_qos_request_list {
 	struct list_head list;
 	union {
 		s32 value;
 		s32 usec;
 		s32 kbps;
 	};
-	char *name;
+	int pm_qos_class;
 };
 
 static s32 max_compare(s32 v1, s32 v2);
 static s32 min_compare(s32 v1, s32 v2);
 
 struct pm_qos_object {
-	struct requirement_list requirements;
+	struct pm_qos_request_list requests;
 	struct blocking_notifier_head *notifiers;
 	struct miscdevice pm_qos_power_miscdev;
 	char *name;
@@ -72,7 +74,7 @@ struct pm_qos_object {
 static struct pm_qos_object null_pm_qos;
 static BLOCKING_NOTIFIER_HEAD(cpu_dma_lat_notifier);
 static struct pm_qos_object cpu_dma_pm_qos = {
-	.requirements = {LIST_HEAD_INIT(cpu_dma_pm_qos.requirements.list)},
+	.requests = {LIST_HEAD_INIT(cpu_dma_pm_qos.requests.list)},
 	.notifiers = &cpu_dma_lat_notifier,
 	.name = "cpu_dma_latency",
 	.default_value = 2000 * USEC_PER_SEC,
@@ -82,7 +84,7 @@ static struct pm_qos_object cpu_dma_pm_qos = {
 
 static BLOCKING_NOTIFIER_HEAD(network_lat_notifier);
 static struct pm_qos_object network_lat_pm_qos = {
-	.requirements = {LIST_HEAD_INIT(network_lat_pm_qos.requirements.list)},
+	.requests = {LIST_HEAD_INIT(network_lat_pm_qos.requests.list)},
 	.notifiers = &network_lat_notifier,
 	.name = "network_latency",
 	.default_value = 2000 * USEC_PER_SEC,
@@ -93,8 +95,7 @@ static struct pm_qos_object network_lat_pm_qos = {
 
 static BLOCKING_NOTIFIER_HEAD(network_throughput_notifier);
 static struct pm_qos_object network_throughput_pm_qos = {
-	.requirements =
-		{LIST_HEAD_INIT(network_throughput_pm_qos.requirements.list)},
+	.requests = {LIST_HEAD_INIT(network_throughput_pm_qos.requests.list)},
 	.notifiers = &network_throughput_notifier,
 	.name = "network_throughput",
 	.default_value = 0,
@@ -135,31 +136,34 @@ static s32 min_compare(s32 v1, s32 v2)
 }
 
 
-static void update_target(int target)
+static void update_target(int pm_qos_class)
 {
 	s32 extreme_value;
-	struct requirement_list *node;
+	struct pm_qos_request_list *node;
 	unsigned long flags;
 	int call_notifier = 0;
 
 	spin_lock_irqsave(&pm_qos_lock, flags);
-	extreme_value = pm_qos_array[target]->default_value;
+	extreme_value = pm_qos_array[pm_qos_class]->default_value;
 	list_for_each_entry(node,
-			&pm_qos_array[target]->requirements.list, list) {
-		extreme_value = pm_qos_array[target]->comparitor(
+			&pm_qos_array[pm_qos_class]->requests.list, list) {
+		extreme_value = pm_qos_array[pm_qos_class]->comparitor(
 				extreme_value, node->value);
 	}
-	if (atomic_read(&pm_qos_array[target]->target_value) != extreme_value) {
+	if (atomic_read(&pm_qos_array[pm_qos_class]->target_value) !=
+			extreme_value) {
 		call_notifier = 1;
-		atomic_set(&pm_qos_array[target]->target_value, extreme_value);
-		pr_debug(KERN_ERR "new target for qos %d is %d\n", target,
-			atomic_read(&pm_qos_array[target]->target_value));
+		atomic_set(&pm_qos_array[pm_qos_class]->target_value,
+				extreme_value);
+		pr_debug(KERN_ERR "new target for qos %d is %d\n", pm_qos_class,
+			atomic_read(&pm_qos_array[pm_qos_class]->target_value));
 	}
 	spin_unlock_irqrestore(&pm_qos_lock, flags);
 
 	if (call_notifier)
-		blocking_notifier_call_chain(pm_qos_array[target]->notifiers,
-			(unsigned long) extreme_value, NULL);
+		blocking_notifier_call_chain(
+				pm_qos_array[pm_qos_class]->notifiers,
+					(unsigned long) extreme_value, NULL);
 }
 
 static int register_pm_qos_misc(struct pm_qos_object *qos)
@@ -185,125 +189,113 @@ static int find_pm_qos_object_by_minor(int minor)
 }
 
 /**
- * pm_qos_requirement - returns current system wide qos expectation
+ * pm_qos_request - returns current system wide qos expectation
  * @pm_qos_class: identification of which qos value is requested
  *
  * This function returns the current target value in an atomic manner.
  */
-int pm_qos_requirement(int pm_qos_class)
+int pm_qos_request(int pm_qos_class)
 {
 	return atomic_read(&pm_qos_array[pm_qos_class]->target_value);
 }
-EXPORT_SYMBOL_GPL(pm_qos_requirement);
+EXPORT_SYMBOL_GPL(pm_qos_request);
 
 /**
- * pm_qos_add_requirement - inserts new qos request into the list
+ * pm_qos_add_request - inserts new qos request into the list
  * @pm_qos_class: identifies which list of qos request to us
- * @name: identifies the request
  * @value: defines the qos request
  *
  * This function inserts a new entry in the pm_qos_class list of requested qos
  * performance characteristics.  It recomputes the aggregate QoS expectations
- * for the pm_qos_class of parameters.
+ * for the pm_qos_class of parameters, and returns the pm_qos_request list
+ * element as a handle for use in updating and removal.  Call needs to save
+ * this handle for later use.
  */
-int pm_qos_add_requirement(int pm_qos_class, char *name, s32 value)
+struct pm_qos_request_list *pm_qos_add_request(int pm_qos_class, s32 value)
 {
-	struct requirement_list *dep;
+	struct pm_qos_request_list *dep;
 	unsigned long flags;
 
-	dep = kzalloc(sizeof(struct requirement_list), GFP_KERNEL);
+	dep = kzalloc(sizeof(struct pm_qos_request_list), GFP_KERNEL);
 	if (dep) {
 		if (value == PM_QOS_DEFAULT_VALUE)
 			dep->value = pm_qos_array[pm_qos_class]->default_value;
 		else
 			dep->value = value;
-		dep->name = kstrdup(name, GFP_KERNEL);
-		if (!dep->name)
-			goto cleanup;
+		dep->pm_qos_class = pm_qos_class;
 
 		spin_lock_irqsave(&pm_qos_lock, flags);
 		list_add(&dep->list,
-			&pm_qos_array[pm_qos_class]->requirements.list);
+			&pm_qos_array[pm_qos_class]->requests.list);
 		spin_unlock_irqrestore(&pm_qos_lock, flags);
 		update_target(pm_qos_class);
-
-		return 0;
 	}
 
-cleanup:
-	kfree(dep);
-	return -ENOMEM;
+	return dep;
 }
-EXPORT_SYMBOL_GPL(pm_qos_add_requirement);
+EXPORT_SYMBOL_GPL(pm_qos_add_request);
 
 /**
- * pm_qos_update_requirement - modifies an existing qos request
- * @pm_qos_class: identifies which list of qos request to us
- * @name: identifies the request
+ * pm_qos_update_request - modifies an existing qos request
+ * @pm_qos_req : handle to list element holding a pm_qos request to use
  * @value: defines the qos request
  *
- * Updates an existing qos requirement for the pm_qos_class of parameters along
+ * Updates an existing qos request for the pm_qos_class of parameters along
  * with updating the target pm_qos_class value.
  *
- * If the named request isn't in the list then no change is made.
+ * Attempts are made to make this code callable on hot code paths.
  */
-int pm_qos_update_requirement(int pm_qos_class, char *name, s32 new_value)
+void pm_qos_update_request(struct pm_qos_request_list *pm_qos_req,
+		s32 new_value)
 {
 	unsigned long flags;
-	struct requirement_list *node;
 	int pending_update = 0;
+	s32 temp;
 
-	spin_lock_irqsave(&pm_qos_lock, flags);
-	list_for_each_entry(node,
-		&pm_qos_array[pm_qos_class]->requirements.list, list) {
-		if (strcmp(node->name, name) == 0) {
-			if (new_value == PM_QOS_DEFAULT_VALUE)
-				node->value =
-				pm_qos_array[pm_qos_class]->default_value;
-			else
-				node->value = new_value;
+	if (pm_qos_req) { /*guard against callers passing in null */
+		spin_lock_irqsave(&pm_qos_lock, flags);
+		if (new_value == PM_QOS_DEFAULT_VALUE)
+			temp = pm_qos_array[pm_qos_req->pm_qos_class]->
+				default_value;
+		else
+			temp = new_value;
+
+		if (temp != pm_qos_req->value) {
 			pending_update = 1;
-			break;
+			pm_qos_req->value = temp;
 		}
+		spin_unlock_irqrestore(&pm_qos_lock, flags);
 	}
-	spin_unlock_irqrestore(&pm_qos_lock, flags);
 	if (pending_update)
-		update_target(pm_qos_class);
-
-	return 0;
+		update_target(pm_qos_req->pm_qos_class);
 }
-EXPORT_SYMBOL_GPL(pm_qos_update_requirement);
+EXPORT_SYMBOL_GPL(pm_qos_update_request);
 
 /**
- * pm_qos_remove_requirement - modifies an existing qos request
- * @pm_qos_class: identifies which list of qos request to us
- * @name: identifies the request
+ * pm_qos_remove_request - modifies an existing qos request
+ * @pm_qos_req: handle to request list element
  *
- * Will remove named qos request from pm_qos_class list of parameters and
- * recompute the current target value for the pm_qos_class.
+ * Will remove pm qos request from the list of requests and
+ * recompute the current target value for the pm_qos_class.  Call this
+ * on slow code paths.
  */
-void pm_qos_remove_requirement(int pm_qos_class, char *name)
+void pm_qos_remove_request(struct pm_qos_request_list *pm_qos_req)
 {
 	unsigned long flags;
-	struct requirement_list *node;
-	int pending_update = 0;
+	int qos_class;
+
+	if (pm_qos_req == NULL)
+		return;
+		/* silent return to keep pcm code cleaner */
 
+	qos_class = pm_qos_req->pm_qos_class;
 	spin_lock_irqsave(&pm_qos_lock, flags);
-	list_for_each_entry(node,
-		&pm_qos_array[pm_qos_class]->requirements.list, list) {
-		if (strcmp(node->name, name) == 0) {
-			kfree(node->name);
-			list_del(&node->list);
-			kfree(node);
-			pending_update = 1;
-			break;
-		}
-	}
+	list_del(&pm_qos_req->list);
+	kfree(pm_qos_req);
 	spin_unlock_irqrestore(&pm_qos_lock, flags);
-	if (pending_update)
-		update_target(pm_qos_class);
+	update_target(qos_class);
 }
-EXPORT_SYMBOL_GPL(pm_qos_remove_requirement);
+EXPORT_SYMBOL_GPL(pm_qos_remove_request);
 
 /**
  * pm_qos_add_notifier - sets notification entry for changes to target value
@@ -313,7 +305,7 @@ EXPORT_SYMBOL_GPL(pm_qos_remove_requirement);
  * will register the notifier into a notification chain that gets called
  * upon changes to the pm_qos_class target value.
  */
- int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier)
+int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier)
 {
 	int retval;
 
@@ -343,21 +335,16 @@ int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier)
 }
 EXPORT_SYMBOL_GPL(pm_qos_remove_notifier);
 
-#define PID_NAME_LEN 32
-
 static int pm_qos_power_open(struct inode *inode, struct file *filp)
 {
-	int ret;
 	long pm_qos_class;
-	char name[PID_NAME_LEN];
 
 	pm_qos_class = find_pm_qos_object_by_minor(iminor(inode));
 	if (pm_qos_class >= 0) {
-		filp->private_data = (void *)pm_qos_class;
-		snprintf(name, PID_NAME_LEN, "process_%d", current->pid);
-		ret = pm_qos_add_requirement(pm_qos_class, name,
-					PM_QOS_DEFAULT_VALUE);
-		if (ret >= 0)
+		filp->private_data = (void *) pm_qos_add_request(pm_qos_class,
+				PM_QOS_DEFAULT_VALUE);
+
+		if (filp->private_data)
 			return 0;
 	}
 	return -EPERM;
@@ -365,32 +352,40 @@ static int pm_qos_power_open(struct inode *inode, struct file *filp)
 
 static int pm_qos_power_release(struct inode *inode, struct file *filp)
 {
-	int pm_qos_class;
-	char name[PID_NAME_LEN];
+	struct pm_qos_request_list *req;
 
-	pm_qos_class = (long)filp->private_data;
-	snprintf(name, PID_NAME_LEN, "process_%d", current->pid);
-	pm_qos_remove_requirement(pm_qos_class, name);
+	req = (struct pm_qos_request_list *)filp->private_data;
+	pm_qos_remove_request(req);
 
 	return 0;
 }
 
+
 static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
 		size_t count, loff_t *f_pos)
 {
 	s32 value;
-	int pm_qos_class;
-	char name[PID_NAME_LEN];
-
-	pm_qos_class = (long)filp->private_data;
-	if (count != sizeof(s32))
+	int x;
+	char ascii_value[11];
+	struct pm_qos_request_list *pm_qos_req;
+
+	if (count == sizeof(s32)) {
+		if (copy_from_user(&value, buf, sizeof(s32)))
+			return -EFAULT;
+	} else if (count == 11) { /* len('0x12345678/0') */
+		if (copy_from_user(ascii_value, buf, 11))
+			return -EFAULT;
+		x = sscanf(ascii_value, "%x", &value);
+		if (x != 1)
+			return -EINVAL;
+		pr_debug(KERN_ERR "%s, %d, 0x%x\n", ascii_value, x, value);
+	} else
 		return -EINVAL;
-	if (copy_from_user(&value, buf, sizeof(s32)))
-		return -EFAULT;
-	snprintf(name, PID_NAME_LEN, "process_%d", current->pid);
-	pm_qos_update_requirement(pm_qos_class, name, value);
 
-	return  sizeof(s32);
+	pm_qos_req = (struct pm_qos_request_list *)filp->private_data;
+	pm_qos_update_request(pm_qos_req, value);
+
+	return count;
 }
 
 
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 875c8de..88f95e7 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -495,7 +495,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
 		s32 beaconint_us;
 
 		if (latency < 0)
-			latency = pm_qos_requirement(PM_QOS_NETWORK_LATENCY);
+			latency = pm_qos_request(PM_QOS_NETWORK_LATENCY);
 
 		beaconint_us = ieee80211_tu_to_usec(
 					found->vif.bss_conf.beacon_int);
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 0d428d0..cbe815d 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -648,9 +648,6 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
 		substream->number = idx;
 		substream->stream = stream;
 		sprintf(substream->name, "subdevice #%i", idx);
-		snprintf(substream->latency_id, sizeof(substream->latency_id),
-			 "ALSA-PCM%d-%d%c%d", pcm->card->number, pcm->device,
-			 (stream ? 'c' : 'p'), idx);
 		substream->buffer_bytes_max = UINT_MAX;
 		if (prev == NULL)
 			pstr->substream = substream;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 20b5982..192dd40 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -484,11 +484,13 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
 	snd_pcm_timer_resolution_change(substream);
 	runtime->status->state = SNDRV_PCM_STATE_SETUP;
 
-	pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
-				substream->latency_id);
+	if (substream->latency_pm_qos_req) {
+		pm_qos_remove_request(substream->latency_pm_qos_req);
+		substream->latency_pm_qos_req = NULL;
+	}
 	if ((usecs = period_to_usecs(runtime)) >= 0)
-		pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY,
-					substream->latency_id, usecs);
+		substream->latency_pm_qos_req = pm_qos_add_request(
+					PM_QOS_CPU_DMA_LATENCY, usecs);
 	return 0;
  _error:
 	/* hardware might be unuseable from this time,
@@ -543,8 +545,8 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
 	if (substream->ops->hw_free)
 		result = substream->ops->hw_free(substream);
 	runtime->status->state = SNDRV_PCM_STATE_OPEN;
-	pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
-		substream->latency_id);
+	pm_qos_remove_request(substream->latency_pm_qos_req);
+	substream->latency_pm_qos_req = NULL;
 	return result;
 }
 
-- 
1.6.3.3

^ permalink raw reply related

* Re: [net-next-2.6 V8 PATCH 0/2] Add virtual port netlink support
From: Scott Feldman @ 2010-05-15  1:37 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: davem, netdev, chrisw, arnd, kaber
In-Reply-To: <20100514182957.4998bea4@nehalam>

On 5/14/10 6:29 PM, "Stephen Hemminger" <shemminger@vyatta.com> wrote:

> On Fri, 14 May 2010 18:04:23 -0700
> Scott Feldman <scofeldm@cisco.com> wrote:
> 
>> [Add symmetrical set/get layout per Patrick McHardy suggestions]
>> 
>> The following series adds virtual port netlink support and adds an
>> implementation to Cisco's enic netdev driver:
>> 
>> 1/2: Adds virtual netlink RTM_SETLINK/RTM_GETLINK support, and
>>     adds matching netdev ops net_{set|get}_vf_port.
>> 
>> 2/2: Adds enic support for net_{set|get}_vf_port for enic
>>     dynamic devices.
>> 
>> Signed-off-by: Scott Feldman <scofeldm@cisco.com>
>> Signed-off-by: Roopa Prabhu<roprabhu@cisco.com>
>> --
>> To unsubscribe from this list: send the line "unsubscribe netdev" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> I assume there will be some documentation for this when the patch
> to iproute for supporting this comes out.

Absolutely.  Been waiting to send iproute2 patch until dust has settled with
kernel patch.

-scott


^ permalink raw reply

* Re: [PATCH] skge: use the DMA state API instead of the pci equivalents
From: Stephen Hemminger @ 2010-05-15  1:33 UTC (permalink / raw)
  To: FUJITA Tomonori; +Cc: netdev
In-Reply-To: <20100428095730K.fujita.tomonori@lab.ntt.co.jp>

On Wed, 28 Apr 2010 09:57:04 +0900
FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> wrote:

> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>

Yes, this works fine. Sorry for the delay but that test system
was offline for several months and the disk went bad.

Acked-by: Stephen Hemminger <shemminger@vyatta.com>

^ permalink raw reply

* Re: [net-next-2.6 V8 PATCH 0/2] Add virtual port netlink support
From: Stephen Hemminger @ 2010-05-15  1:29 UTC (permalink / raw)
  To: Scott Feldman; +Cc: davem, netdev, chrisw, arnd, kaber
In-Reply-To: <20100515010415.21260.35219.stgit@savbu-pc100.cisco.com>

On Fri, 14 May 2010 18:04:23 -0700
Scott Feldman <scofeldm@cisco.com> wrote:

> [Add symmetrical set/get layout per Patrick McHardy suggestions]
> 
> The following series adds virtual port netlink support and adds an
> implementation to Cisco's enic netdev driver:
> 
> 	1/2: Adds virtual netlink RTM_SETLINK/RTM_GETLINK support, and
> 	     adds matching netdev ops net_{set|get}_vf_port.
> 
> 	2/2: Adds enic support for net_{set|get}_vf_port for enic
> 	     dynamic devices.
> 
> Signed-off-by: Scott Feldman <scofeldm@cisco.com>
> Signed-off-by: Roopa Prabhu<roprabhu@cisco.com>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

I assume there will be some documentation for this when the patch
to iproute for supporting this comes out.

^ permalink raw reply


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