162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* $Date: 2006/02/07 04:21:54 $ $RCSfile: tp.c,v $ $Revision: 1.73 $ */ 362306a36Sopenharmony_ci#include "common.h" 462306a36Sopenharmony_ci#include "regs.h" 562306a36Sopenharmony_ci#include "tp.h" 662306a36Sopenharmony_ci#ifdef CONFIG_CHELSIO_T1_1G 762306a36Sopenharmony_ci#include "fpga_defs.h" 862306a36Sopenharmony_ci#endif 962306a36Sopenharmony_ci 1062306a36Sopenharmony_cistruct petp { 1162306a36Sopenharmony_ci adapter_t *adapter; 1262306a36Sopenharmony_ci}; 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci/* Pause deadlock avoidance parameters */ 1562306a36Sopenharmony_ci#define DROP_MSEC 16 1662306a36Sopenharmony_ci#define DROP_PKTS_CNT 1 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistatic void tp_init(adapter_t * ap, const struct tp_params *p, 1962306a36Sopenharmony_ci unsigned int tp_clk) 2062306a36Sopenharmony_ci{ 2162306a36Sopenharmony_ci u32 val; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci if (!t1_is_asic(ap)) 2462306a36Sopenharmony_ci return; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci val = F_TP_IN_CSPI_CPL | F_TP_IN_CSPI_CHECK_IP_CSUM | 2762306a36Sopenharmony_ci F_TP_IN_CSPI_CHECK_TCP_CSUM | F_TP_IN_ESPI_ETHERNET; 2862306a36Sopenharmony_ci if (!p->pm_size) 2962306a36Sopenharmony_ci val |= F_OFFLOAD_DISABLE; 3062306a36Sopenharmony_ci else 3162306a36Sopenharmony_ci val |= F_TP_IN_ESPI_CHECK_IP_CSUM | F_TP_IN_ESPI_CHECK_TCP_CSUM; 3262306a36Sopenharmony_ci writel(val, ap->regs + A_TP_IN_CONFIG); 3362306a36Sopenharmony_ci writel(F_TP_OUT_CSPI_CPL | 3462306a36Sopenharmony_ci F_TP_OUT_ESPI_ETHERNET | 3562306a36Sopenharmony_ci F_TP_OUT_ESPI_GENERATE_IP_CSUM | 3662306a36Sopenharmony_ci F_TP_OUT_ESPI_GENERATE_TCP_CSUM, ap->regs + A_TP_OUT_CONFIG); 3762306a36Sopenharmony_ci writel(V_IP_TTL(64) | 3862306a36Sopenharmony_ci F_PATH_MTU /* IP DF bit */ | 3962306a36Sopenharmony_ci V_5TUPLE_LOOKUP(p->use_5tuple_mode) | 4062306a36Sopenharmony_ci V_SYN_COOKIE_PARAMETER(29), ap->regs + A_TP_GLOBAL_CONFIG); 4162306a36Sopenharmony_ci /* 4262306a36Sopenharmony_ci * Enable pause frame deadlock prevention. 4362306a36Sopenharmony_ci */ 4462306a36Sopenharmony_ci if (is_T2(ap) && ap->params.nports > 1) { 4562306a36Sopenharmony_ci u32 drop_ticks = DROP_MSEC * (tp_clk / 1000); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci writel(F_ENABLE_TX_DROP | F_ENABLE_TX_ERROR | 4862306a36Sopenharmony_ci V_DROP_TICKS_CNT(drop_ticks) | 4962306a36Sopenharmony_ci V_NUM_PKTS_DROPPED(DROP_PKTS_CNT), 5062306a36Sopenharmony_ci ap->regs + A_TP_TX_DROP_CONFIG); 5162306a36Sopenharmony_ci } 5262306a36Sopenharmony_ci} 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_civoid t1_tp_destroy(struct petp *tp) 5562306a36Sopenharmony_ci{ 5662306a36Sopenharmony_ci kfree(tp); 5762306a36Sopenharmony_ci} 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cistruct petp *t1_tp_create(adapter_t *adapter, struct tp_params *p) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci struct petp *tp = kzalloc(sizeof(*tp), GFP_KERNEL); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci if (!tp) 6462306a36Sopenharmony_ci return NULL; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci tp->adapter = adapter; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci return tp; 6962306a36Sopenharmony_ci} 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_civoid t1_tp_intr_enable(struct petp *tp) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci u32 tp_intr = readl(tp->adapter->regs + A_PL_ENABLE); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci#ifdef CONFIG_CHELSIO_T1_1G 7662306a36Sopenharmony_ci if (!t1_is_asic(tp->adapter)) { 7762306a36Sopenharmony_ci /* FPGA */ 7862306a36Sopenharmony_ci writel(0xffffffff, 7962306a36Sopenharmony_ci tp->adapter->regs + FPGA_TP_ADDR_INTERRUPT_ENABLE); 8062306a36Sopenharmony_ci writel(tp_intr | FPGA_PCIX_INTERRUPT_TP, 8162306a36Sopenharmony_ci tp->adapter->regs + A_PL_ENABLE); 8262306a36Sopenharmony_ci } else 8362306a36Sopenharmony_ci#endif 8462306a36Sopenharmony_ci { 8562306a36Sopenharmony_ci /* We don't use any TP interrupts */ 8662306a36Sopenharmony_ci writel(0, tp->adapter->regs + A_TP_INT_ENABLE); 8762306a36Sopenharmony_ci writel(tp_intr | F_PL_INTR_TP, 8862306a36Sopenharmony_ci tp->adapter->regs + A_PL_ENABLE); 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_civoid t1_tp_intr_disable(struct petp *tp) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci u32 tp_intr = readl(tp->adapter->regs + A_PL_ENABLE); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci#ifdef CONFIG_CHELSIO_T1_1G 9762306a36Sopenharmony_ci if (!t1_is_asic(tp->adapter)) { 9862306a36Sopenharmony_ci /* FPGA */ 9962306a36Sopenharmony_ci writel(0, tp->adapter->regs + FPGA_TP_ADDR_INTERRUPT_ENABLE); 10062306a36Sopenharmony_ci writel(tp_intr & ~FPGA_PCIX_INTERRUPT_TP, 10162306a36Sopenharmony_ci tp->adapter->regs + A_PL_ENABLE); 10262306a36Sopenharmony_ci } else 10362306a36Sopenharmony_ci#endif 10462306a36Sopenharmony_ci { 10562306a36Sopenharmony_ci writel(0, tp->adapter->regs + A_TP_INT_ENABLE); 10662306a36Sopenharmony_ci writel(tp_intr & ~F_PL_INTR_TP, 10762306a36Sopenharmony_ci tp->adapter->regs + A_PL_ENABLE); 10862306a36Sopenharmony_ci } 10962306a36Sopenharmony_ci} 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_civoid t1_tp_intr_clear(struct petp *tp) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci#ifdef CONFIG_CHELSIO_T1_1G 11462306a36Sopenharmony_ci if (!t1_is_asic(tp->adapter)) { 11562306a36Sopenharmony_ci writel(0xffffffff, 11662306a36Sopenharmony_ci tp->adapter->regs + FPGA_TP_ADDR_INTERRUPT_CAUSE); 11762306a36Sopenharmony_ci writel(FPGA_PCIX_INTERRUPT_TP, tp->adapter->regs + A_PL_CAUSE); 11862306a36Sopenharmony_ci return; 11962306a36Sopenharmony_ci } 12062306a36Sopenharmony_ci#endif 12162306a36Sopenharmony_ci writel(0xffffffff, tp->adapter->regs + A_TP_INT_CAUSE); 12262306a36Sopenharmony_ci writel(F_PL_INTR_TP, tp->adapter->regs + A_PL_CAUSE); 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ciint t1_tp_intr_handler(struct petp *tp) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci u32 cause; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci#ifdef CONFIG_CHELSIO_T1_1G 13062306a36Sopenharmony_ci /* FPGA doesn't support TP interrupts. */ 13162306a36Sopenharmony_ci if (!t1_is_asic(tp->adapter)) 13262306a36Sopenharmony_ci return 1; 13362306a36Sopenharmony_ci#endif 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci cause = readl(tp->adapter->regs + A_TP_INT_CAUSE); 13662306a36Sopenharmony_ci writel(cause, tp->adapter->regs + A_TP_INT_CAUSE); 13762306a36Sopenharmony_ci return 0; 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cistatic void set_csum_offload(struct petp *tp, u32 csum_bit, int enable) 14162306a36Sopenharmony_ci{ 14262306a36Sopenharmony_ci u32 val = readl(tp->adapter->regs + A_TP_GLOBAL_CONFIG); 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci if (enable) 14562306a36Sopenharmony_ci val |= csum_bit; 14662306a36Sopenharmony_ci else 14762306a36Sopenharmony_ci val &= ~csum_bit; 14862306a36Sopenharmony_ci writel(val, tp->adapter->regs + A_TP_GLOBAL_CONFIG); 14962306a36Sopenharmony_ci} 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_civoid t1_tp_set_ip_checksum_offload(struct petp *tp, int enable) 15262306a36Sopenharmony_ci{ 15362306a36Sopenharmony_ci set_csum_offload(tp, F_IP_CSUM, enable); 15462306a36Sopenharmony_ci} 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_civoid t1_tp_set_tcp_checksum_offload(struct petp *tp, int enable) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci set_csum_offload(tp, F_TCP_CSUM, enable); 15962306a36Sopenharmony_ci} 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci/* 16262306a36Sopenharmony_ci * Initialize TP state. tp_params contains initial settings for some TP 16362306a36Sopenharmony_ci * parameters, particularly the one-time PM and CM settings. 16462306a36Sopenharmony_ci */ 16562306a36Sopenharmony_ciint t1_tp_reset(struct petp *tp, struct tp_params *p, unsigned int tp_clk) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci adapter_t *adapter = tp->adapter; 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci tp_init(adapter, p, tp_clk); 17062306a36Sopenharmony_ci writel(F_TP_RESET, adapter->regs + A_TP_RESET); 17162306a36Sopenharmony_ci return 0; 17262306a36Sopenharmony_ci} 173