diff mbox series

[v3,05/11] igc: Add support for Tx/Rx rings

Message ID 20180624084508.10153-1-sasha.neftin@intel.com
State RFC
Headers show
Series None | expand

Commit Message

Sasha Neftin June 24, 2018, 8:45 a.m. UTC
This change adds the defines and structures necessary to support both Tx
and Rx descriptor rings.

Sasha Neftin (v2):
fixed code indentation

Sasha Nedftin (v3):
minor code fixes

Signed-off-by: Sasha Neftin <sasha.neftin@intel.com>
---
 drivers/net/ethernet/intel/igc/Makefile        |   3 +-
 drivers/net/ethernet/intel/igc/e1000_base.c    |  83 +++
 drivers/net/ethernet/intel/igc/e1000_base.h    |  89 +++
 drivers/net/ethernet/intel/igc/e1000_defines.h |  53 ++
 drivers/net/ethernet/intel/igc/e1000_hw.h      |   1 +
 drivers/net/ethernet/intel/igc/e1000_regs.h    |   3 +
 drivers/net/ethernet/intel/igc/igc.h           | 127 ++++
 drivers/net/ethernet/intel/igc/igc_main.c      | 839 ++++++++++++++++++++++++-
 8 files changed, 1193 insertions(+), 5 deletions(-)
 create mode 100644 drivers/net/ethernet/intel/igc/e1000_base.c
 create mode 100644 drivers/net/ethernet/intel/igc/e1000_base.h

Comments

kernel test robot June 24, 2018, 2:11 p.m. UTC | #1
Hi Sasha,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on jkirsher-next-queue/dev-queue]
[also build test WARNING on v4.18-rc2 next-20180622]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Sasha-Neftin/igc-Add-skeletal-frame-for-Intel-R-2-5G-Ethernet-Controller-support/20180624-164739
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue.git dev-queue
reproduce:
        # apt-get install sparse
        make ARCH=x86_64 allmodconfig
        make C=1 CF=-D__CHECK_ENDIAN__


sparse warnings: (new ones prefixed by >>)

   include/linux/slab.h:631:13: sparse: undefined identifier '__builtin_mul_overflow'
   drivers/net/ethernet/intel/igc/igc_main.c:1991:17: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:1991:17:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:1991:17:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:1992:17: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:1992:17:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:1992:17:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:1994:17: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:1994:17:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:1994:17:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:1997:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:1997:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:1997:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:1998:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:1998:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:1998:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:2025:17: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:2025:17:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:2025:17:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:2027:17: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:2027:17:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:2027:17:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:2028:17: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:2028:17:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:2028:17:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:2029:17: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:2029:17:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:2029:17:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:2031:17: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:2031:17:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:2031:17:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:2032:17: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:2032:17:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:2032:17:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:1144:17: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:1144:17:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:1144:17:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:1152:17: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:1152:17:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:1152:17:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:1563:25: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:1563:25:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:1563:25:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:1589:23: sparse: expression using sizeof(void)
   drivers/net/ethernet/intel/igc/igc_main.c:1589:23: sparse: expression using sizeof(void)
   drivers/net/ethernet/intel/igc/igc_main.c:1619:27: sparse: expression using sizeof(void)
   drivers/net/ethernet/intel/igc/igc_main.c:1619:27: sparse: expression using sizeof(void)
   drivers/net/ethernet/intel/igc/igc_main.c:1365:33: sparse: expression using sizeof(void)
   drivers/net/ethernet/intel/igc/igc_main.c:1365:33: sparse: expression using sizeof(void)
   drivers/net/ethernet/intel/igc/igc_main.c:1376:25: sparse: expression using sizeof(void)
   drivers/net/ethernet/intel/igc/igc_main.c:77:6: sparse: symbol 'igc_reset' was not declared. Should it be static?
   drivers/net/ethernet/intel/igc/igc_main.c:87:6: sparse: symbol 'igc_power_up_link' was not declared. Should it be static?
   drivers/net/ethernet/intel/igc/igc_main.c:114:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:114:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:114:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:133:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:133:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:133:9:    got unsigned char [usertype] *__val
>> drivers/net/ethernet/intel/igc/igc_main.c:143:6: sparse: symbol 'igc_free_tx_resources' was not declared. Should it be static?
>> drivers/net/ethernet/intel/igc/igc_main.c:174:6: sparse: symbol 'igc_unmap_and_free_tx_resource' was not declared. Should it be static?
>> drivers/net/ethernet/intel/igc/igc_main.c:233:5: sparse: symbol 'igc_setup_tx_resources' was not declared. Should it be static?
>> drivers/net/ethernet/intel/igc/igc_main.c:295:6: sparse: symbol 'igc_clean_rx_ring' was not declared. Should it be static?
>> drivers/net/ethernet/intel/igc/igc_main.c:341:6: sparse: symbol 'igc_free_rx_resources' was not declared. Should it be static?
>> drivers/net/ethernet/intel/igc/igc_main.c:378:5: sparse: symbol 'igc_setup_rx_resources' was not declared. Should it be static?
   drivers/net/ethernet/intel/igc/igc_main.c:462:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:462:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:462:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:465:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:465:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:465:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:467:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:467:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:467:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:468:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:468:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:468:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:473:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:473:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:473:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:488:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:488:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:488:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:505:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:505:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:505:9:    got unsigned char [usertype] *__val
>> drivers/net/ethernet/intel/igc/igc_main.c:452:6: sparse: symbol 'igc_configure_rx_ring' was not declared. Should it be static?
   drivers/net/ethernet/intel/igc/igc_main.c:541:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:541:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:541:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:545:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:545:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:545:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:547:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:547:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:547:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:549:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:549:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:549:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:552:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:552:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:552:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:560:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:560:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:560:9:    got unsigned char [usertype] *__val
>> drivers/net/ethernet/intel/igc/igc_main.c:532:6: sparse: symbol 'igc_configure_tx_ring' was not declared. Should it be static?
   drivers/net/ethernet/intel/igc/igc_main.c:615:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:615:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:615:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:630:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:630:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:630:9:    got unsigned char [usertype] *__val
>> drivers/net/ethernet/intel/igc/igc_main.c:589:6: sparse: symbol 'igc_setup_rctl' was not declared. Should it be static?
   drivers/net/ethernet/intel/igc/igc_main.c:643:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:643:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:643:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:654:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:654:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:654:9:    got unsigned char [usertype] *__val
>> drivers/net/ethernet/intel/igc/igc_main.c:637:6: sparse: symbol 'igc_setup_tctl' was not declared. Should it be static?
>> drivers/net/ethernet/intel/igc/igc_main.c:739:6: sparse: symbol 'igc_alloc_rx_buffers' was not declared. Should it be static?
   drivers/net/ethernet/intel/igc/igc_main.c:822:5: sparse: symbol 'igc_up' was not declared. Should it be static?
   drivers/net/ethernet/intel/igc/igc_main.c:857:6: sparse: symbol 'igc_down' was not declared. Should it be static?
   drivers/net/ethernet/intel/igc/igc_main.c:921:6: sparse: symbol 'igc_update_stats' was not declared. Should it be static?
   drivers/net/ethernet/intel/igc/igc_main.c:1003:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:1003:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:1003:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:1005:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:1005:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:1005:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:1055:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:1055:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:1055:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:1083:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:1083:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:1083:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:2203:5: sparse: symbol 'igc_open' was not declared. Should it be static?
   drivers/net/ethernet/intel/igc/igc_main.c:2237:5: sparse: symbol 'igc_close' was not declared. Should it be static?
   drivers/net/ethernet/intel/igc/igc_main.c:2302:31: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:2302:31:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:2302:31:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/igc_main.c:2404:21: sparse: incorrect type in assignment (different address spaces) @@    expected unsigned char [usertype] *hw_addr @@    got unsigned char [nounsigned char [usertype] *hw_addr @@
   drivers/net/ethernet/intel/igc/igc_main.c:2404:21:    expected unsigned char [usertype] *hw_addr
   drivers/net/ethernet/intel/igc/igc_main.c:2404:21:    got unsigned char [noderef] [usertype] <asn:2>*io_addr
   include/linux/slab.h:631:13: sparse: call with no type!
--
>> drivers/net/ethernet/intel/igc/e1000_base.c:26:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/e1000_base.c:26:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/e1000_base.c:26:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/e1000_base.c:34:17: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/e1000_base.c:34:17:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/e1000_base.c:34:17:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/e1000_base.c:54:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/e1000_base.c:54:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/e1000_base.c:54:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/e1000_base.c:57:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/e1000_base.c:57:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/e1000_base.c:57:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/e1000_base.c:63:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/e1000_base.c:63:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/e1000_base.c:63:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/e1000_base.c:64:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/e1000_base.c:64:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/e1000_base.c:64:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/e1000_base.c:72:17: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/e1000_base.c:72:17:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/e1000_base.c:72:17:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/e1000_base.c:73:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/e1000_base.c:73:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/e1000_base.c:73:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/e1000_base.c:76:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/e1000_base.c:76:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/e1000_base.c:76:9:    got unsigned char [usertype] *__val
   drivers/net/ethernet/intel/igc/e1000_base.c:77:9: sparse: incorrect type in initializer (different address spaces) @@    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr @@    got deref] [usertype] <asn:2>*hw_addr @@
   drivers/net/ethernet/intel/igc/e1000_base.c:77:9:    expected unsigned char [noderef] [usertype] <asn:2>*hw_addr
   drivers/net/ethernet/intel/igc/e1000_base.c:77:9:    got unsigned char [usertype] *__val

