This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / drivers / net / chelsio / ixf1010.c
1 /* $Date: 2005/11/12 02:13:49 $ $RCSfile: ixf1010.c,v $ $Revision: 1.36 $ */
2 #include "gmac.h"
3 #include "elmer0.h"
4
5 /* Update fast changing statistics every 15 seconds */
6 #define STATS_TICK_SECS 15
7 /* 30 minutes for full statistics update */
8 #define MAJOR_UPDATE_TICKS (1800 / STATS_TICK_SECS)
9
10 /*
11  * The IXF1010 can handle frames up to 16383 bytes but it's optimized for
12  * frames up to 9831 (0x2667) bytes, so we limit jumbo frame size to this.
13  * This length includes ethernet header and FCS.
14  */
15 #define MAX_FRAME_SIZE 0x2667
16
17 /* MAC registers */
18 enum {
19         /* Per-port registers */
20         REG_MACADDR_LOW = 0,
21         REG_MACADDR_HIGH = 0x4,
22         REG_FDFC_TYPE = 0xC,
23         REG_FC_TX_TIMER_VALUE = 0x1c,
24         REG_IPG_RX_TIME1 = 0x28,
25         REG_IPG_RX_TIME2 = 0x2c,
26         REG_IPG_TX_TIME = 0x30,
27         REG_PAUSE_THRES = 0x38,
28         REG_MAX_FRAME_SIZE = 0x3c,
29         REG_RGMII_SPEED = 0x40,
30         REG_FC_ENABLE = 0x48,
31         REG_DISCARD_CTRL_FRAMES = 0x54,
32         REG_DIVERSE_CONFIG = 0x60,
33         REG_RX_FILTER = 0x64,
34         REG_MC_ADDR_LOW = 0x68,
35         REG_MC_ADDR_HIGH = 0x6c,
36
37         REG_RX_OCTETS_OK = 0x80,
38         REG_RX_OCTETS_BAD = 0x84,
39         REG_RX_UC_PKTS = 0x88,
40         REG_RX_MC_PKTS = 0x8c,
41         REG_RX_BC_PKTS = 0x90,
42         REG_RX_FCS_ERR = 0xb0,
43         REG_RX_TAGGED = 0xb4,
44         REG_RX_DATA_ERR = 0xb8,
45         REG_RX_ALIGN_ERR = 0xbc,
46         REG_RX_LONG_ERR = 0xc0,
47         REG_RX_JABBER_ERR = 0xc4,
48         REG_RX_PAUSE_FRAMES = 0xc8,
49         REG_RX_UNKNOWN_CTRL_FRAMES = 0xcc,
50         REG_RX_VERY_LONG_ERR = 0xd0,
51         REG_RX_RUNT_ERR = 0xd4,
52         REG_RX_SHORT_ERR = 0xd8,
53         REG_RX_SYMBOL_ERR = 0xe4,
54
55         REG_TX_OCTETS_OK = 0x100,
56         REG_TX_OCTETS_BAD = 0x104,
57         REG_TX_UC_PKTS = 0x108,
58         REG_TX_MC_PKTS = 0x10c,
59         REG_TX_BC_PKTS = 0x110,
60         REG_TX_EXCESSIVE_LEN_DROP = 0x14c,
61         REG_TX_UNDERRUN = 0x150,
62         REG_TX_TAGGED = 0x154,
63         REG_TX_PAUSE_FRAMES = 0x15C,
64
65         /* Global registers */
66         REG_PORT_ENABLE = 0x1400,
67
68         REG_JTAG_ID = 0x1430,
69
70         RX_FIFO_HIGH_WATERMARK_BASE = 0x1600,
71         RX_FIFO_LOW_WATERMARK_BASE = 0x1628,
72         RX_FIFO_FRAMES_REMOVED_BASE = 0x1650,
73
74         REG_RX_ERR_DROP = 0x167c,
75         REG_RX_FIFO_OVERFLOW_EVENT = 0x1680,
76
77         TX_FIFO_HIGH_WATERMARK_BASE = 0x1800,
78         TX_FIFO_LOW_WATERMARK_BASE = 0x1828,
79         TX_FIFO_XFER_THRES_BASE = 0x1850,
80
81         REG_TX_FIFO_OVERFLOW_EVENT = 0x1878,
82         REG_TX_FIFO_OOS_EVENT = 0x1884,
83
84         TX_FIFO_FRAMES_REMOVED_BASE = 0x1888,
85
86         REG_SPI_RX_BURST = 0x1c00,
87         REG_SPI_RX_TRAINING = 0x1c04,
88         REG_SPI_RX_CALENDAR = 0x1c08,
89         REG_SPI_TX_SYNC = 0x1c0c
90 };
91
92 enum {                     /* RMON registers */
93         REG_RxOctetsTotalOK = 0x80,
94         REG_RxOctetsBad = 0x84,
95         REG_RxUCPkts = 0x88,
96         REG_RxMCPkts = 0x8c,
97         REG_RxBCPkts = 0x90,
98         REG_RxJumboPkts = 0xac,
99         REG_RxFCSErrors = 0xb0,
100         REG_RxDataErrors = 0xb8,
101         REG_RxAlignErrors = 0xbc,
102         REG_RxLongErrors = 0xc0,
103         REG_RxJabberErrors = 0xc4,
104         REG_RxPauseMacControlCounter = 0xc8,
105         REG_RxVeryLongErrors = 0xd0,
106         REG_RxRuntErrors = 0xd4,
107         REG_RxShortErrors = 0xd8,
108         REG_RxSequenceErrors = 0xe0,
109         REG_RxSymbolErrors = 0xe4,
110
111         REG_TxOctetsTotalOK = 0x100,
112         REG_TxOctetsBad = 0x104,
113         REG_TxUCPkts = 0x108,
114         REG_TxMCPkts = 0x10c,
115         REG_TxBCPkts = 0x110,
116         REG_TxJumboPkts = 0x12C,
117         REG_TxTotalCollisions = 0x134,
118         REG_TxExcessiveLengthDrop = 0x14c,
119         REG_TxUnderrun = 0x150,
120         REG_TxCRCErrors = 0x158,
121         REG_TxPauseFrames = 0x15c
122 };
123
124 enum {
125         DIVERSE_CONFIG_PAD_ENABLE = 0x80,
126         DIVERSE_CONFIG_CRC_ADD = 0x40
127 };
128
129 #define MACREG_BASE            0
130 #define MACREG(mac, mac_reg)   ((mac)->instance->mac_base + (mac_reg))
131
132 struct _cmac_instance {
133         u32 mac_base;
134         u32 index;
135         u32 version;
136         u32 ticks;
137 };
138
139 static void disable_port(struct cmac *mac)
140 {
141         u32 val;
142
143         t1_tpi_read(mac->adapter, REG_PORT_ENABLE, &val);
144         val &= ~(1 << mac->instance->index);
145         t1_tpi_write(mac->adapter, REG_PORT_ENABLE, val);
146 }
147
148 #define RMON_UPDATE(mac, name, stat_name) \
149         t1_tpi_read((mac)->adapter, MACREG(mac, REG_##name), &val); \
150         (mac)->stats.stat_name += val;
151
152 /*
153  * Read the current values of the RMON counters and add them to the cumulative
154  * port statistics.  The HW RMON counters are cleared by this operation.
155  */
156 static void port_stats_update(struct cmac *mac)
157 {
158         u32 val;
159
160         /* Rx stats */
161         RMON_UPDATE(mac, RxOctetsTotalOK, RxOctetsOK);
162         RMON_UPDATE(mac, RxOctetsBad, RxOctetsBad);
163         RMON_UPDATE(mac, RxUCPkts, RxUnicastFramesOK);
164         RMON_UPDATE(mac, RxMCPkts, RxMulticastFramesOK);
165         RMON_UPDATE(mac, RxBCPkts, RxBroadcastFramesOK);
166         RMON_UPDATE(mac, RxJumboPkts, RxJumboFramesOK);
167         RMON_UPDATE(mac, RxFCSErrors, RxFCSErrors);
168         RMON_UPDATE(mac, RxAlignErrors, RxAlignErrors);
169         RMON_UPDATE(mac, RxLongErrors, RxFrameTooLongErrors);
170         RMON_UPDATE(mac, RxVeryLongErrors, RxFrameTooLongErrors);
171         RMON_UPDATE(mac, RxPauseMacControlCounter, RxPauseFrames);
172         RMON_UPDATE(mac, RxDataErrors, RxDataErrors);
173         RMON_UPDATE(mac, RxJabberErrors, RxJabberErrors);
174         RMON_UPDATE(mac, RxRuntErrors, RxRuntErrors);
175         RMON_UPDATE(mac, RxShortErrors, RxRuntErrors);
176         RMON_UPDATE(mac, RxSequenceErrors, RxSequenceErrors);
177         RMON_UPDATE(mac, RxSymbolErrors, RxSymbolErrors);
178
179         /* Tx stats (skip collision stats as we are full-duplex only) */
180         RMON_UPDATE(mac, TxOctetsTotalOK, TxOctetsOK);
181         RMON_UPDATE(mac, TxOctetsBad, TxOctetsBad);
182         RMON_UPDATE(mac, TxUCPkts, TxUnicastFramesOK);
183         RMON_UPDATE(mac, TxMCPkts, TxMulticastFramesOK);
184         RMON_UPDATE(mac, TxBCPkts, TxBroadcastFramesOK);
185         RMON_UPDATE(mac, TxJumboPkts, TxJumboFramesOK);
186         RMON_UPDATE(mac, TxPauseFrames, TxPauseFrames);
187         RMON_UPDATE(mac, TxExcessiveLengthDrop, TxLengthErrors);
188         RMON_UPDATE(mac, TxUnderrun, TxUnderrun);
189         RMON_UPDATE(mac, TxCRCErrors, TxFCSErrors);
190 }
191
192 /* No-op interrupt operation as this MAC does not support interrupts */
193 static int mac_intr_op(struct cmac *mac)
194 {
195         return 0;
196 }
197
198 /* Expect MAC address to be in network byte order. */
199 static int mac_set_address(struct cmac *mac, u8 addr[6])
200 {
201         u32 addr_lo, addr_hi;
202
203         addr_lo = addr[2];
204         addr_lo = (addr_lo << 8) | addr[3];
205         addr_lo = (addr_lo << 8) | addr[4];
206         addr_lo = (addr_lo << 8) | addr[5];
207
208         addr_hi = addr[0];
209         addr_hi = (addr_hi << 8) | addr[1];
210
211         t1_tpi_write(mac->adapter, MACREG(mac, REG_MACADDR_LOW), addr_lo);
212         t1_tpi_write(mac->adapter, MACREG(mac, REG_MACADDR_HIGH), addr_hi);
213         return 0;
214 }
215
216 static int mac_get_address(struct cmac *mac, u8 addr[6])
217 {
218         u32 addr_lo, addr_hi;
219
220         t1_tpi_read(mac->adapter, MACREG(mac, REG_MACADDR_LOW), &addr_lo);
221         t1_tpi_read(mac->adapter, MACREG(mac, REG_MACADDR_HIGH), &addr_hi);
222
223         addr[0] = (u8) (addr_hi >> 8);
224         addr[1] = (u8) addr_hi;
225         addr[2] = (u8) (addr_lo >> 24);
226         addr[3] = (u8) (addr_lo >> 16);
227         addr[4] = (u8) (addr_lo >> 8);
228         addr[5] = (u8) addr_lo;
229         return 0;
230 }
231
232 /* This is intended to reset a port, not the whole MAC */
233 static int mac_reset(struct cmac *mac)
234 {
235         return 0;
236 }
237
238 static int mac_set_rx_mode(struct cmac *mac, struct t1_rx_mode *rm)
239 {
240         u32 val, new_mode;
241         adapter_t *adapter = mac->adapter;
242         u32 addr_lo, addr_hi;
243         u8 *addr;
244
245         t1_tpi_read(adapter, MACREG(mac, REG_RX_FILTER), &val);
246         new_mode = val & ~7;
247         if (!t1_rx_mode_promisc(rm) && mac->instance->version > 0)
248                 new_mode |= 1;     /* only set if version > 0 due to erratum */
249         if (!t1_rx_mode_promisc(rm) && !t1_rx_mode_allmulti(rm)
250              && t1_rx_mode_mc_cnt(rm) <= 1)
251                 new_mode |= 2;
252         if (new_mode != val)
253                 t1_tpi_write(adapter, MACREG(mac, REG_RX_FILTER), new_mode);
254         switch (t1_rx_mode_mc_cnt(rm)) {
255         case 0:
256                 t1_tpi_write(adapter, MACREG(mac, REG_MC_ADDR_LOW), 0);
257                 t1_tpi_write(adapter, MACREG(mac, REG_MC_ADDR_HIGH), 0);
258                 break;
259         case 1:
260                 addr = t1_get_next_mcaddr(rm);
261                 addr_lo = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) |
262                         addr[5];
263                 addr_hi = (addr[0] << 8) | addr[1];
264                 t1_tpi_write(adapter, MACREG(mac, REG_MC_ADDR_LOW), addr_lo);
265                 t1_tpi_write(adapter, MACREG(mac, REG_MC_ADDR_HIGH), addr_hi);
266                 break;
267         default:
268                 break;
269         }
270         return 0;
271 }
272
273 static int mac_set_mtu(struct cmac *mac, int mtu)
274 {
275         /* MAX_FRAME_SIZE inludes header + FCS, mtu doesn't */
276         if (mtu > (MAX_FRAME_SIZE - 14 - 4)) return -EINVAL;
277         t1_tpi_write(mac->adapter, MACREG(mac, REG_MAX_FRAME_SIZE),
278                      mtu + 14 + 4);
279         return 0;
280 }
281
282 static int mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex,
283                                    int fc)
284 {
285         u32 val;
286
287         if (speed >= 0 && speed != SPEED_100 && speed != SPEED_1000)
288                 return -1;
289         if (duplex >= 0 && duplex != DUPLEX_FULL)
290                 return -1;
291
292         if (speed >= 0) {
293                 val = speed == SPEED_100 ? 1 : 2;
294                 t1_tpi_write(mac->adapter, MACREG(mac, REG_RGMII_SPEED), val);
295         }
296
297         t1_tpi_read(mac->adapter, MACREG(mac, REG_FC_ENABLE), &val);
298         val &= ~3;
299         if (fc & PAUSE_RX)
300                 val |= 1;
301         if (fc & PAUSE_TX)
302                 val |= 2;
303         t1_tpi_write(mac->adapter, MACREG(mac, REG_FC_ENABLE), val);
304         return 0;
305 }
306
307 static int mac_get_speed_duplex_fc(struct cmac *mac, int *speed, int *duplex,
308                                    int *fc)
309 {
310         u32 val;
311
312         if (duplex)
313                 *duplex = DUPLEX_FULL;
314         if (speed) {
315                 t1_tpi_read(mac->adapter, MACREG(mac, REG_RGMII_SPEED),
316                          &val);
317                 *speed = (val & 2) ? SPEED_1000 : SPEED_100;
318         }
319         if (fc) {
320                 t1_tpi_read(mac->adapter, MACREG(mac, REG_FC_ENABLE), &val);
321                 *fc = 0;
322                 if (val & 1)
323                         *fc |= PAUSE_RX;
324                 if (val & 2)
325                         *fc |= PAUSE_TX;
326         }
327         return 0;
328 }
329
330 static void enable_port(struct cmac *mac)
331 {
332         u32 val;
333         u32 index = mac->instance->index;
334         adapter_t *adapter = mac->adapter;
335
336         t1_tpi_read(adapter, MACREG(mac, REG_DIVERSE_CONFIG), &val);
337         val |= DIVERSE_CONFIG_CRC_ADD | DIVERSE_CONFIG_PAD_ENABLE;
338         t1_tpi_write(adapter, MACREG(mac, REG_DIVERSE_CONFIG), val);
339         if (mac->instance->version > 0)
340                 t1_tpi_write(adapter, MACREG(mac, REG_RX_FILTER), 3);
341         else /* Don't enable unicast address filtering due to IXF1010 bug */
342                 t1_tpi_write(adapter, MACREG(mac, REG_RX_FILTER), 2);
343
344         t1_tpi_read(adapter, REG_RX_ERR_DROP, &val);
345         val |= (1 << index);
346         t1_tpi_write(adapter, REG_RX_ERR_DROP, val);
347
348         /*
349          * Clear the port RMON registers by adding their current values to the
350          * cumulatice port stats and then clearing the stats.  Really.
351          */
352         port_stats_update(mac);
353         memset(&mac->stats, 0, sizeof(struct cmac_statistics));
354         mac->instance->ticks = 0;
355
356         t1_tpi_read(adapter, REG_PORT_ENABLE, &val);
357         val |= (1 << index);
358         t1_tpi_write(adapter, REG_PORT_ENABLE, val);
359
360         index <<= 2;
361         if (is_T2(adapter)) {
362                 /* T204: set the Fifo water level & threshold */
363                 t1_tpi_write(adapter, RX_FIFO_HIGH_WATERMARK_BASE + index, 0x740);
364                 t1_tpi_write(adapter, RX_FIFO_LOW_WATERMARK_BASE + index, 0x730);
365                 t1_tpi_write(adapter, TX_FIFO_HIGH_WATERMARK_BASE + index, 0x600);
366                 t1_tpi_write(adapter, TX_FIFO_LOW_WATERMARK_BASE + index, 0x1d0);
367                 t1_tpi_write(adapter, TX_FIFO_XFER_THRES_BASE + index, 0x1100);
368         } else {
369         /*
370          * Set the TX Fifo Threshold to 0x400 instead of 0x100 to work around
371          * Underrun problem. Intel has blessed this solution.
372          */
373                 t1_tpi_write(adapter, TX_FIFO_XFER_THRES_BASE + index, 0x400);
374         }
375 }
376
377 /* IXF1010 ports do not have separate enables for TX and RX */
378 static int mac_enable(struct cmac *mac, int which)
379 {
380         if (which & (MAC_DIRECTION_RX | MAC_DIRECTION_TX))
381                 enable_port(mac);
382         return 0;
383 }
384
385 static int mac_disable(struct cmac *mac, int which)
386 {
387         if (which & (MAC_DIRECTION_RX | MAC_DIRECTION_TX))
388                 disable_port(mac);
389         return 0;
390 }
391
392 /*
393  * This function is called periodically to accumulate the current values of the
394  * RMON counters into the port statistics.  Since the counters are only 32 bits
395  * some of them can overflow in less than a minute at GigE speeds, so this
396  * function should be called every 30 seconds or so.
397  *
398  * To cut down on reading costs we update only the octet counters at each tick
399  * and do a full update at major ticks, which can be every 30 minutes or more.
400  */
401 static const struct cmac_statistics *mac_update_statistics(struct cmac *mac,
402                                                            int flag)
403 {
404         if (flag == MAC_STATS_UPDATE_FULL ||
405             MAJOR_UPDATE_TICKS <= mac->instance->ticks) {
406                 port_stats_update(mac);
407                 mac->instance->ticks = 0;
408         } else {
409                 u32 val;
410
411                 RMON_UPDATE(mac, RxOctetsTotalOK, RxOctetsOK);
412                 RMON_UPDATE(mac, TxOctetsTotalOK, TxOctetsOK);
413                 mac->instance->ticks++;
414         }
415         return &mac->stats;
416 }
417
418 static void mac_destroy(struct cmac *mac)
419 {
420         kfree(mac);
421 }
422
423 static struct cmac_ops ixf1010_ops = {
424         .destroy                  = mac_destroy,
425         .reset                    = mac_reset,
426         .interrupt_enable         = mac_intr_op,
427         .interrupt_disable        = mac_intr_op,
428         .interrupt_clear          = mac_intr_op,
429         .enable                   = mac_enable,
430         .disable                  = mac_disable,
431         .set_mtu                  = mac_set_mtu,
432         .set_rx_mode              = mac_set_rx_mode,
433         .set_speed_duplex_fc      = mac_set_speed_duplex_fc,
434         .get_speed_duplex_fc      = mac_get_speed_duplex_fc,
435         .statistics_update        = mac_update_statistics,
436         .macaddress_get           = mac_get_address,
437         .macaddress_set           = mac_set_address,
438 };
439
440 static int ixf1010_mac_reset(adapter_t *adapter)
441 {
442         u32 val;
443
444         t1_tpi_read(adapter, A_ELMER0_GPO, &val);
445         if ((val & 1) != 0) {
446                 val &= ~1;
447                 t1_tpi_write(adapter, A_ELMER0_GPO, val);
448                 udelay(2);
449         }
450         val |= 1;
451         t1_tpi_write(adapter, A_ELMER0_GPO, val);
452         udelay(2);
453
454         t1_tpi_write(adapter, REG_PORT_ENABLE, 0);
455         return 0;
456 }
457
458 static struct cmac *ixf1010_mac_create(adapter_t *adapter, int index)
459 {
460         struct cmac *mac;
461         u32 val;
462
463         if (index > 9) return NULL;
464
465         mac = kzalloc(sizeof(*mac) + sizeof(cmac_instance), GFP_KERNEL);
466         if (!mac) return NULL;
467
468         mac->ops = &ixf1010_ops;
469         mac->instance = (cmac_instance *)(mac + 1);
470
471         mac->instance->mac_base = MACREG_BASE + (index * 0x200);
472         mac->instance->index    = index;
473         mac->adapter  = adapter;
474         mac->instance->ticks    = 0;
475
476         t1_tpi_read(adapter, REG_JTAG_ID, &val);
477         mac->instance->version = val >> 28;
478         return mac;
479 }
480
481 struct gmac t1_ixf1010_ops = {
482         STATS_TICK_SECS,
483         ixf1010_mac_create,
484         ixf1010_mac_reset
485 };