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>"); ...@@ -307,3 +307,5 @@ MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Broadcom Blutonium firmware driver ver " VERSION); MODULE_DESCRIPTION("Broadcom Blutonium firmware driver ver " VERSION);
MODULE_VERSION(VERSION); MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_FIRMWARE("BCM2033-MD.hex");
MODULE_FIRMWARE("BCM2033-FW.bin");
...@@ -801,3 +801,4 @@ MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); ...@@ -801,3 +801,4 @@ MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("BlueFRITZ! USB driver ver " VERSION); MODULE_DESCRIPTION("BlueFRITZ! USB driver ver " VERSION);
MODULE_VERSION(VERSION); MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_FIRMWARE("bfubase.frm");
...@@ -63,6 +63,7 @@ ...@@ -63,6 +63,7 @@
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>, Jose Orlando Pereira <jop@di.uminho.pt>"); 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_DESCRIPTION("Bluetooth driver for the 3Com Bluetooth PCMCIA card");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_FIRMWARE("BT3CPCC.bin");
......
...@@ -64,8 +64,8 @@ ...@@ -64,8 +64,8 @@
#define DRV_MODULE_NAME "tg3" #define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": " #define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "3.73" #define DRV_MODULE_VERSION "3.74"
#define DRV_MODULE_RELDATE "February 12, 2007" #define DRV_MODULE_RELDATE "February 20, 2007"
#define TG3_DEF_MAC_MODE 0 #define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0 #define TG3_DEF_RX_MODE 0
...@@ -3993,7 +3993,10 @@ static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb) ...@@ -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 */ /* Estimate the number of fragments in the worst case */
if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->gso_segs * 3))) { if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->gso_segs * 3))) {
netif_stop_queue(tp->dev); 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); 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) ...@@ -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; hdr_len = ip_tcp_len + tcp_opt_len;
if (unlikely((ETH_HLEN + hdr_len) > 80) && 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)); return (tg3_tso_bug(tp, skb));
base_flags |= (TXD_FLAG_CPU_PRE_DMA | base_flags |= (TXD_FLAG_CPU_PRE_DMA |
...@@ -8137,7 +8140,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e ...@@ -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->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) ||
(ering->tx_pending > TG3_TX_RING_SIZE - 1) || (ering->tx_pending > TG3_TX_RING_SIZE - 1) ||
(ering->tx_pending <= MAX_SKB_FRAGS) || (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)))) (ering->tx_pending <= (MAX_SKB_FRAGS * 3))))
return -EINVAL; return -EINVAL;
...@@ -10557,12 +10560,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) ...@@ -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_HW_TSO_2;
tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI; tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI;
} else { } else {
tp->tg3_flags2 |= TG3_FLG2_HW_TSO_1 | tp->tg3_flags2 |= TG3_FLG2_HW_TSO_1 | TG3_FLG2_TSO_BUG;
TG3_FLG2_HW_TSO_1_BUG;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
ASIC_REV_5750 && ASIC_REV_5750 &&
tp->pci_chip_rev_id >= CHIPREV_ID_5750_C2) 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, ...@@ -11867,7 +11869,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0) { (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0) {
tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE; tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE;
} else { } 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. /* TSO is on by default on chips that support hardware TSO.
......
...@@ -2227,7 +2227,7 @@ struct tg3 { ...@@ -2227,7 +2227,7 @@ struct tg3 {
#define TG3_FLAG_INIT_COMPLETE 0x80000000 #define TG3_FLAG_INIT_COMPLETE 0x80000000
u32 tg3_flags2; u32 tg3_flags2;
#define TG3_FLG2_RESTART_TIMER 0x00000001 #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_NO_ETH_WIRE_SPEED 0x00000004
#define TG3_FLG2_IS_5788 0x00000008 #define TG3_FLG2_IS_5788 0x00000008
#define TG3_FLG2_MAX_RXPEND_64 0x00000010 #define TG3_FLG2_MAX_RXPEND_64 0x00000010
......
...@@ -113,4 +113,20 @@ do { if(!(expr)) { \ ...@@ -113,4 +113,20 @@ do { if(!(expr)) { \
#define IAS_IRCOMM_ID 0x2343 #define IAS_IRCOMM_ID 0x2343
#define IAS_IRLPT_ID 0x9876 #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 */ #endif /* NET_IRDA_H */
config BT_HIDP config BT_HIDP
tristate "HIDP protocol support" tristate "HIDP protocol support"
depends on BT && BT_L2CAP && INPUT depends on BT && BT_L2CAP && INPUT
select HID
help help
HIDP (Human Interface Device Protocol) is a transport layer HIDP (Human Interface Device Protocol) is a transport layer
for HID reports. HIDP is required for the Bluetooth Human for HID reports. HIDP is required for the Bluetooth Human
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <net/sock.h> #include <net/sock.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/hid.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
...@@ -50,7 +51,7 @@ ...@@ -50,7 +51,7 @@
#define BT_DBG(D...) #define BT_DBG(D...)
#endif #endif
#define VERSION "1.1" #define VERSION "1.2"
static DECLARE_RWSEM(hidp_session_sem); static DECLARE_RWSEM(hidp_session_sem);
static LIST_HEAD(hidp_session_list); static LIST_HEAD(hidp_session_list);
...@@ -124,15 +125,22 @@ static void __hidp_copy_session(struct hidp_session *session, struct hidp_connin ...@@ -124,15 +125,22 @@ static void __hidp_copy_session(struct hidp_session *session, struct hidp_connin
else else
strncpy(ci->name, "HID Boot Device", 128); 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; 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) if (type != EV_LED)
return -1; return -1;
...@@ -164,6 +172,21 @@ static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned i ...@@ -164,6 +172,21 @@ static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned i
return 0; 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) static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
{ {
struct input_dev *dev = session->input; struct input_dev *dev = session->input;
...@@ -219,6 +242,42 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb) ...@@ -219,6 +242,42 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
input_sync(dev); 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) static void hidp_idle_timeout(unsigned long arg)
{ {
struct hidp_session *session = (struct hidp_session *) 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 ...@@ -346,6 +405,10 @@ static inline void hidp_process_data(struct hidp_session *session, struct sk_buf
if (session->input) if (session->input)
hidp_input_report(session, skb); hidp_input_report(session, skb);
if (session->hid)
hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
break; break;
case HIDP_DATA_RTYPE_OTHER: case HIDP_DATA_RTYPE_OTHER:
...@@ -404,8 +467,14 @@ static inline void hidp_recv_intr_frame(struct hidp_session *session, struct sk_ ...@@ -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)) { if (hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
hidp_set_timer(session); hidp_set_timer(session);
if (session->input) if (session->input)
hidp_input_report(session, skb); 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 { } else {
BT_DBG("Unsupported protocol header 0x%02x", hdr); BT_DBG("Unsupported protocol header 0x%02x", hdr);
} }
...@@ -471,6 +540,11 @@ static int hidp_session(void *arg) ...@@ -471,6 +540,11 @@ static int hidp_session(void *arg)
product = session->input->id.product; product = session->input->id.product;
} }
if (session->hid) {
vendor = session->hid->vendor;
product = session->hid->product;
}
daemonize("khidpd_%04x%04x", vendor, product); daemonize("khidpd_%04x%04x", vendor, product);
set_user_nice(current, -15); set_user_nice(current, -15);
current->flags |= PF_NOFREEZE; current->flags |= PF_NOFREEZE;
...@@ -521,6 +595,12 @@ static int hidp_session(void *arg) ...@@ -521,6 +595,12 @@ static int hidp_session(void *arg)
session->input = NULL; 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); up_write(&hidp_session_sem);
kfree(session); kfree(session);
...@@ -590,6 +670,56 @@ static inline void hidp_setup_input(struct hidp_session *session, struct hidp_co ...@@ -590,6 +670,56 @@ static inline void hidp_setup_input(struct hidp_session *session, struct hidp_co
input_register_device(input); 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) int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
{ {
struct hidp_session *session, *s; struct hidp_session *session, *s;
...@@ -605,10 +735,38 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, ...@@ -605,10 +735,38 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
if (!session) if (!session)
return -ENOMEM; return -ENOMEM;
session->input = input_allocate_device(); BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size);
if (!session->input) {
kfree(session); if (req->rd_size > 0) {
return -ENOMEM; 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); down_write(&hidp_session_sem);
...@@ -644,6 +802,9 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, ...@@ -644,6 +802,9 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
if (session->input) if (session->input)
hidp_setup_input(session, req); hidp_setup_input(session, req);
if (session->hid)
hidp_setup_hid(session, req);
__hidp_link_session(session); __hidp_link_session(session);
hidp_set_timer(session); hidp_set_timer(session);
...@@ -677,6 +838,9 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, ...@@ -677,6 +838,9 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
failed: failed:
up_write(&hidp_session_sem); up_write(&hidp_session_sem);
if (session->hid)
hid_free_device(session->hid);
kfree(session->input); kfree(session->input);
kfree(session); kfree(session);
return err; return err;
......
...@@ -145,6 +145,8 @@ struct hidp_session { ...@@ -145,6 +145,8 @@ struct hidp_session {
struct input_dev *input; struct input_dev *input;
struct hid_device *hid;
struct timer_list timer; struct timer_list timer;
struct sk_buff_head ctrl_transmit; struct sk_buff_head ctrl_transmit;
......
...@@ -194,7 +194,7 @@ static int hidp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigne ...@@ -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) || if (put_user(ca.ctrl_sock, &uca->ctrl_sock) ||
put_user(ca.intr_sock, &uca->intr_sock) || put_user(ca.intr_sock, &uca->intr_sock) ||
put_user(ca.parser, &uca->parser) || 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(compat_ptr(ca.rd_data), &uca->rd_data) ||
put_user(ca.country, &uca->country) || put_user(ca.country, &uca->country) ||
put_user(ca.subclass, &uca->subclass) || put_user(ca.subclass, &uca->subclass) ||
......
...@@ -74,6 +74,8 @@ struct rfcomm_dev { ...@@ -74,6 +74,8 @@ struct rfcomm_dev {
wait_queue_head_t wait; wait_queue_head_t wait;
struct tasklet_struct wakeup_task; struct tasklet_struct wakeup_task;
struct device *tty_dev;
atomic_t wmem_alloc; atomic_t wmem_alloc;
}; };
...@@ -261,7 +263,7 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) ...@@ -261,7 +263,7 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
return err; 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; return dev->id;
} }
...@@ -630,6 +632,9 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) ...@@ -630,6 +632,9 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
remove_wait_queue(&dev->wait, &wait); remove_wait_queue(&dev->wait, &wait);
if (err == 0)
device_move(dev->tty_dev, rfcomm_get_device(dev));
return err; return err;
} }
...@@ -642,6 +647,8 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp) ...@@ -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); BT_DBG("tty %p dev %p dlc %p opened %d", tty, dev, dev->dlc, dev->opened);
if (--dev->opened == 0) { if (--dev->opened == 0) {
device_move(dev->tty_dev, NULL);
/* Close DLC and dettach TTY */ /* Close DLC and dettach TTY */
rfcomm_dlc_close(dev->dlc, 0); rfcomm_dlc_close(dev->dlc, 0);
......
...@@ -77,26 +77,15 @@ static int port_cost(struct net_device *dev) ...@@ -77,26 +77,15 @@ static int port_cost(struct net_device *dev)
* Called from work queue to allow for calling functions that * Called from work queue to allow for calling functions that
* might sleep (such as speed check), and to debounce. * 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 = p->dev;
struct net_device *dev; struct net_bridge *br = p->br;
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;
if (netif_carrier_ok(dev)) if (netif_carrier_ok(dev))
p->path_cost = port_cost(dev); p->path_cost = port_cost(dev);
if (br->dev->flags & IFF_UP) { if (netif_running(br->dev)) {
spin_lock_bh(&br->lock); spin_lock_bh(&br->lock);
if (netif_carrier_ok(dev)) { if (netif_carrier_ok(dev)) {
if (p->state == BR_STATE_DISABLED) if (p->state == BR_STATE_DISABLED)
...@@ -107,9 +96,6 @@ static void port_carrier_check(struct work_struct *work) ...@@ -107,9 +96,6 @@ static void port_carrier_check(struct work_struct *work)
} }
spin_unlock_bh(&br->lock); spin_unlock_bh(&br->lock);
} }
done:
dev_put(dev);
rtnl_unlock();
} }
static void release_nbp(struct kobject *kobj) static void release_nbp(struct kobject *kobj)
...@@ -162,9 +148,6 @@ static void del_nbp(struct net_bridge_port *p) ...@@ -162,9 +148,6 @@ static void del_nbp(struct net_bridge_port *p)
dev_set_promiscuity(dev, -1); dev_set_promiscuity(dev, -1);
if (cancel_delayed_work(&p->carrier_check))
dev_put(dev);
spin_lock_bh(&br->lock); spin_lock_bh(&br->lock);
br_stp_disable_port(p); br_stp_disable_port(p);
spin_unlock_bh(&br->lock); spin_unlock_bh(&br->lock);
...@@ -282,7 +265,6 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, ...@@ -282,7 +265,6 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
p->port_no = index; p->port_no = index;
br_init_port(p); br_init_port(p);
p->state = BR_STATE_DISABLED; p->state = BR_STATE_DISABLED;
INIT_DELAYED_WORK_NAR(&p->carrier_check, port_carrier_check);
br_stp_port_timer_init(p); br_stp_port_timer_init(p);
kobject_init(&p->kobj); kobject_init(&p->kobj);
...@@ -446,12 +428,10 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) ...@@ -446,12 +428,10 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
spin_lock_bh(&br->lock); spin_lock_bh(&br->lock);
br_stp_recalculate_bridge_id(br); br_stp_recalculate_bridge_id(br);
br_features_recompute(br); br_features_recompute(br);
if (schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE))
dev_hold(dev);
spin_unlock_bh(&br->lock); spin_unlock_bh(&br->lock);
dev_set_mtu(br->dev, br_min_mtu(br)); dev_set_mtu(br->dev, br_min_mtu(br));
kobject_uevent(&p->kobj, KOBJ_ADD); kobject_uevent(&p->kobj, KOBJ_ADD);
return 0; return 0;
......
...@@ -42,51 +42,48 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v ...@@ -42,51 +42,48 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
br = p->br; br = p->br;
spin_lock_bh(&br->lock);
switch (event) { switch (event) {
case NETDEV_CHANGEMTU: case NETDEV_CHANGEMTU:
dev_set_mtu(br->dev, br_min_mtu(br)); dev_set_mtu(br->dev, br_min_mtu(br));
break; break;
case NETDEV_CHANGEADDR: case NETDEV_CHANGEADDR:
spin_lock_bh(&br->lock);
br_fdb_changeaddr(p, dev->dev_addr); br_fdb_changeaddr(p, dev->dev_addr);
br_ifinfo_notify(RTM_NEWLINK, p); br_ifinfo_notify(RTM_NEWLINK, p);
br_stp_recalculate_bridge_id(br); br_stp_recalculate_bridge_id(br);
spin_unlock_bh(&br->lock);
break; break;
case NETDEV_CHANGE: case NETDEV_CHANGE:
if (br->dev->flags & IFF_UP) br_port_carrier_check(p);
if (schedule_delayed_work(&p->carrier_check,
BR_PORT_DEBOUNCE))
dev_hold(dev);
break; break;
case NETDEV_FEAT_CHANGE: case NETDEV_FEAT_CHANGE:
if (br->dev->flags & IFF_UP) spin_lock_bh(&br->lock);
if (netif_running(br->dev))
br_features_recompute(br); br_features_recompute(br);
spin_unlock_bh(&br->lock);
/* could do recursive feature change notification
* but who would care??
*/
break; break;
case NETDEV_DOWN: case NETDEV_DOWN:
spin_lock_bh(&br->lock);
if (br->dev->flags & IFF_UP) if (br->dev->flags & IFF_UP)
br_stp_disable_port(p); br_stp_disable_port(p);
spin_unlock_bh(&br->lock);
break; break;
case NETDEV_UP: case NETDEV_UP:
spin_lock_bh(&br->lock);
if (netif_carrier_ok(dev) && (br->dev->flags & IFF_UP)) if (netif_carrier_ok(dev) && (br->dev->flags & IFF_UP))
br_stp_enable_port(p); br_stp_enable_port(p);
spin_unlock_bh(&br->lock);
break; break;
case NETDEV_UNREGISTER: case NETDEV_UNREGISTER:
spin_unlock_bh(&br->lock);
br_del_if(br, dev); br_del_if(br, dev);
goto done; break;
} }
spin_unlock_bh(&br->lock);
done:
return NOTIFY_DONE; return NOTIFY_DONE;
} }
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#define _BR_PRIVATE_H #define _BR_PRIVATE_H
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/miscdevice.h>
#include <linux/if_bridge.h> #include <linux/if_bridge.h>
#define BR_HASH_BITS 8 #define BR_HASH_BITS 8
...@@ -27,8 +26,6 @@ ...@@ -27,8 +26,6 @@
#define BR_PORT_BITS 10 #define BR_PORT_BITS 10
#define BR_MAX_PORTS (1<<BR_PORT_BITS) #define BR_MAX_PORTS (1<<BR_PORT_BITS)
#define BR_PORT_DEBOUNCE (HZ/10)
#define BR_VERSION "2.2" #define BR_VERSION "2.2"
typedef struct bridge_id bridge_id; typedef struct bridge_id bridge_id;
...@@ -82,7 +79,6 @@ struct net_bridge_port ...@@ -82,7 +79,6 @@ struct net_bridge_port
struct timer_list hold_timer; struct timer_list hold_timer;
struct timer_list message_age_timer; struct timer_list message_age_timer;
struct kobject kobj; struct kobject kobj;
struct delayed_work carrier_check;
struct rcu_head rcu; struct rcu_head rcu;
}; };
...@@ -173,6 +169,7 @@ extern void br_flood_forward(struct net_bridge *br, ...@@ -173,6 +169,7 @@ extern void br_flood_forward(struct net_bridge *br,
int clone); int clone);
/* br_if.c */ /* 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_add_bridge(const char *name);
extern int br_del_bridge(const char *name); extern int br_del_bridge(const char *name);
extern void br_cleanup_bridges(void); extern void br_cleanup_bridges(void);
......
...@@ -442,7 +442,7 @@ config INET_DIAG ...@@ -442,7 +442,7 @@ config INET_DIAG
---help--- ---help---
Support for INET (TCP, DCCP, etc) socket monitoring interface used by Support for INET (TCP, DCCP, etc) socket monitoring interface used by
native Linux tools such as ss. ss is included in iproute2, currently 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. If unsure, say Y.
...@@ -550,7 +550,7 @@ config TCP_CONG_SCALABLE ...@@ -550,7 +550,7 @@ config TCP_CONG_SCALABLE
Scalable TCP is a sender-side only change to TCP which uses a Scalable TCP is a sender-side only change to TCP which uses a
MIMD congestion control algorithm which has some nice scaling MIMD congestion control algorithm which has some nice scaling
properties, though is known to have fairness issues. 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 config TCP_CONG_LP
tristate "TCP Low Priority" tristate "TCP Low Priority"
......
...@@ -1054,12 +1054,14 @@ static int inetdev_event(struct notifier_block *this, unsigned long event, ...@@ -1054,12 +1054,14 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
ASSERT_RTNL(); ASSERT_RTNL();
if (!in_dev) { if (!in_dev) {
if (event == NETDEV_REGISTER && dev == &loopback_dev) { if (event == NETDEV_REGISTER) {
in_dev = inetdev_init(dev); in_dev = inetdev_init(dev);
if (!in_dev) if (!in_dev)
panic("devinet: Failed to create loopback\n"); panic("devinet: Failed to create loopback\n");
in_dev->cnf.no_xfrm = 1; if (dev == &loopback_dev) {
in_dev->cnf.no_policy = 1; in_dev->cnf.no_xfrm = 1;
in_dev->cnf.no_policy = 1;
}
} }
goto out; goto out;
} }
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/mroute.h> #include <linux/mroute.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/random.h>
#include <net/ip.h> #include <net/ip.h>
#include <net/protocol.h> #include <net/protocol.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
...@@ -48,21 +49,6 @@ ...@@ -48,21 +49,6 @@
#define MULTIPATH_MAX_CANDIDATES 40 #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, static void random_select_route(const struct flowi *flp,
struct rtable *first, struct rtable *first,
struct rtable **rp) struct rtable **rp)
...@@ -84,7 +70,7 @@ static void random_select_route(const struct flowi *flp, ...@@ -84,7 +70,7 @@ static void random_select_route(const struct flowi *flp,
if (candidate_count > 1) { if (candidate_count > 1) {
unsigned char i = 0; unsigned char i = 0;
unsigned char candidate_no = (unsigned char) unsigned char candidate_no = (unsigned char)
random(candidate_count); (random32() % candidate_count);
/* find chosen candidate and adjust GC data for all candidates /* find chosen candidate and adjust GC data for all candidates
* to ensure they stay in cache * to ensure they stay in cache
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/mroute.h> #include <linux/mroute.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/random.h>
#include <net/ip.h> #include <net/ip.h>
#include <net/protocol.h> #include <net/protocol.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
...@@ -84,18 +85,6 @@ struct multipath_route { ...@@ -84,18 +85,6 @@ struct multipath_route {
/* state: primarily weight per route information */ /* state: primarily weight per route information */
static struct multipath_bucket state[MULTIPATH_STATE_SIZE]; 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, static unsigned char __multipath_lookup_weight(const struct flowi *fl,
const struct rtable *rt) const struct rtable *rt)
{ {
...@@ -193,7 +182,7 @@ static void wrandom_select_route(const struct flowi *flp, ...@@ -193,7 +182,7 @@ static void wrandom_select_route(const struct flowi *flp,
/* choose a weighted random candidate */ /* choose a weighted random candidate */
decision = first; decision = first;
selector = random(power); selector = random32() % power;
last_power = 0; last_power = 0;
/* select candidate, adjust GC data and cleanup local state */ /* select candidate, adjust GC data and cleanup local state */
......
...@@ -2266,12 +2266,12 @@ void tcp_free_md5sig_pool(void) ...@@ -2266,12 +2266,12 @@ void tcp_free_md5sig_pool(void)
{ {
struct tcp_md5sig_pool **pool = NULL; struct tcp_md5sig_pool **pool = NULL;
spin_lock(&tcp_md5sig_pool_lock); spin_lock_bh(&tcp_md5sig_pool_lock);
if (--tcp_md5sig_users == 0) { if (--tcp_md5sig_users == 0) {
pool = tcp_md5sig_pool; pool = tcp_md5sig_pool;
tcp_md5sig_pool = NULL; tcp_md5sig_pool = NULL;
} }
spin_unlock(&tcp_md5sig_pool_lock); spin_unlock_bh(&tcp_md5sig_pool_lock);
if (pool) if (pool)
__tcp_free_md5sig_pool(pool); __tcp_free_md5sig_pool(pool);
} }
...@@ -2314,36 +2314,36 @@ struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(void) ...@@ -2314,36 +2314,36 @@ struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(void)
int alloc = 0; int alloc = 0;
retry: retry:
spin_lock(&tcp_md5sig_pool_lock); spin_lock_bh(&tcp_md5sig_pool_lock);
pool = tcp_md5sig_pool; pool = tcp_md5sig_pool;
if (tcp_md5sig_users++ == 0) { if (tcp_md5sig_users++ == 0) {
alloc = 1; alloc = 1;
spin_unlock(&tcp_md5sig_pool_lock); spin_unlock_bh(&tcp_md5sig_pool_lock);
} else if (!pool) { } else if (!pool) {
tcp_md5sig_users--; tcp_md5sig_users--;
spin_unlock(&tcp_md5sig_pool_lock); spin_unlock_bh(&tcp_md5sig_pool_lock);
cpu_relax(); cpu_relax();
goto retry; goto retry;
} else } else
spin_unlock(&tcp_md5sig_pool_lock); spin_unlock_bh(&tcp_md5sig_pool_lock);
if (alloc) { if (alloc) {
/* we cannot hold spinlock here because this may sleep. */ /* we cannot hold spinlock here because this may sleep. */
struct tcp_md5sig_pool **p = __tcp_alloc_md5sig_pool(); struct tcp_md5sig_pool **p = __tcp_alloc_md5sig_pool();
spin_lock(&tcp_md5sig_pool_lock); spin_lock_bh(&tcp_md5sig_pool_lock);
if (!p) { if (!p) {
tcp_md5sig_users--; tcp_md5sig_users--;
spin_unlock(&tcp_md5sig_pool_lock); spin_unlock_bh(&tcp_md5sig_pool_lock);
return NULL; return NULL;
} }
pool = tcp_md5sig_pool; pool = tcp_md5sig_pool;
if (pool) { if (pool) {
/* oops, it has already been assigned. */ /* oops, it has already been assigned. */
spin_unlock(&tcp_md5sig_pool_lock); spin_unlock_bh(&tcp_md5sig_pool_lock);
__tcp_free_md5sig_pool(p); __tcp_free_md5sig_pool(p);
} else { } else {
tcp_md5sig_pool = pool = p; tcp_md5sig_pool = pool = p;
spin_unlock(&tcp_md5sig_pool_lock); spin_unlock_bh(&tcp_md5sig_pool_lock);
} }
} }
return pool; return pool;
...@@ -2354,11 +2354,11 @@ EXPORT_SYMBOL(tcp_alloc_md5sig_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 *__tcp_get_md5sig_pool(int cpu)
{ {
struct tcp_md5sig_pool **p; struct tcp_md5sig_pool **p;
spin_lock(&tcp_md5sig_pool_lock); spin_lock_bh(&tcp_md5sig_pool_lock);
p = tcp_md5sig_pool; p = tcp_md5sig_pool;
if (p) if (p)
tcp_md5sig_users++; tcp_md5sig_users++;
spin_unlock(&tcp_md5sig_pool_lock); spin_unlock_bh(&tcp_md5sig_pool_lock);
return (p ? *per_cpu_ptr(p, cpu) : NULL); 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) ...@@ -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))) (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
goto out; goto out;
iph = skb->nh.iph;
if (iph->protocol == IPPROTO_IPIP) { if (iph->protocol == IPPROTO_IPIP) {
if (x->props.flags & XFRM_STATE_DECAP_DSCP) if (x->props.flags & XFRM_STATE_DECAP_DSCP)
ipv4_copy_dscp(iph, skb->h.ipiph); ipv4_copy_dscp(iph, skb->h.ipiph);
......
...@@ -291,7 +291,7 @@ static void xfrm4_dst_destroy(struct dst_entry *dst) ...@@ -291,7 +291,7 @@ static void xfrm4_dst_destroy(struct dst_entry *dst)
if (likely(xdst->u.rt.idev)) if (likely(xdst->u.rt.idev))
in_dev_put(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); inet_putpeer(xdst->u.rt.peer);
xfrm_dst_destroy(xdst); xfrm_dst_destroy(xdst);
} }
......
...@@ -32,6 +32,6 @@ obj-$(CONFIG_NETFILTER) += netfilter/ ...@@ -32,6 +32,6 @@ obj-$(CONFIG_NETFILTER) += netfilter/
obj-$(CONFIG_IPV6_SIT) += sit.o obj-$(CONFIG_IPV6_SIT) += sit.o
obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.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 obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o
...@@ -211,74 +211,6 @@ const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; ...@@ -211,74 +211,6 @@ const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
#endif #endif
const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; 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) static void addrconf_del_timer(struct inet6_ifaddr *ifp)
{ {
if (del_timer(&ifp->timer)) if (del_timer(&ifp->timer))
...@@ -1910,6 +1842,7 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, ...@@ -1910,6 +1842,7 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
struct inet6_dev *idev; struct inet6_dev *idev;
struct net_device *dev; struct net_device *dev;
int scope; int scope;
u32 flags = RTF_EXPIRES;
ASSERT_RTNL(); ASSERT_RTNL();
...@@ -1925,9 +1858,10 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, ...@@ -1925,9 +1858,10 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
scope = ipv6_addr_scope(pfx); scope = ipv6_addr_scope(pfx);
if (valid_lft == INFINITY_LIFE_TIME) if (valid_lft == INFINITY_LIFE_TIME) {
ifa_flags |= IFA_F_PERMANENT; ifa_flags |= IFA_F_PERMANENT;
else if (valid_lft >= 0x7FFFFFFF/HZ) flags = 0;
} else if (valid_lft >= 0x7FFFFFFF/HZ)
valid_lft = 0x7FFFFFFF/HZ; valid_lft = 0x7FFFFFFF/HZ;
if (prefered_lft == 0) if (prefered_lft == 0)
...@@ -1945,6 +1879,8 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, ...@@ -1945,6 +1879,8 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
ifp->tstamp = jiffies; ifp->tstamp = jiffies;
spin_unlock_bh(&ifp->lock); 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); addrconf_dad_start(ifp, 0);
in6_ifa_put(ifp); in6_ifa_put(ifp);
addrconf_verify(0); addrconf_verify(0);
...@@ -2124,6 +2060,7 @@ static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr ...@@ -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); ifp = ipv6_add_addr(idev, addr, 64, IFA_LINK, IFA_F_PERMANENT);
if (!IS_ERR(ifp)) { if (!IS_ERR(ifp)) {
addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0);
addrconf_dad_start(ifp, 0); addrconf_dad_start(ifp, 0);
in6_ifa_put(ifp); in6_ifa_put(ifp);
} }
...@@ -2240,6 +2177,14 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, ...@@ -2240,6 +2177,14 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
int run_pending = 0; int run_pending = 0;
switch(event) { 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_UP:
case NETDEV_CHANGE: case NETDEV_CHANGE:
if (event == NETDEV_UP) { if (event == NETDEV_UP) {
...@@ -2538,10 +2483,6 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) ...@@ -2538,10 +2483,6 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
addrconf_join_solict(dev, &ifp->addr); 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]); net_srandom(ifp->addr.s6_addr32[3]);
read_lock_bh(&idev->lock); read_lock_bh(&idev->lock);
...@@ -2972,12 +2913,15 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -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, static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
u32 prefered_lft, u32 valid_lft) u32 prefered_lft, u32 valid_lft)
{ {
u32 flags = RTF_EXPIRES;
if (!valid_lft || (prefered_lft > valid_lft)) if (!valid_lft || (prefered_lft > valid_lft))
return -EINVAL; return -EINVAL;
if (valid_lft == INFINITY_LIFE_TIME) if (valid_lft == INFINITY_LIFE_TIME) {
ifa_flags |= IFA_F_PERMANENT; ifa_flags |= IFA_F_PERMANENT;
else if (valid_lft >= 0x7FFFFFFF/HZ) flags = 0;
} else if (valid_lft >= 0x7FFFFFFF/HZ)
valid_lft = 0x7FFFFFFF/HZ; valid_lft = 0x7FFFFFFF/HZ;
if (prefered_lft == 0) if (prefered_lft == 0)
...@@ -2996,6 +2940,8 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags, ...@@ -2996,6 +2940,8 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
if (!(ifp->flags&IFA_F_TENTATIVE)) if (!(ifp->flags&IFA_F_TENTATIVE))
ipv6_ifa_notify(0, ifp); 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); addrconf_verify(0);
return 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) ...@@ -929,25 +929,28 @@ static void __exit inet6_exit(void)
{ {
/* First of all disallow new sockets creation. */ /* First of all disallow new sockets creation. */
sock_unregister(PF_INET6); 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 #ifdef CONFIG_PROC_FS
/* Cleanup code parts. */
if6_proc_exit(); if6_proc_exit();
ac6_proc_exit(); ac6_proc_exit();
ipv6_misc_proc_exit(); ipv6_misc_proc_exit();
udp6_proc_exit();
udplite6_proc_exit(); udplite6_proc_exit();
udp6_proc_exit();
tcp6_proc_exit(); tcp6_proc_exit();
raw6_proc_exit(); raw6_proc_exit();
#endif #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(); ipv6_netfilter_fini();
igmp6_cleanup();
ndisc_cleanup(); ndisc_cleanup();
icmpv6_cleanup(); icmpv6_cleanup();
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
...@@ -955,6 +958,7 @@ static void __exit inet6_exit(void) ...@@ -955,6 +958,7 @@ static void __exit inet6_exit(void)
#endif #endif
cleanup_ipv6_mibs(); cleanup_ipv6_mibs();
proto_unregister(&rawv6_prot); proto_unregister(&rawv6_prot);
proto_unregister(&udplitev6_prot);
proto_unregister(&udpv6_prot); proto_unregister(&udpv6_prot);
proto_unregister(&tcpv6_prot); proto_unregister(&tcpv6_prot);
} }
......
...@@ -727,11 +727,8 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -727,11 +727,8 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
} }
if (mtu < IPV6_MIN_MTU) if (mtu < IPV6_MIN_MTU)
mtu = IPV6_MIN_MTU; mtu = IPV6_MIN_MTU;
if (skb->dst && mtu < dst_mtu(skb->dst)) { if (skb->dst)
struct rt6_info *rt = (struct rt6_info *) skb->dst; skb->dst->ops->update_pmtu(skb->dst, mtu);
rt->rt6i_flags |= RTF_MODIFIED;
rt->u.dst.metrics[RTAX_MTU-1] = mtu;
}
if (skb->len > mtu) { if (skb->len > mtu) {
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev); icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev);
goto tx_err_dst_release; goto tx_err_dst_release;
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#include <net/ip6_route.h> #include <net/ip6_route.h>
#include <net/xfrm.h> #include <net/xfrm.h>
EXPORT_SYMBOL(__ipv6_addr_type);
EXPORT_SYMBOL(icmpv6_send); EXPORT_SYMBOL(icmpv6_send);
EXPORT_SYMBOL(icmpv6_statistics); EXPORT_SYMBOL(icmpv6_statistics);
EXPORT_SYMBOL(icmpv6_err_convert); EXPORT_SYMBOL(icmpv6_err_convert);
......
...@@ -189,7 +189,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int ...@@ -189,7 +189,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
case AF_INET6: 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_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; break;
default: default:
BUG_ON(1); BUG_ON(1);
......
...@@ -42,19 +42,6 @@ ...@@ -42,19 +42,6 @@
#include <net/irda/irttp.h> /* irttp_init */ #include <net/irda/irttp.h> /* irttp_init */
#include <net/irda/irda_device.h> /* irda_device_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 * Module parameters
*/ */
......
...@@ -227,17 +227,14 @@ struct packet_skb_cb { ...@@ -227,17 +227,14 @@ struct packet_skb_cb {
#ifdef CONFIG_PACKET_MMAP #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; unsigned int pg_vec_pos, frame_offset;
char *frame;
pg_vec_pos = position / po->frames_per_block; pg_vec_pos = position / po->frames_per_block;
frame_offset = 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 (struct tpacket_hdr *)(po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size));
return frame;
} }
#endif #endif
...@@ -639,7 +636,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe ...@@ -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); 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) if (h->tp_status)
goto ring_is_full; goto ring_is_full;
...@@ -1473,7 +1470,7 @@ static int packet_notifier(struct notifier_block *this, unsigned long msg, void ...@@ -1473,7 +1470,7 @@ static int packet_notifier(struct notifier_block *this, unsigned long msg, void
{ {
struct sock *sk; struct sock *sk;
struct hlist_node *node; struct hlist_node *node;
struct net_device *dev = (struct net_device*)data; struct net_device *dev = data;
read_lock(&packet_sklist_lock); read_lock(&packet_sklist_lock);
sk_for_each(sk, node, &packet_sklist) { sk_for_each(sk, node, &packet_sklist) {
...@@ -1588,7 +1585,7 @@ static unsigned int packet_poll(struct file * file, struct socket *sock, ...@@ -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; unsigned last = po->head ? po->head-1 : po->frame_max;
struct tpacket_hdr *h; struct tpacket_hdr *h;
h = (struct tpacket_hdr *)packet_lookup_frame(po, last); h = packet_lookup_frame(po, last);
if (h->tp_status) if (h->tp_status)
mask |= POLLIN | POLLRDNORM; mask |= POLLIN | POLLRDNORM;
......
...@@ -396,6 +396,19 @@ void sctp_retransmit_mark(struct sctp_outq *q, ...@@ -396,6 +396,19 @@ void sctp_retransmit_mark(struct sctp_outq *q,
if (sctp_chunk_abandoned(chunk)) { if (sctp_chunk_abandoned(chunk)) {
list_del_init(lchunk); list_del_init(lchunk);
sctp_insert_list(&q->abandoned, 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; continue;
} }
...@@ -1244,6 +1257,15 @@ static void sctp_check_transmitted(struct sctp_outq *q, ...@@ -1244,6 +1257,15 @@ static void sctp_check_transmitted(struct sctp_outq *q,
if (sctp_chunk_abandoned(tchunk)) { if (sctp_chunk_abandoned(tchunk)) {
/* Move the chunk to abandoned list. */ /* Move the chunk to abandoned list. */
sctp_insert_list(&q->abandoned, lchunk); 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; continue;
} }
...@@ -1695,11 +1717,6 @@ static void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 ctsn) ...@@ -1695,11 +1717,6 @@ static void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 ctsn)
*/ */
if (TSN_lte(tsn, ctsn)) { if (TSN_lte(tsn, ctsn)) {
list_del_init(lchunk); 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); sctp_chunk_free(chunk);
} else { } else {
if (TSN_lte(tsn, asoc->adv_peer_ack_point+1)) { 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, ...@@ -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). * 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). */ /* Do some failure management (Section 8.2). */
sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, SCTP_TRANSPORT(transport)); 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; 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