Netdev List
 help / color / mirror / Atom feed
* Re: [RFC 2/2] xen-netback: disable multicast and use a random hw MAC address
From: Bill Fink @ 2014-02-12 17:17 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Luis R. Rodriguez, netdev@vger.kernel.org, xen-devel,
	Paul Durrant, Wei Liu, kvm, linux-kernel@vger.kernel.org
In-Reply-To: <1392203708.13563.50.camel@kazak.uk.xensource.com>

On Wed, 12 Feb 2014, Ian Campbell wrote:

> On Tue, 2014-02-11 at 13:53 -0800, Luis R. Rodriguez wrote:
> > Cc'ing kvm folks as they may have a shared interest on the shared
> > physical case with the bridge (non NAT).
> > 
> > On Tue, Feb 11, 2014 at 12:43 AM, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> > > On Mon, 2014-02-10 at 14:29 -0800, Luis R. Rodriguez wrote:
> > >> From: "Luis R. Rodriguez" <mcgrof@suse.com>
> > >>
> > >> Although the xen-netback interfaces do not participate in the
> > >> link as a typical Ethernet device interfaces for them are
> > >> still required under the current archtitecture. IPv6 addresses
> > >> do not need to be created or assigned on the xen-netback interfaces
> > >> however, even if the frontend devices do need them, so clear the
> > >> multicast flag to ensure the net core does not initiate IPv6
> > >> Stateless Address Autoconfiguration.
> > >
> > > How does disabling SAA flow from the absence of multicast?
> > 
> > See patch 1 in this series [0], but I explain the issue I see with
> > this on the cover letter [1].
> 
> Oop, I felt like I'd missed some context. Thanks for pointing out that
> it was right under my nose.
> 
> > In summary the RFCs on IPv6 make it
> > clear you need multicast for Stateless address autoconfiguration
> > (SLAAC is the preferred acronym) and DAD,
> 
> That seems reasonable, but I think is the opposite to what I was trying
> to get at.
> 
> Why is it not possible to disable SLAAC and/or DAD even if multicast is
> present?
> 
> IOW -- enabling/disabling multicast seems to me to be an odd proxy for
> disabling SLAAC or DAD and AIUI your patch fixes the opposite case,
> which is to avoid SLAAC and DAD on interfaces which don't do multicast
> (which makes sense since those protocols involve multicast).

Forgive me if this doesn't make sense in this context since
I'm not a kernel developer, but I was just wondering if any of
the sysctls:

	/proc/sys/net/ipv6/conf/<ifc>/disable_ipv6
	/proc/sys/net/ipv6/conf/<ifc>/accept_dad
	/proc/sys/net/ipv6/conf/<ifc>/accept_ra
	/proc/sys/net/ipv6/conf/<ifc>/autoconf

would be apropos for the requirement being discussed.

					-Bill

^ permalink raw reply

* Re: igb and bnx2: "NETDEV WATCHDOG: transmit queue timed out" when skb has huge linear buffer
From: Zoltan Kiss @ 2014-02-12 17:13 UTC (permalink / raw)
  To: Zoltan Kiss, Jeff Kirsher, Jesse Brandeburg, Bruce Allan,
	Carolyn Wyborny, Don Skidmore, Greg Rose, Peter P Waskiewicz Jr,
	Alex Duyck, John Ronciak, Tushar Dave, Akeem G Abodunrin,
	David S. Miller, e1000-devel, netdev@vger.kernel.org,
	linux-kernel, Michael Chan, xen-devel@lists.xenproject.org
In-Reply-To: <52EAA31B.1090606@schaman.hu>

Hi,

I still haven't managed to crack this problem. I've made sure the below 
mentioned skb's look the same as the other ones: linear buffer with 
header, and the rest is aggregated into frags. Utilizing the skb 
destructor I've also checked that these packets are all freed before the 
TX hang happens. So the only difference from current upstream is that 
the pages are grant mapped into Dom0 instead of grant copy to a local page.
I've also found some of my older notes about this issue, where I managed 
to reproduce this on igb, and in that particular case the TX hang could 
be solved with ifconfig down/up. Does the "Detected Tx Unit Hang" 
messages give any hint to igb developers?

Nov 26 04:18:34 localhost kernel: [ 7814.197868] ------------[ cut here 
]------------
Nov 26 04:18:34 localhost kernel: [ 7814.197889] WARNING: at 
net/sched/sch_generic.c:255 dev_watchdog+0x165/0x220()
Nov 26 04:18:34 localhost kernel: [ 7814.197892] NETDEV WATCHDOG: eth0 
(igb): transmit queue 7 timed out
Nov 26 04:18:34 localhost kernel: [ 7814.197894] Modules linked in: tun 
nfsv3 nfs_acl nfs fscache dm_multipath scsi_dh lockd sunrpc openvswitch 
ipt_REJECT nf_conntrack_ipv4 nf_defrag_ip
v4 xt_tcpudp xt_conntrack nf_conntrack iptable_filter ip_tables x_tables 
nls_utf8 isofs dm_mirror video backlight sbs sbshc hed acpi_ipmi 
ipmi_msghandler nvram sg psmouse serio_raw igb
i2c_algo_bit ptp pps_core hpilo tpm_tis tpm tpm_bios lpc_ich mfd_core 
ehci_pci crc32_pclmul aesni_intel ablk_helper cryptd lrw aes_i586 xts 
gf128mul dm_region_hash dm_log dm_mod shpchp
hpsa sd_mod scsi_mod uhci_hcd ohci_hcd ehci_hcd fbcon font tileblit 
bitblit softcursor [last unloaded: microcode]
Nov 26 04:18:34 localhost kernel: [ 7814.197957] CPU: 5 PID: 0 Comm: 
swapper/5 Not tainted 3.10.11-0.xs1.8.50.127.377543 #1
Nov 26 04:18:34 localhost kernel: [ 7814.197959] Hardware name: HP 
ProLiant BL420c Gen8, BIOS I30 12/14/2012
Nov 26 04:18:34 localhost kernel: [ 7814.197962]  e5cd9e10 c13e4c55 
e5cd9ddc c1278546 e5cd9e00 c1047fd3 c1643220 e5cd9e2c
Nov 26 04:18:34 localhost kernel: [ 7814.197969]  000000ff c13e4c55 
e1fa8700 00000007 000004e2 e5cd9e18 c1048093 00000009
Nov 26 04:18:34 localhost kernel: [ 7814.197975]  e5cd9e10 c1643220 
e5cd9e2c e5cd9e50 c13e4c55 c163fe6b 000000ff c1643220
Nov 26 04:18:34 localhost kernel: [ 7814.197982] Call Trace:
Nov 26 04:18:34 localhost kernel: [ 7814.197988]  [<c13e4c55>] ? 
dev_watchdog+0x165/0x220
Nov 26 04:18:34 localhost kernel: [ 7814.197994]  [<c1278546>] 
dump_stack+0x16/0x20
Nov 26 04:18:34 localhost kernel: [ 7814.198000]  [<c1047fd3>] 
warn_slowpath_common+0x63/0x80
Nov 26 04:18:34 localhost kernel: [ 7814.198003]  [<c13e4c55>] ? 
dev_watchdog+0x165/0x220
Nov 26 04:18:34 localhost kernel: [ 7814.198007]  [<c1048093>] 
warn_slowpath_fmt+0x33/0x40
Nov 26 04:18:34 localhost kernel: [ 7814.198011]  [<c13e4c55>] 
dev_watchdog+0x165/0x220
Nov 26 04:18:34 localhost kernel: [ 7814.198017]  [<c13e4af0>] ? 
dev_activate+0x110/0x110
Nov 26 04:18:34 localhost kernel: [ 7814.198020]  [<c1055c18>] 
call_timer_fn+0x58/0xe0
Nov 26 04:18:34 localhost kernel: [ 7814.198024]  [<c1056ce8>] 
run_timer_softirq+0x1a8/0x1f0
Nov 26 04:18:34 localhost kernel: [ 7814.198028]  [<c12fb61d>] ? 
info_for_irq+0xd/0x20
Nov 26 04:18:34 localhost kernel: [ 7814.198031]  [<c12fbb6c>] ? 
evtchn_from_irq+0x3c/0x50
Nov 26 04:18:34 localhost kernel: [ 7814.198034]  [<c13e4af0>] ? 
dev_activate+0x110/0x110
Nov 26 04:18:34 localhost kernel: [ 7814.198038]  [<c104fcb9>] 
__do_softirq+0xd9/0x1e0
Nov 26 04:18:34 localhost kernel: [ 7814.198041]  [<c12fc045>] ? 
__xen_evtchn_do_upcall+0x245/0x280
Nov 26 04:18:34 localhost kernel: [ 7814.198045]  [<c104fe41>] 
irq_exit+0x41/0x80
Nov 26 04:18:34 localhost kernel: [ 7814.198048]  [<c12fc0e5>] 
xen_evtchn_do_upcall+0x25/0x30
Nov 26 04:18:34 localhost kernel: [ 7814.198053]  [<c147b287>] 
xen_do_upcall+0x7/0xc
Nov 26 04:18:34 localhost kernel: [ 7814.198058]  [<c10c00d8>] ? 
rcu_process_gp_end+0x58/0x70
Nov 26 04:18:34 localhost kernel: [ 7814.198061]  [<c10013a7>] ? 
xen_hypercall_sched_op+0x7/0x20
Nov 26 04:18:34 localhost kernel: [ 7814.198066]  [<c1007ef2>] ? 
xen_safe_halt+0x12/0x20
Nov 26 04:18:34 localhost kernel: [ 7814.198070]  [<c1015be6>] 
default_idle+0x56/0xb0
Nov 26 04:18:34 localhost kernel: [ 7814.198074]  [<c10158e7>] 
arch_cpu_idle+0x17/0x30
Nov 26 04:18:34 localhost kernel: [ 7814.198078]  [<c108e2ae>] 
cpu_startup_entry+0x15e/0x1d0
Nov 26 04:18:34 localhost kernel: [ 7814.198085]  [<c1464282>] 
cpu_bringup_and_idle+0x12/0x20
Nov 26 04:18:34 localhost kernel: [ 7814.198088] ---[ end trace 
d8c0d3f5c187aa6b ]---

And the recovery:

Nov 26 21:47:54 localhost kernel: [70773.950715] ------------[ cut here 
]------------
Nov 26 21:47:54 localhost kernel: [70773.950747] WARNING: at 
net/core/dev.c:4201 net_rx_action+0xfd/0x1c0()
Nov 26 21:47:54 localhost kernel: [70773.950751] Modules linked in: tun 
nfsv3 nfs_acl nfs fscache dm_multipath scsi_dh lockd sunrpc openvswitch 
ipt_REJECT nf_conntrack_ipv4 nf_defrag_ip
v4 xt_tcpudp xt_conntrack nf_conntrack iptable_filter ip_tables x_tables 
nls_utf8 isofs dm_mirror video backlight sbs sbshc hed acpi_ipmi 
ipmi_msghandler nvram sg psmouse serio_raw igb
i2c_algo_bit ptp pps_core hpilo tpm_tis tpm tpm_bios lpc_ich mfd_core 
ehci_pci crc32_pclmul aesni_intel ablk_helper cryptd lrw aes_i586 xts 
gf128mul dm_region_hash dm_log dm_mod shpchp
hpsa sd_mod scsi_mod uhci_hcd ohci_hcd ehci_hcd fbcon font tileblit 
bitblit softcursor [last unloaded: microcode]
Nov 26 21:47:54 localhost kernel: [70773.950852] CPU: 0 PID: 0 Comm: 
swapper/0 Tainted: G        W    3.10.11-0.xs1.8.50.127.377543 #1
Nov 26 21:47:54 localhost kernel: [70773.950856] Hardware name: HP 
ProLiant BL420c Gen8, BIOS I30 12/14/2012
Nov 26 21:47:54 localhost kernel: [70773.950860]  00000000 c13ccdfd 
c167fc78 c1278546 c167fc9c c1047fd3 c15ebc78 c163f7da
Nov 26 21:47:54 localhost kernel: [70773.950873]  00001069 c13ccdfd 
dff404c8 00000040 00000000 c167fcac c1048012 00000009
Nov 26 21:47:54 localhost kernel: [70773.950884]  00000000 c167fcd8 
c13ccdfd ed383888 010cbb97 000000e2 ed383880 00000043
Nov 26 21:47:54 localhost kernel: [70773.950896] Call Trace:
Nov 26 21:47:54 localhost kernel: [70773.950905]  [<c13ccdfd>] ? 
net_rx_action+0xfd/0x1c0
Nov 26 21:47:54 localhost kernel: [70773.950915]  [<c1278546>] 
dump_stack+0x16/0x20
Nov 26 21:47:54 localhost kernel: [70773.950924]  [<c1047fd3>] 
warn_slowpath_common+0x63/0x80
Nov 26 21:47:54 localhost kernel: [70773.950930]  [<c13ccdfd>] ? 
net_rx_action+0xfd/0x1c0
Nov 26 21:47:54 localhost kernel: [70773.950937]  [<c1048012>] 
warn_slowpath_null+0x22/0x30
Nov 26 21:47:54 localhost kernel: [70773.950954]  [<c13ccdfd>] 
net_rx_action+0xfd/0x1c0
Nov 26 21:47:54 localhost kernel: [70773.950969]  [<c104fcb9>] 
__do_softirq+0xd9/0x1e0
Nov 26 21:47:54 localhost kernel: [70773.950985]  [<c12fc045>] ? 
__xen_evtchn_do_upcall+0x245/0x280
Nov 26 21:47:54 localhost kernel: [70773.951002]  [<c104fe41>] 
irq_exit+0x41/0x80
Nov 26 21:47:54 localhost kernel: [70773.951011]  [<c12fc0e5>] 
xen_evtchn_do_upcall+0x25/0x30
Nov 26 21:47:54 localhost kernel: [70773.951019]  [<c147b287>] 
xen_do_upcall+0x7/0xc
Nov 26 21:47:54 localhost kernel: [70773.951026]  [<c10013a7>] ? 
xen_hypercall_sched_op+0x7/0x20
Nov 26 21:47:54 localhost kernel: [70773.951033]  [<c1007ef2>] ? 
xen_safe_halt+0x12/0x20
Nov 26 21:47:54 localhost kernel: [70773.951041]  [<c1015be6>] 
default_idle+0x56/0xb0
Nov 26 21:47:54 localhost kernel: [70773.951046]  [<c10158e7>] 
arch_cpu_idle+0x17/0x30
Nov 26 21:47:54 localhost kernel: [70773.951054]  [<c108e2ae>] 
cpu_startup_entry+0x15e/0x1d0
Nov 26 21:47:54 localhost kernel: [70773.951064]  [<c1460362>] 
rest_init+0x62/0x70
Nov 26 21:47:54 localhost kernel: [70773.951071]  [<c16efcea>] 
start_kernel+0x39a/0x3b0
Nov 26 21:47:54 localhost kernel: [70773.951076]  [<c16ef520>] ? 
repair_env_string+0x60/0x60
Nov 26 21:47:54 localhost kernel: [70773.951082]  [<c16ef2eb>] 
i386_start_kernel+0x8b/0x90
Nov 26 21:47:54 localhost kernel: [70773.951088]  [<c16f2c2d>] 
xen_start_kernel+0x7cd/0x7f0
Nov 26 21:47:54 localhost kernel: [70773.951097] ---[ end trace 
d8c0d3f5c187aa6c ]---
Nov 26 21:47:54 localhost kernel: [70773.952034] ------------[ cut here 
]------------
Nov 26 21:47:54 localhost kernel: [70773.952067] WARNING: at 
drivers/net/ethernet/intel/igb/igb_main.c:2860 __igb_close+0x3d/0xb0 [igb]()
Nov 26 21:47:54 localhost kernel: [70773.952071] Modules linked in: tun 
nfsv3 nfs_acl nfs fscache dm_multipath scsi_dh lockd sunrpc openvswitch 
ipt_REJECT nf_conntrack_ipv4 nf_defrag_ip
v4 xt_tcpudp xt_conntrack nf_conntrack iptable_filter ip_tables x_tables 
nls_utf8 isofs dm_mirror video backlight sbs sbshc hed acpi_ipmi 
ipmi_msghandler nvram sg psmouse serio_raw igb i2c_algo_bit ptp pps_core 
hpilo tpm_tis tpm tpm_bios lpc_ich mfd_core ehci_pci crc32_pclmul 
aesni_intel ablk_helper cryptd lrw aes_i586 xts gf128mul dm_region_hash 
dm_log dm_mod shpchp hpsa sd_mod scsi_mod uhci_hcd ohci_hcd ehci_hcd 
fbcon font tileblit bitblit softcursor [last unloaded: microcode]
Nov 26 21:47:54 localhost kernel: [70773.952150] CPU: 4 PID: 3467 Comm: 
ifconfig Tainted: G        W    3.10.11-0.xs1.8.50.127.377543 #1
Nov 26 21:47:54 localhost kernel: [70773.952153] Hardware name: HP 
ProLiant BL420c Gen8, BIOS I30 12/14/2012
Nov 26 21:47:54 localhost kernel: [70773.952157]  00000000 eddcec4d 
ca701d8c c1278546 ca701db0 c1047fd3 c15ebc78 edde1b0c
Nov 26 21:47:54 localhost kernel: [70773.952169]  00000b2c eddcec4d 
00000000 e35504c0 e5f17000 ca701dc0 c1048012 00000009
Nov 26 21:47:54 localhost kernel: [70773.952180]  00000000 ca701dd4 
eddcec4d e3550000 ca701e00 ca701e00 ca701ddc eddceccf
Nov 26 21:47:54 localhost kernel: [70773.952192] Call Trace:
Nov 26 21:47:54 localhost kernel: [70773.952207]  [<eddcec4d>] ? 
__igb_close+0x3d/0xb0 [igb]
Nov 26 21:47:54 localhost kernel: [70773.952216]  [<c1278546>] 
dump_stack+0x16/0x20
Nov 26 21:47:54 localhost kernel: [70773.952223]  [<c1047fd3>] 
warn_slowpath_common+0x63/0x80
Nov 26 21:47:54 localhost kernel: [70773.952237]  [<eddcec4d>] ? 
__igb_close+0x3d/0xb0 [igb]
Nov 26 21:47:54 localhost kernel: [70773.952243]  [<c1048012>] 
warn_slowpath_null+0x22/0x30
Nov 26 21:47:54 localhost kernel: [70773.952255]  [<eddcec4d>] 
__igb_close+0x3d/0xb0 [igb]
Nov 26 21:47:54 localhost kernel: [70773.952267]  [<eddceccf>] 
igb_close+0xf/0x20 [igb]
Nov 26 21:47:54 localhost kernel: [70773.952275]  [<c13c8691>] 
__dev_close_many+0x91/0xb0
Nov 26 21:47:54 localhost kernel: [70773.952284]  [<c13df583>] ? 
netpoll_rx_disable+0x43/0x50
Nov 26 21:47:54 localhost kernel: [70773.952289]  [<c13c9163>] 
__dev_close+0x43/0x80
Nov 26 21:47:54 localhost kernel: [70773.952300]  [<c13c7c28>] 
__dev_change_flags+0xa8/0x120
Nov 26 21:47:54 localhost kernel: [70773.952308]  [<c13c85c3>] 
dev_change_flags+0x23/0x60
Nov 26 21:47:54 localhost kernel: [70773.952314]  [<c1424d9c>] 
devinet_ioctl+0x29c/0x600
Nov 26 21:47:54 localhost kernel: [70773.952323]  [<c13dbf05>] ? 
dev_ioctl+0x475/0x4d0
Nov 26 21:47:54 localhost kernel: [70773.952330]  [<c1425d6b>] 
inet_ioctl+0x5b/0x80
Nov 26 21:47:54 localhost kernel: [70773.952340]  [<c13b776e>] 
sock_ioctl+0x1fe/0x230
Nov 26 21:47:54 localhost kernel: [70773.952350]  [<c13b7570>] ? 
sock_recvmsg_nosec+0xb0/0xb0
Nov 26 21:47:54 localhost kernel: [70773.952360]  [<c1143cf6>] 
vfs_ioctl+0x26/0x40
Nov 26 21:47:54 localhost kernel: [70773.952367]  [<c11448ba>] 
do_vfs_ioctl+0x4ea/0x550
Nov 26 21:47:54 localhost kernel: [70773.952376]  [<c113de22>] ? 
final_putname+0x32/0x40
Nov 26 21:47:54 localhost kernel: [70773.952382]  [<c113de22>] ? 
final_putname+0x32/0x40
Nov 26 21:47:54 localhost kernel: [70773.952391]  [<c113de67>] ? 
putname+0x37/0x40
Nov 26 21:47:54 localhost kernel: [70773.952401]  [<c1134b64>] ? 
do_sys_open+0x194/0x1a0
Nov 26 21:47:54 localhost kernel: [70773.952408]  [<c1144983>] 
SyS_ioctl+0x63/0x90
Nov 26 21:47:54 localhost kernel: [70773.952416]  [<c147ad4d>] 
sysenter_do_call+0x12/0x28
Nov 26 21:47:54 localhost kernel: [70773.952423] ---[ end trace 
d8c0d3f5c187aa6d ]---
Nov 26 21:47:54 localhost kernel: [70773.971294] igb 0000:04:00.1 eth1: 
Reset adapter
Nov 26 21:47:54 localhost kernel: [70774.068154] igb 0000:04:00.0 eth0: 
Reset adapter
Nov 26 21:47:55 localhost kernel: [70774.357949] igb: eth1 NIC Link is 
Up 1000 Mbps Full Duplex, Flow Control: RX/TX
Nov 26 21:48:00 localhost kernel: [70779.231904] igb: eth0 NIC Link is 
Up 1000 Mbps Full Duplex, Flow Control: RX/TX
Nov 26 21:48:00 localhost kernel: [70779.346793] igb: eth0 NIC Link is 
Up 1000 Mbps Full Duplex, Flow Control: RX/TX
Nov 26 21:48:02 localhost kernel: [70781.214844] igb 0000:04:00.0: 
Detected Tx Unit Hang
Nov 26 21:48:02 localhost kernel: [70781.214844]   Tx Queue             <7>
Nov 26 21:48:02 localhost kernel: [70781.214844]   TDH                  <0>
Nov 26 21:48:02 localhost kernel: [70781.214844]   TDT                  <0>
Nov 26 21:48:02 localhost kernel: [70781.214844]   next_to_use          <1>
Nov 26 21:48:02 localhost kernel: [70781.214844]   next_to_clean        <0>
Nov 26 21:48:02 localhost kernel: [70781.214844] buffer_info[next_to_clean]
Nov 26 21:48:02 localhost kernel: [70781.214844]   time_stamp 
<10cc0cd>
Nov 26 21:48:02 localhost kernel: [70781.214844]   next_to_watch 
<e2d5e000>
Nov 26 21:48:02 localhost kernel: [70781.214844]   jiffies 
<10cc2ae>
Nov 26 21:48:02 localhost kernel: [70781.214844]   desc.status 
<12c000>
Nov 26 21:48:04 localhost kernel: [70783.214857] igb 0000:04:00.0: 
Detected Tx Unit Hang
Nov 26 21:48:04 localhost kernel: [70783.214857]   Tx Queue             <7>
Nov 26 21:48:04 localhost kernel: [70783.214857]   TDH                  <0>
Nov 26 21:48:04 localhost kernel: [70783.214857]   TDT                  <0>
Nov 26 21:48:04 localhost kernel: [70783.214857]   next_to_use          <1>
Nov 26 21:48:04 localhost kernel: [70783.214857]   next_to_clean        <0>
Nov 26 21:48:04 localhost kernel: [70783.214857] buffer_info[next_to_clean]
Nov 26 21:48:04 localhost kernel: [70783.214857]   time_stamp 
<10cc0cd>
Nov 26 21:48:04 localhost kernel: [70783.214857]   next_to_watch 
<e2d5e000>
Nov 26 21:48:04 localhost kernel: [70783.214857]   jiffies 
<10cc4a2>
Nov 26 21:48:04 localhost kernel: [70783.214857]   desc.status 
<12c000>
Nov 26 21:48:06 localhost kernel: [70785.214700] igb 0000:04:00.0: 
Detected Tx Unit Hang
Nov 26 21:48:06 localhost kernel: [70785.214700]   Tx Queue             <7>
Nov 26 21:48:06 localhost kernel: [70785.214700]   TDH                  <0>
Nov 26 21:48:06 localhost kernel: [70785.214700]   TDT                  <0>
Nov 26 21:48:06 localhost kernel: [70785.214700]   next_to_use          <1>
Nov 26 21:48:06 localhost kernel: [70785.214700]   next_to_clean        <0>
Nov 26 21:48:06 localhost kernel: [70785.214700] buffer_info[next_to_clean]
Nov 26 21:48:06 localhost kernel: [70785.214700]   time_stamp 
<10cc0cd>
Nov 26 21:48:06 localhost kernel: [70785.214700]   next_to_watch 
<e2d5e000>
Nov 26 21:48:06 localhost kernel: [70785.214700]   jiffies 
<10cc696>
Nov 26 21:48:06 localhost kernel: [70785.214700]   desc.status 
<12c000>
Nov 26 21:48:08 localhost kernel: [70787.214734] igb 0000:04:00.0: 
Detected Tx Unit Hang
Nov 26 21:48:08 localhost kernel: [70787.214734]   Tx Queue             <7>
Nov 26 21:48:08 localhost kernel: [70787.214734]   TDH                  <0>
Nov 26 21:48:08 localhost kernel: [70787.214734]   TDT                  <0>
Nov 26 21:48:08 localhost kernel: [70787.214734]   next_to_use          <1>
Nov 26 21:48:08 localhost kernel: [70787.214734]   next_to_clean        <0>
Nov 26 21:48:08 localhost kernel: [70787.214734] buffer_info[next_to_clean]
Nov 26 21:48:08 localhost kernel: [70787.214734]   time_stamp 
<10cc0cd>
Nov 26 21:48:08 localhost kernel: [70787.214734]   next_to_watch 
<e2d5e000>
Nov 26 21:48:08 localhost kernel: [70787.214734]   jiffies 
<10cc88a>
Nov 26 21:48:08 localhost kernel: [70787.214734]   desc.status 
<12c000>
Nov 26 21:48:10 localhost kernel: [70789.214752] igb 0000:04:00.0: 
Detected Tx Unit Hang
Nov 26 21:48:10 localhost kernel: [70789.214752]   Tx Queue             <7>
Nov 26 21:48:10 localhost kernel: [70789.214752]   TDH                  <0>
Nov 26 21:48:10 localhost kernel: [70789.214752]   TDT                  <0>
Nov 26 21:48:10 localhost kernel: [70789.214752]   next_to_use          <1>
Nov 26 21:48:10 localhost kernel: [70789.214752]   next_to_clean        <0>
Nov 26 21:48:10 localhost kernel: [70789.214752] buffer_info[next_to_clean]
Nov 26 21:48:10 localhost kernel: [70789.214752]   time_stamp 
<10cc0cd>
Nov 26 21:48:10 localhost kernel: [70789.214752]   next_to_watch 
<e2d5e000>
Nov 26 21:48:10 localhost kernel: [70789.214752]   jiffies 
<10cca7e>
Nov 26 21:48:10 localhost kernel: [70789.214752]   desc.status 
<12c000>
Nov 26 21:48:11 localhost kernel: [70790.214611] igb 0000:04:00.0 eth0: 
Reset adapter
Nov 26 21:48:11 localhost kernel: [70790.246610] igb 0000:04:00.1 eth1: 
Reset adapter
Nov 26 21:48:11 localhost kernel: [70790.250616] igb: eth1 NIC Link is Down
Nov 26 21:48:11 localhost kernel: [70790.340089] igb: eth0 NIC Link is 
Up 1000 Mbps Full Duplex, Flow Control: RX/TX
Nov 26 21:48:11 localhost kernel: [70790.367984] igb: eth1 NIC Link is 
Up 1000 Mbps Full Duplex, Flow Control: RX/TX
Nov 26 21:48:11 localhost kernel: [70790.598550] igb: eth1 NIC Link is Down
Nov 26 21:48:11 localhost kernel: [70790.634559] igb: eth1 NIC Link is 
Up 1000 Mbps Full Duplex, Flow Control: RX/TX
Nov 26 21:48:11 localhost kernel: [70790.638593] igb: eth0 NIC Link is Down
Nov 26 21:48:11 localhost kernel: [70790.674599] igb: eth0 NIC Link is 
Up 1000 Mbps Full Duplex, Flow Control: RX/TX


