All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] KVM: booke: Do Not start decrementer when SPRN_DEC set 0
From: Alexander Graf @ 2011-10-23 21:46 UTC (permalink / raw)
  To: kvm-ppc
In-Reply-To: <1318909023-31003-1-git-send-email-bharat.bhushan@freescale.com>


On 20.10.2011, at 17:55, Bhushan Bharat-R65777 <R65777@freescale.com> wrote:

> 
> 
>> -----Original Message-----
>> From: Alexander Graf [mailto:agraf@suse.de]
>> Sent: Thursday, October 20, 2011 11:15 PM
>> To: Bhushan Bharat-R65777
>> Cc: kvm-ppc@vger.kernel.org; bharatb.yadav@gmail.com
>> Subject: Re: [PATCH] KVM: booke: Do Not start decrementer when SPRN_DEC
>> set 0
>> 
>> 
>> On 20.10.2011, at 10:43, Bhushan Bharat-R65777 wrote:
>> 
>>> 
>>> 
>>>> -----Original Message-----
>>>> From: kvm-ppc-owner@vger.kernel.org [mailto:kvm-ppc-
>>>> owner@vger.kernel.org] On Behalf Of Alexander Graf
>>>> Sent: Thursday, October 20, 2011 10:40 PM
>>>> To: Bhushan Bharat-R65777
>>>> Cc: kvm-ppc@vger.kernel.org; bharatb.yadav@gmail.com; Bhushan Bharat-
>>>> R65777
>>>> Subject: Re: [PATCH] KVM: booke: Do Not start decrementer when
>>>> SPRN_DEC set 0
>>>> 
>>>> 
>>>> On 17.10.2011, at 20:37, Bharat Bhushan wrote:
>>>> 
>>>>> As per specification the decrementer interrupt not happen when DEC
>>>>> is
>>>> written with 0. So we should not start hrtimer with timeout = 0 as
>> well.
>>>>> 
>>>>> Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com>
>>>>> ---
>>>>> arch/powerpc/kvm/emulate.c |    8 ++++----
>>>>> 1 files changed, 4 insertions(+), 4 deletions(-)
>>>>> 
>>>>> diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
>>>>> index 141dce3..8af3bad 100644
>>>>> --- a/arch/powerpc/kvm/emulate.c
>>>>> +++ b/arch/powerpc/kvm/emulate.c
>>>>> @@ -70,14 +70,14 @@
>>>>> #define OP_STHU 45
>>>>> 
>>>>> #ifdef CONFIG_PPC_BOOK3S
>>>>> -static int kvmppc_dec_enabled(struct kvm_vcpu *vcpu)
>>>>> +static bool kvmppc_dec_enabled(struct kvm_vcpu *vcpu)
>>>>> {
>>>>> -    return 1;
>>>>> +    return true;
>>>> 
>>>> It's not necessary to change it to bool. The function will be inlined
>>>> anyways.
>>>> 
>>>>> }
>>>>> #else
>>>>> -static int kvmppc_dec_enabled(struct kvm_vcpu *vcpu)
>>>>> +static bool kvmppc_dec_enabled(struct kvm_vcpu *vcpu)
>>>>> {
>>>>> -    return vcpu->arch.tcr & TCR_DIE;
>>>>> +    return (vcpu->arch.tcr & TCR_DIE) && !vcpu->arch.dec;
>>>> 
>>>> This means we declare the dec as enabled only when dec=0, no?
>>> 
>>> I think we can change the name of this function as
>> kvmppc_dec_runnable() ?
>> 
>> It'd still be wrong. You're declaring the DEC as running when dec = 0,
>> not when dec != 0.
> 
> That I have to anyway fix, 
> I mean like this:
> 
> bool kvmppc_dec_runnable(struct kvm_vcpu *vcpu)

Sorry for the late reply. Please keep your patch as little intrusive as possible. Changing the name doesn't quite buy us anything atm, so please limit your patch to the actual fix :)

Alex

> {
>     return (vcpu->arch.tcr & TCR_DIE) && vcpu->arch.dec;
> }
> 
> Thanks
> -Bharat
> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [patch net-next V2] net: introduce ethernet teaming device
From: Or Gerlitz @ 2011-10-23 21:46 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: netdev, davem, eric.dumazet, bhutchings, shemminger, fubar, andy,
	tgraf, ebiederm, mirqus, kaber, greearb, jesse, fbl,
	benjamin.poirier, jzupka
In-Reply-To: <1319200747-2508-1-git-send-email-jpirko@redhat.com>

On Fri, Oct 21, 2011 at 2:39 PM, Jiri Pirko <jpirko@redhat.com> wrote:
> This patch introduces new network device called team. It supposes to be
> very fast, simple, userspace-driven alternative to existing bonding driver.

Jiri,

Could you elaborate a little further on the motivation for this
teaming approach/solution vs. the current bonding driver? You say that
it suppose to be very fast, simple  and user space driven, so... do
you find bonding not to be fast enough? or too complex? or the fact
that bonding's driving logic being in the kernel is something you
prefer to see in user-space? anything else?

thanks,

Or.


>
> Userspace library called libteam with couple of demo apps is available
> here:
> https://github.com/jpirko/libteam
> Note it's still in its dipers atm.
>
> team<->libteam use generic netlink for communication. That and rtnl
> suppose to be the only way to configure team device, no sysfs etc.
>
> Python binding basis for libteam was recently introduced (some need
> still need to be done on it though). Daemon providing arpmon/miimon
> active-backup functionality will be introduced shortly.
> All what's necessary is already implemented in kernel team driver.
>
> Signed-off-by: Jiri Pirko <jpirko@redhat.com>
>
> v1->v2:
>        - modes are made as modules. Makes team more modular and
>          extendable.
>        - several commenters' nitpicks found on v1 were fixed
>        - several other bugs were fixed.
>        - note I ignored Eric's comment about roundrobin port selector
>          as Eric's way may be easily implemented as another mode (mode
>          "random") in future.
> ---
>  Documentation/networking/team.txt         |    2 +
>  MAINTAINERS                               |    7 +
>  drivers/net/Kconfig                       |    2 +
>  drivers/net/Makefile                      |    1 +
>  drivers/net/team/Kconfig                  |   38 +
>  drivers/net/team/Makefile                 |    7 +
>  drivers/net/team/team.c                   | 1593 +++++++++++++++++++++++++++++
>  drivers/net/team/team_mode_activebackup.c |  152 +++
>  drivers/net/team/team_mode_roundrobin.c   |  107 ++
>  include/linux/Kbuild                      |    1 +
>  include/linux/if.h                        |    1 +
>  include/linux/if_team.h                   |  233 +++++
>  12 files changed, 2144 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/networking/team.txt
>  create mode 100644 drivers/net/team/Kconfig
>  create mode 100644 drivers/net/team/Makefile
>  create mode 100644 drivers/net/team/team.c
>  create mode 100644 drivers/net/team/team_mode_activebackup.c
>  create mode 100644 drivers/net/team/team_mode_roundrobin.c
>  create mode 100644 include/linux/if_team.h
>
> diff --git a/Documentation/networking/team.txt b/Documentation/networking/team.txt
> new file mode 100644
> index 0000000..5a01368
> --- /dev/null
> +++ b/Documentation/networking/team.txt
> @@ -0,0 +1,2 @@
> +Team devices are driven from userspace via libteam library which is here:
> +       https://github.com/jpirko/libteam
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 5008b08..c33400d 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -6372,6 +6372,13 @@ W:       http://tcp-lp-mod.sourceforge.net/
>  S:     Maintained
>  F:     net/ipv4/tcp_lp.c
>
> +TEAM DRIVER
> +M:     Jiri Pirko <jpirko@redhat.com>
> +L:     netdev@vger.kernel.org
> +S:     Supported
> +F:     drivers/net/team/
> +F:     include/linux/if_team.h
> +
>  TEGRA SUPPORT
>  M:     Colin Cross <ccross@android.com>
>  M:     Erik Gilling <konkers@android.com>
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index 583f66c..b3020be 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -125,6 +125,8 @@ config IFB
>          'ifb1' etc.
>          Look at the iproute2 documentation directory for usage etc
>
> +source "drivers/net/team/Kconfig"
> +
>  config MACVLAN
>        tristate "MAC-VLAN support (EXPERIMENTAL)"
>        depends on EXPERIMENTAL
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index fa877cd..4e4ebfe 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -17,6 +17,7 @@ obj-$(CONFIG_NET) += Space.o loopback.o
>  obj-$(CONFIG_NETCONSOLE) += netconsole.o
>  obj-$(CONFIG_PHYLIB) += phy/
>  obj-$(CONFIG_RIONET) += rionet.o
> +obj-$(CONFIG_NET_TEAM) += team/
>  obj-$(CONFIG_TUN) += tun.o
>  obj-$(CONFIG_VETH) += veth.o
>  obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
> diff --git a/drivers/net/team/Kconfig b/drivers/net/team/Kconfig
> new file mode 100644
> index 0000000..70a43a6
> --- /dev/null
> +++ b/drivers/net/team/Kconfig
> @@ -0,0 +1,38 @@
> +menuconfig NET_TEAM
> +       tristate "Ethernet team driver support (EXPERIMENTAL)"
> +       depends on EXPERIMENTAL
> +       ---help---
> +         This allows one to create virtual interfaces that teams together
> +         multiple ethernet devices.
> +
> +         Team devices can be added using the "ip" command from the
> +         iproute2 package:
> +
> +         "ip link add link [ address MAC ] [ NAME ] type team"
> +
> +         To compile this driver as a module, choose M here: the module
> +         will be called team.
> +
> +if NET_TEAM
> +
> +config NET_TEAM_MODE_ROUNDROBIN
> +       tristate "Round-robin mode support"
> +       depends on NET_TEAM
> +       ---help---
> +         Basic mode where port used for transmitting packets is selected in
> +         round-robin fashion using packet counter.
> +
> +         To compile this team mode as a module, choose M here: the module
> +         will be called team_mode_roundrobin.
> +
> +config NET_TEAM_MODE_ACTIVEBACKUP
> +       tristate "Active-backup mode support"
> +       depends on NET_TEAM
> +       ---help---
> +         Only one port is active at a time and the rest of ports are used
> +         for backup.
> +
> +         To compile this team mode as a module, choose M here: the module
> +         will be called team_mode_activebackup.
> +
> +endif # NET_TEAM
> diff --git a/drivers/net/team/Makefile b/drivers/net/team/Makefile
> new file mode 100644
> index 0000000..85f2028
> --- /dev/null
> +++ b/drivers/net/team/Makefile
> @@ -0,0 +1,7 @@
> +#
> +# Makefile for the network team driver
> +#
> +
> +obj-$(CONFIG_NET_TEAM) += team.o
> +obj-$(CONFIG_NET_TEAM_MODE_ROUNDROBIN) += team_mode_roundrobin.o
> +obj-$(CONFIG_NET_TEAM_MODE_ACTIVEBACKUP) += team_mode_activebackup.o
> diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
> new file mode 100644
> index 0000000..398be58
> --- /dev/null
> +++ b/drivers/net/team/team.c
> @@ -0,0 +1,1593 @@
> +/*
> + * net/drivers/team/team.c - Network team device driver
> + * Copyright (c) 2011 Jiri Pirko <jpirko@redhat.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/types.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/slab.h>
> +#include <linux/rcupdate.h>
> +#include <linux/errno.h>
> +#include <linux/ctype.h>
> +#include <linux/notifier.h>
> +#include <linux/netdevice.h>
> +#include <linux/if_arp.h>
> +#include <linux/socket.h>
> +#include <linux/etherdevice.h>
> +#include <linux/rtnetlink.h>
> +#include <net/rtnetlink.h>
> +#include <net/genetlink.h>
> +#include <net/netlink.h>
> +#include <linux/if_team.h>
> +
> +#define DRV_NAME "team"
> +
> +
> +/**********
> + * Helpers
> + **********/
> +
> +#define team_port_exists(dev) (dev->priv_flags & IFF_TEAM_PORT)
> +
> +static struct team_port *team_port_get_rcu(const struct net_device *dev)
> +{
> +       struct team_port *port = rcu_dereference(dev->rx_handler_data);
> +
> +       return team_port_exists(dev) ? port : NULL;
> +}
> +
> +static struct team_port *team_port_get_rtnl(const struct net_device *dev)
> +{
> +       struct team_port *port = rtnl_dereference(dev->rx_handler_data);
> +
> +       return team_port_exists(dev) ? port : NULL;
> +}
> +
> +/*
> + * Since the ability to change mac address for open port device is tested in
> + * team_port_add, this function can be called without control of return value
> + */
> +static int __set_port_mac(struct net_device *port_dev,
> +                         const unsigned char *dev_addr)
> +{
> +       struct sockaddr addr;
> +
> +       memcpy(addr.sa_data, dev_addr, ETH_ALEN);
> +       addr.sa_family = ARPHRD_ETHER;
> +       return dev_set_mac_address(port_dev, &addr);
> +}
> +
> +int team_port_set_orig_mac(struct team_port *port)
> +{
> +       return __set_port_mac(port->dev, port->orig.dev_addr);
> +}
> +EXPORT_SYMBOL(team_port_set_orig_mac);
> +
> +int team_port_set_team_mac(struct team_port *port)
> +{
> +       return __set_port_mac(port->dev, port->team->dev->dev_addr);
> +}
> +EXPORT_SYMBOL(team_port_set_team_mac);
> +
> +
> +/*******************
> + * Options handling
> + *******************/
> +
> +void team_options_register(struct team *team, struct team_option *option,
> +                          size_t option_count)
> +{
> +       int i;
> +
> +       for (i = 0; i < option_count; i++, option++)
> +               list_add_tail(&option->list, &team->option_list);
> +}
> +EXPORT_SYMBOL(team_options_register);
> +
> +static void __team_options_change_check(struct team *team,
> +                                       struct team_option *changed_option);
> +
> +static void __team_options_unregister(struct team *team,
> +                                     struct team_option *option,
> +                                     size_t option_count)
> +{
> +       int i;
> +
> +       for (i = 0; i < option_count; i++, option++)
> +               list_del(&option->list);
> +}
> +
> +void team_options_unregister(struct team *team, struct team_option *option,
> +                            size_t option_count)
> +{
> +       __team_options_unregister(team, option, option_count);
> +       __team_options_change_check(team, NULL);
> +}
> +EXPORT_SYMBOL(team_options_unregister);
> +
> +static int team_option_get(struct team *team, struct team_option *option,
> +                          void *arg)
> +{
> +       return option->getter(team, arg);
> +}
> +
> +static int team_option_set(struct team *team, struct team_option *option,
> +                          void *arg)
> +{
> +       int err;
> +
> +       err = option->setter(team, arg);
> +       if (err)
> +               return err;
> +
> +       __team_options_change_check(team, option);
> +       return err;
> +}
> +
> +/****************
> + * Mode handling
> + ****************/
> +
> +static LIST_HEAD(mode_list);
> +static DEFINE_SPINLOCK(mode_list_lock);
> +
> +static struct team_mode *__find_mode(const char *kind)
> +{
> +       struct team_mode *mode;
> +
> +       list_for_each_entry(mode, &mode_list, list) {
> +               if (strcmp(mode->kind, kind) == 0)
> +                       return mode;
> +       }
> +       return NULL;
> +}
> +
> +static bool is_good_mode_name(const char *name)
> +{
> +       while (*name != '\0') {
> +               if (!isalpha(*name) && !isdigit(*name) && *name != '_')
> +                       return false;
> +               name++;
> +       }
> +       return true;
> +}
> +
> +int team_mode_register(struct team_mode *mode)
> +{
> +       int err = 0;
> +
> +       if (!is_good_mode_name(mode->kind) ||
> +           mode->priv_size > TEAM_MODE_PRIV_SIZE)
> +               return -EINVAL;
> +       spin_lock(&mode_list_lock);
> +       if (__find_mode(mode->kind)) {
> +               err = -EEXIST;
> +               goto unlock;
> +       }
> +       list_add_tail(&mode->list, &mode_list);
> +unlock:
> +       spin_unlock(&mode_list_lock);
> +       return err;
> +}
> +EXPORT_SYMBOL(team_mode_register);
> +
> +int team_mode_unregister(struct team_mode *mode)
> +{
> +       spin_lock(&mode_list_lock);
> +       list_del_init(&mode->list);
> +       spin_unlock(&mode_list_lock);
> +       return 0;
> +}
> +EXPORT_SYMBOL(team_mode_unregister);
> +
> +static struct team_mode *team_mode_get(const char *kind)
> +{
> +       struct team_mode *mode;
> +
> +       spin_lock(&mode_list_lock);
> +       mode = __find_mode(kind);
> +       if (!mode) {
> +               spin_unlock(&mode_list_lock);
> +               request_module("team-mode-%s", kind);
> +               spin_lock(&mode_list_lock);
> +               mode = __find_mode(kind);
> +       }
> +       if (mode)
> +               if (!try_module_get(mode->owner))
> +                       mode = NULL;
> +
> +       spin_unlock(&mode_list_lock);
> +       return mode;
> +}
> +
> +static void team_mode_put(const char *kind)
> +{
> +       struct team_mode *mode;
> +
> +       spin_lock(&mode_list_lock);
> +       mode = __find_mode(kind);
> +       BUG_ON(!mode);
> +       module_put(mode->owner);
> +       spin_unlock(&mode_list_lock);
> +}
> +
> +/*
> + * We can benefit from the fact that it's ensured no port is present
> + * at the time of mode change.
> + */
> +static int __team_change_mode(struct team *team,
> +                             const struct team_mode *new_mode)
> +{
> +       /* Check if mode was previously set and do cleanup if so */
> +       if (team->mode_kind) {
> +               void (*exit_op)(struct team *team) = team->mode_ops.exit;
> +
> +               /* Clear ops area so no callback is called any longer */
> +               memset(&team->mode_ops, 0, sizeof(struct team_mode_ops));
> +
> +               synchronize_rcu();
> +
> +               if (exit_op)
> +                       exit_op(team);
> +               team_mode_put(team->mode_kind);
> +               team->mode_kind = NULL;
> +               /* zero private data area */
> +               memset(&team->mode_priv, 0,
> +                      sizeof(struct team) - offsetof(struct team, mode_priv));
> +       }
> +
> +       if (!new_mode)
> +               return 0;
> +
> +       if (new_mode->ops->init) {
> +               int err;
> +
> +               err = new_mode->ops->init(team);
> +               if (err)
> +                       return err;
> +       }
> +
> +       team->mode_kind = new_mode->kind;
> +       memcpy(&team->mode_ops, new_mode->ops, sizeof(struct team_mode_ops));
> +
> +       return 0;
> +}
> +
> +static int team_change_mode(struct team *team, const char *kind)
> +{
> +       struct team_mode *new_mode;
> +       struct net_device *dev = team->dev;
> +       int err;
> +
> +       if (!list_empty(&team->port_list)) {
> +               netdev_err(dev, "No ports can be present during mode change\n");
> +               return -EBUSY;
> +       }
> +
> +       if (team->mode_kind && strcmp(team->mode_kind, kind) == 0) {
> +               netdev_err(dev, "Unable to change to the same mode the team is in\n");
> +               return -EINVAL;
> +       }
> +
> +       new_mode = team_mode_get(kind);
> +       if (!new_mode) {
> +               netdev_err(dev, "Mode \"%s\" not found\n", kind);
> +               return -EINVAL;
> +       }
> +
> +       err = __team_change_mode(team, new_mode);
> +       if (err) {
> +               netdev_err(dev, "Failed to change to mode \"%s\"\n", kind);
> +               team_mode_put(kind);
> +               return err;
> +       }
> +
> +       netdev_info(dev, "Mode changed to \"%s\"\n", kind);
> +       return 0;
> +}
> +
> +
> +/************************
> + * Rx path frame handler
> + ************************/
> +
> +/* note: already called with rcu_read_lock */
> +static rx_handler_result_t team_handle_frame(struct sk_buff **pskb)
> +{
> +       struct sk_buff *skb = *pskb;
> +       struct team_port *port;
> +       struct team *team;
> +       rx_handler_result_t res = RX_HANDLER_ANOTHER;
> +
> +       skb = skb_share_check(skb, GFP_ATOMIC);
> +       if (!skb)
> +               return RX_HANDLER_CONSUMED;
> +
> +       *pskb = skb;
> +
> +       port = team_port_get_rcu(skb->dev);
> +       team = port->team;
> +
> +       if (team->mode_ops.receive)
> +               res = team->mode_ops.receive(team, port, skb);
> +
> +       if (res == RX_HANDLER_ANOTHER) {
> +               struct team_pcpu_stats *pcpu_stats;
> +
> +               pcpu_stats = this_cpu_ptr(team->pcpu_stats);
> +               u64_stats_update_begin(&pcpu_stats->syncp);
> +               pcpu_stats->rx_packets++;
> +               pcpu_stats->rx_bytes += skb->len;
> +               if (skb->pkt_type == PACKET_MULTICAST)
> +                       pcpu_stats->rx_multicast++;
> +               u64_stats_update_end(&pcpu_stats->syncp);
> +
> +               skb->dev = team->dev;
> +       } else {
> +               this_cpu_inc(team->pcpu_stats->rx_dropped);
> +       }
> +
> +       return res;
> +}
> +
> +
> +/****************
> + * Port handling
> + ****************/
> +
> +static bool team_port_find(const struct team *team,
> +                          const struct team_port *port)
> +{
> +       struct team_port *cur;
> +
> +       list_for_each_entry(cur, &team->port_list, list)
> +               if (cur == port)
> +                       return true;
> +       return false;
> +}
> +
> +static int team_port_list_init(struct team *team)
> +{
> +       int i;
> +       struct hlist_head *hash;
> +
> +       hash = kmalloc(sizeof(*hash) * TEAM_PORT_HASHENTRIES, GFP_KERNEL);
> +       if (!hash)
> +               return -ENOMEM;
> +
> +       for (i = 0; i < TEAM_PORT_HASHENTRIES; i++)
> +               INIT_HLIST_HEAD(&hash[i]);
> +       team->port_hlist = hash;
> +       INIT_LIST_HEAD(&team->port_list);
> +       return 0;
> +}
> +
> +static void team_port_list_fini(struct team *team)
> +{
> +       kfree(team->port_hlist);
> +}
> +
> +/*
> + * Add/delete port to the team port list. Write guarded by rtnl_lock.
> + * Takes care of correct port->index setup (might be racy).
> + */
> +static void team_port_list_add_port(struct team *team,
> +                                   struct team_port *port)
> +{
> +       port->index = team->port_count++;
> +       hlist_add_head_rcu(&port->hlist,
> +                          team_port_index_hash(team, port->index));
> +       list_add_tail_rcu(&port->list, &team->port_list);
> +}
> +
> +static void __reconstruct_port_hlist(struct team *team, int rm_index)
> +{
> +       int i;
> +       struct team_port *port;
> +
> +       for (i = rm_index + 1; i < team->port_count; i++) {
> +               port = team_get_port_by_index_rcu(team, i);
> +               hlist_del_rcu(&port->hlist);
> +               port->index--;
> +               hlist_add_head_rcu(&port->hlist,
> +                                  team_port_index_hash(team, port->index));
> +       }
> +}
> +
> +static void team_port_list_del_port(struct team *team,
> +                                  struct team_port *port)
> +{
> +       int rm_index = port->index;
> +
> +       hlist_del_rcu(&port->hlist);
> +       list_del_rcu(&port->list);
> +       __reconstruct_port_hlist(team, rm_index);
> +       team->port_count--;
> +}
> +
> +#define TEAM_VLAN_FEATURES (NETIF_F_ALL_CSUM | NETIF_F_SG | \
> +                           NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \
> +                           NETIF_F_HIGHDMA | NETIF_F_LRO)
> +
> +static void __team_compute_features(struct team *team)
> +{
> +       struct team_port *port;
> +       u32 vlan_features = TEAM_VLAN_FEATURES;
> +       unsigned short max_hard_header_len = ETH_HLEN;
> +
> +       list_for_each_entry(port, &team->port_list, list) {
> +               vlan_features = netdev_increment_features(vlan_features,
> +                                       port->dev->vlan_features,
> +                                       TEAM_VLAN_FEATURES);
> +
> +               if (port->dev->hard_header_len > max_hard_header_len)
> +                       max_hard_header_len = port->dev->hard_header_len;
> +       }
> +
> +       team->dev->vlan_features = vlan_features;
> +       team->dev->hard_header_len = max_hard_header_len;
> +
> +       netdev_change_features(team->dev);
> +}
> +
> +static void team_compute_features(struct team *team)
> +{
> +       spin_lock(&team->lock);
> +       __team_compute_features(team);
> +       spin_unlock(&team->lock);
> +}
> +
> +static int team_port_enter(struct team *team, struct team_port *port)
> +{
> +       int err = 0;
> +
> +       dev_hold(team->dev);
> +       port->dev->priv_flags |= IFF_TEAM_PORT;
> +       if (team->mode_ops.port_enter) {
> +               err = team->mode_ops.port_enter(team, port);
> +               if (err)
> +                       netdev_err(team->dev, "Device %s failed to enter team mode\n",
> +                                  port->dev->name);
> +       }
> +       return err;
> +}
> +
> +static void team_port_leave(struct team *team, struct team_port *port)
> +{
> +       if (team->mode_ops.port_leave)
> +               team->mode_ops.port_leave(team, port);
> +       port->dev->priv_flags &= ~IFF_TEAM_PORT;
> +       dev_put(team->dev);
> +}
> +
> +static void __team_port_change_check(struct team_port *port, bool linkup);
> +
> +static int team_port_add(struct team *team, struct net_device *port_dev)
> +{
> +       struct net_device *dev = team->dev;
> +       struct team_port *port;
> +       char *portname = port_dev->name;
> +       char tmp_addr[ETH_ALEN];
> +       int err;
> +
> +       if (port_dev->flags & IFF_LOOPBACK ||
> +           port_dev->type != ARPHRD_ETHER) {
> +               netdev_err(dev, "Device %s is of an unsupported type\n",
> +                          portname);
> +               return -EINVAL;
> +       }
> +
> +       if (team_port_exists(port_dev)) {
> +               netdev_err(dev, "Device %s is already a port "
> +                               "of a team device\n", portname);
> +               return -EBUSY;
> +       }
> +
> +       if (port_dev->flags & IFF_UP) {
> +               netdev_err(dev, "Device %s is up. Set it down before adding it as a team port\n",
> +                          portname);
> +               return -EBUSY;
> +       }
> +
> +       port = kzalloc(sizeof(struct team_port), GFP_KERNEL);
> +       if (!port)
> +               return -ENOMEM;
> +
> +       port->dev = port_dev;
> +       port->team = team;
> +
> +       port->orig.mtu = port_dev->mtu;
> +       err = dev_set_mtu(port_dev, dev->mtu);
> +       if (err) {
> +               netdev_dbg(dev, "Error %d calling dev_set_mtu\n", err);
> +               goto err_set_mtu;
> +       }
> +
> +       memcpy(port->orig.dev_addr, port_dev->dev_addr, ETH_ALEN);
> +       random_ether_addr(tmp_addr);
> +       err = __set_port_mac(port_dev, tmp_addr);
> +       if (err) {
> +               netdev_dbg(dev, "Device %s mac addr set failed\n",
> +                          portname);
> +               goto err_set_mac_rand;
> +       }
> +
> +       err = dev_open(port_dev);
> +       if (err) {
> +               netdev_dbg(dev, "Device %s opening failed\n",
> +                          portname);
> +               goto err_dev_open;
> +       }
> +
> +       err = team_port_set_orig_mac(port);
> +       if (err) {
> +               netdev_dbg(dev, "Device %s mac addr set failed - Device does not support addr change when it's opened\n",
> +                          portname);
> +               goto err_set_mac_opened;
> +       }
> +
> +       err = team_port_enter(team, port);
> +       if (err) {
> +               netdev_err(dev, "Device %s failed to enter team mode\n",
> +                          portname);
> +               goto err_port_enter;
> +       }
> +
> +       err = netdev_set_master(port_dev, dev);
> +       if (err) {
> +               netdev_err(dev, "Device %s failed to set master\n", portname);
> +               goto err_set_master;
> +       }
> +
> +       err = netdev_rx_handler_register(port_dev, team_handle_frame,
> +                                        port);
> +       if (err) {
> +               netdev_err(dev, "Device %s failed to register rx_handler\n",
> +                          portname);
> +               goto err_handler_register;
> +       }
> +
> +       team_port_list_add_port(team, port);
> +       __team_compute_features(team);
> +       __team_port_change_check(port, !!netif_carrier_ok(port_dev));
> +
> +       netdev_info(dev, "Port device %s added\n", portname);
> +
> +       return 0;
> +
> +err_handler_register:
> +       netdev_set_master(port_dev, NULL);
> +
> +err_set_master:
> +       team_port_leave(team, port);
> +
> +err_port_enter:
> +err_set_mac_opened:
> +       dev_close(port_dev);
> +
> +err_dev_open:
> +       team_port_set_orig_mac(port);
> +
> +err_set_mac_rand:
> +       dev_set_mtu(port_dev, port->orig.mtu);
> +
> +err_set_mtu:
> +       kfree(port);
> +
> +       return err;
> +}
> +
> +static int team_port_del(struct team *team, struct net_device *port_dev)
> +{
> +       struct net_device *dev = team->dev;
> +       struct team_port *port;
> +       char *portname = port_dev->name;
> +
> +       port = team_port_get_rtnl(port_dev);
> +       if (!port || !team_port_find(team, port)) {
> +               netdev_err(dev, "Device %s does not act as a port of this team\n",
> +                          portname);
> +               return -ENOENT;
> +       }
> +
> +       __team_port_change_check(port, false);
> +       team_port_list_del_port(team, port);
> +       netdev_rx_handler_unregister(port_dev);
> +       netdev_set_master(port_dev, NULL);
> +       team_port_leave(team, port);
> +       dev_close(port_dev);
> +       team_port_set_orig_mac(port);
> +       dev_set_mtu(port_dev, port->orig.mtu);
> +       synchronize_rcu();
> +       kfree(port);
> +       netdev_info(dev, "Port device %s removed\n", portname);
> +       __team_compute_features(team);
> +
> +       return 0;
> +}
> +
> +
> +/*****************
> + * Net device ops
> + *****************/
> +
> +static const char team_no_mode_kind[] = "*NOMODE*";
> +
> +static int team_mode_option_get(struct team *team, void *arg)
> +{
> +       const char **str = arg;
> +
> +       *str = team->mode_kind ? team->mode_kind : team_no_mode_kind;
> +       return 0;
> +}
> +
> +static int team_mode_option_set(struct team *team, void *arg)
> +{
> +       const char **str = arg;
> +
> +       return team_change_mode(team, *str);
> +}
> +
> +static struct team_option team_options[] = {
> +       {
> +               .name = "mode",
> +               .type = TEAM_OPTION_TYPE_STRING,
> +               .getter = team_mode_option_get,
> +               .setter = team_mode_option_set,
> +       },
> +};
> +
> +static int team_init(struct net_device *dev)
> +{
> +       struct team *team = netdev_priv(dev);
> +       int err;
> +
> +       team->dev = dev;
> +       spin_lock_init(&team->lock);
> +
> +       team->pcpu_stats = alloc_percpu(struct team_pcpu_stats);
> +       if (!team->pcpu_stats)
> +               return -ENOMEM;
> +
> +       err = team_port_list_init(team);
> +       if (err)
> +               goto err_port_list_init;
> +
> +       INIT_LIST_HEAD(&team->option_list);
> +       team_options_register(team, team_options, ARRAY_SIZE(team_options));
> +       netif_carrier_off(dev);
> +
> +       return 0;
> +
> +err_port_list_init:
> +
> +       free_percpu(team->pcpu_stats);
> +
> +       return err;
> +}
> +
> +static void team_uninit(struct net_device *dev)
> +{
> +       struct team *team = netdev_priv(dev);
> +       struct team_port *port;
> +       struct team_port *tmp;
> +
> +       spin_lock(&team->lock);
> +       list_for_each_entry_safe(port, tmp, &team->port_list, list)
> +               team_port_del(team, port->dev);
> +
> +       __team_change_mode(team, NULL); /* cleanup */
> +       __team_options_unregister(team, team_options, ARRAY_SIZE(team_options));
> +       spin_unlock(&team->lock);
> +}
> +
> +static void team_destructor(struct net_device *dev)
> +{
> +       struct team *team = netdev_priv(dev);
> +
> +       team_port_list_fini(team);
> +       free_percpu(team->pcpu_stats);
> +       free_netdev(dev);
> +}
> +
> +static int team_open(struct net_device *dev)
> +{
> +       netif_carrier_on(dev);
> +       return 0;
> +}
> +
> +static int team_close(struct net_device *dev)
> +{
> +       netif_carrier_off(dev);
> +       return 0;
> +}
> +
> +/*
> + * note: already called with rcu_read_lock
> + */
> +static netdev_tx_t team_xmit(struct sk_buff *skb, struct net_device *dev)
> +{
> +       struct team *team = netdev_priv(dev);
> +       bool tx_success = false;
> +       unsigned int len = skb->len;
> +
> +       /*
> +        * Ensure transmit function is called only in case there is at least
> +        * one port present.
> +        */
> +       if (likely(!list_empty(&team->port_list) && team->mode_ops.transmit))
> +               tx_success = team->mode_ops.transmit(team, skb);
> +       if (tx_success) {
> +               struct team_pcpu_stats *pcpu_stats;
> +
> +               pcpu_stats = this_cpu_ptr(team->pcpu_stats);
> +               u64_stats_update_begin(&pcpu_stats->syncp);
> +               pcpu_stats->tx_packets++;
> +               pcpu_stats->tx_bytes += len;
> +               u64_stats_update_end(&pcpu_stats->syncp);
> +       } else {
> +               this_cpu_inc(team->pcpu_stats->tx_dropped);
> +       }
> +
> +       return NETDEV_TX_OK;
> +}
> +
> +static void team_change_rx_flags(struct net_device *dev, int change)
> +{
> +       struct team *team = netdev_priv(dev);
> +       struct team_port *port;
> +       int inc;
> +
> +       rcu_read_lock();
> +       list_for_each_entry_rcu(port, &team->port_list, list) {
> +               if (change & IFF_PROMISC) {
> +                       inc = dev->flags & IFF_PROMISC ? 1 : -1;
> +                       dev_set_promiscuity(port->dev, inc);
> +               }
> +               if (change & IFF_ALLMULTI) {
> +                       inc = dev->flags & IFF_ALLMULTI ? 1 : -1;
> +                       dev_set_allmulti(port->dev, inc);
> +               }
> +       }
> +       rcu_read_unlock();
> +}
> +
> +static void team_set_rx_mode(struct net_device *dev)
> +{
> +       struct team *team = netdev_priv(dev);
> +       struct team_port *port;
> +
> +       rcu_read_lock();
> +       list_for_each_entry_rcu(port, &team->port_list, list) {
> +               dev_uc_sync(port->dev, dev);
> +               dev_mc_sync(port->dev, dev);
> +       }
> +       rcu_read_unlock();
> +}
> +
> +static int team_set_mac_address(struct net_device *dev, void *p)
> +{
> +       struct team *team = netdev_priv(dev);
> +       struct team_port *port;
> +       struct sockaddr *addr = p;
> +
> +       memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
> +       rcu_read_lock();
> +       list_for_each_entry_rcu(port, &team->port_list, list)
> +               if (team->mode_ops.port_change_mac)
> +                       team->mode_ops.port_change_mac(team, port);
> +       rcu_read_unlock();
> +       return 0;
> +}
> +
> +static int team_change_mtu(struct net_device *dev, int new_mtu)
> +{
> +       struct team *team = netdev_priv(dev);
> +       struct team_port *port;
> +       int err;
> +
> +       rcu_read_lock();
> +       list_for_each_entry_rcu(port, &team->port_list, list) {
> +               err = dev_set_mtu(port->dev, new_mtu);
> +               if (err) {
> +                       netdev_err(dev, "Device %s failed to change mtu",
> +                                  port->dev->name);
> +                       goto unwind;
> +               }
> +       }
> +       rcu_read_unlock();
> +
> +       dev->mtu = new_mtu;
> +
> +       return 0;
> +
> +unwind:
> +       list_for_each_entry_continue_reverse(port, &team->port_list, list)
> +               dev_set_mtu(port->dev, dev->mtu);
> +
> +       rcu_read_unlock();
> +       return err;
> +}
> +
> +static struct rtnl_link_stats64 *
> +team_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
> +{
> +       struct team *team = netdev_priv(dev);
> +       struct team_pcpu_stats *p;
> +       u64 rx_packets, rx_bytes, rx_multicast, tx_packets, tx_bytes;
> +       u32 rx_dropped = 0, tx_dropped = 0;
> +       unsigned int start;
> +       int i;
> +
> +       for_each_possible_cpu(i) {
> +               p = per_cpu_ptr(team->pcpu_stats, i);
> +               do {
> +                       start = u64_stats_fetch_begin_bh(&p->syncp);
> +                       rx_packets      = p->rx_packets;
> +                       rx_bytes        = p->rx_bytes;
> +                       rx_multicast    = p->rx_multicast;
> +                       tx_packets      = p->tx_packets;
> +                       tx_bytes        = p->tx_bytes;
> +               } while (u64_stats_fetch_retry_bh(&p->syncp, start));
> +
> +               stats->rx_packets       += rx_packets;
> +               stats->rx_bytes         += rx_bytes;
> +               stats->multicast        += rx_multicast;
> +               stats->tx_packets       += tx_packets;
> +               stats->tx_bytes         += tx_bytes;
> +               /*
> +                * rx_dropped & tx_dropped are u32, updated
> +                * without syncp protection.
> +                */
> +               rx_dropped      += p->rx_dropped;
> +               tx_dropped      += p->tx_dropped;
> +       }
> +       stats->rx_dropped       = rx_dropped;
> +       stats->tx_dropped       = tx_dropped;
> +       return stats;
> +}
> +
> +static void team_vlan_rx_add_vid(struct net_device *dev, uint16_t vid)
> +{
> +       struct team *team = netdev_priv(dev);
> +       struct team_port *port;
> +
> +       rcu_read_lock();
> +       list_for_each_entry_rcu(port, &team->port_list, list) {
> +               const struct net_device_ops *ops = port->dev->netdev_ops;
> +
> +               ops->ndo_vlan_rx_add_vid(port->dev, vid);
> +       }
> +       rcu_read_unlock();
> +}
> +
> +static void team_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
> +{
> +       struct team *team = netdev_priv(dev);
> +       struct team_port *port;
> +
> +       rcu_read_lock();
> +       list_for_each_entry_rcu(port, &team->port_list, list) {
> +               const struct net_device_ops *ops = port->dev->netdev_ops;
> +
> +               ops->ndo_vlan_rx_kill_vid(port->dev, vid);
> +       }
> +       rcu_read_unlock();
> +}
> +
> +static int team_add_slave(struct net_device *dev, struct net_device *port_dev)
> +{
> +       struct team *team = netdev_priv(dev);
> +       int err;
> +
> +       spin_lock(&team->lock);
> +       err = team_port_add(team, port_dev);
> +       spin_unlock(&team->lock);
> +       return err;
> +}
> +
> +static int team_del_slave(struct net_device *dev, struct net_device *port_dev)
> +{
> +       struct team *team = netdev_priv(dev);
> +       int err;
> +
> +       spin_lock(&team->lock);
> +       err = team_port_del(team, port_dev);
> +       spin_unlock(&team->lock);
> +       return err;
> +}
> +
> +static const struct net_device_ops team_netdev_ops = {
> +       .ndo_init               = team_init,
> +       .ndo_uninit             = team_uninit,
> +       .ndo_open               = team_open,
> +       .ndo_stop               = team_close,
> +       .ndo_start_xmit         = team_xmit,
> +       .ndo_change_rx_flags    = team_change_rx_flags,
> +       .ndo_set_rx_mode        = team_set_rx_mode,
> +       .ndo_set_mac_address    = team_set_mac_address,
> +       .ndo_change_mtu         = team_change_mtu,
> +       .ndo_get_stats64        = team_get_stats64,
> +       .ndo_vlan_rx_add_vid    = team_vlan_rx_add_vid,
> +       .ndo_vlan_rx_kill_vid   = team_vlan_rx_kill_vid,
> +       .ndo_add_slave          = team_add_slave,
> +       .ndo_del_slave          = team_del_slave,
> +};
> +
> +
> +/***********************
> + * rt netlink interface
> + ***********************/
> +
> +static void team_setup(struct net_device *dev)
> +{
> +       ether_setup(dev);
> +
> +       dev->netdev_ops = &team_netdev_ops;
> +       dev->destructor = team_destructor;
> +       dev->tx_queue_len = 0;
> +       dev->flags |= IFF_MULTICAST;
> +       dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
> +
> +       /*
> +        * Indicate we support unicast address filtering. That way core won't
> +        * bring us to promisc mode in case a unicast addr is added.
> +        * Let this up to underlay drivers.
> +        */
> +       dev->priv_flags |= IFF_UNICAST_FLT;
> +
> +       dev->features |= NETIF_F_LLTX;
> +       dev->features |= NETIF_F_GRO;
> +       dev->hw_features = NETIF_F_HW_VLAN_TX |
> +                          NETIF_F_HW_VLAN_RX |
> +                          NETIF_F_HW_VLAN_FILTER;
> +
> +       dev->features |= dev->hw_features;
> +}
> +
> +static int team_newlink(struct net *src_net, struct net_device *dev,
> +                       struct nlattr *tb[], struct nlattr *data[])
> +{
> +       int err;
> +
> +       if (tb[IFLA_ADDRESS] == NULL)
> +               random_ether_addr(dev->dev_addr);
> +
> +       err = register_netdevice(dev);
> +       if (err)
> +               return err;
> +
> +       return 0;
> +}
> +
> +static int team_validate(struct nlattr *tb[], struct nlattr *data[])
> +{
> +       if (tb[IFLA_ADDRESS]) {
> +               if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
> +                       return -EINVAL;
> +               if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
> +                       return -EADDRNOTAVAIL;
> +       }
> +       return 0;
> +}
> +
> +static struct rtnl_link_ops team_link_ops __read_mostly = {
> +       .kind           = DRV_NAME,
> +       .priv_size      = sizeof(struct team),
> +       .setup          = team_setup,
> +       .newlink        = team_newlink,
> +       .validate       = team_validate,
> +};
> +
> +
> +/***********************************
> + * Generic netlink custom interface
> + ***********************************/
> +
> +static struct genl_family team_nl_family = {
> +       .id             = GENL_ID_GENERATE,
> +       .name           = TEAM_GENL_NAME,
> +       .version        = TEAM_GENL_VERSION,
> +       .maxattr        = TEAM_ATTR_MAX,
> +       .netnsok        = true,
> +};
> +
> +static const struct nla_policy team_nl_policy[TEAM_ATTR_MAX + 1] = {
> +       [TEAM_ATTR_UNSPEC]                      = { .type = NLA_UNSPEC, },
> +       [TEAM_ATTR_TEAM_IFINDEX]                = { .type = NLA_U32 },
> +       [TEAM_ATTR_LIST_OPTION]                 = { .type = NLA_NESTED },
> +       [TEAM_ATTR_LIST_PORT]                   = { .type = NLA_NESTED },
> +};
> +
> +static const struct nla_policy
> +team_nl_option_policy[TEAM_ATTR_OPTION_MAX + 1] = {
> +       [TEAM_ATTR_OPTION_UNSPEC]               = { .type = NLA_UNSPEC, },
> +       [TEAM_ATTR_OPTION_NAME] = {
> +               .type = NLA_STRING,
> +               .len = TEAM_STRING_MAX_LEN,
> +       },
> +       [TEAM_ATTR_OPTION_CHANGED]              = { .type = NLA_FLAG },
> +       [TEAM_ATTR_OPTION_TYPE]                 = { .type = NLA_U8 },
> +       [TEAM_ATTR_OPTION_DATA] = {
> +               .type = NLA_BINARY,
> +               .len = TEAM_STRING_MAX_LEN,
> +       },
> +};
> +
> +static int team_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info)
> +{
> +       struct sk_buff *msg;
> +       void *hdr;
> +       int err;
> +
> +       msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
> +       if (!msg)
> +               return -ENOMEM;
> +
> +       hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq,
> +                         &team_nl_family, 0, TEAM_CMD_NOOP);
> +       if (IS_ERR(hdr)) {
> +               err = PTR_ERR(hdr);
> +               goto err_msg_put;
> +       }
> +
> +       genlmsg_end(msg, hdr);
> +
> +       return genlmsg_unicast(genl_info_net(info), msg, info->snd_pid);
> +
> +err_msg_put:
> +       nlmsg_free(msg);
> +
> +       return err;
> +}
> +
> +/*
> + * Netlink cmd functions should be locked by following two functions.
> + * To ensure team_uninit would not be called in between, hold rcu_read_lock
> + * all the time.
> + */
> +static struct team *team_nl_team_get(struct genl_info *info)
> +{
> +       struct net *net = genl_info_net(info);
> +       int ifindex;
> +       struct net_device *dev;
> +       struct team *team;
> +
> +       if (!info->attrs[TEAM_ATTR_TEAM_IFINDEX])
> +               return NULL;
> +
> +       ifindex = nla_get_u32(info->attrs[TEAM_ATTR_TEAM_IFINDEX]);
> +       rcu_read_lock();
> +       dev = dev_get_by_index_rcu(net, ifindex);
> +       if (!dev || dev->netdev_ops != &team_netdev_ops) {
> +               rcu_read_unlock();
> +               return NULL;
> +       }
> +
> +       team = netdev_priv(dev);
> +       spin_lock(&team->lock);
> +       return team;
> +}
> +
> +static void team_nl_team_put(struct team *team)
> +{
> +       spin_unlock(&team->lock);
> +       rcu_read_unlock();
> +}
> +
> +static int team_nl_send_generic(struct genl_info *info, struct team *team,
> +                               int (*fill_func)(struct sk_buff *skb,
> +                                                struct genl_info *info,
> +                                                int flags, struct team *team))
> +{
> +       struct sk_buff *skb;
> +       int err;
> +
> +       skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
> +       if (!skb)
> +               return -ENOMEM;
> +
> +       err = fill_func(skb, info, NLM_F_ACK, team);
> +       if (err < 0)
> +               goto err_fill;
> +
> +       err = genlmsg_unicast(genl_info_net(info), skb, info->snd_pid);
> +       return err;
> +
> +err_fill:
> +       nlmsg_free(skb);
> +       return err;
> +}
> +
> +static int team_nl_fill_options_get_changed(struct sk_buff *skb,
> +                                           u32 pid, u32 seq, int flags,
> +                                           struct team *team,
> +                                           struct team_option *changed_option)
> +{
> +       struct nlattr *option_list;
> +       void *hdr;
> +       struct team_option *option;
> +
> +       hdr = genlmsg_put(skb, pid, seq, &team_nl_family, flags,
> +                         TEAM_CMD_OPTIONS_GET);
> +       if (IS_ERR(hdr))
> +               return PTR_ERR(hdr);
> +
> +       NLA_PUT_U32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex);
> +       option_list = nla_nest_start(skb, TEAM_ATTR_LIST_OPTION);
> +       if (!option_list)
> +               return -EMSGSIZE;
> +
> +       list_for_each_entry(option, &team->option_list, list) {
> +               struct nlattr *option_item;
> +               long arg;
> +
> +               option_item = nla_nest_start(skb, TEAM_ATTR_ITEM_OPTION);
> +               if (!option_item)
> +                       goto nla_put_failure;
> +               NLA_PUT_STRING(skb, TEAM_ATTR_OPTION_NAME, option->name);
> +               if (option == changed_option)
> +                       NLA_PUT_FLAG(skb, TEAM_ATTR_OPTION_CHANGED);
> +               switch (option->type) {
> +               case TEAM_OPTION_TYPE_U32:
> +                       NLA_PUT_U8(skb, TEAM_ATTR_OPTION_TYPE, NLA_U32);
> +                       team_option_get(team, option, &arg);
> +                       NLA_PUT_U32(skb, TEAM_ATTR_OPTION_DATA, arg);
> +                       break;
> +               case TEAM_OPTION_TYPE_STRING:
> +                       NLA_PUT_U8(skb, TEAM_ATTR_OPTION_TYPE, NLA_STRING);
> +                       team_option_get(team, option, &arg);
> +                       NLA_PUT_STRING(skb, TEAM_ATTR_OPTION_DATA,
> +                                      (char *) arg);
> +                       break;
> +               default:
> +                       BUG();
> +               }
> +               nla_nest_end(skb, option_item);
> +       }
> +
> +       nla_nest_end(skb, option_list);
> +       return genlmsg_end(skb, hdr);
> +
> +nla_put_failure:
> +       genlmsg_cancel(skb, hdr);
> +       return -EMSGSIZE;
> +}
> +
> +static int team_nl_fill_options_get(struct sk_buff *skb,
> +                                   struct genl_info *info, int flags,
> +                                   struct team *team)
> +{
> +       return team_nl_fill_options_get_changed(skb, info->snd_pid,
> +                                               info->snd_seq, NLM_F_ACK,
> +                                               team, NULL);
> +}
> +
> +static int team_nl_cmd_options_get(struct sk_buff *skb, struct genl_info *info)
> +{
> +       struct team *team;
> +       int err;
> +
> +       team = team_nl_team_get(info);
> +       if (!team)
> +               return -EINVAL;
> +
> +       err = team_nl_send_generic(info, team, team_nl_fill_options_get);
> +
> +       team_nl_team_put(team);
> +
> +       return err;
> +}
> +
> +static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
> +{
> +       struct team *team;
> +       int err = 0;
> +       int i;
> +       struct nlattr *nl_option;
> +
> +       team = team_nl_team_get(info);
> +       if (!team)
> +               return -EINVAL;
> +
> +       err = -EINVAL;
> +       if (!info->attrs[TEAM_ATTR_LIST_OPTION]) {
> +               err = -EINVAL;
> +               goto team_put;
> +       }
> +
> +       nla_for_each_nested(nl_option, info->attrs[TEAM_ATTR_LIST_OPTION], i) {
> +               struct nlattr *mode_attrs[TEAM_ATTR_OPTION_MAX + 1];
> +               enum team_option_type opt_type;
> +               struct team_option *option;
> +               char *opt_name;
> +               bool opt_found = false;
> +
> +               if (nla_type(nl_option) != TEAM_ATTR_ITEM_OPTION) {
> +                       err = -EINVAL;
> +                       goto team_put;
> +               }
> +               err = nla_parse_nested(mode_attrs, TEAM_ATTR_OPTION_MAX,
> +                                      nl_option, team_nl_option_policy);
> +               if (err)
> +                       goto team_put;
> +               if (!mode_attrs[TEAM_ATTR_OPTION_NAME] ||
> +                   !mode_attrs[TEAM_ATTR_OPTION_TYPE] ||
> +                   !mode_attrs[TEAM_ATTR_OPTION_DATA]) {
> +                       err = -EINVAL;
> +                       goto team_put;
> +               }
> +               switch (nla_get_u8(mode_attrs[TEAM_ATTR_OPTION_TYPE])) {
> +               case NLA_U32:
> +                       opt_type = TEAM_OPTION_TYPE_U32;
> +                       break;
> +               case NLA_STRING:
> +                       opt_type = TEAM_OPTION_TYPE_STRING;
> +                       break;
> +               default:
> +                       goto team_put;
> +               }
> +
> +               opt_name = nla_data(mode_attrs[TEAM_ATTR_OPTION_NAME]);
> +               list_for_each_entry(option, &team->option_list, list) {
> +                       long arg;
> +                       struct nlattr *opt_data_attr;
> +
> +                       if (option->type != opt_type ||
> +                           strcmp(option->name, opt_name))
> +                               continue;
> +                       opt_found = true;
> +                       opt_data_attr = mode_attrs[TEAM_ATTR_OPTION_DATA];
> +                       switch (opt_type) {
> +                       case TEAM_OPTION_TYPE_U32:
> +                               arg = nla_get_u32(opt_data_attr);
> +                               break;
> +                       case TEAM_OPTION_TYPE_STRING:
> +                               arg = (long) nla_data(opt_data_attr);
> +                               break;
> +                       default:
> +                               BUG();
> +                       }
> +                       err = team_option_set(team, option, &arg);
> +                       if (err)
> +                               goto team_put;
> +               }
> +               if (!opt_found) {
> +                       err = -ENOENT;
> +                       goto team_put;
> +               }
> +       }
> +
> +team_put:
> +       team_nl_team_put(team);
> +
> +       return err;
> +}
> +
> +static int team_nl_fill_port_list_get_changed(struct sk_buff *skb,
> +                                             u32 pid, u32 seq, int flags,
> +                                             struct team *team,
> +                                             struct team_port *changed_port)
> +{
> +       struct nlattr *port_list;
> +       void *hdr;
> +       struct team_port *port;
> +
> +       hdr = genlmsg_put(skb, pid, seq, &team_nl_family, flags,
> +                         TEAM_CMD_PORT_LIST_GET);
> +       if (IS_ERR(hdr))
> +               return PTR_ERR(hdr);
> +
> +       NLA_PUT_U32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex);
> +       port_list = nla_nest_start(skb, TEAM_ATTR_LIST_PORT);
> +       if (!port_list)
> +               return -EMSGSIZE;
> +
> +       list_for_each_entry_rcu(port, &team->port_list, list) {
> +               struct nlattr *port_item;
> +
> +               port_item = nla_nest_start(skb, TEAM_ATTR_ITEM_PORT);
> +               if (!port_item)
> +                       goto nla_put_failure;
> +               NLA_PUT_U32(skb, TEAM_ATTR_PORT_IFINDEX, port->dev->ifindex);
> +               if (port == changed_port)
> +                       NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_CHANGED);
> +               if (port->linkup)
> +                       NLA_PUT_FLAG(skb, TEAM_ATTR_PORT_LINKUP);
> +               NLA_PUT_U32(skb, TEAM_ATTR_PORT_SPEED, port->speed);
> +               NLA_PUT_U8(skb, TEAM_ATTR_PORT_DUPLEX, port->duplex);
> +               nla_nest_end(skb, port_item);
> +       }
> +
> +       nla_nest_end(skb, port_list);
> +       return genlmsg_end(skb, hdr);
> +
> +nla_put_failure:
> +       genlmsg_cancel(skb, hdr);
> +       return -EMSGSIZE;
> +}
> +
> +static int team_nl_fill_port_list_get(struct sk_buff *skb,
> +                                     struct genl_info *info, int flags,
> +                                     struct team *team)
> +{
> +       return team_nl_fill_port_list_get_changed(skb, info->snd_pid,
> +                                                 info->snd_seq, NLM_F_ACK,
> +                                                 team, NULL);
> +}
> +
> +static int team_nl_cmd_port_list_get(struct sk_buff *skb,
> +                                    struct genl_info *info)
> +{
> +       struct team *team;
> +       int err;
> +
> +       team = team_nl_team_get(info);
> +       if (!team)
> +               return -EINVAL;
> +
> +       err = team_nl_send_generic(info, team, team_nl_fill_port_list_get);
> +
> +       team_nl_team_put(team);
> +
> +       return err;
> +}
> +
> +static struct genl_ops team_nl_ops[] = {
> +       {
> +               .cmd = TEAM_CMD_NOOP,
> +               .doit = team_nl_cmd_noop,
> +               .policy = team_nl_policy,
> +       },
> +       {
> +               .cmd = TEAM_CMD_OPTIONS_SET,
> +               .doit = team_nl_cmd_options_set,
> +               .policy = team_nl_policy,
> +               .flags = GENL_ADMIN_PERM,
> +       },
> +       {
> +               .cmd = TEAM_CMD_OPTIONS_GET,
> +               .doit = team_nl_cmd_options_get,
> +               .policy = team_nl_policy,
> +               .flags = GENL_ADMIN_PERM,
> +       },
> +       {
> +               .cmd = TEAM_CMD_PORT_LIST_GET,
> +               .doit = team_nl_cmd_port_list_get,
> +               .policy = team_nl_policy,
> +               .flags = GENL_ADMIN_PERM,
> +       },
> +};
> +
> +static struct genl_multicast_group team_change_event_mcgrp = {
> +       .name = TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME,
> +};
> +
> +static int team_nl_send_event_options_get(struct team *team,
> +                                         struct team_option *changed_option)
> +{
> +       struct sk_buff *skb;
> +       int err;
> +       struct net *net = dev_net(team->dev);
> +
> +       skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
> +       if (!skb)
> +               return -ENOMEM;
> +
> +       err = team_nl_fill_options_get_changed(skb, 0, 0, 0, team,
> +                                              changed_option);
> +       if (err < 0)
> +               goto err_fill;
> +
> +       err = genlmsg_multicast_netns(net, skb, 0, team_change_event_mcgrp.id,
> +                                     GFP_KERNEL);
> +       return err;
> +
> +err_fill:
> +       nlmsg_free(skb);
> +       return err;
> +}
> +
> +static int team_nl_send_event_port_list_get(struct team_port *port)
> +{
> +       struct sk_buff *skb;
> +       int err;
> +       struct net *net = dev_net(port->team->dev);
> +
> +       skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
> +       if (!skb)
> +               return -ENOMEM;
> +
> +       err = team_nl_fill_port_list_get_changed(skb, 0, 0, 0,
> +                                                port->team, port);
> +       if (err < 0)
> +               goto err_fill;
> +
> +       err = genlmsg_multicast_netns(net, skb, 0, team_change_event_mcgrp.id,
> +                                     GFP_KERNEL);
> +       return err;
> +
> +err_fill:
> +       nlmsg_free(skb);
> +       return err;
> +}
> +
> +static int team_nl_init(void)
> +{
> +       int err;
> +
> +       err = genl_register_family_with_ops(&team_nl_family, team_nl_ops,
> +                                           ARRAY_SIZE(team_nl_ops));
> +       if (err)
> +               return err;
> +
> +       err = genl_register_mc_group(&team_nl_family, &team_change_event_mcgrp);
> +       if (err)
> +               goto err_change_event_grp_reg;
> +
> +       return 0;
> +
> +err_change_event_grp_reg:
> +       genl_unregister_family(&team_nl_family);
> +
> +       return err;
> +}
> +
> +static void team_nl_fini(void)
> +{
> +       genl_unregister_family(&team_nl_family);
> +}
> +
> +
> +/******************
> + * Change checkers
> + ******************/
> +
> +static void __team_options_change_check(struct team *team,
> +                                       struct team_option *changed_option)
> +{
> +       int err;
> +
> +       err = team_nl_send_event_options_get(team, changed_option);
> +       if (err)
> +               netdev_warn(team->dev, "Failed to send options change via netlink\n");
> +}
> +
> +/* rtnl lock is held */
> +static void __team_port_change_check(struct team_port *port, bool linkup)
> +{
> +       int err;
> +
> +       if (port->linkup == linkup)
> +               return;
> +
> +       port->linkup = linkup;
> +       if (linkup) {
> +               struct ethtool_cmd ecmd;
> +
> +               err = __ethtool_get_settings(port->dev, &ecmd);
> +               if (!err) {
> +                       port->speed = ethtool_cmd_speed(&ecmd);
> +                       port->duplex = ecmd.duplex;
> +                       goto send_event;
> +               }
> +       }
> +       port->speed = 0;
> +       port->duplex = 0;
> +
> +send_event:
> +       err = team_nl_send_event_port_list_get(port);
> +       if (err)
> +               netdev_warn(port->team->dev, "Failed to send port change of device %s via netlink\n",
> +                           port->dev->name);
> +
> +}
> +
> +static void team_port_change_check(struct team_port *port, bool linkup)
> +{
> +       struct team *team = port->team;
> +
> +       spin_lock(&team->lock);
> +       __team_port_change_check(port, linkup);
> +       spin_unlock(&team->lock);
> +}
> +
> +/************************************
> + * Net device notifier event handler
> + ************************************/
> +
> +static int team_device_event(struct notifier_block *unused,
> +                            unsigned long event, void *ptr)
> +{
> +       struct net_device *dev = (struct net_device *) ptr;
> +       struct team_port *port;
> +
> +       port = team_port_get_rtnl(dev);
> +       if (!port)
> +               return NOTIFY_DONE;
> +
> +       switch (event) {
> +       case NETDEV_UP:
> +               if (netif_carrier_ok(dev))
> +                       team_port_change_check(port, true);
> +       case NETDEV_DOWN:
> +               team_port_change_check(port, false);
> +       case NETDEV_CHANGE:
> +               if (netif_running(port->dev))
> +                       team_port_change_check(port,
> +                                              !!netif_carrier_ok(port->dev));
> +               break;
> +       case NETDEV_UNREGISTER:
> +               team_del_slave(port->team->dev, dev);
> +               break;
> +       case NETDEV_FEAT_CHANGE:
> +               team_compute_features(port->team);
> +               break;
> +       case NETDEV_CHANGEMTU:
> +               /* Forbid to change mtu of underlaying device */
> +               return NOTIFY_BAD;
> +       case NETDEV_CHANGEADDR:
> +               /* Forbid to change addr of underlaying device */
> +               return NOTIFY_BAD;
> +       case NETDEV_PRE_TYPE_CHANGE:
> +               /* Forbid to change type of underlaying device */
> +               return NOTIFY_BAD;
> +       }
> +       return NOTIFY_DONE;
> +}
> +
> +static struct notifier_block team_notifier_block __read_mostly = {
> +       .notifier_call = team_device_event,
> +};
> +
> +
> +/***********************
> + * Module init and exit
> + ***********************/
> +
> +static int __init team_module_init(void)
> +{
> +       int err;
> +
> +       register_netdevice_notifier(&team_notifier_block);
> +
> +       err = rtnl_link_register(&team_link_ops);
> +       if (err)
> +               goto err_rtln_reg;
> +
> +       err = team_nl_init();
> +       if (err)
> +               goto err_nl_init;
> +
> +       return 0;
> +
> +err_nl_init:
> +       rtnl_link_unregister(&team_link_ops);
> +
> +err_rtln_reg:
> +       unregister_netdevice_notifier(&team_notifier_block);
> +
> +       return err;
> +}
> +
> +static void __exit team_module_exit(void)
> +{
> +       team_nl_fini();
> +       rtnl_link_unregister(&team_link_ops);
> +       unregister_netdevice_notifier(&team_notifier_block);
> +}
> +
> +module_init(team_module_init);
> +module_exit(team_module_exit);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_AUTHOR("Jiri Pirko <jpirko@redhat.com>");
> +MODULE_DESCRIPTION("Ethernet team device driver");
> +MODULE_ALIAS_RTNL_LINK(DRV_NAME);
> diff --git a/drivers/net/team/team_mode_activebackup.c b/drivers/net/team/team_mode_activebackup.c
> new file mode 100644
> index 0000000..1aa2bfb
> --- /dev/null
> +++ b/drivers/net/team/team_mode_activebackup.c
> @@ -0,0 +1,152 @@
> +/*
> + * net/drivers/team/team_mode_activebackup.c - Active-backup mode for team
> + * Copyright (c) 2011 Jiri Pirko <jpirko@redhat.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/types.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/errno.h>
> +#include <linux/netdevice.h>
> +#include <net/rtnetlink.h>
> +#include <linux/if_team.h>
> +
> +struct ab_priv {
> +       struct team_port __rcu *active_port;
> +};
> +
> +static struct ab_priv *ab_priv(struct team *team)
> +{
> +       return (struct ab_priv *) &team->mode_priv;
> +}
> +
> +static rx_handler_result_t ab_receive(struct team *team, struct team_port *port,
> +                                     struct sk_buff *skb) {
> +       struct team_port *active_port;
> +
> +       active_port = rcu_dereference(ab_priv(team)->active_port);
> +       if (active_port != port)
> +               return RX_HANDLER_EXACT;
> +       return RX_HANDLER_ANOTHER;
> +}
> +
> +static bool ab_transmit(struct team *team, struct sk_buff *skb)
> +{
> +       struct team_port *active_port;
> +
> +       active_port = rcu_dereference(ab_priv(team)->active_port);
> +       if (unlikely(!active_port))
> +               goto drop;
> +       skb->dev = active_port->dev;
> +       if (dev_queue_xmit(skb))
> +               return false;
> +       return true;
> +
> +drop:
> +       dev_kfree_skb(skb);
> +       return false;
> +}
> +
> +static void ab_port_leave(struct team *team, struct team_port *port)
> +{
> +       if (ab_priv(team)->active_port == port)
> +               rcu_assign_pointer(ab_priv(team)->active_port, NULL);
> +}
> +
> +static void ab_port_change_mac(struct team *team, struct team_port *port)
> +{
> +       if (ab_priv(team)->active_port == port)
> +               team_port_set_team_mac(port);
> +}
> +
> +static int ab_active_port_get(struct team *team, void *arg)
> +{
> +       u32 *ifindex = arg;
> +
> +       *ifindex = 0;
> +       if (ab_priv(team)->active_port)
> +               *ifindex = ab_priv(team)->active_port->dev->ifindex;
> +       return 0;
> +}
> +
> +static int ab_active_port_set(struct team *team, void *arg)
> +{
> +       u32 *ifindex = arg;
> +       struct team_port *port;
> +
> +       list_for_each_entry_rcu(port, &team->port_list, list) {
> +               if (port->dev->ifindex == *ifindex) {
> +                       struct team_port *ac_port = ab_priv(team)->active_port;
> +
> +                       /* rtnl_lock needs to be held when setting macs */
> +                       rtnl_lock();
> +                       if (ac_port)
> +                               team_port_set_orig_mac(ac_port);
> +                       rcu_assign_pointer(ab_priv(team)->active_port, port);
> +                       team_port_set_team_mac(port);
> +                       rtnl_unlock();
> +                       return 0;
> +               }
> +       }
> +       return -ENOENT;
> +}
> +
> +static struct team_option ab_options[] = {
> +       {
> +               .name = "activeport",
> +               .type = TEAM_OPTION_TYPE_U32,
> +               .getter = ab_active_port_get,
> +               .setter = ab_active_port_set,
> +       },
> +};
> +
> +int ab_init(struct team *team)
> +{
> +       team_options_register(team, ab_options, ARRAY_SIZE(ab_options));
> +       return 0;
> +}
> +
> +void ab_exit(struct team *team)
> +{
> +       team_options_unregister(team, ab_options, ARRAY_SIZE(ab_options));
> +}
> +
> +static const struct team_mode_ops ab_mode_ops = {
> +       .init                   = ab_init,
> +       .exit                   = ab_exit,
> +       .receive                = ab_receive,
> +       .transmit               = ab_transmit,
> +       .port_leave             = ab_port_leave,
> +       .port_change_mac        = ab_port_change_mac,
> +};
> +
> +static struct team_mode ab_mode = {
> +       .kind           = "activebackup",
> +       .owner          = THIS_MODULE,
> +       .priv_size      = sizeof(struct ab_priv),
> +       .ops            = &ab_mode_ops,
> +};
> +
> +static int __init ab_init_module(void)
> +{
> +       return team_mode_register(&ab_mode);
> +}
> +
> +static void __exit ab_cleanup_module(void)
> +{
> +       team_mode_unregister(&ab_mode);
> +}
> +
> +module_init(ab_init_module);
> +module_exit(ab_cleanup_module);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_AUTHOR("Jiri Pirko <jpirko@redhat.com>");
> +MODULE_DESCRIPTION("Active-backup mode for team");
> +MODULE_ALIAS("team-mode-activebackup");
> diff --git a/drivers/net/team/team_mode_roundrobin.c b/drivers/net/team/team_mode_roundrobin.c
> new file mode 100644
> index 0000000..0374052
> --- /dev/null
> +++ b/drivers/net/team/team_mode_roundrobin.c
> @@ -0,0 +1,107 @@
> +/*
> + * net/drivers/team/team_mode_roundrobin.c - Round-robin mode for team
> + * Copyright (c) 2011 Jiri Pirko <jpirko@redhat.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/types.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/errno.h>
> +#include <linux/netdevice.h>
> +#include <linux/if_team.h>
> +
> +struct rr_priv {
> +       unsigned int sent_packets;
> +};
> +
> +static struct rr_priv *rr_priv(struct team *team)
> +{
> +       return (struct rr_priv *) &team->mode_priv;
> +}
> +
> +static struct team_port *__get_first_port_up(struct team *team,
> +                                            struct team_port *port)
> +{
> +       struct team_port *cur;
> +
> +       if (port->linkup)
> +               return port;
> +       cur = port;
> +       list_for_each_entry_continue_rcu(cur, &team->port_list, list)
> +               if (cur->linkup)
> +                       return cur;
> +       list_for_each_entry_rcu(cur, &team->port_list, list) {
> +               if (cur == port)
> +                       break;
> +               if (cur->linkup)
> +                       return cur;
> +       }
> +       return NULL;
> +}
> +
> +static bool rr_transmit(struct team *team, struct sk_buff *skb)
> +{
> +       struct team_port *port;
> +       int port_index;
> +
> +       port_index = rr_priv(team)->sent_packets++ % team->port_count;
> +       port = team_get_port_by_index_rcu(team, port_index);
> +       port = __get_first_port_up(team, port);
> +       if (unlikely(!port))
> +               goto drop;
> +       skb->dev = port->dev;
> +       if (dev_queue_xmit(skb))
> +               return false;
> +       return true;
> +
> +drop:
> +       dev_kfree_skb(skb);
> +       return false;
> +}
> +
> +static int rr_port_enter(struct team *team, struct team_port *port)
> +{
> +       return team_port_set_team_mac(port);
> +}
> +
> +static void rr_port_change_mac(struct team *team, struct team_port *port)
> +{
> +       team_port_set_team_mac(port);
> +}
> +
> +static const struct team_mode_ops rr_mode_ops = {
> +       .transmit               = rr_transmit,
> +       .port_enter             = rr_port_enter,
> +       .port_change_mac        = rr_port_change_mac,
> +};
> +
> +static struct team_mode rr_mode = {
> +       .kind           = "roundrobin",
> +       .owner          = THIS_MODULE,
> +       .priv_size      = sizeof(struct rr_priv),
> +       .ops            = &rr_mode_ops,
> +};
> +
> +static int __init rr_init_module(void)
> +{
> +       return team_mode_register(&rr_mode);
> +}
> +
> +static void __exit rr_cleanup_module(void)
> +{
> +       team_mode_unregister(&rr_mode);
> +}
> +
> +module_init(rr_init_module);
> +module_exit(rr_cleanup_module);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_AUTHOR("Jiri Pirko <jpirko@redhat.com>");
> +MODULE_DESCRIPTION("Round-robin mode for team");
> +MODULE_ALIAS("team-mode-roundrobin");
> diff --git a/include/linux/Kbuild b/include/linux/Kbuild
> index 619b565..0b091b3 100644
> --- a/include/linux/Kbuild
> +++ b/include/linux/Kbuild
> @@ -185,6 +185,7 @@ header-y += if_pppol2tp.h
>  header-y += if_pppox.h
>  header-y += if_slip.h
>  header-y += if_strip.h
> +header-y += if_team.h
>  header-y += if_tr.h
>  header-y += if_tun.h
>  header-y += if_tunnel.h
> diff --git a/include/linux/if.h b/include/linux/if.h
> index db20bd4..06b6ef6 100644
> --- a/include/linux/if.h
> +++ b/include/linux/if.h
> @@ -79,6 +79,7 @@
>  #define IFF_TX_SKB_SHARING     0x10000 /* The interface supports sharing
>                                         * skbs on transmit */
>  #define IFF_UNICAST_FLT        0x20000         /* Supports unicast filtering   */
> +#define IFF_TEAM_PORT  0x40000         /* device used as team port */
>
>  #define IF_GET_IFACE   0x0001          /* for querying only */
>  #define IF_GET_PROTO   0x0002
> diff --git a/include/linux/if_team.h b/include/linux/if_team.h
> new file mode 100644
> index 0000000..21581a7
> --- /dev/null
> +++ b/include/linux/if_team.h
> @@ -0,0 +1,233 @@
> +/*
> + * include/linux/if_team.h - Network team device driver header
> + * Copyright (c) 2011 Jiri Pirko <jpirko@redhat.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef _LINUX_IF_TEAM_H_
> +#define _LINUX_IF_TEAM_H_
> +
> +#ifdef __KERNEL__
> +
> +struct team_pcpu_stats {
> +       u64                     rx_packets;
> +       u64                     rx_bytes;
> +       u64                     rx_multicast;
> +       u64                     tx_packets;
> +       u64                     tx_bytes;
> +       struct u64_stats_sync   syncp;
> +       u32                     rx_dropped;
> +       u32                     tx_dropped;
> +};
> +
> +struct team;
> +
> +struct team_port {
> +       struct net_device *dev;
> +       struct hlist_node hlist; /* node in hash list */
> +       struct list_head list; /* node in ordinary list */
> +       struct team *team;
> +       int index;
> +
> +       /*
> +        * A place for storing original values of the device before it
> +        * become a port.
> +        */
> +       struct {
> +               unsigned char dev_addr[MAX_ADDR_LEN];
> +               unsigned int mtu;
> +       } orig;
> +
> +       bool linkup;
> +       u32 speed;
> +       u8 duplex;
> +
> +       struct rcu_head rcu;
> +};
> +
> +struct team_mode_ops {
> +       int (*init)(struct team *team);
> +       void (*exit)(struct team *team);
> +       rx_handler_result_t (*receive)(struct team *team,
> +                                      struct team_port *port,
> +                                      struct sk_buff *skb);
> +       bool (*transmit)(struct team *team, struct sk_buff *skb);
> +       int (*port_enter)(struct team *team, struct team_port *port);
> +       void (*port_leave)(struct team *team, struct team_port *port);
> +       void (*port_change_mac)(struct team *team, struct team_port *port);
> +};
> +
> +enum team_option_type {
> +       TEAM_OPTION_TYPE_U32,
> +       TEAM_OPTION_TYPE_STRING,
> +};
> +
> +struct team_option {
> +       struct list_head list;
> +       const char *name;
> +       enum team_option_type type;
> +       int (*getter)(struct team *team, void *arg);
> +       int (*setter)(struct team *team, void *arg);
> +};
> +
> +struct team_mode {
> +       struct list_head list;
> +       const char *kind;
> +       struct module *owner;
> +       size_t priv_size;
> +       const struct team_mode_ops *ops;
> +};
> +
> +#define TEAM_MODE_PRIV_LONGS 4
> +#define TEAM_MODE_PRIV_SIZE (sizeof(long) * TEAM_MODE_PRIV_LONGS)
> +
> +struct team {
> +       struct net_device *dev; /* associated netdevice */
> +       struct team_pcpu_stats __percpu *pcpu_stats;
> +
> +       spinlock_t lock; /* used for overall locking, e.g. port lists write */
> +
> +       /*
> +        * port lists with port count
> +        */
> +       int port_count;
> +       struct hlist_head *port_hlist;
> +       struct list_head port_list;
> +
> +       struct list_head option_list;
> +
> +       const char *mode_kind;
> +       struct team_mode_ops mode_ops;
> +       long mode_priv[TEAM_MODE_PRIV_LONGS];
> +};
> +
> +#define TEAM_PORT_HASHBITS 4
> +#define TEAM_PORT_HASHENTRIES (1 << TEAM_PORT_HASHBITS)
> +
> +static inline struct hlist_head *
> +team_port_index_hash(const struct team *team,
> +                    int port_index)
> +{
> +       return &team->port_hlist[port_index & (TEAM_PORT_HASHENTRIES - 1)];
> +}
> +
> +static inline struct team_port *
> +team_get_port_by_index_rcu(const struct team *team,
> +                          int port_index)
> +{
> +       struct hlist_node *p;
> +       struct team_port *port;
> +       struct hlist_head *head = team_port_index_hash(team, port_index);
> +
> +       hlist_for_each_entry_rcu(port, p, head, hlist)
> +               if (port->index == port_index)
> +                       return port;
> +       return NULL;
> +}
> +
> +extern int team_port_set_orig_mac(struct team_port *port);
> +extern int team_port_set_team_mac(struct team_port *port);
> +extern void team_options_register(struct team *team,
> +                                 struct team_option *option,
> +                                 size_t option_count);
> +extern void team_options_unregister(struct team *team,
> +                                   struct team_option *option,
> +                                   size_t option_count);
> +extern int team_mode_register(struct team_mode *mode);
> +extern int team_mode_unregister(struct team_mode *mode);
> +
> +#endif /* __KERNEL__ */
> +
> +#define TEAM_STRING_MAX_LEN 32
> +
> +/**********************************
> + * NETLINK_GENERIC netlink family.
> + **********************************/
> +
> +enum {
> +       TEAM_CMD_NOOP,
> +       TEAM_CMD_OPTIONS_SET,
> +       TEAM_CMD_OPTIONS_GET,
> +       TEAM_CMD_PORT_LIST_GET,
> +
> +       __TEAM_CMD_MAX,
> +       TEAM_CMD_MAX = (__TEAM_CMD_MAX - 1),
> +};
> +
> +enum {
> +       TEAM_ATTR_UNSPEC,
> +       TEAM_ATTR_TEAM_IFINDEX,         /* u32 */
> +       TEAM_ATTR_LIST_OPTION,          /* nest */
> +       TEAM_ATTR_LIST_PORT,            /* nest */
> +
> +       __TEAM_ATTR_MAX,
> +       TEAM_ATTR_MAX = __TEAM_ATTR_MAX - 1,
> +};
> +
> +/* Nested layout of get/set msg:
> + *
> + *     [TEAM_ATTR_LIST_OPTION]
> + *             [TEAM_ATTR_ITEM_OPTION]
> + *                     [TEAM_ATTR_OPTION_*], ...
> + *             [TEAM_ATTR_ITEM_OPTION]
> + *                     [TEAM_ATTR_OPTION_*], ...
> + *             ...
> + *     [TEAM_ATTR_LIST_PORT]
> + *             [TEAM_ATTR_ITEM_PORT]
> + *                     [TEAM_ATTR_PORT_*], ...
> + *             [TEAM_ATTR_ITEM_PORT]
> + *                     [TEAM_ATTR_PORT_*], ...
> + *             ...
> + */
> +
> +enum {
> +       TEAM_ATTR_ITEM_OPTION_UNSPEC,
> +       TEAM_ATTR_ITEM_OPTION,          /* nest */
> +
> +       __TEAM_ATTR_ITEM_OPTION_MAX,
> +       TEAM_ATTR_ITEM_OPTION_MAX = __TEAM_ATTR_ITEM_OPTION_MAX - 1,
> +};
> +
> +enum {
> +       TEAM_ATTR_OPTION_UNSPEC,
> +       TEAM_ATTR_OPTION_NAME,          /* string */
> +       TEAM_ATTR_OPTION_CHANGED,       /* flag */
> +       TEAM_ATTR_OPTION_TYPE,          /* u8 */
> +       TEAM_ATTR_OPTION_DATA,          /* dynamic */
> +
> +       __TEAM_ATTR_OPTION_MAX,
> +       TEAM_ATTR_OPTION_MAX = __TEAM_ATTR_OPTION_MAX - 1,
> +};
> +
> +enum {
> +       TEAM_ATTR_ITEM_PORT_UNSPEC,
> +       TEAM_ATTR_ITEM_PORT,            /* nest */
> +
> +       __TEAM_ATTR_ITEM_PORT_MAX,
> +       TEAM_ATTR_ITEM_PORT_MAX = __TEAM_ATTR_ITEM_PORT_MAX - 1,
> +};
> +
> +enum {
> +       TEAM_ATTR_PORT_UNSPEC,
> +       TEAM_ATTR_PORT_IFINDEX,         /* u32 */
> +       TEAM_ATTR_PORT_CHANGED,         /* flag */
> +       TEAM_ATTR_PORT_LINKUP,          /* flag */
> +       TEAM_ATTR_PORT_SPEED,           /* u32 */
> +       TEAM_ATTR_PORT_DUPLEX,          /* u8 */
> +
> +       __TEAM_ATTR_PORT_MAX,
> +       TEAM_ATTR_PORT_MAX = __TEAM_ATTR_PORT_MAX - 1,
> +};
> +
> +/*
> + * NETLINK_GENERIC related info
> + */
> +#define TEAM_GENL_NAME "team"
> +#define TEAM_GENL_VERSION 0x1
> +#define TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME "change_event"
> +
> +#endif /* _LINUX_IF_TEAM_H_ */
> --
> 1.7.6
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply

* [U-Boot] [PATCH 14/17 V4] M28: Add MMC SPL
From: Robert Schwebel @ 2011-10-23 21:42 UTC (permalink / raw)
  To: u-boot
In-Reply-To: <1319237066-14954-15-git-send-email-marek.vasut@gmail.com>

Hi Marek,

On Sat, Oct 22, 2011 at 12:44:23AM +0200, Marek Vasut wrote:
>  board/denx/m28evk/power_init.c   |  913 ++++++++++++++++++++++++++++++++++++++

Shouldn't the power library functions go into
arch/arm/cpu/arm926ejs/mx28/? They are not m28evk specific and should be
re-usable by other MX28 boards.

rsc
-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply

* [PATCH v2 1/5] ARM: SPMP8000: Add machine base files
From: Zoltan Devai @ 2011-10-23 21:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1409922.Ostx0EbfK3@wuerfel>

2011/10/19 Arnd Bergmann <arnd@arndb.de>:
> On Wednesday 19 October 2011 18:01:54 Zoltan Devai wrote:
>> Files needed for the basic machine support of SPMP8000
>>
>> Signed-off-by: Zoltan Devai <zoss@devai.org>
>
> Hi Zoltan,
>
> This version looks very nice, only a few small things remain that I noticed
> reading through it again:
OK, will correct these.

