]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Merge branch 'vhost-net' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
authorDavid S. Miller <davem@davemloft.net>
Fri, 16 Jul 2010 19:41:44 +0000 (12:41 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 16 Jul 2010 19:41:44 +0000 (12:41 -0700)
61 files changed:
drivers/bluetooth/bluecard_cs.c
drivers/bluetooth/hci_bcsp.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/hysdn/hysdn_net.c
drivers/net/bonding/bond_alb.c
drivers/net/bonding/bond_main.c
drivers/net/cpmac.c
drivers/net/ixgbe/ixgbe_main.c
drivers/net/ll_temac_main.c
drivers/net/mv643xx_eth.c
drivers/net/ne.c
drivers/net/pcmcia/axnet_cs.c
drivers/net/pcmcia/smc91c92_cs.c
drivers/net/phy/lxt.c
drivers/net/qlge/qlge_main.c
drivers/net/r8169.c
drivers/net/s2io.c
drivers/net/s2io.h
drivers/net/sb1250-mac.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/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/hif_usb.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-sta.h
include/linux/ethtool.h
include/linux/mv643xx_eth.h
include/linux/net.h
include/linux/netdevice.h
include/net/sch_generic.h
include/net/sock.h
include/net/xfrm.h
net/bluetooth/bnep/netdev.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_event.c
net/bluetooth/l2cap.c
net/bridge/br_multicast.c
net/bridge/br_netfilter.c
net/core/dev.c
net/core/ethtool.c
net/core/neighbour.c
net/dsa/Kconfig
net/ipv4/ipmr.c
net/ipv4/tcp.c
net/ipv4/xfrm4_policy.c
net/ipv6/ndisc.c
net/ipv6/netfilter/ip6t_REJECT.c
net/ipv6/xfrm6_policy.c
net/phonet/pep.c
net/sched/act_nat.c
net/xfrm/xfrm_policy.c

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 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 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 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 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 ce30c62a97f70bd08f3d4bdbcb6009dda523ff0e..7b5d9764f317c3c776712009dde301c27d9c3b99 100644 (file)
@@ -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);
@@ -6023,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);
@@ -6032,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 52dcc84956477059e44161a00fea68fa5f2e5c1c..6474c4973d3ad977542ba53529ed9f0165cd21d6 100644 (file)
@@ -964,7 +964,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
        np = of_parse_phandle(op->dev.of_node, "llink-connected", 0);
        if (!np) {
                dev_err(&op->dev, "could not find DMA node\n");
-               goto nodev;
+               goto err_iounmap;
        }
 
        /* Setup the DMA register accesses, could be DCR or memory mapped */
@@ -978,7 +978,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
                        dev_dbg(&op->dev, "MEM base: %p\n", lp->sdma_regs);
                } else {
                        dev_err(&op->dev, "unable to map DMA registers\n");
-                       goto nodev;
+                       goto err_iounmap;
                }
        }
 
@@ -987,7 +987,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
        if ((lp->rx_irq == NO_IRQ) || (lp->tx_irq == NO_IRQ)) {
                dev_err(&op->dev, "could not determine irqs\n");
                rc = -ENOMEM;
-               goto nodev;
+               goto err_iounmap_2;
        }
 
        of_node_put(np); /* Finished with the DMA node; drop the reference */
@@ -997,7 +997,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
        if ((!addr) || (size != 6)) {
                dev_err(&op->dev, "could not find MAC address\n");
                rc = -ENODEV;
-               goto nodev;
+               goto err_iounmap_2;
        }
        temac_set_mac_address(ndev, (void *)addr);
 
@@ -1013,7 +1013,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
        rc = sysfs_create_group(&lp->dev->kobj, &temac_attr_group);
        if (rc) {
                dev_err(lp->dev, "Error creating sysfs files\n");
-               goto nodev;
+               goto err_iounmap_2;
        }
 
        rc = register_netdev(lp->ndev);
@@ -1026,6 +1026,11 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
 
  err_register_ndev:
        sysfs_remove_group(&lp->dev->kobj, &temac_attr_group);
+ err_iounmap_2:
+       if (lp->sdma_regs)
+               iounmap(lp->sdma_regs);
+ err_iounmap:
+       iounmap(lp->regs);
  nodev:
        free_netdev(ndev);
        ndev = NULL;
@@ -1044,6 +1049,9 @@ static int __devexit temac_of_remove(struct of_device *op)
                of_node_put(lp->phy_node);
        lp->phy_node = NULL;
        dev_set_drvdata(&op->dev, NULL);
