* Re: CPU: 0 Not tainted (3.1.9+ #1) when ifconfig rose0 down
From: Folkert van Heusden @ 2012-08-05 17:08 UTC (permalink / raw)
To: Bernard Pidoux, folkert; +Cc: Eric W. Biederman, linux-hams, Linux Netdev List
Good luck!
I'm to busy myself with debugging the baycom driver.
Can do at most 2 steps a day and it are 15 steps... (54k changesets)
Bernard Pidoux <bernard.pidoux@free.fr> wrote:
>Thanks for suggesting a bissect. However I guess that this bug has
>always been there !
>
>I am not professionaly involved in programming, however I committed a
>few patches for ROSE, AX.25 and NetRom modules since a few years.
>
>I reactivated netconfig and here is the report showing that kernel panic
>occurs when rose_device_event is triggered when issuing command
>ifconfig rose0 down
>
>[ 1215.153302] rose_kill_by_device() rose->neighbour->use 0
>[ 1215.153316] BUG: unable to handle kernel NULL pointer dereference at
>000000000000002a
>[ 1215.153321] IP: [<ffffffffa065e37d>] rose_device_event+0x11d/0x160 [rose]
>[ 1215.153333] PGD 36340067 PUD 359fa067 PMD 0
>[ 1215.153338] Oops: 0002 [#1] SMP
>[ 1215.153343] CPU 1
>[ 1215.153344] Modules linked in: af_packet rose mkiss ax25 nfsd
>exportfs nfs nfs_acl auth_rpcgss fscache lockd sunrpc netconsole
>configfs bnep bluetooth rfkill snd_hda_codec_idt snd_hda_intel
>snd_hda_codec snd_hwdep snd_pcm snd_page_alloc snd_timer snd
>i82975x_edac soundcore e1000e ppdev parport_pc parport edac_core
>iTCO_wdt iTCO_vendor_support serio_raw i2c_i801 processor coretemp evdev
>ipv6 autofs4 usbhid hid ext4 crc16 jbd2 sd_mod crc_t10dif firewire_ohci
>firewire_core ehci_hcd crc_itu_t uhci_hcd usbcore usb_common nouveau
>button video mxm_wmi wmi i2c_algo_bit drm_kms_helper ttm drm i2c_core
>ahci libahci ata_piix pata_marvell libata scsi_mod [last unloaded:
>microcode]
>[ 1215.153395]
>[ 1215.153398] Pid: 18637, comm: ifconfig Not tainted 3.4.7 #8
>/D975XBX2
>[ 1215.153404] RIP: 0010:[<ffffffffa065e37d>] [<ffffffffa065e37d>]
>rose_device_event+0x11d/0x160 [rose]
>[ 1215.153411] RSP: 0000:ffff880035271ca8 EFLAGS: 00010296
>[ 1215.153414] RAX: 0000000000000000 RBX: ffff88003d0c2838 RCX:
>0000000230924000
>[ 1215.153417] RDX: 0000000000000002 RSI: 0000000000000001 RDI:
>ffffffffa0665f28
>[ 1215.153420] RBP: ffff880035271cb8 R08: 0000000000000002 R09:
>0000000000000000
>[ 1215.153422] R10: 0000000000000003 R11: 0000000000000000 R12:
>ffff88003a9e1000
>[ 1215.153425] R13: 00000000fffffff1 R14: ffffffffa05b0000 R15:
>0000000000000000
>[ 1215.153429] FS: 00007fb7a318f700(0000) GS:ffff88003fa80000(0000)
>knlGS:0000000000000000
>[ 1215.153433] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
>[ 1215.153435] CR2: 000000000000002a CR3: 00000000393fd000 CR4:
>00000000000007e0
>[ 1215.153438] DR0: 0000000000000000 DR1: 0000000000000000 DR2:
>0000000000000000
>[ 1215.153441] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7:
>0000000000000400
>[ 1215.153445] Process ifconfig (pid: 18637, threadinfo
>ffff880035270000, task ffff88003f5f5d90)
>[ 1215.153448] Stack:
>[ 1215.153450] 0000000000000002 ffff88003a9e1000 ffff880035271cf8
>ffffffff8146d86d
>[ 1215.153455] ffff880036040d00 0000000000000002 ffff88003a9e1000
>0000000000000000
>[ 1215.153459] 00000000ffffff9d 0000000000000000 ffff880035271d08
>ffffffff8107a2b6
>[ 1215.153464] Call Trace:
>[ 1215.153470] [<ffffffff8146d86d>] notifier_call_chain+0x4d/0x70
>[ 1215.153476] [<ffffffff8107a2b6>] raw_notifier_call_chain+0x16/0x20
>[ 1215.153483] [<ffffffff81395136>] call_netdevice_notifiers+0x36/0x60
>[ 1215.153487] [<ffffffff8139b9ea>] __dev_notify_flags+0x6a/0x90
>[ 1215.153491] [<ffffffff8139ba55>] dev_change_flags+0x45/0x70
>[ 1215.153496] [<ffffffff81403aed>] devinet_ioctl+0x61d/0x7b0
>[ 1215.153500] [<ffffffff81403f05>] inet_ioctl+0x75/0x90
>[ 1215.153505] [<ffffffff8137fbd0>] sock_do_ioctl+0x30/0x70
>[ 1215.153509] [<ffffffff8137fc89>] sock_ioctl+0x79/0x2f0
>[ 1215.153514] [<ffffffff811829d8>] do_vfs_ioctl+0x98/0x560
>[ 1215.153517] [<ffffffff81182f31>] sys_ioctl+0x91/0xa0
>[ 1215.153522] [<ffffffff81471b39>] system_call_fastpath+0x16/0x1b
>[ 1215.153525] Code: e0 5b 41 5c 31 c0 5d c3 48 8d 7b c8 31 c9 ba 09 00
>00 00 be 65 00 00 00 e8 a1 5c 00 00 48 8b 83 b8 04 00 00 48 c7 c7 28 5f
>66 a0 <66> 83 68 2a 01 48 8b 83 b8 04 00 00 0f b7 70 2a 31 c0 e8 d4 10
>[ 1215.153561] RIP [<ffffffffa065e37d>] rose_device_event+0x11d/0x160
>[rose]
>[ 1215.153567] RSP <ffff880035271ca8>
>[ 1215.153569] CR2: 000000000000002a
>[ 1215.177577] ---[ end trace d23a7ddff228876c ]---
>[ 1215.177589] Kernel panic - not syncing: Fatal exception in interrupt
>[ 1215.177662] panic occurred, switching back to text console
>[ 1215.177717] Rebooting in 60 seconds..
>
>I inserted some printk into rose_device_event() and commented calls to
>subroutines.
>Without calling subroutines, there is no more kernel panic.
>Same results when replacing rose_kill_by_device() in net/rose/af_rose.c,
>rose_link_device_down() and rose_rt_device() in
>net/rose_route.c by a dummy functions with just a printk inside.
>
>I am glad that I found make parameters that shorten the debugging
>cycle :
>
>make modules SUBDIRS=net/rose
>make modules_install SUBDIRS=net/rose
>
>Now I have to go further into each subroutines step by step in order to
>find out the falty code !
>
>
>Bernard
>
>
>On 03/08/2012 16:32, folkert wrote:
>>> You might want to simply try moving unregister_netdevice_notifier a bit
>>> earlier in rose_exit and see if that helps. Otherwise I would recommend
>>> instrumenting the code up with some printk so you can understand what
>>> part of unregistration is failing.
>>
>> Or bisect! Give e.g. the oldest 2.6 kernel a try to find a last known
>> good and then do a bisect upto a known bad kernel.
>>
>>
>> Folkert van Heusden
>>
>
^ permalink raw reply
* Re: [RFC v2 6/7] tracepoint: use new hashtable implementation
From: Mathieu Desnoyers @ 2012-08-05 17:12 UTC (permalink / raw)
To: Sasha Levin
Cc: Steven Rostedt, torvalds, tj, akpm, linux-kernel, linux-mm,
paul.gortmaker, davem, mingo, ebiederm, aarcange, ericvh, netdev,
Lai Jiangshan, Paul E. McKenney
In-Reply-To: <501EA749.9060400@gmail.com>
* Sasha Levin (levinsasha928@gmail.com) wrote:
[...]
> > Other than that, it looks good!
> >
> > Thanks!
> >
> > Mathieu
> >
>
> Thanks for the review Mathieu!
No problem! By the way, if you want to have a look at another hash table
API for ideas, here is the RCU lock-free hash table API, within the
Userspace RCU tree:
from git://git.lttng.org/userspace-rcu.git
branch: master
API: urcu/rculfhash.h
core code: rculfhash.c
hash table index memory management:
rculfhash-mm-chunk.c, rculfhash-mm-mmap.c, rculfhash-mm-order.c
The git tree is down today due to electrical maintenance, so I am
appending the hash table API below.
#ifndef _URCU_RCULFHASH_H
#define _URCU_RCULFHASH_H
/*
* urcu/rculfhash.h
*
* Userspace RCU library - Lock-Free RCU Hash Table
*
* Copyright 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
* Copyright 2011 - Lai Jiangshan <laijs@cn.fujitsu.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Include this file _after_ including your URCU flavor.
*/
#include <stdint.h>
#include <urcu/compiler.h>
#include <urcu-call-rcu.h>
#include <urcu-flavor.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* cds_lfht_node: Contains the next pointers and reverse-hash
* value required for lookup and traversal of the hash table.
*
* struct cds_lfht_node should be aligned on 8-bytes boundaries because
* the three lower bits are used as flags. It is worth noting that the
* information contained within these three bits could be represented on
* two bits by re-using the same bit for REMOVAL_OWNER_FLAG and
* BUCKET_FLAG. This can be done if we ensure that no iterator nor
* updater check the BUCKET_FLAG after it detects that the REMOVED_FLAG
* is set. Given the minimum size of struct cds_lfht_node is 8 bytes on
* 32-bit architectures, we choose to go for simplicity and reserve
* three bits.
*
* struct cds_lfht_node can be embedded into a structure (as a field).
* caa_container_of() can be used to get the structure from the struct
* cds_lfht_node after a lookup.
*
* The structure which embeds it typically holds the key (or key-value
* pair) of the object. The caller code is responsible for calculation
* of the hash value for cds_lfht APIs.
*/
struct cds_lfht_node {
struct cds_lfht_node *next; /* ptr | REMOVAL_OWNER_FLAG | BUCKET_FLAG | REMOVED_FLAG */
unsigned long reverse_hash;
} __attribute__((aligned(8)));
/* cds_lfht_iter: Used to track state while traversing a hash chain. */
struct cds_lfht_iter {
struct cds_lfht_node *node, *next;
};
static inline
struct cds_lfht_node *cds_lfht_iter_get_node(struct cds_lfht_iter *iter)
{
return iter->node;
}
struct cds_lfht;
/*
* Caution !
* Ensure reader and writer threads are registered as urcu readers.
*/
typedef int (*cds_lfht_match_fct)(struct cds_lfht_node *node, const void *key);
/*
* cds_lfht_node_init - initialize a hash table node
* @node: the node to initialize.
*
* This function is kept to be eventually used for debugging purposes
* (detection of memory corruption).
*/
static inline
void cds_lfht_node_init(struct cds_lfht_node *node)
{
}
/*
* Hash table creation flags.
*/
enum {
CDS_LFHT_AUTO_RESIZE = (1U << 0),
CDS_LFHT_ACCOUNTING = (1U << 1),
};
struct cds_lfht_mm_type {
struct cds_lfht *(*alloc_cds_lfht)(unsigned long min_nr_alloc_buckets,
unsigned long max_nr_buckets);
void (*alloc_bucket_table)(struct cds_lfht *ht, unsigned long order);
void (*free_bucket_table)(struct cds_lfht *ht, unsigned long order);
struct cds_lfht_node *(*bucket_at)(struct cds_lfht *ht,
unsigned long index);
};
extern const struct cds_lfht_mm_type cds_lfht_mm_order;
extern const struct cds_lfht_mm_type cds_lfht_mm_chunk;
extern const struct cds_lfht_mm_type cds_lfht_mm_mmap;
/*
* _cds_lfht_new - API used by cds_lfht_new wrapper. Do not use directly.
*/
struct cds_lfht *_cds_lfht_new(unsigned long init_size,
unsigned long min_nr_alloc_buckets,
unsigned long max_nr_buckets,
int flags,
const struct cds_lfht_mm_type *mm,
const struct rcu_flavor_struct *flavor,
pthread_attr_t *attr);
/*
* cds_lfht_new - allocate a hash table.
* @init_size: number of buckets to allocate initially. Must be power of two.
* @min_nr_alloc_buckets: the minimum number of allocated buckets.
* (must be power of two)
* @max_nr_buckets: the maximum number of hash table buckets allowed.
* (must be power of two)
* @flags: hash table creation flags (can be combined with bitwise or: '|').
* 0: no flags.
* CDS_LFHT_AUTO_RESIZE: automatically resize hash table.
* CDS_LFHT_ACCOUNTING: count the number of node addition
* and removal in the table
* @attr: optional resize worker thread attributes. NULL for default.
*
* Return NULL on error.
* Note: the RCU flavor must be already included before the hash table header.
*
* The programmer is responsible for ensuring that resize operation has a
* priority equal to hash table updater threads. It should be performed by
* specifying the appropriate priority in the pthread "attr" argument, and,
* for CDS_LFHT_AUTO_RESIZE, by ensuring that call_rcu worker threads also have
* this priority level. Having lower priority for call_rcu and resize threads
* does not pose any correctness issue, but the resize operations could be
* starved by updates, thus leading to long hash table bucket chains.
* Threads calling cds_lfht_new are NOT required to be registered RCU
* read-side threads. It can be called very early. (e.g. before RCU is
* initialized)
*/
static inline
struct cds_lfht *cds_lfht_new(unsigned long init_size,
unsigned long min_nr_alloc_buckets,
unsigned long max_nr_buckets,
int flags,
pthread_attr_t *attr)
{
return _cds_lfht_new(init_size, min_nr_alloc_buckets, max_nr_buckets,
flags, NULL, &rcu_flavor, attr);
}
/*
* cds_lfht_destroy - destroy a hash table.
* @ht: the hash table to destroy.
* @attr: (output) resize worker thread attributes, as received by cds_lfht_new.
* The caller will typically want to free this pointer if dynamically
* allocated. The attr point can be NULL if the caller does not
* need to be informed of the value passed to cds_lfht_new().
*
* Return 0 on success, negative error value on error.
* Threads calling this API need to be registered RCU read-side threads.
*/
int cds_lfht_destroy(struct cds_lfht *ht, pthread_attr_t **attr);
/*
* cds_lfht_count_nodes - count the number of nodes in the hash table.
* @ht: the hash table.
* @split_count_before: sample the node count split-counter before traversal.
* @count: traverse the hash table, count the number of nodes observed.
* @split_count_after: sample the node count split-counter after traversal.
*
* Call with rcu_read_lock held.
* Threads calling this API need to be registered RCU read-side threads.
*/
void cds_lfht_count_nodes(struct cds_lfht *ht,
long *split_count_before,
unsigned long *count,
long *split_count_after);
/*
* cds_lfht_lookup - lookup a node by key.
* @ht: the hash table.
* @hash: the key hash.
* @match: the key match function.
* @key: the current node key.
* @iter: node, if found (output). *iter->node set to NULL if not found.
*
* Call with rcu_read_lock held.
* Threads calling this API need to be registered RCU read-side threads.
* This function acts as a rcu_dereference() to read the node pointer.
*/
void cds_lfht_lookup(struct cds_lfht *ht, unsigned long hash,
cds_lfht_match_fct match, const void *key,
struct cds_lfht_iter *iter);
/*
* cds_lfht_next_duplicate - get the next item with same key, after iterator.
* @ht: the hash table.
* @match: the key match function.
* @key: the current node key.
* @iter: input: current iterator.
* output: node, if found. *iter->node set to NULL if not found.
*
* Uses an iterator initialized by a lookup or traversal. Important: the
* iterator _needs_ to be initialized before calling
* cds_lfht_next_duplicate.
* Sets *iter-node to the following node with same key.
* Sets *iter->node to NULL if no following node exists with same key.
* RCU read-side lock must be held across cds_lfht_lookup and
* cds_lfht_next calls, and also between cds_lfht_next calls using the
* node returned by a previous cds_lfht_next.
* Call with rcu_read_lock held.
* Threads calling this API need to be registered RCU read-side threads.
* This function acts as a rcu_dereference() to read the node pointer.
*/
void cds_lfht_next_duplicate(struct cds_lfht *ht,
cds_lfht_match_fct match, const void *key,
struct cds_lfht_iter *iter);
/*
* cds_lfht_first - get the first node in the table.
* @ht: the hash table.
* @iter: First node, if exists (output). *iter->node set to NULL if not found.
*
* Output in "*iter". *iter->node set to NULL if table is empty.
* Call with rcu_read_lock held.
* Threads calling this API need to be registered RCU read-side threads.
* This function acts as a rcu_dereference() to read the node pointer.
*/
void cds_lfht_first(struct cds_lfht *ht, struct cds_lfht_iter *iter);
/*
* cds_lfht_next - get the next node in the table.
* @ht: the hash table.
* @iter: input: current iterator.
* output: next node, if exists. *iter->node set to NULL if not found.
*
* Input/Output in "*iter". *iter->node set to NULL if *iter was
* pointing to the last table node.
* Call with rcu_read_lock held.
* Threads calling this API need to be registered RCU read-side threads.
* This function acts as a rcu_dereference() to read the node pointer.
*/
void cds_lfht_next(struct cds_lfht *ht, struct cds_lfht_iter *iter);
/*
* cds_lfht_add - add a node to the hash table.
* @ht: the hash table.
* @hash: the key hash.
* @node: the node to add.
*
* This function supports adding redundant keys into the table.
* Call with rcu_read_lock held.
* Threads calling this API need to be registered RCU read-side threads.
* This function issues a full memory barrier before and after its
* atomic commit.
*/
void cds_lfht_add(struct cds_lfht *ht, unsigned long hash,
struct cds_lfht_node *node);
/*
* cds_lfht_add_unique - add a node to hash table, if key is not present.
* @ht: the hash table.
* @hash: the node's hash.
* @match: the key match function.
* @key: the node's key.
* @node: the node to try adding.
*
* Return the node added upon success.
* Return the unique node already present upon failure. If
* cds_lfht_add_unique fails, the node passed as parameter should be
* freed by the caller. In this case, the caller does NOT need to wait
* for a grace period before freeing the node.
* Call with rcu_read_lock held.
* Threads calling this API need to be registered RCU read-side threads.
*
* The semantic of this function is that if only this function is used
* to add keys into the table, no duplicated keys should ever be
* observable in the table. The same guarantee apply for combination of
* add_unique and add_replace (see below).
*
* Upon success, this function issues a full memory barrier before and
* after its atomic commit. Upon failure, this function acts like a
* simple lookup operation: it acts as a rcu_dereference() to read the
* node pointer. The failure case does not guarantee any other memory
* barrier.
*/
struct cds_lfht_node *cds_lfht_add_unique(struct cds_lfht *ht,
unsigned long hash,
cds_lfht_match_fct match,
const void *key,
struct cds_lfht_node *node);
/*
* cds_lfht_add_replace - replace or add a node within hash table.
* @ht: the hash table.
* @hash: the node's hash.
* @match: the key match function.
* @key: the node's key.
* @node: the node to add.
*
* Return the node replaced upon success. If no node matching the key
* was present, return NULL, which also means the operation succeeded.
* This replacement operation should never fail.
* Call with rcu_read_lock held.
* Threads calling this API need to be registered RCU read-side threads.
* After successful replacement, a grace period must be waited for before
* freeing the memory reserved for the returned node.
*
* The semantic of replacement vs lookups and traversals is the
* following: if lookups and traversals are performed between a key
* unique insertion and its removal, we guarantee that the lookups and
* traversals will always find exactly one instance of the key if it is
* replaced concurrently with the lookups.
*
* Providing this semantic allows us to ensure that replacement-only
* schemes will never generate duplicated keys. It also allows us to
* guarantee that a combination of add_replace and add_unique updates
* will never generate duplicated keys.
*
* This function issues a full memory barrier before and after its
* atomic commit.
*/
struct cds_lfht_node *cds_lfht_add_replace(struct cds_lfht *ht,
unsigned long hash,
cds_lfht_match_fct match,
const void *key,
struct cds_lfht_node *node);
/*
* cds_lfht_replace - replace a node pointed to by iter within hash table.
* @ht: the hash table.
* @old_iter: the iterator position of the node to replace.
* @hash: the node's hash.
* @match: the key match function.
* @key: the node's key.
* @new_node: the new node to use as replacement.
*
* Return 0 if replacement is successful, negative value otherwise.
* Replacing a NULL old node or an already removed node will fail with
* -ENOENT.
* If the hash or value of the node to replace and the new node differ,
* this function returns -EINVAL without proceeding to the replacement.
* Old node can be looked up with cds_lfht_lookup and cds_lfht_next.
* RCU read-side lock must be held between lookup and replacement.
* Call with rcu_read_lock held.
* Threads calling this API need to be registered RCU read-side threads.
* After successful replacement, a grace period must be waited for before
* freeing the memory reserved for the old node (which can be accessed
* with cds_lfht_iter_get_node).
*
* The semantic of replacement vs lookups is the same as
* cds_lfht_add_replace().
*
* Upon success, this function issues a full memory barrier before and
* after its atomic commit. Upon failure, this function does not issue
* any memory barrier.
*/
int cds_lfht_replace(struct cds_lfht *ht,
struct cds_lfht_iter *old_iter,
unsigned long hash,
cds_lfht_match_fct match,
const void *key,
struct cds_lfht_node *new_node);
/*
* cds_lfht_del - remove node pointed to by iterator from hash table.
* @ht: the hash table.
* @node: the node to delete.
*
* Return 0 if the node is successfully removed, negative value
* otherwise.
* Deleting a NULL node or an already removed node will fail with a
* negative value.
* Node can be looked up with cds_lfht_lookup and cds_lfht_next,
* followed by use of cds_lfht_iter_get_node.
* RCU read-side lock must be held between lookup and removal.
* Call with rcu_read_lock held.
* Threads calling this API need to be registered RCU read-side threads.
* After successful removal, a grace period must be waited for before
* freeing the memory reserved for old node (which can be accessed with
* cds_lfht_iter_get_node).
* Upon success, this function issues a full memory barrier before and
* after its atomic commit. Upon failure, this function does not issue
* any memory barrier.
*/
int cds_lfht_del(struct cds_lfht *ht, struct cds_lfht_node *node);
/*
* cds_lfht_is_node_deleted - query whether a node is removed from hash table.
*
* Return non-zero if the node is deleted from the hash table, 0
* otherwise.
* Node can be looked up with cds_lfht_lookup and cds_lfht_next,
* followed by use of cds_lfht_iter_get_node.
* RCU read-side lock must be held between lookup and call to this
* function.
* Call with rcu_read_lock held.
* Threads calling this API need to be registered RCU read-side threads.
* This function does not issue any memory barrier.
*/
int cds_lfht_is_node_deleted(struct cds_lfht_node *node);
/*
* cds_lfht_resize - Force a hash table resize
* @ht: the hash table.
* @new_size: update to this hash table size.
*
* Threads calling this API need to be registered RCU read-side threads.
* This function does not (necessarily) issue memory barriers.
*/
void cds_lfht_resize(struct cds_lfht *ht, unsigned long new_size);
/*
* Note: it is safe to perform element removal (del), replacement, or
* any hash table update operation during any of the following hash
* table traversals.
* These functions act as rcu_dereference() to read the node pointers.
*/
#define cds_lfht_for_each(ht, iter, node) \
for (cds_lfht_first(ht, iter), \
node = cds_lfht_iter_get_node(iter); \
node != NULL; \
cds_lfht_next(ht, iter), \
node = cds_lfht_iter_get_node(iter))
#define cds_lfht_for_each_duplicate(ht, hash, match, key, iter, node) \
for (cds_lfht_lookup(ht, hash, match, key, iter), \
node = cds_lfht_iter_get_node(iter); \
node != NULL; \
cds_lfht_next_duplicate(ht, match, key, iter), \
node = cds_lfht_iter_get_node(iter))
#define cds_lfht_for_each_entry(ht, iter, pos, member) \
for (cds_lfht_first(ht, iter), \
pos = caa_container_of(cds_lfht_iter_get_node(iter), \
__typeof__(*(pos)), member); \
&(pos)->member != NULL; \
cds_lfht_next(ht, iter), \
pos = caa_container_of(cds_lfht_iter_get_node(iter), \
__typeof__(*(pos)), member))
#define cds_lfht_for_each_entry_duplicate(ht, hash, match, key, \
iter, pos, member) \
for (cds_lfht_lookup(ht, hash, match, key, iter), \
pos = caa_container_of(cds_lfht_iter_get_node(iter), \
__typeof__(*(pos)), member); \
&(pos)->member != NULL; \
cds_lfht_next_duplicate(ht, match, key, iter), \
pos = caa_container_of(cds_lfht_iter_get_node(iter), \
__typeof__(*(pos)), member))
#ifdef __cplusplus
}
#endif
#endif /* _URCU_RCULFHASH_H */
--
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: CPU: 0 Not tainted (3.1.9+ #1) when ifconfig rose0 down
From: Eric W. Biederman @ 2012-08-05 17:23 UTC (permalink / raw)
To: Bernard Pidoux; +Cc: folkert, linux-hams, Linux Netdev List
In-Reply-To: <501E9DFD.4040301@free.fr>
Bernard Pidoux <bernard.pidoux@free.fr> writes:
> Thanks for suggesting a bissect. However I guess that this bug has always been
> there !
One thing that has changed recently is I modified
unregister_netdev_notifier to create synthetic events so drivers don't
need a separate network device tear down path in module unload.
For rose it looks like this has triggered latent bugs.
> I am not professionaly involved in programming, however I committed a few
> patches for ROSE, AX.25 and NetRom modules since a few years.
>
> I reactivated netconfig and here is the report showing that kernel panic occurs
> when rose_device_event is triggered when issuing command
> ifconfig rose0 down
Oh ouch! This is from an ioctl not even at module unload time.
> [ 1215.153302] rose_kill_by_device() rose->neighbour->use 0
> [ 1215.153316] BUG: unable to handle kernel NULL pointer dereference at
> 000000000000002a
> [ 1215.153321] IP: [<ffffffffa065e37d>] rose_device_event+0x11d/0x160 [rose]
> [ 1215.153333] PGD 36340067 PUD 359fa067 PMD 0
> [ 1215.153338] Oops: 0002 [#1] SMP
> [ 1215.153343] CPU 1
> [ 1215.153344] Modules linked in: af_packet rose mkiss ax25 nfsd exportfs nfs
> nfs_acl auth_rpcgss fscache lockd sunrpc netconsole configfs bnep bluetooth
> rfkill snd_hda_codec_idt snd_hda_intel snd_hda_codec snd_hwdep snd_pcm
> snd_page_alloc snd_timer snd i82975x_edac soundcore e1000e ppdev parport_pc
> parport edac_core iTCO_wdt iTCO_vendor_support serio_raw i2c_i801 processor
> coretemp evdev ipv6 autofs4 usbhid hid ext4 crc16 jbd2 sd_mod crc_t10dif
> firewire_ohci firewire_core ehci_hcd crc_itu_t uhci_hcd usbcore usb_common
> nouveau button video mxm_wmi wmi i2c_algo_bit drm_kms_helper ttm drm i2c_core
> ahci libahci ata_piix pata_marvell libata scsi_mod [last unloaded: microcode]
> [ 1215.153395]
> [ 1215.153398] Pid: 18637, comm: ifconfig Not tainted 3.4.7 #8 /D975XBX2
> [ 1215.153404] RIP: 0010:[<ffffffffa065e37d>] [<ffffffffa065e37d>]
> rose_device_event+0x11d/0x160 [rose]
> [ 1215.153411] RSP: 0000:ffff880035271ca8 EFLAGS: 00010296
> [ 1215.153414] RAX: 0000000000000000 RBX: ffff88003d0c2838 RCX: 0000000230924000
> [ 1215.153417] RDX: 0000000000000002 RSI: 0000000000000001 RDI: ffffffffa0665f28
> [ 1215.153420] RBP: ffff880035271cb8 R08: 0000000000000002 R09: 0000000000000000
> [ 1215.153422] R10: 0000000000000003 R11: 0000000000000000 R12: ffff88003a9e1000
> [ 1215.153425] R13: 00000000fffffff1 R14: ffffffffa05b0000 R15: 0000000000000000
> [ 1215.153429] FS: 00007fb7a318f700(0000) GS:ffff88003fa80000(0000)
> knlGS:0000000000000000
> [ 1215.153433] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
> [ 1215.153435] CR2: 000000000000002a CR3: 00000000393fd000 CR4: 00000000000007e0
> [ 1215.153438] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> [ 1215.153441] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
> [ 1215.153445] Process ifconfig (pid: 18637, threadinfo ffff880035270000, task
> ffff88003f5f5d90)
> [ 1215.153448] Stack:
> [ 1215.153450] 0000000000000002 ffff88003a9e1000 ffff880035271cf8
> ffffffff8146d86d
> [ 1215.153455] ffff880036040d00 0000000000000002 ffff88003a9e1000
> 0000000000000000
> [ 1215.153459] 00000000ffffff9d 0000000000000000 ffff880035271d08
> ffffffff8107a2b6
> [ 1215.153464] Call Trace:
> [ 1215.153470] [<ffffffff8146d86d>] notifier_call_chain+0x4d/0x70
> [ 1215.153476] [<ffffffff8107a2b6>] raw_notifier_call_chain+0x16/0x20
> [ 1215.153483] [<ffffffff81395136>] call_netdevice_notifiers+0x36/0x60
> [ 1215.153487] [<ffffffff8139b9ea>] __dev_notify_flags+0x6a/0x90
> [ 1215.153491] [<ffffffff8139ba55>] dev_change_flags+0x45/0x70
> [ 1215.153496] [<ffffffff81403aed>] devinet_ioctl+0x61d/0x7b0
> [ 1215.153500] [<ffffffff81403f05>] inet_ioctl+0x75/0x90
> [ 1215.153505] [<ffffffff8137fbd0>] sock_do_ioctl+0x30/0x70
> [ 1215.153509] [<ffffffff8137fc89>] sock_ioctl+0x79/0x2f0
> [ 1215.153514] [<ffffffff811829d8>] do_vfs_ioctl+0x98/0x560
> [ 1215.153517] [<ffffffff81182f31>] sys_ioctl+0x91/0xa0
> [ 1215.153522] [<ffffffff81471b39>] system_call_fastpath+0x16/0x1b
> [ 1215.153525] Code: e0 5b 41 5c 31 c0 5d c3 48 8d 7b c8 31 c9 ba 09 00 00 00 be
> 65 00 00 00 e8 a1 5c 00 00 48 8b 83 b8 04 00 00 48 c7 c7 28 5f 66 a0 <66> 83 68
> 2a 01 48 8b 83 b8 04 00 00 0f b7 70 2a 31 c0 e8 d4 10
> [ 1215.153561] RIP [<ffffffffa065e37d>] rose_device_event+0x11d/0x160 [rose]
> [ 1215.153567] RSP <ffff880035271ca8>
> [ 1215.153569] CR2: 000000000000002a
> [ 1215.177577] ---[ end trace d23a7ddff228876c ]---
> [ 1215.177589] Kernel panic - not syncing: Fatal exception in interrupt
> [ 1215.177662] panic occurred, switching back to text console
> [ 1215.177717] Rebooting in 60 seconds..
>
> I inserted some printk into rose_device_event() and commented calls to
> subroutines.
> Without calling subroutines, there is no more kernel panic.
> Same results when replacing rose_kill_by_device() in net/rose/af_rose.c,
> rose_link_device_down() and rose_rt_device() in
> net/rose_route.c by a dummy functions with just a printk inside.
>
> I am glad that I found make parameters that shorten the debugging
> cycle :
>
> make modules SUBDIRS=net/rose
> make modules_install SUBDIRS=net/rose
>
> Now I have to go further into each subroutines step by step in order to find out
> the falty code !
Argh inline functions obscuring the backtraces again.
If you are any good at reading assembly you might be able to cut the
tracing time down by using gdb to get a disassembly and looking in the
disassembly.
Although in something easily reproducible what I tend to do is I have
a printk that does.
printk(KERN_EMERG "@%s.%s.%d\n", __FILE__, __func__, __LINE__);
Which I sprinkle all over the code so I know where I fail, and don't
need to cycle too many times.
Sometimes it can be productive to use kvm or a second machine so your
cycle times aren't as long.
In any event I wish you luck tracking this down.
Eric
^ permalink raw reply
* Re: [PATCH V2 09/12] net/eipoib: Add main driver functionality
From: Michael S. Tsirkin @ 2012-08-05 18:50 UTC (permalink / raw)
To: Eric W. Biederman
Cc: Or Gerlitz, davem, roland, netdev, ali, sean.hefty, Erez Shitrit
In-Reply-To: <87boitz044.fsf@xmission.com>
On Thu, Aug 02, 2012 at 10:15:23AM -0700, Eric W. Biederman wrote:
> Or Gerlitz <ogerlitz@mellanox.com> writes:
>
> > From: Erez Shitrit <erezsh@mellanox.co.il>
> >
> > The eipoib driver provides a standard Ethernet netdevice over
> > the InfiniBand IPoIB interface .
> >
> > Some services can run only on top of Ethernet L2 interfaces, and cannot be
> > bound to an IPoIB interface. With this new driver, these services can run
> > seamlessly.
>
> Do I read this code correctly that what you are doing is not tunneling
> ethernet over IB but instead you are removing an ethernet header and
> replacing it with an IB header?
>
> Do I also read this code correctly if you can't find your destination
> mac address in your ""neighbor table"" you do a normal IPoIB arp
> for the infiniband GUID?
>
> Do I read this right that if presented with a non-IPv4 or ARP packet
> this code will do something undefined and unpredictable?
>
> Maybe this makes some sense but just skimming it looks like you
> are trying to force a square peg into a round hole resulting in
> some weird code and some very weird maintainability issues.
>
> I am honestly surprised at this approach. I would think it would be
> faster and simpler to run an IB queue pair directly to the hypervisor or
> possibly even the guest operating system bypassing the kernel and doing
> all of this translation in userspace.
>
> Eric
I'm on vacation and I have not looked at the patches, at Erez' request,
just reacting to the presentation and the discussion.
Bypassing the kernel has its own set of issues, not the
least of which is the need to lock all of guest memory which breaks
overcommit. Running an IB queue pair directly to the hypervisor
will also break live migration.
Another problem with exposing IB to guests has to do with the fact that
IB addresses such as combinations of LIDs, GIDs and QPNs to best of my
knowledge do not support soft hardware address setting, which interferes
with live migration.
So it seems that a sane solution would involve an extra level of
indirection, with guest addresses being translated to host IB addresses.
As long as you do this, maybe using an ethernet frame format makes
sense.
So far the things that make sense. Here are some that don't, to me:
- Is a pdf presentation all you have in terms of documentation?
We are talking communication protocols here - I would expect a
proper spec, and some effort to standardize, otherwise where's the
guarantee it won't change in an incompatible way?
Other things that I would expect to be addressed in such a spec is
interaction with other IPoIB features, such as connected
mode, checksum offloading etc, and IB features such as multipath etc.
- The way you encode LID/QPN in the MAC seems questionable. IIRC there's
more to IB addressing than just the LID. Since everyone on the subnet
need access to this translation, I think it makes sense to store it in
the SM. I think this would also obviate some IPv4 specific hacks
in kernel.
- IGMP/MAC snooping in a driver is just too hairy.
As you point out, bridge currently needs the uplink in promisc mode.
I don't think a driver should work around that limitation.
For some setups, it might be interesting to remove the
promisc mode requirement, failing that,
I think you could use macvtap passthrough.
- Currently migration works without host kernel help, would be
preferable to keep it that way.
Hope this helps,
MST
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* RE: [PATCH net-next,1/1] hyperv: Move wait completion msg code into rndis_filter_halt_device()
From: Haiyang Zhang @ 2012-08-05 19:16 UTC (permalink / raw)
To: David Miller
Cc: olaf@aepfle.de, netdev@vger.kernel.org, jasowang@redhat.com,
linux-kernel@vger.kernel.org, devel@linuxdriverproject.org
In-Reply-To: <20120803.165212.106382119661240198.davem@davemloft.net>
> -----Original Message-----
> From: David Miller [mailto:davem@davemloft.net]
> Sent: Friday, August 03, 2012 7:52 PM
> To: Haiyang Zhang
> Cc: netdev@vger.kernel.org; KY Srinivasan; olaf@aepfle.de;
> jasowang@redhat.com; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org
> Subject: Re: [PATCH net-next,1/1] hyperv: Move wait completion msg code
> into rndis_filter_halt_device()
>
> From: Haiyang Zhang <haiyangz@microsoft.com>
> Date: Fri, 3 Aug 2012 12:32:18 -0700
>
> > We need to wait for send_completion msg before put_rndis_request() at
> > the end of rndis_filter_halt_device(). Otherwise,
> > netvsc_send_completion() may reference freed memory which is
> overwritten, and cause panic.
> >
> > Reported-by: Long Li <longli@microsoft.com>
> > Reported-by: Jason Wang <jasowang@redhat.com>
> > Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
>
> This is a bug fix, so applied to 'net'. Please target your patches properly.
>
> Don't just be afraid that I'll reject the patch if you target it at 'net', and
> therefore just target everything at 'net-next'. That is certainly worse.
I see.
Thanks,
- Haiyang
^ permalink raw reply
* Subject: [PATCH] sched: add missing group change to qfq_change_class
From: Paolo Valente @ 2012-08-05 19:45 UTC (permalink / raw)
To: shemminger, jhs, davem
Cc: paolo.valente, Fabio Checconi, Luigi Rizzo, netdev, linux-kernel
To speed up operations, QFQ internally divides classes into
groups. Which group a class belongs to depends on the ratio between
the maximum packet length and the weight of the class. Unfortunately
the function qfq_change_class lacks the steps for changing the group
of a class when the ratio max_pkt_len/weight of the class changes.
For example, when the last of the following three commands is
executed, the group of class 1:1 is not correctly changed:
tc disc add dev XXX root handle 1: qfq
tc class add dev XXX parent 1: qfq classid 1:1 weight 1
tc class change dev XXX parent 1: classid 1:1 qfq weight 4
Not changing the group of a class does not affect the long-term
bandwidth guaranteed to the class, as the latter is independent of the
maximum packet length, and correctly changes (only) if the weight of
the class changes. In contrast, if the group of the class is not
updated, the class is still guaranteed the short-term bandwidth and
packet delay related to its old group, and not the guarantees that it
should receive according to its new weight and/or maximum packet
length. This may also break service guarantees for other classes.
This patch adds the missing operations.
Signed-off-by: Paolo Valente <paolo.valente@unimore.it>
---
net/sched/sch_qfq.c | 95 +++++++++++++++++++++++++++++++++++++--------------
1 file changed, 69 insertions(+), 26 deletions(-)
diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c
index 9af01f3..e4723d3 100644
--- a/net/sched/sch_qfq.c
+++ b/net/sched/sch_qfq.c
@@ -203,6 +203,34 @@ out:
return index;
}
+/* Length of the next packet (0 if the queue is empty). */
+static unsigned int qdisc_peek_len(struct Qdisc *sch)
+{
+ struct sk_buff *skb;
+
+ skb = sch->ops->peek(sch);
+ return skb ? qdisc_pkt_len(skb) : 0;
+}
+
+static void qfq_deactivate_class(struct qfq_sched *, struct qfq_class *);
+static void qfq_activate_class(struct qfq_sched *q, struct qfq_class *cl,
+ unsigned int len);
+
+static void qfq_update_class_params(struct qfq_sched *q, struct qfq_class *cl,
+ u32 lmax, u32 inv_w, int delta_w)
+{
+ int i;
+
+ /* update qfq-specific data */
+ cl->lmax = lmax;
+ cl->inv_w = inv_w;
+ i = qfq_calc_index(cl->inv_w, cl->lmax);
+
+ cl->grp = &q->groups[i];
+
+ q->wsum += delta_w;
+}
+
static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
struct nlattr **tca, unsigned long *arg)
{
@@ -250,6 +278,8 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
lmax = 1UL << QFQ_MTU_SHIFT;
if (cl != NULL) {
+ bool need_reactivation = false;
+
if (tca[TCA_RATE]) {
err = gen_replace_estimator(&cl->bstats, &cl->rate_est,
qdisc_root_sleeping_lock(sch),
@@ -258,12 +288,29 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
return err;
}
- if (inv_w != cl->inv_w) {
- sch_tree_lock(sch);
- q->wsum += delta_w;
- cl->inv_w = inv_w;
- sch_tree_unlock(sch);
+ if (lmax == cl->lmax && inv_w == cl->inv_w)
+ return 0; /* nothing to update */
+
+ i = qfq_calc_index(inv_w, lmax);
+ sch_tree_lock(sch);
+ if (&q->groups[i] != cl->grp && cl->qdisc->q.qlen > 0) {
+ /*
+ * shift cl->F back, to not charge the
+ * class for the not-yet-served head
+ * packet
+ */
+ cl->F = cl->S;
+ /* remove class from its slot in the old group */
+ qfq_deactivate_class(q, cl);
+ need_reactivation = true;
}
+
+ qfq_update_class_params(q, cl, lmax, inv_w, delta_w);
+
+ if (need_reactivation) /* activate in new group */
+ qfq_activate_class(q, cl, qdisc_peek_len(cl->qdisc));
+ sch_tree_unlock(sch);
+
return 0;
}
@@ -273,11 +320,8 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
cl->refcnt = 1;
cl->common.classid = classid;
- cl->lmax = lmax;
- cl->inv_w = inv_w;
- i = qfq_calc_index(cl->inv_w, cl->lmax);
- cl->grp = &q->groups[i];
+ qfq_update_class_params(q, cl, lmax, inv_w, delta_w);
cl->qdisc = qdisc_create_dflt(sch->dev_queue,
&pfifo_qdisc_ops, classid);
@@ -294,7 +338,6 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
return err;
}
}
- q->wsum += weight;
sch_tree_lock(sch);
qdisc_class_hash_insert(&q->clhash, &cl->common);
@@ -711,15 +754,6 @@ static void qfq_update_eligible(struct qfq_sched *q, u64 old_V)
}
}
-/* What is length of next packet in queue (0 if queue is empty) */
-static unsigned int qdisc_peek_len(struct Qdisc *sch)
-{
- struct sk_buff *skb;
-
- skb = sch->ops->peek(sch);
- return skb ? qdisc_pkt_len(skb) : 0;
-}
-
/*
* Updates the class, returns true if also the group needs to be updated.
*/
@@ -843,11 +877,8 @@ static void qfq_update_start(struct qfq_sched *q, struct qfq_class *cl)
static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
{
struct qfq_sched *q = qdisc_priv(sch);
- struct qfq_group *grp;
struct qfq_class *cl;
int err;
- u64 roundedS;
- int s;
cl = qfq_classify(skb, sch, &err);
if (cl == NULL) {
@@ -876,11 +907,25 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
return err;
/* If reach this point, queue q was idle */
- grp = cl->grp;
+ qfq_activate_class(q, cl, qdisc_pkt_len(skb));
+
+ return err;
+}
+
+/*
+ * Handle class switch from idle to backlogged.
+ */
+static void qfq_activate_class(struct qfq_sched *q, struct qfq_class *cl,
+ unsigned int pkt_len)
+{
+ struct qfq_group *grp = cl->grp;
+ u64 roundedS;
+ int s;
+
qfq_update_start(q, cl);
/* compute new finish time and rounded start. */
- cl->F = cl->S + (u64)qdisc_pkt_len(skb) * cl->inv_w;
+ cl->F = cl->S + (u64)pkt_len * cl->inv_w;
roundedS = qfq_round_down(cl->S, grp->slot_shift);
/*
@@ -917,8 +962,6 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
skip_update:
qfq_slot_insert(grp, cl, roundedS);
-
- return err;
}
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH] can: kvaser_usb: Add support for Kvaser CAN/USB devices
From: Wolfgang Grandegger @ 2012-08-05 20:41 UTC (permalink / raw)
To: Marc Kleine-Budde; +Cc: Olivier Sobrie, linux-can, netdev
In-Reply-To: <5017ABC6.7030307@pengutronix.de>
On 07/31/2012 11:56 AM, Marc Kleine-Budde wrote:
> On 07/30/2012 03:33 PM, Olivier Sobrie wrote:
...
>>>> +static void kvaser_usb_rx_error(const struct kvaser_usb *dev,
>>>> + const struct kvaser_msg *msg)
>>>> +{
>>>> + struct can_frame *cf;
>>>> + struct sk_buff *skb;
>>>> + struct net_device_stats *stats;
>>>> + struct kvaser_usb_net_priv *priv;
>>>> + u8 channel, status, txerr, rxerr;
>>>> +
>>>> + if (msg->id == CMD_CAN_ERROR_EVENT) {
>>>> + channel = msg->u.error_event.channel;
>>>> + status = msg->u.error_event.status;
>>>> + txerr = msg->u.error_event.tx_errors_count;
>>>> + rxerr = msg->u.error_event.rx_errors_count;
>>>> + } else {
>>>> + channel = msg->u.chip_state_event.channel;
>>>> + status = msg->u.chip_state_event.status;
>>>> + txerr = msg->u.chip_state_event.tx_errors_count;
>>>> + rxerr = msg->u.chip_state_event.rx_errors_count;
>>>> + }
>>>> +
>>>> + if (channel >= dev->nchannels) {
>>>> + dev_err(dev->udev->dev.parent,
>>>> + "Invalid channel number (%d)\n", channel);
>>>> + return;
>>>> + }
>>>> +
>>>> + priv = dev->nets[channel];
>>>> + stats = &priv->netdev->stats;
>>>> +
>>>> + skb = alloc_can_err_skb(priv->netdev, &cf);
>>>> + if (!skb) {
>>>> + stats->rx_dropped++;
>>>> + return;
>>>> + }
>>>> +
>>>> + if ((status & M16C_STATE_BUS_OFF) ||
>>>> + (status & M16C_STATE_BUS_RESET)) {
>>>> + priv->can.state = CAN_STATE_BUS_OFF;
>>>> + cf->can_id |= CAN_ERR_BUSOFF;
>>>> + can_bus_off(priv->netdev);
>
> you should increment priv->can.can_stats.bus_off
No, already done in can_bus_off():
http://lxr.free-electrons.com/source/drivers/net/can/dev.c#L439
Wolfgang.
^ permalink raw reply
* Re: [PATCH] can: kvaser_usb: Add support for Kvaser CAN/USB devices
From: Wolfgang Grandegger @ 2012-08-05 20:43 UTC (permalink / raw)
To: Marc Kleine-Budde; +Cc: Olivier Sobrie, linux-can, netdev
In-Reply-To: <501A6AE7.9060508@pengutronix.de>
On 08/02/2012 01:56 PM, Marc Kleine-Budde wrote:
> On 08/02/2012 12:53 PM, Olivier Sobrie wrote:
...
>> I actually implemeted it as you said and here is what I observed in
>> candump output with restart_ms set to 100 ms:
>>
>> t0: Short circuit between CAN-H and CAN-L + cansend can1 123#1122
>> can1 2000008C [8] 00 04 90 00 00 00 00 00 ERRORFRAME
>> controller-problem{rx-error-warning}
>> protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
>> bus-error
>> can1 2000008C [8] 00 10 90 00 00 00 00 00 ERRORFRAME
>> controller-problem{rx-error-passive}
>> protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
>> bus-error
>> can1 200000C8 [8] 00 00 90 00 00 00 00 00 ERRORFRAME
>> protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
>> bus-off
>> bus-error
>> ...
FYI, the option "-td" nicely shows the timing. I assume that the
"warning->passive->bus-off" sequence repeats because automatic bus-off
is active via ip option "restart-ms xx ms". What I'm missing is the
message "restarted-after-bus-off". Maybe it's not listed here...
>> can1 2000008C [8] 00 04 90 00 00 00 00 00 ERRORFRAME
>> controller-problem{rx-error-warning}
>> protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
>> bus-error
>> can1 2000008C [8] 00 10 90 00 00 00 00 00 ERRORFRAME
>> controller-problem{rx-error-passive}
>> protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
>> bus-error
>> can1 200000C8 [8] 00 00 90 00 00 00 00 00 ERRORFRAME
>> protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
>> bus-off
>> bus-error
>>
>> t1: short circuit removed
>> can1 123 [2] 11 22
>> can1 20000100 [8] 00 00 00 00 00 00 00 00 ERRORFRAME
>> restarted-after-bus-of
>>
>> The echo coming before the restart looks weird? No?
Yes. It should come later.
>> Shouldn't we drop the frame once BUF-OFF is reached?
No.
> No, I don't think so. But wait for Wolfgang, here's more into error
> handling then me.
Looking to your code it's not clear to me how you do recovery from
bus-off (called "restart"). This is usually done via
do_set_mode(CAN_MODE_START), either manually (restart-ms==0) or
automatically (restart-ms>0). Could you please explain how the device
does bus-off recovery? Does the hardware do it automatically? This
should be suppressed if if restart-ms==0 (as Marc already pointed out).
Wolfgang.
^ permalink raw reply
* [patch 1/1] ixp4xx_eth: fix ptp_ixp46x build failure
From: Arnaud Patard @ 2012-08-05 20:30 UTC (permalink / raw)
To: netdev; +Cc: Krzysztof Halasa
[-- Attachment #1: ixp46x_build_failure.patch --]
[-- Type: text/plain, Size: 826 bytes --]
When building with ixp4xx_eth and ptp_ixp46x as module, one is getting the
following error:
ERROR: "ixp46x_phc_index" [drivers/ptp/ptp_ixp46x.ko] undefined!
This has been introduced by commit 509a7c25729feab353502e1b544c614772a1d49a.
Signed-off-by: Arnaud Patard <arnaud.patard@rtp-net.org>
Index: efika/drivers/net/ethernet/xscale/ixp4xx_eth.c
===================================================================
--- efika.orig/drivers/net/ethernet/xscale/ixp4xx_eth.c 2012-07-29 14:03:12.710197591 +0200
+++ efika/drivers/net/ethernet/xscale/ixp4xx_eth.c 2012-08-05 11:13:13.188037295 +0200
@@ -1003,6 +1003,7 @@ static int ixp4xx_nway_reset(struct net_
}
int ixp46x_phc_index = -1;
+EXPORT_SYMBOL_GPL(ixp46x_phc_index);
static int ixp4xx_get_ts_info(struct net_device *dev,
struct ethtool_ts_info *info)
^ permalink raw reply
* Re: [PATCH v2] ipv4/ipv6: multicast api unappropriate errno fix.
From: Li Wei @ 2012-08-06 1:19 UTC (permalink / raw)
To: David Stevens; +Cc: davem, netdev
In-Reply-To: <OF074B1468.BAD353FE-ON85257A4F.0041C4E9-85257A4F.0042D425@us.ibm.com>
On 08/03/2012 08:09 PM, David Stevens wrote:
> netdev-owner@vger.kernel.org wrote on 08/03/2012 05:29:05 AM:
>
>> @@ -1933,10 +1933,8 @@ int ip_mc_source(int add, int omode, struct
>> sock *sk, struct
>> (pmc->multi.imr_ifindex == imr.imr_ifindex))
>> break;
>> }
>> - if (!pmc) { /* must have a prior join */
>> - err = -EINVAL;
>> - goto done;
>> - }
>> + if (!pmc) /* must have a prior join */
>> + goto done; /* err = -EADDRNOTAVAIL */
>
> RFC3678, section 4.1.3:
> "When the option itself is not legal on the group (i.e., when
> trying a
> Source-Specific option on a group after doing IP_ADD_MEMBERSHIP, or
> when trying an Any-Source option without doing IP_ADD_MEMBERSHIP) the
> error generated is EINVAL."
>
>> }
>> - if (rv == 0) /* address already there is an error */
>> + if (rv == 0) { /* address already there is an error */
>> + err = -EADDRINUSE;
>> goto done;
>> + }
>
> EADDRINUSE is not one of the API's listed error codes. Section 4.1.3
> of RFC3678 specifies:
> "When the option would be legal on the group, but an address is
> invalid (e.g., when trying to block a source that is already blocked
> by the socket, or when trying to drop an unjoined group) the error
> generated is EADDRNOTAVAIL."
>
> At least some of this patch directly differs with RFC3678.
I read the RFC and found you are right, thanks :)
>
> +-DLS
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: ethtool 3.5 released
From: Naoto MATSUMOTO @ 2012-08-06 1:27 UTC (permalink / raw)
To: Ben Hutchings; +Cc: netdev
In-Reply-To: <1344023317.2610.13.camel@bwh-desktop.uk.solarflarecom.com>
Dear Ben.
FYI(For Your Information)
This is Naoto MATSUMOTO, Senior Researcher, SAKURA Internet.
We tried ethtool 3.5 on 40GbE NIC(Mellanox), it's result here.
-----------------------------------------------------------------------
# ./ethtool --version
ethtool version 3.5
# ./ethtool eth1
Settings for eth1:
Supported ports: [ TP ]
Supported link modes: 10000baseT/Full
Supported pause frame use: No
Supports auto-negotiation: No
Advertised link modes: 10000baseT/Full
Advertised pause frame use: No
Advertised auto-negotiation: No
Speed: 40000Mb/s
Duplex: Full
Port: Twisted Pair
PHYAD: 0
Transceiver: internal
Auto-negotiation: off
MDI-X: Unknown
Supports Wake-on: d
Wake-on: d
Current message level: 0x00000014 (20)
link ifdown
Link detected: yes
Our 40GbE NIC Firmware/Dirver status are here.
-----------------------------------------------------------------------
Mellanox ConnectX HCA Ethernet driver v1.5.8.3 (June 2012)
Ethernet controller: Mellanox Technologies MT27500 Family [ConnectX-3]
Firmware Version: 2.10.800
-----------------------------------------------------------------------
And We were testing 10GbE(Intel) NIC and your 40GbE NIC in our lab
using ethtool with added some debug code.
-----------------------------------------------------------------------
# ./ethtool-p eth5 (10GbE NIC by Intel)
Settings for eth5:
Supported ports: [ FIBRE ]
Supported link modes: 10000baseT/Full
mask == 5120 <--- ep->support number
# ./ethtool-p eth1 (40GbE NIC by Mellanox)
Settings for eth1:
Supported ports: [ TP ]
Supported link modes: 10000baseT/Full
mask == 4224 <--- ep->support number
-----------------------------------------------------------------------
It's firmware problem I thinks. But Just Information for you ;-)
regards,
--
Naoto MATSUMOTO
On Fri, 3 Aug 2012 20:48:37 +0100
Ben Hutchings <bhutchings@solarflare.com> wrote:
> ethtool version 3.5 has been released.
>
> Home page: https://ftp.kernel.org/pub/software/network/ethtool/
> Download link:
> https://ftp.kernel.org/pub/software/network/ethtool/ethtool-3.1.tar.gz
>
> Release notes:
>
> * Feature: Display support for 40G link modes
--
SAKURA Internet Inc. / Senior Researcher
Naoto MATSUMOTO <n-matsumoto@sakura.ad.jp>
SAKURA Research Center <http://research.sakura.ad.jp/>
^ permalink raw reply
* Re: [PATCH iproute2] Install the bridge command under the same name we build it.
From: Li Wei @ 2012-08-06 1:51 UTC (permalink / raw)
To: Nick Alcock; +Cc: netdev, Stephen Hemminger
In-Reply-To: <87ehnmiv1m.fsf@spindle.srvr.nix>
On 08/04/2012 10:36 PM, Nick Alcock wrote:
>
> Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
> ---
> bridge/Makefile | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/bridge/Makefile b/bridge/Makefile
> index 0c333bf..9a6743e 100644
> --- a/bridge/Makefile
> +++ b/bridge/Makefile
> @@ -7,8 +7,8 @@ all: bridge
> bridge: $(BROBJ) $(LIBNETLINK)
>
> install: all
> - install -m 0755 br $(DESTDIR)$(SBINDIR)
> + install -m 0755 bridge $(DESTDIR)$(SBINDIR)
>
> clean:
> - rm -f $(BROBJ) br
> + rm -f $(BROBJ) bridge
>
Hi Nick,
To post a patch for iproute2, you should send it to
Stephen Hemminger <shemminger@vyatta.com> who is the maintainer of iproute2.
Stephen, I also noticed this problem and thought should ask you for the final
name of the brige extension. Personally I prefer br, it is short and
distingushable enough.
Thanks.
^ permalink raw reply
* [PATCH v2] can: kvaser_usb: Add support for Kvaser CAN/USB devices
From: Olivier Sobrie @ 2012-08-06 5:21 UTC (permalink / raw)
To: Wolfgang Grandegger, Marc Kleine-Budde, linux-can, linux-usb
Cc: netdev, Olivier Sobrie
In-Reply-To: <1343626352-24760-1-git-send-email-olivier@sobrie.be>
This driver provides support for several Kvaser CAN/USB devices.
Such kind of devices supports up to three can network interfaces.
It has been tested with a Kvaser USB Leaf Light (one network interface)
connected to a pch_can interface.
The firmware version of the Kvaser device was 2.5.205.
List of Kvaser devices supported by the driver:
- Kvaser Leaf prototype (P010v2 and v3)
- Kvaser Leaf Light (P010v3)
- Kvaser Leaf Professional HS
- Kvaser Leaf SemiPro HS
- Kvaser Leaf Professional LS
- Kvaser Leaf Professional SWC
- Kvaser Leaf Professional LIN
- Kvaser Leaf SemiPro LS
- Kvaser Leaf SemiPro SWC
- Kvaser Memorator II, Prototype
- Kvaser Memorator II HS/HS
- Kvaser USBcan Professional HS/HS
- Kvaser Leaf Light GI
- Kvaser Leaf Professional HS (OBD-II connector)
- Kvaser Memorator Professional HS/LS
- Kvaser Leaf Light "China"
- Kvaser BlackBird SemiPro
- Kvaser OEM Mercury
- Kvaser OEM Leaf
- Kvaser USBcan R
Signed-off-by: Olivier Sobrie <olivier@sobrie.be>
---
Changes since v1:
- added copyrights
- kvaser_usb.h merged into kvaser.c
- added kvaser_usb_get_endpoints to find eindpoints instead of
hardcoding their address
- some cleanup and comestic changes
- fixed issues with errors handling
- fixed restart-ms == 0 case
- removed do_get_berr_counter method since the hardware doens't return
good values for txerr and rxerr.
If someone in the linux-usb mailing can review it, it would be nice.
Concerning the errors, it behaves like that now:
1) Short-circuit CAN-H and CAN-L and restart-ms = 0
t0: short-circuit + 'cansend can1 123#112233'
can1 2000008C [8] 00 0C 90 00 00 00 00 00 ERRORFRAME
controller-problem{rx-error-warning,tx-error-warning}
protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
bus-error
can1 2000008C [8] 00 30 90 00 00 00 00 00 ERRORFRAME
controller-problem{rx-error-passive,tx-error-passive}
protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
bus-error
can1 200000C8 [8] 00 00 90 00 00 00 00 00 ERRORFRAME
protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
bus-off
bus-error
t1: remove short-circuit + 'ip link set can1 type can restart'
can1 20000100 [8] 00 00 00 00 00 00 00 00 ERRORFRAME
restarted-after-bus-off
can1 20000004 [8] 00 0C 00 00 00 00 00 00 ERRORFRAME
controller-problem{rx-error-warning,tx-error-warning}
2) Short-circuit CAN-H and CAN-L and restart-ms = 100
t0: short-circuit + cansend can1 123#112233
can1 2000008C [8] 00 0C 90 00 00 00 00 00 ERRORFRAME
controller-problem{rx-error-warning,tx-error-warning}
protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
bus-error
can1 2000008C [8] 00 30 90 00 00 00 00 00 ERRORFRAME
controller-problem{rx-error-passive,tx-error-passive}
protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
bus-error
can1 200000C8 [8] 00 00 90 00 00 00 00 00 ERRORFRAME
protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
bus-off
bus-error
can1 2000018C [8] 00 0C 90 00 00 00 00 00 ERRORFRAME
controller-problem{rx-error-warning,tx-error-warning}
protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
bus-error
restarted-after-bus-off
can1 2000008C [8] 00 0C 90 00 00 00 00 00 ERRORFRAME
controller-problem{rx-error-warning,tx-error-warning}
protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
bus-error
can1 2000008C [8] 00 30 90 00 00 00 00 00 ERRORFRAME
controller-problem{rx-error-passive,tx-error-passive}
protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
bus-error
can1 200000C8 [8] 00 00 90 00 00 00 00 00 ERRORFRAME
protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
bus-off
bus-error
...
can1 2000018C [8] 00 0C 90 00 00 00 00 00 ERRORFRAME
controller-problem{rx-error-warning,tx-error-warning}
protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
bus-error
restarted-after-bus-off
can1 2000008C [8] 00 0C 90 00 00 00 00 00 ERRORFRAME
controller-problem{rx-error-warning,tx-error-warning}
protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
bus-error
can1 2000008C [8] 00 30 90 00 00 00 00 00 ERRORFRAME
controller-problem{rx-error-passive,tx-error-passive}
protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
bus-error
t1: remove short-circuit
can1 123 [3] 11 22 33
can1 20000008 [8] 00 00 40 00 00 00 00 00 ERRORFRAME
protocol-violation{{back-to-error-active}{}}
3) CAN-H and CAN-L disconnected
t0: CAN-H and CAN-L disconnected + cansend can1 123#112233
can1 20000004 [8] 00 30 00 00 00 00 00 00 ERRORFRAME
controller-problem{rx-error-passive,tx-error-passive}
can1 2000008C [8] 00 30 80 1B 00 00 00 00 ERRORFRAME
controller-problem{rx-error-passive,tx-error-passive}
protocol-violation{{error-on-tx}{acknowledge-delimiter}}
bus-error
t1: CAN-H and CAN-L reconnected
can1 123 [3] 11 22 33
can1 20000004 [8] 00 30 00 00 00 00 00 00 ERRORFRAME
controller-problem{rx-error-passive,tx-error-passive}
Let me know if it is correct.
Thanks,
Olivier
drivers/net/can/usb/Kconfig | 33 +
drivers/net/can/usb/Makefile | 1 +
drivers/net/can/usb/kvaser_usb.c | 1437 ++++++++++++++++++++++++++++++++++++++
3 files changed, 1471 insertions(+)
create mode 100644 drivers/net/can/usb/kvaser_usb.c
diff --git a/drivers/net/can/usb/Kconfig b/drivers/net/can/usb/Kconfig
index 0a68768..578955f 100644
--- a/drivers/net/can/usb/Kconfig
+++ b/drivers/net/can/usb/Kconfig
@@ -13,6 +13,39 @@ config CAN_ESD_USB2
This driver supports the CAN-USB/2 interface
from esd electronic system design gmbh (http://www.esd.eu).
+config CAN_KVASER_USB
+ tristate "Kvaser CAN/USB interface"
+ ---help---
+ This driver adds support for Kvaser CAN/USB devices like Kvaser
+ Leaf Light.
+
+ The driver gives support for the following devices:
+ - Kvaser Leaf prototype (P010v2 and v3)
+ - Kvaser Leaf Light (P010v3)
+ - Kvaser Leaf Professional HS
+ - Kvaser Leaf SemiPro HS
+ - Kvaser Leaf Professional LS
+ - Kvaser Leaf Professional SWC
+ - Kvaser Leaf Professional LIN
+ - Kvaser Leaf SemiPro LS
+ - Kvaser Leaf SemiPro SWC
+ - Kvaser Memorator II, Prototype
+ - Kvaser Memorator II HS/HS
+ - Kvaser USBcan Professional HS/HS
+ - Kvaser Leaf Light GI
+ - Kvaser Leaf Professional HS (OBD-II connector)
+ - Kvaser Memorator Professional HS/LS
+ - Kvaser Leaf Light "China"
+ - Kvaser BlackBird SemiPro
+ - Kvaser OEM Mercury
+ - Kvaser OEM Leaf
+ - Kvaser USBcan R
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called kvaser_usb.
+
config CAN_PEAK_USB
tristate "PEAK PCAN-USB/USB Pro interfaces"
---help---
diff --git a/drivers/net/can/usb/Makefile b/drivers/net/can/usb/Makefile
index da6d1d3..80a2ee4 100644
--- a/drivers/net/can/usb/Makefile
+++ b/drivers/net/can/usb/Makefile
@@ -4,6 +4,7 @@
obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o
obj-$(CONFIG_CAN_ESD_USB2) += esd_usb2.o
+obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb.o
obj-$(CONFIG_CAN_PEAK_USB) += peak_usb/
ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c
new file mode 100644
index 0000000..eea0655
--- /dev/null
+++ b/drivers/net/can/usb/kvaser_usb.c
@@ -0,0 +1,1437 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * Parts of this driver are based on the following:
+ * - Kvaser linux leaf driver (version 4.78)
+ * - CAN driver for esd CAN-USB/2
+ *
+ * Copyright (C) 2002-2006 KVASER AB, Sweden. All rights reserved.
+ * Copyright (C) 2010 Matthias Fuchs <matthias.fuchs@esd.eu>, esd gmbh
+ * Copyright (C) 2012 Olivier Sobrie <olivier@sobrie.be>
+ */
+
+#include <linux/init.h>
+#include <linux/completion.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/usb.h>
+
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
+
+#define MAX_TX_URBS 16
+#define MAX_RX_URBS 4
+#define START_TIMEOUT 1000
+#define STOP_TIMEOUT 1000
+#define USB_SEND_TIMEOUT 1000
+#define USB_RECV_TIMEOUT 1000
+#define RX_BUFFER_SIZE 3072
+#define CAN_USB_CLOCK 8000000
+#define MAX_NET_DEVICES 3
+
+/* Kvaser USB devices */
+#define KVASER_VENDOR_ID 0x0bfd
+#define USB_LEAF_DEVEL_PRODUCT_ID 10
+#define USB_LEAF_LITE_PRODUCT_ID 11
+#define USB_LEAF_PRO_PRODUCT_ID 12
+#define USB_LEAF_SPRO_PRODUCT_ID 14
+#define USB_LEAF_PRO_LS_PRODUCT_ID 15
+#define USB_LEAF_PRO_SWC_PRODUCT_ID 16
+#define USB_LEAF_PRO_LIN_PRODUCT_ID 17
+#define USB_LEAF_SPRO_LS_PRODUCT_ID 18
+#define USB_LEAF_SPRO_SWC_PRODUCT_ID 19
+#define USB_MEMO2_DEVEL_PRODUCT_ID 22
+#define USB_MEMO2_HSHS_PRODUCT_ID 23
+#define USB_UPRO_HSHS_PRODUCT_ID 24
+#define USB_LEAF_LITE_GI_PRODUCT_ID 25
+#define USB_LEAF_PRO_OBDII_PRODUCT_ID 26
+#define USB_MEMO2_HSLS_PRODUCT_ID 27
+#define USB_LEAF_LITE_CH_PRODUCT_ID 28
+#define USB_BLACKBIRD_SPRO_PRODUCT_ID 29
+#define USB_OEM_MERCURY_PRODUCT_ID 34
+#define USB_OEM_LEAF_PRODUCT_ID 35
+#define USB_CAN_R_PRODUCT_ID 39
+
+/* USB devices features */
+#define KVASER_HAS_SILENT_MODE BIT(0)
+
+/* Message header size */
+#define MSG_HEADER_LEN 2
+
+/* Can message flags */
+#define MSG_FLAG_ERROR_FRAME BIT(0)
+#define MSG_FLAG_OVERRUN BIT(1)
+#define MSG_FLAG_NERR BIT(2)
+#define MSG_FLAG_WAKEUP BIT(3)
+#define MSG_FLAG_REMOTE_FRAME BIT(4)
+#define MSG_FLAG_RESERVED BIT(5)
+#define MSG_FLAG_TX_ACK BIT(6)
+#define MSG_FLAG_TX_REQUEST BIT(7)
+
+/* Can states */
+#define M16C_STATE_BUS_RESET BIT(0)
+#define M16C_STATE_BUS_ERROR BIT(4)
+#define M16C_STATE_BUS_PASSIVE BIT(5)
+#define M16C_STATE_BUS_OFF BIT(6)
+
+/* Can msg ids */
+#define CMD_RX_STD_MESSAGE 12
+#define CMD_TX_STD_MESSAGE 13
+#define CMD_RX_EXT_MESSAGE 14
+#define CMD_TX_EXT_MESSAGE 15
+#define CMD_SET_BUS_PARAMS 16
+#define CMD_GET_BUS_PARAMS 17
+#define CMD_GET_BUS_PARAMS_REPLY 18
+#define CMD_GET_CHIP_STATE 19
+#define CMD_CHIP_STATE_EVENT 20
+#define CMD_SET_CTRL_MODE 21
+#define CMD_GET_CTRL_MODE 22
+#define CMD_GET_CTRL_MODE_REPLY 23
+#define CMD_RESET_CHIP 24
+#define CMD_RESET_CARD 25
+#define CMD_START_CHIP 26
+#define CMD_START_CHIP_REPLY 27
+#define CMD_STOP_CHIP 28
+#define CMD_STOP_CHIP_REPLY 29
+#define CMD_GET_CARD_INFO2 32
+#define CMD_GET_CARD_INFO 34
+#define CMD_GET_CARD_INFO_REPLY 35
+#define CMD_GET_SOFTWARE_INFO 38
+#define CMD_GET_SOFTWARE_INFO_REPLY 39
+#define CMD_ERROR_EVENT 45
+#define CMD_FLUSH_QUEUE 48
+#define CMD_RESET_ERROR_COUNTER 49
+#define CMD_TX_ACKNOWLEDGE 50
+#define CMD_CAN_ERROR_EVENT 51
+#define CMD_USB_THROTTLE 77
+
+/* error factors */
+#define M16C_EF_ACKE BIT(0)
+#define M16C_EF_CRCE BIT(1)
+#define M16C_EF_FORME BIT(2)
+#define M16C_EF_STFE BIT(3)
+#define M16C_EF_BITE0 BIT(4)
+#define M16C_EF_BITE1 BIT(5)
+#define M16C_EF_RCVE BIT(6)
+#define M16C_EF_TRE BIT(7)
+
+/* bittiming parameters */
+#define KVASER_USB_TSEG1_MIN 1
+#define KVASER_USB_TSEG1_MAX 16
+#define KVASER_USB_TSEG2_MIN 1
+#define KVASER_USB_TSEG2_MAX 8
+#define KVASER_USB_SJW_MAX 4
+#define KVASER_USB_BRP_MIN 1
+#define KVASER_USB_BRP_MAX 64
+#define KVASER_USB_BRP_INC 1
+
+/* ctrl modes */
+#define KVASER_CTRL_MODE_NORMAL 1
+#define KVASER_CTRL_MODE_SILENT 2
+#define KVASER_CTRL_MODE_SELFRECEPTION 3
+#define KVASER_CTRL_MODE_OFF 4
+
+struct kvaser_msg_simple {
+ u8 tid;
+ u8 channel;
+} __packed;
+
+struct kvaser_msg_cardinfo {
+ u8 tid;
+ u8 nchannels;
+ __le32 serial_number;
+ __le32 padding;
+ __le32 clock_resolution;
+ __le32 mfgdate;
+ u8 ean[8];
+ u8 hw_revision;
+ u8 usb_hs_mode;
+ __le16 padding2;
+} __packed;
+
+struct kvaser_msg_cardinfo2 {
+ u8 tid;
+ u8 channel;
+ u8 pcb_id[24];
+ __le32 oem_unlock_code;
+} __packed;
+
+struct kvaser_msg_softinfo {
+ u8 tid;
+ u8 channel;
+ __le32 sw_options;
+ __le32 fw_version;
+ __le16 max_outstanding_tx;
+ __le16 padding[9];
+} __packed;
+
+struct kvaser_msg_busparams {
+ u8 tid;
+ u8 channel;
+ __le32 bitrate;
+ u8 tseg1;
+ u8 tseg2;
+ u8 sjw;
+ u8 no_samp;
+} __packed;
+
+struct kvaser_msg_tx_can {
+ u8 channel;
+ u8 tid;
+ u8 msg[14];
+ u8 padding;
+ u8 flags;
+} __packed;
+
+struct kvaser_msg_rx_can {
+ u8 channel;
+ u8 flag;
+ __le16 time[3];
+ u8 msg[14];
+} __packed;
+
+struct kvaser_msg_chip_state_event {
+ u8 tid;
+ u8 channel;
+ __le16 time[3];
+ u8 tx_errors_count;
+ u8 rx_errors_count;
+ u8 status;
+ u8 padding[3];
+} __packed;
+
+struct kvaser_msg_tx_acknowledge {
+ u8 channel;
+ u8 tid;
+ __le16 time[3];
+ u8 flags;
+ u8 time_offset;
+} __packed;
+
+struct kvaser_msg_error_event {
+ u8 tid;
+ u8 flags;
+ __le16 time[3];
+ u8 channel;
+ u8 padding;
+ u8 tx_errors_count;
+ u8 rx_errors_count;
+ u8 status;
+ u8 error_factor;
+} __packed;
+
+struct kvaser_msg_ctrl_mode {
+ u8 tid;
+ u8 channel;
+ u8 ctrl_mode;
+ u8 padding[3];
+} __packed;
+
+struct kvaser_msg_flush_queue {
+ u8 tid;
+ u8 channel;
+ u8 flags;
+ u8 padding[3];
+} __packed;
+
+struct kvaser_msg {
+ u8 len;
+ u8 id;
+ union {
+ struct kvaser_msg_simple simple;
+ struct kvaser_msg_cardinfo cardinfo;
+ struct kvaser_msg_cardinfo2 cardinfo2;
+ struct kvaser_msg_softinfo softinfo;
+ struct kvaser_msg_busparams busparams;
+ struct kvaser_msg_tx_can tx_can;
+ struct kvaser_msg_rx_can rx_can;
+ struct kvaser_msg_chip_state_event chip_state_event;
+ struct kvaser_msg_tx_acknowledge tx_acknowledge;
+ struct kvaser_msg_error_event error_event;
+ struct kvaser_msg_ctrl_mode ctrl_mode;
+ struct kvaser_msg_flush_queue flush_queue;
+ } u;
+} __packed;
+
+struct kvaser_usb_tx_urb_context {
+ struct kvaser_usb_net_priv *priv;
+ u32 echo_index;
+ int dlc;
+};
+
+struct kvaser_usb {
+ struct usb_device *udev;
+ struct kvaser_usb_net_priv *nets[MAX_NET_DEVICES];
+
+ struct usb_endpoint_descriptor *bulk_in, *bulk_out;
+ struct usb_anchor rx_submitted;
+
+ u32 fw_version;
+ unsigned int nchannels;
+
+ bool rxinitdone;
+};
+
+struct kvaser_usb_net_priv {
+ struct can_priv can;
+
+ atomic_t active_tx_urbs;
+ struct usb_anchor tx_submitted;
+ struct kvaser_usb_tx_urb_context tx_contexts[MAX_TX_URBS];
+
+ struct completion start_comp, stop_comp;
+
+ struct kvaser_usb *dev;
+ struct net_device *netdev;
+ int channel;
+
+ struct can_frame cf_err_old;
+};
+
+static struct usb_device_id kvaser_usb_table[] = {
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_DEVEL_PRODUCT_ID) },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_PRODUCT_ID) },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_PRODUCT_ID),
+ .driver_info = KVASER_HAS_SILENT_MODE },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_PRODUCT_ID),
+ .driver_info = KVASER_HAS_SILENT_MODE },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LS_PRODUCT_ID),
+ .driver_info = KVASER_HAS_SILENT_MODE },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_SWC_PRODUCT_ID),
+ .driver_info = KVASER_HAS_SILENT_MODE },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LIN_PRODUCT_ID),
+ .driver_info = KVASER_HAS_SILENT_MODE },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_LS_PRODUCT_ID),
+ .driver_info = KVASER_HAS_SILENT_MODE },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_SWC_PRODUCT_ID),
+ .driver_info = KVASER_HAS_SILENT_MODE },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_DEVEL_PRODUCT_ID),
+ .driver_info = KVASER_HAS_SILENT_MODE },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_HSHS_PRODUCT_ID),
+ .driver_info = KVASER_HAS_SILENT_MODE },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_UPRO_HSHS_PRODUCT_ID) },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_GI_PRODUCT_ID) },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_OBDII_PRODUCT_ID),
+ .driver_info = KVASER_HAS_SILENT_MODE },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_HSLS_PRODUCT_ID) },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_CH_PRODUCT_ID) },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_BLACKBIRD_SPRO_PRODUCT_ID) },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_OEM_MERCURY_PRODUCT_ID) },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_OEM_LEAF_PRODUCT_ID) },
+ { USB_DEVICE(KVASER_VENDOR_ID, USB_CAN_R_PRODUCT_ID) },
+ { }
+};
+MODULE_DEVICE_TABLE(usb, kvaser_usb_table);
+
+static inline int kvaser_usb_send_msg(const struct kvaser_usb *dev,
+ struct kvaser_msg *msg)
+{
+ int actual_len;
+
+ return usb_bulk_msg(dev->udev,
+ usb_sndbulkpipe(dev->udev,
+ dev->bulk_out->bEndpointAddress),
+ msg, msg->len, &actual_len,
+ USB_SEND_TIMEOUT);
+}
+
+static int kvaser_usb_wait_msg(const struct kvaser_usb *dev, u8 id,
+ struct kvaser_msg *msg)
+{
+ struct kvaser_msg *tmp;
+ void *buf;
+ int actual_len;
+ int err;
+ int pos = 0;
+
+ buf = kzalloc(RX_BUFFER_SIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ err = usb_bulk_msg(dev->udev,
+ usb_rcvbulkpipe(dev->udev,
+ dev->bulk_in->bEndpointAddress),
+ buf, RX_BUFFER_SIZE, &actual_len,
+ USB_RECV_TIMEOUT);
+ if (err < 0) {
+ kfree(buf);
+ return err;
+ }
+
+ while (pos <= actual_len - MSG_HEADER_LEN) {
+ tmp = buf + pos;
+
+ if (!tmp->len)
+ break;
+
+ if (pos + tmp->len > actual_len) {
+ dev_err(dev->udev->dev.parent, "Format error\n");
+ break;
+ }
+
+ if (tmp->id == id) {
+ memcpy(msg, tmp, tmp->len);
+ kfree(buf);
+ return 0;
+ }
+
+ pos += tmp->len;
+ }
+
+ kfree(buf);
+
+ return -EINVAL;
+}
+
+static int kvaser_usb_send_simple_msg(const struct kvaser_usb *dev,
+ u8 msg_id, int channel)
+{
+ struct kvaser_msg msg = {
+ .len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_simple),
+ .id = msg_id,
+ .u.simple.channel = channel,
+ .u.simple.tid = 0xff,
+ };
+
+ return kvaser_usb_send_msg(dev, &msg);
+}
+
+static int kvaser_usb_get_software_info(struct kvaser_usb *dev)
+{
+ struct kvaser_msg msg;
+ int err;
+
+ err = kvaser_usb_send_simple_msg(dev, CMD_GET_SOFTWARE_INFO, 0);
+ if (err)
+ return err;
+
+ err = kvaser_usb_wait_msg(dev, CMD_GET_SOFTWARE_INFO_REPLY, &msg);
+ if (err)
+ return err;
+
+ dev->fw_version = le32_to_cpu(msg.u.softinfo.fw_version);
+
+ return 0;
+}
+
+static int kvaser_usb_get_card_info(struct kvaser_usb *dev)
+{
+ struct kvaser_msg msg;
+ int err;
+
+ err = kvaser_usb_send_simple_msg(dev, CMD_GET_CARD_INFO, 0);
+ if (err)
+ return err;
+
+ err = kvaser_usb_wait_msg(dev, CMD_GET_CARD_INFO_REPLY, &msg);
+ if (err)
+ return err;
+
+ dev->nchannels = msg.u.cardinfo.nchannels;
+
+ return 0;
+}
+
+static void kvaser_usb_tx_acknowledge(const struct kvaser_usb *dev,
+ const struct kvaser_msg *msg)
+{
+ struct net_device_stats *stats;
+ struct kvaser_usb_tx_urb_context *context;
+ struct kvaser_usb_net_priv *priv;
+ u8 channel = msg->u.tx_acknowledge.channel;
+ u8 tid = msg->u.tx_acknowledge.tid;
+
+ if (channel >= dev->nchannels) {
+ dev_err(dev->udev->dev.parent,
+ "Invalid channel number (%d)\n", channel);
+ return;
+ }
+
+ priv = dev->nets[channel];
+
+ if (!netif_device_present(priv->netdev))
+ return;
+
+ stats = &priv->netdev->stats;
+
+ context = &priv->tx_contexts[tid % MAX_TX_URBS];
+
+ /*
+ * It looks like the firmware never sets the flags field of the
+ * tx_acknowledge frame and never reports a transmit failure.
+ * If the can message can't be transmited (e.g. incompatible
+ * bitrates), a frame CMD_CAN_ERROR_EVENT is sent (with a null
+ * tid) and the firmware tries to transmit again the packet until
+ * it succeeds. Once the packet is successfully transmitted, then
+ * the tx_acknowledge frame is sent.
+ */
+
+ stats->tx_packets++;
+ stats->tx_bytes += context->dlc;
+ can_get_echo_skb(priv->netdev, context->echo_index);
+
+ context->echo_index = MAX_TX_URBS;
+ atomic_dec(&priv->active_tx_urbs);
+
+ netif_wake_queue(priv->netdev);
+}
+
+static void kvaser_usb_simple_msg_callback(struct urb *urb)
+{
+ struct net_device *netdev = urb->context;
+
+ if (urb->status)
+ netdev_warn(netdev, "urb status received: %d\n",
+ urb->status);
+}
+
+static int kvaser_usb_simple_msg_async(struct kvaser_usb_net_priv *priv,
+ u8 msg_id)
+{
+ struct kvaser_usb *dev = priv->dev;
+ struct net_device *netdev = priv->netdev;
+ struct kvaser_msg *msg;
+ struct urb *urb;
+ void *buf;
+ int err;
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
+ netdev_err(netdev, "No memory left for URBs\n");
+ return -ENOMEM;
+ }
+
+ buf = usb_alloc_coherent(dev->udev, sizeof(struct kvaser_msg),
+ GFP_ATOMIC, &urb->transfer_dma);
+ if (!buf) {
+ netdev_err(netdev, "No memory left for USB buffer\n");
+ return -ENOMEM;
+ }
+
+ msg = (struct kvaser_msg *)buf;
+ msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_simple);
+ msg->id = msg_id;
+ msg->u.simple.channel = priv->channel;
+
+ usb_fill_bulk_urb(urb, dev->udev,
+ usb_sndbulkpipe(dev->udev,
+ dev->bulk_out->bEndpointAddress),
+ buf, msg->len,
+ kvaser_usb_simple_msg_callback, priv);
+ urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ usb_anchor_urb(urb, &priv->tx_submitted);
+
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err) {
+ netdev_err(netdev, "Error transmitting URB\n");
+ usb_unanchor_urb(urb);
+ return err;
+ }
+
+ return 0;
+}
+
+static void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv)
+{
+ int i;
+
+ usb_kill_anchored_urbs(&priv->tx_submitted);
+ atomic_set(&priv->active_tx_urbs, 0);
+
+ for (i = 0; i < MAX_TX_URBS; i++)
+ priv->tx_contexts[i].echo_index = MAX_TX_URBS;
+}
+
+static void kvaser_usb_rx_error(const struct kvaser_usb *dev,
+ const struct kvaser_msg *msg)
+{
+ struct can_frame *cf;
+ struct sk_buff *skb;
+ struct net_device_stats *stats;
+ struct kvaser_usb_net_priv *priv;
+ unsigned int new_state;
+ u8 channel, status;
+
+ if (msg->id == CMD_CAN_ERROR_EVENT) {
+ channel = msg->u.error_event.channel;
+ status = msg->u.error_event.status;
+ } else {
+ channel = msg->u.chip_state_event.channel;
+ status = msg->u.chip_state_event.status;
+ }
+
+ if (channel >= dev->nchannels) {
+ dev_err(dev->udev->dev.parent,
+ "Invalid channel number (%d)\n", channel);
+ return;
+ }
+
+ priv = dev->nets[channel];
+ stats = &priv->netdev->stats;
+
+ if (status & M16C_STATE_BUS_RESET) {
+ kvaser_usb_unlink_tx_urbs(priv);
+ return;
+ }
+
+ skb = alloc_can_err_skb(priv->netdev, &cf);
+ if (!skb) {
+ stats->rx_dropped++;
+ return;
+ }
+
+ if (status & M16C_STATE_BUS_OFF) {
+ cf->can_id |= CAN_ERR_BUSOFF;
+
+ if (!priv->can.restart_ms)
+ kvaser_usb_simple_msg_async(priv, CMD_STOP_CHIP);
+
+ if (!priv->can.state != CAN_ERR_BUSOFF) {
+ priv->can.can_stats.bus_off++;
+ netif_carrier_off(priv->netdev);
+ }
+
+ new_state = CAN_STATE_BUS_OFF;
+ } else if (status & M16C_STATE_BUS_PASSIVE) {
+ cf->can_id |= CAN_ERR_CRTL;
+ cf->data[1] = CAN_ERR_CRTL_TX_PASSIVE |
+ CAN_ERR_CRTL_RX_PASSIVE;
+
+ if (priv->can.state != CAN_STATE_ERROR_PASSIVE)
+ priv->can.can_stats.error_passive++;
+
+ new_state = CAN_STATE_ERROR_PASSIVE;
+ } else if (status & M16C_STATE_BUS_ERROR) {
+ cf->can_id |= CAN_ERR_CRTL;
+ cf->data[1] = CAN_ERR_CRTL_TX_WARNING |
+ CAN_ERR_CRTL_RX_WARNING;
+
+ if (priv->can.state != CAN_STATE_ERROR_WARNING)
+ priv->can.can_stats.error_warning++;
+
+ new_state = CAN_STATE_ERROR_WARNING;
+ } else {
+ cf->can_id |= CAN_ERR_PROT;
+ cf->data[2] = CAN_ERR_PROT_ACTIVE;
+
+ new_state = CAN_STATE_ERROR_ACTIVE;
+ }
+
+ if (priv->can.restart_ms &&
+ (priv->can.state >= CAN_STATE_BUS_OFF) &&
+ (new_state < CAN_STATE_BUS_OFF)) {
+ cf->can_id |= CAN_ERR_RESTARTED;
+ priv->can.can_stats.restarts++;
+ netif_carrier_on(priv->netdev);
+ }
+
+ if (msg->id == CMD_CAN_ERROR_EVENT) {
+ u8 error_factor = msg->u.error_event.error_factor;
+
+ priv->can.can_stats.bus_error++;
+ stats->rx_errors++;
+
+ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+
+ if (error_factor & M16C_EF_ACKE)
+ cf->data[3] |= (CAN_ERR_PROT_LOC_ACK |
+ CAN_ERR_PROT_LOC_ACK_DEL);
+ if (error_factor & M16C_EF_CRCE)
+ cf->data[3] |= (CAN_ERR_PROT_LOC_CRC_SEQ |
+ CAN_ERR_PROT_LOC_CRC_DEL);
+ if (error_factor & M16C_EF_FORME)
+ cf->data[2] |= CAN_ERR_PROT_FORM;
+ if (error_factor & M16C_EF_STFE)
+ cf->data[2] |= CAN_ERR_PROT_STUFF;
+ if (error_factor & M16C_EF_BITE0)
+ cf->data[2] |= CAN_ERR_PROT_BIT0;
+ if (error_factor & M16C_EF_BITE1)
+ cf->data[2] |= CAN_ERR_PROT_BIT1;
+ if (error_factor & M16C_EF_TRE)
+ cf->data[2] |= CAN_ERR_PROT_TX;
+ }
+
+ priv->can.state = new_state;
+
+ if (!memcmp(cf, &priv->cf_err_old, sizeof(*cf))) {
+ kfree_skb(skb);
+ return;
+ }
+
+ netif_rx(skb);
+
+ priv->cf_err_old = *cf;
+
+ stats->rx_packets++;
+ stats->rx_bytes += cf->can_dlc;
+}
+
+static void kvaser_usb_rx_can_msg(const struct kvaser_usb *dev,
+ const struct kvaser_msg *msg)
+{
+ struct kvaser_usb_net_priv *priv;
+ struct can_frame *cf;
+ struct sk_buff *skb;
+ struct net_device_stats *stats;
+ u8 channel = msg->u.rx_can.channel;
+
+ if (channel >= dev->nchannels) {
+ dev_err(dev->udev->dev.parent,
+ "Invalid channel number (%d)\n", channel);
+ return;
+ }
+
+ priv = dev->nets[channel];
+ stats = &priv->netdev->stats;
+
+ skb = alloc_can_skb(priv->netdev, &cf);
+ if (skb == NULL) {
+ stats->tx_dropped++;
+ return;
+ }
+
+ cf->can_id = ((msg->u.rx_can.msg[0] & 0x1f) << 6) |
+ (msg->u.rx_can.msg[1] & 0x3f);
+ cf->can_dlc = get_can_dlc(msg->u.rx_can.msg[5]);
+
+ if (msg->id == CMD_RX_EXT_MESSAGE) {
+ cf->can_id <<= 18;
+ cf->can_id |= ((msg->u.rx_can.msg[2] & 0x0f) << 14) |
+ ((msg->u.rx_can.msg[3] & 0xff) << 6) |
+ (msg->u.rx_can.msg[4] & 0x3f);
+ cf->can_id |= CAN_EFF_FLAG;
+ }
+
+ if (msg->u.rx_can.flag & MSG_FLAG_REMOTE_FRAME) {
+ cf->can_id |= CAN_RTR_FLAG;
+ } else if (msg->u.rx_can.flag & (MSG_FLAG_ERROR_FRAME |
+ MSG_FLAG_NERR)) {
+ cf->can_id |= CAN_ERR_FLAG;
+ cf->can_dlc = CAN_ERR_DLC;
+ cf->data[1] = CAN_ERR_CRTL_UNSPEC;
+
+ stats->rx_errors++;
+ } else if (msg->u.rx_can.flag & MSG_FLAG_OVERRUN) {
+ cf->can_id = CAN_ERR_FLAG | CAN_ERR_CRTL;
+ cf->can_dlc = CAN_ERR_DLC;
+ cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+
+ stats->rx_over_errors++;
+ stats->rx_errors++;
+ } else if (!msg->u.rx_can.flag) {
+ memcpy(cf->data, &msg->u.rx_can.msg[6], cf->can_dlc);
+ } else {
+ kfree_skb(skb);
+ return;
+ }
+
+ netif_rx(skb);
+
+ stats->rx_packets++;
+ stats->rx_bytes += cf->can_dlc;
+}
+
+static void kvaser_usb_start_chip_reply(const struct kvaser_usb *dev,
+ const struct kvaser_msg *msg)
+{
+ struct kvaser_usb_net_priv *priv;
+ u8 channel = msg->u.simple.channel;
+
+ if (channel >= dev->nchannels) {
+ dev_err(dev->udev->dev.parent,
+ "Invalid channel number (%d)\n", channel);
+ return;
+ }
+
+ priv = dev->nets[channel];
+
+ if (completion_done(&priv->start_comp) &&
+ netif_queue_stopped(priv->netdev)) {
+ netif_wake_queue(priv->netdev);
+ } else {
+ netif_start_queue(priv->netdev);
+ complete(&priv->start_comp);
+ }
+}
+
+static void kvaser_usb_stop_chip_reply(const struct kvaser_usb *dev,
+ const struct kvaser_msg *msg)
+{
+ struct kvaser_usb_net_priv *priv;
+ u8 channel = msg->u.simple.channel;
+
+ if (channel >= dev->nchannels) {
+ dev_err(dev->udev->dev.parent,
+ "Invalid channel number (%d)\n", channel);
+ return;
+ }
+
+ priv = dev->nets[channel];
+
+ complete(&priv->stop_comp);
+}
+
+static void kvaser_usb_handle_message(const struct kvaser_usb *dev,
+ const struct kvaser_msg *msg)
+{
+ switch (msg->id) {
+ case CMD_START_CHIP_REPLY:
+ kvaser_usb_start_chip_reply(dev, msg);
+ break;
+
+ case CMD_STOP_CHIP_REPLY:
+ kvaser_usb_stop_chip_reply(dev, msg);
+ break;
+
+ case CMD_RX_STD_MESSAGE:
+ case CMD_RX_EXT_MESSAGE:
+ kvaser_usb_rx_can_msg(dev, msg);
+ break;
+
+ case CMD_CHIP_STATE_EVENT:
+ case CMD_CAN_ERROR_EVENT:
+ kvaser_usb_rx_error(dev, msg);
+ break;
+
+ case CMD_TX_ACKNOWLEDGE:
+ kvaser_usb_tx_acknowledge(dev, msg);
+ break;
+
+ default:
+ dev_warn(dev->udev->dev.parent,
+ "Unhandled message (%d)\n", msg->id);
+ break;
+ }
+}
+
+static void kvaser_usb_read_bulk_callback(struct urb *urb)
+{
+ struct kvaser_usb *dev = urb->context;
+ struct kvaser_msg *msg;
+ int pos = 0;
+ int err, i;
+
+ switch (urb->status) {
+ case 0:
+ break;
+ case -ENOENT:
+ case -ESHUTDOWN:
+ return;
+ default:
+ dev_info(dev->udev->dev.parent, "Rx URB aborted (%d)\n",
+ urb->status);
+ goto resubmit_urb;
+ }
+
+ while (pos <= urb->actual_length - MSG_HEADER_LEN) {
+ msg = urb->transfer_buffer + pos;
+
+ if (!msg->len)
+ break;
+
+ if (pos + msg->len > urb->actual_length) {
+ dev_err(dev->udev->dev.parent, "Format error\n");
+ break;
+ }
+
+ kvaser_usb_handle_message(dev, msg);
+
+ pos += msg->len;
+ }
+
+resubmit_urb:
+ usb_fill_bulk_urb(urb, dev->udev,
+ usb_rcvbulkpipe(dev->udev,
+ dev->bulk_in->bEndpointAddress),
+ urb->transfer_buffer, RX_BUFFER_SIZE,
+ kvaser_usb_read_bulk_callback, dev);
+
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err == -ENODEV) {
+ for (i = 0; i < dev->nchannels; i++) {
+ if (!dev->nets[i])
+ continue;
+
+ netif_device_detach(dev->nets[i]->netdev);
+ }
+ } else if (err) {
+ dev_err(dev->udev->dev.parent,
+ "Failed resubmitting read bulk urb: %d\n", err);
+ }
+
+ return;
+}
+
+static int kvaser_usb_setup_rx_urbs(struct kvaser_usb *dev)
+{
+ int i, err = 0;
+
+ if (dev->rxinitdone)
+ return 0;
+
+ for (i = 0; i < MAX_RX_URBS; i++) {
+ struct urb *urb = NULL;
+ u8 *buf = NULL;
+
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb) {
+ dev_warn(dev->udev->dev.parent,
+ "No memory left for URBs\n");
+ err = -ENOMEM;
+ break;
+ }
+
+ buf = usb_alloc_coherent(dev->udev, RX_BUFFER_SIZE,
+ GFP_KERNEL, &urb->transfer_dma);
+ if (!buf) {
+ dev_warn(dev->udev->dev.parent,
+ "No memory left for USB buffer\n");
+ usb_free_urb(urb);
+ err = -ENOMEM;
+ break;
+ }
+
+ usb_fill_bulk_urb(urb, dev->udev,
+ usb_rcvbulkpipe(dev->udev,
+ dev->bulk_in->bEndpointAddress),
+ buf, RX_BUFFER_SIZE,
+ kvaser_usb_read_bulk_callback,
+ dev);
+ urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ usb_anchor_urb(urb, &dev->rx_submitted);
+
+ err = usb_submit_urb(urb, GFP_KERNEL);
+ if (err) {
+ usb_unanchor_urb(urb);
+ usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf,
+ urb->transfer_dma);
+ break;
+ }
+
+ usb_free_urb(urb);
+ }
+
+ if (i == 0) {
+ dev_warn(dev->udev->dev.parent,
+ "Cannot setup read URBs, error %d\n", err);
+ return err;
+ } else if (i < MAX_RX_URBS) {
+ dev_warn(dev->udev->dev.parent,
+ "RX performances may be slow\n");
+ }
+
+ dev->rxinitdone = true;
+
+ return 0;
+}
+
+static int kvaser_usb_set_opt_mode(const struct kvaser_usb_net_priv *priv)
+{
+ struct kvaser_msg msg = {
+ .id = CMD_SET_CTRL_MODE,
+ .len = MSG_HEADER_LEN +
+ sizeof(struct kvaser_msg_ctrl_mode),
+ .u.ctrl_mode.tid = 0xff,
+ .u.ctrl_mode.channel = priv->channel,
+ };
+
+ if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
+ msg.u.ctrl_mode.ctrl_mode = KVASER_CTRL_MODE_SILENT;
+ else
+ msg.u.ctrl_mode.ctrl_mode = KVASER_CTRL_MODE_NORMAL;
+
+ return kvaser_usb_send_msg(priv->dev, &msg);
+}
+
+static int kvaser_usb_start_chip(struct kvaser_usb_net_priv *priv)
+{
+ int err;
+
+ init_completion(&priv->start_comp);
+
+ err = kvaser_usb_send_simple_msg(priv->dev, CMD_START_CHIP,
+ priv->channel);
+ if (err)
+ return err;
+
+ if (!wait_for_completion_timeout(&priv->start_comp,
+ msecs_to_jiffies(START_TIMEOUT)))
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static int kvaser_usb_open(struct net_device *netdev)
+{
+ struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+ struct kvaser_usb *dev = priv->dev;
+ int err;
+
+ err = open_candev(netdev);
+ if (err)
+ return err;
+
+ err = kvaser_usb_setup_rx_urbs(dev);
+ if (err)
+ return err;
+
+ err = kvaser_usb_set_opt_mode(priv);
+ if (err)
+ return err;
+
+ err = kvaser_usb_start_chip(priv);
+ if (err) {
+ netdev_warn(netdev, "Cannot start device, error %d\n", err);
+ close_candev(netdev);
+ return err;
+ }
+
+ priv->can.state = CAN_STATE_ERROR_ACTIVE;
+
+ return 0;
+}
+
+static void kvaser_usb_unlink_all_urbs(struct kvaser_usb *dev)
+{
+ int i;
+
+ usb_kill_anchored_urbs(&dev->rx_submitted);
+
+ for (i = 0; i < MAX_NET_DEVICES; i++) {
+ struct kvaser_usb_net_priv *priv = dev->nets[i];
+
+ if (priv)
+ kvaser_usb_unlink_tx_urbs(priv);
+ }
+}
+
+static int kvaser_usb_stop_chip(struct kvaser_usb_net_priv *priv)
+{
+ int err;
+
+ init_completion(&priv->stop_comp);
+
+ err = kvaser_usb_send_simple_msg(priv->dev, CMD_STOP_CHIP,
+ priv->channel);
+ if (err)
+ return err;
+
+ if (!wait_for_completion_timeout(&priv->stop_comp,
+ msecs_to_jiffies(STOP_TIMEOUT)))
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static int kvaser_usb_flush_queue(struct kvaser_usb_net_priv *priv)
+{
+ struct kvaser_msg msg = {
+ .id = CMD_FLUSH_QUEUE,
+ .len = MSG_HEADER_LEN +
+ sizeof(struct kvaser_msg_flush_queue),
+ .u.flush_queue.channel = priv->channel,
+ .u.flush_queue.flags = 0x00,
+ };
+
+ return kvaser_usb_send_msg(priv->dev, &msg);
+}
+
+static int kvaser_usb_close(struct net_device *netdev)
+{
+ struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+ struct kvaser_usb *dev = priv->dev;
+ int err;
+
+ netif_stop_queue(netdev);
+
+ err = kvaser_usb_flush_queue(priv);
+ if (err)
+ netdev_warn(netdev, "Cannot flush queue, error %d\n", err);
+
+ if (kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, priv->channel))
+ netdev_warn(netdev, "Cannot reset card, error %d\n", err);
+
+ err = kvaser_usb_stop_chip(priv);
+ if (err) {
+ netdev_warn(netdev, "Cannot stop device, error %d\n", err);
+ return err;
+ }
+
+ priv->can.state = CAN_STATE_STOPPED;
+ close_candev(priv->netdev);
+
+ return 0;
+}
+
+static void kvaser_usb_write_bulk_callback(struct urb *urb)
+{
+ struct kvaser_usb_tx_urb_context *context = urb->context;
+ struct kvaser_usb_net_priv *priv;
+ struct net_device *netdev;
+
+ if (WARN_ON(!context))
+ return;
+
+ priv = context->priv;
+ netdev = priv->netdev;
+
+ usb_free_coherent(urb->dev, urb->transfer_buffer_length,
+ urb->transfer_buffer, urb->transfer_dma);
+
+ if (!netif_device_present(netdev))
+ return;
+
+ if (urb->status)
+ netdev_info(netdev, "Tx URB aborted (%d)\n", urb->status);
+}
+
+static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
+ struct net_device *netdev)
+{
+ struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+ struct kvaser_usb *dev = priv->dev;
+ struct net_device_stats *stats = &netdev->stats;
+ struct can_frame *cf = (struct can_frame *)skb->data;
+ struct kvaser_usb_tx_urb_context *context = NULL;
+ struct urb *urb;
+ void *buf;
+ struct kvaser_msg *msg;
+ int i, err;
+ int ret = NETDEV_TX_OK;
+
+ if (can_dropped_invalid_skb(netdev, skb))
+ return NETDEV_TX_OK;
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
+ netdev_err(netdev, "No memory left for URBs\n");
+ stats->tx_dropped++;
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ buf = usb_alloc_coherent(dev->udev, sizeof(struct kvaser_msg),
+ GFP_ATOMIC, &urb->transfer_dma);
+ if (!buf) {
+ netdev_err(netdev, "No memory left for USB buffer\n");
+ stats->tx_dropped++;
+ dev_kfree_skb(skb);
+ goto nobufmem;
+ }
+
+ msg = (struct kvaser_msg *)buf;
+ msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_tx_can);
+ msg->u.tx_can.flags = 0;
+ msg->u.tx_can.channel = priv->channel;
+
+ if (cf->can_id & CAN_EFF_FLAG) {
+ msg->id = CMD_TX_EXT_MESSAGE;
+ msg->u.tx_can.msg[0] = (cf->can_id >> 24) & 0x1f;
+ msg->u.tx_can.msg[1] = (cf->can_id >> 18) & 0x3f;
+ msg->u.tx_can.msg[2] = (cf->can_id >> 14) & 0x0f;
+ msg->u.tx_can.msg[3] = (cf->can_id >> 6) & 0xff;
+ msg->u.tx_can.msg[4] = cf->can_id & 0x3f;
+ } else {
+ msg->id = CMD_TX_STD_MESSAGE;
+ msg->u.tx_can.msg[0] = (cf->can_id >> 6) & 0x1f;
+ msg->u.tx_can.msg[1] = cf->can_id & 0x3f;
+ }
+
+ msg->u.tx_can.msg[5] = cf->can_dlc;
+ memcpy(&msg->u.tx_can.msg[6], cf->data, cf->can_dlc);
+
+ if (cf->can_id & CAN_RTR_FLAG)
+ msg->u.tx_can.flags |= MSG_FLAG_REMOTE_FRAME;
+
+ for (i = 0; i < ARRAY_SIZE(priv->tx_contexts); i++) {
+ if (priv->tx_contexts[i].echo_index == MAX_TX_URBS) {
+ context = &priv->tx_contexts[i];
+ break;
+ }
+ }
+
+ if (!context) {
+ netdev_warn(netdev, "cannot find free context\n");
+ ret = NETDEV_TX_BUSY;
+ goto releasebuf;
+ }
+
+ context->priv = priv;
+ context->echo_index = i;
+ context->dlc = cf->can_dlc;
+
+ msg->u.tx_can.tid = context->echo_index;
+
+ usb_fill_bulk_urb(urb, dev->udev,
+ usb_sndbulkpipe(dev->udev,
+ dev->bulk_out->bEndpointAddress),
+ buf, msg->len,
+ kvaser_usb_write_bulk_callback, context);
+ urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ usb_anchor_urb(urb, &priv->tx_submitted);
+
+ can_put_echo_skb(skb, netdev, context->echo_index);
+
+ atomic_inc(&priv->active_tx_urbs);
+
+ if (atomic_read(&priv->active_tx_urbs) >= MAX_TX_URBS)
+ netif_stop_queue(netdev);
+
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (unlikely(err)) {
+ can_free_echo_skb(netdev, context->echo_index);
+
+ atomic_dec(&priv->active_tx_urbs);
+ usb_unanchor_urb(urb);
+
+ stats->tx_dropped++;
+
+ if (err == -ENODEV)
+ netif_device_detach(netdev);
+ else
+ netdev_warn(netdev, "Failed tx_urb %d\n", err);
+
+ goto releasebuf;
+ }
+
+ netdev->trans_start = jiffies;
+
+ usb_free_urb(urb);
+
+ return NETDEV_TX_OK;
+
+releasebuf:
+ usb_free_coherent(dev->udev, sizeof(struct kvaser_msg),
+ buf, urb->transfer_dma);
+nobufmem:
+ usb_free_urb(urb);
+ return ret;
+}
+
+static const struct net_device_ops kvaser_usb_netdev_ops = {
+ .ndo_open = kvaser_usb_open,
+ .ndo_stop = kvaser_usb_close,
+ .ndo_start_xmit = kvaser_usb_start_xmit,
+};
+
+static struct can_bittiming_const kvaser_usb_bittiming_const = {
+ .name = "kvaser_usb",
+ .tseg1_min = KVASER_USB_TSEG1_MIN,
+ .tseg1_max = KVASER_USB_TSEG1_MAX,
+ .tseg2_min = KVASER_USB_TSEG2_MIN,
+ .tseg2_max = KVASER_USB_TSEG2_MAX,
+ .sjw_max = KVASER_USB_SJW_MAX,
+ .brp_min = KVASER_USB_BRP_MIN,
+ .brp_max = KVASER_USB_BRP_MAX,
+ .brp_inc = KVASER_USB_BRP_INC,
+};
+
+static int kvaser_usb_set_bittiming(struct net_device *netdev)
+{
+ struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+ struct can_bittiming *bt = &priv->can.bittiming;
+ struct kvaser_usb *dev = priv->dev;
+ struct kvaser_msg msg = {
+ .id = CMD_SET_BUS_PARAMS,
+ .len = MSG_HEADER_LEN +
+ sizeof(struct kvaser_msg_busparams),
+ .u.busparams.channel = priv->channel,
+ .u.busparams.tid = 0xff,
+ .u.busparams.bitrate = cpu_to_le32(bt->bitrate),
+ .u.busparams.sjw = bt->sjw,
+ .u.busparams.tseg1 = bt->prop_seg + bt->phase_seg1,
+ .u.busparams.tseg2 = bt->phase_seg2,
+ };
+
+ if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
+ msg.u.busparams.no_samp = 3;
+ else
+ msg.u.busparams.no_samp = 1;
+
+ return kvaser_usb_send_msg(dev, &msg);
+}
+
+static int kvaser_usb_set_mode(struct net_device *netdev,
+ enum can_mode mode)
+{
+ struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+ int err;
+
+ switch (mode) {
+ case CAN_MODE_START:
+ err = kvaser_usb_simple_msg_async(priv, CMD_START_CHIP);
+ if (err)
+ return err;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int kvaser_usb_init_one(struct usb_interface *intf,
+ const struct usb_device_id *id, int channel)
+{
+ struct kvaser_usb *dev = usb_get_intfdata(intf);
+ struct net_device *netdev;
+ struct kvaser_usb_net_priv *priv;
+ int i, err;
+
+ netdev = alloc_candev(sizeof(*priv), MAX_TX_URBS);
+ if (!netdev) {
+ dev_err(&intf->dev, "Cannot alloc candev\n");
+ return -ENOMEM;
+ }
+
+ priv = netdev_priv(netdev);
+
+ init_completion(&priv->start_comp);
+ init_completion(&priv->stop_comp);
+
+ init_usb_anchor(&priv->tx_submitted);
+ atomic_set(&priv->active_tx_urbs, 0);
+
+ for (i = 0; i < ARRAY_SIZE(priv->tx_contexts); i++)
+ priv->tx_contexts[i].echo_index = MAX_TX_URBS;
+
+ priv->dev = dev;
+ priv->netdev = netdev;
+ priv->channel = channel;
+
+ priv->can.state = CAN_STATE_STOPPED;
+ priv->can.clock.freq = CAN_USB_CLOCK;
+ priv->can.bittiming_const = &kvaser_usb_bittiming_const;
+ priv->can.do_set_bittiming = kvaser_usb_set_bittiming;
+ priv->can.do_set_mode = kvaser_usb_set_mode;
+ priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
+ if (id->driver_info & KVASER_HAS_SILENT_MODE)
+ priv->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY;
+
+ netdev->flags |= IFF_ECHO;
+
+ netdev->netdev_ops = &kvaser_usb_netdev_ops;
+
+ SET_NETDEV_DEV(netdev, &intf->dev);
+
+ err = register_candev(netdev);
+ if (err) {
+ dev_err(&intf->dev, "Failed to register can device\n");
+ free_candev(netdev);
+ return err;
+ }
+
+ dev->nets[channel] = priv;
+ netdev_dbg(netdev, "device registered\n");
+
+ return 0;
+}
+
+static void kvaser_usb_get_endpoints(const struct usb_interface *intf,
+ struct usb_endpoint_descriptor **in,
+ struct usb_endpoint_descriptor **out)
+{
+ const struct usb_host_interface *iface_desc;
+ struct usb_endpoint_descriptor *endpoint;
+ int i;
+
+ iface_desc = &intf->altsetting[0];
+
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+ endpoint = &iface_desc->endpoint[i].desc;
+
+ if (usb_endpoint_is_bulk_in(endpoint))
+ *in = endpoint;
+
+ if (usb_endpoint_is_bulk_out(endpoint))
+ *out = endpoint;
+ }
+}
+
+static int kvaser_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct kvaser_usb *dev;
+ int err = -ENOMEM;
+ int i;
+
+ dev = devm_kzalloc(&intf->dev, sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ kvaser_usb_get_endpoints(intf, &dev->bulk_in, &dev->bulk_out);
+ if (!dev->bulk_in || !dev->bulk_out) {
+ dev_err(&intf->dev, "Cannot get usb endpoint(s)");
+ return err;
+ }
+
+ dev->udev = interface_to_usbdev(intf);
+
+ init_usb_anchor(&dev->rx_submitted);
+
+ usb_set_intfdata(intf, dev);
+
+ for (i = 0; i < MAX_NET_DEVICES; i++)
+ kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, i);
+
+ err = kvaser_usb_get_software_info(dev);
+ if (err) {
+ dev_err(&intf->dev,
+ "Cannot get software infos, error %d\n", err);
+ return err;
+ }
+
+ err = kvaser_usb_get_card_info(dev);
+ if (err) {
+ dev_err(&intf->dev,
+ "Cannot get card infos, error %d\n", err);
+ return err;
+ }
+
+ dev_dbg(&intf->dev, "Firmware version: %d.%d.%d\n",
+ ((dev->fw_version >> 24) & 0xff),
+ ((dev->fw_version >> 16) & 0xff),
+ (dev->fw_version & 0xffff));
+
+ for (i = 0; i < dev->nchannels; i++)
+ kvaser_usb_init_one(intf, id, i);
+
+ return 0;
+}
+
+static void kvaser_usb_disconnect(struct usb_interface *intf)
+{
+ struct kvaser_usb *dev = usb_get_intfdata(intf);
+ int i;
+
+ usb_set_intfdata(intf, NULL);
+
+ if (!dev)
+ return;
+
+ for (i = 0; i < dev->nchannels; i++) {
+ if (!dev->nets[i])
+ continue;
+
+ unregister_netdev(dev->nets[i]->netdev);
+ free_candev(dev->nets[i]->netdev);
+ }
+
+ kvaser_usb_unlink_all_urbs(dev);
+}
+
+static struct usb_driver kvaser_usb_driver = {
+ .name = "kvaser_usb",
+ .probe = kvaser_usb_probe,
+ .disconnect = kvaser_usb_disconnect,
+ .id_table = kvaser_usb_table
+};
+
+module_usb_driver(kvaser_usb_driver);
+
+MODULE_AUTHOR("Olivier Sobrie <olivier@sobrie.be>");
+MODULE_DESCRIPTION("Can driver for Kvaser CAN/USB devices");
+MODULE_LICENSE("GPL v2");
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH] can: kvaser_usb: Add support for Kvaser CAN/USB devices
From: Olivier Sobrie @ 2012-08-06 5:27 UTC (permalink / raw)
To: Wolfgang Grandegger; +Cc: Marc Kleine-Budde, linux-can, netdev
In-Reply-To: <501EDB0B.5040204@grandegger.com>
On Sun, Aug 05, 2012 at 10:43:55PM +0200, Wolfgang Grandegger wrote:
> On 08/02/2012 01:56 PM, Marc Kleine-Budde wrote:
> > On 08/02/2012 12:53 PM, Olivier Sobrie wrote:
> ...
> >> I actually implemeted it as you said and here is what I observed in
> >> candump output with restart_ms set to 100 ms:
> >>
> >> t0: Short circuit between CAN-H and CAN-L + cansend can1 123#1122
> >> can1 2000008C [8] 00 04 90 00 00 00 00 00 ERRORFRAME
> >> controller-problem{rx-error-warning}
> >> protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
> >> bus-error
> >> can1 2000008C [8] 00 10 90 00 00 00 00 00 ERRORFRAME
> >> controller-problem{rx-error-passive}
> >> protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
> >> bus-error
> >> can1 200000C8 [8] 00 00 90 00 00 00 00 00 ERRORFRAME
> >> protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
> >> bus-off
> >> bus-error
> >> ...
>
> FYI, the option "-td" nicely shows the timing. I assume that the
> "warning->passive->bus-off" sequence repeats because automatic bus-off
> is active via ip option "restart-ms xx ms". What I'm missing is the
> message "restarted-after-bus-off". Maybe it's not listed here...
Indeed it's missing. Please look at the patch I just sent if it is now
correct or not.
>
> >> can1 2000008C [8] 00 04 90 00 00 00 00 00 ERRORFRAME
> >> controller-problem{rx-error-warning}
> >> protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
> >> bus-error
> >> can1 2000008C [8] 00 10 90 00 00 00 00 00 ERRORFRAME
> >> controller-problem{rx-error-passive}
> >> protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
> >> bus-error
> >> can1 200000C8 [8] 00 00 90 00 00 00 00 00 ERRORFRAME
> >> protocol-violation{{tx-recessive-bit-error,error-on-tx}{}}
> >> bus-off
> >> bus-error
> >>
> >> t1: short circuit removed
> >> can1 123 [2] 11 22
> >> can1 20000100 [8] 00 00 00 00 00 00 00 00 ERRORFRAME
> >> restarted-after-bus-of
> >>
> >> The echo coming before the restart looks weird? No?
>
> Yes. It should come later.
Ok I've to change this.
>
> >> Shouldn't we drop the frame once BUF-OFF is reached?
>
> No.
Ok.
>
> > No, I don't think so. But wait for Wolfgang, here's more into error
> > handling then me.
>
> Looking to your code it's not clear to me how you do recovery from
> bus-off (called "restart"). This is usually done via
> do_set_mode(CAN_MODE_START), either manually (restart-ms==0) or
> automatically (restart-ms>0). Could you please explain how the device
> does bus-off recovery? Does the hardware do it automatically? This
> should be suppressed if if restart-ms==0 (as Marc already pointed out).
The hardware automatically recovers from BUS-OFF if it isn't stopped.
In the second version of the patch I just sent, I put the device off if
restart-ms == 0.
Thanks,
--
Olivier
^ permalink raw reply
* Re: [patch 1/1] ixp4xx_eth: fix ptp_ixp46x build failure
From: Richard Cochran @ 2012-08-06 6:23 UTC (permalink / raw)
To: Arnaud Patard; +Cc: netdev, Krzysztof Halasa
In-Reply-To: <20120805203042.509148064@rtp-net.org>
On Sun, Aug 05, 2012 at 10:30:11PM +0200, Arnaud Patard wrote:
> When building with ixp4xx_eth and ptp_ixp46x as module, one is getting the
> following error:
>
> ERROR: "ixp46x_phc_index" [drivers/ptp/ptp_ixp46x.ko] undefined!
>
> This has been introduced by commit 509a7c25729feab353502e1b544c614772a1d49a.
Thanks for patching this.
Acked-by: Richard Cochran <richardcochran@gmail.com>
> Signed-off-by: Arnaud Patard <arnaud.patard@rtp-net.org>
> Index: efika/drivers/net/ethernet/xscale/ixp4xx_eth.c
> ===================================================================
> --- efika.orig/drivers/net/ethernet/xscale/ixp4xx_eth.c 2012-07-29 14:03:12.710197591 +0200
> +++ efika/drivers/net/ethernet/xscale/ixp4xx_eth.c 2012-08-05 11:13:13.188037295 +0200
> @@ -1003,6 +1003,7 @@ static int ixp4xx_nway_reset(struct net_
> }
>
> int ixp46x_phc_index = -1;
> +EXPORT_SYMBOL_GPL(ixp46x_phc_index);
>
> static int ixp4xx_get_ts_info(struct net_device *dev,
> struct ethtool_ts_info *info)
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v2] can: kvaser_usb: Add support for Kvaser CAN/USB devices
From: Oliver Neukum @ 2012-08-06 8:10 UTC (permalink / raw)
To: Olivier Sobrie
Cc: Wolfgang Grandegger, Marc Kleine-Budde, linux-can, linux-usb,
netdev
In-Reply-To: <1344230489-16595-1-git-send-email-olivier@sobrie.be>
On Monday 06 August 2012 07:21:29 Olivier Sobrie wrote:
> This driver provides support for several Kvaser CAN/USB devices.
> Such kind of devices supports up to three can network interfaces.
>
> It has been tested with a Kvaser USB Leaf Light (one network interface)
> connected to a pch_can interface.
> The firmware version of the Kvaser device was 2.5.205.
> +static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
> + struct net_device *netdev)
> +{
> + struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
> + struct kvaser_usb *dev = priv->dev;
> + struct net_device_stats *stats = &netdev->stats;
> + struct can_frame *cf = (struct can_frame *)skb->data;
> + struct kvaser_usb_tx_urb_context *context = NULL;
> + struct urb *urb;
> + void *buf;
> + struct kvaser_msg *msg;
> + int i, err;
> + int ret = NETDEV_TX_OK;
> +
> + if (can_dropped_invalid_skb(netdev, skb))
> + return NETDEV_TX_OK;
> +
> + urb = usb_alloc_urb(0, GFP_ATOMIC);
> + if (!urb) {
> + netdev_err(netdev, "No memory left for URBs\n");
> + stats->tx_dropped++;
> + dev_kfree_skb(skb);
> + return NETDEV_TX_OK;
> + }
> +
> + buf = usb_alloc_coherent(dev->udev, sizeof(struct kvaser_msg),
> + GFP_ATOMIC, &urb->transfer_dma);
usb_alloc_coherent() as a rule only makes sense if you reuse the buffer
and in some cases not even then. Please use a simple kmalloc()
> + if (!buf) {
> + netdev_err(netdev, "No memory left for USB buffer\n");
> + stats->tx_dropped++;
> + dev_kfree_skb(skb);
> + goto nobufmem;
> + }
> +
> + msg = (struct kvaser_msg *)buf;
> + msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_tx_can);
> + msg->u.tx_can.flags = 0;
> + msg->u.tx_can.channel = priv->channel;
> +
> + if (cf->can_id & CAN_EFF_FLAG) {
> + msg->id = CMD_TX_EXT_MESSAGE;
> + msg->u.tx_can.msg[0] = (cf->can_id >> 24) & 0x1f;
> + msg->u.tx_can.msg[1] = (cf->can_id >> 18) & 0x3f;
> + msg->u.tx_can.msg[2] = (cf->can_id >> 14) & 0x0f;
> + msg->u.tx_can.msg[3] = (cf->can_id >> 6) & 0xff;
> + msg->u.tx_can.msg[4] = cf->can_id & 0x3f;
> + } else {
> + msg->id = CMD_TX_STD_MESSAGE;
> + msg->u.tx_can.msg[0] = (cf->can_id >> 6) & 0x1f;
> + msg->u.tx_can.msg[1] = cf->can_id & 0x3f;
> + }
> +
> + msg->u.tx_can.msg[5] = cf->can_dlc;
> + memcpy(&msg->u.tx_can.msg[6], cf->data, cf->can_dlc);
> +
> + if (cf->can_id & CAN_RTR_FLAG)
> + msg->u.tx_can.flags |= MSG_FLAG_REMOTE_FRAME;
> +
> + for (i = 0; i < ARRAY_SIZE(priv->tx_contexts); i++) {
> + if (priv->tx_contexts[i].echo_index == MAX_TX_URBS) {
> + context = &priv->tx_contexts[i];
> + break;
> + }
> + }
> +
> + if (!context) {
> + netdev_warn(netdev, "cannot find free context\n");
> + ret = NETDEV_TX_BUSY;
> + goto releasebuf;
> + }
> +
> + context->priv = priv;
> + context->echo_index = i;
> + context->dlc = cf->can_dlc;
> +
> + msg->u.tx_can.tid = context->echo_index;
> +
> + usb_fill_bulk_urb(urb, dev->udev,
> + usb_sndbulkpipe(dev->udev,
> + dev->bulk_out->bEndpointAddress),
> + buf, msg->len,
> + kvaser_usb_write_bulk_callback, context);
> + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
> + usb_anchor_urb(urb, &priv->tx_submitted);
> +
> + can_put_echo_skb(skb, netdev, context->echo_index);
> +
> + atomic_inc(&priv->active_tx_urbs);
> +
> + if (atomic_read(&priv->active_tx_urbs) >= MAX_TX_URBS)
> + netif_stop_queue(netdev);
> +
> + err = usb_submit_urb(urb, GFP_ATOMIC);
> + if (unlikely(err)) {
> + can_free_echo_skb(netdev, context->echo_index);
> +
> + atomic_dec(&priv->active_tx_urbs);
> + usb_unanchor_urb(urb);
> +
> + stats->tx_dropped++;
> +
> + if (err == -ENODEV)
> + netif_device_detach(netdev);
> + else
> + netdev_warn(netdev, "Failed tx_urb %d\n", err);
> +
> + goto releasebuf;
> + }
> +
> + netdev->trans_start = jiffies;
> +
> + usb_free_urb(urb);
> +
> + return NETDEV_TX_OK;
> +
> +releasebuf:
> + usb_free_coherent(dev->udev, sizeof(struct kvaser_msg),
> + buf, urb->transfer_dma);
> +nobufmem:
> + usb_free_urb(urb);
> + return ret;
> +}
> +static int kvaser_usb_init_one(struct usb_interface *intf,
> + const struct usb_device_id *id, int channel)
> +{
> + struct kvaser_usb *dev = usb_get_intfdata(intf);
> + struct net_device *netdev;
> + struct kvaser_usb_net_priv *priv;
> + int i, err;
> +
> + netdev = alloc_candev(sizeof(*priv), MAX_TX_URBS);
> + if (!netdev) {
> + dev_err(&intf->dev, "Cannot alloc candev\n");
> + return -ENOMEM;
> + }
> +
> + priv = netdev_priv(netdev);
> +
> + init_completion(&priv->start_comp);
> + init_completion(&priv->stop_comp);
> +
> + init_usb_anchor(&priv->tx_submitted);
> + atomic_set(&priv->active_tx_urbs, 0);
> +
> + for (i = 0; i < ARRAY_SIZE(priv->tx_contexts); i++)
> + priv->tx_contexts[i].echo_index = MAX_TX_URBS;
> +
> + priv->dev = dev;
> + priv->netdev = netdev;
> + priv->channel = channel;
> +
> + priv->can.state = CAN_STATE_STOPPED;
> + priv->can.clock.freq = CAN_USB_CLOCK;
> + priv->can.bittiming_const = &kvaser_usb_bittiming_const;
> + priv->can.do_set_bittiming = kvaser_usb_set_bittiming;
> + priv->can.do_set_mode = kvaser_usb_set_mode;
> + priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
> + if (id->driver_info & KVASER_HAS_SILENT_MODE)
> + priv->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY;
> +
> + netdev->flags |= IFF_ECHO;
> +
> + netdev->netdev_ops = &kvaser_usb_netdev_ops;
> +
> + SET_NETDEV_DEV(netdev, &intf->dev);
> +
> + err = register_candev(netdev);
> + if (err) {
> + dev_err(&intf->dev, "Failed to register can device\n");
> + free_candev(netdev);
> + return err;
> + }
> +
Here the device is usable.
> + dev->nets[channel] = priv;
And only know you init this field. Looks like a race condition.
> + netdev_dbg(netdev, "device registered\n");
> +
> + return 0;
> +}
> +
> +static void kvaser_usb_disconnect(struct usb_interface *intf)
> +{
> + struct kvaser_usb *dev = usb_get_intfdata(intf);
> + int i;
> +
> + usb_set_intfdata(intf, NULL);
> +
> + if (!dev)
> + return;
> +
> + for (i = 0; i < dev->nchannels; i++) {
> + if (!dev->nets[i])
> + continue;
> +
> + unregister_netdev(dev->nets[i]->netdev);
> + free_candev(dev->nets[i]->netdev);
> + }
> +
> + kvaser_usb_unlink_all_urbs(dev);
So what happens if an URB completes between freeing the candev
and unlinking and proceeds to push data to upper layers?
Regards
Oliver
^ permalink raw reply
* [PATCH RFC] net: tcp: GRO should be ECN friendly
From: Eric Dumazet @ 2012-08-06 8:34 UTC (permalink / raw)
To: David Miller, Herbert Xu; +Cc: netdev
From: Eric Dumazet <edumazet@google.com>
While doing TCP ECN tests, I discovered GRO was reordering packets if it
receives one packet with CE set, while previous packets in same NAPI run
have ECT(0) for the same flow :
09:25:25.857620 IP (tos 0x2,ECT(0), ttl 64, id 27893, offset 0, flags
[DF], proto TCP (6), length 4396)
172.30.42.19.54550 > 172.30.42.13.44139: Flags [.], seq
233801:238145, ack 1, win 115, options [nop,nop,TS val 3397779 ecr
1990627], length 4344
09:25:25.857626 IP (tos 0x3,CE, ttl 64, id 27892, offset 0, flags [DF],
proto TCP (6), length 1500)
172.30.42.19.54550 > 172.30.42.13.44139: Flags [.], seq
232353:233801, ack 1, win 115, options [nop,nop,TS val 3397779 ecr
1990627], length 1448
09:25:25.857638 IP (tos 0x0, ttl 64, id 34581, offset 0, flags [DF],
proto TCP (6), length 64)
172.30.42.13.44139 > 172.30.42.19.54550: Flags [.], cksum 0xac8f
(incorrect -> 0xca69), ack 232353, win 1271, options [nop,nop,TS val
1990627 ecr 3397779,nop,nop,sack 1 {233801:238145}], length 0
We have two problems here :
1) GRO reorders packets
If NIC gave packet1, then packet2, which happen to be from "different
flows" GRO feeds stack with packet2, then packet1. I have yet to
understand how to solve this problem.
2) GRO is not ECN friendly
Delivering packets out of order makes TCP stack not as fast as it could
be.
In this patch I suggest we make the tos test not part of the 'same_flow'
determination, but part of the 'should flush' logic
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
---
net/ipv4/af_inet.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index fe4582c..6681ccf 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1364,7 +1364,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head,
if (*(u8 *)iph != 0x45)
goto out_unlock;
- if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl)))
+ if (unlikely(ip_fast_csum((u8 *)iph, 5)))
goto out_unlock;
id = ntohl(*(__be32 *)&iph->id);
@@ -1380,7 +1380,6 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head,
iph2 = ip_hdr(p);
if ((iph->protocol ^ iph2->protocol) |
- (iph->tos ^ iph2->tos) |
((__force u32)iph->saddr ^ (__force u32)iph2->saddr) |
((__force u32)iph->daddr ^ (__force u32)iph2->daddr)) {
NAPI_GRO_CB(p)->same_flow = 0;
@@ -1390,6 +1389,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head,
/* All fields must match except length and checksum. */
NAPI_GRO_CB(p)->flush |=
(iph->ttl ^ iph2->ttl) |
+ (iph->tos ^ iph2->tos) |
((u16)(ntohs(iph2->id) + NAPI_GRO_CB(p)->count) ^ id);
NAPI_GRO_CB(p)->flush |= flush;
^ permalink raw reply related
* Re: [PATCH RFC] net: tcp: GRO should be ECN friendly
From: Herbert Xu @ 2012-08-06 9:01 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, netdev
In-Reply-To: <1344242090.9299.1656.camel@edumazet-glaptop>
On Mon, Aug 06, 2012 at 10:34:50AM +0200, Eric Dumazet wrote:
> From: Eric Dumazet <edumazet@google.com>
>
> While doing TCP ECN tests, I discovered GRO was reordering packets if it
> receives one packet with CE set, while previous packets in same NAPI run
> have ECT(0) for the same flow :
>
> 09:25:25.857620 IP (tos 0x2,ECT(0), ttl 64, id 27893, offset 0, flags
> [DF], proto TCP (6), length 4396)
> 172.30.42.19.54550 > 172.30.42.13.44139: Flags [.], seq
> 233801:238145, ack 1, win 115, options [nop,nop,TS val 3397779 ecr
> 1990627], length 4344
>
> 09:25:25.857626 IP (tos 0x3,CE, ttl 64, id 27892, offset 0, flags [DF],
> proto TCP (6), length 1500)
> 172.30.42.19.54550 > 172.30.42.13.44139: Flags [.], seq
> 232353:233801, ack 1, win 115, options [nop,nop,TS val 3397779 ecr
> 1990627], length 1448
>
> 09:25:25.857638 IP (tos 0x0, ttl 64, id 34581, offset 0, flags [DF],
> proto TCP (6), length 64)
> 172.30.42.13.44139 > 172.30.42.19.54550: Flags [.], cksum 0xac8f
> (incorrect -> 0xca69), ack 232353, win 1271, options [nop,nop,TS val
> 1990627 ecr 3397779,nop,nop,sack 1 {233801:238145}], length 0
>
> We have two problems here :
>
> 1) GRO reorders packets
>
> If NIC gave packet1, then packet2, which happen to be from "different
> flows" GRO feeds stack with packet2, then packet1. I have yet to
> understand how to solve this problem.
>
> 2) GRO is not ECN friendly
>
> Delivering packets out of order makes TCP stack not as fast as it could
> be.
>
> In this patch I suggest we make the tos test not part of the 'same_flow'
> determination, but part of the 'should flush' logic
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Good catch, thanks Eric!
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: [PATCH 1/7] netpoll: use GFP_ATOMIC in slave_enable_netpoll() and __netpoll_setup()
From: Cong Wang @ 2012-08-06 9:08 UTC (permalink / raw)
To: Eric Dumazet
Cc: netdev, David S. Miller, Jay Vosburgh, Andy Gospodarek,
Eric Dumazet, Cong Wang, Joe Perches, Neil Horman, linux-kernel
In-Reply-To: <1343988623.9299.932.camel@edumazet-glaptop>
On Fri, 2012-08-03 at 12:10 +0200, Eric Dumazet wrote:
>
> I did this , just take it ;)
Do we have to pass gfp to ->ndo_netpoll_setup() too? It seems no, so far
I don't think we have to do that.
Thanks.
^ permalink raw reply
* Re: skb_warn_bad_offload with kernel 3.5 (maybe gso/bridge related ?)
From: Herbert Xu @ 2012-08-06 9:18 UTC (permalink / raw)
To: Ben Hutchings; +Cc: Eric Dumazet, Yann Dupont, netdev@vger.kernel.org
In-Reply-To: <1344008408.4642.160.camel@deadeye.wl.decadent.org.uk>
On Fri, Aug 03, 2012 at 04:40:08PM +0100, Ben Hutchings wrote:
>
> I think GRO is doing the right thing, and I can't think why we should
> see ip_summed = CHECKSUM_PARTIAL if the skb is forwarded by a bridge. I
If it is was created by GRO then it should always be CHECKSUM_PARTIAL,
even if it came through a bridge.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* если хош подружиться
From: Эльзонька Фильченкова @ 2012-08-06 3:53 UTC (permalink / raw)
To: netdev
http://translate.yandex.net/ya.ru/../tr-url/ya.ru/../en-ru.ru/www.burghleycourt.com/privat.php/ya.ru/../
^ permalink raw reply
* Re: Huge performance degradation for UDP between 2.4.17 and 2.6
From: leroy christophe @ 2012-08-06 9:27 UTC (permalink / raw)
To: Eric Dumazet; +Cc: linux-kernel, netdev
In-Reply-To: <1344155331.9299.1573.camel@edumazet-glaptop>
[-- Attachment #1: Type: text/plain, Size: 1649 bytes --]
Le 05/08/2012 10:28, Eric Dumazet a écrit :
> On Sun, 2012-08-05 at 10:16 +0200, LEROY christophe wrote:
>> Le 02/08/2012 16:13, Eric Dumazet a écrit :
>>> On Thu, 2012-08-02 at 14:27 +0200, leroy christophe wrote:
>>>> Hi
>>>>
>>>> I'm having a big issue with UDP. Using a powerpc board (MPC860).
>>>>
>>>> With our board running kernel 2.4.17, I'm able to send 160000 voice
>>>> packets (UDP, 96 bytes per packet) in 11 seconds.
>>>> With the same board running either Kernel 2.6.35.14 or Kernel 3.4.7, I
>>>> need 55 seconds to send the same amount of packets.
>>>>
>>>>
>>>> Is there anything to tune in order to get same output rate as with
>>>> Kernel 2.4 ?
>>> kernel size is probably too big for your old / slow cpu.
>>>
>>> Maybe you added too many features on your 3.4.7 kernel. (netfilter ?
>>> SLUB debugging ...)
>>>
>>> Its hard to say, 2.4.17 had less features and was faster.
>>>
>> Thanks for your answer.
>> Yes I have netfilter as I need it. However, I tried without it and still
>> need about 37 seconds to send the 160000 packets I was sending in 11
>> seconds with 2.4.17
>>
>> I don't think there is any problem with size of the kernel. I still have
>> plenty of memory available.
>>
> I believe you misunderstood me.
>
> I was referring to cpu caches ( dcache & icache )
>
>> All debugging is turned off, and I'm not using SLUB but SLOB.
>> I have 32Mbytes of RAM. Would SLUB be more performant than SLOB ?
> I never used SLOB I cannot comment
>
> Please provide (on 3.4.7)
>
> cat /proc/cpuinfo
> lsmod
> dmesg
>
Ok, I have recompiled with SLUB.
Find attached cpuinfo, lsmod and dmesg. I do not have any modules loaded.
[-- Attachment #2: lsmod.txt --]
[-- Type: text/plain, Size: 54 bytes --]
Module Size Used by Not tainted
[-- Attachment #3: cpuinfo.txt --]
[-- Type: text/plain, Size: 174 bytes --]
processor : 0
cpu : 8xx
clock : 132.000000MHz
revision : 0.0 (pvr 0050 0000)
bogomips : 16.50
timebase : 8250000
platform : CMPC885
model : MIAE
Memory : 128 MB
[-- Attachment #4: dmesg.txt --]
[-- Type: text/plain, Size: 29225 bytes --]
[ 0.000000] Using CMPC885 machine description
[ 0.000000] Linux version 3.4.7-s3k-3.8.3+-svn2796 (root@localhost.localdomain) (gcc version 4.4.4 (GCC) ) #19 PREEMPT Sun Aug 5 06:43:31 CEST 2012
[ 0.000000] Top of RAM: 0x8000000, Total RAM: 0x8000000
[ 0.000000] Memory hole size: 0MB
[ 0.000000] Zone PFN ranges:
[ 0.000000] DMA 0x00000000 -> 0x00008000
[ 0.000000] Normal empty
[ 0.000000] Movable zone start PFN for each node
[ 0.000000] Early memory PFN ranges
[ 0.000000] 0: 0x00000000 -> 0x00008000
[ 0.000000] On node 0 totalpages: 32768
[ 0.000000] free_area_init_node: node 0, pgdat c03f4be8, node_mem_map c0433000
[ 0.000000] DMA zone: 256 pages used for memmap
[ 0.000000] DMA zone: 0 pages reserved
[ 0.000000] DMA zone: 32512 pages, LIFO batch:7
[ 0.000000] MMU: Allocated 72 bytes of context maps for 16 contexts
[ 0.000000] pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
[ 0.000000] pcpu-alloc: [0] 0
[ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 32512
[ 0.000000] Kernel command line: console=ttyCPM0,115200N8 ip=172.25.231.39:172.25.231.59::255.0.0.0:miae:eth0:off
[ 0.000000] PID hash table entries: 512 (order: -1, 2048 bytes)
[ 0.000000] Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
[ 0.000000] Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
[ 0.000000] Memory: 125432k/131072k available (3972k kernel code, 5640k reserved, 140k data, 178k bss, 488k init)
[ 0.000000] Kernel virtual memory layout:
[ 0.000000] * 0xfffdf000..0xfffff000 : fixmap
[ 0.000000] * 0xfde00000..0xfe000000 : consistent mem
[ 0.000000] * 0xfddf6000..0xfde00000 : early ioremap
[ 0.000000] * 0xc9000000..0xfddf6000 : vmalloc & ioremap
[ 0.000000] SLUB: Genslabs=14, HWalign=16, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[ 0.000000] NR_IRQS:512 nr_irqs:512 16
[ 0.000000] Decrementer Frequency = 0x7de290
[ 0.000000] time_init: decrementer frequency = 8.250000 MHz
[ 0.000000] time_init: processor frequency = 132.000000 MHz
[ 0.000000] clocksource: timebase mult[79364d93] shift[24] registered
[ 0.000000] clockevent: decrementer mult[21cac08] shift[32] cpu[0]
[ 0.000000] console [ttyCPM0] enabled
[ 0.144102] pid_max: default: 32768 minimum: 301
[ 0.149489] Mount-cache hash table entries: 512
[ 0.175086] devtmpfs: initialized
[ 0.178575] device: 'platform': device_add
[ 0.179079] bus: 'platform': registered
[ 0.179451] bus: 'cpu': registered
[ 0.179551] device: 'cpu': device_add
[ 0.181718] NET: Registered protocol family 16
[ 0.186374] device class 'bdi': registering
[ 0.188054] device class 'gpio': registering
[ 0.189423] device class 'tty': registering
[ 0.191855] bus: 'spi': registered
[ 0.191932] device class 'spi_master': registering
[ 0.193842] gpiochip_find_base: found new base at 1008
[ 0.193974] device: 'gpiochip1008': device_add
[ 0.195387] gpiochip_add: registered GPIOs 1008 to 1023 on device: /soc@ff000000/cpm@9c0/gpio-controller@950
[ 0.205830] gpiochip_find_base: found new base at 976
[ 0.205962] device: 'gpiochip976': device_add
[ 0.207142] gpiochip_add: registered GPIOs 976 to 1007 on device: /soc@ff000000/cpm@9c0/gpio-controller@ab8
[ 0.221332] gpiochip_find_base: found new base at 960
[ 0.221466] device: 'gpiochip960': device_add
[ 0.222639] gpiochip_add: registered GPIOs 960 to 975 on device: /soc@ff000000/cpm@9c0/gpio-controller@960
[ 0.232869] gpiochip_find_base: found new base at 944
[ 0.232999] device: 'gpiochip944': device_add
[ 0.234181] gpiochip_add: registered GPIOs 944 to 959 on device: /soc@ff000000/cpm@9c0/gpio-controller@970
[ 0.244378] gpiochip_find_base: found new base at 912
[ 0.244508] device: 'gpiochip912': device_add
[ 0.245744] gpiochip_add: registered GPIOs 912 to 943 on device: /soc@ff000000/cpm@9c0/gpio-controller@ac8
[ 0.255606] bus: 'platform': add driver mpc8xxx_wdt
[ 0.256898] device: 'cpu0': device_add
[ 0.257044] bus: 'cpu': add device cpu0
[ 0.330377] device: 'default': device_add
[ 0.332266] device class 'misc': registering
[ 0.333402] device class 'mdio_bus': registering
[ 0.336232] bus: 'mdio_bus': registered
[ 0.336318] bus: 'mdio_bus': add driver Generic PHY
[ 0.337607] device class 'hwmon': registering
[ 0.338929] device class 'leds': registering
[ 0.340236] device class 'net': registering
[ 0.341620] device: 'lo': device_add
[ 0.345289] Switching to clocksource timebase
[ 0.350674] FS-Cache: Loaded
[ 0.353317] device class 'mem': registering
[ 0.354397] device: 'mem': device_add
[ 0.356110] device: 'kmem': device_add
[ 0.357737] device: 'null': device_add
[ 0.359373] device: 'zero': device_add
[ 0.361445] device: 'full': device_add
[ 0.363081] device: 'random': device_add
[ 0.364738] device: 'urandom': device_add
[ 0.366391] device: 'kmsg': device_add
[ 0.368042] device: 'tty': device_add
[ 0.369797] device: 'console': device_add
[ 0.371798] device class 'firmware': registering
[ 0.373031] device class 'thermal': registering
[ 0.375174] NET: Registered protocol family 2
[ 0.380793] IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.389420] TCP established hash table entries: 4096 (order: 3, 32768 bytes)
[ 0.397191] TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
[ 0.403931] TCP: Hash tables configured (established 4096 bind 4096)
[ 0.410141] TCP: reno registered
[ 0.413212] UDP hash table entries: 256 (order: 0, 4096 bytes)
[ 0.419057] UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
[ 0.426463] NET: Registered protocol family 1
[ 0.432619] RPC: Registered named UNIX socket transport module.
[ 0.438291] RPC: Registered udp transport module.
[ 0.443459] RPC: Registered tcp transport module.
[ 0.447931] RPC: Registered tcp NFSv4.1 backchannel transport module.
[ 0.493551] Registering platform device 'rtc-generic'. Parent at platform
[ 0.493649] device: 'rtc-generic': device_add
[ 0.493788] bus: 'platform': add device rtc-generic
[ 0.494880] MIAE declare_of_platform_devices()
[ 0.499330] device: 'ff000100.localbus': device_add
[ 0.499487] bus: 'platform': add device ff000100.localbus
[ 0.501396] device: '40000000.flash': device_add
[ 0.501549] bus: 'platform': add device 40000000.flash
[ 0.502899] device: 'c0000000.nand': device_add
[ 0.503051] bus: 'platform': add device c0000000.nand
[ 0.504625] device: 'c8000000.cpld-cmpc': device_add
[ 0.504781] bus: 'platform': add device c8000000.cpld-cmpc
[ 0.506303] device: 'c8000000.cpld-mpc': device_add
[ 0.506464] bus: 'platform': add device c8000000.cpld-mpc
[ 0.507966] device: 'd0000000.fpga-m': device_add
[ 0.508126] bus: 'platform': add device d0000000.fpga-m
[ 0.510502] device: 'd2000000.e1': device_add
[ 0.510654] bus: 'platform': add device d2000000.e1
[ 0.512758] device: 'e0000000.dpram': device_add
[ 0.512913] bus: 'platform': add device e0000000.dpram
[ 0.514469] device: 'f0000000.dsp': device_add
[ 0.514620] bus: 'platform': add device f0000000.dsp
[ 0.516116] device: 'd0000042.GPIO': device_add
[ 0.516270] bus: 'platform': add device d0000042.GPIO
[ 0.517683] device: 'soc.0': device_add
[ 0.517834] bus: 'platform': add device soc.0
[ 0.519352] device: 'ff000000.watchdog': device_add
[ 0.519510] bus: 'platform': add device ff000000.watchdog
[ 0.521164] bus: 'platform': driver_probe_device: matched device ff000000.watchdog with driver mpc8xxx_wdt
[ 0.521279] bus: 'platform': really_probe: probing driver mpc8xxx_wdt with device ff000000.watchdog
[ 0.521572] mpc8xxx_wdt: could not be enabled in software
[ 0.526748] mpc8xxx_wdt: probe of ff000000.watchdog failed with error -38
[ 0.534033] device: 'ff000e00.mdio': device_add
[ 0.534183] bus: 'platform': add device ff000e00.mdio
[ 0.536047] device: 'ff000e00.ethernet': device_add
[ 0.536201] bus: 'platform': add device ff000e00.ethernet
[ 0.538220] device: 'ff001e00.ethernet': device_add
[ 0.538376] bus: 'platform': add device ff001e00.ethernet
[ 0.540262] device: 'ff000000.pic': device_add
[ 0.540413] bus: 'platform': add device ff000000.pic
[ 0.542495] device: 'ff000200.sit': device_add
[ 0.542646] bus: 'platform': add device ff000200.sit
[ 0.544347] device: 'ff0009c0.cpm': device_add
[ 0.544503] bus: 'platform': add device ff0009c0.cpm
[ 0.545955] device: 'muram.1': device_add
[ 0.546105] bus: 'platform': add device muram.1
[ 0.547601] device: 'ff0009f0.brg': device_add
[ 0.547754] bus: 'platform': add device ff0009f0.brg
[ 0.549874] device: 'ff000930.pic': device_add
[ 0.550348] bus: 'platform': add device ff000930.pic
[ 0.551936] device: 'ff000950.gpio-controller': device_add
[ 0.552097] bus: 'platform': add device ff000950.gpio-controller
[ 0.553636] device: 'ff000ab8.gpio-controller': device_add
[ 0.553798] bus: 'platform': add device ff000ab8.gpio-controller
[ 0.556578] device: 'ff000960.gpio-controller': device_add
[ 0.556743] bus: 'platform': add device ff000960.gpio-controller
[ 0.558297] device: 'ff000970.gpio-controller': device_add
[ 0.558458] bus: 'platform': add device ff000970.gpio-controller
[ 0.560395] device: 'ff000ac8.gpio-controller': device_add
[ 0.560556] bus: 'platform': add device ff000ac8.gpio-controller
[ 0.562169] device: 'ff0009c0.tsa': device_add
[ 0.562320] bus: 'platform': add device ff0009c0.tsa
[ 0.564072] device: 'ff000a80.serial': device_add
[ 0.564230] bus: 'platform': add device ff000a80.serial
[ 0.566300] device: 'ff000a20.serial': device_add
[ 0.566458] bus: 'platform': add device ff000a20.serial
[ 0.568565] device: 'ff000a40.tdm': device_add
[ 0.568724] bus: 'platform': add device ff000a40.tdm
[ 0.571169] device: 'ff000a60.tdm': device_add
[ 0.571328] bus: 'platform': add device ff000a60.tdm
[ 0.573531] device: 'ff000a90.tdm_smc': device_add
[ 0.573689] bus: 'platform': add device ff000a90.tdm_smc
[ 0.575816] device: 'ff000a80.spi': device_add
[ 0.575977] bus: 'platform': add device ff000a80.spi
[ 0.577542] device: 'ff00a980.dummy_pio': device_add
[ 0.577704] bus: 'platform': add device ff00a980.dummy_pio
[ 0.579225] device: 'ff000002.gpio-controller': device_add
[ 0.579394] bus: 'platform': add device ff000002.gpio-controller
[ 0.581054] CTS2 and CTS3 temporarily deactivated (FEV170)
[ 0.586510] gpiochip_find_base: found new base at 896
[ 0.586636] device: 'gpiochip896': device_add
[ 0.588093] gpiochip_add: registered GPIOs 896 to 911 on device: /localbus@ff000100/fpga-m@4,0000000/gpio-controller@00
[ 0.599034] gpiochip_find_base: found new base at 880
[ 0.599165] device: 'gpiochip880': device_add
[ 0.600516] gpiochip_add: registered GPIOs 880 to 895 on device: /localbus@ff000100/fpga-m@4,0000000/gpio-controller@02
[ 0.611617] gpiochip_find_base: found new base at 864
[ 0.611807] device: 'gpiochip864': device_add
[ 0.613003] gpiochip_add: registered GPIOs 864 to 879 on device: /localbus@ff000100/fpga-m@4,0000000/gpio-controller@04
[ 0.624149] gpiochip_find_base: found new base at 848
[ 0.624279] device: 'gpiochip848': device_add
[ 0.625456] gpiochip_add: registered GPIOs 848 to 863 on device: /localbus@ff000100/fpga-m@4,0000000/gpio-controller@10
[ 0.636625] gpiochip_find_base: found new base at 832
[ 0.636752] device: 'gpiochip832': device_add
[ 0.637993] gpiochip_add: registered GPIOs 832 to 847 on device: /localbus@ff000100/fpga-m@4,0000000/gpio-controller@20
[ 0.649112] gpiochip_find_base: found new base at 816
[ 0.649241] device: 'gpiochip816': device_add
[ 0.650637] gpiochip_add: registered GPIOs 816 to 831 on device: /localbus@ff000100/fpga-m@4,0000000/gpio-controller@22
[ 0.661713] gpiochip_find_base: found new base at 800
[ 0.661840] device: 'gpiochip800': device_add
[ 0.663101] gpiochip_add: registered GPIOs 800 to 815 on device: /localbus@ff000100/fpga-m@4,0000000/gpio-controller@24
[ 0.674239] gpiochip_find_base: found new base at 784
[ 0.674369] device: 'gpiochip784': device_add
[ 0.675551] gpiochip_add: registered GPIOs 784 to 799 on device: /localbus@ff000100/fpga-m@4,0000000/gpio-controller@26
[ 0.686714] gpiochip_find_base: found new base at 768
[ 0.686844] device: 'gpiochip768': device_add
[ 0.688026] gpiochip_add: registered GPIOs 768 to 783 on device: /localbus@ff000100/fpga-m@4,0000000/gpio-controller@28
[ 0.699202] gpiochip_find_base: found new base at 752
[ 0.699332] device: 'gpiochip752': device_add
[ 0.700721] gpiochip_add: registered GPIOs 752 to 767 on device: /localbus@ff000100/fpga-m@4,0000000/gpio-controller@2A
[ 0.711803] gpiochip_find_base: found new base at 736
[ 0.711931] device: 'gpiochip736': device_add
[ 0.713252] gpiochip_add: registered GPIOs 736 to 751 on device: /localbus@ff000100/fpga-m@4,0000000/gpio-controller@2C
[ 0.728958] gpiochip_find_base: found new base at 720
[ 0.729088] device: 'gpiochip720': device_add
[ 0.730524] gpiochip_add: registered GPIOs 720 to 735 on device: /localbus@ff000100/fpga-m@4,0000000/gpio-controller@30
[ 0.741588] gpiochip_find_base: found new base at 704
[ 0.741718] device: 'gpiochip704': device_add
[ 0.742907] gpiochip_add: registered GPIOs 704 to 719 on device: /localbus@ff000100/fpga-m@4,0000000/gpio-controller@32
[ 0.754062] gpiochip_find_base: found new base at 688
[ 0.754192] device: 'gpiochip688': device_add
[ 0.755386] gpiochip_add: registered GPIOs 688 to 703 on device: /localbus@ff000100/fpga-m@4,0000000/gpio-controller@40
[ 0.768695] gpiochip_find_base: found new base at 672
[ 0.768823] device: 'gpiochip672': device_add
[ 0.770226] gpiochip_add: registered GPIOs 672 to 687 on device: /localbus@ff000100/fpga-m@4,0000000/gpio-controller@42
[ 0.784715] gpiochip_find_base: found new base at 656
[ 0.784844] device: 'gpiochip656': device_add
[ 0.786031] gpiochip_add: registered GPIOs 656 to 671 on device: /localbus@ff000100/fpga-m@4,0000000/gpio-controller@44
[ 0.797136] gpiochip_find_base: found new base at 640
[ 0.797265] device: 'gpiochip640': device_add
[ 0.798449] gpiochip_add: registered GPIOs 640 to 655 on device: /localbus@ff000100/fpga-m@4,0000000/gpio-controller@50
[ 0.809624] gpiochip_find_base: found new base at 624
[ 0.809754] device: 'gpiochip624': device_add
[ 0.811165] gpiochip_add: registered GPIOs 624 to 639 on device: /localbus@ff000100/fpga-m@4,0000000/gpio-controller@52
[ 0.822229] gpiochip_find_base: found new base at 608
[ 0.822359] device: 'gpiochip608': device_add
[ 0.823636] gpiochip_add: registered GPIOs 608 to 623 on device: /localbus@ff000100/fpga-m@4,0000000/gpio-controller@54
[ 0.834743] Number of GPIO found = 0
[ 0.839274] bus: 'clocksource': registered
[ 0.839398] device: 'clocksource': device_add
[ 0.839573] device: 'clocksource0': device_add
[ 0.839708] bus: 'clocksource': add device clocksource0
[ 0.841307] bus: 'platform': add driver alarmtimer
[ 0.842717] Registering platform device 'alarmtimer'. Parent at platform
[ 0.842816] device: 'alarmtimer': device_add
[ 0.842957] bus: 'platform': add device alarmtimer
[ 0.844218] bus: 'platform': driver_probe_device: matched device alarmtimer with driver alarmtimer
[ 0.844329] bus: 'platform': really_probe: probing driver alarmtimer with device alarmtimer
[ 0.844484] driver: 'alarmtimer': driver_bound: bound to device 'alarmtimer'
[ 0.844581] bus: 'platform': really_probe: bound device alarmtimer to driver alarmtimer
[ 0.946411] msgmni has been set to 244
[ 0.952742] device: 'ptyp0': device_add
[ 0.954595] device: 'ptyp1': device_add
[ 0.956281] device: 'ptyp2': device_add
[ 0.957965] device: 'ptyp3': device_add
[ 0.959777] device: 'ptyp4': device_add
[ 0.961841] device: 'ttyp0': device_add
[ 0.963542] device: 'ttyp1': device_add
[ 0.965243] device: 'ttyp2': device_add
[ 0.967064] device: 'ttyp3': device_add
[ 0.968758] device: 'ttyp4': device_add
[ 0.970845] device: 'ptmx': device_add
[ 0.972612] bus: 'platform': add driver cpm_uart
[ 0.973307] bus: 'platform': driver_probe_device: matched device ff000a80.serial with driver cpm_uart
[ 0.973416] bus: 'platform': really_probe: probing driver cpm_uart with device ff000a80.serial
[ 0.973925] ff000a80.serial: ttyCPM0 at MMIO 0xc9048a80 (irq = 20) is a CPM UART
[ 0.981598] device: 'ttyCPM0': device_add
[ 0.983183] driver: 'ff000a80.serial': driver_bound: bound to device 'cpm_uart'
[ 0.983290] bus: 'platform': really_probe: bound device ff000a80.serial to driver cpm_uart
[ 0.983421] bus: 'platform': driver_probe_device: matched device ff000a20.serial with driver cpm_uart
[ 0.983520] bus: 'platform': really_probe: probing driver cpm_uart with device ff000a20.serial
[ 0.984208] ff000a20.serial: ttyCPM1 at MMIO 0xc904ca20 (irq = 39) is a CPM UART
[ 0.991793] device: 'ttyCPM1': device_add
[ 0.993465] driver: 'ff000a20.serial': driver_bound: bound to device 'cpm_uart'
[ 0.993572] bus: 'platform': really_probe: bound device ff000a20.serial to driver cpm_uart
[ 0.995444] Generic RTC Driver v1.07
[ 0.998755] device: 'rtc': device_add
[ 1.000927] bus: 'spi': add driver at25
[ 1.002200] device class 'mtd': registering
[ 1.003448] device: 'mtd-unmap': device_add
[ 1.004812] device: 'mtd-romap': device_add
[ 1.006189] device: 'mtd-rwmap': device_add
[ 1.007718] bus: 'platform': add driver of-flash
[ 1.007938] bus: 'platform': driver_probe_device: matched device 40000000.flash with driver of-flash
[ 1.008046] bus: 'platform': really_probe: probing driver of-flash with device 40000000.flash
[ 1.009123] 40000000.flash: Found 1 x16 devices at 0x0 in 16-bit bank. Manufacturer ID 0x000020 Chip ID 0x002257
[ 1.019662] Amd/Fujitsu Extended Query Table at 0x0040
[ 1.024787] Amd/Fujitsu Extended Query version 1.1.
[ 1.029546] number of CFI chips: 1
[ 1.034403] 4 ofpart partitions found on MTD device 40000000.flash
[ 1.040614] Creating 4 MTD partitions on "40000000.flash":
[ 1.045835] 0x000000000000-0x000000050000 : "boot"
[ 1.050810] device: 'mtd0': device_add
[ 1.052636] device: 'mtd0ro': device_add
[ 1.054362] 0x000000050000-0x000000060000 : "env"
[ 1.058855] device: 'mtd1': device_add
[ 1.060941] device: 'mtd1ro': device_add
[ 1.062670] 0x000000060000-0x000000090000 : "blob"
[ 1.067283] device: 'mtd2': device_add
[ 1.069226] device: 'mtd2ro': device_add
[ 1.071290] 0x000000090000-0x000000400000 : "kernel"
[ 1.076064] device: 'mtd3': device_add
[ 1.077916] device: 'mtd3ro': device_add
[ 1.079619] driver: '40000000.flash': driver_bound: bound to device 'of-flash'
[ 1.079728] bus: 'platform': really_probe: bound device 40000000.flash to driver of-flash
[ 1.081833] bus: 'platform': add driver cmpc885-nand
[ 1.082059] bus: 'platform': driver_probe_device: matched device c0000000.nand with driver cmpc885-nand
[ 1.082169] bus: 'platform': really_probe: probing driver cmpc885-nand with device c0000000.nand
[ 1.083191] NAND device: Manufacturer ID: 0xad, Chip ID: 0x76 (Hynix NAND 64MiB 3,3V 8-bit)
[ 1.091734] Scanning device for bad blocks
[ 1.431745] device: 'mtd4': device_add
[ 1.433479] device: 'mtd4ro': device_add
[ 1.435182] driver: 'c0000000.nand': driver_bound: bound to device 'cmpc885-nand'
[ 1.435292] bus: 'platform': really_probe: bound device c0000000.nand to driver cmpc885-nand
[ 1.436826] bus: 'platform': add driver gen_nand
[ 1.438182] device class 'ubi': registering
[ 1.439458] device: 'ubi_ctrl': device_add
[ 1.441662] bus: 'platform': add driver fsl_spi
[ 1.442087] bus: 'platform': driver_probe_device: matched device ff000a80.spi with driver fsl_spi
[ 1.442194] bus: 'platform': really_probe: probing driver fsl_spi with device ff000a80.spi
[ 1.445117] device: 'spi32766': device_add
[ 1.446456] fsl_spi ff000a80.spi: master is unqueued, this is deprecated
[ 1.454691] device: 'spi32766.0': device_add
[ 1.454853] bus: 'spi': add device spi32766.0
[ 1.457526] device: 'spi32766.1': device_add
[ 1.457689] bus: 'spi': add device spi32766.1
[ 1.460862] device: 'spi32766.2': device_add
[ 1.461025] bus: 'spi': add device spi32766.2
[ 1.463718] device: 'spi32766.3': device_add
[ 1.463882] bus: 'spi': add device spi32766.3
[ 1.465083] bus: 'spi': driver_probe_device: matched device spi32766.3 with driver at25
[ 1.465188] bus: 'spi': really_probe: probing driver at25 with device spi32766.3
[ 1.465956] at25 spi32766.3: 1 KByte at25080 eeprom, pagesize 32
[ 1.472245] driver: 'spi32766.3': driver_bound: bound to device 'at25'
[ 1.472349] bus: 'spi': really_probe: bound device spi32766.3 to driver at25
[ 1.473868] device: 'spi32766.4': device_add
[ 1.474033] bus: 'spi': add device spi32766.4
[ 1.476755] device: 'spi32766.5': device_add
[ 1.476919] bus: 'spi': add device spi32766.5
[ 1.479626] device: 'spi32766.6': device_add
[ 1.479791] bus: 'spi': add device spi32766.6
[ 1.481491] bus: 'spi': driver_probe_device: matched device spi32766.6 with driver at25
[ 1.481596] bus: 'spi': really_probe: probing driver at25 with device spi32766.6
[ 1.482316] at25 spi32766.6: 1 KByte at25080 eeprom, pagesize 32
[ 1.488067] driver: 'spi32766.6': driver_bound: bound to device 'at25'
[ 1.488158] bus: 'spi': really_probe: bound device spi32766.6 to driver at25
[ 1.488294] fsl_spi ff000a80.spi: at 0xc9056a80 (irq = 43), CPM1 mode
[ 1.494846] driver: 'ff000a80.spi': driver_bound: bound to device 'fsl_spi'
[ 1.494953] bus: 'platform': really_probe: bound device ff000a80.spi to driver fsl_spi
[ 1.496083] bonding: Ethernet Channel Bonding Driver: v3.7.1 (April 27, 2011)
[ 1.504285] device: 'bond0': device_add
[ 1.528580] bus: 'mdio_bus': add driver LXT970
[ 1.530367] bus: 'mdio_bus': add driver LXT971
[ 1.531640] bus: 'mdio_bus': add driver LXT973
[ 1.532923] bus: 'mdio_bus': add driver Micrel KS8001 or KS8721
[ 1.534223] bus: 'mdio_bus': add driver Micrel KSZ9021 Gigabit PHY
[ 1.535526] bus: 'mdio_bus': add driver Micrel KS8737
[ 1.536813] bus: 'mdio_bus': add driver Micrel KS8041
[ 1.538118] bus: 'mdio_bus': add driver Micrel KS8051
[ 1.539420] bus: 'platform': add driver fs_enet
[ 1.539726] bus: 'platform': driver_probe_device: matched device ff000e00.ethernet with driver fs_enet
[ 1.539836] bus: 'platform': really_probe: probing driver fs_enet with device ff000e00.ethernet
[ 1.540997] device: 'eth0': device_add
[ 1.545222] eth0: fs_enet: 08:00:51:20:44:23
[ 1.549360] driver: 'ff000e00.ethernet': driver_bound: bound to device 'fs_enet'
[ 1.549463] bus: 'platform': really_probe: bound device ff000e00.ethernet to driver fs_enet
[ 1.549589] bus: 'platform': driver_probe_device: matched device ff001e00.ethernet with driver fs_enet
[ 1.549691] bus: 'platform': really_probe: probing driver fs_enet with device ff001e00.ethernet
[ 1.550767] PHY-disable = isolate
[ 1.554310] device: 'eth1': device_add
[ 1.558272] eth1: fs_enet: 08:00:51:20:44:24
[ 1.562840] driver: 'ff001e00.ethernet': driver_bound: bound to device 'fs_enet'
[ 1.562949] bus: 'platform': really_probe: bound device ff001e00.ethernet to driver fs_enet
[ 1.564230] bus: 'platform': add driver fsl-fec-mdio
[ 1.564521] bus: 'platform': driver_probe_device: matched device ff000e00.mdio with driver fsl-fec-mdio
[ 1.564631] bus: 'platform': really_probe: probing driver fsl-fec-mdio with device ff000e00.mdio
[ 1.564972] device: 'ff000e00': device_add
[ 1.566333] FEC MII Bus: probed
[ 1.571618] device: 'ff000e00:01': device_add
[ 1.571785] bus: 'mdio_bus': add device ff000e00:01
[ 1.572929] bus: 'mdio_bus': driver_probe_device: matched device ff000e00:01 with driver Micrel KS8041
[ 1.573041] bus: 'mdio_bus': really_probe: probing driver Micrel KS8041 with device ff000e00:01
[ 1.573215] driver: 'ff000e00:01': driver_bound: bound to device 'Micrel KS8041'
[ 1.573317] bus: 'mdio_bus': really_probe: bound device ff000e00:01 to driver Micrel KS8041
[ 1.575186] device: 'ff000e00:02': device_add
[ 1.575354] bus: 'mdio_bus': add device ff000e00:02
[ 1.576498] bus: 'mdio_bus': driver_probe_device: matched device ff000e00:02 with driver Micrel KS8041
[ 1.576610] bus: 'mdio_bus': really_probe: probing driver Micrel KS8041 with device ff000e00:02
[ 1.576784] driver: 'ff000e00:02': driver_bound: bound to device 'Micrel KS8041'
[ 1.576886] bus: 'mdio_bus': really_probe: bound device ff000e00:02 to driver Micrel KS8041
[ 1.578760] device: 'ff000e00:03': device_add
[ 1.578929] bus: 'mdio_bus': add device ff000e00:03
[ 1.580484] bus: 'mdio_bus': driver_probe_device: matched device ff000e00:03 with driver Micrel KS8041
[ 1.580597] bus: 'mdio_bus': really_probe: probing driver Micrel KS8041 with device ff000e00:03
[ 1.580771] driver: 'ff000e00:03': driver_bound: bound to device 'Micrel KS8041'
[ 1.580872] bus: 'mdio_bus': really_probe: bound device ff000e00:03 to driver Micrel KS8041
[ 1.580990] driver: 'ff000e00.mdio': driver_bound: bound to device 'fsl-fec-mdio'
[ 1.581084] bus: 'platform': really_probe: bound device ff000e00.mdio to driver fsl-fec-mdio
[ 1.582511] bus: 'spi': add driver lm70
[ 1.582694] bus: 'spi': driver_probe_device: matched device spi32766.1 with driver lm70
[ 1.582795] bus: 'spi': really_probe: probing driver lm70 with device spi32766.1
[ 1.583147] device: 'hwmon0': device_add
[ 1.584544] driver: 'spi32766.1': driver_bound: bound to device 'lm70'
[ 1.584650] bus: 'spi': really_probe: bound device spi32766.1 to driver lm70
[ 1.584762] bus: 'spi': driver_probe_device: matched device spi32766.5 with driver lm70
[ 1.584852] bus: 'spi': really_probe: probing driver lm70 with device spi32766.5
[ 1.585124] device: 'hwmon1': device_add
[ 1.586574] driver: 'spi32766.5': driver_bound: bound to device 'lm70'
[ 1.586679] bus: 'spi': really_probe: bound device spi32766.5 to driver lm70
[ 1.587942] bus: 'platform': add driver talitos
[ 1.589613] nf_conntrack version 0.5.0 (1959 buckets, 7836 max)
[ 1.601203] ip_tables: (C) 2000-2006 Netfilter Core Team
[ 1.606999] TCP: cubic registered
[ 1.610492] NET: Registered protocol family 17
[ 1.614758] 8021q: 802.1Q VLAN Support v1.8
[ 1.619247] device: 'cpu_dma_latency': device_add
[ 1.621013] device: 'network_latency': device_add
[ 1.622734] device: 'network_throughput': device_add
[ 1.638486] Freeing unused kernel memory: 488k freed
[ 1.745200] UBI: attaching mtd4 to ubi0
[ 1.752891] UBI: physical eraseblock size: 16384 bytes (16 KiB)
[ 1.758719] UBI: logical eraseblock size: 15872 bytes
[ 1.764104] UBI: smallest flash I/O unit: 512
[ 1.768529] UBI: sub-page size: 256
[ 1.773225] UBI: VID header offset: 256 (aligned 256)
[ 1.778856] UBI: data offset: 512
[ 2.707154] UBI: max. sequence number: 3567
[ 2.755007] device: 'ubi0': device_add
[ 2.756808] device: 'ubi0_0': device_add
[ 2.759183] UBI: attached mtd4 to ubi0
[ 2.763020] UBI: MTD device name: "cmpc885-nand"
[ 2.768298] UBI: MTD device size: 64 MiB
[ 2.773283] UBI: number of good PEBs: 4096
[ 2.777761] UBI: number of bad PEBs: 0
[ 2.782282] UBI: number of corrupted PEBs: 0
[ 2.786540] UBI: max. allowed volumes: 92
[ 2.791145] UBI: wear-leveling threshold: 4096
[ 2.795662] UBI: number of internal volumes: 1
[ 2.800180] UBI: number of user volumes: 1
[ 2.804440] UBI: available PEBs: 0
[ 2.808829] UBI: total number of reserved PEBs: 4096
[ 2.813866] UBI: number of PEBs reserved for bad PEB handling: 40
[ 2.819763] UBI: max/mean erase counter: 13/8
[ 2.824195] UBI: image sequence number: 1870984234
[ 2.828961] UBI: background thread "ubi_bgt0d" started, PID 356
[ 2.851633] device: 'ubifs_0_0': device_add
[ 2.913328] UBIFS: mounted UBI device 0, volume 0, name "rootfs"
[ 2.919092] UBIFS: file system size: 63837184 bytes (62341 KiB, 60 MiB, 4022 LEBs)
[ 2.926908] UBIFS: journal size: 8428032 bytes (8230 KiB, 8 MiB, 531 LEBs)
[ 2.934191] UBIFS: media format: w4/r0 (latest is w4/r0)
[ 2.939814] UBIFS: default compressor: lzo
[ 2.943991] UBIFS: reserved for root: 0 bytes (0 KiB)
^ permalink raw reply
* Re: [PATCH 1/7] netpoll: use GFP_ATOMIC in slave_enable_netpoll() and __netpoll_setup()
From: Eric Dumazet @ 2012-08-06 9:44 UTC (permalink / raw)
To: Cong Wang
Cc: netdev, David S. Miller, Jay Vosburgh, Andy Gospodarek,
Eric Dumazet, Cong Wang, Joe Perches, Neil Horman, linux-kernel
In-Reply-To: <1344244118.14728.28.camel@cr0>
On Mon, 2012-08-06 at 17:08 +0800, Cong Wang wrote:
> On Fri, 2012-08-03 at 12:10 +0200, Eric Dumazet wrote:
> >
> > I did this , just take it ;)
>
> Do we have to pass gfp to ->ndo_netpoll_setup() too? It seems no, so far
> I don't think we have to do that.
>
> Thanks.
>
It is needed.
->ndo_netpoll_setup() is called from __netpoll_setup()
So it would make no sense to allow GFP_KERNEL allocations in
ndo_netpoll_setup() hgandlers if we called __netpoll_setup() with
GFP_ATOMIC gfp
^ permalink raw reply
* [PATCH net-next 0/5] Per-net and on-demand link indices (and related)
From: Pavel Emelyanov @ 2012-08-06 10:30 UTC (permalink / raw)
To: David Miller, Eric Dumazet, Eric W. Biederman, Linux Netdev List
Hi!
This set tries to summarize the recent discussion of making ifindices friendly
to checkpoint-restore and consists of:
1. Prepare hash function to non-unique ifindices
2. Allow for specifying the desired ifindex on net link creation
3. Make ifindex generation per-net
4. Simplify loopback device ifindex access
Thanks,
Pavel
^ permalink raw reply
* [PATCH 1/5] net: Don't use ifindices in hash fns
From: Pavel Emelyanov @ 2012-08-06 10:30 UTC (permalink / raw)
To: David Miller, Eric Dumazet, Eric W. Biederman, Linux Netdev List
In-Reply-To: <501F9CAF.3030605@parallels.com>
Eric noticed, that when there will be devices with equal indices, some
hash functions that use them will become less effective as they could.
Fix this in advance by taking the net_device address into calculations
instead of the device index. Since the net_device is always aligned in
memory, shift the pointer to eliminate always zero bits (like we do it
in net_hash_mix).
This is true for arp and ndisc hash fns. The netlabel, can and llc ones
are also ifindex-based, but that three are init_net-only, thus will not
be affected.
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
---
include/linux/netdevice.h | 6 ++++++
include/net/arp.h | 2 +-
include/net/ndisc.h | 2 +-
3 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index a9db4f3..6010b37 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1330,6 +1330,12 @@ struct net_device {
#define NETDEV_ALIGN 32
+static inline unsigned int netdev_hash_mix(const struct net_device *dev)
+{
+ return (unsigned int)(((unsigned long)dev) >>
+ max(L1_CACHE_BYTES, NETDEV_ALIGN));
+}
+
static inline
int netdev_get_prio_tc_map(const struct net_device *dev, u32 prio)
{
diff --git a/include/net/arp.h b/include/net/arp.h
index 7f7df93..0305a38 100644
--- a/include/net/arp.h
+++ b/include/net/arp.h
@@ -10,7 +10,7 @@ extern struct neigh_table arp_tbl;
static inline u32 arp_hashfn(u32 key, const struct net_device *dev, u32 hash_rnd)
{
- u32 val = key ^ dev->ifindex;
+ u32 val = key ^ netdev_hash_mix(dev);
return val * hash_rnd;
}
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index 96a3b5c..ae7c1fd 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -134,7 +134,7 @@ static inline u32 ndisc_hashfn(const void *pkey, const struct net_device *dev, _
{
const u32 *p32 = pkey;
- return (((p32[0] ^ dev->ifindex) * hash_rnd[0]) +
+ return (((p32[0] ^ netdev_hash_mix(dev)) * hash_rnd[0]) +
(p32[1] * hash_rnd[1]) +
(p32[2] * hash_rnd[2]) +
(p32[3] * hash_rnd[3]));
--
1.7.6.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox