]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-2.6
authorDavid S. Miller <davem@davemloft.net>
Sat, 3 Jul 2010 05:04:49 +0000 (22:04 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sat, 3 Jul 2010 05:04:49 +0000 (22:04 -0700)
148 files changed:
MAINTAINERS
drivers/bluetooth/bluecard_cs.c
drivers/bluetooth/hci_bcsp.c
drivers/isdn/capi/kcapi.c
drivers/isdn/gigaset/asyncdata.c
drivers/isdn/gigaset/capi.c
drivers/isdn/gigaset/common.c
drivers/isdn/gigaset/ev-layer.c
drivers/isdn/gigaset/gigaset.h
drivers/isdn/gigaset/i4l.c
drivers/isdn/gigaset/isocdata.c
drivers/isdn/hardware/mISDN/hfcsusb.c
drivers/isdn/hardware/mISDN/netjet.c
drivers/isdn/hysdn/hysdn_net.c
drivers/net/8139cp.c
drivers/net/8139too.c
drivers/net/Kconfig
drivers/net/benet/be_cmds.c
drivers/net/bnx2.c
drivers/net/bonding/bond_alb.c
drivers/net/bonding/bond_main.c
drivers/net/can/mscan/mpc5xxx_can.c
drivers/net/cnic.c
drivers/net/cpmac.c
drivers/net/e1000/e1000_main.c
drivers/net/e1000e/netdev.c
drivers/net/ehea/ehea.h
drivers/net/ehea/ehea_main.c
drivers/net/enic/enic.h
drivers/net/enic/enic_main.c
drivers/net/enic/vnic_dev.c
drivers/net/epic100.c
drivers/net/fec.c
drivers/net/fs_enet/mac-fcc.c
drivers/net/gianfar.c
drivers/net/greth.c
drivers/net/ixgbe/ixgbe_common.c
drivers/net/ixgbe/ixgbe_ethtool.c
drivers/net/ixgbe/ixgbe_main.c
drivers/net/ixgbe/ixgbe_phy.c
drivers/net/ixgbe/ixgbe_type.h
drivers/net/korina.c
drivers/net/ksz884x.c
drivers/net/lib82596.c
drivers/net/mipsnet.c
drivers/net/mv643xx_eth.c
drivers/net/netxen/netxen_nic_ctx.c
drivers/net/netxen/netxen_nic_hw.c
drivers/net/netxen/netxen_nic_init.c
drivers/net/pcmcia/pcnet_cs.c
drivers/net/pcmcia/smc91c92_cs.c
drivers/net/phy/lxt.c
drivers/net/ppp_generic.c
drivers/net/qlge/qlge_main.c
drivers/net/r8169.c
drivers/net/sfc/net_driver.h
drivers/net/sfc/siena.c
drivers/net/sky2.c
drivers/net/tehuti.c
drivers/net/ucc_geth.c
drivers/net/usb/asix.c
drivers/net/usb/hso.c
drivers/net/usb/rndis_host.c
drivers/net/usb/usbnet.c
drivers/net/virtio_net.c
drivers/net/vxge/vxge-main.c
drivers/net/wan/x25_asy.c
drivers/net/wimax/i2400m/fw.c
drivers/net/wireless/ath/ar9170/usb.c
drivers/net/wireless/ath/ath5k/attach.c
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath5k/phy.c
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/hostap/hostap_cs.c
drivers/net/wireless/hostap/hostap_hw.c
drivers/net/wireless/hostap/hostap_wlan.h
drivers/net/wireless/iwlwifi/iwl-3945.c
drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
drivers/net/wireless/iwlwifi/iwl-agn-lib.c
drivers/net/wireless/iwlwifi/iwl-agn-tx.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl-scan.c
drivers/net/wireless/iwlwifi/iwl-sta.c
drivers/net/wireless/iwlwifi/iwl3945-base.c
drivers/net/wireless/libertas/rx.c
drivers/net/wireless/libertas_tf/main.c
drivers/net/wireless/p54/p54pci.c
drivers/net/wireless/p54/p54usb.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/wl12xx/wl1251_sdio.c
drivers/serial/serial_cs.c
drivers/ssb/pci.c
drivers/ssb/sprom.c
include/linux/ethtool.h
include/linux/mv643xx_eth.h
include/linux/net.h
include/linux/netdevice.h
include/linux/skbuff.h
include/net/dst.h
include/net/sch_generic.h
include/net/snmp.h
include/net/sock.h
include/net/xfrm.h
net/8021q/vlan_core.c
net/8021q/vlan_dev.c
net/bluetooth/bnep/netdev.c
net/bridge/br_fdb.c
net/bridge/br_forward.c
net/caif/cfrfml.c
net/caif/cfserl.c
net/caif/cfveil.c
net/core/dev.c
net/core/ethtool.c
net/core/gen_estimator.c
net/core/pktgen.c
net/core/skbuff.c
net/ipv4/Kconfig
net/ipv4/ip_output.c
net/ipv4/ipmr.c
net/ipv4/syncookies.c
net/ipv4/tcp_hybla.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/udp.c
net/ipv6/icmp.c
net/ipv6/ip6mr.c
net/ipv6/mcast.c
net/ipv6/ndisc.c
net/ipv6/route.c
net/mac80211/agg-tx.c
net/mac80211/chan.c
net/mac80211/driver-ops.h
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/work.c
net/phonet/pep.c
net/rds/ib_cm.c
net/rds/iw_cm.c
net/sched/act_nat.c
net/sched/act_pedit.c
net/sched/cls_u32.c
net/sched/sch_teql.c
net/xfrm/xfrm_output.c
net/xfrm/xfrm_policy.c

index 13608bd2e7913941bae445f08c201912f798c2fd..2ebb56710f4d1b883f1ec379b312684533b6c57a 100644 (file)
@@ -2978,22 +2978,14 @@ F:      drivers/net/ixgb/
 F:     drivers/net/ixgbe/
 
 INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT
-M:     Zhu Yi <yi.zhu@intel.com>
-M:     Reinette Chatre <reinette.chatre@intel.com>
-M:     Intel Linux Wireless <ilw@linux.intel.com>
 L:     linux-wireless@vger.kernel.org
-W:     http://ipw2100.sourceforge.net
-S:     Odd Fixes
+S:     Orphan
 F:     Documentation/networking/README.ipw2100
 F:     drivers/net/wireless/ipw2x00/ipw2100.*
 
 INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT
-M:     Zhu Yi <yi.zhu@intel.com>
-M:     Reinette Chatre <reinette.chatre@intel.com>
-M:     Intel Linux Wireless <ilw@linux.intel.com>
 L:     linux-wireless@vger.kernel.org
-W:     http://ipw2200.sourceforge.net
-S:     Odd Fixes
+S:     Orphan
 F:     Documentation/networking/README.ipw2200
 F:     drivers/net/wireless/ipw2x00/ipw2200.*
 
@@ -3019,8 +3011,8 @@ F:        drivers/net/wimax/i2400m/
 F:     include/linux/wimax/i2400m.h
 
 INTEL WIRELESS WIFI LINK (iwlwifi)
-M:     Zhu Yi <yi.zhu@intel.com>
 M:     Reinette Chatre <reinette.chatre@intel.com>
+M:     Wey-Yi Guy <wey-yi.w.guy@intel.com>
 M:     Intel Linux Wireless <ilw@linux.intel.com>
 L:     linux-wireless@vger.kernel.org
 W:     http://intellinuxwireless.org
@@ -3030,7 +3022,6 @@ F:        drivers/net/wireless/iwlwifi/
 
 INTEL WIRELESS MULTICOMM 3200 WIFI (iwmc3200wifi)
 M:     Samuel Ortiz <samuel.ortiz@intel.com>
-M:     Zhu Yi <yi.zhu@intel.com>
 M:     Intel Linux Wireless <ilw@linux.intel.com>
 L:     linux-wireless@vger.kernel.org
 S:     Supported
index 6f907ebed2d50064a6c1058828097fca53192099..6d34f405a2f37424976a685c669217bbd17fbca9 100644 (file)
@@ -37,7 +37,7 @@
 #include <linux/wait.h>
 
 #include <linux/skbuff.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
index 40aec0fb85967d5354943545cb88ea9329444c86..42d69d4de05c9859bd01af180bc2937a1443d4fa 100644 (file)
@@ -244,7 +244,7 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
        if (rel) {
                hdr[0] |= 0x80 + bcsp->msgq_txseq;
                BT_DBG("Sending packet with seqno %u", bcsp->msgq_txseq);
-               bcsp->msgq_txseq = ++(bcsp->msgq_txseq) & 0x07;
+               bcsp->msgq_txseq = (bcsp->msgq_txseq + 1) & 0x07;
        }
 
        if (bcsp->use_crc)
index bde3c88b8b270e0ca527849b0f58c9647bfb67ad..b054494df846958d99fdc45c4075dc57339981bd 100644 (file)
@@ -1020,12 +1020,12 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data)
                if (cmd == AVMB1_ADDCARD) {
                   if ((retval = copy_from_user(&cdef, data,
                                            sizeof(avmb1_carddef))))
-                          return retval;
+                          return -EFAULT;
                   cdef.cardtype = AVM_CARDTYPE_B1;
                } else {
                   if ((retval = copy_from_user(&cdef, data,
                                            sizeof(avmb1_extcarddef))))
-                          return retval;
+                          return -EFAULT;
                }
                cparams.port = cdef.port;
                cparams.irq = cdef.irq;
@@ -1218,7 +1218,7 @@ int capi20_manufacturer(unsigned int cmd, void __user *data)
                kcapi_carddef cdef;
 
                if ((retval = copy_from_user(&cdef, data, sizeof(cdef))))
-                       return retval;
+                       return -EFAULT;
 
                cparams.port = cdef.port;
                cparams.irq = cdef.irq;
index c5016bd2d94f6d10f132a288e3b9b11e5185b66f..c3b1dc3a13a0f998a23e01b81d3b99ede2bc2428 100644 (file)
@@ -126,26 +126,6 @@ static unsigned lock_loop(unsigned numbytes, struct inbuf_t *inbuf)
        return numbytes;
 }
 
-/* set up next receive skb for data mode
- */
-static void new_rcv_skb(struct bc_state *bcs)
-{
-       struct cardstate *cs = bcs->cs;
-       unsigned short hw_hdr_len = cs->hw_hdr_len;
-
-       if (bcs->ignore) {
-               bcs->skb = NULL;
-               return;
-       }
-
-       bcs->skb = dev_alloc_skb(SBUFSIZE + hw_hdr_len);
-       if (bcs->skb == NULL) {
-               dev_warn(cs->dev, "could not allocate new skb\n");
-               return;
-       }
-       skb_reserve(bcs->skb, hw_hdr_len);
-}
-
 /* process a block of received bytes in HDLC data mode
  * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 == L2_HDLC)
  * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes.
@@ -159,8 +139,8 @@ static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf)
        struct cardstate *cs = inbuf->cs;
        struct bc_state *bcs = cs->bcs;
        int inputstate = bcs->inputstate;
-       __u16 fcs = bcs->fcs;
-       struct sk_buff *skb = bcs->skb;
+       __u16 fcs = bcs->rx_fcs;
+       struct sk_buff *skb = bcs->rx_skb;
        unsigned char *src = inbuf->data + inbuf->head;
        unsigned procbytes = 0;
        unsigned char c;
@@ -245,8 +225,7 @@ byte_stuff:
 
                                /* prepare reception of next frame */
                                inputstate &= ~INS_have_data;
-                               new_rcv_skb(bcs);
-                               skb = bcs->skb;
+                               skb = gigaset_new_rx_skb(bcs);
                        } else {
                                /* empty frame (7E 7E) */
 #ifdef CONFIG_GIGASET_DEBUG
@@ -255,8 +234,7 @@ byte_stuff:
                                if (!skb) {
                                        /* skipped (?) */
                                        gigaset_isdn_rcv_err(bcs);
-                                       new_rcv_skb(bcs);
-                                       skb = bcs->skb;
+                                       skb = gigaset_new_rx_skb(bcs);
                                }
                        }
 
@@ -279,11 +257,11 @@ byte_stuff:
 #endif
                inputstate |= INS_have_data;
                if (skb) {
-                       if (skb->len == SBUFSIZE) {
+                       if (skb->len >= bcs->rx_bufsize) {
                                dev_warn(cs->dev, "received packet too long\n");
                                dev_kfree_skb_any(skb);
                                /* skip remainder of packet */
-                               bcs->skb = skb = NULL;
+                               bcs->rx_skb = skb = NULL;
                        } else {
                                *__skb_put(skb, 1) = c;
                                fcs = crc_ccitt_byte(fcs, c);
@@ -292,7 +270,7 @@ byte_stuff:
        }
 
        bcs->inputstate = inputstate;
-       bcs->fcs = fcs;
+       bcs->rx_fcs = fcs;
        return procbytes;
 }
 
@@ -308,18 +286,18 @@ static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf)
        struct cardstate *cs = inbuf->cs;
        struct bc_state *bcs = cs->bcs;
        int inputstate = bcs->inputstate;
-       struct sk_buff *skb = bcs->skb;
+       struct sk_buff *skb = bcs->rx_skb;
        unsigned char *src = inbuf->data + inbuf->head;
        unsigned procbytes = 0;
        unsigned char c;
 
        if (!skb) {
                /* skip this block */
-               new_rcv_skb(bcs);
+               gigaset_new_rx_skb(bcs);
                return numbytes;
        }
 
-       while (procbytes < numbytes && skb->len < SBUFSIZE) {
+       while (procbytes < numbytes && skb->len < bcs->rx_bufsize) {
                c = *src++;
                procbytes++;
 
@@ -343,7 +321,7 @@ static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf)
        if (inputstate & INS_have_data) {
                gigaset_skb_rcvd(bcs, skb);
                inputstate &= ~INS_have_data;
-               new_rcv_skb(bcs);
+               gigaset_new_rx_skb(bcs);
        }
 
        bcs->inputstate = inputstate;
index 8f78f15c8ef78798f06a6e4a076a718829b7999c..6fbe8999c4191e6b5b7d1ac78512c1135803f4c5 100644 (file)
@@ -70,7 +70,7 @@
 #define MAX_NUMBER_DIGITS 20
 #define MAX_FMT_IE_LEN 20
 
-/* values for gigaset_capi_appl.connected */
+/* values for bcs->apconnstate */
 #define APCONN_NONE    0       /* inactive/listening */
 #define APCONN_SETUP   1       /* connecting */
 #define APCONN_ACTIVE  2       /* B channel up */
@@ -80,10 +80,10 @@ struct gigaset_capi_appl {
        struct list_head ctrlist;
        struct gigaset_capi_appl *bcnext;
        u16 id;
+       struct capi_register_params rp;
        u16 nextMessageNumber;
        u32 listenInfoMask;
        u32 listenCIPmask;
-       int connected;
 };
 
 /* CAPI specific controller data structure */
@@ -319,6 +319,39 @@ static const char *format_ie(const char *ie)
        return result;
 }
 
+/*
+ * emit DATA_B3_CONF message
+ */
+static void send_data_b3_conf(struct cardstate *cs, struct capi_ctr *ctr,
+                             u16 appl, u16 msgid, int channel,
+                             u16 handle, u16 info)
+{
+       struct sk_buff *cskb;
+       u8 *msg;
+
+       cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC);
+       if (!cskb) {
+               dev_err(cs->dev, "%s: out of memory\n", __func__);
+               return;
+       }
+       /* frequent message, avoid _cmsg overhead */
+       msg = __skb_put(cskb, CAPI_DATA_B3_CONF_LEN);
+       CAPIMSG_SETLEN(msg, CAPI_DATA_B3_CONF_LEN);
+       CAPIMSG_SETAPPID(msg, appl);
+       CAPIMSG_SETCOMMAND(msg, CAPI_DATA_B3);
+       CAPIMSG_SETSUBCOMMAND(msg,  CAPI_CONF);
+       CAPIMSG_SETMSGID(msg, msgid);
+       CAPIMSG_SETCONTROLLER(msg, ctr->cnr);
+       CAPIMSG_SETPLCI_PART(msg, channel);
+       CAPIMSG_SETNCCI_PART(msg, 1);
+       CAPIMSG_SETHANDLE_CONF(msg, handle);
+       CAPIMSG_SETINFO_CONF(msg, info);
+
+       /* emit message */
+       dump_rawmsg(DEBUG_MCMD, __func__, msg);
+       capi_ctr_handle_message(ctr, appl, cskb);
+}
+
 
 /*
  * driver interface functions
@@ -339,7 +372,6 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb)
        struct gigaset_capi_ctr *iif = cs->iif;
        struct gigaset_capi_appl *ap = bcs->ap;
        unsigned char *req = skb_mac_header(dskb);
-       struct sk_buff *cskb;
        u16 flags;
 
        /* update statistics */
@@ -351,39 +383,22 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb)
        }
 
        /* don't send further B3 messages if disconnected */
-       if (ap->connected < APCONN_ACTIVE) {
+       if (bcs->apconnstate < APCONN_ACTIVE) {
                gig_dbg(DEBUG_LLDATA, "disconnected, discarding ack");
                return;
        }
 
-       /* ToDo: honor unset "delivery confirmation" bit */
+       /*
+        * send DATA_B3_CONF if "delivery confirmation" bit was set in request;
+        * otherwise it has already been sent by do_data_b3_req()
+        */
        flags = CAPIMSG_FLAGS(req);
-
-       /* build DATA_B3_CONF message */
-       cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC);
-       if (!cskb) {
-               dev_err(cs->dev, "%s: out of memory\n", __func__);
-               return;
-       }
-       /* frequent message, avoid _cmsg overhead */
-       CAPIMSG_SETLEN(cskb->data, CAPI_DATA_B3_CONF_LEN);
-       CAPIMSG_SETAPPID(cskb->data, ap->id);
-       CAPIMSG_SETCOMMAND(cskb->data, CAPI_DATA_B3);
-       CAPIMSG_SETSUBCOMMAND(cskb->data,  CAPI_CONF);
-       CAPIMSG_SETMSGID(cskb->data, CAPIMSG_MSGID(req));
-       CAPIMSG_SETCONTROLLER(cskb->data, iif->ctr.cnr);
-       CAPIMSG_SETPLCI_PART(cskb->data, bcs->channel + 1);
-       CAPIMSG_SETNCCI_PART(cskb->data, 1);
-       CAPIMSG_SETHANDLE_CONF(cskb->data, CAPIMSG_HANDLE_REQ(req));
-       if (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION)
-               CAPIMSG_SETINFO_CONF(cskb->data,
-                                    CapiFlagsNotSupportedByProtocol);
-       else
-               CAPIMSG_SETINFO_CONF(cskb->data, CAPI_NOERROR);
-
-       /* emit message */
-       dump_rawmsg(DEBUG_LLDATA, "DATA_B3_CONF", cskb->data);
-       capi_ctr_handle_message(&iif->ctr, ap->id, cskb);
+       if (flags & CAPI_FLAGS_DELIVERY_CONFIRMATION)
+               send_data_b3_conf(cs, &iif->ctr, ap->id, CAPIMSG_MSGID(req),
+                                 bcs->channel + 1, CAPIMSG_HANDLE_REQ(req),
+                                 (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION) ?
+                                       CapiFlagsNotSupportedByProtocol :
+                                       CAPI_NOERROR);
 }
 EXPORT_SYMBOL_GPL(gigaset_skb_sent);
 
@@ -412,7 +427,7 @@ void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb)
        }
 
        /* don't send further B3 messages if disconnected */
-       if (ap->connected < APCONN_ACTIVE) {
+       if (bcs->apconnstate < APCONN_ACTIVE) {
                gig_dbg(DEBUG_LLDATA, "disconnected, discarding data");
                dev_kfree_skb_any(skb);
                return;
@@ -484,6 +499,7 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
        u32 actCIPmask;
        struct sk_buff *skb;
        unsigned int msgsize;
+       unsigned long flags;
        int i;
 
        /*
@@ -608,7 +624,14 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
                format_ie(iif->hcmsg.CalledPartyNumber));
 
        /* scan application list for matching listeners */
-       bcs->ap = NULL;
+       spin_lock_irqsave(&bcs->aplock, flags);
+       if (bcs->ap != NULL || bcs->apconnstate != APCONN_NONE) {
+               dev_warn(cs->dev, "%s: channel not properly cleared (%p/%d)\n",
+                        __func__, bcs->ap, bcs->apconnstate);
+               bcs->ap = NULL;
+               bcs->apconnstate = APCONN_NONE;
+       }
+       spin_unlock_irqrestore(&bcs->aplock, flags);
        actCIPmask = 1 | (1 << iif->hcmsg.CIPValue);
        list_for_each_entry(ap, &iif->appls, ctrlist)
                if (actCIPmask & ap->listenCIPmask) {
@@ -626,10 +649,12 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
                        dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg);
 
                        /* add to listeners on this B channel, update state */
+                       spin_lock_irqsave(&bcs->aplock, flags);
                        ap->bcnext = bcs->ap;
                        bcs->ap = ap;
                        bcs->chstate |= CHS_NOTIFY_LL;
-                       ap->connected = APCONN_SETUP;
+                       bcs->apconnstate = APCONN_SETUP;
+                       spin_unlock_irqrestore(&bcs->aplock, flags);
 
                        /* emit message */
                        capi_ctr_handle_message(&iif->ctr, ap->id, skb);
@@ -654,7 +679,7 @@ static void send_disconnect_ind(struct bc_state *bcs,
        struct gigaset_capi_ctr *iif = cs->iif;
        struct sk_buff *skb;
 
-       if (ap->connected == APCONN_NONE)
+       if (bcs->apconnstate == APCONN_NONE)
                return;
 
        capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT, CAPI_IND,
@@ -668,7 +693,6 @@ static void send_disconnect_ind(struct bc_state *bcs,
        }
        capi_cmsg2message(&iif->hcmsg, __skb_put(skb, CAPI_DISCONNECT_IND_LEN));
        dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg);
-       ap->connected = APCONN_NONE;
        capi_ctr_handle_message(&iif->ctr, ap->id, skb);
 }
 
@@ -685,9 +709,9 @@ static void send_disconnect_b3_ind(struct bc_state *bcs,
        struct sk_buff *skb;
 
        /* nothing to do if no logical connection active */
-       if (ap->connected < APCONN_ACTIVE)
+       if (bcs->apconnstate < APCONN_ACTIVE)
                return;
-       ap->connected = APCONN_SETUP;
+       bcs->apconnstate = APCONN_SETUP;
 
        capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND,
                         ap->nextMessageNumber++,
@@ -714,14 +738,25 @@ void gigaset_isdn_connD(struct bc_state *bcs)
 {
        struct cardstate *cs = bcs->cs;
        struct gigaset_capi_ctr *iif = cs->iif;
-       struct gigaset_capi_appl *ap = bcs->ap;
+       struct gigaset_capi_appl *ap;
        struct sk_buff *skb;
        unsigned int msgsize;
+       unsigned long flags;
 
+       spin_lock_irqsave(&bcs->aplock, flags);
+       ap = bcs->ap;
        if (!ap) {
+               spin_unlock_irqrestore(&bcs->aplock, flags);
                dev_err(cs->dev, "%s: no application\n", __func__);
                return;
        }
+       if (bcs->apconnstate == APCONN_NONE) {
+               spin_unlock_irqrestore(&bcs->aplock, flags);
+               dev_warn(cs->dev, "%s: application %u not connected\n",
+                        __func__, ap->id);
+               return;
+       }
+       spin_unlock_irqrestore(&bcs->aplock, flags);
        while (ap->bcnext) {
                /* this should never happen */
                dev_warn(cs->dev, "%s: dropping extra application %u\n",
@@ -730,11 +765,6 @@ void gigaset_isdn_connD(struct bc_state *bcs)
                                    CapiCallGivenToOtherApplication);
                ap->bcnext = ap->bcnext->bcnext;
        }
-       if (ap->connected == APCONN_NONE) {
-               dev_warn(cs->dev, "%s: application %u not connected\n",
-                        __func__, ap->id);
-               return;
-       }
 
        /* prepare CONNECT_ACTIVE_IND message
         * Note: LLC not supported by device
@@ -772,17 +802,24 @@ void gigaset_isdn_connD(struct bc_state *bcs)
 void gigaset_isdn_hupD(struct bc_state *bcs)
 {
        struct gigaset_capi_appl *ap;
+       unsigned long flags;
 
        /*
         * ToDo: pass on reason code reported by device
         * (requires ev-layer state machine extension to collect
         * ZCAU device reply)
         */
-       for (ap = bcs->ap; ap != NULL; ap = ap->bcnext) {
+       spin_lock_irqsave(&bcs->aplock, flags);
+       while (bcs->ap != NULL) {
+               ap = bcs->ap;
+               bcs->ap = ap->bcnext;
+               spin_unlock_irqrestore(&bcs->aplock, flags);
                send_disconnect_b3_ind(bcs, ap);
                send_disconnect_ind(bcs, ap, 0);
+               spin_lock_irqsave(&bcs->aplock, flags);
        }
-       bcs->ap = NULL;
+       bcs->apconnstate = APCONN_NONE;
+       spin_unlock_irqrestore(&bcs->aplock, flags);
 }
 
 /**
@@ -796,24 +833,21 @@ void gigaset_isdn_connB(struct bc_state *bcs)
 {
        struct cardstate *cs = bcs->cs;
        struct gigaset_capi_ctr *iif = cs->iif;
-       struct gigaset_capi_appl *ap = bcs->ap;
+       struct gigaset_capi_appl *ap;
        struct sk_buff *skb;
+       unsigned long flags;
        unsigned int msgsize;
        u8 command;
 
+       spin_lock_irqsave(&bcs->aplock, flags);
+       ap = bcs->ap;
        if (!ap) {
+               spin_unlock_irqrestore(&bcs->aplock, flags);
                dev_err(cs->dev, "%s: no application\n", __func__);
                return;
        }
-       while (ap->bcnext) {
-               /* this should never happen */
-               dev_warn(cs->dev, "%s: dropping extra application %u\n",
-                        __func__, ap->bcnext->id);
-               send_disconnect_ind(bcs, ap->bcnext,
-                                   CapiCallGivenToOtherApplication);
-               ap->bcnext = ap->bcnext->bcnext;
-       }
-       if (!ap->connected) {
+       if (!bcs->apconnstate) {
+               spin_unlock_irqrestore(&bcs->aplock, flags);
                dev_warn(cs->dev, "%s: application %u not connected\n",
                         __func__, ap->id);
                return;
@@ -825,13 +859,26 @@ void gigaset_isdn_connB(struct bc_state *bcs)
         * CONNECT_B3_ACTIVE_IND in reply to CONNECT_B3_RESP
         * Parameters in both cases always: NCCI = 1, NCPI empty
         */
-       if (ap->connected >= APCONN_ACTIVE) {
+       if (bcs->apconnstate >= APCONN_ACTIVE) {
                command = CAPI_CONNECT_B3_ACTIVE;
                msgsize = CAPI_CONNECT_B3_ACTIVE_IND_BASELEN;
        } else {
                command = CAPI_CONNECT_B3;
                msgsize = CAPI_CONNECT_B3_IND_BASELEN;
        }
+       bcs->apconnstate = APCONN_ACTIVE;
+
+       spin_unlock_irqrestore(&bcs->aplock, flags);
+
+       while (ap->bcnext) {
+               /* this should never happen */
+               dev_warn(cs->dev, "%s: dropping extra application %u\n",
+                        __func__, ap->bcnext->id);
+               send_disconnect_ind(bcs, ap->bcnext,
+                                   CapiCallGivenToOtherApplication);
+               ap->bcnext = ap->bcnext->bcnext;
+       }
+
        capi_cmsg_header(&iif->hcmsg, ap->id, command, CAPI_IND,
                         ap->nextMessageNumber++,
                         iif->ctr.cnr | ((bcs->channel + 1) << 8) | (1 << 16));
@@ -842,7 +889,6 @@ void gigaset_isdn_connB(struct bc_state *bcs)
        }
        capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize));
        dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg);
-       ap->connected = APCONN_ACTIVE;
        capi_ctr_handle_message(&iif->ctr, ap->id, skb);
 }
 
@@ -945,8 +991,64 @@ static void gigaset_register_appl(struct capi_ctr *ctr, u16 appl,
                return;
        }
        ap->id = appl;
+       ap->rp = *rp;
 
        list_add(&ap->ctrlist, &iif->appls);
