Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorDavid S. Miller <davem@davemloft.net>
Tue, 25 May 2010 20:15:11 +0000 (13:15 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 25 May 2010 20:15:11 +0000 (13:15 -0700)
32 files changed:
drivers/isdn/capi/kcapi.c
drivers/isdn/gigaset/capi.c
drivers/net/benet/be_main.c
drivers/net/bfin_mac.c
drivers/net/enic/enic_main.c
drivers/net/ethoc.c
drivers/net/fec.c
drivers/net/fec.h
drivers/net/irda/bfin_sir.c
drivers/net/macvlan.c
drivers/net/pppoe.c
drivers/net/tun.c
include/linux/fec.h [new file with mode: 0644]
include/linux/netdevice.h
include/net/caif/cfctrl.h
include/net/cls_cgroup.h [new file with mode: 0644]
include/net/sock.h
net/caif/Kconfig
net/caif/caif_socket.c
net/caif/cfctrl.c
net/caif/cfmuxl.c
net/caif/cfpkt_skbuff.c
net/caif/cfserl.c
net/caif/cfsrvl.c
net/core/dev.c
net/core/rtnetlink.c
net/core/sock.c
net/dccp/input.c
net/ieee802154/wpan-class.c
net/sched/cls_cgroup.c
net/sched/sch_api.c
net/socket.c

index bd00dce..bde3c88 100644 (file)
@@ -1147,6 +1147,12 @@ load_unlock_out:
                if (ctr->state == CAPI_CTR_DETECTED)
                        goto reset_unlock_out;
 
+               if (ctr->reset_ctr == NULL) {
+                       printk(KERN_DEBUG "kcapi: reset: no reset function\n");
+                       retval = -ESRCH;
+                       goto reset_unlock_out;
+               }
+
                ctr->reset_ctr(ctr);
 
                retval = wait_on_ctr_state(ctr, CAPI_CTR_DETECTED);
index 964a55f..e72f86b 100644 (file)
@@ -933,30 +933,6 @@ void gigaset_isdn_stop(struct cardstate *cs)
  */
 
 /*
- * load firmware
- */
-static int gigaset_load_firmware(struct capi_ctr *ctr, capiloaddata *data)
-{
-       struct cardstate *cs = ctr->driverdata;
-
-       /* AVM specific operation, not needed for Gigaset -- ignore */
-       dev_notice(cs->dev, "load_firmware ignored\n");
-
-       return 0;
-}
-
-/*
- * reset (deactivate) controller
- */
-static void gigaset_reset_ctr(struct capi_ctr *ctr)
-{
-       struct cardstate *cs = ctr->driverdata;
-
-       /* AVM specific operation, not needed for Gigaset -- ignore */
-       dev_notice(cs->dev, "reset_ctr ignored\n");
-}
-
-/*
  * register CAPI application
  */
 static void gigaset_register_appl(struct capi_ctr *ctr, u16 appl,
@@ -2213,8 +2189,8 @@ int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
        iif->ctr.driverdata    = cs;
        strncpy(iif->ctr.name, isdnid, sizeof(iif->ctr.name));
        iif->ctr.driver_name   = "gigaset";
-       iif->ctr.load_firmware = gigaset_load_firmware;
-       iif->ctr.reset_ctr     = gigaset_reset_ctr;
+       iif->ctr.load_firmware = NULL;
+       iif->ctr.reset_ctr     = NULL;
        iif->ctr.register_appl = gigaset_register_appl;
        iif->ctr.release_appl  = gigaset_release_appl;
        iif->ctr.send_message  = gigaset_send_message;
index 058d7f9..1c79c20 100644 (file)
@@ -2487,10 +2487,6 @@ static int __devinit be_probe(struct pci_dev *pdev,
                status = be_cmd_POST(adapter);
                if (status)
                        goto ctrl_clean;
-
-               status = be_cmd_reset_function(adapter);
-               if (status)
-                       goto ctrl_clean;
        }
 
        /* tell fw we're ready to fire cmds */
@@ -2498,6 +2494,12 @@ static int __devinit be_probe(struct pci_dev *pdev,
        if (status)
                goto ctrl_clean;
 
+       if (be_physfn(adapter)) {
+               status = be_cmd_reset_function(adapter);
+               if (status)
+                       goto ctrl_clean;
+       }
+
        status = be_stats_init(adapter);
        if (status)
                goto ctrl_clean;
index 39a54ba..368f333 100644 (file)
@@ -1626,6 +1626,7 @@ static int __devinit bfin_mii_bus_probe(struct platform_device *pdev)
        return 0;
 
 out_err_mdiobus_register:
+       kfree(miibus->irq);
        mdiobus_free(miibus);
 out_err_alloc:
        peripheral_free_list(pin_req);
@@ -1638,6 +1639,7 @@ static int __devexit bfin_mii_bus_remove(struct platform_device *pdev)
        struct mii_bus *miibus = platform_get_drvdata(pdev);
        platform_set_drvdata(pdev, NULL);
        mdiobus_unregister(miibus);
+       kfree(miibus->irq);
        mdiobus_free(miibus);
        peripheral_free_list(pin_req);
        return 0;
index e125113..6586b5c 100644 (file)
@@ -1034,9 +1034,10 @@ static int enic_set_port_profile(struct enic *enic, u8 request, u8 *mac,
 {
        struct vic_provinfo *vp;
        u8 oui[3] = VIC_PROVINFO_CISCO_OUI;
-       unsigned short *uuid;
+       u8 *uuid;
        char uuid_str[38];
-       static char *uuid_fmt = "%04X%04X-%04X-%04X-%04X-%04X%04X%04X";
+       static char *uuid_fmt = "%02X%02X%02X%02X-%02X%02X-%02X%02X-"
+               "%02X%02X-%02X%02X%02X%02X%0X%02X";
        int err;
 
        if (!name)
@@ -1058,20 +1059,24 @@ static int enic_set_port_profile(struct enic *enic, u8 request, u8 *mac,
                ETH_ALEN, mac);
 
        if (instance_uuid) {
-               uuid = (unsigned short *)instance_uuid;
+               uuid = instance_uuid;
                sprintf(uuid_str, uuid_fmt,
-                       uuid[0], uuid[1], uuid[2], uuid[3],
-                       uuid[4], uuid[5], uuid[6], uuid[7]);
+                       uuid[0],  uuid[1],  uuid[2],  uuid[3],
+                       uuid[4],  uuid[5],  uuid[6],  uuid[7],
+                       uuid[8],  uuid[9],  uuid[10], uuid[11],
+                       uuid[12], uuid[13], uuid[14], uuid[15]);
                vic_provinfo_add_tlv(vp,
                        VIC_LINUX_PROV_TLV_CLIENT_UUID_STR,
                        sizeof(uuid_str), uuid_str);
        }
 
        if (host_uuid) {
-               uuid = (unsigned short *)host_uuid;
+               uuid = host_uuid;
                sprintf(uuid_str, uuid_fmt,
-                       uuid[0], uuid[1], uuid[2], uuid[3],
-                       uuid[4], uuid[5], uuid[6], uuid[7]);
+                       uuid[0],  uuid[1],  uuid[2],  uuid[3],
+                       uuid[4],  uuid[5],  uuid[6],  uuid[7],
+                       uuid[8],  uuid[9],  uuid[10], uuid[11],
+                       uuid[12], uuid[13], uuid[14], uuid[15]);
                vic_provinfo_add_tlv(vp,
                        VIC_LINUX_PROV_TLV_HOST_UUID_STR,
                        sizeof(uuid_str), uuid_str);
@@ -1127,6 +1132,14 @@ static int enic_set_vf_port(struct net_device *netdev, int vf,
        switch (request) {
        case PORT_REQUEST_ASSOCIATE:
 
+               /* If the interface mac addr hasn't been assigned,
+                * assign a random mac addr before setting port-
+                * profile.
+                */
+
+               if (is_zero_ether_addr(netdev->dev_addr))
+                       random_ether_addr(netdev->dev_addr);
+
                if (port[IFLA_PORT_PROFILE])
                        name = nla_data(port[IFLA_PORT_PROFILE]);
 
index 14cbde5..6ed2df1 100644 (file)
@@ -174,6 +174,7 @@ MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size");
  * @iobase:    pointer to I/O memory region
  * @membase:   pointer to buffer memory region
  * @dma_alloc: dma allocated buffer size
+ * @io_region_size:    I/O memory region size
  * @num_tx:    number of send buffers
  * @cur_tx:    last send buffer written
  * @dty_tx:    last buffer actually sent
@@ -193,6 +194,7 @@ struct ethoc {
        void __iomem *iobase;
        void __iomem *membase;
        int dma_alloc;
+       resource_size_t io_region_size;
 
        unsigned int num_tx;
        unsigned int cur_tx;
@@ -943,6 +945,7 @@ static int ethoc_probe(struct platform_device *pdev)
        priv = netdev_priv(netdev);
        priv->netdev = netdev;
        priv->dma_alloc = 0;
+       priv->io_region_size = mmio->end - mmio->start + 1;
 
        priv->iobase = devm_ioremap_nocache(&pdev->dev, netdev->base_addr,
                        resource_size(mmio));
@@ -1047,20 +1050,34 @@ static int ethoc_probe(struct platform_device *pdev)
        ret = register_netdev(netdev);
        if (ret < 0) {
                dev_err(&netdev->dev, "failed to register interface\n");
-               goto error;
+               goto error2;
        }
 
        goto out;
 
+error2:
+       netif_napi_del(&priv->napi);
 error:
        mdiobus_unregister(priv->mdio);
 free_mdio:
        kfree(priv->mdio->irq);
        mdiobus_free(priv->mdio);
 free:
-       if (priv->dma_alloc)
-               dma_free_coherent(NULL, priv->dma_alloc, priv->membase,
-                       netdev->mem_start);
+       if (priv) {
+               if (priv->dma_alloc)
+                       dma_free_coherent(NULL, priv->dma_alloc, priv->membase,
+                                         netdev->mem_start);
+               else if (priv->membase)
+                       devm_iounmap(&pdev->dev, priv->membase);
+               if (priv->iobase)
+                       devm_iounmap(&pdev->dev, priv->iobase);
+       }
+       if (mem)
+               devm_release_mem_region(&pdev->dev, mem->start,
+                                       mem->end - mem->start + 1);
+       if (mmio)
+               devm_release_mem_region(&pdev->dev, mmio->start,
+                                       mmio->end - mmio->start + 1);
        free_netdev(netdev);
 out:
        return ret;
@@ -1078,6 +1095,7 @@ static int ethoc_remove(struct platform_device *pdev)
        platform_set_drvdata(pdev, NULL);
 
        if (netdev) {
+               netif_napi_del(&priv->napi);
                phy_disconnect(priv->phy);
                priv->phy = NULL;
 
@@ -1089,6 +1107,14 @@ static int ethoc_remove(struct platform_device *pdev)
                if (priv->dma_alloc)
                        dma_free_coherent(NULL, priv->dma_alloc, priv->membase,
                                netdev->mem_start);
+               else {
+                       devm_iounmap(&pdev->dev, priv->membase);
+                       devm_release_mem_region(&pdev->dev, netdev->mem_start,
+                               netdev->mem_end - netdev->mem_start + 1);
+               }
+               devm_iounmap(&pdev->dev, priv->iobase);
+               devm_release_mem_region(&pdev->dev, netdev->base_addr,
+                       priv->io_region_size);
                unregister_netdev(netdev);
                free_netdev(netdev);
        }
index 42d9ac9..326465f 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/phy.h>
+#include <linux/fec.h>
 
 #include <asm/cacheflush.h>
 
@@ -182,6 +183,7 @@ struct fec_enet_private {
        struct  phy_device *phy_dev;
        int     mii_timeout;
        uint    phy_speed;
+       phy_interface_t phy_interface;
        int     index;
        int     link;
        int     full_duplex;
@@ -1191,6 +1193,21 @@ fec_restart(struct net_device *dev, int duplex)
        /* Set MII speed */
        writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
 
+#ifdef FEC_MIIGSK_ENR
+       if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) {
+               /* disable the gasket and wait */
+               writel(0, fep->hwp + FEC_MIIGSK_ENR);
+               while (readl(fep->hwp + FEC_MIIGSK_ENR) & 4)
+                       udelay(1);
+
+               /* configure the gasket: RMII, 50 MHz, no loopback, no echo */
+               writel(1, fep->hwp + FEC_MIIGSK_CFGR);
+
+               /* re-enable the gasket */
+               writel(2, fep->hwp + FEC_MIIGSK_ENR);
+       }
+#endif
+
        /* And last, enable the transmit and receive processing */
        writel(2, fep->hwp + FEC_ECNTRL);
        writel(0, fep->hwp + FEC_R_DES_ACTIVE);
@@ -1226,6 +1243,7 @@ static int __devinit
 fec_probe(struct platform_device *pdev)
 {
        struct fec_enet_private *fep;
+       struct fec_platform_data *pdata;
        struct net_device *ndev;
        int i, irq, ret = 0;
        struct resource *r;
@@ -1259,6 +1277,10 @@ fec_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, ndev);
 
+       pdata = pdev->dev.platform_data;
+       if (pdata)
+               fep->phy_interface = pdata->phy;
+
        /* This device has up to three irqs on some platforms */
        for (i = 0; i < 3; i++) {
                irq = platform_get_irq(pdev, i);
index cc47f3f..2c48b25 100644 (file)
@@ -43,6 +43,8 @@
 #define FEC_R_DES_START                0x180 /* Receive descriptor ring */
 #define FEC_X_DES_START                0x184 /* Transmit descriptor ring */
 #define FEC_R_BUFF_SIZE                0x188 /* Maximum receive buff size */
+#define FEC_MIIGSK_CFGR                0x300 /* MIIGSK Configuration reg */
+#define FEC_MIIGSK_ENR         0x308 /* MIIGSK Enable reg */
 
 #else
 
index 911c082..f940dfa 100644 (file)
@@ -107,8 +107,12 @@ static int bfin_sir_set_speed(struct bfin_sir_port *port, int speed)
        case 57600:
        case 115200:
 
-               quot = (port->clk + (8 * speed)) / (16 * speed)\
-                                               - ANOMALY_05000230;
+               /*
+                * IRDA is not affected by anomaly 05000230, so there is no
+                * need to tweak the divisor like he UART driver (which will
+                * slightly speed up the baud rate on us).
+                */
+               quot = (port->clk + (8 * speed)) / (16 * speed);
 
                do {
                        udelay(utime);
index 4e238af..87e8d4c 100644 (file)
@@ -634,11 +634,18 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
 
        err = register_netdevice(dev);
        if (err < 0)
-               return err;
+               goto destroy_port;
 
        list_add_tail(&vlan->list, &port->vlans);
        netif_stacked_transfer_operstate(lowerdev, dev);
+
        return 0;
+
+destroy_port:
+       if (list_empty(&port->vlans))
+               macvlan_port_destroy(lowerdev);
+
+       return err;
 }
 EXPORT_SYMBOL_GPL(macvlan_common_newlink);
 
index b1b93ff..805b64d 100644 (file)
@@ -289,6 +289,7 @@ static void pppoe_flush_dev(struct net_device *dev)
        struct pppoe_net *pn;
        int i;
 
+       pn = pppoe_pernet(dev_net(dev));
        write_lock_bh(&pn->hash_lock);
        for (i = 0; i < PPPOE_HASH_SIZE; i++) {
                struct pppox_sock *po = pn->hash_table[i];
index 97b2553..8793c2b 100644 (file)
@@ -526,6 +526,8 @@ static inline struct sk_buff *tun_alloc_skb(struct tun_struct *tun,
        struct sk_buff *skb;
        int err;
 
+       sock_update_classid(sk);
+
        /* Under a page?  Don't bother with paged skb. */
        if (prepad + len < PAGE_SIZE || !linear)
                linear = len;
diff --git a/include/linux/fec.h b/include/linux/fec.h
new file mode 100644 (file)
index 0000000..5d3523d
--- /dev/null
@@ -0,0 +1,21 @@
+/* include/linux/fec.h
+ *
+ * Copyright (c) 2009 Orex Computed Radiography
+ *   Baruch Siach <baruch@tkos.co.il>
+ *
+ * Header file for the FEC platform data
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __LINUX_FEC_H__
+#define __LINUX_FEC_H__
+
+#include <linux/phy.h>
+
+struct fec_platform_data {
+       phy_interface_t phy;
+};
+
+#endif
index 2564195..40291f3 100644 (file)
@@ -2334,7 +2334,7 @@ do {                                                              \
 #define netif_vdbg(priv, type, dev, format, args...)           \
 ({                                                             \
        if (0)                                                  \
-               netif_printk(KERN_DEBUG, dev, format, ##args);  \
+               netif_printk(priv, type, KERN_DEBUG, dev, format, ##args); \
        0;                                                      \
 })
 #endif
index 997603f..9402543 100644 (file)
@@ -94,8 +94,8 @@ struct cfctrl_request_info {
        enum cfctrl_cmd cmd;
        u8 channel_id;
        struct cfctrl_link_param param;
-       struct cfctrl_request_info *next;
        struct cflayer *client_layer;
+       struct list_head list;
 };
 
 struct cfctrl {
@@ -103,7 +103,7 @@ struct cfctrl {
        struct cfctrl_rsp res;
        atomic_t req_seq_no;
        atomic_t rsp_seq_no;
-       struct cfctrl_request_info *first_req;
+       struct list_head list;
        /* Protects from simultaneous access to first_req list */
        spinlock_t info_list_lock;
 #ifndef CAIF_NO_LOOP
diff --git a/include/net/cls_cgroup.h b/include/net/cls_cgroup.h
new file mode 100644 (file)
index 0000000..6cf4486
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * cls_cgroup.h                        Control Group Classifier
+ *
+ * Authors:    Thomas Graf <tgraf@suug.ch>
+ *
+ * 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 _NET_CLS_CGROUP_H
+#define _NET_CLS_CGROUP_H
+
+#include <linux/cgroup.h>
+#include <linux/hardirq.h>
+#include <linux/rcupdate.h>
+
+#ifdef CONFIG_CGROUPS
+struct cgroup_cls_state
+{
+       struct cgroup_subsys_state css;
+       u32 classid;
+};
+
+#ifdef CONFIG_NET_CLS_CGROUP
+static inline u32 task_cls_classid(struct task_struct *p)
+{
+       if (in_interrupt())
+               return 0;
+
+       return container_of(task_subsys_state(p, net_cls_subsys_id),
+                           struct cgroup_cls_state, css)->classid;
+}
+#else
+extern int net_cls_subsys_id;
+
+static inline u32 task_cls_classid(struct task_struct *p)
+{
+       int id;
+       u32 classid;
+
+       if (in_interrupt())
+               return 0;
+
+       rcu_read_lock();
+       id = rcu_dereference(net_cls_subsys_id);
+       if (id >= 0)
+               classid = container_of(task_subsys_state(p, id),
+                                      struct cgroup_cls_state, css)->classid;
+       rcu_read_unlock();
+
+       return classid;
+}
+#endif
+#else
+static inline u32 task_cls_classid(struct task_struct *p)
+{
+       return 0;
+}
+#endif
+#endif  /* _NET_CLS_CGROUP_H */
index 5697caf..d2a71b0 100644 (file)
@@ -312,7 +312,7 @@ struct sock {
        void                    *sk_security;
 #endif
        __u32                   sk_mark;
-       /* XXX 4 bytes hole on 64 bit */
+       u32                     sk_classid;
        void                    (*sk_state_change)(struct sock *sk);
        void                    (*sk_data_ready)(struct sock *sk, int bytes);
        void                    (*sk_write_space)(struct sock *sk);
@@ -1074,6 +1074,14 @@ extern void *sock_kmalloc(struct sock *sk, int size,
 extern void sock_kfree_s(struct sock *sk, void *mem, int size);
 extern void sk_send_sigurg(struct sock *sk);
 
+#ifdef CONFIG_CGROUPS
+extern void sock_update_classid(struct sock *sk);
+#else
+static inline void sock_update_classid(struct sock *sk)
+{
+}
+#endif
+
 /*
  * Functions to fill in entries in struct proto_ops when a protocol
  * does not implement a particular function.
@@ -1404,7 +1412,7 @@ static inline int sk_has_allocations(const struct sock *sk)
 
 /**
  * wq_has_sleeper - check if there are any waiting processes
- * @sk: struct socket_wq
+ * @wq: struct socket_wq
  *
  * Returns true if socket_wq has waiting processes
  *
index cd1daf6..ed65178 100644 (file)
@@ -2,10 +2,8 @@
 # CAIF net configurations
 #
 
-#menu "CAIF Support"
-comment "CAIF Support"
 menuconfig CAIF
-       tristate "Enable CAIF support"
+       tristate "CAIF support"
        select CRC_CCITT
        default n
        ---help---
@@ -45,4 +43,3 @@ config CAIF_NETDEV
        If unsure say Y.
 
 endif
-#endmenu
index c3a70c5..3d0e095 100644 (file)
@@ -60,7 +60,7 @@ struct debug_fs_counter {
        atomic_t num_rx_flow_off;
        atomic_t num_rx_flow_on;
 };
-struct debug_fs_counter cnt;
+static struct debug_fs_counter cnt;
 #define        dbfs_atomic_inc(v) atomic_inc(v)
 #define        dbfs_atomic_dec(v) atomic_dec(v)
 #else
@@ -128,17 +128,17 @@ static void caif_read_unlock(struct sock *sk)
        mutex_unlock(&cf_sk->readlock);
 }
 
-int sk_rcvbuf_lowwater(struct caifsock *cf_sk)
+static int sk_rcvbuf_lowwater(struct caifsock *cf_sk)
 {
        /* A quarter of full buffer is used a low water mark */
        return cf_sk->sk.sk_rcvbuf / 4;
 }
 
-void caif_flow_ctrl(struct sock *sk, int mode)
+static void caif_flow_ctrl(struct sock *sk, int mode)
 {
        struct caifsock *cf_sk;
        cf_sk = container_of(sk, struct caifsock, sk);
-       if (cf_sk->layer.dn)
+       if (cf_sk->layer.dn && cf_sk->layer.dn->modemcmd)
                cf_sk->layer.dn->modemcmd(cf_sk->layer.dn, mode);
 }
 
@@ -146,7 +146,7 @@ void caif_flow_ctrl(struct sock *sk, int mode)
  * Copied from sock.c:sock_queue_rcv_skb(), but changed so packets are
  * not dropped, but CAIF is sending flow off instead.
  */
-int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
+static int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
        int err;
        int skb_len;
@@ -162,9 +162,8 @@ int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
                        atomic_read(&cf_sk->sk.sk_rmem_alloc),
                        sk_rcvbuf_lowwater(cf_sk));
                set_rx_flow_off(cf_sk);
-               if (cf_sk->layer.dn)
-                       cf_sk->layer.dn->modemcmd(cf_sk->layer.dn,
-                                               CAIF_MODEMCMD_FLOW_OFF_REQ);
+               dbfs_atomic_inc(&cnt.num_rx_flow_off);
+               caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_OFF_REQ);
        }
 
        err = sk_filter(sk, skb);
@@ -175,9 +174,8 @@ int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
                trace_printk("CAIF: %s():"
                        " sending flow OFF due to rmem_schedule\n",
                        __func__);
-               if (cf_sk->layer.dn)
-                       cf_sk->layer.dn->modemcmd(cf_sk->layer.dn,
-                                               CAIF_MODEMCMD_FLOW_OFF_REQ);
+               dbfs_atomic_inc(&cnt.num_rx_flow_off);
+               caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_OFF_REQ);
        }
        skb->dev = NULL;
        skb_set_owner_r(skb, sk);
@@ -285,65 +283,51 @@ static void caif_check_flow_release(struct sock *sk)
 {
        struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
 
-       if (cf_sk->layer.dn == NULL || cf_sk->layer.dn->modemcmd == NULL)
-               return;
        if (rx_flow_is_on(cf_sk))
                return;
 
        if (atomic_read(&sk->sk_rmem_alloc) <= sk_rcvbuf_lowwater(cf_sk)) {
                        dbfs_atomic_inc(&cnt.num_rx_flow_on);
                        set_rx_flow_on(cf_sk);
-                       cf_sk->layer.dn->modemcmd(cf_sk->layer.dn,
-                                               CAIF_MODEMCMD_FLOW_ON_REQ);
+                       caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_ON_REQ);
        }
 }
+
 /*
- * Copied from sock.c:sock_queue_rcv_skb(), and added check that user buffer
- * has sufficient size.
+ * Copied from unix_dgram_recvmsg, but removed credit checks,
+ * changed locking, address handling and added MSG_TRUNC.
  */
-
 static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock,
-                               struct msghdr *m, size_t buf_len, int flags)
+                               struct msghdr *m, size_t len, int flags)
 
 {
        struct sock *sk = sock->sk;
        struct sk_buff *skb;
-       int ret = 0;
-       int len;
+       int ret;
+       int copylen;
 
-       if (unlikely(!buf_len))
-               return -EINVAL;
+       ret = -EOPNOTSUPP;
+       if (m->msg_flags&MSG_OOB)
+               goto read_error;
 
        skb = skb_recv_datagram(sk, flags, 0 , &ret);
        if (!skb)
                goto read_error;
-
-       len = skb->len;
-
-       if (skb && skb->len > buf_len && !(flags & MSG_PEEK)) {
-               len = buf_len;
-               /*
-                * Push skb back on receive queue if buffer too small.
-                * This has a built-in race where multi-threaded receive
-                * may get packet in wrong order, but multiple read does
-                * not really guarantee ordered delivery anyway.
-                * Let's optimize for speed without taking locks.
-                */
-
-               skb_queue_head(&sk->sk_receive_queue, skb);
-               ret = -EMSGSIZE;
-               goto read_error;
+       copylen = skb->len;
+       if (len < copylen) {
+               m->msg_flags |= MSG_TRUNC;
+               copylen = len;
        }
 
-       ret = skb_copy_datagram_iovec(skb, 0, m->msg_iov, len);
+       ret = skb_copy_datagram_iovec(skb, 0, m->msg_iov, copylen);
        if (ret)
-               goto read_error;
+               goto out_free;
 
+       ret = (flags & MSG_TRUNC) ? skb->len : copylen;
+out_free:
        skb_free_datagram(sk, skb);
-
        caif_check_flow_release(sk);
-
-       return len;
+       return ret;
 
 read_error:
        return ret;
@@ -920,17 +904,17 @@ wait_connect:
        timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
 
        release_sock(sk);
-       err = wait_event_interruptible_timeout(*sk_sleep(sk),
+       err = -ERESTARTSYS;
+       timeo = wait_event_interruptible_timeout(*sk_sleep(sk),
                        sk->sk_state != CAIF_CONNECTING,
                        timeo);
        lock_sock(sk);
-       if (err < 0)
+       if (timeo < 0)
                goto out; /* -ERESTARTSYS */
-       if (err == 0 && sk->sk_state != CAIF_CONNECTED) {
-               err = -ETIMEDOUT;
-               goto out;
-       }
 
+       err = -ETIMEDOUT;
+       if (timeo == 0 && sk->sk_state != CAIF_CONNECTED)
+               goto out;
        if (sk->sk_state != CAIF_CONNECTED) {
                sock->state = SS_UNCONNECTED;
                err = sock_error(sk);
@@ -945,7 +929,6 @@ out:
        return err;
 }
 
-
 /*
  * caif_release() - Disconnect a CAIF Socket
  * Copied and modified af_irda.c:irda_release().
@@ -1019,10 +1002,6 @@ static unsigned int caif_poll(struct file *file,
                (sk->sk_shutdown & RCV_SHUTDOWN))
                mask |= POLLIN | POLLRDNORM;
 
-       /* Connection-based need to check for termination and startup */
-       if (sk->sk_state == CAIF_DISCONNECTED)
-               mask |= POLLHUP;
-
        /*
         * we set writable also when the other side has shut down the
         * connection. This prevents stuck sockets.
@@ -1194,7 +1173,7 @@ static struct net_proto_family caif_family_ops = {
        .owner = THIS_MODULE,
 };
 
-int af_caif_init(void)
+static int af_caif_init(void)
 {
        int err = sock_register(&caif_family_ops);
        if (!err)
index 0ffe1e1..fcfda98 100644 (file)
@@ -44,13 +44,14 @@ struct cflayer *cfctrl_create(void)
        dev_info.id = 0xff;
        memset(this, 0, sizeof(*this));
        cfsrvl_init(&this->serv, 0, &dev_info);
-       spin_lock_init(&this->info_list_lock);
        atomic_set(&this->req_seq_no, 1);
        atomic_set(&this->rsp_seq_no, 1);
        this->serv.layer.receive = cfctrl_recv;
        sprintf(this->serv.layer.name, "ctrl");
        this->serv.layer.ctrlcmd = cfctrl_ctrlcmd;
        spin_lock_init(&this->loop_linkid_lock);
+       spin_lock_init(&this->info_list_lock);
+       INIT_LIST_HEAD(&this->list);
        this->loop_linkid = 1;
        return &this->serv.layer;
 }
@@ -112,20 +113,10 @@ bool cfctrl_req_eq(struct cfctrl_request_info *r1,
 void cfctrl_insert_req(struct cfctrl *ctrl,
                              struct cfctrl_request_info *req)
 {
-       struct cfctrl_request_info *p;
        spin_lock(&ctrl->info_list_lock);
-       req->next = NULL;
        atomic_inc(&ctrl->req_seq_no);
        req->sequence_no = atomic_read(&ctrl->req_seq_no);
-       if (ctrl->first_req == NULL) {
-               ctrl->first_req = req;
-               spin_unlock(&ctrl->info_list_lock);
-               return;
-       }
-       p = ctrl->first_req;
-       while (p->next != NULL)
-               p = p->next;
-       p->next = req;
+       list_add_tail(&req->list, &ctrl->list);
        spin_unlock(&ctrl->info_list_lock);
 }
 
@@ -133,46 +124,28 @@ void cfctrl_insert_req(struct cfctrl *ctrl,
 struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl,
                                              struct cfctrl_request_info *req)
 {
-       struct cfctrl_request_info *p;
-       struct cfctrl_request_info *ret;
+       struct cfctrl_request_info *p, *tmp, *first;
 
        spin_lock(&ctrl->info_list_lock);
-       if (ctrl->first_req == NULL) {
-               spin_unlock(&ctrl->info_list_lock);
-               return NULL;
-       }
-
-       if (cfctrl_req_eq(req, ctrl->first_req)) {
-               ret = ctrl->first_req;
-               caif_assert(ctrl->first_req);
-               atomic_set(&ctrl->rsp_seq_no,
-                                ctrl->first_req->sequence_no);
-               ctrl->first_req = ctrl->first_req->next;
-               spin_unlock(&ctrl->info_list_lock);
-               return ret;
-       }
+       first = list_first_entry(&ctrl->list, struct cfctrl_request_info, list);
 
-       p = ctrl->first_req;
-
-       while (p->next != NULL) {
-               if (cfctrl_req_eq(req, p->next)) {
-                       pr_warning("CAIF: %s(): Requests are not "
+       list_for_each_entry_safe(p, tmp, &ctrl->list, list) {
+               if (cfctrl_req_eq(req, p)) {
+                       if (p != first)
+                               pr_warning("CAIF: %s(): Requests are not "
                                        "received in order\n",
                                        __func__);
-                       ret = p->next;
+
                        atomic_set(&ctrl->rsp_seq_no,
-                                       p->next->sequence_no);
-                       p->next = p->next->next;
-                       spin_unlock(&ctrl->info_list_lock);
-                       return ret;
+                                        p->sequence_no);
+                       list_del(&p->list);
+                       goto out;
                }
-               p = p->next;
        }
+       p = NULL;
+out:
        spin_unlock(&ctrl->info_list_lock);
-
-       pr_warning("CAIF: %s(): Request does not match\n",
-                  __func__);
-       return NULL;
+       return p;
 }
 
 struct cfctrl_rsp *cfctrl_get_respfuncs(struct cflayer *layer)
@@ -388,31 +361,18 @@ void cfctrl_getstartreason_req(struct cflayer *layer)
 
 void cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer)
 {
-       struct cfctrl_request_info *p, *req;
+       struct cfctrl_request_info *p, *tmp;
        struct cfctrl *ctrl = container_obj(layr);
        spin_lock(&ctrl->info_list_lock);
-
-       if (ctrl->first_req == NULL) {
-               spin_unlock(&ctrl->info_list_lock);
-               return;
-       }
-
-       if (ctrl->first_req->client_layer == adap_layer) {
-
-               req = ctrl->first_req;
-               ctrl->first_req = ctrl->first_req->next;
-               kfree(req);
-       }
-
-       p = ctrl->first_req;
-       while (p != NULL && p->next != NULL) {
-               if (p->next->client_layer == adap_layer) {
-
-                       req = p->next;
-                       p->next = p->next->next;
-                       kfree(p->next);
+       pr_warning("CAIF: %s(): enter\n", __func__);
+
+       list_for_each_entry_safe(p, tmp, &ctrl->list, list) {
+               if (p->client_layer == adap_layer) {
+                       pr_warning("CAIF: %s(): cancel req :%d\n", __func__,
+                                       p->sequence_no);
+                       list_del(&p->list);
+                       kfree(p);
                }
-               p = p->next;
        }
 
        spin_unlock(&ctrl->info_list_lock);
@@ -634,7 +594,7 @@ static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
        case _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND:
        case CAIF_CTRLCMD_FLOW_OFF_IND:
                spin_lock(&this->info_list_lock);
-               if (this->first_req != NULL) {
+               if (!list_empty(&this->list)) {
                        pr_debug("CAIF: %s(): Received flow off in "
                                   "control layer", __func__);
                }
index 7372f27..80c8d33 100644 (file)
@@ -174,10 +174,11 @@ struct cflayer *cfmuxl_remove_uplayer(struct cflayer *layr, u8 id)
        spin_lock(&muxl->receive_lock);
        up = get_up(muxl, id);
        if (up == NULL)
-               return NULL;
+               goto out;
        memset(muxl->up_cache, 0, sizeof(muxl->up_cache));
        list_del(&up->node);
        cfsrvl_put(up);
+out:
        spin_unlock(&muxl->receive_lock);
        return up;
 }
index 83fff2f..a6fdf89 100644 (file)
@@ -238,6 +238,7 @@ int cfpkt_add_head(struct cfpkt *pkt, const void *data2, u16 len)
        struct sk_buff *lastskb;
        u8 *to;
        const u8 *data = data2;
+       int ret;
        if (unlikely(is_erronous(pkt)))
                return -EPROTO;
        if (unlikely(skb_headroom(skb) < len)) {
@@ -246,9 +247,10 @@ int cfpkt_add_head(struct cfpkt *pkt, const void *data2, u16 len)
        }
 
        /* Make sure data is writable */
-       if (unlikely(skb_cow_data(skb, 0, &lastskb) < 0)) {
+       ret = skb_cow_data(skb, 0, &lastskb);
+       if (unlikely(ret < 0)) {
                PKT_ERROR(pkt, "cfpkt_add_head: cow failed\n");
-               return -EPROTO;
+               return ret;
        }
 
        to = skb_push(skb, len);
@@ -316,6 +318,8 @@ EXPORT_SYMBOL(cfpkt_setlen);
 struct cfpkt *cfpkt_create_uplink(const unsigned char *data, unsigned int len)
 {
        struct cfpkt *pkt = cfpkt_create_pfx(len + PKT_POSTFIX, PKT_PREFIX);
+       if (!pkt)
+               return NULL;
        if (unlikely(data != NULL))
                cfpkt_add_body(pkt, data, len);
        return pkt;
@@ -344,12 +348,13 @@ struct cfpkt *cfpkt_append(struct cfpkt *dstpkt,
 
        if (dst->tail + neededtailspace > dst->end) {
                /* Create a dumplicate of 'dst' with more tail space */
+               struct cfpkt *tmppkt;
                dstlen = skb_headlen(dst);
                createlen = dstlen + neededtailspace;
-               tmp = pkt_to_skb(
-                       cfpkt_create(createlen + PKT_PREFIX + PKT_POSTFIX));
-               if (!tmp)
+               tmppkt = cfpkt_create(createlen + PKT_PREFIX + PKT_POSTFIX);
+               if (tmppkt == NULL)
                        return NULL;
+               tmp = pkt_to_skb(tmppkt);
                skb_set_tail_pointer(tmp, dstlen);
                tmp->len = dstlen;
                memcpy(tmp->data, dst->data, dstlen);
@@ -368,6 +373,7 @@ struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos)
 {
        struct sk_buff *skb2;
        struct sk_buff *skb = pkt_to_skb(pkt);
+       struct cfpkt *tmppkt;
        u8 *split = skb->data + pos;
        u16 len2nd = skb_tail_pointer(skb) - split;
 
@@ -381,9 +387,12 @@ struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos)
        }
 
        /* Create a new packet for the second part of the data */
-       skb2 = pkt_to_skb(
-               cfpkt_create_pfx(len2nd + PKT_PREFIX + PKT_POSTFIX,
-                                PKT_PREFIX));
+       tmppkt = cfpkt_create_pfx(len2nd + PKT_PREFIX + PKT_POSTFIX,
+                                 PKT_PREFIX);
+       if (tmppkt == NULL)
+               return NULL;
+       skb2 = pkt_to_skb(tmppkt);
+
 
        if (skb2 == NULL)
                return NULL;
index 06029ea..cb4325a 100644 (file)
@@ -67,6 +67,8 @@ static int cfserl_receive(struct cflayer *l, struct cfpkt *newpkt)
                layr->incomplete_frm =
                    cfpkt_append(layr->incomplete_frm, newpkt, expectlen);
                pkt = layr->incomplete_frm;
+               if (pkt == NULL)
+                       return -ENOMEM;
        } else {
                pkt = newpkt;
        }
@@ -154,7 +156,6 @@ static int cfserl_receive(struct cflayer *l, struct cfpkt *newpkt)
                        if (layr->usestx) {
                                if (tail_pkt != NULL)
                                        pkt = cfpkt_append(pkt, tail_pkt, 0);
-
                                /* Start search for next STX if frame failed */
                                continue;
                        } else {
index aff31f3..6e5b707 100644 (file)
@@ -123,6 +123,12 @@ static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl)
                        struct caif_payload_info *info;
                        u8 flow_off = SRVL_FLOW_OFF;
                        pkt = cfpkt_create(SRVL_CTRL_PKT_SIZE);
+                       if (!pkt) {
+                               pr_warning("CAIF: %s(): Out of memory\n",
+                                       __func__);
+                               return -ENOMEM;
+                       }
+
                        if (cfpkt_add_head(pkt, &flow_off, 1) < 0) {
                                pr_err("CAIF: %s(): Packet is erroneous!\n",
                                        __func__);
index 0aab66d..07a48e2 100644 (file)
@@ -954,18 +954,22 @@ int dev_alloc_name(struct net_device *dev, const char *name)
 }
 EXPORT_SYMBOL(dev_alloc_name);
 
-static int dev_get_valid_name(struct net *net, const char *name, char *buf,
-                             bool fmt)
+static int dev_get_valid_name(struct net_device *dev, const char *name, bool fmt)
 {
+       struct net *net;
+
+       BUG_ON(!dev_net(dev));
+       net = dev_net(dev);
+
        if (!dev_valid_name(name))
                return -EINVAL;
 
        if (fmt && strchr(name, '%'))
-               return __dev_alloc_name(net, name, buf);
+               return dev_alloc_name(dev, name);
        else if (__dev_get_by_name(net, name))
                return -EEXIST;
-       else if (buf != name)
-               strlcpy(buf, name, IFNAMSIZ);
+       else if (dev->name != name)
+               strlcpy(dev->name, name, IFNAMSIZ);
 
        return 0;
 }
@@ -997,7 +1001,7 @@ int dev_change_name(struct net_device *dev, const char *newname)
 
        memcpy(oldname, dev->name, IFNAMSIZ);
 
-       err = dev_get_valid_name(net, newname, dev->name, 1);
+       err = dev_get_valid_name(dev, newname, 1);
        if (err < 0)
                return err;
 
@@ -4965,7 +4969,7 @@ int register_netdevice(struct net_device *dev)
                }
        }
 
-       ret = dev_get_valid_name(net, dev->name, dev->name, 0);
+       ret = dev_get_valid_name(dev, dev->name, 0);
        if (ret)
                goto err_uninit;
 
@@ -5574,7 +5578,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
                /* We get here if we can't use the current device name */
                if (!pat)
                        goto out;
-               if (dev_get_valid_name(net, pat, dev->name, 1))
+               if (dev_get_valid_name(dev, pat, 1))
                        goto out;
        }
 
index e4b9870..7ab86f3 100644 (file)
@@ -1199,8 +1199,10 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
                struct nlattr *attr;
                int rem;
                nla_for_each_nested(attr, tb[IFLA_VFINFO_LIST], rem) {
-                       if (nla_type(attr) != IFLA_VF_INFO)
+                       if (nla_type(attr) != IFLA_VF_INFO) {
+                               err = -EINVAL;
                                goto errout;
+                       }
                        err = do_setvfinfo(dev, attr);
                        if (err < 0)
                                goto errout;
index bf88a16..37fe9b6 100644 (file)
 #include <linux/net_tstamp.h>
 #include <net/xfrm.h>
 #include <linux/ipsec.h>
+#include <net/cls_cgroup.h>
 
 #include <linux/filter.h>
 
@@ -217,6 +218,11 @@ __u32 sysctl_rmem_default __read_mostly = SK_RMEM_MAX;
 int sysctl_optmem_max __read_mostly = sizeof(unsigned long)*(2*UIO_MAXIOV+512);
 EXPORT_SYMBOL(sysctl_optmem_max);
 
+#if defined(CONFIG_CGROUPS) && !defined(CONFIG_NET_CLS_CGROUP)
+int net_cls_subsys_id = -1;
+EXPORT_SYMBOL_GPL(net_cls_subsys_id);
+#endif
+
 static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen)
 {
        struct timeval tv;
@@ -1050,6 +1056,17 @@ static void sk_prot_free(struct proto *prot, struct sock *sk)
        module_put(owner);
 }
 
+#ifdef CONFIG_CGROUPS
+void sock_update_classid(struct sock *sk)
+{
+       u32 classid = task_cls_classid(current);
+
+       if (classid && classid != sk->sk_classid)
+               sk->sk_classid = classid;
+}
+EXPORT_SYMBOL(sock_update_classid);
+#endif
+
 /**
  *     sk_alloc - All socket objects are allocated here
  *     @net: the applicable net namespace
@@ -1073,6 +1090,8 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
                sock_lock_init(sk);
                sock_net_set(sk, get_net(net));
                atomic_set(&sk->sk_wmem_alloc, 1);
+
+               sock_update_classid(sk);
        }
 
        return sk;
index 58f7bc1..6beb6a7 100644 (file)
@@ -124,9 +124,9 @@ static int dccp_rcv_closereq(struct sock *sk, struct sk_buff *skb)
        return queued;
 }
 
-static u8 dccp_reset_code_convert(const u8 code)
+static u16 dccp_reset_code_convert(const u8 code)
 {
-       const u8 error_code[] = {
+       const u16 error_code[] = {
        [DCCP_RESET_CODE_CLOSED]             = 0,       /* normal termination */
        [DCCP_RESET_CODE_UNSPECIFIED]        = 0,       /* nothing known */
        [DCCP_RESET_CODE_ABORTED]            = ECONNRESET,
@@ -148,7 +148,7 @@ static u8 dccp_reset_code_convert(const u8 code)
 
 static void dccp_rcv_reset(struct sock *sk, struct sk_buff *skb)
 {
-       u8 err = dccp_reset_code_convert(dccp_hdr_reset(skb)->dccph_reset_code);
+       u16 err = dccp_reset_code_convert(dccp_hdr_reset(skb)->dccph_reset_code);
 
        sk->sk_err = err;
 
index 3d803a1..1627ef2 100644 (file)
@@ -147,13 +147,15 @@ struct wpan_phy *wpan_phy_alloc(size_t priv_size)
        struct wpan_phy *phy = kzalloc(sizeof(*phy) + priv_size,
                        GFP_KERNEL);
 
+       if (!phy)
+               goto out;
        mutex_lock(&wpan_phy_mutex);
        phy->idx = wpan_phy_idx++;
        if (unlikely(!wpan_phy_idx_valid(phy->idx))) {
                wpan_phy_idx--;
                mutex_unlock(&wpan_phy_mutex);
                kfree(phy);
-               return NULL;
+               goto out;
        }
        mutex_unlock(&wpan_phy_mutex);
 
@@ -168,6 +170,9 @@ struct wpan_phy *wpan_phy_alloc(size_t priv_size)
        phy->current_page = 0; /* for compatibility */
 
        return phy;
+
+out:
+       return NULL;
 }
 EXPORT_SYMBOL(wpan_phy_alloc);
 
index 2211803..78ef2c5 100644 (file)
 #include <linux/errno.h>
 #include <linux/skbuff.h>
 #include <linux/cgroup.h>
+#include <linux/rcupdate.h>
 #include <net/rtnetlink.h>
 #include <net/pkt_cls.h>
-
-struct cgroup_cls_state
-{
-       struct cgroup_subsys_state css;
-       u32 classid;
-};
+#include <net/sock.h>
+#include <net/cls_cgroup.h>
 
 static struct cgroup_subsys_state *cgrp_create(struct cgroup_subsys *ss,
                                               struct cgroup *cgrp);
@@ -112,6 +109,10 @@ static int cls_cgroup_classify(struct sk_buff *skb, struct tcf_proto *tp,
        struct cls_cgroup_head *head = tp->root;
        u32 classid;
 
+       rcu_read_lock();
+       classid = task_cls_state(current)->classid;
+       rcu_read_unlock();
+
        /*
         * Due to the nature of the classifier it is required to ignore all
         * packets originating from softirq context as accessing `current'
@@ -122,12 +123,12 @@ static int cls_cgroup_classify(struct sk_buff *skb, struct tcf_proto *tp,
         * calls by looking at the number of nested bh disable calls because
         * softirqs always disables bh.
         */
-       if (softirq_count() != SOFTIRQ_OFFSET)
-               return -1;
-
-       rcu_read_lock();
-       classid = task_cls_state(current)->classid;
-       rcu_read_unlock();
+       if (softirq_count() != SOFTIRQ_OFFSET) {
+               /* If there is an sk_classid we'll use that. */
+               if (!skb->sk)
+                       return -1;
+               classid = skb->sk->sk_classid;
+       }
 
        if (!classid)
                return -1;
@@ -289,18 +290,35 @@ static struct tcf_proto_ops cls_cgroup_ops __read_mostly = {
 
 static int __init init_cgroup_cls(void)
 {
-       int ret = register_tcf_proto_ops(&cls_cgroup_ops);
-       if (ret)
-               return ret;
+       int ret;
+
        ret = cgroup_load_subsys(&net_cls_subsys);
        if (ret)
-               unregister_tcf_proto_ops(&cls_cgroup_ops);
+               goto out;
+
+#ifndef CONFIG_NET_CLS_CGROUP
+       /* We can't use rcu_assign_pointer because this is an int. */
+       smp_wmb();
+       net_cls_subsys_id = net_cls_subsys.subsys_id;
+#endif
+
+       ret = register_tcf_proto_ops(&cls_cgroup_ops);
+       if (ret)
+               cgroup_unload_subsys(&net_cls_subsys);
+
+out:
        return ret;
 }
 
 static void __exit exit_cgroup_cls(void)
 {
        unregister_tcf_proto_ops(&cls_cgroup_ops);
+
+#ifndef CONFIG_NET_CLS_CGROUP
+       net_cls_subsys_id = -1;
+       synchronize_rcu();
+#endif
+
        cgroup_unload_subsys(&net_cls_subsys);
 }
 
index fe35c1f..b9e8c3b 100644 (file)
@@ -1195,6 +1195,11 @@ nla_put_failure:
        return -1;
 }
 
+static bool tc_qdisc_dump_ignore(struct Qdisc *q)
+{
+       return (q->flags & TCQ_F_BUILTIN) ? true : false;
+}
+
 static int qdisc_notify(struct net *net, struct sk_buff *oskb,
                        struct nlmsghdr *n, u32 clid,
                        struct Qdisc *old, struct Qdisc *new)
@@ -1206,11 +1211,11 @@ static int qdisc_notify(struct net *net, struct sk_buff *oskb,
        if (!skb)
                return -ENOBUFS;
 
-       if (old && old->handle) {
+       if (old && !tc_qdisc_dump_ignore(old)) {
                if (tc_fill_qdisc(skb, old, clid, pid, n->nlmsg_seq, 0, RTM_DELQDISC) < 0)
                        goto err_out;
        }
-       if (new) {
+       if (new && !tc_qdisc_dump_ignore(new)) {
                if (tc_fill_qdisc(skb, new, clid, pid, n->nlmsg_seq, old ? NLM_F_REPLACE : 0, RTM_NEWQDISC) < 0)
                        goto err_out;
        }
@@ -1223,11 +1228,6 @@ err_out:
        return -EINVAL;
 }
 
-static bool tc_qdisc_dump_ignore(struct Qdisc *q)
-{
-       return (q->flags & TCQ_F_BUILTIN) ? true : false;
-}
-
 static int tc_dump_qdisc_root(struct Qdisc *root, struct sk_buff *skb,
                              struct netlink_callback *cb,
                              int *q_idx_p, int s_q_idx)
index f9f7d08..367d547 100644 (file)
@@ -94,6 +94,7 @@
 
 #include <net/compat.h>
 #include <net/wext.h>
+#include <net/cls_cgroup.h>
 
 #include <net/sock.h>
 #include <linux/netfilter.h>
@@ -558,6 +559,8 @@ static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
        struct sock_iocb *si = kiocb_to_siocb(iocb);
        int err;
 
+       sock_update_classid(sock->sk);
+
        si->sock = sock;
        si->scm = NULL;
        si->msg = msg;
@@ -684,6 +687,8 @@ static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
 {
        struct sock_iocb *si = kiocb_to_siocb(iocb);
 
+       sock_update_classid(sock->sk);
+
        si->sock = sock;
        si->scm = NULL;
        si->msg = msg;
@@ -777,6 +782,8 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
        if (unlikely(!sock->ops->splice_read))
                return -EINVAL;
 
+       sock_update_classid(sock->sk);
+
        return sock->ops->splice_read(sock, ppos, pipe, len, flags);
 }
 
@@ -3069,6 +3076,8 @@ int kernel_setsockopt(struct socket *sock, int level, int optname,
 int kernel_sendpage(struct socket *sock, struct page *page, int offset,
                    size_t size, int flags)
 {
+       sock_update_classid(sock->sk);
+
        if (sock->ops->sendpage)
                return sock->ops->sendpage(sock, page, offset, size, flags);