Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH 3/4] xen-netback: remove skb in xen_netbk_alloc_page
From: Ian Campbell @ 2013-03-18 11:37 UTC (permalink / raw)
  To: Wei Liu
  Cc: netdev@vger.kernel.org, xen-devel@lists.xen.org,
	konrad.wilk@oracle.com, annie.li@oracle.com
In-Reply-To: <1363602955-24790-4-git-send-email-wei.liu2@citrix.com>

On Mon, 2013-03-18 at 10:35 +0000, Wei Liu wrote:
> This variable is never used.
> 
> Signed-off-by: Wei Liu <wei.liu2@citrix.com>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

> ---
>  drivers/net/xen-netback/netback.c |    5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
> index da726a3..6e8e51a 100644
> --- a/drivers/net/xen-netback/netback.c
> +++ b/drivers/net/xen-netback/netback.c
> @@ -948,7 +948,6 @@ static int netbk_count_requests(struct xenvif *vif,
>  }
>  
>  static struct page *xen_netbk_alloc_page(struct xen_netbk *netbk,
> -					 struct sk_buff *skb,
>  					 u16 pending_idx)
>  {
>  	struct page *page;
> @@ -982,7 +981,7 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk,
>  
>  		index = pending_index(netbk->pending_cons++);
>  		pending_idx = netbk->pending_ring[index];
> -		page = xen_netbk_alloc_page(netbk, skb, pending_idx);
> +		page = xen_netbk_alloc_page(netbk, pending_idx);
>  		if (!page)
>  			goto err;
>  
> @@ -1387,7 +1386,7 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
>  		}
>  
>  		/* XXX could copy straight to head */
> -		page = xen_netbk_alloc_page(netbk, skb, pending_idx);
> +		page = xen_netbk_alloc_page(netbk, pending_idx);
>  		if (!page) {
>  			kfree_skb(skb);
>  			netbk_tx_err(vif, &txreq, idx);

^ permalink raw reply

* [PULL] vhost: tcm_vhost fixes for 3.9
From: Michael S. Tsirkin @ 2013-03-18 11:20 UTC (permalink / raw)
  To: David Miller
  Cc: kvm, virtualization, netdev, linux-kernel, asias, mst, nab,
	target-devel

The following changes since commit 8c6216d7f118a128678270824b6a1286a63863ca:

  Revert "ip_gre: make ipgre_tunnel_xmit() not parse network header as IP unconditionally" (2013-03-16 23:00:41 -0400)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git vhost-net

for you to fetch changes up to deb7cb067dabd3be625eaf5495da8bdc97377fc1:

  tcm_vhost: Flush vhost_work in vhost_scsi_flush() (2013-03-17 13:04:14 +0200)

----------------------------------------------------------------
Asias He (2):
      tcm_vhost: Add missed lock in vhost_scsi_clear_endpoint()
      tcm_vhost: Flush vhost_work in vhost_scsi_flush()

 drivers/vhost/tcm_vhost.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

^ permalink raw reply

* Re: sctp: hang in sctp_remaddr_seq_show
From: Neil Horman @ 2013-03-18 11:04 UTC (permalink / raw)
  To: Sasha Levin
  Cc: vyasevich, sri, David S. Miller, linux-sctp, netdev, Dave Jones,
	linux-kernel@vger.kernel.org
In-Reply-To: <51434D78.9030308@oracle.com>

On Fri, Mar 15, 2013 at 12:34:00PM -0400, Sasha Levin wrote:
> Hi all,
> 
> While fuzzing with trinity inside a KVM tools guest running latest -next kernel,
> I've stumbled on an interesting hang related to sctp.
> 
> After some fuzzing, I get a hang message about procfs not able to grab a hold
> of a mutex for one of the files:
> 
> [  375.900309] INFO: task trinity-child21:7178 blocked for more than 120 seconds.
> [  375.901767] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> [  375.903022] trinity-child21 D ffff88009b9f74a8  5336  7178   7121 0x00000004
> [  375.904211]  ffff88009ba79cb8 0000000000000002 ffff8800abf48690 ffff8800abf48690
> [  375.905972]  ffff880075308000 ffff88009c798000 ffff88009ba79cb8 00000000001d7140
> [  375.907263]  ffff88009c798000 ffff88009ba79fd8 00000000001d7140 00000000001d7140
> [  375.908987] Call Trace:
> [  375.909415]  [<ffffffff83d89569>] __schedule+0x2e9/0x3b0
> [  375.910795]  [<ffffffff83d89795>] schedule+0x55/0x60
> [  375.911611]  [<ffffffff83d89ae3>] schedule_preempt_disabled+0x13/0x20
> [  375.912644]  [<ffffffff83d87b7d>] __mutex_lock_common+0x36d/0x5a0
> [  375.913986]  [<ffffffff8129f11a>] ? seq_read+0x3a/0x3d0
> [  375.914838]  [<ffffffff8129f11a>] ? seq_read+0x3a/0x3d0
> [  375.916187]  [<ffffffff8129f0e0>] ? seq_lseek+0x110/0x110
> [  375.917075]  [<ffffffff83d87edf>] mutex_lock_nested+0x3f/0x50
> [  375.918005]  [<ffffffff8129f11a>] seq_read+0x3a/0x3d0
> [  375.919124]  [<ffffffff819f19cd>] ? delay_tsc+0xdd/0x110
> [  375.920916]  [<ffffffff8129f0e0>] ? seq_lseek+0x110/0x110
> [  375.921794]  [<ffffffff8129f0e0>] ? seq_lseek+0x110/0x110
> [  375.922966]  [<ffffffff812e7b61>] proc_reg_read+0x201/0x230
> [  375.923870]  [<ffffffff812e7960>] ? proc_reg_write+0x230/0x230
> [  375.924820]  [<ffffffff81279e05>] vfs_read+0xb5/0x180
> [  375.925668]  [<ffffffff81279f20>] SyS_read+0x50/0xa0
> [  375.926476]  [<ffffffff83d946d8>] tracesys+0xe1/0xe6
> [  375.940223] 1 lock held by trinity-child21/7178:
> [  375.940985]  #0:  (&p->lock){+.+.+.}, at: [<ffffffff8129f11a>] seq_read+0x3a/0x3d
> 
> Digging deeper, there's another thread that's stuck holding that lock:
> 
> [  381.880804] trinity-child97 R  running task     4856  9490   7121 0x00000004
> [  381.882064]  ffff880084cad708 0000000000000002 ffff8800bbbd71f8 ffff8800bbbd71f8
> [  381.883341]  ffff8800b9490000 ffff88009a5e8000 ffff880084cad708 00000000001d7140
> [  381.884652]  ffff88009a5e8000 ffff880084cadfd8 00000000001d7140 00000000001d7140
> [  381.885977] Call Trace:
> [  381.886392]  [<ffffffff83d89569>] __schedule+0x2e9/0x3b0
> [  381.887238]  [<ffffffff83d89714>] preempt_schedule+0x44/0x70
> [  381.888175]  [<ffffffff83b5674a>] ? sctp_remaddr_seq_show+0x2da/0x2f0
> [  381.889314]  [<ffffffff8110e8a8>] local_bh_enable+0x128/0x140
> [  381.890292]  [<ffffffff83b5674a>] sctp_remaddr_seq_show+0x2da/0x2f0
> [  381.891397]  [<ffffffff83b56497>] ? sctp_remaddr_seq_show+0x27/0x2f0
> [  381.892448]  [<ffffffff8129f11a>] ? seq_read+0x3a/0x3d0
> [  381.893308]  [<ffffffff8129ec50>] traverse+0xe0/0x1f0
> [  381.894135]  [<ffffffff8129f0e0>] ? seq_lseek+0x110/0x110
> [  381.895100]  [<ffffffff8129f0e0>] ? seq_lseek+0x110/0x110
> [  381.896074]  [<ffffffff8129f13c>] seq_read+0x5c/0x3d0
> [  381.896912]  [<ffffffff819f19cd>] ? delay_tsc+0xdd/0x110
> [  381.897796]  [<ffffffff8129f0e0>] ? seq_lseek+0x110/0x110
> [  381.898734]  [<ffffffff8129f0e0>] ? seq_lseek+0x110/0x110
> [  381.899629]  [<ffffffff812e7b61>] proc_reg_read+0x201/0x230
> [  381.900592]  [<ffffffff812e7960>] ? proc_reg_write+0x230/0x230
> [  381.901614]  [<ffffffff812e7960>] ? proc_reg_write+0x230/0x230
> [  381.902543]  [<ffffffff8127a22b>] do_loop_readv_writev+0x4b/0x90
> [  381.903480]  [<ffffffff8127a4a6>] do_readv_writev+0xf6/0x1d0
> [  381.904456]  [<ffffffff8109b1c8>] ? kvm_clock_read+0x38/0x70
> [  381.905460]  [<ffffffff8127a61e>] vfs_readv+0x3e/0x60
> [  381.906306]  [<ffffffff812abb31>] default_file_splice_read+0x1e1/0x320
> [  381.907365]  [<ffffffff81259396>] ? deactivate_slab+0x7d6/0x820
> [  381.908412]  [<ffffffff81259396>] ? deactivate_slab+0x7d6/0x820
> [  381.909404]  [<ffffffff8117db31>] ? __lock_release+0xf1/0x110
> [  381.910435]  [<ffffffff81259396>] ? deactivate_slab+0x7d6/0x820
> [  381.911483]  [<ffffffff81a06ee8>] ? do_raw_spin_unlock+0xc8/0xe0
> [  381.912478]  [<ffffffff83d8b3d0>] ? _raw_spin_unlock+0x30/0x60
> [  381.913438]  [<ffffffff81259396>] ? deactivate_slab+0x7d6/0x820
> [  381.914478]  [<ffffffff812830ae>] ? alloc_pipe_info+0x3e/0xa0
> [  381.915504]  [<ffffffff812830ae>] ? alloc_pipe_info+0x3e/0xa0
> [  381.916461]  [<ffffffff812830ae>] ? alloc_pipe_info+0x3e/0xa0
> [  381.917418]  [<ffffffff83d00b0c>] ? __slab_alloc.isra.34+0x2ed/0x31f
> [  381.918533]  [<ffffffff8117acf8>] ? trace_hardirqs_on_caller+0x168/0x1a0
> [  381.919637]  [<ffffffff8117ae35>] ? debug_check_no_locks_freed+0xf5/0x130
> [  381.920799]  [<ffffffff812a9ef0>] ? page_cache_pipe_buf_release+0x20/0x20
> [  381.921963]  [<ffffffff812aa823>] do_splice_to+0x83/0xb0
> [  381.922849]  [<ffffffff812aabee>] splice_direct_to_actor+0xce/0x1c0
> [  381.923874]  [<ffffffff812aa780>] ? do_splice_from+0xb0/0xb0
> [  381.924855]  [<ffffffff812ac398>] do_splice_direct+0x48/0x60
> [  381.925865]  [<ffffffff81279a25>] do_sendfile+0x165/0x310
> [  381.926763]  [<ffffffff8117ad3d>] ? trace_hardirqs_on+0xd/0x10
> [  381.927722]  [<ffffffff8127aaaa>] SyS_sendfile64+0x8a/0xc0
> [  381.928702]  [<ffffffff83d94675>] ? tracesys+0x7e/0xe6
> [  381.929556]  [<ffffffff83d946d8>] tracesys+0xe1/0xe6
> 
> It has gone to sleep while holding the proc mutex we're trying to acquire and
> never woke up!
> 
> Looking at the code, we see:
> 
>         rcu_read_unlock();
>         read_unlock(&head->lock);
>         sctp_local_bh_enable(); <--- here
> 
> It hangs on local_bh_enable().
> 
> It seems that local_bh_enable() calls preempt_check_resched() which never
> gets woken up. Why? I have no clue.
> 
> It's also pretty reproducible with sctp.
> 
I'm not sure why the process would never get back to the schedule, but looking
at the sctp_remaddr_seq_show function, I think that we should convert this
sequence:
	sctp_local_bh_disable();
	read_lock(&head->lock);
	rcu_read_lock();

to this:
	read_lock(&head->lock);
	rcu_read_lock_bh();

Neil

^ permalink raw reply

* [patch] RxRPC: use copy_to_user() instead of memcpy()
From: Dan Carpenter @ 2013-03-18 10:55 UTC (permalink / raw)
  To: David S. Miller, David Howells; +Cc: netdev, kernel-janitors

This is a user pointer.  Changing the memcpy() to copy_to_user()
fixes a hang on my system.

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
---
I'm not very familiar with this code, so please review this
carefully.

diff --git a/net/rxrpc/ar-recvmsg.c b/net/rxrpc/ar-recvmsg.c
index 4b48687..428501f 100644
--- a/net/rxrpc/ar-recvmsg.c
+++ b/net/rxrpc/ar-recvmsg.c
@@ -143,10 +143,15 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock,
 
 		/* copy the peer address and timestamp */
 		if (!continue_call) {
-			if (msg->msg_name && msg->msg_namelen > 0)
-				memcpy(msg->msg_name,
-				       &call->conn->trans->peer->srx,
-				       sizeof(call->conn->trans->peer->srx));
+			if (msg->msg_name && msg->msg_namelen > 0) {
+				ret = copy_to_user((void __user *)msg->msg_name,
+					&call->conn->trans->peer->srx,
+					sizeof(call->conn->trans->peer->srx));
+				if (ret) {
+					ret = -EFAULT;
+					goto copy_error;
+				}
+			}
 			sock_recv_ts_and_drops(msg, &rx->sk, skb);
 		}
 

^ permalink raw reply related

* [PATCH regression/bisected] Revert "brcmsmac: support 4313iPA"
From: David Herrmann @ 2013-03-18 10:45 UTC (permalink / raw)
  To: linux-wireless-u79uwXL29TY76Z2rM5mHXA
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, Arend van Spriel,
	John W. Linville, Piotr Haber,
	brcm80211-dev-list-dY08KVG/lbpWk0Htik3J/w,
	netdev-u79uwXL29TY76Z2rM5mHXA, Pieter-Paul Giesberts,
	David Herrmann

This reverts commit b6fc28a158076ca2764edc9a6d1e1402f56e1c0c. It breaks
wireless AP reconnection on: (14e4:4727)
  Broadcom Corporation BCM4313 802.11b/g/n Wireless LAN Controller

Any attempt to reconnect to an AP results in timeouts no matter how near to the
AP I am:
 00:10:40 $nb kernel: wlan0: authenticate with 00:18:39:0a:8e:23
 00:10:40 $nb kernel: wlan0: direct probe to 00:18:39:0a:8e:23 (try 1/3)
 00:10:40 $nb kernel: wlan0: direct probe to 00:18:39:0a:8e:23 (try 2/3)
 00:10:41 $nb kernel: wlan0: direct probe to 00:18:39:0a:8e:23 (try 3/3)
 00:10:41 $nb kernel: wlan0: authentication with 00:18:39:0a:8e:23 timed out
---
Hi

I tried coming up with a fix instead of reverting this commit, but the commit is
way to big for me to understand what's going on. Sorry.

With linux-3.8 connecting to an AP broke on my machine. I could connect to an AP
one time, but any further attempt resulted in:
 00:10:40 $nb kernel: wlan0: authenticate with 00:18:39:0a:8e:23
 00:10:40 $nb kernel: wlan0: direct probe to 00:18:39:0a:8e:23 (try 1/3)
 00:10:40 $nb kernel: wlan0: direct probe to 00:18:39:0a:8e:23 (try 2/3)
 00:10:41 $nb kernel: wlan0: direct probe to 00:18:39:0a:8e:23 (try 3/3)
 00:10:41 $nb kernel: wlan0: authentication with 00:18:39:0a:8e:23 timed out

Even sitting right next to the AP didn't help so I started bisecting and it
turned out to be:
  "brcmsmac: support 4313iPA" b6fc28a158076ca2764edc9a6d1e1402f56e1c0c
Please revert it.

Thanks
David


wpa.conf:
  ctrl_interface=/run/wpa_supplicant
  ctrl_interface_group=wheel
  network={
    ssid="$name"
    proto=RSN WPA
    psk="$pw"
  }

iwlist wlan0 scan:
          Cell 05 - Address: 00:18:39:0A:8E:23
                    Channel:9
                    Frequency:2.452 GHz (Channel 9)
                    Quality=44/70  Signal level=-66 dBm
                    Encryption key:on
                    ESSID:"$name"
                    Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 11 Mb/s; 18 Mb/s
                              24 Mb/s; 36 Mb/s; 54 Mb/s
                    Bit Rates:6 Mb/s; 9 Mb/s; 12 Mb/s; 48 Mb/s
                    Mode:Master
                    Extra:tsf=0000004f3b16bb1d
                    Extra: Last beacon: 21ms ago
                    IE: Unknown: 000B626C6F636B666C6F657465
                    IE: Unknown: 010882848B962430486C
                    IE: Unknown: 030109
                    IE: Unknown: 2A0104
                    IE: Unknown: 2F0104
                    IE: IEEE 802.11i/WPA2 Version 1
                        Group Cipher : CCMP
                        Pairwise Ciphers (1) : CCMP
                        Authentication Suites (1) : PSK
                    IE: Unknown: 32040C121860
                    IE: Unknown: DD06001018020204


 .../net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c  | 369 ++++++++-------------
 .../wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c   |  64 ++--
 2 files changed, 162 insertions(+), 271 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
index 21a8242..18d3764 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
@@ -1137,9 +1137,8 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
 	gain0_15 = ((biq1 & 0xf) << 12) |
 		   ((tia & 0xf) << 8) |
 		   ((lna2 & 0x3) << 6) |
-		   ((lna2 & 0x3) << 4) |
-		   ((lna1 & 0x3) << 2) |
-		   ((lna1 & 0x3) << 0);
+		   ((lna2 &
+		     0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0);
 
 	mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
 	mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
@@ -1157,8 +1156,6 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
 	}
 
 	mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0);