On 30/01/14 19:08, Zoltan Kiss wrote:
> I've experienced some queue timeout problems mentioned in the subject
> with igb and bnx2 cards. I haven't seen them on other cards so far. I'm
> using XenServer with 3.10 Dom0 kernel (however igb were already updated
> to latest version), and there are Windows guests sending data through
> these cards. I noticed these problems in XenRT test runs, and I know
> that they usually mean some lost interrupt problem or other hardware
> error, but in my case they started to appear more often, and they are
> likely connected to my netback grant mapping patches. These patches
> causing skb's with huge (~64kb) linear buffers to appear more often.
> The reason for that is an old problem in the ring protocol: originally
> the maximum amount of slots were linked to MAX_SKB_FRAGS, as every slot
> ended up as a frag of the skb. When this value were changed, netback had
> to cope with the situation by coalescing the packets into fewer frags.
> My patch series take a different approach: the leftover slots (pages)
> were assigned to a new skb's frags, and that skb were stashed to the
> frag_list of the first one. Then, before sending it off to the stack it
> calls skb = skb_copy_expand(skb, 0, 0, GFP_ATOMIC, __GFP_NOWARN), which
> basically creates a new skb and copied all the data into it. As far as I
> understood, it put everything into the linear buffer, which can amount
> to 64KB at most. The original skb are freed then, and this new one were
> sent to the stack.
> I suspect that this is the problem as it only happens when guests send
> too much slots. Does anyone familiar with these drivers have seen such
> issue before? (when these kind of skb's get stucked in the queue)


------------------------------------------------------------------------------
Android apps run on BlackBerry 10
Introducing the new BlackBerry 10.2.1 Runtime for Android apps.
Now with support for Jelly Bean, Bluetooth, Mapview and more.
Get your Android app in front of a whole new audience.  Start now.
http://pubads.g.doubleclick.net/gampad/clk?id=124407151&iu=/4140/ostg.clktrk
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel&#174; Ethernet, visit http://communities.intel.com/community/wired

^ permalink raw reply

* Re: [PATCH net] net: Clear local_df only if crossing namespace.
From: Pravin Shelar @ 2014-02-12 17:05 UTC (permalink / raw)
  To: Nicolas Dichtel; +Cc: David Miller, netdev, Templin, Fred L, Steffen Klassert
In-Reply-To: <52FB3FC1.8080603@6wind.com>

On Wed, Feb 12, 2014 at 1:32 AM, Nicolas Dichtel
<nicolas.dichtel@6wind.com> wrote:
> Le 12/02/2014 05:26, Pravin Shelar a écrit :
>
>> On Mon, Feb 10, 2014 at 6:11 PM, Hannes Frederic Sowa
>> <hannes@stressinduktion.org> wrote:
>>>
>>> On Mon, Feb 10, 2014 at 01:00:14PM -0800, Pravin Shelar wrote:
>>>>
>>>> On Fri, Feb 7, 2014 at 4:58 PM, Hannes Frederic Sowa
>>>> <hannes@stressinduktion.org> wrote:
>>>>>
>>>>> May I know because of wich vport, vxlan or gre, you did this change?
>>>>>
>>>> It affects both gre and vxlan.
>>>
>>>
>>> Ok, thanks.
>>>
>>>>> I am feeling a bit uncomfortable handling remote and local packets that
>>>>> differently on lower tunnel output (local_df is mostly set on locally
>>>>> originating packets).
>>>>
>>>>
>>>> For ip traffic it make sense to turn on local_df only for local
>>>> traffic, since for remote case we can send icmp (frag-needed) back to
>>>> source. No such thing exist for OVS tunnels. ICMP packet are not
>>>> returned to source for the tunnels. That is why to be on safe side,
>>>> local_df is turned on for tunnels in OVS.
>>>
>>>
>>> I have a proposal:
>>>
>>> I don't like it that much because of the many arguments. But I currently
>>> don't see another easy solution. Maybe we should make bool xnet an enum
>>> and
>>> test with bitops?
>>>
>>> I left the clearing of local_df in skb_scrub_packet as we need it for the
>>> dev_forward_skb case and it should be done that in any case.
>>>
>>> This diff is slightly compile tested. ;)
>>>
>>> I can test and make proper submit if you agree.
>>>
>>> What do you think?
>>>
>>
>> I am not sure why the caller can not just set skb->local_df before
>> calling iptunnel_xmit() rather than passing extra arg to this
>> function?
>> There are not that many caller of this function.
>
> The benefit is that it ensures that future callers will think about this
> point
> ;-)
>

But that add extra test cases in fast path.
For example OVS we can not reset skb->mark in skb_scrub_packet(). I am
going to send patch for that too. Do you think I should add another
argument for skb-mark clear too ?
We can not make code every piece of code future proof. thats why we
have review process.

^ permalink raw reply

* Re: [PATCH net 1/3] kref: add kref_sub_return
From: Greg Kroah-Hartman @ 2014-02-12 16:56 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: virtio-dev, Joern Engel, Anatol Pomozov, netdev, linux-kernel,
	virtualization, qinchuanyu, davem
In-Reply-To: <1392222846-26699-2-git-send-email-mst@redhat.com>

On Wed, Feb 12, 2014 at 06:38:21PM +0200, Michael S. Tsirkin wrote:
> It is sometimes useful to get the value of the reference count after
> decrement.
> For example, vhost wants to execute some periodic cleanup operations
> once number of references drops below a specific value, before it
> reaches zero (for efficiency).

You should never care about what the value of the kref is, if you are
using it correctly :)

So I really don't want to add this function, as I'm sure people will use
it incorrectly.  You should only care if the reference drops to 0, if
not, then your usage doesn't really fit into the "kref" model, and so,
just use an atomic variable.

I really want to know why it matters for "efficiency" that you know this
number.  How does that help anything, as the number could then go up
later on, and the work you did at a "lower" number is obsolete, right?

thanks,

greg k-h

^ permalink raw reply

* [PATCH ipsec-next] ipsec: add support of limited SA dump
From: Nicolas Dichtel @ 2014-02-12 16:46 UTC (permalink / raw)
  To: steffen.klassert, herbert, davem; +Cc: netdev, Nicolas Dichtel

The goal of this patch is to allow userland to dump only a part of SA by
specifying a filter during the dump.
The kernel is in charge to filter SA, this avoids to generate useless netlink
traffic (it save also some cpu cycles). This is particularly useful when there
is a big number of SA set on the system.

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---

Note that iproute2 patches are available and will be submitted once
the patch will be accepted. I can send them on demand.

 include/net/xfrm.h           |  4 +++-
 include/uapi/linux/pfkeyv2.h | 15 ++++++++++++++-
 include/uapi/linux/xfrm.h    | 10 ++++++++++
 net/key/af_key.c             | 19 ++++++++++++++++++-
 net/xfrm/xfrm_state.c        | 25 ++++++++++++++++++++++++-
 net/xfrm/xfrm_user.c         | 28 +++++++++++++++++++++++++++-
 6 files changed, 96 insertions(+), 5 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index afa5730fb3bd..17e4bfdbe0b3 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -123,6 +123,7 @@ struct xfrm_state_walk {
 		u8		proto;
 	};
 	u32			seq;
+	struct xfrm_filter	*filter;
 };
 
 /* Full description of state of transformer. */
@@ -1405,7 +1406,8 @@ static inline void xfrm_sysctl_fini(struct net *net)
 }
 #endif
 
-void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto);
+void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto,
+			  struct xfrm_filter *filter);
 int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
 		    int (*func)(struct xfrm_state *, int, void*), void *);
 void xfrm_state_walk_done(struct xfrm_state_walk *walk, struct net *net);
diff --git a/include/uapi/linux/pfkeyv2.h b/include/uapi/linux/pfkeyv2.h
index 0b80c806631f..ada7f0171ccc 100644
--- a/include/uapi/linux/pfkeyv2.h
+++ b/include/uapi/linux/pfkeyv2.h
@@ -235,6 +235,18 @@ struct sadb_x_kmaddress {
 } __attribute__((packed));
 /* sizeof(struct sadb_x_kmaddress) == 8 */
 
+/* To specify the SA dump filter */
+struct sadb_x_filter {
+	__u16	sadb_x_filter_len;
+	__u16	sadb_x_filter_exttype;
+	__u32	sadb_x_filter_saddr[4];
+	__u32	sadb_x_filter_daddr[4];
+	__u16	sadb_x_filter_family;
+	__u8	sadb_x_filter_splen;
+	__u8	sadb_x_filter_dplen;
+} __attribute__((packed));
+/* sizeof(struct sadb_x_filter) == 40 */
+
 /* Message types */
 #define SADB_RESERVED		0
 #define SADB_GETSPI		1
@@ -358,7 +370,8 @@ struct sadb_x_kmaddress {
 #define SADB_X_EXT_SEC_CTX		24
 /* Used with MIGRATE to pass @ to IKE for negotiation */
 #define SADB_X_EXT_KMADDRESS		25
-#define SADB_EXT_MAX			25
+#define SADB_X_EXT_FILTER		26
+#define SADB_EXT_MAX			26
 
 /* Identity Extension values */
 #define SADB_IDENTTYPE_RESERVED	0
diff --git a/include/uapi/linux/xfrm.h b/include/uapi/linux/xfrm.h
index a8cd6a4a2970..6550c679584f 100644
--- a/include/uapi/linux/xfrm.h
+++ b/include/uapi/linux/xfrm.h
@@ -298,6 +298,8 @@ enum xfrm_attr_type_t {
 	XFRMA_TFCPAD,		/* __u32 */
 	XFRMA_REPLAY_ESN_VAL,	/* struct xfrm_replay_esn */
 	XFRMA_SA_EXTRA_FLAGS,	/* __u32 */
+	XFRMA_PROTO,		/* __u8 */
+	XFRMA_FILTER,		/* struct xfrm_filter */
 	__XFRMA_MAX
 
 #define XFRMA_MAX (__XFRMA_MAX - 1)
@@ -474,6 +476,14 @@ struct xfrm_user_mapping {
 	__be16				new_sport;
 };
 
+struct xfrm_filter {
+	xfrm_address_t			saddr;
+	xfrm_address_t			daddr;
+	__u16				family;
+	__u8				splen;
+	__u8				dplen;
+};
+
 #ifndef __KERNEL__
 /* backwards compatibility for userspace */
 #define XFRMGRP_ACQUIRE		1
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 1a04c1329362..70f8464eb6f0 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1798,6 +1798,7 @@ static void pfkey_dump_sa_done(struct pfkey_sock *pfk)
 static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
 {
 	u8 proto;
+	struct xfrm_filter *filter = NULL;
 	struct pfkey_sock *pfk = pfkey_sk(sk);
 
 	if (pfk->dump.dump != NULL)
@@ -1807,11 +1808,27 @@ static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_ms
 	if (proto == 0)
 		return -EINVAL;
 
+	if (ext_hdrs[SADB_X_EXT_FILTER - 1]) {
+		struct sadb_x_filter *xfilter = ext_hdrs[SADB_X_EXT_FILTER - 1];
+
+		filter = kmalloc(sizeof(*filter), GFP_KERNEL);
+		if (filter == NULL)
+			return -ENOMEM;
+
+		memcpy(&filter->saddr, &xfilter->sadb_x_filter_saddr,
+		       sizeof(xfrm_address_t));
+		memcpy(&filter->daddr, &xfilter->sadb_x_filter_daddr,
+		       sizeof(xfrm_address_t));
+		filter->family = xfilter->sadb_x_filter_family;
+		filter->splen = xfilter->sadb_x_filter_splen;
+		filter->dplen = xfilter->sadb_x_filter_dplen;
+	}
+
 	pfk->dump.msg_version = hdr->sadb_msg_version;
 	pfk->dump.msg_portid = hdr->sadb_msg_pid;
 	pfk->dump.dump = pfkey_dump_sa;
 	pfk->dump.done = pfkey_dump_sa_done;
-	xfrm_state_walk_init(&pfk->dump.u.state, proto);
+	xfrm_state_walk_init(&pfk->dump.u.state, proto, filter);
 
 	return pfkey_do_dump(pfk);
 }
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index a26b7aa79475..45533b3fa63f 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1590,6 +1590,23 @@ unlock:
 }
 EXPORT_SYMBOL(xfrm_alloc_spi);
 
+static bool __xfrm_state_filter_match(struct xfrm_state *x,
+				      struct xfrm_filter *filter)
+{
+	if (filter) {
+		if ((filter->family == AF_INET ||
+		     filter->family == AF_INET6) &&
+		    x->props.family != filter->family)
+			return false;
+
+		return addr_match(&x->props.saddr, &filter->saddr,
+				  filter->splen) &&
+		       addr_match(&x->id.daddr, &filter->daddr,
+				  filter->dplen);
+	}
+	return true;
+}
+
 int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
 		    int (*func)(struct xfrm_state *, int, void*),
 		    void *data)
@@ -1612,6 +1629,8 @@ int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
 		state = container_of(x, struct xfrm_state, km);
 		if (!xfrm_id_proto_match(state->id.proto, walk->proto))
 			continue;
+		if (!__xfrm_state_filter_match(state, walk->filter))
+			continue;
 		err = func(state, walk->seq, data);
 		if (err) {
 			list_move_tail(&walk->all, &x->all);
@@ -1630,17 +1649,21 @@ out:
 }
 EXPORT_SYMBOL(xfrm_state_walk);
 
-void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto)
+void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto,
+			  struct xfrm_filter *filter)
 {
 	INIT_LIST_HEAD(&walk->all);
 	walk->proto = proto;
 	walk->state = XFRM_STATE_DEAD;
 	walk->seq = 0;
+	walk->filter = filter;
 }
 EXPORT_SYMBOL(xfrm_state_walk_init);
 
 void xfrm_state_walk_done(struct xfrm_state_walk *walk, struct net *net)
 {
+	kfree(walk->filter);
+
 	if (list_empty(&walk->all))
 		return;
 
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index ade9988f6e33..594ccb441801 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -887,6 +887,7 @@ static int xfrm_dump_sa_done(struct netlink_callback *cb)
 	return 0;
 }
 
+static const struct nla_policy xfrma_policy[XFRMA_MAX+1];
 static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb)
 {
 	struct net *net = sock_net(skb->sk);
@@ -902,8 +903,31 @@ static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb)
 	info.nlmsg_flags = NLM_F_MULTI;
 
 	if (!cb->args[0]) {
+		struct nlattr *attrs[XFRMA_MAX+1];
+		struct xfrm_filter *filter = NULL;
+		u8 proto = 0;
+		int err;
+
 		cb->args[0] = 1;
-		xfrm_state_walk_init(walk, 0);
+
+		err = nlmsg_parse(cb->nlh, 0, attrs, XFRMA_MAX,
+				  xfrma_policy);
+		if (err < 0)
+			return err;
+
+		if (attrs[XFRMA_FILTER]) {
+			filter = kmalloc(sizeof(*filter), GFP_KERNEL);
+			if (filter == NULL)
+				return -ENOMEM;
+
+			memcpy(filter, nla_data(attrs[XFRMA_FILTER]),
+			       sizeof(*filter));
+		}
+
+		if (attrs[XFRMA_PROTO])
+			proto = nla_get_u8(attrs[XFRMA_PROTO]);
+
+		xfrm_state_walk_init(walk, proto, filter);
 	}
 
 	(void) xfrm_state_walk(net, walk, dump_one_state, &info);
