Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
This commit is contained in:
Коммит
597e608a84
|
@ -37,7 +37,7 @@
|
|||
#include <linux/wait.h>
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/cs.h>
|
||||
|
|
|
@ -244,7 +244,7 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
|
|||
if (rel) {
|
||||
hdr[0] |= 0x80 + bcsp->msgq_txseq;
|
||||
BT_DBG("Sending packet with seqno %u", bcsp->msgq_txseq);
|
||||
bcsp->msgq_txseq = ++(bcsp->msgq_txseq) & 0x07;
|
||||
bcsp->msgq_txseq = (bcsp->msgq_txseq + 1) & 0x07;
|
||||
}
|
||||
|
||||
if (bcsp->use_crc)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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} },
|
||||
|
|
|
@ -45,10 +45,6 @@
|
|||
#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,
|
||||
|
|
|
@ -16,7 +16,10 @@
|
|||
#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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -333,7 +333,8 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp)
|
|||
|
||||
if ((client_info->assigned) &&
|
||||
(client_info->ip_src == arp->ip_dst) &&
|
||||
(client_info->ip_dst == arp->ip_src)) {
|
||||
(client_info->ip_dst == arp->ip_src) &&
|
||||
(compare_ether_addr_64bits(client_info->mac_dst, arp->mac_src))) {
|
||||
/* update the clients MAC address */
|
||||
memcpy(client_info->mac_dst, arp->mac_src, ETH_ALEN);
|
||||
client_info->ntt = 1;
|
||||
|
|
|
@ -176,7 +176,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},
|
||||
|
@ -1766,15 +1766,23 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
|
|||
bond_set_carrier(bond);
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
if (slaves_support_netpoll(bond_dev)) {
|
||||
bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
|
||||
if (bond_dev->npinfo)
|
||||
slave_dev->npinfo = bond_dev->npinfo;
|
||||
} else if (!(bond_dev->priv_flags & IFF_DISABLE_NETPOLL)) {
|
||||
/*
|
||||
* Netpoll and bonding is broken, make sure it is not initialized
|
||||
* until it is fixed.
|
||||
*/
|
||||
if (disable_netpoll) {
|
||||
bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
|
||||
pr_info("New slave device %s does not support netpoll\n",
|
||||
slave_dev->name);
|
||||
pr_info("Disabling netpoll support for %s\n", bond_dev->name);
|
||||
} else {
|
||||
if (slaves_support_netpoll(bond_dev)) {
|
||||
bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
|
||||
if (bond_dev->npinfo)
|
||||
slave_dev->npinfo = bond_dev->npinfo;
|
||||
} else if (!(bond_dev->priv_flags & IFF_DISABLE_NETPOLL)) {
|
||||
bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
|
||||
pr_info("New slave device %s does not support netpoll\n",
|
||||
slave_dev->name);
|
||||
pr_info("Disabling netpoll support for %s\n", bond_dev->name);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
read_unlock(&bond->lock);
|
||||
|
@ -1977,8 +1985,11 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
|
|||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
read_lock_bh(&bond->lock);
|
||||
if (slaves_support_netpoll(bond_dev))
|
||||
bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
|
||||
|
||||
/* Make sure netpoll over stays disabled until fixed. */
|
||||
if (!disable_netpoll)
|
||||
if (slaves_support_netpoll(bond_dev))
|
||||
bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
|
||||
read_unlock_bh(&bond->lock);
|
||||
if (slave_dev->netdev_ops->ndo_netpoll_cleanup)
|
||||
slave_dev->netdev_ops->ndo_netpoll_cleanup(slave_dev);
|
||||
|
|
|
@ -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))) {
|
||||
|
|
|
@ -3741,10 +3741,6 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
|
|||
/* signal that we are down to the interrupt handler */
|
||||
set_bit(__IXGBE_DOWN, &adapter->state);
|
||||
|
||||
/* power down the optics */
|
||||
if (hw->phy.multispeed_fiber)
|
||||
hw->mac.ops.disable_tx_laser(hw);
|
||||
|
||||
/* disable receive for all VFs and wait one second */
|
||||
if (adapter->num_vfs) {
|
||||
/* ping all the active vfs to let them know we are going down */
|
||||
|
@ -3799,6 +3795,10 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
|
|||
(IXGBE_READ_REG(hw, IXGBE_DMATXCTL) &
|
||||
~IXGBE_DMATXCTL_TE));
|
||||
|
||||
/* power down the optics */
|
||||
if (hw->phy.multispeed_fiber)
|
||||
hw->mac.ops.disable_tx_laser(hw);
|
||||
|
||||
/* clear n-tuple filters that are cached */
|
||||
ethtool_ntuple_flush(netdev);
|
||||
|
||||
|
@ -4058,7 +4058,7 @@ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
|
|||
|
||||
done:
|
||||
/* Notify the stack of the (possibly) reduced Tx Queue count. */
|
||||
adapter->netdev->real_num_tx_queues = adapter->num_tx_queues;
|
||||
netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);
|
||||
}
|
||||
|
||||
static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter,
|
||||
|
@ -5246,7 +5246,6 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake)
|
|||
ixgbe_free_all_tx_resources(adapter);
|
||||
ixgbe_free_all_rx_resources(adapter);
|
||||
}
|
||||
ixgbe_clear_interrupt_scheme(adapter);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
retval = pci_save_state(pdev);
|
||||
|
@ -5281,6 +5280,8 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake)
|
|||
|
||||
*enable_wake = !!wufc;
|
||||
|
||||
ixgbe_clear_interrupt_scheme(adapter);
|
||||
|
||||
ixgbe_release_hw_control(adapter);
|
||||
|
||||
pci_disable_device(pdev);
|
||||
|
@ -6071,7 +6072,6 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter,
|
|||
static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb,
|
||||
int queue, u32 tx_flags)
|
||||
{
|
||||
/* Right now, we support IPv4 only */
|
||||
struct ixgbe_atr_input atr_input;
|
||||
struct tcphdr *th;
|
||||
struct iphdr *iph = ip_hdr(skb);
|
||||
|
@ -6080,6 +6080,9 @@ static void ixgbe_atr(struct ixgbe_adapter *adapter, struct sk_buff *skb,
|
|||
u32 src_ipv4_addr, dst_ipv4_addr;
|
||||
u8 l4type = 0;
|
||||
|
||||
/* Right now, we support IPv4 only */
|
||||
if (skb->protocol != htons(ETH_P_IP))
|
||||
return;
|
||||
/* check if we're UDP or TCP */
|
||||
if (iph->protocol == IPPROTO_TCP) {
|
||||
th = tcp_hdr(skb);
|
||||
|
|
|
@ -985,7 +985,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
|
|||
np = of_parse_phandle(op->dev.of_node, "llink-connected", 0);
|
||||
if (!np) {
|
||||
dev_err(&op->dev, "could not find DMA node\n");
|
||||
goto nodev;
|
||||
goto err_iounmap;
|
||||
}
|
||||
|
||||
/* Setup the DMA register accesses, could be DCR or memory mapped */
|
||||
|
@ -999,7 +999,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
|
|||
dev_dbg(&op->dev, "MEM base: %p\n", lp->sdma_regs);
|
||||
} else {
|
||||
dev_err(&op->dev, "unable to map DMA registers\n");
|
||||
goto nodev;
|
||||
goto err_iounmap;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1008,7 +1008,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
|
|||
if ((lp->rx_irq == NO_IRQ) || (lp->tx_irq == NO_IRQ)) {
|
||||
dev_err(&op->dev, "could not determine irqs\n");
|
||||
rc = -ENOMEM;
|
||||
goto nodev;
|
||||
goto err_iounmap_2;
|
||||
}
|
||||
|
||||
of_node_put(np); /* Finished with the DMA node; drop the reference */
|
||||
|
@ -1018,7 +1018,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
|
|||
if ((!addr) || (size != 6)) {
|
||||
dev_err(&op->dev, "could not find MAC address\n");
|
||||
rc = -ENODEV;
|
||||
goto nodev;
|
||||
goto err_iounmap_2;
|
||||
}
|
||||
temac_set_mac_address(ndev, (void *)addr);
|
||||
|
||||
|
@ -1034,7 +1034,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
|
|||
rc = sysfs_create_group(&lp->dev->kobj, &temac_attr_group);
|
||||
if (rc) {
|
||||
dev_err(lp->dev, "Error creating sysfs files\n");
|
||||
goto nodev;
|
||||
goto err_iounmap_2;
|
||||
}
|
||||
|
||||
rc = register_netdev(lp->ndev);
|
||||
|
@ -1047,6 +1047,11 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
|
|||
|
||||
err_register_ndev:
|
||||
sysfs_remove_group(&lp->dev->kobj, &temac_attr_group);
|
||||
err_iounmap_2:
|
||||
if (lp->sdma_regs)
|
||||
iounmap(lp->sdma_regs);
|
||||
err_iounmap:
|
||||
iounmap(lp->regs);
|
||||
nodev:
|
||||
free_netdev(ndev);
|
||||
ndev = NULL;
|
||||
|
@ -1065,6 +1070,9 @@ static int __devexit temac_of_remove(struct of_device *op)
|
|||
of_node_put(lp->phy_node);
|
||||
lp->phy_node = NULL;
|
||||
dev_set_drvdata(&op->dev, NULL);
|
||||
iounmap(lp->regs);
|
||||
if (lp->sdma_regs)
|
||||
iounmap(lp->sdma_regs);
|
||||
free_netdev(ndev);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -289,6 +289,7 @@ struct mv643xx_eth_shared_private {
|
|||
unsigned int t_clk;
|
||||
int extended_rx_coal_limit;
|
||||
int tx_bw_control;
|
||||
int tx_csum_limit;
|
||||
};
|
||||
|
||||
#define TX_BW_CONTROL_ABSENT 0
|
||||
|
@ -776,13 +777,16 @@ static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb)
|
|||
l4i_chk = 0;
|
||||
|
||||
if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
||||
int hdr_len;
|
||||
int tag_bytes;
|
||||
|
||||
BUG_ON(skb->protocol != htons(ETH_P_IP) &&
|
||||
skb->protocol != htons(ETH_P_8021Q));
|
||||
|
||||
tag_bytes = (void *)ip_hdr(skb) - (void *)skb->data - ETH_HLEN;
|
||||
if (unlikely(tag_bytes & ~12)) {
|
||||
hdr_len = (void *)ip_hdr(skb) - (void *)skb->data;
|
||||
tag_bytes = hdr_len - ETH_HLEN;
|
||||
if (skb->len - hdr_len > mp->shared->tx_csum_limit ||
|
||||
unlikely(tag_bytes & ~12)) {
|
||||
if (skb_checksum_help(skb) == 0)
|
||||
goto no_csum;
|
||||
kfree_skb(skb);
|
||||
|
@ -2671,6 +2675,7 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
|
|||
* Detect hardware parameters.
|
||||
*/
|
||||
msp->t_clk = (pd != NULL && pd->t_clk != 0) ? pd->t_clk : 133000000;
|
||||
msp->tx_csum_limit = pd->tx_csum_limit ? pd->tx_csum_limit : 9 * 1024;
|
||||
infer_hw_params(msp);
|
||||
|
||||
platform_set_drvdata(pdev, msp);
|
||||
|
|
|
@ -806,8 +806,10 @@ static int __init ne_drv_probe(struct platform_device *pdev)
|
|||
dev->base_addr = res->start;
|
||||
dev->irq = platform_get_irq(pdev, 0);
|
||||
} else {
|
||||
if (this_dev < 0 || this_dev >= MAX_NE_CARDS)
|
||||
if (this_dev < 0 || this_dev >= MAX_NE_CARDS) {
|
||||
free_netdev(dev);
|
||||
return -EINVAL;
|
||||
}
|
||||
dev->base_addr = io[this_dev];
|
||||
dev->irq = irq[this_dev];
|
||||
dev->mem_end = bad[this_dev];
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -226,6 +226,7 @@ module_exit(lxt_exit);
|
|||
static struct mdio_device_id lxt_tbl[] = {
|
||||
{ 0x78100000, 0xfffffff0 },
|
||||
{ 0x001378e0, 0xfffffff0 },
|
||||
{ 0x00137a10, 0xfffffff0 },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -4642,8 +4642,7 @@ static void ql_timer(unsigned long data)
|
|||
return;
|
||||
}
|
||||
|
||||
qdev->timer.expires = jiffies + (5*HZ);
|
||||
add_timer(&qdev->timer);
|
||||
mod_timer(&qdev->timer, jiffies + (5*HZ));
|
||||
}
|
||||
|
||||
static int __devinit qlge_probe(struct pci_dev *pdev,
|
||||
|
@ -4744,6 +4743,8 @@ static void ql_eeh_close(struct net_device *ndev)
|
|||
netif_stop_queue(ndev);
|
||||
}
|
||||
|
||||
/* Disabling the timer */
|
||||
del_timer_sync(&qdev->timer);
|
||||
if (test_bit(QL_ADAPTER_UP, &qdev->flags))
|
||||
cancel_delayed_work_sync(&qdev->asic_reset_work);
|
||||
cancel_delayed_work_sync(&qdev->mpi_reset_work);
|
||||
|
@ -4839,8 +4840,7 @@ static void qlge_io_resume(struct pci_dev *pdev)
|
|||
netif_err(qdev, ifup, qdev->ndev,
|
||||
"Device was not running prior to EEH.\n");
|
||||
}
|
||||
qdev->timer.expires = jiffies + (5*HZ);
|
||||
add_timer(&qdev->timer);
|
||||
mod_timer(&qdev->timer, jiffies + (5*HZ));
|
||||
netif_device_attach(ndev);
|
||||
}
|
||||
|
||||
|
@ -4902,8 +4902,7 @@ static int qlge_resume(struct pci_dev *pdev)
|
|||
return err;
|
||||
}
|
||||
|
||||
qdev->timer.expires = jiffies + (5*HZ);
|
||||
add_timer(&qdev->timer);
|
||||
mod_timer(&qdev->timer, jiffies + (5*HZ));
|
||||
netif_device_attach(ndev);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -3129,7 +3129,6 @@ static void tx_intr_handler(struct fifo_info *fifo_data)
|
|||
pkt_cnt++;
|
||||
|
||||
/* Updating the statistics block */
|
||||
nic->dev->stats.tx_bytes += skb->len;
|
||||
swstats->mem_freed += skb->truesize;
|
||||
dev_kfree_skb_irq(skb);
|
||||
|
||||
|
@ -4900,48 +4899,81 @@ static void s2io_updt_stats(struct s2io_nic *sp)
|
|||
* Return value:
|
||||
* pointer to the updated net_device_stats structure.
|
||||
*/
|
||||
|
||||
static struct net_device_stats *s2io_get_stats(struct net_device *dev)
|
||||
{
|
||||
struct s2io_nic *sp = netdev_priv(dev);
|
||||
struct config_param *config = &sp->config;
|
||||
struct mac_info *mac_control = &sp->mac_control;
|
||||
struct stat_block *stats = mac_control->stats_info;
|
||||
int i;
|
||||
u64 delta;
|
||||
|
||||
/* Configure Stats for immediate updt */
|
||||
s2io_updt_stats(sp);
|
||||
|
||||
/* Using sp->stats as a staging area, because reset (due to mtu
|
||||
change, for example) will clear some hardware counters */
|
||||
dev->stats.tx_packets += le32_to_cpu(stats->tmac_frms) -
|
||||
sp->stats.tx_packets;
|
||||
sp->stats.tx_packets = le32_to_cpu(stats->tmac_frms);
|
||||
/* 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;
|
||||
|
||||
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->tmac_frms_oflow) << 32 |
|
||||
le32_to_cpu(stats->tmac_frms)) - sp->stats.tx_packets;
|
||||
sp->stats.tx_packets += delta;
|
||||
dev->stats.tx_packets += 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 = ((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;
|
||||
|
||||
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);
|
||||
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;
|
||||
|
||||
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);
|
||||
delta = le64_to_cpu(stats->rmac_drop_frms) - sp->stats.rx_errors;
|
||||
sp->stats.rx_errors += delta;
|
||||
dev->stats.rx_errors += delta;
|
||||
|
||||
/* collect per-ring rx_packets and rx_bytes */
|
||||
dev->stats.rx_packets = dev->stats.rx_bytes = 0;
|
||||
for (i = 0; i < config->rx_ring_num; i++) {
|
||||
struct ring_info *ring = &mac_control->rings[i];
|
||||
delta = ((u64) le32_to_cpu(stats->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;
|
||||
|
||||
dev->stats.rx_packets += ring->rx_packets;
|
||||
dev->stats.rx_bytes += ring->rx_bytes;
|
||||
}
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
delta = le64_to_cpu(stats->rmac_fcs_err_frms) - sp->stats.rx_crc_errors;
|
||||
sp->stats.rx_crc_errors += delta;
|
||||
dev->stats.rx_crc_errors += delta;
|
||||
|
||||
return &dev->stats;
|
||||
}
|
||||
|
@ -7494,15 +7526,11 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
|
|||
}
|
||||
}
|
||||
|
||||
/* Updating statistics */
|
||||
ring_data->rx_packets++;
|
||||
rxdp->Host_Control = 0;
|
||||
if (sp->rxd_mode == RXD_MODE_1) {
|
||||
int len = RXD_GET_BUFFER0_SIZE_1(rxdp->Control_2);
|
||||
|
||||
ring_data->rx_bytes += len;
|
||||
skb_put(skb, len);
|
||||
|
||||
} else if (sp->rxd_mode == RXD_MODE_3B) {
|
||||
int get_block = ring_data->rx_curr_get_info.block_index;
|
||||
int get_off = ring_data->rx_curr_get_info.offset;
|
||||
|
@ -7511,7 +7539,6 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
|
|||
unsigned char *buff = skb_push(skb, buf0_len);
|
||||
|
||||
struct buffAdd *ba = &ring_data->ba[get_block][get_off];
|
||||
ring_data->rx_bytes += buf0_len + buf2_len;
|
||||
memcpy(buff, ba->ba_0, buf0_len);
|
||||
skb_put(skb, buf2_len);
|
||||
}
|
||||
|
|
|
@ -745,10 +745,6 @@ struct ring_info {
|
|||
|
||||
/* Buffer Address store. */
|
||||
struct buffAdd **ba;
|
||||
|
||||
/* per-Ring statistics */
|
||||
unsigned long rx_packets;
|
||||
unsigned long rx_bytes;
|
||||
} ____cacheline_aligned;
|
||||
|
||||
/* Fifo specific structure */
|
||||
|
|
|
@ -2671,6 +2671,7 @@ static struct platform_driver sbmac_driver = {
|
|||
.remove = __exit_p(sbmac_remove),
|
||||
.driver = {
|
||||
.name = sbmac_string,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -104,10 +104,8 @@ static void rndis_msg_indicate(struct usbnet *dev, struct rndis_indicate *msg,
|
|||
int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen)
|
||||
{
|
||||
struct cdc_state *info = (void *) &dev->data;
|
||||
struct usb_cdc_notification notification;
|
||||
int master_ifnum;
|
||||
int retval;
|
||||
int partial;
|
||||
unsigned count;
|
||||
__le32 rsp;
|
||||
u32 xid = 0, msg_len, request_id;
|
||||
|
@ -135,17 +133,13 @@ int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen)
|
|||
if (unlikely(retval < 0 || xid == 0))
|
||||
return retval;
|
||||
|
||||
/* Some devices don't respond on the control channel until
|
||||
* polled on the status channel, so do that first. */
|
||||
retval = usb_interrupt_msg(
|
||||
dev->udev,
|
||||
usb_rcvintpipe(dev->udev, dev->status->desc.bEndpointAddress),
|
||||
¬ification, sizeof(notification), &partial,
|
||||
RNDIS_CONTROL_TIMEOUT_MS);
|
||||
if (unlikely(retval < 0))
|
||||
return retval;
|
||||
// FIXME Seems like some devices discard responses when
|
||||
// we time out and cancel our "get response" requests...
|
||||
// so, this is fragile. Probably need to poll for status.
|
||||
|
||||
/* Poll the control channel; the request probably completed immediately */
|
||||
/* ignore status endpoint, just poll the control channel;
|
||||
* the request probably completed immediately
|
||||
*/
|
||||
rsp = buf->msg_type | RNDIS_MSG_COMPLETION;
|
||||
for (count = 0; count < 10; count++) {
|
||||
memset(buf, 0, CONTROL_BUFFER_SIZE);
|
||||
|
|
|
@ -1293,6 +1293,9 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* netdev_printk() needs this so do it as early as possible */
|
||||
SET_NETDEV_DEV(net, &udev->dev);
|
||||
|
||||
dev = netdev_priv(net);
|
||||
dev->udev = xdev;
|
||||
dev->intf = udev;
|
||||
|
@ -1377,8 +1380,6 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
|
|||
dev->rx_urb_size = dev->hard_mtu;
|
||||
dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1);
|
||||
|
||||
SET_NETDEV_DEV(net, &udev->dev);
|
||||
|
||||
if ((dev->driver_info->flags & FLAG_WLAN) != 0)
|
||||
SET_NETDEV_DEVTYPE(net, &wlan_type);
|
||||
if ((dev->driver_info->flags & FLAG_WWAN) != 0)
|
||||
|
|
|
@ -415,7 +415,7 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp)
|
|||
static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)
|
||||
{
|
||||
int err;
|
||||
bool oom = false;
|
||||
bool oom;
|
||||
|
||||
do {
|
||||
if (vi->mergeable_rx_bufs)
|
||||
|
@ -425,10 +425,9 @@ static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)
|
|||
else
|
||||
err = add_recvbuf_small(vi, gfp);
|
||||
|
||||
if (err < 0) {
|
||||
oom = true;
|
||||
oom = err == -ENOMEM;
|
||||
if (err < 0)
|
||||
break;
|
||||
}
|
||||
++vi->num;
|
||||
} while (err > 0);
|
||||
if (unlikely(vi->num > vi->max))
|
||||
|
@ -563,7 +562,6 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
struct virtnet_info *vi = netdev_priv(dev);
|
||||
int capacity;
|
||||
|
||||
again:
|
||||
/* Free up any pending old buffers before queueing new ones. */
|
||||
free_old_xmit_skbs(vi);
|
||||
|
||||
|
@ -572,14 +570,20 @@ again:
|
|||
|
||||
/* This can happen with OOM and indirect buffers. */
|
||||
if (unlikely(capacity < 0)) {
|
||||
netif_stop_queue(dev);
|
||||
dev_warn(&dev->dev, "Unexpected full queue\n");
|
||||
if (unlikely(!virtqueue_enable_cb(vi->svq))) {
|
||||
virtqueue_disable_cb(vi->svq);
|
||||
netif_start_queue(dev);
|
||||
goto again;
|
||||
if (net_ratelimit()) {
|
||||
if (likely(capacity == -ENOMEM)) {
|
||||
dev_warn(&dev->dev,
|
||||
"TX queue failure: out of memory\n");
|
||||
} else {
|
||||
dev->stats.tx_fifo_errors++;
|
||||
dev_warn(&dev->dev,
|
||||
"Unexpected TX queue failure: %d\n",
|
||||
capacity);
|
||||
}
|
||||
}
|
||||
return NETDEV_TX_BUSY;
|
||||
dev->stats.tx_dropped++;
|
||||
kfree_skb(skb);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
virtqueue_kick(vi->svq);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
@ -4515,9 +4526,9 @@ vxge_starter(void)
|
|||
char version[32];
|
||||
snprintf(version, 32, "%s", DRV_VERSION);
|
||||
|
||||
printk(KERN_CRIT "%s: Copyright(c) 2002-2009 Neterion Inc\n",
|
||||
printk(KERN_INFO "%s: Copyright(c) 2002-2009 Neterion Inc\n",
|
||||
VXGE_DRIVER_NAME);
|
||||
printk(KERN_CRIT "%s: Driver version: %s\n",
|
||||
printk(KERN_INFO "%s: Driver version: %s\n",
|
||||
VXGE_DRIVER_NAME, version);
|
||||
|
||||
verify_bandwidth();
|
||||
|
|
|
@ -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 (unlikely(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 (unlikely(head < 0))
|
||||
break;
|
||||
/* OK, now we need to know about added descriptors. */
|
||||
if (head == vq->num) {
|
||||
if (unlikely(vhost_enable_notify(vq))) {
|
||||
|
|
|
@ -736,12 +736,12 @@ static int translate_desc(struct vhost_dev *dev, u64 addr, u32 len,
|
|||
mem = rcu_dereference(dev->memory);
|
||||
while ((u64)len > s) {
|
||||
u64 size;
|
||||
if (ret >= iov_size) {
|
||||
if (unlikely(ret >= iov_size)) {
|
||||
ret = -ENOBUFS;
|
||||
break;
|
||||
}
|
||||
reg = find_region(mem, addr, len);
|
||||
if (!reg) {
|
||||
if (unlikely(!reg)) {
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
@ -780,18 +780,18 @@ static unsigned next_desc(struct vring_desc *desc)
|
|||
return next;
|
||||
}
|
||||
|
||||
static unsigned get_indirect(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 *indirect)
|
||||
static int get_indirect(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 *indirect)
|
||||
{
|
||||
struct vring_desc desc;
|
||||
unsigned int i = 0, count, found = 0;
|
||||
int ret;
|
||||
|
||||
/* Sanity check */
|
||||
if (indirect->len % sizeof desc) {
|
||||
if (unlikely(indirect->len % sizeof desc)) {
|
||||
vq_err(vq, "Invalid length in indirect descriptor: "
|
||||
"len 0x%llx not multiple of 0x%zx\n",
|
||||
(unsigned long long)indirect->len,
|
||||
|
@ -801,7 +801,7 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
|
|||
|
||||
ret = translate_desc(dev, indirect->addr, indirect->len, vq->indirect,
|
||||
ARRAY_SIZE(vq->indirect));
|
||||
if (ret < 0) {
|
||||
if (unlikely(ret < 0)) {
|
||||
vq_err(vq, "Translation failure %d in indirect.\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -813,7 +813,7 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
|
|||
count = indirect->len / sizeof desc;
|
||||
/* Buffers are chained via a 16 bit next field, so
|
||||
* we can have at most 2^16 of these. */
|
||||
if (count > USHRT_MAX + 1) {
|
||||
if (unlikely(count > USHRT_MAX + 1)) {
|
||||
vq_err(vq, "Indirect buffer length too big: %d\n",
|
||||
indirect->len);
|
||||
return -E2BIG;
|
||||
|
@ -821,19 +821,19 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
|
|||
|
||||
do {
|
||||
unsigned iov_count = *in_num + *out_num;
|
||||
if (++found > count) {
|
||||
if (unlikely(++found > count)) {
|
||||
vq_err(vq, "Loop detected: last one at %u "
|
||||
"indirect size %u\n",
|
||||
i, count);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (memcpy_fromiovec((unsigned char *)&desc, vq->indirect,
|
||||
sizeof desc)) {
|
||||
if (unlikely(memcpy_fromiovec((unsigned char *)&desc, vq->indirect,
|
||||
sizeof desc))) {
|
||||
vq_err(vq, "Failed indirect descriptor: idx %d, %zx\n",
|
||||
i, (size_t)indirect->addr + i * sizeof desc);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (desc.flags & VRING_DESC_F_INDIRECT) {
|
||||
if (unlikely(desc.flags & VRING_DESC_F_INDIRECT)) {
|
||||
vq_err(vq, "Nested indirect descriptor: idx %d, %zx\n",
|
||||
i, (size_t)indirect->addr + i * sizeof desc);
|
||||
return -EINVAL;
|
||||
|
@ -841,7 +841,7 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
|
|||
|
||||
ret = translate_desc(dev, desc.addr, desc.len, iov + iov_count,
|
||||
iov_size - iov_count);
|
||||
if (ret < 0) {
|
||||
if (unlikely(ret < 0)) {
|
||||
vq_err(vq, "Translation failure %d indirect idx %d\n",
|
||||
ret, i);
|
||||
return ret;
|
||||
|
@ -857,7 +857,7 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
|
|||
} else {
|
||||
/* If it's an output descriptor, they're all supposed
|
||||
* to come before any input descriptors. */
|
||||
if (*in_num) {
|
||||
if (unlikely(*in_num)) {
|
||||
vq_err(vq, "Indirect descriptor "
|
||||
"has out after in: idx %d\n", i);
|
||||
return -EINVAL;
|
||||
|
@ -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;
|
||||
|
@ -887,16 +888,16 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
|
|||
|
||||
/* Check it isn't doing very strange things with descriptor numbers. */
|
||||
last_avail_idx = vq->last_avail_idx;
|
||||
if (get_user(vq->avail_idx, &vq->avail->idx)) {
|
||||
if (unlikely(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) {
|
||||
if (unlikely((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. */
|
||||
|
@ -908,18 +909,19 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
|
|||
|
||||
/* Grab the next descriptor number they're advertising, and increment
|
||||
* the index we've seen. */
|
||||
if (get_user(head, &vq->avail->ring[last_avail_idx % vq->num])) {
|
||||
if (unlikely(get_user(head,
|
||||
&vq->avail->ring[last_avail_idx % vq->num]))) {
|
||||
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) {
|
||||
if (unlikely(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. */
|
||||
|
@ -930,41 +932,41 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
|
|||
i = head;
|
||||
do {
|
||||
unsigned iov_count = *in_num + *out_num;
|
||||
if (i >= vq->num) {
|
||||
if (unlikely(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) {
|
||||
if (unlikely(++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) {
|
||||
if (unlikely(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,
|
||||
out_num, in_num,
|
||||
log, log_num, &desc);
|
||||
if (ret < 0) {
|
||||
if (unlikely(ret < 0)) {
|
||||
vq_err(vq, "Failure detected "
|
||||
"in indirect descriptor at idx %d\n", i);
|
||||
return vq->num;
|
||||
return ret;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = translate_desc(dev, desc.addr, desc.len, iov + iov_count,
|
||||
iov_size - iov_count);
|
||||
if (ret < 0) {
|
||||
if (unlikely(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,
|
||||
|
@ -978,10 +980,10 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
|
|||
} else {
|
||||
/* If it's an output descriptor, they're all supposed
|
||||
* to come before any input descriptors. */
|
||||
if (*in_num) {
|
||||
if (unlikely(*in_num)) {
|
||||
vq_err(vq, "Descriptor has out after in: "
|
||||
"idx %d\n", i);
|
||||
return vq->num;
|
||||
return -EINVAL;
|
||||
}
|
||||
*out_num += ret;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -379,6 +379,8 @@ struct ethtool_rxnfc {
|
|||
__u32 flow_type;
|
||||
/* The rx flow hash value or the rule DB size */
|
||||
__u64 data;
|
||||
/* The following fields are not valid and must not be used for
|
||||
* the ETHTOOL_{G,X}RXFH commands. */
|
||||
struct ethtool_rx_flow_spec fs;
|
||||
__u32 rule_cnt;
|
||||
__u32 rule_locs[0];
|
||||
|
|
|
@ -19,6 +19,11 @@ struct mv643xx_eth_shared_platform_data {
|
|||
struct mbus_dram_target_info *dram;
|
||||
struct platform_device *shared_smi;
|
||||
unsigned int t_clk;
|
||||
/*
|
||||
* Max packet size for Tx IP/Layer 4 checksum, when set to 0, default
|
||||
* limit of 9KiB will be used.
|
||||
*/
|
||||
int tx_csum_limit;
|
||||
};
|
||||
|
||||
#define MV643XX_ETH_PHY_ADDR_DEFAULT 0
|
||||
|
|
|
@ -129,10 +129,9 @@ struct socket_wq {
|
|||
* @type: socket type (%SOCK_STREAM, etc)
|
||||
* @flags: socket flags (%SOCK_ASYNC_NOSPACE, etc)
|
||||
* @ops: protocol specific socket operations
|
||||
* @fasync_list: Asynchronous wake up list
|
||||
* @file: File back pointer for gc
|
||||
* @sk: internal networking protocol agnostic socket representation
|
||||
* @wait: wait queue for several uses
|
||||
* @wq: wait queue for several uses
|
||||
*/
|
||||
struct socket {
|
||||
socket_state state;
|
||||
|
|
|
@ -1674,6 +1674,9 @@ static inline int netif_is_multiqueue(const struct net_device *dev)
|
|||
return (dev->num_tx_queues > 1);
|
||||
}
|
||||
|
||||
extern void netif_set_real_num_tx_queues(struct net_device *dev,
|
||||
unsigned int txq);
|
||||
|
||||
/* Use this variant when it is known for sure that it
|
||||
* is executing from hardware interrupt context or with hardware interrupts
|
||||
* disabled.
|
||||
|
@ -2360,7 +2363,7 @@ do { \
|
|||
#endif
|
||||
|
||||
#if defined(VERBOSE_DEBUG)
|
||||
#define netif_vdbg netdev_dbg
|
||||
#define netif_vdbg netif_dbg
|
||||
#else
|
||||
#define netif_vdbg(priv, type, dev, format, args...) \
|
||||
({ \
|
||||
|
|
|
@ -336,12 +336,24 @@ extern void qdisc_calculate_pkt_len(struct sk_buff *skb,
|
|||
extern void tcf_destroy(struct tcf_proto *tp);
|
||||
extern void tcf_destroy_chain(struct tcf_proto **fl);
|
||||
|
||||
/* Reset all TX qdiscs of a device. */
|
||||
/* Reset all TX qdiscs greater then index of a device. */
|
||||
static inline void qdisc_reset_all_tx_gt(struct net_device *dev, unsigned int i)
|
||||
{
|
||||
struct Qdisc *qdisc;
|
||||
|
||||
for (; i < dev->num_tx_queues; i++) {
|
||||
qdisc = netdev_get_tx_queue(dev, i)->qdisc;
|
||||
if (qdisc) {
|
||||
spin_lock_bh(qdisc_lock(qdisc));
|
||||
qdisc_reset(qdisc);
|
||||
spin_unlock_bh(qdisc_lock(qdisc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void qdisc_reset_all_tx(struct net_device *dev)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < dev->num_tx_queues; i++)
|
||||
qdisc_reset(netdev_get_tx_queue(dev, i)->qdisc);
|
||||
qdisc_reset_all_tx_gt(dev, 0);
|
||||
}
|
||||
|
||||
/* Are all TX queues of the device empty? */
|
||||
|
|
|
@ -1586,7 +1586,7 @@ static inline struct xfrm_state *xfrm_input_state(struct sk_buff *skb)
|
|||
static inline int xfrm_mark_get(struct nlattr **attrs, struct xfrm_mark *m)
|
||||
{
|
||||
if (attrs[XFRMA_MARK])
|
||||
memcpy(m, nla_data(attrs[XFRMA_MARK]), sizeof(m));
|
||||
memcpy(m, nla_data(attrs[XFRMA_MARK]), sizeof(struct xfrm_mark));
|
||||
else
|
||||
m->v = m->m = 0;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -99,6 +99,15 @@ static struct net_bridge_mdb_entry *__br_mdb_ip_get(
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static struct net_bridge_mdb_entry *br_mdb_ip_get(
|
||||
struct net_bridge_mdb_htable *mdb, struct br_ip *dst)
|
||||
{
|
||||
if (!mdb)
|
||||
return NULL;
|
||||
|
||||
return __br_mdb_ip_get(mdb, dst, br_ip_hash(mdb, dst));
|
||||
}
|
||||
|
||||
static struct net_bridge_mdb_entry *br_mdb_ip4_get(
|
||||
struct net_bridge_mdb_htable *mdb, __be32 dst)
|
||||
{
|
||||
|
@ -107,7 +116,7 @@ static struct net_bridge_mdb_entry *br_mdb_ip4_get(
|
|||
br_dst.u.ip4 = dst;
|
||||
br_dst.proto = htons(ETH_P_IP);
|
||||
|
||||
return __br_mdb_ip_get(mdb, &br_dst, __br_ip4_hash(mdb, dst));
|
||||
return br_mdb_ip_get(mdb, &br_dst);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||
|
@ -119,23 +128,17 @@ static struct net_bridge_mdb_entry *br_mdb_ip6_get(
|
|||
ipv6_addr_copy(&br_dst.u.ip6, dst);
|
||||
br_dst.proto = htons(ETH_P_IPV6);
|
||||
|
||||
return __br_mdb_ip_get(mdb, &br_dst, __br_ip6_hash(mdb, dst));
|
||||
return br_mdb_ip_get(mdb, &br_dst);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct net_bridge_mdb_entry *br_mdb_ip_get(
|
||||
struct net_bridge_mdb_htable *mdb, struct br_ip *dst)
|
||||
{
|
||||
return __br_mdb_ip_get(mdb, dst, br_ip_hash(mdb, dst));
|
||||
}
|
||||
|
||||
struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct net_bridge_mdb_htable *mdb = br->mdb;
|
||||
struct br_ip ip;
|
||||
|
||||
if (!mdb || br->multicast_disabled)
|
||||
if (br->multicast_disabled)
|
||||
return NULL;
|
||||
|
||||
if (BR_INPUT_SKB_CB(skb)->igmp)
|
||||
|
|
|
@ -598,6 +598,9 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff *skb,
|
|||
|
||||
pskb_trim_rcsum(skb, len);
|
||||
|
||||
/* BUG: Should really parse the IP options here. */
|
||||
memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
|
||||
|
||||
nf_bridge_put(skb->nf_bridge);
|
||||
if (!nf_bridge_alloc(skb))
|
||||
return NF_DROP;
|
||||
|
|
|
@ -1550,6 +1550,24 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
|
|||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
/*
|
||||
* Routine to help set real_num_tx_queues. To avoid skbs mapped to queues
|
||||
* greater then real_num_tx_queues stale skbs on the qdisc must be flushed.
|
||||
*/
|
||||
void netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)
|
||||
{
|
||||
unsigned int real_num = dev->real_num_tx_queues;
|
||||
|
||||
if (unlikely(txq > dev->num_tx_queues))
|
||||
;
|
||||
else if (txq > real_num)
|
||||
dev->real_num_tx_queues = txq;
|
||||
else if (txq < real_num) {
|
||||
dev->real_num_tx_queues = txq;
|
||||
qdisc_reset_all_tx_gt(dev, txq);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(netif_set_real_num_tx_queues);
|
||||
|
||||
static inline void __netif_reschedule(struct Qdisc *q)
|
||||
{
|
||||
|
|
|
@ -300,23 +300,33 @@ out:
|
|||
}
|
||||
|
||||
static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev,
|
||||
void __user *useraddr)
|
||||
u32 cmd, void __user *useraddr)
|
||||
{
|
||||
struct ethtool_rxnfc cmd;
|
||||
struct ethtool_rxnfc info;
|
||||
size_t info_size = sizeof(info);
|
||||
|
||||
if (!dev->ethtool_ops->set_rxnfc)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
|
||||
/* struct ethtool_rxnfc was originally defined for
|
||||
* ETHTOOL_{G,S}RXFH with only the cmd, flow_type and data
|
||||
* members. User-space might still be using that
|
||||
* definition. */
|
||||
if (cmd == ETHTOOL_SRXFH)
|
||||
info_size = (offsetof(struct ethtool_rxnfc, data) +
|
||||
sizeof(info.data));
|
||||
|
||||
if (copy_from_user(&info, useraddr, info_size))
|
||||
return -EFAULT;
|
||||
|
||||
return dev->ethtool_ops->set_rxnfc(dev, &cmd);
|
||||
return dev->ethtool_ops->set_rxnfc(dev, &info);
|
||||
}
|
||||
|
||||
static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev,
|
||||
void __user *useraddr)
|
||||
u32 cmd, void __user *useraddr)
|
||||
{
|
||||
struct ethtool_rxnfc info;
|
||||
size_t info_size = sizeof(info);
|
||||
const struct ethtool_ops *ops = dev->ethtool_ops;
|
||||
int ret;
|
||||
void *rule_buf = NULL;
|
||||
|
@ -324,13 +334,22 @@ static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev,
|
|||
if (!ops->get_rxnfc)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (copy_from_user(&info, useraddr, sizeof(info)))
|
||||
/* struct ethtool_rxnfc was originally defined for
|
||||
* ETHTOOL_{G,S}RXFH with only the cmd, flow_type and data
|
||||
* members. User-space might still be using that
|
||||
* definition. */
|
||||
if (cmd == ETHTOOL_GRXFH)
|
||||
info_size = (offsetof(struct ethtool_rxnfc, data) +
|
||||
sizeof(info.data));
|
||||
|
||||
if (copy_from_user(&info, useraddr, info_size))
|
||||
return -EFAULT;
|
||||
|
||||
if (info.cmd == ETHTOOL_GRXCLSRLALL) {
|
||||
if (info.rule_cnt > 0) {
|
||||
rule_buf = kmalloc(info.rule_cnt * sizeof(u32),
|
||||
GFP_USER);
|
||||
if (info.rule_cnt <= KMALLOC_MAX_SIZE / sizeof(u32))
|
||||
rule_buf = kmalloc(info.rule_cnt * sizeof(u32),
|
||||
GFP_USER);
|
||||
if (!rule_buf)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -341,7 +360,7 @@ static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev,
|
|||
goto err_out;
|
||||
|
||||
ret = -EFAULT;
|
||||
if (copy_to_user(useraddr, &info, sizeof(info)))
|
||||
if (copy_to_user(useraddr, &info, info_size))
|
||||
goto err_out;
|
||||
|
||||
if (rule_buf) {
|
||||
|
@ -1572,12 +1591,12 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
|
|||
case ETHTOOL_GRXCLSRLCNT:
|
||||
case ETHTOOL_GRXCLSRULE:
|
||||
case ETHTOOL_GRXCLSRLALL:
|
||||
rc = ethtool_get_rxnfc(dev, useraddr);
|
||||
rc = ethtool_get_rxnfc(dev, ethcmd, useraddr);
|
||||
break;
|
||||
case ETHTOOL_SRXFH:
|
||||
case ETHTOOL_SRXCLSRLDEL:
|
||||
case ETHTOOL_SRXCLSRLINS:
|
||||
rc = ethtool_set_rxnfc(dev, useraddr);
|
||||
rc = ethtool_set_rxnfc(dev, ethcmd, useraddr);
|
||||
break;
|
||||
case ETHTOOL_GGRO:
|
||||
rc = ethtool_get_gro(dev, useraddr);
|
||||
|
|
|
@ -108,6 +108,8 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
|
|||
u8 *xprth = skb_network_header(skb) + iph->ihl * 4;
|
||||
|
||||
memset(fl, 0, sizeof(struct flowi));
|
||||
fl->mark = skb->mark;
|
||||
|
||||
if (!(iph->frag_off & htons(IP_MF | IP_OFFSET))) {
|
||||
switch (iph->protocol) {
|
||||
case IPPROTO_UDP:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -97,9 +97,11 @@ static void send_reset(struct net *net, struct sk_buff *oldskb)
|
|||
fl.fl_ip_dport = otcph.source;
|
||||
security_skb_classify_flow(oldskb, &fl);
|
||||
dst = ip6_route_output(net, NULL, &fl);
|
||||
if (dst == NULL)
|
||||
if (dst == NULL || dst->error) {
|
||||
dst_release(dst);
|
||||
return;
|
||||
if (dst->error || xfrm_lookup(net, &dst, &fl, NULL, 0))
|
||||
}
|
||||
if (xfrm_lookup(net, &dst, &fl, NULL, 0))
|
||||
return;
|
||||
|
||||
hh_len = (dst->dev->hard_header_len + 15)&~15;
|
||||
|
|
|
@ -124,6 +124,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
|
|||
u8 nexthdr = nh[IP6CB(skb)->nhoff];
|
||||
|
||||
memset(fl, 0, sizeof(struct flowi));
|
||||
fl->mark = skb->mark;
|
||||
|
||||
ipv6_addr_copy(&fl->fl6_dst, reverse ? &hdr->saddr : &hdr->daddr);
|
||||
ipv6_addr_copy(&fl->fl6_src, reverse ? &hdr->daddr : &hdr->saddr);
|
||||
|
||||
|
|
|
@ -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 &&
|
||||
|
|
Загрузка…
Ссылка в новой задаче