Commit 5d5dde2e authored by Linus Torvalds's avatar Linus Torvalds

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

* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (25 commits)
  [XFRM]: Fix oops in xfrm4_dst_destroy()
  [XFRM_TUNNEL]: Reload header pointer after pskb_may_pull/pskb_expand_head
  [IPV4]: Use random32() in net/ipv4/multipath
  [BRIDGE]: eliminate workqueue for carrier check
  [BRIDGE]: get rid of miscdevice include
  [IPV6]: Fix __ipv6_addr_type() export in correct place.
  [IPV4] devinet: Register inetdev earlier.
  [IPV6] ADDRCONF: Register inet6_dev earlier.
  [IPV6] ADDRCONF: Manage prefix route corresponding to address manually added.
  [IPV6] IP6TUNNEL: Use update_pmtu() of dst on xmit.
  [IPV6] ADDRCONF: Statically link __ipv6_addr_type() for sunrpc subsystem.
  [IPV4]: Correct links in net/ipv4/Kconfig
  [SCTP]: Strike the transport before updating rto.
  [SCTP]: Fix connection hang/slowdown with PR-SCTP
  [TCP]: Fix MD5 signature pool locking.
  [TG3]: TSO workaround fixes.
  [AF_PACKET]: Remove unnecessary casts.
  [IPV6]: Adjust inet6_exit() cleanup sequence against inet6_init()
  [IPSEC]: More fix is needed for __xfrm6_bundle_create().
  [IRDA] net/irda/: proper prototypes
  ...
