Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 27 Jun 2010 18:28:02 +0000 (11:28 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 27 Jun 2010 18:28:02 +0000 (11:28 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (52 commits)
  phylib: Add autoload support for the LXT973 phy.
  ISDN: hysdn, fix potential NULL dereference
  vxge: fix memory leak in vxge_alloc_msix() error path
  isdn/gigaset: correct CAPI connection state storage
  isdn/gigaset: encode HLC and BC together
  isdn/gigaset: correct CAPI DATA_B3 Delivery Confirmation
  isdn/gigaset: correct CAPI voice connection encoding
  isdn/gigaset: honor CAPI application's buffer size request
  cpmac: do not leak struct net_device on phy_connect errors
  smc91c92_cs: fix the problem that lan & modem does not work simultaneously
  ipv6: fix NULL reference in proxy neighbor discovery
  Bluetooth: Bring back var 'i' increment
  xfrm: check bundle policy existance before dereferencing it
  sky2: enable rx/tx in sky2_phy_reinit()
  cnic: Disable statistics initialization for eth clients that do not support statistics
  net: add dependency on fw class module to qlcnic and netxen_nic
  snmp: fix SNMP_ADD_STATS()
  hso: remove setting of low_latency flag
  udp: Fix bogus UFO packet generation
  lasi82596: fix netdev_mc_count conversion
  ...

56 files changed:
MAINTAINERS
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/Kconfig
drivers/net/bnx2.c
drivers/net/cnic.c
drivers/net/cpmac.c
drivers/net/e1000/e1000_main.c
drivers/net/ehea/ehea.h
drivers/net/ehea/ehea_main.c
drivers/net/enic/vnic_dev.c
drivers/net/gianfar.c
drivers/net/ixgbe/ixgbe_ethtool.c
drivers/net/ixgbe/ixgbe_main.c
drivers/net/ixgbe/ixgbe_phy.c
drivers/net/lib82596.c
drivers/net/mipsnet.c
drivers/net/netxen/netxen_nic_ctx.c
drivers/net/netxen/netxen_nic_hw.c
drivers/net/netxen/netxen_nic_init.c
drivers/net/pcmcia/pcnet_cs.c
drivers/net/pcmcia/smc91c92_cs.c
drivers/net/phy/lxt.c
drivers/net/sky2.c
drivers/net/ucc_geth.c
drivers/net/usb/hso.c
drivers/net/vxge/vxge-main.c
drivers/net/wireless/ath/ath5k/attach.c
drivers/net/wireless/hostap/hostap_cs.c
drivers/net/wireless/hostap/hostap_hw.c
drivers/net/wireless/hostap/hostap_wlan.h
drivers/net/wireless/iwlwifi/iwl-agn-tx.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-scan.c
drivers/net/wireless/iwlwifi/iwl-sta.c
drivers/net/wireless/iwlwifi/iwl3945-base.c
drivers/net/wireless/libertas_tf/main.c
drivers/net/wireless/p54/p54pci.c
drivers/serial/serial_cs.c
include/net/snmp.h
net/bluetooth/bnep/netdev.c
net/bridge/br_fdb.c
net/bridge/br_forward.c
net/core/skbuff.c
net/ipv4/ip_output.c
net/ipv6/ndisc.c
net/mac80211/work.c
net/netfilter/ipvs/ip_vs_conn.c
net/sched/sch_teql.c
net/xfrm/xfrm_policy.c

index 78758e12a810490766eac2de89f321c887fd851d..6c73b3bc7f34d09da97d8f45808b5b24c5ddd2ee 100644 (file)
@@ -2985,20 +2985,14 @@ F:      drivers/net/ixgb/
 F:     drivers/net/ixgbe/
 
 INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT
-M:     Reinette Chatre <reinette.chatre@intel.com>
-M:     Intel Linux Wireless <ilw@linux.intel.com>
 L:     linux-wireless@vger.kernel.org
-W:     http://ipw2100.sourceforge.net
-S:     Odd Fixes
+S:     Orphan
 F:     Documentation/networking/README.ipw2100
 F:     drivers/net/wireless/ipw2x00/ipw2100.*
 
 INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT
-M:     Reinette Chatre <reinette.chatre@intel.com>
-M:     Intel Linux Wireless <ilw@linux.intel.com>
 L:     linux-wireless@vger.kernel.org
-W:     http://ipw2200.sourceforge.net
-S:     Odd Fixes
+S:     Orphan
 F:     Documentation/networking/README.ipw2200
 F:     drivers/net/wireless/ipw2x00/ipw2200.*
 
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 2decc597bda704bd74fac951551517421fc0a4e1..ce2fcdd4ab90521af8a8fb9a3f873b796b0a2bd9 100644 (file)
@@ -2754,6 +2754,7 @@ config MYRI10GE_DCA
 config NETXEN_NIC
        tristate "NetXen Multi port (1/10) Gigabit Ethernet NIC"
        depends on PCI
+       select FW_LOADER
        help
          This enables the support for NetXen's Gigabit Ethernet card.
 
@@ -2819,6 +2820,7 @@ config BNX2X
 config QLCNIC
        tristate "QLOGIC QLCNIC 1/10Gb Converged Ethernet NIC Support"
        depends on PCI
+       select FW_LOADER
        help
          This driver supports QLogic QLE8240 and QLE8242 Converged Ethernet
          devices.
index 949d7a9dcf9269b4ccef78703ffb7e1701767237..117432222a09e8b3c7521c6bf237621afe938fd9 100644 (file)
@@ -3073,7 +3073,6 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
        u16 hw_cons, sw_cons, sw_ring_cons, sw_prod, sw_ring_prod;
        struct l2_fhdr *rx_hdr;
        int rx_pkt = 0, pg_ring_used = 0;
-       struct pci_dev *pdev = bp->pdev;
 
        hw_cons = bnx2_get_hw_rx_cons(bnapi);
        sw_cons = rxr->rx_cons;
@@ -3099,12 +3098,10 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
                skb = rx_buf->skb;
                prefetchw(skb);
 
-               if (!get_dma_ops(&pdev->dev)->sync_single_for_cpu) {
-                       next_rx_buf =
-                               &rxr->rx_buf_ring[
-                                       RX_RING_IDX(NEXT_RX_BD(sw_cons))];
-                       prefetch(next_rx_buf->desc);
-               }
+               next_rx_buf =
+                       &rxr->rx_buf_ring[RX_RING_IDX(NEXT_RX_BD(sw_cons))];
+               prefetch(next_rx_buf->desc);
+
                rx_buf->skb = NULL;
 
                dma_addr = dma_unmap_addr(rx_buf, mapping);
index fe925663d39a535a5c9d2c6f65866c3f2f29e6d7..80471269977adefdaae7e0a7845611a2e1e7cadc 100644 (file)
@@ -3919,8 +3919,9 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev)
                HC_INDEX_DEF_C_ETH_ISCSI_CQ_CONS;
        context->cstorm_st_context.status_block_id = BNX2X_DEF_SB_ID;
 
-       context->xstorm_st_context.statistics_data = (cli |
-                               XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE);
+       if (cli < MAX_X_STAT_COUNTER_ID)
+               context->xstorm_st_context.statistics_data = cli |
+                               XSTORM_ETH_ST_CONTEXT_STATISTICS_ENABLE;
 
        context->xstorm_ag_context.cdu_reserved =
                CDU_RSRVD_VALUE_TYPE_A(BNX2X_HW_CID(BNX2X_ISCSI_L2_CID, func),
@@ -3928,10 +3929,12 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev)
                                        ETH_CONNECTION_TYPE);
 
        /* reset xstorm per client statistics */