+       dev_info(cs->dev, "application %u registered\n", ap->id);
+}
+
+/*
+ * remove CAPI application from channel
+ * helper function to keep indentation levels down and stay in 80 columns
+ */
+
+static inline void remove_appl_from_channel(struct bc_state *bcs,
+                                           struct gigaset_capi_appl *ap)
+{
+       struct cardstate *cs = bcs->cs;
+       struct gigaset_capi_appl *bcap;
+       unsigned long flags;
+       int prevconnstate;
+
+       spin_lock_irqsave(&bcs->aplock, flags);
+       bcap = bcs->ap;
+       if (bcap == NULL) {
+               spin_unlock_irqrestore(&bcs->aplock, flags);
+               return;
+       }
+
+       /* check first application on channel */
+       if (bcap == ap) {
+               bcs->ap = ap->bcnext;
+               if (bcs->ap != NULL) {
+                       spin_unlock_irqrestore(&bcs->aplock, flags);
+                       return;
+               }
+
+               /* none left, clear channel state */
+               prevconnstate = bcs->apconnstate;
+               bcs->apconnstate = APCONN_NONE;
+               spin_unlock_irqrestore(&bcs->aplock, flags);
+
+               if (prevconnstate == APCONN_ACTIVE) {
+                       dev_notice(cs->dev, "%s: hanging up channel %u\n",
+                                  __func__, bcs->channel);
+                       gigaset_add_event(cs, &bcs->at_state,
+                                         EV_HUP, NULL, 0, NULL);
+                       gigaset_schedule_event(cs);
+               }
+               return;
+       }
+
+       /* check remaining list */
+       do {
+               if (bcap->bcnext == ap) {
+                       bcap->bcnext = bcap->bcnext->bcnext;
+                       return;
+               }
+               bcap = bcap->bcnext;
+       } while (bcap != NULL);
+       spin_unlock_irqrestore(&bcs->aplock, flags);
 }
 
 /*
@@ -958,19 +1060,19 @@ static void gigaset_release_appl(struct capi_ctr *ctr, u16 appl)
                = container_of(ctr, struct gigaset_capi_ctr, ctr);
        struct cardstate *cs = iif->ctr.driverdata;
        struct gigaset_capi_appl *ap, *tmp;
+       unsigned ch;
 
        list_for_each_entry_safe(ap, tmp, &iif->appls, ctrlist)
                if (ap->id == appl) {
-                       if (ap->connected != APCONN_NONE) {
-                               dev_err(cs->dev,
-                                       "%s: application %u still connected\n",
-                                       __func__, ap->id);
-                               /* ToDo: clear active connection */
-                       }
+                       /* remove from any channels */
+                       for (ch = 0; ch < cs->channels; ch++)
+                               remove_appl_from_channel(&cs->bcs[ch], ap);
+
+                       /* remove from registration list */
                        list_del(&ap->ctrlist);
                        kfree(ap);
+                       dev_info(cs->dev, "application %u released\n", appl);
                }
-
 }
 
 /*
@@ -1149,7 +1251,8 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
        char **commands;
        char *s;
        u8 *pp;
-       int i, l;
+       unsigned long flags;
+       int i, l, lbc, lhlc;
        u16 info;
 
        /* decode message */
@@ -1164,8 +1267,18 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
                send_conf(iif, ap, skb, CapiNoPlciAvailable);
                return;
        }
+       spin_lock_irqsave(&bcs->aplock, flags);
+       if (bcs->ap != NULL || bcs->apconnstate != APCONN_NONE)
+               dev_warn(cs->dev, "%s: channel not properly cleared (%p/%d)\n",
+                        __func__, bcs->ap, bcs->apconnstate);
        ap->bcnext = NULL;
        bcs->ap = ap;
+       bcs->apconnstate = APCONN_SETUP;
+       spin_unlock_irqrestore(&bcs->aplock, flags);
+
+       bcs->rx_bufsize = ap->rp.datablklen;
+       dev_kfree_skb(bcs->rx_skb);
+       gigaset_new_rx_skb(bcs);
        cmsg->adr.adrPLCI |= (bcs->channel + 1) << 8;
 
        /* build command table */
@@ -1273,42 +1386,59 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
                goto error;
        }
 
-       /* check/encode parameter: BC */
-       if (cmsg->BC && cmsg->BC[0]) {
-               /* explicit BC overrides CIP */
-               l = 2*cmsg->BC[0] + 7;
+       /*
+        * check/encode parameters: BC & HLC
+        * must be encoded together as device doesn't accept HLC separately
+        * explicit parameters override values derived from CIP
+        */
+
+       /* determine lengths */
+       if (cmsg->BC && cmsg->BC[0])            /* BC specified explicitly */
+               lbc = 2*cmsg->BC[0];
+       else if (cip2bchlc[cmsg->CIPValue].bc)  /* BC derived from CIP */
+               lbc = strlen(cip2bchlc[cmsg->CIPValue].bc);
+       else                                    /* no BC */
+               lbc = 0;
+       if (cmsg->HLC && cmsg->HLC[0])          /* HLC specified explicitly */
+               lhlc = 2*cmsg->HLC[0];
+       else if (cip2bchlc[cmsg->CIPValue].hlc) /* HLC derived from CIP */
+               lhlc = strlen(cip2bchlc[cmsg->CIPValue].hlc);
+       else                                    /* no HLC */
+               lhlc = 0;
+
+       if (lbc) {
+               /* have BC: allocate and assemble command string */
+               l = lbc + 7;            /* "^SBC=" + value + "\r" + null byte */
+               if (lhlc)
+                       l += lhlc + 7;  /* ";^SHLC=" + value */
                commands[AT_BC] = kmalloc(l, GFP_KERNEL);
                if (!commands[AT_BC])
                        goto oom;
                strcpy(commands[AT_BC], "^SBC=");
-               decode_ie(cmsg->BC, commands[AT_BC]+5);
+               if (cmsg->BC && cmsg->BC[0])    /* BC specified explicitly */
+                       decode_ie(cmsg->BC, commands[AT_BC] + 5);
+               else                            /* BC derived from CIP */
+                       strcpy(commands[AT_BC] + 5,
+                              cip2bchlc[cmsg->CIPValue].bc);
+               if (lhlc) {
+                       strcpy(commands[AT_BC] + lbc + 5, ";^SHLC=");
+                       if (cmsg->HLC && cmsg->HLC[0])
+                               /* HLC specified explicitly */
+                               decode_ie(cmsg->HLC,
+                                         commands[AT_BC] + lbc + 12);
+                       else    /* HLC derived from CIP */
+                               strcpy(commands[AT_BC] + lbc + 12,
+                                      cip2bchlc[cmsg->CIPValue].hlc);
+               }
                strcpy(commands[AT_BC] + l - 2, "\r");
-       } else if (cip2bchlc[cmsg->CIPValue].bc) {
-               l = strlen(cip2bchlc[cmsg->CIPValue].bc) + 7;
-               commands[AT_BC] = kmalloc(l, GFP_KERNEL);
-               if (!commands[AT_BC])
-                       goto oom;
-               snprintf(commands[AT_BC], l, "^SBC=%s\r",
-                        cip2bchlc[cmsg->CIPValue].bc);
-       }
-
-       /* check/encode parameter: HLC */
-       if (cmsg->HLC && cmsg->HLC[0]) {
-               /* explicit HLC overrides CIP */
-               l = 2*cmsg->HLC[0] + 7;
-               commands[AT_HLC] = kmalloc(l, GFP_KERNEL);
-               if (!commands[AT_HLC])
-                       goto oom;
-               strcpy(commands[AT_HLC], "^SHLC=");
-               decode_ie(cmsg->HLC, commands[AT_HLC]+5);
-               strcpy(commands[AT_HLC] + l - 2, "\r");
-       } else if (cip2bchlc[cmsg->CIPValue].hlc) {
-               l = strlen(cip2bchlc[cmsg->CIPValue].hlc) + 7;
-               commands[AT_HLC] = kmalloc(l, GFP_KERNEL);
-               if (!commands[AT_HLC])
-                       goto oom;
-               snprintf(commands[AT_HLC], l, "^SHLC=%s\r",
-                        cip2bchlc[cmsg->CIPValue].hlc);
+       } else {
+               /* no BC */
+               if (lhlc) {
+                       dev_notice(cs->dev, "%s: cannot set HLC without BC\n",
+                                  "CONNECT_REQ");
+                       info = CapiIllMessageParmCoding; /* ? */
+                       goto error;
+               }
        }
 
        /* check/encode parameter: B Protocol */
@@ -1322,13 +1452,13 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
                        bcs->proto2 = L2_HDLC;
                        break;
                case 1:
-                       bcs->proto2 = L2_BITSYNC;
+                       bcs->proto2 = L2_VOICE;
                        break;
                default:
                        dev_warn(cs->dev,
                            "B1 Protocol %u unsupported, using Transparent\n",
                                 cmsg->B1protocol);
-                       bcs->proto2 = L2_BITSYNC;
+                       bcs->proto2 = L2_VOICE;
                }
                if (cmsg->B2protocol != 1)
                        dev_warn(cs->dev,
@@ -1382,7 +1512,6 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
                goto error;
        }
        gigaset_schedule_event(cs);
-       ap->connected = APCONN_SETUP;
        send_conf(iif, ap, skb, CapiSuccess);
        return;
 
@@ -1410,6 +1539,7 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
        _cmsg *cmsg = &iif->acmsg;
        struct bc_state *bcs;
        struct gigaset_capi_appl *oap;
+       unsigned long flags;
        int channel;
 
        /* decode message */
@@ -1429,12 +1559,24 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
        switch (cmsg->Reject) {
        case 0:         /* Accept */
                /* drop all competing applications, keep only this one */
-               for (oap = bcs->ap; oap != NULL; oap = oap->bcnext)
-                       if (oap != ap)
+               spin_lock_irqsave(&bcs->aplock, flags);
+               while (bcs->ap != NULL) {
+                       oap = bcs->ap;
+                       bcs->ap = oap->bcnext;
+                       if (oap != ap) {
+                               spin_unlock_irqrestore(&bcs->aplock, flags);
                                send_disconnect_ind(bcs, oap,
                                        CapiCallGivenToOtherApplication);
+                               spin_lock_irqsave(&bcs->aplock, flags);
+                       }
+               }
                ap->bcnext = NULL;
                bcs->ap = ap;
+               spin_unlock_irqrestore(&bcs->aplock, flags);
+
+               bcs->rx_bufsize = ap->rp.datablklen;
+               dev_kfree_skb(bcs->rx_skb);
+               gigaset_new_rx_skb(bcs);
                bcs->chstate |= CHS_NOTIFY_LL;
 
                /* check/encode B channel protocol */
@@ -1448,13 +1590,13 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
                                bcs->proto2 = L2_HDLC;
                                break;
                        case 1:
-                               bcs->proto2 = L2_BITSYNC;
+                               bcs->proto2 = L2_VOICE;
                                break;
                        default:
                                dev_warn(cs->dev,
                        "B1 Protocol %u unsupported, using Transparent\n",
                                         cmsg->B1protocol);
-                               bcs->proto2 = L2_BITSYNC;
+                               bcs->proto2 = L2_VOICE;
                        }
                        if (cmsg->B2protocol != 1)
                                dev_warn(cs->dev,
@@ -1502,31 +1644,45 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif,
                send_disconnect_ind(bcs, ap, 0);
 
                /* remove it from the list of listening apps */
+               spin_lock_irqsave(&bcs->aplock, flags);
                if (bcs->ap == ap) {
                        bcs->ap = ap->bcnext;
-                       if (bcs->ap == NULL)
+                       if (bcs->ap == NULL) {
                                /* last one: stop ev-layer hupD notifications */
+                               bcs->apconnstate = APCONN_NONE;
                                bcs->chstate &= ~CHS_NOTIFY_LL;
+                       }
+                       spin_unlock_irqrestore(&bcs->aplock, flags);
                        return;
                }
                for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) {
                        if (oap->bcnext == ap) {
                                oap->bcnext = oap->bcnext->bcnext;
+                               spin_unlock_irqrestore(&bcs->aplock, flags);
                                return;
                        }
                }
+               spin_unlock_irqrestore(&bcs->aplock, flags);
                dev_err(cs->dev, "%s: application %u not found\n",
                        __func__, ap->id);
                return;
 
        default:                /* Reject */
                /* drop all competing applications, keep only this one */
-               for (oap = bcs->ap; oap != NULL; oap = oap->bcnext)
-                       if (oap != ap)
+               spin_lock_irqsave(&bcs->aplock, flags);
+               while (bcs->ap != NULL) {
+                       oap = bcs->ap;
+                       bcs->ap = oap->bcnext;
+                       if (oap != ap) {
+                               spin_unlock_irqrestore(&bcs->aplock, flags);
                                send_disconnect_ind(bcs, oap,
                                        CapiCallGivenToOtherApplication);
+                               spin_lock_irqsave(&bcs->aplock, flags);
+                       }
+               }
                ap->bcnext = NULL;
                bcs->ap = ap;
+               spin_unlock_irqrestore(&bcs->aplock, flags);
 
                /* reject call - will trigger DISCONNECT_IND for this app */
                dev_info(cs->dev, "%s: Reject=%x\n",
@@ -1549,6 +1705,7 @@ static void do_connect_b3_req(struct gigaset_capi_ctr *iif,
 {
        struct cardstate *cs = iif->ctr.driverdata;
        _cmsg *cmsg = &iif->acmsg;
+       struct bc_state *bcs;
        int channel;
 
        /* decode message */
@@ -1563,9 +1720,10 @@ static void do_connect_b3_req(struct gigaset_capi_ctr *iif,
                send_conf(iif, ap, skb, CapiIllContrPlciNcci);
                return;
        }
+       bcs = &cs->bcs[channel-1];
 
        /* mark logical connection active */
-       ap->connected = APCONN_ACTIVE;
+       bcs->apconnstate = APCONN_ACTIVE;
 
        /* build NCCI: always 1 (one B3 connection only) */
        cmsg->adr.adrNCCI |= 1 << 16;
@@ -1611,7 +1769,7 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif,
 
        if (cmsg->Reject) {
                /* Reject: clear B3 connect received flag */
-               ap->connected = APCONN_SETUP;
+               bcs->apconnstate = APCONN_SETUP;
 
                /* trigger hangup, causing eventual DISCONNECT_IND */
                if (!gigaset_add_event(cs, &bcs->at_state,
@@ -1683,11 +1841,11 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif,
        }
 
        /* skip if DISCONNECT_IND already sent */
-       if (!ap->connected)
+       if (!bcs->apconnstate)
                return;
 
        /* check for active logical connection */
-       if (ap->connected >= APCONN_ACTIVE) {
+       if (bcs->apconnstate >= APCONN_ACTIVE) {
                /*
                 * emit DISCONNECT_B3_IND with cause 0x3301
                 * use separate cmsg structure, as the content of iif->acmsg
@@ -1736,6 +1894,7 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif,
 {
        struct cardstate *cs = iif->ctr.driverdata;
        _cmsg *cmsg = &iif->acmsg;
+       struct bc_state *bcs;
        int channel;
 
        /* decode message */
@@ -1751,17 +1910,17 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif,
                send_conf(iif, ap, skb, CapiIllContrPlciNcci);
                return;
        }
+       bcs = &cs->bcs[channel-1];
 
        /* reject if logical connection not active */
-       if (ap->connected < APCONN_ACTIVE) {
+       if (bcs->apconnstate < APCONN_ACTIVE) {
                send_conf(iif, ap, skb,
                          CapiMessageNotSupportedInCurrentState);
                return;
        }
 
        /* trigger hangup, causing eventual DISCONNECT_B3_IND */
-       if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state,
-                              EV_HUP, NULL, 0, NULL)) {
+       if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) {
                send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR);
                return;
        }
@@ -1782,11 +1941,14 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,
                           struct sk_buff *skb)
 {
        struct cardstate *cs = iif->ctr.driverdata;
+       struct bc_state *bcs;
        int channel = CAPIMSG_PLCI_PART(skb->data);
        u16 ncci = CAPIMSG_NCCI_PART(skb->data);
        u16 msglen = CAPIMSG_LEN(skb->data);
        u16 datalen = CAPIMSG_DATALEN(skb->data);
        u16 flags = CAPIMSG_FLAGS(skb->data);
+       u16 msgid = CAPIMSG_MSGID(skb->data);
+       u16 handle = CAPIMSG_HANDLE_REQ(skb->data);
 
        /* frequent message, avoid _cmsg overhead */
        dump_rawmsg(DEBUG_LLDATA, "DATA_B3_REQ", skb->data);
@@ -1802,6 +1964,7 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,
                send_conf(iif, ap, skb, CapiIllContrPlciNcci);
                return;
        }
+       bcs = &cs->bcs[channel-1];
        if (msglen != CAPI_DATA_B3_REQ_LEN && msglen != CAPI_DATA_B3_REQ_LEN64)
                dev_notice(cs->dev, "%s: unexpected length %d\n",
                           "DATA_B3_REQ", msglen);
@@ -1821,7 +1984,7 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,
        }
 
        /* reject if logical connection not active */
-       if (ap->connected < APCONN_ACTIVE) {
+       if (bcs->apconnstate < APCONN_ACTIVE) {
                send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState);
                return;
        }
@@ -1832,17 +1995,19 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,
        skb_pull(skb, msglen);
 
        /* pass to device-specific module */
-       if (cs->ops->send_skb(&cs->bcs[channel-1], skb) < 0) {
+       if (cs->ops->send_skb(bcs, skb) < 0) {
                send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR);
                return;
        }
 
-       /* DATA_B3_CONF reply will be sent by gigaset_skb_sent() */
-
        /*
-        * ToDo: honor unset "delivery confirmation" bit
-        * (send DATA_B3_CONF immediately?)
+        * DATA_B3_CONF will be sent by gigaset_skb_sent() only if "delivery
+        * confirmation" bit is set; otherwise we have to send it now
         */
+       if (!(flags & CAPI_FLAGS_DELIVERY_CONFIRMATION))
+               send_data_b3_conf(cs, &iif->ctr, ap->id, msgid, channel, handle,
+                                 flags ? CapiFlagsNotSupportedByProtocol
+                                       : CAPI_NOERROR);
 }
 
 /*
index f6f45f2219209781aa6955153d494060f7f941ff..5d4befb81057a1c7675cb86d05b8cb82737495ec 100644 (file)
@@ -399,8 +399,8 @@ static void gigaset_freebcs(struct bc_state *bcs)
        gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel);
        clear_at_state(&bcs->at_state);
        gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel);
-       dev_kfree_skb(bcs->skb);
-       bcs->skb = NULL;
+       dev_kfree_skb(bcs->rx_skb);
+       bcs->rx_skb = NULL;
 
        for (i = 0; i < AT_NUM; ++i) {
                kfree(bcs->commands[i]);
@@ -634,19 +634,10 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
        bcs->emptycount = 0;
 #endif
 
-       gig_dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel);
-       bcs->fcs = PPP_INITFCS;
+       bcs->rx_bufsize = 0;
+       bcs->rx_skb = NULL;
+       bcs->rx_fcs = PPP_INITFCS;
        bcs->inputstate = 0;
-       if (cs->ignoreframes) {
-               bcs->skb = NULL;
-       } else {
-               bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
-               if (bcs->skb != NULL)
-                       skb_reserve(bcs->skb, cs->hw_hdr_len);
-               else
-                       pr_err("out of memory\n");
-       }
-
        bcs->channel = channel;
        bcs->cs = cs;
 
@@ -658,16 +649,15 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
        for (i = 0; i < AT_NUM; ++i)
                bcs->commands[i] = NULL;
 
+       spin_lock_init(&bcs->aplock);
+       bcs->ap = NULL;
+       bcs->apconnstate = 0;
+
        gig_dbg(DEBUG_INIT, "  setting up bcs[%d]->hw", channel);
        if (cs->ops->initbcshw(bcs))
                return bcs;
 
        gig_dbg(DEBUG_INIT, "  failed");
-
-       gig_dbg(DEBUG_INIT, "  freeing bcs[%d]->skb", channel);
-       dev_kfree_skb(bcs->skb);
-       bcs->skb = NULL;
-
        return NULL;
 }
 
@@ -839,14 +829,12 @@ void gigaset_bcs_reinit(struct bc_state *bcs)
        bcs->emptycount = 0;
 #endif
 
-       bcs->fcs = PPP_INITFCS;
+       bcs->rx_fcs = PPP_INITFCS;
        bcs->chstate = 0;
 
        bcs->ignore = cs->ignoreframes;
-       if (bcs->ignore) {
-               dev_kfree_skb(bcs->skb);
-               bcs->skb = NULL;
-       }
+       dev_kfree_skb(bcs->rx_skb);
+       bcs->rx_skb = NULL;
 
        cs->ops->reinitbcshw(bcs);
 }
index 206c380c52358c724aa72a06ce6c7405d9ff7164..ceaef9a04a42410b876de74558a51301d3a89c3e 100644 (file)
@@ -282,9 +282,7 @@ struct reply_t gigaset_tab_cid[] =
 /* dial */
 {EV_DIAL,       -1,  -1, -1,                    -1, -1, {ACT_DIAL} },
 {RSP_INIT,       0,   0, SEQ_DIAL,             601,  5, {ACT_CMD+AT_BC} },
-{RSP_OK,       601, 601, -1,                   602,  5, {ACT_CMD+AT_HLC} },
-{RSP_NULL,     602, 602, -1,                   603,  5, {ACT_CMD+AT_PROTO} },
-{RSP_OK,       602, 602, -1,                   603,  5, {ACT_CMD+AT_PROTO} },
+{RSP_OK,       601, 601, -1,                   603,  5, {ACT_CMD+AT_PROTO} },
 {RSP_OK,       603, 603, -1,                   604,  5, {ACT_CMD+AT_TYPE} },
 {RSP_OK,       604, 604, -1,                   605,  5, {ACT_CMD+AT_MSN} },
 {RSP_NULL,     605, 605, -1,                   606,  5, {ACT_CMD+AT_CLIP} },
index 05947f9c18496b8b9b197cbe61c6696f450ca24d..8738b0821fc9c29ea7ddcbec6a888db709766272 100644 (file)
 #define MAX_EVENTS 64          /* size of event queue */
 
 #define RBUFSIZE 8192
-#define SBUFSIZE 4096          /* sk_buff payload size */
-
-#define TRANSBUFSIZE 768       /* bytes per skb for transparent receive */
-#define MAX_BUF_SIZE (SBUFSIZE - 2)    /* Max. size of a data packet from LL */
 
 /* compile time options */
 #define GIG_MAJOR 0
@@ -190,10 +186,9 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
 #define AT_BC          3
 #define AT_PROTO       4
 #define AT_TYPE                5
-#define AT_HLC         6
-#define AT_CLIP                7
+#define AT_CLIP                6
 /* total number */
-#define AT_NUM         8
+#define AT_NUM         7
 
 /* variables in struct at_state_t */
 #define VAR_ZSAU       0
@@ -380,8 +375,10 @@ struct bc_state {
 
        struct at_state_t at_state;
 
-       __u16 fcs;
-       struct sk_buff *skb;
+       /* receive buffer */
+       unsigned rx_bufsize;            /* max size accepted by application */
+       struct sk_buff *rx_skb;
+       __u16 rx_fcs;
        int inputstate;                 /* see INS_XXXX */
 
        int channel;
@@ -406,7 +403,9 @@ struct bc_state {
                struct bas_bc_state *bas;       /* usb hardware driver (base) */
        } hw;
 
-       void *ap;                       /* LL application structure */
+       void *ap;                       /* associated LL application */
+       int apconnstate;                /* LL application connection state */
+       spinlock_t aplock;
 };
 
 struct cardstate {
@@ -801,8 +800,23 @@ static inline void gigaset_bchannel_up(struct bc_state *bcs)
        gigaset_schedule_event(bcs->cs);
 }
 
-/* handling routines for sk_buff */
-/* ============================= */
+/* set up next receive skb for data mode */
+static inline struct sk_buff *gigaset_new_rx_skb(struct bc_state *bcs)
+{
+       struct cardstate *cs = bcs->cs;
+       unsigned short hw_hdr_len = cs->hw_hdr_len;
+
+       if (bcs->ignore) {
+               bcs->rx_skb = NULL;
+       } else {
+               bcs->rx_skb = dev_alloc_skb(bcs->rx_bufsize + hw_hdr_len);
+               if (bcs->rx_skb == NULL)
+                       dev_warn(cs->dev, "could not allocate skb\n");
+               else
+                       skb_reserve(bcs->rx_skb, hw_hdr_len);
+       }
+       return bcs->rx_skb;
+}
 
 /* append received bytes to inbuf */
 int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
index c22e5ace8276a99fe39188eb13941e56f6b07cb4..f01c3c2e2e46eb5f5194fa8afa8ba78e8d3b8532 100644 (file)
 #include "gigaset.h"
 #include <linux/isdnif.h>
 
+#define SBUFSIZE       4096    /* sk_buff payload size */
+#define TRANSBUFSIZE   768     /* bytes per skb for transparent receive */
 #define HW_HDR_LEN     2       /* Header size used to store ack info */
+#define MAX_BUF_SIZE   (SBUFSIZE - HW_HDR_LEN) /* max data packet from LL */
 
 /* == Handling of I4L IO =====================================================*/
 
@@ -231,6 +234,15 @@ static int command_from_LL(isdn_ctrl *cntrl)
                        dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n");
                        return -EBUSY;
                }
+               switch (bcs->proto2) {
+               case L2_HDLC:
+                       bcs->rx_bufsize = SBUFSIZE;
+                       break;
+               default:                        /* assume transparent */
+                       bcs->rx_bufsize = TRANSBUFSIZE;
+               }
+               dev_kfree_skb(bcs->rx_skb);
+               gigaset_new_rx_skb(bcs);
 
                commands = kzalloc(AT_NUM*(sizeof *commands), GFP_ATOMIC);
                if (!commands) {
@@ -314,6 +326,15 @@ static int command_from_LL(isdn_ctrl *cntrl)
                        return -EINVAL;
                }
                bcs = cs->bcs + ch;
+               switch (bcs->proto2) {
+               case L2_HDLC:
+                       bcs->rx_bufsize = SBUFSIZE;
+                       break;
+               default:                        /* assume transparent */
+                       bcs->rx_bufsize = TRANSBUFSIZE;
+               }
+               dev_kfree_skb(bcs->rx_skb);
+               gigaset_new_rx_skb(bcs);
                if (!gigaset_add_event(cs, &bcs->at_state,
                                       EV_ACCEPT, NULL, 0, NULL))
                        return -ENOMEM;
index 16fd3bd488834101b74a7dd316f82b6badbe8b5d..2dfd346fc889abe9f423873551647c21d319038e 100644 (file)
@@ -500,19 +500,18 @@ int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len)
  */
 static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs)
 {
-       bcs->fcs = crc_ccitt_byte(bcs->fcs, c);
-       if (unlikely(bcs->skb == NULL)) {
+       bcs->rx_fcs = crc_ccitt_byte(bcs->rx_fcs, c);
+       if (bcs->rx_skb == NULL)
                /* skipping */
                return;
-       }
-       if (unlikely(bcs->skb->len == SBUFSIZE)) {
+       if (bcs->rx_skb->len >= bcs->rx_bufsize) {
                dev_warn(bcs->cs->dev, "received oversized packet discarded\n");
                bcs->hw.bas->giants++;
-               dev_kfree_skb_any(bcs->skb);
-               bcs->skb = NULL;
+               dev_kfree_skb_any(bcs->rx_skb);
+               bcs->rx_skb = NULL;
                return;
        }
-       *__skb_put(bcs->skb, 1) = c;
+       *__skb_put(bcs->rx_skb, 1) = c;
 }
 
 /* hdlc_flush
@@ -521,18 +520,13 @@ static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs)
 static inline void hdlc_flush(struct bc_state *bcs)
 {
        /* clear skb or allocate new if not skipping */
-       if (likely(bcs->skb != NULL))
-               skb_trim(bcs->skb, 0);
-       else if (!bcs->ignore) {
-               bcs->skb = dev_alloc_skb(SBUFSIZE + bcs->cs->hw_hdr_len);
-               if (bcs->skb)
-                       skb_reserve(bcs->skb, bcs->cs->hw_hdr_len);
-               else
-                       dev_err(bcs->cs->dev, "could not allocate skb\n");
-       }
+       if (bcs->rx_skb != NULL)
+               skb_trim(bcs->rx_skb, 0);
+       else
+               gigaset_new_rx_skb(bcs);
 
        /* reset packet state */
-       bcs->fcs = PPP_INITFCS;
+       bcs->rx_fcs = PPP_INITFCS;
 }
 
 /* hdlc_done
@@ -549,7 +543,7 @@ static inline void hdlc_done(struct bc_state *bcs)
                hdlc_flush(bcs);
                return;
        }
-       procskb = bcs->skb;
+       procskb = bcs->rx_skb;
        if (procskb == NULL) {
                /* previous error */
                gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__);
@@ -560,8 +554,8 @@ static inline void hdlc_done(struct bc_state *bcs)
                bcs->hw.bas->runts++;
                dev_kfree_skb_any(procskb);
                gigaset_isdn_rcv_err(bcs);
-       } else if (bcs->fcs != PPP_GOODFCS) {
-               dev_notice(cs->dev, "frame check error (0x%04x)\n", bcs->fcs);
+       } else if (bcs->rx_fcs != PPP_GOODFCS) {
+               dev_notice(cs->dev, "frame check error\n");
                bcs->hw.bas->fcserrs++;
                dev_kfree_skb_any(procskb);
                gigaset_isdn_rcv_err(bcs);
@@ -574,13 +568,8 @@ static inline void hdlc_done(struct bc_state *bcs)
                bcs->hw.bas->goodbytes += len;
                gigaset_skb_rcvd(bcs, procskb);
        }
