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