@@ -2309,6 +2333,8 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
 	[XFRMA_TFCPAD]		= { .type = NLA_U32 },
 	[XFRMA_REPLAY_ESN_VAL]	= { .len = sizeof(struct xfrm_replay_state_esn) },
 	[XFRMA_SA_EXTRA_FLAGS]	= { .type = NLA_U32 },
+	[XFRMA_PROTO]		= { .type = NLA_U8 },
+	[XFRMA_FILTER]		= { .len = sizeof(struct xfrm_filter) },
 };
 
 static const struct xfrm_link {
-- 
1.8.5.4

^ permalink raw reply related

* [PATCH net-next 10/10] ieee802154: enable smart transmitter features of RF212
From: Phoebe Buckheister @ 2014-02-12 16:37 UTC (permalink / raw)
  To: netdev; +Cc: linux-zigbee-devel, davem, Phoebe Buckheister
In-Reply-To: <1392223034-19955-1-git-send-email-phoebe.buckheister@itwm.fraunhofer.de>

This patch does multiple things:

 * add .set_csma_params and .set_frame_retries for the RF212 radio.
   This should work fine with RF230, but since I have no RF230 radios to
   test with, RF230 does not implement these right now
 * enable TX_ARET for frame retransmission limits greater than -1

Since RF230 has no operations to change CSMA parameters or frame retry
limits, RF230 will not be able to enter TX_ARET with this patch.

Signed-off-by: Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
---
 drivers/net/ieee802154/at86rf230.c |   65 +++++++++++++++++++++++++++++++++++-
 1 file changed, 64 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index 77b8111..4f87102 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -52,6 +52,7 @@ struct at86rf230_local {
 	spinlock_t lock;
 	bool irq_busy;
 	bool is_tx;
+	bool tx_aret;
 
 	int rssi_base_val;
 };
@@ -549,7 +550,10 @@ at86rf230_state(struct ieee802154_dev *dev, int state)
 	} while (val == STATE_TRANSITION_IN_PROGRESS);
 
 
-	if (val == desired_status)
+	if (val == desired_status ||
+		(desired_status == STATE_RX_ON && val == STATE_BUSY_RX) ||
+		(desired_status == STATE_RX_AACK_ON &&
+			val == STATE_BUSY_RX_AACK))
 		return 0;
 
 	pr_err("unexpected state change: %d, asked for %d\n", val, state);
@@ -570,6 +574,10 @@ at86rf230_start(struct ieee802154_dev *dev)
 	if (rc)
 		return rc;
 
+	rc = at86rf230_state(dev, STATE_FORCE_TX_ON);
+	if (rc)
+		return rc;
+
 	return at86rf230_state(dev, STATE_RX_AACK_ON);
 }
 
@@ -673,6 +681,12 @@ at86rf230_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
 	if (rc)
 		goto err_rx;
 
+	if (lp->tx_aret) {
+		rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_TX_ARET_ON);
+		if (rc)
+			goto err_rx;
+	}
+
 	rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_BUSY_TX);
 	if (rc)
 		goto err_rx;
@@ -827,6 +841,44 @@ at86rf212_set_cca_ed_level(struct ieee802154_dev *dev, s32 level)
 	return at86rf230_write_subreg(lp, SR_CCA_ED_THRES, desens_steps);
 }
 
+static int
+at86rf212_set_csma_params(struct ieee802154_dev *dev, u8 min_be, u8 max_be,
+			  u8 retries)
+{
+	struct at86rf230_local *lp = dev->priv;
+	int rc;
+
+	if (min_be > max_be || max_be > 8 || retries > 5)
+		return -EINVAL;
+
+	rc = at86rf230_write_subreg(lp, SR_MIN_BE, min_be);
+	if (rc)
+		return rc;
+
+	rc = at86rf230_write_subreg(lp, SR_MAX_BE, max_be);
+	if (rc)
+		return rc;
+
+	return at86rf230_write_subreg(lp, SR_MAX_CSMA_RETRIES, max_be);
+}
+
+static int
+at86rf212_set_frame_retries(struct ieee802154_dev *dev, s8 retries)
+{
+	struct at86rf230_local *lp = dev->priv;
+	int rc = 0;
+
+	if (retries < -1 || retries > 15)
+		return -EINVAL;
+
+	lp->tx_aret = retries >= 0;
+
+	if (retries >= 0)
+		rc = at86rf230_write_subreg(lp, SR_MAX_FRAME_RETRIES, retries);
+
+	return rc;
+}
+
 static struct ieee802154_ops at86rf230_ops = {
 	.owner = THIS_MODULE,
 	.xmit = at86rf230_xmit,
@@ -849,6 +901,8 @@ static struct ieee802154_ops at86rf212_ops = {
 	.set_lbt = at86rf212_set_lbt,
 	.set_cca_mode = at86rf212_set_cca_mode,
 	.set_cca_ed_level = at86rf212_set_cca_ed_level,
+	.set_csma_params = at86rf212_set_csma_params,
+	.set_frame_retries = at86rf212_set_frame_retries,
 };
 
 static void at86rf230_irqwork(struct work_struct *work)
@@ -925,6 +979,7 @@ static int at86rf230_hw_init(struct at86rf230_local *lp)
 	struct at86rf230_platform_data *pdata = lp->spi->dev.platform_data;
 	int rc, irq_pol;
 	u8 status;
+	u8 csma_seed[2];
 
 	rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &status);
 	if (rc)
@@ -948,6 +1003,14 @@ static int at86rf230_hw_init(struct at86rf230_local *lp)
 	if (rc)
 		return rc;
 
+	get_random_bytes(csma_seed, ARRAY_SIZE(csma_seed));
+	rc = at86rf230_write_subreg(lp, SR_CSMA_SEED_0, csma_seed[0]);
+	if (rc)
+		return rc;
+	rc = at86rf230_write_subreg(lp, SR_CSMA_SEED_1, csma_seed[1]);
+	if (rc)
+		return rc;
+
 	/* CLKM changes are applied immediately */
 	rc = at86rf230_write_subreg(lp, SR_CLKM_SHA_SEL, 0x00);
 	if (rc)
-- 
1.7.9.5

^ permalink raw reply related

* RE: [PATCH 05/14] net: axienet: Service completion interrupts ASAP
From: David Laight @ 2014-02-12 16:38 UTC (permalink / raw)
  To: 'Michal Simek', netdev@vger.kernel.org
  Cc: Srikanth Thokala, Peter Crosthwaite, Michal Simek,
	Anirudha Sarangi, John Linn, linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <cafb13f2ebe4bb996bafb91e405d8609454bb920.1392220536.git.michal.simek@xilinx.com>

From: Michal Simek
> From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
> 
> The packet completion interrupts for TX and RX should be serviced before
> the packets are consumed. This ensures against the degenerate case when a
> new completion interrupt is raised after the handler has exited but before
> the interrupts are cleared. In this case its possible for the ISR to clear
> an unhandled interrupt (leading to potential deadlock).

I would clear the IRQ after processing the last packet, and then do a final
check for another packet.

That reduces the number of interrupts you take and then find there is
no work (because it was done on the previous interrupt).

There is a slight 'gotcha' in that the write to clear the IRQ can easily
get delayed enough the that cpu exits the ISR before the IRQ line
actually drops - leading the unwanted and unclaimed interrupts.
A posted write over PCIe could easily take long enough.

Maybe a hybrid scheme where the IRQ is cleared when the next entry
is still owned by the device would work.

	David

^ permalink raw reply

* [PATCH net 1/3] kref: add kref_sub_return
From: Michael S. Tsirkin @ 2014-02-12 16:38 UTC (permalink / raw)
  To: linux-kernel
  Cc: virtio-dev, Joern Engel, Anatol Pomozov, netdev, virtualization,
	Greg Kroah-Hartman, qinchuanyu, davem
In-Reply-To: <1392222846-26699-1-git-send-email-mst@redhat.com>

It is sometimes useful to get the value of the reference count after
decrement.
For example, vhost wants to execute some periodic cleanup operations
once number of references drops below a specific value, before it
reaches zero (for efficiency).

Add an API to do this atomically and efficiently using
atomic_sub_return.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---

Greg, could you ack this API extension please?
I think it is cleanest to merge this through -net together
with the first user.

 include/linux/kref.h | 34 +++++++++++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/include/linux/kref.h b/include/linux/kref.h
index 484604d..cb20550 100644
--- a/include/linux/kref.h
+++ b/include/linux/kref.h
@@ -61,7 +61,7 @@ static inline void kref_get(struct kref *kref)
  *
  * Subtract @count from the refcount, and if 0, call release().
  * Return 1 if the object was removed, otherwise return 0.  Beware, if this
- * function returns 0, you still can not count on the kref from remaining in
+ * function returns 0, you still can not count on the kref remaining in
  * memory.  Only use the return value if you want to see if the kref is now
  * gone, not present.
  */
@@ -78,6 +78,38 @@ static inline int kref_sub(struct kref *kref, unsigned int count,
 }
 
 /**
+ * kref_sub_return - subtract a number of refcounts for object.
+ * @kref: object.
+ * @count: Number of recounts to subtract.
+ * @release: pointer to the function that will clean up the object when the
+ *	     last reference to the object is released.
+ *	     This pointer is required, and it is not acceptable to pass kfree
+ *	     in as this function.  If the caller does pass kfree to this
+ *	     function, you will be publicly mocked mercilessly by the kref
+ *	     maintainer, and anyone else who happens to notice it.  You have
+ *	     been warned.
+ *
+ * Subtract @count from the refcount, and if 0, call release().
+ * Return the new refcount.  Beware, if this function returns > N, you still
+ * can not count on there being at least N other references, and in
+ * particular, on the kref remaining in memory.
+ * Only use the return value if you want to see if there are at most,
+ * not at least, N other references to kref,
+ */
+static inline int kref_sub_return(struct kref *kref, unsigned int count,
+				  void (*release)(struct kref *kref))
+{
+	int r;
+
+	WARN_ON(release == NULL);
+
+	r = atomic_sub_return((int) count, &kref->refcount);
+	if (!r)
+		release(kref);
+	return r;
+}
+
+/**
  * kref_put - decrement refcount for object.
  * @kref: object.
  * @release: pointer to the function that will clean up the object when the
-- 
MST

^ permalink raw reply related

* [PATCH net 2/3] vhost: fix ref cnt checking deadlock
From: Michael S. Tsirkin @ 2014-02-12 16:38 UTC (permalink / raw)
  To: linux-kernel; +Cc: virtio-dev, kvm, netdev, virtualization, qinchuanyu, davem
In-Reply-To: <1392222846-26699-1-git-send-email-mst@redhat.com>

vhost checked the counter within the refcnt before decrementing.  It
really wanted to know that there aren't too many references, as a way to
batch freeing resources a bit more efficiently.

This works well but it we now access the
ref counter twice so there's a race:
all users might see a high count and decide
to defer freeing resources.
In the end no one initiates freeing resources
until the last reference is gone (which is on VM shotdown
so might happen after a looooong time).

Let's do what we should have done straight away:
add a kref API to return the kref value atomically,
and use that to avoid the deadlock.

Reported-by: Qin Chuanyu <qinchuanyu@huawei.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 drivers/vhost/net.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 831eb4f..7eaf2de 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -140,9 +140,9 @@ vhost_net_ubuf_alloc(struct vhost_virtqueue *vq, bool zcopy)
 	return ubufs;
 }
 
-static void vhost_net_ubuf_put(struct vhost_net_ubuf_ref *ubufs)
+static int vhost_net_ubuf_put(struct vhost_net_ubuf_ref *ubufs)
 {
-	kref_put(&ubufs->kref, vhost_net_zerocopy_done_signal);
+	return kref_sub_return(&ubufs->kref, 1, vhost_net_zerocopy_done_signal);
 }
 
 static void vhost_net_ubuf_put_and_wait(struct vhost_net_ubuf_ref *ubufs)
@@ -306,22 +306,21 @@ static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success)
 {
 	struct vhost_net_ubuf_ref *ubufs = ubuf->ctx;
 	struct vhost_virtqueue *vq = ubufs->vq;
-	int cnt = atomic_read(&ubufs->kref.refcount);
+	int cnt;
 
 	/* set len to mark this desc buffers done DMA */
 	vq->heads[ubuf->desc].len = success ?
 		VHOST_DMA_DONE_LEN : VHOST_DMA_FAILED_LEN;
-	vhost_net_ubuf_put(ubufs);
+	cnt = vhost_net_ubuf_put(ubufs);
 
 	/*
 	 * Trigger polling thread if guest stopped submitting new buffers:
-	 * in this case, the refcount after decrement will eventually reach 1
-	 * so here it is 2.
+	 * in this case, the refcount after decrement will eventually reach 1.
 	 * We also trigger polling periodically after each 16 packets
 	 * (the value 16 here is more or less arbitrary, it's tuned to trigger
 	 * less than 10% of times).
 	 */
-	if (cnt <= 2 || !(cnt % 16))
+	if (cnt <= 1 || !(cnt % 16))
 		vhost_poll_queue(&vq->poll);
 }
 
-- 
MST

^ permalink raw reply related

* [PATCH net 0/3] vhost fixes for 3.14, -stable
From: Michael S. Tsirkin @ 2014-02-12 16:37 UTC (permalink / raw)
  To: linux-kernel; +Cc: virtio-dev, netdev, virtualization, qinchuanyu, davem

This fixes a deadlock with vhost reported in the field,
as well as a theoretical race issue found by code
review.

Patches 1+2 are needed for stable.

Thanks to Qin Chuanyu for reporting the issue!

Michael S. Tsirkin (3):
  kref: add kref_sub_return
  vhost: fix ref cnt checking deadlock
  vhost: fix a theoretical race in device cleanup

 include/linux/kref.h | 33 ++++++++++++++++++++++++++++++++-
 drivers/vhost/net.c  | 15 ++++++++++-----
 2 files changed, 42 insertions(+), 6 deletions(-)

-- 
MST

^ permalink raw reply

* [PATCH net-next 09/10] ieee802154: add netlink APIs for smartMAC configuration
From: Phoebe Buckheister @ 2014-02-12 16:37 UTC (permalink / raw)
  To: netdev; +Cc: linux-zigbee-devel, davem, Phoebe Buckheister
In-Reply-To: <1392223034-19955-1-git-send-email-phoebe.buckheister@itwm.fraunhofer.de>

Introduce new netlink attributes for SET_PHY_ATTRS:
 * CSMA minimal backoff exponent
 * CSMA maximal backoff exponent
 * CSMA retry limit
 * frame retransmission limit

The CSMA attributes shall correspond to minBE, maxBE and maxCSMABackoffs of
802.15.4, respectively. The frame retransmission shall correspond to
maxFrameRetries of 802.15.4, unless given as -1: then the old behaviour
of the stack shall apply. For RF2xy, the old behaviour is to not do
channel sensing at all and simply send *right now*, which is not
intended behaviour for most applications and actually prohibited for
some channel/page combinations.

For all values except frame retransmission limit, the defaults of
802.15.4 apply. Frame retransmission limits are set to -1 to indicate
backward-compatible behaviour.

Signed-off-by: Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
---
 include/linux/nl802154.h       |    5 ++++
 include/net/mac802154.h        |   12 ++++++++
 include/net/wpan-phy.h         |    7 +++++
 net/ieee802154/nl-phy.c        |   63 +++++++++++++++++++++++++++++++++++++++-
 net/ieee802154/nl_policy.c     |    5 ++++
 net/ieee802154/wpan-class.c    |    6 ++++
 net/mac802154/ieee802154_dev.c |   23 +++++++++++++++
 7 files changed, 120 insertions(+), 1 deletion(-)

diff --git a/include/linux/nl802154.h b/include/linux/nl802154.h
index 0594a0a..e110b8c 100644
--- a/include/linux/nl802154.h
+++ b/include/linux/nl802154.h
@@ -74,6 +74,11 @@ enum {
 	IEEE802154_ATTR_LBT_ENABLED,
 	IEEE802154_ATTR_CCA_MODE,
 	IEEE802154_ATTR_CCA_ED_LEVEL,
+	IEEE802154_ATTR_CSMA_RETRIES,
+	IEEE802154_ATTR_CSMA_MIN_BE,
+	IEEE802154_ATTR_CSMA_MAX_BE,
+
+	IEEE802154_ATTR_FRAME_RETRIES,
 
 	__IEEE802154_ATTR_MAX,
 };
diff --git a/include/net/mac802154.h b/include/net/mac802154.h
index 15fe6bc..8ca3d04 100644
--- a/include/net/mac802154.h
+++ b/include/net/mac802154.h
@@ -131,6 +131,14 @@ struct ieee802154_dev {
  *	  Sets the CCA energy detection threshold in dBm. Called with pib_lock
  *	  held.
  *	  Returns either zero, or negative errno.
+ *
+ * set_csma_params
+ *	  Sets the CSMA parameter set for the PHY. Called with pib_lock held.
+ *	  Returns either zero, or negative errno.
+ *
+ * set_frame_retries
+ *	  Sets the retransmission attempt limit. Called with pib_lock held.
+ *	  Returns either zero, or negative errno.
  */
 struct ieee802154_ops {
 	struct module	*owner;
@@ -152,6 +160,10 @@ struct ieee802154_ops {
 	int		(*set_cca_mode)(struct ieee802154_dev *dev, u8 mode);
 	int		(*set_cca_ed_level)(struct ieee802154_dev *dev,
 					    s32 level);
+	int		(*set_csma_params)(struct ieee802154_dev *dev,
+					   u8 min_be, u8 max_be, u8 retries);
+	int		(*set_frame_retries)(struct ieee802154_dev *dev,
+					     s8 retries);
 };
 
 /* Basic interface to register ieee802154 device */
diff --git a/include/net/wpan-phy.h b/include/net/wpan-phy.h
index 0b570ad..10ab0fc 100644
--- a/include/net/wpan-phy.h
+++ b/include/net/wpan-phy.h
@@ -46,6 +46,10 @@ struct wpan_phy {
 	u32 channels_supported[32];
 	s8 transmit_power;
 	u8 cca_mode;
+	u8 min_be;
+	u8 max_be;
+	u8 csma_retries;
+	s8 frame_retries;
 
 	bool lbt;
 	s32 cca_ed_level;
@@ -61,6 +65,9 @@ struct wpan_phy {
 	int (*set_lbt)(struct wpan_phy *phy, bool on);
 	int (*set_cca_mode)(struct wpan_phy *phy, u8 cca_mode);
 	int (*set_cca_ed_level)(struct wpan_phy *phy, int level);
+	int (*set_csma_params)(struct wpan_phy *phy, u8 min_be, u8 max_be,
+			       u8 retries);
+	int (*set_frame_retries)(struct wpan_phy *phy, s8 retries);
 
 	char priv[0] __attribute__((__aligned__(NETDEV_ALIGN)));
 };
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c
index 23365fa..7331bc6 100644
--- a/net/ieee802154/nl-phy.c
+++ b/net/ieee802154/nl-phy.c
@@ -418,6 +418,49 @@ static int phy_set_cca_ed_level(struct wpan_phy *phy, struct genl_info *info)
 	return 0;
 }
 
+static int phy_set_csma_params(struct wpan_phy *phy, struct genl_info *info)
+{
+	int rc;
+	u8 min_be = phy->min_be;
+	u8 max_be = phy->max_be;
+	u8 retries = phy->csma_retries;
+
+	if (info->attrs[IEEE802154_ATTR_CSMA_RETRIES])
+		retries = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_RETRIES]);
+	if (info->attrs[IEEE802154_ATTR_CSMA_MIN_BE])
+		min_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MIN_BE]);
+	if (info->attrs[IEEE802154_ATTR_CSMA_MAX_BE])
+		max_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MAX_BE]);
+
+	if (retries > 5 || max_be > 8 || min_be > max_be ||
+		retries < -1 || retries > 7)
+		return -EINVAL;
+
+	rc = phy->set_csma_params(phy, min_be, max_be, retries);
+	if (rc < 0)
+		return rc;
+
+	phy->min_be = min_be;
+	phy->max_be = max_be;
+	phy->csma_retries = retries;
+
+	return 0;
+}
+
+static int phy_set_frame_retries(struct wpan_phy *phy, struct genl_info *info)
+{
+	s8 retries = nla_get_s8(info->attrs[IEEE802154_ATTR_FRAME_RETRIES]);
+	int rc;
+
+	rc = phy->set_frame_retries(phy, retries);
+	if (rc < 0)
+		return rc;
+
+	phy->frame_retries = retries;
+
+	return 0;
+}
+
 int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info)
 {
 	struct wpan_phy *phy;
@@ -429,7 +472,11 @@ int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info)
 	if (!info->attrs[IEEE802154_ATTR_PHY_NAME] &&
 		!info->attrs[IEEE802154_ATTR_LBT_ENABLED] &&
 		!info->attrs[IEEE802154_ATTR_CCA_MODE] &&
-		!info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL])
+		!info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL] &&
+		!info->attrs[IEEE802154_ATTR_CSMA_RETRIES] &&
+		!info->attrs[IEEE802154_ATTR_CSMA_MIN_BE] &&
+		!info->attrs[IEEE802154_ATTR_CSMA_MAX_BE] &&
+		!info->attrs[IEEE802154_ATTR_FRAME_RETRIES])
 		return -EINVAL;
 
 	name = nla_data(info->attrs[IEEE802154_ATTR_PHY_NAME]);
@@ -473,6 +520,20 @@ int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info)
 			goto error;
 	}
 
+	if (info->attrs[IEEE802154_ATTR_CSMA_RETRIES] ||
+		info->attrs[IEEE802154_ATTR_CSMA_MIN_BE] ||
+		info->attrs[IEEE802154_ATTR_CSMA_MAX_BE]) {
+		rc = phy_set_csma_params(phy, info);
+		if (rc < 0)
+			goto error;
+	}
+
+	if (info->attrs[IEEE802154_ATTR_FRAME_RETRIES]) {
+		rc = phy_set_frame_retries(phy, info);
+		if (rc < 0)
+			goto error;
+	}
+
 	mutex_unlock(&phy->pib_lock);
 
 	wpan_phy_put(phy);