What's next then ?
I assume I'd need some more review on at least the dts file.
Also, can the timer code go through your tree into drivers/clocksource ?

Thanks,
Zoltan

^ permalink raw reply

* [U-Boot] [PATCH v2] NS16550: buffer reads
From: Graeme Russ @ 2011-10-23 21:32 UTC (permalink / raw)
  To: u-boot
In-Reply-To: <20111023212231.396E81408771@gemini.denx.de>

Hi Wolfgang,

On Monday, October 24, 2011, Wolfgang Denk <wd@denx.de> wrote:
> Dear Graeme Russ,
>
> In message <CALButCK0oVLTbYxbTF=y-vXL+3+=
09VEJpzUnX1+-0SYJQEQJA@mail.gmail.com> you wrote:
>>
>> > > So how does kermit/ymodem send the XON after the user has entered the
>> > > receive command and we have sent the XOFF after the newline?
>> >
>> > Upon the first getc() that follows?
>>
>> And as there will be no corresponding newline, when do we send XOFF?
>
> Never?  Note that kermit / ymodem / S-record download etc. all don't
> have any issues with sendign characters back-to-back at line speed.
>
> Problems happen only with multi-line input, so it is perfectly fine
> to handle just that - at the root cause, i. e. when input turns into
> multi-line input.