-
-       bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
-       if (bcs->skb)
-               skb_reserve(bcs->skb, cs->hw_hdr_len);
-       else
-               dev_err(cs->dev, "could not allocate skb\n");
-       bcs->fcs = PPP_INITFCS;
+       gigaset_new_rx_skb(bcs);
+       bcs->rx_fcs = PPP_INITFCS;
 }
 
 /* hdlc_frag
@@ -597,8 +586,8 @@ static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits)
        dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits);
        bcs->hw.bas->alignerrs++;
        gigaset_isdn_rcv_err(bcs);
-       __skb_trim(bcs->skb, 0);
-       bcs->fcs = PPP_INITFCS;
+       __skb_trim(bcs->rx_skb, 0);
+       bcs->rx_fcs = PPP_INITFCS;
 }
 
 /* bit counts lookup table for HDLC bit unstuffing
@@ -847,7 +836,6 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
 static inline void trans_receive(unsigned char *src, unsigned count,
                                 struct bc_state *bcs)
 {
-       struct cardstate *cs = bcs->cs;
        struct sk_buff *skb;
        int dobytes;
        unsigned char *dst;
@@ -857,17 +845,11 @@ static inline void trans_receive(unsigned char *src, unsigned count,
                hdlc_flush(bcs);
                return;
        }
-       skb = bcs->skb;
-       if (unlikely(skb == NULL)) {
-               bcs->skb = skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
-               if (!skb) {
-                       dev_err(cs->dev, "could not allocate skb\n");
-                       return;
-               }
-               skb_reserve(skb, cs->hw_hdr_len);
-       }
+       skb = bcs->rx_skb;
+       if (skb == NULL)
+               skb = gigaset_new_rx_skb(bcs);
        bcs->hw.bas->goodbytes += skb->len;
-       dobytes = TRANSBUFSIZE - skb->len;
+       dobytes = bcs->rx_bufsize - skb->len;
        while (count > 0) {
                dst = skb_put(skb, count < dobytes ? count : dobytes);
                while (count > 0 && dobytes > 0) {
@@ -879,14 +861,10 @@ static inline void trans_receive(unsigned char *src, unsigned count,
                        dump_bytes(DEBUG_STREAM_DUMP,
                                   "rcv data", skb->data, skb->len);
                        gigaset_skb_rcvd(bcs, skb);
-                       bcs->skb = skb =
-                               dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
-                       if (!skb) {
-                               dev_err(cs->dev, "could not allocate skb\n");
+                       skb = gigaset_new_rx_skb(bcs);
+                       if (skb == NULL)
                                return;
-                       }
-                       skb_reserve(skb, cs->hw_hdr_len);
-                       dobytes = TRANSBUFSIZE;
+                       dobytes = bcs->rx_bufsize;
                }
        }
 }
index b3b7e2879bac25873da4d2666567f2c52fae434f..8700474747e8cd0251bc54f99f80cb2a7b8eb8e1 100644 (file)
@@ -97,8 +97,10 @@ static int write_reg(struct hfcsusb *hw, __u8 reg, __u8 val)
                        hw->name, __func__, reg, val);
 
        spin_lock(&hw->ctrl_lock);
-       if (hw->ctrl_cnt >= HFC_CTRL_BUFSIZE)
+       if (hw->ctrl_cnt >= HFC_CTRL_BUFSIZE) {
+               spin_unlock(&hw->ctrl_lock);
                return 1;
+       }
        buf = &hw->ctrl_buff[hw->ctrl_in_idx];
        buf->hfcs_reg = reg;
        buf->reg_val = val;
index 0a3553df065fcd38d884e939e040486760073de7..54ae71a907f937c8fcf3d443bf79d4a43a5499bd 100644 (file)
@@ -320,12 +320,12 @@ inittiger(struct tiger_hw *card)
                return -ENOMEM;
        }
        for (i = 0; i < 2; i++) {
-               card->bc[i].hsbuf = kmalloc(NJ_DMA_TXSIZE, GFP_KERNEL);
+               card->bc[i].hsbuf = kmalloc(NJ_DMA_TXSIZE, GFP_ATOMIC);
                if (!card->bc[i].hsbuf) {
                        pr_info("%s: no B%d send buffer\n", card->name, i + 1);
                        return -ENOMEM;
                }
-               card->bc[i].hrbuf = kmalloc(NJ_DMA_RXSIZE, GFP_KERNEL);
+               card->bc[i].hrbuf = kmalloc(NJ_DMA_RXSIZE, GFP_ATOMIC);
                if (!card->bc[i].hrbuf) {
                        pr_info("%s: no B%d recv buffer\n", card->name, i + 1);
                        return -ENOMEM;
index 72eb92647c1b15e2619f1969892196240a5d2fb2..feec8d89d719c07395ed0e5aa7b02fd6e7fb32c0 100644 (file)
@@ -187,12 +187,13 @@ void
 hysdn_rx_netpkt(hysdn_card * card, unsigned char *buf, unsigned short len)
 {
        struct net_local *lp = card->netif;
-       struct net_device *dev = lp->dev;
+       struct net_device *dev;
        struct sk_buff *skb;
 
        if (!lp)
                return;         /* non existing device */
 
+       dev = lp->dev;
        dev->stats.rx_bytes += len;
 
        skb = dev_alloc_skb(len);
index 9c149750e2bf9754518941e9233e94800d45b889..284a5f4a63ac8a48c955125c64e67ae8b89e16f9 100644 (file)
@@ -598,8 +598,8 @@ rx_next:
                        goto rx_status_loop;
 
                spin_lock_irqsave(&cp->lock, flags);
-               cpw16_f(IntrMask, cp_intr_mask);
                __napi_complete(napi);
+               cpw16_f(IntrMask, cp_intr_mask);
                spin_unlock_irqrestore(&cp->lock, flags);
        }
 
index 4ba72933f0da57b72f069e4d95a29fc1ad8da1f1..97d8068b372b228d6764055ad1d0529439c940af 100644 (file)
@@ -860,6 +860,7 @@ retry:
                }
 
        /* if unknown chip, assume array element #0, original RTL-8139 in this case */
+       i = 0;
        dev_dbg(&pdev->dev, "unknown chip version, assuming RTL-8139\n");
        dev_dbg(&pdev->dev, "TxConfig = 0x%lx\n", RTL_R32 (TxConfig));
        tp->chipset = 0;
@@ -2088,8 +2089,8 @@ static int rtl8139_poll(struct napi_struct *napi, int budget)
                 * again when we think we are done.
                 */
                spin_lock_irqsave(&tp->lock, flags);
-               RTL_W16_F(IntrMask, rtl8139_intr_mask);
                __napi_complete(napi);
+               RTL_W16_F(IntrMask, rtl8139_intr_mask);
                spin_unlock_irqrestore(&tp->lock, flags);
        }
        spin_unlock(&tp->rx_lock);
index 2decc597bda704bd74fac951551517421fc0a4e1..ce2fcdd4ab90521af8a8fb9a3f873b796b0a2bd9 100644 (file)
@@ -2754,6 +2754,7 @@ config MYRI10GE_DCA
 config NETXEN_NIC
        tristate "NetXen Multi port (1/10) Gigabit Ethernet NIC"
        depends on PCI
+       select FW_LOADER
        help
          This enables the support for NetXen's Gigabit Ethernet card.
 
@@ -2819,6 +2820,7 @@ config BNX2X
 config QLCNIC
        tristate "QLOGIC QLCNIC 1/10Gb Converged Ethernet NIC Support"
        depends on PCI
+       select FW_LOADER
        help
          This driver supports QLogic QLE8240 and QLE8242 Converged Ethernet
          devices.
index 9d11dbf5e4da2d96d941a48c2af51d8bae9bdb57..b9ad799c719f1d5b541a33d93d095318e6c362fc 100644 (file)
@@ -1429,7 +1429,7 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
        wrb = wrb_from_mccq(adapter);
        if (!wrb) {
                status = -EBUSY;
-               goto err;
+               goto err_unlock;
        }
        req = cmd->va;
        sge = nonembedded_sgl(wrb);
@@ -1457,7 +1457,10 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
        else
                status = adapter->flash_status;
 
-err:
+       return status;
+
+err_unlock:
+       spin_unlock_bh(&adapter->mcc_lock);
        return status;
 }
 
@@ -1497,7 +1500,7 @@ err:
        return status;
 }
 
-extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
+int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
                                struct be_dma_mem *nonemb_cmd)
 {
        struct be_mcc_wrb *wrb;
@@ -1590,7 +1593,7 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
 
        be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
                        OPCODE_LOWLEVEL_LOOPBACK_TEST, sizeof(*req));
-       req->hdr.timeout = 4;
+       req->hdr.timeout = cpu_to_le32(4);
 
        req->pattern = cpu_to_le64(pattern);
        req->src_port = cpu_to_le32(port_num);
@@ -1662,7 +1665,7 @@ err:
        return status;
 }
 
-extern int be_cmd_get_seeprom_data(struct be_adapter *adapter,
+int be_cmd_get_seeprom_data(struct be_adapter *adapter,
                                struct be_dma_mem *nonemb_cmd)
 {
        struct be_mcc_wrb *wrb;
index 188e356c30a30e005a69eaf05997ea57fdae880e..117432222a09e8b3c7521c6bf237621afe938fd9 100644 (file)
@@ -247,6 +247,7 @@ static const struct flash_spec flash_5709 = {
 MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl);
 
 static void bnx2_init_napi(struct bnx2 *bp);
+static void bnx2_del_napi(struct bnx2 *bp);
 
 static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_tx_ring_info *txr)
 {
@@ -3072,7 +3073,6 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
        u16 hw_cons, sw_cons, sw_ring_cons, sw_prod, sw_ring_prod;
        struct l2_fhdr *rx_hdr;
        int rx_pkt = 0, pg_ring_used = 0;
-       struct pci_dev *pdev = bp->pdev;
 
        hw_cons = bnx2_get_hw_rx_cons(bnapi);
        sw_cons = rxr->rx_cons;
@@ -3098,12 +3098,10 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
                skb = rx_buf->skb;
                prefetchw(skb);
 
-               if (!get_dma_ops(&pdev->dev)->sync_single_for_cpu) {
-                       next_rx_buf =
-                               &rxr->rx_buf_ring[
-                                       RX_RING_IDX(NEXT_RX_BD(sw_cons))];
-                       prefetch(next_rx_buf->desc);
-               }
+               next_rx_buf =
+                       &rxr->rx_buf_ring[RX_RING_IDX(NEXT_RX_BD(sw_cons))];
+               prefetch(next_rx_buf->desc);
+
                rx_buf->skb = NULL;
 
                dma_addr = dma_unmap_addr(rx_buf, mapping);
@@ -6270,6 +6268,7 @@ open_err:
        bnx2_free_skbs(bp);
        bnx2_free_irq(bp);
        bnx2_free_mem(bp);
+       bnx2_del_napi(bp);
        return rc;
 }
 
@@ -6537,6 +6536,7 @@ bnx2_close(struct net_device *dev)
        bnx2_free_irq(bp);
        bnx2_free_skbs(bp);
        bnx2_free_mem(bp);
+       bnx2_del_napi(bp);
        bp->link_up = 0;
        netif_carrier_off(bp->dev);
        bnx2_set_power_state(bp, PCI_D3hot);
@@ -8227,7 +8227,16 @@ bnx2_bus_string(struct bnx2 *bp, char *str)
        return str;
 }
 
-static void __devinit
+static void
+bnx2_del_napi(struct bnx2 *bp)
+{
+       int i;
+
+       for (i = 0; i < bp->irq_nvecs; i++)
+               netif_napi_del(&bp->bnx2_napi[i].napi);
+}
+
+static void
 bnx2_init_napi(struct bnx2 *bp)
 {
        int i;
index 40fdc41446cc130f1363e9d4a17a9d3203b3166b..df483076eda6df4284e9e576fc522a0ff022af11 100644 (file)
@@ -340,7 +340,8 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp)
 
        if ((client_info->assigned) &&
            (client_info->ip_src == arp->ip_dst) &&
-           (client_info->ip_dst == arp->ip_src)) {
+           (client_info->ip_dst == arp->ip_src) &&
+           (compare_ether_addr_64bits(client_info->mac_dst, arp->mac_src))) {
                /* update the clients MAC address */
                memcpy(client_info->mac_dst, arp->mac_src, ETH_ALEN);
                client_info->ntt = 1;
index 5e12462a9d5ed7965a56c3178244bc8fd646c290..c3d98dde2f86a5812067b2ef8ee52659b66dcda5 100644 (file)
@@ -168,7 +168,7 @@ static int arp_ip_count;
 static int bond_mode   = BOND_MODE_ROUNDROBIN;
 static int xmit_hashtype = BOND_XMIT_POLICY_LAYER2;
 static int lacp_fast;
-
+static int disable_netpoll = 1;
 
 const struct bond_parm_tbl bond_lacp_tbl[] = {
 {      "slow",         AD_LACP_SLOW},
@@ -1742,15 +1742,23 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
        bond_set_carrier(bond);
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-       if (slaves_support_netpoll(bond_dev)) {
-               bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
-               if (bond_dev->npinfo)
-                       slave_dev->npinfo = bond_dev->npinfo;
-       } else if (!(bond_dev->priv_flags & IFF_DISABLE_NETPOLL)) {
+       /*
+        * Netpoll and bonding is broken, make sure it is not initialized
+        * until it is fixed.
+        */
+       if (disable_netpoll) {
                bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
-               pr_info("New slave device %s does not support netpoll\n",
-                       slave_dev->name);
-               pr_info("Disabling netpoll support for %s\n", bond_dev->name);
+       } else {
+               if (slaves_support_netpoll(bond_dev)) {
+                       bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
+                       if (bond_dev->npinfo)
+                               slave_dev->npinfo = bond_dev->npinfo;
+               } else if (!(bond_dev->priv_flags & IFF_DISABLE_NETPOLL)) {
+                       bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
+                       pr_info("New slave device %s does not support netpoll\n",
+                               slave_dev->name);
+                       pr_info("Disabling netpoll support for %s\n", bond_dev->name);
+               }
        }
 #endif
        read_unlock(&bond->lock);
@@ -1950,8 +1958,11 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
        read_lock_bh(&bond->lock);
-       if (slaves_support_netpoll(bond_dev))
-               bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
+
+        /* Make sure netpoll over stays disabled until fixed. */
+       if (!disable_netpoll)
+               if (slaves_support_netpoll(bond_dev))
+                               bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
        read_unlock_bh(&bond->lock);
        if (slave_dev->netdev_ops->ndo_netpoll_cleanup)
                slave_dev->netdev_ops->ndo_netpoll_cleanup(slave_dev);
index 8af8442c694a69c2e4e5dea49ebcd7d13a4e92de..af753936e835840ac0127ea78f6421893887b37d 100644 (file)
@@ -73,7 +73,7 @@ static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev,
        else
                *mscan_clksrc = MSCAN_CLKSRC_XTAL;
 
-       freq = mpc5xxx_get_bus_frequency(ofdev->node);
+       freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node);
        if (!freq)
                return 0;
 
@@ -152,7 +152,7 @@ static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev,
        }
 
        /* Determine the MSCAN device index from the physical address */
-       pval = of_get_property(ofdev->node, "reg", &plen);
+       pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
        BUG_ON(!pval || plen < sizeof(*pval));
        clockidx = (*pval & 0x80) ? 1 : 0;
        if (*pval & 0x2000)
@@ -168,11 +168,11 @@ static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev,
         */
        if (clock_name && !strcmp(clock_name, "ip")) {
                *mscan_clksrc = MSCAN_CLKSRC_IPS;
-               freq = mpc5xxx_get_bus_frequency(ofdev->node);
+               freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node);
        } else {
                *mscan_clksrc = MSCAN_CLKSRC_BUS;
 
-               pval = of_get_property(ofdev->node,
+               pval = of_get_property(ofdev->dev.of_node,
                                       "fsl,mscan-clock-divider", &plen);
                if (pval && plen == sizeof(*pval))
                        clockdiv = *pval;
@@ -251,7 +251,7 @@ static int __devinit mpc5xxx_can_probe(struct of_device *ofdev,
                                       const struct of_device_id *id)
 {
        struct mpc5xxx_can_data *data = (struct mpc5xxx_can_data *)id->data;
-       struct device_node *np = ofdev->node;
+       struct device_node *np = ofdev->dev.of_node;
        struct net_device *dev;
        struct mscan_priv *priv;
        void __iomem *base;
index fe925663d39a535a5c9d2c6f65866c3f2f29e6d7..80471269977adefdaae7e0a7845611a2e1e7cadc 100644 (file)
@@ -3919,8 +3919,9 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev)
                HC_INDEX_DEF_C_ETH_ISCSI_CQ_CONS;
        context->cstorm_st_context.status_block_id = BNX2X_DEF_SB_ID;
 
-       context->xstorm_st_context.statistics_data = (cli |
-                               XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE);
+       if (cli < MAX_X_STAT_COUNTER_ID)
+               context->xstorm_st_context.statistics_data = cli |
+                               XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE;
 
        context->xstorm_ag_context.cdu_reserved =
                CDU_RSRVD_VALUE_TYPE_A(BNX2X_HW_CID(BNX2X_ISCSI_L2_CID, func),
@@ -3928,10 +3929,12 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev)
                                        ETH_CONNECTION_TYPE);
 
        /* reset xstorm per client statistics */
-       val = BAR_XSTRORM_INTMEM +
-             XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
-       for (i = 0; i < sizeof(struct xstorm_per_client_stats) / 4; i++)
-               CNIC_WR(dev, val + i * 4, 0);
+       if (cli < MAX_X_STAT_COUNTER_ID) {
+               val = BAR_XSTRORM_INTMEM +
+                     XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
+               for (i = 0; i < sizeof(struct xstorm_per_client_stats) / 4; i++)
+                       CNIC_WR(dev, val + i * 4, 0);
+       }
 
        cp->tx_cons_ptr =
                &cp->bnx2x_def_status_blk->c_def_status_block.index_values[
@@ -3978,9 +3981,11 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev)
                                                BNX2X_ISCSI_RX_SB_INDEX_NUM;
        context->ustorm_st_context.common.clientId = cli;
        context->ustorm_st_context.common.status_block_id = BNX2X_DEF_SB_ID;
-       context->ustorm_st_context.common.flags =
-               USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS;
-       context->ustorm_st_context.common.statistics_counter_id = cli;
+       if (cli < MAX_U_STAT_COUNTER_ID) {
+               context->ustorm_st_context.common.flags =
+                       USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS;
+               context->ustorm_st_context.common.statistics_counter_id = cli;
+       }
        context->ustorm_st_context.common.mc_alignment_log_size = 0;
        context->ustorm_st_context.common.bd_buff_size =
                                                cp->l2_single_buf_size;
@@ -4011,10 +4016,13 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev)
 
        /* client tstorm info */
        tstorm_client.mtu = cp->l2_single_buf_size - 14;
-       tstorm_client.config_flags =
-                       (TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE |
-                       TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE);
-       tstorm_client.statistics_counter_id = cli;
+       tstorm_client.config_flags = TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE;
+
+       if (cli < MAX_T_STAT_COUNTER_ID) {
+               tstorm_client.config_flags |=
+                               TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE;
+               tstorm_client.statistics_counter_id = cli;
+       }
 
        CNIC_WR(dev, BAR_TSTRORM_INTMEM +
                   TSTORM_CLIENT_CONFIG_OFFSET(port, cli),
@@ -4024,16 +4032,21 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev)
                   ((u32 *)&tstorm_client)[1]);
 
        /* reset tstorm per client statistics */
-       val = BAR_TSTRORM_INTMEM +
-             TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
-       for (i = 0; i < sizeof(struct tstorm_per_client_stats) / 4; i++)
-               CNIC_WR(dev, val + i * 4, 0);
+       if (cli < MAX_T_STAT_COUNTER_ID) {
+
+               val = BAR_TSTRORM_INTMEM +
+                     TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
+               for (i = 0; i < sizeof(struct tstorm_per_client_stats) / 4; i++)
+                       CNIC_WR(dev, val + i * 4, 0);
+       }
 
        /* reset ustorm per client statistics */
-       val = BAR_USTRORM_INTMEM +
-             USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
-       for (i = 0; i < sizeof(struct ustorm_per_client_stats) / 4; i++)
-               CNIC_WR(dev, val + i * 4, 0);
+       if (cli < MAX_U_STAT_COUNTER_ID) {
+               val = BAR_USTRORM_INTMEM +
+                     USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
+               for (i = 0; i < sizeof(struct ustorm_per_client_stats) / 4; i++)
+                       CNIC_WR(dev, val + i * 4, 0);
+       }
 
        cp->rx_cons_ptr =
                &cp->bnx2x_def_status_blk->u_def_status_block.index_values[
index 3c58db5952852ad5319741c7135e452e2ad086a0..23786ee34beded0a9ae6d2c0484ca75965eeab93 100644 (file)
@@ -1181,7 +1181,8 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
                if (netif_msg_drv(priv))
                        printk(KERN_ERR "%s: Could not attach to PHY\n",
                               dev->name);
-               return PTR_ERR(priv->phy);
+               rc = PTR_ERR(priv->phy);
+               goto fail;
        }
 
        if ((rc = register_netdev(dev))) {
index ebdea0891665dbb81fbd6e7894abc4e97b6fd2c4..68a80893dce1daa492c23f6a7e6e0dd290645046 100644 (file)
@@ -1047,15 +1047,14 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
                goto err_register;
 
        /* print bus type/speed/width info */
-       e_info("(PCI%s:%s:%s) ",
-               ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
-               ((hw->bus_speed == e1000_bus_speed_133) ? "133MHz" :
-                (hw->bus_speed == e1000_bus_speed_120) ? "120MHz" :
-                (hw->bus_speed == e1000_bus_speed_100) ? "100MHz" :
-                (hw->bus_speed == e1000_bus_speed_66) ? "66MHz" : "33MHz"),
-               ((hw->bus_width == e1000_bus_width_64) ? "64-bit" : "32-bit"));
-
-       e_info("%pM\n", netdev->dev_addr);
+       e_info("(PCI%s:%dMHz:%d-bit) %pM\n",
+              ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
+              ((hw->bus_speed == e1000_bus_speed_133) ? 133 :
+               (hw->bus_speed == e1000_bus_speed_120) ? 120 :
+               (hw->bus_speed == e1000_bus_speed_100) ? 100 :
+               (hw->bus_speed == e1000_bus_speed_66) ? 66 : 33),
+              ((hw->bus_width == e1000_bus_width_64) ? 64 : 32),
+              netdev->dev_addr);
 
        /* carrier off reporting is important to ethtool even BEFORE open */
        netif_carrier_off(netdev);
index 24507f3b8b1708755e0631d9c28be2fe08f67493..57a7e41da69e91e64d547362d04c7495d907f567 100644 (file)
@@ -2554,7 +2554,7 @@ static void e1000_init_manageability_pt(struct e1000_adapter *adapter)
                        mdef = er32(MDEF(i));
 
                        /* Ignore filters with anything other than IPMI ports */
-                       if (mdef & !(E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664))
+                       if (mdef & ~(E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664))
                                continue;
 
                        /* Enable this decision filter in MANC2H */
index 0630980a27222ce31ab4bb77d8af754d5ddc0c09..0060e422f171bda3c385ef757fce13ee39d0a517 100644 (file)
@@ -40,7 +40,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME       "ehea"
-#define DRV_VERSION    "EHEA_0103"
+#define DRV_VERSION    "EHEA_0105"
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
index f547894ff48fc3a02317548dafe8ec900e5044e2..8b92acb448c2691e7d2ca4de669c61e4a33677e9 100644 (file)
@@ -867,6 +867,7 @@ static int ehea_poll(struct napi_struct *napi, int budget)
                ehea_reset_cq_ep(pr->send_cq);
                ehea_reset_cq_n1(pr->recv_cq);
                ehea_reset_cq_n1(pr->send_cq);
+               rmb();
                cqe = ehea_poll_rq1(pr->qp, &wqe_index);
                cqe_skb = ehea_poll_cq(pr->send_cq);
 
@@ -2859,6 +2860,7 @@ static void ehea_reset_port(struct work_struct *work)
                container_of(work, struct ehea_port, reset_task);
        struct net_device *dev = port->netdev;
 
+       mutex_lock(&dlpar_mem_lock);
        port->resets++;
        mutex_lock(&port->port_lock);
        netif_stop_queue(dev);
@@ -2881,6 +2883,7 @@ static void ehea_reset_port(struct work_struct *work)
        netif_wake_queue(dev);
 out:
        mutex_unlock(&port->port_lock);
+       mutex_unlock(&dlpar_mem_lock);
 }
 
 static void ehea_rereg_mrs(struct work_struct *work)