-	mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
-	mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3);
 
 }
 
@@ -1331,43 +1328,6 @@ static u32 wlc_lcnphy_measure_digital_power(struct brcms_phy *pi, u16 nsamples)
 	return (iq_est.i_pwr + iq_est.q_pwr) / nsamples;
 }
 
-static bool wlc_lcnphy_rx_iq_cal_gain(struct brcms_phy *pi, u16 biq1_gain,
-				      u16 tia_gain, u16 lna2_gain)
-{
-	u32 i_thresh_l, q_thresh_l;
-	u32 i_thresh_h, q_thresh_h;
-	struct lcnphy_iq_est iq_est_h, iq_est_l;
-
-	wlc_lcnphy_set_rx_gain_by_distribution(pi, 0, 0, 0, biq1_gain, tia_gain,
-					       lna2_gain, 0);
-
-	wlc_lcnphy_rx_gain_override_enable(pi, true);
-	wlc_lcnphy_start_tx_tone(pi, 2000, (40 >> 1), 0);
-	udelay(500);
-	write_radio_reg(pi, RADIO_2064_REG112, 0);
-	if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_l))
-		return false;
-
-	wlc_lcnphy_start_tx_tone(pi, 2000, 40, 0);
-	udelay(500);
-	write_radio_reg(pi, RADIO_2064_REG112, 0);
-	if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_h))
-		return false;
-
-	i_thresh_l = (iq_est_l.i_pwr << 1);
-	i_thresh_h = (iq_est_l.i_pwr << 2) + iq_est_l.i_pwr;
-
-	q_thresh_l = (iq_est_l.q_pwr << 1);
-	q_thresh_h = (iq_est_l.q_pwr << 2) + iq_est_l.q_pwr;
-	if ((iq_est_h.i_pwr > i_thresh_l) &&
-	    (iq_est_h.i_pwr < i_thresh_h) &&
-	    (iq_est_h.q_pwr > q_thresh_l) &&
-	    (iq_est_h.q_pwr < q_thresh_h))
-		return true;
-
-	return false;
-}
-
 static bool
 wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
 		     const struct lcnphy_rx_iqcomp *iqcomp,
@@ -1382,8 +1342,8 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
 	    RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old,
 	    rfoverride3_old, rfoverride3val_old, rfoverride4_old,
 	    rfoverride4val_old, afectrlovr_old, afectrlovrval_old;
-	int tia_gain, lna2_gain, biq1_gain;
-	bool set_gain;
+	int tia_gain;
+	u32 received_power, rx_pwr_threshold;
 	u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
 	u16 values_to_save[11];
 	s16 *ptr;
@@ -1408,134 +1368,126 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
 		goto cal_done;
 	}
 