Can the U-Boot command line handle multiple commands per line (delimited by
; for example)

If so, could it not be possible that a Kermit/ymodem command followed by a
time consuming command on the same line cause lost input?

Regards,

Graeme

^ permalink raw reply

* Re: [PATCHv2 3/3] completion: match ctags symbol names in grep patterns
From: SZEDER Gábor @ 2011-10-23 21:29 UTC (permalink / raw)
  To: Jeff King; +Cc: git
In-Reply-To: <20111021173021.GC24417@sigill.intra.peff.net>

Hi,

On Fri, Oct 21, 2011 at 01:30:21PM -0400, Jeff King wrote:
> This incorporates the suggestions from Gábor's review, with one
> exception: it still looks only in the current directory for the "tags"
> files. I think that might have some performance implications, so I'd
> rather add it separately, if at all.

I agree that scanning through a whole working tree for tags files
would cost too much.  But I think that a tags file at the top of the
working tree is common enough to be supported, and checking its
existence is fairly cheap.

> +	case "$cword,$prev" in
> +	2,*|*,-*)
> +		if test -r tags; then
> +			__gitcomp "$(__git_match_ctag "$cur" tags)"
> +			return
> +		fi
> +		;;

So how about something like this for the case arm? (I didn't actually
tested it.)

		local tagsfile
		if test -r tags; then
			tagsfile=tags
		else
			local dir="$(__gitdir)"
			if test -r "$dir"/tags; then
				tagsfile="$dir"/tags
			fi
		fi
		if [ -n "tagsfile" ]; then
			__gitcomp "$(__git_match_ctag "$cur" "$tagsfile")"
			return
		fi


