summaryrefslogtreecommitdiff
path: root/sys/dev/cxgb
diff options
context:
space:
mode:
authorKip Macy <kmacy@FreeBSD.org>2007-08-18 09:10:26 +0000
committerKip Macy <kmacy@FreeBSD.org>2007-08-18 09:10:26 +0000
commitf048630ee48e858dc47c8e2104dfd52332a2c93a (patch)
tree686ed9d5a9610acbd5321137b5494f477f45cd92 /sys/dev/cxgb
parent85fc7ca020774f84b1cd8cfed6a294e04d1b3802 (diff)
Notes
Diffstat (limited to 'sys/dev/cxgb')
-rw-r--r--sys/dev/cxgb/common/cxgb_common.h27
-rw-r--r--sys/dev/cxgb/common/cxgb_ctl_defs.h24
-rw-r--r--sys/dev/cxgb/common/cxgb_mc5.c45
-rw-r--r--sys/dev/cxgb/common/cxgb_t3_cpl.h36
-rw-r--r--sys/dev/cxgb/common/cxgb_t3_hw.c161
-rw-r--r--sys/dev/cxgb/common/cxgb_vsc7323.c37
-rw-r--r--sys/dev/cxgb/common/cxgb_xgmac.c55
-rw-r--r--sys/dev/cxgb/cxgb_adapter.h21
-rw-r--r--sys/dev/cxgb/cxgb_include.h8
-rw-r--r--sys/dev/cxgb/cxgb_ioctl.h29
-rw-r--r--sys/dev/cxgb/cxgb_l2t.c4
-rw-r--r--sys/dev/cxgb/cxgb_main.c667
-rw-r--r--sys/dev/cxgb/cxgb_offload.c39
-rw-r--r--sys/dev/cxgb/cxgb_offload.h19
-rw-r--r--sys/dev/cxgb/cxgb_osdep.h4
-rw-r--r--sys/dev/cxgb/cxgb_sge.c228
-rw-r--r--sys/dev/cxgb/sys/mvec.h3
-rw-r--r--sys/dev/cxgb/t3fw-4.1.0.bin.gz.uu482
-rw-r--r--sys/dev/cxgb/ulp/toecore/toedev.h2
19 files changed, 1080 insertions, 811 deletions
diff --git a/sys/dev/cxgb/common/cxgb_common.h b/sys/dev/cxgb/common/cxgb_common.h
index 0a60a560c42e..9d75102a7bd3 100644
--- a/sys/dev/cxgb/common/cxgb_common.h
+++ b/sys/dev/cxgb/common/cxgb_common.h
@@ -38,8 +38,6 @@ $FreeBSD$
#endif
enum {
- 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 */
@@ -48,6 +46,10 @@ enum {
NCCTRL_WIN = 32, /* # of congestion control windows */
NTX_SCHED = 8, /* # of HW Tx scheduling queues */
PROTO_SRAM_LINES = 128, /* size of protocol sram */
+ MAX_NPORTS = 4,
+ TP_TMR_RES = 200,
+ TP_SRAM_OFFSET = 4096, /* TP SRAM content offset in eeprom */
+ TP_SRAM_LEN = 2112, /* TP SRAM content offset in eeprom */
};
#define MAX_RX_COALESCING_LEN 12288U
@@ -72,8 +74,8 @@ enum { /* adapter interrupt-maintained statistics */
enum {
TP_VERSION_MAJOR = 1,
- TP_VERSION_MINOR = 0,
- TP_VERSION_MICRO = 44
+ TP_VERSION_MINOR = 1,
+ TP_VERSION_MICRO = 0
};
#define S_TP_VERSION_MAJOR 16
@@ -96,7 +98,7 @@ enum {
enum {
FW_VERSION_MAJOR = 4,
- FW_VERSION_MINOR = 1,
+ FW_VERSION_MINOR = 5,
FW_VERSION_MICRO = 0
};
@@ -393,6 +395,7 @@ enum { /* chip revisions */
T3_REV_A = 0,
T3_REV_B = 2,
T3_REV_B2 = 3,
+ T3_REV_C = 4,
};
struct trace_params {
@@ -467,6 +470,7 @@ struct cmac {
unsigned int tx_xcnt;
u64 tx_mcnt;
unsigned int rx_xcnt;
+ unsigned int rx_ocnt;
u64 rx_mcnt;
unsigned int toggle_cnt;
unsigned int txen;
@@ -562,6 +566,9 @@ static inline void cphy_init(struct cphy *phy, adapter_t *adapter,
/* Accumulate MAC statistics every 180 seconds. For 1G we multiply by 10. */
#define MAC_STATS_ACCUM_SECS 180
+/* The external MAC needs accumulation every 30 seconds */
+#define VSC_STATS_ACCUM_SECS 30
+
#define XGM_REG(reg_addr, idx) \
((reg_addr) + (idx) * (XGMAC0_1_BASE_ADDR - XGMAC0_0_BASE_ADDR))
@@ -656,9 +663,10 @@ 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_get_tp_version(adapter_t *adapter, u32 *vers);
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_check_tpsram(adapter_t *adapter, const u8 *tp_ram, unsigned int size);
+int t3_load_fw(adapter_t *adapter, const 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);
@@ -668,10 +676,11 @@ 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);
void t3_set_vlan_accel(adapter_t *adapter, unsigned int ports, int on);
+void t3_enable_filters(adapter_t *adap);
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_set_proto_sram(adapter_t *adap, const 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);
@@ -753,8 +762,8 @@ 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_set_addr(adapter_t *adap, u8 addr[6], 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);
diff --git a/sys/dev/cxgb/common/cxgb_ctl_defs.h b/sys/dev/cxgb/common/cxgb_ctl_defs.h
index 590995588854..e96f497bd4c3 100644
--- a/sys/dev/cxgb/common/cxgb_ctl_defs.h
+++ b/sys/dev/cxgb/common/cxgb_ctl_defs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2007 Chelsio Communications. All rights reserved.
+ * Copyright (C) 2003-2006 Chelsio Communications. All rights reserved.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -12,7 +12,6 @@
#ifndef _CXGB3_OFFLOAD_CTL_DEFS_H
#define _CXGB3_OFFLOAD_CTL_DEFS_H
-
enum {
GET_MAX_OUTSTANDING_WR,
GET_TX_MAX_CHUNK,
@@ -25,9 +24,6 @@ enum {
GET_IFF_FROM_MAC,
GET_DDP_PARAMS,
GET_PORTS,
- FAILOVER,
- FAILOVER_DONE,
- FAILOVER_CLEAR,
ULP_ISCSI_GET_PARAMS,
ULP_ISCSI_SET_PARAMS,
@@ -38,6 +34,14 @@ enum {
RDMA_CQ_DISABLE,
RDMA_CTRL_QP_SETUP,
RDMA_GET_MEM,
+
+ FAILOVER,
+ FAILOVER_DONE,
+ FAILOVER_CLEAR,
+
+ GET_CPUIDX_OF_QSET,
+
+ GET_RX_PAGE_INFO,
};
/*
@@ -81,7 +85,7 @@ struct ddp_params {
struct adap_ports {
unsigned int nports; /* number of ports on this adapter */
- struct ifnet *lldevs[4];
+ struct net_device *lldevs[2];
};
/*
@@ -102,6 +106,14 @@ struct ulp_iscsi_info {
};
/*
+ * Offload TX/RX page information.
+ */
+struct ofld_page_info {
+ unsigned int page_size; /* Page size, should be a power of 2 */
+ unsigned int num; /* Number of pages */
+};
+
+/*
* Structure used to return information to the RDMA layer.
*/
struct rdma_info {
diff --git a/sys/dev/cxgb/common/cxgb_mc5.c b/sys/dev/cxgb/common/cxgb_mc5.c
index 07a4d39b33ab..d3eed4a2c32e 100644
--- a/sys/dev/cxgb/common/cxgb_mc5.c
+++ b/sys/dev/cxgb/common/cxgb_mc5.c
@@ -165,16 +165,26 @@ static int init_mask_data_array(struct mc5 *mc5, u32 mask_array_base,
return -1;
/* Initialize the mask array. */
- dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
- for (i = 0; i < size72; i++) {
- if (i == server_base) /* entering server or routing region */
- t3_write_reg(adap, A_MC5_DB_DBGI_REQ_DATA0,
- mc5->mode == MC5_MODE_144_BIT ?
- 0xfffffff9 : 0xfffffffd);
+ for (i = 0; i < server_base; i++) {
+ dbgi_wr_data3(adap, 0x3fffffff, 0xfff80000, 0xff);
+ if (mc5_write(adap, mask_array_base + (i << addr_shift),
+ write_cmd))
+ return -1;
+ i++;
+ dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
if (mc5_write(adap, mask_array_base + (i << addr_shift),
write_cmd))
return -1;
}
+
+ dbgi_wr_data3(adap,
+ mc5->mode == MC5_MODE_144_BIT ? 0xfffffff9 : 0xfffffffd,
+ 0xffffffff, 0xff);
+ for (; i < size72; i++)
+ if (mc5_write(adap, mask_array_base + (i << addr_shift),
+ write_cmd))
+ return -1;
+
return 0;
}
@@ -305,17 +315,15 @@ static int init_idt43102(struct mc5 *mc5)
/* Put MC5 in DBGI mode. */
static inline void mc5_dbgi_mode_enable(const struct mc5 *mc5)
{
- t3_write_reg(mc5->adapter, A_MC5_DB_CONFIG,
- V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | F_DBGIEN);
+ t3_set_reg_field(mc5->adapter, A_MC5_DB_CONFIG, F_PRTYEN | F_MBUSEN,
+ F_DBGIEN);
}
/* Put MC5 in M-Bus mode. */
static void mc5_dbgi_mode_disable(const struct mc5 *mc5)
{
- t3_write_reg(mc5->adapter, A_MC5_DB_CONFIG,
- V_TMMODE(mc5->mode == MC5_MODE_72_BIT) |
- V_COMPEN(mc5->mode == MC5_MODE_72_BIT) |
- V_PRTYEN(mc5->parity_enabled) | F_MBUSEN);
+ t3_set_reg_field(mc5->adapter, A_MC5_DB_CONFIG, F_DBGIEN,
+ V_PRTYEN(mc5->parity_enabled) | F_MBUSEN);
}
/*
@@ -325,9 +333,9 @@ static void mc5_dbgi_mode_disable(const struct mc5 *mc5)
int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters,
unsigned int nroutes)
{
- u32 cfg;
int err;
unsigned int tcam_size = mc5->tcam_size;
+ unsigned int mode72 = mc5->mode == MC5_MODE_72_BIT;
adapter_t *adap = mc5->adapter;
if (!tcam_size)
@@ -336,10 +344,12 @@ int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters,
if (nroutes > MAX_ROUTES || nroutes + nservers + nfilters > tcam_size)
return -EINVAL;
+ if (nfilters && adap->params.rev < T3_REV_C)
+ mc5->parity_enabled = 0;
+
/* Reset the TCAM */
- cfg = t3_read_reg(adap, A_MC5_DB_CONFIG) & ~F_TMMODE;
- cfg |= V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | F_TMRST;
- t3_write_reg(adap, A_MC5_DB_CONFIG, cfg);
+ t3_set_reg_field(adap, A_MC5_DB_CONFIG, F_TMMODE | F_COMPEN,
+ V_COMPEN(mode72) | V_TMMODE(mode72) | F_TMRST);
if (t3_wait_op_done(adap, A_MC5_DB_CONFIG, F_TMRDY, 1, 500, 0)) {
CH_ERR(adap, "TCAM reset timed out\n");
return -1;
@@ -351,8 +361,6 @@ int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters,
t3_write_reg(adap, A_MC5_DB_SERVER_INDEX,
tcam_size - nroutes - nfilters - nservers);
- mc5->parity_enabled = 1;
-
/* All the TCAM addresses we access have only the low 32 bits non 0 */
t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR1, 0);
t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR2, 0);
@@ -467,6 +475,7 @@ void __devinit t3_mc5_prep(adapter_t *adapter, struct mc5 *mc5, int mode)
u32 cfg = t3_read_reg(adapter, A_MC5_DB_CONFIG);
mc5->adapter = adapter;
+ mc5->parity_enabled = 1;
mc5->mode = (unsigned char) mode;
mc5->part_type = (unsigned char) G_TMTYPE(cfg);
if (cfg & F_TMTYPEHI)
diff --git a/sys/dev/cxgb/common/cxgb_t3_cpl.h b/sys/dev/cxgb/common/cxgb_t3_cpl.h
index 06e99f264d74..e1b40303a6f7 100644
--- a/sys/dev/cxgb/common/cxgb_t3_cpl.h
+++ b/sys/dev/cxgb/common/cxgb_t3_cpl.h
@@ -31,10 +31,6 @@ $FreeBSD$
#ifndef T3_CPL_H
#define T3_CPL_H
-#if !defined(__LITTLE_ENDIAN_BITFIELD) && !defined(__BIG_ENDIAN_BITFIELD)
-# include <asm/byteorder.h>
-#endif
-
enum CPL_opcode {
CPL_PASS_OPEN_REQ = 0x1,
CPL_PASS_ACCEPT_RPL = 0x2,
@@ -133,6 +129,7 @@ enum CPL_error {
enum {
CPL_CONN_POLICY_AUTO = 0,
CPL_CONN_POLICY_ASK = 1,
+ CPL_CONN_POLICY_FILTER = 2,
CPL_CONN_POLICY_DENY = 3
};
@@ -259,16 +256,16 @@ struct work_request_hdr {
/* Applicable to BYPASS WRs only: the uP will added a CPL_BARRIER before
* and after the BYPASS WR if the ATOMIC bit is set.
*/
-#define S_WR_ATOMIC 16
-#define V_WR_ATOMIC(x) ((x) << S_WR_ATOMIC)
-#define F_WR_ATOMIC V_WR_ATOMIC(1U)
+#define S_WR_ATOMIC 16
+#define V_WR_ATOMIC(x) ((x) << S_WR_ATOMIC)
+#define F_WR_ATOMIC V_WR_ATOMIC(1U)
/* Applicable to BYPASS WRs only: the uP will flush buffered non abort
* related WRs.
*/
-#define S_WR_FLUSH 17
-#define V_WR_FLUSH(x) ((x) << S_WR_FLUSH)
-#define F_WR_FLUSH V_WR_FLUSH(1U)
+#define S_WR_FLUSH 17
+#define V_WR_FLUSH(x) ((x) << S_WR_FLUSH)
+#define F_WR_FLUSH V_WR_FLUSH(1U)
#define S_WR_DATATYPE 20
#define V_WR_DATATYPE(x) ((x) << S_WR_DATATYPE)
@@ -415,6 +412,11 @@ struct work_request_hdr {
#define V_CPU_IDX(x) ((x) << S_CPU_IDX)
#define G_CPU_IDX(x) (((x) >> S_CPU_IDX) & M_CPU_IDX)
+#define S_OPT1_VLAN 6
+#define M_OPT1_VLAN 0xFFF
+#define V_OPT1_VLAN(x) ((x) << S_OPT1_VLAN)
+#define G_OPT1_VLAN(x) (((x) >> S_OPT1_VLAN) & M_OPT1_VLAN)
+
#define S_MAC_MATCH_VALID 18
#define V_MAC_MATCH_VALID(x) ((x) << S_MAC_MATCH_VALID)
#define F_MAC_MATCH_VALID V_MAC_MATCH_VALID(1U)
@@ -808,6 +810,12 @@ struct tx_data_wr {
__be32 param;
};
+/* tx_data_wr.flags fields */
+#define S_TX_ACK_PAGES 21
+#define M_TX_ACK_PAGES 0x7
+#define V_TX_ACK_PAGES(x) ((x) << S_TX_ACK_PAGES)
+#define G_TX_ACK_PAGES(x) (((x) >> S_TX_ACK_PAGES) & M_TX_ACK_PAGES)
+
/* tx_data_wr.param fields */
#define S_TX_PORT 0
#define M_TX_PORT 0x7
@@ -1009,7 +1017,7 @@ struct cpl_rx_data_ddp {
union {
__be32 nxt_seq;
__be32 ddp_report;
- } __U;
+ } u;
__be32 ulp_crc;
__be32 ddpvld_status;
};
@@ -1515,7 +1523,7 @@ struct ulp_mem_io {
__be32 len;
};
- /* ulp_mem_io.cmd_lock_addr fields */
+/* ulp_mem_io.cmd_lock_addr fields */
#define S_ULP_MEMIO_ADDR 0
#define M_ULP_MEMIO_ADDR 0x7FFFFFF
#define V_ULP_MEMIO_ADDR(x) ((x) << S_ULP_MEMIO_ADDR)
@@ -1524,7 +1532,7 @@ struct ulp_mem_io {
#define V_ULP_MEMIO_LOCK(x) ((x) << S_ULP_MEMIO_LOCK)
#define F_ULP_MEMIO_LOCK V_ULP_MEMIO_LOCK(1U)
- /* ulp_mem_io.len fields */
+/* ulp_mem_io.len fields */
#define S_ULP_MEMIO_DATA_LEN 28
#define M_ULP_MEMIO_DATA_LEN 0xF
#define V_ULP_MEMIO_DATA_LEN(x) ((x) << S_ULP_MEMIO_DATA_LEN)
@@ -1534,7 +1542,7 @@ struct ulp_txpkt {
__be32 len;
};
- /* ulp_txpkt.cmd_dest fields */
+/* ulp_txpkt.cmd_dest fields */
#define S_ULP_TXPKT_DEST 24
#define M_ULP_TXPKT_DEST 0xF
#define V_ULP_TXPKT_DEST(x) ((x) << S_ULP_TXPKT_DEST)
diff --git a/sys/dev/cxgb/common/cxgb_t3_hw.c b/sys/dev/cxgb/common/cxgb_t3_hw.c
index 2b3b045a90f6..69e0e83353fd 100644
--- a/sys/dev/cxgb/common/cxgb_t3_hw.c
+++ b/sys/dev/cxgb/common/cxgb_t3_hw.c
@@ -37,8 +37,8 @@ __FBSDID("$FreeBSD$");
#include <dev/cxgb/cxgb_include.h>
#endif
-#define DENTER() printf("entered %s\n", __FUNCTION__);
-#define DEXIT() printf("exiting %s\n", __FUNCTION__);
+#undef msleep
+#define msleep t3_os_sleep
/**
@@ -355,7 +355,7 @@ int t3_phy_reset(struct cphy *phy, int mmd, int wait)
return err;
ctl &= BMCR_RESET;
if (ctl)
- t3_os_sleep(1);
+ msleep(1);
} while (ctl && --wait);
return ctl ? -1 : 0;
@@ -482,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, 0, NULL },
+ { NULL },
{ t3_ael1002_phy_prep, CAPS_10G | SUPPORTED_FIBRE,
"10GBASE-XR" },
{ t3_vsc8211_phy_prep, CAPS_1G | SUPPORTED_TP | SUPPORTED_IRQ,
@@ -501,7 +501,7 @@ static struct port_type_info port_types[] = {
#undef CAPS_10G
#define VPD_ENTRY(name, len) \
- u8 name##_kword[2]; u8 name##_len; u8 name##_data[len]
+ u8 name##_kword[2]; u8 name##_len; char name##_data[len]
/*
* Partial EEPROM Vital Product Data structure. Includes only the ID and
@@ -594,7 +594,7 @@ int t3_seeprom_write(adapter_t *adapter, u32 addr, u32 data)
t3_os_pci_write_config_2(adapter, base + PCI_VPD_ADDR,
(u16)addr | PCI_VPD_ADDR_F);
do {
- t3_os_sleep(1);
+ msleep(1);
t3_os_pci_read_config_2(adapter, base + PCI_VPD_ADDR, &val);
} while ((val & PCI_VPD_ADDR_F) && --attempts);
@@ -653,11 +653,11 @@ static int get_vpd_params(adapter_t *adapter, struct vpd_params *p)
return ret;
}
- p->cclk = simple_strtoul((char *)vpd.cclk_data, NULL, 10);
- p->mclk = simple_strtoul((char *)vpd.mclk_data, NULL, 10);
- p->uclk = simple_strtoul((char *)vpd.uclk_data, NULL, 10);
- p->mdc = simple_strtoul((char *)vpd.mdc_data, NULL, 10);
- p->mem_timing = simple_strtoul((char *)vpd.mt_data, NULL, 10);
+ p->cclk = simple_strtoul(vpd.cclk_data, NULL, 10);
+ p->mclk = simple_strtoul(vpd.mclk_data, NULL, 10);
+ p->uclk = simple_strtoul(vpd.uclk_data, NULL, 10);
+ p->mdc = simple_strtoul(vpd.mdc_data, NULL, 10);
+ p->mem_timing = simple_strtoul(vpd.mt_data, NULL, 10);
/* Old eeproms didn't have port information */
if (adapter->params.rev == 0 && !vpd.port0_data[0]) {
@@ -668,8 +668,8 @@ static int get_vpd_params(adapter_t *adapter, struct vpd_params *p)
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((char *)vpd.xaui0cfg_data, NULL, 16);
- p->xauicfg[1] = simple_strtoul((char *)vpd.xaui1cfg_data, NULL, 16);
+ p->xauicfg[0] = simple_strtoul(vpd.xaui0cfg_data, NULL, 16);
+ p->xauicfg[1] = simple_strtoul(vpd.xaui1cfg_data, NULL, 16);
}
for (i = 0; i < 6; i++)
@@ -770,7 +770,7 @@ static int flash_wait_op(adapter_t *adapter, int attempts, int delay)
if (--attempts == 0)
return -EAGAIN;
if (delay)
- t3_os_sleep(delay);
+ msleep(delay);
}
}
@@ -860,10 +860,32 @@ static int t3_write_flash(adapter_t *adapter, unsigned int addr,
}
/**
+ * t3_get_tp_version - read the tp sram version
+ * @adapter: the adapter
+ * @vers: where to place the version
+ *
+ * Reads the protocol sram version from sram.
+ */
+int t3_get_tp_version(adapter_t *adapter, u32 *vers)
+{
+ int ret;
+
+ /* 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);
+
+ 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)
{
@@ -886,6 +908,9 @@ int t3_check_tpsram_version(adapter_t *adapter)
if (major == TP_VERSION_MAJOR && minor == TP_VERSION_MINOR)
return 0;
+ CH_ERR(adapter, "found wrong TP version (%u.%u), "
+ "driver needs version %d.%d\n", major, minor,
+ TP_VERSION_MAJOR, TP_VERSION_MINOR);
return -EINVAL;
}
@@ -899,7 +924,7 @@ int t3_check_tpsram_version(adapter_t *adapter)
* 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)
+int t3_check_tpsram(adapter_t *adapter, const u8 *tp_sram, unsigned int size)
{
u32 csum;
unsigned int i;
@@ -960,8 +985,8 @@ int t3_check_fw_version(adapter_t *adapter)
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);
+ "driver needs version %d.%d\n", major, minor,
+ FW_VERSION_MAJOR, FW_VERSION_MINOR);
return -EINVAL;
}
@@ -2329,6 +2354,28 @@ void t3_tp_set_offload_mode(adapter_t *adap, int enable)
V_NICMODE(!enable));
}
+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);
+}
+
+/**
+ * t3_enable_filters - enable the HW filters
+ * @adap: the adapter
+ *
+ * Enables the HW filters for NIC traffic.
+ */
+void t3_enable_filters(adapter_t *adap)
+{
+ t3_set_reg_field(adap, A_TP_IN_CONFIG, F_NICMODE, 0);
+ t3_set_reg_field(adap, A_MC5_DB_CONFIG, 0, F_FILTEREN);
+ t3_set_reg_field(adap, A_TP_GLOBAL_CONFIG, 0, V_FIVETUPLELOOKUP(3));
+ tp_wr_bits_indirect(adap, A_TP_INGRESS_CONFIG, 0, F_LOOKUPEVERYPKT);
+}
+
/**
* pm_num_pages - calculate the number of pages of the payload memory
* @mem_size: the size of the payload memory
@@ -2422,14 +2469,6 @@ 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 |
@@ -2459,10 +2498,12 @@ static void tp_config(adapter_t *adap, const struct tp_params *p)
if (adap->params.rev > 0) {
tp_wr_indirect(adap, A_TP_EGRESS_CONFIG, F_REWRITEFORCETOSIZE);
- t3_set_reg_field(adap, A_TP_PARA_REG3, F_TXPACEAUTO,
- F_TXPACEAUTO);
+ t3_set_reg_field(adap, A_TP_PARA_REG3, 0,
+ F_TXPACEAUTO | F_TXPACEAUTOSTRICT);
t3_set_reg_field(adap, A_TP_PC_CONFIG, F_LOCKTID, F_LOCKTID);
- t3_set_reg_field(adap, A_TP_PARA_REG3, 0, F_TXPACEAUTOSTRICT);
+ tp_wr_indirect(adap, A_TP_VLAN_PRI_MAP, 0xfa50);
+ tp_wr_indirect(adap, A_TP_MAC_MATCH_MAP0, 0xfac688);
+ tp_wr_indirect(adap, A_TP_MAC_MATCH_MAP1, 0xfac688);
} else
t3_set_reg_field(adap, A_TP_PARA_REG3, 0, F_TXPACEFIXED);
@@ -2816,17 +2857,17 @@ static void ulp_config(adapter_t *adap, const struct tp_params *p)
*
* Write the contents of the protocol SRAM.
*/
-int t3_set_proto_sram(adapter_t *adap, u8 *data)
+int t3_set_proto_sram(adapter_t *adap, const u8 *data)
{
int i;
- u32 *buf = (u32 *)data;
+ u32 *buf = (u32 *)(uintptr_t)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_FIELD5, cpu_to_be32(*buf++));
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD4, cpu_to_be32(*buf++));
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD3, cpu_to_be32(*buf++));
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD2, cpu_to_be32(*buf++));
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD1, cpu_to_be32(*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))
@@ -3053,7 +3094,7 @@ static int calibrate_xgm(adapter_t *adapter)
for (i = 0; i < 5; ++i) {
t3_write_reg(adapter, A_XGM_XAUI_IMP, 0);
(void) t3_read_reg(adapter, A_XGM_XAUI_IMP);
- t3_os_sleep(1);
+ msleep(1);
v = t3_read_reg(adapter, A_XGM_XAUI_IMP);
if (!(v & (F_XGM_CALFAULT | F_CALBUSY))) {
t3_write_reg(adapter, A_XGM_XAUI_IMP,
@@ -3140,12 +3181,12 @@ static int mc7_init(struct mc7 *mc7, unsigned int mc7_clock, int mem_type)
t3_write_reg(adapter, mc7->offset + A_MC7_CFG, val | F_IFEN);
val = t3_read_reg(adapter, mc7->offset + A_MC7_CFG); /* flush */
- t3_os_sleep(1);
+ msleep(1);
if (!slow) {
t3_write_reg(adapter, mc7->offset + A_MC7_CAL, F_SGL_CAL_EN);
(void) t3_read_reg(adapter, mc7->offset + A_MC7_CAL);
- t3_os_sleep(1);
+ msleep(1);
if (t3_read_reg(adapter, mc7->offset + A_MC7_CAL) &
(F_BUSY | F_SGL_CAL_EN | F_CAL_FAULT)) {
CH_ERR(adapter, "%s MC7 calibration timed out\n",
@@ -3211,7 +3252,7 @@ static int mc7_init(struct mc7 *mc7, unsigned int mc7_clock, int mem_type)
attempts = 50;
do {
- t3_os_sleep(250);
+ msleep(250);
val = t3_read_reg(adapter, mc7->offset + A_MC7_BIST_OP);
} while ((val & F_BUSY) && --attempts);
if (val & F_BUSY) {
@@ -3297,11 +3338,8 @@ int t3_init_hw(adapter_t *adapter, u32 fw_params)
else if (calibrate_xgm(adapter))
goto out_err;
- if (adapter->params.nports > 2) {
+ 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);
@@ -3341,7 +3379,7 @@ int t3_init_hw(adapter_t *adapter, u32 fw_params)
(void) t3_read_reg(adapter, A_CIM_BOOT_CFG); /* flush */
do { /* wait for uP to initialize */
- t3_os_sleep(20);
+ msleep(20);
} while (t3_read_reg(adapter, A_CIM_HOST_ACC_DATA) && --attempts);
if (!attempts) {
CH_ERR(adapter, "uP initialization timed out\n");
@@ -3453,7 +3491,6 @@ 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;
@@ -3516,7 +3553,7 @@ static int t3_reset_adapter(adapter_t *adapter)
* XXX The delay time should be modified.
*/
for (i = 0; i < 10; i++) {
- t3_os_sleep(50);
+ msleep(50);
t3_os_pci_read_config_2(adapter, 0x00, &devid);
if (devid == 0x1425)
break;
@@ -3548,16 +3585,18 @@ int __devinit t3_prep_adapter(adapter_t *adapter,
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) ?
- MAC_STATS_ACCUM_SECS : (MAC_STATS_ACCUM_SECS * 10);
+ if (adapter->params.nports > 2)
+ adapter->params.stats_update_period = VSC_STATS_ACCUM_SECS;
+ else
+ adapter->params.stats_update_period = is_10G(adapter) ?
+ MAC_STATS_ACCUM_SECS : (MAC_STATS_ACCUM_SECS * 10);
adapter->params.pci.vpd_cap_addr =
t3_os_find_pci_capability(adapter, PCI_CAP_ID_VPD);
ret = get_vpd_params(adapter, &adapter->params.vpd);
- if (ret < 0) {
- printf("failed to get VPD params\n");
+ if (ret < 0)
return ret;
- }
+
if (reset && t3_reset_adapter(adapter))
return -1;
@@ -3606,24 +3645,18 @@ int __devinit t3_prep_adapter(adapter_t *adapter,
early_hw_init(adapter, ai);
+ if (adapter->params.nports > 2 &&
+ (ret = t3_vsc7323_init(adapter, adapter->params.nports)))
+ return ret;
+
for_each_port(adapter, i) {
u8 hw_addr[6];
struct port_info *p = adap2pinfo(adapter, i);
- while (adapter->params.vpd.port_type[j] == 0) {
+ while (!adapter->params.vpd.port_type[j])
++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
index 51e254eb15c4..4efd24e42228 100644
--- a/sys/dev/cxgb/common/cxgb_vsc7323.c
+++ b/sys/dev/cxgb/common/cxgb_vsc7323.c
@@ -115,13 +115,16 @@ int t3_vsc7323_init(adapter_t *adap, int nports)
{ VSC_REG(2, 0, 0x2f), 0 },
{ VSC_REG(2, 0, 0xf), 0xa0010291 },
{ VSC_REG(2, 1, 0x2f), 1 },
- { VSC_REG(2, 1, 0xf), 0xa0026301 }
+ { VSC_REG(2, 1, 0xf), 0xa026301 }
};
static struct addr_val_pair xg_avp[] = {
{ VSC_REG(1, 10, 0), 0x600b },
- { VSC_REG(1, 10, 2), 0x4000 },
+ { VSC_REG(1, 10, 1), 0x70600 }, //QUANTA = 96*1024*8/512
+ { VSC_REG(1, 10, 2), 0x2710 },
{ VSC_REG(1, 10, 5), 0x65 },
- { VSC_REG(1, 10, 7), 3 },
+ { VSC_REG(1, 10, 7), 0x23 },
+ { VSC_REG(1, 10, 0x23), 0x800007bf },
+ { VSC_REG(1, 10, 0x23), 0x000007bf },
{ VSC_REG(1, 10, 0x23), 0x800007bf },
{ VSC_REG(1, 10, 0x24), 4 }
};
@@ -130,10 +133,9 @@ int t3_vsc7323_init(adapter_t *adap, int nports)
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)))
+ &sys_avp[i].val, 1)))
return ret;
-
ing_step = 0xc0 / nports;
egr_step = 0x40 / nports;
ing_bot = egr_bot = 0;
@@ -141,22 +143,27 @@ int t3_vsc7323_init(adapter_t *adap, int nports)
// 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),
+ 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, 0, 0x40 + i),
+ 0x6000a00)) ||
+ (ret = elmr_write(adap, VSC_REG(2, 0, 0x50 + i), 1)) ||
(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;
-
+ ing_bot += ing_step;
+ egr_bot += egr_step;
+ }
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;
+ &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,
@@ -198,7 +205,7 @@ int t3_vsc7323_set_speed_fc(adapter_t *adap, int speed, int fc, int port)
return r;
}
- r = (fc & PAUSE_RX) ? 0x6ffff : 0x2ffff;
+ r = (fc & PAUSE_RX) ? 0x60200 : 0x20200; //QUANTA = 32*1024*8/512
if (fc & PAUSE_TX)
r |= (1 << 19);
return elmr_write(adap, VSC_REG(1, port, 1), r);
@@ -212,12 +219,12 @@ int t3_vsc7323_set_mtu(adapter_t *adap, unsigned int mtu, int port)
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]);
+ (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]);
+ (addr[3] << 16) | (addr[4] << 8) | addr[5]);
return ret;
}
diff --git a/sys/dev/cxgb/common/cxgb_xgmac.c b/sys/dev/cxgb/common/cxgb_xgmac.c
index 34b05cd09241..f11b34336337 100644
--- a/sys/dev/cxgb/common/cxgb_xgmac.c
+++ b/sys/dev/cxgb/common/cxgb_xgmac.c
@@ -37,6 +37,9 @@ __FBSDID("$FreeBSD$");
#include <dev/cxgb/cxgb_include.h>
#endif
+#undef msleep
+#define msleep t3_os_sleep
+
/*
* # of exact address filters. The first one is used for the station address,
* the rest are available for multicast addresses.
@@ -154,7 +157,7 @@ int t3_mac_reset(struct cmac *mac)
t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val);
(void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
if ((val & F_PCS_RESET_) && adap->params.rev) {
- t3_os_sleep(1);
+ msleep(1);
t3b_pcs_reset(mac);
}
@@ -179,7 +182,7 @@ static int t3b2_mac_reset(struct cmac *mac)
t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_);
(void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
- t3_os_sleep(10);
+ msleep(10);
/* Check for xgm Rx fifo empty */
if (t3_wait_op_done(adap, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + oft,
@@ -202,7 +205,7 @@ static int t3b2_mac_reset(struct cmac *mac)
t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val);
(void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
if ((val & F_PCS_RESET_) && adap->params.rev) {
- t3_os_sleep(1);
+ msleep(1);
t3b_pcs_reset(mac);
}
t3_write_reg(adap, A_XGM_RX_CFG + oft,
@@ -243,7 +246,6 @@ int t3_mac_set_address(struct cmac *mac, unsigned int idx, u8 addr[6])
set_addr_filter(mac, idx, addr);
if (mac->multiport && idx < mac->adapter->params.nports)
t3_vsc7323_set_addr(mac->adapter, addr, idx);
-
return 0;
}
@@ -425,8 +427,17 @@ 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)
+ if (mac->multiport) {
+ val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft);
+ val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM);
+ 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);
+
+ t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN,
+ F_TXPAUSEEN);
return t3_vsc7323_set_speed_fc(adap, speed, fc, mac->ext_port);
+ }
if (speed >= 0) {
if (speed == SPEED_10)
val = V_PORTSPEED(0);
@@ -451,7 +462,7 @@ int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc)
t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val);
t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN,
- (fc & PAUSE_RX) ? F_TXPAUSEEN : 0);
+ (fc & PAUSE_RX) ? F_TXPAUSEEN : 0);
return 0;
}
@@ -466,12 +477,13 @@ int t3_mac_enable(struct cmac *mac, int which)
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);
t3_write_reg(adap, A_TP_PIO_DATA, 0xc0ede401);
t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE);
t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx);
+ t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN);
+
t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + idx);
mac->tx_mcnt = s->tx_frames;
mac->tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap,
@@ -493,7 +505,6 @@ int t3_mac_enable(struct cmac *mac, int which)
int t3_mac_disable(struct cmac *mac, int which)
{
- int idx = macidx(mac);
adapter_t *adap = mac->adapter;
int val;
@@ -501,17 +512,14 @@ int t3_mac_disable(struct cmac *mac, int which)
return t3_vsc7323_disable(adap, mac->ext_port, which);
if (which & MAC_DIRECTION_TX) {
+ val = t3_read_reg(adap, A_MPS_CFG);
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);
- t3_write_reg(adap, A_TP_PIO_DATA, 0xc000001f);
- t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE);
- t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx);
mac->txen = 0;
}
if (which & MAC_DIRECTION_RX) {
t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset,
F_PCS_RESET_, 0);
- t3_os_sleep(100);
+ msleep(100);
t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0);
val = F_MAC_RESET_;
if (is_10G(adap))
@@ -535,6 +543,13 @@ int t3b2_mac_watchdog_task(struct cmac *mac)
unsigned int rx_mcnt = (unsigned int)s->rx_frames;
unsigned int rx_xcnt;
+ if (mac->multiport) {
+ tx_mcnt = t3_read_reg(adap, A_XGM_STAT_TX_FRAME_LOW);
+ rx_mcnt = t3_read_reg(adap, A_XGM_STAT_RX_FRAMES_LOW);
+ } else {
+ tx_mcnt = (unsigned int)s->tx_frames;
+ rx_mcnt = (unsigned int)s->rx_frames;
+ }
status = 0;
tx_xcnt = 1; /* By default tx_xcnt is making progress*/
tx_tcnt = mac->tx_tcnt; /* If tx_mcnt is progressing ignore tx_tcnt*/
@@ -573,15 +588,18 @@ int t3b2_mac_watchdog_task(struct cmac *mac)
}
rxcheck:
- if (rx_mcnt != mac->rx_mcnt)
+ if (rx_mcnt != mac->rx_mcnt) {
rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
A_XGM_RX_SPI4_SOP_EOP_CNT +
- mac->offset)));
- else
+ mac->offset))) +
+ (s->rx_fifo_ovfl - mac->rx_ocnt);
+ mac->rx_ocnt = s->rx_fifo_ovfl;
+ } else
goto out;
if (mac->rx_mcnt != s->rx_frames && rx_xcnt == 0 && mac->rx_xcnt == 0) {
- status = 2;
+ if (!mac->multiport)
+ status = 2;
goto out;
}
@@ -622,6 +640,9 @@ const struct mac_stats *t3_mac_update_stats(struct cmac *mac)
u32 v, lo;
+ if (mac->multiport)
+ return t3_vsc7323_update_stats(mac);
+
RMON_UPDATE64(mac, rx_octets, RX_BYTES_LOW, RX_BYTES_HIGH);
RMON_UPDATE64(mac, rx_frames, RX_FRAMES_LOW, RX_FRAMES_HIGH);
RMON_UPDATE(mac, rx_mcast_frames, RX_MCAST_FRAMES);
diff --git a/sys/dev/cxgb/cxgb_adapter.h b/sys/dev/cxgb/cxgb_adapter.h
index bdca764a38ba..6605ea9693e4 100644
--- a/sys/dev/cxgb/cxgb_adapter.h
+++ b/sys/dev/cxgb/cxgb_adapter.h
@@ -117,7 +117,7 @@ struct port_info {
#else
struct mtx lock;
#endif
- int port;
+ int port_id;
uint8_t hw_addr[ETHER_ADDR_LEN];
uint8_t nqsets;
uint8_t first_qset;
@@ -138,6 +138,7 @@ enum { /* adapter flags */
USING_MSIX = (1 << 2),
QUEUES_BOUND = (1 << 3),
FW_UPTODATE = (1 << 4),
+ TPS_UPTODATE = (1 << 5),
};
@@ -239,6 +240,8 @@ struct sge_fl {
struct tx_desc;
struct tx_sw_desc;
+#define TXQ_TRANSMITTING 0x1
+
struct sge_txq {
uint64_t flags;
uint32_t in_use;
@@ -254,7 +257,9 @@ struct sge_txq {
struct tx_sw_desc *sdesc;
uint32_t token;
bus_addr_t phys_addr;
- struct task qresume_tsk;
+ struct task qresume_task;
+ struct task qreclaim_task;
+ struct port_info *port;
uint32_t cntxt_id;
uint64_t stops;
uint64_t restarts;
@@ -297,13 +302,15 @@ struct sge {
struct mtx reg_lock;
};
+struct filter_info;
+
struct adapter {
device_t dev;
int flags;
TAILQ_ENTRY(adapter) adapter_entry;
/* PCI register resources */
- uint32_t regs_rid;
+ int regs_rid;
struct resource *regs_res;
bus_space_handle_t bh;
bus_space_tag_t bt;
@@ -327,7 +334,11 @@ struct adapter {
struct resource *msix_irq_res[SGE_QSETS];
int msix_irq_rid[SGE_QSETS];
void *msix_intr_tag[SGE_QSETS];
+ uint8_t rxpkt_map[8]; /* maps RX_PKT interface values to port ids */
+ uint8_t rrss_map[SGE_QSETS]; /* revers RSS map table */
+ struct filter_info *filters;
+
/* Tasks */
struct task ext_intr_task;
struct task slow_intr_task;
@@ -391,13 +402,13 @@ struct t3_rx_mode {
#define PORT_UNLOCK(port) sx_xunlock(&(port)->lock);
#define PORT_LOCK_INIT(port, name) SX_INIT(&(port)->lock, name)
#define PORT_LOCK_DEINIT(port) SX_DESTROY(&(port)->lock)
-#define PORT_LOCK_ASSERT_OWNED(port) sx_assert(&(port)->lock, SX_LOCKED)
+#define PORT_LOCK_ASSERT_OWNED(port) sx_assert(&(port)->lock, SA_LOCKED)
#define ADAPTER_LOCK(adap) sx_xlock(&(adap)->lock);
#define ADAPTER_UNLOCK(adap) sx_xunlock(&(adap)->lock);
#define ADAPTER_LOCK_INIT(adap, name) SX_INIT(&(adap)->lock, name)
#define ADAPTER_LOCK_DEINIT(adap) SX_DESTROY(&(adap)->lock)
-#define ADAPTER_LOCK_ASSERT_NOTOWNED(adap) sx_assert(&(adap)->lock, SX_UNLOCKED)
+#define ADAPTER_LOCK_ASSERT_NOTOWNED(adap) sx_assert(&(adap)->lock, SA_UNLOCKED)
#else
#define PORT_LOCK(port) mtx_lock(&(port)->lock);
#define PORT_UNLOCK(port) mtx_unlock(&(port)->lock);
diff --git a/sys/dev/cxgb/cxgb_include.h b/sys/dev/cxgb/cxgb_include.h
index 0caebec62120..c4eb5add9ffe 100644
--- a/sys/dev/cxgb/cxgb_include.h
+++ b/sys/dev/cxgb/cxgb_include.h
@@ -5,15 +5,13 @@
#ifdef CONFIG_DEFINED
#include <cxgb_osdep.h>
-#include <cxgb_l2t.h>
#include <common/cxgb_common.h>
#include <cxgb_ioctl.h>
#include <cxgb_offload.h>
#include <common/cxgb_regs.h>
#include <common/cxgb_t3_cpl.h>
-#include <common/cxgb_tcb.h>
-#include <common/cxgb_ctl_defs.h>
-#include <common/cxgb_sge_defs.h>
+#include <dev/cxgb/common/cxgb_ctl_defs.h>
+#include <dev/cxgb/common/cxgb_sge_defs.h>
#include <common/cxgb_firmware_exports.h>
#include <sys/mvec.h>
#include <ulp/toecore/toedev.h>
@@ -25,10 +23,8 @@
#include <dev/cxgb/cxgb_osdep.h>
#include <dev/cxgb/common/cxgb_common.h>
#include <dev/cxgb/cxgb_ioctl.h>
-#include <dev/cxgb/cxgb_l2t.h>
#include <dev/cxgb/cxgb_offload.h>
#include <dev/cxgb/common/cxgb_regs.h>
-#include <dev/cxgb/common/cxgb_tcb.h>
#include <dev/cxgb/common/cxgb_t3_cpl.h>
#include <dev/cxgb/common/cxgb_ctl_defs.h>
#include <dev/cxgb/common/cxgb_sge_defs.h>
diff --git a/sys/dev/cxgb/cxgb_ioctl.h b/sys/dev/cxgb/cxgb_ioctl.h
index d725a9a06ae9..65deb447da3b 100644
--- a/sys/dev/cxgb/cxgb_ioctl.h
+++ b/sys/dev/cxgb/cxgb_ioctl.h
@@ -66,6 +66,7 @@ enum {
CH_SETMIIREGS,
CH_SET_FILTER,
CH_SET_HW_SCHED,
+ CH_DEL_FILTER,
};
struct ch_reg {
@@ -127,7 +128,31 @@ struct ch_hw_sched {
int8_t channel;
int32_t kbps; /* rate in Kbps */
int32_t class_ipg; /* tenths of nanoseconds */
- int32_t flow_ipg; /* usec */
+ uint32_t flow_ipg; /* usec */
+};
+
+struct ch_filter_tuple {
+ uint32_t sip;
+ uint32_t dip;
+ uint16_t sport;
+ uint16_t dport;
+ uint16_t vlan:12;
+ uint16_t vlan_prio:3;
+};
+
+struct ch_filter {
+ uint32_t cmd;
+ uint32_t filter_id;
+ struct ch_filter_tuple val;
+ struct ch_filter_tuple mask;
+ uint16_t mac_addr_idx;
+ uint8_t mac_hit:1;
+ uint8_t proto:2;
+
+ uint8_t want_filter_id:1; /* report filter TID instead of RSS hash */
+ uint8_t pass:1; /* whether to pass or drop packets */
+ uint8_t rss:1; /* use RSS or specified qset */
+ uint8_t qset;
};
#ifndef TCB_SIZE
@@ -232,5 +257,7 @@ struct mii_data {
#define SIOCGMIIREG _IOWR('f', CH_GETMIIREGS, struct mii_data)
#define SIOCSMIIREG _IOWR('f', CH_SETMIIREGS, struct mii_data)
#define CHELSIO_SET_HW_SCHED _IOWR('f', CH_SET_HW_SCHED, struct ch_hw_sched)
+#define CHELSIO_SET_FILTER _IOW('f', CH_SET_FILTER, struct ch_filter)
+#define CHELSIO_DEL_FILTER _IOW('f', CH_DEL_FILTER, struct ch_filter)
#define CHELSIO_DEVUP _IO('f', CH_DEVUP)
#endif
diff --git a/sys/dev/cxgb/cxgb_l2t.c b/sys/dev/cxgb/cxgb_l2t.c
index 97c0ffafc381..d4a40bad430d 100644
--- a/sys/dev/cxgb/cxgb_l2t.c
+++ b/sys/dev/cxgb/cxgb_l2t.c
@@ -37,7 +37,9 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/lock.h>
#include <sys/mutex.h>
-
+#if __FreeBSD_version > 700000
+#include <sys/rwlock.h>
+#endif
#include <sys/socket.h>
#include <sys/socketvar.h>
diff --git a/sys/dev/cxgb/cxgb_main.c b/sys/dev/cxgb/cxgb_main.c
index 07e4b175d0cd..04fd15fd5c44 100644
--- a/sys/dev/cxgb/cxgb_main.c
+++ b/sys/dev/cxgb/cxgb_main.c
@@ -189,6 +189,7 @@ extern int collapse_mbufs;
* msi = 0: force pin interrupts
*/
static int msi_allowed = 2;
+
TUNABLE_INT("hw.cxgb.msi_allowed", &msi_allowed);
SYSCTL_NODE(_hw, OID_AUTO, cxgb, CTLFLAG_RD, 0, "CXGB driver parameters");
SYSCTL_UINT(_hw_cxgb, OID_AUTO, msi_allowed, CTLFLAG_RDTUN, &msi_allowed, 0,
@@ -224,6 +225,28 @@ enum {
MIN_FL_ENTRIES = 32
};
+struct filter_info {
+ u32 sip;
+ u32 sip_mask;
+ u32 dip;
+ u16 sport;
+ u16 dport;
+ u32 vlan:12;
+ u32 vlan_prio:3;
+ u32 mac_hit:1;
+ u32 mac_idx:4;
+ u32 mac_vld:1;
+ u32 pkt_type:2;
+ u32 report_filter_id:1;
+ u32 pass:1;
+ u32 rss:1;
+ u32 qset:3;
+ u32 locked:1;
+ u32 valid:1;
+};
+
+enum { FILTER_NO_VLAN_PRI = 7 };
+
#define PORT_MASK ((1 << MAX_NPORTS) - 1)
/* Table for probing the cards. The desc field isn't actually used */
@@ -247,6 +270,29 @@ struct cxgb_ident {
{0, 0, 0, NULL}
};
+
+static int set_eeprom(struct port_info *pi, const uint8_t *data, int len, int offset);
+
+static inline char
+t3rev2char(struct adapter *adapter)
+{
+ char rev = 'z';
+
+ switch(adapter->params.rev) {
+ case T3_REV_A:
+ rev = 'a';
+ break;
+ case T3_REV_B:
+ case T3_REV_B2:
+ rev = 'b';
+ break;
+ case T3_REV_C:
+ rev = 'c';
+ break;
+ }
+ return rev;
+}
+
static struct cxgb_ident *
cxgb_get_ident(device_t dev)
{
@@ -298,6 +344,10 @@ cxgb_controller_probe(device_t dev)
return (BUS_PROBE_DEFAULT);
}
+#define FW_FNAME "t3fw%d%d%d"
+#define TPEEPROM_NAME "t3%ctpe%d%d%d"
+#define TPSRAM_NAME "t3%cps%d%d%d"
+
static int
upgrade_fw(adapter_t *sc)
{
@@ -309,7 +359,7 @@ upgrade_fw(adapter_t *sc)
#endif
int status;
- snprintf(&buf[0], sizeof(buf), "t3fw%d%d%d", FW_VERSION_MAJOR,
+ snprintf(&buf[0], sizeof(buf), FW_FNAME, FW_VERSION_MAJOR,
FW_VERSION_MINOR, FW_VERSION_MICRO);
fw = firmware_get(buf);
@@ -317,9 +367,12 @@ upgrade_fw(adapter_t *sc)
if (fw == NULL) {
device_printf(sc->dev, "Could not find firmware image %s\n", buf);
return (ENOENT);
- }
+ } else
+ device_printf(sc->dev, "updating firmware on card with %s\n", buf);
status = t3_load_fw(sc, (const uint8_t *)fw->data, fw->datasize);
+ device_printf(sc->dev, "firmware update returned %s %d\n", (status == 0) ? "success" : "fail", status);
+
firmware_put(fw, FIRMWARE_UNLOAD);
return (status);
@@ -331,14 +384,17 @@ cxgb_controller_attach(device_t dev)
device_t child;
const struct adapter_info *ai;
struct adapter *sc;
- int i, reg, msi_needed, error = 0;
+ int i, reg, error = 0;
uint32_t vers;
int port_qsets = 1;
+#ifdef MSI_SUPPORTED
+ int msi_needed;
+#endif
+
sc = device_get_softc(dev);
sc->dev = dev;
sc->msi_count = 0;
- msi_needed = 0;
/* find the PCIe link width and set max read request to 4KB*/
if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
@@ -350,7 +406,10 @@ cxgb_controller_attach(device_t dev)
pectl = (pectl & ~0x7000) | (5 << 12);
pci_write_config(dev, reg + 0x8, pectl, 2);
}
- if (sc->link_width != 0 && sc->link_width <= 4) {
+
+ ai = cxgb_get_adapter_info(dev);
+ if (sc->link_width != 0 && sc->link_width <= 4 &&
+ (ai->nports0 + ai->nports1) <= 2) {
device_printf(sc->dev,
"PCIe x%d Link, expect reduced performance\n",
sc->link_width);
@@ -363,7 +422,7 @@ cxgb_controller_attach(device_t dev)
*/
sc->regs_rid = PCIR_BAR(0);
if ((sc->regs_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- (int *)&sc->regs_rid, RF_ACTIVE)) == NULL) {
+ &sc->regs_rid, RF_ACTIVE)) == NULL) {
device_printf(dev, "Cannot allocate BAR\n");
return (ENXIO);
}
@@ -387,7 +446,6 @@ cxgb_controller_attach(device_t dev)
sc->bh = rman_get_bushandle(sc->regs_res);
sc->mmio_len = rman_get_size(sc->regs_res);
- ai = cxgb_get_adapter_info(dev);
if (t3_prep_adapter(sc, ai, 1) < 0) {
printf("prep adapter failed\n");
error = ENODEV;
@@ -455,12 +513,12 @@ cxgb_controller_attach(device_t dev)
device_printf(dev, "failed to allocate controller task queue\n");
goto out;
}
-
+
taskqueue_start_threads(&sc->tq, 1, PI_NET, "%s taskq",
device_get_nameunit(dev));
TASK_INIT(&sc->ext_intr_task, 0, cxgb_ext_intr_handler, sc);
-
TASK_INIT(&sc->tick_task, 0, cxgb_tick_handler, sc);
+
/* Create a periodic callout for checking adapter status */
callout_init(&sc->cxgb_tick_ch, TRUE);
@@ -475,6 +533,17 @@ cxgb_controller_attach(device_t dev)
} else {
sc->flags |= FW_UPTODATE;
}
+
+ if (t3_check_tpsram_version(sc) != 0) {
+ /*
+ * Warn user that a firmware update will be attempted in init.
+ */
+ device_printf(dev, "SRAM needs to be updated to version %c-%d.%d.%d\n",
+ t3rev2char(sc), TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO);
+ sc->flags &= ~TPS_UPTODATE;
+ } else {
+ sc->flags |= TPS_UPTODATE;
+ }
if ((sc->flags & USING_MSIX) && !singleq)
port_qsets = min((SGE_QSETS/(sc)->params.nports), mp_ncpus);
@@ -489,11 +558,11 @@ cxgb_controller_attach(device_t dev)
error = EINVAL;
goto out;
}
- sc->portdev[i] = child;
sc->port[i].adapter = sc;
sc->port[i].nqsets = port_qsets;
sc->port[i].first_qset = i*port_qsets;
- sc->port[i].port = i;
+ sc->port[i].port_id = i;
+ sc->portdev[i] = child;
device_set_softc(child, &sc->port[i]);
}
if ((error = bus_generic_attach(dev)) != 0)
@@ -569,12 +638,12 @@ cxgb_free(struct adapter *sc)
t3_sge_deinit_sw(sc);
if (sc->tq != NULL) {
- taskqueue_drain(sc->tq, &sc->tick_task);
taskqueue_drain(sc->tq, &sc->ext_intr_task);
+ taskqueue_drain(sc->tq, &sc->tick_task);
taskqueue_free(sc->tq);
+ }
tsleep(&sc, 0, "cxgb unload", hz);
- }
for (i = 0; i < (sc)->params.nports; ++i) {
if (sc->portdev[i] != NULL)
@@ -588,8 +657,10 @@ cxgb_free(struct adapter *sc)
if (isset(&sc->open_device_map, OFFLOAD_DEVMAP_BIT))
offload_close(&sc->tdev);
}
-#endif
+#endif
+
t3_free_sge_resources(sc);
+ free(sc->filters, M_DEVBUF);
t3_sge_free(sc);
cxgb_offload_exit();
@@ -606,6 +677,111 @@ cxgb_free(struct adapter *sc)
return;
}
+static int
+alloc_filters(struct adapter *adap)
+{
+ struct filter_info *p;
+ int nfilters;
+
+ if ((nfilters = adap->params.mc5.nfilters) == 0)
+ return (0);
+
+ adap->filters = malloc(nfilters*sizeof(struct filter_info),
+ M_DEVBUF, M_ZERO|M_WAITOK);
+
+ if (adap->filters == NULL)
+ return (ENOMEM);
+
+ /* Set the default filters, only need to set non-0 fields here. */
+ p = &adap->filters[nfilters - 1];
+ p->vlan = 0xfff;
+ p->vlan_prio = FILTER_NO_VLAN_PRI;
+ p->pass = p->rss = p->valid = p->locked = 1;
+
+ return (0);
+}
+
+static inline void
+set_tcb_field_ulp(struct cpl_set_tcb_field *req,
+ unsigned int tid, unsigned int word,
+ uint64_t mask, uint64_t val)
+{
+ struct ulp_txpkt *txpkt = (struct ulp_txpkt *)req;
+
+ txpkt->cmd_dest = htonl(V_ULPTX_CMD(ULP_TXPKT));
+ txpkt->len = htonl(V_ULPTX_NFLITS(sizeof(*req) / 8));
+ OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
+ req->reply = V_NO_REPLY(1);
+ req->cpu_idx = 0;
+ req->word = htons(word);
+ req->mask = htobe64(mask);
+ req->val = htobe64(val);
+}
+
+static int
+set_filter(struct adapter *adap, int id, const struct filter_info *f)
+{
+ int len;
+ struct mbuf *m;
+ struct ulp_txpkt *txpkt;
+ struct work_request_hdr *wr;
+ struct cpl_pass_open_req *oreq;
+ struct cpl_set_tcb_field *sreq;
+
+ len = sizeof(*wr) + sizeof(*oreq) + 2 * sizeof(*sreq);
+ id += t3_mc5_size(&adap->mc5) - adap->params.mc5.nroutes -
+ adap->params.mc5.nfilters;
+
+ m = m_gethdr(M_TRYWAIT, MT_DATA);
+ wr = mtod(m, struct work_request_hdr *);
+ wr->wr_hi = htonl(V_WR_OP(FW_WROPCODE_BYPASS) | F_WR_ATOMIC);
+ m->m_len = m->m_pkthdr.len = len;
+
+ oreq = (struct cpl_pass_open_req *)(wr + 1);
+ txpkt = (struct ulp_txpkt *)oreq;
+ txpkt->cmd_dest = htonl(V_ULPTX_CMD(ULP_TXPKT));
+ txpkt->len = htonl(V_ULPTX_NFLITS(sizeof(*oreq) / 8));
+ OPCODE_TID(oreq) = htonl(MK_OPCODE_TID(CPL_PASS_OPEN_REQ, id));
+ oreq->local_port = htons(f->dport);
+ oreq->peer_port = htons(f->sport);
+ oreq->local_ip = htonl(f->dip);
+ oreq->peer_ip = htonl(f->sip);
+ oreq->peer_netmask = htonl(f->sip_mask);
+ oreq->opt0h = 0;
+ oreq->opt0l = htonl(F_NO_OFFLOAD);
+ oreq->opt1 = htonl(V_MAC_MATCH_VALID(f->mac_vld) |
+ V_CONN_POLICY(CPL_CONN_POLICY_FILTER) |
+ V_VLAN_PRI(f->vlan_prio >> 1) |
+ V_VLAN_PRI_VALID(f->vlan_prio != FILTER_NO_VLAN_PRI) |
+ V_PKT_TYPE(f->pkt_type) | V_OPT1_VLAN(f->vlan) |
+ V_MAC_MATCH(f->mac_idx | (f->mac_hit << 4)));
+
+ sreq = (struct cpl_set_tcb_field *)(oreq + 1);
+ set_tcb_field_ulp(sreq, id, 1, 0x1800808000ULL,
+ (f->report_filter_id << 15) | (1 << 23) |
+ ((u64)f->pass << 35) | ((u64)!f->rss << 36));
+ set_tcb_field_ulp(sreq + 1, id, 25, 0x3f80000,
+ (u64)adap->rrss_map[f->qset] << 19);
+ t3_mgmt_tx(adap, m);
+ return 0;
+}
+
+static int
+setup_hw_filters(struct adapter *adap)
+{
+ int i, err;
+
+ if (adap->filters == NULL)
+ return 0;
+
+ t3_enable_filters(adap);
+
+ for (i = err = 0; i < adap->params.mc5.nfilters && !err; i++)
+ if (adap->filters[i].locked)
+ err = set_filter(adap, i, &adap->filters[i]);
+ return err;
+}
+
/**
* setup_sge_qsets - configure SGE Tx/Rx/response queues
* @sc: the controller softc
@@ -695,7 +871,7 @@ cxgb_setup_msix(adapter_t *sc, int msix_count)
nqsets = sc->port[i].nqsets;
for (j = 0; j < nqsets; j++, k++) {
struct sge_qset *qs = &sc->sge.qs[k];
-
+
rid = k + 2;
if (cxgb_debug)
printf("rid=%d ", rid);
@@ -732,7 +908,7 @@ cxgb_port_probe(device_t dev)
p = device_get_softc(dev);
- snprintf(buf, sizeof(buf), "Port %d %s", p->port, p->port_type->desc);
+ snprintf(buf, sizeof(buf), "Port %d %s", p->port_id, p->port_type->desc);
device_set_desc_copy(dev, buf);
return (0);
}
@@ -743,7 +919,7 @@ cxgb_makedev(struct port_info *pi)
{
pi->port_cdev = make_dev(&cxgb_cdevsw, pi->ifp->if_dunit,
- UID_ROOT, GID_WHEEL, 0600, pi->ifp->if_xname);
+ UID_ROOT, GID_WHEEL, 0600, if_name(pi->ifp));
if (pi->port_cdev == NULL)
return (ENOMEM);
@@ -763,6 +939,7 @@ cxgb_makedev(struct port_info *pi)
/* Don't enable TSO6 yet */
#define CXGB_CAP_ENABLE (IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU | IFCAP_HWCSUM | IFCAP_JUMBO_MTU)
#define IFCAP_TSO4 0x0
+#define IFCAP_TSO6 0x0
#define CSUM_TSO 0x0
#endif
@@ -777,7 +954,7 @@ cxgb_port_attach(device_t dev)
p = device_get_softc(dev);
snprintf(p->lockbuf, PORT_NAME_LEN, "cxgb port lock %d:%d",
- device_get_unit(device_get_parent(dev)), p->port);
+ device_get_unit(device_get_parent(dev)), p->port_id);
PORT_LOCK_INIT(p, p->lockbuf);
/* Allocate an ifnet object and set it up */
@@ -807,11 +984,21 @@ cxgb_port_attach(device_t dev)
ifp->if_capabilities |= CXGB_CAP;
ifp->if_capenable |= CXGB_CAP_ENABLE;
ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP | CSUM_IP | CSUM_TSO);
-
+ /*
+ * disable TSO on 4-port - it isn't supported by the firmware yet
+ */
+ if (p->adapter->params.nports > 2) {
+ ifp->if_capabilities &= ~(IFCAP_TSO4 | IFCAP_TSO6);
+ ifp->if_capenable &= ~(IFCAP_TSO4 | IFCAP_TSO6);
+ ifp->if_hwassist &= ~CSUM_TSO;
+ }
+
ether_ifattach(ifp, p->hw_addr);
-#ifdef DEFAULT_JUMBO
- ifp->if_mtu = 9000;
-#endif
+ /*
+ * Only default to jumbo frames on 10GigE
+ */
+ if (p->adapter->params.nports <= 2)
+ ifp->if_mtu = 9000;
if ((err = cxgb_makedev(p)) != 0) {
printf("makedev failed %d\n", err);
return (err);
@@ -849,7 +1036,7 @@ cxgb_port_attach(device_t dev)
}
- snprintf(p->taskqbuf, TASKQ_NAME_LEN, "cxgb_port_taskq%d", p->port);
+ snprintf(p->taskqbuf, TASKQ_NAME_LEN, "cxgb_port_taskq%d", p->port_id);
#ifdef TASKQUEUE_CURRENT
/* Create a port for handling TX without starvation */
p->tq = taskqueue_create(p->taskqbuf, M_NOWAIT,
@@ -866,6 +1053,7 @@ cxgb_port_attach(device_t dev)
}
taskqueue_start_threads(&p->tq, 1, PI_NET, "%s taskq",
device_get_nameunit(dev));
+
TASK_INIT(&p->start_task, 0, cxgb_start_proc, ifp);
t3_sge_init_port(p);
@@ -1012,7 +1200,6 @@ t3_os_link_changed(adapter_t *adapter, int port_id, int link_status, int speed,
}
}
-
/*
* Interrupt-context handler for external (PHY) interrupts.
*/
@@ -1089,23 +1276,30 @@ static void
setup_rss(adapter_t *adap)
{
int i;
- u_int nq0 = adap->port[0].nqsets;
- u_int nq1 = max((u_int)adap->port[1].nqsets, 1U);
+ u_int nq[2];
uint8_t cpus[SGE_QSETS + 1];
uint16_t rspq_map[RSS_TABLE_SIZE];
-
+
+ nq[0] = adap->port[0].nqsets;
+ nq[1] = max((u_int)adap->port[1].nqsets, 1U);
+
for (i = 0; i < SGE_QSETS; ++i)
cpus[i] = i;
cpus[SGE_QSETS] = 0xff;
for (i = 0; i < RSS_TABLE_SIZE / 2; ++i) {
- rspq_map[i] = i % nq0;
- rspq_map[i + RSS_TABLE_SIZE / 2] = (i % nq1) + nq0;
+ rspq_map[i] = nq[0] ? i % nq[0] : 0;
+ rspq_map[i + RSS_TABLE_SIZE / 2] = nq[1] ? i % nq[1] + nq[0] : 0;
}
+ /* Calculate the reverse RSS map table */
+ for (i = 0; i < RSS_TABLE_SIZE; ++i)
+ if (adap->rrss_map[rspq_map[i]] == 0xff)
+ adap->rrss_map[rspq_map[i]] = i;
t3_config_rss(adap, F_RQFEEDBACKENABLE | F_TNLLKPEN | F_TNLMAPEN |
- F_TNLPRTEN | F_TNL2TUPEN | F_TNL4TUPEN |
- V_RRCPLCPUSIZE(6), cpus, rspq_map);
+ F_TNLPRTEN | F_TNL2TUPEN | F_TNL4TUPEN | F_OFDMAPEN |
+ F_RRCPLMAPEN | V_RRCPLCPUSIZE(6), cpus, rspq_map);
+
}
/*
@@ -1175,7 +1369,7 @@ send_pktsched_cmd(struct adapter *adap, int sched, int qidx, int lo,
struct mbuf *m;
struct mngt_pktsched_wr *req;
- m = m_gethdr(M_NOWAIT, MT_DATA);
+ m = m_gethdr(M_DONTWAIT, MT_DATA);
if (m) {
req = mtod(m, struct mngt_pktsched_wr *);
req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_MNGT));
@@ -1204,6 +1398,101 @@ bind_qsets(adapter_t *sc)
}
}
+static void
+update_tpeeprom(struct adapter *adap)
+{
+ const struct firmware *tpeeprom;
+ char buf[64];
+ uint32_t version;
+ unsigned int major, minor;
+ int ret, len;
+ char rev;
+
+ t3_seeprom_read(adap, TP_SRAM_OFFSET, &version);
+
+ major = G_TP_VERSION_MAJOR(version);
+ minor = G_TP_VERSION_MINOR(version);
+ if (major == TP_VERSION_MAJOR && minor == TP_VERSION_MINOR)
+ return;
+
+ rev = t3rev2char(adap);
+
+ snprintf(buf, sizeof(buf), TPEEPROM_NAME, rev,
+ TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO);
+
+ tpeeprom = firmware_get(buf);
+ if (tpeeprom == NULL) {
+ device_printf(adap->dev, "could not load TP EEPROM: unable to load %s\n",
+ buf);
+ return;
+ }
+
+ len = tpeeprom->datasize - 4;
+
+ ret = t3_check_tpsram(adap, tpeeprom->data, tpeeprom->datasize);
+ if (ret)
+ goto release_tpeeprom;
+
+ if (len != TP_SRAM_LEN) {
+ device_printf(adap->dev, "%s length is wrong len=%d expected=%d\n", buf, len, TP_SRAM_LEN);
+ return;
+ }
+
+ ret = set_eeprom(&adap->port[0], tpeeprom->data, tpeeprom->datasize,
+ TP_SRAM_OFFSET);
+
+ if (!ret) {
+ device_printf(adap->dev,
+ "Protocol SRAM image updated in EEPROM to %d.%d.%d\n",
+ TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO);
+ } else
+ device_printf(adap->dev, "Protocol SRAM image update in EEPROM failed\n");
+
+release_tpeeprom:
+ firmware_put(tpeeprom, FIRMWARE_UNLOAD);
+
+ return;
+}
+
+static int
+update_tpsram(struct adapter *adap)
+{
+ const struct firmware *tpsram;
+ char buf[64];
+ int ret;
+ char rev;
+
+ rev = t3rev2char(adap);
+ if (!rev)
+ return 0;
+
+ update_tpeeprom(adap);
+
+ snprintf(buf, sizeof(buf), TPSRAM_NAME, rev,
+ TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO);
+
+ tpsram = firmware_get(buf);
+ if (tpsram == NULL){
+ device_printf(adap->dev, "could not load TP SRAM: unable to load %s\n",
+ buf);
+ return (EINVAL);
+ } else
+ device_printf(adap->dev, "updating TP SRAM with %s\n", buf);
+
+ ret = t3_check_tpsram(adap, tpsram->data, tpsram->datasize);
+ if (ret)
+ goto release_tpsram;
+
+ ret = t3_set_proto_sram(adap, tpsram->data);
+ if (ret)
+ device_printf(adap->dev, "loading protocol SRAM failed\n");
+
+release_tpsram:
+ firmware_put(tpsram, FIRMWARE_UNLOAD);
+
+ return ret;
+}
+
/**
* cxgb_up - enable the adapter
* @adap: adapter being enabled
@@ -1221,11 +1510,11 @@ cxgb_up(struct adapter *sc)
if ((sc->flags & FULL_INIT_DONE) == 0) {
if ((sc->flags & FW_UPTODATE) == 0)
- err = upgrade_fw(sc);
-
- if (err)
- goto out;
-
+ if ((err = upgrade_fw(sc)))
+ goto out;
+ if ((sc->flags & TPS_UPTODATE) == 0)
+ if ((err = update_tpsram(sc)))
+ goto out;
err = t3_init_hw(sc, 0);
if (err)
goto out;
@@ -1236,6 +1525,7 @@ cxgb_up(struct adapter *sc)
if (err)
goto out;
+ alloc_filters(sc);
setup_rss(sc);
sc->flags |= FULL_INIT_DONE;
}
@@ -1252,12 +1542,13 @@ cxgb_up(struct adapter *sc)
}
device_printf(sc->dev, "allocated irq_res=%p\n", sc->irq_res);
- if ((err = bus_setup_intr(sc->dev, sc->irq_res, INTR_MPSAFE|INTR_TYPE_NET,
+ if (bus_setup_intr(sc->dev, sc->irq_res, INTR_MPSAFE|INTR_TYPE_NET,
#ifdef INTR_FILTERS
NULL,
#endif
- sc->cxgb_intr, sc, &sc->intr_tag))) {
- device_printf(sc->dev, "Cannot set up interrupt %d\n", err);
+ sc->cxgb_intr, sc, &sc->intr_tag)) {
+ device_printf(sc->dev, "Cannot set up interrupt\n");
+ err = EINVAL;
goto irq_err;
}
} else {
@@ -1267,9 +1558,11 @@ cxgb_up(struct adapter *sc)
t3_sge_start(sc);
t3_intr_enable(sc);
- if ((sc->flags & (USING_MSIX | QUEUES_BOUND)) == USING_MSIX)
+ if ((sc->flags & (USING_MSIX | QUEUES_BOUND)) == USING_MSIX) {
bind_qsets(sc);
- sc->flags |= QUEUES_BOUND;
+ setup_hw_filters(sc);
+ sc->flags |= QUEUES_BOUND;
+ }
out:
return (err);
irq_err:
@@ -1333,7 +1626,7 @@ offload_open(struct port_info *pi)
if (!adap_up)
err = cxgb_up(adapter);
ADAPTER_UNLOCK(pi->adapter);
- if (err < 0)
+ if (err)
return (err);
t3_tp_set_offload_mode(adapter, 1);
@@ -1361,7 +1654,6 @@ out:
}
return (err);
}
-
#ifdef notyet
static int
offload_close(struct toedev *tdev)
@@ -1407,7 +1699,7 @@ cxgb_init_locked(struct port_info *p)
ifp = p->ifp;
ADAPTER_LOCK(p->adapter);
- if ((sc->open_device_map == 0) && ((err = cxgb_up(sc)) < 0)) {
+ if ((sc->open_device_map == 0) && (err = cxgb_up(sc))) {
ADAPTER_UNLOCK(p->adapter);
cxgb_stop_locked(p);
return;
@@ -1416,7 +1708,7 @@ cxgb_init_locked(struct port_info *p)
t3_intr_clear(sc);
t3_sge_init_adapter(sc);
}
- setbit(&p->adapter->open_device_map, p->port);
+ setbit(&p->adapter->open_device_map, p->port_id);
ADAPTER_UNLOCK(p->adapter);
if (is_offload(sc) && !ofld_disable) {
@@ -1426,18 +1718,16 @@ cxgb_init_locked(struct port_info *p)
"Could not initialize offload capabilities\n");
}
cxgb_link_start(p);
- t3_link_changed(sc, p->port);
+ t3_link_changed(sc, p->port_id);
ifp->if_baudrate = p->link_config.speed * 1000000;
- t3_port_intr_enable(sc, p->port);
+ t3_port_intr_enable(sc, p->port_id);
callout_reset(&sc->cxgb_tick_ch, sc->params.stats_update_period * hz,
cxgb_tick, sc);
- PORT_LOCK(p);
ifp->if_drv_flags |= IFF_DRV_RUNNING;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- PORT_UNLOCK(p);
}
static void
@@ -1462,13 +1752,13 @@ cxgb_stop_locked(struct port_info *p)
ifp = p->ifp;
- t3_port_intr_disable(p->adapter, p->port);
+ t3_port_intr_disable(p->adapter, p->port_id);
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
p->phy.ops->power_down(&p->phy, 1);
t3_mac_disable(&p->mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX);
ADAPTER_LOCK(p->adapter);
- clrbit(&p->adapter->open_device_map, p->port);
+ clrbit(&p->adapter->open_device_map, p->port_id);
if (p->adapter->open_device_map == 0) {
@@ -1615,7 +1905,11 @@ cxgb_start_tx(struct ifnet *ifp, uint32_t txmax)
txq = &qs->txq[TXQ_ETH];
err = 0;
+ if (txq->flags & TXQ_TRANSMITTING)
+ return (EINPROGRESS);
+
mtx_lock(&txq->lock);
+ txq->flags |= TXQ_TRANSMITTING;
in_use_init = txq->in_use;
while ((txq->in_use - in_use_init < txmax) &&
(txq->size > txq->in_use + TX_MAX_DESC)) {
@@ -1637,7 +1931,7 @@ cxgb_start_tx(struct ifnet *ifp, uint32_t txmax)
m0->m_flags &= ~M_PKTHDR;
m0 = m0->m_next;
}
- M_SANITY(m0, 0);
+ m_sanity(m0, 0);
m0 = m;
#endif
if (collapse_mbufs && m->m_pkthdr.len > MCLBYTES &&
@@ -1646,13 +1940,14 @@ cxgb_start_tx(struct ifnet *ifp, uint32_t txmax)
m = m0;
m_collapse(m, TX_MAX_SEGS, &m0);
} else
- break;
+ break;
}
m = m0;
if ((err = t3_encap(p, &m)) != 0)
break;
BPF_MTAP(ifp, m);
}
+ txq->flags &= ~TXQ_TRANSMITTING;
mtx_unlock(&txq->lock);
if (__predict_false(err)) {
@@ -1686,9 +1981,8 @@ cxgb_start_proc(void *arg, int ncount)
txq = &qs->txq[TXQ_ETH];
do {
- if (desc_reclaimable(txq) > TX_CLEAN_MAX_DESC)
- taskqueue_enqueue(pi->adapter->tq,
- &pi->timer_reclaim_task);
+ if (desc_reclaimable(txq) > TX_CLEAN_MAX_DESC >> 2)
+ taskqueue_enqueue(pi->tq, &txq->qreclaim_task);
error = cxgb_start_tx(ifp, TX_START_MAX_DESC);
} while (error == 0);
@@ -1705,9 +1999,9 @@ cxgb_start(struct ifnet *ifp)
qs = &pi->adapter->sge.qs[pi->first_qset];
txq = &qs->txq[TXQ_ETH];
- if (desc_reclaimable(txq) > TX_CLEAN_MAX_DESC)
- taskqueue_enqueue(pi->adapter->tq,
- &pi->timer_reclaim_task);
+ if (desc_reclaimable(txq) > TX_CLEAN_MAX_DESC >> 2)
+ taskqueue_enqueue(pi->tq,
+ &txq->qreclaim_task);
err = cxgb_start_tx(ifp, TX_START_MAX_DESC);
@@ -1829,7 +2123,7 @@ check_t3b2_mac(struct adapter *adapter)
cxgb_set_rxmode(p);
t3_link_start(&p->phy, mac, &p->link_config);
t3_mac_enable(mac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
- t3_port_intr_enable(adapter, p->port);
+ t3_port_intr_enable(adapter, p->port_id);
p->mac.stats.num_resets++;
}
PORT_UNLOCK(p);
@@ -1854,8 +2148,8 @@ cxgb_tick_handler(void *arg, int count)
adapter_t *sc = (adapter_t *)arg;
const struct adapter_params *p = &sc->params;
- if (p->linkpoll_period)
ADAPTER_LOCK(sc);
+ if (p->linkpoll_period)
check_link_status(sc);
/*
@@ -1864,10 +2158,170 @@ cxgb_tick_handler(void *arg, int count)
*/
ADAPTER_UNLOCK(sc);
- if (p->rev == T3_REV_B2)
+ if (p->rev == T3_REV_B2 && p->nports < 4)
check_t3b2_mac(sc);
}
+#if 0
+static void *
+filter_get_idx(struct seq_file *seq, loff_t pos)
+{
+ int i;
+ struct adapter *adap = seq->private;
+ struct filter_info *p = adap->filters;
+
+ if (!p)
+ return NULL;
+
+ for (i = 0; i < adap->params.mc5.nfilters; i++, p++)
+ if (p->valid) {
+ if (!pos)
+ return p;
+ pos--;
+ }
+ return NULL;
+}
+
+static void *filter_get_nxt_idx(struct seq_file *seq, struct filter_info *p)
+{
+ struct adapter *adap = seq->private;
+ struct filter_info *end = &adap->filters[adap->params.mc5.nfilters];
+
+ while (++p < end && !p->valid)
+ ;
+ return p < end ? p : NULL;
+}
+
+static void *filter_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ return *pos ? filter_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
+}
+
+static void *filter_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ v = *pos ? filter_get_nxt_idx(seq, v) : filter_get_idx(seq, 0);
+ if (v)
+ ++*pos;
+ return v;
+}
+
+static void filter_seq_stop(struct seq_file *seq, void *v)
+{
+}
+
+static int filter_seq_show(struct seq_file *seq, void *v)
+{
+ static const char *pkt_type[] = { "any", "tcp", "udp", "frag" };
+
+ if (v == SEQ_START_TOKEN)
+ seq_puts(seq, "index SIP DIP sport "
+ "dport VLAN PRI MAC type Q\n");
+ else {
+ char sip[20], dip[20];
+ struct filter_info *f = v;
+ struct adapter *adap = seq->private;
+
+ sprintf(sip, NIPQUAD_FMT "/%-2u", HIPQUAD(f->sip),
+ f->sip_mask ? 33 - ffs(f->sip_mask) : 0);
+ sprintf(dip, NIPQUAD_FMT, HIPQUAD(f->dip));
+ seq_printf(seq, "%5zu %18s %15s ", f - adap->filters, sip, dip);
+ seq_printf(seq, f->sport ? "%5u " : " * ", f->sport);
+ seq_printf(seq, f->dport ? "%5u " : " * ", f->dport);
+ seq_printf(seq, f->vlan != 0xfff ? "%4u " : " * ", f->vlan);
+ seq_printf(seq, f->vlan_prio == FILTER_NO_VLAN_PRI ?
+ " * " : "%1u/%1u ", f->vlan_prio, f->vlan_prio | 1);
+ if (!f->mac_vld)
+ seq_printf(seq, " * ");
+ else if (f->mac_hit)
+ seq_printf(seq, "%3u ", f->mac_idx);
+ else
+ seq_printf(seq, " -1 ");
+ seq_printf(seq, "%4s ", pkt_type[f->pkt_type]);
+ if (!f->pass)
+ seq_printf(seq, "-\n");
+ else if (f->rss)
+ seq_printf(seq, "*\n");
+ else
+ seq_printf(seq, "%1u\n", f->qset);
+ }
+ return 0;
+}
+
+static struct seq_operations filter_seq_ops = {
+ .start = filter_seq_start,
+ .next = filter_seq_next,
+ .stop = filter_seq_stop,
+ .show = filter_seq_show
+};
+
+static int filter_seq_open(struct inode *inode, struct file *file)
+{
+ int rc = seq_open(file, &filter_seq_ops);
+
+ if (!rc) {
+ struct proc_dir_entry *dp = PDE(inode);
+ struct seq_file *seq = file->private_data;
+
+ seq->private = dp->data;
+ }
+ return rc;
+}
+
+static struct file_operations filter_seq_fops = {
+ .owner = THIS_MODULE,
+ .open = filter_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release
+};
+
+#endif
+
+static int
+set_eeprom(struct port_info *pi, const uint8_t *data, int len, int offset)
+{
+ uint8_t *buf;
+ int err = 0;
+ u32 aligned_offset, aligned_len, *p;
+ struct adapter *adapter = pi->adapter;
+
+
+ aligned_offset = offset & ~3;
+ aligned_len = (len + (offset & 3) + 3) & ~3;
+
+ if (aligned_offset != offset || aligned_len != len) {
+ buf = malloc(aligned_len, M_DEVBUF, M_WAITOK|M_ZERO);
+ if (!buf)
+ return (ENOMEM);
+ err = t3_seeprom_read(adapter, aligned_offset, (u32 *)buf);
+ if (!err && aligned_len > 4)
+ err = t3_seeprom_read(adapter,
+ aligned_offset + aligned_len - 4,
+ (u32 *)&buf[aligned_len - 4]);
+ if (err)
+ goto out;
+ memcpy(buf + (offset & 3), data, len);
+ } else
+ buf = (uint8_t *)(uintptr_t)data;
+
+ err = t3_seeprom_wp(adapter, 0);
+ if (err)
+ goto out;
+
+ for (p = (u32 *)buf; !err && aligned_len; aligned_len -= 4, p++) {
+ err = t3_seeprom_write(adapter, aligned_offset, *p);
+ aligned_offset += 4;
+ }
+
+ if (!err)
+ err = t3_seeprom_wp(adapter, 1);
+out:
+ if (buf != data)
+ free(buf, M_DEVBUF);
+ return err;
+}
+
+
static int
in_range(int val, int lo, int hi)
{
@@ -1921,7 +2375,7 @@ cxgb_extension_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data,
if (!mmd)
mmd = MDIO_DEV_PCS;
else if (mmd > MDIO_DEV_XGXS)
- return -EINVAL;
+ return (EINVAL);
error = phy->mdio_read(sc, mid->phy_id & 0x1f, mmd,
mid->reg_num, &val);
@@ -2011,7 +2465,7 @@ cxgb_extension_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data,
struct ch_qset_params *t = (struct ch_qset_params *)data;
if (t->qset_idx >= SGE_QSETS)
- return -EINVAL;
+ return (EINVAL);
if (!in_range(t->intr_lat, 0, M_NEWTIMER) ||
!in_range(t->cong_thres, 0, 255) ||
!in_range(t->txq_size[0], MIN_TXQ_ENTRIES,
@@ -2024,13 +2478,13 @@ cxgb_extension_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data,
!in_range(t->fl_size[1], MIN_FL_ENTRIES,
MAX_RX_JUMBO_BUFFERS) ||
!in_range(t->rspq_size, MIN_RSPQ_ENTRIES, MAX_RSPQ_ENTRIES))
- return -EINVAL;
+ return (EINVAL);
if ((sc->flags & FULL_INIT_DONE) &&
(t->rspq_size >= 0 || t->fl_size[0] >= 0 ||
t->fl_size[1] >= 0 || t->txq_size[0] >= 0 ||
t->txq_size[1] >= 0 || t->txq_size[2] >= 0 ||
t->polling >= 0 || t->cong_thres >= 0))
- return -EBUSY;
+ return (EBUSY);
q = &sc->params.sge.qset[t->qset_idx];
@@ -2077,7 +2531,7 @@ cxgb_extension_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data,
}
case CHELSIO_SET_QSET_NUM: {
struct ch_reg *edata = (struct ch_reg *)data;
- unsigned int port_idx = pi->port;
+ unsigned int port_idx = pi->port_id;
if (sc->flags & FULL_INIT_DONE)
return (EBUSY);
@@ -2139,6 +2593,79 @@ cxgb_extension_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data,
memcpy(m->mtus, sc->params.mtus, sizeof(m->mtus));
m->nmtus = NMTUS;
break;
+ }
+ case CHELSIO_SET_FILTER: {
+ struct ch_filter *f = (struct ch_filter *)data;
+ struct filter_info *p;
+ int ret;
+
+ if (sc->params.mc5.nfilters == 0)
+ return (EOPNOTSUPP);
+ if (!(sc->flags & FULL_INIT_DONE))
+ return (EAGAIN); /* can still change nfilters */
+ if (sc->filters == NULL)
+ return (ENOMEM);
+
+ if (f->filter_id >= sc->params.mc5.nfilters ||
+ (f->val.dip && f->mask.dip != 0xffffffff) ||
+ (f->val.sport && f->mask.sport != 0xffff) ||
+ (f->val.dport && f->mask.dport != 0xffff) ||
+ (f->mask.vlan && f->mask.vlan != 0xfff) ||
+ (f->mask.vlan_prio && f->mask.vlan_prio != 7) ||
+ (f->mac_addr_idx != 0xffff && f->mac_addr_idx > 15) ||
+ f->qset >= SGE_QSETS ||
+ sc->rrss_map[f->qset] >= RSS_TABLE_SIZE)
+ return (EINVAL);
+
+ p = &sc->filters[f->filter_id];
+ if (p->locked)
+ return (EPERM);
+
+ p->sip = f->val.sip;
+ p->sip_mask = f->mask.sip;
+ p->dip = f->val.dip;
+ p->sport = f->val.sport;
+ p->dport = f->val.dport;
+ p->vlan = f->mask.vlan ? f->val.vlan : 0xfff;
+ p->vlan_prio = f->mask.vlan_prio ? (f->val.vlan_prio & 6) :
+ FILTER_NO_VLAN_PRI;
+ p->mac_hit = f->mac_hit;
+ p->mac_vld = f->mac_addr_idx != 0xffff;
+ p->mac_idx = f->mac_addr_idx;
+ p->pkt_type = f->proto;
+ p->report_filter_id = f->want_filter_id;
+ p->pass = f->pass;
+ p->rss = f->rss;
+ p->qset = f->qset;
+
+ ret = set_filter(sc, f->filter_id, p);
+ if (ret)
+ return ret;
+ p->valid = 1;
+ break;
+ }
+ case CHELSIO_DEL_FILTER: {
+ struct ch_filter *f = (struct ch_filter *)data;
+ struct filter_info *p;
+
+ if (sc->params.mc5.nfilters == 0)
+ return (EOPNOTSUPP);
+ if (!(sc->flags & FULL_INIT_DONE))
+ return (EAGAIN); /* can still change nfilters */
+ if (sc->filters == NULL)
+ return (ENOMEM);
+ if (f->filter_id >= sc->params.mc5.nfilters)
+ return (EINVAL);
+
+ p = &sc->filters[f->filter_id];
+ if (p->locked)
+ return (EPERM);
+ memset(p, 0, sizeof(*p));
+ p->sip_mask = 0xffffffff;
+ p->vlan = 0xfff;
+ p->vlan_prio = FILTER_NO_VLAN_PRI;
+ p->pkt_type = 1;
+ return set_filter(sc, f->filter_id, p);
}
case CHELSIO_DEVUP:
if (!is_offload(sc))
@@ -2197,6 +2724,8 @@ cxgb_extension_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data,
if (!is_offload(sc))
return (EOPNOTSUPP);
+ if (!(sc->flags & FULL_INIT_DONE))
+ return (EIO); /* need MC5 */
return -t3_read_mc5_range(&sc->mc5, t->addr, 1, t->buf);
break;
}
@@ -2264,7 +2793,7 @@ cxgb_extension_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data,
t3_set_sched_ipg(sc, t->sched, t->class_ipg);
if (t->flow_ipg >= 0) {
t->flow_ipg *= 1000; /* us -> ns */
- t3_set_pace_tbl(sc, (uint32_t *)&t->flow_ipg, t->sched, 1);
+ t3_set_pace_tbl(sc, &t->flow_ipg, t->sched, 1);
}
if (t->mode >= 0) {
int bit = 1 << (S_TX_MOD_TIMER_MODE + t->sched);
diff --git a/sys/dev/cxgb/cxgb_offload.c b/sys/dev/cxgb/cxgb_offload.c
index 0559c134089e..991fb7e96a65 100644
--- a/sys/dev/cxgb/cxgb_offload.c
+++ b/sys/dev/cxgb/cxgb_offload.c
@@ -1,3 +1,4 @@
+
/**************************************************************************
Copyright (c) 2007, Chelsio Inc.
@@ -271,7 +272,7 @@ cxgb_ulp_iscsi_ctl(adapter_t *adapter, unsigned int req, void *data)
t3_write_reg(adapter, A_ULPRX_ISCSI_TAGMASK, uiip->tagmask);
break;
default:
- ret = -EOPNOTSUPP;
+ ret = (EOPNOTSUPP);
}
return ret;
}
@@ -314,7 +315,7 @@ cxgb_rdma_ctl(adapter_t *adapter, unsigned int req, void *data)
struct mc7 *mem;
if ((t->addr & 7) || (t->len & 7))
- return -EINVAL;
+ return (EINVAL);
if (t->mem_id == MEM_CM)
mem = &adapter->cm;
else if (t->mem_id == MEM_PMRX)
@@ -322,11 +323,11 @@ cxgb_rdma_ctl(adapter_t *adapter, unsigned int req, void *data)
else if (t->mem_id == MEM_PMTX)
mem = &adapter->pmtx;
else
- return -EINVAL;
+ return (EINVAL);
ret = t3_mc7_bd_read(mem, t->addr/8, t->len/8, (u64 *)t->buf);
if (ret)
- return ret;
+ return (ret);
break;
}
case RDMA_CQ_SETUP: {
@@ -357,9 +358,9 @@ cxgb_rdma_ctl(adapter_t *adapter, unsigned int req, void *data)
break;
}
default:
- ret = -EOPNOTSUPP;
+ ret = EOPNOTSUPP;
}
- return ret;
+ return (ret);
}
static int
@@ -438,7 +439,7 @@ cxgb_offload_ctl(struct toedev *tdev, unsigned int req, void *data)
case ULP_ISCSI_GET_PARAMS:
case ULP_ISCSI_SET_PARAMS:
if (!offload_running(adapter))
- return -EAGAIN;
+ return (EAGAIN);
return cxgb_ulp_iscsi_ctl(adapter, req, data);
case RDMA_GET_PARAMS:
case RDMA_CQ_OP:
@@ -447,10 +448,10 @@ cxgb_offload_ctl(struct toedev *tdev, unsigned int req, void *data)
case RDMA_CTRL_QP_SETUP:
case RDMA_GET_MEM:
if (!offload_running(adapter))
- return -EAGAIN;
+ return (EAGAIN);
return cxgb_rdma_ctl(adapter, req, data);
default:
- return -EOPNOTSUPP;
+ return (EOPNOTSUPP);
}
return 0;
}
@@ -463,8 +464,8 @@ cxgb_offload_ctl(struct toedev *tdev, unsigned int req, void *data)
static int
rx_offload_blackhole(struct toedev *dev, struct mbuf **m, int n)
{
- CH_ERR(tdev2adap(dev), "%d unexpected offload packets, first data %u\n",
- n, ntohl(*mtod(m[0], uint32_t *)));
+ CH_ERR(tdev2adap(dev), "%d unexpected offload packets, first data 0x%x\n",
+ n, *mtod(m[0], uint32_t *));
while (n--)
m_freem(m[n]);
return 0;
@@ -525,7 +526,7 @@ cxgb_insert_tid(struct toedev *tdev, struct cxgb_client *client,
t->tid_tab[tid].client = client;
t->tid_tab[tid].ctx = ctx;
- atomic_add_int((volatile unsigned int *)&t->tids_in_use, 1);
+ atomic_add_int(&t->tids_in_use, 1);
}
/*
@@ -595,7 +596,7 @@ cxgb_remove_tid(struct toedev *tdev, void *ctx, unsigned int tid)
BUG_ON(tid >= t->ntids);
if (tdev->type == T3A)
- atomic_cmpset_ptr((void *)&t->tid_tab[tid].ctx, (long)NULL, (long)ctx);
+ atomic_cmpset_ptr((uintptr_t *)&t->tid_tab[tid].ctx, (long)NULL, (long)ctx);
else {
struct mbuf *m;
@@ -607,7 +608,7 @@ cxgb_remove_tid(struct toedev *tdev, void *ctx, unsigned int tid)
} else
cxgb_queue_tid_release(tdev, tid);
}
- atomic_add_int((volatile unsigned int *)&t->tids_in_use, -1);
+ atomic_add_int(&t->tids_in_use, -1);
}
int
@@ -1249,7 +1250,7 @@ cxgb_redirect(struct rtentry *old, struct rtentry *new)
}
/* Add new L2T entry */
- e = t3_l2t_get(tdev, new, ((struct port_info *)new->rt_ifp->if_softc)->port);
+ e = t3_l2t_get(tdev, new, ((struct port_info *)new->rt_ifp->if_softc)->port_id);
if (!e) {
log(LOG_ERR, "%s: couldn't allocate new l2t entry!\n",
__FUNCTION__);
@@ -1307,7 +1308,7 @@ init_tid_tabs(struct tid_info *t, unsigned int ntids,
t->tid_tab = cxgb_alloc_mem(size);
if (!t->tid_tab)
- return -ENOMEM;
+ return (ENOMEM);
t->stid_tab = (union listen_entry *)&t->tid_tab[ntids];
t->atid_tab = (union active_open_entry *)&t->stid_tab[nstids];
@@ -1319,7 +1320,7 @@ init_tid_tabs(struct tid_info *t, unsigned int ntids,
t->atid_base = atid_base;
t->afree = NULL;
t->stids_in_use = t->atids_in_use = 0;
- atomic_set_int((volatile unsigned int *)&t->tids_in_use, 0);
+ atomic_set_int(&t->tids_in_use, 0);
mtx_init(&t->stid_lock, "stid", NULL, MTX_DEF);
mtx_init(&t->atid_lock, "atid", NULL, MTX_DEF);
@@ -1597,11 +1598,11 @@ offload_info_proc_setup(struct proc_dir_entry *dir,
struct proc_dir_entry *p;
if (!dir)
- return -EINVAL;
+ return (EINVAL);
p = create_proc_read_entry("info", 0, dir, offload_info_read_proc, d);
if (!p)
- return -ENOMEM;
+ return (ENOMEM);
p->owner = THIS_MODULE;
return 0;
diff --git a/sys/dev/cxgb/cxgb_offload.h b/sys/dev/cxgb/cxgb_offload.h
index 10b4aab11b16..62ecfa8183ce 100644
--- a/sys/dev/cxgb/cxgb_offload.h
+++ b/sys/dev/cxgb/cxgb_offload.h
@@ -10,11 +10,7 @@ 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. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Chelsio Corporation nor the names of its
+ 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.
@@ -37,11 +33,12 @@ $FreeBSD$
#ifndef _CXGB_OFFLOAD_H
#define _CXGB_OFFLOAD_H
-#ifdef CONFIG_DEFINED
-#include <cxgb_include.h>
-#else
-#include <dev/cxgb/cxgb_include.h>
-#endif
+
+#include <dev/cxgb/common/cxgb_tcb.h>
+#include <dev/cxgb/cxgb_l2t.h>
+
+#include <dev/cxgb/ulp/toecore/toedev.h>
+#include <dev/cxgb/common/cxgb_t3_cpl.h>
struct adapter;
struct cxgb_client;
@@ -152,7 +149,7 @@ union active_open_entry {
struct tid_info {
struct toe_tid_entry *tid_tab;
unsigned int ntids;
- volatile int tids_in_use;
+ volatile unsigned int tids_in_use;
union listen_entry *stid_tab;
unsigned int nstids;
diff --git a/sys/dev/cxgb/cxgb_osdep.h b/sys/dev/cxgb/cxgb_osdep.h
index d5ebf960d830..ccef5c5c5456 100644
--- a/sys/dev/cxgb/cxgb_osdep.h
+++ b/sys/dev/cxgb/cxgb_osdep.h
@@ -165,8 +165,12 @@ static const int debug_flags = DBG_RX;
#define max_t(type, a, b) (type)max((a), (b))
#define net_device ifnet
+#define cpu_to_be32 htobe32
+#ifndef if_name
+#define if_name(ifp) (ifp)->if_xname
+#endif
/* Standard PHY definitions */
#define BMCR_LOOPBACK BMCR_LOOP
diff --git a/sys/dev/cxgb/cxgb_sge.c b/sys/dev/cxgb/cxgb_sge.c
index b84147e58900..de4a3bedf823 100644
--- a/sys/dev/cxgb/cxgb_sge.c
+++ b/sys/dev/cxgb/cxgb_sge.c
@@ -66,9 +66,10 @@ __FBSDID("$FreeBSD$");
uint32_t collapse_free = 0;
uint32_t mb_free_vec_free = 0;
+int txq_fills = 0;
int collapse_mbufs = 0;
static int recycle_enable = 1;
-
+static int bogus_imm = 0;
/*
* XXX GC
@@ -186,7 +187,8 @@ int cxgb_debug = 0;
static void t3_free_qset(adapter_t *sc, struct sge_qset *q);
static void sge_timer_cb(void *arg);
static void sge_timer_reclaim(void *arg, int ncount);
-static int free_tx_desc(adapter_t *sc, struct sge_txq *q, int n, struct mbuf **m_vec);
+static void sge_txq_reclaim_handler(void *arg, int ncount);
+static int free_tx_desc(struct sge_txq *q, int n, struct mbuf **m_vec);
/**
* reclaim_completed_tx - reclaims completed Tx descriptors
@@ -198,14 +200,14 @@ static int free_tx_desc(adapter_t *sc, struct sge_txq *q, int n, struct mbuf **m
* queue's lock held.
*/
static __inline int
-reclaim_completed_tx(adapter_t *adapter, struct sge_txq *q, int nbufs, struct mbuf **mvec)
+reclaim_completed_tx(struct sge_txq *q, int nbufs, struct mbuf **mvec)
{
int reclaimed, reclaim = desc_reclaimable(q);
int n = 0;
mtx_assert(&q->lock, MA_OWNED);
if (reclaim > 0) {
- n = free_tx_desc(adapter, q, min(reclaim, nbufs), mvec);
+ n = free_tx_desc(q, min(reclaim, nbufs), mvec);
reclaimed = min(reclaim, nbufs);
q->cleaned += reclaimed;
q->in_use -= reclaimed;
@@ -290,20 +292,23 @@ sgl_len(unsigned int n)
*
* Return a packet containing the immediate data of the given response.
*/
-static __inline void
-get_imm_packet(adapter_t *sc, const struct rsp_desc *resp, struct mbuf *m, void *cl)
+static int
+get_imm_packet(adapter_t *sc, const struct rsp_desc *resp, struct mbuf *m, void *cl, uint32_t flags)
{
- int len;
- uint32_t flags = ntohl(resp->flags);
+ int len, error;
uint8_t sopeop = G_RSPD_SOP_EOP(flags);
-
+
/*
* would be a firmware bug
*/
- if (sopeop == RSPQ_NSOP_NEOP || sopeop == RSPQ_SOP)
- return;
-
len = G_RSPD_LEN(ntohl(resp->len_cq));
+ if (sopeop == RSPQ_NSOP_NEOP || sopeop == RSPQ_SOP) {
+ if (cxgb_debug)
+ device_printf(sc->dev, "unexpected value sopeop=%d flags=0x%x len=%din get_imm_packet\n", sopeop, flags, len);
+ bogus_imm++;
+ return (EINVAL);
+ }
+ error = 0;
switch (sopeop) {
case RSPQ_SOP_EOP:
m->m_len = m->m_pkthdr.len = len;
@@ -313,7 +318,12 @@ get_imm_packet(adapter_t *sc, const struct rsp_desc *resp, struct mbuf *m, void
memcpy(cl, resp->imm_data, len);
m_iovappend(m, cl, MSIZE, len, 0);
break;
+ default:
+ bogus_imm++;
+ error = EINVAL;
}
+
+ return (error);
}
@@ -360,8 +370,11 @@ t3_sge_prep(adapter_t *adap, struct sge_params *p)
q->polling = adap->params.rev > 0;
- q->coalesce_nsecs = 5000;
-
+ if (adap->params.nports > 2)
+ q->coalesce_nsecs = 50000;
+ else
+ q->coalesce_nsecs = 5000;
+
q->rspq_size = RSPQ_Q_SIZE;
q->fl_size = FL_Q_SIZE;
q->jumbo_size = JUMBO_Q_SIZE;
@@ -662,6 +675,35 @@ sge_slow_intr_handler(void *arg, int ncount)
t3_slow_intr_handler(sc);
}
+/**
+ * sge_timer_cb - perform periodic maintenance of an SGE qset
+ * @data: the SGE queue set to maintain
+ *
+ * Runs periodically from a timer to perform maintenance of an SGE queue
+ * set. It performs two tasks:
+ *
+ * a) Cleans up any completed Tx descriptors that may still be pending.
+ * Normal descriptor cleanup happens when new packets are added to a Tx
+ * queue so this timer is relatively infrequent and does any cleanup only
+ * if the Tx queue has not seen any new packets in a while. We make a
+ * best effort attempt to reclaim descriptors, in that we don't wait
+ * around if we cannot get a queue's lock (which most likely is because
+ * someone else is queueing new packets and so will also handle the clean
+ * up). Since control queues use immediate data exclusively we don't
+ * bother cleaning them up here.
+ *
+ * b) Replenishes Rx queues that have run out due to memory shortage.
+ * Normally new Rx buffers are added when existing ones are consumed but
+ * when out of memory a queue can become empty. We try to add only a few
+ * buffers here, the queue will be replenished fully as these new buffers
+ * are used up if memory shortage has subsided.
+ *
+ * c) Return coalesced response queue credits in case a response queue is
+ * starved.
+ *
+ * d) Ring doorbells for T304 tunnel queues since we have seen doorbell
+ * fifo overflows and the FW doesn't implement any recovery scheme yet.
+ */
static void
sge_timer_cb(void *arg)
{
@@ -686,6 +728,17 @@ sge_timer_cb(void *arg)
break;
}
}
+ if (sc->params.nports > 2) {
+ int i;
+
+ for_each_port(sc, i) {
+ struct port_info *pi = &sc->port[i];
+
+ t3_write_reg(sc, A_SG_KDOORBELL,
+ F_SELEGRCNTX |
+ (FW_TUNNEL_SGEEC_START + pi->first_qset));
+ }
+ }
if (sc->open_device_map != 0)
callout_reset(&sc->sge_timer_ch, TX_RECLAIM_PERIOD, sge_timer_cb, sc);
}
@@ -708,7 +761,6 @@ int
t3_sge_init_port(struct port_info *p)
{
TASK_INIT(&p->timer_reclaim_task, 0, sge_timer_reclaim, p);
-
return (0);
}
@@ -743,6 +795,45 @@ refill_rspq(adapter_t *sc, const struct sge_rspq *q, u_int credits)
V_RSPQ(q->cntxt_id) | V_CREDITS(credits));
}
+static __inline void
+sge_txq_reclaim_(struct sge_txq *txq)
+{
+ int reclaimable, i, n;
+ struct mbuf *m_vec[TX_CLEAN_MAX_DESC];
+ struct port_info *p;
+
+ p = txq->port;
+reclaim_more:
+ n = 0;
+ reclaimable = desc_reclaimable(txq);
+ if (reclaimable > 0 && mtx_trylock(&txq->lock)) {
+ n = reclaim_completed_tx(txq, TX_CLEAN_MAX_DESC, m_vec);
+ mtx_unlock(&txq->lock);
+ }
+ if (n == 0)
+ return;
+
+ for (i = 0; i < n; i++) {
+ m_freem_vec(m_vec[i]);
+ }
+ if (p && p->ifp->if_drv_flags & IFF_DRV_OACTIVE &&
+ txq->size - txq->in_use >= TX_START_MAX_DESC) {
+ txq_fills++;
+ p->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ taskqueue_enqueue(p->tq, &p->start_task);
+ }
+
+ if (n)
+ goto reclaim_more;
+}
+
+static void
+sge_txq_reclaim_handler(void *arg, int ncount)
+{
+ struct sge_txq *q = arg;
+
+ sge_txq_reclaim_(q);
+}
static void
sge_timer_reclaim(void *arg, int ncount)
@@ -753,39 +844,15 @@ sge_timer_reclaim(void *arg, int ncount)
struct sge_qset *qs;
struct sge_txq *txq;
struct mtx *lock;
- struct mbuf *m_vec[TX_CLEAN_MAX_DESC];
- int n, reclaimable;
for (i = 0; i < nqsets; i++) {
qs = &sc->sge.qs[i];
txq = &qs->txq[TXQ_ETH];
- reclaimable = desc_reclaimable(txq);
- if (reclaimable > 0) {
- mtx_lock(&txq->lock);
- n = reclaim_completed_tx(sc, txq, TX_CLEAN_MAX_DESC, m_vec);
- mtx_unlock(&txq->lock);
-
- for (i = 0; i < n; i++)
- m_freem_vec(m_vec[i]);
-
- if (p->ifp->if_drv_flags & IFF_DRV_OACTIVE &&
- txq->size - txq->in_use >= TX_START_MAX_DESC) {
- p->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- taskqueue_enqueue(p->tq, &p->start_task);
- }
- }
+ sge_txq_reclaim_(txq);
txq = &qs->txq[TXQ_OFLD];
- reclaimable = desc_reclaimable(txq);
- if (reclaimable > 0) {
- mtx_lock(&txq->lock);
- n = reclaim_completed_tx(sc, txq, TX_CLEAN_MAX_DESC, m_vec);
- mtx_unlock(&txq->lock);
-
- for (i = 0; i < n; i++)
- m_freem_vec(m_vec[i]);
- }
-
+ sge_txq_reclaim_(txq);
+
lock = (sc->flags & USING_MSIX) ? &qs->rspq.lock :
&sc->sge.qs[0].rspq.lock;
@@ -904,7 +971,7 @@ busdma_map_mbufs(struct mbuf **m, struct sge_txq *txq,
#endif
if (err == EFBIG) {
/* Too many segments, try to defrag */
- m0 = m_defrag(m0, M_NOWAIT);
+ m0 = m_defrag(m0, M_DONTWAIT);
if (m0 == NULL) {
m_freem(*m);
*m = NULL;
@@ -1102,7 +1169,7 @@ t3_encap(struct port_info *p, struct mbuf **m)
struct tx_sw_desc *stx;
struct txq_state txqs;
unsigned int ndesc, flits, cntrl, mlen;
- int nsegs, err, tso_info = 0;
+ int err, nsegs, tso_info = 0;
struct work_request_hdr *wrp;
struct tx_sw_desc *txsd;
@@ -1129,7 +1196,7 @@ t3_encap(struct port_info *p, struct mbuf **m)
* XXX handle checksum, TSO, and VLAN here
*
*/
- cntrl = V_TXPKT_INTF(p->port);
+ cntrl = V_TXPKT_INTF(p->port_id);
/*
* XXX need to add VLAN support for 6.x
@@ -1145,7 +1212,7 @@ t3_encap(struct port_info *p, struct mbuf **m)
struct cpl_tx_pkt_lso *hdr = (struct cpl_tx_pkt_lso *) cpl;
struct ip *ip;
struct tcphdr *tcp;
- uint8_t *pkthdr, tmp[TCPPKTHDRSIZE]; /* is this too large for the stack? */
+ char *pkthdr, tmp[TCPPKTHDRSIZE]; /* is this too large for the stack? */
txd->flit[2] = 0;
cntrl |= V_TXPKT_OPCODE(CPL_TX_PKT_LSO);
@@ -1153,9 +1220,9 @@ t3_encap(struct port_info *p, struct mbuf **m)
if (__predict_false(m0->m_len < TCPPKTHDRSIZE)) {
pkthdr = &tmp[0];
- m_copydata(m0, 0, TCPPKTHDRSIZE, (caddr_t)pkthdr);
+ m_copydata(m0, 0, TCPPKTHDRSIZE, pkthdr);
} else {
- pkthdr = mtod(m0, uint8_t *);
+ pkthdr = mtod(m0, char *);
}
if (__predict_false(m0->m_flags & M_VLANTAG)) {
@@ -1562,8 +1629,8 @@ t3_sge_stop(adapter_t *sc)
for (i = 0; i < nqsets; ++i) {
struct sge_qset *qs = &sc->sge.qs[i];
- taskqueue_drain(sc->tq, &qs->txq[TXQ_OFLD].qresume_tsk);
- taskqueue_drain(sc->tq, &qs->txq[TXQ_CTRL].qresume_tsk);
+ taskqueue_drain(sc->tq, &qs->txq[TXQ_OFLD].qresume_task);
+ taskqueue_drain(sc->tq, &qs->txq[TXQ_CTRL].qresume_task);
}
}
@@ -1578,7 +1645,7 @@ t3_sge_stop(adapter_t *sc)
* Tx buffers. Called with the Tx queue lock held.
*/
int
-free_tx_desc(adapter_t *sc, struct sge_txq *q, int n, struct mbuf **m_vec)
+free_tx_desc(struct sge_txq *q, int n, struct mbuf **m_vec)
{
struct tx_sw_desc *d;
unsigned int cidx = q->cidx;
@@ -1725,9 +1792,9 @@ calc_tx_descs_ofld(struct mbuf *m, unsigned int nsegs)
static int
ofld_xmit(adapter_t *adap, struct sge_txq *q, struct mbuf *m)
{
- int ret;
- unsigned int pidx, gen, ndesc;
- int nsegs;
+ int ret, nsegs;
+ unsigned int ndesc;
+ unsigned int pidx, gen;
struct mbuf *m_vec[TX_CLEAN_MAX_DESC];
bus_dma_segment_t segs[TX_MAX_SEGS];
int i, cleaned;
@@ -1739,7 +1806,7 @@ ofld_xmit(adapter_t *adap, struct sge_txq *q, struct mbuf *m)
return (ret);
}
ndesc = calc_tx_descs_ofld(m, nsegs);
-again: cleaned = reclaim_completed_tx(adap, q, TX_CLEAN_MAX_DESC, m_vec);
+again: cleaned = reclaim_completed_tx(q, TX_CLEAN_MAX_DESC, m_vec);
ret = check_desc_avail(adap, q, m, ndesc, TXQ_OFLD);
if (__predict_false(ret)) {
@@ -1796,7 +1863,7 @@ restart_offloadq(void *data, int npending)
struct tx_sw_desc *stx = &q->sdesc[q->pidx];
mtx_lock(&q->lock);
-again: cleaned = reclaim_completed_tx(adap, q, TX_CLEAN_MAX_DESC, m_vec);
+again: cleaned = reclaim_completed_tx(q, TX_CLEAN_MAX_DESC, m_vec);
while ((m = mbufq_peek(&q->sendq)) != NULL) {
unsigned int gen, pidx;
@@ -1935,13 +2002,13 @@ restart_tx(struct sge_qset *qs)
should_restart_tx(&qs->txq[TXQ_OFLD]) &&
test_and_clear_bit(TXQ_OFLD, &qs->txq_stopped)) {
qs->txq[TXQ_OFLD].restarts++;
- taskqueue_enqueue(sc->tq, &qs->txq[TXQ_OFLD].qresume_tsk);
+ taskqueue_enqueue(sc->tq, &qs->txq[TXQ_OFLD].qresume_task);
}
if (isset(&qs->txq_stopped, TXQ_CTRL) &&
should_restart_tx(&qs->txq[TXQ_CTRL]) &&
test_and_clear_bit(TXQ_CTRL, &qs->txq_stopped)) {
qs->txq[TXQ_CTRL].restarts++;
- taskqueue_enqueue(sc->tq, &qs->txq[TXQ_CTRL].qresume_tsk);
+ taskqueue_enqueue(sc->tq, &qs->txq[TXQ_CTRL].qresume_task);
}
}
@@ -2020,14 +2087,19 @@ t3_sge_alloc_qset(adapter_t *sc, u_int id, int nports, int irq_vec_idx,
MTX_INIT(&q->txq[i].lock, q->txq[i].lockbuf, NULL, MTX_DEF);
}
- TASK_INIT(&q->txq[TXQ_OFLD].qresume_tsk, 0, restart_offloadq, q);
- TASK_INIT(&q->txq[TXQ_CTRL].qresume_tsk, 0, restart_ctrlq, q);
+ q->txq[TXQ_ETH].port = pi;
+ TASK_INIT(&q->txq[TXQ_OFLD].qresume_task, 0, restart_offloadq, q);
+ TASK_INIT(&q->txq[TXQ_CTRL].qresume_task, 0, restart_ctrlq, q);
+ TASK_INIT(&q->txq[TXQ_ETH].qreclaim_task, 0, sge_txq_reclaim_handler, &q->txq[TXQ_ETH]);
+ TASK_INIT(&q->txq[TXQ_OFLD].qreclaim_task, 0, sge_txq_reclaim_handler, &q->txq[TXQ_OFLD]);
+
q->fl[0].gen = q->fl[1].gen = 1;
q->fl[0].size = p->fl_size;
q->fl[1].size = p->jumbo_size;
q->rspq.gen = 1;
+ q->rspq.cidx = 0;
q->rspq.size = p->rspq_size;
q->txq[TXQ_ETH].stop_thres = nports *
@@ -2188,7 +2260,7 @@ get_packet(adapter_t *adap, unsigned int drop_thres, struct sge_qset *qs,
int ret = 0;
prefetch(sd->cl);
-
+
fl->credits--;
bus_dmamap_sync(fl->entry_tag, sd->map, BUS_DMASYNC_POSTREAD);
@@ -2305,7 +2377,7 @@ process_responses(adapter_t *adap, struct sge_qset *qs, int budget)
int ngathered = 0;
#ifdef DEBUG
static int last_holdoff = 0;
- if (rspq->holdoff_tmr != last_holdoff) {
+ if (cxgb_debug && rspq->holdoff_tmr != last_holdoff) {
printf("next_holdoff=%d\n", rspq->holdoff_tmr);
last_holdoff = rspq->holdoff_tmr;
}
@@ -2326,26 +2398,31 @@ process_responses(adapter_t *adap, struct sge_qset *qs, int budget)
} else if (flags & F_RSPD_IMM_DATA_VALID) {
struct mbuf *m = NULL;
+
if (cxgb_debug)
- printf("IMM DATA VALID\n");
+ printf("IMM DATA VALID opcode=0x%x rspq->cidx=%d\n", r->rss_hdr.opcode, rspq->cidx);
if (rspq->m == NULL)
- rspq->m = m_gethdr(M_NOWAIT, MT_DATA);
+ rspq->m = m_gethdr(M_DONTWAIT, MT_DATA);
else
- m = m_gethdr(M_NOWAIT, MT_DATA);
+ m = m_gethdr(M_DONTWAIT, MT_DATA);
- if (rspq->m == NULL || m == NULL) {
+ /*
+ * XXX revisit me
+ */
+ if (rspq->m == NULL && m == NULL) {
rspq->next_holdoff = NOMEM_INTR_DELAY;
budget_left--;
break;
}
- get_imm_packet(adap, r, rspq->m, m);
+ if (get_imm_packet(adap, r, rspq->m, m, flags))
+ goto skip;
eop = 1;
rspq->imm_data++;
} else if (r->len_cq) {
int drop_thresh = eth ? SGE_RX_DROP_THRES : 0;
if (rspq->m == NULL)
- rspq->m = m_gethdr(M_NOWAIT, MT_DATA);
+ rspq->m = m_gethdr(M_DONTWAIT, MT_DATA);
if (rspq->m == NULL) {
log(LOG_WARNING, "failed to get mbuf for packet\n");
break;
@@ -2362,7 +2439,7 @@ process_responses(adapter_t *adap, struct sge_qset *qs, int budget)
sleeping |= flags & RSPD_GTS_MASK;
handle_rsp_cntrl_info(qs, flags);
}
-
+ skip:
r++;
if (__predict_false(++rspq->cidx == rspq->size)) {
rspq->cidx = 0;
@@ -2395,12 +2472,9 @@ process_responses(adapter_t *adap, struct sge_qset *qs, int budget)
ngathered = rx_offload(&adap->tdev, rspq, rspq->m,
offload_mbufs, ngathered);
}
-#ifdef notyet
- taskqueue_enqueue(adap->tq, &adap->timer_reclaim_task);
-#else
__refill_fl(adap, &qs->fl[0]);
__refill_fl(adap, &qs->fl[1]);
-#endif
+
}
--budget_left;
}
@@ -2637,6 +2711,14 @@ t3_add_sysctls(adapter_t *sc)
"collapse_mbufs",
CTLFLAG_RW, &collapse_mbufs,
0, "collapse mbuf chains into iovecs");
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ "txq_overrun",
+ CTLFLAG_RD, &txq_fills,
+ 0, "#times txq overrun");
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ "bogus_imm",
+ CTLFLAG_RD, &bogus_imm,
+ 0, "#times a bogus immediate response was seen");
}
/**
diff --git a/sys/dev/cxgb/sys/mvec.h b/sys/dev/cxgb/sys/mvec.h
index 7e0c082cb44b..ec7817b2f08d 100644
--- a/sys/dev/cxgb/sys/mvec.h
+++ b/sys/dev/cxgb/sys/mvec.h
@@ -129,6 +129,9 @@ m_cljset(struct mbuf *m, void *cl, int type)
m->m_ext.ext_size = size;
m->m_ext.ext_type = type;
m->m_ext.ref_cnt = uma_find_refcnt(zone, cl);
+ if (*m->m_ext.ref_cnt == 0)
+ *m->m_ext.ref_cnt = 1;
+
m->m_flags |= M_EXT;
}
diff --git a/sys/dev/cxgb/t3fw-4.1.0.bin.gz.uu b/sys/dev/cxgb/t3fw-4.1.0.bin.gz.uu
deleted file mode 100644
index e434c1d696f5..000000000000
--- a/sys/dev/cxgb/t3fw-4.1.0.bin.gz.uu
+++ /dev/null
@@ -1,482 +0,0 @@
-/**************************************************************************
-
-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.
-
-$FreeBSD$
-
-***************************************************************************/
-
-begin 644 t3fw-4.1.0.bin.gz
-M'XL("$@Q:T8``W0S9G<M-"XQ+C`N8FEN`.R\"UP3U]HO/)D$DDPFY$+`@!"2
-M$&!RCUAOK;74NFM;[5ML:S>[=K=L$ZRV6FUKJU4KB$##/2!B`@206B]X`VJM
-M5ML.:!&5MBBM52'<5-2J>*F]*_,]:P)J^^Z]?^_Y?N=WOO.=\T;7S)HUZ_*L
-MM9[+_UEK#<D8#SN#85(YPQ!J#,.2L<>P7@S/P/@8NCLQ#H;U8&RHAB@V9<J4
-M!/1\!N.$W(WS$M2<GCOY<+BKL:1R&L/.CL*^'X5=&855C\+6C\)PC-;@_:,X
-M.-:DCB:P!520>9S-/.X^\[CQYG$3HQ_D0(Y&-6V#%]9QF'6<U#I.;1UG\[_0
-M$E)_F;AQ6-PX:=PX=1S[BHMC<J8]F&DG<6R-6LX<OR=*CUJC3H=(6S!S#"6T
-MA3#'0IECM.T[=<`<3C*FX(T-@*HY,AS^OS5*P9^J"!A-\GF/O#WJ++QZ:\(5
-M#-7>',(TTS8\#D_&`NYDX4V"]]?8UNDCZM7J#$VF=O'HP-:'6O^>C,FR$G?-
-M++5%3^0M'OV#UD3:&9^<^3B:2%LP@0]-K5%K30ELU1_2\5Q+`%M+?3!3OT8M
-M8^H)*?;?O__^_:_X@9R>_+<93HR2,C\3__)UU"U_.(,%;OB7<8;&4/CG\:9.
-M?[RITQ\7IL&])XHYT@KQ##5+(R?M#"9;BNX0,LY@\E_4(#P0(B!^"]TAJ,]@
-MP4ITAS`1XBAM(H0$B(]'=PC3(8[2ID-(A/ACZ`[A!8BCM!<@)$,\"=TAS(<X
-M2IL/81'$YZ([A#R(H[2\H;@3[BX(VX;BVX;B&^#>IL:X=?XXM\X?5V3\[QE/
-MMOKCR59__'7>_U?Q/_+HB[HHYFL:3)4:^*(-XDO]]#Y;`?EU/6!S4($HYN!9
-M-?;,94AO56,O[8*\W_AYJ>D:Q-']8-2M00R3,`RR40$0$B"D85A8%\-@7=L_
-MN_HP/(]!C=)@%"&+#;U/QK!%+!W`G"S3_X+*J"!P,`&&_F-B"$I_'K8@"15'
-M0.`EL(\8"8'+ML7#`ME>V;!N#%$A()G/&8;IAM##9U!MOV!\!H2`095!W_A<
-M>,6@Q&M\AAGD,JGP>`#"<+$HYL"U:G\_HI+9N@5IB=`<RL%VEKD&::$P;DW0
-M*^;G#_QCE0'!Y>^!2*VV,FG,(+0"N3',A$%Y'%$>Q;0H4:]02U#V*@>3H;+K
-M(10QS%64]GL4\]DUAOD9Q6_#.)_$.+]#6T=`G@]U]F)(=\1)>Z'7:IL?2\`<
-MV"`L@CK60)Z3$&!^6GB]0$HO:I;;YC(FVM.,B>]`<$'8F`;M2A`645L'43UI
-M0"_4!+1RF%^,B?5I\$X*=\R8V`#A4PKN4.[3:DB7&1,_@;3]:;TP]KT`;'J@
-MC5YV]M.@+X>`1P[U1-W&!'"_"70(?/"#>P30[()P&;)J:';,6DQJ[+EO(%R&
-M_H%.>>XF!-`KSR5',8=-D&8#WDR&9C20!GJ)NQ_*[&%^9ZZIL1>^4&-_CX'0
-M#OP<#'GWJS'>LRP[,4=:[N5WSI]TK%J*)=P)"N@[,-.=,)PV')08K8[@8'>"
-MFI/`I@T'E/;G9Y3G;DC^0]!QJM78])X_AFDG[PG*H2!58T_`_?'[U-A4T,%_
-MZ;PKO]-!5J>O&+I#F/;/@L!_GPIZ]]%.*.^Z6YYW4(W90-_R=JFQA^$=#\9N
-M`NA3'NC9AR!=W:+&QKK5V'V@FZT@_Y;%:LQ@4V,Z:#-^LQJ+A.=PT`W!"C4F
-MWZ/&I-"6%.H5@ST1@0U`=N8O<_TA@%1C?-!%DR!]#.3CM2(:XAU^6M#=\:=_
-M_S-^(`L]_GMS*_`AZ+M#*_ZG5/S?O__^_6_X`WZ_X+>,_^SW3](?B4[[K]3K
-MU\E_K1[2S3?_F/Y_16#MT=`=0A+HPQ<==Y__SP[#\XT@$[+30_&'X)9VS_/G
-M<$NXYQF!"?6?GJ5_>A;\Z9GWIV?\3\\<A`6&XL-I=W\OE'#^7H*_6,)]J01[
-MY+_"V7_ZO>#B_-V%O^CBON3"GOE_4;ZB!(MT<;PE>&4)MZJ$)R@)$)8$$B5\
-MT7^1G`HH[,(K7?Q(%[?*Q5OJ"GC'%;C,Q5_^7R2GDVW?5X)WE7"[2WB\DH"`
-MDL#`$CZ_1"`H$0I+"*)$].]HZ83"+KS+)8+VNUV\7:Z`CUR!NUW\CUV"/2[A
-M7A?QB4NT[U_3`C+Q-TW$R0IY!--%T/_Y/<)SF@A7L6)-2#!S&[]@*PGE1A.K
-M;6M'$#9_^9E2[#CXQH/$4'TSD[#V/SR[L6_^\'P3^_;N\__(+T"!V9E?_X>+
-M_?_F-U\:P)'A2:'EQR1H)8[&:`V&C\(?'X4]AI8*:4QVE0R^*N:R"X?*JZ*1
-M5TG:)?B$?'>30)^%47D\P[9;*S81GC1]%H?*$QBV_4(\H5BP1>1)\ZSRI.NS
-MN%2>5'$5XR=@B@$F=("!B'R`"1Y@UJCI9'J1<F!0,3!(I?LSW(8K2Q.N&/@=
-MQ7GLX,^7\FB;?.#G=/6;&CP9>X!."![X<;5MM6WQJ+C0@1]"!FYD)NZ:N399
-M,7`M(T'W)*.;_)`H`:,7A0Y<CIV-P?\E\[Y3#ER@7X_+PJ";J#YT8^M50^R>
-MYS_?Z6H]P3-J590V4J\+-,3@R[-Q8BM^>%_PP(EVB:F.;ZG#Z&/<`<+2-^6T
-M6M2#=52G[#S/UHK*"PP:/);`WMHD==ZGCP](?4^06A40^`H.%1&B:2V?MO[U
-MM+K#UIF0)/X.E1DY<,#24$F?7-F.)W/*S`W>[C;',7><FJ3I=5)RB6SK2GU?
-M%D40[ZR&]V9]7Z9J8(^C2$?%<P1.19"3LW"5CNZEVRD-K_('@5,F=N*1`_7N
-MZ]YK)(Y1#5[S+265IZ1V>]^[CSZ;NN0^Y<#6PC&=/:J!VHJB2E>!NK1$,(!7
-M%M-]RH&-E6O=:R2"!(E31I7R4W\66)_`)#MQ:PR^<DD`-4I,Q6C?71)@&"4Q
-MQ&A6+!EOF*BV$AR*P,2_C!<()CO25BD'UD4-K+-F3<*JG5A;WKU7(,;0X#5L
-M4QIV>W-L2S9-L&IX^:,+XND,X2'1KE;WZ\J!'!XC<R]R&BO?]BZ)''BO]"WH
-MBOL-PIT0Z)0)&)PB(N!J?9MWF#:H2;)6)JH5Z&LRA8=%^HV9*8EOT&IP\X$:
-M@J4FI?!U.[,D8N!5Y<`K]/I\J46KVK8"B-`WI&/'>%AM.+4*%V[!];O3(5%P
-M=E0A77DMG\YNVN7STN]Z`BQ-'$LS9M7@_O[;!Q]OEY@)S#[X#R,1B!OPI*`-
-M]L$Q!M/BCH2DH#7'JX])YDN)$[9HT^(UP<$#3R5CKX0/3#N8IAIX`O@(6K#&
-MIUMZ<43_6-1@T-E1^=O+V[*W.W?N\N@WBM_)YA;NJ-JNU^`&(H'PX/H8_*MG
-MLY.%\V;,70.S/AD8)ADQS#2Z[D1=R\?TC(QZ^G4>;RI_!>YHE-&+*`UN(C"!
-M8%I*8;-^-@;EYJWYU!!?N7`C;F<66^*]NQYS7)T/PV:</E@FA[%[?Z?^1I:O
-MCN6IO^EO9#J*GJ$;Z=7A`UJ8EXHS93T"!HUY52\0:XKW&N9+3:U*TUAORHRW
-M.UT6@F,E,.'5\1+)9,>U4M5`F'(@C.J?]$I]>.K'`6B^Z3Q1E&+!KR)_W'\U
-M$%A><LB`;,FA:4Z[6<-[;[;P,Q$])6J`+.FMZLDPKNMWG^?Y9`%3\)(^^EK5
-M.;(J(9"127QXXVVX>,_JU>3Q:M(C>]]#%6?N^E1P4D259AZ30/)PXO'JX40D
-M5T`BP9*8PKQ@9V9[I'.+_YJM,ZDE1G50?:M))ZF;OF%?W3ZC+FC/JY2+;W!Q
-M-SCK:PTEW#HG5<+/"4X2\O*E<X^![O'2/;DZ@UJBO'+&L(NK5P<5UNEW\='P
-MU%7J[(/SVR5#\T.>*=/I=$%TO5$GH>OL@T]'7CE*UU-:58%\^W8_%V"]/&Q?
-MN.K*0<GG.'#$'7;(;G.["ML*CN]BJMI2+P98CG,L)UC^^YSEO]M7<X*]"H^L
-M/(1NR)/Y@!5J<D/R%=DR^^`6:.GV!=`[@90Z$#AHGE,A%$X[7'1'S9"?LJ(!
-M_\.O;#'65*JN?+!P-\P[9J[QTJ\[VGZQ@JYI)G^2U;ZJ;\BB"UBFB-8W9"JO
-M5#F*PD&YV.-`N;2[VP2ILD#H];&LL<HK)8&%BL#`J9%7JIP9WJ+(*Y4[G5%7
-M*I'(NO(-PCG20!^.IJTXUB:WVDR4+9ADI#RG-'".5#`'EZ3BJ*(U^?=[2YSC
-MW&NSQD=><966QM9X"R?$SE=6K7..J2QWNT'!H0K+\FVQ&[U+OANGO)*NNI*6
-M-SHGGKY9Y:VLR#*:2H/I(X92.5T-M996&DIE8I9M>"MED@'$.0.XI50*0\PJ
-MPTQ!BXC:#<HB6TN@\8B\,OL@;64%U%B3KN_%R7VX<2.:$>'944Y?55JN+[M[
-MU[YRWW(/KZ#+<D(,$T(R?H50!88SXLJSV'6>&53+?&QY.&J"K46P!Z?NU$)[
-MT[)I9],NCX=^)SO`W,0Q-V,6#1[T&6Y!U23Y=8@XW:]#!`9UH%&#S]W,F[N)
-M<TPB$DQK*403V9G084LBI_G)5ET9I^^K7%@*TY1H[?/2/L?UQ\!>L-9BQ]OZ
-MV5F-F>P</F2:G<F=`!IB+/VZ\HJI1*[3\-S7UOU`OREX3,:'@;W^GMFJB51>
-ML?)_%@J6X.OH$5>L5)]W76.<30I&@UPBY4_!1UPQ4OU>B)0TO3<F0^Y8]%B7
-MS2OST:E+0G9-*)A`Q8=6'G(WYX^S3)2:FP7F5I*O5"S(UI@[E7L\T<4*Y\4U
-M;>YCSO.KK[B/4\4A:[YQMZ^^9+FL7O-MOHR^C^ZI9R22IUY=/(Z^C_^.D/00
-M_'$DG_OPX?A*]WY/W>B6^]G[^)9T=(<\E'Q!CJBRTE(JJW17ENLK;,HK`='-
-MP2,N_Z371,0URZTQD7%:+-43`.)OB8FT-(^@FD/#+M\.8&369F74Y4OZYA#@
-M/FNS8NZFE]&,S<Y$2F,.,,4&5DR&]+O89!_,''FY,^SR:7H]L$B^=.MRO^$P
-M]Z7KBW#Q=MS</SS'=55I^779#6`[ZI#M:.!8=M]K.Q[,IBAMX#NKGFILMS9'
-M6)I5EF8-71Q^^3"=H6^.#KM\PM"L-32'AU_^5M\<:6B.HII'*B^WT^NIYACE
-MY>/$)[A@*4XUZP`_V)EI?GXA?T+\0KL!G]B9<<`W>G4@&(&Y;M[<=<`W8`E:
-M\N\H`-&G2!\:U63HY2WD)[*-M:::+#U!KD"FY;"I)M/1>,`XNY+5"5\89WL;
-M\QSUG^HU:F%:LED]\1"#\2=QB$GU._C?3R!JA>(=,LOEB*"@AR4#W/H!N`?5
-MB@S;(KZK7OE=A%D38PV_M:PC6+R#E/0F8\))'/ZD^J7"]R802XCL6$K+%SK)
-M);G03@5]TJ")MF@T];4$\90A)GK9)7G=-N!\4TRT&(00=752NX1NHZ_1Q25R
-MNE=Y><7:8'I*#"BB#]UU]&K!3)D@"7?74^J).39>!H=W=;R`D0J=',&5\7R?
-M%%0/49A`E"7P:Z6434J[='F#O(OC)5<GB!@IX9%*/+C8@Q<:S=!-!M=K8L1F
-MA5"O4%Q>(IB)\T`UT1EJT%:"*3+!%)S.@4M)8Z&!YY%5'806H:A@?$*`4THX
-M<2'(4;-./9%W7P(QA;5>API'TVE5!_+CW2V5A[U->JVB\87Z,D.L8NT7[J.>
-M(QGC2UH+[Z_ZLN"!RJ_R)WB_SAD3,]MK:)9FCXUY0:EOECG'Q<SQ4LUR'1BV
-M*;*-4ZR3,S.#K;<2K8]F9L@/+\J)S=9OJC7$!A(>4BA\3!\3DY*XD.5<Q+;D
-M2OM@8+LDXK+Q8+7RLM'"ZC;]['1`.PA6S!E&.U\"VODR]VO@V"_?W<O-_LKS
-M)8P]X1_XVU]4R$ZKRZ7\Y7A2X-_R9+E2N@U,/@'3?V5\2M<4^^T-0TPX$S'A
-M'S`UR1V+PW@#-\Y[#Z:Y>)@AP2[1BX3$M,,;OTQ$QI(W'4\2C8C;P&4I9]DS
-M'EO\L=2DB383O)9#8B]N1CS0%G;IEJ6X<F$_5/:"H=CK6/^<(92@;QS:">RL
-MO/0CN5^VN57?!/A8RJJ\1TQ-P,X/&C76@CFB2V.!?QWUFZT:M:2.Y4;)I/I?
-MA(43)(Q0Q(@D@H<))[?>*1`\O)F1_`8`$U_:AG@XM2.4"K\E_HT4K&=+`?-O
-M%N9,D-02^;%Z+5_L(9>50UL9^7;O@>S9GB9GBKO%FBR=]S-@A:/K#E-:I54;
-M7`Z3775DY3Z45A;67EVNH%=%73I*G\D/KP@Q@2)NKVH3M,J"6O&*8Q&7#NB3
-MI<8FKV$VW[A?:6SV'MVINM2.!BHOI%!A3N9ZI*1/)EX@,'>JDSB_6K3!<;'*
-M^@%+;'#+0\[80OW[3G>L@"$EDL>LP`\S`M&`FN>K59>:/-+A6I(X&^S,P7;)
-MPK6@DEX[V.-7#K[$),$Y5I?L1OPC&K`/OL!&+ML'GRG_@BX"$;Q1==@+C+OR
-M0YB0T14AY8JR,$?B#KK'7S/T'`BLDA8JO$H@<OL"EL:V;$6!,C]LQPZ+@YL7
-MFZO?WDKN(T6BQRIB<^888V*$M639'!@H^H;0*:!BE?9!$]A3:K_2'0K30>1P
-MD5YXV!#*!Y`/3D/J2:!Y%4S-LG:(+'6&%H[8S(#QA#)^>DZKC7)A4L".E.V5
-M.6&YBKR0@CGVP1?];"K:BOHWI`N)92>JZ1G`>';F0<2W"')KH@$P&;8Q?DTT
-MM^3!>>XQ1HUF^58K8%;`[R9M)'("#W,ZJL$'O#3SW_F`P,TI.S^#@9XO59RP
-M60A>'(&!-$1>>F*N.V#N.CP9+S5H=(ZGN91&NPPT(?X:4`#-MWA9=8U0)#&#
-ME0=M2$[\\O608UG>>/J&HVDY<#SMSAE'9Q'N">ZHACPQN&FA0:#0Q;4"2TW6
-MR@.0=XH%U'G?)*/&DO.R:.M8T%5QFB@J5.QHF,*ONU<A'ZKB+R%$2PB^X&'A
-ML!`L<4;&A?)3TZR4)L:M7)(;IPU5O*=TCM"&W^*_1^*O)T>'AF!<5(5V!8<;
-M-T&PA-#*%='RD.Q89]R09L=5M,MSP>EP7\R>XTPI/Z?O%U']Q#(0`]P$7$\7
-MK38XDX'O!3F@G2>(:J6`\22@M=T30`FO&1FMB0(US(U6\)W2-1&KU>XP9Y1@
-MM$PP&E=>DH/ZA<B:\&BMR%'W55RH4A<:&A,Z(G,NO7CM97I&^17G*QGSW%=+
-M!D`=TVG\J1S)%`XO:3R=P']V_(A+W,R1_)GX>V%KSV9&\)%J!SB**[X?%&P&
-M98Y#/"/<W5/2"T,6L'9(O0,F@B)Q<N7:?J@R1C["K^1Y!W$)Z/GS.GEHG@IF
-M1:_1D?MDV_<9&C+K/-MJ#;LS*6V(/D97[Z1B0PXORH_-TV_RF6,#Q:TD23YF
-M`@E].HGE%,,V#LMS.L#W]"KH#;TK%DA/$+W*D<SA!&:,IY-%6>-S1Y:?S8UP
-MAHO*<7<O?PK@9VG@%#ST^V.\#3CO/ASB)3U0+",L<&Q"`/N.MP\O[X>.`('0
-M$0+<YQ9<`G;JO)UYLO%+4XS)0J3YY2'@[W@2'^0?B)E7`CKMR[FE?4A6DHC+
-M]MO@V#2>-,>8[,Q7=*\%W9L/%<;M5ZR3\_D/"Y9PG9'U2R"V3K9U2=P*1:H3
-M3,=-8!TJ5+!D-<0O..7`0.FRS5IM*!\8Q7Y[!\BK*51F"96#O(8&=RQ*XC4:
-MY<&1WZ^VR.7T#9-<EK+MYYR7[;<_:9<80J6.&1_0:=ESW<'E5SR7L^<Y7_$,
-MN*\ZYQGD4K<T^Q5WZ):]'L7R\H!L:;W'$TIG`"OH-5%^MC"$A@'8!7X%"QZG
-MB0&>XL<I>$MDPB7XZM`<Q9IY]*BR5V)@K*L%21S)3$[`_>,!*=")@C'C@3UG
-M2@-J<4%F0L"8":N-HIE28B8>,!H/^?XM@3L!(FMZ<M2948):&:2'?S\_^/OY
-M$%G;FV,`MN+6XF5GH6*#/"Q@3$+`3"G@">"AM?V0!HP$:<1,A!*`F89Y:'5*
-M0;!SSOL#F_=0H0$@3<MS<<MECF@KZ0RI3''/`>'2;_*`>`D$CU$Q,4Z5)[;\
-M9>`Z<J]LNU=_/!,4@,`CT)_(C/Q^E/WW&WZ=1[S&SJD_F]@C,!1G+=P$IBC=
-M6ISIN+:"?C_X>ZM9@R12Y)/Q6F7B5MS\A!RNE==5W\?Y$BJO%1C7_;CNYW4_
-M5=SD#N"5-Y"+5)S9N<BX7VTLS>Q(,.@"H:4D`D.ZE9U0F%B84^X#.++M0C4[
-MK^+A>3U1[=Q$SZ!"I?9!(S(OQ+/^-3D!R*EH,O]^1?T64=D$_70;72_<XU]-
-MNAKY/3?B>Z[IQ*17UH>G;@K`$IV8*X]0*19<%/GC_BO=EFNCB^E5=`^:SYN2
-MESB2@O&"`:EP)H>^%E`XGL]()0MQO5PJRDPP50R2^>,#,B<XC>`9HIGU20-\
-M>)`/!S\3S$O$Q=L`!$DGOGN;0:-V)V2J>6XI@IHS<4K#"_@"7_MPH4'@E%5-
-M$54E6-03H>Z@20D!`U*H[:TY`H,FBC`HDC$<KCRPU]M1S=Y'K>J)`C<N>2B!
-M\"^J3+6HR:B+S>2`;.>`N2]3_*7(W(\6+:X%?.Y?K^#9&6*^E*!I>J.1P%(6
-MG:`7T8ET":"9`B.]:K5->(HC?&^\8(E4+U=P"Q,DA0C5`@GT#8D/.BW.',^?
-M":`-NLKS2<4+</%,W%PQ*"X<3S!2/H,',#ADYE8E`/F5"?EJ7J54X).A0=B.
-M>Q^&82!;I#`,<5H".@$Z$+H>]R@/N@L]O[>[)DT4:8+N!I@T:HB(O_QWW<T9
-M[N[Q.O%VU&%@3U]"P8PC?0VU]:WF3FG0TK%N:(TL3'2?JCJ9_4SATQYYE=33
-M475ZY6JB?E_,"U+'RI_L3&N^W"G;GB^X2.J?XRSMX!9*ZQGO,U5/VP=/(7ON
-ML#T98$O&B$D<X:1Z-Y$]P:B>*)Q.'=JY;327Q7M4'@=LG6"T8.7'409-C"G\
-MUIM;0XD'2+*>-8_XI'I*F#Z!JR6`ON,VF)4B._,)BW%)L.,`;X<AK4&#@VTG
-M!-,.9]W%M(+9]V+:7)N>X"W^&,8G.J4I//SBX^::RH4G0`P'335>^@<'_5/D
-MQ4>=XP%<.U9Q3*&!(*X1%Q-`H+?Y730I<M&P+G--IE?I:#O1>-"JL13,/:V6
-M#(PU:Z(Z>BK#9C$'D/$M&P'Z`<$)S@/YRFR[I]TY>]U)]_'"E*I3!2_GA%5V
-MY,TI^[;B=.[<Y5LA3US413W=FQ\*TL]BT,IV^HP?AU[4(#E'.%0XA$,WJ2[>
-MS^(\96$8G09`SRT=`GG4+.:O!2-:KB+\N>./^#/:CS\IU47C4,EJ0RCR3V8Q
-M@+L.@U^W&TR,\!G[X$&P"$@?"!/M@WN@^^4*L*3$/H&^81C28Y?T#9D.U[E8
-M#<]+5QX0S)4A2];(+K9X\VQH;7NC=\FA!Y07?L\9G1]/WU1=^+FJJ-)5:%RW
-MMFP=XK]BLC(A<$#F+>4M0$S>V(.XM(1=D,XT;%,;T(*0BYTSA"+Y2=R(E!W@
-M_7_4+G$D9J@N'/=WG[[F1[EAWI"[`S`B_^6"$*<?Y1;,V9[?V;.T@U-_V1F6
-M.Z)BCO=EY*MMK?4[:F6QA7/!68-1JIIK'U2`@6,5M9"'%*AP&SB^8#(_.JW.
-M520)Q?;;6_VO!;?NP:[\HW>PZ\M(=S:^0:&=!@%X^T>ROGP1Y4(\R&^$LJ`W
-M3(0\B=L>NP&+V\!'$^)?/`J_L%E?4QEQ80.[?I1O!$:\[JC/!!DEK\AJ3U%@
-M*#+AQ8>FXDS.09ZCL99NM\1+G9-B1PE+I!D/Q<;P!'-DXCEXY(6/O'6E]:`]
-MLI2E'])S2S_"#O)X&4I!RS,80"2P&;L"NF1!3EQU86OHA4*(N!OH='>CZL*6
-M4AIF0%?C]3;IIBMU&[T'=AJ^"(3YT!5GZJ9+=:69!6,J#?ECO<:<<66F[/%F
-M`R;\F\)CID8%6VR4;M0(BVYB4-!4'B\AUJ;7Q43JY!@5$Q&K>]`P*@1&@Q`^
-M+-Q"ZBLNZV.B5IX?(:Y.QLA)',$D8QZ'W#,A","0AX175DV4\L)[DE7)C306
-M-(DCFE3_:5#'!$O%+4N,FMPWEJ:I42,-H\),,=&F&!U@-D!-IEBE:"!"Q$10
-M,5IKC,428S6K%888C5C\B%FG@$'_*I$>U=@$0Y_$?8M>YQ]Y4!-Z72#``G`A
-MT"QT)/@2:#I)$$^OHT?]^:7JPH,'VRC_CD%-NK$1%S.XE5U*%)T=E7W%[2J\
-MDGMU%U-U)74OUSG@O@*^@YC=+;#?'@1)4EZP8KT\O58U\H)Y:Q=V.]Q8@SQ_
-M4<?0JB9X_KD]GCIG3V[?+J>[9^G>`%,?Q]3/KD=VL>N1MS\&'7I:'7'AX<@+
-M,;F:J`L)HL=%.ZEW5D^E>T1[<2/!$7XV/BAH\I'SUB]OFW^:],K#X:E3`S`;
-M,L0\)5J;\\?]U_3UP'`6`N.R95*N'K$S7W;91%J2+J((3*(5X`_)16Z_N;=3
-M4&'6I$.NU+(H_2UIZKH`K,>)U>4)H^3MD@6_B?Q/_NO[^OU;Z5XZ370!E3V:
-M98&B_4!+`:+%A7+PHN2H#!OW7UE:H%6NV[\]5&AGBNEKPJ$=@OUV=$(!9(I2
-M!\Y]#[2.,Y;@@'I/>;H""2*2JUG,7KI.=?YVWH;@\U\6JBDBC=H@IM.#6CET
-M3]P&TJR)X(*RJ8E6/TA?YW(3N(/CB0$I4JL;4%*/8#0'DJ+.#XC`?+9RHLY?
-M@7>J\Y<K-L`3F^VUXZ$+!&#IL'H>-B_\W7*!G1F`206R@\^?59T_:]7PZC[5
-M5T=0U2,EDJ?`%@N=.-KP$S\B],GT.:G"PQQ@!G.UPK-!*)PJ\,C8IY#A2*@_
-M$N3A1)X_;JE6(<;9$"K,5N@WA+!7!7L-UE='1IX_ZJ\;I#;[`ZX3ZN7DFU7G
-MF\61BB`?1^Q#%7D^R#9$GF\2"I\*\"!2J`TJ\.6H#9'L-:)@DYB1B0<X`!6L
-MU>K*32"Q@@$9^Z09CFC]$>X`)[HFF"TVLM#$_>$QZ%X`@]X4;K%LT`85*"P;
-M-.Q5[=S,WJ.RC6(G!YH6LTV'G:\QUVB$#"?L?'7`:!G`(_'V1]V;83ZB:[3-
-MA=R@Q[GO*V`"`D?+`,Q:-FH/(AL@%C\:R/8D\GQ)=`Z7RP`548?RH?T@R`=S
-MN47`<)RUT)!^HR9:/3'R?"XW.D'"OCLTJ6H+`"(H$Z1*`$(KM^C5$X//9W`\
-M4K0@6`M/,&S""0DXFQ!V_F5$+XH\FK_!75M(%<1R?3`V)'T]:'`"#HP"-FG#
-M:DC.7LL=("$MZOP;7.`4'X=]$QL;'!NKB(T-B8O!G;'Y9K<>0+T^5AQ\_CY]
-M/+L5@'49XKV.ZI,(\G\B>[_67).U9_J[!^!%F[X&#.@1C[2D"'B9KH\\;]Q3
-M82[%>$^"K9!:-)'$)MS1\R@%!9TRKE-@3<^4/"6R9F7&QD0>>>>KOQJU*KTV
-M<KD'I!\[O#?X?,B_6OTXO@AXU4E9M8%+KS]&7U.>U]!-D7`YFRL-.Q\DFB;:
-M/<535UF?HZ[:Y?ZHZF/5>:5G#VBPR@\#/7C%7N^^R/,C(LYS$0C]A`0WJ@'I
-M->9ENL6$%KE?8C$#_U&D)E%DRMW]=I!90SQW83KT]2:='-Q_><3YF(C^`8LZ
-MI#!V9/_W,6J13@-@7VB>H9LW&3(=*J.6_8K6Y0ZEYC7D?KBP$^Q=!-;(J[N`
-M.<,W;T;;-[%\`'MSUQB@[P;H^Q8.77=XS[_?^Z?4#KH7HWG0??ZGT`L.\2LI
-MODV*Q6'"BQ-@MMY)K]>KR9']+:1'MM5C*<YZ[7PUN%2.S\N4_;_2WZCZCWCK
-M*^M,:J+T0P&H@X8"-=J8WV56\\L^KMIM_HB(U?'1;FQQIJE5;2K-M#/_^"99
-MAX;(BIJGZV-U(=98?M!)=B]@IFY>,73QQWGKX)HS=PUDB]=KHU*J3'KU\_.*
-MX#&:S=`3WG_*$J\Q;&>*>\SQ&E-\]"Z?>:/FW<,!IGBM::/&J'O>/O@+=(LN
-M(GXA!>X)_+U<X1:.\%?`-&%;G`+A5+TN1'"!W'P2FG2X5J)A]&*^\.W;Q9_B
-MWKB4_]AM(?"@__!O=M6".O/OUVZKH)JRZ-^6_@"$K-`W93JJWA[9OR>\?Z^R
-M?S5]-K)_=661UU6H+EU7MK:TI'R-'\;AF*4IDSYIN:RV-&<BF_B]S:P+C(W!
-MR]$.7P[XED]5Q=F9G'9)+)ML'WP(+2JR?$WF":Q-60M_AO9(MKU`>E=D_X)R
-M:(:"(5^#ML.*"]7@'565Y,=:8-#7>4LM:X<&W=B4B1S?YLQ8&([;%Y%OYNIP
-MI2SZP3!=:9RHI!O!L(A:_(;LJ\C^F1'],\%O_2[QE6>C3"_<3CW$;HK7Y9$J
-M9,N^%_F?_-?<!`.4+9@:))DJ(I\1/9;(:Y62*_"*41']LW8YT1X$D&3+?\2I
-M]HX!Q]0=7QB[D;'&!N8G1/6_NNS$5.YR$?U-1/_]WOJ*.NB)YT,$CX%YD%+:
-ME1]K4O.]NYV4Z2/"_;%53>IU?'E_',G(:ACMC<Q=*_$!D>6G3(0QX:6\7\.^
-ML=R`E*"5Z,W0D8H6O\W4V1D#"USS$LKER[^*IC\T353Z$K]+3`H8S)73KG(I
-MW6N&WEP9[^A^,3>A0&IGXOR+S%W)93*$\S%>1^)WU3FRI,!':1==#W@`_*HX
-M&,$Z^D!4__T%"3NM0053>5=$I]M2VW&#[Q>Z[:U+2ZI"DC&5IYK:)L72G&XY
-MG89=RZL*=J]W)#^G!T3BX[YUZ9D]6PJK^2<)R<*Q._=)YI!5:2==*+.4?U*T
-MQXFEY;EE5`TV#VWG9S:TZD-Y[M"E/[R4O;Y0D5*UX<,!ZS9E=LCI:^_\@!MN
-M_Y*R<+,9Z0EN_N2.MO#^4)@:ZQ28D3*;83+7JL66'PM0]LL$M1SEN1_*QJ#Y
-MB2^8+!H@*R?GQV[_U!N;/>4XO66O9\HQ2>;[DBSR@Q]+J[-JUKX?N`!/G<6I
-M7^"MR9]L9S;6M\:M4'H4=F8QVKLWJ$/TZE#%N<_`6W"X)IO4(MY70F.O3OCI
-M6/$^TGA.M[V6(*8:="%'JG,?*:2R)]=MQHIX2%\QDGVX,99?&"O90RY]8`3K
-M=X(4#*`MEQK_61):<TPBKB6A.G\=V_=!A8[J1;F/Y%.%D^MV8-=YV$#X#I]X
-M'UX>1Z\?>:[RXZ_"SE6:`8A>E:$3"[7A._<ACZLXW?HP+MB,4Z4(3DK.CBJH
-M\_9DUSD;=GD\=>]DRYWUT*J[#AVLB<&U!`?8!RUO;QDF`HEG)>M+EX2M"6E/
-MR`AQ)M!%@I=G"`13`]SCJ=#`9"S^JQ?T:L4*I+=^`)<FH=/F6Y04,.6;ZL,U
-M]`SZ'ZO7OU?-Y4[E"Z9";O[+,SJ3';2;3J:K47]IH7!:2M6G\][\)/N1=Y%_
-M(\BG5I0&&-7/.QK""V.%KTX5#Y*.GOFJ<\[&-,'X<68U&7;.X56`1^<=L<6G
-M/YZUV\DZG>\:CV<ZZI:4R\ND^9,KE-[@H*ZQV7&^'HF'7(GV?F(+@E=VP!UL
-M0*Z\,\$K<X9:U7R?K4"VF;'J^-V)LP9_9G=58#92/B\<>6ZJ7BT2>41Z+X=R
-M%>M=:_SP+>Q<VA8G7%3GTM#6Y<`X.S.'5>;KP\Y-`C]`=>Z!_!'(&2A.W^$K
-M4/BG0G5NC&0G>WBD]#\='K&>P%(O\@J/P1U\0S132`UN`S5H5`?.^Q`H'DGW
-MT#]8=8'Y4RPZOC?.2WGUWEA+P@CAK*<!HUMTHET#%AU))4B,.H=`\!=*1U@F
-M!RSJAS'IIZ^//!<:)'@QMX'CE"&4RH1C=;S-#$4,UC$229B`&4NG2R13!<PX
-MJR[4/IC!'HSIL81R9C%3P8/NI=L*I?0JHG""!#1$5VCVY'R9)]@^V."5.1)=
-M_I'D/HA;Y)Q9@[\IS]ZBZV%^(L[^CO;=]X63W;+(L[]NN[6=T=_(M&A5PBTB
-M_4^9_J,=^N/(SQ'NQ?4G_G">*\=_GFN+++\1?!PO[3]UP?KZ=\Y@L.-]PXH4
-M>V<^91^\0:^F@/K;S4!0"'<BGL2]\DTUX`\6:P1&G?T]Y&R7>+HL].QO^>H<
-MK;@#QT^1Q!,B0RRNK[C9<M_"2AAD\=8C&RW+SCQWJN[H6`/!`>`DW#I>))I\
-M=!=U^W9,%K@J$7?=IG!D%&K_X#CEJ&N/++L(8[Z_3'V\[9@$*N"R%:1\_JF=
-MH4_;1!9RXT!0*^FPO1$T5LZZ4X%3R&%?:JX>6BF=="CM[9PH_7S6EV)MC5")
-MFLKY@_UY_^)^`UU/IQ'LLNO17",4W3WLUX'G5)W'4\F1S6+C_FO-U_N9*I:P
-M>QRJ'#N3#[Z><,C7VVUG]NZW^G.=MM%IPDF*QKJ@?:1HVEB]3T#W"EG?[<A[
-M0P-RY^B8*T_D7^)EX_YKKAIX&#5UP=_4$=9N\.CDR+-OC#C[^H%5>AO78!/H
-M=<32]?(##<NWP,@5GTYFE\!9*6Q,27P*`(&A30F@D")^MZI%1K4"`)-@'T?,
-M"*GK.J-.(1@06'X$M7A\&/!R.I(/?SP,^?@LY`,;-H3Y^N_LGW+0)J)0,BV%
-M*89*Z_:)1%.A-D?=%RL^7D4WDA5H:8>H07Y<Z]\L-L'RWC!KF[+E]IWRV$U$
-MHW]U!J#LO/1N_Y;@O*(3?ASC!Z$6M<BD#A$/"*V].J!\9ZOIG`Z`:4>RX_,=
-M0*25)9(AK#<0+KWFQZ619PUVQH6D?S_C)^OH1RL^1@3YMS67'T;`]E_W$<D&
-MT(#HBT4@O(65`?\ZZ,*U+QUY=FZ)UK]KB?H1AN@63&M)]ZLPHFQX68-N/*WF
-M/H##2!VN'5K+XBKUU;(3U2O7"8S$;5$YQ[A!1L\PJ17T-^)6W*0#L[BQ74+?
-MW:3F3+QSUD#`'8>GS.#3HY*QV*_0RNNB_$6=">(%,Y*X^[ZK;MF&K$3&^M75
-M/-Y4,!2GDQW5+70RA8Y6^D]('LE>-/),/WM&\G-C`WON!3LX\DQ?Q)E>8X/7
-M.AUWU'T$BH?LDFV[#"@5,&HR!T.8T?6;ZDPGO3K\S"EPQ==\6%8W=$BROM*E
-M.G,<?*H^;TF1N5-I[O>FS'AQSSOT>I!;DI5;1]UCJC-?1YYI0^L4DU5U3Z`-
-M#1<Z%DD,KV^P3_YKV)G/_:AUBU.;GDE7XY-%VJS,87MR1YND?%YK9^I6VZ"7
-M=F8DPM8:GO+,-?8@!#?RS-:#0%:M\LRVH2.HZ>@(JI#!K5E#9L-TG#0?#UIQ
-MBA]YICJOVW2"/'B-:KT%BC'L3`7`1W>%,0MC<;L;<9!616EX$6=*H\Y\9VK$
-ME_X^"=2R\DP)?0S0/M0MZ1ZJF#P[*N+,5]LN%]"%32M_Y18<J*2M&IRZ?,M-
-MEZ>A7*C&1]LE4#SJ3`9];.=`U)G54(?^1KKP%*[_::@.9T]Y6F%/=A_8M'XL
-MU<-U]KI[$'^=8I>[!@/8-4X.\F&Y+X6=>?.>\;IGM':72<%7Y.X%W^!V.WM.
-M)9;`CCY]9^]S%C-_F&=1_GO$]VC]NQ]?&I;>.VNPR58;UT+\;`;=$8-;=420
-MCV/6*0#8)7$6VIE-0Z+"^J0:'(_%@=\.I[4F&>8O1@W.&ESDEW+PT>5G'B7W
-MRVJ.@)NNG\Y]MWP%..FJ,X\[7&]6NO:LJY]F+.6D)#:<LIU>9&)/V_*_]I^V
-M_4O$F4G*,Y.HYF$;XE?1D0I@HE-_4-)TM=4FL"[&K,GD/:C^,X3J_7I["-1O
-MMS,?1I[1*,^HZ?5@U"VS5=N/`LI`5E6;/G1*.G;8JM:!5;USTHU74(\.NOV#
-M/>B6`IZ5`O@$^MJYR)<`KD!=$OYKKO3?$,&>OU`K0.?5>_0ZQ=Q56KK>H,&-
-MND"">*1E@XG`8.SIMN%U;4[HL`2@<C9NTRY0^`:;C"*BEZX?O7R][>@,T$P+
-MUSH<B8_/+7ET6'7,8BK0')/36II8773,?[:(C:/@`I.@[.L!DX`\6=88>'2;
-M!\`4V)D=H(-H5-$LYEN@U$`($*!&VJF:OG!7@8?</0=U="9@`Z,V2GF&;]"J
-M-E.`#$C`[[%1AEC5TJV1+0THJYY(VZ+7QZKTL9&T2Q\;==SEI\6P_1?(9F=.
-M^O4<]":.P%Y;ET!O1,,$&DP7*!`\$LB2T+(J#@R:5F741BZK%[?4^ND$^)2$
-MM3H2YY@T.$E..WP@&?L6)F7>6M!Q#68-+A9/2VG[/+QOD[6FTD((4B\]I:_Q
-M.ER/1_0=6>=2]:T#Q4:O]JLU.K.RM*JH:AW,O+G&2^D"S9TVHP8W;_22[#DQ
-M_WE[&S8W>\F03N>\;V>R(OOR#]8I^_*&CI[Y%Z"!XN$%Z$)?Y;4\=*RVU71"
-MO,(CS>Z"*??X1'?6P.'Q[D/KBT9H86_L'1[(0:G'%PV-EVFQ?[]YUFV/G1'Y
-M]U38M=K;:_U\$DB[3J@-R8%:0OW:!S`&WX[HFZOJFP/NIF;>!G@^1_T#"2E[
-MR#;9WXDW_#)J`H[]4K;IM+4FJ^'Q5'144HG6T8KD)47*OEE[*MRNE!E/[)E`
-MKP>'E]P^7BR>[&A[*:KO.57?7RT__5G'#^.N>W0\76V&%GRR33[3\4QRNLAT
-M(E.?'#BW*-22''*DGTX'L:(<@3B#)`OQ#`MFH"TAVU9*]QH[XVF7&!VLQK'.
-M5EEF1Z9>Y-#7_-WP)3;V2"P39C'^<P"HJ4X9_X@`>K/P)^AWM17Z<JTLLB]%
-MV6>B#Y@<@177W=>H9*+\!W3B^D9>,C+#/_&H9,4RM!R^QW@3^2&FFDST'<#&
-M3/HZ(N7V^)2N3^V#33M\RCXIUL@SSE9A!E9SO#&L.=X>GO:V\FO9;<[CX"BV
-MO9,=H#_.T9_`C/_`15MQ(ZB.P96@-^AZ'XS_92/ZSJ)W1ZNR%R%__7"=5K9.
-MI&KNU$E[KCG!RNQRNNFEOP;HFSCZ9LST#YPN(K?A)J20_MHNT;*$FVLRD6'>
-MF-GR/%+&"4EX+#NH=4-R&VA@/_=9ELVAJ\&9O-AXO/$@CY\0UA="-]`W)4]Q
-M1-,XY5*A3N"H?G:!8!K*NFJ:L1I;49_Z[EZTPK9L1LQ*%,F>NS=L[B>A>D+T
-M3KV4+EQ:+VHL?Z<^L/&SQ@)J`[:R?IZQFD^`C?D$7_PA;OCTEY8-=F8[.A:C
-MP;_Z&FRL&4#9L8`W]_*3,<WA2?X5U]X]_W+%-1E4>;4T6SKW/?2A1TH5."JO
-MI3!E<&V7.%*+Z7\T?F;<@-D9)_*Y'3.VQ\5C?/Y4RK28=;4SD;[6\,)ZSRP#
-M!L<WJ7HK#U9']7K#>JO\F`$Y_-=QPGG7X3?UD9:^H!47^:K>-7E73?WDP31]
-MZRTP\.&]A:`T/-N,I1A8^*^>R[8-?[WRCR'U@)73MI:)+#H;]9X-?;W"G^I+
-M=AQ3L.C,/(3.#A;:PGM3)0B=[374^+]@>3Z\=UG==$.-MXMV['RR0H'.?O:^
-M71Y,[I.5RS?O0YO%TP-8V#-7WY!YTN4.<13-H9M">U^G5X_L?<VLX:U[O[Q:
-MX),)?+BR=ZYW/5K22_<VGD2;W%G>U)]$V2&EKHHB<XE`7R%-F9&^Y_X.5XS_
-M*Y>7_':W(*HW6=F;3"'1CBA4I/X\Y%))_)M>]SA4`#-S;58Y+W5W]*Y!(2,*
-MZYUFOBFHN%YZ[5Z,TC>,4<)ZI_S3=*2_LFUQ!&=E)8C'=+J1;@-@#NIN%O.L
-M?7`B?8UXR;]UE6)G7D4?M\S\%Q^W//!//FX)G77KR:&/6[ZF>U:S'[?TF@SW
-ML1^WV/3WL1^WV-#'+4\.3Y[)_VF+C?VXQ3XXAG;9!TN`?RP`"GN?67ET:8$\
-MK%="7W<&1_1*L%4\9>^3P$.;!]`^>U,ZQH3KBW#B-]S0/'1H/J^'ZL-79'/S
-MSE0@7&=HO5768]R("7_U;V=^6CG"(Z/K<T([70CC8?W9LH(1C2=-!/KTPJMD
-M-P,XC^0K[;?7>)5HWYZ;Q'D(/6;0-OOM=:Q,JWJE43T_@#T>T:L#,VG01IVH
-MP_?ZG?4H?47:D+-^7PR1MO'()O.R]A=/)1\=9V"_:0O<S+K#>88KMZT;_^BO
-M#R_BWN.O@WL&#OLI&,Y3!K#IC:9=W.-U0_N-F_TPZR,[L^>T+=!,;O(Y;._J
-M_8T,^>OI>FBE=))XG)SZ[=H2\-E7#/OLR7_PV9/S_-</#'0R]Y2`^BU-0)'1
-M!$<P=GQ@X&1'\C0*ZLF:Q/\/\I7>\-3S0^`PZ,Y>Z#`T%+>0FZD/G!20JM$.
-MD4JG#3ORKX,F0>OFP/SC_2F;[$PM(*&B#PS0.STJ,.33CU$TM@7X2/&38_6?
-M"N@9PB36IW?ZR7CE6'CJ=T,^O1A]$_('GSY6&VD?S(!6D^[UZ=%'#,/VF&6\
-M64S!T+F%GF7ZFDI5S]OL9M=^@"UTO<.UJWP-_8.RYRT0<:H4`PF7^'!S*8<U
-M55ZC3<!:*^_A.E#[['D*;/.P;)EM4KU-9K0%8YYX;'^\H^TO!ILBLN=]K#9^
-MZ><!XG*A:1<VLF?]G.H`<870<)`3T5,5V5.UM5RT%W^M/D#?APGWDF1%Q*ZM
-MXE:!X6"N\6!>$N<+.[/6;)./["G"3L<O[0X058H,9[$Y=("H2F2ZR0&L"K7;
-MF6\C>Z8<K+NSS6_JQ47#V_S@^&3[W*Y"7U[W+J;*EWJ8Z^QR^T`^1/YM_L'^
-M>[Y?/:&>]PPY/$SL?MC<IV=`/_<\D*VSJB464`6,52?9,%`W8-$%F5W<NNGU
-M/M`&YA+0!E0>`YI@UN_3YLT80Z>E.TS)DO`>HTG'-28'9:N-.CX@78_:[?![
-M/NS^M[',H7,$T6KZF-DA\8\BBWFY+Y+B)%EHSQCQ@[)";9Y&_'?)1B,Y483.
-MNFC)([@IEN-H>S.X!Z31M.TD/0,T)._Y\00Q>>F'=O(P?G2SZ?;M:'!H[O!L
-MPCT\FY#GO^9HB-."9<C$MI9IK%K\\'4TD^`C"%\83Y*34[[>:V?VTZ[]9J_&
-MJ_9HA<5HP67Y@>^2L0V\QW'22`;N$XC&R@,'2$?U*Q0TF#4I\!7\E7^$I[X<
-M@-'LT4*_*F?C_NM^_89/0/&F$4-;.Y/_3.@_$R[1:;+6L+^V3`/P`WU<G48.
-M<7BVG<D#*4H3#CE>]79F5[MD/\@4Q\Z8#%_^@HK$P7B*)\IRM<KNOAP-^`_W
-M(_^A7%NF6;HUV.\]T&W[]1Z-1^W5HK4U\!E0N3-(WW7OQ$;QZ/7*[IWD0^"$
-MJ"*[MZ&E>Y_?]4?0:=CUSVLKI^_"L:#L8R!WGC;_>C'XP1H6EZ$HS*^\T[9G
-M7,J,]^FBDRXJ5)J,V;YZ_K2Z(JR#SK>QZRZSF+]W5A_>T%Z]9Y-_[<52@X%Y
-M#PJ::@F5GDYVK'^:M?!T-6O@&_-M8M:Z*[M;5=WI1K6H4!VT3VBIUQGKM711
-MT#Z2[A%5CL]]?3-3'B5R)KI52]"72::.!&7WVV'=M.`7D>`"41#ECJ32YPL'
-M."O1L;?1I^J4W:];U:0GO&HD>)I5$0)&0-W(TN_G+448A-+?R%1VSW,415'I
-ME5'=+R_,@D2[]897'RIS7'_>()>><.G5(;4>(;NA^5H9O,[+4XD+IZ8TUN^9
-M+Q:^)'XLD>>1"A_'/?\8WI:SSL%2GA[[)Q_@567WS*CNYY#^^Z,/$(GT^.D_
-M^0!YD6:YE&J:KU?S@YSD=G_S_$(;U3Q_V4_H.ZG([HDF@`>MLNVM^B8`!L*]
-M(GUS)GN^\(_^P'MV)K\=$`/48!^<6?>XLMLH*9<)PQ0>55CW8O^@4:%B&#-5
-M]R+`2O;!HQ5A]">&T&#V7-ZBO#"#/-@^&$W7AW5'H:V'[LC\B#M;#R.'OEOM
-M#AWZ;O4_;SVPWZU:CW.&MA[VL%L/M]L/MBF[A2.[B2%_L`&!>'3FHIM[]]MK
-M<`GO?FD)OD&0_H08G%7VE`;Z#.@V](Q^/Z+K=TK#J[A&TQ[TH3N@TO"N']W7
-M_2<!3;H0_U%`^^!4M'!(9^2KHKK'N6554D?;?_B2]\PWS%<6JO0K!`M^?:B[
-M[:1_)Y'=1^RF3:WJDXM0@@(2J->Y<2ND52'=+L""[F_,G>H=!2>K#=O4V#5G
-M52C:21R1DOA"CM(^^##=I.SJC.I6Y8:;U43@9Z*&?>B3U[[(KJ_=/9XS%;TT
-M;=+Q[YD^H@:_,W^64#FH:E^",51!U\\:W&&4*RQRN?WV982IV'?PIB-AUN"M
-MX3?'[_W;!;FCZ6H3P4G&<,,V#K:>A[6$"QHX2^NN^75RX#!6_#&RJW9DU\^'
-MJIQUPBU<80ZGK,YX#'\G;41$U\;(KAL`S<2U0Z!,='84T-78$_09'A3TE.5;
-M'*:776LQO.)2=O5'=9V/Z+J@ZG*'=:TU]Z5K*R(D/HZQB/T,<A]')'K*N!:'
-M*IQI99[PKFYW69E[R+<B0KLZ([K>&]'UGL0LXW<1E:&D2=3@X_L(K]P<7K+]
-M2V^(Z4N.@789Z2(!^JP?-]+%)GJ-8)^,W(='[Q>(:B.,A",I\.]EP=;756ND
-M5;)O%@5WM>2$Y`8;JK&8B=VB6BI7FA0X,U<FVDKEA1I#><;F".14V;`W#H?D
-M*0R):N/]:K*62@J<3A\C?./,?Z%V36F8V3#Z[0FG&Y84R@M"G2&[!NJ=[I#*
-MT-2+U4-V#>U8HK$,[TJ"=I(X.>PJ]BSFUY%=,^F#^GJ\91M9@9/D4Z:/<!*-
-ME:IK1E17.0P.0B'#7X?ZYRNBZ[&178^SAT[3]8WXFSL#X16:3'E72617J;*K
-M5+R=8]Z=+G!S!(*GJ"]PD(OBK[2M]PW-)WV63@SMFM">H%<'*KK&L,<Z?IB'
-MC@=G1W0YR0>!P8Q-/QJ:;IH?QI>O?VA7K:7I9T/SS95;`@Q-/T%D^1;CH2JP
-M#O!$$1QB*XXYPX5.KJ'Y1WB)Q'QVNH#A6-D/!,5G1\7HGE^V+]3:]).^Z6?1
-M#E+B(8,\I%"O:"E+QGXD]I`"2I&2=IDN%I["A<*G]'_!V8[F4$9MX+)Z\-A>
-M,6FC4KYV^'D_L%5@;LI:^!T0>PRD(++K08>K1=D55%GD=EG5Q-HU8G2\PZE&
-M*P\E5C6_O-10RK>N)6+8LQ?F)G#=U>;F3/_ZHK_*C:V&IBRZ#+FMF-O0E.FH
-M+J9_4791D5W42-^-,-\/E>L]U=GJM9N\'ZS=X'Z?78#"P;>FFC+10G:>FFK.
-MM.H"8V+PY:?P@%FXX[,](WQ=_VP?!(8J9><Y^Z`;2%%V<=AQPN^,$PC,2-_O
-M^H=Q-+.ST]'"U9RA>4<?:OM^-+&OS+/3D2J;,P3QAN8TPO>%WSN*]#4NWBG4
-M'L-Q/T\H?8.D'AS"L*[@W#3G*N$6CKXY??DJ;G9=:S%Z']$5!$(\)'7?(JG+
-M<6D[32`\99W^NHF0+DSNJXWH"J"=H5U<780TV+?Y5()AXB*L.JM,BKER/$K]
-M;&Q!SE.2*EE`I1"_35AZ,"XCE`S(>`.$X?A\XW6*:"%%SK&Y/?4>N-7F"/:1
-MU'5]>8_Q^`+#B?FB(Z2@=JRS5RB<#'?"2;I[M]8:3BRH+P-@5Y8\O*ZB\/5#
-M5T)\YX)]W<[$+:./%,QB3M*T(?ZF,?['BD1@,BK^)TO\SZ*=I&"`E`R0019%
-M,@:FDOC,'^47)/@STS,B?4L.+30?PZ-\2V#HEZ]_F(K_V52#&;;Q#&-O+LL.
-M,,3_!)'E6YZ$"*;A(29/"@\$)A_[(Z0CZW,C7>#A^+<8H`90GH`?EV^)'-I$
-MOI$.I;#GPP-KN<0]V>HNE2>T[FXY2#8A2`EIVD\8RXUT?(!SG+8,9_I/?T/&
-MKZ>A_T_0HWB4D%H5:?V->2UC1:3O/=(BV^'+/9;3IO+]9?GZ!YSM>=6[:LO:
-MEF5S<XZ7M2W?\FS.<2"DHQJ;$"[Q<,N.&4ZP?[Z@+UWHY`"K4<.:99A^G9]^
-M8Q^B_SAM>!C''@R7^+CB?1PCFY=`]!VGAR$[HJ_#IO!IZ32PT<#T>L3T/`^A
-M+T9K2R[_VI*??I4O@C3*=GRBK\FBB,GLV8A,4TTF/<I!OQOI>U;ADV__%'7E
-M$+-\_8/^G@"YR[)Y.<?A_K^D+X'(0:';8FQ\RH:%=5X1/"87.@DJ?4IGHB@-
-M&]EYF7Q"MK567Y,A_)M(OS'#WR]_F;#.7B@#)>\I$-'934Z3;=MG:,@@GA<9
-M=F>P-I!>11ID$9VG1G:>V`9U96TU&NL2N!X!.@;A#']G%5];DX''BX;W)P*-
-M!.90)X?ZJ$QI<&>+#ES83P3&[8/&!HMA^Z`H[.&Y:QZ=6_S4O**D9.PIM+OV
-M(/)9#34&<UT103QIJG,9MMT0L-]EO77X05-=L;ENC?]QV6&+T8#M&:V;SGGC
-M\2W`D*F?3PWQ2>W,/J@FYOX+=J8AAG#8F6UF@A!^.][.O+_H)5%`@<+Z("?F
-M9I'EIFO13A'A5.@?Y!A*UE`EQ;PG\%F#(^S,EN'B;[+\H>R\%=[Y._ZX0K]1
-M-O3G,]+EN/`1B4>&SAV-#J>CP9YHPX5:+I[.479>XVIQ;9;<O^:NINOHQ"SI
-MB,[\0_]1(E-TYB5CHWS5KZWG1W9FY;>)MY.=R2,[SX5W'E%UKB).4T&O@;J]
-M;VMM!UK7/&YSV+).)!IM2/<;WDC/DRUK>26R<XGX[X3YN"[@>5S4AK57.ZPG
-M#%H.D:/@U7(<#]68XCEDGH+7RB&/XLL:UR1CC[=+4JLD,2]P``"G5/U`)YZJ
-M3MUT-;)S#EWGK^AT(EO/(0:;P:-[L8%PR0"W4F9G/H`R6"*/$(8A=[+.SBQ]
-MK9$_LO-ON76BHR10%-'I577N)O=3D9V[=[16'+,S,>QX174FJCIG!'?6RSL;
-MZ#:Z,1D3MTL,-Q.LMSB6R](W>E\R]F6MC`\'U_>UAO/@"`B(^EH_;%N>^YV=
-M&6B7Z/LRQ9_("*/"\?EAPO#PX0UUM5[7+D_+MKK-[#W#7(KI*W@B`]KJVT)Z
-M7=XB<REN+N4"3+4SI2,[XTV[T]#"Q^Y5P_CE87FG01_>1!'F\,ZXD9VNX,XB
-MR!`=;T82!IQ8C8E$"2+W!"I&-:\&)#MK%C,CI#,CO#/1>/\%XGY.$@\S:E3$
-M/JJ]NCPQB=O;69V;2%>3^P1)W)Z0SN46#1[9^3IO`!<_2%EB</-S6!+W))MG
-M/9OG.T7GF_0--M=BR7`N;T(2]VO(E$#7;-N7Q/W*`([A+K";[(>P>!*W#U@Z
-MK',V_:VR\^6HSKFJSKD1G7-'=CZ4J=:58+H2GJY$()I)Z4K(@(#`;2_L>''G
-M2YMGZI[=:GYVF^[F)?/-R[JS1O-9D_G@?-W!5^V,&8V#@;`9">XLY@EYYU\.
-MK*<_I.]7=DZ)Z)QRP*5O#D4#DC5B%O,(/3VRH]MBOG7@NK4?I9K;E+K^$8ZV
-M+P[4`$!G'O#?)C3MI.LIR%6LST*Y=*CL?<AZ$.L/?4B?;.JC!TWF6TV%%%NU
-MM7E$5,<5"QLW-X\X<*(Q/;IY2*`,37)1+8?MO*%9WO@^_:&?'*H9[5@8A[-9
-MFN3HK]@TR]DJ4`9#\P@#43.+"0WKC*8_;CK:^*W!?,M"U%@VLLUL9'=JV+B1
-MC>LW2H])#M2P8R"T,V/0F,@[O@_N5$1V*L([0U2=(1&=(70"_>S(CO[0CDJ*
-M$,0B;#"Z6_W&43Q02X[HZ.''45N7[GAG^QNU2ZRQ:=:U&=$9.=$3.3$9>;J,
-MW+C8RKA8KRZV2GN+$]7!!'=RH8H%.:..7TN%\@P9UM$F9*BM/^_X9?NOM8RV
-M-"TZ,Z-^=,SB/-WB7.WB'%UIE;6TTEKJK;?2ORH[?@SK^%S5<3.BHRF\XR8Y
-MGQK9\0,I#MQ\LO;TUH[*.OT'&=:,G*B.JZJ.JW21/B.7_L``1.R.(@=(R^Y(
-MRV[5R([O=W:3^TAEQ\7PCHNJCN]K3^_P41M;=#]B,=]LTWVS5?=-K7%COW'C
-M.=W&\\,V1-G1R^JXX+".SU(+@Q<(1&B@O8.&FN#4G3P[<Z5=(N\X%=[QG+)C
-M-YOQ0;I>L&<"M4$)3^DQ#O4BNFY$1UU4!ZWJH!4=;;2-?C:O.K*CN$(:T?'9
-M`OVTTW4?[@Y\%7_CU1!E1][;1WFY4M&KI&`/I7]R<).3*N5T5(=U9"UCT[>2
-MPKU4_=;MI4%N@<0CH$J]%/K31FG1I571CMP81UY8Q]KPCOM,WMNF)C$Z8A*A
-M:/D:Z93`^GTH?L#.W``?N,GBO5U>`P:*7@4FJL[I?A](+;P"EP*T*I_O"A(^
-MM?*[\)$=:F&DPMQYP?R!SOQ!C/D#K?F#:-,NM.9JK;A@61]C_4!G_4!K^2!Z
-M>*SD'6\J.S)9(MX:V;$XHN/-R(XWZ,28$Q14&].L1]?=!G3=:!R"5L4!P1T"
-MH9.DQF*SF`V*CFPD.I.CHSJR>,\J2I#\6&_$J#I65Z&3W`57%!TO!+VHL(P-
-MF,7,G,5(D-[M>+>QS@QL_AMC.?$`FIM1N.G$_4.*8PR>A'\S:_#`K$$OJNK)
-M6S$_F6<-_GWHK$!PQ\(,6\SDIUN?BPZ?_OY?8AY].F-&XT.+[^<>LAZ3!#Q"
-M%,?7/[)FQEULI.RP.]-BTI\^DOC>C+HE<Q:%!"V5[7$&9`F<R7$K&(`(L?-O
-MO9QZ/3,QY26?LB,I)XVJD;2L@O33:C"BLRY]*>UXM@@KYJS!2[BR#ENZE/.]
-MK4;&N3:*3N"=#<5P3-;Q9+HT^@D,;&:Q5-:AHC7%4M[941G<U6!+5Z'O3CG1
-MZ&\B2CNFW*TG:KB>Z_?4\T"Z-/AT!UO/O16TVSBCV?)CBK!5G!3IXZOP%.F4
-M5=ROHX9K(X=KNW%/;7&HMDM_K(V6%G&+\")4ZS<VSB.02^,">_.SM$-]ES95
-MNA0Z<MJW6CK4I9'R#EFQ]&[-,E3SB?]$Y[<V#OI[H>F*U2$9H9DC-!&+.`IL
-MZ*^`EH2N'8%?L"7#^V*EO(//K;?A_:'1H9@VE`,9Y1T\#HYQ=3A/)YPO#2*Y
-M-G$@%GF:*516@*:T!6&VBC"28ZL,KQ@IOD7DT1S5_U/9\<<T<87?O7=7M+WV
-M6J"-Y>?UKMM0?O0=12M$+5!TD&WJ$/`/3:C6JJ1*45C4N>D$=<,)(J`3E<TL
-MF5F6F=B8+?MO11)UD2QE+L:[L"AJ2)R)`;=LR>+2O6NA_AC@UC^:][[W_7SW
-MW?O>NUZ_#UX;X,*@P]J9=BQ=#R4#D#A*ZDQF+<"`I$QEW*A,Z(FRD;DQ/VA]
-MNVTU')-::P[6J7)"4EOMH;4`S98W,I@CI2NC:<HHFV=BOV+G?YXQY,X]GV$_
-MGZGK9\.\OKN8W%/B<X#$^RPC9#^J\.NBC^)YP#3!?'>&$DE7KAL6F'2YVNM%
-MK1??*[;T7&0=;/B.5;F>J0QQ=Q=?N-`7(3P3X"N9RI5)<)PS.T@.XX.$?SO_
-M4>ZEOCY^3[NN??Z1!==Z3_,7SYR9?]1^]?:UP7X[8:)F!`4_3-H"X5VLZ@'A
-MO=@S()BJA)(LH*WT<!E<"$^4:FHIYKZ4%$L0JOY+.IZ_4_GR*0ZL1=.AJ7AH
-M#%\MA="#*BA8`>DQ"4$/08C)28PQ'N85-H[!%)4\@S2I7XQG;"\/;_"I2CN1
-MW%IVJ+2G##TC<YA+ED=3%&T/'S913].;@G$)3$C@L21HSQ$#3<K>%&4O&I-2
-ME;UD7,U*JNS1JEE);V*3/$P_PG8+\D6?4#X"2E;\<4_L,7:;5#]4-C[KAUG*
-M%NXN9N_CCE$V2A&O[$_9-+[G;'+W/.&O*!NEL^5;($QSG)43$'>/N)WWZR']
-MD*[C\K$[_:/Z*,7=5U7D-$`/,0=POU5/X<_2^M,[PK>-G0-<Y$7_S5+>X"R@
-MX\[1%%7L+Q1AX1]/:YUW=C0O&9)SJ5%9DJD4LTB:<FU]E,Y2/!=&#$.ZSD$8
-MI0Q1*DLI\4<W9LLA$*$YO?78H/Z>Q`E0+Q"C_;`2AP3`TZ@*(V@E&_\M^'N$
-MZLFM#)$&.BGDIH%$0VB%51+!%?*RD<BBV$3#*KR)?W>_8\X^A_5]1XD7'!'/
-MCO?B$]+)PD^<T))*S2&!=40<2<#$];^W87')G5.X3SI=>,8)%Z1"%><[@ID_
-M,MX5.3[<_5//#3&#H.6/&,4ED2G*4T5]"Q<LTN0N2N+FT'!9*E+)#A`RHA(Y
-M2(9MY*A"%%2O/A_APK8(QPDF(8]"E;C)H1.71$FWZ;4_$/(08X!H0L(\"%<1
-M"H3P93YA45B(3/J?1?Z-&<,_`TTU%1+BSK@F^DVDE'G&+\WR!7(4PE\X:;=:
-M;XH53#3MH07H=S\4M<BNG0,9#SEK(,:ZOUX'RU,O5OA7/8R]DV8;YLSRIV&U
-M9-=TU&%GN')ZVKAM,=F=,\E6>7\X(^](_%XVR_LFZ5W3T>^:HO_7:(*^<29Z
-M49OV4MOK9^0_4#*[[9.YA,WR2HO\<:+LF.VY_,?_I0:965Y&-)BI`EEL&4I\
-MS++3(N_X?S7.S/*KL_"?O(:9*L^9%3#+YEEY/,WW3'AI+7)50L7L:>;C!G>#
-M>U[;L82V+]A[ZT^+[$HP2WXYO6J/)D7.[3&V&@4!;.7-!XWV<J`K!8>-9#=U
-MTGC(>&AUP^H'L5@8$Q;+%6[+R`%J+NXG@$1@3"-\J1"&I)`3P3+H9,5"$D[5
-M9Q%H<`V-),H,`XL]@2(^4&@(2`R@R+2TV-8W>4%CP,G8JFDO\-NJ&2^H#RS2
-M!Q82B,8+UAQ8ZP4K`RY&LX&@+T_:0;[=@9*L0+%^OYL>_L`+I+G'"2Q7[9WS
-M`E$7(KW,?6[#?C?##I"V2:^^1J,C7<,H:4!N`E+(\^-287V37=O$I+`MS@*4
-MUT7G=Z&,7CJS%Q5TT8XNE-5+9_>VUK35'JR+[2L`#9")]46OJM>CEA6K>7NU
-MK:>FMU:L%NS58D]=[UI?]-MX[/LU'IN'[&A<\@)#4&#0!&DP09%!CR4PM?X,
-MV>$X)I&=C,.)6$.DX6,\M>>`@G:R)F".JS3'59'CJLQQO1FO[Q>/_?'??V!C
-M8?%-G@G2M)MN66=G*EA0ILZZ0&BK],T^&FUF0P)90%%*:K,/DE55E=#LH\(V
-M(O-:0IZ:<WS=`^TPIP6>K?YMS0U!?L5:OF)Y>>WK2S&?4_Y.P[86?L7.!OZM
-M#7MXOHB77"6XN,2YB%]=4<,78NSB@XW\9O^VAMT%&YH;?)O\S0U;&OT[FPM\
-MP>TECJW![7Y';-2QR[%Y5WU1`:YO\N_</#^/KR-(#82VQKE[-X\Q&9$*,.;S
-6>8ET,/DRTA1`S>E__P.PN$K4G'$`````
-`
-end
diff --git a/sys/dev/cxgb/ulp/toecore/toedev.h b/sys/dev/cxgb/ulp/toecore/toedev.h
index 1cdde5ac278d..edf0263f4c65 100644
--- a/sys/dev/cxgb/ulp/toecore/toedev.h
+++ b/sys/dev/cxgb/ulp/toecore/toedev.h
@@ -72,8 +72,8 @@ struct offload_id {
unsigned long data;
};
-struct rtentry;
struct ifnet;
+struct rt_entry;
struct tom_info;
struct sysctl_oid;
struct socket;