-       val = BAR_XSTRORM_INTMEM +
-             XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
-       for (i = 0; i < sizeof(struct xstorm_per_client_stats) / 4; i++)
-               CNIC_WR(dev, val + i * 4, 0);
+       if (cli < MAX_X_STAT_COUNTER_ID) {
+               val = BAR_XSTRORM_INTMEM +
+                     XSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
+               for (i = 0; i < sizeof(struct xstorm_per_client_stats) / 4; i++)
+                       CNIC_WR(dev, val + i * 4, 0);
+       }
 
        cp->tx_cons_ptr =
                &cp->bnx2x_def_status_blk->c_def_status_block.index_values[
@@ -3978,9 +3981,11 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev)
                                                BNX2X_ISCSI_RX_SB_INDEX_NUM;
        context->ustorm_st_context.common.clientId = cli;
        context->ustorm_st_context.common.status_block_id = BNX2X_DEF_SB_ID;
-       context->ustorm_st_context.common.flags =
-               USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS;
-       context->ustorm_st_context.common.statistics_counter_id = cli;
+       if (cli < MAX_U_STAT_COUNTER_ID) {
+               context->ustorm_st_context.common.flags =
+                       USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_STATISTICS;
+               context->ustorm_st_context.common.statistics_counter_id = cli;
+       }
        context->ustorm_st_context.common.mc_alignment_log_size = 0;
        context->ustorm_st_context.common.bd_buff_size =
                                                cp->l2_single_buf_size;
@@ -4011,10 +4016,13 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev)
 
        /* client tstorm info */
        tstorm_client.mtu = cp->l2_single_buf_size - 14;
-       tstorm_client.config_flags =
-                       (TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE |
-                       TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE);
-       tstorm_client.statistics_counter_id = cli;
+       tstorm_client.config_flags = TSTORM_ETH_CLIENT_CONFIG_E1HOV_REM_ENABLE;
+
+       if (cli < MAX_T_STAT_COUNTER_ID) {
+               tstorm_client.config_flags |=
+                               TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE;
+               tstorm_client.statistics_counter_id = cli;
+       }
 
        CNIC_WR(dev, BAR_TSTRORM_INTMEM +
                   TSTORM_CLIENT_CONFIG_OFFSET(port, cli),
@@ -4024,16 +4032,21 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev)
                   ((u32 *)&tstorm_client)[1]);
 
        /* reset tstorm per client statistics */
-       val = BAR_TSTRORM_INTMEM +
-             TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
-       for (i = 0; i < sizeof(struct tstorm_per_client_stats) / 4; i++)
-               CNIC_WR(dev, val + i * 4, 0);
+       if (cli < MAX_T_STAT_COUNTER_ID) {
+
+               val = BAR_TSTRORM_INTMEM +
+                     TSTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
+               for (i = 0; i < sizeof(struct tstorm_per_client_stats) / 4; i++)
+                       CNIC_WR(dev, val + i * 4, 0);
+       }
 
        /* reset ustorm per client statistics */
