Commit 20dd3850bcf860561496827b711fa10fecf6e787

Authored by Oliver Hartkopp
Committed by David S. Miller
1 parent 75ed0a8972

can: Speed up CAN frame receiption by using ml_priv

this patch removes the hlist that contains the CAN receiver filter lists.
It uses the 'midlayer private' pointer ml_priv and links the filters directly
to the CAN netdevice, which allows to omit the walk through the complete CAN
devices hlist for each received CAN frame.

This patch is tested and does not remove any locking.

Signed-off-by: Oliver Hartkopp <oliver@hartkopp.net>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 3 changed files with 96 additions and 119 deletions Side-by-side Diff

... ... @@ -77,8 +77,8 @@
77 77 module_param(stats_timer, int, S_IRUGO);
78 78 MODULE_PARM_DESC(stats_timer, "enable timer for statistics (default:on)");
79 79  
80   -HLIST_HEAD(can_rx_dev_list);
81   -static struct dev_rcv_lists can_rx_alldev_list;
  80 +/* receive filters subscribed for 'all' CAN devices */
  81 +struct dev_rcv_lists can_rx_alldev_list;
82 82 static DEFINE_SPINLOCK(can_rcvlists_lock);
83 83  
84 84 static struct kmem_cache *rcv_cache __read_mostly;
... ... @@ -292,28 +292,10 @@
292 292  
293 293 static struct dev_rcv_lists *find_dev_rcv_lists(struct net_device *dev)
294 294 {
295   - struct dev_rcv_lists *d = NULL;
296   - struct hlist_node *n;
297   -
298   - /*
299   - * find receive list for this device
300   - *
301   - * The hlist_for_each_entry*() macros curse through the list
302   - * using the pointer variable n and set d to the containing
303   - * struct in each list iteration. Therefore, after list
304   - * iteration, d is unmodified when the list is empty, and it
305   - * points to last list element, when the list is non-empty
306   - * but no match in the loop body is found. I.e. d is *not*
307   - * NULL when no match is found. We can, however, use the
308   - * cursor variable n to decide if a match was found.
309   - */
310   -
311   - hlist_for_each_entry_rcu(d, n, &can_rx_dev_list, list) {
312   - if (d->dev == dev)
313   - break;
314   - }
315   -
316   - return n ? d : NULL;
  295 + if (!dev)
  296 + return &can_rx_alldev_list;
  297 + else
  298 + return (struct dev_rcv_lists *)dev->ml_priv;
317 299 }
318 300  
319 301 /**
... ... @@ -468,16 +450,6 @@
468 450 EXPORT_SYMBOL(can_rx_register);
469 451  
470 452 /*
471   - * can_rx_delete_device - rcu callback for dev_rcv_lists structure removal
472   - */
473   -static void can_rx_delete_device(struct rcu_head *rp)
474   -{
475   - struct dev_rcv_lists *d = container_of(rp, struct dev_rcv_lists, rcu);
476   -
477   - kfree(d);
478   -}
479   -
480   -/*
481 453 * can_rx_delete_receiver - rcu callback for single receiver entry removal
482 454 */
483 455 static void can_rx_delete_receiver(struct rcu_head *rp)
... ... @@ -541,7 +513,6 @@
541 513 "dev %s, id %03X, mask %03X\n",
542 514 DNAME(dev), can_id, mask);
543 515 r = NULL;
544   - d = NULL;
545 516 goto out;
546 517 }
547 518  
... ... @@ -552,10 +523,10 @@
552 523 can_pstats.rcv_entries--;
553 524  
554 525 /* remove device structure requested by NETDEV_UNREGISTER */
555   - if (d->remove_on_zero_entries && !d->entries)
556   - hlist_del_rcu(&d->list);
557   - else
558   - d = NULL;
  526 + if (d->remove_on_zero_entries && !d->entries) {
  527 + kfree(d);
  528 + dev->ml_priv = NULL;
  529 + }
