From 0e5a117441ce245b87949cc7713627a293f37227 Mon Sep 17 00:00:00 2001 From: "sjur.brandeland@stericsson.com" Date: Sun, 22 May 2011 11:18:50 +0000 Subject: caif: Bugfix add check NULL pointer before calling functions. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add check on layer->dn != NULL before calling functions in layer below. Signed-off-by: Sjur Brændeland Signed-off-by: David S. Miller --- net/caif/cfctrl.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) (limited to 'net') diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c index 0c00a6015dda..f8ac31371a4a 100644 --- a/net/caif/cfctrl.c +++ b/net/caif/cfctrl.c @@ -178,20 +178,23 @@ static void init_info(struct caif_payload_info *info, struct cfctrl *cfctrl) void cfctrl_enum_req(struct cflayer *layer, u8 physlinkid) { struct cfctrl *cfctrl = container_obj(layer); - int ret; struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); + struct cflayer *dn = cfctrl->serv.layer.dn; if (!pkt) { pr_warn("Out of memory\n"); return; } + if (!dn) { + pr_debug("not able to send enum request\n"); + return; + } caif_assert(offsetof(struct cfctrl, serv.layer) == 0); init_info(cfpkt_info(pkt), cfctrl); cfpkt_info(pkt)->dev_info->id = physlinkid; cfctrl->serv.dev_info.id = physlinkid; cfpkt_addbdy(pkt, CFCTRL_CMD_ENUM); cfpkt_addbdy(pkt, physlinkid); - ret = - cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); + dn->transmit(dn, pkt); } int cfctrl_linkup_request(struct cflayer *layer, @@ -206,6 +209,12 @@ int cfctrl_linkup_request(struct cflayer *layer, int ret; char utility_name[16]; struct cfpkt *pkt; + struct cflayer *dn = cfctrl->serv.layer.dn; + + if (!dn) { + pr_debug("not able to send linkup request\n"); + return -ENODEV; + } if (cfctrl_cancel_req(layer, user_layer) > 0) { /* Slight Paranoia, check if already connecting */ @@ -282,7 +291,7 @@ int cfctrl_linkup_request(struct cflayer *layer, */ cfpkt_info(pkt)->dev_info->id = param->phyid; ret = - cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); + dn->transmit(dn, pkt); if (ret < 0) { int count; @@ -301,15 +310,23 @@ int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid, int ret; struct cfctrl *cfctrl = container_obj(layer); struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); + struct cflayer *dn = cfctrl->serv.layer.dn; + if (!pkt) { pr_warn("Out of memory\n"); return -ENOMEM; } + + if (!dn) { + pr_debug("not able to send link-down request\n"); + return -ENODEV; + } + cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_DESTROY); cfpkt_addbdy(pkt, channelid); init_info(cfpkt_info(pkt), cfctrl); ret = - cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); + dn->transmit(dn, pkt); #ifndef CAIF_NO_LOOP cfctrl->loop_linkused[channelid] = 0; #endif @@ -477,7 +494,7 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) cfpkt_extr_head(pkt, ¶m, len); break; default: - pr_warn("Request setup - invalid link type (%d)\n", + pr_warn("Request setup, invalid type (%d)\n", serv); goto error; } @@ -489,7 +506,8 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) if (CFCTRL_ERR_BIT == (CFCTRL_ERR_BIT & cmdrsp) || cfpkt_erroneous(pkt)) { - pr_err("Invalid O/E bit or parse error on CAIF control channel\n"); + pr_err("Invalid O/E bit or parse error " + "on CAIF control channel\n"); cfctrl->res.reject_rsp(cfctrl->serv.layer.up, 0, req ? req->client_layer @@ -550,9 +568,8 @@ static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, case _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND: case CAIF_CTRLCMD_FLOW_OFF_IND: spin_lock_bh(&this->info_list_lock); - if (!list_empty(&this->list)) { + if (!list_empty(&this->list)) pr_debug("Received flow off in control layer\n"); - } spin_unlock_bh(&this->info_list_lock); break; case _CAIF_CTRLCMD_PHYIF_DOWN_IND: { -- cgit v1.2.3 From 54e90fb5ca8050156d3e748ddc690ed6ea9d71ac Mon Sep 17 00:00:00 2001 From: "sjur.brandeland@stericsson.com" Date: Sun, 22 May 2011 11:18:51 +0000 Subject: caif: Fixes freeze on Link layer removal. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CAIF Socket layer - caif_socket.c: - Plug mem-leak at reconnect. - Always call disconnect to cleanup CAIF stack. - Disconnect will always report success. CAIF configuration layer - cfcnfg.c - Disconnect must dismantle the caif stack correctly - Protect against faulty removals (check on id zero) CAIF mux layer - cfmuxl.c - When inserting new service layer in the MUX remove any old entries with the same ID. - When removing CAIF Link layer, remove the associated service layers before notifying service layers. Signed-off-by: Sjur Brændeland Signed-off-by: David S. Miller --- net/caif/caif_socket.c | 13 +++++-------- net/caif/cfcnfg.c | 44 +++++++++++++++++++------------------------- net/caif/cfmuxl.c | 49 ++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 62 insertions(+), 44 deletions(-) (limited to 'net') diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index b840395ced1d..a98628086452 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -816,6 +816,7 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr, if (sk->sk_shutdown & SHUTDOWN_MASK) { /* Allow re-connect after SHUTDOWN_IND */ caif_disconnect_client(sock_net(sk), &cf_sk->layer); + caif_free_client(&cf_sk->layer); break; } /* No reconnect on a seqpacket socket */ @@ -926,7 +927,6 @@ static int caif_release(struct socket *sock) { struct sock *sk = sock->sk; struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); - int res = 0; if (!sk) return 0; @@ -953,10 +953,7 @@ static int caif_release(struct socket *sock) sk->sk_state = CAIF_DISCONNECTED; sk->sk_shutdown = SHUTDOWN_MASK; - if (cf_sk->sk.sk_socket->state == SS_CONNECTED || - cf_sk->sk.sk_socket->state == SS_CONNECTING) - res = caif_disconnect_client(sock_net(sk), &cf_sk->layer); - + caif_disconnect_client(sock_net(sk), &cf_sk->layer); cf_sk->sk.sk_socket->state = SS_DISCONNECTING; wake_up_interruptible_poll(sk_sleep(sk), POLLERR|POLLHUP); @@ -964,7 +961,7 @@ static int caif_release(struct socket *sock) sk_stream_kill_queues(&cf_sk->sk); release_sock(sk); sock_put(sk); - return res; + return 0; } /* Copied from af_unix.c:unix_poll(), added CAIF tx_flow handling */ @@ -1120,7 +1117,7 @@ static int caif_create(struct net *net, struct socket *sock, int protocol, set_rx_flow_on(cf_sk); /* Set default options on configuration */ - cf_sk->sk.sk_priority= CAIF_PRIO_NORMAL; + cf_sk->sk.sk_priority = CAIF_PRIO_NORMAL; cf_sk->conn_req.link_selector = CAIF_LINK_LOW_LATENCY; cf_sk->conn_req.protocol = protocol; /* Increase the number of sockets created. */ diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c index 351c2ca7e7b9..52fe33bee029 100644 --- a/net/caif/cfcnfg.c +++ b/net/caif/cfcnfg.c @@ -182,39 +182,26 @@ static int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi) int caif_disconnect_client(struct net *net, struct cflayer *adap_layer) { - u8 channel_id = 0; - int ret = 0; - struct cflayer *servl = NULL; + u8 channel_id; struct cfcnfg *cfg = get_cfcnfg(net); caif_assert(adap_layer != NULL); - - channel_id = adap_layer->id; - if (adap_layer->dn == NULL || channel_id == 0) { - pr_err("adap_layer->dn == NULL or adap_layer->id is 0\n"); - ret = -ENOTCONN; - goto end; - } - - servl = cfmuxl_remove_uplayer(cfg->mux, channel_id); - if (servl == NULL) { - pr_err("PROTOCOL ERROR - " - "Error removing service_layer Channel_Id(%d)", - channel_id); - ret = -EINVAL; - goto end; - } - - ret = cfctrl_linkdown_req(cfg->ctrl, channel_id, adap_layer); - -end: cfctrl_cancel_req(cfg->ctrl, adap_layer); + channel_id = adap_layer->id; + if (channel_id != 0) { + struct cflayer *servl; + servl = cfmuxl_remove_uplayer(cfg->mux, channel_id); + if (servl != NULL) + layer_set_up(servl, NULL); + } else + pr_debug("nothing to disconnect\n"); + cfctrl_linkdown_req(cfg->ctrl, channel_id, adap_layer); /* Do RCU sync before initiating cleanup */ synchronize_rcu(); if (adap_layer->ctrlcmd != NULL) adap_layer->ctrlcmd(adap_layer, CAIF_CTRLCMD_DEINIT_RSP, 0); - return ret; + return 0; } EXPORT_SYMBOL(caif_disconnect_client); @@ -400,6 +387,14 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv, struct cfcnfg_phyinfo *phyinfo; struct net_device *netdev; + if (channel_id == 0) { + pr_warn("received channel_id zero\n"); + if (adapt_layer != NULL && adapt_layer->ctrlcmd != NULL) + adapt_layer->ctrlcmd(adapt_layer, + CAIF_CTRLCMD_INIT_FAIL_RSP, 0); + return; + } + rcu_read_lock(); if (adapt_layer == NULL) { @@ -523,7 +518,6 @@ got_phyid: phyinfo->use_stx = stx; phyinfo->use_fcs = fcs; - phy_layer->type = phy_type; frml = cffrml_create(phyid, fcs); if (!frml) { diff --git a/net/caif/cfmuxl.c b/net/caif/cfmuxl.c index 2a56df7e0a4b..3a66b8c10e09 100644 --- a/net/caif/cfmuxl.c +++ b/net/caif/cfmuxl.c @@ -62,16 +62,6 @@ struct cflayer *cfmuxl_create(void) return &this->layer; } -int cfmuxl_set_uplayer(struct cflayer *layr, struct cflayer *up, u8 linkid) -{ - struct cfmuxl *muxl = container_obj(layr); - - spin_lock_bh(&muxl->receive_lock); - list_add_rcu(&up->node, &muxl->srvl_list); - spin_unlock_bh(&muxl->receive_lock); - return 0; -} - int cfmuxl_set_dnlayer(struct cflayer *layr, struct cflayer *dn, u8 phyid) { struct cfmuxl *muxl = (struct cfmuxl *) layr; @@ -93,6 +83,24 @@ static struct cflayer *get_from_id(struct list_head *list, u16 id) return NULL; } +int cfmuxl_set_uplayer(struct cflayer *layr, struct cflayer *up, u8 linkid) +{ + struct cfmuxl *muxl = container_obj(layr); + struct cflayer *old; + + spin_lock_bh(&muxl->receive_lock); + + /* Two entries with same id is wrong, so remove old layer from mux */ + old = get_from_id(&muxl->srvl_list, linkid); + if (old != NULL) + list_del_rcu(&old->node); + + list_add_rcu(&up->node, &muxl->srvl_list); + spin_unlock_bh(&muxl->receive_lock); + + return 0; +} + struct cflayer *cfmuxl_remove_dnlayer(struct cflayer *layr, u8 phyid) { struct cfmuxl *muxl = container_obj(layr); @@ -146,6 +154,11 @@ struct cflayer *cfmuxl_remove_uplayer(struct cflayer *layr, u8 id) struct cfmuxl *muxl = container_obj(layr); int idx = id % UP_CACHE_SIZE; + if (id == 0) { + pr_warn("Trying to remove control layer\n"); + return NULL; + } + spin_lock_bh(&muxl->receive_lock); up = get_from_id(&muxl->srvl_list, id); if (up == NULL) @@ -235,12 +248,26 @@ static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, { struct cfmuxl *muxl = container_obj(layr); struct cflayer *layer; + int idx; rcu_read_lock(); list_for_each_entry_rcu(layer, &muxl->srvl_list, node) { - if (cfsrvl_phyid_match(layer, phyid) && layer->ctrlcmd) + + if (cfsrvl_phyid_match(layer, phyid) && layer->ctrlcmd) { + + if ((ctrl == _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND || + ctrl == CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND) && + layer->id != 0) { + + idx = layer->id % UP_CACHE_SIZE; + spin_lock_bh(&muxl->receive_lock); + rcu_assign_pointer(muxl->up_cache[idx], NULL); + list_del_rcu(&layer->node); + spin_unlock_bh(&muxl->receive_lock); + } /* NOTE: ctrlcmd is not allowed to block */ layer->ctrlcmd(layer, ctrl, phyid); + } } rcu_read_unlock(); } -- cgit v1.2.3 From 96796ea8b6b1221c7cacf68ce056d77eff0a793d Mon Sep 17 00:00:00 2001 From: "sjur.brandeland@stericsson.com" Date: Sun, 22 May 2011 11:18:52 +0000 Subject: caif: Fix freezes when running CAIF loopback device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix spinlock bugs when running out of link-ids in loopback tests and avoid allocating link-id when error is set in link-setup-response. Signed-off-by: Sjur Brændeland Signed-off-by: David S. Miller --- net/caif/cfctrl.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c index f8ac31371a4a..e22671bed669 100644 --- a/net/caif/cfctrl.c +++ b/net/caif/cfctrl.c @@ -368,7 +368,8 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) cfpkt_extr_head(pkt, &cmdrsp, 1); cmd = cmdrsp & CFCTRL_CMD_MASK; if (cmd != CFCTRL_CMD_LINK_ERR - && CFCTRL_RSP_BIT != (CFCTRL_RSP_BIT & cmdrsp)) { + && CFCTRL_RSP_BIT != (CFCTRL_RSP_BIT & cmdrsp) + && CFCTRL_ERR_BIT != (CFCTRL_ERR_BIT & cmdrsp)) { if (handle_loop(cfctrl, cmd, pkt) != 0) cmdrsp |= CFCTRL_ERR_BIT; } @@ -604,16 +605,16 @@ static int handle_loop(struct cfctrl *ctrl, int cmd, struct cfpkt *pkt) case CFCTRL_CMD_LINK_SETUP: spin_lock_bh(&ctrl->loop_linkid_lock); if (!dec) { - for (linkid = last_linkid + 1; linkid < 255; linkid++) + for (linkid = last_linkid + 1; linkid < 254; linkid++) if (!ctrl->loop_linkused[linkid]) goto found; } dec = 1; - for (linkid = last_linkid - 1; linkid > 0; linkid--) + for (linkid = last_linkid - 1; linkid > 1; linkid--) if (!ctrl->loop_linkused[linkid]) goto found; spin_unlock_bh(&ctrl->loop_linkid_lock); - + return -1; found: if (linkid < 10) dec = 0; -- cgit v1.2.3 From 69c867c90c7fe0773d9aa4e8bbf777f574be13d2 Mon Sep 17 00:00:00 2001 From: "sjur.brandeland@stericsson.com" Date: Sun, 22 May 2011 11:18:54 +0000 Subject: caif: Plug memory leak for checksum error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In case of checksum error, the framing layer returns -EILSEQ, but does not free the packet. Plug this hole by freeing the packet if -EILSEQ is returned. Signed-off-by: Sjur Brændeland Signed-off-by: David S. Miller --- net/caif/caif_dev.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index 366ca0fb7a29..682c0fedf360 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c @@ -142,6 +142,7 @@ static int receive(struct sk_buff *skb, struct net_device *dev, { struct cfpkt *pkt; struct caif_device_entry *caifd; + int err; pkt = cfpkt_fromnative(CAIF_DIR_IN, skb); @@ -159,7 +160,11 @@ static int receive(struct sk_buff *skb, struct net_device *dev, caifd_hold(caifd); rcu_read_unlock(); - caifd->layer.up->receive(caifd->layer.up, pkt); + err = caifd->layer.up->receive(caifd->layer.up, pkt); + + /* For -EILSEQ the packet is not freed so so it now */ + if (err == -EILSEQ) + cfpkt_destroy(pkt); /* Release reference to stack upwards */ caifd_put(caifd); -- cgit v1.2.3 From 474b4c4ff007c992ea7dc88ba2605aa124f8bafb Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 22 May 2011 20:42:10 -0400 Subject: netlabel: Remove prefetches from list handlers. Signed-off-by: David S. Miller --- net/netlabel/netlabel_addrlist.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/netlabel/netlabel_addrlist.h b/net/netlabel/netlabel_addrlist.h index 1c1c093cf279..2b9644e19de0 100644 --- a/net/netlabel/netlabel_addrlist.h +++ b/net/netlabel/netlabel_addrlist.h @@ -96,12 +96,12 @@ static inline struct netlbl_af4list *__af4list_valid_rcu(struct list_head *s, #define netlbl_af4list_foreach(iter, head) \ for (iter = __af4list_valid((head)->next, head); \ - prefetch(iter->list.next), &iter->list != (head); \ + &iter->list != (head); \ iter = __af4list_valid(iter->list.next, head)) #define netlbl_af4list_foreach_rcu(iter, head) \ for (iter = __af4list_valid_rcu((head)->next, head); \ - prefetch(iter->list.next), &iter->list != (head); \ + &iter->list != (head); \ iter = __af4list_valid_rcu(iter->list.next, head)) #define netlbl_af4list_foreach_safe(iter, tmp, head) \ @@ -163,12 +163,12 @@ static inline struct netlbl_af6list *__af6list_valid_rcu(struct list_head *s, #define netlbl_af6list_foreach(iter, head) \ for (iter = __af6list_valid((head)->next, head); \ - prefetch(iter->list.next), &iter->list != (head); \ + &iter->list != (head); \ iter = __af6list_valid(iter->list.next, head)) #define netlbl_af6list_foreach_rcu(iter, head) \ for (iter = __af6list_valid_rcu((head)->next, head); \ - prefetch(iter->list.next), &iter->list != (head); \ + &iter->list != (head); \ iter = __af6list_valid_rcu(iter->list.next, head)) #define netlbl_af6list_foreach_safe(iter, tmp, head) \ -- cgit v1.2.3 From 120a3d5c7c1f37752e7956d296a4f031f38cb217 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 22 May 2011 20:53:43 -0400 Subject: ipv4: Include linux/prefetch.h in fib_trie.c Signed-off-by: David S. Miller --- net/ipv4/fib_trie.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index c779ce96e5b5..dd5a3206423e 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -67,6 +67,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From bb8ed6302b0613339c1a5f0a2cb0b3807c0af611 Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Thu, 19 May 2011 21:39:11 +0000 Subject: bridge: call NETDEV_JOIN notifiers when add a slave In the previous patch I added NETDEV_JOIN, now we can notify netconsole when adding a device to a bridge too. Signed-off-by: WANG Cong Cc: Neil Horman Signed-off-by: David S. Miller --- net/bridge/br_if.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'net') diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 5dbdfdfc3a34..d5147ddd70bf 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -338,6 +338,8 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) if (IS_ERR(p)) return PTR_ERR(p); + call_netdevice_notifiers(NETDEV_JOIN, dev); + err = dev_set_promiscuity(dev, 1); if (err) goto put_back; -- cgit v1.2.3 From ac3d3f81516fcbf80416e84682fd4bdaf3080611 Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Thu, 19 May 2011 23:06:32 +0000 Subject: rtnetlink: ignore NETDEV_RELEASE and NETDEV_JOIN event These two events are not expected to be caught by userspace. Signed-off-by: WANG Cong Signed-off-by: David S. Miller --- net/core/rtnetlink.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'net') diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index d2ba2597c75a..d1644e317e70 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1956,6 +1956,8 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi case NETDEV_GOING_DOWN: case NETDEV_UNREGISTER: case NETDEV_UNREGISTER_BATCH: + case NETDEV_RELEASE: + case NETDEV_JOIN: break; default: rtmsg_ifinfo(RTM_NEWLINK, dev, 0); -- cgit v1.2.3 From 6df427fe8c481d3be437cbe8bd366bdac82b73c4 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 19 May 2011 19:37:40 +0000 Subject: net: remove synchronize_net() from netdev_set_master() In the old days, we used to access dev->master in __netif_receive_skb() in a rcu_read_lock section. So one synchronize_net() call was needed in netdev_set_master() to make sure another cpu could not use old master while/after we release it. We now use netdev_rx_handler infrastructure and added one synchronize_net() call in bond_release()/bond_release_all() Remove the obsolete synchronize_net() from netdev_set_master() and add one in bridge del_nbp() after its netdev_rx_handler_unregister() call. This makes enslave -d a bit faster. Signed-off-by: Eric Dumazet CC: Jiri Pirko CC: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br_if.c | 1 + net/core/dev.c | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index d5147ddd70bf..1bacca4cb676 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -147,6 +147,7 @@ static void del_nbp(struct net_bridge_port *p) dev->priv_flags &= ~IFF_BRIDGE_PORT; netdev_rx_handler_unregister(dev); + synchronize_net(); netdev_set_master(dev, NULL); diff --git a/net/core/dev.c b/net/core/dev.c index d94537914a71..bcb05cb799c1 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4294,10 +4294,8 @@ int netdev_set_master(struct net_device *slave, struct net_device *master) slave->master = master; - if (old) { - synchronize_net(); + if (old) dev_put(old); - } return 0; } EXPORT_SYMBOL(netdev_set_master); -- cgit v1.2.3 From 3137663dfb43bb3e3174e9da81db0c05f395fc1b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 19 May 2011 23:42:09 +0000 Subject: net: avoid synchronize_rcu() in dev_deactivate_many dev_deactivate_many() issues one synchronize_rcu() call after qdiscs set to noop_qdisc. This call is here to make sure they are no outstanding qdisc-less dev_queue_xmit calls before returning to caller. But in dismantle phase, we dont have to wait, because we wont activate again the device, and we are going to wait one rcu grace period later in rollback_registered_many(). After this patch, device dismantle uses one synchronize_net() and one rcu_barrier() call only, so we have a ~30% speedup and a smaller RTNL latency. Signed-off-by: Eric Dumazet CC: Patrick McHardy , CC: Ben Greear Signed-off-by: David S. Miller --- net/sched/sch_generic.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index c84b65920d1b..b1721d71c27c 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -815,9 +815,17 @@ static bool some_qdisc_is_busy(struct net_device *dev) return false; } +/** + * dev_deactivate_many - deactivate transmissions on several devices + * @head: list of devices to deactivate + * + * This function returns only when all outstanding transmissions + * have completed, unless all devices are in dismantle phase. + */ void dev_deactivate_many(struct list_head *head) { struct net_device *dev; + bool sync_needed = false; list_for_each_entry(dev, head, unreg_list) { netdev_for_each_tx_queue(dev, dev_deactivate_queue, @@ -827,10 +835,15 @@ void dev_deactivate_many(struct list_head *head) &noop_qdisc); dev_watchdog_down(dev); + sync_needed |= !dev->dismantle; } - /* Wait for outstanding qdisc-less dev_queue_xmit calls. */ - synchronize_rcu(); + /* Wait for outstanding qdisc-less dev_queue_xmit calls. + * This is avoided if all devices are in dismantle phase : + * Caller will call synchronize_net() for us + */ + if (sync_needed) + synchronize_net(); /* Wait for outstanding qdisc_run calls. */ list_for_each_entry(dev, head, unreg_list) -- cgit v1.2.3 From c378a9c019cf5e017d1ed24954b54fae7bebd2bc Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sat, 21 May 2011 07:16:42 +0000 Subject: ipv4: Give backtrace in ip_rt_bug(). Add a stack backtrace to the ip_rt_bug path for debugging Signed-off-by: Dave Jones Signed-off-by: David S. Miller --- net/ipv4/route.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/ipv4/route.c b/net/ipv4/route.c index b24d58e6bbcd..52b0b956508b 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1665,6 +1665,7 @@ static int ip_rt_bug(struct sk_buff *skb) &ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr, skb->dev ? skb->dev->name : "?"); kfree_skb(skb); + WARN_ON(1); return 0; } -- cgit v1.2.3 From 68d5ac2ed6180567407e4187e206df3ba6466373 Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Sun, 22 May 2011 00:17:11 +0000 Subject: pktgen: use vzalloc_node() instead of vmalloc_node() + memset() Signed-off-by: WANG Cong Cc: "David S. Miller" Signed-off-by: David S. Miller --- net/core/pktgen.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'net') diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 67870e9fd097..3b85c0dffa61 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -3544,13 +3544,12 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) return -ENOMEM; strcpy(pkt_dev->odevname, ifname); - pkt_dev->flows = vmalloc_node(MAX_CFLOWS * sizeof(struct flow_state), + pkt_dev->flows = vzalloc_node(MAX_CFLOWS * sizeof(struct flow_state), node); if (pkt_dev->flows == NULL) { kfree(pkt_dev); return -ENOMEM; } - memset(pkt_dev->flows, 0, MAX_CFLOWS * sizeof(struct flow_state)); pkt_dev->removal_mark = 0; pkt_dev->min_pkt_size = ETH_ZLEN; -- cgit v1.2.3 From ce14f8946a294ffa741ec29558a1c7e455cecd3b Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Sun, 22 May 2011 00:52:08 +0000 Subject: pktgen: refactor pg_init() code This also shrinks the object size a little. text data bss dec hex filename 28834 186 8 29028 7164 net/core/pktgen.o 28816 186 8 29010 7152 net/core/pktgen.o.AFTER Signed-off-by: WANG Cong Cc: "David Miller" , Signed-off-by: David S. Miller --- net/core/pktgen.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 3b85c0dffa61..f76079cd750c 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -3707,6 +3707,7 @@ static int __init pg_init(void) { int cpu; struct proc_dir_entry *pe; + int ret = 0; pr_info("%s", version); @@ -3717,11 +3718,10 @@ static int __init pg_init(void) pe = proc_create(PGCTRL, 0600, pg_proc_dir, &pktgen_fops); if (pe == NULL) { pr_err("ERROR: cannot create %s procfs entry\n", PGCTRL); - proc_net_remove(&init_net, PG_PROC_DIR); - return -EINVAL; + ret = -EINVAL; + goto remove_dir; } - /* Register us to receive netdevice events */ register_netdevice_notifier(&pktgen_notifier_block); for_each_online_cpu(cpu) { @@ -3735,13 +3735,18 @@ static int __init pg_init(void) if (list_empty(&pktgen_threads)) { pr_err("ERROR: Initialization failed for all threads\n"); - unregister_netdevice_notifier(&pktgen_notifier_block); - remove_proc_entry(PGCTRL, pg_proc_dir); - proc_net_remove(&init_net, PG_PROC_DIR); - return -ENODEV; + ret = -ENODEV; + goto unregister; } return 0; + + unregister: + unregister_netdevice_notifier(&pktgen_notifier_block); + remove_proc_entry(PGCTRL, pg_proc_dir); + remove_dir: + proc_net_remove(&init_net, PG_PROC_DIR); + return ret; } static void __exit pg_cleanup(void) -- cgit v1.2.3