diff --git a/net/ieee802154/nl_policy.c b/net/ieee802154/nl_policy.c
index 55b5616..fd7be5e 100644
--- a/net/ieee802154/nl_policy.c
+++ b/net/ieee802154/nl_policy.c
@@ -57,5 +57,10 @@ const struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = {
 	[IEEE802154_ATTR_LBT_ENABLED] = { .type = NLA_U8, },
 	[IEEE802154_ATTR_CCA_MODE] = { .type = NLA_U8, },
 	[IEEE802154_ATTR_CCA_ED_LEVEL] = { .type = NLA_S32, },
+	[IEEE802154_ATTR_CSMA_RETRIES] = { .type = NLA_U8, },
+	[IEEE802154_ATTR_CSMA_MIN_BE] = { .type = NLA_U8, },
+	[IEEE802154_ATTR_CSMA_MAX_BE] = { .type = NLA_U8, },
+
+	[IEEE802154_ATTR_FRAME_RETRIES] = { .type = NLA_S8, },
 };
 
diff --git a/net/ieee802154/wpan-class.c b/net/ieee802154/wpan-class.c
index 8d6f670..edd0962 100644
--- a/net/ieee802154/wpan-class.c
+++ b/net/ieee802154/wpan-class.c
@@ -169,6 +169,12 @@ struct wpan_phy *wpan_phy_alloc(size_t priv_size)
 	phy->current_channel = -1; /* not initialised */
 	phy->current_page = 0; /* for compatibility */
 
+	/* defaults per 802.15.4-2011 */
+	phy->min_be = 3;
+	phy->max_be = 5;
+	phy->csma_retries = 4;
+	phy->frame_retries = -1; /* for compatibility, actual default is 3 */
+
 	return phy;
 
 out:
diff --git a/net/mac802154/ieee802154_dev.c b/net/mac802154/ieee802154_dev.c
index 4707f36..b75bb01 100644
--- a/net/mac802154/ieee802154_dev.c
+++ b/net/mac802154/ieee802154_dev.c
@@ -205,6 +205,27 @@ static int mac802154_set_cca_ed_level(struct wpan_phy *phy, s32 level)
 	return priv->ops->set_cca_ed_level(&priv->hw, level);
 }
 
+static int mac802154_set_csma_params(struct wpan_phy *phy, u8 min_be,
+				     u8 max_be, u8 retries)
+{
+	struct mac802154_priv *priv = wpan_phy_priv(phy);
+
+	if (!priv->ops->set_csma_params)
+		return -ENOTSUPP;
+
+	return priv->ops->set_csma_params(&priv->hw, min_be, max_be, retries);
+}
+
+static int mac802154_set_frame_retries(struct wpan_phy *phy, s8 retries)
+{
+	struct mac802154_priv *priv = wpan_phy_priv(phy);
+
+	if (!priv->ops->set_frame_retries)
+		return -ENOTSUPP;
+
+	return priv->ops->set_frame_retries(&priv->hw, retries);
+}
+
 struct ieee802154_dev *
 ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops)
 {
@@ -286,6 +307,8 @@ int ieee802154_register_device(struct ieee802154_dev *dev)
 	priv->phy->set_lbt = mac802154_set_lbt;
 	priv->phy->set_cca_mode = mac802154_set_cca_mode;
 	priv->phy->set_cca_ed_level = mac802154_set_cca_ed_level;
+	priv->phy->set_csma_params = mac802154_set_csma_params;
+	priv->phy->set_frame_retries = mac802154_set_frame_retries;
 
 	rc = wpan_phy_register(priv->phy);
 	if (rc < 0)
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH net-next 08/10] ieee802154: ensure that first RF212 state comes from TRX_OFF
From: Phoebe Buckheister @ 2014-02-12 16:37 UTC (permalink / raw)
  To: netdev; +Cc: linux-zigbee-devel, davem, Phoebe Buckheister
In-Reply-To: <1392223034-19955-1-git-send-email-phoebe.buckheister@itwm.fraunhofer.de>

A documented erratum of the RF212 chip describes that some versions of
RF212 may not be properly reset by the standard reset procedure. The
described workaround seems to not fully work either; my RF212 chips will
not correctly receive any frames unless they are taken from RX mode to
TRX_OFF and back to RX mode, effectively forcing a up-down-up-cycle.
Going to TRX_OFF and to RX without intermediate state changes at least
once fixes this.

The same transition is allowed for RF230, so simply do it all the time.

Signed-off-by: Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
---
 drivers/net/ieee802154/at86rf230.c |   25 +++----------------------
 1 file changed, 3 insertions(+), 22 deletions(-)

diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index 9e3bb34..77b8111 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -930,18 +930,9 @@ static int at86rf230_hw_init(struct at86rf230_local *lp)
 	if (rc)
 		return rc;
 
-	dev_info(&lp->spi->dev, "Status: %02x\n", status);
-	if (status == STATE_P_ON) {
-		rc = at86rf230_write_subreg(lp, SR_TRX_CMD,
-			STATE_FORCE_TRX_OFF);
-		if (rc)
-			return rc;
-		msleep(1);
-		rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &status);
-		if (rc)
-			return rc;
-		dev_info(&lp->spi->dev, "Status: %02x\n", status);
-	}
+	rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_FORCE_TRX_OFF);
+	if (rc)
+		return rc;
 
 	/* configure irq polarity, defaults to high active */
 	if (pdata->irq_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW))
@@ -969,16 +960,6 @@ static int at86rf230_hw_init(struct at86rf230_local *lp)
 	/* Wait the next SLEEP cycle */
 	msleep(100);
 
-	rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_TX_ON);
-	if (rc)
-		return rc;
-	msleep(1);
-
-	rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &status);
-	if (rc)
-		return rc;
-	dev_info(&lp->spi->dev, "Status: %02x\n", status);
-
 	rc = at86rf230_read_subreg(lp, SR_DVDD_OK, &status);
 	if (rc)
 		return rc;
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH net-next 03/10] ieee802154: add TX power control to wpan_phy
From: Phoebe Buckheister @ 2014-02-12 16:37 UTC (permalink / raw)
  To: netdev; +Cc: linux-zigbee-devel, davem, Phoebe Buckheister
In-Reply-To: <1392223034-19955-1-git-send-email-phoebe.buckheister@itwm.fraunhofer.de>

Replace the current u8 transmit_power in wpan_phy with s8 transmit_power.
The u8 field contained the actual tx power and a tolerance field,
which no physical radio every used. Adjust sysfs entries to keep
compatibility with userspace, give tolerances of +-1dB statically there.

This patch only adds support for this in the at86rf230 driver and the
RF212 chip. Configuration calculation for RF212 is also somewhat basic,
but does the job - the RF212 datasheet gives a large table with
suggested values for combinations of TX power and page/channel, if this
does not work well, we might have to copy the whole table.

Signed-off-by: Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
---
 drivers/net/ieee802154/at86rf230.c |   25 ++++++++++++++++++
 include/linux/nl802154.h           |    4 +++
 include/net/mac802154.h            |    5 ++++
 include/net/wpan-phy.h             |    6 +++--
 net/ieee802154/ieee802154.h        |    1 +
 net/ieee802154/netlink.c           |    1 +
 net/ieee802154/nl-phy.c            |   49 +++++++++++++++++++++++++++++++++++-
 net/ieee802154/nl_policy.c         |    2 ++
 net/ieee802154/wpan-class.c        |    4 +--
 net/mac802154/ieee802154_dev.c     |   11 ++++++++
 10 files changed, 102 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index 8cd2d83..99bc822 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -756,6 +756,30 @@ at86rf230_set_hw_addr_filt(struct ieee802154_dev *dev,
 	return 0;
 }
 
+static int
+at86rf212_set_txpower(struct ieee802154_dev *dev, int db)
+{
+	struct at86rf230_local *lp = dev->priv;
+	int rc;
+
+	/* typical maximum output is 5dBm with RG_PHY_TX_PWR 0x60, lower five
+	 * bits decrease power in 1dB steps. 0x60 represents extra PA gain of
+	 * 0dB.
+	 * thus, supported values for db range from -26 to 5, for 31dB of
+	 * reduction to 0dB of reduction.
+	 */
+	if (db > 5 || db < -26)
+		return -EINVAL;
+
+	db = -(db - 5);
+
+	rc = __at86rf230_write(lp, RG_PHY_TX_PWR, 0x60 | db);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
 static struct ieee802154_ops at86rf230_ops = {
 	.owner = THIS_MODULE,
 	.xmit = at86rf230_xmit,
@@ -774,6 +798,7 @@ static struct ieee802154_ops at86rf212_ops = {
 	.start = at86rf230_start,
 	.stop = at86rf230_stop,
 	.set_hw_addr_filt = at86rf230_set_hw_addr_filt,
+	.set_txpower = at86rf212_set_txpower,
 };
 
 static void at86rf230_irqwork(struct work_struct *work)
diff --git a/include/linux/nl802154.h b/include/linux/nl802154.h
index fd4f2d1..625d19e 100644
--- a/include/linux/nl802154.h
+++ b/include/linux/nl802154.h
@@ -70,6 +70,8 @@ enum {
 	IEEE802154_ATTR_PHY_NAME,
 	IEEE802154_ATTR_DEV_TYPE,
 
+	IEEE802154_ATTR_TXPOWER,
+
 	__IEEE802154_ATTR_MAX,
 };
 
@@ -122,6 +124,8 @@ enum {
 	IEEE802154_ADD_IFACE,
 	IEEE802154_DEL_IFACE,
 
+	IEEE802154_SET_PHYPARAMS,
+
 	__IEEE802154_CMD_MAX,
 };
 
diff --git a/include/net/mac802154.h b/include/net/mac802154.h
index 807d6b7..8bd2785 100644
--- a/include/net/mac802154.h
+++ b/include/net/mac802154.h
@@ -113,6 +113,10 @@ struct ieee802154_dev {
  *	  Set radio for listening on specific address.
  *	  Set the device for listening on specified address.
  *	  Returns either zero, or negative errno.
+ *
+ * set_txpower:
+ *	  Set radio transmit power in dB. Called with pib_lock held.
+ *	  Returns either zero, or negative errno.
  */
 struct ieee802154_ops {
 	struct module	*owner;
@@ -129,6 +133,7 @@ struct ieee802154_ops {
 					    unsigned long changed);
 	int		(*ieee_addr)(struct ieee802154_dev *dev,
 				     u8 addr[IEEE802154_ADDR_LEN]);
+	int		(*set_txpower)(struct ieee802154_dev *dev, int db);
 };
 
 /* Basic interface to register ieee802154 device */
diff --git a/include/net/wpan-phy.h b/include/net/wpan-phy.h
index b52bda8..47fc0c1 100644
--- a/include/net/wpan-phy.h
+++ b/include/net/wpan-phy.h
@@ -37,14 +37,14 @@ struct wpan_phy {
 	struct mutex pib_lock;
 
 	/*
-	 * This is a PIB according to 802.15.4-2006.
+	 * This is a PIB according to 802.15.4-2011.
 	 * We do not provide timing-related variables, as they
 	 * aren't used outside of driver
 	 */
 	u8 current_channel;
 	u8 current_page;
 	u32 channels_supported[32];
-	u8 transmit_power;
+	s8 transmit_power;
 	u8 cca_mode;
 
 	struct device dev;
@@ -54,6 +54,8 @@ struct wpan_phy {
 					const char *name, int type);
 	void (*del_iface)(struct wpan_phy *phy, struct net_device *dev);
 
+	int (*set_txpower)(struct wpan_phy *phy, int db);
+
 	char priv[0] __attribute__((__aligned__(NETDEV_ALIGN)));
 };
 
diff --git a/net/ieee802154/ieee802154.h b/net/ieee802154/ieee802154.h
index cee4425..6cbc896 100644
--- a/net/ieee802154/ieee802154.h
+++ b/net/ieee802154/ieee802154.h
@@ -53,6 +53,7 @@ int ieee802154_list_phy(struct sk_buff *skb, struct genl_info *info);
 int ieee802154_dump_phy(struct sk_buff *skb, struct netlink_callback *cb);
 int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info);
 int ieee802154_del_iface(struct sk_buff *skb, struct genl_info *info);
+int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info);
 
 enum ieee802154_mcgrp_ids {
 	IEEE802154_COORD_MCGRP,
diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c
index 43f1b2b..67c151b 100644
--- a/net/ieee802154/netlink.c
+++ b/net/ieee802154/netlink.c
@@ -115,6 +115,7 @@ static const struct genl_ops ieee8021154_ops[] = {
 			ieee802154_dump_phy),
 	IEEE802154_OP(IEEE802154_ADD_IFACE, ieee802154_add_iface),
 	IEEE802154_OP(IEEE802154_DEL_IFACE, ieee802154_del_iface),
+	IEEE802154_OP(IEEE802154_SET_PHYPARAMS, ieee802154_set_phyparams),
 	/* see nl-mac.c */
 	IEEE802154_OP(IEEE802154_ASSOCIATE_REQ, ieee802154_associate_req),
 	IEEE802154_OP(IEEE802154_ASSOCIATE_RESP, ieee802154_associate_resp),
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c
index 89b265a..d3ee62f 100644
--- a/net/ieee802154/nl-phy.c
+++ b/net/ieee802154/nl-phy.c
@@ -55,7 +55,8 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid,
 	mutex_lock(&phy->pib_lock);
 	if (nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) ||
 	    nla_put_u8(msg, IEEE802154_ATTR_PAGE, phy->current_page) ||
-	    nla_put_u8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel))
+	    nla_put_u8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel) ||
+	    nla_put_s8(msg, IEEE802154_ATTR_TXPOWER, phy->transmit_power))
 		goto nla_put_failure;
 	for (i = 0; i < 32; i++) {
 		if (phy->channels_supported[i])
@@ -354,3 +355,49 @@ out_dev:
 
 	return rc;
 }
+
+int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info)
+{
+	struct wpan_phy *phy;
+	const char *name;
+	int txpower;
+	int rc = -EINVAL;
+
+	pr_debug("%s\n", __func__);
+
+	if (!info->attrs[IEEE802154_ATTR_PHY_NAME])
+		return -EINVAL;
+
+	name = nla_data(info->attrs[IEEE802154_ATTR_PHY_NAME]);
+	if (name[nla_len(info->attrs[IEEE802154_ATTR_PHY_NAME]) - 1] != '\0')
+		return -EINVAL; /* phy name should be null-terminated */
+
+	txpower = nla_get_s8(info->attrs[IEEE802154_ATTR_TXPOWER]);
+
+	phy = wpan_phy_find(name);
+	if (!phy)
+		return -ENODEV;
+
+	if (!phy->set_txpower)
+		goto out;
+
+	mutex_lock(&phy->pib_lock);
+
+	rc = phy->set_txpower(phy, txpower);
+	if (rc < 0) {
+		mutex_unlock(&phy->pib_lock);
+		goto out;
+	}
+
+	phy->transmit_power = txpower;
+
+	mutex_unlock(&phy->pib_lock);
+
+	wpan_phy_put(phy);
+
+	return 0;
+
+out:
+	wpan_phy_put(phy);
+	return rc;
+}
diff --git a/net/ieee802154/nl_policy.c b/net/ieee802154/nl_policy.c
index 6adda4d..90b1d0d 100644
--- a/net/ieee802154/nl_policy.c
+++ b/net/ieee802154/nl_policy.c
@@ -52,5 +52,7 @@ const struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = {
 	[IEEE802154_ATTR_DURATION] = { .type = NLA_U8, },
 	[IEEE802154_ATTR_ED_LIST] = { .len = 27 },
 	[IEEE802154_ATTR_CHANNEL_PAGE_LIST] = { .len = 32 * 4, },
+
+	[IEEE802154_ATTR_TXPOWER] = { .type = NLA_S8, },
 };
 
diff --git a/net/ieee802154/wpan-class.c b/net/ieee802154/wpan-class.c
index 4dd3761..8d6f670 100644
--- a/net/ieee802154/wpan-class.c
+++ b/net/ieee802154/wpan-class.c
@@ -44,9 +44,7 @@ static DEVICE_ATTR_RO(name);
 
 MASTER_SHOW(current_channel, "%d");
 MASTER_SHOW(current_page, "%d");
-MASTER_SHOW_COMPLEX(transmit_power, "%d +- %d dB",
-	((signed char) (phy->transmit_power << 2)) >> 2,
-	(phy->transmit_power >> 6) ? (phy->transmit_power >> 6) * 3 : 1);
+MASTER_SHOW(transmit_power, "%d +- 1 dB");
 MASTER_SHOW(cca_mode, "%d");
 
 static ssize_t channels_supported_show(struct device *dev,
diff --git a/net/mac802154/ieee802154_dev.c b/net/mac802154/ieee802154_dev.c
index 52ae664..9eb49e0 100644
--- a/net/mac802154/ieee802154_dev.c
+++ b/net/mac802154/ieee802154_dev.c
@@ -165,6 +165,16 @@ err:
 	return ERR_PTR(err);
 }
 
+static int mac802154_set_txpower(struct wpan_phy *phy, int db)
+{
+	struct mac802154_priv *priv = wpan_phy_priv(phy);
+
+	if (!priv->ops->set_txpower)
+		return -ENOTSUPP;
+
+	return priv->ops->set_txpower(&priv->hw, db);
+}
+
 struct ieee802154_dev *
 ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops)
 {
@@ -242,6 +252,7 @@ int ieee802154_register_device(struct ieee802154_dev *dev)
 
 	priv->phy->add_iface = mac802154_add_iface;
 	priv->phy->del_iface = mac802154_del_iface;
+	priv->phy->set_txpower = mac802154_set_txpower;
 
 	rc = wpan_phy_register(priv->phy);
 	if (rc < 0)
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH net-next 01/10] ieee802154: add basic support for RF212 to at86rf230 driver
From: Phoebe Buckheister @ 2014-02-12 16:37 UTC (permalink / raw)
  To: netdev; +Cc: linux-zigbee-devel, davem, Phoebe Buckheister
In-Reply-To: <1392223034-19955-1-git-send-email-phoebe.buckheister@itwm.fraunhofer.de>

Since the AT86RF2xy chips are mostly compatible, this is only a small
change to the actual driver code. The at86rf230 driver already supports the
RF212 in most places, only three small adjustments are required:

 * force the initial state after P_ON to FORCE_TRX_OFF to work around a
   documented erratum
 * channels_supported depends on the frequency of the transceiver, and
   thus is_rf212
 * do early detection of chip version select an appropriate _ops struct
   based on the chip version.

Signed-off-by: Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
---
 drivers/net/ieee802154/at86rf230.c |  271 ++++++++++++++++++++++++------------
 1 file changed, 182 insertions(+), 89 deletions(-)

diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index ab31544..93123ae 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -37,7 +37,6 @@
 
 struct at86rf230_local {
 	struct spi_device *spi;
-	int rstn, slp_tr, dig2;
 
 	u8 part;
 	u8 vers;
@@ -55,6 +54,11 @@ struct at86rf230_local {
 	bool is_tx;
 };
 
+static inline int is_rf212(struct at86rf230_local *local)
+{
+	return local->part == 7;
+}
+
 #define	RG_TRX_STATUS	(0x01)
 #define	SR_TRX_STATUS		0x01, 0x1f, 0
 #define	SR_RESERVED_01_3	0x01, 0x20, 5
@@ -100,7 +104,9 @@ struct at86rf230_local {
 #define	SR_SFD_VALUE		0x0b, 0xff, 0
 #define	RG_TRX_CTRL_2	(0x0c)
 #define	SR_OQPSK_DATA_RATE	0x0c, 0x03, 0
-#define	SR_RESERVED_0c_2	0x0c, 0x7c, 2
+#define	SR_SUB_MODE		0x0c, 0x04, 2
+#define	SR_BPSK_QPSK		0x0c, 0x08, 3
+#define	SR_RESERVED_0c_4	0x0c, 0x70, 4
 #define	SR_RX_SAFE_MODE		0x0c, 0x80, 7
 #define	RG_ANT_DIV	(0x0d)
 #define	SR_ANT_CTRL		0x0d, 0x03, 0
@@ -244,6 +250,57 @@ struct at86rf230_local {
 #define STATE_TRANSITION_IN_PROGRESS 0x1F
 
 static int
+__at86rf230_detect_device(struct spi_device *spi, u16 *man_id, u8 *part,
+		u8 *version)
+{
+	u8 data[4];
+	u8 *buf = kmalloc(2, GFP_KERNEL);
+	int status;
+	struct spi_message msg;
+	struct spi_transfer xfer = {
+		.len	= 2,
+		.tx_buf	= buf,
+		.rx_buf	= buf,
+	};
+	u8 reg;
+
+	if (!buf)
+		return -ENOMEM;
+
+	for (reg = RG_PART_NUM; reg <= RG_MAN_ID_1; reg++) {
+		buf[0] = (reg & CMD_REG_MASK) | CMD_REG;
+		buf[1] = 0xff;
+		dev_vdbg(&spi->dev, "buf[0] = %02x\n", buf[0]);
+		spi_message_init(&msg);
+		spi_message_add_tail(&xfer, &msg);
+
+		status = spi_sync(spi, &msg);
+		dev_vdbg(&spi->dev, "status = %d\n", status);
+		if (msg.status)
+			status = msg.status;
+
+		dev_vdbg(&spi->dev, "status = %d\n", status);
+		dev_vdbg(&spi->dev, "buf[0] = %02x\n", buf[0]);
+		dev_vdbg(&spi->dev, "buf[1] = %02x\n", buf[1]);
+
+		if (status == 0)
+			data[reg - RG_PART_NUM] = buf[1];
+		else
+			break;
+	}
+
+	if (status == 0) {
+		*part = data[0];
+		*version = data[1];
+		*man_id = (data[3] << 8) | data[2];
+	}
+
+	kfree(buf);
+
+	return status;
+}
+
+static int
 __at86rf230_write(struct at86rf230_local *lp, u8 addr, u8 data)
 {
 	u8 *buf = lp->buf;
@@ -520,6 +577,28 @@ at86rf230_stop(struct ieee802154_dev *dev)
 }
 
 static int
+at86rf230_set_channel(struct at86rf230_local *lp, int page, int channel)
+{
+	return at86rf230_write_subreg(lp, SR_CHANNEL, channel);
+}
+
+static int
+at86rf212_set_channel(struct at86rf230_local *lp, int page, int channel)
+{
+	int rc;
+
+	if (channel == 0)
+		rc = at86rf230_write_subreg(lp, SR_SUB_MODE, 0);
+	else
+		rc = at86rf230_write_subreg(lp, SR_SUB_MODE, 1);
+
+	if (rc < 0)
+		return rc;
+
+	return at86rf230_write_subreg(lp, SR_CHANNEL, channel);
+}
+
+static int
 at86rf230_channel(struct ieee802154_dev *dev, int page, int channel)
 {
 	struct at86rf230_local *lp = dev->priv;
@@ -527,12 +606,21 @@ at86rf230_channel(struct ieee802154_dev *dev, int page, int channel)
 
 	might_sleep();
 
-	if (page != 0 || channel < 11 || channel > 26) {
+	if (page < 0
+		|| page > 31
+		|| !(lp->dev->phy->channels_supported[page] & BIT(channel))) {
 		WARN_ON(1);
 		return -EINVAL;
 	}
 
-	rc = at86rf230_write_subreg(lp, SR_CHANNEL, channel);
+	if (is_rf212(lp))
+		rc = at86rf212_set_channel(lp, page, channel);
+	else
+		rc = at86rf230_set_channel(lp, page, channel);
+
+	if (rc < 0)
+		return rc;
+
 	msleep(1); /* Wait for PLL */
 	dev->phy->current_channel = channel;
 
@@ -678,6 +766,16 @@ static struct ieee802154_ops at86rf230_ops = {
 	.set_hw_addr_filt = at86rf230_set_hw_addr_filt,
 };
 
+static struct ieee802154_ops at86rf212_ops = {
+	.owner = THIS_MODULE,
+	.xmit = at86rf230_xmit,
+	.ed = at86rf230_ed,
+	.set_channel = at86rf230_channel,
+	.start = at86rf230_start,
+	.stop = at86rf230_stop,
+	.set_hw_addr_filt = at86rf230_set_hw_addr_filt,
+};
+
 static void at86rf230_irqwork(struct work_struct *work)
 {
 	struct at86rf230_local *lp =
@@ -759,7 +857,8 @@ static int at86rf230_hw_init(struct at86rf230_local *lp)
 
 	dev_info(&lp->spi->dev, "Status: %02x\n", status);
 	if (status == STATE_P_ON) {
-		rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_TRX_OFF);
+		rc = at86rf230_write_subreg(lp, SR_TRX_CMD,
+			STATE_FORCE_TRX_OFF);
 		if (rc)
 			return rc;
 		msleep(1);
@@ -824,26 +923,18 @@ static int at86rf230_hw_init(struct at86rf230_local *lp)
 	return 0;
 }
 
-static void at86rf230_fill_data(struct spi_device *spi)
-{
-	struct at86rf230_local *lp = spi_get_drvdata(spi);
-	struct at86rf230_platform_data *pdata = spi->dev.platform_data;
-
-	lp->rstn = pdata->rstn;
-	lp->slp_tr = pdata->slp_tr;
-	lp->dig2 = pdata->dig2;
-}
-
 static int at86rf230_probe(struct spi_device *spi)
 {
 	struct at86rf230_platform_data *pdata;
 	struct ieee802154_dev *dev;
 	struct at86rf230_local *lp;
-	u8 man_id_0, man_id_1, status;
+	u16 man_id = 0;
+	u8 part = 0, version = 0, status;
 	irq_handler_t irq_handler;
 	work_func_t irq_worker;
-	int rc, supported = 0;
+	int rc;
 	const char *chip;
+	struct ieee802154_ops *ops = NULL;
 
 	if (!spi->irq) {
 		dev_err(&spi->dev, "no IRQ specified\n");
@@ -856,116 +947,115 @@ static int at86rf230_probe(struct spi_device *spi)
 		return -EINVAL;
 	}
 
-	dev = ieee802154_alloc_device(sizeof(*lp), &at86rf230_ops);
-	if (!dev)
-		return -ENOMEM;
-
-	lp = dev->priv;
-	lp->dev = dev;
-
-	lp->spi = spi;
-
-	dev->parent = &spi->dev;
-	dev->extra_tx_headroom = 0;
-	/* We do support only 2.4 Ghz */
-	dev->phy->channels_supported[0] = 0x7FFF800;
-	dev->flags = IEEE802154_HW_OMIT_CKSUM;
-
-	if (pdata->irq_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
-		irq_worker = at86rf230_irqwork;
-		irq_handler = at86rf230_isr;
-	} else {
-		irq_worker = at86rf230_irqwork_level;
-		irq_handler = at86rf230_isr_level;
-	}
-
-	mutex_init(&lp->bmux);
-	INIT_WORK(&lp->irqwork, irq_worker);
-	spin_lock_init(&lp->lock);
-	init_completion(&lp->tx_complete);
-
-	spi_set_drvdata(spi, lp);
-
-	at86rf230_fill_data(spi);
-
-	rc = gpio_request(lp->rstn, "rstn");
+	rc = gpio_request(pdata->rstn, "rstn");
 	if (rc)
-		goto err_rstn;
+		return rc;
 
-	if (gpio_is_valid(lp->slp_tr)) {
-		rc = gpio_request(lp->slp_tr, "slp_tr");
+	if (gpio_is_valid(pdata->slp_tr)) {
+		rc = gpio_request(pdata->slp_tr, "slp_tr");
 		if (rc)
 			goto err_slp_tr;
 	}
 
-	rc = gpio_direction_output(lp->rstn, 1);
+	rc = gpio_direction_output(pdata->rstn, 1);
 	if (rc)
 		goto err_gpio_dir;
 
-	if (gpio_is_valid(lp->slp_tr)) {
-		rc = gpio_direction_output(lp->slp_tr, 0);
+	if (gpio_is_valid(pdata->slp_tr)) {
+		rc = gpio_direction_output(pdata->slp_tr, 0);
 		if (rc)
 			goto err_gpio_dir;
 	}
 
 	/* Reset */
 	msleep(1);
-	gpio_set_value(lp->rstn, 0);
+	gpio_set_value(pdata->rstn, 0);
 	msleep(1);
-	gpio_set_value(lp->rstn, 1);
+	gpio_set_value(pdata->rstn, 1);
 	msleep(1);
 
-	rc = at86rf230_read_subreg(lp, SR_MAN_ID_0, &man_id_0);
-	if (rc)
-		goto err_gpio_dir;
-	rc = at86rf230_read_subreg(lp, SR_MAN_ID_1, &man_id_1);
-	if (rc)
+	rc = __at86rf230_detect_device(spi, &man_id, &part, &version);
+	if (rc < 0)
 		goto err_gpio_dir;
 
-	if (man_id_1 != 0x00 || man_id_0 != 0x1f) {
+	if (man_id != 0x001f) {
 		dev_err(&spi->dev, "Non-Atmel dev found (MAN_ID %02x %02x)\n",
-			man_id_1, man_id_0);
+			man_id >> 8, man_id & 0xFF);
 		rc = -EINVAL;
 		goto err_gpio_dir;
 	}
 
-	rc = at86rf230_read_subreg(lp, SR_PART_NUM, &lp->part);
-	if (rc)
-		goto err_gpio_dir;
-
-	rc = at86rf230_read_subreg(lp, SR_VERSION_NUM, &lp->vers);
-	if (rc)
-		goto err_gpio_dir;
-
-	switch (lp->part) {
+	switch (part) {
 	case 2:
 		chip = "at86rf230";
-		/* supported = 1;  FIXME: should be easy to support; */
+		/* FIXME: should be easy to support; */
 		break;
 	case 3:
 		chip = "at86rf231";
-		supported = 1;
+		ops = &at86rf230_ops;
+		break;
+	case 7:
+		chip = "at86rf212";
+		if (version == 1)
+			ops = &at86rf212_ops;
 		break;
 	default:
 		chip = "UNKNOWN";
 		break;
 	}
 
-	dev_info(&spi->dev, "Detected %s chip version %d\n", chip, lp->vers);
-	if (!supported) {
+	dev_info(&spi->dev, "Detected %s chip version %d\n", chip, version);
+	if (!ops) {
 		rc = -ENOTSUPP;
 		goto err_gpio_dir;
 	}
 
+	dev = ieee802154_alloc_device(sizeof(*lp), ops);
+	if (!dev) {
+		rc = -ENOMEM;
+		goto err_gpio_dir;
+	}
+
+	lp = dev->priv;
+	lp->dev = dev;
+	lp->part = part;
+	lp->vers = version;
+
+	lp->spi = spi;
+
+	dev->parent = &spi->dev;
+	dev->extra_tx_headroom = 0;
+	dev->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK;
+
+	if (pdata->irq_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
+		irq_worker = at86rf230_irqwork;
+		irq_handler = at86rf230_isr;
+	} else {
+		irq_worker = at86rf230_irqwork_level;
+		irq_handler = at86rf230_isr_level;
+	}
+
+	mutex_init(&lp->bmux);
+	INIT_WORK(&lp->irqwork, irq_worker);
+	spin_lock_init(&lp->lock);
+	init_completion(&lp->tx_complete);
+
+	spi_set_drvdata(spi, lp);
+
+	if (is_rf212(lp))
+		dev->phy->channels_supported[0] = 0x00007FF;
+	else
+		dev->phy->channels_supported[0] = 0x7FFF800;
+
 	rc = at86rf230_hw_init(lp);
 	if (rc)
-		goto err_gpio_dir;
+		goto err_hw_init;
 
 	rc = request_irq(spi->irq, irq_handler,
 			 IRQF_SHARED | pdata->irq_type,
 			 dev_name(&spi->dev), lp);
 	if (rc)
-		goto err_gpio_dir;
+		goto err_hw_init;
 
 	/* Read irq status register to reset irq line */
 	rc = at86rf230_read_subreg(lp, RG_IRQ_STATUS, 0xff, 0, &status);
@@ -980,30 +1070,33 @@ static int at86rf230_probe(struct spi_device *spi)
 
 err_irq:
 	free_irq(spi->irq, lp);
+err_hw_init:
 	flush_work(&lp->irqwork);
-err_gpio_dir:
-	if (gpio_is_valid(lp->slp_tr))
-		gpio_free(lp->slp_tr);
-err_slp_tr:
-	gpio_free(lp->rstn);
-err_rstn:
+	spi_set_drvdata(spi, NULL);
 	mutex_destroy(&lp->bmux);
 	ieee802154_free_device(lp->dev);
+
+err_gpio_dir:
+	if (gpio_is_valid(pdata->slp_tr))
+		gpio_free(pdata->slp_tr);
+err_slp_tr:
+	gpio_free(pdata->rstn);
 	return rc;
 }
 
 static int at86rf230_remove(struct spi_device *spi)
 {
 	struct at86rf230_local *lp = spi_get_drvdata(spi);
+	struct at86rf230_platform_data *pdata = spi->dev.platform_data;
 
 	ieee802154_unregister_device(lp->dev);
 
 	free_irq(spi->irq, lp);
 	flush_work(&lp->irqwork);
 
-	if (gpio_is_valid(lp->slp_tr))
-		gpio_free(lp->slp_tr);
-	gpio_free(lp->rstn);
+	if (gpio_is_valid(pdata->slp_tr))
+		gpio_free(pdata->slp_tr);
+	gpio_free(pdata->rstn);
 
 	mutex_destroy(&lp->bmux);
 	ieee802154_free_device(lp->dev);
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH net-next 0/10] ieee802154: support rf212 and extended mac features
From: Phoebe Buckheister @ 2014-02-12 16:37 UTC (permalink / raw)
  To: netdev; +Cc: linux-zigbee-devel, davem

Hi,

this patch set adds support for the RF212 radio chip to the existing at86rf230
driver and adds support for numerous features of the RF212 chips to the
ieee802154 stack. These features include CSMA parameter configuration, transmit
power control, CCA parameter configuration, and automatic retransmission of
frames. Netlink APIs are provided for all new options introduced in this set.

Many features might also work for RF230, but since I have no such chips at my
disposal, most new features are implemented only for RF212.

^ permalink raw reply

* [PATCH net-next 07/10] ieee802154: add support for setting CCA energy detection levels
From: Phoebe Buckheister @ 2014-02-12 16:37 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	linux-zigbee-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <1392223034-19955-1-git-send-email-phoebe.buckheister-mPn0NPGs4xGatNDF+KUbs4QuADTiUCJX@public.gmane.org>

Since three of the four clear channel assesment modes make use of energy
detection, provide an API to set the energy detection threshold.
Driver support for this is available in at86rf230 for the RF212 chips.
Since for these chips the minimal energy detection threshold depends on
page and channel used, add a field to struct at86rf230_local that stores
the minimal threshold. Actual ED thresholds are configured as offsets
from this value.

For RF212, setting the ED threshold will not work before a channel/page
has been set due to the dependency of energy detection in the chip and
the actual channel/page selected.

Signed-off-by: Phoebe Buckheister <phoebe.buckheister-mPn0NPGs4xGatNDF+KUbs4QuADTiUCJX@public.gmane.org>
---
 drivers/net/ieee802154/at86rf230.c |   26 ++++++++++++++++++++++++--
 include/linux/nl802154.h           |    1 +
 include/net/mac802154.h            |    7 +++++++
 include/net/wpan-phy.h             |    2 ++
 net/ieee802154/nl-phy.c            |   30 +++++++++++++++++++++++++++---
 net/ieee802154/nl_policy.c         |    1 +
 net/mac802154/ieee802154_dev.c     |   11 +++++++++++
 7 files changed, 73 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index fb5e55a..9e3bb34 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -52,6 +52,8 @@ struct at86rf230_local {
 	spinlock_t lock;
 	bool irq_busy;
 	bool is_tx;
+
+	int rssi_base_val;
 };
 
 static inline int is_rf212(struct at86rf230_local *local)
@@ -580,6 +582,8 @@ at86rf230_stop(struct ieee802154_dev *dev)
 static int
 at86rf230_set_channel(struct at86rf230_local *lp, int page, int channel)
 {
+	lp->rssi_base_val = -91;
+
 	return at86rf230_write_subreg(lp, SR_CHANNEL, channel);
 }
 
@@ -596,10 +600,13 @@ at86rf212_set_channel(struct at86rf230_local *lp, int page, int channel)
 	if (rc < 0)
 		return rc;
 
-	if (page == 0)
+	if (page == 0) {
 		rc = at86rf230_write_subreg(lp, SR_BPSK_QPSK, 0);
-	else
+		lp->rssi_base_val = -100;
+	} else {
 		rc = at86rf230_write_subreg(lp, SR_BPSK_QPSK, 1);
+		lp->rssi_base_val = -98;
+	}
 
 	if (rc < 0)
 		return rc;
@@ -806,6 +813,20 @@ at86rf212_set_cca_mode(struct ieee802154_dev *dev, u8 mode)
 	return at86rf230_write_subreg(lp, SR_CCA_MODE, mode);
 }
 
+static int
+at86rf212_set_cca_ed_level(struct ieee802154_dev *dev, s32 level)
+{
+	struct at86rf230_local *lp = dev->priv;
+	int desens_steps;
+
+	if (level < lp->rssi_base_val || level > 30)
+		return -EINVAL;
+
+	desens_steps = (level - lp->rssi_base_val) * 100 / 207;
+
+	return at86rf230_write_subreg(lp, SR_CCA_ED_THRES, desens_steps);
+}
+
 static struct ieee802154_ops at86rf230_ops = {
 	.owner = THIS_MODULE,
 	.xmit = at86rf230_xmit,
@@ -827,6 +848,7 @@ static struct ieee802154_ops at86rf212_ops = {
 	.set_txpower = at86rf212_set_txpower,
 	.set_lbt = at86rf212_set_lbt,
 	.set_cca_mode = at86rf212_set_cca_mode,
+	.set_cca_ed_level = at86rf212_set_cca_ed_level,
 };
 
 static void at86rf230_irqwork(struct work_struct *work)
diff --git a/include/linux/nl802154.h b/include/linux/nl802154.h
index 5edefc1..0594a0a 100644
--- a/include/linux/nl802154.h
+++ b/include/linux/nl802154.h
@@ -73,6 +73,7 @@ enum {
 	IEEE802154_ATTR_TXPOWER,
 	IEEE802154_ATTR_LBT_ENABLED,
 	IEEE802154_ATTR_CCA_MODE,
+	IEEE802154_ATTR_CCA_ED_LEVEL,
 
 	__IEEE802154_ATTR_MAX,
 };
diff --git a/include/net/mac802154.h b/include/net/mac802154.h
index 1a98e50..15fe6bc 100644
--- a/include/net/mac802154.h
+++ b/include/net/mac802154.h
@@ -126,6 +126,11 @@ struct ieee802154_dev {
  * set_cca_mode
  *	  Sets the CCA mode used by the device. Called with pib_lock held.
  *	  Returns either zero, or negative errno.
+ *
+ * set_cca_ed_level
+ *	  Sets the CCA energy detection threshold in dBm. Called with pib_lock
+ *	  held.
+ *	  Returns either zero, or negative errno.
  */
 struct ieee802154_ops {
 	struct module	*owner;
@@ -145,6 +150,8 @@ struct ieee802154_ops {
 	int		(*set_txpower)(struct ieee802154_dev *dev, int db);
 	int		(*set_lbt)(struct ieee802154_dev *dev, bool on);
 	int		(*set_cca_mode)(struct ieee802154_dev *dev, u8 mode);
+	int		(*set_cca_ed_level)(struct ieee802154_dev *dev,
+					    s32 level);
 };
 
 /* Basic interface to register ieee802154 device */
diff --git a/include/net/wpan-phy.h b/include/net/wpan-phy.h
index 03b5905..0b570ad 100644
--- a/include/net/wpan-phy.h
+++ b/include/net/wpan-phy.h
@@ -48,6 +48,7 @@ struct wpan_phy {
 	u8 cca_mode;
 
 	bool lbt;
+	s32 cca_ed_level;
 
 	struct device dev;
 	int idx;
@@ -59,6 +60,7 @@ struct wpan_phy {
 	int (*set_txpower)(struct wpan_phy *phy, int db);
 	int (*set_lbt)(struct wpan_phy *phy, bool on);
 	int (*set_cca_mode)(struct wpan_phy *phy, u8 cca_mode);
+	int (*set_cca_ed_level)(struct wpan_phy *phy, int level);
 
 	char priv[0] __attribute__((__aligned__(NETDEV_ALIGN)));
 };
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c
index 026b21a..23365fa 100644
--- a/net/ieee802154/nl-phy.c
+++ b/net/ieee802154/nl-phy.c
@@ -58,7 +58,8 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid,
 	    nla_put_u8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel) ||
 	    nla_put_s8(msg, IEEE802154_ATTR_TXPOWER, phy->transmit_power) ||
 	    nla_put_u8(msg, IEEE802154_ATTR_LBT_ENABLED, phy->lbt) ||
-	    nla_put_u8(msg, IEEE802154_ATTR_CCA_MODE, phy->cca_mode))
+	    nla_put_u8(msg, IEEE802154_ATTR_CCA_MODE, phy->cca_mode) ||
+	    nla_put_s32(msg, IEEE802154_ATTR_CCA_ED_LEVEL, phy->cca_ed_level))
 		goto nla_put_failure;
 	for (i = 0; i < 32; i++) {
 		if (phy->channels_supported[i])
@@ -403,6 +404,20 @@ static int phy_set_cca_mode(struct wpan_phy *phy, struct genl_info *info)
 	return 0;
 }
 
+static int phy_set_cca_ed_level(struct wpan_phy *phy, struct genl_info *info)
+{
+	s32 level = nla_get_s32(info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]);
+	int rc;
+
+	rc = phy->set_cca_ed_level(phy, level);
+	if (rc < 0)
+		return rc;
+
+	phy->cca_ed_level = level;
+
+	return 0;
+}
+
 int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info)
 {
 	struct wpan_phy *phy;
@@ -413,7 +428,8 @@ int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info)
 
 	if (!info->attrs[IEEE802154_ATTR_PHY_NAME] &&
 		!info->attrs[IEEE802154_ATTR_LBT_ENABLED] &&
-		!info->attrs[IEEE802154_ATTR_CCA_MODE])
+		!info->attrs[IEEE802154_ATTR_CCA_MODE] &&
+		!info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL])
 		return -EINVAL;
 
 	name = nla_data(info->attrs[IEEE802154_ATTR_PHY_NAME]);
@@ -426,7 +442,9 @@ int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info)
 
 	if ((!phy->set_txpower && info->attrs[IEEE802154_ATTR_TXPOWER]) ||
 		(!phy->set_lbt && info->attrs[IEEE802154_ATTR_LBT_ENABLED]) ||
-		(!phy->set_cca_mode && info->attrs[IEEE802154_ATTR_CCA_MODE]))
+		(!phy->set_cca_mode && info->attrs[IEEE802154_ATTR_CCA_MODE]) ||
+		(!phy->set_cca_ed_level &&
+			info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]))
 		goto out;
 
 	mutex_lock(&phy->pib_lock);
@@ -449,6 +467,12 @@ int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info)
 			goto error;
 	}
 
+	if (info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]) {
+		rc = phy_set_cca_ed_level(phy, info);
+		if (rc < 0)
+			goto error;
+	}
+
 	mutex_unlock(&phy->pib_lock);
 
 	wpan_phy_put(phy);