559 530  
560 531 out:
561 532 spin_unlock(&can_rcvlists_lock);
... ... @@ -563,10 +534,6 @@
563 534 /* schedule the receiver item for deletion */
564 535 if (r)
565 536 call_rcu(&r->rcu, can_rx_delete_receiver);
566   -
567   - /* schedule the device structure for deletion */
568   - if (d)
569   - call_rcu(&d->rcu, can_rx_delete_device);
570 537 }
571 538 EXPORT_SYMBOL(can_rx_unregister);
572 539  
573 540  
574 541  
575 542  
576 543  
577 544  
578 545  
... ... @@ -780,48 +747,35 @@
780 747  
781 748 case NETDEV_REGISTER:
782 749  
783   - /*
784   - * create new dev_rcv_lists for this device
785   - *
786   - * N.B. zeroing the struct is the correct initialization
787   - * for the embedded hlist_head structs.
788   - * Another list type, e.g. list_head, would require
789   - * explicit initialization.
790   - */
791   -
  750 + /* create new dev_rcv_lists for this device */
792 751 d = kzalloc(sizeof(*d), GFP_KERNEL);
793 752 if (!d) {
794 753 printk(KERN_ERR
795 754 "can: allocation of receive list failed\n");
796 755 return NOTIFY_DONE;
797 756 }
798   - d->dev = dev;
  757 + BUG_ON(dev->ml_priv);
  758 + dev->ml_priv = d;
799 759  
800   - spin_lock(&can_rcvlists_lock);
801   - hlist_add_head_rcu(&d->list, &can_rx_dev_list);
802   - spin_unlock(&can_rcvlists_lock);
803   -
804 760 break;
805 761  
806 762 case NETDEV_UNREGISTER:
807 763 spin_lock(&can_rcvlists_lock);
808 764  
809   - d = find_dev_rcv_lists(dev);
  765 + d = dev->ml_priv;
810 766 if (d) {
811   - if (d->entries) {
  767 + if (d->entries)
812 768 d->remove_on_zero_entries = 1;
813   - d = NULL;
814   - } else
815   - hlist_del_rcu(&d->list);
  769 + else {
  770 + kfree(d);
  771 + dev->ml_priv = NULL;
  772 + }
816 773 } else
817 774 printk(KERN_ERR "can: notifier: receive list not "
818 775 "found for dev %s\n", dev->name);
819 776  
820 777 spin_unlock(&can_rcvlists_lock);
821 778  
822   - if (d)
823   - call_rcu(&d->rcu, can_rx_delete_device);
824   -
825 779 break;
826 780 }
827 781  
828 782  
... ... @@ -853,21 +807,13 @@
853 807 {
854 808 printk(banner);
855 809  
  810 + memset(&can_rx_alldev_list, 0, sizeof(can_rx_alldev_list));
  811 +
856 812 rcv_cache = kmem_cache_create("can_receiver", sizeof(struct receiver),
857 813 0, 0, NULL);
858 814 if (!rcv_cache)
859 815 return -ENOMEM;
860 816  
861   - /*
862   - * Insert can_rx_alldev_list for reception on all devices.
863   - * This struct is zero initialized which is correct for the
864   - * embedded hlist heads, the dev pointer, and the entries counter.
865   - */
866   -
867   - spin_lock(&can_rcvlists_lock);
868   - hlist_add_head_rcu(&can_rx_alldev_list.list, &can_rx_dev_list);
869   - spin_unlock(&can_rcvlists_lock);
870   -
871 817 if (stats_timer) {
872 818 /* the statistics are updated every second (timer triggered) */
873 819 setup_timer(&can_stattimer, can_stat_update, 0);
... ... @@ -887,8 +833,7 @@
887 833  
888 834 static __exit void can_exit(void)
889 835 {
890   - struct dev_rcv_lists *d;
891   - struct hlist_node *n, *next;
  836 + struct net_device *dev;
892 837  
893 838 if (stats_timer)
894 839 del_timer(&can_stattimer);
895 840  
... ... @@ -900,14 +845,19 @@
900 845 unregister_netdevice_notifier(&can_netdev_notifier);
901 846 sock_unregister(PF_CAN);
902 847  
903   - /* remove can_rx_dev_list */
904   - spin_lock(&can_rcvlists_lock);
905   - hlist_del(&can_rx_alldev_list.list);
906   - hlist_for_each_entry_safe(d, n, next, &can_rx_dev_list, list) {
907   - hlist_del(&d->list);
908   - kfree(d);
  848 + /* remove created dev_rcv_lists from still registered CAN devices */
  849 + rcu_read_lock();
  850 + for_each_netdev_rcu(&init_net, dev) {
  851 + if (dev->type == ARPHRD_CAN && dev->ml_priv){
  852 +
  853 + struct dev_rcv_lists *d = dev->ml_priv;
  854 +
  855 + BUG_ON(d->entries);
  856 + kfree(d);
  857 + dev->ml_priv = NULL;
  858 + }
909 859 }
910   - spin_unlock(&can_rcvlists_lock);
  860 + rcu_read_unlock();
911 861  
912 862 rcu_barrier(); /* Wait for completion of call_rcu()'s */
913 863  
... ... @@ -63,10 +63,8 @@
63 63  
64 64 enum { RX_ERR, RX_ALL, RX_FIL, RX_INV, RX_EFF, RX_MAX };
65 65  
  66 +/* per device receive filters linked at dev->ml_priv */
66 67 struct dev_rcv_lists {
67   - struct hlist_node list;
68   - struct rcu_head rcu;
69   - struct net_device *dev;
70 68 struct hlist_head rx[RX_MAX];
71 69 struct hlist_head rx_sff[0x800];
72 70 int remove_on_zero_entries;
... ... @@ -45,6 +45,7 @@
45 45 #include <linux/proc_fs.h>
46 46 #include <linux/list.h>
47 47 #include <linux/rcupdate.h>
  48 +#include <linux/if_arp.h>
48 49 #include <linux/can/core.h>
49 50  
50 51 #include "af_can.h"
... ... @@ -84,6 +85,9 @@
84 85 [RX_EFF] = "rx_eff",
85 86 };
86 87  
  88 +/* receive filters subscribed for 'all' CAN devices */
  89 +extern struct dev_rcv_lists can_rx_alldev_list;
  90 +
87 91 /*
88 92 * af_can statistics stuff
89 93 */
... ... @@ -190,10 +194,6 @@
190 194  
191 195 /*
192 196 * proc read functions
193   - *
194   - * From known use-cases we expect about 10 entries in a receive list to be
195   - * printed in the proc_fs. So PAGE_SIZE is definitely enough space here.
196   - *
197 197 */
198 198  
199 199 static void can_print_rcvlist(struct seq_file *m, struct hlist_head *rx_list,
... ... @@ -202,7 +202,6 @@
202 202 struct receiver *r;
203 203 struct hlist_node *n;
204 204  
205   - rcu_read_lock();
206 205 hlist_for_each_entry_rcu(r, n, rx_list, list) {
207 206 char *fmt = (r->can_id & CAN_EFF_FLAG)?
208 207 " %-5s %08X %08x %08x %08x %8ld %s\n" :
... ... @@ -212,7 +211,6 @@
212 211 (unsigned long)r->func, (unsigned long)r->data,
213 212 r->matches, r->ident);
214 213 }
215   - rcu_read_unlock();
216 214 }
217 215  
218 216 static void can_print_recv_banner(struct seq_file *m)
219 217  
220 218  
221 219  
222 220  
223 221  
... ... @@ -346,24 +344,39 @@
346 344 .release = single_release,
347 345 };
348 346  
  347 +static inline void can_rcvlist_proc_show_one(struct seq_file *m, int idx,
  348 + struct net_device *dev,
  349 + struct dev_rcv_lists *d)
  350 +{
  351 + if (!hlist_empty(&d->rx[idx])) {
  352 + can_print_recv_banner(m);
  353 + can_print_rcvlist(m, &d->rx[idx], dev);
  354 + } else
  355 + seq_printf(m, " (%s: no entry)\n", DNAME(dev));
  356 +
  357 +}
  358 +
349 359 static int can_rcvlist_proc_show(struct seq_file *m, void *v)
350 360 {
351 361 /* double cast to prevent GCC warning */
352 362 int idx = (int)(long)m->private;
  363 + struct net_device *dev;
353 364 struct dev_rcv_lists *d;
354   - struct hlist_node *n;
355 365  
356 366 seq_printf(m, "\nreceive list '%s':\n", rx_list_name[idx]);
357 367  
358 368 rcu_read_lock();
359   - hlist_for_each_entry_rcu(d, n, &can_rx_dev_list, list) {
360 369  
361   - if (!hlist_empty(&d->rx[idx])) {
362   - can_print_recv_banner(m);
363   - can_print_rcvlist(m, &d->rx[idx], d->dev);
364   - } else
365   - seq_printf(m, " (%s: no entry)\n", DNAME(d->dev));
  370 + /* receive list for 'all' CAN devices (dev == NULL) */
  371 + d = &can_rx_alldev_list;
  372 + can_rcvlist_proc_show_one(m, idx, NULL, d);
  373 +
  374 + /* receive list for registered CAN devices */
  375 + for_each_netdev_rcu(&init_net, dev) {
  376 + if (dev->type == ARPHRD_CAN && dev->ml_priv)
  377 + can_rcvlist_proc_show_one(m, idx, dev, dev->ml_priv);
366 378 }
  379 +
367 380 rcu_read_unlock();
368 381  
369 382 seq_putc(m, '\n');
370 383  
371 384  
372 385  
373 386  
374 387  
... ... @@ -383,34 +396,50 @@
383 396 .release = single_release,
384 397 };
385 398  
  399 +static inline void can_rcvlist_sff_proc_show_one(struct seq_file *m,
  400 + struct net_device *dev,
  401 + struct dev_rcv_lists *d)
  402 +{
  403 + int i;
  404 + int all_empty = 1;
  405 +
  406 + /* check wether at least one list is non-empty */
  407 + for (i = 0; i < 0x800; i++)
  408 + if (!hlist_empty(&d->rx_sff[i])) {
  409 + all_empty = 0;
  410 + break;
  411 + }
  412 +
  413 + if (!all_empty) {
  414 + can_print_recv_banner(m);
  415 + for (i = 0; i < 0x800; i++) {
  416 + if (!hlist_empty(&d->rx_sff[i]))
  417 + can_print_rcvlist(m, &d->rx_sff[i], dev);
  418 + }
  419 + } else
  420 + seq_printf(m, " (%s: no entry)\n", DNAME(dev));
  421 +}
  422 +
386 423 static int can_rcvlist_sff_proc_show(struct seq_file *m, void *v)
387 424 {
  425 + struct net_device *dev;
388 426 struct dev_rcv_lists *d;
389   - struct hlist_node *n;
390 427  
391 428 /* RX_SFF */
392 429 seq_puts(m, "\nreceive list 'rx_sff':\n");
393 430  
394 431 rcu_read_lock();
395   - hlist_for_each_entry_rcu(d, n, &can_rx_dev_list, list) {
396   - int i, all_empty = 1;
397   - /* check wether at least one list is non-empty */
398   - for (i = 0; i < 0x800; i++)
399   - if (!hlist_empty(&d->rx_sff[i])) {
400   - all_empty = 0;
401   - break;
402   - }
403 432  
404   - if (!all_empty) {
405   - can_print_recv_banner(m);
406   - for (i = 0; i < 0x800; i++) {
407   - if (!hlist_empty(&d->rx_sff[i]))
408   - can_print_rcvlist(m, &d->rx_sff[i],
409   - d->dev);
410   - }
411   - } else
412   - seq_printf(m, " (%s: no entry)\n", DNAME(d->dev));
  433 + /* sff receive list for 'all' CAN devices (dev == NULL) */
  434 + d = &can_rx_alldev_list;
  435 + can_rcvlist_sff_proc_show_one(m, NULL, d);
  436 +
  437 + /* sff receive list for registered CAN devices */
  438 + for_each_netdev_rcu(&init_net, dev) {
  439 + if (dev->type == ARPHRD_CAN && dev->ml_priv)
  440 + can_rcvlist_sff_proc_show_one(m, dev, dev->ml_priv);
413 441 }
  442 +
414 443 rcu_read_unlock();
415 444  
416 445 seq_putc(m, '\n');