-	WARN_ON(module != 1);
-	tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
-
-	for (i = 0; i < 11; i++)
-		values_to_save[i] =
-			read_radio_reg(pi, rxiq_cal_rf_reg[i]);
-	Core1TxControl_old = read_phy_reg(pi, 0x631);
-
-	or_phy_reg(pi, 0x631, 0x0015);
-
-	RFOverride0_old = read_phy_reg(pi, 0x44c);
-	RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
-	rfoverride2_old = read_phy_reg(pi, 0x4b0);
-	rfoverride2val_old = read_phy_reg(pi, 0x4b1);
-	rfoverride3_old = read_phy_reg(pi, 0x4f9);
-	rfoverride3val_old = read_phy_reg(pi, 0x4fa);
-	rfoverride4_old = read_phy_reg(pi, 0x938);
-	rfoverride4val_old = read_phy_reg(pi, 0x939);
-	afectrlovr_old = read_phy_reg(pi, 0x43b);
-	afectrlovrval_old = read_phy_reg(pi, 0x43c);
-	old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
-	old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
-
-	tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
-	if (tx_gain_override_old) {
-		wlc_lcnphy_get_tx_gain(pi, &old_gains);
-		tx_gain_index_old = pi_lcn->lcnphy_current_index;
-	}
-
-	wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
+	if (module == 1) {
 
-	mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
-	mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
+		tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
 
-	mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
-	mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
+		for (i = 0; i < 11; i++)
+			values_to_save[i] =
+				read_radio_reg(pi, rxiq_cal_rf_reg[i]);
+		Core1TxControl_old = read_phy_reg(pi, 0x631);
+
+		or_phy_reg(pi, 0x631, 0x0015);
+
+		RFOverride0_old = read_phy_reg(pi, 0x44c);
+		RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
+		rfoverride2_old = read_phy_reg(pi, 0x4b0);
+		rfoverride2val_old = read_phy_reg(pi, 0x4b1);
+		rfoverride3_old = read_phy_reg(pi, 0x4f9);
+		rfoverride3val_old = read_phy_reg(pi, 0x4fa);
+		rfoverride4_old = read_phy_reg(pi, 0x938);
+		rfoverride4val_old = read_phy_reg(pi, 0x939);
+		afectrlovr_old = read_phy_reg(pi, 0x43b);
+		afectrlovrval_old = read_phy_reg(pi, 0x43c);
+		old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+		old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
+
+		tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
+		if (tx_gain_override_old) {
+			wlc_lcnphy_get_tx_gain(pi, &old_gains);
+			tx_gain_index_old = pi_lcn->lcnphy_current_index;
+		}
 
-	write_radio_reg(pi, RADIO_2064_REG116, 0x06);
-	write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
-	write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
-	write_radio_reg(pi, RADIO_2064_REG098, 0x03);
-	write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
-	mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
-	write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
-	write_radio_reg(pi, RADIO_2064_REG114, 0x01);
-	write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
-	write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
-
-	mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
-	mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
-	mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
-	mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
-	mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
-	mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
-	mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
-	mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
-	mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
-	mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
+		wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
 
-	mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
-	mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
+		mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
+		mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
 
-	write_phy_reg(pi, 0x6da, 0xffff);
-	or_phy_reg(pi, 0x6db, 0x3);
+		mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
+		mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
 
-	wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
-	set_gain = false;
-
-	lna2_gain = 3;
-	while ((lna2_gain >= 0) && !set_gain) {
-		tia_gain = 4;
-
-		while ((tia_gain >= 0) && !set_gain) {
-			biq1_gain = 6;
-
-			while ((biq1_gain >= 0) && !set_gain) {
-				set_gain = wlc_lcnphy_rx_iq_cal_gain(pi,
-								     (u16)
-								     biq1_gain,
-								     (u16)
-								     tia_gain,
-								     (u16)
-								     lna2_gain);
-				biq1_gain -= 1;
-			}
+		write_radio_reg(pi, RADIO_2064_REG116, 0x06);
+		write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
+		write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
+		write_radio_reg(pi, RADIO_2064_REG098, 0x03);
+		write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
+		mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
+		write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
+		write_radio_reg(pi, RADIO_2064_REG114, 0x01);
+		write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
+		write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
+
+		mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
+		mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
+		mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
+		mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
+		mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
+		mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
+		mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
+		mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
+		mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
+		mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
+
+		mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
+		mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
+
+		wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0);
+		write_phy_reg(pi, 0x6da, 0xffff);
+		or_phy_reg(pi, 0x6db, 0x3);
+		wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
+		wlc_lcnphy_rx_gain_override_enable(pi, true);
+
+		tia_gain = 8;
+		rx_pwr_threshold = 950;
+		while (tia_gain > 0) {
 			tia_gain -= 1;
+			wlc_lcnphy_set_rx_gain_by_distribution(pi,
+							       0, 0, 2, 2,
+							       (u16)
+							       tia_gain, 1, 0);
+			udelay(500);
+
+			received_power =
+				wlc_lcnphy_measure_digital_power(pi, 2000);
+			if (received_power < rx_pwr_threshold)
+				break;
 		}
-		lna2_gain -= 1;
-	}
+		result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff);
 
-	if (set_gain)
-		result = wlc_lcnphy_calc_rx_iq_comp(pi, 1024);
-	else
-		result = false;
+		wlc_lcnphy_stop_tx_tone(pi);
 
-	wlc_lcnphy_stop_tx_tone(pi);
+		write_phy_reg(pi, 0x631, Core1TxControl_old);
 
-	write_phy_reg(pi, 0x631, Core1TxControl_old);
-
-	write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
-	write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
-	write_phy_reg(pi, 0x4b0, rfoverride2_old);
-	write_phy_reg(pi, 0x4b1, rfoverride2val_old);
-	write_phy_reg(pi, 0x4f9, rfoverride3_old);
-	write_phy_reg(pi, 0x4fa, rfoverride3val_old);
-	write_phy_reg(pi, 0x938, rfoverride4_old);
-	write_phy_reg(pi, 0x939, rfoverride4val_old);
-	write_phy_reg(pi, 0x43b, afectrlovr_old);
-	write_phy_reg(pi, 0x43c, afectrlovrval_old);
-	write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
-	write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
+		write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
+		write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
+		write_phy_reg(pi, 0x4b0, rfoverride2_old);
+		write_phy_reg(pi, 0x4b1, rfoverride2val_old);
+		write_phy_reg(pi, 0x4f9, rfoverride3_old);
+		write_phy_reg(pi, 0x4fa, rfoverride3val_old);
+		write_phy_reg(pi, 0x938, rfoverride4_old);
+		write_phy_reg(pi, 0x939, rfoverride4val_old);
+		write_phy_reg(pi, 0x43b, afectrlovr_old);
+		write_phy_reg(pi, 0x43c, afectrlovrval_old);
+		write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
+		write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
 
-	wlc_lcnphy_clear_trsw_override(pi);
+		wlc_lcnphy_clear_trsw_override(pi);
 
-	mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
+		mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
 
-	for (i = 0; i < 11; i++)
-		write_radio_reg(pi, rxiq_cal_rf_reg[i],
-				values_to_save[i]);
+		for (i = 0; i < 11; i++)
+			write_radio_reg(pi, rxiq_cal_rf_reg[i],
+					values_to_save[i]);
 
-	if (tx_gain_override_old)
-		wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
-	else
-		wlc_lcnphy_disable_tx_gain_override(pi);
+		if (tx_gain_override_old)
+			wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
+		else
+			wlc_lcnphy_disable_tx_gain_override(pi);
 
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
-	wlc_lcnphy_rx_gain_override_enable(pi, false);
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
+		wlc_lcnphy_rx_gain_override_enable(pi, false);
+	}
 
 cal_done:
 	kfree(ptr);
@@ -1829,17 +1781,6 @@ wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
 		write_radio_reg(pi, RADIO_2064_REG038, 3);
 		write_radio_reg(pi, RADIO_2064_REG091, 7);
 	}
-
-	if (!(pi->sh->boardflags & BFL_FEM)) {
-		u8 reg038[14] = {0xd, 0xe, 0xd, 0xd, 0xd, 0xc,
-			0xa, 0xb, 0xb, 0x3, 0x3, 0x2, 0x0, 0x0};
-
-		write_radio_reg(pi, RADIO_2064_REG02A, 0xf);
-		write_radio_reg(pi, RADIO_2064_REG091, 0x3);
-		write_radio_reg(pi, RADIO_2064_REG038, 0x3);
-
-		write_radio_reg(pi, RADIO_2064_REG038, reg038[channel - 1]);
-	}
 }
 
 static int
@@ -2034,16 +1975,6 @@ wlc_lcnphy_set_tssi_mux(struct brcms_phy *pi, enum lcnphy_tssi_mode pos)
 		} else {
 			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1);
 			mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
-			mod_radio_reg(pi, RADIO_2064_REG028, 0x1, 0x0);
-			mod_radio_reg(pi, RADIO_2064_REG11A, 0x4, 1<<2);
-			mod_radio_reg(pi, RADIO_2064_REG036, 0x10, 0x0);
-			mod_radio_reg(pi, RADIO_2064_REG11A, 0x10, 1<<4);
-			mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0);
-			mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x77);
-			mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0xe<<1);
-			mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1<<7);
-			mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 1<<1);
-			mod_radio_reg(pi, RADIO_2064_REG029, 0xf0, 0<<4);
 		}
 	} else {
 		mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2);
@@ -2130,14 +2061,12 @@ static void wlc_lcnphy_pwrctrl_rssiparams(struct brcms_phy *pi)
 		    (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
 
 	mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5));
-	mod_radio_reg(pi, RADIO_2064_REG07C, (1 << 0), (1 << 0));
 }
 
 static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
 {
 	struct phytbl_info tab;
 	u32 rfseq, ind;
-	u8 tssi_sel;
 
 	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
 	tab.tbl_width = 32;
@@ -2159,13 +2088,7 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
 
 	mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4);
 
-	if (pi->sh->boardflags & BFL_FEM) {
-		tssi_sel = 0x1;
-		wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
-	} else {
-		tssi_sel = 0xe;
-		wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_POST_PA);
-	}
+	wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
 	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
 
 	mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15);
@@ -2201,10 +2124,9 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
 	mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0);
 
 	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
-		mod_radio_reg(pi, RADIO_2064_REG028, 0xf, tssi_sel);
+		mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe);
 		mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
 	} else {
-		mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, tssi_sel << 1);
 		mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
 		mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3);
 	}
@@ -2251,10 +2173,6 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
 
 	mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8);
 
-	mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x0);
-	mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0);
-	mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
-
 	wlc_lcnphy_pwrctrl_rssiparams(pi);
 }
 
@@ -2873,8 +2791,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
 		read_radio_reg(pi, RADIO_2064_REG007) & 1;
 	u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10;
 	u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4;
-	u8 SAVE_bbmult = wlc_lcnphy_get_bbmult(pi);
-
 	idleTssi = read_phy_reg(pi, 0x4ab);
 	suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
 			 MCTL_EN_MAC));
@@ -2892,12 +2808,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
 	mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4);
 	mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2);
 	wlc_lcnphy_tssi_setup(pi);
-
-	mod_phy_reg(pi, 0x4d7, (0x1 << 0), (1 << 0));
-	mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1 << 6));
-
-	wlc_lcnphy_set_bbmult(pi, 0x0);
-
 	wlc_phy_do_dummy_tx(pi, true, OFF);
 	idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
 		    >> 0);
@@ -2919,7 +2829,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
 
 	mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12);
 
-	wlc_lcnphy_set_bbmult(pi, SAVE_bbmult);
 	wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old);
 	wlc_lcnphy_set_tx_gain(pi, &old_gains);
 	wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
@@ -3133,11 +3042,6 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi)
 			wlc_lcnphy_write_table(pi, &tab);
 			tab.tbl_offset++;
 		}
-		mod_phy_reg(pi, 0x4d0, (0x1 << 0), (0) << 0);
-		mod_phy_reg(pi, 0x4d3, (0xff << 0), (0) << 0);
-		mod_phy_reg(pi, 0x4d3, (0xff << 8), (0) << 8);
-		mod_phy_reg(pi, 0x4d0, (0x1 << 4), (0) << 4);
-		mod_phy_reg(pi, 0x4d0, (0x1 << 2), (0) << 2);
 
 		mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7);
 
@@ -3939,6 +3843,7 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
 	target_gains.pad_gain = 21;
 	target_gains.dac_gain = 0;
 	wlc_lcnphy_set_tx_gain(pi, &target_gains);
+	wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
 
 	if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) {
 
@@ -3949,7 +3854,6 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
 					lcnphy_recal ? LCNPHY_CAL_RECAL :
 					LCNPHY_CAL_FULL), false);
 	} else {
-		wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
 		wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
 	}
 
@@ -4374,22 +4278,17 @@ wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi,
 	if (CHSPEC_IS5G(pi->radio_chanspec))
 		pa_gain = 0x70;
 	else
-		pa_gain = 0x60;
+		pa_gain = 0x70;
 
 	if (pi->sh->boardflags & BFL_FEM)
 		pa_gain = 0x10;
-
 	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
 	tab.tbl_width = 32;
 	tab.tbl_len = 1;
 	tab.tbl_ptr = &val;
 
 	for (j = 0; j < 128; j++) {
-		if (pi->sh->boardflags & BFL_FEM)
-			gm_gain = gain_table[j].gm;
-		else
-			gm_gain = 15;
-
+		gm_gain = gain_table[j].gm;
 		val = (((u32) pa_gain << 24) |
 		       (gain_table[j].pad << 16) |
 		       (gain_table[j].pga << 8) | gm_gain);
@@ -4600,10 +4499,7 @@ static void wlc_radio_2064_init(struct brcms_phy *pi)
 
 	write_phy_reg(pi, 0x4ea, 0x4688);
 
-	if (pi->sh->boardflags & BFL_FEM)
-		mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
-	else
-		mod_phy_reg(pi, 0x4eb, (0x7 << 0), 3 << 0);
+	mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
 
 	mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
 
@@ -4614,13 +4510,6 @@ static void wlc_radio_2064_init(struct brcms_phy *pi)
 	wlc_lcnphy_rcal(pi);
 
 	wlc_lcnphy_rc_cal(pi);
-
-	if (!(pi->sh->boardflags & BFL_FEM)) {
-		write_radio_reg(pi, RADIO_2064_REG032, 0x6f);
-		write_radio_reg(pi, RADIO_2064_REG033, 0x19);
-		write_radio_reg(pi, RADIO_2064_REG039, 0xe);
-	}
-
 }
 
 static void wlc_lcnphy_radio_init(struct brcms_phy *pi)