diff --git a/net/ieee802154/nl_policy.c b/net/ieee802154/nl_policy.c
index d87c2c9..55b5616 100644
--- a/net/ieee802154/nl_policy.c
+++ b/net/ieee802154/nl_policy.c
@@ -56,5 +56,6 @@ const struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = {
 	[IEEE802154_ATTR_TXPOWER] = { .type = NLA_S8, },
 	[IEEE802154_ATTR_LBT_ENABLED] = { .type = NLA_U8, },
 	[IEEE802154_ATTR_CCA_MODE] = { .type = NLA_U8, },
+	[IEEE802154_ATTR_CCA_ED_LEVEL] = { .type = NLA_S32, },
 };
 
diff --git a/net/mac802154/ieee802154_dev.c b/net/mac802154/ieee802154_dev.c
index 4965e4c..4707f36 100644
--- a/net/mac802154/ieee802154_dev.c
+++ b/net/mac802154/ieee802154_dev.c
@@ -195,6 +195,16 @@ static int mac802154_set_cca_mode(struct wpan_phy *phy, u8 mode)
 	return priv->ops->set_cca_mode(&priv->hw, mode);
 }
 
+static int mac802154_set_cca_ed_level(struct wpan_phy *phy, s32 level)
+{
+	struct mac802154_priv *priv = wpan_phy_priv(phy);
+
+	if (!priv->ops->set_cca_ed_level)
+		return -ENOTSUPP;
+
+	return priv->ops->set_cca_ed_level(&priv->hw, level);
+}
+
 struct ieee802154_dev *
 ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops)
 {
@@ -275,6 +285,7 @@ int ieee802154_register_device(struct ieee802154_dev *dev)
 	priv->phy->set_txpower = mac802154_set_txpower;
 	priv->phy->set_lbt = mac802154_set_lbt;
 	priv->phy->set_cca_mode = mac802154_set_cca_mode;
+	priv->phy->set_cca_ed_level = mac802154_set_cca_ed_level;
 
 	rc = wpan_phy_register(priv->phy);
 	if (rc < 0)
-- 
1.7.9.5


------------------------------------------------------------------------------
Android apps run on BlackBerry 10
Introducing the new BlackBerry 10.2.1 Runtime for Android apps.
Now with support for Jelly Bean, Bluetooth, Mapview and more.
Get your Android app in front of a whole new audience.  Start now.
http://pubads.g.doubleclick.net/gampad/clk?id=124407151&iu=/4140/ostg.clktrk

^ permalink raw reply related

* [PATCH net-next 06/10] ieee802154: add support for CCA mode in wpan phys
From: Phoebe Buckheister @ 2014-02-12 16:37 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	linux-zigbee-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <1392223034-19955-1-git-send-email-phoebe.buckheister-mPn0NPGs4xGatNDF+KUbs4QuADTiUCJX@public.gmane.org>

The standard describes four modes of clear channel assesment: "energy
above threshold", "carrier found", and the logical and/or of these two.
Support for CCA mode setting is included in the at86rf230 driver,
predicated for RF212 chips.

Signed-off-by: Phoebe Buckheister <phoebe.buckheister-mPn0NPGs4xGatNDF+KUbs4QuADTiUCJX@public.gmane.org>
---
 drivers/net/ieee802154/at86rf230.c |    9 +++++++++
 include/linux/nl802154.h           |    1 +
 include/net/mac802154.h            |    5 +++++
 include/net/wpan-phy.h             |    1 +
 net/ieee802154/nl-phy.c            |   32 +++++++++++++++++++++++++++++---
 net/ieee802154/nl_policy.c         |    1 +
 net/mac802154/ieee802154_dev.c     |   11 +++++++++++
 7 files changed, 57 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index a785efd..fb5e55a 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -798,6 +798,14 @@ at86rf212_set_lbt(struct ieee802154_dev *dev, bool on)
 	return at86rf230_write_subreg(lp, SR_CSMA_LBT_MODE, on);
 }
 
+static int
+at86rf212_set_cca_mode(struct ieee802154_dev *dev, u8 mode)
+{
+	struct at86rf230_local *lp = dev->priv;
+
+	return at86rf230_write_subreg(lp, SR_CCA_MODE, mode);
+}
+
 static struct ieee802154_ops at86rf230_ops = {
 	.owner = THIS_MODULE,
 	.xmit = at86rf230_xmit,
@@ -818,6 +826,7 @@ static struct ieee802154_ops at86rf212_ops = {
 	.set_hw_addr_filt = at86rf230_set_hw_addr_filt,
 	.set_txpower = at86rf212_set_txpower,
 	.set_lbt = at86rf212_set_lbt,
+	.set_cca_mode = at86rf212_set_cca_mode,
 };
 
 static void at86rf230_irqwork(struct work_struct *work)
diff --git a/include/linux/nl802154.h b/include/linux/nl802154.h
index 326baee..5edefc1 100644
--- a/include/linux/nl802154.h
+++ b/include/linux/nl802154.h
@@ -72,6 +72,7 @@ enum {
 
 	IEEE802154_ATTR_TXPOWER,
 	IEEE802154_ATTR_LBT_ENABLED,
+	IEEE802154_ATTR_CCA_MODE,
 
 	__IEEE802154_ATTR_MAX,
 };
diff --git a/include/net/mac802154.h b/include/net/mac802154.h
index 521edcb..1a98e50 100644
--- a/include/net/mac802154.h
+++ b/include/net/mac802154.h
@@ -122,6 +122,10 @@ struct ieee802154_dev {
  *	  Enables or disables listen before talk on the device. Called with
  *	  pib_lock held.
  *	  Returns either zero, or negative errno.
+ *
+ * set_cca_mode
+ *	  Sets the CCA mode used by the device. Called with pib_lock held.
+ *	  Returns either zero, or negative errno.
  */
 struct ieee802154_ops {
 	struct module	*owner;
@@ -140,6 +144,7 @@ struct ieee802154_ops {
 				     u8 addr[IEEE802154_ADDR_LEN]);
 	int		(*set_txpower)(struct ieee802154_dev *dev, int db);
 	int		(*set_lbt)(struct ieee802154_dev *dev, bool on);
+	int		(*set_cca_mode)(struct ieee802154_dev *dev, u8 mode);
 };
 
 /* Basic interface to register ieee802154 device */
diff --git a/include/net/wpan-phy.h b/include/net/wpan-phy.h
index 804e6c4..03b5905 100644
--- a/include/net/wpan-phy.h
+++ b/include/net/wpan-phy.h
@@ -58,6 +58,7 @@ struct wpan_phy {
 
 	int (*set_txpower)(struct wpan_phy *phy, int db);
 	int (*set_lbt)(struct wpan_phy *phy, bool on);
+	int (*set_cca_mode)(struct wpan_phy *phy, u8 cca_mode);
 
 	char priv[0] __attribute__((__aligned__(NETDEV_ALIGN)));
 };
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c
index f248122..026b21a 100644
--- a/net/ieee802154/nl-phy.c
+++ b/net/ieee802154/nl-phy.c
@@ -57,7 +57,8 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid,
 	    nla_put_u8(msg, IEEE802154_ATTR_PAGE, phy->current_page) ||
 	    nla_put_u8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel) ||
 	    nla_put_s8(msg, IEEE802154_ATTR_TXPOWER, phy->transmit_power) ||
-	    nla_put_u8(msg, IEEE802154_ATTR_LBT_ENABLED, phy->lbt))
+	    nla_put_u8(msg, IEEE802154_ATTR_LBT_ENABLED, phy->lbt) ||
+	    nla_put_u8(msg, IEEE802154_ATTR_CCA_MODE, phy->cca_mode))
 		goto nla_put_failure;
 	for (i = 0; i < 32; i++) {
 		if (phy->channels_supported[i])
@@ -385,6 +386,23 @@ static int phy_set_lbt(struct wpan_phy *phy, struct genl_info *info)
 	return 0;
 }
 
+static int phy_set_cca_mode(struct wpan_phy *phy, struct genl_info *info)
+{
+	u8 mode = nla_get_u8(info->attrs[IEEE802154_ATTR_CCA_MODE]);
+	int rc;
+
+	if (mode > 3)
+		return -EINVAL;
+
+	rc = phy->set_cca_mode(phy, mode);
+	if (rc < 0)
+		return rc;
+
+	phy->cca_mode = mode;
+
+	return 0;
+}
+
 int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info)
 {
 	struct wpan_phy *phy;
@@ -394,7 +412,8 @@ int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info)
 	pr_debug("%s\n", __func__);
 
 	if (!info->attrs[IEEE802154_ATTR_PHY_NAME] &&
-		!info->attrs[IEEE802154_ATTR_LBT_ENABLED])
+		!info->attrs[IEEE802154_ATTR_LBT_ENABLED] &&
+		!info->attrs[IEEE802154_ATTR_CCA_MODE])
 		return -EINVAL;
 
 	name = nla_data(info->attrs[IEEE802154_ATTR_PHY_NAME]);
@@ -406,7 +425,8 @@ int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info)
 		return -ENODEV;
 
 	if ((!phy->set_txpower && info->attrs[IEEE802154_ATTR_TXPOWER]) ||
-		(!phy->set_lbt && info->attrs[IEEE802154_ATTR_LBT_ENABLED]))
+		(!phy->set_lbt && info->attrs[IEEE802154_ATTR_LBT_ENABLED]) ||
+		(!phy->set_cca_mode && info->attrs[IEEE802154_ATTR_CCA_MODE]))
 		goto out;
 
 	mutex_lock(&phy->pib_lock);
@@ -423,6 +443,12 @@ int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info)
 			goto error;
 	}
 
+	if (info->attrs[IEEE802154_ATTR_CCA_MODE]) {
+		rc = phy_set_cca_mode(phy, info);
+		if (rc < 0)
+			goto error;
+	}
+
 	mutex_unlock(&phy->pib_lock);
 
 	wpan_phy_put(phy);
diff --git a/net/ieee802154/nl_policy.c b/net/ieee802154/nl_policy.c
index a09f642..d87c2c9 100644
--- a/net/ieee802154/nl_policy.c
+++ b/net/ieee802154/nl_policy.c
@@ -55,5 +55,6 @@ const struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = {
 
 	[IEEE802154_ATTR_TXPOWER] = { .type = NLA_S8, },
 	[IEEE802154_ATTR_LBT_ENABLED] = { .type = NLA_U8, },
+	[IEEE802154_ATTR_CCA_MODE] = { .type = NLA_U8, },
 };
 
diff --git a/net/mac802154/ieee802154_dev.c b/net/mac802154/ieee802154_dev.c
index 56338c8..4965e4c 100644
--- a/net/mac802154/ieee802154_dev.c
+++ b/net/mac802154/ieee802154_dev.c
@@ -185,6 +185,16 @@ static int mac802154_set_lbt(struct wpan_phy *phy, bool on)
 	return priv->ops->set_lbt(&priv->hw, on);
 }
 
+static int mac802154_set_cca_mode(struct wpan_phy *phy, u8 mode)
+{
+	struct mac802154_priv *priv = wpan_phy_priv(phy);
+
+	if (!priv->ops->set_cca_mode)
+		return -ENOTSUPP;
+
+	return priv->ops->set_cca_mode(&priv->hw, mode);
+}
+
 struct ieee802154_dev *
 ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops)
 {
@@ -264,6 +274,7 @@ int ieee802154_register_device(struct ieee802154_dev *dev)
 	priv->phy->del_iface = mac802154_del_iface;
 	priv->phy->set_txpower = mac802154_set_txpower;
 	priv->phy->set_lbt = mac802154_set_lbt;
+	priv->phy->set_cca_mode = mac802154_set_cca_mode;
 
 	rc = wpan_phy_register(priv->phy);
 	if (rc < 0)
-- 
1.7.9.5


------------------------------------------------------------------------------
Android apps run on BlackBerry 10
Introducing the new BlackBerry 10.2.1 Runtime for Android apps.
Now with support for Jelly Bean, Bluetooth, Mapview and more.
Get your Android app in front of a whole new audience.  Start now.
http://pubads.g.doubleclick.net/gampad/clk?id=124407151&iu=/4140/ostg.clktrk

^ permalink raw reply related

* [PATCH net-next 05/10] ieee802154: add support for listen-before-talk in wpan_phy
From: Phoebe Buckheister @ 2014-02-12 16:37 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	linux-zigbee-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <1392223034-19955-1-git-send-email-phoebe.buckheister-mPn0NPGs4xGatNDF+KUbs4QuADTiUCJX@public.gmane.org>

Listen-before-talk is an alternative to CSMA in uncoordinated networks
and prescribed by european regulations if one wants to have a device
with radio duty cycles above 10% (or less in some bands). Add a phy
property to enable/disable LBT in the phy, including support in the
at86rf230 driver for RF212 chips.

Signed-off-by: Phoebe Buckheister <phoebe.buckheister-mPn0NPGs4xGatNDF+KUbs4QuADTiUCJX@public.gmane.org>
---
 drivers/net/ieee802154/at86rf230.c |   11 ++++++-
 include/linux/nl802154.h           |    1 +
 include/net/mac802154.h            |    6 ++++
 include/net/wpan-phy.h             |    3 ++
 net/ieee802154/nl-phy.c            |   58 ++++++++++++++++++++++++++++--------
 net/ieee802154/nl_policy.c         |    1 +
 net/mac802154/ieee802154_dev.c     |   11 +++++++
 7 files changed, 78 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index f6338c4..a785efd 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -152,7 +152,7 @@ static inline int is_rf212(struct at86rf230_local *local)
 #define	SR_RESERVED_17_5	0x17, 0x08, 3
 #define	SR_AACK_UPLD_RES_FT	0x17, 0x10, 4
 #define	SR_AACK_FLTR_RES_FT	0x17, 0x20, 5
-#define	SR_RESERVED_17_2	0x17, 0x40, 6
+#define	SR_CSMA_LBT_MODE	0x17, 0x40, 6
 #define	SR_RESERVED_17_1	0x17, 0x80, 7
 #define	RG_FTN_CTRL	(0x18)
 #define	SR_RESERVED_18_2	0x18, 0x7f, 0
@@ -790,6 +790,14 @@ at86rf212_set_txpower(struct ieee802154_dev *dev, int db)
 	return 0;
 }
 
+static int
+at86rf212_set_lbt(struct ieee802154_dev *dev, bool on)
+{
+	struct at86rf230_local *lp = dev->priv;
+
+	return at86rf230_write_subreg(lp, SR_CSMA_LBT_MODE, on);
+}
+
 static struct ieee802154_ops at86rf230_ops = {
 	.owner = THIS_MODULE,
 	.xmit = at86rf230_xmit,
@@ -809,6 +817,7 @@ static struct ieee802154_ops at86rf212_ops = {
 	.stop = at86rf230_stop,
 	.set_hw_addr_filt = at86rf230_set_hw_addr_filt,
 	.set_txpower = at86rf212_set_txpower,
+	.set_lbt = at86rf212_set_lbt,
 };
 
 static void at86rf230_irqwork(struct work_struct *work)
diff --git a/include/linux/nl802154.h b/include/linux/nl802154.h
index 625d19e..326baee 100644
--- a/include/linux/nl802154.h
+++ b/include/linux/nl802154.h
@@ -71,6 +71,7 @@ enum {
 	IEEE802154_ATTR_DEV_TYPE,
 
 	IEEE802154_ATTR_TXPOWER,
+	IEEE802154_ATTR_LBT_ENABLED,
 
 	__IEEE802154_ATTR_MAX,
 };
diff --git a/include/net/mac802154.h b/include/net/mac802154.h
index 8bd2785..521edcb 100644
--- a/include/net/mac802154.h
+++ b/include/net/mac802154.h
@@ -117,6 +117,11 @@ struct ieee802154_dev {
  * set_txpower:
  *	  Set radio transmit power in dB. Called with pib_lock held.
  *	  Returns either zero, or negative errno.
+ *
+ * set_lbt
+ *	  Enables or disables listen before talk on the device. Called with
+ *	  pib_lock held.
+ *	  Returns either zero, or negative errno.
  */
 struct ieee802154_ops {
 	struct module	*owner;
@@ -134,6 +139,7 @@ struct ieee802154_ops {
 	int		(*ieee_addr)(struct ieee802154_dev *dev,
 				     u8 addr[IEEE802154_ADDR_LEN]);
 	int		(*set_txpower)(struct ieee802154_dev *dev, int db);
+	int		(*set_lbt)(struct ieee802154_dev *dev, bool on);
 };
 
 /* Basic interface to register ieee802154 device */
diff --git a/include/net/wpan-phy.h b/include/net/wpan-phy.h
index 47fc0c1..804e6c4 100644
--- a/include/net/wpan-phy.h
+++ b/include/net/wpan-phy.h
@@ -47,6 +47,8 @@ struct wpan_phy {
 	s8 transmit_power;
 	u8 cca_mode;
 
+	bool lbt;
+
 	struct device dev;
 	int idx;
 
@@ -55,6 +57,7 @@ struct wpan_phy {
 	void (*del_iface)(struct wpan_phy *phy, struct net_device *dev);
 
 	int (*set_txpower)(struct wpan_phy *phy, int db);
+	int (*set_lbt)(struct wpan_phy *phy, bool on);
 
 	char priv[0] __attribute__((__aligned__(NETDEV_ALIGN)));
 };
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c
index d3ee62f..f248122 100644
--- a/net/ieee802154/nl-phy.c
+++ b/net/ieee802154/nl-phy.c
@@ -56,7 +56,8 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid,
 	if (nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) ||
 	    nla_put_u8(msg, IEEE802154_ATTR_PAGE, phy->current_page) ||
 	    nla_put_u8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel) ||
-	    nla_put_s8(msg, IEEE802154_ATTR_TXPOWER, phy->transmit_power))
+	    nla_put_s8(msg, IEEE802154_ATTR_TXPOWER, phy->transmit_power) ||
+	    nla_put_u8(msg, IEEE802154_ATTR_LBT_ENABLED, phy->lbt))
 		goto nla_put_failure;
 	for (i = 0; i < 32; i++) {
 		if (phy->channels_supported[i])
@@ -356,40 +357,71 @@ out_dev:
 	return rc;
 }
 
+static int phy_set_txpower(struct wpan_phy *phy, struct genl_info *info)
+{
+	int txpower = nla_get_s8(info->attrs[IEEE802154_ATTR_TXPOWER]);
+	int rc;
+
+	rc = phy->set_txpower(phy, txpower);
+	if (rc < 0)
+		return rc;
+
+	phy->transmit_power = txpower;
+
+	return 0;
+}
+
+static int phy_set_lbt(struct wpan_phy *phy, struct genl_info *info)
+{
+	u8 on = !!nla_get_u8(info->attrs[IEEE802154_ATTR_LBT_ENABLED]);
+	int rc;
+
+	rc = phy->set_lbt(phy, on);
+	if (rc < 0)
+		return rc;
+
+	phy->lbt = on;
+
+	return 0;
+}
+
 int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info)
 {
 	struct wpan_phy *phy;
 	const char *name;
-	int txpower;
-	int rc = -EINVAL;
+	int rc = -ENOTSUPP;
 
 	pr_debug("%s\n", __func__);
 
-	if (!info->attrs[IEEE802154_ATTR_PHY_NAME])
+	if (!info->attrs[IEEE802154_ATTR_PHY_NAME] &&
+		!info->attrs[IEEE802154_ATTR_LBT_ENABLED])
 		return -EINVAL;
 
 	name = nla_data(info->attrs[IEEE802154_ATTR_PHY_NAME]);
 	if (name[nla_len(info->attrs[IEEE802154_ATTR_PHY_NAME]) - 1] != '\0')
 		return -EINVAL; /* phy name should be null-terminated */
 
-	txpower = nla_get_s8(info->attrs[IEEE802154_ATTR_TXPOWER]);
-
 	phy = wpan_phy_find(name);
 	if (!phy)
 		return -ENODEV;
 
-	if (!phy->set_txpower)
+	if ((!phy->set_txpower && info->attrs[IEEE802154_ATTR_TXPOWER]) ||
+		(!phy->set_lbt && info->attrs[IEEE802154_ATTR_LBT_ENABLED]))
 		goto out;
 
 	mutex_lock(&phy->pib_lock);
 
-	rc = phy->set_txpower(phy, txpower);
-	if (rc < 0) {
-		mutex_unlock(&phy->pib_lock);
-		goto out;
+	if (info->attrs[IEEE802154_ATTR_TXPOWER]) {
+		rc = phy_set_txpower(phy, info);
+		if (rc < 0)
+			goto error;
 	}
 
-	phy->transmit_power = txpower;
+	if (info->attrs[IEEE802154_ATTR_LBT_ENABLED]) {
+		rc = phy_set_lbt(phy, info);
+		if (rc < 0)
+			goto error;
+	}
 
 	mutex_unlock(&phy->pib_lock);
 
@@ -397,6 +429,8 @@ int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info)
 
 	return 0;
 
+error:
+	mutex_unlock(&phy->pib_lock);
 out:
 	wpan_phy_put(phy);
 	return rc;
diff --git a/net/ieee802154/nl_policy.c b/net/ieee802154/nl_policy.c
index 90b1d0d..a09f642 100644
--- a/net/ieee802154/nl_policy.c
+++ b/net/ieee802154/nl_policy.c
@@ -54,5 +54,6 @@ const struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = {
 	[IEEE802154_ATTR_CHANNEL_PAGE_LIST] = { .len = 32 * 4, },
 
 	[IEEE802154_ATTR_TXPOWER] = { .type = NLA_S8, },
+	[IEEE802154_ATTR_LBT_ENABLED] = { .type = NLA_U8, },
 };
 
diff --git a/net/mac802154/ieee802154_dev.c b/net/mac802154/ieee802154_dev.c
index 9eb49e0..56338c8 100644
--- a/net/mac802154/ieee802154_dev.c
+++ b/net/mac802154/ieee802154_dev.c
@@ -175,6 +175,16 @@ static int mac802154_set_txpower(struct wpan_phy *phy, int db)
 	return priv->ops->set_txpower(&priv->hw, db);
 }
 
