diff -Naur src.orig/ixgbe_fcoe.c src/ixgbe_fcoe.c
--- src.orig/ixgbe_fcoe.c	2011-09-20 22:31:44.000000000 +0000
+++ src/ixgbe_fcoe.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,886 +0,0 @@
-/*******************************************************************************
-
-  Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms and conditions of the GNU General Public License,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Contact Information:
-  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-*******************************************************************************/
-
-#include "ixgbe.h"
-
-
-#ifdef IXGBE_FCOE
-#ifdef CONFIG_DCB
-#include "ixgbe_dcb_82599.h"
-#endif /* CONFIG_DCB */
-#include <linux/if_ether.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/fc/fc_fs.h>
-#include <scsi/fc/fc_fcoe.h>
-#include <scsi/libfc.h>
-#include <scsi/libfcoe.h>
-
-/**
- * ixgbe_fcoe_clear_ddp - clear the given ddp context
- * @ddp - ptr to the ixgbe_fcoe_ddp
- *
- * Returns : none
- *
- */
-static inline void ixgbe_fcoe_clear_ddp(struct ixgbe_fcoe_ddp *ddp)
-{
-	ddp->len = 0;
-	ddp->err = 1;
-	ddp->udl = NULL;
-	ddp->udp = 0UL;
-	ddp->sgl = NULL;
-	ddp->sgc = 0;
-}
-
-/**
- * ixgbe_fcoe_ddp_put - free the ddp context for a given xid
- * @netdev: the corresponding net_device
- * @xid: the xid that corresponding ddp will be freed
- *
- * This is the implementation of net_device_ops.ndo_fcoe_ddp_done
- * and it is expected to be called by ULD, i.e., FCP layer of libfc
- * to release the corresponding ddp context when the I/O is done.
- *
- * Returns : data length already ddp-ed in bytes
- */
-int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid)
-{
-	int len = 0;
-	struct ixgbe_fcoe *fcoe;
-	struct ixgbe_adapter *adapter;
-	struct ixgbe_fcoe_ddp *ddp;
-	u32 fcbuff;
-
-	if (!netdev)
-		goto out_ddp_put;
-
-	if (xid >= IXGBE_FCOE_DDP_MAX)
-		goto out_ddp_put;
-
-	adapter = netdev_priv(netdev);
-	fcoe = &adapter->fcoe;
-	ddp = &fcoe->ddp[xid];
-	if (!ddp->udl)
-		goto out_ddp_put;
-
-	len = ddp->len;
-	/* if there an error, force to invalidate ddp context */
-	if (ddp->err) {
-		spin_lock_bh(&fcoe->lock);
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCFLT, 0);
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCFLTRW,
-				(xid | IXGBE_FCFLTRW_WE));
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCBUFF, 0);
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCDMARW,
-				(xid | IXGBE_FCDMARW_WE));
-
-		/* guaranteed to be invalidated after 100us */
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCDMARW,
-				(xid | IXGBE_FCDMARW_RE));
-		fcbuff = IXGBE_READ_REG(&adapter->hw, IXGBE_FCBUFF);
-		spin_unlock_bh(&fcoe->lock);
-		if (fcbuff & IXGBE_FCBUFF_VALID)
-			udelay(100);
-	}
-	if (ddp->sgl)
-		pci_unmap_sg(adapter->pdev, ddp->sgl, ddp->sgc,
-			     DMA_FROM_DEVICE);
-	pci_pool_free(fcoe->pool, ddp->udl, ddp->udp);
-	ixgbe_fcoe_clear_ddp(ddp);
-
-out_ddp_put:
-	return len;
-}
-
-/**
- * ixgbe_fcoe_ddp_setup - called to set up ddp context
- * @netdev: the corresponding net_device
- * @xid: the exchange id requesting ddp
- * @sgl: the scatter-gather list for this request
- * @sgc: the number of scatter-gather items
- *
- * Returns : 1 for success and 0 for no ddp
- */
-static int ixgbe_fcoe_ddp_setup(struct net_device *netdev, u16 xid,
-				struct scatterlist *sgl, unsigned int sgc,
-				int target_mode)
-{
-	struct ixgbe_adapter *adapter;
-	struct ixgbe_hw *hw;
-	struct ixgbe_fcoe *fcoe;
-	struct ixgbe_fcoe_ddp *ddp;
-	struct scatterlist *sg;
-	unsigned int i, j, dmacount;
-	unsigned int len;
-	static const unsigned int bufflen = IXGBE_FCBUFF_MIN;
-	unsigned int firstoff = 0;
-	unsigned int lastsize;
-	unsigned int thisoff = 0;
-	unsigned int thislen = 0;
-	u32 fcbuff, fcdmarw, fcfltrw, fcrxctl;
-	dma_addr_t addr = 0;
-
-	if (!netdev || !sgl || !sgc)
-		return 0;
-
-	adapter = netdev_priv(netdev);
-	if (xid >= IXGBE_FCOE_DDP_MAX) {
-		e_warn(drv, "xid=0x%x out-of-range\n", xid);
-		return 0;
-	}
-
-	/* no DDP if we are already down or resetting */
-	if (test_bit(__IXGBE_DOWN, &adapter->state) ||
-	    test_bit(__IXGBE_RESETTING, &adapter->state))
-		return 0;
-
-	fcoe = &adapter->fcoe;
-	if (!fcoe->pool) {
-		e_warn(drv, "xid=0x%x no ddp pool for fcoe\n", xid);
-		return 0;
-	}
-
-	ddp = &fcoe->ddp[xid];
-	if (ddp->sgl) {
-		e_err(drv, "xid 0x%x w/ non-null sgl=%p nents=%d\n",
-			xid, ddp->sgl, ddp->sgc);
-		return 0;
-	}
-	ixgbe_fcoe_clear_ddp(ddp);
-
-	/* setup dma from scsi command sgl */
-	dmacount = pci_map_sg(adapter->pdev, sgl, sgc, DMA_FROM_DEVICE);
-	if (dmacount == 0) {
-		e_err(drv, "xid 0x%x DMA map error\n", xid);
-		return 0;
-	}
-
-	/* alloc the udl from our ddp pool */
-	ddp->udl = pci_pool_alloc(fcoe->pool, GFP_ATOMIC, &ddp->udp);
-	if (!ddp->udl) {
-		e_err(drv, "failed allocated ddp context\n");
-		goto out_noddp_unmap;
-	}
-	ddp->sgl = sgl;
-	ddp->sgc = sgc;
-
-	j = 0;
-	for_each_sg(sgl, sg, dmacount, i) {
-		addr = sg_dma_address(sg);
-		len = sg_dma_len(sg);
-		while (len) {
-			/* max number of buffers allowed in one DDP context */
-			if (j >= IXGBE_BUFFCNT_MAX) {
-				e_err(drv, "xid=%x:%d,%d,%d:addr=%llx "
-				      "not enough descriptors\n",
-					xid, i, j, dmacount, (u64)addr);
-				goto out_noddp_free;
-			}
-
-			/* get the offset of length of current buffer */
-			thisoff = addr & ((dma_addr_t)bufflen - 1);
-			thislen = min((bufflen - thisoff), len);
-			/*
-			 * all but the 1st buffer (j == 0)
-			 * must be aligned on bufflen
-			 */
-			if ((j != 0) && (thisoff))
-				goto out_noddp_free;
-			/*
-			 * all but the last buffer
-			 * ((i == (dmacount - 1)) && (thislen == len))
-			 * must end at bufflen
-			 */
-			if (((i != (dmacount - 1)) || (thislen != len))
-			    && ((thislen + thisoff) != bufflen))
-				goto out_noddp_free;
-
-			ddp->udl[j] = (u64)(addr - thisoff);
-			/* only the first buffer may have none-zero offset */
-			if (j == 0)
-				firstoff = thisoff;
-			len -= thislen;
-			addr += thislen;
-			j++;
-		}
-	}
-	/* only the last buffer may have non-full bufflen */
-	lastsize = thisoff + thislen;
-
-	/*
-	 * lastsize can not be bufflen.
-	 * If it is then adding another buffer with lastsize = 1.
-	 * Since lastsize is 1 there will be no HW access to this buffer.
-	 */
-	if (lastsize == bufflen) {
-		if (j >= IXGBE_BUFFCNT_MAX) {
-			printk_once("Will NOT use DDP since there are not "
-				    "enough user buffers. We need an  extra "
-				    "buffer because lastsize is bufflen. "
-				    "xid=%x:%d,%d,%d:addr=%llx\n",
-				    xid, i, j, dmacount, (u64)addr);
-
-			goto out_noddp_free;
-		}
-
-		ddp->udl[j] = (u64)(fcoe->extra_ddp_buffer_dma);
-		j++;
-		lastsize = 1;
-	}
-
-	fcbuff = (IXGBE_FCBUFF_4KB << IXGBE_FCBUFF_BUFFSIZE_SHIFT);
-	fcbuff |= ((j & 0xff) << IXGBE_FCBUFF_BUFFCNT_SHIFT);
-	fcbuff |= (firstoff << IXGBE_FCBUFF_OFFSET_SHIFT);
-	/* Set WRCONTX bit to allow DDP for target */
-	if (target_mode)
-		fcbuff |= (IXGBE_FCBUFF_WRCONTX);
-	fcbuff |= (IXGBE_FCBUFF_VALID);
-
-	fcdmarw = xid;
-	fcdmarw |= IXGBE_FCDMARW_WE;
-	fcdmarw |= (lastsize << IXGBE_FCDMARW_LASTSIZE_SHIFT);
-
-	fcfltrw = xid;
-	fcfltrw |= IXGBE_FCFLTRW_WE;
-
-	/* program DMA context */
-	hw = &adapter->hw;
-	spin_lock_bh(&fcoe->lock);
-
-	/* turn on last frame indication for target mode as FCP_RSPtarget is
-	 * supposed to send FCP_RSP when it is done. */
-	if (target_mode && !test_bit(__IXGBE_FCOE_TARGET, &fcoe->mode)) {
-		set_bit(__IXGBE_FCOE_TARGET, &fcoe->mode);
-		fcrxctl = IXGBE_READ_REG(hw, IXGBE_FCRXCTRL);
-		fcrxctl |= IXGBE_FCRXCTRL_LASTSEQH;
-		IXGBE_WRITE_REG(hw, IXGBE_FCRXCTRL, fcrxctl);
-	}
-
-	IXGBE_WRITE_REG(hw, IXGBE_FCPTRL, ddp->udp & DMA_BIT_MASK(32));
-	IXGBE_WRITE_REG(hw, IXGBE_FCPTRH, (u64)ddp->udp >> 32);
-	IXGBE_WRITE_REG(hw, IXGBE_FCBUFF, fcbuff);
-	IXGBE_WRITE_REG(hw, IXGBE_FCDMARW, fcdmarw);
-	/* program filter context */
-	IXGBE_WRITE_REG(hw, IXGBE_FCPARAM, 0);
-	IXGBE_WRITE_REG(hw, IXGBE_FCFLT, IXGBE_FCFLT_VALID);
-	IXGBE_WRITE_REG(hw, IXGBE_FCFLTRW, fcfltrw);
-
-	spin_unlock_bh(&fcoe->lock);
-
-	return 1;
-
-out_noddp_free:
-	pci_pool_free(fcoe->pool, ddp->udl, ddp->udp);
-	ixgbe_fcoe_clear_ddp(ddp);
-
-out_noddp_unmap:
-	pci_unmap_sg(adapter->pdev, sgl, sgc, DMA_FROM_DEVICE);
-	return 0;
-}
-
-/**
- * ixgbe_fcoe_ddp_get - called to set up ddp context in initiator mode
- * @netdev: the corresponding net_device
- * @xid: the exchange id requesting ddp
- * @sgl: the scatter-gather list for this request
- * @sgc: the number of scatter-gather items
- *
- * This is the implementation of net_device_ops.ndo_fcoe_ddp_setup
- * and is expected to be called from ULD, e.g., FCP layer of libfc
- * to set up ddp for the corresponding xid of the given sglist for
- * the corresponding I/O.
- *
- * Returns : 1 for success and 0 for no ddp
- */
-int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
-		       struct scatterlist *sgl, unsigned int sgc)
-{
-	return ixgbe_fcoe_ddp_setup(netdev, xid, sgl, sgc, 0);
-}
-
-#ifdef HAVE_NETDEV_OPS_FCOE_DDP_TARGET
-/**
- * ixgbe_fcoe_ddp_target - called to set up ddp context in target mode
- * @netdev: the corresponding net_device
- * @xid: the exchange id requesting ddp
- * @sgl: the scatter-gather list for this request
- * @sgc: the number of scatter-gather items
- *
- * This is the implementation of net_device_ops.ndo_fcoe_ddp_target
- * and is expected to be called from ULD, e.g., FCP layer of libfc
- * to set up ddp for the corresponding xid of the given sglist for
- * the corresponding I/O. The DDP in target mode is a write I/O request
- * from the initiator.
- *
- * Returns : 1 for success and 0 for no ddp
- */
-int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid,
-			    struct scatterlist *sgl, unsigned int sgc)
-{
-	return ixgbe_fcoe_ddp_setup(netdev, xid, sgl, sgc, 1);
-}
-
-#endif /* HAVE_NETDEV_OPS_FCOE_DDP_TARGET */
-/**
- * ixgbe_fcoe_ddp - check ddp status and mark it done
- * @adapter: ixgbe adapter
- * @rx_desc: advanced rx descriptor
- * @skb: the skb holding the received data
- *
- * This checks ddp status.
- *
- * Returns : < 0 indicates an error or not a FCiE ddp, 0 indicates
- * not passing the skb to ULD, > 0 indicates is the length of data
- * being ddped.
- */
-int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
-		   union ixgbe_adv_rx_desc *rx_desc,
-		   struct sk_buff *skb)
-{
-	struct ixgbe_fcoe *fcoe = &adapter->fcoe;
-	struct ixgbe_fcoe_ddp *ddp;
-	struct fc_frame_header *fh;
-	struct fcoe_crc_eof *crc;
-	int rc = -EINVAL;
-	__le32 fcerr = ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_ERR_FCERR);
-	__le32 ddp_err;
-	u32 fctl;
-	u16 xid;
-
-	if (fcerr == cpu_to_le32(IXGBE_FCERR_BADCRC))
-		skb->ip_summed = CHECKSUM_NONE;
-	else
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-
-	fh = (struct fc_frame_header *)(skb->data + sizeof(struct fcoe_hdr));
-
-	if (skb->protocol == htons(ETH_P_8021Q))
-		fh = (struct fc_frame_header *)((char *)fh + VLAN_HLEN);
-
-	fctl = ntoh24(fh->fh_f_ctl);
-	if (fctl & FC_FC_EX_CTX)
-		xid =  ntohs(fh->fh_ox_id);
-	else
-		xid =  ntohs(fh->fh_rx_id);
-
-	if (xid >= IXGBE_FCOE_DDP_MAX)
-		goto ddp_out;
-
-	ddp = &fcoe->ddp[xid];
-	if (!ddp->udl)
-		goto ddp_out;
-
-	ddp_err = ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_ERR_FCEOFE |
-					      IXGBE_RXDADV_ERR_FCERR);
-	if (ddp_err)
-		goto ddp_out;
-
-	switch (ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_STAT_FCSTAT)) {
-	/* return 0 to bypass going to ULD for DDPed data */
-	case IXGBE_RXDADV_STAT_FCSTAT_DDP:
-		/* update length of DDPed data */
-		ddp->len = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
-		rc = 0;
-		break;
-	/* unmap the sg list when FCPRSP is received */
-	case IXGBE_RXDADV_STAT_FCSTAT_FCPRSP:
-		pci_unmap_sg(adapter->pdev, ddp->sgl,
-			     ddp->sgc, DMA_FROM_DEVICE);
-		ddp->err = ddp_err;
-		ddp->sgl = NULL;
-		ddp->sgc = 0;
-		/* fall through */
-	/* if DDP length is present pass it through to ULD */
-	case IXGBE_RXDADV_STAT_FCSTAT_NODDP:
-		/* update length of DDPed data */
-		ddp->len = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
-		if (rx_desc->wb.lower.hi_dword.rss)
-			rc = ddp->len;
-		break;
-	/* no match will return as an error */
-	case IXGBE_RXDADV_STAT_FCSTAT_NOMTCH:
-	default:
-		break;
-	}
-
-	/* In target mode, check the last data frame of the sequence.
-	 * For DDP in target mode, data is already DDPed but the header
-	 * indication of the last data frame ould allow is to tell if we
-	 * got all the data and the ULP can send FCP_RSP back, as this is
-	 * not a full fcoe frame, we fill the trailer here so it won't be
-	 * dropped by the ULP stack.
-	 */
-	if ((fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA) &&
-	    (fctl & FC_FC_END_SEQ)) {
-		crc = (struct fcoe_crc_eof *)skb_put(skb, sizeof(*crc));
-		crc->fcoe_eof = FC_EOF_T;
-	}
-ddp_out:
-	return rc;
-}
-
-/**
- * ixgbe_fso - ixgbe FCoE Sequence Offload (FSO)
- * @tx_ring: tx desc ring
- * @first: first tx_buffer structure containing skb, tx_flags, and protocol
- * @hdr_len: hdr_len to be returned
- *
- * This sets up large send offload for FCoE
- *
- * Returns : 0 indicates success, < 0 for error
- */
-int ixgbe_fso(struct ixgbe_ring *tx_ring,
-	      struct ixgbe_tx_buffer *first,
-	      u8 *hdr_len)
-{
-	struct sk_buff *skb = first->skb;
-	struct fc_frame_header *fh;
-	u32 vlan_macip_lens;
-	u32 fcoe_sof_eof = 0;
-	u32 mss_l4len_idx;
-	u8 sof, eof;
-
-#ifdef NETIF_F_FSO
-	if (skb_is_gso(skb) && skb_shinfo(skb)->gso_type != SKB_GSO_FCOE) {
-		dev_err(tx_ring->dev, "Wrong gso type %d:expecting SKB_GSO_FCOE\n",
-			skb_shinfo(skb)->gso_type);
-		return -EINVAL;
-	}
-
-#endif
-	/* resets the header to point fcoe/fc */
-	skb_set_network_header(skb, skb->mac_len);
-	skb_set_transport_header(skb, skb->mac_len +
-				 sizeof(struct fcoe_hdr));
-
-	/* sets up SOF and ORIS */
-	sof = ((struct fcoe_hdr *)skb_network_header(skb))->fcoe_sof;
-	switch (sof) {
-	case FC_SOF_I2:
-		fcoe_sof_eof = IXGBE_ADVTXD_FCOEF_ORIS;
-		break;
-	case FC_SOF_I3:
-		fcoe_sof_eof = IXGBE_ADVTXD_FCOEF_SOF |
-			       IXGBE_ADVTXD_FCOEF_ORIS;
-		break;
-	case FC_SOF_N2:
-		break;
-	case FC_SOF_N3:
-		fcoe_sof_eof = IXGBE_ADVTXD_FCOEF_SOF;
-		break;
-	default:
-		dev_warn(tx_ring->dev, "unknown sof = 0x%x\n", sof);
-		return -EINVAL;
-	}
-
-	/* the first byte of the last dword is EOF */
-	skb_copy_bits(skb, skb->len - 4, &eof, 1);
-	/* sets up EOF and ORIE */
-	switch (eof) {
-	case FC_EOF_N:
-		fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_N;
-		break;
-	case FC_EOF_T:
-		/* lso needs ORIE */
-		if (skb_is_gso(skb))
-			fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_N |
-					IXGBE_ADVTXD_FCOEF_ORIE;
-		else
-			fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_T;
-		break;
-	case FC_EOF_NI:
-		fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_NI;
-		break;
-	case FC_EOF_A:
-		fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_EOF_A;
-		break;
-	default:
-		dev_warn(tx_ring->dev, "unknown eof = 0x%x\n", eof);
-		return -EINVAL;
-	}
-
-	/* sets up PARINC indicating data offset */
-	fh = (struct fc_frame_header *)skb_transport_header(skb);
-	if (fh->fh_f_ctl[2] & FC_FC_REL_OFF)
-		fcoe_sof_eof |= IXGBE_ADVTXD_FCOEF_PARINC;
-
-	/* include trailer in headlen as it is replicated per frame */
-	*hdr_len = sizeof(struct fcoe_crc_eof);
-
-	/* hdr_len includes fc_hdr if FCoE LSO is enabled */
-	if (skb_is_gso(skb)) {
-		*hdr_len += skb_transport_offset(skb) +
-			    sizeof(struct fc_frame_header);
-		/* update gso_segs and bytecount */
-		first->gso_segs = DIV_ROUND_UP(skb->len - *hdr_len,
-					       skb_shinfo(skb)->gso_size);
-		first->bytecount += (first->gso_segs - 1) * *hdr_len;
-		first->tx_flags |= IXGBE_TX_FLAGS_FSO;
-	}
-
-	/* set flag indicating FCOE to ixgbe_tx_map call */
-	first->tx_flags |= IXGBE_TX_FLAGS_FCOE;
-
-	/* mss_l4len_id: use 1 for FSO as TSO, no need for L4LEN */
-	mss_l4len_idx = skb_shinfo(skb)->gso_size << IXGBE_ADVTXD_MSS_SHIFT;
-	mss_l4len_idx |= 1 << IXGBE_ADVTXD_IDX_SHIFT;
-
-	/* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */
-	vlan_macip_lens = skb_transport_offset(skb) +
-			  sizeof(struct fc_frame_header);
-	vlan_macip_lens |= (skb_transport_offset(skb) - 4)
-			   << IXGBE_ADVTXD_MACLEN_SHIFT;
-	vlan_macip_lens |= first->tx_flags & IXGBE_TX_FLAGS_VLAN_MASK;
-
-	/* write context desc */
-	ixgbe_tx_ctxtdesc(tx_ring, vlan_macip_lens, fcoe_sof_eof,
-			  IXGBE_ADVTXT_TUCMD_FCOE, mss_l4len_idx);
-
-	return 0;
-}
-
-/**
- * ixgbe_configure_fcoe - configures registers for fcoe at start
- * @adapter: ptr to ixgbe adapter
- *
- * This sets up FCoE related registers
- *
- * Returns : none
- */
-void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter)
-{
-	int i, fcoe_q, fcoe_i;
-	struct ixgbe_hw *hw = &adapter->hw;
-	struct ixgbe_fcoe *fcoe = &adapter->fcoe;
-	struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_FCOE];
-#ifdef CONFIG_DCB
-	u8 tc;
-	u32 up2tc;
-
-#endif /* CONFIG_DCB */
-	/* create the pool for ddp if not created yet */
-	if (!fcoe->pool) {
-		/* allocate ddp pool */
-		fcoe->pool = pci_pool_create("ixgbe_fcoe_ddp",
-					     adapter->pdev, IXGBE_FCPTR_MAX,
-					     IXGBE_FCPTR_ALIGN, PAGE_SIZE);
-		if (!fcoe->pool)
-			e_err(drv, "failed to allocated FCoE DDP pool\n");
-		spin_lock_init(&fcoe->lock);
-
-		/* Extra buffer to be shared by all DDPs for HW work around */
-		fcoe->extra_ddp_buffer = kmalloc(IXGBE_FCBUFF_MIN, GFP_ATOMIC);
-		if (fcoe->extra_ddp_buffer == NULL) {
-			e_err(drv, "failed to allocated extra DDP buffer\n");
-			goto out_extra_ddp_buffer_alloc;
-		}
-
-		fcoe->extra_ddp_buffer_dma = 
-			dma_map_single(&adapter->pdev->dev,
-				       fcoe->extra_ddp_buffer,
-				       IXGBE_FCBUFF_MIN,
-				       DMA_FROM_DEVICE);
-		if (dma_mapping_error(&adapter->pdev->dev,
-				      fcoe->extra_ddp_buffer_dma)) {
-			e_err(drv, "failed to map extra DDP buffer\n");
-			goto out_extra_ddp_buffer_dma;
-
-		}
-	}
-
-	/* Enable L2 eth type filter for FCoE */
-	IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_FCOE),
-			(ETH_P_FCOE | IXGBE_ETQF_FCOE | IXGBE_ETQF_FILTER_EN));
-	/* Enable L2 eth type filter for FIP */
-	IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_FIP),
-			(ETH_P_FIP | IXGBE_ETQF_FILTER_EN));
-	if (adapter->ring_feature[RING_F_FCOE].indices) {
-		/* Use multiple rx queues for FCoE by redirection table */
-		for (i = 0; i < IXGBE_FCRETA_SIZE; i++) {
-			fcoe_i = f->mask + i % f->indices;
-			fcoe_i &= IXGBE_FCRETA_ENTRY_MASK;
-			fcoe_q = adapter->rx_ring[fcoe_i]->reg_idx;
-			IXGBE_WRITE_REG(hw, IXGBE_FCRETA(i), fcoe_q);
-		}
-		IXGBE_WRITE_REG(hw, IXGBE_FCRECTL, IXGBE_FCRECTL_ENA);
-		IXGBE_WRITE_REG(hw, IXGBE_ETQS(IXGBE_ETQF_FILTER_FCOE), 0);
-	} else  {
-		/* Use single rx queue for FCoE */
-		fcoe_i = f->mask;
-		fcoe_q = adapter->rx_ring[fcoe_i]->reg_idx;
-		IXGBE_WRITE_REG(hw, IXGBE_FCRECTL, 0);
-		IXGBE_WRITE_REG(hw, IXGBE_ETQS(IXGBE_ETQF_FILTER_FCOE),
-				IXGBE_ETQS_QUEUE_EN |
-				(fcoe_q << IXGBE_ETQS_RX_QUEUE_SHIFT));
-	}
-	/* Enable L2 eth type filter for FIP */
-	IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_FIP),
-			(ETH_P_FIP | IXGBE_ETQF_FILTER_EN));
-	/* send FIP frames to the first FCoE queue */
-	fcoe_i = f->mask;
-	fcoe_q = adapter->rx_ring[fcoe_i]->reg_idx;
-	IXGBE_WRITE_REG(hw, IXGBE_ETQS(IXGBE_ETQF_FILTER_FIP),
-			IXGBE_ETQS_QUEUE_EN |
-			(fcoe_q << IXGBE_ETQS_RX_QUEUE_SHIFT));
-
-	IXGBE_WRITE_REG(hw, IXGBE_FCRXCTRL,
-			IXGBE_FCRXCTRL_FCOELLI |
-			IXGBE_FCRXCTRL_FCCRCBO |
-			(FC_FCOE_VER << IXGBE_FCRXCTRL_FCOEVER_SHIFT));
-#ifdef CONFIG_DCB
-
-	up2tc = IXGBE_READ_REG(&adapter->hw, IXGBE_RTTUP2TC);
-	for (i = 0; i < MAX_USER_PRIORITY; i++) {
-		tc = (u8)(up2tc >> (i * IXGBE_RTTUP2TC_UP_SHIFT));
-		tc &= (MAX_TRAFFIC_CLASS - 1);
-		if (fcoe->tc == tc) {
-			fcoe->up = i;
-			break;
-		}
-	}
-#endif /* CONFIG_DCB */
-
-	return;
-
-out_extra_ddp_buffer_dma:
-	kfree(fcoe->extra_ddp_buffer);
-out_extra_ddp_buffer_alloc:
-	pci_pool_destroy(fcoe->pool);
-	fcoe->pool = NULL;
-}
-
-/**
- * ixgbe_cleanup_fcoe - release all fcoe ddp context resources
- * @adapter : ixgbe adapter
- *
- * Cleans up outstanding ddp context resources
- *
- * Returns : none
- */
-void ixgbe_cleanup_fcoe(struct ixgbe_adapter *adapter)
-{
-	int i;
-	struct ixgbe_fcoe *fcoe = &adapter->fcoe;
-
-	/* release ddp resource */
-	if (fcoe->pool) {
-		for (i = 0; i < IXGBE_FCOE_DDP_MAX; i++)
-			ixgbe_fcoe_ddp_put(adapter->netdev, i);
-		dma_unmap_single(&adapter->pdev->dev,
-				 fcoe->extra_ddp_buffer_dma,
-				 IXGBE_FCBUFF_MIN,
-				 DMA_FROM_DEVICE);
-		kfree(fcoe->extra_ddp_buffer);
-		pci_pool_destroy(fcoe->pool);
-		fcoe->pool = NULL;
-	}
-}
-
-#ifdef HAVE_NETDEV_OPS_FCOE_ENABLE
-/**
- * ixgbe_fcoe_enable - turn on FCoE offload feature
- * @netdev: the corresponding netdev
- *
- * Turns on FCoE offload feature in 82599.
- *
- * Returns : 0 indicates success or -EINVAL on failure
- */
-int ixgbe_fcoe_enable(struct net_device *netdev)
-{
-	int rc = -EINVAL;
-	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	struct ixgbe_fcoe *fcoe = &adapter->fcoe;
-
-
-	if (!(adapter->flags & IXGBE_FLAG_FCOE_CAPABLE))
-		goto out_enable;
-
-	atomic_inc(&fcoe->refcnt);
-	if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)
-		goto out_enable;
-
-	e_info(drv, "Enabling FCoE offload features.\n");
-	if (netif_running(netdev))
-		netdev->netdev_ops->ndo_stop(netdev);
-
-	ixgbe_clear_interrupt_scheme(adapter);
-
-	adapter->flags |= IXGBE_FLAG_FCOE_ENABLED;
-	adapter->ring_feature[RING_F_FCOE].indices = IXGBE_FCRETA_SIZE;
-	netdev->features |= NETIF_F_FCOE_CRC;
-	netdev->features |= NETIF_F_FSO;
-	netdev->features |= NETIF_F_FCOE_MTU;
-	netdev->fcoe_ddp_xid = IXGBE_FCOE_DDP_MAX - 1;
-
-	ixgbe_init_interrupt_scheme(adapter);
-	netdev_features_change(netdev);
-
-	if (netif_running(netdev))
-		netdev->netdev_ops->ndo_open(netdev);
-	rc = 0;
-
-out_enable:
-	return rc;
-}
-
-/**
- * ixgbe_fcoe_disable - turn off FCoE offload feature
- * @netdev: the corresponding netdev
- *
- * Turns off FCoE offload feature in 82599.
- *
- * Returns : 0 indicates success or -EINVAL on failure
- */
-int ixgbe_fcoe_disable(struct net_device *netdev)
-{
-	int rc = -EINVAL;
-	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	struct ixgbe_fcoe *fcoe = &adapter->fcoe;
-
-	if (!(adapter->flags & IXGBE_FLAG_FCOE_CAPABLE) ||
-	    !(adapter->flags & IXGBE_FLAG_FCOE_ENABLED))
-		goto out_disable;
-
-	if (!atomic_dec_and_test(&fcoe->refcnt))
-		goto out_disable;
-
-	e_info(drv, "Disabling FCoE offload features.\n");
-	netdev->features &= ~NETIF_F_FCOE_CRC;
-	netdev->features &= ~NETIF_F_FSO;
-	netdev->features &= ~NETIF_F_FCOE_MTU;
-	netdev->fcoe_ddp_xid = 0;
-	netdev_features_change(netdev);
-
-	if (netif_running(netdev))
-		netdev->netdev_ops->ndo_stop(netdev);
-
-	ixgbe_clear_interrupt_scheme(adapter);
-	adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED;
-	adapter->ring_feature[RING_F_FCOE].indices = 0;
-	ixgbe_cleanup_fcoe(adapter);
-	ixgbe_init_interrupt_scheme(adapter);
-
-	if (netif_running(netdev))
-		netdev->netdev_ops->ndo_open(netdev);
-	rc = 0;
-
-out_disable:
-	return rc;
-}
-#endif /* HAVE_NETDEV_OPS_FCOE_ENABLE */
-
-#ifdef CONFIG_DCB
-#ifdef HAVE_DCBNL_OPS_GETAPP
-/**
- * ixgbe_fcoe_getapp - retrieves current user priority bitmap for FCoE
- * @adapter : ixgbe adapter
- *
- * Finds out the corresponding user priority bitmap from the current
- * traffic class that FCoE belongs to. Returns 0 as the invalid user
- * priority bitmap to indicate an error.
- *
- * Returns : 802.1p user priority bitmap for FCoE
- */
-u8 ixgbe_fcoe_getapp(struct ixgbe_adapter *adapter)
-{
-	return 1 << adapter->fcoe.up;
-}
-
-#endif /* HAVE_DCBNL_OPS_GETAPP */
-/**
- * ixgbe_fcoe_setapp - sets the user priority bitmap for FCoE
- * @adapter : ixgbe adapter
- * @up : 802.1p user priority bitmap
- *
- * Finds out the traffic class from the input user priority
- * bitmap for FCoE.
- *
- * Returns : 0 on success otherwise returns 1 on error
- */
-u8 ixgbe_fcoe_setapp(struct ixgbe_adapter *adapter, u8 up)
-{
-	int i;
-	struct tc_configuration *tc_cfg;
-
-	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
-		tc_cfg = &adapter->temp_dcb_cfg.tc_config[i];
-		if (tc_cfg->path[0].up_to_tc_bitmap & up)
-			adapter->fcoe.tc = i;
-	}
-
-	adapter->fcoe.up = ffs(up) - 1;
-	return 0;
-}
-#endif /* CONFIG_DCB */
-
-#ifdef HAVE_NETDEV_OPS_FCOE_GETWWN
-/**
- * ixgbe_fcoe_get_wwn - get world wide name for the node or the port
- * @netdev : ixgbe adapter
- * @wwn : the world wide name
- * @type: the type of world wide name
- *
- * Returns the node or port world wide name if both the prefix and the san
- * mac address are valid, then the wwn is formed based on the NAA-2 for
- * IEEE Extended name identifier (ref. to T10 FC-LS Spec., Sec. 15.3).
- *
- * Returns : 0 on success
- */
-int ixgbe_fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type)
-{
-	int rc = -EINVAL;
-	u16 prefix = 0xffff;
-	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	struct ixgbe_mac_info *mac = &adapter->hw.mac;
-
-	switch (type) {
-	case NETDEV_FCOE_WWNN:
-		prefix = mac->wwnn_prefix;
-		break;
-	case NETDEV_FCOE_WWPN:
-		prefix = mac->wwpn_prefix;
-		break;
-	default:
-		break;
-	}
-
-	if ((prefix != 0xffff) &&
-	    is_valid_ether_addr(mac->san_addr)) {
-		*wwn = ((u64) prefix << 48) |
-		       ((u64) mac->san_addr[0] << 40) |
-		       ((u64) mac->san_addr[1] << 32) |
-		       ((u64) mac->san_addr[2] << 24) |
-		       ((u64) mac->san_addr[3] << 16) |
-		       ((u64) mac->san_addr[4] << 8)  |
-		       ((u64) mac->san_addr[5]);
-		rc = 0;
-	}
-	return rc;
-}
-#endif /* HAVE_NETDEV_OPS_FCOE_GETWWN */
-#endif /* IXGBE_FCOE */
diff -Naur src.orig/ixgbe_fcoe.h src/ixgbe_fcoe.h
--- src.orig/ixgbe_fcoe.h	2011-09-20 22:31:44.000000000 +0000
+++ src/ixgbe_fcoe.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,87 +0,0 @@
-/*******************************************************************************
-
-  Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms and conditions of the GNU General Public License,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Contact Information:
-  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-*******************************************************************************/
-
-#ifndef _IXGBE_FCOE_H
-#define _IXGBE_FCOE_H
-
-#ifdef IXGBE_FCOE
-
-#include <scsi/fc/fc_fs.h>
-#include <scsi/fc/fc_fcoe.h>
-
-/* shift bits within STAT fo FCSTAT */
-#define IXGBE_RXDADV_FCSTAT_SHIFT	4
-
-/* ddp user buffer */
-#define IXGBE_BUFFCNT_MAX	256	/* 8 bits bufcnt */
-#define IXGBE_FCPTR_ALIGN	16
-#define IXGBE_FCPTR_MAX	(IXGBE_BUFFCNT_MAX * sizeof(dma_addr_t))
-#define IXGBE_FCBUFF_4KB	0x0
-#define IXGBE_FCBUFF_8KB	0x1
-#define IXGBE_FCBUFF_16KB	0x2
-#define IXGBE_FCBUFF_64KB	0x3
-#define IXGBE_FCBUFF_MAX	65536	/* 64KB max */
-#define IXGBE_FCBUFF_MIN	4096	/* 4KB min */
-#define IXGBE_FCOE_DDP_MAX	512	/* 9 bits xid */
-
-/* Default traffic class to use for FCoE */
-#define IXGBE_FCOE_DEFTC	3
-
-/* fcerr */
-#define IXGBE_FCERR_BADCRC       0x00100000
-#define IXGBE_FCERR_EOFSOF       0x00200000
-#define IXGBE_FCERR_NOFIRST      0x00300000
-#define IXGBE_FCERR_OOOSEQ       0x00400000
-#define IXGBE_FCERR_NODMA        0x00500000
-#define IXGBE_FCERR_PKTLOST      0x00600000
-
-/* FCoE DDP for target mode */
-#define __IXGBE_FCOE_TARGET	1
-
-struct ixgbe_fcoe_ddp {
-	int len;
-	u32 err;
-	unsigned int sgc;
-	struct scatterlist *sgl;
-	dma_addr_t udp;
-	u64 *udl;
-};
-
-struct ixgbe_fcoe {
-	u8 tc;
-	u8 up;
-	unsigned long mode;
-	atomic_t refcnt;
-	spinlock_t lock;
-	struct pci_pool *pool;
-	struct ixgbe_fcoe_ddp ddp[IXGBE_FCOE_DDP_MAX];
-	unsigned char *extra_ddp_buffer;
-	dma_addr_t extra_ddp_buffer_dma;
-};
-#endif /* IXGBE_FCOE */
-
-#endif /* _IXGBE_FCOE_H */
diff -Naur src.orig/ixgbe_main.c src/ixgbe_main.c
--- src.orig/ixgbe_main.c	2011-09-20 22:31:44.000000000 +0000
+++ src/ixgbe_main.c	2011-11-09 17:25:47.000000000 +0000
@@ -79,7 +79,10 @@
 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." __stringify(BUILD) DRIVERNAPI DRV_HW_PERF FPGA VMDQ_TAG
 const char ixgbe_driver_version[] = DRV_VERSION;
 static const char ixgbe_copyright[] =