@@ -3542,10 +3545,7 @@ static int ehea_mem_notifier(struct notifier_block *nb,
        int ret = NOTIFY_BAD;
        struct memory_notify *arg = data;
 
-       if (!mutex_trylock(&dlpar_mem_lock)) {
-               ehea_info("ehea_mem_notifier must not be called parallelized");
-               goto out;
-       }
+       mutex_lock(&dlpar_mem_lock);
 
        switch (action) {
        case MEM_CANCEL_OFFLINE:
@@ -3574,7 +3574,6 @@ static int ehea_mem_notifier(struct notifier_block *nb,
 
 out_unlock:
        mutex_unlock(&dlpar_mem_lock);
-out:
        return ret;
 }
 
index 85f2a2e7030aa2e1962385f9c8e92a04e1aaa29d..45e86d1e5b1b29545371a7a1129fbb99f94cfb40 100644 (file)
@@ -74,7 +74,14 @@ struct enic_msix_entry {
        void *devid;
 };
 
+#define ENIC_SET_APPLIED               (1 << 0)
+#define ENIC_SET_REQUEST               (1 << 1)
+#define ENIC_SET_NAME                  (1 << 2)
+#define ENIC_SET_INSTANCE              (1 << 3)
+#define ENIC_SET_HOST                  (1 << 4)
+
 struct enic_port_profile {
+       u32 set;
        u8 request;
        char name[PORT_PROFILE_MAX];
        u8 instance_uuid[PORT_UUID_MAX];
index 6586b5c7e4b617066bea1d652f175b51b5f9d6f4..bc7d6b96de3dec39ca96b369a6656ec22ab04a12 100644 (file)
@@ -1029,8 +1029,7 @@ static int enic_dev_init_done(struct enic *enic, int *done, int *error)
        return err;
 }
 
-static int enic_set_port_profile(struct enic *enic, u8 request, u8 *mac,
-       char *name, u8 *instance_uuid, u8 *host_uuid)
+static int enic_set_port_profile(struct enic *enic, u8 *mac)
 {
        struct vic_provinfo *vp;
        u8 oui[3] = VIC_PROVINFO_CISCO_OUI;
@@ -1040,97 +1039,112 @@ static int enic_set_port_profile(struct enic *enic, u8 request, u8 *mac,
                "%02X%02X-%02X%02X%02X%02X%0X%02X";
        int err;
 
-       if (!name)
-               return -EINVAL;
+       err = enic_vnic_dev_deinit(enic);
+       if (err)
+               return err;
 
-       if (!is_valid_ether_addr(mac))
-               return -EADDRNOTAVAIL;
+       switch (enic->pp.request) {
 
-       vp = vic_provinfo_alloc(GFP_KERNEL, oui, VIC_PROVINFO_LINUX_TYPE);
-       if (!vp)
-               return -ENOMEM;
+       case PORT_REQUEST_ASSOCIATE:
 
-       vic_provinfo_add_tlv(vp,
-               VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR,
-               strlen(name) + 1, name);
-
-       vic_provinfo_add_tlv(vp,
-               VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR,
-               ETH_ALEN, mac);
-
-       if (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[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 (!(enic->pp.set & ENIC_SET_NAME) || !strlen(enic->pp.name))
+                       return -EINVAL;
 
-       if (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[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);
-       }
+               if (!is_valid_ether_addr(mac))
+                       return -EADDRNOTAVAIL;
 
-       err = enic_vnic_dev_deinit(enic);
-       if (err)
-               goto err_out;
+               vp = vic_provinfo_alloc(GFP_KERNEL, oui,
+                       VIC_PROVINFO_LINUX_TYPE);
+               if (!vp)
+                       return -ENOMEM;
 
-       memset(&enic->pp, 0, sizeof(enic->pp));
+               vic_provinfo_add_tlv(vp,
+                       VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR,
+                       strlen(enic->pp.name) + 1, enic->pp.name);
 
-       err = enic_dev_init_prov(enic, vp);
-       if (err)
-               goto err_out;
+               vic_provinfo_add_tlv(vp,
+                       VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR,
+                       ETH_ALEN, mac);
+
+               if (enic->pp.set & ENIC_SET_INSTANCE) {
+                       uuid = enic->pp.instance_uuid;
+                       sprintf(uuid_str, uuid_fmt,
+                               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);
+               }
 
-       enic->pp.request = request;
-       memcpy(enic->pp.name, name, PORT_PROFILE_MAX);
-       if (instance_uuid)
-               memcpy(enic->pp.instance_uuid,
-                       instance_uuid, PORT_UUID_MAX);
-       if (host_uuid)
-               memcpy(enic->pp.host_uuid,
-                       host_uuid, PORT_UUID_MAX);
+               if (enic->pp.set & ENIC_SET_HOST) {
+                       uuid = enic->pp.host_uuid;
+                       sprintf(uuid_str, uuid_fmt,
+                               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);
+               }
 
-err_out:
-       vic_provinfo_free(vp);
+               err = enic_dev_init_prov(enic, vp);
+               vic_provinfo_free(vp);
+               if (err)
+                       return err;
+               break;
 
-       return err;
-}
+       case PORT_REQUEST_DISASSOCIATE:
+               break;
 
-static int enic_unset_port_profile(struct enic *enic)
-{
-       memset(&enic->pp, 0, sizeof(enic->pp));
-       return enic_vnic_dev_deinit(enic);
+       default:
+               return -EINVAL;
+       }
+
+       enic->pp.set |= ENIC_SET_APPLIED;
+       return 0;
 }
 
 static int enic_set_vf_port(struct net_device *netdev, int vf,
        struct nlattr *port[])
 {
        struct enic *enic = netdev_priv(netdev);
-       char *name = NULL;
-       u8 *instance_uuid = NULL;
-       u8 *host_uuid = NULL;
-       u8 request = PORT_REQUEST_DISASSOCIATE;
+
+       memset(&enic->pp, 0, sizeof(enic->pp));
+
+       if (port[IFLA_PORT_REQUEST]) {
+               enic->pp.set |= ENIC_SET_REQUEST;
+               enic->pp.request = nla_get_u8(port[IFLA_PORT_REQUEST]);
+       }
+
+       if (port[IFLA_PORT_PROFILE]) {
+               enic->pp.set |= ENIC_SET_NAME;
+               memcpy(enic->pp.name, nla_data(port[IFLA_PORT_PROFILE]),
+                       PORT_PROFILE_MAX);
+       }
+
+       if (port[IFLA_PORT_INSTANCE_UUID]) {
+               enic->pp.set |= ENIC_SET_INSTANCE;
+               memcpy(enic->pp.instance_uuid,
+                       nla_data(port[IFLA_PORT_INSTANCE_UUID]), PORT_UUID_MAX);
+       }
+
+       if (port[IFLA_PORT_HOST_UUID]) {
+               enic->pp.set |= ENIC_SET_HOST;
+               memcpy(enic->pp.host_uuid,
+                       nla_data(port[IFLA_PORT_HOST_UUID]), PORT_UUID_MAX);
+       }
 
        /* don't support VFs, yet */
        if (vf != PORT_SELF_VF)
                return -EOPNOTSUPP;
 
-       if (port[IFLA_PORT_REQUEST])
-               request = nla_get_u8(port[IFLA_PORT_REQUEST]);
+       if (!(enic->pp.set & ENIC_SET_REQUEST))
+               return -EOPNOTSUPP;
 
-       switch (request) {
-       case PORT_REQUEST_ASSOCIATE:
+       if (enic->pp.request == PORT_REQUEST_ASSOCIATE) {
 
                /* If the interface mac addr hasn't been assigned,
                 * assign a random mac addr before setting port-
@@ -1139,30 +1153,9 @@ static int enic_set_vf_port(struct net_device *netdev, int vf,
 
                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]);
-
-               if (port[IFLA_PORT_INSTANCE_UUID])
-                       instance_uuid =
-                               nla_data(port[IFLA_PORT_INSTANCE_UUID]);
-
-               if (port[IFLA_PORT_HOST_UUID])
-                       host_uuid = nla_data(port[IFLA_PORT_HOST_UUID]);
-
-               return enic_set_port_profile(enic, request,
-                       netdev->dev_addr, name,
-                       instance_uuid, host_uuid);
-
-       case PORT_REQUEST_DISASSOCIATE:
-
-               return enic_unset_port_profile(enic);
-
-       default:
-               break;
        }
 
-       return -EOPNOTSUPP;
+       return enic_set_port_profile(enic, netdev->dev_addr);
 }
 
 static int enic_get_vf_port(struct net_device *netdev, int vf,
@@ -1172,14 +1165,12 @@ static int enic_get_vf_port(struct net_device *netdev, int vf,
        int err, error, done;
        u16 response = PORT_PROFILE_RESPONSE_SUCCESS;
 
-       /* don't support VFs, yet */
-       if (vf != PORT_SELF_VF)
-               return -EOPNOTSUPP;
+       if (!(enic->pp.set & ENIC_SET_APPLIED))
+               return -ENODATA;
 
        err = enic_dev_init_done(enic, &done, &error);
-
        if (err)
-               return err;
+               error = err;
 
        switch (error) {
        case ERR_SUCCESS:
@@ -1202,12 +1193,15 @@ static int enic_get_vf_port(struct net_device *netdev, int vf,
 
        NLA_PUT_U16(skb, IFLA_PORT_REQUEST, enic->pp.request);
        NLA_PUT_U16(skb, IFLA_PORT_RESPONSE, response);
-       NLA_PUT(skb, IFLA_PORT_PROFILE, PORT_PROFILE_MAX,
-               enic->pp.name);
-       NLA_PUT(skb, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX,
-               enic->pp.instance_uuid);
-       NLA_PUT(skb, IFLA_PORT_HOST_UUID, PORT_UUID_MAX,
-               enic->pp.host_uuid);
+       if (enic->pp.set & ENIC_SET_NAME)
+               NLA_PUT(skb, IFLA_PORT_PROFILE, PORT_PROFILE_MAX,
+                       enic->pp.name);
+       if (enic->pp.set & ENIC_SET_INSTANCE)
+               NLA_PUT(skb, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX,
+                       enic->pp.instance_uuid);
+       if (enic->pp.set & ENIC_SET_HOST)
+               NLA_PUT(skb, IFLA_PORT_HOST_UUID, PORT_UUID_MAX,
+                       enic->pp.host_uuid);
 
        return 0;
 
index 2b3e16db5c82f2a75763f128854b06a3d2447d24..e0d33281ec980b6013dea7c1632b19358af7d30c 100644 (file)
@@ -709,7 +709,7 @@ int vnic_dev_init_prov(struct vnic_dev *vdev, u8 *buf, u32 len)
 {
        u64 a0, a1 = len;
        int wait = 1000;
-       u64 prov_pa;
+       dma_addr_t prov_pa;
        void *prov_buf;
        int ret;
 
index 6838dfc9ef23a4549c69144c7d87db589e1c7928..4c274657283c36ad2157d5874447e3c434483869 100644 (file)
@@ -87,6 +87,7 @@ static int rx_copybreak;
 #include <linux/bitops.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
+#include <asm/byteorder.h>
 
 /* These identify the driver base version and may not be removed. */
 static char version[] __devinitdata =
@@ -230,7 +231,7 @@ static const u16 media2miictl[16] = {
  * The EPIC100 Rx and Tx buffer descriptors.  Note that these
  * really ARE host-endian; it's not a misannotation.  We tell
  * the card to byteswap them internally on big-endian hosts -
- * look for #ifdef CONFIG_BIG_ENDIAN in epic_open().
+ * look for #ifdef __BIG_ENDIAN in epic_open().
  */
 
 struct epic_tx_desc {
@@ -690,7 +691,7 @@ static int epic_open(struct net_device *dev)
                outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
 
        /* Tell the chip to byteswap descriptors on big-endian hosts */
-#ifdef CONFIG_BIG_ENDIAN
+#ifdef __BIG_ENDIAN
        outl(0x4432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
        inl(ioaddr + GENCTL);
        outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
@@ -806,7 +807,7 @@ static void epic_restart(struct net_device *dev)
        for (i = 16; i > 0; i--)
                outl(0x0008, ioaddr + TEST1);
 
-#ifdef CONFIG_BIG_ENDIAN
+#ifdef __BIG_ENDIAN
        outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
 #else
        outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
index ddf7a86cd4661f0cdfa438d7a2a9dae6db68acec..edfff92a6d8ebd8c141b9697b216efccfbbec226 100644 (file)
@@ -1373,10 +1373,9 @@ fec_suspend(struct platform_device *dev, pm_message_t state)
 
        if (ndev) {
                fep = netdev_priv(ndev);
-               if (netif_running(ndev)) {
-                       netif_device_detach(ndev);
-                       fec_stop(ndev);
-               }
+               if (netif_running(ndev))
+                       fec_enet_close(ndev);
+               clk_disable(fep->clk);
        }
        return 0;
 }
@@ -1385,12 +1384,13 @@ static int
 fec_resume(struct platform_device *dev)
 {
        struct net_device *ndev = platform_get_drvdata(dev);
+       struct fec_enet_private *fep;
 
        if (ndev) {
-               if (netif_running(ndev)) {
-                       fec_enet_init(ndev, 0);
-                       netif_device_attach(ndev);
-               }
+               fep = netdev_priv(ndev);
+               clk_enable(fep->clk);
+               if (netif_running(ndev))
+                       fec_enet_open(ndev);
        }
        return 0;
 }
index 5d45084b287d13afa6d24dcfc02d18f56afb0ce1..48e91b6242ce99b8382aeb4d55ec17c3af682cc7 100644 (file)
@@ -504,17 +504,54 @@ static int get_regs_len(struct net_device *dev)
 }
 
 /* Some transmit errors cause the transmitter to shut
- * down.  We now issue a restart transmit.  Since the
- * errors close the BD and update the pointers, the restart
- * _should_ pick up without having to reset any of our
- * pointers either.  Also, To workaround 8260 device erratum
- * CPM37, we must disable and then re-enable the transmitter
- * following a Late Collision, Underrun, or Retry Limit error.
+ * down.  We now issue a restart transmit.
+ * Also, to workaround 8260 device erratum CPM37, we must
+ * disable and then re-enable the transmitterfollowing a
+ * Late Collision, Underrun, or Retry Limit error.
+ * In addition, tbptr may point beyond BDs beyond still marked
+ * as ready due to internal pipelining, so we need to look back
+ * through the BDs and adjust tbptr to point to the last BD
+ * marked as ready.  This may result in some buffers being
+ * retransmitted.
  */
 static void tx_restart(struct net_device *dev)
 {
        struct fs_enet_private *fep = netdev_priv(dev);
        fcc_t __iomem *fccp = fep->fcc.fccp;
+       const struct fs_platform_info *fpi = fep->fpi;
+       fcc_enet_t __iomem *ep = fep->fcc.ep;
+       cbd_t __iomem *curr_tbptr;
+       cbd_t __iomem *recheck_bd;
+       cbd_t __iomem *prev_bd;
+       cbd_t __iomem *last_tx_bd;
+
+       last_tx_bd = fep->tx_bd_base + (fpi->tx_ring * sizeof(cbd_t));
+
+       /* get the current bd held in TBPTR  and scan back from this point */
+       recheck_bd = curr_tbptr = (cbd_t __iomem *)
+               ((R32(ep, fen_genfcc.fcc_tbptr) - fep->ring_mem_addr) +
+               fep->ring_base);
+
+       prev_bd = (recheck_bd == fep->tx_bd_base) ? last_tx_bd : recheck_bd - 1;
+
+       /* Move through the bds in reverse, look for the earliest buffer
+        * that is not ready.  Adjust TBPTR to the following buffer */
+       while ((CBDR_SC(prev_bd) & BD_ENET_TX_READY) != 0) {
+               /* Go back one buffer */
+               recheck_bd = prev_bd;
+
+               /* update the previous buffer */
+               prev_bd = (prev_bd == fep->tx_bd_base) ? last_tx_bd : prev_bd - 1;
+
+               /* We should never see all bds marked as ready, check anyway */
+               if (recheck_bd == curr_tbptr)
+                       break;
+       }
+       /* Now update the TBPTR and dirty flag to the current buffer */
+       W32(ep, fen_genfcc.fcc_tbptr,
+               (uint) (((void *)recheck_bd - fep->ring_base) +
+               fep->ring_mem_addr));
+       fep->dirty_tx = recheck_bd;
 
        C32(fccp, fcc_gfmr, FCC_GFMR_ENT);
        udelay(10);
index 1830f3199cb523080b1a880dd5e834ad9fb8d99a..28b53d1cd4f168701fa4ce41a7c5e0edbaa6f783 100644 (file)
@@ -381,10 +381,14 @@ static void gfar_init_mac(struct net_device *ndev)
        /* Insert receive time stamps into padding alignment bytes */
        if (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) {
                rctrl &= ~RCTRL_PAL_MASK;
-               rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE | RCTRL_PADDING(8);
+               rctrl |= RCTRL_PADDING(8);
                priv->padding = 8;
        }
 
+       /* Enable HW time stamping if requested from user space */
+       if (priv->hwts_rx_en)
+               rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE;
+
        /* keep vlan related bits if it's enabled */
        if (priv->vlgrp) {
                rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT;
@@ -806,12 +810,20 @@ static int gfar_hwtstamp_ioctl(struct net_device *netdev,
 
        switch (config.rx_filter) {
        case HWTSTAMP_FILTER_NONE:
-               priv->hwts_rx_en = 0;
+               if (priv->hwts_rx_en) {
+                       stop_gfar(netdev);
+                       priv->hwts_rx_en = 0;
+                       startup_gfar(netdev);
+               }
                break;
        default:
                if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER))
                        return -ERANGE;
-               priv->hwts_rx_en = 1;
+               if (!priv->hwts_rx_en) {
+                       stop_gfar(netdev);
+                       priv->hwts_rx_en = 1;
+                       startup_gfar(netdev);
+               }
                config.rx_filter = HWTSTAMP_FILTER_ALL;
                break;
        }
@@ -2643,6 +2655,10 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
                dma_unmap_single(&priv->ofdev->dev, bdp->bufPtr,
                                priv->rx_buffer_size, DMA_FROM_DEVICE);
 
+               if (unlikely(!(bdp->status & RXBD_ERR) &&
+                               bdp->length > priv->rx_buffer_size))
+                       bdp->status = RXBD_LARGE;
+
                /* We drop the frame if we failed to allocate a new buffer */
                if (unlikely(!newskb || !(bdp->status & RXBD_LAST) ||
                                 bdp->status & RXBD_ERR)) {
index f37a4c143ddddf985556018dc5e21288e23f3207..3a029d02c2b410405dd37c5e6b1b7e8e4ccb63c9 100644 (file)
@@ -1607,14 +1607,13 @@ static struct of_device_id greth_of_match[] = {
 MODULE_DEVICE_TABLE(of, greth_of_match);
 
 static struct of_platform_driver greth_of_driver = {
-       .name = "grlib-greth",
-       .match_table = greth_of_match,
+       .driver = {
+               .name = "grlib-greth",
+               .owner = THIS_MODULE,
+               .of_match_table = greth_of_match,
+       },
        .probe = greth_of_probe,
        .remove = __devexit_p(greth_of_remove),
-       .driver = {
-                  .owner = THIS_MODULE,
-                  .name = "grlib-greth",
-                  },
 };
 
 static int __init greth_init(void)
index 1159d9138f0577c84643ba3db8b263d995cd683a..9595b1bfb8dd54edab12c60fcf0bace4a19d1d1f 100644 (file)
@@ -1188,6 +1188,7 @@ s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
                IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
        } else {
                hw_dbg(hw, "RAR index %d is out of range.\n", index);
+               return IXGBE_ERR_RAR_INDEX;
        }
 
        return 0;
@@ -1219,6 +1220,7 @@ s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index)
                IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
        } else {
                hw_dbg(hw, "RAR index %d is out of range.\n", index);
+               return IXGBE_ERR_RAR_INDEX;
        }
 
        /* clear VMDq pool/queue selection for this RAR */
index c50a7541ffecf763fb0050de183f4db98f43b1b7..3a93a81872b87153404111152bf5860307815772 100644 (file)
@@ -2077,25 +2077,6 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
        return 0;
 }
 
-/*
- * this function must be called before setting the new value of
- * rx_itr_setting
- */
-static bool ixgbe_reenable_rsc(struct ixgbe_adapter *adapter,
-                               struct ethtool_coalesce *ec)
-{
-       /* check the old value and enable RSC if necessary */
-       if ((adapter->rx_itr_setting == 0) &&
-           (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)) {
-               adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
-               adapter->netdev->features |= NETIF_F_LRO;
-               DPRINTK(PROBE, INFO, "rx-usecs set to %d, re-enabling RSC\n",
-                       ec->rx_coalesce_usecs);
-               return true;
-       }
-       return false;
-}
-
 static int ixgbe_set_coalesce(struct net_device *netdev,
                               struct ethtool_coalesce *ec)
 {
@@ -2124,9 +2105,6 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
                    (1000000/ec->rx_coalesce_usecs < IXGBE_MIN_INT_RATE))
                        return -EINVAL;
 
-               /* check the old value and enable RSC if necessary */
-               need_reset = ixgbe_reenable_rsc(adapter, ec);
-
                /* store the value in ints/second */
                adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs;
 
@@ -2135,9 +2113,6 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
                /* clear the lower bit as its used for dynamic state */
                adapter->rx_itr_setting &= ~1;
        } else if (ec->rx_coalesce_usecs == 1) {
-               /* check the old value and enable RSC if necessary */
-               need_reset = ixgbe_reenable_rsc(adapter, ec);
-
                /* 1 means dynamic mode */
                adapter->rx_eitr_param = 20000;
                adapter->rx_itr_setting = 1;
@@ -2157,10 +2132,11 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
                 */
                if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
                        adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED;
-                       netdev->features &= ~NETIF_F_LRO;
-                       DPRINTK(PROBE, INFO,
-                               "rx-usecs set to 0, disabling RSC\n");
-
+                       if (netdev->features & NETIF_F_LRO) {
+                               netdev->features &= ~NETIF_F_LRO;
+                               DPRINTK(PROBE, INFO, "rx-usecs set to 0, "
+                                       "disabling LRO/RSC\n");
+                       }
                        need_reset = true;
                }
        }
@@ -2255,6 +2231,9 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data)
                        }
                } else if (!adapter->rx_itr_setting) {
                        netdev->features &= ~ETH_FLAG_LRO;
+                       if (data & ETH_FLAG_LRO)
+                               DPRINTK(PROBE, INFO, "rx-usecs set to 0, "
+                                       "LRO/RSC cannot be enabled.\n");
                }
        }
 
index d571d101de08fb4c183af77cb9b64d10904d10a7..7b5d9764f317c3c776712009dde301c27d9c3b99 100644 (file)
@@ -642,7 +642,7 @@ static inline bool ixgbe_tx_xon_state(struct ixgbe_adapter *adapter,
        u32 txoff = IXGBE_TFCS_TXOFF;
 
 #ifdef CONFIG_IXGBE_DCB
-       if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
+       if (adapter->dcb_cfg.pfc_mode_enable) {
                int tc;
                int reg_idx = tx_ring->reg_idx;
                int dcb_i = adapter->ring_feature[RING_F_DCB].indices;
@@ -3684,10 +3684,6 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
        /* signal that we are down to the interrupt handler */
        set_bit(__IXGBE_DOWN, &adapter->state);
 
-       /* power down the optics */
-       if (hw->phy.multispeed_fiber)
-               hw->mac.ops.disable_tx_laser(hw);
-
        /* disable receive for all VFs and wait one second */
        if (adapter->num_vfs) {
                /* ping all the active vfs to let them know we are going down */
@@ -3742,6 +3738,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
                                (IXGBE_READ_REG(hw, IXGBE_DMATXCTL) &
                                 ~IXGBE_DMATXCTL_TE));
 
+       /* power down the optics */
+       if (hw->phy.multispeed_fiber)
+               hw->mac.ops.disable_tx_laser(hw);
+
        /* clear n-tuple filters that are cached */
        ethtool_ntuple_flush(netdev);
 
@@ -4001,7 +4001,7 @@ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
 
 done:
        /* Notify the stack of the (possibly) reduced Tx Queue count. */
-       adapter->netdev->real_num_tx_queues = adapter->num_tx_queues;
+       netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);
 }
 
 static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter,
@@ -5195,7 +5195,6 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake)
                ixgbe_free_all_tx_resources(adapter);
                ixgbe_free_all_rx_resources(adapter);
        }
-       ixgbe_clear_interrupt_scheme(adapter);
 
 #ifdef CONFIG_PM
        retval = pci_save_state(pdev);
@@ -5230,6 +5229,8 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake)
 
        *enable_wake = !!wufc;
 
+       ixgbe_clear_interrupt_scheme(adapter);
+
        ixgbe_release_hw_control(adapter);
 
        pci_disable_device(pdev);
@@ -5282,6 +5283,10 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
        u32 i, missed_rx = 0, mpc, bprc, lxon, lxoff, xon_off_tot;
        u64 non_eop_descs = 0, restart_queue = 0;
 
+       if (test_bit(__IXGBE_DOWN, &adapter->state) ||
+           test_bit(__IXGBE_RESETTING, &adapter->state))
+               return;
+
        if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
                u64 rsc_count = 0;
                u64 rsc_flush = 0;
@@ -6019,7 +6024,6 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter,
 static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb,
                      int queue, u32 tx_flags)
 {
-       /* Right now, we support IPv4 only */
        struct ixgbe_atr_input atr_input;
        struct tcphdr *th;
        struct iphdr *iph = ip_hdr(skb);
@@ -6028,6 +6032,9 @@ static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb,
        u32 src_ipv4_addr, dst_ipv4_addr;
        u8 l4type = 0;
 
+       /* Right now, we support IPv4 only */
+       if (skb->protocol != htons(ETH_P_IP))
+               return;
        /* check if we're UDP or TCP */
        if (iph->protocol == IPPROTO_TCP) {
                th = tcp_hdr(skb);
index 09e1911ff510474ecda600446a51330d057647e3..48325a5beff2054c59b2aa9f6b333bcdf4d3d0c8 100644 (file)
@@ -575,6 +575,8 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
                 * 4    SFP_DA_CORE1 - 82599-specific
                 * 5    SFP_SR/LR_CORE0 - 82599-specific
                 * 6    SFP_SR/LR_CORE1 - 82599-specific
+                * 7    SFP_act_lmt_DA_CORE0 - 82599-specific
+                * 8    SFP_act_lmt_DA_CORE1 - 82599-specific
                 */
                if (hw->mac.type == ixgbe_mac_82598EB) {
                        if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
index 2eb6e151016cac10ca15eadfd9311283361e09b9..cdd1998f18c705348a618098f8e098edda8d7e98 100644 (file)
@@ -2609,6 +2609,7 @@ struct ixgbe_info {
 #define IXGBE_ERR_EEPROM_VERSION                -24
 #define IXGBE_ERR_NO_SPACE                      -25
 #define IXGBE_ERR_OVERTEMP                      -26
+#define IXGBE_ERR_RAR_INDEX                     -27
 #define IXGBE_NOT_IMPLEMENTED                   0x7FFFFFFF
 
 #endif /* _IXGBE_TYPE_H_ */
index 26bf1b76b9977a1510bf3407c34322bed46512ba..c7a9bef4dfb0890001c5243211862def6a4de2a6 100644 (file)
@@ -135,6 +135,7 @@ struct korina_private {
        struct napi_struct napi;
        struct timer_list media_check_timer;
        struct mii_if_info mii_if;
+       struct work_struct restart_task;
        struct net_device *dev;
        int phy_addr;
 };
@@ -375,7 +376,7 @@ static int korina_rx(struct net_device *dev, int limit)
                if (devcs & ETH_RX_LE)
                        dev->stats.rx_length_errors++;
                if (devcs & ETH_RX_OVR)
-                       dev->stats.rx_over_errors++;
+                       dev->stats.rx_fifo_errors++;
                if (devcs & ETH_RX_CV)
                        dev->stats.rx_frame_errors++;
                if (devcs & ETH_RX_CES)
@@ -764,10 +765,9 @@ static int korina_alloc_ring(struct net_device *dev)
 
        /* Initialize the receive descriptors */
        for (i = 0; i < KORINA_NUM_RDS; i++) {
-               skb = dev_alloc_skb(KORINA_RBSIZE + 2);
+               skb = netdev_alloc_skb_ip_align(dev, KORINA_RBSIZE);
                if (!skb)
                        return -ENOMEM;
-               skb_reserve(skb, 2);
                lp->rx_skb[i] = skb;
                lp->rd_ring[i].control = DMA_DESC_IOD |
                                DMA_COUNT(KORINA_RBSIZE);
@@ -890,12 +890,12 @@ static int korina_init(struct net_device *dev)
 
 /*
  * Restart the RC32434 ethernet controller.
- * FIXME: check the return status where we call it
  */
-static int korina_restart(struct net_device *dev)
+static void korina_restart_task(struct work_struct *work)
 {
-       struct korina_private *lp = netdev_priv(dev);
-       int ret;
+       struct korina_private *lp = container_of(work,
+                       struct korina_private, restart_task);
+       struct net_device *dev = lp->dev;
 
        /*
         * Disable interrupts
@@ -916,10 +916,9 @@ static int korina_restart(struct net_device *dev)
 
        napi_disable(&lp->napi);
 
-       ret = korina_init(dev);
-       if (ret < 0) {
+       if (korina_init(dev) < 0) {
                printk(KERN_ERR "%s: cannot restart device\n", dev->name);
-               return ret;
+               return;
        }
        korina_multicast_list(dev);
 
@@ -927,8 +926,6 @@ static int korina_restart(struct net_device *dev)
        enable_irq(lp->ovr_irq);
        enable_irq(lp->tx_irq);
        enable_irq(lp->rx_irq);
-
-       return ret;
 }
 
 static void korina_clear_and_restart(struct net_device *dev, u32 value)
@@ -937,7 +934,7 @@ static void korina_clear_and_restart(struct net_device *dev, u32 value)
 
        netif_stop_queue(dev);
        writel(value, &lp->eth_regs->ethintfc);
-       korina_restart(dev);
+       schedule_work(&lp->restart_task);
 }
 
 /* Ethernet Tx Underflow interrupt */
@@ -962,11 +959,8 @@ static irqreturn_t korina_und_interrupt(int irq, void *dev_id)
 static void korina_tx_timeout(struct net_device *dev)
 {
        struct korina_private *lp = netdev_priv(dev);
-       unsigned long flags;
 
-       spin_lock_irqsave(&lp->lock, flags);
-       korina_restart(dev);
-       spin_unlock_irqrestore(&lp->lock, flags);
+       schedule_work(&lp->restart_task);
 }
 
 /* Ethernet Rx Overflow interrupt */
@@ -1086,6 +1080,8 @@ static int korina_close(struct net_device *dev)
 
        napi_disable(&lp->napi);
 
+       cancel_work_sync(&lp->restart_task);
+
        free_irq(lp->rx_irq, dev);
        free_irq(lp->tx_irq, dev);
        free_irq(lp->ovr_irq, dev);
@@ -1198,6 +1194,8 @@ static int korina_probe(struct platform_device *pdev)
        }
        setup_timer(&lp->media_check_timer, korina_poll_media, (unsigned long) dev);
 
+       INIT_WORK(&lp->restart_task, korina_restart_task);
+
        printk(KERN_INFO "%s: " DRV_NAME "-" DRV_VERSION " " DRV_RELDATE "\n",
                        dev->name);
 out:
index c80ca64277b224934bc57e1b541c7cef7193a9ff..7805bbf1d53a6ceeaf02f8c68f4e3740e2c4939d 100644 (file)
@@ -4854,7 +4854,7 @@ static inline void copy_old_skb(struct sk_buff *old, struct sk_buff *skb)
  *
  * Return 0 if successful; otherwise an error code indicating failure.
  */
-static int netdev_tx(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t netdev_tx(struct sk_buff *skb, struct net_device *dev)
 {
        struct dev_priv *priv = netdev_priv(dev);
        struct dev_info *hw_priv = priv->adapter;
@@ -6863,6 +6863,7 @@ static const struct net_device_ops netdev_ops = {
        .ndo_tx_timeout         = netdev_tx_timeout,
        .ndo_change_mtu         = netdev_change_mtu,
        .ndo_set_mac_address    = netdev_set_mac_address,
+       .ndo_validate_addr      = eth_validate_addr,
        .ndo_do_ioctl           = netdev_ioctl,
        .ndo_set_rx_mode        = netdev_set_rx_mode,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index ce5d6e9092182a43d2f0660e68667edf44bfae3b..c27f4291b350422978ab9fbf55bd6318ec0953ae 100644 (file)
@@ -1343,7 +1343,7 @@ static void set_multicast_list(struct net_device *dev)
        DEB(DEB_MULTI,
            printk(KERN_DEBUG
                   "%s: set multicast list, %d entries, promisc %s, allmulti %s\n",
-                  dev->name, dev->mc_count,
+                  dev->name, netdev_mc_count(dev),
                   dev->flags & IFF_PROMISC ? "ON" : "OFF",
                   dev->flags & IFF_ALLMULTI ? "ON" : "OFF"));
 
index 8e9704f5c12213390923cf77005df3dc63b88dd5..869f0ea43a5bbc820ae71fca9ffcb21ba6315119 100644 (file)
@@ -247,7 +247,7 @@ static const struct net_device_ops mipsnet_netdev_ops = {
        .ndo_set_mac_address    = eth_mac_addr,
 };
 
-static int __init mipsnet_probe(struct platform_device *dev)
+static int __devinit mipsnet_probe(struct platform_device *dev)
 {
        struct net_device *netdev;
        int err;
index e345ec8cb473cda0d3454d5f2711b08c55fe8bdf..73bb8ea6f54a46a3c7c9c9246753a497b452d035 100644 (file)
@@ -289,6 +289,7 @@ struct mv643xx_eth_shared_private {
        unsigned int t_clk;
        int extended_rx_coal_limit;
        int tx_bw_control;
+       int tx_csum_limit;
 };
 
 #define TX_BW_CONTROL_ABSENT           0
@@ -776,13 +777,16 @@ static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb)
        l4i_chk = 0;
 
        if (skb->ip_summed == CHECKSUM_PARTIAL) {
+               int hdr_len;
                int tag_bytes;
 
                BUG_ON(skb->protocol != htons(ETH_P_IP) &&
                       skb->protocol != htons(ETH_P_8021Q));
 
-               tag_bytes = (void *)ip_hdr(skb) - (void *)skb->data - ETH_HLEN;
-               if (unlikely(tag_bytes & ~12)) {
+               hdr_len = (void *)ip_hdr(skb) - (void *)skb->data;
+               tag_bytes = hdr_len - ETH_HLEN;
+               if (skb->len - hdr_len > mp->shared->tx_csum_limit ||
+                   unlikely(tag_bytes & ~12)) {
                        if (skb_checksum_help(skb) == 0)
                                goto no_csum;
                        kfree_skb(skb);
@@ -2666,6 +2670,7 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
         * Detect hardware parameters.
         */
        msp->t_clk = (pd != NULL && pd->t_clk != 0) ? pd->t_clk : 133000000;
+       msp->tx_csum_limit = pd->tx_csum_limit ? pd->tx_csum_limit : 9 * 1024;
        infer_hw_params(msp);
 
        platform_set_drvdata(pdev, msp);
index f26e54716c886569f9e30d9a8a5c34d6056b58e6..3a41b6a84a68636a61fd85fd233a17a4c0ce3cd6 100644 (file)
@@ -629,7 +629,8 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
        if (addr == NULL) {
                dev_err(&pdev->dev, "%s: failed to allocate tx desc ring\n",
                                netdev->name);
-               return -ENOMEM;
+               err = -ENOMEM;
+               goto err_out_free;
        }
 
        tx_ring->desc_head = (struct cmd_desc_type0 *)addr;
index 5c496f8d7c497f16c5a17fe7398794efdca550b3..29d7b93d0493be12e4a5def185282371b5cd400d 100644 (file)
@@ -1159,9 +1159,6 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong off)
 
        window = CRB_HI(off);
 
-       if (adapter->ahw.crb_win == window)
-               return;
-
        writel(window, addr);
        if (readl(addr) != window) {
                if (printk_ratelimit())
@@ -1169,7 +1166,6 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong off)
                                "failed to set CRB window to %d off 0x%lx\n",
                                window, off);
        }
-       adapter->ahw.crb_win = window;
 }
 
 static void __iomem *
index 045a7c8f5bdf8e08fd4b317a96f0917023f238d3..c865dda2adf15f8b59a579640d416099e9fabc0c 100644 (file)
@@ -218,7 +218,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
        if (cmd_buf_arr == NULL) {
                dev_err(&pdev->dev, "%s: failed to allocate cmd buffer ring\n",
                       netdev->name);
-               return -ENOMEM;
+               goto err_out;
        }
        memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
        tx_ring->cmd_buf_arr = cmd_buf_arr;
@@ -230,7 +230,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
        if (rds_ring == NULL) {
                dev_err(&pdev->dev, "%s: failed to allocate rds ring struct\n",
                       netdev->name);
-               return -ENOMEM;
+               goto err_out;
        }
        recv_ctx->rds_rings = rds_ring;
 
@@ -1805,9 +1805,10 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
        netxen_ctx_msg msg = 0;
        struct list_head *head;
 
+       spin_lock(&rds_ring->lock);
+
        producer = rds_ring->producer;
 
-       spin_lock(&rds_ring->lock);
        head = &rds_ring->free_list;
        while (!list_empty(head)) {
 
@@ -1829,7 +1830,6 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
 
                producer = get_next_index(producer, rds_ring->num_desc);
        }
-       spin_unlock(&rds_ring->lock);
 
        if (count) {
                rds_ring->producer = producer;
@@ -1853,6 +1853,8 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
                                        NETXEN_RCV_PRODUCER_OFFSET), msg);
                }
        }
+
+       spin_unlock(&rds_ring->lock);
 }
 
 static void
@@ -1864,10 +1866,11 @@ netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
        int producer, count = 0;
        struct list_head *head;
 
-       producer = rds_ring->producer;
        if (!spin_trylock(&rds_ring->lock))
                return;
 
+       producer = rds_ring->producer;
+
        head = &rds_ring->free_list;
        while (!list_empty(head)) {
 
index 6f77a768ba880b532dfa85521e1883a460a4bf9d..bfdef72c5d5ea6371b2fc634c9e2a8476d13fa33 100644 (file)
@@ -1727,6 +1727,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),
        PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
        PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
        PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "cis/DP83903.cis"),
index 7b6fe89f9db0aa4c3f5373a25465efaf8d658ad3..307cd1721e91271bb1b3762868f9dbcb6400d218 100644 (file)
@@ -322,6 +322,7 @@ static int smc91c92_probe(struct pcmcia_device *link)
        return -ENOMEM;
     smc = netdev_priv(dev);
     smc->p_dev = link;
+    link->priv = dev;
 
     spin_lock_init(&smc->lock);
     link->io.NumPorts1 = 16;
@@ -1504,12 +1505,20 @@ irq_done:
        writeb(cor & ~COR_IREQ_ENA, smc->base + MOT_LAN + CISREG_COR);
        writeb(cor, smc->base + MOT_LAN + CISREG_COR);
     }
-#ifdef DOES_NOT_WORK
-    if (smc->base != NULL) { /* Megahertz MFC's */
-       readb(smc->base+MEGAHERTZ_ISR);
-       readb(smc->base+MEGAHERTZ_ISR);
+
+    if ((smc->base != NULL) &&  /* Megahertz MFC's */
+       (smc->manfid == MANFID_MEGAHERTZ) &&
+       (smc->cardid == PRODID_MEGAHERTZ_EM3288)) {
+
+       u_char tmp;
+       tmp = readb(smc->base+MEGAHERTZ_ISR);
+       tmp = readb(smc->base+MEGAHERTZ_ISR);
+
+       /* Retrigger interrupt if needed */
+       writeb(tmp, smc->base + MEGAHERTZ_ISR);
+       writeb(tmp, smc->base + MEGAHERTZ_ISR);
     }
-#endif
+
     spin_unlock(&smc->lock);
     return IRQ_RETVAL(handled);
 }
index 8ee929b796d848e5440271f92b103ff32f5c9c8d..29c39ff85de56a0012ac8be5a50508aeab56e784 100644 (file)
@@ -53,6 +53,9 @@
 
 #define MII_LXT971_ISR         19  /* Interrupt Status Register */
 
+/* register definitions for the 973 */
+#define MII_LXT973_PCR 16 /* Port Configuration Register */
+#define PCR_FIBER_SELECT 1
 
 MODULE_DESCRIPTION("Intel LXT PHY driver");
 MODULE_AUTHOR("Andy Fleming");
@@ -119,6 +122,33 @@ static int lxt971_config_intr(struct phy_device *phydev)
        return err;
 }
 
+static int lxt973_probe(struct phy_device *phydev)
+{
+       int val = phy_read(phydev, MII_LXT973_PCR);
+
+       if (val & PCR_FIBER_SELECT) {
+               /*
+                * If fiber is selected, then the only correct setting
+                * is 100Mbps, full duplex, and auto negotiation off.
+                */
+               val = phy_read(phydev, MII_BMCR);
+               val |= (BMCR_SPEED100 | BMCR_FULLDPLX);
+               val &= ~BMCR_ANENABLE;
+               phy_write(phydev, MII_BMCR, val);
+               /* Remember that the port is in fiber mode. */
+               phydev->priv = lxt973_probe;
+       } else {
+               phydev->priv = NULL;
+       }
+       return 0;
+}
+
+static int lxt973_config_aneg(struct phy_device *phydev)
+{
+       /* Do nothing if port is in fiber mode. */
+       return phydev->priv ? 0 : genphy_config_aneg(phydev);
+}
+
 static struct phy_driver lxt970_driver = {
        .phy_id         = 0x78100000,
        .name           = "LXT970",
@@ -146,6 +176,18 @@ static struct phy_driver lxt971_driver = {
        .driver         = { .owner = THIS_MODULE,},
 };
 
+static struct phy_driver lxt973_driver = {
+       .phy_id         = 0x00137a10,
+       .name           = "LXT973",
+       .phy_id_mask    = 0xfffffff0,
+       .features       = PHY_BASIC_FEATURES,
+       .flags          = 0,
+       .probe          = lxt973_probe,
+       .config_aneg    = lxt973_config_aneg,
+       .read_status    = genphy_read_status,
+       .driver         = { .owner = THIS_MODULE,},
+};
+
 static int __init lxt_init(void)
 {
        int ret;
@@ -157,9 +199,15 @@ static int __init lxt_init(void)
        ret = phy_driver_register(&lxt971_driver);
        if (ret)
                goto err2;
+
+       ret = phy_driver_register(&lxt973_driver);
+       if (ret)
+               goto err3;
        return 0;
 
- err2: 
+ err3:
+       phy_driver_unregister(&lxt971_driver);
+ err2:
        phy_driver_unregister(&lxt970_driver);
  err1:
        return ret;
@@ -169,6 +217,7 @@ static void __exit lxt_exit(void)
 {
        phy_driver_unregister(&lxt970_driver);
        phy_driver_unregister(&lxt971_driver);
+       phy_driver_unregister(&lxt973_driver);
 }
 
 module_init(lxt_init);
@@ -177,6 +226,7 @@ module_exit(lxt_exit);
 static struct mdio_device_id lxt_tbl[] = {
        { 0x78100000, 0xfffffff0 },
        { 0x001378e0, 0xfffffff0 },
+       { 0x00137a10, 0xfffffff0 },
        { }
 };
 
index c5f8eb102bf76de12c86d2665b19b1c7fcb8d8b0..1b2c29150202080e75c2e9732b0150c204ed9161 100644 (file)
@@ -1422,7 +1422,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
                flen = len;
                if (nfree > 0) {
                        if (pch->speed == 0) {
-                               flen = totlen/nfree;
+                               flen = len/nfree;
                                if (nbigger > 0) {
                                        flen++;
                                        nbigger--;
index fa4b24c49f42875bfad43015a9db6ab089b2add8..d10bcefc0e45442aae6c468b622d9c9651249e30 100644 (file)
@@ -4611,8 +4611,7 @@ static void ql_timer(unsigned long data)
                return;
        }
 
-       qdev->timer.expires = jiffies + (5*HZ);
-       add_timer(&qdev->timer);
+       mod_timer(&qdev->timer, jiffies + (5*HZ));
 }
 
 static int __devinit qlge_probe(struct pci_dev *pdev,
@@ -4713,6 +4712,8 @@ static void ql_eeh_close(struct net_device *ndev)
                netif_stop_queue(ndev);
        }
 
+       /* Disabling the timer */
+       del_timer_sync(&qdev->timer);
        if (test_bit(QL_ADAPTER_UP, &qdev->flags))
                cancel_delayed_work_sync(&qdev->asic_reset_work);
        cancel_delayed_work_sync(&qdev->mpi_reset_work);
@@ -4808,8 +4809,7 @@ static void qlge_io_resume(struct pci_dev *pdev)
                netif_err(qdev, ifup, qdev->ndev,
                          "Device was not running prior to EEH.\n");
        }
-       qdev->timer.expires = jiffies + (5*HZ);
-       add_timer(&qdev->timer);
+       mod_timer(&qdev->timer, jiffies + (5*HZ));
        netif_device_attach(ndev);
 }
 
@@ -4871,8 +4871,7 @@ static int qlge_resume(struct pci_dev *pdev)
                        return err;
        }
 
-       qdev->timer.expires = jiffies + (5*HZ);
-       add_timer(&qdev->timer);
+       mod_timer(&qdev->timer, jiffies + (5*HZ));
        netif_device_attach(ndev);
 
        return 0;
index 217e709bda3ede440478bf2eb73c5646dd96e903..96b6cfbf0a3a682b14216fa23a9e737a48973aaa 100644 (file)
@@ -559,6 +559,11 @@ static void mdio_write(void __iomem *ioaddr, int reg_addr, int value)
                        break;
                udelay(25);
        }
+       /*
+        * According to hardware specs a 20us delay is required after write
+        * complete indication, but before sending next command.
+        */
+       udelay(20);
 }
 
 static int mdio_read(void __iomem *ioaddr, int reg_addr)
@@ -578,6 +583,12 @@ static int mdio_read(void __iomem *ioaddr, int reg_addr)
                }
                udelay(25);
        }
+       /*
+        * According to hardware specs a 20us delay is required after read
+        * complete indication, but before sending next command.
+        */
+       udelay(20);
+
        return value;
 }
 
index 2e6fd89f2a72d722555357bf46595754f6426e38..4762c91cb587f03c19eddd58abef2ea449a2e941 100644 (file)
@@ -830,7 +830,7 @@ static inline const char *efx_dev_name(struct efx_nic *efx)
 
 static inline unsigned int efx_port_num(struct efx_nic *efx)
 {
-       return PCI_FUNC(efx->pci_dev->devfn);
+       return efx->net_dev->dev_id;
 }
 
 /**
index 727b4228e0819bfe336e38ed6504bd8c2d852edc..f2b1e6180753536336921b90f53f62c8675fda72 100644 (file)
@@ -206,6 +206,7 @@ static int siena_probe_nic(struct efx_nic *efx)
 {
        struct siena_nic_data *nic_data;
        bool already_attached = 0;
+       efx_oword_t reg;
        int rc;
 
        /* Allocate storage for hardware specific data */
@@ -220,6 +221,9 @@ static int siena_probe_nic(struct efx_nic *efx)
                goto fail1;
        }
 
+       efx_reado(efx, &reg, FR_AZ_CS_DEBUG);
+       efx->net_dev->dev_id = EFX_OWORD_FIELD(reg, FRF_CZ_CS_PORT_NUM) - 1;
+
        efx_mcdi_init(efx);
 
        /* Recover from a failed assertion before probing */
index 2111c7bbf57831209b689871ceea4cb48a82de87..7985165e84fc4ed6ca6ce5fceb8e60d54dca0b5d 100644 (file)
@@ -717,11 +717,24 @@ static void sky2_phy_power_down(struct sky2_hw *hw, unsigned port)
        sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
 }
 
+/* Enable Rx/Tx */
+static void sky2_enable_rx_tx(struct sky2_port *sky2)
+{
+       struct sky2_hw *hw = sky2->hw;
+       unsigned port = sky2->port;
+       u16 reg;
+
+       reg = gma_read16(hw, port, GM_GP_CTRL);
+       reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
+       gma_write16(hw, port, GM_GP_CTRL, reg);
+}
+
 /* Force a renegotiation */
 static void sky2_phy_reinit(struct sky2_port *sky2)
 {
        spin_lock_bh(&sky2->phy_lock);
        sky2_phy_init(sky2->hw, sky2->port);
+       sky2_enable_rx_tx(sky2);
        spin_unlock_bh(&sky2->phy_lock);
 }
 
@@ -2040,7 +2053,6 @@ static void sky2_link_up(struct sky2_port *sky2)
 {
        struct sky2_hw *hw = sky2->hw;
        unsigned port = sky2->port;
-       u16 reg;
        static const char *fc_name[] = {
                [FC_NONE]       = "none",
                [FC_TX]         = "tx",
@@ -2048,10 +2060,7 @@ static void sky2_link_up(struct sky2_port *sky2)
                [FC_BOTH]       = "both",
        };
 
-       /* enable Rx/Tx */
-       reg = gma_read16(hw, port, GM_GP_CTRL);
-       reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
-       gma_write16(hw, port, GM_GP_CTRL, reg);
+       sky2_enable_rx_tx(sky2);
 
        gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
 
index 20ab161923253835b7ee760f8fc027bdcc8aa82c..737df6032bbc1d4bd9635b78210a52bcfa7efea2 100644 (file)
@@ -646,7 +646,7 @@ static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd)
                error = copy_from_user(data, ifr->ifr_data, sizeof(data));
                if (error) {
                        pr_err("cant copy from user\n");
-                       RET(error);
+                       RET(-EFAULT);
                }
                DBG("%d 0x%x 0x%x\n", data[0], data[1], data[2]);
        }
@@ -665,7 +665,7 @@ static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd)
                    data[2]);
                error = copy_to_user(ifr->ifr_data, data, sizeof(data));
                if (error)
-                       RET(error);
+                       RET(-EFAULT);
                break;
 
        case BDX_OP_WRITE:
index 4a34833b85ddad284c1f19efff1bf9d23ed7f7e1..807470e156affad7d05529ed7ffb0d29d0973c48 100644 (file)
@@ -3215,6 +3215,8 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit
                                           __func__, __LINE__, (u32) skb);
                        if (skb) {
                                skb->data = skb->head + NET_SKB_PAD;
+                               skb->len = 0;
+                               skb_reset_tail_pointer(skb);
                                __skb_queue_head(&ugeth->rx_recycle, skb);
                        }
 
index 1f802e90474c3ccd342a70fb8b7352cadedf6bcd..9516f382a6baf76dfdafe63afdd3b22380a2595f 100644 (file)
@@ -344,7 +344,7 @@ static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                        return 2;
                }
 
-               if (size > ETH_FRAME_LEN) {
+               if (size > dev->net->mtu + ETH_HLEN) {
                        netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n",
                                   size);
                        return 0;
index 0a3c41faea9c2118dd28f6c558c939002c34d135..4dd23513c5af1d661e23498740fd9f20841426e0 100644 (file)
@@ -1334,7 +1334,6 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp)
        /* check for port already opened, if not set the termios */
        serial->open_count++;
        if (serial->open_count == 1) {
-               tty->low_latency = 1;
                serial->rx_state = RX_IDLE;
                /* Force default termio settings */
                _hso_serial_set_termios(tty, NULL);
index 28d3ee175e7bbffe697e00f0019c15636eeb6050..dd8a4adf48cadf3d1c85507dc9c71c9d9c316004 100644 (file)
@@ -104,10 +104,8 @@ static void rndis_msg_indicate(struct usbnet *dev, struct rndis_indicate *msg,
 int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen)
 {
        struct cdc_state        *info = (void *) &dev->data;
-       struct usb_cdc_notification notification;
        int                     master_ifnum;
        int                     retval;
-       int                     partial;
        unsigned                count;
        __le32                  rsp;
        u32                     xid = 0, msg_len, request_id;
@@ -135,17 +133,13 @@ int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen)
        if (unlikely(retval < 0 || xid == 0))
                return retval;
 
-       /* Some devices don't respond on the control channel until
-        * polled on the status channel, so do that first. */
-       retval = usb_interrupt_msg(
-               dev->udev,
-               usb_rcvintpipe(dev->udev, dev->status->desc.bEndpointAddress),
-               &notification, sizeof(notification), &partial,
-               RNDIS_CONTROL_TIMEOUT_MS);
-       if (unlikely(retval < 0))
-               return retval;
+       // FIXME Seems like some devices discard responses when
+       // we time out and cancel our "get response" requests...
+       // so, this is fragile.  Probably need to poll for status.
 
-       /* Poll the control channel; the request probably completed immediately */
+       /* ignore status endpoint, just poll the control channel;
+        * the request probably completed immediately
+        */
        rsp = buf->msg_type | RNDIS_MSG_COMPLETION;
        for (count = 0; count < 10; count++) {
                memset(buf, 0, CONTROL_BUFFER_SIZE);
index a95c73de5824c67f7bd3ca471a4e8697c16ffd34..81c76ada8e56c25259f9429203ae3f2f6a81ba50 100644 (file)
@@ -1293,6 +1293,9 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
                goto out;
        }
 
+       /* netdev_printk() needs this so do it as early as possible */
+       SET_NETDEV_DEV(net, &udev->dev);
+
        dev = netdev_priv(net);
        dev->udev = xdev;
        dev->intf = udev;
@@ -1377,8 +1380,6 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
                dev->rx_urb_size = dev->hard_mtu;
        dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1);
 
-       SET_NETDEV_DEV(net, &udev->dev);
-
        if ((dev->driver_info->flags & FLAG_WLAN) != 0)
                SET_NETDEV_DEVTYPE(net, &wlan_type);
        if ((dev->driver_info->flags & FLAG_WWAN) != 0)
index 78eb3190b9b1343bee9e1cd786090c395ebd0877..1edb7a61983c05660aaec2624e596159ab2cd5c9 100644 (file)
@@ -340,7 +340,7 @@ static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp)
 
        skb_to_sgvec(skb, vi->rx_sg + 1, 0, skb->len);
 
-       err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, 2, skb);
+       err = virtqueue_add_buf_gfp(vi->rvq, vi->rx_sg, 0, 2, skb, gfp);
        if (err < 0)
                dev_kfree_skb(skb);
 
@@ -385,8 +385,8 @@ static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp)
 
        /* chain first in list head */
        first->private = (unsigned long)list;
-       err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, MAX_SKB_FRAGS + 2,
-                                      first);
+       err = virtqueue_add_buf_gfp(vi->rvq, vi->rx_sg, 0, MAX_SKB_FRAGS + 2,
+                                   first, gfp);
        if (err < 0)
                give_pages(vi, first);
 
@@ -404,7 +404,7 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp)
 
        sg_init_one(vi->rx_sg, page_address(page), PAGE_SIZE);
 
-       err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, 1, page);
+       err = virtqueue_add_buf_gfp(vi->rvq, vi->rx_sg, 0, 1, page, gfp);
        if (err < 0)
                give_pages(vi, page);
 
index b504bd56136210776fa0d31e87a5e00b687cb03b..d14e207de1df8c8f074d0428e0d21d380344a7f2 100644 (file)
@@ -2262,7 +2262,8 @@ start:
                vxge_debug_init(VXGE_ERR,
                        "%s: memory allocation failed",
                        VXGE_DRIVER_NAME);
-               return  -ENOMEM;
+               ret = -ENOMEM;
+               goto alloc_entries_failed;
        }
 
        vdev->vxge_entries =
@@ -2271,8 +2272,8 @@ start:
        if (!vdev->vxge_entries) {
                vxge_debug_init(VXGE_ERR, "%s: memory allocation failed",
                        VXGE_DRIVER_NAME);
-               kfree(vdev->entries);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto alloc_vxge_entries_failed;
        }
 
        for (i = 0, j = 0; i < vdev->no_of_vpath; i++) {
@@ -2303,22 +2304,32 @@ start:
                vxge_debug_init(VXGE_ERR,
                        "%s: MSI-X enable failed for %d vectors, ret: %d",
                        VXGE_DRIVER_NAME, vdev->intr_cnt, ret);
+               if ((max_config_vpath != VXGE_USE_DEFAULT) || (ret < 3)) {
+                       ret = -ENODEV;
+                       goto enable_msix_failed;
+               }
+
                kfree(vdev->entries);
                kfree(vdev->vxge_entries);
                vdev->entries = NULL;
                vdev->vxge_entries = NULL;
-
-               if ((max_config_vpath != VXGE_USE_DEFAULT) || (ret < 3))
-                       return -ENODEV;
                /* Try with less no of vector by reducing no of vpaths count */
                temp = (ret - 1)/2;
                vxge_close_vpaths(vdev, temp);
                vdev->no_of_vpath = temp;
                goto start;
-       } else if (ret < 0)
-               return -ENODEV;
-
+       } else if (ret < 0) {
+               ret = -ENODEV;
+               goto enable_msix_failed;
+       }
        return 0;
+
+enable_msix_failed:
+       kfree(vdev->vxge_entries);
+alloc_vxge_entries_failed:
+       kfree(vdev->entries);
+alloc_entries_failed:
+       return ret;
 }
 
 static int vxge_enable_msix(struct vxgedev *vdev)
index 166e77dfffda9f9ec1b00c764d09b5b41b763506..e47f5a986b1c213c7f14e43b38dda541504c8b7d 100644 (file)
@@ -37,8 +37,6 @@
 #include <net/x25device.h>
 #include "x25_asy.h"
 
-#include <net/x25device.h>
-
 static struct net_device **x25_asy_devs;
 static int x25_asy_maxdev = SL_NRUNIT;
 
index 3f283bff0ff7146447419ea714ef7cdd78884b12..11491354e5b5bf3de80d0b91ee13d7a203a0e914 100644 (file)
@@ -1192,7 +1192,7 @@ int i2400m_fw_hdr_check(struct i2400m *i2400m,
        unsigned module_type, header_len, major_version, minor_version,
                module_id, module_vendor, date, size;
 
-       module_type = bcf_hdr->module_type;
+       module_type = le32_to_cpu(bcf_hdr->module_type);
        header_len = sizeof(u32) * le32_to_cpu(bcf_hdr->header_len);
        major_version = (le32_to_cpu(bcf_hdr->header_version) & 0xffff0000)
                >> 16;
index 82ab532a492335c803af5f1cd32f34eb527a334a..a93dc18a45c3fc9e0911197f7292948518741927 100644 (file)
@@ -739,17 +739,27 @@ err_out:
 static void ar9170_usb_firmware_failed(struct ar9170_usb *aru)
 {
        struct device *parent = aru->udev->dev.parent;
+       struct usb_device *udev;
+
+       /*
+        * Store a copy of the usb_device pointer locally.
+        * This is because device_release_driver initiates
+        * ar9170_usb_disconnect, which in turn frees our
+        * driver context (aru).
+        */
+       udev = aru->udev;
 
        complete(&aru->firmware_loading_complete);
 
        /* unbind anything failed */
        if (parent)
                device_lock(parent);
-       device_release_driver(&aru->udev->dev);
+
+       device_release_driver(&udev->dev);
        if (parent)
                device_unlock(parent);
 
-       usb_put_dev(aru->udev);
+       usb_put_dev(udev);
 }
 
 static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context)
index e0c244b02f05d17cc1ee9fb7cc12dd9e0e01541e..31c008042bfe066238edc359111047d8064693d3 100644 (file)
@@ -126,6 +126,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
        ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT;
        ah->ah_noise_floor = -95;       /* until first NF calibration is run */
        sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO;
+       ah->ah_current_channel = &sc->channels[0];
 
        /*
         * Find the mac version
index cc6d41dec332091eeef2c9a0b7905f2e26c95cfe..648972df369d849fa8d2e6a1ba836953787aef63 100644 (file)
@@ -195,7 +195,7 @@ static const struct ieee80211_rate ath5k_rates[] = {
 static int __devinit   ath5k_pci_probe(struct pci_dev *pdev,
                                const struct pci_device_id *id);
 static void __devexit  ath5k_pci_remove(struct pci_dev *pdev);
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int             ath5k_pci_suspend(struct device *dev);
 static int             ath5k_pci_resume(struct device *dev);
 
@@ -203,7 +203,7 @@ static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume);
 #define ATH5K_PM_OPS   (&ath5k_pm_ops)
 #else
 #define ATH5K_PM_OPS   NULL
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
 
 static struct pci_driver ath5k_pci_driver = {
        .name           = KBUILD_MODNAME,
@@ -222,7 +222,6 @@ static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
 static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
                struct ath5k_txq *txq);
 static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan);
-static int ath5k_reset_wake(struct ath5k_softc *sc);
 static int ath5k_start(struct ieee80211_hw *hw);
 static void ath5k_stop(struct ieee80211_hw *hw);
 static int ath5k_add_interface(struct ieee80211_hw *hw,
@@ -709,7 +708,7 @@ ath5k_pci_remove(struct pci_dev *pdev)
        ieee80211_free_hw(hw);
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int ath5k_pci_suspend(struct device *dev)
 {
        struct ieee80211_hw *hw = pci_get_drvdata(to_pci_dev(dev));
@@ -735,7 +734,7 @@ static int ath5k_pci_resume(struct device *dev)
        ath5k_led_enable(sc);
        return 0;
 }
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
 
 
 /***********************\
@@ -2770,7 +2769,7 @@ ath5k_tasklet_reset(unsigned long data)
 {
        struct ath5k_softc *sc = (void *)data;
 
-       ath5k_reset_wake(sc);
+       ath5k_reset(sc, sc->curchan);
 }
 
 /*
@@ -2941,23 +2940,13 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
        ath5k_beacon_config(sc);
        /* intrs are enabled by ath5k_beacon_config */
 
+       ieee80211_wake_queues(sc->hw);
+
        return 0;
 err:
        return ret;
 }
 
-static int
-ath5k_reset_wake(struct ath5k_softc *sc)
-{
-       int ret;
-
-       ret = ath5k_reset(sc, sc->curchan);
-       if (!ret)
-               ieee80211_wake_queues(sc->hw);
-
-       return ret;
-}
-
 static int ath5k_start(struct ieee80211_hw *hw)
 {
        return ath5k_init(hw->priv);
@@ -3151,13 +3140,15 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
 
        if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
                if (*new_flags & FIF_PROMISC_IN_BSS) {
-                       rfilt |= AR5K_RX_FILTER_PROM;
                        __set_bit(ATH_STAT_PROMISC, sc->status);
                } else {
                        __clear_bit(ATH_STAT_PROMISC, sc->status);
                }
        }
 
+       if (test_bit(ATH_STAT_PROMISC, sc->status))
+               rfilt |= AR5K_RX_FILTER_PROM;
+
        /* Note, AR5K_RX_FILTER_MCAST is already enabled */
        if (*new_flags & FIF_ALLMULTI) {
                mfilt[0] =  ~0;
index 1b81c4778800f62222eec48bc88c61ff993e9a69..492cbb15720d2076667681a8860a7ed866a2df5f 100644 (file)
@@ -1814,6 +1814,13 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)
        u8 def_ant, tx_ant, ee_mode;
        u32 sta_id1 = 0;
 
+       /* if channel is not initialized yet we can't set the antennas
+        * so just store the mode. it will be set on the next reset */
+       if (channel == NULL) {
+               ah->ah_ant_mode = ant_mode;
+               return;
+       }
+
        def_ant = ah->ah_def_ant;
 
        ATH5K_TRACE(ah->ah_sc);
index fbb7dec6ddebc11beb49a7b57b6e7342b38f9188..5ea87736a6ae49e0fa5ffe764241b7f72722bb2f 100644 (file)
@@ -445,6 +445,7 @@ void ath_deinit_leds(struct ath_softc *sc);
 #define SC_OP_TSF_RESET              BIT(11)
 #define SC_OP_BT_PRIORITY_DETECTED   BIT(12)
 #define SC_OP_BT_SCAN               BIT(13)
+#define SC_OP_ANI_RUN               BIT(14)
 
 /* Powersave flags */
 #define PS_WAIT_FOR_BEACON        BIT(0)
index abfa0493236f5a8c5f785d0126a26c9c0cba45bc..1e2a68ea935597a6f3f9499693a59ab8e191841f 100644 (file)
@@ -336,6 +336,10 @@ set_timer:
 static void ath_start_ani(struct ath_common *common)
 {
        unsigned long timestamp = jiffies_to_msecs(jiffies);
+       struct ath_softc *sc = (struct ath_softc *) common->priv;
+
+       if (!(sc->sc_flags & SC_OP_ANI_RUN))
+               return;
 
        common->ani.longcal_timer = timestamp;
        common->ani.shortcal_timer = timestamp;
@@ -872,11 +876,13 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
                /* Reset rssi stats */
                sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
 
+               sc->sc_flags |= SC_OP_ANI_RUN;
                ath_start_ani(common);
        } else {
                ath_print(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n");
                common->curaid = 0;
                /* Stop ANI */
+               sc->sc_flags &= ~SC_OP_ANI_RUN;
                del_timer_sync(&common->ani.timer);
        }
 }