+static int mac802154_set_lbt(struct wpan_phy *phy, bool on)
+{
+	struct mac802154_priv *priv = wpan_phy_priv(phy);
+
+	if (!priv->ops->set_lbt)
+		return -ENOTSUPP;
+
+	return priv->ops->set_lbt(&priv->hw, on);
+}
+
 struct ieee802154_dev *
 ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops)
 {
@@ -253,6 +263,7 @@ int ieee802154_register_device(struct ieee802154_dev *dev)
 	priv->phy->add_iface = mac802154_add_iface;
 	priv->phy->del_iface = mac802154_del_iface;
 	priv->phy->set_txpower = mac802154_set_txpower;
+	priv->phy->set_lbt = mac802154_set_lbt;
 
 	rc = wpan_phy_register(priv->phy);
 	if (rc < 0)
-- 
1.7.9.5


------------------------------------------------------------------------------
Android apps run on BlackBerry 10
Introducing the new BlackBerry 10.2.1 Runtime for Android apps.
Now with support for Jelly Bean, Bluetooth, Mapview and more.
Get your Android app in front of a whole new audience.  Start now.
http://pubads.g.doubleclick.net/gampad/clk?id=124407151&iu=/4140/ostg.clktrk

^ permalink raw reply related

* [PATCH net-next 04/10] ieee802154: support 100kbps QPSK/EU in at86rf230
From: Phoebe Buckheister @ 2014-02-12 16:37 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	linux-zigbee-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <1392223034-19955-1-git-send-email-phoebe.buckheister-mPn0NPGs4xGatNDF+KUbs4QuADTiUCJX@public.gmane.org>

The standard assigns channel 0 on page 2 to be 100kbps QPSK in the
868.3MHz band. Add support to the at86rf230 driver for this channel and
page, at the moment predicated only for the RF212 chip.

Per the datasheet, configurations for page 0, channels 0 to 10 and page
2, channels 0 to 10 differ only in the BPSK_QPSK bit. Support for
channels 1 to 10 is untested.

Signed-off-by: Phoebe Buckheister <phoebe.buckheister-mPn0NPGs4xGatNDF+KUbs4QuADTiUCJX@public.gmane.org>
---
 drivers/net/ieee802154/at86rf230.c |   17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index 99bc822..f6338c4 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -106,7 +106,8 @@ static inline int is_rf212(struct at86rf230_local *local)
 #define	SR_OQPSK_DATA_RATE	0x0c, 0x03, 0
 #define	SR_SUB_MODE		0x0c, 0x04, 2
 #define	SR_BPSK_QPSK		0x0c, 0x08, 3
-#define	SR_RESERVED_0c_4	0x0c, 0x70, 4
+#define	SR_OQPSK_SUB1_RC_EN	0x0c, 0x10, 4
+#define	SR_RESERVED_0c_5	0x0c, 0x60, 5
 #define	SR_RX_SAFE_MODE		0x0c, 0x80, 7
 #define	RG_ANT_DIV	(0x0d)
 #define	SR_ANT_CTRL		0x0d, 0x03, 0
@@ -595,6 +596,14 @@ at86rf212_set_channel(struct at86rf230_local *lp, int page, int channel)
 	if (rc < 0)
 		return rc;
 
+	if (page == 0)
+		rc = at86rf230_write_subreg(lp, SR_BPSK_QPSK, 0);
+	else
+		rc = at86rf230_write_subreg(lp, SR_BPSK_QPSK, 1);
+
+	if (rc < 0)
+		return rc;
+
 	return at86rf230_write_subreg(lp, SR_CHANNEL, channel);
 }
 
@@ -623,6 +632,7 @@ at86rf230_channel(struct ieee802154_dev *dev, int page, int channel)
 
 	msleep(1); /* Wait for PLL */
 	dev->phy->current_channel = channel;
+	dev->phy->current_page = page;
 
 	return 0;
 }
@@ -1067,9 +1077,10 @@ static int at86rf230_probe(struct spi_device *spi)
 
 	spi_set_drvdata(spi, lp);
 
-	if (is_rf212(lp))
+	if (is_rf212(lp)) {
 		dev->phy->channels_supported[0] = 0x00007FF;
-	else
+		dev->phy->channels_supported[2] = 0x00007FF;
+	} else
 		dev->phy->channels_supported[0] = 0x7FFF800;
 
 	rc = at86rf230_hw_init(lp);
-- 
1.7.9.5


------------------------------------------------------------------------------
Android apps run on BlackBerry 10
Introducing the new BlackBerry 10.2.1 Runtime for Android apps.
Now with support for Jelly Bean, Bluetooth, Mapview and more.
Get your Android app in front of a whole new audience.  Start now.
http://pubads.g.doubleclick.net/gampad/clk?id=124407151&iu=/4140/ostg.clktrk

^ permalink raw reply related

* [PATCH net-next 02/10] ieee802154: default to AACK in at86rf230
From: Phoebe Buckheister @ 2014-02-12 16:37 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	linux-zigbee-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In-Reply-To: <1392223034-19955-1-git-send-email-phoebe.buckheister-mPn0NPGs4xGatNDF+KUbs4QuADTiUCJX@public.gmane.org>

The current IEEE802.15.4 stack assumes that a radio will never deliver
packets with a bad CRC into the stack, as required by the standard.
at86rf230 driven radios violates this assumption because of another
incompatibility: devices are required to send ACKs if requested by a
sender, but RF2xx will only send ACKs from a special receive mode that
is currently not used by the driver.

Enable this receive mode to fix both bugs. Frames with bad CRCs will not
be received at all, and ACKs will be sent if so requested.

Signed-off-by: Phoebe Buckheister <phoebe.buckheister-mPn0NPGs4xGatNDF+KUbs4QuADTiUCJX@public.gmane.org>
---
 drivers/net/ieee802154/at86rf230.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index 93123ae..8cd2d83 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -567,7 +567,7 @@ at86rf230_start(struct ieee802154_dev *dev)
 	if (rc)
 		return rc;
 
-	return at86rf230_state(dev, STATE_RX_ON);
+	return at86rf230_state(dev, STATE_RX_AACK_ON);
 }
 
 static void
-- 
1.7.9.5


------------------------------------------------------------------------------
Android apps run on BlackBerry 10
Introducing the new BlackBerry 10.2.1 Runtime for Android apps.
Now with support for Jelly Bean, Bluetooth, Mapview and more.
Get your Android app in front of a whole new audience.  Start now.
http://pubads.g.doubleclick.net/gampad/clk?id=124407151&iu=/4140/ostg.clktrk

^ permalink raw reply related

* [PATCH net 3/3] vhost: fix a theoretical race in device cleanup
From: Michael S. Tsirkin @ 2014-02-12 16:36 UTC (permalink / raw)
  To: linux-kernel; +Cc: virtio-dev, kvm, netdev, virtualization, qinchuanyu, davem
In-Reply-To: <1392222846-26699-1-git-send-email-mst@redhat.com>

vhost_zerocopy_callback accesses VQ right after
it drops the last ubuf reference.
In theory, this could race with device removal
which waits on the ubuf kref, and crash
on use after free.

Do all accesses within rcu read side critical
section, and all synchronize on release.

Since callbacks are always invoked from bh,
synchronize_rcu_bh seems enough and will help
release complete a bit faster.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 drivers/vhost/net.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 7eaf2de..78a9d42 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -308,6 +308,8 @@ static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success)
 	struct vhost_virtqueue *vq = ubufs->vq;
 	int cnt;
 
+	rcu_read_lock_bh();
+
 	/* set len to mark this desc buffers done DMA */
 	vq->heads[ubuf->desc].len = success ?
 		VHOST_DMA_DONE_LEN : VHOST_DMA_FAILED_LEN;
@@ -322,6 +324,8 @@ static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success)
 	 */
 	if (cnt <= 1 || !(cnt % 16))
 		vhost_poll_queue(&vq->poll);
+
+	rcu_read_unlock_bh();
 }
 
 /* Expects to be always run from workqueue - which acts as
@@ -804,6 +808,8 @@ static int vhost_net_release(struct inode *inode, struct file *f)
 		fput(tx_sock->file);
 	if (rx_sock)
 		fput(rx_sock->file);
+	/* Make sure no callbacks are outstanding */
+	synchronize_rcu_bh();
 	/* We do an extra flush before freeing memory,
 	 * since jobs can re-queue themselves. */
 	vhost_net_flush(n);
-- 
MST

^ permalink raw reply related

* Re: [PATCH] net: clear iflink when moving to a new netns
From: Stephen Hemminger @ 2014-02-12 16:33 UTC (permalink / raw)
  To: Cong Wang
  Cc: netdev, David S. Miller, Eric W. Biederman, Eric Dumazet,
	Hannes Frederic Sowa, Cong Wang
In-Reply-To: <1392162690-6647-1-git-send-email-xiyou.wangcong@gmail.com>

On Tue, 11 Feb 2014 15:51:28 -0800
Cong Wang <xiyou.wangcong@gmail.com> wrote:

> From: Cong Wang <cwang@twopensource.com>
> 
> BZ: https://bugzilla.kernel.org/show_bug.cgi?id=66691
> 
> macvlan and vlan both use iflink to identify its lower device,
> however, after such device is moved to the new netns, its iflink
> would become meaningless as ifindex is per netns. So, instead of
> forbid them moving to another netns, just clear this field so that
> it will not be dumped at least.
> 
> Cc: David S. Miller <davem@davemloft.net>
> Cc: Eric W. Biederman <ebiederm@xmission.com>
> Cc: Eric Dumazet <eric.dumazet@gmail.com>
> Cc: Hannes Frederic Sowa <hannes@stressinduktion.org>,
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
> Signed-off-by: Cong Wang <cwang@twopensource.com>
> ---
>  net/core/dev.c | 9 ++++-----
>  1 file changed, 4 insertions(+), 5 deletions(-)
> 
> diff --git a/net/core/dev.c b/net/core/dev.c
> index 4ad1b78..5e88b0c2 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -6608,12 +6608,11 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
>  	dev_net_set(dev, net);
>  
>  	/* If there is an ifindex conflict assign a new one */
> -	if (__dev_get_by_index(net, dev->ifindex)) {
> -		int iflink = (dev->iflink == dev->ifindex);
> +	if (__dev_get_by_index(net, dev->ifindex))
>  		dev->ifindex = dev_new_index(net);
> -		if (iflink)
> -			dev->iflink = dev->ifindex;
> -	}
> +
> +	/* Old iflink is meaningless in the new namespace */
> +	dev->iflink = dev->ifindex;
>  
>  	/* Send a netdev-add uevent to the new namespace */
>  	kobject_uevent(&dev->dev.kobj, KOBJ_ADD);

This also breaks propogation of state changes from lower device
to upper device. Things like carrier and up/down.

^ permalink raw reply

* [PATCH net-next 9/9] bnx2x: utilize FW 7.8.19
From: Yuval Mintz @ 2014-02-12 16:19 UTC (permalink / raw)
  To: davem, netdev; +Cc: ariele, Dmitry Kravkov, Yuval Mintz
In-Reply-To: <1392221997-25525-1-git-send-email-yuvalmin@broadcom.com>

From: Dmitry Kravkov <dmitry@broadcom.com>

    This new firmware fixes following bugs:
     1. HW attention appears and traffic stops when iSCSI firmware tries to
        retransmit iSCSI login command when the iSCSI login is carrying data
        not aligned to 4-bytes.
     2. FCoE traffic fails to run when running in switch-independent multi-function
        mode and there's more than one interface supporting FCoE on a given port.
     3. While two ports are running FCoE with at least one of them has a function
        number (>1) on the same engine in a 4-port device a zeroed CQE is given,
        causing FCoE traffic to stop.

Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com>
Signed-off-by: Yuval Mintz <yuvalmin@broadcom.com>
Signed-off-by: Ariel Elior <ariele@broadcom.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x.h     | 4 ++--
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 391f29e..064824a 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -26,8 +26,8 @@
  * (you will need to reboot afterwards) */
 /* #define BNX2X_STOP_ON_ERROR */
 
-#define DRV_MODULE_VERSION      "1.78.17-0"
-#define DRV_MODULE_RELDATE      "2013/04/11"
+#define DRV_MODULE_VERSION      "1.78.19-0"
+#define DRV_MODULE_RELDATE      "2014/02/10"
 #define BNX2X_BC_VER            0x040200
 
 #if defined(CONFIG_DCB)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