Please review and possibly fold the followup patch.

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Shannon Nelson June 28, 2018, 12:42 a.m. UTC | #2
On 6/24/2018 1:45 AM, Sasha Neftin wrote:
> This change adds the defines and structures necessary to support both Tx
> and Rx descriptor rings.
> 
> Sasha Neftin (v2):
> fixed code indentation
> 
> Sasha Nedftin (v3):
> minor code fixes
> 
> Signed-off-by: Sasha Neftin <sasha.neftin@intel.com>
> ---
>   drivers/net/ethernet/intel/igc/Makefile        |   3 +-
>   drivers/net/ethernet/intel/igc/e1000_base.c    |  83 +++
>   drivers/net/ethernet/intel/igc/e1000_base.h    |  89 +++
>   drivers/net/ethernet/intel/igc/e1000_defines.h |  53 ++
>   drivers/net/ethernet/intel/igc/e1000_hw.h      |   1 +
>   drivers/net/ethernet/intel/igc/e1000_regs.h    |   3 +
>   drivers/net/ethernet/intel/igc/igc.h           | 127 ++++
>   drivers/net/ethernet/intel/igc/igc_main.c      | 839 ++++++++++++++++++++++++-
>   8 files changed, 1193 insertions(+), 5 deletions(-)
>   create mode 100644 drivers/net/ethernet/intel/igc/e1000_base.c
>   create mode 100644 drivers/net/ethernet/intel/igc/e1000_base.h
> 
> diff --git a/drivers/net/ethernet/intel/igc/Makefile b/drivers/net/ethernet/intel/igc/Makefile
> index 4563b83cd4e0..6a757ac8492d 100644
> --- a/drivers/net/ethernet/intel/igc/Makefile
> +++ b/drivers/net/ethernet/intel/igc/Makefile
> @@ -7,4 +7,5 @@
>   
>   obj-$(CONFIG_IGC) += igc.o
>   
> -igc-objs := igc_main.o e1000_mac.o
> +igc-objs := igc_main.o e1000_mac.o \
> +e1000_base.o
> diff --git a/drivers/net/ethernet/intel/igc/e1000_base.c b/drivers/net/ethernet/intel/igc/e1000_base.c
> new file mode 100644
> index 000000000000..265ec98000e7
> --- /dev/null
> +++ b/drivers/net/ethernet/intel/igc/e1000_base.c
> @@ -0,0 +1,83 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c)  2018 Intel Corporation */
> +
> +#include <linux/delay.h>
> +
> +#include "e1000_hw.h"
> +#include "e1000_i225.h"
> +
> +/**
> + *  igc_rx_fifo_flush_base - Clean rx fifo after Rx enable
> + *  @hw: pointer to the HW structure
> + *
> + *  After Rx enable, if manageability is enabled then there is likely some
> + *  bad data at the start of the fifo and possibly in the DMA fifo.  This
> + *  function clears the fifos and flushes any packets that came in as rx was
> + *  being enabled.
> + **/
> +void igc_rx_fifo_flush_base(struct e1000_hw *hw)
> +{
> +	u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled;
> +	int i, ms_wait;
> +
> +	/* disable IPv6 options as per hardware errata */
> +	rfctl = rd32(E1000_RFCTL);
> +	rfctl |= E1000_RFCTL_IPV6_EX_DIS;
> +	wr32(E1000_RFCTL, rfctl);

Interesting... does this new hardware really have the same errata as the 
82575?

> +
> +	if (!(rd32(E1000_MANC) & E1000_MANC_RCV_TCO_EN))
> +		return;
> +
> +	/* Disable all Rx queues */
> +	for (i = 0; i < 4; i++) {
> +		rxdctl[i] = rd32(E1000_RXDCTL(i));
> +		wr32(E1000_RXDCTL(i),
> +		     rxdctl[i] & ~E1000_RXDCTL_QUEUE_ENABLE);
> +	}
> +	/* Poll all queues to verify they have shut down */
> +	for (ms_wait = 0; ms_wait < 10; ms_wait++) {
> +		usleep_range(1000, 2000);
> +		rx_enabled = 0;
> +		for (i = 0; i < 4; i++)
> +			rx_enabled |= rd32(E1000_RXDCTL(i));
> +		if (!(rx_enabled & E1000_RXDCTL_QUEUE_ENABLE))
> +			break;
> +	}
> +
> +	if (ms_wait == 10)
> +		pr_debug("Queue disable timed out after 10ms\n");
> +
> +	/* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all
> +	 * incoming packets are rejected.  Set enable and wait 2ms so that
> +	 * any packet that was coming in as RCTL.EN was set is flushed
> +	 */
> +	wr32(E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF);
> +
> +	rlpml = rd32(E1000_RLPML);
> +	wr32(E1000_RLPML, 0);
> +
> +	rctl = rd32(E1000_RCTL);
> +	temp_rctl = rctl & ~(E1000_RCTL_EN | E1000_RCTL_SBP);
> +	temp_rctl |= E1000_RCTL_LPE;
> +
> +	wr32(E1000_RCTL, temp_rctl);
> +	wr32(E1000_RCTL, temp_rctl | E1000_RCTL_EN);
> +	wrfl();
> +	usleep_range(2000, 3000);
> +
> +	/* Enable Rx queues that were previously enabled and restore our
> +	 * previous state
> +	 */
> +	for (i = 0; i < 4; i++)
> +		wr32(E1000_RXDCTL(i), rxdctl[i]);
> +	wr32(E1000_RCTL, rctl);
> +	wrfl();
> +
> +	wr32(E1000_RLPML, rlpml);
> +	wr32(E1000_RFCTL, rfctl);
> +
> +	/* Flush receive errors generated by workaround */
> +	rd32(E1000_ROC);
> +	rd32(E1000_RNBC);
> +	rd32(E1000_MPC);
> +}
> diff --git a/drivers/net/ethernet/intel/igc/e1000_base.h b/drivers/net/ethernet/intel/igc/e1000_base.h
> new file mode 100644
> index 000000000000..9acc41d73f4f
> --- /dev/null
> +++ b/drivers/net/ethernet/intel/igc/e1000_base.h
> @@ -0,0 +1,89 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright (c)  2018 Intel Corporation */
> +
> +#ifndef _E1000_BASE_H
> +#define _E1000_BASE_H
> +
> +/* forward declaration */
> +void igc_rx_fifo_flush_base(struct e1000_hw *hw);
> +
> +/* Transmit Descriptor - Advanced */
> +union e1000_adv_tx_desc {
> +	struct {
> +		__le64 buffer_addr;    /* Address of descriptor's data buf */
> +		__le32 cmd_type_len;
> +	__le32 olinfo_status;

Intent problem?

> +	} read;
> +	struct {
> +		__le64 rsvd;       /* Reserved */
> +		__le32 nxtseq_seed;
> +		__le32 status;
> +	} wb;
> +};
> +
> +struct e1000_adv_data_desc {
> +	__le64 buffer_addr;    /* Address of the descriptor's data buffer */
> +	union {
> +		u32 data;
> +		struct {
> +			u32 datalen:16; /* Data buffer length */
> +			u32 rsvd:4;
> +			u32 dtyp:4;  /* Descriptor type */
> +			u32 dcmd:8;  /* Descriptor command */
> +		} config;

Will this bit layout work correctly on big-endian CPU?

> +	} lower;
> +	union {
> +		u32 data;
> +		struct {
> +			u32 status:4;  /* Descriptor status */
> +			u32 idx:4;
> +			u32 popts:6;  /* Packet Options */
> +			u32 paylen:18; /* Payload length */

Will this bit layout work correctly on big-endian CPU?

> +		} options;
> +	} upper;
> +};
> +
> +/* Receive Descriptor - Advanced */
> +union e1000_adv_rx_desc {
> +	struct {
> +		__le64 pkt_addr; /* Packet buffer address */
> +		__le64 hdr_addr; /* Header buffer address */
> +	} read;
> +	struct {
> +		struct {
> +			union {
> +				__le32 data;
> +				struct {
> +					__le16 pkt_info; /*RSS type, Pkt type*/
> +					/* Split Header, header buffer len */
> +					__le16 hdr_info;
> +				} hs_rss;
> +			} lo_dword;
> +			union {
> +				__le32 rss; /* RSS Hash */
> +				struct {
> +					__le16 ip_id; /* IP id */
> +					__le16 csum; /* Packet Checksum */
> +				} csum_ip;
> +			} hi_dword;
> +		} lower;
> +		struct {
> +			__le32 status_error; /* ext status/error */
> +			__le16 length; /* Packet length */
> +			__le16 vlan; /* VLAN tag */
> +		} upper;
> +	} wb;  /* writeback */
> +};
> +
> +/* Additional Transmit Descriptor Control definitions */
> +#define E1000_TXDCTL_QUEUE_ENABLE	0x02000000 /* Ena specific Tx Queue */
> +
> +/* Additional Receive Descriptor Control definitions */
> +#define E1000_RXDCTL_QUEUE_ENABLE	0x02000000 /* Ena specific Rx Queue */
> +
> +/* SRRCTL bit definitions */
> +#define E1000_SRRCTL_BSIZEPKT_SHIFT		10 /* Shift _right_ */
> +#define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT		2  /* Shift _left_ */
> +#define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF	0x02000000
> +
> +#endif /* _E1000_BASE_H */
> diff --git a/drivers/net/ethernet/intel/igc/e1000_defines.h b/drivers/net/ethernet/intel/igc/e1000_defines.h
> index 1f8bc16c7029..66f8fc96dfb8 100644
> --- a/drivers/net/ethernet/intel/igc/e1000_defines.h
> +++ b/drivers/net/ethernet/intel/igc/e1000_defines.h
> @@ -71,6 +71,10 @@
>   #define E1000_ICR_RXO		0x00000040 /* Rx overrun */
>   #define E1000_ICR_RXT0		0x00000080 /* Rx timer intr (ring 0) */
>   #define E1000_ICR_DRSTA		0x40000000 /* Device Reset Asserted */
> +
> +/* If this bit asserted, the driver should claim the interrupt */
> +#define E1000_ICR_INT_ASSERTED	0x80000000
> +
>   #define E1000_ICS_RXT0		E1000_ICR_RXT0      /* Rx timer intr */
>   
>   #define IMS_ENABLE_MASK ( \
> @@ -97,4 +101,53 @@
>   #define E1000_GPIE_EIAME	0x40000000
>   #define E1000_GPIE_PBA		0x80000000
>   
> +/* Transmit Control */
> +#define E1000_TCTL_EN		0x00000002 /* enable Tx */
> +#define E1000_TCTL_PSP		0x00000008 /* pad short packets */
> +#define E1000_TCTL_CT		0x00000ff0 /* collision threshold */
> +#define E1000_TCTL_COLD		0x003ff000 /* collision distance */
> +#define E1000_TCTL_RTLC		0x01000000 /* Re-transmit on late collision */
> +#define E1000_TCTL_MULR		0x10000000 /* Multiple request support */
> +
> +#define E1000_CT_SHIFT			4
> +#define E1000_COLLISION_THRESHOLD	15
> +
> +/* Management Control */
> +#define E1000_MANC_RCV_TCO_EN	0x00020000 /* Receive TCO Packets Enabled */
> +
> +/* Receive Control */
> +#define E1000_RCTL_RST		0x00000001 /* Software reset */
> +#define E1000_RCTL_EN		0x00000002 /* enable */
> +#define E1000_RCTL_SBP		0x00000004 /* store bad packet */
> +#define E1000_RCTL_UPE		0x00000008 /* unicast promisc enable */
> +#define E1000_RCTL_MPE		0x00000010 /* multicast promisc enable */
> +#define E1000_RCTL_LPE		0x00000020 /* long packet enable */
> +#define E1000_RCTL_LBM_NO	0x00000000 /* no loopback mode */
> +#define E1000_RCTL_LBM_MAC	0x00000040 /* MAC loopback mode */
> +#define E1000_RCTL_LBM_TCVR	0x000000C0 /* tcvr loopback mode */
> +#define E1000_RCTL_DTYP_PS	0x00000400 /* Packet Split descriptor */
> +
> +#define E1000_RCTL_RDMTS_HALF	0x00000000 /* Rx desc min thresh size */
> +#define E1000_RCTL_BAM		0x00008000 /* broadcast enable */
> +
> +/* Header split receive */
> +#define E1000_RFCTL_IPV6_EX_DIS	0x00010000
> +#define E1000_RFCTL_LEF		0x00040000
> +
> +/* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */
> +#define E1000_RCTL_SZ_2048	0x00000000 /* Rx buffer size 2048 */
> +#define E1000_RCTL_SZ_1024	0x00010000 /* Rx buffer size 1024 */
> +#define E1000_RCTL_SZ_512	0x00020000 /* Rx buffer size 512 */
> +#define E1000_RCTL_SZ_256	0x00030000 /* Rx buffer size 256 */
> +/* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */
> +#define E1000_RCTL_SZ_16384	0x00010000 /* Rx buffer size 16384 */
> +#define E1000_RCTL_SZ_8192	0x00020000 /* Rx buffer size 8192 */
> +#define E1000_RCTL_SZ_4096	0x00030000 /* Rx buffer size 4096 */
> +
> +#define E1000_RCTL_MO_SHIFT	12 /* multicast offset shift */
> +#define E1000_RCTL_CFIEN	0x00080000 /* canonical form enable */
> +#define E1000_RCTL_DPF		0x00400000 /* discard pause frames */
> +#define E1000_RCTL_PMCF		0x00800000 /* pass MAC control frames */
> +#define E1000_RCTL_SECRC	0x04000000 /* Strip Ethernet CRC */
> +
>   #endif /* _E1000_DEFINES_H_ */
> diff --git a/drivers/net/ethernet/intel/igc/e1000_hw.h b/drivers/net/ethernet/intel/igc/e1000_hw.h
> index 650c4ac981d9..67fa4f696b98 100644
> --- a/drivers/net/ethernet/intel/igc/e1000_hw.h
> +++ b/drivers/net/ethernet/intel/igc/e1000_hw.h
> @@ -10,6 +10,7 @@
>   #include "e1000_defines.h"
>   #include "e1000_mac.h"
>   #include "e1000_i225.h"
> +#include "e1000_base.h"
>   
>   #define E1000_DEV_ID_I225_LM			0x15F2
>   #define E1000_DEV_ID_I225_V			0x15F3
> diff --git a/drivers/net/ethernet/intel/igc/e1000_regs.h b/drivers/net/ethernet/intel/igc/e1000_regs.h
> index 5634a01afff3..dcc4d89c9933 100644
> --- a/drivers/net/ethernet/intel/igc/e1000_regs.h
> +++ b/drivers/net/ethernet/intel/igc/e1000_regs.h
> @@ -229,6 +229,9 @@
>   #define E1000_TLPIC	0x4148 /* EEE Tx LPI Count - TLPIC */
>   #define E1000_RLPIC	0x414C /* EEE Rx LPI Count - RLPIC */
>   
> +/* Management registers */
> +#define E1000_MANC	0x05820  /* Management Control - RW */
> +
>   /* forward declaration */
>   struct e1000_hw;
>   u32 igc_rd32(struct e1000_hw *hw, u32 reg);
> diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
> index 7cab3e9c8e91..abf2e302c417 100644
> --- a/drivers/net/ethernet/intel/igc/igc.h
> +++ b/drivers/net/ethernet/intel/igc/igc.h
> @@ -46,6 +46,47 @@ extern char igc_driver_version[];
>   #define MAX_Q_VECTORS                     10
>   #define MAX_STD_JUMBO_FRAME_SIZE        9216
>   
> +#define IGC_TX_PTHRESH			8
> +#define IGC_TX_HTHRESH			1
> +
> +/* Supported Rx Buffer Sizes */
> +#define IGC_RXBUFFER_256		256
> +#define IGC_RXBUFFER_2048		2048
> +#define IGC_RXBUFFER_3072		3072
> +
> +#define IGC_RX_HDR_LEN			IGC_RXBUFFER_256
> +
> +/* RX and TX descriptor control thresholds.
> + * PTHRESH - MAC will consider prefetch if it has fewer than this number of
> + *           descriptors available in its onboard memory.
> + *           Setting this to 0 disables RX descriptor prefetch.
> + * HTHRESH - MAC will only prefetch if there are at least this many descriptors
> + *           available in host memory.
> + *           If PTHRESH is 0, this should also be 0.
> + * WTHRESH - RX descriptor writeback threshold - MAC will delay writing back
> + *           descriptors until either it has this many to write back, or the
> + *           ITR timer expires.
> + */
> +#define IGC_RX_PTHRESH			8
> +#define IGC_RX_HTHRESH			8
> +#define IGC_TX_PTHRESH			8
> +#define IGC_TX_HTHRESH			1
> +#define IGC_RX_WTHRESH			4
> +
> +#define IGC_RX_DMA_ATTR \
> +	(DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING)
> +
> +#define IGC_TS_HDR_LEN			16
> +
> +#define IGC_SKB_PAD			(NET_SKB_PAD + NET_IP_ALIGN)
> +
> +#if (PAGE_SIZE < 8192)
> +#define IGC_MAX_FRAME_BUILD_SKB \
> +	(SKB_WITH_OVERHEAD(IGC_RXBUFFER_2048) - IGC_SKB_PAD - IGC_TS_HDR_LEN)
> +#else
> +#define IGC_MAX_FRAME_BUILD_SKB (IGC_RXBUFFER_2048 - IGC_TS_HDR_LEN)
> +#endif
> +
>   enum e1000_state_t {
>   	 __IGC_TESTING,
>   	__IGC_RESETTING,
> @@ -53,6 +94,33 @@ enum e1000_state_t {
>   	 __IGC_PTP_TX_IN_PROGRESS,
>   };
>   
> +/** wrapper around a pointer to a socket buffer,
> + *  so a DMA handle can be stored along with the buffer
> + **/

This comment shouldn't have /** or **/, just /* and */

> +struct igc_tx_buffer {
> +	union e1000_adv_tx_desc *next_to_watch;
> +	unsigned long time_stamp;
> +	struct sk_buff *skb;
> +	unsigned int bytecount;
> +	u16 gso_segs;
> +	__be16 protocol;
> +
> +	DEFINE_DMA_UNMAP_ADDR(dma);
> +	DEFINE_DMA_UNMAP_LEN(len);
> +	u32 tx_flags;
> +};
> +
> +struct igc_rx_buffer {
> +	dma_addr_t dma;
> +	struct page *page;
> +#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)
> +	__u32 page_offset;
> +#else
> +	__u16 page_offset;
> +#endif
> +	__u16 pagecnt_bias;
> +};
> +
>   struct igc_tx_queue_stats {
>   	u64 packets;
>   	u64 bytes;
> @@ -218,4 +286,63 @@ struct igc_adapter {
>   	struct igc_mac_addr *mac_table;
>   };
>   
> +/* igc_desc_unused - calculate if we have unused descriptors */
> +static inline u16 igc_desc_unused(const struct igc_ring *ring)
> +{
> +	u16 ntc = ring->next_to_clean;
> +	u16 ntu = ring->next_to_use;
> +
> +	return ((ntc > ntu) ? 0 : ring->count) + ntc - ntu - 1;
> +}
> +
> +static inline struct netdev_queue *txring_txq(const struct igc_ring *tx_ring)
> +{
> +	return netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index);
> +}
> +
> +enum e1000_ring_flags_t {
> +	IGC_RING_FLAG_RX_3K_BUFFER,
> +	IGC_RING_FLAG_RX_BUILD_SKB_ENABLED,
> +	IGC_RING_FLAG_RX_SCTP_CSUM,
> +	IGC_RING_FLAG_RX_LB_VLAN_BSWAP,
> +	IGC_RING_FLAG_TX_CTX_IDX,
> +	IGC_RING_FLAG_TX_DETECT_HANG
> +};
> +
> +#define ring_uses_large_buffer(ring) \
> +	test_bit(IGC_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
> +
> +#define ring_uses_build_skb(ring) \
> +	test_bit(IGC_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
> +
> +static inline unsigned int igc_rx_bufsz(struct igc_ring *ring)
> +{
> +#if (PAGE_SIZE < 8192)
> +	if (ring_uses_large_buffer(ring))
> +		return IGC_RXBUFFER_3072;
> +
> +	if (ring_uses_build_skb(ring))
> +		return IGC_MAX_FRAME_BUILD_SKB + IGC_TS_HDR_LEN;
> +#endif
> +	return IGC_RXBUFFER_2048;
> +}
> +
> +static inline unsigned int igc_rx_pg_order(struct igc_ring *ring)
> +{
> +#if (PAGE_SIZE < 8192)
> +	if (ring_uses_large_buffer(ring))
> +		return 1;
> +#endif
> +	return 0;
> +}
> +
> +#define igc_rx_pg_size(_ring) (PAGE_SIZE << igc_rx_pg_order(_ring))
> +
> +#define IGC_RX_DESC(R, i)       \
> +	(&(((union e1000_adv_rx_desc *)((R)->desc))[i]))
> +#define IGC_TX_DESC(R, i)       \
> +	(&(((union e1000_adv_tx_desc *)((R)->desc))[i]))
> +#define IGC_TX_CTXTDESC(R, i)   \
> +	(&(((struct e1000_adv_tx_context_desc *)((R)->desc))[i]))
> +
>   #endif /* _IGC_H_ */
> diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
> index 30b778c9b94b..a147a1b7585e 100644
> --- a/drivers/net/ethernet/intel/igc/igc_main.c
> +++ b/drivers/net/ethernet/intel/igc/igc_main.c
> @@ -29,11 +29,21 @@ static const struct pci_device_id igc_pci_tbl[] = {
>   MODULE_DEVICE_TABLE(pci, igc_pci_tbl);
>   
>   /* forward declaration */
> +static int igc_setup_all_tx_resources(struct igc_adapter *adapter);
> +static void igc_clean_tx_ring(struct igc_ring *tx_ring);
> +static void igc_free_all_tx_resources(struct igc_adapter *adapter);
> +static int igc_setup_all_rx_resources(struct igc_adapter *adapter);
>   static int igc_sw_init(struct igc_adapter *);
>   static void igc_configure(struct igc_adapter *adapter);
> +static void igc_configure_tx(struct igc_adapter *);
> +static void igc_configure_rx(struct igc_adapter *adapter);
>   static void igc_power_down_link(struct igc_adapter *adapter);
>   static void igc_set_default_mac_filter(struct igc_adapter *adapter);
> +static void igc_set_rx_mode(struct net_device *netdev);
> +static void igc_setup_mrqc(struct igc_adapter *adapter);
>   static irqreturn_t igc_msix_ring(int irq, void *data);
> +static irqreturn_t igc_intr_msi(int irq, void *data);
> +static irqreturn_t igc_intr(int irq, void *data);
>   static void igc_write_itr(struct igc_q_vector *q_vector);
>   static int igc_request_msix(struct igc_adapter *adapter);
>   static void igc_assign_vector(struct igc_q_vector *q_vector, int msix_vector);
> @@ -125,6 +135,526 @@ static void igc_get_hw_control(struct igc_adapter *adapter)
>   }
>   
>   /**
> + *  igc_free_tx_resources - Free Tx Resources per Queue
> + *  @tx_ring: Tx descriptor ring for a specific queue
> + *
> + *  Free all transmit software resources
> + **/
> +void igc_free_tx_resources(struct igc_ring *tx_ring)
> +{
> +	igc_clean_tx_ring(tx_ring);
> +
> +	vfree(tx_ring->tx_buffer_info);
> +	tx_ring->tx_buffer_info = NULL;
> +
> +	/* if not set, then don't free */
> +	if (!tx_ring->desc)
> +		return;
> +
> +	dma_free_coherent(tx_ring->dev, tx_ring->size,
> +			  tx_ring->desc, tx_ring->dma);
> +
> +	tx_ring->desc = NULL;
> +}
> +
> +/**
> + *  igc_free_all_tx_resources - Free Tx Resources for All Queues
> + *  @adapter: board private structure
> + *
> + *  Free all transmit software resources
> + **/
> +static void igc_free_all_tx_resources(struct igc_adapter *adapter)
> +{
> +	int i;
> +
> +	for (i = 0; i < adapter->num_tx_queues; i++)
> +		igc_free_tx_resources(adapter->tx_ring[i]);
> +}
> +
> +void igc_unmap_and_free_tx_resource(struct igc_ring *ring,
> +				    struct igc_tx_buffer *tx_buffer)
> +{
> +	if (tx_buffer->skb) {
> +		dev_kfree_skb_any(tx_buffer->skb);
> +		if (dma_unmap_len(tx_buffer, len))
> +			dma_unmap_single(ring->dev,
> +					 dma_unmap_addr(tx_buffer, dma),
> +					 dma_unmap_len(tx_buffer, len),
> +					 DMA_TO_DEVICE);
> +	} else if (dma_unmap_len(tx_buffer, len)) {
> +		dma_unmap_page(ring->dev,
> +			       dma_unmap_addr(tx_buffer, dma),
> +			       dma_unmap_len(tx_buffer, len),
> +			       DMA_TO_DEVICE);
> +	}
> +	tx_buffer->next_to_watch = NULL;
> +	tx_buffer->skb = NULL;
> +	dma_unmap_len_set(tx_buffer, len, 0);
> +	/* buffer_info must be completely set up in the transmit path */
> +}
> +
> +/**
> + *  igc_clean_tx_ring - Free Tx Buffers
> + *  @tx_ring: ring to be cleaned
> + **/
> +static void igc_clean_tx_ring(struct igc_ring *tx_ring)
> +{
> +	struct igc_tx_buffer *buffer_info;
> +	unsigned long size;
> +	u16 i;
> +
> +	if (!tx_ring->tx_buffer_info)
> +		return;
> +
> +	/* Free all the Tx ring sk_buffs */
> +	for (i = 0; i < tx_ring->count; i++) {
> +		buffer_info = &tx_ring->tx_buffer_info[i];
> +		igc_unmap_and_free_tx_resource(tx_ring, buffer_info);
> +	}
> +
> +	netdev_tx_reset_queue(txring_txq(tx_ring));
> +
> +	size = sizeof(struct igc_tx_buffer) * tx_ring->count;
> +	memset(tx_ring->tx_buffer_info, 0, size);
> +
> +	/* Zero out the descriptor ring */
> +	memset(tx_ring->desc, 0, tx_ring->size);
> +
> +	tx_ring->next_to_use = 0;
> +	tx_ring->next_to_clean = 0;
> +}
> +
> +/**
> + *  igc_setup_tx_resources - allocate Tx resources (Descriptors)
> + *  @tx_ring: tx descriptor ring (for a specific queue) to setup
> + *
> + *  Return 0 on success, negative on failure
> + **/
> +int igc_setup_tx_resources(struct igc_ring *tx_ring)
> +{
> +	struct device *dev = tx_ring->dev;
> +	int size = 0;
> +
> +	size = sizeof(struct igc_tx_buffer) * tx_ring->count;
> +	tx_ring->tx_buffer_info = vzalloc(size);
> +	if (!tx_ring->tx_buffer_info)
> +		goto err;
> +
> +	/* round up to nearest 4K */
> +	tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc);
> +	tx_ring->size = ALIGN(tx_ring->size, 4096);
> +
> +	tx_ring->desc = dma_alloc_coherent(dev, tx_ring->size,
> +					   &tx_ring->dma, GFP_KERNEL);
> +
> +	if (!tx_ring->desc)
> +		goto err;
> +
> +	tx_ring->next_to_use = 0;
> +	tx_ring->next_to_clean = 0;
> +
> +	return 0;
> +
> +err:
> +	vfree(tx_ring->tx_buffer_info);
> +	dev_err(dev,
> +		"Unable to allocate memory for the transmit descriptor ring\n");
> +	return -ENOMEM;
> +}
> +
> +/**
> + *  igc_setup_all_tx_resources - wrapper to allocate Tx resources
> + *                                (Descriptors) for all queues

This should be a single line

> + *  @adapter: board private structure
> + *
> + *  Return 0 on success, negative on failure
> + **/
> +static int igc_setup_all_tx_resources(struct igc_adapter *adapter)
> +{
> +	struct pci_dev *pdev = adapter->pdev;
> +	int i, err = 0;
> +
> +	for (i = 0; i < adapter->num_tx_queues; i++) {
> +		err = igc_setup_tx_resources(adapter->tx_ring[i]);
> +		if (err) {
> +			dev_err(&pdev->dev,
> +				"Allocation for Tx Queue %u failed\n", i);
> +			for (i--; i >= 0; i--)
> +				igc_free_tx_resources(adapter->tx_ring[i]);
> +			break;
> +		}
> +	}
> +
> +	return err;
> +}
> +
> +/**
> + *  igc_clean_rx_ring - Free Rx Buffers per Queue
> + *  @rx_ring: ring to free buffers from
> + **/
> +void igc_clean_rx_ring(struct igc_ring *rx_ring)
> +{
> +	u16 i = rx_ring->next_to_clean;
> +
> +	if (rx_ring->skb)
> +		dev_kfree_skb(rx_ring->skb);
> +	rx_ring->skb = NULL;
> +
> +	/* Free all the Rx ring sk_buffs */
> +	while (i != rx_ring->next_to_alloc) {
> +		struct igc_rx_buffer *buffer_info = &rx_ring->rx_buffer_info[i];
> +
> +		/* Invalidate cache lines that may have been written to by
> +		 * device so that we avoid corrupting memory.
> +		 */
> +		dma_sync_single_range_for_cpu(rx_ring->dev,
> +					      buffer_info->dma,
> +					      buffer_info->page_offset,
> +					      igc_rx_bufsz(rx_ring),
> +					      DMA_FROM_DEVICE);
> +
> +		/* free resources associated with mapping */
> +		dma_unmap_page_attrs(rx_ring->dev,
> +				     buffer_info->dma,
> +				     igc_rx_pg_size(rx_ring),
> +				     DMA_FROM_DEVICE,
> +				     IGC_RX_DMA_ATTR);
> +		__page_frag_cache_drain(buffer_info->page,
> +					buffer_info->pagecnt_bias);
> +
> +		i++;
> +		if (i == rx_ring->count)
> +			i = 0;
> +	}
> +
> +	rx_ring->next_to_alloc = 0;
> +	rx_ring->next_to_clean = 0;
> +	rx_ring->next_to_use = 0;
> +}
> +
> +/**
> + *  igc_free_rx_resources - Free Rx Resources
> + *  @rx_ring: ring to clean the resources from
> + *
> + *  Free all receive software resources
> + **/
> +void igc_free_rx_resources(struct igc_ring *rx_ring)
> +{
> +	igc_clean_rx_ring(rx_ring);
> +
> +	vfree(rx_ring->rx_buffer_info);
> +	rx_ring->rx_buffer_info = NULL;
> +
> +	/* if not set, then don't free */
> +	if (!rx_ring->desc)
> +		return;
> +
> +	dma_free_coherent(rx_ring->dev, rx_ring->size,
> +			  rx_ring->desc, rx_ring->dma);
> +
> +	rx_ring->desc = NULL;
> +}
> +
> +/**
> + *  igc_free_all_rx_resources - Free Rx Resources for All Queues
> + *  @adapter: board private structure
> + *
> + *  Free all receive software resources
> + **/
> +static void igc_free_all_rx_resources(struct igc_adapter *adapter)
> +{
> +	int i;
> +
> +	for (i = 0; i < adapter->num_rx_queues; i++)
> +		igc_free_rx_resources(adapter->rx_ring[i]);
> +}
> +
> +/**
> + *  igc_setup_rx_resources - allocate Rx resources (Descriptors)
> + *  @rx_ring:    rx descriptor ring (for a specific queue) to setup
> + *
> + *  Returns 0 on success, negative on failure
> + **/
> +int igc_setup_rx_resources(struct igc_ring *rx_ring)
> +{
> +	struct device *dev = rx_ring->dev;
> +	int size, desc_len;
> +
> +	size = sizeof(struct igc_rx_buffer) * rx_ring->count;
> +	rx_ring->rx_buffer_info = vzalloc(size);
> +	if (!rx_ring->rx_buffer_info)
> +		goto err;
> +
> +	desc_len = sizeof(union e1000_adv_rx_desc);
> +
> +	/* Round up to nearest 4K */
> +	rx_ring->size = rx_ring->count * desc_len;
> +	rx_ring->size = ALIGN(rx_ring->size, 4096);
> +
> +	rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size,
> +					   &rx_ring->dma, GFP_KERNEL);
> +
> +	if (!rx_ring->desc)
> +		goto err;
> +
> +	rx_ring->next_to_alloc = 0;
> +	rx_ring->next_to_clean = 0;
> +	rx_ring->next_to_use = 0;
> +
> +	return 0;
> +
> +err:
> +	vfree(rx_ring->rx_buffer_info);
> +	rx_ring->rx_buffer_info = NULL;
> +	dev_err(dev,
> +		"Unable to allocate memory for the receive descriptor ring\n");
> +	return -ENOMEM;
> +}
> +
> +/**
> + *  igc_setup_all_rx_resources - wrapper to allocate Rx resources
> + *                                (Descriptors) for all queues
> + *  @adapter: board private structure
> + *
> + *  Return 0 on success, negative on failure
> + **/
> +static int igc_setup_all_rx_resources(struct igc_adapter *adapter)
> +{
> +	struct pci_dev *pdev = adapter->pdev;
> +	int i, err = 0;
> +
> +	for (i = 0; i < adapter->num_rx_queues; i++) {
> +		err = igc_setup_rx_resources(adapter->rx_ring[i]);
> +		if (err) {
> +			dev_err(&pdev->dev,
> +				"Allocation for Rx Queue %u failed\n", i);
> +			for (i--; i >= 0; i--)
> +				igc_free_rx_resources(adapter->rx_ring[i]);
> +			break;
> +		}
> +	}
> +
> +	return err;
> +}
> +
> +static u32 igc_tx_wthresh(struct igc_adapter *adapter)
> +{
> +	return 16;

Is there a #define for this?  Why is this a function?

> +}
> +
> +/**
> + *  igc_configure_rx_ring - Configure a receive ring after Reset
> + *  @adapter: board private structure
> + *  @ring: receive ring to be configured
> + *
> + *  Configure the Rx unit of the MAC after a reset.
> + **/
> +void igc_configure_rx_ring(struct igc_adapter *adapter,
> +			   struct igc_ring *ring)
> +{
> +	struct e1000_hw *hw = &adapter->hw;
> +	union e1000_adv_rx_desc *rx_desc;
> +	u64 rdba = ring->dma;
> +	int reg_idx = ring->reg_idx;
> +	u32 srrctl = 0, rxdctl = 0;

reverse xmas tree

> +
> +	/* disable the queue */
> +	wr32(E1000_RXDCTL(reg_idx), 0);
> +
> +	/* Set DMA base address registers */
> +	wr32(E1000_RDBAL(reg_idx),
> +	     rdba & 0x00000000ffffffffULL);
> +	wr32(E1000_RDBAH(reg_idx), rdba >> 32);
> +	wr32(E1000_RDLEN(reg_idx),
> +	     ring->count * sizeof(union e1000_adv_rx_desc));
> +
> +	/* initialize head and tail */
> +	ring->tail = adapter->io_addr + E1000_RDT(reg_idx);
> +	wr32(E1000_RDH(reg_idx), 0);
> +	writel(0, ring->tail);
> +
> +	/* reset next-to- use/clean to place SW in sync with hardwdare */

s/hardwdare/hardware/

> +	ring->next_to_clean = 0;
> +	ring->next_to_use = 0;
> +
> +	/* set descriptor configuration */
> +	srrctl = IGC_RX_HDR_LEN << E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
> +	if (ring_uses_large_buffer(ring))
> +		srrctl |= IGC_RXBUFFER_3072 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
> +	else
> +		srrctl |= IGC_RXBUFFER_2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
> +	srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
> +
> +	wr32(E1000_SRRCTL(reg_idx), srrctl);
> +
> +	rxdctl |= IGC_RX_PTHRESH;
> +	rxdctl |= IGC_RX_HTHRESH << 8;
> +	rxdctl |= IGC_RX_WTHRESH << 16;
> +
> +	/* initialize rx_buffer_info */
> +	memset(ring->rx_buffer_info, 0,
> +	       sizeof(struct igc_rx_buffer) * ring->count);
> +
> +	/* initialize Rx descriptor 0 */
> +	rx_desc = IGC_RX_DESC(ring, 0);
> +	rx_desc->wb.upper.length = 0;
> +
> +	/* enable receive descriptor fetching */
> +	rxdctl |= E1000_RXDCTL_QUEUE_ENABLE;
> +
> +	wr32(E1000_RXDCTL(reg_idx), rxdctl);
> +}
> +
> +/**
> + *  igc_configure_rx - Configure receive Unit after Reset
> + *  @adapter: board private structure
> + *
> + *  Configure the Rx unit of the MAC after a reset.
> + **/
> +static void igc_configure_rx(struct igc_adapter *adapter)
> +{
> +	int i;
> +
> +	/* Setup the HW Rx Head and Tail Descriptor Pointers and
> +	 * the Base and Length of the Rx Descriptor Ring
> +	 */
> +	for (i = 0; i < adapter->num_rx_queues; i++)
> +		igc_configure_rx_ring(adapter, adapter->rx_ring[i]);
> +}
> +
> +/**
> + *  igc_configure_tx_ring - Configure transmit ring after Reset
> + *  @adapter: board private structure
> + *  @ring: tx ring to configure
> + *
> + *  Configure a transmit ring after a reset.
> + **/
> +void igc_configure_tx_ring(struct igc_adapter *adapter,
> +			   struct igc_ring *ring)
> +{
> +	struct e1000_hw *hw = &adapter->hw;
> +	u32 txdctl = 0;
> +	u64 tdba = ring->dma;
> +	int reg_idx = ring->reg_idx;

reverse xmas tree

> +
> +	/* disable the queue */
> +	wr32(E1000_TXDCTL(reg_idx), 0);
> +	wrfl();
> +	mdelay(10);
> +
> +	wr32(E1000_TDLEN(reg_idx),
> +	     ring->count * sizeof(union e1000_adv_tx_desc));
> +	wr32(E1000_TDBAL(reg_idx),
> +	     tdba & 0x00000000ffffffffULL);
> +	wr32(E1000_TDBAH(reg_idx), tdba >> 32);
> +
> +	ring->tail = adapter->io_addr + E1000_TDT(reg_idx);
> +	wr32(E1000_TDH(reg_idx), 0);
> +	writel(0, ring->tail);
> +
> +	txdctl |= IGC_TX_PTHRESH;
> +	txdctl |= IGC_TX_HTHRESH << 8;
> +	txdctl |= igc_tx_wthresh(adapter) << 16;
> +
> +	txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
> +	wr32(E1000_TXDCTL(reg_idx), txdctl);
> +}
> +
> +/**
> + *  igc_configure_tx - Configure transmit Unit after Reset
> + *  @adapter: board private structure
> + *
> + *  Configure the Tx unit of the MAC after a reset.
> + **/
> +static void igc_configure_tx(struct igc_adapter *adapter)
> +{
> +	int i;
> +
> +	for (i = 0; i < adapter->num_tx_queues; i++)
> +		igc_configure_tx_ring(adapter, adapter->tx_ring[i]);
> +}
> +
> +/**
> + *  igc_setup_mrqc - configure the multiple receive queue control registers
> + *  @adapter: Board private structure
> + **/
> +static void igc_setup_mrqc(struct igc_adapter *adapter)
> +{
> +}
> +
> +/**
> + *  igc_setup_rctl - configure the receive control registers
> + *  @adapter: Board private structure
> + **/
> +void igc_setup_rctl(struct igc_adapter *adapter)
> +{
> +	struct e1000_hw *hw = &adapter->hw;
> +	u32 rctl;
> +
> +	rctl = rd32(E1000_RCTL);
> +
> +	rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
> +	rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
> +
> +	rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_RDMTS_HALF |
> +		(hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT);
> +
> +	/* enable stripping of CRC. It's unlikely this will break BMC
> +	 * redirection as it did with e1000. Newer features require
> +	 * that the HW strips the CRC.
> +	 */
> +	rctl |= E1000_RCTL_SECRC;
> +
> +	/* disable store bad packets and clear size bits. */
> +	rctl &= ~(E1000_RCTL_SBP | E1000_RCTL_SZ_256);
> +
> +	/* enable LPE to allow for reception of jumbo frames */
> +	rctl |= E1000_RCTL_LPE;
> +
> +	/* disable queue 0 to prevent tail write w/o re-config */
> +	wr32(E1000_RXDCTL(0), 0);
> +
> +	/* This is useful for sniffing bad packets. */
> +	if (adapter->netdev->features & NETIF_F_RXALL) {
> +		/* UPE and MPE will be handled by normal PROMISC logic
> +		 * in e1000e_set_rx_mode
> +		 */
> +		rctl |= (E1000_RCTL_SBP | /* Receive bad packets */
> +			 E1000_RCTL_BAM | /* RX All Bcast Pkts */
> +			 E1000_RCTL_PMCF); /* RX All MAC Ctrl Pkts */
> +
> +		rctl &= ~(E1000_RCTL_DPF | /* Allow filtered pause */
> +			  E1000_RCTL_CFIEN); /* Disable VLAN CFIEN Filter */
> +	}
> +
> +	wr32(E1000_RCTL, rctl);
> +}
> +
> +/**
> + *  igc_setup_tctl - configure the transmit control registers
> + *  @adapter: Board private structure
> + **/
> +void igc_setup_tctl(struct igc_adapter *adapter)
> +{
> +	struct e1000_hw *hw = &adapter->hw;
> +	u32 tctl;
> +
> +	/* disable queue 0 which icould be enabled by default */
> +	wr32(E1000_TXDCTL(0), 0);
> +
> +	/* Program the Transmit Control Register */
> +	tctl = rd32(E1000_TCTL);
> +	tctl &= ~E1000_TCTL_CT;
> +	tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC |
> +		(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
> +
> +	/* Enable transmits */
> +	tctl |= E1000_TCTL_EN;
> +
> +	wr32(E1000_TCTL, tctl);
> +}
> +
> +/**
>    *  igc_set_mac - Change the Ethernet Address of the NIC
>    *  @netdev: network interface device structure
>    *  @p: pointer to an address structure
> @@ -156,6 +686,121 @@ static netdev_tx_t igc_xmit_frame(struct sk_buff *skb,
>   	return NETDEV_TX_OK;
>   }
>   
> +static inline unsigned int igc_rx_offset(struct igc_ring *rx_ring)
> +{
> +	return ring_uses_build_skb(rx_ring) ? IGC_SKB_PAD : 0;
> +}
> +
> +static bool igc_alloc_mapped_page(struct igc_ring *rx_ring,
> +				  struct igc_rx_buffer *bi)
> +{
> +	struct page *page = bi->page;
> +	dma_addr_t dma;
> +
> +	/* since we are recycling buffers we should seldom need to alloc */
> +	if (likely(page))
> +		return true;
> +
> +	/* alloc new page for storage */
> +	page = dev_alloc_pages(igc_rx_pg_order(rx_ring));
> +	if (unlikely(!page)) {
> +		rx_ring->rx_stats.alloc_failed++;
> +		return false;
> +	}
> +
> +	/* map page for use */
> +	dma = dma_map_page_attrs(rx_ring->dev, page, 0,
> +				 igc_rx_pg_size(rx_ring),
> +				 DMA_FROM_DEVICE,
> +				 IGC_RX_DMA_ATTR);
> +
> +	/* if mapping failed free memory back to system since
> +	 * there isn't much point in holding memory we can't use
> +	 */
> +	if (dma_mapping_error(rx_ring->dev, dma)) {
> +		__free_page(page);
> +
> +		rx_ring->rx_stats.alloc_failed++;
> +		return false;
> +	}
> +
> +	bi->dma = dma;
> +	bi->page = page;
> +	bi->page_offset = igc_rx_offset(rx_ring);
> +	bi->pagecnt_bias = 1;
> +
> +	return true;
> +}
> +
> +/**
> + *  igc_alloc_rx_buffers - Replace used receive buffers; packet split
> + *  @adapter: address of board private structure
> + **/
> +void igc_alloc_rx_buffers(struct igc_ring *rx_ring, u16 cleaned_count)
> +{
> +	union e1000_adv_rx_desc *rx_desc;
> +	struct igc_rx_buffer *bi;
> +	u16 i = rx_ring->next_to_use;
> +	u16 bufsz;

reverse xmas tree

> +
> +	/* nothing to do */
> +	if (!cleaned_count)
> +		return;
> +
> +	rx_desc = IGC_RX_DESC(rx_ring, i);
> +	bi = &rx_ring->rx_buffer_info[i];
> +	i -= rx_ring->count;
> +
> +	bufsz = igc_rx_bufsz(rx_ring);
> +
> +	do {
> +		if (!igc_alloc_mapped_page(rx_ring, bi))
> +			break;
> +
> +		/* sync the buffer for use by the device */
> +		dma_sync_single_range_for_device(rx_ring->dev, bi->dma,
> +						 bi->page_offset, bufsz,
> +						 DMA_FROM_DEVICE);
> +
> +		/* Refresh the desc even if buffer_addrs didn't change
> +		 * because each write-back erases this info.
> +		 */
> +		rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset);
> +
> +		rx_desc++;
> +		bi++;
> +		i++;
> +		if (unlikely(!i)) {
> +			rx_desc = IGC_RX_DESC(rx_ring, 0);
> +			bi = rx_ring->rx_buffer_info;
> +			i -= rx_ring->count;
> +		}
> +
> +		/* clear the length for the next_to_use descriptor */
> +		rx_desc->wb.upper.length = 0;
> +
> +		cleaned_count--;
> +	} while (cleaned_count);
> +
> +	i += rx_ring->count;
> +
> +	if (rx_ring->next_to_use != i) {
> +		/* record the next descriptor to use */
> +		rx_ring->next_to_use = i;
> +
> +		/* update next to alloc since we have filled the ring */
> +		rx_ring->next_to_alloc = i;
> +
> +		/* Force memory writes to complete before letting h/w
> +		 * know there are new descriptors to fetch.  (Only
> +		 * applicable for weak-ordered memory model archs,
> +		 * such as IA-64).
> +		 */
> +		wmb();
> +		writel(i, rx_ring->tail);
> +	}
> +}
> +
>   /**
>    *  igc_ioctl - I/O control method
>    *  @netdev: network interface device structure
> @@ -196,6 +841,12 @@ int igc_up(struct igc_adapter *adapter)
>   	rd32(E1000_ICR);
>   	igc_irq_enable(adapter);
>   
> +	netif_tx_start_all_queues(adapter->netdev);
> +
> +	/* start the watchdog. */
> +	hw->mac.get_link_status = 1;
> +	schedule_work(&adapter->watchdog_task);