@@ -1478,8 +1484,10 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
 
        if (vif->type == NL80211_IFTYPE_AP    ||
            vif->type == NL80211_IFTYPE_ADHOC ||
-           vif->type == NL80211_IFTYPE_MONITOR)
+           vif->type == NL80211_IFTYPE_MONITOR) {
+               sc->sc_flags |= SC_OP_ANI_RUN;
                ath_start_ani(common);
+       }
 
 out:
        mutex_unlock(&sc->mutex);
@@ -1500,6 +1508,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
        mutex_lock(&sc->mutex);
 
        /* Stop ANI */
+       sc->sc_flags &= ~SC_OP_ANI_RUN;
        del_timer_sync(&common->ani.timer);
 
        /* Reclaim beacon resources */
index 3db19172b43b7a1aa165e68463fabaf71dd4d278..859aa4ab07698aafcd937b606cb7bafd7f4e05fe 100644 (file)
@@ -1198,7 +1198,7 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
                int r;
 
                ath_print(common, ATH_DBG_FATAL,
-                         "Unable to stop TxDMA. Reset HAL!\n");
+                         "Failed to stop TX DMA. Resetting hardware!\n");
 
                spin_lock_bh(&sc->sc_resetlock);
                r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false);
@@ -1728,6 +1728,8 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
        } else
                bf->bf_isnullfunc = false;
 
+       bf->bf_tx_aborted = false;
+
        return 0;
 }
 
@@ -1989,7 +1991,7 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
        int nbad = 0;
        int isaggr = 0;
 
-       if (bf->bf_tx_aborted)
+       if (bf->bf_lastbf->bf_tx_aborted)
                return 0;
 
        isaggr = bf_isaggr(bf);
index db72461c486b50a2c90a3fa09e6ce6958eb99eac..29b31a694b59cc2140cf7b044757f29c5dfd9701 100644 (file)
@@ -594,6 +594,7 @@ static int prism2_config(struct pcmcia_device *link)
        local_info_t *local;
        int ret = 1;
        struct hostap_cs_priv *hw_priv;
+       unsigned long flags;
 
        PDEBUG(DEBUG_FLOW, "prism2_config()\n");
 
@@ -625,9 +626,15 @@ static int prism2_config(struct pcmcia_device *link)
        local->hw_priv = hw_priv;
        hw_priv->link = link;
 
+       /*
+        * Make sure the IRQ handler cannot proceed until at least
+        * dev->base_addr is initialized.
+        */
+       spin_lock_irqsave(&local->irq_init_lock, flags);
+
        ret = pcmcia_request_irq(link, prism2_interrupt);
        if (ret)
-               goto failed;
+               goto failed_unlock;
 
        /*
         * This actually configures the PCMCIA socket -- setting up
@@ -636,11 +643,13 @@ static int prism2_config(struct pcmcia_device *link)
         */
        ret = pcmcia_request_configuration(link, &link->conf);
        if (ret)
-               goto failed;
+               goto failed_unlock;
 
        dev->irq = link->irq;
        dev->base_addr = link->io.BasePort1;
 
+       spin_unlock_irqrestore(&local->irq_init_lock, flags);
+
        /* Finally, report what we've done */
        printk(KERN_INFO "%s: index 0x%02x: ",
               dev_info, link->conf.ConfigIndex);
@@ -667,6 +676,8 @@ static int prism2_config(struct pcmcia_device *link)
 
        return ret;
 
+ failed_unlock:
+        spin_unlock_irqrestore(&local->irq_init_lock, flags);
  failed:
        kfree(hw_priv);
        prism2_release((u_long)link);
index d70732819423d25d09627fa0bc371be5f6976896..2f999fc94f60ca9b36bb11d70fd29096c85eaf7e 100644 (file)
@@ -2618,17 +2618,20 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id)
        int events = 0;
        u16 ev;
 
+       iface = netdev_priv(dev);
+       local = iface->local;
+
        /* Detect early interrupt before driver is fully configued */
+       spin_lock(&local->irq_init_lock);
        if (!dev->base_addr) {
                if (net_ratelimit()) {
                        printk(KERN_DEBUG "%s: Interrupt, but dev not configured\n",
                               dev->name);
                }
+               spin_unlock(&local->irq_init_lock);
                return IRQ_HANDLED;
        }
-
-       iface = netdev_priv(dev);
-       local = iface->local;
+       spin_unlock(&local->irq_init_lock);
 
        prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 0);
 
@@ -3147,6 +3150,7 @@ prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx,
        spin_lock_init(&local->cmdlock);
        spin_lock_init(&local->baplock);
        spin_lock_init(&local->lock);
+       spin_lock_init(&local->irq_init_lock);
        mutex_init(&local->rid_bap_mtx);
 
        if (card_idx < 0 || card_idx >= MAX_PARM_DEVICES)
index 3d238917af07f32bcd16ffcf8eb75f90f824b120..1ba33be98b254ce9ef8a56fcb6c55501d14a9839 100644 (file)
@@ -654,7 +654,7 @@ struct local_info {
        rwlock_t iface_lock; /* hostap_interfaces read lock; use write lock
                              * when removing entries from the list.
                              * TX and RX paths can use read lock. */
-       spinlock_t cmdlock, baplock, lock;
+       spinlock_t cmdlock, baplock, lock, irq_init_lock;
        struct mutex rid_bap_mtx;
        u16 infofid; /* MAC buffer id for info frame */
        /* txfid, intransmitfid, next_txtid, and next_alloc are protected by
index 068f7f8435c5d98c63626062a98f46f1853c6e2e..c44a303e62ed45c2bdc9ea9b77db020eb927c39c 100644 (file)
@@ -2852,6 +2852,7 @@ static struct iwl_lib_ops iwl3945_lib = {
        .isr = iwl_isr_legacy,
        .config_ap = iwl3945_config_ap,
        .manage_ibss_station = iwl3945_manage_ibss_station,
+       .recover_from_tx_stall = iwl_bg_monitor_recover,
        .check_plcp_health = iwl3945_good_plcp_health,
 
        .debugfs_ops = {
index 44ef5d93befcda26e6bec109c4b5ae66994da549..01658cf82d3904dc7cb1dc91bb7bdbf7f3152f85 100644 (file)
@@ -212,11 +212,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
 static void iwlagn_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
                        __le32 *tx_flags)
 {
-       if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
-           (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT))
-               *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK;
-       else
-               *tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK;
+       *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK;
 }
 
 /* Calc max signal level (dBm) among 3 possible receivers */
index 1004cfc403b1a3d8316243a58cd16dcc273f93ee..0f292a210ed92d1a67153234b56045647807f3f9 100644 (file)
@@ -1119,10 +1119,9 @@ static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
                                           struct iwl_scan_channel *scan_ch)
 {
        const struct ieee80211_supported_band *sband;
-       const struct iwl_channel_info *ch_info;
        u16 passive_dwell = 0;
        u16 active_dwell = 0;
-       int i, added = 0;
+       int added = 0;
        u16 channel = 0;
 
        sband = iwl_get_hw_mode(priv, band);
@@ -1137,32 +1136,7 @@ static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
        if (passive_dwell <= active_dwell)
                passive_dwell = active_dwell + 1;
 
-       /* only scan single channel, good enough to reset the RF */
-       /* pick the first valid not in-use channel */
-       if (band == IEEE80211_BAND_5GHZ) {
-               for (i = 14; i < priv->channel_count; i++) {
-                       if (priv->channel_info[i].channel !=
-                           le16_to_cpu(priv->staging_rxon.channel)) {
-                               channel = priv->channel_info[i].channel;
-                               ch_info = iwl_get_channel_info(priv,
-                                       band, channel);
-                               if (is_channel_valid(ch_info))
-                                       break;
-                       }
-               }
-       } else {
-               for (i = 0; i < 14; i++) {
-                       if (priv->channel_info[i].channel !=
-                           le16_to_cpu(priv->staging_rxon.channel)) {
-                                       channel =
-                                               priv->channel_info[i].channel;
-                                       ch_info = iwl_get_channel_info(priv,
-                                               band, channel);
-                                       if (is_channel_valid(ch_info))
-                                               break;
-                       }
-               }
-       }
+       channel = iwl_get_single_channel_number(priv, band);
        if (channel) {
                scan_ch->channel = cpu_to_le16(channel);
                scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
index c402bfc83f36360358ebeef3ab1fe4cbeeb863e4..7d614c4d3c6200d5410bba749105f4d371b2e5b7 100644 (file)
@@ -1125,6 +1125,7 @@ static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
        struct ieee80211_sta *sta;
        struct iwl_station_priv *sta_priv;
 
+       rcu_read_lock();
        sta = ieee80211_find_sta(priv->vif, hdr->addr1);
        if (sta) {
                sta_priv = (void *)sta->drv_priv;
@@ -1133,6 +1134,7 @@ static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
                    atomic_dec_return(&sta_priv->pending_frames) == 0)
                        ieee80211_sta_block_awake(priv->hw, sta, false);
        }
+       rcu_read_unlock();
 
        ieee80211_tx_status_irqsafe(priv->hw, skb);
 }
@@ -1297,6 +1299,11 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
        sta_id = ba_resp->sta_id;
        tid = ba_resp->tid;
        agg = &priv->stations[sta_id].tid[tid].agg;
+       if (unlikely(agg->txq_id != scd_flow)) {
+               IWL_ERR(priv, "BA scd_flow %d does not match txq_id %d\n",
+                       scd_flow, agg->txq_id);
+               return;
+       }
 
        /* Find index just before block-ack window */
        index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
index aef4f71f1981c3e31461932228bbdb9f3aedf15b..24aff654fa9c44251b11f3d12ab63d639ea06384 100644 (file)
@@ -1484,6 +1484,156 @@ bool iwl_good_ack_health(struct iwl_priv *priv,
 }
 
 
+/*****************************************************************************
+ *
+ * sysfs attributes
+ *
+ *****************************************************************************/
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+
+/*
+ * The following adds a new attribute to the sysfs representation
+ * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
+ * used for controlling the debug level.
+ *
+ * See the level definitions in iwl for details.
+ *
+ * The debug_level being managed using sysfs below is a per device debug
+ * level that is used instead of the global debug level if it (the per
+ * device debug level) is set.
+ */
+static ssize_t show_debug_level(struct device *d,
+                               struct device_attribute *attr, char *buf)
+{
+       struct iwl_priv *priv = dev_get_drvdata(d);
+       return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv));
+}
+static ssize_t store_debug_level(struct device *d,
+                               struct device_attribute *attr,
+                                const char *buf, size_t count)
+{
+       struct iwl_priv *priv = dev_get_drvdata(d);
+       unsigned long val;
+       int ret;
+
+       ret = strict_strtoul(buf, 0, &val);
+       if (ret)
+               IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
+       else {
+               priv->debug_level = val;
+               if (iwl_alloc_traffic_mem(priv))
+                       IWL_ERR(priv,
+                               "Not enough memory to generate traffic log\n");
+       }
+       return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
+                       show_debug_level, store_debug_level);
+
+
+#endif /* CONFIG_IWLWIFI_DEBUG */
+
+
+static ssize_t show_temperature(struct device *d,
+                               struct device_attribute *attr, char *buf)
+{
+       struct iwl_priv *priv = dev_get_drvdata(d);
+
+       if (!iwl_is_alive(priv))
+               return -EAGAIN;
+
+       return sprintf(buf, "%d\n", priv->temperature);
+}
+
+static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
+
+static ssize_t show_tx_power(struct device *d,
+                            struct device_attribute *attr, char *buf)
+{
+       struct iwl_priv *priv = dev_get_drvdata(d);
+
+       if (!iwl_is_ready_rf(priv))
+               return sprintf(buf, "off\n");
+       else
+               return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
+}
+
+static ssize_t store_tx_power(struct device *d,
+                             struct device_attribute *attr,
+                             const char *buf, size_t count)
+{
+       struct iwl_priv *priv = dev_get_drvdata(d);
+       unsigned long val;
+       int ret;
+
+       ret = strict_strtoul(buf, 10, &val);
+       if (ret)
+               IWL_INFO(priv, "%s is not in decimal form.\n", buf);
+       else {
+               ret = iwl_set_tx_power(priv, val, false);
+               if (ret)
+                       IWL_ERR(priv, "failed setting tx power (0x%d).\n",
+                               ret);
+               else
+                       ret = count;
+       }
+       return ret;
+}
+
+static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
+
+static ssize_t show_rts_ht_protection(struct device *d,
+                            struct device_attribute *attr, char *buf)
+{
+       struct iwl_priv *priv = dev_get_drvdata(d);
+
+       return sprintf(buf, "%s\n",
+               priv->cfg->use_rts_for_ht ? "RTS/CTS" : "CTS-to-self");
+}
+
+static ssize_t store_rts_ht_protection(struct device *d,
+                             struct device_attribute *attr,
+                             const char *buf, size_t count)
+{
+       struct iwl_priv *priv = dev_get_drvdata(d);
+       unsigned long val;
+       int ret;
+
+       ret = strict_strtoul(buf, 10, &val);
+       if (ret)
+               IWL_INFO(priv, "Input is not in decimal form.\n");
+       else {
+               if (!iwl_is_associated(priv))
+                       priv->cfg->use_rts_for_ht = val ? true : false;
+               else
+                       IWL_ERR(priv, "Sta associated with AP - "
+                               "Change protection mechanism is not allowed\n");
+               ret = count;
+       }
+       return ret;
+}
+
+static DEVICE_ATTR(rts_ht_protection, S_IWUSR | S_IRUGO,
+                       show_rts_ht_protection, store_rts_ht_protection);
+
+
+static struct attribute *iwl_sysfs_entries[] = {
+       &dev_attr_temperature.attr,
+       &dev_attr_tx_power.attr,
+       &dev_attr_rts_ht_protection.attr,
+#ifdef CONFIG_IWLWIFI_DEBUG
+       &dev_attr_debug_level.attr,
+#endif
+       NULL
+};
+
+static struct attribute_group iwl_attribute_group = {
+       .name = NULL,           /* put in device directory */
+       .attrs = iwl_sysfs_entries,
+};
+
 /******************************************************************************
  *
  * uCode download functions
@@ -1965,6 +2115,13 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
        if (err)
                IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
 
+       err = sysfs_create_group(&priv->pci_dev->dev.kobj,
+                                       &iwl_attribute_group);
+       if (err) {
+               IWL_ERR(priv, "failed to create sysfs device attributes\n");
+               goto out_unbind;
+       }
+
        /* We have our copies now, allow OS release its copies */
        release_firmware(ucode_raw);
        complete(&priv->_agn.firmware_loading_complete);
@@ -3234,10 +3391,12 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
        int ret;
        u8 sta_id;
 
-       sta_priv->common.sta_id = IWL_INVALID_STATION;
-
        IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
                        sta->addr);
+       mutex_lock(&priv->mutex);
+       IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
+                       sta->addr);
+       sta_priv->common.sta_id = IWL_INVALID_STATION;
 
        atomic_set(&sta_priv->pending_frames, 0);
        if (vif->type == NL80211_IFTYPE_AP)
@@ -3249,6 +3408,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
                IWL_ERR(priv, "Unable to add station %pM (%d)\n",
                        sta->addr, ret);
                /* Should we return success if return code is EEXIST ? */
+               mutex_unlock(&priv->mutex);
                return ret;
        }
 
@@ -3258,145 +3418,11 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
        IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
                       sta->addr);
        iwl_rs_rate_init(priv, sta, sta_id);
+       mutex_unlock(&priv->mutex);
 
        return 0;
 }
 
-/*****************************************************************************
- *
- * sysfs attributes
- *
- *****************************************************************************/
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-
-/*
- * The following adds a new attribute to the sysfs representation
- * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
- * used for controlling the debug level.
- *
- * See the level definitions in iwl for details.
- *
- * The debug_level being managed using sysfs below is a per device debug
- * level that is used instead of the global debug level if it (the per
- * device debug level) is set.
- */
-static ssize_t show_debug_level(struct device *d,
-                               struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv));
-}
-static ssize_t store_debug_level(struct device *d,
-                               struct device_attribute *attr,
-                                const char *buf, size_t count)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       unsigned long val;
-       int ret;
-
-       ret = strict_strtoul(buf, 0, &val);
-       if (ret)
-               IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
-       else {
-               priv->debug_level = val;
-               if (iwl_alloc_traffic_mem(priv))
-                       IWL_ERR(priv,
-                               "Not enough memory to generate traffic log\n");
-       }
-       return strnlen(buf, count);
-}
-
-static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
-                       show_debug_level, store_debug_level);
-
-
-#endif /* CONFIG_IWLWIFI_DEBUG */
-
-
-static ssize_t show_temperature(struct device *d,
-                               struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-
-       if (!iwl_is_alive(priv))
-               return -EAGAIN;
-
-       return sprintf(buf, "%d\n", priv->temperature);
-}
-
-static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
-
-static ssize_t show_tx_power(struct device *d,
-                            struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-
-       if (!iwl_is_ready_rf(priv))
-               return sprintf(buf, "off\n");
-       else
-               return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
-}
-
-static ssize_t store_tx_power(struct device *d,
-                             struct device_attribute *attr,
-                             const char *buf, size_t count)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       unsigned long val;
-       int ret;
-
-       ret = strict_strtoul(buf, 10, &val);
-       if (ret)
-               IWL_INFO(priv, "%s is not in decimal form.\n", buf);
-       else {
-               ret = iwl_set_tx_power(priv, val, false);
-               if (ret)
-                       IWL_ERR(priv, "failed setting tx power (0x%d).\n",
-                               ret);
-               else
-                       ret = count;
-       }
-       return ret;
-}
-
-static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
-
-static ssize_t show_rts_ht_protection(struct device *d,
-                            struct device_attribute *attr, char *buf)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-
-       return sprintf(buf, "%s\n",
-               priv->cfg->use_rts_for_ht ? "RTS/CTS" : "CTS-to-self");
-}
-
-static ssize_t store_rts_ht_protection(struct device *d,
-                             struct device_attribute *attr,
-                             const char *buf, size_t count)
-{
-       struct iwl_priv *priv = dev_get_drvdata(d);
-       unsigned long val;
-       int ret;
-
-       ret = strict_strtoul(buf, 10, &val);
-       if (ret)
-               IWL_INFO(priv, "Input is not in decimal form.\n");
-       else {
-               if (!iwl_is_associated(priv))
-                       priv->cfg->use_rts_for_ht = val ? true : false;
-               else
-                       IWL_ERR(priv, "Sta associated with AP - "
-                               "Change protection mechanism is not allowed\n");
-               ret = count;
-       }
-       return ret;
-}
-
-static DEVICE_ATTR(rts_ht_protection, S_IWUSR | S_IRUGO,
-                       show_rts_ht_protection, store_rts_ht_protection);
-
-
 /*****************************************************************************
  *
  * driver setup and teardown
@@ -3550,21 +3576,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
        kfree(priv->scan_cmd);
 }
 
-static struct attribute *iwl_sysfs_entries[] = {
-       &dev_attr_temperature.attr,
-       &dev_attr_tx_power.attr,
-       &dev_attr_rts_ht_protection.attr,
-#ifdef CONFIG_IWLWIFI_DEBUG
-       &dev_attr_debug_level.attr,
-#endif
-       NULL
-};
-
-static struct attribute_group iwl_attribute_group = {
-       .name = NULL,           /* put in device directory */
-       .attrs = iwl_sysfs_entries,
-};
-
 static struct ieee80211_ops iwl_hw_ops = {
        .tx = iwl_mac_tx,
        .start = iwl_mac_start,
@@ -3750,11 +3761,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
                goto out_disable_msi;
        }
-       err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group);
-       if (err) {
-               IWL_ERR(priv, "failed to create sysfs device attributes\n");
-               goto out_free_irq;
-       }
 
        iwl_setup_deferred_work(priv);
        iwl_setup_rx_handlers(priv);
@@ -3788,15 +3794,13 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        err = iwl_request_firmware(priv, true);
        if (err)
-               goto out_remove_sysfs;
+               goto out_destroy_workqueue;
 
        return 0;
 
- out_remove_sysfs:
+ out_destroy_workqueue:
        destroy_workqueue(priv->workqueue);
        priv->workqueue = NULL;
-       sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
- out_free_irq:
        free_irq(priv->pci_dev->irq, priv);
        iwl_free_isr_ict(priv);
  out_disable_msi:
index 5a7eca8fb789621f69d15a6b79e5bae143386664..5bbc5298ef96e50b29206ea3e5ea8ca408e22695 100644 (file)
@@ -854,6 +854,45 @@ void iwl_set_rxon_chain(struct iwl_priv *priv)
 }
 EXPORT_SYMBOL(iwl_set_rxon_chain);
 
+/* Return valid channel */
+u8 iwl_get_single_channel_number(struct iwl_priv *priv,
+                                 enum ieee80211_band band)
+{
+       const struct iwl_channel_info *ch_info;
+       int i;
+       u8 channel = 0;
+
+       /* only scan single channel, good enough to reset the RF */
+       /* pick the first valid not in-use channel */
+       if (band == IEEE80211_BAND_5GHZ) {
+               for (i = 14; i < priv->channel_count; i++) {
+                       if (priv->channel_info[i].channel !=
+                           le16_to_cpu(priv->staging_rxon.channel)) {
+                               channel = priv->channel_info[i].channel;
+                               ch_info = iwl_get_channel_info(priv,
+                                       band, channel);
+                               if (is_channel_valid(ch_info))
+                                       break;
+                       }
+               }
+       } else {
+               for (i = 0; i < 14; i++) {
+                       if (priv->channel_info[i].channel !=
+                           le16_to_cpu(priv->staging_rxon.channel)) {
+                                       channel =
+                                               priv->channel_info[i].channel;
+                                       ch_info = iwl_get_channel_info(priv,
+                                               band, channel);
+                                       if (is_channel_valid(ch_info))
+                                               break;
+                       }
+               }
+       }
+
+       return channel;
+}
+EXPORT_SYMBOL(iwl_get_single_channel_number);
+
 /**
  * iwl_set_rxon_channel - Set the phymode and channel values in staging RXON
  * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
@@ -1275,7 +1314,6 @@ void iwl_configure_filter(struct ieee80211_hw *hw,
                        changed_flags, *total_flags);
 
        CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
-       CHK(FIF_ALLMULTI, RXON_FILTER_ACCEPT_GRP_MSK);
        CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK);
        CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
 
@@ -1290,6 +1328,12 @@ void iwl_configure_filter(struct ieee80211_hw *hw,
 
        mutex_unlock(&priv->mutex);
 
+       /*
+        * Receiving all multicast frames is always enabled by the
+        * default flags setup in iwl_connection_init_rx_config()
+        * since we currently do not support programming multicast
+        * filters into the device.
+        */
        *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
                        FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
 }
index 7e5a5ba41fd210e492655a5248d39bd7d4c7beb1..31775bd9c36170faa839da119456fd4cf747a385 100644 (file)
@@ -343,6 +343,8 @@ int iwl_check_rxon_cmd(struct iwl_priv *priv);
 int iwl_full_rxon_required(struct iwl_priv *priv);
 void iwl_set_rxon_chain(struct iwl_priv *priv);
 int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch);
+u8 iwl_get_single_channel_number(struct iwl_priv *priv,
+                                 enum ieee80211_band band);
 void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf);
 u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
                         struct ieee80211_sta_ht_cap *sta_ht_inf);
index 5d3f51ff2f0d075ad6ef81c022a687651afd2e07..386c5f96eff81c6467f026bc970c39734b853ffb 100644 (file)
@@ -491,6 +491,7 @@ void iwl_bg_abort_scan(struct work_struct *work)
 
        mutex_lock(&priv->mutex);
 
+       cancel_delayed_work_sync(&priv->scan_check);
        set_bit(STATUS_SCAN_ABORTING, &priv->status);
        iwl_send_scan_abort(priv);
 
index 83a26361a9b56b35d4364c93b9f9df32905c8cc6..c27c13fbb1aec26bac302623b96d089e1f13c0dd 100644 (file)
@@ -1373,10 +1373,14 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw,
 
        IWL_DEBUG_INFO(priv, "received request to remove station %pM\n",
                        sta->addr);
+       mutex_lock(&priv->mutex);
+       IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n",
+                       sta->addr);
        ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr);
        if (ret)
                IWL_ERR(priv, "Error removing station %pM\n",
                        sta->addr);
+       mutex_unlock(&priv->mutex);
        return ret;
 }
 EXPORT_SYMBOL(iwl_mac_sta_remove);
index 3e5bffb6034f47bad2d69ed89b7b38ae0f25be30..a27872de41061d62cec0af818aa72f88927396da 100644 (file)
@@ -1844,6 +1844,49 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
 #endif
 }
 
+static int iwl3945_get_single_channel_for_scan(struct iwl_priv *priv,
+                                              struct ieee80211_vif *vif,
+                                              enum ieee80211_band band,
+                                              struct iwl3945_scan_channel *scan_ch)
+{
+       const struct ieee80211_supported_band *sband;
+       u16 passive_dwell = 0;
+       u16 active_dwell = 0;
+       int added = 0;
+       u8 channel = 0;
+
+       sband = iwl_get_hw_mode(priv, band);
+       if (!sband) {
+               IWL_ERR(priv, "invalid band\n");
+               return added;
+       }
+
+       active_dwell = iwl_get_active_dwell_time(priv, band, 0);
+       passive_dwell = iwl_get_passive_dwell_time(priv, band, vif);
+
+       if (passive_dwell <= active_dwell)
+               passive_dwell = active_dwell + 1;
+
+
+       channel = iwl_get_single_channel_number(priv, band);
+
+       if (channel) {
+               scan_ch->channel = channel;
+               scan_ch->type = 0;      /* passive */
+               scan_ch->active_dwell = cpu_to_le16(active_dwell);
+               scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+               /* Set txpower levels to defaults */
+               scan_ch->tpc.dsp_atten = 110;
+               if (band == IEEE80211_BAND_5GHZ)
+                       scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
+               else
+                       scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
+               added++;
+       } else
+               IWL_ERR(priv, "no valid channel found\n");
+       return added;
+}
+
 static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
                                         enum ieee80211_band band,
                                     u8 is_active, u8 n_probes,
@@ -2992,9 +3035,16 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
        /* select Rx antennas */
        scan->flags |= iwl3945_get_antenna_flags(priv);
 
-       scan->channel_count =
-               iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
-                       (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
+       if (priv->is_internal_short_scan) {
+               scan->channel_count =
+                       iwl3945_get_single_channel_for_scan(priv, vif, band,
+                               (void *)&scan->data[le16_to_cpu(
+                               scan->tx_cmd.len)]);
+       } else {
+               scan->channel_count =
+                       iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
+                               (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
+       }
 
        if (scan->channel_count == 0) {
                IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
@@ -3387,10 +3437,13 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
        bool is_ap = vif->type == NL80211_IFTYPE_STATION;
        u8 sta_id;
 
-       sta_priv->common.sta_id = IWL_INVALID_STATION;
-
        IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
                        sta->addr);
+       mutex_lock(&priv->mutex);
+       IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
+                       sta->addr);
+       sta_priv->common.sta_id = IWL_INVALID_STATION;
+
 
        ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap,
                                     &sta_id);
@@ -3398,6 +3451,7 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
                IWL_ERR(priv, "Unable to add station %pM (%d)\n",
                        sta->addr, ret);
                /* Should we return success if return code is EEXIST ? */
+               mutex_unlock(&priv->mutex);
                return ret;
        }
 
@@ -3407,6 +3461,7 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
        IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
                       sta->addr);
        iwl3945_rs_rate_init(priv, sta, sta_id);
+       mutex_unlock(&priv->mutex);
 
        return 0;
 }
index a115bfa9513a8776f49139924e475a517884819c..7a377f5b76627540b6309f563bf6c974be503799 100644 (file)
@@ -329,9 +329,8 @@ static int process_rxed_802_11_packet(struct lbs_private *priv,
        /* create the exported radio header */
 
        /* radiotap header */
-       radiotap_hdr.hdr.it_version = 0;
-       /* XXX must check this value for pad */
-       radiotap_hdr.hdr.it_pad = 0;
+       memset(&radiotap_hdr, 0, sizeof(radiotap_hdr));
+       /* XXX must check radiotap_hdr.hdr.it_pad for pad */
        radiotap_hdr.hdr.it_len = cpu_to_le16 (sizeof(struct rx_radiotap_hdr));
        radiotap_hdr.hdr.it_present = cpu_to_le32 (RX_RADIOTAP_PRESENT);
        radiotap_hdr.rate = convert_mv_rate_to_radiotap(prxpd->rx_rate);
index 6a04c2157f73f3788109afcdfbc50c4ecdf62b9e..817fffc0de4b5093c869fc11a5f72aa9ca0ab3ba 100644 (file)
@@ -549,7 +549,7 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
 
        prxpd = (struct rxpd *) skb->data;
 
-       stats.flag = 0;
+       memset(&stats, 0, sizeof(stats));
        if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK)))
                stats.flag |= RX_FLAG_FAILED_FCS_CRC;
        stats.freq = priv->cur_freq;
index 07c4528f6e6b895d59e2cddc3fd30edcf80cb000..a5ea89cde8c43a9c837018459e9f689a83162e1e 100644 (file)
@@ -41,6 +41,8 @@ static DEFINE_PCI_DEVICE_TABLE(p54p_table) = {
        { PCI_DEVICE(0x1260, 0x3877) },
        /* Intersil PRISM Javelin/Xbow Wireless LAN adapter */
        { PCI_DEVICE(0x1260, 0x3886) },
+       /* Intersil PRISM Xbow Wireless LAN adapter (Symbol AP-300) */
+       { PCI_DEVICE(0x1260, 0xffff) },
        { },
 };
 
