Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland...
[deliverable/linux.git] / drivers / staging / octeon / ethernet.c
1 /**********************************************************************
2 * Author: Cavium Networks
3 *
4 * Contact: support@caviumnetworks.com
5 * This file is part of the OCTEON SDK
6 *
7 * Copyright (c) 2003-2007 Cavium Networks
8 *
9 * This file is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License, Version 2, as
11 * published by the Free Software Foundation.
12 *
13 * This file is distributed in the hope that it will be useful, but
14 * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
15 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
16 * NONINFRINGEMENT. See the GNU General Public License for more
17 * details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this file; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 * or visit http://www.gnu.org/licenses/.
23 *
24 * This file may also be available under a different license from Cavium.
25 * Contact Cavium Networks for more information
26 **********************************************************************/
27 #include <linux/kernel.h>
28 #include <linux/init.h>
29 #include <linux/module.h>
30 #include <linux/netdevice.h>
31 #include <linux/etherdevice.h>
32 #include <linux/delay.h>
33 #include <linux/mii.h>
34
35 #include <net/dst.h>
36
37 #include <asm/octeon/octeon.h>
38
39 #include "ethernet-defines.h"
40 #include "ethernet-mem.h"
41 #include "ethernet-rx.h"
42 #include "ethernet-tx.h"
43 #include "ethernet-util.h"
44 #include "ethernet-proc.h"
45 #include "ethernet-common.h"
46 #include "octeon-ethernet.h"
47
48 #include "cvmx-pip.h"
49 #include "cvmx-pko.h"
50 #include "cvmx-fau.h"
51 #include "cvmx-ipd.h"
52 #include "cvmx-helper.h"
53
54 #include "cvmx-smix-defs.h"
55
56 #if defined(CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS) \
57 && CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS
58 int num_packet_buffers = CONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS;
59 #else
60 int num_packet_buffers = 1024;
61 #endif
62 module_param(num_packet_buffers, int, 0444);
63 MODULE_PARM_DESC(num_packet_buffers, "\n"
64 "\tNumber of packet buffers to allocate and store in the\n"
65 "\tFPA. By default, 1024 packet buffers are used unless\n"
66 "\tCONFIG_CAVIUM_OCTEON_NUM_PACKET_BUFFERS is defined.");
67
68 int pow_receive_group = 15;
69 module_param(pow_receive_group, int, 0444);
70 MODULE_PARM_DESC(pow_receive_group, "\n"
71 "\tPOW group to receive packets from. All ethernet hardware\n"
72 "\twill be configured to send incomming packets to this POW\n"
73 "\tgroup. Also any other software can submit packets to this\n"
74 "\tgroup for the kernel to process.");
75
76 int pow_send_group = -1;
77 module_param(pow_send_group, int, 0644);
78 MODULE_PARM_DESC(pow_send_group, "\n"
79 "\tPOW group to send packets to other software on. This\n"
80 "\tcontrols the creation of the virtual device pow0.\n"
81 "\talways_use_pow also depends on this value.");
82
83 int always_use_pow;
84 module_param(always_use_pow, int, 0444);
85 MODULE_PARM_DESC(always_use_pow, "\n"
86 "\tWhen set, always send to the pow group. This will cause\n"
87 "\tpackets sent to real ethernet devices to be sent to the\n"
88 "\tPOW group instead of the hardware. Unless some other\n"
89 "\tapplication changes the config, packets will still be\n"
90 "\treceived from the low level hardware. Use this option\n"
91 "\tto allow a CVMX app to intercept all packets from the\n"
92 "\tlinux kernel. You must specify pow_send_group along with\n"
93 "\tthis option.");
94
95 char pow_send_list[128] = "";
96 module_param_string(pow_send_list, pow_send_list, sizeof(pow_send_list), 0444);
97 MODULE_PARM_DESC(pow_send_list, "\n"
98 "\tComma separated list of ethernet devices that should use the\n"
99 "\tPOW for transmit instead of the actual ethernet hardware. This\n"
100 "\tis a per port version of always_use_pow. always_use_pow takes\n"
101 "\tprecedence over this list. For example, setting this to\n"
102 "\t\"eth2,spi3,spi7\" would cause these three devices to transmit\n"
103 "\tusing the pow_send_group.");
104
105 static int disable_core_queueing = 1;
106 module_param(disable_core_queueing, int, 0444);
107 MODULE_PARM_DESC(disable_core_queueing, "\n"
108 "\tWhen set the networking core's tx_queue_len is set to zero. This\n"
109 "\tallows packets to be sent without lock contention in the packet\n"
110 "\tscheduler resulting in some cases in improved throughput.\n");
111
112 /**
113 * Periodic timer to check auto negotiation
114 */
115 static struct timer_list cvm_oct_poll_timer;
116
117 /**
118 * Array of every ethernet device owned by this driver indexed by
119 * the ipd input port number.
120 */
121 struct net_device *cvm_oct_device[TOTAL_NUMBER_OF_PORTS];
122
123 extern struct semaphore mdio_sem;
124
125 /**
126 * Periodic timer tick for slow management operations
127 *
128 * @arg: Device to check
129 */
130 static void cvm_do_timer(unsigned long arg)
131 {
132 static int port;
133 if (port < CVMX_PIP_NUM_INPUT_PORTS) {
134 if (cvm_oct_device[port]) {
135 int queues_per_port;
136 int qos;
137 struct octeon_ethernet *priv =
138 netdev_priv(cvm_oct_device[port]);
139 if (priv->poll) {
140 /* skip polling if we don't get the lock */
141 if (!down_trylock(&mdio_sem)) {
142 priv->poll(cvm_oct_device[port]);
143 up(&mdio_sem);
144 }
145 }
146
147 queues_per_port = cvmx_pko_get_num_queues(port);
148 /* Drain any pending packets in the free list */
149 for (qos = 0; qos < queues_per_port; qos++) {
150 if (skb_queue_len(&priv->tx_free_list[qos])) {
151 spin_lock(&priv->tx_free_list[qos].
152 lock);
153 while (skb_queue_len
154 (&priv->tx_free_list[qos]) >
155 cvmx_fau_fetch_and_add32(priv->
156 fau +
157 qos * 4,
158 0))
159 dev_kfree_skb(__skb_dequeue
160 (&priv->
161 tx_free_list
162 [qos]));
163 spin_unlock(&priv->tx_free_list[qos].
164 lock);
165 }
166 }
167 cvm_oct_device[port]->get_stats(cvm_oct_device[port]);
168 }
169 port++;
170 /* Poll the next port in a 50th of a second.
171 This spreads the polling of ports out a little bit */
172 mod_timer(&cvm_oct_poll_timer, jiffies + HZ / 50);
173 } else {
174 port = 0;
175 /* All ports have been polled. Start the next iteration through
176 the ports in one second */
177 mod_timer(&cvm_oct_poll_timer, jiffies + HZ);
178 }
179 }
180
181 /**
182 * Configure common hardware for all interfaces
183 */
184 static __init void cvm_oct_configure_common_hw(void)
185 {
186 int r;
187 /* Setup the FPA */
188 cvmx_fpa_enable();
189 cvm_oct_mem_fill_fpa(CVMX_FPA_PACKET_POOL, CVMX_FPA_PACKET_POOL_SIZE,
190 num_packet_buffers);
191 cvm_oct_mem_fill_fpa(CVMX_FPA_WQE_POOL, CVMX_FPA_WQE_POOL_SIZE,
192 num_packet_buffers);
193 if (CVMX_FPA_OUTPUT_BUFFER_POOL != CVMX_FPA_PACKET_POOL)
194 cvm_oct_mem_fill_fpa(CVMX_FPA_OUTPUT_BUFFER_POOL,
195 CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, 128);
196
197 if (USE_RED)
198 cvmx_helper_setup_red(num_packet_buffers / 4,
199 num_packet_buffers / 8);
200
201 /* Enable the MII interface */
202 if (!octeon_is_simulation())
203 cvmx_write_csr(CVMX_SMIX_EN(0), 1);
204
205 /* Register an IRQ hander for to receive POW interrupts */
206 r = request_irq(OCTEON_IRQ_WORKQ0 + pow_receive_group,
207 cvm_oct_do_interrupt, IRQF_SHARED, "Ethernet",
208 cvm_oct_device);
209
210 #if defined(CONFIG_SMP) && 0
211 if (USE_MULTICORE_RECEIVE) {
212 irq_set_affinity(OCTEON_IRQ_WORKQ0 + pow_receive_group,
213 cpu_online_mask);
214 }
215 #endif
216 }
217
218 /**
219 * Free a work queue entry received in a intercept callback.
220 *
221 * @work_queue_entry:
222 * Work queue entry to free
223 * Returns Zero on success, Negative on failure.
224 */
225 int cvm_oct_free_work(void *work_queue_entry)
226 {
227 cvmx_wqe_t *work = work_queue_entry;
228
229 int segments = work->word2.s.bufs;
230 union cvmx_buf_ptr segment_ptr = work->packet_ptr;
231
232 while (segments--) {
233 union cvmx_buf_ptr next_ptr = *(union cvmx_buf_ptr *)
234 cvmx_phys_to_ptr(segment_ptr.s.addr - 8);
235 if (unlikely(!segment_ptr.s.i))
236 cvmx_fpa_free(cvm_oct_get_buffer_ptr(segment_ptr),
237 segment_ptr.s.pool,
238 DONT_WRITEBACK(CVMX_FPA_PACKET_POOL_SIZE /
239 128));
240 segment_ptr = next_ptr;
241 }
242 cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, DONT_WRITEBACK(1));
243
244 return 0;
245 }
246 EXPORT_SYMBOL(cvm_oct_free_work);
247
248 /**
249 * Module/ driver initialization. Creates the linux network
250 * devices.
251 *
252 * Returns Zero on success
253 */
254 static int __init cvm_oct_init_module(void)
255 {
256 int num_interfaces;
257 int interface;
258 int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE;
259 int qos;
260
261 pr_notice("cavium-ethernet %s\n", OCTEON_ETHERNET_VERSION);
262
263 cvm_oct_proc_initialize();
264 cvm_oct_rx_initialize();
265 cvm_oct_configure_common_hw();
266
267 cvmx_helper_initialize_packet_io_global();
268
269 /* Change the input group for all ports before input is enabled */
270 num_interfaces = cvmx_helper_get_number_of_interfaces();
271 for (interface = 0; interface < num_interfaces; interface++) {
272 int num_ports = cvmx_helper_ports_on_interface(interface);
273 int port;
274
275 for (port = cvmx_helper_get_ipd_port(interface, 0);
276 port < cvmx_helper_get_ipd_port(interface, num_ports);
277 port++) {
278 union cvmx_pip_prt_tagx pip_prt_tagx;
279 pip_prt_tagx.u64 =
280 cvmx_read_csr(CVMX_PIP_PRT_TAGX(port));
281 pip_prt_tagx.s.grp = pow_receive_group;
282 cvmx_write_csr(CVMX_PIP_PRT_TAGX(port),
283 pip_prt_tagx.u64);
284 }
285 }
286
287 cvmx_helper_ipd_and_packet_input_enable();
288
289 memset(cvm_oct_device, 0, sizeof(cvm_oct_device));
290
291 /*
292 * Initialize the FAU used for counting packet buffers that
293 * need to be freed.
294 */
295 cvmx_fau_atomic_write32(FAU_NUM_PACKET_BUFFERS_TO_FREE, 0);
296
297 if ((pow_send_group != -1)) {
298 struct net_device *dev;
299 pr_info("\tConfiguring device for POW only access\n");
300 dev = alloc_etherdev(sizeof(struct octeon_ethernet));
301 if (dev) {
302 /* Initialize the device private structure. */
303 struct octeon_ethernet *priv = netdev_priv(dev);
304 memset(priv, 0, sizeof(struct octeon_ethernet));
305
306 dev->init = cvm_oct_common_init;
307 priv->imode = CVMX_HELPER_INTERFACE_MODE_DISABLED;
308 priv->port = CVMX_PIP_NUM_INPUT_PORTS;
309 priv->queue = -1;
310 strcpy(dev->name, "pow%d");
311 for (qos = 0; qos < 16; qos++)
312 skb_queue_head_init(&priv->tx_free_list[qos]);
313
314 if (register_netdev(dev) < 0) {
315 pr_err("Failed to register ethernet "
316 "device for POW\n");
317 kfree(dev);
318 } else {
319 cvm_oct_device[CVMX_PIP_NUM_INPUT_PORTS] = dev;
320 pr_info("%s: POW send group %d, receive "
321 "group %d\n",
322 dev->name, pow_send_group,
323 pow_receive_group);
324 }
325 } else {
326 pr_err("Failed to allocate ethernet device "
327 "for POW\n");
328 }
329 }
330
331 num_interfaces = cvmx_helper_get_number_of_interfaces();
332 for (interface = 0; interface < num_interfaces; interface++) {
333 cvmx_helper_interface_mode_t imode =
334 cvmx_helper_interface_get_mode(interface);
335 int num_ports = cvmx_helper_ports_on_interface(interface);
336 int port;
337
338 for (port = cvmx_helper_get_ipd_port(interface, 0);
339 port < cvmx_helper_get_ipd_port(interface, num_ports);
340 port++) {
341 struct octeon_ethernet *priv;
342 struct net_device *dev =
343 alloc_etherdev(sizeof(struct octeon_ethernet));
344 if (!dev) {
345 pr_err("Failed to allocate ethernet device "
346 "for port %d\n", port);
347 continue;
348 }
349 if (disable_core_queueing)
350 dev->tx_queue_len = 0;
351
352 /* Initialize the device private structure. */
353 priv = netdev_priv(dev);
354 memset(priv, 0, sizeof(struct octeon_ethernet));
355
356 priv->imode = imode;
357 priv->port = port;
358 priv->queue = cvmx_pko_get_base_queue(priv->port);
359 priv->fau = fau - cvmx_pko_get_num_queues(port) * 4;
360 for (qos = 0; qos < 16; qos++)
361 skb_queue_head_init(&priv->tx_free_list[qos]);
362 for (qos = 0; qos < cvmx_pko_get_num_queues(port);
363 qos++)
364 cvmx_fau_atomic_write32(priv->fau + qos * 4, 0);
365
366 switch (priv->imode) {
367
368 /* These types don't support ports to IPD/PKO */
369 case CVMX_HELPER_INTERFACE_MODE_DISABLED:
370 case CVMX_HELPER_INTERFACE_MODE_PCIE:
371 case CVMX_HELPER_INTERFACE_MODE_PICMG:
372 break;
373
374 case CVMX_HELPER_INTERFACE_MODE_NPI:
375 dev->init = cvm_oct_common_init;
376 dev->uninit = cvm_oct_common_uninit;
377 strcpy(dev->name, "npi%d");
378 break;
379
380 case CVMX_HELPER_INTERFACE_MODE_XAUI:
381 dev->init = cvm_oct_xaui_init;
382 dev->uninit = cvm_oct_xaui_uninit;
383 strcpy(dev->name, "xaui%d");
384 break;
385
386 case CVMX_HELPER_INTERFACE_MODE_LOOP:
387 dev->init = cvm_oct_common_init;
388 dev->uninit = cvm_oct_common_uninit;
389 strcpy(dev->name, "loop%d");
390 break;
391
392 case CVMX_HELPER_INTERFACE_MODE_SGMII:
393 dev->init = cvm_oct_sgmii_init;
394 dev->uninit = cvm_oct_sgmii_uninit;
395 strcpy(dev->name, "eth%d");
396 break;
397
398 case CVMX_HELPER_INTERFACE_MODE_SPI:
399 dev->init = cvm_oct_spi_init;
400 dev->uninit = cvm_oct_spi_uninit;
401 strcpy(dev->name, "spi%d");
402 break;
403
404 case CVMX_HELPER_INTERFACE_MODE_RGMII:
405 case CVMX_HELPER_INTERFACE_MODE_GMII:
406 dev->init = cvm_oct_rgmii_init;
407 dev->uninit = cvm_oct_rgmii_uninit;
408 strcpy(dev->name, "eth%d");
409 break;
410 }
411
412 if (!dev->init) {
413 kfree(dev);
414 } else if (register_netdev(dev) < 0) {
415 pr_err("Failed to register ethernet device "
416 "for interface %d, port %d\n",
417 interface, priv->port);
418 kfree(dev);
419 } else {
420 cvm_oct_device[priv->port] = dev;
421 fau -=
422 cvmx_pko_get_num_queues(priv->port) *
423 sizeof(uint32_t);
424 }
425 }
426 }
427
428 if (INTERRUPT_LIMIT) {
429 /*
430 * Set the POW timer rate to give an interrupt at most
431 * INTERRUPT_LIMIT times per second.
432 */
433 cvmx_write_csr(CVMX_POW_WQ_INT_PC,
434 octeon_bootinfo->eclock_hz / (INTERRUPT_LIMIT *
435 16 * 256) << 8);
436
437 /*
438 * Enable POW timer interrupt. It will count when
439 * there are packets available.
440 */
441 cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group),
442 0x1ful << 24);
443 } else {
444 /* Enable POW interrupt when our port has at least one packet */
445 cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), 0x1001);
446 }
447
448 /* Enable the poll timer for checking RGMII status */
449 init_timer(&cvm_oct_poll_timer);
450 cvm_oct_poll_timer.data = 0;
451 cvm_oct_poll_timer.function = cvm_do_timer;
452 mod_timer(&cvm_oct_poll_timer, jiffies + HZ);
453
454 return 0;
455 }
456
457 /**
458 * Module / driver shutdown
459 *
460 * Returns Zero on success
461 */
462 static void __exit cvm_oct_cleanup_module(void)
463 {
464 int port;
465
466 /* Disable POW interrupt */
467 cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), 0);
468
469 cvmx_ipd_disable();
470
471 /* Free the interrupt handler */
472 free_irq(OCTEON_IRQ_WORKQ0 + pow_receive_group, cvm_oct_device);
473
474 del_timer(&cvm_oct_poll_timer);
475 cvm_oct_rx_shutdown();
476 cvmx_pko_disable();
477
478 /* Free the ethernet devices */
479 for (port = 0; port < TOTAL_NUMBER_OF_PORTS; port++) {
480 if (cvm_oct_device[port]) {
481 cvm_oct_tx_shutdown(cvm_oct_device[port]);
482 unregister_netdev(cvm_oct_device[port]);
483 kfree(cvm_oct_device[port]);
484 cvm_oct_device[port] = NULL;
485 }
486 }
487
488 cvmx_pko_shutdown();
489 cvm_oct_proc_shutdown();
490
491 cvmx_ipd_free_ptr();
492
493 /* Free the HW pools */
494 cvm_oct_mem_empty_fpa(CVMX_FPA_PACKET_POOL, CVMX_FPA_PACKET_POOL_SIZE,
495 num_packet_buffers);
496 cvm_oct_mem_empty_fpa(CVMX_FPA_WQE_POOL, CVMX_FPA_WQE_POOL_SIZE,
497 num_packet_buffers);
498 if (CVMX_FPA_OUTPUT_BUFFER_POOL != CVMX_FPA_PACKET_POOL)
499 cvm_oct_mem_empty_fpa(CVMX_FPA_OUTPUT_BUFFER_POOL,
500 CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, 128);
501 }
502
503 MODULE_LICENSE("GPL");
504 MODULE_AUTHOR("Cavium Networks <support@caviumnetworks.com>");
505 MODULE_DESCRIPTION("Cavium Networks Octeon ethernet driver.");
506 module_init(cvm_oct_init_module);
507 module_exit(cvm_oct_cleanup_module);
This page took 0.041976 seconds and 6 git commands to generate.