-				"Copyright (c) 1999-2011 Intel Corporation.";
+  "Copyright (c) 1999-2011 Intel Corporation.";
+
+extern int __sc_netif_rx__(struct sk_buff *skb);
+
 /* ixgbe_pci_tbl - PCI Device ID Table
  *
  * Wildcard entries (PCI_ANY_ID) should come last
@@ -1041,13 +1044,10 @@
 	} else {
 #endif /* NETIF_F_HW_VLAN_TX */
 #ifdef CONFIG_IXGBE_NAPI
-		if (adapter->flags & IXGBE_FLAG_IN_NETPOLL)
-			netif_rx(skb);
-		else
-			napi_gro_receive(&q_vector->napi, skb);
+          __sc_netif_rx__(skb);
 #else
-		if (netif_rx(skb) == NET_RX_DROP)
-			adapter->rx_dropped_backlog++;
+          if (__sc_netif_rx__(skb) == NET_RX_DROP)
+            adapter->rx_dropped_backlog++;
 #endif
 #ifdef NETIF_F_HW_VLAN_TX
 	}
@@ -1208,10 +1208,10 @@
 	ixgbe_receive_skb(q_vector, skb);
 #else
 #ifdef CONFIG_IXGBE_NAPI
-	napi_gro_receive(&q_vector->napi, skb);
+        __sc_netif_rx__(skb);
 #else
