OSDN Git Service

e8ef9e0b791fd48fd1d63874a27c09907573a2e4
[tomoyo/tomoyo-test1.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);