Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next

Ben Hutchings says:

====================
1. A little more refactoring.
2. Remove the unnecessary use of atomic_t that you pointed out.
3. Add support for starting or queueing firmware requests from atomic
context.
4. Add hwmon support for additional sensors found on some new boards.
5. Add support for the EF10 controller architecture, the SFC9100 family
and specifically the SFC9120 controller.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2013-08-31 22:24:24 -04:00
commit ae5dbf1ad8
39 changed files with 4407 additions and 274 deletions

View File

@ -1,5 +1,5 @@
config SFC
tristate "Solarflare SFC4000/SFC9000-family support"
tristate "Solarflare SFC4000/SFC9000/SFC9100-family support"
depends on PCI
select MDIO
select CRC32
@ -8,12 +8,13 @@ config SFC
select PTP_1588_CLOCK
---help---
This driver supports 10-gigabit Ethernet cards based on
the Solarflare SFC4000 and SFC9000-family controllers.
the Solarflare SFC4000, SFC9000-family and SFC9100-family
controllers.
To compile this driver as a module, choose M here. The module
will be called sfc.
config SFC_MTD
bool "Solarflare SFC4000/SFC9000-family MTD support"
bool "Solarflare SFC4000/SFC9000/SFC9100-family MTD support"
depends on SFC && MTD && !(SFC=y && MTD=m)
default y
---help---
@ -21,7 +22,7 @@ config SFC_MTD
(e.g. /dev/mtd1). This is required to update the firmware or
the boot configuration under Linux.
config SFC_MCDI_MON
bool "Solarflare SFC9000-family hwmon support"
bool "Solarflare SFC9000/SFC9100-family hwmon support"
depends on SFC && HWMON && !(SFC=y && HWMON=m)
default y
---help---

View File

@ -1,5 +1,5 @@
sfc-y += efx.o nic.o farch.o falcon.o siena.o tx.o rx.o \
selftest.o ethtool.o qt202x_phy.o mdio_10g.o \
sfc-y += efx.o nic.o farch.o falcon.o siena.o ef10.o tx.o \
rx.o selftest.o ethtool.o qt202x_phy.o mdio_10g.o \
tenxpress.o txc43128_phy.o falcon_boards.o \
mcdi.o mcdi_port.o mcdi_mon.o ptp.o
sfc-$(CONFIG_SFC_MTD) += mtd.o

View File