+       iounmap(lp->regs);
+       if (lp->sdma_regs)
+               iounmap(lp->sdma_regs);
        free_netdev(ndev);
        return 0;
 }
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 b8e2923a1d69e4d50fe7c9e47620c69b42a1005f..1063093b3afc5cfd9cd1545b73cbbdd64db0ec12 100644 (file)
@@ -806,8 +806,10 @@ static int __init ne_drv_probe(struct platform_device *pdev)
                dev->base_addr = res->start;
                dev->irq = platform_get_irq(pdev, 0);
        } else {
-               if (this_dev < 0 || this_dev >= MAX_NE_CARDS)
+               if (this_dev < 0 || this_dev >= MAX_NE_CARDS) {
+                       free_netdev(dev);
                        return -EINVAL;
+               }
                dev->base_addr = io[this_dev];
                dev->irq = irq[this_dev];
                dev->mem_end = bad[this_dev];
index 5b3dfb4ab27985cd8823c08035dd066da36e4d1c..33525bf2a3d3e87f6769ac24c65861441c375dd3 100644 (file)
@@ -1168,6 +1168,7 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id)
        int interrupts, nr_serviced = 0, i;
        struct ei_device *ei_local;
        int handled = 0;
+       unsigned long flags;
 
        e8390_base = dev->base_addr;
        ei_local = netdev_priv(dev);
@@ -1176,7 +1177,7 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id)
         *      Protect the irq test too.
         */
         
-       spin_lock(&ei_local->page_lock);
+       spin_lock_irqsave(&ei_local->page_lock, flags);
 
        if (ei_local->irqlock) 
        {
@@ -1188,7 +1189,7 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id)
                           dev->name, inb_p(e8390_base + EN0_ISR),
                           inb_p(e8390_base + EN0_IMR));
 #endif
-               spin_unlock(&ei_local->page_lock);
+               spin_unlock_irqrestore(&ei_local->page_lock, flags);
                return IRQ_NONE;
        }
     
@@ -1261,7 +1262,7 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id)
        ei_local->irqlock = 0;
        outb_p(ENISR_ALL, e8390_base + EN0_IMR);
 
-       spin_unlock(&ei_local->page_lock);
+       spin_unlock_irqrestore(&ei_local->page_lock, flags);
        return IRQ_RETVAL(handled);
 }
 
index 64e6a84bbbbee840c0258a5d29736a033f34ab81..307cd1721e91271bb1b3762868f9dbcb6400d218 100644 (file)
@@ -1505,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 dbd0034537371c85a20db95daed608d553bf02b7..29c39ff85de56a0012ac8be5a50508aeab56e784 100644 (file)
@@ -226,6 +226,7 @@ module_exit(lxt_exit);
 static struct mdio_device_id lxt_tbl[] = {
        { 0x78100000, 0xfffffff0 },
        { 0x001378e0, 0xfffffff0 },
+       { 0x00137a10, 0xfffffff0 },
        { }
 };
 
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 96b6cfbf0a3a682b14216fa23a9e737a48973aaa..cdc6a5c2e70d81955efec9d3c633a593ef943b16 100644 (file)
@@ -1316,7 +1316,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
                { 0x7c800000, 0x28000000,       RTL_GIGA_MAC_VER_26 },
 
                /* 8168C family. */
-               { 0x7cf00000, 0x3ca00000,       RTL_GIGA_MAC_VER_24 },
+               { 0x7cf00000, 0x3cb00000,       RTL_GIGA_MAC_VER_24 },
                { 0x7cf00000, 0x3c900000,       RTL_GIGA_MAC_VER_23 },
                { 0x7cf00000, 0x3c800000,       RTL_GIGA_MAC_VER_18 },
                { 0x7c800000, 0x3c800000,       RTL_GIGA_MAC_VER_24 },
index 668327ccd8d0f8c29f60b974234efaa6a51e5859..1d37f0c310ca4bd91d715129f24a11356ad41fa1 100644 (file)
@@ -3130,7 +3130,6 @@ static void tx_intr_handler(struct fifo_info *fifo_data)
                pkt_cnt++;
 
                /* Updating the statistics block */
-               nic->dev->stats.tx_bytes += skb->len;
                swstats->mem_freed += skb->truesize;
                dev_kfree_skb_irq(skb);
 
@@ -4901,48 +4900,81 @@ static void s2io_updt_stats(struct s2io_nic *sp)
  *  Return value:
  *  pointer to the updated net_device_stats structure.
  */