parents dafdcfba aef8811a
......@@ -307,3 +307,5 @@ MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Broadcom Blutonium firmware driver ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
MODULE_FIRMWARE("BCM2033-MD.hex");
MODULE_FIRMWARE("BCM2033-FW.bin");
......@@ -801,3 +801,4 @@ MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("BlueFRITZ! USB driver ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
MODULE_FIRMWARE("bfubase.frm");
......@@ -63,6 +63,7 @@
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>, Jose Orlando Pereira <jop@di.uminho.pt>");
MODULE_DESCRIPTION("Bluetooth driver for the 3Com Bluetooth PCMCIA card");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE("BT3CPCC.bin");
......
......@@ -64,8 +64,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "3.73"
#define DRV_MODULE_RELDATE "February 12, 2007"
#define DRV_MODULE_VERSION "3.74"
#define DRV_MODULE_RELDATE "February 20, 2007"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
......@@ -3993,7 +3993,10 @@ static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb)
/* Estimate the number of fragments in the worst case */
if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->gso_segs * 3))) {
netif_stop_queue(tp->dev);
return NETDEV_TX_BUSY;
if (tg3_tx_avail(tp) <= (skb_shinfo(skb)->gso_segs * 3))
return NETDEV_TX_BUSY;
netif_wake_queue(tp->dev);
}
segs = skb_gso_segment(skb, tp->dev->features & ~NETIF_F_TSO);
......@@ -4061,7 +4064,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
hdr_len = ip_tcp_len + tcp_opt_len;
if (unlikely((ETH_HLEN + hdr_len) > 80) &&
(tp->tg3_flags2 & TG3_FLG2_HW_TSO_1_BUG))
(tp->tg3_flags2 & TG3_FLG2_TSO_BUG))
return (tg3_tso_bug(tp, skb));
base_flags |= (TXD_FLAG_CPU_PRE_DMA |
......@@ -8137,7 +8140,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
(ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) ||
(ering->tx_pending > TG3_TX_RING_SIZE - 1) ||
(ering->tx_pending <= MAX_SKB_FRAGS) ||
((tp->tg3_flags2 & TG3_FLG2_HW_TSO_1_BUG) &&
((tp->tg3_flags2 & TG3_FLG2_TSO_BUG) &&
(ering->tx_pending <= (MAX_SKB_FRAGS * 3))))
return -EINVAL;
......@@ -10557,12 +10560,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2;
tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI;
} else {
tp->tg3_flags2 |= TG3_FLG2_HW_TSO_1 |
TG3_FLG2_HW_TSO_1_BUG;
tp->tg3_flags2 |= TG3_FLG2_HW_TSO_1 | TG3_FLG2_TSO_BUG;
if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
ASIC_REV_5750 &&
tp->pci_chip_rev_id >= CHIPREV_ID_5750_C2)
tp->tg3_flags2 &= ~TG3_FLG2_HW_TSO_1_BUG;
tp->tg3_flags2 &= ~TG3_FLG2_TSO_BUG;
}
}
......@@ -11867,7 +11869,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0) {
tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE;
} else {
tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE;
tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE | TG3_FLG2_TSO_BUG;
}
/* TSO is on by default on chips that support hardware TSO.
......
......@@ -2227,7 +2227,7 @@ struct tg3 {
#define TG3_FLAG_INIT_COMPLETE 0x80000000
u32 tg3_flags2;
#define TG3_FLG2_RESTART_TIMER 0x00000001
#define TG3_FLG2_HW_TSO_1_BUG 0x00000002
#define TG3_FLG2_TSO_BUG 0x00000002
#define TG3_FLG2_NO_ETH_WIRE_SPEED 0x00000004
#define TG3_FLG2_IS_5788 0x00000008
#define TG3_FLG2_MAX_RXPEND_64 0x00000010
......
......@@ -113,4 +113,20 @@ do { if(!(expr)) { \
#define IAS_IRCOMM_ID 0x2343
#define IAS_IRLPT_ID 0x9876
struct net_device;
struct packet_type;
extern void irda_proc_register(void);
extern void irda_proc_unregister(void);
extern int irda_sysctl_register(void);
extern void irda_sysctl_unregister(void);
extern int irsock_init(void);
extern void irsock_cleanup(void);
extern int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *ptype,
struct net_device *orig_dev);
#endif /* NET_IRDA_H */
config BT_HIDP
tristate "HIDP protocol support"
depends on BT && BT_L2CAP && INPUT
select HID
help
HIDP (Human Interface Device Protocol) is a transport layer
for HID reports. HIDP is required for the Bluetooth Human
......
......@@ -38,6 +38,7 @@
#include <net/sock.h>
#include <linux/input.h>
#include <linux/hid.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
......@@ -50,7 +51,7 @@
#define BT_DBG(D...)
#endif
#define VERSION "1.1"
#define VERSION "1.2"
static DECLARE_RWSEM(hidp_session_sem);
static LIST_HEAD(hidp_session_list);
......@@ -124,15 +125,22 @@ static void __hidp_copy_session(struct hidp_session *session, struct hidp_connin
else
strncpy(ci->name, "HID Boot Device", 128);
}
if (session->hid) {
ci->vendor = session->hid->vendor;
ci->product = session->hid->product;
ci->version = session->hid->version;
strncpy(ci->name, session->hid->name, 128);
}
}
static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
static inline int hidp_queue_event(struct hidp_session *session, struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{
struct hidp_session *session = dev->private;
struct sk_buff *skb;
unsigned char newleds;
struct sk_buff *skb;
BT_DBG("input %p type %d code %d value %d", dev, type, code, value);
BT_DBG("session %p type %d code %d value %d", session, type, code, value);
if (type != EV_LED)
return -1;
......@@ -164,6 +172,21 @@ static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned i
return 0;
}
static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
struct hid_device *hid = dev->private;
struct hidp_session *session = hid->driver_data;
return hidp_queue_event(session, dev, type, code, value);
}
static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
struct hidp_session *session = dev->private;
return hidp_queue_event(session, dev, type, code, value);
}
static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
{
struct input_dev *dev = session->input;
......@@ -219,6 +242,42 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
input_sync(dev);
}
static inline int hidp_queue_report(struct hidp_session *session, unsigned char *data, int size)
{
struct sk_buff *skb;
BT_DBG("session %p hid %p data %p size %d", session, device, data, size);
if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) {
BT_ERR("Can't allocate memory for new frame");
return -ENOMEM;
}
*skb_put(skb, 1) = 0xa2;
if (size > 0)
memcpy(skb_put(skb, size), data, size);
skb_queue_tail(&session->intr_transmit, skb);
hidp_schedule(session);
return 0;
}
static int hidp_send_report(struct hidp_session *session, struct hid_report *report)
{
unsigned char buf[32];
int rsize;
rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0);
if (rsize > sizeof(buf))
return -EIO;
hid_output_report(report, buf);
return hidp_queue_report(session, buf, rsize);
}
static void hidp_idle_timeout(unsigned long arg)
{
struct hidp_session *session = (struct hidp_session *) arg;
......@@ -346,6 +405,10 @@ static inline void hidp_process_data(struct hidp_session *session, struct sk_buf
if (session->input)
hidp_input_report(session, skb);
if (session->hid)
hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
break;
case HIDP_DATA_RTYPE_OTHER:
......@@ -404,8 +467,14 @@ static inline void hidp_recv_intr_frame(struct hidp_session *session, struct sk_
if (hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
hidp_set_timer(session);
if (session->input)
hidp_input_report(session, skb);
if (session->hid) {
hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1);
BT_DBG("report len %d", skb->len);
}
} else {
BT_DBG("Unsupported protocol header 0x%02x", hdr);
}
......@@ -471,6 +540,11 @@ static int hidp_session(void *arg)
product = session->input->id.product;
}
if (session->hid) {
vendor = session->hid->vendor;
product = session->hid->product;
}
daemonize("khidpd_%04x%04x", vendor, product);
set_user_nice(current, -15);
current->flags |= PF_NOFREEZE;
......@@ -521,6 +595,12 @@ static int hidp_session(void *arg)
session->input = NULL;
}
if (session->hid) {
if (session->hid->claimed & HID_CLAIMED_INPUT)
hidinput_disconnect(session->hid);
hid_free_device(session->hid);
}
up_write(&hidp_session_sem);
kfree(session);
......@@ -590,6 +670,56 @@ static inline void hidp_setup_input(struct hidp_session *session, struct hidp_co
input_register_device(input);
}
static int hidp_open(struct hid_device *hid)
{
return 0;
}
static void hidp_close(struct hid_device *hid)
{
}
static inline void hidp_setup_hid(struct hidp_session *session, struct hidp_connadd_req *req)
{
struct hid_device *hid = session->hid;
struct hid_report *report;
bdaddr_t src, dst;
baswap(&src, &bt_sk(session->ctrl_sock->sk)->src);
baswap(&dst, &bt_sk(session->ctrl_sock->sk)->dst);
hid->driver_data = session;
hid->country = req->country;
hid->bus = BUS_BLUETOOTH;
hid->vendor = req->vendor;
hid->product = req->product;
hid->version = req->version;
strncpy(hid->name, req->name, 128);
strncpy(hid->phys, batostr(&src), 64);
strncpy(hid->uniq, batostr(&dst), 64);
hid->dev = hidp_get_device(session);
hid->hid_open = hidp_open;
hid->hid_close = hidp_close;
hid->hidinput_input_event = hidp_hidinput_event;
list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list)
hidp_send_report(session, report);
list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
hidp_send_report(session, report);
if (hidinput_connect(hid) == 0) {
hid->claimed |= HID_CLAIMED_INPUT;
hid_ff_init(hid);
}
}
int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
{
struct hidp_session *session, *s;
......@@ -605,10 +735,38 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
if (!session)
return -ENOMEM;
session->input = input_allocate_device();
if (!session->input) {
kfree(session);
return -ENOMEM;
BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size);
if (req->rd_size > 0) {
unsigned char *buf = kmalloc(req->rd_size, GFP_KERNEL);
if (!buf) {
kfree(session);
return -ENOMEM;
}
if (copy_from_user(buf, req->rd_data, req->rd_size)) {
kfree(buf);
kfree(session);
return -EFAULT;
}
session->hid = hid_parse_report(buf, req->rd_size);
kfree(buf);
if (!session->hid) {
kfree(session);
return -EINVAL;
}
}
if (!session->hid) {
session->input = input_allocate_device();
if (!session->input) {
kfree(session);
return -ENOMEM;
}
}
down_write(&hidp_session_sem);
......@@ -644,6 +802,9 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
if (session->input)
hidp_setup_input(session, req);
if (session->hid)
hidp_setup_hid(session, req);
__hidp_link_session(session);
hidp_set_timer(session);
......@@ -677,6 +838,9 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
failed:
up_write(&hidp_session_sem);
if (session->hid)
hid_free_device(session->hid);
kfree(session->input);
kfree(session);
return err;
......
......@@ -145,6 +145,8 @@ struct hidp_session {
struct input_dev *input;
struct hid_device *hid;
struct timer_list timer;
struct sk_buff_head ctrl_transmit;
......
......@@ -194,7 +194,7 @@ static int hidp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigne
if (put_user(ca.ctrl_sock, &uca->ctrl_sock) ||
put_user(ca.intr_sock, &uca->intr_sock) ||
put_user(ca.parser, &uca->parser) ||
put_user(ca.rd_size, &uca->parser) ||
put_user(ca.rd_size, &uca->rd_size) ||
put_user(compat_ptr(ca.rd_data), &uca->rd_data) ||
put_user(ca.country, &uca->country) ||
put_user(ca.subclass, &uca->subclass) ||
......
......@@ -74,6 +74,8 @@ struct rfcomm_dev {
wait_queue_head_t wait;
struct tasklet_struct wakeup_task;
struct device *tty_dev;
atomic_t wmem_alloc;
};
......@@ -261,7 +263,7 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
return err;
}
tty_register_device(rfcomm_tty_driver, dev->id, rfcomm_get_device(dev));
dev->tty_dev = tty_register_device(rfcomm_tty_driver, dev->id, NULL);
return dev->id;
}
......@@ -630,6 +632,9 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
set_current_state(TASK_RUNNING);
remove_wait_queue(&dev->wait, &wait);
if (err == 0)
device_move(dev->tty_dev, rfcomm_get_device(dev));
return err;
}
......@@ -642,6 +647,8 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp)
BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc, dev->opened);
if (--dev->opened == 0) {
device_move(dev->tty_dev, NULL);
/* Close DLC and dettach TTY */
rfcomm_dlc_close(dev->dlc, 0);
......
......@@ -77,26 +77,15 @@ static int port_cost(struct net_device *dev)
* Called from work queue to allow for calling functions that
* might sleep (such as speed check), and to debounce.
*/
static void port_carrier_check(struct work_struct *work)
void br_port_carrier_check(struct net_bridge_port *p)
{
struct net_bridge_port *p;
struct net_device *dev;
struct net_bridge *br;
dev = container_of(work, struct net_bridge_port,
carrier_check.work)->dev;
work_release(work);
rtnl_lock();
p = dev->br_port;
if (!p)
goto done;
br = p->br;
struct net_device *dev = p->dev;
struct net_bridge *br = p->br;
if (netif_carrier_ok(dev))
p->path_cost = port_cost(dev);
if (br->dev->flags & IFF_UP) {
if (netif_running(br->dev)) {
spin_lock_bh(&br->lock);
if (netif_carrier_ok(dev)) {
if (p->state == BR_STATE_DISABLED)
......@@ -107,9 +96,6 @@ static void port_carrier_check(struct work_struct *work)
}
spin_unlock_bh(&br->lock);
}
done:
dev_put(dev);
rtnl_unlock();
}
static void release_nbp(struct kobject *kobj)
......@@ -162,9 +148,6 @@ static void del_nbp(struct net_bridge_port *p)
dev_set_promiscuity(dev, -1);
if (cancel_delayed_work(&p->carrier_check))
dev_put(dev);
spin_lock_bh(&br->lock);
br_stp_disable_port(p);
spin_unlock_bh(&br->lock);
......@@ -282,7 +265,6 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
p->port_no = index;
br_init_port(p);
p->state = BR_STATE_DISABLED;
INIT_DELAYED_WORK_NAR(&p->carrier_check, port_carrier_check);
br_stp_port_timer_init(p);
kobject_init(&p->kobj);
......@@ -446,12 +428,10 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
spin_lock_bh(&br->lock);
br_stp_recalculate_bridge_id(br);
br_features_recompute(br);
if (schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE))
dev_hold(dev);
spin_unlock_bh(&br->lock);
dev_set_mtu(br->dev, br_min_mtu(br));
kobject_uevent(&p->kobj, KOBJ_ADD);
return 0;
......
......@@ -42,51 +42,48 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
br = p->br;
spin_lock_bh(&br->lock);
switch (event) {
case NETDEV_CHANGEMTU:
dev_set_mtu(br->dev, br_min_mtu(br));
break;
case NETDEV_CHANGEADDR:
spin_lock_bh(&br->lock);
br_fdb_changeaddr(p, dev->dev_addr);
br_ifinfo_notify(RTM_NEWLINK, p);
br_stp_recalculate_bridge_id(br);
spin_unlock_bh(&br->lock);
break;
case NETDEV_CHANGE:
if (br->dev->flags & IFF_UP)
if (schedule_delayed_work(&p->carrier_check,
BR_PORT_DEBOUNCE))
dev_hold(dev);
br_port_carrier_check(p);
break;
case NETDEV_FEAT_CHANGE:
if (br->dev->flags & IFF_UP)
spin_lock_bh(&br->lock);
if (netif_running(br->dev))
br_features_recompute(br);
/* could do recursive feature change notification
* but who would care??
*/
spin_unlock_bh(&br->lock);
break;
case NETDEV_DOWN:
spin_lock_bh(&br->lock);
if (br->dev->flags & IFF_UP)
br_stp_disable_port(p);
spin_unlock_bh(&br->lock);
break;
case NETDEV_UP:
spin_lock_bh(&br->lock);
if (netif_carrier_ok(dev) && (br->dev->flags & IFF_UP))
br_stp_enable_port(p);
spin_unlock_bh(&br->lock);
break;
case NETDEV_UNREGISTER:
spin_unlock_bh(&br->lock);
br_del_if(br, dev);
goto done;
break;
}
spin_unlock_bh(&br->lock);
done:
return NOTIFY_DONE;
}
......@@ -16,7 +16,6 @@
#define _BR_PRIVATE_H
#include <linux/netdevice.h>
#include <linux/miscdevice.h>
#include <linux/if_bridge.h>
#define BR_HASH_BITS 8
......@@ -27,8 +26,6 @@
#define BR_PORT_BITS 10
#define BR_MAX_PORTS (1<<BR_PORT_BITS)
#define BR_PORT_DEBOUNCE (HZ/10)
#define BR_VERSION "2.2"
typedef struct bridge_id bridge_id;
......@@ -82,7 +79,6 @@ struct net_bridge_port
struct timer_list hold_timer;
struct timer_list message_age_timer;
struct kobject kobj;
struct delayed_work carrier_check;
struct rcu_head rcu;
};
......@@ -173,6 +169,7 @@ extern void br_flood_forward(struct net_bridge *br,
int clone);
/* br_if.c */
extern void br_port_carrier_check(struct net_bridge_port *p);
extern int br_add_bridge(const char *name);
extern int br_del_bridge(const char *name);
extern void br_cleanup_bridges(void);
......
......@@ -442,7 +442,7 @@ config INET_DIAG
---help---
Support for INET (TCP, DCCP, etc) socket monitoring interface used by
native Linux tools such as ss. ss is included in iproute2, currently
downloadable at <http://developer.osdl.org/dev/iproute2>.
downloadable at <http://linux-net.osdl.org/index.php/Iproute2>.
If unsure, say Y.
......@@ -550,7 +550,7 @@ config TCP_CONG_SCALABLE
Scalable TCP is a sender-side only change to TCP which uses a
MIMD congestion control algorithm which has some nice scaling
properties, though is known to have fairness issues.
See http://www-lce.eng.cam.ac.uk/~ctk21/scalable/
See http://www.deneholme.net/tom/scalable/
config TCP_CONG_LP
tristate "TCP Low Priority"
......
......@@ -1054,12 +1054,14 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
ASSERT_RTNL();
if (!in_dev) {
if (event == NETDEV_REGISTER && dev == &loopback_dev) {
if (event == NETDEV_REGISTER) {
in_dev = inetdev_init(dev);
if (!in_dev)
panic("devinet: Failed to create loopback\n");
in_dev->cnf.no_xfrm = 1;
in_dev->cnf.no_policy = 1;
if (dev == &loopback_dev) {
in_dev->cnf.no_xfrm = 1;
in_dev->cnf.no_policy = 1;
}
}
goto out;
}
......
......@@ -32,6 +32,7 @@
#include <linux/module.h>
#include <linux/mroute.h>
#include <linux/init.h>
#include <linux/random.h>
#include <net/ip.h>
#include <net/protocol.h>
#include <linux/skbuff.h>
......@@ -48,21 +49,6 @@
#define MULTIPATH_MAX_CANDIDATES 40
/* interface to random number generation */
static unsigned int RANDOM_SEED = 93186752;
static inline unsigned int random(unsigned int ubound)
{
static unsigned int a = 1588635695,
q = 2,
r = 1117695901;
RANDOM_SEED = a*(RANDOM_SEED % q) - r*(RANDOM_SEED / q);
return RANDOM_SEED % ubound;
}
static void random_select_route(const struct flowi *flp,
struct rtable *first,
struct rtable **rp)
......@@ -84,7 +70,7 @@ static void random_select_route(const struct flowi *flp,
if (candidate_count > 1) {
unsigned char i = 0;
unsigned char candidate_no = (unsigned char)
random(candidate_count);
(random32() % candidate_count);
/* find chosen candidate and adjust GC data for all candidates
* to ensure they stay in cache
......
......@@ -32,6 +32,7 @@
#include <linux/module.h>
#include <linux/mroute.h>
#include <linux/init.h>
#include <linux/random.h>
#include <net/ip.h>
#include <net/protocol.h>
#include <linux/skbuff.h>
......@@ -84,18 +85,6 @@ struct multipath_route {
/* state: primarily weight per route information */
static struct multipath_bucket state[MULTIPATH_STATE_SIZE];
/* interface to random number generation */
static unsigned int RANDOM_SEED = 93186752;
static inline unsigned int random(unsigned int ubound)
{
static unsigned int a = 1588635695,
q = 2,
r = 1117695901;
RANDOM_SEED = a*(RANDOM_SEED % q) - r*(RANDOM_SEED / q);
return RANDOM_SEED % ubound;
}
static unsigned char __multipath_lookup_weight(const struct flowi *fl,
const struct rtable *rt)
{
......@@ -193,7 +182,7 @@ static void wrandom_select_route(const struct flowi *flp,
/* choose a weighted random candidate */
decision = first;
selector = random(power);
selector = random32() % power;
last_power = 0;
/* select candidate, adjust GC data and cleanup local state */
......
......@@ -2266,12 +2266,12 @@ void tcp_free_md5sig_pool(void)
{
struct tcp_md5sig_pool **pool = NULL;
spin_lock(&tcp_md5sig_pool_lock);
spin_lock_bh(&tcp_md5sig_pool_lock);
if (--tcp_md5sig_users == 0) {
pool = tcp_md5sig_pool;
tcp_md5sig_pool = NULL;
}
spin_unlock(&tcp_md5sig_pool_lock);
spin_unlock_bh(&tcp_md5sig_pool_lock);
if (pool)
__tcp_free_md5sig_pool(pool);
}
......@@ -2314,36 +2314,36 @@ struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(void)
int alloc = 0;
retry:
spin_lock(&tcp_md5sig_pool_lock);
spin_lock_bh(&tcp_md5sig_pool_lock);
pool = tcp_md5sig_pool;
if (tcp_md5sig_users++ == 0) {
alloc = 1;
spin_unlock(&tcp_md5sig_pool_lock);
spin_unlock_bh(&tcp_md5sig_pool_lock);
} else if (!pool) {
tcp_md5sig_users--;
spin_unlock(&tcp_md5sig_pool_lock);
spin_unlock_bh(&tcp_md5sig_pool_lock);
cpu_relax();
goto retry;
} else
spin_unlock(&tcp_md5sig_pool_lock);
spin_unlock_bh(&tcp_md5sig_pool_lock);
if (alloc) {
/* we cannot hold spinlock here because this may sleep. */
struct tcp_md5sig_pool **p = __tcp_alloc_md5sig_pool();
spin_lock(&tcp_md5sig_pool_lock);
spin_lock_bh(&tcp_md5sig_pool_lock);
if (!p) {
tcp_md5sig_users--;
spin_unlock(&tcp_md5sig_pool_lock);
spin_unlock_bh(&tcp_md5sig_pool_lock);
return NULL;
}
pool = tcp_md5sig_pool;
if (pool) {
/* oops, it has already been assigned. */
spin_unlock(&tcp_md5sig_pool_lock);
spin_unlock_bh(&tcp_md5sig_pool_lock);
__tcp_free_md5sig_pool(p);
} else {
tcp_md5sig_pool = pool = p;
spin_unlock(&tcp_md5sig_pool_lock);
spin_unlock_bh(&tcp_md5sig_pool_lock);
}
}
return pool;
......@@ -2354,11 +2354,11 @@ EXPORT_SYMBOL(tcp_alloc_md5sig_pool);
struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu)
{
struct tcp_md5sig_pool **p;
spin_lock(&tcp_md5sig_pool_lock);
spin_lock_bh(&tcp_md5sig_pool_lock);
p = tcp_md5sig_pool;
if (p)
tcp_md5sig_users++;
spin_unlock(&tcp_md5sig_pool_lock);
spin_unlock_bh(&tcp_md5sig_pool_lock);
return (p ? *per_cpu_ptr(p, cpu) : NULL);
}
......
......@@ -111,6 +111,7 @@ static int xfrm4_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
(err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
goto out;
iph = skb->nh.iph;
if (iph->protocol == IPPROTO_IPIP) {
if (x->props.flags & XFRM_STATE_DECAP_DSCP)
ipv4_copy_dscp(iph, skb->h.ipiph);
......
......@@ -291,7 +291,7 @@ static void xfrm4_dst_destroy(struct dst_entry *dst)
if (likely(xdst->u.rt.idev))
in_dev_put(xdst->u.rt.idev);
if (dst->xfrm->props.family == AF_INET && likely(xdst->u.rt.peer))
if (dst->xfrm && dst->xfrm->props.family == AF_INET && likely(xdst->u.rt.peer))
inet_putpeer(xdst->u.rt.peer);
xfrm_dst_destroy(xdst);
}
......
......@@ -32,6 +32,6 @@ obj-$(CONFIG_NETFILTER) += netfilter/
obj-$(CONFIG_IPV6_SIT) += sit.o
obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
obj-y += exthdrs_core.o
obj-y += addrconf_core.o exthdrs_core.o
obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o
......@@ -211,74 +211,6 @@ const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
#endif
const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
#define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16)
static inline unsigned ipv6_addr_scope2type(unsigned scope)
{
switch(scope) {
case IPV6_ADDR_SCOPE_NODELOCAL:
return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_NODELOCAL) |
IPV6_ADDR_LOOPBACK);
case IPV6_ADDR_SCOPE_LINKLOCAL:
return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL) |
IPV6_ADDR_LINKLOCAL);
case IPV6_ADDR_SCOPE_SITELOCAL:
return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL) |
IPV6_ADDR_SITELOCAL);
}
return IPV6_ADDR_SCOPE_TYPE(scope);
}
int __ipv6_addr_type(const struct in6_addr *addr)
{
__be32 st;
st = addr->s6_addr32[0];
/* Consider all addresses with the first three bits different of
000 and 111 as unicasts.
*/
if ((st & htonl(0xE0000000)) != htonl(0x00000000) &&
(st & htonl(0xE0000000)) != htonl(0xE0000000))
return (IPV6_ADDR_UNICAST |
IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));
if ((st & htonl(0xFF000000)) == htonl(0xFF000000)) {
/* multicast */
/* addr-select 3.1 */
return (IPV6_ADDR_MULTICAST |
ipv6_addr_scope2type(IPV6_ADDR_MC_SCOPE(addr)));
}
if ((st & htonl(0xFFC00000)) == htonl(0xFE800000))
return (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST |
IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.1 */
if ((st & htonl(0xFFC00000)) == htonl(0xFEC00000))
return (IPV6_ADDR_SITELOCAL | IPV6_ADDR_UNICAST |
IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL)); /* addr-select 3.1 */
if ((addr->s6_addr32[0] | addr->s6_addr32[1]) == 0) {
if (addr->s6_addr32[2] == 0) {
if (addr->s6_addr32[3] == 0)
return IPV6_ADDR_ANY;
if (addr->s6_addr32[3] == htonl(0x00000001))
return (IPV6_ADDR_LOOPBACK | IPV6_ADDR_UNICAST |
IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.4 */
return (IPV6_ADDR_COMPATv4 | IPV6_ADDR_UNICAST |
IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */
}
if (addr->s6_addr32[2] == htonl(0x0000ffff))
return (IPV6_ADDR_MAPPED |
IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */
}
return (IPV6_ADDR_RESERVED |
IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.4 */
}
static void addrconf_del_timer(struct inet6_ifaddr *ifp)
{
if (del_timer(&ifp->timer))
......@@ -1910,6 +1842,7 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
struct inet6_dev *idev;
struct net_device *dev;
int scope;
u32 flags = RTF_EXPIRES;
ASSERT_RTNL();
......@@ -1925,9 +1858,10 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
scope = ipv6_addr_scope(pfx);
if (valid_lft == INFINITY_LIFE_TIME)
if (valid_lft == INFINITY_LIFE_TIME) {
ifa_flags |= IFA_F_PERMANENT;
else if (valid_lft >= 0x7FFFFFFF/HZ)
flags = 0;
} else if (valid_lft >= 0x7FFFFFFF/HZ)
valid_lft = 0x7FFFFFFF/HZ;
if (prefered_lft == 0)
......@@ -1945,6 +1879,8 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
ifp->tstamp = jiffies;
spin_unlock_bh(&ifp->lock);
addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev,
jiffies_to_clock_t(valid_lft * HZ), flags);
addrconf_dad_start(ifp, 0);
in6_ifa_put(ifp);
addrconf_verify(0);
......@@ -2124,6 +2060,7 @@ static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr
ifp = ipv6_add_addr(idev, addr, 64, IFA_LINK, IFA_F_PERMANENT);
if (!IS_ERR(ifp)) {
addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0);
addrconf_dad_start(ifp, 0);
in6_ifa_put(ifp);
}
......@@ -2240,6 +2177,14 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
int run_pending = 0;
switch(event) {
case NETDEV_REGISTER:
if (!idev) {
idev = ipv6_add_dev(dev);
if (!idev)
printk(KERN_WARNING "IPv6: add_dev failed for %s\n",
dev->name);
}
break;
case NETDEV_UP:
case NETDEV_CHANGE:
if (event == NETDEV_UP) {
......@@ -2538,10 +2483,6 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
addrconf_join_solict(dev, &ifp->addr);
if (ifp->prefix_len != 128 && (ifp->flags&IFA_F_PERMANENT))
addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev, 0,
flags);
net_srandom(ifp->addr.s6_addr32[3]);
read_lock_bh(&idev->lock);
......@@ -2972,12 +2913,15 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
u32 prefered_lft, u32 valid_lft)
{
u32 flags = RTF_EXPIRES;
if (!valid_lft || (prefered_lft > valid_lft))
return -EINVAL;
if (valid_lft == INFINITY_LIFE_TIME)
if (valid_lft == INFINITY_LIFE_TIME) {
ifa_flags |= IFA_F_PERMANENT;
else if (valid_lft >= 0x7FFFFFFF/HZ)
flags = 0;
} else if (valid_lft >= 0x7FFFFFFF/HZ)
valid_lft = 0x7FFFFFFF/HZ;
if (prefered_lft == 0)
......@@ -2996,6 +2940,8 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
if (!(ifp->flags&IFA_F_TENTATIVE))
ipv6_ifa_notify(0, ifp);
addrconf_prefix_route(&ifp->addr, ifp->prefix_len, ifp->idev->dev,
jiffies_to_clock_t(valid_lft * HZ), flags);
addrconf_verify(0);
return 0;
......
/*
* IPv6 library code, needed by static components when full IPv6 support is
* not configured or static.
*/
#include <net/ipv6.h>
#define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16)
static inline unsigned ipv6_addr_scope2type(unsigned scope)
{
switch(scope) {
case IPV6_ADDR_SCOPE_NODELOCAL:
return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_NODELOCAL) |
IPV6_ADDR_LOOPBACK);
case IPV6_ADDR_SCOPE_LINKLOCAL:
return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL) |
IPV6_ADDR_LINKLOCAL);
case IPV6_ADDR_SCOPE_SITELOCAL:
return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL) |
IPV6_ADDR_SITELOCAL);
}
return IPV6_ADDR_SCOPE_TYPE(scope);
}
int __ipv6_addr_type(const struct in6_addr *addr)
{
__be32 st;
st = addr->s6_addr32[0];
/* Consider all addresses with the first three bits different of
000 and 111 as unicasts.
*/
if ((st & htonl(0xE0000000)) != htonl(0x00000000) &&
(st & htonl(0xE0000000)) != htonl(0xE0000000))
return (IPV6_ADDR_UNICAST |
IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));
if ((st & htonl(0xFF000000)) == htonl(0xFF000000)) {
/* multicast */
/* addr-select 3.1 */
return (IPV6_ADDR_MULTICAST |
ipv6_addr_scope2type(IPV6_ADDR_MC_SCOPE(addr)));
}
if ((st & htonl(0xFFC00000)) == htonl(0xFE800000))
return (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST |
IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.1 */
if ((st & htonl(0xFFC00000)) == htonl(0xFEC00000))
return (IPV6_ADDR_SITELOCAL | IPV6_ADDR_UNICAST |
IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL)); /* addr-select 3.1 */
if ((addr->s6_addr32[0] | addr->s6_addr32[1]) == 0) {
if (addr->s6_addr32[2] == 0) {
if (addr->s6_addr32[3] == 0)
return IPV6_ADDR_ANY;
if (addr->s6_addr32[3] == htonl(0x00000001))
return (IPV6_ADDR_LOOPBACK | IPV6_ADDR_UNICAST |
IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.4 */
return (IPV6_ADDR_COMPATv4 | IPV6_ADDR_UNICAST |
IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */
}
if (addr->s6_addr32[2] == htonl(0x0000ffff))
return (IPV6_ADDR_MAPPED |
IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */
}
return (IPV6_ADDR_RESERVED |
IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.4 */
}
EXPORT_SYMBOL(__ipv6_addr_type);
......@@ -929,25 +929,28 @@ static void __exit inet6_exit(void)
{
/* First of all disallow new sockets creation. */
sock_unregister(PF_INET6);
/* Cleanup code parts. */
ipv6_packet_cleanup();
#ifdef CONFIG_IPV6_MIP6
mip6_fini();
#endif
addrconf_cleanup();
ip6_flowlabel_cleanup();
ip6_route_cleanup();
#ifdef CONFIG_PROC_FS
/* Cleanup code parts. */
if6_proc_exit();
ac6_proc_exit();
ipv6_misc_proc_exit();
udp6_proc_exit();
udplite6_proc_exit();
udp6_proc_exit();
tcp6_proc_exit();
raw6_proc_exit();
#endif
#ifdef CONFIG_IPV6_MIP6
mip6_fini();
#endif
/* Cleanup code parts. */
ip6_flowlabel_cleanup();
addrconf_cleanup();
ip6_route_cleanup();
ipv6_packet_cleanup();
igmp6_cleanup();
ipv6_netfilter_fini();
igmp6_cleanup();
ndisc_cleanup();
icmpv6_cleanup();
#ifdef CONFIG_SYSCTL
......@@ -955,6 +958,7 @@ static void __exit inet6_exit(void)
#endif
cleanup_ipv6_mibs();
proto_unregister(&rawv6_prot);
proto_unregister(&udplitev6_prot);
proto_unregister(&udpv6_prot);
proto_unregister(&tcpv6_prot);
}
......
......@@ -727,11 +727,8 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
}
if (mtu < IPV6_MIN_MTU)
mtu = IPV6_MIN_MTU;
if (skb->dst && mtu < dst_mtu(skb->dst)) {
struct rt6_info *rt = (struct rt6_info *) skb->dst;
rt->rt6i_flags |= RTF_MODIFIED;
rt->u.dst.metrics[RTAX_MTU-1] = mtu;
}
if (skb->dst)
skb->dst->ops->update_pmtu(skb->dst, mtu);
if (skb->len > mtu) {
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev);
goto tx_err_dst_release;
......
......@@ -6,7 +6,6 @@
#include <net/ip6_route.h>
#include <net/xfrm.h>
EXPORT_SYMBOL(__ipv6_addr_type);
EXPORT_SYMBOL(icmpv6_send);
EXPORT_SYMBOL(icmpv6_statistics);
EXPORT_SYMBOL(icmpv6_err_convert);
......
......@@ -189,7 +189,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
case AF_INET6:
ipv6_addr_copy(&fl_tunnel.fl6_dst, __xfrm6_bundle_addr_remote(xfrm[i], &fl->fl6_dst));
ipv6_addr_copy(&fl_tunnel.fl6_src, __xfrm6_bundle_addr_remote(xfrm[i], &fl->fl6_src));
ipv6_addr_copy(&fl_tunnel.fl6_src, __xfrm6_bundle_addr_local(xfrm[i], &fl->fl6_src));
break;
default:
BUG_ON(1);
......
......@@ -42,19 +42,6 @@
#include <net/irda/irttp.h> /* irttp_init */
#include <net/irda/irda_device.h> /* irda_device_init */
/* irproc.c */
extern void irda_proc_register(void);
extern void irda_proc_unregister(void);
/* irsysctl.c */
extern int irda_sysctl_register(void);
extern void irda_sysctl_unregister(void);
/* af_irda.c */
extern int irsock_init(void);
extern void irsock_cleanup(void);
/* irlap_frame.c */
extern int irlap_driver_rcv(struct sk_buff *, struct net_device *,
struct packet_type *, struct net_device *);
/*
* Module parameters
*/
......
......@@ -227,17 +227,14 @@ struct packet_skb_cb {
#ifdef CONFIG_PACKET_MMAP
static inline char *packet_lookup_frame(struct packet_sock *po, unsigned int position)
static inline struct tpacket_hdr *packet_lookup_frame(struct packet_sock *po, unsigned int position)
{
unsigned int pg_vec_pos, frame_offset;
char *frame;
pg_vec_pos = position / po->frames_per_block;
frame_offset = position % po->frames_per_block;
frame = po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size);
return frame;
return (struct tpacket_hdr *)(po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size));
}
#endif
......@@ -639,7 +636,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
}
spin_lock(&sk->sk_receive_queue.lock);
h = (struct tpacket_hdr *)packet_lookup_frame(po, po->head);
h = packet_lookup_frame(po, po->head);
if (h->tp_status)
goto ring_is_full;
......@@ -1473,7 +1470,7 @@ static int packet_notifier(struct notifier_block *this, unsigned long msg, void
{
struct sock *sk;
struct hlist_node *node;
struct net_device *dev = (struct net_device*)data;
struct net_device *dev = data;
read_lock(&packet_sklist_lock);
sk_for_each(sk, node, &packet_sklist) {
......@@ -1588,7 +1585,7 @@ static unsigned int packet_poll(struct file * file, struct socket *sock,
unsigned last = po->head ? po->head-1 : po->frame_max;
struct tpacket_hdr *h;
h = (struct tpacket_hdr *)packet_lookup_frame(po, last);
h = packet_lookup_frame(po, last);
if (h->tp_status)
mask |= POLLIN | POLLRDNORM;
......
......@@ -396,6 +396,19 @@ void sctp_retransmit_mark(struct sctp_outq *q,
if (sctp_chunk_abandoned(chunk)) {
list_del_init(lchunk);
sctp_insert_list(&q->abandoned, lchunk);
/* If this chunk has not been previousely acked,
* stop considering it 'outstanding'. Our peer
* will most likely never see it since it will
* not be retransmitted
*/
if (!chunk->tsn_gap_acked) {
chunk->transport->flight_size -=
sctp_data_size(chunk);
q->outstanding_bytes -= sctp_data_size(chunk);
q->asoc->peer.rwnd += (sctp_data_size(chunk) +
sizeof(struct sk_buff));
}
continue;
}
......@@ -1244,6 +1257,15 @@ static void sctp_check_transmitted(struct sctp_outq *q,
if (sctp_chunk_abandoned(tchunk)) {
/* Move the chunk to abandoned list. */
sctp_insert_list(&q->abandoned, lchunk);
/* If this chunk has not been acked, stop
* considering it as 'outstanding'.
*/
if (!tchunk->tsn_gap_acked) {
tchunk->transport->flight_size -=
sctp_data_size(tchunk);
q->outstanding_bytes -= sctp_data_size(tchunk);
}
continue;
}
......@@ -1695,11 +1717,6 @@ static void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 ctsn)
*/
if (TSN_lte(tsn, ctsn)) {
list_del_init(lchunk);
if (!chunk->tsn_gap_acked) {
chunk->transport->flight_size -=
sctp_data_size(chunk);
q->outstanding_bytes -= sctp_data_size(chunk);
}
sctp_chunk_free(chunk);
} else {
if (TSN_lte(tsn, asoc->adv_peer_ack_point+1)) {
......
......@@ -4605,12 +4605,12 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep,
* sent as soon as cwnd allows (normally when a SACK arrives).
*/
/* NB: Rules E4 and F1 are implicit in R1. */
sctp_add_cmd_sf(commands, SCTP_CMD_RETRAN, SCTP_TRANSPORT(transport));
/* Do some failure management (Section 8.2). */
sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, SCTP_TRANSPORT(transport));
/* NB: Rules E4 and F1 are implicit in R1. */
sctp_add_cmd_sf(commands, SCTP_CMD_RETRAN, SCTP_TRANSPORT(transport));
return SCTP_DISPOSITION_CONSUME;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment