]> Pileus Git - ~andy/linux/blob - drivers/net/chelsio/ixf1010.c
chelsio: spaces, tabs and friends
[~andy/linux] / 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))
277                 return -EINVAL;
278         t1_tpi_write(mac->adapter, MACREG(mac, REG_MAX_FRAME_SIZE),
279                      mtu + 14 + 4);
280         return 0;
281 }
282
283 static int mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex,
284                                    int fc)
285 {
286         u32 val;
287
288         if (speed >= 0 && speed != SPEED_100 && speed != SPEED_1000)
289                 return -1;
290         if (duplex >= 0 && duplex != DUPLEX_FULL)
291                 return -1;
292
293         if (speed >= 0) {
294                 val = speed == SPEED_100 ? 1 : 2;
295                 t1_tpi_write(mac->adapter, MACREG(mac, REG_RGMII_SPEED), val);
296         }
297
298         t1_tpi_read(mac->adapter, MACREG(mac, REG_FC_ENABLE), &val);
299         val &= ~3;
300         if (fc & PAUSE_RX)
301                 val |= 1;
302         if (fc & PAUSE_TX)
303                 val |= 2;
304         t1_tpi_write(mac->adapter, MACREG(mac, REG_FC_ENABLE), val);
305         return 0;
306 }
307
308 static int mac_get_speed_duplex_fc(struct cmac *mac, int *speed, int *duplex,
309                                    int *fc)
310 {
311         u32 val;
312
313         if (duplex)
314                 *duplex = DUPLEX_FULL;
315         if (speed) {
316                 t1_tpi_read(mac->adapter, MACREG(mac, REG_RGMII_SPEED),
317                          &val);
318                 *speed = (val & 2) ? SPEED_1000 : SPEED_100;
319         }
320         if (fc) {
321                 t1_tpi_read(mac->adapter, MACREG(mac, REG_FC_ENABLE), &val);
322                 *fc = 0;
323                 if (val & 1)
324                         *fc |= PAUSE_RX;
325                 if (val & 2)
326                         *fc |= PAUSE_TX;
327         }
328         return 0;
329 }
330
331 static void enable_port(struct cmac *mac)
332 {
333         u32 val;
334         u32 index = mac->instance->index;
335         adapter_t *adapter = mac->adapter;
336
337         t1_tpi_read(adapter, MACREG(mac, REG_DIVERSE_CONFIG), &val);
338         val |= DIVERSE_CONFIG_CRC_ADD | DIVERSE_CONFIG_PAD_ENABLE;
339         t1_tpi_write(adapter, MACREG(mac, REG_DIVERSE_CONFIG), val);
340         if (mac->instance->version > 0)
341                 t1_tpi_write(adapter, MACREG(mac, REG_RX_FILTER), 3);
342         else /* Don't enable unicast address filtering due to IXF1010 bug */
343                 t1_tpi_write(adapter, MACREG(mac, REG_RX_FILTER), 2);
344
345         t1_tpi_read(adapter, REG_RX_ERR_DROP, &val);
346         val |= (1 << index);
347         t1_tpi_write(adapter, REG_RX_ERR_DROP, val);
348
349         /*
350          * Clear the port RMON registers by adding their current values to the
351          * cumulatice port stats and then clearing the stats.  Really.
352          */
353         port_stats_update(mac);
354         memset(&mac->stats, 0, sizeof(struct cmac_statistics));
355         mac->instance->ticks = 0;
356
357         t1_tpi_read(adapter, REG_PORT_ENABLE, &val);
358         val |= (1 << index);
359         t1_tpi_write(adapter, REG_PORT_ENABLE, val);
360
361         index <<= 2;
362         if (is_T2(adapter)) {
363                 /* T204: set the Fifo water level & threshold */
364                 t1_tpi_write(adapter, RX_FIFO_HIGH_WATERMARK_BASE + index, 0x740);
365                 t1_tpi_write(adapter, RX_FIFO_LOW_WATERMARK_BASE + index, 0x730);
366                 t1_tpi_write(adapter, TX_FIFO_HIGH_WATERMARK_BASE + index, 0x600);
367                 t1_tpi_write(adapter, TX_FIFO_LOW_WATERMARK_BASE + index, 0x1d0);
368                 t1_tpi_write(adapter, TX_FIFO_XFER_THRES_BASE + index, 0x1100);
369         } else {
370         /*
371          * Set the TX Fifo Threshold to 0x400 instead of 0x100 to work around
372          * Underrun problem. Intel has blessed this solution.
373          */
374                 t1_tpi_write(adapter, TX_FIFO_XFER_THRES_BASE + index, 0x400);
375         }
376 }
377
378 /* IXF1010 ports do not have separate enables for TX and RX */
379 static int mac_enable(struct cmac *mac, int which)
380 {
381         if (which & (MAC_DIRECTION_RX | MAC_DIRECTION_TX))
382                 enable_port(mac);
383         return 0;
384 }
385
386 static int mac_disable(struct cmac *mac, int which)
387 {
388         if (which & (MAC_DIRECTION_RX | MAC_DIRECTION_TX))
389                 disable_port(mac);
390         return 0;
391 }
392
393 /*
394  * This function is called periodically to accumulate the current values of the
395  * RMON counters into the port statistics.  Since the counters are only 32 bits
396  * some of them can overflow in less than a minute at GigE speeds, so this
397  * function should be called every 30 seconds or so.
398  *
399  * To cut down on reading costs we update only the octet counters at each tick
400  * and do a full update at major ticks, which can be every 30 minutes or more.
401  */
402 static const struct cmac_statistics *mac_update_statistics(struct cmac *mac,
403                                                            int flag)
404 {
405         if (flag == MAC_STATS_UPDATE_FULL ||
406             MAJOR_UPDATE_TICKS <= mac->instance->ticks) {
407                 port_stats_update(mac);
408                 mac->instance->ticks = 0;
409         } else {
410                 u32 val;
411
412                 RMON_UPDATE(mac, RxOctetsTotalOK, RxOctetsOK);
413                 RMON_UPDATE(mac, TxOctetsTotalOK, TxOctetsOK);
414                 mac->instance->ticks++;
415         }
416         return &mac->stats;
417 }
418
419 static void mac_destroy(struct cmac *mac)
420 {
421         kfree(mac);
422 }
423
424 static struct cmac_ops ixf1010_ops = {
425         .destroy                  = mac_destroy,
426         .reset                    = mac_reset,
427         .interrupt_enable         = mac_intr_op,
428         .interrupt_disable        = mac_intr_op,
429         .interrupt_clear          = mac_intr_op,
430         .enable                   = mac_enable,
431         .disable                  = mac_disable,
432         .set_mtu                  = mac_set_mtu,
433         .set_rx_mode              = mac_set_rx_mode,
434         .set_speed_duplex_fc      = mac_set_speed_duplex_fc,
435         .get_speed_duplex_fc      = mac_get_speed_duplex_fc,
436         .statistics_update        = mac_update_statistics,
437         .macaddress_get           = mac_get_address,
438         .macaddress_set           = mac_set_address,
439 };
440
441 static int ixf1010_mac_reset(adapter_t *adapter)
442 {
443         u32 val;
444
445         t1_tpi_read(adapter, A_ELMER0_GPO, &val);
446         if ((val & 1) != 0) {
447                 val &= ~1;
448                 t1_tpi_write(adapter, A_ELMER0_GPO, val);
449                 udelay(2);
450         }
451         val |= 1;
452         t1_tpi_write(adapter, A_ELMER0_GPO, val);
453         udelay(2);
454
455         t1_tpi_write(adapter, REG_PORT_ENABLE, 0);
456         return 0;
457 }
458
459 static struct cmac *ixf1010_mac_create(adapter_t *adapter, int index)
460 {
461         struct cmac *mac;
462         u32 val;
463
464         if (index > 9)
465                 return NULL;
466
467         mac = kzalloc(sizeof(*mac) + sizeof(cmac_instance), GFP_KERNEL);
468         if (!mac)
469                 return NULL;
470
471         mac->ops = &ixf1010_ops;
472         mac->instance = (cmac_instance *)(mac + 1);
473
474         mac->instance->mac_base = MACREG_BASE + (index * 0x200);
475         mac->instance->index    = index;
476         mac->adapter  = adapter;
477         mac->instance->ticks    = 0;
478
479         t1_tpi_read(adapter, REG_JTAG_ID, &val);
480         mac->instance->version = val >> 28;
481         return mac;
482 }
483
484 struct gmac t1_ixf1010_ops = {
485         STATS_TICK_SECS,
486         ixf1010_mac_create,
487         ixf1010_mac_reset
488 };