Synchronize with version 1.0.071 of Chelsio's common code

(with the notable exception of improvements for using multiple TX queues)

This adds support for the T3B2 ASIC rev

Obtained from: Chelsio
MFC after: 3 days
This commit is contained in:
kmacy 2007-03-20 21:43:32 +00:00
parent 9c3aae9403
commit febce07b18
10 changed files with 364 additions and 58 deletions

View File

@ -45,6 +45,7 @@ enum {
TCB_SIZE = 128, /* TCB size */
NMTUS = 16, /* size of MTU table */
NCCTRL_WIN = 32, /* # of congestion control windows */
NTX_SCHED = 8, /* # of HW Tx scheduling queues */
};
#define MAX_RX_COALESCING_LEN 16224U
@ -68,6 +69,12 @@ enum { /* adapter interrupt-maintained statistics */
IRQ_NUM_STATS /* keep last */
};
enum {
FW_VERSION_MAJOR = 3,
FW_VERSION_MINOR = 2,
FW_VERSION_MICRO = 0
};
enum {
SGE_QSETS = 8, /* # of SGE Tx/Rx/RspQ sets */
SGE_RXQ_PER_SET = 2, /* # of Rx queues per set */
@ -203,6 +210,9 @@ struct mac_stats {
unsigned long serdes_signal_loss;
unsigned long xaui_pcs_ctc_err;
unsigned long xaui_pcs_align_change;
unsigned long num_toggled; /* # times toggled TxEn due to stuck TX */
unsigned long num_resets; /* # times reset due to stuck TX */
};
struct tp_mib_stats {
@ -261,6 +271,7 @@ struct tp_params {
unsigned int rx_num_pgs; /* # of Rx pages */
unsigned int tx_num_pgs; /* # of Tx pages */
unsigned int ntimer_qs; /* # of timer queues */
unsigned int dack_re; /* DACK timer resolution */
};
struct qset_params { /* SGE queue set parameters */
@ -271,6 +282,7 @@ struct qset_params { /* SGE queue set parameters */
unsigned int jumbo_size; /* # of entries in jumbo free list */
unsigned int txq_size[SGE_TXQ_PER_SET]; /* Tx queue sizes */
unsigned int cong_thres; /* FL congestion threshold */
unsigned int vector; /* Interrupt (line or vector) number */
};
struct sge_params {
@ -344,6 +356,12 @@ struct adapter_params {
unsigned int rev; /* chip revision */
};
enum { /* chip revisions */
T3_REV_A = 0,
T3_REV_B = 2,
T3_REV_B2 = 3,
};
struct trace_params {
u32 sip;
u32 sip_mask;
@ -409,6 +427,10 @@ struct cmac {
adapter_t *adapter;
unsigned int offset;
unsigned int nucast; /* # of address filters for unicast MACs */
unsigned int tcnt;
unsigned int xcnt;
unsigned int toggle_cnt;
unsigned int txen;
struct mac_stats stats;
};
@ -544,6 +566,12 @@ static inline unsigned int core_ticks_per_usec(const adapter_t *adap)
return adap->params.vpd.cclk / 1000;
}
static inline unsigned int dack_ticks_to_usec(const adapter_t *adap,
unsigned int ticks)
{
return (ticks << adap->params.tp.dack_re) / core_ticks_per_usec(adap);
}
static inline unsigned int is_pcie(const adapter_t *adap)
{
return adap->params.pci.variant == PCI_VARIANT_PCIE;
@ -622,6 +650,7 @@ int t3_mac_set_num_ucast(struct cmac *mac, int n);
const struct mac_stats *t3_mac_update_stats(struct cmac *mac);
int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex,
int fc);
int t3b2_mac_watchdog_task(struct cmac *mac);
void t3_mc5_prep(adapter_t *adapter, struct mc5 *mc5, int mode);
int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters,
@ -644,6 +673,12 @@ void t3_get_cong_cntl_tab(adapter_t *adap,
void t3_config_trace_filter(adapter_t *adapter, const struct trace_params *tp,
int filter_index, int invert, int enable);
int t3_config_sched(adapter_t *adap, unsigned int kbps, int sched);
int t3_set_sched_ipg(adapter_t *adap, int sched, unsigned int ipg);
void t3_get_tx_sched(adapter_t *adap, unsigned int sched, unsigned int *kbps,
unsigned int *ipg);
void t3_read_pace_tbl(adapter_t *adap, unsigned int pace_vals[NTX_SCHED]);
void t3_set_pace_tbl(adapter_t *adap, unsigned int *pace_vals,
unsigned int start, unsigned int n);
#endif
void t3_sge_prep(adapter_t *adap, struct sge_params *p);

View File

@ -4163,8 +4163,8 @@ POSSIBILITY OF SUCH DAMAGE.
#define V_TX_MOD_WEIGHT(x) ((x) << S_TX_MOD_WEIGHT)
#define G_TX_MOD_WEIGHT(x) (((x) >> S_TX_MOD_WEIGHT) & M_TX_MOD_WEIGHT)
#define S_TX_MOD_TIMER_MODE 9
#define M_TX_MOD_TIMER_MODE 0x7f
#define S_TX_MOD_TIMER_MODE 8
#define M_TX_MOD_TIMER_MODE 0xff
#define V_TX_MOD_TIMER_MODE(x) ((x) << S_TX_MOD_TIMER_MODE)
#define G_TX_MOD_TIMER_MODE(x) (((x) >> S_TX_MOD_TIMER_MODE) & M_TX_MOD_TIMER_MODE)

View File

@ -684,7 +684,8 @@ enum {
SF_ERASE_SECTOR = 0xd8, /* erase sector */
FW_FLASH_BOOT_ADDR = 0x70000, /* start address of FW in flash */
FW_VERS_ADDR = 0x77ffc /* flash address holding FW version */
FW_VERS_ADDR = 0x77ffc, /* flash address holding FW version */
FW_MIN_SIZE = 8 /* at least version and csum */
};
/**
@ -887,12 +888,13 @@ int t3_check_fw_version(adapter_t *adapter)
major = G_FW_VERSION_MAJOR(vers);
minor = G_FW_VERSION_MINOR(vers);
if (type == FW_VERSION_T3 && major == CHELSIO_FW_MAJOR && minor == CHELSIO_FW_MINOR)
if (type == FW_VERSION_T3 && major == FW_VERSION_MAJOR &&
minor == FW_VERSION_MINOR)
return 0;
CH_ERR(adapter, "found wrong FW version(%u.%u), "
"driver needs version %d.%d\n", major, minor,
CHELSIO_FW_MAJOR, CHELSIO_FW_MINOR);
FW_VERSION_MAJOR, FW_VERSION_MINOR);
return -EINVAL;
}
@ -937,7 +939,7 @@ int t3_load_fw(adapter_t *adapter, const u8 *fw_data, unsigned int size)
const u32 *p = (const u32 *)fw_data;
int ret, addr, fw_sector = FW_FLASH_BOOT_ADDR >> 16;
if (size & 3)
if ((size & 3) || (size < FW_MIN_SIZE))
return -EINVAL;
if (size > FW_VERS_ADDR + 8 - FW_FLASH_BOOT_ADDR)
return -EFBIG;
@ -1558,7 +1560,6 @@ int t3_slow_intr_handler(adapter_t *adapter)
if (!cause)
return 0;
printf("slow intr handler\n");
if (cause & F_PCIM0) {
if (is_pcie(adapter))
pcie_intr_handler(adapter);
@ -2353,7 +2354,7 @@ static void tp_config(adapter_t *adap, const struct tp_params *p)
F_TCPCHECKSUMOFFLOAD | V_IPTTL(64));
t3_write_reg(adap, A_TP_TCP_OPTIONS, V_MTUDEFAULT(576) |
F_MTUENABLE | V_WINDOWSCALEMODE(1) |
V_TIMESTAMPSMODE(1) | V_SACKMODE(1) | V_SACKRX(1));
V_TIMESTAMPSMODE(0) | V_SACKMODE(1) | V_SACKRX(1));
t3_write_reg(adap, A_TP_DACK_CONFIG, V_AUTOSTATE3(1) |
V_AUTOSTATE2(1) | V_AUTOSTATE1(0) |
V_BYTETHRESHOLD(16384) | V_MSSTHRESHOLD(2) |
@ -2380,13 +2381,14 @@ static void tp_config(adapter_t *adap, const struct tp_params *p)
} else
t3_set_reg_field(adap, A_TP_PARA_REG3, 0, F_TXPACEFIXED);
t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0x12121212);
t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0x12121212);
t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0x1212);
t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0);
t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0);
t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0);
t3_write_reg(adap, A_TP_MOD_RATE_LIMIT, 0);
}
/* Desired TP timer resolution in usec */
#define TP_TMR_RES 50
#define TP_TMR_RES 200
/* TCP timer values in ms */
#define TP_DACK_TIMER 50
@ -2403,7 +2405,7 @@ static void tp_config(adapter_t *adap, const struct tp_params *p)
static void tp_set_timers(adapter_t *adap, unsigned int core_clk)
{
unsigned int tre = fls(core_clk / (1000000 / TP_TMR_RES)) - 1;
unsigned int dack_re = fls(core_clk / 5000) - 1; /* 200us */
unsigned int dack_re = adap->params.tp.dack_re;
unsigned int tstamp_re = fls(core_clk / 1000); /* 1ms, at least */
unsigned int tps = core_clk >> tre;
@ -2489,10 +2491,11 @@ static void __devinit init_mtus(unsigned short mtus[])
* are enabled and still have at least 8 bytes of payload.
*/
mtus[0] = 88;
mtus[1] = 256;
mtus[2] = 512;
mtus[3] = 576;
mtus[4] = 808;
mtus[1] = 88; /* workaround for silicon starting at 1 */
mtus[2] = 256;
mtus[3] = 512;
mtus[4] = 576;
/* mtus[4] = 808; */
mtus[5] = 1024;
mtus[6] = 1280;
mtus[7] = 1492;
@ -2648,6 +2651,42 @@ void t3_tp_get_mib_stats(adapter_t *adap, struct tp_mib_stats *tps)
sizeof(*tps) / sizeof(u32), 0);
}
/**
* t3_read_pace_tbl - read the pace table
* @adap: the adapter
* @pace_vals: holds the returned values
*
* Returns the values of TP's pace table in nanoseconds.
*/
void t3_read_pace_tbl(adapter_t *adap, unsigned int pace_vals[NTX_SCHED])
{
unsigned int i, tick_ns = dack_ticks_to_usec(adap, 1000);
for (i = 0; i < NTX_SCHED; i++) {
t3_write_reg(adap, A_TP_PACE_TABLE, 0xffff0000 + i);
pace_vals[i] = t3_read_reg(adap, A_TP_PACE_TABLE) * tick_ns;
}
}
/**
* t3_set_pace_tbl - set the pace table
* @adap: the adapter
* @pace_vals: the pace values in nanoseconds
* @start: index of the first entry in the HW pace table to set
* @n: how many entries to set
*
* Sets (a subset of the) HW pace table.
*/
void t3_set_pace_tbl(adapter_t *adap, unsigned int *pace_vals,
unsigned int start, unsigned int n)
{
unsigned int tick_ns = dack_ticks_to_usec(adap, 1000);
for ( ; n; n--, start++, pace_vals++)
t3_write_reg(adap, A_TP_PACE_TABLE, (start << 16) |
((*pace_vals + tick_ns / 2) / tick_ns));
}
#define ulp_region(adap, name, start, len) \
t3_write_reg((adap), A_ULPRX_ ## name ## _LLIMIT, (start)); \
t3_write_reg((adap), A_ULPRX_ ## name ## _ULIMIT, \
@ -2712,7 +2751,7 @@ void t3_config_trace_filter(adapter_t *adapter, const struct trace_params *tp,
* @kbps: target rate in Kbps
* @sched: the scheduler index
*
* Configure a HW scheduler for the target rate
* Configure a Tx HW scheduler for the target rate.
*/
int t3_config_sched(adapter_t *adap, unsigned int kbps, int sched)
{
@ -2750,6 +2789,75 @@ int t3_config_sched(adapter_t *adap, unsigned int kbps, int sched)
return 0;
}
/**
* t3_set_sched_ipg - set the IPG for a Tx HW packet rate scheduler
* @adap: the adapter
* @sched: the scheduler index
* @ipg: the interpacket delay in tenths of nanoseconds
*
* Set the interpacket delay for a HW packet rate scheduler.
*/
int t3_set_sched_ipg(adapter_t *adap, int sched, unsigned int ipg)
{
unsigned int v, addr = A_TP_TX_MOD_Q1_Q0_TIMER_SEPARATOR - sched / 2;
/* convert ipg to nearest number of core clocks */
ipg *= core_ticks_per_usec(adap);
ipg = (ipg + 5000) / 10000;
if (ipg > 0xffff)
return -EINVAL;
t3_write_reg(adap, A_TP_TM_PIO_ADDR, addr);
v = t3_read_reg(adap, A_TP_TM_PIO_DATA);
if (sched & 1)
v = (v & 0xffff) | (ipg << 16);
else
v = (v & 0xffff0000) | ipg;
t3_write_reg(adap, A_TP_TM_PIO_DATA, v);
t3_read_reg(adap, A_TP_TM_PIO_DATA);
return 0;
}
/**
* t3_get_tx_sched - get the configuration of a Tx HW traffic scheduler
* @adap: the adapter
* @sched: the scheduler index
* @kbps: the byte rate in Kbps
* @ipg: the interpacket delay in tenths of nanoseconds
*
* Return the current configuration of a HW Tx scheduler.
*/
void t3_get_tx_sched(adapter_t *adap, unsigned int sched, unsigned int *kbps,
unsigned int *ipg)
{
unsigned int v, addr, bpt, cpt;
if (kbps) {
addr = A_TP_TX_MOD_Q1_Q0_RATE_LIMIT - sched / 2;
t3_write_reg(adap, A_TP_TM_PIO_ADDR, addr);
v = t3_read_reg(adap, A_TP_TM_PIO_DATA);
if (sched & 1)
v >>= 16;
bpt = (v >> 8) & 0xff;
cpt = v & 0xff;
if (!cpt)
*kbps = 0; /* scheduler disabled */
else {
v = (adap->params.vpd.cclk * 1000) / cpt;
*kbps = (v * bpt) / 125;
}
}
if (ipg) {
addr = A_TP_TX_MOD_Q1_Q0_TIMER_SEPARATOR - sched / 2;
t3_write_reg(adap, A_TP_TM_PIO_ADDR, addr);
v = t3_read_reg(adap, A_TP_TM_PIO_DATA);
if (sched & 1)
v >>= 16;
v &= 0xffff;
*ipg = (10000 * v) / core_ticks_per_usec(adap);
}
}
static int tp_init(adapter_t *adap, const struct tp_params *p)
{
int busy = 0;
@ -3249,10 +3357,11 @@ void early_hw_init(adapter_t *adapter, const struct adapter_info *ai)
*/
int t3_reset_adapter(adapter_t *adapter)
{
int i;
uint16_t devid = 0;
int i, save_and_restore_pcie =
adapter->params.rev < T3_REV_B2 && is_pcie(adapter);
uint16_t devid = 0;
if (is_pcie(adapter))
if (save_and_restore_pcie)
t3_os_pci_save_state(adapter);
t3_write_reg(adapter, A_PL_RST, F_CRSTWRM | F_CRSTWRMMODE);
@ -3270,7 +3379,7 @@ int t3_reset_adapter(adapter_t *adapter)
if (devid != 0x1425)
return -1;
if (is_pcie(adapter))
if (save_and_restore_pcie)
t3_os_pci_restore_state(adapter);
return 0;
}
@ -3325,6 +3434,7 @@ int __devinit t3_prep_adapter(adapter_t *adapter,
p->tx_num_pgs = pm_num_pages(p->chan_tx_size, p->tx_pg_size);
p->ntimer_qs = p->cm_size >= (128 << 20) ||
adapter->params.rev > 0 ? 12 : 6;
p->dack_re = fls(adapter->params.vpd.cclk / 10) - 1; /* 100us */
adapter->params.mc5.nservers = DEFAULT_NSERVERS;
adapter->params.mc5.nfilters = adapter->params.rev > 0 ?

View File

@ -32,10 +32,14 @@ POSSIBILITY OF SUCH DAMAGE.
$FreeBSD$
***************************************************************************/
/*
* Note that although this driver doesn't contain all of the functionality of the Linux driver
* the common code is 99% the same. Hence we keep the same version number to indicate what linux
* driver the common code corresponds to.
*/
#ifndef __CHELSIO_VERSION_H
#define __CHELSIO_VERSION_H
#define DRV_DESC "Chelsio T3 Network Driver"
#define DRV_NAME "cxgb"
#define DRV_VERSION "1.0"
#define DRV_VERSION "1.0.071"
#endif

View File

@ -129,9 +129,6 @@ int t3_mac_reset(struct cmac *mac)
xaui_serdes_reset(mac);
}
if (adap->params.rev > 0)
t3_write_reg(adap, A_XGM_PAUSE_TIMER + oft, 0xf000);
val = F_MAC_RESET_;
if (is_10G(adap))
val |= F_PCS_RESET_;
@ -150,6 +147,62 @@ int t3_mac_reset(struct cmac *mac)
return 0;
}
static int t3b2_mac_reset(struct cmac *mac)
{
u32 val;
adapter_t *adap = mac->adapter;
unsigned int oft = mac->offset;
/* Stop egress traffic to xgm*/
if (!macidx(mac))
t3_set_reg_field(adap, A_MPS_CFG, F_PORT0ACTIVE, 0);
else
t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE, 0);
/* PCS in reset */
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);
/* Check for xgm Rx fifo empty */
if (t3_wait_op_done(adap, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + oft,
0x80000000, 1, 5, 2)) {
CH_ERR(adap, "MAC %d Rx fifo drain failed\n",
macidx(mac));
return -1;
}
t3_write_reg(adap, A_XGM_RESET_CTRL + oft, 0); /*MAC in reset*/
(void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
val = F_MAC_RESET_;
if (is_10G(adap))
val |= F_PCS_RESET_;
else if (uses_xaui(adap))
val |= F_PCS_RESET_ | F_XG2G_RESET_;
else
val |= F_RGMII_RESET_ | F_XG2G_RESET_;
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);
t3b_pcs_reset(mac);
}
t3_write_reg(adap, A_XGM_RX_CFG + oft,
F_DISPAUSEFRAMES | F_EN1536BFRAMES |
F_RMFCS | F_ENJUMBO | F_ENHASHMCAST );
/*Resume egress traffic to xgm*/
if (!macidx(mac))
t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT0ACTIVE);
else
t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT1ACTIVE);
return 0;
}
/*
* Set the exact match register 'idx' to recognize the given Ethernet address.
*/
@ -256,9 +309,10 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
* Adjust the PAUSE frame watermarks. We always set the LWM, and the
* HWM only if flow-control is enabled.
*/
hwm = max(MAC_RXFIFO_SIZE - 3 * mtu, MAC_RXFIFO_SIZE / 2U);
hwm = min(hwm, 3 * MAC_RXFIFO_SIZE / 4 + 1024);
lwm = hwm - 1024;
hwm = max_t(unsigned int, MAC_RXFIFO_SIZE - 3 * mtu,
MAC_RXFIFO_SIZE * 38 / 100);
hwm = min(hwm, MAC_RXFIFO_SIZE - 8192);
lwm = min(3 * (int) mtu, MAC_RXFIFO_SIZE /4);
v = t3_read_reg(adap, A_XGM_RXFIFO_CFG + mac->offset);
v &= ~V_RXFIFOPAUSELWM(M_RXFIFOPAUSELWM);
v |= V_RXFIFOPAUSELWM(lwm / 8);
@ -275,8 +329,16 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
thres = mtu > thres ? (mtu - thres + 7) / 8 : 0;
thres = max(thres, 8U); /* need at least 8 */
t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + mac->offset,
V_TXFIFOTHRESH(M_TXFIFOTHRESH),
V_TXFIFOTHRESH(thres));
V_TXFIFOTHRESH(M_TXFIFOTHRESH) | V_TXIPG(M_TXIPG),
V_TXFIFOTHRESH(thres) | V_TXIPG(1));
/* Assuming a minimum drain rate of 2.5Gbps...
*/
if (adap->params.rev > 0)
t3_write_reg(adap, A_XGM_PAUSE_TIMER + mac->offset,
(hwm-lwm) * 4 / 8);
t3_write_reg(adap, A_XGM_TX_PAUSE_QUANTA + mac->offset,
MAC_RXFIFO_SIZE * 4 * 8 / 512);
return 0;
}
@ -303,13 +365,13 @@ int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc)
t3_set_reg_field(adap, A_XGM_PORT_CFG + oft,
V_PORTSPEED(M_PORTSPEED), val);
}
#if 0
val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft);
val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM);
if (fc & PAUSE_TX)
val |= V_RXFIFOPAUSEHWM(G_RXFIFOPAUSELWM(val) + 128); /* +1KB */
t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val);
#endif
t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN,
(fc & PAUSE_RX) ? F_TXPAUSEEN : 0);
return 0;
@ -324,9 +386,15 @@ int t3_mac_enable(struct cmac *mac, int 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, 0xbf000001);
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_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + idx);
mac->tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap, A_TP_PIO_DATA)));
mac->xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, A_XGM_TX_SPI4_SOP_EOP_CNT)));
mac->txen = F_TXEN;
mac->toggle_cnt = 0;
}
if (which & MAC_DIRECTION_RX)
t3_write_reg(adap, A_XGM_RX_CTRL + oft, F_RXEN);
@ -343,13 +411,45 @@ int t3_mac_disable(struct cmac *mac, int which)
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, 0);
t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx);
mac->txen = 0;
}
if (which & MAC_DIRECTION_RX)
t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0);
return 0;
}
int t3b2_mac_watchdog_task(struct cmac *mac)
{
int status;
unsigned int tcnt, xcnt;
adapter_t *adap = mac->adapter;
t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + macidx(mac));
tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap, A_TP_PIO_DATA)));
xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, A_XGM_TX_SPI4_SOP_EOP_CNT + mac->offset)));
if ((tcnt != mac->tcnt) && (xcnt == 0) && (mac->xcnt == 0)) {
if (mac->toggle_cnt > 4) {
t3b2_mac_reset(mac);
mac->toggle_cnt = 0;
status = 2;
} else {
t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0);
t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */
t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, mac->txen);
t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */
mac->toggle_cnt++;
status = 1;
}
} else {
mac->toggle_cnt = 0;
status = 0;
}
mac->tcnt = tcnt;
mac->xcnt = xcnt;
return status;
}
/*
* This function is called periodically to accumulate the current values of the
* RMON counters into the port statistics. Since the packet counters are only
@ -379,7 +479,11 @@ const struct mac_stats *t3_mac_update_stats(struct cmac *mac)
RMON_UPDATE(mac, rx_symbol_errs, RX_SYM_CODE_ERR_FRAMES);
RMON_UPDATE(mac, rx_too_long, RX_OVERSIZE_FRAMES);
mac->stats.rx_too_long += RMON_READ(mac, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT);
v = RMON_READ(mac, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT);
if (mac->adapter->params.rev == T3_REV_B2)
v &= 0x7fffffff;
mac->stats.rx_too_long += v;
RMON_UPDATE(mac, rx_frames_64, RX_64B_FRAMES);
RMON_UPDATE(mac, rx_frames_65_127, RX_65_127B_FRAMES);

View File

@ -71,7 +71,6 @@ struct port_info {
struct cphy phy;
struct cmac mac;
struct link_config link_config;
int activity;
struct ifmedia media;
struct mtx lock;

View File

@ -38,8 +38,6 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef CONFIG_DEFINED
#define CONFIG_CHELSIO_T3_CORE
#define CHELSIO_FW_MAJOR 3
#define CHELSIO_FW_MINOR 2
#define DEFAULT_JUMBO
#endif

View File

@ -110,6 +110,8 @@ struct ch_qset_params {
int32_t intr_lat;
int32_t polling;
int32_t cong_thres;
int32_t vector;
int32_t qnum;
};
struct ch_pktsched_params {
@ -121,6 +123,16 @@ struct ch_pktsched_params {
uint8_t binding;
};
struct ch_hw_sched {
uint32_t cmd;
uint8_t sched;
int8_t mode;
int8_t channel;
int32_t kbps; /* rate in Kbps */
int32_t class_ipg; /* tenths of nanoseconds */
int32_t flow_ipg; /* usec */
};
#ifndef TCB_SIZE
# define TCB_SIZE 128
#endif

View File

@ -104,7 +104,6 @@ static int setup_sge_qsets(adapter_t *);
static void cxgb_async_intr(void *);
static void cxgb_ext_intr_handler(void *, int);
static void cxgb_tick(void *);
static void check_link_status(adapter_t *sc);
static void setup_rss(adapter_t *sc);
/* Attachment glue for the PCI controller end of the device. Each port of
@ -278,7 +277,8 @@ cxgb_fw_download(adapter_t *sc, device_t dev)
#endif
int status;
snprintf(&buf[0], sizeof(buf), "t3fw%d%d", CHELSIO_FW_MAJOR, CHELSIO_FW_MINOR);
snprintf(&buf[0], sizeof(buf), "t3fw%d%d", FW_VERSION_MAJOR,
FW_VERSION_MINOR);
fw = firmware_get(buf);
@ -395,7 +395,7 @@ cxgb_controller_attach(device_t dev)
/* Create a periodic callout for checking adapter status */
callout_init_mtx(&sc->cxgb_tick_ch, &sc->lock, 0);
callout_init_mtx(&sc->cxgb_tick_ch, &sc->lock, CALLOUT_RETURNUNLOCKED);
ai = cxgb_get_adapter_info(dev);
if (t3_prep_adapter(sc, ai, 1) < 0) {
@ -407,7 +407,7 @@ cxgb_controller_attach(device_t dev)
* Warn user that a firmware update will be attempted in init.
*/
device_printf(dev, "firmware needs to be updated to version %d.%d\n",
CHELSIO_FW_MAJOR, CHELSIO_FW_MINOR);
FW_VERSION_MAJOR, FW_VERSION_MINOR);
sc->flags &= ~FW_UPTODATE;
} else {
sc->flags |= FW_UPTODATE;
@ -1090,7 +1090,7 @@ cxgb_init_locked(struct port_info *p)
ifp = p->ifp;
if ((sc->flags & FW_UPTODATE) == 0) {
device_printf(sc->dev, "updating firmware to version %d.%d\n",
CHELSIO_FW_MAJOR, CHELSIO_FW_MINOR);
FW_VERSION_MAJOR, FW_VERSION_MINOR);
if ((error = cxgb_fw_download(sc, sc->dev)) != 0) {
device_printf(sc->dev, "firmware download failed err: %d"
"interface will be unavailable\n", error);
@ -1392,19 +1392,6 @@ cxgb_ext_intr_handler(void *arg, int count)
}
}
static void
cxgb_tick(void *arg)
{
adapter_t *sc = (adapter_t *)arg;
const struct adapter_params *p = &sc->params;
if (p->linkpoll_period)
check_link_status(sc);
callout_reset(&sc->cxgb_tick_ch, sc->params.stats_update_period * hz,
cxgb_tick, sc);
}
static void
check_link_status(adapter_t *sc)
{
@ -1418,6 +1405,61 @@ check_link_status(adapter_t *sc)
}
}
static void
check_t3b2_mac(struct adapter *adapter)
{
int i;
for_each_port(adapter, i) {
struct port_info *p = &adapter->port[i];
struct ifnet *ifp = p->ifp;
int status;
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
continue;
status = 0;
PORT_LOCK(p);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING))
status = t3b2_mac_watchdog_task(&p->mac);
if (status == 1)
p->mac.stats.num_toggled++;
else if (status == 2) {
struct cmac *mac = &p->mac;
t3_mac_set_mtu(mac, ifp->if_mtu);
t3_mac_set_address(mac, 0, p->hw_addr);
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);
p->mac.stats.num_resets++;
}
PORT_UNLOCK(p);
}
}
static void
cxgb_tick(void *arg)
{
adapter_t *sc = (adapter_t *)arg;
const struct adapter_params *p = &sc->params;
if (p->linkpoll_period)
check_link_status(sc);
callout_reset(&sc->cxgb_tick_ch, sc->params.stats_update_period * hz,
cxgb_tick, sc);
/*
* adapter lock can currently only be acquire after the
* port lock
*/
ADAPTER_UNLOCK(sc);
if (p->rev == T3_REV_B2)
check_t3b2_mac(sc);
}
static int
in_range(int val, int lo, int hi)
{

View File

@ -141,6 +141,8 @@ static const int debug_flags = DBG_RX;
#define t3_os_sleep(x) DELAY((x) * 1000)
#define max_t(type, a, b) (type)max((a), (b))
/* Standard PHY definitions */
#define BMCR_LOOPBACK BMCR_LOOP
#define BMCR_ISOLATE BMCR_ISO