diff --git a/[refs] b/[refs] index 4372426d4be6..e10c4a54cd0b 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 58eba97d0774c69b1cf3e5a8ac74419409d1abbf +refs/heads/master: d5675bd204efd87a174eeea592de23c4c4e7f908 diff --git a/trunk/drivers/bluetooth/bluecard_cs.c b/trunk/drivers/bluetooth/bluecard_cs.c index 6d34f405a2f3..6f907ebed2d5 100644 --- a/trunk/drivers/bluetooth/bluecard_cs.c +++ b/trunk/drivers/bluetooth/bluecard_cs.c @@ -37,7 +37,7 @@ #include #include -#include +#include #include #include diff --git a/trunk/drivers/bluetooth/hci_bcsp.c b/trunk/drivers/bluetooth/hci_bcsp.c index 42d69d4de05c..40aec0fb8596 100644 --- a/trunk/drivers/bluetooth/hci_bcsp.c +++ b/trunk/drivers/bluetooth/hci_bcsp.c @@ -244,7 +244,7 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data, if (rel) { hdr[0] |= 0x80 + bcsp->msgq_txseq; BT_DBG("Sending packet with seqno %u", bcsp->msgq_txseq); - bcsp->msgq_txseq = (bcsp->msgq_txseq + 1) & 0x07; + bcsp->msgq_txseq = ++(bcsp->msgq_txseq) & 0x07; } if (bcsp->use_crc) diff --git a/trunk/drivers/isdn/gigaset/asyncdata.c b/trunk/drivers/isdn/gigaset/asyncdata.c index c3b1dc3a13a0..c5016bd2d94f 100644 --- a/trunk/drivers/isdn/gigaset/asyncdata.c +++ b/trunk/drivers/isdn/gigaset/asyncdata.c @@ -126,6 +126,26 @@ 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. @@ -139,8 +159,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->rx_fcs; - struct sk_buff *skb = bcs->rx_skb; + __u16 fcs = bcs->fcs; + struct sk_buff *skb = bcs->skb; unsigned char *src = inbuf->data + inbuf->head; unsigned procbytes = 0; unsigned char c; @@ -225,7 +245,8 @@ static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf) /* prepare reception of next frame */ inputstate &= ~INS_have_data; - skb = gigaset_new_rx_skb(bcs); + new_rcv_skb(bcs); + skb = bcs->skb; } else { /* empty frame (7E 7E) */ #ifdef CONFIG_GIGASET_DEBUG @@ -234,7 +255,8 @@ static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf) if (!skb) { /* skipped (?) */ gigaset_isdn_rcv_err(bcs); - skb = gigaset_new_rx_skb(bcs); + new_rcv_skb(bcs); + skb = bcs->skb; } } @@ -257,11 +279,11 @@ static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf) #endif inputstate |= INS_have_data; if (skb) { - if (skb->len >= bcs->rx_bufsize) { + if (skb->len == SBUFSIZE) { dev_warn(cs->dev, "received packet too long\n"); dev_kfree_skb_any(skb); /* skip remainder of packet */ - bcs->rx_skb = skb = NULL; + bcs->skb = skb = NULL; } else { *__skb_put(skb, 1) = c; fcs = crc_ccitt_byte(fcs, c); @@ -270,7 +292,7 @@ static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf) } bcs->inputstate = inputstate; - bcs->rx_fcs = fcs; + bcs->fcs = fcs; return procbytes; } @@ -286,18 +308,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->rx_skb; + struct sk_buff *skb = bcs->skb; unsigned char *src = inbuf->data + inbuf->head; unsigned procbytes = 0; unsigned char c; if (!skb) { /* skip this block */ - gigaset_new_rx_skb(bcs); + new_rcv_skb(bcs); return numbytes; } - while (procbytes < numbytes && skb->len < bcs->rx_bufsize) { + while (procbytes < numbytes && skb->len < SBUFSIZE) { c = *src++; procbytes++; @@ -321,7 +343,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; - gigaset_new_rx_skb(bcs); + new_rcv_skb(bcs); } bcs->inputstate = inputstate; diff --git a/trunk/drivers/isdn/gigaset/capi.c b/trunk/drivers/isdn/gigaset/capi.c index 6fbe8999c419..8f78f15c8ef7 100644 --- a/trunk/drivers/isdn/gigaset/capi.c +++ b/trunk/drivers/isdn/gigaset/capi.c @@ -70,7 +70,7 @@ #define MAX_NUMBER_DIGITS 20 #define MAX_FMT_IE_LEN 20 -/* values for bcs->apconnstate */ +/* values for gigaset_capi_appl.connected */ #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,39 +319,6 @@ 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 @@ -372,6 +339,7 @@ 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 */ @@ -383,22 +351,39 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb) } /* don't send further B3 messages if disconnected */ - if (bcs->apconnstate < APCONN_ACTIVE) { + if (ap->connected < APCONN_ACTIVE) { gig_dbg(DEBUG_LLDATA, "disconnected, discarding ack"); return; } - /* - * send DATA_B3_CONF if "delivery confirmation" bit was set in request; - * otherwise it has already been sent by do_data_b3_req() - */ + /* ToDo: honor unset "delivery confirmation" bit */ flags = CAPIMSG_FLAGS(req); - 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); + + /* 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); } EXPORT_SYMBOL_GPL(gigaset_skb_sent); @@ -427,7 +412,7 @@ void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb) } /* don't send further B3 messages if disconnected */ - if (bcs->apconnstate < APCONN_ACTIVE) { + if (ap->connected < APCONN_ACTIVE) { gig_dbg(DEBUG_LLDATA, "disconnected, discarding data"); dev_kfree_skb_any(skb); return; @@ -499,7 +484,6 @@ int gigaset_isdn_icall(struct at_state_t *at_state) u32 actCIPmask; struct sk_buff *skb; unsigned int msgsize; - unsigned long flags; int i; /* @@ -624,14 +608,7 @@ int gigaset_isdn_icall(struct at_state_t *at_state) format_ie(iif->hcmsg.CalledPartyNumber)); /* scan application list for matching listeners */ - 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); + bcs->ap = NULL; actCIPmask = 1 | (1 << iif->hcmsg.CIPValue); list_for_each_entry(ap, &iif->appls, ctrlist) if (actCIPmask & ap->listenCIPmask) { @@ -649,12 +626,10 @@ 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; - bcs->apconnstate = APCONN_SETUP; - spin_unlock_irqrestore(&bcs->aplock, flags); + ap->connected = APCONN_SETUP; /* emit message */ capi_ctr_handle_message(&iif->ctr, ap->id, skb); @@ -679,7 +654,7 @@ static void send_disconnect_ind(struct bc_state *bcs, struct gigaset_capi_ctr *iif = cs->iif; struct sk_buff *skb; - if (bcs->apconnstate == APCONN_NONE) + if (ap->connected == APCONN_NONE) return; capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT, CAPI_IND, @@ -693,6 +668,7 @@ 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); } @@ -709,9 +685,9 @@ static void send_disconnect_b3_ind(struct bc_state *bcs, struct sk_buff *skb; /* nothing to do if no logical connection active */ - if (bcs->apconnstate < APCONN_ACTIVE) + if (ap->connected < APCONN_ACTIVE) return; - bcs->apconnstate = APCONN_SETUP; + ap->connected = APCONN_SETUP; capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND, ap->nextMessageNumber++, @@ -738,25 +714,14 @@ 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; + struct gigaset_capi_appl *ap = bcs->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", @@ -765,6 +730,11 @@ 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 @@ -802,24 +772,17 @@ 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) */ - spin_lock_irqsave(&bcs->aplock, flags); - while (bcs->ap != NULL) { - ap = bcs->ap; - bcs->ap = ap->bcnext; - spin_unlock_irqrestore(&bcs->aplock, flags); + for (ap = bcs->ap; ap != NULL; ap = ap->bcnext) { send_disconnect_b3_ind(bcs, ap); send_disconnect_ind(bcs, ap, 0); - spin_lock_irqsave(&bcs->aplock, flags); } - bcs->apconnstate = APCONN_NONE; - spin_unlock_irqrestore(&bcs->aplock, flags); + bcs->ap = NULL; } /** @@ -833,21 +796,24 @@ 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; + struct gigaset_capi_appl *ap = bcs->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; } - if (!bcs->apconnstate) { - 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; + } + if (!ap->connected) { dev_warn(cs->dev, "%s: application %u not connected\n", __func__, ap->id); return; @@ -859,26 +825,13 @@ 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 (bcs->apconnstate >= APCONN_ACTIVE) { + if (ap->connected >= 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)); @@ -889,6 +842,7 @@ 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); } @@ -991,64 +945,8 @@ 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); } /* @@ -1060,19 +958,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) { - /* remove from any channels */ - for (ch = 0; ch < cs->channels; ch++) - remove_appl_from_channel(&cs->bcs[ch], ap); - - /* remove from registration list */ + if (ap->connected != APCONN_NONE) { + dev_err(cs->dev, + "%s: application %u still connected\n", + __func__, ap->id); + /* ToDo: clear active connection */ + } list_del(&ap->ctrlist); kfree(ap); - dev_info(cs->dev, "application %u released\n", appl); } + } /* @@ -1251,8 +1149,7 @@ static void do_connect_req(struct gigaset_capi_ctr *iif, char **commands; char *s; u8 *pp; - unsigned long flags; - int i, l, lbc, lhlc; + int i, l; u16 info; /* decode message */ @@ -1267,18 +1164,8 @@ 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 */ @@ -1386,59 +1273,42 @@ static void do_connect_req(struct gigaset_capi_ctr *iif, goto error; } - /* - * 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 */ + /* check/encode parameter: BC */ + if (cmsg->BC && cmsg->BC[0]) { + /* explicit BC overrides CIP */ + l = 2*cmsg->BC[0] + 7; commands[AT_BC] = kmalloc(l, GFP_KERNEL); if (!commands[AT_BC]) goto oom; strcpy(commands[AT_BC], "^SBC="); - 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); - } + decode_ie(cmsg->BC, commands[AT_BC]+5); strcpy(commands[AT_BC] + l - 2, "\r"); - } else { - /* no BC */ - if (lhlc) { - dev_notice(cs->dev, "%s: cannot set HLC without BC\n", - "CONNECT_REQ"); - info = CapiIllMessageParmCoding; /* ? */ - goto error; - } + } 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); } /* check/encode parameter: B Protocol */ @@ -1452,13 +1322,13 @@ static void do_connect_req(struct gigaset_capi_ctr *iif, bcs->proto2 = L2_HDLC; break; case 1: - bcs->proto2 = L2_VOICE; + bcs->proto2 = L2_BITSYNC; break; default: dev_warn(cs->dev, "B1 Protocol %u unsupported, using Transparent\n", cmsg->B1protocol); - bcs->proto2 = L2_VOICE; + bcs->proto2 = L2_BITSYNC; } if (cmsg->B2protocol != 1) dev_warn(cs->dev, @@ -1512,6 +1382,7 @@ 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; @@ -1539,7 +1410,6 @@ 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 */ @@ -1559,24 +1429,12 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif, switch (cmsg->Reject) { case 0: /* Accept */ /* drop all competing applications, keep only this one */ - 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); + for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) + if (oap != ap) 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 */ @@ -1590,13 +1448,13 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif, bcs->proto2 = L2_HDLC; break; case 1: - bcs->proto2 = L2_VOICE; + bcs->proto2 = L2_BITSYNC; break; default: dev_warn(cs->dev, "B1 Protocol %u unsupported, using Transparent\n", cmsg->B1protocol); - bcs->proto2 = L2_VOICE; + bcs->proto2 = L2_BITSYNC; } if (cmsg->B2protocol != 1) dev_warn(cs->dev, @@ -1644,45 +1502,31 @@ 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 */ - 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); + for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) + if (oap != ap) 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", @@ -1705,7 +1549,6 @@ 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 */ @@ -1720,10 +1563,9 @@ 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 */ - bcs->apconnstate = APCONN_ACTIVE; + ap->connected = APCONN_ACTIVE; /* build NCCI: always 1 (one B3 connection only) */ cmsg->adr.adrNCCI |= 1 << 16; @@ -1769,7 +1611,7 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif, if (cmsg->Reject) { /* Reject: clear B3 connect received flag */ - bcs->apconnstate = APCONN_SETUP; + ap->connected = APCONN_SETUP; /* trigger hangup, causing eventual DISCONNECT_IND */ if (!gigaset_add_event(cs, &bcs->at_state, @@ -1841,11 +1683,11 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif, } /* skip if DISCONNECT_IND already sent */ - if (!bcs->apconnstate) + if (!ap->connected) return; /* check for active logical connection */ - if (bcs->apconnstate >= APCONN_ACTIVE) { + if (ap->connected >= APCONN_ACTIVE) { /* * emit DISCONNECT_B3_IND with cause 0x3301 * use separate cmsg structure, as the content of iif->acmsg @@ -1894,7 +1736,6 @@ 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 */ @@ -1910,17 +1751,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 (bcs->apconnstate < APCONN_ACTIVE) { + if (ap->connected < APCONN_ACTIVE) { send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState); return; } /* trigger hangup, causing eventual DISCONNECT_B3_IND */ - if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) { + if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state, + EV_HUP, NULL, 0, NULL)) { send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); return; } @@ -1941,14 +1782,11 @@ 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); @@ -1964,7 +1802,6 @@ 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); @@ -1984,7 +1821,7 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif, } /* reject if logical connection not active */ - if (bcs->apconnstate < APCONN_ACTIVE) { + if (ap->connected < APCONN_ACTIVE) { send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState); return; } @@ -1995,19 +1832,17 @@ 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(bcs, skb) < 0) { + if (cs->ops->send_skb(&cs->bcs[channel-1], skb) < 0) { send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); return; } + /* DATA_B3_CONF reply will be sent by gigaset_skb_sent() */ + /* - * DATA_B3_CONF will be sent by gigaset_skb_sent() only if "delivery - * confirmation" bit is set; otherwise we have to send it now + * ToDo: honor unset "delivery confirmation" bit + * (send DATA_B3_CONF immediately?) */ - if (!(flags & CAPI_FLAGS_DELIVERY_CONFIRMATION)) - send_data_b3_conf(cs, &iif->ctr, ap->id, msgid, channel, handle, - flags ? CapiFlagsNotSupportedByProtocol - : CAPI_NOERROR); } /* diff --git a/trunk/drivers/isdn/gigaset/common.c b/trunk/drivers/isdn/gigaset/common.c index 5d4befb81057..f6f45f221920 100644 --- a/trunk/drivers/isdn/gigaset/common.c +++ b/trunk/drivers/isdn/gigaset/common.c @@ -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->rx_skb); - bcs->rx_skb = NULL; + dev_kfree_skb(bcs->skb); + bcs->skb = NULL; for (i = 0; i < AT_NUM; ++i) { kfree(bcs->commands[i]); @@ -634,10 +634,19 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, bcs->emptycount = 0; #endif - bcs->rx_bufsize = 0; - bcs->rx_skb = NULL; - bcs->rx_fcs = PPP_INITFCS; + gig_dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel); + bcs->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; @@ -649,15 +658,16 @@ 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; } @@ -829,12 +839,14 @@ void gigaset_bcs_reinit(struct bc_state *bcs) bcs->emptycount = 0; #endif - bcs->rx_fcs = PPP_INITFCS; + bcs->fcs = PPP_INITFCS; bcs->chstate = 0; bcs->ignore = cs->ignoreframes; - dev_kfree_skb(bcs->rx_skb); - bcs->rx_skb = NULL; + if (bcs->ignore) { + dev_kfree_skb(bcs->skb); + bcs->skb = NULL; + } cs->ops->reinitbcshw(bcs); } diff --git a/trunk/drivers/isdn/gigaset/ev-layer.c b/trunk/drivers/isdn/gigaset/ev-layer.c index ceaef9a04a42..206c380c5235 100644 --- a/trunk/drivers/isdn/gigaset/ev-layer.c +++ b/trunk/drivers/isdn/gigaset/ev-layer.c @@ -282,7 +282,9 @@ 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, 603, 5, {ACT_CMD+AT_PROTO} }, +{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, 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} }, diff --git a/trunk/drivers/isdn/gigaset/gigaset.h b/trunk/drivers/isdn/gigaset/gigaset.h index 8738b0821fc9..05947f9c1849 100644 --- a/trunk/drivers/isdn/gigaset/gigaset.h +++ b/trunk/drivers/isdn/gigaset/gigaset.h @@ -45,6 +45,10 @@ #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 @@ -186,9 +190,10 @@ 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_CLIP 6 +#define AT_HLC 6 +#define AT_CLIP 7 /* total number */ -#define AT_NUM 7 +#define AT_NUM 8 /* variables in struct at_state_t */ #define VAR_ZSAU 0 @@ -375,10 +380,8 @@ struct bc_state { struct at_state_t at_state; - /* receive buffer */ - unsigned rx_bufsize; /* max size accepted by application */ - struct sk_buff *rx_skb; - __u16 rx_fcs; + __u16 fcs; + struct sk_buff *skb; int inputstate; /* see INS_XXXX */ int channel; @@ -403,9 +406,7 @@ struct bc_state { struct bas_bc_state *bas; /* usb hardware driver (base) */ } hw; - void *ap; /* associated LL application */ - int apconnstate; /* LL application connection state */ - spinlock_t aplock; + void *ap; /* LL application structure */ }; struct cardstate { @@ -800,23 +801,8 @@ static inline void gigaset_bchannel_up(struct bc_state *bcs) gigaset_schedule_event(bcs->cs); } -/* 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; -} +/* handling routines for sk_buff */ +/* ============================= */ /* append received bytes to inbuf */ int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, diff --git a/trunk/drivers/isdn/gigaset/i4l.c b/trunk/drivers/isdn/gigaset/i4l.c index f01c3c2e2e46..c22e5ace8276 100644 --- a/trunk/drivers/isdn/gigaset/i4l.c +++ b/trunk/drivers/isdn/gigaset/i4l.c @@ -16,10 +16,7 @@ #include "gigaset.h" #include -#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 =====================================================*/ @@ -234,15 +231,6 @@ 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) { @@ -326,15 +314,6 @@ 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; diff --git a/trunk/drivers/isdn/gigaset/isocdata.c b/trunk/drivers/isdn/gigaset/isocdata.c index 2dfd346fc889..16fd3bd48883 100644 --- a/trunk/drivers/isdn/gigaset/isocdata.c +++ b/trunk/drivers/isdn/gigaset/isocdata.c @@ -500,18 +500,19 @@ 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->rx_fcs = crc_ccitt_byte(bcs->rx_fcs, c); - if (bcs->rx_skb == NULL) + bcs->fcs = crc_ccitt_byte(bcs->fcs, c); + if (unlikely(bcs->skb == NULL)) { /* skipping */ return; - if (bcs->rx_skb->len >= bcs->rx_bufsize) { + } + if (unlikely(bcs->skb->len == SBUFSIZE)) { dev_warn(bcs->cs->dev, "received oversized packet discarded\n"); bcs->hw.bas->giants++; - dev_kfree_skb_any(bcs->rx_skb); - bcs->rx_skb = NULL; + dev_kfree_skb_any(bcs->skb); + bcs->skb = NULL; return; } - *__skb_put(bcs->rx_skb, 1) = c; + *__skb_put(bcs->skb, 1) = c; } /* hdlc_flush @@ -520,13 +521,18 @@ 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 (bcs->rx_skb != NULL) - skb_trim(bcs->rx_skb, 0); - else - gigaset_new_rx_skb(bcs); + 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"); + } /* reset packet state */ - bcs->rx_fcs = PPP_INITFCS; + bcs->fcs = PPP_INITFCS; } /* hdlc_done @@ -543,7 +549,7 @@ static inline void hdlc_done(struct bc_state *bcs) hdlc_flush(bcs); return; } - procskb = bcs->rx_skb; + procskb = bcs->skb; if (procskb == NULL) { /* previous error */ gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__); @@ -554,8 +560,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->rx_fcs != PPP_GOODFCS) { - dev_notice(cs->dev, "frame check error\n"); + } else if (bcs->fcs != PPP_GOODFCS) { + dev_notice(cs->dev, "frame check error (0x%04x)\n", bcs->fcs); bcs->hw.bas->fcserrs++; dev_kfree_skb_any(procskb); gigaset_isdn_rcv_err(bcs); @@ -568,8 +574,13 @@ static inline void hdlc_done(struct bc_state *bcs) bcs->hw.bas->goodbytes += len; gigaset_skb_rcvd(bcs, procskb); } - gigaset_new_rx_skb(bcs); - bcs->rx_fcs = PPP_INITFCS; + + 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; } /* hdlc_frag @@ -586,8 +597,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->rx_skb, 0); - bcs->rx_fcs = PPP_INITFCS; + __skb_trim(bcs->skb, 0); + bcs->fcs = PPP_INITFCS; } /* bit counts lookup table for HDLC bit unstuffing @@ -836,6 +847,7 @@ 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; @@ -845,11 +857,17 @@ static inline void trans_receive(unsigned char *src, unsigned count, hdlc_flush(bcs); return; } - skb = bcs->rx_skb; - if (skb == NULL) - skb = gigaset_new_rx_skb(bcs); + 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); + } bcs->hw.bas->goodbytes += skb->len; - dobytes = bcs->rx_bufsize - skb->len; + dobytes = TRANSBUFSIZE - skb->len; while (count > 0) { dst = skb_put(skb, count < dobytes ? count : dobytes); while (count > 0 && dobytes > 0) { @@ -861,10 +879,14 @@ 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); - skb = gigaset_new_rx_skb(bcs); - if (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; - dobytes = bcs->rx_bufsize; + } + skb_reserve(skb, cs->hw_hdr_len); + dobytes = TRANSBUFSIZE; } } } diff --git a/trunk/drivers/isdn/hysdn/hysdn_net.c b/trunk/drivers/isdn/hysdn/hysdn_net.c index feec8d89d719..72eb92647c1b 100644 --- a/trunk/drivers/isdn/hysdn/hysdn_net.c +++ b/trunk/drivers/isdn/hysdn/hysdn_net.c @@ -187,13 +187,12 @@ void hysdn_rx_netpkt(hysdn_card * card, unsigned char *buf, unsigned short len) { struct net_local *lp = card->netif; - struct net_device *dev; + struct net_device *dev = lp->dev; struct sk_buff *skb; if (!lp) return; /* non existing device */ - dev = lp->dev; dev->stats.rx_bytes += len; skb = dev_alloc_skb(len); diff --git a/trunk/drivers/net/bonding/bond_alb.c b/trunk/drivers/net/bonding/bond_alb.c index df483076eda6..40fdc41446cc 100644 --- a/trunk/drivers/net/bonding/bond_alb.c +++ b/trunk/drivers/net/bonding/bond_alb.c @@ -340,8 +340,7 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp) if ((client_info->assigned) && (client_info->ip_src == arp->ip_dst) && - (client_info->ip_dst == arp->ip_src) && - (compare_ether_addr_64bits(client_info->mac_dst, arp->mac_src))) { + (client_info->ip_dst == arp->ip_src)) { /* update the clients MAC address */ memcpy(client_info->mac_dst, arp->mac_src, ETH_ALEN); client_info->ntt = 1; diff --git a/trunk/drivers/net/bonding/bond_main.c b/trunk/drivers/net/bonding/bond_main.c index c3d98dde2f86..5e12462a9d5e 100644 --- a/trunk/drivers/net/bonding/bond_main.c +++ b/trunk/drivers/net/bonding/bond_main.c @@ -168,7 +168,7 @@ static int arp_ip_count; static int bond_mode = BOND_MODE_ROUNDROBIN; static int xmit_hashtype = BOND_XMIT_POLICY_LAYER2; static int lacp_fast; -static int disable_netpoll = 1; + const struct bond_parm_tbl bond_lacp_tbl[] = { { "slow", AD_LACP_SLOW}, @@ -1742,23 +1742,15 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) bond_set_carrier(bond); #ifdef CONFIG_NET_POLL_CONTROLLER - /* - * Netpoll and bonding is broken, make sure it is not initialized - * until it is fixed. - */ - if (disable_netpoll) { + if (slaves_support_netpoll(bond_dev)) { + bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL; + if (bond_dev->npinfo) + slave_dev->npinfo = bond_dev->npinfo; + } else if (!(bond_dev->priv_flags & IFF_DISABLE_NETPOLL)) { bond_dev->priv_flags |= IFF_DISABLE_NETPOLL; - } else { - if (slaves_support_netpoll(bond_dev)) { - bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL; - if (bond_dev->npinfo) - slave_dev->npinfo = bond_dev->npinfo; - } else if (!(bond_dev->priv_flags & IFF_DISABLE_NETPOLL)) { - bond_dev->priv_flags |= IFF_DISABLE_NETPOLL; - pr_info("New slave device %s does not support netpoll\n", - slave_dev->name); - pr_info("Disabling netpoll support for %s\n", bond_dev->name); - } + pr_info("New slave device %s does not support netpoll\n", + slave_dev->name); + pr_info("Disabling netpoll support for %s\n", bond_dev->name); } #endif read_unlock(&bond->lock); @@ -1958,11 +1950,8 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) #ifdef CONFIG_NET_POLL_CONTROLLER read_lock_bh(&bond->lock); - - /* Make sure netpoll over stays disabled until fixed. */ - if (!disable_netpoll) - if (slaves_support_netpoll(bond_dev)) - bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL; + if (slaves_support_netpoll(bond_dev)) + bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL; read_unlock_bh(&bond->lock); if (slave_dev->netdev_ops->ndo_netpoll_cleanup) slave_dev->netdev_ops->ndo_netpoll_cleanup(slave_dev); diff --git a/trunk/drivers/net/cpmac.c b/trunk/drivers/net/cpmac.c index 23786ee34bed..3c58db595285 100644 --- a/trunk/drivers/net/cpmac.c +++ b/trunk/drivers/net/cpmac.c @@ -1181,8 +1181,7 @@ 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); - rc = PTR_ERR(priv->phy); - goto fail; + return PTR_ERR(priv->phy); } if ((rc = register_netdev(dev))) { diff --git a/trunk/drivers/net/ixgbe/ixgbe_main.c b/trunk/drivers/net/ixgbe/ixgbe_main.c index 7b5d9764f317..ce30c62a97f7 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_main.c +++ b/trunk/drivers/net/ixgbe/ixgbe_main.c @@ -3684,6 +3684,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter) /* signal that we are down to the interrupt handler */ set_bit(__IXGBE_DOWN, &adapter->state); + /* power down the optics */ + if (hw->phy.multispeed_fiber) + hw->mac.ops.disable_tx_laser(hw); + /* disable receive for all VFs and wait one second */ if (adapter->num_vfs) { /* ping all the active vfs to let them know we are going down */ @@ -3738,10 +3742,6 @@ void ixgbe_down(struct ixgbe_adapter *adapter) (IXGBE_READ_REG(hw, IXGBE_DMATXCTL) & ~IXGBE_DMATXCTL_TE)); - /* power down the optics */ - if (hw->phy.multispeed_fiber) - hw->mac.ops.disable_tx_laser(hw); - /* clear n-tuple filters that are cached */ ethtool_ntuple_flush(netdev); @@ -4001,7 +4001,7 @@ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter) done: /* Notify the stack of the (possibly) reduced Tx Queue count. */ - netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues); + adapter->netdev->real_num_tx_queues = adapter->num_tx_queues; } static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter, @@ -5195,6 +5195,7 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake) ixgbe_free_all_tx_resources(adapter); ixgbe_free_all_rx_resources(adapter); } + ixgbe_clear_interrupt_scheme(adapter); #ifdef CONFIG_PM retval = pci_save_state(pdev); @@ -5229,8 +5230,6 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake) *enable_wake = !!wufc; - ixgbe_clear_interrupt_scheme(adapter); - ixgbe_release_hw_control(adapter); pci_disable_device(pdev); @@ -6024,6 +6023,7 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter, static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb, int queue, u32 tx_flags) { + /* Right now, we support IPv4 only */ struct ixgbe_atr_input atr_input; struct tcphdr *th; struct iphdr *iph = ip_hdr(skb); @@ -6032,9 +6032,6 @@ static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb, u32 src_ipv4_addr, dst_ipv4_addr; u8 l4type = 0; - /* Right now, we support IPv4 only */ - if (skb->protocol != htons(ETH_P_IP)) - return; /* check if we're UDP or TCP */ if (iph->protocol == IPPROTO_TCP) { th = tcp_hdr(skb); diff --git a/trunk/drivers/net/mv643xx_eth.c b/trunk/drivers/net/mv643xx_eth.c index 73bb8ea6f54a..e345ec8cb473 100644 --- a/trunk/drivers/net/mv643xx_eth.c +++ b/trunk/drivers/net/mv643xx_eth.c @@ -289,7 +289,6 @@ struct mv643xx_eth_shared_private { unsigned int t_clk; int extended_rx_coal_limit; int tx_bw_control; - int tx_csum_limit; }; #define TX_BW_CONTROL_ABSENT 0 @@ -777,16 +776,13 @@ static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb) l4i_chk = 0; if (skb->ip_summed == CHECKSUM_PARTIAL) { - int hdr_len; int tag_bytes; BUG_ON(skb->protocol != htons(ETH_P_IP) && skb->protocol != htons(ETH_P_8021Q)); - hdr_len = (void *)ip_hdr(skb) - (void *)skb->data; - tag_bytes = hdr_len - ETH_HLEN; - if (skb->len - hdr_len > mp->shared->tx_csum_limit || - unlikely(tag_bytes & ~12)) { + tag_bytes = (void *)ip_hdr(skb) - (void *)skb->data - ETH_HLEN; + if (unlikely(tag_bytes & ~12)) { if (skb_checksum_help(skb) == 0) goto no_csum; kfree_skb(skb); @@ -2670,7 +2666,6 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev) * Detect hardware parameters. */ msp->t_clk = (pd != NULL && pd->t_clk != 0) ? pd->t_clk : 133000000; - msp->tx_csum_limit = pd->tx_csum_limit ? pd->tx_csum_limit : 9 * 1024; infer_hw_params(msp); platform_set_drvdata(pdev, msp); diff --git a/trunk/drivers/net/pcmcia/smc91c92_cs.c b/trunk/drivers/net/pcmcia/smc91c92_cs.c index 307cd1721e91..64e6a84bbbbe 100644 --- a/trunk/drivers/net/pcmcia/smc91c92_cs.c +++ b/trunk/drivers/net/pcmcia/smc91c92_cs.c @@ -1505,20 +1505,12 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id) writeb(cor & ~COR_IREQ_ENA, smc->base + MOT_LAN + CISREG_COR); writeb(cor, smc->base + MOT_LAN + CISREG_COR); } - - 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); +#ifdef DOES_NOT_WORK + if (smc->base != NULL) { /* Megahertz MFC's */ + readb(smc->base+MEGAHERTZ_ISR); + readb(smc->base+MEGAHERTZ_ISR); } - +#endif spin_unlock(&smc->lock); return IRQ_RETVAL(handled); } diff --git a/trunk/drivers/net/phy/lxt.c b/trunk/drivers/net/phy/lxt.c index 29c39ff85de5..dbd003453737 100644 --- a/trunk/drivers/net/phy/lxt.c +++ b/trunk/drivers/net/phy/lxt.c @@ -226,7 +226,6 @@ module_exit(lxt_exit); static struct mdio_device_id lxt_tbl[] = { { 0x78100000, 0xfffffff0 }, { 0x001378e0, 0xfffffff0 }, - { 0x00137a10, 0xfffffff0 }, { } }; diff --git a/trunk/drivers/net/qlge/qlge_main.c b/trunk/drivers/net/qlge/qlge_main.c index d10bcefc0e45..fa4b24c49f42 100644 --- a/trunk/drivers/net/qlge/qlge_main.c +++ b/trunk/drivers/net/qlge/qlge_main.c @@ -4611,7 +4611,8 @@ static void ql_timer(unsigned long data) return; } - mod_timer(&qdev->timer, jiffies + (5*HZ)); + qdev->timer.expires = jiffies + (5*HZ); + add_timer(&qdev->timer); } static int __devinit qlge_probe(struct pci_dev *pdev, @@ -4712,8 +4713,6 @@ static void ql_eeh_close(struct net_device *ndev) netif_stop_queue(ndev); } - /* Disabling the timer */ - del_timer_sync(&qdev->timer); if (test_bit(QL_ADAPTER_UP, &qdev->flags)) cancel_delayed_work_sync(&qdev->asic_reset_work); cancel_delayed_work_sync(&qdev->mpi_reset_work); @@ -4809,7 +4808,8 @@ static void qlge_io_resume(struct pci_dev *pdev) netif_err(qdev, ifup, qdev->ndev, "Device was not running prior to EEH.\n"); } - mod_timer(&qdev->timer, jiffies + (5*HZ)); + qdev->timer.expires = jiffies + (5*HZ); + add_timer(&qdev->timer); netif_device_attach(ndev); } @@ -4871,7 +4871,8 @@ static int qlge_resume(struct pci_dev *pdev) return err; } - mod_timer(&qdev->timer, jiffies + (5*HZ)); + qdev->timer.expires = jiffies + (5*HZ); + add_timer(&qdev->timer); netif_device_attach(ndev); return 0; diff --git a/trunk/drivers/net/s2io.c b/trunk/drivers/net/s2io.c index 1d37f0c310ca..668327ccd8d0 100644 --- a/trunk/drivers/net/s2io.c +++ b/trunk/drivers/net/s2io.c @@ -3130,6 +3130,7 @@ static void tx_intr_handler(struct fifo_info *fifo_data) pkt_cnt++; /* Updating the statistics block */ + nic->dev->stats.tx_bytes += skb->len; swstats->mem_freed += skb->truesize; dev_kfree_skb_irq(skb); @@ -4900,81 +4901,48 @@ static void s2io_updt_stats(struct s2io_nic *sp) * Return value: * pointer to the updated net_device_stats structure. */ + static struct net_device_stats *s2io_get_stats(struct net_device *dev) { struct s2io_nic *sp = netdev_priv(dev); + struct config_param *config = &sp->config; struct mac_info *mac_control = &sp->mac_control; struct stat_block *stats = mac_control->stats_info; - u64 delta; + int i; /* Configure Stats for immediate updt */ s2io_updt_stats(sp); - /* A device reset will cause the on-adapter statistics to be zero'ed. - * This can be done while running by changing the MTU. To prevent the - * system from having the stats zero'ed, the driver keeps a copy of the - * last update to the system (which is also zero'ed on reset). This - * enables the driver to accurately know the delta between the last - * update and the current update. - */ - delta = ((u64) le32_to_cpu(stats->rmac_vld_frms_oflow) << 32 | - le32_to_cpu(stats->rmac_vld_frms)) - sp->stats.rx_packets; - sp->stats.rx_packets += delta; - dev->stats.rx_packets += delta; - - delta = ((u64) le32_to_cpu(stats->tmac_frms_oflow) << 32 | - le32_to_cpu(stats->tmac_frms)) - sp->stats.tx_packets; - sp->stats.tx_packets += delta; - dev->stats.tx_packets += delta; - - delta = ((u64) le32_to_cpu(stats->rmac_data_octets_oflow) << 32 | - le32_to_cpu(stats->rmac_data_octets)) - sp->stats.rx_bytes; - sp->stats.rx_bytes += delta; - dev->stats.rx_bytes += delta; - - delta = ((u64) le32_to_cpu(stats->tmac_data_octets_oflow) << 32 | - le32_to_cpu(stats->tmac_data_octets)) - sp->stats.tx_bytes; - sp->stats.tx_bytes += delta; - dev->stats.tx_bytes += delta; - - delta = le64_to_cpu(stats->rmac_drop_frms) - sp->stats.rx_errors; - sp->stats.rx_errors += delta; - dev->stats.rx_errors += delta; - - delta = ((u64) le32_to_cpu(stats->tmac_any_err_frms_oflow) << 32 | - le32_to_cpu(stats->tmac_any_err_frms)) - sp->stats.tx_errors; - sp->stats.tx_errors += delta; - dev->stats.tx_errors += delta; - - delta = le64_to_cpu(stats->rmac_drop_frms) - sp->stats.rx_dropped; - sp->stats.rx_dropped += delta; - dev->stats.rx_dropped += delta; - - delta = le64_to_cpu(stats->tmac_drop_frms) - sp->stats.tx_dropped; - sp->stats.tx_dropped += delta; - dev->stats.tx_dropped += delta; - - /* The adapter MAC interprets pause frames as multicast packets, but - * does not pass them up. This erroneously increases the multicast - * packet count and needs to be deducted when the multicast frame count - * is queried. - */ - delta = (u64) le32_to_cpu(stats->rmac_vld_mcst_frms_oflow) << 32 | - le32_to_cpu(stats->rmac_vld_mcst_frms); - delta -= le64_to_cpu(stats->rmac_pause_ctrl_frms); - delta -= sp->stats.multicast; - sp->stats.multicast += delta; - dev->stats.multicast += delta; + /* Using sp->stats as a staging area, because reset (due to mtu + change, for example) will clear some hardware counters */ + dev->stats.tx_packets += le32_to_cpu(stats->tmac_frms) - + sp->stats.tx_packets; + sp->stats.tx_packets = le32_to_cpu(stats->tmac_frms); + + dev->stats.tx_errors += le32_to_cpu(stats->tmac_any_err_frms) - + sp->stats.tx_errors; + sp->stats.tx_errors = le32_to_cpu(stats->tmac_any_err_frms); - delta = ((u64) le32_to_cpu(stats->rmac_usized_frms_oflow) << 32 | - le32_to_cpu(stats->rmac_usized_frms)) + - le64_to_cpu(stats->rmac_long_frms) - sp->stats.rx_length_errors; - sp->stats.rx_length_errors += delta; - dev->stats.rx_length_errors += delta; + dev->stats.rx_errors += le64_to_cpu(stats->rmac_drop_frms) - + sp->stats.rx_errors; + sp->stats.rx_errors = le64_to_cpu(stats->rmac_drop_frms); - delta = le64_to_cpu(stats->rmac_fcs_err_frms) - sp->stats.rx_crc_errors; - sp->stats.rx_crc_errors += delta; - dev->stats.rx_crc_errors += delta; + dev->stats.multicast = le32_to_cpu(stats->rmac_vld_mcst_frms) - + sp->stats.multicast; + sp->stats.multicast = le32_to_cpu(stats->rmac_vld_mcst_frms); + + dev->stats.rx_length_errors = le64_to_cpu(stats->rmac_long_frms) - + sp->stats.rx_length_errors; + sp->stats.rx_length_errors = le64_to_cpu(stats->rmac_long_frms); + + /* collect per-ring rx_packets and rx_bytes */ + dev->stats.rx_packets = dev->stats.rx_bytes = 0; + for (i = 0; i < config->rx_ring_num; i++) { + struct ring_info *ring = &mac_control->rings[i]; + + dev->stats.rx_packets += ring->rx_packets; + dev->stats.rx_bytes += ring->rx_bytes; + } return &dev->stats; } @@ -7487,11 +7455,15 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) } } + /* Updating statistics */ + ring_data->rx_packets++; rxdp->Host_Control = 0; if (sp->rxd_mode == RXD_MODE_1) { int len = RXD_GET_BUFFER0_SIZE_1(rxdp->Control_2); + ring_data->rx_bytes += len; skb_put(skb, len); + } else if (sp->rxd_mode == RXD_MODE_3B) { int get_block = ring_data->rx_curr_get_info.block_index; int get_off = ring_data->rx_curr_get_info.offset; @@ -7500,6 +7472,7 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp) unsigned char *buff = skb_push(skb, buf0_len); struct buffAdd *ba = &ring_data->ba[get_block][get_off]; + ring_data->rx_bytes += buf0_len + buf2_len; memcpy(buff, ba->ba_0, buf0_len); skb_put(skb, buf2_len); } diff --git a/trunk/drivers/net/s2io.h b/trunk/drivers/net/s2io.h index 5e52c75892df..47c36e0994f5 100644 --- a/trunk/drivers/net/s2io.h +++ b/trunk/drivers/net/s2io.h @@ -745,6 +745,10 @@ struct ring_info { /* Buffer Address store. */ struct buffAdd **ba; + + /* per-Ring statistics */ + unsigned long rx_packets; + unsigned long rx_bytes; } ____cacheline_aligned; /* Fifo specific structure */ diff --git a/trunk/drivers/net/usb/rndis_host.c b/trunk/drivers/net/usb/rndis_host.c index dd8a4adf48ca..28d3ee175e7b 100644 --- a/trunk/drivers/net/usb/rndis_host.c +++ b/trunk/drivers/net/usb/rndis_host.c @@ -104,8 +104,10 @@ static void rndis_msg_indicate(struct usbnet *dev, struct rndis_indicate *msg, int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen) { struct cdc_state *info = (void *) &dev->data; + struct usb_cdc_notification notification; int master_ifnum; int retval; + int partial; unsigned count; __le32 rsp; u32 xid = 0, msg_len, request_id; @@ -133,13 +135,17 @@ int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen) if (unlikely(retval < 0 || xid == 0)) return retval; - // FIXME Seems like some devices discard responses when - // we time out and cancel our "get response" requests... - // so, this is fragile. Probably need to poll for status. + /* Some devices don't respond on the control channel until + * polled on the status channel, so do that first. */ + retval = usb_interrupt_msg( + dev->udev, + usb_rcvintpipe(dev->udev, dev->status->desc.bEndpointAddress), + ¬ification, sizeof(notification), &partial, + RNDIS_CONTROL_TIMEOUT_MS); + if (unlikely(retval < 0)) + return retval; - /* ignore status endpoint, just poll the control channel; - * the request probably completed immediately - */ + /* Poll the control channel; the request probably completed immediately */ rsp = buf->msg_type | RNDIS_MSG_COMPLETION; for (count = 0; count < 10; count++) { memset(buf, 0, CONTROL_BUFFER_SIZE); diff --git a/trunk/drivers/net/usb/usbnet.c b/trunk/drivers/net/usb/usbnet.c index 81c76ada8e56..a95c73de5824 100644 --- a/trunk/drivers/net/usb/usbnet.c +++ b/trunk/drivers/net/usb/usbnet.c @@ -1293,9 +1293,6 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) goto out; } - /* netdev_printk() needs this so do it as early as possible */ - SET_NETDEV_DEV(net, &udev->dev); - dev = netdev_priv(net); dev->udev = xdev; dev->intf = udev; @@ -1380,6 +1377,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) dev->rx_urb_size = dev->hard_mtu; dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1); + SET_NETDEV_DEV(net, &udev->dev); + if ((dev->driver_info->flags & FLAG_WLAN) != 0) SET_NETDEV_DEVTYPE(net, &wlan_type); if ((dev->driver_info->flags & FLAG_WWAN) != 0) diff --git a/trunk/drivers/net/virtio_net.c b/trunk/drivers/net/virtio_net.c index bb6b67f6b0cc..1edb7a61983c 100644 --- a/trunk/drivers/net/virtio_net.c +++ b/trunk/drivers/net/virtio_net.c @@ -415,7 +415,7 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp) static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp) { int err; - bool oom; + bool oom = false; do { if (vi->mergeable_rx_bufs) @@ -425,9 +425,10 @@ static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp) else err = add_recvbuf_small(vi, gfp); - oom = err == -ENOMEM; - if (err < 0) + if (err < 0) { + oom = true; break; + } ++vi->num; } while (err > 0); if (unlikely(vi->num > vi->max)) @@ -562,6 +563,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) struct virtnet_info *vi = netdev_priv(dev); int capacity; +again: /* Free up any pending old buffers before queueing new ones. */ free_old_xmit_skbs(vi); @@ -570,20 +572,14 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) /* This can happen with OOM and indirect buffers. */ if (unlikely(capacity < 0)) { - if (net_ratelimit()) { - if (likely(capacity == -ENOMEM)) { - dev_warn(&dev->dev, - "TX queue failure: out of memory\n"); - } else { - dev->stats.tx_fifo_errors++; - dev_warn(&dev->dev, - "Unexpected TX queue failure: %d\n", - capacity); - } + netif_stop_queue(dev); + dev_warn(&dev->dev, "Unexpected full queue\n"); + if (unlikely(!virtqueue_enable_cb(vi->svq))) { + virtqueue_disable_cb(vi->svq); + netif_start_queue(dev); + goto again; } - dev->stats.tx_dropped++; - kfree_skb(skb); - return NETDEV_TX_OK; + return NETDEV_TX_BUSY; } virtqueue_kick(vi->svq); diff --git a/trunk/drivers/net/vxge/vxge-main.c b/trunk/drivers/net/vxge/vxge-main.c index d14e207de1df..b504bd561362 100644 --- a/trunk/drivers/net/vxge/vxge-main.c +++ b/trunk/drivers/net/vxge/vxge-main.c @@ -2262,8 +2262,7 @@ static int vxge_alloc_msix(struct vxgedev *vdev) vxge_debug_init(VXGE_ERR, "%s: memory allocation failed", VXGE_DRIVER_NAME); - ret = -ENOMEM; - goto alloc_entries_failed; + return -ENOMEM; } vdev->vxge_entries = @@ -2272,8 +2271,8 @@ static int vxge_alloc_msix(struct vxgedev *vdev) if (!vdev->vxge_entries) { vxge_debug_init(VXGE_ERR, "%s: memory allocation failed", VXGE_DRIVER_NAME); - ret = -ENOMEM; - goto alloc_vxge_entries_failed; + kfree(vdev->entries); + return -ENOMEM; } for (i = 0, j = 0; i < vdev->no_of_vpath; i++) { @@ -2304,32 +2303,22 @@ static int vxge_alloc_msix(struct vxgedev *vdev) 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) { - ret = -ENODEV; - goto enable_msix_failed; - } - return 0; + } else if (ret < 0) + return -ENODEV; -enable_msix_failed: - kfree(vdev->vxge_entries); -alloc_vxge_entries_failed: - kfree(vdev->entries); -alloc_entries_failed: - return ret; + return 0; } static int vxge_enable_msix(struct vxgedev *vdev) diff --git a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h index 5ea87736a6ae..fbb7dec6ddeb 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h @@ -445,7 +445,6 @@ void ath_deinit_leds(struct ath_softc *sc); #define SC_OP_TSF_RESET BIT(11) #define SC_OP_BT_PRIORITY_DETECTED BIT(12) #define SC_OP_BT_SCAN BIT(13) -#define SC_OP_ANI_RUN BIT(14) /* Powersave flags */ #define PS_WAIT_FOR_BEACON BIT(0) diff --git a/trunk/drivers/net/wireless/ath/ath9k/main.c b/trunk/drivers/net/wireless/ath/ath9k/main.c index 1e2a68ea9355..abfa0493236f 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/main.c @@ -336,10 +336,6 @@ void ath_ani_calibrate(unsigned long data) static void ath_start_ani(struct ath_common *common) { unsigned long timestamp = jiffies_to_msecs(jiffies); - struct ath_softc *sc = (struct ath_softc *) common->priv; - - if (!(sc->sc_flags & SC_OP_ANI_RUN)) - return; common->ani.longcal_timer = timestamp; common->ani.shortcal_timer = timestamp; @@ -876,13 +872,11 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, /* Reset rssi stats */ sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; - sc->sc_flags |= SC_OP_ANI_RUN; ath_start_ani(common); } else { ath_print(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); common->curaid = 0; /* Stop ANI */ - sc->sc_flags &= ~SC_OP_ANI_RUN; del_timer_sync(&common->ani.timer); } } @@ -1484,10 +1478,8 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, if (vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_ADHOC || - vif->type == NL80211_IFTYPE_MONITOR) { - sc->sc_flags |= SC_OP_ANI_RUN; + vif->type == NL80211_IFTYPE_MONITOR) ath_start_ani(common); - } out: mutex_unlock(&sc->mutex); @@ -1508,7 +1500,6 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, mutex_lock(&sc->mutex); /* Stop ANI */ - sc->sc_flags &= ~SC_OP_ANI_RUN; del_timer_sync(&common->ani.timer); /* Reclaim beacon resources */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 01658cf82d39..44ef5d93befc 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -212,7 +212,11 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv) static void iwlagn_rts_tx_cmd_flag(struct ieee80211_tx_info *info, __le32 *tx_flags) { - *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; + if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || + (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) + *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; + else + *tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK; } /* Calc max signal level (dBm) among 3 possible receivers */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-core.c b/trunk/drivers/net/wireless/iwlwifi/iwl-core.c index 5bbc5298ef96..426e95567de3 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1314,6 +1314,7 @@ void iwl_configure_filter(struct ieee80211_hw *hw, changed_flags, *total_flags); CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK); + CHK(FIF_ALLMULTI, RXON_FILTER_ACCEPT_GRP_MSK); CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK); CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK); @@ -1328,12 +1329,6 @@ void iwl_configure_filter(struct ieee80211_hw *hw, mutex_unlock(&priv->mutex); - /* - * Receiving all multicast frames is always enabled by the - * default flags setup in iwl_connection_init_rx_config() - * since we currently do not support programming multicast - * filters into the device. - */ *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; } diff --git a/trunk/drivers/vhost/net.c b/trunk/drivers/vhost/net.c index 0f41c9195e9b..54096eef4840 100644 --- a/trunk/drivers/vhost/net.c +++ b/trunk/drivers/vhost/net.c @@ -98,7 +98,8 @@ static void tx_poll_start(struct vhost_net *net, struct socket *sock) static void handle_tx(struct vhost_net *net) { struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_TX]; - unsigned head, out, in, s; + unsigned out, in, s; + int head; struct msghdr msg = { .msg_name = NULL, .msg_namelen = 0, @@ -135,6 +136,9 @@ static void handle_tx(struct vhost_net *net) ARRAY_SIZE(vq->iov), &out, &in, NULL, NULL); + /* On error, stop handling until the next kick. */ + if (head < 0) + break; /* Nothing new? Wait for eventfd to tell us they refilled. */ if (head == vq->num) { wmem = atomic_read(&sock->sk->sk_wmem_alloc); @@ -192,7 +196,8 @@ static void handle_tx(struct vhost_net *net) static void handle_rx(struct vhost_net *net) { struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX]; - unsigned head, out, in, log, s; + unsigned out, in, log, s; + int head; struct vhost_log *vq_log; struct msghdr msg = { .msg_name = NULL, @@ -228,6 +233,9 @@ static void handle_rx(struct vhost_net *net) ARRAY_SIZE(vq->iov), &out, &in, vq_log, &log); + /* On error, stop handling until the next kick. */ + if (head < 0) + break; /* OK, now we need to know about added descriptors. */ if (head == vq->num) { if (unlikely(vhost_enable_notify(vq))) { diff --git a/trunk/drivers/vhost/vhost.c b/trunk/drivers/vhost/vhost.c index 3b83382e06eb..5ccd384ec0be 100644 --- a/trunk/drivers/vhost/vhost.c +++ b/trunk/drivers/vhost/vhost.c @@ -873,12 +873,13 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq, * number of output then some number of input descriptors, it's actually two * iovecs, but we pack them into one and note how many of each there were. * - * This function returns the descriptor number found, or vq->num (which - * is never a valid descriptor number) if none was found. */ -unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, - struct iovec iov[], unsigned int iov_size, - unsigned int *out_num, unsigned int *in_num, - struct vhost_log *log, unsigned int *log_num) + * This function returns the descriptor number found, or vq->num (which is + * never a valid descriptor number) if none was found. A negative code is + * returned on error. */ +int vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, + struct iovec iov[], unsigned int iov_size, + unsigned int *out_num, unsigned int *in_num, + struct vhost_log *log, unsigned int *log_num) { struct vring_desc desc; unsigned int i, head, found = 0; @@ -890,13 +891,13 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, if (get_user(vq->avail_idx, &vq->avail->idx)) { vq_err(vq, "Failed to access avail idx at %p\n", &vq->avail->idx); - return vq->num; + return -EFAULT; } if ((u16)(vq->avail_idx - last_avail_idx) > vq->num) { vq_err(vq, "Guest moved used index from %u to %u", last_avail_idx, vq->avail_idx); - return vq->num; + return -EFAULT; } /* If there's nothing new since last we looked, return invalid. */ @@ -912,14 +913,14 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, vq_err(vq, "Failed to read head: idx %d address %p\n", last_avail_idx, &vq->avail->ring[last_avail_idx % vq->num]); - return vq->num; + return -EFAULT; } /* If their number is silly, that's an error. */ if (head >= vq->num) { vq_err(vq, "Guest says index %u > %u is available", head, vq->num); - return vq->num; + return -EINVAL; } /* When we start there are none of either input nor output. */ @@ -933,19 +934,19 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, if (i >= vq->num) { vq_err(vq, "Desc index is %u > %u, head = %u", i, vq->num, head); - return vq->num; + return -EINVAL; } if (++found > vq->num) { vq_err(vq, "Loop detected: last one at %u " "vq size %u head %u\n", i, vq->num, head); - return vq->num; + return -EINVAL; } ret = copy_from_user(&desc, vq->desc + i, sizeof desc); if (ret) { vq_err(vq, "Failed to get descriptor: idx %d addr %p\n", i, vq->desc + i); - return vq->num; + return -EFAULT; } if (desc.flags & VRING_DESC_F_INDIRECT) { ret = get_indirect(dev, vq, iov, iov_size, @@ -954,7 +955,7 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, if (ret < 0) { vq_err(vq, "Failure detected " "in indirect descriptor at idx %d\n", i); - return vq->num; + return ret; } continue; } @@ -964,7 +965,7 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, if (ret < 0) { vq_err(vq, "Translation failure %d descriptor idx %d\n", ret, i); - return vq->num; + return ret; } if (desc.flags & VRING_DESC_F_WRITE) { /* If this is an input descriptor, @@ -981,7 +982,7 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, if (*in_num) { vq_err(vq, "Descriptor has out after in: " "idx %d\n", i); - return vq->num; + return -EINVAL; } *out_num += ret; } diff --git a/trunk/drivers/vhost/vhost.h b/trunk/drivers/vhost/vhost.h index 44591ba9b07a..11ee13dba0f7 100644 --- a/trunk/drivers/vhost/vhost.h +++ b/trunk/drivers/vhost/vhost.h @@ -120,10 +120,10 @@ long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, unsigned long arg); int vhost_vq_access_ok(struct vhost_virtqueue *vq); int vhost_log_access_ok(struct vhost_dev *); -unsigned vhost_get_vq_desc(struct vhost_dev *, struct vhost_virtqueue *, - struct iovec iov[], unsigned int iov_count, - unsigned int *out_num, unsigned int *in_num, - struct vhost_log *log, unsigned int *log_num); +int vhost_get_vq_desc(struct vhost_dev *, struct vhost_virtqueue *, + struct iovec iov[], unsigned int iov_count, + unsigned int *out_num, unsigned int *in_num, + struct vhost_log *log, unsigned int *log_num); void vhost_discard_vq_desc(struct vhost_virtqueue *); int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len); diff --git a/trunk/include/linux/ethtool.h b/trunk/include/linux/ethtool.h index b4207ca3ad52..276b40a16835 100644 --- a/trunk/include/linux/ethtool.h +++ b/trunk/include/linux/ethtool.h @@ -379,8 +379,6 @@ struct ethtool_rxnfc { __u32 flow_type; /* The rx flow hash value or the rule DB size */ __u64 data; - /* The following fields are not valid and must not be used for - * the ETHTOOL_{G,X}RXFH commands. */ struct ethtool_rx_flow_spec fs; __u32 rule_cnt; __u32 rule_locs[0]; diff --git a/trunk/include/linux/mv643xx_eth.h b/trunk/include/linux/mv643xx_eth.h index 30b0c4e78f91..cbbbe9bfecad 100644 --- a/trunk/include/linux/mv643xx_eth.h +++ b/trunk/include/linux/mv643xx_eth.h @@ -19,11 +19,6 @@ struct mv643xx_eth_shared_platform_data { struct mbus_dram_target_info *dram; struct platform_device *shared_smi; unsigned int t_clk; - /* - * Max packet size for Tx IP/Layer 4 checksum, when set to 0, default - * limit of 9KiB will be used. - */ - int tx_csum_limit; }; #define MV643XX_ETH_PHY_ADDR_DEFAULT 0 diff --git a/trunk/include/linux/net.h b/trunk/include/linux/net.h index dee0b11a8759..2b4deeeb8646 100644 --- a/trunk/include/linux/net.h +++ b/trunk/include/linux/net.h @@ -129,9 +129,10 @@ struct socket_wq { * @type: socket type (%SOCK_STREAM, etc) * @flags: socket flags (%SOCK_ASYNC_NOSPACE, etc) * @ops: protocol specific socket operations + * @fasync_list: Asynchronous wake up list * @file: File back pointer for gc * @sk: internal networking protocol agnostic socket representation - * @wq: wait queue for several uses + * @wait: wait queue for several uses */ struct socket { socket_state state; diff --git a/trunk/include/linux/netdevice.h b/trunk/include/linux/netdevice.h index 5e6188d9f017..40291f375024 100644 --- a/trunk/include/linux/netdevice.h +++ b/trunk/include/linux/netdevice.h @@ -1656,9 +1656,6 @@ static inline int netif_is_multiqueue(const struct net_device *dev) return (dev->num_tx_queues > 1); } -extern void netif_set_real_num_tx_queues(struct net_device *dev, - unsigned int txq); - /* Use this variant when it is known for sure that it * is executing from hardware interrupt context or with hardware interrupts * disabled. diff --git a/trunk/include/net/sch_generic.h b/trunk/include/net/sch_generic.h index 433604bb3fe8..03ca5d826757 100644 --- a/trunk/include/net/sch_generic.h +++ b/trunk/include/net/sch_generic.h @@ -313,24 +313,12 @@ extern void qdisc_calculate_pkt_len(struct sk_buff *skb, extern void tcf_destroy(struct tcf_proto *tp); extern void tcf_destroy_chain(struct tcf_proto **fl); -/* Reset all TX qdiscs greater then index of a device. */ -static inline void qdisc_reset_all_tx_gt(struct net_device *dev, unsigned int i) -{ - struct Qdisc *qdisc; - - for (; i < dev->num_tx_queues; i++) { - qdisc = netdev_get_tx_queue(dev, i)->qdisc; - if (qdisc) { - spin_lock_bh(qdisc_lock(qdisc)); - qdisc_reset(qdisc); - spin_unlock_bh(qdisc_lock(qdisc)); - } - } -} - +/* Reset all TX qdiscs of a device. */ static inline void qdisc_reset_all_tx(struct net_device *dev) { - qdisc_reset_all_tx_gt(dev, 0); + unsigned int i; + for (i = 0; i < dev->num_tx_queues; i++) + qdisc_reset(netdev_get_tx_queue(dev, i)->qdisc); } /* Are all TX queues of the device empty? */ diff --git a/trunk/include/net/xfrm.h b/trunk/include/net/xfrm.h index fc8f36dd0f5c..1913af67c43d 100644 --- a/trunk/include/net/xfrm.h +++ b/trunk/include/net/xfrm.h @@ -1586,7 +1586,7 @@ static inline struct xfrm_state *xfrm_input_state(struct sk_buff *skb) static inline int xfrm_mark_get(struct nlattr **attrs, struct xfrm_mark *m) { if (attrs[XFRMA_MARK]) - memcpy(m, nla_data(attrs[XFRMA_MARK]), sizeof(struct xfrm_mark)); + memcpy(m, nla_data(attrs[XFRMA_MARK]), sizeof(m)); else m->v = m->m = 0; diff --git a/trunk/net/bluetooth/bnep/netdev.c b/trunk/net/bluetooth/bnep/netdev.c index 8c100c9dae28..0faad5ce6dc4 100644 --- a/trunk/net/bluetooth/bnep/netdev.c +++ b/trunk/net/bluetooth/bnep/netdev.c @@ -104,8 +104,6 @@ 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); } diff --git a/trunk/net/core/dev.c b/trunk/net/core/dev.c index 723a34710ad4..2b3bf53bc687 100644 --- a/trunk/net/core/dev.c +++ b/trunk/net/core/dev.c @@ -1553,24 +1553,6 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) rcu_read_unlock(); } -/* - * Routine to help set real_num_tx_queues. To avoid skbs mapped to queues - * greater then real_num_tx_queues stale skbs on the qdisc must be flushed. - */ -void netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq) -{ - unsigned int real_num = dev->real_num_tx_queues; - - if (unlikely(txq > dev->num_tx_queues)) - ; - else if (txq > real_num) - dev->real_num_tx_queues = txq; - else if (txq < real_num) { - dev->real_num_tx_queues = txq; - qdisc_reset_all_tx_gt(dev, txq); - } -} -EXPORT_SYMBOL(netif_set_real_num_tx_queues); static inline void __netif_reschedule(struct Qdisc *q) { diff --git a/trunk/net/core/ethtool.c b/trunk/net/core/ethtool.c index 75e4ffeb8cc9..a0f4964033d2 100644 --- a/trunk/net/core/ethtool.c +++ b/trunk/net/core/ethtool.c @@ -318,33 +318,23 @@ static noinline_for_stack int ethtool_get_sset_info(struct net_device *dev, } static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev, - u32 cmd, void __user *useraddr) + void __user *useraddr) { - struct ethtool_rxnfc info; - size_t info_size = sizeof(info); + struct ethtool_rxnfc cmd; if (!dev->ethtool_ops->set_rxnfc) return -EOPNOTSUPP; - /* struct ethtool_rxnfc was originally defined for - * ETHTOOL_{G,S}RXFH with only the cmd, flow_type and data - * members. User-space might still be using that - * definition. */ - if (cmd == ETHTOOL_SRXFH) - info_size = (offsetof(struct ethtool_rxnfc, data) + - sizeof(info.data)); - - if (copy_from_user(&info, useraddr, info_size)) + if (copy_from_user(&cmd, useraddr, sizeof(cmd))) return -EFAULT; - return dev->ethtool_ops->set_rxnfc(dev, &info); + return dev->ethtool_ops->set_rxnfc(dev, &cmd); } static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev, - u32 cmd, void __user *useraddr) + void __user *useraddr) { struct ethtool_rxnfc info; - size_t info_size = sizeof(info); const struct ethtool_ops *ops = dev->ethtool_ops; int ret; void *rule_buf = NULL; @@ -352,22 +342,13 @@ static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev, if (!ops->get_rxnfc) return -EOPNOTSUPP; - /* struct ethtool_rxnfc was originally defined for - * ETHTOOL_{G,S}RXFH with only the cmd, flow_type and data - * members. User-space might still be using that - * definition. */ - if (cmd == ETHTOOL_GRXFH) - info_size = (offsetof(struct ethtool_rxnfc, data) + - sizeof(info.data)); - - if (copy_from_user(&info, useraddr, info_size)) + if (copy_from_user(&info, useraddr, sizeof(info))) return -EFAULT; if (info.cmd == ETHTOOL_GRXCLSRLALL) { if (info.rule_cnt > 0) { - if (info.rule_cnt <= KMALLOC_MAX_SIZE / sizeof(u32)) - rule_buf = kmalloc(info.rule_cnt * sizeof(u32), - GFP_USER); + rule_buf = kmalloc(info.rule_cnt * sizeof(u32), + GFP_USER); if (!rule_buf) return -ENOMEM; } @@ -378,7 +359,7 @@ static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev, goto err_out; ret = -EFAULT; - if (copy_to_user(useraddr, &info, info_size)) + if (copy_to_user(useraddr, &info, sizeof(info))) goto err_out; if (rule_buf) { @@ -1535,12 +1516,12 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) case ETHTOOL_GRXCLSRLCNT: case ETHTOOL_GRXCLSRULE: case ETHTOOL_GRXCLSRLALL: - rc = ethtool_get_rxnfc(dev, ethcmd, useraddr); + rc = ethtool_get_rxnfc(dev, useraddr); break; case ETHTOOL_SRXFH: case ETHTOOL_SRXCLSRLDEL: case ETHTOOL_SRXCLSRLINS: - rc = ethtool_set_rxnfc(dev, ethcmd, useraddr); + rc = ethtool_set_rxnfc(dev, useraddr); break; case ETHTOOL_GGRO: rc = ethtool_get_gro(dev, useraddr); diff --git a/trunk/net/ipv6/ndisc.c b/trunk/net/ipv6/ndisc.c index 2efef52fb461..0abdc242ddb7 100644 --- a/trunk/net/ipv6/ndisc.c +++ b/trunk/net/ipv6/ndisc.c @@ -586,7 +586,6 @@ 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, @@ -600,6 +599,7 @@ 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); diff --git a/trunk/net/ipv6/netfilter/ip6t_REJECT.c b/trunk/net/ipv6/netfilter/ip6t_REJECT.c index 2933396e0281..47d227713758 100644 --- a/trunk/net/ipv6/netfilter/ip6t_REJECT.c +++ b/trunk/net/ipv6/netfilter/ip6t_REJECT.c @@ -97,11 +97,9 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) fl.fl_ip_dport = otcph.source; security_skb_classify_flow(oldskb, &fl); dst = ip6_route_output(net, NULL, &fl); - if (dst == NULL || dst->error) { - dst_release(dst); + if (dst == NULL) return; - } - if (xfrm_lookup(net, &dst, &fl, NULL, 0)) + if (dst->error || xfrm_lookup(net, &dst, &fl, NULL, 0)) return; hh_len = (dst->dev->hard_header_len + 15)&~15; diff --git a/trunk/net/xfrm/xfrm_policy.c b/trunk/net/xfrm/xfrm_policy.c index af1c173be4ad..4bf27d901333 100644 --- a/trunk/net/xfrm/xfrm_policy.c +++ b/trunk/net/xfrm/xfrm_policy.c @@ -2300,8 +2300,7 @@ 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->num_pols > 0 && - xdst->policy_genid != atomic_read(&xdst->pols[0]->genid)) + if (xdst->policy_genid != atomic_read(&xdst->pols[0]->genid)) return 0; if (strict && fl &&