index d5b197b4d5bb492ac70c8e2a98297a2e82e5e356..73073259f50814b36ab947e4fd58fc6293e6f459 100644 (file)
@@ -80,6 +80,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
        {USB_DEVICE(0x1413, 0x5400)},   /* Telsey 802.11g USB2.0 Adapter */
        {USB_DEVICE(0x1435, 0x0427)},   /* Inventel UR054G */
        {USB_DEVICE(0x2001, 0x3704)},   /* DLink DWL-G122 rev A2 */
+       {USB_DEVICE(0x413c, 0x5513)},   /* Dell WLA3310 USB Wireless Adapter */
        {USB_DEVICE(0x413c, 0x8102)},   /* Spinnaker DUT */
        {USB_DEVICE(0x413c, 0x8104)},   /* Cohiba Proto board */
        {}
index 699161327d656feb56cb7c74d081e17e277a9394..0f8b84b7224cace0167ebe5b0065da28af08986c 100644 (file)
@@ -413,7 +413,7 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
         */
        rt2x00_desc_read(txi, 0, &word);
        rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN,
-                          skb->len - TXINFO_DESC_SIZE);
+                          skb->len + TXWI_DESC_SIZE);
        rt2x00_set_field32(&word, TXINFO_W0_WIV,
                           !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
        rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2);
index d234285c2c81186fc096044dcfa309236e7e2d51..c561332e70092b18280fff1843f948b13603289a 100644 (file)
@@ -259,6 +259,7 @@ disable:
        sdio_disable_func(func);
 release:
        sdio_release_host(func);
+       wl1251_free_hw(wl);
        return ret;
 }
 
index dadd686c98012e545bf90d07a61447853630818d..8bb715a1a7a6a07609a34b363de5ce9a58960933 100644 (file)
@@ -807,6 +807,7 @@ static struct pcmcia_device_id serial_ids[] = {
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),
        PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
        PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
        PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "cis/3CCFEM556.cis"),
index 989e2752cc36d8abb9613b6c77b50936be85184c..6dcda86be6ebdb83d579d27907ee1f153889000a 100644 (file)
@@ -625,9 +625,12 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
                ssb_printk(KERN_ERR PFX "No SPROM available!\n");
                return -ENODEV;
        }
-
-       bus->sprom_offset = (bus->chipco.dev->id.revision < 31) ?
-               SSB_SPROM_BASE1 : SSB_SPROM_BASE31;
+       if (bus->chipco.dev) {  /* can be unavailible! */
+               bus->sprom_offset = (bus->chipco.dev->id.revision < 31) ?
+                       SSB_SPROM_BASE1 : SSB_SPROM_BASE31;
+       } else {
+               bus->sprom_offset = SSB_SPROM_BASE1;
+       }
 
        buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
        if (!buf)
index 007bc3a03486b621034134f33a1c3029cb8e0b29..4f7cc8d13277ddb84126430923202f9fa7938ac7 100644 (file)
@@ -185,6 +185,7 @@ bool ssb_is_sprom_available(struct ssb_bus *bus)
        /* this routine differs from specs as we do not access SPROM directly
           on PCMCIA */
        if (bus->bustype == SSB_BUSTYPE_PCI &&
+           bus->chipco.dev &&  /* can be unavailible! */
            bus->chipco.dev->id.revision >= 31)
                return bus->chipco.capabilities & SSB_CHIPCO_CAP_SPROM;
 
index 276b40a168357ed5d4b793ccae7cbf387ba12711..b4207ca3ad5277c5ae66ea2f2ccc41fd961a0426 100644 (file)
@@ -379,6 +379,8 @@ struct ethtool_rxnfc {
        __u32                           flow_type;
        /* The rx flow hash value or the rule DB size */
        __u64                           data;
+       /* The following fields are not valid and must not be used for
+        * the ETHTOOL_{G,X}RXFH commands. */
        struct ethtool_rx_flow_spec     fs;
        __u32                           rule_cnt;
        __u32                           rule_locs[0];
index cbbbe9bfecad0652334963de2cd8363c43e6b28a..30b0c4e78f91ce8a43ca2c13ab5845f8a30fd9f1 100644 (file)
@@ -19,6 +19,11 @@ struct mv643xx_eth_shared_platform_data {
        struct mbus_dram_target_info    *dram;
        struct platform_device  *shared_smi;
        unsigned int            t_clk;
+       /*
+        * Max packet size for Tx IP/Layer 4 checksum, when set to 0, default
+        * limit of 9KiB will be used.
+        */
+       int                     tx_csum_limit;
 };
 
 #define MV643XX_ETH_PHY_ADDR_DEFAULT   0
index 2b4deeeb8646e7c6621261e24e2e3a94bb123f2a..dee0b11a87590b31750706fec2bfe93bfec7d2bf 100644 (file)
@@ -129,10 +129,9 @@ struct socket_wq {
  *  @type: socket type (%SOCK_STREAM, etc)
  *  @flags: socket flags (%SOCK_ASYNC_NOSPACE, etc)
  *  @ops: protocol specific socket operations
- *  @fasync_list: Asynchronous wake up list
  *  @file: File back pointer for gc
  *  @sk: internal networking protocol agnostic socket representation
- *  @wait: wait queue for several uses
+ *  @wq: wait queue for several uses
  */
 struct socket {
        socket_state            state;
index 40291f3750247dfa12102178a6aed457e7735516..5e6188d9f017aa385717f490f4e1c6b896777d36 100644 (file)
@@ -1656,6 +1656,9 @@ static inline int netif_is_multiqueue(const struct net_device *dev)
        return (dev->num_tx_queues > 1);
 }
 
+extern void netif_set_real_num_tx_queues(struct net_device *dev,
+                                        unsigned int txq);
+
 /* Use this variant when it is known for sure that it
  * is executing from hardware interrupt context or with hardware interrupts
  * disabled.
index 7cdfb4d52847e6f733df1538f48fc73508e3d13e..f89e7fd59a4c4029a5e301b30c14df0ee7ae2699 100644 (file)
@@ -380,7 +380,10 @@ struct sk_buff {
        kmemcheck_bitfield_begin(flags2);
        __u16                   queue_mapping:16;
 #ifdef CONFIG_IPV6_NDISC_NODETYPE
-       __u8                    ndisc_nodetype:2;
+       __u8                    ndisc_nodetype:2,
+                               deliver_no_wcard:1;
+#else
+       __u8                    deliver_no_wcard:1;
 #endif
        kmemcheck_bitfield_end(flags2);
 
@@ -501,7 +504,7 @@ static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
        return __alloc_skb(size, priority, 1, -1);
 }
 
-extern int skb_recycle_check(struct sk_buff *skb, int skb_size);
+extern bool skb_recycle_check(struct sk_buff *skb, int skb_size);
 
 extern struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src);
 extern struct sk_buff *skb_clone(struct sk_buff *skb,
index 612069beda733676b1e106ce8f24ee19e66b8910..81d1413a87010967684febe7344169baa7d828ef 100644 (file)
@@ -250,11 +250,11 @@ static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev)
  * Linux networking.  Thus, destinations are stackable.
  */
 
-static inline struct dst_entry *dst_pop(struct dst_entry *dst)
+static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb)
 {
-       struct dst_entry *child = dst_clone(dst->child);
+       struct dst_entry *child = skb_dst(skb)->child;
 
-       dst_release(dst);
+       skb_dst_drop(skb);
        return child;
 }
 
index 03ca5d826757bb0459b3e612b5fdf5ae03757e9b..433604bb3fe8a70df241dcdc1370a867fd57ed92 100644 (file)
@@ -313,12 +313,24 @@ extern void qdisc_calculate_pkt_len(struct sk_buff *skb,
 extern void tcf_destroy(struct tcf_proto *tp);
 extern void tcf_destroy_chain(struct tcf_proto **fl);
 
-/* Reset all TX qdiscs of a device.  */
+/* Reset all TX qdiscs greater then index of a device.  */
+static inline void qdisc_reset_all_tx_gt(struct net_device *dev, unsigned int i)
+{
+       struct Qdisc *qdisc;
+
+       for (; i < dev->num_tx_queues; i++) {
+               qdisc = netdev_get_tx_queue(dev, i)->qdisc;
+               if (qdisc) {
+                       spin_lock_bh(qdisc_lock(qdisc));
+                       qdisc_reset(qdisc);
+                       spin_unlock_bh(qdisc_lock(qdisc));
+               }
+       }
+}
+
 static inline void qdisc_reset_all_tx(struct net_device *dev)
 {
-       unsigned int i;
-       for (i = 0; i < dev->num_tx_queues; i++)
-               qdisc_reset(netdev_get_tx_queue(dev, i)->qdisc);
+       qdisc_reset_all_tx_gt(dev, 0);
 }
 
 /* Are all TX queues of the device empty?  */
index 92456f1035f52bd6e1a6c8e7733c7737d58d15e1..899003d18db9e57ab8813176f4ea896a27376c49 100644 (file)
@@ -134,7 +134,7 @@ struct linux_xfrm_mib {
 #define SNMP_ADD_STATS_USER(mib, field, addend)        \
                        this_cpu_add(mib[1]->mibs[field], addend)
 #define SNMP_ADD_STATS(mib, field, addend)     \
-                       this_cpu_add(mib[0]->mibs[field], addend)
+                       this_cpu_add(mib[!in_softirq()]->mibs[field], addend)
 /*
  * Use "__typeof__(*mib[0]) *ptr" instead of "__typeof__(mib[0]) ptr"
  * to make @ptr a non-percpu pointer.
index ca241ea148758a555d123343e2fe8639f7dd5bd3..731150d52799ecc5492b3590c3b7b5b34de09072 100644 (file)
@@ -1524,20 +1524,7 @@ extern void sk_stop_timer(struct sock *sk, struct timer_list* timer);
 
 extern int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
 
-static inline int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
-{
-       /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
-          number of warnings when compiling with -W --ANK
-        */
-       if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
-           (unsigned)sk->sk_rcvbuf)
-               return -ENOMEM;
-       skb_set_owner_r(skb, sk);
-       skb_queue_tail(&sk->sk_error_queue, skb);
-       if (!sock_flag(sk, SOCK_DEAD))
-               sk->sk_data_ready(sk, skb->len);
-       return 0;
-}
+extern int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb);
 
 /*
  *     Recover an error report and clear atomically
index 1913af67c43d8ef976f08dcaef307499b59e4e0b..fc8f36dd0f5c5145932c45aa8e9f441697dcb0ec 100644 (file)
@@ -1586,7 +1586,7 @@ static inline struct xfrm_state *xfrm_input_state(struct sk_buff *skb)
 static inline int xfrm_mark_get(struct nlattr **attrs, struct xfrm_mark *m)
 {
        if (attrs[XFRMA_MARK])
-               memcpy(m, nla_data(attrs[XFRMA_MARK]), sizeof(m));
+               memcpy(m, nla_data(attrs[XFRMA_MARK]), sizeof(struct xfrm_mark));
        else
                m->v = m->m = 0;
 
index bd537fc10254c9fbb6cf3872e8488bba1809781b..50f58f5f1c3491f775a5ac6c97ea32c5c5b23674 100644 (file)
@@ -12,7 +12,7 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
                return NET_RX_DROP;
 
        if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master)))
-               goto drop;
+               skb->deliver_no_wcard = 1;
 
        skb->skb_iif = skb->dev->ifindex;
        __vlan_hwaccel_put_tag(skb, vlan_tci);
@@ -84,7 +84,7 @@ vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp,
        struct sk_buff *p;
 
        if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master)))
-               goto drop;
+               skb->deliver_no_wcard = 1;
 
        skb->skb_iif = skb->dev->ifindex;
        __vlan_hwaccel_put_tag(skb, vlan_tci);
index 55be90826f5fd1317f961b9fbabb3f3b989f380e..52984267781782cd78aa0bd7bc3d38280745c1b1 100644 (file)
@@ -708,7 +708,8 @@ static int vlan_dev_init(struct net_device *dev)
        netif_carrier_off(dev);
 
        /* IFF_BROADCAST|IFF_MULTICAST; ??? */
-       dev->flags  = real_dev->flags & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI);
+       dev->flags  = real_dev->flags & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI |
+                                         IFF_MASTER | IFF_SLAVE);
        dev->iflink = real_dev->ifindex;
        dev->state  = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
                                          (1<<__LINK_STATE_DORMANT))) |
index 0faad5ce6dc480efe1928c1c60728e14b4093b92..8c100c9dae2833bcf3963a2cc4c8a9a2fcbdc064 100644 (file)
@@ -104,6 +104,8 @@ static void bnep_net_set_mc_list(struct net_device *dev)
                                break;
                        memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN);
                        memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN);
+
+                       i++;
                }
                r->len = htons(skb->len - len);
        }
index 26637439965bef745542f7baa4242d5249a33d9d..b01dde35a69ed3f1cecf30ebe604cc1808d72a69 100644 (file)
@@ -128,7 +128,7 @@ void br_fdb_cleanup(unsigned long _data)
 {
        struct net_bridge *br = (struct net_bridge *)_data;
        unsigned long delay = hold_time(br);
-       unsigned long next_timer = jiffies + br->forward_delay;
+       unsigned long next_timer = jiffies + br->ageing_time;
        int i;
 
        spin_lock_bh(&br->hash_lock);
@@ -149,9 +149,7 @@ void br_fdb_cleanup(unsigned long _data)
        }
        spin_unlock_bh(&br->hash_lock);
 
-       /* Add HZ/4 to ensure we round the jiffies upwards to be after the next
-        * timer, otherwise we might round down and will have no-op run. */
-       mod_timer(&br->gc_timer, round_jiffies(next_timer + HZ/4));
+       mod_timer(&br->gc_timer, round_jiffies_up(next_timer));
 }
 
 /* Completely flush all dynamic entries in forwarding database.*/
