chelsio: tabulate the update of the statistic counters
[linux-3.10.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 /*
149  * Read the current values of the RMON counters and add them to the cumulative
150  * port statistics.  The HW RMON counters are cleared by this operation.
151  */
152 static void port_stats_update(struct cmac *mac)
153 {
154         static struct {
155                 unsigned int reg;
156                 unsigned int offset;
157         } hw_stats[] = {
158
159 #define HW_STAT(name, stat_name) \
160         { REG_##name, \
161           (&((struct cmac_statistics *)NULL)->stat_name) - (u64 *)NULL }
162
163                 /* Rx stats */
164                 HW_STAT(RxOctetsTotalOK, RxOctetsOK),
165                 HW_STAT(RxOctetsBad, RxOctetsBad),
166                 HW_STAT(RxUCPkts, RxUnicastFramesOK),
167                 HW_STAT(RxMCPkts, RxMulticastFramesOK),
168                 HW_STAT(RxBCPkts, RxBroadcastFramesOK),
169                 HW_STAT(RxJumboPkts, RxJumboFramesOK),
170                 HW_STAT(RxFCSErrors, RxFCSErrors),
171                 HW_STAT(RxAlignErrors, RxAlignErrors),
172                 HW_STAT(RxLongErrors, RxFrameTooLongErrors),
173                 HW_STAT(RxVeryLongErrors, RxFrameTooLongErrors),
174                 HW_STAT(RxPauseMacControlCounter, RxPauseFrames),
175                 HW_STAT(RxDataErrors, RxDataErrors),
176                 HW_STAT(RxJabberErrors, RxJabberErrors),
177                 HW_STAT(RxRuntErrors, RxRuntErrors),
178                 HW_STAT(RxShortErrors, RxRuntErrors),
179                 HW_STAT(RxSequenceErrors, RxSequenceErrors),
180                 HW_STAT(RxSymbolErrors, RxSymbolErrors),
181
182                 /* Tx stats (skip collision stats as we are full-duplex only) */
183                 HW_STAT(TxOctetsTotalOK, TxOctetsOK),
184                 HW_STAT(TxOctetsBad, TxOctetsBad),
185                 HW_STAT(TxUCPkts, TxUnicastFramesOK),
186                 HW_STAT(TxMCPkts, TxMulticastFramesOK),
187                 HW_STAT(TxBCPkts, TxBroadcastFramesOK),
188                 HW_STAT(TxJumboPkts, TxJumboFramesOK),
189                 HW_STAT(TxPauseFrames, TxPauseFrames),
190                 HW_STAT(TxExcessiveLengthDrop, TxLengthErrors),
191                 HW_STAT(TxUnderrun, TxUnderrun),
192                 HW_STAT(TxCRCErrors, TxFCSErrors)
193         }, *p = hw_stats;
194         u64 *stats = (u64 *) &mac->stats;
195         unsigned int i;
196
197         for (i = 0; i < ARRAY_SIZE(hw_stats); i++) {
198                 u32 val;
199
200                 t1_tpi_read(mac->adapter, MACREG(mac, p->reg), &val);
201                 stats[p->offset] += val;
202         }
203 }
204
205 /* No-op interrupt operation as this MAC does not support interrupts */
206 static int mac_intr_op(struct cmac *mac)
207 {
208         return 0;
209 }
210
211 /* Expect MAC address to be in network byte order. */
212 static int mac_set_address(struct cmac *mac, u8 addr[6])
213 {
214         u32 addr_lo, addr_hi;
215
216         addr_lo = addr[2];
217         addr_lo = (addr_lo << 8) | addr[3];
218         addr_lo = (addr_lo << 8) | addr[4];
219         addr_lo = (addr_lo << 8) | addr[5];
220
221         addr_hi = addr[0];
222         addr_hi = (addr_hi << 8) | addr[1];
223
224         t1_tpi_write(mac->adapter, MACREG(mac, REG_MACADDR_LOW), addr_lo);
225         t1_tpi_write(mac->adapter, MACREG(mac, REG_MACADDR_HIGH), addr_hi);
226         return 0;
227 }
228
229 static int mac_get_address(struct cmac *mac, u8 addr[6])
230 {
231         u32 addr_lo, addr_hi;
232
233         t1_tpi_read(mac->adapter, MACREG(mac, REG_MACADDR_LOW), &addr_lo);
234         t1_tpi_read(mac->adapter, MACREG(mac, REG_MACADDR_HIGH), &addr_hi);
235
236         addr[0] = (u8) (addr_hi >> 8);
237         addr[1] = (u8) addr_hi;
238         addr[2] = (u8) (addr_lo >> 24);
239         addr[3] = (u8) (addr_lo >> 16);
240         addr[4] = (u8) (addr_lo >> 8);
241         addr[5] = (u8) addr_lo;
242         return 0;
243 }
244
245 /* This is intended to reset a port, not the whole MAC */
246 static int mac_reset(struct cmac *mac)
247 {
248         return 0;
249 }
250
251 static int mac_set_rx_mode(struct cmac *mac, struct t1_rx_mode *rm)
252 {
253         u32 val, new_mode;
254         adapter_t *adapter = mac->adapter;
255         u32 addr_lo, addr_hi;
256         u8 *addr;
257
258         t1_tpi_read(adapter, MACREG(mac, REG_RX_FILTER), &val);
259         new_mode = val & ~7;
260         if (!t1_rx_mode_promisc(rm) && mac->instance->version > 0)
261                 new_mode |= 1;     /* only set if version > 0 due to erratum */
262         if (!t1_rx_mode_promisc(rm) && !t1_rx_mode_allmulti(rm)
263              && t1_rx_mode_mc_cnt(rm) <= 1)
264                 new_mode |= 2;
265         if (new_mode != val)
266                 t1_tpi_write(adapter, MACREG(mac, REG_RX_FILTER), new_mode);
267         switch (t1_rx_mode_mc_cnt(rm)) {
268         case 0:
269                 t1_tpi_write(adapter, MACREG(mac, REG_MC_ADDR_LOW), 0);
270                 t1_tpi_write(adapter, MACREG(mac, REG_MC_ADDR_HIGH), 0);
271                 break;
272         case 1:
273                 addr = t1_get_next_mcaddr(rm);
274                 addr_lo = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) |
275                         addr[5];
276                 addr_hi = (addr[0] << 8) | addr[1];
277                 t1_tpi_write(adapter, MACREG(mac, REG_MC_ADDR_LOW), addr_lo);
278                 t1_tpi_write(adapter, MACREG(mac, REG_MC_ADDR_HIGH), addr_hi);
279                 break;
280         default:
281                 break;
282         }
283         return 0;
284 }
285
286 static int mac_set_mtu(struct cmac *mac, int mtu)
287 {
288         /* MAX_FRAME_SIZE inludes header + FCS, mtu doesn't */
289         if (mtu > (MAX_FRAME_SIZE - 14 - 4))
290                 return -EINVAL;
291         t1_tpi_write(mac->adapter, MACREG(mac, REG_MAX_FRAME_SIZE),
292                      mtu + 14 + 4);
293         return 0;
294 }
295
296 static int mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex,
297                                    int fc)
298 {
299         u32 val;
300
301         if (speed >= 0 && speed != SPEED_100 && speed != SPEED_1000)
302                 return -1;
303         if (duplex >= 0 && duplex != DUPLEX_FULL)
304                 return -1;
305
306         if (speed >= 0) {
307                 val = speed == SPEED_100 ? 1 : 2;
308                 t1_tpi_write(mac->adapter, MACREG(mac, REG_RGMII_SPEED), val);
309         }
310
311         t1_tpi_read(mac->adapter, MACREG(mac, REG_FC_ENABLE), &val);
312         val &= ~3;
313         if (fc & PAUSE_RX)
314                 val |= 1;
315         if (fc & PAUSE_TX)
316                 val |= 2;
317         t1_tpi_write(mac->adapter, MACREG(mac, REG_FC_ENABLE), val);
318         return 0;
319 }
320
321 static int mac_get_speed_duplex_fc(struct cmac *mac, int *speed, int *duplex,
322                                    int *fc)
323 {
324         u32 val;
325
326         if (duplex)
327                 *duplex = DUPLEX_FULL;
328         if (speed) {
329                 t1_tpi_read(mac->adapter, MACREG(mac, REG_RGMII_SPEED),
330                          &val);
331                 *speed = (val & 2) ? SPEED_1000 : SPEED_100;
332         }
333         if (fc) {
334                 t1_tpi_read(mac->adapter, MACREG(mac, REG_FC_ENABLE), &val);
335                 *fc = 0;
336                 if (val & 1)
337                         *fc |= PAUSE_RX;
338                 if (val & 2)
339                         *fc |= PAUSE_TX;
340         }
341         return 0;
342 }
343
344 static void enable_port(struct cmac *mac)
345 {
346         u32 val;
347         u32 index = mac->instance->index;
348         adapter_t *adapter = mac->adapter;
349
350         t1_tpi_read(adapter, MACREG(mac, REG_DIVERSE_CONFIG), &val);
351         val |= DIVERSE_CONFIG_CRC_ADD | DIVERSE_CONFIG_PAD_ENABLE;
352         t1_tpi_write(adapter, MACREG(mac, REG_DIVERSE_CONFIG), val);
353         if (mac->instance->version > 0)
354                 t1_tpi_write(adapter, MACREG(mac, REG_RX_FILTER), 3);
355         else /* Don't enable unicast address filtering due to IXF1010 bug */
356                 t1_tpi_write(adapter, MACREG(mac, REG_RX_FILTER), 2);
357
358         t1_tpi_read(adapter, REG_RX_ERR_DROP, &val);
359         val |= (1 << index);
360         t1_tpi_write(adapter, REG_RX_ERR_DROP, val);
361
362         /*
363          * Clear the port RMON registers by adding their current values to the
364          * cumulatice port stats and then clearing the stats.  Really.
365          */
366         port_stats_update(mac);
367         memset(&mac->stats, 0, sizeof(struct cmac_statistics));
368         mac->instance->ticks = 0;
369
370         t1_tpi_read(adapter, REG_PORT_ENABLE, &val);
371         val |= (1 << index);
372         t1_tpi_write(adapter, REG_PORT_ENABLE, val);
373
374         index <<= 2;
375         if (is_T2(adapter)) {
376                 /* T204: set the Fifo water level & threshold */
377                 t1_tpi_write(adapter, RX_FIFO_HIGH_WATERMARK_BASE + index, 0x740);
378                 t1_tpi_write(adapter, RX_FIFO_LOW_WATERMARK_BASE + index, 0x730);
379                 t1_tpi_write(adapter, TX_FIFO_HIGH_WATERMARK_BASE + index, 0x600);
380                 t1_tpi_write(adapter, TX_FIFO_LOW_WATERMARK_BASE + index, 0x1d0);
381                 t1_tpi_write(adapter, TX_FIFO_XFER_THRES_BASE + index, 0x1100);
382         } else {
383         /*
384          * Set the TX Fifo Threshold to 0x400 instead of 0x100 to work around
385          * Underrun problem. Intel has blessed this solution.
386          */
387                 t1_tpi_write(adapter, TX_FIFO_XFER_THRES_BASE + index, 0x400);
388         }
389 }
390
391 /* IXF1010 ports do not have separate enables for TX and RX */
392 static int mac_enable(struct cmac *mac, int which)
393 {
394         if (which & (MAC_DIRECTION_RX | MAC_DIRECTION_TX))
395                 enable_port(mac);
396         return 0;
397 }
398
399 static int mac_disable(struct cmac *mac, int which)
400 {
401         if (which & (MAC_DIRECTION_RX | MAC_DIRECTION_TX))
402                 disable_port(mac);
403         return 0;
404 }
405
406 #define RMON_UPDATE(mac, name, stat_name) \
407         t1_tpi_read((mac)->adapter, MACREG(mac, REG_##name), &val); \
408         (mac)->stats.stat_name += val;
409
410 /*
411  * This function is called periodically to accumulate the current values of the
412  * RMON counters into the port statistics.  Since the counters are only 32 bits
413  * some of them can overflow in less than a minute at GigE speeds, so this
414  * function should be called every 30 seconds or so.
415  *
416  * To cut down on reading costs we update only the octet counters at each tick
417  * and do a full update at major ticks, which can be every 30 minutes or more.
418  */
419 static const struct cmac_statistics *mac_update_statistics(struct cmac *mac,
420                                                            int flag)
421 {
422         if (flag == MAC_STATS_UPDATE_FULL ||
423             MAJOR_UPDATE_TICKS <= mac->instance->ticks) {
424                 port_stats_update(mac);
425                 mac->instance->ticks = 0;
426         } else {
427                 u32 val;
428
429                 RMON_UPDATE(mac, RxOctetsTotalOK, RxOctetsOK);
430                 RMON_UPDATE(mac, TxOctetsTotalOK, TxOctetsOK);
431                 mac->instance->ticks++;
432         }
433         return &mac->stats;
434 }
435
436 static void mac_destroy(struct cmac *mac)
437 {
438         kfree(mac);
439 }
440
441 static struct cmac_ops ixf1010_ops = {
442         .destroy                  = mac_destroy,
443         .reset                    = mac_reset,
444         .interrupt_enable         = mac_intr_op,
445         .interrupt_disable        = mac_intr_op,
446         .interrupt_clear          = mac_intr_op,
447         .enable                   = mac_enable,
448         .disable                  = mac_disable,
449         .set_mtu                  = mac_set_mtu,
450         .set_rx_mode              = mac_set_rx_mode,
451         .set_speed_duplex_fc      = mac_set_speed_duplex_fc,
452         .get_speed_duplex_fc      = mac_get_speed_duplex_fc,
453         .statistics_update        = mac_update_statistics,
454         .macaddress_get           = mac_get_address,
455         .macaddress_set           = mac_set_address,
456 };
457
458 static int ixf1010_mac_reset(adapter_t *adapter)
459 {
460         u32 val;
461
462         t1_tpi_read(adapter, A_ELMER0_GPO, &val);
463         if ((val & 1) != 0) {
464                 val &= ~1;
465                 t1_tpi_write(adapter, A_ELMER0_GPO, val);
466                 udelay(2);
467         }
468         val |= 1;
469         t1_tpi_write(adapter, A_ELMER0_GPO, val);
470         udelay(2);
471
472         t1_tpi_write(adapter, REG_PORT_ENABLE, 0);
473         return 0;
474 }
475
476 static struct cmac *ixf1010_mac_create(adapter_t *adapter, int index)
477 {
478         struct cmac *mac;
479         u32 val;
480
481         if (index > 9)
482                 return NULL;
483
484         mac = kzalloc(sizeof(*mac) + sizeof(cmac_instance), GFP_KERNEL);
485         if (!mac)
486                 return NULL;
487
488         mac->ops = &ixf1010_ops;
489         mac->instance = (cmac_instance *)(mac + 1);
490
491         mac->instance->mac_base = MACREG_BASE + (index * 0x200);
492         mac->instance->index    = index;
493         mac->adapter  = adapter;
494         mac->instance->ticks    = 0;
495
496         t1_tpi_read(adapter, REG_JTAG_ID, &val);
497         mac->instance->version = val >> 28;
498         return mac;
499 }
500
501 struct gmac t1_ixf1010_ops = {
502         STATS_TICK_SECS,
503         ixf1010_mac_create,
504         ixf1010_mac_reset
505 };