-       val = BAR_USTRORM_INTMEM +
-             USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
-       for (i = 0; i < sizeof(struct ustorm_per_client_stats) / 4; i++)
-               CNIC_WR(dev, val + i * 4, 0);
+       if (cli < MAX_U_STAT_COUNTER_ID) {
+               val = BAR_USTRORM_INTMEM +
+                     USTORM_PER_COUNTER_ID_STATS_OFFSET(port, cli);
+               for (i = 0; i < sizeof(struct ustorm_per_client_stats) / 4; i++)
+                       CNIC_WR(dev, val + i * 4, 0);
+       }
 
        cp->rx_cons_ptr =
                &cp->bnx2x_def_status_blk->u_def_status_block.index_values[
index 3c58db5952852ad5319741c7135e452e2ad086a0..23786ee34beded0a9ae6d2c0484ca75965eeab93 100644 (file)
@@ -1181,7 +1181,8 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
                if (netif_msg_drv(priv))
                        printk(KERN_ERR "%s: Could not attach to PHY\n",
                               dev->name);
-               return PTR_ERR(priv->phy);
+               rc = PTR_ERR(priv->phy);
+               goto fail;
        }
 
        if ((rc = register_netdev(dev))) {
index ebdea0891665dbb81fbd6e7894abc4e97b6fd2c4..68a80893dce1daa492c23f6a7e6e0dd290645046 100644 (file)
@@ -1047,15 +1047,14 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
                goto err_register;
 
        /* print bus type/speed/width info */
-       e_info("(PCI%s:%s:%s) ",
-               ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
-               ((hw->bus_speed == e1000_bus_speed_133) ? "133MHz" :
-                (hw->bus_speed == e1000_bus_speed_120) ? "120MHz" :
-                (hw->bus_speed == e1000_bus_speed_100) ? "100MHz" :
-                (hw->bus_speed == e1000_bus_speed_66) ? "66MHz" : "33MHz"),
-               ((hw->bus_width == e1000_bus_width_64) ? "64-bit" : "32-bit"));
-
-       e_info("%pM\n", netdev->dev_addr);
+       e_info("(PCI%s:%dMHz:%d-bit) %pM\n",
+              ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
+              ((hw->bus_speed == e1000_bus_speed_133) ? 133 :
+               (hw->bus_speed == e1000_bus_speed_120) ? 120 :
+               (hw->bus_speed == e1000_bus_speed_100) ? 100 :
+               (hw->bus_speed == e1000_bus_speed_66) ? 66 : 33),
+              ((hw->bus_width == e1000_bus_width_64) ? 64 : 32),
+              netdev->dev_addr);
 
        /* carrier off reporting is important to ethtool even BEFORE open */
        netif_carrier_off(netdev);
index 0630980a27222ce31ab4bb77d8af754d5ddc0c09..0060e422f171bda3c385ef757fce13ee39d0a517 100644 (file)
@@ -40,7 +40,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME       "ehea"
-#define DRV_VERSION    "EHEA_0103"
+#define DRV_VERSION    "EHEA_0105"
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
index f547894ff48fc3a02317548dafe8ec900e5044e2..8b92acb448c2691e7d2ca4de669c61e4a33677e9 100644 (file)
@@ -867,6 +867,7 @@ static int ehea_poll(struct napi_struct *napi, int budget)
                ehea_reset_cq_ep(pr->send_cq);
                ehea_reset_cq_n1(pr->recv_cq);
                ehea_reset_cq_n1(pr->send_cq);
+               rmb();
                cqe = ehea_poll_rq1(pr->qp, &wqe_index);
                cqe_skb = ehea_poll_cq(pr->send_cq);
 
@@ -2859,6 +2860,7 @@ static void ehea_reset_port(struct work_struct *work)
                container_of(work, struct ehea_port, reset_task);
        struct net_device *dev = port->netdev;
 
+       mutex_lock(&dlpar_mem_lock);
        port->resets++;
        mutex_lock(&port->port_lock);
        netif_stop_queue(dev);
@@ -2881,6 +2883,7 @@ static void ehea_reset_port(struct work_struct *work)
        netif_wake_queue(dev);
 out:
        mutex_unlock(&port->port_lock);
+       mutex_unlock(&dlpar_mem_lock);
 }
 
 static void ehea_rereg_mrs(struct work_struct *work)
@@ -3542,10 +3545,7 @@ static int ehea_mem_notifier(struct notifier_block *nb,
        int ret = NOTIFY_BAD;
        struct memory_notify *arg = data;
 
-       if (!mutex_trylock(&dlpar_mem_lock)) {
-               ehea_info("ehea_mem_notifier must not be called parallelized");
-               goto out;
-       }
+       mutex_lock(&dlpar_mem_lock);
 
        switch (action) {
        case MEM_CANCEL_OFFLINE:
@@ -3574,7 +3574,6 @@ static int ehea_mem_notifier(struct notifier_block *nb,
 
 out_unlock:
        mutex_unlock(&dlpar_mem_lock);
-out:
        return ret;
 }
 
index 2b3e16db5c82f2a75763f128854b06a3d2447d24..e0d33281ec980b6013dea7c1632b19358af7d30c 100644 (file)
@@ -709,7 +709,7 @@ int vnic_dev_init_prov(struct vnic_dev *vdev, u8 *buf, u32 len)
 {
        u64 a0, a1 = len;
        int wait = 1000;
-       u64 prov_pa;
+       dma_addr_t prov_pa;
        void *prov_buf;
        int ret;
 
index 46c69cd0655358a74c726d9b0ae56fd1d2c7d0fd..28b53d1cd4f168701fa4ce41a7c5e0edbaa6f783 100644 (file)
@@ -381,10 +381,14 @@ static void gfar_init_mac(struct net_device *ndev)
        /* Insert receive time stamps into padding alignment bytes */
        if (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) {
                rctrl &= ~RCTRL_PAL_MASK;
-               rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE | RCTRL_PADDING(8);
+               rctrl |= RCTRL_PADDING(8);
                priv->padding = 8;
        }
 
+       /* Enable HW time stamping if requested from user space */
+       if (priv->hwts_rx_en)
+               rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE;
+
        /* keep vlan related bits if it's enabled */
        if (priv->vlgrp) {
                rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT;
@@ -747,7 +751,8 @@ static int gfar_of_init(struct of_device *ofdev, struct net_device **pdev)
                        FSL_GIANFAR_DEV_HAS_CSUM |
                        FSL_GIANFAR_DEV_HAS_VLAN |
                        FSL_GIANFAR_DEV_HAS_MAGIC_PACKET |
-                       FSL_GIANFAR_DEV_HAS_EXTENDED_HASH;
+                       FSL_GIANFAR_DEV_HAS_EXTENDED_HASH |
+                       FSL_GIANFAR_DEV_HAS_TIMER;
 
        ctype = of_get_property(np, "phy-connection-type", NULL);
 
@@ -805,12 +810,20 @@ static int gfar_hwtstamp_ioctl(struct net_device *netdev,
 
        switch (config.rx_filter) {
        case HWTSTAMP_FILTER_NONE:
-               priv->hwts_rx_en = 0;
+               if (priv->hwts_rx_en) {
+                       stop_gfar(netdev);
+                       priv->hwts_rx_en = 0;
+                       startup_gfar(netdev);
+               }
                break;
        default:
                if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER))
                        return -ERANGE;
-               priv->hwts_rx_en = 1;
+               if (!priv->hwts_rx_en) {
+                       stop_gfar(netdev);
+                       priv->hwts_rx_en = 1;
+                       startup_gfar(netdev);
+               }
                config.rx_filter = HWTSTAMP_FILTER_ALL;
                break;
        }
@@ -2642,6 +2655,10 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
                dma_unmap_single(&priv->ofdev->dev, bdp->bufPtr,
                                priv->rx_buffer_size, DMA_FROM_DEVICE);
 
+               if (unlikely(!(bdp->status & RXBD_ERR) &&
+                               bdp->length > priv->rx_buffer_size))
+                       bdp->status = RXBD_LARGE;
+
                /* We drop the frame if we failed to allocate a new buffer */
                if (unlikely(!newskb || !(bdp->status & RXBD_LAST) ||
                                 bdp->status & RXBD_ERR)) {
index c50a7541ffecf763fb0050de183f4db98f43b1b7..3a93a81872b87153404111152bf5860307815772 100644 (file)
@@ -2077,25 +2077,6 @@ static int ixgbe_get_coalesce(struct net_device *netdev,
        return 0;
 }
 
-/*
- * this function must be called before setting the new value of
- * rx_itr_setting
- */
-static bool ixgbe_reenable_rsc(struct ixgbe_adapter *adapter,
-                               struct ethtool_coalesce *ec)
-{
-       /* check the old value and enable RSC if necessary */
-       if ((adapter->rx_itr_setting == 0) &&
-           (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)) {
-               adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
-               adapter->netdev->features |= NETIF_F_LRO;
-               DPRINTK(PROBE, INFO, "rx-usecs set to %d, re-enabling RSC\n",
-                       ec->rx_coalesce_usecs);
-               return true;
-       }
-       return false;
-}
-
 static int ixgbe_set_coalesce(struct net_device *netdev,
                               struct ethtool_coalesce *ec)
 {
@@ -2124,9 +2105,6 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
                    (1000000/ec->rx_coalesce_usecs < IXGBE_MIN_INT_RATE))
                        return -EINVAL;
 
-               /* check the old value and enable RSC if necessary */
-               need_reset = ixgbe_reenable_rsc(adapter, ec);
-
                /* store the value in ints/second */
                adapter->rx_eitr_param = 1000000/ec->rx_coalesce_usecs;
 
@@ -2135,9 +2113,6 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
                /* clear the lower bit as its used for dynamic state */
                adapter->rx_itr_setting &= ~1;
        } else if (ec->rx_coalesce_usecs == 1) {
-               /* check the old value and enable RSC if necessary */
-               need_reset = ixgbe_reenable_rsc(adapter, ec);
-
                /* 1 means dynamic mode */
                adapter->rx_eitr_param = 20000;
                adapter->rx_itr_setting = 1;
@@ -2157,10 +2132,11 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
                 */
                if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
                        adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED;
-                       netdev->features &= ~NETIF_F_LRO;
-                       DPRINTK(PROBE, INFO,
-                               "rx-usecs set to 0, disabling RSC\n");
-
+                       if (netdev->features & NETIF_F_LRO) {
+                               netdev->features &= ~NETIF_F_LRO;
+                               DPRINTK(PROBE, INFO, "rx-usecs set to 0, "
+                                       "disabling LRO/RSC\n");
+                       }
                        need_reset = true;
                }
        }
@@ -2255,6 +2231,9 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data)
                        }
                } else if (!adapter->rx_itr_setting) {
                        netdev->features &= ~ETH_FLAG_LRO;
+                       if (data & ETH_FLAG_LRO)
+                               DPRINTK(PROBE, INFO, "rx-usecs set to 0, "
+                                       "LRO/RSC cannot be enabled.\n");
                }
        }
 