index a98ef13930979a129a8d0195e5a94dee3ec7bd2a..a4e72a89e4ffc4eae7a2e7e09963bd0fb58e26a4 100644 (file)
@@ -140,10 +140,10 @@ static int deliver_clone(const struct net_bridge_port *prev,
                         void (*__packet_hook)(const struct net_bridge_port *p,
                                               struct sk_buff *skb))
 {
+       struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
+
        skb = skb_clone(skb, GFP_ATOMIC);
        if (!skb) {
-               struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
-
                dev->stats.tx_dropped++;
                return -ENOMEM;
        }
index cd2830fec9351322156e941c9d7043418ea549a4..fd27b172fb5d444ffdf5664312f0b0c86b4836cd 100644 (file)
@@ -83,7 +83,7 @@ static int cfrfml_transmit(struct cflayer *layr, struct cfpkt *pkt)
        if (!cfsrvl_ready(service, &ret))
                return ret;
 
-       if (!cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) {
+       if (cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) {
                pr_err("CAIF: %s():Packet too large - size=%d\n",
                        __func__, cfpkt_getlen(pkt));
                return -EOVERFLOW;
index cb4325a3dc83184f4a4f8e382dbec6b7ac6c21f2..965c5baace40b10c401c8fff3ecaaacb612c0aa6 100644 (file)
@@ -59,16 +59,18 @@ static int cfserl_receive(struct cflayer *l, struct cfpkt *newpkt)
        u8 stx = CFSERL_STX;
        int ret;
        u16 expectlen = 0;
+
        caif_assert(newpkt != NULL);
        spin_lock(&layr->sync);
 
        if (layr->incomplete_frm != NULL) {
-
                layr->incomplete_frm =
                    cfpkt_append(layr->incomplete_frm, newpkt, expectlen);
                pkt = layr->incomplete_frm;
-               if (pkt == NULL)
+               if (pkt == NULL) {
+                       spin_unlock(&layr->sync);
                        return -ENOMEM;
+               }
        } else {
                pkt = newpkt;
        }
index 0fd827f494919caa44926264baa885ea409df776..e04f7d964e83ea8d0c88308bb0fcd2e3dd9dfbd6 100644 (file)
@@ -84,7 +84,7 @@ static int cfvei_transmit(struct cflayer *layr, struct cfpkt *pkt)
                return ret;
        caif_assert(layr->dn != NULL);
        caif_assert(layr->dn->transmit != NULL);
-       if (!cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) {
+       if (cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) {
                pr_warning("CAIF: %s(): Packet too large - size=%d\n",
                           __func__, cfpkt_getlen(pkt));
                return -EOVERFLOW;
index 1845b08c624e1fa4c9dd398f4b61c2963dbfc1f2..723a34710ad401ff24afd5b1be1af86505f7da33 100644 (file)
@@ -1553,6 +1553,24 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
        rcu_read_unlock();
 }
 
+/*
+ * Routine to help set real_num_tx_queues. To avoid skbs mapped to queues
+ * greater then real_num_tx_queues stale skbs on the qdisc must be flushed.
+ */
+void netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)
+{
+       unsigned int real_num = dev->real_num_tx_queues;
+
+       if (unlikely(txq > dev->num_tx_queues))
+               ;
+       else if (txq > real_num)
+               dev->real_num_tx_queues = txq;
+       else if (txq < real_num) {
+               dev->real_num_tx_queues = txq;
+               qdisc_reset_all_tx_gt(dev, txq);
+       }
+}
+EXPORT_SYMBOL(netif_set_real_num_tx_queues);
 
 static inline void __netif_reschedule(struct Qdisc *q)
 {
@@ -2253,11 +2271,9 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb,
        if (skb_rx_queue_recorded(skb)) {
                u16 index = skb_get_rx_queue(skb);
                if (unlikely(index >= dev->num_rx_queues)) {
-                       if (net_ratelimit()) {
-                               pr_warning("%s received packet on queue "
-                                       "%u, but number of RX queues is %u\n",
-                                       dev->name, index, dev->num_rx_queues);
-                       }
+                       WARN_ONCE(dev->num_rx_queues > 1, "%s received packet "
+                               "on queue %u, but number of RX queues is %u\n",
+                               dev->name, index, dev->num_rx_queues);
                        goto done;
                }
                rxqueue = dev->_rx + index;
@@ -2795,7 +2811,7 @@ static int __netif_receive_skb(struct sk_buff *skb)
        struct net_device *orig_dev;
        struct net_device *master;
        struct net_device *null_or_orig;
-       struct net_device *null_or_bond;
+       struct net_device *orig_or_bond;
        int ret = NET_RX_DROP;
        __be16 type;
 
@@ -2812,13 +2828,24 @@ static int __netif_receive_skb(struct sk_buff *skb)
        if (!skb->skb_iif)
                skb->skb_iif = skb->dev->ifindex;
 
+       /*
+        * bonding note: skbs received on inactive slaves should only
+        * be delivered to pkt handlers that are exact matches.  Also
+        * the deliver_no_wcard flag will be set.  If packet handlers
+        * are sensitive to duplicate packets these skbs will need to
+        * be dropped at the handler.  The vlan accel path may have
+        * already set the deliver_no_wcard flag.
+        */
        null_or_orig = NULL;
        orig_dev = skb->dev;
        master = ACCESS_ONCE(orig_dev->master);
-       if (master) {
-               if (skb_bond_should_drop(skb, master))
+       if (skb->deliver_no_wcard)
+               null_or_orig = orig_dev;
+       else if (master) {
+               if (skb_bond_should_drop(skb, master)) {
+                       skb->deliver_no_wcard = 1;
                        null_or_orig = orig_dev; /* deliver only exact match */
-               else
+               else
                        skb->dev = master;
        }
 
@@ -2868,10 +2895,10 @@ ncls:
         * device that may have registered for a specific ptype.  The
         * handler may have to adjust skb->dev and orig_dev.
         */
-       null_or_bond = NULL;
+       orig_or_bond = orig_dev;
        if ((skb->dev->priv_flags & IFF_802_1Q_VLAN) &&
            (vlan_dev_real_dev(skb->dev)->priv_flags & IFF_BONDING)) {
-               null_or_bond = vlan_dev_real_dev(skb->dev);
+               orig_or_bond = vlan_dev_real_dev(skb->dev);
        }
 
        type = skb->protocol;
@@ -2879,7 +2906,7 @@ ncls:
                        &ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) {
                if (ptype->type == type && (ptype->dev == null_or_orig ||
                     ptype->dev == skb->dev || ptype->dev == orig_dev ||
-                    ptype->dev == null_or_bond)) {
+                    ptype->dev == orig_or_bond)) {
                        if (pt_prev)
                                ret = deliver_skb(skb, pt_prev, orig_dev);
                        pt_prev = ptype;
index a0f4964033d289b8d1b4959d4d1196ccc094bdff..75e4ffeb8cc99dae9c03c07c39962b17c4453f43 100644 (file)
@@ -318,23 +318,33 @@ out:
 }
 
 static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev,
-                                               void __user *useraddr)
+                                               u32 cmd, void __user *useraddr)
 {
-       struct ethtool_rxnfc cmd;
+       struct ethtool_rxnfc info;
+       size_t info_size = sizeof(info);
 
        if (!dev->ethtool_ops->set_rxnfc)
                return -EOPNOTSUPP;
 
-       if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
+       /* struct ethtool_rxnfc was originally defined for
+        * ETHTOOL_{G,S}RXFH with only the cmd, flow_type and data
+        * members.  User-space might still be using that
+        * definition. */
+       if (cmd == ETHTOOL_SRXFH)
+               info_size = (offsetof(struct ethtool_rxnfc, data) +
+                            sizeof(info.data));
+
+       if (copy_from_user(&info, useraddr, info_size))
                return -EFAULT;
 
-       return dev->ethtool_ops->set_rxnfc(dev, &cmd);
+       return dev->ethtool_ops->set_rxnfc(dev, &info);
 }
 
 static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev,
-                                               void __user *useraddr)
+                                               u32 cmd, void __user *useraddr)
 {
        struct ethtool_rxnfc info;
+       size_t info_size = sizeof(info);
        const struct ethtool_ops *ops = dev->ethtool_ops;
        int ret;
        void *rule_buf = NULL;
@@ -342,13 +352,22 @@ static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev,
        if (!ops->get_rxnfc)
                return -EOPNOTSUPP;
 
-       if (copy_from_user(&info, useraddr, sizeof(info)))
+       /* struct ethtool_rxnfc was originally defined for
+        * ETHTOOL_{G,S}RXFH with only the cmd, flow_type and data
+        * members.  User-space might still be using that
+        * definition. */
+       if (cmd == ETHTOOL_GRXFH)
+               info_size = (offsetof(struct ethtool_rxnfc, data) +
+                            sizeof(info.data));
+
+       if (copy_from_user(&info, useraddr, info_size))
                return -EFAULT;
 
        if (info.cmd == ETHTOOL_GRXCLSRLALL) {
                if (info.rule_cnt > 0) {
-                       rule_buf = kmalloc(info.rule_cnt * sizeof(u32),
-                                          GFP_USER);
+                       if (info.rule_cnt <= KMALLOC_MAX_SIZE / sizeof(u32))
+                               rule_buf = kmalloc(info.rule_cnt * sizeof(u32),
+                                                  GFP_USER);
                        if (!rule_buf)
                                return -ENOMEM;
                }
@@ -359,7 +378,7 @@ static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev,
                goto err_out;
 
        ret = -EFAULT;
-       if (copy_to_user(useraddr, &info, sizeof(info)))
+       if (copy_to_user(useraddr, &info, info_size))
                goto err_out;
 
        if (rule_buf) {
@@ -1516,12 +1535,12 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
        case ETHTOOL_GRXCLSRLCNT:
        case ETHTOOL_GRXCLSRULE:
        case ETHTOOL_GRXCLSRLALL:
-               rc = ethtool_get_rxnfc(dev, useraddr);
+               rc = ethtool_get_rxnfc(dev, ethcmd, useraddr);
                break;
        case ETHTOOL_SRXFH:
        case ETHTOOL_SRXCLSRLDEL:
        case ETHTOOL_SRXCLSRLINS:
-               rc = ethtool_set_rxnfc(dev, useraddr);
+               rc = ethtool_set_rxnfc(dev, ethcmd, useraddr);
                break;
        case ETHTOOL_GGRO:
                rc = ethtool_get_gro(dev, useraddr);
index cf8e70392fe0938acb4b8b88fa8bc74dbeaed584..785e5276a300e6f14c634e785eb1be8e0633c18e 100644 (file)
@@ -107,6 +107,7 @@ static DEFINE_RWLOCK(est_lock);
 
 /* Protects against soft lockup during large deletion */
 static struct rb_root est_root = RB_ROOT;
+static DEFINE_SPINLOCK(est_tree_lock);
 
 static void est_timer(unsigned long arg)
 {
@@ -201,7 +202,6 @@ struct gen_estimator *gen_find_node(const struct gnet_stats_basic_packed *bstats
  *
  * Returns 0 on success or a negative error code.
  *
- * NOTE: Called under rtnl_mutex
  */
 int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
                      struct gnet_stats_rate_est *rate_est,
@@ -232,6 +232,7 @@ int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
        est->last_packets = bstats->packets;
        est->avpps = rate_est->pps<<10;
 
+       spin_lock(&est_tree_lock);
        if (!elist[idx].timer.function) {
                INIT_LIST_HEAD(&elist[idx].list);
                setup_timer(&elist[idx].timer, est_timer, idx);
@@ -242,6 +243,7 @@ int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
 
        list_add_rcu(&est->list, &elist[idx].list);
        gen_add_node(est);
+       spin_unlock(&est_tree_lock);
 
        return 0;
 }
@@ -261,13 +263,13 @@ static void __gen_kill_estimator(struct rcu_head *head)
  *
  * Removes the rate estimator specified by &bstats and &rate_est.
  *
- * NOTE: Called under rtnl_mutex
  */
 void gen_kill_estimator(struct gnet_stats_basic_packed *bstats,
                        struct gnet_stats_rate_est *rate_est)
 {
        struct gen_estimator *e;
 
+       spin_lock(&est_tree_lock);
        while ((e = gen_find_node(bstats, rate_est))) {
                rb_erase(&e->node, &est_root);
 
@@ -278,6 +280,7 @@ void gen_kill_estimator(struct gnet_stats_basic_packed *bstats,
                list_del_rcu(&e->list);
                call_rcu(&e->e_rcu, __gen_kill_estimator);
        }
+       spin_unlock(&est_tree_lock);
 }
 EXPORT_SYMBOL(gen_kill_estimator);
 
@@ -312,8 +315,14 @@ EXPORT_SYMBOL(gen_replace_estimator);
 bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats,
                          const struct gnet_stats_rate_est *rate_est)
 {
+       bool res;
+
        ASSERT_RTNL();
 
-       return gen_find_node(bstats, rate_est) != NULL;
+       spin_lock(&est_tree_lock);
+       res = gen_find_node(bstats, rate_est) != NULL;
+       spin_unlock(&est_tree_lock);
+
+       return res;
 }
 EXPORT_SYMBOL(gen_estimator_active);
index 2ad68da418df6a6d6d4ae81db9e78d4a8f6ae981..1dacd7ba8dbb1d4c2e5e6e9f623b3806e202f0ee 100644 (file)
@@ -2170,7 +2170,7 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
        end_time = ktime_now();
 
        pkt_dev->idle_acc += ktime_to_ns(ktime_sub(end_time, start_time));
-       pkt_dev->next_tx = ktime_add_ns(end_time, pkt_dev->delay);
+       pkt_dev->next_tx = ktime_add_ns(spin_until, pkt_dev->delay);
 }
 
 static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev)
index f8abf68e3988f7cd5b4a83eb6a18b3ae25d52afd..34432b4e96bb288931e8b6ebf2d8d78b5c6589c5 100644 (file)
@@ -482,22 +482,22 @@ EXPORT_SYMBOL(consume_skb);
  *     reference count dropping and cleans up the skbuff as if it
  *     just came from __alloc_skb().
  */
-int skb_recycle_check(struct sk_buff *skb, int skb_size)
+bool skb_recycle_check(struct sk_buff *skb, int skb_size)
 {
        struct skb_shared_info *shinfo;
 
        if (irqs_disabled())
-               return 0;
+               return false;
 
        if (skb_is_nonlinear(skb) || skb->fclone != SKB_FCLONE_UNAVAILABLE)
-               return 0;
+               return false;
 
        skb_size = SKB_DATA_ALIGN(skb_size + NET_SKB_PAD);
        if (skb_end_pointer(skb) - skb->head < skb_size)
-               return 0;
+               return false;
 
        if (skb_shared(skb) || skb_cloned(skb))
-               return 0;
+               return false;
 
        skb_release_head_state(skb);
 
@@ -509,7 +509,7 @@ int skb_recycle_check(struct sk_buff *skb, int skb_size)
        skb->data = skb->head + NET_SKB_PAD;
        skb_reset_tail_pointer(skb);
 
-       return 1;
+       return true;
 }
 EXPORT_SYMBOL(skb_recycle_check);
 
@@ -532,6 +532,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
        new->ip_summed          = old->ip_summed;
        skb_copy_queue_mapping(new, old);
        new->priority           = old->priority;
+       new->deliver_no_wcard   = old->deliver_no_wcard;
 #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
        new->ipvs_property      = old->ipvs_property;
 #endif
@@ -569,7 +570,6 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
        C(len);
        C(data_len);
        C(mac_len);
-       C(rxhash);
        n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
        n->cloned = 1;
        n->nohdr = 0;
@@ -2965,6 +2965,34 @@ int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer)
 }
 EXPORT_SYMBOL_GPL(skb_cow_data);
 
+static void sock_rmem_free(struct sk_buff *skb)
+{
+       struct sock *sk = skb->sk;
+
+       atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
+}
+
+/*
+ * Note: We dont mem charge error packets (no sk_forward_alloc changes)
+ */
+int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
+{
+       if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
+           (unsigned)sk->sk_rcvbuf)
+               return -ENOMEM;
+
+       skb_orphan(skb);
+       skb->sk = sk;
+       skb->destructor = sock_rmem_free;
+       atomic_add(skb->truesize, &sk->sk_rmem_alloc);
+
+       skb_queue_tail(&sk->sk_error_queue, skb);
+       if (!sock_flag(sk, SOCK_DEAD))
+               sk->sk_data_ready(sk, skb->len);
+       return 0;
+}
+EXPORT_SYMBOL(sock_queue_err_skb);
+
 void skb_tstamp_tx(struct sk_buff *orig_skb,
                struct skb_shared_hwtstamps *hwtstamps)
 {
@@ -2996,7 +3024,9 @@ void skb_tstamp_tx(struct sk_buff *orig_skb,
        memset(serr, 0, sizeof(*serr));
        serr->ee.ee_errno = ENOMSG;
        serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;
+
        err = sock_queue_err_skb(sk, skb);
+
        if (err)
                kfree_skb(skb);
 }
index 8e3a1fd938ab3c2f18a8f9884598858b2020cd88..7c3a7d19124995fd89034a4db2254566aab4cdfd 100644 (file)
@@ -303,7 +303,7 @@ config ARPD
          If unsure, say N.
 
 config SYN_COOKIES
-       bool "IP: TCP syncookie support (disabled per default)"
+       bool "IP: TCP syncookie support"
        ---help---
          Normal TCP/IP networking is open to an attack known as "SYN
          flooding". This denial-of-service attack prevents legitimate remote
@@ -328,13 +328,13 @@ config SYN_COOKIES
          server is really overloaded. If this happens frequently better turn
          them off.
 
-         If you say Y here, note that SYN cookies aren't enabled by default;
-         you can enable them by saying Y to "/proc file system support" and
+         If you say Y here, you can disable SYN cookies at run time by
+         saying Y to "/proc file system support" and
          "Sysctl support" below and executing the command
 
-         echo 1 >/proc/sys/net/ipv4/tcp_syncookies
+         echo 0 > /proc/sys/net/ipv4/tcp_syncookies
 
-         at boot time after the /proc file system has been mounted.
+         after the /proc file system has been mounted.
 
          If unsure, say N.
 
index 9a4a6c96cb0d634414691da197bf9e337fe18f81..041d41df1224eec36f214cd649467e423be5de96 100644 (file)
@@ -873,8 +873,10 @@ int ip_append_data(struct sock *sk,
            !exthdrlen)
                csummode = CHECKSUM_PARTIAL;
 
+       skb = skb_peek_tail(&sk->sk_write_queue);
+
        inet->cork.length += length;
-       if (((length> mtu) || !skb_queue_empty(&sk->sk_write_queue)) &&
+       if (((length > mtu) || (skb && skb_is_gso(skb))) &&
            (sk->sk_protocol == IPPROTO_UDP) &&
            (rt->u.dst.dev->features & NETIF_F_UFO)) {
                err = ip_ufo_append_data(sk, getfrag, from, length, hh_len,
@@ -892,7 +894,7 @@ int ip_append_data(struct sock *sk,
         * adding appropriate IP header.
         */
 
-       if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL)
+       if (!skb)
                goto alloc_new_skb;
 
        while (length > 0) {
@@ -1121,7 +1123,8 @@ ssize_t   ip_append_page(struct sock *sk, struct page *page,
                return -EINVAL;
 
        inet->cork.length += size;
-       if ((sk->sk_protocol == IPPROTO_UDP) &&
+       if ((size + skb->len > mtu) &&
+           (sk->sk_protocol == IPPROTO_UDP) &&
            (rt->u.dst.dev->features & NETIF_F_UFO)) {
                skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
                skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
index 856123fe32f98c97e3364a322fe9899d4b8d1359..757f25eb9b4b2404ebebc6c4422b4ad1693ea227 100644 (file)
@@ -267,8 +267,10 @@ static void __net_exit ipmr_rules_exit(struct net *net)
 {
        struct mr_table *mrt, *next;
 
-       list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list)
+       list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list) {
+               list_del(&mrt->list);
                kfree(mrt);
+       }
        fib_rules_unregister(net->ipv4.mr_rules_ops);
 }
 #else
index 5c24db4a3c91a54d7d6b3b86e8d4d906999d7d76..9f6b22206c527263fea9c56727967afd92b773bb 100644 (file)
@@ -347,7 +347,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
                                               { .sport = th->dest,
                                                 .dport = th->source } } };
                security_req_classify_flow(req, &fl);
-               if (ip_route_output_key(&init_net, &rt, &fl)) {
+               if (ip_route_output_key(sock_net(sk), &rt, &fl)) {
                        reqsk_free(req);
                        goto out;
                }
index c209e054a634ed5b07f9b6d8374006887a2c2085..377bc93493712f3037ae1cb2e12eb6e421366a4e 100644 (file)
@@ -126,8 +126,8 @@ static void hybla_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
                 * calculate 2^fract in a <<7 value.
                 */
                is_slowstart = 1;
-               increment = ((1 << ca->rho) * hybla_fraction(rho_fractions))
-                       - 128;
+               increment = ((1 << min(ca->rho, 16U)) *
+                       hybla_fraction(rho_fractions)) - 128;
        } else {
                /*
                 * congestion avoidance
index 3e6dafcb1071663c2e0590da7c379b6b324bbe0f..548d575e6cc684673ef9c7a7a613e2f444ec509c 100644 (file)
@@ -2639,7 +2639,7 @@ static void DBGUNDO(struct sock *sk, const char *msg)
        if (sk->sk_family == AF_INET) {
                printk(KERN_DEBUG "Undo %s %pI4/%u c%u l%u ss%u/%u p%u\n",
                       msg,
-                      &inet->daddr, ntohs(inet->dport),
+                      &inet->inet_daddr, ntohs(inet->inet_dport),
                       tp->snd_cwnd, tcp_left_out(tp),
                       tp->snd_ssthresh, tp->prior_ssthresh,
                       tp->packets_out);
@@ -2649,7 +2649,7 @@ static void DBGUNDO(struct sock *sk, const char *msg)
                struct ipv6_pinfo *np = inet6_sk(sk);
                printk(KERN_DEBUG "Undo %s %pI6/%u c%u l%u ss%u/%u p%u\n",
                       msg,
-                      &np->daddr, ntohs(inet->dport),
+                      &np->daddr, ntohs(inet->inet_dport),
                       tp->snd_cwnd, tcp_left_out(tp),
                       tp->snd_ssthresh, tp->prior_ssthresh,
                       tp->packets_out);
index 202cf09c4cd4be9f8a556d2740a51ca4bba96e56..fe193e53af447f49fe05a8cba7b495c38f421be2 100644 (file)
@@ -1555,6 +1555,7 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
 #endif
 
        if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
+               sock_rps_save_rxhash(sk, skb->rxhash);
                TCP_CHECK_TIMER(sk);
                if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) {
                        rsk = sk;
@@ -1579,7 +1580,9 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
                        }
                        return 0;
                }
-       }
+       } else
+               sock_rps_save_rxhash(sk, skb->rxhash);
+
 
        TCP_CHECK_TIMER(sk);
        if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) {
@@ -1672,8 +1675,6 @@ process:
 
        skb->dev = NULL;
 
-       sock_rps_save_rxhash(sk, skb->rxhash);
-
        bh_lock_sock_nested(sk);
        ret = 0;
        if (!sock_owned_by_user(sk)) {
index 58585748bdac7cc7be011c090409e37f492573a4..eec4ff456e332e0b086d5451478fa5874213e0d1 100644 (file)
@@ -633,9 +633,9 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
        if (!inet->recverr) {
                if (!harderr || sk->sk_state != TCP_ESTABLISHED)
                        goto out;
-       } else {
+       } else
                ip_icmp_error(sk, skb, err, uh->dest, info, (u8 *)(uh+1));
-       }
+
        sk->sk_err = err;
        sk->sk_error_report(sk);
 out:
index ce7992982557d8cc28037bbb6388ede8f0e62d46..03e62f94ff8efb35a5c865322d72e623b539eeef 100644 (file)
@@ -483,7 +483,7 @@ route_done:
                              np->tclass, NULL, &fl, (struct rt6_info*)dst,
                              MSG_DONTWAIT, np->dontfrag);
        if (err) {
-               ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
+               ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS);
                ip6_flush_pending_frames(sk);
                goto out_put;
        }
@@ -565,7 +565,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
                                np->dontfrag);
 
        if (err) {
-               ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
+               ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS);
                ip6_flush_pending_frames(sk);
                goto out_put;
        }
index 073071f2b75b500207a9c14f823d1d50f56b2aec..66078dad7fe8c353bd4de83115dc4eee73ba978f 100644 (file)
@@ -120,7 +120,7 @@ static void mroute_clean_tables(struct mr6_table *mrt);
 static void ipmr_expire_process(unsigned long arg);
 
 #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
-#define ip6mr_for_each_table(mrt, met) \
+#define ip6mr_for_each_table(mrt, net) \
        list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list)
 
 static struct mr6_table *ip6mr_get_table(struct net *net, u32 id)
@@ -254,8 +254,10 @@ static void __net_exit ip6mr_rules_exit(struct net *net)
 {
        struct mr6_table *mrt, *next;
 
-       list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list)
+       list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) {
+               list_del(&mrt->list);
                ip6mr_free_table(mrt);
+       }
        fib_rules_unregister(net->ipv6.mr6_rules_ops);
 }
 #else
index 59f1881968c70aad15b0296cf6400c6b0b3e49cb..ab1622d7d409f0a853a956ee06db49aad930050a 100644 (file)
@@ -1356,7 +1356,10 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size)
                     IPV6_TLV_PADN, 0 };
 
        /* we assume size > sizeof(ra) here */
-       skb = sock_alloc_send_skb(sk, size + LL_ALLOCATED_SPACE(dev), 1, &err);
+       size += LL_ALLOCATED_SPACE(dev);
+       /* limit our allocations to order-0 page */
+       size = min_t(int, size, SKB_MAX_ORDER(0, 0));
+       skb = sock_alloc_send_skb(sk, size, 1, &err);
 
        if (!skb)
                return NULL;
index 0abdc242ddb76029cc2f6a52bed1bbdea2189364..2efef52fb4616fb5d598026a35ecf1d76aba0fd8 100644 (file)
@@ -586,6 +586,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
                src_addr = solicited_addr;
                if (ifp->flags & IFA_F_OPTIMISTIC)
                        override = 0;
+               inc_opt |= ifp->idev->cnf.force_tllao;
                in6_ifa_put(ifp);
        } else {
                if (ipv6_dev_get_saddr(dev_net(dev), dev, daddr,
@@ -599,7 +600,6 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
        icmp6h.icmp6_solicited = solicited;
        icmp6h.icmp6_override = override;
 
-       inc_opt |= ifp->idev->cnf.force_tllao;
        __ndisc_send(dev, neigh, daddr, src_addr,
                     &icmp6h, solicited_addr,
                     inc_opt ? ND_OPT_TARGET_LL_ADDR : 0);
index 294cbe8b0725f7ad9f58690f2b511829d391a672..252d76199c41e7589b85416bef1145e407239126 100644 (file)
@@ -814,7 +814,7 @@ struct dst_entry * ip6_route_output(struct net *net, struct sock *sk,
 {
        int flags = 0;
 
-       if (fl->oif || rt6_need_strict(&fl->fl6_dst))
+       if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl->fl6_dst))
                flags |= RT6_LOOKUP_F_IFACE;
 
        if (!ipv6_addr_any(&fl->fl6_src))
index c163d0a149f49be05b07fa879562f2d821004beb..98258b7341e356111bef3674f56b3a6adeee5961 100644 (file)
@@ -332,14 +332,16 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
                IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
 
        spin_unlock(&local->ampdu_lock);
-       spin_unlock_bh(&sta->lock);
 
-       /* send an addBA request */
+       /* prepare tid data */
        sta->ampdu_mlme.dialog_token_allocator++;
        sta->ampdu_mlme.tid_tx[tid]->dialog_token =
                        sta->ampdu_mlme.dialog_token_allocator;
        sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num;
 
+       spin_unlock_bh(&sta->lock);
+
+       /* send AddBA request */
        ieee80211_send_addba_request(sdata, pubsta->addr, tid,
                         sta->ampdu_mlme.tid_tx[tid]->dialog_token,
                         sta->ampdu_mlme.tid_tx[tid]->ssn,
index 5d218c530a4efae71826f33ac3b7868d741dd897..32be11e4c4d92dbe9d34d8cae84d7e0a482e8882 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/nl80211.h>
 #include "ieee80211_i.h"
 
-enum ieee80211_chan_mode
+static enum ieee80211_chan_mode
 __ieee80211_get_channel_mode(struct ieee80211_local *local,
                             struct ieee80211_sub_if_data *ignore)
 {
index 4f2271316650d98f08de2f1c460b4b8fb283d752..9c1da0809160215c4178358f8f17be8c6d774e27 100644 (file)
@@ -349,7 +349,7 @@ static inline int drv_get_survey(struct ieee80211_local *local, int idx,
                                struct survey_info *survey)
 {
        int ret = -EOPNOTSUPP;
-       if (local->ops->conf_tx)
+       if (local->ops->get_survey)
                ret = local->ops->get_survey(&local->hw, idx, survey);
        /* trace_drv_get_survey(local, idx, survey, ret); */
        return ret;
index 0839c4e8fd2e35b2042e968a9eddebb1e49dc99e..f803f8b72a930dd58b60ae362ea1b7117f1247b2 100644 (file)
@@ -1692,14 +1692,52 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
                        rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
                        break;
                case IEEE80211_STYPE_ACTION:
-                       if (mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT)
+                       switch (mgmt->u.action.category) {
+                       case WLAN_CATEGORY_BACK: {
+                               struct ieee80211_local *local = sdata->local;
+                               int len = skb->len;
+                               struct sta_info *sta;
+
+                               rcu_read_lock();
+                               sta = sta_info_get(sdata, mgmt->sa);
+                               if (!sta) {
+                                       rcu_read_unlock();
+                                       break;
+                               }
+
+                               local_bh_disable();
+
+                               switch (mgmt->u.action.u.addba_req.action_code) {
+                               case WLAN_ACTION_ADDBA_REQ:
+                                       if (len < (IEEE80211_MIN_ACTION_SIZE +
+                                                  sizeof(mgmt->u.action.u.addba_req)))
+                                               break;
+                                       ieee80211_process_addba_request(local, sta, mgmt, len);
+                                       break;
+                               case WLAN_ACTION_ADDBA_RESP:
+                                       if (len < (IEEE80211_MIN_ACTION_SIZE +
+                                                  sizeof(mgmt->u.action.u.addba_resp)))
+                                               break;
+                                       ieee80211_process_addba_resp(local, sta, mgmt, len);
+                                       break;
+                               case WLAN_ACTION_DELBA:
+                                       if (len < (IEEE80211_MIN_ACTION_SIZE +
+                                                  sizeof(mgmt->u.action.u.delba)))
+                                               break;
+                                       ieee80211_process_delba(sdata, sta, mgmt, len);
+                                       break;
+                               }
+                               local_bh_enable();
+                               rcu_read_unlock();
                                break;
-
-                       ieee80211_sta_process_chanswitch(sdata,
-                                       &mgmt->u.action.u.chan_switch.sw_elem,
-                                       (void *)ifmgd->associated->priv,
-                                       rx_status->mactime);
-                       break;
+                               }
+                       case WLAN_CATEGORY_SPECTRUM_MGMT:
+                               ieee80211_sta_process_chanswitch(sdata,
+                                               &mgmt->u.action.u.chan_switch.sw_elem,
+                                               (void *)ifmgd->associated->priv,
+                                               rx_status->mactime);
+                               break;
+                       }
                }
                mutex_unlock(&ifmgd->mtx);
 
@@ -1722,9 +1760,45 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
        mutex_unlock(&ifmgd->mtx);
 
        if (skb->len >= 24 + 2 /* mgmt + deauth reason */ &&
-           (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH)
-               cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
+           (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH) {
+               struct ieee80211_local *local = sdata->local;
+               struct ieee80211_work *wk;
+
+               mutex_lock(&local->work_mtx);
+               list_for_each_entry(wk, &local->work_list, list) {
+                       if (wk->sdata != sdata)
+                               continue;
+
+                       if (wk->type != IEEE80211_WORK_ASSOC)
+                               continue;
+
+                       if (memcmp(mgmt->bssid, wk->filter_ta, ETH_ALEN))
+                               continue;
+                       if (memcmp(mgmt->sa, wk->filter_ta, ETH_ALEN))
+                               continue;
 
+                       /*
+                        * Printing the message only here means we can't
+                        * spuriously print it, but it also means that it
+                        * won't be printed when the frame comes in before
+                        * we even tried to associate or in similar cases.
+                        *
+                        * Ultimately, I suspect cfg80211 should print the
+                        * messages instead.
+                        */
+                       printk(KERN_DEBUG
+                              "%s: deauthenticated from %pM (Reason: %u)\n",
+                              sdata->name, mgmt->bssid,
+                              le16_to_cpu(mgmt->u.deauth.reason_code));
+
+                       list_del_rcu(&wk->list);
+                       free_work(wk);
+                       break;
+               }
+               mutex_unlock(&local->work_mtx);
+
+               cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
+       }
  out:
        kfree_skb(skb);
 }
index 6e2a7bcd8cb888ce24be03cc56cb2516ca95fade..be9abc2e6348943753aab8daae864b561adce82f 100644 (file)
@@ -1818,17 +1818,26 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames)
                return RX_CONTINUE;
 
        if (ieee80211_is_back_req(bar->frame_control)) {
+               struct {
+                       __le16 control, start_seq_num;
+               } __packed bar_data;
+
                if (!rx->sta)
                        return RX_DROP_MONITOR;
+
+               if (skb_copy_bits(skb, offsetof(struct ieee80211_bar, control),
+                                 &bar_data, sizeof(bar_data)))
+                       return RX_DROP_MONITOR;
+
                spin_lock(&rx->sta->lock);
-               tid = le16_to_cpu(bar->control) >> 12;
+               tid = le16_to_cpu(bar_data.control) >> 12;
                if (!rx->sta->ampdu_mlme.tid_active_rx[tid]) {
                        spin_unlock(&rx->sta->lock);
                        return RX_DROP_MONITOR;
                }
                tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid];
 
-               start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4;
+               start_seq_num = le16_to_cpu(bar_data.start_seq_num) >> 4;
 
                /* reset session timer */
                if (tid_agg_rx->timeout)
@@ -1935,6 +1944,9 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                if (len < IEEE80211_MIN_ACTION_SIZE + 1)
                        break;
 
+               if (sdata->vif.type == NL80211_IFTYPE_STATION)
+                       return ieee80211_sta_rx_mgmt(sdata, rx->skb);
+
                switch (mgmt->u.action.u.addba_req.action_code) {
                case WLAN_ACTION_ADDBA_REQ:
                        if (len < (IEEE80211_MIN_ACTION_SIZE +
index be3d4a698692d1ce958b695c1e1676297b1d15cd..b025dc7bb0fd4e1decb356709cb3ac5d3163db58 100644 (file)
@@ -715,7 +715,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
        struct ieee80211_rx_status *rx_status;
        struct ieee80211_mgmt *mgmt;
        struct ieee80211_work *wk;
-       enum work_action rma;
+       enum work_action rma = WORK_ACT_NONE;
        u16 fc;
 
        rx_status = (struct ieee80211_rx_status *) skb->cb;
index 7b048a35ca5837368e4ace101a57564eacbb51fc..94d72e85a475ae094d14f8df5f4f54a936f0db15 100644 (file)
@@ -1045,12 +1045,12 @@ static void pep_sock_unhash(struct sock *sk)
        lock_sock(sk);
        if ((1 << sk->sk_state) & ~(TCPF_CLOSE|TCPF_LISTEN)) {
                skparent = pn->listener;
-               sk_del_node_init(sk);
                release_sock(sk);
 
-               sk = skparent;
                pn = pep_sk(skparent);
-               lock_sock(sk);
+               lock_sock(skparent);
+               sk_del_node_init(sk);
+               sk = skparent;
        }
        /* Unhash a listening sock only when it is closed
         * and all of its active connected pipes are closed. */
index 10ed0d55f75948702837e2154327876a521d3d8b..f68832798db224d6abffcc08f4ad494fa2b3bc17 100644 (file)
@@ -475,6 +475,7 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id,
        err = rds_ib_setup_qp(conn);
        if (err) {
                rds_ib_conn_error(conn, "rds_ib_setup_qp failed (%d)\n", err);
+               mutex_unlock(&conn->c_cm_lock);
                goto out;
        }
 
index a9d951b4fbaec49dfea00dc6494639b0d32403ac..b5dd6ac39be86b87afc1bd7761971a11550e572f 100644 (file)
@@ -452,6 +452,7 @@ int rds_iw_cm_handle_connect(struct rdma_cm_id *cm_id,
        err = rds_iw_setup_qp(conn);
        if (err) {
                rds_iw_conn_error(conn, "rds_iw_setup_qp failed (%d)\n", err);
+               mutex_unlock(&conn->c_cm_lock);
                goto out;
        }
 
index d885ba311564d9a766fce6eac37edbaf0ed82b71..570949417f388735e93bf887294326a8f24aa534 100644 (file)
@@ -159,6 +159,9 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
                        iph->daddr = new_addr;
 
                csum_replace4(&iph->check, addr, new_addr);
+       } else if ((iph->frag_off & htons(IP_OFFSET)) ||
+                  iph->protocol != IPPROTO_ICMP) {
+               goto out;
        }
 
        ihl = iph->ihl * 4;
@@ -247,6 +250,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
                break;
        }
 
+out:
        return action;
 
 drop:
index fdbd0b7bd840715c41626abfa74831ddcd9ef2fb..50e3d945e1f48a12b8a499aeb07d50f3d286017a 100644 (file)
@@ -125,7 +125,7 @@ static int tcf_pedit(struct sk_buff *skb, struct tc_action *a,
 {
        struct tcf_pedit *p = a->priv;
        int i, munged = 0;
-       u8 *pptr;
+       unsigned int off;
 
        if (!(skb->tc_verd & TC_OK2MUNGE)) {
                /* should we set skb->cloned? */
@@ -134,7 +134,7 @@ static int tcf_pedit(struct sk_buff *skb, struct tc_action *a,
                }
        }
 
-       pptr = skb_network_header(skb);
+       off = skb_network_offset(skb);
 
        spin_lock(&p->tcf_lock);
 
@@ -144,17 +144,17 @@ static int tcf_pedit(struct sk_buff *skb, struct tc_action *a,
                struct tc_pedit_key *tkey = p->tcfp_keys;
 
                for (i = p->tcfp_nkeys; i > 0; i--, tkey++) {
-                       u32 *ptr;
+                       u32 *ptr, _data;
                        int offset = tkey->off;
 
                        if (tkey->offmask) {
-                               if (skb->len > tkey->at) {
-                                        char *j = pptr + tkey->at;
-                                        offset += ((*j & tkey->offmask) >>
-                                                  tkey->shift);
-                               } else {
+                               char *d, _d;
+
+                               d = skb_header_pointer(skb, off + tkey->at, 1,
+                                                      &_d);
+                               if (!d)
                                        goto bad;
-                               }
+                               offset += (*d & tkey->offmask) >> tkey->shift;
                        }
 
                        if (offset % 4) {
@@ -169,9 +169,13 @@ static int tcf_pedit(struct sk_buff *skb, struct tc_action *a,
                                goto bad;
                        }
 
-                       ptr = (u32 *)(pptr+offset);
+                       ptr = skb_header_pointer(skb, off + offset, 4, &_data);
+                       if (!ptr)
+                               goto bad;
                        /* just do it, baby */
                        *ptr = ((*ptr & tkey->mask) ^ tkey->val);
+                       if (ptr == &_data)
+                               skb_store_bits(skb, off + offset, ptr, 4);
                        munged++;
                }
 
index 96275422c619e9d2a4e5eecd4fa8b433a526c8ab..4f522143811e467fe70e7e4b13db47f979b11b8a 100644 (file)
@@ -98,11 +98,11 @@ static int u32_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_re
 {
        struct {
                struct tc_u_knode *knode;
-               u8                *ptr;
+               unsigned int      off;
        } stack[TC_U32_MAXDEPTH];
 
        struct tc_u_hnode *ht = (struct tc_u_hnode*)tp->root;
-       u8 *ptr = skb_network_header(skb);
+       unsigned int off = skb_network_offset(skb);
        struct tc_u_knode *n;
        int sdepth = 0;
        int off2 = 0;
@@ -134,8 +134,14 @@ next_knode:
 #endif
 
                for (i = n->sel.nkeys; i>0; i--, key++) {
-
-                       if ((*(__be32*)(ptr+key->off+(off2&key->offmask))^key->val)&key->mask) {
+                       unsigned int toff;
+                       __be32 *data, _data;
+
+                       toff = off + key->off + (off2 & key->offmask);
+                       data = skb_header_pointer(skb, toff, 4, &_data);
+                       if (!data)
+                               goto out;
+                       if ((*data ^ key->val) & key->mask) {
                                n = n->next;
                                goto next_knode;
                        }
@@ -174,29 +180,45 @@ check_terminal:
                if (sdepth >= TC_U32_MAXDEPTH)
                        goto deadloop;
                stack[sdepth].knode = n;
-               stack[sdepth].ptr = ptr;
+               stack[sdepth].off = off;
                sdepth++;
 
                ht = n->ht_down;
                sel = 0;
-               if (ht->divisor)
-                       sel = ht->divisor&u32_hash_fold(*(__be32*)(ptr+n->sel.hoff), &n->sel,n->fshift);
-
+               if (ht->divisor) {
+                       __be32 *data, _data;
+
+                       data = skb_header_pointer(skb, off + n->sel.hoff, 4,
+                                                 &_data);
+                       if (!data)
+                               goto out;
+                       sel = ht->divisor & u32_hash_fold(*data, &n->sel,
+                                                         n->fshift);
+               }
                if (!(n->sel.flags&(TC_U32_VAROFFSET|TC_U32_OFFSET|TC_U32_EAT)))
                        goto next_ht;
 
                if (n->sel.flags&(TC_U32_OFFSET|TC_U32_VAROFFSET)) {
                        off2 = n->sel.off + 3;
-                       if (n->sel.flags&TC_U32_VAROFFSET)
-                               off2 += ntohs(n->sel.offmask & *(__be16*)(ptr+n->sel.offoff)) >>n->sel.offshift;
+                       if (n->sel.flags & TC_U32_VAROFFSET) {
+                               __be16 *data, _data;
+
+                               data = skb_header_pointer(skb,
+                                                         off + n->sel.offoff,
+                                                         2, &_data);
+                               if (!data)
+                                       goto out;
+                               off2 += ntohs(n->sel.offmask & *data) >>
+                                       n->sel.offshift;
+                       }
                        off2 &= ~3;
                }
                if (n->sel.flags&TC_U32_EAT) {
-                       ptr += off2;
+                       off += off2;
                        off2 = 0;
                }
 
-               if (ptr < skb_tail_pointer(skb))
+               if (off < skb->len)
                        goto next_ht;
        }
 
@@ -204,9 +226,10 @@ check_terminal:
        if (sdepth--) {
                n = stack[sdepth].knode;
                ht = n->ht_up;
-               ptr = stack[sdepth].ptr;
+               off = stack[sdepth].off;
                goto check_terminal;
        }
+out:
        return -1;
 
 deadloop:
index 3415b6ce1c0a5b1116a4e23cc710c0b8f5b0f8d5..807643bdcbac30817edecfb4185dd45826b750eb 100644 (file)
@@ -449,6 +449,7 @@ static __init void teql_master_setup(struct net_device *dev)
        dev->tx_queue_len       = 100;
        dev->flags              = IFF_NOARP;
        dev->hard_header_len    = LL_MAX_HEADER;
+       dev->priv_flags         &= ~IFF_XMIT_DST_RELEASE;
 }
 
 static LIST_HEAD(master_dev_list);
index 6a329158bdfaa14de3891194e0c98ae70f4f1834..a3cca0a94346319dec462ef7ef2fb7df2265945e 100644 (file)
@@ -95,13 +95,13 @@ resume:
                        goto error_nolock;
                }
 
-               dst = dst_pop(dst);
+               dst = skb_dst_pop(skb);
                if (!dst) {
                        XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTERROR);
                        err = -EHOSTUNREACH;
                        goto error_nolock;
                }
-               skb_dst_set(skb, dst);
+               skb_dst_set_noref(skb, dst);
                x = dst->xfrm;
        } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL));
 
index d965a2bad8d3b9cf993f72eaa372fb791642f3bc..af1c173be4ad88906d55d7efa24fb47fcd0cf19d 100644 (file)
@@ -2153,6 +2153,7 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
                return 0;
        }
 
+       skb_dst_force(skb);
        dst = skb_dst(skb);
 
        res = xfrm_lookup(net, &dst, &fl, NULL, 0) == 0;
@@ -2299,7 +2300,8 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
                        return 0;
                if (xdst->xfrm_genid != dst->xfrm->genid)
                        return 0;
-               if (xdst->policy_genid != atomic_read(&xdst->pols[0]->genid))
+               if (xdst->num_pols > 0 &&
+                   xdst->policy_genid != atomic_read(&xdst->pols[0]->genid))
                        return 0;
 
                if (strict && fl &&