Commit 486bfe5c authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (42 commits)
  cxgb3: fix premature page unmap
  ibm_newemac: Fix EMACx_TRTR[TRT] bit shifts
  vlan: Fix register_vlan_dev() error path
  gro: Fix illegal merging of trailer trash
  sungem: Fix Serdes detection.
  net: fix mdio section mismatch warning
  ppp: fix BUG on non-linear SKB (multilink receive)
  ixgbe: Fixing EEH handler to handle more than one error
  net: Fix the rollback test in dev_change_name()
  Revert "isdn: isdn_ppp: Use SKB list facilities instead of home-grown implementation."
  TI Davinci EMAC : Fix Console Hang when bringing the interface down
  smsc911x: Fix Console Hang when bringing the interface down.
  mISDN: fix error return in HFCmulti_init()
  forcedeth: mac address fix
  r6040: fix version printing
  Bluetooth: Fix regression with L2CAP configuration in Basic Mode
  Bluetooth: Select Basic Mode as default for SOCK_SEQPACKET
  Bluetooth: Set general bonding security for ACL by default
  r8169: Fix receive buffer length when MTU is between 1515 and 1536
  can: add the missing netlink get_xstats_size callback
  ...
parents 5cbb0601 70e3bb50
......@@ -4332,6 +4332,8 @@ F: drivers/video/aty/aty128fb.c
RALINK RT2X00 WIRELESS LAN DRIVER
P: rt2x00 project
M: Ivo van Doorn <IvDoorn@gmail.com>
M: Gertjan van Wingerde <gwingerde@gmail.com>
L: linux-wireless@vger.kernel.org
L: users@rt2x00.serialmonkey.com (moderated for non-subscribers)
W: http://rt2x00.serialmonkey.com/
......@@ -4419,7 +4421,7 @@ RFKILL
M: Johannes Berg <johannes@sipsolutions.net>
L: linux-wireless@vger.kernel.org
S: Maintained
F Documentation/rfkill.txt
F: Documentation/rfkill.txt
F: net/rfkill/
RISCOM8 DRIVER
......
......@@ -5481,7 +5481,7 @@ HFCmulti_init(void)
if (err) {
printk(KERN_ERR "error registering embedded driver: "
"%x\n", err);
return -err;
return err;
}
HFC_cnt++;
printk(KERN_INFO "%d devices registered\n", HFC_cnt);
......
......@@ -1535,10 +1535,8 @@ static int isdn_ppp_mp_bundle_array_init(void)
int sz = ISDN_MAX_CHANNELS*sizeof(ippp_bundle);
if( (isdn_ppp_bundle_arr = kzalloc(sz, GFP_KERNEL)) == NULL )
return -ENOMEM;
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
for( i = 0; i < ISDN_MAX_CHANNELS; i++ )
spin_lock_init(&isdn_ppp_bundle_arr[i].lock);
skb_queue_head_init(&isdn_ppp_bundle_arr[i].frags);
}
return 0;
}
......@@ -1571,7 +1569,7 @@ static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
if ((lp->netdev->pb = isdn_ppp_mp_bundle_alloc()) == NULL)
return -ENOMEM;
lp->next = lp->last = lp; /* nobody else in a queue */
skb_queue_head_init(&lp->netdev->pb->frags);
lp->netdev->pb->frags = NULL;
lp->netdev->pb->frames = 0;
lp->netdev->pb->seq = UINT_MAX;
}
......@@ -1583,29 +1581,28 @@ static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
static u32 isdn_ppp_mp_get_seq( int short_seq,
struct sk_buff * skb, u32 last_seq );
static void isdn_ppp_mp_discard(ippp_bundle *mp, struct sk_buff *from,
struct sk_buff *to);
static void isdn_ppp_mp_reassembly(isdn_net_dev *net_dev, isdn_net_local *lp,
struct sk_buff *from, struct sk_buff *to,
u32 lastseq);
static void isdn_ppp_mp_free_skb(ippp_bundle *mp, struct sk_buff *skb);
static struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp,
struct sk_buff * from, struct sk_buff * to );
static void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp,
struct sk_buff * from, struct sk_buff * to );
static void isdn_ppp_mp_free_skb( ippp_bundle * mp, struct sk_buff * skb );
static void isdn_ppp_mp_print_recv_pkt( int slot, struct sk_buff * skb );
static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
struct sk_buff *skb)
struct sk_buff *skb)
{
struct sk_buff *newfrag, *frag, *start, *nextf;
u32 newseq, minseq, thisseq;
isdn_mppp_stats *stats;
struct ippp_struct *is;
isdn_net_local * lpq;
ippp_bundle * mp;
isdn_mppp_stats * stats;
struct sk_buff * newfrag, * frag, * start, *nextf;
u32 newseq, minseq, thisseq;
unsigned long flags;
isdn_net_local *lpq;
ippp_bundle *mp;
int slot;
spin_lock_irqsave(&net_dev->pb->lock, flags);
mp = net_dev->pb;
stats = &mp->stats;
mp = net_dev->pb;
stats = &mp->stats;
slot = lp->ppp_slot;
if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: lp->ppp_slot(%d)\n",
......@@ -1616,19 +1613,20 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
return;
}
is = ippp_table[slot];
if (++mp->frames > stats->max_queue_len)
if( ++mp->frames > stats->max_queue_len )
stats->max_queue_len = mp->frames;
if (is->debug & 0x8)
isdn_ppp_mp_print_recv_pkt(lp->ppp_slot, skb);
newseq = isdn_ppp_mp_get_seq(is->mpppcfg & SC_IN_SHORT_SEQ,
skb, is->last_link_seqno);
newseq = isdn_ppp_mp_get_seq(is->mpppcfg & SC_IN_SHORT_SEQ,
skb, is->last_link_seqno);
/* if this packet seq # is less than last already processed one,
* toss it right away, but check for sequence start case first
*/
if (mp->seq > MP_LONGSEQ_MAX && (newseq & MP_LONGSEQ_MAXBIT)) {
if( mp->seq > MP_LONGSEQ_MAX && (newseq & MP_LONGSEQ_MAXBIT) ) {
mp->seq = newseq; /* the first packet: required for
* rfc1990 non-compliant clients --
* prevents constant packet toss */
......@@ -1638,7 +1636,7 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
spin_unlock_irqrestore(&mp->lock, flags);
return;
}
/* find the minimum received sequence number over all links */
is->last_link_seqno = minseq = newseq;
for (lpq = net_dev->queue;;) {
......@@ -1659,31 +1657,22 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
* packets */
newfrag = skb;
/* Insert new fragment into the proper sequence slot. */
skb_queue_walk(&mp->frags, frag) {
if (MP_SEQ(frag) == newseq) {
isdn_ppp_mp_free_skb(mp, newfrag);
newfrag = NULL;
break;
}
if (MP_LT(newseq, MP_SEQ(frag))) {
__skb_queue_before(&mp->frags, frag, newfrag);
newfrag = NULL;
break;
}
}
if (newfrag)
__skb_queue_tail(&mp->frags, newfrag);
/* if this new fragment is before the first one, then enqueue it now. */
if ((frag = mp->frags) == NULL || MP_LT(newseq, MP_SEQ(frag))) {
newfrag->next = frag;
mp->frags = frag = newfrag;
newfrag = NULL;
}
frag = skb_peek(&mp->frags);
start = ((MP_FLAGS(frag) & MP_BEGIN_FRAG) &&
(MP_SEQ(frag) == mp->seq)) ? frag : NULL;
if (!start)
goto check_overflow;
start = MP_FLAGS(frag) & MP_BEGIN_FRAG &&
MP_SEQ(frag) == mp->seq ? frag : NULL;
/* main fragment traversing loop
/*
* main fragment traversing loop
*
* try to accomplish several tasks:
* - insert new fragment into the proper sequence slot (once that's done
* newfrag will be set to NULL)
* - reassemble any complete fragment sequence (non-null 'start'
* indicates there is a continguous sequence present)
* - discard any incomplete sequences that are below minseq -- due
......@@ -1692,46 +1681,71 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
* come to complete such sequence and it should be discarded
*
* loop completes when we accomplished the following tasks:
* - new fragment is inserted in the proper sequence ('newfrag' is
* set to NULL)
* - we hit a gap in the sequence, so no reassembly/processing is
* possible ('start' would be set to NULL)
*
* algorithm for this code is derived from code in the book
* 'PPP Design And Debugging' by James Carlson (Addison-Wesley)
*/
skb_queue_walk_safe(&mp->frags, frag, nextf) {
thisseq = MP_SEQ(frag);
/* check for misplaced start */
if (start != frag && (MP_FLAGS(frag) & MP_BEGIN_FRAG)) {
printk(KERN_WARNING"isdn_mppp(seq %d): new "
"BEGIN flag with no prior END", thisseq);
stats->seqerrs++;
stats->frame_drops++;
isdn_ppp_mp_discard(mp, start, frag);
start = frag;
} else if (MP_LE(thisseq, minseq)) {
if (MP_FLAGS(frag) & MP_BEGIN_FRAG)
while (start != NULL || newfrag != NULL) {
thisseq = MP_SEQ(frag);
nextf = frag->next;
/* drop any duplicate fragments */
if (newfrag != NULL && thisseq == newseq) {
isdn_ppp_mp_free_skb(mp, newfrag);
newfrag = NULL;
}
/* insert new fragment before next element if possible. */
if (newfrag != NULL && (nextf == NULL ||
MP_LT(newseq, MP_SEQ(nextf)))) {
newfrag->next = nextf;
frag->next = nextf = newfrag;
newfrag = NULL;
}
if (start != NULL) {
/* check for misplaced start */
if (start != frag && (MP_FLAGS(frag) & MP_BEGIN_FRAG)) {
printk(KERN_WARNING"isdn_mppp(seq %d): new "
"BEGIN flag with no prior END", thisseq);
stats->seqerrs++;
stats->frame_drops++;
start = isdn_ppp_mp_discard(mp, start,frag);
nextf = frag->next;
}
} else if (MP_LE(thisseq, minseq)) {
if (MP_FLAGS(frag) & MP_BEGIN_FRAG)
start = frag;
else {
else {
if (MP_FLAGS(frag) & MP_END_FRAG)
stats->frame_drops++;
__skb_unlink(skb, &mp->frags);
stats->frame_drops++;
if( mp->frags == frag )
mp->frags = nextf;
isdn_ppp_mp_free_skb(mp, frag);
frag = nextf;
continue;
}
}
}
/* if we have end fragment, then we have full reassembly
* sequence -- reassemble and process packet now
/* if start is non-null and we have end fragment, then
* we have full reassembly sequence -- reassemble
* and process packet now
*/
if (MP_FLAGS(frag) & MP_END_FRAG) {
minseq = mp->seq = (thisseq+1) & MP_LONGSEQ_MASK;
/* Reassemble the packet then dispatch it */
isdn_ppp_mp_reassembly(net_dev, lp, start, frag, thisseq);
if (start != NULL && (MP_FLAGS(frag) & MP_END_FRAG)) {
minseq = mp->seq = (thisseq+1) & MP_LONGSEQ_MASK;
/* Reassemble the packet then dispatch it */
isdn_ppp_mp_reassembly(net_dev, lp, start, nextf);
start = NULL;
frag = NULL;
start = NULL;
frag = NULL;
}
mp->frags = nextf;
}
/* check if need to update start pointer: if we just
* reassembled the packet and sequence is contiguous
......@@ -1742,25 +1756,26 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
* below low watermark and set start to the next frag or
* clear start ptr.
*/
if (nextf != (struct sk_buff *)&mp->frags &&
if (nextf != NULL &&
((thisseq+1) & MP_LONGSEQ_MASK) == MP_SEQ(nextf)) {
/* if we just reassembled and the next one is here,
* then start another reassembly.
*/
if (frag == NULL) {
/* if we just reassembled and the next one is here,
* then start another reassembly. */
if (frag == NULL) {
if (MP_FLAGS(nextf) & MP_BEGIN_FRAG)
start = nextf;
else {
printk(KERN_WARNING"isdn_mppp(seq %d):"
" END flag with no following "
"BEGIN", thisseq);
start = nextf;
else
{
printk(KERN_WARNING"isdn_mppp(seq %d):"
" END flag with no following "
"BEGIN", thisseq);
stats->seqerrs++;
}
}
} else {
if (nextf != (struct sk_buff *)&mp->frags &&
frag != NULL &&
MP_LT(thisseq, minseq)) {
} else {
if ( nextf != NULL && frag != NULL &&
MP_LT(thisseq, minseq)) {
/* we've got a break in the sequence
* and we not at the end yet
* and we did not just reassembled
......@@ -1769,39 +1784,41 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
* discard all the frames below low watermark
* and start over */
stats->frame_drops++;
isdn_ppp_mp_discard(mp, start, nextf);
mp->frags = isdn_ppp_mp_discard(mp,start,nextf);
}
/* break in the sequence, no reassembly */
start = NULL;
}
if (!start)
break;
}
check_overflow:
start = NULL;
}
frag = nextf;
} /* while -- main loop */
if (mp->frags == NULL)
mp->frags = frag;
/* rather straighforward way to deal with (not very) possible
* queue overflow
*/
* queue overflow */
if (mp->frames > MP_MAX_QUEUE_LEN) {
stats->overflows++;
skb_queue_walk_safe(&mp->frags, frag, nextf) {
if (mp->frames <= MP_MAX_QUEUE_LEN)
break;
__skb_unlink(frag, &mp->frags);
isdn_ppp_mp_free_skb(mp, frag);
while (mp->frames > MP_MAX_QUEUE_LEN) {
frag = mp->frags->next;
isdn_ppp_mp_free_skb(mp, mp->frags);
mp->frags = frag;
}
}
spin_unlock_irqrestore(&mp->lock, flags);
}
static void isdn_ppp_mp_cleanup(isdn_net_local *lp)
static void isdn_ppp_mp_cleanup( isdn_net_local * lp )
{
struct sk_buff *skb, *tmp;
skb_queue_walk_safe(&lp->netdev->pb->frags, skb, tmp) {
__skb_unlink(skb, &lp->netdev->pb->frags);
isdn_ppp_mp_free_skb(lp->netdev->pb, skb);
}
struct sk_buff * frag = lp->netdev->pb->frags;
struct sk_buff * nextfrag;
while( frag ) {
nextfrag = frag->next;
isdn_ppp_mp_free_skb(lp->netdev->pb, frag);
frag = nextfrag;
}
lp->netdev->pb->frags = NULL;
}
static u32 isdn_ppp_mp_get_seq( int short_seq,
......@@ -1838,115 +1855,72 @@ static u32 isdn_ppp_mp_get_seq( int short_seq,
return seq;
}
static void isdn_ppp_mp_discard(ippp_bundle *mp, struct sk_buff *from,
struct sk_buff *to)
struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp,
struct sk_buff * from, struct sk_buff * to )
{
if (from) {
struct sk_buff *skb, *tmp;
int freeing = 0;
skb_queue_walk_safe(&mp->frags, skb, tmp) {
if (skb == to)
break;
if (skb == from)
freeing = 1;
if (!freeing)
continue;
__skb_unlink(skb, &mp->frags);
isdn_ppp_mp_free_skb(mp, skb);
if( from )
while (from != to) {
struct sk_buff * next = from->next;
isdn_ppp_mp_free_skb(mp, from);
from = next;
}
}
}
static unsigned int calc_tot_len(struct sk_buff_head *queue,
struct sk_buff *from, struct sk_buff *to)
{
unsigned int tot_len = 0;
struct sk_buff *skb;
int found_start = 0;
skb_queue_walk(queue, skb) {
if (skb == from)
found_start = 1;
if (!found_start)
continue;
tot_len += skb->len - MP_HEADER_LEN;
if (skb == to)
break;
}
return tot_len;
return from;
}
/* Reassemble packet using fragments in the reassembly queue from
* 'from' until 'to', inclusive.
*/
static void isdn_ppp_mp_reassembly(isdn_net_dev *net_dev, isdn_net_local *lp,
struct sk_buff *from, struct sk_buff *to,
u32 lastseq)
void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp,
struct sk_buff * from, struct sk_buff * to )
{
ippp_bundle *mp = net_dev->pb;
unsigned int tot_len;
struct sk_buff *skb;
ippp_bundle * mp = net_dev->pb;
int proto;
struct sk_buff * skb;
unsigned int tot_len;
if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
__func__, lp->ppp_slot);
return;
}
tot_len = calc_tot_len(&mp->frags, from, to);
if (MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG)) {
if (ippp_table[lp->ppp_slot]->debug & 0x40)
if( MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG) ) {
if( ippp_table[lp->ppp_slot]->debug & 0x40 )
printk(KERN_DEBUG "isdn_mppp: reassembly: frame %d, "
"len %d\n", MP_SEQ(from), from->len);
"len %d\n", MP_SEQ(from), from->len );
skb = from;
skb_pull(skb, MP_HEADER_LEN);
__skb_unlink(skb, &mp->frags);
mp->frames--;
} else {
struct sk_buff *walk, *tmp;
int found_start = 0;
struct sk_buff * frag;
int n;
if (ippp_table[lp->ppp_slot]->debug & 0x40)
printk(KERN_DEBUG"isdn_mppp: reassembling frames %d "
"to %d, len %d\n", MP_SEQ(from), lastseq,
tot_len);
for(tot_len=n=0, frag=from; frag != to; frag=frag->next, n++)
tot_len += frag->len - MP_HEADER_LEN;
skb = dev_alloc_skb(tot_len);
if (!skb)
if( ippp_table[lp->ppp_slot]->debug & 0x40 )
printk(KERN_DEBUG"isdn_mppp: reassembling frames %d "
"to %d, len %d\n", MP_SEQ(from),
(MP_SEQ(from)+n-1) & MP_LONGSEQ_MASK, tot_len );
if( (skb = dev_alloc_skb(tot_len)) == NULL ) {
printk(KERN_ERR "isdn_mppp: cannot allocate sk buff "
"of size %d\n", tot_len);
found_start = 0;
skb_queue_walk_safe(&mp->frags, walk, tmp) {
if (walk == from)
found_start = 1;
if (!found_start)
continue;
"of size %d\n", tot_len);
isdn_ppp_mp_discard(mp, from, to);
return;
}
if (skb) {
unsigned int len = walk->len - MP_HEADER_LEN;
skb_copy_from_linear_data_offset(walk, MP_HEADER_LEN,
skb_put(skb, len),
len);
}
__skb_unlink(walk, &mp->frags);
isdn_ppp_mp_free_skb(mp, walk);
while( from != to ) {
unsigned int len = from->len - MP_HEADER_LEN;
if (walk == to)
break;
skb_copy_from_linear_data_offset(from, MP_HEADER_LEN,
skb_put(skb,len),
len);
frag = from->next;
isdn_ppp_mp_free_skb(mp, from);
from = frag;
}
}
if (!skb)
return;
proto = isdn_ppp_strip_proto(skb);
isdn_ppp_push_higher(net_dev, lp, skb, proto);
}
static void isdn_ppp_mp_free_skb(ippp_bundle *mp, struct sk_buff *skb)
static void isdn_ppp_mp_free_skb(ippp_bundle * mp, struct sk_buff * skb)
{
dev_kfree_skb(skb);
mp->frames--;
......
......@@ -35,66 +35,16 @@ config CAN_CALC_BITTIMING
arguments "tq", "prop_seg", "phase_seg1", "phase_seg2" and "sjw".
If unsure, say Y.
config CAN_SJA1000
depends on CAN_DEV && HAS_IOMEM
tristate "Philips SJA1000"
---help---
Driver for the SJA1000 CAN controllers from Philips or NXP
config CAN_SJA1000_ISA
depends on CAN_SJA1000 && ISA
tristate "ISA Bus based legacy SJA1000 driver"
---help---
This driver adds legacy support for SJA1000 chips connected to
the ISA bus using I/O port, memory mapped or indirect access.
config CAN_SJA1000_PLATFORM
depends on CAN_SJA1000
tristate "Generic Platform Bus based SJA1000 driver"
---help---
This driver adds support for the SJA1000 chips connected to
the "platform bus" (Linux abstraction for directly to the
processor attached devices). Which can be found on various
boards from Phytec (http://www.phytec.de) like the PCM027,
PCM038.
config CAN_SJA1000_OF_PLATFORM
depends on CAN_SJA1000 && PPC_OF
tristate "Generic OF Platform Bus based SJA1000 driver"
---help---
This driver adds support for the SJA1000 chips connected to
the OpenFirmware "platform bus" found on embedded systems with
OpenFirmware bindings, e.g. if you have a PowerPC based system
you may want to enable this option.
config CAN_EMS_PCI
tristate "EMS CPC-PCI, CPC-PCIe and CPC-104P Card"
depends on PCI && CAN_SJA1000
---help---
This driver is for the one, two or four channel CPC-PCI,
CPC-PCIe and CPC-104P cards from EMS Dr. Thomas Wuensche
(http://www.ems-wuensche.de).
config CAN_EMS_USB
tristate "EMS CPC-USB/ARM7 CAN/USB interface"
depends on USB && CAN_DEV
---help---
This driver is for the one channel CPC-USB/ARM7 CAN/USB interface
from from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de).
config CAN_KVASER_PCI
tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards"
depends on PCI && CAN_SJA1000
---help---
This driver is for the the PCIcanx and PCIcan cards (1, 2 or
4 channel) from Kvaser (http://www.kvaser.com).
config CAN_AT91
tristate "Atmel AT91 onchip CAN controller"
depends on CAN && CAN_DEV && ARCH_AT91SAM9263
depends on CAN_DEV && ARCH_AT91SAM9263
---help---
This is a driver for the SoC CAN controller in Atmel's AT91SAM9263.
source "drivers/net/can/sja1000/Kconfig"
source "drivers/net/can/usb/Kconfig"
config CAN_DEBUG_DEVICES
bool "CAN devices debugging messages"
depends on CAN
......
......@@ -629,6 +629,11 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
return -EMSGSIZE;
}
static size_t can_get_xstats_size(const struct net_device *dev)
{
return sizeof(struct can_device_stats);
}