From 9219b2a08c8a1ca9935b85ec4ab119bb55b0cb15 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Mon, 2 Jan 2012 20:08:04 -0200 Subject: Bluetooth: Fix bacpy in l2cap_core.c It should be the dst in the copy not src. 03a001948 introduced this bug. Reported-by: Vinicius Costa Gomes Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index cd7bb3d..d66aea8 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1190,7 +1190,7 @@ inline int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdad } /* Set destination address and psm */ - bacpy(&bt_sk(sk)->dst, src); + bacpy(&bt_sk(sk)->dst, dst); chan->psm = psm; chan->dcid = cid; -- cgit v0.10.2 From 95ca83f42fb5f5bf789b514635f79242afe555d1 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 27 Dec 2011 15:28:44 -0200 Subject: Bluetooth: Fix context in rfcomm_sock_lock Code now run in process context, does not need to disable interrupt anymore. Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index aea2bdd..f066678 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -370,7 +370,7 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr goto done; } - write_lock_bh(&rfcomm_sk_list.lock); + write_lock(&rfcomm_sk_list.lock); if (sa->rc_channel && __rfcomm_get_sock_by_addr(sa->rc_channel, &sa->rc_bdaddr)) { err = -EADDRINUSE; @@ -381,7 +381,7 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr sk->sk_state = BT_BOUND; } - write_unlock_bh(&rfcomm_sk_list.lock); + write_unlock(&rfcomm_sk_list.lock); done: release_sock(sk); @@ -455,7 +455,7 @@ static int rfcomm_sock_listen(struct socket *sock, int backlog) err = -EINVAL; - write_lock_bh(&rfcomm_sk_list.lock); + write_lock(&rfcomm_sk_list.lock); for (channel = 1; channel < 31; channel++) if (!__rfcomm_get_sock_by_addr(channel, src)) { @@ -464,7 +464,7 @@ static int rfcomm_sock_listen(struct socket *sock, int backlog) break; } - write_unlock_bh(&rfcomm_sk_list.lock); + write_unlock(&rfcomm_sk_list.lock); if (err < 0) goto done; @@ -982,7 +982,7 @@ static int rfcomm_sock_debugfs_show(struct seq_file *f, void *p) struct sock *sk; struct hlist_node *node; - read_lock_bh(&rfcomm_sk_list.lock); + read_lock(&rfcomm_sk_list.lock); sk_for_each(sk, node, &rfcomm_sk_list.head) { seq_printf(f, "%s %s %d %d\n", @@ -991,7 +991,7 @@ static int rfcomm_sock_debugfs_show(struct seq_file *f, void *p) sk->sk_state, rfcomm_pi(sk)->channel); } - read_unlock_bh(&rfcomm_sk_list.lock); + read_unlock(&rfcomm_sk_list.lock); return 0; } -- cgit v0.10.2 From 393432cd8dc02b88a00decd495913643aa5ff705 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 27 Dec 2011 15:28:45 -0200 Subject: Bluetooth: Fix context in RFCOMM tty We now run in process context, no need to disable interrupts. Calls from the tty layer also run in process context. rw_lock was converted to spinlock, we have more writers than readers in this case. Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index fa8f4de5..a2d4f51 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -76,7 +76,7 @@ struct rfcomm_dev { }; static LIST_HEAD(rfcomm_dev_list); -static DEFINE_RWLOCK(rfcomm_dev_lock); +static DEFINE_SPINLOCK(rfcomm_dev_lock); static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb); static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err); @@ -146,7 +146,7 @@ static inline struct rfcomm_dev *rfcomm_dev_get(int id) { struct rfcomm_dev *dev; - read_lock(&rfcomm_dev_lock); + spin_lock(&rfcomm_dev_lock); dev = __rfcomm_dev_get(id); @@ -157,7 +157,7 @@ static inline struct rfcomm_dev *rfcomm_dev_get(int id) rfcomm_dev_hold(dev); } - read_unlock(&rfcomm_dev_lock); + spin_unlock(&rfcomm_dev_lock); return dev; } @@ -205,7 +205,7 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) if (!dev) return -ENOMEM; - write_lock_bh(&rfcomm_dev_lock); + spin_lock(&rfcomm_dev_lock); if (req->dev_id < 0) { dev->id = 0; @@ -290,7 +290,7 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) __module_get(THIS_MODULE); out: - write_unlock_bh(&rfcomm_dev_lock); + spin_unlock(&rfcomm_dev_lock); if (err < 0) goto free; @@ -327,9 +327,9 @@ static void rfcomm_dev_del(struct rfcomm_dev *dev) if (atomic_read(&dev->opened) > 0) return; - write_lock_bh(&rfcomm_dev_lock); + spin_lock(&rfcomm_dev_lock); list_del_init(&dev->list); - write_unlock_bh(&rfcomm_dev_lock); + spin_unlock(&rfcomm_dev_lock); rfcomm_dev_put(dev); } @@ -473,7 +473,7 @@ static int rfcomm_get_dev_list(void __user *arg) di = dl->dev_info; - read_lock_bh(&rfcomm_dev_lock); + spin_lock(&rfcomm_dev_lock); list_for_each_entry(dev, &rfcomm_dev_list, list) { if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) @@ -488,7 +488,7 @@ static int rfcomm_get_dev_list(void __user *arg) break; } - read_unlock_bh(&rfcomm_dev_lock); + spin_unlock(&rfcomm_dev_lock); dl->dev_num = n; size = sizeof(*dl) + n * sizeof(*di); @@ -766,9 +766,9 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp) rfcomm_dlc_unlock(dev->dlc); if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) { - write_lock_bh(&rfcomm_dev_lock); + spin_lock(&rfcomm_dev_lock); list_del_init(&dev->list); - write_unlock_bh(&rfcomm_dev_lock); + spin_unlock(&rfcomm_dev_lock); rfcomm_dev_put(dev); } -- cgit v0.10.2 From ee65d19e25c7ace7792bcd289776b2e24f4bf059 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 27 Dec 2011 15:28:46 -0200 Subject: Bluetooth: Remove *_bh locks from SCO Those locks are not shared between interrupt and process context anymore, so remove the part that disable interrupts. We are still safe because preemption is disabled. Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 0d59e61..471283e 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -482,7 +482,7 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le goto done; } - write_lock_bh(&sco_sk_list.lock); + write_lock(&sco_sk_list.lock); if (bacmp(src, BDADDR_ANY) && __sco_get_sock_by_addr(src)) { err = -EADDRINUSE; @@ -492,7 +492,7 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le sk->sk_state = BT_BOUND; } - write_unlock_bh(&sco_sk_list.lock); + write_unlock(&sco_sk_list.lock); done: release_sock(sk); @@ -965,14 +965,14 @@ static int sco_debugfs_show(struct seq_file *f, void *p) struct sock *sk; struct hlist_node *node; - read_lock_bh(&sco_sk_list.lock); + read_lock(&sco_sk_list.lock); sk_for_each(sk, node, &sco_sk_list.head) { seq_printf(f, "%s %s %d\n", batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), sk->sk_state); } - read_unlock_bh(&sco_sk_list.lock); + read_unlock(&sco_sk_list.lock); return 0; } -- cgit v0.10.2 From 4b5dd696f81b210c1511ca7a969525126266c933 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 27 Dec 2011 15:28:47 -0200 Subject: Bluetooth: Remove local_bh_disable() from hci_sock.c Everything is in process context now, we do not need such a call. Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 189a667..896a72f 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -767,7 +767,6 @@ static int hci_sock_dev_event(struct notifier_block *this, unsigned long event, /* Detach sockets from device */ read_lock(&hci_sk_list.lock); sk_for_each(sk, node, &hci_sk_list.head) { - local_bh_disable(); bh_lock_sock_nested(sk); if (hci_pi(sk)->hdev == hdev) { hci_pi(sk)->hdev = NULL; @@ -778,7 +777,6 @@ static int hci_sock_dev_event(struct notifier_block *this, unsigned long event, hci_dev_put(hdev); } bh_unlock_sock(sk); - local_bh_enable(); } read_unlock(&hci_sk_list.lock); } -- cgit v0.10.2 From 94f5bfb8c1641080c3c4325714b8fe7d2839a906 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 27 Dec 2011 15:28:48 -0200 Subject: Bluetooth: Remove *_bh from socket list lock. We don't need it anymore. Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index cdcfcab..ef92864 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -156,17 +156,17 @@ static int bt_sock_create(struct net *net, struct socket *sock, int proto, void bt_sock_link(struct bt_sock_list *l, struct sock *sk) { - write_lock_bh(&l->lock); + write_lock(&l->lock); sk_add_node(sk, &l->head); - write_unlock_bh(&l->lock); + write_unlock(&l->lock); } EXPORT_SYMBOL(bt_sock_link); void bt_sock_unlink(struct bt_sock_list *l, struct sock *sk) { - write_lock_bh(&l->lock); + write_lock(&l->lock); sk_del_node_init(sk); - write_unlock_bh(&l->lock); + write_unlock(&l->lock); } EXPORT_SYMBOL(bt_sock_unlink); -- cgit v0.10.2 From 59e294065ddee7074af91e4f5e12e6095eb1135b Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Fri, 30 Dec 2011 10:34:03 -0300 Subject: Bluetooth: Rename extfeatures This patch renames hdev->extfeatures to hdev->host_features since it holds the extended features Page 1 (aka host features). Signed-off-by: Andre Guedes Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 5e2e984..ea9231f 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -127,7 +127,7 @@ struct hci_dev { __u8 major_class; __u8 minor_class; __u8 features[8]; - __u8 extfeatures[8]; + __u8 host_features[8]; __u8 commands[64]; __u8 ssp_mode; __u8 hci_ver; @@ -676,7 +676,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn); #define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE) /* ----- Extended LMP capabilities ----- */ -#define lmp_host_le_capable(dev) ((dev)->extfeatures[0] & LMP_HOST_LE) +#define lmp_host_le_capable(dev) ((dev)->host_features[0] & LMP_HOST_LE) /* ----- HCI protocols ----- */ static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 919e3c0..37c31c5 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -711,7 +711,7 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev, if (rp->status) return; - memcpy(hdev->extfeatures, rp->features, 8); + memcpy(hdev->host_features, rp->features, 8); hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); } diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 2540944..38ec8ca 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -291,7 +291,7 @@ static u32 get_current_settings(struct hci_dev *hdev) if (!(hdev->features[4] & LMP_NO_BREDR)) settings |= MGMT_SETTING_BREDR; - if (hdev->extfeatures[0] & LMP_HOST_LE) + if (hdev->host_features[0] & LMP_HOST_LE) settings |= MGMT_SETTING_LE; if (test_bit(HCI_AUTH, &hdev->flags)) -- cgit v0.10.2 From b5b32b653dedb29eb95e57cbbaefc4abf7141cb2 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Fri, 30 Dec 2011 10:34:04 -0300 Subject: Bluetooth: Fix hci_cc_read_local_ext_features() Copy the Features value according to the Page number. Signed-off-by: Andre Guedes Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 37c31c5..10152d2 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -711,7 +711,14 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev, if (rp->status) return; - memcpy(hdev->host_features, rp->features, 8); + switch (rp->page) { + case 0: + memcpy(hdev->features, rp->features, 8); + break; + case 1: + memcpy(hdev->host_features, rp->features, 8); + break; + } hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); } -- cgit v0.10.2 From c1b9b4f45f014093231c568be9b5c2e392943696 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Mon, 2 Jan 2012 19:18:10 -0300 Subject: Bluetooth: Fix adv_work delay This patch fixes the adv_work delay. It should be set to ADV_ CLEAR_TIMEOUT instead of (jiffies + ADV_CLEAR_TIMEOUT) since queue_delayed_work() receives the number of jiffies to wait before queueing. It also removes the unnecessary cancel_delayed_ work_sync() call in case LE scan has been disabled. Signed-off-by: Andre Guedes Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 10152d2..444ca41 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1054,9 +1054,8 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, case LE_SCANNING_DISABLED: clear_bit(HCI_LE_SCAN, &hdev->dev_flags); - cancel_delayed_work_sync(&hdev->adv_work); queue_delayed_work(hdev->workqueue, &hdev->adv_work, - jiffies + ADV_CLEAR_TIMEOUT); + ADV_CLEAR_TIMEOUT); break; default: -- cgit v0.10.2 From d084329e2862922bbc9a2de04a5c8e7219bfceb9 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Mon, 2 Jan 2012 19:18:11 -0300 Subject: Bluetooth: Queue adv_work on system workqueue This patch queues hdev->adv_work on the system-wide workqueue instead of on hdev->workqueue. This way we keep only tx/rx works on hdev->workqueue. Signed-off-by: Andre Guedes Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 444ca41..08c0b42 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1054,8 +1054,7 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, case LE_SCANNING_DISABLED: clear_bit(HCI_LE_SCAN, &hdev->dev_flags); - queue_delayed_work(hdev->workqueue, &hdev->adv_work, - ADV_CLEAR_TIMEOUT); + schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT); break; default: -- cgit v0.10.2 From e75a8b0c332875b2a2d22acdc331fc2b83788cac Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Mon, 2 Jan 2012 16:50:53 -0300 Subject: Bluetooth: Fix mgmt_stop_discovery_failed() Stop Discovery Command Status Event should use mgmt status code. Signed-off-by: Andre Guedes Acked-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 38ec8ca..bc8e59d 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2756,7 +2756,7 @@ int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status) if (!cmd) return -ENOENT; - err = cmd_status(cmd->sk, hdev->id, cmd->opcode, status); + err = cmd_status(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status)); mgmt_pending_remove(cmd); return err; -- cgit v0.10.2 From 333055f2aaabadb951b5ecd90f6a20a9aee38c29 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Thu, 22 Dec 2011 15:14:39 -0200 Subject: Bluetooth: Don't use *_bh locks anymore Those locks are not shared between interrupt and process context anymore, so remove the part that disable interrupts. We are still safe because preemption is disabled. Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index d66aea8..3ee9bde 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -165,7 +165,7 @@ int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) { int err; - write_lock_bh(&chan_list_lock); + write_lock(&chan_list_lock); if (psm && __l2cap_global_chan_by_addr(psm, src)) { err = -EADDRINUSE; @@ -190,17 +190,17 @@ int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) } done: - write_unlock_bh(&chan_list_lock); + write_unlock(&chan_list_lock); return err; } int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) { - write_lock_bh(&chan_list_lock); + write_lock(&chan_list_lock); chan->scid = scid; - write_unlock_bh(&chan_list_lock); + write_unlock(&chan_list_lock); return 0; } @@ -289,9 +289,9 @@ struct l2cap_chan *l2cap_chan_create(struct sock *sk) chan->sk = sk; - write_lock_bh(&chan_list_lock); + write_lock(&chan_list_lock); list_add(&chan->global_l, &chan_list); - write_unlock_bh(&chan_list_lock); + write_unlock(&chan_list_lock); INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout); @@ -306,9 +306,9 @@ struct l2cap_chan *l2cap_chan_create(struct sock *sk) void l2cap_chan_destroy(struct l2cap_chan *chan) { - write_lock_bh(&chan_list_lock); + write_lock(&chan_list_lock); list_del(&chan->global_l); - write_unlock_bh(&chan_list_lock); + write_unlock(&chan_list_lock); l2cap_chan_put(chan); } @@ -543,14 +543,14 @@ static u8 l2cap_get_ident(struct l2cap_conn *conn) * 200 - 254 are used by utilities like l2ping, etc. */ - spin_lock_bh(&conn->lock); + spin_lock(&conn->lock); if (++conn->tx_ident > 128) conn->tx_ident = 1; id = conn->tx_ident; - spin_unlock_bh(&conn->lock); + spin_unlock(&conn->lock); return id; } @@ -4702,7 +4702,7 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p) { struct l2cap_chan *c; - read_lock_bh(&chan_list_lock); + read_lock(&chan_list_lock); list_for_each_entry(c, &chan_list, global_l) { struct sock *sk = c->sk; @@ -4715,7 +4715,7 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p) c->sec_level, c->mode); } - read_unlock_bh(&chan_list_lock); + read_unlock(&chan_list_lock); return 0; } -- cgit v0.10.2 From 3542b854bc26e5f8e42e0eab4d7f7453b74a362d Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 28 Dec 2011 13:54:17 -0200 Subject: Bluetooth: Keep chan->state and sk->sk_state in sync Those vars need to be in sync, otherwise l2cap_core.c can get the wrong state. Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 9ca5616..c61d967 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -587,6 +587,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch if (smp_conn_security(conn, sec.level)) break; sk->sk_state = BT_CONFIG; + chan->state = BT_CONFIG; /* or for ACL link, under defer_setup time */ } else if (sk->sk_state == BT_CONNECT2 && @@ -731,6 +732,7 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) { sk->sk_state = BT_CONFIG; + pi->chan->state = BT_CONFIG; __l2cap_connect_rsp_defer(pi->chan); release_sock(sk); -- cgit v0.10.2 From c5993de864d96b3656e9fca38c377b130105d97a Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Fri, 30 Dec 2011 12:07:47 +0200 Subject: Bluetooth: Correct packet len calculation Remove unneeded skb_pull and correct packet length calculation removing magic number. Move BT_DBG after len check otherwise it could possibly access wrong memory. Signed-off-by: Andrei Emeltchenko Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 08c0b42..d37f5b2 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2271,20 +2271,19 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s struct hci_ev_num_comp_pkts *ev = (void *) skb->data; int i; - skb_pull(skb, sizeof(*ev)); - - BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); - if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); return; } - if (skb->len < ev->num_hndl * 4) { + if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + + ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { BT_DBG("%s bad parameters", hdev->name); return; } + BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); + for (i = 0; i < ev->num_hndl; i++) { struct hci_comp_pkts_info *info = &ev->handles[i]; struct hci_conn *conn; -- cgit v0.10.2 From 269f3114b53a3ce93eb5977852ac2624a380f600 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Fri, 30 Dec 2011 14:43:54 +0100 Subject: via-rhine: factor out tx_thresh handling Signed-off-by: Francois Romieu diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c index 5c4983b..93987e8 100644 --- a/drivers/net/ethernet/via/via-rhine.c +++ b/drivers/net/ethernet/via/via-rhine.c @@ -657,6 +657,16 @@ static void rhine_poll(struct net_device *dev) } #endif +static void rhine_kick_tx_threshold(struct rhine_private *rp) +{ + if (rp->tx_thresh < 0xe0) { + void __iomem *ioaddr = rp->base; + + rp->tx_thresh += 0x20; + BYTE_REG_BITS_SET(rp->tx_thresh, 0x80, ioaddr + TxConfig); + } +} + static int rhine_napipoll(struct napi_struct *napi, int budget) { struct rhine_private *rp = container_of(napi, struct rhine_private, napi); @@ -1910,8 +1920,7 @@ static void rhine_error(struct net_device *dev, int intr_status) intr_status); } if (intr_status & IntrTxUnderrun) { - if (rp->tx_thresh < 0xE0) - BYTE_REG_BITS_SET((rp->tx_thresh += 0x20), 0x80, ioaddr + TxConfig); + rhine_kick_tx_threshold(rp); if (debug > 1) netdev_info(dev, "Transmitter underrun, Tx threshold now %02x\n", rp->tx_thresh); @@ -1923,9 +1932,7 @@ static void rhine_error(struct net_device *dev, int intr_status) if ((intr_status & IntrTxError) && (intr_status & (IntrTxAborted | IntrTxUnderrun | IntrTxDescRace)) == 0) { - if (rp->tx_thresh < 0xE0) { - BYTE_REG_BITS_SET((rp->tx_thresh += 0x20), 0x80, ioaddr + TxConfig); - } + rhine_kick_tx_threshold(rp); if (debug > 1) netdev_info(dev, "Unspecified error. Tx threshold now %02x\n", rp->tx_thresh); -- cgit v0.10.2 From a20a28bc321fefcc23f8da7ce3722e6ae7a7199d Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Fri, 30 Dec 2011 14:53:58 +0100 Subject: via-rhine: balance interrupt acknowledge and events retrieval. Signed-off-by: Francois Romieu diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c index 93987e8..716fd42 100644 --- a/drivers/net/ethernet/via/via-rhine.c +++ b/drivers/net/ethernet/via/via-rhine.c @@ -508,9 +508,8 @@ do { \ 1024 - i, __func__, __LINE__); \ } while (0) -static inline u32 get_intr_status(struct net_device *dev) +static u32 rhine_get_events(struct rhine_private *rp) { - struct rhine_private *rp = netdev_priv(dev); void __iomem *ioaddr = rp->base; u32 intr_status; @@ -521,6 +520,16 @@ static inline u32 get_intr_status(struct net_device *dev) return intr_status; } +static void rhine_ack_events(struct rhine_private *rp, u32 mask) +{ + void __iomem *ioaddr = rp->base; + + if (rp->quirks & rqStatusWBRace) + iowrite8(mask >> 16, ioaddr + IntrStatus2); + iowrite16(mask, ioaddr + IntrStatus); + IOSYNC; +} + /* * Get power related registers into sane state. * Notify user about past WOL event. @@ -1580,14 +1589,11 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance) int boguscnt = max_interrupt_work; int handled = 0; - while ((intr_status = get_intr_status(dev))) { + while ((intr_status = rhine_get_events(rp))) { handled = 1; /* Acknowledge all of the current interrupt sources ASAP. */ - if (intr_status & IntrTxDescRace) - iowrite8(0x08, ioaddr + IntrStatus2); - iowrite16(intr_status & 0xffff, ioaddr + IntrStatus); - IOSYNC; + rhine_ack_events(rp, intr_status); if (debug > 4) netdev_dbg(dev, "Interrupt, status %08x\n", @@ -1872,7 +1878,7 @@ static void rhine_restart_tx(struct net_device *dev) { * If new errors occurred, we need to sort them out before doing Tx. * In that case the ISR will be back here RSN anyway. */ - intr_status = get_intr_status(dev); + intr_status = rhine_get_events(rp); if ((intr_status & IntrTxErrSummary) == 0) { -- cgit v0.10.2 From a5abec1e84c3d9cd197667e5fa94f25c21a2cb8e Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Fri, 6 Jan 2012 21:03:59 +0100 Subject: via-rhine: remove useless forward declarations. Signed-off-by: Francois Romieu diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c index 716fd42..d17ca32 100644 --- a/drivers/net/ethernet/via/via-rhine.c +++ b/drivers/net/ethernet/via/via-rhine.c @@ -488,15 +488,8 @@ static struct net_device_stats *rhine_get_stats(struct net_device *dev); static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static const struct ethtool_ops netdev_ethtool_ops; static int rhine_close(struct net_device *dev); -static void rhine_shutdown (struct pci_dev *pdev); static int rhine_vlan_rx_add_vid(struct net_device *dev, unsigned short vid); static int rhine_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid); -static void rhine_set_cam(void __iomem *ioaddr, int idx, u8 *addr); -static void rhine_set_vlan_cam(void __iomem *ioaddr, int idx, u8 *addr); -static void rhine_set_cam_mask(void __iomem *ioaddr, u32 mask); -static void rhine_set_vlan_cam_mask(void __iomem *ioaddr, u32 mask); -static void rhine_init_cam_filter(struct net_device *dev); -static void rhine_update_vcam(struct net_device *dev); #define RHINE_WAIT_FOR(condition) \ do { \ -- cgit v0.10.2 From 7ab87ff4c770eed71e3777936299292739fcd0fe Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Fri, 6 Jan 2012 21:42:26 +0100 Subject: via-rhine: move work from irq handler to softirq and beyond. - Tx processing is moved from the irq handler to NAPI poll - link events and obscure event processing is moved to its proper work queue Locking rules undergo some changes through the driver. - the driver offers the usual lock-free Tx path - besides the IRQ handler, the link event task schedules the napi handler. The driver thus adds some internal locking to prevent a loop when both must be disabled. - the reset task keeps being scheduled from the Tx watchdog handler, thus with implicit Tx queue disabling. It does not need to care about irq, only napi softirq and competing task. - it is not worth to add a dedicated lock between {g, s}et_wol and rhine_shutdown. It should not hurt no narrow it down a bit though. - rhine_reset_task must keep its huge spin_lock_bh protected section due to : - races for the CAM registers (see rhine_vlan_rx_{add, kill}_vid) - implicit use of napi_enable (see init_registers) - use of the same lock for stats read / update exclusion between napi rx processing and rhine_get_stats - rhine_resume requires a softirq disabled section for the same reason as rhine_reset_task - {free, request}_irq have been replaced with IntrEnable actions in rhine_{suspend, resume}. It is hidden behind init_registers for the latter. Signed-off-by: Francois Romieu diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c index d17ca32..9a7bacc 100644 --- a/drivers/net/ethernet/via/via-rhine.c +++ b/drivers/net/ethernet/via/via-rhine.c @@ -42,7 +42,6 @@ #define DEBUG static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ -static int max_interrupt_work = 20; /* Set the copy breakpoint for the copy-only-tiny-frames scheme. Setting to > 1518 effectively disables this feature. */ @@ -128,11 +127,9 @@ MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("VIA Rhine PCI Fast Ethernet driver"); MODULE_LICENSE("GPL"); -module_param(max_interrupt_work, int, 0); module_param(debug, int, 0); module_param(rx_copybreak, int, 0); module_param(avoid_D3, bool, 0); -MODULE_PARM_DESC(max_interrupt_work, "VIA Rhine maximum events handled per interrupt"); MODULE_PARM_DESC(debug, "VIA Rhine debug level (0-7)"); MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames"); MODULE_PARM_DESC(avoid_D3, "Avoid power state D3 (work-around for broken BIOSes)"); @@ -351,16 +348,25 @@ static const int mmio_verify_registers[] = { /* Bits in the interrupt status/mask registers. */ enum intr_status_bits { - IntrRxDone=0x0001, IntrRxErr=0x0004, IntrRxEmpty=0x0020, - IntrTxDone=0x0002, IntrTxError=0x0008, IntrTxUnderrun=0x0210, - IntrPCIErr=0x0040, - IntrStatsMax=0x0080, IntrRxEarly=0x0100, - IntrRxOverflow=0x0400, IntrRxDropped=0x0800, IntrRxNoBuf=0x1000, - IntrTxAborted=0x2000, IntrLinkChange=0x4000, - IntrRxWakeUp=0x8000, - IntrNormalSummary=0x0003, IntrAbnormalSummary=0xC260, - IntrTxDescRace=0x080000, /* mapped from IntrStatus2 */ - IntrTxErrSummary=0x082218, + IntrRxDone = 0x0001, + IntrTxDone = 0x0002, + IntrRxErr = 0x0004, + IntrTxError = 0x0008, + IntrRxEmpty = 0x0020, + IntrPCIErr = 0x0040, + IntrStatsMax = 0x0080, + IntrRxEarly = 0x0100, + IntrTxUnderrun = 0x0210, + IntrRxOverflow = 0x0400, + IntrRxDropped = 0x0800, + IntrRxNoBuf = 0x1000, + IntrTxAborted = 0x2000, + IntrLinkChange = 0x4000, + IntrRxWakeUp = 0x8000, + IntrTxDescRace = 0x080000, /* mapped from IntrStatus2 */ + IntrNormalSummary = IntrRxDone | IntrTxDone, + IntrTxErrSummary = IntrTxDescRace | IntrTxAborted | IntrTxError | + IntrTxUnderrun, }; /* Bits in WOLcrSet/WOLcrClr and PwrcsrSet/PwrcsrClr */ @@ -439,6 +445,9 @@ struct rhine_private { struct net_device *dev; struct napi_struct napi; spinlock_t lock; + struct mutex task_lock; + bool task_enable; + struct work_struct slow_event_task; struct work_struct reset_task; /* Frequently used values: keep some adjacent for cache effect. */ @@ -476,13 +485,13 @@ static int mdio_read(struct net_device *dev, int phy_id, int location); static void mdio_write(struct net_device *dev, int phy_id, int location, int value); static int rhine_open(struct net_device *dev); static void rhine_reset_task(struct work_struct *work); +static void rhine_slow_event_task(struct work_struct *work); static void rhine_tx_timeout(struct net_device *dev); static netdev_tx_t rhine_start_tx(struct sk_buff *skb, struct net_device *dev); static irqreturn_t rhine_interrupt(int irq, void *dev_instance); static void rhine_tx(struct net_device *dev); static int rhine_rx(struct net_device *dev, int limit); -static void rhine_error(struct net_device *dev, int intr_status); static void rhine_set_rx_mode(struct net_device *dev); static struct net_device_stats *rhine_get_stats(struct net_device *dev); static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); @@ -490,6 +499,7 @@ static const struct ethtool_ops netdev_ethtool_ops; static int rhine_close(struct net_device *dev); static int rhine_vlan_rx_add_vid(struct net_device *dev, unsigned short vid); static int rhine_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid); +static void rhine_restart_tx(struct net_device *dev); #define RHINE_WAIT_FOR(condition) \ do { \ @@ -520,7 +530,7 @@ static void rhine_ack_events(struct rhine_private *rp, u32 mask) if (rp->quirks & rqStatusWBRace) iowrite8(mask >> 16, ioaddr + IntrStatus2); iowrite16(mask, ioaddr + IntrStatus); - IOSYNC; + mmiowb(); } /* @@ -669,23 +679,125 @@ static void rhine_kick_tx_threshold(struct rhine_private *rp) } } +static void rhine_tx_err(struct rhine_private *rp, u32 status) +{ + struct net_device *dev = rp->dev; + + if (status & IntrTxAborted) { + if (debug > 1) + netdev_info(dev, "Abort %08x, frame dropped\n", status); + } + + if (status & IntrTxUnderrun) { + rhine_kick_tx_threshold(rp); + if (debug > 1) + netdev_info(dev, "Transmitter underrun, Tx threshold now %02x\n", + rp->tx_thresh); + } + + if (status & IntrTxDescRace) { + if (debug > 2) + netdev_info(dev, "Tx descriptor write-back race\n"); + } + + if ((status & IntrTxError) && + (status & (IntrTxAborted | IntrTxUnderrun | IntrTxDescRace)) == 0) { + rhine_kick_tx_threshold(rp); + if (debug > 1) + netdev_info(dev, "Unspecified error. Tx threshold now %02x\n", + rp->tx_thresh); + } + + rhine_restart_tx(dev); +} + +static void rhine_update_rx_crc_and_missed_errord(struct rhine_private *rp) +{ + void __iomem *ioaddr = rp->base; + struct net_device_stats *stats = &rp->dev->stats; + + stats->rx_crc_errors += ioread16(ioaddr + RxCRCErrs); + stats->rx_missed_errors += ioread16(ioaddr + RxMissed); + + /* + * Clears the "tally counters" for CRC errors and missed frames(?). + * It has been reported that some chips need a write of 0 to clear + * these, for others the counters are set to 1 when written to and + * instead cleared when read. So we clear them both ways ... + */ + iowrite32(0, ioaddr + RxMissed); + ioread16(ioaddr + RxCRCErrs); + ioread16(ioaddr + RxMissed); +} + +#define RHINE_EVENT_NAPI_RX (IntrRxDone | \ + IntrRxErr | \ + IntrRxEmpty | \ + IntrRxOverflow | \ + IntrRxDropped | \ + IntrRxNoBuf | \ + IntrRxWakeUp) + +#define RHINE_EVENT_NAPI_TX_ERR (IntrTxError | \ + IntrTxAborted | \ + IntrTxUnderrun | \ + IntrTxDescRace) +#define RHINE_EVENT_NAPI_TX (IntrTxDone | RHINE_EVENT_NAPI_TX_ERR) + +#define RHINE_EVENT_NAPI (RHINE_EVENT_NAPI_RX | \ + RHINE_EVENT_NAPI_TX | \ + IntrStatsMax) +#define RHINE_EVENT_SLOW (IntrPCIErr | IntrLinkChange) +#define RHINE_EVENT (RHINE_EVENT_NAPI | RHINE_EVENT_SLOW) + static int rhine_napipoll(struct napi_struct *napi, int budget) { struct rhine_private *rp = container_of(napi, struct rhine_private, napi); struct net_device *dev = rp->dev; void __iomem *ioaddr = rp->base; - int work_done; + u16 enable_mask = RHINE_EVENT & 0xffff; + int work_done = 0; + u32 status; + + status = rhine_get_events(rp); + rhine_ack_events(rp, status & ~RHINE_EVENT_SLOW); + + if (status & RHINE_EVENT_NAPI_RX) + work_done += rhine_rx(dev, budget); + + if (status & RHINE_EVENT_NAPI_TX) { + if (status & RHINE_EVENT_NAPI_TX_ERR) { + u8 cmd; + + /* Avoid scavenging before Tx engine turned off */ + RHINE_WAIT_FOR(!(ioread8(ioaddr + ChipCmd) & CmdTxOn)); + cmd = ioread8(ioaddr + ChipCmd); + if ((cmd & CmdTxOn) && (debug > 2)) { + netdev_warn(dev, "%s: Tx engine still on\n", + __func__); + } + } + rhine_tx(dev); + + if (status & RHINE_EVENT_NAPI_TX_ERR) + rhine_tx_err(rp, status); + } + + if (status & IntrStatsMax) { + spin_lock(&rp->lock); + rhine_update_rx_crc_and_missed_errord(rp); + spin_unlock(&rp->lock); + } - work_done = rhine_rx(dev, budget); + if (status & RHINE_EVENT_SLOW) { + enable_mask &= ~RHINE_EVENT_SLOW; + schedule_work(&rp->slow_event_task); + } if (work_done < budget) { napi_complete(napi); - - iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow | - IntrRxDropped | IntrRxNoBuf | IntrTxAborted | - IntrTxDone | IntrTxError | IntrTxUnderrun | - IntrPCIErr | IntrStatsMax | IntrLinkChange, - ioaddr + IntrEnable); + iowrite16(enable_mask, ioaddr + IntrEnable); + mmiowb(); } return work_done; } @@ -868,7 +980,9 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, dev->irq = pdev->irq; spin_lock_init(&rp->lock); + mutex_init(&rp->task_lock); INIT_WORK(&rp->reset_task, rhine_reset_task); + INIT_WORK(&rp->slow_event_task, rhine_slow_event_task); rp->mii_if.dev = dev; rp->mii_if.mdio_read = mdio_read; @@ -1278,10 +1392,10 @@ static int rhine_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) { struct rhine_private *rp = netdev_priv(dev); - spin_lock_irq(&rp->lock); + spin_lock_bh(&rp->lock); set_bit(vid, rp->active_vlans); rhine_update_vcam(dev); - spin_unlock_irq(&rp->lock); + spin_unlock_bh(&rp->lock); return 0; } @@ -1289,10 +1403,10 @@ static int rhine_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) { struct rhine_private *rp = netdev_priv(dev); - spin_lock_irq(&rp->lock); + spin_lock_bh(&rp->lock); clear_bit(vid, rp->active_vlans); rhine_update_vcam(dev); - spin_unlock_irq(&rp->lock); + spin_unlock_bh(&rp->lock); return 0; } @@ -1322,12 +1436,7 @@ static void init_registers(struct net_device *dev) napi_enable(&rp->napi); - /* Enable interrupts by setting the interrupt mask. */ - iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow | - IntrRxDropped | IntrRxNoBuf | IntrTxAborted | - IntrTxDone | IntrTxError | IntrTxUnderrun | - IntrPCIErr | IntrStatsMax | IntrLinkChange, - ioaddr + IntrEnable); + iowrite16(RHINE_EVENT & 0xffff, ioaddr + IntrEnable); iowrite16(CmdStart | CmdTxOn | CmdRxOn | (Cmd1NoTxPoll << 8), ioaddr + ChipCmd); @@ -1407,6 +1516,23 @@ static void mdio_write(struct net_device *dev, int phy_id, int regnum, int value rhine_enable_linkmon(ioaddr); } +static void rhine_task_disable(struct rhine_private *rp) +{ + mutex_lock(&rp->task_lock); + rp->task_enable = false; + mutex_unlock(&rp->task_lock); + + cancel_work_sync(&rp->slow_event_task); + cancel_work_sync(&rp->reset_task); +} + +static void rhine_task_enable(struct rhine_private *rp) +{ + mutex_lock(&rp->task_lock); + rp->task_enable = true; + mutex_unlock(&rp->task_lock); +} + static int rhine_open(struct net_device *dev) { struct rhine_private *rp = netdev_priv(dev); @@ -1429,6 +1555,7 @@ static int rhine_open(struct net_device *dev) alloc_rbufs(dev); alloc_tbufs(dev); rhine_chip_reset(dev); + rhine_task_enable(rp); init_registers(dev); if (debug > 2) netdev_dbg(dev, "%s() Done - status %04x MII status: %04x\n", @@ -1446,11 +1573,12 @@ static void rhine_reset_task(struct work_struct *work) reset_task); struct net_device *dev = rp->dev; - /* protect against concurrent rx interrupts */ - disable_irq(rp->pdev->irq); + mutex_lock(&rp->task_lock); - napi_disable(&rp->napi); + if (!rp->task_enable) + goto out_unlock; + napi_disable(&rp->napi); spin_lock_bh(&rp->lock); /* clear all descriptors */ @@ -1464,11 +1592,13 @@ static void rhine_reset_task(struct work_struct *work) init_registers(dev); spin_unlock_bh(&rp->lock); - enable_irq(rp->pdev->irq); dev->trans_start = jiffies; /* prevent tx timeout */ dev->stats.tx_errors++; netif_wake_queue(dev); + +out_unlock: + mutex_unlock(&rp->task_lock); } static void rhine_tx_timeout(struct net_device *dev) @@ -1489,7 +1619,6 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb, struct rhine_private *rp = netdev_priv(dev); void __iomem *ioaddr = rp->base; unsigned entry; - unsigned long flags; /* Caution: the write order is important here, set the field with the "ownership" bits last. */ @@ -1541,7 +1670,6 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb, rp->tx_ring[entry].tx_status = 0; /* lock eth irq */ - spin_lock_irqsave(&rp->lock, flags); wmb(); rp->tx_ring[entry].tx_status |= cpu_to_le32(DescOwn); wmb(); @@ -1562,8 +1690,6 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb, if (rp->cur_tx == rp->dirty_tx + TX_QUEUE_LEN) netif_stop_queue(dev); - spin_unlock_irqrestore(&rp->lock, flags); - if (debug > 4) { netdev_dbg(dev, "Transmit frame #%d queued in slot %d\n", rp->cur_tx-1, entry); @@ -1571,66 +1697,39 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb, return NETDEV_TX_OK; } +static void rhine_irq_disable(struct rhine_private *rp) +{ + iowrite16(0x0000, rp->base + IntrEnable); + mmiowb(); +} + /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ static irqreturn_t rhine_interrupt(int irq, void *dev_instance) { struct net_device *dev = dev_instance; struct rhine_private *rp = netdev_priv(dev); - void __iomem *ioaddr = rp->base; - u32 intr_status; - int boguscnt = max_interrupt_work; + u32 status; int handled = 0; - while ((intr_status = rhine_get_events(rp))) { - handled = 1; - - /* Acknowledge all of the current interrupt sources ASAP. */ - rhine_ack_events(rp, intr_status); - - if (debug > 4) - netdev_dbg(dev, "Interrupt, status %08x\n", - intr_status); + status = rhine_get_events(rp); - if (intr_status & (IntrRxDone | IntrRxErr | IntrRxDropped | - IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf)) { - iowrite16(IntrTxAborted | - IntrTxDone | IntrTxError | IntrTxUnderrun | - IntrPCIErr | IntrStatsMax | IntrLinkChange, - ioaddr + IntrEnable); + if (debug > 4) + netdev_dbg(dev, "Interrupt, status %08x\n", status); - napi_schedule(&rp->napi); - } - - if (intr_status & (IntrTxErrSummary | IntrTxDone)) { - if (intr_status & IntrTxErrSummary) { - /* Avoid scavenging before Tx engine turned off */ - RHINE_WAIT_FOR(!(ioread8(ioaddr+ChipCmd) & CmdTxOn)); - if (debug > 2 && - ioread8(ioaddr+ChipCmd) & CmdTxOn) - netdev_warn(dev, - "%s: Tx engine still on\n", - __func__); - } - rhine_tx(dev); - } + if (status & RHINE_EVENT) { + handled = 1; - /* Abnormal error summary/uncommon events handlers. */ - if (intr_status & (IntrPCIErr | IntrLinkChange | - IntrStatsMax | IntrTxError | IntrTxAborted | - IntrTxUnderrun | IntrTxDescRace)) - rhine_error(dev, intr_status); + rhine_irq_disable(rp); + napi_schedule(&rp->napi); + } - if (--boguscnt < 0) { - netdev_warn(dev, "Too much work at interrupt, status=%#08x\n", - intr_status); - break; - } + if (status & ~(IntrLinkChange | IntrStatsMax | RHINE_EVENT_NAPI)) { + if (debug > 1) + netdev_err(dev, "Something Wicked happened! %08x\n", + status); } - if (debug > 3) - netdev_dbg(dev, "exiting interrupt, status=%08x\n", - ioread16(ioaddr + IntrStatus)); return IRQ_RETVAL(handled); } @@ -1641,8 +1740,6 @@ static void rhine_tx(struct net_device *dev) struct rhine_private *rp = netdev_priv(dev); int txstatus = 0, entry = rp->dirty_tx % TX_RING_SIZE; - spin_lock(&rp->lock); - /* find and cleanup dirty tx descriptors */ while (rp->dirty_tx != rp->cur_tx) { txstatus = le32_to_cpu(rp->tx_ring[entry].tx_status); @@ -1696,8 +1793,6 @@ static void rhine_tx(struct net_device *dev) } if ((rp->cur_tx - rp->dirty_tx) < TX_QUEUE_LEN - 4) netif_wake_queue(dev); - - spin_unlock(&rp->lock); } /** @@ -1848,19 +1943,6 @@ static int rhine_rx(struct net_device *dev, int limit) return count; } -/* - * Clears the "tally counters" for CRC errors and missed frames(?). - * It has been reported that some chips need a write of 0 to clear - * these, for others the counters are set to 1 when written to and - * instead cleared when read. So we clear them both ways ... - */ -static inline void clear_tally_counters(void __iomem *ioaddr) -{ - iowrite32(0, ioaddr + RxMissed); - ioread16(ioaddr + RxCRCErrs); - ioread16(ioaddr + RxMissed); -} - static void rhine_restart_tx(struct net_device *dev) { struct rhine_private *rp = netdev_priv(dev); void __iomem *ioaddr = rp->base; @@ -1899,69 +1981,41 @@ static void rhine_restart_tx(struct net_device *dev) { } -static void rhine_error(struct net_device *dev, int intr_status) +static void rhine_slow_event_task(struct work_struct *work) { - struct rhine_private *rp = netdev_priv(dev); - void __iomem *ioaddr = rp->base; + struct rhine_private *rp = + container_of(work, struct rhine_private, slow_event_task); + struct net_device *dev = rp->dev; + u32 intr_status; - spin_lock(&rp->lock); + mutex_lock(&rp->task_lock); + + if (!rp->task_enable) + goto out_unlock; + + intr_status = rhine_get_events(rp); + rhine_ack_events(rp, intr_status & RHINE_EVENT_SLOW); if (intr_status & IntrLinkChange) rhine_check_media(dev, 0); - if (intr_status & IntrStatsMax) { - dev->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs); - dev->stats.rx_missed_errors += ioread16(ioaddr + RxMissed); - clear_tally_counters(ioaddr); - } - if (intr_status & IntrTxAborted) { - if (debug > 1) - netdev_info(dev, "Abort %08x, frame dropped\n", - intr_status); - } - if (intr_status & IntrTxUnderrun) { - rhine_kick_tx_threshold(rp); - if (debug > 1) - netdev_info(dev, "Transmitter underrun, Tx threshold now %02x\n", - rp->tx_thresh); - } - if (intr_status & IntrTxDescRace) { - if (debug > 2) - netdev_info(dev, "Tx descriptor write-back race\n"); - } - if ((intr_status & IntrTxError) && - (intr_status & (IntrTxAborted | - IntrTxUnderrun | IntrTxDescRace)) == 0) { - rhine_kick_tx_threshold(rp); - if (debug > 1) - netdev_info(dev, "Unspecified error. Tx threshold now %02x\n", - rp->tx_thresh); - } - if (intr_status & (IntrTxAborted | IntrTxUnderrun | IntrTxDescRace | - IntrTxError)) - rhine_restart_tx(dev); - if (intr_status & ~(IntrLinkChange | IntrStatsMax | IntrTxUnderrun | - IntrTxError | IntrTxAborted | IntrNormalSummary | - IntrTxDescRace)) { - if (debug > 1) - netdev_err(dev, "Something Wicked happened! %08x\n", - intr_status); - } + napi_disable(&rp->napi); + rhine_irq_disable(rp); + /* Slow and safe. Consider __napi_schedule as a replacement ? */ + napi_enable(&rp->napi); + napi_schedule(&rp->napi); - spin_unlock(&rp->lock); +out_unlock: + mutex_unlock(&rp->task_lock); } static struct net_device_stats *rhine_get_stats(struct net_device *dev) { struct rhine_private *rp = netdev_priv(dev); - void __iomem *ioaddr = rp->base; - unsigned long flags; - spin_lock_irqsave(&rp->lock, flags); - dev->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs); - dev->stats.rx_missed_errors += ioread16(ioaddr + RxMissed); - clear_tally_counters(ioaddr); - spin_unlock_irqrestore(&rp->lock, flags); + spin_lock_bh(&rp->lock); + rhine_update_rx_crc_and_missed_errord(rp); + spin_unlock_bh(&rp->lock); return &dev->stats; } @@ -2028,9 +2082,9 @@ static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) struct rhine_private *rp = netdev_priv(dev); int rc; - spin_lock_irq(&rp->lock); + mutex_lock(&rp->task_lock); rc = mii_ethtool_gset(&rp->mii_if, cmd); - spin_unlock_irq(&rp->lock); + mutex_unlock(&rp->task_lock); return rc; } @@ -2040,10 +2094,10 @@ static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) struct rhine_private *rp = netdev_priv(dev); int rc; - spin_lock_irq(&rp->lock); + mutex_lock(&rp->task_lock); rc = mii_ethtool_sset(&rp->mii_if, cmd); - spin_unlock_irq(&rp->lock); rhine_set_carrier(&rp->mii_if); + mutex_unlock(&rp->task_lock); return rc; } @@ -2125,10 +2179,10 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) if (!netif_running(dev)) return -EINVAL; - spin_lock_irq(&rp->lock); + mutex_lock(&rp->task_lock); rc = generic_mii_ioctl(&rp->mii_if, if_mii(rq), cmd, NULL); - spin_unlock_irq(&rp->lock); rhine_set_carrier(&rp->mii_if); + mutex_unlock(&rp->task_lock); return rc; } @@ -2138,12 +2192,10 @@ static int rhine_close(struct net_device *dev) struct rhine_private *rp = netdev_priv(dev); void __iomem *ioaddr = rp->base; + rhine_task_disable(rp); napi_disable(&rp->napi); - cancel_work_sync(&rp->reset_task); netif_stop_queue(dev); - spin_lock_irq(&rp->lock); - if (debug > 1) netdev_dbg(dev, "Shutting down ethercard, status was %04x\n", ioread16(ioaddr + ChipCmd)); @@ -2151,14 +2203,11 @@ static int rhine_close(struct net_device *dev) /* Switch to loopback mode to avoid hardware races. */ iowrite8(rp->tx_thresh | 0x02, ioaddr + TxConfig); - /* Disable interrupts by clearing the interrupt mask. */ - iowrite16(0x0000, ioaddr + IntrEnable); + rhine_irq_disable(rp); /* Stop the chip's Tx and Rx processes. */ iowrite16(CmdStop, ioaddr + ChipCmd); - spin_unlock_irq(&rp->lock); - free_irq(rp->pdev->irq, dev); free_rbufs(dev); free_tbufs(dev); @@ -2198,6 +2247,8 @@ static void rhine_shutdown (struct pci_dev *pdev) if (rp->quirks & rq6patterns) iowrite8(0x04, ioaddr + WOLcgClr); + spin_lock(&rp->lock); + if (rp->wolopts & WAKE_MAGIC) { iowrite8(WOLmagic, ioaddr + WOLcrSet); /* @@ -2222,6 +2273,8 @@ static void rhine_shutdown (struct pci_dev *pdev) iowrite8(ioread8(ioaddr + StickyHW) | 0x04, ioaddr + StickyHW); } + spin_unlock(&rp->lock); + /* Hit power state D3 (sleep) */ if (!avoid_D3) iowrite8(ioread8(ioaddr + StickyHW) | 0x03, ioaddr + StickyHW); @@ -2235,21 +2288,19 @@ static int rhine_suspend(struct pci_dev *pdev, pm_message_t state) { struct net_device *dev = pci_get_drvdata(pdev); struct rhine_private *rp = netdev_priv(dev); - unsigned long flags; if (!netif_running(dev)) return 0; + rhine_task_disable(rp); + rhine_irq_disable(rp); napi_disable(&rp->napi); netif_device_detach(dev); pci_save_state(pdev); - spin_lock_irqsave(&rp->lock, flags); rhine_shutdown(pdev); - spin_unlock_irqrestore(&rp->lock, flags); - free_irq(dev->irq, dev); return 0; } @@ -2257,15 +2308,11 @@ static int rhine_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct rhine_private *rp = netdev_priv(dev); - unsigned long flags; int ret; if (!netif_running(dev)) return 0; - if (request_irq(dev->irq, rhine_interrupt, IRQF_SHARED, dev->name, dev)) - netdev_err(dev, "request_irq failed\n"); - ret = pci_set_power_state(pdev, PCI_D0); if (debug > 1) netdev_info(dev, "Entering power state D0 %s (%d)\n", @@ -2273,7 +2320,6 @@ static int rhine_resume(struct pci_dev *pdev) pci_restore_state(pdev); - spin_lock_irqsave(&rp->lock, flags); #ifdef USE_MMIO enable_mmio(rp->pioaddr, rp->quirks); #endif @@ -2282,8 +2328,10 @@ static int rhine_resume(struct pci_dev *pdev) free_rbufs(dev); alloc_tbufs(dev); alloc_rbufs(dev); + rhine_task_enable(rp); + spin_lock_bh(&rp->lock); init_registers(dev); - spin_unlock_irqrestore(&rp->lock, flags); + spin_unlock_bh(&rp->lock); netif_device_attach(dev); -- cgit v0.10.2 From a384a33bb1c9ec2d99db2046b41f57023fa7d77b Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sat, 7 Jan 2012 22:19:36 +0100 Subject: via-rhine: RHINE_WAIT_FOR macro removal. Signed-off-by: Francois Romieu diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c index 9a7bacc..98ec14e 100644 --- a/drivers/net/ethernet/via/via-rhine.c +++ b/drivers/net/ethernet/via/via-rhine.c @@ -501,15 +501,31 @@ static int rhine_vlan_rx_add_vid(struct net_device *dev, unsigned short vid); static int rhine_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid); static void rhine_restart_tx(struct net_device *dev); -#define RHINE_WAIT_FOR(condition) \ -do { \ - int i = 1024; \ - while (!(condition) && --i) \ - ; \ - if (debug > 1 && i < 512) \ - pr_info("%4d cycles used @ %s:%d\n", \ - 1024 - i, __func__, __LINE__); \ -} while (0) +static void rhine_wait_bit(struct rhine_private *rp, u8 reg, u8 mask, bool high) +{ + void __iomem *ioaddr = rp->base; + int i; + + for (i = 0; i < 1024; i++) { + if (high ^ !!(ioread8(ioaddr + reg) & mask)) + break; + udelay(10); + } + if (i > 64) { + netdev_dbg(rp->dev, "%s bit wait (%02x/%02x) cycle " + "count: %04d\n", high ? "high" : "low", reg, mask, i); + } +} + +static void rhine_wait_bit_high(struct rhine_private *rp, u8 reg, u8 mask) +{ + rhine_wait_bit(rp, reg, mask, true); +} + +static void rhine_wait_bit_low(struct rhine_private *rp, u8 reg, u8 mask) +{ + rhine_wait_bit(rp, reg, mask, false); +} static u32 rhine_get_events(struct rhine_private *rp) { @@ -609,7 +625,7 @@ static void rhine_chip_reset(struct net_device *dev) iowrite8(0x40, ioaddr + MiscCmd); /* Reset can take somewhat longer (rare) */ - RHINE_WAIT_FOR(!(ioread8(ioaddr + ChipCmd1) & Cmd1Reset)); + rhine_wait_bit_low(rp, ChipCmd1, Cmd1Reset); } if (debug > 1) @@ -641,9 +657,15 @@ static void __devinit rhine_reload_eeprom(long pioaddr, struct net_device *dev) { struct rhine_private *rp = netdev_priv(dev); void __iomem *ioaddr = rp->base; + int i; outb(0x20, pioaddr + MACRegEEcsr); - RHINE_WAIT_FOR(!(inb(pioaddr + MACRegEEcsr) & 0x20)); + for (i = 0; i < 1024; i++) { + if (!(inb(pioaddr + MACRegEEcsr) & 0x20)) + break; + } + if (i > 512) + pr_info("%4d cycles used @ %s:%d\n", i, __func__, __LINE__); #ifdef USE_MMIO /* @@ -770,7 +792,7 @@ static int rhine_napipoll(struct napi_struct *napi, int budget) u8 cmd; /* Avoid scavenging before Tx engine turned off */ - RHINE_WAIT_FOR(!(ioread8(ioaddr + ChipCmd) & CmdTxOn)); + rhine_wait_bit_low(rp, ChipCmd, CmdTxOn); cmd = ioread8(ioaddr + ChipCmd); if ((cmd & CmdTxOn) && (debug > 2)) { netdev_warn(dev, "%s: Tx engine still on\n", @@ -1444,23 +1466,27 @@ static void init_registers(struct net_device *dev) } /* Enable MII link status auto-polling (required for IntrLinkChange) */ -static void rhine_enable_linkmon(void __iomem *ioaddr) +static void rhine_enable_linkmon(struct rhine_private *rp) { + void __iomem *ioaddr = rp->base; + iowrite8(0, ioaddr + MIICmd); iowrite8(MII_BMSR, ioaddr + MIIRegAddr); iowrite8(0x80, ioaddr + MIICmd); - RHINE_WAIT_FOR((ioread8(ioaddr + MIIRegAddr) & 0x20)); + rhine_wait_bit_high(rp, MIIRegAddr, 0x20); iowrite8(MII_BMSR | 0x40, ioaddr + MIIRegAddr); } /* Disable MII link status auto-polling (required for MDIO access) */ -static void rhine_disable_linkmon(void __iomem *ioaddr, u32 quirks) +static void rhine_disable_linkmon(struct rhine_private *rp) { + void __iomem *ioaddr = rp->base; + iowrite8(0, ioaddr + MIICmd); - if (quirks & rqRhineI) { + if (rp->quirks & rqRhineI) { iowrite8(0x01, ioaddr + MIIRegAddr); // MII_BMSR /* Can be called from ISR. Evil. */ @@ -1469,13 +1495,13 @@ static void rhine_disable_linkmon(void __iomem *ioaddr, u32 quirks) /* 0x80 must be set immediately before turning it off */ iowrite8(0x80, ioaddr + MIICmd); - RHINE_WAIT_FOR(ioread8(ioaddr + MIIRegAddr) & 0x20); + rhine_wait_bit_high(rp, MIIRegAddr, 0x20); /* Heh. Now clear 0x80 again. */ iowrite8(0, ioaddr + MIICmd); } else - RHINE_WAIT_FOR(ioread8(ioaddr + MIIRegAddr) & 0x80); + rhine_wait_bit_high(rp, MIIRegAddr, 0x80); } /* Read and write over the MII Management Data I/O (MDIO) interface. */ @@ -1486,16 +1512,16 @@ static int mdio_read(struct net_device *dev, int phy_id, int regnum) void __iomem *ioaddr = rp->base; int result; - rhine_disable_linkmon(ioaddr, rp->quirks); + rhine_disable_linkmon(rp); /* rhine_disable_linkmon already cleared MIICmd */ iowrite8(phy_id, ioaddr + MIIPhyAddr); iowrite8(regnum, ioaddr + MIIRegAddr); iowrite8(0x40, ioaddr + MIICmd); /* Trigger read */ - RHINE_WAIT_FOR(!(ioread8(ioaddr + MIICmd) & 0x40)); + rhine_wait_bit_low(rp, MIICmd, 0x40); result = ioread16(ioaddr + MIIData); - rhine_enable_linkmon(ioaddr); + rhine_enable_linkmon(rp); return result; } @@ -1504,16 +1530,16 @@ static void mdio_write(struct net_device *dev, int phy_id, int regnum, int value struct rhine_private *rp = netdev_priv(dev); void __iomem *ioaddr = rp->base; - rhine_disable_linkmon(ioaddr, rp->quirks); + rhine_disable_linkmon(rp); /* rhine_disable_linkmon already cleared MIICmd */ iowrite8(phy_id, ioaddr + MIIPhyAddr); iowrite8(regnum, ioaddr + MIIRegAddr); iowrite16(value, ioaddr + MIIData); iowrite8(0x20, ioaddr + MIICmd); /* Trigger write */ - RHINE_WAIT_FOR(!(ioread8(ioaddr + MIICmd) & 0x20)); + rhine_wait_bit_low(rp, MIICmd, 0x20); - rhine_enable_linkmon(ioaddr); + rhine_enable_linkmon(rp); } static void rhine_task_disable(struct rhine_private *rp) -- cgit v0.10.2 From fc3e0f8aec05dd812cba2c1e31c3d1f5fc85e55c Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sat, 7 Jan 2012 22:39:37 +0100 Subject: via-rhine: per device debug level. Signed-off-by: Francois Romieu diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c index 98ec14e..e39802f 100644 --- a/drivers/net/ethernet/via/via-rhine.c +++ b/drivers/net/ethernet/via/via-rhine.c @@ -39,9 +39,9 @@ /* A few user-configurable values. These may be modified when a driver module is loaded. */ - -#define DEBUG -static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ +static int debug = 0; +#define RHINE_MSG_DEFAULT \ + (0x0000) /* Set the copy breakpoint for the copy-only-tiny-frames scheme. Setting to > 1518 effectively disables this feature. */ @@ -130,7 +130,7 @@ MODULE_LICENSE("GPL"); module_param(debug, int, 0); module_param(rx_copybreak, int, 0); module_param(avoid_D3, bool, 0); -MODULE_PARM_DESC(debug, "VIA Rhine debug level (0-7)"); +MODULE_PARM_DESC(debug, "VIA Rhine debug message flags"); MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames"); MODULE_PARM_DESC(avoid_D3, "Avoid power state D3 (work-around for broken BIOSes)"); @@ -450,6 +450,8 @@ struct rhine_private { struct work_struct slow_event_task; struct work_struct reset_task; + u32 msg_enable; + /* Frequently used values: keep some adjacent for cache effect. */ u32 quirks; struct rx_desc *rx_head_desc; @@ -512,8 +514,8 @@ static void rhine_wait_bit(struct rhine_private *rp, u8 reg, u8 mask, bool high) udelay(10); } if (i > 64) { - netdev_dbg(rp->dev, "%s bit wait (%02x/%02x) cycle " - "count: %04d\n", high ? "high" : "low", reg, mask, i); + netif_dbg(rp, hw, rp->dev, "%s bit wait (%02x/%02x) cycle " + "count: %04d\n", high ? "high" : "low", reg, mask, i); } } @@ -613,6 +615,7 @@ static void rhine_chip_reset(struct net_device *dev) { struct rhine_private *rp = netdev_priv(dev); void __iomem *ioaddr = rp->base; + u8 cmd1; iowrite8(Cmd1Reset, ioaddr + ChipCmd1); IOSYNC; @@ -628,10 +631,9 @@ static void rhine_chip_reset(struct net_device *dev) rhine_wait_bit_low(rp, ChipCmd1, Cmd1Reset); } - if (debug > 1) - netdev_info(dev, "Reset %s\n", - (ioread8(ioaddr + ChipCmd1) & Cmd1Reset) ? - "failed" : "succeeded"); + cmd1 = ioread8(ioaddr + ChipCmd1); + netif_info(rp, hw, dev, "Reset %s\n", (cmd1 & Cmd1Reset) ? + "failed" : "succeeded"); } #ifdef USE_MMIO @@ -706,28 +708,24 @@ static void rhine_tx_err(struct rhine_private *rp, u32 status) struct net_device *dev = rp->dev; if (status & IntrTxAborted) { - if (debug > 1) - netdev_info(dev, "Abort %08x, frame dropped\n", status); + netif_info(rp, tx_err, dev, + "Abort %08x, frame dropped\n", status); } if (status & IntrTxUnderrun) { rhine_kick_tx_threshold(rp); - if (debug > 1) - netdev_info(dev, "Transmitter underrun, Tx threshold now %02x\n", - rp->tx_thresh); + netif_info(rp, tx_err ,dev, "Transmitter underrun, " + "Tx threshold now %02x\n", rp->tx_thresh); } - if (status & IntrTxDescRace) { - if (debug > 2) - netdev_info(dev, "Tx descriptor write-back race\n"); - } + if (status & IntrTxDescRace) + netif_info(rp, tx_err, dev, "Tx descriptor write-back race\n"); if ((status & IntrTxError) && (status & (IntrTxAborted | IntrTxUnderrun | IntrTxDescRace)) == 0) { rhine_kick_tx_threshold(rp); - if (debug > 1) - netdev_info(dev, "Unspecified error. Tx threshold now %02x\n", - rp->tx_thresh); + netif_info(rp, tx_err, dev, "Unspecified error. " + "Tx threshold now %02x\n", rp->tx_thresh); } rhine_restart_tx(dev); @@ -789,16 +787,12 @@ static int rhine_napipoll(struct napi_struct *napi, int budget) if (status & RHINE_EVENT_NAPI_TX) { if (status & RHINE_EVENT_NAPI_TX_ERR) { - u8 cmd; - /* Avoid scavenging before Tx engine turned off */ rhine_wait_bit_low(rp, ChipCmd, CmdTxOn); - cmd = ioread8(ioaddr + ChipCmd); - if ((cmd & CmdTxOn) && (debug > 2)) { - netdev_warn(dev, "%s: Tx engine still on\n", - __func__); - } + if (ioread8(ioaddr + ChipCmd) & CmdTxOn) + netif_warn(rp, tx_err, dev, "Tx still on\n"); } + rhine_tx(dev); if (status & RHINE_EVENT_NAPI_TX_ERR) @@ -943,6 +937,7 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, rp->quirks = quirks; rp->pioaddr = pioaddr; rp->pdev = pdev; + rp->msg_enable = netif_msg_init(debug, RHINE_MSG_DEFAULT); rc = pci_request_regions(pdev, DRV_NAME); if (rc) @@ -1064,8 +1059,8 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, } } rp->mii_if.phy_id = phy_id; - if (debug > 1 && avoid_D3) - netdev_info(dev, "No D3 power state at shutdown\n"); + if (avoid_D3) + netif_info(rp, probe, dev, "No D3 power state at shutdown\n"); return 0; @@ -1241,7 +1236,7 @@ static void rhine_check_media(struct net_device *dev, unsigned int init_media) struct rhine_private *rp = netdev_priv(dev); void __iomem *ioaddr = rp->base; - mii_check_media(&rp->mii_if, debug, init_media); + mii_check_media(&rp->mii_if, netif_msg_link(rp), init_media); if (rp->mii_if.full_duplex) iowrite8(ioread8(ioaddr + ChipCmd1) | Cmd1FDuplex, @@ -1249,24 +1244,26 @@ static void rhine_check_media(struct net_device *dev, unsigned int init_media) else iowrite8(ioread8(ioaddr + ChipCmd1) & ~Cmd1FDuplex, ioaddr + ChipCmd1); - if (debug > 1) - netdev_info(dev, "force_media %d, carrier %d\n", - rp->mii_if.force_media, netif_carrier_ok(dev)); + + netif_info(rp, link, dev, "force_media %d, carrier %d\n", + rp->mii_if.force_media, netif_carrier_ok(dev)); } /* Called after status of force_media possibly changed */ static void rhine_set_carrier(struct mii_if_info *mii) { + struct net_device *dev = mii->dev; + struct rhine_private *rp = netdev_priv(dev); + if (mii->force_media) { /* autoneg is off: Link is always assumed to be up */ - if (!netif_carrier_ok(mii->dev)) - netif_carrier_on(mii->dev); - } - else /* Let MMI library update carrier status */ - rhine_check_media(mii->dev, 0); - if (debug > 1) - netdev_info(mii->dev, "force_media %d, carrier %d\n", - mii->force_media, netif_carrier_ok(mii->dev)); + if (!netif_carrier_ok(dev)) + netif_carrier_on(dev); + } else /* Let MMI library update carrier status */ + rhine_check_media(dev, 0); + + netif_info(rp, link, dev, "force_media %d, carrier %d\n", + mii->force_media, netif_carrier_ok(dev)); } /** @@ -1570,8 +1567,7 @@ static int rhine_open(struct net_device *dev) if (rc) return rc; - if (debug > 1) - netdev_dbg(dev, "%s() irq %d\n", __func__, rp->pdev->irq); + netif_dbg(rp, ifup, dev, "%s() irq %d\n", __func__, rp->pdev->irq); rc = alloc_ring(dev); if (rc) { @@ -1583,10 +1579,10 @@ static int rhine_open(struct net_device *dev) rhine_chip_reset(dev); rhine_task_enable(rp); init_registers(dev); - if (debug > 2) - netdev_dbg(dev, "%s() Done - status %04x MII status: %04x\n", - __func__, ioread16(ioaddr + ChipCmd), - mdio_read(dev, rp->mii_if.phy_id, MII_BMSR)); + + netif_dbg(rp, ifup, dev, "%s() Done - status %04x MII status: %04x\n", + __func__, ioread16(ioaddr + ChipCmd), + mdio_read(dev, rp->mii_if.phy_id, MII_BMSR)); netif_start_queue(dev); @@ -1716,10 +1712,9 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb, if (rp->cur_tx == rp->dirty_tx + TX_QUEUE_LEN) netif_stop_queue(dev); - if (debug > 4) { - netdev_dbg(dev, "Transmit frame #%d queued in slot %d\n", - rp->cur_tx-1, entry); - } + netif_dbg(rp, tx_queued, dev, "Transmit frame #%d queued in slot %d\n", + rp->cur_tx - 1, entry); + return NETDEV_TX_OK; } @@ -1740,8 +1735,7 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance) status = rhine_get_events(rp); - if (debug > 4) - netdev_dbg(dev, "Interrupt, status %08x\n", status); + netif_dbg(rp, intr, dev, "Interrupt, status %08x\n", status); if (status & RHINE_EVENT) { handled = 1; @@ -1751,9 +1745,8 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance) } if (status & ~(IntrLinkChange | IntrStatsMax | RHINE_EVENT_NAPI)) { - if (debug > 1) - netdev_err(dev, "Something Wicked happened! %08x\n", - status); + netif_err(rp, intr, dev, "Something Wicked happened! %08x\n", + status); } return IRQ_RETVAL(handled); @@ -1769,15 +1762,13 @@ static void rhine_tx(struct net_device *dev) /* find and cleanup dirty tx descriptors */ while (rp->dirty_tx != rp->cur_tx) { txstatus = le32_to_cpu(rp->tx_ring[entry].tx_status); - if (debug > 6) - netdev_dbg(dev, "Tx scavenge %d status %08x\n", - entry, txstatus); + netif_dbg(rp, tx_done, dev, "Tx scavenge %d status %08x\n", + entry, txstatus); if (txstatus & DescOwn) break; if (txstatus & 0x8000) { - if (debug > 1) - netdev_dbg(dev, "Transmit error, Tx status %08x\n", - txstatus); + netif_dbg(rp, tx_done, dev, + "Transmit error, Tx status %08x\n", txstatus); dev->stats.tx_errors++; if (txstatus & 0x0400) dev->stats.tx_carrier_errors++; @@ -1799,10 +1790,8 @@ static void rhine_tx(struct net_device *dev) dev->stats.collisions += (txstatus >> 3) & 0x0F; else dev->stats.collisions += txstatus & 0x0F; - if (debug > 6) - netdev_dbg(dev, "collisions: %1.1x:%1.1x\n", - (txstatus >> 3) & 0xF, - txstatus & 0xF); + netif_dbg(rp, tx_done, dev, "collisions: %1.1x:%1.1x\n", + (txstatus >> 3) & 0xF, txstatus & 0xF); dev->stats.tx_bytes += rp->tx_skbuff[entry]->len; dev->stats.tx_packets++; } @@ -1843,11 +1832,8 @@ static int rhine_rx(struct net_device *dev, int limit) int count; int entry = rp->cur_rx % RX_RING_SIZE; - if (debug > 4) { - netdev_dbg(dev, "%s(), entry %d status %08x\n", - __func__, entry, - le32_to_cpu(rp->rx_head_desc->rx_status)); - } + netif_dbg(rp, rx_status, dev, "%s(), entry %d status %08x\n", __func__, + entry, le32_to_cpu(rp->rx_head_desc->rx_status)); /* If EOP is set on the next entry, it's a new packet. Send it up. */ for (count = 0; count < limit; ++count) { @@ -1859,9 +1845,8 @@ static int rhine_rx(struct net_device *dev, int limit) if (desc_status & DescOwn) break; - if (debug > 4) - netdev_dbg(dev, "%s() status is %08x\n", - __func__, desc_status); + netif_dbg(rp, rx_status, dev, "%s() status %08x\n", __func__, + desc_status); if ((desc_status & (RxWholePkt | RxErr)) != RxWholePkt) { if ((desc_status & RxWholePkt) != RxWholePkt) { @@ -1877,9 +1862,9 @@ static int rhine_rx(struct net_device *dev, int limit) dev->stats.rx_length_errors++; } else if (desc_status & RxErr) { /* There was a error. */ - if (debug > 2) - netdev_dbg(dev, "%s() Rx error was %08x\n", - __func__, desc_status); + netif_dbg(rp, rx_err, dev, + "%s() Rx error %08x\n", __func__, + desc_status); dev->stats.rx_errors++; if (desc_status & 0x0030) dev->stats.rx_length_errors++; @@ -2000,9 +1985,8 @@ static void rhine_restart_tx(struct net_device *dev) { } else { /* This should never happen */ - if (debug > 1) - netdev_warn(dev, "%s() Another error occurred %08x\n", - __func__, intr_status); + netif_warn(rp, tx_err, dev, "another error occurred %08x\n", + intr_status); } } @@ -2025,6 +2009,9 @@ static void rhine_slow_event_task(struct work_struct *work) if (intr_status & IntrLinkChange) rhine_check_media(dev, 0); + if (intr_status & IntrPCIErr) + netif_warn(rp, hw, dev, "PCI error\n"); + napi_disable(&rp->napi); rhine_irq_disable(rp); /* Slow and safe. Consider __napi_schedule as a replacement ? */ @@ -2144,12 +2131,16 @@ static u32 netdev_get_link(struct net_device *dev) static u32 netdev_get_msglevel(struct net_device *dev) { - return debug; + struct rhine_private *rp = netdev_priv(dev); + + return rp->msg_enable; } static void netdev_set_msglevel(struct net_device *dev, u32 value) { - debug = value; + struct rhine_private *rp = netdev_priv(dev); + + rp->msg_enable = value; } static void rhine_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) @@ -2222,9 +2213,8 @@ static int rhine_close(struct net_device *dev) napi_disable(&rp->napi); netif_stop_queue(dev); - if (debug > 1) - netdev_dbg(dev, "Shutting down ethercard, status was %04x\n", - ioread16(ioaddr + ChipCmd)); + netif_dbg(rp, ifdown, dev, "Shutting down ethercard, status was %04x\n", + ioread16(ioaddr + ChipCmd)); /* Switch to loopback mode to avoid hardware races. */ iowrite8(rp->tx_thresh | 0x02, ioaddr + TxConfig); @@ -2340,9 +2330,8 @@ static int rhine_resume(struct pci_dev *pdev) return 0; ret = pci_set_power_state(pdev, PCI_D0); - if (debug > 1) - netdev_info(dev, "Entering power state D0 %s (%d)\n", - ret ? "failed" : "succeeded", ret); + netif_info(rp, drv, dev, "Entering power state D0 %s (%d)\n", + ret ? "failed" : "succeeded", ret); pci_restore_state(pdev); -- cgit v0.10.2 From e92b9b3b091d5fcdaed91d6fa9410deae135704b Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Sat, 7 Jan 2012 22:58:27 +0100 Subject: via-rhine: rework suspend and resume. Cover of 861ab44059350e5cab350238606cf8814abab93b. Signed-off-by: Francois Romieu diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c index e39802f..10b18eb 100644 --- a/drivers/net/ethernet/via/via-rhine.c +++ b/drivers/net/ethernet/via/via-rhine.c @@ -2291,17 +2291,18 @@ static void rhine_shutdown (struct pci_dev *pdev) spin_unlock(&rp->lock); - /* Hit power state D3 (sleep) */ - if (!avoid_D3) + if (system_state == SYSTEM_POWER_OFF && !avoid_D3) { iowrite8(ioread8(ioaddr + StickyHW) | 0x03, ioaddr + StickyHW); - /* TODO: Check use of pci_enable_wake() */ - + pci_wake_from_d3(pdev, true); + pci_set_power_state(pdev, PCI_D3hot); + } } -#ifdef CONFIG_PM -static int rhine_suspend(struct pci_dev *pdev, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int rhine_suspend(struct device *device) { + struct pci_dev *pdev = to_pci_dev(device); struct net_device *dev = pci_get_drvdata(pdev); struct rhine_private *rp = netdev_priv(dev); @@ -2313,28 +2314,21 @@ static int rhine_suspend(struct pci_dev *pdev, pm_message_t state) napi_disable(&rp->napi); netif_device_detach(dev); - pci_save_state(pdev); rhine_shutdown(pdev); return 0; } -static int rhine_resume(struct pci_dev *pdev) +static int rhine_resume(struct device *device) { + struct pci_dev *pdev = to_pci_dev(device); struct net_device *dev = pci_get_drvdata(pdev); struct rhine_private *rp = netdev_priv(dev); - int ret; if (!netif_running(dev)) return 0; - ret = pci_set_power_state(pdev, PCI_D0); - netif_info(rp, drv, dev, "Entering power state D0 %s (%d)\n", - ret ? "failed" : "succeeded", ret); - - pci_restore_state(pdev); - #ifdef USE_MMIO enable_mmio(rp->pioaddr, rp->quirks); #endif @@ -2352,18 +2346,23 @@ static int rhine_resume(struct pci_dev *pdev) return 0; } -#endif /* CONFIG_PM */ + +static SIMPLE_DEV_PM_OPS(rhine_pm_ops, rhine_suspend, rhine_resume); +#define RHINE_PM_OPS (&rhine_pm_ops) + +#else + +#define RHINE_PM_OPS NULL + +#endif /* !CONFIG_PM_SLEEP */ static struct pci_driver rhine_driver = { .name = DRV_NAME, .id_table = rhine_pci_tbl, .probe = rhine_init_one, .remove = __devexit_p(rhine_remove_one), -#ifdef CONFIG_PM - .suspend = rhine_suspend, - .resume = rhine_resume, -#endif /* CONFIG_PM */ - .shutdown = rhine_shutdown, + .shutdown = rhine_shutdown, + .driver.pm = RHINE_PM_OPS, }; static struct dmi_system_id __initdata rhine_dmi_table[] = { -- cgit v0.10.2 From d90db4b12bc1b9b8a787ef28550fdb767ee25a49 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 4 Jan 2012 20:50:47 -0600 Subject: rtl8192se: Fix BUG caused by failure to check skb allocation When downloading firmware into the device, the driver fails to check the return when allocating an skb. When the allocation fails, a BUG can be generated, as seen in https://bugzilla.redhat.com/show_bug.cgi?id=771656. Signed-off-by: Larry Finger Cc: Stable Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c index 6f91a14..3fda6b1 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c @@ -196,6 +196,8 @@ static bool _rtl92s_firmware_downloadcode(struct ieee80211_hw *hw, /* Allocate skb buffer to contain firmware */ /* info and tx descriptor info. */ skb = dev_alloc_skb(frag_length); + if (!skb) + return false; skb_reserve(skb, extra_descoffset); seg_ptr = (u8 *)skb_put(skb, (u32)(frag_length - extra_descoffset)); @@ -573,6 +575,8 @@ static bool _rtl92s_firmware_set_h2c_cmd(struct ieee80211_hw *hw, u8 h2c_cmd, len = _rtl92s_get_h2c_cmdlen(MAX_TRANSMIT_BUFFER_SIZE, 1, &cmd_len); skb = dev_alloc_skb(len); + if (!skb) + return false; cb_desc = (struct rtl_tcb_desc *)(skb->cb); cb_desc->queue_index = TXCMD_QUEUE; cb_desc->cmd_or_init = DESC_PACKET_TYPE_NORMAL; -- cgit v0.10.2 From e4922f2b5f1c2b3daa80b56a6eeca984cbee0dde Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Sat, 7 Jan 2012 21:06:02 +0530 Subject: ath9k_hw: fix a comment also remove an unused macro and a function declaration Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 2589b38..2b0bfb8 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -46,7 +46,7 @@ static const int m2ThreshExt_off = 127; * @chan: * * This is the function to change channel on single-chip devices, that is - * all devices after ar9280. + * for AR9300 family of chipsets. * * This function takes the channel value in MHz and sets * hardware channel value. Assumes writes have been enabled to analog bus. diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index b30e9fc..171ccf7 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -679,7 +679,6 @@ void ath9k_deinit_device(struct ath_softc *sc); void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); void ath9k_reload_chainmask_settings(struct ath_softc *sc); -void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw); bool ath9k_uses_beacons(int type); #ifdef CONFIG_ATH9K_PCI diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index 05b9dbf..3b33996d 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h @@ -19,7 +19,6 @@ #include "hw.h" -#define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3 #define AR_PHY_CCA_FILTERWINDOW_LENGTH 5 #define NUM_NF_READINGS 6 -- cgit v0.10.2 From c40701eacbaebcfe3fb6fac8ef3da653021c212c Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 8 Jan 2012 23:41:21 +0100 Subject: brcm80211: Don't leak 'vbuffer' in brcmf_sdbrcm_write_vars() If the memory allocation 'nvram_ularray = kmalloc(varsize, GFP_ATOMIC);' fails we'll leak the memory allocated to 'vbuffer' when we return -ENOMEM from the function. This patch resolves the leak by kfree()'ing the allocated memory before the return. Signed-off-by: Jesper Juhl Acked-by: Arend van Spriel Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 5a002a2..f7eeee1 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c @@ -3119,8 +3119,10 @@ static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus) /* Verify NVRAM bytes */ brcmf_dbg(INFO, "Compare NVRAM dl & ul; varsize=%d\n", varsize); nvram_ularray = kmalloc(varsize, GFP_ATOMIC); - if (!nvram_ularray) + if (!nvram_ularray) { + kfree(vbuffer); return -ENOMEM; + } /* Upload image to verify downloaded contents. */ memset(nvram_ularray, 0xaa, varsize); -- cgit v0.10.2 From 1a19f77f3642b8194ad9cf55548cc5d92e841766 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 9 Jan 2012 15:37:53 +0530 Subject: ath9k: Fix regression in channelwidth switch at the same channel The commit "ath9k: Fix invalid noisefloor reading due to channel update" preserves the current channel noisefloor readings before updating channel type at the same channel index. It is also updating the curchan pointer. As survey updation is also referring curchan pointer to fetch the appropriate index, which might leads to invalid memory access. This patch partially reverts the change and stores the noise floor history buffer before updating channel type w/o updating curchan. Cc: stable@kernel.org Cc: Gary Morain Cc: Paul Stewart Reported-by: Mohammed Shafi Shajakhan Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 172e33d..2f4b48e 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -400,6 +400,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) ah->noise = ath9k_hw_getchan_noise(ah, chan); return true; } +EXPORT_SYMBOL(ath9k_hw_getnf); void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, struct ath9k_channel *chan) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index e267c92..4a00806 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1629,7 +1629,6 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { struct ieee80211_channel *curchan = hw->conf.channel; - struct ath9k_channel old_chan; int pos = curchan->hw_value; int old_pos = -1; unsigned long flags; @@ -1654,11 +1653,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) * Preserve the current channel values, before updating * the same channel */ - if (old_pos == pos) { - memcpy(&old_chan, &sc->sc_ah->channels[pos], - sizeof(struct ath9k_channel)); - ah->curchan = &old_chan; - } + if (ah->curchan && (old_pos == pos)) + ath9k_hw_getnf(ah, ah->curchan); ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos], curchan, conf->channel_type); -- cgit v0.10.2 From 1dd8117e3320fb42ec40ef2ace982871572d34ed Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 10 Jan 2012 01:47:40 +0000 Subject: stmmac: Fix compilation error in mmc_core.c Fix this error: CC drivers/net/ethernet/stmicro/stmmac/mmc_core.o drivers/net/ethernet/stmicro/stmmac/mmc_core.c: In function 'dwmac_mmc_ctrl': drivers/net/ethernet/stmicro/stmmac/mmc_core.c:143:2: error: implicit declaration of function 'pr_debug' [-Werror=implicit-function-declaration] Signed-off-by: Stefan Roese Cc: Giuseppe Cavallaro Acked-by: Giuseppe Cavallaro Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c index 41e6b33..c07cfe9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c @@ -22,6 +22,7 @@ Author: Giuseppe Cavallaro *******************************************************************************/ +#include #include #include "mmc.h" -- cgit v0.10.2 From aae54cff9255f190ec712468d1b40e63bb51e127 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 10 Jan 2012 01:47:51 +0000 Subject: stmmac: Add missing LF to pr_info() in stmmac_main.c Otherwise the output looks like this: ... STMMAC - user ID: 0x10, Synopsys ID: 0x32 No HW DMA feature register supported Normal descriptors Remote wake-up capable Checksum Offload Engine supported No MAC Management Counters availableIP-Config: Complete: device=eth0, addr=192.168.20.42, mask=255.255.0.0, gw=192.168.1.254, ... Signed-off-by: Stefan Roese Cc: Giuseppe Cavallaro Acked-by: Giuseppe Cavallaro Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 3738b47..ee85a14 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -772,7 +772,7 @@ static void stmmac_mmc_setup(struct stmmac_priv *priv) dwmac_mmc_ctrl(priv->ioaddr, mode); memset(&priv->mmc, 0, sizeof(struct stmmac_counters)); } else - pr_info(" No MAC Management Counters available"); + pr_info(" No MAC Management Counters available\n"); } static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv) -- cgit v0.10.2 From 2193ceabdcde1fca5e017acf1d0023285531748f Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 10 Jan 2012 01:54:23 +0000 Subject: drivers: isdn: Fix dependency for ISDN_PPP Fix the following build warning: warning: (ISDN_PPP) selects SLHC which has unmet direct dependencies (NETDEVICES) Signed-off-by: Fabio Estevam Signed-off-by: David S. Miller diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig index 9c6650e..2302fbe 100644 --- a/drivers/isdn/i4l/Kconfig +++ b/drivers/isdn/i4l/Kconfig @@ -6,7 +6,7 @@ if ISDN_I4L config ISDN_PPP bool "Support synchronous PPP" - depends on INET + depends on INET && NETDEVICES select SLHC help Over digital connections such as ISDN, there is no need to -- cgit v0.10.2 From 8ef66bdc4bda6aac2dae73b84d79dc8c2db33637 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Tue, 10 Jan 2012 06:40:17 +0000 Subject: asix: fix setting custom MAC address on Asix 88772 devices In kernel v3.2 initialization sequence for Asix 88772 devices was changed so that hardware is reseted on every time interface is brought up (ifconfig up), instead just at USB probe time. This causes problem with setting custom MAC address to device as ax88772_reset causes reload of MAC address from EEPROM. This patch fixes the issue by rewriting MAC address at end of ax88772_reset. Signed-off-by: Jussi Kivilinna Acked-by: Grant Grundler Cc: Allan Chou Cc: stable Signed-off-by: David S. Miller diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index d0937c4..8414bdc 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -978,6 +978,7 @@ static int ax88772_link_reset(struct usbnet *dev) static int ax88772_reset(struct usbnet *dev) { + struct asix_data *data = (struct asix_data *)&dev->data; int ret, embd_phy; u16 rx_ctl; @@ -1055,6 +1056,13 @@ static int ax88772_reset(struct usbnet *dev) goto out; } + /* Rewrite MAC address */ + memcpy(data->mac_addr, dev->net->dev_addr, ETH_ALEN); + ret = asix_write_cmd(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN, + data->mac_addr); + if (ret < 0) + goto out; + /* Set RX_CTL to default values with 2k buffer, and enable cactus */ ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL); if (ret < 0) -- cgit v0.10.2 From 71bc5d94061516c4e70303570128797bcf768b10 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Tue, 10 Jan 2012 06:40:23 +0000 Subject: asix: fix setting custom MAC address on Asix 88178 devices In kernel v3.2 initialization sequence for Asix 88178 devices was changed so that hardware is reseted on every time interface is brought up (ifconfig up), instead just at USB probe time. This causes problem with setting custom MAC address to device as ax88178_reset causes reload of MAC address from EEPROM. This patch fixes the issue by rewriting MAC address at end of ax88178_reset. Signed-off-by: Jussi Kivilinna Acked-by: Grant Grundler Cc: Allan Chou Cc: stable Signed-off-by: David S. Miller diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 8414bdc..8e84f5b 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -1328,6 +1328,13 @@ static int ax88178_reset(struct usbnet *dev) if (ret < 0) return ret; + /* Rewrite MAC address */ + memcpy(data->mac_addr, dev->net->dev_addr, ETH_ALEN); + ret = asix_write_cmd(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN, + data->mac_addr); + if (ret < 0) + return ret; + ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL); if (ret < 0) return ret; -- cgit v0.10.2 From fa84e7201c592945b390fb51a5ffc7e785868be4 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 9 Jan 2012 23:59:07 +0000 Subject: ax88796: use an unique MDIO bus name. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c index 9e8ba4f..0f92e35 100644 --- a/drivers/net/ethernet/8390/ax88796.c +++ b/drivers/net/ethernet/8390/ax88796.c @@ -623,7 +623,8 @@ static int ax_mii_init(struct net_device *dev) ax->mii_bus->name = "ax88796_mii_bus"; ax->mii_bus->parent = dev->dev.parent; - snprintf(ax->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id); + snprintf(ax->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", + pdev->name, pdev->id); ax->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); if (!ax->mii_bus->irq) { -- cgit v0.10.2 From 75432fd2913e03696f56289a853754ef0124545f Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 9 Jan 2012 23:59:08 +0000 Subject: bfin_mac: use an unique MDIO bus name. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c index b6d69c9..d812a10 100644 --- a/drivers/net/ethernet/adi/bfin_mac.c +++ b/drivers/net/ethernet/adi/bfin_mac.c @@ -1670,7 +1670,8 @@ static int __devinit bfin_mii_bus_probe(struct platform_device *pdev) miibus->name = "bfin_mii_bus"; miibus->phy_mask = mii_bus_pd->phy_mask; - snprintf(miibus->id, MII_BUS_ID_SIZE, "0"); + snprintf(miibus->id, MII_BUS_ID_SIZE, "%s-%x", + pdev->name, pdev->id); miibus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); if (!miibus->irq) goto out_err_irq_alloc; -- cgit v0.10.2 From f74299b6c1d01363adf356c9ecc01ba000a5a1aa Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 9 Jan 2012 23:59:09 +0000 Subject: au1000-eth: use an unique MDIO bus name. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c index cc9262b..8b95dd3 100644 --- a/drivers/net/ethernet/amd/au1000_eth.c +++ b/drivers/net/ethernet/amd/au1000_eth.c @@ -1171,7 +1171,8 @@ static int __devinit au1000_probe(struct platform_device *pdev) aup->mii_bus->write = au1000_mdiobus_write; aup->mii_bus->reset = au1000_mdiobus_reset; aup->mii_bus->name = "au1000_eth_mii"; - snprintf(aup->mii_bus->id, MII_BUS_ID_SIZE, "%x", aup->mac_id); + snprintf(aup->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", + pdev->name, aup->mac_id); aup->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); if (aup->mii_bus->irq == NULL) goto err_out; -- cgit v0.10.2 From 446bbc4b5ee122c3a3a4954b144d031f0f9aa006 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 9 Jan 2012 23:59:10 +0000 Subject: sb1250: use an unique MDIO bus name. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/sb1250-mac.c b/drivers/net/ethernet/broadcom/sb1250-mac.c index 8fa7abc..084904c 100644 --- a/drivers/net/ethernet/broadcom/sb1250-mac.c +++ b/drivers/net/ethernet/broadcom/sb1250-mac.c @@ -2259,7 +2259,8 @@ static int sbmac_init(struct platform_device *pldev, long long base) } sc->mii_bus->name = sbmac_mdio_string; - snprintf(sc->mii_bus->id, MII_BUS_ID_SIZE, "%x", idx); + snprintf(sc->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", + pldev->name, idx); sc->mii_bus->priv = sc; sc->mii_bus->read = sbmac_mii_read; sc->mii_bus->write = sbmac_mii_write; -- cgit v0.10.2 From 98d5e57eafce7a68d864fdb5a26542ba8b4f59ba Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 9 Jan 2012 23:59:11 +0000 Subject: macb: use an unique MDIO bus name. Signed-off-by: Florian Fainelli Acked-by: Nicolas Ferre Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index f3d5c65..2320068 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -243,7 +243,8 @@ static int macb_mii_init(struct macb *bp) bp->mii_bus->read = &macb_mdio_read; bp->mii_bus->write = &macb_mdio_write; bp->mii_bus->reset = &macb_mdio_reset; - snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%x", bp->pdev->id); + snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", + bp->pdev->name, bp->pdev->id); bp->mii_bus->priv = bp; bp->mii_bus->parent = &bp->dev->dev; pdata = bp->pdev->dev.platform_data; -- cgit v0.10.2 From 63f678301fb952c2d758d9ded4ed88c1da6c0c50 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 9 Jan 2012 23:59:12 +0000 Subject: dnet: use an unique MDIO bus name. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/dnet.c b/drivers/net/ethernet/dnet.c index ce88c0f..925c9ba 100644 --- a/drivers/net/ethernet/dnet.c +++ b/drivers/net/ethernet/dnet.c @@ -325,7 +325,8 @@ static int dnet_mii_init(struct dnet *bp) bp->mii_bus->write = &dnet_mdio_write; bp->mii_bus->reset = &dnet_mdio_reset; - snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0); + snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", + bp->pdev->name, bp->pdev->id); bp->mii_bus->priv = bp; -- cgit v0.10.2 From 391420f7b829e73b26a543e39c40a83f7de6467c Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 9 Jan 2012 23:59:13 +0000 Subject: fec: use an unique MDIO bus name. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c index ddcbbb3..236cc89 100644 --- a/drivers/net/ethernet/freescale/fec.c +++ b/drivers/net/ethernet/freescale/fec.c @@ -1077,7 +1077,8 @@ static int fec_enet_mii_init(struct platform_device *pdev) fep->mii_bus->read = fec_enet_mdio_read; fep->mii_bus->write = fec_enet_mdio_write; fep->mii_bus->reset = fec_enet_mdio_reset; - snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", fep->dev_id + 1); + snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", + pdev->name, fep->dev_id + 1); fep->mii_bus->priv = fep; fep->mii_bus->parent = &pdev->dev; -- cgit v0.10.2 From d1b86507d87c94a201a9a1bb31d2285b189d8e26 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 9 Jan 2012 23:59:14 +0000 Subject: lantiq_etop: use an unique MDIO bus name. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c index 0b3567a..85e2c6c 100644 --- a/drivers/net/ethernet/lantiq_etop.c +++ b/drivers/net/ethernet/lantiq_etop.c @@ -98,6 +98,7 @@ struct ltq_etop_chan { struct ltq_etop_priv { struct net_device *netdev; + struct platform_device *pdev; struct ltq_eth_data *pldata; struct resource *res; @@ -436,7 +437,8 @@ ltq_etop_mdio_init(struct net_device *dev) priv->mii_bus->read = ltq_etop_mdio_rd; priv->mii_bus->write = ltq_etop_mdio_wr; priv->mii_bus->name = "ltq_mii"; - snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0); + snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", + priv->pdev->name, priv->pdev->id); priv->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); if (!priv->mii_bus->irq) { err = -ENOMEM; @@ -734,6 +736,7 @@ ltq_etop_probe(struct platform_device *pdev) dev->ethtool_ops = <q_etop_ethtool_ops; priv = netdev_priv(dev); priv->res = res; + priv->pdev = pdev; priv->pldata = dev_get_platdata(&pdev->dev); priv->netdev = dev; spin_lock_init(&priv->lock); -- cgit v0.10.2 From 12322431d154250db9e61b0c79151c968a8d7766 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 9 Jan 2012 23:59:15 +0000 Subject: mv643xx-eth: use an unique MDIO bus name. Signed-off-by: Florian Fainelli Acked-by: Lennert Buytenhek Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 80aab4e..9c049d2 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -2613,7 +2613,8 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev) msp->smi_bus->name = "mv643xx_eth smi"; msp->smi_bus->read = smi_bus_read; msp->smi_bus->write = smi_bus_write, - snprintf(msp->smi_bus->id, MII_BUS_ID_SIZE, "%d", pdev->id); + snprintf(msp->smi_bus->id, MII_BUS_ID_SIZE, "%s-%d", + pdev->name, pdev->id); msp->smi_bus->parent = &pdev->dev; msp->smi_bus->phy_mask = 0xffffffff; if (mdiobus_register(msp->smi_bus) < 0) -- cgit v0.10.2 From d073a102a185e9847785c93669bffd1a09a8c1f2 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 9 Jan 2012 23:59:16 +0000 Subject: pxa168-eth: use an unique MDIO bus name. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c index 5ec409e..953ba58 100644 --- a/drivers/net/ethernet/marvell/pxa168_eth.c +++ b/drivers/net/ethernet/marvell/pxa168_eth.c @@ -1552,7 +1552,8 @@ static int pxa168_eth_probe(struct platform_device *pdev) pep->smi_bus->name = "pxa168_eth smi"; pep->smi_bus->read = pxa168_smi_read; pep->smi_bus->write = pxa168_smi_write; - snprintf(pep->smi_bus->id, MII_BUS_ID_SIZE, "%d", pdev->id); + snprintf(pep->smi_bus->id, MII_BUS_ID_SIZE, "%s-%d", + pdev->name, pdev->id); pep->smi_bus->parent = &pdev->dev; pep->smi_bus->phy_mask = 0xffffffff; err = mdiobus_register(pep->smi_bus); -- cgit v0.10.2 From 5278fb547076ad6768d16c8b4df45c086470c163 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 9 Jan 2012 23:59:17 +0000 Subject: sh-eth: use an unique MDIO bus name. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index fc9bda9..6ece429 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -1702,7 +1702,8 @@ static int sh_mdio_init(struct net_device *ndev, int id, /* Hook up MII support for ethtool */ mdp->mii_bus->name = "sh_mii"; mdp->mii_bus->parent = &ndev->dev; - snprintf(mdp->mii_bus->id, MII_BUS_ID_SIZE, "%x", id); + snprintf(mdp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", + mdp->pdev->name, pdid); /* PHY IRQ */ mdp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); -- cgit v0.10.2 From 859ad35e711d95f2794ab2196aac7c45fe5f7cfe Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 9 Jan 2012 23:59:18 +0000 Subject: s6gmac: use an unique MDIO bus name. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/s6gmac.c b/drivers/net/ethernet/s6gmac.c index a7ff8ea..22e9c01 100644 --- a/drivers/net/ethernet/s6gmac.c +++ b/drivers/net/ethernet/s6gmac.c @@ -1004,7 +1004,7 @@ static int __devinit s6gmac_probe(struct platform_device *pdev) mb->write = s6mii_write; mb->reset = s6mii_reset; mb->priv = pd; - snprintf(mb->id, MII_BUS_ID_SIZE, "0"); + snprintf(mb->id, MII_BUS_ID_SIZE, "%s-%x", pdev->name, pdev->id); mb->phy_mask = ~(1 << 0); mb->irq = &pd->mii.irq[0]; for (i = 0; i < PHY_MAX_ADDR; i++) { -- cgit v0.10.2 From 09ef0789bbceb0fe89ce4ad2bb1fdb2b937d3eba Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 9 Jan 2012 23:59:19 +0000 Subject: smsc911x: use an unique MDIO bus name. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index 9d0b8ce..24d2df0 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -1044,7 +1044,8 @@ static int __devinit smsc911x_mii_init(struct platform_device *pdev, } pdata->mii_bus->name = SMSC_MDIONAME; - snprintf(pdata->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id); + snprintf(pdata->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", + pdev->name, pdev->id); pdata->mii_bus->priv = pdata; pdata->mii_bus->read = smsc911x_mii_read; pdata->mii_bus->write = smsc911x_mii_write; -- cgit v0.10.2 From db8857bf5bd888d763e1984f9449d0b824b39ee1 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 9 Jan 2012 23:59:20 +0000 Subject: stmmac: use an unique MDIO bus name. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index ee85a14..96fa2da 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -307,7 +307,7 @@ static int stmmac_init_phy(struct net_device *dev) priv->speed = 0; priv->oldduplex = -1; - snprintf(bus_id, MII_BUS_ID_SIZE, "%x", priv->plat->bus_id); + snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x", priv->plat->bus_id); snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id, priv->plat->phy_addr); pr_debug("stmmac_init_phy: trying to attach to %s\n", phy_id); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 51f4412..da4a104 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -158,7 +158,8 @@ int stmmac_mdio_register(struct net_device *ndev) new_bus->read = &stmmac_mdio_read; new_bus->write = &stmmac_mdio_write; new_bus->reset = &stmmac_mdio_reset; - snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", mdio_bus_data->bus_id); + snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x", + new_bus->name, mdio_bus_data->bus_id); new_bus->priv = ndev; new_bus->irq = irqlist; new_bus->phy_mask = mdio_bus_data->phy_mask; -- cgit v0.10.2 From d1733f078b1b3777fed8e8fe598e7f10f28f59fb Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 9 Jan 2012 23:59:21 +0000 Subject: cpmac: use an unique MDIO bus name. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/ti/cpmac.c b/drivers/net/ethernet/ti/cpmac.c index aaac0c7..4d9a28f 100644 --- a/drivers/net/ethernet/ti/cpmac.c +++ b/drivers/net/ethernet/ti/cpmac.c @@ -1269,7 +1269,7 @@ int __devinit cpmac_init(void) } cpmac_mii->phy_mask = ~(mask | 0x80000000); - snprintf(cpmac_mii->id, MII_BUS_ID_SIZE, "1"); + snprintf(cpmac_mii->id, MII_BUS_ID_SIZE, "cpmac-1"); res = mdiobus_register(cpmac_mii); if (res) -- cgit v0.10.2 From 5a05a8200a4359ef2bfe9094c137dee35cfdd516 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 9 Jan 2012 23:59:22 +0000 Subject: davinci_emac: use an unique MDIO bus name. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c index 7615040..ef7c9c1 100644 --- a/drivers/net/ethernet/ti/davinci_mdio.c +++ b/drivers/net/ethernet/ti/davinci_mdio.c @@ -313,7 +313,8 @@ static int __devinit davinci_mdio_probe(struct platform_device *pdev) data->bus->reset = davinci_mdio_reset, data->bus->parent = dev; data->bus->priv = data; - snprintf(data->bus->id, MII_BUS_ID_SIZE, "%x", pdev->id); + snprintf(data->bus->id, MII_BUS_ID_SIZE, "%s-%x", + pdev->name, pdev->id); data->clk = clk_get(dev, NULL); if (IS_ERR(data->clk)) { -- cgit v0.10.2 From 0869b3a456d62070fb1f7e3519fd53934b52530c Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 9 Jan 2012 23:59:23 +0000 Subject: ixp4xx-eth: use an unique MDIO bus name. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c index f45c85a..72a854f 100644 --- a/drivers/net/ethernet/xscale/ixp4xx_eth.c +++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c @@ -529,7 +529,7 @@ static int ixp4xx_mdio_register(void) mdio_bus->name = "IXP4xx MII Bus"; mdio_bus->read = &ixp4xx_mdio_read; mdio_bus->write = &ixp4xx_mdio_write; - strcpy(mdio_bus->id, "0"); + snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "ixp4xx-eth-0"); if ((err = mdiobus_register(mdio_bus))) mdiobus_free(mdio_bus); -- cgit v0.10.2 From 3e617506c17df5cba55d7c615ec7cfbc812ec5fa Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 9 Jan 2012 23:59:24 +0000 Subject: bcm63xx_enet: use an unique MDIO bus name. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c index d44331e..986019b 100644 --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c @@ -1727,7 +1727,7 @@ static int __devinit bcm_enet_probe(struct platform_device *pdev) bus->priv = priv; bus->read = bcm_enet_mdio_read_phylib; bus->write = bcm_enet_mdio_write_phylib; - sprintf(bus->id, "%d", priv->mac_id); + sprintf(bus->id, "%s-%d", pdev->name, priv->mac_id); /* only probe bus where we think the PHY is, because * the mdio read operation return 0 instead of 0xffff -- cgit v0.10.2 From 9e6c643bb4502c50b6511206601b7760c610dfcc Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 9 Jan 2012 23:59:25 +0000 Subject: phy/fixed: use an unique MDIO bus name. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c index 1fa4d73..633680d 100644 --- a/drivers/net/phy/fixed.c +++ b/drivers/net/phy/fixed.c @@ -220,7 +220,7 @@ static int __init fixed_mdio_bus_init(void) goto err_mdiobus_reg; } - snprintf(fmb->mii_bus->id, MII_BUS_ID_SIZE, "0"); + snprintf(fmb->mii_bus->id, MII_BUS_ID_SIZE, "fixed-0"); fmb->mii_bus->name = "Fixed MDIO Bus"; fmb->mii_bus->priv = fmb; fmb->mii_bus->parent = &pdev->dev; -- cgit v0.10.2 From a77e929a24ccf5a8545266a0c247e5ae862f13ba Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 9 Jan 2012 23:59:26 +0000 Subject: mdio-gpio: use an unique MDIO bus name. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index 89c5a3e..50e8e5e 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c @@ -116,7 +116,7 @@ static struct mii_bus * __devinit mdio_gpio_bus_init(struct device *dev, if (!new_bus->irq[i]) new_bus->irq[i] = PHY_POLL; - snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", bus_id); + snprintf(new_bus->id, MII_BUS_ID_SIZE, "gpio-%x", bus_id); if (gpio_request(bitbang->mdc, "mdc")) goto out_free_bus; -- cgit v0.10.2 From d6c25beba35a76c002bff9235484d75a6f8e7e6b Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 9 Jan 2012 23:59:27 +0000 Subject: mdio-octeon: use an unique MDIO bus name. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller diff --git a/drivers/net/phy/mdio-octeon.c b/drivers/net/phy/mdio-octeon.c index bd12ba9..826d961 100644 --- a/drivers/net/phy/mdio-octeon.c +++ b/drivers/net/phy/mdio-octeon.c @@ -118,7 +118,8 @@ static int __devinit octeon_mdiobus_probe(struct platform_device *pdev) bus->mii_bus->priv = bus; bus->mii_bus->irq = bus->phy_irq; bus->mii_bus->name = "mdio-octeon"; - snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%x", bus->unit); + snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", + bus->mii_bus->name, bus->unit); bus->mii_bus->parent = &pdev->dev; bus->mii_bus->read = octeon_mdiobus_read; -- cgit v0.10.2 From bdd3ae3d1e749cf6597f035a5357f297a1af8eb3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 2 Jan 2012 13:30:03 +0100 Subject: nl80211: fix old station flags compatibility My patch to validate station flags broke compatibility with the old station flags setting where all flags are always set at once since it always set the mask as all possible flags which ended up being rejected later in the station add/modify code. Fix by parsing only the current flags in the old flags attribute -- new applications and new flags should use (and will now require) the new flags attribute where the mask is given by the application. Reported-and-tested-by: Thomas Hilber Signed-off-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index b3d3cf8..afeea32 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2250,6 +2250,7 @@ static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { }; static int parse_station_flags(struct genl_info *info, + enum nl80211_iftype iftype, struct station_parameters *params) { struct nlattr *flags[NL80211_STA_FLAG_MAX + 1]; @@ -2283,8 +2284,33 @@ static int parse_station_flags(struct genl_info *info, nla, sta_flags_policy)) return -EINVAL; - params->sta_flags_mask = (1 << __NL80211_STA_FLAG_AFTER_LAST) - 1; - params->sta_flags_mask &= ~1; + /* + * Only allow certain flags for interface types so that + * other attributes are silently ignored. Remember that + * this is backward compatibility code with old userspace + * and shouldn't be hit in other cases anyway. + */ + switch (iftype) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_AP_VLAN: + case NL80211_IFTYPE_P2P_GO: + params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) | + BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) | + BIT(NL80211_STA_FLAG_WME) | + BIT(NL80211_STA_FLAG_MFP); + break; + case NL80211_IFTYPE_P2P_CLIENT: + case NL80211_IFTYPE_STATION: + params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) | + BIT(NL80211_STA_FLAG_TDLS_PEER); + break; + case NL80211_IFTYPE_MESH_POINT: + params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHENTICATED) | + BIT(NL80211_STA_FLAG_MFP) | + BIT(NL80211_STA_FLAG_AUTHORIZED); + default: + return -EINVAL; + } for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++) if (flags[flag]) @@ -2585,7 +2611,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) if (!rdev->ops->change_station) return -EOPNOTSUPP; - if (parse_station_flags(info, ¶ms)) + if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms)) return -EINVAL; if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) @@ -2731,7 +2757,7 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) if (!rdev->ops->add_station) return -EOPNOTSUPP; - if (parse_station_flags(info, ¶ms)) + if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms)) return -EINVAL; switch (dev->ieee80211_ptr->iftype) { -- cgit v0.10.2 From 1140afa862842ac3e56678693050760edc4ecde9 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 11 Jan 2012 09:26:54 +0100 Subject: mac80211: fix rx->key NULL pointer dereference in promiscuous mode Since: commit 816c04fe7ef01dd9649f5ccfe796474db8708be5 Author: Christian Lamparter Date: Sat Apr 30 15:24:30 2011 +0200 mac80211: consolidate MIC failure report handling is possible to that we dereference rx->key == NULL when driver set RX_FLAG_MMIC_STRIPPED and not RX_FLAG_IV_STRIPPED and we are in promiscuous mode. This happen with rt73usb and rt61pci at least. Before the commit we always check rx->key against NULL, so I assume fix should be done in mac80211 (also mic_fail path has similar check). References: https://bugzilla.redhat.com/show_bug.cgi?id=769766 http://rt2x00.serialmonkey.com/pipermail/users_rt2x00.serialmonkey.com/2012-January/004395.html Cc: stable@vger.kernel.org # 3.0+ Reported-by: Stuart D Gathman Reported-by: Kai Wohlfahrt Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 93aab07..422b798 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -106,7 +106,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) if (status->flag & RX_FLAG_MMIC_ERROR) goto mic_fail; - if (!(status->flag & RX_FLAG_IV_STRIPPED)) + if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key) goto update_iv; return RX_CONTINUE; -- cgit v0.10.2 From f515e6b77045b4b1f54617d9fbf4a22b95a58757 Mon Sep 17 00:00:00 2001 From: Maxim Uvarov Date: Mon, 9 Jan 2012 12:01:37 +0000 Subject: bond_alb: don't disable softirq under bond_alb_xmit No need to lock soft irqs under bond_alb_xmit() which already has softirq disabled. Changes: 1. add non-bh/bh version to tlb_clear_slave() 2. represent BH and non BH hash table locks _lock_rx_hashtbl_bh/_unlock_rx_hashtbl_bh _lock_rx_hashtbl/_unlock_rx_hashtbl _lock_tx_hashtbl_bh/_unlock_tx_hashtbl_bh _lock_tx_hashtbl/_unlock_tx_hashtbl Signed-off-by: Maxim Uvarov Signed-off-by: Cong Wang Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 106b88a..342626f 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -99,16 +99,26 @@ static inline u8 _simple_hash(const u8 *hash_start, int hash_size) /*********************** tlb specific functions ***************************/ -static inline void _lock_tx_hashtbl(struct bonding *bond) +static inline void _lock_tx_hashtbl_bh(struct bonding *bond) { spin_lock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock)); } -static inline void _unlock_tx_hashtbl(struct bonding *bond) +static inline void _unlock_tx_hashtbl_bh(struct bonding *bond) { spin_unlock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock)); } +static inline void _lock_tx_hashtbl(struct bonding *bond) +{ + spin_lock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock)); +} + +static inline void _unlock_tx_hashtbl(struct bonding *bond) +{ + spin_unlock(&(BOND_ALB_INFO(bond).tx_hashtbl_lock)); +} + /* Caller must hold tx_hashtbl lock */ static inline void tlb_init_table_entry(struct tlb_client_info *entry, int save_load) { @@ -129,14 +139,13 @@ static inline void tlb_init_slave(struct slave *slave) SLAVE_TLB_INFO(slave).head = TLB_NULL_INDEX; } -/* Caller must hold bond lock for read */ -static void tlb_clear_slave(struct bonding *bond, struct slave *slave, int save_load) +/* Caller must hold bond lock for read, BH disabled */ +static void __tlb_clear_slave(struct bonding *bond, struct slave *slave, + int save_load) { struct tlb_client_info *tx_hash_table; u32 index; - _lock_tx_hashtbl(bond); - /* clear slave from tx_hashtbl */ tx_hash_table = BOND_ALB_INFO(bond).tx_hashtbl; @@ -151,8 +160,15 @@ static void tlb_clear_slave(struct bonding *bond, struct slave *slave, int save_ } tlb_init_slave(slave); +} - _unlock_tx_hashtbl(bond); +/* Caller must hold bond lock for read */ +static void tlb_clear_slave(struct bonding *bond, struct slave *slave, + int save_load) +{ + _lock_tx_hashtbl_bh(bond); + __tlb_clear_slave(bond, slave, save_load); + _unlock_tx_hashtbl_bh(bond); } /* Must be called before starting the monitor timer */ @@ -169,7 +185,7 @@ static int tlb_initialize(struct bonding *bond) bond->dev->name); return -1; } - _lock_tx_hashtbl(bond); + _lock_tx_hashtbl_bh(bond); bond_info->tx_hashtbl = new_hashtbl; @@ -177,7 +193,7 @@ static int tlb_initialize(struct bonding *bond) tlb_init_table_entry(&bond_info->tx_hashtbl[i], 0); } - _unlock_tx_hashtbl(bond); + _unlock_tx_hashtbl_bh(bond); return 0; } @@ -187,12 +203,12 @@ static void tlb_deinitialize(struct bonding *bond) { struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); - _lock_tx_hashtbl(bond); + _lock_tx_hashtbl_bh(bond); kfree(bond_info->tx_hashtbl); bond_info->tx_hashtbl = NULL; - _unlock_tx_hashtbl(bond); + _unlock_tx_hashtbl_bh(bond); } static long long compute_gap(struct slave *slave) @@ -226,15 +242,13 @@ static struct slave *tlb_get_least_loaded_slave(struct bonding *bond) return least_loaded; } -/* Caller must hold bond lock for read */ -static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u32 skb_len) +static struct slave *__tlb_choose_channel(struct bonding *bond, u32 hash_index, + u32 skb_len) { struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); struct tlb_client_info *hash_table; struct slave *assigned_slave; - _lock_tx_hashtbl(bond); - hash_table = bond_info->tx_hashtbl; assigned_slave = hash_table[hash_index].tx_slave; if (!assigned_slave) { @@ -263,22 +277,46 @@ static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u3 hash_table[hash_index].tx_bytes += skb_len; } - _unlock_tx_hashtbl(bond); - return assigned_slave; } +/* Caller must hold bond lock for read */ +static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, + u32 skb_len) +{ + struct slave *tx_slave; + /* + * We don't need to disable softirq here, becase + * tlb_choose_channel() is only called by bond_alb_xmit() + * which already has softirq disabled. + */ + _lock_tx_hashtbl(bond); + tx_slave = __tlb_choose_channel(bond, hash_index, skb_len); + _unlock_tx_hashtbl(bond); + return tx_slave; +} + /*********************** rlb specific functions ***************************/ -static inline void _lock_rx_hashtbl(struct bonding *bond) +static inline void _lock_rx_hashtbl_bh(struct bonding *bond) { spin_lock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock)); } -static inline void _unlock_rx_hashtbl(struct bonding *bond) +static inline void _unlock_rx_hashtbl_bh(struct bonding *bond) { spin_unlock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock)); } +static inline void _lock_rx_hashtbl(struct bonding *bond) +{ + spin_lock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock)); +} + +static inline void _unlock_rx_hashtbl(struct bonding *bond) +{ + spin_unlock(&(BOND_ALB_INFO(bond).rx_hashtbl_lock)); +} + /* when an ARP REPLY is received from a client update its info * in the rx_hashtbl */ @@ -288,7 +326,7 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp) struct rlb_client_info *client_info; u32 hash_index; - _lock_rx_hashtbl(bond); + _lock_rx_hashtbl_bh(bond); hash_index = _simple_hash((u8*)&(arp->ip_src), sizeof(arp->ip_src)); client_info = &(bond_info->rx_hashtbl[hash_index]); @@ -303,7 +341,7 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp) bond_info->rx_ntt = 1; } - _unlock_rx_hashtbl(bond); + _unlock_rx_hashtbl_bh(bond); } static void rlb_arp_recv(struct sk_buff *skb, struct bonding *bond, @@ -401,7 +439,7 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave) u32 index, next_index; /* clear slave from rx_hashtbl */ - _lock_rx_hashtbl(bond); + _lock_rx_hashtbl_bh(bond); rx_hash_table = bond_info->rx_hashtbl; index = bond_info->rx_hashtbl_head; @@ -432,7 +470,7 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave) } } - _unlock_rx_hashtbl(bond); + _unlock_rx_hashtbl_bh(bond); write_lock_bh(&bond->curr_slave_lock); @@ -489,7 +527,7 @@ static void rlb_update_rx_clients(struct bonding *bond) struct rlb_client_info *client_info; u32 hash_index; - _lock_rx_hashtbl(bond); + _lock_rx_hashtbl_bh(bond); hash_index = bond_info->rx_hashtbl_head; for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) { @@ -507,7 +545,7 @@ static void rlb_update_rx_clients(struct bonding *bond) */ bond_info->rlb_update_delay_counter = RLB_UPDATE_DELAY; - _unlock_rx_hashtbl(bond); + _unlock_rx_hashtbl_bh(bond); } /* The slave was assigned a new mac address - update the clients */ @@ -518,7 +556,7 @@ static void rlb_req_update_slave_clients(struct bonding *bond, struct slave *sla int ntt = 0; u32 hash_index; - _lock_rx_hashtbl(bond); + _lock_rx_hashtbl_bh(bond); hash_index = bond_info->rx_hashtbl_head; for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) { @@ -538,7 +576,7 @@ static void rlb_req_update_slave_clients(struct bonding *bond, struct slave *sla bond_info->rlb_update_retry_counter = RLB_UPDATE_RETRY; } - _unlock_rx_hashtbl(bond); + _unlock_rx_hashtbl_bh(bond); } /* mark all clients using src_ip to be updated */ @@ -709,7 +747,7 @@ static void rlb_rebalance(struct bonding *bond) int ntt; u32 hash_index; - _lock_rx_hashtbl(bond); + _lock_rx_hashtbl_bh(bond); ntt = 0; hash_index = bond_info->rx_hashtbl_head; @@ -727,7 +765,7 @@ static void rlb_rebalance(struct bonding *bond) if (ntt) { bond_info->rx_ntt = 1; } - _unlock_rx_hashtbl(bond); + _unlock_rx_hashtbl_bh(bond); } /* Caller must hold rx_hashtbl lock */ @@ -751,7 +789,7 @@ static int rlb_initialize(struct bonding *bond) bond->dev->name); return -1; } - _lock_rx_hashtbl(bond); + _lock_rx_hashtbl_bh(bond); bond_info->rx_hashtbl = new_hashtbl; @@ -761,7 +799,7 @@ static int rlb_initialize(struct bonding *bond) rlb_init_table_entry(bond_info->rx_hashtbl + i); } - _unlock_rx_hashtbl(bond); + _unlock_rx_hashtbl_bh(bond); /* register to receive ARPs */ bond->recv_probe = rlb_arp_recv; @@ -773,13 +811,13 @@ static void rlb_deinitialize(struct bonding *bond) { struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); - _lock_rx_hashtbl(bond); + _lock_rx_hashtbl_bh(bond); kfree(bond_info->rx_hashtbl); bond_info->rx_hashtbl = NULL; bond_info->rx_hashtbl_head = RLB_NULL_INDEX; - _unlock_rx_hashtbl(bond); + _unlock_rx_hashtbl_bh(bond); } static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id) @@ -787,7 +825,7 @@ static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id) struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); u32 curr_index; - _lock_rx_hashtbl(bond); + _lock_rx_hashtbl_bh(bond); curr_index = bond_info->rx_hashtbl_head; while (curr_index != RLB_NULL_INDEX) { @@ -812,7 +850,7 @@ static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id) curr_index = next_index; } - _unlock_rx_hashtbl(bond); + _unlock_rx_hashtbl_bh(bond); } /*********************** tlb/rlb shared functions *********************/ @@ -1320,7 +1358,9 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) res = bond_dev_queue_xmit(bond, skb, tx_slave->dev); } else { if (tx_slave) { - tlb_clear_slave(bond, tx_slave, 0); + _lock_tx_hashtbl(bond); + __tlb_clear_slave(bond, tx_slave, 0); + _unlock_tx_hashtbl(bond); } } -- cgit v0.10.2 From c8991362a0d3cf317dfbfb6cb946607870654e6d Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Tue, 10 Jan 2012 22:36:35 +0000 Subject: inet_diag: Rename inet_diag_req into inet_diag_req_v2 Signed-off-by: Pavel Emelyanov Signed-off-by: David S. Miller diff --git a/include/linux/inet_diag.h b/include/linux/inet_diag.h index 34e8d52..a5b7e91 100644 --- a/include/linux/inet_diag.h +++ b/include/linux/inet_diag.h @@ -34,7 +34,7 @@ struct inet_diag_req_compat { __u32 idiag_dbs; /* Tables to dump (NI) */ }; -struct inet_diag_req { +struct inet_diag_req_v2 { __u8 sdiag_family; __u8 sdiag_protocol; __u8 idiag_ext; @@ -143,12 +143,12 @@ struct netlink_callback; struct inet_diag_handler { void (*dump)(struct sk_buff *skb, struct netlink_callback *cb, - struct inet_diag_req *r, + struct inet_diag_req_v2 *r, struct nlattr *bc); int (*dump_one)(struct sk_buff *in_skb, const struct nlmsghdr *nlh, - struct inet_diag_req *req); + struct inet_diag_req_v2 *req); void (*idiag_get_info)(struct sock *sk, struct inet_diag_msg *r, @@ -158,15 +158,15 @@ struct inet_diag_handler { struct inet_connection_sock; int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, - struct sk_buff *skb, struct inet_diag_req *req, + struct sk_buff *skb, struct inet_diag_req_v2 *req, u32 pid, u32 seq, u16 nlmsg_flags, const struct nlmsghdr *unlh); void inet_diag_dump_icsk(struct inet_hashinfo *h, struct sk_buff *skb, - struct netlink_callback *cb, struct inet_diag_req *r, + struct netlink_callback *cb, struct inet_diag_req_v2 *r, struct nlattr *bc); int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_skb, const struct nlmsghdr *nlh, - struct inet_diag_req *req); + struct inet_diag_req_v2 *req); int inet_diag_bc_sk(const struct nlattr *_bc, struct sock *sk); diff --git a/net/dccp/diag.c b/net/dccp/diag.c index 8f16257..028fc43 100644 --- a/net/dccp/diag.c +++ b/net/dccp/diag.c @@ -49,13 +49,13 @@ static void dccp_diag_get_info(struct sock *sk, struct inet_diag_msg *r, } static void dccp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, - struct inet_diag_req *r, struct nlattr *bc) + struct inet_diag_req_v2 *r, struct nlattr *bc) { inet_diag_dump_icsk(&dccp_hashinfo, skb, cb, r, bc); } static int dccp_diag_dump_one(struct sk_buff *in_skb, const struct nlmsghdr *nlh, - struct inet_diag_req *req) + struct inet_diag_req_v2 *req) { return inet_diag_dump_one_icsk(&dccp_hashinfo, in_skb, nlh, req); } diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 2240a8e..cf23a7c 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -71,7 +71,7 @@ static inline void inet_diag_unlock_handler( } int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, - struct sk_buff *skb, struct inet_diag_req *req, + struct sk_buff *skb, struct inet_diag_req_v2 *req, u32 pid, u32 seq, u16 nlmsg_flags, const struct nlmsghdr *unlh) { @@ -193,7 +193,7 @@ nlmsg_failure: EXPORT_SYMBOL_GPL(inet_sk_diag_fill); static int inet_csk_diag_fill(struct sock *sk, - struct sk_buff *skb, struct inet_diag_req *req, + struct sk_buff *skb, struct inet_diag_req_v2 *req, u32 pid, u32 seq, u16 nlmsg_flags, const struct nlmsghdr *unlh) { @@ -202,7 +202,7 @@ static int inet_csk_diag_fill(struct sock *sk, } static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, - struct sk_buff *skb, struct inet_diag_req *req, + struct sk_buff *skb, struct inet_diag_req_v2 *req, u32 pid, u32 seq, u16 nlmsg_flags, const struct nlmsghdr *unlh) { @@ -253,7 +253,7 @@ nlmsg_failure: } static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, - struct inet_diag_req *r, u32 pid, u32 seq, u16 nlmsg_flags, + struct inet_diag_req_v2 *r, u32 pid, u32 seq, u16 nlmsg_flags, const struct nlmsghdr *unlh) { if (sk->sk_state == TCP_TIME_WAIT) @@ -264,7 +264,7 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, } int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_skb, - const struct nlmsghdr *nlh, struct inet_diag_req *req) + const struct nlmsghdr *nlh, struct inet_diag_req_v2 *req) { int err; struct sock *sk; @@ -333,7 +333,7 @@ EXPORT_SYMBOL_GPL(inet_diag_dump_one_icsk); static int inet_diag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh, - struct inet_diag_req *req) + struct inet_diag_req_v2 *req) { const struct inet_diag_handler *handler; int err; @@ -540,7 +540,7 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) static int inet_csk_diag_dump(struct sock *sk, struct sk_buff *skb, struct netlink_callback *cb, - struct inet_diag_req *r, + struct inet_diag_req_v2 *r, const struct nlattr *bc) { if (!inet_diag_bc_sk(bc, sk)) @@ -554,7 +554,7 @@ static int inet_csk_diag_dump(struct sock *sk, static int inet_twsk_diag_dump(struct inet_timewait_sock *tw, struct sk_buff *skb, struct netlink_callback *cb, - struct inet_diag_req *r, + struct inet_diag_req_v2 *r, const struct nlattr *bc) { if (bc != NULL) { @@ -639,7 +639,7 @@ nlmsg_failure: static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, struct netlink_callback *cb, - struct inet_diag_req *r, + struct inet_diag_req_v2 *r, const struct nlattr *bc) { struct inet_diag_entry entry; @@ -721,7 +721,7 @@ out: } void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb, - struct netlink_callback *cb, struct inet_diag_req *r, struct nlattr *bc) + struct netlink_callback *cb, struct inet_diag_req_v2 *r, struct nlattr *bc) { int i, num; int s_i, s_num; @@ -872,7 +872,7 @@ out: EXPORT_SYMBOL_GPL(inet_diag_dump_icsk); static int __inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, - struct inet_diag_req *r, struct nlattr *bc) + struct inet_diag_req_v2 *r, struct nlattr *bc) { const struct inet_diag_handler *handler; @@ -887,12 +887,12 @@ static int __inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) { struct nlattr *bc = NULL; - int hdrlen = sizeof(struct inet_diag_req); + int hdrlen = sizeof(struct inet_diag_req_v2); if (nlmsg_attrlen(cb->nlh, hdrlen)) bc = nlmsg_find_attr(cb->nlh, hdrlen, INET_DIAG_REQ_BYTECODE); - return __inet_diag_dump(skb, cb, (struct inet_diag_req *)NLMSG_DATA(cb->nlh), bc); + return __inet_diag_dump(skb, cb, (struct inet_diag_req_v2 *)NLMSG_DATA(cb->nlh), bc); } static inline int inet_diag_type2proto(int type) @@ -910,7 +910,7 @@ static inline int inet_diag_type2proto(int type) static int inet_diag_dump_compat(struct sk_buff *skb, struct netlink_callback *cb) { struct inet_diag_req_compat *rc = NLMSG_DATA(cb->nlh); - struct inet_diag_req req; + struct inet_diag_req_v2 req; struct nlattr *bc = NULL; int hdrlen = sizeof(struct inet_diag_req_compat); @@ -930,7 +930,7 @@ static int inet_diag_get_exact_compat(struct sk_buff *in_skb, const struct nlmsghdr *nlh) { struct inet_diag_req_compat *rc = NLMSG_DATA(nlh); - struct inet_diag_req req; + struct inet_diag_req_v2 req; req.sdiag_family = rc->idiag_family; req.sdiag_protocol = inet_diag_type2proto(nlh->nlmsg_type); @@ -970,7 +970,7 @@ static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh) static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) { - int hdrlen = sizeof(struct inet_diag_req); + int hdrlen = sizeof(struct inet_diag_req_v2); if (nlmsg_len(h) < hdrlen) return -EINVAL; @@ -990,7 +990,7 @@ static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) inet_diag_dump, NULL, 0); } - return inet_diag_get_exact(skb, h, (struct inet_diag_req *)NLMSG_DATA(h)); + return inet_diag_get_exact(skb, h, (struct inet_diag_req_v2 *)NLMSG_DATA(h)); } static struct sock_diag_handler inet_diag_handler = { diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c index 8cd357a..ed3f2ad 100644 --- a/net/ipv4/tcp_diag.c +++ b/net/ipv4/tcp_diag.c @@ -35,13 +35,13 @@ static void tcp_diag_get_info(struct sock *sk, struct inet_diag_msg *r, } static void tcp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, - struct inet_diag_req *r, struct nlattr *bc) + struct inet_diag_req_v2 *r, struct nlattr *bc) { inet_diag_dump_icsk(&tcp_hashinfo, skb, cb, r, bc); } static int tcp_diag_dump_one(struct sk_buff *in_skb, const struct nlmsghdr *nlh, - struct inet_diag_req *req) + struct inet_diag_req_v2 *req) { return inet_diag_dump_one_icsk(&tcp_hashinfo, in_skb, nlh, req); } diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c index 69f8a7c..e5e18cb 100644 --- a/net/ipv4/udp_diag.c +++ b/net/ipv4/udp_diag.c @@ -19,7 +19,7 @@ #include static int sk_diag_dump(struct sock *sk, struct sk_buff *skb, - struct netlink_callback *cb, struct inet_diag_req *req, + struct netlink_callback *cb, struct inet_diag_req_v2 *req, struct nlattr *bc) { if (!inet_diag_bc_sk(bc, sk)) @@ -30,7 +30,7 @@ static int sk_diag_dump(struct sock *sk, struct sk_buff *skb, } static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb, - const struct nlmsghdr *nlh, struct inet_diag_req *req) + const struct nlmsghdr *nlh, struct inet_diag_req_v2 *req) { int err = -EINVAL; struct sock *sk; @@ -88,7 +88,7 @@ out_nosk: } static void udp_dump(struct udp_table *table, struct sk_buff *skb, struct netlink_callback *cb, - struct inet_diag_req *r, struct nlattr *bc) + struct inet_diag_req_v2 *r, struct nlattr *bc) { int num, s_num, slot, s_slot; @@ -136,13 +136,13 @@ done: } static void udp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, - struct inet_diag_req *r, struct nlattr *bc) + struct inet_diag_req_v2 *r, struct nlattr *bc) { udp_dump(&udp_table, skb, cb, r, bc); } static int udp_diag_dump_one(struct sk_buff *in_skb, const struct nlmsghdr *nlh, - struct inet_diag_req *req) + struct inet_diag_req_v2 *req) { return udp_dump_one(&udp_table, in_skb, nlh, req); } @@ -154,13 +154,13 @@ static const struct inet_diag_handler udp_diag_handler = { }; static void udplite_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, - struct inet_diag_req *r, struct nlattr *bc) + struct inet_diag_req_v2 *r, struct nlattr *bc) { udp_dump(&udplite_table, skb, cb, r, bc); } static int udplite_diag_dump_one(struct sk_buff *in_skb, const struct nlmsghdr *nlh, - struct inet_diag_req *req) + struct inet_diag_req_v2 *req) { return udp_dump_one(&udplite_table, in_skb, nlh, req); } -- cgit v0.10.2 From 3b09c84cb622ffbcdb5d541986b1eaf7d5812602 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Tue, 10 Jan 2012 22:37:26 +0000 Subject: inet_diag: Rename inet_diag_req_compat into inet_diag_req Signed-off-by: Pavel Emelyanov Signed-off-by: David S. Miller diff --git a/include/linux/inet_diag.h b/include/linux/inet_diag.h index a5b7e91..f1362b5 100644 --- a/include/linux/inet_diag.h +++ b/include/linux/inet_diag.h @@ -22,7 +22,7 @@ struct inet_diag_sockid { /* Request structure */ -struct inet_diag_req_compat { +struct inet_diag_req { __u8 idiag_family; /* Family of addresses. */ __u8 idiag_src_len; __u8 idiag_dst_len; diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index cf23a7c..fcf2818 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -909,10 +909,10 @@ static inline int inet_diag_type2proto(int type) static int inet_diag_dump_compat(struct sk_buff *skb, struct netlink_callback *cb) { - struct inet_diag_req_compat *rc = NLMSG_DATA(cb->nlh); + struct inet_diag_req *rc = NLMSG_DATA(cb->nlh); struct inet_diag_req_v2 req; struct nlattr *bc = NULL; - int hdrlen = sizeof(struct inet_diag_req_compat); + int hdrlen = sizeof(struct inet_diag_req); req.sdiag_family = AF_UNSPEC; /* compatibility */ req.sdiag_protocol = inet_diag_type2proto(cb->nlh->nlmsg_type); @@ -929,7 +929,7 @@ static int inet_diag_dump_compat(struct sk_buff *skb, struct netlink_callback *c static int inet_diag_get_exact_compat(struct sk_buff *in_skb, const struct nlmsghdr *nlh) { - struct inet_diag_req_compat *rc = NLMSG_DATA(nlh); + struct inet_diag_req *rc = NLMSG_DATA(nlh); struct inet_diag_req_v2 req; req.sdiag_family = rc->idiag_family; @@ -943,7 +943,7 @@ static int inet_diag_get_exact_compat(struct sk_buff *in_skb, static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh) { - int hdrlen = sizeof(struct inet_diag_req_compat); + int hdrlen = sizeof(struct inet_diag_req); if (nlh->nlmsg_type >= INET_DIAG_GETSOCK_MAX || nlmsg_len(nlh) < hdrlen) -- cgit v0.10.2 From cf778b00e96df6d64f8e21b8395d1f8a859ecdc7 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 12 Jan 2012 04:41:32 +0000 Subject: net: reintroduce missing rcu_assign_pointer() calls commit a9b3cd7f32 (rcu: convert uses of rcu_assign_pointer(x, NULL) to RCU_INIT_POINTER) did a lot of incorrect changes, since it did a complete conversion of rcu_assign_pointer(x, y) to RCU_INIT_POINTER(x, y). We miss needed barriers, even on x86, when y is not NULL. Signed-off-by: Eric Dumazet CC: Stephen Hemminger CC: Paul E. McKenney Signed-off-by: David S. Miller diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index abf4393..f3dbd4f 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -1177,9 +1177,9 @@ static ssize_t store_xps_map(struct netdev_queue *queue, nonempty = 1; } - if (nonempty) - RCU_INIT_POINTER(dev->xps_maps, new_dev_maps); - else { + if (nonempty) { + rcu_assign_pointer(dev->xps_maps, new_dev_maps); + } else { kfree(new_dev_maps); RCU_INIT_POINTER(dev->xps_maps, NULL); } diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 0d38808..556b082 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -765,7 +765,7 @@ int __netpoll_setup(struct netpoll *np) } /* last thing to do is link it to the net device structure */ - RCU_INIT_POINTER(ndev->npinfo, npinfo); + rcu_assign_pointer(ndev->npinfo, npinfo); return 0; diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 2ab16e1..74d321a 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -388,7 +388,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa) } ifa->ifa_next = dn_db->ifa_list; - RCU_INIT_POINTER(dn_db->ifa_list, ifa); + rcu_assign_pointer(dn_db->ifa_list, ifa); dn_ifaddr_notify(RTM_NEWADDR, ifa); blocking_notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa); @@ -1093,7 +1093,7 @@ static struct dn_dev *dn_dev_create(struct net_device *dev, int *err) memcpy(&dn_db->parms, p, sizeof(struct dn_dev_parms)); - RCU_INIT_POINTER(dev->dn_ptr, dn_db); + rcu_assign_pointer(dev->dn_ptr, dn_db); dn_db->dev = dev; init_timer(&dn_db->timer); diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 65f01dc..e41c40f 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -258,7 +258,7 @@ static struct in_device *inetdev_init(struct net_device *dev) ip_mc_up(in_dev); /* we can receive as soon as ip_ptr is set -- do this last */ - RCU_INIT_POINTER(dev->ip_ptr, in_dev); + rcu_assign_pointer(dev->ip_ptr, in_dev); out: return in_dev; out_kfree: diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index d04b13a..2b555a5 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -205,7 +205,7 @@ static inline struct tnode *node_parent_rcu(const struct rt_trie_node *node) return (struct tnode *)(parent & ~NODE_TYPE_MASK); } -/* Same as RCU_INIT_POINTER +/* Same as rcu_assign_pointer * but that macro() assumes that value is a pointer. */ static inline void node_set_parent(struct rt_trie_node *node, struct tnode *ptr) @@ -529,7 +529,7 @@ static void tnode_put_child_reorg(struct tnode *tn, int i, struct rt_trie_node * if (n) node_set_parent(n, tn); - RCU_INIT_POINTER(tn->child[i], n); + rcu_assign_pointer(tn->child[i], n); } #define MAX_WORK 10 @@ -1015,7 +1015,7 @@ static void trie_rebalance(struct trie *t, struct tnode *tn) tp = node_parent((struct rt_trie_node *) tn); if (!tp) - RCU_INIT_POINTER(t->trie, (struct rt_trie_node *)tn); + rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn); tnode_free_flush(); if (!tp) @@ -1027,7 +1027,7 @@ static void trie_rebalance(struct trie *t, struct tnode *tn) if (IS_TNODE(tn)) tn = (struct tnode *)resize(t, (struct tnode *)tn); - RCU_INIT_POINTER(t->trie, (struct rt_trie_node *)tn); + rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn); tnode_free_flush(); } @@ -1164,7 +1164,7 @@ static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen) put_child(t, (struct tnode *)tp, cindex, (struct rt_trie_node *)tn); } else { - RCU_INIT_POINTER(t->trie, (struct rt_trie_node *)tn); + rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn); tp = tn; } } diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 5104bc0..450e5d2 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -1249,7 +1249,7 @@ void ip_mc_inc_group(struct in_device *in_dev, __be32 addr) im->next_rcu = in_dev->mc_list; in_dev->mc_count++; - RCU_INIT_POINTER(in_dev->mc_list, im); + rcu_assign_pointer(in_dev->mc_list, im); #ifdef CONFIG_IP_MULTICAST igmpv3_del_delrec(in_dev, im->multiaddr); @@ -1821,7 +1821,7 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr) iml->next_rcu = inet->mc_list; iml->sflist = NULL; iml->sfmode = MCAST_EXCLUDE; - RCU_INIT_POINTER(inet->mc_list, iml); + rcu_assign_pointer(inet->mc_list, iml); ip_mc_inc_group(in_dev, addr); err = 0; done: @@ -2008,7 +2008,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct atomic_sub(IP_SFLSIZE(psl->sl_max), &sk->sk_omem_alloc); kfree_rcu(psl, rcu); } - RCU_INIT_POINTER(pmc->sflist, newpsl); + rcu_assign_pointer(pmc->sflist, newpsl); psl = newpsl; } rv = 1; /* > 0 for insert logic below if sl_count is 0 */ @@ -2111,7 +2111,7 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex) } else (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode, 0, NULL, 0); - RCU_INIT_POINTER(pmc->sflist, newpsl); + rcu_assign_pointer(pmc->sflist, newpsl); pmc->sfmode = msf->imsf_fmode; err = 0; done: diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 413ed1b..22a1993 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -231,7 +231,7 @@ static void ipip_tunnel_unlink(struct ipip_net *ipn, struct ip_tunnel *t) (iter = rtnl_dereference(*tp)) != NULL; tp = &iter->next) { if (t == iter) { - RCU_INIT_POINTER(*tp, t->next); + rcu_assign_pointer(*tp, t->next); break; } } @@ -241,8 +241,8 @@ static void ipip_tunnel_link(struct ipip_net *ipn, struct ip_tunnel *t) { struct ip_tunnel __rcu **tp = ipip_bucket(ipn, t); - RCU_INIT_POINTER(t->next, rtnl_dereference(*tp)); - RCU_INIT_POINTER(*tp, t); + rcu_assign_pointer(t->next, rtnl_dereference(*tp)); + rcu_assign_pointer(*tp, t); } static struct ip_tunnel * ipip_tunnel_locate(struct net *net, @@ -792,7 +792,7 @@ static int __net_init ipip_fb_tunnel_init(struct net_device *dev) return -ENOMEM; dev_hold(dev); - RCU_INIT_POINTER(ipn->tunnels_wc[0], tunnel); + rcu_assign_pointer(ipn->tunnels_wc[0], tunnel); return 0; } diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 8e54490..7bc2db6 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1225,7 +1225,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi ret = ip_ra_control(sk, 1, mrtsock_destruct); if (ret == 0) { - RCU_INIT_POINTER(mrt->mroute_sk, sk); + rcu_assign_pointer(mrt->mroute_sk, sk); IPV4_DEVCONF_ALL(net, MC_FORWARDING)++; } rtnl_unlock(); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 0ba0866..a225d5e 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -429,7 +429,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) ndev->tstamp = jiffies; addrconf_sysctl_register(ndev); /* protected by rtnl_lock */ - RCU_INIT_POINTER(dev->ip6_ptr, ndev); + rcu_assign_pointer(dev->ip6_ptr, ndev); /* Join all-node multicast group */ ipv6_dev_mc_inc(dev, &in6addr_linklocal_allnodes); diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index e1f7761..aa21da6 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -218,8 +218,8 @@ ip6_tnl_link(struct ip6_tnl_net *ip6n, struct ip6_tnl *t) { struct ip6_tnl __rcu **tp = ip6_tnl_bucket(ip6n, &t->parms); - RCU_INIT_POINTER(t->next , rtnl_dereference(*tp)); - RCU_INIT_POINTER(*tp, t); + rcu_assign_pointer(t->next , rtnl_dereference(*tp)); + rcu_assign_pointer(*tp, t); } /** @@ -237,7 +237,7 @@ ip6_tnl_unlink(struct ip6_tnl_net *ip6n, struct ip6_tnl *t) (iter = rtnl_dereference(*tp)) != NULL; tp = &iter->next) { if (t == iter) { - RCU_INIT_POINTER(*tp, t->next); + rcu_assign_pointer(*tp, t->next); break; } } @@ -1450,7 +1450,7 @@ static int __net_init ip6_fb_tnl_dev_init(struct net_device *dev) t->parms.proto = IPPROTO_IPV6; dev_hold(dev); - RCU_INIT_POINTER(ip6n->tnls_wc[0], t); + rcu_assign_pointer(ip6n->tnls_wc[0], t); return 0; } diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index a4894f4..d02f7e4 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -131,7 +131,7 @@ static mh_filter_t __rcu *mh_filter __read_mostly; int rawv6_mh_filter_register(mh_filter_t filter) { - RCU_INIT_POINTER(mh_filter, filter); + rcu_assign_pointer(mh_filter, filter); return 0; } EXPORT_SYMBOL(rawv6_mh_filter_register); diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 3b6dac9..133768e 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -182,7 +182,7 @@ static void ipip6_tunnel_unlink(struct sit_net *sitn, struct ip_tunnel *t) (iter = rtnl_dereference(*tp)) != NULL; tp = &iter->next) { if (t == iter) { - RCU_INIT_POINTER(*tp, t->next); + rcu_assign_pointer(*tp, t->next); break; } } @@ -192,8 +192,8 @@ static void ipip6_tunnel_link(struct sit_net *sitn, struct ip_tunnel *t) { struct ip_tunnel __rcu **tp = ipip6_bucket(sitn, t); - RCU_INIT_POINTER(t->next, rtnl_dereference(*tp)); - RCU_INIT_POINTER(*tp, t); + rcu_assign_pointer(t->next, rtnl_dereference(*tp)); + rcu_assign_pointer(*tp, t); } static void ipip6_tunnel_clone_6rd(struct net_device *dev, struct sit_net *sitn) @@ -393,7 +393,7 @@ ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg) p->addr = a->addr; p->flags = a->flags; t->prl_count++; - RCU_INIT_POINTER(t->prl, p); + rcu_assign_pointer(t->prl, p); out: return err; } @@ -1177,7 +1177,7 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) if (!dev->tstats) return -ENOMEM; dev_hold(dev); - RCU_INIT_POINTER(sitn->tunnels_wc[0], tunnel); + rcu_assign_pointer(sitn->tunnels_wc[0], tunnel); return 0; } diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 96debba..1068f66 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -332,7 +332,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, status = WLAN_STATUS_SUCCESS; /* activate it for RX */ - RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx); + rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx); if (timeout) mod_timer(&tid_agg_rx->session_timer, TU_TO_EXP_TIME(timeout)); diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 850bb96..e60df48 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -616,7 +616,7 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, sdata->vif.bss_conf.dtim_period = new->dtim_period; - RCU_INIT_POINTER(sdata->u.ap.beacon, new); + rcu_assign_pointer(sdata->u.ap.beacon, new); synchronize_rcu(); @@ -1033,7 +1033,7 @@ static int ieee80211_change_station(struct wiphy *wiphy, return -EBUSY; } - RCU_INIT_POINTER(vlansdata->u.vlan.sta, sta); + rcu_assign_pointer(vlansdata->u.vlan.sta, sta); } sta->sdata = vlansdata; diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index f8a32bf..b3d76b7 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -207,7 +207,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, *pos++ = 0; /* U-APSD no in use */ } - RCU_INIT_POINTER(ifibss->presp, skb); + rcu_assign_pointer(ifibss->presp, skb); sdata->vif.bss_conf.beacon_int = beacon_int; sdata->vif.bss_conf.basic_rates = basic_rates; diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index b197136..3c428d4 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -73,7 +73,7 @@ static int sta_info_hash_del(struct ieee80211_local *local, if (!s) return -ENOENT; if (s == sta) { - RCU_INIT_POINTER(local->sta_hash[STA_HASH(sta->sta.addr)], + rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], s->hnext); return 0; } @@ -83,7 +83,7 @@ static int sta_info_hash_del(struct ieee80211_local *local, s = rcu_dereference_protected(s->hnext, lockdep_is_held(&local->sta_mtx)); if (rcu_access_pointer(s->hnext)) { - RCU_INIT_POINTER(s->hnext, sta->hnext); + rcu_assign_pointer(s->hnext, sta->hnext); return 0; } @@ -226,7 +226,7 @@ static void sta_info_hash_add(struct ieee80211_local *local, { lockdep_assert_held(&local->sta_mtx); sta->hnext = local->sta_hash[STA_HASH(sta->sta.addr)]; - RCU_INIT_POINTER(local->sta_hash[STA_HASH(sta->sta.addr)], sta); + rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta); } static void sta_unblock(struct work_struct *wk) diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index e875f89..76613f5 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -777,7 +777,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, if (exp->helper) { help = nf_ct_helper_ext_add(ct, GFP_ATOMIC); if (help) - RCU_INIT_POINTER(help->helper, exp->helper); + rcu_assign_pointer(help->helper, exp->helper); } #ifdef CONFIG_NF_CONNTRACK_MARK diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c index b62c414..14af632 100644 --- a/net/netfilter/nf_conntrack_ecache.c +++ b/net/netfilter/nf_conntrack_ecache.c @@ -91,7 +91,7 @@ int nf_conntrack_register_notifier(struct net *net, ret = -EBUSY; goto out_unlock; } - RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb, new); + rcu_assign_pointer(net->ct.nf_conntrack_event_cb, new); mutex_unlock(&nf_ct_ecache_mutex); return ret; @@ -128,7 +128,7 @@ int nf_ct_expect_register_notifier(struct net *net, ret = -EBUSY; goto out_unlock; } - RCU_INIT_POINTER(net->ct.nf_expect_event_cb, new); + rcu_assign_pointer(net->ct.nf_expect_event_cb, new); mutex_unlock(&nf_ct_ecache_mutex); return ret; diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c index 4605c94..641ff5f 100644 --- a/net/netfilter/nf_conntrack_extend.c +++ b/net/netfilter/nf_conntrack_extend.c @@ -169,7 +169,7 @@ int nf_ct_extend_register(struct nf_ct_ext_type *type) before updating alloc_size */ type->alloc_size = ALIGN(sizeof(struct nf_ct_ext), type->align) + type->len; - RCU_INIT_POINTER(nf_ct_ext_types[type->id], type); + rcu_assign_pointer(nf_ct_ext_types[type->id], type); update_alloc_size(type); out: mutex_unlock(&nf_ct_ext_type_mutex); diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index c9e0de0..299fec9 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -157,7 +157,7 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl, memset(&help->help, 0, sizeof(help->help)); } - RCU_INIT_POINTER(help->helper, helper); + rcu_assign_pointer(help->helper, helper); out: return ret; } diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index e07dc3a..2a4834b 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1172,7 +1172,7 @@ ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[]) return -EOPNOTSUPP; } - RCU_INIT_POINTER(help->helper, helper); + rcu_assign_pointer(help->helper, helper); return 0; } diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index ce0c406..957374a 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c @@ -55,7 +55,7 @@ int nf_log_register(u_int8_t pf, struct nf_logger *logger) llog = rcu_dereference_protected(nf_loggers[pf], lockdep_is_held(&nf_log_mutex)); if (llog == NULL) - RCU_INIT_POINTER(nf_loggers[pf], logger); + rcu_assign_pointer(nf_loggers[pf], logger); } mutex_unlock(&nf_log_mutex); @@ -92,7 +92,7 @@ int nf_log_bind_pf(u_int8_t pf, const struct nf_logger *logger) mutex_unlock(&nf_log_mutex); return -ENOENT; } - RCU_INIT_POINTER(nf_loggers[pf], logger); + rcu_assign_pointer(nf_loggers[pf], logger); mutex_unlock(&nf_log_mutex); return 0; } @@ -250,7 +250,7 @@ static int nf_log_proc_dostring(ctl_table *table, int write, mutex_unlock(&nf_log_mutex); return -ENOENT; } - RCU_INIT_POINTER(nf_loggers[tindex], logger); + rcu_assign_pointer(nf_loggers[tindex], logger); mutex_unlock(&nf_log_mutex); } else { mutex_lock(&nf_log_mutex); diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index 99ffd28..b3a7db6 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -40,7 +40,7 @@ int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh) else if (old) ret = -EBUSY; else { - RCU_INIT_POINTER(queue_handler[pf], qh); + rcu_assign_pointer(queue_handler[pf], qh); ret = 0; } mutex_unlock(&queue_handler_mutex); diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index c879c1a..b4f8d84 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -59,7 +59,7 @@ int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n) nfnl_unlock(); return -EBUSY; } - RCU_INIT_POINTER(subsys_table[n->subsys_id], n); + rcu_assign_pointer(subsys_table[n->subsys_id], n); nfnl_unlock(); return 0; @@ -210,7 +210,7 @@ static int __net_init nfnetlink_net_init(struct net *net) if (!nfnl) return -ENOMEM; net->nfnl_stash = nfnl; - RCU_INIT_POINTER(net->nfnl, nfnl); + rcu_assign_pointer(net->nfnl, nfnl); return 0; } diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index 3820411..d8d4243 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c @@ -282,7 +282,7 @@ int __init netlbl_domhsh_init(u32 size) INIT_LIST_HEAD(&hsh_tbl->tbl[iter]); spin_lock(&netlbl_domhsh_lock); - RCU_INIT_POINTER(netlbl_domhsh, hsh_tbl); + rcu_assign_pointer(netlbl_domhsh, hsh_tbl); spin_unlock(&netlbl_domhsh_lock); return 0; @@ -330,7 +330,7 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, &rcu_dereference(netlbl_domhsh)->tbl[bkt]); } else { INIT_LIST_HEAD(&entry->list); - RCU_INIT_POINTER(netlbl_domhsh_def, entry); + rcu_assign_pointer(netlbl_domhsh_def, entry); } if (entry->type == NETLBL_NLTYPE_ADDRSELECT) { diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 4b5fa0f..e7ff694 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -354,7 +354,7 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex) INIT_LIST_HEAD(&iface->list); if (netlbl_unlhsh_rcu_deref(netlbl_unlhsh_def) != NULL) goto add_iface_failure; - RCU_INIT_POINTER(netlbl_unlhsh_def, iface); + rcu_assign_pointer(netlbl_unlhsh_def, iface); } spin_unlock(&netlbl_unlhsh_lock); @@ -1447,11 +1447,9 @@ int __init netlbl_unlabel_init(u32 size) for (iter = 0; iter < hsh_tbl->size; iter++) INIT_LIST_HEAD(&hsh_tbl->tbl[iter]); - rcu_read_lock(); spin_lock(&netlbl_unlhsh_lock); - RCU_INIT_POINTER(netlbl_unlhsh, hsh_tbl); + rcu_assign_pointer(netlbl_unlhsh, hsh_tbl); spin_unlock(&netlbl_unlhsh_lock); - rcu_read_unlock(); register_netdevice_notifier(&netlbl_unlhsh_netdev_notifier); diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index bf10ea8..d65f699 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c @@ -480,7 +480,7 @@ int __init_or_module phonet_proto_register(unsigned int protocol, if (proto_tab[protocol]) err = -EBUSY; else - RCU_INIT_POINTER(proto_tab[protocol], pp); + rcu_assign_pointer(proto_tab[protocol], pp); mutex_unlock(&proto_tab_lock); return err; diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index c582761..9b9a85e 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c @@ -390,7 +390,7 @@ int phonet_route_add(struct net_device *dev, u8 daddr) daddr = daddr >> 2; mutex_lock(&routes->lock); if (routes->table[daddr] == NULL) { - RCU_INIT_POINTER(routes->table[daddr], dev); + rcu_assign_pointer(routes->table[daddr], dev); dev_hold(dev); err = 0; } diff --git a/net/phonet/socket.c b/net/phonet/socket.c index 3f8d0b1..4c7eff3 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c @@ -680,7 +680,7 @@ int pn_sock_bind_res(struct sock *sk, u8 res) mutex_lock(&resource_mutex); if (pnres.sk[res] == NULL) { sock_hold(sk); - RCU_INIT_POINTER(pnres.sk[res], sk); + rcu_assign_pointer(pnres.sk[res], sk); ret = 0; } mutex_unlock(&resource_mutex); diff --git a/net/socket.c b/net/socket.c index e56162c..28a96af 100644 --- a/net/socket.c +++ b/net/socket.c @@ -2492,7 +2492,7 @@ int sock_register(const struct net_proto_family *ops) lockdep_is_held(&net_family_lock))) err = -EEXIST; else { - RCU_INIT_POINTER(net_families[ops->family], ops); + rcu_assign_pointer(net_families[ops->family], ops); err = 0; } spin_unlock(&net_family_lock); diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index afb5655..db0efde 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -122,7 +122,7 @@ gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx) if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)) return; gss_get_ctx(ctx); - RCU_INIT_POINTER(gss_cred->gc_ctx, ctx); + rcu_assign_pointer(gss_cred->gc_ctx, ctx); set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); smp_mb__before_clear_bit(); clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index e0d747a..637f11a 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -2927,7 +2927,7 @@ static int __net_init xfrm_user_net_init(struct net *net) if (nlsk == NULL) return -ENOMEM; net->xfrm.nlsk_stash = nlsk; /* Don't set to NULL */ - RCU_INIT_POINTER(net->xfrm.nlsk, nlsk); + rcu_assign_pointer(net->xfrm.nlsk, nlsk); return 0; } -- cgit v0.10.2 From 1398eee08222a038fa5f017900f387e81f6e3ff4 Mon Sep 17 00:00:00 2001 From: Glauber Costa Date: Thu, 12 Jan 2012 02:16:06 +0000 Subject: net: decrement memcg jump label when limit, not usage, is changed The logic of the current code is that whenever we destroy a cgroup that had its limit set (set meaning different than maximum), we should decrement the jump_label counter. Otherwise we assume it was never incremented. But what the code actually does is test for RES_USAGE instead of RES_LIMIT. Usage being different than maximum is likely to be true most of the time. The effect of this is that the key must become negative, and since the jump_label test says: !!atomic_read(&key->enabled); we'll have jump_labels still on when no one else is using this functionality. Signed-off-by: Glauber Costa CC: David S. Miller Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp_memcontrol.c b/net/ipv4/tcp_memcontrol.c index 7fed04f..4997878 100644 --- a/net/ipv4/tcp_memcontrol.c +++ b/net/ipv4/tcp_memcontrol.c @@ -108,7 +108,7 @@ void tcp_destroy_cgroup(struct cgroup *cgrp, struct cgroup_subsys *ss) tcp = tcp_from_cgproto(cg_proto); percpu_counter_destroy(&tcp->tcp_sockets_allocated); - val = res_counter_read_u64(&tcp->tcp_memory_allocated, RES_USAGE); + val = res_counter_read_u64(&tcp->tcp_memory_allocated, RES_LIMIT); if (val != RESOURCE_MAX) jump_label_dec(&memcg_socket_limit_enabled); -- cgit v0.10.2 From eb8a54a78e974e1af3e17fa38bb74d3747c5c1bd Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Thu, 12 Jan 2012 15:23:04 -0800 Subject: phylib: introduce mdiobus_alloc_size() Introduce function mdiobus_alloc_size() as an alternative to mdiobus_alloc(). Most callers of mdiobus_alloc() also allocate a private data structure, and then manually point bus->priv to this object. mdiobus_alloc_size() combines the two operations into one, which simplifies memory management. The original mdiobus_alloc() now just calls mdiobus_alloc_size(0). Signed-off-by: Timur Tabi Signed-off-by: David S. Miller diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 6c58da2..88cc5db 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -37,22 +37,36 @@ #include /** - * mdiobus_alloc - allocate a mii_bus structure + * mdiobus_alloc_size - allocate a mii_bus structure * * Description: called by a bus driver to allocate an mii_bus * structure to fill in. + * + * 'size' is an an extra amount of memory to allocate for private storage. + * If non-zero, then bus->priv is points to that memory. */ -struct mii_bus *mdiobus_alloc(void) +struct mii_bus *mdiobus_alloc_size(size_t size) { struct mii_bus *bus; + size_t aligned_size = ALIGN(sizeof(*bus), NETDEV_ALIGN); + size_t alloc_size; + + /* If we alloc extra space, it should be aligned */ + if (size) + alloc_size = aligned_size + size; + else + alloc_size = sizeof(*bus); - bus = kzalloc(sizeof(*bus), GFP_KERNEL); - if (bus != NULL) + bus = kzalloc(alloc_size, GFP_KERNEL); + if (bus) { bus->state = MDIOBUS_ALLOCATED; + if (size) + bus->priv = (void *)bus + aligned_size; + } return bus; } -EXPORT_SYMBOL(mdiobus_alloc); +EXPORT_SYMBOL(mdiobus_alloc_size); /** * mdiobus_release - mii_bus device release callback diff --git a/include/linux/phy.h b/include/linux/phy.h index 79f337c..c599f7ec 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -129,7 +129,12 @@ struct mii_bus { }; #define to_mii_bus(d) container_of(d, struct mii_bus, dev) -struct mii_bus *mdiobus_alloc(void); +struct mii_bus *mdiobus_alloc_size(size_t); +static inline struct mii_bus *mdiobus_alloc(void) +{ + return mdiobus_alloc_size(0); +} + int mdiobus_register(struct mii_bus *bus); void mdiobus_unregister(struct mii_bus *bus); void mdiobus_free(struct mii_bus *bus); -- cgit v0.10.2 From db83d136d7f7534857cd9c6e588adc08a428b190 Mon Sep 17 00:00:00 2001 From: Manfred Rudigier Date: Mon, 9 Jan 2012 23:26:50 +0000 Subject: gianfar: Fix missing sock reference when processing TX time stamps When there is not enough headroom in the skb a private copy will be made. However, the private copy had no reference to the socket and consequently no time stamp could be queued on the socket error queue during the skb_tstamp_tx function. This patch fixes this issue by also stealing the sock reference from the original skb after making the private copy. Signed-off-by: Manfred Rudigier Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index e01cdaa..2b3c129 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -2086,6 +2086,10 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) kfree_skb(skb); return NETDEV_TX_OK; } + + /* Steal sock reference for processing TX time stamps */ + swap(skb_new->sk, skb->sk); + swap(skb_new->destructor, skb->destructor); kfree_skb(skb); skb = skb_new; } -- cgit v0.10.2 From 9c4886e5e63bbecea0b560829a96f37e8d9ddd7c Mon Sep 17 00:00:00 2001 From: Manfred Rudigier Date: Mon, 9 Jan 2012 23:26:51 +0000 Subject: gianfar: Fix invalid TX frames returned on error queue when time stamping When TX time stamping for PTP messages is enabled on a socket, a time stamp is returned on the socket error queue to the user space application after the frame was transmitted. The transmitted frame is also returned on the error queue so that an application knows to which frame the time stamp belongs. In the current implementation the TxFCB is immediately followed by the frame. Since the eTSEC inserts the TX time stamp 8 bytes after the TxFCB, parts of the frame have been overwritten and an invalid frame was returned on the socket error queue. This patch fixes the described problem by adding additional 16 padding bytes between the TxFCB and the frame for all messages sent from a time stamping enabled socket (other sockets are not affected). Signed-off-by: Manfred Rudigier Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 2b3c129..39d160d 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -1984,7 +1984,8 @@ static inline struct txfcb *gfar_add_fcb(struct sk_buff *skb) return fcb; } -static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb) +static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb, + int fcb_length) { u8 flags = 0; @@ -2006,7 +2007,7 @@ static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb) * frame (skb->data) and the start of the IP hdr. * l4os is the distance between the start of the * l3 hdr and the l4 hdr */ - fcb->l3os = (u16)(skb_network_offset(skb) - GMAC_FCB_LEN); + fcb->l3os = (u16)(skb_network_offset(skb) - fcb_length); fcb->l4os = skb_network_header_len(skb); fcb->flags = flags; @@ -2046,7 +2047,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) int i, rq = 0, do_tstamp = 0; u32 bufaddr; unsigned long flags; - unsigned int nr_frags, nr_txbds, length; + unsigned int nr_frags, nr_txbds, length, fcb_length = GMAC_FCB_LEN; /* * TOE=1 frames larger than 2500 bytes may see excess delays @@ -2070,17 +2071,19 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) /* check if time stamp should be generated */ if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && - priv->hwts_tx_en)) + priv->hwts_tx_en)) { do_tstamp = 1; + fcb_length = GMAC_FCB_LEN + GMAC_TXPAL_LEN; + } /* make space for additional header when fcb is needed */ if (((skb->ip_summed == CHECKSUM_PARTIAL) || vlan_tx_tag_present(skb) || unlikely(do_tstamp)) && - (skb_headroom(skb) < GMAC_FCB_LEN)) { + (skb_headroom(skb) < fcb_length)) { struct sk_buff *skb_new; - skb_new = skb_realloc_headroom(skb, GMAC_FCB_LEN); + skb_new = skb_realloc_headroom(skb, fcb_length); if (!skb_new) { dev->stats.tx_errors++; kfree_skb(skb); @@ -2158,6 +2161,12 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) lstatus = txbdp_start->lstatus; } + /* Add TxPAL between FCB and frame if required */ + if (unlikely(do_tstamp)) { + skb_push(skb, GMAC_TXPAL_LEN); + memset(skb->data, 0, GMAC_TXPAL_LEN); + } + /* Set up checksumming */ if (CHECKSUM_PARTIAL == skb->ip_summed) { fcb = gfar_add_fcb(skb); @@ -2168,7 +2177,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) skb_checksum_help(skb); } else { lstatus |= BD_LFLAG(TXBD_TOE); - gfar_tx_checksum(skb, fcb); + gfar_tx_checksum(skb, fcb, fcb_length); } } @@ -2200,9 +2209,9 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) * the full frame length. */ if (unlikely(do_tstamp)) { - txbdp_tstamp->bufPtr = txbdp_start->bufPtr + GMAC_FCB_LEN; + txbdp_tstamp->bufPtr = txbdp_start->bufPtr + fcb_length; txbdp_tstamp->lstatus |= BD_LFLAG(TXBD_READY) | - (skb_headlen(skb) - GMAC_FCB_LEN); + (skb_headlen(skb) - fcb_length); lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | GMAC_FCB_LEN; } else { lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | skb_headlen(skb); @@ -2494,7 +2503,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) { next = next_txbd(bdp, base, tx_ring_size); - buflen = next->length + GMAC_FCB_LEN; + buflen = next->length + GMAC_FCB_LEN + GMAC_TXPAL_LEN; } else buflen = bdp->length; @@ -2506,6 +2515,7 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) u64 *ns = (u64*) (((u32)skb->data + 0x10) & ~0x7); memset(&shhwtstamps, 0, sizeof(shhwtstamps)); shhwtstamps.hwtstamp = ns_to_ktime(*ns); + skb_pull(skb, GMAC_FCB_LEN + GMAC_TXPAL_LEN); skb_tstamp_tx(skb, &shhwtstamps); bdp->lstatus &= BD_LFLAG(TXBD_WRAP); bdp = next; diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h index fe7ac3a..40c33a7 100644 --- a/drivers/net/ethernet/freescale/gianfar.h +++ b/drivers/net/ethernet/freescale/gianfar.h @@ -63,6 +63,9 @@ struct ethtool_rx_list { /* Length for FCB */ #define GMAC_FCB_LEN 8 +/* Length for TxPAL */ +#define GMAC_TXPAL_LEN 16 + /* Default padding amount */ #define DEFAULT_PADDING 2 -- cgit v0.10.2 From 72092cc45378176ba700034c91b7af2db524df26 Mon Sep 17 00:00:00 2001 From: Manfred Rudigier Date: Mon, 9 Jan 2012 23:52:15 +0000 Subject: dp83640: Fix NOHZ local_softirq_pending 08 warning Similar problem as in 481a8199142c050b72bff8a1956a49fd0a75bbe0 ("can: fix NOHZ local_softirq_pending 08 warning"). This fix replaces netif_rx() with netif_rx_ni() which has to be used from process/softirq context. Signed-off-by: Manfred Rudigier Signed-off-by: David S. Miller diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index 9663e0b..ba3c591 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -1159,7 +1159,7 @@ static void rx_timestamp_work(struct work_struct *work) } } spin_unlock_irqrestore(&dp83640->rx_lock, flags); - netif_rx(skb); + netif_rx_ni(skb); } /* Clear out expired time stamps. */ -- cgit v0.10.2 From ddecf0f4db44ef94847a62d6ecf74456b4dcc66f Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 6 Jan 2012 06:31:44 +0000 Subject: net_sched: sfq: add optional RED on top of SFQ Adds an optional Random Early Detection on each SFQ flow queue. Traditional SFQ limits count of packets, while RED permits to also control number of bytes per flow, and adds ECN capability as well. 1) We dont handle the idle time management in this RED implementation, since each 'new flow' begins with a null qavg. We really want to address backlogged flows. 2) if headdrop is selected, we try to ecn mark first packet instead of currently enqueued packet. This gives faster feedback for tcp flows compared to traditional RED [ marking the last packet in queue ] Example of use : tc qdisc add dev $DEV parent 1:1 handle 10: est 1sec 4sec sfq \ limit 3000 headdrop flows 512 divisor 16384 \ redflowlimit 100000 min 8000 max 60000 probability 0.20 ecn qdisc sfq 10: parent 1:1 limit 3000p quantum 1514b depth 127 headdrop flows 512/16384 divisor 16384 ewma 6 min 8000b max 60000b probability 0.2 ecn prob_mark 0 prob_mark_head 4876 prob_drop 6131 forced_mark 0 forced_mark_head 0 forced_drop 0 Sent 1175211782 bytes 777537 pkt (dropped 6131, overlimits 11007 requeues 0) rate 99483Kbit 8219pps backlog 689392b 456p requeues 0 In this test, with 64 netperf TCP_STREAM sessions, 50% using ECN enabled flows, we can see number of packets CE marked is smaller than number of drops (for non ECN flows) If same test is run, without RED, we can check backlog is much bigger. qdisc sfq 10: parent 1:1 limit 3000p quantum 1514b depth 127 headdrop flows 512/16384 divisor 16384 Sent 1148683617 bytes 795006 pkt (dropped 0, overlimits 0 requeues 0) rate 98429Kbit 8521pps backlog 1221290b 841p requeues 0 Signed-off-by: Eric Dumazet CC: Stephen Hemminger CC: Dave Taht Tested-by: Dave Taht Signed-off-by: David S. Miller diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index 8f1b928..0d5b793 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -162,10 +162,30 @@ struct tc_sfq_qopt { unsigned flows; /* Maximal number of flows */ }; +struct tc_sfqred_stats { + __u32 prob_drop; /* Early drops, below max threshold */ + __u32 forced_drop; /* Early drops, after max threshold */ + __u32 prob_mark; /* Marked packets, below max threshold */ + __u32 forced_mark; /* Marked packets, after max threshold */ + __u32 prob_mark_head; /* Marked packets, below max threshold */ + __u32 forced_mark_head;/* Marked packets, after max threshold */ +}; + struct tc_sfq_qopt_v1 { struct tc_sfq_qopt v0; unsigned int depth; /* max number of packets per flow */ unsigned int headdrop; +/* SFQRED parameters */ + __u32 limit; /* HARD maximal flow queue length (bytes) */ + __u32 qth_min; /* Min average length threshold (bytes) */ + __u32 qth_max; /* Max average length threshold (bytes) */ + unsigned char Wlog; /* log(W) */ + unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */ + unsigned char Scell_log; /* cell size for idle damping */ + unsigned char flags; + __u32 max_P; /* probability, high resolution */ +/* SFQRED stats */ + struct tc_sfqred_stats stats; }; diff --git a/include/net/red.h b/include/net/red.h index baab385..28068ec 100644 --- a/include/net/red.h +++ b/include/net/red.h @@ -199,7 +199,8 @@ static inline void red_set_parms(struct red_parms *p, p->Scell_log = Scell_log; p->Scell_max = (255 << Scell_log); - memcpy(p->Stab, stab, sizeof(p->Stab)); + if (stab) + memcpy(p->Stab, stab, sizeof(p->Stab)); } static inline int red_is_idling(const struct red_vars *v) diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 0a79640..67494ae 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -24,6 +24,7 @@ #include #include #include +#include /* Stochastic Fairness Queuing algorithm. @@ -108,24 +109,30 @@ struct sfq_slot { struct sfq_head dep; /* anchor in dep[] chains */ unsigned short hash; /* hash value (index in ht[]) */ short allot; /* credit for this slot */ + + unsigned int backlog; + struct red_vars vars; }; struct sfq_sched_data { /* frequently used fields */ int limit; /* limit of total number of packets in this qdisc */ unsigned int divisor; /* number of slots in hash table */ - unsigned int maxflows; /* number of flows in flows array */ - int headdrop; - int maxdepth; /* limit of packets per flow */ + u8 headdrop; + u8 maxdepth; /* limit of packets per flow */ u32 perturbation; - struct tcf_proto *filter_list; - sfq_index cur_depth; /* depth of longest slot */ + u8 cur_depth; /* depth of longest slot */ + u8 flags; unsigned short scaled_quantum; /* SFQ_ALLOT_SIZE(quantum) */ - struct sfq_slot *tail; /* current slot in round */ + struct tcf_proto *filter_list; sfq_index *ht; /* Hash table ('divisor' slots) */ struct sfq_slot *slots; /* Flows table ('maxflows' entries) */ + struct red_parms *red_parms; + struct tc_sfqred_stats stats; + struct sfq_slot *tail; /* current slot in round */ + struct sfq_head dep[SFQ_MAX_DEPTH + 1]; /* Linked lists of slots, indexed by depth * dep[0] : list of unused flows @@ -133,6 +140,7 @@ struct sfq_sched_data { * dep[X] : list of flows with X packets */ + unsigned int maxflows; /* number of flows in flows array */ int perturb_period; unsigned int quantum; /* Allotment per round: MUST BE >= MTU */ struct timer_list perturb_timer; @@ -321,6 +329,7 @@ static unsigned int sfq_drop(struct Qdisc *sch) drop: skb = q->headdrop ? slot_dequeue_head(slot) : slot_dequeue_tail(slot); len = qdisc_pkt_len(skb); + slot->backlog -= len; sfq_dec(q, x); kfree_skb(skb); sch->q.qlen--; @@ -341,6 +350,23 @@ drop: return 0; } +/* Is ECN parameter configured */ +static int sfq_prob_mark(const struct sfq_sched_data *q) +{ + return q->flags & TC_RED_ECN; +} + +/* Should packets over max threshold just be marked */ +static int sfq_hard_mark(const struct sfq_sched_data *q) +{ + return (q->flags & (TC_RED_ECN | TC_RED_HARDDROP)) == TC_RED_ECN; +} + +static int sfq_headdrop(const struct sfq_sched_data *q) +{ + return q->headdrop; +} + static int sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) { @@ -349,6 +375,8 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) sfq_index x, qlen; struct sfq_slot *slot; int uninitialized_var(ret); + struct sk_buff *head; + int delta; hash = sfq_classify(skb, sch, &ret); if (hash == 0) { @@ -368,24 +396,75 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) q->ht[hash] = x; slot = &q->slots[x]; slot->hash = hash; + slot->backlog = 0; /* should already be 0 anyway... */ + red_set_vars(&slot->vars); + goto enqueue; } + if (q->red_parms) { + slot->vars.qavg = red_calc_qavg_no_idle_time(q->red_parms, + &slot->vars, + slot->backlog); + switch (red_action(q->red_parms, + &slot->vars, + slot->vars.qavg)) { + case RED_DONT_MARK: + break; - if (slot->qlen >= q->maxdepth) { - struct sk_buff *head; + case RED_PROB_MARK: + sch->qstats.overlimits++; + if (sfq_prob_mark(q)) { + /* We know we have at least one packet in queue */ + if (sfq_headdrop(q) && + INET_ECN_set_ce(slot->skblist_next)) { + q->stats.prob_mark_head++; + break; + } + if (INET_ECN_set_ce(skb)) { + q->stats.prob_mark++; + break; + } + } + q->stats.prob_drop++; + goto congestion_drop; + + case RED_HARD_MARK: + sch->qstats.overlimits++; + if (sfq_hard_mark(q)) { + /* We know we have at least one packet in queue */ + if (sfq_headdrop(q) && + INET_ECN_set_ce(slot->skblist_next)) { + q->stats.forced_mark_head++; + break; + } + if (INET_ECN_set_ce(skb)) { + q->stats.forced_mark++; + break; + } + } + q->stats.forced_drop++; + goto congestion_drop; + } + } - if (!q->headdrop) + if (slot->qlen >= q->maxdepth) { +congestion_drop: + if (!sfq_headdrop(q)) return qdisc_drop(skb, sch); + /* We know we have at least one packet in queue */ head = slot_dequeue_head(slot); - sch->qstats.backlog -= qdisc_pkt_len(head); + delta = qdisc_pkt_len(head) - qdisc_pkt_len(skb); + sch->qstats.backlog -= delta; + slot->backlog -= delta; qdisc_drop(head, sch); - sch->qstats.backlog += qdisc_pkt_len(skb); slot_queue_add(slot, skb); return NET_XMIT_CN; } +enqueue: sch->qstats.backlog += qdisc_pkt_len(skb); + slot->backlog += qdisc_pkt_len(skb); slot_queue_add(slot, skb); sfq_inc(q, x); if (slot->qlen == 1) { /* The flow is new */ @@ -396,6 +475,7 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) slot->next = q->tail->next; q->tail->next = x; } + /* We could use a bigger initial quantum for new flows */ slot->allot = q->scaled_quantum; } if (++sch->q.qlen <= q->limit) @@ -439,7 +519,7 @@ next_slot: qdisc_bstats_update(sch, skb); sch->q.qlen--; sch->qstats.backlog -= qdisc_pkt_len(skb); - + slot->backlog -= qdisc_pkt_len(skb); /* Is the slot empty? */ if (slot->qlen == 0) { q->ht[slot->hash] = SFQ_EMPTY_SLOT; @@ -490,6 +570,8 @@ static void sfq_rehash(struct Qdisc *sch) sfq_dec(q, i); __skb_queue_tail(&list, skb); } + slot->backlog = 0; + red_set_vars(&slot->vars); q->ht[slot->hash] = SFQ_EMPTY_SLOT; } q->tail = NULL; @@ -514,6 +596,11 @@ drop: sch->qstats.backlog -= qdisc_pkt_len(skb); if (slot->qlen >= q->maxdepth) goto drop; slot_queue_add(slot, skb); + if (q->red_parms) + slot->vars.qavg = red_calc_qavg(q->red_parms, + &slot->vars, + slot->backlog); + slot->backlog += qdisc_pkt_len(skb); sfq_inc(q, x); if (slot->qlen == 1) { /* The flow is new */ if (q->tail == NULL) { /* It is the first flow */ @@ -552,6 +639,7 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt) struct tc_sfq_qopt *ctl = nla_data(opt); struct tc_sfq_qopt_v1 *ctl_v1 = NULL; unsigned int qlen; + struct red_parms *p = NULL; if (opt->nla_len < nla_attr_size(sizeof(*ctl))) return -EINVAL; @@ -560,7 +648,11 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt) if (ctl->divisor && (!is_power_of_2(ctl->divisor) || ctl->divisor > 65536)) return -EINVAL; - + if (ctl_v1 && ctl_v1->qth_min) { + p = kmalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return -ENOMEM; + } sch_tree_lock(sch); if (ctl->quantum) { q->quantum = ctl->quantum; @@ -576,6 +668,16 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt) if (ctl_v1) { if (ctl_v1->depth) q->maxdepth = min_t(u32, ctl_v1->depth, SFQ_MAX_DEPTH); + if (p) { + swap(q->red_parms, p); + red_set_parms(q->red_parms, + ctl_v1->qth_min, ctl_v1->qth_max, + ctl_v1->Wlog, + ctl_v1->Plog, ctl_v1->Scell_log, + NULL, + ctl_v1->max_P); + } + q->flags = ctl_v1->flags; q->headdrop = ctl_v1->headdrop; } if (ctl->limit) { @@ -594,6 +696,7 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt) q->perturbation = net_random(); } sch_tree_unlock(sch); + kfree(p); return 0; } @@ -625,6 +728,7 @@ static void sfq_destroy(struct Qdisc *sch) del_timer_sync(&q->perturb_timer); sfq_free(q->ht); sfq_free(q->slots); + kfree(q->red_parms); } static int sfq_init(struct Qdisc *sch, struct nlattr *opt) @@ -683,6 +787,7 @@ static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb) struct sfq_sched_data *q = qdisc_priv(sch); unsigned char *b = skb_tail_pointer(skb); struct tc_sfq_qopt_v1 opt; + struct red_parms *p = q->red_parms; memset(&opt, 0, sizeof(opt)); opt.v0.quantum = q->quantum; @@ -693,6 +798,17 @@ static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb) opt.depth = q->maxdepth; opt.headdrop = q->headdrop; + if (p) { + opt.qth_min = p->qth_min >> p->Wlog; + opt.qth_max = p->qth_max >> p->Wlog; + opt.Wlog = p->Wlog; + opt.Plog = p->Plog; + opt.Scell_log = p->Scell_log; + opt.max_P = p->max_P; + } + memcpy(&opt.stats, &q->stats, sizeof(opt.stats)); + opt.flags = q->flags; + NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); return skb->len; @@ -747,15 +863,13 @@ static int sfq_dump_class_stats(struct Qdisc *sch, unsigned long cl, sfq_index idx = q->ht[cl - 1]; struct gnet_stats_queue qs = { 0 }; struct tc_sfq_xstats xstats = { 0 }; - struct sk_buff *skb; if (idx != SFQ_EMPTY_SLOT) { const struct sfq_slot *slot = &q->slots[idx]; xstats.allot = slot->allot << SFQ_ALLOT_SHIFT; qs.qlen = slot->qlen; - slot_queue_walk(slot, skb) - qs.backlog += qdisc_pkt_len(skb); + qs.backlog = slot->backlog; } if (gnet_stats_copy_queue(d, &qs) < 0) return -1; -- cgit v0.10.2 From 83636580ad99cffd85b07e75da7ad45ada0fd530 Mon Sep 17 00:00:00 2001 From: Doug Kehn Date: Wed, 11 Jan 2012 13:12:43 +0000 Subject: ksz884x: fix mtu for VLAN The Ethernet header does not account for the addition of a VLAN header. Full size Ethernet frames containing VLAN header are not processed because the frame is larger than the resulting hw mtu. Signed-off-by: Doug Kehn Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c index 6ed09a8..e52cd31 100644 --- a/drivers/net/ethernet/micrel/ksz884x.c +++ b/drivers/net/ethernet/micrel/ksz884x.c @@ -746,7 +746,7 @@ #define MAC_ADDR_ORDER(i) (ETH_ALEN - 1 - (i)) #define MAX_ETHERNET_BODY_SIZE 1500 -#define ETHERNET_HEADER_SIZE 14 +#define ETHERNET_HEADER_SIZE (14 + VLAN_HLEN) #define MAX_ETHERNET_PACKET_SIZE \ (MAX_ETHERNET_BODY_SIZE + ETHERNET_HEADER_SIZE) -- cgit v0.10.2 From 20d4369b6892159895d6136946e692eaf29e8413 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 11 Jan 2012 23:55:04 +0000 Subject: drivers/net/ethernet/tundra/tsi108_eth.c: add missing iounmap Add missing iounmap in error handling code, in a case where the function already preforms iounmap on some other execution path. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression e; statement S,S1; int ret; @@ e = \(ioremap\|ioremap_nocache\)(...) ... when != iounmap(e) if (<+...e...+>) S ... when any when != iounmap(e) *if (...) { ... when != iounmap(e) return ...; } ... when any iounmap(e); // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/tundra/tsi108_eth.c b/drivers/net/ethernet/tundra/tsi108_eth.c index a9ce01ba..164fb77 100644 --- a/drivers/net/ethernet/tundra/tsi108_eth.c +++ b/drivers/net/ethernet/tundra/tsi108_eth.c @@ -1604,7 +1604,7 @@ tsi108_init_one(struct platform_device *pdev) data->phyregs = ioremap(einfo->phyregs, 0x400); if (NULL == data->phyregs) { err = -ENOMEM; - goto regs_fail; + goto phyregs_fail; } /* MII setup */ data->mii_if.dev = dev; @@ -1663,9 +1663,11 @@ tsi108_init_one(struct platform_device *pdev) return 0; register_fail: - iounmap(data->regs); iounmap(data->phyregs); +phyregs_fail: + iounmap(data->regs); + regs_fail: free_netdev(dev); return err; -- cgit v0.10.2 From 25cecd7e355bf90b8fea039bd06947bb3234e77d Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 11 Jan 2012 23:55:10 +0000 Subject: drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c: add missing iounmap Add missing iounmap in error handling code, in a case where the function already preforms iounmap on some other execution path. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression e; statement S,S1; int ret; @@ e = \(ioremap\|ioremap_nocache\)(...) ... when != iounmap(e) if (<+...e...+>) S ... when any when != iounmap(e) *if (...) { ... when != iounmap(e) return ...; } ... when any iounmap(e); // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 7b1594f..1ac8324 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -62,7 +62,7 @@ static int stmmac_pltfr_probe(struct platform_device *pdev) priv = stmmac_dvr_probe(&(pdev->dev), plat_dat); if (!priv) { pr_err("%s: main drivr probe failed", __func__); - goto out_release_region; + goto out_unmap; } priv->ioaddr = addr; -- cgit v0.10.2 From 8d82f219c2d476811cd3157a39c7b5c1f045ebc3 Mon Sep 17 00:00:00 2001 From: Eric Benard Date: Thu, 12 Jan 2012 06:10:28 +0000 Subject: net: fsl: fec: handle 10Mbps speed in RMII mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit when the link is 10 Mbps and the mode is RMII, it's necessary to set FRCONT to 1 in MIIGSK_CFGR to divide the RMII source clock by 10 in order to support 10 Mbps operations. Signed-off-by: Eric BĂ©nard Acked-by: Shawn Guo Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c index 236cc89..7b25e9c 100644 --- a/drivers/net/ethernet/freescale/fec.c +++ b/drivers/net/ethernet/freescale/fec.c @@ -476,6 +476,7 @@ fec_restart(struct net_device *ndev, int duplex) } else { #ifdef FEC_MIIGSK_ENR if (id_entry->driver_data & FEC_QUIRK_USE_GASKET) { + u32 cfgr; /* disable the gasket and wait */ writel(0, fep->hwp + FEC_MIIGSK_ENR); while (readl(fep->hwp + FEC_MIIGSK_ENR) & 4) @@ -486,9 +487,11 @@ fec_restart(struct net_device *ndev, int duplex) * RMII, 50 MHz, no loopback, no echo * MII, 25 MHz, no loopback, no echo */ - writel((fep->phy_interface == PHY_INTERFACE_MODE_RMII) ? - 1 : 0, fep->hwp + FEC_MIIGSK_CFGR); - + cfgr = (fep->phy_interface == PHY_INTERFACE_MODE_RMII) + ? BM_MIIGSK_CFGR_RMII : BM_MIIGSK_CFGR_MII; + if (fep->phy_dev && fep->phy_dev->speed == SPEED_10) + cfgr |= BM_MIIGSK_CFGR_FRCONT_10M; + writel(cfgr, fep->hwp + FEC_MIIGSK_CFGR); /* re-enable the gasket */ writel(2, fep->hwp + FEC_MIIGSK_ENR); diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 8b2c6d7..8408c62 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -47,6 +47,10 @@ #define FEC_MIIGSK_CFGR 0x300 /* MIIGSK Configuration reg */ #define FEC_MIIGSK_ENR 0x308 /* MIIGSK Enable reg */ +#define BM_MIIGSK_CFGR_MII 0x00 +#define BM_MIIGSK_CFGR_RMII 0x01 +#define BM_MIIGSK_CFGR_FRCONT_10M 0x40 + #else #define FEC_ECNTRL 0x000 /* Ethernet control reg */ -- cgit v0.10.2 From 5b7bf42e3d47fb16aaf53776ae3eaaf1be247a35 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 12 Jan 2012 08:57:56 +0000 Subject: RDS: Remove some unused iWARP code rds_iw_flush_goal() just returns a count, but it is only called in one place and its return value is ignored there. So delete all the dead code. Signed-off-by: Roland Dreier Signed-off-by: David S. Miller diff --git a/net/rds/iw_rdma.c b/net/rds/iw_rdma.c index 4e1de17..a817705 100644 --- a/net/rds/iw_rdma.c +++ b/net/rds/iw_rdma.c @@ -477,17 +477,6 @@ void rds_iw_sync_mr(void *trans_private, int direction) } } -static inline unsigned int rds_iw_flush_goal(struct rds_iw_mr_pool *pool, int free_all) -{ - unsigned int item_count; - - item_count = atomic_read(&pool->item_count); - if (free_all) - return item_count; - - return 0; -} - /* * Flush our pool of MRs. * At a minimum, all currently unused MRs are unmapped. @@ -500,7 +489,7 @@ static int rds_iw_flush_mr_pool(struct rds_iw_mr_pool *pool, int free_all) LIST_HEAD(unmap_list); LIST_HEAD(kill_list); unsigned long flags; - unsigned int nfreed = 0, ncleaned = 0, unpinned = 0, free_goal; + unsigned int nfreed = 0, ncleaned = 0, unpinned = 0; int ret = 0; rds_iw_stats_inc(s_iw_rdma_mr_pool_flush); @@ -514,8 +503,6 @@ static int rds_iw_flush_mr_pool(struct rds_iw_mr_pool *pool, int free_all) list_splice_init(&pool->clean_list, &kill_list); spin_unlock_irqrestore(&pool->list_lock, flags); - free_goal = rds_iw_flush_goal(pool, free_all); - /* Batched invalidate of dirty MRs. * For FMR based MRs, the mappings on the unmap list are * actually members of an ibmr (ibmr->mapping). They either -- cgit v0.10.2 From 91dce7ddab99a29b600e3d792b847dc2cdbf0848 Mon Sep 17 00:00:00 2001 From: Bradley Peterson Date: Thu, 12 Jan 2012 10:39:16 +0000 Subject: pptp: Accept packet with seq zero Initialize the PPTP "seq received" value to 0xffffffff, so we don't ignore packets with seq zero. Signed-off-by: Bradley Peterson Signed-off-by: David S. Miller diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index c1c9293..df884dd 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c @@ -585,8 +585,8 @@ static int pptp_create(struct net *net, struct socket *sock) po = pppox_sk(sk); opt = &po->proto.pptp; - opt->seq_sent = 0; opt->seq_recv = 0; - opt->ack_recv = 0; opt->ack_sent = 0; + opt->seq_sent = 0; opt->seq_recv = 0xffffffff; + opt->ack_recv = 0; opt->ack_sent = 0xffffffff; error = 0; out: -- cgit v0.10.2