@ -1,7 +1,7 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Driver for Solarflare network controllers and boards
* Copyright 2005-2006 Fen Systems Ltd.
* Copyright 2006-2009 Solarflare Communications Inc.
* Copyright 2006-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@ -29,6 +29,10 @@
/* Lowest bit numbers and widths */
#define EFX_DUMMY_FIELD_LBN 0
#define EFX_DUMMY_FIELD_WIDTH 0
#define EFX_WORD_0_LBN 0
#define EFX_WORD_0_WIDTH 16
#define EFX_WORD_1_LBN 16
#define EFX_WORD_1_WIDTH 16
#define EFX_DWORD_0_LBN 0
#define EFX_DWORD_0_WIDTH 32
#define EFX_DWORD_1_LBN 32

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,415 @@
/****************************************************************************
* Driver for Solarflare network controllers and boards
* Copyright 2012-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation, incorporated herein by reference.
*/
#ifndef EFX_EF10_REGS_H
#define EFX_EF10_REGS_H
/* EF10 hardware architecture definitions have a name prefix following
* the format:
*
* E<type>_<min-rev><max-rev>_
*
* The following <type> strings are used:
*
* MMIO register Host memory structure
* -------------------------------------------------------------
* Address R
* Bitfield RF SF
* Enumerator FE SE
*
* <min-rev> is the first revision to which the definition applies:
*
* D: Huntington A0
*
* If the definition has been changed or removed in later revisions
* then <max-rev> is the last revision to which the definition applies;
* otherwise it is "Z".
*/
/**************************************************************************
*
* EF10 registers and descriptors
*
**************************************************************************
*/
/* BIU_HW_REV_ID_REG: */
#define ER_DZ_BIU_HW_REV_ID 0x00000000
#define ERF_DZ_HW_REV_ID_LBN 0
#define ERF_DZ_HW_REV_ID_WIDTH 32
/* BIU_MC_SFT_STATUS_REG: */
#define ER_DZ_BIU_MC_SFT_STATUS 0x00000010
#define ER_DZ_BIU_MC_SFT_STATUS_STEP 4
#define ER_DZ_BIU_MC_SFT_STATUS_ROWS 8
#define ERF_DZ_MC_SFT_STATUS_LBN 0
#define ERF_DZ_MC_SFT_STATUS_WIDTH 32
/* BIU_INT_ISR_REG: */
#define ER_DZ_BIU_INT_ISR 0x00000090
#define ERF_DZ_ISR_REG_LBN 0
#define ERF_DZ_ISR_REG_WIDTH 32
/* MC_DB_LWRD_REG: */
#define ER_DZ_MC_DB_LWRD 0x00000200
#define ERF_DZ_MC_DOORBELL_L_LBN 0
#define ERF_DZ_MC_DOORBELL_L_WIDTH 32
/* MC_DB_HWRD_REG: */
#define ER_DZ_MC_DB_HWRD 0x00000204
#define ERF_DZ_MC_DOORBELL_H_LBN 0
#define ERF_DZ_MC_DOORBELL_H_WIDTH 32
/* EVQ_RPTR_REG: */
#define ER_DZ_EVQ_RPTR 0x00000400
#define ER_DZ_EVQ_RPTR_STEP 8192
#define ER_DZ_EVQ_RPTR_ROWS 2048
#define ERF_DZ_EVQ_RPTR_VLD_LBN 15
#define ERF_DZ_EVQ_RPTR_VLD_WIDTH 1
#define ERF_DZ_EVQ_RPTR_LBN 0
#define ERF_DZ_EVQ_RPTR_WIDTH 15
/* EVQ_TMR_REG: */
#define ER_DZ_EVQ_TMR 0x00000420
#define ER_DZ_EVQ_TMR_STEP 8192
#define ER_DZ_EVQ_TMR_ROWS 2048
#define ERF_DZ_TC_TIMER_MODE_LBN 14
#define ERF_DZ_TC_TIMER_MODE_WIDTH 2
#define ERF_DZ_TC_TIMER_VAL_LBN 0
#define ERF_DZ_TC_TIMER_VAL_WIDTH 14
/* RX_DESC_UPD_REG: */
#define ER_DZ_RX_DESC_UPD 0x00000830
#define ER_DZ_RX_DESC_UPD_STEP 8192
#define ER_DZ_RX_DESC_UPD_ROWS 2048
#define ERF_DZ_RX_DESC_WPTR_LBN 0
#define ERF_DZ_RX_DESC_WPTR_WIDTH 12
/* TX_DESC_UPD_REG: */
#define ER_DZ_TX_DESC_UPD 0x00000a10
#define ER_DZ_TX_DESC_UPD_STEP 8192
#define ER_DZ_TX_DESC_UPD_ROWS 2048
#define ERF_DZ_RSVD_LBN 76
#define ERF_DZ_RSVD_WIDTH 20
#define ERF_DZ_TX_DESC_WPTR_LBN 64
#define ERF_DZ_TX_DESC_WPTR_WIDTH 12
#define ERF_DZ_TX_DESC_HWORD_LBN 32
#define ERF_DZ_TX_DESC_HWORD_WIDTH 32
#define ERF_DZ_TX_DESC_LWORD_LBN 0
#define ERF_DZ_TX_DESC_LWORD_WIDTH 32
/* DRIVER_EV */
#define ESF_DZ_DRV_CODE_LBN 60
#define ESF_DZ_DRV_CODE_WIDTH 4
#define ESF_DZ_DRV_SUB_CODE_LBN 56
#define ESF_DZ_DRV_SUB_CODE_WIDTH 4
#define ESE_DZ_DRV_TIMER_EV 3
#define ESE_DZ_DRV_START_UP_EV 2
#define ESE_DZ_DRV_WAKE_UP_EV 1
#define ESF_DZ_DRV_SUB_DATA_LBN 0
#define ESF_DZ_DRV_SUB_DATA_WIDTH 56
#define ESF_DZ_DRV_EVQ_ID_LBN 0
#define ESF_DZ_DRV_EVQ_ID_WIDTH 14
#define ESF_DZ_DRV_TMR_ID_LBN 0
#define ESF_DZ_DRV_TMR_ID_WIDTH 14
/* EVENT_ENTRY */
#define ESF_DZ_EV_CODE_LBN 60
#define ESF_DZ_EV_CODE_WIDTH 4
#define ESE_DZ_EV_CODE_MCDI_EV 12
#define ESE_DZ_EV_CODE_DRIVER_EV 5
#define ESE_DZ_EV_CODE_TX_EV 2
#define ESE_DZ_EV_CODE_RX_EV 0
#define ESE_DZ_OTHER other
#define ESF_DZ_EV_DATA_LBN 0
#define ESF_DZ_EV_DATA_WIDTH 60
/* MC_EVENT */
#define ESF_DZ_MC_CODE_LBN 60
#define ESF_DZ_MC_CODE_WIDTH 4
#define ESF_DZ_MC_OVERRIDE_HOLDOFF_LBN 59
#define ESF_DZ_MC_OVERRIDE_HOLDOFF_WIDTH 1
#define ESF_DZ_MC_DROP_EVENT_LBN 58
#define ESF_DZ_MC_DROP_EVENT_WIDTH 1
#define ESF_DZ_MC_SOFT_LBN 0
#define ESF_DZ_MC_SOFT_WIDTH 58
/* RX_EVENT */
#define ESF_DZ_RX_CODE_LBN 60
#define ESF_DZ_RX_CODE_WIDTH 4
#define ESF_DZ_RX_OVERRIDE_HOLDOFF_LBN 59
#define ESF_DZ_RX_OVERRIDE_HOLDOFF_WIDTH 1
#define ESF_DZ_RX_DROP_EVENT_LBN 58
#define ESF_DZ_RX_DROP_EVENT_WIDTH 1
#define ESF_DZ_RX_EV_RSVD2_LBN 54
#define ESF_DZ_RX_EV_RSVD2_WIDTH 4
#define ESF_DZ_RX_EV_SOFT2_LBN 52
#define ESF_DZ_RX_EV_SOFT2_WIDTH 2
#define ESF_DZ_RX_DSC_PTR_LBITS_LBN 48
#define ESF_DZ_RX_DSC_PTR_LBITS_WIDTH 4
#define ESF_DZ_RX_L4_CLASS_LBN 45
#define ESF_DZ_RX_L4_CLASS_WIDTH 3
#define ESE_DZ_L4_CLASS_RSVD7 7
#define ESE_DZ_L4_CLASS_RSVD6 6
#define ESE_DZ_L4_CLASS_RSVD5 5
#define ESE_DZ_L4_CLASS_RSVD4 4
#define ESE_DZ_L4_CLASS_RSVD3 3
#define ESE_DZ_L4_CLASS_UDP 2
#define ESE_DZ_L4_CLASS_TCP 1
#define ESE_DZ_L4_CLASS_UNKNOWN 0
#define ESF_DZ_RX_L3_CLASS_LBN 42
#define ESF_DZ_RX_L3_CLASS_WIDTH 3
#define ESE_DZ_L3_CLASS_RSVD7 7
#define ESE_DZ_L3_CLASS_IP6_FRAG 6
#define ESE_DZ_L3_CLASS_ARP 5
#define ESE_DZ_L3_CLASS_IP4_FRAG 4
#define ESE_DZ_L3_CLASS_FCOE 3
#define ESE_DZ_L3_CLASS_IP6 2
#define ESE_DZ_L3_CLASS_IP4 1
#define ESE_DZ_L3_CLASS_UNKNOWN 0
#define ESF_DZ_RX_ETH_TAG_CLASS_LBN 39
#define ESF_DZ_RX_ETH_TAG_CLASS_WIDTH 3
#define ESE_DZ_ETH_TAG_CLASS_RSVD7 7
#define ESE_DZ_ETH_TAG_CLASS_RSVD6 6
#define ESE_DZ_ETH_TAG_CLASS_RSVD5 5
#define ESE_DZ_ETH_TAG_CLASS_RSVD4 4
#define ESE_DZ_ETH_TAG_CLASS_RSVD3 3
#define ESE_DZ_ETH_TAG_CLASS_VLAN2 2
#define ESE_DZ_ETH_TAG_CLASS_VLAN1 1
#define ESE_DZ_ETH_TAG_CLASS_NONE 0
#define ESF_DZ_RX_ETH_BASE_CLASS_LBN 36
#define ESF_DZ_RX_ETH_BASE_CLASS_WIDTH 3
#define ESE_DZ_ETH_BASE_CLASS_LLC_SNAP 2
#define ESE_DZ_ETH_BASE_CLASS_LLC 1
#define ESE_DZ_ETH_BASE_CLASS_ETH2 0
#define ESF_DZ_RX_MAC_CLASS_LBN 35
#define ESF_DZ_RX_MAC_CLASS_WIDTH 1
#define ESE_DZ_MAC_CLASS_MCAST 1
#define ESE_DZ_MAC_CLASS_UCAST 0
#define ESF_DZ_RX_EV_SOFT1_LBN 32
#define ESF_DZ_RX_EV_SOFT1_WIDTH 3
#define ESF_DZ_RX_EV_RSVD1_LBN 31
#define ESF_DZ_RX_EV_RSVD1_WIDTH 1
#define ESF_DZ_RX_ABORT_LBN 30
#define ESF_DZ_RX_ABORT_WIDTH 1
#define ESF_DZ_RX_ECC_ERR_LBN 29
#define ESF_DZ_RX_ECC_ERR_WIDTH 1
#define ESF_DZ_RX_CRC1_ERR_LBN 28
#define ESF_DZ_RX_CRC1_ERR_WIDTH 1
#define ESF_DZ_RX_CRC0_ERR_LBN 27
#define ESF_DZ_RX_CRC0_ERR_WIDTH 1
#define ESF_DZ_RX_TCPUDP_CKSUM_ERR_LBN 26
#define ESF_DZ_RX_TCPUDP_CKSUM_ERR_WIDTH 1
#define ESF_DZ_RX_IPCKSUM_ERR_LBN 25
#define ESF_DZ_RX_IPCKSUM_ERR_WIDTH 1
#define ESF_DZ_RX_ECRC_ERR_LBN 24
#define ESF_DZ_RX_ECRC_ERR_WIDTH 1
#define ESF_DZ_RX_QLABEL_LBN 16
#define ESF_DZ_RX_QLABEL_WIDTH 5
#define ESF_DZ_RX_PARSE_INCOMPLETE_LBN 15
#define ESF_DZ_RX_PARSE_INCOMPLETE_WIDTH 1
#define ESF_DZ_RX_CONT_LBN 14
#define ESF_DZ_RX_CONT_WIDTH 1
#define ESF_DZ_RX_BYTES_LBN 0
#define ESF_DZ_RX_BYTES_WIDTH 14
/* RX_KER_DESC */
#define ESF_DZ_RX_KER_RESERVED_LBN 62
#define ESF_DZ_RX_KER_RESERVED_WIDTH 2
#define ESF_DZ_RX_KER_BYTE_CNT_LBN 48
#define ESF_DZ_RX_KER_BYTE_CNT_WIDTH 14
#define ESF_DZ_RX_KER_BUF_ADDR_LBN 0
#define ESF_DZ_RX_KER_BUF_ADDR_WIDTH 48
/* RX_USER_DESC */
#define ESF_DZ_RX_USR_RESERVED_LBN 62
#define ESF_DZ_RX_USR_RESERVED_WIDTH 2
#define ESF_DZ_RX_USR_BYTE_CNT_LBN 48
#define ESF_DZ_RX_USR_BYTE_CNT_WIDTH 14
#define ESF_DZ_RX_USR_BUF_PAGE_SIZE_LBN 44
#define ESF_DZ_RX_USR_BUF_PAGE_SIZE_WIDTH 4
#define ESE_DZ_USR_BUF_PAGE_SZ_4MB 10
#define ESE_DZ_USR_BUF_PAGE_SZ_1MB 8
#define ESE_DZ_USR_BUF_PAGE_SZ_64KB 4
#define ESE_DZ_USR_BUF_PAGE_SZ_4KB 0
#define ESF_DZ_RX_USR_BUF_ID_OFFSET_LBN 0
#define ESF_DZ_RX_USR_BUF_ID_OFFSET_WIDTH 44
#define ESF_DZ_RX_USR_4KBPS_BUF_ID_LBN 12
#define ESF_DZ_RX_USR_4KBPS_BUF_ID_WIDTH 32
#define ESF_DZ_RX_USR_64KBPS_BUF_ID_LBN 16
#define ESF_DZ_RX_USR_64KBPS_BUF_ID_WIDTH 28
#define ESF_DZ_RX_USR_1MBPS_BUF_ID_LBN 20
#define ESF_DZ_RX_USR_1MBPS_BUF_ID_WIDTH 24
#define ESF_DZ_RX_USR_4MBPS_BUF_ID_LBN 22
#define ESF_DZ_RX_USR_4MBPS_BUF_ID_WIDTH 22
#define ESF_DZ_RX_USR_4MBPS_BYTE_OFFSET_LBN 0
#define ESF_DZ_RX_USR_4MBPS_BYTE_OFFSET_WIDTH 22
#define ESF_DZ_RX_USR_1MBPS_BYTE_OFFSET_LBN 0
#define ESF_DZ_RX_USR_1MBPS_BYTE_OFFSET_WIDTH 20
#define ESF_DZ_RX_USR_64KBPS_BYTE_OFFSET_LBN 0
#define ESF_DZ_RX_USR_64KBPS_BYTE_OFFSET_WIDTH 16
#define ESF_DZ_RX_USR_4KBPS_BYTE_OFFSET_LBN 0
#define ESF_DZ_RX_USR_4KBPS_BYTE_OFFSET_WIDTH 12
/* TX_CSUM_TSTAMP_DESC */
#define ESF_DZ_TX_DESC_IS_OPT_LBN 63
#define ESF_DZ_TX_DESC_IS_OPT_WIDTH 1
#define ESF_DZ_TX_OPTION_TYPE_LBN 60
#define ESF_DZ_TX_OPTION_TYPE_WIDTH 3
#define ESE_DZ_TX_OPTION_DESC_TSO 7
#define ESE_DZ_TX_OPTION_DESC_VLAN 6
#define ESE_DZ_TX_OPTION_DESC_CRC_CSUM 0
#define ESF_DZ_TX_TIMESTAMP_LBN 5
#define ESF_DZ_TX_TIMESTAMP_WIDTH 1
#define ESF_DZ_TX_OPTION_CRC_MODE_LBN 2
#define ESF_DZ_TX_OPTION_CRC_MODE_WIDTH 3
#define ESE_DZ_TX_OPTION_CRC_FCOIP_MPA 5
#define ESE_DZ_TX_OPTION_CRC_FCOIP_FCOE 4
#define ESE_DZ_TX_OPTION_CRC_ISCSI_HDR_AND_PYLD 3
#define ESE_DZ_TX_OPTION_CRC_ISCSI_HDR 2
#define ESE_DZ_TX_OPTION_CRC_FCOE 1
#define ESE_DZ_TX_OPTION_CRC_OFF 0
#define ESF_DZ_TX_OPTION_UDP_TCP_CSUM_LBN 1
#define ESF_DZ_TX_OPTION_UDP_TCP_CSUM_WIDTH 1
#define ESF_DZ_TX_OPTION_IP_CSUM_LBN 0
#define ESF_DZ_TX_OPTION_IP_CSUM_WIDTH 1
/* TX_EVENT */
#define ESF_DZ_TX_CODE_LBN 60
#define ESF_DZ_TX_CODE_WIDTH 4
#define ESF_DZ_TX_OVERRIDE_HOLDOFF_LBN 59
#define ESF_DZ_TX_OVERRIDE_HOLDOFF_WIDTH 1
#define ESF_DZ_TX_DROP_EVENT_LBN 58
#define ESF_DZ_TX_DROP_EVENT_WIDTH 1
#define ESF_DZ_TX_EV_RSVD_LBN 48
#define ESF_DZ_TX_EV_RSVD_WIDTH 10
#define ESF_DZ_TX_SOFT2_LBN 32
#define ESF_DZ_TX_SOFT2_WIDTH 16
#define ESF_DZ_TX_CAN_MERGE_LBN 31
#define ESF_DZ_TX_CAN_MERGE_WIDTH 1
#define ESF_DZ_TX_SOFT1_LBN 24
#define ESF_DZ_TX_SOFT1_WIDTH 7
#define ESF_DZ_TX_QLABEL_LBN 16
#define ESF_DZ_TX_QLABEL_WIDTH 5
#define ESF_DZ_TX_DESCR_INDX_LBN 0
#define ESF_DZ_TX_DESCR_INDX_WIDTH 16
/* TX_KER_DESC */
#define ESF_DZ_TX_KER_TYPE_LBN 63
#define ESF_DZ_TX_KER_TYPE_WIDTH 1
#define ESF_DZ_TX_KER_CONT_LBN 62
#define ESF_DZ_TX_KER_CONT_WIDTH 1
#define ESF_DZ_TX_KER_BYTE_CNT_LBN 48
#define ESF_DZ_TX_KER_BYTE_CNT_WIDTH 14
#define ESF_DZ_TX_KER_BUF_ADDR_LBN 0
#define ESF_DZ_TX_KER_BUF_ADDR_WIDTH 48
/* TX_PIO_DESC */
#define ESF_DZ_TX_PIO_TYPE_LBN 63
#define ESF_DZ_TX_PIO_TYPE_WIDTH 1
#define ESF_DZ_TX_PIO_OPT_LBN 60
#define ESF_DZ_TX_PIO_OPT_WIDTH 3
#define ESF_DZ_TX_PIO_CONT_LBN 59
#define ESF_DZ_TX_PIO_CONT_WIDTH 1
#define ESF_DZ_TX_PIO_BYTE_CNT_LBN 32
#define ESF_DZ_TX_PIO_BYTE_CNT_WIDTH 12
#define ESF_DZ_TX_PIO_BUF_ADDR_LBN 0
#define ESF_DZ_TX_PIO_BUF_ADDR_WIDTH 12
/* TX_TSO_DESC */
#define ESF_DZ_TX_DESC_IS_OPT_LBN 63
#define ESF_DZ_TX_DESC_IS_OPT_WIDTH 1
#define ESF_DZ_TX_OPTION_TYPE_LBN 60
#define ESF_DZ_TX_OPTION_TYPE_WIDTH 3
#define ESE_DZ_TX_OPTION_DESC_TSO 7
#define ESE_DZ_TX_OPTION_DESC_VLAN 6
#define ESE_DZ_TX_OPTION_DESC_CRC_CSUM 0
#define ESF_DZ_TX_TSO_TCP_FLAGS_LBN 48
#define ESF_DZ_TX_TSO_TCP_FLAGS_WIDTH 8
#define ESF_DZ_TX_TSO_IP_ID_LBN 32
#define ESF_DZ_TX_TSO_IP_ID_WIDTH 16
#define ESF_DZ_TX_TSO_TCP_SEQNO_LBN 0
#define ESF_DZ_TX_TSO_TCP_SEQNO_WIDTH 32
/* TX_USER_DESC */
#define ESF_DZ_TX_USR_TYPE_LBN 63
#define ESF_DZ_TX_USR_TYPE_WIDTH 1
#define ESF_DZ_TX_USR_CONT_LBN 62
#define ESF_DZ_TX_USR_CONT_WIDTH 1
#define ESF_DZ_TX_USR_BYTE_CNT_LBN 48
#define ESF_DZ_TX_USR_BYTE_CNT_WIDTH 14
#define ESF_DZ_TX_USR_BUF_PAGE_SIZE_LBN 44
#define ESF_DZ_TX_USR_BUF_PAGE_SIZE_WIDTH 4
#define ESE_DZ_USR_BUF_PAGE_SZ_4MB 10
#define ESE_DZ_USR_BUF_PAGE_SZ_1MB 8
#define ESE_DZ_USR_BUF_PAGE_SZ_64KB 4
#define ESE_DZ_USR_BUF_PAGE_SZ_4KB 0
#define ESF_DZ_TX_USR_BUF_ID_OFFSET_LBN 0
#define ESF_DZ_TX_USR_BUF_ID_OFFSET_WIDTH 44
#define ESF_DZ_TX_USR_4KBPS_BUF_ID_LBN 12
#define ESF_DZ_TX_USR_4KBPS_BUF_ID_WIDTH 32
#define ESF_DZ_TX_USR_64KBPS_BUF_ID_LBN 16
#define ESF_DZ_TX_USR_64KBPS_BUF_ID_WIDTH 28
#define ESF_DZ_TX_USR_1MBPS_BUF_ID_LBN 20
#define ESF_DZ_TX_USR_1MBPS_BUF_ID_WIDTH 24
#define ESF_DZ_TX_USR_4MBPS_BUF_ID_LBN 22
#define ESF_DZ_TX_USR_4MBPS_BUF_ID_WIDTH 22
#define ESF_DZ_TX_USR_4MBPS_BYTE_OFFSET_LBN 0
#define ESF_DZ_TX_USR_4MBPS_BYTE_OFFSET_WIDTH 22
#define ESF_DZ_TX_USR_1MBPS_BYTE_OFFSET_LBN 0
#define ESF_DZ_TX_USR_1MBPS_BYTE_OFFSET_WIDTH 20
#define ESF_DZ_TX_USR_64KBPS_BYTE_OFFSET_LBN 0
#define ESF_DZ_TX_USR_64KBPS_BYTE_OFFSET_WIDTH 16
#define ESF_DZ_TX_USR_4KBPS_BYTE_OFFSET_LBN 0
#define ESF_DZ_TX_USR_4KBPS_BYTE_OFFSET_WIDTH 12
/*************************************************************************/
/* TX_DESC_UPD_REG: Transmit descriptor update register.
* We may write just one dword of these registers.
*/
#define ER_DZ_TX_DESC_UPD_DWORD (ER_DZ_TX_DESC_UPD + 2 * 4)
#define ERF_DZ_TX_DESC_WPTR_DWORD_LBN (ERF_DZ_TX_DESC_WPTR_LBN - 2 * 32)
#define ERF_DZ_TX_DESC_WPTR_DWORD_WIDTH ERF_DZ_TX_DESC_WPTR_WIDTH
/* The workaround for bug 35388 requires multiplexing writes through
* the TX_DESC_UPD_DWORD address.
* TX_DESC_UPD: 0ppppppppppp (bit 11 lost)
* EVQ_RPTR: 1000hhhhhhhh, 1001llllllll (split into high and low bits)
* EVQ_TMR: 11mmvvvvvvvv (bits 8:13 of value lost)
*/
#define ER_DD_EVQ_INDIRECT ER_DZ_TX_DESC_UPD_DWORD
#define ERF_DD_EVQ_IND_RPTR_FLAGS_LBN 8
#define ERF_DD_EVQ_IND_RPTR_FLAGS_WIDTH 4
#define EFE_DD_EVQ_IND_RPTR_FLAGS_HIGH 8
#define EFE_DD_EVQ_IND_RPTR_FLAGS_LOW 9
#define ERF_DD_EVQ_IND_RPTR_LBN 0
#define ERF_DD_EVQ_IND_RPTR_WIDTH 8
#define ERF_DD_EVQ_IND_TIMER_FLAGS_LBN 10
#define ERF_DD_EVQ_IND_TIMER_FLAGS_WIDTH 2
#define EFE_DD_EVQ_IND_TIMER_FLAGS 3
#define ERF_DD_EVQ_IND_TIMER_MODE_LBN 8
#define ERF_DD_EVQ_IND_TIMER_MODE_WIDTH 2
#define ERF_DD_EVQ_IND_TIMER_VAL_LBN 0
#define ERF_DD_EVQ_IND_TIMER_VAL_WIDTH 8
/* TX_PIOBUF
* PIO buffer aperture (paged)
*/
#define ER_DZ_TX_PIOBUF 4096
#define ER_DZ_TX_PIOBUF_SIZE 2048
/* RX packet prefix */
#define ES_DZ_RX_PREFIX_HASH_OFST 0
#define ES_DZ_RX_PREFIX_VLAN1_OFST 4
#define ES_DZ_RX_PREFIX_VLAN2_OFST 6
#define ES_DZ_RX_PREFIX_PKTLEN_OFST 8
#define ES_DZ_RX_PREFIX_TSTAMP_OFST 10
#define ES_DZ_RX_PREFIX_SIZE 14
#endif /* EFX_EF10_REGS_H */

