Updated host/linvcons.c to use new timer API introduced in Linux 4.14.0.
[xeon-phi-kernel-module] / host / linvnet.c
CommitLineData
800f879a
AT
1/*
2 * Copyright 2010-2017 Intel Corporation.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * Disclaimer: The codes contained in these modules may be specific to
14 * the Intel Software Development Platform codenamed Knights Ferry,
15 * and the Intel product codenamed Knights Corner, and are not backward
16 * compatible with other Intel products. Additionally, Intel will NOT
17 * support the codes or instruction set in future products.
18 *
19 * Intel offers no warranty of any kind regarding the code. This code is
20 * licensed on an "AS IS" basis and Intel is not obligated to provide
21 * any support, assistance, installation, training, or other services
22 * of any kind. Intel is also not obligated to provide any updates,
23 * enhancements or extensions. Intel specifically disclaims any warranty
24 * of merchantability, non-infringement, fitness for any particular
25 * purpose, and any other warranty.
26 *
27 * Further, Intel disclaims all liability of any kind, including but
28 * not limited to liability for infringement of any proprietary rights,
29 * relating to the use of the code, even if Intel is notified of the
30 * possibility of such liability. Except as expressly stated in an Intel
31 * license agreement provided with this code and agreed upon with Intel,
32 * no license, express or implied, by estoppel or otherwise, to any
33 * intellectual property rights is granted herein.
34 */
35
36#include "micint.h"
37#include "mic_common.h"
38#include <mic/micsboxdefine.h>
39#include <linux/ip.h>
40#include <linux/tcp.h>
41#include <linux/kernel.h>
42#include "mic/micveth.h"
43
44#define PWR_MGMT_NO_POLL_AFTER_LINKS_UP 1
45
46/*
47 In intr/poll modes, mic_smpt_uninit has already been called before
48 micveth_destroy is called during rmmod. This results in host driver crash. The
49 current workaround is, given the 'legacy' nature of VNET intr/poll modes, to
50 not call mic_ctx_unmap_single() at rmmod. This workaround will result in some
51 unmapped memory and a warn_on from micscif_smpt.c.
52 */
53#define WA_UNMAP_AT_RMMOD 0
54
55static void micveth_clientpoll(struct work_struct *work);
56static void micveth_poll(struct work_struct *work);
57static int micvnet_host_doorbell_intr_handler(mic_ctx_t *mic_ctx, int doorbell);
58static void micvnet_intr_bh_handler(struct work_struct *work);
59void micveth_send_intr(micveth_info_t *veth_info);
60
61micveth_t micveth;
62
63void dump_skb(struct sk_buff *skb, int xmit);
64
65static inline
66mic_ctx_t *veth_to_ctx(micveth_info_t *veth_info)
67{
68 return veth_info->mic_ctx;
69}
70
71static int
72micveth_set_address(struct net_device *dev, void *p)
73{
74 struct sockaddr *sa = p;
75
76 if (!is_valid_ether_addr(sa->sa_data))
77 return -EADDRNOTAVAIL;
78
79 memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN);
80 return 0;
81}
82
83#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0)
84static void
85micveth_multicast_list(struct net_device *dev)
86{
87}
88#endif
89
90static int
91micveth_deliver(struct sk_buff *skb, struct net_device *dev, micveth_info_t *veth_info)
92{
93 veth_ring_t *ring;
94 ring_queue_t *tx_queue;
95 ring_desc_t *desc;
96 ring_packet_t *packet;
97 int next_tail;
98
99 //dump_skb(skb, 1);
100
101 spin_lock(&veth_info->vi_txlock);
102 ring = &veth_info->vi_ring.ring;
103 tx_queue = &ring->r_tx;
104
105 next_tail = (tx_queue->rq_tail + 1) % tx_queue->rq_length;
106 if (next_tail == tx_queue->rq_head) {
107 // queue_full situation - just drop the packet and let the stack retry
108 spin_unlock(&veth_info->vi_txlock);
109 return 1;
110 }
111
112 desc = &tx_queue->rq_descs[tx_queue->rq_tail];
113 packet = &veth_info->vi_tx_desc[tx_queue->rq_tail];
114 packet->pd_skb = skb;
115 packet->pd_phys = mic_ctx_map_single(veth_to_ctx(veth_info),
116 skb->data, skb->len);
117 packet->pd_length = skb->len;
118 desc->rd_phys = packet->pd_phys;
119 desc->rd_length = skb->len;
120 desc->rd_valid = 1;
121
122 /*
123 * Need a write memory barrier between copying the skb data to
124 * the buffer and updating the tail pointer. NOT an smp_wmb(),
125 * because this memory barrier needs to be done even if there is
126 * a single CPU in the system.
127 */
128 wmb();
129 tx_queue->rq_tail = (tx_queue->rq_tail + 1) % tx_queue->rq_length;
130 spin_unlock(&veth_info->vi_txlock);
131
132 if (mic_vnet_mode == VNET_MODE_INTR) {
133 micveth_send_intr(veth_info);
134 }
135
136 return 0;
137}
138
139static int
140micveth_xmit(struct sk_buff *skb, struct net_device *dev)
141{
142 micveth_info_t *veth_info;
143
144 if (be16_to_cpu(skb->protocol) == ETH_P_IPV6) {
145 kfree_skb(skb);
146 dev->stats.tx_dropped++;
147 return NETDEV_TX_OK;
148 }
149
150 dev->stats.tx_packets++;
151 dev->stats.tx_bytes += skb->len;
152
153 veth_info = dev->ml_priv;
154
155 if (veth_info->vi_state != VETH_STATE_LINKUP) {
156 kfree_skb(skb);
157 dev->stats.tx_dropped++;
158 return NETDEV_TX_OK;
159 }
160
161 if (micveth_deliver(skb, dev, veth_info)) {
162 kfree_skb(skb);
163 dev->stats.tx_dropped++;
164 }
165
166 return NETDEV_TX_OK;
167}
168
169static int
170micveth_change_mtu(struct net_device *dev, int new_mtu)
171{
172 dev->mtu = new_mtu;
173 return 0;
174}
175
176/* Start callback */
177static int
178micveth_start_dev(struct net_device *dev)
179{
180 micveth_info_t *veth_info = dev->ml_priv;
181
182 micveth_start(veth_info->mic_ctx);
183 return 0;
184}
185
186/* Stop callback */
187static int
188micveth_stop_dev(struct net_device *dev)
189{
190 micveth_info_t *veth_info = dev->ml_priv;
191
192 micveth_stop(veth_info->mic_ctx);
193 return 0;
194}
195
196#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)
197static const struct net_device_ops veth_netdev_ops = {
198 .ndo_open = micveth_start_dev,
199 .ndo_stop = micveth_stop_dev,
200 .ndo_start_xmit = micveth_xmit,
201 .ndo_validate_addr = eth_validate_addr,
202#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0)
203 .ndo_set_multicast_list = micveth_multicast_list,
204#endif
205 .ndo_set_mac_address = micveth_set_address,
206 .ndo_change_mtu = micveth_change_mtu,
207};
208#endif
209
210static void
211micveth_setup(struct net_device *dev)
212{
213#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,28)
214 dev->hard_start_xmit = micveth_xmit;
215 dev->set_multicast_list = micveth_multicast_list;
216 dev->set_mac_address = micveth_set_address;
217#endif
218 ether_setup(dev);
219
220 /* Initialize the device structure. */
221#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)
222 dev->netdev_ops = &veth_netdev_ops;
223#endif
224 dev->destructor = free_netdev;
225
226 /* Fill in device structure with ethernet-generic values. */
227 dev->mtu = (MICVETH_MAX_PACKET_SIZE);
228 dev->tx_queue_len = 0;
229 dev->flags &= ~IFF_MULTICAST;
230 random_ether_addr(dev->dev_addr);
231}
232
233static int
234micveth_validate(struct nlattr *tb[], struct nlattr *data[])
235{
236 if (tb[IFLA_ADDRESS]) {
237 if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
238 return -EINVAL;
239 if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
240 return -EADDRNOTAVAIL;
241 }
242 return 0;
243}
244
245static struct rtnl_link_ops micveth_link_ops __read_mostly = {
246 .kind = "micveth",
247 .setup = micveth_setup,
248 .validate = micveth_validate,
249};
250
251static int
252micveth_probe_int(micveth_info_t *veth_info, mic_ctx_t *mic_ctx)
253{
254 struct net_device *dev_veth;
255 ring_queue_t *queue;
256 ring_desc_t *desc;
257 ring_packet_t *packet;
258 int idx;
259 int err = 0;
260
261 veth_info->vi_pdev = mic_ctx->bi_pdev;
262 veth_info->vi_sbox = (uint8_t *)((unsigned long)mic_ctx->mmio.va +
263 HOST_SBOX_BASE_ADDRESS);
264 veth_info->vi_scratch14 = (uint32_t *)((unsigned long)mic_ctx->mmio.va +
265 HOST_SBOX_BASE_ADDRESS + SBOX_SCRATCH14);
266 veth_info->vi_scratch15 = (uint32_t *)((unsigned long)mic_ctx->mmio.va +
267 HOST_SBOX_BASE_ADDRESS + SBOX_SCRATCH15);
268 veth_info->mic_ctx = mic_ctx;
269 mic_ctx->bi_vethinfo = (void *)veth_info;
270
271 spin_lock_init(&veth_info->vi_txlock);
272 spin_lock_init(&veth_info->vi_rxlock);
273
274 if (mic_vnet_mode == VNET_MODE_POLL)
275 INIT_DELAYED_WORK(&veth_info->vi_poll, micveth_poll);
276
277 // Set the current sk_buff allocation size
278 veth_info->vi_skb_mtu = MICVETH_MAX_PACKET_SIZE + 32;
279
280 // Get the physical memory address for the ring descriptors
281 veth_info->vi_ring.phys = mic_ctx_map_single(veth_to_ctx(veth_info), &veth_info->vi_ring.ring,
282 sizeof(veth_ring_t));
283 veth_info->vi_ring.length = sizeof(veth_ring_t);
284
285 queue = &veth_info->vi_ring.ring.r_tx;
286 queue->rq_head = 0;
287 queue->rq_tail = 0;
288 queue->rq_length = MICVETH_TRANSFER_FIFO_SIZE;
289
290 veth_info->vi_pend = 0;
291
292 packet = &veth_info->vi_tx_desc[0];
293 for (idx = 0; idx < queue->rq_length; idx++) {
294 desc = &queue->rq_descs[idx];
295 packet[idx].pd_skb = NULL;
296 packet[idx].pd_phys = 0;
297 packet[idx].pd_length = 0;
298
299 desc->rd_phys = 0;
300 desc->rd_length = 0;
301 desc->rd_valid = 0;
302 }
303
304 // This is the recieve end.
305 queue = &veth_info->vi_ring.ring.r_rx;
306 queue->rq_head = 0;
307 queue->rq_tail = 0;
308 queue->rq_length = MICVETH_TRANSFER_FIFO_SIZE;
309
310 packet = &veth_info->vi_rx_desc[0];
311 for (idx = 0; idx < queue->rq_length; idx++) {
312 desc = &queue->rq_descs[idx];
313 if (!(packet[idx].pd_skb = dev_alloc_skb(veth_info->vi_skb_mtu)))
314 return -ENOMEM;
315 packet[idx].pd_phys = mic_ctx_map_single(veth_to_ctx(veth_info), packet[idx].pd_skb->data,
316 veth_info->vi_skb_mtu);
317 packet[idx].pd_length = veth_info->vi_skb_mtu;
318
319 desc->rd_phys = packet[idx].pd_phys;
320 desc->rd_length = packet[idx].pd_length;
321 desc->rd_valid = 1;
322 }
323#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
324 if ((dev_veth = alloc_netdev(sizeof(micveth_info_t), "mic%d", micveth_setup)) == NULL) {
325#else
326 if ((dev_veth = alloc_netdev(sizeof(micveth_info_t), "mic%d", NET_NAME_UNKNOWN, micveth_setup)) == NULL) {
327#endif
328 return -ENOMEM;
329 }
330
331 veth_info->vi_netdev = dev_veth;
332 dev_veth->ml_priv = veth_info;
333 dev_veth->rtnl_link_ops = &micveth_link_ops;
334
335 if ((err = register_netdev(dev_veth)) < 0) {
336 printk("register netdev failed %d\n", err);
337 free_netdev(dev_veth);
338 return err;
339 }
340
341 veth_info->vi_state = VETH_STATE_INITIALIZED;
342 return 0;
343}
344
345static ssize_t show_veth(struct device *dev,
346 struct device_attribute *attr, char *buf);
347DEVICE_ATTR(veth, S_IRUGO, show_veth, NULL);
348
349static int
350micveth_init_int(int num_bds, struct device *dev)
351{
352 int bd;
353 int err = 0;
354
355 micveth.lv_num_interfaces = num_bds;
356 micveth.lv_num_clients = num_bds;
357 micveth.lv_active_clients = 0;
358 micveth.lv_num_links_remaining = num_bds;
359
360 BUG_ON(rtnl_link_register(&micveth_link_ops));
361
362 // Allocate space for the control of each device in the system.
363 micveth.lv_info = kmalloc(sizeof(micveth_info_t) * num_bds, GFP_KERNEL);
364
365 // Initialize state mutex. Overloaded use for several fields.
366 mutex_init(&micveth.lv_state_mutex);
367
368 // Setup of timer for probeing active mic clients. When the total active board
369 // count is zero the poll is not running.
370 micveth.lv_pollstate = CLIENT_POLL_STOPPED;
371 INIT_DELAYED_WORK(&micveth.lv_poll, micveth_clientpoll);
372 init_waitqueue_head(&micveth.lv_wq);
373
374 // Init each of the existing boards.
375 for (bd = 0; bd < num_bds; bd++) {
376 micveth_probe_int(&micveth.lv_info[bd], &mic_data.dd_bi[bd]->bi_ctx);
377 }
378
379 err = device_create_file(dev, &dev_attr_veth);
380 return err;
381}
382
383static void
384micveth_exit_int(void)
385{
386 mic_ctx_t *mic_ctx = kmalloc(sizeof(mic_ctx_t), GFP_KERNEL);
387 micveth_info_t *veth_info;
388 ring_packet_t *packet;
389 int bd;
390 int idx;
391
392 rtnl_link_unregister(&micveth_link_ops);
393
394 for (bd = 0; bd < micveth.lv_num_clients; bd++) {
395 veth_info = &micveth.lv_info[bd];
396
397 /* veth_info->mic_ctx == mic_data.dd_bi[bd] is freed in
398 remove so cannot be used in exit */
399 mic_ctx->bi_vethinfo = veth_info;
400 micveth_stop(mic_ctx);
401
402#if WA_UNMAP_AT_RMMOD
403 mic_ctx_unmap_single(veth_to_ctx(veth_info), veth_info->vi_ring.phys,
404 sizeof(veth_ring_t));
405#endif
406
407 for (idx = 0; idx < veth_info->vi_ring.ring.r_tx.rq_length; idx++) {
408 packet = &veth_info->vi_tx_desc[idx];
409 if (packet->pd_skb != NULL) {
410#if WA_UNMAP_AT_RMMOD
411 mic_ctx_unmap_single(veth_to_ctx(veth_info), packet->pd_phys,
412 packet->pd_skb->len);
413#endif
414 kfree_skb(packet->pd_skb);
415 }
416 }
417
418 for (idx = 0; idx < veth_info->vi_ring.ring.r_rx.rq_length; idx++) {
419 packet = &veth_info->vi_rx_desc[idx];
420#if WA_UNMAP_AT_RMMOD
421 mic_ctx_unmap_single(veth_to_ctx(veth_info), packet->pd_phys, packet->pd_skb->len);
422#endif
423 kfree_skb(packet->pd_skb);
424 }
425 }
426
427 kfree(mic_ctx);
428 kfree(micveth.lv_info);
429}
430
431static int
432micveth_start_int(mic_ctx_t *mic_ctx)
433{
434 micveth_info_t *veth_info = &micveth.lv_info[mic_ctx->bi_id];
435
436 // Eventuall (very soon) most of the descriptor allocation for a board will be done here
437 if (veth_info->vi_state != VETH_STATE_INITIALIZED)
438 return 0;
439
440 mutex_lock(&micveth.lv_state_mutex);
441
442 if (micveth.lv_pollstate == CLIENT_POLL_STOPPED) {
443 schedule_delayed_work(&micveth.lv_poll, msecs_to_jiffies(MICVETH_CLIENT_TIMER_DELAY));
444 micveth.lv_pollstate = CLIENT_POLL_RUNNING;
445 }
446
447 micveth.lv_active_clients++;
448 mutex_unlock(&micveth.lv_state_mutex);
449
450 veth_info->vi_pend = 0;
451
452 veth_info->vi_ring.ring.r_tx.rq_head = 0;
453 veth_info->vi_ring.ring.r_tx.rq_tail = 0;
454
455 veth_info->vi_ring.ring.r_rx.rq_head = 0;
456 veth_info->vi_ring.ring.r_rx.rq_tail = 0;
457 veth_info->vi_state = VETH_STATE_LINKDOWN;
458
459 if (mic_vnet_mode == VNET_MODE_INTR) {
460 snprintf(veth_info->vi_wqname, sizeof(veth_info->vi_wqname),
461 "VNET INTR %d\n", mic_ctx->bi_id);
462 veth_info->vi_wq = create_singlethread_workqueue(veth_info->vi_wqname);
463 INIT_WORK(&veth_info->vi_bh, micvnet_intr_bh_handler);
464
465 // Install interrupt handler on doorbell 3
466 mic_reg_irqhandler(mic_ctx, 3, "Host DoorBell 3",
467 micvnet_host_doorbell_intr_handler);
468 }
469
470 return 0;
471}
472
473static void
474micveth_stop_int(mic_ctx_t *mic_ctx)
475{
476 micveth_info_t *veth_info = (micveth_info_t *)(mic_ctx->bi_vethinfo);
477
478 if (veth_info->vi_state == VETH_STATE_INITIALIZED)
479 return;
480
481 mutex_lock(&micveth.lv_state_mutex);
482
483 if (mic_vnet_mode == VNET_MODE_INTR) {
484 // Remove interrupt handler on doorbell 3
485 mic_unreg_irqhandler(mic_ctx, 3, "Host DoorBell 3");
486
487 destroy_workqueue(veth_info->vi_wq);
488 }
489
490 micveth.lv_active_clients--;
491 veth_info->vi_state = VETH_STATE_INITIALIZED;
492
493 if (micveth.lv_active_clients) {
494 mutex_unlock(&micveth.lv_state_mutex);
495 return;
496 }
497
498 micveth.lv_num_links_remaining = micveth.lv_num_clients;
499
500#if PWR_MGMT_NO_POLL_AFTER_LINKS_UP
501 micveth.lv_pollstate = CLIENT_POLL_STOPPED;
502 mutex_unlock(&micveth.lv_state_mutex);
503#else
504 micveth.lv_pollstate = CLIENT_POLL_STOPPING;
505 mutex_unlock(&micveth.lv_state_mutex);
506 wait_event(micveth.lv_wq, micveth.lv_pollstate == CLIENT_POLL_STOPPED);
507#endif
508}
509
510#define NO_SRATCHREGREAD_AFTER_CONNECT 1
511static void
512micveth_clientpoll(struct work_struct *work)
513{
514 micveth_info_t *veth_info;
515 uint32_t transRingHi;
516 uint32_t transRingLo;
517 uint32_t scratch14 = 0;
518 uint32_t scratch15 = 0;
519 int bd;
520 static int enter = 0;
521
522 if (enter == 0)
523 {
524 printk("micveth is polling\n");
525 enter = 1;
526 }
527
528 mutex_lock(&micveth.lv_state_mutex);
529 if (micveth.lv_pollstate == CLIENT_POLL_STOPPING) {
530 micveth.lv_pollstate = CLIENT_POLL_STOPPED;
531 mutex_unlock(&micveth.lv_state_mutex);
532 wake_up(&micveth.lv_wq);
533 return;
534 }
535
536 // Check for state changes for each board in the system
537 for (bd = 0; bd < micveth.lv_num_clients; bd++) {
538 veth_info = &micveth.lv_info[bd];
539
540 // Do not poll boards that have not had the interface started.
541 if (veth_info->vi_state == VETH_STATE_INITIALIZED) {
542 break;
543 }
544
545#ifdef NO_SRATCHREGREAD_AFTER_CONNECT
546 if(veth_info->vi_state != VETH_STATE_LINKUP) {
547#endif
548 scratch14 = readl(veth_info->vi_scratch14);
549 scratch15 = readl(veth_info->vi_scratch15);
550#ifdef NO_SRATCHREGREAD_AFTER_CONNECT
551 }
552#endif
553
554 if (veth_info->vi_state == VETH_STATE_LINKUP) {
555 if (scratch14 == MICVETH_LINK_DOWN_MAGIC) {
556 veth_info->vi_state = VETH_STATE_LINKDOWN;
557 }
558 } else if (veth_info->vi_state == VETH_STATE_LINKDOWN) {
559 if (scratch14 == MICVETH_LINK_UP_MAGIC) {
560 // Write the transfer ring address.
561 transRingHi = (uint32_t)(veth_info->vi_ring.phys >> 32);
562 transRingLo = (uint32_t)(veth_info->vi_ring.phys & 0xffffffff);
563
564 writel(transRingLo, veth_info->vi_scratch14);
565 writel(transRingHi, veth_info->vi_scratch15);
566
567 veth_info->vi_state = VETH_STATE_LINKUP;
568 printk("MIC virtual ethernet up for board %d\n", bd);
569#ifdef MIC_IS_EMULATION
570 printk("Card wrote Magic: It must be UP!\n");
571#endif
572
573 if (mic_vnet_mode == VNET_MODE_POLL) {
574 schedule_delayed_work(&veth_info->vi_poll,
575 msecs_to_jiffies(MICVETH_POLL_TIMER_DELAY));
576 }
577
578 micveth.lv_num_links_remaining--;
579 }
580#ifdef MIC_IS_EMULATION
581 else if (scratch14) {
582 printk("---> 0x%x \n", scratch14);
583 writel(0x0, veth_info->vi_scratch14);
584 }
585#endif
586 }
587 }
588
589 mutex_unlock(&micveth.lv_state_mutex);
590
591#if PWR_MGMT_NO_POLL_AFTER_LINKS_UP
592 if (micveth.lv_num_links_remaining)
593#endif
594 schedule_delayed_work(&micveth.lv_poll, msecs_to_jiffies(MICVETH_CLIENT_TIMER_DELAY));
595}
596
597static int
598micvnet_host_doorbell_intr_handler(mic_ctx_t *mic_ctx, int doorbell)
599{
600 micveth_info_t *veth_info;
601 veth_info = &micveth.lv_info[mic_ctx->bi_id];
602 queue_work(veth_info->vi_wq, &veth_info->vi_bh);
603 return 0;
604}
605
606void
607micveth_send_intr(micveth_info_t *veth_info)
608{
609 mic_ctx_t *mic_ctx = veth_info->mic_ctx;
610 mic_send_vnet_intr(mic_ctx);
611}
612
613void
614_micveth_process_descriptors(micveth_info_t *veth_info)
615{
616 veth_ring_t *ring = &veth_info->vi_ring.ring;
617 ring_queue_t *rx_queue = &ring->r_rx;
618 ring_queue_t *tx_queue = &ring->r_tx;
619 ring_desc_t *desc;
620 ring_packet_t *packet;
621 struct sk_buff *skb;
622 int receive_skb = 0;
623 int err;
624
625 if (veth_info->vi_state != VETH_STATE_LINKUP) {
626 return;
627 }
628
629 spin_lock_bh(&veth_info->vi_rxlock);
630
631 while (rx_queue->rq_head != rx_queue->rq_tail) {
632 desc = &rx_queue->rq_descs[rx_queue->rq_head];
633
634 veth_info->vi_netdev->stats.rx_packets++;
635 veth_info->vi_netdev->stats.rx_bytes += desc->rd_length;
636
637 packet = &veth_info->vi_rx_desc[rx_queue->rq_head];
638
639 skb = packet->pd_skb;
640 skb_put(skb, desc->rd_length);
641
642 //dump_skb(skb, 0);
643 mic_ctx_unmap_single(veth_to_ctx(veth_info), packet->pd_phys, veth_info->vi_skb_mtu);
644 packet->pd_skb = dev_alloc_skb(veth_info->vi_skb_mtu);
645 packet->pd_phys = mic_ctx_map_single(veth_to_ctx(veth_info), packet->pd_skb->data,
646 veth_info->vi_skb_mtu);
647 desc->rd_phys = packet->pd_phys;
648 desc->rd_length = packet->pd_length;
649
650 skb->dev = veth_info->vi_netdev;
651 skb->protocol = eth_type_trans(skb, skb->dev);
652 skb->ip_summed = CHECKSUM_NONE;
653
654 err = netif_receive_skb(skb);
655 /*
656 * Need a general memory barrier between copying the data from
657 * the buffer and updating the head pointer. It's the general
658 * mb() because we're ordering the read of the data with the write.
659 */
660 mb();
661 rx_queue->rq_head = (rx_queue->rq_head + 1) % rx_queue->rq_length;
662 receive_skb++;
663 }
664
665 /* Send intr to TX so that pending SKB's can be freed */
666 if (receive_skb && mic_vnet_mode == VNET_MODE_INTR) {
667 micveth_send_intr(veth_info);
668 }
669
670 spin_unlock_bh(&veth_info->vi_rxlock);
671
672 spin_lock_bh(&veth_info->vi_txlock);
673
674 // Also handle completed tx requests
675 while (veth_info->vi_pend != tx_queue->rq_head) {
676 desc = &tx_queue->rq_descs[veth_info->vi_pend];
677 packet = &veth_info->vi_tx_desc[veth_info->vi_pend];
678
679 skb = packet->pd_skb;
680 packet->pd_skb = NULL;
681
682 mic_ctx_unmap_single(veth_to_ctx(veth_info), packet->pd_phys, skb->len);
683 packet->pd_phys = 0;
684
685 kfree_skb(skb);
686
687 veth_info->vi_pend = (veth_info->vi_pend + 1) % tx_queue->rq_length;
688 }
689
690 spin_unlock_bh(&veth_info->vi_txlock);
691
692 if (mic_vnet_mode == VNET_MODE_POLL) {
693 schedule_delayed_work(&veth_info->vi_poll, msecs_to_jiffies(MICVETH_POLL_TIMER_DELAY));
694 }
695}
696
697static void
698micvnet_intr_bh_handler(struct work_struct *work)
699{
700 micveth_info_t *veth_info = container_of(work, micveth_info_t, vi_bh);
701 _micveth_process_descriptors(veth_info);
702}
703
704static void
705micveth_poll(struct work_struct *work)
706{
707 micveth_info_t *veth_info = container_of(work, micveth_info_t, vi_poll.work);
708
709 _micveth_process_descriptors(veth_info);
710}
711
712static ssize_t
713show_veth(struct device *dev, struct device_attribute *attr, char *buf)
714{
715 return snprintf(buf, PAGE_SIZE, "%s\n",
716 micveth.lv_pollstate == CLIENT_POLL_RUNNING ?
717 "running" : "stopped");
718}
719
720/*
721 VNET driver public API. These are simply wrappers which either invoke the old
722 interrupt/poll mode functions or the new DMA mode functions. These are temporary and
723 will be phased out with the old interrupt/poll mode so only the DMA mode will be around
724 eventually.
725 */
726int __init
727micveth_init(struct device *dev)
728{
729 printk("vnet: mode: %s, buffers: %d\n",
730 mic_vnet_modes[mic_vnet_mode], vnet_num_buffers);
731
732 if (mic_vnet_mode == VNET_MODE_DMA)
733 return micvnet_init(dev);
734 /* Intr/poll modes use micveth_init_legacy */
735 return 0;
736}
737
738int __init
739micveth_init_legacy(int num_bds, struct device *dev)
740{
741 if (mic_vnet_mode != VNET_MODE_DMA)
742 return micveth_init_int(num_bds, dev);
743 /* DMA mode uses micveth_init */
744 return 0;
745}
746
747void
748micveth_exit(void)
749{
750 if (mic_vnet_mode == VNET_MODE_DMA)
751 micvnet_exit();
752 else
753 micveth_exit_int();
754}
755
756int
757micveth_probe(mic_ctx_t *mic_ctx)
758{
759 if (mic_vnet_mode == VNET_MODE_DMA)
760 return micvnet_probe(mic_ctx);
761 /* No support for micveth_probe in legacy intr/poll modes */
762 return 0;
763}
764
765void
766micveth_remove(mic_ctx_t *mic_ctx)
767{
768 if (mic_vnet_mode == VNET_MODE_DMA)
769 micvnet_remove(mic_ctx);
770 /* No support for micveth_remove in legacy intr/poll modes */
771}
772
773int
774micveth_start(mic_ctx_t *mic_ctx)
775{
776 micveth_info_t *veth_info = mic_ctx->bi_vethinfo;
777 int err;
778
779 if (mic_vnet_mode == VNET_MODE_DMA)
780 err = micvnet_start(mic_ctx);
781 else
782 err = micveth_start_int(mic_ctx);
783
784 if (!err)
785 netif_carrier_on(veth_info->vi_netdev);
786
787 return err;
788}
789
790void
791micveth_stop(mic_ctx_t *mic_ctx)
792{
793 micveth_info_t *veth_info = mic_ctx->bi_vethinfo;
794
795 if (mic_vnet_mode == VNET_MODE_DMA)
796 micvnet_stop(mic_ctx);
797 else
798 micveth_stop_int(mic_ctx);
799
800 if (veth_info)
801 netif_carrier_off(veth_info->vi_netdev);
802}