index b2af2f67f604c2d24018a2e9af8307e5e33d5828..ce30c62a97f70bd08f3d4bdbcb6009dda523ff0e 100644 (file)
@@ -5282,6 +5282,10 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
        u32 i, missed_rx = 0, mpc, bprc, lxon, lxoff, xon_off_tot;
        u64 non_eop_descs = 0, restart_queue = 0;
 
+       if (test_bit(__IXGBE_DOWN, &adapter->state) ||
+           test_bit(__IXGBE_RESETTING, &adapter->state))
+               return;
+
        if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
                u64 rsc_count = 0;
                u64 rsc_flush = 0;
index 09e1911ff510474ecda600446a51330d057647e3..48325a5beff2054c59b2aa9f6b333bcdf4d3d0c8 100644 (file)
@@ -575,6 +575,8 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
                 * 4    SFP_DA_CORE1 - 82599-specific
                 * 5    SFP_SR/LR_CORE0 - 82599-specific
                 * 6    SFP_SR/LR_CORE1 - 82599-specific
+                * 7    SFP_act_lmt_DA_CORE0 - 82599-specific
+                * 8    SFP_act_lmt_DA_CORE1 - 82599-specific
                 */
                if (hw->mac.type == ixgbe_mac_82598EB) {
                        if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
index ce5d6e9092182a43d2f0660e68667edf44bfae3b..c27f4291b350422978ab9fbf55bd6318ec0953ae 100644 (file)
@@ -1343,7 +1343,7 @@ static void set_multicast_list(struct net_device *dev)
        DEB(DEB_MULTI,
            printk(KERN_DEBUG
                   "%s: set multicast list, %d entries, promisc %s, allmulti %s\n",
-                  dev->name, dev->mc_count,
+                  dev->name, netdev_mc_count(dev),
                   dev->flags & IFF_PROMISC ? "ON" : "OFF",
                   dev->flags & IFF_ALLMULTI ? "ON" : "OFF"));
 
index 8e9704f5c12213390923cf77005df3dc63b88dd5..869f0ea43a5bbc820ae71fca9ffcb21ba6315119 100644 (file)
@@ -247,7 +247,7 @@ static const struct net_device_ops mipsnet_netdev_ops = {
        .ndo_set_mac_address    = eth_mac_addr,
 };
 
-static int __init mipsnet_probe(struct platform_device *dev)
+static int __devinit mipsnet_probe(struct platform_device *dev)
 {
        struct net_device *netdev;
        int err;
index f26e54716c886569f9e30d9a8a5c34d6056b58e6..3a41b6a84a68636a61fd85fd233a17a4c0ce3cd6 100644 (file)
@@ -629,7 +629,8 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
        if (addr == NULL) {
                dev_err(&pdev->dev, "%s: failed to allocate tx desc ring\n",
                                netdev->name);
-               return -ENOMEM;
+               err = -ENOMEM;
+               goto err_out_free;
        }
 
        tx_ring->desc_head = (struct cmd_desc_type0 *)addr;
index 5c496f8d7c497f16c5a17fe7398794efdca550b3..29d7b93d0493be12e4a5def185282371b5cd400d 100644 (file)
@@ -1159,9 +1159,6 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong off)
 
        window = CRB_HI(off);
 
-       if (adapter->ahw.crb_win == window)
-               return;
-
        writel(window, addr);
        if (readl(addr) != window) {
                if (printk_ratelimit())
@@ -1169,7 +1166,6 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong off)
                                "failed to set CRB window to %d off 0x%lx\n",
                                window, off);
        }