-
 static struct net_device_stats *s2io_get_stats(struct net_device *dev)
 {
        struct s2io_nic *sp = netdev_priv(dev);
-       struct config_param *config = &sp->config;
        struct mac_info *mac_control = &sp->mac_control;
        struct stat_block *stats = mac_control->stats_info;
-       int i;
+       u64 delta;
 
        /* Configure Stats for immediate updt */
        s2io_updt_stats(sp);
 
-       /* Using sp->stats as a staging area, because reset (due to mtu
-          change, for example) will clear some hardware counters */
-       dev->stats.tx_packets += le32_to_cpu(stats->tmac_frms) -
-               sp->stats.tx_packets;
-       sp->stats.tx_packets = le32_to_cpu(stats->tmac_frms);
-
-       dev->stats.tx_errors += le32_to_cpu(stats->tmac_any_err_frms) -
-               sp->stats.tx_errors;
-       sp->stats.tx_errors = le32_to_cpu(stats->tmac_any_err_frms);
-
-       dev->stats.rx_errors += le64_to_cpu(stats->rmac_drop_frms) -
-               sp->stats.rx_errors;
-       sp->stats.rx_errors = le64_to_cpu(stats->rmac_drop_frms);
-
-       dev->stats.multicast = le32_to_cpu(stats->rmac_vld_mcst_frms) -
-               sp->stats.multicast;
-       sp->stats.multicast = le32_to_cpu(stats->rmac_vld_mcst_frms);
-
-       dev->stats.rx_length_errors = le64_to_cpu(stats->rmac_long_frms) -
-               sp->stats.rx_length_errors;
-       sp->stats.rx_length_errors = le64_to_cpu(stats->rmac_long_frms);
+       /* A device reset will cause the on-adapter statistics to be zero'ed.
+        * This can be done while running by changing the MTU.  To prevent the
+        * system from having the stats zero'ed, the driver keeps a copy of the
+        * last update to the system (which is also zero'ed on reset).  This
+        * enables the driver to accurately know the delta between the last
+        * update and the current update.
+        */
+       delta = ((u64) le32_to_cpu(stats->rmac_vld_frms_oflow) << 32 |
+               le32_to_cpu(stats->rmac_vld_frms)) - sp->stats.rx_packets;
+       sp->stats.rx_packets += delta;
+       dev->stats.rx_packets += delta;
+
+       delta = ((u64) le32_to_cpu(stats->tmac_frms_oflow) << 32 |
+               le32_to_cpu(stats->tmac_frms)) - sp->stats.tx_packets;
+       sp->stats.tx_packets += delta;
+       dev->stats.tx_packets += delta;
+
+       delta = ((u64) le32_to_cpu(stats->rmac_data_octets_oflow) << 32 |
+               le32_to_cpu(stats->rmac_data_octets)) - sp->stats.rx_bytes;
+       sp->stats.rx_bytes += delta;
+       dev->stats.rx_bytes += delta;
+
+       delta = ((u64) le32_to_cpu(stats->tmac_data_octets_oflow) << 32 |
+               le32_to_cpu(stats->tmac_data_octets)) - sp->stats.tx_bytes;
+       sp->stats.tx_bytes += delta;
+       dev->stats.tx_bytes += delta;
+
+       delta = le64_to_cpu(stats->rmac_drop_frms) - sp->stats.rx_errors;
+       sp->stats.rx_errors += delta;
+       dev->stats.rx_errors += delta;
+
+       delta = ((u64) le32_to_cpu(stats->tmac_any_err_frms_oflow) << 32 |
+               le32_to_cpu(stats->tmac_any_err_frms)) - sp->stats.tx_errors;
+       sp->stats.tx_errors += delta;
+       dev->stats.tx_errors += delta;
+
+       delta = le64_to_cpu(stats->rmac_drop_frms) - sp->stats.rx_dropped;
+       sp->stats.rx_dropped += delta;
+       dev->stats.rx_dropped += delta;
+
+       delta = le64_to_cpu(stats->tmac_drop_frms) - sp->stats.tx_dropped;
+       sp->stats.tx_dropped += delta;
+       dev->stats.tx_dropped += delta;
+
+       /* The adapter MAC interprets pause frames as multicast packets, but
+        * does not pass them up.  This erroneously increases the multicast
+        * packet count and needs to be deducted when the multicast frame count
+        * is queried.
+        */
+       delta = (u64) le32_to_cpu(stats->rmac_vld_mcst_frms_oflow) << 32 |
+               le32_to_cpu(stats->rmac_vld_mcst_frms);
+       delta -= le64_to_cpu(stats->rmac_pause_ctrl_frms);
+       delta -= sp->stats.multicast;
+       sp->stats.multicast += delta;
+       dev->stats.multicast += delta;
 
-       /* collect per-ring rx_packets and rx_bytes */
-       dev->stats.rx_packets = dev->stats.rx_bytes = 0;
-       for (i = 0; i < config->rx_ring_num; i++) {
-               struct ring_info *ring = &mac_control->rings[i];
+       delta = ((u64) le32_to_cpu(stats->rmac_usized_frms_oflow) << 32 |
+               le32_to_cpu(stats->rmac_usized_frms)) +
+               le64_to_cpu(stats->rmac_long_frms) - sp->stats.rx_length_errors;
+       sp->stats.rx_length_errors += delta;
+       dev->stats.rx_length_errors += delta;
 
-               dev->stats.rx_packets += ring->rx_packets;
-               dev->stats.rx_bytes += ring->rx_bytes;
-       }
+       delta = le64_to_cpu(stats->rmac_fcs_err_frms) - sp->stats.rx_crc_errors;
+       sp->stats.rx_crc_errors += delta;
+       dev->stats.rx_crc_errors += delta;
 
        return &dev->stats;
 }