@@ -4650,20 +4539,22 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
 		wlc_lcnphy_write_table(pi, &tab);
 	}
 
-	if (!(pi->sh->boardflags & BFL_FEM)) {
-		tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
-		tab.tbl_width = 16;
-		tab.tbl_ptr = &val;
-		tab.tbl_len = 1;
+	tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
+	tab.tbl_width = 16;
+	tab.tbl_ptr = &val;
+	tab.tbl_len = 1;
 
-		val = 150;
-		tab.tbl_offset = 0;
-		wlc_lcnphy_write_table(pi, &tab);
+	val = 114;
+	tab.tbl_offset = 0;
+	wlc_lcnphy_write_table(pi, &tab);
 
-		val = 220;
-		tab.tbl_offset = 1;
-		wlc_lcnphy_write_table(pi, &tab);
-	}
+	val = 130;
+	tab.tbl_offset = 1;
+	wlc_lcnphy_write_table(pi, &tab);
+
+	val = 6;
+	tab.tbl_offset = 8;
+	wlc_lcnphy_write_table(pi, &tab);
 
 	if (CHSPEC_IS2G(pi->radio_chanspec)) {
 		if (pi->sh->boardflags & BFL_FEM)
@@ -5055,7 +4946,6 @@ void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec)
 		wlc_lcnphy_load_tx_iir_filter(pi, true, 3);
 
 	mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3);
-	wlc_lcnphy_tssi_setup(pi);
 }
 
 void wlc_phy_detach_lcnphy(struct brcms_phy *pi)
@@ -5094,7 +4984,8 @@ bool wlc_phy_attach_lcnphy(struct brcms_phy *pi)
 	if (!wlc_phy_txpwr_srom_read_lcnphy(pi))
 		return false;
 
-	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+	if ((pi->sh->boardflags & BFL_FEM) &&
+	    (LCNREV_IS(pi->pubpi.phy_rev, 1))) {
 		if (pi_lcn->lcnphy_tempsense_option == 3) {
 			pi->hwpwrctrl = true;
 			pi->hwpwrctrl_capable = true;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
index b7e95ac..622c01c 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
@@ -1992,70 +1992,70 @@ static const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = {
 };
 
 static const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = {
-	0x0009,
 	0x000a,
-	0x0005,
-	0x0006,
 	0x0009,
-	0x000a,
-	0x0005,
 	0x0006,
-	0x0009,
-	0x000a,
 	0x0005,
-	0x0006,
-	0x0009,
 	0x000a,
-	0x0005,
-	0x0006,
 	0x0009,
-	0x000a,
-	0x0005,
 	0x0006,
-	0x0009,
-	0x000a,
 	0x0005,
-	0x0006,
-	0x0009,
 	0x000a,
-	0x0005,
-	0x0006,
 	0x0009,
-	0x000a,
-	0x0005,
 	0x0006,
-	0x0009,
-	0x000a,
 	0x0005,
-	0x0006,
-	0x0009,
 	0x000a,
-	0x0005,
-	0x0006,
 	0x0009,
-	0x000a,
-	0x0005,
 	0x0006,
-	0x0009,
-	0x000a,
 	0x0005,
-	0x0006,
+	0x000a,
 	0x0009,
+	0x0006,
+	0x0005,
 	0x000a,
+	0x0009,
+	0x0006,
 	0x0005,
+	0x000a,
+	0x0009,
 	0x0006,
+	0x0005,
+	0x000a,
 	0x0009,
+	0x0006,
+	0x0005,
 	0x000a,
+	0x0009,
+	0x0006,
 	0x0005,
+	0x000a,
+	0x0009,
 	0x0006,
+	0x0005,
+	0x000a,
 	0x0009,
+	0x0006,
+	0x0005,
 	0x000a,
+	0x0009,
+	0x0006,
 	0x0005,
+	0x000a,
+	0x0009,
 	0x0006,
+	0x0005,
+	0x000a,
 	0x0009,
+	0x0006,
+	0x0005,
 	0x000a,
+	0x0009,
+	0x0006,
 	0x0005,
+	0x000a,
+	0x0009,
 	0x0006,
+	0x0005,
 };
 
 static const u16 dot11lcn_sw_ctrl_tbl_rev0[] = {
-- 
1.8.2

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH 4/4] xen-netback: coalesce slots before copying
From: Wei Liu @ 2013-03-18 10:35 UTC (permalink / raw)
  To: netdev, xen-devel; +Cc: ian.campbell, konrad.wilk, annie.li, Wei Liu
In-Reply-To: <1363602955-24790-1-git-send-email-wei.liu2@citrix.com>

This patch tries to coalesce tx requests when constructing grant copy
structures. It enables netback to deal with situation when frontend's
MAX_SKB_FRAGS is larger than backend's MAX_SKB_FRAGS.

It defines max_skb_slots, which is a estimation of the maximum number of slots
a guest can send, anything bigger than that is considered malicious. Now it is
set to 20, which should be enough to accommodate Linux (16 to 19) and possibly
Windows (19?).

Also change variable name from "frags" to "slots" in netbk_count_requests.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 drivers/net/xen-netback/netback.c |  204 ++++++++++++++++++++++++++++---------
 1 file changed, 157 insertions(+), 47 deletions(-)

diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 6e8e51a..d7bbce9 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -47,9 +47,20 @@
 #include <asm/xen/hypercall.h>
 #include <asm/xen/page.h>
 
+/*
+ * This is an estimation of the maximum possible frags a SKB might
+ * have, anything larger than this is considered malicious. Typically
+ * Linux has 16 to 19, Windows has 19(?).
+ */
+#define MAX_SKB_SLOTS_DEFAULT 20
+static unsigned int max_skb_slots = MAX_SKB_SLOTS_DEFAULT;
+module_param(max_skb_slots, uint, 0444);
+
 struct pending_tx_info {
-	struct xen_netif_tx_request req;
+	struct xen_netif_tx_request req; /* coalesced tx request  */
 	struct xenvif *vif;
+	unsigned int nr_tx_req; /* how many tx req we have in a chain (>=1) */
+	unsigned int start_idx; /* starting index of pending ring index */
 };
 typedef unsigned int pending_ring_idx_t;
 
@@ -251,7 +262,7 @@ static int max_required_rx_slots(struct xenvif *vif)
 	int max = DIV_ROUND_UP(vif->dev->mtu, PAGE_SIZE);
 
 	if (vif->can_sg || vif->gso || vif->gso_prefix)
-		max += MAX_SKB_FRAGS + 1; /* extra_info + frags */
+		max += max_skb_slots + 1; /* extra_info + frags */
 
 	return max;
 }
@@ -657,7 +668,7 @@ static void xen_netbk_rx_action(struct xen_netbk *netbk)
 		__skb_queue_tail(&rxq, skb);
 
 		/* Filled the batch queue? */
-		if (count + MAX_SKB_FRAGS >= XEN_NETIF_RX_RING_SIZE)
+		if (count + max_skb_slots >= XEN_NETIF_RX_RING_SIZE)
 			break;
 	}
 