-       adapter->ahw.crb_win = window;
 }
 
 static void __iomem *
index 045a7c8f5bdf8e08fd4b317a96f0917023f238d3..c865dda2adf15f8b59a579640d416099e9fabc0c 100644 (file)
@@ -218,7 +218,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
        if (cmd_buf_arr == NULL) {
                dev_err(&pdev->dev, "%s: failed to allocate cmd buffer ring\n",
                       netdev->name);
-               return -ENOMEM;
+               goto err_out;
        }
        memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
        tx_ring->cmd_buf_arr = cmd_buf_arr;
@@ -230,7 +230,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
        if (rds_ring == NULL) {
                dev_err(&pdev->dev, "%s: failed to allocate rds ring struct\n",
                       netdev->name);
-               return -ENOMEM;
+               goto err_out;
        }
        recv_ctx->rds_rings = rds_ring;
 
@@ -1805,9 +1805,10 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
        netxen_ctx_msg msg = 0;
        struct list_head *head;
 
+       spin_lock(&rds_ring->lock);
+
        producer = rds_ring->producer;
 
-       spin_lock(&rds_ring->lock);
        head = &rds_ring->free_list;
        while (!list_empty(head)) {
 
@@ -1829,7 +1830,6 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
 
                producer = get_next_index(producer, rds_ring->num_desc);
        }
-       spin_unlock(&rds_ring->lock);
 
        if (count) {
                rds_ring->producer = producer;
@@ -1853,6 +1853,8 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
                                        NETXEN_RCV_PRODUCER_OFFSET), msg);
                }
        }
+
+       spin_unlock(&rds_ring->lock);
 }
 
 static void
@@ -1864,10 +1866,11 @@ netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
        int producer, count = 0;
        struct list_head *head;
 
-       producer = rds_ring->producer;
        if (!spin_trylock(&rds_ring->lock))
                return;
 
+       producer = rds_ring->producer;
+
        head = &rds_ring->free_list;
        while (!list_empty(head)) {
 
index 6f77a768ba880b532dfa85521e1883a460a4bf9d..bfdef72c5d5ea6371b2fc634c9e2a8476d13fa33 100644 (file)
@@ -1727,6 +1727,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),
        PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
        PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
        PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "cis/DP83903.cis"),
index 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 2111c7bbf57831209b689871ceea4cb48a82de87..7985165e84fc4ed6ca6ce5fceb8e60d54dca0b5d 100644 (file)
@@ -717,11 +717,24 @@ static void sky2_phy_power_down(struct sky2_hw *hw, unsigned port)
        sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
 }
 
+/* Enable Rx/Tx */
+static void sky2_enable_rx_tx(struct sky2_port *sky2)
+{
+       struct sky2_hw *hw = sky2->hw;
+       unsigned port = sky2->port;
+       u16 reg;
+
+       reg = gma_read16(hw, port, GM_GP_CTRL);
+       reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
+       gma_write16(hw, port, GM_GP_CTRL, reg);
+}
+
 /* Force a renegotiation */
 static void sky2_phy_reinit(struct sky2_port *sky2)
 {
        spin_lock_bh(&sky2->phy_lock);
        sky2_phy_init(sky2->hw, sky2->port);
+       sky2_enable_rx_tx(sky2);
        spin_unlock_bh(&sky2->phy_lock);
 }
 
@@ -2040,7 +2053,6 @@ static void sky2_link_up(struct sky2_port *sky2)
 {
        struct sky2_hw *hw = sky2->hw;
        unsigned port = sky2->port;
-       u16 reg;
        static const char *fc_name[] = {
                [FC_NONE]       = "none",
                [FC_TX]         = "tx",
@@ -2048,10 +2060,7 @@ static void sky2_link_up(struct sky2_port *sky2)
                [FC_BOTH]       = "both",
        };
 
-       /* enable Rx/Tx */
-       reg = gma_read16(hw, port, GM_GP_CTRL);
-       reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
-       gma_write16(hw, port, GM_GP_CTRL, reg);
+       sky2_enable_rx_tx(sky2);
 
        gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
 
index 4a34833b85ddad284c1f19efff1bf9d23ed7f7e1..807470e156affad7d05529ed7ffb0d29d0973c48 100644 (file)
@@ -3215,6 +3215,8 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit
                                           __func__, __LINE__, (u32) skb);
                        if (skb) {
                                skb->data = skb->head + NET_SKB_PAD;
+                               skb->len = 0;
+                               skb_reset_tail_pointer(skb);
                                __skb_queue_head(&ugeth->rx_recycle, skb);
                        }
 
index 0a3c41faea9c2118dd28f6c558c939002c34d135..4dd23513c5af1d661e23498740fd9f20841426e0 100644 (file)
@@ -1334,7 +1334,6 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp)
        /* check for port already opened, if not set the termios */
        serial->open_count++;
        if (serial->open_count == 1) {
-               tty->low_latency = 1;
                serial->rx_state = RX_IDLE;
                /* Force default termio settings */
                _hso_serial_set_termios(tty, NULL);
index b504bd56136210776fa0d31e87a5e00b687cb03b..d14e207de1df8c8f074d0428e0d21d380344a7f2 100644 (file)
@@ -2262,7 +2262,8 @@ start:
                vxge_debug_init(VXGE_ERR,
                        "%s: memory allocation failed",
                        VXGE_DRIVER_NAME);
-               return  -ENOMEM;
+               ret = -ENOMEM;
+               goto alloc_entries_failed;
        }
 
        vdev->vxge_entries =
@@ -2271,8 +2272,8 @@ start:
        if (!vdev->vxge_entries) {
                vxge_debug_init(VXGE_ERR, "%s: memory allocation failed",
                        VXGE_DRIVER_NAME);
-               kfree(vdev->entries);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto alloc_vxge_entries_failed;
        }
 
        for (i = 0, j = 0; i < vdev->no_of_vpath; i++) {
@@ -2303,22 +2304,32 @@ start:
                vxge_debug_init(VXGE_ERR,
                        "%s: MSI-X enable failed for %d vectors, ret: %d",
                        VXGE_DRIVER_NAME, vdev->intr_cnt, ret);
+               if ((max_config_vpath != VXGE_USE_DEFAULT) || (ret < 3)) {
+                       ret = -ENODEV;
+                       goto enable_msix_failed;
+               }
+
                kfree(vdev->entries);
                kfree(vdev->vxge_entries);
                vdev->entries = NULL;
                vdev->vxge_entries = NULL;
-
-               if ((max_config_vpath != VXGE_USE_DEFAULT) || (ret < 3))
-                       return -ENODEV;
                /* Try with less no of vector by reducing no of vpaths count */
                temp = (ret - 1)/2;
                vxge_close_vpaths(vdev, temp);
                vdev->no_of_vpath = temp;
                goto start;
-       } else if (ret < 0)
-               return -ENODEV;
-
+       } else if (ret < 0) {
+               ret = -ENODEV;
+               goto enable_msix_failed;
+       }
        return 0;
+
+enable_msix_failed:
+       kfree(vdev->vxge_entries);
+alloc_vxge_entries_failed:
+       kfree(vdev->entries);
+alloc_entries_failed:
+       return ret;
 }
 
 static int vxge_enable_msix(struct vxgedev *vdev)
index e0c244b02f05d17cc1ee9fb7cc12dd9e0e01541e..31c008042bfe066238edc359111047d8064693d3 100644 (file)
@@ -126,6 +126,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
        ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT;
        ah->ah_noise_floor = -95;       /* until first NF calibration is run */
        sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO;
+       ah->ah_current_channel = &sc->channels[0];
 
        /*
         * Find the mac version
index db72461c486b50a2c90a3fa09e6ce6958eb99eac..29b31a694b59cc2140cf7b044757f29c5dfd9701 100644 (file)
@@ -594,6 +594,7 @@ static int prism2_config(struct pcmcia_device *link)
        local_info_t *local;
        int ret = 1;
        struct hostap_cs_priv *hw_priv;
+       unsigned long flags;
 
        PDEBUG(DEBUG_FLOW, "prism2_config()\n");
 
@@ -625,9 +626,15 @@ static int prism2_config(struct pcmcia_device *link)
        local->hw_priv = hw_priv;
        hw_priv->link = link;
 
+       /*
+        * Make sure the IRQ handler cannot proceed until at least
+        * dev->base_addr is initialized.
+        */
+       spin_lock_irqsave(&local->irq_init_lock, flags);
+
        ret = pcmcia_request_irq(link, prism2_interrupt);
        if (ret)
-               goto failed;
+               goto failed_unlock;
 
        /*
         * This actually configures the PCMCIA socket -- setting up
@@ -636,11 +643,13 @@ static int prism2_config(struct pcmcia_device *link)
         */
        ret = pcmcia_request_configuration(link, &link->conf);
        if (ret)
-               goto failed;
+               goto failed_unlock;
 
        dev->irq = link->irq;
        dev->base_addr = link->io.BasePort1;
 
+       spin_unlock_irqrestore(&local->irq_init_lock, flags);
+
        /* Finally, report what we've done */
        printk(KERN_INFO "%s: index 0x%02x: ",
               dev_info, link->conf.ConfigIndex);
@@ -667,6 +676,8 @@ static int prism2_config(struct pcmcia_device *link)
 
        return ret;
 
+ failed_unlock:
+        spin_unlock_irqrestore(&local->irq_init_lock, flags);
  failed:
        kfree(hw_priv);
        prism2_release((u_long)link);
index ff9b5c882184a00e58316166a62fd5514ead0ae6..2f999fc94f60ca9b36bb11d70fd29096c85eaf7e 100644 (file)
@@ -2621,6 +2621,18 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id)
        iface = netdev_priv(dev);
        local = iface->local;
 
+       /* Detect early interrupt before driver is fully configued */
+       spin_lock(&local->irq_init_lock);
+       if (!dev->base_addr) {
+               if (net_ratelimit()) {
+                       printk(KERN_DEBUG "%s: Interrupt, but dev not configured\n",
+                              dev->name);
+               }
+               spin_unlock(&local->irq_init_lock);
+               return IRQ_HANDLED;
+       }
+       spin_unlock(&local->irq_init_lock);
+
        prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 0);
 
        if (local->func->card_present && !local->func->card_present(local)) {
@@ -3138,6 +3150,7 @@ prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx,
        spin_lock_init(&local->cmdlock);
        spin_lock_init(&local->baplock);
        spin_lock_init(&local->lock);
+       spin_lock_init(&local->irq_init_lock);
        mutex_init(&local->rid_bap_mtx);
 
        if (card_idx < 0 || card_idx >= MAX_PARM_DEVICES)
index 3d238917af07f32bcd16ffcf8eb75f90f824b120..1ba33be98b254ce9ef8a56fcb6c55501d14a9839 100644 (file)
@@ -654,7 +654,7 @@ struct local_info {
        rwlock_t iface_lock; /* hostap_interfaces read lock; use write lock
                              * when removing entries from the list.
                              * TX and RX paths can use read lock. */
-       spinlock_t cmdlock, baplock, lock;
+       spinlock_t cmdlock, baplock, lock, irq_init_lock;
        struct mutex rid_bap_mtx;
        u16 infofid; /* MAC buffer id for info frame */
        /* txfid, intransmitfid, next_txtid, and next_alloc are protected by
index a732f1094e5d3a983a102d7afe3038eddc2eb6a2..7d614c4d3c6200d5410bba749105f4d371b2e5b7 100644 (file)
@@ -1299,6 +1299,11 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
        sta_id = ba_resp->sta_id;
        tid = ba_resp->tid;
        agg = &priv->stations[sta_id].tid[tid].agg;
+       if (unlikely(agg->txq_id != scd_flow)) {
+               IWL_ERR(priv, "BA scd_flow %d does not match txq_id %d\n",
+                       scd_flow, agg->txq_id);
+               return;
+       }
 
        /* Find index just before block-ack window */
        index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
index 7726e67044c08b91a36d41759b2dfd22c19ae263..24aff654fa9c44251b11f3d12ab63d639ea06384 100644 (file)
@@ -3391,10 +3391,12 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
        int ret;
        u8 sta_id;
 
-       sta_priv->common.sta_id = IWL_INVALID_STATION;
-
        IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
                        sta->addr);
+       mutex_lock(&priv->mutex);
+       IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
+                       sta->addr);
+       sta_priv->common.sta_id = IWL_INVALID_STATION;
 
        atomic_set(&sta_priv->pending_frames, 0);
        if (vif->type == NL80211_IFTYPE_AP)
@@ -3406,6 +3408,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
                IWL_ERR(priv, "Unable to add station %pM (%d)\n",
                        sta->addr, ret);
                /* Should we return success if return code is EEXIST ? */
+               mutex_unlock(&priv->mutex);
                return ret;
        }
 
@@ -3415,6 +3418,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
        IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
                       sta->addr);
        iwl_rs_rate_init(priv, sta, sta_id);
+       mutex_unlock(&priv->mutex);
 
        return 0;
 }
index 5d3f51ff2f0d075ad6ef81c022a687651afd2e07..386c5f96eff81c6467f026bc970c39734b853ffb 100644 (file)
@@ -491,6 +491,7 @@ void iwl_bg_abort_scan(struct work_struct *work)
 
        mutex_lock(&priv->mutex);
 
+       cancel_delayed_work_sync(&priv->scan_check);
        set_bit(STATUS_SCAN_ABORTING, &priv->status);
        iwl_send_scan_abort(priv);
 
index 83a26361a9b56b35d4364c93b9f9df32905c8cc6..c27c13fbb1aec26bac302623b96d089e1f13c0dd 100644 (file)
@@ -1373,10 +1373,14 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw,
 
        IWL_DEBUG_INFO(priv, "received request to remove station %pM\n",
                        sta->addr);
+       mutex_lock(&priv->mutex);
+       IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n",
+                       sta->addr);
        ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr);
        if (ret)
                IWL_ERR(priv, "Error removing station %pM\n",
                        sta->addr);
+       mutex_unlock(&priv->mutex);
        return ret;
 }
 EXPORT_SYMBOL(iwl_mac_sta_remove);
index 6c353cacc8d663f43d1a19c4b4bebcb697d61e45..a27872de41061d62cec0af818aa72f88927396da 100644 (file)
@@ -3437,10 +3437,13 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
        bool is_ap = vif->type == NL80211_IFTYPE_STATION;
        u8 sta_id;
 
-       sta_priv->common.sta_id = IWL_INVALID_STATION;
-
        IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
                        sta->addr);
+       mutex_lock(&priv->mutex);
+       IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
+                       sta->addr);
+       sta_priv->common.sta_id = IWL_INVALID_STATION;
+
 
        ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap,
                                     &sta_id);
@@ -3448,6 +3451,7 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
                IWL_ERR(priv, "Unable to add station %pM (%d)\n",
                        sta->addr, ret);
                /* Should we return success if return code is EEXIST ? */
+               mutex_unlock(&priv->mutex);
                return ret;
        }
 
@@ -3457,6 +3461,7 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
        IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
                       sta->addr);
        iwl3945_rs_rate_init(priv, sta, sta_id);
+       mutex_unlock(&priv->mutex);
 
        return 0;
 }
index 6a04c2157f73f3788109afcdfbc50c4ecdf62b9e..817fffc0de4b5093c869fc11a5f72aa9ca0ab3ba 100644 (file)
@@ -549,7 +549,7 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
 
        prxpd = (struct rxpd *) skb->data;
 
-       stats.flag = 0;
+       memset(&stats, 0, sizeof(stats));
        if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK)))
                stats.flag |= RX_FLAG_FAILED_FCS_CRC;
        stats.freq = priv->cur_freq;
index 07c4528f6e6b895d59e2cddc3fd30edcf80cb000..a5ea89cde8c43a9c837018459e9f689a83162e1e 100644 (file)
@@ -41,6 +41,8 @@ static DEFINE_PCI_DEVICE_TABLE(p54p_table) = {
        { PCI_DEVICE(0x1260, 0x3877) },
        /* Intersil PRISM Javelin/Xbow Wireless LAN adapter */
        { PCI_DEVICE(0x1260, 0x3886) },
+       /* Intersil PRISM Xbow Wireless LAN adapter (Symbol AP-300) */
+       { PCI_DEVICE(0x1260, 0xffff) },
        { },
 };
 
index 526307368f8be5f8c1a1a553b01ac83799db2ffa..ab17c08ddc03cac3fcc6674dba53bd2a4e9960a9 100644 (file)
@@ -821,6 +821,7 @@ static struct pcmcia_device_id serial_ids[] = {
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
        PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),
        PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
        PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
        PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "cis/3CCFEM556.cis"),
index 92456f1035f52bd6e1a6c8e7733c7737d58d15e1..899003d18db9e57ab8813176f4ea896a27376c49 100644 (file)
@@ -134,7 +134,7 @@ struct linux_xfrm_mib {
 #define SNMP_ADD_STATS_USER(mib, field, addend)        \
                        this_cpu_add(mib[1]->mibs[field], addend)
 #define SNMP_ADD_STATS(mib, field, addend)     \
-                       this_cpu_add(mib[0]->mibs[field], addend)
+                       this_cpu_add(mib[!in_softirq()]->mibs[field], addend)
 /*
  * Use "__typeof__(*mib[0]) *ptr" instead of "__typeof__(mib[0]) ptr"
  * to make @ptr a non-percpu pointer.
index 0faad5ce6dc480efe1928c1c60728e14b4093b92..8c100c9dae2833bcf3963a2cc4c8a9a2fcbdc064 100644 (file)
@@ -104,6 +104,8 @@ static void bnep_net_set_mc_list(struct net_device *dev)
                                break;
                        memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN);
                        memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN);
+
+                       i++;
                }
                r->len = htons(skb->len - len);
        }
index 26637439965bef745542f7baa4242d5249a33d9d..b01dde35a69ed3f1cecf30ebe604cc1808d72a69 100644 (file)
@@ -128,7 +128,7 @@ void br_fdb_cleanup(unsigned long _data)
 {
        struct net_bridge *br = (struct net_bridge *)_data;
        unsigned long delay = hold_time(br);
-       unsigned long next_timer = jiffies + br->forward_delay;
+       unsigned long next_timer = jiffies + br->ageing_time;
        int i;
 
        spin_lock_bh(&br->hash_lock);
@@ -149,9 +149,7 @@ void br_fdb_cleanup(unsigned long _data)
        }
        spin_unlock_bh(&br->hash_lock);
 
-       /* Add HZ/4 to ensure we round the jiffies upwards to be after the next
-        * timer, otherwise we might round down and will have no-op run. */
-       mod_timer(&br->gc_timer, round_jiffies(next_timer + HZ/4));
+       mod_timer(&br->gc_timer, round_jiffies_up(next_timer));
 }
 
 /* Completely flush all dynamic entries in forwarding database.*/