Btw, there is a bug in the case statement: 'git --no-pager grep <TAB>'
offers refs instead of symbols, because $cword is not 2 and $prev
doesn't start with a dash.  But it's not worse than the current
behavior, so I don't think this bug is a show-stopper for the patch.


Best,
Gábor

^ permalink raw reply

* [RFC][PATCH] uncompress.h cleanup and DT support
From: Zoltan Devai @ 2011-10-23 21:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20111023092059.GB12814@n2100.arm.linux.org.uk>

2011/10/23 Russell King - ARM Linux <linux@arm.linux.org.uk>:
> On Sun, Oct 23, 2011 at 11:12:50AM +0200, Zoltan Devai wrote:
>> 2011/10/23 Russell King - ARM Linux <linux@arm.linux.org.uk>:
>> > On Sun, Oct 23, 2011 at 10:18:29AM +0200, Zoltan Devai wrote:
>> >> Plase consider all this as RFC, it's mostly not even compile-tested.
>> >> If you think it's worth to follow-up, I'm happy to do it.
>> >
>> > Is the patch available?
>> git://github.com/zdevai/linux.git uncompress-h
>
> I'd rather not pull your tree just to look at the patch. ?Is it
> available somewhere else?
Submitted as patches.
I tried to make the whole series bisectable, which is why it contains
some extra steps, and didn't want to spam everybody's inbox
with this noise.