But you don't actually add the watchdog setup until patch 11?

> +
>   	return 0;
>   }
>   
> @@ -295,7 +946,30 @@ static struct net_device_stats *igc_get_stats(struct net_device *netdev)
>    **/
>   static void igc_configure(struct igc_adapter *adapter)
>   {
> +	struct net_device *netdev = adapter->netdev;
> +	int i = 0;
> +
>   	igc_get_hw_control(adapter);
> +	igc_set_rx_mode(netdev);
> +
> +	igc_setup_tctl(adapter);
> +	igc_setup_mrqc(adapter);
> +	igc_setup_rctl(adapter);
> +
> +	igc_configure_tx(adapter);
> +	igc_configure_rx(adapter);
> +
> +	igc_rx_fifo_flush_base(&adapter->hw);
> +
> +	/* call igc_desc_unused which always leaves
> +	 * at least 1 descriptor unused to make sure
> +	 * next_to_use != next_to_clean
> +	 */
> +	for (i = 0; i < adapter->num_rx_queues; i++) {
> +		struct igc_ring *ring = adapter->rx_ring[i];
> +
> +		igc_alloc_rx_buffers(ring, igc_desc_unused(ring));
> +	}
>   }
>   
>   /**
> @@ -343,6 +1017,19 @@ static void igc_set_default_mac_filter(struct igc_adapter *adapter)
>   	igc_rar_set_index(adapter, 0);
>   }
>   
> +/**
> + *  igc_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set
> + *  @netdev: network interface device structure
> + *
> + *  The set_rx_mode entry point is called whenever the unicast or multicast
> + *  address lists or the network interface flags are updated.  This routine is
> + *  responsible for configuring the hardware for proper unicast, multicast,
> + *  promiscuous mode, and all-multi behavior.
> + **/
> +static void igc_set_rx_mode(struct net_device *netdev)
> +{
> +}
> +
>   static irqreturn_t igc_msix_other(int irq, void *data)
>   {
>   	struct igc_adapter *adapter = data;
> @@ -781,6 +1468,83 @@ static void igc_update_itr(struct igc_q_vector *q_vector,
>   	ring_container->itr = itrval;
>   }
>   
> +/**
> + *  igc_intr_msi - Interrupt Handler
> + *  @irq: interrupt number
> + *  @data: pointer to a network interface device structure
> + **/
> +static irqreturn_t igc_intr_msi(int irq, void *data)
> +{
> +	struct igc_adapter *adapter = data;
> +	struct igc_q_vector *q_vector = adapter->q_vector[0];
> +	struct e1000_hw *hw = &adapter->hw;
> +	/* read ICR disables interrupts using IAM */
> +	u32 icr = rd32(E1000_ICR);
> +
> +	igc_write_itr(q_vector);
> +
> +	if (icr & E1000_ICR_DRSTA)
> +		schedule_work(&adapter->reset_task);

This task probably should have been set up in a previous patch, too.

> +
> +	if (icr & E1000_ICR_DOUTSYNC) {
> +		/* HW is reporting DMA is out of sync */
> +		adapter->stats.doosync++;
> +	}
> +
> +	if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
> +		hw->mac.get_link_status = 1;
> +		if (!test_bit(__IGC_DOWN, &adapter->state))
> +			mod_timer(&adapter->watchdog_timer, jiffies + 1);

And this too.

> +	}
> +
> +	 napi_schedule(&q_vector->napi);

Extra space indented?

> +
> +	return IRQ_HANDLED;
> +}
> +
> +/**
> + *  igc_intr - Legacy Interrupt Handler
> + *  @irq: interrupt number
> + *  @data: pointer to a network interface device structure
> + **/
> +static irqreturn_t igc_intr(int irq, void *data)
> +{
> +	struct igc_adapter *adapter = data;
> +	struct igc_q_vector *q_vector = adapter->q_vector[0];
> +	struct e1000_hw *hw = &adapter->hw;
> +	/* Interrupt Auto-Mask...upon reading ICR, interrupts are masked.  No
> +	 * need for the IMC write
> +	 */
> +	u32 icr = rd32(E1000_ICR);
> +
> +	/* IMS will not auto-mask if INT_ASSERTED is not set, and if it is
> +	 * not set, then the adapter didn't send an interrupt
> +	 */
> +	if (!(icr & E1000_ICR_INT_ASSERTED))
> +		return IRQ_NONE;
> +
> +	igc_write_itr(q_vector);
> +
> +	if (icr & E1000_ICR_DRSTA)
> +		schedule_work(&adapter->reset_task);
> +
> +	if (icr & E1000_ICR_DOUTSYNC) {
> +		/* HW is reporting DMA is out of sync */
> +		adapter->stats.doosync++;
> +	}
> +
> +	if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
> +		hw->mac.get_link_status = 1;
> +		/* guard against interrupt when we're going down */
> +		if (!test_bit(__IGC_DOWN, &adapter->state))
> +			mod_timer(&adapter->watchdog_timer, jiffies + 1);
> +	}
> +
> +	napi_schedule(&q_vector->napi);
> +
> +	return IRQ_HANDLED;
> +}
> +
>   static void igc_ring_irq_enable(struct igc_q_vector *q_vector)
>   {
>   	struct igc_adapter *adapter = q_vector->adapter;
> @@ -1148,6 +1912,29 @@ static int igc_alloc_q_vectors(struct igc_adapter *adapter)
>   }
>   
>   /**
> + *  igc_cache_ring_register - Descriptor ring to register mapping
> + *  @adapter: board private structure to initialize
> + *
> + *  Once we know the feature-set enabled for the device, we'll cache
> + *  the register offset the descriptor ring is assigned to.
> + **/
> +static void igc_cache_ring_register(struct igc_adapter *adapter)
> +{
> +	int i = 0, j = 0;
> +
> +	switch (adapter->hw.mac.type) {
> +	case e1000_i225:
> +	/* Fall through */
> +	default:
> +		for (; i < adapter->num_rx_queues; i++)
> +			adapter->rx_ring[i]->reg_idx = i;
> +		for (; j < adapter->num_tx_queues; j++)
> +			adapter->tx_ring[j]->reg_idx = j;
> +		break;
> +	}
> +}
> +
> +/**
>    *  igc_init_interrupt_scheme - initialize interrupts, allocate queues/vectors
>    *  @adapter: Pointer to adapter structure
>    *
> @@ -1166,7 +1953,7 @@ static int igc_init_interrupt_scheme(struct igc_adapter *adapter, bool msix)
>   		goto err_alloc_q_vectors;
>   	}
>   
> -	/* TODO complete igc_cache_ring_register */
> +	igc_cache_ring_register(adapter);
>   
>   	return 0;
>   
> @@ -1255,6 +2042,8 @@ static void igc_irq_enable(struct igc_adapter *adapter)
>    **/
>   static int igc_request_irq(struct igc_adapter *adapter)
>   {
> +	struct net_device *netdev = adapter->netdev;
> +	struct pci_dev *pdev = adapter->pdev;
>   	int err = 0;
>   
>   	if (adapter->flags & IGC_FLAG_HAS_MSIX) {
> @@ -1262,16 +2051,38 @@ static int igc_request_irq(struct igc_adapter *adapter)
>   		if (!err)
>   			goto request_done;
>   		/* fall back to MSI */
> -		/* TODO complete free tx/rx resources */
> +		igc_free_all_tx_resources(adapter);
> +		igc_free_all_rx_resources(adapter);
>   
>   		igc_clear_interrupt_scheme(adapter);
>   		err = igc_init_interrupt_scheme(adapter, false);
>   		if (err)
>   			goto request_done;
> -		/* TODO complete setup tx/rx resources */
> +		igc_setup_all_tx_resources(adapter);
> +		igc_setup_all_rx_resources(adapter);
>   		igc_configure(adapter);
>   	}
>   
> +	igc_assign_vector(adapter->q_vector[0], 0);
> +
> +	if (adapter->flags & IGC_FLAG_HAS_MSI) {
> +		err = request_irq(pdev->irq, &igc_intr_msi, 0,
> +				  netdev->name, adapter);
> +		if (!err)
> +			goto request_done;
> +
> +		/* fall back to legacy interrupts */
> +		igc_reset_interrupt_capability(adapter);
> +		adapter->flags &= ~IGC_FLAG_HAS_MSI;
> +	}
> +
> +	err = request_irq(pdev->irq, &igc_intr, IRQF_SHARED,
> +			  netdev->name, adapter);
> +
> +	if (err)
> +		dev_err(&pdev->dev, "Error %d getting interrupt\n",
> +			err);
> +
>   request_done:
>   	return err;
>   }
> @@ -1332,6 +2143,16 @@ static int __igc_open(struct net_device *netdev, bool resuming)
>   
>   	netif_carrier_off(netdev);
>   
> +	/* allocate transmit descriptors */
> +	err = igc_setup_all_tx_resources(adapter);
> +	if (err)
> +		goto err_setup_tx;
> +
> +	/* allocate receive descriptors */
> +	err = igc_setup_all_rx_resources(adapter);
> +	if (err)
> +		goto err_setup_rx;
> +
>   	igc_power_up_link(adapter);
>   
>   	igc_configure(adapter);
> @@ -1357,6 +2178,8 @@ static int __igc_open(struct net_device *netdev, bool resuming)
>   	rd32(E1000_ICR);
>   	igc_irq_enable(adapter);
>   
> +	netif_tx_start_all_queues(netdev);
> +
>   	/* start the watchdog. */
>   	hw->mac.get_link_status = 1;
>   	schedule_work(&adapter->watchdog_task);
> @@ -1368,7 +2191,11 @@ static int __igc_open(struct net_device *netdev, bool resuming)
>   err_req_irq:
>   	igc_release_hw_control(adapter);
>   	igc_power_down_link(adapter);
> -	/* TODO complete free_all_rx_resources */
> +	igc_free_all_rx_resources(adapter);
> +err_setup_rx:
> +	igc_free_all_tx_resources(adapter);
> +err_setup_tx:
> +	igc_reset(adapter);
>   
>   	return err;
>   }
> @@ -1401,6 +2228,9 @@ static int __igc_close(struct net_device *netdev, bool suspending)
>   
>   	igc_free_irq(adapter);
>   
> +	igc_free_all_tx_resources(adapter);
> +	igc_free_all_rx_resources(adapter);
> +
>   	return 0;
>   }
>   
> @@ -1415,6 +2245,7 @@ static const struct net_device_ops igc_netdev_ops = {
>   	.ndo_open               = igc_open,
>   	.ndo_stop               = igc_close,
>   	.ndo_start_xmit         = igc_xmit_frame,
> +	.ndo_set_rx_mode        = igc_set_rx_mode,
>   	.ndo_set_mac_address    = igc_set_mac,
>   	.ndo_change_mtu         = igc_change_mtu,
>   	.ndo_get_stats          = igc_get_stats,
>
Sasha Neftin July 3, 2018, 1:17 p.m. UTC | #3
On 6/28/2018 03:42, Shannon Nelson wrote:
> On 6/24/2018 1:45 AM, Sasha Neftin wrote:
>> This change adds the defines and structures necessary to support both Tx
>> and Rx descriptor rings.
>>
>> Sasha Neftin (v2):
>> fixed code indentation
>>
>> Sasha Nedftin (v3):
>> minor code fixes
>>
>> Signed-off-by: Sasha Neftin <sasha.neftin@intel.com>
>> ---
>>   drivers/net/ethernet/intel/igc/Makefile        |   3 +-
>>   drivers/net/ethernet/intel/igc/e1000_base.c    |  83 +++
>>   drivers/net/ethernet/intel/igc/e1000_base.h    |  89 +++
>>   drivers/net/ethernet/intel/igc/e1000_defines.h |  53 ++
>>   drivers/net/ethernet/intel/igc/e1000_hw.h      |   1 +
>>   drivers/net/ethernet/intel/igc/e1000_regs.h    |   3 +
>>   drivers/net/ethernet/intel/igc/igc.h           | 127 ++++
>>   drivers/net/ethernet/intel/igc/igc_main.c      | 839 
>> ++++++++++++++++++++++++-
>>   8 files changed, 1193 insertions(+), 5 deletions(-)
>>   create mode 100644 drivers/net/ethernet/intel/igc/e1000_base.c
>>   create mode 100644 drivers/net/ethernet/intel/igc/e1000_base.h
>>
>> diff --git a/drivers/net/ethernet/intel/igc/Makefile 
>> b/drivers/net/ethernet/intel/igc/Makefile
>> index 4563b83cd4e0..6a757ac8492d 100644
>> --- a/drivers/net/ethernet/intel/igc/Makefile
>> +++ b/drivers/net/ethernet/intel/igc/Makefile
>> @@ -7,4 +7,5 @@
>>   obj-$(CONFIG_IGC) += igc.o
>> -igc-objs := igc_main.o e1000_mac.o
>> +igc-objs := igc_main.o e1000_mac.o \
>> +e1000_base.o
>> diff --git a/drivers/net/ethernet/intel/igc/e1000_base.c 
>> b/drivers/net/ethernet/intel/igc/e1000_base.c
>> new file mode 100644
>> index 000000000000..265ec98000e7
>> --- /dev/null
>> +++ b/drivers/net/ethernet/intel/igc/e1000_base.c
>> @@ -0,0 +1,83 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/* Copyright (c)  2018 Intel Corporation */
>> +
>> +#include <linux/delay.h>
>> +
>> +#include "e1000_hw.h"
>> +#include "e1000_i225.h"
>> +
>> +/**
>> + *  igc_rx_fifo_flush_base - Clean rx fifo after Rx enable
>> + *  @hw: pointer to the HW structure
>> + *
>> + *  After Rx enable, if manageability is enabled then there is likely 
>> some
>> + *  bad data at the start of the fifo and possibly in the DMA fifo.  
>> This
>> + *  function clears the fifos and flushes any packets that came in as 
>> rx was
>> + *  being enabled.
>> + **/
>> +void igc_rx_fifo_flush_base(struct e1000_hw *hw)
>> +{
>> +    u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled;
>> +    int i, ms_wait;
>> +
>> +    /* disable IPv6 options as per hardware errata */
>> +    rfctl = rd32(E1000_RFCTL);
>> +    rfctl |= E1000_RFCTL_IPV6_EX_DIS;
>> +    wr32(E1000_RFCTL, rfctl);
> 
> Interesting... does this new hardware really have the same errata as the 
> 82575?
> 
I do not know. Probably yes, because design of MAC based on same code. I 
need to check it. Anyway, this will required validation cycle.
>> +
>> +    if (!(rd32(E1000_MANC) & E1000_MANC_RCV_TCO_EN))
>> +        return;
>> +
>> +    /* Disable all Rx queues */
>> +    for (i = 0; i < 4; i++) {
>> +        rxdctl[i] = rd32(E1000_RXDCTL(i));
>> +        wr32(E1000_RXDCTL(i),
>> +             rxdctl[i] & ~E1000_RXDCTL_QUEUE_ENABLE);
>> +    }
>> +    /* Poll all queues to verify they have shut down */
>> +    for (ms_wait = 0; ms_wait < 10; ms_wait++) {
>> +        usleep_range(1000, 2000);
>> +        rx_enabled = 0;
>> +        for (i = 0; i < 4; i++)
>> +            rx_enabled |= rd32(E1000_RXDCTL(i));
>> +        if (!(rx_enabled & E1000_RXDCTL_QUEUE_ENABLE))
>> +            break;
>> +    }
>> +
>> +    if (ms_wait == 10)
>> +        pr_debug("Queue disable timed out after 10ms\n");
>> +
>> +    /* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all
>> +     * incoming packets are rejected.  Set enable and wait 2ms so that
>> +     * any packet that was coming in as RCTL.EN was set is flushed
>> +     */
>> +    wr32(E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF);
>> +
>> +    rlpml = rd32(E1000_RLPML);
>> +    wr32(E1000_RLPML, 0);
>> +
>> +    rctl = rd32(E1000_RCTL);
>> +    temp_rctl = rctl & ~(E1000_RCTL_EN | E1000_RCTL_SBP);
>> +    temp_rctl |= E1000_RCTL_LPE;
>> +
>> +    wr32(E1000_RCTL, temp_rctl);
>> +    wr32(E1000_RCTL, temp_rctl | E1000_RCTL_EN);
>> +    wrfl();
>> +    usleep_range(2000, 3000);
>> +
>> +    /* Enable Rx queues that were previously enabled and restore our
>> +     * previous state
>> +     */
>> +    for (i = 0; i < 4; i++)
>> +        wr32(E1000_RXDCTL(i), rxdctl[i]);
>> +    wr32(E1000_RCTL, rctl);
>> +    wrfl();
>> +
>> +    wr32(E1000_RLPML, rlpml);
>> +    wr32(E1000_RFCTL, rfctl);
>> +
>> +    /* Flush receive errors generated by workaround */
>> +    rd32(E1000_ROC);
>> +    rd32(E1000_RNBC);
>> +    rd32(E1000_MPC);
>> +}
>> diff --git a/drivers/net/ethernet/intel/igc/e1000_base.h 
>> b/drivers/net/ethernet/intel/igc/e1000_base.h
>> new file mode 100644
>> index 000000000000..9acc41d73f4f
>> --- /dev/null
>> +++ b/drivers/net/ethernet/intel/igc/e1000_base.h
>> @@ -0,0 +1,89 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/* Copyright (c)  2018 Intel Corporation */
>> +
>> +#ifndef _E1000_BASE_H
>> +#define _E1000_BASE_H
>> +
>> +/* forward declaration */
>> +void igc_rx_fifo_flush_base(struct e1000_hw *hw);
>> +
>> +/* Transmit Descriptor - Advanced */
>> +union e1000_adv_tx_desc {
>> +    struct {
>> +        __le64 buffer_addr;    /* Address of descriptor's data buf */
>> +        __le32 cmd_type_len;
>> +    __le32 olinfo_status;
> 
> Intent problem?
> 
Right. fix will be applied in v4.
>> +    } read;
>> +    struct {
>> +        __le64 rsvd;       /* Reserved */
>> +        __le32 nxtseq_seed;
>> +        __le32 status;
>> +    } wb;
>> +};
>> +
>> +struct e1000_adv_data_desc {
>> +    __le64 buffer_addr;    /* Address of the descriptor's data buffer */
>> +    union {
>> +        u32 data;
>> +        struct {
>> +            u32 datalen:16; /* Data buffer length */
>> +            u32 rsvd:4;
>> +            u32 dtyp:4;  /* Descriptor type */
>> +            u32 dcmd:8;  /* Descriptor command */
>> +        } config;
> 
> Will this bit layout work correctly on big-endian CPU?
> 
>> +    } lower;
>> +    union {
>> +        u32 data;
>> +        struct {
>> +            u32 status:4;  /* Descriptor status */
>> +            u32 idx:4;
>> +            u32 popts:6;  /* Packet Options */
>> +            u32 paylen:18; /* Payload length */
> 
> Will this bit layout work correctly on big-endian CPU?
> 
>> +        } options;
>> +    } upper;
>> +};
>> +
>> +/* Receive Descriptor - Advanced */
>> +union e1000_adv_rx_desc {
>> +    struct {
>> +        __le64 pkt_addr; /* Packet buffer address */
>> +        __le64 hdr_addr; /* Header buffer address */
>> +    } read;
>> +    struct {
>> +        struct {
>> +            union {
>> +                __le32 data;
>> +                struct {
>> +                    __le16 pkt_info; /*RSS type, Pkt type*/
>> +                    /* Split Header, header buffer len */
>> +                    __le16 hdr_info;
>> +                } hs_rss;
>> +            } lo_dword;
>> +            union {
>> +                __le32 rss; /* RSS Hash */
>> +                struct {
>> +                    __le16 ip_id; /* IP id */
>> +                    __le16 csum; /* Packet Checksum */
>> +                } csum_ip;
>> +            } hi_dword;
>> +        } lower;
>> +        struct {
>> +            __le32 status_error; /* ext status/error */
>> +            __le16 length; /* Packet length */
>> +            __le16 vlan; /* VLAN tag */
>> +        } upper;
>> +    } wb;  /* writeback */
>> +};
>> +
>> +/* Additional Transmit Descriptor Control definitions */
>> +#define E1000_TXDCTL_QUEUE_ENABLE    0x02000000 /* Ena specific Tx 
>> Queue */
>> +
>> +/* Additional Receive Descriptor Control definitions */
>> +#define E1000_RXDCTL_QUEUE_ENABLE    0x02000000 /* Ena specific Rx 
>> Queue */
>> +
>> +/* SRRCTL bit definitions */
>> +#define E1000_SRRCTL_BSIZEPKT_SHIFT        10 /* Shift _right_ */
>> +#define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT        2  /* Shift _left_ */
>> +#define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF    0x02000000
>> +
>> +#endif /* _E1000_BASE_H */
>> diff --git a/drivers/net/ethernet/intel/igc/e1000_defines.h 
>> b/drivers/net/ethernet/intel/igc/e1000_defines.h
>> index 1f8bc16c7029..66f8fc96dfb8 100644
>> --- a/drivers/net/ethernet/intel/igc/e1000_defines.h
>> +++ b/drivers/net/ethernet/intel/igc/e1000_defines.h
>> @@ -71,6 +71,10 @@
>>   #define E1000_ICR_RXO        0x00000040 /* Rx overrun */
>>   #define E1000_ICR_RXT0        0x00000080 /* Rx timer intr (ring 0) */
>>   #define E1000_ICR_DRSTA        0x40000000 /* Device Reset Asserted */
>> +
>> +/* If this bit asserted, the driver should claim the interrupt */
>> +#define E1000_ICR_INT_ASSERTED    0x80000000
>> +
>>   #define E1000_ICS_RXT0        E1000_ICR_RXT0      /* Rx timer intr */
>>   #define IMS_ENABLE_MASK ( \
>> @@ -97,4 +101,53 @@
>>   #define E1000_GPIE_EIAME    0x40000000
>>   #define E1000_GPIE_PBA        0x80000000
>> +/* Transmit Control */
>> +#define E1000_TCTL_EN        0x00000002 /* enable Tx */
>> +#define E1000_TCTL_PSP        0x00000008 /* pad short packets */
>> +#define E1000_TCTL_CT        0x00000ff0 /* collision threshold */
>> +#define E1000_TCTL_COLD        0x003ff000 /* collision distance */
>> +#define E1000_TCTL_RTLC        0x01000000 /* Re-transmit on late 
>> collision */
>> +#define E1000_TCTL_MULR        0x10000000 /* Multiple request support */
>> +
>> +#define E1000_CT_SHIFT            4
>> +#define E1000_COLLISION_THRESHOLD    15
>> +
>> +/* Management Control */
>> +#define E1000_MANC_RCV_TCO_EN    0x00020000 /* Receive TCO Packets 
>> Enabled */
>> +
>> +/* Receive Control */
>> +#define E1000_RCTL_RST        0x00000001 /* Software reset */
>> +#define E1000_RCTL_EN        0x00000002 /* enable */
>> +#define E1000_RCTL_SBP        0x00000004 /* store bad packet */
>> +#define E1000_RCTL_UPE        0x00000008 /* unicast promisc enable */
>> +#define E1000_RCTL_MPE        0x00000010 /* multicast promisc enable */
>> +#define E1000_RCTL_LPE        0x00000020 /* long packet enable */
>> +#define E1000_RCTL_LBM_NO    0x00000000 /* no loopback mode */
>> +#define E1000_RCTL_LBM_MAC    0x00000040 /* MAC loopback mode */
>> +#define E1000_RCTL_LBM_TCVR    0x000000C0 /* tcvr loopback mode */
>> +#define E1000_RCTL_DTYP_PS    0x00000400 /* Packet Split descriptor */
>> +
>> +#define E1000_RCTL_RDMTS_HALF    0x00000000 /* Rx desc min thresh 
>> size */
>> +#define E1000_RCTL_BAM        0x00008000 /* broadcast enable */
>> +
>> +/* Header split receive */
>> +#define E1000_RFCTL_IPV6_EX_DIS    0x00010000
>> +#define E1000_RFCTL_LEF        0x00040000
>> +
>> +/* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */
>> +#define E1000_RCTL_SZ_2048    0x00000000 /* Rx buffer size 2048 */
>> +#define E1000_RCTL_SZ_1024    0x00010000 /* Rx buffer size 1024 */
>> +#define E1000_RCTL_SZ_512    0x00020000 /* Rx buffer size 512 */
>> +#define E1000_RCTL_SZ_256    0x00030000 /* Rx buffer size 256 */
>> +/* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */
>> +#define E1000_RCTL_SZ_16384    0x00010000 /* Rx buffer size 16384 */
>> +#define E1000_RCTL_SZ_8192    0x00020000 /* Rx buffer size 8192 */
>> +#define E1000_RCTL_SZ_4096    0x00030000 /* Rx buffer size 4096 */
>> +
>> +#define E1000_RCTL_MO_SHIFT    12 /* multicast offset shift */
>> +#define E1000_RCTL_CFIEN    0x00080000 /* canonical form enable */
>> +#define E1000_RCTL_DPF        0x00400000 /* discard pause frames */
>> +#define E1000_RCTL_PMCF        0x00800000 /* pass MAC control frames */
>> +#define E1000_RCTL_SECRC    0x04000000 /* Strip Ethernet CRC */
>> +
>>   #endif /* _E1000_DEFINES_H_ */
>> diff --git a/drivers/net/ethernet/intel/igc/e1000_hw.h 
>> b/drivers/net/ethernet/intel/igc/e1000_hw.h
>> index 650c4ac981d9..67fa4f696b98 100644
>> --- a/drivers/net/ethernet/intel/igc/e1000_hw.h
>> +++ b/drivers/net/ethernet/intel/igc/e1000_hw.h
>> @@ -10,6 +10,7 @@
>>   #include "e1000_defines.h"
>>   #include "e1000_mac.h"
>>   #include "e1000_i225.h"
>> +#include "e1000_base.h"
>>   #define E1000_DEV_ID_I225_LM            0x15F2
>>   #define E1000_DEV_ID_I225_V            0x15F3
>> diff --git a/drivers/net/ethernet/intel/igc/e1000_regs.h 
>> b/drivers/net/ethernet/intel/igc/e1000_regs.h
>> index 5634a01afff3..dcc4d89c9933 100644
>> --- a/drivers/net/ethernet/intel/igc/e1000_regs.h
>> +++ b/drivers/net/ethernet/intel/igc/e1000_regs.h
>> @@ -229,6 +229,9 @@
>>   #define E1000_TLPIC    0x4148 /* EEE Tx LPI Count - TLPIC */
>>   #define E1000_RLPIC    0x414C /* EEE Rx LPI Count - RLPIC */
>> +/* Management registers */
>> +#define E1000_MANC    0x05820  /* Management Control - RW */
>> +
>>   /* forward declaration */
>>   struct e1000_hw;
>>   u32 igc_rd32(struct e1000_hw *hw, u32 reg);
>> diff --git a/drivers/net/ethernet/intel/igc/igc.h 
>> b/drivers/net/ethernet/intel/igc/igc.h
>> index 7cab3e9c8e91..abf2e302c417 100644
>> --- a/drivers/net/ethernet/intel/igc/igc.h
>> +++ b/drivers/net/ethernet/intel/igc/igc.h
>> @@ -46,6 +46,47 @@ extern char igc_driver_version[];
>>   #define MAX_Q_VECTORS                     10
>>   #define MAX_STD_JUMBO_FRAME_SIZE        9216
>> +#define IGC_TX_PTHRESH            8
>> +#define IGC_TX_HTHRESH            1
>> +
my apologies. this define duplicated. fix will be applied in v4.
>> +/* Supported Rx Buffer Sizes */
>> +#define IGC_RXBUFFER_256        256
>> +#define IGC_RXBUFFER_2048        2048
>> +#define IGC_RXBUFFER_3072        3072
>> +
>> +#define IGC_RX_HDR_LEN            IGC_RXBUFFER_256
>> +
>> +/* RX and TX descriptor control thresholds.
>> + * PTHRESH - MAC will consider prefetch if it has fewer than this 
>> number of
>> + *           descriptors available in its onboard memory.
>> + *           Setting this to 0 disables RX descriptor prefetch.
>> + * HTHRESH - MAC will only prefetch if there are at least this many 
>> descriptors
>> + *           available in host memory.
>> + *           If PTHRESH is 0, this should also be 0.
>> + * WTHRESH - RX descriptor writeback threshold - MAC will delay 
>> writing back
>> + *           descriptors until either it has this many to write back, 
>> or the
>> + *           ITR timer expires.
>> + */
>> +#define IGC_RX_PTHRESH            8
>> +#define IGC_RX_HTHRESH            8
>> +#define IGC_TX_PTHRESH            8
>> +#define IGC_TX_HTHRESH            1
>> +#define IGC_RX_WTHRESH            4
>> +
>> +#define IGC_RX_DMA_ATTR \
>> +    (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING)
>> +
>> +#define IGC_TS_HDR_LEN            16
>> +
>> +#define IGC_SKB_PAD            (NET_SKB_PAD + NET_IP_ALIGN)
>> +
>> +#if (PAGE_SIZE < 8192)
>> +#define IGC_MAX_FRAME_BUILD_SKB \
>> +    (SKB_WITH_OVERHEAD(IGC_RXBUFFER_2048) - IGC_SKB_PAD - 
>> IGC_TS_HDR_LEN)
>> +#else
>> +#define IGC_MAX_FRAME_BUILD_SKB (IGC_RXBUFFER_2048 - IGC_TS_HDR_LEN)
>> +#endif
>> +
>>   enum e1000_state_t {
>>        __IGC_TESTING,
>>       __IGC_RESETTING,
>> @@ -53,6 +94,33 @@ enum e1000_state_t {
>>        __IGC_PTP_TX_IN_PROGRESS,
>>   };
>> +/** wrapper around a pointer to a socket buffer,
>> + *  so a DMA handle can be stored along with the buffer
>> + **/
> 
> This comment shouldn't have /** or **/, just /* and */
> 
fix will be applied in v4.
>> +struct igc_tx_buffer {
>> +    union e1000_adv_tx_desc *next_to_watch;
>> +    unsigned long time_stamp;
>> +    struct sk_buff *skb;
>> +    unsigned int bytecount;
>> +    u16 gso_segs;
>> +    __be16 protocol;
>> +
>> +    DEFINE_DMA_UNMAP_ADDR(dma);
>> +    DEFINE_DMA_UNMAP_LEN(len);
>> +    u32 tx_flags;
>> +};
>> +
>> +struct igc_rx_buffer {
>> +    dma_addr_t dma;
>> +    struct page *page;
>> +#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)
>> +    __u32 page_offset;
>> +#else
>> +    __u16 page_offset;
>> +#endif
>> +    __u16 pagecnt_bias;
>> +};
>> +
>>   struct igc_tx_queue_stats {
>>       u64 packets;
>>       u64 bytes;
>> @@ -218,4 +286,63 @@ struct igc_adapter {
>>       struct igc_mac_addr *mac_table;
>>   };
>> +/* igc_desc_unused - calculate if we have unused descriptors */
>> +static inline u16 igc_desc_unused(const struct igc_ring *ring)
>> +{
>> +    u16 ntc = ring->next_to_clean;
>> +    u16 ntu = ring->next_to_use;
>> +
>> +    return ((ntc > ntu) ? 0 : ring->count) + ntc - ntu - 1;
>> +}
>> +
>> +static inline struct netdev_queue *txring_txq(const struct igc_ring 
>> *tx_ring)
>> +{
>> +    return netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index);
>> +}
>> +
>> +enum e1000_ring_flags_t {
>> +    IGC_RING_FLAG_RX_3K_BUFFER,
>> +    IGC_RING_FLAG_RX_BUILD_SKB_ENABLED,
>> +    IGC_RING_FLAG_RX_SCTP_CSUM,
>> +    IGC_RING_FLAG_RX_LB_VLAN_BSWAP,
>> +    IGC_RING_FLAG_TX_CTX_IDX,
>> +    IGC_RING_FLAG_TX_DETECT_HANG
>> +};
>> +
>> +#define ring_uses_large_buffer(ring) \
>> +    test_bit(IGC_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
>> +
>> +#define ring_uses_build_skb(ring) \
>> +    test_bit(IGC_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
>> +
>> +static inline unsigned int igc_rx_bufsz(struct igc_ring *ring)
>> +{
>> +#if (PAGE_SIZE < 8192)
>> +    if (ring_uses_large_buffer(ring))
>> +        return IGC_RXBUFFER_3072;
>> +
>> +    if (ring_uses_build_skb(ring))
>> +        return IGC_MAX_FRAME_BUILD_SKB + IGC_TS_HDR_LEN;
>> +#endif
>> +    return IGC_RXBUFFER_2048;
>> +}
>> +
>> +static inline unsigned int igc_rx_pg_order(struct igc_ring *ring)
>> +{
>> +#if (PAGE_SIZE < 8192)
>> +    if (ring_uses_large_buffer(ring))
>> +        return 1;
>> +#endif
>> +    return 0;
>> +}
>> +
>> +#define igc_rx_pg_size(_ring) (PAGE_SIZE << igc_rx_pg_order(_ring))
>> +
>> +#define IGC_RX_DESC(R, i)       \
>> +    (&(((union e1000_adv_rx_desc *)((R)->desc))[i]))
>> +#define IGC_TX_DESC(R, i)       \
>> +    (&(((union e1000_adv_tx_desc *)((R)->desc))[i]))
>> +#define IGC_TX_CTXTDESC(R, i)   \
>> +    (&(((struct e1000_adv_tx_context_desc *)((R)->desc))[i]))
>> +
>>   #endif /* _IGC_H_ */
>> diff --git a/drivers/net/ethernet/intel/igc/igc_main.c 
>> b/drivers/net/ethernet/intel/igc/igc_main.c
>> index 30b778c9b94b..a147a1b7585e 100644
>> --- a/drivers/net/ethernet/intel/igc/igc_main.c
>> +++ b/drivers/net/ethernet/intel/igc/igc_main.c
>> @@ -29,11 +29,21 @@ static const struct pci_device_id igc_pci_tbl[] = {
>>   MODULE_DEVICE_TABLE(pci, igc_pci_tbl);
>>   /* forward declaration */
>> +static int igc_setup_all_tx_resources(struct igc_adapter *adapter);
>> +static void igc_clean_tx_ring(struct igc_ring *tx_ring);
>> +static void igc_free_all_tx_resources(struct igc_adapter *adapter);
>> +static int igc_setup_all_rx_resources(struct igc_adapter *adapter);
>>   static int igc_sw_init(struct igc_adapter *);
>>   static void igc_configure(struct igc_adapter *adapter);
>> +static void igc_configure_tx(struct igc_adapter *);
>> +static void igc_configure_rx(struct igc_adapter *adapter);
>>   static void igc_power_down_link(struct igc_adapter *adapter);
>>   static void igc_set_default_mac_filter(struct igc_adapter *adapter);
>> +static void igc_set_rx_mode(struct net_device *netdev);
>> +static void igc_setup_mrqc(struct igc_adapter *adapter);
>>   static irqreturn_t igc_msix_ring(int irq, void *data);
>> +static irqreturn_t igc_intr_msi(int irq, void *data);
>> +static irqreturn_t igc_intr(int irq, void *data);
>>   static void igc_write_itr(struct igc_q_vector *q_vector);
>>   static int igc_request_msix(struct igc_adapter *adapter);
>>   static void igc_assign_vector(struct igc_q_vector *q_vector, int 
>> msix_vector);
>> @@ -125,6 +135,526 @@ static void igc_get_hw_control(struct 
>> igc_adapter *adapter)
>>   }
>>   /**
>> + *  igc_free_tx_resources - Free Tx Resources per Queue
>> + *  @tx_ring: Tx descriptor ring for a specific queue
>> + *
>> + *  Free all transmit software resources
>> + **/
>> +void igc_free_tx_resources(struct igc_ring *tx_ring)
>> +{
>> +    igc_clean_tx_ring(tx_ring);
>> +
>> +    vfree(tx_ring->tx_buffer_info);
>> +    tx_ring->tx_buffer_info = NULL;
>> +
>> +    /* if not set, then don't free */
>> +    if (!tx_ring->desc)
>> +        return;
>> +
>> +    dma_free_coherent(tx_ring->dev, tx_ring->size,
>> +              tx_ring->desc, tx_ring->dma);
>> +
>> +    tx_ring->desc = NULL;
>> +}
>> +
>> +/**
>> + *  igc_free_all_tx_resources - Free Tx Resources for All Queues
>> + *  @adapter: board private structure
>> + *
>> + *  Free all transmit software resources
>> + **/
>> +static void igc_free_all_tx_resources(struct igc_adapter *adapter)
>> +{
>> +    int i;
>> +
>> +    for (i = 0; i < adapter->num_tx_queues; i++)
>> +        igc_free_tx_resources(adapter->tx_ring[i]);
>> +}
>> +
>> +void igc_unmap_and_free_tx_resource(struct igc_ring *ring,
>> +                    struct igc_tx_buffer *tx_buffer)
>> +{
>> +    if (tx_buffer->skb) {
>> +        dev_kfree_skb_any(tx_buffer->skb);
>> +        if (dma_unmap_len(tx_buffer, len))
>> +            dma_unmap_single(ring->dev,
>> +                     dma_unmap_addr(tx_buffer, dma),
>> +                     dma_unmap_len(tx_buffer, len),
>> +                     DMA_TO_DEVICE);
>> +    } else if (dma_unmap_len(tx_buffer, len)) {
>> +        dma_unmap_page(ring->dev,
>> +                   dma_unmap_addr(tx_buffer, dma),
>> +                   dma_unmap_len(tx_buffer, len),
>> +                   DMA_TO_DEVICE);
>> +    }
>> +    tx_buffer->next_to_watch = NULL;
>> +    tx_buffer->skb = NULL;
>> +    dma_unmap_len_set(tx_buffer, len, 0);
>> +    /* buffer_info must be completely set up in the transmit path */
>> +}
>> +
>> +/**
>> + *  igc_clean_tx_ring - Free Tx Buffers
>> + *  @tx_ring: ring to be cleaned
>> + **/
>> +static void igc_clean_tx_ring(struct igc_ring *tx_ring)
>> +{
>> +    struct igc_tx_buffer *buffer_info;
>> +    unsigned long size;
>> +    u16 i;
>> +
>> +    if (!tx_ring->tx_buffer_info)
>> +        return;
>> +
>> +    /* Free all the Tx ring sk_buffs */
>> +    for (i = 0; i < tx_ring->count; i++) {
>> +        buffer_info = &tx_ring->tx_buffer_info[i];
>> +        igc_unmap_and_free_tx_resource(tx_ring, buffer_info);
>> +    }
>> +
>> +    netdev_tx_reset_queue(txring_txq(tx_ring));
>> +
>> +    size = sizeof(struct igc_tx_buffer) * tx_ring->count;
>> +    memset(tx_ring->tx_buffer_info, 0, size);
>> +
>> +    /* Zero out the descriptor ring */
>> +    memset(tx_ring->desc, 0, tx_ring->size);
>> +
>> +    tx_ring->next_to_use = 0;
>> +    tx_ring->next_to_clean = 0;
>> +}
>> +
>> +/**
>> + *  igc_setup_tx_resources - allocate Tx resources (Descriptors)
>> + *  @tx_ring: tx descriptor ring (for a specific queue) to setup
>> + *
>> + *  Return 0 on success, negative on failure
>> + **/
>> +int igc_setup_tx_resources(struct igc_ring *tx_ring)
>> +{
>> +    struct device *dev = tx_ring->dev;
>> +    int size = 0;
>> +
>> +    size = sizeof(struct igc_tx_buffer) * tx_ring->count;
>> +    tx_ring->tx_buffer_info = vzalloc(size);
>> +    if (!tx_ring->tx_buffer_info)
>> +        goto err;
>> +
>> +    /* round up to nearest 4K */
>> +    tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc);
>> +    tx_ring->size = ALIGN(tx_ring->size, 4096);
>> +
>> +    tx_ring->desc = dma_alloc_coherent(dev, tx_ring->size,
>> +                       &tx_ring->dma, GFP_KERNEL);
>> +
>> +    if (!tx_ring->desc)
>> +        goto err;
>> +
>> +    tx_ring->next_to_use = 0;
>> +    tx_ring->next_to_clean = 0;
>> +
>> +    return 0;
>> +
>> +err:
>> +    vfree(tx_ring->tx_buffer_info);
>> +    dev_err(dev,
>> +        "Unable to allocate memory for the transmit descriptor ring\n");
>> +    return -ENOMEM;
>> +}
>> +
>> +/**
>> + *  igc_setup_all_tx_resources - wrapper to allocate Tx resources
>> + *                                (Descriptors) for all queues
> 
> This should be a single line
> 
fix will be applied in v4.
>> + *  @adapter: board private structure
>> + *
>> + *  Return 0 on success, negative on failure
>> + **/
>> +static int igc_setup_all_tx_resources(struct igc_adapter *adapter)
>> +{
>> +    struct pci_dev *pdev = adapter->pdev;
>> +    int i, err = 0;
>> +
>> +    for (i = 0; i < adapter->num_tx_queues; i++) {
>> +        err = igc_setup_tx_resources(adapter->tx_ring[i]);
>> +        if (err) {
>> +            dev_err(&pdev->dev,
>> +                "Allocation for Tx Queue %u failed\n", i);
>> +            for (i--; i >= 0; i--)
>> +                igc_free_tx_resources(adapter->tx_ring[i]);
>> +            break;
>> +        }
>> +    }
>> +
>> +    return err;
>> +}
>> +
>> +/**
>> + *  igc_clean_rx_ring - Free Rx Buffers per Queue
>> + *  @rx_ring: ring to free buffers from
>> + **/
>> +void igc_clean_rx_ring(struct igc_ring *rx_ring)
>> +{
>> +    u16 i = rx_ring->next_to_clean;
>> +
>> +    if (rx_ring->skb)
>> +        dev_kfree_skb(rx_ring->skb);
>> +    rx_ring->skb = NULL;
>> +
>> +    /* Free all the Rx ring sk_buffs */
>> +    while (i != rx_ring->next_to_alloc) {
>> +        struct igc_rx_buffer *buffer_info = &rx_ring->rx_buffer_info[i];
>> +
>> +        /* Invalidate cache lines that may have been written to by
>> +         * device so that we avoid corrupting memory.
>> +         */
>> +        dma_sync_single_range_for_cpu(rx_ring->dev,
>> +                          buffer_info->dma,
>> +                          buffer_info->page_offset,
>> +                          igc_rx_bufsz(rx_ring),
>> +                          DMA_FROM_DEVICE);
>> +
>> +        /* free resources associated with mapping */
>> +        dma_unmap_page_attrs(rx_ring->dev,
>> +                     buffer_info->dma,
>> +                     igc_rx_pg_size(rx_ring),
>> +                     DMA_FROM_DEVICE,
>> +                     IGC_RX_DMA_ATTR);
>> +        __page_frag_cache_drain(buffer_info->page,
>> +                    buffer_info->pagecnt_bias);
>> +
>> +        i++;
>> +        if (i == rx_ring->count)
>> +            i = 0;
>> +    }
>> +
>> +    rx_ring->next_to_alloc = 0;
>> +    rx_ring->next_to_clean = 0;
>> +    rx_ring->next_to_use = 0;
>> +}
>> +
>> +/**
>> + *  igc_free_rx_resources - Free Rx Resources
>> + *  @rx_ring: ring to clean the resources from
>> + *
>> + *  Free all receive software resources
>> + **/
>> +void igc_free_rx_resources(struct igc_ring *rx_ring)
>> +{
>> +    igc_clean_rx_ring(rx_ring);
>> +
>> +    vfree(rx_ring->rx_buffer_info);
>> +    rx_ring->rx_buffer_info = NULL;
>> +
>> +    /* if not set, then don't free */
>> +    if (!rx_ring->desc)
>> +        return;
>> +
>> +    dma_free_coherent(rx_ring->dev, rx_ring->size,
>> +              rx_ring->desc, rx_ring->dma);
>> +
>> +    rx_ring->desc = NULL;
>> +}
>> +
>> +/**
>> + *  igc_free_all_rx_resources - Free Rx Resources for All Queues
>> + *  @adapter: board private structure
>> + *
>> + *  Free all receive software resources
>> + **/
>> +static void igc_free_all_rx_resources(struct igc_adapter *adapter)
>> +{
>> +    int i;
>> +
>> +    for (i = 0; i < adapter->num_rx_queues; i++)
>> +        igc_free_rx_resources(adapter->rx_ring[i]);
>> +}
>> +
>> +/**
>> + *  igc_setup_rx_resources - allocate Rx resources (Descriptors)
>> + *  @rx_ring:    rx descriptor ring (for a specific queue) to setup
>> + *
>> + *  Returns 0 on success, negative on failure
>> + **/
>> +int igc_setup_rx_resources(struct igc_ring *rx_ring)
>> +{
>> +    struct device *dev = rx_ring->dev;
>> +    int size, desc_len;
>> +
>> +    size = sizeof(struct igc_rx_buffer) * rx_ring->count;
>> +    rx_ring->rx_buffer_info = vzalloc(size);
>> +    if (!rx_ring->rx_buffer_info)
>> +        goto err;
>> +
>> +    desc_len = sizeof(union e1000_adv_rx_desc);
>> +
>> +    /* Round up to nearest 4K */
>> +    rx_ring->size = rx_ring->count * desc_len;
>> +    rx_ring->size = ALIGN(rx_ring->size, 4096);
>> +
>> +    rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size,
>> +                       &rx_ring->dma, GFP_KERNEL);
>> +
>> +    if (!rx_ring->desc)
>> +        goto err;
>> +
>> +    rx_ring->next_to_alloc = 0;
>> +    rx_ring->next_to_clean = 0;
>> +    rx_ring->next_to_use = 0;
>> +
>> +    return 0;
>> +
>> +err:
>> +    vfree(rx_ring->rx_buffer_info);
>> +    rx_ring->rx_buffer_info = NULL;
>> +    dev_err(dev,
>> +        "Unable to allocate memory for the receive descriptor ring\n");
>> +    return -ENOMEM;
>> +}
>> +
>> +/**
>> + *  igc_setup_all_rx_resources - wrapper to allocate Rx resources
>> + *                                (Descriptors) for all queues
>> + *  @adapter: board private structure
>> + *
>> + *  Return 0 on success, negative on failure
>> + **/
>> +static int igc_setup_all_rx_resources(struct igc_adapter *adapter)
>> +{
>> +    struct pci_dev *pdev = adapter->pdev;
>> +    int i, err = 0;
>> +
>> +    for (i = 0; i < adapter->num_rx_queues; i++) {
>> +        err = igc_setup_rx_resources(adapter->rx_ring[i]);
>> +        if (err) {
>> +            dev_err(&pdev->dev,
>> +                "Allocation for Rx Queue %u failed\n", i);
>> +            for (i--; i >= 0; i--)
>> +                igc_free_rx_resources(adapter->rx_ring[i]);
>> +            break;
>> +        }
>> +    }
>> +
>> +    return err;
>> +}
>> +
>> +static u32 igc_tx_wthresh(struct igc_adapter *adapter)
>> +{
>> +    return 16;
> 
> Is there a #define for this?  Why is this a function?
> 
Good catch. Thanks. This function should be gone. I will rework and use 
define for IGC_TX_WTHRESH. Fix will be applied in v4.
>> +}
>> +
>> +/**
>> + *  igc_configure_rx_ring - Configure a receive ring after Reset
>> + *  @adapter: board private structure
>> + *  @ring: receive ring to be configured
>> + *
>> + *  Configure the Rx unit of the MAC after a reset.
>> + **/
>> +void igc_configure_rx_ring(struct igc_adapter *adapter,
>> +               struct igc_ring *ring)
>> +{
>> +    struct e1000_hw *hw = &adapter->hw;
>> +    union e1000_adv_rx_desc *rx_desc;
>> +    u64 rdba = ring->dma;
>> +    int reg_idx = ring->reg_idx;
>> +    u32 srrctl = 0, rxdctl = 0;
> 
> reverse xmas tree
> 
fix will be applied in v4.
>> +
>> +    /* disable the queue */
>> +    wr32(E1000_RXDCTL(reg_idx), 0);
>> +
>> +    /* Set DMA base address registers */
>> +    wr32(E1000_RDBAL(reg_idx),
>> +         rdba & 0x00000000ffffffffULL);
>> +    wr32(E1000_RDBAH(reg_idx), rdba >> 32);
>> +    wr32(E1000_RDLEN(reg_idx),
>> +         ring->count * sizeof(union e1000_adv_rx_desc));
>> +
>> +    /* initialize head and tail */
>> +    ring->tail = adapter->io_addr + E1000_RDT(reg_idx);
>> +    wr32(E1000_RDH(reg_idx), 0);
>> +    writel(0, ring->tail);
>> +
>> +    /* reset next-to- use/clean to place SW in sync with hardwdare */
> 
> s/hardwdare/hardware/
> 
fix will be applied in v4.
>> +    ring->next_to_clean = 0;
>> +    ring->next_to_use = 0;
>> +
>> +    /* set descriptor configuration */
>> +    srrctl = IGC_RX_HDR_LEN << E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
>> +    if (ring_uses_large_buffer(ring))
>> +        srrctl |= IGC_RXBUFFER_3072 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
>> +    else
>> +        srrctl |= IGC_RXBUFFER_2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
>> +    srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
>> +
>> +    wr32(E1000_SRRCTL(reg_idx), srrctl);
>> +
>> +    rxdctl |= IGC_RX_PTHRESH;
>> +    rxdctl |= IGC_RX_HTHRESH << 8;
>> +    rxdctl |= IGC_RX_WTHRESH << 16;
>> +
>> +    /* initialize rx_buffer_info */
>> +    memset(ring->rx_buffer_info, 0,
>> +           sizeof(struct igc_rx_buffer) * ring->count);
>> +
>> +    /* initialize Rx descriptor 0 */
>> +    rx_desc = IGC_RX_DESC(ring, 0);
>> +    rx_desc->wb.upper.length = 0;
>> +
>> +    /* enable receive descriptor fetching */
>> +    rxdctl |= E1000_RXDCTL_QUEUE_ENABLE;
>> +
>> +    wr32(E1000_RXDCTL(reg_idx), rxdctl);
>> +}
>> +
>> +/**
>> + *  igc_configure_rx - Configure receive Unit after Reset
>> + *  @adapter: board private structure
>> + *
>> + *  Configure the Rx unit of the MAC after a reset.
>> + **/
>> +static void igc_configure_rx(struct igc_adapter *adapter)
>> +{
>> +    int i;
>> +
>> +    /* Setup the HW Rx Head and Tail Descriptor Pointers and
>> +     * the Base and Length of the Rx Descriptor Ring
>> +     */
>> +    for (i = 0; i < adapter->num_rx_queues; i++)
>> +        igc_configure_rx_ring(adapter, adapter->rx_ring[i]);
>> +}
>> +
>> +/**
>> + *  igc_configure_tx_ring - Configure transmit ring after Reset
>> + *  @adapter: board private structure
>> + *  @ring: tx ring to configure
>> + *
>> + *  Configure a transmit ring after a reset.
>> + **/
>> +void igc_configure_tx_ring(struct igc_adapter *adapter,
>> +               struct igc_ring *ring)
>> +{
>> +    struct e1000_hw *hw = &adapter->hw;
>> +    u32 txdctl = 0;
>> +    u64 tdba = ring->dma;
>> +    int reg_idx = ring->reg_idx;
> 
> reverse xmas tree
> 
fix will be applied in v4.
>> +
>> +    /* disable the queue */
>> +    wr32(E1000_TXDCTL(reg_idx), 0);
>> +    wrfl();
>> +    mdelay(10);
>> +
>> +    wr32(E1000_TDLEN(reg_idx),
>> +         ring->count * sizeof(union e1000_adv_tx_desc));
>> +    wr32(E1000_TDBAL(reg_idx),
>> +         tdba & 0x00000000ffffffffULL);
>> +    wr32(E1000_TDBAH(reg_idx), tdba >> 32);
>> +
>> +    ring->tail = adapter->io_addr + E1000_TDT(reg_idx);
>> +    wr32(E1000_TDH(reg_idx), 0);
>> +    writel(0, ring->tail);
>> +
>> +    txdctl |= IGC_TX_PTHRESH;
>> +    txdctl |= IGC_TX_HTHRESH << 8;
>> +    txdctl |= igc_tx_wthresh(adapter) << 16;
>> +
>> +    txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
>> +    wr32(E1000_TXDCTL(reg_idx), txdctl);
>> +}
>> +
>> +/**
>> + *  igc_configure_tx - Configure transmit Unit after Reset
>> + *  @adapter: board private structure
>> + *
>> + *  Configure the Tx unit of the MAC after a reset.
>> + **/
>> +static void igc_configure_tx(struct igc_adapter *adapter)
>> +{
>> +    int i;
>> +
>> +    for (i = 0; i < adapter->num_tx_queues; i++)
>> +        igc_configure_tx_ring(adapter, adapter->tx_ring[i]);
>> +}
>> +
>> +/**
>> + *  igc_setup_mrqc - configure the multiple receive queue control 
>> registers
>> + *  @adapter: Board private structure
>> + **/
>> +static void igc_setup_mrqc(struct igc_adapter *adapter)
>> +{
>> +}
>> +
>> +/**
>> + *  igc_setup_rctl - configure the receive control registers
>> + *  @adapter: Board private structure
>> + **/
>> +void igc_setup_rctl(struct igc_adapter *adapter)
>> +{
>> +    struct e1000_hw *hw = &adapter->hw;
>> +    u32 rctl;
>> +
>> +    rctl = rd32(E1000_RCTL);
>> +
>> +    rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
>> +    rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
>> +
>> +    rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_RDMTS_HALF |
>> +        (hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT);
>> +
>> +    /* enable stripping of CRC. It's unlikely this will break BMC
>> +     * redirection as it did with e1000. Newer features require
>> +     * that the HW strips the CRC.
>> +     */
>> +    rctl |= E1000_RCTL_SECRC;
>> +
>> +    /* disable store bad packets and clear size bits. */
>> +    rctl &= ~(E1000_RCTL_SBP | E1000_RCTL_SZ_256);
>> +
>> +    /* enable LPE to allow for reception of jumbo frames */
>> +    rctl |= E1000_RCTL_LPE;
>> +
>> +    /* disable queue 0 to prevent tail write w/o re-config */
>> +    wr32(E1000_RXDCTL(0), 0);
>> +
>> +    /* This is useful for sniffing bad packets. */
>> +    if (adapter->netdev->features & NETIF_F_RXALL) {
>> +        /* UPE and MPE will be handled by normal PROMISC logic
>> +         * in e1000e_set_rx_mode
>> +         */
>> +        rctl |= (E1000_RCTL_SBP | /* Receive bad packets */
>> +             E1000_RCTL_BAM | /* RX All Bcast Pkts */
>> +             E1000_RCTL_PMCF); /* RX All MAC Ctrl Pkts */
>> +
>> +        rctl &= ~(E1000_RCTL_DPF | /* Allow filtered pause */
>> +              E1000_RCTL_CFIEN); /* Disable VLAN CFIEN Filter */
>> +    }
>> +
>> +    wr32(E1000_RCTL, rctl);
>> +}
>> +
>> +/**
>> + *  igc_setup_tctl - configure the transmit control registers
>> + *  @adapter: Board private structure
>> + **/
>> +void igc_setup_tctl(struct igc_adapter *adapter)
>> +{
>> +    struct e1000_hw *hw = &adapter->hw;
>> +    u32 tctl;
>> +
>> +    /* disable queue 0 which icould be enabled by default */
>> +    wr32(E1000_TXDCTL(0), 0);
>> +
>> +    /* Program the Transmit Control Register */
>> +    tctl = rd32(E1000_TCTL);
>> +    tctl &= ~E1000_TCTL_CT;
>> +    tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC |
>> +        (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
>> +
>> +    /* Enable transmits */
>> +    tctl |= E1000_TCTL_EN;
>> +
>> +    wr32(E1000_TCTL, tctl);
>> +}
>> +
>> +/**
>>    *  igc_set_mac - Change the Ethernet Address of the NIC
>>    *  @netdev: network interface device structure
>>    *  @p: pointer to an address structure
>> @@ -156,6 +686,121 @@ static netdev_tx_t igc_xmit_frame(struct sk_buff 
>> *skb,
>>       return NETDEV_TX_OK;
>>   }
>> +static inline unsigned int igc_rx_offset(struct igc_ring *rx_ring)
>> +{
>> +    return ring_uses_build_skb(rx_ring) ? IGC_SKB_PAD : 0;
>> +}
>> +
>> +static bool igc_alloc_mapped_page(struct igc_ring *rx_ring,
>> +                  struct igc_rx_buffer *bi)
>> +{
>> +    struct page *page = bi->page;
>> +    dma_addr_t dma;
>> +
>> +    /* since we are recycling buffers we should seldom need to alloc */
>> +    if (likely(page))
>> +        return true;
>> +
>> +    /* alloc new page for storage */
>> +    page = dev_alloc_pages(igc_rx_pg_order(rx_ring));
>> +    if (unlikely(!page)) {
>> +        rx_ring->rx_stats.alloc_failed++;
>> +        return false;
>> +    }
>> +
>> +    /* map page for use */
>> +    dma = dma_map_page_attrs(rx_ring->dev, page, 0,
>> +                 igc_rx_pg_size(rx_ring),
>> +                 DMA_FROM_DEVICE,
>> +                 IGC_RX_DMA_ATTR);
>> +
>> +    /* if mapping failed free memory back to system since
>> +     * there isn't much point in holding memory we can't use
>> +     */
>> +    if (dma_mapping_error(rx_ring->dev, dma)) {
>> +        __free_page(page);
>> +
>> +        rx_ring->rx_stats.alloc_failed++;
>> +        return false;
>> +    }
>> +
>> +    bi->dma = dma;
>> +    bi->page = page;
>> +    bi->page_offset = igc_rx_offset(rx_ring);
>> +    bi->pagecnt_bias = 1;
>> +
>> +    return true;
>> +}
>> +
>> +/**
>> + *  igc_alloc_rx_buffers - Replace used receive buffers; packet split
>> + *  @adapter: address of board private structure
>> + **/
>> +void igc_alloc_rx_buffers(struct igc_ring *rx_ring, u16 cleaned_count)
>> +{
>> +    union e1000_adv_rx_desc *rx_desc;
>> +    struct igc_rx_buffer *bi;
>> +    u16 i = rx_ring->next_to_use;
>> +    u16 bufsz;
> 
> reverse xmas tree
> 
fix will be applied in v4.
>> +
>> +    /* nothing to do */
>> +    if (!cleaned_count)
>> +        return;
>> +
>> +    rx_desc = IGC_RX_DESC(rx_ring, i);
>> +    bi = &rx_ring->rx_buffer_info[i];
>> +    i -= rx_ring->count;
>> +
>> +    bufsz = igc_rx_bufsz(rx_ring);
>> +
>> +    do {
>> +        if (!igc_alloc_mapped_page(rx_ring, bi))
>> +            break;
>> +
>> +        /* sync the buffer for use by the device */
>> +        dma_sync_single_range_for_device(rx_ring->dev, bi->dma,
>> +                         bi->page_offset, bufsz,
>> +                         DMA_FROM_DEVICE);
>> +
>> +        /* Refresh the desc even if buffer_addrs didn't change
>> +         * because each write-back erases this info.
>> +         */
>> +        rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset);
>> +
>> +        rx_desc++;
>> +        bi++;
>> +        i++;
>> +        if (unlikely(!i)) {
>> +            rx_desc = IGC_RX_DESC(rx_ring, 0);
>> +            bi = rx_ring->rx_buffer_info;
>> +            i -= rx_ring->count;
>> +        }
>> +
>> +        /* clear the length for the next_to_use descriptor */
>> +        rx_desc->wb.upper.length = 0;
>> +
>> +        cleaned_count--;
>> +    } while (cleaned_count);
>> +
>> +    i += rx_ring->count;
>> +
>> +    if (rx_ring->next_to_use != i) {
>> +        /* record the next descriptor to use */
>> +        rx_ring->next_to_use = i;
>> +
>> +        /* update next to alloc since we have filled the ring */
>> +        rx_ring->next_to_alloc = i;
>> +
>> +        /* Force memory writes to complete before letting h/w
>> +         * know there are new descriptors to fetch.  (Only
>> +         * applicable for weak-ordered memory model archs,
>> +         * such as IA-64).
>> +         */
>> +        wmb();
>> +        writel(i, rx_ring->tail);
>> +    }
>> +}
>> +
>>   /**
>>    *  igc_ioctl - I/O control method
>>    *  @netdev: network interface device structure
>> @@ -196,6 +841,12 @@ int igc_up(struct igc_adapter *adapter)
>>       rd32(E1000_ICR);
>>       igc_irq_enable(adapter);
>> +    netif_tx_start_all_queues(adapter->netdev);
>> +
>> +    /* start the watchdog. */
>> +    hw->mac.get_link_status = 1;
>> +    schedule_work(&adapter->watchdog_task);
> 
> But you don't actually add the watchdog setup until patch 11?
> 
>> +
>>       return 0;
>>   }
>> @@ -295,7 +946,30 @@ static struct net_device_stats 
>> *igc_get_stats(struct net_device *netdev)
>>    **/
>>   static void igc_configure(struct igc_adapter *adapter)
>>   {
>> +    struct net_device *netdev = adapter->netdev;
>> +    int i = 0;
>> +
>>       igc_get_hw_control(adapter);
>> +    igc_set_rx_mode(netdev);
>> +
>> +    igc_setup_tctl(adapter);
>> +    igc_setup_mrqc(adapter);
>> +    igc_setup_rctl(adapter);
>> +
>> +    igc_configure_tx(adapter);
>> +    igc_configure_rx(adapter);
>> +
>> +    igc_rx_fifo_flush_base(&adapter->hw);
>> +
>> +    /* call igc_desc_unused which always leaves
>> +     * at least 1 descriptor unused to make sure
>> +     * next_to_use != next_to_clean
>> +     */
>> +    for (i = 0; i < adapter->num_rx_queues; i++) {
>> +        struct igc_ring *ring = adapter->rx_ring[i];
>> +
>> +        igc_alloc_rx_buffers(ring, igc_desc_unused(ring));
>> +    }
>>   }
>>   /**
>> @@ -343,6 +1017,19 @@ static void igc_set_default_mac_filter(struct 
>> igc_adapter *adapter)
>>       igc_rar_set_index(adapter, 0);
>>   }
>> +/**
>> + *  igc_set_rx_mode - Secondary Unicast, Multicast and Promiscuous 
>> mode set
>> + *  @netdev: network interface device structure
>> + *
>> + *  The set_rx_mode entry point is called whenever the unicast or 
>> multicast
>> + *  address lists or the network interface flags are updated.  This 
>> routine is
>> + *  responsible for configuring the hardware for proper unicast, 
>> multicast,
>> + *  promiscuous mode, and all-multi behavior.
>> + **/
>> +static void igc_set_rx_mode(struct net_device *netdev)
>> +{
>> +}
>> +
>>   static irqreturn_t igc_msix_other(int irq, void *data)
>>   {
>>       struct igc_adapter *adapter = data;
>> @@ -781,6 +1468,83 @@ static void igc_update_itr(struct igc_q_vector 
>> *q_vector,
>>       ring_container->itr = itrval;
>>   }
>> +/**
>> + *  igc_intr_msi - Interrupt Handler
>> + *  @irq: interrupt number
>> + *  @data: pointer to a network interface device structure
>> + **/
>> +static irqreturn_t igc_intr_msi(int irq, void *data)
>> +{
>> +    struct igc_adapter *adapter = data;
>> +    struct igc_q_vector *q_vector = adapter->q_vector[0];
>> +    struct e1000_hw *hw = &adapter->hw;
>> +    /* read ICR disables interrupts using IAM */
>> +    u32 icr = rd32(E1000_ICR);
>> +
>> +    igc_write_itr(q_vector);
>> +
>> +    if (icr & E1000_ICR_DRSTA)
>> +        schedule_work(&adapter->reset_task);
> 
> This task probably should have been set up in a previous patch, too.
> 
>> +
>> +    if (icr & E1000_ICR_DOUTSYNC) {
>> +        /* HW is reporting DMA is out of sync */
>> +        adapter->stats.doosync++;
>> +    }
>> +
>> +    if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
>> +        hw->mac.get_link_status = 1;
>> +        if (!test_bit(__IGC_DOWN, &adapter->state))
>> +            mod_timer(&adapter->watchdog_timer, jiffies + 1);
> 
> And this too.
> 
>> +    }
>> +
>> +     napi_schedule(&q_vector->napi);
> 
> Extra space indented?
> 
fix will be applied in v4.
>> +
>> +    return IRQ_HANDLED;
>> +}
>> +
>> +/**
>> + *  igc_intr - Legacy Interrupt Handler
>> + *  @irq: interrupt number
>> + *  @data: pointer to a network interface device structure
>> + **/
>> +static irqreturn_t igc_intr(int irq, void *data)
>> +{
>> +    struct igc_adapter *adapter = data;
>> +    struct igc_q_vector *q_vector = adapter->q_vector[0];
>> +    struct e1000_hw *hw = &adapter->hw;
>> +    /* Interrupt Auto-Mask...upon reading ICR, interrupts are 
>> masked.  No
>> +     * need for the IMC write
>> +     */
>> +    u32 icr = rd32(E1000_ICR);
>> +
>> +    /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is
>> +     * not set, then the adapter didn't send an interrupt
>> +     */
>> +    if (!(icr & E1000_ICR_INT_ASSERTED))
>> +        return IRQ_NONE;
>> +
>> +    igc_write_itr(q_vector);
>> +
>> +    if (icr & E1000_ICR_DRSTA)
>> +        schedule_work(&adapter->reset_task);
>> +
>> +    if (icr & E1000_ICR_DOUTSYNC) {
>> +        /* HW is reporting DMA is out of sync */
>> +        adapter->stats.doosync++;
>> +    }
>> +
>> +    if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
>> +        hw->mac.get_link_status = 1;
>> +        /* guard against interrupt when we're going down */
>> +        if (!test_bit(__IGC_DOWN, &adapter->state))
>> +            mod_timer(&adapter->watchdog_timer, jiffies + 1);
>> +    }
>> +
>> +    napi_schedule(&q_vector->napi);
>> +
>> +    return IRQ_HANDLED;
>> +}
>> +
>>   static void igc_ring_irq_enable(struct igc_q_vector *q_vector)
>>   {
>>       struct igc_adapter *adapter = q_vector->adapter;
>> @@ -1148,6 +1912,29 @@ static int igc_alloc_q_vectors(struct 
>> igc_adapter *adapter)
>>   }
>>   /**
>> + *  igc_cache_ring_register - Descriptor ring to register mapping
>> + *  @adapter: board private structure to initialize
>> + *
>> + *  Once we know the feature-set enabled for the device, we'll cache
>> + *  the register offset the descriptor ring is assigned to.
>> + **/
>> +static void igc_cache_ring_register(struct igc_adapter *adapter)
>> +{
>> +    int i = 0, j = 0;
>> +
>> +    switch (adapter->hw.mac.type) {
>> +    case e1000_i225:
>> +    /* Fall through */
>> +    default:
>> +        for (; i < adapter->num_rx_queues; i++)
>> +            adapter->rx_ring[i]->reg_idx = i;
>> +        for (; j < adapter->num_tx_queues; j++)
>> +            adapter->tx_ring[j]->reg_idx = j;
>> +        break;
>> +    }
>> +}
>> +
>> +/**
>>    *  igc_init_interrupt_scheme - initialize interrupts, allocate 
>> queues/vectors
>>    *  @adapter: Pointer to adapter structure
>>    *
>> @@ -1166,7 +1953,7 @@ static int igc_init_interrupt_scheme(struct 
>> igc_adapter *adapter, bool msix)
>>           goto err_alloc_q_vectors;
>>       }
>> -    /* TODO complete igc_cache_ring_register */
>> +    igc_cache_ring_register(adapter);
>>       return 0;
>> @@ -1255,6 +2042,8 @@ static void igc_irq_enable(struct igc_adapter 
>> *adapter)
>>    **/
>>   static int igc_request_irq(struct igc_adapter *adapter)
>>   {
>> +    struct net_device *netdev = adapter->netdev;
>> +    struct pci_dev *pdev = adapter->pdev;
>>       int err = 0;
>>       if (adapter->flags & IGC_FLAG_HAS_MSIX) {
>> @@ -1262,16 +2051,38 @@ static int igc_request_irq(struct igc_adapter 
>> *adapter)
>>           if (!err)
>>               goto request_done;
>>           /* fall back to MSI */
>> -        /* TODO complete free tx/rx resources */
>> +        igc_free_all_tx_resources(adapter);
>> +        igc_free_all_rx_resources(adapter);
>>           igc_clear_interrupt_scheme(adapter);
>>           err = igc_init_interrupt_scheme(adapter, false);
>>           if (err)
>>               goto request_done;
>> -        /* TODO complete setup tx/rx resources */
>> +        igc_setup_all_tx_resources(adapter);
>> +        igc_setup_all_rx_resources(adapter);
>>           igc_configure(adapter);
>>       }
>> +    igc_assign_vector(adapter->q_vector[0], 0);
>> +
>> +    if (adapter->flags & IGC_FLAG_HAS_MSI) {
>> +        err = request_irq(pdev->irq, &igc_intr_msi, 0,
>> +                  netdev->name, adapter);
>> +        if (!err)
>> +            goto request_done;
>> +
>> +        /* fall back to legacy interrupts */
>> +        igc_reset_interrupt_capability(adapter);
>> +        adapter->flags &= ~IGC_FLAG_HAS_MSI;
>> +    }
>> +
>> +    err = request_irq(pdev->irq, &igc_intr, IRQF_SHARED,
>> +              netdev->name, adapter);
>> +
>> +    if (err)
>> +        dev_err(&pdev->dev, "Error %d getting interrupt\n",
>> +            err);
>> +
>>   request_done:
>>       return err;
>>   }
>> @@ -1332,6 +2143,16 @@ static int __igc_open(struct net_device 
>> *netdev, bool resuming)
>>       netif_carrier_off(netdev);
>> +    /* allocate transmit descriptors */
>> +    err = igc_setup_all_tx_resources(adapter);
>> +    if (err)
>> +        goto err_setup_tx;
>> +
>> +    /* allocate receive descriptors */
>> +    err = igc_setup_all_rx_resources(adapter);
>> +    if (err)
>> +        goto err_setup_rx;
>> +
>>       igc_power_up_link(adapter);
>>       igc_configure(adapter);
>> @@ -1357,6 +2178,8 @@ static int __igc_open(struct net_device *netdev, 
>> bool resuming)
>>       rd32(E1000_ICR);
>>       igc_irq_enable(adapter);
>> +    netif_tx_start_all_queues(netdev);
>> +
>>       /* start the watchdog. */
>>       hw->mac.get_link_status = 1;
>>       schedule_work(&adapter->watchdog_task);
>> @@ -1368,7 +2191,11 @@ static int __igc_open(struct net_device 
>> *netdev, bool resuming)
>>   err_req_irq:
>>       igc_release_hw_control(adapter);
>>       igc_power_down_link(adapter);
>> -    /* TODO complete free_all_rx_resources */
>> +    igc_free_all_rx_resources(adapter);
>> +err_setup_rx:
>> +    igc_free_all_tx_resources(adapter);
>> +err_setup_tx:
>> +    igc_reset(adapter);
>>       return err;
>>   }
>> @@ -1401,6 +2228,9 @@ static int __igc_close(struct net_device 
>> *netdev, bool suspending)
>>       igc_free_irq(adapter);
>> +    igc_free_all_tx_resources(adapter);
>> +    igc_free_all_rx_resources(adapter);
>> +
>>       return 0;
>>   }
>> @@ -1415,6 +2245,7 @@ static const struct net_device_ops 
>> igc_netdev_ops = {
>>       .ndo_open               = igc_open,
>>       .ndo_stop               = igc_close,
>>       .ndo_start_xmit         = igc_xmit_frame,
>> +    .ndo_set_rx_mode        = igc_set_rx_mode,
>>       .ndo_set_mac_address    = igc_set_mac,
>>       .ndo_change_mtu         = igc_change_mtu,
>>       .ndo_get_stats          = igc_get_stats,
>>
> 
> _______________________________________________
> Intel-wired-lan mailing list
> Intel-wired-lan@osuosl.org
> https://lists.osuosl.org/mailman/listinfo/intel-wired-lan
Thanks for your comments. I address part (10, ten) of them
diff mbox series

Patch

diff --git a/drivers/net/ethernet/intel/igc/Makefile b/drivers/net/ethernet/intel/igc/Makefile
index 4563b83cd4e0..6a757ac8492d 100644
--- a/drivers/net/ethernet/intel/igc/Makefile
+++ b/drivers/net/ethernet/intel/igc/Makefile
@@ -7,4 +7,5 @@ 
 
 obj-$(CONFIG_IGC) += igc.o
 
-igc-objs := igc_main.o e1000_mac.o
+igc-objs := igc_main.o e1000_mac.o \
+e1000_base.o
diff --git a/drivers/net/ethernet/intel/igc/e1000_base.c b/drivers/net/ethernet/intel/igc/e1000_base.c
new file mode 100644
index 000000000000..265ec98000e7
--- /dev/null
+++ b/drivers/net/ethernet/intel/igc/e1000_base.c
@@ -0,0 +1,83 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c)  2018 Intel Corporation */
+
+#include <linux/delay.h>
+
+#include "e1000_hw.h"
+#include "e1000_i225.h"
+
+/**
+ *  igc_rx_fifo_flush_base - Clean rx fifo after Rx enable
+ *  @hw: pointer to the HW structure
+ *
+ *  After Rx enable, if manageability is enabled then there is likely some
+ *  bad data at the start of the fifo and possibly in the DMA fifo.  This
+ *  function clears the fifos and flushes any packets that came in as rx was
+ *  being enabled.
+ **/
+void igc_rx_fifo_flush_base(struct e1000_hw *hw)
+{
+	u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled;
+	int i, ms_wait;
+
+	/* disable IPv6 options as per hardware errata */
+	rfctl = rd32(E1000_RFCTL);
+	rfctl |= E1000_RFCTL_IPV6_EX_DIS;
+	wr32(E1000_RFCTL, rfctl);
+
+	if (!(rd32(E1000_MANC) & E1000_MANC_RCV_TCO_EN))
+		return;
+
+	/* Disable all Rx queues */
+	for (i = 0; i < 4; i++) {
+		rxdctl[i] = rd32(E1000_RXDCTL(i));
+		wr32(E1000_RXDCTL(i),
+		     rxdctl[i] & ~E1000_RXDCTL_QUEUE_ENABLE);
+	}
+	/* Poll all queues to verify they have shut down */
+	for (ms_wait = 0; ms_wait < 10; ms_wait++) {
+		usleep_range(1000, 2000);
+		rx_enabled = 0;
+		for (i = 0; i < 4; i++)
+			rx_enabled |= rd32(E1000_RXDCTL(i));
+		if (!(rx_enabled & E1000_RXDCTL_QUEUE_ENABLE))
+			break;
+	}
+
+	if (ms_wait == 10)
+		pr_debug("Queue disable timed out after 10ms\n");
+
+	/* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all
+	 * incoming packets are rejected.  Set enable and wait 2ms so that
+	 * any packet that was coming in as RCTL.EN was set is flushed
+	 */
+	wr32(E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF);
+
+	rlpml = rd32(E1000_RLPML);
+	wr32(E1000_RLPML, 0);
+
+	rctl = rd32(E1000_RCTL);
+	temp_rctl = rctl & ~(E1000_RCTL_EN | E1000_RCTL_SBP);
+	temp_rctl |= E1000_RCTL_LPE;
+
+	wr32(E1000_RCTL, temp_rctl);
+	wr32(E1000_RCTL, temp_rctl | E1000_RCTL_EN);
+	wrfl();
+	usleep_range(2000, 3000);
+
+	/* Enable Rx queues that were previously enabled and restore our
+	 * previous state
+	 */
+	for (i = 0; i < 4; i++)
+		wr32(E1000_RXDCTL(i), rxdctl[i]);
+	wr32(E1000_RCTL, rctl);
+	wrfl();
+
+	wr32(E1000_RLPML, rlpml);
+	wr32(E1000_RFCTL, rfctl);
+
+	/* Flush receive errors generated by workaround */
+	rd32(E1000_ROC);
+	rd32(E1000_RNBC);
+	rd32(E1000_MPC);
+}
diff --git a/drivers/net/ethernet/intel/igc/e1000_base.h b/drivers/net/ethernet/intel/igc/e1000_base.h
new file mode 100644
index 000000000000..9acc41d73f4f
--- /dev/null
+++ b/drivers/net/ethernet/intel/igc/e1000_base.h
@@ -0,0 +1,89 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c)  2018 Intel Corporation */
+
+#ifndef _E1000_BASE_H
+#define _E1000_BASE_H
+
+/* forward declaration */
+void igc_rx_fifo_flush_base(struct e1000_hw *hw);
+
+/* Transmit Descriptor - Advanced */
+union e1000_adv_tx_desc {
+	struct {
+		__le64 buffer_addr;    /* Address of descriptor's data buf */
+		__le32 cmd_type_len;
+	__le32 olinfo_status;
+	} read;
+	struct {
+		__le64 rsvd;       /* Reserved */
+		__le32 nxtseq_seed;
+		__le32 status;
+	} wb;
+};
+
+struct e1000_adv_data_desc {
+	__le64 buffer_addr;    /* Address of the descriptor's data buffer */
+	union {
+		u32 data;
+		struct {
+			u32 datalen:16; /* Data buffer length */
+			u32 rsvd:4;
+			u32 dtyp:4;  /* Descriptor type */
+			u32 dcmd:8;  /* Descriptor command */
+		} config;
+	} lower;
+	union {
+		u32 data;
+		struct {
+			u32 status:4;  /* Descriptor status */
+			u32 idx:4;
+			u32 popts:6;  /* Packet Options */
+			u32 paylen:18; /* Payload length */
+		} options;
+	} upper;
+};
+
+/* Receive Descriptor - Advanced */
+union e1000_adv_rx_desc {
+	struct {
+		__le64 pkt_addr; /* Packet buffer address */
+		__le64 hdr_addr; /* Header buffer address */
+	} read;
+	struct {
+		struct {
+			union {
+				__le32 data;
+				struct {
+					__le16 pkt_info; /*RSS type, Pkt type*/
+					/* Split Header, header buffer len */
+					__le16 hdr_info;
+				} hs_rss;
+			} lo_dword;
+			union {
+				__le32 rss; /* RSS Hash */
+				struct {
+					__le16 ip_id; /* IP id */
+					__le16 csum; /* Packet Checksum */
+				} csum_ip;
+			} hi_dword;
+		} lower;
+		struct {
+			__le32 status_error; /* ext status/error */
+			__le16 length; /* Packet length */
+			__le16 vlan; /* VLAN tag */
+		} upper;
+	} wb;  /* writeback */
+};
+
+/* Additional Transmit Descriptor Control definitions */
+#define E1000_TXDCTL_QUEUE_ENABLE	0x02000000 /* Ena specific Tx Queue */
+
+/* Additional Receive Descriptor Control definitions */
+#define E1000_RXDCTL_QUEUE_ENABLE	0x02000000 /* Ena specific Rx Queue */
+
+/* SRRCTL bit definitions */
+#define E1000_SRRCTL_BSIZEPKT_SHIFT		10 /* Shift _right_ */
+#define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT		2  /* Shift _left_ */
+#define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF	0x02000000
+
+#endif /* _E1000_BASE_H */
diff --git a/drivers/net/ethernet/intel/igc/e1000_defines.h b/drivers/net/ethernet/intel/igc/e1000_defines.h
index 1f8bc16c7029..66f8fc96dfb8 100644
--- a/drivers/net/ethernet/intel/igc/e1000_defines.h
+++ b/drivers/net/ethernet/intel/igc/e1000_defines.h
@@ -71,6 +71,10 @@ 
 #define E1000_ICR_RXO		0x00000040 /* Rx overrun */
 #define E1000_ICR_RXT0		0x00000080 /* Rx timer intr (ring 0) */
 #define E1000_ICR_DRSTA		0x40000000 /* Device Reset Asserted */