-	if (netif_rx(skb) == NET_RX_DROP)
-		q_vector->adapter->rx_dropped_backlog++;
+	if (__sc_netif_rx__(skb) == NET_RX_DROP)
+          q_vector->adapter->rx_dropped_backlog++;
 #endif
 #endif
 	lrolist->stats.flushed++;
@@ -1484,10 +1484,10 @@
 	ixgbe_receive_skb(q_vector, new_skb);
 #else
 #ifdef CONFIG_IXGBE_NAPI
-	napi_gro_receive(&q_vector->napi, new_skb);
+        __sc_netif_rx__(new_skb);
 #else
-	if (netif_rx(new_skb) == NET_RX_DROP)
-		q_vector->adapter->rx_dropped_backlog++;
+	if (__sc_netif_rx__(new_skb) == NET_RX_DROP)
+          q_vector->adapter->rx_dropped_backlog++;
 #endif
 #endif /* HAVE_VLAN_RX_REGISTER */
 	return NULL;
@@ -1748,13 +1748,13 @@
 		else
 #endif
 #ifdef HAVE_VLAN_RX_REGISTER
-			ixgbe_receive_skb(q_vector, skb);
+                        ixgbe_receive_skb(q_vector, skb);
 #else
 #ifdef CONFIG_IXGBE_NAPI
-			napi_gro_receive(&q_vector->napi, skb);
+                __sc_netif_rx__(skb);
 #else
-			if (netif_rx(skb) == NET_RX_DROP)
-				q_vector->adapter->rx_dropped_backlog++;
+                if (__sc_netif_rx__(skb) == NET_RX_DROP)
+                  q_vector->adapter->rx_dropped_backlog++;
 #endif
 #endif
 
@@ -9656,6 +9656,9 @@
 	pr_info("%s - version %s\n", ixgbe_driver_string, ixgbe_driver_version);
 	pr_info("%s\n", ixgbe_copyright);
 
+	/* pr_info("netdev offset in private pci data: %lu\n", */
+	/*         offsetof(struct ixgbe_adapter, netdev)); */
+
 #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
 	dca_register_notify(&dca_notifier);
 
diff -Naur src.orig/kcompat_ethtool.c src/kcompat_ethtool.c
--- src.orig/kcompat_ethtool.c	2011-09-20 22:31:44.000000000 +0000
+++ src/kcompat_ethtool.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,1172 +0,0 @@
-/*******************************************************************************
-
-  Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2011 Intel Corporation.
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms and conditions of the GNU General Public License,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Contact Information:
-  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
-  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-
-*******************************************************************************/
-
-/*
- * net/core/ethtool.c - Ethtool ioctl handler
- * Copyright (c) 2003 Matthew Wilcox <matthew@wil.cx>
- *
- * This file is where we call all the ethtool_ops commands to get
- * the information ethtool needs.  We fall back to calling do_ioctl()
- * for drivers which haven't been converted to ethtool_ops yet.
- *
- * It's GPL, stupid.
- *
- * Modification by sfeldma@pobox.com to work as backward compat
- * solution for pre-ethtool_ops kernels.
- * 	- copied struct ethtool_ops from ethtool.h
- * 	- defined SET_ETHTOOL_OPS
- * 	- put in some #ifndef NETIF_F_xxx wrappers
- * 	- changes refs to dev->ethtool_ops to ethtool_ops
- * 	- changed dev_ethtool to ethtool_ioctl
- *      - remove EXPORT_SYMBOL()s
- *      - added _kc_ prefix in built-in ethtool_op_xxx ops.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/mii.h>
-#include <linux/ethtool.h>
-#include <linux/netdevice.h>
-#include <asm/uaccess.h>
-
-#include "kcompat.h"
-
-#undef SUPPORTED_10000baseT_Full
-#define SUPPORTED_10000baseT_Full	(1 << 12)
-#undef ADVERTISED_10000baseT_Full
-#define ADVERTISED_10000baseT_Full	(1 << 12)
-#undef SPEED_10000
-#define SPEED_10000		10000
-
-#undef ethtool_ops
-#define ethtool_ops _kc_ethtool_ops
-
-struct _kc_ethtool_ops {
-	int  (*get_settings)(struct net_device *, struct ethtool_cmd *);
-	int  (*set_settings)(struct net_device *, struct ethtool_cmd *);
-	void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *);
-	int  (*get_regs_len)(struct net_device *);
-	void (*get_regs)(struct net_device *, struct ethtool_regs *, void *);
-	void (*get_wol)(struct net_device *, struct ethtool_wolinfo *);
-	int  (*set_wol)(struct net_device *, struct ethtool_wolinfo *);
-	u32  (*get_msglevel)(struct net_device *);
-	void (*set_msglevel)(struct net_device *, u32);
-	int  (*nway_reset)(struct net_device *);
-	u32  (*get_link)(struct net_device *);
-	int  (*get_eeprom_len)(struct net_device *);
-	int  (*get_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *);
-	int  (*set_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *);
-	int  (*get_coalesce)(struct net_device *, struct ethtool_coalesce *);
-	int  (*set_coalesce)(struct net_device *, struct ethtool_coalesce *);
-	void (*get_ringparam)(struct net_device *, struct ethtool_ringparam *);
-	int  (*set_ringparam)(struct net_device *, struct ethtool_ringparam *);
-	void (*get_pauseparam)(struct net_device *,
-	                       struct ethtool_pauseparam*);
-	int  (*set_pauseparam)(struct net_device *,
-	                       struct ethtool_pauseparam*);
-	u32  (*get_rx_csum)(struct net_device *);
-	int  (*set_rx_csum)(struct net_device *, u32);
-	u32  (*get_tx_csum)(struct net_device *);
-	int  (*set_tx_csum)(struct net_device *, u32);
-	u32  (*get_sg)(struct net_device *);
-	int  (*set_sg)(struct net_device *, u32);
-	u32  (*get_tso)(struct net_device *);
-	int  (*set_tso)(struct net_device *, u32);
-	int  (*self_test_count)(struct net_device *);
-	void (*self_test)(struct net_device *, struct ethtool_test *, u64 *);
-	void (*get_strings)(struct net_device *, u32 stringset, u8 *);
-	int  (*phys_id)(struct net_device *, u32);
-	int  (*get_stats_count)(struct net_device *);
-	void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *,
-	                          u64 *);
-} *ethtool_ops = NULL;
-
-#undef SET_ETHTOOL_OPS
-#define SET_ETHTOOL_OPS(netdev, ops) (ethtool_ops = (ops))
-
-/*
- * Some useful ethtool_ops methods that are device independent. If we find that
- * all drivers want to do the same thing here, we can turn these into dev_()
- * function calls.
- */
-
-#undef ethtool_op_get_link
-#define ethtool_op_get_link _kc_ethtool_op_get_link
-u32 _kc_ethtool_op_get_link(struct net_device *dev)
-{
-	return netif_carrier_ok(dev) ? 1 : 0;
-}
-
-#undef ethtool_op_get_tx_csum
-#define ethtool_op_get_tx_csum _kc_ethtool_op_get_tx_csum
-u32 _kc_ethtool_op_get_tx_csum(struct net_device *dev)
-{
-#ifdef NETIF_F_IP_CSUM
-	return (dev->features & NETIF_F_IP_CSUM) != 0;
-#else
-	return 0;
-#endif
-}
-
-#undef ethtool_op_set_tx_csum
-#define ethtool_op_set_tx_csum _kc_ethtool_op_set_tx_csum
-int _kc_ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
-{
-#ifdef NETIF_F_IP_CSUM
-	if (data)
-#ifdef NETIF_F_IPV6_CSUM
-		dev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-	else
-		dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
-#else
-		dev->features |= NETIF_F_IP_CSUM;
-	else
-		dev->features &= ~NETIF_F_IP_CSUM;
-#endif
-#endif
-
-	return 0;
-}
-
-#undef ethtool_op_get_sg
-#define ethtool_op_get_sg _kc_ethtool_op_get_sg
-u32 _kc_ethtool_op_get_sg(struct net_device *dev)
-{
-#ifdef NETIF_F_SG
-	return (dev->features & NETIF_F_SG) != 0;
-#else
-	return 0;
-#endif
-}
-
-#undef ethtool_op_set_sg
-#define ethtool_op_set_sg _kc_ethtool_op_set_sg
-int _kc_ethtool_op_set_sg(struct net_device *dev, u32 data)
-{
-#ifdef NETIF_F_SG
-	if (data)
-		dev->features |= NETIF_F_SG;
-	else
-		dev->features &= ~NETIF_F_SG;
-#endif
-
-	return 0;
-}
-
-#undef ethtool_op_get_tso
-#define ethtool_op_get_tso _kc_ethtool_op_get_tso
-u32 _kc_ethtool_op_get_tso(struct net_device *dev)
-{
-#ifdef NETIF_F_TSO
-	return (dev->features & NETIF_F_TSO) != 0;
-#else
-	return 0;
-#endif
-}
-
-#undef ethtool_op_set_tso
-#define ethtool_op_set_tso _kc_ethtool_op_set_tso
-int _kc_ethtool_op_set_tso(struct net_device *dev, u32 data)
-{
-#ifdef NETIF_F_TSO
-	if (data)
-		dev->features |= NETIF_F_TSO;
-	else
-		dev->features &= ~NETIF_F_TSO;
-#endif
-
-	return 0;
-}
-
-/* Handlers for each ethtool command */
-
-static int ethtool_get_settings(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_cmd cmd = { ETHTOOL_GSET };
-	int err;
-
-	if (!ethtool_ops->get_settings)
-		return -EOPNOTSUPP;
-
-	err = ethtool_ops->get_settings(dev, &cmd);
-	if (err < 0)
-		return err;
-
-	if (copy_to_user(useraddr, &cmd, sizeof(cmd)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_set_settings(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_cmd cmd;
-
-	if (!ethtool_ops->set_settings)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
-		return -EFAULT;
-
-	return ethtool_ops->set_settings(dev, &cmd);
-}
-
-static int ethtool_get_drvinfo(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_drvinfo info;
-	struct ethtool_ops *ops = ethtool_ops;
-
-	if (!ops->get_drvinfo)
-		return -EOPNOTSUPP;
-
-	memset(&info, 0, sizeof(info));
-	info.cmd = ETHTOOL_GDRVINFO;
-	ops->get_drvinfo(dev, &info);
-
-	if (ops->self_test_count)
-		info.testinfo_len = ops->self_test_count(dev);
-	if (ops->get_stats_count)
-		info.n_stats = ops->get_stats_count(dev);
-	if (ops->get_regs_len)
-		info.regdump_len = ops->get_regs_len(dev);
-	if (ops->get_eeprom_len)
-		info.eedump_len = ops->get_eeprom_len(dev);
-
-	if (copy_to_user(useraddr, &info, sizeof(info)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_get_regs(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_regs regs;
-	struct ethtool_ops *ops = ethtool_ops;
-	void *regbuf;
-	int reglen, ret;
-
-	if (!ops->get_regs || !ops->get_regs_len)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&regs, useraddr, sizeof(regs)))
-		return -EFAULT;
-
-	reglen = ops->get_regs_len(dev);
-	if (regs.len > reglen)
-		regs.len = reglen;
-
-	regbuf = kmalloc(reglen, GFP_USER);
-	if (!regbuf)
-		return -ENOMEM;
-
-	ops->get_regs(dev, &regs, regbuf);
-
-	ret = -EFAULT;
-	if (copy_to_user(useraddr, &regs, sizeof(regs)))
-		goto out;
-	useraddr += offsetof(struct ethtool_regs, data);
-	if (copy_to_user(useraddr, regbuf, reglen))
-		goto out;
-	ret = 0;
-
-out:
-	kfree(regbuf);
-	return ret;
-}
-
-static int ethtool_get_wol(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_wolinfo wol = { ETHTOOL_GWOL };
-
-	if (!ethtool_ops->get_wol)
-		return -EOPNOTSUPP;
-
-	ethtool_ops->get_wol(dev, &wol);
-
-	if (copy_to_user(useraddr, &wol, sizeof(wol)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_set_wol(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_wolinfo wol;
-
-	if (!ethtool_ops->set_wol)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&wol, useraddr, sizeof(wol)))
-		return -EFAULT;
-
-	return ethtool_ops->set_wol(dev, &wol);
-}
-
-static int ethtool_get_msglevel(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_value edata = { ETHTOOL_GMSGLVL };
-
-	if (!ethtool_ops->get_msglevel)
-		return -EOPNOTSUPP;
-
-	edata.data = ethtool_ops->get_msglevel(dev);
-
-	if (copy_to_user(useraddr, &edata, sizeof(edata)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_set_msglevel(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_value edata;
-
-	if (!ethtool_ops->set_msglevel)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&edata, useraddr, sizeof(edata)))
-		return -EFAULT;
-
-	ethtool_ops->set_msglevel(dev, edata.data);
-	return 0;
-}
-
-static int ethtool_nway_reset(struct net_device *dev)
-{
-	if (!ethtool_ops->nway_reset)
-		return -EOPNOTSUPP;
-
-	return ethtool_ops->nway_reset(dev);
-}
-
-static int ethtool_get_link(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_value edata = { ETHTOOL_GLINK };
-
-	if (!ethtool_ops->get_link)
-		return -EOPNOTSUPP;
-
-	edata.data = ethtool_ops->get_link(dev);
-
-	if (copy_to_user(useraddr, &edata, sizeof(edata)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_get_eeprom(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_eeprom eeprom;
-	struct ethtool_ops *ops = ethtool_ops;
-	u8 *data;
-	int ret;
-
-	if (!ops->get_eeprom || !ops->get_eeprom_len)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
-		return -EFAULT;
-
-	/* Check for wrap and zero */
-	if (eeprom.offset + eeprom.len <= eeprom.offset)
-		return -EINVAL;
-
-	/* Check for exceeding total eeprom len */
-	if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev))
-		return -EINVAL;
-
-	data = kmalloc(eeprom.len, GFP_USER);
-	if (!data)
-		return -ENOMEM;
-
-	ret = -EFAULT;
-	if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len))
-		goto out;
-
-	ret = ops->get_eeprom(dev, &eeprom, data);
-	if (ret)
-		goto out;
-
-	ret = -EFAULT;
-	if (copy_to_user(useraddr, &eeprom, sizeof(eeprom)))
-		goto out;
-	if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len))
-		goto out;
-	ret = 0;
-
-out:
-	kfree(data);
-	return ret;
-}
-
-static int ethtool_set_eeprom(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_eeprom eeprom;
-	struct ethtool_ops *ops = ethtool_ops;
-	u8 *data;
-	int ret;
-
-	if (!ops->set_eeprom || !ops->get_eeprom_len)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
-		return -EFAULT;
-
-	/* Check for wrap and zero */
-	if (eeprom.offset + eeprom.len <= eeprom.offset)
-		return -EINVAL;
-
-	/* Check for exceeding total eeprom len */
-	if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev))
-		return -EINVAL;
-
-	data = kmalloc(eeprom.len, GFP_USER);
-	if (!data)
-		return -ENOMEM;
-
-	ret = -EFAULT;
-	if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len))
-		goto out;
-
-	ret = ops->set_eeprom(dev, &eeprom, data);
-	if (ret)
-		goto out;
-
-	if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len))
-		ret = -EFAULT;
-
-out:
-	kfree(data);
-	return ret;
-}
-
-static int ethtool_get_coalesce(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_coalesce coalesce = { ETHTOOL_GCOALESCE };
-
-	if (!ethtool_ops->get_coalesce)
-		return -EOPNOTSUPP;
-
-	ethtool_ops->get_coalesce(dev, &coalesce);
-
-	if (copy_to_user(useraddr, &coalesce, sizeof(coalesce)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_set_coalesce(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_coalesce coalesce;
-
-	if (!ethtool_ops->get_coalesce)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&coalesce, useraddr, sizeof(coalesce)))
-		return -EFAULT;
-
-	return ethtool_ops->set_coalesce(dev, &coalesce);
-}
-
-static int ethtool_get_ringparam(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_ringparam ringparam = { ETHTOOL_GRINGPARAM };
-
-	if (!ethtool_ops->get_ringparam)
-		return -EOPNOTSUPP;
-
-	ethtool_ops->get_ringparam(dev, &ringparam);
-
-	if (copy_to_user(useraddr, &ringparam, sizeof(ringparam)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_set_ringparam(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_ringparam ringparam;
-
-	if (!ethtool_ops->get_ringparam)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&ringparam, useraddr, sizeof(ringparam)))
-		return -EFAULT;
-
-	return ethtool_ops->set_ringparam(dev, &ringparam);
-}
-
-static int ethtool_get_pauseparam(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM };
-
-	if (!ethtool_ops->get_pauseparam)
-		return -EOPNOTSUPP;
-
-	ethtool_ops->get_pauseparam(dev, &pauseparam);
-
-	if (copy_to_user(useraddr, &pauseparam, sizeof(pauseparam)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_set_pauseparam(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_pauseparam pauseparam;
-
-	if (!ethtool_ops->get_pauseparam)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam)))
-		return -EFAULT;
-
-	return ethtool_ops->set_pauseparam(dev, &pauseparam);
-}
-
-static int ethtool_get_rx_csum(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_value edata = { ETHTOOL_GRXCSUM };
-
-	if (!ethtool_ops->get_rx_csum)
-		return -EOPNOTSUPP;
-
-	edata.data = ethtool_ops->get_rx_csum(dev);
-
-	if (copy_to_user(useraddr, &edata, sizeof(edata)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_set_rx_csum(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_value edata;
-
-	if (!ethtool_ops->set_rx_csum)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&edata, useraddr, sizeof(edata)))
-		return -EFAULT;
-
-	ethtool_ops->set_rx_csum(dev, edata.data);
-	return 0;
-}
-
-static int ethtool_get_tx_csum(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_value edata = { ETHTOOL_GTXCSUM };
-
-	if (!ethtool_ops->get_tx_csum)
-		return -EOPNOTSUPP;
-
-	edata.data = ethtool_ops->get_tx_csum(dev);
-
-	if (copy_to_user(useraddr, &edata, sizeof(edata)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_set_tx_csum(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_value edata;
-
-	if (!ethtool_ops->set_tx_csum)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&edata, useraddr, sizeof(edata)))
-		return -EFAULT;
-
-	return ethtool_ops->set_tx_csum(dev, edata.data);
-}
-
-static int ethtool_get_sg(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_value edata = { ETHTOOL_GSG };
-
-	if (!ethtool_ops->get_sg)
-		return -EOPNOTSUPP;
-
-	edata.data = ethtool_ops->get_sg(dev);
-
-	if (copy_to_user(useraddr, &edata, sizeof(edata)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_set_sg(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_value edata;
-
-	if (!ethtool_ops->set_sg)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&edata, useraddr, sizeof(edata)))
-		return -EFAULT;
-
-	return ethtool_ops->set_sg(dev, edata.data);
-}
-
-static int ethtool_get_tso(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_value edata = { ETHTOOL_GTSO };
-
-	if (!ethtool_ops->get_tso)
-		return -EOPNOTSUPP;
-
-	edata.data = ethtool_ops->get_tso(dev);
-
-	if (copy_to_user(useraddr, &edata, sizeof(edata)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_set_tso(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_value edata;
-
-	if (!ethtool_ops->set_tso)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&edata, useraddr, sizeof(edata)))
-		return -EFAULT;
-
-	return ethtool_ops->set_tso(dev, edata.data);
-}
-
-static int ethtool_self_test(struct net_device *dev, char *useraddr)
-{
-	struct ethtool_test test;
-	struct ethtool_ops *ops = ethtool_ops;
-	u64 *data;
-	int ret;
-
-	if (!ops->self_test || !ops->self_test_count)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&test, useraddr, sizeof(test)))
-		return -EFAULT;
-
-	test.len = ops->self_test_count(dev);
-	data = kmalloc(test.len * sizeof(u64), GFP_USER);
-	if (!data)
-		return -ENOMEM;
-
-	ops->self_test(dev, &test, data);
-
-	ret = -EFAULT;
-	if (copy_to_user(useraddr, &test, sizeof(test)))
-		goto out;
-	useraddr += sizeof(test);
-	if (copy_to_user(useraddr, data, test.len * sizeof(u64)))
-		goto out;
-	ret = 0;
-
-out:
-	kfree(data);
-	return ret;
-}
-
-static int ethtool_get_strings(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_gstrings gstrings;
-	struct ethtool_ops *ops = ethtool_ops;
-	u8 *data;
-	int ret;
-
-	if (!ops->get_strings)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&gstrings, useraddr, sizeof(gstrings)))
-		return -EFAULT;
-
-	switch (gstrings.string_set) {
-	case ETH_SS_TEST:
-		if (!ops->self_test_count)
-			return -EOPNOTSUPP;
-		gstrings.len = ops->self_test_count(dev);
-		break;
-	case ETH_SS_STATS:
-		if (!ops->get_stats_count)
-			return -EOPNOTSUPP;
-		gstrings.len = ops->get_stats_count(dev);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);
-	if (!data)
-		return -ENOMEM;
-
-	ops->get_strings(dev, gstrings.string_set, data);
-
-	ret = -EFAULT;
-	if (copy_to_user(useraddr, &gstrings, sizeof(gstrings)))
-		goto out;
-	useraddr += sizeof(gstrings);
-	if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN))
-		goto out;
-	ret = 0;
-
-out:
-	kfree(data);
-	return ret;
-}
-
-static int ethtool_phys_id(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_value id;
-
-	if (!ethtool_ops->phys_id)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&id, useraddr, sizeof(id)))
-		return -EFAULT;
-
-	return ethtool_ops->phys_id(dev, id.data);
-}
-
-static int ethtool_get_stats(struct net_device *dev, void *useraddr)
-{
-	struct ethtool_stats stats;
-	struct ethtool_ops *ops = ethtool_ops;
-	u64 *data;
-	int ret;
-
-	if (!ops->get_ethtool_stats || !ops->get_stats_count)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&stats, useraddr, sizeof(stats)))
-		return -EFAULT;
-
-	stats.n_stats = ops->get_stats_count(dev);
-	data = kmalloc(stats.n_stats * sizeof(u64), GFP_USER);
-	if (!data)
-		return -ENOMEM;
-
-	ops->get_ethtool_stats(dev, &stats, data);
-
-	ret = -EFAULT;
-	if (copy_to_user(useraddr, &stats, sizeof(stats)))
-		goto out;
-	useraddr += sizeof(stats);
-	if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64)))
-		goto out;
-	ret = 0;
-
-out:
-	kfree(data);
-	return ret;
-}
-
-/* The main entry point in this file.  Called from net/core/dev.c */
-
-#define ETHTOOL_OPS_COMPAT
-int ethtool_ioctl(struct ifreq *ifr)
-{
-	struct net_device *dev = __dev_get_by_name(ifr->ifr_name);
-	void *useraddr = (void *) ifr->ifr_data;
-	u32 ethcmd;
-
-	/*
-	 * XXX: This can be pushed down into the ethtool_* handlers that
-	 * need it.  Keep existing behavior for the moment.
-	 */
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
-	if (!dev || !netif_device_present(dev))
-		return -ENODEV;
-
-	if (copy_from_user(&ethcmd, useraddr, sizeof (ethcmd)))
-		return -EFAULT;
-
-	switch (ethcmd) {
-	case ETHTOOL_GSET:
-		return ethtool_get_settings(dev, useraddr);
-	case ETHTOOL_SSET:
-		return ethtool_set_settings(dev, useraddr);
-	case ETHTOOL_GDRVINFO:
-		return ethtool_get_drvinfo(dev, useraddr);
-	case ETHTOOL_GREGS:
-		return ethtool_get_regs(dev, useraddr);
-	case ETHTOOL_GWOL:
-		return ethtool_get_wol(dev, useraddr);
-	case ETHTOOL_SWOL:
-		return ethtool_set_wol(dev, useraddr);
-	case ETHTOOL_GMSGLVL:
-		return ethtool_get_msglevel(dev, useraddr);
-	case ETHTOOL_SMSGLVL:
-		return ethtool_set_msglevel(dev, useraddr);
-	case ETHTOOL_NWAY_RST:
-		return ethtool_nway_reset(dev);
-	case ETHTOOL_GLINK:
-		return ethtool_get_link(dev, useraddr);
-	case ETHTOOL_GEEPROM:
-		return ethtool_get_eeprom(dev, useraddr);
-	case ETHTOOL_SEEPROM:
-		return ethtool_set_eeprom(dev, useraddr);
-	case ETHTOOL_GCOALESCE:
-		return ethtool_get_coalesce(dev, useraddr);
-	case ETHTOOL_SCOALESCE:
-		return ethtool_set_coalesce(dev, useraddr);
-	case ETHTOOL_GRINGPARAM:
-		return ethtool_get_ringparam(dev, useraddr);
-	case ETHTOOL_SRINGPARAM:
-		return ethtool_set_ringparam(dev, useraddr);
-	case ETHTOOL_GPAUSEPARAM:
-		return ethtool_get_pauseparam(dev, useraddr);
-	case ETHTOOL_SPAUSEPARAM:
-		return ethtool_set_pauseparam(dev, useraddr);
-	case ETHTOOL_GRXCSUM:
-		return ethtool_get_rx_csum(dev, useraddr);
-	case ETHTOOL_SRXCSUM:
-		return ethtool_set_rx_csum(dev, useraddr);
-	case ETHTOOL_GTXCSUM:
-		return ethtool_get_tx_csum(dev, useraddr);
-	case ETHTOOL_STXCSUM:
-		return ethtool_set_tx_csum(dev, useraddr);
-	case ETHTOOL_GSG:
-		return ethtool_get_sg(dev, useraddr);
-	case ETHTOOL_SSG:
-		return ethtool_set_sg(dev, useraddr);
-	case ETHTOOL_GTSO:
-		return ethtool_get_tso(dev, useraddr);
-	case ETHTOOL_STSO:
-		return ethtool_set_tso(dev, useraddr);
-	case ETHTOOL_TEST:
-		return ethtool_self_test(dev, useraddr);
-	case ETHTOOL_GSTRINGS:
-		return ethtool_get_strings(dev, useraddr);
-	case ETHTOOL_PHYS_ID:
-		return ethtool_phys_id(dev, useraddr);
-	case ETHTOOL_GSTATS:
-		return ethtool_get_stats(dev, useraddr);
-	default:
-		return -EOPNOTSUPP;
-	}
-
-	return -EOPNOTSUPP;
-}
-
-#define mii_if_info _kc_mii_if_info
-struct _kc_mii_if_info {
-	int phy_id;
-	int advertising;
-	int phy_id_mask;
-	int reg_num_mask;
-
-	unsigned int full_duplex : 1;	/* is full duplex? */
-	unsigned int force_media : 1;	/* is autoneg. disabled? */
-
-	struct net_device *dev;
-	int (*mdio_read) (struct net_device *dev, int phy_id, int location);
-	void (*mdio_write) (struct net_device *dev, int phy_id, int location, int val);
-};
-
-struct ethtool_cmd;
-struct mii_ioctl_data;
-
-#undef mii_link_ok
-#define mii_link_ok _kc_mii_link_ok
-#undef mii_nway_restart
-#define mii_nway_restart _kc_mii_nway_restart
-#undef mii_ethtool_gset
-#define mii_ethtool_gset _kc_mii_ethtool_gset
-#undef mii_ethtool_sset
-#define mii_ethtool_sset _kc_mii_ethtool_sset
-#undef mii_check_link
-#define mii_check_link _kc_mii_check_link
-extern int _kc_mii_link_ok (struct mii_if_info *mii);
-extern int _kc_mii_nway_restart (struct mii_if_info *mii);
-extern int _kc_mii_ethtool_gset(struct mii_if_info *mii,
-                                struct ethtool_cmd *ecmd);
-extern int _kc_mii_ethtool_sset(struct mii_if_info *mii,
-                                struct ethtool_cmd *ecmd);
-extern void _kc_mii_check_link (struct mii_if_info *mii);
-#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,4,6) )
-#undef generic_mii_ioctl
-#define generic_mii_ioctl _kc_generic_mii_ioctl
-extern int _kc_generic_mii_ioctl(struct mii_if_info *mii_if,
-                                 struct mii_ioctl_data *mii_data, int cmd,
-                                 unsigned int *duplex_changed);
-#endif /* > 2.4.6 */
-
-
-struct _kc_pci_dev_ext {
-	struct pci_dev *dev;
-	void *pci_drvdata;
-	struct pci_driver *driver;
-};
-
-struct _kc_net_dev_ext {
-	struct net_device *dev;
-	unsigned int carrier;
-};
-
-
-/**************************************/
-/* mii support */
-
-int _kc_mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
-{
-	struct net_device *dev = mii->dev;
-	u32 advert, bmcr, lpa, nego;
-
-	ecmd->supported =
-	    (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
-	     SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
-	     SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII);
-
-	/* only supports twisted-pair */
-	ecmd->port = PORT_MII;
-
-	/* only supports internal transceiver */
-	ecmd->transceiver = XCVR_INTERNAL;
-
-	/* this isn't fully supported at higher layers */
-	ecmd->phy_address = mii->phy_id;
-
-	ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII;
-	advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
-	if (advert & ADVERTISE_10HALF)
-		ecmd->advertising |= ADVERTISED_10baseT_Half;
-	if (advert & ADVERTISE_10FULL)
-		ecmd->advertising |= ADVERTISED_10baseT_Full;
-	if (advert & ADVERTISE_100HALF)
-		ecmd->advertising |= ADVERTISED_100baseT_Half;
-	if (advert & ADVERTISE_100FULL)
-		ecmd->advertising |= ADVERTISED_100baseT_Full;
-
-	bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
-	lpa = mii->mdio_read(dev, mii->phy_id, MII_LPA);
-	if (bmcr & BMCR_ANENABLE) {
-		ecmd->advertising |= ADVERTISED_Autoneg;
-		ecmd->autoneg = AUTONEG_ENABLE;
-
-		nego = mii_nway_result(advert & lpa);
-		if (nego == LPA_100FULL || nego == LPA_100HALF)
-			ecmd->speed = SPEED_100;
-		else
-			ecmd->speed = SPEED_10;
-		if (nego == LPA_100FULL || nego == LPA_10FULL) {
-			ecmd->duplex = DUPLEX_FULL;
-			mii->full_duplex = 1;
-		} else {
-			ecmd->duplex = DUPLEX_HALF;
-			mii->full_duplex = 0;
-		}
-	} else {
-		ecmd->autoneg = AUTONEG_DISABLE;
-
-		ecmd->speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
-		ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
-	}
-
-	/* ignore maxtxpkt, maxrxpkt for now */
-
-	return 0;
-}
-
-int _kc_mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
-{
-	struct net_device *dev = mii->dev;
-
-	if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100)
-		return -EINVAL;
-	if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
-		return -EINVAL;
-	if (ecmd->port != PORT_MII)
-		return -EINVAL;
-	if (ecmd->transceiver != XCVR_INTERNAL)
-		return -EINVAL;
-	if (ecmd->phy_address != mii->phy_id)
-		return -EINVAL;
-	if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)
-		return -EINVAL;
-
-	/* ignore supported, maxtxpkt, maxrxpkt */
-
-	if (ecmd->autoneg == AUTONEG_ENABLE) {
-		u32 bmcr, advert, tmp;
-
-		if ((ecmd->advertising & (ADVERTISED_10baseT_Half |
-					  ADVERTISED_10baseT_Full |
-					  ADVERTISED_100baseT_Half |
-					  ADVERTISED_100baseT_Full)) == 0)
-			return -EINVAL;
-
-		/* advertise only what has been requested */
-		advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
-		tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
-		if (ADVERTISED_10baseT_Half)
-			tmp |= ADVERTISE_10HALF;
-		if (ADVERTISED_10baseT_Full)
-			tmp |= ADVERTISE_10FULL;
-		if (ADVERTISED_100baseT_Half)
-			tmp |= ADVERTISE_100HALF;
-		if (ADVERTISED_100baseT_Full)
-			tmp |= ADVERTISE_100FULL;
-		if (advert != tmp) {
-			mii->mdio_write(dev, mii->phy_id, MII_ADVERTISE, tmp);
-			mii->advertising = tmp;
-		}
-
-		/* turn on autonegotiation, and force a renegotiate */
-		bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
-		bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
-		mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr);
-
-		mii->force_media = 0;
-	} else {
-		u32 bmcr, tmp;
-
-		/* turn off auto negotiation, set speed and duplexity */
-		bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
-		tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX);
-		if (ecmd->speed == SPEED_100)
-			tmp |= BMCR_SPEED100;
-		if (ecmd->duplex == DUPLEX_FULL) {
-			tmp |= BMCR_FULLDPLX;
-			mii->full_duplex = 1;
-		} else
-			mii->full_duplex = 0;
-		if (bmcr != tmp)
-			mii->mdio_write(dev, mii->phy_id, MII_BMCR, tmp);
-
-		mii->force_media = 1;
-	}
-	return 0;
-}
-
-int _kc_mii_link_ok (struct mii_if_info *mii)
-{
-	/* first, a dummy read, needed to latch some MII phys */
-	mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
-	if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS)
-		return 1;
-	return 0;
-}
-
-int _kc_mii_nway_restart (struct mii_if_info *mii)
-{
-	int bmcr;
-	int r = -EINVAL;
-
-	/* if autoneg is off, it's an error */
-	bmcr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMCR);
-
-	if (bmcr & BMCR_ANENABLE) {
-		bmcr |= BMCR_ANRESTART;
-		mii->mdio_write(mii->dev, mii->phy_id, MII_BMCR, bmcr);
-		r = 0;
-	}
-
-	return r;
-}
-
-void _kc_mii_check_link (struct mii_if_info *mii)
-{
-	int cur_link = mii_link_ok(mii);
-	int prev_link = netif_carrier_ok(mii->dev);
-
-	if (cur_link && !prev_link)
-		netif_carrier_on(mii->dev);
-	else if (prev_link && !cur_link)
-		netif_carrier_off(mii->dev);
-}
-
-#if ( LINUX_VERSION_CODE > KERNEL_VERSION(2,4,6) )
-int _kc_generic_mii_ioctl(struct mii_if_info *mii_if,
-                          struct mii_ioctl_data *mii_data, int cmd,
-                          unsigned int *duplex_chg_out)
-{
-	int rc = 0;
-	unsigned int duplex_changed = 0;
-
-	if (duplex_chg_out)
-		*duplex_chg_out = 0;
-
-	mii_data->phy_id &= mii_if->phy_id_mask;
-	mii_data->reg_num &= mii_if->reg_num_mask;
-
-	switch(cmd) {
-	case SIOCDEVPRIVATE:	/* binary compat, remove in 2.5 */
-	case SIOCGMIIPHY:
-		mii_data->phy_id = mii_if->phy_id;
-		/* fall through */
-
-	case SIOCDEVPRIVATE + 1:/* binary compat, remove in 2.5 */
-	case SIOCGMIIREG:
-		mii_data->val_out =
-			mii_if->mdio_read(mii_if->dev, mii_data->phy_id,
-					  mii_data->reg_num);
-		break;
-
-	case SIOCDEVPRIVATE + 2:/* binary compat, remove in 2.5 */
-	case SIOCSMIIREG: {
-		u16 val = mii_data->val_in;
-
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-
-		if (mii_data->phy_id == mii_if->phy_id) {
-			switch(mii_data->reg_num) {
-			case MII_BMCR: {
-				unsigned int new_duplex = 0;
-				if (val & (BMCR_RESET|BMCR_ANENABLE))
-					mii_if->force_media = 0;
-				else
-					mii_if->force_media = 1;
-				if (mii_if->force_media &&
-				    (val & BMCR_FULLDPLX))
-					new_duplex = 1;
-				if (mii_if->full_duplex != new_duplex) {
-					duplex_changed = 1;
-					mii_if->full_duplex = new_duplex;
-				}
-				break;
-			}
-			case MII_ADVERTISE:
-				mii_if->advertising = val;
-				break;
-			default:
-				/* do nothing */
-				break;
-			}
-		}
-
-		mii_if->mdio_write(mii_if->dev, mii_data->phy_id,
-				   mii_data->reg_num, val);
-		break;
-	}
-
-	default:
-		rc = -EOPNOTSUPP;
-		break;
-	}
-
-	if ((rc == 0) && (duplex_chg_out) && (duplex_changed))
-		*duplex_chg_out = 1;
-
-	return rc;
-}
-#endif /* > 2.4.6 */
-