index a98ef13930979a129a8d0195e5a94dee3ec7bd2a..a4e72a89e4ffc4eae7a2e7e09963bd0fb58e26a4 100644 (file)
@@ -140,10 +140,10 @@ static int deliver_clone(const struct net_bridge_port *prev,
                         void (*__packet_hook)(const struct net_bridge_port *p,
                                               struct sk_buff *skb))
 {
+       struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
+
        skb = skb_clone(skb, GFP_ATOMIC);
        if (!skb) {
-               struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
-
                dev->stats.tx_dropped++;
                return -ENOMEM;
        }
index 9f07e749d7b15ce9451a8a9b8ac7ed5318568ff3..34432b4e96bb288931e8b6ebf2d8d78b5c6589c5 100644 (file)
@@ -532,6 +532,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
        new->ip_summed          = old->ip_summed;
        skb_copy_queue_mapping(new, old);
        new->priority           = old->priority;
+       new->deliver_no_wcard   = old->deliver_no_wcard;
 #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
        new->ipvs_property      = old->ipvs_property;
 #endif
@@ -569,7 +570,6 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
        C(len);
        C(data_len);
        C(mac_len);
-       C(rxhash);
        n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
        n->cloned = 1;
        n->nohdr = 0;
index 9a4a6c96cb0d634414691da197bf9e337fe18f81..041d41df1224eec36f214cd649467e423be5de96 100644 (file)
@@ -873,8 +873,10 @@ int ip_append_data(struct sock *sk,
            !exthdrlen)
                csummode = CHECKSUM_PARTIAL;
 
+       skb = skb_peek_tail(&sk->sk_write_queue);
+
        inet->cork.length += length;
-       if (((length> mtu) || !skb_queue_empty(&sk->sk_write_queue)) &&
+       if (((length > mtu) || (skb && skb_is_gso(skb))) &&
            (sk->sk_protocol == IPPROTO_UDP) &&
            (rt->u.dst.dev->features & NETIF_F_UFO)) {
                err = ip_ufo_append_data(sk, getfrag, from, length, hh_len,
@@ -892,7 +894,7 @@ int ip_append_data(struct sock *sk,
         * adding appropriate IP header.
         */
 
-       if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL)
+       if (!skb)
                goto alloc_new_skb;
 
        while (length > 0) {
@@ -1121,7 +1123,8 @@ ssize_t   ip_append_page(struct sock *sk, struct page *page,
                return -EINVAL;
 
        inet->cork.length += size;
-       if ((sk->sk_protocol == IPPROTO_UDP) &&
+       if ((size + skb->len > mtu) &&
+           (sk->sk_protocol == IPPROTO_UDP) &&
            (rt->u.dst.dev->features & NETIF_F_UFO)) {
                skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
                skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
index 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 be3d4a698692d1ce958b695c1e1676297b1d15cd..b025dc7bb0fd4e1decb356709cb3ac5d3163db58 100644 (file)
@@ -715,7 +715,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
        struct ieee80211_rx_status *rx_status;
        struct ieee80211_mgmt *mgmt;
        struct ieee80211_work *wk;
-       enum work_action rma;
+       enum work_action rma = WORK_ACT_NONE;
        u16 fc;
 
        rx_status = (struct ieee80211_rx_status *) skb->cb;
index d8f7e8ef67b41e2bedb7b47cf81070d9cd5cb390..ff04e9edbed6636198b294796654c5aab64d9fdd 100644 (file)
@@ -162,6 +162,7 @@ static inline int ip_vs_conn_hash(struct ip_vs_conn *cp)
        hash = ip_vs_conn_hashkey(cp->af, cp->protocol, &cp->caddr, cp->cport);
 
        ct_write_lock(hash);
+       spin_lock(&cp->lock);
 
        if (!(cp->flags & IP_VS_CONN_F_HASHED)) {
                list_add(&cp->c_list, &ip_vs_conn_tab[hash]);
@@ -174,6 +175,7 @@ static inline int ip_vs_conn_hash(struct ip_vs_conn *cp)
                ret = 0;
        }
 
+       spin_unlock(&cp->lock);
        ct_write_unlock(hash);
 
        return ret;
@@ -193,6 +195,7 @@ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp)
        hash = ip_vs_conn_hashkey(cp->af, cp->protocol, &cp->caddr, cp->cport);
 
        ct_write_lock(hash);
+       spin_lock(&cp->lock);
 
        if (cp->flags & IP_VS_CONN_F_HASHED) {
                list_del(&cp->c_list);
@@ -202,6 +205,7 @@ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp)
        } else
                ret = 0;
 
+       spin_unlock(&cp->lock);
        ct_write_unlock(hash);
 
        return ret;
index 3415b6ce1c0a5b1116a4e23cc710c0b8f5b0f8d5..807643bdcbac30817edecfb4185dd45826b750eb 100644 (file)
@@ -449,6 +449,7 @@ static __init void teql_master_setup(struct net_device *dev)
        dev->tx_queue_len       = 100;
        dev->flags              = IFF_NOARP;
        dev->hard_header_len    = LL_MAX_HEADER;
+       dev->priv_flags         &= ~IFF_XMIT_DST_RELEASE;
 }
 
 static LIST_HEAD(master_dev_list);
index 4bf27d90133336a1f862e6c7b28e4939397284c5..af1c173be4ad88906d55d7efa24fb47fcd0cf19d 100644 (file)
@@ -2300,7 +2300,8 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
                        return 0;
                if (xdst->xfrm_genid != dst->xfrm->genid)
                        return 0;
-               if (xdst->policy_genid != atomic_read(&xdst->pols[0]->genid))
+               if (xdst->num_pols > 0 &&
+                   xdst->policy_genid != atomic_read(&xdst->pols[0]->genid))
                        return 0;
 
                if (strict && fl &&