diff options
Diffstat (limited to 'drivers/net/sfc')
35 files changed, 0 insertions, 16501 deletions
diff --git a/drivers/net/sfc/Kconfig b/drivers/net/sfc/Kconfig deleted file mode 100644 index c535408ad6b..00000000000 --- a/drivers/net/sfc/Kconfig +++ /dev/null @@ -1,22 +0,0 @@ -config SFC - tristate "Solarflare Solarstorm SFC4000 support" - depends on PCI && INET - select MII - select INET_LRO - select CRC32 - select I2C - select I2C_ALGOBIT - help - This driver supports 10-gigabit Ethernet cards based on - the Solarflare Communications Solarstorm SFC4000 controller. - - To compile this driver as a module, choose M here. The module - will be called sfc. -config SFC_MTD - bool "Solarflare Solarstorm SFC4000 flash MTD support" - depends on SFC && MTD && !(SFC=y && MTD=m) - default y - help - This exposes the on-board flash memory as an MTD device (e.g. - /dev/mtd1). This makes it possible to upload new boot code - to the NIC. diff --git a/drivers/net/sfc/Makefile b/drivers/net/sfc/Makefile deleted file mode 100644 index b89f9be3cb1..00000000000 --- a/drivers/net/sfc/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -sfc-y += efx.o falcon.o tx.o rx.o falcon_gmac.o \ - falcon_xmac.o selftest.o ethtool.o xfp_phy.o \ - mdio_10g.o tenxpress.o boards.o sfe4001.o -sfc-$(CONFIG_SFC_MTD) += mtd.o - -obj-$(CONFIG_SFC) += sfc.o diff --git a/drivers/net/sfc/bitfield.h b/drivers/net/sfc/bitfield.h deleted file mode 100644 index d95c2182801..00000000000 --- a/drivers/net/sfc/bitfield.h +++ /dev/null @@ -1,549 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2006-2008 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_BITFIELD_H -#define EFX_BITFIELD_H - -/* - * Efx bitfield access - * - * Efx NICs make extensive use of bitfields up to 128 bits - * wide. Since there is no native 128-bit datatype on most systems, - * and since 64-bit datatypes are inefficient on 32-bit systems and - * vice versa, we wrap accesses in a way that uses the most efficient - * datatype. - * - * The NICs are PCI devices and therefore little-endian. Since most - * of the quantities that we deal with are DMAed to/from host memory, - * we define our datatypes (efx_oword_t, efx_qword_t and - * efx_dword_t) to be little-endian. - */ - -/* Lowest bit numbers and widths */ -#define EFX_DUMMY_FIELD_LBN 0 -#define EFX_DUMMY_FIELD_WIDTH 0 -#define EFX_DWORD_0_LBN 0 -#define EFX_DWORD_0_WIDTH 32 -#define EFX_DWORD_1_LBN 32 -#define EFX_DWORD_1_WIDTH 32 -#define EFX_DWORD_2_LBN 64 -#define EFX_DWORD_2_WIDTH 32 -#define EFX_DWORD_3_LBN 96 -#define EFX_DWORD_3_WIDTH 32 - -/* Specified attribute (e.g. LBN) of the specified field */ -#define EFX_VAL(field, attribute) field ## _ ## attribute -/* Low bit number of the specified field */ -#define EFX_LOW_BIT(field) EFX_VAL(field, LBN) -/* Bit width of the specified field */ -#define EFX_WIDTH(field) EFX_VAL(field, WIDTH) -/* High bit number of the specified field */ -#define EFX_HIGH_BIT(field) (EFX_LOW_BIT(field) + EFX_WIDTH(field) - 1) -/* Mask equal in width to the specified field. - * - * For example, a field with width 5 would have a mask of 0x1f. - * - * The maximum width mask that can be generated is 64 bits. - */ -#define EFX_MASK64(width) \ - ((width) == 64 ? ~((u64) 0) : \ - (((((u64) 1) << (width))) - 1)) - -/* Mask equal in width to the specified field. - * - * For example, a field with width 5 would have a mask of 0x1f. - * - * The maximum width mask that can be generated is 32 bits. Use - * EFX_MASK64 for higher width fields. - */ -#define EFX_MASK32(width) \ - ((width) == 32 ? ~((u32) 0) : \ - (((((u32) 1) << (width))) - 1)) - -/* A doubleword (i.e. 4 byte) datatype - little-endian in HW */ -typedef union efx_dword { - __le32 u32[1]; -} efx_dword_t; - -/* A quadword (i.e. 8 byte) datatype - little-endian in HW */ -typedef union efx_qword { - __le64 u64[1]; - __le32 u32[2]; - efx_dword_t dword[2]; -} efx_qword_t; - -/* An octword (eight-word, i.e. 16 byte) datatype - little-endian in HW */ -typedef union efx_oword { - __le64 u64[2]; - efx_qword_t qword[2]; - __le32 u32[4]; - efx_dword_t dword[4]; -} efx_oword_t; - -/* Format string and value expanders for printk */ -#define EFX_DWORD_FMT "%08x" -#define EFX_QWORD_FMT "%08x:%08x" -#define EFX_OWORD_FMT "%08x:%08x:%08x:%08x" -#define EFX_DWORD_VAL(dword) \ - ((unsigned int) le32_to_cpu((dword).u32[0])) -#define EFX_QWORD_VAL(qword) \ - ((unsigned int) le32_to_cpu((qword).u32[1])), \ - ((unsigned int) le32_to_cpu((qword).u32[0])) -#define EFX_OWORD_VAL(oword) \ - ((unsigned int) le32_to_cpu((oword).u32[3])), \ - ((unsigned int) le32_to_cpu((oword).u32[2])), \ - ((unsigned int) le32_to_cpu((oword).u32[1])), \ - ((unsigned int) le32_to_cpu((oword).u32[0])) - -/* - * Extract bit field portion [low,high) from the native-endian element - * which contains bits [min,max). - * - * For example, suppose "element" represents the high 32 bits of a - * 64-bit value, and we wish to extract the bits belonging to the bit - * field occupying bits 28-45 of this 64-bit value. - * - * Then EFX_EXTRACT ( element, 32, 63, 28, 45 ) would give - * - * ( element ) << 4 - * - * The result will contain the relevant bits filled in in the range - * [0,high-low), with garbage in bits [high-low+1,...). - */ -#define EFX_EXTRACT_NATIVE(native_element, min, max, low, high) \ - (((low > max) || (high < min)) ? 0 : \ - ((low > min) ? \ - ((native_element) >> (low - min)) : \ - ((native_element) << (min - low)))) - -/* - * Extract bit field portion [low,high) from the 64-bit little-endian - * element which contains bits [min,max) - */ -#define EFX_EXTRACT64(element, min, max, low, high) \ - EFX_EXTRACT_NATIVE(le64_to_cpu(element), min, max, low, high) - -/* - * Extract bit field portion [low,high) from the 32-bit little-endian - * element which contains bits [min,max) - */ -#define EFX_EXTRACT32(element, min, max, low, high) \ - EFX_EXTRACT_NATIVE(le32_to_cpu(element), min, max, low, high) - -#define EFX_EXTRACT_OWORD64(oword, low, high) \ - ((EFX_EXTRACT64((oword).u64[0], 0, 63, low, high) | \ - EFX_EXTRACT64((oword).u64[1], 64, 127, low, high)) & \ - EFX_MASK64(high + 1 - low)) - -#define EFX_EXTRACT_QWORD64(qword, low, high) \ - (EFX_EXTRACT64((qword).u64[0], 0, 63, low, high) & \ - EFX_MASK64(high + 1 - low)) - -#define EFX_EXTRACT_OWORD32(oword, low, high) \ - ((EFX_EXTRACT32((oword).u32[0], 0, 31, low, high) | \ - EFX_EXTRACT32((oword).u32[1], 32, 63, low, high) | \ - EFX_EXTRACT32((oword).u32[2], 64, 95, low, high) | \ - EFX_EXTRACT32((oword).u32[3], 96, 127, low, high)) & \ - EFX_MASK32(high + 1 - low)) - -#define EFX_EXTRACT_QWORD32(qword, low, high) \ - ((EFX_EXTRACT32((qword).u32[0], 0, 31, low, high) | \ - EFX_EXTRACT32((qword).u32[1], 32, 63, low, high)) & \ - EFX_MASK32(high + 1 - low)) - -#define EFX_EXTRACT_DWORD(dword, low, high) \ - (EFX_EXTRACT32((dword).u32[0], 0, 31, low, high) & \ - EFX_MASK32(high + 1 - low)) - -#define EFX_OWORD_FIELD64(oword, field) \ - EFX_EXTRACT_OWORD64(oword, EFX_LOW_BIT(field), \ - EFX_HIGH_BIT(field)) - -#define EFX_QWORD_FIELD64(qword, field) \ - EFX_EXTRACT_QWORD64(qword, EFX_LOW_BIT(field), \ - EFX_HIGH_BIT(field)) - -#define EFX_OWORD_FIELD32(oword, field) \ - EFX_EXTRACT_OWORD32(oword, EFX_LOW_BIT(field), \ - EFX_HIGH_BIT(field)) - -#define EFX_QWORD_FIELD32(qword, field) \ - EFX_EXTRACT_QWORD32(qword, EFX_LOW_BIT(field), \ - EFX_HIGH_BIT(field)) - -#define EFX_DWORD_FIELD(dword, field) \ - EFX_EXTRACT_DWORD(dword, EFX_LOW_BIT(field), \ - EFX_HIGH_BIT(field)) - -#define EFX_OWORD_IS_ZERO64(oword) \ - (((oword).u64[0] | (oword).u64[1]) == (__force __le64) 0) - -#define EFX_QWORD_IS_ZERO64(qword) \ - (((qword).u64[0]) == (__force __le64) 0) - -#define EFX_OWORD_IS_ZERO32(oword) \ - (((oword).u32[0] | (oword).u32[1] | (oword).u32[2] | (oword).u32[3]) \ - == (__force __le32) 0) - -#define EFX_QWORD_IS_ZERO32(qword) \ - (((qword).u32[0] | (qword).u32[1]) == (__force __le32) 0) - -#define EFX_DWORD_IS_ZERO(dword) \ - (((dword).u32[0]) == (__force __le32) 0) - -#define EFX_OWORD_IS_ALL_ONES64(oword) \ - (((oword).u64[0] & (oword).u64[1]) == ~((__force __le64) 0)) - -#define EFX_QWORD_IS_ALL_ONES64(qword) \ - ((qword).u64[0] == ~((__force __le64) 0)) - -#define EFX_OWORD_IS_ALL_ONES32(oword) \ - (((oword).u32[0] & (oword).u32[1] & (oword).u32[2] & (oword).u32[3]) \ - == ~((__force __le32) 0)) - -#define EFX_QWORD_IS_ALL_ONES32(qword) \ - (((qword).u32[0] & (qword).u32[1]) == ~((__force __le32) 0)) - -#define EFX_DWORD_IS_ALL_ONES(dword) \ - ((dword).u32[0] == ~((__force __le32) 0)) - -#if BITS_PER_LONG == 64 -#define EFX_OWORD_FIELD EFX_OWORD_FIELD64 -#define EFX_QWORD_FIELD EFX_QWORD_FIELD64 -#define EFX_OWORD_IS_ZERO EFX_OWORD_IS_ZERO64 -#define EFX_QWORD_IS_ZERO EFX_QWORD_IS_ZERO64 -#define EFX_OWORD_IS_ALL_ONES EFX_OWORD_IS_ALL_ONES64 -#define EFX_QWORD_IS_ALL_ONES EFX_QWORD_IS_ALL_ONES64 -#else -#define EFX_OWORD_FIELD EFX_OWORD_FIELD32 -#define EFX_QWORD_FIELD EFX_QWORD_FIELD32 -#define EFX_OWORD_IS_ZERO EFX_OWORD_IS_ZERO32 -#define EFX_QWORD_IS_ZERO EFX_QWORD_IS_ZERO32 -#define EFX_OWORD_IS_ALL_ONES EFX_OWORD_IS_ALL_ONES32 -#define EFX_QWORD_IS_ALL_ONES EFX_QWORD_IS_ALL_ONES32 -#endif - -/* - * Construct bit field portion - * - * Creates the portion of the bit field [low,high) that lies within - * the range [min,max). - */ -#define EFX_INSERT_NATIVE64(min, max, low, high, value) \ - (((low > max) || (high < min)) ? 0 : \ - ((low > min) ? \ - (((u64) (value)) << (low - min)) : \ - (((u64) (value)) >> (min - low)))) - -#define EFX_INSERT_NATIVE32(min, max, low, high, value) \ - (((low > max) || (high < min)) ? 0 : \ - ((low > min) ? \ - (((u32) (value)) << (low - min)) : \ - (((u32) (value)) >> (min - low)))) - -#define EFX_INSERT_NATIVE(min, max, low, high, value) \ - ((((max - min) >= 32) || ((high - low) >= 32)) ? \ - EFX_INSERT_NATIVE64(min, max, low, high, value) : \ - EFX_INSERT_NATIVE32(min, max, low, high, value)) - -/* - * Construct bit field portion - * - * Creates the portion of the named bit field that lies within the - * range [min,max). - */ -#define EFX_INSERT_FIELD_NATIVE(min, max, field, value) \ - EFX_INSERT_NATIVE(min, max, EFX_LOW_BIT(field), \ - EFX_HIGH_BIT(field), value) - -/* - * Construct bit field - * - * Creates the portion of the named bit fields that lie within the - * range [min,max). - */ -#define EFX_INSERT_FIELDS_NATIVE(min, max, \ - field1, value1, \ - field2, value2, \ - field3, value3, \ - field4, value4, \ - field5, value5, \ - field6, value6, \ - field7, value7, \ - field8, value8, \ - field9, value9, \ - field10, value10) \ - (EFX_INSERT_FIELD_NATIVE((min), (max), field1, (value1)) | \ - EFX_INSERT_FIELD_NATIVE((min), (max), field2, (value2)) | \ - EFX_INSERT_FIELD_NATIVE((min), (max), field3, (value3)) | \ - EFX_INSERT_FIELD_NATIVE((min), (max), field4, (value4)) | \ - EFX_INSERT_FIELD_NATIVE((min), (max), field5, (value5)) | \ - EFX_INSERT_FIELD_NATIVE((min), (max), field6, (value6)) | \ - EFX_INSERT_FIELD_NATIVE((min), (max), field7, (value7)) | \ - EFX_INSERT_FIELD_NATIVE((min), (max), field8, (value8)) | \ - EFX_INSERT_FIELD_NATIVE((min), (max), field9, (value9)) | \ - EFX_INSERT_FIELD_NATIVE((min), (max), field10, (value10))) - -#define EFX_INSERT_FIELDS64(...) \ - cpu_to_le64(EFX_INSERT_FIELDS_NATIVE(__VA_ARGS__)) - -#define EFX_INSERT_FIELDS32(...) \ - cpu_to_le32(EFX_INSERT_FIELDS_NATIVE(__VA_ARGS__)) - -#define EFX_POPULATE_OWORD64(oword, ...) do { \ - (oword).u64[0] = EFX_INSERT_FIELDS64(0, 63, __VA_ARGS__); \ - (oword).u64[1] = EFX_INSERT_FIELDS64(64, 127, __VA_ARGS__); \ - } while (0) - -#define EFX_POPULATE_QWORD64(qword, ...) do { \ - (qword).u64[0] = EFX_INSERT_FIELDS64(0, 63, __VA_ARGS__); \ - } while (0) - -#define EFX_POPULATE_OWORD32(oword, ...) do { \ - (oword).u32[0] = EFX_INSERT_FIELDS32(0, 31, __VA_ARGS__); \ - (oword).u32[1] = EFX_INSERT_FIELDS32(32, 63, __VA_ARGS__); \ - (oword).u32[2] = EFX_INSERT_FIELDS32(64, 95, __VA_ARGS__); \ - (oword).u32[3] = EFX_INSERT_FIELDS32(96, 127, __VA_ARGS__); \ - } while (0) - -#define EFX_POPULATE_QWORD32(qword, ...) do { \ - (qword).u32[0] = EFX_INSERT_FIELDS32(0, 31, __VA_ARGS__); \ - (qword).u32[1] = EFX_INSERT_FIELDS32(32, 63, __VA_ARGS__); \ - } while (0) - -#define EFX_POPULATE_DWORD(dword, ...) do { \ - (dword).u32[0] = EFX_INSERT_FIELDS32(0, 31, __VA_ARGS__); \ - } while (0) - -#if BITS_PER_LONG == 64 -#define EFX_POPULATE_OWORD EFX_POPULATE_OWORD64 -#define EFX_POPULATE_QWORD EFX_POPULATE_QWORD64 -#else -#define EFX_POPULATE_OWORD EFX_POPULATE_OWORD32 -#define EFX_POPULATE_QWORD EFX_POPULATE_QWORD32 -#endif - -/* Populate an octword field with various numbers of arguments */ -#define EFX_POPULATE_OWORD_10 EFX_POPULATE_OWORD -#define EFX_POPULATE_OWORD_9(oword, ...) \ - EFX_POPULATE_OWORD_10(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_OWORD_8(oword, ...) \ - EFX_POPULATE_OWORD_9(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_OWORD_7(oword, ...) \ - EFX_POPULATE_OWORD_8(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_OWORD_6(oword, ...) \ - EFX_POPULATE_OWORD_7(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_OWORD_5(oword, ...) \ - EFX_POPULATE_OWORD_6(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_OWORD_4(oword, ...) \ - EFX_POPULATE_OWORD_5(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_OWORD_3(oword, ...) \ - EFX_POPULATE_OWORD_4(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_OWORD_2(oword, ...) \ - EFX_POPULATE_OWORD_3(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_OWORD_1(oword, ...) \ - EFX_POPULATE_OWORD_2(oword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_ZERO_OWORD(oword) \ - EFX_POPULATE_OWORD_1(oword, EFX_DUMMY_FIELD, 0) -#define EFX_SET_OWORD(oword) \ - EFX_POPULATE_OWORD_4(oword, \ - EFX_DWORD_0, 0xffffffff, \ - EFX_DWORD_1, 0xffffffff, \ - EFX_DWORD_2, 0xffffffff, \ - EFX_DWORD_3, 0xffffffff) - -/* Populate a quadword field with various numbers of arguments */ -#define EFX_POPULATE_QWORD_10 EFX_POPULATE_QWORD -#define EFX_POPULATE_QWORD_9(qword, ...) \ - EFX_POPULATE_QWORD_10(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_QWORD_8(qword, ...) \ - EFX_POPULATE_QWORD_9(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_QWORD_7(qword, ...) \ - EFX_POPULATE_QWORD_8(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_QWORD_6(qword, ...) \ - EFX_POPULATE_QWORD_7(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_QWORD_5(qword, ...) \ - EFX_POPULATE_QWORD_6(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_QWORD_4(qword, ...) \ - EFX_POPULATE_QWORD_5(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_QWORD_3(qword, ...) \ - EFX_POPULATE_QWORD_4(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_QWORD_2(qword, ...) \ - EFX_POPULATE_QWORD_3(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_QWORD_1(qword, ...) \ - EFX_POPULATE_QWORD_2(qword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_ZERO_QWORD(qword) \ - EFX_POPULATE_QWORD_1(qword, EFX_DUMMY_FIELD, 0) -#define EFX_SET_QWORD(qword) \ - EFX_POPULATE_QWORD_2(qword, \ - EFX_DWORD_0, 0xffffffff, \ - EFX_DWORD_1, 0xffffffff) - -/* Populate a dword field with various numbers of arguments */ -#define EFX_POPULATE_DWORD_10 EFX_POPULATE_DWORD -#define EFX_POPULATE_DWORD_9(dword, ...) \ - EFX_POPULATE_DWORD_10(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_DWORD_8(dword, ...) \ - EFX_POPULATE_DWORD_9(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_DWORD_7(dword, ...) \ - EFX_POPULATE_DWORD_8(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_DWORD_6(dword, ...) \ - EFX_POPULATE_DWORD_7(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_DWORD_5(dword, ...) \ - EFX_POPULATE_DWORD_6(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_DWORD_4(dword, ...) \ - EFX_POPULATE_DWORD_5(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_DWORD_3(dword, ...) \ - EFX_POPULATE_DWORD_4(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_DWORD_2(dword, ...) \ - EFX_POPULATE_DWORD_3(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_POPULATE_DWORD_1(dword, ...) \ - EFX_POPULATE_DWORD_2(dword, EFX_DUMMY_FIELD, 0, __VA_ARGS__) -#define EFX_ZERO_DWORD(dword) \ - EFX_POPULATE_DWORD_1(dword, EFX_DUMMY_FIELD, 0) -#define EFX_SET_DWORD(dword) \ - EFX_POPULATE_DWORD_1(dword, EFX_DWORD_0, 0xffffffff) - -/* - * Modify a named field within an already-populated structure. Used - * for read-modify-write operations. - * - */ -#define EFX_INVERT_OWORD(oword) do { \ - (oword).u64[0] = ~((oword).u64[0]); \ - (oword).u64[1] = ~((oword).u64[1]); \ - } while (0) - -#define EFX_AND_OWORD(oword, from, mask) \ - do { \ - (oword).u64[0] = (from).u64[0] & (mask).u64[0]; \ - (oword).u64[1] = (from).u64[1] & (mask).u64[1]; \ - } while (0) - -#define EFX_OR_OWORD(oword, from, mask) \ - do { \ - (oword).u64[0] = (from).u64[0] | (mask).u64[0]; \ - (oword).u64[1] = (from).u64[1] | (mask).u64[1]; \ - } while (0) - -#define EFX_INSERT64(min, max, low, high, value) \ - cpu_to_le64(EFX_INSERT_NATIVE(min, max, low, high, value)) - -#define EFX_INSERT32(min, max, low, high, value) \ - cpu_to_le32(EFX_INSERT_NATIVE(min, max, low, high, value)) - -#define EFX_INPLACE_MASK64(min, max, low, high) \ - EFX_INSERT64(min, max, low, high, EFX_MASK64(high + 1 - low)) - -#define EFX_INPLACE_MASK32(min, max, low, high) \ - EFX_INSERT32(min, max, low, high, EFX_MASK32(high + 1 - low)) - -#define EFX_SET_OWORD64(oword, low, high, value) do { \ - (oword).u64[0] = (((oword).u64[0] \ - & ~EFX_INPLACE_MASK64(0, 63, low, high)) \ - | EFX_INSERT64(0, 63, low, high, value)); \ - (oword).u64[1] = (((oword).u64[1] \ - & ~EFX_INPLACE_MASK64(64, 127, low, high)) \ - | EFX_INSERT64(64, 127, low, high, value)); \ - } while (0) - -#define EFX_SET_QWORD64(qword, low, high, value) do { \ - (qword).u64[0] = (((qword).u64[0] \ - & ~EFX_INPLACE_MASK64(0, 63, low, high)) \ - | EFX_INSERT64(0, 63, low, high, value)); \ - } while (0) - -#define EFX_SET_OWORD32(oword, low, high, value) do { \ - (oword).u32[0] = (((oword).u32[0] \ - & ~EFX_INPLACE_MASK32(0, 31, low, high)) \ - | EFX_INSERT32(0, 31, low, high, value)); \ - (oword).u32[1] = (((oword).u32[1] \ - & ~EFX_INPLACE_MASK32(32, 63, low, high)) \ - | EFX_INSERT32(32, 63, low, high, value)); \ - (oword).u32[2] = (((oword).u32[2] \ - & ~EFX_INPLACE_MASK32(64, 95, low, high)) \ - | EFX_INSERT32(64, 95, low, high, value)); \ - (oword).u32[3] = (((oword).u32[3] \ - & ~EFX_INPLACE_MASK32(96, 127, low, high)) \ - | EFX_INSERT32(96, 127, low, high, value)); \ - } while (0) - -#define EFX_SET_QWORD32(qword, low, high, value) do { \ - (qword).u32[0] = (((qword).u32[0] \ - & ~EFX_INPLACE_MASK32(0, 31, low, high)) \ - | EFX_INSERT32(0, 31, low, high, value)); \ - (qword).u32[1] = (((qword).u32[1] \ - & ~EFX_INPLACE_MASK32(32, 63, low, high)) \ - | EFX_INSERT32(32, 63, low, high, value)); \ - } while (0) - -#define EFX_SET_DWORD32(dword, low, high, value) do { \ - (dword).u32[0] = (((dword).u32[0] \ - & ~EFX_INPLACE_MASK32(0, 31, low, high)) \ - | EFX_INSERT32(0, 31, low, high, value)); \ - } while (0) - -#define EFX_SET_OWORD_FIELD64(oword, field, value) \ - EFX_SET_OWORD64(oword, EFX_LOW_BIT(field), \ - EFX_HIGH_BIT(field), value) - -#define EFX_SET_QWORD_FIELD64(qword, field, value) \ - EFX_SET_QWORD64(qword, EFX_LOW_BIT(field), \ - EFX_HIGH_BIT(field), value) - -#define EFX_SET_OWORD_FIELD32(oword, field, value) \ - EFX_SET_OWORD32(oword, EFX_LOW_BIT(field), \ - EFX_HIGH_BIT(field), value) - -#define EFX_SET_QWORD_FIELD32(qword, field, value) \ - EFX_SET_QWORD32(qword, EFX_LOW_BIT(field), \ - EFX_HIGH_BIT(field), value) - -#define EFX_SET_DWORD_FIELD(dword, field, value) \ - EFX_SET_DWORD32(dword, EFX_LOW_BIT(field), \ - EFX_HIGH_BIT(field), value) - - - -#if BITS_PER_LONG == 64 -#define EFX_SET_OWORD_FIELD EFX_SET_OWORD_FIELD64 -#define EFX_SET_QWORD_FIELD EFX_SET_QWORD_FIELD64 -#else -#define EFX_SET_OWORD_FIELD EFX_SET_OWORD_FIELD32 -#define EFX_SET_QWORD_FIELD EFX_SET_QWORD_FIELD32 -#endif - -#define EFX_SET_OWORD_FIELD_VER(efx, oword, field, value) do { \ - if (falcon_rev(efx) >= FALCON_REV_B0) { \ - EFX_SET_OWORD_FIELD((oword), field##_B0, (value)); \ - } else { \ - EFX_SET_OWORD_FIELD((oword), field##_A1, (value)); \ - } \ -} while (0) - -#define EFX_QWORD_FIELD_VER(efx, qword, field) \ - (falcon_rev(efx) >= FALCON_REV_B0 ? \ - EFX_QWORD_FIELD((qword), field##_B0) : \ - EFX_QWORD_FIELD((qword), field##_A1)) - -/* Used to avoid compiler warnings about shift range exceeding width - * of the data types when dma_addr_t is only 32 bits wide. - */ -#define DMA_ADDR_T_WIDTH (8 * sizeof(dma_addr_t)) -#define EFX_DMA_TYPE_WIDTH(width) \ - (((width) < DMA_ADDR_T_WIDTH) ? (width) : DMA_ADDR_T_WIDTH) - - -/* Static initialiser */ -#define EFX_OWORD32(a, b, c, d) \ - { .u32 = { __constant_cpu_to_le32(a), __constant_cpu_to_le32(b), \ - __constant_cpu_to_le32(c), __constant_cpu_to_le32(d) } } - -#endif /* EFX_BITFIELD_H */ diff --git a/drivers/net/sfc/boards.c b/drivers/net/sfc/boards.c deleted file mode 100644 index 64903496aa9..00000000000 --- a/drivers/net/sfc/boards.c +++ /dev/null @@ -1,270 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2007-2008 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. - */ - -#include "net_driver.h" -#include "phy.h" -#include "boards.h" -#include "efx.h" -#include "workarounds.h" - -/* Macros for unpacking the board revision */ -/* The revision info is in host byte order. */ -#define BOARD_TYPE(_rev) (_rev >> 8) -#define BOARD_MAJOR(_rev) ((_rev >> 4) & 0xf) -#define BOARD_MINOR(_rev) (_rev & 0xf) - -/* Blink support. If the PHY has no auto-blink mode so we hang it off a timer */ -#define BLINK_INTERVAL (HZ/2) - -static void blink_led_timer(unsigned long context) -{ - struct efx_nic *efx = (struct efx_nic *)context; - struct efx_blinker *bl = &efx->board_info.blinker; - efx->board_info.set_fault_led(efx, bl->state); - bl->state = !bl->state; - if (bl->resubmit) - mod_timer(&bl->timer, jiffies + BLINK_INTERVAL); -} - -static void board_blink(struct efx_nic *efx, bool blink) -{ - struct efx_blinker *blinker = &efx->board_info.blinker; - - /* The rtnl mutex serialises all ethtool ioctls, so - * nothing special needs doing here. */ - if (blink) { - blinker->resubmit = true; - blinker->state = false; - setup_timer(&blinker->timer, blink_led_timer, - (unsigned long)efx); - mod_timer(&blinker->timer, jiffies + BLINK_INTERVAL); - } else { - blinker->resubmit = false; - if (blinker->timer.function) - del_timer_sync(&blinker->timer); - efx->board_info.set_fault_led(efx, false); - } -} - -/***************************************************************************** - * Support for LM87 sensor chip used on several boards - */ -#define LM87_REG_ALARMS1 0x41 -#define LM87_REG_ALARMS2 0x42 -#define LM87_IN_LIMITS(nr, _min, _max) \ - 0x2B + (nr) * 2, _max, 0x2C + (nr) * 2, _min -#define LM87_AIN_LIMITS(nr, _min, _max) \ - 0x3B + (nr), _max, 0x1A + (nr), _min -#define LM87_TEMP_INT_LIMITS(_min, _max) \ - 0x39, _max, 0x3A, _min -#define LM87_TEMP_EXT1_LIMITS(_min, _max) \ - 0x37, _max, 0x38, _min - -#define LM87_ALARM_TEMP_INT 0x10 -#define LM87_ALARM_TEMP_EXT1 0x20 - -#if defined(CONFIG_SENSORS_LM87) || defined(CONFIG_SENSORS_LM87_MODULE) - -static int efx_init_lm87(struct efx_nic *efx, struct i2c_board_info *info, - const u8 *reg_values) -{ - struct i2c_client *client = i2c_new_device(&efx->i2c_adap, info); - int rc; - - if (!client) - return -EIO; - - while (*reg_values) { - u8 reg = *reg_values++; - u8 value = *reg_values++; - rc = i2c_smbus_write_byte_data(client, reg, value); - if (rc) - goto err; - } - - efx->board_info.hwmon_client = client; - return 0; - -err: - i2c_unregister_device(client); - return rc; -} - -static void efx_fini_lm87(struct efx_nic *efx) -{ - i2c_unregister_device(efx->board_info.hwmon_client); -} - -static int efx_check_lm87(struct efx_nic *efx, unsigned mask) -{ - struct i2c_client *client = efx->board_info.hwmon_client; - s32 alarms1, alarms2; - - /* If link is up then do not monitor temperature */ - if (EFX_WORKAROUND_7884(efx) && efx->link_up) - return 0; - - alarms1 = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS1); - alarms2 = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS2); - if (alarms1 < 0) - return alarms1; - if (alarms2 < 0) - return alarms2; - alarms1 &= mask; - alarms2 &= mask >> 8; - if (alarms1 || alarms2) { - EFX_ERR(efx, - "LM87 detected a hardware failure (status %02x:%02x)" - "%s%s\n", - alarms1, alarms2, - (alarms1 & LM87_ALARM_TEMP_INT) ? " INTERNAL" : "", - (alarms1 & LM87_ALARM_TEMP_EXT1) ? " EXTERNAL" : ""); - return -ERANGE; - } - - return 0; -} - -#else /* !CONFIG_SENSORS_LM87 */ - -static inline int -efx_init_lm87(struct efx_nic *efx, struct i2c_board_info *info, - const u8 *reg_values) -{ - return 0; -} -static inline void efx_fini_lm87(struct efx_nic *efx) -{ -} -static inline int efx_check_lm87(struct efx_nic *efx, unsigned mask) -{ - return 0; -} - -#endif /* CONFIG_SENSORS_LM87 */ - -/***************************************************************************** - * Support for the SFE4002 - * - */ -static u8 sfe4002_lm87_channel = 0x03; /* use AIN not FAN inputs */ - -static const u8 sfe4002_lm87_regs[] = { - LM87_IN_LIMITS(0, 0x83, 0x91), /* 2.5V: 1.8V +/- 5% */ - LM87_IN_LIMITS(1, 0x51, 0x5a), /* Vccp1: 1.2V +/- 5% */ - LM87_IN_LIMITS(2, 0xb6, 0xca), /* 3.3V: 3.3V +/- 5% */ - LM87_IN_LIMITS(3, 0xb0, 0xc9), /* 5V: 4.6-5.2V */ - LM87_IN_LIMITS(4, 0xb0, 0xe0), /* 12V: 11-14V */ - LM87_IN_LIMITS(5, 0x44, 0x4b), /* Vccp2: 1.0V +/- 5% */ - LM87_AIN_LIMITS(0, 0xa0, 0xb2), /* AIN1: 1.66V +/- 5% */ - LM87_AIN_LIMITS(1, 0x91, 0xa1), /* AIN2: 1.5V +/- 5% */ - LM87_TEMP_INT_LIMITS(10, 60), /* board */ - LM87_TEMP_EXT1_LIMITS(10, 70), /* Falcon */ - 0 -}; - -static struct i2c_board_info sfe4002_hwmon_info = { - I2C_BOARD_INFO("lm87", 0x2e), - .platform_data = &sfe4002_lm87_channel, - .irq = -1, -}; - -/****************************************************************************/ -/* LED allocations. Note that on rev A0 boards the schematic and the reality - * differ: red and green are swapped. Below is the fixed (A1) layout (there - * are only 3 A0 boards in existence, so no real reason to make this - * conditional). - */ -#define SFE4002_FAULT_LED (2) /* Red */ -#define SFE4002_RX_LED (0) /* Green */ -#define SFE4002_TX_LED (1) /* Amber */ - -static int sfe4002_init_leds(struct efx_nic *efx) -{ - /* Set the TX and RX LEDs to reflect status and activity, and the - * fault LED off */ - xfp_set_led(efx, SFE4002_TX_LED, - QUAKE_LED_TXLINK | QUAKE_LED_LINK_ACTSTAT); - xfp_set_led(efx, SFE4002_RX_LED, - QUAKE_LED_RXLINK | QUAKE_LED_LINK_ACTSTAT); - xfp_set_led(efx, SFE4002_FAULT_LED, QUAKE_LED_OFF); - efx->board_info.blinker.led_num = SFE4002_FAULT_LED; - return 0; -} - -static void sfe4002_fault_led(struct efx_nic *efx, bool state) -{ - xfp_set_led(efx, SFE4002_FAULT_LED, state ? QUAKE_LED_ON : - QUAKE_LED_OFF); -} - -static int sfe4002_check_hw(struct efx_nic *efx) -{ - /* A0 board rev. 4002s report a temperature fault the whole time - * (bad sensor) so we mask it out. */ - unsigned alarm_mask = - (efx->board_info.major == 0 && efx->board_info.minor == 0) ? - ~LM87_ALARM_TEMP_EXT1 : ~0; - - return efx_check_lm87(efx, alarm_mask); -} - -static int sfe4002_init(struct efx_nic *efx) -{ - int rc = efx_init_lm87(efx, &sfe4002_hwmon_info, sfe4002_lm87_regs); - if (rc) - return rc; - efx->board_info.monitor = sfe4002_check_hw; - efx->board_info.init_leds = sfe4002_init_leds; - efx->board_info.set_fault_led = sfe4002_fault_led; - efx->board_info.blink = board_blink; - efx->board_info.fini = efx_fini_lm87; - return 0; -} - -/* This will get expanded as board-specific details get moved out of the - * PHY drivers. */ -struct efx_board_data { - enum efx_board_type type; - const char *ref_model; - const char *gen_type; - int (*init) (struct efx_nic *nic); -}; - - -static struct efx_board_data board_data[] = { - { EFX_BOARD_SFE4001, "SFE4001", "10GBASE-T adapter", sfe4001_init }, - { EFX_BOARD_SFE4002, "SFE4002", "XFP adapter", sfe4002_init }, - { EFX_BOARD_SFN4111T, "SFN4111T", "100/1000/10GBASE-T adapter", - sfn4111t_init }, -}; - -void efx_set_board_info(struct efx_nic *efx, u16 revision_info) -{ - struct efx_board_data *data = NULL; - int i; - - efx->board_info.type = BOARD_TYPE(revision_info); - efx->board_info.major = BOARD_MAJOR(revision_info); - efx->board_info.minor = BOARD_MINOR(revision_info); - - for (i = 0; i < ARRAY_SIZE(board_data); i++) - if (board_data[i].type == efx->board_info.type) - data = &board_data[i]; - - if (data) { - EFX_INFO(efx, "board is %s rev %c%d\n", - (efx->pci_dev->subsystem_vendor == EFX_VENDID_SFC) - ? data->ref_model : data->gen_type, - 'A' + efx->board_info.major, efx->board_info.minor); - efx->board_info.init = data->init; - } else { - EFX_ERR(efx, "unknown board type %d\n", efx->board_info.type); - } -} diff --git a/drivers/net/sfc/boards.h b/drivers/net/sfc/boards.h deleted file mode 100644 index d93c6c6a754..00000000000 --- a/drivers/net/sfc/boards.h +++ /dev/null @@ -1,27 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2007-2008 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_BOARDS_H -#define EFX_BOARDS_H - -/* Board IDs (must fit in 8 bits) */ -enum efx_board_type { - EFX_BOARD_SFE4001 = 1, - EFX_BOARD_SFE4002 = 2, - EFX_BOARD_SFN4111T = 0x51, -}; - -extern void efx_set_board_info(struct efx_nic *efx, u16 revision_info); - -/* SFE4001 (10GBASE-T) */ -extern int sfe4001_init(struct efx_nic *efx); -/* SFN4111T (100/1000/10GBASE-T) */ -extern int sfn4111t_init(struct efx_nic *efx); - -#endif diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c deleted file mode 100644 index ab0e09bf154..00000000000 --- a/drivers/net/sfc/efx.c +++ /dev/null @@ -1,2274 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2005-2008 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. - */ - -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/delay.h> -#include <linux/notifier.h> -#include <linux/ip.h> -#include <linux/tcp.h> -#include <linux/in.h> -#include <linux/crc32.h> -#include <linux/ethtool.h> -#include <linux/topology.h> -#include "net_driver.h" -#include "ethtool.h" -#include "tx.h" -#include "rx.h" -#include "efx.h" -#include "mdio_10g.h" -#include "falcon.h" - -#define EFX_MAX_MTU (9 * 1024) - -/* RX slow fill workqueue. If memory allocation fails in the fast path, - * a work item is pushed onto this work queue to retry the allocation later, - * to avoid the NIC being starved of RX buffers. Since this is a per cpu - * workqueue, there is nothing to be gained in making it per NIC - */ -static struct workqueue_struct *refill_workqueue; - -/* Reset workqueue. If any NIC has a hardware failure then a reset will be - * queued onto this work queue. This is not a per-nic work queue, because - * efx_reset_work() acquires the rtnl lock, so resets are naturally serialised. - */ -static struct workqueue_struct *reset_workqueue; - -/************************************************************************** - * - * Configurable values - * - *************************************************************************/ - -/* - * Enable large receive offload (LRO) aka soft segment reassembly (SSR) - * - * This sets the default for new devices. It can be controlled later - * using ethtool. - */ -static int lro = true; -module_param(lro, int, 0644); -MODULE_PARM_DESC(lro, "Large receive offload acceleration"); - -/* - * Use separate channels for TX and RX events - * - * Set this to 1 to use separate channels for TX and RX. It allows us - * to control interrupt affinity separately for TX and RX. - * - * This is only used in MSI-X interrupt mode - */ -static unsigned int separate_tx_channels; -module_param(separate_tx_channels, uint, 0644); -MODULE_PARM_DESC(separate_tx_channels, - "Use separate channels for TX and RX"); - -/* This is the weight assigned to each of the (per-channel) virtual - * NAPI devices. - */ -static int napi_weight = 64; - -/* This is the time (in jiffies) between invocations of the hardware - * monitor, which checks for known hardware bugs and resets the - * hardware and driver as necessary. - */ -unsigned int efx_monitor_interval = 1 * HZ; - -/* This controls whether or not the driver will initialise devices - * with invalid MAC addresses stored in the EEPROM or flash. If true, - * such devices will be initialised with a random locally-generated - * MAC address. This allows for loading the sfc_mtd driver to - * reprogram the flash, even if the flash contents (including the MAC - * address) have previously been erased. - */ -static unsigned int allow_bad_hwaddr; - -/* Initial interrupt moderation settings. They can be modified after - * module load with ethtool. - * - * The default for RX should strike a balance between increasing the - * round-trip latency and reducing overhead. - */ -static unsigned int rx_irq_mod_usec = 60; - -/* Initial interrupt moderation settings. They can be modified after - * module load with ethtool. - * - * This default is chosen to ensure that a 10G link does not go idle - * while a TX queue is stopped after it has become full. A queue is - * restarted when it drops below half full. The time this takes (assuming - * worst case 3 descriptors per packet and 1024 descriptors) is - * 512 / 3 * 1.2 = 205 usec. - */ -static unsigned int tx_irq_mod_usec = 150; - -/* This is the first interrupt mode to try out of: - * 0 => MSI-X - * 1 => MSI - * 2 => legacy - */ -static unsigned int interrupt_mode; - -/* This is the requested number of CPUs to use for Receive-Side Scaling (RSS), - * i.e. the number of CPUs among which we may distribute simultaneous - * interrupt handling. - * - * Cards without MSI-X will only target one CPU via legacy or MSI interrupt. - * The default (0) means to assign an interrupt to each package (level II cache) - */ -static unsigned int rss_cpus; -module_param(rss_cpus, uint, 0444); -MODULE_PARM_DESC(rss_cpus, "Number of CPUs to use for Receive-Side Scaling"); - -static int phy_flash_cfg; -module_param(phy_flash_cfg, int, 0644); -MODULE_PARM_DESC(phy_flash_cfg, "Set PHYs into reflash mode initially"); - -/************************************************************************** - * - * Utility functions and prototypes - * - *************************************************************************/ -static void efx_remove_channel(struct efx_channel *channel); -static void efx_remove_port(struct efx_nic *efx); -static void efx_fini_napi(struct efx_nic *efx); -static void efx_fini_channels(struct efx_nic *efx); - -#define EFX_ASSERT_RESET_SERIALISED(efx) \ - do { \ - if (efx->state == STATE_RUNNING) \ - ASSERT_RTNL(); \ - } while (0) - -/************************************************************************** - * - * Event queue processing - * - *************************************************************************/ - -/* Process channel's event queue - * - * This function is responsible for processing the event queue of a - * single channel. The caller must guarantee that this function will - * never be concurrently called more than once on the same channel, - * though different channels may be being processed concurrently. - */ -static int efx_process_channel(struct efx_channel *channel, int rx_quota) -{ - struct efx_nic *efx = channel->efx; - int rx_packets; - - if (unlikely(efx->reset_pending != RESET_TYPE_NONE || - !channel->enabled)) - return 0; - - rx_packets = falcon_process_eventq(channel, rx_quota); - if (rx_packets == 0) - return 0; - - /* Deliver last RX packet. */ - if (channel->rx_pkt) { - __efx_rx_packet(channel, channel->rx_pkt, - channel->rx_pkt_csummed); - channel->rx_pkt = NULL; - } - - efx_flush_lro(channel); - efx_rx_strategy(channel); - - efx_fast_push_rx_descriptors(&efx->rx_queue[channel->channel]); - - return rx_packets; -} - -/* Mark channel as finished processing - * - * Note that since we will not receive further interrupts for this - * channel before we finish processing and call the eventq_read_ack() - * method, there is no need to use the interrupt hold-off timers. - */ -static inline void efx_channel_processed(struct efx_channel *channel) -{ - /* The interrupt handler for this channel may set work_pending - * as soon as we acknowledge the events we've seen. Make sure - * it's cleared before then. */ - channel->work_pending = false; - smp_wmb(); - - falcon_eventq_read_ack(channel); -} - -/* NAPI poll handler - * - * NAPI guarantees serialisation of polls of the same device, which - * provides the guarantee required by efx_process_channel(). - */ -static int efx_poll(struct napi_struct *napi, int budget) -{ - struct efx_channel *channel = - container_of(napi, struct efx_channel, napi_str); - int rx_packets; - - EFX_TRACE(channel->efx, "channel %d NAPI poll executing on CPU %d\n", - channel->channel, raw_smp_processor_id()); - - rx_packets = efx_process_channel(channel, budget); - - if (rx_packets < budget) { - /* There is no race here; although napi_disable() will - * only wait for netif_rx_complete(), this isn't a problem - * since efx_channel_processed() will have no effect if - * interrupts have already been disabled. - */ - netif_rx_complete(napi); - efx_channel_processed(channel); - } - - return rx_packets; -} - -/* Process the eventq of the specified channel immediately on this CPU - * - * Disable hardware generated interrupts, wait for any existing - * processing to finish, then directly poll (and ack ) the eventq. - * Finally reenable NAPI and interrupts. - * - * Since we are touching interrupts the caller should hold the suspend lock - */ -void efx_process_channel_now(struct efx_channel *channel) -{ - struct efx_nic *efx = channel->efx; - - BUG_ON(!channel->used_flags); - BUG_ON(!channel->enabled); - - /* Disable interrupts and wait for ISRs to complete */ - falcon_disable_interrupts(efx); - if (efx->legacy_irq) - synchronize_irq(efx->legacy_irq); - if (channel->irq) - synchronize_irq(channel->irq); - - /* Wait for any NAPI processing to complete */ - napi_disable(&channel->napi_str); - - /* Poll the channel */ - efx_process_channel(channel, efx->type->evq_size); - - /* Ack the eventq. This may cause an interrupt to be generated - * when they are reenabled */ - efx_channel_processed(channel); - - napi_enable(&channel->napi_str); - falcon_enable_interrupts(efx); -} - -/* Create event queue - * Event queue memory allocations are done only once. If the channel - * is reset, the memory buffer will be reused; this guards against - * errors during channel reset and also simplifies interrupt handling. - */ -static int efx_probe_eventq(struct efx_channel *channel) -{ - EFX_LOG(channel->efx, "chan %d create event queue\n", channel->channel); - - return falcon_probe_eventq(channel); -} - -/* Prepare channel's event queue */ -static void efx_init_eventq(struct efx_channel *channel) -{ - EFX_LOG(channel->efx, "chan %d init event queue\n", channel->channel); - - channel->eventq_read_ptr = 0; - - falcon_init_eventq(channel); -} - -static void efx_fini_eventq(struct efx_channel *channel) -{ - EFX_LOG(channel->efx, "chan %d fini event queue\n", channel->channel); - - falcon_fini_eventq(channel); -} - -static void efx_remove_eventq(struct efx_channel *channel) -{ - EFX_LOG(channel->efx, "chan %d remove event queue\n", channel->channel); - - falcon_remove_eventq(channel); -} - -/************************************************************************** - * - * Channel handling - * - *************************************************************************/ - -static int efx_probe_channel(struct efx_channel *channel) -{ - struct efx_tx_queue *tx_queue; - struct efx_rx_queue *rx_queue; - int rc; - - EFX_LOG(channel->efx, "creating channel %d\n", channel->channel); - - rc = efx_probe_eventq(channel); - if (rc) - goto fail1; - - efx_for_each_channel_tx_queue(tx_queue, channel) { - rc = efx_probe_tx_queue(tx_queue); - if (rc) - goto fail2; - } - - efx_for_each_channel_rx_queue(rx_queue, channel) { - rc = efx_probe_rx_queue(rx_queue); - if (rc) - goto fail3; - } - - channel->n_rx_frm_trunc = 0; - - return 0; - - fail3: - efx_for_each_channel_rx_queue(rx_queue, channel) - efx_remove_rx_queue(rx_queue); - fail2: - efx_for_each_channel_tx_queue(tx_queue, channel) - efx_remove_tx_queue(tx_queue); - fail1: - return rc; -} - - -static void efx_set_channel_names(struct efx_nic *efx) -{ - struct efx_channel *channel; - const char *type = ""; - int number; - - efx_for_each_channel(channel, efx) { - number = channel->channel; - if (efx->n_channels > efx->n_rx_queues) { - if (channel->channel < efx->n_rx_queues) { - type = "-rx"; - } else { - type = "-tx"; - number -= efx->n_rx_queues; - } - } - snprintf(channel->name, sizeof(channel->name), - "%s%s-%d", efx->name, type, number); - } -} - -/* Channels are shutdown and reinitialised whilst the NIC is running - * to propagate configuration changes (mtu, checksum offload), or - * to clear hardware error conditions - */ -static void efx_init_channels(struct efx_nic *efx) -{ - struct efx_tx_queue *tx_queue; - struct efx_rx_queue *rx_queue; - struct efx_channel *channel; - - /* Calculate the rx buffer allocation parameters required to - * support the current MTU, including padding for header - * alignment and overruns. - */ - efx->rx_buffer_len = (max(EFX_PAGE_IP_ALIGN, NET_IP_ALIGN) + - EFX_MAX_FRAME_LEN(efx->net_dev->mtu) + - efx->type->rx_buffer_padding); - efx->rx_buffer_order = get_order(efx->rx_buffer_len); - - /* Initialise the channels */ - efx_for_each_channel(channel, efx) { - EFX_LOG(channel->efx, "init chan %d\n", channel->channel); - - efx_init_eventq(channel); - - efx_for_each_channel_tx_queue(tx_queue, channel) - efx_init_tx_queue(tx_queue); - - /* The rx buffer allocation strategy is MTU dependent */ - efx_rx_strategy(channel); - - efx_for_each_channel_rx_queue(rx_queue, channel) - efx_init_rx_queue(rx_queue); - - WARN_ON(channel->rx_pkt != NULL); - efx_rx_strategy(channel); - } -} - -/* This enables event queue processing and packet transmission. - * - * Note that this function is not allowed to fail, since that would - * introduce too much complexity into the suspend/resume path. - */ -static void efx_start_channel(struct efx_channel *channel) -{ - struct efx_rx_queue *rx_queue; - - EFX_LOG(channel->efx, "starting chan %d\n", channel->channel); - - if (!(channel->efx->net_dev->flags & IFF_UP)) - netif_napi_add(channel->napi_dev, &channel->napi_str, - efx_poll, napi_weight); - - /* The interrupt handler for this channel may set work_pending - * as soon as we enable it. Make sure it's cleared before - * then. Similarly, make sure it sees the enabled flag set. */ - channel->work_pending = false; - channel->enabled = true; - smp_wmb(); - - napi_enable(&channel->napi_str); - - /* Load up RX descriptors */ - efx_for_each_channel_rx_queue(rx_queue, channel) - efx_fast_push_rx_descriptors(rx_queue); -} - -/* This disables event queue processing and packet transmission. - * This function does not guarantee that all queue processing - * (e.g. RX refill) is complete. - */ -static void efx_stop_channel(struct efx_channel *channel) -{ - struct efx_rx_queue *rx_queue; - - if (!channel->enabled) - return; - - EFX_LOG(channel->efx, "stop chan %d\n", channel->channel); - - channel->enabled = false; - napi_disable(&channel->napi_str); - - /* Ensure that any worker threads have exited or will be no-ops */ - efx_for_each_channel_rx_queue(rx_queue, channel) { - spin_lock_bh(&rx_queue->add_lock); - spin_unlock_bh(&rx_queue->add_lock); - } -} - -static void efx_fini_channels(struct efx_nic *efx) -{ - struct efx_channel *channel; - struct efx_tx_queue *tx_queue; - struct efx_rx_queue *rx_queue; - int rc; - - EFX_ASSERT_RESET_SERIALISED(efx); - BUG_ON(efx->port_enabled); - - rc = falcon_flush_queues(efx); - if (rc) - EFX_ERR(efx, "failed to flush queues\n"); - else - EFX_LOG(efx, "successfully flushed all queues\n"); - - efx_for_each_channel(channel, efx) { - EFX_LOG(channel->efx, "shut down chan %d\n", channel->channel); - - efx_for_each_channel_rx_queue(rx_queue, channel) - efx_fini_rx_queue(rx_queue); - efx_for_each_channel_tx_queue(tx_queue, channel) - efx_fini_tx_queue(tx_queue); - efx_fini_eventq(channel); - } -} - -static void efx_remove_channel(struct efx_channel *channel) -{ - struct efx_tx_queue *tx_queue; - struct efx_rx_queue *rx_queue; - - EFX_LOG(channel->efx, "destroy chan %d\n", channel->channel); - - efx_for_each_channel_rx_queue(rx_queue, channel) - efx_remove_rx_queue(rx_queue); - efx_for_each_channel_tx_queue(tx_queue, channel) - efx_remove_tx_queue(tx_queue); - efx_remove_eventq(channel); - - channel->used_flags = 0; -} - -void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue, int delay) -{ - queue_delayed_work(refill_workqueue, &rx_queue->work, delay); -} - -/************************************************************************** - * - * Port handling - * - **************************************************************************/ - -/* This ensures that the kernel is kept informed (via - * netif_carrier_on/off) of the link status, and also maintains the - * link status's stop on the port's TX queue. - */ -static void efx_link_status_changed(struct efx_nic *efx) -{ - /* SFC Bug 5356: A net_dev notifier is registered, so we must ensure - * that no events are triggered between unregister_netdev() and the - * driver unloading. A more general condition is that NETDEV_CHANGE - * can only be generated between NETDEV_UP and NETDEV_DOWN */ - if (!netif_running(efx->net_dev)) - return; - - if (efx->port_inhibited) { - netif_carrier_off(efx->net_dev); - return; - } - - if (efx->link_up != netif_carrier_ok(efx->net_dev)) { - efx->n_link_state_changes++; - - if (efx->link_up) - netif_carrier_on(efx->net_dev); - else - netif_carrier_off(efx->net_dev); - } - - /* Status message for kernel log */ - if (efx->link_up) { - EFX_INFO(efx, "link up at %uMbps %s-duplex (MTU %d)%s\n", - efx->link_speed, efx->link_fd ? "full" : "half", - efx->net_dev->mtu, - (efx->promiscuous ? " [PROMISC]" : "")); - } else { - EFX_INFO(efx, "link down\n"); - } - -} - -/* This call reinitialises the MAC to pick up new PHY settings. The - * caller must hold the mac_lock */ -void __efx_reconfigure_port(struct efx_nic *efx) -{ - WARN_ON(!mutex_is_locked(&efx->mac_lock)); - - EFX_LOG(efx, "reconfiguring MAC from PHY settings on CPU %d\n", - raw_smp_processor_id()); - - /* Serialise the promiscuous flag with efx_set_multicast_list. */ - if (efx_dev_registered(efx)) { - netif_addr_lock_bh(efx->net_dev); - netif_addr_unlock_bh(efx->net_dev); - } - - falcon_deconfigure_mac_wrapper(efx); - - /* Reconfigure the PHY, disabling transmit in mac level loopback. */ - if (LOOPBACK_INTERNAL(efx)) - efx->phy_mode |= PHY_MODE_TX_DISABLED; - else - efx->phy_mode &= ~PHY_MODE_TX_DISABLED; - efx->phy_op->reconfigure(efx); - - if (falcon_switch_mac(efx)) - goto fail; - - efx->mac_op->reconfigure(efx); - - /* Inform kernel of loss/gain of carrier */ - efx_link_status_changed(efx); - return; - -fail: - EFX_ERR(efx, "failed to reconfigure MAC\n"); - efx->phy_op->fini(efx); - efx->port_initialized = false; -} - -/* Reinitialise the MAC to pick up new PHY settings, even if the port is - * disabled. */ -void efx_reconfigure_port(struct efx_nic *efx) -{ - EFX_ASSERT_RESET_SERIALISED(efx); - - mutex_lock(&efx->mac_lock); - __efx_reconfigure_port(efx); - mutex_unlock(&efx->mac_lock); -} - -/* Asynchronous efx_reconfigure_port work item. To speed up efx_flush_all() - * we don't efx_reconfigure_port() if the port is disabled. Care is taken - * in efx_stop_all() and efx_start_port() to prevent PHY events being lost */ -static void efx_phy_work(struct work_struct *data) -{ - struct efx_nic *efx = container_of(data, struct efx_nic, phy_work); - - mutex_lock(&efx->mac_lock); - if (efx->port_enabled) - __efx_reconfigure_port(efx); - mutex_unlock(&efx->mac_lock); -} - -static void efx_mac_work(struct work_struct *data) -{ - struct efx_nic *efx = container_of(data, struct efx_nic, mac_work); - - mutex_lock(&efx->mac_lock); - if (efx->port_enabled) - efx->mac_op->irq(efx); - mutex_unlock(&efx->mac_lock); -} - -static int efx_probe_port(struct efx_nic *efx) -{ - int rc; - - EFX_LOG(efx, "create port\n"); - - /* Connect up MAC/PHY operations table and read MAC address */ - rc = falcon_probe_port(efx); - if (rc) - goto err; - - if (phy_flash_cfg) - efx->phy_mode = PHY_MODE_SPECIAL; - - /* Sanity check MAC address */ - if (is_valid_ether_addr(efx->mac_address)) { - memcpy(efx->net_dev->dev_addr, efx->mac_address, ETH_ALEN); - } else { - EFX_ERR(efx, "invalid MAC address %pM\n", - efx->mac_address); - if (!allow_bad_hwaddr) { - rc = -EINVAL; - goto err; - } - random_ether_addr(efx->net_dev->dev_addr); - EFX_INFO(efx, "using locally-generated MAC %pM\n", - efx->net_dev->dev_addr); - } - - return 0; - - err: - efx_remove_port(efx); - return rc; -} - -static int efx_init_port(struct efx_nic *efx) -{ - int rc; - - EFX_LOG(efx, "init port\n"); - - rc = efx->phy_op->init(efx); - if (rc) - return rc; - mutex_lock(&efx->mac_lock); - efx->phy_op->reconfigure(efx); - rc = falcon_switch_mac(efx); - mutex_unlock(&efx->mac_lock); - if (rc) - goto fail; - efx->mac_op->reconfigure(efx); - - efx->port_initialized = true; - efx_stats_enable(efx); - return 0; - -fail: - efx->phy_op->fini(efx); - return rc; -} - -/* Allow efx_reconfigure_port() to be scheduled, and close the window - * between efx_stop_port and efx_flush_all whereby a previously scheduled - * efx_phy_work()/efx_mac_work() may have been cancelled */ -static void efx_start_port(struct efx_nic *efx) -{ - EFX_LOG(efx, "start port\n"); - BUG_ON(efx->port_enabled); - - mutex_lock(&efx->mac_lock); - efx->port_enabled = true; - __efx_reconfigure_port(efx); - efx->mac_op->irq(efx); - mutex_unlock(&efx->mac_lock); -} - -/* Prevent efx_phy_work, efx_mac_work, and efx_monitor() from executing, - * and efx_set_multicast_list() from scheduling efx_phy_work. efx_phy_work - * and efx_mac_work may still be scheduled via NAPI processing until - * efx_flush_all() is called */ -static void efx_stop_port(struct efx_nic *efx) -{ - EFX_LOG(efx, "stop port\n"); - - mutex_lock(&efx->mac_lock); - efx->port_enabled = false; - mutex_unlock(&efx->mac_lock); - - /* Serialise against efx_set_multicast_list() */ - if (efx_dev_registered(efx)) { - netif_addr_lock_bh(efx->net_dev); - netif_addr_unlock_bh(efx->net_dev); - } -} - -static void efx_fini_port(struct efx_nic *efx) -{ - EFX_LOG(efx, "shut down port\n"); - - if (!efx->port_initialized) - return; - - efx_stats_disable(efx); - efx->phy_op->fini(efx); - efx->port_initialized = false; - - efx->link_up = false; - efx_link_status_changed(efx); -} - -static void efx_remove_port(struct efx_nic *efx) -{ - EFX_LOG(efx, "destroying port\n"); - - falcon_remove_port(efx); -} - -/************************************************************************** - * - * NIC handling - * - **************************************************************************/ - -/* This configures the PCI device to enable I/O and DMA. */ -static int efx_init_io(struct efx_nic *efx) -{ - struct pci_dev *pci_dev = efx->pci_dev; - dma_addr_t dma_mask = efx->type->max_dma_mask; - int rc; - - EFX_LOG(efx, "initialising I/O\n"); - - rc = pci_enable_device(pci_dev); - if (rc) { - EFX_ERR(efx, "failed to enable PCI device\n"); - goto fail1; - } - - pci_set_master(pci_dev); - - /* Set the PCI DMA mask. Try all possibilities from our - * genuine mask down to 32 bits, because some architectures - * (e.g. x86_64 with iommu_sac_force set) will allow 40 bit - * masks event though they reject 46 bit masks. - */ - while (dma_mask > 0x7fffffffUL) { - if (pci_dma_supported(pci_dev, dma_mask) && - ((rc = pci_set_dma_mask(pci_dev, dma_mask)) == 0)) - break; - dma_mask >>= 1; - } - if (rc) { - EFX_ERR(efx, "could not find a suitable DMA mask\n"); - goto fail2; - } - EFX_LOG(efx, "using DMA mask %llx\n", (unsigned long long) dma_mask); - rc = pci_set_consistent_dma_mask(pci_dev, dma_mask); - if (rc) { - /* pci_set_consistent_dma_mask() is not *allowed* to - * fail with a mask that pci_set_dma_mask() accepted, - * but just in case... - */ - EFX_ERR(efx, "failed to set consistent DMA mask\n"); - goto fail2; - } - - efx->membase_phys = pci_resource_start(efx->pci_dev, - efx->type->mem_bar); - rc = pci_request_region(pci_dev, efx->type->mem_bar, "sfc"); - if (rc) { - EFX_ERR(efx, "request for memory BAR failed\n"); - rc = -EIO; - goto fail3; - } - efx->membase = ioremap_nocache(efx->membase_phys, - efx->type->mem_map_size); - if (!efx->membase) { - EFX_ERR(efx, "could not map memory BAR %d at %llx+%x\n", - efx->type->mem_bar, - (unsigned long long)efx->membase_phys, - efx->type->mem_map_size); - rc = -ENOMEM; - goto fail4; - } - EFX_LOG(efx, "memory BAR %u at %llx+%x (virtual %p)\n", - efx->type->mem_bar, (unsigned long long)efx->membase_phys, - efx->type->mem_map_size, efx->membase); - - return 0; - - fail4: - pci_release_region(efx->pci_dev, efx->type->mem_bar); - fail3: - efx->membase_phys = 0; - fail2: - pci_disable_device(efx->pci_dev); - fail1: - return rc; -} - -static void efx_fini_io(struct efx_nic *efx) -{ - EFX_LOG(efx, "shutting down I/O\n"); - - if (efx->membase) { - iounmap(efx->membase); - efx->membase = NULL; - } - - if (efx->membase_phys) { - pci_release_region(efx->pci_dev, efx->type->mem_bar); - efx->membase_phys = 0; - } - - pci_disable_device(efx->pci_dev); -} - -/* Get number of RX queues wanted. Return number of online CPU - * packages in the expectation that an IRQ balancer will spread - * interrupts across them. */ -static int efx_wanted_rx_queues(void) -{ - cpumask_t core_mask; - int count; - int cpu; - - cpus_clear(core_mask); - count = 0; - for_each_online_cpu(cpu) { - if (!cpu_isset(cpu, core_mask)) { - ++count; - cpus_or(core_mask, core_mask, - topology_core_siblings(cpu)); - } - } - - return count; -} - -/* Probe the number and type of interrupts we are able to obtain, and - * the resulting numbers of channels and RX queues. - */ -static void efx_probe_interrupts(struct efx_nic *efx) -{ - int max_channels = - min_t(int, efx->type->phys_addr_channels, EFX_MAX_CHANNELS); - int rc, i; - - if (efx->interrupt_mode == EFX_INT_MODE_MSIX) { - struct msix_entry xentries[EFX_MAX_CHANNELS]; - int wanted_ints; - int rx_queues; - - /* We want one RX queue and interrupt per CPU package - * (or as specified by the rss_cpus module parameter). - * We will need one channel per interrupt. - */ - rx_queues = rss_cpus ? rss_cpus : efx_wanted_rx_queues(); - wanted_ints = rx_queues + (separate_tx_channels ? 1 : 0); - wanted_ints = min(wanted_ints, max_channels); - - for (i = 0; i < wanted_ints; i++) - xentries[i].entry = i; - rc = pci_enable_msix(efx->pci_dev, xentries, wanted_ints); - if (rc > 0) { - EFX_ERR(efx, "WARNING: Insufficient MSI-X vectors" - " available (%d < %d).\n", rc, wanted_ints); - EFX_ERR(efx, "WARNING: Performance may be reduced.\n"); - EFX_BUG_ON_PARANOID(rc >= wanted_ints); - wanted_ints = rc; - rc = pci_enable_msix(efx->pci_dev, xentries, - wanted_ints); - } - - if (rc == 0) { - efx->n_rx_queues = min(rx_queues, wanted_ints); - efx->n_channels = wanted_ints; - for (i = 0; i < wanted_ints; i++) - efx->channel[i].irq = xentries[i].vector; - } else { - /* Fall back to single channel MSI */ - efx->interrupt_mode = EFX_INT_MODE_MSI; - EFX_ERR(efx, "could not enable MSI-X\n"); - } - } - - /* Try single interrupt MSI */ - if (efx->interrupt_mode == EFX_INT_MODE_MSI) { - efx->n_rx_queues = 1; - efx->n_channels = 1; - rc = pci_enable_msi(efx->pci_dev); - if (rc == 0) { - efx->channel[0].irq = efx->pci_dev->irq; - } else { - EFX_ERR(efx, "could not enable MSI\n"); - efx->interrupt_mode = EFX_INT_MODE_LEGACY; - } - } - - /* Assume legacy interrupts */ - if (efx->interrupt_mode == EFX_INT_MODE_LEGACY) { - efx->n_rx_queues = 1; - efx->n_channels = 1 + (separate_tx_channels ? 1 : 0); - efx->legacy_irq = efx->pci_dev->irq; - } -} - -static void efx_remove_interrupts(struct efx_nic *efx) -{ - struct efx_channel *channel; - - /* Remove MSI/MSI-X interrupts */ - efx_for_each_channel(channel, efx) - channel->irq = 0; - pci_disable_msi(efx->pci_dev); - pci_disable_msix(efx->pci_dev); - - /* Remove legacy interrupt */ - efx->legacy_irq = 0; -} - -static void efx_set_channels(struct efx_nic *efx) -{ - struct efx_tx_queue *tx_queue; - struct efx_rx_queue *rx_queue; - - efx_for_each_tx_queue(tx_queue, efx) { - if (separate_tx_channels) - tx_queue->channel = &efx->channel[efx->n_channels-1]; - else - tx_queue->channel = &efx->channel[0]; - tx_queue->channel->used_flags |= EFX_USED_BY_TX; - } - - efx_for_each_rx_queue(rx_queue, efx) { - rx_queue->channel = &efx->channel[rx_queue->queue]; - rx_queue->channel->used_flags |= EFX_USED_BY_RX; - } -} - -static int efx_probe_nic(struct efx_nic *efx) -{ - int rc; - - EFX_LOG(efx, "creating NIC\n"); - - /* Carry out hardware-type specific initialisation */ - rc = falcon_probe_nic(efx); - if (rc) - return rc; - - /* Determine the number of channels and RX queues by trying to hook - * in MSI-X interrupts. */ - efx_probe_interrupts(efx); - - efx_set_channels(efx); - - /* Initialise the interrupt moderation settings */ - efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec); - - return 0; -} - -static void efx_remove_nic(struct efx_nic *efx) -{ - EFX_LOG(efx, "destroying NIC\n"); - - efx_remove_interrupts(efx); - falcon_remove_nic(efx); -} - -/************************************************************************** - * - * NIC startup/shutdown - * - *************************************************************************/ - -static int efx_probe_all(struct efx_nic *efx) -{ - struct efx_channel *channel; - int rc; - - /* Create NIC */ - rc = efx_probe_nic(efx); - if (rc) { - EFX_ERR(efx, "failed to create NIC\n"); - goto fail1; - } - - /* Create port */ - rc = efx_probe_port(efx); - if (rc) { - EFX_ERR(efx, "failed to create port\n"); - goto fail2; - } - - /* Create channels */ - efx_for_each_channel(channel, efx) { - rc = efx_probe_channel(channel); - if (rc) { - EFX_ERR(efx, "failed to create channel %d\n", - channel->channel); - goto fail3; - } - } - efx_set_channel_names(efx); - - return 0; - - fail3: - efx_for_each_channel(channel, efx) - efx_remove_channel(channel); - efx_remove_port(efx); - fail2: - efx_remove_nic(efx); - fail1: - return rc; -} - -/* Called after previous invocation(s) of efx_stop_all, restarts the - * port, kernel transmit queue, NAPI processing and hardware interrupts, - * and ensures that the port is scheduled to be reconfigured. - * This function is safe to call multiple times when the NIC is in any - * state. */ -static void efx_start_all(struct efx_nic *efx) -{ - struct efx_channel *channel; - - EFX_ASSERT_RESET_SERIALISED(efx); - - /* Check that it is appropriate to restart the interface. All - * of these flags are safe to read under just the rtnl lock */ - if (efx->port_enabled) - return; - if ((efx->state != STATE_RUNNING) && (efx->state != STATE_INIT)) - return; - if (efx_dev_registered(efx) && !netif_running(efx->net_dev)) - return; - - /* Mark the port as enabled so port reconfigurations can start, then - * restart the transmit interface early so the watchdog timer stops */ - efx_start_port(efx); - if (efx_dev_registered(efx)) - efx_wake_queue(efx); - - efx_for_each_channel(channel, efx) - efx_start_channel(channel); - - falcon_enable_interrupts(efx); - - /* Start hardware monitor if we're in RUNNING */ - if (efx->state == STATE_RUNNING) - queue_delayed_work(efx->workqueue, &efx->monitor_work, - efx_monitor_interval); -} - -/* Flush all delayed work. Should only be called when no more delayed work - * will be scheduled. This doesn't flush pending online resets (efx_reset), - * since we're holding the rtnl_lock at this point. */ -static void efx_flush_all(struct efx_nic *efx) -{ - struct efx_rx_queue *rx_queue; - - /* Make sure the hardware monitor is stopped */ - cancel_delayed_work_sync(&efx->monitor_work); - - /* Ensure that all RX slow refills are complete. */ - efx_for_each_rx_queue(rx_queue, efx) - cancel_delayed_work_sync(&rx_queue->work); - - /* Stop scheduled port reconfigurations */ - cancel_work_sync(&efx->mac_work); - cancel_work_sync(&efx->phy_work); - -} - -/* Quiesce hardware and software without bringing the link down. - * Safe to call multiple times, when the nic and interface is in any - * state. The caller is guaranteed to subsequently be in a position - * to modify any hardware and software state they see fit without - * taking locks. */ -static void efx_stop_all(struct efx_nic *efx) -{ - struct efx_channel *channel; - - EFX_ASSERT_RESET_SERIALISED(efx); - - /* port_enabled can be read safely under the rtnl lock */ - if (!efx->port_enabled) - return; - - /* Disable interrupts and wait for ISR to complete */ - falcon_disable_interrupts(efx); - if (efx->legacy_irq) - synchronize_irq(efx->legacy_irq); - efx_for_each_channel(channel, efx) { - if (channel->irq) - synchronize_irq(channel->irq); - } - - /* Stop all NAPI processing and synchronous rx refills */ - efx_for_each_channel(channel, efx) - efx_stop_channel(channel); - - /* Stop all asynchronous port reconfigurations. Since all - * event processing has already been stopped, there is no - * window to loose phy events */ - efx_stop_port(efx); - - /* Flush efx_phy_work, efx_mac_work, refill_workqueue, monitor_work */ - efx_flush_all(efx); - - /* Isolate the MAC from the TX and RX engines, so that queue - * flushes will complete in a timely fashion. */ - falcon_drain_tx_fifo(efx); - - /* Stop the kernel transmit interface late, so the watchdog - * timer isn't ticking over the flush */ - if (efx_dev_registered(efx)) { - efx_stop_queue(efx); - netif_tx_lock_bh(efx->net_dev); - netif_tx_unlock_bh(efx->net_dev); - } -} - -static void efx_remove_all(struct efx_nic *efx) -{ - struct efx_channel *channel; - - efx_for_each_channel(channel, efx) - efx_remove_channel(channel); - efx_remove_port(efx); - efx_remove_nic(efx); -} - -/* A convinience function to safely flush all the queues */ -void efx_flush_queues(struct efx_nic *efx) -{ - EFX_ASSERT_RESET_SERIALISED(efx); - - efx_stop_all(efx); - - efx_fini_channels(efx); - efx_init_channels(efx); - - efx_start_all(efx); -} - -/************************************************************************** - * - * Interrupt moderation - * - **************************************************************************/ - -/* Set interrupt moderation parameters */ -void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs) -{ - struct efx_tx_queue *tx_queue; - struct efx_rx_queue *rx_queue; - - EFX_ASSERT_RESET_SERIALISED(efx); - - efx_for_each_tx_queue(tx_queue, efx) - tx_queue->channel->irq_moderation = tx_usecs; - - efx_for_each_rx_queue(rx_queue, efx) - rx_queue->channel->irq_moderation = rx_usecs; -} - -/************************************************************************** - * - * Hardware monitor - * - **************************************************************************/ - -/* Run periodically off the general workqueue. Serialised against - * efx_reconfigure_port via the mac_lock */ -static void efx_monitor(struct work_struct *data) -{ - struct efx_nic *efx = container_of(data, struct efx_nic, - monitor_work.work); - int rc; - - EFX_TRACE(efx, "hardware monitor executing on CPU %d\n", - raw_smp_processor_id()); - - /* If the mac_lock is already held then it is likely a port - * reconfiguration is already in place, which will likely do - * most of the work of check_hw() anyway. */ - if (!mutex_trylock(&efx->mac_lock)) - goto out_requeue; - if (!efx->port_enabled) - goto out_unlock; - rc = efx->board_info.monitor(efx); - if (rc) { - EFX_ERR(efx, "Board sensor %s; shutting down PHY\n", - (rc == -ERANGE) ? "reported fault" : "failed"); - efx->phy_mode |= PHY_MODE_LOW_POWER; - falcon_sim_phy_event(efx); - } - efx->phy_op->poll(efx); - efx->mac_op->poll(efx); - -out_unlock: - mutex_unlock(&efx->mac_lock); -out_requeue: - queue_delayed_work(efx->workqueue, &efx->monitor_work, - efx_monitor_interval); -} - -/************************************************************************** - * - * ioctls - * - *************************************************************************/ - -/* Net device ioctl - * Context: process, rtnl_lock() held. - */ -static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd) -{ - struct efx_nic *efx = netdev_priv(net_dev); - - EFX_ASSERT_RESET_SERIALISED(efx); - - return generic_mii_ioctl(&efx->mii, if_mii(ifr), cmd, NULL); -} - -/************************************************************************** - * - * NAPI interface - * - **************************************************************************/ - -static int efx_init_napi(struct efx_nic *efx) -{ - struct efx_channel *channel; - int rc; - - efx_for_each_channel(channel, efx) { - channel->napi_dev = efx->net_dev; - rc = efx_lro_init(&channel->lro_mgr, efx); - if (rc) - goto err; - } - return 0; - err: - efx_fini_napi(efx); - return rc; -} - -static void efx_fini_napi(struct efx_nic *efx) -{ - struct efx_channel *channel; - - efx_for_each_channel(channel, efx) { - efx_lro_fini(&channel->lro_mgr); - channel->napi_dev = NULL; - } -} - -/************************************************************************** - * - * Kernel netpoll interface - * - *************************************************************************/ - -#ifdef CONFIG_NET_POLL_CONTROLLER - -/* Although in the common case interrupts will be disabled, this is not - * guaranteed. However, all our work happens inside the NAPI callback, - * so no locking is required. - */ -static void efx_netpoll(struct net_device *net_dev) -{ - struct efx_nic *efx = netdev_priv(net_dev); - struct efx_channel *channel; - - efx_for_each_channel(channel, efx) - efx_schedule_channel(channel); -} - -#endif - -/************************************************************************** - * - * Kernel net device interface - * - *************************************************************************/ - -/* Context: process, rtnl_lock() held. */ -static int efx_net_open(struct net_device *net_dev) -{ - struct efx_nic *efx = netdev_priv(net_dev); - EFX_ASSERT_RESET_SERIALISED(efx); - - EFX_LOG(efx, "opening device %s on CPU %d\n", net_dev->name, - raw_smp_processor_id()); - - if (efx->state == STATE_DISABLED) - return -EIO; - if (efx->phy_mode & PHY_MODE_SPECIAL) - return -EBUSY; - - efx_start_all(efx); - return 0; -} - -/* Context: process, rtnl_lock() held. - * Note that the kernel will ignore our return code; this method - * should really be a void. - */ -static int efx_net_stop(struct net_device *net_dev) -{ - struct efx_nic *efx = netdev_priv(net_dev); - - EFX_LOG(efx, "closing %s on CPU %d\n", net_dev->name, - raw_smp_processor_id()); - - if (efx->state != STATE_DISABLED) { - /* Stop the device and flush all the channels */ - efx_stop_all(efx); - efx_fini_channels(efx); - efx_init_channels(efx); - } - - return 0; -} - -void efx_stats_disable(struct efx_nic *efx) -{ - spin_lock(&efx->stats_lock); - ++efx->stats_disable_count; - spin_unlock(&efx->stats_lock); -} - -void efx_stats_enable(struct efx_nic *efx) -{ - spin_lock(&efx->stats_lock); - --efx->stats_disable_count; - spin_unlock(&efx->stats_lock); -} - -/* Context: process, dev_base_lock or RTNL held, non-blocking. */ -static struct net_device_stats *efx_net_stats(struct net_device *net_dev) -{ - struct efx_nic *efx = netdev_priv(net_dev); - struct efx_mac_stats *mac_stats = &efx->mac_stats; - struct net_device_stats *stats = &net_dev->stats; - - /* Update stats if possible, but do not wait if another thread - * is updating them or if MAC stats fetches are temporarily - * disabled; slightly stale stats are acceptable. - */ - if (!spin_trylock(&efx->stats_lock)) - return stats; - if (!efx->stats_disable_count) { - efx->mac_op->update_stats(efx); - falcon_update_nic_stats(efx); - } - spin_unlock(&efx->stats_lock); - - stats->rx_packets = mac_stats->rx_packets; - stats->tx_packets = mac_stats->tx_packets; - stats->rx_bytes = mac_stats->rx_bytes; - stats->tx_bytes = mac_stats->tx_bytes; - stats->multicast = mac_stats->rx_multicast; - stats->collisions = mac_stats->tx_collision; - stats->rx_length_errors = (mac_stats->rx_gtjumbo + - mac_stats->rx_length_error); - stats->rx_over_errors = efx->n_rx_nodesc_drop_cnt; - stats->rx_crc_errors = mac_stats->rx_bad; - stats->rx_frame_errors = mac_stats->rx_align_error; - stats->rx_fifo_errors = mac_stats->rx_overflow; - stats->rx_missed_errors = mac_stats->rx_missed; - stats->tx_window_errors = mac_stats->tx_late_collision; - - stats->rx_errors = (stats->rx_length_errors + - stats->rx_over_errors + - stats->rx_crc_errors + - stats->rx_frame_errors + - stats->rx_fifo_errors + - stats->rx_missed_errors + - mac_stats->rx_symbol_error); - stats->tx_errors = (stats->tx_window_errors + - mac_stats->tx_bad); - - return stats; -} - -/* Context: netif_tx_lock held, BHs disabled. */ -static void efx_watchdog(struct net_device *net_dev) -{ - struct efx_nic *efx = netdev_priv(net_dev); - - EFX_ERR(efx, "TX stuck with stop_count=%d port_enabled=%d:" - " resetting channels\n", - atomic_read(&efx->netif_stop_count), efx->port_enabled); - - efx_schedule_reset(efx, RESET_TYPE_TX_WATCHDOG); -} - - -/* Context: process, rtnl_lock() held. */ -static int efx_change_mtu(struct net_device *net_dev, int new_mtu) -{ - struct efx_nic *efx = netdev_priv(net_dev); - int rc = 0; - - EFX_ASSERT_RESET_SERIALISED(efx); - - if (new_mtu > EFX_MAX_MTU) - return -EINVAL; - - efx_stop_all(efx); - - EFX_LOG(efx, "changing MTU to %d\n", new_mtu); - - efx_fini_channels(efx); - net_dev->mtu = new_mtu; - efx_init_channels(efx); - - efx_start_all(efx); - return rc; -} - -static int efx_set_mac_address(struct net_device *net_dev, void *data) -{ - struct efx_nic *efx = netdev_priv(net_dev); - struct sockaddr *addr = data; - char *new_addr = addr->sa_data; - - EFX_ASSERT_RESET_SERIALISED(efx); - - if (!is_valid_ether_addr(new_addr)) { - EFX_ERR(efx, "invalid ethernet MAC address requested: %pM\n", - new_addr); - return -EINVAL; - } - - memcpy(net_dev->dev_addr, new_addr, net_dev->addr_len); - - /* Reconfigure the MAC */ - efx_reconfigure_port(efx); - - return 0; -} - -/* Context: netif_addr_lock held, BHs disabled. */ -static void efx_set_multicast_list(struct net_device *net_dev) -{ - struct efx_nic *efx = netdev_priv(net_dev); - struct dev_mc_list *mc_list = net_dev->mc_list; - union efx_multicast_hash *mc_hash = &efx->multicast_hash; - bool promiscuous = !!(net_dev->flags & IFF_PROMISC); - bool changed = (efx->promiscuous != promiscuous); - u32 crc; - int bit; - int i; - - efx->promiscuous = promiscuous; - - /* Build multicast hash table */ - if (promiscuous || (net_dev->flags & IFF_ALLMULTI)) { - memset(mc_hash, 0xff, sizeof(*mc_hash)); - } else { - memset(mc_hash, 0x00, sizeof(*mc_hash)); - for (i = 0; i < net_dev->mc_count; i++) { - crc = ether_crc_le(ETH_ALEN, mc_list->dmi_addr); - bit = crc & (EFX_MCAST_HASH_ENTRIES - 1); - set_bit_le(bit, mc_hash->byte); - mc_list = mc_list->next; - } - } - - if (!efx->port_enabled) - /* Delay pushing settings until efx_start_port() */ - return; - - if (changed) - queue_work(efx->workqueue, &efx->phy_work); - - /* Create and activate new global multicast hash table */ - falcon_set_multicast_hash(efx); -} - -static const struct net_device_ops efx_netdev_ops = { - .ndo_open = efx_net_open, - .ndo_stop = efx_net_stop, - .ndo_get_stats = 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_multicast_list = efx_set_multicast_list, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = efx_netpoll, -#endif -}; - -static void efx_update_name(struct efx_nic *efx) -{ - strcpy(efx->name, efx->net_dev->name); - efx_mtd_rename(efx); - efx_set_channel_names(efx); -} - -static int efx_netdev_event(struct notifier_block *this, - unsigned long event, void *ptr) -{ - struct net_device *net_dev = ptr; - - if (net_dev->netdev_ops == &efx_netdev_ops && - event == NETDEV_CHANGENAME) - efx_update_name(netdev_priv(net_dev)); - - return NOTIFY_DONE; -} - -static struct notifier_block efx_netdev_notifier = { - .notifier_call = efx_netdev_event, -}; - -static ssize_t -show_phy_type(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); - return sprintf(buf, "%d\n", efx->phy_type); -} -static DEVICE_ATTR(phy_type, 0644, show_phy_type, NULL); - -static int efx_register_netdev(struct efx_nic *efx) -{ - struct net_device *net_dev = efx->net_dev; - int rc; - - net_dev->watchdog_timeo = 5 * HZ; - net_dev->irq = efx->pci_dev->irq; - net_dev->netdev_ops = &efx_netdev_ops; - SET_NETDEV_DEV(net_dev, &efx->pci_dev->dev); - SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops); - - /* Always start with carrier off; PHY events will detect the link */ - netif_carrier_off(efx->net_dev); - - /* Clear MAC statistics */ - efx->mac_op->update_stats(efx); - memset(&efx->mac_stats, 0, sizeof(efx->mac_stats)); - - rc = register_netdev(net_dev); - if (rc) { - EFX_ERR(efx, "could not register net dev\n"); - return rc; - } - - rtnl_lock(); - efx_update_name(efx); - rtnl_unlock(); - - rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_type); - if (rc) { - EFX_ERR(efx, "failed to init net dev attributes\n"); - goto fail_registered; - } - - return 0; - -fail_registered: - unregister_netdev(net_dev); - return rc; -} - -static void efx_unregister_netdev(struct efx_nic *efx) -{ - struct efx_tx_queue *tx_queue; - - if (!efx->net_dev) - return; - - BUG_ON(netdev_priv(efx->net_dev) != efx); - - /* Free up any skbs still remaining. This has to happen before - * we try to unregister the netdev as running their destructors - * may be needed to get the device ref. count to 0. */ - efx_for_each_tx_queue(tx_queue, efx) - efx_release_tx_buffers(tx_queue); - - if (efx_dev_registered(efx)) { - strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name)); - device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_type); - unregister_netdev(efx->net_dev); - } -} - -/************************************************************************** - * - * Device reset and suspend - * - **************************************************************************/ - -/* Tears down the entire software state and most of the hardware state - * before reset. */ -void efx_reset_down(struct efx_nic *efx, enum reset_type method, - struct ethtool_cmd *ecmd) -{ - EFX_ASSERT_RESET_SERIALISED(efx); - - efx_stats_disable(efx); - efx_stop_all(efx); - mutex_lock(&efx->mac_lock); - mutex_lock(&efx->spi_lock); - - efx->phy_op->get_settings(efx, ecmd); - - efx_fini_channels(efx); - if (efx->port_initialized && method != RESET_TYPE_INVISIBLE) - efx->phy_op->fini(efx); -} - -/* This function will always ensure that the locks acquired in - * efx_reset_down() are released. A failure return code indicates - * that we were unable to reinitialise the hardware, and the - * driver should be disabled. If ok is false, then the rx and tx - * engines are not restarted, pending a RESET_DISABLE. */ -int efx_reset_up(struct efx_nic *efx, enum reset_type method, - struct ethtool_cmd *ecmd, bool ok) -{ - int rc; - - EFX_ASSERT_RESET_SERIALISED(efx); - - rc = falcon_init_nic(efx); - if (rc) { - EFX_ERR(efx, "failed to initialise NIC\n"); - ok = false; - } - - if (efx->port_initialized && method != RESET_TYPE_INVISIBLE) { - if (ok) { - rc = efx->phy_op->init(efx); - if (rc) - ok = false; - } else - efx->port_initialized = false; - } - - if (ok) { - efx_init_channels(efx); - - if (efx->phy_op->set_settings(efx, ecmd)) - EFX_ERR(efx, "could not restore PHY settings\n"); - } - - mutex_unlock(&efx->spi_lock); - mutex_unlock(&efx->mac_lock); - - if (ok) { - efx_start_all(efx); - efx_stats_enable(efx); - } - return rc; -} - -/* Reset the NIC as transparently as possible. Do not reset the PHY - * Note that the reset may fail, in which case the card will be left - * in a most-probably-unusable state. - * - * This function will sleep. You cannot reset from within an atomic - * state; use efx_schedule_reset() instead. - * - * Grabs the rtnl_lock. - */ -static int efx_reset(struct efx_nic *efx) -{ - struct ethtool_cmd ecmd; - enum reset_type method = efx->reset_pending; - int rc = 0; - - /* Serialise with kernel interfaces */ - rtnl_lock(); - - /* If we're not RUNNING then don't reset. Leave the reset_pending - * flag set so that efx_pci_probe_main will be retried */ - if (efx->state != STATE_RUNNING) { - EFX_INFO(efx, "scheduled reset quenched. NIC not RUNNING\n"); - goto out_unlock; - } - - EFX_INFO(efx, "resetting (%d)\n", method); - - efx_reset_down(efx, method, &ecmd); - - rc = falcon_reset_hw(efx, method); - if (rc) { - EFX_ERR(efx, "failed to reset hardware\n"); - goto out_disable; - } - - /* Allow resets to be rescheduled. */ - efx->reset_pending = RESET_TYPE_NONE; - - /* Reinitialise bus-mastering, which may have been turned off before - * the reset was scheduled. This is still appropriate, even in the - * RESET_TYPE_DISABLE since this driver generally assumes the hardware - * can respond to requests. */ - pci_set_master(efx->pci_dev); - - /* Leave device stopped if necessary */ - if (method == RESET_TYPE_DISABLE) { - efx_reset_up(efx, method, &ecmd, false); - rc = -EIO; - } else { - rc = efx_reset_up(efx, method, &ecmd, true); - } - -out_disable: - if (rc) { - EFX_ERR(efx, "has been disabled\n"); - efx->state = STATE_DISABLED; - dev_close(efx->net_dev); - } else { - EFX_LOG(efx, "reset complete\n"); - } - -out_unlock: - rtnl_unlock(); - return rc; -} - -/* The worker thread exists so that code that cannot sleep can - * schedule a reset for later. - */ -static void efx_reset_work(struct work_struct *data) -{ - struct efx_nic *nic = container_of(data, struct efx_nic, reset_work); - - efx_reset(nic); -} - -void efx_schedule_reset(struct efx_nic *efx, enum reset_type type) -{ - enum reset_type method; - - if (efx->reset_pending != RESET_TYPE_NONE) { - EFX_INFO(efx, "quenching already scheduled reset\n"); - return; - } - - switch (type) { - case RESET_TYPE_INVISIBLE: - case RESET_TYPE_ALL: - case RESET_TYPE_WORLD: - case RESET_TYPE_DISABLE: - method = type; - break; - case RESET_TYPE_RX_RECOVERY: - case RESET_TYPE_RX_DESC_FETCH: - case RESET_TYPE_TX_DESC_FETCH: - case RESET_TYPE_TX_SKIP: - method = RESET_TYPE_INVISIBLE; - break; - default: - method = RESET_TYPE_ALL; - break; - } - - if (method != type) - EFX_LOG(efx, "scheduling reset (%d:%d)\n", type, method); - else - EFX_LOG(efx, "scheduling reset (%d)\n", method); - - efx->reset_pending = method; - - queue_work(reset_workqueue, &efx->reset_work); -} - -/************************************************************************** - * - * List of NICs we support - * - **************************************************************************/ - -/* PCI device ID table */ -static struct pci_device_id efx_pci_table[] __devinitdata = { - {PCI_DEVICE(EFX_VENDID_SFC, FALCON_A_P_DEVID), - .driver_data = (unsigned long) &falcon_a_nic_type}, - {PCI_DEVICE(EFX_VENDID_SFC, FALCON_B_P_DEVID), - .driver_data = (unsigned long) &falcon_b_nic_type}, - {0} /* end of list */ -}; - -/************************************************************************** - * - * Dummy PHY/MAC/Board operations - * - * Can be used for some unimplemented operations - * Needed so all function pointers are valid and do not have to be tested - * before use - * - **************************************************************************/ -int efx_port_dummy_op_int(struct efx_nic *efx) -{ - return 0; -} -void efx_port_dummy_op_void(struct efx_nic *efx) {} -void efx_port_dummy_op_blink(struct efx_nic *efx, bool blink) {} - -static struct efx_mac_operations efx_dummy_mac_operations = { - .reconfigure = efx_port_dummy_op_void, - .poll = efx_port_dummy_op_void, - .irq = efx_port_dummy_op_void, -}; - -static struct efx_phy_operations efx_dummy_phy_operations = { - .init = efx_port_dummy_op_int, - .reconfigure = efx_port_dummy_op_void, - .poll = efx_port_dummy_op_void, - .fini = efx_port_dummy_op_void, - .clear_interrupt = efx_port_dummy_op_void, -}; - -static struct efx_board efx_dummy_board_info = { - .init = efx_port_dummy_op_int, - .init_leds = efx_port_dummy_op_int, - .set_fault_led = efx_port_dummy_op_blink, - .monitor = efx_port_dummy_op_int, - .blink = efx_port_dummy_op_blink, - .fini = efx_port_dummy_op_void, -}; - -/************************************************************************** - * - * Data housekeeping - * - **************************************************************************/ - -/* This zeroes out and then fills in the invariants in a struct - * efx_nic (including all sub-structures). - */ -static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, - struct pci_dev *pci_dev, struct net_device *net_dev) -{ - struct efx_channel *channel; - struct efx_tx_queue *tx_queue; - struct efx_rx_queue *rx_queue; - int i; - - /* Initialise common structures */ - memset(efx, 0, sizeof(*efx)); - spin_lock_init(&efx->biu_lock); - spin_lock_init(&efx->phy_lock); - mutex_init(&efx->spi_lock); - INIT_WORK(&efx->reset_work, efx_reset_work); - INIT_DELAYED_WORK(&efx->monitor_work, efx_monitor); - efx->pci_dev = pci_dev; - efx->state = STATE_INIT; - efx->reset_pending = RESET_TYPE_NONE; - strlcpy(efx->name, pci_name(pci_dev), sizeof(efx->name)); - efx->board_info = efx_dummy_board_info; - - efx->net_dev = net_dev; - efx->rx_checksum_enabled = true; - spin_lock_init(&efx->netif_stop_lock); - spin_lock_init(&efx->stats_lock); - efx->stats_disable_count = 1; - mutex_init(&efx->mac_lock); - efx->mac_op = &efx_dummy_mac_operations; - efx->phy_op = &efx_dummy_phy_operations; - efx->mii.dev = net_dev; - INIT_WORK(&efx->phy_work, efx_phy_work); - INIT_WORK(&efx->mac_work, efx_mac_work); - atomic_set(&efx->netif_stop_count, 1); - - for (i = 0; i < EFX_MAX_CHANNELS; i++) { - channel = &efx->channel[i]; - channel->efx = efx; - channel->channel = i; - channel->work_pending = false; - } - for (i = 0; i < EFX_TX_QUEUE_COUNT; i++) { - tx_queue = &efx->tx_queue[i]; - tx_queue->efx = efx; - tx_queue->queue = i; - tx_queue->buffer = NULL; - tx_queue->channel = &efx->channel[0]; /* for safety */ - tx_queue->tso_headers_free = NULL; - } - for (i = 0; i < EFX_MAX_RX_QUEUES; i++) { - rx_queue = &efx->rx_queue[i]; - rx_queue->efx = efx; - rx_queue->queue = i; - rx_queue->channel = &efx->channel[0]; /* for safety */ - rx_queue->buffer = NULL; - spin_lock_init(&rx_queue->add_lock); - INIT_DELAYED_WORK(&rx_queue->work, efx_rx_work); - } - - efx->type = type; - - /* Sanity-check NIC type */ - EFX_BUG_ON_PARANOID(efx->type->txd_ring_mask & - (efx->type->txd_ring_mask + 1)); - EFX_BUG_ON_PARANOID(efx->type->rxd_ring_mask & - (efx->type->rxd_ring_mask + 1)); - EFX_BUG_ON_PARANOID(efx->type->evq_size & - (efx->type->evq_size - 1)); - /* As close as we can get to guaranteeing that we don't overflow */ - EFX_BUG_ON_PARANOID(efx->type->evq_size < - (efx->type->txd_ring_mask + 1 + - efx->type->rxd_ring_mask + 1)); - EFX_BUG_ON_PARANOID(efx->type->phys_addr_channels > EFX_MAX_CHANNELS); - - /* Higher numbered interrupt modes are less capable! */ - efx->interrupt_mode = max(efx->type->max_interrupt_mode, - interrupt_mode); - - /* Would be good to use the net_dev name, but we're too early */ - snprintf(efx->workqueue_name, sizeof(efx->workqueue_name), "sfc%s", - pci_name(pci_dev)); - efx->workqueue = create_singlethread_workqueue(efx->workqueue_name); - if (!efx->workqueue) - return -ENOMEM; - - return 0; -} - -static void efx_fini_struct(struct efx_nic *efx) -{ - if (efx->workqueue) { - destroy_workqueue(efx->workqueue); - efx->workqueue = NULL; - } -} - -/************************************************************************** - * - * PCI interface - * - **************************************************************************/ - -/* Main body of final NIC shutdown code - * This is called only at module unload (or hotplug removal). - */ -static void efx_pci_remove_main(struct efx_nic *efx) -{ - EFX_ASSERT_RESET_SERIALISED(efx); - - /* Skip everything if we never obtained a valid membase */ - if (!efx->membase) - return; - - efx_fini_channels(efx); - efx_fini_port(efx); - - /* Shutdown the board, then the NIC and board state */ - efx->board_info.fini(efx); - falcon_fini_interrupt(efx); - - efx_fini_napi(efx); - efx_remove_all(efx); -} - -/* Final NIC shutdown - * This is called only at module unload (or hotplug removal). - */ -static void efx_pci_remove(struct pci_dev *pci_dev) -{ - struct efx_nic *efx; - - efx = pci_get_drvdata(pci_dev); - if (!efx) - return; - - /* Mark the NIC as fini, then stop the interface */ - rtnl_lock(); - efx->state = STATE_FINI; - dev_close(efx->net_dev); - - /* Allow any queued efx_resets() to complete */ - rtnl_unlock(); - - if (efx->membase == NULL) - goto out; - - efx_unregister_netdev(efx); - - efx_mtd_remove(efx); - - /* Wait for any scheduled resets to complete. No more will be - * scheduled from this point because efx_stop_all() has been - * called, we are no longer registered with driverlink, and - * the net_device's have been removed. */ - cancel_work_sync(&efx->reset_work); - - efx_pci_remove_main(efx); - -out: - efx_fini_io(efx); - EFX_LOG(efx, "shutdown successful\n"); - - pci_set_drvdata(pci_dev, NULL); - efx_fini_struct(efx); - free_netdev(efx->net_dev); -}; - -/* Main body of NIC initialisation - * This is called at module load (or hotplug insertion, theoretically). - */ -static int efx_pci_probe_main(struct efx_nic *efx) -{ - int rc; - - /* Do start-of-day initialisation */ - rc = efx_probe_all(efx); - if (rc) - goto fail1; - - rc = efx_init_napi(efx); - if (rc) - goto fail2; - - /* Initialise the board */ - rc = efx->board_info.init(efx); - if (rc) { - EFX_ERR(efx, "failed to initialise board\n"); - goto fail3; - } - - rc = falcon_init_nic(efx); - if (rc) { - EFX_ERR(efx, "failed to initialise NIC\n"); - goto fail4; - } - - rc = efx_init_port(efx); - if (rc) { - EFX_ERR(efx, "failed to initialise port\n"); - goto fail5; - } - - efx_init_channels(efx); - - rc = falcon_init_interrupt(efx); - if (rc) - goto fail6; - - return 0; - - fail6: - efx_fini_channels(efx); - efx_fini_port(efx); - fail5: - fail4: - efx->board_info.fini(efx); - fail3: - efx_fini_napi(efx); - fail2: - efx_remove_all(efx); - fail1: - return rc; -} - -/* NIC initialisation - * - * This is called at module load (or hotplug insertion, - * theoretically). It sets up PCI mappings, tests and resets the NIC, - * sets up and registers the network devices with the kernel and hooks - * the interrupt service routine. It does not prepare the device for - * transmission; this is left to the first time one of the network - * interfaces is brought up (i.e. efx_net_open). - */ -static int __devinit efx_pci_probe(struct pci_dev *pci_dev, - const struct pci_device_id *entry) -{ - struct efx_nic_type *type = (struct efx_nic_type *) entry->driver_data; - struct net_device *net_dev; - struct efx_nic *efx; - int i, rc; - - /* Allocate and initialise a struct net_device and struct efx_nic */ - net_dev = alloc_etherdev(sizeof(*efx)); - if (!net_dev) - return -ENOMEM; - net_dev->features |= (NETIF_F_IP_CSUM | NETIF_F_SG | - NETIF_F_HIGHDMA | NETIF_F_TSO); - if (lro) - net_dev->features |= NETIF_F_LRO; - /* Mask for features that also apply to VLAN devices */ - net_dev->vlan_features |= (NETIF_F_ALL_CSUM | NETIF_F_SG | - NETIF_F_HIGHDMA | NETIF_F_TSO); - efx = netdev_priv(net_dev); - pci_set_drvdata(pci_dev, efx); - rc = efx_init_struct(efx, type, pci_dev, net_dev); - if (rc) - goto fail1; - - EFX_INFO(efx, "Solarflare Communications NIC detected\n"); - - /* Set up basic I/O (BAR mappings etc) */ - rc = efx_init_io(efx); - if (rc) - goto fail2; - - /* No serialisation is required with the reset path because - * we're in STATE_INIT. */ - for (i = 0; i < 5; i++) { - rc = efx_pci_probe_main(efx); - - /* Serialise against efx_reset(). No more resets will be - * scheduled since efx_stop_all() has been called, and we - * have not and never have been registered with either - * the rtnetlink or driverlink layers. */ - cancel_work_sync(&efx->reset_work); - - if (rc == 0) { - if (efx->reset_pending != RESET_TYPE_NONE) { - /* If there was a scheduled reset during - * probe, the NIC is probably hosed anyway */ - efx_pci_remove_main(efx); - rc = -EIO; - } else { - break; - } - } - - /* Retry if a recoverably reset event has been scheduled */ - if ((efx->reset_pending != RESET_TYPE_INVISIBLE) && - (efx->reset_pending != RESET_TYPE_ALL)) - goto fail3; - - efx->reset_pending = RESET_TYPE_NONE; - } - - if (rc) { - EFX_ERR(efx, "Could not reset NIC\n"); - goto fail4; - } - - /* Switch to the running state before we expose the device to - * the OS. This is to ensure that the initial gathering of - * MAC stats succeeds. */ - efx->state = STATE_RUNNING; - - efx_mtd_probe(efx); /* allowed to fail */ - - rc = efx_register_netdev(efx); - if (rc) - goto fail5; - - EFX_LOG(efx, "initialisation successful\n"); - return 0; - - fail5: - efx_pci_remove_main(efx); - fail4: - fail3: - efx_fini_io(efx); - fail2: - efx_fini_struct(efx); - fail1: - EFX_LOG(efx, "initialisation failed. rc=%d\n", rc); - free_netdev(net_dev); - return rc; -} - -static struct pci_driver efx_pci_driver = { - .name = EFX_DRIVER_NAME, - .id_table = efx_pci_table, - .probe = efx_pci_probe, - .remove = efx_pci_remove, -}; - -/************************************************************************** - * - * Kernel module interface - * - *************************************************************************/ - -module_param(interrupt_mode, uint, 0444); -MODULE_PARM_DESC(interrupt_mode, - "Interrupt mode (0=>MSIX 1=>MSI 2=>legacy)"); - -static int __init efx_init_module(void) -{ - int rc; - - printk(KERN_INFO "Solarflare NET driver v" EFX_DRIVER_VERSION "\n"); - - rc = register_netdevice_notifier(&efx_netdev_notifier); - if (rc) - goto err_notifier; - - refill_workqueue = create_workqueue("sfc_refill"); - if (!refill_workqueue) { - rc = -ENOMEM; - goto err_refill; - } - reset_workqueue = create_singlethread_workqueue("sfc_reset"); - if (!reset_workqueue) { - rc = -ENOMEM; - goto err_reset; - } - - rc = pci_register_driver(&efx_pci_driver); - if (rc < 0) - goto err_pci; - - return 0; - - err_pci: - destroy_workqueue(reset_workqueue); - err_reset: - destroy_workqueue(refill_workqueue); - err_refill: - unregister_netdevice_notifier(&efx_netdev_notifier); - err_notifier: - return rc; -} - -static void __exit efx_exit_module(void) -{ - printk(KERN_INFO "Solarflare NET driver unloading\n"); - - pci_unregister_driver(&efx_pci_driver); - destroy_workqueue(reset_workqueue); - destroy_workqueue(refill_workqueue); - unregister_netdevice_notifier(&efx_netdev_notifier); - -} - -module_init(efx_init_module); -module_exit(efx_exit_module); - -MODULE_AUTHOR("Michael Brown <mbrown@fensystems.co.uk> and " - "Solarflare Communications"); -MODULE_DESCRIPTION("Solarflare Communications network driver"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, efx_pci_table); diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h deleted file mode 100644 index 55d0f131b0e..00000000000 --- a/drivers/net/sfc/efx.h +++ /dev/null @@ -1,86 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2006-2008 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_EFX_H -#define EFX_EFX_H - -#include "net_driver.h" - -/* PCI IDs */ -#define EFX_VENDID_SFC 0x1924 -#define FALCON_A_P_DEVID 0x0703 -#define FALCON_A_S_DEVID 0x6703 -#define FALCON_B_P_DEVID 0x0710 - -/* TX */ -extern int efx_xmit(struct efx_nic *efx, - struct efx_tx_queue *tx_queue, struct sk_buff *skb); -extern void efx_stop_queue(struct efx_nic *efx); -extern void efx_wake_queue(struct efx_nic *efx); - -/* RX */ -extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index); -extern void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index, - unsigned int len, bool checksummed, bool discard); -extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue, int delay); - -/* Channels */ -extern void efx_process_channel_now(struct efx_channel *channel); -extern void efx_flush_queues(struct efx_nic *efx); - -/* Ports */ -extern void efx_stats_disable(struct efx_nic *efx); -extern void efx_stats_enable(struct efx_nic *efx); -extern void efx_reconfigure_port(struct efx_nic *efx); -extern void __efx_reconfigure_port(struct efx_nic *efx); - -/* Reset handling */ -extern void efx_reset_down(struct efx_nic *efx, enum reset_type method, - struct ethtool_cmd *ecmd); -extern int efx_reset_up(struct efx_nic *efx, enum reset_type method, - struct ethtool_cmd *ecmd, bool ok); - -/* Global */ -extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type); -extern void efx_suspend(struct efx_nic *efx); -extern void efx_resume(struct efx_nic *efx); -extern void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, - int rx_usecs); -extern int efx_request_power(struct efx_nic *efx, int mw, const char *name); -extern void efx_hex_dump(const u8 *, unsigned int, const char *); - -/* Dummy PHY ops for PHY drivers */ -extern int efx_port_dummy_op_int(struct efx_nic *efx); -extern void efx_port_dummy_op_void(struct efx_nic *efx); -extern void efx_port_dummy_op_blink(struct efx_nic *efx, bool blink); - -/* MTD */ -#ifdef CONFIG_SFC_MTD -extern int efx_mtd_probe(struct efx_nic *efx); -extern void efx_mtd_rename(struct efx_nic *efx); -extern void efx_mtd_remove(struct efx_nic *efx); -#else -static inline int efx_mtd_probe(struct efx_nic *efx) { return 0; } -static inline void efx_mtd_rename(struct efx_nic *efx) {} -static inline void efx_mtd_remove(struct efx_nic *efx) {} -#endif - -extern unsigned int efx_monitor_interval; - -static inline void efx_schedule_channel(struct efx_channel *channel) -{ - EFX_TRACE(channel->efx, "channel %d scheduling NAPI poll on CPU%d\n", - channel->channel, raw_smp_processor_id()); - channel->work_pending = true; - - netif_rx_schedule(&channel->napi_str); -} - -#endif /* EFX_EFX_H */ diff --git a/drivers/net/sfc/enum.h b/drivers/net/sfc/enum.h deleted file mode 100644 index 60cbc6e1e66..00000000000 --- a/drivers/net/sfc/enum.h +++ /dev/null @@ -1,104 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2007-2008 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_ENUM_H -#define EFX_ENUM_H - -/** - * enum efx_loopback_mode - loopback modes - * @LOOPBACK_NONE: no loopback - * @LOOPBACK_GMAC: loopback within GMAC at unspecified level - * @LOOPBACK_XGMII: loopback within XMAC at XGMII level - * @LOOPBACK_XGXS: loopback within XMAC at XGXS level - * @LOOPBACK_XAUI: loopback within XMAC at XAUI level - * @LOOPBACK_GPHY: loopback within 1G PHY at unspecified level - * @LOOPBACK_PHYXS: loopback within 10G PHY at PHYXS level - * @LOOPBACK_PCS: loopback within 10G PHY at PCS level - * @LOOPBACK_PMAPMD: loopback within 10G PHY at PMAPMD level - * @LOOPBACK_NETWORK: reflecting loopback (even further than furthest!) - */ -/* Please keep in order and up-to-date w.r.t the following two #defines */ -enum efx_loopback_mode { - LOOPBACK_NONE = 0, - LOOPBACK_GMAC = 1, - LOOPBACK_XGMII = 2, - LOOPBACK_XGXS = 3, - LOOPBACK_XAUI = 4, - LOOPBACK_GPHY = 5, - LOOPBACK_PHYXS = 6, - LOOPBACK_PCS = 7, - LOOPBACK_PMAPMD = 8, - LOOPBACK_NETWORK = 9, - LOOPBACK_MAX -}; - -#define LOOPBACK_TEST_MAX LOOPBACK_PMAPMD - -extern const char *efx_loopback_mode_names[]; -#define LOOPBACK_MODE_NAME(mode) \ - STRING_TABLE_LOOKUP(mode, efx_loopback_mode) -#define LOOPBACK_MODE(efx) \ - LOOPBACK_MODE_NAME(efx->loopback_mode) - -/* These loopbacks occur within the controller */ -#define LOOPBACKS_INTERNAL ((1 << LOOPBACK_GMAC) | \ - (1 << LOOPBACK_XGMII)| \ - (1 << LOOPBACK_XGXS) | \ - (1 << LOOPBACK_XAUI)) - -#define LOOPBACK_MASK(_efx) \ - (1 << (_efx)->loopback_mode) - -#define LOOPBACK_INTERNAL(_efx) \ - (!!(LOOPBACKS_INTERNAL & LOOPBACK_MASK(_efx))) - -#define LOOPBACK_CHANGED(_from, _to, _mask) \ - (!!((LOOPBACK_MASK(_from) ^ LOOPBACK_MASK(_to)) & (_mask))) - -#define LOOPBACK_OUT_OF(_from, _to, _mask) \ - ((LOOPBACK_MASK(_from) & (_mask)) && !(LOOPBACK_MASK(_to) & (_mask))) - -/*****************************************************************************/ - -/** - * enum reset_type - reset types - * - * %RESET_TYPE_INVSIBLE, %RESET_TYPE_ALL, %RESET_TYPE_WORLD and - * %RESET_TYPE_DISABLE specify the method/scope of the reset. The - * other valuesspecify reasons, which efx_schedule_reset() will choose - * a method for. - * - * @RESET_TYPE_INVISIBLE: don't reset the PHYs or interrupts - * @RESET_TYPE_ALL: reset everything but PCI core blocks - * @RESET_TYPE_WORLD: reset everything, save & restore PCI config - * @RESET_TYPE_DISABLE: disable NIC - * @RESET_TYPE_TX_WATCHDOG: reset due to TX watchdog - * @RESET_TYPE_INT_ERROR: reset due to internal error - * @RESET_TYPE_RX_RECOVERY: reset to recover from RX datapath errors - * @RESET_TYPE_RX_DESC_FETCH: pcie error during rx descriptor fetch - * @RESET_TYPE_TX_DESC_FETCH: pcie error during tx descriptor fetch - * @RESET_TYPE_TX_SKIP: hardware completed empty tx descriptors - */ -enum reset_type { - RESET_TYPE_NONE = -1, - RESET_TYPE_INVISIBLE = 0, - RESET_TYPE_ALL = 1, - RESET_TYPE_WORLD = 2, - RESET_TYPE_DISABLE = 3, - RESET_TYPE_MAX_METHOD, - RESET_TYPE_TX_WATCHDOG, - RESET_TYPE_INT_ERROR, - RESET_TYPE_RX_RECOVERY, - RESET_TYPE_RX_DESC_FETCH, - RESET_TYPE_TX_DESC_FETCH, - RESET_TYPE_TX_SKIP, - RESET_TYPE_MAX, -}; - -#endif /* EFX_ENUM_H */ diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c deleted file mode 100644 index 7b5924c039b..00000000000 --- a/drivers/net/sfc/ethtool.c +++ /dev/null @@ -1,767 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2006-2008 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. - */ - -#include <linux/netdevice.h> -#include <linux/ethtool.h> -#include <linux/rtnetlink.h> -#include "net_driver.h" -#include "workarounds.h" -#include "selftest.h" -#include "efx.h" -#include "ethtool.h" -#include "falcon.h" -#include "spi.h" -#include "mdio_10g.h" - -const char *efx_loopback_mode_names[] = { - [LOOPBACK_NONE] = "NONE", - [LOOPBACK_GMAC] = "GMAC", - [LOOPBACK_XGMII] = "XGMII", - [LOOPBACK_XGXS] = "XGXS", - [LOOPBACK_XAUI] = "XAUI", - [LOOPBACK_GPHY] = "GPHY", - [LOOPBACK_PHYXS] = "PHYXS", - [LOOPBACK_PCS] = "PCS", - [LOOPBACK_PMAPMD] = "PMA/PMD", - [LOOPBACK_NETWORK] = "NETWORK", -}; - -struct ethtool_string { - char name[ETH_GSTRING_LEN]; -}; - -struct efx_ethtool_stat { - const char *name; - enum { - EFX_ETHTOOL_STAT_SOURCE_mac_stats, - EFX_ETHTOOL_STAT_SOURCE_nic, - EFX_ETHTOOL_STAT_SOURCE_channel - } source; - unsigned offset; - u64(*get_stat) (void *field); /* Reader function */ -}; - -/* Initialiser for a struct #efx_ethtool_stat with type-checking */ -#define EFX_ETHTOOL_STAT(stat_name, source_name, field, field_type, \ - get_stat_function) { \ - .name = #stat_name, \ - .source = EFX_ETHTOOL_STAT_SOURCE_##source_name, \ - .offset = ((((field_type *) 0) == \ - &((struct efx_##source_name *)0)->field) ? \ - offsetof(struct efx_##source_name, field) : \ - offsetof(struct efx_##source_name, field)), \ - .get_stat = get_stat_function, \ -} - -static u64 efx_get_uint_stat(void *field) -{ - return *(unsigned int *)field; -} - -static u64 efx_get_ulong_stat(void *field) -{ - return *(unsigned long *)field; -} - -static u64 efx_get_u64_stat(void *field) -{ - return *(u64 *) field; -} - -static u64 efx_get_atomic_stat(void *field) -{ - return atomic_read((atomic_t *) field); -} - -#define EFX_ETHTOOL_ULONG_MAC_STAT(field) \ - EFX_ETHTOOL_STAT(field, mac_stats, field, \ - unsigned long, efx_get_ulong_stat) - -#define EFX_ETHTOOL_U64_MAC_STAT(field) \ - EFX_ETHTOOL_STAT(field, mac_stats, field, \ - u64, efx_get_u64_stat) - -#define EFX_ETHTOOL_UINT_NIC_STAT(name) \ - EFX_ETHTOOL_STAT(name, nic, n_##name, \ - unsigned int, efx_get_uint_stat) - -#define EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(field) \ - EFX_ETHTOOL_STAT(field, nic, field, \ - atomic_t, efx_get_atomic_stat) - -#define EFX_ETHTOOL_UINT_CHANNEL_STAT(field) \ - EFX_ETHTOOL_STAT(field, channel, n_##field, \ - unsigned int, efx_get_uint_stat) - -static struct efx_ethtool_stat efx_ethtool_stats[] = { - EFX_ETHTOOL_U64_MAC_STAT(tx_bytes), - EFX_ETHTOOL_U64_MAC_STAT(tx_good_bytes), - EFX_ETHTOOL_U64_MAC_STAT(tx_bad_bytes), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_packets), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_bad), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_pause), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_control), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_unicast), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_multicast), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_broadcast), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_lt64), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_64), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_65_to_127), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_128_to_255), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_256_to_511), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_512_to_1023), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_1024_to_15xx), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_15xx_to_jumbo), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_gtjumbo), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_collision), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_single_collision), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_multiple_collision), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_excessive_collision), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_deferred), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_late_collision), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_excessive_deferred), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_non_tcpudp), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_mac_src_error), - EFX_ETHTOOL_ULONG_MAC_STAT(tx_ip_src_error), - EFX_ETHTOOL_U64_MAC_STAT(rx_bytes), - EFX_ETHTOOL_U64_MAC_STAT(rx_good_bytes), - EFX_ETHTOOL_U64_MAC_STAT(rx_bad_bytes), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_packets), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_good), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_pause), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_control), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_unicast), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_multicast), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_broadcast), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_lt64), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_64), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_65_to_127), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_128_to_255), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_256_to_511), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_512_to_1023), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_1024_to_15xx), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_15xx_to_jumbo), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_gtjumbo), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_lt64), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_64_to_15xx), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_15xx_to_jumbo), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_bad_gtjumbo), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_overflow), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_missed), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_false_carrier), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_symbol_error), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_align_error), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_length_error), - EFX_ETHTOOL_ULONG_MAC_STAT(rx_internal_error), - EFX_ETHTOOL_UINT_NIC_STAT(rx_nodesc_drop_cnt), - EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(rx_reset), - EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tobe_disc), - EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_ip_hdr_chksum_err), - EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tcp_udp_chksum_err), - EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_frm_trunc), -}; - -/* Number of ethtool statistics */ -#define EFX_ETHTOOL_NUM_STATS ARRAY_SIZE(efx_ethtool_stats) - -#define EFX_ETHTOOL_EEPROM_MAGIC 0xEFAB - -/************************************************************************** - * - * Ethtool operations - * - ************************************************************************** - */ - -/* Identify device by flashing LEDs */ -static int efx_ethtool_phys_id(struct net_device *net_dev, u32 count) -{ - struct efx_nic *efx = netdev_priv(net_dev); - - efx->board_info.blink(efx, 1); - set_current_state(TASK_INTERRUPTIBLE); - if (count) - schedule_timeout(count * HZ); - else - schedule(); - efx->board_info.blink(efx, 0); - return 0; -} - -/* This must be called with rtnl_lock held. */ -int efx_ethtool_get_settings(struct net_device *net_dev, - struct ethtool_cmd *ecmd) -{ - struct efx_nic *efx = netdev_priv(net_dev); - - mutex_lock(&efx->mac_lock); - efx->phy_op->get_settings(efx, ecmd); - mutex_unlock(&efx->mac_lock); - - /* Falcon GMAC does not support 1000Mbps HD */ - ecmd->supported &= ~SUPPORTED_1000baseT_Half; - - return 0; -} - -/* This must be called with rtnl_lock held. */ -int efx_ethtool_set_settings(struct net_device *net_dev, - struct ethtool_cmd *ecmd) -{ - struct efx_nic *efx = netdev_priv(net_dev); - int rc; - - /* Falcon GMAC does not support 1000Mbps HD */ - if (ecmd->speed == SPEED_1000 && ecmd->duplex != DUPLEX_FULL) { - EFX_LOG(efx, "rejecting unsupported 1000Mbps HD" - " setting\n"); - return -EINVAL; - } - - mutex_lock(&efx->mac_lock); - rc = efx->phy_op->set_settings(efx, ecmd); - mutex_unlock(&efx->mac_lock); - if (!rc) - efx_reconfigure_port(efx); - - return rc; -} - -static void efx_ethtool_get_drvinfo(struct net_device *net_dev, - struct ethtool_drvinfo *info) -{ - struct efx_nic *efx = netdev_priv(net_dev); - - strlcpy(info->driver, EFX_DRIVER_NAME, sizeof(info->driver)); - strlcpy(info->version, EFX_DRIVER_VERSION, sizeof(info->version)); - strlcpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info)); -} - -/** - * efx_fill_test - fill in an individual self-test entry - * @test_index: Index of the test - * @strings: Ethtool strings, or %NULL - * @data: Ethtool test results, or %NULL - * @test: Pointer to test result (used only if data != %NULL) - * @unit_format: Unit name format (e.g. "chan\%d") - * @unit_id: Unit id (e.g. 0 for "chan0") - * @test_format: Test name format (e.g. "loopback.\%s.tx.sent") - * @test_id: Test id (e.g. "PHYXS" for "loopback.PHYXS.tx_sent") - * - * Fill in an individual self-test entry. - */ -static void efx_fill_test(unsigned int test_index, - struct ethtool_string *strings, u64 *data, - int *test, const char *unit_format, int unit_id, - const char *test_format, const char *test_id) -{ - struct ethtool_string unit_str, test_str; - - /* Fill data value, if applicable */ - if (data) - data[test_index] = *test; - - /* Fill string, if applicable */ - if (strings) { - if (strchr(unit_format, '%')) - snprintf(unit_str.name, sizeof(unit_str.name), - unit_format, unit_id); - else - strcpy(unit_str.name, unit_format); - snprintf(test_str.name, sizeof(test_str.name), - test_format, test_id); - snprintf(strings[test_index].name, - sizeof(strings[test_index].name), - "%-6s %-24s", unit_str.name, test_str.name); - } -} - -#define EFX_CHANNEL_NAME(_channel) "chan%d", _channel->channel -#define EFX_TX_QUEUE_NAME(_tx_queue) "txq%d", _tx_queue->queue -#define EFX_RX_QUEUE_NAME(_rx_queue) "rxq%d", _rx_queue->queue -#define EFX_LOOPBACK_NAME(_mode, _counter) \ - "loopback.%s." _counter, LOOPBACK_MODE_NAME(mode) - -/** - * efx_fill_loopback_test - fill in a block of loopback self-test entries - * @efx: Efx NIC - * @lb_tests: Efx loopback self-test results structure - * @mode: Loopback test mode - * @test_index: Starting index of the test - * @strings: Ethtool strings, or %NULL - * @data: Ethtool test results, or %NULL - */ -static int efx_fill_loopback_test(struct efx_nic *efx, - struct efx_loopback_self_tests *lb_tests, - enum efx_loopback_mode mode, - unsigned int test_index, - struct ethtool_string *strings, u64 *data) -{ - struct efx_tx_queue *tx_queue; - - efx_for_each_tx_queue(tx_queue, efx) { - efx_fill_test(test_index++, strings, data, - &lb_tests->tx_sent[tx_queue->queue], - EFX_TX_QUEUE_NAME(tx_queue), - EFX_LOOPBACK_NAME(mode, "tx_sent")); - efx_fill_test(test_index++, strings, data, - &lb_tests->tx_done[tx_queue->queue], - EFX_TX_QUEUE_NAME(tx_queue), - EFX_LOOPBACK_NAME(mode, "tx_done")); - } - efx_fill_test(test_index++, strings, data, - &lb_tests->rx_good, - "rx", 0, - EFX_LOOPBACK_NAME(mode, "rx_good")); - efx_fill_test(test_index++, strings, data, - &lb_tests->rx_bad, - "rx", 0, - EFX_LOOPBACK_NAME(mode, "rx_bad")); - - return test_index; -} - -/** - * efx_ethtool_fill_self_tests - get self-test details - * @efx: Efx NIC - * @tests: Efx self-test results structure, or %NULL - * @strings: Ethtool strings, or %NULL - * @data: Ethtool test results, or %NULL - */ -static int efx_ethtool_fill_self_tests(struct efx_nic *efx, - struct efx_self_tests *tests, - struct ethtool_string *strings, - u64 *data) -{ - struct efx_channel *channel; - unsigned int n = 0, i; - enum efx_loopback_mode mode; - - efx_fill_test(n++, strings, data, &tests->mii, - "core", 0, "mii", NULL); - efx_fill_test(n++, strings, data, &tests->nvram, - "core", 0, "nvram", NULL); - efx_fill_test(n++, strings, data, &tests->interrupt, - "core", 0, "interrupt", NULL); - - /* Event queues */ - efx_for_each_channel(channel, efx) { - efx_fill_test(n++, strings, data, - &tests->eventq_dma[channel->channel], - EFX_CHANNEL_NAME(channel), - "eventq.dma", NULL); - efx_fill_test(n++, strings, data, - &tests->eventq_int[channel->channel], - EFX_CHANNEL_NAME(channel), - "eventq.int", NULL); - efx_fill_test(n++, strings, data, - &tests->eventq_poll[channel->channel], - EFX_CHANNEL_NAME(channel), - "eventq.poll", NULL); - } - - efx_fill_test(n++, strings, data, &tests->registers, - "core", 0, "registers", NULL); - - for (i = 0; i < efx->phy_op->num_tests; i++) - efx_fill_test(n++, strings, data, &tests->phy[i], - "phy", 0, efx->phy_op->test_names[i], NULL); - - /* Loopback tests */ - for (mode = LOOPBACK_NONE; mode <= LOOPBACK_TEST_MAX; mode++) { - if (!(efx->loopback_modes & (1 << mode))) - continue; - n = efx_fill_loopback_test(efx, - &tests->loopback[mode], mode, n, - strings, data); - } - - return n; -} - -static int efx_ethtool_get_sset_count(struct net_device *net_dev, - int string_set) -{ - switch (string_set) { - case ETH_SS_STATS: - return EFX_ETHTOOL_NUM_STATS; - case ETH_SS_TEST: - return efx_ethtool_fill_self_tests(netdev_priv(net_dev), - NULL, NULL, NULL); - default: - return -EINVAL; - } -} - -static void efx_ethtool_get_strings(struct net_device *net_dev, - u32 string_set, u8 *strings) -{ - struct efx_nic *efx = netdev_priv(net_dev); - struct ethtool_string *ethtool_strings = - (struct ethtool_string *)strings; - int i; - - switch (string_set) { - case ETH_SS_STATS: - for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++) - strncpy(ethtool_strings[i].name, - efx_ethtool_stats[i].name, - sizeof(ethtool_strings[i].name)); - break; - case ETH_SS_TEST: - efx_ethtool_fill_self_tests(efx, NULL, - ethtool_strings, NULL); - break; - default: - /* No other string sets */ - break; - } -} - -static void efx_ethtool_get_stats(struct net_device *net_dev, - struct ethtool_stats *stats, - u64 *data) -{ - struct efx_nic *efx = netdev_priv(net_dev); - struct efx_mac_stats *mac_stats = &efx->mac_stats; - struct efx_ethtool_stat *stat; - struct efx_channel *channel; - int i; - - EFX_BUG_ON_PARANOID(stats->n_stats != EFX_ETHTOOL_NUM_STATS); - - /* Update MAC and NIC statistics */ - dev_get_stats(net_dev); - - /* Fill detailed statistics buffer */ - for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++) { - stat = &efx_ethtool_stats[i]; - switch (stat->source) { - case EFX_ETHTOOL_STAT_SOURCE_mac_stats: - data[i] = stat->get_stat((void *)mac_stats + - stat->offset); - break; - case EFX_ETHTOOL_STAT_SOURCE_nic: - data[i] = stat->get_stat((void *)efx + stat->offset); - break; - case EFX_ETHTOOL_STAT_SOURCE_channel: - data[i] = 0; - efx_for_each_channel(channel, efx) - data[i] += stat->get_stat((void *)channel + - stat->offset); - break; - } - } -} - -static int efx_ethtool_set_rx_csum(struct net_device *net_dev, u32 enable) -{ - struct efx_nic *efx = netdev_priv(net_dev); - - /* No way to stop the hardware doing the checks; we just - * ignore the result. - */ - efx->rx_checksum_enabled = !!enable; - - return 0; -} - -static u32 efx_ethtool_get_rx_csum(struct net_device *net_dev) -{ - struct efx_nic *efx = netdev_priv(net_dev); - - return efx->rx_checksum_enabled; -} - -static void efx_ethtool_self_test(struct net_device *net_dev, - struct ethtool_test *test, u64 *data) -{ - struct efx_nic *efx = netdev_priv(net_dev); - struct efx_self_tests efx_tests; - int already_up; - int rc; - - ASSERT_RTNL(); - if (efx->state != STATE_RUNNING) { - rc = -EIO; - goto fail1; - } - - /* We need rx buffers and interrupts. */ - already_up = (efx->net_dev->flags & IFF_UP); - if (!already_up) { - rc = dev_open(efx->net_dev); - if (rc) { - EFX_ERR(efx, "failed opening device.\n"); - goto fail2; - } - } - - memset(&efx_tests, 0, sizeof(efx_tests)); - - rc = efx_selftest(efx, &efx_tests, test->flags); - - if (!already_up) - dev_close(efx->net_dev); - - EFX_LOG(efx, "%s %sline self-tests\n", - rc == 0 ? "passed" : "failed", - (test->flags & ETH_TEST_FL_OFFLINE) ? "off" : "on"); - - fail2: - fail1: - /* Fill ethtool results structures */ - efx_ethtool_fill_self_tests(efx, &efx_tests, NULL, data); - if (rc) - test->flags |= ETH_TEST_FL_FAILED; -} - -/* Restart autonegotiation */ -static int efx_ethtool_nway_reset(struct net_device *net_dev) -{ - struct efx_nic *efx = netdev_priv(net_dev); - - return mii_nway_restart(&efx->mii); -} - -static u32 efx_ethtool_get_link(struct net_device *net_dev) -{ - struct efx_nic *efx = netdev_priv(net_dev); - - return efx->link_up; -} - -static int efx_ethtool_get_eeprom_len(struct net_device *net_dev) -{ - struct efx_nic *efx = netdev_priv(net_dev); - struct efx_spi_device *spi = efx->spi_eeprom; - - if (!spi) - return 0; - return min(spi->size, EFX_EEPROM_BOOTCONFIG_END) - - min(spi->size, EFX_EEPROM_BOOTCONFIG_START); -} - -static int efx_ethtool_get_eeprom(struct net_device *net_dev, - struct ethtool_eeprom *eeprom, u8 *buf) -{ - struct efx_nic *efx = netdev_priv(net_dev); - struct efx_spi_device *spi = efx->spi_eeprom; - size_t len; - int rc; - - rc = mutex_lock_interruptible(&efx->spi_lock); - if (rc) - return rc; - rc = falcon_spi_read(spi, eeprom->offset + EFX_EEPROM_BOOTCONFIG_START, - eeprom->len, &len, buf); - mutex_unlock(&efx->spi_lock); - - eeprom->magic = EFX_ETHTOOL_EEPROM_MAGIC; - eeprom->len = len; - return rc; -} - -static int efx_ethtool_set_eeprom(struct net_device *net_dev, - struct ethtool_eeprom *eeprom, u8 *buf) -{ - struct efx_nic *efx = netdev_priv(net_dev); - struct efx_spi_device *spi = efx->spi_eeprom; - size_t len; - int rc; - - if (eeprom->magic != EFX_ETHTOOL_EEPROM_MAGIC) - return -EINVAL; - - rc = mutex_lock_interruptible(&efx->spi_lock); - if (rc) - return rc; - rc = falcon_spi_write(spi, eeprom->offset + EFX_EEPROM_BOOTCONFIG_START, - eeprom->len, &len, buf); - mutex_unlock(&efx->spi_lock); - - eeprom->len = len; - return rc; -} - -static int efx_ethtool_get_coalesce(struct net_device *net_dev, - struct ethtool_coalesce *coalesce) -{ - struct efx_nic *efx = netdev_priv(net_dev); - struct efx_tx_queue *tx_queue; - struct efx_rx_queue *rx_queue; - struct efx_channel *channel; - - memset(coalesce, 0, sizeof(*coalesce)); - - /* Find lowest IRQ moderation across all used TX queues */ - coalesce->tx_coalesce_usecs_irq = ~((u32) 0); - efx_for_each_tx_queue(tx_queue, efx) { - channel = tx_queue->channel; - if (channel->irq_moderation < coalesce->tx_coalesce_usecs_irq) { - if (channel->used_flags != EFX_USED_BY_RX_TX) - coalesce->tx_coalesce_usecs_irq = - channel->irq_moderation; - else - coalesce->tx_coalesce_usecs_irq = 0; - } - } - - /* Find lowest IRQ moderation across all used RX queues */ - coalesce->rx_coalesce_usecs_irq = ~((u32) 0); - efx_for_each_rx_queue(rx_queue, efx) { - channel = rx_queue->channel; - if (channel->irq_moderation < coalesce->rx_coalesce_usecs_irq) - coalesce->rx_coalesce_usecs_irq = - channel->irq_moderation; - } - - return 0; -} - -/* Set coalescing parameters - * The difficulties occur for shared channels - */ -static int efx_ethtool_set_coalesce(struct net_device *net_dev, - struct ethtool_coalesce *coalesce) -{ - struct efx_nic *efx = netdev_priv(net_dev); - struct efx_channel *channel; - struct efx_tx_queue *tx_queue; - unsigned tx_usecs, rx_usecs; - - if (coalesce->use_adaptive_rx_coalesce || - coalesce->use_adaptive_tx_coalesce) - return -EOPNOTSUPP; - - if (coalesce->rx_coalesce_usecs || coalesce->tx_coalesce_usecs) { - EFX_ERR(efx, "invalid coalescing setting. " - "Only rx/tx_coalesce_usecs_irq are supported\n"); - return -EOPNOTSUPP; - } - - rx_usecs = coalesce->rx_coalesce_usecs_irq; - tx_usecs = coalesce->tx_coalesce_usecs_irq; - - /* If the channel is shared only allow RX parameters to be set */ - efx_for_each_tx_queue(tx_queue, efx) { - if ((tx_queue->channel->used_flags == EFX_USED_BY_RX_TX) && - tx_usecs) { - EFX_ERR(efx, "Channel is shared. " - "Only RX coalescing may be set\n"); - return -EOPNOTSUPP; - } - } - - efx_init_irq_moderation(efx, tx_usecs, rx_usecs); - - /* Reset channel to pick up new moderation value. Note that - * this may change the value of the irq_moderation field - * (e.g. to allow for hardware timer granularity). - */ - efx_for_each_channel(channel, efx) - falcon_set_int_moderation(channel); - - return 0; -} - -static int efx_ethtool_set_pauseparam(struct net_device *net_dev, - struct ethtool_pauseparam *pause) -{ - struct efx_nic *efx = netdev_priv(net_dev); - enum efx_fc_type wanted_fc; - bool reset; - - wanted_fc = ((pause->rx_pause ? EFX_FC_RX : 0) | - (pause->tx_pause ? EFX_FC_TX : 0) | - (pause->autoneg ? EFX_FC_AUTO : 0)); - - if ((wanted_fc & EFX_FC_TX) && !(wanted_fc & EFX_FC_RX)) { - EFX_LOG(efx, "Flow control unsupported: tx ON rx OFF\n"); - return -EINVAL; - } - - if (!(efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) && - (wanted_fc & EFX_FC_AUTO)) { - EFX_LOG(efx, "PHY does not support flow control " - "autonegotiation\n"); - return -EINVAL; - } - - /* TX flow control may automatically turn itself off if the - * link partner (intermittently) stops responding to pause - * frames. There isn't any indication that this has happened, - * so the best we do is leave it up to the user to spot this - * and fix it be cycling transmit flow control on this end. */ - reset = (wanted_fc & EFX_FC_TX) && !(efx->wanted_fc & EFX_FC_TX); - if (EFX_WORKAROUND_11482(efx) && reset) { - if (falcon_rev(efx) >= FALCON_REV_B0) { - /* Recover by resetting the EM block */ - if (efx->link_up) - falcon_drain_tx_fifo(efx); - } else { - /* Schedule a reset to recover */ - efx_schedule_reset(efx, RESET_TYPE_INVISIBLE); - } - } - - /* Try to push the pause parameters */ - mutex_lock(&efx->mac_lock); - - efx->wanted_fc = wanted_fc; - mdio_clause45_set_pause(efx); - __efx_reconfigure_port(efx); - - mutex_unlock(&efx->mac_lock); - - return 0; -} - -static void efx_ethtool_get_pauseparam(struct net_device *net_dev, - struct ethtool_pauseparam *pause) -{ - struct efx_nic *efx = netdev_priv(net_dev); - - pause->rx_pause = !!(efx->wanted_fc & EFX_FC_RX); - pause->tx_pause = !!(efx->wanted_fc & EFX_FC_TX); - pause->autoneg = !!(efx->wanted_fc & EFX_FC_AUTO); -} - - -struct ethtool_ops efx_ethtool_ops = { - .get_settings = efx_ethtool_get_settings, - .set_settings = efx_ethtool_set_settings, - .get_drvinfo = efx_ethtool_get_drvinfo, - .nway_reset = efx_ethtool_nway_reset, - .get_link = efx_ethtool_get_link, - .get_eeprom_len = efx_ethtool_get_eeprom_len, - .get_eeprom = efx_ethtool_get_eeprom, - .set_eeprom = efx_ethtool_set_eeprom, - .get_coalesce = efx_ethtool_get_coalesce, - .set_coalesce = efx_ethtool_set_coalesce, - .get_pauseparam = efx_ethtool_get_pauseparam, - .set_pauseparam = efx_ethtool_set_pauseparam, - .get_rx_csum = efx_ethtool_get_rx_csum, - .set_rx_csum = efx_ethtool_set_rx_csum, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, - .get_tso = ethtool_op_get_tso, - .set_tso = ethtool_op_set_tso, - .get_flags = ethtool_op_get_flags, - .set_flags = ethtool_op_set_flags, - .get_sset_count = efx_ethtool_get_sset_count, - .self_test = efx_ethtool_self_test, - .get_strings = efx_ethtool_get_strings, - .phys_id = efx_ethtool_phys_id, - .get_ethtool_stats = efx_ethtool_get_stats, -}; diff --git a/drivers/net/sfc/ethtool.h b/drivers/net/sfc/ethtool.h deleted file mode 100644 index 3628e43df14..00000000000 --- a/drivers/net/sfc/ethtool.h +++ /dev/null @@ -1,27 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005 Fen Systems Ltd. - * Copyright 2006 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_ETHTOOL_H -#define EFX_ETHTOOL_H - -#include "net_driver.h" - -/* - * Ethtool support - */ - -extern int efx_ethtool_get_settings(struct net_device *net_dev, - struct ethtool_cmd *ecmd); -extern int efx_ethtool_set_settings(struct net_device *net_dev, - struct ethtool_cmd *ecmd); - -extern struct ethtool_ops efx_ethtool_ops; - -#endif /* EFX_ETHTOOL_H */ diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c deleted file mode 100644 index d5378e60fcd..00000000000 --- a/drivers/net/sfc/falcon.c +++ /dev/null @@ -1,3196 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2006-2008 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. - */ - -#include <linux/bitops.h> -#include <linux/delay.h> -#include <linux/pci.h> -#include <linux/module.h> -#include <linux/seq_file.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> -#include <linux/mii.h> -#include "net_driver.h" -#include "bitfield.h" -#include "efx.h" -#include "mac.h" -#include "spi.h" -#include "falcon.h" -#include "falcon_hwdefs.h" -#include "falcon_io.h" -#include "mdio_10g.h" -#include "phy.h" -#include "boards.h" -#include "workarounds.h" - -/* Falcon hardware control. - * Falcon is the internal codename for the SFC4000 controller that is - * present in SFE400X evaluation boards - */ - -/** - * struct falcon_nic_data - Falcon NIC state - * @next_buffer_table: First available buffer table id - * @pci_dev2: The secondary PCI device if present - * @i2c_data: Operations and state for I2C bit-bashing algorithm - */ -struct falcon_nic_data { - unsigned next_buffer_table; - struct pci_dev *pci_dev2; - struct i2c_algo_bit_data i2c_data; -}; - -/************************************************************************** - * - * Configurable values - * - ************************************************************************** - */ - -static int disable_dma_stats; - -/* This is set to 16 for a good reason. In summary, if larger than - * 16, the descriptor cache holds more than a default socket - * buffer's worth of packets (for UDP we can only have at most one - * socket buffer's worth outstanding). This combined with the fact - * that we only get 1 TX event per descriptor cache means the NIC - * goes idle. - */ -#define TX_DC_ENTRIES 16 -#define TX_DC_ENTRIES_ORDER 0 -#define TX_DC_BASE 0x130000 - -#define RX_DC_ENTRIES 64 -#define RX_DC_ENTRIES_ORDER 2 -#define RX_DC_BASE 0x100000 - -static const unsigned int -/* "Large" EEPROM device: Atmel AT25640 or similar - * 8 KB, 16-bit address, 32 B write block */ -large_eeprom_type = ((13 << SPI_DEV_TYPE_SIZE_LBN) - | (2 << SPI_DEV_TYPE_ADDR_LEN_LBN) - | (5 << SPI_DEV_TYPE_BLOCK_SIZE_LBN)), -/* Default flash device: Atmel AT25F1024 - * 128 KB, 24-bit address, 32 KB erase block, 256 B write block */ -default_flash_type = ((17 << SPI_DEV_TYPE_SIZE_LBN) - | (3 << SPI_DEV_TYPE_ADDR_LEN_LBN) - | (0x52 << SPI_DEV_TYPE_ERASE_CMD_LBN) - | (15 << SPI_DEV_TYPE_ERASE_SIZE_LBN) - | (8 << SPI_DEV_TYPE_BLOCK_SIZE_LBN)); - -/* RX FIFO XOFF watermark - * - * When the amount of the RX FIFO increases used increases past this - * watermark send XOFF. Only used if RX flow control is enabled (ethtool -A) - * This also has an effect on RX/TX arbitration - */ -static int rx_xoff_thresh_bytes = -1; -module_param(rx_xoff_thresh_bytes, int, 0644); -MODULE_PARM_DESC(rx_xoff_thresh_bytes, "RX fifo XOFF threshold"); - -/* RX FIFO XON watermark - * - * When the amount of the RX FIFO used decreases below this - * watermark send XON. Only used if TX flow control is enabled (ethtool -A) - * This also has an effect on RX/TX arbitration - */ -static int rx_xon_thresh_bytes = -1; -module_param(rx_xon_thresh_bytes, int, 0644); -MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold"); - -/* TX descriptor ring size - min 512 max 4k */ -#define FALCON_TXD_RING_ORDER TX_DESCQ_SIZE_1K -#define FALCON_TXD_RING_SIZE 1024 -#define FALCON_TXD_RING_MASK (FALCON_TXD_RING_SIZE - 1) - -/* RX descriptor ring size - min 512 max 4k */ -#define FALCON_RXD_RING_ORDER RX_DESCQ_SIZE_1K -#define FALCON_RXD_RING_SIZE 1024 -#define FALCON_RXD_RING_MASK (FALCON_RXD_RING_SIZE - 1) - -/* Event queue size - max 32k */ -#define FALCON_EVQ_ORDER EVQ_SIZE_4K -#define FALCON_EVQ_SIZE 4096 -#define FALCON_EVQ_MASK (FALCON_EVQ_SIZE - 1) - -/* Max number of internal errors. After this resets will not be performed */ -#define FALCON_MAX_INT_ERRORS 4 - -/* We poll for events every FLUSH_INTERVAL ms, and check FLUSH_POLL_COUNT times - */ -#define FALCON_FLUSH_INTERVAL 10 -#define FALCON_FLUSH_POLL_COUNT 100 - -/************************************************************************** - * - * Falcon constants - * - ************************************************************************** - */ - -/* DMA address mask */ -#define FALCON_DMA_MASK DMA_BIT_MASK(46) - -/* TX DMA length mask (13-bit) */ -#define FALCON_TX_DMA_MASK (4096 - 1) - -/* Size and alignment of special buffers (4KB) */ -#define FALCON_BUF_SIZE 4096 - -/* Dummy SRAM size code */ -#define SRM_NB_BSZ_ONCHIP_ONLY (-1) - -/* Be nice if these (or equiv.) were in linux/pci_regs.h, but they're not. */ -#define PCI_EXP_DEVCAP_PWR_VAL_LBN 18 -#define PCI_EXP_DEVCAP_PWR_SCL_LBN 26 -#define PCI_EXP_DEVCTL_PAYLOAD_LBN 5 -#define PCI_EXP_LNKSTA_LNK_WID 0x3f0 -#define PCI_EXP_LNKSTA_LNK_WID_LBN 4 - -#define FALCON_IS_DUAL_FUNC(efx) \ - (falcon_rev(efx) < FALCON_REV_B0) - -/************************************************************************** - * - * Falcon hardware access - * - **************************************************************************/ - -/* Read the current event from the event queue */ -static inline efx_qword_t *falcon_event(struct efx_channel *channel, - unsigned int index) -{ - return (((efx_qword_t *) (channel->eventq.addr)) + index); -} - -/* See if an event is present - * - * We check both the high and low dword of the event for all ones. We - * wrote all ones when we cleared the event, and no valid event can - * have all ones in either its high or low dwords. This approach is - * robust against reordering. - * - * Note that using a single 64-bit comparison is incorrect; even - * though the CPU read will be atomic, the DMA write may not be. - */ -static inline int falcon_event_present(efx_qword_t *event) -{ - return (!(EFX_DWORD_IS_ALL_ONES(event->dword[0]) | - EFX_DWORD_IS_ALL_ONES(event->dword[1]))); -} - -/************************************************************************** - * - * I2C bus - this is a bit-bashing interface using GPIO pins - * Note that it uses the output enables to tristate the outputs - * SDA is the data pin and SCL is the clock - * - ************************************************************************** - */ -static void falcon_setsda(void *data, int state) -{ - struct efx_nic *efx = (struct efx_nic *)data; - efx_oword_t reg; - - falcon_read(efx, ®, GPIO_CTL_REG_KER); - EFX_SET_OWORD_FIELD(reg, GPIO3_OEN, !state); - falcon_write(efx, ®, GPIO_CTL_REG_KER); -} - -static void falcon_setscl(void *data, int state) -{ - struct efx_nic *efx = (struct efx_nic *)data; - efx_oword_t reg; - - falcon_read(efx, ®, GPIO_CTL_REG_KER); - EFX_SET_OWORD_FIELD(reg, GPIO0_OEN, !state); - falcon_write(efx, ®, GPIO_CTL_REG_KER); -} - -static int falcon_getsda(void *data) -{ - struct efx_nic *efx = (struct efx_nic *)data; - efx_oword_t reg; - - falcon_read(efx, ®, GPIO_CTL_REG_KER); - return EFX_OWORD_FIELD(reg, GPIO3_IN); -} - -static int falcon_getscl(void *data) -{ - struct efx_nic *efx = (struct efx_nic *)data; - efx_oword_t reg; - - falcon_read(efx, ®, GPIO_CTL_REG_KER); - return EFX_OWORD_FIELD(reg, GPIO0_IN); -} - -static struct i2c_algo_bit_data falcon_i2c_bit_operations = { - .setsda = falcon_setsda, - .setscl = falcon_setscl, - .getsda = falcon_getsda, - .getscl = falcon_getscl, - .udelay = 5, - /* Wait up to 50 ms for slave to let us pull SCL high */ - .timeout = DIV_ROUND_UP(HZ, 20), -}; - -/************************************************************************** - * - * Falcon special buffer handling - * Special buffers are used for event queues and the TX and RX - * descriptor rings. - * - *************************************************************************/ - -/* - * Initialise a Falcon special buffer - * - * This will define a buffer (previously allocated via - * falcon_alloc_special_buffer()) in Falcon's buffer table, allowing - * it to be used for event queues, descriptor rings etc. - */ -static void -falcon_init_special_buffer(struct efx_nic *efx, - struct efx_special_buffer *buffer) -{ - efx_qword_t buf_desc; - int index; - dma_addr_t dma_addr; - int i; - - EFX_BUG_ON_PARANOID(!buffer->addr); - - /* Write buffer descriptors to NIC */ - for (i = 0; i < buffer->entries; i++) { - index = buffer->index + i; - dma_addr = buffer->dma_addr + (i * 4096); - EFX_LOG(efx, "mapping special buffer %d at %llx\n", - index, (unsigned long long)dma_addr); - EFX_POPULATE_QWORD_4(buf_desc, - IP_DAT_BUF_SIZE, IP_DAT_BUF_SIZE_4K, - BUF_ADR_REGION, 0, - BUF_ADR_FBUF, (dma_addr >> 12), - BUF_OWNER_ID_FBUF, 0); - falcon_write_sram(efx, &buf_desc, index); - } -} - -/* Unmaps a buffer from Falcon and clears the buffer table entries */ -static void -falcon_fini_special_buffer(struct efx_nic *efx, - struct efx_special_buffer *buffer) -{ - efx_oword_t buf_tbl_upd; - unsigned int start = buffer->index; - unsigned int end = (buffer->index + buffer->entries - 1); - - if (!buffer->entries) - return; - - EFX_LOG(efx, "unmapping special buffers %d-%d\n", - buffer->index, buffer->index + buffer->entries - 1); - - EFX_POPULATE_OWORD_4(buf_tbl_upd, - BUF_UPD_CMD, 0, - BUF_CLR_CMD, 1, - BUF_CLR_END_ID, end, - BUF_CLR_START_ID, start); - falcon_write(efx, &buf_tbl_upd, BUF_TBL_UPD_REG_KER); -} - -/* - * Allocate a new Falcon special buffer - * - * This allocates memory for a new buffer, clears it and allocates a - * new buffer ID range. It does not write into Falcon's buffer table. - * - * This call will allocate 4KB buffers, since Falcon can't use 8KB - * buffers for event queues and descriptor rings. - */ -static int falcon_alloc_special_buffer(struct efx_nic *efx, - struct efx_special_buffer *buffer, - unsigned int len) -{ - struct falcon_nic_data *nic_data = efx->nic_data; - - len = ALIGN(len, FALCON_BUF_SIZE); - - buffer->addr = pci_alloc_consistent(efx->pci_dev, len, - &buffer->dma_addr); - if (!buffer->addr) - return -ENOMEM; - buffer->len = len; - buffer->entries = len / FALCON_BUF_SIZE; - BUG_ON(buffer->dma_addr & (FALCON_BUF_SIZE - 1)); - - /* All zeros is a potentially valid event so memset to 0xff */ - memset(buffer->addr, 0xff, len); - - /* Select new buffer ID */ - buffer->index = nic_data->next_buffer_table; - nic_data->next_buffer_table += buffer->entries; - - EFX_LOG(efx, "allocating special buffers %d-%d at %llx+%x " - "(virt %p phys %lx)\n", buffer->index, - buffer->index + buffer->entries - 1, - (unsigned long long)buffer->dma_addr, len, - buffer->addr, virt_to_phys(buffer->addr)); - - return 0; -} - -static void falcon_free_special_buffer(struct efx_nic *efx, - struct efx_special_buffer *buffer) -{ - if (!buffer->addr) - return; - - EFX_LOG(efx, "deallocating special buffers %d-%d at %llx+%x " - "(virt %p phys %lx)\n", buffer->index, - buffer->index + buffer->entries - 1, - (unsigned long long)buffer->dma_addr, buffer->len, - buffer->addr, virt_to_phys(buffer->addr)); - - pci_free_consistent(efx->pci_dev, buffer->len, buffer->addr, - buffer->dma_addr); - buffer->addr = NULL; - buffer->entries = 0; -} - -/************************************************************************** - * - * Falcon generic buffer handling - * These buffers are used for interrupt status and MAC stats - * - **************************************************************************/ - -static int falcon_alloc_buffer(struct efx_nic *efx, - struct efx_buffer *buffer, unsigned int len) -{ - buffer->addr = pci_alloc_consistent(efx->pci_dev, len, - &buffer->dma_addr); - if (!buffer->addr) - return -ENOMEM; - buffer->len = len; - memset(buffer->addr, 0, len); - return 0; -} - -static void falcon_free_buffer(struct efx_nic *efx, struct efx_buffer *buffer) -{ - if (buffer->addr) { - pci_free_consistent(efx->pci_dev, buffer->len, - buffer->addr, buffer->dma_addr); - buffer->addr = NULL; - } -} - -/************************************************************************** - * - * Falcon TX path - * - **************************************************************************/ - -/* Returns a pointer to the specified transmit descriptor in the TX - * descriptor queue belonging to the specified channel. - */ -static inline efx_qword_t *falcon_tx_desc(struct efx_tx_queue *tx_queue, - unsigned int index) -{ - return (((efx_qword_t *) (tx_queue->txd.addr)) + index); -} - -/* This writes to the TX_DESC_WPTR; write pointer for TX descriptor ring */ -static inline void falcon_notify_tx_desc(struct efx_tx_queue *tx_queue) -{ - unsigned write_ptr; - efx_dword_t reg; - - write_ptr = tx_queue->write_count & FALCON_TXD_RING_MASK; - EFX_POPULATE_DWORD_1(reg, TX_DESC_WPTR_DWORD, write_ptr); - falcon_writel_page(tx_queue->efx, ®, - TX_DESC_UPD_REG_KER_DWORD, tx_queue->queue); -} - - -/* For each entry inserted into the software descriptor ring, create a - * descriptor in the hardware TX descriptor ring (in host memory), and - * write a doorbell. - */ -void falcon_push_buffers(struct efx_tx_queue *tx_queue) -{ - - struct efx_tx_buffer *buffer; - efx_qword_t *txd; - unsigned write_ptr; - - BUG_ON(tx_queue->write_count == tx_queue->insert_count); - - do { - write_ptr = tx_queue->write_count & FALCON_TXD_RING_MASK; - buffer = &tx_queue->buffer[write_ptr]; - txd = falcon_tx_desc(tx_queue, write_ptr); - ++tx_queue->write_count; - - /* Create TX descriptor ring entry */ - EFX_POPULATE_QWORD_5(*txd, - TX_KER_PORT, 0, - TX_KER_CONT, buffer->continuation, - TX_KER_BYTE_CNT, buffer->len, - TX_KER_BUF_REGION, 0, - TX_KER_BUF_ADR, buffer->dma_addr); - } while (tx_queue->write_count != tx_queue->insert_count); - - wmb(); /* Ensure descriptors are written before they are fetched */ - falcon_notify_tx_desc(tx_queue); -} - -/* Allocate hardware resources for a TX queue */ -int falcon_probe_tx(struct efx_tx_queue *tx_queue) -{ - struct efx_nic *efx = tx_queue->efx; - return falcon_alloc_special_buffer(efx, &tx_queue->txd, - FALCON_TXD_RING_SIZE * - sizeof(efx_qword_t)); -} - -void falcon_init_tx(struct efx_tx_queue *tx_queue) -{ - efx_oword_t tx_desc_ptr; - struct efx_nic *efx = tx_queue->efx; - - tx_queue->flushed = false; - - /* Pin TX descriptor ring */ - falcon_init_special_buffer(efx, &tx_queue->txd); - - /* Push TX descriptor ring to card */ - EFX_POPULATE_OWORD_10(tx_desc_ptr, - TX_DESCQ_EN, 1, - TX_ISCSI_DDIG_EN, 0, - TX_ISCSI_HDIG_EN, 0, - TX_DESCQ_BUF_BASE_ID, tx_queue->txd.index, - TX_DESCQ_EVQ_ID, tx_queue->channel->channel, - TX_DESCQ_OWNER_ID, 0, - TX_DESCQ_LABEL, tx_queue->queue, - TX_DESCQ_SIZE, FALCON_TXD_RING_ORDER, - TX_DESCQ_TYPE, 0, - TX_NON_IP_DROP_DIS_B0, 1); - - if (falcon_rev(efx) >= FALCON_REV_B0) { - int csum = tx_queue->queue == EFX_TX_QUEUE_OFFLOAD_CSUM; - EFX_SET_OWORD_FIELD(tx_desc_ptr, TX_IP_CHKSM_DIS_B0, !csum); - EFX_SET_OWORD_FIELD(tx_desc_ptr, TX_TCP_CHKSM_DIS_B0, !csum); - } - - falcon_write_table(efx, &tx_desc_ptr, efx->type->txd_ptr_tbl_base, - tx_queue->queue); - - if (falcon_rev(efx) < FALCON_REV_B0) { - efx_oword_t reg; - - /* Only 128 bits in this register */ - BUILD_BUG_ON(EFX_TX_QUEUE_COUNT >= 128); - - falcon_read(efx, ®, TX_CHKSM_CFG_REG_KER_A1); - if (tx_queue->queue == EFX_TX_QUEUE_OFFLOAD_CSUM) - clear_bit_le(tx_queue->queue, (void *)®); - else - set_bit_le(tx_queue->queue, (void *)®); - falcon_write(efx, ®, TX_CHKSM_CFG_REG_KER_A1); - } -} - -static void falcon_flush_tx_queue(struct efx_tx_queue *tx_queue) -{ - struct efx_nic *efx = tx_queue->efx; - efx_oword_t tx_flush_descq; - - /* Post a flush command */ - EFX_POPULATE_OWORD_2(tx_flush_descq, - TX_FLUSH_DESCQ_CMD, 1, - TX_FLUSH_DESCQ, tx_queue->queue); - falcon_write(efx, &tx_flush_descq, TX_FLUSH_DESCQ_REG_KER); -} - -void falcon_fini_tx(struct efx_tx_queue *tx_queue) -{ - struct efx_nic *efx = tx_queue->efx; - efx_oword_t tx_desc_ptr; - - /* The queue should have been flushed */ - WARN_ON(!tx_queue->flushed); - - /* Remove TX descriptor ring from card */ - EFX_ZERO_OWORD(tx_desc_ptr); - falcon_write_table(efx, &tx_desc_ptr, efx->type->txd_ptr_tbl_base, - tx_queue->queue); - - /* Unpin TX descriptor ring */ - falcon_fini_special_buffer(efx, &tx_queue->txd); -} - -/* Free buffers backing TX queue */ -void falcon_remove_tx(struct efx_tx_queue *tx_queue) -{ - falcon_free_special_buffer(tx_queue->efx, &tx_queue->txd); -} - -/************************************************************************** - * - * Falcon RX path - * - **************************************************************************/ - -/* Returns a pointer to the specified descriptor in the RX descriptor queue */ -static inline efx_qword_t *falcon_rx_desc(struct efx_rx_queue *rx_queue, - unsigned int index) -{ - return (((efx_qword_t *) (rx_queue->rxd.addr)) + index); -} - -/* This creates an entry in the RX descriptor queue */ -static inline void falcon_build_rx_desc(struct efx_rx_queue *rx_queue, - unsigned index) -{ - struct efx_rx_buffer *rx_buf; - efx_qword_t *rxd; - - rxd = falcon_rx_desc(rx_queue, index); - rx_buf = efx_rx_buffer(rx_queue, index); - EFX_POPULATE_QWORD_3(*rxd, - RX_KER_BUF_SIZE, - rx_buf->len - - rx_queue->efx->type->rx_buffer_padding, - RX_KER_BUF_REGION, 0, - RX_KER_BUF_ADR, rx_buf->dma_addr); -} - -/* This writes to the RX_DESC_WPTR register for the specified receive - * descriptor ring. - */ -void falcon_notify_rx_desc(struct efx_rx_queue *rx_queue) -{ - efx_dword_t reg; - unsigned write_ptr; - - while (rx_queue->notified_count != rx_queue->added_count) { - falcon_build_rx_desc(rx_queue, - rx_queue->notified_count & - FALCON_RXD_RING_MASK); - ++rx_queue->notified_count; - } - - wmb(); - write_ptr = rx_queue->added_count & FALCON_RXD_RING_MASK; - EFX_POPULATE_DWORD_1(reg, RX_DESC_WPTR_DWORD, write_ptr); - falcon_writel_page(rx_queue->efx, ®, - RX_DESC_UPD_REG_KER_DWORD, rx_queue->queue); -} - -int falcon_probe_rx(struct efx_rx_queue *rx_queue) -{ - struct efx_nic *efx = rx_queue->efx; - return falcon_alloc_special_buffer(efx, &rx_queue->rxd, - FALCON_RXD_RING_SIZE * - sizeof(efx_qword_t)); -} - -void falcon_init_rx(struct efx_rx_queue *rx_queue) -{ - efx_oword_t rx_desc_ptr; - struct efx_nic *efx = rx_queue->efx; - bool is_b0 = falcon_rev(efx) >= FALCON_REV_B0; - bool iscsi_digest_en = is_b0; - - EFX_LOG(efx, "RX queue %d ring in special buffers %d-%d\n", - rx_queue->queue, rx_queue->rxd.index, - rx_queue->rxd.index + rx_queue->rxd.entries - 1); - - rx_queue->flushed = false; - - /* Pin RX descriptor ring */ - falcon_init_special_buffer(efx, &rx_queue->rxd); - - /* Push RX descriptor ring to card */ - EFX_POPULATE_OWORD_10(rx_desc_ptr, - RX_ISCSI_DDIG_EN, iscsi_digest_en, - RX_ISCSI_HDIG_EN, iscsi_digest_en, - RX_DESCQ_BUF_BASE_ID, rx_queue->rxd.index, - RX_DESCQ_EVQ_ID, rx_queue->channel->channel, - RX_DESCQ_OWNER_ID, 0, - RX_DESCQ_LABEL, rx_queue->queue, - RX_DESCQ_SIZE, FALCON_RXD_RING_ORDER, - RX_DESCQ_TYPE, 0 /* kernel queue */ , - /* For >=B0 this is scatter so disable */ - RX_DESCQ_JUMBO, !is_b0, - RX_DESCQ_EN, 1); - falcon_write_table(efx, &rx_desc_ptr, efx->type->rxd_ptr_tbl_base, - rx_queue->queue); -} - -static void falcon_flush_rx_queue(struct efx_rx_queue *rx_queue) -{ - struct efx_nic *efx = rx_queue->efx; - efx_oword_t rx_flush_descq; - - /* Post a flush command */ - EFX_POPULATE_OWORD_2(rx_flush_descq, - RX_FLUSH_DESCQ_CMD, 1, - RX_FLUSH_DESCQ, rx_queue->queue); - falcon_write(efx, &rx_flush_descq, RX_FLUSH_DESCQ_REG_KER); -} - -void falcon_fini_rx(struct efx_rx_queue *rx_queue) -{ - efx_oword_t rx_desc_ptr; - struct efx_nic *efx = rx_queue->efx; - - /* The queue should already have been flushed */ - WARN_ON(!rx_queue->flushed); - - /* Remove RX descriptor ring from card */ - EFX_ZERO_OWORD(rx_desc_ptr); - falcon_write_table(efx, &rx_desc_ptr, efx->type->rxd_ptr_tbl_base, - rx_queue->queue); - - /* Unpin RX descriptor ring */ - falcon_fini_special_buffer(efx, &rx_queue->rxd); -} - -/* Free buffers backing RX queue */ -void falcon_remove_rx(struct efx_rx_queue *rx_queue) -{ - falcon_free_special_buffer(rx_queue->efx, &rx_queue->rxd); -} - -/************************************************************************** - * - * Falcon event queue processing - * Event queues are processed by per-channel tasklets. - * - **************************************************************************/ - -/* Update a channel's event queue's read pointer (RPTR) register - * - * This writes the EVQ_RPTR_REG register for the specified channel's - * event queue. - * - * Note that EVQ_RPTR_REG contains the index of the "last read" event, - * whereas channel->eventq_read_ptr contains the index of the "next to - * read" event. - */ -void falcon_eventq_read_ack(struct efx_channel *channel) -{ - efx_dword_t reg; - struct efx_nic *efx = channel->efx; - - EFX_POPULATE_DWORD_1(reg, EVQ_RPTR_DWORD, channel->eventq_read_ptr); - falcon_writel_table(efx, ®, efx->type->evq_rptr_tbl_base, - channel->channel); -} - -/* Use HW to insert a SW defined event */ -void falcon_generate_event(struct efx_channel *channel, efx_qword_t *event) -{ - efx_oword_t drv_ev_reg; - - EFX_POPULATE_OWORD_2(drv_ev_reg, - DRV_EV_QID, channel->channel, - DRV_EV_DATA, - EFX_QWORD_FIELD64(*event, WHOLE_EVENT)); - falcon_write(channel->efx, &drv_ev_reg, DRV_EV_REG_KER); -} - -/* Handle a transmit completion event - * - * Falcon batches TX completion events; the message we receive is of - * the form "complete all TX events up to this index". - */ -static void falcon_handle_tx_event(struct efx_channel *channel, - efx_qword_t *event) -{ - unsigned int tx_ev_desc_ptr; - unsigned int tx_ev_q_label; - struct efx_tx_queue *tx_queue; - struct efx_nic *efx = channel->efx; - - if (likely(EFX_QWORD_FIELD(*event, TX_EV_COMP))) { - /* Transmit completion */ - tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, TX_EV_DESC_PTR); - tx_ev_q_label = EFX_QWORD_FIELD(*event, TX_EV_Q_LABEL); - tx_queue = &efx->tx_queue[tx_ev_q_label]; - efx_xmit_done(tx_queue, tx_ev_desc_ptr); - } else if (EFX_QWORD_FIELD(*event, TX_EV_WQ_FF_FULL)) { - /* Rewrite the FIFO write pointer */ - tx_ev_q_label = EFX_QWORD_FIELD(*event, TX_EV_Q_LABEL); - tx_queue = &efx->tx_queue[tx_ev_q_label]; - - if (efx_dev_registered(efx)) - netif_tx_lock(efx->net_dev); - falcon_notify_tx_desc(tx_queue); - if (efx_dev_registered(efx)) - netif_tx_unlock(efx->net_dev); - } else if (EFX_QWORD_FIELD(*event, TX_EV_PKT_ERR) && - EFX_WORKAROUND_10727(efx)) { - efx_schedule_reset(efx, RESET_TYPE_TX_DESC_FETCH); - } else { - EFX_ERR(efx, "channel %d unexpected TX event " - EFX_QWORD_FMT"\n", channel->channel, - EFX_QWORD_VAL(*event)); - } -} - -/* Detect errors included in the rx_evt_pkt_ok bit. */ -static void falcon_handle_rx_not_ok(struct efx_rx_queue *rx_queue, - const efx_qword_t *event, - bool *rx_ev_pkt_ok, - bool *discard) -{ - struct efx_nic *efx = rx_queue->efx; - bool rx_ev_buf_owner_id_err, rx_ev_ip_hdr_chksum_err; - bool rx_ev_tcp_udp_chksum_err, rx_ev_eth_crc_err; - bool rx_ev_frm_trunc, rx_ev_drib_nib, rx_ev_tobe_disc; - bool rx_ev_other_err, rx_ev_pause_frm; - bool rx_ev_ip_frag_err, rx_ev_hdr_type, rx_ev_mcast_pkt; - unsigned rx_ev_pkt_type; - - rx_ev_hdr_type = EFX_QWORD_FIELD(*event, RX_EV_HDR_TYPE); - rx_ev_mcast_pkt = EFX_QWORD_FIELD(*event, RX_EV_MCAST_PKT); - rx_ev_tobe_disc = EFX_QWORD_FIELD(*event, RX_EV_TOBE_DISC); - rx_ev_pkt_type = EFX_QWORD_FIELD(*event, RX_EV_PKT_TYPE); - rx_ev_buf_owner_id_err = EFX_QWORD_FIELD(*event, - RX_EV_BUF_OWNER_ID_ERR); - rx_ev_ip_frag_err = EFX_QWORD_FIELD(*event, RX_EV_IF_FRAG_ERR); - rx_ev_ip_hdr_chksum_err = EFX_QWORD_FIELD(*event, - RX_EV_IP_HDR_CHKSUM_ERR); - rx_ev_tcp_udp_chksum_err = EFX_QWORD_FIELD(*event, - RX_EV_TCP_UDP_CHKSUM_ERR); - rx_ev_eth_crc_err = EFX_QWORD_FIELD(*event, RX_EV_ETH_CRC_ERR); - rx_ev_frm_trunc = EFX_QWORD_FIELD(*event, RX_EV_FRM_TRUNC); - rx_ev_drib_nib = ((falcon_rev(efx) >= FALCON_REV_B0) ? - 0 : EFX_QWORD_FIELD(*event, RX_EV_DRIB_NIB)); - rx_ev_pause_frm = EFX_QWORD_FIELD(*event, RX_EV_PAUSE_FRM_ERR); - - /* Every error apart from tobe_disc and pause_frm */ - rx_ev_other_err = (rx_ev_drib_nib | rx_ev_tcp_udp_chksum_err | - rx_ev_buf_owner_id_err | rx_ev_eth_crc_err | - rx_ev_frm_trunc | rx_ev_ip_hdr_chksum_err); - - /* Count errors that are not in MAC stats. Ignore expected - * checksum errors during self-test. */ - if (rx_ev_frm_trunc) - ++rx_queue->channel->n_rx_frm_trunc; - else if (rx_ev_tobe_disc) - ++rx_queue->channel->n_rx_tobe_disc; - else if (!efx->loopback_selftest) { - if (rx_ev_ip_hdr_chksum_err) - ++rx_queue->channel->n_rx_ip_hdr_chksum_err; - else if (rx_ev_tcp_udp_chksum_err) - ++rx_queue->channel->n_rx_tcp_udp_chksum_err; - } - if (rx_ev_ip_frag_err) - ++rx_queue->channel->n_rx_ip_frag_err; - - /* The frame must be discarded if any of these are true. */ - *discard = (rx_ev_eth_crc_err | rx_ev_frm_trunc | rx_ev_drib_nib | - rx_ev_tobe_disc | rx_ev_pause_frm); - - /* TOBE_DISC is expected on unicast mismatches; don't print out an - * error message. FRM_TRUNC indicates RXDP dropped the packet due - * to a FIFO overflow. - */ -#ifdef EFX_ENABLE_DEBUG - if (rx_ev_other_err) { - EFX_INFO_RL(efx, " RX queue %d unexpected RX event " - EFX_QWORD_FMT "%s%s%s%s%s%s%s%s\n", - rx_queue->queue, EFX_QWORD_VAL(*event), - rx_ev_buf_owner_id_err ? " [OWNER_ID_ERR]" : "", - rx_ev_ip_hdr_chksum_err ? - " [IP_HDR_CHKSUM_ERR]" : "", - rx_ev_tcp_udp_chksum_err ? - " [TCP_UDP_CHKSUM_ERR]" : "", - rx_ev_eth_crc_err ? " [ETH_CRC_ERR]" : "", - rx_ev_frm_trunc ? " [FRM_TRUNC]" : "", - rx_ev_drib_nib ? " [DRIB_NIB]" : "", - rx_ev_tobe_disc ? " [TOBE_DISC]" : "", - rx_ev_pause_frm ? " [PAUSE]" : ""); - } -#endif -} - -/* Handle receive events that are not in-order. */ -static void falcon_handle_rx_bad_index(struct efx_rx_queue *rx_queue, - unsigned index) -{ - struct efx_nic *efx = rx_queue->efx; - unsigned expected, dropped; - - expected = rx_queue->removed_count & FALCON_RXD_RING_MASK; - dropped = ((index + FALCON_RXD_RING_SIZE - expected) & - FALCON_RXD_RING_MASK); - EFX_INFO(efx, "dropped %d events (index=%d expected=%d)\n", - dropped, index, expected); - - efx_schedule_reset(efx, EFX_WORKAROUND_5676(efx) ? - RESET_TYPE_RX_RECOVERY : RESET_TYPE_DISABLE); -} - -/* Handle a packet received event - * - * Falcon silicon gives a "discard" flag if it's a unicast packet with the - * wrong destination address - * Also "is multicast" and "matches multicast filter" flags can be used to - * discard non-matching multicast packets. - */ -static void falcon_handle_rx_event(struct efx_channel *channel, - const efx_qword_t *event) -{ - unsigned int rx_ev_desc_ptr, rx_ev_byte_cnt; - unsigned int rx_ev_hdr_type, rx_ev_mcast_pkt; - unsigned expected_ptr; - bool rx_ev_pkt_ok, discard = false, checksummed; - struct efx_rx_queue *rx_queue; - struct efx_nic *efx = channel->efx; - - /* Basic packet information */ - rx_ev_byte_cnt = EFX_QWORD_FIELD(*event, RX_EV_BYTE_CNT); - rx_ev_pkt_ok = EFX_QWORD_FIELD(*event, RX_EV_PKT_OK); - rx_ev_hdr_type = EFX_QWORD_FIELD(*event, RX_EV_HDR_TYPE); - WARN_ON(EFX_QWORD_FIELD(*event, RX_EV_JUMBO_CONT)); - WARN_ON(EFX_QWORD_FIELD(*event, RX_EV_SOP) != 1); - WARN_ON(EFX_QWORD_FIELD(*event, RX_EV_Q_LABEL) != channel->channel); - - rx_queue = &efx->rx_queue[channel->channel]; - - rx_ev_desc_ptr = EFX_QWORD_FIELD(*event, RX_EV_DESC_PTR); - expected_ptr = rx_queue->removed_count & FALCON_RXD_RING_MASK; - if (unlikely(rx_ev_desc_ptr != expected_ptr)) - falcon_handle_rx_bad_index(rx_queue, rx_ev_desc_ptr); - - if (likely(rx_ev_pkt_ok)) { - /* If packet is marked as OK and packet type is TCP/IPv4 or - * UDP/IPv4, then we can rely on the hardware checksum. - */ - checksummed = RX_EV_HDR_TYPE_HAS_CHECKSUMS(rx_ev_hdr_type); - } else { - falcon_handle_rx_not_ok(rx_queue, event, &rx_ev_pkt_ok, - &discard); - checksummed = false; - } - - /* Detect multicast packets that didn't match the filter */ - rx_ev_mcast_pkt = EFX_QWORD_FIELD(*event, RX_EV_MCAST_PKT); - if (rx_ev_mcast_pkt) { - unsigned int rx_ev_mcast_hash_match = - EFX_QWORD_FIELD(*event, RX_EV_MCAST_HASH_MATCH); - - if (unlikely(!rx_ev_mcast_hash_match)) - discard = true; - } - - /* Handle received packet */ - efx_rx_packet(rx_queue, rx_ev_desc_ptr, rx_ev_byte_cnt, - checksummed, discard); -} - -/* Global events are basically PHY events */ -static void falcon_handle_global_event(struct efx_channel *channel, - efx_qword_t *event) -{ - struct efx_nic *efx = channel->efx; - bool handled = false; - - if (EFX_QWORD_FIELD(*event, G_PHY0_INTR) || - EFX_QWORD_FIELD(*event, G_PHY1_INTR) || - EFX_QWORD_FIELD(*event, XG_PHY_INTR) || - EFX_QWORD_FIELD(*event, XFP_PHY_INTR)) { - efx->phy_op->clear_interrupt(efx); - queue_work(efx->workqueue, &efx->phy_work); - handled = true; - } - - if ((falcon_rev(efx) >= FALCON_REV_B0) && - EFX_QWORD_FIELD(*event, XG_MNT_INTR_B0)) { - queue_work(efx->workqueue, &efx->mac_work); - handled = true; - } - - if (EFX_QWORD_FIELD_VER(efx, *event, RX_RECOVERY)) { - EFX_ERR(efx, "channel %d seen global RX_RESET " - "event. Resetting.\n", channel->channel); - - atomic_inc(&efx->rx_reset); - efx_schedule_reset(efx, EFX_WORKAROUND_6555(efx) ? - RESET_TYPE_RX_RECOVERY : RESET_TYPE_DISABLE); - handled = true; - } - - if (!handled) - EFX_ERR(efx, "channel %d unknown global event " - EFX_QWORD_FMT "\n", channel->channel, - EFX_QWORD_VAL(*event)); -} - -static void falcon_handle_driver_event(struct efx_channel *channel, - efx_qword_t *event) -{ - struct efx_nic *efx = channel->efx; - unsigned int ev_sub_code; - unsigned int ev_sub_data; - - ev_sub_code = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_CODE); - ev_sub_data = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_DATA); - - switch (ev_sub_code) { - case TX_DESCQ_FLS_DONE_EV_DECODE: - EFX_TRACE(efx, "channel %d TXQ %d flushed\n", - channel->channel, ev_sub_data); - break; - case RX_DESCQ_FLS_DONE_EV_DECODE: - EFX_TRACE(efx, "channel %d RXQ %d flushed\n", - channel->channel, ev_sub_data); - break; - case EVQ_INIT_DONE_EV_DECODE: - EFX_LOG(efx, "channel %d EVQ %d initialised\n", - channel->channel, ev_sub_data); - break; - case SRM_UPD_DONE_EV_DECODE: - EFX_TRACE(efx, "channel %d SRAM update done\n", - channel->channel); - break; - case WAKE_UP_EV_DECODE: - EFX_TRACE(efx, "channel %d RXQ %d wakeup event\n", - channel->channel, ev_sub_data); - break; - case TIMER_EV_DECODE: - EFX_TRACE(efx, "channel %d RX queue %d timer expired\n", - channel->channel, ev_sub_data); - break; - case RX_RECOVERY_EV_DECODE: - EFX_ERR(efx, "channel %d seen DRIVER RX_RESET event. " - "Resetting.\n", channel->channel); - atomic_inc(&efx->rx_reset); - efx_schedule_reset(efx, - EFX_WORKAROUND_6555(efx) ? - RESET_TYPE_RX_RECOVERY : - RESET_TYPE_DISABLE); - break; - case RX_DSC_ERROR_EV_DECODE: - EFX_ERR(efx, "RX DMA Q %d reports descriptor fetch error." - " RX Q %d is disabled.\n", ev_sub_data, ev_sub_data); - efx_schedule_reset(efx, RESET_TYPE_RX_DESC_FETCH); - break; - case TX_DSC_ERROR_EV_DECODE: - EFX_ERR(efx, "TX DMA Q %d reports descriptor fetch error." - " TX Q %d is disabled.\n", ev_sub_data, ev_sub_data); - efx_schedule_reset(efx, RESET_TYPE_TX_DESC_FETCH); - break; - default: - EFX_TRACE(efx, "channel %d unknown driver event code %d " - "data %04x\n", channel->channel, ev_sub_code, - ev_sub_data); - break; - } -} - -int falcon_process_eventq(struct efx_channel *channel, int rx_quota) -{ - unsigned int read_ptr; - efx_qword_t event, *p_event; - int ev_code; - int rx_packets = 0; - - read_ptr = channel->eventq_read_ptr; - - do { - p_event = falcon_event(channel, read_ptr); - event = *p_event; - - if (!falcon_event_present(&event)) - /* End of events */ - break; - - EFX_TRACE(channel->efx, "channel %d event is "EFX_QWORD_FMT"\n", - channel->channel, EFX_QWORD_VAL(event)); - - /* Clear this event by marking it all ones */ - EFX_SET_QWORD(*p_event); - - ev_code = EFX_QWORD_FIELD(event, EV_CODE); - - switch (ev_code) { - case RX_IP_EV_DECODE: - falcon_handle_rx_event(channel, &event); - ++rx_packets; - break; - case TX_IP_EV_DECODE: - falcon_handle_tx_event(channel, &event); - break; - case DRV_GEN_EV_DECODE: - channel->eventq_magic - = EFX_QWORD_FIELD(event, EVQ_MAGIC); - EFX_LOG(channel->efx, "channel %d received generated " - "event "EFX_QWORD_FMT"\n", channel->channel, - EFX_QWORD_VAL(event)); - break; - case GLOBAL_EV_DECODE: - falcon_handle_global_event(channel, &event); - break; - case DRIVER_EV_DECODE: - falcon_handle_driver_event(channel, &event); - break; - default: - EFX_ERR(channel->efx, "channel %d unknown event type %d" - " (data " EFX_QWORD_FMT ")\n", channel->channel, - ev_code, EFX_QWORD_VAL(event)); - } - - /* Increment read pointer */ - read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK; - - } while (rx_packets < rx_quota); - - channel->eventq_read_ptr = read_ptr; - return rx_packets; -} - -void falcon_set_int_moderation(struct efx_channel *channel) -{ - efx_dword_t timer_cmd; - struct efx_nic *efx = channel->efx; - - /* Set timer register */ - if (channel->irq_moderation) { - /* Round to resolution supported by hardware. The value we - * program is based at 0. So actual interrupt moderation - * achieved is ((x + 1) * res). - */ - unsigned int res = 5; - channel->irq_moderation -= (channel->irq_moderation % res); - if (channel->irq_moderation < res) - channel->irq_moderation = res; - EFX_POPULATE_DWORD_2(timer_cmd, - TIMER_MODE, TIMER_MODE_INT_HLDOFF, - TIMER_VAL, - (channel->irq_moderation / res) - 1); - } else { - EFX_POPULATE_DWORD_2(timer_cmd, - TIMER_MODE, TIMER_MODE_DIS, - TIMER_VAL, 0); - } - falcon_writel_page_locked(efx, &timer_cmd, TIMER_CMD_REG_KER, - channel->channel); - -} - -/* Allocate buffer table entries for event queue */ -int falcon_probe_eventq(struct efx_channel *channel) -{ - struct efx_nic *efx = channel->efx; - unsigned int evq_size; - - evq_size = FALCON_EVQ_SIZE * sizeof(efx_qword_t); - return falcon_alloc_special_buffer(efx, &channel->eventq, evq_size); -} - -void falcon_init_eventq(struct efx_channel *channel) -{ - efx_oword_t evq_ptr; - struct efx_nic *efx = channel->efx; - - EFX_LOG(efx, "channel %d event queue in special buffers %d-%d\n", - channel->channel, channel->eventq.index, - channel->eventq.index + channel->eventq.entries - 1); - - /* Pin event queue buffer */ - falcon_init_special_buffer(efx, &channel->eventq); - - /* Fill event queue with all ones (i.e. empty events) */ - memset(channel->eventq.addr, 0xff, channel->eventq.len); - - /* Push event queue to card */ - EFX_POPULATE_OWORD_3(evq_ptr, - EVQ_EN, 1, - EVQ_SIZE, FALCON_EVQ_ORDER, - EVQ_BUF_BASE_ID, channel->eventq.index); - falcon_write_table(efx, &evq_ptr, efx->type->evq_ptr_tbl_base, - channel->channel); - - falcon_set_int_moderation(channel); -} - -void falcon_fini_eventq(struct efx_channel *channel) -{ - efx_oword_t eventq_ptr; - struct efx_nic *efx = channel->efx; - - /* Remove event queue from card */ - EFX_ZERO_OWORD(eventq_ptr); - falcon_write_table(efx, &eventq_ptr, efx->type->evq_ptr_tbl_base, - channel->channel); - - /* Unpin event queue */ - falcon_fini_special_buffer(efx, &channel->eventq); -} - -/* Free buffers backing event queue */ -void falcon_remove_eventq(struct efx_channel *channel) -{ - falcon_free_special_buffer(channel->efx, &channel->eventq); -} - - -/* Generates a test event on the event queue. A subsequent call to - * process_eventq() should pick up the event and place the value of - * "magic" into channel->eventq_magic; - */ -void falcon_generate_test_event(struct efx_channel *channel, unsigned int magic) -{ - efx_qword_t test_event; - - EFX_POPULATE_QWORD_2(test_event, - EV_CODE, DRV_GEN_EV_DECODE, - EVQ_MAGIC, magic); - falcon_generate_event(channel, &test_event); -} - -void falcon_sim_phy_event(struct efx_nic *efx) -{ - efx_qword_t phy_event; - - EFX_POPULATE_QWORD_1(phy_event, EV_CODE, GLOBAL_EV_DECODE); - if (EFX_IS10G(efx)) - EFX_SET_OWORD_FIELD(phy_event, XG_PHY_INTR, 1); - else - EFX_SET_OWORD_FIELD(phy_event, G_PHY0_INTR, 1); - - falcon_generate_event(&efx->channel[0], &phy_event); -} - -/************************************************************************** - * - * Flush handling - * - **************************************************************************/ - - -static void falcon_poll_flush_events(struct efx_nic *efx) -{ - struct efx_channel *channel = &efx->channel[0]; - struct efx_tx_queue *tx_queue; - struct efx_rx_queue *rx_queue; - unsigned int read_ptr, i; - - read_ptr = channel->eventq_read_ptr; - for (i = 0; i < FALCON_EVQ_SIZE; ++i) { - efx_qword_t *event = falcon_event(channel, read_ptr); - int ev_code, ev_sub_code, ev_queue; - bool ev_failed; - if (!falcon_event_present(event)) - break; - - ev_code = EFX_QWORD_FIELD(*event, EV_CODE); - if (ev_code != DRIVER_EV_DECODE) - continue; - - ev_sub_code = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_CODE); - switch (ev_sub_code) { - case TX_DESCQ_FLS_DONE_EV_DECODE: - ev_queue = EFX_QWORD_FIELD(*event, - DRIVER_EV_TX_DESCQ_ID); - if (ev_queue < EFX_TX_QUEUE_COUNT) { - tx_queue = efx->tx_queue + ev_queue; - tx_queue->flushed = true; - } - break; - case RX_DESCQ_FLS_DONE_EV_DECODE: - ev_queue = EFX_QWORD_FIELD(*event, - DRIVER_EV_RX_DESCQ_ID); - ev_failed = EFX_QWORD_FIELD(*event, - DRIVER_EV_RX_FLUSH_FAIL); - if (ev_queue < efx->n_rx_queues) { - rx_queue = efx->rx_queue + ev_queue; - - /* retry the rx flush */ - if (ev_failed) - falcon_flush_rx_queue(rx_queue); - else - rx_queue->flushed = true; - } - break; - } - - read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK; - } -} - -/* Handle tx and rx flushes at the same time, since they run in - * parallel in the hardware and there's no reason for us to - * serialise them */ -int falcon_flush_queues(struct efx_nic *efx) -{ - struct efx_rx_queue *rx_queue; - struct efx_tx_queue *tx_queue; - int i; - bool outstanding; - - /* Issue flush requests */ - efx_for_each_tx_queue(tx_queue, efx) { - tx_queue->flushed = false; - falcon_flush_tx_queue(tx_queue); - } - efx_for_each_rx_queue(rx_queue, efx) { - rx_queue->flushed = false; - falcon_flush_rx_queue(rx_queue); - } - - /* Poll the evq looking for flush completions. Since we're not pushing - * any more rx or tx descriptors at this point, we're in no danger of - * overflowing the evq whilst we wait */ - for (i = 0; i < FALCON_FLUSH_POLL_COUNT; ++i) { - msleep(FALCON_FLUSH_INTERVAL); - falcon_poll_flush_events(efx); - - /* Check if every queue has been succesfully flushed */ - outstanding = false; - efx_for_each_tx_queue(tx_queue, efx) - outstanding |= !tx_queue->flushed; - efx_for_each_rx_queue(rx_queue, efx) - outstanding |= !rx_queue->flushed; - if (!outstanding) - return 0; - } - - /* Mark the queues as all flushed. We're going to return failure - * leading to a reset, or fake up success anyway. "flushed" now - * indicates that we tried to flush. */ - efx_for_each_tx_queue(tx_queue, efx) { - if (!tx_queue->flushed) - EFX_ERR(efx, "tx queue %d flush command timed out\n", - tx_queue->queue); - tx_queue->flushed = true; - } - efx_for_each_rx_queue(rx_queue, efx) { - if (!rx_queue->flushed) - EFX_ERR(efx, "rx queue %d flush command timed out\n", - rx_queue->queue); - rx_queue->flushed = true; - } - - if (EFX_WORKAROUND_7803(efx)) - return 0; - - return -ETIMEDOUT; -} - -/************************************************************************** - * - * Falcon hardware interrupts - * The hardware interrupt handler does very little work; all the event - * queue processing is carried out by per-channel tasklets. - * - **************************************************************************/ - -/* Enable/disable/generate Falcon interrupts */ -static inline void falcon_interrupts(struct efx_nic *efx, int enabled, - int force) -{ - efx_oword_t int_en_reg_ker; - - EFX_POPULATE_OWORD_2(int_en_reg_ker, - KER_INT_KER, force, - DRV_INT_EN_KER, enabled); - falcon_write(efx, &int_en_reg_ker, INT_EN_REG_KER); -} - -void falcon_enable_interrupts(struct efx_nic *efx) -{ - efx_oword_t int_adr_reg_ker; - struct efx_channel *channel; - - EFX_ZERO_OWORD(*((efx_oword_t *) efx->irq_status.addr)); - wmb(); /* Ensure interrupt vector is clear before interrupts enabled */ - - /* Program address */ - EFX_POPULATE_OWORD_2(int_adr_reg_ker, - NORM_INT_VEC_DIS_KER, EFX_INT_MODE_USE_MSI(efx), - INT_ADR_KER, efx->irq_status.dma_addr); - falcon_write(efx, &int_adr_reg_ker, INT_ADR_REG_KER); - - /* Enable interrupts */ - falcon_interrupts(efx, 1, 0); - - /* Force processing of all the channels to get the EVQ RPTRs up to - date */ - efx_for_each_channel(channel, efx) - efx_schedule_channel(channel); -} - -void falcon_disable_interrupts(struct efx_nic *efx) -{ - /* Disable interrupts */ - falcon_interrupts(efx, 0, 0); -} - -/* Generate a Falcon test interrupt - * Interrupt must already have been enabled, otherwise nasty things - * may happen. - */ -void falcon_generate_interrupt(struct efx_nic *efx) -{ - falcon_interrupts(efx, 1, 1); -} - -/* Acknowledge a legacy interrupt from Falcon - * - * This acknowledges a legacy (not MSI) interrupt via INT_ACK_KER_REG. - * - * Due to SFC bug 3706 (silicon revision <=A1) reads can be duplicated in the - * BIU. Interrupt acknowledge is read sensitive so must write instead - * (then read to ensure the BIU collector is flushed) - * - * NB most hardware supports MSI interrupts - */ -static inline void falcon_irq_ack_a1(struct efx_nic *efx) -{ - efx_dword_t reg; - - EFX_POPULATE_DWORD_1(reg, INT_ACK_DUMMY_DATA, 0xb7eb7e); - falcon_writel(efx, ®, INT_ACK_REG_KER_A1); - falcon_readl(efx, ®, WORK_AROUND_BROKEN_PCI_READS_REG_KER_A1); -} - -/* Process a fatal interrupt - * Disable bus mastering ASAP and schedule a reset - */ -static irqreturn_t falcon_fatal_interrupt(struct efx_nic *efx) -{ - struct falcon_nic_data *nic_data = efx->nic_data; - efx_oword_t *int_ker = efx->irq_status.addr; - efx_oword_t fatal_intr; - int error, mem_perr; - static int n_int_errors; - - falcon_read(efx, &fatal_intr, FATAL_INTR_REG_KER); - error = EFX_OWORD_FIELD(fatal_intr, INT_KER_ERROR); - - EFX_ERR(efx, "SYSTEM ERROR " EFX_OWORD_FMT " status " - EFX_OWORD_FMT ": %s\n", EFX_OWORD_VAL(*int_ker), - EFX_OWORD_VAL(fatal_intr), - error ? "disabling bus mastering" : "no recognised error"); - if (error == 0) - goto out; - - /* If this is a memory parity error dump which blocks are offending */ - mem_perr = EFX_OWORD_FIELD(fatal_intr, MEM_PERR_INT_KER); - if (mem_perr) { - efx_oword_t reg; - falcon_read(efx, ®, MEM_STAT_REG_KER); - EFX_ERR(efx, "SYSTEM ERROR: memory parity error " - EFX_OWORD_FMT "\n", EFX_OWORD_VAL(reg)); - } - - /* Disable both devices */ - pci_clear_master(efx->pci_dev); - if (FALCON_IS_DUAL_FUNC(efx)) - pci_clear_master(nic_data->pci_dev2); - falcon_disable_interrupts(efx); - - if (++n_int_errors < FALCON_MAX_INT_ERRORS) { - EFX_ERR(efx, "SYSTEM ERROR - reset scheduled\n"); - efx_schedule_reset(efx, RESET_TYPE_INT_ERROR); - } else { - EFX_ERR(efx, "SYSTEM ERROR - max number of errors seen." - "NIC will be disabled\n"); - efx_schedule_reset(efx, RESET_TYPE_DISABLE); - } -out: - return IRQ_HANDLED; -} - -/* Handle a legacy interrupt from Falcon - * Acknowledges the interrupt and schedule event queue processing. - */ -static irqreturn_t falcon_legacy_interrupt_b0(int irq, void *dev_id) -{ - struct efx_nic *efx = dev_id; - efx_oword_t *int_ker = efx->irq_status.addr; - struct efx_channel *channel; - efx_dword_t reg; - u32 queues; - int syserr; - - /* Read the ISR which also ACKs the interrupts */ - falcon_readl(efx, ®, INT_ISR0_B0); - queues = EFX_EXTRACT_DWORD(reg, 0, 31); - - /* Check to see if we have a serious error condition */ - syserr = EFX_OWORD_FIELD(*int_ker, FATAL_INT); - if (unlikely(syserr)) - return falcon_fatal_interrupt(efx); - - if (queues == 0) - return IRQ_NONE; - - efx->last_irq_cpu = raw_smp_processor_id(); - EFX_TRACE(efx, "IRQ %d on CPU %d status " EFX_DWORD_FMT "\n", - irq, raw_smp_processor_id(), EFX_DWORD_VAL(reg)); - - /* Schedule processing of any interrupting queues */ - channel = &efx->channel[0]; - while (queues) { - if (queues & 0x01) - efx_schedule_channel(channel); - channel++; - queues >>= 1; - } - - return IRQ_HANDLED; -} - - -static irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id) -{ - struct efx_nic *efx = dev_id; - efx_oword_t *int_ker = efx->irq_status.addr; - struct efx_channel *channel; - int syserr; - int queues; - - /* Check to see if this is our interrupt. If it isn't, we - * exit without having touched the hardware. - */ - if (unlikely(EFX_OWORD_IS_ZERO(*int_ker))) { - EFX_TRACE(efx, "IRQ %d on CPU %d not for me\n", irq, - raw_smp_processor_id()); - return IRQ_NONE; - } - efx->last_irq_cpu = raw_smp_processor_id(); - EFX_TRACE(efx, "IRQ %d on CPU %d status " EFX_OWORD_FMT "\n", - irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker)); - - /* Check to see if we have a serious error condition */ - syserr = EFX_OWORD_FIELD(*int_ker, FATAL_INT); - if (unlikely(syserr)) - return falcon_fatal_interrupt(efx); - - /* Determine interrupting queues, clear interrupt status - * register and acknowledge the device interrupt. - */ - BUILD_BUG_ON(INT_EVQS_WIDTH > EFX_MAX_CHANNELS); - queues = EFX_OWORD_FIELD(*int_ker, INT_EVQS); - EFX_ZERO_OWORD(*int_ker); - wmb(); /* Ensure the vector is cleared before interrupt ack */ - falcon_irq_ack_a1(efx); - - /* Schedule processing of any interrupting queues */ - channel = &efx->channel[0]; - while (queues) { - if (queues & 0x01) - efx_schedule_channel(channel); - channel++; - queues >>= 1; - } - - return IRQ_HANDLED; -} - -/* Handle an MSI interrupt from Falcon - * - * Handle an MSI hardware interrupt. This routine schedules event - * queue processing. No interrupt acknowledgement cycle is necessary. - * Also, we never need to check that the interrupt is for us, since - * MSI interrupts cannot be shared. - */ -static irqreturn_t falcon_msi_interrupt(int irq, void *dev_id) -{ - struct efx_channel *channel = dev_id; - struct efx_nic *efx = channel->efx; - efx_oword_t *int_ker = efx->irq_status.addr; - int syserr; - - efx->last_irq_cpu = raw_smp_processor_id(); - EFX_TRACE(efx, "IRQ %d on CPU %d status " EFX_OWORD_FMT "\n", - irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker)); - - /* Check to see if we have a serious error condition */ - syserr = EFX_OWORD_FIELD(*int_ker, FATAL_INT); - if (unlikely(syserr)) - return falcon_fatal_interrupt(efx); - - /* Schedule processing of the channel */ - efx_schedule_channel(channel); - - return IRQ_HANDLED; -} - - -/* Setup RSS indirection table. - * This maps from the hash value of the packet to RXQ - */ -static void falcon_setup_rss_indir_table(struct efx_nic *efx) -{ - int i = 0; - unsigned long offset; - efx_dword_t dword; - - if (falcon_rev(efx) < FALCON_REV_B0) - return; - - for (offset = RX_RSS_INDIR_TBL_B0; - offset < RX_RSS_INDIR_TBL_B0 + 0x800; - offset += 0x10) { - EFX_POPULATE_DWORD_1(dword, RX_RSS_INDIR_ENT_B0, - i % efx->n_rx_queues); - falcon_writel(efx, &dword, offset); - i++; - } -} - -/* Hook interrupt handler(s) - * Try MSI and then legacy interrupts. - */ -int falcon_init_interrupt(struct efx_nic *efx) -{ - struct efx_channel *channel; - int rc; - - if (!EFX_INT_MODE_USE_MSI(efx)) { - irq_handler_t handler; - if (falcon_rev(efx) >= FALCON_REV_B0) - handler = falcon_legacy_interrupt_b0; - else - handler = falcon_legacy_interrupt_a1; - - rc = request_irq(efx->legacy_irq, handler, IRQF_SHARED, - efx->name, efx); - if (rc) { - EFX_ERR(efx, "failed to hook legacy IRQ %d\n", - efx->pci_dev->irq); - goto fail1; - } - return 0; - } - - /* Hook MSI or MSI-X interrupt */ - efx_for_each_channel(channel, efx) { - rc = request_irq(channel->irq, falcon_msi_interrupt, - IRQF_PROBE_SHARED, /* Not shared */ - channel->name, channel); - if (rc) { - EFX_ERR(efx, "failed to hook IRQ %d\n", channel->irq); - goto fail2; - } - } - - return 0; - - fail2: - efx_for_each_channel(channel, efx) - free_irq(channel->irq, channel); - fail1: - return rc; -} - -void falcon_fini_interrupt(struct efx_nic *efx) -{ - struct efx_channel *channel; - efx_oword_t reg; - - /* Disable MSI/MSI-X interrupts */ - efx_for_each_channel(channel, efx) { - if (channel->irq) - free_irq(channel->irq, channel); - } - - /* ACK legacy interrupt */ - if (falcon_rev(efx) >= FALCON_REV_B0) - falcon_read(efx, ®, INT_ISR0_B0); - else - falcon_irq_ack_a1(efx); - - /* Disable legacy interrupt */ - if (efx->legacy_irq) - free_irq(efx->legacy_irq, efx); -} - -/************************************************************************** - * - * EEPROM/flash - * - ************************************************************************** - */ - -#define FALCON_SPI_MAX_LEN sizeof(efx_oword_t) - -static int falcon_spi_poll(struct efx_nic *efx) -{ - efx_oword_t reg; - falcon_read(efx, ®, EE_SPI_HCMD_REG_KER); - return EFX_OWORD_FIELD(reg, EE_SPI_HCMD_CMD_EN) ? -EBUSY : 0; -} - -/* Wait for SPI command completion */ -static int falcon_spi_wait(struct efx_nic *efx) -{ - /* Most commands will finish quickly, so we start polling at - * very short intervals. Sometimes the command may have to - * wait for VPD or expansion ROM access outside of our - * control, so we allow up to 100 ms. */ - unsigned long timeout = jiffies + 1 + DIV_ROUND_UP(HZ, 10); - int i; - - for (i = 0; i < 10; i++) { - if (!falcon_spi_poll(efx)) - return 0; - udelay(10); - } - - for (;;) { - if (!falcon_spi_poll(efx)) - return 0; - if (time_after_eq(jiffies, timeout)) { - EFX_ERR(efx, "timed out waiting for SPI\n"); - return -ETIMEDOUT; - } - schedule_timeout_uninterruptible(1); - } -} - -int falcon_spi_cmd(const struct efx_spi_device *spi, - unsigned int command, int address, - const void *in, void *out, size_t len) -{ - struct efx_nic *efx = spi->efx; - bool addressed = (address >= 0); - bool reading = (out != NULL); - efx_oword_t reg; - int rc; - - /* Input validation */ - if (len > FALCON_SPI_MAX_LEN) - return -EINVAL; - BUG_ON(!mutex_is_locked(&efx->spi_lock)); - - /* Check that previous command is not still running */ - rc = falcon_spi_poll(efx); - if (rc) - return rc; - - /* Program address register, if we have an address */ - if (addressed) { - EFX_POPULATE_OWORD_1(reg, EE_SPI_HADR_ADR, address); - falcon_write(efx, ®, EE_SPI_HADR_REG_KER); - } - - /* Program data register, if we have data */ - if (in != NULL) { - memcpy(®, in, len); - falcon_write(efx, ®, EE_SPI_HDATA_REG_KER); - } - - /* Issue read/write command */ - EFX_POPULATE_OWORD_7(reg, - EE_SPI_HCMD_CMD_EN, 1, - EE_SPI_HCMD_SF_SEL, spi->device_id, - EE_SPI_HCMD_DABCNT, len, - EE_SPI_HCMD_READ, reading, - EE_SPI_HCMD_DUBCNT, 0, - EE_SPI_HCMD_ADBCNT, - (addressed ? spi->addr_len : 0), - EE_SPI_HCMD_ENC, command); - falcon_write(efx, ®, EE_SPI_HCMD_REG_KER); - - /* Wait for read/write to complete */ - rc = falcon_spi_wait(efx); - if (rc) - return rc; - - /* Read data */ - if (out != NULL) { - falcon_read(efx, ®, EE_SPI_HDATA_REG_KER); - memcpy(out, ®, len); - } - - return 0; -} - -static size_t -falcon_spi_write_limit(const struct efx_spi_device *spi, size_t start) -{ - return min(FALCON_SPI_MAX_LEN, - (spi->block_size - (start & (spi->block_size - 1)))); -} - -static inline u8 -efx_spi_munge_command(const struct efx_spi_device *spi, - const u8 command, const unsigned int address) -{ - return command | (((address >> 8) & spi->munge_address) << 3); -} - -/* Wait up to 10 ms for buffered write completion */ -int falcon_spi_wait_write(const struct efx_spi_device *spi) -{ - struct efx_nic *efx = spi->efx; - unsigned long timeout = jiffies + 1 + DIV_ROUND_UP(HZ, 100); - u8 status; - int rc; - - for (;;) { - rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL, - &status, sizeof(status)); - if (rc) - return rc; - if (!(status & SPI_STATUS_NRDY)) - return 0; - if (time_after_eq(jiffies, timeout)) { - EFX_ERR(efx, "SPI write timeout on device %d" - " last status=0x%02x\n", - spi->device_id, status); - return -ETIMEDOUT; - } - schedule_timeout_uninterruptible(1); - } -} - -int falcon_spi_read(const struct efx_spi_device *spi, loff_t start, - size_t len, size_t *retlen, u8 *buffer) -{ - size_t block_len, pos = 0; - unsigned int command; - int rc = 0; - - while (pos < len) { - block_len = min(len - pos, FALCON_SPI_MAX_LEN); - - command = efx_spi_munge_command(spi, SPI_READ, start + pos); - rc = falcon_spi_cmd(spi, command, start + pos, NULL, - buffer + pos, block_len); - if (rc) - break; - pos += block_len; - - /* Avoid locking up the system */ - cond_resched(); - if (signal_pending(current)) { - rc = -EINTR; - break; - } - } - - if (retlen) - *retlen = pos; - return rc; -} - -int falcon_spi_write(const struct efx_spi_device *spi, loff_t start, - size_t len, size_t *retlen, const u8 *buffer) -{ - u8 verify_buffer[FALCON_SPI_MAX_LEN]; - size_t block_len, pos = 0; - unsigned int command; - int rc = 0; - - while (pos < len) { - rc = falcon_spi_cmd(spi, SPI_WREN, -1, NULL, NULL, 0); - if (rc) - break; - - block_len = min(len - pos, - falcon_spi_write_limit(spi, start + pos)); - command = efx_spi_munge_command(spi, SPI_WRITE, start + pos); - rc = falcon_spi_cmd(spi, command, start + pos, - buffer + pos, NULL, block_len); - if (rc) - break; - - rc = falcon_spi_wait_write(spi); - if (rc) - break; - - command = efx_spi_munge_command(spi, SPI_READ, start + pos); - rc = falcon_spi_cmd(spi, command, start + pos, - NULL, verify_buffer, block_len); - if (memcmp(verify_buffer, buffer + pos, block_len)) { - rc = -EIO; - break; - } - - pos += block_len; - - /* Avoid locking up the system */ - cond_resched(); - if (signal_pending(current)) { - rc = -EINTR; - break; - } - } - - if (retlen) - *retlen = pos; - return rc; -} - -/************************************************************************** - * - * MAC wrapper - * - ************************************************************************** - */ - -static int falcon_reset_macs(struct efx_nic *efx) -{ - efx_oword_t reg; - int count; - - if (falcon_rev(efx) < FALCON_REV_B0) { - /* It's not safe to use GLB_CTL_REG to reset the - * macs, so instead use the internal MAC resets - */ - if (!EFX_IS10G(efx)) { - EFX_POPULATE_OWORD_1(reg, GM_SW_RST, 1); - falcon_write(efx, ®, GM_CFG1_REG); - udelay(1000); - - EFX_POPULATE_OWORD_1(reg, GM_SW_RST, 0); - falcon_write(efx, ®, GM_CFG1_REG); - udelay(1000); - return 0; - } else { - EFX_POPULATE_OWORD_1(reg, XM_CORE_RST, 1); - falcon_write(efx, ®, XM_GLB_CFG_REG); - - for (count = 0; count < 10000; count++) { - falcon_read(efx, ®, XM_GLB_CFG_REG); - if (EFX_OWORD_FIELD(reg, XM_CORE_RST) == 0) - return 0; - udelay(10); - } - - EFX_ERR(efx, "timed out waiting for XMAC core reset\n"); - return -ETIMEDOUT; - } - } - - /* MAC stats will fail whilst the TX fifo is draining. Serialise - * the drain sequence with the statistics fetch */ - efx_stats_disable(efx); - - falcon_read(efx, ®, MAC0_CTRL_REG_KER); - EFX_SET_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0, 1); - falcon_write(efx, ®, MAC0_CTRL_REG_KER); - - falcon_read(efx, ®, GLB_CTL_REG_KER); - EFX_SET_OWORD_FIELD(reg, RST_XGTX, 1); - EFX_SET_OWORD_FIELD(reg, RST_XGRX, 1); - EFX_SET_OWORD_FIELD(reg, RST_EM, 1); - falcon_write(efx, ®, GLB_CTL_REG_KER); - - count = 0; - while (1) { - falcon_read(efx, ®, GLB_CTL_REG_KER); - if (!EFX_OWORD_FIELD(reg, RST_XGTX) && - !EFX_OWORD_FIELD(reg, RST_XGRX) && - !EFX_OWORD_FIELD(reg, RST_EM)) { - EFX_LOG(efx, "Completed MAC reset after %d loops\n", - count); - break; - } - if (count > 20) { - EFX_ERR(efx, "MAC reset failed\n"); - break; - } - count++; - udelay(10); - } - - efx_stats_enable(efx); - - /* If we've reset the EM block and the link is up, then - * we'll have to kick the XAUI link so the PHY can recover */ - if (efx->link_up && EFX_IS10G(efx) && EFX_WORKAROUND_5147(efx)) - falcon_reset_xaui(efx); - - return 0; -} - -void falcon_drain_tx_fifo(struct efx_nic *efx) -{ - efx_oword_t reg; - - if ((falcon_rev(efx) < FALCON_REV_B0) || - (efx->loopback_mode != LOOPBACK_NONE)) - return; - - falcon_read(efx, ®, MAC0_CTRL_REG_KER); - /* There is no point in draining more than once */ - if (EFX_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0)) - return; - - falcon_reset_macs(efx); -} - -void falcon_deconfigure_mac_wrapper(struct efx_nic *efx) -{ - efx_oword_t reg; - - if (falcon_rev(efx) < FALCON_REV_B0) - return; - - /* Isolate the MAC -> RX */ - falcon_read(efx, ®, RX_CFG_REG_KER); - EFX_SET_OWORD_FIELD(reg, RX_INGR_EN_B0, 0); - falcon_write(efx, ®, RX_CFG_REG_KER); - - if (!efx->link_up) - falcon_drain_tx_fifo(efx); -} - -void falcon_reconfigure_mac_wrapper(struct efx_nic *efx) -{ - efx_oword_t reg; - int link_speed; - bool tx_fc; - - switch (efx->link_speed) { - case 10000: link_speed = 3; break; - case 1000: link_speed = 2; break; - case 100: link_speed = 1; break; - default: link_speed = 0; break; - } - /* MAC_LINK_STATUS controls MAC backpressure but doesn't work - * as advertised. Disable to ensure packets are not - * indefinitely held and TX queue can be flushed at any point - * while the link is down. */ - EFX_POPULATE_OWORD_5(reg, - MAC_XOFF_VAL, 0xffff /* max pause time */, - MAC_BCAD_ACPT, 1, - MAC_UC_PROM, efx->promiscuous, - MAC_LINK_STATUS, 1, /* always set */ - MAC_SPEED, link_speed); - /* On B0, MAC backpressure can be disabled and packets get - * discarded. */ - if (falcon_rev(efx) >= FALCON_REV_B0) { - EFX_SET_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0, - !efx->link_up); - } - - falcon_write(efx, ®, MAC0_CTRL_REG_KER); - - /* Restore the multicast hash registers. */ - falcon_set_multicast_hash(efx); - - /* Transmission of pause frames when RX crosses the threshold is - * covered by RX_XOFF_MAC_EN and XM_TX_CFG_REG:XM_FCNTL. - * Action on receipt of pause frames is controller by XM_DIS_FCNTL */ - tx_fc = !!(efx->link_fc & EFX_FC_TX); - falcon_read(efx, ®, RX_CFG_REG_KER); - EFX_SET_OWORD_FIELD_VER(efx, reg, RX_XOFF_MAC_EN, tx_fc); - - /* Unisolate the MAC -> RX */ - if (falcon_rev(efx) >= FALCON_REV_B0) - EFX_SET_OWORD_FIELD(reg, RX_INGR_EN_B0, 1); - falcon_write(efx, ®, RX_CFG_REG_KER); -} - -int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset) -{ - efx_oword_t reg; - u32 *dma_done; - int i; - - if (disable_dma_stats) - return 0; - - /* Statistics fetch will fail if the MAC is in TX drain */ - if (falcon_rev(efx) >= FALCON_REV_B0) { - efx_oword_t temp; - falcon_read(efx, &temp, MAC0_CTRL_REG_KER); - if (EFX_OWORD_FIELD(temp, TXFIFO_DRAIN_EN_B0)) - return 0; - } - - dma_done = (efx->stats_buffer.addr + done_offset); - *dma_done = FALCON_STATS_NOT_DONE; - wmb(); /* ensure done flag is clear */ - - /* Initiate DMA transfer of stats */ - EFX_POPULATE_OWORD_2(reg, - MAC_STAT_DMA_CMD, 1, - MAC_STAT_DMA_ADR, - efx->stats_buffer.dma_addr); - falcon_write(efx, ®, MAC0_STAT_DMA_REG_KER); - - /* Wait for transfer to complete */ - for (i = 0; i < 400; i++) { - if (*(volatile u32 *)dma_done == FALCON_STATS_DONE) { - rmb(); /* Ensure the stats are valid. */ - return 0; - } - udelay(10); - } - - EFX_ERR(efx, "timed out waiting for statistics\n"); - return -ETIMEDOUT; -} - -/************************************************************************** - * - * PHY access via GMII - * - ************************************************************************** - */ - -/* Use the top bit of the MII PHY id to indicate the PHY type - * (1G/10G), with the remaining bits as the actual PHY id. - * - * This allows us to avoid leaking information from the mii_if_info - * structure into other data structures. - */ -#define FALCON_PHY_ID_ID_WIDTH EFX_WIDTH(MD_PRT_DEV_ADR) -#define FALCON_PHY_ID_ID_MASK ((1 << FALCON_PHY_ID_ID_WIDTH) - 1) -#define FALCON_PHY_ID_WIDTH (FALCON_PHY_ID_ID_WIDTH + 1) -#define FALCON_PHY_ID_MASK ((1 << FALCON_PHY_ID_WIDTH) - 1) -#define FALCON_PHY_ID_10G (1 << (FALCON_PHY_ID_WIDTH - 1)) - - -/* Packing the clause 45 port and device fields into a single value */ -#define MD_PRT_ADR_COMP_LBN (MD_PRT_ADR_LBN - MD_DEV_ADR_LBN) -#define MD_PRT_ADR_COMP_WIDTH MD_PRT_ADR_WIDTH -#define MD_DEV_ADR_COMP_LBN 0 -#define MD_DEV_ADR_COMP_WIDTH MD_DEV_ADR_WIDTH - - -/* Wait for GMII access to complete */ -static int falcon_gmii_wait(struct efx_nic *efx) -{ - efx_dword_t md_stat; - int count; - - /* wait upto 50ms - taken max from datasheet */ - for (count = 0; count < 5000; count++) { - falcon_readl(efx, &md_stat, MD_STAT_REG_KER); - if (EFX_DWORD_FIELD(md_stat, MD_BSY) == 0) { - if (EFX_DWORD_FIELD(md_stat, MD_LNFL) != 0 || - EFX_DWORD_FIELD(md_stat, MD_BSERR) != 0) { - EFX_ERR(efx, "error from GMII access " - EFX_DWORD_FMT"\n", - EFX_DWORD_VAL(md_stat)); - return -EIO; - } - return 0; - } - udelay(10); - } - EFX_ERR(efx, "timed out waiting for GMII\n"); - return -ETIMEDOUT; -} - -/* Writes a GMII register of a PHY connected to Falcon using MDIO. */ -static void falcon_mdio_write(struct net_device *net_dev, int phy_id, - int addr, int value) -{ - struct efx_nic *efx = netdev_priv(net_dev); - unsigned int phy_id2 = phy_id & FALCON_PHY_ID_ID_MASK; - efx_oword_t reg; - - /* The 'generic' prt/dev packing in mdio_10g.h is conveniently - * chosen so that the only current user, Falcon, can take the - * packed value and use them directly. - * Fail to build if this assumption is broken. - */ - BUILD_BUG_ON(FALCON_PHY_ID_10G != MDIO45_XPRT_ID_IS10G); - BUILD_BUG_ON(FALCON_PHY_ID_ID_WIDTH != MDIO45_PRT_DEV_WIDTH); - BUILD_BUG_ON(MD_PRT_ADR_COMP_LBN != MDIO45_PRT_ID_COMP_LBN); - BUILD_BUG_ON(MD_DEV_ADR_COMP_LBN != MDIO45_DEV_ID_COMP_LBN); - - if (phy_id2 == PHY_ADDR_INVALID) - return; - - /* See falcon_mdio_read for an explanation. */ - if (!(phy_id & FALCON_PHY_ID_10G)) { - int mmd = ffs(efx->phy_op->mmds) - 1; - EFX_TRACE(efx, "Fixing erroneous clause22 write\n"); - phy_id2 = mdio_clause45_pack(phy_id2, mmd) - & FALCON_PHY_ID_ID_MASK; - } - - EFX_REGDUMP(efx, "writing GMII %d register %02x with %04x\n", phy_id, - addr, value); - - spin_lock_bh(&efx->phy_lock); - - /* Check MII not currently being accessed */ - if (falcon_gmii_wait(efx) != 0) - goto out; - - /* Write the address/ID register */ - EFX_POPULATE_OWORD_1(reg, MD_PHY_ADR, addr); - falcon_write(efx, ®, MD_PHY_ADR_REG_KER); - - EFX_POPULATE_OWORD_1(reg, MD_PRT_DEV_ADR, phy_id2); - falcon_write(efx, ®, MD_ID_REG_KER); - - /* Write data */ - EFX_POPULATE_OWORD_1(reg, MD_TXD, value); - falcon_write(efx, ®, MD_TXD_REG_KER); - - EFX_POPULATE_OWORD_2(reg, - MD_WRC, 1, - MD_GC, 0); - falcon_write(efx, ®, MD_CS_REG_KER); - - /* Wait for data to be written */ - if (falcon_gmii_wait(efx) != 0) { - /* Abort the write operation */ - EFX_POPULATE_OWORD_2(reg, - MD_WRC, 0, - MD_GC, 1); - falcon_write(efx, ®, MD_CS_REG_KER); - udelay(10); - } - - out: - spin_unlock_bh(&efx->phy_lock); -} - -/* Reads a GMII register from a PHY connected to Falcon. If no value - * could be read, -1 will be returned. */ -static int falcon_mdio_read(struct net_device *net_dev, int phy_id, int addr) -{ - struct efx_nic *efx = netdev_priv(net_dev); - unsigned int phy_addr = phy_id & FALCON_PHY_ID_ID_MASK; - efx_oword_t reg; - int value = -1; - - if (phy_addr == PHY_ADDR_INVALID) - return -1; - - /* Our PHY code knows whether it needs to talk clause 22(1G) or 45(10G) - * but the generic Linux code does not make any distinction or have - * any state for this. - * We spot the case where someone tried to talk 22 to a 45 PHY and - * redirect the request to the lowest numbered MMD as a clause45 - * request. This is enough to allow simple queries like id and link - * state to succeed. TODO: We may need to do more in future. - */ - if (!(phy_id & FALCON_PHY_ID_10G)) { - int mmd = ffs(efx->phy_op->mmds) - 1; - EFX_TRACE(efx, "Fixing erroneous clause22 read\n"); - phy_addr = mdio_clause45_pack(phy_addr, mmd) - & FALCON_PHY_ID_ID_MASK; - } - - spin_lock_bh(&efx->phy_lock); - - /* Check MII not currently being accessed */ - if (falcon_gmii_wait(efx) != 0) - goto out; - - EFX_POPULATE_OWORD_1(reg, MD_PHY_ADR, addr); - falcon_write(efx, ®, MD_PHY_ADR_REG_KER); - - EFX_POPULATE_OWORD_1(reg, MD_PRT_DEV_ADR, phy_addr); - falcon_write(efx, ®, MD_ID_REG_KER); - - /* Request data to be read */ - EFX_POPULATE_OWORD_2(reg, MD_RDC, 1, MD_GC, 0); - falcon_write(efx, ®, MD_CS_REG_KER); - - /* Wait for data to become available */ - value = falcon_gmii_wait(efx); - if (value == 0) { - falcon_read(efx, ®, MD_RXD_REG_KER); - value = EFX_OWORD_FIELD(reg, MD_RXD); - EFX_REGDUMP(efx, "read from GMII %d register %02x, got %04x\n", - phy_id, addr, value); - } else { - /* Abort the read operation */ - EFX_POPULATE_OWORD_2(reg, - MD_RIC, 0, - MD_GC, 1); - falcon_write(efx, ®, MD_CS_REG_KER); - - EFX_LOG(efx, "read from GMII 0x%x register %02x, got " - "error %d\n", phy_id, addr, value); - } - - out: - spin_unlock_bh(&efx->phy_lock); - - return value; -} - -static void falcon_init_mdio(struct mii_if_info *gmii) -{ - gmii->mdio_read = falcon_mdio_read; - gmii->mdio_write = falcon_mdio_write; - gmii->phy_id_mask = FALCON_PHY_ID_MASK; - gmii->reg_num_mask = ((1 << EFX_WIDTH(MD_PHY_ADR)) - 1); -} - -static int falcon_probe_phy(struct efx_nic *efx) -{ - switch (efx->phy_type) { - case PHY_TYPE_SFX7101: - efx->phy_op = &falcon_sfx7101_phy_ops; - break; - case PHY_TYPE_SFT9001A: - case PHY_TYPE_SFT9001B: - efx->phy_op = &falcon_sft9001_phy_ops; - break; - case PHY_TYPE_QT2022C2: - efx->phy_op = &falcon_xfp_phy_ops; - break; - default: - EFX_ERR(efx, "Unknown PHY type %d\n", - efx->phy_type); - return -1; - } - - if (efx->phy_op->macs & EFX_XMAC) - efx->loopback_modes |= ((1 << LOOPBACK_XGMII) | - (1 << LOOPBACK_XGXS) | - (1 << LOOPBACK_XAUI)); - if (efx->phy_op->macs & EFX_GMAC) - efx->loopback_modes |= (1 << LOOPBACK_GMAC); - efx->loopback_modes |= efx->phy_op->loopbacks; - - return 0; -} - -int falcon_switch_mac(struct efx_nic *efx) -{ - struct efx_mac_operations *old_mac_op = efx->mac_op; - efx_oword_t nic_stat; - unsigned strap_val; - int rc = 0; - - /* Don't try to fetch MAC stats while we're switching MACs */ - efx_stats_disable(efx); - - /* Internal loopbacks override the phy speed setting */ - if (efx->loopback_mode == LOOPBACK_GMAC) { - efx->link_speed = 1000; - efx->link_fd = true; - } else if (LOOPBACK_INTERNAL(efx)) { - efx->link_speed = 10000; - efx->link_fd = true; - } - - WARN_ON(!mutex_is_locked(&efx->mac_lock)); - efx->mac_op = (EFX_IS10G(efx) ? - &falcon_xmac_operations : &falcon_gmac_operations); - - /* Always push the NIC_STAT_REG setting even if the mac hasn't - * changed, because this function is run post online reset */ - falcon_read(efx, &nic_stat, NIC_STAT_REG); - strap_val = EFX_IS10G(efx) ? 5 : 3; - if (falcon_rev(efx) >= FALCON_REV_B0) { - EFX_SET_OWORD_FIELD(nic_stat, EE_STRAP_EN, 1); - EFX_SET_OWORD_FIELD(nic_stat, EE_STRAP_OVR, strap_val); - falcon_write(efx, &nic_stat, NIC_STAT_REG); - } else { - /* Falcon A1 does not support 1G/10G speed switching - * and must not be used with a PHY that does. */ - BUG_ON(EFX_OWORD_FIELD(nic_stat, STRAP_PINS) != strap_val); - } - - if (old_mac_op == efx->mac_op) - goto out; - - EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G'); - /* Not all macs support a mac-level link state */ - efx->mac_up = true; - - rc = falcon_reset_macs(efx); -out: - efx_stats_enable(efx); - return rc; -} - -/* This call is responsible for hooking in the MAC and PHY operations */ -int falcon_probe_port(struct efx_nic *efx) -{ - int rc; - - /* Hook in PHY operations table */ - rc = falcon_probe_phy(efx); - if (rc) - return rc; - - /* Set up GMII structure for PHY */ - efx->mii.supports_gmii = true; - falcon_init_mdio(&efx->mii); - - /* Hardware flow ctrl. FalconA RX FIFO too small for pause generation */ - if (falcon_rev(efx) >= FALCON_REV_B0) - efx->wanted_fc = EFX_FC_RX | EFX_FC_TX; - else - efx->wanted_fc = EFX_FC_RX; - - /* Allocate buffer for stats */ - rc = falcon_alloc_buffer(efx, &efx->stats_buffer, - FALCON_MAC_STATS_SIZE); - if (rc) - return rc; - EFX_LOG(efx, "stats buffer at %llx (virt %p phys %lx)\n", - (unsigned long long)efx->stats_buffer.dma_addr, - efx->stats_buffer.addr, - virt_to_phys(efx->stats_buffer.addr)); - - return 0; -} - -void falcon_remove_port(struct efx_nic *efx) -{ - falcon_free_buffer(efx, &efx->stats_buffer); -} - -/************************************************************************** - * - * Multicast filtering - * - ************************************************************************** - */ - -void falcon_set_multicast_hash(struct efx_nic *efx) -{ - union efx_multicast_hash *mc_hash = &efx->multicast_hash; - - /* Broadcast packets go through the multicast hash filter. - * ether_crc_le() of the broadcast address is 0xbe2612ff - * so we always add bit 0xff to the mask. - */ - set_bit_le(0xff, mc_hash->byte); - - falcon_write(efx, &mc_hash->oword[0], MAC_MCAST_HASH_REG0_KER); - falcon_write(efx, &mc_hash->oword[1], MAC_MCAST_HASH_REG1_KER); -} - - -/************************************************************************** - * - * Falcon test code - * - **************************************************************************/ - -int falcon_read_nvram(struct efx_nic *efx, struct falcon_nvconfig *nvconfig_out) -{ - struct falcon_nvconfig *nvconfig; - struct efx_spi_device *spi; - void *region; - int rc, magic_num, struct_ver; - __le16 *word, *limit; - u32 csum; - - spi = efx->spi_flash ? efx->spi_flash : efx->spi_eeprom; - if (!spi) - return -EINVAL; - - region = kmalloc(FALCON_NVCONFIG_END, GFP_KERNEL); - if (!region) - return -ENOMEM; - nvconfig = region + NVCONFIG_OFFSET; - - mutex_lock(&efx->spi_lock); - rc = falcon_spi_read(spi, 0, FALCON_NVCONFIG_END, NULL, region); - mutex_unlock(&efx->spi_lock); - if (rc) { - EFX_ERR(efx, "Failed to read %s\n", - efx->spi_flash ? "flash" : "EEPROM"); - rc = -EIO; - goto out; - } - - magic_num = le16_to_cpu(nvconfig->board_magic_num); - struct_ver = le16_to_cpu(nvconfig->board_struct_ver); - - rc = -EINVAL; - if (magic_num != NVCONFIG_BOARD_MAGIC_NUM) { - EFX_ERR(efx, "NVRAM bad magic 0x%x\n", magic_num); - goto out; - } - if (struct_ver < 2) { - EFX_ERR(efx, "NVRAM has ancient version 0x%x\n", struct_ver); - goto out; - } else if (struct_ver < 4) { - word = &nvconfig->board_magic_num; - limit = (__le16 *) (nvconfig + 1); - } else { - word = region; - limit = region + FALCON_NVCONFIG_END; - } - for (csum = 0; word < limit; ++word) - csum += le16_to_cpu(*word); - - if (~csum & 0xffff) { - EFX_ERR(efx, "NVRAM has incorrect checksum\n"); - goto out; - } - - rc = 0; - if (nvconfig_out) - memcpy(nvconfig_out, nvconfig, sizeof(*nvconfig)); - - out: - kfree(region); - return rc; -} - -/* Registers tested in the falcon register test */ -static struct { - unsigned address; - efx_oword_t mask; -} efx_test_registers[] = { - { ADR_REGION_REG_KER, - EFX_OWORD32(0x0001FFFF, 0x0001FFFF, 0x0001FFFF, 0x0001FFFF) }, - { RX_CFG_REG_KER, - EFX_OWORD32(0xFFFFFFFE, 0x00017FFF, 0x00000000, 0x00000000) }, - { TX_CFG_REG_KER, - EFX_OWORD32(0x7FFF0037, 0x00000000, 0x00000000, 0x00000000) }, - { TX_CFG2_REG_KER, - EFX_OWORD32(0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF) }, - { MAC0_CTRL_REG_KER, - EFX_OWORD32(0xFFFF0000, 0x00000000, 0x00000000, 0x00000000) }, - { SRM_TX_DC_CFG_REG_KER, - EFX_OWORD32(0x001FFFFF, 0x00000000, 0x00000000, 0x00000000) }, - { RX_DC_CFG_REG_KER, - EFX_OWORD32(0x0000000F, 0x00000000, 0x00000000, 0x00000000) }, - { RX_DC_PF_WM_REG_KER, - EFX_OWORD32(0x000003FF, 0x00000000, 0x00000000, 0x00000000) }, - { DP_CTRL_REG, - EFX_OWORD32(0x00000FFF, 0x00000000, 0x00000000, 0x00000000) }, - { GM_CFG2_REG, - EFX_OWORD32(0x00007337, 0x00000000, 0x00000000, 0x00000000) }, - { GMF_CFG0_REG, - EFX_OWORD32(0x00001F1F, 0x00000000, 0x00000000, 0x00000000) }, - { XM_GLB_CFG_REG, - EFX_OWORD32(0x00000C68, 0x00000000, 0x00000000, 0x00000000) }, - { XM_TX_CFG_REG, - EFX_OWORD32(0x00080164, 0x00000000, 0x00000000, 0x00000000) }, - { XM_RX_CFG_REG, - EFX_OWORD32(0x07100A0C, 0x00000000, 0x00000000, 0x00000000) }, - { XM_RX_PARAM_REG, - EFX_OWORD32(0x00001FF8, 0x00000000, 0x00000000, 0x00000000) }, - { XM_FC_REG, - EFX_OWORD32(0xFFFF0001, 0x00000000, 0x00000000, 0x00000000) }, - { XM_ADR_LO_REG, - EFX_OWORD32(0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000) }, - { XX_SD_CTL_REG, - EFX_OWORD32(0x0003FF0F, 0x00000000, 0x00000000, 0x00000000) }, -}; - -static bool efx_masked_compare_oword(const efx_oword_t *a, const efx_oword_t *b, - const efx_oword_t *mask) -{ - return ((a->u64[0] ^ b->u64[0]) & mask->u64[0]) || - ((a->u64[1] ^ b->u64[1]) & mask->u64[1]); -} - -int falcon_test_registers(struct efx_nic *efx) -{ - unsigned address = 0, i, j; - efx_oword_t mask, imask, original, reg, buf; - - /* Falcon should be in loopback to isolate the XMAC from the PHY */ - WARN_ON(!LOOPBACK_INTERNAL(efx)); - - for (i = 0; i < ARRAY_SIZE(efx_test_registers); ++i) { - address = efx_test_registers[i].address; - mask = imask = efx_test_registers[i].mask; - EFX_INVERT_OWORD(imask); - - falcon_read(efx, &original, address); - - /* bit sweep on and off */ - for (j = 0; j < 128; j++) { - if (!EFX_EXTRACT_OWORD32(mask, j, j)) - continue; - - /* Test this testable bit can be set in isolation */ - EFX_AND_OWORD(reg, original, mask); - EFX_SET_OWORD32(reg, j, j, 1); - - falcon_write(efx, ®, address); - falcon_read(efx, &buf, address); - - if (efx_masked_compare_oword(®, &buf, &mask)) - goto fail; - - /* Test this testable bit can be cleared in isolation */ - EFX_OR_OWORD(reg, original, mask); - EFX_SET_OWORD32(reg, j, j, 0); - - falcon_write(efx, ®, address); - falcon_read(efx, &buf, address); - - if (efx_masked_compare_oword(®, &buf, &mask)) - goto fail; - } - - falcon_write(efx, &original, address); - } - - return 0; - -fail: - EFX_ERR(efx, "wrote "EFX_OWORD_FMT" read "EFX_OWORD_FMT - " at address 0x%x mask "EFX_OWORD_FMT"\n", EFX_OWORD_VAL(reg), - EFX_OWORD_VAL(buf), address, EFX_OWORD_VAL(mask)); - return -EIO; -} - -/************************************************************************** - * - * Device reset - * - ************************************************************************** - */ - -/* Resets NIC to known state. This routine must be called in process - * context and is allowed to sleep. */ -int falcon_reset_hw(struct efx_nic *efx, enum reset_type method) -{ - struct falcon_nic_data *nic_data = efx->nic_data; - efx_oword_t glb_ctl_reg_ker; - int rc; - - EFX_LOG(efx, "performing hardware reset (%d)\n", method); - - /* Initiate device reset */ - if (method == RESET_TYPE_WORLD) { - rc = pci_save_state(efx->pci_dev); - if (rc) { - EFX_ERR(efx, "failed to backup PCI state of primary " - "function prior to hardware reset\n"); - goto fail1; - } - if (FALCON_IS_DUAL_FUNC(efx)) { - rc = pci_save_state(nic_data->pci_dev2); - if (rc) { - EFX_ERR(efx, "failed to backup PCI state of " - "secondary function prior to " - "hardware reset\n"); - goto fail2; - } - } - - EFX_POPULATE_OWORD_2(glb_ctl_reg_ker, - EXT_PHY_RST_DUR, 0x7, - SWRST, 1); - } else { - int reset_phy = (method == RESET_TYPE_INVISIBLE ? - EXCLUDE_FROM_RESET : 0); - - EFX_POPULATE_OWORD_7(glb_ctl_reg_ker, - EXT_PHY_RST_CTL, reset_phy, - PCIE_CORE_RST_CTL, EXCLUDE_FROM_RESET, - PCIE_NSTCK_RST_CTL, EXCLUDE_FROM_RESET, - PCIE_SD_RST_CTL, EXCLUDE_FROM_RESET, - EE_RST_CTL, EXCLUDE_FROM_RESET, - EXT_PHY_RST_DUR, 0x7 /* 10ms */, - SWRST, 1); - } - falcon_write(efx, &glb_ctl_reg_ker, GLB_CTL_REG_KER); - - EFX_LOG(efx, "waiting for hardware reset\n"); - schedule_timeout_uninterruptible(HZ / 20); - - /* Restore PCI configuration if needed */ - if (method == RESET_TYPE_WORLD) { - if (FALCON_IS_DUAL_FUNC(efx)) { - rc = pci_restore_state(nic_data->pci_dev2); - if (rc) { - EFX_ERR(efx, "failed to restore PCI config for " - "the secondary function\n"); - goto fail3; - } - } - rc = pci_restore_state(efx->pci_dev); - if (rc) { - EFX_ERR(efx, "failed to restore PCI config for the " - "primary function\n"); - goto fail4; - } - EFX_LOG(efx, "successfully restored PCI config\n"); - } - - /* Assert that reset complete */ - falcon_read(efx, &glb_ctl_reg_ker, GLB_CTL_REG_KER); - if (EFX_OWORD_FIELD(glb_ctl_reg_ker, SWRST) != 0) { - rc = -ETIMEDOUT; - EFX_ERR(efx, "timed out waiting for hardware reset\n"); - goto fail5; - } - EFX_LOG(efx, "hardware reset complete\n"); - - return 0; - - /* pci_save_state() and pci_restore_state() MUST be called in pairs */ -fail2: -fail3: - pci_restore_state(efx->pci_dev); -fail1: -fail4: -fail5: - return rc; -} - -/* Zeroes out the SRAM contents. This routine must be called in - * process context and is allowed to sleep. - */ -static int falcon_reset_sram(struct efx_nic *efx) -{ - efx_oword_t srm_cfg_reg_ker, gpio_cfg_reg_ker; - int count; - - /* Set the SRAM wake/sleep GPIO appropriately. */ - falcon_read(efx, &gpio_cfg_reg_ker, GPIO_CTL_REG_KER); - EFX_SET_OWORD_FIELD(gpio_cfg_reg_ker, GPIO1_OEN, 1); - EFX_SET_OWORD_FIELD(gpio_cfg_reg_ker, GPIO1_OUT, 1); - falcon_write(efx, &gpio_cfg_reg_ker, GPIO_CTL_REG_KER); - - /* Initiate SRAM reset */ - EFX_POPULATE_OWORD_2(srm_cfg_reg_ker, - SRAM_OOB_BT_INIT_EN, 1, - SRM_NUM_BANKS_AND_BANK_SIZE, 0); - falcon_write(efx, &srm_cfg_reg_ker, SRM_CFG_REG_KER); - - /* Wait for SRAM reset to complete */ - count = 0; - do { - EFX_LOG(efx, "waiting for SRAM reset (attempt %d)...\n", count); - - /* SRAM reset is slow; expect around 16ms */ - schedule_timeout_uninterruptible(HZ / 50); - - /* Check for reset complete */ - falcon_read(efx, &srm_cfg_reg_ker, SRM_CFG_REG_KER); - if (!EFX_OWORD_FIELD(srm_cfg_reg_ker, SRAM_OOB_BT_INIT_EN)) { - EFX_LOG(efx, "SRAM reset complete\n"); - - return 0; - } - } while (++count < 20); /* wait upto 0.4 sec */ - - EFX_ERR(efx, "timed out waiting for SRAM reset\n"); - return -ETIMEDOUT; -} - -static int falcon_spi_device_init(struct efx_nic *efx, - struct efx_spi_device **spi_device_ret, - unsigned int device_id, u32 device_type) -{ - struct efx_spi_device *spi_device; - - if (device_type != 0) { - spi_device = kzalloc(sizeof(*spi_device), GFP_KERNEL); - if (!spi_device) - return -ENOMEM; - spi_device->device_id = device_id; - spi_device->size = - 1 << SPI_DEV_TYPE_FIELD(device_type, SPI_DEV_TYPE_SIZE); - spi_device->addr_len = - SPI_DEV_TYPE_FIELD(device_type, SPI_DEV_TYPE_ADDR_LEN); - spi_device->munge_address = (spi_device->size == 1 << 9 && - spi_device->addr_len == 1); - spi_device->erase_command = - SPI_DEV_TYPE_FIELD(device_type, SPI_DEV_TYPE_ERASE_CMD); - spi_device->erase_size = - 1 << SPI_DEV_TYPE_FIELD(device_type, - SPI_DEV_TYPE_ERASE_SIZE); - spi_device->block_size = - 1 << SPI_DEV_TYPE_FIELD(device_type, - SPI_DEV_TYPE_BLOCK_SIZE); - - spi_device->efx = efx; - } else { - spi_device = NULL; - } - - kfree(*spi_device_ret); - *spi_device_ret = spi_device; - return 0; -} - - -static void falcon_remove_spi_devices(struct efx_nic *efx) -{ - kfree(efx->spi_eeprom); - efx->spi_eeprom = NULL; - kfree(efx->spi_flash); - efx->spi_flash = NULL; -} - -/* Extract non-volatile configuration */ -static int falcon_probe_nvconfig(struct efx_nic *efx) -{ - struct falcon_nvconfig *nvconfig; - int board_rev; - int rc; - - nvconfig = kmalloc(sizeof(*nvconfig), GFP_KERNEL); - if (!nvconfig) - return -ENOMEM; - - rc = falcon_read_nvram(efx, nvconfig); - if (rc == -EINVAL) { - EFX_ERR(efx, "NVRAM is invalid therefore using defaults\n"); - efx->phy_type = PHY_TYPE_NONE; - efx->mii.phy_id = PHY_ADDR_INVALID; - board_rev = 0; - rc = 0; - } else if (rc) { - goto fail1; - } else { - struct falcon_nvconfig_board_v2 *v2 = &nvconfig->board_v2; - struct falcon_nvconfig_board_v3 *v3 = &nvconfig->board_v3; - - efx->phy_type = v2->port0_phy_type; - efx->mii.phy_id = v2->port0_phy_addr; - board_rev = le16_to_cpu(v2->board_revision); - - if (le16_to_cpu(nvconfig->board_struct_ver) >= 3) { - __le32 fl = v3->spi_device_type[EE_SPI_FLASH]; - __le32 ee = v3->spi_device_type[EE_SPI_EEPROM]; - rc = falcon_spi_device_init(efx, &efx->spi_flash, - EE_SPI_FLASH, - le32_to_cpu(fl)); - if (rc) - goto fail2; - rc = falcon_spi_device_init(efx, &efx->spi_eeprom, - EE_SPI_EEPROM, - le32_to_cpu(ee)); - if (rc) - goto fail2; - } - } - - /* Read the MAC addresses */ - memcpy(efx->mac_address, nvconfig->mac_address[0], ETH_ALEN); - - EFX_LOG(efx, "PHY is %d phy_id %d\n", efx->phy_type, efx->mii.phy_id); - - efx_set_board_info(efx, board_rev); - - kfree(nvconfig); - return 0; - - fail2: - falcon_remove_spi_devices(efx); - fail1: - kfree(nvconfig); - return rc; -} - -/* Probe the NIC variant (revision, ASIC vs FPGA, function count, port - * count, port speed). Set workaround and feature flags accordingly. - */ -static int falcon_probe_nic_variant(struct efx_nic *efx) -{ - efx_oword_t altera_build; - efx_oword_t nic_stat; - - falcon_read(efx, &altera_build, ALTERA_BUILD_REG_KER); - if (EFX_OWORD_FIELD(altera_build, VER_ALL)) { - EFX_ERR(efx, "Falcon FPGA not supported\n"); - return -ENODEV; - } - - falcon_read(efx, &nic_stat, NIC_STAT_REG); - - switch (falcon_rev(efx)) { - case FALCON_REV_A0: - case 0xff: - EFX_ERR(efx, "Falcon rev A0 not supported\n"); - return -ENODEV; - - case FALCON_REV_A1: - if (EFX_OWORD_FIELD(nic_stat, STRAP_PCIE) == 0) { - EFX_ERR(efx, "Falcon rev A1 PCI-X not supported\n"); - return -ENODEV; - } - break; - - case FALCON_REV_B0: - break; - - default: - EFX_ERR(efx, "Unknown Falcon rev %d\n", falcon_rev(efx)); - return -ENODEV; - } - - /* Initial assumed speed */ - efx->link_speed = EFX_OWORD_FIELD(nic_stat, STRAP_10G) ? 10000 : 1000; - - return 0; -} - -/* Probe all SPI devices on the NIC */ -static void falcon_probe_spi_devices(struct efx_nic *efx) -{ - efx_oword_t nic_stat, gpio_ctl, ee_vpd_cfg; - int boot_dev; - - falcon_read(efx, &gpio_ctl, GPIO_CTL_REG_KER); - falcon_read(efx, &nic_stat, NIC_STAT_REG); - falcon_read(efx, &ee_vpd_cfg, EE_VPD_CFG_REG_KER); - - if (EFX_OWORD_FIELD(gpio_ctl, BOOTED_USING_NVDEVICE)) { - boot_dev = (EFX_OWORD_FIELD(nic_stat, SF_PRST) ? - EE_SPI_FLASH : EE_SPI_EEPROM); - EFX_LOG(efx, "Booted from %s\n", - boot_dev == EE_SPI_FLASH ? "flash" : "EEPROM"); - } else { - /* Disable VPD and set clock dividers to safe - * values for initial programming. */ - boot_dev = -1; - EFX_LOG(efx, "Booted from internal ASIC settings;" - " setting SPI config\n"); - EFX_POPULATE_OWORD_3(ee_vpd_cfg, EE_VPD_EN, 0, - /* 125 MHz / 7 ~= 20 MHz */ - EE_SF_CLOCK_DIV, 7, - /* 125 MHz / 63 ~= 2 MHz */ - EE_EE_CLOCK_DIV, 63); - falcon_write(efx, &ee_vpd_cfg, EE_VPD_CFG_REG_KER); - } - - if (boot_dev == EE_SPI_FLASH) - falcon_spi_device_init(efx, &efx->spi_flash, EE_SPI_FLASH, - default_flash_type); - if (boot_dev == EE_SPI_EEPROM) - falcon_spi_device_init(efx, &efx->spi_eeprom, EE_SPI_EEPROM, - large_eeprom_type); -} - -int falcon_probe_nic(struct efx_nic *efx) -{ - struct falcon_nic_data *nic_data; - int rc; - - /* Allocate storage for hardware specific data */ - nic_data = kzalloc(sizeof(*nic_data), GFP_KERNEL); - if (!nic_data) - return -ENOMEM; - efx->nic_data = nic_data; - - /* Determine number of ports etc. */ - rc = falcon_probe_nic_variant(efx); - if (rc) - goto fail1; - - /* Probe secondary function if expected */ - if (FALCON_IS_DUAL_FUNC(efx)) { - struct pci_dev *dev = pci_dev_get(efx->pci_dev); - - while ((dev = pci_get_device(EFX_VENDID_SFC, FALCON_A_S_DEVID, - dev))) { - if (dev->bus == efx->pci_dev->bus && - dev->devfn == efx->pci_dev->devfn + 1) { - nic_data->pci_dev2 = dev; - break; - } - } - if (!nic_data->pci_dev2) { - EFX_ERR(efx, "failed to find secondary function\n"); - rc = -ENODEV; - goto fail2; - } - } - - /* Now we can reset the NIC */ - rc = falcon_reset_hw(efx, RESET_TYPE_ALL); - if (rc) { - EFX_ERR(efx, "failed to reset NIC\n"); - goto fail3; - } - - /* Allocate memory for INT_KER */ - rc = falcon_alloc_buffer(efx, &efx->irq_status, sizeof(efx_oword_t)); - if (rc) - goto fail4; - BUG_ON(efx->irq_status.dma_addr & 0x0f); - - EFX_LOG(efx, "INT_KER at %llx (virt %p phys %lx)\n", - (unsigned long long)efx->irq_status.dma_addr, - efx->irq_status.addr, virt_to_phys(efx->irq_status.addr)); - - falcon_probe_spi_devices(efx); - - /* Read in the non-volatile configuration */ - rc = falcon_probe_nvconfig(efx); - if (rc) - goto fail5; - - /* Initialise I2C adapter */ - efx->i2c_adap.owner = THIS_MODULE; - nic_data->i2c_data = falcon_i2c_bit_operations; - nic_data->i2c_data.data = efx; - efx->i2c_adap.algo_data = &nic_data->i2c_data; - efx->i2c_adap.dev.parent = &efx->pci_dev->dev; - strlcpy(efx->i2c_adap.name, "SFC4000 GPIO", sizeof(efx->i2c_adap.name)); - rc = i2c_bit_add_bus(&efx->i2c_adap); - if (rc) - goto fail5; - - return 0; - - fail5: - falcon_remove_spi_devices(efx); - falcon_free_buffer(efx, &efx->irq_status); - fail4: - fail3: - if (nic_data->pci_dev2) { - pci_dev_put(nic_data->pci_dev2); - nic_data->pci_dev2 = NULL; - } - fail2: - fail1: - kfree(efx->nic_data); - return rc; -} - -/* This call performs hardware-specific global initialisation, such as - * defining the descriptor cache sizes and number of RSS channels. - * It does not set up any buffers, descriptor rings or event queues. - */ -int falcon_init_nic(struct efx_nic *efx) -{ - efx_oword_t temp; - unsigned thresh; - int rc; - - /* Use on-chip SRAM */ - falcon_read(efx, &temp, NIC_STAT_REG); - EFX_SET_OWORD_FIELD(temp, ONCHIP_SRAM, 1); - falcon_write(efx, &temp, NIC_STAT_REG); - - /* Set the source of the GMAC clock */ - if (falcon_rev(efx) == FALCON_REV_B0) { - falcon_read(efx, &temp, GPIO_CTL_REG_KER); - EFX_SET_OWORD_FIELD(temp, GPIO_USE_NIC_CLK, true); - falcon_write(efx, &temp, GPIO_CTL_REG_KER); - } - - /* Set buffer table mode */ - EFX_POPULATE_OWORD_1(temp, BUF_TBL_MODE, BUF_TBL_MODE_FULL); - falcon_write(efx, &temp, BUF_TBL_CFG_REG_KER); - - rc = falcon_reset_sram(efx); - if (rc) - return rc; - - /* Set positions of descriptor caches in SRAM. */ - EFX_POPULATE_OWORD_1(temp, SRM_TX_DC_BASE_ADR, TX_DC_BASE / 8); - falcon_write(efx, &temp, SRM_TX_DC_CFG_REG_KER); - EFX_POPULATE_OWORD_1(temp, SRM_RX_DC_BASE_ADR, RX_DC_BASE / 8); - falcon_write(efx, &temp, SRM_RX_DC_CFG_REG_KER); - - /* Set TX descriptor cache size. */ - BUILD_BUG_ON(TX_DC_ENTRIES != (16 << TX_DC_ENTRIES_ORDER)); - EFX_POPULATE_OWORD_1(temp, TX_DC_SIZE, TX_DC_ENTRIES_ORDER); - falcon_write(efx, &temp, TX_DC_CFG_REG_KER); - - /* Set RX descriptor cache size. Set low watermark to size-8, as - * this allows most efficient prefetching. - */ - BUILD_BUG_ON(RX_DC_ENTRIES != (16 << RX_DC_ENTRIES_ORDER)); - EFX_POPULATE_OWORD_1(temp, RX_DC_SIZE, RX_DC_ENTRIES_ORDER); - falcon_write(efx, &temp, RX_DC_CFG_REG_KER); - EFX_POPULATE_OWORD_1(temp, RX_DC_PF_LWM, RX_DC_ENTRIES - 8); - falcon_write(efx, &temp, RX_DC_PF_WM_REG_KER); - - /* Clear the parity enables on the TX data fifos as - * they produce false parity errors because of timing issues - */ - if (EFX_WORKAROUND_5129(efx)) { - falcon_read(efx, &temp, SPARE_REG_KER); - EFX_SET_OWORD_FIELD(temp, MEM_PERR_EN_TX_DATA, 0); - falcon_write(efx, &temp, SPARE_REG_KER); - } - - /* Enable all the genuinely fatal interrupts. (They are still - * masked by the overall interrupt mask, controlled by - * falcon_interrupts()). - * - * Note: All other fatal interrupts are enabled - */ - EFX_POPULATE_OWORD_3(temp, - ILL_ADR_INT_KER_EN, 1, - RBUF_OWN_INT_KER_EN, 1, - TBUF_OWN_INT_KER_EN, 1); - EFX_INVERT_OWORD(temp); - falcon_write(efx, &temp, FATAL_INTR_REG_KER); - - if (EFX_WORKAROUND_7244(efx)) { - falcon_read(efx, &temp, RX_FILTER_CTL_REG); - EFX_SET_OWORD_FIELD(temp, UDP_FULL_SRCH_LIMIT, 8); - EFX_SET_OWORD_FIELD(temp, UDP_WILD_SRCH_LIMIT, 8); - EFX_SET_OWORD_FIELD(temp, TCP_FULL_SRCH_LIMIT, 8); - EFX_SET_OWORD_FIELD(temp, TCP_WILD_SRCH_LIMIT, 8); - falcon_write(efx, &temp, RX_FILTER_CTL_REG); - } - - falcon_setup_rss_indir_table(efx); - - /* Setup RX. Wait for descriptor is broken and must - * be disabled. RXDP recovery shouldn't be needed, but is. - */ - falcon_read(efx, &temp, RX_SELF_RST_REG_KER); - EFX_SET_OWORD_FIELD(temp, RX_NODESC_WAIT_DIS, 1); - EFX_SET_OWORD_FIELD(temp, RX_RECOVERY_EN, 1); - if (EFX_WORKAROUND_5583(efx)) - EFX_SET_OWORD_FIELD(temp, RX_ISCSI_DIS, 1); - falcon_write(efx, &temp, RX_SELF_RST_REG_KER); - - /* Disable the ugly timer-based TX DMA backoff and allow TX DMA to be - * controlled by the RX FIFO fill level. Set arbitration to one pkt/Q. - */ - falcon_read(efx, &temp, TX_CFG2_REG_KER); - EFX_SET_OWORD_FIELD(temp, TX_RX_SPACER, 0xfe); - EFX_SET_OWORD_FIELD(temp, TX_RX_SPACER_EN, 1); - EFX_SET_OWORD_FIELD(temp, TX_ONE_PKT_PER_Q, 1); - EFX_SET_OWORD_FIELD(temp, TX_CSR_PUSH_EN, 0); - EFX_SET_OWORD_FIELD(temp, TX_DIS_NON_IP_EV, 1); - /* Enable SW_EV to inherit in char driver - assume harmless here */ - EFX_SET_OWORD_FIELD(temp, TX_SW_EV_EN, 1); - /* Prefetch threshold 2 => fetch when descriptor cache half empty */ - EFX_SET_OWORD_FIELD(temp, TX_PREF_THRESHOLD, 2); - /* Squash TX of packets of 16 bytes or less */ - if (falcon_rev(efx) >= FALCON_REV_B0 && EFX_WORKAROUND_9141(efx)) - EFX_SET_OWORD_FIELD(temp, TX_FLUSH_MIN_LEN_EN_B0, 1); - falcon_write(efx, &temp, TX_CFG2_REG_KER); - - /* Do not enable TX_NO_EOP_DISC_EN, since it limits packets to 16 - * descriptors (which is bad). - */ - falcon_read(efx, &temp, TX_CFG_REG_KER); - EFX_SET_OWORD_FIELD(temp, TX_NO_EOP_DISC_EN, 0); - falcon_write(efx, &temp, TX_CFG_REG_KER); - - /* RX config */ - falcon_read(efx, &temp, RX_CFG_REG_KER); - EFX_SET_OWORD_FIELD_VER(efx, temp, RX_DESC_PUSH_EN, 0); - if (EFX_WORKAROUND_7575(efx)) - EFX_SET_OWORD_FIELD_VER(efx, temp, RX_USR_BUF_SIZE, - (3 * 4096) / 32); - if (falcon_rev(efx) >= FALCON_REV_B0) - EFX_SET_OWORD_FIELD(temp, RX_INGR_EN_B0, 1); - - /* RX FIFO flow control thresholds */ - thresh = ((rx_xon_thresh_bytes >= 0) ? - rx_xon_thresh_bytes : efx->type->rx_xon_thresh); - EFX_SET_OWORD_FIELD_VER(efx, temp, RX_XON_MAC_TH, thresh / 256); - thresh = ((rx_xoff_thresh_bytes >= 0) ? - rx_xoff_thresh_bytes : efx->type->rx_xoff_thresh); - EFX_SET_OWORD_FIELD_VER(efx, temp, RX_XOFF_MAC_TH, thresh / 256); - /* RX control FIFO thresholds [32 entries] */ - EFX_SET_OWORD_FIELD_VER(efx, temp, RX_XON_TX_TH, 20); - EFX_SET_OWORD_FIELD_VER(efx, temp, RX_XOFF_TX_TH, 25); - falcon_write(efx, &temp, RX_CFG_REG_KER); - - /* Set destination of both TX and RX Flush events */ - if (falcon_rev(efx) >= FALCON_REV_B0) { - EFX_POPULATE_OWORD_1(temp, FLS_EVQ_ID, 0); - falcon_write(efx, &temp, DP_CTRL_REG); - } - - return 0; -} - -void falcon_remove_nic(struct efx_nic *efx) -{ - struct falcon_nic_data *nic_data = efx->nic_data; - int rc; - - rc = i2c_del_adapter(&efx->i2c_adap); - BUG_ON(rc); - - falcon_remove_spi_devices(efx); - falcon_free_buffer(efx, &efx->irq_status); - - falcon_reset_hw(efx, RESET_TYPE_ALL); - - /* Release the second function after the reset */ - if (nic_data->pci_dev2) { - pci_dev_put(nic_data->pci_dev2); - nic_data->pci_dev2 = NULL; - } - - /* Tear down the private nic state */ - kfree(efx->nic_data); - efx->nic_data = NULL; -} - -void falcon_update_nic_stats(struct efx_nic *efx) -{ - efx_oword_t cnt; - - falcon_read(efx, &cnt, RX_NODESC_DROP_REG_KER); - efx->n_rx_nodesc_drop_cnt += EFX_OWORD_FIELD(cnt, RX_NODESC_DROP_CNT); -} - -/************************************************************************** - * - * Revision-dependent attributes used by efx.c - * - ************************************************************************** - */ - -struct efx_nic_type falcon_a_nic_type = { - .mem_bar = 2, - .mem_map_size = 0x20000, - .txd_ptr_tbl_base = TX_DESC_PTR_TBL_KER_A1, - .rxd_ptr_tbl_base = RX_DESC_PTR_TBL_KER_A1, - .buf_tbl_base = BUF_TBL_KER_A1, - .evq_ptr_tbl_base = EVQ_PTR_TBL_KER_A1, - .evq_rptr_tbl_base = EVQ_RPTR_REG_KER_A1, - .txd_ring_mask = FALCON_TXD_RING_MASK, - .rxd_ring_mask = FALCON_RXD_RING_MASK, - .evq_size = FALCON_EVQ_SIZE, - .max_dma_mask = FALCON_DMA_MASK, - .tx_dma_mask = FALCON_TX_DMA_MASK, - .bug5391_mask = 0xf, - .rx_xoff_thresh = 2048, - .rx_xon_thresh = 512, - .rx_buffer_padding = 0x24, - .max_interrupt_mode = EFX_INT_MODE_MSI, - .phys_addr_channels = 4, -}; - -struct efx_nic_type falcon_b_nic_type = { - .mem_bar = 2, - /* Map everything up to and including the RSS indirection - * table. Don't map MSI-X table, MSI-X PBA since Linux - * requires that they not be mapped. */ - .mem_map_size = RX_RSS_INDIR_TBL_B0 + 0x800, - .txd_ptr_tbl_base = TX_DESC_PTR_TBL_KER_B0, - .rxd_ptr_tbl_base = RX_DESC_PTR_TBL_KER_B0, - .buf_tbl_base = BUF_TBL_KER_B0, - .evq_ptr_tbl_base = EVQ_PTR_TBL_KER_B0, - .evq_rptr_tbl_base = EVQ_RPTR_REG_KER_B0, - .txd_ring_mask = FALCON_TXD_RING_MASK, - .rxd_ring_mask = FALCON_RXD_RING_MASK, - .evq_size = FALCON_EVQ_SIZE, - .max_dma_mask = FALCON_DMA_MASK, - .tx_dma_mask = FALCON_TX_DMA_MASK, - .bug5391_mask = 0, - .rx_xoff_thresh = 54272, /* ~80Kb - 3*max MTU */ - .rx_xon_thresh = 27648, /* ~3*max MTU */ - .rx_buffer_padding = 0, - .max_interrupt_mode = EFX_INT_MODE_MSIX, - .phys_addr_channels = 32, /* Hardware limit is 64, but the legacy - * interrupt handler only supports 32 - * channels */ -}; - diff --git a/drivers/net/sfc/falcon.h b/drivers/net/sfc/falcon.h deleted file mode 100644 index 7869c3d7438..00000000000 --- a/drivers/net/sfc/falcon.h +++ /dev/null @@ -1,143 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2006-2008 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_FALCON_H -#define EFX_FALCON_H - -#include "net_driver.h" -#include "efx.h" - -/* - * Falcon hardware control - */ - -enum falcon_revision { - FALCON_REV_A0 = 0, - FALCON_REV_A1 = 1, - FALCON_REV_B0 = 2, -}; - -static inline int falcon_rev(struct efx_nic *efx) -{ - return efx->pci_dev->revision; -} - -extern struct efx_nic_type falcon_a_nic_type; -extern struct efx_nic_type falcon_b_nic_type; - -/************************************************************************** - * - * Externs - * - ************************************************************************** - */ - -/* TX data path */ -extern int falcon_probe_tx(struct efx_tx_queue *tx_queue); -extern void falcon_init_tx(struct efx_tx_queue *tx_queue); -extern void falcon_fini_tx(struct efx_tx_queue *tx_queue); -extern void falcon_remove_tx(struct efx_tx_queue *tx_queue); -extern void falcon_push_buffers(struct efx_tx_queue *tx_queue); - -/* RX data path */ -extern int falcon_probe_rx(struct efx_rx_queue *rx_queue); -extern void falcon_init_rx(struct efx_rx_queue *rx_queue); -extern void falcon_fini_rx(struct efx_rx_queue *rx_queue); -extern void falcon_remove_rx(struct efx_rx_queue *rx_queue); -extern void falcon_notify_rx_desc(struct efx_rx_queue *rx_queue); - -/* Event data path */ -extern int falcon_probe_eventq(struct efx_channel *channel); -extern void falcon_init_eventq(struct efx_channel *channel); -extern void falcon_fini_eventq(struct efx_channel *channel); -extern void falcon_remove_eventq(struct efx_channel *channel); -extern int falcon_process_eventq(struct efx_channel *channel, int rx_quota); -extern void falcon_eventq_read_ack(struct efx_channel *channel); - -/* Ports */ -extern int falcon_probe_port(struct efx_nic *efx); -extern void falcon_remove_port(struct efx_nic *efx); - -/* MAC/PHY */ -extern int falcon_switch_mac(struct efx_nic *efx); -extern bool falcon_xaui_link_ok(struct efx_nic *efx); -extern int falcon_dma_stats(struct efx_nic *efx, - unsigned int done_offset); -extern void falcon_drain_tx_fifo(struct efx_nic *efx); -extern void falcon_deconfigure_mac_wrapper(struct efx_nic *efx); -extern void falcon_reconfigure_mac_wrapper(struct efx_nic *efx); - -/* Interrupts and test events */ -extern int falcon_init_interrupt(struct efx_nic *efx); -extern void falcon_enable_interrupts(struct efx_nic *efx); -extern void falcon_generate_test_event(struct efx_channel *channel, - unsigned int magic); -extern void falcon_sim_phy_event(struct efx_nic *efx); -extern void falcon_generate_interrupt(struct efx_nic *efx); -extern void falcon_set_int_moderation(struct efx_channel *channel); -extern void falcon_disable_interrupts(struct efx_nic *efx); -extern void falcon_fini_interrupt(struct efx_nic *efx); - -/* Global Resources */ -extern int falcon_probe_nic(struct efx_nic *efx); -extern int falcon_probe_resources(struct efx_nic *efx); -extern int falcon_init_nic(struct efx_nic *efx); -extern int falcon_flush_queues(struct efx_nic *efx); -extern int falcon_reset_hw(struct efx_nic *efx, enum reset_type method); -extern void falcon_remove_resources(struct efx_nic *efx); -extern void falcon_remove_nic(struct efx_nic *efx); -extern void falcon_update_nic_stats(struct efx_nic *efx); -extern void falcon_set_multicast_hash(struct efx_nic *efx); -extern int falcon_reset_xaui(struct efx_nic *efx); - -/* Tests */ -struct falcon_nvconfig; -extern int falcon_read_nvram(struct efx_nic *efx, - struct falcon_nvconfig *nvconfig); -extern int falcon_test_registers(struct efx_nic *efx); - -/************************************************************************** - * - * Falcon MAC stats - * - ************************************************************************** - */ - -#define FALCON_STAT_OFFSET(falcon_stat) EFX_VAL(falcon_stat, offset) -#define FALCON_STAT_WIDTH(falcon_stat) EFX_VAL(falcon_stat, WIDTH) - -/* Retrieve statistic from statistics block */ -#define FALCON_STAT(efx, falcon_stat, efx_stat) do { \ - if (FALCON_STAT_WIDTH(falcon_stat) == 16) \ - (efx)->mac_stats.efx_stat += le16_to_cpu( \ - *((__force __le16 *) \ - (efx->stats_buffer.addr + \ - FALCON_STAT_OFFSET(falcon_stat)))); \ - else if (FALCON_STAT_WIDTH(falcon_stat) == 32) \ - (efx)->mac_stats.efx_stat += le32_to_cpu( \ - *((__force __le32 *) \ - (efx->stats_buffer.addr + \ - FALCON_STAT_OFFSET(falcon_stat)))); \ - else \ - (efx)->mac_stats.efx_stat += le64_to_cpu( \ - *((__force __le64 *) \ - (efx->stats_buffer.addr + \ - FALCON_STAT_OFFSET(falcon_stat)))); \ - } while (0) - -#define FALCON_MAC_STATS_SIZE 0x100 - -#define MAC_DATA_LBN 0 -#define MAC_DATA_WIDTH 32 - -extern void falcon_generate_event(struct efx_channel *channel, - efx_qword_t *event); - -#endif /* EFX_FALCON_H */ diff --git a/drivers/net/sfc/falcon_gmac.c b/drivers/net/sfc/falcon_gmac.c deleted file mode 100644 index 8865eae20ac..00000000000 --- a/drivers/net/sfc/falcon_gmac.c +++ /dev/null @@ -1,229 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2006-2008 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. - */ - -#include <linux/delay.h> -#include "net_driver.h" -#include "efx.h" -#include "falcon.h" -#include "mac.h" -#include "falcon_hwdefs.h" -#include "falcon_io.h" -#include "gmii.h" - -/************************************************************************** - * - * MAC operations - * - *************************************************************************/ - -static void falcon_reconfigure_gmac(struct efx_nic *efx) -{ - bool loopback, tx_fc, rx_fc, bytemode; - int if_mode; - unsigned int max_frame_len; - efx_oword_t reg; - - /* Configuration register 1 */ - tx_fc = (efx->link_fc & EFX_FC_TX) || !efx->link_fd; - rx_fc = !!(efx->link_fc & EFX_FC_RX); - loopback = (efx->loopback_mode == LOOPBACK_GMAC); - bytemode = (efx->link_speed == 1000); - - EFX_POPULATE_OWORD_5(reg, - GM_LOOP, loopback, - GM_TX_EN, 1, - GM_TX_FC_EN, tx_fc, - GM_RX_EN, 1, - GM_RX_FC_EN, rx_fc); - falcon_write(efx, ®, GM_CFG1_REG); - udelay(10); - - /* Configuration register 2 */ - if_mode = (bytemode) ? 2 : 1; - EFX_POPULATE_OWORD_5(reg, - GM_IF_MODE, if_mode, - GM_PAD_CRC_EN, 1, - GM_LEN_CHK, 1, - GM_FD, efx->link_fd, - GM_PAMBL_LEN, 0x7/*datasheet recommended */); - - falcon_write(efx, ®, GM_CFG2_REG); - udelay(10); - - /* Max frame len register */ - max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu); - EFX_POPULATE_OWORD_1(reg, GM_MAX_FLEN, max_frame_len); - falcon_write(efx, ®, GM_MAX_FLEN_REG); - udelay(10); - - /* FIFO configuration register 0 */ - EFX_POPULATE_OWORD_5(reg, - GMF_FTFENREQ, 1, - GMF_STFENREQ, 1, - GMF_FRFENREQ, 1, - GMF_SRFENREQ, 1, - GMF_WTMENREQ, 1); - falcon_write(efx, ®, GMF_CFG0_REG); - udelay(10); - - /* FIFO configuration register 1 */ - EFX_POPULATE_OWORD_2(reg, - GMF_CFGFRTH, 0x12, - GMF_CFGXOFFRTX, 0xffff); - falcon_write(efx, ®, GMF_CFG1_REG); - udelay(10); - - /* FIFO configuration register 2 */ - EFX_POPULATE_OWORD_2(reg, - GMF_CFGHWM, 0x3f, - GMF_CFGLWM, 0xa); - falcon_write(efx, ®, GMF_CFG2_REG); - udelay(10); - - /* FIFO configuration register 3 */ - EFX_POPULATE_OWORD_2(reg, - GMF_CFGHWMFT, 0x1c, - GMF_CFGFTTH, 0x08); - falcon_write(efx, ®, GMF_CFG3_REG); - udelay(10); - - /* FIFO configuration register 4 */ - EFX_POPULATE_OWORD_1(reg, GMF_HSTFLTRFRM_PAUSE, 1); - falcon_write(efx, ®, GMF_CFG4_REG); - udelay(10); - - /* FIFO configuration register 5 */ - falcon_read(efx, ®, GMF_CFG5_REG); - EFX_SET_OWORD_FIELD(reg, GMF_CFGBYTMODE, bytemode); - EFX_SET_OWORD_FIELD(reg, GMF_CFGHDPLX, !efx->link_fd); - EFX_SET_OWORD_FIELD(reg, GMF_HSTDRPLT64, !efx->link_fd); - EFX_SET_OWORD_FIELD(reg, GMF_HSTFLTRFRMDC_PAUSE, 0); - falcon_write(efx, ®, GMF_CFG5_REG); - udelay(10); - - /* MAC address */ - EFX_POPULATE_OWORD_4(reg, - GM_HWADDR_5, efx->net_dev->dev_addr[5], - GM_HWADDR_4, efx->net_dev->dev_addr[4], - GM_HWADDR_3, efx->net_dev->dev_addr[3], - GM_HWADDR_2, efx->net_dev->dev_addr[2]); - falcon_write(efx, ®, GM_ADR1_REG); - udelay(10); - EFX_POPULATE_OWORD_2(reg, - GM_HWADDR_1, efx->net_dev->dev_addr[1], - GM_HWADDR_0, efx->net_dev->dev_addr[0]); - falcon_write(efx, ®, GM_ADR2_REG); - udelay(10); - - falcon_reconfigure_mac_wrapper(efx); -} - -static void falcon_update_stats_gmac(struct efx_nic *efx) -{ - struct efx_mac_stats *mac_stats = &efx->mac_stats; - unsigned long old_rx_pause, old_tx_pause; - unsigned long new_rx_pause, new_tx_pause; - int rc; - - rc = falcon_dma_stats(efx, GDmaDone_offset); - if (rc) - return; - - /* Pause frames are erroneously counted as errors (SFC bug 3269) */ - old_rx_pause = mac_stats->rx_pause; - old_tx_pause = mac_stats->tx_pause; - - /* Update MAC stats from DMAed values */ - FALCON_STAT(efx, GRxGoodOct, rx_good_bytes); - FALCON_STAT(efx, GRxBadOct, rx_bad_bytes); - FALCON_STAT(efx, GRxMissPkt, rx_missed); - FALCON_STAT(efx, GRxFalseCRS, rx_false_carrier); - FALCON_STAT(efx, GRxPausePkt, rx_pause); - FALCON_STAT(efx, GRxBadPkt, rx_bad); - FALCON_STAT(efx, GRxUcastPkt, rx_unicast); - FALCON_STAT(efx, GRxMcastPkt, rx_multicast); - FALCON_STAT(efx, GRxBcastPkt, rx_broadcast); - FALCON_STAT(efx, GRxGoodLt64Pkt, rx_good_lt64); - FALCON_STAT(efx, GRxBadLt64Pkt, rx_bad_lt64); - FALCON_STAT(efx, GRx64Pkt, rx_64); - FALCON_STAT(efx, GRx65to127Pkt, rx_65_to_127); - FALCON_STAT(efx, GRx128to255Pkt, rx_128_to_255); - FALCON_STAT(efx, GRx256to511Pkt, rx_256_to_511); - FALCON_STAT(efx, GRx512to1023Pkt, rx_512_to_1023); - FALCON_STAT(efx, GRx1024to15xxPkt, rx_1024_to_15xx); - FALCON_STAT(efx, GRx15xxtoJumboPkt, rx_15xx_to_jumbo); - FALCON_STAT(efx, GRxGtJumboPkt, rx_gtjumbo); - FALCON_STAT(efx, GRxFcsErr64to15xxPkt, rx_bad_64_to_15xx); - FALCON_STAT(efx, GRxFcsErr15xxtoJumboPkt, rx_bad_15xx_to_jumbo); - FALCON_STAT(efx, GRxFcsErrGtJumboPkt, rx_bad_gtjumbo); - FALCON_STAT(efx, GTxGoodBadOct, tx_bytes); - FALCON_STAT(efx, GTxGoodOct, tx_good_bytes); - FALCON_STAT(efx, GTxSglColPkt, tx_single_collision); - FALCON_STAT(efx, GTxMultColPkt, tx_multiple_collision); - FALCON_STAT(efx, GTxExColPkt, tx_excessive_collision); - FALCON_STAT(efx, GTxDefPkt, tx_deferred); - FALCON_STAT(efx, GTxLateCol, tx_late_collision); - FALCON_STAT(efx, GTxExDefPkt, tx_excessive_deferred); - FALCON_STAT(efx, GTxPausePkt, tx_pause); - FALCON_STAT(efx, GTxBadPkt, tx_bad); - FALCON_STAT(efx, GTxUcastPkt, tx_unicast); - FALCON_STAT(efx, GTxMcastPkt, tx_multicast); - FALCON_STAT(efx, GTxBcastPkt, tx_broadcast); - FALCON_STAT(efx, GTxLt64Pkt, tx_lt64); - FALCON_STAT(efx, GTx64Pkt, tx_64); - FALCON_STAT(efx, GTx65to127Pkt, tx_65_to_127); - FALCON_STAT(efx, GTx128to255Pkt, tx_128_to_255); - FALCON_STAT(efx, GTx256to511Pkt, tx_256_to_511); - FALCON_STAT(efx, GTx512to1023Pkt, tx_512_to_1023); - FALCON_STAT(efx, GTx1024to15xxPkt, tx_1024_to_15xx); - FALCON_STAT(efx, GTx15xxtoJumboPkt, tx_15xx_to_jumbo); - FALCON_STAT(efx, GTxGtJumboPkt, tx_gtjumbo); - FALCON_STAT(efx, GTxNonTcpUdpPkt, tx_non_tcpudp); - FALCON_STAT(efx, GTxMacSrcErrPkt, tx_mac_src_error); - FALCON_STAT(efx, GTxIpSrcErrPkt, tx_ip_src_error); - - /* Pause frames are erroneously counted as errors (SFC bug 3269) */ - new_rx_pause = mac_stats->rx_pause; - new_tx_pause = mac_stats->tx_pause; - mac_stats->rx_bad -= (new_rx_pause - old_rx_pause); - mac_stats->tx_bad -= (new_tx_pause - old_tx_pause); - - /* Derive stats that the MAC doesn't provide directly */ - mac_stats->tx_bad_bytes = - mac_stats->tx_bytes - mac_stats->tx_good_bytes; - mac_stats->tx_packets = - mac_stats->tx_lt64 + mac_stats->tx_64 + - mac_stats->tx_65_to_127 + mac_stats->tx_128_to_255 + - mac_stats->tx_256_to_511 + mac_stats->tx_512_to_1023 + - mac_stats->tx_1024_to_15xx + mac_stats->tx_15xx_to_jumbo + - mac_stats->tx_gtjumbo; - mac_stats->tx_collision = - mac_stats->tx_single_collision + - mac_stats->tx_multiple_collision + - mac_stats->tx_excessive_collision + - mac_stats->tx_late_collision; - mac_stats->rx_bytes = - mac_stats->rx_good_bytes + mac_stats->rx_bad_bytes; - mac_stats->rx_packets = - mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64 + - mac_stats->rx_64 + mac_stats->rx_65_to_127 + - mac_stats->rx_128_to_255 + mac_stats->rx_256_to_511 + - mac_stats->rx_512_to_1023 + mac_stats->rx_1024_to_15xx + - mac_stats->rx_15xx_to_jumbo + mac_stats->rx_gtjumbo; - mac_stats->rx_good = mac_stats->rx_packets - mac_stats->rx_bad; - mac_stats->rx_lt64 = mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64; -} - -struct efx_mac_operations falcon_gmac_operations = { - .reconfigure = falcon_reconfigure_gmac, - .update_stats = falcon_update_stats_gmac, - .irq = efx_port_dummy_op_void, - .poll = efx_port_dummy_op_void, -}; diff --git a/drivers/net/sfc/falcon_hwdefs.h b/drivers/net/sfc/falcon_hwdefs.h deleted file mode 100644 index bda8d5bb72e..00000000000 --- a/drivers/net/sfc/falcon_hwdefs.h +++ /dev/null @@ -1,1334 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2006-2008 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_FALCON_HWDEFS_H -#define EFX_FALCON_HWDEFS_H - -/* - * Falcon hardware value definitions. - * Falcon is the internal codename for the SFC4000 controller that is - * present in SFE400X evaluation boards - */ - -/************************************************************************** - * - * Falcon registers - * - ************************************************************************** - */ - -/* Address region register */ -#define ADR_REGION_REG_KER 0x00 -#define ADR_REGION0_LBN 0 -#define ADR_REGION0_WIDTH 18 -#define ADR_REGION1_LBN 32 -#define ADR_REGION1_WIDTH 18 -#define ADR_REGION2_LBN 64 -#define ADR_REGION2_WIDTH 18 -#define ADR_REGION3_LBN 96 -#define ADR_REGION3_WIDTH 18 - -/* Interrupt enable register */ -#define INT_EN_REG_KER 0x0010 -#define KER_INT_KER_LBN 3 -#define KER_INT_KER_WIDTH 1 -#define DRV_INT_EN_KER_LBN 0 -#define DRV_INT_EN_KER_WIDTH 1 - -/* Interrupt status address register */ -#define INT_ADR_REG_KER 0x0030 -#define NORM_INT_VEC_DIS_KER_LBN 64 -#define NORM_INT_VEC_DIS_KER_WIDTH 1 -#define INT_ADR_KER_LBN 0 -#define INT_ADR_KER_WIDTH EFX_DMA_TYPE_WIDTH(64) /* not 46 for this one */ - -/* Interrupt status register (B0 only) */ -#define INT_ISR0_B0 0x90 -#define INT_ISR1_B0 0xA0 - -/* Interrupt acknowledge register (A0/A1 only) */ -#define INT_ACK_REG_KER_A1 0x0050 -#define INT_ACK_DUMMY_DATA_LBN 0 -#define INT_ACK_DUMMY_DATA_WIDTH 32 - -/* Interrupt acknowledge work-around register (A0/A1 only )*/ -#define WORK_AROUND_BROKEN_PCI_READS_REG_KER_A1 0x0070 - -/* SPI host command register */ -#define EE_SPI_HCMD_REG_KER 0x0100 -#define EE_SPI_HCMD_CMD_EN_LBN 31 -#define EE_SPI_HCMD_CMD_EN_WIDTH 1 -#define EE_WR_TIMER_ACTIVE_LBN 28 -#define EE_WR_TIMER_ACTIVE_WIDTH 1 -#define EE_SPI_HCMD_SF_SEL_LBN 24 -#define EE_SPI_HCMD_SF_SEL_WIDTH 1 -#define EE_SPI_EEPROM 0 -#define EE_SPI_FLASH 1 -#define EE_SPI_HCMD_DABCNT_LBN 16 -#define EE_SPI_HCMD_DABCNT_WIDTH 5 -#define EE_SPI_HCMD_READ_LBN 15 -#define EE_SPI_HCMD_READ_WIDTH 1 -#define EE_SPI_READ 1 -#define EE_SPI_WRITE 0 -#define EE_SPI_HCMD_DUBCNT_LBN 12 -#define EE_SPI_HCMD_DUBCNT_WIDTH 2 -#define EE_SPI_HCMD_ADBCNT_LBN 8 -#define EE_SPI_HCMD_ADBCNT_WIDTH 2 -#define EE_SPI_HCMD_ENC_LBN 0 -#define EE_SPI_HCMD_ENC_WIDTH 8 - -/* SPI host address register */ -#define EE_SPI_HADR_REG_KER 0x0110 -#define EE_SPI_HADR_ADR_LBN 0 -#define EE_SPI_HADR_ADR_WIDTH 24 - -/* SPI host data register */ -#define EE_SPI_HDATA_REG_KER 0x0120 - -/* SPI/VPD config register */ -#define EE_VPD_CFG_REG_KER 0x0140 -#define EE_VPD_EN_LBN 0 -#define EE_VPD_EN_WIDTH 1 -#define EE_VPD_EN_AD9_MODE_LBN 1 -#define EE_VPD_EN_AD9_MODE_WIDTH 1 -#define EE_EE_CLOCK_DIV_LBN 112 -#define EE_EE_CLOCK_DIV_WIDTH 7 -#define EE_SF_CLOCK_DIV_LBN 120 -#define EE_SF_CLOCK_DIV_WIDTH 7 - -/* PCIE CORE ACCESS REG */ -#define PCIE_CORE_ADDR_PCIE_DEVICE_CTRL_STAT 0x68 -#define PCIE_CORE_ADDR_PCIE_LINK_CTRL_STAT 0x70 -#define PCIE_CORE_ADDR_ACK_RPL_TIMER 0x700 -#define PCIE_CORE_ADDR_ACK_FREQ 0x70C - -/* NIC status register */ -#define NIC_STAT_REG 0x0200 -#define EE_STRAP_EN_LBN 31 -#define EE_STRAP_EN_WIDTH 1 -#define EE_STRAP_OVR_LBN 24 -#define EE_STRAP_OVR_WIDTH 4 -#define ONCHIP_SRAM_LBN 16 -#define ONCHIP_SRAM_WIDTH 1 -#define SF_PRST_LBN 9 -#define SF_PRST_WIDTH 1 -#define EE_PRST_LBN 8 -#define EE_PRST_WIDTH 1 -#define STRAP_PINS_LBN 0 -#define STRAP_PINS_WIDTH 3 -/* These bit definitions are extrapolated from the list of numerical - * values for STRAP_PINS. - */ -#define STRAP_10G_LBN 2 -#define STRAP_10G_WIDTH 1 -#define STRAP_PCIE_LBN 0 -#define STRAP_PCIE_WIDTH 1 - -#define BOOTED_USING_NVDEVICE_LBN 3 -#define BOOTED_USING_NVDEVICE_WIDTH 1 - -/* GPIO control register */ -#define GPIO_CTL_REG_KER 0x0210 -#define GPIO_USE_NIC_CLK_LBN (30) -#define GPIO_USE_NIC_CLK_WIDTH (1) -#define GPIO_OUTPUTS_LBN (16) -#define GPIO_OUTPUTS_WIDTH (4) -#define GPIO_INPUTS_LBN (8) -#define GPIO_DIRECTION_LBN (24) -#define GPIO_DIRECTION_WIDTH (4) -#define GPIO_DIRECTION_OUT (1) -#define GPIO_SRAM_SLEEP (1 << 1) - -#define GPIO3_OEN_LBN (GPIO_DIRECTION_LBN + 3) -#define GPIO3_OEN_WIDTH 1 -#define GPIO2_OEN_LBN (GPIO_DIRECTION_LBN + 2) -#define GPIO2_OEN_WIDTH 1 -#define GPIO1_OEN_LBN (GPIO_DIRECTION_LBN + 1) -#define GPIO1_OEN_WIDTH 1 -#define GPIO0_OEN_LBN (GPIO_DIRECTION_LBN + 0) -#define GPIO0_OEN_WIDTH 1 - -#define GPIO3_OUT_LBN (GPIO_OUTPUTS_LBN + 3) -#define GPIO3_OUT_WIDTH 1 -#define GPIO2_OUT_LBN (GPIO_OUTPUTS_LBN + 2) -#define GPIO2_OUT_WIDTH 1 -#define GPIO1_OUT_LBN (GPIO_OUTPUTS_LBN + 1) -#define GPIO1_OUT_WIDTH 1 -#define GPIO0_OUT_LBN (GPIO_OUTPUTS_LBN + 0) -#define GPIO0_OUT_WIDTH 1 - -#define GPIO3_IN_LBN (GPIO_INPUTS_LBN + 3) -#define GPIO3_IN_WIDTH 1 -#define GPIO2_IN_WIDTH 1 -#define GPIO1_IN_WIDTH 1 -#define GPIO0_IN_LBN (GPIO_INPUTS_LBN + 0) -#define GPIO0_IN_WIDTH 1 - -/* Global control register */ -#define GLB_CTL_REG_KER 0x0220 -#define EXT_PHY_RST_CTL_LBN 63 -#define EXT_PHY_RST_CTL_WIDTH 1 -#define PCIE_SD_RST_CTL_LBN 61 -#define PCIE_SD_RST_CTL_WIDTH 1 - -#define PCIE_NSTCK_RST_CTL_LBN 58 -#define PCIE_NSTCK_RST_CTL_WIDTH 1 -#define PCIE_CORE_RST_CTL_LBN 57 -#define PCIE_CORE_RST_CTL_WIDTH 1 -#define EE_RST_CTL_LBN 49 -#define EE_RST_CTL_WIDTH 1 -#define RST_XGRX_LBN 24 -#define RST_XGRX_WIDTH 1 -#define RST_XGTX_LBN 23 -#define RST_XGTX_WIDTH 1 -#define RST_EM_LBN 22 -#define RST_EM_WIDTH 1 -#define EXT_PHY_RST_DUR_LBN 1 -#define EXT_PHY_RST_DUR_WIDTH 3 -#define SWRST_LBN 0 -#define SWRST_WIDTH 1 -#define INCLUDE_IN_RESET 0 -#define EXCLUDE_FROM_RESET 1 - -/* Fatal interrupt register */ -#define FATAL_INTR_REG_KER 0x0230 -#define RBUF_OWN_INT_KER_EN_LBN 39 -#define RBUF_OWN_INT_KER_EN_WIDTH 1 -#define TBUF_OWN_INT_KER_EN_LBN 38 -#define TBUF_OWN_INT_KER_EN_WIDTH 1 -#define ILL_ADR_INT_KER_EN_LBN 33 -#define ILL_ADR_INT_KER_EN_WIDTH 1 -#define MEM_PERR_INT_KER_LBN 8 -#define MEM_PERR_INT_KER_WIDTH 1 -#define INT_KER_ERROR_LBN 0 -#define INT_KER_ERROR_WIDTH 12 - -#define DP_CTRL_REG 0x250 -#define FLS_EVQ_ID_LBN 0 -#define FLS_EVQ_ID_WIDTH 11 - -#define MEM_STAT_REG_KER 0x260 - -/* Debug probe register */ -#define DEBUG_BLK_SEL_MISC 7 -#define DEBUG_BLK_SEL_SERDES 6 -#define DEBUG_BLK_SEL_EM 5 -#define DEBUG_BLK_SEL_SR 4 -#define DEBUG_BLK_SEL_EV 3 -#define DEBUG_BLK_SEL_RX 2 -#define DEBUG_BLK_SEL_TX 1 -#define DEBUG_BLK_SEL_BIU 0 - -/* FPGA build version */ -#define ALTERA_BUILD_REG_KER 0x0300 -#define VER_ALL_LBN 0 -#define VER_ALL_WIDTH 32 - -/* Spare EEPROM bits register (flash 0x390) */ -#define SPARE_REG_KER 0x310 -#define MEM_PERR_EN_TX_DATA_LBN 72 -#define MEM_PERR_EN_TX_DATA_WIDTH 2 - -/* Timer table for kernel access */ -#define TIMER_CMD_REG_KER 0x420 -#define TIMER_MODE_LBN 12 -#define TIMER_MODE_WIDTH 2 -#define TIMER_MODE_DIS 0 -#define TIMER_MODE_INT_HLDOFF 2 -#define TIMER_VAL_LBN 0 -#define TIMER_VAL_WIDTH 12 - -/* Driver generated event register */ -#define DRV_EV_REG_KER 0x440 -#define DRV_EV_QID_LBN 64 -#define DRV_EV_QID_WIDTH 12 -#define DRV_EV_DATA_LBN 0 -#define DRV_EV_DATA_WIDTH 64 - -/* Buffer table configuration register */ -#define BUF_TBL_CFG_REG_KER 0x600 -#define BUF_TBL_MODE_LBN 3 -#define BUF_TBL_MODE_WIDTH 1 -#define BUF_TBL_MODE_HALF 0 -#define BUF_TBL_MODE_FULL 1 - -/* SRAM receive descriptor cache configuration register */ -#define SRM_RX_DC_CFG_REG_KER 0x610 -#define SRM_RX_DC_BASE_ADR_LBN 0 -#define SRM_RX_DC_BASE_ADR_WIDTH 21 - -/* SRAM transmit descriptor cache configuration register */ -#define SRM_TX_DC_CFG_REG_KER 0x620 -#define SRM_TX_DC_BASE_ADR_LBN 0 -#define SRM_TX_DC_BASE_ADR_WIDTH 21 - -/* SRAM configuration register */ -#define SRM_CFG_REG_KER 0x630 -#define SRAM_OOB_BT_INIT_EN_LBN 3 -#define SRAM_OOB_BT_INIT_EN_WIDTH 1 -#define SRM_NUM_BANKS_AND_BANK_SIZE_LBN 0 -#define SRM_NUM_BANKS_AND_BANK_SIZE_WIDTH 3 -#define SRM_NB_BSZ_1BANKS_2M 0 -#define SRM_NB_BSZ_1BANKS_4M 1 -#define SRM_NB_BSZ_1BANKS_8M 2 -#define SRM_NB_BSZ_DEFAULT 3 /* char driver will set the default */ -#define SRM_NB_BSZ_2BANKS_4M 4 -#define SRM_NB_BSZ_2BANKS_8M 5 -#define SRM_NB_BSZ_2BANKS_16M 6 -#define SRM_NB_BSZ_RESERVED 7 - -/* Special buffer table update register */ -#define BUF_TBL_UPD_REG_KER 0x0650 -#define BUF_UPD_CMD_LBN 63 -#define BUF_UPD_CMD_WIDTH 1 -#define BUF_CLR_CMD_LBN 62 -#define BUF_CLR_CMD_WIDTH 1 -#define BUF_CLR_END_ID_LBN 32 -#define BUF_CLR_END_ID_WIDTH 20 -#define BUF_CLR_START_ID_LBN 0 -#define BUF_CLR_START_ID_WIDTH 20 - -/* Receive configuration register */ -#define RX_CFG_REG_KER 0x800 - -/* B0 */ -#define RX_INGR_EN_B0_LBN 47 -#define RX_INGR_EN_B0_WIDTH 1 -#define RX_DESC_PUSH_EN_B0_LBN 43 -#define RX_DESC_PUSH_EN_B0_WIDTH 1 -#define RX_XON_TX_TH_B0_LBN 33 -#define RX_XON_TX_TH_B0_WIDTH 5 -#define RX_XOFF_TX_TH_B0_LBN 28 -#define RX_XOFF_TX_TH_B0_WIDTH 5 -#define RX_USR_BUF_SIZE_B0_LBN 19 -#define RX_USR_BUF_SIZE_B0_WIDTH 9 -#define RX_XON_MAC_TH_B0_LBN 10 -#define RX_XON_MAC_TH_B0_WIDTH 9 -#define RX_XOFF_MAC_TH_B0_LBN 1 -#define RX_XOFF_MAC_TH_B0_WIDTH 9 -#define RX_XOFF_MAC_EN_B0_LBN 0 -#define RX_XOFF_MAC_EN_B0_WIDTH 1 - -/* A1 */ -#define RX_DESC_PUSH_EN_A1_LBN 35 -#define RX_DESC_PUSH_EN_A1_WIDTH 1 -#define RX_XON_TX_TH_A1_LBN 25 -#define RX_XON_TX_TH_A1_WIDTH 5 -#define RX_XOFF_TX_TH_A1_LBN 20 -#define RX_XOFF_TX_TH_A1_WIDTH 5 -#define RX_USR_BUF_SIZE_A1_LBN 11 -#define RX_USR_BUF_SIZE_A1_WIDTH 9 -#define RX_XON_MAC_TH_A1_LBN 6 -#define RX_XON_MAC_TH_A1_WIDTH 5 -#define RX_XOFF_MAC_TH_A1_LBN 1 -#define RX_XOFF_MAC_TH_A1_WIDTH 5 -#define RX_XOFF_MAC_EN_A1_LBN 0 -#define RX_XOFF_MAC_EN_A1_WIDTH 1 - -/* Receive filter control register */ -#define RX_FILTER_CTL_REG 0x810 -#define UDP_FULL_SRCH_LIMIT_LBN 32 -#define UDP_FULL_SRCH_LIMIT_WIDTH 8 -#define NUM_KER_LBN 24 -#define NUM_KER_WIDTH 2 -#define UDP_WILD_SRCH_LIMIT_LBN 16 -#define UDP_WILD_SRCH_LIMIT_WIDTH 8 -#define TCP_WILD_SRCH_LIMIT_LBN 8 -#define TCP_WILD_SRCH_LIMIT_WIDTH 8 -#define TCP_FULL_SRCH_LIMIT_LBN 0 -#define TCP_FULL_SRCH_LIMIT_WIDTH 8 - -/* RX queue flush register */ -#define RX_FLUSH_DESCQ_REG_KER 0x0820 -#define RX_FLUSH_DESCQ_CMD_LBN 24 -#define RX_FLUSH_DESCQ_CMD_WIDTH 1 -#define RX_FLUSH_DESCQ_LBN 0 -#define RX_FLUSH_DESCQ_WIDTH 12 - -/* Receive descriptor update register */ -#define RX_DESC_UPD_REG_KER_DWORD (0x830 + 12) -#define RX_DESC_WPTR_DWORD_LBN 0 -#define RX_DESC_WPTR_DWORD_WIDTH 12 - -/* Receive descriptor cache configuration register */ -#define RX_DC_CFG_REG_KER 0x840 -#define RX_DC_SIZE_LBN 0 -#define RX_DC_SIZE_WIDTH 2 - -#define RX_DC_PF_WM_REG_KER 0x850 -#define RX_DC_PF_LWM_LBN 0 -#define RX_DC_PF_LWM_WIDTH 6 - -/* RX no descriptor drop counter */ -#define RX_NODESC_DROP_REG_KER 0x880 -#define RX_NODESC_DROP_CNT_LBN 0 -#define RX_NODESC_DROP_CNT_WIDTH 16 - -/* RX black magic register */ -#define RX_SELF_RST_REG_KER 0x890 -#define RX_ISCSI_DIS_LBN 17 -#define RX_ISCSI_DIS_WIDTH 1 -#define RX_NODESC_WAIT_DIS_LBN 9 -#define RX_NODESC_WAIT_DIS_WIDTH 1 -#define RX_RECOVERY_EN_LBN 8 -#define RX_RECOVERY_EN_WIDTH 1 - -/* TX queue flush register */ -#define TX_FLUSH_DESCQ_REG_KER 0x0a00 -#define TX_FLUSH_DESCQ_CMD_LBN 12 -#define TX_FLUSH_DESCQ_CMD_WIDTH 1 -#define TX_FLUSH_DESCQ_LBN 0 -#define TX_FLUSH_DESCQ_WIDTH 12 - -/* Transmit descriptor update register */ -#define TX_DESC_UPD_REG_KER_DWORD (0xa10 + 12) -#define TX_DESC_WPTR_DWORD_LBN 0 -#define TX_DESC_WPTR_DWORD_WIDTH 12 - -/* Transmit descriptor cache configuration register */ -#define TX_DC_CFG_REG_KER 0xa20 -#define TX_DC_SIZE_LBN 0 -#define TX_DC_SIZE_WIDTH 2 - -/* Transmit checksum configuration register (A0/A1 only) */ -#define TX_CHKSM_CFG_REG_KER_A1 0xa30 - -/* Transmit configuration register */ -#define TX_CFG_REG_KER 0xa50 -#define TX_NO_EOP_DISC_EN_LBN 5 -#define TX_NO_EOP_DISC_EN_WIDTH 1 - -/* Transmit configuration register 2 */ -#define TX_CFG2_REG_KER 0xa80 -#define TX_CSR_PUSH_EN_LBN 89 -#define TX_CSR_PUSH_EN_WIDTH 1 -#define TX_RX_SPACER_LBN 64 -#define TX_RX_SPACER_WIDTH 8 -#define TX_SW_EV_EN_LBN 59 -#define TX_SW_EV_EN_WIDTH 1 -#define TX_RX_SPACER_EN_LBN 57 -#define TX_RX_SPACER_EN_WIDTH 1 -#define TX_PREF_THRESHOLD_LBN 19 -#define TX_PREF_THRESHOLD_WIDTH 2 -#define TX_ONE_PKT_PER_Q_LBN 18 -#define TX_ONE_PKT_PER_Q_WIDTH 1 -#define TX_DIS_NON_IP_EV_LBN 17 -#define TX_DIS_NON_IP_EV_WIDTH 1 -#define TX_FLUSH_MIN_LEN_EN_B0_LBN 7 -#define TX_FLUSH_MIN_LEN_EN_B0_WIDTH 1 - -/* PHY management transmit data register */ -#define MD_TXD_REG_KER 0xc00 -#define MD_TXD_LBN 0 -#define MD_TXD_WIDTH 16 - -/* PHY management receive data register */ -#define MD_RXD_REG_KER 0xc10 -#define MD_RXD_LBN 0 -#define MD_RXD_WIDTH 16 - -/* PHY management configuration & status register */ -#define MD_CS_REG_KER 0xc20 -#define MD_GC_LBN 4 -#define MD_GC_WIDTH 1 -#define MD_RIC_LBN 2 -#define MD_RIC_WIDTH 1 -#define MD_RDC_LBN 1 -#define MD_RDC_WIDTH 1 -#define MD_WRC_LBN 0 -#define MD_WRC_WIDTH 1 - -/* PHY management PHY address register */ -#define MD_PHY_ADR_REG_KER 0xc30 -#define MD_PHY_ADR_LBN 0 -#define MD_PHY_ADR_WIDTH 16 - -/* PHY management ID register */ -#define MD_ID_REG_KER 0xc40 -#define MD_PRT_ADR_LBN 11 -#define MD_PRT_ADR_WIDTH 5 -#define MD_DEV_ADR_LBN 6 -#define MD_DEV_ADR_WIDTH 5 -/* Used for writing both at once */ -#define MD_PRT_DEV_ADR_LBN 6 -#define MD_PRT_DEV_ADR_WIDTH 10 - -/* PHY management status & mask register (DWORD read only) */ -#define MD_STAT_REG_KER 0xc50 -#define MD_BSERR_LBN 2 -#define MD_BSERR_WIDTH 1 -#define MD_LNFL_LBN 1 -#define MD_LNFL_WIDTH 1 -#define MD_BSY_LBN 0 -#define MD_BSY_WIDTH 1 - -/* Port 0 and 1 MAC stats registers */ -#define MAC0_STAT_DMA_REG_KER 0xc60 -#define MAC_STAT_DMA_CMD_LBN 48 -#define MAC_STAT_DMA_CMD_WIDTH 1 -#define MAC_STAT_DMA_ADR_LBN 0 -#define MAC_STAT_DMA_ADR_WIDTH EFX_DMA_TYPE_WIDTH(46) - -/* Port 0 and 1 MAC control registers */ -#define MAC0_CTRL_REG_KER 0xc80 -#define MAC_XOFF_VAL_LBN 16 -#define MAC_XOFF_VAL_WIDTH 16 -#define TXFIFO_DRAIN_EN_B0_LBN 7 -#define TXFIFO_DRAIN_EN_B0_WIDTH 1 -#define MAC_BCAD_ACPT_LBN 4 -#define MAC_BCAD_ACPT_WIDTH 1 -#define MAC_UC_PROM_LBN 3 -#define MAC_UC_PROM_WIDTH 1 -#define MAC_LINK_STATUS_LBN 2 -#define MAC_LINK_STATUS_WIDTH 1 -#define MAC_SPEED_LBN 0 -#define MAC_SPEED_WIDTH 2 - -/* 10G XAUI XGXS default values */ -#define XX_TXDRV_DEQ_DEFAULT 0xe /* deq=.6 */ -#define XX_TXDRV_DTX_DEFAULT 0x5 /* 1.25 */ -#define XX_SD_CTL_DRV_DEFAULT 0 /* 20mA */ - -/* Multicast address hash table */ -#define MAC_MCAST_HASH_REG0_KER 0xca0 -#define MAC_MCAST_HASH_REG1_KER 0xcb0 - -/* GMAC configuration register 1 */ -#define GM_CFG1_REG 0xe00 -#define GM_SW_RST_LBN 31 -#define GM_SW_RST_WIDTH 1 -#define GM_LOOP_LBN 8 -#define GM_LOOP_WIDTH 1 -#define GM_RX_FC_EN_LBN 5 -#define GM_RX_FC_EN_WIDTH 1 -#define GM_TX_FC_EN_LBN 4 -#define GM_TX_FC_EN_WIDTH 1 -#define GM_RX_EN_LBN 2 -#define GM_RX_EN_WIDTH 1 -#define GM_TX_EN_LBN 0 -#define GM_TX_EN_WIDTH 1 - -/* GMAC configuration register 2 */ -#define GM_CFG2_REG 0xe10 -#define GM_PAMBL_LEN_LBN 12 -#define GM_PAMBL_LEN_WIDTH 4 -#define GM_IF_MODE_LBN 8 -#define GM_IF_MODE_WIDTH 2 -#define GM_LEN_CHK_LBN 4 -#define GM_LEN_CHK_WIDTH 1 -#define GM_PAD_CRC_EN_LBN 2 -#define GM_PAD_CRC_EN_WIDTH 1 -#define GM_FD_LBN 0 -#define GM_FD_WIDTH 1 - -/* GMAC maximum frame length register */ -#define GM_MAX_FLEN_REG 0xe40 -#define GM_MAX_FLEN_LBN 0 -#define GM_MAX_FLEN_WIDTH 16 - -/* GMAC station address register 1 */ -#define GM_ADR1_REG 0xf00 -#define GM_HWADDR_5_LBN 24 -#define GM_HWADDR_5_WIDTH 8 -#define GM_HWADDR_4_LBN 16 -#define GM_HWADDR_4_WIDTH 8 -#define GM_HWADDR_3_LBN 8 -#define GM_HWADDR_3_WIDTH 8 -#define GM_HWADDR_2_LBN 0 -#define GM_HWADDR_2_WIDTH 8 - -/* GMAC station address register 2 */ -#define GM_ADR2_REG 0xf10 -#define GM_HWADDR_1_LBN 24 -#define GM_HWADDR_1_WIDTH 8 -#define GM_HWADDR_0_LBN 16 -#define GM_HWADDR_0_WIDTH 8 - -/* GMAC FIFO configuration register 0 */ -#define GMF_CFG0_REG 0xf20 -#define GMF_FTFENREQ_LBN 12 -#define GMF_FTFENREQ_WIDTH 1 -#define GMF_STFENREQ_LBN 11 -#define GMF_STFENREQ_WIDTH 1 -#define GMF_FRFENREQ_LBN 10 -#define GMF_FRFENREQ_WIDTH 1 -#define GMF_SRFENREQ_LBN 9 -#define GMF_SRFENREQ_WIDTH 1 -#define GMF_WTMENREQ_LBN 8 -#define GMF_WTMENREQ_WIDTH 1 - -/* GMAC FIFO configuration register 1 */ -#define GMF_CFG1_REG 0xf30 -#define GMF_CFGFRTH_LBN 16 -#define GMF_CFGFRTH_WIDTH 5 -#define GMF_CFGXOFFRTX_LBN 0 -#define GMF_CFGXOFFRTX_WIDTH 16 - -/* GMAC FIFO configuration register 2 */ -#define GMF_CFG2_REG 0xf40 -#define GMF_CFGHWM_LBN 16 -#define GMF_CFGHWM_WIDTH 6 -#define GMF_CFGLWM_LBN 0 -#define GMF_CFGLWM_WIDTH 6 - -/* GMAC FIFO configuration register 3 */ -#define GMF_CFG3_REG 0xf50 -#define GMF_CFGHWMFT_LBN 16 -#define GMF_CFGHWMFT_WIDTH 6 -#define GMF_CFGFTTH_LBN 0 -#define GMF_CFGFTTH_WIDTH 6 - -/* GMAC FIFO configuration register 4 */ -#define GMF_CFG4_REG 0xf60 -#define GMF_HSTFLTRFRM_PAUSE_LBN 12 -#define GMF_HSTFLTRFRM_PAUSE_WIDTH 12 - -/* GMAC FIFO configuration register 5 */ -#define GMF_CFG5_REG 0xf70 -#define GMF_CFGHDPLX_LBN 22 -#define GMF_CFGHDPLX_WIDTH 1 -#define GMF_CFGBYTMODE_LBN 19 -#define GMF_CFGBYTMODE_WIDTH 1 -#define GMF_HSTDRPLT64_LBN 18 -#define GMF_HSTDRPLT64_WIDTH 1 -#define GMF_HSTFLTRFRMDC_PAUSE_LBN 12 -#define GMF_HSTFLTRFRMDC_PAUSE_WIDTH 1 - -/* XGMAC address register low */ -#define XM_ADR_LO_REG 0x1200 -#define XM_ADR_3_LBN 24 -#define XM_ADR_3_WIDTH 8 -#define XM_ADR_2_LBN 16 -#define XM_ADR_2_WIDTH 8 -#define XM_ADR_1_LBN 8 -#define XM_ADR_1_WIDTH 8 -#define XM_ADR_0_LBN 0 -#define XM_ADR_0_WIDTH 8 - -/* XGMAC address register high */ -#define XM_ADR_HI_REG 0x1210 -#define XM_ADR_5_LBN 8 -#define XM_ADR_5_WIDTH 8 -#define XM_ADR_4_LBN 0 -#define XM_ADR_4_WIDTH 8 - -/* XGMAC global configuration */ -#define XM_GLB_CFG_REG 0x1220 -#define XM_RX_STAT_EN_LBN 11 -#define XM_RX_STAT_EN_WIDTH 1 -#define XM_TX_STAT_EN_LBN 10 -#define XM_TX_STAT_EN_WIDTH 1 -#define XM_RX_JUMBO_MODE_LBN 6 -#define XM_RX_JUMBO_MODE_WIDTH 1 -#define XM_INTCLR_MODE_LBN 3 -#define XM_INTCLR_MODE_WIDTH 1 -#define XM_CORE_RST_LBN 0 -#define XM_CORE_RST_WIDTH 1 - -/* XGMAC transmit configuration */ -#define XM_TX_CFG_REG 0x1230 -#define XM_IPG_LBN 16 -#define XM_IPG_WIDTH 4 -#define XM_FCNTL_LBN 10 -#define XM_FCNTL_WIDTH 1 -#define XM_TXCRC_LBN 8 -#define XM_TXCRC_WIDTH 1 -#define XM_AUTO_PAD_LBN 5 -#define XM_AUTO_PAD_WIDTH 1 -#define XM_TX_PRMBL_LBN 2 -#define XM_TX_PRMBL_WIDTH 1 -#define XM_TXEN_LBN 1 -#define XM_TXEN_WIDTH 1 - -/* XGMAC receive configuration */ -#define XM_RX_CFG_REG 0x1240 -#define XM_PASS_CRC_ERR_LBN 25 -#define XM_PASS_CRC_ERR_WIDTH 1 -#define XM_ACPT_ALL_MCAST_LBN 11 -#define XM_ACPT_ALL_MCAST_WIDTH 1 -#define XM_ACPT_ALL_UCAST_LBN 9 -#define XM_ACPT_ALL_UCAST_WIDTH 1 -#define XM_AUTO_DEPAD_LBN 8 -#define XM_AUTO_DEPAD_WIDTH 1 -#define XM_RXEN_LBN 1 -#define XM_RXEN_WIDTH 1 - -/* XGMAC management interrupt mask register */ -#define XM_MGT_INT_MSK_REG_B0 0x1250 -#define XM_MSK_PRMBLE_ERR_LBN 2 -#define XM_MSK_PRMBLE_ERR_WIDTH 1 -#define XM_MSK_RMTFLT_LBN 1 -#define XM_MSK_RMTFLT_WIDTH 1 -#define XM_MSK_LCLFLT_LBN 0 -#define XM_MSK_LCLFLT_WIDTH 1 - -/* XGMAC flow control register */ -#define XM_FC_REG 0x1270 -#define XM_PAUSE_TIME_LBN 16 -#define XM_PAUSE_TIME_WIDTH 16 -#define XM_DIS_FCNTL_LBN 0 -#define XM_DIS_FCNTL_WIDTH 1 - -/* XGMAC pause time count register */ -#define XM_PAUSE_TIME_REG 0x1290 - -/* XGMAC transmit parameter register */ -#define XM_TX_PARAM_REG 0x012d0 -#define XM_TX_JUMBO_MODE_LBN 31 -#define XM_TX_JUMBO_MODE_WIDTH 1 -#define XM_MAX_TX_FRM_SIZE_LBN 16 -#define XM_MAX_TX_FRM_SIZE_WIDTH 14 - -/* XGMAC receive parameter register */ -#define XM_RX_PARAM_REG 0x12e0 -#define XM_MAX_RX_FRM_SIZE_LBN 0 -#define XM_MAX_RX_FRM_SIZE_WIDTH 14 - -/* XGMAC management interrupt status register */ -#define XM_MGT_INT_REG_B0 0x12f0 -#define XM_PRMBLE_ERR 2 -#define XM_PRMBLE_WIDTH 1 -#define XM_RMTFLT_LBN 1 -#define XM_RMTFLT_WIDTH 1 -#define XM_LCLFLT_LBN 0 -#define XM_LCLFLT_WIDTH 1 - -/* XGXS/XAUI powerdown/reset register */ -#define XX_PWR_RST_REG 0x1300 - -#define XX_PWRDND_EN_LBN 15 -#define XX_PWRDND_EN_WIDTH 1 -#define XX_PWRDNC_EN_LBN 14 -#define XX_PWRDNC_EN_WIDTH 1 -#define XX_PWRDNB_EN_LBN 13 -#define XX_PWRDNB_EN_WIDTH 1 -#define XX_PWRDNA_EN_LBN 12 -#define XX_PWRDNA_EN_WIDTH 1 -#define XX_RSTPLLCD_EN_LBN 9 -#define XX_RSTPLLCD_EN_WIDTH 1 -#define XX_RSTPLLAB_EN_LBN 8 -#define XX_RSTPLLAB_EN_WIDTH 1 -#define XX_RESETD_EN_LBN 7 -#define XX_RESETD_EN_WIDTH 1 -#define XX_RESETC_EN_LBN 6 -#define XX_RESETC_EN_WIDTH 1 -#define XX_RESETB_EN_LBN 5 -#define XX_RESETB_EN_WIDTH 1 -#define XX_RESETA_EN_LBN 4 -#define XX_RESETA_EN_WIDTH 1 -#define XX_RSTXGXSRX_EN_LBN 2 -#define XX_RSTXGXSRX_EN_WIDTH 1 -#define XX_RSTXGXSTX_EN_LBN 1 -#define XX_RSTXGXSTX_EN_WIDTH 1 -#define XX_RST_XX_EN_LBN 0 -#define XX_RST_XX_EN_WIDTH 1 - -/* XGXS/XAUI powerdown/reset control register */ -#define XX_SD_CTL_REG 0x1310 -#define XX_HIDRVD_LBN 15 -#define XX_HIDRVD_WIDTH 1 -#define XX_LODRVD_LBN 14 -#define XX_LODRVD_WIDTH 1 -#define XX_HIDRVC_LBN 13 -#define XX_HIDRVC_WIDTH 1 -#define XX_LODRVC_LBN 12 -#define XX_LODRVC_WIDTH 1 -#define XX_HIDRVB_LBN 11 -#define XX_HIDRVB_WIDTH 1 -#define XX_LODRVB_LBN 10 -#define XX_LODRVB_WIDTH 1 -#define XX_HIDRVA_LBN 9 -#define XX_HIDRVA_WIDTH 1 -#define XX_LODRVA_LBN 8 -#define XX_LODRVA_WIDTH 1 -#define XX_LPBKD_LBN 3 -#define XX_LPBKD_WIDTH 1 -#define XX_LPBKC_LBN 2 -#define XX_LPBKC_WIDTH 1 -#define XX_LPBKB_LBN 1 -#define XX_LPBKB_WIDTH 1 -#define XX_LPBKA_LBN 0 -#define XX_LPBKA_WIDTH 1 - -#define XX_TXDRV_CTL_REG 0x1320 -#define XX_DEQD_LBN 28 -#define XX_DEQD_WIDTH 4 -#define XX_DEQC_LBN 24 -#define XX_DEQC_WIDTH 4 -#define XX_DEQB_LBN 20 -#define XX_DEQB_WIDTH 4 -#define XX_DEQA_LBN 16 -#define XX_DEQA_WIDTH 4 -#define XX_DTXD_LBN 12 -#define XX_DTXD_WIDTH 4 -#define XX_DTXC_LBN 8 -#define XX_DTXC_WIDTH 4 -#define XX_DTXB_LBN 4 -#define XX_DTXB_WIDTH 4 -#define XX_DTXA_LBN 0 -#define XX_DTXA_WIDTH 4 - -/* XAUI XGXS core status register */ -#define XX_CORE_STAT_REG 0x1360 -#define XX_FORCE_SIG_LBN 24 -#define XX_FORCE_SIG_WIDTH 8 -#define XX_FORCE_SIG_DECODE_FORCED 0xff -#define XX_XGXS_LB_EN_LBN 23 -#define XX_XGXS_LB_EN_WIDTH 1 -#define XX_XGMII_LB_EN_LBN 22 -#define XX_XGMII_LB_EN_WIDTH 1 -#define XX_ALIGN_DONE_LBN 20 -#define XX_ALIGN_DONE_WIDTH 1 -#define XX_SYNC_STAT_LBN 16 -#define XX_SYNC_STAT_WIDTH 4 -#define XX_SYNC_STAT_DECODE_SYNCED 0xf -#define XX_COMMA_DET_LBN 12 -#define XX_COMMA_DET_WIDTH 4 -#define XX_COMMA_DET_DECODE_DETECTED 0xf -#define XX_COMMA_DET_RESET 0xf -#define XX_CHARERR_LBN 4 -#define XX_CHARERR_WIDTH 4 -#define XX_CHARERR_RESET 0xf -#define XX_DISPERR_LBN 0 -#define XX_DISPERR_WIDTH 4 -#define XX_DISPERR_RESET 0xf - -/* Receive filter table */ -#define RX_FILTER_TBL0 0xF00000 - -/* Receive descriptor pointer table */ -#define RX_DESC_PTR_TBL_KER_A1 0x11800 -#define RX_DESC_PTR_TBL_KER_B0 0xF40000 -#define RX_DESC_PTR_TBL_KER_P0 0x900 -#define RX_ISCSI_DDIG_EN_LBN 88 -#define RX_ISCSI_DDIG_EN_WIDTH 1 -#define RX_ISCSI_HDIG_EN_LBN 87 -#define RX_ISCSI_HDIG_EN_WIDTH 1 -#define RX_DESCQ_BUF_BASE_ID_LBN 36 -#define RX_DESCQ_BUF_BASE_ID_WIDTH 20 -#define RX_DESCQ_EVQ_ID_LBN 24 -#define RX_DESCQ_EVQ_ID_WIDTH 12 -#define RX_DESCQ_OWNER_ID_LBN 10 -#define RX_DESCQ_OWNER_ID_WIDTH 14 -#define RX_DESCQ_LABEL_LBN 5 -#define RX_DESCQ_LABEL_WIDTH 5 -#define RX_DESCQ_SIZE_LBN 3 -#define RX_DESCQ_SIZE_WIDTH 2 -#define RX_DESCQ_SIZE_4K 3 -#define RX_DESCQ_SIZE_2K 2 -#define RX_DESCQ_SIZE_1K 1 -#define RX_DESCQ_SIZE_512 0 -#define RX_DESCQ_TYPE_LBN 2 -#define RX_DESCQ_TYPE_WIDTH 1 -#define RX_DESCQ_JUMBO_LBN 1 -#define RX_DESCQ_JUMBO_WIDTH 1 -#define RX_DESCQ_EN_LBN 0 -#define RX_DESCQ_EN_WIDTH 1 - -/* Transmit descriptor pointer table */ -#define TX_DESC_PTR_TBL_KER_A1 0x11900 -#define TX_DESC_PTR_TBL_KER_B0 0xF50000 -#define TX_DESC_PTR_TBL_KER_P0 0xa40 -#define TX_NON_IP_DROP_DIS_B0_LBN 91 -#define TX_NON_IP_DROP_DIS_B0_WIDTH 1 -#define TX_IP_CHKSM_DIS_B0_LBN 90 -#define TX_IP_CHKSM_DIS_B0_WIDTH 1 -#define TX_TCP_CHKSM_DIS_B0_LBN 89 -#define TX_TCP_CHKSM_DIS_B0_WIDTH 1 -#define TX_DESCQ_EN_LBN 88 -#define TX_DESCQ_EN_WIDTH 1 -#define TX_ISCSI_DDIG_EN_LBN 87 -#define TX_ISCSI_DDIG_EN_WIDTH 1 -#define TX_ISCSI_HDIG_EN_LBN 86 -#define TX_ISCSI_HDIG_EN_WIDTH 1 -#define TX_DESCQ_BUF_BASE_ID_LBN 36 -#define TX_DESCQ_BUF_BASE_ID_WIDTH 20 -#define TX_DESCQ_EVQ_ID_LBN 24 -#define TX_DESCQ_EVQ_ID_WIDTH 12 -#define TX_DESCQ_OWNER_ID_LBN 10 -#define TX_DESCQ_OWNER_ID_WIDTH 14 -#define TX_DESCQ_LABEL_LBN 5 -#define TX_DESCQ_LABEL_WIDTH 5 -#define TX_DESCQ_SIZE_LBN 3 -#define TX_DESCQ_SIZE_WIDTH 2 -#define TX_DESCQ_SIZE_4K 3 -#define TX_DESCQ_SIZE_2K 2 -#define TX_DESCQ_SIZE_1K 1 -#define TX_DESCQ_SIZE_512 0 -#define TX_DESCQ_TYPE_LBN 1 -#define TX_DESCQ_TYPE_WIDTH 2 - -/* Event queue pointer */ -#define EVQ_PTR_TBL_KER_A1 0x11a00 -#define EVQ_PTR_TBL_KER_B0 0xf60000 -#define EVQ_PTR_TBL_KER_P0 0x500 -#define EVQ_EN_LBN 23 -#define EVQ_EN_WIDTH 1 -#define EVQ_SIZE_LBN 20 -#define EVQ_SIZE_WIDTH 3 -#define EVQ_SIZE_32K 6 -#define EVQ_SIZE_16K 5 -#define EVQ_SIZE_8K 4 -#define EVQ_SIZE_4K 3 -#define EVQ_SIZE_2K 2 -#define EVQ_SIZE_1K 1 -#define EVQ_SIZE_512 0 -#define EVQ_BUF_BASE_ID_LBN 0 -#define EVQ_BUF_BASE_ID_WIDTH 20 - -/* Event queue read pointer */ -#define EVQ_RPTR_REG_KER_A1 0x11b00 -#define EVQ_RPTR_REG_KER_B0 0xfa0000 -#define EVQ_RPTR_REG_KER_DWORD (EVQ_RPTR_REG_KER + 0) -#define EVQ_RPTR_DWORD_LBN 0 -#define EVQ_RPTR_DWORD_WIDTH 14 - -/* RSS indirection table */ -#define RX_RSS_INDIR_TBL_B0 0xFB0000 -#define RX_RSS_INDIR_ENT_B0_LBN 0 -#define RX_RSS_INDIR_ENT_B0_WIDTH 6 - -/* Special buffer descriptors (full-mode) */ -#define BUF_FULL_TBL_KER_A1 0x8000 -#define BUF_FULL_TBL_KER_B0 0x800000 -#define IP_DAT_BUF_SIZE_LBN 50 -#define IP_DAT_BUF_SIZE_WIDTH 1 -#define IP_DAT_BUF_SIZE_8K 1 -#define IP_DAT_BUF_SIZE_4K 0 -#define BUF_ADR_REGION_LBN 48 -#define BUF_ADR_REGION_WIDTH 2 -#define BUF_ADR_FBUF_LBN 14 -#define BUF_ADR_FBUF_WIDTH 34 -#define BUF_OWNER_ID_FBUF_LBN 0 -#define BUF_OWNER_ID_FBUF_WIDTH 14 - -/* Transmit descriptor */ -#define TX_KER_PORT_LBN 63 -#define TX_KER_PORT_WIDTH 1 -#define TX_KER_CONT_LBN 62 -#define TX_KER_CONT_WIDTH 1 -#define TX_KER_BYTE_CNT_LBN 48 -#define TX_KER_BYTE_CNT_WIDTH 14 -#define TX_KER_BUF_REGION_LBN 46 -#define TX_KER_BUF_REGION_WIDTH 2 -#define TX_KER_BUF_REGION0_DECODE 0 -#define TX_KER_BUF_REGION1_DECODE 1 -#define TX_KER_BUF_REGION2_DECODE 2 -#define TX_KER_BUF_REGION3_DECODE 3 -#define TX_KER_BUF_ADR_LBN 0 -#define TX_KER_BUF_ADR_WIDTH EFX_DMA_TYPE_WIDTH(46) - -/* Receive descriptor */ -#define RX_KER_BUF_SIZE_LBN 48 -#define RX_KER_BUF_SIZE_WIDTH 14 -#define RX_KER_BUF_REGION_LBN 46 -#define RX_KER_BUF_REGION_WIDTH 2 -#define RX_KER_BUF_REGION0_DECODE 0 -#define RX_KER_BUF_REGION1_DECODE 1 -#define RX_KER_BUF_REGION2_DECODE 2 -#define RX_KER_BUF_REGION3_DECODE 3 -#define RX_KER_BUF_ADR_LBN 0 -#define RX_KER_BUF_ADR_WIDTH EFX_DMA_TYPE_WIDTH(46) - -/************************************************************************** - * - * Falcon events - * - ************************************************************************** - */ - -/* Event queue entries */ -#define EV_CODE_LBN 60 -#define EV_CODE_WIDTH 4 -#define RX_IP_EV_DECODE 0 -#define TX_IP_EV_DECODE 2 -#define DRIVER_EV_DECODE 5 -#define GLOBAL_EV_DECODE 6 -#define DRV_GEN_EV_DECODE 7 -#define WHOLE_EVENT_LBN 0 -#define WHOLE_EVENT_WIDTH 64 - -/* Receive events */ -#define RX_EV_PKT_OK_LBN 56 -#define RX_EV_PKT_OK_WIDTH 1 -#define RX_EV_PAUSE_FRM_ERR_LBN 55 -#define RX_EV_PAUSE_FRM_ERR_WIDTH 1 -#define RX_EV_BUF_OWNER_ID_ERR_LBN 54 -#define RX_EV_BUF_OWNER_ID_ERR_WIDTH 1 -#define RX_EV_IF_FRAG_ERR_LBN 53 -#define RX_EV_IF_FRAG_ERR_WIDTH 1 -#define RX_EV_IP_HDR_CHKSUM_ERR_LBN 52 -#define RX_EV_IP_HDR_CHKSUM_ERR_WIDTH 1 -#define RX_EV_TCP_UDP_CHKSUM_ERR_LBN 51 -#define RX_EV_TCP_UDP_CHKSUM_ERR_WIDTH 1 -#define RX_EV_ETH_CRC_ERR_LBN 50 -#define RX_EV_ETH_CRC_ERR_WIDTH 1 -#define RX_EV_FRM_TRUNC_LBN 49 -#define RX_EV_FRM_TRUNC_WIDTH 1 -#define RX_EV_DRIB_NIB_LBN 48 -#define RX_EV_DRIB_NIB_WIDTH 1 -#define RX_EV_TOBE_DISC_LBN 47 -#define RX_EV_TOBE_DISC_WIDTH 1 -#define RX_EV_PKT_TYPE_LBN 44 -#define RX_EV_PKT_TYPE_WIDTH 3 -#define RX_EV_PKT_TYPE_ETH_DECODE 0 -#define RX_EV_PKT_TYPE_LLC_DECODE 1 -#define RX_EV_PKT_TYPE_JUMBO_DECODE 2 -#define RX_EV_PKT_TYPE_VLAN_DECODE 3 -#define RX_EV_PKT_TYPE_VLAN_LLC_DECODE 4 -#define RX_EV_PKT_TYPE_VLAN_JUMBO_DECODE 5 -#define RX_EV_HDR_TYPE_LBN 42 -#define RX_EV_HDR_TYPE_WIDTH 2 -#define RX_EV_HDR_TYPE_TCP_IPV4_DECODE 0 -#define RX_EV_HDR_TYPE_UDP_IPV4_DECODE 1 -#define RX_EV_HDR_TYPE_OTHER_IP_DECODE 2 -#define RX_EV_HDR_TYPE_NON_IP_DECODE 3 -#define RX_EV_HDR_TYPE_HAS_CHECKSUMS(hdr_type) \ - ((hdr_type) <= RX_EV_HDR_TYPE_UDP_IPV4_DECODE) -#define RX_EV_MCAST_HASH_MATCH_LBN 40 -#define RX_EV_MCAST_HASH_MATCH_WIDTH 1 -#define RX_EV_MCAST_PKT_LBN 39 -#define RX_EV_MCAST_PKT_WIDTH 1 -#define RX_EV_Q_LABEL_LBN 32 -#define RX_EV_Q_LABEL_WIDTH 5 -#define RX_EV_JUMBO_CONT_LBN 31 -#define RX_EV_JUMBO_CONT_WIDTH 1 -#define RX_EV_BYTE_CNT_LBN 16 -#define RX_EV_BYTE_CNT_WIDTH 14 -#define RX_EV_SOP_LBN 15 -#define RX_EV_SOP_WIDTH 1 -#define RX_EV_DESC_PTR_LBN 0 -#define RX_EV_DESC_PTR_WIDTH 12 - -/* Transmit events */ -#define TX_EV_PKT_ERR_LBN 38 -#define TX_EV_PKT_ERR_WIDTH 1 -#define TX_EV_Q_LABEL_LBN 32 -#define TX_EV_Q_LABEL_WIDTH 5 -#define TX_EV_WQ_FF_FULL_LBN 15 -#define TX_EV_WQ_FF_FULL_WIDTH 1 -#define TX_EV_COMP_LBN 12 -#define TX_EV_COMP_WIDTH 1 -#define TX_EV_DESC_PTR_LBN 0 -#define TX_EV_DESC_PTR_WIDTH 12 - -/* Driver events */ -#define DRIVER_EV_SUB_CODE_LBN 56 -#define DRIVER_EV_SUB_CODE_WIDTH 4 -#define DRIVER_EV_SUB_DATA_LBN 0 -#define DRIVER_EV_SUB_DATA_WIDTH 14 -#define TX_DESCQ_FLS_DONE_EV_DECODE 0 -#define RX_DESCQ_FLS_DONE_EV_DECODE 1 -#define EVQ_INIT_DONE_EV_DECODE 2 -#define EVQ_NOT_EN_EV_DECODE 3 -#define RX_DESCQ_FLSFF_OVFL_EV_DECODE 4 -#define SRM_UPD_DONE_EV_DECODE 5 -#define WAKE_UP_EV_DECODE 6 -#define TX_PKT_NON_TCP_UDP_DECODE 9 -#define TIMER_EV_DECODE 10 -#define RX_RECOVERY_EV_DECODE 11 -#define RX_DSC_ERROR_EV_DECODE 14 -#define TX_DSC_ERROR_EV_DECODE 15 -#define DRIVER_EV_TX_DESCQ_ID_LBN 0 -#define DRIVER_EV_TX_DESCQ_ID_WIDTH 12 -#define DRIVER_EV_RX_FLUSH_FAIL_LBN 12 -#define DRIVER_EV_RX_FLUSH_FAIL_WIDTH 1 -#define DRIVER_EV_RX_DESCQ_ID_LBN 0 -#define DRIVER_EV_RX_DESCQ_ID_WIDTH 12 -#define SRM_CLR_EV_DECODE 0 -#define SRM_UPD_EV_DECODE 1 -#define SRM_ILLCLR_EV_DECODE 2 - -/* Global events */ -#define RX_RECOVERY_B0_LBN 12 -#define RX_RECOVERY_B0_WIDTH 1 -#define XG_MNT_INTR_B0_LBN 11 -#define XG_MNT_INTR_B0_WIDTH 1 -#define RX_RECOVERY_A1_LBN 11 -#define RX_RECOVERY_A1_WIDTH 1 -#define XFP_PHY_INTR_LBN 10 -#define XFP_PHY_INTR_WIDTH 1 -#define XG_PHY_INTR_LBN 9 -#define XG_PHY_INTR_WIDTH 1 -#define G_PHY1_INTR_LBN 8 -#define G_PHY1_INTR_WIDTH 1 -#define G_PHY0_INTR_LBN 7 -#define G_PHY0_INTR_WIDTH 1 - -/* Driver-generated test events */ -#define EVQ_MAGIC_LBN 0 -#define EVQ_MAGIC_WIDTH 32 - -/************************************************************************** - * - * Falcon MAC stats - * - ************************************************************************** - * - */ - -#define GRxGoodOct_offset 0x0 -#define GRxGoodOct_WIDTH 48 -#define GRxBadOct_offset 0x8 -#define GRxBadOct_WIDTH 48 -#define GRxMissPkt_offset 0x10 -#define GRxMissPkt_WIDTH 32 -#define GRxFalseCRS_offset 0x14 -#define GRxFalseCRS_WIDTH 32 -#define GRxPausePkt_offset 0x18 -#define GRxPausePkt_WIDTH 32 -#define GRxBadPkt_offset 0x1C -#define GRxBadPkt_WIDTH 32 -#define GRxUcastPkt_offset 0x20 -#define GRxUcastPkt_WIDTH 32 -#define GRxMcastPkt_offset 0x24 -#define GRxMcastPkt_WIDTH 32 -#define GRxBcastPkt_offset 0x28 -#define GRxBcastPkt_WIDTH 32 -#define GRxGoodLt64Pkt_offset 0x2C -#define GRxGoodLt64Pkt_WIDTH 32 -#define GRxBadLt64Pkt_offset 0x30 -#define GRxBadLt64Pkt_WIDTH 32 -#define GRx64Pkt_offset 0x34 -#define GRx64Pkt_WIDTH 32 -#define GRx65to127Pkt_offset 0x38 -#define GRx65to127Pkt_WIDTH 32 -#define GRx128to255Pkt_offset 0x3C -#define GRx128to255Pkt_WIDTH 32 -#define GRx256to511Pkt_offset 0x40 -#define GRx256to511Pkt_WIDTH 32 -#define GRx512to1023Pkt_offset 0x44 -#define GRx512to1023Pkt_WIDTH 32 -#define GRx1024to15xxPkt_offset 0x48 -#define GRx1024to15xxPkt_WIDTH 32 -#define GRx15xxtoJumboPkt_offset 0x4C -#define GRx15xxtoJumboPkt_WIDTH 32 -#define GRxGtJumboPkt_offset 0x50 -#define GRxGtJumboPkt_WIDTH 32 -#define GRxFcsErr64to15xxPkt_offset 0x54 -#define GRxFcsErr64to15xxPkt_WIDTH 32 -#define GRxFcsErr15xxtoJumboPkt_offset 0x58 -#define GRxFcsErr15xxtoJumboPkt_WIDTH 32 -#define GRxFcsErrGtJumboPkt_offset 0x5C -#define GRxFcsErrGtJumboPkt_WIDTH 32 -#define GTxGoodBadOct_offset 0x80 -#define GTxGoodBadOct_WIDTH 48 -#define GTxGoodOct_offset 0x88 -#define GTxGoodOct_WIDTH 48 -#define GTxSglColPkt_offset 0x90 -#define GTxSglColPkt_WIDTH 32 -#define GTxMultColPkt_offset 0x94 -#define GTxMultColPkt_WIDTH 32 -#define GTxExColPkt_offset 0x98 -#define GTxExColPkt_WIDTH 32 -#define GTxDefPkt_offset 0x9C -#define GTxDefPkt_WIDTH 32 -#define GTxLateCol_offset 0xA0 -#define GTxLateCol_WIDTH 32 -#define GTxExDefPkt_offset 0xA4 -#define GTxExDefPkt_WIDTH 32 -#define GTxPausePkt_offset 0xA8 -#define GTxPausePkt_WIDTH 32 -#define GTxBadPkt_offset 0xAC -#define GTxBadPkt_WIDTH 32 -#define GTxUcastPkt_offset 0xB0 -#define GTxUcastPkt_WIDTH 32 -#define GTxMcastPkt_offset 0xB4 -#define GTxMcastPkt_WIDTH 32 -#define GTxBcastPkt_offset 0xB8 -#define GTxBcastPkt_WIDTH 32 -#define GTxLt64Pkt_offset 0xBC -#define GTxLt64Pkt_WIDTH 32 -#define GTx64Pkt_offset 0xC0 -#define GTx64Pkt_WIDTH 32 -#define GTx65to127Pkt_offset 0xC4 -#define GTx65to127Pkt_WIDTH 32 -#define GTx128to255Pkt_offset 0xC8 -#define GTx128to255Pkt_WIDTH 32 -#define GTx256to511Pkt_offset 0xCC -#define GTx256to511Pkt_WIDTH 32 -#define GTx512to1023Pkt_offset 0xD0 -#define GTx512to1023Pkt_WIDTH 32 -#define GTx1024to15xxPkt_offset 0xD4 -#define GTx1024to15xxPkt_WIDTH 32 -#define GTx15xxtoJumboPkt_offset 0xD8 -#define GTx15xxtoJumboPkt_WIDTH 32 -#define GTxGtJumboPkt_offset 0xDC -#define GTxGtJumboPkt_WIDTH 32 -#define GTxNonTcpUdpPkt_offset 0xE0 -#define GTxNonTcpUdpPkt_WIDTH 16 -#define GTxMacSrcErrPkt_offset 0xE4 -#define GTxMacSrcErrPkt_WIDTH 16 -#define GTxIpSrcErrPkt_offset 0xE8 -#define GTxIpSrcErrPkt_WIDTH 16 -#define GDmaDone_offset 0xEC -#define GDmaDone_WIDTH 32 - -#define XgRxOctets_offset 0x0 -#define XgRxOctets_WIDTH 48 -#define XgRxOctetsOK_offset 0x8 -#define XgRxOctetsOK_WIDTH 48 -#define XgRxPkts_offset 0x10 -#define XgRxPkts_WIDTH 32 -#define XgRxPktsOK_offset 0x14 -#define XgRxPktsOK_WIDTH 32 -#define XgRxBroadcastPkts_offset 0x18 -#define XgRxBroadcastPkts_WIDTH 32 -#define XgRxMulticastPkts_offset 0x1C -#define XgRxMulticastPkts_WIDTH 32 -#define XgRxUnicastPkts_offset 0x20 -#define XgRxUnicastPkts_WIDTH 32 -#define XgRxUndersizePkts_offset 0x24 -#define XgRxUndersizePkts_WIDTH 32 -#define XgRxOversizePkts_offset 0x28 -#define XgRxOversizePkts_WIDTH 32 -#define XgRxJabberPkts_offset 0x2C -#define XgRxJabberPkts_WIDTH 32 -#define XgRxUndersizeFCSerrorPkts_offset 0x30 -#define XgRxUndersizeFCSerrorPkts_WIDTH 32 -#define XgRxDropEvents_offset 0x34 -#define XgRxDropEvents_WIDTH 32 -#define XgRxFCSerrorPkts_offset 0x38 -#define XgRxFCSerrorPkts_WIDTH 32 -#define XgRxAlignError_offset 0x3C -#define XgRxAlignError_WIDTH 32 -#define XgRxSymbolError_offset 0x40 -#define XgRxSymbolError_WIDTH 32 -#define XgRxInternalMACError_offset 0x44 -#define XgRxInternalMACError_WIDTH 32 -#define XgRxControlPkts_offset 0x48 -#define XgRxControlPkts_WIDTH 32 -#define XgRxPausePkts_offset 0x4C -#define XgRxPausePkts_WIDTH 32 -#define XgRxPkts64Octets_offset 0x50 -#define XgRxPkts64Octets_WIDTH 32 -#define XgRxPkts65to127Octets_offset 0x54 -#define XgRxPkts65to127Octets_WIDTH 32 -#define XgRxPkts128to255Octets_offset 0x58 -#define XgRxPkts128to255Octets_WIDTH 32 -#define XgRxPkts256to511Octets_offset 0x5C -#define XgRxPkts256to511Octets_WIDTH 32 -#define XgRxPkts512to1023Octets_offset 0x60 -#define XgRxPkts512to1023Octets_WIDTH 32 -#define XgRxPkts1024to15xxOctets_offset 0x64 -#define XgRxPkts1024to15xxOctets_WIDTH 32 -#define XgRxPkts15xxtoMaxOctets_offset 0x68 -#define XgRxPkts15xxtoMaxOctets_WIDTH 32 -#define XgRxLengthError_offset 0x6C -#define XgRxLengthError_WIDTH 32 -#define XgTxPkts_offset 0x80 -#define XgTxPkts_WIDTH 32 -#define XgTxOctets_offset 0x88 -#define XgTxOctets_WIDTH 48 -#define XgTxMulticastPkts_offset 0x90 -#define XgTxMulticastPkts_WIDTH 32 -#define XgTxBroadcastPkts_offset 0x94 -#define XgTxBroadcastPkts_WIDTH 32 -#define XgTxUnicastPkts_offset 0x98 -#define XgTxUnicastPkts_WIDTH 32 -#define XgTxControlPkts_offset 0x9C -#define XgTxControlPkts_WIDTH 32 -#define XgTxPausePkts_offset 0xA0 -#define XgTxPausePkts_WIDTH 32 -#define XgTxPkts64Octets_offset 0xA4 -#define XgTxPkts64Octets_WIDTH 32 -#define XgTxPkts65to127Octets_offset 0xA8 -#define XgTxPkts65to127Octets_WIDTH 32 -#define XgTxPkts128to255Octets_offset 0xAC -#define XgTxPkts128to255Octets_WIDTH 32 -#define XgTxPkts256to511Octets_offset 0xB0 -#define XgTxPkts256to511Octets_WIDTH 32 -#define XgTxPkts512to1023Octets_offset 0xB4 -#define XgTxPkts512to1023Octets_WIDTH 32 -#define XgTxPkts1024to15xxOctets_offset 0xB8 -#define XgTxPkts1024to15xxOctets_WIDTH 32 -#define XgTxPkts1519toMaxOctets_offset 0xBC -#define XgTxPkts1519toMaxOctets_WIDTH 32 -#define XgTxUndersizePkts_offset 0xC0 -#define XgTxUndersizePkts_WIDTH 32 -#define XgTxOversizePkts_offset 0xC4 -#define XgTxOversizePkts_WIDTH 32 -#define XgTxNonTcpUdpPkt_offset 0xC8 -#define XgTxNonTcpUdpPkt_WIDTH 16 -#define XgTxMacSrcErrPkt_offset 0xCC -#define XgTxMacSrcErrPkt_WIDTH 16 -#define XgTxIpSrcErrPkt_offset 0xD0 -#define XgTxIpSrcErrPkt_WIDTH 16 -#define XgDmaDone_offset 0xD4 - -#define FALCON_STATS_NOT_DONE 0x00000000 -#define FALCON_STATS_DONE 0xffffffff - -/* Interrupt status register bits */ -#define FATAL_INT_LBN 64 -#define FATAL_INT_WIDTH 1 -#define INT_EVQS_LBN 40 -#define INT_EVQS_WIDTH 4 - -/************************************************************************** - * - * Falcon non-volatile configuration - * - ************************************************************************** - */ - -/* Board configuration v2 (v1 is obsolete; later versions are compatible) */ -struct falcon_nvconfig_board_v2 { - __le16 nports; - u8 port0_phy_addr; - u8 port0_phy_type; - u8 port1_phy_addr; - u8 port1_phy_type; - __le16 asic_sub_revision; - __le16 board_revision; -} __packed; - -/* Board configuration v3 extra information */ -struct falcon_nvconfig_board_v3 { - __le32 spi_device_type[2]; -} __packed; - -/* Bit numbers for spi_device_type */ -#define SPI_DEV_TYPE_SIZE_LBN 0 -#define SPI_DEV_TYPE_SIZE_WIDTH 5 -#define SPI_DEV_TYPE_ADDR_LEN_LBN 6 -#define SPI_DEV_TYPE_ADDR_LEN_WIDTH 2 -#define SPI_DEV_TYPE_ERASE_CMD_LBN 8 -#define SPI_DEV_TYPE_ERASE_CMD_WIDTH 8 -#define SPI_DEV_TYPE_ERASE_SIZE_LBN 16 -#define SPI_DEV_TYPE_ERASE_SIZE_WIDTH 5 -#define SPI_DEV_TYPE_BLOCK_SIZE_LBN 24 -#define SPI_DEV_TYPE_BLOCK_SIZE_WIDTH 5 -#define SPI_DEV_TYPE_FIELD(type, field) \ - (((type) >> EFX_LOW_BIT(field)) & EFX_MASK32(EFX_WIDTH(field))) - -#define NVCONFIG_OFFSET 0x300 - -#define NVCONFIG_BOARD_MAGIC_NUM 0xFA1C -struct falcon_nvconfig { - efx_oword_t ee_vpd_cfg_reg; /* 0x300 */ - u8 mac_address[2][8]; /* 0x310 */ - efx_oword_t pcie_sd_ctl0123_reg; /* 0x320 */ - efx_oword_t pcie_sd_ctl45_reg; /* 0x330 */ - efx_oword_t pcie_pcs_ctl_stat_reg; /* 0x340 */ - efx_oword_t hw_init_reg; /* 0x350 */ - efx_oword_t nic_stat_reg; /* 0x360 */ - efx_oword_t glb_ctl_reg; /* 0x370 */ - efx_oword_t srm_cfg_reg; /* 0x380 */ - efx_oword_t spare_reg; /* 0x390 */ - __le16 board_magic_num; /* 0x3A0 */ - __le16 board_struct_ver; - __le16 board_checksum; - struct falcon_nvconfig_board_v2 board_v2; - efx_oword_t ee_base_page_reg; /* 0x3B0 */ - struct falcon_nvconfig_board_v3 board_v3; -} __packed; - -#endif /* EFX_FALCON_HWDEFS_H */ diff --git a/drivers/net/sfc/falcon_io.h b/drivers/net/sfc/falcon_io.h deleted file mode 100644 index c16da3149fa..00000000000 --- a/drivers/net/sfc/falcon_io.h +++ /dev/null @@ -1,255 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2006-2008 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_FALCON_IO_H -#define EFX_FALCON_IO_H - -#include <linux/io.h> -#include <linux/spinlock.h> - -/************************************************************************** - * - * Falcon hardware access - * - ************************************************************************** - * - * Notes on locking strategy: - * - * Most Falcon registers require 16-byte (or 8-byte, for SRAM - * registers) atomic writes which necessitates locking. - * Under normal operation few writes to the Falcon BAR are made and these - * registers (EVQ_RPTR_REG, RX_DESC_UPD_REG and TX_DESC_UPD_REG) are special - * cased to allow 4-byte (hence lockless) accesses. - * - * It *is* safe to write to these 4-byte registers in the middle of an - * access to an 8-byte or 16-byte register. We therefore use a - * spinlock to protect accesses to the larger registers, but no locks - * for the 4-byte registers. - * - * A write barrier is needed to ensure that DW3 is written after DW0/1/2 - * due to the way the 16byte registers are "collected" in the Falcon BIU - * - * We also lock when carrying out reads, to ensure consistency of the - * data (made possible since the BIU reads all 128 bits into a cache). - * Reads are very rare, so this isn't a significant performance - * impact. (Most data transferred from NIC to host is DMAed directly - * into host memory). - * - * I/O BAR access uses locks for both reads and writes (but is only provided - * for testing purposes). - */ - -/* Special buffer descriptors (Falcon SRAM) */ -#define BUF_TBL_KER_A1 0x18000 -#define BUF_TBL_KER_B0 0x800000 - - -#if BITS_PER_LONG == 64 -#define FALCON_USE_QWORD_IO 1 -#endif - -#ifdef FALCON_USE_QWORD_IO -static inline void _falcon_writeq(struct efx_nic *efx, __le64 value, - unsigned int reg) -{ - __raw_writeq((__force u64)value, efx->membase + reg); -} -static inline __le64 _falcon_readq(struct efx_nic *efx, unsigned int reg) -{ - return (__force __le64)__raw_readq(efx->membase + reg); -} -#endif - -static inline void _falcon_writel(struct efx_nic *efx, __le32 value, - unsigned int reg) -{ - __raw_writel((__force u32)value, efx->membase + reg); -} -static inline __le32 _falcon_readl(struct efx_nic *efx, unsigned int reg) -{ - return (__force __le32)__raw_readl(efx->membase + reg); -} - -/* Writes to a normal 16-byte Falcon register, locking as appropriate. */ -static inline void falcon_write(struct efx_nic *efx, efx_oword_t *value, - unsigned int reg) -{ - unsigned long flags; - - EFX_REGDUMP(efx, "writing register %x with " EFX_OWORD_FMT "\n", reg, - EFX_OWORD_VAL(*value)); - - spin_lock_irqsave(&efx->biu_lock, flags); -#ifdef FALCON_USE_QWORD_IO - _falcon_writeq(efx, value->u64[0], reg + 0); - wmb(); - _falcon_writeq(efx, value->u64[1], reg + 8); -#else - _falcon_writel(efx, value->u32[0], reg + 0); - _falcon_writel(efx, value->u32[1], reg + 4); - _falcon_writel(efx, value->u32[2], reg + 8); - wmb(); - _falcon_writel(efx, value->u32[3], reg + 12); -#endif - mmiowb(); - spin_unlock_irqrestore(&efx->biu_lock, flags); -} - -/* Writes to an 8-byte Falcon SRAM register, locking as appropriate. */ -static inline void falcon_write_sram(struct efx_nic *efx, efx_qword_t *value, - unsigned int index) -{ - unsigned int reg = efx->type->buf_tbl_base + (index * sizeof(*value)); - unsigned long flags; - - EFX_REGDUMP(efx, "writing SRAM register %x with " EFX_QWORD_FMT "\n", - reg, EFX_QWORD_VAL(*value)); - - spin_lock_irqsave(&efx->biu_lock, flags); -#ifdef FALCON_USE_QWORD_IO - _falcon_writeq(efx, value->u64[0], reg + 0); -#else - _falcon_writel(efx, value->u32[0], reg + 0); - wmb(); - _falcon_writel(efx, value->u32[1], reg + 4); -#endif - mmiowb(); - spin_unlock_irqrestore(&efx->biu_lock, flags); -} - -/* Write dword to Falcon register that allows partial writes - * - * Some Falcon registers (EVQ_RPTR_REG, RX_DESC_UPD_REG and - * TX_DESC_UPD_REG) can be written to as a single dword. This allows - * for lockless writes. - */ -static inline void falcon_writel(struct efx_nic *efx, efx_dword_t *value, - unsigned int reg) -{ - EFX_REGDUMP(efx, "writing partial register %x with "EFX_DWORD_FMT"\n", - reg, EFX_DWORD_VAL(*value)); - - /* No lock required */ - _falcon_writel(efx, value->u32[0], reg); -} - -/* Read from a Falcon register - * - * This reads an entire 16-byte Falcon register in one go, locking as - * appropriate. It is essential to read the first dword first, as this - * prompts Falcon to load the current value into the shadow register. - */ -static inline void falcon_read(struct efx_nic *efx, efx_oword_t *value, - unsigned int reg) -{ - unsigned long flags; - - spin_lock_irqsave(&efx->biu_lock, flags); - value->u32[0] = _falcon_readl(efx, reg + 0); - rmb(); - value->u32[1] = _falcon_readl(efx, reg + 4); - value->u32[2] = _falcon_readl(efx, reg + 8); - value->u32[3] = _falcon_readl(efx, reg + 12); - spin_unlock_irqrestore(&efx->biu_lock, flags); - - EFX_REGDUMP(efx, "read from register %x, got " EFX_OWORD_FMT "\n", reg, - EFX_OWORD_VAL(*value)); -} - -/* This reads an 8-byte Falcon SRAM entry in one go. */ -static inline void falcon_read_sram(struct efx_nic *efx, efx_qword_t *value, - unsigned int index) -{ - unsigned int reg = efx->type->buf_tbl_base + (index * sizeof(*value)); - unsigned long flags; - - spin_lock_irqsave(&efx->biu_lock, flags); -#ifdef FALCON_USE_QWORD_IO - value->u64[0] = _falcon_readq(efx, reg + 0); -#else - value->u32[0] = _falcon_readl(efx, reg + 0); - rmb(); - value->u32[1] = _falcon_readl(efx, reg + 4); -#endif - spin_unlock_irqrestore(&efx->biu_lock, flags); - - EFX_REGDUMP(efx, "read from SRAM register %x, got "EFX_QWORD_FMT"\n", - reg, EFX_QWORD_VAL(*value)); -} - -/* Read dword from Falcon register that allows partial writes (sic) */ -static inline void falcon_readl(struct efx_nic *efx, efx_dword_t *value, - unsigned int reg) -{ - value->u32[0] = _falcon_readl(efx, reg); - EFX_REGDUMP(efx, "read from register %x, got "EFX_DWORD_FMT"\n", - reg, EFX_DWORD_VAL(*value)); -} - -/* Write to a register forming part of a table */ -static inline void falcon_write_table(struct efx_nic *efx, efx_oword_t *value, - unsigned int reg, unsigned int index) -{ - falcon_write(efx, value, reg + index * sizeof(efx_oword_t)); -} - -/* Read to a register forming part of a table */ -static inline void falcon_read_table(struct efx_nic *efx, efx_oword_t *value, - unsigned int reg, unsigned int index) -{ - falcon_read(efx, value, reg + index * sizeof(efx_oword_t)); -} - -/* Write to a dword register forming part of a table */ -static inline void falcon_writel_table(struct efx_nic *efx, efx_dword_t *value, - unsigned int reg, unsigned int index) -{ - falcon_writel(efx, value, reg + index * sizeof(efx_oword_t)); -} - -/* Page-mapped register block size */ -#define FALCON_PAGE_BLOCK_SIZE 0x2000 - -/* Calculate offset to page-mapped register block */ -#define FALCON_PAGED_REG(page, reg) \ - ((page) * FALCON_PAGE_BLOCK_SIZE + (reg)) - -/* As for falcon_write(), but for a page-mapped register. */ -static inline void falcon_write_page(struct efx_nic *efx, efx_oword_t *value, - unsigned int reg, unsigned int page) -{ - falcon_write(efx, value, FALCON_PAGED_REG(page, reg)); -} - -/* As for falcon_writel(), but for a page-mapped register. */ -static inline void falcon_writel_page(struct efx_nic *efx, efx_dword_t *value, - unsigned int reg, unsigned int page) -{ - falcon_writel(efx, value, FALCON_PAGED_REG(page, reg)); -} - -/* Write dword to Falcon page-mapped register with an extra lock. - * - * As for falcon_writel_page(), but for a register that suffers from - * SFC bug 3181. Take out a lock so the BIU collector cannot be - * confused. */ -static inline void falcon_writel_page_locked(struct efx_nic *efx, - efx_dword_t *value, - unsigned int reg, - unsigned int page) -{ - unsigned long flags; - - spin_lock_irqsave(&efx->biu_lock, flags); - falcon_writel(efx, value, FALCON_PAGED_REG(page, reg)); - spin_unlock_irqrestore(&efx->biu_lock, flags); -} - -#endif /* EFX_FALCON_IO_H */ diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c deleted file mode 100644 index 5a03713685a..00000000000 --- a/drivers/net/sfc/falcon_xmac.c +++ /dev/null @@ -1,376 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2006-2008 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. - */ - -#include <linux/delay.h> -#include "net_driver.h" -#include "efx.h" -#include "falcon.h" -#include "falcon_hwdefs.h" -#include "falcon_io.h" -#include "mac.h" -#include "mdio_10g.h" -#include "phy.h" -#include "boards.h" -#include "workarounds.h" - -/************************************************************************** - * - * MAC operations - * - *************************************************************************/ - -/* Configure the XAUI driver that is an output from Falcon */ -static void falcon_setup_xaui(struct efx_nic *efx) -{ - efx_oword_t sdctl, txdrv; - - /* Move the XAUI into low power, unless there is no PHY, in - * which case the XAUI will have to drive a cable. */ - if (efx->phy_type == PHY_TYPE_NONE) - return; - - falcon_read(efx, &sdctl, XX_SD_CTL_REG); - EFX_SET_OWORD_FIELD(sdctl, XX_HIDRVD, XX_SD_CTL_DRV_DEFAULT); - EFX_SET_OWORD_FIELD(sdctl, XX_LODRVD, XX_SD_CTL_DRV_DEFAULT); - EFX_SET_OWORD_FIELD(sdctl, XX_HIDRVC, XX_SD_CTL_DRV_DEFAULT); - EFX_SET_OWORD_FIELD(sdctl, XX_LODRVC, XX_SD_CTL_DRV_DEFAULT); - EFX_SET_OWORD_FIELD(sdctl, XX_HIDRVB, XX_SD_CTL_DRV_DEFAULT); - EFX_SET_OWORD_FIELD(sdctl, XX_LODRVB, XX_SD_CTL_DRV_DEFAULT); - EFX_SET_OWORD_FIELD(sdctl, XX_HIDRVA, XX_SD_CTL_DRV_DEFAULT); - EFX_SET_OWORD_FIELD(sdctl, XX_LODRVA, XX_SD_CTL_DRV_DEFAULT); - falcon_write(efx, &sdctl, XX_SD_CTL_REG); - - EFX_POPULATE_OWORD_8(txdrv, - XX_DEQD, XX_TXDRV_DEQ_DEFAULT, - XX_DEQC, XX_TXDRV_DEQ_DEFAULT, - XX_DEQB, XX_TXDRV_DEQ_DEFAULT, - XX_DEQA, XX_TXDRV_DEQ_DEFAULT, - XX_DTXD, XX_TXDRV_DTX_DEFAULT, - XX_DTXC, XX_TXDRV_DTX_DEFAULT, - XX_DTXB, XX_TXDRV_DTX_DEFAULT, - XX_DTXA, XX_TXDRV_DTX_DEFAULT); - falcon_write(efx, &txdrv, XX_TXDRV_CTL_REG); -} - -int falcon_reset_xaui(struct efx_nic *efx) -{ - efx_oword_t reg; - int count; - - EFX_POPULATE_DWORD_1(reg, XX_RST_XX_EN, 1); - falcon_write(efx, ®, XX_PWR_RST_REG); - - /* Give some time for the link to establish */ - for (count = 0; count < 1000; count++) { /* wait upto 10ms */ - falcon_read(efx, ®, XX_PWR_RST_REG); - if (EFX_OWORD_FIELD(reg, XX_RST_XX_EN) == 0) { - falcon_setup_xaui(efx); - return 0; - } - udelay(10); - } - EFX_ERR(efx, "timed out waiting for XAUI/XGXS reset\n"); - return -ETIMEDOUT; -} - -static void falcon_mask_status_intr(struct efx_nic *efx, bool enable) -{ - efx_oword_t reg; - - if ((falcon_rev(efx) != FALCON_REV_B0) || LOOPBACK_INTERNAL(efx)) - return; - - /* We expect xgmii faults if the wireside link is up */ - if (!EFX_WORKAROUND_5147(efx) || !efx->link_up) - return; - - /* We can only use this interrupt to signal the negative edge of - * xaui_align [we have to poll the positive edge]. */ - if (!efx->mac_up) - return; - - /* Flush the ISR */ - if (enable) - falcon_read(efx, ®, XM_MGT_INT_REG_B0); - - EFX_POPULATE_OWORD_2(reg, - XM_MSK_RMTFLT, !enable, - XM_MSK_LCLFLT, !enable); - falcon_write(efx, ®, XM_MGT_INT_MSK_REG_B0); -} - -/* Get status of XAUI link */ -bool falcon_xaui_link_ok(struct efx_nic *efx) -{ - efx_oword_t reg; - bool align_done, link_ok = false; - int sync_status; - - if (LOOPBACK_INTERNAL(efx)) - return true; - - /* Read link status */ - falcon_read(efx, ®, XX_CORE_STAT_REG); - - align_done = EFX_OWORD_FIELD(reg, XX_ALIGN_DONE); - sync_status = EFX_OWORD_FIELD(reg, XX_SYNC_STAT); - if (align_done && (sync_status == XX_SYNC_STAT_DECODE_SYNCED)) - link_ok = true; - - /* Clear link status ready for next read */ - EFX_SET_OWORD_FIELD(reg, XX_COMMA_DET, XX_COMMA_DET_RESET); - EFX_SET_OWORD_FIELD(reg, XX_CHARERR, XX_CHARERR_RESET); - EFX_SET_OWORD_FIELD(reg, XX_DISPERR, XX_DISPERR_RESET); - falcon_write(efx, ®, XX_CORE_STAT_REG); - - /* If the link is up, then check the phy side of the xaui link */ - if (efx->link_up && link_ok) - if (efx->phy_op->mmds & (1 << MDIO_MMD_PHYXS)) - link_ok = mdio_clause45_phyxgxs_lane_sync(efx); - - return link_ok; -} - -static void falcon_reconfigure_xmac_core(struct efx_nic *efx) -{ - unsigned int max_frame_len; - efx_oword_t reg; - bool rx_fc = !!(efx->link_fc & EFX_FC_RX); - - /* Configure MAC - cut-thru mode is hard wired on */ - EFX_POPULATE_DWORD_3(reg, - XM_RX_JUMBO_MODE, 1, - XM_TX_STAT_EN, 1, - XM_RX_STAT_EN, 1); - falcon_write(efx, ®, XM_GLB_CFG_REG); - - /* Configure TX */ - EFX_POPULATE_DWORD_6(reg, - XM_TXEN, 1, - XM_TX_PRMBL, 1, - XM_AUTO_PAD, 1, - XM_TXCRC, 1, - XM_FCNTL, 1, - XM_IPG, 0x3); - falcon_write(efx, ®, XM_TX_CFG_REG); - - /* Configure RX */ - EFX_POPULATE_DWORD_5(reg, - XM_RXEN, 1, - XM_AUTO_DEPAD, 0, - XM_ACPT_ALL_MCAST, 1, - XM_ACPT_ALL_UCAST, efx->promiscuous, - XM_PASS_CRC_ERR, 1); - falcon_write(efx, ®, XM_RX_CFG_REG); - - /* Set frame length */ - max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu); - EFX_POPULATE_DWORD_1(reg, XM_MAX_RX_FRM_SIZE, max_frame_len); - falcon_write(efx, ®, XM_RX_PARAM_REG); - EFX_POPULATE_DWORD_2(reg, - XM_MAX_TX_FRM_SIZE, max_frame_len, - XM_TX_JUMBO_MODE, 1); - falcon_write(efx, ®, XM_TX_PARAM_REG); - - EFX_POPULATE_DWORD_2(reg, - XM_PAUSE_TIME, 0xfffe, /* MAX PAUSE TIME */ - XM_DIS_FCNTL, !rx_fc); - falcon_write(efx, ®, XM_FC_REG); - - /* Set MAC address */ - EFX_POPULATE_DWORD_4(reg, - XM_ADR_0, efx->net_dev->dev_addr[0], - XM_ADR_1, efx->net_dev->dev_addr[1], - XM_ADR_2, efx->net_dev->dev_addr[2], - XM_ADR_3, efx->net_dev->dev_addr[3]); - falcon_write(efx, ®, XM_ADR_LO_REG); - EFX_POPULATE_DWORD_2(reg, - XM_ADR_4, efx->net_dev->dev_addr[4], - XM_ADR_5, efx->net_dev->dev_addr[5]); - falcon_write(efx, ®, XM_ADR_HI_REG); -} - -static void falcon_reconfigure_xgxs_core(struct efx_nic *efx) -{ - efx_oword_t reg; - bool xgxs_loopback = (efx->loopback_mode == LOOPBACK_XGXS); - bool xaui_loopback = (efx->loopback_mode == LOOPBACK_XAUI); - bool xgmii_loopback = (efx->loopback_mode == LOOPBACK_XGMII); - - /* XGXS block is flaky and will need to be reset if moving - * into our out of XGMII, XGXS or XAUI loopbacks. */ - if (EFX_WORKAROUND_5147(efx)) { - bool old_xgmii_loopback, old_xgxs_loopback, old_xaui_loopback; - bool reset_xgxs; - - falcon_read(efx, ®, XX_CORE_STAT_REG); - old_xgxs_loopback = EFX_OWORD_FIELD(reg, XX_XGXS_LB_EN); - old_xgmii_loopback = EFX_OWORD_FIELD(reg, XX_XGMII_LB_EN); - - falcon_read(efx, ®, XX_SD_CTL_REG); - old_xaui_loopback = EFX_OWORD_FIELD(reg, XX_LPBKA); - - /* The PHY driver may have turned XAUI off */ - reset_xgxs = ((xgxs_loopback != old_xgxs_loopback) || - (xaui_loopback != old_xaui_loopback) || - (xgmii_loopback != old_xgmii_loopback)); - - if (reset_xgxs) - falcon_reset_xaui(efx); - } - - falcon_read(efx, ®, XX_CORE_STAT_REG); - EFX_SET_OWORD_FIELD(reg, XX_FORCE_SIG, - (xgxs_loopback || xaui_loopback) ? - XX_FORCE_SIG_DECODE_FORCED : 0); - EFX_SET_OWORD_FIELD(reg, XX_XGXS_LB_EN, xgxs_loopback); - EFX_SET_OWORD_FIELD(reg, XX_XGMII_LB_EN, xgmii_loopback); - falcon_write(efx, ®, XX_CORE_STAT_REG); - - falcon_read(efx, ®, XX_SD_CTL_REG); - EFX_SET_OWORD_FIELD(reg, XX_LPBKD, xaui_loopback); - EFX_SET_OWORD_FIELD(reg, XX_LPBKC, xaui_loopback); - EFX_SET_OWORD_FIELD(reg, XX_LPBKB, xaui_loopback); - EFX_SET_OWORD_FIELD(reg, XX_LPBKA, xaui_loopback); - falcon_write(efx, ®, XX_SD_CTL_REG); -} - - -/* Try and bring the Falcon side of the Falcon-Phy XAUI link fails - * to come back up. Bash it until it comes back up */ -static void falcon_check_xaui_link_up(struct efx_nic *efx, int tries) -{ - efx->mac_up = falcon_xaui_link_ok(efx); - - if ((efx->loopback_mode == LOOPBACK_NETWORK) || - efx_phy_mode_disabled(efx->phy_mode)) - /* XAUI link is expected to be down */ - return; - - while (!efx->mac_up && tries) { - EFX_LOG(efx, "bashing xaui\n"); - falcon_reset_xaui(efx); - udelay(200); - - efx->mac_up = falcon_xaui_link_ok(efx); - --tries; - } -} - -static void falcon_reconfigure_xmac(struct efx_nic *efx) -{ - falcon_mask_status_intr(efx, false); - - falcon_reconfigure_xgxs_core(efx); - falcon_reconfigure_xmac_core(efx); - - falcon_reconfigure_mac_wrapper(efx); - - falcon_check_xaui_link_up(efx, 5); - falcon_mask_status_intr(efx, true); -} - -static void falcon_update_stats_xmac(struct efx_nic *efx) -{ - struct efx_mac_stats *mac_stats = &efx->mac_stats; - int rc; - - rc = falcon_dma_stats(efx, XgDmaDone_offset); - if (rc) - return; - - /* Update MAC stats from DMAed values */ - FALCON_STAT(efx, XgRxOctets, rx_bytes); - FALCON_STAT(efx, XgRxOctetsOK, rx_good_bytes); - FALCON_STAT(efx, XgRxPkts, rx_packets); - FALCON_STAT(efx, XgRxPktsOK, rx_good); - FALCON_STAT(efx, XgRxBroadcastPkts, rx_broadcast); - FALCON_STAT(efx, XgRxMulticastPkts, rx_multicast); - FALCON_STAT(efx, XgRxUnicastPkts, rx_unicast); - FALCON_STAT(efx, XgRxUndersizePkts, rx_lt64); - FALCON_STAT(efx, XgRxOversizePkts, rx_gtjumbo); - FALCON_STAT(efx, XgRxJabberPkts, rx_bad_gtjumbo); - FALCON_STAT(efx, XgRxUndersizeFCSerrorPkts, rx_bad_lt64); - FALCON_STAT(efx, XgRxDropEvents, rx_overflow); - FALCON_STAT(efx, XgRxFCSerrorPkts, rx_bad); - FALCON_STAT(efx, XgRxAlignError, rx_align_error); - FALCON_STAT(efx, XgRxSymbolError, rx_symbol_error); - FALCON_STAT(efx, XgRxInternalMACError, rx_internal_error); - FALCON_STAT(efx, XgRxControlPkts, rx_control); - FALCON_STAT(efx, XgRxPausePkts, rx_pause); - FALCON_STAT(efx, XgRxPkts64Octets, rx_64); - FALCON_STAT(efx, XgRxPkts65to127Octets, rx_65_to_127); - FALCON_STAT(efx, XgRxPkts128to255Octets, rx_128_to_255); - FALCON_STAT(efx, XgRxPkts256to511Octets, rx_256_to_511); - FALCON_STAT(efx, XgRxPkts512to1023Octets, rx_512_to_1023); - FALCON_STAT(efx, XgRxPkts1024to15xxOctets, rx_1024_to_15xx); - FALCON_STAT(efx, XgRxPkts15xxtoMaxOctets, rx_15xx_to_jumbo); - FALCON_STAT(efx, XgRxLengthError, rx_length_error); - FALCON_STAT(efx, XgTxPkts, tx_packets); - FALCON_STAT(efx, XgTxOctets, tx_bytes); - FALCON_STAT(efx, XgTxMulticastPkts, tx_multicast); - FALCON_STAT(efx, XgTxBroadcastPkts, tx_broadcast); - FALCON_STAT(efx, XgTxUnicastPkts, tx_unicast); - FALCON_STAT(efx, XgTxControlPkts, tx_control); - FALCON_STAT(efx, XgTxPausePkts, tx_pause); - FALCON_STAT(efx, XgTxPkts64Octets, tx_64); - FALCON_STAT(efx, XgTxPkts65to127Octets, tx_65_to_127); - FALCON_STAT(efx, XgTxPkts128to255Octets, tx_128_to_255); - FALCON_STAT(efx, XgTxPkts256to511Octets, tx_256_to_511); - FALCON_STAT(efx, XgTxPkts512to1023Octets, tx_512_to_1023); - FALCON_STAT(efx, XgTxPkts1024to15xxOctets, tx_1024_to_15xx); - FALCON_STAT(efx, XgTxPkts1519toMaxOctets, tx_15xx_to_jumbo); - FALCON_STAT(efx, XgTxUndersizePkts, tx_lt64); - FALCON_STAT(efx, XgTxOversizePkts, tx_gtjumbo); - FALCON_STAT(efx, XgTxNonTcpUdpPkt, tx_non_tcpudp); - FALCON_STAT(efx, XgTxMacSrcErrPkt, tx_mac_src_error); - FALCON_STAT(efx, XgTxIpSrcErrPkt, tx_ip_src_error); - - /* Update derived statistics */ - mac_stats->tx_good_bytes = - (mac_stats->tx_bytes - mac_stats->tx_bad_bytes - - mac_stats->tx_control * 64); - mac_stats->rx_bad_bytes = - (mac_stats->rx_bytes - mac_stats->rx_good_bytes - - mac_stats->rx_control * 64); -} - -static void falcon_xmac_irq(struct efx_nic *efx) -{ - /* The XGMII link has a transient fault, which indicates either: - * - there's a transient xgmii fault - * - falcon's end of the xaui link may need a kick - * - the wire-side link may have gone down, but the lasi/poll() - * hasn't noticed yet. - * - * We only want to even bother polling XAUI if we're confident it's - * not (1) or (3). In both cases, the only reliable way to spot this - * is to wait a bit. We do this here by forcing the mac link state - * to down, and waiting for the mac poll to come round and check - */ - efx->mac_up = false; -} - -static void falcon_poll_xmac(struct efx_nic *efx) -{ - if (!EFX_WORKAROUND_5147(efx) || !efx->link_up || efx->mac_up) - return; - - falcon_mask_status_intr(efx, false); - falcon_check_xaui_link_up(efx, 1); - falcon_mask_status_intr(efx, true); -} - -struct efx_mac_operations falcon_xmac_operations = { - .reconfigure = falcon_reconfigure_xmac, - .update_stats = falcon_update_stats_xmac, - .irq = falcon_xmac_irq, - .poll = falcon_poll_xmac, -}; diff --git a/drivers/net/sfc/gmii.h b/drivers/net/sfc/gmii.h deleted file mode 100644 index dfccaa7b573..00000000000 --- a/drivers/net/sfc/gmii.h +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2006-2008 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_GMII_H -#define EFX_GMII_H - -/* - * GMII interface - */ - -#include <linux/mii.h> - -/* GMII registers, excluding registers already defined as MII - * registers in mii.h - */ -#define GMII_IER 0x12 /* Interrupt enable register */ -#define GMII_ISR 0x13 /* Interrupt status register */ - -/* Interrupt enable register */ -#define IER_ANEG_ERR 0x8000 /* Bit 15 - autonegotiation error */ -#define IER_SPEED_CHG 0x4000 /* Bit 14 - speed changed */ -#define IER_DUPLEX_CHG 0x2000 /* Bit 13 - duplex changed */ -#define IER_PAGE_RCVD 0x1000 /* Bit 12 - page received */ -#define IER_ANEG_DONE 0x0800 /* Bit 11 - autonegotiation complete */ -#define IER_LINK_CHG 0x0400 /* Bit 10 - link status changed */ -#define IER_SYM_ERR 0x0200 /* Bit 9 - symbol error */ -#define IER_FALSE_CARRIER 0x0100 /* Bit 8 - false carrier */ -#define IER_FIFO_ERR 0x0080 /* Bit 7 - FIFO over/underflow */ -#define IER_MDIX_CHG 0x0040 /* Bit 6 - MDI crossover changed */ -#define IER_DOWNSHIFT 0x0020 /* Bit 5 - downshift */ -#define IER_ENERGY 0x0010 /* Bit 4 - energy detect */ -#define IER_DTE_POWER 0x0004 /* Bit 2 - DTE power detect */ -#define IER_POLARITY_CHG 0x0002 /* Bit 1 - polarity changed */ -#define IER_JABBER 0x0001 /* Bit 0 - jabber */ - -/* Interrupt status register */ -#define ISR_ANEG_ERR 0x8000 /* Bit 15 - autonegotiation error */ -#define ISR_SPEED_CHG 0x4000 /* Bit 14 - speed changed */ -#define ISR_DUPLEX_CHG 0x2000 /* Bit 13 - duplex changed */ -#define ISR_PAGE_RCVD 0x1000 /* Bit 12 - page received */ -#define ISR_ANEG_DONE 0x0800 /* Bit 11 - autonegotiation complete */ -#define ISR_LINK_CHG 0x0400 /* Bit 10 - link status changed */ -#define ISR_SYM_ERR 0x0200 /* Bit 9 - symbol error */ -#define ISR_FALSE_CARRIER 0x0100 /* Bit 8 - false carrier */ -#define ISR_FIFO_ERR 0x0080 /* Bit 7 - FIFO over/underflow */ -#define ISR_MDIX_CHG 0x0040 /* Bit 6 - MDI crossover changed */ -#define ISR_DOWNSHIFT 0x0020 /* Bit 5 - downshift */ -#define ISR_ENERGY 0x0010 /* Bit 4 - energy detect */ -#define ISR_DTE_POWER 0x0004 /* Bit 2 - DTE power detect */ -#define ISR_POLARITY_CHG 0x0002 /* Bit 1 - polarity changed */ -#define ISR_JABBER 0x0001 /* Bit 0 - jabber */ - -#endif /* EFX_GMII_H */ diff --git a/drivers/net/sfc/mac.h b/drivers/net/sfc/mac.h deleted file mode 100644 index 4e7074278fe..00000000000 --- a/drivers/net/sfc/mac.h +++ /dev/null @@ -1,19 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2006-2008 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_MAC_H -#define EFX_MAC_H - -#include "net_driver.h" - -extern struct efx_mac_operations falcon_gmac_operations; -extern struct efx_mac_operations falcon_xmac_operations; - -#endif diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c deleted file mode 100644 index f9e2f95c3b4..00000000000 --- a/drivers/net/sfc/mdio_10g.c +++ /dev/null @@ -1,566 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2006-2008 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. - */ -/* - * Useful functions for working with MDIO clause 45 PHYs - */ -#include <linux/types.h> -#include <linux/ethtool.h> -#include <linux/delay.h> -#include "net_driver.h" -#include "mdio_10g.h" -#include "boards.h" -#include "workarounds.h" - -int mdio_clause45_reset_mmd(struct efx_nic *port, int mmd, - int spins, int spintime) -{ - u32 ctrl; - int phy_id = port->mii.phy_id; - - /* Catch callers passing values in the wrong units (or just silly) */ - EFX_BUG_ON_PARANOID(spins * spintime >= 5000); - - mdio_clause45_write(port, phy_id, mmd, MDIO_MMDREG_CTRL1, - (1 << MDIO_MMDREG_CTRL1_RESET_LBN)); - /* Wait for the reset bit to clear. */ - do { - msleep(spintime); - ctrl = mdio_clause45_read(port, phy_id, mmd, MDIO_MMDREG_CTRL1); - spins--; - - } while (spins && (ctrl & (1 << MDIO_MMDREG_CTRL1_RESET_LBN))); - - return spins ? spins : -ETIMEDOUT; -} - -static int mdio_clause45_check_mmd(struct efx_nic *efx, int mmd, - int fault_fatal) -{ - int status; - int phy_id = efx->mii.phy_id; - - if (LOOPBACK_INTERNAL(efx)) - return 0; - - if (mmd != MDIO_MMD_AN) { - /* Read MMD STATUS2 to check it is responding. */ - status = mdio_clause45_read(efx, phy_id, mmd, - MDIO_MMDREG_STAT2); - if (((status >> MDIO_MMDREG_STAT2_PRESENT_LBN) & - ((1 << MDIO_MMDREG_STAT2_PRESENT_WIDTH) - 1)) != - MDIO_MMDREG_STAT2_PRESENT_VAL) { - EFX_ERR(efx, "PHY MMD %d not responding.\n", mmd); - return -EIO; - } - } - - /* Read MMD STATUS 1 to check for fault. */ - status = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_STAT1); - if ((status & (1 << MDIO_MMDREG_STAT1_FAULT_LBN)) != 0) { - if (fault_fatal) { - EFX_ERR(efx, "PHY MMD %d reporting fatal" - " fault: status %x\n", mmd, status); - return -EIO; - } else { - EFX_LOG(efx, "PHY MMD %d reporting status" - " %x (expected)\n", mmd, status); - } - } - return 0; -} - -/* This ought to be ridiculous overkill. We expect it to fail rarely */ -#define MDIO45_RESET_TIME 1000 /* ms */ -#define MDIO45_RESET_ITERS 100 - -int mdio_clause45_wait_reset_mmds(struct efx_nic *efx, - unsigned int mmd_mask) -{ - const int spintime = MDIO45_RESET_TIME / MDIO45_RESET_ITERS; - int tries = MDIO45_RESET_ITERS; - int rc = 0; - int in_reset; - - while (tries) { - int mask = mmd_mask; - int mmd = 0; - int stat; - in_reset = 0; - while (mask) { - if (mask & 1) { - stat = mdio_clause45_read(efx, - efx->mii.phy_id, - mmd, - MDIO_MMDREG_CTRL1); - if (stat < 0) { - EFX_ERR(efx, "failed to read status of" - " MMD %d\n", mmd); - return -EIO; - } - if (stat & (1 << MDIO_MMDREG_CTRL1_RESET_LBN)) - in_reset |= (1 << mmd); - } - mask = mask >> 1; - mmd++; - } - if (!in_reset) - break; - tries--; - msleep(spintime); - } - if (in_reset != 0) { - EFX_ERR(efx, "not all MMDs came out of reset in time." - " MMDs still in reset: %x\n", in_reset); - rc = -ETIMEDOUT; - } - return rc; -} - -int mdio_clause45_check_mmds(struct efx_nic *efx, - unsigned int mmd_mask, unsigned int fatal_mask) -{ - u32 devices; - int mmd = 0, probe_mmd; - - /* Historically we have probed the PHYXS to find out what devices are - * present,but that doesn't work so well if the PHYXS isn't expected - * to exist, if so just find the first item in the list supplied. */ - probe_mmd = (mmd_mask & MDIO_MMDREG_DEVS_PHYXS) ? MDIO_MMD_PHYXS : - __ffs(mmd_mask); - devices = (mdio_clause45_read(efx, efx->mii.phy_id, - probe_mmd, MDIO_MMDREG_DEVS0) | - mdio_clause45_read(efx, efx->mii.phy_id, - probe_mmd, MDIO_MMDREG_DEVS1) << 16); - - /* Check all the expected MMDs are present */ - if (devices < 0) { - EFX_ERR(efx, "failed to read devices present\n"); - return -EIO; - } - if ((devices & mmd_mask) != mmd_mask) { - EFX_ERR(efx, "required MMDs not present: got %x, " - "wanted %x\n", devices, mmd_mask); - return -ENODEV; - } - EFX_TRACE(efx, "Devices present: %x\n", devices); - - /* Check all required MMDs are responding and happy. */ - while (mmd_mask) { - if (mmd_mask & 1) { - int fault_fatal = fatal_mask & 1; - if (mdio_clause45_check_mmd(efx, mmd, fault_fatal)) - return -EIO; - } - mmd_mask = mmd_mask >> 1; - fatal_mask = fatal_mask >> 1; - mmd++; - } - - return 0; -} - -bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask) -{ - int phy_id = efx->mii.phy_id; - u32 reg; - bool ok = true; - int mmd = 0; - - /* If the port is in loopback, then we should only consider a subset - * of mmd's */ - if (LOOPBACK_INTERNAL(efx)) - return true; - else if (efx->loopback_mode == LOOPBACK_NETWORK) - return false; - else if (efx_phy_mode_disabled(efx->phy_mode)) - return false; - else if (efx->loopback_mode == LOOPBACK_PHYXS) - mmd_mask &= ~(MDIO_MMDREG_DEVS_PHYXS | - MDIO_MMDREG_DEVS_PCS | - MDIO_MMDREG_DEVS_PMAPMD | - MDIO_MMDREG_DEVS_AN); - else if (efx->loopback_mode == LOOPBACK_PCS) - mmd_mask &= ~(MDIO_MMDREG_DEVS_PCS | - MDIO_MMDREG_DEVS_PMAPMD | - MDIO_MMDREG_DEVS_AN); - else if (efx->loopback_mode == LOOPBACK_PMAPMD) - mmd_mask &= ~(MDIO_MMDREG_DEVS_PMAPMD | - MDIO_MMDREG_DEVS_AN); - - if (!mmd_mask) { - /* Use presence of XGMII faults in leui of link state */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS, - MDIO_PHYXS_STATUS2); - return !(reg & (1 << MDIO_PHYXS_STATUS2_RX_FAULT_LBN)); - } - - while (mmd_mask) { - if (mmd_mask & 1) { - /* Double reads because link state is latched, and a - * read moves the current state into the register */ - reg = mdio_clause45_read(efx, phy_id, - mmd, MDIO_MMDREG_STAT1); - reg = mdio_clause45_read(efx, phy_id, - mmd, MDIO_MMDREG_STAT1); - ok = ok && (reg & (1 << MDIO_MMDREG_STAT1_LINK_LBN)); - } - mmd_mask = (mmd_mask >> 1); - mmd++; - } - return ok; -} - -void mdio_clause45_transmit_disable(struct efx_nic *efx) -{ - mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_TXDIS, MDIO_MMDREG_TXDIS_GLOBAL_LBN, - efx->phy_mode & PHY_MODE_TX_DISABLED); -} - -void mdio_clause45_phy_reconfigure(struct efx_nic *efx) -{ - int phy_id = efx->mii.phy_id; - - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_CTRL1, MDIO_PMAPMD_CTRL1_LBACK_LBN, - efx->loopback_mode == LOOPBACK_PMAPMD); - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PCS, - MDIO_MMDREG_CTRL1, MDIO_MMDREG_CTRL1_LBACK_LBN, - efx->loopback_mode == LOOPBACK_PCS); - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PHYXS, - MDIO_MMDREG_CTRL1, MDIO_MMDREG_CTRL1_LBACK_LBN, - efx->loopback_mode == LOOPBACK_NETWORK); -} - -static void mdio_clause45_set_mmd_lpower(struct efx_nic *efx, - int lpower, int mmd) -{ - int phy = efx->mii.phy_id; - int stat = mdio_clause45_read(efx, phy, mmd, MDIO_MMDREG_STAT1); - - EFX_TRACE(efx, "Setting low power mode for MMD %d to %d\n", - mmd, lpower); - - if (stat & (1 << MDIO_MMDREG_STAT1_LPABLE_LBN)) { - mdio_clause45_set_flag(efx, phy, mmd, MDIO_MMDREG_CTRL1, - MDIO_MMDREG_CTRL1_LPOWER_LBN, lpower); - } -} - -void mdio_clause45_set_mmds_lpower(struct efx_nic *efx, - int low_power, unsigned int mmd_mask) -{ - int mmd = 0; - mmd_mask &= ~MDIO_MMDREG_DEVS_AN; - while (mmd_mask) { - if (mmd_mask & 1) - mdio_clause45_set_mmd_lpower(efx, low_power, mmd); - mmd_mask = (mmd_mask >> 1); - mmd++; - } -} - -static u32 mdio_clause45_get_an(struct efx_nic *efx, u16 addr) -{ - int phy_id = efx->mii.phy_id; - u32 result = 0; - int reg; - - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, addr); - if (reg & ADVERTISE_10HALF) - result |= ADVERTISED_10baseT_Half; - if (reg & ADVERTISE_10FULL) - result |= ADVERTISED_10baseT_Full; - if (reg & ADVERTISE_100HALF) - result |= ADVERTISED_100baseT_Half; - if (reg & ADVERTISE_100FULL) - result |= ADVERTISED_100baseT_Full; - return result; -} - -/** - * mdio_clause45_get_settings - Read (some of) the PHY settings over MDIO. - * @efx: Efx NIC - * @ecmd: Buffer for settings - * - * On return the 'port', 'speed', 'supported' and 'advertising' fields of - * ecmd have been filled out. - */ -void mdio_clause45_get_settings(struct efx_nic *efx, - struct ethtool_cmd *ecmd) -{ - mdio_clause45_get_settings_ext(efx, ecmd, 0, 0); -} - -/** - * mdio_clause45_get_settings_ext - Read (some of) the PHY settings over MDIO. - * @efx: Efx NIC - * @ecmd: Buffer for settings - * @xnp: Advertised Extended Next Page state - * @xnp_lpa: Link Partner's advertised XNP state - * - * On return the 'port', 'speed', 'supported' and 'advertising' fields of - * ecmd have been filled out. - */ -void mdio_clause45_get_settings_ext(struct efx_nic *efx, - struct ethtool_cmd *ecmd, - u32 npage_adv, u32 npage_lpa) -{ - int phy_id = efx->mii.phy_id; - int reg; - - ecmd->transceiver = XCVR_INTERNAL; - ecmd->phy_address = phy_id; - - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_CTRL2); - switch (reg & MDIO_PMAPMD_CTRL2_TYPE_MASK) { - case MDIO_PMAPMD_CTRL2_10G_BT: - case MDIO_PMAPMD_CTRL2_1G_BT: - case MDIO_PMAPMD_CTRL2_100_BT: - case MDIO_PMAPMD_CTRL2_10_BT: - ecmd->port = PORT_TP; - ecmd->supported = SUPPORTED_TP; - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_SPEED); - if (reg & (1 << MDIO_MMDREG_SPEED_10G_LBN)) - ecmd->supported |= SUPPORTED_10000baseT_Full; - if (reg & (1 << MDIO_MMDREG_SPEED_1000M_LBN)) - ecmd->supported |= (SUPPORTED_1000baseT_Full | - SUPPORTED_1000baseT_Half); - if (reg & (1 << MDIO_MMDREG_SPEED_100M_LBN)) - ecmd->supported |= (SUPPORTED_100baseT_Full | - SUPPORTED_100baseT_Half); - if (reg & (1 << MDIO_MMDREG_SPEED_10M_LBN)) - ecmd->supported |= (SUPPORTED_10baseT_Full | - SUPPORTED_10baseT_Half); - ecmd->advertising = ADVERTISED_TP; - break; - - /* We represent CX4 as fibre in the absence of anything better */ - case MDIO_PMAPMD_CTRL2_10G_CX4: - /* All the other defined modes are flavours of optical */ - default: - ecmd->port = PORT_FIBRE; - ecmd->supported = SUPPORTED_FIBRE; - ecmd->advertising = ADVERTISED_FIBRE; - break; - } - - if (efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) { - ecmd->supported |= SUPPORTED_Autoneg; - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1); - if (reg & BMCR_ANENABLE) { - ecmd->autoneg = AUTONEG_ENABLE; - ecmd->advertising |= - ADVERTISED_Autoneg | - mdio_clause45_get_an(efx, MDIO_AN_ADVERTISE) | - npage_adv; - } else - ecmd->autoneg = AUTONEG_DISABLE; - } else - ecmd->autoneg = AUTONEG_DISABLE; - - if (ecmd->autoneg) { - /* If AN is complete, report best common mode, - * otherwise report best advertised mode. */ - u32 modes = 0; - if (mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_STAT1) & - (1 << MDIO_AN_STATUS_AN_DONE_LBN)) - modes = (ecmd->advertising & - (mdio_clause45_get_an(efx, MDIO_AN_LPA) | - npage_lpa)); - if (modes == 0) - modes = ecmd->advertising; - - if (modes & ADVERTISED_10000baseT_Full) { - ecmd->speed = SPEED_10000; - ecmd->duplex = DUPLEX_FULL; - } else if (modes & (ADVERTISED_1000baseT_Full | - ADVERTISED_1000baseT_Half)) { - ecmd->speed = SPEED_1000; - ecmd->duplex = !!(modes & ADVERTISED_1000baseT_Full); - } else if (modes & (ADVERTISED_100baseT_Full | - ADVERTISED_100baseT_Half)) { - ecmd->speed = SPEED_100; - ecmd->duplex = !!(modes & ADVERTISED_100baseT_Full); - } else { - ecmd->speed = SPEED_10; - ecmd->duplex = !!(modes & ADVERTISED_10baseT_Full); - } - } else { - /* Report forced settings */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_CTRL1); - ecmd->speed = (((reg & BMCR_SPEED1000) ? 100 : 1) * - ((reg & BMCR_SPEED100) ? 100 : 10)); - ecmd->duplex = (reg & BMCR_FULLDPLX || - ecmd->speed == SPEED_10000); - } -} - -/** - * mdio_clause45_set_settings - Set (some of) the PHY settings over MDIO. - * @efx: Efx NIC - * @ecmd: New settings - */ -int mdio_clause45_set_settings(struct efx_nic *efx, - struct ethtool_cmd *ecmd) -{ - int phy_id = efx->mii.phy_id; - struct ethtool_cmd prev; - u32 required; - int reg; - - efx->phy_op->get_settings(efx, &prev); - - if (ecmd->advertising == prev.advertising && - ecmd->speed == prev.speed && - ecmd->duplex == prev.duplex && - ecmd->port == prev.port && - ecmd->autoneg == prev.autoneg) - return 0; - - /* We can only change these settings for -T PHYs */ - if (prev.port != PORT_TP || ecmd->port != PORT_TP) - return -EINVAL; - - /* Check that PHY supports these settings */ - if (ecmd->autoneg) { - required = SUPPORTED_Autoneg; - } else if (ecmd->duplex) { - switch (ecmd->speed) { - case SPEED_10: required = SUPPORTED_10baseT_Full; break; - case SPEED_100: required = SUPPORTED_100baseT_Full; break; - default: return -EINVAL; - } - } else { - switch (ecmd->speed) { - case SPEED_10: required = SUPPORTED_10baseT_Half; break; - case SPEED_100: required = SUPPORTED_100baseT_Half; break; - default: return -EINVAL; - } - } - required |= ecmd->advertising; - if (required & ~prev.supported) - return -EINVAL; - - if (ecmd->autoneg) { - bool xnp = (ecmd->advertising & ADVERTISED_10000baseT_Full - || EFX_WORKAROUND_13204(efx)); - - /* Set up the base page */ - reg = ADVERTISE_CSMA; - if (ecmd->advertising & ADVERTISED_10baseT_Half) - reg |= ADVERTISE_10HALF; - if (ecmd->advertising & ADVERTISED_10baseT_Full) - reg |= ADVERTISE_10FULL; - if (ecmd->advertising & ADVERTISED_100baseT_Half) - reg |= ADVERTISE_100HALF; - if (ecmd->advertising & ADVERTISED_100baseT_Full) - reg |= ADVERTISE_100FULL; - if (xnp) - reg |= ADVERTISE_RESV; - else if (ecmd->advertising & (ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full)) - reg |= ADVERTISE_NPAGE; - reg |= efx_fc_advertise(efx->wanted_fc); - mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_ADVERTISE, reg); - - /* Set up the (extended) next page if necessary */ - if (efx->phy_op->set_npage_adv) - efx->phy_op->set_npage_adv(efx, ecmd->advertising); - - /* Enable and restart AN */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1); - reg |= BMCR_ANENABLE; - if (!(EFX_WORKAROUND_15195(efx) && - LOOPBACK_MASK(efx) & efx->phy_op->loopbacks)) - reg |= BMCR_ANRESTART; - if (xnp) - reg |= 1 << MDIO_AN_CTRL_XNP_LBN; - else - reg &= ~(1 << MDIO_AN_CTRL_XNP_LBN); - mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1, reg); - } else { - /* Disable AN */ - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1, - __ffs(BMCR_ANENABLE), false); - - /* Set the basic control bits */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_CTRL1); - reg &= ~(BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX | - 0x003c); - if (ecmd->speed == SPEED_100) - reg |= BMCR_SPEED100; - if (ecmd->duplex) - reg |= BMCR_FULLDPLX; - mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_CTRL1, reg); - } - - return 0; -} - -void mdio_clause45_set_pause(struct efx_nic *efx) -{ - int phy_id = efx->mii.phy_id; - int reg; - - if (efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) { - /* Set pause capability advertising */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_ADVERTISE); - reg &= ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); - reg |= efx_fc_advertise(efx->wanted_fc); - mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_ADVERTISE, reg); - - /* Restart auto-negotiation */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1); - if (reg & BMCR_ANENABLE) { - reg |= BMCR_ANRESTART; - mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1, reg); - } - } -} - -enum efx_fc_type mdio_clause45_get_pause(struct efx_nic *efx) -{ - int phy_id = efx->mii.phy_id; - int lpa; - - if (!(efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN))) - return efx->wanted_fc; - lpa = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, MDIO_AN_LPA); - return efx_fc_resolve(efx->wanted_fc, lpa); -} - -void mdio_clause45_set_flag(struct efx_nic *efx, u8 prt, u8 dev, - u16 addr, int bit, bool sense) -{ - int old_val = mdio_clause45_read(efx, prt, dev, addr); - int new_val; - - if (sense) - new_val = old_val | (1 << bit); - else - new_val = old_val & ~(1 << bit); - if (old_val != new_val) - mdio_clause45_write(efx, prt, dev, addr, new_val); -} diff --git a/drivers/net/sfc/mdio_10g.h b/drivers/net/sfc/mdio_10g.h deleted file mode 100644 index 8ba49773ce7..00000000000 --- a/drivers/net/sfc/mdio_10g.h +++ /dev/null @@ -1,311 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2006-2008 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_MDIO_10G_H -#define EFX_MDIO_10G_H - -/* - * Definitions needed for doing 10G MDIO as specified in clause 45 - * MDIO, which do not appear in Linux yet. Also some helper functions. - */ - -#include "efx.h" -#include "boards.h" - -/* Numbering of the MDIO Manageable Devices (MMDs) */ -/* Physical Medium Attachment/ Physical Medium Dependent sublayer */ -#define MDIO_MMD_PMAPMD (1) -/* WAN Interface Sublayer */ -#define MDIO_MMD_WIS (2) -/* Physical Coding Sublayer */ -#define MDIO_MMD_PCS (3) -/* PHY Extender Sublayer */ -#define MDIO_MMD_PHYXS (4) -/* Extender Sublayer */ -#define MDIO_MMD_DTEXS (5) -/* Transmission convergence */ -#define MDIO_MMD_TC (6) -/* Auto negotiation */ -#define MDIO_MMD_AN (7) -/* Clause 22 extension */ -#define MDIO_MMD_C22EXT 29 - -/* Generic register locations */ -#define MDIO_MMDREG_CTRL1 (0) -#define MDIO_MMDREG_STAT1 (1) -#define MDIO_MMDREG_IDHI (2) -#define MDIO_MMDREG_IDLOW (3) -#define MDIO_MMDREG_SPEED (4) -#define MDIO_MMDREG_DEVS0 (5) -#define MDIO_MMDREG_DEVS1 (6) -#define MDIO_MMDREG_CTRL2 (7) -#define MDIO_MMDREG_STAT2 (8) -#define MDIO_MMDREG_TXDIS (9) - -/* Bits in MMDREG_CTRL1 */ -/* Reset */ -#define MDIO_MMDREG_CTRL1_RESET_LBN (15) -#define MDIO_MMDREG_CTRL1_RESET_WIDTH (1) -/* Loopback */ -/* Loopback bit for WIS, PCS, PHYSX and DTEXS */ -#define MDIO_MMDREG_CTRL1_LBACK_LBN (14) -#define MDIO_MMDREG_CTRL1_LBACK_WIDTH (1) -/* Low power */ -#define MDIO_MMDREG_CTRL1_LPOWER_LBN (11) -#define MDIO_MMDREG_CTRL1_LPOWER_WIDTH (1) - -/* Bits in MMDREG_STAT1 */ -#define MDIO_MMDREG_STAT1_FAULT_LBN (7) -#define MDIO_MMDREG_STAT1_FAULT_WIDTH (1) -/* Link state */ -#define MDIO_MMDREG_STAT1_LINK_LBN (2) -#define MDIO_MMDREG_STAT1_LINK_WIDTH (1) -/* Low power ability */ -#define MDIO_MMDREG_STAT1_LPABLE_LBN (1) -#define MDIO_MMDREG_STAT1_LPABLE_WIDTH (1) - -/* Bits in ID reg */ -#define MDIO_ID_REV(_id32) (_id32 & 0xf) -#define MDIO_ID_MODEL(_id32) ((_id32 >> 4) & 0x3f) -#define MDIO_ID_OUI(_id32) (_id32 >> 10) - -/* Bits in MMDREG_DEVS0/1. Someone thoughtfully layed things out - * so the 'bit present' bit number of an MMD is the number of - * that MMD */ -#define DEV_PRESENT_BIT(_b) (1 << _b) - -#define MDIO_MMDREG_DEVS_PHYXS DEV_PRESENT_BIT(MDIO_MMD_PHYXS) -#define MDIO_MMDREG_DEVS_PCS DEV_PRESENT_BIT(MDIO_MMD_PCS) -#define MDIO_MMDREG_DEVS_PMAPMD DEV_PRESENT_BIT(MDIO_MMD_PMAPMD) -#define MDIO_MMDREG_DEVS_AN DEV_PRESENT_BIT(MDIO_MMD_AN) -#define MDIO_MMDREG_DEVS_C22EXT DEV_PRESENT_BIT(MDIO_MMD_C22EXT) - -/* Bits in MMDREG_SPEED */ -#define MDIO_MMDREG_SPEED_10G_LBN 0 -#define MDIO_MMDREG_SPEED_10G_WIDTH 1 -#define MDIO_MMDREG_SPEED_1000M_LBN 4 -#define MDIO_MMDREG_SPEED_1000M_WIDTH 1 -#define MDIO_MMDREG_SPEED_100M_LBN 5 -#define MDIO_MMDREG_SPEED_100M_WIDTH 1 -#define MDIO_MMDREG_SPEED_10M_LBN 6 -#define MDIO_MMDREG_SPEED_10M_WIDTH 1 - -/* Bits in MMDREG_STAT2 */ -#define MDIO_MMDREG_STAT2_PRESENT_VAL (2) -#define MDIO_MMDREG_STAT2_PRESENT_LBN (14) -#define MDIO_MMDREG_STAT2_PRESENT_WIDTH (2) - -/* Bits in MMDREG_TXDIS */ -#define MDIO_MMDREG_TXDIS_GLOBAL_LBN (0) -#define MDIO_MMDREG_TXDIS_GLOBAL_WIDTH (1) - -/* MMD-specific bits, ordered by MMD, then register */ -#define MDIO_PMAPMD_CTRL1_LBACK_LBN (0) -#define MDIO_PMAPMD_CTRL1_LBACK_WIDTH (1) - -/* PMA type (4 bits) */ -#define MDIO_PMAPMD_CTRL2_10G_CX4 (0x0) -#define MDIO_PMAPMD_CTRL2_10G_EW (0x1) -#define MDIO_PMAPMD_CTRL2_10G_LW (0x2) -#define MDIO_PMAPMD_CTRL2_10G_SW (0x3) -#define MDIO_PMAPMD_CTRL2_10G_LX4 (0x4) -#define MDIO_PMAPMD_CTRL2_10G_ER (0x5) -#define MDIO_PMAPMD_CTRL2_10G_LR (0x6) -#define MDIO_PMAPMD_CTRL2_10G_SR (0x7) -/* Reserved */ -#define MDIO_PMAPMD_CTRL2_10G_BT (0x9) -/* Reserved */ -/* Reserved */ -#define MDIO_PMAPMD_CTRL2_1G_BT (0xc) -/* Reserved */ -#define MDIO_PMAPMD_CTRL2_100_BT (0xe) -#define MDIO_PMAPMD_CTRL2_10_BT (0xf) -#define MDIO_PMAPMD_CTRL2_TYPE_MASK (0xf) - -/* PMA 10GBT registers */ -#define MDIO_PMAPMD_10GBT_TXPWR (131) -#define MDIO_PMAPMD_10GBT_TXPWR_SHORT_LBN (0) -#define MDIO_PMAPMD_10GBT_TXPWR_SHORT_WIDTH (1) - -/* PHY XGXS Status 2 */ -#define MDIO_PHYXS_STATUS2 (8) -#define MDIO_PHYXS_STATUS2_RX_FAULT_LBN 10 - -/* PHY XGXS lane state */ -#define MDIO_PHYXS_LANE_STATE (0x18) -#define MDIO_PHYXS_LANE_ALIGNED_LBN (12) - -/* AN registers */ -#define MDIO_AN_CTRL_XNP_LBN 13 -#define MDIO_AN_STATUS (1) -#define MDIO_AN_STATUS_XNP_LBN (7) -#define MDIO_AN_STATUS_PAGE_LBN (6) -#define MDIO_AN_STATUS_AN_DONE_LBN (5) -#define MDIO_AN_STATUS_LP_AN_CAP_LBN (0) - -#define MDIO_AN_ADVERTISE 16 -#define MDIO_AN_ADVERTISE_XNP_LBN 12 -#define MDIO_AN_LPA 19 -#define MDIO_AN_XNP 22 -#define MDIO_AN_LPA_XNP 25 - -#define MDIO_AN_10GBT_CTRL 32 -#define MDIO_AN_10GBT_CTRL_ADV_10G_LBN 12 -#define MDIO_AN_10GBT_STATUS (33) -#define MDIO_AN_10GBT_STATUS_MS_FLT_LBN (15) /* MASTER/SLAVE config fault */ -#define MDIO_AN_10GBT_STATUS_MS_LBN (14) /* MASTER/SLAVE config */ -#define MDIO_AN_10GBT_STATUS_LOC_OK_LBN (13) /* Local OK */ -#define MDIO_AN_10GBT_STATUS_REM_OK_LBN (12) /* Remote OK */ -#define MDIO_AN_10GBT_STATUS_LP_10G_LBN (11) /* Link partner is 10GBT capable */ -#define MDIO_AN_10GBT_STATUS_LP_LTA_LBN (10) /* LP loop timing ability */ -#define MDIO_AN_10GBT_STATUS_LP_TRR_LBN (9) /* LP Training Reset Request */ - - -/* Packing of the prt and dev arguments of clause 45 style MDIO into a - * single int so they can be passed into the mdio_read/write functions - * that currently exist. Note that as Falcon is the only current user, - * the packed form is chosen to match what Falcon needs to write into - * a register. This is checked at compile-time so do not change it. If - * your target chip needs things layed out differently you will need - * to unpack the arguments in your chip-specific mdio functions. - */ - /* These are defined by the standard. */ -#define MDIO45_PRT_ID_WIDTH (5) -#define MDIO45_DEV_ID_WIDTH (5) - -/* The prt ID is just packed in immediately to the left of the dev ID */ -#define MDIO45_PRT_DEV_WIDTH (MDIO45_PRT_ID_WIDTH + MDIO45_DEV_ID_WIDTH) - -#define MDIO45_PRT_ID_MASK ((1 << MDIO45_PRT_DEV_WIDTH) - 1) -/* This is the prt + dev extended by 1 bit to hold the 'is clause 45' flag. */ -#define MDIO45_XPRT_ID_WIDTH (MDIO45_PRT_DEV_WIDTH + 1) -#define MDIO45_XPRT_ID_MASK ((1 << MDIO45_XPRT_ID_WIDTH) - 1) -#define MDIO45_XPRT_ID_IS10G (1 << (MDIO45_XPRT_ID_WIDTH - 1)) - - -#define MDIO45_PRT_ID_COMP_LBN MDIO45_DEV_ID_WIDTH -#define MDIO45_PRT_ID_COMP_WIDTH MDIO45_PRT_ID_WIDTH -#define MDIO45_DEV_ID_COMP_LBN 0 -#define MDIO45_DEV_ID_COMP_WIDTH MDIO45_DEV_ID_WIDTH - -/* Compose port and device into a phy_id */ -static inline int mdio_clause45_pack(u8 prt, u8 dev) -{ - efx_dword_t phy_id; - EFX_POPULATE_DWORD_2(phy_id, MDIO45_PRT_ID_COMP, prt, - MDIO45_DEV_ID_COMP, dev); - return MDIO45_XPRT_ID_IS10G | EFX_DWORD_VAL(phy_id); -} - -static inline void mdio_clause45_unpack(u32 val, u8 *prt, u8 *dev) -{ - efx_dword_t phy_id; - EFX_POPULATE_DWORD_1(phy_id, EFX_DWORD_0, val); - *prt = EFX_DWORD_FIELD(phy_id, MDIO45_PRT_ID_COMP); - *dev = EFX_DWORD_FIELD(phy_id, MDIO45_DEV_ID_COMP); -} - -static inline int mdio_clause45_read(struct efx_nic *efx, - u8 prt, u8 dev, u16 addr) -{ - return efx->mii.mdio_read(efx->net_dev, - mdio_clause45_pack(prt, dev), addr); -} - -static inline void mdio_clause45_write(struct efx_nic *efx, - u8 prt, u8 dev, u16 addr, int value) -{ - efx->mii.mdio_write(efx->net_dev, - mdio_clause45_pack(prt, dev), addr, value); -} - - -static inline u32 mdio_clause45_read_id(struct efx_nic *efx, int mmd) -{ - int phy_id = efx->mii.phy_id; - u16 id_low = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_IDLOW); - u16 id_hi = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_IDHI); - return (id_hi << 16) | (id_low); -} - -static inline bool mdio_clause45_phyxgxs_lane_sync(struct efx_nic *efx) -{ - int i, lane_status; - bool sync; - - for (i = 0; i < 2; ++i) - lane_status = mdio_clause45_read(efx, efx->mii.phy_id, - MDIO_MMD_PHYXS, - MDIO_PHYXS_LANE_STATE); - - sync = !!(lane_status & (1 << MDIO_PHYXS_LANE_ALIGNED_LBN)); - if (!sync) - EFX_LOG(efx, "XGXS lane status: %x\n", lane_status); - return sync; -} - -extern const char *mdio_clause45_mmd_name(int mmd); - -/* - * Reset a specific MMD and wait for reset to clear. - * Return number of spins left (>0) on success, -%ETIMEDOUT on failure. - * - * This function will sleep - */ -extern int mdio_clause45_reset_mmd(struct efx_nic *efx, int mmd, - int spins, int spintime); - -/* As mdio_clause45_check_mmd but for multiple MMDs */ -int mdio_clause45_check_mmds(struct efx_nic *efx, - unsigned int mmd_mask, unsigned int fatal_mask); - -/* Check the link status of specified mmds in bit mask */ -extern bool mdio_clause45_links_ok(struct efx_nic *efx, - unsigned int mmd_mask); - -/* Generic transmit disable support though PMAPMD */ -extern void mdio_clause45_transmit_disable(struct efx_nic *efx); - -/* Generic part of reconfigure: set/clear loopback bits */ -extern void mdio_clause45_phy_reconfigure(struct efx_nic *efx); - -/* Set the power state of the specified MMDs */ -extern void mdio_clause45_set_mmds_lpower(struct efx_nic *efx, - int low_power, unsigned int mmd_mask); - -/* Read (some of) the PHY settings over MDIO */ -extern void mdio_clause45_get_settings(struct efx_nic *efx, - struct ethtool_cmd *ecmd); - -/* Read (some of) the PHY settings over MDIO */ -extern void -mdio_clause45_get_settings_ext(struct efx_nic *efx, struct ethtool_cmd *ecmd, - u32 xnp, u32 xnp_lpa); - -/* Set (some of) the PHY settings over MDIO */ -extern int mdio_clause45_set_settings(struct efx_nic *efx, - struct ethtool_cmd *ecmd); - -/* Set pause parameters to be advertised through AN (if available) */ -extern void mdio_clause45_set_pause(struct efx_nic *efx); - -/* Get pause parameters from AN if available (otherwise return - * requested pause parameters) - */ -enum efx_fc_type mdio_clause45_get_pause(struct efx_nic *efx); - -/* Wait for specified MMDs to exit reset within a timeout */ -extern int mdio_clause45_wait_reset_mmds(struct efx_nic *efx, - unsigned int mmd_mask); - -/* Set or clear flag, debouncing */ -extern void mdio_clause45_set_flag(struct efx_nic *efx, u8 prt, u8 dev, - u16 addr, int bit, bool sense); - -#endif /* EFX_MDIO_10G_H */ diff --git a/drivers/net/sfc/mtd.c b/drivers/net/sfc/mtd.c deleted file mode 100644 index 665cafb88d6..00000000000 --- a/drivers/net/sfc/mtd.c +++ /dev/null @@ -1,268 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2006-2008 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. - */ - -#include <linux/module.h> -#include <linux/mtd/mtd.h> -#include <linux/delay.h> - -#define EFX_DRIVER_NAME "sfc_mtd" -#include "net_driver.h" -#include "spi.h" - -#define EFX_SPI_VERIFY_BUF_LEN 16 - -struct efx_mtd { - const struct efx_spi_device *spi; - struct mtd_info mtd; - char name[IFNAMSIZ + 20]; -}; - -/* SPI utilities */ - -static int efx_spi_slow_wait(struct efx_mtd *efx_mtd, bool uninterruptible) -{ - const struct efx_spi_device *spi = efx_mtd->spi; - struct efx_nic *efx = spi->efx; - u8 status; - int rc, i; - - /* Wait up to 4s for flash/EEPROM to finish a slow operation. */ - for (i = 0; i < 40; i++) { - __set_current_state(uninterruptible ? - TASK_UNINTERRUPTIBLE : TASK_INTERRUPTIBLE); - schedule_timeout(HZ / 10); - rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL, - &status, sizeof(status)); - if (rc) - return rc; - if (!(status & SPI_STATUS_NRDY)) - return 0; - if (signal_pending(current)) - return -EINTR; - } - EFX_ERR(efx, "timed out waiting for %s\n", efx_mtd->name); - return -ETIMEDOUT; -} - -static int efx_spi_unlock(const struct efx_spi_device *spi) -{ - const u8 unlock_mask = (SPI_STATUS_BP2 | SPI_STATUS_BP1 | - SPI_STATUS_BP0); - u8 status; - int rc; - - rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL, &status, sizeof(status)); - if (rc) - return rc; - - if (!(status & unlock_mask)) - return 0; /* already unlocked */ - - rc = falcon_spi_cmd(spi, SPI_WREN, -1, NULL, NULL, 0); - if (rc) - return rc; - rc = falcon_spi_cmd(spi, SPI_SST_EWSR, -1, NULL, NULL, 0); - if (rc) - return rc; - - status &= ~unlock_mask; - rc = falcon_spi_cmd(spi, SPI_WRSR, -1, &status, NULL, sizeof(status)); - if (rc) - return rc; - rc = falcon_spi_wait_write(spi); - if (rc) - return rc; - - return 0; -} - -static int efx_spi_erase(struct efx_mtd *efx_mtd, loff_t start, size_t len) -{ - const struct efx_spi_device *spi = efx_mtd->spi; - unsigned pos, block_len; - u8 empty[EFX_SPI_VERIFY_BUF_LEN]; - u8 buffer[EFX_SPI_VERIFY_BUF_LEN]; - int rc; - - if (len != spi->erase_size) - return -EINVAL; - - if (spi->erase_command == 0) - return -EOPNOTSUPP; - - rc = efx_spi_unlock(spi); - if (rc) - return rc; - rc = falcon_spi_cmd(spi, SPI_WREN, -1, NULL, NULL, 0); - if (rc) - return rc; - rc = falcon_spi_cmd(spi, spi->erase_command, start, NULL, NULL, 0); - if (rc) - return rc; - rc = efx_spi_slow_wait(efx_mtd, false); - - /* Verify the entire region has been wiped */ - memset(empty, 0xff, sizeof(empty)); - for (pos = 0; pos < len; pos += block_len) { - block_len = min(len - pos, sizeof(buffer)); - rc = falcon_spi_read(spi, start + pos, block_len, NULL, buffer); - if (rc) - return rc; - if (memcmp(empty, buffer, block_len)) - return -EIO; - - /* Avoid locking up the system */ - cond_resched(); - if (signal_pending(current)) - return -EINTR; - } - - return rc; -} - -/* MTD interface */ - -static int efx_mtd_read(struct mtd_info *mtd, loff_t start, size_t len, - size_t *retlen, u8 *buffer) -{ - struct efx_mtd *efx_mtd = mtd->priv; - const struct efx_spi_device *spi = efx_mtd->spi; - struct efx_nic *efx = spi->efx; - int rc; - - rc = mutex_lock_interruptible(&efx->spi_lock); - if (rc) - return rc; - rc = falcon_spi_read(spi, FALCON_FLASH_BOOTCODE_START + start, - len, retlen, buffer); - mutex_unlock(&efx->spi_lock); - return rc; -} - -static int efx_mtd_erase(struct mtd_info *mtd, struct erase_info *erase) -{ - struct efx_mtd *efx_mtd = mtd->priv; - struct efx_nic *efx = efx_mtd->spi->efx; - int rc; - - rc = mutex_lock_interruptible(&efx->spi_lock); - if (rc) - return rc; - rc = efx_spi_erase(efx_mtd, FALCON_FLASH_BOOTCODE_START + erase->addr, - erase->len); - mutex_unlock(&efx->spi_lock); - - if (rc == 0) { - erase->state = MTD_ERASE_DONE; - } else { - erase->state = MTD_ERASE_FAILED; - erase->fail_addr = 0xffffffff; - } - mtd_erase_callback(erase); - return rc; -} - -static int efx_mtd_write(struct mtd_info *mtd, loff_t start, - size_t len, size_t *retlen, const u8 *buffer) -{ - struct efx_mtd *efx_mtd = mtd->priv; - const struct efx_spi_device *spi = efx_mtd->spi; - struct efx_nic *efx = spi->efx; - int rc; - - rc = mutex_lock_interruptible(&efx->spi_lock); - if (rc) - return rc; - rc = falcon_spi_write(spi, FALCON_FLASH_BOOTCODE_START + start, - len, retlen, buffer); - mutex_unlock(&efx->spi_lock); - return rc; -} - -static void efx_mtd_sync(struct mtd_info *mtd) -{ - struct efx_mtd *efx_mtd = mtd->priv; - struct efx_nic *efx = efx_mtd->spi->efx; - int rc; - - mutex_lock(&efx->spi_lock); - rc = efx_spi_slow_wait(efx_mtd, true); - mutex_unlock(&efx->spi_lock); - - if (rc) - EFX_ERR(efx, "%s sync failed (%d)\n", efx_mtd->name, rc); - return; -} - -void efx_mtd_remove(struct efx_nic *efx) -{ - if (efx->spi_flash && efx->spi_flash->mtd) { - struct efx_mtd *efx_mtd = efx->spi_flash->mtd; - int rc; - - for (;;) { - rc = del_mtd_device(&efx_mtd->mtd); - if (rc != -EBUSY) - break; - ssleep(1); - } - WARN_ON(rc); - kfree(efx_mtd); - } -} - -void efx_mtd_rename(struct efx_nic *efx) -{ - if (efx->spi_flash && efx->spi_flash->mtd) { - struct efx_mtd *efx_mtd = efx->spi_flash->mtd; - snprintf(efx_mtd->name, sizeof(efx_mtd->name), - "%s sfc_flash_bootrom", efx->name); - } -} - -int efx_mtd_probe(struct efx_nic *efx) -{ - struct efx_spi_device *spi = efx->spi_flash; - struct efx_mtd *efx_mtd; - - if (!spi || spi->size <= FALCON_FLASH_BOOTCODE_START) - return -ENODEV; - - efx_mtd = kzalloc(sizeof(*efx_mtd), GFP_KERNEL); - if (!efx_mtd) - return -ENOMEM; - - efx_mtd->spi = spi; - spi->mtd = efx_mtd; - - efx_mtd->mtd.type = MTD_NORFLASH; - efx_mtd->mtd.flags = MTD_CAP_NORFLASH; - efx_mtd->mtd.size = spi->size - FALCON_FLASH_BOOTCODE_START; - efx_mtd->mtd.erasesize = spi->erase_size; - efx_mtd->mtd.writesize = 1; - efx_mtd_rename(efx); - - efx_mtd->mtd.owner = THIS_MODULE; - efx_mtd->mtd.priv = efx_mtd; - efx_mtd->mtd.name = efx_mtd->name; - efx_mtd->mtd.erase = efx_mtd_erase; - efx_mtd->mtd.read = efx_mtd_read; - efx_mtd->mtd.write = efx_mtd_write; - efx_mtd->mtd.sync = efx_mtd_sync; - - if (add_mtd_device(&efx_mtd->mtd)) { - kfree(efx_mtd); - spi->mtd = NULL; - /* add_mtd_device() returns 1 if the MTD table is full */ - return -ENOMEM; - } - - return 0; -} diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h deleted file mode 100644 index e019ad1fb9a..00000000000 --- a/drivers/net/sfc/net_driver.h +++ /dev/null @@ -1,1013 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2005-2008 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. - */ - -/* Common definitions for all Efx net driver code */ - -#ifndef EFX_NET_DRIVER_H -#define EFX_NET_DRIVER_H - -#include <linux/version.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/ethtool.h> -#include <linux/if_vlan.h> -#include <linux/timer.h> -#include <linux/mii.h> -#include <linux/list.h> -#include <linux/pci.h> -#include <linux/device.h> -#include <linux/highmem.h> -#include <linux/workqueue.h> -#include <linux/inet_lro.h> -#include <linux/i2c.h> - -#include "enum.h" -#include "bitfield.h" - -#define EFX_MAX_LRO_DESCRIPTORS 8 -#define EFX_MAX_LRO_AGGR MAX_SKB_FRAGS - -/************************************************************************** - * - * Build definitions - * - **************************************************************************/ -#ifndef EFX_DRIVER_NAME -#define EFX_DRIVER_NAME "sfc" -#endif -#define EFX_DRIVER_VERSION "2.3" - -#ifdef EFX_ENABLE_DEBUG -#define EFX_BUG_ON_PARANOID(x) BUG_ON(x) -#define EFX_WARN_ON_PARANOID(x) WARN_ON(x) -#else -#define EFX_BUG_ON_PARANOID(x) do {} while (0) -#define EFX_WARN_ON_PARANOID(x) do {} while (0) -#endif - -/* Un-rate-limited logging */ -#define EFX_ERR(efx, fmt, args...) \ -dev_err(&((efx)->pci_dev->dev), "ERR: %s " fmt, efx_dev_name(efx), ##args) - -#define EFX_INFO(efx, fmt, args...) \ -dev_info(&((efx)->pci_dev->dev), "INFO: %s " fmt, efx_dev_name(efx), ##args) - -#ifdef EFX_ENABLE_DEBUG -#define EFX_LOG(efx, fmt, args...) \ -dev_info(&((efx)->pci_dev->dev), "DBG: %s " fmt, efx_dev_name(efx), ##args) -#else -#define EFX_LOG(efx, fmt, args...) \ -dev_dbg(&((efx)->pci_dev->dev), "DBG: %s " fmt, efx_dev_name(efx), ##args) -#endif - -#define EFX_TRACE(efx, fmt, args...) do {} while (0) - -#define EFX_REGDUMP(efx, fmt, args...) do {} while (0) - -/* Rate-limited logging */ -#define EFX_ERR_RL(efx, fmt, args...) \ -do {if (net_ratelimit()) EFX_ERR(efx, fmt, ##args); } while (0) - -#define EFX_INFO_RL(efx, fmt, args...) \ -do {if (net_ratelimit()) EFX_INFO(efx, fmt, ##args); } while (0) - -#define EFX_LOG_RL(efx, fmt, args...) \ -do {if (net_ratelimit()) EFX_LOG(efx, fmt, ##args); } while (0) - -/************************************************************************** - * - * Efx data structures - * - **************************************************************************/ - -#define EFX_MAX_CHANNELS 32 -#define EFX_MAX_RX_QUEUES EFX_MAX_CHANNELS - -#define EFX_TX_QUEUE_OFFLOAD_CSUM 0 -#define EFX_TX_QUEUE_NO_CSUM 1 -#define EFX_TX_QUEUE_COUNT 2 - -/** - * struct efx_special_buffer - An Efx special buffer - * @addr: CPU base address of the buffer - * @dma_addr: DMA base address of the buffer - * @len: Buffer length, in bytes - * @index: Buffer index within controller;s buffer table - * @entries: Number of buffer table entries - * - * Special buffers are used for the event queues and the TX and RX - * descriptor queues for each channel. They are *not* used for the - * actual transmit and receive buffers. - * - * Note that for Falcon, TX and RX descriptor queues live in host memory. - * Allocation and freeing procedures must take this into account. - */ -struct efx_special_buffer { - void *addr; - dma_addr_t dma_addr; - unsigned int len; - int index; - int entries; -}; - -/** - * struct efx_tx_buffer - An Efx TX buffer - * @skb: The associated socket buffer. - * Set only on the final fragment of a packet; %NULL for all other - * fragments. When this fragment completes, then we can free this - * skb. - * @tsoh: The associated TSO header structure, or %NULL if this - * buffer is not a TSO header. - * @dma_addr: DMA address of the fragment. - * @len: Length of this fragment. - * This field is zero when the queue slot is empty. - * @continuation: True if this fragment is not the end of a packet. - * @unmap_single: True if pci_unmap_single should be used. - * @unmap_len: Length of this fragment to unmap - */ -struct efx_tx_buffer { - const struct sk_buff *skb; - struct efx_tso_header *tsoh; - dma_addr_t dma_addr; - unsigned short len; - bool continuation; - bool unmap_single; - unsigned short unmap_len; -}; - -/** - * struct efx_tx_queue - An Efx TX queue - * - * This is a ring buffer of TX fragments. - * Since the TX completion path always executes on the same - * CPU and the xmit path can operate on different CPUs, - * performance is increased by ensuring that the completion - * path and the xmit path operate on different cache lines. - * This is particularly important if the xmit path is always - * executing on one CPU which is different from the completion - * path. There is also a cache line for members which are - * read but not written on the fast path. - * - * @efx: The associated Efx NIC - * @queue: DMA queue number - * @channel: The associated channel - * @buffer: The software buffer ring - * @txd: The hardware descriptor ring - * @flushed: Used when handling queue flushing - * @read_count: Current read pointer. - * This is the number of buffers that have been removed from both rings. - * @stopped: Stopped count. - * Set if this TX queue is currently stopping its port. - * @insert_count: Current insert pointer - * This is the number of buffers that have been added to the - * software ring. - * @write_count: Current write pointer - * This is the number of buffers that have been added to the - * hardware ring. - * @old_read_count: The value of read_count when last checked. - * This is here for performance reasons. The xmit path will - * only get the up-to-date value of read_count if this - * variable indicates that the queue is full. This is to - * avoid cache-line ping-pong between the xmit path and the - * completion path. - * @tso_headers_free: A list of TSO headers allocated for this TX queue - * that are not in use, and so available for new TSO sends. The list - * is protected by the TX queue lock. - * @tso_bursts: Number of times TSO xmit invoked by kernel - * @tso_long_headers: Number of packets with headers too long for standard - * blocks - * @tso_packets: Number of packets via the TSO xmit path - */ -struct efx_tx_queue { - /* Members which don't change on the fast path */ - struct efx_nic *efx ____cacheline_aligned_in_smp; - int queue; - struct efx_channel *channel; - struct efx_nic *nic; - struct efx_tx_buffer *buffer; - struct efx_special_buffer txd; - bool flushed; - - /* Members used mainly on the completion path */ - unsigned int read_count ____cacheline_aligned_in_smp; - int stopped; - - /* Members used only on the xmit path */ - unsigned int insert_count ____cacheline_aligned_in_smp; - unsigned int write_count; - unsigned int old_read_count; - struct efx_tso_header *tso_headers_free; - unsigned int tso_bursts; - unsigned int tso_long_headers; - unsigned int tso_packets; -}; - -/** - * struct efx_rx_buffer - An Efx RX data buffer - * @dma_addr: DMA base address of the buffer - * @skb: The associated socket buffer, if any. - * If both this and page are %NULL, the buffer slot is currently free. - * @page: The associated page buffer, if any. - * If both this and skb are %NULL, the buffer slot is currently free. - * @data: Pointer to ethernet header - * @len: Buffer length, in bytes. - * @unmap_addr: DMA address to unmap - */ -struct efx_rx_buffer { - dma_addr_t dma_addr; - struct sk_buff *skb; - struct page *page; - char *data; - unsigned int len; - dma_addr_t unmap_addr; -}; - -/** - * struct efx_rx_queue - An Efx RX queue - * @efx: The associated Efx NIC - * @queue: DMA queue number - * @channel: The associated channel - * @buffer: The software buffer ring - * @rxd: The hardware descriptor ring - * @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. - * @add_lock: Receive queue descriptor add spin lock. - * This lock must be held in order to add buffers to the RX - * descriptor ring (rxd and buffer) and to update added_count (but - * not removed_count). - * @max_fill: RX descriptor maximum fill level (<= ring size) - * @fast_fill_trigger: RX descriptor fill level that will trigger a fast fill - * (<= @max_fill) - * @fast_fill_limit: The level to which a fast fill will fill - * (@fast_fill_trigger <= @fast_fill_limit <= @max_fill) - * @min_fill: RX descriptor minimum non-zero fill level. - * This records the minimum fill level observed when a ring - * refill was triggered. - * @min_overfill: RX descriptor minimum overflow fill level. - * This records the minimum fill level at which RX queue - * overflow was observed. It should never be set. - * @alloc_page_count: RX allocation strategy counter. - * @alloc_skb_count: RX allocation strategy counter. - * @work: Descriptor push work thread - * @buf_page: Page for next RX buffer. - * We can use a single page for multiple RX buffers. This tracks - * the remaining space in the allocation. - * @buf_dma_addr: Page's DMA address. - * @buf_data: Page's host address. - * @flushed: Use when handling queue flushing - */ -struct efx_rx_queue { - struct efx_nic *efx; - int queue; - struct efx_channel *channel; - struct efx_rx_buffer *buffer; - struct efx_special_buffer rxd; - - int added_count; - int notified_count; - int removed_count; - spinlock_t add_lock; - unsigned int max_fill; - unsigned int fast_fill_trigger; - unsigned int fast_fill_limit; - unsigned int min_fill; - unsigned int min_overfill; - unsigned int alloc_page_count; - unsigned int alloc_skb_count; - struct delayed_work work; - unsigned int slow_fill_count; - - struct page *buf_page; - dma_addr_t buf_dma_addr; - char *buf_data; - bool flushed; -}; - -/** - * struct efx_buffer - An Efx general-purpose buffer - * @addr: host base address of the buffer - * @dma_addr: DMA base address of the buffer - * @len: Buffer length, in bytes - * - * Falcon uses these buffers for its interrupt status registers and - * MAC stats dumps. - */ -struct efx_buffer { - void *addr; - dma_addr_t dma_addr; - unsigned int len; -}; - - -/* Flags for channel->used_flags */ -#define EFX_USED_BY_RX 1 -#define EFX_USED_BY_TX 2 -#define EFX_USED_BY_RX_TX (EFX_USED_BY_RX | EFX_USED_BY_TX) - -enum efx_rx_alloc_method { - RX_ALLOC_METHOD_AUTO = 0, - RX_ALLOC_METHOD_SKB = 1, - RX_ALLOC_METHOD_PAGE = 2, -}; - -/** - * struct efx_channel - An Efx channel - * - * A channel comprises an event queue, at least one TX queue, at least - * one RX queue, and an associated tasklet for processing the event - * queue. - * - * @efx: Associated Efx NIC - * @channel: Channel instance number - * @name: Name for channel and IRQ - * @used_flags: Channel is used by net driver - * @enabled: Channel enabled indicator - * @irq: IRQ number (MSI and MSI-X only) - * @irq_moderation: IRQ moderation value (in us) - * @napi_dev: Net device used with NAPI - * @napi_str: NAPI control structure - * @reset_work: Scheduled reset work thread - * @work_pending: Is work pending via NAPI? - * @eventq: Event queue buffer - * @eventq_read_ptr: Event queue read pointer - * @last_eventq_read_ptr: Last event queue read pointer value. - * @eventq_magic: Event queue magic value for driver-generated test events - * @lro_mgr: LRO state - * @rx_alloc_level: Watermark based heuristic counter for pushing descriptors - * and diagnostic counters - * @rx_alloc_push_pages: RX allocation method currently in use for pushing - * descriptors - * @rx_alloc_pop_pages: RX allocation method currently in use for popping - * descriptors - * @n_rx_tobe_disc: Count of RX_TOBE_DISC errors - * @n_rx_ip_frag_err: Count of RX IP fragment errors - * @n_rx_ip_hdr_chksum_err: Count of RX IP header checksum errors - * @n_rx_tcp_udp_chksum_err: Count of RX TCP and UDP checksum errors - * @n_rx_frm_trunc: Count of RX_FRM_TRUNC errors - * @n_rx_overlength: Count of RX_OVERLENGTH errors - * @n_skbuff_leaks: Count of skbuffs leaked due to RX overrun - */ -struct efx_channel { - struct efx_nic *efx; - int channel; - char name[IFNAMSIZ + 6]; - int used_flags; - bool enabled; - int irq; - unsigned int irq_moderation; - struct net_device *napi_dev; - struct napi_struct napi_str; - bool work_pending; - struct efx_special_buffer eventq; - unsigned int eventq_read_ptr; - unsigned int last_eventq_read_ptr; - unsigned int eventq_magic; - - struct net_lro_mgr lro_mgr; - int rx_alloc_level; - int rx_alloc_push_pages; - int rx_alloc_pop_pages; - - unsigned n_rx_tobe_disc; - unsigned n_rx_ip_frag_err; - unsigned n_rx_ip_hdr_chksum_err; - unsigned n_rx_tcp_udp_chksum_err; - unsigned n_rx_frm_trunc; - unsigned n_rx_overlength; - unsigned n_skbuff_leaks; - - /* Used to pipeline received packets in order to optimise memory - * access with prefetches. - */ - struct efx_rx_buffer *rx_pkt; - bool rx_pkt_csummed; - -}; - -/** - * struct efx_blinker - S/W LED blinking context - * @led_num: LED ID (board-specific meaning) - * @state: Current state - on or off - * @resubmit: Timer resubmission flag - * @timer: Control timer for blinking - */ -struct efx_blinker { - int led_num; - bool state; - bool resubmit; - struct timer_list timer; -}; - - -/** - * struct efx_board - board information - * @type: Board model type - * @major: Major rev. ('A', 'B' ...) - * @minor: Minor rev. (0, 1, ...) - * @init: Initialisation function - * @init_leds: Sets up board LEDs - * @set_fault_led: Turns the fault LED on or off - * @blink: Starts/stops blinking - * @monitor: Board-specific health check function - * @fini: Cleanup function - * @blinker: used to blink LEDs in software - * @hwmon_client: I2C client for hardware monitor - * @ioexp_client: I2C client for power/port control - */ -struct efx_board { - int type; - int major; - int minor; - int (*init) (struct efx_nic *nic); - /* As the LEDs are typically attached to the PHY, LEDs - * have a separate init callback that happens later than - * board init. */ - int (*init_leds)(struct efx_nic *efx); - int (*monitor) (struct efx_nic *nic); - void (*set_fault_led) (struct efx_nic *efx, bool state); - void (*blink) (struct efx_nic *efx, bool start); - void (*fini) (struct efx_nic *nic); - struct efx_blinker blinker; - struct i2c_client *hwmon_client, *ioexp_client; -}; - -#define STRING_TABLE_LOOKUP(val, member) \ - member ## _names[val] - -enum efx_int_mode { - /* Be careful if altering to correct macro below */ - EFX_INT_MODE_MSIX = 0, - EFX_INT_MODE_MSI = 1, - EFX_INT_MODE_LEGACY = 2, - EFX_INT_MODE_MAX /* Insert any new items before this */ -}; -#define EFX_INT_MODE_USE_MSI(x) (((x)->interrupt_mode) <= EFX_INT_MODE_MSI) - -enum phy_type { - PHY_TYPE_NONE = 0, - PHY_TYPE_TXC43128 = 1, - PHY_TYPE_88E1111 = 2, - PHY_TYPE_SFX7101 = 3, - PHY_TYPE_QT2022C2 = 4, - PHY_TYPE_PM8358 = 6, - PHY_TYPE_SFT9001A = 8, - PHY_TYPE_SFT9001B = 10, - PHY_TYPE_MAX /* Insert any new items before this */ -}; - -#define PHY_ADDR_INVALID 0xff - -#define EFX_IS10G(efx) ((efx)->link_speed == 10000) - -enum nic_state { - STATE_INIT = 0, - STATE_RUNNING = 1, - STATE_FINI = 2, - STATE_DISABLED = 3, - STATE_MAX, -}; - -/* - * Alignment of page-allocated RX buffers - * - * Controls the number of bytes inserted at the start of an RX buffer. - * This is the equivalent of NET_IP_ALIGN [which controls the alignment - * of the skb->head for hardware DMA]. - */ -#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS -#define EFX_PAGE_IP_ALIGN 0 -#else -#define EFX_PAGE_IP_ALIGN NET_IP_ALIGN -#endif - -/* - * Alignment of the skb->head which wraps a page-allocated RX buffer - * - * The skb allocated to wrap an rx_buffer can have this alignment. Since - * the data is memcpy'd from the rx_buf, it does not need to be equal to - * EFX_PAGE_IP_ALIGN. - */ -#define EFX_PAGE_SKB_ALIGN 2 - -/* Forward declaration */ -struct efx_nic; - -/* Pseudo bit-mask flow control field */ -enum efx_fc_type { - EFX_FC_RX = 1, - EFX_FC_TX = 2, - EFX_FC_AUTO = 4, -}; - -/* Supported MAC bit-mask */ -enum efx_mac_type { - EFX_GMAC = 1, - EFX_XMAC = 2, -}; - -static inline unsigned int efx_fc_advertise(enum efx_fc_type wanted_fc) -{ - unsigned int adv = 0; - if (wanted_fc & EFX_FC_RX) - adv = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - if (wanted_fc & EFX_FC_TX) - adv ^= ADVERTISE_PAUSE_ASYM; - return adv; -} - -static inline enum efx_fc_type efx_fc_resolve(enum efx_fc_type wanted_fc, - unsigned int lpa) -{ - unsigned int adv = efx_fc_advertise(wanted_fc); - - if (!(wanted_fc & EFX_FC_AUTO)) - return wanted_fc; - - if (adv & lpa & ADVERTISE_PAUSE_CAP) - return EFX_FC_RX | EFX_FC_TX; - if (adv & lpa & ADVERTISE_PAUSE_ASYM) { - if (adv & ADVERTISE_PAUSE_CAP) - return EFX_FC_RX; - if (lpa & ADVERTISE_PAUSE_CAP) - return EFX_FC_TX; - } - return 0; -} - -/** - * struct efx_mac_operations - Efx MAC operations table - * @reconfigure: Reconfigure MAC. Serialised by the mac_lock - * @update_stats: Update statistics - * @irq: Hardware MAC event callback. Serialised by the mac_lock - * @poll: Poll for hardware state. Serialised by the mac_lock - */ -struct efx_mac_operations { - void (*reconfigure) (struct efx_nic *efx); - void (*update_stats) (struct efx_nic *efx); - void (*irq) (struct efx_nic *efx); - void (*poll) (struct efx_nic *efx); -}; - -/** - * struct efx_phy_operations - Efx PHY operations table - * @init: Initialise PHY - * @fini: Shut down PHY - * @reconfigure: Reconfigure PHY (e.g. for new link parameters) - * @clear_interrupt: Clear down interrupt - * @blink: Blink LEDs - * @poll: Poll for hardware state. Serialised by the mac_lock. - * @get_settings: Get ethtool settings. Serialised by the mac_lock. - * @set_settings: Set ethtool settings. Serialised by the mac_lock. - * @set_npage_adv: Set abilities advertised in (Extended) Next Page - * (only needed where AN bit is set in mmds) - * @num_tests: Number of PHY-specific tests/results - * @test_names: Names of the tests/results - * @run_tests: Run tests and record results as appropriate. - * Flags are the ethtool tests flags. - * @mmds: MMD presence mask - * @loopbacks: Supported loopback modes mask - */ -struct efx_phy_operations { - enum efx_mac_type macs; - int (*init) (struct efx_nic *efx); - void (*fini) (struct efx_nic *efx); - void (*reconfigure) (struct efx_nic *efx); - void (*clear_interrupt) (struct efx_nic *efx); - void (*poll) (struct efx_nic *efx); - void (*get_settings) (struct efx_nic *efx, - struct ethtool_cmd *ecmd); - int (*set_settings) (struct efx_nic *efx, - struct ethtool_cmd *ecmd); - void (*set_npage_adv) (struct efx_nic *efx, u32); - u32 num_tests; - const char *const *test_names; - int (*run_tests) (struct efx_nic *efx, int *results, unsigned flags); - int mmds; - unsigned loopbacks; -}; - -/** - * @enum efx_phy_mode - PHY operating mode flags - * @PHY_MODE_NORMAL: on and should pass traffic - * @PHY_MODE_TX_DISABLED: on with TX disabled - * @PHY_MODE_LOW_POWER: set to low power through MDIO - * @PHY_MODE_OFF: switched off through external control - * @PHY_MODE_SPECIAL: on but will not pass traffic - */ -enum efx_phy_mode { - PHY_MODE_NORMAL = 0, - PHY_MODE_TX_DISABLED = 1, - PHY_MODE_LOW_POWER = 2, - PHY_MODE_OFF = 4, - PHY_MODE_SPECIAL = 8, -}; - -static inline bool efx_phy_mode_disabled(enum efx_phy_mode mode) -{ - return !!(mode & ~PHY_MODE_TX_DISABLED); -} - -/* - * Efx extended statistics - * - * Not all statistics are provided by all supported MACs. The purpose - * is this structure is to contain the raw statistics provided by each - * MAC. - */ -struct efx_mac_stats { - u64 tx_bytes; - u64 tx_good_bytes; - u64 tx_bad_bytes; - unsigned long tx_packets; - unsigned long tx_bad; - unsigned long tx_pause; - unsigned long tx_control; - unsigned long tx_unicast; - unsigned long tx_multicast; - unsigned long tx_broadcast; - unsigned long tx_lt64; - unsigned long tx_64; - unsigned long tx_65_to_127; - unsigned long tx_128_to_255; - unsigned long tx_256_to_511; - unsigned long tx_512_to_1023; - unsigned long tx_1024_to_15xx; - unsigned long tx_15xx_to_jumbo; - unsigned long tx_gtjumbo; - unsigned long tx_collision; - unsigned long tx_single_collision; - unsigned long tx_multiple_collision; - unsigned long tx_excessive_collision; - unsigned long tx_deferred; - unsigned long tx_late_collision; - unsigned long tx_excessive_deferred; - unsigned long tx_non_tcpudp; - unsigned long tx_mac_src_error; - unsigned long tx_ip_src_error; - u64 rx_bytes; - u64 rx_good_bytes; - u64 rx_bad_bytes; - unsigned long rx_packets; - unsigned long rx_good; - unsigned long rx_bad; - unsigned long rx_pause; - unsigned long rx_control; - unsigned long rx_unicast; - unsigned long rx_multicast; - unsigned long rx_broadcast; - unsigned long rx_lt64; - unsigned long rx_64; - unsigned long rx_65_to_127; - unsigned long rx_128_to_255; - unsigned long rx_256_to_511; - unsigned long rx_512_to_1023; - unsigned long rx_1024_to_15xx; - unsigned long rx_15xx_to_jumbo; - unsigned long rx_gtjumbo; - unsigned long rx_bad_lt64; - unsigned long rx_bad_64_to_15xx; - unsigned long rx_bad_15xx_to_jumbo; - unsigned long rx_bad_gtjumbo; - unsigned long rx_overflow; - unsigned long rx_missed; - unsigned long rx_false_carrier; - unsigned long rx_symbol_error; - unsigned long rx_align_error; - unsigned long rx_length_error; - unsigned long rx_internal_error; - unsigned long rx_good_lt64; -}; - -/* Number of bits used in a multicast filter hash address */ -#define EFX_MCAST_HASH_BITS 8 - -/* Number of (single-bit) entries in a multicast filter hash */ -#define EFX_MCAST_HASH_ENTRIES (1 << EFX_MCAST_HASH_BITS) - -/* An Efx multicast filter hash */ -union efx_multicast_hash { - u8 byte[EFX_MCAST_HASH_ENTRIES / 8]; - efx_oword_t oword[EFX_MCAST_HASH_ENTRIES / sizeof(efx_oword_t) / 8]; -}; - -/** - * struct efx_nic - an Efx NIC - * @name: Device name (net device name or bus id before net device registered) - * @pci_dev: The PCI device - * @type: Controller type attributes - * @legacy_irq: IRQ number - * @workqueue: Workqueue for port reconfigures and the HW monitor. - * Work items do not hold and must not acquire RTNL. - * @workqueue_name: Name of workqueue - * @reset_work: Scheduled reset workitem - * @monitor_work: Hardware monitor workitem - * @membase_phys: Memory BAR value as physical address - * @membase: Memory BAR value - * @biu_lock: BIU (bus interface unit) lock - * @interrupt_mode: Interrupt mode - * @i2c_adap: I2C adapter - * @board_info: Board-level information - * @state: Device state flag. Serialised by the rtnl_lock. - * @reset_pending: Pending reset method (normally RESET_TYPE_NONE) - * @tx_queue: TX DMA queues - * @rx_queue: RX DMA queues - * @channel: Channels - * @n_rx_queues: Number of RX queues - * @n_channels: Number of channels in use - * @rx_buffer_len: RX buffer length - * @rx_buffer_order: Order (log2) of number of pages for each RX buffer - * @irq_status: Interrupt status buffer - * @last_irq_cpu: Last CPU to handle interrupt. - * This register is written with the SMP processor ID whenever an - * interrupt is handled. It is used by falcon_test_interrupt() - * to verify that an interrupt has occurred. - * @spi_flash: SPI flash device - * This field will be %NULL if no flash device is present. - * @spi_eeprom: SPI EEPROM device - * This field will be %NULL if no EEPROM device is present. - * @spi_lock: SPI bus lock - * @n_rx_nodesc_drop_cnt: RX no descriptor drop count - * @nic_data: Hardware dependant state - * @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode, - * @port_inhibited, efx_monitor() and efx_reconfigure_port() - * @port_enabled: Port enabled indicator. - * Serialises efx_stop_all(), efx_start_all(), efx_monitor(), - * efx_phy_work(), and efx_mac_work() with kernel interfaces. Safe to read - * under any one of the rtnl_lock, mac_lock, or netif_tx_lock, but all - * three must be held to modify it. - * @port_inhibited: If set, the netif_carrier is always off. Hold the mac_lock - * @port_initialized: Port initialized? - * @net_dev: Operating system network device. Consider holding the rtnl lock - * @rx_checksum_enabled: RX checksumming enabled - * @netif_stop_count: Port stop count - * @netif_stop_lock: Port stop lock - * @mac_stats: MAC statistics. These include all statistics the MACs - * can provide. Generic code converts these into a standard - * &struct net_device_stats. - * @stats_buffer: DMA buffer for statistics - * @stats_lock: Statistics update lock. Serialises statistics fetches - * @stats_disable_count: Nest count for disabling statistics fetches - * @mac_op: MAC interface - * @mac_address: Permanent MAC address - * @phy_type: PHY type - * @phy_lock: PHY access lock - * @phy_op: PHY interface - * @phy_data: PHY private data (including PHY-specific stats) - * @mii: PHY interface - * @phy_mode: PHY operating mode. Serialised by @mac_lock. - * @mac_up: MAC link state - * @link_up: Link status - * @link_fd: Link is full duplex - * @link_fc: Actualy flow control flags - * @link_speed: Link speed (Mbps) - * @n_link_state_changes: Number of times the link has changed state - * @promiscuous: Promiscuous flag. Protected by netif_tx_lock. - * @multicast_hash: Multicast hash table - * @wanted_fc: Wanted flow control flags - * @phy_work: work item for dealing with PHY events - * @mac_work: work item for dealing with MAC events - * @loopback_mode: Loopback status - * @loopback_modes: Supported loopback mode bitmask - * @loopback_selftest: Offline self-test private state - * - * The @priv field of the corresponding &struct net_device points to - * this. - */ -struct efx_nic { - char name[IFNAMSIZ]; - struct pci_dev *pci_dev; - const struct efx_nic_type *type; - int legacy_irq; - struct workqueue_struct *workqueue; - char workqueue_name[16]; - struct work_struct reset_work; - struct delayed_work monitor_work; - resource_size_t membase_phys; - void __iomem *membase; - spinlock_t biu_lock; - enum efx_int_mode interrupt_mode; - - struct i2c_adapter i2c_adap; - struct efx_board board_info; - - enum nic_state state; - enum reset_type reset_pending; - - struct efx_tx_queue tx_queue[EFX_TX_QUEUE_COUNT]; - struct efx_rx_queue rx_queue[EFX_MAX_RX_QUEUES]; - struct efx_channel channel[EFX_MAX_CHANNELS]; - - int n_rx_queues; - int n_channels; - unsigned int rx_buffer_len; - unsigned int rx_buffer_order; - - struct efx_buffer irq_status; - volatile signed int last_irq_cpu; - - struct efx_spi_device *spi_flash; - struct efx_spi_device *spi_eeprom; - struct mutex spi_lock; - - unsigned n_rx_nodesc_drop_cnt; - - struct falcon_nic_data *nic_data; - - struct mutex mac_lock; - struct work_struct mac_work; - bool port_enabled; - bool port_inhibited; - - bool port_initialized; - struct net_device *net_dev; - bool rx_checksum_enabled; - - atomic_t netif_stop_count; - spinlock_t netif_stop_lock; - - struct efx_mac_stats mac_stats; - struct efx_buffer stats_buffer; - spinlock_t stats_lock; - unsigned int stats_disable_count; - - struct efx_mac_operations *mac_op; - unsigned char mac_address[ETH_ALEN]; - - enum phy_type phy_type; - spinlock_t phy_lock; - struct work_struct phy_work; - struct efx_phy_operations *phy_op; - void *phy_data; - struct mii_if_info mii; - enum efx_phy_mode phy_mode; - - bool mac_up; - bool link_up; - bool link_fd; - enum efx_fc_type link_fc; - unsigned int link_speed; - unsigned int n_link_state_changes; - - bool promiscuous; - union efx_multicast_hash multicast_hash; - enum efx_fc_type wanted_fc; - - atomic_t rx_reset; - enum efx_loopback_mode loopback_mode; - unsigned int loopback_modes; - - void *loopback_selftest; -}; - -static inline int efx_dev_registered(struct efx_nic *efx) -{ - return efx->net_dev->reg_state == NETREG_REGISTERED; -} - -/* Net device name, for inclusion in log messages if it has been registered. - * Use efx->name not efx->net_dev->name so that races with (un)registration - * are harmless. - */ -static inline const char *efx_dev_name(struct efx_nic *efx) -{ - return efx_dev_registered(efx) ? efx->name : ""; -} - -/** - * struct efx_nic_type - Efx device type definition - * @mem_bar: Memory BAR number - * @mem_map_size: Memory BAR mapped size - * @txd_ptr_tbl_base: TX descriptor ring base address - * @rxd_ptr_tbl_base: RX descriptor ring base address - * @buf_tbl_base: Buffer table base address - * @evq_ptr_tbl_base: Event queue pointer table base address - * @evq_rptr_tbl_base: Event queue read-pointer table base address - * @txd_ring_mask: TX descriptor ring size - 1 (must be a power of two - 1) - * @rxd_ring_mask: RX descriptor ring size - 1 (must be a power of two - 1) - * @evq_size: Event queue size (must be a power of two) - * @max_dma_mask: Maximum possible DMA mask - * @tx_dma_mask: TX DMA mask - * @bug5391_mask: Address mask for bug 5391 workaround - * @rx_xoff_thresh: RX FIFO XOFF watermark (bytes) - * @rx_xon_thresh: RX FIFO XON watermark (bytes) - * @rx_buffer_padding: Padding added to each RX buffer - * @max_interrupt_mode: Highest capability interrupt mode supported - * from &enum efx_init_mode. - * @phys_addr_channels: Number of channels with physically addressed - * descriptors - */ -struct efx_nic_type { - unsigned int mem_bar; - unsigned int mem_map_size; - unsigned int txd_ptr_tbl_base; - unsigned int rxd_ptr_tbl_base; - unsigned int buf_tbl_base; - unsigned int evq_ptr_tbl_base; - unsigned int evq_rptr_tbl_base; - - unsigned int txd_ring_mask; - unsigned int rxd_ring_mask; - unsigned int evq_size; - u64 max_dma_mask; - unsigned int tx_dma_mask; - unsigned bug5391_mask; - - int rx_xoff_thresh; - int rx_xon_thresh; - unsigned int rx_buffer_padding; - unsigned int max_interrupt_mode; - unsigned int phys_addr_channels; -}; - -/************************************************************************** - * - * Prototypes and inline functions - * - *************************************************************************/ - -/* Iterate over all used channels */ -#define efx_for_each_channel(_channel, _efx) \ - for (_channel = &_efx->channel[0]; \ - _channel < &_efx->channel[EFX_MAX_CHANNELS]; \ - _channel++) \ - if (!_channel->used_flags) \ - continue; \ - else - -/* Iterate over all used TX queues */ -#define efx_for_each_tx_queue(_tx_queue, _efx) \ - for (_tx_queue = &_efx->tx_queue[0]; \ - _tx_queue < &_efx->tx_queue[EFX_TX_QUEUE_COUNT]; \ - _tx_queue++) - -/* Iterate over all TX queues belonging to a channel */ -#define efx_for_each_channel_tx_queue(_tx_queue, _channel) \ - for (_tx_queue = &_channel->efx->tx_queue[0]; \ - _tx_queue < &_channel->efx->tx_queue[EFX_TX_QUEUE_COUNT]; \ - _tx_queue++) \ - if (_tx_queue->channel != _channel) \ - continue; \ - else - -/* Iterate over all used RX queues */ -#define efx_for_each_rx_queue(_rx_queue, _efx) \ - for (_rx_queue = &_efx->rx_queue[0]; \ - _rx_queue < &_efx->rx_queue[_efx->n_rx_queues]; \ - _rx_queue++) - -/* Iterate over all RX queues belonging to a channel */ -#define efx_for_each_channel_rx_queue(_rx_queue, _channel) \ - for (_rx_queue = &_channel->efx->rx_queue[_channel->channel]; \ - _rx_queue; \ - _rx_queue = NULL) \ - if (_rx_queue->channel != _channel) \ - continue; \ - else - -/* Returns a pointer to the specified receive buffer in the RX - * descriptor queue. - */ -static inline struct efx_rx_buffer *efx_rx_buffer(struct efx_rx_queue *rx_queue, - unsigned int index) -{ - return (&rx_queue->buffer[index]); -} - -/* Set bit in a little-endian bitfield */ -static inline void set_bit_le(unsigned nr, unsigned char *addr) -{ - addr[nr / 8] |= (1 << (nr % 8)); -} - -/* Clear bit in a little-endian bitfield */ -static inline void clear_bit_le(unsigned nr, unsigned char *addr) -{ - addr[nr / 8] &= ~(1 << (nr % 8)); -} - - -/** - * EFX_MAX_FRAME_LEN - calculate maximum frame length - * - * This calculates the maximum frame length that will be used for a - * given MTU. The frame length will be equal to the MTU plus a - * constant amount of header space and padding. This is the quantity - * that the net driver will program into the MAC as the maximum frame - * length. - * - * The 10G MAC used in Falcon requires 8-byte alignment on the frame - * length, so we round up to the nearest 8. - */ -#define EFX_MAX_FRAME_LEN(mtu) \ - ((((mtu) + ETH_HLEN + VLAN_HLEN + 4/* FCS */) + 7) & ~7) - - -#endif /* EFX_NET_DRIVER_H */ diff --git a/drivers/net/sfc/phy.h b/drivers/net/sfc/phy.h deleted file mode 100644 index 07e855c148b..00000000000 --- a/drivers/net/sfc/phy.h +++ /dev/null @@ -1,40 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2007-2008 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_PHY_H -#define EFX_PHY_H - -/**************************************************************************** - * 10Xpress (SFX7101 and SFT9001) PHYs - */ -extern struct efx_phy_operations falcon_sfx7101_phy_ops; -extern struct efx_phy_operations falcon_sft9001_phy_ops; - -extern void tenxpress_phy_blink(struct efx_nic *efx, bool blink); - -/**************************************************************************** - * Exported functions from the driver for XFP optical PHYs - */ -extern struct efx_phy_operations falcon_xfp_phy_ops; - -/* The QUAKE XFP PHY provides various H/W control states for LEDs */ -#define QUAKE_LED_LINK_INVAL (0) -#define QUAKE_LED_LINK_STAT (1) -#define QUAKE_LED_LINK_ACT (2) -#define QUAKE_LED_LINK_ACTSTAT (3) -#define QUAKE_LED_OFF (4) -#define QUAKE_LED_ON (5) -#define QUAKE_LED_LINK_INPUT (6) /* Pin is an input. */ -/* What link the LED tracks */ -#define QUAKE_LED_TXLINK (0) -#define QUAKE_LED_RXLINK (8) - -extern void xfp_set_led(struct efx_nic *p, int led, int state); - -#endif diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c deleted file mode 100644 index b8ba4bbad88..00000000000 --- a/drivers/net/sfc/rx.c +++ /dev/null @@ -1,880 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2005-2008 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. - */ - -#include <linux/socket.h> -#include <linux/in.h> -#include <linux/ip.h> -#include <linux/tcp.h> -#include <linux/udp.h> -#include <net/ip.h> -#include <net/checksum.h> -#include "net_driver.h" -#include "rx.h" -#include "efx.h" -#include "falcon.h" -#include "selftest.h" -#include "workarounds.h" - -/* Number of RX descriptors pushed at once. */ -#define EFX_RX_BATCH 8 - -/* Size of buffer allocated for skb header area. */ -#define EFX_SKB_HEADERS 64u - -/* - * rx_alloc_method - RX buffer allocation method - * - * This driver supports two methods for allocating and using RX buffers: - * each RX buffer may be backed by an skb or by an order-n page. - * - * When LRO is in use then the second method has a lower overhead, - * since we don't have to allocate then free skbs on reassembled frames. - * - * Values: - * - RX_ALLOC_METHOD_AUTO = 0 - * - RX_ALLOC_METHOD_SKB = 1 - * - RX_ALLOC_METHOD_PAGE = 2 - * - * The heuristic for %RX_ALLOC_METHOD_AUTO is a simple hysteresis count - * controlled by the parameters below. - * - * - Since pushing and popping descriptors are separated by the rx_queue - * size, so the watermarks should be ~rxd_size. - * - The performance win by using page-based allocation for LRO is less - * than the performance hit of using page-based allocation of non-LRO, - * so the watermarks should reflect this. - * - * Per channel we maintain a single variable, updated by each channel: - * - * rx_alloc_level += (lro_performed ? RX_ALLOC_FACTOR_LRO : - * RX_ALLOC_FACTOR_SKB) - * Per NAPI poll interval, we constrain rx_alloc_level to 0..MAX (which - * limits the hysteresis), and update the allocation strategy: - * - * rx_alloc_method = (rx_alloc_level > RX_ALLOC_LEVEL_LRO ? - * RX_ALLOC_METHOD_PAGE : RX_ALLOC_METHOD_SKB) - */ -static int rx_alloc_method = RX_ALLOC_METHOD_PAGE; - -#define RX_ALLOC_LEVEL_LRO 0x2000 -#define RX_ALLOC_LEVEL_MAX 0x3000 -#define RX_ALLOC_FACTOR_LRO 1 -#define RX_ALLOC_FACTOR_SKB (-2) - -/* This is the percentage fill level below which new RX descriptors - * will be added to the RX descriptor ring. - */ -static unsigned int rx_refill_threshold = 90; - -/* This is the percentage fill level to which an RX queue will be refilled - * when the "RX refill threshold" is reached. - */ -static unsigned int rx_refill_limit = 95; - -/* - * RX maximum head room required. - * - * This must be at least 1 to prevent overflow and at least 2 to allow - * pipelined receives. - */ -#define EFX_RXD_HEAD_ROOM 2 - -static inline unsigned int efx_rx_buf_offset(struct efx_rx_buffer *buf) -{ - /* Offset is always within one page, so we don't need to consider - * the page order. - */ - return (__force unsigned long) buf->data & (PAGE_SIZE - 1); -} -static inline unsigned int efx_rx_buf_size(struct efx_nic *efx) -{ - return PAGE_SIZE << efx->rx_buffer_order; -} - - -/************************************************************************** - * - * Linux generic LRO handling - * - ************************************************************************** - */ - -static int efx_lro_get_skb_hdr(struct sk_buff *skb, void **ip_hdr, - void **tcpudp_hdr, u64 *hdr_flags, void *priv) -{ - struct efx_channel *channel = priv; - struct iphdr *iph; - struct tcphdr *th; - - iph = (struct iphdr *)skb->data; - if (skb->protocol != htons(ETH_P_IP) || iph->protocol != IPPROTO_TCP) - goto fail; - - th = (struct tcphdr *)(skb->data + iph->ihl * 4); - - *tcpudp_hdr = th; - *ip_hdr = iph; - *hdr_flags = LRO_IPV4 | LRO_TCP; - - channel->rx_alloc_level += RX_ALLOC_FACTOR_LRO; - return 0; -fail: - channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB; - return -1; -} - -static int efx_get_frag_hdr(struct skb_frag_struct *frag, void **mac_hdr, - void **ip_hdr, void **tcpudp_hdr, u64 *hdr_flags, - void *priv) -{ - struct efx_channel *channel = priv; - struct ethhdr *eh; - struct iphdr *iph; - - /* We support EtherII and VLAN encapsulated IPv4 */ - eh = page_address(frag->page) + frag->page_offset; - *mac_hdr = eh; - - if (eh->h_proto == htons(ETH_P_IP)) { - iph = (struct iphdr *)(eh + 1); - } else { - struct vlan_ethhdr *veh = (struct vlan_ethhdr *)eh; - if (veh->h_vlan_encapsulated_proto != htons(ETH_P_IP)) - goto fail; - - iph = (struct iphdr *)(veh + 1); - } - *ip_hdr = iph; - - /* We can only do LRO over TCP */ - if (iph->protocol != IPPROTO_TCP) - goto fail; - - *hdr_flags = LRO_IPV4 | LRO_TCP; - *tcpudp_hdr = (struct tcphdr *)((u8 *) iph + iph->ihl * 4); - - channel->rx_alloc_level += RX_ALLOC_FACTOR_LRO; - return 0; - fail: - channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB; - return -1; -} - -int efx_lro_init(struct net_lro_mgr *lro_mgr, struct efx_nic *efx) -{ - size_t s = sizeof(struct net_lro_desc) * EFX_MAX_LRO_DESCRIPTORS; - struct net_lro_desc *lro_arr; - - /* Allocate the LRO descriptors structure */ - lro_arr = kzalloc(s, GFP_KERNEL); - if (lro_arr == NULL) - return -ENOMEM; - - lro_mgr->lro_arr = lro_arr; - lro_mgr->max_desc = EFX_MAX_LRO_DESCRIPTORS; - lro_mgr->max_aggr = EFX_MAX_LRO_AGGR; - lro_mgr->frag_align_pad = EFX_PAGE_SKB_ALIGN; - - lro_mgr->get_skb_header = efx_lro_get_skb_hdr; - lro_mgr->get_frag_header = efx_get_frag_hdr; - lro_mgr->dev = efx->net_dev; - - lro_mgr->features = LRO_F_NAPI; - - /* We can pass packets up with the checksum intact */ - lro_mgr->ip_summed = CHECKSUM_UNNECESSARY; - - lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY; - - return 0; -} - -void efx_lro_fini(struct net_lro_mgr *lro_mgr) -{ - kfree(lro_mgr->lro_arr); - lro_mgr->lro_arr = NULL; -} - -/** - * efx_init_rx_buffer_skb - create new RX buffer using skb-based allocation - * - * @rx_queue: Efx RX queue - * @rx_buf: RX buffer structure to populate - * - * This allocates memory for a new receive buffer, maps it for DMA, - * and populates a struct efx_rx_buffer with the relevant - * information. Return a negative error code or 0 on success. - */ -static int efx_init_rx_buffer_skb(struct efx_rx_queue *rx_queue, - struct efx_rx_buffer *rx_buf) -{ - struct efx_nic *efx = rx_queue->efx; - struct net_device *net_dev = efx->net_dev; - int skb_len = efx->rx_buffer_len; - - rx_buf->skb = netdev_alloc_skb(net_dev, skb_len); - if (unlikely(!rx_buf->skb)) - return -ENOMEM; - - /* Adjust the SKB for padding and checksum */ - skb_reserve(rx_buf->skb, NET_IP_ALIGN); - rx_buf->len = skb_len - NET_IP_ALIGN; - rx_buf->data = (char *)rx_buf->skb->data; - rx_buf->skb->ip_summed = CHECKSUM_UNNECESSARY; - - rx_buf->dma_addr = pci_map_single(efx->pci_dev, - rx_buf->data, rx_buf->len, - PCI_DMA_FROMDEVICE); - - if (unlikely(pci_dma_mapping_error(efx->pci_dev, rx_buf->dma_addr))) { - dev_kfree_skb_any(rx_buf->skb); - rx_buf->skb = NULL; - return -EIO; - } - - return 0; -} - -/** - * efx_init_rx_buffer_page - create new RX buffer using page-based allocation - * - * @rx_queue: Efx RX queue - * @rx_buf: RX buffer structure to populate - * - * This allocates memory for a new receive buffer, maps it for DMA, - * and populates a struct efx_rx_buffer with the relevant - * information. Return a negative error code or 0 on success. - */ -static int efx_init_rx_buffer_page(struct efx_rx_queue *rx_queue, - struct efx_rx_buffer *rx_buf) -{ - struct efx_nic *efx = rx_queue->efx; - int bytes, space, offset; - - bytes = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN; - - /* If there is space left in the previously allocated page, - * then use it. Otherwise allocate a new one */ - rx_buf->page = rx_queue->buf_page; - if (rx_buf->page == NULL) { - dma_addr_t dma_addr; - - rx_buf->page = alloc_pages(__GFP_COLD | __GFP_COMP | GFP_ATOMIC, - efx->rx_buffer_order); - if (unlikely(rx_buf->page == NULL)) - return -ENOMEM; - - dma_addr = pci_map_page(efx->pci_dev, rx_buf->page, - 0, efx_rx_buf_size(efx), - PCI_DMA_FROMDEVICE); - - if (unlikely(pci_dma_mapping_error(efx->pci_dev, dma_addr))) { - __free_pages(rx_buf->page, efx->rx_buffer_order); - rx_buf->page = NULL; - return -EIO; - } - - rx_queue->buf_page = rx_buf->page; - rx_queue->buf_dma_addr = dma_addr; - rx_queue->buf_data = (page_address(rx_buf->page) + - EFX_PAGE_IP_ALIGN); - } - - rx_buf->len = bytes; - rx_buf->data = rx_queue->buf_data; - offset = efx_rx_buf_offset(rx_buf); - rx_buf->dma_addr = rx_queue->buf_dma_addr + offset; - - /* Try to pack multiple buffers per page */ - if (efx->rx_buffer_order == 0) { - /* The next buffer starts on the next 512 byte boundary */ - rx_queue->buf_data += ((bytes + 0x1ff) & ~0x1ff); - offset += ((bytes + 0x1ff) & ~0x1ff); - - space = efx_rx_buf_size(efx) - offset; - if (space >= bytes) { - /* Refs dropped on kernel releasing each skb */ - get_page(rx_queue->buf_page); - goto out; - } - } - - /* This is the final RX buffer for this page, so mark it for - * unmapping */ - rx_queue->buf_page = NULL; - rx_buf->unmap_addr = rx_queue->buf_dma_addr; - - out: - return 0; -} - -/* This allocates memory for a new receive buffer, maps it for DMA, - * and populates a struct efx_rx_buffer with the relevant - * information. - */ -static int efx_init_rx_buffer(struct efx_rx_queue *rx_queue, - struct efx_rx_buffer *new_rx_buf) -{ - int rc = 0; - - if (rx_queue->channel->rx_alloc_push_pages) { - new_rx_buf->skb = NULL; - rc = efx_init_rx_buffer_page(rx_queue, new_rx_buf); - rx_queue->alloc_page_count++; - } else { - new_rx_buf->page = NULL; - rc = efx_init_rx_buffer_skb(rx_queue, new_rx_buf); - rx_queue->alloc_skb_count++; - } - - if (unlikely(rc < 0)) - EFX_LOG_RL(rx_queue->efx, "%s RXQ[%d] =%d\n", __func__, - rx_queue->queue, rc); - return rc; -} - -static void efx_unmap_rx_buffer(struct efx_nic *efx, - struct efx_rx_buffer *rx_buf) -{ - if (rx_buf->page) { - EFX_BUG_ON_PARANOID(rx_buf->skb); - if (rx_buf->unmap_addr) { - pci_unmap_page(efx->pci_dev, rx_buf->unmap_addr, - efx_rx_buf_size(efx), - PCI_DMA_FROMDEVICE); - rx_buf->unmap_addr = 0; - } - } else if (likely(rx_buf->skb)) { - pci_unmap_single(efx->pci_dev, rx_buf->dma_addr, - rx_buf->len, PCI_DMA_FROMDEVICE); - } -} - -static void efx_free_rx_buffer(struct efx_nic *efx, - struct efx_rx_buffer *rx_buf) -{ - if (rx_buf->page) { - __free_pages(rx_buf->page, efx->rx_buffer_order); - rx_buf->page = NULL; - } else if (likely(rx_buf->skb)) { - dev_kfree_skb_any(rx_buf->skb); - rx_buf->skb = NULL; - } -} - -static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue, - struct efx_rx_buffer *rx_buf) -{ - efx_unmap_rx_buffer(rx_queue->efx, rx_buf); - efx_free_rx_buffer(rx_queue->efx, rx_buf); -} - -/** - * efx_fast_push_rx_descriptors - push new RX descriptors quickly - * @rx_queue: RX descriptor queue - * @retry: Recheck the fill level - * This will aim to fill the RX descriptor queue up to - * @rx_queue->@fast_fill_limit. If there is insufficient atomic - * memory to do so, the caller should retry. - */ -static int __efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue, - int retry) -{ - struct efx_rx_buffer *rx_buf; - unsigned fill_level, index; - int i, space, rc = 0; - - /* Calculate current fill level. Do this outside the lock, - * because most of the time we'll end up not wanting to do the - * fill anyway. - */ - fill_level = (rx_queue->added_count - rx_queue->removed_count); - EFX_BUG_ON_PARANOID(fill_level > - rx_queue->efx->type->rxd_ring_mask + 1); - - /* Don't fill if we don't need to */ - if (fill_level >= rx_queue->fast_fill_trigger) - return 0; - - /* Record minimum fill level */ - if (unlikely(fill_level < rx_queue->min_fill)) { - if (fill_level) - rx_queue->min_fill = fill_level; - } - - /* Acquire RX add lock. If this lock is contended, then a fast - * fill must already be in progress (e.g. in the refill - * tasklet), so we don't need to do anything - */ - if (!spin_trylock_bh(&rx_queue->add_lock)) - return -1; - - retry: - /* Recalculate current fill level now that we have the lock */ - fill_level = (rx_queue->added_count - rx_queue->removed_count); - EFX_BUG_ON_PARANOID(fill_level > - rx_queue->efx->type->rxd_ring_mask + 1); - space = rx_queue->fast_fill_limit - fill_level; - if (space < EFX_RX_BATCH) - goto out_unlock; - - EFX_TRACE(rx_queue->efx, "RX queue %d fast-filling descriptor ring from" - " level %d to level %d using %s allocation\n", - rx_queue->queue, fill_level, rx_queue->fast_fill_limit, - rx_queue->channel->rx_alloc_push_pages ? "page" : "skb"); - - do { - for (i = 0; i < EFX_RX_BATCH; ++i) { - index = (rx_queue->added_count & - rx_queue->efx->type->rxd_ring_mask); - rx_buf = efx_rx_buffer(rx_queue, index); - rc = efx_init_rx_buffer(rx_queue, rx_buf); - if (unlikely(rc)) - goto out; - ++rx_queue->added_count; - } - } while ((space -= EFX_RX_BATCH) >= EFX_RX_BATCH); - - EFX_TRACE(rx_queue->efx, "RX queue %d fast-filled descriptor ring " - "to level %d\n", rx_queue->queue, - rx_queue->added_count - rx_queue->removed_count); - - out: - /* Send write pointer to card. */ - falcon_notify_rx_desc(rx_queue); - - /* If the fast fill is running inside from the refill tasklet, then - * for SMP systems it may be running on a different CPU to - * RX event processing, which means that the fill level may now be - * out of date. */ - if (unlikely(retry && (rc == 0))) - goto retry; - - out_unlock: - spin_unlock_bh(&rx_queue->add_lock); - - return rc; -} - -/** - * efx_fast_push_rx_descriptors - push new RX descriptors quickly - * @rx_queue: RX descriptor queue - * - * This will aim to fill the RX descriptor queue up to - * @rx_queue->@fast_fill_limit. If there is insufficient memory to do so, - * it will schedule a work item to immediately continue the fast fill - */ -void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue) -{ - int rc; - - rc = __efx_fast_push_rx_descriptors(rx_queue, 0); - if (unlikely(rc)) { - /* Schedule the work item to run immediately. The hope is - * that work is immediately pending to free some memory - * (e.g. an RX event or TX completion) - */ - efx_schedule_slow_fill(rx_queue, 0); - } -} - -void efx_rx_work(struct work_struct *data) -{ - struct efx_rx_queue *rx_queue; - int rc; - - rx_queue = container_of(data, struct efx_rx_queue, work.work); - - if (unlikely(!rx_queue->channel->enabled)) - return; - - EFX_TRACE(rx_queue->efx, "RX queue %d worker thread executing on CPU " - "%d\n", rx_queue->queue, raw_smp_processor_id()); - - ++rx_queue->slow_fill_count; - /* Push new RX descriptors, allowing at least 1 jiffy for - * the kernel to free some more memory. */ - rc = __efx_fast_push_rx_descriptors(rx_queue, 1); - if (rc) - efx_schedule_slow_fill(rx_queue, 1); -} - -static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue, - struct efx_rx_buffer *rx_buf, - int len, bool *discard, - bool *leak_packet) -{ - struct efx_nic *efx = rx_queue->efx; - unsigned max_len = rx_buf->len - efx->type->rx_buffer_padding; - - if (likely(len <= max_len)) - return; - - /* The packet must be discarded, but this is only a fatal error - * if the caller indicated it was - */ - *discard = true; - - if ((len > rx_buf->len) && EFX_WORKAROUND_8071(efx)) { - EFX_ERR_RL(efx, " RX queue %d seriously overlength " - "RX event (0x%x > 0x%x+0x%x). Leaking\n", - rx_queue->queue, len, max_len, - efx->type->rx_buffer_padding); - /* If this buffer was skb-allocated, then the meta - * data at the end of the skb will be trashed. So - * we have no choice but to leak the fragment. - */ - *leak_packet = (rx_buf->skb != NULL); - efx_schedule_reset(efx, RESET_TYPE_RX_RECOVERY); - } else { - EFX_ERR_RL(efx, " RX queue %d overlength RX event " - "(0x%x > 0x%x)\n", rx_queue->queue, len, max_len); - } - - rx_queue->channel->n_rx_overlength++; -} - -/* Pass a received packet up through the generic LRO stack - * - * Handles driverlink veto, and passes the fragment up via - * the appropriate LRO method - */ -static void efx_rx_packet_lro(struct efx_channel *channel, - struct efx_rx_buffer *rx_buf) -{ - struct net_lro_mgr *lro_mgr = &channel->lro_mgr; - void *priv = channel; - - /* Pass the skb/page into the LRO engine */ - if (rx_buf->page) { - struct skb_frag_struct frags; - - frags.page = rx_buf->page; - frags.page_offset = efx_rx_buf_offset(rx_buf); - frags.size = rx_buf->len; - - lro_receive_frags(lro_mgr, &frags, rx_buf->len, - rx_buf->len, priv, 0); - - EFX_BUG_ON_PARANOID(rx_buf->skb); - rx_buf->page = NULL; - } else { - EFX_BUG_ON_PARANOID(!rx_buf->skb); - - lro_receive_skb(lro_mgr, rx_buf->skb, priv); - rx_buf->skb = NULL; - } -} - -/* Allocate and construct an SKB around a struct page.*/ -static struct sk_buff *efx_rx_mk_skb(struct efx_rx_buffer *rx_buf, - struct efx_nic *efx, - int hdr_len) -{ - struct sk_buff *skb; - - /* Allocate an SKB to store the headers */ - skb = netdev_alloc_skb(efx->net_dev, hdr_len + EFX_PAGE_SKB_ALIGN); - if (unlikely(skb == NULL)) { - EFX_ERR_RL(efx, "RX out of memory for skb\n"); - return NULL; - } - - EFX_BUG_ON_PARANOID(skb_shinfo(skb)->nr_frags); - EFX_BUG_ON_PARANOID(rx_buf->len < hdr_len); - - skb->ip_summed = CHECKSUM_UNNECESSARY; - skb_reserve(skb, EFX_PAGE_SKB_ALIGN); - - skb->len = rx_buf->len; - skb->truesize = rx_buf->len + sizeof(struct sk_buff); - memcpy(skb->data, rx_buf->data, hdr_len); - skb->tail += hdr_len; - - /* Append the remaining page onto the frag list */ - if (unlikely(rx_buf->len > hdr_len)) { - struct skb_frag_struct *frag = skb_shinfo(skb)->frags; - frag->page = rx_buf->page; - frag->page_offset = efx_rx_buf_offset(rx_buf) + hdr_len; - frag->size = skb->len - hdr_len; - skb_shinfo(skb)->nr_frags = 1; - skb->data_len = frag->size; - } else { - __free_pages(rx_buf->page, efx->rx_buffer_order); - skb->data_len = 0; - } - - /* Ownership has transferred from the rx_buf to skb */ - rx_buf->page = NULL; - - /* Move past the ethernet header */ - skb->protocol = eth_type_trans(skb, efx->net_dev); - - return skb; -} - -void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index, - unsigned int len, bool checksummed, bool discard) -{ - struct efx_nic *efx = rx_queue->efx; - struct efx_rx_buffer *rx_buf; - bool leak_packet = false; - - rx_buf = efx_rx_buffer(rx_queue, index); - EFX_BUG_ON_PARANOID(!rx_buf->data); - EFX_BUG_ON_PARANOID(rx_buf->skb && rx_buf->page); - EFX_BUG_ON_PARANOID(!(rx_buf->skb || rx_buf->page)); - - /* This allows the refill path to post another buffer. - * EFX_RXD_HEAD_ROOM ensures that the slot we are using - * isn't overwritten yet. - */ - rx_queue->removed_count++; - - /* Validate the length encoded in the event vs the descriptor pushed */ - efx_rx_packet__check_len(rx_queue, rx_buf, len, - &discard, &leak_packet); - - EFX_TRACE(efx, "RX queue %d received id %x at %llx+%x %s%s\n", - rx_queue->queue, index, - (unsigned long long)rx_buf->dma_addr, len, - (checksummed ? " [SUMMED]" : ""), - (discard ? " [DISCARD]" : "")); - - /* Discard packet, if instructed to do so */ - if (unlikely(discard)) { - if (unlikely(leak_packet)) - rx_queue->channel->n_skbuff_leaks++; - else - /* We haven't called efx_unmap_rx_buffer yet, - * so fini the entire rx_buffer here */ - efx_fini_rx_buffer(rx_queue, rx_buf); - return; - } - - /* Release card resources - assumes all RX buffers consumed in-order - * per RX queue - */ - efx_unmap_rx_buffer(efx, rx_buf); - - /* Prefetch nice and early so data will (hopefully) be in cache by - * the time we look at it. - */ - prefetch(rx_buf->data); - - /* Pipeline receives so that we give time for packet headers to be - * prefetched into cache. - */ - rx_buf->len = len; - if (rx_queue->channel->rx_pkt) - __efx_rx_packet(rx_queue->channel, - rx_queue->channel->rx_pkt, - rx_queue->channel->rx_pkt_csummed); - rx_queue->channel->rx_pkt = rx_buf; - rx_queue->channel->rx_pkt_csummed = checksummed; -} - -/* Handle a received packet. Second half: Touches packet payload. */ -void __efx_rx_packet(struct efx_channel *channel, - struct efx_rx_buffer *rx_buf, bool checksummed) -{ - struct efx_nic *efx = channel->efx; - struct sk_buff *skb; - bool lro = !!(efx->net_dev->features & NETIF_F_LRO); - - /* If we're in loopback test, then pass the packet directly to the - * loopback layer, and free the rx_buf here - */ - if (unlikely(efx->loopback_selftest)) { - efx_loopback_rx_packet(efx, rx_buf->data, rx_buf->len); - efx_free_rx_buffer(efx, rx_buf); - goto done; - } - - if (rx_buf->skb) { - prefetch(skb_shinfo(rx_buf->skb)); - - skb_put(rx_buf->skb, rx_buf->len); - - /* Move past the ethernet header. rx_buf->data still points - * at the ethernet header */ - rx_buf->skb->protocol = eth_type_trans(rx_buf->skb, - efx->net_dev); - } - - /* Both our generic-LRO and SFC-SSR support skb and page based - * allocation, but neither support switching from one to the - * other on the fly. If we spot that the allocation mode has - * changed, then flush the LRO state. - */ - if (unlikely(channel->rx_alloc_pop_pages != (rx_buf->page != NULL))) { - efx_flush_lro(channel); - channel->rx_alloc_pop_pages = (rx_buf->page != NULL); - } - if (likely(checksummed && lro)) { - efx_rx_packet_lro(channel, rx_buf); - goto done; - } - - /* Form an skb if required */ - if (rx_buf->page) { - int hdr_len = min(rx_buf->len, EFX_SKB_HEADERS); - skb = efx_rx_mk_skb(rx_buf, efx, hdr_len); - if (unlikely(skb == NULL)) { - efx_free_rx_buffer(efx, rx_buf); - goto done; - } - } else { - /* We now own the SKB */ - skb = rx_buf->skb; - rx_buf->skb = NULL; - } - - EFX_BUG_ON_PARANOID(rx_buf->page); - EFX_BUG_ON_PARANOID(rx_buf->skb); - EFX_BUG_ON_PARANOID(!skb); - - /* Set the SKB flags */ - if (unlikely(!checksummed || !efx->rx_checksum_enabled)) - skb->ip_summed = CHECKSUM_NONE; - - /* Pass the packet up */ - netif_receive_skb(skb); - - /* Update allocation strategy method */ - channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB; - -done: - ; -} - -void efx_rx_strategy(struct efx_channel *channel) -{ - enum efx_rx_alloc_method method = rx_alloc_method; - - /* Only makes sense to use page based allocation if LRO is enabled */ - if (!(channel->efx->net_dev->features & NETIF_F_LRO)) { - method = RX_ALLOC_METHOD_SKB; - } else if (method == RX_ALLOC_METHOD_AUTO) { - /* Constrain the rx_alloc_level */ - if (channel->rx_alloc_level < 0) - channel->rx_alloc_level = 0; - else if (channel->rx_alloc_level > RX_ALLOC_LEVEL_MAX) - channel->rx_alloc_level = RX_ALLOC_LEVEL_MAX; - - /* Decide on the allocation method */ - method = ((channel->rx_alloc_level > RX_ALLOC_LEVEL_LRO) ? - RX_ALLOC_METHOD_PAGE : RX_ALLOC_METHOD_SKB); - } - - /* Push the option */ - channel->rx_alloc_push_pages = (method == RX_ALLOC_METHOD_PAGE); -} - -int efx_probe_rx_queue(struct efx_rx_queue *rx_queue) -{ - struct efx_nic *efx = rx_queue->efx; - unsigned int rxq_size; - int rc; - - EFX_LOG(efx, "creating RX queue %d\n", rx_queue->queue); - - /* Allocate RX buffers */ - rxq_size = (efx->type->rxd_ring_mask + 1) * sizeof(*rx_queue->buffer); - rx_queue->buffer = kzalloc(rxq_size, GFP_KERNEL); - if (!rx_queue->buffer) - return -ENOMEM; - - rc = falcon_probe_rx(rx_queue); - if (rc) { - kfree(rx_queue->buffer); - rx_queue->buffer = NULL; - } - return rc; -} - -void efx_init_rx_queue(struct efx_rx_queue *rx_queue) -{ - struct efx_nic *efx = rx_queue->efx; - unsigned int max_fill, trigger, limit; - - EFX_LOG(rx_queue->efx, "initialising RX queue %d\n", rx_queue->queue); - - /* Initialise ptr fields */ - rx_queue->added_count = 0; - rx_queue->notified_count = 0; - rx_queue->removed_count = 0; - rx_queue->min_fill = -1U; - rx_queue->min_overfill = -1U; - - /* Initialise limit fields */ - max_fill = efx->type->rxd_ring_mask + 1 - EFX_RXD_HEAD_ROOM; - trigger = max_fill * min(rx_refill_threshold, 100U) / 100U; - limit = max_fill * min(rx_refill_limit, 100U) / 100U; - - rx_queue->max_fill = max_fill; - rx_queue->fast_fill_trigger = trigger; - rx_queue->fast_fill_limit = limit; - - /* Set up RX descriptor ring */ - falcon_init_rx(rx_queue); -} - -void efx_fini_rx_queue(struct efx_rx_queue *rx_queue) -{ - int i; - struct efx_rx_buffer *rx_buf; - - EFX_LOG(rx_queue->efx, "shutting down RX queue %d\n", rx_queue->queue); - - falcon_fini_rx(rx_queue); - - /* Release RX buffers NB start at index 0 not current HW ptr */ - if (rx_queue->buffer) { - for (i = 0; i <= rx_queue->efx->type->rxd_ring_mask; i++) { - rx_buf = efx_rx_buffer(rx_queue, i); - efx_fini_rx_buffer(rx_queue, rx_buf); - } - } - - /* For a page that is part-way through splitting into RX buffers */ - if (rx_queue->buf_page != NULL) { - pci_unmap_page(rx_queue->efx->pci_dev, rx_queue->buf_dma_addr, - efx_rx_buf_size(rx_queue->efx), - PCI_DMA_FROMDEVICE); - __free_pages(rx_queue->buf_page, - rx_queue->efx->rx_buffer_order); - rx_queue->buf_page = NULL; - } -} - -void efx_remove_rx_queue(struct efx_rx_queue *rx_queue) -{ - EFX_LOG(rx_queue->efx, "destroying RX queue %d\n", rx_queue->queue); - - falcon_remove_rx(rx_queue); - - kfree(rx_queue->buffer); - rx_queue->buffer = NULL; -} - -void efx_flush_lro(struct efx_channel *channel) -{ - lro_flush_all(&channel->lro_mgr); -} - - -module_param(rx_alloc_method, int, 0644); -MODULE_PARM_DESC(rx_alloc_method, "Allocation method used for RX buffers"); - -module_param(rx_refill_threshold, uint, 0444); -MODULE_PARM_DESC(rx_refill_threshold, - "RX descriptor ring fast/slow fill threshold (%)"); - diff --git a/drivers/net/sfc/rx.h b/drivers/net/sfc/rx.h deleted file mode 100644 index 0e88a9ddc1c..00000000000 --- a/drivers/net/sfc/rx.h +++ /dev/null @@ -1,29 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2006 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_RX_H -#define EFX_RX_H - -#include "net_driver.h" - -int efx_probe_rx_queue(struct efx_rx_queue *rx_queue); -void efx_remove_rx_queue(struct efx_rx_queue *rx_queue); -void efx_init_rx_queue(struct efx_rx_queue *rx_queue); -void efx_fini_rx_queue(struct efx_rx_queue *rx_queue); - -int efx_lro_init(struct net_lro_mgr *lro_mgr, struct efx_nic *efx); -void efx_lro_fini(struct net_lro_mgr *lro_mgr); -void efx_flush_lro(struct efx_channel *channel); -void efx_rx_strategy(struct efx_channel *channel); -void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue); -void efx_rx_work(struct work_struct *data); -void __efx_rx_packet(struct efx_channel *channel, - struct efx_rx_buffer *rx_buf, bool checksummed); - -#endif /* EFX_RX_H */ diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c deleted file mode 100644 index 0a598084c51..00000000000 --- a/drivers/net/sfc/selftest.c +++ /dev/null @@ -1,762 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2006-2008 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. - */ - -#include <linux/netdevice.h> -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/kernel_stat.h> -#include <linux/pci.h> -#include <linux/ethtool.h> -#include <linux/ip.h> -#include <linux/in.h> -#include <linux/udp.h> -#include <linux/rtnetlink.h> -#include <asm/io.h> -#include "net_driver.h" -#include "ethtool.h" -#include "efx.h" -#include "falcon.h" -#include "selftest.h" -#include "boards.h" -#include "workarounds.h" -#include "spi.h" -#include "falcon_io.h" -#include "mdio_10g.h" - -/* - * Loopback test packet structure - * - * The self-test should stress every RSS vector, and unfortunately - * Falcon only performs RSS on TCP/UDP packets. - */ -struct efx_loopback_payload { - struct ethhdr header; - struct iphdr ip; - struct udphdr udp; - __be16 iteration; - const char msg[64]; -} __attribute__ ((packed)); - -/* Loopback test source MAC address */ -static const unsigned char payload_source[ETH_ALEN] = { - 0x00, 0x0f, 0x53, 0x1b, 0x1b, 0x1b, -}; - -static const char *payload_msg = - "Hello world! This is an Efx loopback test in progress!"; - -/** - * efx_loopback_state - persistent state during a loopback selftest - * @flush: Drop all packets in efx_loopback_rx_packet - * @packet_count: Number of packets being used in this test - * @skbs: An array of skbs transmitted - * @rx_good: RX good packet count - * @rx_bad: RX bad packet count - * @payload: Payload used in tests - */ -struct efx_loopback_state { - bool flush; - int packet_count; - struct sk_buff **skbs; - - /* Checksums are being offloaded */ - bool offload_csum; - - atomic_t rx_good; - atomic_t rx_bad; - struct efx_loopback_payload payload; -}; - -/************************************************************************** - * - * MII, NVRAM and register tests - * - **************************************************************************/ - -static int efx_test_mii(struct efx_nic *efx, struct efx_self_tests *tests) -{ - int rc = 0; - u16 physid1, physid2; - struct mii_if_info *mii = &efx->mii; - struct net_device *net_dev = efx->net_dev; - - if (efx->phy_type == PHY_TYPE_NONE) - return 0; - - mutex_lock(&efx->mac_lock); - tests->mii = -1; - - physid1 = mii->mdio_read(net_dev, mii->phy_id, MII_PHYSID1); - physid2 = mii->mdio_read(net_dev, mii->phy_id, MII_PHYSID2); - - if ((physid1 == 0x0000) || (physid1 == 0xffff) || - (physid2 == 0x0000) || (physid2 == 0xffff)) { - EFX_ERR(efx, "no MII PHY present with ID %d\n", - mii->phy_id); - rc = -EINVAL; - goto out; - } - - if (EFX_IS10G(efx)) { - rc = mdio_clause45_check_mmds(efx, efx->phy_op->mmds, 0); - if (rc) - goto out; - } - -out: - mutex_unlock(&efx->mac_lock); - tests->mii = rc ? -1 : 1; - return rc; -} - -static int efx_test_nvram(struct efx_nic *efx, struct efx_self_tests *tests) -{ - int rc; - - rc = falcon_read_nvram(efx, NULL); - tests->nvram = rc ? -1 : 1; - return rc; -} - -static int efx_test_chip(struct efx_nic *efx, struct efx_self_tests *tests) -{ - int rc; - - /* Not supported on A-series silicon */ - if (falcon_rev(efx) < FALCON_REV_B0) - return 0; - - rc = falcon_test_registers(efx); - tests->registers = rc ? -1 : 1; - return rc; -} - -/************************************************************************** - * - * Interrupt and event queue testing - * - **************************************************************************/ - -/* Test generation and receipt of interrupts */ -static int efx_test_interrupts(struct efx_nic *efx, - struct efx_self_tests *tests) -{ - struct efx_channel *channel; - - EFX_LOG(efx, "testing interrupts\n"); - tests->interrupt = -1; - - /* Reset interrupt flag */ - efx->last_irq_cpu = -1; - smp_wmb(); - - /* ACK each interrupting event queue. Receiving an interrupt due to - * traffic before a test event is raised is considered a pass */ - efx_for_each_channel(channel, efx) { - if (channel->work_pending) - efx_process_channel_now(channel); - if (efx->last_irq_cpu >= 0) - goto success; - } - - falcon_generate_interrupt(efx); - - /* Wait for arrival of test interrupt. */ - EFX_LOG(efx, "waiting for test interrupt\n"); - schedule_timeout_uninterruptible(HZ / 10); - if (efx->last_irq_cpu >= 0) - goto success; - - EFX_ERR(efx, "timed out waiting for interrupt\n"); - return -ETIMEDOUT; - - success: - EFX_LOG(efx, "test interrupt (mode %d) seen on CPU%d\n", - efx->interrupt_mode, efx->last_irq_cpu); - tests->interrupt = 1; - return 0; -} - -/* Test generation and receipt of interrupting events */ -static int efx_test_eventq_irq(struct efx_channel *channel, - struct efx_self_tests *tests) -{ - unsigned int magic, count; - - /* Channel specific code, limited to 20 bits */ - magic = (0x00010150 + channel->channel); - EFX_LOG(channel->efx, "channel %d testing event queue with code %x\n", - channel->channel, magic); - - tests->eventq_dma[channel->channel] = -1; - tests->eventq_int[channel->channel] = -1; - tests->eventq_poll[channel->channel] = -1; - - /* Reset flag and zero magic word */ - channel->efx->last_irq_cpu = -1; - channel->eventq_magic = 0; - smp_wmb(); - - falcon_generate_test_event(channel, magic); - - /* Wait for arrival of interrupt */ - count = 0; - do { - schedule_timeout_uninterruptible(HZ / 100); - - if (channel->work_pending) - efx_process_channel_now(channel); - - if (channel->eventq_magic == magic) - goto eventq_ok; - } while (++count < 2); - - EFX_ERR(channel->efx, "channel %d timed out waiting for event queue\n", - channel->channel); - - /* See if interrupt arrived */ - if (channel->efx->last_irq_cpu >= 0) { - EFX_ERR(channel->efx, "channel %d saw interrupt on CPU%d " - "during event queue test\n", channel->channel, - raw_smp_processor_id()); - tests->eventq_int[channel->channel] = 1; - } - - /* Check to see if event was received even if interrupt wasn't */ - efx_process_channel_now(channel); - if (channel->eventq_magic == magic) { - EFX_ERR(channel->efx, "channel %d event was generated, but " - "failed to trigger an interrupt\n", channel->channel); - tests->eventq_dma[channel->channel] = 1; - } - - return -ETIMEDOUT; - eventq_ok: - EFX_LOG(channel->efx, "channel %d event queue passed\n", - channel->channel); - tests->eventq_dma[channel->channel] = 1; - tests->eventq_int[channel->channel] = 1; - tests->eventq_poll[channel->channel] = 1; - return 0; -} - -static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests, - unsigned flags) -{ - int rc; - - if (!efx->phy_op->run_tests) - return 0; - - EFX_BUG_ON_PARANOID(efx->phy_op->num_tests == 0 || - efx->phy_op->num_tests > EFX_MAX_PHY_TESTS); - - mutex_lock(&efx->mac_lock); - rc = efx->phy_op->run_tests(efx, tests->phy, flags); - mutex_unlock(&efx->mac_lock); - return rc; -} - -/************************************************************************** - * - * Loopback testing - * NB Only one loopback test can be executing concurrently. - * - **************************************************************************/ - -/* Loopback test RX callback - * This is called for each received packet during loopback testing. - */ -void efx_loopback_rx_packet(struct efx_nic *efx, - const char *buf_ptr, int pkt_len) -{ - struct efx_loopback_state *state = efx->loopback_selftest; - struct efx_loopback_payload *received; - struct efx_loopback_payload *payload; - - BUG_ON(!buf_ptr); - - /* If we are just flushing, then drop the packet */ - if ((state == NULL) || state->flush) - return; - - payload = &state->payload; - - received = (struct efx_loopback_payload *) buf_ptr; - received->ip.saddr = payload->ip.saddr; - if (state->offload_csum) - received->ip.check = payload->ip.check; - - /* Check that header exists */ - if (pkt_len < sizeof(received->header)) { - EFX_ERR(efx, "saw runt RX packet (length %d) in %s loopback " - "test\n", pkt_len, LOOPBACK_MODE(efx)); - goto err; - } - - /* Check that the ethernet header exists */ - if (memcmp(&received->header, &payload->header, ETH_HLEN) != 0) { - EFX_ERR(efx, "saw non-loopback RX packet in %s loopback test\n", - LOOPBACK_MODE(efx)); - goto err; - } - - /* Check packet length */ - if (pkt_len != sizeof(*payload)) { - EFX_ERR(efx, "saw incorrect RX packet length %d (wanted %d) in " - "%s loopback test\n", pkt_len, (int)sizeof(*payload), - LOOPBACK_MODE(efx)); - goto err; - } - - /* Check that IP header matches */ - if (memcmp(&received->ip, &payload->ip, sizeof(payload->ip)) != 0) { - EFX_ERR(efx, "saw corrupted IP header in %s loopback test\n", - LOOPBACK_MODE(efx)); - goto err; - } - - /* Check that msg and padding matches */ - if (memcmp(&received->msg, &payload->msg, sizeof(received->msg)) != 0) { - EFX_ERR(efx, "saw corrupted RX packet in %s loopback test\n", - LOOPBACK_MODE(efx)); - goto err; - } - - /* Check that iteration matches */ - if (received->iteration != payload->iteration) { - EFX_ERR(efx, "saw RX packet from iteration %d (wanted %d) in " - "%s loopback test\n", ntohs(received->iteration), - ntohs(payload->iteration), LOOPBACK_MODE(efx)); - goto err; - } - - /* Increase correct RX count */ - EFX_TRACE(efx, "got loopback RX in %s loopback test\n", - LOOPBACK_MODE(efx)); - - atomic_inc(&state->rx_good); - return; - - err: -#ifdef EFX_ENABLE_DEBUG - if (atomic_read(&state->rx_bad) == 0) { - EFX_ERR(efx, "received packet:\n"); - print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1, - buf_ptr, pkt_len, 0); - EFX_ERR(efx, "expected packet:\n"); - print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1, - &state->payload, sizeof(state->payload), 0); - } -#endif - atomic_inc(&state->rx_bad); -} - -/* Initialise an efx_selftest_state for a new iteration */ -static void efx_iterate_state(struct efx_nic *efx) -{ - struct efx_loopback_state *state = efx->loopback_selftest; - struct net_device *net_dev = efx->net_dev; - struct efx_loopback_payload *payload = &state->payload; - - /* Initialise the layerII header */ - memcpy(&payload->header.h_dest, net_dev->dev_addr, ETH_ALEN); - memcpy(&payload->header.h_source, &payload_source, ETH_ALEN); - payload->header.h_proto = htons(ETH_P_IP); - - /* saddr set later and used as incrementing count */ - payload->ip.daddr = htonl(INADDR_LOOPBACK); - payload->ip.ihl = 5; - payload->ip.check = htons(0xdead); - payload->ip.tot_len = htons(sizeof(*payload) - sizeof(struct ethhdr)); - payload->ip.version = IPVERSION; - payload->ip.protocol = IPPROTO_UDP; - - /* Initialise udp header */ - payload->udp.source = 0; - payload->udp.len = htons(sizeof(*payload) - sizeof(struct ethhdr) - - sizeof(struct iphdr)); - payload->udp.check = 0; /* checksum ignored */ - - /* Fill out payload */ - payload->iteration = htons(ntohs(payload->iteration) + 1); - memcpy(&payload->msg, payload_msg, sizeof(payload_msg)); - - /* Fill out remaining state members */ - atomic_set(&state->rx_good, 0); - atomic_set(&state->rx_bad, 0); - smp_wmb(); -} - -static int efx_begin_loopback(struct efx_tx_queue *tx_queue) -{ - struct efx_nic *efx = tx_queue->efx; - struct efx_loopback_state *state = efx->loopback_selftest; - struct efx_loopback_payload *payload; - struct sk_buff *skb; - int i, rc; - - /* Transmit N copies of buffer */ - for (i = 0; i < state->packet_count; i++) { - /* Allocate an skb, holding an extra reference for - * transmit completion counting */ - skb = alloc_skb(sizeof(state->payload), GFP_KERNEL); - if (!skb) - return -ENOMEM; - state->skbs[i] = skb; - skb_get(skb); - - /* Copy the payload in, incrementing the source address to - * exercise the rss vectors */ - payload = ((struct efx_loopback_payload *) - skb_put(skb, sizeof(state->payload))); - memcpy(payload, &state->payload, sizeof(state->payload)); - payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2)); - - /* Ensure everything we've written is visible to the - * interrupt handler. */ - smp_wmb(); - - if (efx_dev_registered(efx)) - netif_tx_lock_bh(efx->net_dev); - rc = efx_xmit(efx, tx_queue, skb); - if (efx_dev_registered(efx)) - netif_tx_unlock_bh(efx->net_dev); - - if (rc != NETDEV_TX_OK) { - EFX_ERR(efx, "TX queue %d could not transmit packet %d " - "of %d in %s loopback test\n", tx_queue->queue, - i + 1, state->packet_count, LOOPBACK_MODE(efx)); - - /* Defer cleaning up the other skbs for the caller */ - kfree_skb(skb); - return -EPIPE; - } - } - - return 0; -} - -static int efx_poll_loopback(struct efx_nic *efx) -{ - struct efx_loopback_state *state = efx->loopback_selftest; - struct efx_channel *channel; - - /* NAPI polling is not enabled, so process channels - * synchronously */ - efx_for_each_channel(channel, efx) { - if (channel->work_pending) - efx_process_channel_now(channel); - } - return atomic_read(&state->rx_good) == state->packet_count; -} - -static int efx_end_loopback(struct efx_tx_queue *tx_queue, - struct efx_loopback_self_tests *lb_tests) -{ - struct efx_nic *efx = tx_queue->efx; - struct efx_loopback_state *state = efx->loopback_selftest; - struct sk_buff *skb; - int tx_done = 0, rx_good, rx_bad; - int i, rc = 0; - - if (efx_dev_registered(efx)) - netif_tx_lock_bh(efx->net_dev); - - /* Count the number of tx completions, and decrement the refcnt. Any - * skbs not already completed will be free'd when the queue is flushed */ - for (i=0; i < state->packet_count; i++) { - skb = state->skbs[i]; - if (skb && !skb_shared(skb)) - ++tx_done; - dev_kfree_skb_any(skb); - } - - if (efx_dev_registered(efx)) - netif_tx_unlock_bh(efx->net_dev); - - /* Check TX completion and received packet counts */ - rx_good = atomic_read(&state->rx_good); - rx_bad = atomic_read(&state->rx_bad); - if (tx_done != state->packet_count) { - /* Don't free the skbs; they will be picked up on TX - * overflow or channel teardown. - */ - EFX_ERR(efx, "TX queue %d saw only %d out of an expected %d " - "TX completion events in %s loopback test\n", - tx_queue->queue, tx_done, state->packet_count, - LOOPBACK_MODE(efx)); - rc = -ETIMEDOUT; - /* Allow to fall through so we see the RX errors as well */ - } - - /* We may always be up to a flush away from our desired packet total */ - if (rx_good != state->packet_count) { - EFX_LOG(efx, "TX queue %d saw only %d out of an expected %d " - "received packets in %s loopback test\n", - tx_queue->queue, rx_good, state->packet_count, - LOOPBACK_MODE(efx)); - rc = -ETIMEDOUT; - /* Fall through */ - } - - /* Update loopback test structure */ - lb_tests->tx_sent[tx_queue->queue] += state->packet_count; - lb_tests->tx_done[tx_queue->queue] += tx_done; - lb_tests->rx_good += rx_good; - lb_tests->rx_bad += rx_bad; - - return rc; -} - -static int -efx_test_loopback(struct efx_tx_queue *tx_queue, - struct efx_loopback_self_tests *lb_tests) -{ - struct efx_nic *efx = tx_queue->efx; - struct efx_loopback_state *state = efx->loopback_selftest; - int i, begin_rc, end_rc; - - for (i = 0; i < 3; i++) { - /* Determine how many packets to send */ - state->packet_count = (efx->type->txd_ring_mask + 1) / 3; - state->packet_count = min(1 << (i << 2), state->packet_count); - state->skbs = kzalloc(sizeof(state->skbs[0]) * - state->packet_count, GFP_KERNEL); - if (!state->skbs) - return -ENOMEM; - state->flush = false; - - EFX_LOG(efx, "TX queue %d testing %s loopback with %d " - "packets\n", tx_queue->queue, LOOPBACK_MODE(efx), - state->packet_count); - - efx_iterate_state(efx); - begin_rc = efx_begin_loopback(tx_queue); - - /* This will normally complete very quickly, but be - * prepared to wait up to 100 ms. */ - msleep(1); - if (!efx_poll_loopback(efx)) { - msleep(100); - efx_poll_loopback(efx); - } - - end_rc = efx_end_loopback(tx_queue, lb_tests); - kfree(state->skbs); - - if (begin_rc || end_rc) { - /* Wait a while to ensure there are no packets - * floating around after a failure. */ - schedule_timeout_uninterruptible(HZ / 10); - return begin_rc ? begin_rc : end_rc; - } - } - - EFX_LOG(efx, "TX queue %d passed %s loopback test with a burst length " - "of %d packets\n", tx_queue->queue, LOOPBACK_MODE(efx), - state->packet_count); - - return 0; -} - -static int efx_test_loopbacks(struct efx_nic *efx, struct efx_self_tests *tests, - unsigned int loopback_modes) -{ - enum efx_loopback_mode mode; - struct efx_loopback_state *state; - struct efx_tx_queue *tx_queue; - bool link_up; - int count, rc = 0; - - /* Set the port loopback_selftest member. From this point on - * all received packets will be dropped. Mark the state as - * "flushing" so all inflight packets are dropped */ - state = kzalloc(sizeof(*state), GFP_KERNEL); - if (state == NULL) - return -ENOMEM; - BUG_ON(efx->loopback_selftest); - state->flush = true; - efx->loopback_selftest = state; - - /* Test all supported loopback modes */ - for (mode = LOOPBACK_NONE; mode <= LOOPBACK_TEST_MAX; mode++) { - if (!(loopback_modes & (1 << mode))) - continue; - - /* Move the port into the specified loopback mode. */ - state->flush = true; - efx->loopback_mode = mode; - efx_reconfigure_port(efx); - - /* Wait for the PHY to signal the link is up. Interrupts - * are enabled for PHY's using LASI, otherwise we poll() - * quickly */ - count = 0; - do { - struct efx_channel *channel = &efx->channel[0]; - - efx->phy_op->poll(efx); - schedule_timeout_uninterruptible(HZ / 10); - if (channel->work_pending) - efx_process_channel_now(channel); - /* Wait for PHY events to be processed */ - flush_workqueue(efx->workqueue); - rmb(); - - /* We need both the phy and xaui links to be ok. - * rather than relying on the falcon_xmac irq/poll - * regime, just poll xaui directly */ - link_up = efx->link_up; - if (link_up && EFX_IS10G(efx) && - !falcon_xaui_link_ok(efx)) - link_up = false; - - } while ((++count < 20) && !link_up); - - /* The link should now be up. If it isn't, there is no point - * in attempting a loopback test */ - if (!link_up) { - EFX_ERR(efx, "loopback %s never came up\n", - LOOPBACK_MODE(efx)); - rc = -EIO; - goto out; - } - - EFX_LOG(efx, "link came up in %s loopback in %d iterations\n", - LOOPBACK_MODE(efx), count); - - /* Test every TX queue */ - efx_for_each_tx_queue(tx_queue, efx) { - state->offload_csum = (tx_queue->queue == - EFX_TX_QUEUE_OFFLOAD_CSUM); - rc = efx_test_loopback(tx_queue, - &tests->loopback[mode]); - if (rc) - goto out; - } - } - - out: - /* Remove the flush. The caller will remove the loopback setting */ - state->flush = true; - efx->loopback_selftest = NULL; - wmb(); - kfree(state); - - return rc; -} - -/************************************************************************** - * - * Entry point - * - *************************************************************************/ - -int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, - unsigned flags) -{ - enum efx_loopback_mode loopback_mode = efx->loopback_mode; - int phy_mode = efx->phy_mode; - enum reset_type reset_method = RESET_TYPE_INVISIBLE; - struct ethtool_cmd ecmd; - struct efx_channel *channel; - int rc_test = 0, rc_reset = 0, rc; - - /* Online (i.e. non-disruptive) testing - * This checks interrupt generation, event delivery and PHY presence. */ - - rc = efx_test_mii(efx, tests); - if (rc && !rc_test) - rc_test = rc; - - rc = efx_test_nvram(efx, tests); - if (rc && !rc_test) - rc_test = rc; - - rc = efx_test_interrupts(efx, tests); - if (rc && !rc_test) - rc_test = rc; - - efx_for_each_channel(channel, efx) { - rc = efx_test_eventq_irq(channel, tests); - if (rc && !rc_test) - rc_test = rc; - } - - if (rc_test) - return rc_test; - - if (!(flags & ETH_TEST_FL_OFFLINE)) - return efx_test_phy(efx, tests, flags); - - /* Offline (i.e. disruptive) testing - * This checks MAC and PHY loopback on the specified port. */ - - /* force the carrier state off so the kernel doesn't transmit during - * the loopback test, and the watchdog timeout doesn't fire. Also put - * falcon into loopback for the register test. - */ - mutex_lock(&efx->mac_lock); - efx->port_inhibited = true; - if (efx->loopback_modes) { - /* We need the 312 clock from the PHY to test the XMAC - * registers, so move into XGMII loopback if available */ - if (efx->loopback_modes & (1 << LOOPBACK_XGMII)) - efx->loopback_mode = LOOPBACK_XGMII; - else - efx->loopback_mode = __ffs(efx->loopback_modes); - } - - __efx_reconfigure_port(efx); - mutex_unlock(&efx->mac_lock); - - /* free up all consumers of SRAM (including all the queues) */ - efx_reset_down(efx, reset_method, &ecmd); - - rc = efx_test_chip(efx, tests); - if (rc && !rc_test) - rc_test = rc; - - /* reset the chip to recover from the register test */ - rc_reset = falcon_reset_hw(efx, reset_method); - - /* Ensure that the phy is powered and out of loopback - * for the bist and loopback tests */ - efx->phy_mode &= ~PHY_MODE_LOW_POWER; - efx->loopback_mode = LOOPBACK_NONE; - - rc = efx_reset_up(efx, reset_method, &ecmd, rc_reset == 0); - if (rc && !rc_reset) - rc_reset = rc; - - if (rc_reset) { - EFX_ERR(efx, "Unable to recover from chip test\n"); - efx_schedule_reset(efx, RESET_TYPE_DISABLE); - return rc_reset; - } - - rc = efx_test_phy(efx, tests, flags); - if (rc && !rc_test) - rc_test = rc; - - rc = efx_test_loopbacks(efx, tests, efx->loopback_modes); - if (rc && !rc_test) - rc_test = rc; - - /* restore the PHY to the previous state */ - efx->loopback_mode = loopback_mode; - efx->phy_mode = phy_mode; - efx->port_inhibited = false; - efx_ethtool_set_settings(efx->net_dev, &ecmd); - - return rc_test; -} - diff --git a/drivers/net/sfc/selftest.h b/drivers/net/sfc/selftest.h deleted file mode 100644 index 39451cf938c..00000000000 --- a/drivers/net/sfc/selftest.h +++ /dev/null @@ -1,53 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2006-2008 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_SELFTEST_H -#define EFX_SELFTEST_H - -#include "net_driver.h" - -/* - * Self tests - */ - -struct efx_loopback_self_tests { - int tx_sent[EFX_TX_QUEUE_COUNT]; - int tx_done[EFX_TX_QUEUE_COUNT]; - int rx_good; - int rx_bad; -}; - -#define EFX_MAX_PHY_TESTS 20 - -/* Efx self test results - * For fields which are not counters, 1 indicates success and -1 - * indicates failure. - */ -struct efx_self_tests { - /* online tests */ - int mii; - int nvram; - int interrupt; - int eventq_dma[EFX_MAX_CHANNELS]; - int eventq_int[EFX_MAX_CHANNELS]; - int eventq_poll[EFX_MAX_CHANNELS]; - /* offline tests */ - int registers; - int phy[EFX_MAX_PHY_TESTS]; - struct efx_loopback_self_tests loopback[LOOPBACK_TEST_MAX + 1]; -}; - -extern void efx_loopback_rx_packet(struct efx_nic *efx, - const char *buf_ptr, int pkt_len); -extern int efx_selftest(struct efx_nic *efx, - struct efx_self_tests *tests, - unsigned flags); - -#endif /* EFX_SELFTEST_H */ diff --git a/drivers/net/sfc/sfe4001.c b/drivers/net/sfc/sfe4001.c deleted file mode 100644 index cb25ae5b257..00000000000 --- a/drivers/net/sfc/sfe4001.c +++ /dev/null @@ -1,429 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2007-2008 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. - */ - -/***************************************************************************** - * Support for the SFE4001 and SFN4111T NICs. - * - * The SFE4001 does not power-up fully at reset due to its high power - * consumption. We control its power via a PCA9539 I/O expander. - * Both boards have a MAX6647 temperature monitor which we expose to - * the lm90 driver. - * - * This also provides minimal support for reflashing the PHY, which is - * initiated by resetting it with the FLASH_CFG_1 pin pulled down. - * On SFE4001 rev A2 and later this is connected to the 3V3X output of - * the IO-expander; on the SFN4111T it is connected to Falcon's GPIO3. - * We represent reflash mode as PHY_MODE_SPECIAL and make it mutually - * exclusive with the network device being open. - */ - -#include <linux/delay.h> -#include "net_driver.h" -#include "efx.h" -#include "phy.h" -#include "boards.h" -#include "falcon.h" -#include "falcon_hwdefs.h" -#include "falcon_io.h" -#include "mac.h" -#include "workarounds.h" - -/************************************************************************** - * - * I2C IO Expander device - * - **************************************************************************/ -#define PCA9539 0x74 - -#define P0_IN 0x00 -#define P0_OUT 0x02 -#define P0_INVERT 0x04 -#define P0_CONFIG 0x06 - -#define P0_EN_1V0X_LBN 0 -#define P0_EN_1V0X_WIDTH 1 -#define P0_EN_1V2_LBN 1 -#define P0_EN_1V2_WIDTH 1 -#define P0_EN_2V5_LBN 2 -#define P0_EN_2V5_WIDTH 1 -#define P0_EN_3V3X_LBN 3 -#define P0_EN_3V3X_WIDTH 1 -#define P0_EN_5V_LBN 4 -#define P0_EN_5V_WIDTH 1 -#define P0_SHORTEN_JTAG_LBN 5 -#define P0_SHORTEN_JTAG_WIDTH 1 -#define P0_X_TRST_LBN 6 -#define P0_X_TRST_WIDTH 1 -#define P0_DSP_RESET_LBN 7 -#define P0_DSP_RESET_WIDTH 1 - -#define P1_IN 0x01 -#define P1_OUT 0x03 -#define P1_INVERT 0x05 -#define P1_CONFIG 0x07 - -#define P1_AFE_PWD_LBN 0 -#define P1_AFE_PWD_WIDTH 1 -#define P1_DSP_PWD25_LBN 1 -#define P1_DSP_PWD25_WIDTH 1 -#define P1_RESERVED_LBN 2 -#define P1_RESERVED_WIDTH 2 -#define P1_SPARE_LBN 4 -#define P1_SPARE_WIDTH 4 - -/* Temperature Sensor */ -#define MAX664X_REG_RSL 0x02 -#define MAX664X_REG_WLHO 0x0B - -static void sfe4001_poweroff(struct efx_nic *efx) -{ - struct i2c_client *ioexp_client = efx->board_info.ioexp_client; - struct i2c_client *hwmon_client = efx->board_info.hwmon_client; - - /* Turn off all power rails and disable outputs */ - i2c_smbus_write_byte_data(ioexp_client, P0_OUT, 0xff); - i2c_smbus_write_byte_data(ioexp_client, P1_CONFIG, 0xff); - i2c_smbus_write_byte_data(ioexp_client, P0_CONFIG, 0xff); - - /* Clear any over-temperature alert */ - i2c_smbus_read_byte_data(hwmon_client, MAX664X_REG_RSL); -} - -static int sfe4001_poweron(struct efx_nic *efx) -{ - struct i2c_client *hwmon_client = efx->board_info.hwmon_client; - struct i2c_client *ioexp_client = efx->board_info.ioexp_client; - unsigned int i, j; - int rc; - u8 out; - - /* Clear any previous over-temperature alert */ - rc = i2c_smbus_read_byte_data(hwmon_client, MAX664X_REG_RSL); - if (rc < 0) - return rc; - - /* Enable port 0 and port 1 outputs on IO expander */ - rc = i2c_smbus_write_byte_data(ioexp_client, P0_CONFIG, 0x00); - if (rc) - return rc; - rc = i2c_smbus_write_byte_data(ioexp_client, P1_CONFIG, - 0xff & ~(1 << P1_SPARE_LBN)); - if (rc) - goto fail_on; - - /* If PHY power is on, turn it all off and wait 1 second to - * ensure a full reset. - */ - rc = i2c_smbus_read_byte_data(ioexp_client, P0_OUT); - if (rc < 0) - goto fail_on; - out = 0xff & ~((0 << P0_EN_1V2_LBN) | (0 << P0_EN_2V5_LBN) | - (0 << P0_EN_3V3X_LBN) | (0 << P0_EN_5V_LBN) | - (0 << P0_EN_1V0X_LBN)); - if (rc != out) { - EFX_INFO(efx, "power-cycling PHY\n"); - rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out); - if (rc) - goto fail_on; - schedule_timeout_uninterruptible(HZ); - } - - for (i = 0; i < 20; ++i) { - /* Turn on 1.2V, 2.5V, 3.3V and 5V power rails */ - out = 0xff & ~((1 << P0_EN_1V2_LBN) | (1 << P0_EN_2V5_LBN) | - (1 << P0_EN_3V3X_LBN) | (1 << P0_EN_5V_LBN) | - (1 << P0_X_TRST_LBN)); - if (efx->phy_mode & PHY_MODE_SPECIAL) - out |= 1 << P0_EN_3V3X_LBN; - - rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out); - if (rc) - goto fail_on; - msleep(10); - - /* Turn on 1V power rail */ - out &= ~(1 << P0_EN_1V0X_LBN); - rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out); - if (rc) - goto fail_on; - - EFX_INFO(efx, "waiting for DSP boot (attempt %d)...\n", i); - - /* In flash config mode, DSP does not turn on AFE, so - * just wait 1 second. - */ - if (efx->phy_mode & PHY_MODE_SPECIAL) { - schedule_timeout_uninterruptible(HZ); - return 0; - } - - for (j = 0; j < 10; ++j) { - msleep(100); - - /* Check DSP has asserted AFE power line */ - rc = i2c_smbus_read_byte_data(ioexp_client, P1_IN); - if (rc < 0) - goto fail_on; - if (rc & (1 << P1_AFE_PWD_LBN)) - return 0; - } - } - - EFX_INFO(efx, "timed out waiting for DSP boot\n"); - rc = -ETIMEDOUT; -fail_on: - sfe4001_poweroff(efx); - return rc; -} - -static int sfn4111t_reset(struct efx_nic *efx) -{ - efx_oword_t reg; - - /* GPIO 3 and the GPIO register are shared with I2C, so block that */ - mutex_lock(&efx->i2c_adap.bus_lock); - - /* Pull RST_N (GPIO 2) low then let it up again, setting the - * FLASH_CFG_1 strap (GPIO 3) appropriately. Only change the - * output enables; the output levels should always be 0 (low) - * and we rely on external pull-ups. */ - falcon_read(efx, ®, GPIO_CTL_REG_KER); - EFX_SET_OWORD_FIELD(reg, GPIO2_OEN, true); - falcon_write(efx, ®, GPIO_CTL_REG_KER); - msleep(1000); - EFX_SET_OWORD_FIELD(reg, GPIO2_OEN, false); - EFX_SET_OWORD_FIELD(reg, GPIO3_OEN, - !!(efx->phy_mode & PHY_MODE_SPECIAL)); - falcon_write(efx, ®, GPIO_CTL_REG_KER); - msleep(1); - - mutex_unlock(&efx->i2c_adap.bus_lock); - - ssleep(1); - return 0; -} - -static ssize_t show_phy_flash_cfg(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); - return sprintf(buf, "%d\n", !!(efx->phy_mode & PHY_MODE_SPECIAL)); -} - -static ssize_t set_phy_flash_cfg(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); - enum efx_phy_mode old_mode, new_mode; - int err; - - rtnl_lock(); - old_mode = efx->phy_mode; - if (count == 0 || *buf == '0') - new_mode = old_mode & ~PHY_MODE_SPECIAL; - else - new_mode = PHY_MODE_SPECIAL; - if (old_mode == new_mode) { - err = 0; - } else if (efx->state != STATE_RUNNING || netif_running(efx->net_dev)) { - err = -EBUSY; - } else { - /* Reset the PHY, reconfigure the MAC and enable/disable - * MAC stats accordingly. */ - efx->phy_mode = new_mode; - if (new_mode & PHY_MODE_SPECIAL) - efx_stats_disable(efx); - if (efx->board_info.type == EFX_BOARD_SFE4001) - err = sfe4001_poweron(efx); - else - err = sfn4111t_reset(efx); - efx_reconfigure_port(efx); - if (!(new_mode & PHY_MODE_SPECIAL)) - efx_stats_enable(efx); - } - rtnl_unlock(); - - return err ? err : count; -} - -static DEVICE_ATTR(phy_flash_cfg, 0644, show_phy_flash_cfg, set_phy_flash_cfg); - -static void sfe4001_fini(struct efx_nic *efx) -{ - EFX_INFO(efx, "%s\n", __func__); - - device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg); - sfe4001_poweroff(efx); - i2c_unregister_device(efx->board_info.ioexp_client); - i2c_unregister_device(efx->board_info.hwmon_client); -} - -static int sfe4001_check_hw(struct efx_nic *efx) -{ - s32 status; - - /* If XAUI link is up then do not monitor */ - if (EFX_WORKAROUND_7884(efx) && efx->mac_up) - return 0; - - /* Check the powered status of the PHY. Lack of power implies that - * the MAX6647 has shut down power to it, probably due to a temp. - * alarm. Reading the power status rather than the MAX6647 status - * directly because the later is read-to-clear and would thus - * start to power up the PHY again when polled, causing us to blip - * the power undesirably. - * We know we can read from the IO expander because we did - * it during power-on. Assume failure now is bad news. */ - status = i2c_smbus_read_byte_data(efx->board_info.ioexp_client, P1_IN); - if (status >= 0 && - (status & ((1 << P1_AFE_PWD_LBN) | (1 << P1_DSP_PWD25_LBN))) != 0) - return 0; - - /* Use board power control, not PHY power control */ - sfe4001_poweroff(efx); - efx->phy_mode = PHY_MODE_OFF; - - return (status < 0) ? -EIO : -ERANGE; -} - -static struct i2c_board_info sfe4001_hwmon_info = { - I2C_BOARD_INFO("max6647", 0x4e), - .irq = -1, -}; - -/* This board uses an I2C expander to provider power to the PHY, which needs to - * be turned on before the PHY can be used. - * Context: Process context, rtnl lock held - */ -int sfe4001_init(struct efx_nic *efx) -{ - int rc; - -#if defined(CONFIG_SENSORS_LM90) || defined(CONFIG_SENSORS_LM90_MODULE) - efx->board_info.hwmon_client = - i2c_new_device(&efx->i2c_adap, &sfe4001_hwmon_info); -#else - efx->board_info.hwmon_client = - i2c_new_dummy(&efx->i2c_adap, sfe4001_hwmon_info.addr); -#endif - if (!efx->board_info.hwmon_client) - return -EIO; - - /* Raise board/PHY high limit from 85 to 90 degrees Celsius */ - rc = i2c_smbus_write_byte_data(efx->board_info.hwmon_client, - MAX664X_REG_WLHO, 90); - if (rc) - goto fail_hwmon; - - efx->board_info.ioexp_client = i2c_new_dummy(&efx->i2c_adap, PCA9539); - if (!efx->board_info.ioexp_client) { - rc = -EIO; - goto fail_hwmon; - } - - /* 10Xpress has fixed-function LED pins, so there is no board-specific - * blink code. */ - efx->board_info.blink = tenxpress_phy_blink; - - efx->board_info.monitor = sfe4001_check_hw; - efx->board_info.fini = sfe4001_fini; - - if (efx->phy_mode & PHY_MODE_SPECIAL) { - /* PHY won't generate a 156.25 MHz clock and MAC stats fetch - * will fail. */ - efx_stats_disable(efx); - } - rc = sfe4001_poweron(efx); - if (rc) - goto fail_ioexp; - - rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg); - if (rc) - goto fail_on; - - EFX_INFO(efx, "PHY is powered on\n"); - return 0; - -fail_on: - sfe4001_poweroff(efx); -fail_ioexp: - i2c_unregister_device(efx->board_info.ioexp_client); -fail_hwmon: - i2c_unregister_device(efx->board_info.hwmon_client); - return rc; -} - -static int sfn4111t_check_hw(struct efx_nic *efx) -{ - s32 status; - - /* If XAUI link is up then do not monitor */ - if (EFX_WORKAROUND_7884(efx) && efx->mac_up) - return 0; - - /* Test LHIGH, RHIGH, FAULT, EOT and IOT alarms */ - status = i2c_smbus_read_byte_data(efx->board_info.hwmon_client, - MAX664X_REG_RSL); - if (status < 0) - return -EIO; - if (status & 0x57) - return -ERANGE; - return 0; -} - -static void sfn4111t_fini(struct efx_nic *efx) -{ - EFX_INFO(efx, "%s\n", __func__); - - device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg); - i2c_unregister_device(efx->board_info.hwmon_client); -} - -static struct i2c_board_info sfn4111t_a0_hwmon_info = { - I2C_BOARD_INFO("max6647", 0x4e), - .irq = -1, -}; - -static struct i2c_board_info sfn4111t_r5_hwmon_info = { - I2C_BOARD_INFO("max6646", 0x4d), - .irq = -1, -}; - -int sfn4111t_init(struct efx_nic *efx) -{ - int rc; - - efx->board_info.hwmon_client = - i2c_new_device(&efx->i2c_adap, - (efx->board_info.minor < 5) ? - &sfn4111t_a0_hwmon_info : - &sfn4111t_r5_hwmon_info); - if (!efx->board_info.hwmon_client) - return -EIO; - - efx->board_info.blink = tenxpress_phy_blink; - efx->board_info.monitor = sfn4111t_check_hw; - efx->board_info.fini = sfn4111t_fini; - - rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg); - if (rc) - goto fail_hwmon; - - if (efx->phy_mode & PHY_MODE_SPECIAL) { - efx_stats_disable(efx); - sfn4111t_reset(efx); - } - - return 0; - -fail_hwmon: - i2c_unregister_device(efx->board_info.hwmon_client); - return rc; -} diff --git a/drivers/net/sfc/spi.h b/drivers/net/sfc/spi.h deleted file mode 100644 index 1b1ceb41167..00000000000 --- a/drivers/net/sfc/spi.h +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005 Fen Systems Ltd. - * Copyright 2006 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_SPI_H -#define EFX_SPI_H - -#include "net_driver.h" - -/************************************************************************** - * - * Basic SPI command set and bit definitions - * - *************************************************************************/ - -#define SPI_WRSR 0x01 /* Write status register */ -#define SPI_WRITE 0x02 /* Write data to memory array */ -#define SPI_READ 0x03 /* Read data from memory array */ -#define SPI_WRDI 0x04 /* Reset write enable latch */ -#define SPI_RDSR 0x05 /* Read status register */ -#define SPI_WREN 0x06 /* Set write enable latch */ -#define SPI_SST_EWSR 0x50 /* SST: Enable write to status register */ - -#define SPI_STATUS_WPEN 0x80 /* Write-protect pin enabled */ -#define SPI_STATUS_BP2 0x10 /* Block protection bit 2 */ -#define SPI_STATUS_BP1 0x08 /* Block protection bit 1 */ -#define SPI_STATUS_BP0 0x04 /* Block protection bit 0 */ -#define SPI_STATUS_WEN 0x02 /* State of the write enable latch */ -#define SPI_STATUS_NRDY 0x01 /* Device busy flag */ - -/** - * struct efx_spi_device - an Efx SPI (Serial Peripheral Interface) device - * @efx: The Efx controller that owns this device - * @mtd: MTD state - * @device_id: Controller's id for the device - * @size: Size (in bytes) - * @addr_len: Number of address bytes in read/write commands - * @munge_address: Flag whether addresses should be munged. - * Some devices with 9-bit addresses (e.g. AT25040A EEPROM) - * use bit 3 of the command byte as address bit A8, rather - * than having a two-byte address. If this flag is set, then - * commands should be munged in this way. - * @erase_command: Erase command (or 0 if sector erase not needed). - * @erase_size: Erase sector size (in bytes) - * Erase commands affect sectors with this size and alignment. - * This must be a power of two. - * @block_size: Write block size (in bytes). - * Write commands are limited to blocks with this size and alignment. - */ -struct efx_spi_device { - struct efx_nic *efx; -#ifdef CONFIG_SFC_MTD - void *mtd; -#endif - int device_id; - unsigned int size; - unsigned int addr_len; - unsigned int munge_address:1; - u8 erase_command; - unsigned int erase_size; - unsigned int block_size; -}; - -int falcon_spi_cmd(const struct efx_spi_device *spi, unsigned int command, - int address, const void* in, void *out, size_t len); -int falcon_spi_wait_write(const struct efx_spi_device *spi); -int falcon_spi_read(const struct efx_spi_device *spi, loff_t start, - size_t len, size_t *retlen, u8 *buffer); -int falcon_spi_write(const struct efx_spi_device *spi, loff_t start, - size_t len, size_t *retlen, const u8 *buffer); - -/* - * SFC4000 flash is partitioned into: - * 0-0x400 chip and board config (see falcon_hwdefs.h) - * 0x400-0x8000 unused (or may contain VPD if EEPROM not present) - * 0x8000-end boot code (mapped to PCI expansion ROM) - * SFC4000 small EEPROM (size < 0x400) is used for VPD only. - * SFC4000 large EEPROM (size >= 0x400) is partitioned into: - * 0-0x400 chip and board config - * configurable VPD - * 0x800-0x1800 boot config - * Aside from the chip and board config, all of these are optional and may - * be absent or truncated depending on the devices used. - */ -#define FALCON_NVCONFIG_END 0x400U -#define FALCON_FLASH_BOOTCODE_START 0x8000U -#define EFX_EEPROM_BOOTCONFIG_START 0x800U -#define EFX_EEPROM_BOOTCONFIG_END 0x1800U - -#endif /* EFX_SPI_H */ diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c deleted file mode 100644 index f0efd246962..00000000000 --- a/drivers/net/sfc/tenxpress.c +++ /dev/null @@ -1,850 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2007-2008 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. - */ - -#include <linux/delay.h> -#include <linux/seq_file.h> -#include "efx.h" -#include "mdio_10g.h" -#include "falcon.h" -#include "phy.h" -#include "falcon_hwdefs.h" -#include "boards.h" -#include "workarounds.h" -#include "selftest.h" - -/* We expect these MMDs to be in the package. SFT9001 also has a - * clause 22 extension MMD, but since it doesn't have all the generic - * MMD registers it is pointless to include it here. - */ -#define TENXPRESS_REQUIRED_DEVS (MDIO_MMDREG_DEVS_PMAPMD | \ - MDIO_MMDREG_DEVS_PCS | \ - MDIO_MMDREG_DEVS_PHYXS | \ - MDIO_MMDREG_DEVS_AN) - -#define SFX7101_LOOPBACKS ((1 << LOOPBACK_PHYXS) | \ - (1 << LOOPBACK_PCS) | \ - (1 << LOOPBACK_PMAPMD) | \ - (1 << LOOPBACK_NETWORK)) - -#define SFT9001_LOOPBACKS ((1 << LOOPBACK_GPHY) | \ - (1 << LOOPBACK_PHYXS) | \ - (1 << LOOPBACK_PCS) | \ - (1 << LOOPBACK_PMAPMD) | \ - (1 << LOOPBACK_NETWORK)) - -/* We complain if we fail to see the link partner as 10G capable this many - * times in a row (must be > 1 as sampling the autoneg. registers is racy) - */ -#define MAX_BAD_LP_TRIES (5) - -/* LASI Control */ -#define PMA_PMD_LASI_CTRL 36866 -#define PMA_PMD_LASI_STATUS 36869 -#define PMA_PMD_LS_ALARM_LBN 0 -#define PMA_PMD_LS_ALARM_WIDTH 1 -#define PMA_PMD_TX_ALARM_LBN 1 -#define PMA_PMD_TX_ALARM_WIDTH 1 -#define PMA_PMD_RX_ALARM_LBN 2 -#define PMA_PMD_RX_ALARM_WIDTH 1 -#define PMA_PMD_AN_ALARM_LBN 3 -#define PMA_PMD_AN_ALARM_WIDTH 1 - -/* Extended control register */ -#define PMA_PMD_XCONTROL_REG 49152 -#define PMA_PMD_EXT_GMII_EN_LBN 1 -#define PMA_PMD_EXT_GMII_EN_WIDTH 1 -#define PMA_PMD_EXT_CLK_OUT_LBN 2 -#define PMA_PMD_EXT_CLK_OUT_WIDTH 1 -#define PMA_PMD_LNPGA_POWERDOWN_LBN 8 /* SFX7101 only */ -#define PMA_PMD_LNPGA_POWERDOWN_WIDTH 1 -#define PMA_PMD_EXT_CLK312_LBN 8 /* SFT9001 only */ -#define PMA_PMD_EXT_CLK312_WIDTH 1 -#define PMA_PMD_EXT_LPOWER_LBN 12 -#define PMA_PMD_EXT_LPOWER_WIDTH 1 -#define PMA_PMD_EXT_ROBUST_LBN 14 -#define PMA_PMD_EXT_ROBUST_WIDTH 1 -#define PMA_PMD_EXT_SSR_LBN 15 -#define PMA_PMD_EXT_SSR_WIDTH 1 - -/* extended status register */ -#define PMA_PMD_XSTATUS_REG 49153 -#define PMA_PMD_XSTAT_FLP_LBN (12) - -/* LED control register */ -#define PMA_PMD_LED_CTRL_REG 49159 -#define PMA_PMA_LED_ACTIVITY_LBN (3) - -/* LED function override register */ -#define PMA_PMD_LED_OVERR_REG 49161 -/* Bit positions for different LEDs (there are more but not wired on SFE4001)*/ -#define PMA_PMD_LED_LINK_LBN (0) -#define PMA_PMD_LED_SPEED_LBN (2) -#define PMA_PMD_LED_TX_LBN (4) -#define PMA_PMD_LED_RX_LBN (6) -/* Override settings */ -#define PMA_PMD_LED_AUTO (0) /* H/W control */ -#define PMA_PMD_LED_ON (1) -#define PMA_PMD_LED_OFF (2) -#define PMA_PMD_LED_FLASH (3) -#define PMA_PMD_LED_MASK 3 -/* All LEDs under hardware control */ -#define PMA_PMD_LED_FULL_AUTO (0) -/* Green and Amber under hardware control, Red off */ -#define PMA_PMD_LED_DEFAULT (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN) - -#define PMA_PMD_SPEED_ENABLE_REG 49192 -#define PMA_PMD_100TX_ADV_LBN 1 -#define PMA_PMD_100TX_ADV_WIDTH 1 -#define PMA_PMD_1000T_ADV_LBN 2 -#define PMA_PMD_1000T_ADV_WIDTH 1 -#define PMA_PMD_10000T_ADV_LBN 3 -#define PMA_PMD_10000T_ADV_WIDTH 1 -#define PMA_PMD_SPEED_LBN 4 -#define PMA_PMD_SPEED_WIDTH 4 - -/* Cable diagnostics - SFT9001 only */ -#define PMA_PMD_CDIAG_CTRL_REG 49213 -#define CDIAG_CTRL_IMMED_LBN 15 -#define CDIAG_CTRL_BRK_LINK_LBN 12 -#define CDIAG_CTRL_IN_PROG_LBN 11 -#define CDIAG_CTRL_LEN_UNIT_LBN 10 -#define CDIAG_CTRL_LEN_METRES 1 -#define PMA_PMD_CDIAG_RES_REG 49174 -#define CDIAG_RES_A_LBN 12 -#define CDIAG_RES_B_LBN 8 -#define CDIAG_RES_C_LBN 4 -#define CDIAG_RES_D_LBN 0 -#define CDIAG_RES_WIDTH 4 -#define CDIAG_RES_OPEN 2 -#define CDIAG_RES_OK 1 -#define CDIAG_RES_INVALID 0 -/* Set of 4 registers for pairs A-D */ -#define PMA_PMD_CDIAG_LEN_REG 49175 - -/* Serdes control registers - SFT9001 only */ -#define PMA_PMD_CSERDES_CTRL_REG 64258 -/* Set the 156.25 MHz output to 312.5 MHz to drive Falcon's XMAC */ -#define PMA_PMD_CSERDES_DEFAULT 0x000f - -/* Misc register defines - SFX7101 only */ -#define PCS_CLOCK_CTRL_REG 55297 -#define PLL312_RST_N_LBN 2 - -#define PCS_SOFT_RST2_REG 55302 -#define SERDES_RST_N_LBN 13 -#define XGXS_RST_N_LBN 12 - -#define PCS_TEST_SELECT_REG 55303 /* PRM 10.5.8 */ -#define CLK312_EN_LBN 3 - -/* PHYXS registers */ -#define PHYXS_XCONTROL_REG 49152 -#define PHYXS_RESET_LBN 15 -#define PHYXS_RESET_WIDTH 1 - -#define PHYXS_TEST1 (49162) -#define LOOPBACK_NEAR_LBN (8) -#define LOOPBACK_NEAR_WIDTH (1) - -#define PCS_10GBASET_STAT1 32 -#define PCS_10GBASET_BLKLK_LBN 0 -#define PCS_10GBASET_BLKLK_WIDTH 1 - -/* Boot status register */ -#define PCS_BOOT_STATUS_REG 53248 -#define PCS_BOOT_FATAL_ERR_LBN (0) -#define PCS_BOOT_PROGRESS_LBN (1) -#define PCS_BOOT_PROGRESS_WIDTH (2) -#define PCS_BOOT_COMPLETE_LBN (3) - -#define PCS_BOOT_MAX_DELAY (100) -#define PCS_BOOT_POLL_DELAY (10) - -/* 100M/1G PHY registers */ -#define GPHY_XCONTROL_REG 49152 -#define GPHY_ISOLATE_LBN 10 -#define GPHY_ISOLATE_WIDTH 1 -#define GPHY_DUPLEX_LBN 8 -#define GPHY_DUPLEX_WIDTH 1 -#define GPHY_LOOPBACK_NEAR_LBN 14 -#define GPHY_LOOPBACK_NEAR_WIDTH 1 - -#define C22EXT_STATUS_REG 49153 -#define C22EXT_STATUS_LINK_LBN 2 -#define C22EXT_STATUS_LINK_WIDTH 1 - -#define C22EXT_MSTSLV_CTRL 49161 -#define C22EXT_MSTSLV_CTRL_ADV_1000_HD_LBN 8 -#define C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN 9 - -#define C22EXT_MSTSLV_STATUS 49162 -#define C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN 10 -#define C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN 11 - -/* Time to wait between powering down the LNPGA and turning off the power - * rails */ -#define LNPGA_PDOWN_WAIT (HZ / 5) - -struct tenxpress_phy_data { - enum efx_loopback_mode loopback_mode; - enum efx_phy_mode phy_mode; - int bad_lp_tries; -}; - -static ssize_t show_phy_short_reach(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); - int reg; - - reg = mdio_clause45_read(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - MDIO_PMAPMD_10GBT_TXPWR); - return sprintf(buf, "%d\n", - !!(reg & (1 << MDIO_PMAPMD_10GBT_TXPWR_SHORT_LBN))); -} - -static ssize_t set_phy_short_reach(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); - - rtnl_lock(); - mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - MDIO_PMAPMD_10GBT_TXPWR, - MDIO_PMAPMD_10GBT_TXPWR_SHORT_LBN, - count != 0 && *buf != '0'); - efx_reconfigure_port(efx); - rtnl_unlock(); - - return count; -} - -static DEVICE_ATTR(phy_short_reach, 0644, show_phy_short_reach, - set_phy_short_reach); - -/* Check that the C166 has booted successfully */ -static int tenxpress_phy_check(struct efx_nic *efx) -{ - int phy_id = efx->mii.phy_id; - int count = PCS_BOOT_MAX_DELAY / PCS_BOOT_POLL_DELAY; - int boot_stat; - - /* Wait for the boot to complete (or not) */ - while (count) { - boot_stat = mdio_clause45_read(efx, phy_id, - MDIO_MMD_PCS, - PCS_BOOT_STATUS_REG); - if (boot_stat & (1 << PCS_BOOT_COMPLETE_LBN)) - break; - count--; - udelay(PCS_BOOT_POLL_DELAY); - } - - if (!count) { - EFX_ERR(efx, "%s: PHY boot timed out. Last status " - "%x\n", __func__, - (boot_stat >> PCS_BOOT_PROGRESS_LBN) & - ((1 << PCS_BOOT_PROGRESS_WIDTH) - 1)); - return -ETIMEDOUT; - } - - return 0; -} - -static int tenxpress_init(struct efx_nic *efx) -{ - int phy_id = efx->mii.phy_id; - int reg; - int rc; - - if (efx->phy_type == PHY_TYPE_SFX7101) { - /* Enable 312.5 MHz clock */ - mdio_clause45_write(efx, phy_id, - MDIO_MMD_PCS, PCS_TEST_SELECT_REG, - 1 << CLK312_EN_LBN); - } else { - /* Enable 312.5 MHz clock and GMII */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG); - reg |= ((1 << PMA_PMD_EXT_GMII_EN_LBN) | - (1 << PMA_PMD_EXT_CLK_OUT_LBN) | - (1 << PMA_PMD_EXT_CLK312_LBN) | - (1 << PMA_PMD_EXT_ROBUST_LBN)); - - mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG, reg); - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT, - GPHY_XCONTROL_REG, GPHY_ISOLATE_LBN, - false); - } - - rc = tenxpress_phy_check(efx); - if (rc < 0) - return rc; - - /* Set the LEDs up as: Green = Link, Amber = Link/Act, Red = Off */ - if (efx->phy_type == PHY_TYPE_SFX7101) { - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_LED_CTRL_REG, - PMA_PMA_LED_ACTIVITY_LBN, - true); - mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_LED_OVERR_REG, PMA_PMD_LED_DEFAULT); - } - - return rc; -} - -static int tenxpress_phy_init(struct efx_nic *efx) -{ - struct tenxpress_phy_data *phy_data; - int rc = 0; - - phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL); - if (!phy_data) - return -ENOMEM; - efx->phy_data = phy_data; - phy_data->phy_mode = efx->phy_mode; - - if (!(efx->phy_mode & PHY_MODE_SPECIAL)) { - if (efx->phy_type == PHY_TYPE_SFT9001A) { - int reg; - reg = mdio_clause45_read(efx, efx->mii.phy_id, - MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG); - reg |= (1 << PMA_PMD_EXT_SSR_LBN); - mdio_clause45_write(efx, efx->mii.phy_id, - MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG, reg); - mdelay(200); - } - - rc = mdio_clause45_wait_reset_mmds(efx, - TENXPRESS_REQUIRED_DEVS); - if (rc < 0) - goto fail; - - rc = mdio_clause45_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0); - if (rc < 0) - goto fail; - } - - rc = tenxpress_init(efx); - if (rc < 0) - goto fail; - mdio_clause45_set_pause(efx); - - if (efx->phy_type == PHY_TYPE_SFT9001B) { - rc = device_create_file(&efx->pci_dev->dev, - &dev_attr_phy_short_reach); - if (rc) - goto fail; - } - - schedule_timeout_uninterruptible(HZ / 5); /* 200ms */ - - /* Let XGXS and SerDes out of reset */ - falcon_reset_xaui(efx); - - return 0; - - fail: - kfree(efx->phy_data); - efx->phy_data = NULL; - return rc; -} - -/* Perform a "special software reset" on the PHY. The caller is - * responsible for saving and restoring the PHY hardware registers - * properly, and masking/unmasking LASI */ -static int tenxpress_special_reset(struct efx_nic *efx) -{ - int rc, reg; - - /* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so - * a special software reset can glitch the XGMAC sufficiently for stats - * requests to fail. */ - efx_stats_disable(efx); - - /* Initiate reset */ - reg = mdio_clause45_read(efx, efx->mii.phy_id, - MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG); - reg |= (1 << PMA_PMD_EXT_SSR_LBN); - mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG, reg); - - mdelay(200); - - /* Wait for the blocks to come out of reset */ - rc = mdio_clause45_wait_reset_mmds(efx, - TENXPRESS_REQUIRED_DEVS); - if (rc < 0) - goto out; - - /* Try and reconfigure the device */ - rc = tenxpress_init(efx); - if (rc < 0) - goto out; - - /* Wait for the XGXS state machine to churn */ - mdelay(10); -out: - efx_stats_enable(efx); - return rc; -} - -static void sfx7101_check_bad_lp(struct efx_nic *efx, bool link_ok) -{ - struct tenxpress_phy_data *pd = efx->phy_data; - int phy_id = efx->mii.phy_id; - bool bad_lp; - int reg; - - if (link_ok) { - bad_lp = false; - } else { - /* Check that AN has started but not completed. */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_STATUS); - if (!(reg & (1 << MDIO_AN_STATUS_LP_AN_CAP_LBN))) - return; /* LP status is unknown */ - bad_lp = !(reg & (1 << MDIO_AN_STATUS_AN_DONE_LBN)); - if (bad_lp) - pd->bad_lp_tries++; - } - - /* Nothing to do if all is well and was previously so. */ - if (!pd->bad_lp_tries) - return; - - /* Use the RX (red) LED as an error indicator once we've seen AN - * failure several times in a row, and also log a message. */ - if (!bad_lp || pd->bad_lp_tries == MAX_BAD_LP_TRIES) { - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_LED_OVERR_REG); - reg &= ~(PMA_PMD_LED_MASK << PMA_PMD_LED_RX_LBN); - if (!bad_lp) { - reg |= PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN; - } else { - reg |= PMA_PMD_LED_FLASH << PMA_PMD_LED_RX_LBN; - EFX_ERR(efx, "appears to be plugged into a port" - " that is not 10GBASE-T capable. The PHY" - " supports 10GBASE-T ONLY, so no link can" - " be established\n"); - } - mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_LED_OVERR_REG, reg); - pd->bad_lp_tries = bad_lp; - } -} - -static bool sfx7101_link_ok(struct efx_nic *efx) -{ - return mdio_clause45_links_ok(efx, - MDIO_MMDREG_DEVS_PMAPMD | - MDIO_MMDREG_DEVS_PCS | - MDIO_MMDREG_DEVS_PHYXS); -} - -static bool sft9001_link_ok(struct efx_nic *efx, struct ethtool_cmd *ecmd) -{ - int phy_id = efx->mii.phy_id; - u32 reg; - - if (efx_phy_mode_disabled(efx->phy_mode)) - return false; - else if (efx->loopback_mode == LOOPBACK_GPHY) - return true; - else if (efx->loopback_mode) - return mdio_clause45_links_ok(efx, - MDIO_MMDREG_DEVS_PMAPMD | - MDIO_MMDREG_DEVS_PHYXS); - - /* We must use the same definition of link state as LASI, - * otherwise we can miss a link state transition - */ - if (ecmd->speed == 10000) { - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS, - PCS_10GBASET_STAT1); - return reg & (1 << PCS_10GBASET_BLKLK_LBN); - } else { - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT, - C22EXT_STATUS_REG); - return reg & (1 << C22EXT_STATUS_LINK_LBN); - } -} - -static void tenxpress_ext_loopback(struct efx_nic *efx) -{ - int phy_id = efx->mii.phy_id; - - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PHYXS, - PHYXS_TEST1, LOOPBACK_NEAR_LBN, - efx->loopback_mode == LOOPBACK_PHYXS); - if (efx->phy_type != PHY_TYPE_SFX7101) - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT, - GPHY_XCONTROL_REG, - GPHY_LOOPBACK_NEAR_LBN, - efx->loopback_mode == LOOPBACK_GPHY); -} - -static void tenxpress_low_power(struct efx_nic *efx) -{ - int phy_id = efx->mii.phy_id; - - if (efx->phy_type == PHY_TYPE_SFX7101) - mdio_clause45_set_mmds_lpower( - efx, !!(efx->phy_mode & PHY_MODE_LOW_POWER), - TENXPRESS_REQUIRED_DEVS); - else - mdio_clause45_set_flag( - efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG, PMA_PMD_EXT_LPOWER_LBN, - !!(efx->phy_mode & PHY_MODE_LOW_POWER)); -} - -static void tenxpress_phy_reconfigure(struct efx_nic *efx) -{ - struct tenxpress_phy_data *phy_data = efx->phy_data; - struct ethtool_cmd ecmd; - bool phy_mode_change, loop_reset; - - if (efx->phy_mode & (PHY_MODE_OFF | PHY_MODE_SPECIAL)) { - phy_data->phy_mode = efx->phy_mode; - return; - } - - tenxpress_low_power(efx); - - phy_mode_change = (efx->phy_mode == PHY_MODE_NORMAL && - phy_data->phy_mode != PHY_MODE_NORMAL); - loop_reset = (LOOPBACK_OUT_OF(phy_data, efx, efx->phy_op->loopbacks) || - LOOPBACK_CHANGED(phy_data, efx, 1 << LOOPBACK_GPHY)); - - if (loop_reset || phy_mode_change) { - int rc; - - efx->phy_op->get_settings(efx, &ecmd); - - if (loop_reset || phy_mode_change) { - tenxpress_special_reset(efx); - - /* Reset XAUI if we were in 10G, and are staying - * in 10G. If we're moving into and out of 10G - * then xaui will be reset anyway */ - if (EFX_IS10G(efx)) - falcon_reset_xaui(efx); - } - - rc = efx->phy_op->set_settings(efx, &ecmd); - WARN_ON(rc); - } - - mdio_clause45_transmit_disable(efx); - mdio_clause45_phy_reconfigure(efx); - tenxpress_ext_loopback(efx); - - phy_data->loopback_mode = efx->loopback_mode; - phy_data->phy_mode = efx->phy_mode; - - if (efx->phy_type == PHY_TYPE_SFX7101) { - efx->link_speed = 10000; - efx->link_fd = true; - efx->link_up = sfx7101_link_ok(efx); - } else { - efx->phy_op->get_settings(efx, &ecmd); - efx->link_speed = ecmd.speed; - efx->link_fd = ecmd.duplex == DUPLEX_FULL; - efx->link_up = sft9001_link_ok(efx, &ecmd); - } - efx->link_fc = mdio_clause45_get_pause(efx); -} - -/* Poll PHY for interrupt */ -static void tenxpress_phy_poll(struct efx_nic *efx) -{ - struct tenxpress_phy_data *phy_data = efx->phy_data; - bool change = false, link_ok; - unsigned link_fc; - - if (efx->phy_type == PHY_TYPE_SFX7101) { - link_ok = sfx7101_link_ok(efx); - if (link_ok != efx->link_up) { - change = true; - } else { - link_fc = mdio_clause45_get_pause(efx); - if (link_fc != efx->link_fc) - change = true; - } - sfx7101_check_bad_lp(efx, link_ok); - } else if (efx->loopback_mode) { - bool link_ok = sft9001_link_ok(efx, NULL); - if (link_ok != efx->link_up) - change = true; - } else { - u32 status = mdio_clause45_read(efx, efx->mii.phy_id, - MDIO_MMD_PMAPMD, - PMA_PMD_LASI_STATUS); - if (status & (1 << PMA_PMD_LS_ALARM_LBN)) - change = true; - } - - if (change) - falcon_sim_phy_event(efx); - - if (phy_data->phy_mode != PHY_MODE_NORMAL) - return; -} - -static void tenxpress_phy_fini(struct efx_nic *efx) -{ - int reg; - - if (efx->phy_type == PHY_TYPE_SFT9001B) - device_remove_file(&efx->pci_dev->dev, - &dev_attr_phy_short_reach); - - if (efx->phy_type == PHY_TYPE_SFX7101) { - /* Power down the LNPGA */ - reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN); - mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG, reg); - - /* Waiting here ensures that the board fini, which can turn - * off the power to the PHY, won't get run until the LNPGA - * powerdown has been given long enough to complete. */ - schedule_timeout_uninterruptible(LNPGA_PDOWN_WAIT); /* 200 ms */ - } - - kfree(efx->phy_data); - efx->phy_data = NULL; -} - - -/* Set the RX and TX LEDs and Link LED flashing. The other LEDs - * (which probably aren't wired anyway) are left in AUTO mode */ -void tenxpress_phy_blink(struct efx_nic *efx, bool blink) -{ - int reg; - - if (blink) - reg = (PMA_PMD_LED_FLASH << PMA_PMD_LED_TX_LBN) | - (PMA_PMD_LED_FLASH << PMA_PMD_LED_RX_LBN) | - (PMA_PMD_LED_FLASH << PMA_PMD_LED_LINK_LBN); - else - reg = PMA_PMD_LED_DEFAULT; - - mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_LED_OVERR_REG, reg); -} - -static const char *const sfx7101_test_names[] = { - "bist" -}; - -static int -sfx7101_run_tests(struct efx_nic *efx, int *results, unsigned flags) -{ - int rc; - - if (!(flags & ETH_TEST_FL_OFFLINE)) - return 0; - - /* BIST is automatically run after a special software reset */ - rc = tenxpress_special_reset(efx); - results[0] = rc ? -1 : 1; - return rc; -} - -static const char *const sft9001_test_names[] = { - "bist", - "cable.pairA.status", - "cable.pairB.status", - "cable.pairC.status", - "cable.pairD.status", - "cable.pairA.length", - "cable.pairB.length", - "cable.pairC.length", - "cable.pairD.length", -}; - -static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags) -{ - struct ethtool_cmd ecmd; - int phy_id = efx->mii.phy_id; - int rc = 0, rc2, i, res_reg; - - if (!(flags & ETH_TEST_FL_OFFLINE)) - return 0; - - efx->phy_op->get_settings(efx, &ecmd); - - /* Initialise cable diagnostic results to unknown failure */ - for (i = 1; i < 9; ++i) - results[i] = -1; - - /* Run cable diagnostics; wait up to 5 seconds for them to complete. - * A cable fault is not a self-test failure, but a timeout is. */ - mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_CDIAG_CTRL_REG, - (1 << CDIAG_CTRL_IMMED_LBN) | - (1 << CDIAG_CTRL_BRK_LINK_LBN) | - (CDIAG_CTRL_LEN_METRES << CDIAG_CTRL_LEN_UNIT_LBN)); - i = 0; - while (mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_CDIAG_CTRL_REG) & - (1 << CDIAG_CTRL_IN_PROG_LBN)) { - if (++i == 50) { - rc = -ETIMEDOUT; - goto reset; - } - msleep(100); - } - res_reg = mdio_clause45_read(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_CDIAG_RES_REG); - for (i = 0; i < 4; i++) { - int pair_res = - (res_reg >> (CDIAG_RES_A_LBN - i * CDIAG_RES_WIDTH)) - & ((1 << CDIAG_RES_WIDTH) - 1); - int len_reg = mdio_clause45_read(efx, efx->mii.phy_id, - MDIO_MMD_PMAPMD, - PMA_PMD_CDIAG_LEN_REG + i); - if (pair_res == CDIAG_RES_OK) - results[1 + i] = 1; - else if (pair_res == CDIAG_RES_INVALID) - results[1 + i] = -1; - else - results[1 + i] = -pair_res; - if (pair_res != CDIAG_RES_INVALID && - pair_res != CDIAG_RES_OPEN && - len_reg != 0xffff) - results[5 + i] = len_reg; - } - - /* We must reset to exit cable diagnostic mode. The BIST will - * also run when we do this. */ -reset: - rc2 = tenxpress_special_reset(efx); - results[0] = rc2 ? -1 : 1; - if (!rc) - rc = rc2; - - rc2 = efx->phy_op->set_settings(efx, &ecmd); - if (!rc) - rc = rc2; - - return rc; -} - -static void -tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) -{ - int phy_id = efx->mii.phy_id; - u32 adv = 0, lpa = 0; - int reg; - - if (efx->phy_type != PHY_TYPE_SFX7101) { - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT, - C22EXT_MSTSLV_CTRL); - if (reg & (1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN)) - adv |= ADVERTISED_1000baseT_Full; - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT, - C22EXT_MSTSLV_STATUS); - if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN)) - lpa |= ADVERTISED_1000baseT_Half; - if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN)) - lpa |= ADVERTISED_1000baseT_Full; - } - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_10GBT_CTRL); - if (reg & (1 << MDIO_AN_10GBT_CTRL_ADV_10G_LBN)) - adv |= ADVERTISED_10000baseT_Full; - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_10GBT_STATUS); - if (reg & (1 << MDIO_AN_10GBT_STATUS_LP_10G_LBN)) - lpa |= ADVERTISED_10000baseT_Full; - - mdio_clause45_get_settings_ext(efx, ecmd, adv, lpa); - - if (efx->phy_type != PHY_TYPE_SFX7101) - ecmd->supported |= (SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Full); - - /* In loopback, the PHY automatically brings up the correct interface, - * but doesn't advertise the correct speed. So override it */ - if (efx->loopback_mode == LOOPBACK_GPHY) - ecmd->speed = SPEED_1000; - else if (LOOPBACK_MASK(efx) & efx->phy_op->loopbacks) - ecmd->speed = SPEED_10000; -} - -static int tenxpress_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) -{ - if (!ecmd->autoneg) - return -EINVAL; - - return mdio_clause45_set_settings(efx, ecmd); -} - -static void sfx7101_set_npage_adv(struct efx_nic *efx, u32 advertising) -{ - mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_AN, - MDIO_AN_10GBT_CTRL, - MDIO_AN_10GBT_CTRL_ADV_10G_LBN, - advertising & ADVERTISED_10000baseT_Full); -} - -static void sft9001_set_npage_adv(struct efx_nic *efx, u32 advertising) -{ - int phy_id = efx->mii.phy_id; - - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT, - C22EXT_MSTSLV_CTRL, - C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN, - advertising & ADVERTISED_1000baseT_Full); - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_10GBT_CTRL, - MDIO_AN_10GBT_CTRL_ADV_10G_LBN, - advertising & ADVERTISED_10000baseT_Full); -} - -struct efx_phy_operations falcon_sfx7101_phy_ops = { - .macs = EFX_XMAC, - .init = tenxpress_phy_init, - .reconfigure = tenxpress_phy_reconfigure, - .poll = tenxpress_phy_poll, - .fini = tenxpress_phy_fini, - .clear_interrupt = efx_port_dummy_op_void, - .get_settings = tenxpress_get_settings, - .set_settings = tenxpress_set_settings, - .set_npage_adv = sfx7101_set_npage_adv, - .num_tests = ARRAY_SIZE(sfx7101_test_names), - .test_names = sfx7101_test_names, - .run_tests = sfx7101_run_tests, - .mmds = TENXPRESS_REQUIRED_DEVS, - .loopbacks = SFX7101_LOOPBACKS, -}; - -struct efx_phy_operations falcon_sft9001_phy_ops = { - .macs = EFX_GMAC | EFX_XMAC, - .init = tenxpress_phy_init, - .reconfigure = tenxpress_phy_reconfigure, - .poll = tenxpress_phy_poll, - .fini = tenxpress_phy_fini, - .clear_interrupt = efx_port_dummy_op_void, - .get_settings = tenxpress_get_settings, - .set_settings = tenxpress_set_settings, - .set_npage_adv = sft9001_set_npage_adv, - .num_tests = ARRAY_SIZE(sft9001_test_names), - .test_names = sft9001_test_names, - .run_tests = sft9001_run_tests, - .mmds = TENXPRESS_REQUIRED_DEVS, - .loopbacks = SFT9001_LOOPBACKS, -}; diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c deleted file mode 100644 index da3e9ff339f..00000000000 --- a/drivers/net/sfc/tx.c +++ /dev/null @@ -1,1143 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2005-2008 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. - */ - -#include <linux/pci.h> -#include <linux/tcp.h> -#include <linux/ip.h> -#include <linux/in.h> -#include <linux/if_ether.h> -#include <linux/highmem.h> -#include "net_driver.h" -#include "tx.h" -#include "efx.h" -#include "falcon.h" -#include "workarounds.h" - -/* - * TX descriptor ring full threshold - * - * The tx_queue descriptor ring fill-level must fall below this value - * before we restart the netif queue - */ -#define EFX_NETDEV_TX_THRESHOLD(_tx_queue) \ - (_tx_queue->efx->type->txd_ring_mask / 2u) - -/* We want to be able to nest calls to netif_stop_queue(), since each - * channel can have an individual stop on the queue. - */ -void efx_stop_queue(struct efx_nic *efx) -{ - spin_lock_bh(&efx->netif_stop_lock); - EFX_TRACE(efx, "stop TX queue\n"); - - atomic_inc(&efx->netif_stop_count); - netif_stop_queue(efx->net_dev); - - spin_unlock_bh(&efx->netif_stop_lock); -} - -/* Wake netif's TX queue - * We want to be able to nest calls to netif_stop_queue(), since each - * channel can have an individual stop on the queue. - */ -void efx_wake_queue(struct efx_nic *efx) -{ - local_bh_disable(); - if (atomic_dec_and_lock(&efx->netif_stop_count, - &efx->netif_stop_lock)) { - EFX_TRACE(efx, "waking TX queue\n"); - netif_wake_queue(efx->net_dev); - spin_unlock(&efx->netif_stop_lock); - } - local_bh_enable(); -} - -static void efx_dequeue_buffer(struct efx_tx_queue *tx_queue, - struct efx_tx_buffer *buffer) -{ - if (buffer->unmap_len) { - struct pci_dev *pci_dev = tx_queue->efx->pci_dev; - dma_addr_t unmap_addr = (buffer->dma_addr + buffer->len - - buffer->unmap_len); - if (buffer->unmap_single) - pci_unmap_single(pci_dev, unmap_addr, buffer->unmap_len, - PCI_DMA_TODEVICE); - else - pci_unmap_page(pci_dev, unmap_addr, buffer->unmap_len, - PCI_DMA_TODEVICE); - buffer->unmap_len = 0; - buffer->unmap_single = false; - } - - if (buffer->skb) { - dev_kfree_skb_any((struct sk_buff *) buffer->skb); - buffer->skb = NULL; - EFX_TRACE(tx_queue->efx, "TX queue %d transmission id %x " - "complete\n", tx_queue->queue, read_ptr); - } -} - -/** - * struct efx_tso_header - a DMA mapped buffer for packet headers - * @next: Linked list of free ones. - * The list is protected by the TX queue lock. - * @dma_unmap_len: Length to unmap for an oversize buffer, or 0. - * @dma_addr: The DMA address of the header below. - * - * This controls the memory used for a TSO header. Use TSOH_DATA() - * to find the packet header data. Use TSOH_SIZE() to calculate the - * total size required for a given packet header length. TSO headers - * in the free list are exactly %TSOH_STD_SIZE bytes in size. - */ -struct efx_tso_header { - union { - struct efx_tso_header *next; - size_t unmap_len; - }; - dma_addr_t dma_addr; -}; - -static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue, - struct sk_buff *skb); -static void efx_fini_tso(struct efx_tx_queue *tx_queue); -static void efx_tsoh_heap_free(struct efx_tx_queue *tx_queue, - struct efx_tso_header *tsoh); - -static void efx_tsoh_free(struct efx_tx_queue *tx_queue, - struct efx_tx_buffer *buffer) -{ - if (buffer->tsoh) { - if (likely(!buffer->tsoh->unmap_len)) { - buffer->tsoh->next = tx_queue->tso_headers_free; - tx_queue->tso_headers_free = buffer->tsoh; - } else { - efx_tsoh_heap_free(tx_queue, buffer->tsoh); - } - buffer->tsoh = NULL; - } -} - - -/* - * Add a socket buffer to a TX queue - * - * This maps all fragments of a socket buffer for DMA and adds them to - * the TX queue. The queue's insert pointer will be incremented by - * the number of fragments in the socket buffer. - * - * If any DMA mapping fails, any mapped fragments will be unmapped, - * the queue's insert pointer will be restored to its original value. - * - * Returns NETDEV_TX_OK or NETDEV_TX_BUSY - * You must hold netif_tx_lock() to call this function. - */ -static int efx_enqueue_skb(struct efx_tx_queue *tx_queue, - struct sk_buff *skb) -{ - struct efx_nic *efx = tx_queue->efx; - struct pci_dev *pci_dev = efx->pci_dev; - struct efx_tx_buffer *buffer; - skb_frag_t *fragment; - struct page *page; - int page_offset; - unsigned int len, unmap_len = 0, fill_level, insert_ptr, misalign; - dma_addr_t dma_addr, unmap_addr = 0; - unsigned int dma_len; - bool unmap_single; - int q_space, i = 0; - int rc = NETDEV_TX_OK; - - EFX_BUG_ON_PARANOID(tx_queue->write_count != tx_queue->insert_count); - - if (skb_shinfo((struct sk_buff *)skb)->gso_size) - return efx_enqueue_skb_tso(tx_queue, skb); - - /* Get size of the initial fragment */ - len = skb_headlen(skb); - - fill_level = tx_queue->insert_count - tx_queue->old_read_count; - q_space = efx->type->txd_ring_mask - 1 - fill_level; - - /* Map for DMA. Use pci_map_single rather than pci_map_page - * since this is more efficient on machines with sparse - * memory. - */ - unmap_single = true; - dma_addr = pci_map_single(pci_dev, skb->data, len, PCI_DMA_TODEVICE); - - /* Process all fragments */ - while (1) { - if (unlikely(pci_dma_mapping_error(pci_dev, dma_addr))) - goto pci_err; - - /* Store fields for marking in the per-fragment final - * descriptor */ - unmap_len = len; - unmap_addr = dma_addr; - - /* Add to TX queue, splitting across DMA boundaries */ - do { - if (unlikely(q_space-- <= 0)) { - /* It might be that completions have - * happened since the xmit path last - * checked. Update the xmit path's - * copy of read_count. - */ - ++tx_queue->stopped; - /* This memory barrier protects the - * change of stopped from the access - * of read_count. */ - smp_mb(); - tx_queue->old_read_count = - *(volatile unsigned *) - &tx_queue->read_count; - fill_level = (tx_queue->insert_count - - tx_queue->old_read_count); - q_space = (efx->type->txd_ring_mask - 1 - - fill_level); - if (unlikely(q_space-- <= 0)) - goto stop; - smp_mb(); - --tx_queue->stopped; - } - - insert_ptr = (tx_queue->insert_count & - efx->type->txd_ring_mask); - buffer = &tx_queue->buffer[insert_ptr]; - efx_tsoh_free(tx_queue, buffer); - EFX_BUG_ON_PARANOID(buffer->tsoh); - EFX_BUG_ON_PARANOID(buffer->skb); - EFX_BUG_ON_PARANOID(buffer->len); - EFX_BUG_ON_PARANOID(!buffer->continuation); - EFX_BUG_ON_PARANOID(buffer->unmap_len); - - dma_len = (((~dma_addr) & efx->type->tx_dma_mask) + 1); - if (likely(dma_len > len)) - dma_len = len; - - misalign = (unsigned)dma_addr & efx->type->bug5391_mask; - if (misalign && dma_len + misalign > 512) - dma_len = 512 - misalign; - - /* Fill out per descriptor fields */ - buffer->len = dma_len; - buffer->dma_addr = dma_addr; - len -= dma_len; - dma_addr += dma_len; - ++tx_queue->insert_count; - } while (len); - - /* Transfer ownership of the unmapping to the final buffer */ - buffer->unmap_single = unmap_single; - buffer->unmap_len = unmap_len; - unmap_len = 0; - - /* Get address and size of next fragment */ - if (i >= skb_shinfo(skb)->nr_frags) - break; - fragment = &skb_shinfo(skb)->frags[i]; - len = fragment->size; - page = fragment->page; - page_offset = fragment->page_offset; - i++; - /* Map for DMA */ - unmap_single = false; - dma_addr = pci_map_page(pci_dev, page, page_offset, len, - PCI_DMA_TODEVICE); - } - - /* Transfer ownership of the skb to the final buffer */ - buffer->skb = skb; - buffer->continuation = false; - - /* Pass off to hardware */ - falcon_push_buffers(tx_queue); - - return NETDEV_TX_OK; - - pci_err: - EFX_ERR_RL(efx, " TX queue %d could not map skb with %d bytes %d " - "fragments for DMA\n", tx_queue->queue, skb->len, - skb_shinfo(skb)->nr_frags + 1); - - /* Mark the packet as transmitted, and free the SKB ourselves */ - dev_kfree_skb_any((struct sk_buff *)skb); - goto unwind; - - stop: - rc = NETDEV_TX_BUSY; - - if (tx_queue->stopped == 1) - efx_stop_queue(efx); - - unwind: - /* Work backwards until we hit the original insert pointer value */ - while (tx_queue->insert_count != tx_queue->write_count) { - --tx_queue->insert_count; - insert_ptr = tx_queue->insert_count & efx->type->txd_ring_mask; - buffer = &tx_queue->buffer[insert_ptr]; - efx_dequeue_buffer(tx_queue, buffer); - buffer->len = 0; - } - - /* Free the fragment we were mid-way through pushing */ - if (unmap_len) { - if (unmap_single) - pci_unmap_single(pci_dev, unmap_addr, unmap_len, - PCI_DMA_TODEVICE); - else - pci_unmap_page(pci_dev, unmap_addr, unmap_len, - PCI_DMA_TODEVICE); - } - - return rc; -} - -/* Remove packets from the TX queue - * - * This removes packets from the TX queue, up to and including the - * specified index. - */ -static void efx_dequeue_buffers(struct efx_tx_queue *tx_queue, - unsigned int index) -{ - struct efx_nic *efx = tx_queue->efx; - unsigned int stop_index, read_ptr; - unsigned int mask = tx_queue->efx->type->txd_ring_mask; - - stop_index = (index + 1) & mask; - read_ptr = tx_queue->read_count & mask; - - while (read_ptr != stop_index) { - struct efx_tx_buffer *buffer = &tx_queue->buffer[read_ptr]; - if (unlikely(buffer->len == 0)) { - EFX_ERR(tx_queue->efx, "TX queue %d spurious TX " - "completion id %x\n", tx_queue->queue, - read_ptr); - efx_schedule_reset(efx, RESET_TYPE_TX_SKIP); - return; - } - - efx_dequeue_buffer(tx_queue, buffer); - buffer->continuation = true; - buffer->len = 0; - - ++tx_queue->read_count; - read_ptr = tx_queue->read_count & mask; - } -} - -/* Initiate a packet transmission on the specified TX queue. - * Note that returning anything other than NETDEV_TX_OK will cause the - * OS to free the skb. - * - * This function is split out from efx_hard_start_xmit to allow the - * loopback test to direct packets via specific TX queues. It is - * therefore a non-static inline, so as not to penalise performance - * for non-loopback transmissions. - * - * Context: netif_tx_lock held - */ -inline int efx_xmit(struct efx_nic *efx, - struct efx_tx_queue *tx_queue, struct sk_buff *skb) -{ - int rc; - - /* Map fragments for DMA and add to TX queue */ - rc = efx_enqueue_skb(tx_queue, skb); - if (unlikely(rc != NETDEV_TX_OK)) - goto out; - - /* Update last TX timer */ - efx->net_dev->trans_start = jiffies; - - out: - return rc; -} - -/* Initiate a packet transmission. We use one channel per CPU - * (sharing when we have more CPUs than channels). On Falcon, the TX - * completion events will be directed back to the CPU that transmitted - * the packet, which should be cache-efficient. - * - * Context: non-blocking. - * Note that returning anything other than NETDEV_TX_OK will cause the - * OS to free the skb. - */ -int efx_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev) -{ - struct efx_nic *efx = netdev_priv(net_dev); - struct efx_tx_queue *tx_queue; - - if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) - tx_queue = &efx->tx_queue[EFX_TX_QUEUE_OFFLOAD_CSUM]; - else - tx_queue = &efx->tx_queue[EFX_TX_QUEUE_NO_CSUM]; - - return efx_xmit(efx, tx_queue, skb); -} - -void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index) -{ - unsigned fill_level; - struct efx_nic *efx = tx_queue->efx; - - EFX_BUG_ON_PARANOID(index > efx->type->txd_ring_mask); - - efx_dequeue_buffers(tx_queue, index); - - /* See if we need to restart the netif queue. This barrier - * separates the update of read_count from the test of - * stopped. */ - smp_mb(); - if (unlikely(tx_queue->stopped)) { - fill_level = tx_queue->insert_count - tx_queue->read_count; - if (fill_level < EFX_NETDEV_TX_THRESHOLD(tx_queue)) { - EFX_BUG_ON_PARANOID(!efx_dev_registered(efx)); - - /* Do this under netif_tx_lock(), to avoid racing - * with efx_xmit(). */ - netif_tx_lock(efx->net_dev); - if (tx_queue->stopped) { - tx_queue->stopped = 0; - efx_wake_queue(efx); - } - netif_tx_unlock(efx->net_dev); - } - } -} - -int efx_probe_tx_queue(struct efx_tx_queue *tx_queue) -{ - struct efx_nic *efx = tx_queue->efx; - unsigned int txq_size; - int i, rc; - - EFX_LOG(efx, "creating TX queue %d\n", tx_queue->queue); - - /* Allocate software ring */ - txq_size = (efx->type->txd_ring_mask + 1) * sizeof(*tx_queue->buffer); - tx_queue->buffer = kzalloc(txq_size, GFP_KERNEL); - if (!tx_queue->buffer) - return -ENOMEM; - for (i = 0; i <= efx->type->txd_ring_mask; ++i) - tx_queue->buffer[i].continuation = true; - - /* Allocate hardware ring */ - rc = falcon_probe_tx(tx_queue); - if (rc) - goto fail; - - return 0; - - fail: - kfree(tx_queue->buffer); - tx_queue->buffer = NULL; - return rc; -} - -void efx_init_tx_queue(struct efx_tx_queue *tx_queue) -{ - EFX_LOG(tx_queue->efx, "initialising TX queue %d\n", tx_queue->queue); - - tx_queue->insert_count = 0; - tx_queue->write_count = 0; - tx_queue->read_count = 0; - tx_queue->old_read_count = 0; - BUG_ON(tx_queue->stopped); - - /* Set up TX descriptor ring */ - falcon_init_tx(tx_queue); -} - -void efx_release_tx_buffers(struct efx_tx_queue *tx_queue) -{ - struct efx_tx_buffer *buffer; - - if (!tx_queue->buffer) - return; - - /* Free any buffers left in the ring */ - while (tx_queue->read_count != tx_queue->write_count) { - buffer = &tx_queue->buffer[tx_queue->read_count & - tx_queue->efx->type->txd_ring_mask]; - efx_dequeue_buffer(tx_queue, buffer); - buffer->continuation = true; - buffer->len = 0; - - ++tx_queue->read_count; - } -} - -void efx_fini_tx_queue(struct efx_tx_queue *tx_queue) -{ - EFX_LOG(tx_queue->efx, "shutting down TX queue %d\n", tx_queue->queue); - - /* Flush TX queue, remove descriptor ring */ - falcon_fini_tx(tx_queue); - - efx_release_tx_buffers(tx_queue); - - /* Free up TSO header cache */ - efx_fini_tso(tx_queue); - - /* Release queue's stop on port, if any */ - if (tx_queue->stopped) { - tx_queue->stopped = 0; - efx_wake_queue(tx_queue->efx); - } -} - -void efx_remove_tx_queue(struct efx_tx_queue *tx_queue) -{ - EFX_LOG(tx_queue->efx, "destroying TX queue %d\n", tx_queue->queue); - falcon_remove_tx(tx_queue); - - kfree(tx_queue->buffer); - tx_queue->buffer = NULL; -} - - -/* Efx TCP segmentation acceleration. - * - * Why? Because by doing it here in the driver we can go significantly - * faster than the GSO. - * - * Requires TX checksum offload support. - */ - -/* Number of bytes inserted at the start of a TSO header buffer, - * similar to NET_IP_ALIGN. - */ -#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS -#define TSOH_OFFSET 0 -#else -#define TSOH_OFFSET NET_IP_ALIGN -#endif - -#define TSOH_BUFFER(tsoh) ((u8 *)(tsoh + 1) + TSOH_OFFSET) - -/* Total size of struct efx_tso_header, buffer and padding */ -#define TSOH_SIZE(hdr_len) \ - (sizeof(struct efx_tso_header) + TSOH_OFFSET + hdr_len) - -/* Size of blocks on free list. Larger blocks must be allocated from - * the heap. - */ -#define TSOH_STD_SIZE 128 - -#define PTR_DIFF(p1, p2) ((u8 *)(p1) - (u8 *)(p2)) -#define ETH_HDR_LEN(skb) (skb_network_header(skb) - (skb)->data) -#define SKB_TCP_OFF(skb) PTR_DIFF(tcp_hdr(skb), (skb)->data) -#define SKB_IPV4_OFF(skb) PTR_DIFF(ip_hdr(skb), (skb)->data) - -/** - * struct tso_state - TSO state for an SKB - * @out_len: Remaining length in current segment - * @seqnum: Current sequence number - * @ipv4_id: Current IPv4 ID, host endian - * @packet_space: Remaining space in current packet - * @dma_addr: DMA address of current position - * @in_len: Remaining length in current SKB fragment - * @unmap_len: Length of SKB fragment - * @unmap_addr: DMA address of SKB fragment - * @unmap_single: DMA single vs page mapping flag - * @header_len: Number of bytes of header - * @full_packet_size: Number of bytes to put in each outgoing segment - * - * The state used during segmentation. It is put into this data structure - * just to make it easy to pass into inline functions. - */ -struct tso_state { - /* Output position */ - unsigned out_len; - unsigned seqnum; - unsigned ipv4_id; - unsigned packet_space; - - /* Input position */ - dma_addr_t dma_addr; - unsigned in_len; - unsigned unmap_len; - dma_addr_t unmap_addr; - bool unmap_single; - - unsigned header_len; - int full_packet_size; -}; - - -/* - * Verify that our various assumptions about sk_buffs and the conditions - * under which TSO will be attempted hold true. - */ -static void efx_tso_check_safe(struct sk_buff *skb) -{ - __be16 protocol = skb->protocol; - - EFX_BUG_ON_PARANOID(((struct ethhdr *)skb->data)->h_proto != - protocol); - if (protocol == htons(ETH_P_8021Q)) { - /* Find the encapsulated protocol; reset network header - * and transport header based on that. */ - struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; - protocol = veh->h_vlan_encapsulated_proto; - skb_set_network_header(skb, sizeof(*veh)); - if (protocol == htons(ETH_P_IP)) - skb_set_transport_header(skb, sizeof(*veh) + - 4 * ip_hdr(skb)->ihl); - } - - EFX_BUG_ON_PARANOID(protocol != htons(ETH_P_IP)); - EFX_BUG_ON_PARANOID(ip_hdr(skb)->protocol != IPPROTO_TCP); - EFX_BUG_ON_PARANOID((PTR_DIFF(tcp_hdr(skb), skb->data) - + (tcp_hdr(skb)->doff << 2u)) > - skb_headlen(skb)); -} - - -/* - * Allocate a page worth of efx_tso_header structures, and string them - * into the tx_queue->tso_headers_free linked list. Return 0 or -ENOMEM. - */ -static int efx_tsoh_block_alloc(struct efx_tx_queue *tx_queue) -{ - - struct pci_dev *pci_dev = tx_queue->efx->pci_dev; - struct efx_tso_header *tsoh; - dma_addr_t dma_addr; - u8 *base_kva, *kva; - - base_kva = pci_alloc_consistent(pci_dev, PAGE_SIZE, &dma_addr); - if (base_kva == NULL) { - EFX_ERR(tx_queue->efx, "Unable to allocate page for TSO" - " headers\n"); - return -ENOMEM; - } - - /* pci_alloc_consistent() allocates pages. */ - EFX_BUG_ON_PARANOID(dma_addr & (PAGE_SIZE - 1u)); - - for (kva = base_kva; kva < base_kva + PAGE_SIZE; kva += TSOH_STD_SIZE) { - tsoh = (struct efx_tso_header *)kva; - tsoh->dma_addr = dma_addr + (TSOH_BUFFER(tsoh) - base_kva); - tsoh->next = tx_queue->tso_headers_free; - tx_queue->tso_headers_free = tsoh; - } - - return 0; -} - - -/* Free up a TSO header, and all others in the same page. */ -static void efx_tsoh_block_free(struct efx_tx_queue *tx_queue, - struct efx_tso_header *tsoh, - struct pci_dev *pci_dev) -{ - struct efx_tso_header **p; - unsigned long base_kva; - dma_addr_t base_dma; - - base_kva = (unsigned long)tsoh & PAGE_MASK; - base_dma = tsoh->dma_addr & PAGE_MASK; - - p = &tx_queue->tso_headers_free; - while (*p != NULL) { - if (((unsigned long)*p & PAGE_MASK) == base_kva) - *p = (*p)->next; - else - p = &(*p)->next; - } - - pci_free_consistent(pci_dev, PAGE_SIZE, (void *)base_kva, base_dma); -} - -static struct efx_tso_header * -efx_tsoh_heap_alloc(struct efx_tx_queue *tx_queue, size_t header_len) -{ - struct efx_tso_header *tsoh; - - tsoh = kmalloc(TSOH_SIZE(header_len), GFP_ATOMIC | GFP_DMA); - if (unlikely(!tsoh)) - return NULL; - - tsoh->dma_addr = pci_map_single(tx_queue->efx->pci_dev, - TSOH_BUFFER(tsoh), header_len, - PCI_DMA_TODEVICE); - if (unlikely(pci_dma_mapping_error(tx_queue->efx->pci_dev, - tsoh->dma_addr))) { - kfree(tsoh); - return NULL; - } - - tsoh->unmap_len = header_len; - return tsoh; -} - -static void -efx_tsoh_heap_free(struct efx_tx_queue *tx_queue, struct efx_tso_header *tsoh) -{ - pci_unmap_single(tx_queue->efx->pci_dev, - tsoh->dma_addr, tsoh->unmap_len, - PCI_DMA_TODEVICE); - kfree(tsoh); -} - -/** - * efx_tx_queue_insert - push descriptors onto the TX queue - * @tx_queue: Efx TX queue - * @dma_addr: DMA address of fragment - * @len: Length of fragment - * @final_buffer: The final buffer inserted into the queue - * - * Push descriptors onto the TX queue. Return 0 on success or 1 if - * @tx_queue full. - */ -static int efx_tx_queue_insert(struct efx_tx_queue *tx_queue, - dma_addr_t dma_addr, unsigned len, - struct efx_tx_buffer **final_buffer) -{ - struct efx_tx_buffer *buffer; - struct efx_nic *efx = tx_queue->efx; - unsigned dma_len, fill_level, insert_ptr, misalign; - int q_space; - - EFX_BUG_ON_PARANOID(len <= 0); - - fill_level = tx_queue->insert_count - tx_queue->old_read_count; - /* -1 as there is no way to represent all descriptors used */ - q_space = efx->type->txd_ring_mask - 1 - fill_level; - - while (1) { - if (unlikely(q_space-- <= 0)) { - /* It might be that completions have happened - * since the xmit path last checked. Update - * the xmit path's copy of read_count. - */ - ++tx_queue->stopped; - /* This memory barrier protects the change of - * stopped from the access of read_count. */ - smp_mb(); - tx_queue->old_read_count = - *(volatile unsigned *)&tx_queue->read_count; - fill_level = (tx_queue->insert_count - - tx_queue->old_read_count); - q_space = efx->type->txd_ring_mask - 1 - fill_level; - if (unlikely(q_space-- <= 0)) { - *final_buffer = NULL; - return 1; - } - smp_mb(); - --tx_queue->stopped; - } - - insert_ptr = tx_queue->insert_count & efx->type->txd_ring_mask; - buffer = &tx_queue->buffer[insert_ptr]; - ++tx_queue->insert_count; - - EFX_BUG_ON_PARANOID(tx_queue->insert_count - - tx_queue->read_count > - efx->type->txd_ring_mask); - - efx_tsoh_free(tx_queue, buffer); - EFX_BUG_ON_PARANOID(buffer->len); - EFX_BUG_ON_PARANOID(buffer->unmap_len); - EFX_BUG_ON_PARANOID(buffer->skb); - EFX_BUG_ON_PARANOID(!buffer->continuation); - EFX_BUG_ON_PARANOID(buffer->tsoh); - - buffer->dma_addr = dma_addr; - - /* Ensure we do not cross a boundary unsupported by H/W */ - dma_len = (~dma_addr & efx->type->tx_dma_mask) + 1; - - misalign = (unsigned)dma_addr & efx->type->bug5391_mask; - if (misalign && dma_len + misalign > 512) - dma_len = 512 - misalign; - - /* If there is enough space to send then do so */ - if (dma_len >= len) - break; - - buffer->len = dma_len; /* Don't set the other members */ - dma_addr += dma_len; - len -= dma_len; - } - - EFX_BUG_ON_PARANOID(!len); - buffer->len = len; - *final_buffer = buffer; - return 0; -} - - -/* - * Put a TSO header into the TX queue. - * - * This is special-cased because we know that it is small enough to fit in - * a single fragment, and we know it doesn't cross a page boundary. It - * also allows us to not worry about end-of-packet etc. - */ -static void efx_tso_put_header(struct efx_tx_queue *tx_queue, - struct efx_tso_header *tsoh, unsigned len) -{ - struct efx_tx_buffer *buffer; - - buffer = &tx_queue->buffer[tx_queue->insert_count & - tx_queue->efx->type->txd_ring_mask]; - efx_tsoh_free(tx_queue, buffer); - EFX_BUG_ON_PARANOID(buffer->len); - EFX_BUG_ON_PARANOID(buffer->unmap_len); - EFX_BUG_ON_PARANOID(buffer->skb); - EFX_BUG_ON_PARANOID(!buffer->continuation); - EFX_BUG_ON_PARANOID(buffer->tsoh); - buffer->len = len; - buffer->dma_addr = tsoh->dma_addr; - buffer->tsoh = tsoh; - - ++tx_queue->insert_count; -} - - -/* Remove descriptors put into a tx_queue. */ -static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue) -{ - struct efx_tx_buffer *buffer; - dma_addr_t unmap_addr; - - /* Work backwards until we hit the original insert pointer value */ - while (tx_queue->insert_count != tx_queue->write_count) { - --tx_queue->insert_count; - buffer = &tx_queue->buffer[tx_queue->insert_count & - tx_queue->efx->type->txd_ring_mask]; - efx_tsoh_free(tx_queue, buffer); - EFX_BUG_ON_PARANOID(buffer->skb); - buffer->len = 0; - buffer->continuation = true; - if (buffer->unmap_len) { - unmap_addr = (buffer->dma_addr + buffer->len - - buffer->unmap_len); - if (buffer->unmap_single) - pci_unmap_single(tx_queue->efx->pci_dev, - unmap_addr, buffer->unmap_len, - PCI_DMA_TODEVICE); - else - pci_unmap_page(tx_queue->efx->pci_dev, - unmap_addr, buffer->unmap_len, - PCI_DMA_TODEVICE); - buffer->unmap_len = 0; - } - } -} - - -/* Parse the SKB header and initialise state. */ -static void tso_start(struct tso_state *st, const struct sk_buff *skb) -{ - /* All ethernet/IP/TCP headers combined size is TCP header size - * plus offset of TCP header relative to start of packet. - */ - st->header_len = ((tcp_hdr(skb)->doff << 2u) - + PTR_DIFF(tcp_hdr(skb), skb->data)); - st->full_packet_size = st->header_len + skb_shinfo(skb)->gso_size; - - st->ipv4_id = ntohs(ip_hdr(skb)->id); - st->seqnum = ntohl(tcp_hdr(skb)->seq); - - EFX_BUG_ON_PARANOID(tcp_hdr(skb)->urg); - EFX_BUG_ON_PARANOID(tcp_hdr(skb)->syn); - EFX_BUG_ON_PARANOID(tcp_hdr(skb)->rst); - - st->packet_space = st->full_packet_size; - st->out_len = skb->len - st->header_len; - st->unmap_len = 0; - st->unmap_single = false; -} - -static int tso_get_fragment(struct tso_state *st, struct efx_nic *efx, - skb_frag_t *frag) -{ - st->unmap_addr = pci_map_page(efx->pci_dev, frag->page, - frag->page_offset, frag->size, - PCI_DMA_TODEVICE); - if (likely(!pci_dma_mapping_error(efx->pci_dev, st->unmap_addr))) { - st->unmap_single = false; - st->unmap_len = frag->size; - st->in_len = frag->size; - st->dma_addr = st->unmap_addr; - return 0; - } - return -ENOMEM; -} - -static int tso_get_head_fragment(struct tso_state *st, struct efx_nic *efx, - const struct sk_buff *skb) -{ - int hl = st->header_len; - int len = skb_headlen(skb) - hl; - - st->unmap_addr = pci_map_single(efx->pci_dev, skb->data + hl, - len, PCI_DMA_TODEVICE); - if (likely(!pci_dma_mapping_error(efx->pci_dev, st->unmap_addr))) { - st->unmap_single = true; - st->unmap_len = len; - st->in_len = len; - st->dma_addr = st->unmap_addr; - return 0; - } - return -ENOMEM; -} - - -/** - * tso_fill_packet_with_fragment - form descriptors for the current fragment - * @tx_queue: Efx TX queue - * @skb: Socket buffer - * @st: TSO state - * - * Form descriptors for the current fragment, until we reach the end - * of fragment or end-of-packet. Return 0 on success, 1 if not enough - * space in @tx_queue. - */ -static int tso_fill_packet_with_fragment(struct efx_tx_queue *tx_queue, - const struct sk_buff *skb, - struct tso_state *st) -{ - struct efx_tx_buffer *buffer; - int n, end_of_packet, rc; - - if (st->in_len == 0) - return 0; - if (st->packet_space == 0) - return 0; - - EFX_BUG_ON_PARANOID(st->in_len <= 0); - EFX_BUG_ON_PARANOID(st->packet_space <= 0); - - n = min(st->in_len, st->packet_space); - - st->packet_space -= n; - st->out_len -= n; - st->in_len -= n; - - rc = efx_tx_queue_insert(tx_queue, st->dma_addr, n, &buffer); - if (likely(rc == 0)) { - if (st->out_len == 0) - /* Transfer ownership of the skb */ - buffer->skb = skb; - - end_of_packet = st->out_len == 0 || st->packet_space == 0; - buffer->continuation = !end_of_packet; - - if (st->in_len == 0) { - /* Transfer ownership of the pci mapping */ - buffer->unmap_len = st->unmap_len; - buffer->unmap_single = st->unmap_single; - st->unmap_len = 0; - } - } - - st->dma_addr += n; - return rc; -} - - -/** - * tso_start_new_packet - generate a new header and prepare for the new packet - * @tx_queue: Efx TX queue - * @skb: Socket buffer - * @st: TSO state - * - * Generate a new header and prepare for the new packet. Return 0 on - * success, or -1 if failed to alloc header. - */ -static int tso_start_new_packet(struct efx_tx_queue *tx_queue, - const struct sk_buff *skb, - struct tso_state *st) -{ - struct efx_tso_header *tsoh; - struct iphdr *tsoh_iph; - struct tcphdr *tsoh_th; - unsigned ip_length; - u8 *header; - - /* Allocate a DMA-mapped header buffer. */ - if (likely(TSOH_SIZE(st->header_len) <= TSOH_STD_SIZE)) { - if (tx_queue->tso_headers_free == NULL) { - if (efx_tsoh_block_alloc(tx_queue)) - return -1; - } - EFX_BUG_ON_PARANOID(!tx_queue->tso_headers_free); - tsoh = tx_queue->tso_headers_free; - tx_queue->tso_headers_free = tsoh->next; - tsoh->unmap_len = 0; - } else { - tx_queue->tso_long_headers++; - tsoh = efx_tsoh_heap_alloc(tx_queue, st->header_len); - if (unlikely(!tsoh)) - return -1; - } - - header = TSOH_BUFFER(tsoh); - tsoh_th = (struct tcphdr *)(header + SKB_TCP_OFF(skb)); - tsoh_iph = (struct iphdr *)(header + SKB_IPV4_OFF(skb)); - - /* Copy and update the headers. */ - memcpy(header, skb->data, st->header_len); - - tsoh_th->seq = htonl(st->seqnum); - st->seqnum += skb_shinfo(skb)->gso_size; - if (st->out_len > skb_shinfo(skb)->gso_size) { - /* This packet will not finish the TSO burst. */ - ip_length = st->full_packet_size - ETH_HDR_LEN(skb); - tsoh_th->fin = 0; - tsoh_th->psh = 0; - } else { - /* This packet will be the last in the TSO burst. */ - ip_length = st->header_len - ETH_HDR_LEN(skb) + st->out_len; - tsoh_th->fin = tcp_hdr(skb)->fin; - tsoh_th->psh = tcp_hdr(skb)->psh; - } - tsoh_iph->tot_len = htons(ip_length); - - /* Linux leaves suitable gaps in the IP ID space for us to fill. */ - tsoh_iph->id = htons(st->ipv4_id); - st->ipv4_id++; - - st->packet_space = skb_shinfo(skb)->gso_size; - ++tx_queue->tso_packets; - - /* Form a descriptor for this header. */ - efx_tso_put_header(tx_queue, tsoh, st->header_len); - - return 0; -} - - -/** - * efx_enqueue_skb_tso - segment and transmit a TSO socket buffer - * @tx_queue: Efx TX queue - * @skb: Socket buffer - * - * Context: You must hold netif_tx_lock() to call this function. - * - * Add socket buffer @skb to @tx_queue, doing TSO or return != 0 if - * @skb was not enqueued. In all cases @skb is consumed. Return - * %NETDEV_TX_OK or %NETDEV_TX_BUSY. - */ -static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue, - struct sk_buff *skb) -{ - struct efx_nic *efx = tx_queue->efx; - int frag_i, rc, rc2 = NETDEV_TX_OK; - struct tso_state state; - - /* Verify TSO is safe - these checks should never fail. */ - efx_tso_check_safe(skb); - - EFX_BUG_ON_PARANOID(tx_queue->write_count != tx_queue->insert_count); - - tso_start(&state, skb); - - /* Assume that skb header area contains exactly the headers, and - * all payload is in the frag list. - */ - if (skb_headlen(skb) == state.header_len) { - /* Grab the first payload fragment. */ - EFX_BUG_ON_PARANOID(skb_shinfo(skb)->nr_frags < 1); - frag_i = 0; - rc = tso_get_fragment(&state, efx, - skb_shinfo(skb)->frags + frag_i); - if (rc) - goto mem_err; - } else { - rc = tso_get_head_fragment(&state, efx, skb); - if (rc) - goto mem_err; - frag_i = -1; - } - - if (tso_start_new_packet(tx_queue, skb, &state) < 0) - goto mem_err; - - while (1) { - rc = tso_fill_packet_with_fragment(tx_queue, skb, &state); - if (unlikely(rc)) - goto stop; - - /* Move onto the next fragment? */ - if (state.in_len == 0) { - if (++frag_i >= skb_shinfo(skb)->nr_frags) - /* End of payload reached. */ - break; - rc = tso_get_fragment(&state, efx, - skb_shinfo(skb)->frags + frag_i); - if (rc) - goto mem_err; - } - - /* Start at new packet? */ - if (state.packet_space == 0 && - tso_start_new_packet(tx_queue, skb, &state) < 0) - goto mem_err; - } - - /* Pass off to hardware */ - falcon_push_buffers(tx_queue); - - tx_queue->tso_bursts++; - return NETDEV_TX_OK; - - mem_err: - EFX_ERR(efx, "Out of memory for TSO headers, or PCI mapping error\n"); - dev_kfree_skb_any((struct sk_buff *)skb); - goto unwind; - - stop: - rc2 = NETDEV_TX_BUSY; - - /* Stop the queue if it wasn't stopped before. */ - if (tx_queue->stopped == 1) - efx_stop_queue(efx); - - unwind: - /* Free the DMA mapping we were in the process of writing out */ - if (state.unmap_len) { - if (state.unmap_single) - pci_unmap_single(efx->pci_dev, state.unmap_addr, - state.unmap_len, PCI_DMA_TODEVICE); - else - pci_unmap_page(efx->pci_dev, state.unmap_addr, - state.unmap_len, PCI_DMA_TODEVICE); - } - - efx_enqueue_unwind(tx_queue); - return rc2; -} - - -/* - * Free up all TSO datastructures associated with tx_queue. This - * routine should be called only once the tx_queue is both empty and - * will no longer be used. - */ -static void efx_fini_tso(struct efx_tx_queue *tx_queue) -{ - unsigned i; - - if (tx_queue->buffer) { - for (i = 0; i <= tx_queue->efx->type->txd_ring_mask; ++i) - efx_tsoh_free(tx_queue, &tx_queue->buffer[i]); - } - - while (tx_queue->tso_headers_free != NULL) - efx_tsoh_block_free(tx_queue, tx_queue->tso_headers_free, - tx_queue->efx->pci_dev); -} diff --git a/drivers/net/sfc/tx.h b/drivers/net/sfc/tx.h deleted file mode 100644 index 5e1cc234e42..00000000000 --- a/drivers/net/sfc/tx.h +++ /dev/null @@ -1,24 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2006 Fen Systems Ltd. - * Copyright 2006-2008 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_TX_H -#define EFX_TX_H - -#include "net_driver.h" - -int efx_probe_tx_queue(struct efx_tx_queue *tx_queue); -void efx_remove_tx_queue(struct efx_tx_queue *tx_queue); -void efx_init_tx_queue(struct efx_tx_queue *tx_queue); -void efx_fini_tx_queue(struct efx_tx_queue *tx_queue); - -int efx_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev); -void efx_release_tx_buffers(struct efx_tx_queue *tx_queue); - -#endif /* EFX_TX_H */ diff --git a/drivers/net/sfc/workarounds.h b/drivers/net/sfc/workarounds.h deleted file mode 100644 index 78de68f4a95..00000000000 --- a/drivers/net/sfc/workarounds.h +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2006-2008 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_WORKAROUNDS_H -#define EFX_WORKAROUNDS_H - -/* - * Hardware workarounds. - * Bug numbers are from Solarflare's Bugzilla. - */ - -#define EFX_WORKAROUND_ALWAYS(efx) 1 -#define EFX_WORKAROUND_FALCON_A(efx) (falcon_rev(efx) <= FALCON_REV_A1) -#define EFX_WORKAROUND_10G(efx) EFX_IS10G(efx) -#define EFX_WORKAROUND_SFT9001(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A || \ - (efx)->phy_type == PHY_TYPE_SFT9001B) - -/* XAUI resets if link not detected */ -#define EFX_WORKAROUND_5147 EFX_WORKAROUND_ALWAYS -/* RX PCIe double split performance issue */ -#define EFX_WORKAROUND_7575 EFX_WORKAROUND_ALWAYS -/* Bit-bashed I2C reads cause performance drop */ -#define EFX_WORKAROUND_7884 EFX_WORKAROUND_10G -/* TX pkt parser problem with <= 16 byte TXes */ -#define EFX_WORKAROUND_9141 EFX_WORKAROUND_ALWAYS -/* TX_EV_PKT_ERR can be caused by a dangling TX descriptor - * or a PCIe error (bug 11028) */ -#define EFX_WORKAROUND_10727 EFX_WORKAROUND_ALWAYS -/* Transmit flow control may get disabled */ -#define EFX_WORKAROUND_11482 EFX_WORKAROUND_ALWAYS -/* Flush events can take a very long time to appear */ -#define EFX_WORKAROUND_11557 EFX_WORKAROUND_ALWAYS - -/* Spurious parity errors in TSORT buffers */ -#define EFX_WORKAROUND_5129 EFX_WORKAROUND_FALCON_A -/* iSCSI parsing errors */ -#define EFX_WORKAROUND_5583 EFX_WORKAROUND_FALCON_A -/* RX events go missing */ -#define EFX_WORKAROUND_5676 EFX_WORKAROUND_FALCON_A -/* RX_RESET on A1 */ -#define EFX_WORKAROUND_6555 EFX_WORKAROUND_FALCON_A -/* Increase filter depth to avoid RX_RESET */ -#define EFX_WORKAROUND_7244 EFX_WORKAROUND_FALCON_A -/* Flushes may never complete */ -#define EFX_WORKAROUND_7803 EFX_WORKAROUND_FALCON_A -/* Leak overlength packets rather than free */ -#define EFX_WORKAROUND_8071 EFX_WORKAROUND_FALCON_A - -/* Need to send XNP pages for 100BaseT */ -#define EFX_WORKAROUND_13204 EFX_WORKAROUND_SFT9001 -/* Don't restart AN in near-side loopback */ -#define EFX_WORKAROUND_15195 EFX_WORKAROUND_SFT9001 - -#endif /* EFX_WORKAROUNDS_H */ diff --git a/drivers/net/sfc/xenpack.h b/drivers/net/sfc/xenpack.h deleted file mode 100644 index b0d1f225b70..00000000000 --- a/drivers/net/sfc/xenpack.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2006 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_XENPACK_H -#define EFX_XENPACK_H - -/* Exported functions from Xenpack standard PHY control */ - -#include "mdio_10g.h" - -/****************************************************************************/ -/* XENPACK MDIO register extensions */ -#define MDIO_XP_LASI_RX_CTRL (0x9000) -#define MDIO_XP_LASI_TX_CTRL (0x9001) -#define MDIO_XP_LASI_CTRL (0x9002) -#define MDIO_XP_LASI_RX_STAT (0x9003) -#define MDIO_XP_LASI_TX_STAT (0x9004) -#define MDIO_XP_LASI_STAT (0x9005) - -/* Control/Status bits */ -#define XP_LASI_LS_ALARM (1 << 0) -#define XP_LASI_TX_ALARM (1 << 1) -#define XP_LASI_RX_ALARM (1 << 2) -/* These two are Quake vendor extensions to the standard XENPACK defines */ -#define XP_LASI_LS_INTB (1 << 3) -#define XP_LASI_TEST (1 << 7) - -/* Enable LASI interrupts for PHY */ -static inline void xenpack_enable_lasi_irqs(struct efx_nic *efx) -{ - int reg; - int phy_id = efx->mii.phy_id; - /* Read to clear LASI status register */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_XP_LASI_STAT); - - mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_XP_LASI_CTRL, XP_LASI_LS_ALARM); -} - -/* Read the LASI interrupt status to clear the interrupt. */ -static inline int xenpack_clear_lasi_irqs(struct efx_nic *efx) -{ - /* Read to clear link status alarm */ - return mdio_clause45_read(efx, efx->mii.phy_id, - MDIO_MMD_PMAPMD, MDIO_XP_LASI_STAT); -} - -/* Turn off LASI interrupts */ -static inline void xenpack_disable_lasi_irqs(struct efx_nic *efx) -{ - mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - MDIO_XP_LASI_CTRL, 0); -} - -#endif /* EFX_XENPACK_H */ diff --git a/drivers/net/sfc/xfp_phy.c b/drivers/net/sfc/xfp_phy.c deleted file mode 100644 index 2d50b6ecf5f..00000000000 --- a/drivers/net/sfc/xfp_phy.c +++ /dev/null @@ -1,171 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2006-2008 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. - */ -/* - * Driver for XFP optical PHYs (plus some support specific to the Quake 2022/32) - * See www.amcc.com for details (search for qt2032) - */ - -#include <linux/timer.h> -#include <linux/delay.h> -#include "efx.h" -#include "mdio_10g.h" -#include "xenpack.h" -#include "phy.h" -#include "falcon.h" - -#define XFP_REQUIRED_DEVS (MDIO_MMDREG_DEVS_PCS | \ - MDIO_MMDREG_DEVS_PMAPMD | \ - MDIO_MMDREG_DEVS_PHYXS) - -#define XFP_LOOPBACKS ((1 << LOOPBACK_PCS) | \ - (1 << LOOPBACK_PMAPMD) | \ - (1 << LOOPBACK_NETWORK)) - -/****************************************************************************/ -/* Quake-specific MDIO registers */ -#define MDIO_QUAKE_LED0_REG (0xD006) - -void xfp_set_led(struct efx_nic *p, int led, int mode) -{ - int addr = MDIO_QUAKE_LED0_REG + led; - mdio_clause45_write(p, p->mii.phy_id, MDIO_MMD_PMAPMD, addr, - mode); -} - -struct xfp_phy_data { - enum efx_phy_mode phy_mode; -}; - -#define XFP_MAX_RESET_TIME 500 -#define XFP_RESET_WAIT 10 - -/* Reset the PHYXS MMD. This is documented (for the Quake PHY) as doing - * a complete soft reset. - */ -static int xfp_reset_phy(struct efx_nic *efx) -{ - int rc; - - rc = mdio_clause45_reset_mmd(efx, MDIO_MMD_PHYXS, - XFP_MAX_RESET_TIME / XFP_RESET_WAIT, - XFP_RESET_WAIT); - if (rc < 0) - goto fail; - - /* Wait 250ms for the PHY to complete bootup */ - msleep(250); - - /* Check that all the MMDs we expect are present and responding. We - * expect faults on some if the link is down, but not on the PHY XS */ - rc = mdio_clause45_check_mmds(efx, XFP_REQUIRED_DEVS, - MDIO_MMDREG_DEVS_PHYXS); - if (rc < 0) - goto fail; - - efx->board_info.init_leds(efx); - - return rc; - - fail: - EFX_ERR(efx, "XFP: reset timed out!\n"); - return rc; -} - -static int xfp_phy_init(struct efx_nic *efx) -{ - struct xfp_phy_data *phy_data; - u32 devid = mdio_clause45_read_id(efx, MDIO_MMD_PHYXS); - int rc; - - phy_data = kzalloc(sizeof(struct xfp_phy_data), GFP_KERNEL); - if (!phy_data) - return -ENOMEM; - efx->phy_data = phy_data; - - EFX_INFO(efx, "XFP: PHY ID reg %x (OUI %x model %x revision" - " %x)\n", devid, MDIO_ID_OUI(devid), MDIO_ID_MODEL(devid), - MDIO_ID_REV(devid)); - - phy_data->phy_mode = efx->phy_mode; - - rc = xfp_reset_phy(efx); - - EFX_INFO(efx, "XFP: PHY init %s.\n", - rc ? "failed" : "successful"); - if (rc < 0) - goto fail; - - return 0; - - fail: - kfree(efx->phy_data); - efx->phy_data = NULL; - return rc; -} - -static void xfp_phy_clear_interrupt(struct efx_nic *efx) -{ - xenpack_clear_lasi_irqs(efx); -} - -static int xfp_link_ok(struct efx_nic *efx) -{ - return mdio_clause45_links_ok(efx, XFP_REQUIRED_DEVS); -} - -static void xfp_phy_poll(struct efx_nic *efx) -{ - int link_up = xfp_link_ok(efx); - /* Simulate a PHY event if link state has changed */ - if (link_up != efx->link_up) - falcon_sim_phy_event(efx); -} - -static void xfp_phy_reconfigure(struct efx_nic *efx) -{ - struct xfp_phy_data *phy_data = efx->phy_data; - - /* Reset the PHY when moving from tx off to tx on */ - if (!(efx->phy_mode & PHY_MODE_TX_DISABLED) && - (phy_data->phy_mode & PHY_MODE_TX_DISABLED)) - xfp_reset_phy(efx); - - mdio_clause45_transmit_disable(efx); - mdio_clause45_phy_reconfigure(efx); - - phy_data->phy_mode = efx->phy_mode; - efx->link_up = xfp_link_ok(efx); - efx->link_speed = 10000; - efx->link_fd = true; - efx->link_fc = efx->wanted_fc; -} - - -static void xfp_phy_fini(struct efx_nic *efx) -{ - /* Clobber the LED if it was blinking */ - efx->board_info.blink(efx, false); - - /* Free the context block */ - kfree(efx->phy_data); - efx->phy_data = NULL; -} - -struct efx_phy_operations falcon_xfp_phy_ops = { - .macs = EFX_XMAC, - .init = xfp_phy_init, - .reconfigure = xfp_phy_reconfigure, - .poll = xfp_phy_poll, - .fini = xfp_phy_fini, - .clear_interrupt = xfp_phy_clear_interrupt, - .get_settings = mdio_clause45_get_settings, - .set_settings = mdio_clause45_set_settings, - .mmds = XFP_REQUIRED_DEVS, - .loopbacks = XFP_LOOPBACKS, -}; |