@@ -7455,15 +7487,11 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
                }
        }
 
-       /* Updating statistics */
-       ring_data->rx_packets++;
        rxdp->Host_Control = 0;
        if (sp->rxd_mode == RXD_MODE_1) {
                int len = RXD_GET_BUFFER0_SIZE_1(rxdp->Control_2);
 
-               ring_data->rx_bytes += len;
                skb_put(skb, len);
-
        } else if (sp->rxd_mode == RXD_MODE_3B) {
                int get_block = ring_data->rx_curr_get_info.block_index;
                int get_off = ring_data->rx_curr_get_info.offset;
@@ -7472,7 +7500,6 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
                unsigned char *buff = skb_push(skb, buf0_len);
 
                struct buffAdd *ba = &ring_data->ba[get_block][get_off];
-               ring_data->rx_bytes += buf0_len + buf2_len;
                memcpy(buff, ba->ba_0, buf0_len);
                skb_put(skb, buf2_len);
        }
index 47c36e0994f5126bfda96887ddee0668442ce358..5e52c75892dfdb5bd878fb58b1fa715e72be5db3 100644 (file)
@@ -745,10 +745,6 @@ struct ring_info {
 
        /* Buffer Address store. */
        struct buffAdd **ba;
-
-       /* per-Ring statistics */
-       unsigned long rx_packets;
-       unsigned long rx_bytes;
 } ____cacheline_aligned;
 
 /* Fifo specific structure */
index 1f3acc3a5dfd0510d487334ac31b2a266eac13db..79eee3062083ab3b900da0c68e7df03cf5bffe9d 100644 (file)
@@ -2671,6 +2671,7 @@ static struct platform_driver sbmac_driver = {
        .remove = __exit_p(sbmac_remove),
        .driver = {
                .name = sbmac_string,
+               .owner  = THIS_MODULE,
        },
 };
 
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 1edb7a61983c05660aaec2624e596159ab2cd5c9..bb6b67f6b0cc731df707cbfc06006a2c8c39b198 100644 (file)
@@ -415,7 +415,7 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp)
 static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)
 {
        int err;
-       bool oom = false;
+       bool oom;
 
        do {
                if (vi->mergeable_rx_bufs)
@@ -425,10 +425,9 @@ static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)
                else
                        err = add_recvbuf_small(vi, gfp);
 
-               if (err < 0) {
-                       oom = true;
+               oom = err == -ENOMEM;
+               if (err < 0)
                        break;
-               }
                ++vi->num;
        } while (err > 0);
        if (unlikely(vi->num > vi->max))
@@ -563,7 +562,6 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
        struct virtnet_info *vi = netdev_priv(dev);
        int capacity;
 
-again:
        /* Free up any pending old buffers before queueing new ones. */
        free_old_xmit_skbs(vi);
 
@@ -572,14 +570,20 @@ again:
 
        /* This can happen with OOM and indirect buffers. */
        if (unlikely(capacity < 0)) {
-               netif_stop_queue(dev);
-               dev_warn(&dev->dev, "Unexpected full queue\n");
-               if (unlikely(!virtqueue_enable_cb(vi->svq))) {
-                       virtqueue_disable_cb(vi->svq);
-                       netif_start_queue(dev);
-                       goto again;
+               if (net_ratelimit()) {
+                       if (likely(capacity == -ENOMEM)) {
+                               dev_warn(&dev->dev,
+                                        "TX queue failure: out of memory\n");
+                       } else {
+                               dev->stats.tx_fifo_errors++;
+                               dev_warn(&dev->dev,
+                                        "Unexpected TX queue failure: %d\n",
+                                        capacity);
+                       }
                }
-               return NETDEV_TX_BUSY;
+               dev->stats.tx_dropped++;
+               kfree_skb(skb);
+               return NETDEV_TX_OK;
        }
        virtqueue_kick(vi->svq);
 
index b504bd56136210776fa0d31e87a5e00b687cb03b..fc8b2d7a0919d1cd9709f8c586f315bc5ec96e82 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)
@@ -4506,9 +4517,9 @@ vxge_starter(void)
        char version[32];
        snprintf(version, 32, "%s", DRV_VERSION);
 