+
+/* If this bit asserted, the driver should claim the interrupt */
+#define E1000_ICR_INT_ASSERTED	0x80000000
+
 #define E1000_ICS_RXT0		E1000_ICR_RXT0      /* Rx timer intr */
 
 #define IMS_ENABLE_MASK ( \
@@ -97,4 +101,53 @@ 
 #define E1000_GPIE_EIAME	0x40000000
 #define E1000_GPIE_PBA		0x80000000
 
+/* Transmit Control */
+#define E1000_TCTL_EN		0x00000002 /* enable Tx */
+#define E1000_TCTL_PSP		0x00000008 /* pad short packets */
+#define E1000_TCTL_CT		0x00000ff0 /* collision threshold */
+#define E1000_TCTL_COLD		0x003ff000 /* collision distance */
+#define E1000_TCTL_RTLC		0x01000000 /* Re-transmit on late collision */
+#define E1000_TCTL_MULR		0x10000000 /* Multiple request support */
+
+#define E1000_CT_SHIFT			4
+#define E1000_COLLISION_THRESHOLD	15
+
+/* Management Control */
+#define E1000_MANC_RCV_TCO_EN	0x00020000 /* Receive TCO Packets Enabled */
+
+/* Receive Control */
+#define E1000_RCTL_RST		0x00000001 /* Software reset */
+#define E1000_RCTL_EN		0x00000002 /* enable */
+#define E1000_RCTL_SBP		0x00000004 /* store bad packet */
+#define E1000_RCTL_UPE		0x00000008 /* unicast promisc enable */
+#define E1000_RCTL_MPE		0x00000010 /* multicast promisc enable */
+#define E1000_RCTL_LPE		0x00000020 /* long packet enable */
+#define E1000_RCTL_LBM_NO	0x00000000 /* no loopback mode */
+#define E1000_RCTL_LBM_MAC	0x00000040 /* MAC loopback mode */
+#define E1000_RCTL_LBM_TCVR	0x000000C0 /* tcvr loopback mode */
+#define E1000_RCTL_DTYP_PS	0x00000400 /* Packet Split descriptor */
+
+#define E1000_RCTL_RDMTS_HALF	0x00000000 /* Rx desc min thresh size */
+#define E1000_RCTL_BAM		0x00008000 /* broadcast enable */
+
+/* Header split receive */
+#define E1000_RFCTL_IPV6_EX_DIS	0x00010000
+#define E1000_RFCTL_LEF		0x00040000
+
+/* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */
+#define E1000_RCTL_SZ_2048	0x00000000 /* Rx buffer size 2048 */
+#define E1000_RCTL_SZ_1024	0x00010000 /* Rx buffer size 1024 */
+#define E1000_RCTL_SZ_512	0x00020000 /* Rx buffer size 512 */
+#define E1000_RCTL_SZ_256	0x00030000 /* Rx buffer size 256 */
+/* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */
+#define E1000_RCTL_SZ_16384	0x00010000 /* Rx buffer size 16384 */
+#define E1000_RCTL_SZ_8192	0x00020000 /* Rx buffer size 8192 */
+#define E1000_RCTL_SZ_4096	0x00030000 /* Rx buffer size 4096 */
+
+#define E1000_RCTL_MO_SHIFT	12 /* multicast offset shift */
+#define E1000_RCTL_CFIEN	0x00080000 /* canonical form enable */
+#define E1000_RCTL_DPF		0x00400000 /* discard pause frames */
+#define E1000_RCTL_PMCF		0x00800000 /* pass MAC control frames */
+#define E1000_RCTL_SECRC	0x04000000 /* Strip Ethernet CRC */
+
 #endif /* _E1000_DEFINES_H_ */