index cf1df8b..46e2f18 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
@@ -2848,7 +2848,7 @@ struct afex_stats {
 
 #define BCM_5710_FW_MAJOR_VERSION			7
 #define BCM_5710_FW_MINOR_VERSION			8
-#define BCM_5710_FW_REVISION_VERSION		17
+#define BCM_5710_FW_REVISION_VERSION		19
 #define BCM_5710_FW_ENGINEERING_VERSION		0
 #define BCM_5710_FW_COMPILE_FLAGS			1
 
-- 
1.8.5.3

^ permalink raw reply related

* [PATCH net-next 5/9] bnx2x: Add support in PF driver for RSC
From: Yuval Mintz @ 2014-02-12 16:19 UTC (permalink / raw)
  To: davem, netdev; +Cc: ariele, Michal Kalderon, Yuval Mintz
In-Reply-To: <1392221997-25525-1-git-send-email-yuvalmin@broadcom.com>

From: Michal Kalderon <michals@broadcom.com>

This provides PF-side support for VFs assigned to a VM running windows
2012 with the RSC feature enabled.

Signed-off-by: Michal Kalderon <michals@broadcom.com>
Signed-off-by: Yuval Mintz <yuvalmin@broadcom.com>
Signed-off-by: Ariel Elior <ariele@broadcom.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x.h       |   1 +
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c  |  21 +++-
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c    | 145 +++++++++++++++-------
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h    |  19 +++
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c |  82 ++++++++++++
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h |  12 ++
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c  |  75 ++++++++++-
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h  |  22 ++++
 8 files changed, 329 insertions(+), 48 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index ae91e8f..c871d19 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1270,6 +1270,7 @@ struct bnx2x_slowpath {
 	union {
 		struct client_init_ramrod_data  init_data;
 		struct client_update_ramrod_data update_data;
+		struct tpa_update_ramrod_data tpa_data;
 	} q_rdata;
 
 	union {
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 383b025..7245059 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -1814,6 +1814,11 @@ void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe)
 		drv_cmd = BNX2X_Q_CMD_EMPTY;
 		break;
 
+	case (RAMROD_CMD_ID_ETH_TPA_UPDATE):
+		DP(BNX2X_MSG_SP, "got tpa update ramrod CID=%d\n", cid);
+		drv_cmd = BNX2X_Q_CMD_UPDATE_TPA;
+		break;
+
 	default:
 		BNX2X_ERR("unexpected MC reply (%d) on fp[%d]\n",
 			  command, fp->index);
@@ -3644,10 +3649,18 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
 			cpu_to_le32((command << SPE_HDR_CMD_ID_SHIFT) |
 				    HW_CID(bp, cid));
 
-	type = (cmd_type << SPE_HDR_CONN_TYPE_SHIFT) & SPE_HDR_CONN_TYPE;
-
-	type |= ((BP_FUNC(bp) << SPE_HDR_FUNCTION_ID_SHIFT) &
-		 SPE_HDR_FUNCTION_ID);
+	/* In some cases, type may already contain the func-id
+	 * mainly in SRIOV related use cases, so we add it here only
+	 * if it's not already set.
+	 */
+	if (!(cmd_type & SPE_HDR_FUNCTION_ID)) {
+		type = (cmd_type << SPE_HDR_CONN_TYPE_SHIFT) &
+			SPE_HDR_CONN_TYPE;
+		type |= ((BP_FUNC(bp) << SPE_HDR_FUNCTION_ID_SHIFT) &
+			 SPE_HDR_FUNCTION_ID);
+	} else {
+		type = cmd_type;
+	}
 
 	spe->hdr.type = cpu_to_le16(type);
 
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
index 0fb6ff2..270ba19 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
@@ -2277,11 +2277,11 @@ static int bnx2x_set_rx_mode_e2(struct bnx2x *bp,
 			 data->header.rule_cnt, p->rx_accept_flags,
 			 p->tx_accept_flags);
 
-	/* No need for an explicit memory barrier here as long we would
-	 * need to ensure the ordering of writing to the SPQ element
+	/* No need for an explicit memory barrier here as long as we
+	 * ensure the ordering of writing to the SPQ element
 	 * and updating of the SPQ producer which involves a memory
-	 * read and we will have to put a full memory barrier there
-	 * (inside bnx2x_sp_post()).
+	 * read. If the memory read is removed we will have to put a
+	 * full memory barrier there (inside bnx2x_sp_post()).
 	 */
 
 	/* Send a ramrod */
@@ -2982,11 +2982,11 @@ static int bnx2x_mcast_setup_e2(struct bnx2x *bp,
 		raw->clear_pending(raw);
 		return 0;
 	} else {
-		/* No need for an explicit memory barrier here as long we would
-		 * need to ensure the ordering of writing to the SPQ element
+		/* No need for an explicit memory barrier here as long as we
+		 * ensure the ordering of writing to the SPQ element
 		 * and updating of the SPQ producer which involves a memory
-		 * read and we will have to put a full memory barrier there
-		 * (inside bnx2x_sp_post()).
+		 * read. If the memory read is removed we will have to put a
+		 * full memory barrier there (inside bnx2x_sp_post()).
 		 */
 
 		/* Send a ramrod */
@@ -3466,11 +3466,11 @@ static int bnx2x_mcast_setup_e1(struct bnx2x *bp,
 		raw->clear_pending(raw);
 		return 0;
 	} else {
-		/* No need for an explicit memory barrier here as long we would
-		 * need to ensure the ordering of writing to the SPQ element
+		/* No need for an explicit memory barrier here as long as we
+		 * ensure the ordering of writing to the SPQ element
 		 * and updating of the SPQ producer which involves a memory
-		 * read and we will have to put a full memory barrier there
-		 * (inside bnx2x_sp_post()).
+		 * read. If the memory read is removed we will have to put a
+		 * full memory barrier there (inside bnx2x_sp_post()).
 		 */
 
 		/* Send a ramrod */
@@ -4091,11 +4091,11 @@ static int bnx2x_setup_rss(struct bnx2x *bp,
 		data->capabilities |= ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY;
 	}
 
-	/* No need for an explicit memory barrier here as long we would
-	 * need to ensure the ordering of writing to the SPQ element
+	/* No need for an explicit memory barrier here as long as we
+	 * ensure the ordering of writing to the SPQ element
 	 * and updating of the SPQ producer which involves a memory
-	 * read and we will have to put a full memory barrier there
-	 * (inside bnx2x_sp_post()).
+	 * read. If the memory read is removed we will have to put a
+	 * full memory barrier there (inside bnx2x_sp_post()).
 	 */
 
 	/* Send a ramrod */
@@ -4587,13 +4587,12 @@ static inline int bnx2x_q_send_setup_e1x(struct bnx2x *bp,
 	/* Fill the ramrod data */
 	bnx2x_q_fill_setup_data_cmn(bp, params, rdata);
 
-	/* No need for an explicit memory barrier here as long we would
-	 * need to ensure the ordering of writing to the SPQ element
+	/* No need for an explicit memory barrier here as long as we
+	 * ensure the ordering of writing to the SPQ element
 	 * and updating of the SPQ producer which involves a memory
-	 * read and we will have to put a full memory barrier there
-	 * (inside bnx2x_sp_post()).
+	 * read. If the memory read is removed we will have to put a
+	 * full memory barrier there (inside bnx2x_sp_post()).
 	 */
-
 	return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX],
 			     U64_HI(data_mapping),
 			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
@@ -4615,13 +4614,12 @@ static inline int bnx2x_q_send_setup_e2(struct bnx2x *bp,
 	bnx2x_q_fill_setup_data_cmn(bp, params, rdata);
 	bnx2x_q_fill_setup_data_e2(bp, params, rdata);
 
-	/* No need for an explicit memory barrier here as long we would
-	 * need to ensure the ordering of writing to the SPQ element
+	/* No need for an explicit memory barrier here as long as we
+	 * ensure the ordering of writing to the SPQ element
 	 * and updating of the SPQ producer which involves a memory
-	 * read and we will have to put a full memory barrier there
-	 * (inside bnx2x_sp_post()).
+	 * read. If the memory read is removed we will have to put a
+	 * full memory barrier there (inside bnx2x_sp_post()).
 	 */
-
 	return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX],
 			     U64_HI(data_mapping),
 			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
@@ -4659,13 +4657,12 @@ static inline int bnx2x_q_send_setup_tx_only(struct bnx2x *bp,
 			 o->cids[cid_index], rdata->general.client_id,
 			 rdata->general.sp_client_id, rdata->general.cos);
 
-	/* No need for an explicit memory barrier here as long we would
-	 * need to ensure the ordering of writing to the SPQ element
+	/* No need for an explicit memory barrier here as long as we
+	 * ensure the ordering of writing to the SPQ element
 	 * and updating of the SPQ producer which involves a memory
-	 * read and we will have to put a full memory barrier there
-	 * (inside bnx2x_sp_post()).
+	 * read. If the memory read is removed we will have to put a
+	 * full memory barrier there (inside bnx2x_sp_post()).
 	 */
-
 	return bnx2x_sp_post(bp, ramrod, o->cids[cid_index],
 			     U64_HI(data_mapping),
 			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
@@ -4760,13 +4757,12 @@ static inline int bnx2x_q_send_update(struct bnx2x *bp,
 	/* Fill the ramrod data */
 	bnx2x_q_fill_update_data(bp, o, update_params, rdata);
 
-	/* No need for an explicit memory barrier here as long we would
-	 * need to ensure the ordering of writing to the SPQ element
+	/* No need for an explicit memory barrier here as long as we
+	 * ensure the ordering of writing to the SPQ element
 	 * and updating of the SPQ producer which involves a memory
-	 * read and we will have to put a full memory barrier there
-	 * (inside bnx2x_sp_post()).
+	 * read. If the memory read is removed we will have to put a
+	 * full memory barrier there (inside bnx2x_sp_post()).
 	 */
-
 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_UPDATE,
 			     o->cids[cid_index], U64_HI(data_mapping),
 			     U64_LO(data_mapping), ETH_CONNECTION_TYPE);
@@ -4813,11 +4809,62 @@ static inline int bnx2x_q_send_activate(struct bnx2x *bp,
 	return bnx2x_q_send_update(bp, params);
 }
 
+static void bnx2x_q_fill_update_tpa_data(struct bnx2x *bp,
+				struct bnx2x_queue_sp_obj *obj,
+				struct bnx2x_queue_update_tpa_params *params,
+				struct tpa_update_ramrod_data *data)
+{
+	data->client_id = obj->cl_id;
+	data->complete_on_both_clients = params->complete_on_both_clients;
+	data->dont_verify_rings_pause_thr_flg =
+		params->dont_verify_thr;
+	data->max_agg_size = cpu_to_le16(params->max_agg_sz);
+	data->max_sges_for_packet = params->max_sges_pkt;
+	data->max_tpa_queues = params->max_tpa_queues;
+	data->sge_buff_size = cpu_to_le16(params->sge_buff_sz);
+	data->sge_page_base_hi = cpu_to_le32(U64_HI(params->sge_map));
+	data->sge_page_base_lo = cpu_to_le32(U64_LO(params->sge_map));
+	data->sge_pause_thr_high = cpu_to_le16(params->sge_pause_thr_high);
+	data->sge_pause_thr_low = cpu_to_le16(params->sge_pause_thr_low);
+	data->tpa_mode = params->tpa_mode;
+	data->update_ipv4 = params->update_ipv4;
+	data->update_ipv6 = params->update_ipv6;
+}
+
 static inline int bnx2x_q_send_update_tpa(struct bnx2x *bp,
 					struct bnx2x_queue_state_params *params)
 {
-	/* TODO: Not implemented yet. */
-	return -1;
+	struct bnx2x_queue_sp_obj *o = params->q_obj;
+	struct tpa_update_ramrod_data *rdata =
+		(struct tpa_update_ramrod_data *)o->rdata;
+	dma_addr_t data_mapping = o->rdata_mapping;
+	struct bnx2x_queue_update_tpa_params *update_tpa_params =
+		&params->params.update_tpa;
+	u16 type;
+
+	/* Clear the ramrod data */
+	memset(rdata, 0, sizeof(*rdata));
+
+	/* Fill the ramrod data */
+	bnx2x_q_fill_update_tpa_data(bp, o, update_tpa_params, rdata);
+
+	/* Add the function id inside the type, so that sp post function
+	 * doesn't automatically add the PF func-id, this is required
+	 * for operations done by PFs on behalf of their VFs
+	 */
+	type = ETH_CONNECTION_TYPE |
+		((o->func_id) << SPE_HDR_FUNCTION_ID_SHIFT);
+
+	/* No need for an explicit memory barrier here as long as we
+	 * ensure the ordering of writing to the SPQ element
+	 * and updating of the SPQ producer which involves a memory
+	 * read. If the memory read is removed we will have to put a
+	 * full memory barrier there (inside bnx2x_sp_post()).
+	 */
+	return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_TPA_UPDATE,
+			     o->cids[BNX2X_PRIMARY_CID_INDEX],
+			     U64_HI(data_mapping),
+			     U64_LO(data_mapping), type);
 }
 
 static inline int bnx2x_q_send_halt(struct bnx2x *bp,
@@ -5647,6 +5694,12 @@ static inline int bnx2x_func_send_switch_update(struct bnx2x *bp,
 	rdata->tx_switch_suspend = switch_update_params->suspend;
 	rdata->echo = SWITCH_UPDATE;
 
+	/* No need for an explicit memory barrier here as long as we
+	 * ensure the ordering of writing to the SPQ element
+	 * and updating of the SPQ producer which involves a memory
+	 * read. If the memory read is removed we will have to put a
+	 * full memory barrier there (inside bnx2x_sp_post()).
+	 */
 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_UPDATE, 0,
 			     U64_HI(data_mapping),
 			     U64_LO(data_mapping), NONE_CONNECTION_TYPE);
@@ -5674,11 +5727,11 @@ static inline int bnx2x_func_send_afex_update(struct bnx2x *bp,
 	rdata->allowed_priorities = afex_update_params->allowed_priorities;
 	rdata->echo = AFEX_UPDATE;
 
-	/*  No need for an explicit memory barrier here as long we would
-	 *  need to ensure the ordering of writing to the SPQ element
-	 *  and updating of the SPQ producer which involves a memory
-	 *  read and we will have to put a full memory barrier there
-	 *  (inside bnx2x_sp_post()).
+	/* No need for an explicit memory barrier here as long as we
+	 * ensure the ordering of writing to the SPQ element
+	 * and updating of the SPQ producer which involves a memory
+	 * read. If the memory read is removed we will have to put a
+	 * full memory barrier there (inside bnx2x_sp_post()).
 	 */
 	DP(BNX2X_MSG_SP,
 	   "afex: sending func_update vif_id 0x%x dvlan 0x%x prio 0x%x\n",
@@ -5763,6 +5816,12 @@ static inline int bnx2x_func_send_tx_start(struct bnx2x *bp,
 		rdata->traffic_type_to_priority_cos[i] =
 			tx_start_params->traffic_type_to_priority_cos[i];
 
+	/* No need for an explicit memory barrier here as long as we
+	 * ensure the ordering of writing to the SPQ element
+	 * and updating of the SPQ producer which involves a memory
+	 * read. If the memory read is removed we will have to put a
+	 * full memory barrier there (inside bnx2x_sp_post()).
+	 */
 	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_START_TRAFFIC, 0,
 			     U64_HI(data_mapping),
 			     U64_LO(data_mapping), NONE_CONNECTION_TYPE);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
index 00d7f21..f7af21f 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
@@ -893,6 +893,24 @@ struct bnx2x_queue_update_params {
 	u8		cid_index;
 };
 
+struct bnx2x_queue_update_tpa_params {
+	dma_addr_t sge_map;
+	u8 update_ipv4;
+	u8 update_ipv6;
+	u8 max_tpa_queues;
+	u8 max_sges_pkt;
+	u8 complete_on_both_clients;
+	u8 dont_verify_thr;
+	u8 tpa_mode;
+	u8 _pad;
+
+	u16 sge_buff_sz;
+	u16 max_agg_sz;
+
+	u16 sge_pause_thr_low;
+	u16 sge_pause_thr_high;
+};
+
 struct rxq_pause_params {
 	u16		bd_th_lo;
 	u16		bd_th_hi;
@@ -987,6 +1005,7 @@ struct bnx2x_queue_state_params {
 	/* Params according to the current command */
 	union {
 		struct bnx2x_queue_update_params	update;
+		struct bnx2x_queue_update_tpa_params    update_tpa;
 		struct bnx2x_queue_setup_params		setup;
 		struct bnx2x_queue_init_params		init;
 		struct bnx2x_queue_setup_tx_only_params	tx_only;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
index c98edb0..e72070a 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
@@ -176,6 +176,11 @@ enum bnx2x_vfop_rss_state {
 	   BNX2X_VFOP_RSS_DONE
 };
 
+enum bnx2x_vfop_tpa_state {
+	   BNX2X_VFOP_TPA_CONFIG,
+	   BNX2X_VFOP_TPA_DONE
+};
+
 #define bnx2x_vfop_reset_wq(vf)	atomic_set(&vf->op_in_progress, 0)
 
 void bnx2x_vfop_qctor_dump_tx(struct bnx2x *bp, struct bnx2x_virtf *vf,
@@ -3047,6 +3052,83 @@ int bnx2x_vfop_rss_cmd(struct bnx2x *bp,
 	return -ENOMEM;
 }
 
+/* VFOP tpa update, send update on all queues */
+static void bnx2x_vfop_tpa(struct bnx2x *bp, struct bnx2x_virtf *vf)
+{
+	struct bnx2x_vfop *vfop = bnx2x_vfop_cur(bp, vf);
+	struct bnx2x_vfop_args_tpa *tpa_args = &vfop->args.tpa;
+	enum bnx2x_vfop_tpa_state state = vfop->state;
+
+	bnx2x_vfop_reset_wq(vf);
+
+	if (vfop->rc < 0)
+		goto op_err;
+
+	DP(BNX2X_MSG_IOV, "vf[%d:%d] STATE: %d\n",
+	   vf->abs_vfid, tpa_args->qid,
+	   state);
+
+	switch (state) {
+	case BNX2X_VFOP_TPA_CONFIG:
+
+		if (tpa_args->qid < vf_rxq_count(vf)) {
+			struct bnx2x_queue_state_params *qstate =
+				&vf->op_params.qstate;
+
+			qstate->q_obj = &bnx2x_vfq(vf, tpa_args->qid, sp_obj);
+
+			/* The only thing that changes for the ramrod params
+			 * between calls is the sge_map
+			 */
+			qstate->params.update_tpa.sge_map =
+				tpa_args->sge_map[tpa_args->qid];
+
+			DP(BNX2X_MSG_IOV, "sge_addr[%d] %08x:%08x\n",
+			   tpa_args->qid,
+			   U64_HI(qstate->params.update_tpa.sge_map),
+			   U64_LO(qstate->params.update_tpa.sge_map));
+			qstate->cmd = BNX2X_Q_CMD_UPDATE_TPA;
+			vfop->rc = bnx2x_queue_state_change(bp, qstate);
+
+			tpa_args->qid++;
+			bnx2x_vfop_finalize(vf, vfop->rc, VFOP_CONT);
+		}
+		vfop->state = BNX2X_VFOP_TPA_DONE;
+		vfop->rc = 0;
+		bnx2x_vfop_finalize(vf, vfop->rc, VFOP_DONE);
+op_err:
+		BNX2X_ERR("TPA update error: rc %d\n", vfop->rc);
+op_done:
+	case BNX2X_VFOP_TPA_DONE:
+		bnx2x_vfop_end(bp, vf, vfop);
+		return;
+	default:
+		bnx2x_vfop_default(state);
+	}
+op_pending:
+	return;
+}
+
+int bnx2x_vfop_tpa_cmd(struct bnx2x *bp,
+			struct bnx2x_virtf *vf,
+			struct bnx2x_vfop_cmd *cmd,
+			struct vfpf_tpa_tlv *tpa_tlv)
+{
+	struct bnx2x_vfop *vfop = bnx2x_vfop_add(bp, vf);
+
+	if (vfop) {
+		vfop->args.qx.qid = 0; /* loop */
+		memcpy(&vfop->args.tpa.sge_map,
+		       tpa_tlv->tpa_client_info.sge_addr,
+		       sizeof(vfop->args.tpa.sge_map));
+		bnx2x_vfop_opset(BNX2X_VFOP_TPA_CONFIG,
+				 bnx2x_vfop_tpa, cmd->done);
+		return bnx2x_vfop_transition(bp, vf, bnx2x_vfop_tpa,
+					     cmd->block);
+	}
+	return -ENOMEM;
+}
+
 /* VF release ~ VF close + VF release-resources
  * Release is the ultimate SW shutdown and is called whenever an
  * irrecoverable error is encountered.
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
index d9fcca1..9b60e80 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
@@ -100,6 +100,7 @@ union bnx2x_vfop_params {
 	struct bnx2x_mcast_ramrod_params	mcast;
 	struct bnx2x_config_rss_params		rss;
 	struct bnx2x_vfop_qctor_params		qctor;
+	struct bnx2x_queue_state_params		qstate;
 };
 
 /* forward */
@@ -166,6 +167,11 @@ struct bnx2x_vfop_args_filters {
 	atomic_t *credit;	/* non NULL means 'don't consume credit' */
 };
 
+struct bnx2x_vfop_args_tpa {
+	int	   qid;
+	dma_addr_t sge_map[PFVF_MAX_QUEUES_PER_VF];
+};
+
 union bnx2x_vfop_args {
 	struct bnx2x_vfop_args_mcast	mc_list;
 	struct bnx2x_vfop_args_qctor	qctor;
@@ -173,6 +179,7 @@ union bnx2x_vfop_args {
 	struct bnx2x_vfop_args_defvlan	defvlan;
 	struct bnx2x_vfop_args_qx	qx;
 	struct bnx2x_vfop_args_filters	filters;
+	struct bnx2x_vfop_args_tpa	tpa;
 };
 
 struct bnx2x_vfop {
@@ -704,6 +711,11 @@ int bnx2x_vfop_rss_cmd(struct bnx2x *bp,
 		       struct bnx2x_virtf *vf,
 		       struct bnx2x_vfop_cmd *cmd);
 
+int bnx2x_vfop_tpa_cmd(struct bnx2x *bp,
+		       struct bnx2x_virtf *vf,
+		       struct bnx2x_vfop_cmd *cmd,
+		       struct vfpf_tpa_tlv *tpa_tlv);
+
 /* VF release ~ VF close + VF release-resources
  *
  * Release is the ultimate SW shutdown and is called whenever an
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
index ebad48a..dfaed28 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
@@ -1159,7 +1159,8 @@ static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf,
 	resp->pfdev_info.db_size = bp->db_size;
 	resp->pfdev_info.indices_per_sb = HC_SB_MAX_INDICES_E2;
 	resp->pfdev_info.pf_cap = (PFVF_CAP_RSS |
-				   /* PFVF_CAP_DHC |*/ PFVF_CAP_TPA);
+				   PFVF_CAP_TPA |
+				   PFVF_CAP_TPA_UPDATE);
 	bnx2x_fill_fw_str(bp, resp->pfdev_info.fw_ver,
 			  sizeof(resp->pfdev_info.fw_ver));
 
@@ -1910,6 +1911,75 @@ mbx_resp:
 		bnx2x_vf_mbx_resp(bp, vf);
 }
 
+static int bnx2x_validate_tpa_params(struct bnx2x *bp,
+				       struct vfpf_tpa_tlv *tpa_tlv)
+{
+	int rc = 0;
+
+	if (tpa_tlv->tpa_client_info.max_sges_for_packet >
+	    U_ETH_MAX_SGES_FOR_PACKET) {
+		rc = -EINVAL;
+		BNX2X_ERR("TPA update: max_sges received %d, max is %d\n",
+			  tpa_tlv->tpa_client_info.max_sges_for_packet,
+			  U_ETH_MAX_SGES_FOR_PACKET);
+	}
+
+	if (tpa_tlv->tpa_client_info.max_tpa_queues > MAX_AGG_QS(bp)) {
+		rc = -EINVAL;
+		BNX2X_ERR("TPA update: max_tpa_queues received %d, max is %d\n",
+			  tpa_tlv->tpa_client_info.max_tpa_queues,
+			  MAX_AGG_QS(bp));
+	}
+
+	return rc;
+}
+
+static void bnx2x_vf_mbx_update_tpa(struct bnx2x *bp, struct bnx2x_virtf *vf,
+				    struct bnx2x_vf_mbx *mbx)
+{
+	struct bnx2x_vfop_cmd cmd = {
+		.done = bnx2x_vf_mbx_resp,
+		.block = false,
+	};
+	struct bnx2x_queue_update_tpa_params *vf_op_params =
+		&vf->op_params.qstate.params.update_tpa;
+	struct vfpf_tpa_tlv *tpa_tlv = &mbx->msg->req.update_tpa;
+
+	memset(vf_op_params, 0, sizeof(*vf_op_params));
+
+	if (bnx2x_validate_tpa_params(bp, tpa_tlv))
+		goto mbx_resp;
+
+	vf_op_params->complete_on_both_clients =
+		tpa_tlv->tpa_client_info.complete_on_both_clients;
+	vf_op_params->dont_verify_thr =
+		tpa_tlv->tpa_client_info.dont_verify_thr;
+	vf_op_params->max_agg_sz =
+		tpa_tlv->tpa_client_info.max_agg_size;
+	vf_op_params->max_sges_pkt =
+		tpa_tlv->tpa_client_info.max_sges_for_packet;
+	vf_op_params->max_tpa_queues =
+		tpa_tlv->tpa_client_info.max_tpa_queues;
+	vf_op_params->sge_buff_sz =
+		tpa_tlv->tpa_client_info.sge_buff_size;
+	vf_op_params->sge_pause_thr_high =
+		tpa_tlv->tpa_client_info.sge_pause_thr_high;
+	vf_op_params->sge_pause_thr_low =
+		tpa_tlv->tpa_client_info.sge_pause_thr_low;
+	vf_op_params->tpa_mode =
+		tpa_tlv->tpa_client_info.tpa_mode;
+	vf_op_params->update_ipv4 =
+		tpa_tlv->tpa_client_info.update_ipv4;
+	vf_op_params->update_ipv6 =
+		tpa_tlv->tpa_client_info.update_ipv6;
+
+	vf->op_rc = bnx2x_vfop_tpa_cmd(bp, vf, &cmd, tpa_tlv);
+
+mbx_resp:
+	if (vf->op_rc)
+		bnx2x_vf_mbx_resp(bp, vf);
+}
+
 /* dispatch request */
 static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
 				  struct bnx2x_vf_mbx *mbx)
@@ -1949,6 +2019,9 @@ static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
 		case CHANNEL_TLV_UPDATE_RSS:
 			bnx2x_vf_mbx_update_rss(bp, vf, mbx);
 			return;
+		case CHANNEL_TLV_UPDATE_TPA:
+			bnx2x_vf_mbx_update_tpa(bp, vf, mbx);
+			return;
 		}
 
 	} else {
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
index 208568b..c922b81 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
@@ -162,6 +162,7 @@ struct pfvf_acquire_resp_tlv {
 #define PFVF_CAP_RSS		0x00000001
 #define PFVF_CAP_DHC		0x00000002
 #define PFVF_CAP_TPA		0x00000004
+#define PFVF_CAP_TPA_UPDATE	0x00000008
 		char fw_ver[32];
 		u16 db_size;
 		u8  indices_per_sb;
@@ -303,6 +304,25 @@ struct vfpf_set_q_filters_tlv {
 	u32 rx_mask;	/* see mask constants at the top of the file */
 };
 
+struct vfpf_tpa_tlv {
+	struct vfpf_first_tlv	first_tlv;
+
+	struct vf_pf_tpa_client_info {
+		aligned_u64 sge_addr[PFVF_MAX_QUEUES_PER_VF];
+		u8 update_ipv4;
+		u8 update_ipv6;
+		u8 max_tpa_queues;
+		u8 max_sges_for_packet;
+		u8 complete_on_both_clients;
+		u8 dont_verify_thr;
+		u8 tpa_mode;
+		u16 sge_buff_size;
+		u16 max_agg_size;
+		u16 sge_pause_thr_low;
+		u16 sge_pause_thr_high;
+	} tpa_client_info;
+};
+
 /* close VF (disable VF) */
 struct vfpf_close_tlv {
 	struct vfpf_first_tlv   first_tlv;
@@ -331,6 +351,7 @@ union vfpf_tlvs {
 	struct vfpf_set_q_filters_tlv	set_q_filters;
 	struct vfpf_release_tlv		release;
 	struct vfpf_rss_tlv		update_rss;
+	struct vfpf_tpa_tlv		update_tpa;
 	struct channel_list_end_tlv	list_end;
 	struct tlv_buffer_size		tlv_buf_size;
 };
@@ -405,6 +426,7 @@ enum channel_tlvs {
 	CHANNEL_TLV_PF_SET_VLAN,
 	CHANNEL_TLV_UPDATE_RSS,
 	CHANNEL_TLV_PHYS_PORT_ID,
+	CHANNEL_TLV_UPDATE_TPA,
 	CHANNEL_TLV_MAX
 };
 
-- 
1.8.1.227.g44fe835

^ permalink raw reply related

* [PATCH net-next 3/9] bnx2x: Remove unnecessary internal mem config
From: Yuval Mintz @ 2014-02-12 16:19 UTC (permalink / raw)
  To: davem, netdev; +Cc: ariele, Yuval Mintz
In-Reply-To: <1392221997-25525-1-git-send-email-yuvalmin@broadcom.com>

From: Ariel Elior <ariele@broadcom.com>

Latest FW performs this autonomously, makes this code surplus.

Signed-off-by: Ariel Elior <ariele@broadcom.com>
Signed-off-by: Yuval Mintz <yuvalmin@broadcom.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h |  1 -
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c    | 12 ------------
 2 files changed, 13 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
index 84aecdf..95dc365 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
@@ -87,7 +87,6 @@
 	(IRO[156].base + ((vfId) * IRO[156].m1))
 #define CSTORM_VF_TO_PF_OFFSET(funcId) \
 	(IRO[150].base + ((funcId) * IRO[150].m1))
-#define TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET (IRO[204].base)
 #define TSTORM_APPROXIMATE_MATCH_MULTICAST_FILTERING_OFFSET(pfId) \
 	(IRO[203].base + ((pfId) * IRO[203].m1))
 #define TSTORM_ASSERT_LIST_INDEX_OFFSET	(IRO[102].base)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 72ff5d2..383b025 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -6005,18 +6005,6 @@ static void bnx2x_init_internal_common(struct bnx2x *bp)
 {
 	int i;
 
-	if (IS_MF_SI(bp))
-		/*
-		 * In switch independent mode, the TSTORM needs to accept
-		 * packets that failed classification, since approximate match
-		 * mac addresses aren't written to NIG LLH
-		 */
-		REG_WR8(bp, BAR_TSTRORM_INTMEM +
-			    TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET, 2);
-	else if (!CHIP_IS_E1(bp)) /* 57710 doesn't support MF */
-		REG_WR8(bp, BAR_TSTRORM_INTMEM +
-			    TSTORM_ACCEPT_CLASSIFY_FAILED_OFFSET, 0);
-
 	/* Zero this manually as its initialization is
 	   currently missing in the initTool */
 	for (i = 0; i < (USTORM_AGG_DATA_SIZE >> 2); i++)
-- 
1.8.1.227.g44fe835

^ permalink raw reply related


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