summaryrefslogtreecommitdiffstats
path: root/sys/dev/cxgb/common
diff options
context:
space:
mode:
authorkmacy <kmacy@FreeBSD.org>2007-06-13 05:36:00 +0000
committerkmacy <kmacy@FreeBSD.org>2007-06-13 05:36:00 +0000
commitca1df96c1a9664f95b9ecb36fac419db0b745b4c (patch)
tree35a64009a2837c5c69bdb3309b0435cdd0fe3a46 /sys/dev/cxgb/common
parenteb05a4b69fd72f248ee8d73dfb09a1e7dd6af8a3 (diff)
downloadFreeBSD-src-ca1df96c1a9664f95b9ecb36fac419db0b745b4c.zip
FreeBSD-src-ca1df96c1a9664f95b9ecb36fac419db0b745b4c.tar.gz
- import new common code for the T304
- update to firmware version 4.1.0 - switch over to standard method for initializing cdevs (contributed by scottl@) - break out timer_reclaim_task to be per-port - move msix teardown into separate function - fix bus_setup_intr for msi-x for the multi-port case so that msi-x resources are not corrupted on unload - handle 10/100/1000 base-T media and auto negotiation - bind qset to cpu even for singleq case - white space cleanups - remove recursive PORT_LOCK - move mtu setting to separate function - stop and re-init port when changing mtu - replace all direct references to m_data with calls to mtod - handle attach failure better by not trying to de-initialize taskqueues when they have not been allocated - no longer default to jumbo frames Sponsored by: Chelsio MFC after: 3 days
Diffstat (limited to 'sys/dev/cxgb/common')
-rw-r--r--sys/dev/cxgb/common/cxgb_ael1002.c10
-rw-r--r--sys/dev/cxgb/common/cxgb_common.h71
-rw-r--r--sys/dev/cxgb/common/cxgb_mc5.c10
-rw-r--r--sys/dev/cxgb/common/cxgb_t3_hw.c304
-rw-r--r--sys/dev/cxgb/common/cxgb_vsc7323.c340
-rw-r--r--sys/dev/cxgb/common/cxgb_xgmac.c117
6 files changed, 744 insertions, 108 deletions
diff --git a/sys/dev/cxgb/common/cxgb_ael1002.c b/sys/dev/cxgb/common/cxgb_ael1002.c
index 3d67b06..c570ed3 100644
--- a/sys/dev/cxgb/common/cxgb_ael1002.c
+++ b/sys/dev/cxgb/common/cxgb_ael1002.c
@@ -277,7 +277,13 @@ static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok,
unsigned int status;
status = t3_read_reg(phy->adapter,
- XGM_REG(A_XGM_SERDES_STAT0, phy->addr));
+ XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) |
+ t3_read_reg(phy->adapter,
+ XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) |
+ t3_read_reg(phy->adapter,
+ XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) |
+ t3_read_reg(phy->adapter,
+ XGM_REG(A_XGM_SERDES_STAT3, phy->addr));
*link_ok = !(status & F_LOWSIG0);
}
if (speed)
@@ -323,5 +329,5 @@ static struct cphy_ops xaui_direct_ops = {
void t3_xaui_direct_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
const struct mdio_ops *mdio_ops)
{
- cphy_init(phy, adapter, 1, &xaui_direct_ops, mdio_ops);
+ cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops);
}
diff --git a/sys/dev/cxgb/common/cxgb_common.h b/sys/dev/cxgb/common/cxgb_common.h
index 1a04772..0a60a56 100644
--- a/sys/dev/cxgb/common/cxgb_common.h
+++ b/sys/dev/cxgb/common/cxgb_common.h
@@ -38,18 +38,19 @@ $FreeBSD$
#endif
enum {
- MAX_NPORTS = 2, /* max # of ports */
- MAX_FRAME_SIZE = 10240, /* max MAC frame size, including header + FCS */
+ MAX_NPORTS = 4,
+ TP_TMR_RES = 200, /* TP timer resolution in usec */
+ MAX_FRAME_SIZE = 10240, /* max MAC frame size, includes header + FCS */
EEPROMSIZE = 8192, /* Serial EEPROM size */
RSS_TABLE_SIZE = 64, /* size of RSS lookup and mapping tables */
TCB_SIZE = 128, /* TCB size */
NMTUS = 16, /* size of MTU table */
NCCTRL_WIN = 32, /* # of congestion control windows */
NTX_SCHED = 8, /* # of HW Tx scheduling queues */
- TP_TMR_RES = 200, /* TP timer resolution in usec */
+ PROTO_SRAM_LINES = 128, /* size of protocol sram */
};
-#define MAX_RX_COALESCING_LEN 16224U
+#define MAX_RX_COALESCING_LEN 12288U
enum {
PAUSE_RX = 1 << 0,
@@ -58,7 +59,7 @@ enum {
};
enum {
- SUPPORTED_IRQ = 1 << 25
+ SUPPORTED_IRQ = 1 << 24
};
enum { /* adapter interrupt-maintained statistics */
@@ -70,8 +71,32 @@ enum { /* adapter interrupt-maintained statistics */
};
enum {
+ TP_VERSION_MAJOR = 1,
+ TP_VERSION_MINOR = 0,
+ TP_VERSION_MICRO = 44
+};
+
+#define S_TP_VERSION_MAJOR 16
+#define M_TP_VERSION_MAJOR 0xFF
+#define V_TP_VERSION_MAJOR(x) ((x) << S_TP_VERSION_MAJOR)
+#define G_TP_VERSION_MAJOR(x) \
+ (((x) >> S_TP_VERSION_MAJOR) & M_TP_VERSION_MAJOR)
+
+#define S_TP_VERSION_MINOR 8
+#define M_TP_VERSION_MINOR 0xFF
+#define V_TP_VERSION_MINOR(x) ((x) << S_TP_VERSION_MINOR)
+#define G_TP_VERSION_MINOR(x) \
+ (((x) >> S_TP_VERSION_MINOR) & M_TP_VERSION_MINOR)
+
+#define S_TP_VERSION_MICRO 0
+#define M_TP_VERSION_MICRO 0xFF
+#define V_TP_VERSION_MICRO(x) ((x) << S_TP_VERSION_MICRO)
+#define G_TP_VERSION_MICRO(x) \
+ (((x) >> S_TP_VERSION_MICRO) & M_TP_VERSION_MICRO)
+
+enum {
FW_VERSION_MAJOR = 4,
- FW_VERSION_MINOR = 0,
+ FW_VERSION_MINOR = 1,
FW_VERSION_MICRO = 0
};
@@ -116,10 +141,11 @@ struct mdio_ops {
};
struct adapter_info {
- unsigned char nports; /* # of ports */
+ unsigned char nports0; /* # of ports on channel 0 */
+ unsigned char nports1; /* # of ports on channel 1 */
unsigned char phy_base_addr; /* MDIO PHY base address */
- unsigned char mdien;
- unsigned char mdiinv;
+ unsigned char mdien:1;
+ unsigned char mdiinv:1;
unsigned int gpio_out; /* GPIO output settings */
unsigned int gpio_intr; /* GPIO IRQ enable mask */
unsigned long caps; /* adapter capabilities */
@@ -271,11 +297,13 @@ struct tp_params {
unsigned int rx_num_pgs; /* # of Rx pages */
unsigned int tx_num_pgs; /* # of Tx pages */
unsigned int ntimer_qs; /* # of timer queues */
+ unsigned int tre; /* log2 of core clocks per TP tick */
unsigned int dack_re; /* DACK timer resolution */
};
struct qset_params { /* SGE queue set parameters */
unsigned int polling; /* polling/interrupt service for rspq */
+ unsigned int lro; /* large receive offload */
unsigned int coalesce_nsecs; /* irq coalescing timer */
unsigned int rspq_size; /* # of entries in response queue */
unsigned int fl_size; /* # of entries in regular free list */
@@ -354,6 +382,7 @@ struct adapter_params {
unsigned short b_wnd[NCCTRL_WIN];
#endif
unsigned int nports; /* # of ethernet ports */
+ unsigned int chan_map; /* bitmap of in-use Tx channels */
unsigned int stats_update_period; /* MAC stats accumulation period */
unsigned int linkpoll_period; /* link poll period in 0.1s */
unsigned int rev; /* chip revision */
@@ -430,7 +459,10 @@ static inline unsigned int t3_mc7_size(const struct mc7 *p)
struct cmac {
adapter_t *adapter;
unsigned int offset;
- unsigned int nucast; /* # of address filters for unicast MACs */
+ unsigned char nucast; /* # of address filters for unicast MACs */
+ unsigned char multiport; /* multiple ports connected to this MAC */
+ unsigned char ext_port; /* external MAC port */
+ unsigned char promisc_map; /* which external ports are promiscuous */
unsigned int tx_tcnt;
unsigned int tx_xcnt;
u64 tx_mcnt;
@@ -589,9 +621,6 @@ static inline unsigned int is_pcie(const adapter_t *adap)
}
void t3_set_reg_field(adapter_t *adap, unsigned int addr, u32 mask, u32 val);
-void t3_read_indirect(adapter_t *adap, unsigned int addr_reg,
- unsigned int data_reg, u32 *vals, unsigned int nregs,
- unsigned int start_idx);
void t3_write_regs(adapter_t *adapter, const struct addr_val_pair *p, int n,
unsigned int offset);
int t3_wait_op_done_val(adapter_t *adapter, int reg, u32 mask, int polarity,
@@ -627,13 +656,14 @@ int t3_seeprom_write(adapter_t *adapter, u32 addr, u32 data);
int t3_seeprom_wp(adapter_t *adapter, int enable);
int t3_read_flash(adapter_t *adapter, unsigned int addr, unsigned int nwords,
u32 *data, int byte_oriented);
+int t3_check_tpsram_version(adapter_t *adapter);
+int t3_check_tpsram(adapter_t *adapter, u8 *tp_ram, unsigned int size);
int t3_load_fw(adapter_t *adapter, const u8 *fw_data, unsigned int size);
int t3_get_fw_version(adapter_t *adapter, u32 *vers);
int t3_check_fw_version(adapter_t *adapter);
int t3_init_hw(adapter_t *adapter, u32 fw_params);
void mac_prep(struct cmac *mac, adapter_t *adapter, int index);
void early_hw_init(adapter_t *adapter, const struct adapter_info *ai);
-int t3_reset_adapter(adapter_t *adapter);
int t3_prep_adapter(adapter_t *adapter, const struct adapter_info *ai, int reset);
void t3_led_ready(adapter_t *adapter);
void t3_fatal_err(adapter_t *adapter);
@@ -641,6 +671,7 @@ void t3_set_vlan_accel(adapter_t *adapter, unsigned int ports, int on);
void t3_config_rss(adapter_t *adapter, unsigned int rss_config, const u8 *cpus,
const u16 *rspq);
int t3_read_rss(adapter_t *adapter, u8 *lkup, u16 *map);
+int t3_set_proto_sram(adapter_t *adap, u8 *data);
int t3_mps_set_active_ports(adapter_t *adap, unsigned int port_mask);
void t3_port_failover(adapter_t *adapter, int port);
void t3_failover_done(adapter_t *adapter, int port);
@@ -657,7 +688,7 @@ int t3_mac_disable(struct cmac *mac, int which);
int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu);
int t3_mac_set_rx_mode(struct cmac *mac, struct t3_rx_mode *rm);
int t3_mac_set_address(struct cmac *mac, unsigned int idx, u8 addr[6]);
-int t3_mac_set_num_ucast(struct cmac *mac, int n);
+int t3_mac_set_num_ucast(struct cmac *mac, unsigned char n);
const struct mac_stats *t3_mac_update_stats(struct cmac *mac);
int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex,
int fc);
@@ -718,6 +749,16 @@ int t3_sge_read_rspq(adapter_t *adapter, unsigned int id, u32 data[4]);
int t3_sge_cqcntxt_op(adapter_t *adapter, unsigned int id, unsigned int op,
unsigned int credits);
+int t3_elmr_blk_write(adapter_t *adap, int start, const u32 *vals, int n);
+int t3_elmr_blk_read(adapter_t *adap, int start, u32 *vals, int n);
+int t3_vsc7323_init(adapter_t *adap, int nports);
+int t3_vsc7323_set_speed_fc(adapter_t *adap, int speed, int fc, int port);
+int t3_vsc7323_set_addr(adapter_t *adap, u8 addr[6], int port);
+int t3_vsc7323_set_mtu(adapter_t *adap, unsigned int mtu, int port);
+int t3_vsc7323_enable(adapter_t *adap, int port, int which);
+int t3_vsc7323_disable(adapter_t *adap, int port, int which);
+const struct mac_stats *t3_vsc7323_update_stats(struct cmac *mac);
+
void t3_mv88e1xxx_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
const struct mdio_ops *mdio_ops);
void t3_vsc8211_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
diff --git a/sys/dev/cxgb/common/cxgb_mc5.c b/sys/dev/cxgb/common/cxgb_mc5.c
index 9d3b94f..07a4d39 100644
--- a/sys/dev/cxgb/common/cxgb_mc5.c
+++ b/sys/dev/cxgb/common/cxgb_mc5.c
@@ -31,9 +31,11 @@ POSSIBILITY OF SUCH DAMAGE.
__FBSDID("$FreeBSD$");
#ifdef CONFIG_DEFINED
-#include <cxgb_include.h>
+#include <common/cxgb_common.h>
+#include <common/cxgb_regs.h>
#else
-#include <dev/cxgb/cxgb_include.h>
+#include <dev/cxgb/common/cxgb_common.h>
+#include <dev/cxgb/common/cxgb_regs.h>
#endif
enum {
@@ -328,9 +330,9 @@ int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters,
unsigned int tcam_size = mc5->tcam_size;
adapter_t *adap = mc5->adapter;
- if (tcam_size == 0)
+ if (!tcam_size)
return 0;
-
+
if (nroutes > MAX_ROUTES || nroutes + nservers + nfilters > tcam_size)
return -EINVAL;
diff --git a/sys/dev/cxgb/common/cxgb_t3_hw.c b/sys/dev/cxgb/common/cxgb_t3_hw.c
index ac4a630..2e92187 100644
--- a/sys/dev/cxgb/common/cxgb_t3_hw.c
+++ b/sys/dev/cxgb/common/cxgb_t3_hw.c
@@ -30,12 +30,17 @@ POSSIBILITY OF SUCH DAMAGE.
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+
#ifdef CONFIG_DEFINED
#include <cxgb_include.h>
#else
#include <dev/cxgb/cxgb_include.h>
#endif
+#define DENTER() printf("entered %s\n", __FUNCTION__);
+#define DEXIT() printf("exiting %s\n", __FUNCTION__);
+
+
/**
* t3_wait_op_done_val - wait until an operation is completed
* @adapter: the adapter performing the operation
@@ -119,7 +124,7 @@ void t3_set_reg_field(adapter_t *adapter, unsigned int addr, u32 mask, u32 val)
* Reads registers that are accessed indirectly through an address/data
* register pair.
*/
-void t3_read_indirect(adapter_t *adap, unsigned int addr_reg,
+static void t3_read_indirect(adapter_t *adap, unsigned int addr_reg,
unsigned int data_reg, u32 *vals, unsigned int nregs,
unsigned int start_idx)
{
@@ -202,7 +207,7 @@ static void mi1_init(adapter_t *adap, const struct adapter_info *ai)
t3_write_reg(adap, A_MI1_CFG, val);
}
-#define MDIO_ATTEMPTS 10
+#define MDIO_ATTEMPTS 20
/*
* MI1 read/write operations for direct-addressed PHYs.
@@ -219,7 +224,7 @@ static int mi1_read(adapter_t *adapter, int phy_addr, int mmd_addr,
MDIO_LOCK(adapter);
t3_write_reg(adapter, A_MI1_ADDR, addr);
t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(2));
- ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 20);
+ ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 10);
if (!ret)
*valp = t3_read_reg(adapter, A_MI1_DATA);
MDIO_UNLOCK(adapter);
@@ -239,7 +244,7 @@ static int mi1_write(adapter_t *adapter, int phy_addr, int mmd_addr,
t3_write_reg(adapter, A_MI1_ADDR, addr);
t3_write_reg(adapter, A_MI1_DATA, val);
t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(1));
- ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 20);
+ ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 10);
MDIO_UNLOCK(adapter);
return ret;
}
@@ -262,11 +267,11 @@ static int mi1_ext_read(adapter_t *adapter, int phy_addr, int mmd_addr,
t3_write_reg(adapter, A_MI1_ADDR, addr);
t3_write_reg(adapter, A_MI1_DATA, reg_addr);
t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(0));
- ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 20);
+ ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 10);
if (!ret) {
t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(3));
ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0,
- MDIO_ATTEMPTS, 20);
+ MDIO_ATTEMPTS, 10);
if (!ret)
*valp = t3_read_reg(adapter, A_MI1_DATA);
}
@@ -284,12 +289,12 @@ static int mi1_ext_write(adapter_t *adapter, int phy_addr, int mmd_addr,
t3_write_reg(adapter, A_MI1_ADDR, addr);
t3_write_reg(adapter, A_MI1_DATA, reg_addr);
t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(0));
- ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 20);
+ ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0, MDIO_ATTEMPTS, 10);
if (!ret) {
t3_write_reg(adapter, A_MI1_DATA, val);
t3_write_reg(adapter, A_MI1_OP, V_MDI_OP(1));
ret = t3_wait_op_done(adapter, A_MI1_OP, F_BUSY, 0,
- MDIO_ATTEMPTS, 20);
+ MDIO_ATTEMPTS, 10);
}
MDIO_UNLOCK(adapter);
return ret;
@@ -435,27 +440,32 @@ int t3_set_phy_speed_duplex(struct cphy *phy, int speed, int duplex)
}
static struct adapter_info t3_adap_info[] = {
- { 2, 0, 0, 0,
+ { 1, 1, 0, 0, 0,
F_GPIO2_OEN | F_GPIO4_OEN |
F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, F_GPIO3 | F_GPIO5,
0,
&mi1_mdio_ops, "Chelsio PE9000" },
- { 2, 0, 0, 0,
+ { 1, 1, 0, 0, 0,
F_GPIO2_OEN | F_GPIO4_OEN |
F_GPIO2_OUT_VAL | F_GPIO4_OUT_VAL, F_GPIO3 | F_GPIO5,
0,
&mi1_mdio_ops, "Chelsio T302" },
- { 1, 0, 0, 0,
+ { 1, 0, 0, 0, 0,
F_GPIO1_OEN | F_GPIO6_OEN | F_GPIO7_OEN | F_GPIO10_OEN |
F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, 0,
SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
&mi1_mdio_ext_ops, "Chelsio T310" },
- { 2, 0, 0, 0,
+ { 1, 1, 0, 0, 0,
F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO5_OEN | F_GPIO6_OEN |
F_GPIO7_OEN | F_GPIO10_OEN | F_GPIO11_OEN | F_GPIO1_OUT_VAL |
F_GPIO5_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL, 0,
SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
&mi1_mdio_ext_ops, "Chelsio T320" },
+ { 4, 0, 0, 0, 0,
+ F_GPIO5_OEN | F_GPIO6_OEN | F_GPIO7_OEN | F_GPIO5_OUT_VAL |
+ F_GPIO6_OUT_VAL | F_GPIO7_OUT_VAL,
+ F_GPIO1 | F_GPIO2 | F_GPIO3 | F_GPIO4, SUPPORTED_AUI,
+ &mi1_mdio_ops, "Chelsio T304" },
};
/*
@@ -472,7 +482,7 @@ const struct adapter_info *t3_get_adapter_info(unsigned int id)
#define CAPS_10G (SUPPORTED_10000baseT_Full | SUPPORTED_AUI)
static struct port_type_info port_types[] = {
- { NULL },
+ { NULL, 0, NULL },
{ t3_ael1002_phy_prep, CAPS_10G | SUPPORTED_FIBRE,
"10GBASE-XR" },
{ t3_vsc8211_phy_prep, CAPS_1G | SUPPORTED_TP | SUPPORTED_IRQ,
@@ -656,6 +666,8 @@ static int get_vpd_params(adapter_t *adapter, struct vpd_params *p)
} else {
p->port_type[0] = (u8)hex2int(vpd.port0_data[0]);
p->port_type[1] = (u8)hex2int(vpd.port1_data[0]);
+ p->port_type[2] = (u8)hex2int(vpd.port2_data[0]);
+ p->port_type[3] = (u8)hex2int(vpd.port3_data[0]);
p->xauicfg[0] = simple_strtoul(vpd.xaui0cfg_data, NULL, 16);
p->xauicfg[1] = simple_strtoul(vpd.xaui1cfg_data, NULL, 16);
}
@@ -847,6 +859,64 @@ static int t3_write_flash(adapter_t *adapter, unsigned int addr,
return 0;
}
+/**
+ * t3_check_tpsram_version - read the tp sram version
+ * @adapter: the adapter
+ *
+ * Reads the protocol sram version from serial eeprom.
+ */
+int t3_check_tpsram_version(adapter_t *adapter)
+{
+ int ret;
+ u32 vers;
+ unsigned int major, minor;
+
+ /* Get version loaded in SRAM */
+ t3_write_reg(adapter, A_TP_EMBED_OP_FIELD0, 0);
+ ret = t3_wait_op_done(adapter, A_TP_EMBED_OP_FIELD0,
+ 1, 1, 5, 1);
+ if (ret)
+ return ret;
+
+ vers = t3_read_reg(adapter, A_TP_EMBED_OP_FIELD1);
+
+ major = G_TP_VERSION_MAJOR(vers);
+ minor = G_TP_VERSION_MINOR(vers);
+
+ if (major == TP_VERSION_MAJOR && minor == TP_VERSION_MINOR)
+ return 0;
+
+ return -EINVAL;
+}
+
+/**
+ * t3_check_tpsram - check if provided protocol SRAM
+ * is compatible with this driver
+ * @adapter: the adapter
+ * @tp_sram: the firmware image to write
+ * @size: image size
+ *
+ * Checks if an adapter's tp sram is compatible with the driver.
+ * Returns 0 if the versions are compatible, a negative error otherwise.
+ */
+int t3_check_tpsram(adapter_t *adapter, u8 *tp_sram, unsigned int size)
+{
+ u32 csum;
+ unsigned int i;
+ const u32 *p = (const u32 *)tp_sram;
+
+ /* Verify checksum */
+ for (csum = 0, i = 0; i < size / sizeof(csum); i++)
+ csum += ntohl(p[i]);
+ if (csum != 0xffffffff) {
+ CH_ERR(adapter, "corrupted protocol SRAM image, checksum %u\n",
+ csum);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
enum fw_version_type {
FW_VERSION_N3,
FW_VERSION_T3
@@ -889,9 +959,9 @@ int t3_check_fw_version(adapter_t *adapter)
minor == FW_VERSION_MINOR)
return 0;
- CH_ERR(adapter, "found wrong FW version(%u.%u), "
- "driver needs version %d.%d\n", major, minor,
- FW_VERSION_MAJOR, FW_VERSION_MINOR);
+ CH_ERR(adapter, "found wrong FW version (%u.%u), "
+ "driver needs version %d.%d\n", major, minor,
+ FW_VERSION_MAJOR, FW_VERSION_MINOR);
return -EINVAL;
}
@@ -921,7 +991,7 @@ static int t3_flash_erase_sectors(adapter_t *adapter, int start, int end)
/*
* t3_load_fw - download firmware
* @adapter: the adapter
- * @fw_data: the firrware image to write
+ * @fw_data: the firmware image to write
* @size: image size
*
* Write the supplied firmware image to the card's serial flash.
@@ -936,7 +1006,7 @@ int t3_load_fw(adapter_t *adapter, const u8 *fw_data, unsigned int size)
const u32 *p = (const u32 *)fw_data;
int ret, addr, fw_sector = FW_FLASH_BOOT_ADDR >> 16;
- if ((size & 3) || (size < FW_MIN_SIZE))
+ if ((size & 3) || size < FW_MIN_SIZE)
return -EINVAL;
if (size > FW_VERS_ADDR + 8 - FW_FLASH_BOOT_ADDR)
return -EFBIG;
@@ -1015,9 +1085,10 @@ int t3_cim_ctl_blk_read(adapter_t *adap, unsigned int addr, unsigned int n,
void t3_link_changed(adapter_t *adapter, int port_id)
{
int link_ok, speed, duplex, fc;
- struct cphy *phy = &adapter->port[port_id].phy;
- struct cmac *mac = &adapter->port[port_id].mac;
- struct link_config *lc = &adapter->port[port_id].link_config;
+ struct port_info *pi = adap2pinfo(adapter, port_id);
+ struct cphy *phy = &pi->phy;
+ struct cmac *mac = &pi->mac;
+ struct link_config *lc = &pi->link_config;
phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc);
@@ -1487,8 +1558,12 @@ static void mc7_intr_handler(struct mc7 *mc7)
*/
static int mac_intr_handler(adapter_t *adap, unsigned int idx)
{
- struct cmac *mac = &adap->port[idx].mac;
- u32 cause = t3_read_reg(adap, A_XGM_INT_CAUSE + mac->offset);
+ u32 cause;
+ struct cmac *mac;
+
+ idx = idx == 0 ? 0 : adapter_info(adap)->nports0; /* MAC idx -> port */
+ mac = &adap2pinfo(adap, idx)->mac;
+ cause = t3_read_reg(adap, A_XGM_INT_CAUSE + mac->offset);
if (cause & V_TXFIFO_PRTY_ERR(M_TXFIFO_PRTY_ERR)) {
mac->stats.tx_fifo_parity_err++;
@@ -1524,7 +1599,7 @@ int t3_phy_intr_handler(adapter_t *adapter)
u32 i, cause = t3_read_reg(adapter, A_T3DBG_INT_CAUSE);
for_each_port(adapter, i) {
- struct port_info *p = &adapter->port[i];
+ struct port_info *p = adap2pinfo(adapter, i);
mask = gpi - (gpi & (gpi - 1));
gpi -= mask;
@@ -1556,7 +1631,6 @@ int t3_slow_intr_handler(adapter_t *adapter)
cause &= adapter->slow_intr_mask;
if (!cause)
return 0;
-
if (cause & F_PCIM0) {
if (is_pcie(adapter))
pcie_intr_handler(adapter);
@@ -1647,11 +1721,10 @@ void t3_intr_enable(adapter_t *adapter)
adapter_info(adapter)->gpio_intr);
t3_write_reg(adapter, A_T3DBG_INT_ENABLE,
adapter_info(adapter)->gpio_intr);
- if (is_pcie(adapter)) {
+ if (is_pcie(adapter))
t3_write_reg(adapter, A_PCIE_INT_ENABLE, PCIE_INTR_MASK);
- } else {
+ else
t3_write_reg(adapter, A_PCIX_INT_ENABLE, PCIX_INTR_MASK);
- }
t3_write_reg(adapter, A_PL_INT_ENABLE0, adapter->slow_intr_mask);
(void) t3_read_reg(adapter, A_PL_INT_ENABLE0); /* flush */
}
@@ -1719,8 +1792,10 @@ void t3_intr_clear(adapter_t *adapter)
*/
void t3_port_intr_enable(adapter_t *adapter, int idx)
{
- t3_write_reg(adapter, XGM_REG(A_XGM_INT_ENABLE, idx), XGM_INTR_MASK);
- adapter->port[idx].phy.ops->intr_enable(&adapter->port[idx].phy);
+ struct port_info *pi = adap2pinfo(adapter, idx);
+
+ t3_write_reg(adapter, A_XGM_INT_ENABLE + pi->mac.offset, XGM_INTR_MASK);
+ pi->phy.ops->intr_enable(&pi->phy);
}
/**
@@ -1733,8 +1808,10 @@ void t3_port_intr_enable(adapter_t *adapter, int idx)
*/
void t3_port_intr_disable(adapter_t *adapter, int idx)
{
- t3_write_reg(adapter, XGM_REG(A_XGM_INT_ENABLE, idx), 0);
- adapter->port[idx].phy.ops->intr_disable(&adapter->port[idx].phy);
+ struct port_info *pi = adap2pinfo(adapter, idx);
+
+ t3_write_reg(adapter, A_XGM_INT_ENABLE + pi->mac.offset, 0);
+ pi->phy.ops->intr_disable(&pi->phy);
}
/**
@@ -1747,10 +1824,11 @@ void t3_port_intr_disable(adapter_t *adapter, int idx)
*/
void t3_port_intr_clear(adapter_t *adapter, int idx)
{
- t3_write_reg(adapter, XGM_REG(A_XGM_INT_CAUSE, idx), 0xffffffff);
- adapter->port[idx].phy.ops->intr_clear(&adapter->port[idx].phy);
-}
+ struct port_info *pi = adap2pinfo(adapter, idx);
+ t3_write_reg(adapter, A_XGM_INT_CAUSE + pi->mac.offset, 0xffffffff);
+ pi->phy.ops->intr_clear(&pi->phy);
+}
/**
* t3_sge_write_context - write an SGE context
@@ -2344,6 +2422,14 @@ static inline void tp_wr_indirect(adapter_t *adap, unsigned int addr, u32 val)
t3_write_reg(adap, A_TP_PIO_DATA, val);
}
+static void tp_wr_bits_indirect(adapter_t *adap, unsigned int addr,
+ unsigned int mask, unsigned int val)
+{
+ t3_write_reg(adap, A_TP_PIO_ADDR, addr);
+ val |= t3_read_reg(adap, A_TP_PIO_DATA) & ~mask;
+ t3_write_reg(adap, A_TP_PIO_DATA, val);
+}
+
static void tp_config(adapter_t *adap, const struct tp_params *p)
{
t3_write_reg(adap, A_TP_GLOBAL_CONFIG, F_TXPACINGENABLE | F_PATHMTU |
@@ -2360,14 +2446,16 @@ static void tp_config(adapter_t *adap, const struct tp_params *p)
F_IPV6ENABLE | F_NICMODE);
t3_write_reg(adap, A_TP_TX_RESOURCE_LIMIT, 0x18141814);
t3_write_reg(adap, A_TP_PARA_REG4, 0x5050105);
- t3_set_reg_field(adap, A_TP_PARA_REG6,
- adap->params.rev > 0 ? F_ENABLEESND : F_T3A_ENABLEESND,
- 0);
+ t3_set_reg_field(adap, A_TP_PARA_REG6, 0,
+ adap->params.rev > 0 ? F_ENABLEESND :
+ F_T3A_ENABLEESND);
t3_set_reg_field(adap, A_TP_PC_CONFIG,
- F_ENABLEEPCMDAFULL | F_ENABLEOCSPIFULL,
- F_TXDEFERENABLE | F_HEARBEATDACK | F_TXCONGESTIONMODE |
- F_RXCONGESTIONMODE);
+ F_ENABLEEPCMDAFULL,
+ F_ENABLEOCSPIFULL |F_TXDEFERENABLE | F_HEARBEATDACK |
+ F_TXCONGESTIONMODE | F_RXCONGESTIONMODE);
t3_set_reg_field(adap, A_TP_PC_CONFIG2, F_CHDRAFULL, 0);
+ t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1080);
+ t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1000);
if (adap->params.rev > 0) {
tp_wr_indirect(adap, A_TP_EGRESS_CONFIG, F_REWRITEFORCETOSIZE);
@@ -2381,7 +2469,21 @@ static void tp_config(adapter_t *adap, const struct tp_params *p)
t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0);
t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0);
t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0);
- t3_write_reg(adap, A_TP_MOD_RATE_LIMIT, 0);
+ t3_write_reg(adap, A_TP_MOD_RATE_LIMIT, 0xf2200000);
+
+ if (adap->params.nports > 2) {
+ t3_set_reg_field(adap, A_TP_PC_CONFIG2, 0,
+ F_ENABLETXPORTFROMDA | F_ENABLERXPORTFROMADDR);
+ tp_wr_bits_indirect(adap, A_TP_QOS_RX_MAP_MODE,
+ V_RXMAPMODE(M_RXMAPMODE), 0);
+ tp_wr_indirect(adap, A_TP_INGRESS_CONFIG, V_BITPOS0(48) |
+ V_BITPOS1(49) | V_BITPOS2(50) | V_BITPOS3(51) |
+ F_ENABLEEXTRACT | F_ENABLEEXTRACTIONSFD |
+ F_ENABLEINSERTION | F_ENABLEINSERTIONSFD);
+ tp_wr_indirect(adap, A_TP_PREAMBLE_MSB, 0xfb000000);
+ tp_wr_indirect(adap, A_TP_PREAMBLE_LSB, 0xd5);
+ tp_wr_indirect(adap, A_TP_INTF_FROM_TX_PKT, F_INTFFROMTXPKT);
+ }
}
/* TCP timer values in ms */
@@ -2398,7 +2500,7 @@ static void tp_config(adapter_t *adap, const struct tp_params *p)
*/
static void tp_set_timers(adapter_t *adap, unsigned int core_clk)
{
- unsigned int tre = fls(core_clk / (1000000 / TP_TMR_RES)) - 1;
+ unsigned int tre = adap->params.tp.tre;
unsigned int dack_re = adap->params.tp.dack_re;
unsigned int tstamp_re = fls(core_clk / 1000); /* 1ms, at least */
unsigned int tps = core_clk >> tre;
@@ -2456,6 +2558,7 @@ int t3_tp_set_coalescing_size(adapter_t *adap, unsigned int size, int psh)
val |= F_RXCOALESCEENABLE;
if (psh)
val |= F_RXCOALESCEPSHEN;
+ size = min(MAX_RX_COALESCING_LEN, size);
t3_write_reg(adap, A_TP_PARA_REG2, V_RXCOALESCESIZE(size) |
V_MAXRXDATA(MAX_RX_COALESCING_LEN));
}
@@ -2485,11 +2588,10 @@ static void __devinit init_mtus(unsigned short mtus[])
* are enabled and still have at least 8 bytes of payload.
*/
mtus[0] = 88;
- mtus[1] = 88; /* workaround for silicon starting at 1 */
+ mtus[1] = 88;
mtus[2] = 256;
mtus[3] = 512;
mtus[4] = 576;
- /* mtus[4] = 808; */
mtus[5] = 1024;
mtus[6] = 1280;
mtus[7] = 1492;
@@ -2705,6 +2807,33 @@ static void ulp_config(adapter_t *adap, const struct tp_params *p)
ulp_region(adap, PBL, m, p->chan_rx_size / 4);
t3_write_reg(adap, A_ULPRX_TDDP_TAGMASK, 0xffffffff);
}
+
+
+/**
+ * t3_set_proto_sram - set the contents of the protocol sram
+ * @adapter: the adapter
+ * @data: the protocol image
+ *
+ * Write the contents of the protocol SRAM.
+ */
+int t3_set_proto_sram(adapter_t *adap, u8 *data)
+{
+ int i;
+ u32 *buf = (u32 *)data;
+
+ for (i = 0; i < PROTO_SRAM_LINES; i++) {
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD5, htobe32(*buf++));
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD4, htobe32(*buf++));
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD3, htobe32(*buf++));
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD2, htobe32(*buf++));
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD1, htobe32(*buf++));
+
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, i << 1 | 1 << 31);
+ if (t3_wait_op_done(adap, A_TP_EMBED_OP_FIELD0, 1, 1, 5, 1))
+ return -EIO;
+ }
+ return 0;
+}
#endif
void t3_config_trace_filter(adapter_t *adapter, const struct trace_params *tp,
@@ -2883,20 +3012,22 @@ int t3_mps_set_active_ports(adapter_t *adap, unsigned int port_mask)
}
/*
- * Perform the bits of HW initialization that are dependent on the number
- * of available ports.
+ * Perform the bits of HW initialization that are dependent on the Tx
+ * channels being used.
*/
-static void init_hw_for_avail_ports(adapter_t *adap, int nports)
+static void chan_init_hw(adapter_t *adap, unsigned int chan_map)
{
int i;
- if (nports == 1) {
+ if (chan_map != 3) { /* one channel */
t3_set_reg_field(adap, A_ULPRX_CTL, F_ROUND_ROBIN, 0);
t3_set_reg_field(adap, A_ULPTX_CONFIG, F_CFG_RR_ARB, 0);
- t3_write_reg(adap, A_MPS_CFG, F_TPRXPORTEN | F_TPTXPORT0EN |
- F_PORT0ACTIVE | F_ENFORCEPKT);
- t3_write_reg(adap, A_PM1_TX_CFG, 0xc000c000);
- } else {
+ t3_write_reg(adap, A_MPS_CFG, F_TPRXPORTEN | F_ENFORCEPKT |
+ (chan_map == 1 ? F_TPTXPORT0EN | F_PORT0ACTIVE :
+ F_TPTXPORT1EN | F_PORT1ACTIVE));
+ t3_write_reg(adap, A_PM1_TX_CFG,
+ chan_map == 1 ? 0xffffffff : 0);
+ } else { /* two channels */
t3_set_reg_field(adap, A_ULPRX_CTL, 0, F_ROUND_ROBIN);
t3_set_reg_field(adap, A_ULPTX_CONFIG, 0, F_CFG_RR_ARB);
t3_write_reg(adap, A_ULPTX_DMA_WEIGHT,
@@ -2999,9 +3130,9 @@ static int mc7_init(struct mc7 *mc7, unsigned int mc7_clock, int mem_type)
adapter_t *adapter = mc7->adapter;
const struct mc7_timing_params *p = &mc7_timings[mem_type];
- if (mc7->size == 0)
+ if (!mc7->size)
return 0;
-
+
val = t3_read_reg(adapter, mc7->offset + A_MC7_CFG);
slow = val & F_SLOW;
width = G_WIDTH(val);
@@ -3166,6 +3297,12 @@ int t3_init_hw(adapter_t *adapter, u32 fw_params)
else if (calibrate_xgm(adapter))
goto out_err;
+ if (adapter->params.nports > 2) {
+ t3_mac_reset(&adap2pinfo(adapter, 0)->mac);
+ if ((err = t3_vsc7323_init(adapter, adapter->params.nports)))
+ goto out_err;
+ }
+
if (vpd->mclk) {
partition_mem(adapter, &adapter->params.tp);
@@ -3194,8 +3331,8 @@ int t3_init_hw(adapter_t *adapter, u32 fw_params)
else
t3_set_reg_field(adapter, A_PCIX_CFG, 0, F_CLIDECEN);
- t3_write_reg(adapter, A_PM1_RX_CFG, 0xf000f000);
- init_hw_for_avail_ports(adapter, adapter->params.nports);
+ t3_write_reg(adapter, A_PM1_RX_CFG, 0xffffffff);
+ chan_init_hw(adapter, adapter->params.chan_map);
t3_sge_init(adapter, &adapter->params.sge);
t3_write_reg(adapter, A_CIM_HOST_ACC_DATA, vpd->uclk | fw_params);
@@ -3210,6 +3347,7 @@ int t3_init_hw(adapter_t *adapter, u32 fw_params)
CH_ERR(adapter, "uP initialization timed out\n");
goto out_err;
}
+
err = 0;
out_err:
return err;
@@ -3314,8 +3452,16 @@ static void __devinit mc7_prep(adapter_t *adapter, struct mc7 *mc7,
void mac_prep(struct cmac *mac, adapter_t *adapter, int index)
{
mac->adapter = adapter;
+ mac->multiport = adapter->params.nports > 2;
+
+ if (mac->multiport) {
+ mac->ext_port = (unsigned char)index;
+ mac->nucast = 8;
+ index = 0;
+ } else
+ mac->nucast = 1;
+
mac->offset = (XGMAC0_1_BASE_ADDR - XGMAC0_0_BASE_ADDR) * index;
- mac->nucast = 1;
if (adapter->params.rev == 0 && uses_xaui(adapter)) {
t3_write_reg(adapter, A_XGM_SERDES_CTRL + mac->offset,
@@ -3327,7 +3473,8 @@ void mac_prep(struct cmac *mac, adapter_t *adapter, int index)
void early_hw_init(adapter_t *adapter, const struct adapter_info *ai)
{
- u32 val = V_PORTSPEED(is_10G(adapter) ? 3 : 2);
+ u32 val = V_PORTSPEED(is_10G(adapter) || adapter->params.nports > 2 ?
+ 3 : 2);
mi1_init(adapter, ai);
t3_write_reg(adapter, A_I2C_CFG, /* set for 80KHz */
@@ -3335,7 +3482,7 @@ void early_hw_init(adapter_t *adapter, const struct adapter_info *ai)
t3_write_reg(adapter, A_T3DBG_GPIO_EN,
ai->gpio_out | F_GPIO0_OEN | F_GPIO0_OUT_VAL);
t3_write_reg(adapter, A_MC5_DB_SERVER_INDEX, 0);
-
+
if (adapter->params.rev == 0 || !uses_xaui(adapter))
val |= F_ENRGMII;
@@ -3354,9 +3501,9 @@ void early_hw_init(adapter_t *adapter, const struct adapter_info *ai)
* Reset the adapter. PCIe cards lose their config space during reset, PCI-X
* ones don't.
*/
-int t3_reset_adapter(adapter_t *adapter)
+static int t3_reset_adapter(adapter_t *adapter)
{
- int i, save_and_restore_pcie =
+ int i, save_and_restore_pcie =
adapter->params.rev < T3_REV_B2 && is_pcie(adapter);
uint16_t devid = 0;
@@ -3397,7 +3544,8 @@ int __devinit t3_prep_adapter(adapter_t *adapter,
get_pci_mode(adapter, &adapter->params.pci);
adapter->params.info = ai;
- adapter->params.nports = ai->nports;
+ adapter->params.nports = ai->nports0 + ai->nports1;
+ adapter->params.chan_map = !!ai->nports0 | (!!ai->nports1 << 1);
adapter->params.rev = t3_read_reg(adapter, A_PL_REV);
adapter->params.linkpoll_period = 0;
adapter->params.stats_update_period = is_10G(adapter) ?
@@ -3406,9 +3554,10 @@ int __devinit t3_prep_adapter(adapter_t *adapter,
t3_os_find_pci_capability(adapter, PCI_CAP_ID_VPD);
ret = get_vpd_params(adapter, &adapter->params.vpd);
- if (ret < 0)
+ if (ret < 0) {
+ printf("failed to get VPD params\n");
return ret;
-
+ }
if (reset && t3_reset_adapter(adapter))
return -1;
@@ -3421,7 +3570,7 @@ int __devinit t3_prep_adapter(adapter_t *adapter,
mc7_prep(adapter, &adapter->pmtx, MC7_PMTX_BASE_ADDR, "PMTX");
mc7_prep(adapter, &adapter->cm, MC7_CM_BASE_ADDR, "CM");
- p->nchan = ai->nports;
+ p->nchan = adapter->params.chan_map == 3 ? 2 : 1;
p->pmrx_size = t3_mc7_size(&adapter->pmrx);
p->pmtx_size = t3_mc7_size(&adapter->pmtx);
p->cm_size = t3_mc7_size(&adapter->cm);
@@ -3433,11 +3582,14 @@ int __devinit t3_prep_adapter(adapter_t *adapter,
p->tx_num_pgs = pm_num_pages(p->chan_tx_size, p->tx_pg_size);
p->ntimer_qs = p->cm_size >= (128 << 20) ||
adapter->params.rev > 0 ? 12 : 6;
+ p->tre = fls(adapter->params.vpd.cclk / (1000 / TP_TMR_RES)) -
+ 1;
p->dack_re = fls(adapter->params.vpd.cclk / 10) - 1; /* 100us */
}
+
adapter->params.offload = t3_mc7_size(&adapter->pmrx) &&
- t3_mc7_size(&adapter->pmtx) &&
- t3_mc7_size(&adapter->cm);
+ t3_mc7_size(&adapter->pmtx) &&
+ t3_mc7_size(&adapter->cm);
if (is_offload(adapter)) {
adapter->params.mc5.nservers = DEFAULT_NSERVERS;
@@ -3456,12 +3608,22 @@ int __devinit t3_prep_adapter(adapter_t *adapter,
for_each_port(adapter, i) {
u8 hw_addr[6];
- struct port_info *p = &adapter->port[i];
+ struct port_info *p = adap2pinfo(adapter, i);
- while (!adapter->params.vpd.port_type[j])
+ while (adapter->params.vpd.port_type[j] == 0) {
++j;
+ }
+ if (adapter->params.vpd.port_type[j] > sizeof(port_types)/sizeof(port_types[0])) {
+ printf("bad port type idx=%d\n", adapter->params.vpd.port_type[j]);
+ printf("port types: ");
+ for (i = 0; i < j; i++)
+ printf("port[%d]=%d ", i, adapter->params.vpd.port_type[i]);
+ printf("\n");
+ return -1;
+ }
+
- p->port_type = &port_types[adapter->params.vpd.port_type[j]];
+ p->port_type = &port_types[adapter->params.vpd.port_type[j]];
p->port_type->phy_prep(&p->phy, adapter, ai->phy_base_addr + j,
ai->mdio_ops);
mac_prep(&p->mac, adapter, j);
diff --git a/sys/dev/cxgb/common/cxgb_vsc7323.c b/sys/dev/cxgb/common/cxgb_vsc7323.c
new file mode 100644
index 0000000..51e254e
--- /dev/null
+++ b/sys/dev/cxgb/common/cxgb_vsc7323.c
@@ -0,0 +1,340 @@
+
+/**************************************************************************
+
+Copyright (c) 2007, Chelsio Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Neither the name of the Chelsio Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef CONFIG_DEFINED
+#include <common/cxgb_common.h>
+#else
+#include <dev/cxgb/common/cxgb_common.h>
+#endif
+
+enum {
+ ELMR_ADDR = 0,
+ ELMR_STAT = 1,
+ ELMR_DATA_LO = 2,
+ ELMR_DATA_HI = 3,
+
+ ELMR_MDIO_ADDR = 10
+};
+
+#define VSC_REG(block, subblock, reg) \
+ ((reg) | ((subblock) << 8) | ((block) << 12))
+
+int t3_elmr_blk_write(adapter_t *adap, int start, const u32 *vals, int n)
+{
+ int ret;
+ const struct mdio_ops *mo = adapter_info(adap)->mdio_ops;
+
+ ELMR_LOCK(adap);
+ ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_ADDR, start);
+ for ( ; !ret && n; n--, vals++) {
+ ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_LO,
+ *vals & 0xffff);
+ if (!ret)
+ ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_HI,
+ *vals >> 16);
+ }
+ ELMR_UNLOCK(adap);
+ return ret;
+}
+
+static int elmr_write(adapter_t *adap, int addr, u32 val)
+{
+ return t3_elmr_blk_write(adap, addr, &val, 1);
+}
+
+int t3_elmr_blk_read(adapter_t *adap, int start, u32 *vals, int n)
+{
+ int ret;
+ unsigned int v;
+ const struct mdio_ops *mo = adapter_info(adap)->mdio_ops;
+
+ ELMR_LOCK(adap);
+
+ ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_ADDR, start);
+ if (ret)
+ goto out;
+ ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_STAT, &v);
+ if (ret)
+ goto out;
+ if (v != 1) {
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+
+ for ( ; !ret && n; n--, vals++) {
+ ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_LO, vals);
+ if (!ret) {
+ ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_HI,
+ &v);
+ *vals |= v << 16;
+ }
+ }
+out: ELMR_UNLOCK(adap);
+ return ret;
+}
+
+int t3_vsc7323_init(adapter_t *adap, int nports)
+{
+ static struct addr_val_pair sys_avp[] = {
+ { VSC_REG(7, 15, 0xf), 2 },
+ { VSC_REG(7, 15, 0x19), 0xd6 },
+ { VSC_REG(7, 15, 7), 0xc },
+ { VSC_REG(7, 1, 0), 0x220 },
+ };
+ static struct addr_val_pair fifo_avp[] = {
+ { VSC_REG(2, 0, 0x2f), 0 },
+ { VSC_REG(2, 0, 0xf), 0xa0010291 },
+ { VSC_REG(2, 1, 0x2f), 1 },
+ { VSC_REG(2, 1, 0xf), 0xa0026301 }
+ };
+ static struct addr_val_pair xg_avp[] = {
+ { VSC_REG(1, 10, 0), 0x600b },
+ { VSC_REG(1, 10, 2), 0x4000 },
+ { VSC_REG(1, 10, 5), 0x65 },
+ { VSC_REG(1, 10, 7), 3 },
+ { VSC_REG(1, 10, 0x23), 0x800007bf },
+ { VSC_REG(1, 10, 0x24), 4 }
+ };
+
+ int i, ret, ing_step, egr_step, ing_bot, egr_bot;
+
+ for (i = 0; i < ARRAY_SIZE(sys_avp); i++)
+ if ((ret = t3_elmr_blk_write(adap, sys_avp[i].reg_addr,
+ &sys_avp[i].val, 1)))
+ return ret;
+
+
+ ing_step = 0xc0 / nports;
+ egr_step = 0x40 / nports;
+ ing_bot = egr_bot = 0;
+// ing_wm = ing_step * 64;
+// egr_wm = egr_step * 64;
+
+ /* {ING,EGR}_CONTROL.CLR = 1 here */
+ for (i = 0; i < nports; i++)
+ if ((ret = elmr_write(adap, VSC_REG(2, 0, 0x10 + i),
+ ((ing_bot + ing_step) << 16) | ing_bot)) ||
+ (ret = elmr_write(adap, VSC_REG(2, 0, 0x50 + i), 0)) ||
+ (ret = elmr_write(adap, VSC_REG(2, 1, 0x10 + i),
+ ((egr_bot + egr_step) << 16) | egr_bot)) ||
+ (ret = elmr_write(adap, VSC_REG(2, 1, 0x40 + i),
+ 0x2000280)) ||
+ (ret = elmr_write(adap, VSC_REG(2, 1, 0x50 + i), 0)))
+ return ret;
+
+
+ for (i = 0; i < ARRAY_SIZE(fifo_avp); i++)
+ if ((ret = t3_elmr_blk_write(adap, fifo_avp[i].reg_addr,
+ &fifo_avp[i].val, 1)))
+ return ret;
+
+ for (i = 0; i < ARRAY_SIZE(xg_avp); i++)
+ if ((ret = t3_elmr_blk_write(adap, xg_avp[i].reg_addr,
+ &xg_avp[i].val, 1)))
+ return ret;
+
+ for (i = 0; i < nports; i++)
+ if ((ret = elmr_write(adap, VSC_REG(1, i, 0), 0xa59c)) ||
+ (ret = elmr_write(adap, VSC_REG(1, i, 5),
+ (i << 12) | 0x63)) ||
+ (ret = elmr_write(adap, VSC_REG(1, i, 0xb), 0x96)) ||
+ (ret = elmr_write(adap, VSC_REG(1, i, 0x15), 0x21)))
+ return ret;
+ return ret;
+}
+
+int t3_vsc7323_set_speed_fc(adapter_t *adap, int speed, int fc, int port)
+{
+ int mode, clk, r;
+
+ if (speed >= 0) {
+ if (speed == SPEED_10)
+ mode = clk = 1;
+ else if (speed == SPEED_100)
+ mode = 1, clk = 2;
+ else if (speed == SPEED_1000)
+ mode = clk = 3;
+ else
+ return -EINVAL;
+
+ if ((r = elmr_write(adap, VSC_REG(1, port, 0),
+ 0xa590 | (mode << 2))) ||
+ (r = elmr_write(adap, VSC_REG(1, port, 0xb),
+ 0x91 | (clk << 1))) ||
+ (r = elmr_write(adap, VSC_REG(1, port, 0xb),
+ 0x90 | (clk << 1))) ||
+ (r = elmr_write(adap, VSC_REG(1, port, 0),
+ 0xa593 | (mode << 2))))
+ return r;
+ }
+
+ r = (fc & PAUSE_RX) ? 0x6ffff : 0x2ffff;
+ if (fc & PAUSE_TX)
+ r |= (1 << 19);
+ return elmr_write(adap, VSC_REG(1, port, 1), r);
+}
+
+int t3_vsc7323_set_mtu(adapter_t *adap, unsigned int mtu, int port)
+{
+ return elmr_write(adap, VSC_REG(1, port, 2), mtu);
+}
+
+int t3_vsc7323_set_addr(adapter_t *adap, u8 addr[6], int port)
+{
+ int ret;
+
+ ret = elmr_write(adap, VSC_REG(1, port, 3),
+ (addr[0] << 16) | (addr[1] << 8) | addr[2]);
+ if (!ret)
+ ret = elmr_write(adap, VSC_REG(1, port, 4),
+ (addr[3] << 16) | (addr[4] << 8) | addr[5]);
+ return ret;
+}
+
+int t3_vsc7323_enable(adapter_t *adap, int port, int which)
+{
+ int ret;
+ unsigned int v, orig;
+
+ ret = t3_elmr_blk_read(adap, VSC_REG(1, port, 0), &v, 1);
+ if (!ret) {
+ orig = v;
+ if (which & MAC_DIRECTION_TX)
+ v |= 1;
+ if (which & MAC_DIRECTION_RX)
+ v |= 2;
+ if (v != orig)
+ ret = elmr_write(adap, VSC_REG(1, port, 0), v);
+ }
+ return ret;
+}
+
+int t3_vsc7323_disable(adapter_t *adap, int port, int which)
+{
+ int ret;
+ unsigned int v, orig;
+
+ ret = t3_elmr_blk_read(adap, VSC_REG(1, port, 0), &v, 1);
+ if (!ret) {
+ orig = v;
+ if (which & MAC_DIRECTION_TX)
+ v &= ~1;
+ if (which & MAC_DIRECTION_RX)
+ v &= ~2;
+ if (v != orig)
+ ret = elmr_write(adap, VSC_REG(1, port, 0), v);
+ }
+ return ret;
+}
+
+#define STATS0_START 1
+#define STATS1_START 0x24
+#define NSTATS0 (0x1d - STATS0_START + 1)
+#define NSTATS1 (0x2a - STATS1_START + 1)
+
+const struct mac_stats *t3_vsc7323_update_stats(struct cmac *mac)
+{
+ int ret;
+ u64 rx_ucast, tx_ucast;
+ u32 stats0[NSTATS0], stats1[NSTATS1];
+
+ ret = t3_elmr_blk_read(mac->adapter,
+ VSC_REG(4, mac->ext_port, STATS0_START),
+ stats0, NSTATS0);
+ if (!ret)
+ ret = t3_elmr_blk_read(mac->adapter,
+ VSC_REG(4, mac->ext_port, STATS1_START),
+ stats1, NSTATS1);
+ if (ret)
+ goto out;
+
+ /*
+ * HW counts Rx/Tx unicast frames but we want all the frames.
+ */
+ rx_ucast = mac->stats.rx_frames - mac->stats.rx_mcast_frames -
+ mac->stats.rx_bcast_frames;
+ rx_ucast += (u64)(stats0[6 - STATS0_START] - (u32)rx_ucast);
+ tx_ucast = mac->stats.tx_frames - mac->stats.tx_mcast_frames -
+ mac->stats.tx_bcast_frames;
+ tx_ucast += (u64)(stats0[27 - STATS0_START] - (u32)tx_ucast);
+
+#define RMON_UPDATE(mac, name, hw_stat) \
+ mac->stats.name += (u64)((hw_stat) - (u32)(mac->stats.name))
+
+ RMON_UPDATE(mac, rx_octets, stats0[4 - STATS0_START]);
+ RMON_UPDATE(mac, rx_frames, stats0[6 - STATS0_START]);
+ RMON_UPDATE(mac, rx_frames, stats0[7 - STATS0_START]);
+ RMON_UPDATE(mac, rx_frames, stats0[8 - STATS0_START]);
+ RMON_UPDATE(mac, rx_mcast_frames, stats0[7 - STATS0_START]);
+ RMON_UPDATE(mac, rx_bcast_frames, stats0[8 - STATS0_START]);
+ RMON_UPDATE(mac, rx_fcs_errs, stats0[9 - STATS0_START]);
+ RMON_UPDATE(mac, rx_pause, stats0[2 - STATS0_START]);
+ RMON_UPDATE(mac, rx_jabber, stats0[16 - STATS0_START]);
+ RMON_UPDATE(mac, rx_short, stats0[11 - STATS0_START]);
+ RMON_UPDATE(mac, rx_symbol_errs, stats0[1 - STATS0_START]);
+ RMON_UPDATE(mac, rx_too_long, stats0[15 - STATS0_START]);
+
+ RMON_UPDATE(mac, rx_frames_64, stats0[17 - STATS0_START]);
+ RMON_UPDATE(mac, rx_frames_65_127, stats0[18 - STATS0_START]);
+ RMON_UPDATE(mac, rx_frames_128_255, stats0[19 - STATS0_START]);
+ RMON_UPDATE(mac, rx_frames_256_511, stats0[20 - STATS0_START]);
+ RMON_UPDATE(mac, rx_frames_512_1023, stats0[21 - STATS0_START]);
+ RMON_UPDATE(mac, rx_frames_1024_1518, stats0[22 - STATS0_START]);
+ RMON_UPDATE(mac, rx_frames_1519_max, stats0[23 - STATS0_START]);
+
+ RMON_UPDATE(mac, tx_octets, stats0[26 - STATS0_START]);
+ RMON_UPDATE(mac, tx_frames, stats0[27 - STATS0_START]);
+ RMON_UPDATE(mac, tx_frames, stats0[28 - STATS0_START]);
+ RMON_UPDATE(mac, tx_frames, stats0[29 - STATS0_START]);
+ RMON_UPDATE(mac, tx_mcast_frames, stats0[28 - STATS0_START]);
+ RMON_UPDATE(mac, tx_bcast_frames, stats0[29 - STATS0_START]);
+ RMON_UPDATE(mac, tx_pause, stats0[25 - STATS0_START]);
+
+ RMON_UPDATE(mac, tx_underrun, 0);
+
+ RMON_UPDATE(mac, tx_frames_64, stats1[36 - STATS1_START]);
+ RMON_UPDATE(mac, tx_frames_65_127, stats1[37 - STATS1_START]);
+ RMON_UPDATE(mac, tx_frames_128_255, stats1[38 - STATS1_START]);
+ RMON_UPDATE(mac, tx_frames_256_511, stats1[39 - STATS1_START]);
+ RMON_UPDATE(mac, tx_frames_512_1023, stats1[40 - STATS1_START]);
+ RMON_UPDATE(mac, tx_frames_1024_1518, stats1[41 - STATS1_START]);
+ RMON_UPDATE(mac, tx_frames_1519_max, stats1[42 - STATS1_START]);
+
+#undef RMON_UPDATE
+
+ mac->stats.rx_frames = rx_ucast + mac->stats.rx_mcast_frames +
+ mac->stats.rx_bcast_frames;
+ mac->stats.tx_frames = tx_ucast + mac->stats.tx_mcast_frames +
+ mac->stats.tx_bcast_frames;
+out: return &mac->stats;
+}
diff --git a/sys/dev/cxgb/common/cxgb_xgmac.c b/sys/dev/cxgb/common/cxgb_xgmac.c
index 22cd22e..34b05cd 100644
--- a/sys/dev/cxgb/common/cxgb_xgmac.c
+++ b/sys/dev/cxgb/common/cxgb_xgmac.c
@@ -1,3 +1,4 @@
+
/**************************************************************************
Copyright (c) 2007, Chelsio Inc.
@@ -128,8 +129,23 @@ int t3_mac_reset(struct cmac *mac)
xaui_serdes_reset(mac);
}
+
+ if (mac->multiport) {
+ t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + oft,
+ MAX_FRAME_SIZE - 4);
+ t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + oft, 0,
+ F_DISPREAMBLE);
+ t3_set_reg_field(adap, A_XGM_RX_CFG + oft, 0, F_COPYPREAMBLE |
+ F_ENNON802_3PREAMBLE);
+ t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + oft,
+ V_TXFIFOTHRESH(M_TXFIFOTHRESH),
+ V_TXFIFOTHRESH(64));
+ t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN);
+ t3_write_reg(adap, A_XGM_RX_CTRL + oft, F_RXEN);
+ }
+
val = F_MAC_RESET_;
- if (is_10G(adap))
+ if (is_10G(adap) || mac->multiport)
val |= F_PCS_RESET_;
else if (uses_xaui(adap))
val |= F_PCS_RESET_ | F_XG2G_RESET_;
@@ -220,9 +236,14 @@ static void set_addr_filter(struct cmac *mac, int idx, const u8 *addr)
/* Set one of the station's unicast MAC addresses. */
int t3_mac_set_address(struct cmac *mac, unsigned int idx, u8 addr[6])
{
+ if (mac->multiport)
+ idx = mac->ext_port + idx * mac->adapter->params.nports;
if (idx >= mac->nucast)
return -EINVAL;
set_addr_filter(mac, idx, addr);
+ if (mac->multiport && idx < mac->adapter->params.nports)
+ t3_vsc7323_set_addr(mac->adapter, addr, idx);
+
return 0;
}
@@ -231,7 +252,7 @@ int t3_mac_set_address(struct cmac *mac, unsigned int idx, u8 addr[6])
* unicast addresses. Caller should reload the unicast and multicast addresses
* after calling this.
*/
-int t3_mac_set_num_ucast(struct cmac *mac, int n)
+int t3_mac_set_num_ucast(struct cmac *mac, unsigned char n)
{
if (n > EXACT_ADDR_FILTERS)
return -EINVAL;
@@ -239,6 +260,28 @@ int t3_mac_set_num_ucast(struct cmac *mac, int n)
return 0;
}
+static void disable_exact_filters(struct cmac *mac)
+{
+ unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_LOW_1;
+
+ for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) {
+ u32 v = t3_read_reg(mac->adapter, reg);
+ t3_write_reg(mac->adapter, reg, v);
+ }
+ t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1); /* flush */
+}
+
+static void enable_exact_filters(struct cmac *mac)
+{
+ unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_HIGH_1;
+
+ for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) {
+ u32 v = t3_read_reg(mac->adapter, reg);
+ t3_write_reg(mac->adapter, reg, v);
+ }
+ t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1); /* flush */
+}
+
/* Calculate the RX hash filter index of an Ethernet address */
static int hash_hw_addr(const u8 *addr)
{
@@ -255,16 +298,18 @@ static int hash_hw_addr(const u8 *addr)
int t3_mac_set_rx_mode(struct cmac *mac, struct t3_rx_mode *rm)
{
- u32 val, hash_lo, hash_hi;
+ u32 hash_lo, hash_hi;
adapter_t *adap = mac->adapter;
unsigned int oft = mac->offset;
- val = t3_read_reg(adap, A_XGM_RX_CFG + oft) & ~F_COPYALLFRAMES;
if (promisc_rx_mode(rm))
- val |= F_COPYALLFRAMES;
- t3_write_reg(adap, A_XGM_RX_CFG + oft, val);
+ mac->promisc_map |= 1 << mac->ext_port;
+ else
+ mac->promisc_map &= ~(1 << mac->ext_port);
+ t3_set_reg_field(adap, A_XGM_RX_CFG + oft, F_COPYALLFRAMES,
+ mac->promisc_map ? F_COPYALLFRAMES : 0);
- if (allmulti_rx_mode(rm))
+ if (allmulti_rx_mode(rm) || mac->multiport)
hash_lo = hash_hi = 0xffffffff;
else {
u8 *addr;
@@ -289,7 +334,15 @@ int t3_mac_set_rx_mode(struct cmac *mac, struct t3_rx_mode *rm)
return 0;
}
-int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
+static int rx_fifo_hwm(int mtu)
+{
+ int hwm;
+
+ hwm = max(MAC_RXFIFO_SIZE - 3 * mtu, (MAC_RXFIFO_SIZE * 38) / 100);
+ return min(hwm, MAC_RXFIFO_SIZE - 8192);
+}
+
+int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
{
int hwm, lwm;
unsigned int thres, v;
@@ -300,17 +353,39 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
* packet size register includes header, but not FCS.
*/
mtu += 14;
+ if (mac->multiport)
+ mtu += 8; /* for preamble */
if (mtu > MAX_FRAME_SIZE - 4)
return -EINVAL;
- t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu);
+ if (mac->multiport)
+ return t3_vsc7323_set_mtu(adap, mtu - 4, mac->ext_port);
+
+ if (adap->params.rev == T3_REV_B2 &&
+ (t3_read_reg(adap, A_XGM_RX_CTRL + mac->offset) & F_RXEN)) {
+ disable_exact_filters(mac);
+ v = t3_read_reg(adap, A_XGM_RX_CFG + mac->offset);
+ t3_set_reg_field(adap, A_XGM_RX_CFG + mac->offset,
+ F_ENHASHMCAST | F_COPYALLFRAMES, F_DISBCAST);
+
+ /* drain rx FIFO */
+ if (t3_wait_op_done(adap,
+ A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + mac->offset,
+ 1 << 31, 1, 20, 5)) {
+ t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v);
+ enable_exact_filters(mac);
+ return -EIO;
+ }
+ t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu);
+ t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v);
+ enable_exact_filters(mac);
+ } else
+ t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu);
/*
* Adjust the PAUSE frame watermarks. We always set the LWM, and the
* HWM only if flow-control is enabled.
*/
- hwm = max_t(unsigned int, MAC_RXFIFO_SIZE - 3 * mtu,
- MAC_RXFIFO_SIZE * 38 / 100);
- hwm = min(hwm, MAC_RXFIFO_SIZE - 8192);
+ hwm = rx_fifo_hwm(mtu);
lwm = min(3 * (int) mtu, MAC_RXFIFO_SIZE /4);
v = t3_read_reg(adap, A_XGM_RXFIFO_CFG + mac->offset);
v &= ~V_RXFIFOPAUSELWM(M_RXFIFOPAUSELWM);
@@ -318,6 +393,7 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
if (G_RXFIFOPAUSEHWM(v))
v = (v & ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM)) |
V_RXFIFOPAUSEHWM(hwm / 8);
+
t3_write_reg(adap, A_XGM_RXFIFO_CFG + mac->offset, v);
/* Adjust the TX FIFO threshold based on the MTU */
@@ -335,7 +411,7 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
*/
if (adap->params.rev > 0)
t3_write_reg(adap, A_XGM_PAUSE_TIMER + mac->offset,
- (hwm-lwm) * 4 / 8);
+ (hwm - lwm) * 4 / 8);
t3_write_reg(adap, A_XGM_TX_PAUSE_QUANTA + mac->offset,
MAC_RXFIFO_SIZE * 4 * 8 / 512);
return 0;
@@ -349,6 +425,8 @@ int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc)
if (duplex >= 0 && duplex != DUPLEX_FULL)
return -EINVAL;
+ if (mac->multiport)
+ return t3_vsc7323_set_speed_fc(adap, speed, fc, mac->ext_port);
if (speed >= 0) {
if (speed == SPEED_10)
val = V_PORTSPEED(0);
@@ -364,13 +442,14 @@ int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc)
t3_set_reg_field(adap, A_XGM_PORT_CFG + oft,
V_PORTSPEED(M_PORTSPEED), val);
}
-#if 0
+
val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft);
val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM);
if (fc & PAUSE_TX)
- val |= V_RXFIFOPAUSEHWM(G_RXFIFOPAUSELWM(val) + 128); /* +1KB */
+ val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm(t3_read_reg(adap,
+ A_XGM_RX_MAX_PKT_SIZE + oft)) / 8);
t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val);
-#endif
+
t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN,
(fc & PAUSE_RX) ? F_TXPAUSEEN : 0);
return 0;
@@ -383,6 +462,9 @@ int t3_mac_enable(struct cmac *mac, int which)
unsigned int oft = mac->offset;
struct mac_stats *s = &mac->stats;
+ if (mac->multiport)
+ return t3_vsc7323_enable(adap, mac->ext_port, which);
+
if (which & MAC_DIRECTION_TX) {
t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN);
t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
@@ -415,6 +497,9 @@ int t3_mac_disable(struct cmac *mac, int which)
adapter_t *adap = mac->adapter;
int val;
+ if (mac->multiport)
+ return t3_vsc7323_disable(adap, mac->ext_port, which);
+
if (which & MAC_DIRECTION_TX) {
t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0);
t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
OpenPOWER on IntegriCloud