-       printk(KERN_CRIT "%s: Copyright(c) 2002-2009 Neterion Inc\n",
+       printk(KERN_INFO "%s: Copyright(c) 2002-2009 Neterion Inc\n",
                VXGE_DRIVER_NAME);
-       printk(KERN_CRIT "%s: Driver version: %s\n",
+       printk(KERN_INFO "%s: Driver version: %s\n",
                        VXGE_DRIVER_NAME, version);
 
        verify_bandwidth();
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 77b359162d6cad0a408754fff4cc8b9af64d3063..23c15aa9fbd5167c51e80601eb5213c0dd144283 100644 (file)
@@ -730,13 +730,17 @@ static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev)
 
        /* RX */
        if (ath9k_hif_usb_alloc_rx_urbs(hif_dev) < 0)
-               goto err;
+               goto err_rx;
 
        /* Register Read */
        if (ath9k_hif_usb_alloc_reg_in_urb(hif_dev) < 0)
-               goto err;
+               goto err_reg;
 
        return 0;
+err_reg:
+       ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
+err_rx:
+       ath9k_hif_usb_dealloc_tx_urbs(hif_dev);
 err:
        return -ENOMEM;
 }
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 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 426e95567de388619dc120fe08178cab038667d9..5bbc5298ef96e50b29206ea3e5ea8ca408e22695 100644 (file)
@@ -1314,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);
 
@@ -1329,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 c2a453a1a9917e4e6bb9124b4af0318416ff0f34..dc43ebd1f1fd2eb3012c900456ec30b35b9fbbb5 100644 (file)
@@ -97,6 +97,17 @@ static inline void iwl_clear_driver_stations(struct iwl_priv *priv)
        spin_lock_irqsave(&priv->sta_lock, flags);
        memset(priv->stations, 0, sizeof(priv->stations));
        priv->num_stations = 0;