diff --git a/drivers/net/ethernet/intel/igc/e1000_hw.h b/drivers/net/ethernet/intel/igc/e1000_hw.h
index 650c4ac981d9..67fa4f696b98 100644
--- a/drivers/net/ethernet/intel/igc/e1000_hw.h
+++ b/drivers/net/ethernet/intel/igc/e1000_hw.h
@@ -10,6 +10,7 @@ 
 #include "e1000_defines.h"
 #include "e1000_mac.h"
 #include "e1000_i225.h"
+#include "e1000_base.h"
 
 #define E1000_DEV_ID_I225_LM			0x15F2
 #define E1000_DEV_ID_I225_V			0x15F3
diff --git a/drivers/net/ethernet/intel/igc/e1000_regs.h b/drivers/net/ethernet/intel/igc/e1000_regs.h
index 5634a01afff3..dcc4d89c9933 100644
--- a/drivers/net/ethernet/intel/igc/e1000_regs.h
+++ b/drivers/net/ethernet/intel/igc/e1000_regs.h
@@ -229,6 +229,9 @@ 
 #define E1000_TLPIC	0x4148 /* EEE Tx LPI Count - TLPIC */
 #define E1000_RLPIC	0x414C /* EEE Rx LPI Count - RLPIC */
 
+/* Management registers */
+#define E1000_MANC	0x05820  /* Management Control - RW */
+
 /* forward declaration */
 struct e1000_hw;
 u32 igc_rd32(struct e1000_hw *hw, u32 reg);
diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
index 7cab3e9c8e91..abf2e302c417 100644
--- a/drivers/net/ethernet/intel/igc/igc.h
+++ b/drivers/net/ethernet/intel/igc/igc.h
@@ -46,6 +46,47 @@  extern char igc_driver_version[];
 #define MAX_Q_VECTORS                     10
 #define MAX_STD_JUMBO_FRAME_SIZE        9216
 
+#define IGC_TX_PTHRESH			8
+#define IGC_TX_HTHRESH			1
+
+/* Supported Rx Buffer Sizes */
+#define IGC_RXBUFFER_256		256
+#define IGC_RXBUFFER_2048		2048
+#define IGC_RXBUFFER_3072		3072
+
+#define IGC_RX_HDR_LEN			IGC_RXBUFFER_256
+
+/* RX and TX descriptor control thresholds.
+ * PTHRESH - MAC will consider prefetch if it has fewer than this number of
+ *           descriptors available in its onboard memory.
+ *           Setting this to 0 disables RX descriptor prefetch.
+ * HTHRESH - MAC will only prefetch if there are at least this many descriptors
+ *           available in host memory.
+ *           If PTHRESH is 0, this should also be 0.
+ * WTHRESH - RX descriptor writeback threshold - MAC will delay writing back
+ *           descriptors until either it has this many to write back, or the
+ *           ITR timer expires.
+ */
+#define IGC_RX_PTHRESH			8
+#define IGC_RX_HTHRESH			8
+#define IGC_TX_PTHRESH			8
+#define IGC_TX_HTHRESH			1
+#define IGC_RX_WTHRESH			4
+
+#define IGC_RX_DMA_ATTR \
+	(DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING)
+
+#define IGC_TS_HDR_LEN			16
+
+#define IGC_SKB_PAD			(NET_SKB_PAD + NET_IP_ALIGN)
+
+#if (PAGE_SIZE < 8192)
+#define IGC_MAX_FRAME_BUILD_SKB \
+	(SKB_WITH_OVERHEAD(IGC_RXBUFFER_2048) - IGC_SKB_PAD - IGC_TS_HDR_LEN)
+#else
+#define IGC_MAX_FRAME_BUILD_SKB (IGC_RXBUFFER_2048 - IGC_TS_HDR_LEN)
+#endif
+
 enum e1000_state_t {
 	 __IGC_TESTING,
 	__IGC_RESETTING,
@@ -53,6 +94,33 @@  enum e1000_state_t {
 	 __IGC_PTP_TX_IN_PROGRESS,
 };
 
+/** wrapper around a pointer to a socket buffer,
+ *  so a DMA handle can be stored along with the buffer
+ **/
+struct igc_tx_buffer {
+	union e1000_adv_tx_desc *next_to_watch;
+	unsigned long time_stamp;
+	struct sk_buff *skb;
+	unsigned int bytecount;
+	u16 gso_segs;
+	__be16 protocol;
+
+	DEFINE_DMA_UNMAP_ADDR(dma);
+	DEFINE_DMA_UNMAP_LEN(len);
+	u32 tx_flags;
+};
+
+struct igc_rx_buffer {
+	dma_addr_t dma;
+	struct page *page;
+#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)
+	__u32 page_offset;
+#else
+	__u16 page_offset;
+#endif
+	__u16 pagecnt_bias;
+};
+
 struct igc_tx_queue_stats {
 	u64 packets;
 	u64 bytes;
@@ -218,4 +286,63 @@  struct igc_adapter {
 	struct igc_mac_addr *mac_table;
 };
 
+/* igc_desc_unused - calculate if we have unused descriptors */
+static inline u16 igc_desc_unused(const struct igc_ring *ring)
+{
+	u16 ntc = ring->next_to_clean;
+	u16 ntu = ring->next_to_use;
+
+	return ((ntc > ntu) ? 0 : ring->count) + ntc - ntu - 1;
+}
+
+static inline struct netdev_queue *txring_txq(const struct igc_ring *tx_ring)
+{
+	return netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index);
+}
+
+enum e1000_ring_flags_t {
+	IGC_RING_FLAG_RX_3K_BUFFER,
+	IGC_RING_FLAG_RX_BUILD_SKB_ENABLED,
+	IGC_RING_FLAG_RX_SCTP_CSUM,
+	IGC_RING_FLAG_RX_LB_VLAN_BSWAP,
+	IGC_RING_FLAG_TX_CTX_IDX,
+	IGC_RING_FLAG_TX_DETECT_HANG
+};
+
+#define ring_uses_large_buffer(ring) \
+	test_bit(IGC_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
+
+#define ring_uses_build_skb(ring) \
+	test_bit(IGC_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
+
+static inline unsigned int igc_rx_bufsz(struct igc_ring *ring)
+{
+#if (PAGE_SIZE < 8192)
+	if (ring_uses_large_buffer(ring))
+		return IGC_RXBUFFER_3072;
+
+	if (ring_uses_build_skb(ring))
+		return IGC_MAX_FRAME_BUILD_SKB + IGC_TS_HDR_LEN;
+#endif
+	return IGC_RXBUFFER_2048;
+}
+
+static inline unsigned int igc_rx_pg_order(struct igc_ring *ring)
+{
+#if (PAGE_SIZE < 8192)
+	if (ring_uses_large_buffer(ring))
+		return 1;
+#endif
+	return 0;
+}
+
+#define igc_rx_pg_size(_ring) (PAGE_SIZE << igc_rx_pg_order(_ring))
+
+#define IGC_RX_DESC(R, i)       \
+	(&(((union e1000_adv_rx_desc *)((R)->desc))[i]))
+#define IGC_TX_DESC(R, i)       \
+	(&(((union e1000_adv_tx_desc *)((R)->desc))[i]))
+#define IGC_TX_CTXTDESC(R, i)   \
+	(&(((struct e1000_adv_tx_context_desc *)((R)->desc))[i]))
+
 #endif /* _IGC_H_ */
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 30b778c9b94b..a147a1b7585e 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -29,11 +29,21 @@  static const struct pci_device_id igc_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, igc_pci_tbl);
 
 /* forward declaration */
+static int igc_setup_all_tx_resources(struct igc_adapter *adapter);
+static void igc_clean_tx_ring(struct igc_ring *tx_ring);
+static void igc_free_all_tx_resources(struct igc_adapter *adapter);
+static int igc_setup_all_rx_resources(struct igc_adapter *adapter);
 static int igc_sw_init(struct igc_adapter *);
 static void igc_configure(struct igc_adapter *adapter);
+static void igc_configure_tx(struct igc_adapter *);
+static void igc_configure_rx(struct igc_adapter *adapter);
 static void igc_power_down_link(struct igc_adapter *adapter);
 static void igc_set_default_mac_filter(struct igc_adapter *adapter);
+static void igc_set_rx_mode(struct net_device *netdev);
+static void igc_setup_mrqc(struct igc_adapter *adapter);
 static irqreturn_t igc_msix_ring(int irq, void *data);
+static irqreturn_t igc_intr_msi(int irq, void *data);
+static irqreturn_t igc_intr(int irq, void *data);
 static void igc_write_itr(struct igc_q_vector *q_vector);
 static int igc_request_msix(struct igc_adapter *adapter);
 static void igc_assign_vector(struct igc_q_vector *q_vector, int msix_vector);
@@ -125,6 +135,526 @@  static void igc_get_hw_control(struct igc_adapter *adapter)
 }
 
 /**
+ *  igc_free_tx_resources - Free Tx Resources per Queue
+ *  @tx_ring: Tx descriptor ring for a specific queue
+ *
+ *  Free all transmit software resources
+ **/
+void igc_free_tx_resources(struct igc_ring *tx_ring)
+{
+	igc_clean_tx_ring(tx_ring);
+
+	vfree(tx_ring->tx_buffer_info);
+	tx_ring->tx_buffer_info = NULL;
+
+	/* if not set, then don't free */
+	if (!tx_ring->desc)
+		return;
+
+	dma_free_coherent(tx_ring->dev, tx_ring->size,
+			  tx_ring->desc, tx_ring->dma);
+
+	tx_ring->desc = NULL;
+}
+
+/**
+ *  igc_free_all_tx_resources - Free Tx Resources for All Queues
+ *  @adapter: board private structure
+ *
+ *  Free all transmit software resources
+ **/
+static void igc_free_all_tx_resources(struct igc_adapter *adapter)
+{
+	int i;
+
+	for (i = 0; i < adapter->num_tx_queues; i++)
+		igc_free_tx_resources(adapter->tx_ring[i]);
+}
+
+void igc_unmap_and_free_tx_resource(struct igc_ring *ring,
+				    struct igc_tx_buffer *tx_buffer)
+{
+	if (tx_buffer->skb) {
+		dev_kfree_skb_any(tx_buffer->skb);
+		if (dma_unmap_len(tx_buffer, len))
+			dma_unmap_single(ring->dev,
+					 dma_unmap_addr(tx_buffer, dma),
+					 dma_unmap_len(tx_buffer, len),
+					 DMA_TO_DEVICE);
+	} else if (dma_unmap_len(tx_buffer, len)) {
+		dma_unmap_page(ring->dev,
+			       dma_unmap_addr(tx_buffer, dma),
+			       dma_unmap_len(tx_buffer, len),
+			       DMA_TO_DEVICE);
+	}
+	tx_buffer->next_to_watch = NULL;
+	tx_buffer->skb = NULL;
+	dma_unmap_len_set(tx_buffer, len, 0);
+	/* buffer_info must be completely set up in the transmit path */
+}
+
+/**
+ *  igc_clean_tx_ring - Free Tx Buffers
+ *  @tx_ring: ring to be cleaned
+ **/
+static void igc_clean_tx_ring(struct igc_ring *tx_ring)
+{
+	struct igc_tx_buffer *buffer_info;
+	unsigned long size;
+	u16 i;
+
+	if (!tx_ring->tx_buffer_info)
+		return;
+
+	/* Free all the Tx ring sk_buffs */
+	for (i = 0; i < tx_ring->count; i++) {
+		buffer_info = &tx_ring->tx_buffer_info[i];
+		igc_unmap_and_free_tx_resource(tx_ring, buffer_info);
+	}
+
+	netdev_tx_reset_queue(txring_txq(tx_ring));
+
+	size = sizeof(struct igc_tx_buffer) * tx_ring->count;
+	memset(tx_ring->tx_buffer_info, 0, size);
+
+	/* Zero out the descriptor ring */
+	memset(tx_ring->desc, 0, tx_ring->size);
+
+	tx_ring->next_to_use = 0;
+	tx_ring->next_to_clean = 0;
+}
+
+/**
+ *  igc_setup_tx_resources - allocate Tx resources (Descriptors)
+ *  @tx_ring: tx descriptor ring (for a specific queue) to setup
+ *
+ *  Return 0 on success, negative on failure
+ **/
+int igc_setup_tx_resources(struct igc_ring *tx_ring)
+{
+	struct device *dev = tx_ring->dev;
+	int size = 0;
+
+	size = sizeof(struct igc_tx_buffer) * tx_ring->count;
+	tx_ring->tx_buffer_info = vzalloc(size);
+	if (!tx_ring->tx_buffer_info)
+		goto err;
+
+	/* round up to nearest 4K */
+	tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc);
+	tx_ring->size = ALIGN(tx_ring->size, 4096);
+
+	tx_ring->desc = dma_alloc_coherent(dev, tx_ring->size,
+					   &tx_ring->dma, GFP_KERNEL);
+
+	if (!tx_ring->desc)
+		goto err;
+
+	tx_ring->next_to_use = 0;
+	tx_ring->next_to_clean = 0;
+
+	return 0;
+
+err:
+	vfree(tx_ring->tx_buffer_info);
+	dev_err(dev,
+		"Unable to allocate memory for the transmit descriptor ring\n");
+	return -ENOMEM;
+}
+
+/**
+ *  igc_setup_all_tx_resources - wrapper to allocate Tx resources
+ *                                (Descriptors) for all queues
+ *  @adapter: board private structure
+ *
+ *  Return 0 on success, negative on failure
+ **/
+static int igc_setup_all_tx_resources(struct igc_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	int i, err = 0;
+
+	for (i = 0; i < adapter->num_tx_queues; i++) {
+		err = igc_setup_tx_resources(adapter->tx_ring[i]);
+		if (err) {
+			dev_err(&pdev->dev,
+				"Allocation for Tx Queue %u failed\n", i);
+			for (i--; i >= 0; i--)
+				igc_free_tx_resources(adapter->tx_ring[i]);
+			break;
+		}
+	}
+
+	return err;
+}
+
+/**
+ *  igc_clean_rx_ring - Free Rx Buffers per Queue
+ *  @rx_ring: ring to free buffers from
+ **/
+void igc_clean_rx_ring(struct igc_ring *rx_ring)
+{
+	u16 i = rx_ring->next_to_clean;
+
+	if (rx_ring->skb)
+		dev_kfree_skb(rx_ring->skb);
+	rx_ring->skb = NULL;
+
+	/* Free all the Rx ring sk_buffs */
+	while (i != rx_ring->next_to_alloc) {
+		struct igc_rx_buffer *buffer_info = &rx_ring->rx_buffer_info[i];
+
+		/* Invalidate cache lines that may have been written to by
+		 * device so that we avoid corrupting memory.
+		 */
+		dma_sync_single_range_for_cpu(rx_ring->dev,
+					      buffer_info->dma,
+					      buffer_info->page_offset,
+					      igc_rx_bufsz(rx_ring),
+					      DMA_FROM_DEVICE);
+
+		/* free resources associated with mapping */
+		dma_unmap_page_attrs(rx_ring->dev,
+				     buffer_info->dma,
+				     igc_rx_pg_size(rx_ring),
+				     DMA_FROM_DEVICE,
+				     IGC_RX_DMA_ATTR);
+		__page_frag_cache_drain(buffer_info->page,
+					buffer_info->pagecnt_bias);
+
+		i++;
+		if (i == rx_ring->count)
+			i = 0;
+	}
+
+	rx_ring->next_to_alloc = 0;
+	rx_ring->next_to_clean = 0;
+	rx_ring->next_to_use = 0;
+}
+
+/**
+ *  igc_free_rx_resources - Free Rx Resources
+ *  @rx_ring: ring to clean the resources from
+ *
+ *  Free all receive software resources
+ **/
+void igc_free_rx_resources(struct igc_ring *rx_ring)
+{
+	igc_clean_rx_ring(rx_ring);
+
+	vfree(rx_ring->rx_buffer_info);
+	rx_ring->rx_buffer_info = NULL;
+
+	/* if not set, then don't free */
+	if (!rx_ring->desc)
+		return;
+
+	dma_free_coherent(rx_ring->dev, rx_ring->size,
+			  rx_ring->desc, rx_ring->dma);
+
+	rx_ring->desc = NULL;
+}
+
+/**
+ *  igc_free_all_rx_resources - Free Rx Resources for All Queues
+ *  @adapter: board private structure
+ *
+ *  Free all receive software resources
+ **/
+static void igc_free_all_rx_resources(struct igc_adapter *adapter)
+{
+	int i;
+
+	for (i = 0; i < adapter->num_rx_queues; i++)
+		igc_free_rx_resources(adapter->rx_ring[i]);
+}
+
+/**
+ *  igc_setup_rx_resources - allocate Rx resources (Descriptors)
+ *  @rx_ring:    rx descriptor ring (for a specific queue) to setup
+ *
+ *  Returns 0 on success, negative on failure
+ **/
+int igc_setup_rx_resources(struct igc_ring *rx_ring)
+{
+	struct device *dev = rx_ring->dev;
+	int size, desc_len;
+
+	size = sizeof(struct igc_rx_buffer) * rx_ring->count;
+	rx_ring->rx_buffer_info = vzalloc(size);
+	if (!rx_ring->rx_buffer_info)
+		goto err;
+
+	desc_len = sizeof(union e1000_adv_rx_desc);
+
+	/* Round up to nearest 4K */
+	rx_ring->size = rx_ring->count * desc_len;
+	rx_ring->size = ALIGN(rx_ring->size, 4096);
+
+	rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size,
+					   &rx_ring->dma, GFP_KERNEL);
+
+	if (!rx_ring->desc)
+		goto err;
+
+	rx_ring->next_to_alloc = 0;
+	rx_ring->next_to_clean = 0;
+	rx_ring->next_to_use = 0;
+
+	return 0;
+
+err:
+	vfree(rx_ring->rx_buffer_info);
+	rx_ring->rx_buffer_info = NULL;
+	dev_err(dev,
+		"Unable to allocate memory for the receive descriptor ring\n");
+	return -ENOMEM;
+}
+
+/**
+ *  igc_setup_all_rx_resources - wrapper to allocate Rx resources
+ *                                (Descriptors) for all queues
+ *  @adapter: board private structure
+ *
+ *  Return 0 on success, negative on failure
+ **/
+static int igc_setup_all_rx_resources(struct igc_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	int i, err = 0;
+
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		err = igc_setup_rx_resources(adapter->rx_ring[i]);
+		if (err) {
+			dev_err(&pdev->dev,
+				"Allocation for Rx Queue %u failed\n", i);
+			for (i--; i >= 0; i--)
+				igc_free_rx_resources(adapter->rx_ring[i]);
+			break;
+		}
+	}
+
+	return err;
+}
+
+static u32 igc_tx_wthresh(struct igc_adapter *adapter)
+{
+	return 16;
+}
+
+/**
+ *  igc_configure_rx_ring - Configure a receive ring after Reset
+ *  @adapter: board private structure
+ *  @ring: receive ring to be configured
+ *
+ *  Configure the Rx unit of the MAC after a reset.
+ **/
+void igc_configure_rx_ring(struct igc_adapter *adapter,
+			   struct igc_ring *ring)
+{
+	struct e1000_hw *hw = &adapter->hw;
+	union e1000_adv_rx_desc *rx_desc;
+	u64 rdba = ring->dma;
+	int reg_idx = ring->reg_idx;
+	u32 srrctl = 0, rxdctl = 0;
+
+	/* disable the queue */
+	wr32(E1000_RXDCTL(reg_idx), 0);
+
+	/* Set DMA base address registers */
+	wr32(E1000_RDBAL(reg_idx),
+	     rdba & 0x00000000ffffffffULL);
+	wr32(E1000_RDBAH(reg_idx), rdba >> 32);
+	wr32(E1000_RDLEN(reg_idx),
+	     ring->count * sizeof(union e1000_adv_rx_desc));
+
+	/* initialize head and tail */
+	ring->tail = adapter->io_addr + E1000_RDT(reg_idx);
+	wr32(E1000_RDH(reg_idx), 0);
+	writel(0, ring->tail);
+
+	/* reset next-to- use/clean to place SW in sync with hardwdare */
+	ring->next_to_clean = 0;
+	ring->next_to_use = 0;
+
+	/* set descriptor configuration */
+	srrctl = IGC_RX_HDR_LEN << E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
+	if (ring_uses_large_buffer(ring))
+		srrctl |= IGC_RXBUFFER_3072 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
+	else
+		srrctl |= IGC_RXBUFFER_2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
+	srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
+
+	wr32(E1000_SRRCTL(reg_idx), srrctl);
+
+	rxdctl |= IGC_RX_PTHRESH;
+	rxdctl |= IGC_RX_HTHRESH << 8;
+	rxdctl |= IGC_RX_WTHRESH << 16;
+
+	/* initialize rx_buffer_info */
+	memset(ring->rx_buffer_info, 0,
+	       sizeof(struct igc_rx_buffer) * ring->count);
+
+	/* initialize Rx descriptor 0 */
+	rx_desc = IGC_RX_DESC(ring, 0);
+	rx_desc->wb.upper.length = 0;
+
+	/* enable receive descriptor fetching */
+	rxdctl |= E1000_RXDCTL_QUEUE_ENABLE;
+
+	wr32(E1000_RXDCTL(reg_idx), rxdctl);
+}
+
+/**
+ *  igc_configure_rx - Configure receive Unit after Reset
+ *  @adapter: board private structure
+ *
+ *  Configure the Rx unit of the MAC after a reset.
+ **/
+static void igc_configure_rx(struct igc_adapter *adapter)
+{
+	int i;
+
+	/* Setup the HW Rx Head and Tail Descriptor Pointers and
+	 * the Base and Length of the Rx Descriptor Ring
+	 */
+	for (i = 0; i < adapter->num_rx_queues; i++)
+		igc_configure_rx_ring(adapter, adapter->rx_ring[i]);
+}
+
+/**
+ *  igc_configure_tx_ring - Configure transmit ring after Reset
+ *  @adapter: board private structure
+ *  @ring: tx ring to configure
+ *
+ *  Configure a transmit ring after a reset.
+ **/
+void igc_configure_tx_ring(struct igc_adapter *adapter,
+			   struct igc_ring *ring)
+{
+	struct e1000_hw *hw = &adapter->hw;
+	u32 txdctl = 0;
+	u64 tdba = ring->dma;
+	int reg_idx = ring->reg_idx;
+
+	/* disable the queue */
+	wr32(E1000_TXDCTL(reg_idx), 0);
+	wrfl();
+	mdelay(10);
+
+	wr32(E1000_TDLEN(reg_idx),
+	     ring->count * sizeof(union e1000_adv_tx_desc));
+	wr32(E1000_TDBAL(reg_idx),
+	     tdba & 0x00000000ffffffffULL);
+	wr32(E1000_TDBAH(reg_idx), tdba >> 32);
+
+	ring->tail = adapter->io_addr + E1000_TDT(reg_idx);
+	wr32(E1000_TDH(reg_idx), 0);
+	writel(0, ring->tail);
+
+	txdctl |= IGC_TX_PTHRESH;
+	txdctl |= IGC_TX_HTHRESH << 8;
+	txdctl |= igc_tx_wthresh(adapter) << 16;
+
+	txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
+	wr32(E1000_TXDCTL(reg_idx), txdctl);
+}
+
+/**
+ *  igc_configure_tx - Configure transmit Unit after Reset
+ *  @adapter: board private structure
+ *
+ *  Configure the Tx unit of the MAC after a reset.
+ **/
+static void igc_configure_tx(struct igc_adapter *adapter)
+{
+	int i;
+
+	for (i = 0; i < adapter->num_tx_queues; i++)
+		igc_configure_tx_ring(adapter, adapter->tx_ring[i]);
+}
+
+/**
+ *  igc_setup_mrqc - configure the multiple receive queue control registers
+ *  @adapter: Board private structure
+ **/
+static void igc_setup_mrqc(struct igc_adapter *adapter)
+{
+}
+
+/**
+ *  igc_setup_rctl - configure the receive control registers
+ *  @adapter: Board private structure
+ **/
+void igc_setup_rctl(struct igc_adapter *adapter)
+{
+	struct e1000_hw *hw = &adapter->hw;
+	u32 rctl;
+
+	rctl = rd32(E1000_RCTL);
+
+	rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
+	rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
+
+	rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_RDMTS_HALF |
+		(hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT);
+
+	/* enable stripping of CRC. It's unlikely this will break BMC
+	 * redirection as it did with e1000. Newer features require
+	 * that the HW strips the CRC.
+	 */
+	rctl |= E1000_RCTL_SECRC;
+
+	/* disable store bad packets and clear size bits. */
+	rctl &= ~(E1000_RCTL_SBP | E1000_RCTL_SZ_256);
+
+	/* enable LPE to allow for reception of jumbo frames */
+	rctl |= E1000_RCTL_LPE;
+
+	/* disable queue 0 to prevent tail write w/o re-config */
+	wr32(E1000_RXDCTL(0), 0);
+
+	/* This is useful for sniffing bad packets. */
+	if (adapter->netdev->features & NETIF_F_RXALL) {
+		/* UPE and MPE will be handled by normal PROMISC logic
+		 * in e1000e_set_rx_mode
+		 */
+		rctl |= (E1000_RCTL_SBP | /* Receive bad packets */
+			 E1000_RCTL_BAM | /* RX All Bcast Pkts */
+			 E1000_RCTL_PMCF); /* RX All MAC Ctrl Pkts */
+
+		rctl &= ~(E1000_RCTL_DPF | /* Allow filtered pause */
+			  E1000_RCTL_CFIEN); /* Disable VLAN CFIEN Filter */
+	}
+
+	wr32(E1000_RCTL, rctl);
+}
+
+/**
+ *  igc_setup_tctl - configure the transmit control registers
+ *  @adapter: Board private structure
+ **/
+void igc_setup_tctl(struct igc_adapter *adapter)
+{
+	struct e1000_hw *hw = &adapter->hw;
+	u32 tctl;
+
+	/* disable queue 0 which icould be enabled by default */
+	wr32(E1000_TXDCTL(0), 0);
+
+	/* Program the Transmit Control Register */
+	tctl = rd32(E1000_TCTL);
+	tctl &= ~E1000_TCTL_CT;
+	tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC |
+		(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
+
+	/* Enable transmits */
+	tctl |= E1000_TCTL_EN;
+
+	wr32(E1000_TCTL, tctl);
+}
+
+/**
  *  igc_set_mac - Change the Ethernet Address of the NIC
  *  @netdev: network interface device structure
  *  @p: pointer to an address structure
@@ -156,6 +686,121 @@  static netdev_tx_t igc_xmit_frame(struct sk_buff *skb,
 	return NETDEV_TX_OK;
 }
 
+static inline unsigned int igc_rx_offset(struct igc_ring *rx_ring)
+{
+	return ring_uses_build_skb(rx_ring) ? IGC_SKB_PAD : 0;
+}
+
+static bool igc_alloc_mapped_page(struct igc_ring *rx_ring,
+				  struct igc_rx_buffer *bi)
+{
+	struct page *page = bi->page;
+	dma_addr_t dma;
+
+	/* since we are recycling buffers we should seldom need to alloc */
+	if (likely(page))
+		return true;
+
+	/* alloc new page for storage */
+	page = dev_alloc_pages(igc_rx_pg_order(rx_ring));
+	if (unlikely(!page)) {
+		rx_ring->rx_stats.alloc_failed++;
+		return false;
+	}
+
+	/* map page for use */
+	dma = dma_map_page_attrs(rx_ring->dev, page, 0,
+				 igc_rx_pg_size(rx_ring),
+				 DMA_FROM_DEVICE,
+				 IGC_RX_DMA_ATTR);
+
+	/* if mapping failed free memory back to system since
+	 * there isn't much point in holding memory we can't use
+	 */
+	if (dma_mapping_error(rx_ring->dev, dma)) {
+		__free_page(page);
+
+		rx_ring->rx_stats.alloc_failed++;
+		return false;
+	}
+
+	bi->dma = dma;
+	bi->page = page;
+	bi->page_offset = igc_rx_offset(rx_ring);
+	bi->pagecnt_bias = 1;
+
+	return true;
+}
+
+/**
+ *  igc_alloc_rx_buffers - Replace used receive buffers; packet split
+ *  @adapter: address of board private structure
+ **/
+void igc_alloc_rx_buffers(struct igc_ring *rx_ring, u16 cleaned_count)
+{
+	union e1000_adv_rx_desc *rx_desc;
+	struct igc_rx_buffer *bi;
+	u16 i = rx_ring->next_to_use;
+	u16 bufsz;
+
+	/* nothing to do */
+	if (!cleaned_count)
+		return;
+
+	rx_desc = IGC_RX_DESC(rx_ring, i);
+	bi = &rx_ring->rx_buffer_info[i];
+	i -= rx_ring->count;
+
+	bufsz = igc_rx_bufsz(rx_ring);
+
+	do {
+		if (!igc_alloc_mapped_page(rx_ring, bi))
+			break;
+
+		/* sync the buffer for use by the device */
+		dma_sync_single_range_for_device(rx_ring->dev, bi->dma,
+						 bi->page_offset, bufsz,
+						 DMA_FROM_DEVICE);
+
+		/* Refresh the desc even if buffer_addrs didn't change
+		 * because each write-back erases this info.
+		 */
+		rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset);
+
+		rx_desc++;
+		bi++;
+		i++;
+		if (unlikely(!i)) {
+			rx_desc = IGC_RX_DESC(rx_ring, 0);
+			bi = rx_ring->rx_buffer_info;
+			i -= rx_ring->count;
+		}
+
+		/* clear the length for the next_to_use descriptor */
+		rx_desc->wb.upper.length = 0;
+
+		cleaned_count--;
+	} while (cleaned_count);
+
+	i += rx_ring->count;
+
+	if (rx_ring->next_to_use != i) {
+		/* record the next descriptor to use */
+		rx_ring->next_to_use = i;
+
+		/* update next to alloc since we have filled the ring */
+		rx_ring->next_to_alloc = i;
+
+		/* Force memory writes to complete before letting h/w
+		 * know there are new descriptors to fetch.  (Only
+		 * applicable for weak-ordered memory model archs,
+		 * such as IA-64).
+		 */
+		wmb();
+		writel(i, rx_ring->tail);
+	}
+}
+
 /**
  *  igc_ioctl - I/O control method
  *  @netdev: network interface device structure
@@ -196,6 +841,12 @@  int igc_up(struct igc_adapter *adapter)
 	rd32(E1000_ICR);
 	igc_irq_enable(adapter);
 
+	netif_tx_start_all_queues(adapter->netdev);
+
+	/* start the watchdog. */
+	hw->mac.get_link_status = 1;
+	schedule_work(&adapter->watchdog_task);
+
 	return 0;
 }
 