View File

@ -1,7 +1,7 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Driver for Solarflare network controllers and boards
* Copyright 2005-2006 Fen Systems Ltd.
* Copyright 2005-2011 Solarflare Communications Inc.
* Copyright 2005-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@ -189,7 +189,7 @@ MODULE_PARM_DESC(debug, "Bitmapped debugging message enable value");
*
*************************************************************************/
static void efx_soft_enable_interrupts(struct efx_nic *efx);
static int efx_soft_enable_interrupts(struct efx_nic *efx);
static void efx_soft_disable_interrupts(struct efx_nic *efx);
static void efx_remove_channel(struct efx_channel *channel);
static void efx_remove_channels(struct efx_nic *efx);
@ -329,15 +329,23 @@ static int efx_probe_eventq(struct efx_channel *channel)
}
/* Prepare channel's event queue */
static void efx_init_eventq(struct efx_channel *channel)
static int efx_init_eventq(struct efx_channel *channel)
{
netif_dbg(channel->efx, drv, channel->efx->net_dev,
struct efx_nic *efx = channel->efx;
int rc;
EFX_WARN_ON_PARANOID(channel->eventq_init);
netif_dbg(efx, drv, efx->net_dev,
"chan %d init event queue\n", channel->channel);
channel->eventq_read_ptr = 0;
efx_nic_init_eventq(channel);
channel->eventq_init = true;
rc = efx_nic_init_eventq(channel);
if (rc == 0) {
efx->type->push_irq_moderation(channel);
channel->eventq_read_ptr = 0;
channel->eventq_init = true;
}
return rc;
}
/* Enable event queue processing and NAPI */
@ -579,7 +587,7 @@ static void efx_start_datapath(struct efx_nic *efx)
rx_buf_len = (sizeof(struct efx_rx_page_state) +
NET_IP_ALIGN + efx->rx_dma_len);
if (rx_buf_len <= PAGE_SIZE) {
efx->rx_scatter = false;
efx->rx_scatter = efx->type->always_rx_scatter;
efx->rx_buffer_order = 0;
} else if (efx->type->can_rx_scatter) {
BUILD_BUG_ON(EFX_RX_USR_BUF_SIZE % L1_CACHE_BYTES);
@ -607,7 +615,7 @@ static void efx_start_datapath(struct efx_nic *efx)
efx->rx_dma_len, efx->rx_page_buf_step,
efx->rx_bufs_per_page, efx->rx_pages_per_batch);
/* RX filters also have scatter-enabled flags */
/* RX filters may also have scatter-enabled flags */
if (efx->rx_scatter != old_rx_scatter)
efx->type->filter_update_rx_scatter(efx);
@ -623,11 +631,14 @@ static void efx_start_datapath(struct efx_nic *efx)
/* Initialise the channels */
efx_for_each_channel(channel, efx) {
efx_for_each_channel_tx_queue(tx_queue, channel)
efx_for_each_channel_tx_queue(tx_queue, channel) {
efx_init_tx_queue(tx_queue);
atomic_inc(&efx->active_queues);
}
efx_for_each_channel_rx_queue(rx_queue, channel) {
efx_init_rx_queue(rx_queue);
atomic_inc(&efx->active_queues);
efx_nic_generate_fill_event(rx_queue);
}
@ -722,7 +733,7 @@ efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries)
struct efx_channel *other_channel[EFX_MAX_CHANNELS], *channel;
u32 old_rxq_entries, old_txq_entries;
unsigned i, next_buffer_table = 0;
int rc;
int rc, rc2;
rc = efx_check_disabled(efx);
if (rc)
@ -802,9 +813,16 @@ out:
}
}
efx_soft_enable_interrupts(efx);
efx_start_all(efx);
netif_device_attach(efx->net_dev);
rc2 = efx_soft_enable_interrupts(efx);
if (rc2) {
rc = rc ? rc : rc2;
netif_err(efx, drv, efx->net_dev,
"unable to restart interrupts on channel reallocation\n");
efx_schedule_reset(efx, RESET_TYPE_DISABLE);
} else {
efx_start_all(efx);
netif_device_attach(efx->net_dev);
}
return rc;
rollback:
@ -1327,9 +1345,10 @@ static int efx_probe_interrupts(struct efx_nic *efx)
return 0;
}
static void efx_soft_enable_interrupts(struct efx_nic *efx)
static int efx_soft_enable_interrupts(struct efx_nic *efx)
{
struct efx_channel *channel;
struct efx_channel *channel, *end_channel;
int rc;
BUG_ON(efx->state == STATE_DISABLED);
@ -1337,12 +1356,28 @@ static void efx_soft_enable_interrupts(struct efx_nic *efx)
smp_wmb();
efx_for_each_channel(channel, efx) {
if (!channel->type->keep_eventq)
efx_init_eventq(channel);
if (!channel->type->keep_eventq) {
rc = efx_init_eventq(channel);
if (rc)
goto fail;
}
efx_start_eventq(channel);
}
efx_mcdi_mode_event(efx);
return 0;
fail:
end_channel = channel;
efx_for_each_channel(channel, efx) {
if (channel == end_channel)
break;
efx_stop_eventq(channel);
if (!channel->type->keep_eventq)
efx_fini_eventq(channel);
}
return rc;
}
static void efx_soft_disable_interrupts(struct efx_nic *efx)
@ -1368,11 +1403,15 @@ static void efx_soft_disable_interrupts(struct efx_nic *efx)
if (!channel->type->keep_eventq)
efx_fini_eventq(channel);
}
/* Flush the asynchronous MCDI request queue */
efx_mcdi_flush_async(efx);
}
static void efx_enable_interrupts(struct efx_nic *efx)
static int efx_enable_interrupts(struct efx_nic *efx)
{
struct efx_channel *channel;
struct efx_channel *channel, *end_channel;
int rc;
BUG_ON(efx->state == STATE_DISABLED);
@ -1384,11 +1423,31 @@ static void efx_enable_interrupts(struct efx_nic *efx)
efx->type->irq_enable_master(efx);
efx_for_each_channel(channel, efx) {
if (channel->type->keep_eventq)
efx_init_eventq(channel);
if (channel->type->keep_eventq) {
rc = efx_init_eventq(channel);
if (rc)
goto fail;
}
}
efx_soft_enable_interrupts(efx);
rc = efx_soft_enable_interrupts(efx);
if (rc)
goto fail;
return 0;
fail:
end_channel = channel;
efx_for_each_channel(channel, efx) {
if (channel == end_channel)
break;
if (channel->type->keep_eventq)
efx_fini_eventq(channel);
}
efx->type->irq_disable_non_ev(efx);
return rc;
}
static void efx_disable_interrupts(struct efx_nic *efx)
@ -1459,9 +1518,11 @@ static int efx_probe_nic(struct efx_nic *efx)
* in MSI-X interrupts. */
rc = efx_probe_interrupts(efx);
if (rc)
goto fail;
goto fail1;
efx->type->dimension_resources(efx);
rc = efx->type->dimension_resources(efx);
if (rc)
goto fail2;
if (efx->n_channels > 1)
get_random_bytes(&efx->rx_hash_key, sizeof(efx->rx_hash_key));
@ -1479,7 +1540,9 @@ static int efx_probe_nic(struct efx_nic *efx)
return 0;
fail:
fail2:
efx_remove_interrupts(efx);
fail1:
efx->type->remove(efx);
return rc;
}
@ -2012,7 +2075,7 @@ static int efx_set_features(struct net_device *net_dev, netdev_features_t data)
return 0;
}
static const struct net_device_ops efx_netdev_ops = {
static const struct net_device_ops efx_farch_netdev_ops = {
.ndo_open = efx_net_open,
.ndo_stop = efx_net_stop,
.ndo_get_stats64 = efx_net_stats,
@ -2039,6 +2102,26 @@ static const struct net_device_ops efx_netdev_ops = {
#endif
};
static const struct net_device_ops efx_ef10_netdev_ops = {
.ndo_open = efx_net_open,
.ndo_stop = efx_net_stop,
.ndo_get_stats64 = efx_net_stats,
.ndo_tx_timeout = efx_watchdog,
.ndo_start_xmit = efx_hard_start_xmit,
.ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = efx_ioctl,
.ndo_change_mtu = efx_change_mtu,
.ndo_set_mac_address = efx_set_mac_address,
.ndo_set_rx_mode = efx_set_rx_mode,
.ndo_set_features = efx_set_features,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = efx_netpoll,
#endif
#ifdef CONFIG_RFS_ACCEL
.ndo_rx_flow_steer = efx_filter_rfs,
#endif
};
static void efx_update_name(struct efx_nic *efx)
{
strcpy(efx->name, efx->net_dev->name);
@ -2051,7 +2134,8 @@ static int efx_netdev_event(struct notifier_block *this,
{
struct net_device *net_dev = netdev_notifier_info_to_dev(ptr);
if (net_dev->netdev_ops == &efx_netdev_ops &&
if ((net_dev->netdev_ops == &efx_farch_netdev_ops ||
net_dev->netdev_ops == &efx_ef10_netdev_ops) &&
event == NETDEV_CHANGENAME)
efx_update_name(netdev_priv(net_dev));
@ -2078,7 +2162,12 @@ static int efx_register_netdev(struct efx_nic *efx)
net_dev->watchdog_timeo = 5 * HZ;
net_dev->irq = efx->pci_dev->irq;
net_dev->netdev_ops = &efx_netdev_ops;
if (efx_nic_rev(efx) >= EFX_REV_HUNT_A0) {
net_dev->netdev_ops = &efx_ef10_netdev_ops;
net_dev->priv_flags |= IFF_UNICAST_FLT;
} else {
net_dev->netdev_ops = &efx_farch_netdev_ops;
}
SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops);
net_dev->gso_max_segs = EFX_TSO_MAX_SEGS;
@ -2202,7 +2291,9 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok)
"could not restore PHY settings\n");
}
efx_enable_interrupts(efx);
rc = efx_enable_interrupts(efx);
if (rc)
goto fail;
efx_restore_filters(efx);
efx_sriov_reset(efx);
@ -2398,6 +2489,8 @@ static DEFINE_PCI_DEVICE_TABLE(efx_pci_table) = {
.driver_data = (unsigned long) &siena_a0_nic_type},
{PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, 0x0813), /* SFL9021 */
.driver_data = (unsigned long) &siena_a0_nic_type},
{PCI_DEVICE(PCI_VENDOR_ID_SOLARFLARE, 0x0903), /* SFC9120 PF */
.driver_data = (unsigned long) &efx_hunt_a0_nic_type},
{0} /* end of list */
};
@ -2646,10 +2739,14 @@ static int efx_pci_probe_main(struct efx_nic *efx)
rc = efx_nic_init_interrupt(efx);
if (rc)
goto fail5;
efx_enable_interrupts(efx);
rc = efx_enable_interrupts(efx);
if (rc)
goto fail6;
return 0;
fail6:
efx_nic_fini_interrupt(efx);
fail5:
efx_fini_port(efx);
fail4:
@ -2777,12 +2874,15 @@ static int efx_pm_freeze(struct device *dev)
static int efx_pm_thaw(struct device *dev)
{
int rc;
struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
rtnl_lock();
if (efx->state != STATE_DISABLED) {
efx_enable_interrupts(efx);
rc = efx_enable_interrupts(efx);
if (rc)
goto fail;
mutex_lock(&efx->mac_lock);
efx->phy_op->reconfigure(efx);
@ -2803,6 +2903,11 @@ static int efx_pm_thaw(struct device *dev)
queue_work(reset_workqueue, &efx->reset_work);
return 0;
fail:
rtnl_unlock();
return rc;
}
static int efx_pm_poweroff(struct device *dev)
@ -2839,8 +2944,8 @@ static int efx_pm_resume(struct device *dev)
rc = efx->type->init(efx);
if (rc)
return rc;
efx_pm_thaw(dev);
return 0;
rc = efx_pm_thaw(dev);
return rc;
}
static int efx_pm_suspend(struct device *dev)

View File

@ -1,7 +1,7 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Driver for Solarflare network controllers and boards
* Copyright 2005-2006 Fen Systems Ltd.
* Copyright 2006-2010 Solarflare Communications Inc.
* Copyright 2006-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@ -79,13 +79,20 @@ extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue);
* On success, return the filter ID.
* On failure, return a negative error code.
*
* If an existing filter has equal match values to the new filter
* spec, then the new filter might replace it, depending on the
* relative priorities. If the existing filter has lower priority, or
* if @replace_equal is set and it has equal priority, then it is
* replaced. Otherwise the function fails, returning -%EPERM if
* the existing filter has higher priority or -%EEXIST if it has
* equal priority.
* If existing filters have equal match values to the new filter spec,
* then the new filter might replace them or the function might fail,
* as follows.
*
* 1. If the existing filters have lower priority, or @replace_equal
* is set and they have equal priority, replace them.
*
* 2. If the existing filters have higher priority, return -%EPERM.
*
* 3. If !efx_filter_is_mc_recipient(@spec), or the NIC does not
* support delivery to multiple recipients, return -%EEXIST.
*
* This implies that filters for multiple multicast recipients must
* all be inserted with the same priority and @replace_equal = %false.
*/
static inline s32 efx_filter_insert_filter(struct efx_nic *efx,
struct efx_filter_spec *spec,
@ -169,6 +176,7 @@ static inline void efx_filter_rfs_expire(struct efx_channel *channel)
static inline void efx_filter_rfs_expire(struct efx_channel *channel) {}
#define efx_filter_rfs_enabled() 0
#endif
extern bool efx_filter_is_mc_recipient(const struct efx_filter_spec *spec);
/* Channels */
extern int efx_channel_dummy_op_int(struct efx_channel *channel);

View File

@ -1,6 +1,6 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Copyright 2007-2009 Solarflare Communications Inc.
* Driver for Solarflare network controllers and boards
* Copyright 2007-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published

View File

@ -1,7 +1,7 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Driver for Solarflare network controllers and boards
* Copyright 2005-2006 Fen Systems Ltd.
* Copyright 2006-2010 Solarflare Communications Inc.
* Copyright 2006-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@ -77,6 +77,8 @@ static const struct efx_sw_stat_desc efx_sw_stat_desc[] = {
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_mcast_mismatch),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_frm_trunc),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_nodesc_trunc),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_merge_events),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_merge_packets),
};
#define EFX_ETHTOOL_SW_STAT_COUNT ARRAY_SIZE(efx_sw_stat_desc)

