1*d39a76e7Sxw161283 /* 2*d39a76e7Sxw161283 * CDDL HEADER START 3*d39a76e7Sxw161283 * 4*d39a76e7Sxw161283 * The contents of this file are subject to the terms of the 5*d39a76e7Sxw161283 * Common Development and Distribution License (the "License"). 6*d39a76e7Sxw161283 * You may not use this file except in compliance with the License. 7*d39a76e7Sxw161283 * 8*d39a76e7Sxw161283 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*d39a76e7Sxw161283 * or http://www.opensolaris.org/os/licensing. 10*d39a76e7Sxw161283 * See the License for the specific language governing permissions 11*d39a76e7Sxw161283 * and limitations under the License. 12*d39a76e7Sxw161283 * 13*d39a76e7Sxw161283 * When distributing Covered Code, include this CDDL HEADER in each 14*d39a76e7Sxw161283 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*d39a76e7Sxw161283 * If applicable, add the following below this CDDL HEADER, with the 16*d39a76e7Sxw161283 * fields enclosed by brackets "[]" replaced with your own identifying 17*d39a76e7Sxw161283 * information: Portions Copyright [yyyy] [name of copyright owner] 18*d39a76e7Sxw161283 * 19*d39a76e7Sxw161283 * CDDL HEADER END 20*d39a76e7Sxw161283 */ 21*d39a76e7Sxw161283 22*d39a76e7Sxw161283 /* 23*d39a76e7Sxw161283 * Copyright (C) 2003-2005 Chelsio Communications. All rights reserved. 24*d39a76e7Sxw161283 */ 25*d39a76e7Sxw161283 26*d39a76e7Sxw161283 #pragma ident "%Z%%M% %I% %E% SMI" /* tp.c */ 27*d39a76e7Sxw161283 28*d39a76e7Sxw161283 #include "common.h" 29*d39a76e7Sxw161283 #include "regs.h" 30*d39a76e7Sxw161283 #include "tp.h" 31*d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G 32*d39a76e7Sxw161283 #include "fpga_defs.h" 33*d39a76e7Sxw161283 #endif 34*d39a76e7Sxw161283 35*d39a76e7Sxw161283 struct petp { 36*d39a76e7Sxw161283 adapter_t *adapter; 37*d39a76e7Sxw161283 }; 38*d39a76e7Sxw161283 39*d39a76e7Sxw161283 /* Pause deadlock avoidance parameters */ 40*d39a76e7Sxw161283 #define DROP_MSEC 16 41*d39a76e7Sxw161283 #define DROP_PKTS_CNT 1 42*d39a76e7Sxw161283 43*d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD 44*d39a76e7Sxw161283 45*d39a76e7Sxw161283 static inline u32 pm_num_pages(u32 size, u32 pg_size) 46*d39a76e7Sxw161283 { 47*d39a76e7Sxw161283 u32 num = size / pg_size; 48*d39a76e7Sxw161283 num -= num % 24; 49*d39a76e7Sxw161283 return num; 50*d39a76e7Sxw161283 } 51*d39a76e7Sxw161283 52*d39a76e7Sxw161283 static void tp_pm_configure(adapter_t *adapter, struct tp_params *p) 53*d39a76e7Sxw161283 { 54*d39a76e7Sxw161283 u32 num; 55*d39a76e7Sxw161283 56*d39a76e7Sxw161283 num = pm_num_pages(p->pm_size - p->pm_rx_base, p->pm_rx_pg_size); 57*d39a76e7Sxw161283 if (p->pm_rx_num_pgs > num) 58*d39a76e7Sxw161283 p->pm_rx_num_pgs = num; 59*d39a76e7Sxw161283 60*d39a76e7Sxw161283 num = pm_num_pages(p->pm_rx_base - p->pm_tx_base, p->pm_tx_pg_size); 61*d39a76e7Sxw161283 if (p->pm_tx_num_pgs > num) 62*d39a76e7Sxw161283 p->pm_tx_num_pgs = num; 63*d39a76e7Sxw161283 64*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_PM_SIZE, p->pm_size); 65*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_PM_RX_BASE, p->pm_rx_base); 66*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_PM_TX_BASE, p->pm_tx_base); 67*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_PM_DEFRAG_BASE, p->pm_size); 68*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_PM_RX_PG_SIZE, p->pm_rx_pg_size); 69*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_PM_RX_MAX_PGS, p->pm_rx_num_pgs); 70*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_PM_TX_PG_SIZE, p->pm_tx_pg_size); 71*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_PM_TX_MAX_PGS, p->pm_tx_num_pgs); 72*d39a76e7Sxw161283 } 73*d39a76e7Sxw161283 74*d39a76e7Sxw161283 static void tp_cm_configure(adapter_t *adapter, u32 cm_size) 75*d39a76e7Sxw161283 { 76*d39a76e7Sxw161283 u32 mm_base = (cm_size >> 1); 77*d39a76e7Sxw161283 u32 mm_sub_size = (cm_size >> 5); 78*d39a76e7Sxw161283 79*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_CM_SIZE, cm_size); 80*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_CM_MM_BASE, mm_base); 81*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_CM_TIMER_BASE, (cm_size >> 2) * 3); 82*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_CM_MM_P_FLST_BASE, 83*d39a76e7Sxw161283 mm_base + 5 * mm_sub_size); 84*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_CM_MM_TX_FLST_BASE, 85*d39a76e7Sxw161283 mm_base + 6 * mm_sub_size); 86*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_CM_MM_RX_FLST_BASE, 87*d39a76e7Sxw161283 mm_base + 7 * mm_sub_size); 88*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_CM_MM_MAX_P, 0x40000); 89*d39a76e7Sxw161283 } 90*d39a76e7Sxw161283 91*d39a76e7Sxw161283 static unsigned int tp_delayed_ack_ticks(adapter_t *adap, unsigned int tp_clk) 92*d39a76e7Sxw161283 { 93*d39a76e7Sxw161283 u32 tr = t1_read_reg_4(adap, A_TP_TIMER_RESOLUTION); 94*d39a76e7Sxw161283 95*d39a76e7Sxw161283 return tp_clk / (1 << G_DELAYED_ACK_TIMER_RESOLUTION(tr)); 96*d39a76e7Sxw161283 } 97*d39a76e7Sxw161283 98*d39a76e7Sxw161283 static unsigned int t1_tp_ticks_per_sec(adapter_t *adap, unsigned int tp_clk) 99*d39a76e7Sxw161283 { 100*d39a76e7Sxw161283 u32 tr = t1_read_reg_4(adap, A_TP_TIMER_RESOLUTION); 101*d39a76e7Sxw161283 102*d39a76e7Sxw161283 return tp_clk / (1 << G_GENERIC_TIMER_RESOLUTION(tr)); 103*d39a76e7Sxw161283 } 104*d39a76e7Sxw161283 105*d39a76e7Sxw161283 static void tp_set_tcp_time_params(adapter_t *adapter, unsigned int tp_clk) 106*d39a76e7Sxw161283 { 107*d39a76e7Sxw161283 u32 tps = t1_tp_ticks_per_sec(adapter, tp_clk); 108*d39a76e7Sxw161283 u32 tp_scnt; 109*d39a76e7Sxw161283 110*d39a76e7Sxw161283 #define SECONDS * tps 111*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_2MSL, (1 SECONDS)/2); 112*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_RXT_MIN, (1 SECONDS)/4); 113*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_RXT_MAX, 64 SECONDS); 114*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_PERS_MIN, (1 SECONDS)/2); 115*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_PERS_MAX, 64 SECONDS); 116*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_KEEP_IDLE, 7200 SECONDS); 117*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_KEEP_INTVL, 75 SECONDS); 118*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_INIT_SRTT, 3 SECONDS); 119*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_FINWAIT2_TIME, 60 SECONDS); 120*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_FAST_FINWAIT2_TIME, 3 SECONDS); 121*d39a76e7Sxw161283 #undef SECONDS 122*d39a76e7Sxw161283 123*d39a76e7Sxw161283 /* Set Retransmission shift max */ 124*d39a76e7Sxw161283 tp_scnt = t1_read_reg_4(adapter, A_TP_SHIFT_CNT); 125*d39a76e7Sxw161283 tp_scnt &= (~V_RETRANSMISSION_MAX(0x3f)); 126*d39a76e7Sxw161283 tp_scnt |= V_RETRANSMISSION_MAX(14); 127*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_SHIFT_CNT, tp_scnt); 128*d39a76e7Sxw161283 129*d39a76e7Sxw161283 /* Set DACK timer to 200ms */ 130*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_DACK_TIME, 131*d39a76e7Sxw161283 tp_delayed_ack_ticks(adapter, tp_clk) / 5); 132*d39a76e7Sxw161283 } 133*d39a76e7Sxw161283 134*d39a76e7Sxw161283 int t1_tp_set_coalescing_size(struct petp *tp, unsigned int size) 135*d39a76e7Sxw161283 { 136*d39a76e7Sxw161283 u32 val; 137*d39a76e7Sxw161283 138*d39a76e7Sxw161283 if (size > TP_MAX_RX_COALESCING_SIZE) 139*d39a76e7Sxw161283 return -EINVAL; 140*d39a76e7Sxw161283 141*d39a76e7Sxw161283 val = t1_read_reg_4(tp->adapter, A_TP_PARA_REG3); 142*d39a76e7Sxw161283 143*d39a76e7Sxw161283 if (tp->adapter->params.nports > 1) 144*d39a76e7Sxw161283 size = 9904; 145*d39a76e7Sxw161283 146*d39a76e7Sxw161283 if (size) { 147*d39a76e7Sxw161283 u32 v = t1_is_T1B(tp->adapter) ? 0 : V_MAX_RX_SIZE(size); 148*d39a76e7Sxw161283 149*d39a76e7Sxw161283 /* Set coalescing size. */ 150*d39a76e7Sxw161283 t1_write_reg_4(tp->adapter, A_TP_PARA_REG2, 151*d39a76e7Sxw161283 V_RX_COALESCE_SIZE(size) | v); 152*d39a76e7Sxw161283 153*d39a76e7Sxw161283 val |= (F_RX_COALESCING_PSH_DELIVER | F_RX_COALESCING_ENABLE); 154*d39a76e7Sxw161283 } else 155*d39a76e7Sxw161283 val &= ~F_RX_COALESCING_ENABLE; 156*d39a76e7Sxw161283 157*d39a76e7Sxw161283 t1_write_reg_4(tp->adapter, A_TP_PARA_REG3, val); 158*d39a76e7Sxw161283 return 0; 159*d39a76e7Sxw161283 } 160*d39a76e7Sxw161283 161*d39a76e7Sxw161283 void t1_tp_get_mib_statistics(adapter_t *adap, struct tp_mib_statistics *tps) 162*d39a76e7Sxw161283 { 163*d39a76e7Sxw161283 u32 *data = (u32 *)tps; 164*d39a76e7Sxw161283 int i; 165*d39a76e7Sxw161283 166*d39a76e7Sxw161283 t1_write_reg_4(adap, A_TP_MIB_INDEX, 0); 167*d39a76e7Sxw161283 168*d39a76e7Sxw161283 for (i = 0; i < sizeof(*tps) / sizeof(u32); i++) 169*d39a76e7Sxw161283 *data++ = t1_read_reg_4(adap, A_TP_MIB_DATA); 170*d39a76e7Sxw161283 } 171*d39a76e7Sxw161283 #endif 172*d39a76e7Sxw161283 173*d39a76e7Sxw161283 static void tp_init(adapter_t *ap, const struct tp_params *p, 174*d39a76e7Sxw161283 unsigned int tp_clk) 175*d39a76e7Sxw161283 { 176*d39a76e7Sxw161283 if (t1_is_asic(ap)) { 177*d39a76e7Sxw161283 u32 val; 178*d39a76e7Sxw161283 179*d39a76e7Sxw161283 val = F_TP_IN_CSPI_CPL | F_TP_IN_CSPI_CHECK_IP_CSUM | 180*d39a76e7Sxw161283 F_TP_IN_CSPI_CHECK_TCP_CSUM | F_TP_IN_ESPI_ETHERNET; 181*d39a76e7Sxw161283 if (!p->pm_size) 182*d39a76e7Sxw161283 val |= F_OFFLOAD_DISABLE; 183*d39a76e7Sxw161283 else 184*d39a76e7Sxw161283 val |= F_TP_IN_ESPI_CHECK_IP_CSUM | 185*d39a76e7Sxw161283 F_TP_IN_ESPI_CHECK_TCP_CSUM; 186*d39a76e7Sxw161283 t1_write_reg_4(ap, A_TP_IN_CONFIG, val); 187*d39a76e7Sxw161283 t1_write_reg_4(ap, A_TP_OUT_CONFIG, F_TP_OUT_CSPI_CPL | 188*d39a76e7Sxw161283 F_TP_OUT_ESPI_ETHERNET | 189*d39a76e7Sxw161283 F_TP_OUT_ESPI_GENERATE_IP_CSUM | 190*d39a76e7Sxw161283 F_TP_OUT_ESPI_GENERATE_TCP_CSUM); 191*d39a76e7Sxw161283 t1_write_reg_4(ap, A_TP_GLOBAL_CONFIG, V_IP_TTL(64) | 192*d39a76e7Sxw161283 F_PATH_MTU /* IP DF bit */ | 193*d39a76e7Sxw161283 V_5TUPLE_LOOKUP(p->use_5tuple_mode) | 194*d39a76e7Sxw161283 V_SYN_COOKIE_PARAMETER(29)); 195*d39a76e7Sxw161283 196*d39a76e7Sxw161283 /* 197*d39a76e7Sxw161283 * Enable pause frame deadlock prevention. 198*d39a76e7Sxw161283 */ 199*d39a76e7Sxw161283 if (is_T2(ap) && ap->params.nports > 1) { 200*d39a76e7Sxw161283 u32 drop_ticks = DROP_MSEC * (tp_clk / 1000); 201*d39a76e7Sxw161283 202*d39a76e7Sxw161283 t1_write_reg_4(ap, A_TP_TX_DROP_CONFIG, 203*d39a76e7Sxw161283 F_ENABLE_TX_DROP | F_ENABLE_TX_ERROR | 204*d39a76e7Sxw161283 V_DROP_TICKS_CNT(drop_ticks) | 205*d39a76e7Sxw161283 V_NUM_PKTS_DROPPED(DROP_PKTS_CNT)); 206*d39a76e7Sxw161283 } 207*d39a76e7Sxw161283 208*d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD 209*d39a76e7Sxw161283 t1_write_reg_4(ap, A_TP_GLOBAL_RX_CREDITS, 0xffffffff); 210*d39a76e7Sxw161283 val = V_WINDOW_SCALE(1) | F_MSS | V_DEFAULT_PEER_MSS(576); 211*d39a76e7Sxw161283 212*d39a76e7Sxw161283 /* We don't want timestamps for T204, otherwise we don't know 213*d39a76e7Sxw161283 * the MSS. 214*d39a76e7Sxw161283 */ 215*d39a76e7Sxw161283 if (ap->params.nports == 1) 216*d39a76e7Sxw161283 val |= V_TIMESTAMP(1); 217*d39a76e7Sxw161283 t1_write_reg_4(ap, A_TP_TCP_OPTIONS, val); 218*d39a76e7Sxw161283 t1_write_reg_4(ap, A_TP_DACK_CONFIG, V_DACK_MSS_SELECTOR(1) | 219*d39a76e7Sxw161283 F_DACK_AUTO_CAREFUL | V_DACK_MODE(1)); 220*d39a76e7Sxw161283 t1_write_reg_4(ap, A_TP_BACKOFF0, 0x3020100); 221*d39a76e7Sxw161283 t1_write_reg_4(ap, A_TP_BACKOFF1, 0x7060504); 222*d39a76e7Sxw161283 t1_write_reg_4(ap, A_TP_BACKOFF2, 0xb0a0908); 223*d39a76e7Sxw161283 t1_write_reg_4(ap, A_TP_BACKOFF3, 0xf0e0d0c); 224*d39a76e7Sxw161283 225*d39a76e7Sxw161283 /* We do scheduling in software for T204, increase the cong. 226*d39a76e7Sxw161283 * window to avoid TP holding on to payload longer than we 227*d39a76e7Sxw161283 * expect. 228*d39a76e7Sxw161283 */ 229*d39a76e7Sxw161283 if (ap->params.nports == 1) 230*d39a76e7Sxw161283 t1_write_reg_4(ap, A_TP_PARA_REG0, 0xd1269324); 231*d39a76e7Sxw161283 else 232*d39a76e7Sxw161283 t1_write_reg_4(ap, A_TP_PARA_REG0, 0xd6269324); 233*d39a76e7Sxw161283 t1_write_reg_4(ap, A_TP_SYNC_TIME_HI, 0); 234*d39a76e7Sxw161283 t1_write_reg_4(ap, A_TP_SYNC_TIME_LO, 0); 235*d39a76e7Sxw161283 t1_write_reg_4(ap, A_TP_INT_ENABLE, 0); 236*d39a76e7Sxw161283 t1_write_reg_4(ap, A_TP_CM_FC_MODE, 0); /* Enable CM cache */ 237*d39a76e7Sxw161283 t1_write_reg_4(ap, A_TP_PC_CONGESTION_CNTL, 0x6186); 238*d39a76e7Sxw161283 239*d39a76e7Sxw161283 /* 240*d39a76e7Sxw161283 * Calculate the time between modulation events, which affects 241*d39a76e7Sxw161283 * both the Tx and Rx pipelines. Larger values force the Tx 242*d39a76e7Sxw161283 * pipeline to wait before processing modulation events, thus 243*d39a76e7Sxw161283 * allowing Rx to use the pipeline. A really small delay can 244*d39a76e7Sxw161283 * starve the Rx side from accessing the pipeline. 245*d39a76e7Sxw161283 * 246*d39a76e7Sxw161283 * A balanced value is optimal. This is roughly 9us per 1G. 247*d39a76e7Sxw161283 * The Tx needs a low delay time for handling a lot of small 248*d39a76e7Sxw161283 * packets. Too big of a delay could cause Tx not to achieve 249*d39a76e7Sxw161283 * line rate. 250*d39a76e7Sxw161283 */ 251*d39a76e7Sxw161283 val = (9 * tp_clk) / 1000000; 252*d39a76e7Sxw161283 /* adjust for multiple ports */ 253*d39a76e7Sxw161283 if (ap->params.nports > 1) { 254*d39a76e7Sxw161283 val = 0; 255*d39a76e7Sxw161283 } 256*d39a76e7Sxw161283 if (is_10G(ap)) /* adjust for 10G */ 257*d39a76e7Sxw161283 val /= 10; 258*d39a76e7Sxw161283 /* 259*d39a76e7Sxw161283 * Bit 0 must be 0 to keep the timer insertion property. 260*d39a76e7Sxw161283 */ 261*d39a76e7Sxw161283 t1_write_reg_4(ap, A_TP_TIMER_SEPARATOR, val & ~1); 262*d39a76e7Sxw161283 263*d39a76e7Sxw161283 t1_write_reg_4(ap, A_TP_TIMER_RESOLUTION, 0xF0011); 264*d39a76e7Sxw161283 tp_set_tcp_time_params(ap, tp_clk); 265*d39a76e7Sxw161283 266*d39a76e7Sxw161283 /* PR3229 */ 267*d39a76e7Sxw161283 if (is_T2(ap)) { 268*d39a76e7Sxw161283 val = t1_read_reg_4(ap, A_TP_PC_CONFIG); 269*d39a76e7Sxw161283 val |= V_DIS_TX_FILL_WIN_PUSH(1); 270*d39a76e7Sxw161283 t1_write_reg_4(ap, A_TP_PC_CONFIG, val); 271*d39a76e7Sxw161283 } 272*d39a76e7Sxw161283 273*d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G 274*d39a76e7Sxw161283 } else { /* FPGA */ 275*d39a76e7Sxw161283 t1_write_reg_4(ap, A_TP_TIMER_RESOLUTION, 0xD000A); 276*d39a76e7Sxw161283 #endif 277*d39a76e7Sxw161283 #endif 278*d39a76e7Sxw161283 } 279*d39a76e7Sxw161283 } 280*d39a76e7Sxw161283 281*d39a76e7Sxw161283 void t1_tp_destroy(struct petp *tp) 282*d39a76e7Sxw161283 { 283*d39a76e7Sxw161283 t1_os_free((void *)tp, sizeof(*tp)); 284*d39a76e7Sxw161283 } 285*d39a76e7Sxw161283 286*d39a76e7Sxw161283 struct petp * __devinit t1_tp_create(adapter_t *adapter, struct tp_params *p) 287*d39a76e7Sxw161283 { 288*d39a76e7Sxw161283 struct petp *tp = t1_os_malloc_wait_zero(sizeof(*tp)); 289*d39a76e7Sxw161283 if (!tp) 290*d39a76e7Sxw161283 return NULL; 291*d39a76e7Sxw161283 292*d39a76e7Sxw161283 tp->adapter = adapter; 293*d39a76e7Sxw161283 294*d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD 295*d39a76e7Sxw161283 if (p->pm_size) { /* Default PM partitioning */ 296*d39a76e7Sxw161283 p->pm_rx_base = p->pm_size >> 1; 297*d39a76e7Sxw161283 #ifdef TDI_SUPPORT 298*d39a76e7Sxw161283 p->pm_tx_base = 2048 * 1024; /* reserve 2 MByte for REGION MAP */ 299*d39a76e7Sxw161283 #else 300*d39a76e7Sxw161283 p->pm_tx_base = 64 * 1024; /* reserve 64 kbytes for REGION MAP */ 301*d39a76e7Sxw161283 #endif 302*d39a76e7Sxw161283 p->pm_rx_pg_size = 64 * 1024; 303*d39a76e7Sxw161283 304*d39a76e7Sxw161283 if (adapter->params.nports == 1) 305*d39a76e7Sxw161283 p->pm_tx_pg_size = 64 * 1024; 306*d39a76e7Sxw161283 else 307*d39a76e7Sxw161283 p->pm_tx_pg_size = 16 * 1024; 308*d39a76e7Sxw161283 p->pm_rx_num_pgs = pm_num_pages(p->pm_size - p->pm_rx_base, 309*d39a76e7Sxw161283 p->pm_rx_pg_size); 310*d39a76e7Sxw161283 p->pm_tx_num_pgs = pm_num_pages(p->pm_rx_base - p->pm_tx_base, 311*d39a76e7Sxw161283 p->pm_tx_pg_size); 312*d39a76e7Sxw161283 } 313*d39a76e7Sxw161283 #endif 314*d39a76e7Sxw161283 return tp; 315*d39a76e7Sxw161283 } 316*d39a76e7Sxw161283 317*d39a76e7Sxw161283 void t1_tp_intr_enable(struct petp *tp) 318*d39a76e7Sxw161283 { 319*d39a76e7Sxw161283 u32 tp_intr = t1_read_reg_4(tp->adapter, A_PL_ENABLE); 320*d39a76e7Sxw161283 321*d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G 322*d39a76e7Sxw161283 if (!t1_is_asic(tp->adapter)) { 323*d39a76e7Sxw161283 /* FPGA */ 324*d39a76e7Sxw161283 t1_write_reg_4(tp->adapter, FPGA_TP_ADDR_INTERRUPT_ENABLE, 325*d39a76e7Sxw161283 0xffffffff); 326*d39a76e7Sxw161283 t1_write_reg_4(tp->adapter, A_PL_ENABLE, 327*d39a76e7Sxw161283 tp_intr | FPGA_PCIX_INTERRUPT_TP); 328*d39a76e7Sxw161283 } else 329*d39a76e7Sxw161283 #endif 330*d39a76e7Sxw161283 { 331*d39a76e7Sxw161283 /* We don't use any TP interrupts */ 332*d39a76e7Sxw161283 t1_write_reg_4(tp->adapter, A_TP_INT_ENABLE, 0); 333*d39a76e7Sxw161283 t1_write_reg_4(tp->adapter, A_PL_ENABLE, 334*d39a76e7Sxw161283 tp_intr | F_PL_INTR_TP); 335*d39a76e7Sxw161283 } 336*d39a76e7Sxw161283 } 337*d39a76e7Sxw161283 338*d39a76e7Sxw161283 void t1_tp_intr_disable(struct petp *tp) 339*d39a76e7Sxw161283 { 340*d39a76e7Sxw161283 u32 tp_intr = t1_read_reg_4(tp->adapter, A_PL_ENABLE); 341*d39a76e7Sxw161283 342*d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G 343*d39a76e7Sxw161283 if (!t1_is_asic(tp->adapter)) { 344*d39a76e7Sxw161283 /* FPGA */ 345*d39a76e7Sxw161283 t1_write_reg_4(tp->adapter, FPGA_TP_ADDR_INTERRUPT_ENABLE, 0); 346*d39a76e7Sxw161283 t1_write_reg_4(tp->adapter, A_PL_ENABLE, 347*d39a76e7Sxw161283 tp_intr & ~FPGA_PCIX_INTERRUPT_TP); 348*d39a76e7Sxw161283 } else 349*d39a76e7Sxw161283 #endif 350*d39a76e7Sxw161283 { 351*d39a76e7Sxw161283 t1_write_reg_4(tp->adapter, A_TP_INT_ENABLE, 0); 352*d39a76e7Sxw161283 t1_write_reg_4(tp->adapter, A_PL_ENABLE, 353*d39a76e7Sxw161283 tp_intr & ~F_PL_INTR_TP); 354*d39a76e7Sxw161283 } 355*d39a76e7Sxw161283 } 356*d39a76e7Sxw161283 357*d39a76e7Sxw161283 void t1_tp_intr_clear(struct petp *tp) 358*d39a76e7Sxw161283 { 359*d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G 360*d39a76e7Sxw161283 if (!t1_is_asic(tp->adapter)) { 361*d39a76e7Sxw161283 t1_write_reg_4(tp->adapter, FPGA_TP_ADDR_INTERRUPT_CAUSE, 362*d39a76e7Sxw161283 0xffffffff); 363*d39a76e7Sxw161283 t1_write_reg_4(tp->adapter, A_PL_CAUSE, FPGA_PCIX_INTERRUPT_TP); 364*d39a76e7Sxw161283 return; 365*d39a76e7Sxw161283 } 366*d39a76e7Sxw161283 #endif 367*d39a76e7Sxw161283 t1_write_reg_4(tp->adapter, A_TP_INT_CAUSE, 0xffffffff); 368*d39a76e7Sxw161283 t1_write_reg_4(tp->adapter, A_PL_CAUSE, F_PL_INTR_TP); 369*d39a76e7Sxw161283 } 370*d39a76e7Sxw161283 371*d39a76e7Sxw161283 int t1_tp_intr_handler(struct petp *tp) 372*d39a76e7Sxw161283 { 373*d39a76e7Sxw161283 u32 cause; 374*d39a76e7Sxw161283 375*d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G 376*d39a76e7Sxw161283 /* FPGA doesn't support TP interrupts. */ 377*d39a76e7Sxw161283 if (!t1_is_asic(tp->adapter)) 378*d39a76e7Sxw161283 return 1; 379*d39a76e7Sxw161283 #endif 380*d39a76e7Sxw161283 381*d39a76e7Sxw161283 cause = t1_read_reg_4(tp->adapter, A_TP_INT_CAUSE); 382*d39a76e7Sxw161283 t1_write_reg_4(tp->adapter, A_TP_INT_CAUSE, cause); 383*d39a76e7Sxw161283 return 0; 384*d39a76e7Sxw161283 } 385*d39a76e7Sxw161283 386*d39a76e7Sxw161283 static void set_csum_offload(struct petp *tp, u32 csum_bit, int enable) 387*d39a76e7Sxw161283 { 388*d39a76e7Sxw161283 u32 val = t1_read_reg_4(tp->adapter, A_TP_GLOBAL_CONFIG); 389*d39a76e7Sxw161283 390*d39a76e7Sxw161283 if (enable) 391*d39a76e7Sxw161283 val |= csum_bit; 392*d39a76e7Sxw161283 else 393*d39a76e7Sxw161283 val &= ~csum_bit; 394*d39a76e7Sxw161283 t1_write_reg_4(tp->adapter, A_TP_GLOBAL_CONFIG, val); 395*d39a76e7Sxw161283 } 396*d39a76e7Sxw161283 397*d39a76e7Sxw161283 void t1_tp_set_ip_checksum_offload(struct petp *tp, int enable) 398*d39a76e7Sxw161283 { 399*d39a76e7Sxw161283 set_csum_offload(tp, F_IP_CSUM, enable); 400*d39a76e7Sxw161283 } 401*d39a76e7Sxw161283 402*d39a76e7Sxw161283 void t1_tp_set_udp_checksum_offload(struct petp *tp, int enable) 403*d39a76e7Sxw161283 { 404*d39a76e7Sxw161283 set_csum_offload(tp, F_UDP_CSUM, enable); 405*d39a76e7Sxw161283 } 406*d39a76e7Sxw161283 407*d39a76e7Sxw161283 void t1_tp_set_tcp_checksum_offload(struct petp *tp, int enable) 408*d39a76e7Sxw161283 { 409*d39a76e7Sxw161283 set_csum_offload(tp, F_TCP_CSUM, enable); 410*d39a76e7Sxw161283 } 411*d39a76e7Sxw161283 412*d39a76e7Sxw161283 /* 413*d39a76e7Sxw161283 * Initialize TP state. tp_params contains initial settings for some TP 414*d39a76e7Sxw161283 * parameters, particularly the one-time PM and CM settings. 415*d39a76e7Sxw161283 */ 416*d39a76e7Sxw161283 int t1_tp_reset(struct petp *tp, struct tp_params *p, unsigned int tp_clk) 417*d39a76e7Sxw161283 { 418*d39a76e7Sxw161283 int busy = 0; 419*d39a76e7Sxw161283 adapter_t *adapter = tp->adapter; 420*d39a76e7Sxw161283 421*d39a76e7Sxw161283 tp_init(adapter, p, tp_clk); 422*d39a76e7Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD 423*d39a76e7Sxw161283 if (p->pm_size) { 424*d39a76e7Sxw161283 tp_pm_configure(adapter, p); 425*d39a76e7Sxw161283 tp_cm_configure(adapter, p->cm_size); 426*d39a76e7Sxw161283 427*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_RESET, F_CM_MEMMGR_INIT); 428*d39a76e7Sxw161283 busy = t1_wait_op_done(adapter, A_TP_RESET, F_CM_MEMMGR_INIT, 429*d39a76e7Sxw161283 0, 1000, 5); 430*d39a76e7Sxw161283 } 431*d39a76e7Sxw161283 #endif 432*d39a76e7Sxw161283 if (!busy) 433*d39a76e7Sxw161283 t1_write_reg_4(adapter, A_TP_RESET, F_TP_RESET); 434*d39a76e7Sxw161283 else 435*d39a76e7Sxw161283 CH_ERR("%s: TP initialization timed out\n", 436*d39a76e7Sxw161283 adapter_name(adapter)); 437*d39a76e7Sxw161283 return busy; 438*d39a76e7Sxw161283 } 439