@@ -908,34 +919,34 @@ static int netbk_count_requests(struct xenvif *vif,
 				int work_to_do)
 {
 	RING_IDX cons = vif->tx.req_cons;
-	int frags = 0;
+	int slots = 0;
 
 	if (!(first->flags & XEN_NETTXF_more_data))
 		return 0;
 
 	do {
-		if (frags >= work_to_do) {
-			netdev_err(vif->dev, "Need more frags\n");
+		if (slots >= work_to_do) {
+			netdev_err(vif->dev, "Need more slots\n");
 			netbk_fatal_tx_err(vif);
 			return -ENODATA;
 		}
 
-		if (unlikely(frags >= MAX_SKB_FRAGS)) {
-			netdev_err(vif->dev, "Too many frags\n");
+		if (unlikely(slots >= max_skb_slots)) {
+			netdev_err(vif->dev, "Too many slots\n");
 			netbk_fatal_tx_err(vif);
 			return -E2BIG;
 		}
 
-		memcpy(txp, RING_GET_REQUEST(&vif->tx, cons + frags),
+		memcpy(txp, RING_GET_REQUEST(&vif->tx, cons + slots),
 		       sizeof(*txp));
 		if (txp->size > first->size) {
-			netdev_err(vif->dev, "Frag is bigger than frame.\n");
+			netdev_err(vif->dev, "Packet is bigger than frame.\n");
 			netbk_fatal_tx_err(vif);
 			return -EIO;
 		}
 
 		first->size -= txp->size;
-		frags++;
+		slots++;
 
 		if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) {
 			netdev_err(vif->dev, "txp->offset: %x, size: %u\n",
@@ -944,7 +955,7 @@ static int netbk_count_requests(struct xenvif *vif,
 			return -EINVAL;
 		}
 	} while ((txp++)->flags & XEN_NETTXF_more_data);
-	return frags;
+	return slots;
 }
 
 static struct page *xen_netbk_alloc_page(struct xen_netbk *netbk,
@@ -968,48 +979,120 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk,
 	struct skb_shared_info *shinfo = skb_shinfo(skb);
 	skb_frag_t *frags = shinfo->frags;
 	u16 pending_idx = *((u16 *)skb->data);
-	int i, start;
+	u16 head_idx = 0;
+	int slot, start;
+	struct page *page;
+	pending_ring_idx_t index;
+	uint16_t dst_offset;
+	unsigned int nr_slots;
+	struct pending_tx_info *first = NULL;
+	int nr_txp;
+	unsigned int start_idx = 0;
+
+	/* At this point shinfo->nr_frags is in fact the number of
+	 * slots, which can be as large as max_skb_slots.
+	 */
+	nr_slots = shinfo->nr_frags;
 
 	/* Skip first skb fragment if it is on same page as header fragment. */
 	start = (frag_get_pending_idx(&shinfo->frags[0]) == pending_idx);
 
-	for (i = start; i < shinfo->nr_frags; i++, txp++) {
-		struct page *page;
-		pending_ring_idx_t index;
+	/* Coalesce tx requests, at this point the packet passed in
+	 * should be <= 64K. Any packets larger than 64K has been
+	 * dropped / caused fatal error early on.
+	 */
+	for (shinfo->nr_frags = slot = start; slot < nr_slots;
+	     shinfo->nr_frags++) {
 		struct pending_tx_info *pending_tx_info =
 			netbk->pending_tx_info;
 
-		index = pending_index(netbk->pending_cons++);
-		pending_idx = netbk->pending_ring[index];
-		page = xen_netbk_alloc_page(netbk, pending_idx);
+		page = alloc_page(GFP_KERNEL|__GFP_COLD);
 		if (!page)
 			goto err;
 
-		gop->source.u.ref = txp->gref;
-		gop->source.domid = vif->domid;
-		gop->source.offset = txp->offset;
-
-		gop->dest.u.gmfn = virt_to_mfn(page_address(page));
-		gop->dest.domid = DOMID_SELF;
-		gop->dest.offset = txp->offset;
-
-		gop->len = txp->size;
-		gop->flags = GNTCOPY_source_gref;
+		nr_txp = 0;
+		dst_offset = 0;
+		first = NULL;
+		while (dst_offset < PAGE_SIZE && slot < nr_slots) {
+			gop->flags = GNTCOPY_source_gref;
+
+			gop->source.u.ref = txp->gref;
+			gop->source.domid = vif->domid;
+			gop->source.offset = txp->offset;
+
+			gop->dest.domid = DOMID_SELF;
+
+			gop->dest.offset = dst_offset;
+			gop->dest.u.gmfn = virt_to_mfn(page_address(page));
+
+			if (dst_offset + txp->size > PAGE_SIZE) {
+				/* This page can only merge a portion
+				 * of tx request. Do not increment any
+				 * pointer / counter here. The txp
+				 * will be dealt with in future
+				 * rounds, eventually hitting the
+				 * `else` branch.
+				 */
+				gop->len = PAGE_SIZE - dst_offset;
+				txp->offset += gop->len;
+				txp->size -= gop->len;
+				dst_offset += gop->len; /* quit loop */
+			} else {
+				/* This tx request can be merged in the page */
+				gop->len = txp->size;
+				dst_offset += gop->len;
+
+				index = pending_index(netbk->pending_cons++);
+
+				pending_idx = netbk->pending_ring[index];
+
+				memcpy(&pending_tx_info[pending_idx].req, txp,
+				       sizeof(*txp));
+				xenvif_get(vif);
+
+				pending_tx_info[pending_idx].vif = vif;
+
+				/* Poison these fields, corresponding
+				 * fields for head tx req will be set
+				 * to correct values after the loop.
+				 */
+				pending_tx_info[pending_idx].nr_tx_req =
+					(u16)(~0);
+				netbk->mmap_pages[pending_idx] = (void *)(~0UL);
+				pending_tx_info[pending_idx].start_idx = ~0U;
+
+				if (unlikely(!first)) {
+					first = &pending_tx_info[pending_idx];
+					start_idx = index;
+					head_idx = pending_idx;
+				}
+
+				txp++;
+				nr_txp++;
+				slot++;
+			}
 
-		gop++;
+			gop++;
+		}
 
-		memcpy(&pending_tx_info[pending_idx].req, txp, sizeof(*txp));
-		xenvif_get(vif);
-		pending_tx_info[pending_idx].vif = vif;
-		frag_set_pending_idx(&frags[i], pending_idx);
+		first->req.offset = 0;
+		first->req.size = dst_offset;
+		first->nr_tx_req = nr_txp;
+		first->start_idx = start_idx;
+		set_page_ext(page, netbk, head_idx);
+		netbk->mmap_pages[head_idx] = page;
+		frag_set_pending_idx(&frags[shinfo->nr_frags], head_idx);
 	}
 
+	BUG_ON(shinfo->nr_frags > MAX_SKB_FRAGS);
+
 	return gop;
 err:
 	/* Unwind, freeing all pages and sending error responses. */
-	while (i-- > start) {
-		xen_netbk_idx_release(netbk, frag_get_pending_idx(&frags[i]),
-				      XEN_NETIF_RSP_ERROR);
+	while (shinfo->nr_frags-- > start) {
+		xen_netbk_idx_release(netbk,
+				frag_get_pending_idx(&frags[shinfo->nr_frags]),
+				XEN_NETIF_RSP_ERROR);
 	}
 	/* The head too, if necessary. */
 	if (start)
@@ -1025,6 +1108,7 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk,
 	struct gnttab_copy *gop = *gopp;
 	u16 pending_idx = *((u16 *)skb->data);
 	struct skb_shared_info *shinfo = skb_shinfo(skb);
+	struct pending_tx_info *tx_info;
 	int nr_frags = shinfo->nr_frags;
 	int i, err, start;
 
@@ -1037,12 +1121,17 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk,
 	start = (frag_get_pending_idx(&shinfo->frags[0]) == pending_idx);
 
 	for (i = start; i < nr_frags; i++) {
-		int j, newerr;
+		int j, newerr = 0, n;
 
 		pending_idx = frag_get_pending_idx(&shinfo->frags[i]);
+		tx_info = &netbk->pending_tx_info[pending_idx];
 
 		/* Check error status: if okay then remember grant handle. */
-		newerr = (++gop)->status;
+		for (n = 0; n < tx_info->nr_tx_req; n++) {
+			newerr = (++gop)->status;
+			if (newerr)
+				break;
+		}
 		if (likely(!newerr)) {
 			/* Had a previous error? Invalidate this fragment. */
 			if (unlikely(err))
@@ -1267,11 +1356,11 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
 	struct sk_buff *skb;
 	int ret;
 
-	while (((nr_pending_reqs(netbk) + MAX_SKB_FRAGS) < MAX_PENDING_REQS) &&
+	while (((nr_pending_reqs(netbk) + max_skb_slots) < MAX_PENDING_REQS) &&
 		!list_empty(&netbk->net_schedule_list)) {
 		struct xenvif *vif;
 		struct xen_netif_tx_request txreq;
-		struct xen_netif_tx_request txfrags[MAX_SKB_FRAGS];
+		struct xen_netif_tx_request txfrags[max_skb_slots];
 		struct page *page;
 		struct xen_netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX-1];
 		u16 pending_idx;
@@ -1359,7 +1448,7 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
 		pending_idx = netbk->pending_ring[index];
 
 		data_len = (txreq.size > PKT_PROT_LEN &&
-			    ret < MAX_SKB_FRAGS) ?
+			    ret < max_skb_slots) ?
 			PKT_PROT_LEN : txreq.size;
 
 		skb = alloc_skb(data_len + NET_SKB_PAD + NET_IP_ALIGN,
@@ -1409,6 +1498,8 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
 		memcpy(&netbk->pending_tx_info[pending_idx].req,
 		       &txreq, sizeof(txreq));
 		netbk->pending_tx_info[pending_idx].vif = vif;
+		netbk->pending_tx_info[pending_idx].start_idx = index;
+		netbk->pending_tx_info[pending_idx].nr_tx_req = 1;
 		*((u16 *)skb->data) = pending_idx;
 
 		__skb_put(skb, data_len);
@@ -1540,6 +1631,11 @@ static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx,
 	struct xenvif *vif;
 	struct pending_tx_info *pending_tx_info;
 	pending_ring_idx_t index;
+	unsigned int nr = 0;
+	unsigned int i = 0;
+	unsigned int start_idx = 0;
+
+	BUG_ON(netbk->mmap_pages[pending_idx] == (void *)(~0UL));
 
 	/* Already complete? */
 	if (netbk->mmap_pages[pending_idx] == NULL)
@@ -1548,13 +1644,27 @@ static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx,
 	pending_tx_info = &netbk->pending_tx_info[pending_idx];
 
 	vif = pending_tx_info->vif;
+	nr = pending_tx_info->nr_tx_req;
+	start_idx = pending_tx_info->start_idx;
 
-	make_tx_response(vif, &pending_tx_info->req, status);
+	BUG_ON(nr == (u16)(~0));
 
-	index = pending_index(netbk->pending_prod++);
-	netbk->pending_ring[index] = pending_idx;
+	BUG_ON(netbk->pending_ring[pending_index(start_idx)] != pending_idx);
 
-	xenvif_put(vif);
+	for (i = 0; i < nr; i++) {
+		struct xen_netif_tx_request *txp;
+		unsigned int idx = pending_index(start_idx + i);
+		unsigned int info_idx = netbk->pending_ring[idx];
+
+		pending_tx_info = &netbk->pending_tx_info[info_idx];
+		txp = &pending_tx_info->req;
+		make_tx_response(vif, &pending_tx_info->req, status);
+
+		index = pending_index(netbk->pending_prod++);
+		netbk->pending_ring[index] = netbk->pending_ring[info_idx];
+
+		xenvif_put(vif);
+	}
 
 	netbk->mmap_pages[pending_idx]->mapping = 0;
 	put_page(netbk->mmap_pages[pending_idx]);
@@ -1613,7 +1723,7 @@ static inline int rx_work_todo(struct xen_netbk *netbk)
 static inline int tx_work_todo(struct xen_netbk *netbk)
 {
 
-	if (((nr_pending_reqs(netbk) + MAX_SKB_FRAGS) < MAX_PENDING_REQS) &&
+	if (((nr_pending_reqs(netbk) + max_skb_slots) < MAX_PENDING_REQS) &&
 			!list_empty(&netbk->net_schedule_list))
 		return 1;
 
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 3/4] xen-netback: remove skb in xen_netbk_alloc_page
From: Wei Liu @ 2013-03-18 10:35 UTC (permalink / raw)
  To: netdev, xen-devel; +Cc: ian.campbell, konrad.wilk, annie.li, Wei Liu
In-Reply-To: <1363602955-24790-1-git-send-email-wei.liu2@citrix.com>

This variable is never used.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 drivers/net/xen-netback/netback.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index da726a3..6e8e51a 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -948,7 +948,6 @@ static int netbk_count_requests(struct xenvif *vif,
 }
 
 static struct page *xen_netbk_alloc_page(struct xen_netbk *netbk,
-					 struct sk_buff *skb,
 					 u16 pending_idx)
 {
 	struct page *page;
@@ -982,7 +981,7 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk,
 
 		index = pending_index(netbk->pending_cons++);
 		pending_idx = netbk->pending_ring[index];
-		page = xen_netbk_alloc_page(netbk, skb, pending_idx);
+		page = xen_netbk_alloc_page(netbk, pending_idx);
 		if (!page)
 			goto err;
 
@@ -1387,7 +1386,7 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
 		}
 
 		/* XXX could copy straight to head */
-		page = xen_netbk_alloc_page(netbk, skb, pending_idx);
+		page = xen_netbk_alloc_page(netbk, pending_idx);
 		if (!page) {
 			kfree_skb(skb);
 			netbk_tx_err(vif, &txreq, idx);
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 1/4] xen-netfront: remove unused variable `extra'
From: Wei Liu @ 2013-03-18 10:35 UTC (permalink / raw)
  To: netdev, xen-devel; +Cc: ian.campbell, konrad.wilk, annie.li, Wei Liu
In-Reply-To: <1363602955-24790-1-git-send-email-wei.liu2@citrix.com>

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 drivers/net/xen-netfront.c |    8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 7ffa43b..5527663 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -537,7 +537,6 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct netfront_info *np = netdev_priv(dev);
 	struct netfront_stats *stats = this_cpu_ptr(np->stats);
 	struct xen_netif_tx_request *tx;
-	struct xen_netif_extra_info *extra;
 	char *data = skb->data;
 	RING_IDX i;
 	grant_ref_t ref;
@@ -581,7 +580,6 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	tx->gref = np->grant_tx_ref[id] = ref;
 	tx->offset = offset;
 	tx->size = len;
-	extra = NULL;
 
 	tx->flags = 0;
 	if (skb->ip_summed == CHECKSUM_PARTIAL)
@@ -597,10 +595,7 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		gso = (struct xen_netif_extra_info *)
 			RING_GET_REQUEST(&np->tx, ++i);
 
-		if (extra)
-			extra->flags |= XEN_NETIF_EXTRA_FLAG_MORE;
-		else
-			tx->flags |= XEN_NETTXF_extra_info;
+		tx->flags |= XEN_NETTXF_extra_info;
 
 		gso->u.gso.size = skb_shinfo(skb)->gso_size;
 		gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
@@ -609,7 +604,6 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 		gso->type = XEN_NETIF_EXTRA_TYPE_GSO;
 		gso->flags = 0;
-		extra = gso;
 	}
 
 	np->tx.req_prod_pvt = i + 1;
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 2/4] xen-netfront: drop skb when skb->len > 65535
From: Wei Liu @ 2013-03-18 10:35 UTC (permalink / raw)
  To: netdev, xen-devel; +Cc: ian.campbell, konrad.wilk, annie.li, Wei Liu
In-Reply-To: <1363602955-24790-1-git-send-email-wei.liu2@citrix.com>

The `size' field of Xen network wire format is uint16_t, anything bigger than
65535 will cause overflow.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 drivers/net/xen-netfront.c |   12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 5527663..8c3d065 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -547,6 +547,18 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	unsigned int len = skb_headlen(skb);
 	unsigned long flags;
 
+	/*
+	 * wire format of xen_netif_tx_request only supports skb->len
+	 * < 64K, because size field in xen_netif_tx_request is
+	 * uint16_t.
+	 */
+	if (unlikely(skb->len > (uint16_t)(~0))) {
+		net_alert_ratelimited(
+			"xennet: skb->len = %d, too big for wire format\n",
+			skb->len);
+		goto drop;
+	}
+
 	slots = DIV_ROUND_UP(offset + len, PAGE_SIZE) +
 		xennet_count_skb_frag_slots(skb);
 	if (unlikely(slots > MAX_SKB_FRAGS + 1)) {
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 0/4] Bundle fixes for xen-netfront/back
From: Wei Liu @ 2013-03-18 10:35 UTC (permalink / raw)
  To: netdev, xen-devel; +Cc: ian.campbell, konrad.wilk, annie.li

This series contains 4 patches for Xen netfront and netback modules.

1 and 3 just remove some unused variables, nothing special.

2 is used to drop malformed packets in netfront before sending it to netback.

4 is used to deal with the situation when netfront's MAX_SKB_FRAGS is bigger
than netback's MAX_SKB_FRAGS.

^ permalink raw reply

* Re: [PATCH] bnx2x: fix occasional statistics off-by-4GB error
From: Eilon Greenstein @ 2013-03-18 10:06 UTC (permalink / raw)
  To: Maciej Żenczykowski
  Cc: Eric Dumazet, David Miller, Dmitry Kravkov, Linux NetDev,
	Mintz Yuval
In-Reply-To: <CANP3RGdZHMTPT6FTbYzSOHkrNq4seF1WcXjysQ6=HEp0A_CxWg@mail.gmail.com>

On Sun, 2013-03-17 at 23:18 -0700, Maciej Żenczykowski wrote:
> This has nothing to do with atomicity or races or anything.
> 
> Look at the ADD_64 macro (which implements a += b) and compare it to
> this one (which implents a = b + c).
> 
> It simply doesn't know how to correctly add in any situation in which
> "qstats_old->t..._lo != 0".
> By this point all the stats are already in software and both firmware
> and hardware is not relevant.
> 
> Normally qstats_old starts off at 0 and the bug isn't visible (since
> with a value of 0, there can't be overflow and carry propagation is
> not needed).
> 
> The reason qstats_old was introduced was to allow for a partial nic
> reset [or whatever the proper term is] which resets fw/hw provided
> stats to not reset sw exported stats.
> During the reset old stats are copied into qstats_old, and in the
> future stats are returned as "qstats_old + current stats from fw/hw"
> except this addition is buggy and only works if qstats_old happens to
> have lower 32-bits zero (ie. basically only before first partial nic
> reset).
> 
> Imagine:
> (a) driver initializes, nic gets brought up, qstats_old = 0, stats
> from device = 0
> (b) 2GB of xfer happens
> (c) qstats_old still = 0, stats from device = 2GB
> (d) addition happens qstats = qstats_old + stats_from_dev = 0 + 2GB =
> 2GB   --- we report 2GB xfer
> (e) something partially resets nic (say mtu change), qstats_old = 2GB,
> stats from device = 0
> (f) 2GB-1 of xfer happens
> (g) qstats_old = 2GB, stats from device = 2GB-1
> (h) addition happens qstats = qstats_old + stats_from_dev = 2GB +
> 2GB-1 = 4GB-1   --- we report 4GB-1 xfer
> (i) 1 byte of xfer happens
> (j) qstats_old = 2GB, stats from device = 2GB
> (k) addition happens qstats = qstats_old + stats_from_dev = 2GB + 2GB
> = 0   --- we report 0 xfer
> (l) 2GB of xfer happens
> (m) qstats_old = 2GB, stats from device = 4GB
> (n) addition happens qstats = qstats_old + stats_from_dev = 2GB + 4GB
> = 6GB   --- we report 6GB xfer
> 
> And yes the macro in question when asked to do 2GB+2GB will return 0.
> 
> (btw. at least on the driver I tested there's still some weirdness
> with mtu change not-resetting per-queue stats but resetting
> coalesced-from-all-queues stats)
> 
> Now, to be fair, I don't yet have confirmation that my patch fixes the
> problem our SREs saw in deployment, but I expect to have that soon.
> (and even if it doesn't fix the problem, this code is still buggy and
> should be fixed)
> 
> Maciej

Maciej - thanks for the detailed information. You are right - it has
nothing to do with the HW/FW and it is simply a bug that needs to be
fixed. I withdraw my objections and add my ACK.

Acked-by: Eilon Greenstein <eilong@broadcom.com>

^ permalink raw reply

* question about klen in move_addr_to_user()
From: Dan Carpenter @ 2013-03-18 10:10 UTC (permalink / raw)
  To: netdev

Smatch complains that about a potential buffer overflow in
move_add_to_user()

net/socket.c
   212  static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen,
   213                               void __user *uaddr, int __user *ulen)
   214  {
   215          int err;
   216          int len;
   217  
   218          err = get_user(len, ulen);
   219          if (err)
   220                  return err;
   221          if (len > klen)
   222                  len = klen;
   223          if (len < 0 || len > sizeof(struct sockaddr_storage))
   224                  return -EINVAL;
   225          if (len) {
   226                  if (audit_sockaddr(klen, kaddr))
                                           ^^^^
Smatch complains that although "len" is capped here, "klen" hasn't
necessarily been.  If "klen" is more than 128 bytes it leads to
memory corruption.

   227                          return -ENOMEM;
   228                  if (copy_to_user(uaddr, kaddr, len))
   229                          return -EFAULT;
   230          }

The call tree is this:

__sys_recvmsg() gets the msg->msg_namelen from the user.

Normally the network protocols set msg->msg_namelen in their
->recvmsg() function but some don't like caif_seqpkt_recvmsg() and
recv_msg() for tipc.

regards,
dan carpenter

^ permalink raw reply

* Re: Trying to implement secondary loopback
From: Thomas Martitz @ 2013-03-18  9:33 UTC (permalink / raw)
  To: Benjamin LaHaise
  Cc: richard -rw- weinberger, Eric W. Biederman,
	netdev@vger.kernel.org, davem@davemloft.net, edumazet@google.com,
	herbert@gondor.apana.org.au
In-Reply-To: <3D7E565A361FB844A410A5EFCDD7BA40031932@MXSRV3.fe.hhi.de>

Am 15.03.2013 20:48, schrieb Martitz, Thomas:
>>
>> ________________________________________
>> Von: Benjamin LaHaise [bcrl@kvack.org]
>> Gesendet: Freitag, 15. März 2013 16:37
>> An: Martitz, Thomas
>> Cc: richard -rw- weinberger; Eric W. Biederman; netdev@vger.kernel.org; davem@davemloft.net; edumazet@google.com; herbert@gondor.apana.org.au
>> Betreff: Re: Trying to implement secondary loopback
>>
>> On Fri, Mar 15, 2013 at 04:07:32PM +0100, Thomas Martitz wrote:
>>> Same result. I assumed the kernel treats lo in a special way for
>>> localhost-connections and that it would be impossible to achieve the
>>> same with a custom interface.
>>>
>>> I did the following:
>>>
>>> ifconfig lo down
>>> insmod ./mykmod.ko
>>> ifconfig eth2 up
>>> ifconfig eth2 127.0.0.1
>>>
>>> At this point ifconfig prints the same information for eth2 that it had
>>> printed for lo before (except for the LOOPBACK flag, but I can enable
>>> that one as well by adding IFF_LOOPBACK to the interface flags in the
>>> module). Yet my test application only works with lo, not eth2.
>>
>> Don't use loopback ip addresses; it makes no sense to do so.  I've worked
>> on a couple opf nic implementations on FPGAs for a while now (a gige
>> implementation that works, and now a 10G nic), and it's easy enough to
>> develop it as a regular ethernet driver.  You can write test programs that
>> use raw sockets to send/receive packets over the ethernet device, or use
>> pktgen to send packets.  You don't even need to configure an ip address for
>> testing with raw packets.  Testing with IP is a lot harder during early
>> bring-up of your hardware as it requires everything to work (that is, you
>> need ARP to work successfully before IP can work).  Just stick to simple
>> packet injection initially, and don't confuse yourself by thinking about
>> the loopback device.
>
> Thank you for your very helpful mail. I haven't considered raw sockets, but it makes total sense now you mention it. This should give a lot less hassle.
>
> However, please let us try to clear up my (mis-)understanding. Even when I use non-looback addresses (e.g. 192.168.1.x) it does not work. For the ARP requirement I tried to workaround by using specifying the IFF_NOARP flag, and using the arp command line tool to populate the arp cache with the the MAC. With this, and all other interfaces down'ed, I cannot get transfers to work. The the sendto() (sending UDP datadagrams) call hangs while the ndk_start_xmit() method isn't even called. As works fine with the loopback interface I started to believe that I need to implement a real loopback interface. It is this supposed to work this way isn't it?
>
> Best regards.



I have found the root problem, that Linux does not allow local (same 
machine) connections via any non-lo interface. See [1] and [2]. Whether 
two NICs connected via crossover cable, or one NIC implementing a 
loopback, the kernel routes transmission via "lo" (and if it's down'ed 
there is no traffic at all).

This made me led me to the conclusion that I need a real (secondary) 
loopback, because an ethX interface simply doesn't work.

According to [2], I have now baked a script which enables local 
connections via non-lo interfaces, and I think I'm happy with it.

Do you guys now why linux makes it so hard (before 2.6.33 even 
impossible) to set up local connections like this (for testing 
purposes)? I understand that routing to lo is a strong optimization for 
real traffic but it should be easy to opt out if routing through NICs is 
really necessary as in my case.

Thank you for your patience and help.
Best regards.

[1]: http://www.zyztematik.com/?p=10
[2]: 
http://umweltsuende.wordpress.com/2011/11/13/monolog-fur-linux-server-send-to-self-patch-alternative/

-----
visit us at

OFC 2013 / March 19-21 / Anaheim Convention Center, CA, USA / booth 11807

NABSHOW 2013 / April 8-11 / Las Vegas Convention Center, Nevada, USA / booth C7843

www.hhi.fraunhofer.de/events

^ permalink raw reply

* Re: [PATCH] netfilter: nf_conntrack: Batch cleanup
From: Gao feng @ 2013-03-18  9:33 UTC (permalink / raw)
  To: Vladimir Davydov
  Cc: Pablo Neira Ayuso, netfilter-devel, netfilter, coreteam, netdev,
	linux-kernel, devel, Patrick McHardy, David S. Miller,
	Eric W. Biederman
In-Reply-To: <1363254014-10725-1-git-send-email-vdavydov@parallels.com>

On 2013/03/14 17:40, Vladimir Davydov wrote:
> The patch introduces nf_conntrack_cleanup_net_list(), which cleanups
> nf_conntrack for a list of netns and calls synchronize_net() only once
> for them all. This should reduce netns destruction time.
> --
> I've measured cleanup time for 1k dummy net ns. Here are the results:
> 
>  <without the patch>
>  # modprobe nf_conntrack
>  # time modprobe -r nf_conntrack
> 
>  real	0m10.337s
>  user	0m0.000s
>  sys	0m0.376s
> 
>  <with the patch>
>  # modprobe nf_conntrack
>  # time modprobe -r nf_conntrack
> 
>  real    0m5.661s
>  user    0m0.000s
>  sys     0m0.216s
> 
> Signed-off-by: Vladimir Davydov <vdavydov@parallels.com>
> Cc: Patrick McHardy <kaber@trash.net>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: "Eric W. Biederman" <ebiederm@xmission.com>
> ---
>  include/net/netfilter/nf_conntrack_core.h |    1 +
>  net/netfilter/nf_conntrack_core.c         |   46 ++++++++++++++++++++---------
>  net/netfilter/nf_conntrack_standalone.c   |   16 ++++++----
>  3 files changed, 43 insertions(+), 20 deletions(-)
> 
> diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
> index 930275f..fb2b623 100644
> --- a/include/net/netfilter/nf_conntrack_core.h
> +++ b/include/net/netfilter/nf_conntrack_core.h
> @@ -27,6 +27,7 @@ extern unsigned int nf_conntrack_in(struct net *net,
>  
>  extern int nf_conntrack_init_net(struct net *net);
>  extern void nf_conntrack_cleanup_net(struct net *net);
> +extern void nf_conntrack_cleanup_net_list(struct list_head *net_exit_list);
>  
>  extern int nf_conntrack_proto_pernet_init(struct net *net);
>  extern void nf_conntrack_proto_pernet_fini(struct net *net);
> diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
> index c8e001a..09c02ef 100644
> --- a/net/netfilter/nf_conntrack_core.c
> +++ b/net/netfilter/nf_conntrack_core.c
> @@ -1364,30 +1364,48 @@ void nf_conntrack_cleanup_end(void)
>   */
>  void nf_conntrack_cleanup_net(struct net *net)
>  {
> +	LIST_HEAD(single);
> +
> +	list_add(&net->exit_list, &single);
> +	nf_conntrack_cleanup_net_list(&single);
> +}
> +

After adding net->exit_list to this single list,in setup_net we will
re-add this net->exit_list to net_exit_list. So there has no invalid
pointer problem.

This patch looks good to me.
Acked-by: Gao feng <gaofeng@cn.fujitsu.com>

Thanks!

^ permalink raw reply

* Re: [PATCH nf-next] netfilter: nfnetlink_queue: zero copy support
From: Florian Westphal @ 2013-03-18  9:24 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Pablo Neira Ayuso, netdev, Netfilter Developer Mailing List
In-Reply-To: <1363576555.29475.122.camel@edumazet-glaptop>

Eric Dumazet <eric.dumazet@gmail.com> wrote:
> From: Eric Dumazet <edumazet@google.com>
> 
> nfqnl_build_packet_message() actually copy the packet
> inside the netlink message, while it can instead use
> zero copy.
> 
> Make sure the skb 'copy' is the last component of the
> cooked netlink message, as we cant add anything after it.
> 
> Patch cooked in Copenhagen at Netfilter Workshop ;)

This is awesome.
Was there a consensus wrt. mmap'd netlink vs. your patch?

[ I ask because both get rid of one skb data copy ]

> Still to be addressed in separate patches :
>
> -GRO/GSO packets are segmented in nf_queue()
> and checksummed in nfqnl_build_packet_message().
> Proper support for GSO/GRO packets (no segmentation,
> and no checksumming) needs application cooperation, if we
> want no regressions.

Since ipqueue is gone we might be able to push the segmentation
down to nfnetlink_queue.  Then new userspace applications
could indicate a 'I won't verify checksums and will handle huge
packets'.

Are you working on something like this?

^ permalink raw reply

* [PATCH net-next] net: neterion: replace ip_fast_csum with csum_replace2
From: roy.qing.li @ 2013-03-18  8:34 UTC (permalink / raw)
  To: netdev

From: Li RongQing <roy.qing.li@gmail.com>

replace ip_fast_csum with csum_replace2 to save cpu cycles

Signed-off-by: Li RongQing <roy.qing.li@gmail.com>
---
 drivers/net/ethernet/neterion/s2io.c |    6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c
index bfd8873..3371ff4 100644
--- a/drivers/net/ethernet/neterion/s2io.c
+++ b/drivers/net/ethernet/neterion/s2io.c
@@ -80,6 +80,7 @@
 #include <linux/slab.h>
 #include <linux/prefetch.h>
 #include <net/tcp.h>
+#include <net/checksum.h>
 
 #include <asm/div64.h>
 #include <asm/irq.h>
@@ -8337,16 +8338,13 @@ static void update_L3L4_header(struct s2io_nic *sp, struct lro *lro)
 {
 	struct iphdr *ip = lro->iph;
 	struct tcphdr *tcp = lro->tcph;
-	__sum16 nchk;
 	struct swStat *swstats = &sp->mac_control.stats_info->sw_stat;
 
 	DBG_PRINT(INFO_DBG, "%s: Been here...\n", __func__);
 
 	/* Update L3 header */
+	csum_replace2(&ip->check, ip->tot_len, htons(lro->total_len));
 	ip->tot_len = htons(lro->total_len);
-	ip->check = 0;
-	nchk = ip_fast_csum((u8 *)lro->iph, ip->ihl);
-	ip->check = nchk;
 
 	/* Update L4 header */
 	tcp->ack_seq = lro->tcp_ack;
-- 
1.7.10.4

^ permalink raw reply related

* RE: [PATCH net-next 0/2] be2net: patch set
From: Kotur, Somnath @ 2013-03-18  8:29 UTC (permalink / raw)
  To: Kotur, Somnath, netdev@vger.kernel.org; +Cc: davem@davemloft.net
In-Reply-To: <bfd8205d-1c91-4947-88f7-c27554b4dd06@CMEXHTCAS2.ad.emulex.com>

Dave,
 These patches have already been applied. Pls ignore ,they were sent by mistake! 

Thanks
Som

> -----Original Message-----
> From: netdev-owner@vger.kernel.org [mailto:netdev-
> owner@vger.kernel.org] On Behalf Of Somnath Kotur
> Sent: Monday, March 18, 2013 12:34 PM
> To: netdev@vger.kernel.org
> Cc: davem@davemloft.net; Kotur, Somnath
> Subject: [PATCH net-next 0/2] be2net: patch set
> 
> Pls apply.
> 
> Somnath Kotur (2):
>   be2net: enable interrupts in be_probe() (RoCE and other ULPs need
>     them)
>   be2net: Use new F/W mailbox cmd to manipulate interrupts.
> 
>  drivers/net/ethernet/emulex/benet/be_cmds.c |   25
> +++++++++++++++++
>  drivers/net/ethernet/emulex/benet/be_cmds.h |    8 +++++
>  drivers/net/ethernet/emulex/benet/be_main.c |   38 ++++++++++++++++-
> ---------
>  3 files changed, 56 insertions(+), 15 deletions(-)
> 
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in the body
> of a message to majordomo@vger.kernel.org More majordomo info at
> http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH v2 4/4] ARM: mxs: remove unneeded enet_out clk initialization
From: Shawn Guo @ 2013-03-18  8:26 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: netdev, David S. Miller, Shawn Guo
In-Reply-To: <1363595185-12302-1-git-send-email-shawn.guo@linaro.org>

With fec driver taking care of enet_out clk, most of board setup
do not need to enable enet_out clk.  So remove them.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
 arch/arm/mach-mxs/mach-mxs.c |   12 ------------
 1 file changed, 12 deletions(-)

diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c
index 0521867..026edfc 100644
--- a/arch/arm/mach-mxs/mach-mxs.c
+++ b/arch/arm/mach-mxs/mach-mxs.c
@@ -271,7 +271,6 @@ static inline void enable_clk_enet_out(void)
 
 static void __init imx28_evk_init(void)
 {
-	enable_clk_enet_out();
 	update_fec_mac_prop(OUI_FSL);
 
 	mxsfb_pdata.mode_list = mx28evk_video_modes;
@@ -299,11 +298,6 @@ static void __init m28evk_init(void)
 	mxsfb_pdata.ld_intf_width = STMLCDIF_18BIT;
 }
 
-static void __init sc_sps1_init(void)
-{
-	enable_clk_enet_out();
-}
-
 static int apx4devkit_phy_fixup(struct phy_device *phy)
 {
 	phy->dev_flags |= MICREL_PHY_50MHZ_CLK;
@@ -400,13 +394,11 @@ static void __init tx28_post_init(void)
 
 static void __init cfa10049_init(void)
 {
-	enable_clk_enet_out();
 	update_fec_mac_prop(OUI_CRYSTALFONTZ);
 }
 
 static void __init cfa10037_init(void)
 {
-	enable_clk_enet_out();
 	update_fec_mac_prop(OUI_CRYSTALFONTZ);
 
 	mxsfb_pdata.mode_list = cfa10049_video_modes;
@@ -417,8 +409,6 @@ static void __init cfa10037_init(void)
 
 static void __init apf28_init(void)
 {
-	enable_clk_enet_out();
-
 	mxsfb_pdata.mode_list = apf28dev_video_modes;
 	mxsfb_pdata.mode_count = ARRAY_SIZE(apf28dev_video_modes);
 	mxsfb_pdata.default_bpp = 16;
@@ -441,8 +431,6 @@ static void __init mxs_machine_init(void)
 		cfa10049_init();
 	else if (of_machine_is_compatible("armadeus,imx28-apf28"))
 		apf28_init();
-	else if (of_machine_is_compatible("schulercontrol,imx28-sps1"))
-		sc_sps1_init();
 
 	of_platform_populate(NULL, of_default_bus_match_table,
 			     mxs_auxdata_lookup, NULL);
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v2 3/4] ARM: dts: mxs: add enet_out clock to devicetree
From: Shawn Guo @ 2013-03-18  8:26 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: netdev, David S. Miller, Wolfram Sang, Shawn Guo
In-Reply-To: <1363595185-12302-1-git-send-email-shawn.guo@linaro.org>

From: Wolfram Sang <w.sang@pengutronix.de>

Put the clock to the devicetree, so the driver can take care of it
later. Then, we don't have to do the enabling as a workaround in board
init.

Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
[shawn.guo: add enet_out into imx28.dtsi and overwrite it for m28evk]
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
 arch/arm/boot/dts/imx28-m28evk.dts |    2 ++
 arch/arm/boot/dts/imx28.dtsi       |    4 ++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/imx28-m28evk.dts b/arch/arm/boot/dts/imx28-m28evk.dts
index 6ce3d17..3d2e1a4 100644
--- a/arch/arm/boot/dts/imx28-m28evk.dts
+++ b/arch/arm/boot/dts/imx28-m28evk.dts
@@ -221,6 +221,8 @@
 			phy-mode = "rmii";
 			pinctrl-names = "default";
 			pinctrl-0 = <&mac0_pins_a>;
+			clocks = <&clks 57>, <&clks 57>;
+			clock-names = "ipg", "ahb";
 			status = "okay";
 		};
 
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index 7ba4966..dc1203d 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -940,8 +940,8 @@
 			compatible = "fsl,imx28-fec";
 			reg = <0x800f0000 0x4000>;
 			interrupts = <101>;
-			clocks = <&clks 57>, <&clks 57>;
-			clock-names = "ipg", "ahb";
+			clocks = <&clks 57>, <&clks 57>, <&clks 64>;
+			clock-names = "ipg", "ahb", "enet_out";
 			status = "disabled";
 		};
 
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v2 2/4] net: freescale: fec: add support for optional enet_out clk
From: Shawn Guo @ 2013-03-18  8:26 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: netdev, David S. Miller, Wolfram Sang, Shawn Guo
In-Reply-To: <1363595185-12302-1-git-send-email-shawn.guo@linaro.org>

From: Wolfram Sang <w.sang@pengutronix.de>

Some MX28 boards need the internal enet_out clock to be enabled. So, do
this in the driver iff the clock was referenced via devicetree.

Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
 drivers/net/ethernet/freescale/fec.c |   10 ++++++++++
 drivers/net/ethernet/freescale/fec.h |    1 +
 2 files changed, 11 insertions(+)

diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index d2a9851..2297283 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -1800,6 +1800,11 @@ fec_probe(struct platform_device *pdev)
 		goto failed_clk;
 	}
 
+	/* enet_out is optional, depends on board */
+	fep->clk_enet_out = devm_clk_get(&pdev->dev, "enet_out");
+	if (IS_ERR(fep->clk_enet_out))
+		fep->clk_enet_out = NULL;
+
 	fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp");
 	fep->bufdesc_ex =
 		pdev->id_entry->driver_data & FEC_QUIRK_HAS_BUFDESC_EX;
@@ -1810,6 +1815,7 @@ fec_probe(struct platform_device *pdev)
 
 	clk_prepare_enable(fep->clk_ahb);
 	clk_prepare_enable(fep->clk_ipg);
+	clk_prepare_enable(fep->clk_enet_out);
 	clk_prepare_enable(fep->clk_ptp);
 
 	reg_phy = devm_regulator_get(&pdev->dev, "phy");
@@ -1875,6 +1881,7 @@ failed_irq:
 failed_regulator:
 	clk_disable_unprepare(fep->clk_ahb);
 	clk_disable_unprepare(fep->clk_ipg);
+	clk_disable_unprepare(fep->clk_enet_out);
 	clk_disable_unprepare(fep->clk_ptp);
 failed_pin:
 failed_clk:
@@ -1901,6 +1908,7 @@ fec_drv_remove(struct platform_device *pdev)
 	clk_disable_unprepare(fep->clk_ptp);
 	if (fep->ptp_clock)
 		ptp_clock_unregister(fep->ptp_clock);
+	clk_disable_unprepare(fep->clk_enet_out);
 	clk_disable_unprepare(fep->clk_ahb);
 	clk_disable_unprepare(fep->clk_ipg);
 	for (i = 0; i < FEC_IRQ_NUM; i++) {
@@ -1931,6 +1939,7 @@ fec_suspend(struct device *dev)
 		fec_stop(ndev);
 		netif_device_detach(ndev);
 	}
+	clk_disable_unprepare(fep->clk_enet_out);
 	clk_disable_unprepare(fep->clk_ahb);
 	clk_disable_unprepare(fep->clk_ipg);
 
@@ -1943,6 +1952,7 @@ fec_resume(struct device *dev)
 	struct net_device *ndev = dev_get_drvdata(dev);
 	struct fec_enet_private *fep = netdev_priv(ndev);
 
+	clk_prepare_enable(fep->clk_enet_out);
 	clk_prepare_enable(fep->clk_ahb);
 	clk_prepare_enable(fep->clk_ipg);
 	if (netif_running(ndev)) {
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 01579b8..becb7bd 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -208,6 +208,7 @@ struct fec_enet_private {
 
 	struct clk *clk_ipg;
 	struct clk *clk_ahb;
+	struct clk *clk_enet_out;
 	struct clk *clk_ptp;
 
 	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v2 1/4] net: fec: handle optional clk_ptp more gracefully
From: Shawn Guo @ 2013-03-18  8:26 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: netdev, David S. Miller, Shawn Guo
In-Reply-To: <1363595185-12302-1-git-send-email-shawn.guo@linaro.org>

When the optional clk_ptp is absent, we can just set it to NULL, and
clk API will just handle it gracefully.  It saves us from checking
clk_ptp whenever calling into clk API.

Also since clk_ptp is optional, the "ret" variable shouldn't be set
in case that the clock is absent.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
 drivers/net/ethernet/freescale/fec.c |    8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index fccc3bf..d2a9851 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -1804,14 +1804,13 @@ fec_probe(struct platform_device *pdev)
 	fep->bufdesc_ex =
 		pdev->id_entry->driver_data & FEC_QUIRK_HAS_BUFDESC_EX;
 	if (IS_ERR(fep->clk_ptp)) {
-		ret = PTR_ERR(fep->clk_ptp);
+		fep->clk_ptp = NULL;
 		fep->bufdesc_ex = 0;
 	}
 
 	clk_prepare_enable(fep->clk_ahb);
 	clk_prepare_enable(fep->clk_ipg);
-	if (!IS_ERR(fep->clk_ptp))
-		clk_prepare_enable(fep->clk_ptp);
+	clk_prepare_enable(fep->clk_ptp);
 
 	reg_phy = devm_regulator_get(&pdev->dev, "phy");
 	if (!IS_ERR(reg_phy)) {
@@ -1876,8 +1875,7 @@ failed_irq:
 failed_regulator:
 	clk_disable_unprepare(fep->clk_ahb);
 	clk_disable_unprepare(fep->clk_ipg);
-	if (!IS_ERR(fep->clk_ptp))
-		clk_disable_unprepare(fep->clk_ptp);
+	clk_disable_unprepare(fep->clk_ptp);
 failed_pin:
 failed_clk:
 	iounmap(fep->hwp);
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v2 0/4] ARM: mxs: sanitize enet_out clock handling
From: Shawn Guo @ 2013-03-18  8:26 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: netdev, David S. Miller, Shawn Guo

Handling enet_out on MX28 is cumbersome at the moment. Most boards need
it enabled and for that, they have to add code to mach-mxs.c (see sps1
as an example). Since this is board specific, we better encode it in
the devicetree, that is the reason it was made for.

The seres propose to have enet_out clock defined in device tree and
have fec driver to enable the clock if found.  This will make adding
new board easier, since we don't have to touch mach-mxs.c for this
case. It scales much better.

Changes since v1:
 * Rebased on v3.9-rc1
 * Add a patch to have clk_ptp handled in the same way that enet_out
   is done
 * Add enet_out into imx28.dtsi and overwrite clocks and clock-names
   for m28evk board where the clock is absent
 * Remove unneeded enet_out clk initialization from board code

David,

If the series looks good to you, I hope I can have your ACK on the
first 2 patches to have the series go via arm-soc tree for sake of
git bisect.  Alternatively, please apply the first 2 on your tree
for 3.10 and we will queue the platform patches for 3.11.

Shawn

Shawn Guo (2):
  net: fec: handle optional clk_ptp more gracefully
  ARM: mxs: remove unneeded enet_out clk initialization

Wolfram Sang (2):
  net: freescale: fec: add support for optional enet_out clk
  ARM: dts: mxs: add enet_out clock to devicetree

 arch/arm/boot/dts/imx28-m28evk.dts   |    2 ++
 arch/arm/boot/dts/imx28.dtsi         |    4 ++--
 arch/arm/mach-mxs/mach-mxs.c         |   12 ------------
 drivers/net/ethernet/freescale/fec.c |   18 +++++++++++++-----
 drivers/net/ethernet/freescale/fec.h |    1 +
 5 files changed, 18 insertions(+), 19 deletions(-)

-- 
1.7.9.5

^ permalink raw reply

* Re: [PATCHv3 vringh] caif_virtio: Introduce caif over virtio
From: Rusty Russell @ 2013-03-18  3:38 UTC (permalink / raw)
  To: David Miller, erwan.yvin
  Cc: rusty, sjur.brandeland, linus.walleij, ohad, virtualization,
	netdev
In-Reply-To: <20130317.121436.461735238002154159.davem@davemloft.net>

David Miller <davem@davemloft.net> writes:

> From: Erwan Yvin <erwan.yvin@stericsson.com>
> Date: Fri, 15 Mar 2013 10:42:17 +0100
>
>> caif-virtio is going to replace caif-shm.
>> This patch should be merged in rusty's tree. (vringh)
>> because there is a dependency with vringh wrapper.
>
> Feel free to add my:
>
> Acked-by: David S. Miller <davem@davemloft.net>

Thanks, applied to my vringh branch.  I'll repost it all, to give you
and Sjur a chance to make sure I've integrated correctly.

Thanks,
Rusty.

^ permalink raw reply

* Re: [PATCHv3 vringh] caif_virtio: Introduce caif over virtio
From: Rusty Russell @ 2013-03-18  3:45 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Erwan Yvin
  Cc: David S. Miller, Rusty Russel, Sjur Braendeland, Linus Walleij,
	virtualization, netdev
In-Reply-To: <CAK=WgbbV6mvYC+KeSKJR+jmrAy3Et5opzzno1_kaicMPdDxNXg@mail.gmail.com>

Ohad Ben-Cohen <ohad@wizery.com> writes:
> Hi Erwan,
>
> On Fri, Mar 15, 2013 at 11:42 AM, Erwan Yvin <erwan.yvin@stericsson.com> wrote:
>> +++ b/drivers/net/caif/caif_virtio.c
...
>> +#include <linux/remoteproc.h>
>
> The driver looks nicely decoupled from remoteproc - do you still need
> remoteproc.h ?

Seems not.

Thanks,
Rusty.

caif_virtio: remove unneeded remoteproc.h

Reported-by: Ohad Ben-Cohen <ohad@wizery.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

diff --git a/drivers/net/caif/caif_virtio.c b/drivers/net/caif/caif_virtio.c
index 6a745dd..b1e1205 100644
--- a/drivers/net/caif/caif_virtio.c
+++ b/drivers/net/caif/caif_virtio.c
@@ -15,7 +15,6 @@
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
-#include <linux/remoteproc.h>
 #include <linux/virtio_ids.h>
 #include <linux/virtio_caif.h>
 #include <linux/virtio_ring.h>

^ permalink raw reply related

* Re: [PATCH] bnx2x: fix occasional statistics off-by-4GB error
From: Eilon Greenstein @ 2013-03-18  7:27 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, dmitry, zenczykowski, maze, netdev, yuvalmin
In-Reply-To: <1363562251.29475.109.camel@edumazet-glaptop>

On Sun, 2013-03-17 at 16:17 -0700, Eric Dumazet wrote:
> On Sun, 2013-03-17 at 22:53 +0200, Eilon Greenstein wrote:
> 
> > This is not such a trivial issue - the HW/FW is guaranteeing the atomic
> > read and this is why we can always use 32b variables.
> > 
> 
> I am glad you qualify the following code as 'trivial'
> 

Eric - I did not mean that the solution is trivial, I meant that the
problem is trivial. Like the trivial statement that the code should not
contain any bugs :)


> All you really needed is to have normal host structures containing u64
> fields, and you only needed one single helper to convert from hw u32:u32
> to host u64.
> 
> Because gcc handles u64 operations very well, even on 32bit hosts, and
> it knows about the carry flag.

I was not clear when I said size-extension: most of the HW counters are
46bits and we are trying to keep 64bits counters in the SW, so simply
copying the data from the HW is not enough.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox