From 6f49a57aa5a0c6d4e4e27c85f7af6c83325a12d1 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 6 Jan 2009 11:38:14 -0700 Subject: dmaengine: up-level reference counting to the module level Simply, if a client wants any dmaengine channel then prevent all dmaengine modules from being removed. Once the clients are done re-enable module removal. Why?, beyond reducing complication: 1/ Tracking reference counts per-transaction in an efficient manner, as is currently done, requires a complicated scheme to avoid cache-line bouncing effects. 2/ Per-transaction ref-counting gives the false impression that a dma-driver can be gracefully removed ahead of its user (net, md, or dma-slave) 3/ None of the in-tree dma-drivers talk to hot pluggable hardware, but if such an engine were built one day we still would not need to notify clients of remove events. The driver can simply return NULL to a ->prep() request, something that is much easier for a client to handle. Reviewed-by: Andrew Morton Acked-by: Maciej Sosnowski Signed-off-by: Dan Williams --- net/ipv4/tcp.c | 1 - 1 file changed, 1 deletion(-) (limited to 'net') diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index f28acf11fc6..75e0e0a2d8d 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1632,7 +1632,6 @@ skip_copy: /* Safe to free early-copied skbs now */ __skb_queue_purge(&sk->sk_async_wait_queue); - dma_chan_put(tp->ucopy.dma_chan); tp->ucopy.dma_chan = NULL; } if (tp->ucopy.pinned_list) { -- cgit v1.2.3-70-g09d2 From 2ba05622b8b143b0c95968ba59bddfbd6d2f2559 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 6 Jan 2009 11:38:14 -0700 Subject: dmaengine: provide a common 'issue_pending_all' implementation async_tx and net_dma each have open-coded versions of issue_pending_all, so provide a common routine in dmaengine. The implementation needs to walk the global device list, so implement rcu to allow dma_issue_pending_all to run lockless. Clients protect themselves from channel removal events by holding a dmaengine reference. Reviewed-by: Andrew Morton Signed-off-by: Dan Williams --- crypto/async_tx/async_tx.c | 12 ------------ drivers/dma/dmaengine.c | 27 ++++++++++++++++++++++++--- include/linux/async_tx.h | 2 +- include/linux/dmaengine.h | 1 + net/core/dev.c | 9 +-------- 5 files changed, 27 insertions(+), 24 deletions(-) (limited to 'net') diff --git a/crypto/async_tx/async_tx.c b/crypto/async_tx/async_tx.c index b88bb1f608f..2cdf7a0867b 100644 --- a/crypto/async_tx/async_tx.c +++ b/crypto/async_tx/async_tx.c @@ -45,18 +45,6 @@ static DEFINE_SPINLOCK(async_tx_lock); static LIST_HEAD(async_tx_master_list); -/* async_tx_issue_pending_all - start all transactions on all channels */ -void async_tx_issue_pending_all(void) -{ - struct dma_chan_ref *ref; - - rcu_read_lock(); - list_for_each_entry_rcu(ref, &async_tx_master_list, node) - ref->chan->device->device_issue_pending(ref->chan); - rcu_read_unlock(); -} -EXPORT_SYMBOL_GPL(async_tx_issue_pending_all); - static void free_dma_chan_ref(struct rcu_head *rcu) { diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 87a8cd4791e..418eca28d47 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -70,6 +70,7 @@ #include #include #include +#include static DEFINE_MUTEX(dma_list_mutex); static LIST_HEAD(dma_device_list); @@ -365,6 +366,26 @@ struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type) } EXPORT_SYMBOL(dma_find_channel); +/** + * dma_issue_pending_all - flush all pending operations across all channels + */ +void dma_issue_pending_all(void) +{ + struct dma_device *device; + struct dma_chan *chan; + + WARN_ONCE(dmaengine_ref_count == 0, + "client called %s without a reference", __func__); + + rcu_read_lock(); + list_for_each_entry_rcu(device, &dma_device_list, global_node) + list_for_each_entry(chan, &device->channels, device_node) + if (chan->client_count) + device->device_issue_pending(chan); + rcu_read_unlock(); +} +EXPORT_SYMBOL(dma_issue_pending_all); + /** * nth_chan - returns the nth channel of the given capability * @cap: capability to match @@ -490,7 +511,7 @@ void dma_async_client_register(struct dma_client *client) err = dma_chan_get(chan); if (err == -ENODEV) { /* module removed before we could use it */ - list_del_init(&device->global_node); + list_del_rcu(&device->global_node); break; } else if (err) pr_err("dmaengine: failed to get %s: (%d)\n", @@ -635,7 +656,7 @@ int dma_async_device_register(struct dma_device *device) goto err_out; } } - list_add_tail(&device->global_node, &dma_device_list); + list_add_tail_rcu(&device->global_node, &dma_device_list); dma_channel_rebalance(); mutex_unlock(&dma_list_mutex); @@ -677,7 +698,7 @@ void dma_async_device_unregister(struct dma_device *device) struct dma_chan *chan; mutex_lock(&dma_list_mutex); - list_del(&device->global_node); + list_del_rcu(&device->global_node); dma_channel_rebalance(); mutex_unlock(&dma_list_mutex); diff --git a/include/linux/async_tx.h b/include/linux/async_tx.h index 1c816775f13..45f6297821b 100644 --- a/include/linux/async_tx.h +++ b/include/linux/async_tx.h @@ -59,7 +59,7 @@ enum async_tx_flags { }; #ifdef CONFIG_DMA_ENGINE -void async_tx_issue_pending_all(void); +#define async_tx_issue_pending_all dma_issue_pending_all #ifdef CONFIG_ARCH_HAS_ASYNC_TX_FIND_CHANNEL #include #else diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index b466f02e243..57a43adfc39 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -471,6 +471,7 @@ int dma_async_device_register(struct dma_device *device); void dma_async_device_unregister(struct dma_device *device); void dma_run_dependencies(struct dma_async_tx_descriptor *tx); struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type); +void dma_issue_pending_all(void); /* --- Helper iov-locking functions --- */ diff --git a/net/core/dev.c b/net/core/dev.c index 09c66a449da..e40b0d57f8f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2635,14 +2635,7 @@ out: * There may not be any more sk_buffs coming right now, so push * any pending DMA copies to hardware */ - if (!cpus_empty(net_dma.channel_mask)) { - int chan_idx; - for_each_cpu_mask_nr(chan_idx, net_dma.channel_mask) { - struct dma_chan *chan = net_dma.channels[chan_idx]; - if (chan) - dma_async_memcpy_issue_pending(chan); - } - } + dma_issue_pending_all(); #endif return; -- cgit v1.2.3-70-g09d2 From f67b45999205164958de4ec0658d51fa4bee066d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 6 Jan 2009 11:38:15 -0700 Subject: net_dma: convert to dma_find_channel Use the general-purpose channel allocation provided by dmaengine. Reviewed-by: Andrew Morton Signed-off-by: Dan Williams --- include/linux/netdevice.h | 3 --- include/net/netdma.h | 11 ----------- net/core/dev.c | 40 ---------------------------------------- net/ipv4/tcp.c | 4 ++-- net/ipv4/tcp_input.c | 2 +- net/ipv4/tcp_ipv4.c | 2 +- net/ipv6/tcp_ipv6.c | 2 +- 7 files changed, 5 insertions(+), 59 deletions(-) (limited to 'net') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 41e1224651c..bac2c458d9b 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1113,9 +1113,6 @@ struct softnet_data struct sk_buff *completion_queue; struct napi_struct backlog; -#ifdef CONFIG_NET_DMA - struct dma_chan *net_dma; -#endif }; DECLARE_PER_CPU(struct softnet_data,softnet_data); diff --git a/include/net/netdma.h b/include/net/netdma.h index cbe2737f4a6..8ba8ce284ee 100644 --- a/include/net/netdma.h +++ b/include/net/netdma.h @@ -24,17 +24,6 @@ #include #include -static inline struct dma_chan *get_softnet_dma(void) -{ - struct dma_chan *chan; - - rcu_read_lock(); - chan = rcu_dereference(__get_cpu_var(softnet_data).net_dma); - rcu_read_unlock(); - - return chan; -} - int dma_skb_copy_datagram_iovec(struct dma_chan* chan, struct sk_buff *skb, int offset, struct iovec *to, size_t len, struct dma_pinned_list *pinned_list); diff --git a/net/core/dev.c b/net/core/dev.c index e40b0d57f8f..bbb07dbe174 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4827,44 +4827,6 @@ static int dev_cpu_callback(struct notifier_block *nfb, } #ifdef CONFIG_NET_DMA -/** - * net_dma_rebalance - try to maintain one DMA channel per CPU - * @net_dma: DMA client and associated data (lock, channels, channel_mask) - * - * This is called when the number of channels allocated to the net_dma client - * changes. The net_dma client tries to have one DMA channel per CPU. - */ - -static void net_dma_rebalance(struct net_dma *net_dma) -{ - unsigned int cpu, i, n, chan_idx; - struct dma_chan *chan; - - if (cpus_empty(net_dma->channel_mask)) { - for_each_online_cpu(cpu) - rcu_assign_pointer(per_cpu(softnet_data, cpu).net_dma, NULL); - return; - } - - i = 0; - cpu = first_cpu(cpu_online_map); - - for_each_cpu_mask_nr(chan_idx, net_dma->channel_mask) { - chan = net_dma->channels[chan_idx]; - - n = ((num_online_cpus() / cpus_weight(net_dma->channel_mask)) - + (i < (num_online_cpus() % - cpus_weight(net_dma->channel_mask)) ? 1 : 0)); - - while(n) { - per_cpu(softnet_data, cpu).net_dma = chan; - cpu = next_cpu(cpu, cpu_online_map); - n--; - } - i++; - } -} - /** * netdev_dma_event - event callback for the net_dma_client * @client: should always be net_dma_client @@ -4894,7 +4856,6 @@ netdev_dma_event(struct dma_client *client, struct dma_chan *chan, ack = DMA_ACK; net_dma->channels[pos] = chan; cpu_set(pos, net_dma->channel_mask); - net_dma_rebalance(net_dma); } break; case DMA_RESOURCE_REMOVED: @@ -4909,7 +4870,6 @@ netdev_dma_event(struct dma_client *client, struct dma_chan *chan, ack = DMA_ACK; cpu_clear(pos, net_dma->channel_mask); net_dma->channels[i] = NULL; - net_dma_rebalance(net_dma); } break; default: diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 75e0e0a2d8d..9b275abc8eb 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1317,7 +1317,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, if ((available < target) && (len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) && !sysctl_tcp_low_latency && - __get_cpu_var(softnet_data).net_dma) { + dma_find_channel(DMA_MEMCPY)) { preempt_enable_no_resched(); tp->ucopy.pinned_list = dma_pin_iovec_pages(msg->msg_iov, len); @@ -1527,7 +1527,7 @@ do_prequeue: if (!(flags & MSG_TRUNC)) { #ifdef CONFIG_NET_DMA if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list) - tp->ucopy.dma_chan = get_softnet_dma(); + tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY); if (tp->ucopy.dma_chan) { tp->ucopy.dma_cookie = dma_skb_copy_datagram_iovec( diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 99b7ecbe889..a6961d75c7e 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5005,7 +5005,7 @@ static int tcp_dma_try_early_copy(struct sock *sk, struct sk_buff *skb, return 0; if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list) - tp->ucopy.dma_chan = get_softnet_dma(); + tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY); if (tp->ucopy.dma_chan && skb_csum_unnecessary(skb)) { diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 9d839fa9331..19d7b429a26 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1594,7 +1594,7 @@ process: #ifdef CONFIG_NET_DMA struct tcp_sock *tp = tcp_sk(sk); if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list) - tp->ucopy.dma_chan = get_softnet_dma(); + tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY); if (tp->ucopy.dma_chan) ret = tcp_v4_do_rcv(sk, skb); else diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index e8b8337a831..71cd70951d7 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1640,7 +1640,7 @@ process: #ifdef CONFIG_NET_DMA struct tcp_sock *tp = tcp_sk(sk); if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list) - tp->ucopy.dma_chan = get_softnet_dma(); + tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY); if (tp->ucopy.dma_chan) ret = tcp_v6_do_rcv(sk, skb); else -- cgit v1.2.3-70-g09d2 From 209b84a88fe81341b4d8d465acc4a67cb7c3feb3 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 6 Jan 2009 11:38:17 -0700 Subject: dmaengine: replace dma_async_client_register with dmaengine_get Now that clients no longer need to be notified of channel arrival dma_async_client_register can simply increment the dmaengine_ref_count. Reviewed-by: Andrew Morton Signed-off-by: Dan Williams --- crypto/async_tx/async_tx.c | 115 +-------------------------------------------- drivers/dma/dmaengine.c | 22 +++------ include/linux/dmaengine.h | 4 +- net/core/dev.c | 3 +- 4 files changed, 11 insertions(+), 133 deletions(-) (limited to 'net') diff --git a/crypto/async_tx/async_tx.c b/crypto/async_tx/async_tx.c index 2cdf7a0867b..f21147f3626 100644 --- a/crypto/async_tx/async_tx.c +++ b/crypto/async_tx/async_tx.c @@ -28,120 +28,9 @@ #include #ifdef CONFIG_DMA_ENGINE -static enum dma_state_client -dma_channel_add_remove(struct dma_client *client, - struct dma_chan *chan, enum dma_state state); - -static struct dma_client async_tx_dma = { - .event_callback = dma_channel_add_remove, - /* .cap_mask == 0 defaults to all channels */ -}; - -/** - * async_tx_lock - protect modification of async_tx_master_list and serialize - * rebalance operations - */ -static DEFINE_SPINLOCK(async_tx_lock); - -static LIST_HEAD(async_tx_master_list); - -static void -free_dma_chan_ref(struct rcu_head *rcu) -{ - struct dma_chan_ref *ref; - ref = container_of(rcu, struct dma_chan_ref, rcu); - kfree(ref); -} - -static void -init_dma_chan_ref(struct dma_chan_ref *ref, struct dma_chan *chan) -{ - INIT_LIST_HEAD(&ref->node); - INIT_RCU_HEAD(&ref->rcu); - ref->chan = chan; - atomic_set(&ref->count, 0); -} - -static enum dma_state_client -dma_channel_add_remove(struct dma_client *client, - struct dma_chan *chan, enum dma_state state) -{ - unsigned long found, flags; - struct dma_chan_ref *master_ref, *ref; - enum dma_state_client ack = DMA_DUP; /* default: take no action */ - - switch (state) { - case DMA_RESOURCE_AVAILABLE: - found = 0; - rcu_read_lock(); - list_for_each_entry_rcu(ref, &async_tx_master_list, node) - if (ref->chan == chan) { - found = 1; - break; - } - rcu_read_unlock(); - - pr_debug("async_tx: dma resource available [%s]\n", - found ? "old" : "new"); - - if (!found) - ack = DMA_ACK; - else - break; - - /* add the channel to the generic management list */ - master_ref = kmalloc(sizeof(*master_ref), GFP_KERNEL); - if (master_ref) { - init_dma_chan_ref(master_ref, chan); - spin_lock_irqsave(&async_tx_lock, flags); - list_add_tail_rcu(&master_ref->node, - &async_tx_master_list); - spin_unlock_irqrestore(&async_tx_lock, - flags); - } else { - printk(KERN_WARNING "async_tx: unable to create" - " new master entry in response to" - " a DMA_RESOURCE_ADDED event" - " (-ENOMEM)\n"); - return 0; - } - break; - case DMA_RESOURCE_REMOVED: - found = 0; - spin_lock_irqsave(&async_tx_lock, flags); - list_for_each_entry(ref, &async_tx_master_list, node) - if (ref->chan == chan) { - list_del_rcu(&ref->node); - call_rcu(&ref->rcu, free_dma_chan_ref); - found = 1; - break; - } - spin_unlock_irqrestore(&async_tx_lock, flags); - - pr_debug("async_tx: dma resource removed [%s]\n", - found ? "ours" : "not ours"); - - if (found) - ack = DMA_ACK; - else - break; - break; - case DMA_RESOURCE_SUSPEND: - case DMA_RESOURCE_RESUME: - printk(KERN_WARNING "async_tx: does not support dma channel" - " suspend/resume\n"); - break; - default: - BUG(); - } - - return ack; -} - static int __init async_tx_init(void) { - dma_async_client_register(&async_tx_dma); - dma_async_client_chan_request(&async_tx_dma); + dmaengine_get(); printk(KERN_INFO "async_tx: api initialized (async)\n"); @@ -150,7 +39,7 @@ static int __init async_tx_init(void) static void __exit async_tx_exit(void) { - dma_async_client_unregister(&async_tx_dma); + dmaengine_put(); } /** diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 90aca505a1d..3f1849b7f5e 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -600,10 +600,9 @@ static void dma_clients_notify_available(void) } /** - * dma_async_client_register - register a &dma_client - * @client: ptr to a client structure with valid 'event_callback' and 'cap_mask' + * dmaengine_get - register interest in dma_channels */ -void dma_async_client_register(struct dma_client *client) +void dmaengine_get(void) { struct dma_device *device, *_d; struct dma_chan *chan; @@ -634,25 +633,18 @@ void dma_async_client_register(struct dma_client *client) */ if (dmaengine_ref_count == 1) dma_channel_rebalance(); - list_add_tail(&client->global_node, &dma_client_list); mutex_unlock(&dma_list_mutex); } -EXPORT_SYMBOL(dma_async_client_register); +EXPORT_SYMBOL(dmaengine_get); /** - * dma_async_client_unregister - unregister a client and free the &dma_client - * @client: &dma_client to free - * - * Force frees any allocated DMA channels, frees the &dma_client memory + * dmaengine_put - let dma drivers be removed when ref_count == 0 */ -void dma_async_client_unregister(struct dma_client *client) +void dmaengine_put(void) { struct dma_device *device; struct dma_chan *chan; - if (!client) - return; - mutex_lock(&dma_list_mutex); dmaengine_ref_count--; BUG_ON(dmaengine_ref_count < 0); @@ -663,11 +655,9 @@ void dma_async_client_unregister(struct dma_client *client) list_for_each_entry(chan, &device->channels, device_node) dma_chan_put(chan); } - - list_del(&client->global_node); mutex_unlock(&dma_list_mutex); } -EXPORT_SYMBOL(dma_async_client_unregister); +EXPORT_SYMBOL(dmaengine_put); /** * dma_async_client_chan_request - send all available channels to the diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index d63544cf8a1..37d95db156d 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -318,8 +318,8 @@ struct dma_device { /* --- public DMA engine API --- */ -void dma_async_client_register(struct dma_client *client); -void dma_async_client_unregister(struct dma_client *client); +void dmaengine_get(void); +void dmaengine_put(void); void dma_async_client_chan_request(struct dma_client *client); dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest, void *src, size_t len); diff --git a/net/core/dev.c b/net/core/dev.c index bbb07dbe174..7596fc9403c 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4894,8 +4894,7 @@ static int __init netdev_dma_register(void) } spin_lock_init(&net_dma.lock); dma_cap_set(DMA_MEMCPY, net_dma.client.cap_mask); - dma_async_client_register(&net_dma.client); - dma_async_client_chan_request(&net_dma.client); + dmaengine_get(); return 0; } -- cgit v1.2.3-70-g09d2 From aa1e6f1a385eb2b04171ec841f3b760091e4a8ee Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 6 Jan 2009 11:38:17 -0700 Subject: dmaengine: kill struct dma_client and supporting infrastructure All users have been converted to either the general-purpose allocator, dma_find_channel, or dma_request_channel. Reviewed-by: Andrew Morton Signed-off-by: Dan Williams --- drivers/dma/dmaengine.c | 74 ++------------------------------- drivers/dma/dw_dmac.c | 3 +- drivers/dma/fsldma.c | 3 +- drivers/dma/ioat_dma.c | 5 +-- drivers/dma/iop-adma.c | 7 ++-- drivers/dma/mv_xor.c | 7 ++-- drivers/mmc/host/atmel-mci.c | 1 - include/linux/dmaengine.h | 50 +--------------------- net/core/dev.c | 99 ++------------------------------------------ 9 files changed, 17 insertions(+), 232 deletions(-) (limited to 'net') diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 3f1849b7f5e..9fc91f973a9 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -31,15 +31,12 @@ * * LOCKING: * - * The subsystem keeps two global lists, dma_device_list and dma_client_list. - * Both of these are protected by a mutex, dma_list_mutex. + * The subsystem keeps a global list of dma_device structs it is protected by a + * mutex, dma_list_mutex. * * Each device has a channels list, which runs unlocked but is never modified * once the device is registered, it's just setup by the driver. * - * Each client is responsible for keeping track of the channels it uses. See - * the definition of dma_event_callback in dmaengine.h. - * * Each device has a kref, which is initialized to 1 when the device is * registered. A kref_get is done for each device registered. When the * device is released, the corresponding kref_put is done in the release @@ -74,7 +71,6 @@ static DEFINE_MUTEX(dma_list_mutex); static LIST_HEAD(dma_device_list); -static LIST_HEAD(dma_client_list); static long dmaengine_ref_count; /* --- sysfs implementation --- */ @@ -189,7 +185,7 @@ static int dma_chan_get(struct dma_chan *chan) /* allocate upon first client reference */ if (chan->client_count == 1 && err == 0) { - int desc_cnt = chan->device->device_alloc_chan_resources(chan, NULL); + int desc_cnt = chan->device->device_alloc_chan_resources(chan); if (desc_cnt < 0) { err = desc_cnt; @@ -218,40 +214,6 @@ static void dma_chan_put(struct dma_chan *chan) chan->device->device_free_chan_resources(chan); } -/** - * dma_client_chan_alloc - try to allocate channels to a client - * @client: &dma_client - * - * Called with dma_list_mutex held. - */ -static void dma_client_chan_alloc(struct dma_client *client) -{ - struct dma_device *device; - struct dma_chan *chan; - enum dma_state_client ack; - - /* Find a channel */ - list_for_each_entry(device, &dma_device_list, global_node) { - if (dma_has_cap(DMA_PRIVATE, device->cap_mask)) - continue; - if (!dma_device_satisfies_mask(device, client->cap_mask)) - continue; - - list_for_each_entry(chan, &device->channels, device_node) { - if (!chan->client_count) - continue; - ack = client->event_callback(client, chan, - DMA_RESOURCE_AVAILABLE); - - /* we are done once this client rejects - * an available resource - */ - if (ack == DMA_NAK) - return; - } - } -} - enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie) { enum dma_status status; @@ -584,21 +546,6 @@ void dma_release_channel(struct dma_chan *chan) } EXPORT_SYMBOL_GPL(dma_release_channel); -/** - * dma_chans_notify_available - broadcast available channels to the clients - */ -static void dma_clients_notify_available(void) -{ - struct dma_client *client; - - mutex_lock(&dma_list_mutex); - - list_for_each_entry(client, &dma_client_list, global_node) - dma_client_chan_alloc(client); - - mutex_unlock(&dma_list_mutex); -} - /** * dmaengine_get - register interest in dma_channels */ @@ -659,19 +606,6 @@ void dmaengine_put(void) } EXPORT_SYMBOL(dmaengine_put); -/** - * dma_async_client_chan_request - send all available channels to the - * client that satisfy the capability mask - * @client - requester - */ -void dma_async_client_chan_request(struct dma_client *client) -{ - mutex_lock(&dma_list_mutex); - dma_client_chan_alloc(client); - mutex_unlock(&dma_list_mutex); -} -EXPORT_SYMBOL(dma_async_client_chan_request); - /** * dma_async_device_register - registers DMA devices found * @device: &dma_device @@ -765,8 +699,6 @@ int dma_async_device_register(struct dma_device *device) dma_channel_rebalance(); mutex_unlock(&dma_list_mutex); - dma_clients_notify_available(); - return 0; err_out: diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index dbd50804e5d..a29dda8f801 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -758,8 +758,7 @@ static void dwc_issue_pending(struct dma_chan *chan) spin_unlock_bh(&dwc->lock); } -static int dwc_alloc_chan_resources(struct dma_chan *chan, - struct dma_client *client) +static int dwc_alloc_chan_resources(struct dma_chan *chan) { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); struct dw_dma *dw = to_dw_dma(chan->device); diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 0b95dcce447..46e0128929a 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -366,8 +366,7 @@ static struct fsl_desc_sw *fsl_dma_alloc_descriptor( * * Return - The number of descriptors allocated. */ -static int fsl_dma_alloc_chan_resources(struct dma_chan *chan, - struct dma_client *client) +static int fsl_dma_alloc_chan_resources(struct dma_chan *chan) { struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan); diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c index 6607fdd00b1..e42e1aea0f1 100644 --- a/drivers/dma/ioat_dma.c +++ b/drivers/dma/ioat_dma.c @@ -734,8 +734,7 @@ static void ioat2_dma_massage_chan_desc(struct ioat_dma_chan *ioat_chan) * ioat_dma_alloc_chan_resources - returns the number of allocated descriptors * @chan: the channel to be filled out */ -static int ioat_dma_alloc_chan_resources(struct dma_chan *chan, - struct dma_client *client) +static int ioat_dma_alloc_chan_resources(struct dma_chan *chan) { struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); struct ioat_desc_sw *desc; @@ -1381,7 +1380,7 @@ static int ioat_dma_self_test(struct ioatdma_device *device) dma_chan = container_of(device->common.channels.next, struct dma_chan, device_node); - if (device->common.device_alloc_chan_resources(dma_chan, NULL) < 1) { + if (device->common.device_alloc_chan_resources(dma_chan) < 1) { dev_err(&device->pdev->dev, "selftest cannot allocate chan resource\n"); err = -ENODEV; diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c index be9ea9f8880..c74ac9eb009 100644 --- a/drivers/dma/iop-adma.c +++ b/drivers/dma/iop-adma.c @@ -470,8 +470,7 @@ static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan); * greater than 2x the number slots needed to satisfy a device->max_xor * request. * */ -static int iop_adma_alloc_chan_resources(struct dma_chan *chan, - struct dma_client *client) +static int iop_adma_alloc_chan_resources(struct dma_chan *chan) { char *hw_desc; int idx; @@ -865,7 +864,7 @@ static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device) dma_chan = container_of(device->common.channels.next, struct dma_chan, device_node); - if (iop_adma_alloc_chan_resources(dma_chan, NULL) < 1) { + if (iop_adma_alloc_chan_resources(dma_chan) < 1) { err = -ENODEV; goto out; } @@ -963,7 +962,7 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device) dma_chan = container_of(device->common.channels.next, struct dma_chan, device_node); - if (iop_adma_alloc_chan_resources(dma_chan, NULL) < 1) { + if (iop_adma_alloc_chan_resources(dma_chan) < 1) { err = -ENODEV; goto out; } diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index 3f46df3390c..fbaa2f6225e 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -606,8 +606,7 @@ submit_done: } /* returns the number of allocated descriptors */ -static int mv_xor_alloc_chan_resources(struct dma_chan *chan, - struct dma_client *client) +static int mv_xor_alloc_chan_resources(struct dma_chan *chan) { char *hw_desc; int idx; @@ -957,7 +956,7 @@ static int __devinit mv_xor_memcpy_self_test(struct mv_xor_device *device) dma_chan = container_of(device->common.channels.next, struct dma_chan, device_node); - if (mv_xor_alloc_chan_resources(dma_chan, NULL) < 1) { + if (mv_xor_alloc_chan_resources(dma_chan) < 1) { err = -ENODEV; goto out; } @@ -1052,7 +1051,7 @@ mv_xor_xor_self_test(struct mv_xor_device *device) dma_chan = container_of(device->common.channels.next, struct dma_chan, device_node); - if (mv_xor_alloc_chan_resources(dma_chan, NULL) < 1) { + if (mv_xor_alloc_chan_resources(dma_chan) < 1) { err = -ENODEV; goto out; } diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 7a34118507d..4b567a0408e 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -55,7 +55,6 @@ enum atmel_mci_state { struct atmel_mci_dma { #ifdef CONFIG_MMC_ATMELMCI_DMA - struct dma_client client; struct dma_chan *chan; struct dma_async_tx_descriptor *data_desc; #endif diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 37d95db156d..db050e97d2b 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -28,20 +28,6 @@ #include #include -/** - * enum dma_state - resource PNP/power management state - * @DMA_RESOURCE_SUSPEND: DMA device going into low power state - * @DMA_RESOURCE_RESUME: DMA device returning to full power - * @DMA_RESOURCE_AVAILABLE: DMA device available to the system - * @DMA_RESOURCE_REMOVED: DMA device removed from the system - */ -enum dma_state { - DMA_RESOURCE_SUSPEND, - DMA_RESOURCE_RESUME, - DMA_RESOURCE_AVAILABLE, - DMA_RESOURCE_REMOVED, -}; - /** * enum dma_state_client - state of the channel in the client * @DMA_ACK: client would like to use, or was using this channel @@ -170,23 +156,6 @@ struct dma_chan { void dma_chan_cleanup(struct kref *kref); -/* - * typedef dma_event_callback - function pointer to a DMA event callback - * For each channel added to the system this routine is called for each client. - * If the client would like to use the channel it returns '1' to signal (ack) - * the dmaengine core to take out a reference on the channel and its - * corresponding device. A client must not 'ack' an available channel more - * than once. When a channel is removed all clients are notified. If a client - * is using the channel it must 'ack' the removal. A client must not 'ack' a - * removed channel more than once. - * @client - 'this' pointer for the client context - * @chan - channel to be acted upon - * @state - available or removed - */ -struct dma_client; -typedef enum dma_state_client (*dma_event_callback) (struct dma_client *client, - struct dma_chan *chan, enum dma_state state); - /** * typedef dma_filter_fn - callback filter for dma_request_channel * @chan: channel to be reviewed @@ -199,21 +168,6 @@ typedef enum dma_state_client (*dma_event_callback) (struct dma_client *client, */ typedef enum dma_state_client (*dma_filter_fn)(struct dma_chan *chan, void *filter_param); -/** - * struct dma_client - info on the entity making use of DMA services - * @event_callback: func ptr to call when something happens - * @cap_mask: only return channels that satisfy the requested capabilities - * a value of zero corresponds to any capability - * @slave: data for preparing slave transfer. Must be non-NULL iff the - * DMA_SLAVE capability is requested. - * @global_node: list_head for global dma_client_list - */ -struct dma_client { - dma_event_callback event_callback; - dma_cap_mask_t cap_mask; - struct list_head global_node; -}; - typedef void (*dma_async_tx_callback)(void *dma_async_param); /** * struct dma_async_tx_descriptor - async transaction descriptor @@ -285,8 +239,7 @@ struct dma_device { int dev_id; struct device *dev; - int (*device_alloc_chan_resources)(struct dma_chan *chan, - struct dma_client *client); + int (*device_alloc_chan_resources)(struct dma_chan *chan); void (*device_free_chan_resources)(struct dma_chan *chan); struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)( @@ -320,7 +273,6 @@ struct dma_device { void dmaengine_get(void); void dmaengine_put(void); -void dma_async_client_chan_request(struct dma_client *client); dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest, void *src, size_t len); dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan, diff --git a/net/core/dev.c b/net/core/dev.c index 7596fc9403c..ac55d84d625 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -167,25 +167,6 @@ static DEFINE_SPINLOCK(ptype_lock); static struct list_head ptype_base[PTYPE_HASH_SIZE] __read_mostly; static struct list_head ptype_all __read_mostly; /* Taps */ -#ifdef CONFIG_NET_DMA -struct net_dma { - struct dma_client client; - spinlock_t lock; - cpumask_t channel_mask; - struct dma_chan **channels; -}; - -static enum dma_state_client -netdev_dma_event(struct dma_client *client, struct dma_chan *chan, - enum dma_state state); - -static struct net_dma net_dma = { - .client = { - .event_callback = netdev_dma_event, - }, -}; -#endif - /* * The @dev_base_head list is protected by @dev_base_lock and the rtnl * semaphore. @@ -4826,81 +4807,6 @@ static int dev_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -#ifdef CONFIG_NET_DMA -/** - * netdev_dma_event - event callback for the net_dma_client - * @client: should always be net_dma_client - * @chan: DMA channel for the event - * @state: DMA state to be handled - */ -static enum dma_state_client -netdev_dma_event(struct dma_client *client, struct dma_chan *chan, - enum dma_state state) -{ - int i, found = 0, pos = -1; - struct net_dma *net_dma = - container_of(client, struct net_dma, client); - enum dma_state_client ack = DMA_DUP; /* default: take no action */ - - spin_lock(&net_dma->lock); - switch (state) { - case DMA_RESOURCE_AVAILABLE: - for (i = 0; i < nr_cpu_ids; i++) - if (net_dma->channels[i] == chan) { - found = 1; - break; - } else if (net_dma->channels[i] == NULL && pos < 0) - pos = i; - - if (!found && pos >= 0) { - ack = DMA_ACK; - net_dma->channels[pos] = chan; - cpu_set(pos, net_dma->channel_mask); - } - break; - case DMA_RESOURCE_REMOVED: - for (i = 0; i < nr_cpu_ids; i++) - if (net_dma->channels[i] == chan) { - found = 1; - pos = i; - break; - } - - if (found) { - ack = DMA_ACK; - cpu_clear(pos, net_dma->channel_mask); - net_dma->channels[i] = NULL; - } - break; - default: - break; - } - spin_unlock(&net_dma->lock); - - return ack; -} - -/** - * netdev_dma_register - register the networking subsystem as a DMA client - */ -static int __init netdev_dma_register(void) -{ - net_dma.channels = kzalloc(nr_cpu_ids * sizeof(struct net_dma), - GFP_KERNEL); - if (unlikely(!net_dma.channels)) { - printk(KERN_NOTICE - "netdev_dma: no memory for net_dma.channels\n"); - return -ENOMEM; - } - spin_lock_init(&net_dma.lock); - dma_cap_set(DMA_MEMCPY, net_dma.client.cap_mask); - dmaengine_get(); - return 0; -} - -#else -static int __init netdev_dma_register(void) { return -ENODEV; } -#endif /* CONFIG_NET_DMA */ /** * netdev_increment_features - increment feature set by one @@ -5120,14 +5026,15 @@ static int __init net_dev_init(void) if (register_pernet_device(&default_device_ops)) goto out; - netdev_dma_register(); - open_softirq(NET_TX_SOFTIRQ, net_tx_action); open_softirq(NET_RX_SOFTIRQ, net_rx_action); hotcpu_notifier(dev_cpu_callback, 0); dst_init(); dev_mcast_init(); + #ifdef CONFIG_NET_DMA + dmaengine_get(); + #endif rc = 0; out: return rc; -- cgit v1.2.3-70-g09d2 From 148bc4303f9ba972cbfe5d30dfec93ec0d8ff1e1 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 6 Jan 2009 10:42:24 -0800 Subject: wireless: convert wireless ioctl to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/wireless/wext.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/wireless/wext.c b/net/wireless/wext.c index e49a2d1ef1e..cb6a5bb85d8 100644 --- a/net/wireless/wext.c +++ b/net/wireless/wext.c @@ -1055,8 +1055,8 @@ static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, return private(dev, iwr, cmd, info, handler); } /* Old driver API : call driver ioctl handler */ - if (dev->do_ioctl) - return dev->do_ioctl(dev, ifr, cmd); + if (dev->netdev_ops->ndo_do_ioctl) + return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd); return -EOPNOTSUPP; } -- cgit v1.2.3-70-g09d2 From 61294e2e2730f24b833d9a713add5f4f6672c2a4 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 6 Jan 2009 10:45:57 -0800 Subject: sch_teql: convert to net_device_ops Convert this driver to net_device_ops. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/sched/sch_teql.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'net') diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index cfc8e7caba6..ec697cebb63 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c @@ -289,9 +289,9 @@ restart: do { struct net_device *slave = qdisc_dev(q); - struct netdev_queue *slave_txq; + struct netdev_queue *slave_txq = netdev_get_tx_queue(slave, 0); + const struct net_device_ops *slave_ops = slave->netdev_ops; - slave_txq = netdev_get_tx_queue(slave, 0); if (slave_txq->qdisc_sleeping != q) continue; if (__netif_subqueue_stopped(slave, subq) || @@ -305,7 +305,7 @@ restart: if (__netif_tx_trylock(slave_txq)) { if (!netif_tx_queue_stopped(slave_txq) && !netif_tx_queue_frozen(slave_txq) && - slave->hard_start_xmit(skb, slave) == 0) { + slave_ops->ndo_start_xmit(skb, slave) == 0) { __netif_tx_unlock(slave_txq); master->slaves = NEXT_SLAVE(q); netif_wake_queue(dev); @@ -420,6 +420,14 @@ static int teql_master_mtu(struct net_device *dev, int new_mtu) return 0; } +static const struct net_device_ops teql_netdev_ops = { + .ndo_open = teql_master_open, + .ndo_stop = teql_master_close, + .ndo_start_xmit = teql_master_xmit, + .ndo_get_stats = teql_master_stats, + .ndo_change_mtu = teql_master_mtu, +}; + static __init void teql_master_setup(struct net_device *dev) { struct teql_master *master = netdev_priv(dev); @@ -436,11 +444,7 @@ static __init void teql_master_setup(struct net_device *dev) ops->destroy = teql_destroy; ops->owner = THIS_MODULE; - dev->open = teql_master_open; - dev->hard_start_xmit = teql_master_xmit; - dev->stop = teql_master_close; - dev->get_stats = teql_master_stats; - dev->change_mtu = teql_master_mtu; + dev->netdev_ops = &teql_netdev_ops; dev->type = ARPHRD_VOID; dev->mtu = 1500; dev->tx_queue_len = 100; -- cgit v1.2.3-70-g09d2 From 96e93eab20337d063c70d537bd7bc70d90e04fa3 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 6 Jan 2009 10:49:34 -0800 Subject: gro: Add internal interfaces for VLAN Previously GRO's only entry point from the outside is through napi_gro_receive and napi_gro_frags. These interfaces are for device drivers. This patch rearranges things to provide a new set of interfaces for VLANs. These interfaces are for internal use only. The VLAN code itself can then provide a set of entry points for device drivers. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- include/linux/netdevice.h | 6 ++++ net/core/dev.c | 82 ++++++++++++++++++++++++++++++++++------------- 2 files changed, 65 insertions(+), 23 deletions(-) (limited to 'net') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index c28bbba3c23..114091be887 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1373,8 +1373,14 @@ extern int netif_rx_ni(struct sk_buff *skb); #define HAVE_NETIF_RECEIVE_SKB 1 extern int netif_receive_skb(struct sk_buff *skb); extern void napi_gro_flush(struct napi_struct *napi); +extern int dev_gro_receive(struct napi_struct *napi, + struct sk_buff *skb); extern int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb); +extern void napi_reuse_skb(struct napi_struct *napi, + struct sk_buff *skb); +extern struct sk_buff * napi_fraginfo_skb(struct napi_struct *napi, + struct napi_gro_fraginfo *info); extern int napi_gro_frags(struct napi_struct *napi, struct napi_gro_fraginfo *info); extern void netif_nit_deliver(struct sk_buff *skb); diff --git a/net/core/dev.c b/net/core/dev.c index 382df6c09ee..bab8bcedd62 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2387,7 +2387,7 @@ void napi_gro_flush(struct napi_struct *napi) } EXPORT_SYMBOL(napi_gro_flush); -static int __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) +int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) { struct sk_buff **pp = NULL; struct packet_type *ptype; @@ -2417,11 +2417,14 @@ static int __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) for (p = napi->gro_list; p; p = p->next) { count++; - NAPI_GRO_CB(p)->same_flow = - p->mac_len == mac_len && - !memcmp(skb_mac_header(p), skb_mac_header(skb), - mac_len); - NAPI_GRO_CB(p)->flush = 0; + + if (!NAPI_GRO_CB(p)->same_flow) + continue; + + if (p->mac_len != mac_len || + memcmp(skb_mac_header(p), skb_mac_header(skb), + mac_len)) + NAPI_GRO_CB(p)->same_flow = 0; } pp = ptype->gro_receive(&napi->gro_list, skb); @@ -2463,6 +2466,19 @@ ok: normal: return -1; } +EXPORT_SYMBOL(dev_gro_receive); + +static int __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) +{ + struct sk_buff *p; + + for (p = napi->gro_list; p; p = p->next) { + NAPI_GRO_CB(p)->same_flow = 1; + NAPI_GRO_CB(p)->flush = 0; + } + + return dev_gro_receive(napi, skb); +} int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) { @@ -2479,11 +2495,26 @@ int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) } EXPORT_SYMBOL(napi_gro_receive); -int napi_gro_frags(struct napi_struct *napi, struct napi_gro_fraginfo *info) +void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb) +{ + skb_shinfo(skb)->nr_frags = 0; + + skb->len -= skb->data_len; + skb->truesize -= skb->data_len; + skb->data_len = 0; + + __skb_pull(skb, skb_headlen(skb)); + skb_reserve(skb, NET_IP_ALIGN - skb_headroom(skb)); + + napi->skb = skb; +} +EXPORT_SYMBOL(napi_reuse_skb); + +struct sk_buff *napi_fraginfo_skb(struct napi_struct *napi, + struct napi_gro_fraginfo *info) { struct net_device *dev = napi->dev; struct sk_buff *skb = napi->skb; - int err = NET_RX_DROP; napi->skb = NULL; @@ -2503,16 +2534,31 @@ int napi_gro_frags(struct napi_struct *napi, struct napi_gro_fraginfo *info) skb->len += info->len; skb->truesize += info->len; - if (!pskb_may_pull(skb, ETH_HLEN)) - goto reuse; - - err = NET_RX_SUCCESS; + if (!pskb_may_pull(skb, ETH_HLEN)) { + napi_reuse_skb(napi, skb); + goto out; + } skb->protocol = eth_type_trans(skb, dev); skb->ip_summed = info->ip_summed; skb->csum = info->csum; +out: + return skb; +} +EXPORT_SYMBOL(napi_fraginfo_skb); + +int napi_gro_frags(struct napi_struct *napi, struct napi_gro_fraginfo *info) +{ + struct sk_buff *skb = napi_fraginfo_skb(napi, info); + int err = NET_RX_DROP; + + if (!skb) + goto out; + + err = NET_RX_SUCCESS; + switch (__napi_gro_receive(napi, skb)) { case -1: return netif_receive_skb(skb); @@ -2521,17 +2567,7 @@ int napi_gro_frags(struct napi_struct *napi, struct napi_gro_fraginfo *info) goto out; } -reuse: - skb_shinfo(skb)->nr_frags = 0; - - skb->len -= skb->data_len; - skb->truesize -= skb->data_len; - skb->data_len = 0; - - __skb_pull(skb, skb_headlen(skb)); - skb_reserve(skb, NET_IP_ALIGN - skb_headroom(skb)); - - napi->skb = skb; + napi_reuse_skb(napi, skb); out: return err; -- cgit v1.2.3-70-g09d2 From e1c096e251e52773afeffbbcb74d0a072be47ea3 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 6 Jan 2009 10:50:09 -0800 Subject: vlan: Add GRO interfaces This patch adds GRO interfaces for hardware-assisted VLAN reception. With this in place we're now at parity with LRO as far as the interface is concerned. That is, you can now take any LRO driver and convert it over to GRO. As the CB memory clashes with GRO's use of CB, I've removed it entirely by storing dev in skb->dev. This is OK because VLAN gets called first thing in netif_receive_skb and skb->dev is not used in between us calling netif_rx and netif_receive_skb getting called. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- include/linux/if_vlan.h | 19 +++++++++ net/8021q/vlan_core.c | 111 ++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 107 insertions(+), 23 deletions(-) (limited to 'net') diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index a5cb0c3f6dc..f8ff918c208 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -115,6 +115,11 @@ extern u16 vlan_dev_vlan_id(const struct net_device *dev); extern int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, u16 vlan_tci, int polling); extern int vlan_hwaccel_do_receive(struct sk_buff *skb); +extern int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, + unsigned int vlan_tci, struct sk_buff *skb); +extern int vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, + unsigned int vlan_tci, + struct napi_gro_fraginfo *info); #else static inline struct net_device *vlan_dev_real_dev(const struct net_device *dev) @@ -140,6 +145,20 @@ static inline int vlan_hwaccel_do_receive(struct sk_buff *skb) { return 0; } + +static inline int vlan_gro_receive(struct napi_struct *napi, + struct vlan_group *grp, + unsigned int vlan_tci, struct sk_buff *skb) +{ + return NET_RX_DROP; +} + +static inline int vlan_gro_frags(struct napi_struct *napi, + struct vlan_group *grp, unsigned int vlan_tci, + struct napi_gro_fraginfo *info) +{ + return NET_RX_DROP; +} #endif /** diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index dd86a1dc4cd..6c132394026 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -3,46 +3,35 @@ #include #include "vlan.h" -struct vlan_hwaccel_cb { - struct net_device *dev; -}; - -static inline struct vlan_hwaccel_cb *vlan_hwaccel_cb(struct sk_buff *skb) -{ - return (struct vlan_hwaccel_cb *)skb->cb; -} - /* VLAN rx hw acceleration helper. This acts like netif_{rx,receive_skb}(). */ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, u16 vlan_tci, int polling) { - struct vlan_hwaccel_cb *cb = vlan_hwaccel_cb(skb); - - if (skb_bond_should_drop(skb)) { - dev_kfree_skb_any(skb); - return NET_RX_DROP; - } + if (skb_bond_should_drop(skb)) + goto drop; skb->vlan_tci = vlan_tci; - cb->dev = vlan_group_get_device(grp, vlan_tci & VLAN_VID_MASK); + skb->dev = vlan_group_get_device(grp, vlan_tci & VLAN_VID_MASK); + + if (!skb->dev) + goto drop; return (polling ? netif_receive_skb(skb) : netif_rx(skb)); + +drop: + dev_kfree_skb_any(skb); + return NET_RX_DROP; } EXPORT_SYMBOL(__vlan_hwaccel_rx); int vlan_hwaccel_do_receive(struct sk_buff *skb) { - struct vlan_hwaccel_cb *cb = vlan_hwaccel_cb(skb); - struct net_device *dev = cb->dev; + struct net_device *dev = skb->dev; struct net_device_stats *stats; + skb->dev = vlan_dev_info(dev)->real_dev; netif_nit_deliver(skb); - if (dev == NULL) { - kfree_skb(skb); - return -1; - } - skb->dev = dev; skb->priority = vlan_get_ingress_priority(dev, skb->vlan_tci); skb->vlan_tci = 0; @@ -80,3 +69,79 @@ u16 vlan_dev_vlan_id(const struct net_device *dev) return vlan_dev_info(dev)->vlan_id; } EXPORT_SYMBOL_GPL(vlan_dev_vlan_id); + +static int vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp, + unsigned int vlan_tci, struct sk_buff *skb) +{ + struct sk_buff *p; + + if (skb_bond_should_drop(skb)) + goto drop; + + skb->vlan_tci = vlan_tci; + skb->dev = vlan_group_get_device(grp, vlan_tci & VLAN_VID_MASK); + + if (!skb->dev) + goto drop; + + for (p = napi->gro_list; p; p = p->next) { + NAPI_GRO_CB(p)->same_flow = p->dev == skb->dev; + NAPI_GRO_CB(p)->flush = 0; + } + + return dev_gro_receive(napi, skb); + +drop: + return 2; +} + +int vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, + unsigned int vlan_tci, struct sk_buff *skb) +{ + int err = NET_RX_SUCCESS; + + switch (vlan_gro_common(napi, grp, vlan_tci, skb)) { + case -1: + return netif_receive_skb(skb); + + case 2: + err = NET_RX_DROP; + /* fall through */ + + case 1: + kfree_skb(skb); + break; + } + + return err; +} +EXPORT_SYMBOL(vlan_gro_receive); + +int vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, + unsigned int vlan_tci, struct napi_gro_fraginfo *info) +{ + struct sk_buff *skb = napi_fraginfo_skb(napi, info); + int err = NET_RX_DROP; + + if (!skb) + goto out; + + err = NET_RX_SUCCESS; + + switch (vlan_gro_common(napi, grp, vlan_tci, skb)) { + case -1: + return netif_receive_skb(skb); + + case 2: + err = NET_RX_DROP; + /* fall through */ + + case 1: + napi_reuse_skb(napi, skb); + break; + } + +out: + return err; +} +EXPORT_SYMBOL(vlan_gro_frags); -- cgit v1.2.3-70-g09d2 From 1fa17d4ba43d7e5aab5e90777b07da06524f6748 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 6 Jan 2009 11:07:54 -0800 Subject: can: omit unneeded skb_clone() calls The AF_CAN core delivered always cloned sk_buffs to the AF_CAN protocols, although this was _only_ needed by the can-raw protocol. With this (additionally documented) change, the AF_CAN core calls the callback functions of the registered AF_CAN protocols with the original (uncloned) sk_buff pointer and let's the can-raw protocol do the skb_clone() itself which omits all unneeded skb_clone() calls for other AF_CAN protocols. Signed-off-by: Oliver Hartkopp Signed-off-by: Urs Thuermann Signed-off-by: David S. Miller --- include/linux/can/core.h | 2 +- net/can/af_can.c | 15 ++++++++------- net/can/bcm.c | 12 +++++------- net/can/raw.c | 15 ++++++++------- 4 files changed, 22 insertions(+), 22 deletions(-) (limited to 'net') diff --git a/include/linux/can/core.h b/include/linux/can/core.h index f50785ad478..25085cbadcf 100644 --- a/include/linux/can/core.h +++ b/include/linux/can/core.h @@ -19,7 +19,7 @@ #include #include -#define CAN_VERSION "20081130" +#define CAN_VERSION "20090105" /* increment this number each time you change some user-space interface */ #define CAN_ABI_VERSION "8" diff --git a/net/can/af_can.c b/net/can/af_can.c index 3dadb338add..fa417ca6cbe 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -414,6 +414,12 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask, * The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can * filter for error frames (CAN_ERR_FLAG bit set in mask). * + * The provided pointer to the sk_buff is guaranteed to be valid as long as + * the callback function is running. The callback function must *not* free + * the given sk_buff while processing it's task. When the given sk_buff is + * needed after the end of the callback function it must be cloned inside + * the callback function with skb_clone(). + * * Return: * 0 on success * -ENOMEM on missing cache mem to create subscription entry @@ -569,13 +575,8 @@ EXPORT_SYMBOL(can_rx_unregister); static inline void deliver(struct sk_buff *skb, struct receiver *r) { - struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC); - - if (clone) { - clone->sk = skb->sk; - r->func(clone, r->data); - r->matches++; - } + r->func(skb, r->data); + r->matches++; } static int can_rcv_filter(struct dev_rcv_lists *d, struct sk_buff *skb) diff --git a/net/can/bcm.c b/net/can/bcm.c index 6248ae2502c..1649c8ab2c2 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -633,7 +633,7 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data) hrtimer_cancel(&op->timer); if (op->can_id != rxframe->can_id) - goto rx_freeskb; + return; /* save rx timestamp */ op->rx_stamp = skb->tstamp; @@ -645,19 +645,19 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data) if (op->flags & RX_RTR_FRAME) { /* send reply for RTR-request (placed in op->frames[0]) */ bcm_can_tx(op); - goto rx_freeskb; + return; } if (op->flags & RX_FILTER_ID) { /* the easiest case */ bcm_rx_update_and_send(op, &op->last_frames[0], rxframe); - goto rx_freeskb_starttimer; + goto rx_starttimer; } if (op->nframes == 1) { /* simple compare with index 0 */ bcm_rx_cmp_to_index(op, 0, rxframe); - goto rx_freeskb_starttimer; + goto rx_starttimer; } if (op->nframes > 1) { @@ -678,10 +678,8 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data) } } -rx_freeskb_starttimer: +rx_starttimer: bcm_rx_starttimer(op); -rx_freeskb: - kfree_skb(skb); } /* diff --git a/net/can/raw.c b/net/can/raw.c index 27aab63df46..0703cba4bf9 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -99,13 +99,14 @@ static void raw_rcv(struct sk_buff *skb, void *data) struct raw_sock *ro = raw_sk(sk); struct sockaddr_can *addr; - if (!ro->recv_own_msgs) { - /* check the received tx sock reference */ - if (skb->sk == sk) { - kfree_skb(skb); - return; - } - } + /* check the received tx sock reference */ + if (!ro->recv_own_msgs && skb->sk == sk) + return; + + /* clone the given skb to be able to enqueue it into the rcv queue */ + skb = skb_clone(skb, GFP_ATOMIC); + if (!skb) + return; /* * Put the datagram to the queue so that raw_recvmsg() can -- cgit v1.2.3-70-g09d2 From d442ad4ab1c86b453e0f44fb3de0932f386ab3e6 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 6 Jan 2009 16:45:26 -0800 Subject: dsa: convert to net_device_ops (v2) Convert this driver to use net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/dsa/slave.c | 51 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 10 deletions(-) (limited to 'net') diff --git a/net/dsa/slave.c b/net/dsa/slave.c index a3a410d20da..a68fd79e9ec 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -286,6 +286,42 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = { .get_sset_count = dsa_slave_get_sset_count, }; +#ifdef CONFIG_NET_DSA_TAG_DSA +static const struct net_device_ops dsa_netdev_ops = { + .ndo_open = dsa_slave_open, + .ndo_stop = dsa_slave_close, + .ndo_start_xmit = dsa_xmit, + .ndo_change_rx_flags = dsa_slave_change_rx_flags, + .ndo_set_rx_mode = dsa_slave_set_rx_mode, + .ndo_set_multicast_list = dsa_slave_set_rx_mode, + .ndo_set_mac_address = dsa_slave_set_mac_address, + .ndo_do_ioctl = dsa_slave_ioctl, +}; +#endif +#ifdef CONFIG_NET_DSA_TAG_EDSA +static const struct net_device_ops edsa_netdev_ops = { + .ndo_open = dsa_slave_open, + .ndo_stop = dsa_slave_close, + .ndo_start_xmit = edsa_xmit, + .ndo_change_rx_flags = dsa_slave_change_rx_flags, + .ndo_set_rx_mode = dsa_slave_set_rx_mode, + .ndo_set_multicast_list = dsa_slave_set_rx_mode, + .ndo_set_mac_address = dsa_slave_set_mac_address, + .ndo_do_ioctl = dsa_slave_ioctl, +}; +#endif +#ifdef CONFIG_NET_DSA_TAG_TRAILER +static const struct net_device_ops trailer_netdev_ops = { + .ndo_open = dsa_slave_open, + .ndo_stop = dsa_slave_close, + .ndo_start_xmit = trailer_xmit, + .ndo_change_rx_flags = dsa_slave_change_rx_flags, + .ndo_set_rx_mode = dsa_slave_set_rx_mode, + .ndo_set_multicast_list = dsa_slave_set_rx_mode, + .ndo_set_mac_address = dsa_slave_set_mac_address, + .ndo_do_ioctl = dsa_slave_ioctl, +}; +#endif /* slave device setup *******************************************************/ struct net_device * @@ -306,32 +342,27 @@ dsa_slave_create(struct dsa_switch *ds, struct device *parent, SET_ETHTOOL_OPS(slave_dev, &dsa_slave_ethtool_ops); memcpy(slave_dev->dev_addr, master->dev_addr, ETH_ALEN); slave_dev->tx_queue_len = 0; + switch (ds->tag_protocol) { #ifdef CONFIG_NET_DSA_TAG_DSA case htons(ETH_P_DSA): - slave_dev->hard_start_xmit = dsa_xmit; + slave_dev->netdev_ops = &dsa_netdev_ops; break; #endif #ifdef CONFIG_NET_DSA_TAG_EDSA case htons(ETH_P_EDSA): - slave_dev->hard_start_xmit = edsa_xmit; + slave_dev->netdev_ops = &edsa_netdev_ops; break; #endif #ifdef CONFIG_NET_DSA_TAG_TRAILER case htons(ETH_P_TRAILER): - slave_dev->hard_start_xmit = trailer_xmit; + slave_dev->netdev_ops = &trailer_netdev_ops; break; #endif default: BUG(); } - slave_dev->open = dsa_slave_open; - slave_dev->stop = dsa_slave_close; - slave_dev->change_rx_flags = dsa_slave_change_rx_flags; - slave_dev->set_rx_mode = dsa_slave_set_rx_mode; - slave_dev->set_multicast_list = dsa_slave_set_rx_mode; - slave_dev->set_mac_address = dsa_slave_set_mac_address; - slave_dev->do_ioctl = dsa_slave_ioctl; + SET_NETDEV_DEV(slave_dev, parent); slave_dev->vlan_features = master->vlan_features; -- cgit v1.2.3-70-g09d2 From 03b35ccb7c41ccc256631ff33e6887b7be88137b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 7 Jan 2009 17:21:44 -0800 Subject: appletalk: convert aarp to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/appletalk/aarp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c index b03ff58e930..89f99d3beb6 100644 --- a/net/appletalk/aarp.c +++ b/net/appletalk/aarp.c @@ -443,13 +443,14 @@ static void aarp_send_probe_phase1(struct atalk_iface *iface) { struct ifreq atreq; struct sockaddr_at *sa = (struct sockaddr_at *)&atreq.ifr_addr; + const struct net_device_ops *ops = iface->dev->netdev_ops; sa->sat_addr.s_node = iface->address.s_node; sa->sat_addr.s_net = ntohs(iface->address.s_net); /* We pass the Net:Node to the drivers/cards by a Device ioctl. */ - if (!(iface->dev->do_ioctl(iface->dev, &atreq, SIOCSIFADDR))) { - (void)iface->dev->do_ioctl(iface->dev, &atreq, SIOCGIFADDR); + if (!(ops->ndo_do_ioctl(iface->dev, &atreq, SIOCSIFADDR))) { + ops->ndo_do_ioctl(iface->dev, &atreq, SIOCGIFADDR); if (iface->address.s_net != htons(sa->sat_addr.s_net) || iface->address.s_node != sa->sat_addr.s_node) iface->status |= ATIF_PROBE_FAIL; -- cgit v1.2.3-70-g09d2 From b4d7f0a46bc0e30514b1779caff0fce6e424c4b5 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 7 Jan 2009 17:23:17 -0800 Subject: bluetooth: driver API update Convert to net_device_ops and use internal net_device_stats in bnep device. Note: no need for bnep_net_ioctl since if ioctl is not set, then dev_ifsioc handles it by returning -EOPNOTSUPP Signed-off-by: Stephen Hemminger Acked-by: Marcel Holtmann Signed-off-by: David S. Miller --- net/bluetooth/bnep/bnep.h | 1 - net/bluetooth/bnep/core.c | 12 ++++++------ net/bluetooth/bnep/netdev.c | 33 +++++++++++++-------------------- 3 files changed, 19 insertions(+), 27 deletions(-) (limited to 'net') diff --git a/net/bluetooth/bnep/bnep.h b/net/bluetooth/bnep/bnep.h index d20f8a40f36..0d9e506f5d5 100644 --- a/net/bluetooth/bnep/bnep.h +++ b/net/bluetooth/bnep/bnep.h @@ -165,7 +165,6 @@ struct bnep_session { struct socket *sock; struct net_device *dev; - struct net_device_stats stats; }; void bnep_net_setup(struct net_device *dev); diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 70fea8bdb4e..52a6ce0d772 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -306,7 +306,7 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) struct sk_buff *nskb; u8 type; - s->stats.rx_bytes += skb->len; + dev->stats.rx_bytes += skb->len; type = *(u8 *) skb->data; skb_pull(skb, 1); @@ -343,7 +343,7 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) * may not be modified and because of the alignment requirements. */ nskb = alloc_skb(2 + ETH_HLEN + skb->len, GFP_KERNEL); if (!nskb) { - s->stats.rx_dropped++; + dev->stats.rx_dropped++; kfree_skb(skb); return -ENOMEM; } @@ -378,14 +378,14 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) skb_copy_from_linear_data(skb, __skb_put(nskb, skb->len), skb->len); kfree_skb(skb); - s->stats.rx_packets++; + dev->stats.rx_packets++; nskb->ip_summed = CHECKSUM_NONE; nskb->protocol = eth_type_trans(nskb, dev); netif_rx_ni(nskb); return 0; badframe: - s->stats.rx_errors++; + dev->stats.rx_errors++; kfree_skb(skb); return 0; } @@ -448,8 +448,8 @@ send: kfree_skb(skb); if (len > 0) { - s->stats.tx_bytes += len; - s->stats.tx_packets++; + s->dev->stats.tx_bytes += len; + s->dev->stats.tx_packets++; return 0; } diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c index f897da6e044..d7a0e9722de 100644 --- a/net/bluetooth/bnep/netdev.c +++ b/net/bluetooth/bnep/netdev.c @@ -55,12 +55,6 @@ static int bnep_net_close(struct net_device *dev) return 0; } -static struct net_device_stats *bnep_net_get_stats(struct net_device *dev) -{ - struct bnep_session *s = netdev_priv(dev); - return &s->stats; -} - static void bnep_net_set_mc_list(struct net_device *dev) { #ifdef CONFIG_BT_BNEP_MC_FILTER @@ -128,11 +122,6 @@ static void bnep_net_timeout(struct net_device *dev) netif_wake_queue(dev); } -static int bnep_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - return -EINVAL; -} - #ifdef CONFIG_BT_BNEP_MC_FILTER static inline int bnep_net_mc_filter(struct sk_buff *skb, struct bnep_session *s) { @@ -217,6 +206,18 @@ static int bnep_net_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } +static const struct net_device_ops bnep_netdev_ops = { + .ndo_open = bnep_net_open, + .ndo_stop = bnep_net_close, + .ndo_start_xmit = bnep_net_xmit, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_multicast_list = bnep_net_set_mc_list, + .ndo_set_mac_address = bnep_net_set_mac_addr, + .ndo_tx_timeout = bnep_net_timeout, + .ndo_change_mtu = eth_change_mtu, + +}; + void bnep_net_setup(struct net_device *dev) { @@ -224,15 +225,7 @@ void bnep_net_setup(struct net_device *dev) dev->addr_len = ETH_ALEN; ether_setup(dev); - - dev->open = bnep_net_open; - dev->stop = bnep_net_close; - dev->hard_start_xmit = bnep_net_xmit; - dev->get_stats = bnep_net_get_stats; - dev->do_ioctl = bnep_net_ioctl; - dev->set_mac_address = bnep_net_set_mac_addr; - dev->set_multicast_list = bnep_net_set_mc_list; + dev->netdev_ops = &bnep_netdev_ops; dev->watchdog_timeo = HZ * 2; - dev->tx_timeout = bnep_net_timeout; } -- cgit v1.2.3-70-g09d2 From ab638e69ff7d4882ac152ada17eab340c93df080 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 7 Jan 2009 17:24:34 -0800 Subject: phonet: update to net_device_ops Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/usb/gadget/f_phonet.c | 12 ++++++++---- net/phonet/pep-gprs.c | 12 ++++++++---- 2 files changed, 16 insertions(+), 8 deletions(-) (limited to 'net') diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c index d8fc9b32fe3..c0916c7b217 100644 --- a/drivers/usb/gadget/f_phonet.c +++ b/drivers/usb/gadget/f_phonet.c @@ -279,6 +279,13 @@ static int pn_net_mtu(struct net_device *dev, int new_mtu) return err; } +static const struct net_device_ops pn_netdev_ops = { + .ndo_open = pn_net_open, + .ndo_stop = pn_net_close, + .ndo_start_xmit = pn_net_xmit, + .ndo_change_mtu = pn_net_mtu, +}; + static void pn_net_setup(struct net_device *dev) { dev->features = 0; @@ -290,12 +297,9 @@ static void pn_net_setup(struct net_device *dev) dev->addr_len = 1; dev->tx_queue_len = 1; + dev->netdev_ops = &pn_netdev_ops; dev->destructor = free_netdev; dev->header_ops = &phonet_header_ops; - dev->open = pn_net_open; - dev->stop = pn_net_close; - dev->hard_start_xmit = pn_net_xmit; /* mandatory */ - dev->change_mtu = pn_net_mtu; } /*-------------------------------------------------------------------------*/ diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c index b0ceac2d6cd..6a91a32a80c 100644 --- a/net/phonet/pep-gprs.c +++ b/net/phonet/pep-gprs.c @@ -227,6 +227,13 @@ static int gprs_set_mtu(struct net_device *dev, int new_mtu) return 0; } +static const struct net_device_ops gprs_netdev_ops = { + .ndo_open = gprs_open, + .ndo_stop = gprs_close, + .ndo_start_xmit = gprs_xmit, + .ndo_change_mtu = gprs_set_mtu, +}; + static void gprs_setup(struct net_device *dev) { dev->features = NETIF_F_FRAGLIST; @@ -237,11 +244,8 @@ static void gprs_setup(struct net_device *dev) dev->addr_len = 0; dev->tx_queue_len = 10; + dev->netdev_ops = &gprs_netdev_ops; dev->destructor = free_netdev; - dev->open = gprs_open; - dev->stop = gprs_close; - dev->hard_start_xmit = gprs_xmit; /* mandatory */ - dev->change_mtu = gprs_set_mtu; } /* -- cgit v1.2.3-70-g09d2 From c19a28e1193a6c854738d609ae9b2fe2f6e6bea4 Mon Sep 17 00:00:00 2001 From: Fernando Carrijo Date: Wed, 7 Jan 2009 18:09:08 -0800 Subject: remove lots of double-semicolons Cc: Ingo Molnar Cc: Thomas Gleixner Acked-by: Theodore Ts'o Acked-by: Mark Fasheh Acked-by: David S. Miller Cc: James Morris Acked-by: Casey Schaufler Acked-by: Takashi Iwai Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86/kernel/cpu/cpufreq/longhaul.c | 2 +- fs/ocfs2/alloc.c | 2 +- fs/ocfs2/file.c | 2 +- net/ipv6/route.c | 2 +- net/ipv6/sysctl_net_ipv6.c | 2 +- net/sched/sch_sfq.c | 2 +- security/smack/smackfs.c | 2 +- sound/soc/au1x/dbdma2.c | 2 +- sound/soc/davinci/davinci-pcm.c | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) (limited to 'net') diff --git a/arch/x86/kernel/cpu/cpufreq/longhaul.c b/arch/x86/kernel/cpu/cpufreq/longhaul.c index b0461856acf..a4cff5d6e38 100644 --- a/arch/x86/kernel/cpu/cpufreq/longhaul.c +++ b/arch/x86/kernel/cpu/cpufreq/longhaul.c @@ -982,7 +982,7 @@ static int __init longhaul_init(void) case 10: printk(KERN_ERR PFX "Use acpi-cpufreq driver for VIA C7\n"); default: - ;; + ; } return -ENODEV; diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 54ff4c77aaa..d861096c9d8 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -3868,7 +3868,7 @@ static void ocfs2_split_record(struct inode *inode, struct ocfs2_extent_list *left_el = NULL, *right_el, *insert_el, *el; struct ocfs2_extent_rec *rec, *tmprec; - right_el = path_leaf_el(right_path);; + right_el = path_leaf_el(right_path); if (left_path) left_el = path_leaf_el(left_path); diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index e8f795f978a..a5887df2cd8 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -1605,7 +1605,7 @@ int ocfs2_change_file_space(struct file *file, unsigned int cmd, struct ocfs2_space_resv *sr) { struct inode *inode = file->f_path.dentry->d_inode; - struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);; + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); if ((cmd == OCFS2_IOC_RESVSP || cmd == OCFS2_IOC_RESVSP64) && !ocfs2_writes_unwritten_extents(osb)) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 76f06b94ab9..c4a59824ac2 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2752,7 +2752,7 @@ int __init ip6_route_init(void) kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0, SLAB_HWCACHE_ALIGN, NULL); if (!ip6_dst_ops_template.kmem_cachep) - goto out;; + goto out; ret = register_pernet_subsys(&ip6_route_net_ops); if (ret) diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c index 9048fe7e7ea..a031034720b 100644 --- a/net/ipv6/sysctl_net_ipv6.c +++ b/net/ipv6/sysctl_net_ipv6.c @@ -128,7 +128,7 @@ static struct ctl_table_header *ip6_header; int ipv6_sysctl_register(void) { - int err = -ENOMEM;; + int err = -ENOMEM; ip6_header = register_net_sysctl_rotable(net_ipv6_ctl_path, ipv6_table); if (ip6_header == NULL) diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index f3965df0055..33133d27b53 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -435,7 +435,7 @@ static int sfq_init(struct Qdisc *sch, struct nlattr *opt) int i; q->perturb_timer.function = sfq_perturbation; - q->perturb_timer.data = (unsigned long)sch;; + q->perturb_timer.data = (unsigned long)sch; init_timer_deferrable(&q->perturb_timer); for (i = 0; i < SFQ_HASH_DIVISOR; i++) diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index bf107a389ac..71e2b914363 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -569,7 +569,7 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf, if (skp == NULL) goto out; - rule += SMK_LABELLEN;; + rule += SMK_LABELLEN; ret = sscanf(rule, "%d", &maplevel); if (ret != 1 || maplevel > SMACK_CIPSO_MAXLEVEL) goto out; diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c index 74c823d60f9..bc8d654576c 100644 --- a/sound/soc/au1x/dbdma2.c +++ b/sound/soc/au1x/dbdma2.c @@ -187,7 +187,7 @@ static int au1x_pcm_dbdma_realloc(struct au1xpsc_audio_dmadata *pcd, au1x_pcm_dmatx_cb, (void *)pcd); if (!pcd->ddma_chan) - return -ENOMEM;; + return -ENOMEM; au1xxx_dbdma_set_devwidth(pcd->ddma_chan, msbits); au1xxx_dbdma_ring_alloc(pcd->ddma_chan, 2); diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index 74abc9b4f1c..366049d8578 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c @@ -212,7 +212,7 @@ davinci_pcm_pointer(struct snd_pcm_substream *substream) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) count = src - runtime->dma_addr; else - count = dst - runtime->dma_addr;; + count = dst - runtime->dma_addr; spin_unlock(&prtd->lock); -- cgit v1.2.3-70-g09d2 From 73ac36ea14fd18ea3dc057e41b16ff31a3c0bd5a Mon Sep 17 00:00:00 2001 From: Coly Li Date: Wed, 7 Jan 2009 18:09:16 -0800 Subject: fix similar typos to successfull When I review ocfs2 code, find there are 2 typos to "successfull". After doing grep "successfull " in kernel tree, 22 typos found totally -- great minds always think alike :) This patch fixes all the similar typos. Thanks for Randy's ack and comments. Signed-off-by: Coly Li Acked-by: Randy Dunlap Acked-by: Roland Dreier Cc: Jeremy Kerr Cc: Jeff Garzik Cc: Heiko Carstens Cc: Martin Schwidefsky Cc: Theodore Ts'o Cc: Mark Fasheh Cc: Vlad Yasevich Cc: Sridhar Samudrala Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/hwmon/abituguru-datasheet | 4 ++-- Documentation/scsi/scsi_fc_transport.txt | 4 ++-- arch/powerpc/platforms/cell/spufs/spufs.h | 2 +- drivers/infiniband/hw/nes/nes_cm.c | 2 +- drivers/isdn/hardware/eicon/debuglib.h | 2 +- drivers/isdn/hardware/eicon/os_4bri.c | 2 +- drivers/isdn/hardware/eicon/os_bri.c | 2 +- drivers/isdn/hardware/eicon/os_pri.c | 2 +- drivers/mtd/ubi/kapi.c | 2 +- drivers/net/wireless/ath5k/dma.c | 2 +- drivers/net/wireless/zd1211rw/zd_mac.c | 2 +- drivers/s390/block/dasd_3990_erp.c | 2 +- drivers/s390/block/dasd_int.h | 2 +- drivers/s390/char/tape_3590.c | 2 +- drivers/s390/cio/cio.c | 2 +- drivers/s390/cio/qdio_main.c | 2 +- fs/ext4/extents.c | 2 +- fs/ocfs2/dlmglue.c | 4 ++-- net/sctp/auth.c | 2 +- 19 files changed, 22 insertions(+), 22 deletions(-) (limited to 'net') diff --git a/Documentation/hwmon/abituguru-datasheet b/Documentation/hwmon/abituguru-datasheet index 4d184f2db0e..d9251efdcec 100644 --- a/Documentation/hwmon/abituguru-datasheet +++ b/Documentation/hwmon/abituguru-datasheet @@ -121,7 +121,7 @@ Once all bytes have been read data will hold 0x09, but there is no reason to test for this. Notice that the number of bytes is bank address dependent see above and below. -After completing a successfull read it is advised to put the uGuru back in +After completing a successful read it is advised to put the uGuru back in ready mode, so that it is ready for the next read / write cycle. This way if your program / driver is unloaded and later loaded again the detection algorithm described above will still work. @@ -141,7 +141,7 @@ don't ask why this is the way it is. Once DATA holds 0x01 read CMD it should hold 0xAC now. -After completing a successfull write it is advised to put the uGuru back in +After completing a successful write it is advised to put the uGuru back in ready mode, so that it is ready for the next read / write cycle. This way if your program / driver is unloaded and later loaded again the detection algorithm described above will still work. diff --git a/Documentation/scsi/scsi_fc_transport.txt b/Documentation/scsi/scsi_fc_transport.txt index 38d324d62b2..e5b071d4661 100644 --- a/Documentation/scsi/scsi_fc_transport.txt +++ b/Documentation/scsi/scsi_fc_transport.txt @@ -191,7 +191,7 @@ Vport States: This is equivalent to a driver "attach" on an adapter, which is independent of the adapter's link state. - Instantiation of the vport on the FC link via ELS traffic, etc. - This is equivalent to a "link up" and successfull link initialization. + This is equivalent to a "link up" and successful link initialization. Further information can be found in the interfaces section below for Vport Creation. @@ -320,7 +320,7 @@ Vport Creation: This is equivalent to a driver "attach" on an adapter, which is independent of the adapter's link state. - Instantiation of the vport on the FC link via ELS traffic, etc. - This is equivalent to a "link up" and successfull link initialization. + This is equivalent to a "link up" and successful link initialization. The LLDD's vport_create() function will not synchronously wait for both parts to be fully completed before returning. It must validate that the diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 15c62d3ca12..3bf908e2873 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h @@ -314,7 +314,7 @@ extern char *isolated_loader; * we need to call spu_release(ctx) before sleeping, and * then spu_acquire(ctx) when awoken. * - * Returns with state_mutex re-acquired when successfull or + * Returns with state_mutex re-acquired when successful or * with -ERESTARTSYS and the state_mutex dropped when interrupted. */ diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index a812db24347..6ba57e91d7a 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -2705,7 +2705,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) sizeof(struct ietf_mpa_frame)); - /* notify OF layer that accept event was successfull */ + /* notify OF layer that accept event was successful */ cm_id->add_ref(cm_id); cm_event.event = IW_CM_EVENT_ESTABLISHED; diff --git a/drivers/isdn/hardware/eicon/debuglib.h b/drivers/isdn/hardware/eicon/debuglib.h index 016410cf227..8ea587783e1 100644 --- a/drivers/isdn/hardware/eicon/debuglib.h +++ b/drivers/isdn/hardware/eicon/debuglib.h @@ -235,7 +235,7 @@ typedef void ( * DbgOld) (unsigned short, char *, va_list) ; typedef void ( * DbgEv) (unsigned short, unsigned long, va_list) ; typedef void ( * DbgIrq) (unsigned short, int, char *, va_list) ; typedef struct _DbgHandle_ -{ char Registered ; /* driver successfull registered */ +{ char Registered ; /* driver successfully registered */ #define DBG_HANDLE_REG_NEW 0x01 /* this (new) structure */ #define DBG_HANDLE_REG_OLD 0x7f /* old structure (see below) */ char Version; /* version of this structure */ diff --git a/drivers/isdn/hardware/eicon/os_4bri.c b/drivers/isdn/hardware/eicon/os_4bri.c index 7b4ec3f60db..c964b8d91ad 100644 --- a/drivers/isdn/hardware/eicon/os_4bri.c +++ b/drivers/isdn/hardware/eicon/os_4bri.c @@ -997,7 +997,7 @@ diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter, diva_xdi_display_adapter_features(IoAdapter->ANum); for (i = 0; i < IoAdapter->tasks; i++) { - DBG_LOG(("A(%d) %s adapter successfull started", + DBG_LOG(("A(%d) %s adapter successfully started", IoAdapter->QuadroList->QuadroAdapter[i]->ANum, (IoAdapter->tasks == 1) ? "BRI 2.0" : "4BRI")) diva_xdi_didd_register_adapter(IoAdapter->QuadroList->QuadroAdapter[i]->ANum); diff --git a/drivers/isdn/hardware/eicon/os_bri.c b/drivers/isdn/hardware/eicon/os_bri.c index f31bba5b16f..08f01993f46 100644 --- a/drivers/isdn/hardware/eicon/os_bri.c +++ b/drivers/isdn/hardware/eicon/os_bri.c @@ -736,7 +736,7 @@ diva_bri_start_adapter(PISDN_ADAPTER IoAdapter, IoAdapter->Properties.Features = (word) features; diva_xdi_display_adapter_features(IoAdapter->ANum); - DBG_LOG(("A(%d) BRI adapter successfull started", IoAdapter->ANum)) + DBG_LOG(("A(%d) BRI adapter successfully started", IoAdapter->ANum)) /* Register with DIDD */ diff --git a/drivers/isdn/hardware/eicon/os_pri.c b/drivers/isdn/hardware/eicon/os_pri.c index 903356547b7..5d65405c75f 100644 --- a/drivers/isdn/hardware/eicon/os_pri.c +++ b/drivers/isdn/hardware/eicon/os_pri.c @@ -513,7 +513,7 @@ diva_pri_start_adapter(PISDN_ADAPTER IoAdapter, diva_xdi_display_adapter_features(IoAdapter->ANum); - DBG_LOG(("A(%d) PRI adapter successfull started", IoAdapter->ANum)) + DBG_LOG(("A(%d) PRI adapter successfully started", IoAdapter->ANum)) /* Register with DIDD */ diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c index 5d9bcf109c1..4abbe573fa4 100644 --- a/drivers/mtd/ubi/kapi.c +++ b/drivers/mtd/ubi/kapi.c @@ -564,7 +564,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_unmap); * @dtype: expected data type * * This function maps an un-mapped logical eraseblock @lnum to a physical - * eraseblock. This means, that after a successfull invocation of this + * eraseblock. This means, that after a successful invocation of this * function the logical eraseblock @lnum will be empty (contain only %0xFF * bytes) and be mapped to a physical eraseblock, even if an unclean reboot * happens. diff --git a/drivers/net/wireless/ath5k/dma.c b/drivers/net/wireless/ath5k/dma.c index 7e2b1a67e5d..b65b4feb2d2 100644 --- a/drivers/net/wireless/ath5k/dma.c +++ b/drivers/net/wireless/ath5k/dma.c @@ -594,7 +594,7 @@ int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) * XXX: BMISS interrupts may occur after association. * I found this on 5210 code but it needs testing. If this is * true we should disable them before assoc and re-enable them - * after a successfull assoc + some jiffies. + * after a successful assoc + some jiffies. interrupt_mask &= ~AR5K_INT_BMISS; */ } diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 9caa96a1358..a611ad85798 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -287,7 +287,7 @@ static void zd_op_stop(struct ieee80211_hw *hw) * @skb - a sk-buffer * @flags: extra flags to set in the TX status info * @ackssi: ACK signal strength - * @success - True for successfull transmission of the frame + * @success - True for successful transmission of the frame * * This information calls ieee80211_tx_status_irqsafe() if required by the * control information. It copies the control information into the status diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index b8f9c00633f..d82aad5224f 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c @@ -2621,7 +2621,7 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr) } } - /* double-check if current erp/cqr was successfull */ + /* double-check if current erp/cqr was successful */ if ((cqr->irb.scsw.cmd.cstat == 0x00) && (cqr->irb.scsw.cmd.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))) { diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 05a14536c36..4a39084d9c9 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -199,7 +199,7 @@ struct dasd_ccw_req { #define DASD_CQR_ERROR 0x82 /* request is completed with error */ #define DASD_CQR_CLEAR_PENDING 0x83 /* request is clear pending */ #define DASD_CQR_CLEARED 0x84 /* request was cleared */ -#define DASD_CQR_SUCCESS 0x85 /* request was successfull */ +#define DASD_CQR_SUCCESS 0x85 /* request was successful */ /* per dasd_ccw_req flags */ diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index 4005c44a404..71605a179d6 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c @@ -801,7 +801,7 @@ tape_3590_done(struct tape_device *device, struct tape_request *request) static inline int tape_3590_erp_succeded(struct tape_device *device, struct tape_request *request) { - DBF_EVENT(3, "Error Recovery successfull for %s\n", + DBF_EVENT(3, "Error Recovery successful for %s\n", tape_op_verbose[request->op]); return tape_3590_done(device, request); } diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 06b71823f39..659f8a79165 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -379,7 +379,7 @@ int cio_commit_config(struct subchannel *sch) if (ccode < 0) /* -EIO if msch gets a program check. */ return ccode; switch (ccode) { - case 0: /* successfull */ + case 0: /* successful */ if (stsch(sch->schid, &schib) || !css_sch_is_valid(&schib)) return -ENODEV; diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 744f928a59e..10cb0f8726e 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -114,7 +114,7 @@ static inline int qdio_check_ccq(struct qdio_q *q, unsigned int ccq) * @count: count of buffers to examine * @auto_ack: automatically acknowledge buffers * - * Returns the number of successfull extracted equal buffer states. + * Returns the number of successfully extracted equal buffer states. * Stops processing if a state is different from the last buffers state. */ static int qdio_do_eqbs(struct qdio_q *q, unsigned char *state, diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index ea2ce3c0ae6..3f54db31cdc 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2536,7 +2536,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, */ newdepth = ext_depth(inode); /* - * update the extent length after successfull insert of the + * update the extent length after successful insert of the * split extent */ orig_ex.ee_len = cpu_to_le16(ee_len - diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index f731ab49179..b0c4cadd4c4 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -1324,7 +1324,7 @@ again: goto out; } - mlog(0, "lock %s, successfull return from ocfs2_dlm_lock\n", + mlog(0, "lock %s, successful return from ocfs2_dlm_lock\n", lockres->l_name); /* At this point we've gone inside the dlm and need to @@ -2951,7 +2951,7 @@ static int ocfs2_drop_lock(struct ocfs2_super *osb, ocfs2_dlm_dump_lksb(&lockres->l_lksb); BUG(); } - mlog(0, "lock %s, successfull return from ocfs2_dlm_unlock\n", + mlog(0, "lock %s, successful return from ocfs2_dlm_unlock\n", lockres->l_name); ocfs2_wait_on_busy_lock(lockres); diff --git a/net/sctp/auth.c b/net/sctp/auth.c index 20c576f530f..56935bbc149 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c @@ -489,7 +489,7 @@ int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp) return 0; out_err: - /* Clean up any successfull allocations */ + /* Clean up any successful allocations */ sctp_auth_destroy_hmacs(ep->auth_hmacs); return -ENOMEM; } -- cgit v1.2.3-70-g09d2 From 787e9208360117835101f513f7db593dc2525cf8 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 8 Jan 2009 10:40:57 -0800 Subject: ipv6: Add GRO support This patch adds GRO support for IPv6. IPv6 GRO supports extension headers in the same way as GSO (by using the same infrastructure). It's also simpler compared to IPv4 since we no longer have to worry about fragmentation attributes or header checksums. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- include/net/protocol.h | 3 ++ net/ipv6/af_inet6.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 105 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/include/net/protocol.h b/include/net/protocol.h index cb2965aa1b6..ffa5b8b1f1d 100644 --- a/include/net/protocol.h +++ b/include/net/protocol.h @@ -59,6 +59,9 @@ struct inet6_protocol int (*gso_send_check)(struct sk_buff *skb); struct sk_buff *(*gso_segment)(struct sk_buff *skb, int features); + struct sk_buff **(*gro_receive)(struct sk_buff **head, + struct sk_buff *skb); + int (*gro_complete)(struct sk_buff *skb); unsigned int flags; /* INET6_PROTO_xxx */ }; diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 437b750b98f..94f74f5b0cb 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -672,8 +672,7 @@ int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb) EXPORT_SYMBOL_GPL(ipv6_opt_accepted); -static struct inet6_protocol *ipv6_gso_pull_exthdrs(struct sk_buff *skb, - int proto) +static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto) { struct inet6_protocol *ops = NULL; @@ -704,7 +703,7 @@ static struct inet6_protocol *ipv6_gso_pull_exthdrs(struct sk_buff *skb, __skb_pull(skb, len); } - return ops; + return proto; } static int ipv6_gso_send_check(struct sk_buff *skb) @@ -721,7 +720,9 @@ static int ipv6_gso_send_check(struct sk_buff *skb) err = -EPROTONOSUPPORT; rcu_read_lock(); - ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr); + ops = rcu_dereference(inet6_protos[ + ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr)]); + if (likely(ops && ops->gso_send_check)) { skb_reset_transport_header(skb); err = ops->gso_send_check(skb); @@ -757,7 +758,9 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features) segs = ERR_PTR(-EPROTONOSUPPORT); rcu_read_lock(); - ops = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr); + ops = rcu_dereference(inet6_protos[ + ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr)]); + if (likely(ops && ops->gso_segment)) { skb_reset_transport_header(skb); segs = ops->gso_segment(skb, features); @@ -777,11 +780,105 @@ out: return segs; } +struct ipv6_gro_cb { + struct napi_gro_cb napi; + int proto; +}; + +#define IPV6_GRO_CB(skb) ((struct ipv6_gro_cb *)(skb)->cb) + +static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, + struct sk_buff *skb) +{ + struct inet6_protocol *ops; + struct sk_buff **pp = NULL; + struct sk_buff *p; + struct ipv6hdr *iph; + unsigned int nlen; + int flush = 1; + int proto; + + if (unlikely(!pskb_may_pull(skb, sizeof(*iph)))) + goto out; + + iph = ipv6_hdr(skb); + __skb_pull(skb, sizeof(*iph)); + + flush += ntohs(iph->payload_len) != skb->len; + + rcu_read_lock(); + proto = ipv6_gso_pull_exthdrs(skb, iph->nexthdr); + IPV6_GRO_CB(skb)->proto = proto; + ops = rcu_dereference(inet6_protos[proto]); + if (!ops || !ops->gro_receive) + goto out_unlock; + + flush--; + skb_reset_transport_header(skb); + nlen = skb_network_header_len(skb); + + for (p = *head; p; p = p->next) { + struct ipv6hdr *iph2; + + if (!NAPI_GRO_CB(p)->same_flow) + continue; + + iph2 = ipv6_hdr(p); + + /* All fields must match except length. */ + if (nlen != skb_network_header_len(p) || + memcmp(iph, iph2, offsetof(struct ipv6hdr, payload_len)) || + memcmp(&iph->nexthdr, &iph2->nexthdr, + nlen - offsetof(struct ipv6hdr, nexthdr))) { + NAPI_GRO_CB(p)->same_flow = 0; + continue; + } + + NAPI_GRO_CB(p)->flush |= flush; + } + + NAPI_GRO_CB(skb)->flush |= flush; + + pp = ops->gro_receive(head, skb); + +out_unlock: + rcu_read_unlock(); + +out: + NAPI_GRO_CB(skb)->flush |= flush; + + return pp; +} + +static int ipv6_gro_complete(struct sk_buff *skb) +{ + struct inet6_protocol *ops; + struct ipv6hdr *iph = ipv6_hdr(skb); + int err = -ENOSYS; + + iph->payload_len = htons(skb->len - skb_network_offset(skb) - + sizeof(*iph)); + + rcu_read_lock(); + ops = rcu_dereference(inet6_protos[IPV6_GRO_CB(skb)->proto]); + if (WARN_ON(!ops || !ops->gro_complete)) + goto out_unlock; + + err = ops->gro_complete(skb); + +out_unlock: + rcu_read_unlock(); + + return err; +} + static struct packet_type ipv6_packet_type = { .type = __constant_htons(ETH_P_IPV6), .func = ipv6_rcv, .gso_send_check = ipv6_gso_send_check, .gso_segment = ipv6_gso_segment, + .gro_receive = ipv6_gro_receive, + .gro_complete = ipv6_gro_complete, }; static int __init ipv6_packet_init(void) -- cgit v1.2.3-70-g09d2 From 684f2176015b313ab59cecf574117969cf638f28 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 8 Jan 2009 10:41:23 -0800 Subject: tcp6: Add GRO support This patch adds GRO support for TCP over IPv6. The code is exactly the same as the IPv4 version except for the pseudo-header checksum computation. Note that I've removed the unused tcphdr argument from tcp_v6_check rather than invent a bogus value for GRO. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv4/tcp.c | 2 ++ net/ipv6/tcp_ipv6.c | 45 +++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 43 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 35bcddf8a93..bd6ff907d9e 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2542,6 +2542,7 @@ out: return pp; } +EXPORT_SYMBOL(tcp_gro_receive); int tcp_gro_complete(struct sk_buff *skb) { @@ -2558,6 +2559,7 @@ int tcp_gro_complete(struct sk_buff *skb) return 0; } +EXPORT_SYMBOL(tcp_gro_complete); #ifdef CONFIG_TCP_MD5SIG static unsigned long tcp_md5sig_users; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index e8b8337a831..1297306d729 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -101,7 +101,7 @@ static void tcp_v6_hash(struct sock *sk) } } -static __inline__ __sum16 tcp_v6_check(struct tcphdr *th, int len, +static __inline__ __sum16 tcp_v6_check(int len, struct in6_addr *saddr, struct in6_addr *daddr, __wsum base) @@ -501,7 +501,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req) if (skb) { struct tcphdr *th = tcp_hdr(skb); - th->check = tcp_v6_check(th, skb->len, + th->check = tcp_v6_check(skb->len, &treq->loc_addr, &treq->rmt_addr, csum_partial(th, skb->len, skb->csum)); @@ -942,6 +942,41 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb) return 0; } +struct sk_buff **tcp6_gro_receive(struct sk_buff **head, struct sk_buff *skb) +{ + struct ipv6hdr *iph = ipv6_hdr(skb); + + switch (skb->ip_summed) { + case CHECKSUM_COMPLETE: + if (!tcp_v6_check(skb->len, &iph->saddr, &iph->daddr, + skb->csum)) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + break; + } + + /* fall through */ + case CHECKSUM_NONE: + NAPI_GRO_CB(skb)->flush = 1; + return NULL; + } + + return tcp_gro_receive(head, skb); +} +EXPORT_SYMBOL(tcp6_gro_receive); + +int tcp6_gro_complete(struct sk_buff *skb) +{ + struct ipv6hdr *iph = ipv6_hdr(skb); + struct tcphdr *th = tcp_hdr(skb); + + th->check = ~tcp_v6_check(skb->len - skb_transport_offset(skb), + &iph->saddr, &iph->daddr, 0); + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; + + return tcp_gro_complete(skb); +} +EXPORT_SYMBOL(tcp6_gro_complete); + static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts, struct tcp_md5sig_key *key, int rst) { @@ -1429,14 +1464,14 @@ out: static __sum16 tcp_v6_checksum_init(struct sk_buff *skb) { if (skb->ip_summed == CHECKSUM_COMPLETE) { - if (!tcp_v6_check(tcp_hdr(skb), skb->len, &ipv6_hdr(skb)->saddr, + if (!tcp_v6_check(skb->len, &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, skb->csum)) { skb->ip_summed = CHECKSUM_UNNECESSARY; return 0; } } - skb->csum = ~csum_unfold(tcp_v6_check(tcp_hdr(skb), skb->len, + skb->csum = ~csum_unfold(tcp_v6_check(skb->len, &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, 0)); @@ -2062,6 +2097,8 @@ static struct inet6_protocol tcpv6_protocol = { .err_handler = tcp_v6_err, .gso_send_check = tcp_v6_gso_send_check, .gso_segment = tcp_tso_segment, + .gro_receive = tcp6_gro_receive, + .gro_complete = tcp6_gro_complete, .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, }; -- cgit v1.2.3-70-g09d2 From cc883d16c3b7434c7da2c45b54a49c2a99e83db7 Mon Sep 17 00:00:00 2001 From: Frank Blaschka Date: Thu, 8 Jan 2009 10:50:20 -0800 Subject: vlan: add neigh_setup In case the real device has a neigh_setup function, this neigh_setup function should be used for the vlan device. Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- net/8021q/vlan_dev.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'net') diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 89a3bbdfca3..4a19acd3a32 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -546,6 +546,18 @@ static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return err; } +static int vlan_dev_neigh_setup(struct net_device *dev, struct neigh_parms *pa) +{ + struct net_device *real_dev = vlan_dev_info(dev)->real_dev; + const struct net_device_ops *ops = real_dev->netdev_ops; + int err = 0; + + if (netif_device_present(real_dev) && ops->ndo_neigh_setup) + err = ops->ndo_neigh_setup(dev, pa); + + return err; +} + static void vlan_dev_change_rx_flags(struct net_device *dev, int change) { struct net_device *real_dev = vlan_dev_info(dev)->real_dev; @@ -713,6 +725,7 @@ static const struct net_device_ops vlan_netdev_ops = { .ndo_set_multicast_list = vlan_dev_set_rx_mode, .ndo_change_rx_flags = vlan_dev_change_rx_flags, .ndo_do_ioctl = vlan_dev_ioctl, + .ndo_neigh_setup = vlan_dev_neigh_setup, }; static const struct net_device_ops vlan_netdev_accel_ops = { @@ -728,6 +741,7 @@ static const struct net_device_ops vlan_netdev_accel_ops = { .ndo_set_multicast_list = vlan_dev_set_rx_mode, .ndo_change_rx_flags = vlan_dev_change_rx_flags, .ndo_do_ioctl = vlan_dev_ioctl, + .ndo_neigh_setup = vlan_dev_neigh_setup, }; void vlan_setup(struct net_device *dev) -- cgit v1.2.3-70-g09d2 From d48e470f76887d0befe025049158aeb6c1219d71 Mon Sep 17 00:00:00 2001 From: Inaky Perez-Gonzalez Date: Thu, 8 Jan 2009 11:06:48 -0800 Subject: wimax: fix '#ifndef CONFIG_BUG' layout to avoid warning Reported by Randy Dunlap: > Also, this warning needs to be fixed: > > linux-next-20090106/net/wimax/id-table.c:133: warning: ISO C90 > forbids mixed declarations and code Move the return on #defined(CONFIG_BUG) below the variable declarations so it doesn't violate ISO C90. On wimax_id_table_release() we want to do a debug check if CONFIG_BUG is enabled. However, we also want the debug code to be always compiled to ensure there is no bitrot. It will be optimized out by the compiler when CONFIG_BUG is disabled. Added a note to the function header stating this. Signed-off-by: Inaky Perez-Gonzalez Signed-off-by: David S. Miller --- net/wimax/id-table.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/wimax/id-table.c b/net/wimax/id-table.c index d3b88558682..5e685f7eda9 100644 --- a/net/wimax/id-table.c +++ b/net/wimax/id-table.c @@ -123,15 +123,17 @@ void wimax_id_table_rm(struct wimax_dev *wimax_dev) /* * Release the gennetlink family id / mapping table * - * On debug, verify that the table is empty upon removal. + * On debug, verify that the table is empty upon removal. We want the + * code always compiled, to ensure it doesn't bit rot. It will be + * compiled out if CONFIG_BUG is disabled. */ void wimax_id_table_release(void) { + struct wimax_dev *wimax_dev; + #ifndef CONFIG_BUG return; #endif - struct wimax_dev *wimax_dev; - spin_lock(&wimax_id_table_lock); list_for_each_entry(wimax_dev, &wimax_id_table, id_table_node) { printk(KERN_ERR "BUG: %s wimax_dev %p ifindex %d not cleared\n", -- cgit v1.2.3-70-g09d2 From 71f78afd67ca51d3656ba45aea293d6e2a27c8bc Mon Sep 17 00:00:00 2001 From: Inaky Perez-Gonzalez Date: Thu, 8 Jan 2009 11:07:36 -0800 Subject: wimax: fix kconfig interactions with rfkill and input layers WiMAX can work without RFKILL, but it was missing a check to make sure RFKILL is not being made a module with wimax compiled into the kernel. This caused failed builds in s390, where CONFIG_INPUT is always off. When RFKILL is enabled, the code uses the input layer to report hardware switch changes; thus, if RFKILL is enabled, INPUT has to be too. It also needs to display some message when INPUT is disabled that explains why WiMAX is not selectable. (issues found by Randy Dunlap in the linux-next tree). Signed-off-by: Inaky Perez-Gonzalez Signed-off-by: David S. Miller --- net/wimax/Kconfig | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'net') diff --git a/net/wimax/Kconfig b/net/wimax/Kconfig index 0bdbb692820..18495cdcd10 100644 --- a/net/wimax/Kconfig +++ b/net/wimax/Kconfig @@ -1,9 +1,23 @@ # # WiMAX LAN device configuration # +# Note the ugly 'depends on' on WIMAX: that disallows RFKILL to be a +# module if WIMAX is to be linked in. The WiMAX code is done in such a +# way that it doesn't require and explicit dependency on RFKILL in +# case an embedded system wants to rip it out. +# +# As well, enablement of the RFKILL code means we need the INPUT layer +# support to inject events coming from hw rfkill switches. That +# dependency could be killed if input.h provided appropiate means to +# work when input is disabled. + +comment "WiMAX Wireless Broadband support requires CONFIG_INPUT enabled" + depends on INPUT = n && RFKILL != n menuconfig WIMAX tristate "WiMAX Wireless Broadband support" + depends on (y && RFKILL != m) || m + depends on (INPUT && RFKILL != n) || RFKILL = n help Select to configure support for devices that provide -- cgit v1.2.3-70-g09d2 From a2e9da4b09c99857080afd2e8143f70bc03ebe9b Mon Sep 17 00:00:00 2001 From: Inaky Perez-Gonzalez Date: Thu, 8 Jan 2009 11:08:01 -0800 Subject: wimax: testing for rfkill support should also test for CONFIG_RFKILL_MODULE Current WiMAX rfkill code is missing the case where rfkill is compiled in as modules and works only when rfkill is compiled in. This is not correct. Fixed to test for CONFIG_RFKILL or CONFIG_RKILL_MODULE. Signed-off-by: Inaky Perez-Gonzalez Signed-off-by: David S. Miller --- net/wimax/op-rfkill.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/wimax/op-rfkill.c b/net/wimax/op-rfkill.c index 8745bac173f..2b75aee0421 100644 --- a/net/wimax/op-rfkill.c +++ b/net/wimax/op-rfkill.c @@ -71,7 +71,7 @@ #define D_SUBMODULE op_rfkill #include "debug-levels.h" -#ifdef CONFIG_RFKILL +#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) /** -- cgit v1.2.3-70-g09d2 From 9498c05820580afbf03a317b0b5bdb0ca0e27e40 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 8 Jan 2009 21:27:06 +0000 Subject: ipcomp: Remove spurious truesize increase When I made ipcomp use frags, I forgot to take out the original truesize update that was added for pskb_expand_head. As we no longer expand the head of skb, that update should have been removed. This bug is not related to the truesize warnings since we only made it bigger than what it should've been. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/xfrm/xfrm_ipcomp.c | 1 - 1 file changed, 1 deletion(-) (limited to 'net') diff --git a/net/xfrm/xfrm_ipcomp.c b/net/xfrm/xfrm_ipcomp.c index c609a4b98e1..42cd18391f4 100644 --- a/net/xfrm/xfrm_ipcomp.c +++ b/net/xfrm/xfrm_ipcomp.c @@ -63,7 +63,6 @@ static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb) if (len > skb_tailroom(skb)) len = skb_tailroom(skb); - skb->truesize += len; __skb_put(skb, len); len += plen; -- cgit v1.2.3-70-g09d2 From 6c614a50206ee56c21b34cc02d0bd40e756db87e Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 9 Jan 2009 10:22:21 +0000 Subject: net/tipc/bcast.h: use ARRAY_SIZE ARRAY_SIZE is more concise to use when the size of an array is divided by the size of its type or the size of its first element. The semantic patch that makes this change is as follows: (http://www.emn.fr/x-info/coccinelle/) // @i@ @@ #include @depends on i using "paren.iso"@ type T; T[] E; @@ - (sizeof(E)/sizeof(T)) + ARRAY_SIZE(E) // Signed-off-by: Julia Lawall Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- net/tipc/bcast.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index 5aa024b99c5..2f2d731bc1c 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h @@ -124,7 +124,7 @@ static inline int tipc_nmap_equal(struct tipc_node_map *nm_a, struct tipc_node_m static inline void tipc_nmap_diff(struct tipc_node_map *nm_a, struct tipc_node_map *nm_b, struct tipc_node_map *nm_diff) { - int stop = sizeof(nm_a->map) / sizeof(u32); + int stop = ARRAY_SIZE(nm_a->map); int w; int b; u32 map; -- cgit v1.2.3-70-g09d2 From f3d8b2e467da7a9237a45248ff03b56b6a7c3df7 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 9 Jan 2009 10:22:22 +0000 Subject: net/bridge/netfilter: move a dereference below a NULL test In each case, if the NULL test is necessary, then the dereference should be moved below the NULL test. The semantic patch that makes this change is as follows: (http://www.emn.fr/x-info/coccinelle/) // @@ type T; expression E; identifier i,fld; statement S; @@ - T i = E->fld; + T i; ... when != E when != i if (E == NULL) S + i = E->fld; // Signed-off-by: Julia Lawall Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- net/bridge/netfilter/ebtables.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index fa108c46e85..8a8743d7d6e 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -85,12 +85,13 @@ static inline int ebt_do_match (struct ebt_entry_match *m, static inline int ebt_dev_check(char *entry, const struct net_device *device) { int i = 0; - const char *devname = device->name; + const char *devname; if (*entry == '\0') return 0; if (!device) return 1; + devname = device->name; /* 1 is the wildcard token */ while (entry[i] != '\0' && entry[i] != 1 && entry[i] == devname[i]) i++; -- cgit v1.2.3-70-g09d2 From 1b6725dea766b7437d885661140b6e0340d47613 Mon Sep 17 00:00:00 2001 From: Leonardo Potenza Date: Fri, 9 Jan 2009 23:06:28 -0800 Subject: net: fix section mismatch warnings in dccp/ccids/lib/tfrc.c Removed the __exit annotation of tfrc_lib_exit(), in order to suppress the following section mismatch messages: WARNING: net/dccp/dccp.o(.text+0xd9): Section mismatch in reference from the function ccid_cleanup_builtins() to the function .exit.text:tfrc_lib_exit() The function ccid_cleanup_builtins() references a function in an exit section. Often the function tfrc_lib_exit() has valid usage outside the exit section and the fix is to remove the __exit annotation of tfrc_lib_exit. WARNING: net/dccp/dccp.o(.init.text+0x48): Section mismatch in reference from the function ccid_initialize_builtins() to the function .exit.text:tfrc_lib_exit() The function __init ccid_initialize_builtins() references a function __exit tfrc_lib_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __exit annotation of tfrc_lib_exit() so it may be used outside an exit section. Signed-off-by: Leonardo Potenza Acked-by: Arnaldo Carvalho de Melo Acked-by: Gerrit Renker Signed-off-by: David S. Miller --- net/dccp/ccids/lib/tfrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/dccp/ccids/lib/tfrc.c b/net/dccp/ccids/lib/tfrc.c index 60c412ccfee..4902029854d 100644 --- a/net/dccp/ccids/lib/tfrc.c +++ b/net/dccp/ccids/lib/tfrc.c @@ -36,7 +36,7 @@ out: return rc; } -void __exit tfrc_lib_exit(void) +void tfrc_lib_exit(void) { tfrc_rx_packet_history_exit(); tfrc_tx_packet_history_exit(); -- cgit v1.2.3-70-g09d2 From 4dbc242ed3c94ff1cc10640d2119279ba0be943e Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Sun, 11 Jan 2009 00:17:22 -0800 Subject: dccp ccid-3: Fix RFC reference Thanks to Wei and Arnaldo for pointing out the correct new reference for CCID-3. Signed-off-by: Gerrit Renker Signed-off-by: David S. Miller --- net/dccp/ccids/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/dccp/ccids/Kconfig b/net/dccp/ccids/Kconfig index b28bf962edc..4b5db44970a 100644 --- a/net/dccp/ccids/Kconfig +++ b/net/dccp/ccids/Kconfig @@ -29,7 +29,7 @@ config IP_DCCP_CCID3 http://www.ietf.org/rfc/rfc4342.txt The TFRC congestion control algorithms were initially described in - RFC 5448. + RFC 5348. This text was extracted from RFC 4340 (sec. 10.2), http://www.ietf.org/rfc/rfc4340.txt -- cgit v1.2.3-70-g09d2 From 649274d993212e7c23c0cb734572c2311c200872 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 11 Jan 2009 00:20:39 -0800 Subject: net_dma: acquire/release dma channels on ifup/ifdown The recent dmaengine rework removed the capability to remove dma device driver modules while net_dma is active. Rather than notify dmaengine-clients that channels are trying to be removed, we now rely on clients to notify dmaengine when they no longer have a need for channels. Teach net_dma to release channels by taking dmaengine references at netdevice open and dropping references at netdevice close. Acked-by: Maciej Sosnowski Signed-off-by: Dan Williams Signed-off-by: David S. Miller --- include/linux/dmaengine.h | 10 ++++++++++ net/core/dev.c | 13 ++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 64dea2ab326..c73f1e2b59b 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -270,8 +270,18 @@ struct dma_device { /* --- public DMA engine API --- */ +#ifdef CONFIG_DMA_ENGINE void dmaengine_get(void); void dmaengine_put(void); +#else +static inline void dmaengine_get(void) +{ +} +static inline void dmaengine_put(void) +{ +} +#endif + dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest, void *src, size_t len); dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan, diff --git a/net/core/dev.c b/net/core/dev.c index 5f736f1ceea..b715a55cccc 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1087,6 +1087,11 @@ int dev_open(struct net_device *dev) */ dev->flags |= IFF_UP; + /* + * Enable NET_DMA + */ + dmaengine_get(); + /* * Initialize multicasting status */ @@ -1164,6 +1169,11 @@ int dev_close(struct net_device *dev) */ call_netdevice_notifiers(NETDEV_DOWN, dev); + /* + * Shutdown NET_DMA + */ + dmaengine_put(); + return 0; } @@ -5151,9 +5161,6 @@ static int __init net_dev_init(void) hotcpu_notifier(dev_cpu_callback, 0); dst_init(); dev_mcast_init(); - #ifdef CONFIG_NET_DMA - dmaengine_get(); - #endif rc = 0; out: return rc; -- cgit v1.2.3-70-g09d2