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:
parent
9c3aae9403
commit
febce07b18
@ -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);
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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 ?
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user