diff options
Diffstat (limited to 'drivers/net/ethernet/chelsio/cxgb/tp.c')
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb/tp.c | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/drivers/net/ethernet/chelsio/cxgb/tp.c b/drivers/net/ethernet/chelsio/cxgb/tp.c new file mode 100644 index 000000000000..8bed4a59e65f --- /dev/null +++ b/drivers/net/ethernet/chelsio/cxgb/tp.c | |||
@@ -0,0 +1,171 @@ | |||
1 | /* $Date: 2006/02/07 04:21:54 $ $RCSfile: tp.c,v $ $Revision: 1.73 $ */ | ||
2 | #include "common.h" | ||
3 | #include "regs.h" | ||
4 | #include "tp.h" | ||
5 | #ifdef CONFIG_CHELSIO_T1_1G | ||
6 | #include "fpga_defs.h" | ||
7 | #endif | ||
8 | |||
9 | struct petp { | ||
10 | adapter_t *adapter; | ||
11 | }; | ||
12 | |||
13 | /* Pause deadlock avoidance parameters */ | ||
14 | #define DROP_MSEC 16 | ||
15 | #define DROP_PKTS_CNT 1 | ||
16 | |||
17 | static void tp_init(adapter_t * ap, const struct tp_params *p, | ||
18 | unsigned int tp_clk) | ||
19 | { | ||
20 | u32 val; | ||
21 | |||
22 | if (!t1_is_asic(ap)) | ||
23 | return; | ||
24 | |||
25 | val = F_TP_IN_CSPI_CPL | F_TP_IN_CSPI_CHECK_IP_CSUM | | ||
26 | F_TP_IN_CSPI_CHECK_TCP_CSUM | F_TP_IN_ESPI_ETHERNET; | ||
27 | if (!p->pm_size) | ||
28 | val |= F_OFFLOAD_DISABLE; | ||
29 | else | ||
30 | val |= F_TP_IN_ESPI_CHECK_IP_CSUM | F_TP_IN_ESPI_CHECK_TCP_CSUM; | ||
31 | writel(val, ap->regs + A_TP_IN_CONFIG); | ||
32 | writel(F_TP_OUT_CSPI_CPL | | ||
33 | F_TP_OUT_ESPI_ETHERNET | | ||
34 | F_TP_OUT_ESPI_GENERATE_IP_CSUM | | ||
35 | F_TP_OUT_ESPI_GENERATE_TCP_CSUM, ap->regs + A_TP_OUT_CONFIG); | ||
36 | writel(V_IP_TTL(64) | | ||
37 | F_PATH_MTU /* IP DF bit */ | | ||
38 | V_5TUPLE_LOOKUP(p->use_5tuple_mode) | | ||
39 | V_SYN_COOKIE_PARAMETER(29), ap->regs + A_TP_GLOBAL_CONFIG); | ||
40 | /* | ||
41 | * Enable pause frame deadlock prevention. | ||
42 | */ | ||
43 | if (is_T2(ap) && ap->params.nports > 1) { | ||
44 | u32 drop_ticks = DROP_MSEC * (tp_clk / 1000); | ||
45 | |||
46 | writel(F_ENABLE_TX_DROP | F_ENABLE_TX_ERROR | | ||
47 | V_DROP_TICKS_CNT(drop_ticks) | | ||
48 | V_NUM_PKTS_DROPPED(DROP_PKTS_CNT), | ||
49 | ap->regs + A_TP_TX_DROP_CONFIG); | ||
50 | } | ||
51 | } | ||
52 | |||
53 | void t1_tp_destroy(struct petp *tp) | ||
54 | { | ||
55 | kfree(tp); | ||
56 | } | ||
57 | |||
58 | struct petp *__devinit t1_tp_create(adapter_t * adapter, struct tp_params *p) | ||
59 | { | ||
60 | struct petp *tp = kzalloc(sizeof(*tp), GFP_KERNEL); | ||
61 | |||
62 | if (!tp) | ||
63 | return NULL; | ||
64 | |||
65 | tp->adapter = adapter; | ||
66 | |||
67 | return tp; | ||
68 | } | ||
69 | |||
70 | void t1_tp_intr_enable(struct petp *tp) | ||
71 | { | ||
72 | u32 tp_intr = readl(tp->adapter->regs + A_PL_ENABLE); | ||
73 | |||
74 | #ifdef CONFIG_CHELSIO_T1_1G | ||
75 | if (!t1_is_asic(tp->adapter)) { | ||
76 | /* FPGA */ | ||
77 | writel(0xffffffff, | ||
78 | tp->adapter->regs + FPGA_TP_ADDR_INTERRUPT_ENABLE); | ||
79 | writel(tp_intr | FPGA_PCIX_INTERRUPT_TP, | ||
80 | tp->adapter->regs + A_PL_ENABLE); | ||
81 | } else | ||
82 | #endif | ||
83 | { | ||
84 | /* We don't use any TP interrupts */ | ||
85 | writel(0, tp->adapter->regs + A_TP_INT_ENABLE); | ||
86 | writel(tp_intr | F_PL_INTR_TP, | ||
87 | tp->adapter->regs + A_PL_ENABLE); | ||
88 | } | ||
89 | } | ||
90 | |||
91 | void t1_tp_intr_disable(struct petp *tp) | ||
92 | { | ||
93 | u32 tp_intr = readl(tp->adapter->regs + A_PL_ENABLE); | ||
94 | |||
95 | #ifdef CONFIG_CHELSIO_T1_1G | ||
96 | if (!t1_is_asic(tp->adapter)) { | ||
97 | /* FPGA */ | ||
98 | writel(0, tp->adapter->regs + FPGA_TP_ADDR_INTERRUPT_ENABLE); | ||
99 | writel(tp_intr & ~FPGA_PCIX_INTERRUPT_TP, | ||
100 | tp->adapter->regs + A_PL_ENABLE); | ||
101 | } else | ||
102 | #endif | ||
103 | { | ||
104 | writel(0, tp->adapter->regs + A_TP_INT_ENABLE); | ||
105 | writel(tp_intr & ~F_PL_INTR_TP, | ||
106 | tp->adapter->regs + A_PL_ENABLE); | ||
107 | } | ||
108 | } | ||
109 | |||
110 | void t1_tp_intr_clear(struct petp *tp) | ||
111 | { | ||
112 | #ifdef CONFIG_CHELSIO_T1_1G | ||
113 | if (!t1_is_asic(tp->adapter)) { | ||
114 | writel(0xffffffff, | ||
115 | tp->adapter->regs + FPGA_TP_ADDR_INTERRUPT_CAUSE); | ||
116 | writel(FPGA_PCIX_INTERRUPT_TP, tp->adapter->regs + A_PL_CAUSE); | ||
117 | return; | ||
118 | } | ||
119 | #endif | ||
120 | writel(0xffffffff, tp->adapter->regs + A_TP_INT_CAUSE); | ||
121 | writel(F_PL_INTR_TP, tp->adapter->regs + A_PL_CAUSE); | ||
122 | } | ||
123 | |||
124 | int t1_tp_intr_handler(struct petp *tp) | ||
125 | { | ||
126 | u32 cause; | ||
127 | |||
128 | #ifdef CONFIG_CHELSIO_T1_1G | ||
129 | /* FPGA doesn't support TP interrupts. */ | ||
130 | if (!t1_is_asic(tp->adapter)) | ||
131 | return 1; | ||
132 | #endif | ||
133 | |||
134 | cause = readl(tp->adapter->regs + A_TP_INT_CAUSE); | ||
135 | writel(cause, tp->adapter->regs + A_TP_INT_CAUSE); | ||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static void set_csum_offload(struct petp *tp, u32 csum_bit, int enable) | ||
140 | { | ||
141 | u32 val = readl(tp->adapter->regs + A_TP_GLOBAL_CONFIG); | ||
142 | |||
143 | if (enable) | ||
144 | val |= csum_bit; | ||
145 | else | ||
146 | val &= ~csum_bit; | ||
147 | writel(val, tp->adapter->regs + A_TP_GLOBAL_CONFIG); | ||
148 | } | ||
149 | |||
150 | void t1_tp_set_ip_checksum_offload(struct petp *tp, int enable) | ||
151 | { | ||
152 | set_csum_offload(tp, F_IP_CSUM, enable); | ||
153 | } | ||
154 | |||
155 | void t1_tp_set_tcp_checksum_offload(struct petp *tp, int enable) | ||
156 | { | ||
157 | set_csum_offload(tp, F_TCP_CSUM, enable); | ||
158 | } | ||
159 | |||
160 | /* | ||
161 | * Initialize TP state. tp_params contains initial settings for some TP | ||
162 | * parameters, particularly the one-time PM and CM settings. | ||
163 | */ | ||
164 | int t1_tp_reset(struct petp *tp, struct tp_params *p, unsigned int tp_clk) | ||
165 | { | ||
166 | adapter_t *adapter = tp->adapter; | ||
167 | |||
168 | tp_init(adapter, p, tp_clk); | ||
169 | writel(F_TP_RESET, adapter->regs + A_TP_RESET); | ||
170 | return 0; | ||
171 | } | ||