+
+       /*
+        * Remove all key information that is not stored as part of station
+        * information since mac80211 may not have had a
+        * chance to remove all the keys. When device is reconfigured by
+        * mac80211 after an error all keys will be reconfigured.
+        */
+       priv->ucode_key_table = 0;
+       priv->key_mapping_key = 0;
+       memset(priv->wep_keys, 0, sizeof(priv->wep_keys));
+
        spin_unlock_irqrestore(&priv->sta_lock, flags);
 }
 
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..b21e4054c12cb250f621b3baa9e1774d354bebcb 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.
@@ -2329,7 +2332,7 @@ do {                                                              \
 #endif
 
 #if defined(VERBOSE_DEBUG)
-#define netif_vdbg     netdev_dbg
+#define netif_vdbg     netif_dbg
 #else
 #define netif_vdbg(priv, type, dev, format, args...)           \
 ({                                                             \
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 731150d52799ecc5492b3590c3b7b5b34de09072..0a691ea7654aefb403e25039f08641691d3de74c 100644 (file)
@@ -1224,12 +1224,7 @@ static inline void sk_tx_queue_clear(struct sock *sk)
 
 static inline int sk_tx_queue_get(const struct sock *sk)
 {
-       return sk->sk_tx_queue_mapping;
-}
-
-static inline bool sk_tx_queue_recorded(const struct sock *sk)
-{
-       return (sk && sk->sk_tx_queue_mapping >= 0);
+       return sk ? sk->sk_tx_queue_mapping : -1;
 }
 
 static inline void sk_set_socket(struct sock *sk, struct socket *sock)
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 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 b10e3cdb08f87358ca64d0db8cf83c27f5ad624a..800b6b9fbbaefe15c90406e7631acd4e25b172b3 100644 (file)
@@ -358,6 +358,11 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
                acl->sec_level = sec_level;
                acl->auth_type = auth_type;
                hci_acl_connect(acl);
+       } else {
+               if (acl->sec_level < sec_level)
+                       acl->sec_level = sec_level;
+               if (acl->auth_type < auth_type)
+                       acl->auth_type = auth_type;
        }
 
        if (type == ACL_LINK)
index 6c57fc71c7e2d0df7c75daf1054901cf7ed8eee6..786b5de0bac42819ae3e207c942840a69f2c13da 100644 (file)
@@ -1049,6 +1049,8 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
        if (conn) {
                if (!ev->status)
                        conn->link_mode |= HCI_LM_AUTH;
+               else
+                       conn->sec_level = BT_SECURITY_LOW;
 
                clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
 
index 1b682a5aa0616911c2861b5d836c015230922faf..cf3c4073a8a655d6e9d8936cb61d30254224962f 100644 (file)
@@ -401,6 +401,11 @@ static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
        l2cap_send_sframe(pi, control);
 }
 
+static inline int __l2cap_no_conn_pending(struct sock *sk)
+{
+       return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
+}
+
 static void l2cap_do_start(struct sock *sk)
 {
        struct l2cap_conn *conn = l2cap_pi(sk)->conn;
@@ -409,12 +414,13 @@ static void l2cap_do_start(struct sock *sk)
                if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
                        return;
 
-               if (l2cap_check_security(sk)) {
+               if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
                        struct l2cap_conn_req req;
                        req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
                        req.psm  = l2cap_pi(sk)->psm;
 
                        l2cap_pi(sk)->ident = l2cap_get_ident(conn);
+                       l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
 
                        l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
                                        L2CAP_CONN_REQ, sizeof(req), &req);
@@ -464,12 +470,14 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
                }
 
                if (sk->sk_state == BT_CONNECT) {
-                       if (l2cap_check_security(sk)) {
+                       if (l2cap_check_security(sk) &&
+                                       __l2cap_no_conn_pending(sk)) {
                                struct l2cap_conn_req req;
                                req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
                                req.psm  = l2cap_pi(sk)->psm;
 
                                l2cap_pi(sk)->ident = l2cap_get_ident(conn);
+                               l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
 
                                l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
                                        L2CAP_CONN_REQ, sizeof(req), &req);
@@ -2912,7 +2920,6 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
                l2cap_pi(sk)->ident = 0;
                l2cap_pi(sk)->dcid = dcid;
                l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
-
                l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
 
                l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
@@ -4404,6 +4411,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
                                req.psm  = l2cap_pi(sk)->psm;
 
                                l2cap_pi(sk)->ident = l2cap_get_ident(conn);
+                               l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
 
                                l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
                                        L2CAP_CONN_REQ, sizeof(req), &req);
index 9d21d98ae5fa98cc5d187bc6ae9b6ceb85f294cc..27ae946363f16c6b709b5f4267e7ab5a574d5314 100644 (file)
@@ -99,6 +99,15 @@ static struct net_bridge_mdb_entry *__br_mdb_ip_get(
        return NULL;
 }
 
+static struct net_bridge_mdb_entry *br_mdb_ip_get(
+       struct net_bridge_mdb_htable *mdb, struct br_ip *dst)
+{
+       if (!mdb)
+               return NULL;
+
+       return __br_mdb_ip_get(mdb, dst, br_ip_hash(mdb, dst));
+}
+
 static struct net_bridge_mdb_entry *br_mdb_ip4_get(
        struct net_bridge_mdb_htable *mdb, __be32 dst)
 {
@@ -107,7 +116,7 @@ static struct net_bridge_mdb_entry *br_mdb_ip4_get(
        br_dst.u.ip4 = dst;
        br_dst.proto = htons(ETH_P_IP);
 
-       return __br_mdb_ip_get(mdb, &br_dst, __br_ip4_hash(mdb, dst));
+       return br_mdb_ip_get(mdb, &br_dst);
 }
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
@@ -119,23 +128,17 @@ static struct net_bridge_mdb_entry *br_mdb_ip6_get(
        ipv6_addr_copy(&br_dst.u.ip6, dst);
        br_dst.proto = htons(ETH_P_IPV6);
 
-       return __br_mdb_ip_get(mdb, &br_dst, __br_ip6_hash(mdb, dst));
+       return br_mdb_ip_get(mdb, &br_dst);
 }
 #endif
 
-static struct net_bridge_mdb_entry *br_mdb_ip_get(
-       struct net_bridge_mdb_htable *mdb, struct br_ip *dst)
-{
-       return __br_mdb_ip_get(mdb, dst, br_ip_hash(mdb, dst));
-}
-
 struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,
                                        struct sk_buff *skb)
 {
        struct net_bridge_mdb_htable *mdb = br->mdb;
        struct br_ip ip;
 
-       if (!mdb || br->multicast_disabled)
+       if (br->multicast_disabled)
                return NULL;
 
        if (BR_INPUT_SKB_CB(skb)->igmp)
index 44420992f72f17cc61f9e854ff511c8ec2bb270b..8fb75f89c4aac6e79aa9f8f41cc3a226b176000b 100644 (file)
@@ -591,6 +591,9 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff *skb,
 
        pskb_trim_rcsum(skb, len);
 
+       /* BUG: Should really parse the IP options here. */
+       memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
+
        nf_bridge_put(skb->nf_bridge);
        if (!nf_bridge_alloc(skb))
                return NF_DROP;
index 2b3bf53bc687aab3c9cfb32cce902eaebb3c18da..0ea10f849be862fff3219bc69ed4c5db0cbd9253 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)
 {
@@ -1893,8 +1911,16 @@ static int dev_gso_segment(struct sk_buff *skb)
  */
 static inline void skb_orphan_try(struct sk_buff *skb)
 {
-       if (!skb_tx(skb)->flags)
+       struct sock *sk = skb->sk;
+
+       if (sk && !skb_tx(skb)->flags) {
+               /* skb_tx_hash() wont be able to get sk.
+                * We copy sk_hash into skb->rxhash
+                */
+               if (!skb->rxhash)
+                       skb->rxhash = sk->sk_hash;
                skb_orphan(skb);
+       }
 }
 
 int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
@@ -1980,8 +2006,7 @@ u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb)
        if (skb->sk && skb->sk->sk_hash)
                hash = skb->sk->sk_hash;
        else
-               hash = (__force u16) skb->protocol;
-
+               hash = (__force u16) skb->protocol ^ skb->rxhash;
        hash = jhash_1word(hash, hashrnd);
 
        return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32);
@@ -2004,12 +2029,11 @@ static inline u16 dev_cap_txqueue(struct net_device *dev, u16 queue_index)
 static struct netdev_queue *dev_pick_tx(struct net_device *dev,
                                        struct sk_buff *skb)
 {
-       u16 queue_index;
+       int queue_index;
        struct sock *sk = skb->sk;
 
-       if (sk_tx_queue_recorded(sk)) {
-               queue_index = sk_tx_queue_get(sk);
-       } else {
+       queue_index = sk_tx_queue_get(sk);
+       if (queue_index < 0) {
                const struct net_device_ops *ops = dev->netdev_ops;
 
                if (ops->ndo_select_queue) {
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 6ba1c0eece039f99f19c0451bf5a52b3b9090a71..a4e0a7482c2bc878bdd6e0986ac45e0dc6659b3d 100644 (file)
@@ -949,7 +949,10 @@ static void neigh_update_hhs(struct neighbour *neigh)
 {
        struct hh_cache *hh;
        void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
-               = neigh->dev->header_ops->cache_update;
+               = NULL;
+
+       if (neigh->dev->header_ops)
+               update = neigh->dev->header_ops->cache_update;
 
        if (update) {
                for (hh = neigh->hh; hh; hh = hh->hh_next) {
index c51b55400dc56818a2f4e0cca68cb74be38048a3..11201784d29a32d6fdddd972a8348d3202de0ec9 100644 (file)
@@ -1,7 +1,7 @@
 menuconfig NET_DSA
        bool "Distributed Switch Architecture support"
        default n
-       depends on EXPERIMENTAL && !S390
+       depends on EXPERIMENTAL && NET_ETHERNET && !S390
        select PHYLIB
        ---help---
          This allows you to use hardware switch chips that use
index 757f25eb9b4b2404ebebc6c4422b4ad1693ea227..7f6273506eea46522a17ff85b9a451cb18fdc7d3 100644 (file)
@@ -442,8 +442,10 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
        int err;
 
        err = ipmr_fib_lookup(net, &fl, &mrt);
-       if (err < 0)
+       if (err < 0) {
+               kfree_skb(skb);
                return err;
+       }
 
        read_lock(&mrt_lock);
        dev->stats.tx_bytes += skb->len;
@@ -1728,8 +1730,10 @@ int ip_mr_input(struct sk_buff *skb)
                goto dont_forward;
 
        err = ipmr_fib_lookup(net, &skb_rtable(skb)->fl, &mrt);
-       if (err < 0)
+       if (err < 0) {
+               kfree_skb(skb);
                return err;
+       }
 
        if (!local) {
                    if (IPCB(skb)->opt.router_alert) {
index 6596b4feeddc7879fc020606f53dabdc8608f3e8..65afeaec15b7ebb85610650353e881aacb3e90aa 100644 (file)
@@ -608,6 +608,7 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos,
        ssize_t spliced;
        int ret;
 
+       sock_rps_record_flow(sk);
        /*
         * We can't seek on a socket input
         */
index 1705476670ef7a05e83d91cb7072e951302a30e2..23883a48ebfb37e0fa5b210d9207e8ba5c12b733 100644 (file)
@@ -108,6 +108,8 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
        u8 *xprth = skb_network_header(skb) + iph->ihl * 4;
 
        memset(fl, 0, sizeof(struct flowi));
+       fl->mark = skb->mark;
+
        if (!(iph->frag_off & htons(IP_MF | IP_OFFSET))) {
                switch (iph->protocol) {
                case IPPROTO_UDP:
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 47d2277137585648f57711618fe9b573ec83a1ff..2933396e02814c4020a5247f04815811b8867ee6 100644 (file)
@@ -97,9 +97,11 @@ static void send_reset(struct net *net, struct sk_buff *oldskb)
        fl.fl_ip_dport = otcph.source;
        security_skb_classify_flow(oldskb, &fl);
        dst = ip6_route_output(net, NULL, &fl);
-       if (dst == NULL)
+       if (dst == NULL || dst->error) {
+               dst_release(dst);
                return;
-       if (dst->error || xfrm_lookup(net, &dst, &fl, NULL, 0))
+       }
+       if (xfrm_lookup(net, &dst, &fl, NULL, 0))
                return;
 
        hh_len = (dst->dev->hard_header_len + 15)&~15;
index 4a0e77e14468e106b51d0ce5629d837a6e95fae2..6baeabbbca82416ffb940be126de520a847779a9 100644 (file)
@@ -124,6 +124,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
        u8 nexthdr = nh[IP6CB(skb)->nhoff];
 
        memset(fl, 0, sizeof(struct flowi));
+       fl->mark = skb->mark;
+
        ipv6_addr_copy(&fl->fl6_dst, reverse ? &hdr->saddr : &hdr->daddr);
        ipv6_addr_copy(&fl->fl6_src, reverse ? &hdr->daddr : &hdr->saddr);
 
index 94d72e85a475ae094d14f8df5f4f54a936f0db15..b2a3ae6cad78e28324e23b857dc0a5773f569786 100644 (file)
@@ -698,6 +698,7 @@ static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp)
                newsk = NULL;
                goto out;
        }
+       kfree_skb(oskb);
 
        sock_hold(sk);
        pep_sk(newsk)->listener = sk;
index 570949417f388735e93bf887294326a8f24aa534..724553e8ed7bc9d8ecd668c71ab9373936a3d2d3 100644 (file)
@@ -205,7 +205,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
        {
                struct icmphdr *icmph;
 
-               if (!pskb_may_pull(skb, ihl + sizeof(*icmph) + sizeof(*iph)))
+               if (!pskb_may_pull(skb, ihl + sizeof(*icmph)))
                        goto drop;
 
                icmph = (void *)(skb_network_header(skb) + ihl);
@@ -215,6 +215,9 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
                    (icmph->type != ICMP_PARAMETERPROB))
                        break;
 
+               if (!pskb_may_pull(skb, ihl + sizeof(*icmph) + sizeof(*iph)))
+                       goto drop;
+
                iph = (void *)(icmph + 1);
                if (egress)
                        addr = iph->daddr;
index 4bf27d90133336a1f862e6c7b28e4939397284c5..a7ec5a8a2380e6277fa4a3755e01fb0aa58076fb 100644 (file)
@@ -1594,8 +1594,8 @@ xfrm_resolve_and_create_bundle(struct xfrm_policy **pols, int num_pols,
 
        /* Try to instantiate a bundle */
        err = xfrm_tmpl_resolve(pols, num_pols, fl, xfrm, family);
-       if (err < 0) {
-               if (err != -EAGAIN)
+       if (err <= 0) {
+               if (err != 0 && err != -EAGAIN)
                        XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR);
                return ERR_PTR(err);
        }
@@ -1678,6 +1678,13 @@ xfrm_bundle_lookup(struct net *net, struct flowi *fl, u16 family, u8 dir,
                        goto make_dummy_bundle;
                dst_hold(&xdst->u.dst);
                return oldflo;
+       } else if (new_xdst == NULL) {
+               num_xfrms = 0;
+               if (oldflo == NULL)
+                       goto make_dummy_bundle;
+               xdst->num_xfrms = 0;
+               dst_hold(&xdst->u.dst);
+               return oldflo;
        }
 
        /* Kill the previous bundle */
@@ -1760,6 +1767,10 @@ restart:
                                xfrm_pols_put(pols, num_pols);
                                err = PTR_ERR(xdst);
                                goto dropdst;
+                       } else if (xdst == NULL) {
+                               num_xfrms = 0;
+                               drop_pols = num_pols;
+                               goto no_transform;
                        }
 
                        spin_lock_bh(&xfrm_policy_sk_bundle_lock);
@@ -2300,7 +2311,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 &&