summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-26 12:23:08 -0800
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-26 12:23:08 -0800
commit5d5dde2ed928677028ef859f48a32a503b01c636 (patch)
tree954eb70d7b8095de8e95f22c6b6759b55bc5edb4
parentdafdcfba62f7ef23045f024a305168cac1c07590 (diff)
parentaef8811abbc9249a2bd59bd2331bbe523df05d17 (diff)
downloadlwn-5d5dde2ed928677028ef859f48a32a503b01c636.tar.gz
lwn-5d5dde2ed928677028ef859f48a32a503b01c636.zip
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 ...
-rw-r--r--drivers/bluetooth/bcm203x.c2
-rw-r--r--drivers/bluetooth/bfusb.c1
-rw-r--r--drivers/bluetooth/bt3c_cs.c1
-rw-r--r--drivers/net/tg3.c20
-rw-r--r--drivers/net/tg3.h2
-rw-r--r--include/net/irda/irda.h16
-rw-r--r--net/bluetooth/hidp/Kconfig1
-rw-r--r--net/bluetooth/hidp/core.c182
-rw-r--r--net/bluetooth/hidp/hidp.h2
-rw-r--r--net/bluetooth/hidp/sock.c2
-rw-r--r--net/bluetooth/rfcomm/tty.c9
-rw-r--r--net/bridge/br_if.c30
-rw-r--r--net/bridge/br_notify.c25
-rw-r--r--net/bridge/br_private.h5
-rw-r--r--net/ipv4/Kconfig4
-rw-r--r--net/ipv4/devinet.c8
-rw-r--r--net/ipv4/multipath_random.c18
-rw-r--r--net/ipv4/multipath_wrandom.c15
-rw-r--r--net/ipv4/tcp.c24
-rw-r--r--net/ipv4/xfrm4_mode_tunnel.c1
-rw-r--r--net/ipv4/xfrm4_policy.c2
-rw-r--r--net/ipv6/Makefile2
-rw-r--r--net/ipv6/addrconf.c98
-rw-r--r--net/ipv6/addrconf_core.c76
-rw-r--r--net/ipv6/af_inet6.c24
-rw-r--r--net/ipv6/ip6_tunnel.c7
-rw-r--r--net/ipv6/ipv6_syms.c1
-rw-r--r--net/ipv6/xfrm6_policy.c2
-rw-r--r--net/irda/irmod.c13
-rw-r--r--net/packet/af_packet.c13
-rw-r--r--net/sctp/outqueue.c27
-rw-r--r--net/sctp/sm_statefuns.c6
32 files changed, 405 insertions, 234 deletions
diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c
index 9256985cbe36..8919ccf8274b 100644
--- a/drivers/bluetooth/bcm203x.c
+++ b/drivers/bluetooth/bcm203x.c
@@ -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");
diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c
index 27cceb6f5652..4c766f36d884 100644
--- a/drivers/bluetooth/bfusb.c
+++ b/drivers/bluetooth/bfusb.c
@@ -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");
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index 34e5555cb917..18b0f3992c5b 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -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");
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 81a1c2e1a3f5..26c6ac48288c 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -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.
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 45d477e8f374..086892d8c1f1 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -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
diff --git a/include/net/irda/irda.h b/include/net/irda/irda.h
index 1cb0607fcbb9..89fe534045f1 100644
--- a/include/net/irda/irda.h
+++ b/include/net/irda/irda.h
@@ -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 */
diff --git a/net/bluetooth/hidp/Kconfig b/net/bluetooth/hidp/Kconfig
index c6abf2a5a932..98fdfa1fbddd 100644
--- a/net/bluetooth/hidp/Kconfig
+++ b/net/bluetooth/hidp/Kconfig
@@ -1,6 +1,7 @@
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
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 4b99c5e4478d..4c914df5fd06 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -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 @@ unlink:
failed:
up_write(&hidp_session_sem);
+ if (session->hid)
+ hid_free_device(session->hid);
+
kfree(session->input);
kfree(session);
return err;
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h
index a326601c8f41..343fb0566b3e 100644
--- a/net/bluetooth/hidp/hidp.h
+++ b/net/bluetooth/hidp/hidp.h
@@ -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;
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c
index 8b8a6c1dbd99..0c185257e55b 100644
--- a/net/bluetooth/hidp/sock.c
+++ b/net/bluetooth/hidp/sock.c
@@ -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) ||
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 8cd82dce5008..9a7a44fc721f 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -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 @@ out:
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);
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index aff6a779c9c8..6845a258408f 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -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;
diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c
index 3311c4e30829..37357ed2149b 100644
--- a/net/bridge/br_notify.c
+++ b/net/bridge/br_notify.c
@@ -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;
}
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 6a0540e0591e..cc3f1c99261a 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -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);
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 91f3a5cdbcf8..9e8ef509c51d 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -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"
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 8a0ec10a13a7..e10794dc5f64 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -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;
}
diff --git a/net/ipv4/multipath_random.c b/net/ipv4/multipath_random.c
index 57f481498fbb..c312785d14d0 100644
--- a/net/ipv4/multipath_random.c
+++ b/net/ipv4/multipath_random.c
@@ -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
diff --git a/net/ipv4/multipath_wrandom.c b/net/ipv4/multipath_wrandom.c
index 2bdbb92b450a..57c503694539 100644
--- a/net/ipv4/multipath_wrandom.c
+++ b/net/ipv4/multipath_wrandom.c
@@ -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 */
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index ac6516c642a1..74c4d103ebc2 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -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);
}
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index e1cab33fdad1..ceb4376f572a 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -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);
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index fef19c6bcb98..5d51a2af34c1 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -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);
}
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index 8bacda109b7f..d460017bb353 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -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
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 569a37d698f7..f6ac65d36559 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -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;
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c
new file mode 100644
index 000000000000..faaefb692298
--- /dev/null
+++ b/net/ipv6/addrconf_core.c
@@ -0,0 +1,76 @@
+/*
+ * 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);
+
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 3585d8fa7f02..5cac14a5c778 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -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);
}
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 662edb826899..08d944223ec8 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -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;
diff --git a/net/ipv6/ipv6_syms.c b/net/ipv6/ipv6_syms.c
index 0e8e0676a033..e12e3d4fccec 100644
--- a/net/ipv6/ipv6_syms.c
+++ b/net/ipv6/ipv6_syms.c
@@ -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);
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index b1133f27c8ae..d8a585bd2cb4 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -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);
diff --git a/net/irda/irmod.c b/net/irda/irmod.c
index 826e6c4ca5d5..c7fad2c5b9f3 100644
--- a/net/irda/irmod.c
+++ b/net/irda/irmod.c
@@ -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
*/
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index bf2699074774..28d47e8f2873 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -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;
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 5c2ddd10db06..41abfd17627e 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -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)) {
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index b3cad8a03736..70c39eac0581 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -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;
}