>> > Has this been tested with ZBOOT_ROM?
>> Not yet, but I don't see a reason why this would break it.
> Please try building it with ZBOOT_ROM enabled.
I did build it, which worked.
Problem is, I don't have a machine which could actually do
ZBOOT_ROM, so I can't test it that way.
(I could execute the image from RAM, but I assume that's
not a good test scenario)

Z

^ permalink raw reply

* linux-ti33x-psp_3.0+3.1rc SRCREV
From: Fernandes, Joel A @ 2011-10-23 21:27 UTC (permalink / raw)
  To: meta-ti@yoctoproject.org

[-- Attachment #1: Type: text/plain, Size: 526 bytes --]

Dear Koen,

In the last update to SRCREV,
http://git.angstrom-distribution.org/cgi-bin/cgit.cgi/meta-texasinstruments/commit/?id=ab07a0ea4be961a7e8c7b8b64a56ce6c730cd6e0

The Commit: c7fc664a6a36a4721b43dc287e410a2453f0b782 doesn't exist anymore in arago. Due to this the fetch breaks.

joel@minted ~/repo/linux-omap-2.6 $ git show c7fc664a6a36a4721b43dc287e410a2453f0b782
fatal: bad object c7fc664a6a36a4721b43dc287e410a2453f0b782

Either the Arago tree was rebased or the commit ID is not valid.

Thanks,
Joel

[-- Attachment #2: Type: text/html, Size: 2779 bytes --]

^ permalink raw reply

* Re: iwlagn is getting very shaky
From: David Rientjes @ 2011-10-23 21:26 UTC (permalink / raw)
  To: Norbert Preining
  Cc: wwguy, linux-kernel@vger.kernel.org,
	ipw3945-devel@lists.sourceforge.net, ilw@linux.intel.com,
	linux-wireless@vger.kernel.org, Pekka Enberg
In-Reply-To: <20111021012442.GB26758@gamma.logic.tuwien.ac.at>

On Fri, 21 Oct 2011, Norbert Preining wrote:

> > Great, this is just a test patch, we will figure out what is the correct
> > way to handle this and fix the issue for good :-)
> 
> Thanks. If you need more testing just let me know.
> 

It'd be interesting to see if this problem still exists in linux-next 
since some wireless changes went into that recently.  Please try the tree 
at git://github.com/sfrothwell/linux-next.git

^ permalink raw reply

* [non-quoted-printable PATCH] Fix caif BUG() with network namespaces
From: Woodhouse, David @ 2011-10-23 21:24 UTC (permalink / raw)
  To: Sjur Brændeland, davem@redhat.com; +Cc: netdev@vger.kernel.org
In-Reply-To: <CAJK669a0cX73J0pEr3EtCkbxsaHRfxnS-56Q3Q5ANdKd47mnrg@mail.gmail.com>

The caif code will register its own pernet_operations, and then register
a netdevice_notifier. Each time the netdevice_notifier is triggered,
it'll do some stuff... including a lookup of its own pernet stuff with
net_generic().

If the net_generic() call ever returns NULL, the caif code will BUG().
That doesn't seem *so* unreasonable, I suppose — it does seem like it
should never happen.

However, it *does* happen. When we clone a network namespace,
setup_net() runs through all the pernet_operations one at a time. It
gets to loopback before it gets to caif. And loopback_net_init()
registers a netdevice... while caif hasn't been initialised. So the caif
netdevice notifier triggers, and immediately goes BUG().

I'm not entirely sure how best to fix this in the general case. Perhaps
the netdevice_notifier registration should be pernet too, rather than
global? Or perhaps we should suppress the notifier calls during
setup_net() and flush them at the end after everything has been
initialised?

But really, I'm inclined to just take the simple approach. Make
caif_device_notify() *not* go looking for its pernet data structures if
the device it's being notified about isn't a caif device in the first
place. This simple patch is sufficient to avoid the problem, and is
probably good enough.

Cc: stable@kernel.org
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>

---
Sorry, forgot to disable signature on previous patch so it got sent as
QP. This should be better.

diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c
index 7f9ac07..47fc8f3 100644
--- a/net/caif/caif_dev.c
+++ b/net/caif/caif_dev.c
@@ -212,8 +212,7 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what,
 	enum cfcnfg_phy_preference pref;
 	enum cfcnfg_phy_type phy_type;
 	struct cfcnfg *cfg;
-	struct caif_device_entry_list *caifdevs =
-	    caif_device_list(dev_net(dev));
+	struct caif_device_entry_list *caifdevs;
 
 	if (dev->type != ARPHRD_CAIF)
 		return 0;
@@ -222,6 +221,8 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what,
 	if (cfg == NULL)
 		return 0;
 
+	caifdevs = caif_device_list(dev_net(dev));
+
 	switch (what) {
 	case NETDEV_REGISTER:
 		caifd = caif_device_alloc(dev);


                   Sent with MeeGo's ActiveSync support.

David Woodhouse                            Open Source Technology Centre
David.Woodhouse@intel.com                              Intel Corporation




^ permalink raw reply related

* LVM2/test t-mdata-strings.sh
From: zkabelac @ 2011-10-23 21:24 UTC (permalink / raw)
  To: lvm-devel

CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	zkabelac at sourceware.org	2011-10-23 21:24:27

Modified files:
	test           : t-mdata-strings.sh 

Log message:
	Test with -F flag
	
	grep need -F to check what we really want to test.
	Add better test for existing device.
	
	Currently this test DOES NOT work with real /dev handle via udev
	since our tool does not see such device listet through udev.
	
	FIXME: We might be able to see it at least through dmsetup table and
	use for lvm.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/test/t-mdata-strings.sh.diff?cvsroot=lvm2&r1=1.7&r2=1.8

--- LVM2/test/t-mdata-strings.sh	2011/10/23 15:39:08	1.7
+++ LVM2/test/t-mdata-strings.sh	2011/10/23 21:24:27	1.8
@@ -23,11 +23,14 @@
 dmsetup rename "$name" "$PREFIX$pv_ugly"
 dev1=$(dirname "$dev1")/$PREFIX$pv_ugly
 
+dmsetup table | grep -F "$pv_ugly"
+
 # 'pvcreate, vgcreate on filename with backslashed chars' 
 created=$dev1
 # when used with real udev without fallback, it will fail here
 pvcreate "$dev1" || created=$dev2
-pvs | should grep $dev1
+pvdisplay | should grep -F "$pv_ugly"
+should check pv_field "$dev1" pv_name "$dev1"
 vgcreate $vg "$created"
 # 'no parse errors and VG really exists' 
 vgs 2>err



^ permalink raw reply

* [lm-sensors] Fan speed on DH67CF
From: Shen Tian @ 2011-10-23 21:23 UTC (permalink / raw)
  To: lm-sensors

Hi

I'm struggling to get the right fan speed on an Intel DH67CF board.
I've set lm-sensor us using this configuration sheet:
http://lm-sensors.org/wiki/Configurations/Intel/DH67BL (not the exact
right model, I know), and am getting a reading of 24RPM from fan2. Any
thing I could try?

Core i3 2100T
Ubuntu 11.10 amd64
lm-sensor 3.3.0

Thanks!
Shen

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply

* RE: [PATCH -v2 -mm] add extra free kbytes tunable
From: David Rientjes @ 2011-10-23 21:22 UTC (permalink / raw)
  To: Satoru Moriya
  Cc: Rik van Riel, Andrew Morton, Randy Dunlap, Satoru Moriya,
	linux-kernel@vger.kernel.org, linux-mm@kvack.org,
	lwoodman@redhat.com, Seiji Aguchi, hughd@google.com,
	hannes@cmpxchg.org
In-Reply-To: <65795E11DBF1E645A09CEC7EAEE94B9CB4F747B1@USINDEVS02.corp.hds.com>

On Fri, 21 Oct 2011, Satoru Moriya wrote:

> We do.
> Basically we need this kind of feature for almost all our latency
> sensitive applications to avoid latency issue in memory allocation.
> 

These are all realtime?

> Currently we run those applications on custom kernels which this
> kind of patch is applied to. But it is hard for us to support every
> kernel version for it. Also there are several customers who can't
> accept a custom kernel and so they must use other commercial Unix.
> If this feature is accepted, they will definitely use it on their
> systems.
> 

That's precisely the problem, it's behavior is going to vary widely from 
version to version as the implementation changes for reclaim and 
compaction.  I think we can do much better with the priority of kswapd and 
reclaiming above the high watermark for threads that need a surplus of 
extra memory because they are realtime, two things we can easily do.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* RE: [PATCH -v2 -mm] add extra free kbytes tunable
From: David Rientjes @ 2011-10-23 21:22 UTC (permalink / raw)
  To: Satoru Moriya
  Cc: Rik van Riel, Andrew Morton, Randy Dunlap, Satoru Moriya,
	linux-kernel@vger.kernel.org, linux-mm@kvack.org,
	lwoodman@redhat.com, Seiji Aguchi, hughd@google.com,
	hannes@cmpxchg.org
In-Reply-To: <65795E11DBF1E645A09CEC7EAEE94B9CB4F747B1@USINDEVS02.corp.hds.com>

On Fri, 21 Oct 2011, Satoru Moriya wrote:

> We do.
> Basically we need this kind of feature for almost all our latency
> sensitive applications to avoid latency issue in memory allocation.
> 

These are all realtime?

> Currently we run those applications on custom kernels which this
> kind of patch is applied to. But it is hard for us to support every
> kernel version for it. Also there are several customers who can't
> accept a custom kernel and so they must use other commercial Unix.
> If this feature is accepted, they will definitely use it on their
> systems.
> 

That's precisely the problem, it's behavior is going to vary widely from 
version to version as the implementation changes for reclaim and 
compaction.  I think we can do much better with the priority of kswapd and 
reclaiming above the high watermark for threads that need a surplus of 
extra memory because they are realtime, two things we can easily do.

^ permalink raw reply

* [U-Boot] [PATCH v4 2/2] NS16550: buffer reads
From: Wolfgang Denk @ 2011-10-23 21:22 UTC (permalink / raw)
  To: u-boot
In-Reply-To: <CALButCK0oVLTbYxbTF=y-vXL+3+=09VEJpzUnX1+-0SYJQEQJA@mail.gmail.com>

Dear Graeme Russ,

In message <CALButCK0oVLTbYxbTF=y-vXL+3+=09VEJpzUnX1+-0SYJQEQJA@mail.gmail.com> you wrote:
>
> > > So how does kermit/ymodem send the XON after the user has entered the
> > > receive command and we have sent the XOFF after the newline?
> >
> > Upon the first getc() that follows?
> 
> And as there will be no corresponding newline, when do we send XOFF?

Never?  Note that kermit / ymodem / S-record download etc. all don't
have any issues with sendign characters back-to-back at line speed.

Problems happen only with multi-line input, so it is perfectly fine
to handle just that - at the root cause, i. e. when input turns into
multi-line input.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Include the success of others in your dreams for your own success.

^ permalink raw reply

* [PATCH] Fix caif BUG() with network namespaces
From: Woodhouse, David @ 2011-10-23 21:21 UTC (permalink / raw)
  To: Sjur Brændeland, davem@redhat.com; +Cc: netdev@vger.kernel.org
In-Reply-To: <CAJK669a0cX73J0pEr3EtCkbxsaHRfxnS-56Q3Q5ANdKd47mnrg@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 2404 bytes --]

The caif code will register its own pernet_operations, and then register
a netdevice_notifier. Each time the netdevice_notifier is triggered,
it'll do some stuff... including a lookup of its own pernet stuff with
net_generic().

If the net_generic() call ever returns NULL, the caif code will BUG().
That doesn't seem *so* unreasonable, I suppose — it does seem like it
should never happen.

However, it *does* happen. When we clone a network namespace,
setup_net() runs through all the pernet_operations one at a time. It
gets to loopback before it gets to caif. And loopback_net_init()
registers a netdevice... while caif hasn't been initialised. So the caif
netdevice notifier triggers, and immediately goes BUG().

I'm not entirely sure how best to fix this in the general case. Perhaps
the netdevice_notifier registration should be pernet too, rather than
global? Or perhaps we should suppress the notifier calls during
setup_net() and flush them at the end after everything has been
initialised?

But really, I'm inclined to just take the simple approach. Make
caif_device_notify() *not* go looking for its pernet data structures if
the device it's being notified about isn't a caif device in the first
place. This simple patch is sufficient to avoid the problem, and is
probably good enough.

Cc: stable@kernel.org
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>

diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c
index 7f9ac07..47fc8f3 100644
--- a/net/caif/caif_dev.c
+++ b/net/caif/caif_dev.c
@@ -212,8 +212,7 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what,
 	enum cfcnfg_phy_preference pref;
 	enum cfcnfg_phy_type phy_type;
 	struct cfcnfg *cfg;
-	struct caif_device_entry_list *caifdevs =
-	    caif_device_list(dev_net(dev));
+	struct caif_device_entry_list *caifdevs;
 
 	if (dev->type != ARPHRD_CAIF)
 		return 0;
@@ -222,6 +221,8 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what,
 	if (cfg == NULL)
 		return 0;
 
+	caifdevs = caif_device_list(dev_net(dev));
+
 	switch (what) {
 	case NETDEV_REGISTER:
 		caifd = caif_device_alloc(dev);


                   Sent with MeeGo's ActiveSync support.

David Woodhouse                            Open Source Technology Centre
David.Woodhouse@intel.com                              Intel Corporation



[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 4370 bytes --]

^ permalink raw reply related

* -next: NET_VENDOR_8390 dependencies
From: Geert Uytterhoeven @ 2011-10-23 21:21 UTC (permalink / raw)
  To: Jeff Kirsher; +Cc: netdev, linux-kernel

drivers/net/ethernet/8390/Kconfig:

config NET_VENDOR_8390
        bool "National Semi-conductor 8390 devices"
        default y
        depends on NET_VENDOR_NATSEMI && (AMIGA_PCMCIA || PCI || SUPERH || \
                   ISA || MCA || EISA || MAC || M32R || MACH_TX49XX || \
                   MCA_LEGACY || H8300 || ARM || MIPS || ZORRO || PCMCIA || \
                   EXPERIMENTAL)
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
          and read the Ethernet-HOWTO, available from
          <http://www.tldp.org/docs.html#howto>.

          Note that the answer to this question doesn't directly affect the
          kernel: saying N will just cause the configurator to skip all
          the questions about Western Digital cards. If you say Y, you will be
          asked for your specific card in the following questions.

So NET_VENDOR_8390 depends on NET_VENDOR_NATSEMI.

drivers/net/ethernet/natsemi/Kconfig:

config NET_VENDOR_NATSEMI
        bool "National Semi-conductor devices"
        default y
        depends on MCA || MAC || MACH_JAZZ || PCI || XTENSA_PLATFORM_XT2000
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
          and read the Ethernet-HOWTO, available from
          <http://www.tldp.org/docs.html#howto>.

          Note that the answer to this question doesn't directly affect the
          kernel: saying N will just cause the configurator to skip all
          the questions about National Semi-conductor devices. If you say Y,
          you will be asked for your specific card in the following questions.

But NET_VENDOR_NATSEMI will never be true for several of the other
dependencies of NET_VENDOR_8390 (e.g. AMIGA_PCMCIA, EISA, H8300, ARM,
ZORRO, PCMCIA)?

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* [RFC][PATCH] uncompress.h cleanup and DT support
From: Zoltan Devai @ 2011-10-23 21:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20111023090247.GH2638@game.jcrosoft.org>

2011/10/23 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>:
> On 10:18 Sun 23 Oct ? ? , Zoltan Devai wrote:
>> Hi,
>>
>> Originally, I just wanted to get rid of arch_decomp_* in all the uncompress.h
>> files, that were mostly empty. But then, I couldn't stop. Which may also mean
>> I have gone too far.
> on small SoC arm926 the kernel may more time that the watchdog refreshing so
> the kernel will never have enough time to decompress
Sure, but:
- only Samsung was using it (with optional Kconfig)
- the feature wasn't working since ARM moved to use the decompress_* libs
  instead of inflate.c (2.6.33)

Carrying around a 95% empty definition, that does nothing even when not
empty, doesn't make sense.
If someone needs a decomp_wdog, he needs to re-implement it from scratch,
using the new decompressor libraries.

Z

^ permalink raw reply

* Re: [PATCH] x86: Fix compilation bug in kprobes' twobyte_is_boostable
From: Linus Torvalds @ 2011-10-23 21:19 UTC (permalink / raw)
  To: Josh Stone
  Cc: linux-kernel, Masami Hiramatsu, Thomas Gleixner, Ingo Molnar,
	H. Peter Anvin, x86, Srikar Dronamraju, Jakub Jelinek
In-Reply-To: <4EA449DD.1010801@redhat.com>

On Sun, Oct 23, 2011 at 7:07 PM, Josh Stone <jistone@redhat.com> wrote:
>
> Unfortunately, no.  Whatever const-propagation gcc is doing here
> (somewhat wrongly per PR50571) is not affected by volatile on that cast.
>  I also tried leaving it to the parameter type (no cast), no help.

Oh, ok.

> I just tried removing the const from twobyte_is_boostable[], and that
> also does the trick.  Not sure why I didn't try that first -- I guess
> because I saw all the volatiles in bitops.  Is that more palatable, or
> would you still rather try to fix it in bitops.h directly?

I guess there's no nice bitops.h fix, so maybe the minimal "remove
const" is the right thing to do.

>>  - Long long ago, we had that "big array" approach for ADDR too. So
>> we've wavered between the volatile and using a block memory op. But
>> we've used the "volatile" for a long time now for the bit change ones,
>> so I don't think we should mix concepts like your patch.
>
> Do you recall why it settled on volatile?  That seems like the less
> descriptive of the two approaches.  But "long long ago" appears to be
> beyond recorded (git) history...

Yeah, it's really long ago. Iirc the reason it got removed was that
there were gcc versions that were unhappy about it, we've had problems
in this area before..

             Linus

^ permalink raw reply

* [PATCH 3/5] m68k/serial: Remove obsolete IRQ_FLG_* users
From: Geert Uytterhoeven @ 2011-10-23 21:18 UTC (permalink / raw)
  To: linux-m68k, linux-kernel; +Cc: Geert Uytterhoeven, Greg Kroah-Hartman, devel
In-Reply-To: <1319404686-10800-1-git-send-email-geert@linux-m68k.org>

The m68k core irq code stopped honoring these flags during the irq
restructuring in 2006.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: devel@driverdev.osuosl.org
---
This is a split-up of "m68k/irq: Remove obsolete IRQ_FLG_* definitions and
users", to reduce conflicts and dependencies.

diff --git a/drivers/tty/serial/68360serial.c b/drivers/tty/serial/68360serial.c
index 0a3e878..daf0b1d 100644
--- a/drivers/staging/serial/68360serial.c
+++ b/drivers/staging/serial/68360serial.c
@@ -2771,8 +2771,8 @@ static int __init rs_360_init(void)
 			*/
 			/* cpm_install_handler(IRQ_MACHSPEC | state->irq, rs_360_interrupt, info);  */
 			/*request_irq(IRQ_MACHSPEC | state->irq, rs_360_interrupt, */
-			request_irq(state->irq, rs_360_interrupt,
-						IRQ_FLG_LOCK, "ttyS", (void *)info);
+			request_irq(state->irq, rs_360_interrupt, 0, "ttyS",
+				    (void *)info);
 
 			/* Set up the baud rate generator.
 			*/
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 4/5] m68k/irq: Remove obsolete IRQ_FLG_* users
From: Geert Uytterhoeven @ 2011-10-23 21:18 UTC (permalink / raw)
  To: linux-m68k, linux-kernel; +Cc: Geert Uytterhoeven
In-Reply-To: <1319404686-10800-1-git-send-email-geert@linux-m68k.org>

The m68k core irq code stopped honoring these flags during the irq
restructuring in 2006.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
This is a split-up of "m68k/irq: Remove obsolete IRQ_FLG_* definitions and
users", to reduce conflicts and remove dependencies.

diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c
index 0daa7fc..e5f3033 100644
--- a/arch/m68k/amiga/amiints.c
+++ b/arch/m68k/amiga/amiints.c
@@ -4,35 +4,6 @@
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file COPYING in the main directory of this archive
  * for more details.
- *
- * 11/07/96: rewritten interrupt handling, irq lists are exists now only for
- *           this sources where it makes sense (VERTB/PORTS/EXTER) and you must
- *           be careful that dev_id for this sources is unique since this the
- *           only possibility to distinguish between different handlers for
- *           free_irq. irq lists also have different irq flags:
- *           - IRQ_FLG_FAST: handler is inserted at top of list (after other
- *                           fast handlers)
- *           - IRQ_FLG_SLOW: handler is inserted at bottom of list and before
- *                           they're executed irq level is set to the previous
- *                           one, but handlers don't need to be reentrant, if
- *                           reentrance occurred, slow handlers will be just
- *                           called again.
- *           The whole interrupt handling for CIAs is moved to cia.c
- *           /Roman Zippel
- *
- * 07/08/99: rewamp of the interrupt handling - we now have two types of
- *           interrupts, normal and fast handlers, fast handlers being
- *           marked with IRQF_DISABLED and runs with all other interrupts
- *           disabled. Normal interrupts disable their own source but
- *           run with all other interrupt sources enabled.
- *           PORTS and EXTER interrupts are always shared even if the
- *           drivers do not explicitly mark this when calling
- *           request_irq which they really should do.
- *           This is similar to the way interrupts are handled on all
- *           other architectures and makes a ton of sense besides
- *           having the advantage of making it easier to share
- *           drivers.
- *           /Jes
  */
 
 #include <linux/init.h>
diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c
index f6312c7..c87fe69 100644
--- a/arch/m68k/hp300/time.c
+++ b/arch/m68k/hp300/time.c
@@ -70,7 +70,7 @@ void __init hp300_sched_init(irq_handler_t vector)
 
   asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE));
 
-  if (request_irq(IRQ_AUTO_6, hp300_tick, IRQ_FLG_STD, "timer tick", vector))
+  if (request_irq(IRQ_AUTO_6, hp300_tick, 0, "timer tick", vector))
     pr_err("Couldn't register timer interrupt\n");
 
   out_8(CLOCKBASE + CLKCR2, 0x1);		/* select CR1 */
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c
index 15dbbe2..f6a4698 100644
--- a/arch/m68k/kernel/ints.c
+++ b/arch/m68k/kernel/ints.c
@@ -4,25 +4,6 @@
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file COPYING in the main directory of this archive
  * for more details.
- *
- * 07/03/96: Timer initialization, and thus mach_sched_init(),
- *           removed from request_irq() and moved to init_time().
- *           We should therefore consider renaming our add_isr() and
- *           remove_isr() to request_irq() and free_irq()
- *           respectively, so they are compliant with the other
- *           architectures.                                     /Jes
- * 11/07/96: Changed all add_/remove_isr() to request_/free_irq() calls.
- *           Removed irq list support, if any machine needs an irq server
- *           it must implement this itself (as it's already done), instead
- *           only default handler are used with mach_default_handler.
- *           request_irq got some flags different from other architectures:
- *           - IRQ_FLG_REPLACE : Replace an existing handler (the default one
- *                               can be replaced without this flag)
- *           - IRQ_FLG_LOCK : handler can't be replaced
- *           There are other machine depending flags, see there
- *           If you want to replace a default handler you should know what
- *           you're doing, since it might handle different other irq sources
- *           which must be served                               /Roman Zippel
  */
 
 #include <linux/module.h>
diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c
index 1ad4e9d..a5462cc 100644
--- a/arch/m68k/mac/iop.c
+++ b/arch/m68k/mac/iop.c
@@ -305,15 +305,13 @@ void __init iop_register_interrupts(void)
 {
 	if (iop_ism_present) {
 		if (oss_present) {
-			if (request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq,
-					IRQ_FLG_LOCK, "ISM IOP",
-					(void *) IOP_NUM_ISM))
+			if (request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq, 0,
+					"ISM IOP", (void *)IOP_NUM_ISM))
 				pr_err("Couldn't register ISM IOP interrupt\n");
 			oss_irq_enable(IRQ_MAC_ADB);
 		} else {
-			if (request_irq(IRQ_VIA2_0, iop_ism_irq,
-					IRQ_FLG_LOCK|IRQ_FLG_FAST, "ISM IOP",
-					(void *) IOP_NUM_ISM))
+			if (request_irq(IRQ_VIA2_0, iop_ism_irq, 0, "ISM IOP",
+					(void *)IOP_NUM_ISM))
 				pr_err("Couldn't register ISM IOP interrupt\n");
 		}
 		if (!iop_alive(iop_base[IOP_NUM_ISM])) {
diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c
index ad51241..1eb60f0 100644
--- a/arch/m68k/mac/oss.c
+++ b/arch/m68k/mac/oss.c
@@ -65,17 +65,14 @@ void __init oss_init(void)
 
 void __init oss_register_interrupts(void)
 {
-	if (request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
-			"scsi", (void *) oss))
+	if (request_irq(OSS_IRQLEV_SCSI, oss_irq, 0, "scsi", (void *)oss))
 		pr_err("Couldn't register %s interrupt\n", "scsi");
-	if (request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
-			"nubus", (void *) oss))
+	if (request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, 0, "nubus",
+			(void *)oss))
 		pr_err("Couldn't register %s interrupt\n", "nubus");
-	if (request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
-			"sound", (void *) oss))
+	if (request_irq(OSS_IRQLEV_SOUND, oss_irq, 0, "sound", (void *)oss))
 		pr_err("Couldn't register %s interrupt\n", "sound");
-	if (request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
-			"via1", (void *) via1))
+	if (request_irq(OSS_IRQLEV_VIA1, via1_irq, 0, "via1", (void *)via1))
 		pr_err("Couldn't register %s interrupt\n", "via1");
 }
 
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index 0678570..af9ed33 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -281,7 +281,7 @@ void __init via_init_clock(irq_handler_t func)
 	via1[vT1CL] = MAC_CLOCK_LOW;
 	via1[vT1CH] = MAC_CLOCK_HIGH;
 
-	if (request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func))
+	if (request_irq(IRQ_MAC_TIMER_1, func, 0, "timer", func))
 		pr_err("Couldn't register %s interrupt\n", "timer");
 }
 
@@ -292,25 +292,19 @@ void __init via_init_clock(irq_handler_t func)
 void __init via_register_interrupts(void)
 {
 	if (via_alt_mapping) {
-		if (request_irq(IRQ_AUTO_1, via1_irq,
-				IRQ_FLG_LOCK|IRQ_FLG_FAST, "software",
-				(void *) via1))
+		if (request_irq(IRQ_AUTO_1, via1_irq, 0, "software",
+				(void *)via1))
 			pr_err("Couldn't register %s interrupt\n", "software");
-		if (request_irq(IRQ_AUTO_6, via1_irq,
-				IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
-				(void *) via1))
+		if (request_irq(IRQ_AUTO_6, via1_irq, 0, "via1", (void *)via1))
 			pr_err("Couldn't register %s interrupt\n", "via1");
 	} else {
-		if (request_irq(IRQ_AUTO_1, via1_irq,
-				IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
-				(void *) via1))
+		if (request_irq(IRQ_AUTO_1, via1_irq, 0, "via1", (void *)via1))
 			pr_err("Couldn't register %s interrupt\n", "via1");
 	}
-	if (request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
-			"via2", (void *) via2))
+	if (request_irq(IRQ_AUTO_2, via2_irq, 0, "via2", (void *)via2))
 		pr_err("Couldn't register %s interrupt\n", "via2");
-	if (request_irq(IRQ_MAC_NUBUS, via_nubus_irq,
-			IRQ_FLG_LOCK|IRQ_FLG_FAST, "nubus", (void *) via2))
+	if (request_irq(IRQ_MAC_NUBUS, via_nubus_irq, 0, "nubus",
+			(void *)via2))
 		pr_err("Couldn't register %s interrupt\n", "nubus");
 }
 
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
index 6cb9c3a..01f2adf 100644
--- a/arch/m68k/mvme147/config.c
+++ b/arch/m68k/mvme147/config.c
@@ -114,8 +114,7 @@ static irqreturn_t mvme147_timer_int (int irq, void *dev_id)
 void mvme147_sched_init (irq_handler_t timer_routine)
 {
 	tick_handler = timer_routine;
-	if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, IRQ_FLG_REPLACE,
-			"timer 1", NULL))
+	if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, 0, "timer 1", NULL))
 		pr_err("Couldn't register timer interrupt\n");
 
 	/* Init the clock with a value */
diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c
index 817f37a..c9570fc 100644
--- a/drivers/macintosh/via-macii.c
+++ b/drivers/macintosh/via-macii.c
@@ -159,7 +159,7 @@ int macii_init(void)
 	err = macii_init_via();
 	if (err) goto out;
 
-	err = request_irq(IRQ_MAC_ADB, macii_interrupt, IRQ_FLG_LOCK, "ADB",
+	err = request_irq(IRQ_MAC_ADB, macii_interrupt, 0, "ADB",
 			  macii_interrupt);
 	if (err) goto out;
 
diff --git a/drivers/macintosh/via-maciisi.c b/drivers/macintosh/via-maciisi.c
index 9ab5b0c..34d02a9 100644
--- a/drivers/macintosh/via-maciisi.c
+++ b/drivers/macintosh/via-maciisi.c
@@ -122,8 +122,8 @@ maciisi_init(void)
 		return err;
 	}
 
-	if (request_irq(IRQ_MAC_ADB, maciisi_interrupt, IRQ_FLG_LOCK | IRQ_FLG_FAST, 
-			"ADB", maciisi_interrupt)) {
+	if (request_irq(IRQ_MAC_ADB, maciisi_interrupt, 0, "ADB",
+			maciisi_interrupt)) {
 		printk(KERN_ERR "maciisi_init: can't get irq %d\n", IRQ_MAC_ADB);
 		return -EAGAIN;
 	}

^ permalink raw reply related

* [PATCH 2/5] m68k/scsi: Remove obsolete IRQ_FLG_* users
From: Geert Uytterhoeven @ 2011-10-23 21:18 UTC (permalink / raw)
  To: linux-m68k, linux-kernel
  Cc: Geert Uytterhoeven, James E.J. Bottomley, linux-scsi
In-Reply-To: <1319404686-10800-1-git-send-email-geert@linux-m68k.org>

The m68k core irq code stopped honoring these flags during the irq
restructuring in 2006.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: "James E.J. Bottomley" <JBottomley@parallels.com>
Cc: linux-scsi@vger.kernel.org
---
This is a split-up of "m68k/irq: Remove obsolete IRQ_FLG_* definitions and
users", to reduce conflicts and dependencies.

diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
index af3a6af..ea2bde2 100644
--- a/drivers/scsi/mac_scsi.c
+++ b/drivers/scsi/mac_scsi.c
@@ -291,8 +291,7 @@ int __init macscsi_detect(struct scsi_host_template * tpnt)
     ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
 
     if (instance->irq != SCSI_IRQ_NONE)
-	if (request_irq(instance->irq, NCR5380_intr, IRQ_FLG_SLOW, 
-			"ncr5380", instance)) {
+	if (request_irq(instance->irq, NCR5380_intr, 0, "ncr5380", instance)) {
 	    printk(KERN_WARNING "scsi%d: IRQ%d not free, interrupts disabled\n",
 		   instance->host_no, instance->irq);
 	    instance->irq = SCSI_IRQ_NONE;

^ permalink raw reply related

* [PATCH 1/5] m68k/net: Remove obsolete IRQ_FLG_* users
From: Geert Uytterhoeven @ 2011-10-23 21:18 UTC (permalink / raw)
  To: linux-m68k, linux-kernel; +Cc: Geert Uytterhoeven, David S. Miller, netdev

The m68k core irq code stopped honoring these flags during the irq
restructuring in 2006.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: netdev@vger.kernel.org
---
This is a split-up of "m68k/irq: Remove obsolete IRQ_FLG_* definitions and
users", to reduce conflicts and dependencies.

diff --git a/drivers/net/ethernet/natsemi/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c
index c93679e..aae4cfc 100644
--- a/drivers/net/ethernet/natsemi/macsonic.c
+++ b/drivers/net/ethernet/natsemi/macsonic.c
@@ -142,8 +142,7 @@ static int macsonic_open(struct net_device* dev)
 {
 	int retval;
 
-	retval = request_irq(dev->irq, sonic_interrupt, IRQ_FLG_FAST,
-				"sonic", dev);
+	retval = request_irq(dev->irq, sonic_interrupt, 0, "sonic", dev);
 	if (retval) {
 		printk(KERN_ERR "%s: unable to get IRQ %d.\n",
 				dev->name, dev->irq);
@@ -154,8 +153,8 @@ static int macsonic_open(struct net_device* dev)
 	 * rupt as well, which must prevent re-entrance of the sonic handler.
 	 */
 	if (dev->irq == IRQ_AUTO_3) {
-		retval = request_irq(IRQ_NUBUS_9, macsonic_interrupt,
-					IRQ_FLG_FAST, "sonic", dev);
+		retval = request_irq(IRQ_NUBUS_9, macsonic_interrupt, 0,
+				     "sonic", dev);
 		if (retval) {
 			printk(KERN_ERR "%s: unable to get IRQ %d.\n",
 					dev->name, IRQ_NUBUS_9);

^ permalink raw reply related

* [PATCH 5/5] m68k/irq: Remove obsolete IRQ_FLG_* definitions
From: Geert Uytterhoeven @ 2011-10-23 21:18 UTC (permalink / raw)
  To: linux-m68k, linux-kernel; +Cc: Geert Uytterhoeven
In-Reply-To: <1319404686-10800-1-git-send-email-geert@linux-m68k.org>

The m68k core irq code stopped honoring these flags during the irq
restructuring in 2006.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
This is a split-up of "m68k/irq: Remove obsolete IRQ_FLG_* definitions and
users", to reduce conflicts and remove dependencies.

diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h
index 9a2bae8..fe625e2 100644
--- a/arch/m68k/include/asm/irq.h
+++ b/arch/m68k/include/asm/irq.h
@@ -59,19 +59,6 @@ extern unsigned int irq_canonicalize(unsigned int irq);
 struct pt_regs;
 
 /*
- * various flags for request_irq() - the Amiga now uses the standard
- * mechanism like all other architectures - IRQF_DISABLED and
- * IRQF_SHARED are your friends.
- */
-#ifndef MACH_AMIGA_ONLY
-#define IRQ_FLG_LOCK	(0x0001)	/* handler is not replaceable	*/
-#define IRQ_FLG_REPLACE	(0x0002)	/* replace existing handler	*/
-#define IRQ_FLG_FAST	(0x0004)
-#define IRQ_FLG_SLOW	(0x0008)
-#define IRQ_FLG_STD	(0x8000)	/* internally used		*/
-#endif
-
-/*
  * This structure is used to chain together the ISRs for a particular
  * interrupt source (if it supports chaining).
  */

^ permalink raw reply related

* [PATCH 3/5] m68k/serial: Remove obsolete IRQ_FLG_* users
From: Geert Uytterhoeven @ 2011-10-23 21:18 UTC (permalink / raw)
  To: linux-m68k, linux-kernel; +Cc: devel, Greg Kroah-Hartman, Geert Uytterhoeven
In-Reply-To: <1319404686-10800-1-git-send-email-geert@linux-m68k.org>

The m68k core irq code stopped honoring these flags during the irq
restructuring in 2006.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: devel@driverdev.osuosl.org
---
This is a split-up of "m68k/irq: Remove obsolete IRQ_FLG_* definitions and
users", to reduce conflicts and dependencies.

diff --git a/drivers/tty/serial/68360serial.c b/drivers/tty/serial/68360serial.c
index 0a3e878..daf0b1d 100644
--- a/drivers/staging/serial/68360serial.c
+++ b/drivers/staging/serial/68360serial.c
@@ -2771,8 +2771,8 @@ static int __init rs_360_init(void)
 			*/
 			/* cpm_install_handler(IRQ_MACHSPEC | state->irq, rs_360_interrupt, info);  */
 			/*request_irq(IRQ_MACHSPEC | state->irq, rs_360_interrupt, */
-			request_irq(state->irq, rs_360_interrupt,
-						IRQ_FLG_LOCK, "ttyS", (void *)info);
+			request_irq(state->irq, rs_360_interrupt, 0, "ttyS",
+				    (void *)info);
 
 			/* Set up the baud rate generator.
 			*/
-- 
1.7.0.4

^ permalink raw reply related


This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.