@@ -295,7 +946,30 @@  static struct net_device_stats *igc_get_stats(struct net_device *netdev)
  **/
 static void igc_configure(struct igc_adapter *adapter)
 {
+	struct net_device *netdev = adapter->netdev;
+	int i = 0;
+
 	igc_get_hw_control(adapter);
+	igc_set_rx_mode(netdev);
+
+	igc_setup_tctl(adapter);
+	igc_setup_mrqc(adapter);
+	igc_setup_rctl(adapter);
+
+	igc_configure_tx(adapter);
+	igc_configure_rx(adapter);
+
+	igc_rx_fifo_flush_base(&adapter->hw);
+
+	/* call igc_desc_unused which always leaves
+	 * at least 1 descriptor unused to make sure
+	 * next_to_use != next_to_clean
+	 */
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		struct igc_ring *ring = adapter->rx_ring[i];
+
+		igc_alloc_rx_buffers(ring, igc_desc_unused(ring));
+	}
 }
 
 /**
@@ -343,6 +1017,19 @@  static void igc_set_default_mac_filter(struct igc_adapter *adapter)
 	igc_rar_set_index(adapter, 0);
 }
 
+/**
+ *  igc_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set
+ *  @netdev: network interface device structure
+ *
+ *  The set_rx_mode entry point is called whenever the unicast or multicast
+ *  address lists or the network interface flags are updated.  This routine is
+ *  responsible for configuring the hardware for proper unicast, multicast,
+ *  promiscuous mode, and all-multi behavior.
+ **/
+static void igc_set_rx_mode(struct net_device *netdev)
+{
+}
+
 static irqreturn_t igc_msix_other(int irq, void *data)
 {
 	struct igc_adapter *adapter = data;
@@ -781,6 +1468,83 @@  static void igc_update_itr(struct igc_q_vector *q_vector,
 	ring_container->itr = itrval;
 }
 
+/**
+ *  igc_intr_msi - Interrupt Handler
+ *  @irq: interrupt number
+ *  @data: pointer to a network interface device structure
+ **/
+static irqreturn_t igc_intr_msi(int irq, void *data)
+{
+	struct igc_adapter *adapter = data;
+	struct igc_q_vector *q_vector = adapter->q_vector[0];
+	struct e1000_hw *hw = &adapter->hw;
+	/* read ICR disables interrupts using IAM */
+	u32 icr = rd32(E1000_ICR);
+
+	igc_write_itr(q_vector);
+
+	if (icr & E1000_ICR_DRSTA)
+		schedule_work(&adapter->reset_task);
+
+	if (icr & E1000_ICR_DOUTSYNC) {
+		/* HW is reporting DMA is out of sync */
+		adapter->stats.doosync++;
+	}
+
+	if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
+		hw->mac.get_link_status = 1;
+		if (!test_bit(__IGC_DOWN, &adapter->state))
+			mod_timer(&adapter->watchdog_timer, jiffies + 1);
+	}
+
+	 napi_schedule(&q_vector->napi);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ *  igc_intr - Legacy Interrupt Handler
+ *  @irq: interrupt number
+ *  @data: pointer to a network interface device structure
+ **/
+static irqreturn_t igc_intr(int irq, void *data)
+{
+	struct igc_adapter *adapter = data;
+	struct igc_q_vector *q_vector = adapter->q_vector[0];
+	struct e1000_hw *hw = &adapter->hw;
+	/* Interrupt Auto-Mask...upon reading ICR, interrupts are masked.  No
+	 * need for the IMC write
+	 */
+	u32 icr = rd32(E1000_ICR);
+
+	/* IMS will not auto-mask if INT_ASSERTED is not set, and if it is
+	 * not set, then the adapter didn't send an interrupt
+	 */
+	if (!(icr & E1000_ICR_INT_ASSERTED))
+		return IRQ_NONE;
+
+	igc_write_itr(q_vector);
+
+	if (icr & E1000_ICR_DRSTA)
+		schedule_work(&adapter->reset_task);
+
+	if (icr & E1000_ICR_DOUTSYNC) {
+		/* HW is reporting DMA is out of sync */
+		adapter->stats.doosync++;
+	}
+
+	if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
+		hw->mac.get_link_status = 1;
+		/* guard against interrupt when we're going down */
+		if (!test_bit(__IGC_DOWN, &adapter->state))
+			mod_timer(&adapter->watchdog_timer, jiffies + 1);
+	}
+
+	napi_schedule(&q_vector->napi);
+
+	return IRQ_HANDLED;
+}
+
 static void igc_ring_irq_enable(struct igc_q_vector *q_vector)
 {
 	struct igc_adapter *adapter = q_vector->adapter;
@@ -1148,6 +1912,29 @@  static int igc_alloc_q_vectors(struct igc_adapter *adapter)
 }
 
 /**
+ *  igc_cache_ring_register - Descriptor ring to register mapping
+ *  @adapter: board private structure to initialize
+ *
+ *  Once we know the feature-set enabled for the device, we'll cache
+ *  the register offset the descriptor ring is assigned to.
+ **/
+static void igc_cache_ring_register(struct igc_adapter *adapter)
+{
+	int i = 0, j = 0;
+
+	switch (adapter->hw.mac.type) {
+	case e1000_i225:
+	/* Fall through */
+	default:
+		for (; i < adapter->num_rx_queues; i++)
+			adapter->rx_ring[i]->reg_idx = i;
+		for (; j < adapter->num_tx_queues; j++)
+			adapter->tx_ring[j]->reg_idx = j;
+		break;
+	}
+}
+
+/**
  *  igc_init_interrupt_scheme - initialize interrupts, allocate queues/vectors
  *  @adapter: Pointer to adapter structure
  *
@@ -1166,7 +1953,7 @@  static int igc_init_interrupt_scheme(struct igc_adapter *adapter, bool msix)
 		goto err_alloc_q_vectors;
 	}
 
-	/* TODO complete igc_cache_ring_register */
+	igc_cache_ring_register(adapter);
 
 	return 0;
 
@@ -1255,6 +2042,8 @@  static void igc_irq_enable(struct igc_adapter *adapter)
  **/
 static int igc_request_irq(struct igc_adapter *adapter)
 {
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = adapter->pdev;
 	int err = 0;
 
 	if (adapter->flags & IGC_FLAG_HAS_MSIX) {
@@ -1262,16 +2051,38 @@  static int igc_request_irq(struct igc_adapter *adapter)
 		if (!err)
 			goto request_done;
 		/* fall back to MSI */
-		/* TODO complete free tx/rx resources */
+		igc_free_all_tx_resources(adapter);
+		igc_free_all_rx_resources(adapter);
 
 		igc_clear_interrupt_scheme(adapter);
 		err = igc_init_interrupt_scheme(adapter, false);
 		if (err)
 			goto request_done;
-		/* TODO complete setup tx/rx resources */
+		igc_setup_all_tx_resources(adapter);
+		igc_setup_all_rx_resources(adapter);
 		igc_configure(adapter);
 	}
 
+	igc_assign_vector(adapter->q_vector[0], 0);
+
+	if (adapter->flags & IGC_FLAG_HAS_MSI) {
+		err = request_irq(pdev->irq, &igc_intr_msi, 0,
+				  netdev->name, adapter);
+		if (!err)
+			goto request_done;
+
+		/* fall back to legacy interrupts */
+		igc_reset_interrupt_capability(adapter);
+		adapter->flags &= ~IGC_FLAG_HAS_MSI;
+	}
+
+	err = request_irq(pdev->irq, &igc_intr, IRQF_SHARED,
+			  netdev->name, adapter);
+
+	if (err)
+		dev_err(&pdev->dev, "Error %d getting interrupt\n",
+			err);
+
 request_done:
 	return err;
 }
@@ -1332,6 +2143,16 @@  static int __igc_open(struct net_device *netdev, bool resuming)
 
 	netif_carrier_off(netdev);
 
+	/* allocate transmit descriptors */
+	err = igc_setup_all_tx_resources(adapter);
+	if (err)
+		goto err_setup_tx;
+
+	/* allocate receive descriptors */
+	err = igc_setup_all_rx_resources(adapter);
+	if (err)
+		goto err_setup_rx;
+
 	igc_power_up_link(adapter);
 
 	igc_configure(adapter);
@@ -1357,6 +2178,8 @@  static int __igc_open(struct net_device *netdev, bool resuming)
 	rd32(E1000_ICR);
 	igc_irq_enable(adapter);
 
+	netif_tx_start_all_queues(netdev);
+
 	/* start the watchdog. */
 	hw->mac.get_link_status = 1;
 	schedule_work(&adapter->watchdog_task);
@@ -1368,7 +2191,11 @@  static int __igc_open(struct net_device *netdev, bool resuming)
 err_req_irq:
 	igc_release_hw_control(adapter);
 	igc_power_down_link(adapter);
-	/* TODO complete free_all_rx_resources */
+	igc_free_all_rx_resources(adapter);
+err_setup_rx:
+	igc_free_all_tx_resources(adapter);
+err_setup_tx:
+	igc_reset(adapter);
 
 	return err;
 }
@@ -1401,6 +2228,9 @@  static int __igc_close(struct net_device *netdev, bool suspending)
 
 	igc_free_irq(adapter);
 
+	igc_free_all_tx_resources(adapter);
+	igc_free_all_rx_resources(adapter);
+
 	return 0;
 }
 
@@ -1415,6 +2245,7 @@  static const struct net_device_ops igc_netdev_ops = {
 	.ndo_open               = igc_open,
 	.ndo_stop               = igc_close,
 	.ndo_start_xmit         = igc_xmit_frame,
+	.ndo_set_rx_mode        = igc_set_rx_mode,
 	.ndo_set_mac_address    = igc_set_mac,
 	.ndo_change_mtu         = igc_change_mtu,
 	.ndo_get_stats          = igc_get_stats,