View File

@ -1,7 +1,7 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Driver for Solarflare network controllers and boards
* Copyright 2005-2006 Fen Systems Ltd.
* Copyright 2006-2010 Solarflare Communications Inc.
* Copyright 2006-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@ -2174,10 +2174,11 @@ out:
return rc;
}
static void falcon_dimension_resources(struct efx_nic *efx)
static int falcon_dimension_resources(struct efx_nic *efx)
{
efx->rx_dc_base = 0x20000;
efx->tx_dc_base = 0x26000;
return 0;
}
/* Probe all SPI devices on the NIC */

View File

@ -1,6 +1,6 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Copyright 2007-2010 Solarflare Communications Inc.
* Driver for Solarflare network controllers and boards
* Copyright 2007-2012 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published

View File

@ -1,7 +1,7 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Driver for Solarflare network controllers and boards
* Copyright 2005-2006 Fen Systems Ltd.
* Copyright 2006-2011 Solarflare Communications Inc.
* Copyright 2006-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@ -325,6 +325,8 @@ void efx_farch_tx_write(struct efx_tx_queue *tx_queue)
txd = efx_tx_desc(tx_queue, write_ptr);
++tx_queue->write_count;
EFX_BUG_ON_PARANOID(buffer->flags & EFX_TX_BUF_OPTION);
/* Create TX descriptor ring entry */
BUILD_BUG_ON(EFX_TX_BUF_CONT != 1);
EFX_POPULATE_QWORD_4(*txd,
@ -594,7 +596,7 @@ static bool efx_farch_flush_wake(struct efx_nic *efx)
/* Ensure that all updates are visible to efx_farch_flush_queues() */
smp_mb();
return (atomic_read(&efx->drain_pending) == 0 ||
return (atomic_read(&efx->active_queues) == 0 ||
(atomic_read(&efx->rxq_flush_outstanding) < EFX_RX_FLUSH_COUNT
&& atomic_read(&efx->rxq_flush_pending) > 0));
}
@ -626,7 +628,7 @@ static bool efx_check_tx_flush_complete(struct efx_nic *efx)
netif_dbg(efx, hw, efx->net_dev,
"flush complete on TXQ %d, so drain "
"the queue\n", tx_queue->queue);
/* Don't need to increment drain_pending as it
/* Don't need to increment active_queues as it
* has already been incremented for the queues
* which did not drain
*/
@ -653,17 +655,15 @@ static int efx_farch_do_flush(struct efx_nic *efx)
efx_for_each_channel(channel, efx) {
efx_for_each_channel_tx_queue(tx_queue, channel) {
atomic_inc(&efx->drain_pending);
efx_farch_flush_tx_queue(tx_queue);
}
efx_for_each_channel_rx_queue(rx_queue, channel) {
atomic_inc(&efx->drain_pending);
rx_queue->flush_pending = true;
atomic_inc(&efx->rxq_flush_pending);
}
}
while (timeout && atomic_read(&efx->drain_pending) > 0) {
while (timeout && atomic_read(&efx->active_queues) > 0) {
/* If SRIOV is enabled, then offload receive queue flushing to
* the firmware (though we will still have to poll for
* completion). If that fails, fall back to the old scheme.
@ -699,15 +699,15 @@ static int efx_farch_do_flush(struct efx_nic *efx)
timeout);
}
if (atomic_read(&efx->drain_pending) &&
if (atomic_read(&efx->active_queues) &&
!efx_check_tx_flush_complete(efx)) {
netif_err(efx, hw, efx->net_dev, "failed to flush %d queues "
"(rx %d+%d)\n", atomic_read(&efx->drain_pending),
"(rx %d+%d)\n", atomic_read(&efx->active_queues),
atomic_read(&efx->rxq_flush_outstanding),
atomic_read(&efx->rxq_flush_pending));
rc = -ETIMEDOUT;
atomic_set(&efx->drain_pending, 0);
atomic_set(&efx->active_queues, 0);
atomic_set(&efx->rxq_flush_pending, 0);
atomic_set(&efx->rxq_flush_outstanding, 0);
}
@ -1123,8 +1123,8 @@ efx_farch_handle_drain_event(struct efx_channel *channel)
{
struct efx_nic *efx = channel->efx;
WARN_ON(atomic_read(&efx->drain_pending) == 0);
atomic_dec(&efx->drain_pending);
WARN_ON(atomic_read(&efx->active_queues) == 0);
atomic_dec(&efx->active_queues);
if (efx_farch_flush_wake(efx))
wake_up(&efx->flush_wq);
}
@ -1325,7 +1325,7 @@ int efx_farch_ev_probe(struct efx_channel *channel)
entries * sizeof(efx_qword_t));
}
void efx_farch_ev_init(struct efx_channel *channel)
int efx_farch_ev_init(struct efx_channel *channel)
{
efx_oword_t reg;
struct efx_nic *efx = channel->efx;
@ -1357,7 +1357,7 @@ void efx_farch_ev_init(struct efx_channel *channel)
efx_writeo_table(efx, &reg, efx->type->evq_ptr_tbl_base,
channel->channel);
efx->type->push_irq_moderation(channel);
return 0;
}
void efx_farch_ev_fini(struct efx_channel *channel)

View File

@ -1,7 +1,7 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Driver for Solarflare network controllers and boards
* Copyright 2005-2006 Fen Systems Ltd.
* Copyright 2006-2010 Solarflare Communications Inc.
* Copyright 2006-2012 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published

View File

@ -1,6 +1,6 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Copyright 2005-2010 Solarflare Communications Inc.
* Driver for Solarflare network controllers and boards
* Copyright 2005-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published

View File

@ -1,7 +1,7 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Driver for Solarflare network controllers and boards
* Copyright 2005-2006 Fen Systems Ltd.
* Copyright 2006-2010 Solarflare Communications Inc.
* Copyright 2006-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@ -20,7 +20,7 @@
*
**************************************************************************
*
* Notes on locking strategy:
* Notes on locking strategy for the Falcon architecture:
*
* Many CSRs are very wide and cannot be read or written atomically.
* Writes from the host are buffered by the Bus Interface Unit (BIU)
@ -54,6 +54,12 @@
* register while the collector already holds values for some other
* register, the write is discarded and the collector maintains its
* current state.
*
* The EF10 architecture exposes very few registers to the host and
* most of them are only 32 bits wide. The only exceptions are the MC
* doorbell register pair, which has its own latching, and
* TX_DESC_UPD, which works in a similar way to the Falcon
* architecture.
*/
#if BITS_PER_LONG == 64
@ -237,8 +243,8 @@ static inline void _efx_writeo_page(struct efx_nic *efx, efx_oword_t *value,
BUILD_BUG_ON_ZERO((reg) != 0x830 && (reg) != 0xa10), \
page)
/* Write a page-mapped 32-bit CSR (EVQ_RPTR or the high bits of
* RX_DESC_UPD or TX_DESC_UPD)
/* Write a page-mapped 32-bit CSR (EVQ_RPTR, EVQ_TMR (EF10), or the
* high bits of RX_DESC_UPD or TX_DESC_UPD)
*/
static inline void
_efx_writed_page(struct efx_nic *efx, const efx_dword_t *value,
@ -249,8 +255,12 @@ _efx_writed_page(struct efx_nic *efx, const efx_dword_t *value,
#define efx_writed_page(efx, value, reg, page) \
_efx_writed_page(efx, value, \
reg + \
BUILD_BUG_ON_ZERO((reg) != 0x400 && (reg) != 0x83c \
&& (reg) != 0xa1c), \
BUILD_BUG_ON_ZERO((reg) != 0x400 && \
(reg) != 0x420 && \
(reg) != 0x830 && \
(reg) != 0x83c && \
(reg) != 0xa18 && \
(reg) != 0xa1c), \
page)
/* Write TIMER_COMMAND. This is a page-mapped 32-bit CSR, but a bug

View File

@ -1,6 +1,6 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Copyright 2008-2011 Solarflare Communications Inc.
* Driver for Solarflare network controllers and boards
* Copyright 2008-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@ -8,6 +8,7 @@
*/
#include <linux/delay.h>
#include <asm/cmpxchg.h>
#include "net_driver.h"
#include "nic.h"
#include "io.h"
@ -36,6 +37,20 @@
#define SEQ_MASK \
EFX_MASK32(EFX_WIDTH(MCDI_HEADER_SEQ))
struct efx_mcdi_async_param {
struct list_head list;
unsigned int cmd;
size_t inlen;
size_t outlen;
efx_mcdi_async_completer *complete;
unsigned long cookie;
/* followed by request/response buffer */
};
static void efx_mcdi_timeout_async(unsigned long context);
static int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
bool *was_attached_out);
static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx)
{
EFX_BUG_ON_PARANOID(!efx->mcdi);
@ -45,40 +60,76 @@ static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx)
int efx_mcdi_init(struct efx_nic *efx)
{
struct efx_mcdi_iface *mcdi;
bool already_attached;
int rc;
efx->mcdi = kzalloc(sizeof(*efx->mcdi), GFP_KERNEL);
if (!efx->mcdi)
return -ENOMEM;
mcdi = efx_mcdi(efx);
mcdi->efx = efx;
init_waitqueue_head(&mcdi->wq);
spin_lock_init(&mcdi->iface_lock);
atomic_set(&mcdi->state, MCDI_STATE_QUIESCENT);
mcdi->state = MCDI_STATE_QUIESCENT;
mcdi->mode = MCDI_MODE_POLL;
spin_lock_init(&mcdi->async_lock);
INIT_LIST_HEAD(&mcdi->async_list);
setup_timer(&mcdi->async_timer, efx_mcdi_timeout_async,
(unsigned long)mcdi);
(void) efx_mcdi_poll_reboot(efx);
mcdi->new_epoch = true;
/* Recover from a failed assertion before probing */
return efx_mcdi_handle_assertion(efx);
rc = efx_mcdi_handle_assertion(efx);
if (rc)
return rc;
/* Let the MC (and BMC, if this is a LOM) know that the driver
* is loaded. We should do this before we reset the NIC.
*/
rc = efx_mcdi_drv_attach(efx, true, &already_attached);
if (rc) {
netif_err(efx, probe, efx->net_dev,
"Unable to register driver with MCPU\n");
return rc;
}
if (already_attached)
/* Not a fatal error */
netif_err(efx, probe, efx->net_dev,
"Host already registered with MCPU\n");
return 0;
}
void efx_mcdi_fini(struct efx_nic *efx)
{
BUG_ON(efx->mcdi &&
atomic_read(&efx->mcdi->iface.state) != MCDI_STATE_QUIESCENT);
if (!efx->mcdi)
return;
BUG_ON(efx->mcdi->iface.state != MCDI_STATE_QUIESCENT);
/* Relinquish the device (back to the BMC, if this is a LOM) */
efx_mcdi_drv_attach(efx, false, NULL);
kfree(efx->mcdi);
}
static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd,
const efx_dword_t *inbuf, size_t inlen)
static void efx_mcdi_send_request(struct efx_nic *efx, unsigned cmd,
const efx_dword_t *inbuf, size_t inlen)
{
struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
efx_dword_t hdr[2];
size_t hdr_len;
u32 xflags, seqno;
BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT);
BUG_ON(mcdi->state == MCDI_STATE_QUIESCENT);
/* Serialise with efx_mcdi_ev_cpl() and efx_mcdi_ev_death() */
spin_lock_bh(&mcdi->iface_lock);
++mcdi->seqno;
spin_unlock_bh(&mcdi->iface_lock);
seqno = mcdi->seqno & SEQ_MASK;
xflags = 0;
@ -114,6 +165,8 @@ static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd,
}
efx->type->mcdi_request(efx, hdr, hdr_len, inbuf, inlen);
mcdi->new_epoch = false;
}
static int efx_mcdi_errno(unsigned int mcdi_err)
@ -246,25 +299,30 @@ int efx_mcdi_poll_reboot(struct efx_nic *efx)
return efx->type->mcdi_poll_reboot(efx);
}
static void efx_mcdi_acquire(struct efx_mcdi_iface *mcdi)
static bool efx_mcdi_acquire_async(struct efx_mcdi_iface *mcdi)
{
return cmpxchg(&mcdi->state,
MCDI_STATE_QUIESCENT, MCDI_STATE_RUNNING_ASYNC) ==
MCDI_STATE_QUIESCENT;
}
static void efx_mcdi_acquire_sync(struct efx_mcdi_iface *mcdi)
{
/* Wait until the interface becomes QUIESCENT and we win the race
* to mark it RUNNING. */
* to mark it RUNNING_SYNC.
*/
wait_event(mcdi->wq,
atomic_cmpxchg(&mcdi->state,
MCDI_STATE_QUIESCENT,
MCDI_STATE_RUNNING)
== MCDI_STATE_QUIESCENT);
cmpxchg(&mcdi->state,
MCDI_STATE_QUIESCENT, MCDI_STATE_RUNNING_SYNC) ==
MCDI_STATE_QUIESCENT);
}
static int efx_mcdi_await_completion(struct efx_nic *efx)
{
struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
if (wait_event_timeout(
mcdi->wq,
atomic_read(&mcdi->state) == MCDI_STATE_COMPLETED,
MCDI_RPC_TIMEOUT) == 0)
if (wait_event_timeout(mcdi->wq, mcdi->state == MCDI_STATE_COMPLETED,
MCDI_RPC_TIMEOUT) == 0)
return -ETIMEDOUT;
/* Check if efx_mcdi_set_mode() switched us back to polled completions.
@ -281,17 +339,14 @@ static int efx_mcdi_await_completion(struct efx_nic *efx)
return 0;
}
static bool efx_mcdi_complete(struct efx_mcdi_iface *mcdi)
/* If the interface is RUNNING_SYNC, switch to COMPLETED and wake the
* requester. Return whether this was done. Does not take any locks.
*/
static bool efx_mcdi_complete_sync(struct efx_mcdi_iface *mcdi)
{
/* If the interface is RUNNING, then move to COMPLETED and wake any
* waiters. If the interface isn't in RUNNING then we've received a
* duplicate completion after we've already transitioned back to
* QUIESCENT. [A subsequent invocation would increment seqno, so would
* have failed the seqno check].
*/
if (atomic_cmpxchg(&mcdi->state,
MCDI_STATE_RUNNING,
MCDI_STATE_COMPLETED) == MCDI_STATE_RUNNING) {
if (cmpxchg(&mcdi->state,
MCDI_STATE_RUNNING_SYNC, MCDI_STATE_COMPLETED) ==
MCDI_STATE_RUNNING_SYNC) {
wake_up(&mcdi->wq);
return true;
}
@ -301,10 +356,91 @@ static bool efx_mcdi_complete(struct efx_mcdi_iface *mcdi)
static void efx_mcdi_release(struct efx_mcdi_iface *mcdi)
{
atomic_set(&mcdi->state, MCDI_STATE_QUIESCENT);
if (mcdi->mode == MCDI_MODE_EVENTS) {
struct efx_mcdi_async_param *async;
struct efx_nic *efx = mcdi->efx;
/* Process the asynchronous request queue */
spin_lock_bh(&mcdi->async_lock);
async = list_first_entry_or_null(
&mcdi->async_list, struct efx_mcdi_async_param, list);
if (async) {
mcdi->state = MCDI_STATE_RUNNING_ASYNC;
efx_mcdi_send_request(efx, async->cmd,
(const efx_dword_t *)(async + 1),
async->inlen);
mod_timer(&mcdi->async_timer,
jiffies + MCDI_RPC_TIMEOUT);
}
spin_unlock_bh(&mcdi->async_lock);
if (async)
return;
}
mcdi->state = MCDI_STATE_QUIESCENT;
wake_up(&mcdi->wq);
}
/* If the interface is RUNNING_ASYNC, switch to COMPLETED, call the
* asynchronous completion function, and release the interface.
* Return whether this was done. Must be called in bh-disabled
* context. Will take iface_lock and async_lock.
*/
static bool efx_mcdi_complete_async(struct efx_mcdi_iface *mcdi, bool timeout)
{
struct efx_nic *efx = mcdi->efx;
struct efx_mcdi_async_param *async;
size_t hdr_len, data_len;
efx_dword_t *outbuf;
int rc;
if (cmpxchg(&mcdi->state,
MCDI_STATE_RUNNING_ASYNC, MCDI_STATE_COMPLETED) !=
MCDI_STATE_RUNNING_ASYNC)
return false;
spin_lock(&mcdi->iface_lock);
if (timeout) {
/* Ensure that if the completion event arrives later,
* the seqno check in efx_mcdi_ev_cpl() will fail
*/
++mcdi->seqno;
++mcdi->credits;
rc = -ETIMEDOUT;
hdr_len = 0;
data_len = 0;
} else {
rc = mcdi->resprc;
hdr_len = mcdi->resp_hdr_len;
data_len = mcdi->resp_data_len;
}
spin_unlock(&mcdi->iface_lock);
/* Stop the timer. In case the timer function is running, we
* must wait for it to return so that there is no possibility
* of it aborting the next request.
*/
if (!timeout)
del_timer_sync(&mcdi->async_timer);
spin_lock(&mcdi->async_lock);
async = list_first_entry(&mcdi->async_list,
struct efx_mcdi_async_param, list);
list_del(&async->list);
spin_unlock(&mcdi->async_lock);
outbuf = (efx_dword_t *)(async + 1);
efx->type->mcdi_read_response(efx, outbuf, hdr_len,
min(async->outlen, data_len));
async->complete(efx, async->cookie, rc, outbuf, data_len);
kfree(async);
efx_mcdi_release(mcdi);
return true;
}
static void efx_mcdi_ev_cpl(struct efx_nic *efx, unsigned int seqno,
unsigned int datalen, unsigned int mcdi_err)
{
@ -336,8 +472,40 @@ static void efx_mcdi_ev_cpl(struct efx_nic *efx, unsigned int seqno,
spin_unlock(&mcdi->iface_lock);
if (wake)
efx_mcdi_complete(mcdi);
if (wake) {
if (!efx_mcdi_complete_async(mcdi, false))
(void) efx_mcdi_complete_sync(mcdi);
/* If the interface isn't RUNNING_ASYNC or
* RUNNING_SYNC then we've received a duplicate
* completion after we've already transitioned back to
* QUIESCENT. [A subsequent invocation would increment
* seqno, so would have failed the seqno check].
*/
}
}
static void efx_mcdi_timeout_async(unsigned long context)
{
struct efx_mcdi_iface *mcdi = (struct efx_mcdi_iface *)context;
efx_mcdi_complete_async(mcdi, true);
}
static int
efx_mcdi_check_supported(struct efx_nic *efx, unsigned int cmd, size_t inlen)
{
if (efx->type->mcdi_max_ver < 0 ||
(efx->type->mcdi_max_ver < 2 &&
cmd > MC_CMD_CMD_SPACE_ESCAPE_7))
return -EINVAL;
if (inlen > MCDI_CTL_SDU_LEN_MAX_V2 ||
(efx->type->mcdi_max_ver < 2 &&
inlen > MCDI_CTL_SDU_LEN_MAX_V1))
return -EMSGSIZE;
return 0;
}
int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd,
@ -358,29 +526,86 @@ int efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd,
const efx_dword_t *inbuf, size_t inlen)
{
struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
int rc;
if (efx->type->mcdi_max_ver < 0 ||
(efx->type->mcdi_max_ver < 2 &&
cmd > MC_CMD_CMD_SPACE_ESCAPE_7))
return -EINVAL;
rc = efx_mcdi_check_supported(efx, cmd, inlen);
if (rc)
return rc;
if (inlen > MCDI_CTL_SDU_LEN_MAX_V2 ||
(efx->type->mcdi_max_ver < 2 &&
inlen > MCDI_CTL_SDU_LEN_MAX_V1))
return -EMSGSIZE;
efx_mcdi_acquire(mcdi);
/* Serialise with efx_mcdi_ev_cpl() and efx_mcdi_ev_death() */
spin_lock_bh(&mcdi->iface_lock);
++mcdi->seqno;
spin_unlock_bh(&mcdi->iface_lock);
efx_mcdi_copyin(efx, cmd, inbuf, inlen);
mcdi->new_epoch = false;
efx_mcdi_acquire_sync(mcdi);
efx_mcdi_send_request(efx, cmd, inbuf, inlen);
return 0;
}
/**
* efx_mcdi_rpc_async - Schedule an MCDI command to run asynchronously
* @efx: NIC through which to issue the command
* @cmd: Command type number
* @inbuf: Command parameters
* @inlen: Length of command parameters, in bytes
* @outlen: Length to allocate for response buffer, in bytes
* @complete: Function to be called on completion or cancellation.
* @cookie: Arbitrary value to be passed to @complete.
*
* This function does not sleep and therefore may be called in atomic
* context. It will fail if event queues are disabled or if MCDI
* event completions have been disabled due to an error.
*
* If it succeeds, the @complete function will be called exactly once
* in atomic context, when one of the following occurs:
* (a) the completion event is received (in NAPI context)
* (b) event queues are disabled (in the process that disables them)
* (c) the request times-out (in timer context)
*/
int
efx_mcdi_rpc_async(struct efx_nic *efx, unsigned int cmd,
const efx_dword_t *inbuf, size_t inlen, size_t outlen,
efx_mcdi_async_completer *complete, unsigned long cookie)
{
struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
struct efx_mcdi_async_param *async;
int rc;
rc = efx_mcdi_check_supported(efx, cmd, inlen);
if (rc)
return rc;
async = kmalloc(sizeof(*async) + ALIGN(max(inlen, outlen), 4),
GFP_ATOMIC);
if (!async)
return -ENOMEM;
async->cmd = cmd;
async->inlen = inlen;
async->outlen = outlen;
async->complete = complete;
async->cookie = cookie;
memcpy(async + 1, inbuf, inlen);
spin_lock_bh(&mcdi->async_lock);
if (mcdi->mode == MCDI_MODE_EVENTS) {
list_add_tail(&async->list, &mcdi->async_list);
/* If this is at the front of the queue, try to start it
* immediately
*/
if (mcdi->async_list.next == &async->list &&
efx_mcdi_acquire_async(mcdi)) {
efx_mcdi_send_request(efx, cmd, inbuf, inlen);
mod_timer(&mcdi->async_timer,
jiffies + MCDI_RPC_TIMEOUT);
}
} else {
kfree(async);
rc = -ENETDOWN;
}
spin_unlock_bh(&mcdi->async_lock);
return rc;
}
int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
efx_dword_t *outbuf, size_t outlen,
size_t *outlen_actual)
@ -448,6 +673,10 @@ int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
return rc;
}
/* Switch to polled MCDI completions. This can be called in various
* error conditions with various locks held, so it must be lockless.
* Caller is responsible for flushing asynchronous requests later.
*/
void efx_mcdi_mode_poll(struct efx_nic *efx)
{
struct efx_mcdi_iface *mcdi;
@ -465,11 +694,50 @@ void efx_mcdi_mode_poll(struct efx_nic *efx)
* efx_mcdi_await_completion() will then call efx_mcdi_poll().
*
* We need an smp_wmb() to synchronise with efx_mcdi_await_completion(),
* which efx_mcdi_complete() provides for us.
* which efx_mcdi_complete_sync() provides for us.
*/
mcdi->mode = MCDI_MODE_POLL;
efx_mcdi_complete(mcdi);
efx_mcdi_complete_sync(mcdi);
}
/* Flush any running or queued asynchronous requests, after event processing
* is stopped
*/
void efx_mcdi_flush_async(struct efx_nic *efx)
{
struct efx_mcdi_async_param *async, *next;
struct efx_mcdi_iface *mcdi;
if (!efx->mcdi)
return;
mcdi = efx_mcdi(efx);
/* We must be in polling mode so no more requests can be queued */
BUG_ON(mcdi->mode != MCDI_MODE_POLL);
del_timer_sync(&mcdi->async_timer);
/* If a request is still running, make sure we give the MC
* time to complete it so that the response won't overwrite our
* next request.
*/
if (mcdi->state == MCDI_STATE_RUNNING_ASYNC) {
efx_mcdi_poll(efx);
mcdi->state = MCDI_STATE_QUIESCENT;
}
/* Nothing else will access the async list now, so it is safe
* to walk it without holding async_lock. If we hold it while
* calling a completer then lockdep may warn that we have
* acquired locks in the wrong order.
*/
list_for_each_entry_safe(async, next, &mcdi->async_list, list) {
async->complete(efx, async->cookie, -ENETDOWN, NULL, 0);
list_del(&async->list);
kfree(async);
}
}
void efx_mcdi_mode_event(struct efx_nic *efx)
@ -491,7 +759,7 @@ void efx_mcdi_mode_event(struct efx_nic *efx)
* write memory barrier ensure that efx_mcdi_rpc() sees it, which
* efx_mcdi_acquire() provides.
*/
efx_mcdi_acquire(mcdi);
efx_mcdi_acquire_sync(mcdi);
mcdi->mode = MCDI_MODE_EVENTS;
efx_mcdi_release(mcdi);
}
@ -508,16 +776,21 @@ static void efx_mcdi_ev_death(struct efx_nic *efx, int rc)
* are sent to the same queue, we can't be racing with
* efx_mcdi_ev_cpl()]
*
* There's a race here with efx_mcdi_rpc(), because we might receive
* a REBOOT event *before* the request has been copied out. In polled
* mode (during startup) this is irrelevant, because efx_mcdi_complete()
* is ignored. In event mode, this condition is just an edge-case of
* receiving a REBOOT event after posting the MCDI request. Did the mc
* reboot before or after the copyout? The best we can do always is
* just return failure.
* If there is an outstanding asynchronous request, we can't
* complete it now (efx_mcdi_complete() would deadlock). The
* reset process will take care of this.
*
* There's a race here with efx_mcdi_send_request(), because
* we might receive a REBOOT event *before* the request has
* been copied out. In polled mode (during startup) this is
* irrelevant, because efx_mcdi_complete_sync() is ignored. In
* event mode, this condition is just an edge-case of
* receiving a REBOOT event after posting the MCDI
* request. Did the mc reboot before or after the copyout? The
* best we can do always is just return failure.
*/
spin_lock(&mcdi->iface_lock);
if (efx_mcdi_complete(mcdi)) {
if (efx_mcdi_complete_sync(mcdi)) {
if (mcdi->mode == MCDI_MODE_EVENTS) {
mcdi->resprc = rc;
mcdi->resp_hdr_len = 0;
@ -579,6 +852,7 @@ void efx_mcdi_process_event(struct efx_channel *channel,
"MC Scheduler error address=0x%x\n", data);
break;
case MCDI_EVENT_CODE_REBOOT:
case MCDI_EVENT_CODE_MC_REBOOT:
netif_info(efx, hw, efx->net_dev, "MC Reboot\n");
efx_mcdi_ev_death(efx, -EIO);
break;
@ -593,7 +867,19 @@ void efx_mcdi_process_event(struct efx_channel *channel,
case MCDI_EVENT_CODE_PTP_PPS:
efx_ptp_event(efx, event);
break;
case MCDI_EVENT_CODE_TX_FLUSH:
case MCDI_EVENT_CODE_RX_FLUSH:
/* Two flush events will be sent: one to the same event
* queue as completions, and one to event queue 0.
* In the latter case the {RX,TX}_FLUSH_TO_DRIVER
* flag will be set, and we should ignore the event
* because we want to wait for all completions.
*/
BUILD_BUG_ON(MCDI_EVENT_TX_FLUSH_TO_DRIVER_LBN !=
MCDI_EVENT_RX_FLUSH_TO_DRIVER_LBN);
if (!MCDI_EVENT_FIELD(*event, TX_FLUSH_TO_DRIVER))
efx_ef10_handle_drain_event(efx);
break;
case MCDI_EVENT_CODE_TX_ERR:
case MCDI_EVENT_CODE_RX_ERR:
netif_err(efx, hw, efx->net_dev,
@ -617,27 +903,55 @@ void efx_mcdi_process_event(struct efx_channel *channel,
void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len)
{
MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_VERSION_OUT_LEN);
MCDI_DECLARE_BUF(outbuf,
max(MC_CMD_GET_VERSION_OUT_LEN,
MC_CMD_GET_CAPABILITIES_OUT_LEN));
size_t outlength;
const __le16 *ver_words;
size_t offset;
int rc;
BUILD_BUG_ON(MC_CMD_GET_VERSION_IN_LEN != 0);
rc = efx_mcdi_rpc(efx, MC_CMD_GET_VERSION, NULL, 0,
outbuf, sizeof(outbuf), &outlength);
if (rc)
goto fail;
if (outlength < MC_CMD_GET_VERSION_OUT_LEN) {
rc = -EIO;
goto fail;
}
ver_words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_OUT_VERSION);
snprintf(buf, len, "%u.%u.%u.%u",
le16_to_cpu(ver_words[0]), le16_to_cpu(ver_words[1]),
le16_to_cpu(ver_words[2]), le16_to_cpu(ver_words[3]));
offset = snprintf(buf, len, "%u.%u.%u.%u",
le16_to_cpu(ver_words[0]), le16_to_cpu(ver_words[1]),
le16_to_cpu(ver_words[2]), le16_to_cpu(ver_words[3]));
/* EF10 may have multiple datapath firmware variants within a
* single version. Report which variants are running.
*/
if (efx_nic_rev(efx) >= EFX_REV_HUNT_A0) {
BUILD_BUG_ON(MC_CMD_GET_CAPABILITIES_IN_LEN != 0);
rc = efx_mcdi_rpc(efx, MC_CMD_GET_CAPABILITIES, NULL, 0,
outbuf, sizeof(outbuf), &outlength);
if (rc || outlength < MC_CMD_GET_CAPABILITIES_OUT_LEN)
offset += snprintf(
buf + offset, len - offset, " rx? tx?");
else
offset += snprintf(
buf + offset, len - offset, " rx%x tx%x",
MCDI_WORD(outbuf,
GET_CAPABILITIES_OUT_RX_DPCPU_FW_ID),
MCDI_WORD(outbuf,
GET_CAPABILITIES_OUT_TX_DPCPU_FW_ID));
/* It's theoretically possible for the string to exceed 31
* characters, though in practice the first three version
* components are short enough that this doesn't happen.
*/
if (WARN_ON(offset >= len))
buf[0] = 0;
}
return;
fail:
@ -645,8 +959,8 @@ fail:
buf[0] = 0;
}
int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
bool *was_attached)
static int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
bool *was_attached)
{
MCDI_DECLARE_BUF(inbuf, MC_CMD_DRV_ATTACH_IN_LEN);
MCDI_DECLARE_BUF(outbuf, MC_CMD_DRV_ATTACH_OUT_LEN);
@ -1157,6 +1471,17 @@ fail:
return rc;
}
int efx_mcdi_set_workaround(struct efx_nic *efx, u32 type, bool enabled)
{
MCDI_DECLARE_BUF(inbuf, MC_CMD_WORKAROUND_IN_LEN);
BUILD_BUG_ON(MC_CMD_WORKAROUND_OUT_LEN != 0);
MCDI_SET_DWORD(inbuf, WORKAROUND_IN_TYPE, type);
MCDI_SET_DWORD(inbuf, WORKAROUND_IN_ENABLED, enabled);
return efx_mcdi_rpc(efx, MC_CMD_WORKAROUND, inbuf, sizeof(inbuf),
NULL, 0, NULL);
}
#ifdef CONFIG_SFC_MTD
#define EFX_MCDI_NVRAM_LEN_MAX 128

View File

@ -1,6 +1,6 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Copyright 2008-2010 Solarflare Communications Inc.
* Driver for Solarflare network controllers and boards
* Copyright 2008-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@ -14,15 +14,17 @@
* enum efx_mcdi_state - MCDI request handling state
* @MCDI_STATE_QUIESCENT: No pending MCDI requests. If the caller holds the
* mcdi @iface_lock then they are able to move to %MCDI_STATE_RUNNING
* @MCDI_STATE_RUNNING: There is an MCDI request pending. Only the thread that
* moved into this state is allowed to move out of it.
* @MCDI_STATE_RUNNING_SYNC: There is a synchronous MCDI request pending.
* Only the thread that moved into this state is allowed to move out of it.
* @MCDI_STATE_RUNNING_ASYNC: There is an asynchronous MCDI request pending.
* @MCDI_STATE_COMPLETED: An MCDI request has completed, but the owning thread
* has not yet consumed the result. For all other threads, equivalent to
* %MCDI_STATE_RUNNING.
*/
enum efx_mcdi_state {
MCDI_STATE_QUIESCENT,
MCDI_STATE_RUNNING,
MCDI_STATE_RUNNING_SYNC,
MCDI_STATE_RUNNING_ASYNC,
MCDI_STATE_COMPLETED,
};
@ -33,20 +35,26 @@ enum efx_mcdi_mode {
/**
* struct efx_mcdi_iface - MCDI protocol context
* @efx: The associated NIC.
* @state: Request handling state. Waited for by @wq.
* @mode: Poll for mcdi completion, or wait for an mcdi_event.
* @wq: Wait queue for threads waiting for @state != %MCDI_STATE_RUNNING
* @new_epoch: Indicates start of day or start of MC reboot recovery
* @iface_lock: Serialises access to all the following fields
* @iface_lock: Serialises access to @seqno, @credits and response metadata
* @seqno: The next sequence number to use for mcdi requests.
* @credits: Number of spurious MCDI completion events allowed before we
* trigger a fatal error
* @resprc: Response error/success code (Linux numbering)
* @resp_hdr_len: Response header length
* @resp_data_len: Response data (SDU or error) length
* @async_lock: Serialises access to @async_list while event processing is
* enabled
* @async_list: Queue of asynchronous requests
* @async_timer: Timer for asynchronous request timeout
*/
struct efx_mcdi_iface {
atomic_t state;
struct efx_nic *efx;
enum efx_mcdi_state state;
enum efx_mcdi_mode mode;
wait_queue_head_t wq;
spinlock_t iface_lock;
@ -56,6 +64,9 @@ struct efx_mcdi_iface {
int resprc;
size_t resp_hdr_len;
size_t resp_data_len;
spinlock_t async_lock;
struct list_head async_list;
struct timer_list async_timer;
};
struct efx_mcdi_mon {
@ -70,7 +81,7 @@ struct efx_mcdi_mon {
struct efx_mcdi_mtd_partition {
struct efx_mtd_partition common;
bool updating;
u8 nvram_type;
u16 nvram_type;
u16 fw_subtype;
};
@ -111,10 +122,20 @@ extern int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
efx_dword_t *outbuf, size_t outlen,
size_t *outlen_actual);
typedef void efx_mcdi_async_completer(struct efx_nic *efx,
unsigned long cookie, int rc,
efx_dword_t *outbuf,
size_t outlen_actual);
extern int efx_mcdi_rpc_async(struct efx_nic *efx, unsigned int cmd,
const efx_dword_t *inbuf, size_t inlen,
size_t outlen,
efx_mcdi_async_completer *complete,
unsigned long cookie);
extern int efx_mcdi_poll_reboot(struct efx_nic *efx);
extern void efx_mcdi_mode_poll(struct efx_nic *efx);
extern void efx_mcdi_mode_event(struct efx_nic *efx);
extern void efx_mcdi_flush_async(struct efx_nic *efx);
extern void efx_mcdi_process_event(struct efx_channel *channel,
efx_qword_t *event);
@ -136,6 +157,9 @@ extern void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
#define _MCDI_DWORD(_buf, _field) \
((_buf) + (_MCDI_CHECK_ALIGN(MC_CMD_ ## _field ## _OFST, 4) >> 2))
#define MCDI_WORD(_buf, _field) \
((u16)BUILD_BUG_ON_ZERO(MC_CMD_ ## _field ## _LEN != 2) + \
le16_to_cpu(*(__force const __le16 *)MCDI_PTR(_buf, _field)))
#define MCDI_SET_DWORD(_buf, _field, _value) \
EFX_POPULATE_DWORD_1(*_MCDI_DWORD(_buf, _field), EFX_DWORD_0, _value)
#define MCDI_DWORD(_buf, _field) \
@ -252,8 +276,6 @@ extern void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
EFX_QWORD_FIELD(_ev, MCDI_EVENT_ ## _field)
extern void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len);
extern int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
bool *was_attached_out);
extern int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address,
u16 *fw_subtype_list, u32 *capabilities);
extern int efx_mcdi_log_ctrl(struct efx_nic *efx, bool evq, bool uart,
@ -274,6 +296,8 @@ extern int efx_mcdi_flush_rxqs(struct efx_nic *efx);
extern int efx_mcdi_port_probe(struct efx_nic *efx);
extern void efx_mcdi_port_remove(struct efx_nic *efx);
extern int efx_mcdi_port_reconfigure(struct efx_nic *efx);
extern int efx_mcdi_port_get_number(struct efx_nic *efx);
extern u32 efx_mcdi_phy_get_caps(struct efx_nic *efx);
extern void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev);
extern int efx_mcdi_set_mac(struct efx_nic *efx);
#define EFX_MC_STATS_GENERATION_INVALID ((__force __le64)(-1))
@ -282,6 +306,7 @@ extern void efx_mcdi_mac_stop_stats(struct efx_nic *efx);
extern bool efx_mcdi_mac_check_fault(struct efx_nic *efx);
extern enum reset_type efx_mcdi_map_reset_reason(enum reset_type reason);
extern int efx_mcdi_reset(struct efx_nic *efx, enum reset_type method);
extern int efx_mcdi_set_workaround(struct efx_nic *efx, u32 type, bool enabled);
#ifdef CONFIG_SFC_MCDI_MON
extern int efx_mcdi_mon_probe(struct efx_nic *efx);

View File

@ -1,6 +1,6 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Copyright 2011 Solarflare Communications Inc.
* Driver for Solarflare network controllers and boards
* Copyright 2011-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@ -21,7 +21,9 @@ enum efx_hwmon_type {
EFX_HWMON_UNKNOWN,
EFX_HWMON_TEMP, /* temperature */
EFX_HWMON_COOL, /* cooling device, probably a heatsink */
EFX_HWMON_IN /* input voltage */
EFX_HWMON_IN, /* voltage */
EFX_HWMON_CURR, /* current */
EFX_HWMON_POWER, /* power */
};
static const struct {
@ -29,23 +31,52 @@ static const struct {
enum efx_hwmon_type hwmon_type;
int port;
} efx_mcdi_sensor_type[] = {
#define SENSOR(name, label, hwmon_type, port) \
[MC_CMD_SENSOR_##name] = { label, hwmon_type, port }
SENSOR(CONTROLLER_TEMP, "Controller temp.", EFX_HWMON_TEMP, -1),
SENSOR(PHY_COMMON_TEMP, "PHY temp.", EFX_HWMON_TEMP, -1),
SENSOR(CONTROLLER_COOLING, "Controller cooling", EFX_HWMON_COOL, -1),
SENSOR(PHY0_TEMP, "PHY temp.", EFX_HWMON_TEMP, 0),
SENSOR(PHY0_COOLING, "PHY cooling", EFX_HWMON_COOL, 0),
SENSOR(PHY1_TEMP, "PHY temp.", EFX_HWMON_TEMP, 1),
SENSOR(PHY1_COOLING, "PHY cooling", EFX_HWMON_COOL, 1),
SENSOR(IN_1V0, "1.0V supply", EFX_HWMON_IN, -1),
SENSOR(IN_1V2, "1.2V supply", EFX_HWMON_IN, -1),
SENSOR(IN_1V8, "1.8V supply", EFX_HWMON_IN, -1),
SENSOR(IN_2V5, "2.5V supply", EFX_HWMON_IN, -1),
SENSOR(IN_3V3, "3.3V supply", EFX_HWMON_IN, -1),
SENSOR(IN_12V0, "12.0V supply", EFX_HWMON_IN, -1),
SENSOR(IN_1V2A, "1.2V analogue supply", EFX_HWMON_IN, -1),
SENSOR(IN_VREF, "ref. voltage", EFX_HWMON_IN, -1),
#define SENSOR(name, label, hwmon_type, port) \
[MC_CMD_SENSOR_##name] = { label, EFX_HWMON_ ## hwmon_type, port }
SENSOR(CONTROLLER_TEMP, "Controller ext. temp.", TEMP, -1),
SENSOR(PHY_COMMON_TEMP, "PHY temp.", TEMP, -1),
SENSOR(CONTROLLER_COOLING, "Controller cooling", COOL, -1),
SENSOR(PHY0_TEMP, "PHY temp.", TEMP, 0),
SENSOR(PHY0_COOLING, "PHY cooling", COOL, 0),
SENSOR(PHY1_TEMP, "PHY temp.", TEMP, 1),
SENSOR(PHY1_COOLING, "PHY cooling", COOL, 1),
SENSOR(IN_1V0, "1.0V supply", IN, -1),
SENSOR(IN_1V2, "1.2V supply", IN, -1),
SENSOR(IN_1V8, "1.8V supply", IN, -1),
SENSOR(IN_2V5, "2.5V supply", IN, -1),
SENSOR(IN_3V3, "3.3V supply", IN, -1),
SENSOR(IN_12V0, "12.0V supply", IN, -1),
SENSOR(IN_1V2A, "1.2V analogue supply", IN, -1),
SENSOR(IN_VREF, "ref. voltage", IN, -1),
SENSOR(OUT_VAOE, "AOE power supply", IN, -1),
SENSOR(AOE_TEMP, "AOE temp.", TEMP, -1),
SENSOR(PSU_AOE_TEMP, "AOE PSU temp.", TEMP, -1),
SENSOR(PSU_TEMP, "Controller PSU temp.", TEMP, -1),
SENSOR(FAN_0, NULL, COOL, -1),
SENSOR(FAN_1, NULL, COOL, -1),
SENSOR(FAN_2, NULL, COOL, -1),
SENSOR(FAN_3, NULL, COOL, -1),
SENSOR(FAN_4, NULL, COOL, -1),
SENSOR(IN_VAOE, "AOE input supply", IN, -1),
SENSOR(OUT_IAOE, "AOE output current", CURR, -1),
SENSOR(IN_IAOE, "AOE input current", CURR, -1),
SENSOR(NIC_POWER, "Board power use", POWER, -1),
SENSOR(IN_0V9, "0.9V supply", IN, -1),
SENSOR(IN_I0V9, "0.9V input current", CURR, -1),
SENSOR(IN_I1V2, "1.2V input current", CURR, -1),
SENSOR(IN_0V9_ADC, "0.9V supply (at ADC)", IN, -1),
SENSOR(CONTROLLER_2_TEMP, "Controller ext. temp. 2", TEMP, -1),
SENSOR(VREG_INTERNAL_TEMP, "Voltage regulator temp.", TEMP, -1),
SENSOR(VREG_0V9_TEMP, "0.9V regulator temp.", TEMP, -1),
SENSOR(VREG_1V2_TEMP, "1.2V regulator temp.", TEMP, -1),
SENSOR(CONTROLLER_VPTAT, "Controller int. temp. raw", IN, -1),
SENSOR(CONTROLLER_INTERNAL_TEMP, "Controller int. temp.", TEMP, -1),
SENSOR(CONTROLLER_VPTAT_EXTADC,
"Controller int. temp. raw (at ADC)", IN, -1),
SENSOR(CONTROLLER_INTERNAL_TEMP_EXTADC,
"Controller int. temp. (via ADC)", TEMP, -1),
SENSOR(AMBIENT_TEMP, "Ambient temp.", TEMP, -1),
SENSOR(AIRFLOW, "Air flow raw", IN, -1),
#undef SENSOR
};
@ -160,9 +191,19 @@ static ssize_t efx_mcdi_mon_show_value(struct device *dev,
value = EFX_DWORD_FIELD(entry, MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE);
/* Convert temperature from degrees to milli-degrees Celsius */
if (mon_attr->hwmon_type == EFX_HWMON_TEMP)
switch (mon_attr->hwmon_type) {
case EFX_HWMON_TEMP:
/* Convert temperature from degrees to milli-degrees Celsius */
value *= 1000;
break;
case EFX_HWMON_POWER:
/* Convert power from watts to microwatts */
value *= 1000000;
break;
default:
/* No conversion needed */
break;
}
return sprintf(buf, "%u\n", value);
}
@ -177,9 +218,19 @@ static ssize_t efx_mcdi_mon_show_limit(struct device *dev,
value = mon_attr->limit_value;
/* Convert temperature from degrees to milli-degrees Celsius */
if (mon_attr->hwmon_type == EFX_HWMON_TEMP)
switch (mon_attr->hwmon_type) {
case EFX_HWMON_TEMP:
/* Convert temperature from degrees to milli-degrees Celsius */
value *= 1000;
break;
case EFX_HWMON_POWER:
/* Convert power from watts to microwatts */
value *= 1000000;
break;
default:
/* No conversion needed */
break;
}
return sprintf(buf, "%u\n", value);
}
@ -243,8 +294,8 @@ efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name,
int efx_mcdi_mon_probe(struct efx_nic *efx)
{
unsigned int n_temp = 0, n_cool = 0, n_in = 0, n_curr = 0, n_power = 0;
struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
unsigned int n_temp = 0, n_cool = 0, n_in = 0;
MCDI_DECLARE_BUF(inbuf, MC_CMD_SENSOR_INFO_EXT_IN_LEN);
MCDI_DECLARE_BUF(outbuf, MC_CMD_SENSOR_INFO_OUT_LENMAX);
unsigned int n_pages, n_sensors, n_attrs, page;
@ -380,6 +431,14 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
hwmon_prefix = "in";
hwmon_index = n_in++; /* 0-based */
break;
case EFX_HWMON_CURR:
hwmon_prefix = "curr";
hwmon_index = ++n_curr; /* 1-based */
break;
case EFX_HWMON_POWER:
hwmon_prefix = "power";
hwmon_index = ++n_power; /* 1-based */
break;
}
min1 = MCDI_ARRAY_FIELD(outbuf, SENSOR_ENTRY,
@ -399,13 +458,15 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
if (rc)
goto fail;
snprintf(name, sizeof(name), "%s%u_min",
hwmon_prefix, hwmon_index);
rc = efx_mcdi_mon_add_attr(
efx, name, efx_mcdi_mon_show_limit,
i, type, min1);
if (rc)
goto fail;
if (hwmon_type != EFX_HWMON_POWER) {
snprintf(name, sizeof(name), "%s%u_min",
hwmon_prefix, hwmon_index);
rc = efx_mcdi_mon_add_attr(
efx, name, efx_mcdi_mon_show_limit,
i, type, min1);
if (rc)
goto fail;
}
snprintf(name, sizeof(name), "%s%u_max",
hwmon_prefix, hwmon_index);

View File

@ -3799,6 +3799,10 @@
#define NVRAM_PARTITION_TYPE_DUMP 0x800
/* enum: Application license key storage partition */
#define NVRAM_PARTITION_TYPE_LICENSE 0x900
/* enum: Start of range used for PHY partitions (low 8 bits are the PHY ID) */
#define NVRAM_PARTITION_TYPE_PHY_MIN 0xa00
/* enum: End of range used for PHY partitions (low 8 bits are the PHY ID) */
#define NVRAM_PARTITION_TYPE_PHY_MAX 0xaff
/* enum: Start of reserved value range (firmware may use for any purpose) */
#define NVRAM_PARTITION_TYPE_RESERVED_VALUES_MIN 0xff00
/* enum: End of reserved value range (firmware may use for any purpose) */

View File

@ -1,6 +1,6 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Copyright 2009-2010 Solarflare Communications Inc.
* Driver for Solarflare network controllers and boards
* Copyright 2009-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@ -830,6 +830,13 @@ static const struct efx_phy_operations efx_mcdi_phy_ops = {
.get_module_info = efx_mcdi_phy_get_module_info,
};
u32 efx_mcdi_phy_get_caps(struct efx_nic *efx)
{
struct efx_mcdi_phy_data *phy_data = efx->phy_data;
return phy_data->supported_cap;
}
static unsigned int efx_mcdi_event_link_speed[] = {
[MCDI_EVENT_LINKCHANGE_SPEED_100M] = 100,
[MCDI_EVENT_LINKCHANGE_SPEED_1G] = 1000,
@ -1004,3 +1011,17 @@ void efx_mcdi_port_remove(struct efx_nic *efx)
efx->phy_op->remove(efx);
efx_nic_free_buffer(efx, &efx->stats_buffer);
}
/* Get physical port number (EF10 only; on Siena it is same as PF number) */
int efx_mcdi_port_get_number(struct efx_nic *efx)
{
MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN);
int rc;
rc = efx_mcdi_rpc(efx, MC_CMD_GET_PORT_ASSIGNMENT, NULL, 0,
outbuf, sizeof(outbuf), NULL);
if (rc)
return rc;
return MCDI_DWORD(outbuf, GET_PORT_ASSIGNMENT_OUT_PORT);
}

View File

@ -1,5 +1,5 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Driver for Solarflare network controllers and boards
* Copyright 2006-2011 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it

View File

@ -1,5 +1,5 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Driver for Solarflare network controllers and boards
* Copyright 2006-2011 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it

View File

@ -1,7 +1,7 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Driver for Solarflare network controllers and boards
* Copyright 2005-2006 Fen Systems Ltd.
* Copyright 2006-2010 Solarflare Communications Inc.
* Copyright 2006-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published

View File

@ -1,7 +1,7 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Driver for Solarflare network controllers and boards
* Copyright 2005-2006 Fen Systems Ltd.
* Copyright 2005-2011 Solarflare Communications Inc.
* Copyright 2005-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@ -39,7 +39,7 @@
*
**************************************************************************/
#define EFX_DRIVER_VERSION "3.2"
#define EFX_DRIVER_VERSION "4.0"
#ifdef DEBUG
#define EFX_BUG_ON_PARANOID(x) BUG_ON(x)
@ -135,6 +135,7 @@ struct efx_special_buffer {
* freed when descriptor completes
* @heap_buf: When @flags & %EFX_TX_BUF_HEAP, the associated heap buffer to be
* freed when descriptor completes.
* @option: When @flags & %EFX_TX_BUF_OPTION, a NIC-specific option descriptor.
* @dma_addr: DMA address of the fragment.
* @flags: Flags for allocation and DMA mapping type
* @len: Length of this fragment.
@ -146,7 +147,10 @@ struct efx_tx_buffer {
const struct sk_buff *skb;
void *heap_buf;
};
dma_addr_t dma_addr;
union {
efx_qword_t option;
dma_addr_t dma_addr;
};
unsigned short flags;
unsigned short len;
unsigned short unmap_len;
@ -155,6 +159,7 @@ struct efx_tx_buffer {
#define EFX_TX_BUF_SKB 2 /* buffer is last part of skb */
#define EFX_TX_BUF_HEAP 4 /* buffer was allocated with kmalloc() */
#define EFX_TX_BUF_MAP_SINGLE 8 /* buffer was mapped with dma_map_single() */
#define EFX_TX_BUF_OPTION 0x10 /* empty buffer for option descriptor */
/**
* struct efx_tx_queue - An Efx TX queue
@ -297,7 +302,8 @@ struct efx_rx_page_state {
* @added_count: Number of buffers added to the receive queue.
* @notified_count: Number of buffers given to NIC (<= @added_count).
* @removed_count: Number of buffers removed from the receive queue.
* @scatter_n: Number of buffers used by current packet
* @scatter_n: Used by NIC specific receive code.
* @scatter_len: Used by NIC specific receive code.
* @page_ring: The ring to store DMA mapped pages for reuse.
* @page_add: Counter to calculate the write pointer for the recycle ring.
* @page_remove: Counter to calculate the read pointer for the recycle ring.
@ -329,6 +335,7 @@ struct efx_rx_queue {
unsigned int notified_count;
unsigned int removed_count;
unsigned int scatter_n;
unsigned int scatter_len;
struct page **page_ring;
unsigned int page_add;
unsigned int page_remove;
@ -382,6 +389,8 @@ enum efx_rx_alloc_method {
* @n_skbuff_leaks: Count of skbuffs leaked due to RX overrun
* @n_rx_nodesc_trunc: Number of RX packets truncated and then dropped due to
* lack of descriptors
* @n_rx_merge_events: Number of RX merged completion events
* @n_rx_merge_packets: Number of RX packets completed by merged events
* @rx_pkt_n_frags: Number of fragments in next packet to be delivered by
* __efx_rx_packet(), or zero if there is none
* @rx_pkt_index: Ring index of first buffer for next packet to be delivered
@ -418,6 +427,8 @@ struct efx_channel {
unsigned n_rx_overlength;
unsigned n_skbuff_leaks;
unsigned int n_rx_nodesc_trunc;
unsigned int n_rx_merge_events;
unsigned int n_rx_merge_packets;
unsigned int rx_pkt_n_frags;
unsigned int rx_pkt_index;
@ -721,7 +732,7 @@ struct vfdi_status;
* @rps_flow_id: Flow IDs of filters allocated for accelerated RFS,
* indexed by filter ID
* @rps_expire_index: Next index to check for expiry in @rps_flow_id
* @drain_pending: Count of RX and TX queues that haven't been flushed and drained.
* @active_queues: Count of RX and TX queues that haven't been flushed and drained.
* @rxq_flush_pending: Count of number of receive queues that need to be flushed.
* Decremented when the efx_flush_rx_queue() is called.
* @rxq_flush_outstanding: Count of number of RX flushes started but not yet
@ -862,7 +873,7 @@ struct efx_nic {
unsigned int rps_expire_index;
#endif
atomic_t drain_pending;
atomic_t active_queues;
atomic_t rxq_flush_pending;
atomic_t rxq_flush_outstanding;
wait_queue_head_t flush_wq;
@ -1023,7 +1034,8 @@ struct efx_mtd_partition {
* @rx_prefix_size: Size of RX prefix before packet data
* @rx_hash_offset: Offset of RX flow hash within prefix
* @rx_buffer_padding: Size of padding at end of RX packet
* @can_rx_scatter: NIC is able to scatter packet to multiple buffers
* @can_rx_scatter: NIC is able to scatter packets to multiple buffers
* @always_rx_scatter: NIC will always scatter packets to multiple buffers
* @max_interrupt_mode: Highest capability interrupt mode supported
* from &enum efx_init_mode.
* @timer_period_max: Maximum period of interrupt timer (in ticks)
@ -1036,7 +1048,7 @@ struct efx_nic_type {
int (*probe)(struct efx_nic *efx);
void (*remove)(struct efx_nic *efx);
int (*init)(struct efx_nic *efx);
void (*dimension_resources)(struct efx_nic *efx);
int (*dimension_resources)(struct efx_nic *efx);
void (*fini)(struct efx_nic *efx);
void (*monitor)(struct efx_nic *efx);
enum reset_type (*map_reset_reason)(enum reset_type reason);
@ -1087,7 +1099,7 @@ struct efx_nic_type {
void (*rx_write)(struct efx_rx_queue *rx_queue);
void (*rx_defer_refill)(struct efx_rx_queue *rx_queue);
int (*ev_probe)(struct efx_channel *channel);
void (*ev_init)(struct efx_channel *channel);
int (*ev_init)(struct efx_channel *channel);
void (*ev_fini)(struct efx_channel *channel);
void (*ev_remove)(struct efx_channel *channel);
int (*ev_process)(struct efx_channel *channel, int quota);
@ -1142,6 +1154,7 @@ struct efx_nic_type {
unsigned int rx_hash_offset;
unsigned int rx_buffer_padding;
bool can_rx_scatter;
bool always_rx_scatter;
unsigned int max_interrupt_mode;
unsigned int timer_period_max;
netdev_features_t offload_features;

View File

@ -1,7 +1,7 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Driver for Solarflare network controllers and boards
* Copyright 2005-2006 Fen Systems Ltd.
* Copyright 2006-2011 Solarflare Communications Inc.
* Copyright 2006-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published

View File

@ -1,7 +1,7 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Driver for Solarflare network controllers and boards
* Copyright 2005-2006 Fen Systems Ltd.
* Copyright 2006-2011 Solarflare Communications Inc.
* Copyright 2006-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@ -17,15 +17,12 @@
#include "efx.h"
#include "mcdi.h"
/*
* Falcon hardware control
*/
enum {
EFX_REV_FALCON_A0 = 0,
EFX_REV_FALCON_A1 = 1,
EFX_REV_FALCON_B0 = 2,
EFX_REV_SIENA_A0 = 3,
EFX_REV_HUNT_A0 = 4,
};
static inline int efx_nic_rev(struct efx_nic *efx)
@ -347,6 +344,78 @@ struct siena_nic_data {
u64 stats[SIENA_STAT_COUNT];
};
enum {
EF10_STAT_tx_bytes,
EF10_STAT_tx_packets,
EF10_STAT_tx_pause,
EF10_STAT_tx_control,
EF10_STAT_tx_unicast,
EF10_STAT_tx_multicast,
EF10_STAT_tx_broadcast,
EF10_STAT_tx_lt64,
EF10_STAT_tx_64,
EF10_STAT_tx_65_to_127,
EF10_STAT_tx_128_to_255,
EF10_STAT_tx_256_to_511,
EF10_STAT_tx_512_to_1023,
EF10_STAT_tx_1024_to_15xx,
EF10_STAT_tx_15xx_to_jumbo,
EF10_STAT_rx_bytes,
EF10_STAT_rx_bytes_minus_good_bytes,
EF10_STAT_rx_good_bytes,
EF10_STAT_rx_bad_bytes,
EF10_STAT_rx_packets,
EF10_STAT_rx_good,
EF10_STAT_rx_bad,
EF10_STAT_rx_pause,
EF10_STAT_rx_control,
EF10_STAT_rx_unicast,
EF10_STAT_rx_multicast,
EF10_STAT_rx_broadcast,
EF10_STAT_rx_lt64,
EF10_STAT_rx_64,
EF10_STAT_rx_65_to_127,
EF10_STAT_rx_128_to_255,
EF10_STAT_rx_256_to_511,
EF10_STAT_rx_512_to_1023,
EF10_STAT_rx_1024_to_15xx,
EF10_STAT_rx_15xx_to_jumbo,
EF10_STAT_rx_gtjumbo,
EF10_STAT_rx_bad_gtjumbo,
EF10_STAT_rx_overflow,
EF10_STAT_rx_align_error,
EF10_STAT_rx_length_error,
EF10_STAT_rx_nodesc_drops,
EF10_STAT_COUNT
};
/**
* struct efx_ef10_nic_data - EF10 architecture NIC state
* @mcdi_buf: DMA buffer for MCDI
* @warm_boot_count: Last seen MC warm boot count
* @vi_base: Absolute index of first VI in this function
* @n_allocated_vis: Number of VIs allocated to this function
* @must_realloc_vis: Flag: VIs have yet to be reallocated after MC reboot
* @must_restore_filters: Flag: filters have yet to be restored after MC reboot
* @rx_rss_context: Firmware handle for our RSS context
* @stats: Hardware statistics
* @workaround_35388: Flag: firmware supports workaround for bug 35388
* @datapath_caps: Capabilities of datapath firmware (FLAGS1 field of
* %MC_CMD_GET_CAPABILITIES response)
*/
struct efx_ef10_nic_data {
struct efx_buffer mcdi_buf;
u16 warm_boot_count;
unsigned int vi_base;
unsigned int n_allocated_vis;
bool must_realloc_vis;
bool must_restore_filters;
u32 rx_rss_context;
u64 stats[EF10_STAT_COUNT];
bool workaround_35388;
u32 datapath_caps;
};
/*
* On the SFC9000 family each port is associated with 1 PCI physical
* function (PF) handled by sfc and a configurable number of virtual
@ -448,6 +517,7 @@ extern void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev);
extern const struct efx_nic_type falcon_a1_nic_type;
extern const struct efx_nic_type falcon_b0_nic_type;
extern const struct efx_nic_type siena_a0_nic_type;
extern const struct efx_nic_type efx_hunt_a0_nic_type;
/**************************************************************************
*
@ -503,9 +573,9 @@ static inline int efx_nic_probe_eventq(struct efx_channel *channel)
{
return channel->efx->type->ev_probe(channel);
}
static inline void efx_nic_init_eventq(struct efx_channel *channel)
static inline int efx_nic_init_eventq(struct efx_channel *channel)
{
channel->efx->type->ev_init(channel);
return channel->efx->type->ev_init(channel);
}
static inline void efx_nic_fini_eventq(struct efx_channel *channel)
{
@ -539,7 +609,7 @@ extern void efx_farch_rx_remove(struct efx_rx_queue *rx_queue);
extern void efx_farch_rx_write(struct efx_rx_queue *rx_queue);
extern void efx_farch_rx_defer_refill(struct efx_rx_queue *rx_queue);
extern int efx_farch_ev_probe(struct efx_channel *channel);
extern void efx_farch_ev_init(struct efx_channel *channel);
extern int efx_farch_ev_init(struct efx_channel *channel);
extern void efx_farch_ev_fini(struct efx_channel *channel);
extern void efx_farch_ev_remove(struct efx_channel *channel);
extern int efx_farch_ev_process(struct efx_channel *channel, int quota);
@ -627,6 +697,7 @@ extern void falcon_stop_nic_stats(struct efx_nic *efx);
extern int falcon_reset_xaui(struct efx_nic *efx);
extern void efx_farch_dimension_resources(struct efx_nic *efx, unsigned sram_lim_qw);
extern void efx_farch_init_common(struct efx_nic *efx);
extern void efx_ef10_handle_drain_event(struct efx_nic *efx);
static inline void efx_nic_push_rx_indir_table(struct efx_nic *efx)
{
efx->type->rx_push_indir_table(efx);

View File

@ -1,5 +1,5 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Driver for Solarflare network controllers and boards
* Copyright 2007-2010 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it

View File

@ -1,6 +1,6 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Copyright 2011 Solarflare Communications Inc.
* Driver for Solarflare network controllers and boards
* Copyright 2011-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published

View File

@ -1,6 +1,6 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Copyright 2006-2010 Solarflare Communications Inc.
* Driver for Solarflare network controllers and boards
* Copyright 2006-2012 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published

View File

@ -1,7 +1,7 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Driver for Solarflare network controllers and boards
* Copyright 2005-2006 Fen Systems Ltd.
* Copyright 2005-2011 Solarflare Communications Inc.
* Copyright 2005-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@ -529,8 +529,8 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
if (!(flags & EFX_RX_PKT_PREFIX_LEN))
efx_rx_packet__check_len(rx_queue, rx_buf, len);
} else if (unlikely(n_frags > EFX_RX_MAX_FRAGS) ||
unlikely(len <= (n_frags - 1) * EFX_RX_USR_BUF_SIZE) ||
unlikely(len > n_frags * EFX_RX_USR_BUF_SIZE) ||
unlikely(len <= (n_frags - 1) * efx->rx_dma_len) ||
unlikely(len > n_frags * efx->rx_dma_len) ||
unlikely(!efx->rx_scatter)) {
/* If this isn't an explicit discard request, either
* the hardware or the driver is broken.
@ -581,9 +581,9 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
rx_buf = efx_rx_buf_next(rx_queue, rx_buf);
if (--tail_frags == 0)
break;
efx_sync_rx_buffer(efx, rx_buf, EFX_RX_USR_BUF_SIZE);
efx_sync_rx_buffer(efx, rx_buf, efx->rx_dma_len);
}
rx_buf->len = len - (n_frags - 1) * EFX_RX_USR_BUF_SIZE;
rx_buf->len = len - (n_frags - 1) * efx->rx_dma_len;
efx_sync_rx_buffer(efx, rx_buf, rx_buf->len);
}
@ -903,3 +903,37 @@ bool __efx_filter_rfs_expire(struct efx_nic *efx, unsigned int quota)
}
#endif /* CONFIG_RFS_ACCEL */
/**
* efx_filter_is_mc_recipient - test whether spec is a multicast recipient
* @spec: Specification to test
*
* Return: %true if the specification is a non-drop RX filter that
* matches a local MAC address I/G bit value of 1 or matches a local
* IPv4 or IPv6 address value in the respective multicast address
* range. Otherwise %false.
*/
bool efx_filter_is_mc_recipient(const struct efx_filter_spec *spec)
{
if (!(spec->flags & EFX_FILTER_FLAG_RX) ||
spec->dmaq_id == EFX_FILTER_RX_DMAQ_ID_DROP)
return false;
if (spec->match_flags &
(EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_LOC_MAC_IG) &&
is_multicast_ether_addr(spec->loc_mac))
return true;
if ((spec->match_flags &
(EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_LOC_HOST)) ==
(EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_LOC_HOST)) {
if (spec->ether_type == htons(ETH_P_IP) &&
ipv4_is_multicast(spec->loc_host[0]))
return true;
if (spec->ether_type == htons(ETH_P_IPV6) &&
((const u8 *)spec->loc_host)[0] == 0xff)
return true;
}
return false;
}

View File

@ -1,7 +1,7 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Driver for Solarflare network controllers and boards
* Copyright 2005-2006 Fen Systems Ltd.
* Copyright 2006-2010 Solarflare Communications Inc.
* Copyright 2006-2012 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published

View File

@ -1,7 +1,7 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Driver for Solarflare network controllers and boards
* Copyright 2005-2006 Fen Systems Ltd.
* Copyright 2006-2010 Solarflare Communications Inc.
* Copyright 2006-2012 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published

View File

@ -1,7 +1,7 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Driver for Solarflare network controllers and boards
* Copyright 2005-2006 Fen Systems Ltd.
* Copyright 2006-2010 Solarflare Communications Inc.
* Copyright 2006-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@ -177,13 +177,14 @@ static int siena_probe_nvconfig(struct efx_nic *efx)
return rc;
}
static void siena_dimension_resources(struct efx_nic *efx)
static int siena_dimension_resources(struct efx_nic *efx)
{
/* Each port has a small block of internal SRAM dedicated to
* the buffer table and descriptor caches. In theory we can
* map both blocks to one port, but we don't.
*/
efx_farch_dimension_resources(efx, FR_CZ_BUF_FULL_TBL_ROWS / 2);
return 0;
}
static unsigned int siena_mem_map_size(struct efx_nic *efx)
@ -195,7 +196,6 @@ static unsigned int siena_mem_map_size(struct efx_nic *efx)
static int siena_probe_nic(struct efx_nic *efx)
{
struct siena_nic_data *nic_data;
bool already_attached = false;
efx_oword_t reg;
int rc;
@ -221,19 +221,6 @@ static int siena_probe_nic(struct efx_nic *efx)
if (rc)
goto fail1;
/* Let the BMC know that the driver is now in charge of link and
* filter settings. We must do this before we reset the NIC */
rc = efx_mcdi_drv_attach(efx, true, &already_attached);
if (rc) {
netif_err(efx, probe, efx->net_dev,
"Unable to register driver with MCPU\n");
goto fail2;
}
if (already_attached)
/* Not a fatal error */
netif_err(efx, probe, efx->net_dev,
"Host already registered with MCPU\n");
/* Now we can reset the NIC */
rc = efx_mcdi_reset(efx, RESET_TYPE_ALL);
if (rc) {
@ -280,8 +267,6 @@ fail5:
efx_nic_free_buffer(efx, &efx->irq_status);
fail4:
fail3:
efx_mcdi_drv_attach(efx, false, NULL);
fail2:
efx_mcdi_fini(efx);
fail1:
kfree(efx->nic_data);
@ -370,14 +355,11 @@ static void siena_remove_nic(struct efx_nic *efx)
efx_mcdi_reset(efx, RESET_TYPE_ALL);
/* Relinquish the device back to the BMC */
efx_mcdi_drv_attach(efx, false, NULL);
efx_mcdi_fini(efx);
/* Tear down the private nic state */
kfree(efx->nic_data);
efx->nic_data = NULL;
efx_mcdi_fini(efx);
}
#define SIENA_DMA_STAT(ext_name, mcdi_name) \

View File

@ -1,6 +1,6 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Copyright 2010-2011 Solarflare Communications Inc.
* Driver for Solarflare network controllers and boards
* Copyright 2010-2012 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published

View File

@ -1,5 +1,5 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Driver for Solarflare network controllers and boards
* Copyright 2007-2011 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it

View File

@ -1,7 +1,7 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Driver for Solarflare network controllers and boards
* Copyright 2005-2006 Fen Systems Ltd.
* Copyright 2005-2010 Solarflare Communications Inc.
* Copyright 2005-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@ -306,7 +306,9 @@ static void efx_dequeue_buffers(struct efx_tx_queue *tx_queue,
while (read_ptr != stop_index) {
struct efx_tx_buffer *buffer = &tx_queue->buffer[read_ptr];
if (unlikely(buffer->len == 0)) {
if (!(buffer->flags & EFX_TX_BUF_OPTION) &&
unlikely(buffer->len == 0)) {
netif_err(efx, tx_err, efx->net_dev,
"TX queue %d spurious TX completion id %x\n",
tx_queue->queue, read_ptr);

View File

@ -1,5 +1,5 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Driver for Solarflare network controllers and boards
* Copyright 2006-2011 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it

View File

@ -1,5 +1,5 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Driver for Solarflare network controllers and boards
* Copyright 2010-2012 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it

View File

@ -1,6 +1,6 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Copyright 2006-2010 Solarflare Communications Inc.
* Driver for Solarflare network controllers and boards
* Copyright 2006-2013 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@ -44,4 +44,10 @@
/* Leak overlength packets rather than free */
#define EFX_WORKAROUND_8071 EFX_WORKAROUND_FALCON_A
/* Lockup when writing event block registers at gen2/gen3 */
#define EFX_EF10_WORKAROUND_35388(efx) \
(((struct efx_ef10_nic_data *)efx->nic_data)->workaround_35388)
#define EFX_WORKAROUND_35388(efx) \
(efx_nic_rev(efx) == EFX_REV_HUNT_A0 && EFX_EF10_WORKAROUND_35388(efx))
#endif /* EFX_WORKAROUNDS_H */