Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking update from David Miller: 1) Checkpoint/restarted TCP sockets now can properly propagate the TCP timestamp offset. From Andrey Vagin. 2) VMWARE VM VSOCK layer, from Andy King. 3) Much improved support for virtual functions and SR-IOV in bnx2x, from Ariel ELior. 4) All protocols on ipv4 and ipv6 are now network namespace aware, and all the compatability checks for initial-namespace-only protocols is removed. Thanks to Tom Parkin for helping deal with the last major holdout, L2TP. 5) IPV6 support in netpoll and network namespace support in pktgen, from Cong Wang. 6) Multiple Registration Protocol (MRP) and Multiple VLAN Registration Protocol (MVRP) support, from David Ward. 7) Compute packet lengths more accurately in the packet scheduler, from Eric Dumazet. 8) Use per-task page fragment allocator in skb_append_datato_frags(), also from Eric Dumazet. 9) Add support for connection tracking labels in netfilter, from Florian Westphal. 10) Fix default multicast group joining on ipv6, and add anti-spoofing checks to 6to4 and 6rd. From Hannes Frederic Sowa. 11) Make ipv4/ipv6 fragmentation memory limits more reasonable in modern times, rearrange inet frag datastructures for better cacheline locality, and move more operations outside of locking. From Jesper Dangaard Brouer. 12) Instead of strict master <--> slave relationships, allow arbitrary scenerios with "upper device lists". From Jiri Pirko. 13) Improve rate limiting accuracy in TBF and act_police, also from Jiri Pirko. 14) Add a BPF filter netfilter match target, from Willem de Bruijn. 15) Orphan and delete a bunch of pre-historic networking drivers from Paul Gortmaker. 16) Add TSO support for GRE tunnels, from Pravin B SHelar. Although this still needs some minor bug fixing before it's %100 correct in all cases. 17) Handle unresolved IPSEC states like ARP, with a resolution packet queue. From Steffen Klassert. 18) Remove TCP Appropriate Byte Count support (ABC), from Stephen Hemminger. This was long overdue. 19) Support SO_REUSEPORT, from Tom Herbert. 20) Allow locking a socket BPF filter, so that it cannot change after a process drops capabilities. 21) Add VLAN filtering to bridge, from Vlad Yasevich. 22) Bring ipv6 on-par with ipv4 and do not cache neighbour entries in the ipv6 routes, from YOSHIFUJI Hideaki. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1538 commits) ipv6: fix race condition regarding dst->expires and dst->from. net: fix a wrong assignment in skb_split() ip_gre: remove an extra dst_release() ppp: set qdisc_tx_busylock to avoid LOCKDEP splat atl1c: restore buffer state net: fix a build failure when !CONFIG_PROC_FS net: ipv4: fix waring -Wunused-variable net: proc: fix build failed when procfs is not configured Revert "xen: netback: remove redundant xenvif_put" net: move procfs code to net/core/net-procfs.c qmi_wwan, cdc-ether: add ADU960S bonding: set sysfs device_type to 'bond' bonding: fix bond_release_all inconsistencies b44: use netdev_alloc_skb_ip_align() xen: netback: remove redundant xenvif_put net: fec: Do a sanity check on the gpio number ip_gre: propogate target device GSO capability to the tunnel device ip_gre: allow CSUM capable devices to handle packets bonding: Fix initialize after use for 3ad machine state spinlock bonding: Fix race condition between bond_enslave() and bond_3ad_update_lacp_rate() ...
This commit is contained in:
Коммит
a0b1c42951
|
@ -107,8 +107,8 @@
|
|||
!Finclude/net/cfg80211.h key_params
|
||||
!Finclude/net/cfg80211.h survey_info_flags
|
||||
!Finclude/net/cfg80211.h survey_info
|
||||
!Finclude/net/cfg80211.h beacon_parameters
|
||||
!Finclude/net/cfg80211.h plink_actions
|
||||
!Finclude/net/cfg80211.h cfg80211_beacon_data
|
||||
!Finclude/net/cfg80211.h cfg80211_ap_settings
|
||||
!Finclude/net/cfg80211.h station_parameters
|
||||
!Finclude/net/cfg80211.h station_info_flags
|
||||
!Finclude/net/cfg80211.h rate_info_flags
|
||||
|
|
|
@ -24,6 +24,8 @@ Required properties:
|
|||
Optional properties:
|
||||
- ti,hwmods : Must be "cpgmac0"
|
||||
- no_bd_ram : Must be 0 or 1
|
||||
- dual_emac : Specifies Switch to act as Dual EMAC
|
||||
- dual_emac_res_vlan : Specifies VID to be used to segregate the ports
|
||||
|
||||
Note: "ti,hwmods" field is used to fetch the base address and irq
|
||||
resources from TI, omap hwmod data base during device registration.
|
||||
|
|
|
@ -179,7 +179,7 @@ Code Seq#(hex) Include File Comments
|
|||
'V' C0 media/davinci/vpfe_capture.h conflict!
|
||||
'V' C0 media/si4713.h conflict!
|
||||
'W' 00-1F linux/watchdog.h conflict!
|
||||
'W' 00-1F linux/wanrouter.h conflict!
|
||||
'W' 00-1F linux/wanrouter.h conflict! (pre 3.9)
|
||||
'W' 00-3F sound/asound.h conflict!
|
||||
'X' all fs/xfs/xfs_fs.h conflict!
|
||||
and fs/xfs/linux-2.6/xfs_ioctl32.h
|
||||
|
|
|
@ -122,7 +122,7 @@ SLAB_C_MAGIC 0x4f17a36d kmem_cache mm/slab.c
|
|||
COW_MAGIC 0x4f4f4f4d cow_header_v1 arch/um/drivers/ubd_user.c
|
||||
I810_CARD_MAGIC 0x5072696E i810_card sound/oss/i810_audio.c
|
||||
TRIDENT_CARD_MAGIC 0x5072696E trident_card sound/oss/trident.c
|
||||
ROUTER_MAGIC 0x524d4157 wan_device include/linux/wanrouter.h
|
||||
ROUTER_MAGIC 0x524d4157 wan_device [in wanrouter.h pre 3.9]
|
||||
SCC_MAGIC 0x52696368 gs_port drivers/char/scc.h
|
||||
SAVEKMSG_MAGIC1 0x53415645 savekmsg arch/*/amiga/config.c
|
||||
GDA_MAGIC 0x58464552 gda arch/mips/include/asm/sn/gda.h
|
||||
|
|
|
@ -52,8 +52,6 @@ de4x5.txt
|
|||
- the Digital EtherWORKS DE4?? and DE5?? PCI Ethernet driver
|
||||
decnet.txt
|
||||
- info on using the DECnet networking layer in Linux.
|
||||
depca.txt
|
||||
- the Digital DEPCA/EtherWORKS DE1?? and DE2?? LANCE Ethernet driver
|
||||
dl2k.txt
|
||||
- README for D-Link DL2000-based Gigabit Ethernet Adapters (dl2k.ko).
|
||||
dm9000.txt
|
||||
|
@ -72,8 +70,6 @@ e1000e.txt
|
|||
- README for the Intel Gigabit Ethernet Driver (e1000e).
|
||||
eql.txt
|
||||
- serial IP load balancing
|
||||
ewrk3.txt
|
||||
- the Digital EtherWORKS 3 DE203/4/5 Ethernet driver
|
||||
fib_trie.txt
|
||||
- Level Compressed Trie (LC-trie) notes: a structure for routing.
|
||||
filter.txt
|
||||
|
@ -126,8 +122,6 @@ ltpc.txt
|
|||
- the Apple or Farallon LocalTalk PC card driver
|
||||
mac80211-injection.txt
|
||||
- HOWTO use packet injection with mac80211
|
||||
multicast.txt
|
||||
- Behaviour of cards under Multicast
|
||||
multiqueue.txt
|
||||
- HOWTO for multiqueue network device support.
|
||||
netconsole.txt
|
||||
|
|
|
@ -1,203 +0,0 @@
|
|||
Released 1994-06-13
|
||||
|
||||
|
||||
CONTENTS:
|
||||
|
||||
1. Introduction.
|
||||
2. License.
|
||||
3. Files in this release.
|
||||
4. Installation.
|
||||
5. Problems and tuning.
|
||||
6. Using the drivers with earlier releases.
|
||||
7. Acknowledgments.
|
||||
|
||||
|
||||
1. INTRODUCTION.
|
||||
|
||||
This is a set of Ethernet drivers for the D-Link DE-600/DE-620
|
||||
pocket adapters, for the parallel port on a Linux based machine.
|
||||
Some adapter "clones" will also work. Xircom is _not_ a clone...
|
||||
These drivers _can_ be used as loadable modules,
|
||||
and were developed for use on Linux 1.1.13 and above.
|
||||
For use on Linux 1.0.X, or earlier releases, see below.
|
||||
|
||||
I have used these drivers for NFS, ftp, telnet and X-clients on
|
||||
remote machines. Transmissions with ftp seems to work as
|
||||
good as can be expected (i.e. > 80k bytes/sec) from a
|
||||
parallel port...:-) Receive speeds will be about 60-80% of this.
|
||||
Depending on your machine, somewhat higher speeds can be achieved.
|
||||
|
||||
All comments/fixes to Bjorn Ekwall (bj0rn@blox.se).
|
||||
|
||||
|
||||
2. LICENSE.
|
||||
|
||||
This program is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
|
||||
02139, USA.
|
||||
|
||||
|
||||
3. FILES IN THIS RELEASE.
|
||||
|
||||
README.DLINK This file.
|
||||
de600.c The Source (may it be with You :-) for the DE-600
|
||||
de620.c ditto for the DE-620
|
||||
de620.h Macros for de620.c
|
||||
|
||||
If you are upgrading from the d-link tar release, there will
|
||||
also be a "dlink-patches" file that will patch Linux 1.1.18:
|
||||
linux/drivers/net/Makefile
|
||||
linux/drivers/net/CONFIG
|
||||
linux/drivers/net/MODULES
|
||||
linux/drivers/net/Space.c
|
||||
linux/config.in
|
||||
Apply the patch by:
|
||||
"cd /usr/src; patch -p0 < linux/drivers/net/dlink-patches"
|
||||
The old source, "linux/drivers/net/d_link.c", can be removed.
|
||||
|
||||
|
||||
4. INSTALLATION.
|
||||
|
||||
o Get the latest net binaries, according to current net.wisdom.
|
||||
|
||||
o Read the NET-2 and Ethernet HOWTOs and modify your setup.
|
||||
|
||||
o If your parallel port has a strange address or irq,
|
||||
modify "linux/drivers/net/CONFIG" accordingly, or adjust
|
||||
the parameters in the "tuning" section in the sources.
|
||||
|
||||
If you are going to use the drivers as loadable modules, do _not_
|
||||
enable them while doing "make config", but instead make sure that
|
||||
the drivers are included in "linux/drivers/net/MODULES".
|
||||
|
||||
If you are _not_ going to use the driver(s) as loadable modules,
|
||||
but instead have them included in the kernel, remember to enable
|
||||
the drivers while doing "make config".
|
||||
|
||||
o To include networking and DE600/DE620 support in your kernel:
|
||||
# cd /linux
|
||||
(as modules:)
|
||||
# make config (answer yes on CONFIG_NET and CONFIG_INET)
|
||||
(else included in the kernel:)
|
||||
# make config (answer yes on CONFIG _NET, _INET and _DE600 or _DE620)
|
||||
# make clean
|
||||
# make zImage (or whatever magic you usually do)
|
||||
|
||||
o I use lilo to boot multiple kernels, so that I at least
|
||||
can have one working kernel :-). If you do too, append
|
||||
these lines to /etc/lilo/config:
|
||||
|
||||
image = /linux/zImage
|
||||
label = newlinux
|
||||
root = /dev/hda2 (or whatever YOU have...)
|
||||
|
||||
# /etc/lilo/install
|
||||
|
||||
o Do "sync" and reboot the new kernel with a D-Link
|
||||
DE-600/DE-620 pocket adapter connected.
|
||||
|
||||
o The adapter can be configured with ifconfig eth?
|
||||
where the actual number is decided by the kernel
|
||||
when the drivers are initialized.
|
||||
|
||||
|
||||
5. "PROBLEMS" AND TUNING,
|
||||
|
||||
o If you see error messages from the driver, and if the traffic
|
||||
stops on the adapter, try to do "ifconfig" and "route" once
|
||||
more, just as in "rc.inet1". This should take care of most
|
||||
problems, including effects from power loss, or adapters that
|
||||
aren't connected to the printer port in some way or another.
|
||||
You can somewhat change the behaviour by enabling/disabling
|
||||
the macro SHUTDOWN_WHEN_LOST in the "tuning" section.
|
||||
For the DE-600 there is another macro, CHECK_LOST_DE600,
|
||||
that you might want to read about in the "tuning" section.
|
||||
|
||||
o Some machines have trouble handling the parallel port and
|
||||
the adapter at high speed. If you experience problems:
|
||||
|
||||
DE-600:
|
||||
- The adapter is not recognized at boot, i.e. an Ethernet
|
||||
address of 00:80:c8:... is not shown, try to add another
|
||||
"; SLOW_DOWN_IO"
|
||||
at DE600_SLOW_DOWN in the "tuning" section. As a last resort,
|
||||
uncomment: "#define REALLY_SLOW_IO" (see <asm/io.h> for hints).
|
||||
|
||||
- You experience "timeout" messages: first try to add another
|
||||
"; SLOW_DOWN_IO"
|
||||
at DE600_SLOW_DOWN in the "tuning" section, _then_ try to
|
||||
increase the value (original value: 5) at
|
||||
"if (tickssofar < 5)" near line 422.
|
||||
|
||||
DE-620:
|
||||
- Your parallel port might be "sluggish". To cater for
|
||||
this, there are the macros LOWSPEED and READ_DELAY/WRITE_DELAY
|
||||
in the "tuning" section. Your first step should be to enable
|
||||
LOWSPEED, and after that you can "tune" the XXX_DELAY values.
|
||||
|
||||
o If the adapter _is_ recognized at boot but you get messages
|
||||
about "Network Unreachable", then the problem is probably
|
||||
_not_ with the driver. Check your net configuration instead
|
||||
(ifconfig and route) in "rc.inet1".
|
||||
|
||||
o There is some rudimentary support for debugging, look at
|
||||
the source. Use "-DDE600_DEBUG=3" or "-DDE620_DEBUG=3"
|
||||
when compiling, or include it in "linux/drivers/net/CONFIG".
|
||||
IF YOU HAVE PROBLEMS YOU CAN'T SOLVE: PLEASE COMPILE THE DRIVER
|
||||
WITH DEBUGGING ENABLED, AND SEND ME THE RESULTING OUTPUT!
|
||||
|
||||
|
||||
6. USING THE DRIVERS WITH EARLIER RELEASES.
|
||||
|
||||
The later 1.1.X releases of the Linux kernel include some
|
||||
changes in the networking layer (a.k.a. NET3). This affects
|
||||
these drivers in a few places. The hints that follow are
|
||||
_not_ tested by me, since I don't have the disk space to keep
|
||||
all releases on-line.
|
||||
Known needed changes to date:
|
||||
- release patchfile: some patches will fail, but they should
|
||||
be easy to apply "by hand", since they are trivial.
|
||||
(Space.c: d_link_init() is now called de600_probe())
|
||||
- de600.c: change "mark_bh(NET_BH)" to "mark_bh(INET_BH)".
|
||||
- de620.c: (maybe) change the code around "netif_rx(skb);" to be
|
||||
similar to the code around "dev_rint(...)" in de600.c
|
||||
|
||||
|
||||
7. ACKNOWLEDGMENTS.
|
||||
|
||||
These drivers wouldn't have been done without the base
|
||||
(and support) from Ross Biro, and D-Link Systems Inc.
|
||||
The driver relies upon GPL-ed source from D-Link Systems Inc.
|
||||
and from Russel Nelson at Crynwr Software <nelson@crynwr.com>.
|
||||
|
||||
Additional input also from:
|
||||
Donald Becker <becker@super.org>, Alan Cox <A.Cox@swansea.ac.uk>
|
||||
and Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG>
|
||||
|
||||
DE-600 alpha release primary victim^H^H^H^H^H^Htester:
|
||||
- Erik Proper <erikp@cs.kun.nl>.
|
||||
Good input also from several users, most notably
|
||||
- Mark Burton <markb@ordern.demon.co.uk>.
|
||||
|
||||
DE-620 alpha release victims^H^H^H^H^H^H^Htesters:
|
||||
- J. Joshua Kopper <kopper@rtsg.mot.com>
|
||||
- Olav Kvittem <Olav.Kvittem@uninett.no>
|
||||
- Germano Caronni <caronni@nessie.cs.id.ethz.ch>
|
||||
- Jeremy Fitzhardinge <jeremy@suite.sw.oz.au>
|
||||
|
||||
|
||||
Happy hacking!
|
||||
|
||||
Bjorn Ekwall == bj0rn@blox.se
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2009-2011 QLogic Corporation
|
||||
Copyright (c) 2009-2013 QLogic Corporation
|
||||
QLogic Linux qlcnic NIC Driver
|
||||
|
||||
You may modify and redistribute the device driver code under the
|
||||
|
|
|
@ -36,7 +36,6 @@ TABLE OF CONTENTS
|
|||
4.1 Compiling the Driver as a Loadable Module
|
||||
4.2 Compiling the driver to support memory mode
|
||||
4.3 Compiling the driver to support Rx DMA
|
||||
4.4 Compiling the Driver into the Kernel
|
||||
|
||||
5.0 TESTING AND TROUBLESHOOTING
|
||||
5.1 Known Defects and Limitations
|
||||
|
@ -364,84 +363,6 @@ The compile-time optionality for DMA was removed in the 2.3 kernel
|
|||
series. DMA support is now unconditionally part of the driver. It is
|
||||
enabled by the 'use_dma=1' module option.
|
||||
|
||||
4.4 COMPILING THE DRIVER INTO THE KERNEL
|
||||
|
||||
If your Linux distribution already has support for the cs89x0 driver
|
||||
then simply copy the source file to the /usr/src/linux/drivers/net
|
||||
directory to replace the original ones and run the make utility to
|
||||
rebuild the kernel. See Step 3 for rebuilding the kernel.
|
||||
|
||||
If your Linux does not include the cs89x0 driver, you need to edit three
|
||||
configuration files, copy the source file to the /usr/src/linux/drivers/net
|
||||
directory, and then run the make utility to rebuild the kernel.
|
||||
|
||||
1. Edit the following configuration files by adding the statements as
|
||||
indicated. (When possible, try to locate the added text to the section of the
|
||||
file containing similar statements).
|
||||
|
||||
|
||||
a.) In /usr/src/linux/drivers/net/Config.in, add:
|
||||
|
||||
tristate 'CS89x0 support' CONFIG_CS89x0
|
||||
|
||||
Example:
|
||||
|
||||
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
|
||||
tristate 'ICL EtherTeam 16i/32 support' CONFIG_ETH16I
|
||||
fi
|
||||
|
||||
tristate 'CS89x0 support' CONFIG_CS89x0
|
||||
|
||||
tristate 'NE2000/NE1000 support' CONFIG_NE2000
|
||||
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
|
||||
tristate 'NI5210 support' CONFIG_NI52
|
||||
|
||||
|
||||
b.) In /usr/src/linux/drivers/net/Makefile, add the following lines:
|
||||
|
||||
ifeq ($(CONFIG_CS89x0),y)
|
||||
L_OBJS += cs89x0.o
|
||||
else
|
||||
ifeq ($(CONFIG_CS89x0),m)
|
||||
M_OBJS += cs89x0.o
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
c.) In /linux/drivers/net/Space.c file, add the line:
|
||||
|
||||
extern int cs89x0_probe(struct device *dev);
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
extern int ultra_probe(struct device *dev);
|
||||
extern int wd_probe(struct device *dev);
|
||||
extern int el2_probe(struct device *dev);
|
||||
|
||||
extern int cs89x0_probe(struct device *dev);
|
||||
|
||||
extern int ne_probe(struct device *dev);
|
||||
extern int hp_probe(struct device *dev);
|
||||
extern int hp_plus_probe(struct device *dev);
|
||||
|
||||
|
||||
Also add:
|
||||
|
||||
#ifdef CONFIG_CS89x0
|
||||
{ cs89x0_probe,0 },
|
||||
#endif
|
||||
|
||||
|
||||
2.) Copy the driver source files (cs89x0.c and cs89x0.h)
|
||||
into the /usr/src/linux/drivers/net directory.
|
||||
|
||||
|
||||
3.) Go to /usr/src/linux directory and run 'make config' followed by 'make'
|
||||
(or make bzImage) to rebuild the kernel.
|
||||
|
||||
4.) Use the DOS 'setup' utility to disable plug and play on the NIC.
|
||||
|
||||
|
||||
5.0 TESTING AND TROUBLESHOOTING
|
||||
===============================================================================
|
||||
|
|
|
@ -1,92 +0,0 @@
|
|||
|
||||
DE10x
|
||||
=====
|
||||
|
||||
Memory Addresses:
|
||||
|
||||
SW1 SW2 SW3 SW4
|
||||
64K on on on on d0000 dbfff
|
||||
off on on on c0000 cbfff
|
||||
off off on on e0000 ebfff
|
||||
|
||||
32K on on off on d8000 dbfff
|
||||
off on off on c8000 cbfff
|
||||
off off off on e8000 ebfff
|
||||
|
||||
DBR ROM on on dc000 dffff
|
||||
off on cc000 cffff
|
||||
off off ec000 effff
|
||||
|
||||
Note that the 2K mode is set by SW3/SW4 on/off or off/off. Address
|
||||
assignment is through the RBSA register.
|
||||
|
||||
I/O Address:
|
||||
SW5
|
||||
0x300 on
|
||||
0x200 off
|
||||
|
||||
Remote Boot:
|
||||
SW6
|
||||
Disable on
|
||||
Enable off
|
||||
|
||||
Remote Boot Timeout:
|
||||
SW7
|
||||
2.5min on
|
||||
30s off
|
||||
|
||||
IRQ:
|
||||
SW8 SW9 SW10 SW11 SW12
|
||||
2 on off off off off
|
||||
3 off on off off off
|
||||
4 off off on off off
|
||||
5 off off off on off
|
||||
7 off off off off on
|
||||
|
||||
DE20x
|
||||
=====
|
||||
|
||||
Memory Size:
|
||||
|
||||
SW3 SW4
|
||||
64K on on
|
||||
32K off on
|
||||
2K on off
|
||||
2K off off
|
||||
|
||||
Start Addresses:
|
||||
|
||||
SW1 SW2 SW3 SW4
|
||||
64K on on on on c0000 cffff
|
||||
on off on on d0000 dffff
|
||||
off on on on e0000 effff
|
||||
|
||||
32K on on off off c8000 cffff
|
||||
on off off off d8000 dffff
|
||||
off on off off e8000 effff
|
||||
|
||||
Illegal off off - - - -
|
||||
|
||||
I/O Address:
|
||||
SW5
|
||||
0x300 on
|
||||
0x200 off
|
||||
|
||||
Remote Boot:
|
||||
SW6
|
||||
Disable on
|
||||
Enable off
|
||||
|
||||
Remote Boot Timeout:
|
||||
SW7
|
||||
2.5min on
|
||||
30s off
|
||||
|
||||
IRQ:
|
||||
SW8 SW9 SW10 SW11 SW12
|
||||
5 on off off off off
|
||||
9 off on off off off
|
||||
10 off off on off off
|
||||
11 off off off on off
|
||||
15 off off off off on
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
The EtherWORKS 3 driver in this distribution is designed to work with all
|
||||
kernels > 1.1.33 (approx) and includes tools in the 'ewrk3tools'
|
||||
subdirectory to allow set up of the card, similar to the MSDOS
|
||||
'NICSETUP.EXE' tools provided on the DOS drivers disk (type 'make' in that
|
||||
subdirectory to make the tools).
|
||||
|
||||
The supported cards are DE203, DE204 and DE205. All other cards are NOT
|
||||
supported - refer to 'depca.c' for running the LANCE based network cards and
|
||||
'de4x5.c' for the DIGITAL Semiconductor PCI chip based adapters from
|
||||
Digital.
|
||||
|
||||
The ability to load this driver as a loadable module has been included and
|
||||
used extensively during the driver development (to save those long reboot
|
||||
sequences). To utilise this ability, you have to do 8 things:
|
||||
|
||||
0) have a copy of the loadable modules code installed on your system.
|
||||
1) copy ewrk3.c from the /linux/drivers/net directory to your favourite
|
||||
temporary directory.
|
||||
2) edit the source code near line 1898 to reflect the I/O address and
|
||||
IRQ you're using.
|
||||
3) compile ewrk3.c, but include -DMODULE in the command line to ensure
|
||||
that the correct bits are compiled (see end of source code).
|
||||
4) if you are wanting to add a new card, goto 5. Otherwise, recompile a
|
||||
kernel with the ewrk3 configuration turned off and reboot.
|
||||
5) insmod ewrk3.o
|
||||
[Alan Cox: Changed this so you can insmod ewrk3.o irq=x io=y]
|
||||
[Adam Kropelin: Multiple cards now supported by irq=x1,x2 io=y1,y2]
|
||||
6) run the net startup bits for your new eth?? interface manually
|
||||
(usually /etc/rc.inet[12] at boot time).
|
||||
7) enjoy!
|
||||
|
||||
Note that autoprobing is not allowed in loadable modules - the system is
|
||||
already up and running and you're messing with interrupts.
|
||||
|
||||
To unload a module, turn off the associated interface
|
||||
'ifconfig eth?? down' then 'rmmod ewrk3'.
|
||||
|
||||
The performance we've achieved so far has been measured through the 'ttcp'
|
||||
tool at 975kB/s. This measures the total TCP stack performance which
|
||||
includes the card, so don't expect to get much nearer the 1.25MB/s
|
||||
theoretical Ethernet rate.
|
||||
|
||||
|
||||
Enjoy!
|
||||
|
||||
Dave
|
|
@ -17,12 +17,12 @@ creating filters.
|
|||
|
||||
LSF is much simpler than BPF. One does not have to worry about
|
||||
devices or anything like that. You simply create your filter
|
||||
code, send it to the kernel via the SO_ATTACH_FILTER ioctl and
|
||||
code, send it to the kernel via the SO_ATTACH_FILTER option and
|
||||
if your filter code passes the kernel check on it, you then
|
||||
immediately begin filtering data on that socket.
|
||||
|
||||
You can also detach filters from your socket via the
|
||||
SO_DETACH_FILTER ioctl. This will probably not be used much
|
||||
SO_DETACH_FILTER option. This will probably not be used much
|
||||
since when you close a socket that has a filter on it the
|
||||
filter is automagically removed. The other less common case
|
||||
may be adding a different filter on the same socket where you had another
|
||||
|
@ -31,12 +31,19 @@ the old one and placing your new one in its place, assuming your
|
|||
filter has passed the checks, otherwise if it fails the old filter
|
||||
will remain on that socket.
|
||||
|
||||
SO_LOCK_FILTER option allows to lock the filter attached to a
|
||||
socket. Once set, a filter cannot be removed or changed. This allows
|
||||
one process to setup a socket, attach a filter, lock it then drop
|
||||
privileges and be assured that the filter will be kept until the
|
||||
socket is closed.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
Ioctls-
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_ATTACH_FILTER, &Filter, sizeof(Filter));
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_DETACH_FILTER, &value, sizeof(value));
|
||||
setsockopt(sockfd, SOL_SOCKET, SO_LOCK_FILTER, &value, sizeof(value));
|
||||
|
||||
See the BSD bpf.4 manpage and the BSD Packet Filter paper written by
|
||||
Steven McCanne and Van Jacobson of Lawrence Berkeley Laboratory.
|
||||
|
|
|
@ -26,6 +26,11 @@ route/max_size - INTEGER
|
|||
Maximum number of routes allowed in the kernel. Increase
|
||||
this when using large numbers of interfaces and/or routes.
|
||||
|
||||
neigh/default/gc_thresh1 - INTEGER
|
||||
Minimum number of entries to keep. Garbage collector will not
|
||||
purge entries if there are fewer than this number.
|
||||
Default: 256
|
||||
|
||||
neigh/default/gc_thresh3 - INTEGER
|
||||
Maximum number of neighbor entries allowed. Increase this
|
||||
when using large numbers of interfaces and when communicating
|
||||
|
@ -125,17 +130,6 @@ somaxconn - INTEGER
|
|||
Defaults to 128. See also tcp_max_syn_backlog for additional tuning
|
||||
for TCP sockets.
|
||||
|
||||
tcp_abc - INTEGER
|
||||
Controls Appropriate Byte Count (ABC) defined in RFC3465.
|
||||
ABC is a way of increasing congestion window (cwnd) more slowly
|
||||
in response to partial acknowledgments.
|
||||
Possible values are:
|
||||
0 increase cwnd once per acknowledgment (no ABC)
|
||||
1 increase cwnd once per acknowledgment of full sized segment
|
||||
2 allow increase cwnd by two if acknowledgment is
|
||||
of two segments to compensate for delayed acknowledgments.
|
||||
Default: 0 (off)
|
||||
|
||||
tcp_abort_on_overflow - BOOLEAN
|
||||
If listening service is too slow to accept new connections,
|
||||
reset them. Default state is FALSE. It means that if overflow
|
||||
|
@ -214,7 +208,8 @@ tcp_ecn - INTEGER
|
|||
congestion before having to drop packets.
|
||||
Possible values are:
|
||||
0 Disable ECN. Neither initiate nor accept ECN.
|
||||
1 Always request ECN on outgoing connection attempts.
|
||||
1 Enable ECN when requested by incoming connections and
|
||||
also request ECN on outgoing connection attempts.
|
||||
2 Enable ECN when requested by incoming connections
|
||||
but do not request ECN on outgoing connections.
|
||||
Default: 2
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
Behaviour of Cards Under Multicast
|
||||
==================================
|
||||
|
||||
This is how they currently behave, not what the hardware can do--for example,
|
||||
the Lance driver doesn't use its filter, even though the code for loading
|
||||
it is in the DEC Lance-based driver.
|
||||
|
||||
The following are requirements for multicasting
|
||||
-----------------------------------------------
|
||||
AppleTalk Multicast hardware filtering not important but
|
||||
avoid cards only doing promisc
|
||||
IP-Multicast Multicast hardware filters really help
|
||||
IP-MRoute AllMulti hardware filters are of no help
|
||||
|
||||
|
||||
Board Multicast AllMulti Promisc Filter
|
||||
------------------------------------------------------------------------
|
||||
3c501 YES YES YES Software
|
||||
3c503 YES YES YES Hardware
|
||||
3c505 YES NO YES Hardware
|
||||
3c507 NO NO NO N/A
|
||||
3c509 YES YES YES Software
|
||||
3c59x YES YES YES Software
|
||||
ac3200 YES YES YES Hardware
|
||||
apricot YES PROMISC YES Hardware
|
||||
arcnet NO NO NO N/A
|
||||
at1700 PROMISC PROMISC YES Software
|
||||
atp PROMISC PROMISC YES Software
|
||||
cs89x0 YES YES YES Software
|
||||
de4x5 YES YES YES Hardware
|
||||
de600 NO NO NO N/A
|
||||
de620 PROMISC PROMISC YES Software
|
||||
depca YES PROMISC YES Hardware
|
||||
dmfe YES YES YES Software(*)
|
||||
e2100 YES YES YES Hardware
|
||||
eepro YES PROMISC YES Hardware
|
||||
eexpress NO NO NO N/A
|
||||
ewrk3 YES PROMISC YES Hardware
|
||||
hp-plus YES YES YES Hardware
|
||||
hp YES YES YES Hardware
|
||||
hp100 YES YES YES Hardware
|
||||
ibmtr NO NO NO N/A
|
||||
ioc3-eth YES YES YES Hardware
|
||||
lance YES YES YES Software(#)
|
||||
ne YES YES YES Hardware
|
||||
ni52 <------------------ Buggy ------------------>
|
||||
ni65 YES YES YES Software(#)
|
||||
seeq NO NO NO N/A
|
||||
sgiseek <------------------ Buggy ------------------>
|
||||
smc-ultra YES YES YES Hardware
|
||||
sunlance YES YES YES Hardware
|
||||
tulip YES YES YES Hardware
|
||||
wavelan YES PROMISC YES Hardware
|
||||
wd YES YES YES Hardware
|
||||
xirc2ps_cs YES YES YES Hardware
|
||||
znet YES YES YES Software
|
||||
|
||||
|
||||
PROMISC = This multicast mode is in fact promiscuous mode. Avoid using
|
||||
cards who go PROMISC on any multicast in a multicast kernel.
|
||||
|
||||
(#) = Hardware multicast support is not used yet.
|
||||
(*) = Hardware support for Davicom 9132 chipset only.
|
|
@ -1,9 +1,10 @@
|
|||
|
||||
started by Ingo Molnar <mingo@redhat.com>, 2001.09.17
|
||||
2.6 port and netpoll api by Matt Mackall <mpm@selenic.com>, Sep 9 2003
|
||||
IPv6 support by Cong Wang <xiyou.wangcong@gmail.com>, Jan 1 2013
|
||||
|
||||
Please send bug reports to Matt Mackall <mpm@selenic.com>
|
||||
and Satyam Sharma <satyam.sharma@gmail.com>
|
||||
Satyam Sharma <satyam.sharma@gmail.com>, and Cong Wang <xiyou.wangcong@gmail.com>
|
||||
|
||||
Introduction:
|
||||
=============
|
||||
|
@ -41,6 +42,10 @@ Examples:
|
|||
|
||||
insmod netconsole netconsole=@/,@10.0.0.2/
|
||||
|
||||
or using IPv6
|
||||
|
||||
insmod netconsole netconsole=@/,@fd00:1:2:3::1/
|
||||
|
||||
It also supports logging to multiple remote agents by specifying
|
||||
parameters for the multiple agents separated by semicolons and the
|
||||
complete string enclosed in "quotes", thusly:
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
/proc/sys/net/netfilter/nf_conntrack_* Variables:
|
||||
|
||||
nf_conntrack_acct - BOOLEAN
|
||||
0 - disabled (default)
|
||||
not 0 - enabled
|
||||
|
||||
Enable connection tracking flow accounting. 64-bit byte and packet
|
||||
counters per flow are added.
|
||||
|
||||
nf_conntrack_buckets - INTEGER (read-only)
|
||||
Size of hash table. If not specified as parameter during module
|
||||
loading, the default size is calculated by dividing total memory
|
||||
by 16384 to determine the number of buckets but the hash table will
|
||||
never have fewer than 32 or more than 16384 buckets.
|
||||
|
||||
nf_conntrack_checksum - BOOLEAN
|
||||
0 - disabled
|
||||
not 0 - enabled (default)
|
||||
|
||||
Verify checksum of incoming packets. Packets with bad checksums are
|
||||
in INVALID state. If this is enabled, such packets will not be
|
||||
considered for connection tracking.
|
||||
|
||||
nf_conntrack_count - INTEGER (read-only)
|
||||
Number of currently allocated flow entries.
|
||||
|
||||
nf_conntrack_events - BOOLEAN
|
||||
0 - disabled
|
||||
not 0 - enabled (default)
|
||||
|
||||
If this option is enabled, the connection tracking code will
|
||||
provide userspace with connection tracking events via ctnetlink.
|
||||
|
||||
nf_conntrack_events_retry_timeout - INTEGER (seconds)
|
||||
default 15
|
||||
|
||||
This option is only relevant when "reliable connection tracking
|
||||
events" are used. Normally, ctnetlink is "lossy", that is,
|
||||
events are normally dropped when userspace listeners can't keep up.
|
||||
|
||||
Userspace can request "reliable event mode". When this mode is
|
||||
active, the conntrack will only be destroyed after the event was
|
||||
delivered. If event delivery fails, the kernel periodically
|
||||
re-tries to send the event to userspace.
|
||||
|
||||
This is the maximum interval the kernel should use when re-trying
|
||||
to deliver the destroy event.
|
||||
|
||||
A higher number means there will be fewer delivery retries and it
|
||||
will take longer for a backlog to be processed.
|
||||
|
||||
nf_conntrack_expect_max - INTEGER
|
||||
Maximum size of expectation table. Default value is
|
||||
nf_conntrack_buckets / 256. Minimum is 1.
|
||||
|
||||
nf_conntrack_frag6_high_thresh - INTEGER
|
||||
default 262144
|
||||
|
||||
Maximum memory used to reassemble IPv6 fragments. When
|
||||
nf_conntrack_frag6_high_thresh bytes of memory is allocated for this
|
||||
purpose, the fragment handler will toss packets until
|
||||
nf_conntrack_frag6_low_thresh is reached.
|
||||
|
||||
nf_conntrack_frag6_low_thresh - INTEGER
|
||||
default 196608
|
||||
|
||||
See nf_conntrack_frag6_low_thresh
|
||||
|
||||
nf_conntrack_frag6_timeout - INTEGER (seconds)
|
||||
default 60
|
||||
|
||||
Time to keep an IPv6 fragment in memory.
|
||||
|
||||
nf_conntrack_generic_timeout - INTEGER (seconds)
|
||||
default 600
|
||||
|
||||
Default for generic timeout. This refers to layer 4 unknown/unsupported
|
||||
protocols.
|
||||
|
||||
nf_conntrack_helper - BOOLEAN
|
||||
0 - disabled
|
||||
not 0 - enabled (default)
|
||||
|
||||
Enable automatic conntrack helper assignment.
|
||||
|
||||
nf_conntrack_icmp_timeout - INTEGER (seconds)
|
||||
default 30
|
||||
|
||||
Default for ICMP timeout.
|
||||
|
||||
nf_conntrack_icmpv6_timeout - INTEGER (seconds)
|
||||
default 30
|
||||
|
||||
Default for ICMP6 timeout.
|
||||
|
||||
nf_conntrack_log_invalid - INTEGER
|
||||
0 - disable (default)
|
||||
1 - log ICMP packets
|
||||
6 - log TCP packets
|
||||
17 - log UDP packets
|
||||
33 - log DCCP packets
|
||||
41 - log ICMPv6 packets
|
||||
136 - log UDPLITE packets
|
||||
255 - log packets of any protocol
|
||||
|
||||
Log invalid packets of a type specified by value.
|
||||
|
||||
nf_conntrack_max - INTEGER
|
||||
Size of connection tracking table. Default value is
|
||||
nf_conntrack_buckets value * 4.
|
||||
|
||||
nf_conntrack_tcp_be_liberal - BOOLEAN
|
||||
0 - disabled (default)
|
||||
not 0 - enabled
|
||||
|
||||
Be conservative in what you do, be liberal in what you accept from others.
|
||||
If it's non-zero, we mark only out of window RST segments as INVALID.
|
||||
|
||||
nf_conntrack_tcp_loose - BOOLEAN
|
||||
0 - disabled
|
||||
not 0 - enabled (default)
|
||||
|
||||
If it is set to zero, we disable picking up already established
|
||||
connections.
|
||||
|
||||
nf_conntrack_tcp_max_retrans - INTEGER
|
||||
default 3
|
||||
|
||||
Maximum number of packets that can be retransmitted without
|
||||
received an (acceptable) ACK from the destination. If this number
|
||||
is reached, a shorter timer will be started.
|
||||
|
||||
nf_conntrack_tcp_timeout_close - INTEGER (seconds)
|
||||
default 10
|
||||
|
||||
nf_conntrack_tcp_timeout_close_wait - INTEGER (seconds)
|
||||
default 60
|
||||
|
||||
nf_conntrack_tcp_timeout_established - INTEGER (seconds)
|
||||
default 432000 (5 days)
|
||||
|
||||
nf_conntrack_tcp_timeout_fin_wait - INTEGER (seconds)
|
||||
default 120
|
||||
|
||||
nf_conntrack_tcp_timeout_last_ack - INTEGER (seconds)
|
||||
default 30
|
||||
|
||||
nf_conntrack_tcp_timeout_max_retrans - INTEGER (seconds)
|
||||
default 300
|
||||
|
||||
nf_conntrack_tcp_timeout_syn_recv - INTEGER (seconds)
|
||||
default 60
|
||||
|
||||
nf_conntrack_tcp_timeout_syn_sent - INTEGER (seconds)
|
||||
default 120
|
||||
|
||||
nf_conntrack_tcp_timeout_time_wait - INTEGER (seconds)
|
||||
default 120
|
||||
|
||||
nf_conntrack_tcp_timeout_unacknowledged - INTEGER (seconds)
|
||||
default 300
|
||||
|
||||
nf_conntrack_timestamp - BOOLEAN
|
||||
0 - disabled (default)
|
||||
not 0 - enabled
|
||||
|
||||
Enable connection tracking flow timestamping.
|
||||
|
||||
nf_conntrack_udp_timeout - INTEGER (seconds)
|
||||
default 30
|
||||
|
||||
nf_conntrack_udp_timeout_stream2 - INTEGER (seconds)
|
||||
default 180
|
||||
|
||||
This extended timeout will be used in case there is an UDP stream
|
||||
detected.
|
|
@ -88,6 +88,10 @@ set this flag. On netif_carrier_off(), the scheduler stops sending
|
|||
packets. The name 'carrier' and the inversion are historical, think of
|
||||
it as lower layer.
|
||||
|
||||
Note that for certain kind of soft-devices, which are not managing any
|
||||
real hardware, there is possible to set this bit from userpsace.
|
||||
One should use TVL IFLA_CARRIER to do so.
|
||||
|
||||
netif_carrier_ok() can be used to query that bit.
|
||||
|
||||
__LINK_STATE_DORMANT, maps to IFF_DORMANT:
|
||||
|
|
|
@ -103,7 +103,7 @@ Letting the PHY Abstraction Layer do Everything
|
|||
|
||||
Now, to connect, just call this function:
|
||||
|
||||
phydev = phy_connect(dev, phy_name, &adjust_link, flags, interface);
|
||||
phydev = phy_connect(dev, phy_name, &adjust_link, interface);
|
||||
|
||||
phydev is a pointer to the phy_device structure which represents the PHY. If
|
||||
phy_connect is successful, it will return the pointer. dev, here, is the
|
||||
|
@ -113,7 +113,9 @@ Letting the PHY Abstraction Layer do Everything
|
|||
current state, though the PHY will not yet be truly operational at this
|
||||
point.
|
||||
|
||||
flags is a u32 which can optionally contain phy-specific flags.
|
||||
PHY-specific flags should be set in phydev->dev_flags prior to the call
|
||||
to phy_connect() such that the underlying PHY driver can check for flags
|
||||
and perform specific operations based on them.
|
||||
This is useful if the system has put hardware restrictions on
|
||||
the PHY/controller, of which the PHY needs to be aware.
|
||||
|
||||
|
@ -185,11 +187,10 @@ Doing it all yourself
|
|||
start, or disables then frees them for stop.
|
||||
|
||||
struct phy_device * phy_attach(struct net_device *dev, const char *phy_id,
|
||||
u32 flags, phy_interface_t interface);
|
||||
phy_interface_t interface);
|
||||
|
||||
Attaches a network device to a particular PHY, binding the PHY to a generic
|
||||
driver if none was found during bus initialization. Passes in
|
||||
any phy-specific flags as needed.
|
||||
driver if none was found during bus initialization.
|
||||
|
||||
int phy_start_aneg(struct phy_device *phydev);
|
||||
|
||||
|
|
|
@ -17,10 +17,12 @@ HCI
|
|||
HCI registers as an nfc device with NFC Core. Requests coming from userspace are
|
||||
routed through netlink sockets to NFC Core and then to HCI. From this point,
|
||||
they are translated in a sequence of HCI commands sent to the HCI layer in the
|
||||
host controller (the chip). The sending context blocks while waiting for the
|
||||
response to arrive.
|
||||
host controller (the chip). Commands can be executed synchronously (the sending
|
||||
context blocks waiting for response) or asynchronously (the response is returned
|
||||
from HCI Rx context).
|
||||
HCI events can also be received from the host controller. They will be handled
|
||||
and a translation will be forwarded to NFC Core as needed.
|
||||
and a translation will be forwarded to NFC Core as needed. There are hooks to
|
||||
let the HCI driver handle proprietary events or override standard behavior.
|
||||
HCI uses 2 execution contexts:
|
||||
- one for executing commands : nfc_hci_msg_tx_work(). Only one command
|
||||
can be executing at any given moment.
|
||||
|
@ -33,6 +35,8 @@ The Session initialization is an HCI standard which must unfortunately
|
|||
support proprietary gates. This is the reason why the driver will pass a list
|
||||
of proprietary gates that must be part of the session. HCI will ensure all
|
||||
those gates have pipes connected when the hci device is set up.
|
||||
In case the chip supports pre-opened gates and pseudo-static pipes, the driver
|
||||
can pass that information to HCI core.
|
||||
|
||||
HCI Gates and Pipes
|
||||
-------------------
|
||||
|
@ -46,6 +50,13 @@ without knowing the pipe connected to it.
|
|||
Driver interface
|
||||
----------------
|
||||
|
||||
A driver is generally written in two parts : the physical link management and
|
||||
the HCI management. This makes it easier to maintain a driver for a chip that
|
||||
can be connected using various phy (i2c, spi, ...)
|
||||
|
||||
HCI Management
|
||||
--------------
|
||||
|
||||
A driver would normally register itself with HCI and provide the following
|
||||
entry points:
|
||||
|
||||
|
@ -53,58 +64,113 @@ struct nfc_hci_ops {
|
|||
int (*open)(struct nfc_hci_dev *hdev);
|
||||
void (*close)(struct nfc_hci_dev *hdev);
|
||||
int (*hci_ready) (struct nfc_hci_dev *hdev);
|
||||
int (*xmit)(struct nfc_hci_dev *hdev, struct sk_buff *skb);
|
||||
int (*start_poll)(struct nfc_hci_dev *hdev, u32 protocols);
|
||||
int (*target_from_gate)(struct nfc_hci_dev *hdev, u8 gate,
|
||||
struct nfc_target *target);
|
||||
int (*xmit) (struct nfc_hci_dev *hdev, struct sk_buff *skb);
|
||||
int (*start_poll) (struct nfc_hci_dev *hdev,
|
||||
u32 im_protocols, u32 tm_protocols);
|
||||
int (*dep_link_up)(struct nfc_hci_dev *hdev, struct nfc_target *target,
|
||||
u8 comm_mode, u8 *gb, size_t gb_len);
|
||||
int (*dep_link_down)(struct nfc_hci_dev *hdev);
|
||||
int (*target_from_gate) (struct nfc_hci_dev *hdev, u8 gate,
|
||||
struct nfc_target *target);
|
||||
int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate,
|
||||
struct nfc_target *target);
|
||||
int (*data_exchange) (struct nfc_hci_dev *hdev,
|
||||
struct nfc_target *target,
|
||||
struct sk_buff *skb, struct sk_buff **res_skb);
|
||||
int (*im_transceive) (struct nfc_hci_dev *hdev,
|
||||
struct nfc_target *target, struct sk_buff *skb,
|
||||
data_exchange_cb_t cb, void *cb_context);
|
||||
int (*tm_send)(struct nfc_hci_dev *hdev, struct sk_buff *skb);
|
||||
int (*check_presence)(struct nfc_hci_dev *hdev,
|
||||
struct nfc_target *target);
|
||||
int (*event_received)(struct nfc_hci_dev *hdev, u8 gate, u8 event,
|
||||
struct sk_buff *skb);
|
||||
};
|
||||
|
||||
- open() and close() shall turn the hardware on and off.
|
||||
- hci_ready() is an optional entry point that is called right after the hci
|
||||
session has been set up. The driver can use it to do additional initialization
|
||||
that must be performed using HCI commands.
|
||||
- xmit() shall simply write a frame to the chip.
|
||||
- xmit() shall simply write a frame to the physical link.
|
||||
- start_poll() is an optional entrypoint that shall set the hardware in polling
|
||||
mode. This must be implemented only if the hardware uses proprietary gates or a
|
||||
mechanism slightly different from the HCI standard.
|
||||
- dep_link_up() is called after a p2p target has been detected, to finish
|
||||
the p2p connection setup with hardware parameters that need to be passed back
|
||||
to nfc core.
|
||||
- dep_link_down() is called to bring the p2p link down.
|
||||
- target_from_gate() is an optional entrypoint to return the nfc protocols
|
||||
corresponding to a proprietary gate.
|
||||
- complete_target_discovered() is an optional entry point to let the driver
|
||||
perform additional proprietary processing necessary to auto activate the
|
||||
discovered target.
|
||||
- data_exchange() must be implemented by the driver if proprietary HCI commands
|
||||
- im_transceive() must be implemented by the driver if proprietary HCI commands
|
||||
are required to send data to the tag. Some tag types will require custom
|
||||
commands, others can be written to using the standard HCI commands. The driver
|
||||
can check the tag type and either do proprietary processing, or return 1 to ask
|
||||
for standard processing.
|
||||
for standard processing. The data exchange command itself must be sent
|
||||
asynchronously.
|
||||
- tm_send() is called to send data in the case of a p2p connection
|
||||
- check_presence() is an optional entry point that will be called regularly
|
||||
by the core to check that an activated tag is still in the field. If this is
|
||||
not implemented, the core will not be able to push tag_lost events to the user
|
||||
space
|
||||
- event_received() is called to handle an event coming from the chip. Driver
|
||||
can handle the event or return 1 to let HCI attempt standard processing.
|
||||
|
||||
On the rx path, the driver is responsible to push incoming HCP frames to HCI
|
||||
using nfc_hci_recv_frame(). HCI will take care of re-aggregation and handling
|
||||
This must be done from a context that can sleep.
|
||||
|
||||
SHDLC
|
||||
-----
|
||||
PHY Management
|
||||
--------------
|
||||
|
||||
Most chips use shdlc to ensure integrity and delivery ordering of the HCP
|
||||
frames between the host controller (the chip) and hosts (entities connected
|
||||
to the chip, like the cpu). In order to simplify writing the driver, an shdlc
|
||||
layer is available for use by the driver.
|
||||
When used, the driver actually registers with shdlc, and shdlc will register
|
||||
with HCI. HCI sees shdlc as the driver and thus send its HCP frames
|
||||
through shdlc->xmit.
|
||||
SHDLC adds a new execution context (nfc_shdlc_sm_work()) to run its state
|
||||
machine and handle both its rx and tx path.
|
||||
The physical link (i2c, ...) management is defined by the following struture:
|
||||
|
||||
struct nfc_phy_ops {
|
||||
int (*write)(void *dev_id, struct sk_buff *skb);
|
||||
int (*enable)(void *dev_id);
|
||||
void (*disable)(void *dev_id);
|
||||
};
|
||||
|
||||
enable(): turn the phy on (power on), make it ready to transfer data
|
||||
disable(): turn the phy off
|
||||
write(): Send a data frame to the chip. Note that to enable higher
|
||||
layers such as an llc to store the frame for re-emission, this function must
|
||||
not alter the skb. It must also not return a positive result (return 0 for
|
||||
success, negative for failure).
|
||||
|
||||
Data coming from the chip shall be sent directly to nfc_hci_recv_frame().
|
||||
|
||||
LLC
|
||||
---
|
||||
|
||||
Communication between the CPU and the chip often requires some link layer
|
||||
protocol. Those are isolated as modules managed by the HCI layer. There are
|
||||
currently two modules : nop (raw transfert) and shdlc.
|
||||
A new llc must implement the following functions:
|
||||
|
||||
struct nfc_llc_ops {
|
||||
void *(*init) (struct nfc_hci_dev *hdev, xmit_to_drv_t xmit_to_drv,
|
||||
rcv_to_hci_t rcv_to_hci, int tx_headroom,
|
||||
int tx_tailroom, int *rx_headroom, int *rx_tailroom,
|
||||
llc_failure_t llc_failure);
|
||||
void (*deinit) (struct nfc_llc *llc);
|
||||
int (*start) (struct nfc_llc *llc);
|
||||
int (*stop) (struct nfc_llc *llc);
|
||||
void (*rcv_from_drv) (struct nfc_llc *llc, struct sk_buff *skb);
|
||||
int (*xmit_from_hci) (struct nfc_llc *llc, struct sk_buff *skb);
|
||||
};
|
||||
|
||||
- init() : allocate and init your private storage
|
||||
- deinit() : cleanup
|
||||
- start() : establish the logical connection
|
||||
- stop () : terminate the logical connection
|
||||
- rcv_from_drv() : handle data coming from the chip, going to HCI
|
||||
- xmit_from_hci() : handle data sent by HCI, going to the chip
|
||||
|
||||
The llc must be registered with nfc before it can be used. Do that by
|
||||
calling nfc_llc_register(const char *name, struct nfc_llc_ops *ops);
|
||||
|
||||
Again, note that the llc does not handle the physical link. It is thus very
|
||||
easy to mix any physical link with any llc for a given chip driver.
|
||||
|
||||
Included Drivers
|
||||
----------------
|
||||
|
@ -117,10 +183,12 @@ Execution Contexts
|
|||
|
||||
The execution contexts are the following:
|
||||
- IRQ handler (IRQH):
|
||||
fast, cannot sleep. stores incoming frames into an shdlc rx queue
|
||||
fast, cannot sleep. sends incoming frames to HCI where they are passed to
|
||||
the current llc. In case of shdlc, the frame is queued in shdlc rx queue.
|
||||
|
||||
- SHDLC State Machine worker (SMW)
|
||||
handles shdlc rx & tx queues. Dispatches HCI cmd responses.
|
||||
Only when llc_shdlc is used: handles shdlc rx & tx queues.
|
||||
Dispatches HCI cmd responses.
|
||||
|
||||
- HCI Tx Cmd worker (MSGTXWQ)
|
||||
Serializes execution of HCI commands. Completes execution in case of response
|
||||
|
@ -166,6 +234,15 @@ waiting command execution. Response processing involves invoking the completion
|
|||
callback that was provided by nfc_hci_msg_tx_work() when it sent the command.
|
||||
The completion callback will then wake the syscall context.
|
||||
|
||||
It is also possible to execute the command asynchronously using this API:
|
||||
|
||||
static int nfc_hci_execute_cmd_async(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
|
||||
const u8 *param, size_t param_len,
|
||||
data_exchange_cb_t cb, void *cb_context)
|
||||
|
||||
The workflow is the same, except that the API call returns immediately, and
|
||||
the callback will be called with the result from the SMW context.
|
||||
|
||||
Workflow receiving an HCI event or command
|
||||
------------------------------------------
|
||||
|
||||
|
|
|
@ -1,32 +1,15 @@
|
|||
Kernel driver for the NXP Semiconductors PN544 Near Field
|
||||
Communication chip
|
||||
|
||||
Author: Jari Vanhala
|
||||
Contact: Matti Aaltonen (matti.j.aaltonen at nokia.com)
|
||||
|
||||
General
|
||||
-------
|
||||
|
||||
The PN544 is an integrated transmission module for contactless
|
||||
communication. The driver goes under drives/nfc/ and is compiled as a
|
||||
module named "pn544". It registers a misc device and creates a device
|
||||
file named "/dev/pn544".
|
||||
module named "pn544".
|
||||
|
||||
Host Interfaces: I2C, SPI and HSU, this driver supports currently only I2C.
|
||||
|
||||
The Interface
|
||||
-------------
|
||||
|
||||
The driver offers a sysfs interface for a hardware test and an IOCTL
|
||||
interface for selecting between two operating modes. There are read,
|
||||
write and poll functions for transferring messages. The two operating
|
||||
modes are the normal (HCI) mode and the firmware update mode.
|
||||
|
||||
PN544 is controlled by sending messages from the userspace to the
|
||||
chip. The main function of the driver is just to pass those messages
|
||||
without caring about the message content.
|
||||
|
||||
|
||||
Protocols
|
||||
---------
|
||||
|
||||
|
@ -47,68 +30,3 @@ and third (LSB) bytes of the message. The maximum FW message length is
|
|||
|
||||
For the ETSI HCI specification see
|
||||
http://www.etsi.org/WebSite/Technologies/ProtocolSpecification.aspx
|
||||
|
||||
The Hardware Test
|
||||
-----------------
|
||||
|
||||
The idea of the test is that it can performed by reading from the
|
||||
corresponding sysfs file. The test is implemented in the board file
|
||||
and it should test that PN544 can be put into the firmware update
|
||||
mode. If the test is not implemented the sysfs file does not get
|
||||
created.
|
||||
|
||||
Example:
|
||||
> cat /sys/module/pn544/drivers/i2c\:pn544/3-002b/nfc_test
|
||||
1
|
||||
|
||||
Normal Operation
|
||||
----------------
|
||||
|
||||
PN544 is powered up when the device file is opened, otherwise it's
|
||||
turned off. Only one instance can use the device at a time.
|
||||
|
||||
Userspace applications control PN544 with HCI messages. The hardware
|
||||
sends an interrupt when data is available for reading. Data is
|
||||
physically read when the read function is called by a userspace
|
||||
application. Poll() checks the read interrupt state. Configuration and
|
||||
self testing are also done from the userspace using read and write.
|
||||
|
||||
Example platform data:
|
||||
|
||||
static int rx71_pn544_nfc_request_resources(struct i2c_client *client)
|
||||
{
|
||||
/* Get and setup the HW resources for the device */
|
||||
}
|
||||
|
||||
static void rx71_pn544_nfc_free_resources(void)
|
||||
{
|
||||
/* Release the HW resources */
|
||||
}
|
||||
|
||||
static void rx71_pn544_nfc_enable(int fw)
|
||||
{
|
||||
/* Turn the device on */
|
||||
}
|
||||
|
||||
static int rx71_pn544_nfc_test(void)
|
||||
{
|
||||
/*
|
||||
* Put the device into the FW update mode
|
||||
* and then back to the normal mode.
|
||||
* Check the behavior and return one on success,
|
||||
* zero on failure.
|
||||
*/
|
||||
}
|
||||
|
||||
static void rx71_pn544_nfc_disable(void)
|
||||
{
|
||||
/* turn the power off */
|
||||
}
|
||||
|
||||
static struct pn544_nfc_platform_data rx71_nfc_data = {
|
||||
.request_resources = rx71_pn544_nfc_request_resources,
|
||||
.free_resources = rx71_pn544_nfc_free_resources,
|
||||
.enable = rx71_pn544_nfc_enable,
|
||||
.test = rx71_pn544_nfc_test,
|
||||
.disable = rx71_pn544_nfc_disable,
|
||||
};
|
||||
|
|
|
@ -122,7 +122,7 @@ SLAB_C_MAGIC 0x4f17a36d kmem_cache mm/slab.c
|
|||
COW_MAGIC 0x4f4f4f4d cow_header_v1 arch/um/drivers/ubd_user.c
|
||||
I810_CARD_MAGIC 0x5072696E i810_card sound/oss/i810_audio.c
|
||||
TRIDENT_CARD_MAGIC 0x5072696E trident_card sound/oss/trident.c
|
||||
ROUTER_MAGIC 0x524d4157 wan_device include/linux/wanrouter.h
|
||||
ROUTER_MAGIC 0x524d4157 wan_device [in wanrouter.h pre 3.9]
|
||||
SCC_MAGIC 0x52696368 gs_port drivers/char/scc.h
|
||||
SAVEKMSG_MAGIC1 0x53415645 savekmsg arch/*/amiga/config.c
|
||||
GDA_MAGIC 0x58464552 gda arch/mips/include/asm/sn/gda.h
|
||||
|
|
14
MAINTAINERS
14
MAINTAINERS
|
@ -2982,11 +2982,6 @@ S: Maintained
|
|||
F: include/linux/netfilter_bridge/
|
||||
F: net/bridge/
|
||||
|
||||
ETHERTEAM 16I DRIVER
|
||||
M: Mika Kuoppala <miku@iki.fi>
|
||||
S: Maintained
|
||||
F: drivers/net/ethernet/fujitsu/eth16i.c
|
||||
|
||||
EXT2 FILE SYSTEM
|
||||
M: Jan Kara <jack@suse.cz>
|
||||
L: linux-ext4@vger.kernel.org
|
||||
|
@ -5385,13 +5380,6 @@ F: include/linux/sunrpc/
|
|||
F: include/uapi/linux/nfs*
|
||||
F: include/uapi/linux/sunrpc/
|
||||
|
||||
NI5010 NETWORK DRIVER
|
||||
M: Jan-Pascal van Best <janpascal@vanbest.org>
|
||||
M: Andreas Mohr <andi@lisas.de>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/ethernet/racal/ni5010.*
|
||||
|
||||
NILFS2 FILESYSTEM
|
||||
M: KONISHI Ryusuke <konishi.ryusuke@lab.ntt.co.jp>
|
||||
L: linux-nilfs@vger.kernel.org
|
||||
|
@ -7544,7 +7532,7 @@ S: Maintained
|
|||
F: drivers/media/tuners/tea5767.*
|
||||
|
||||
TEAM DRIVER
|
||||
M: Jiri Pirko <jpirko@redhat.com>
|
||||
M: Jiri Pirko <jiri@resnulli.us>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/net/team/
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#define SO_BROADCAST 0x0020
|
||||
#define SO_LINGER 0x0080
|
||||
#define SO_OOBINLINE 0x0100
|
||||
/* To add :#define SO_REUSEPORT 0x0200 */
|
||||
#define SO_REUSEPORT 0x0200
|
||||
|
||||
#define SO_TYPE 0x1008
|
||||
#define SO_ERROR 0x1007
|
||||
|
@ -77,5 +77,6 @@
|
|||
/* Instruct lower device to use last 4-bytes of skb data as FCS */
|
||||
#define SO_NOFCS 43
|
||||
|
||||
#define SO_LOCK_FILTER 44
|
||||
|
||||
#endif /* _UAPI_ASM_SOCKET_H */
|
||||
|
|
|
@ -309,7 +309,7 @@ static struct omap2_hsmmc_info mmc[] = {
|
|||
.gpio_wp = 63,
|
||||
.deferred = true,
|
||||
},
|
||||
#ifdef CONFIG_WL12XX_PLATFORM_DATA
|
||||
#ifdef CONFIG_WILINK_PLATFORM_DATA
|
||||
{
|
||||
.name = "wl1271",
|
||||
.mmc = 2,
|
||||
|
@ -450,7 +450,7 @@ static struct regulator_init_data omap3evm_vio = {
|
|||
.consumer_supplies = omap3evm_vio_supply,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_WL12XX_PLATFORM_DATA
|
||||
#ifdef CONFIG_WILINK_PLATFORM_DATA
|
||||
|
||||
#define OMAP3EVM_WLAN_PMENA_GPIO (150)
|
||||
#define OMAP3EVM_WLAN_IRQ_GPIO (149)
|
||||
|
@ -563,7 +563,7 @@ static struct omap_board_mux omap35x_board_mux[] __initdata = {
|
|||
OMAP_PIN_OFF_NONE),
|
||||
OMAP3_MUX(GPMC_WAIT2, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP |
|
||||
OMAP_PIN_OFF_NONE),
|
||||
#ifdef CONFIG_WL12XX_PLATFORM_DATA
|
||||
#ifdef CONFIG_WILINK_PLATFORM_DATA
|
||||
/* WLAN IRQ - GPIO 149 */
|
||||
OMAP3_MUX(UART1_RTS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
|
||||
|
||||
|
@ -601,7 +601,7 @@ static struct omap_board_mux omap36x_board_mux[] __initdata = {
|
|||
OMAP3_MUX(SYS_BOOT4, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
|
||||
OMAP3_MUX(SYS_BOOT5, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
|
||||
OMAP3_MUX(SYS_BOOT6, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
|
||||
#ifdef CONFIG_WL12XX_PLATFORM_DATA
|
||||
#ifdef CONFIG_WILINK_PLATFORM_DATA
|
||||
/* WLAN IRQ - GPIO 149 */
|
||||
OMAP3_MUX(UART1_RTS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
|
||||
|
||||
|
@ -637,7 +637,7 @@ static struct gpio omap3_evm_ehci_gpios[] __initdata = {
|
|||
|
||||
static void __init omap3_evm_wl12xx_init(void)
|
||||
{
|
||||
#ifdef CONFIG_WL12XX_PLATFORM_DATA
|
||||
#ifdef CONFIG_WILINK_PLATFORM_DATA
|
||||
int ret;
|
||||
|
||||
/* WL12xx WLAN Init */
|
||||
|
|
|
@ -341,10 +341,17 @@ static void emit_load_be16(u8 cond, u8 r_res, u8 r_addr, struct jit_ctx *ctx)
|
|||
|
||||
static inline void emit_swap16(u8 r_dst, u8 r_src, struct jit_ctx *ctx)
|
||||
{
|
||||
emit(ARM_LSL_R(ARM_R1, r_src, 8), ctx);
|
||||
emit(ARM_ORR_S(r_dst, ARM_R1, r_src, SRTYPE_LSL, 8), ctx);
|
||||
emit(ARM_LSL_I(r_dst, r_dst, 8), ctx);
|
||||
emit(ARM_LSL_R(r_dst, r_dst, 8), ctx);
|
||||
/* r_dst = (r_src << 8) | (r_src >> 8) */
|
||||
emit(ARM_LSL_I(ARM_R1, r_src, 8), ctx);
|
||||
emit(ARM_ORR_S(r_dst, ARM_R1, r_src, SRTYPE_LSR, 8), ctx);
|
||||
|
||||
/*
|
||||
* we need to mask out the bits set in r_dst[23:16] due to
|
||||
* the first shift instruction.
|
||||
*
|
||||
* note that 0x8ff is the encoded immediate 0x00ff0000.
|
||||
*/
|
||||
emit(ARM_BIC_I(r_dst, r_dst, 0x8ff), ctx);
|
||||
}
|
||||
|
||||
#else /* ARMv6+ */
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#define SO_PRIORITY 12
|
||||
#define SO_LINGER 13
|
||||
#define SO_BSDCOMPAT 14
|
||||
/* To add :#define SO_REUSEPORT 15 */
|
||||
#define SO_REUSEPORT 15
|
||||
#define SO_PASSCRED 16
|
||||
#define SO_PEERCRED 17
|
||||
#define SO_RCVLOWAT 18
|
||||
|
@ -70,4 +70,6 @@
|
|||
/* Instruct lower device to use last 4-bytes of skb data as FCS */
|
||||
#define SO_NOFCS 43
|
||||
|
||||
#define SO_LOCK_FILTER 44
|
||||
|
||||
#endif /* __ASM_AVR32_SOCKET_H */
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#define SO_PRIORITY 12
|
||||
#define SO_LINGER 13
|
||||
#define SO_BSDCOMPAT 14
|
||||
/* To add :#define SO_REUSEPORT 15 */
|
||||
#define SO_REUSEPORT 15
|
||||
#define SO_PASSCRED 16
|
||||
#define SO_PEERCRED 17
|
||||
#define SO_RCVLOWAT 18
|
||||
|
@ -72,6 +72,8 @@
|
|||
/* Instruct lower device to use last 4-bytes of skb data as FCS */
|
||||
#define SO_NOFCS 43
|
||||
|
||||
#define SO_LOCK_FILTER 44
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#define SO_PRIORITY 12
|
||||
#define SO_LINGER 13
|
||||
#define SO_BSDCOMPAT 14
|
||||
/* To add :#define SO_REUSEPORT 15 */
|
||||
#define SO_REUSEPORT 15
|
||||
#define SO_PASSCRED 16
|
||||
#define SO_PEERCRED 17
|
||||
#define SO_RCVLOWAT 18
|
||||
|
@ -70,5 +70,7 @@
|
|||
/* Instruct lower device to use last 4-bytes of skb data as FCS */
|
||||
#define SO_NOFCS 43
|
||||
|
||||
#define SO_LOCK_FILTER 44
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#define SO_PRIORITY 12
|
||||
#define SO_LINGER 13
|
||||
#define SO_BSDCOMPAT 14
|
||||
/* To add :#define SO_REUSEPORT 15 */
|
||||
#define SO_REUSEPORT 15
|
||||
#define SO_PASSCRED 16
|
||||
#define SO_PEERCRED 17
|
||||
#define SO_RCVLOWAT 18
|
||||
|
@ -70,4 +70,6 @@
|
|||
/* Instruct lower device to use last 4-bytes of skb data as FCS */
|
||||
#define SO_NOFCS 43
|
||||
|
||||
#define SO_LOCK_FILTER 44
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#define SO_PRIORITY 12
|
||||
#define SO_LINGER 13
|
||||
#define SO_BSDCOMPAT 14
|
||||
/* To add :#define SO_REUSEPORT 15 */
|
||||
#define SO_REUSEPORT 15
|
||||
#define SO_PASSCRED 16
|
||||
#define SO_PEERCRED 17
|
||||
#define SO_RCVLOWAT 18
|
||||
|
@ -79,4 +79,6 @@
|
|||
/* Instruct lower device to use last 4-bytes of skb data as FCS */
|
||||
#define SO_NOFCS 43
|
||||
|
||||
#define SO_LOCK_FILTER 44
|
||||
|
||||
#endif /* _ASM_IA64_SOCKET_H */
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#define SO_PRIORITY 12
|
||||
#define SO_LINGER 13
|
||||
#define SO_BSDCOMPAT 14
|
||||
/* To add :#define SO_REUSEPORT 15 */
|
||||
#define SO_REUSEPORT 15
|
||||
#define SO_PASSCRED 16
|
||||
#define SO_PEERCRED 17
|
||||
#define SO_RCVLOWAT 18
|
||||
|
@ -70,4 +70,6 @@
|
|||
/* Instruct lower device to use last 4-bytes of skb data as FCS */
|
||||
#define SO_NOFCS 43
|
||||
|
||||
#define SO_LOCK_FILTER 44
|
||||
|
||||
#endif /* _ASM_M32R_SOCKET_H */
|
||||
|
|
|
@ -62,7 +62,7 @@ static int __init uart8250_init_bcma(void)
|
|||
|
||||
p->mapbase = (unsigned int) bcma_port->regs;
|
||||
p->membase = (void *) bcma_port->regs;
|
||||
p->irq = bcma_port->irq + 2;
|
||||
p->irq = bcma_port->irq;
|
||||
p->uartclk = bcma_port->baud_base;
|
||||
p->regshift = bcma_port->reg_shift;
|
||||
p->iotype = UPIO_MEM;
|
||||
|
|
|
@ -28,9 +28,7 @@
|
|||
#define SO_LINGER 0x0080 /* Block on close of a reliable
|
||||
socket to transmit pending data. */
|
||||
#define SO_OOBINLINE 0x0100 /* Receive out-of-band data in-band. */
|
||||
#if 0
|
||||
To add: #define SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */
|
||||
#endif
|
||||
#define SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */
|
||||
|
||||
#define SO_TYPE 0x1008 /* Compatible name for SO_STYLE. */
|
||||
#define SO_STYLE SO_TYPE /* Synonym */
|
||||
|
@ -90,5 +88,6 @@ To add: #define SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */
|
|||
/* Instruct lower device to use last 4-bytes of skb data as FCS */
|
||||
#define SO_NOFCS 43
|
||||
|
||||
#define SO_LOCK_FILTER 44
|
||||
|
||||
#endif /* _UAPI_ASM_SOCKET_H */
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#define SO_PRIORITY 12
|
||||
#define SO_LINGER 13
|
||||
#define SO_BSDCOMPAT 14
|
||||
/* To add :#define SO_REUSEPORT 15 */
|
||||
#define SO_REUSEPORT 15
|
||||
#define SO_PASSCRED 16
|
||||
#define SO_PEERCRED 17
|
||||
#define SO_RCVLOWAT 18
|
||||
|
@ -70,4 +70,6 @@
|
|||
/* Instruct lower device to use last 4-bytes of skb data as FCS */
|
||||
#define SO_NOFCS 43
|
||||
|
||||
#define SO_LOCK_FILTER 44
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#define SO_BROADCAST 0x0020
|
||||
#define SO_LINGER 0x0080
|
||||
#define SO_OOBINLINE 0x0100
|
||||
/* To add :#define SO_REUSEPORT 0x0200 */
|
||||
#define SO_REUSEPORT 0x0200
|
||||
#define SO_SNDBUF 0x1001
|
||||
#define SO_RCVBUF 0x1002
|
||||
#define SO_SNDBUFFORCE 0x100a
|
||||
|
@ -69,6 +69,7 @@
|
|||
/* Instruct lower device to use last 4-bytes of skb data as FCS */
|
||||
#define SO_NOFCS 0x4024
|
||||
|
||||
#define SO_LOCK_FILTER 0x4025
|
||||
|
||||
/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
|
||||
* have to define SOCK_NONBLOCK to a different value here.
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#define SO_PRIORITY 12
|
||||
#define SO_LINGER 13
|
||||
#define SO_BSDCOMPAT 14
|
||||
/* To add :#define SO_REUSEPORT 15 */
|
||||
#define SO_REUSEPORT 15
|
||||
#define SO_RCVLOWAT 16
|
||||
#define SO_SNDLOWAT 17
|
||||
#define SO_RCVTIMEO 18
|
||||
|
@ -77,4 +77,6 @@
|
|||
/* Instruct lower device to use last 4-bytes of skb data as FCS */
|
||||
#define SO_NOFCS 43
|
||||
|
||||
#define SO_LOCK_FILTER 44
|
||||
|
||||
#endif /* _ASM_POWERPC_SOCKET_H */
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#define SO_PRIORITY 12
|
||||
#define SO_LINGER 13
|
||||
#define SO_BSDCOMPAT 14
|
||||
/* To add :#define SO_REUSEPORT 15 */
|
||||
#define SO_REUSEPORT 15
|
||||
#define SO_PASSCRED 16
|
||||
#define SO_PEERCRED 17
|
||||
#define SO_RCVLOWAT 18
|
||||
|
@ -76,4 +76,6 @@
|
|||
/* Instruct lower device to use last 4-bytes of skb data as FCS */
|
||||
#define SO_NOFCS 43
|
||||
|
||||
#define SO_LOCK_FILTER 44
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#define SO_PEERCRED 0x0040
|
||||
#define SO_LINGER 0x0080
|
||||
#define SO_OOBINLINE 0x0100
|
||||
/* To add :#define SO_REUSEPORT 0x0200 */
|
||||
#define SO_REUSEPORT 0x0200
|
||||
#define SO_BSDCOMPAT 0x0400
|
||||
#define SO_RCVLOWAT 0x0800
|
||||
#define SO_SNDLOWAT 0x1000
|
||||
|
@ -66,6 +66,7 @@
|
|||
/* Instruct lower device to use last 4-bytes of skb data as FCS */
|
||||
#define SO_NOFCS 0x0027
|
||||
|
||||
#define SO_LOCK_FILTER 0x0028
|
||||
|
||||
/* Security levels - as per NRL IPv6 - don't actually do anything */
|
||||
#define SO_SECURITY_AUTHENTICATION 0x5001
|
||||
|
|
|
@ -274,8 +274,8 @@ static void uml_net_poll_controller(struct net_device *dev)
|
|||
static void uml_net_get_drvinfo(struct net_device *dev,
|
||||
struct ethtool_drvinfo *info)
|
||||
{
|
||||
strcpy(info->driver, DRIVER_NAME);
|
||||
strcpy(info->version, "42");
|
||||
strlcpy(info->driver, DRIVER_NAME, sizeof(info->driver));
|
||||
strlcpy(info->version, "42", sizeof(info->version));
|
||||
}
|
||||
|
||||
static const struct ethtool_ops uml_net_ethtool_ops = {
|
||||
|
@ -293,8 +293,9 @@ static void uml_net_user_timer_expire(unsigned long _conn)
|
|||
#endif
|
||||
}
|
||||
|
||||
static int setup_etheraddr(char *str, unsigned char *addr, char *name)
|
||||
static void setup_etheraddr(struct net_device *dev, char *str)
|
||||
{
|
||||
unsigned char *addr = dev->dev_addr;
|
||||
char *end;
|
||||
int i;
|
||||
|
||||
|
@ -334,13 +335,12 @@ static int setup_etheraddr(char *str, unsigned char *addr, char *name)
|
|||
addr[0] | 0x02, addr[1], addr[2], addr[3], addr[4],
|
||||
addr[5]);
|
||||
}
|
||||
return 0;
|
||||
return;
|
||||
|
||||
random:
|
||||
printk(KERN_INFO
|
||||
"Choosing a random ethernet address for device %s\n", name);
|
||||
eth_random_addr(addr);
|
||||
return 1;
|
||||
"Choosing a random ethernet address for device %s\n", dev->name);
|
||||
eth_hw_addr_random(dev);
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(devices_lock);
|
||||
|
@ -392,7 +392,6 @@ static void eth_configure(int n, void *init, char *mac,
|
|||
struct net_device *dev;
|
||||
struct uml_net_private *lp;
|
||||
int err, size;
|
||||
int random_mac;
|
||||
|
||||
size = transport->private_size + sizeof(struct uml_net_private);
|
||||
|
||||
|
@ -419,9 +418,9 @@ static void eth_configure(int n, void *init, char *mac,
|
|||
*/
|
||||
snprintf(dev->name, sizeof(dev->name), "eth%d", n);
|
||||
|
||||
random_mac = setup_etheraddr(mac, device->mac, dev->name);
|
||||
setup_etheraddr(dev, mac);
|
||||
|
||||
printk(KERN_INFO "Netdevice %d (%pM) : ", n, device->mac);
|
||||
printk(KERN_INFO "Netdevice %d (%pM) : ", n, dev->dev_addr);
|
||||
|
||||
lp = netdev_priv(dev);
|
||||
/* This points to the transport private data. It's still clear, but we
|
||||
|
@ -468,17 +467,12 @@ static void eth_configure(int n, void *init, char *mac,
|
|||
init_timer(&lp->tl);
|
||||
spin_lock_init(&lp->lock);
|
||||
lp->tl.function = uml_net_user_timer_expire;
|
||||
memcpy(lp->mac, device->mac, sizeof(lp->mac));
|
||||
memcpy(lp->mac, dev->dev_addr, sizeof(lp->mac));
|
||||
|
||||
if ((transport->user->init != NULL) &&
|
||||
((*transport->user->init)(&lp->user, dev) != 0))
|
||||
goto out_unregister;
|
||||
|
||||
/* don't use eth_mac_addr, it will not work here */
|
||||
memcpy(dev->dev_addr, device->mac, ETH_ALEN);
|
||||
if (random_mac)
|
||||
dev->addr_assign_type |= NET_ADDR_RANDOM;
|
||||
|
||||
dev->mtu = transport->user->mtu;
|
||||
dev->netdev_ops = ¨_netdev_ops;
|
||||
dev->ethtool_ops = ¨_net_ethtool_ops;
|
||||
|
|
|
@ -18,7 +18,6 @@ struct uml_net {
|
|||
struct net_device *dev;
|
||||
struct platform_device pdev;
|
||||
int index;
|
||||
unsigned char mac[ETH_ALEN];
|
||||
};
|
||||
|
||||
struct uml_net_private {
|
||||
|
|
|
@ -40,10 +40,6 @@
|
|||
#include <linux/workqueue.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#if defined(CONFIG_CRYPTO_CTR) || defined(CONFIG_CRYPTO_CTR_MODULE)
|
||||
#define HAS_CTR
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CRYPTO_PCBC) || defined(CONFIG_CRYPTO_PCBC_MODULE)
|
||||
#define HAS_PCBC
|
||||
#endif
|
||||
|
@ -395,12 +391,6 @@ static int ablk_ctr_init(struct crypto_tfm *tfm)
|
|||
return ablk_init_common(tfm, "__driver-ctr-aes-aesni");
|
||||
}
|
||||
|
||||
#ifdef HAS_CTR
|
||||
static int ablk_rfc3686_ctr_init(struct crypto_tfm *tfm)
|
||||
{
|
||||
return ablk_init_common(tfm, "rfc3686(__driver-ctr-aes-aesni)");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAS_PCBC
|
||||
|
@ -1158,33 +1148,6 @@ static struct crypto_alg aesni_algs[] = { {
|
|||
.maxauthsize = 16,
|
||||
},
|
||||
},
|
||||
#ifdef HAS_CTR
|
||||
}, {
|
||||
.cra_name = "rfc3686(ctr(aes))",
|
||||
.cra_driver_name = "rfc3686-ctr-aes-aesni",
|
||||
.cra_priority = 400,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
|
||||
.cra_blocksize = 1,
|
||||
.cra_ctxsize = sizeof(struct async_helper_ctx),
|
||||
.cra_alignmask = 0,
|
||||
.cra_type = &crypto_ablkcipher_type,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_init = ablk_rfc3686_ctr_init,
|
||||
.cra_exit = ablk_exit,
|
||||
.cra_u = {
|
||||
.ablkcipher = {
|
||||
.min_keysize = AES_MIN_KEY_SIZE +
|
||||
CTR_RFC3686_NONCE_SIZE,
|
||||
.max_keysize = AES_MAX_KEY_SIZE +
|
||||
CTR_RFC3686_NONCE_SIZE,
|
||||
.ivsize = CTR_RFC3686_IV_SIZE,
|
||||
.setkey = ablk_set_key,
|
||||
.encrypt = ablk_encrypt,
|
||||
.decrypt = ablk_decrypt,
|
||||
.geniv = "seqiv",
|
||||
},
|
||||
},
|
||||
#endif
|
||||
#endif
|
||||
#ifdef HAS_PCBC
|
||||
}, {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* bpf_jit_comp.c : BPF JIT compiler
|
||||
*
|
||||
* Copyright (C) 2011 Eric Dumazet (eric.dumazet@gmail.com)
|
||||
* Copyright (C) 2011-2013 Eric Dumazet (eric.dumazet@gmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -124,6 +124,26 @@ static inline void bpf_flush_icache(void *start, void *end)
|
|||
#define CHOOSE_LOAD_FUNC(K, func) \
|
||||
((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset)
|
||||
|
||||
/* Helper to find the offset of pkt_type in sk_buff
|
||||
* We want to make sure its still a 3bit field starting at a byte boundary.
|
||||
*/
|
||||
#define PKT_TYPE_MAX 7
|
||||
static int pkt_type_offset(void)
|
||||
{
|
||||
struct sk_buff skb_probe = {
|
||||
.pkt_type = ~0,
|
||||
};
|
||||
char *ct = (char *)&skb_probe;
|
||||
unsigned int off;
|
||||
|
||||
for (off = 0; off < sizeof(struct sk_buff); off++) {
|
||||
if (ct[off] == PKT_TYPE_MAX)
|
||||
return off;
|
||||
}
|
||||
pr_err_once("Please fix pkt_type_offset(), as pkt_type couldn't be found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void bpf_jit_compile(struct sk_filter *fp)
|
||||
{
|
||||
u8 temp[64];
|
||||
|
@ -216,6 +236,7 @@ void bpf_jit_compile(struct sk_filter *fp)
|
|||
case BPF_S_ANC_VLAN_TAG:
|
||||
case BPF_S_ANC_VLAN_TAG_PRESENT:
|
||||
case BPF_S_ANC_QUEUE:
|
||||
case BPF_S_ANC_PKTTYPE:
|
||||
case BPF_S_LD_W_ABS:
|
||||
case BPF_S_LD_H_ABS:
|
||||
case BPF_S_LD_B_ABS:
|
||||
|
@ -536,6 +557,23 @@ void bpf_jit_compile(struct sk_filter *fp)
|
|||
EMIT3(0x83, 0xe0, 0x01); /* and $0x1,%eax */
|
||||
}
|
||||
break;
|
||||
case BPF_S_ANC_PKTTYPE:
|
||||
{
|
||||
int off = pkt_type_offset();
|
||||
|
||||
if (off < 0)
|
||||
goto out;
|
||||
if (is_imm8(off)) {
|
||||
/* movzbl off8(%rdi),%eax */
|
||||
EMIT4(0x0f, 0xb6, 0x47, off);
|
||||
} else {
|
||||
/* movbl off32(%rdi),%eax */
|
||||
EMIT3(0x0f, 0xb6, 0x87);
|
||||
EMIT(off, 4);
|
||||
}
|
||||
EMIT3(0x83, 0xe0, PKT_TYPE_MAX); /* and $0x7,%eax */
|
||||
break;
|
||||
}
|
||||
case BPF_S_LD_W_ABS:
|
||||
func = CHOOSE_LOAD_FUNC(K, sk_load_word);
|
||||
common_load: seen |= SEEN_DATAREF;
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#define SO_PRIORITY 12
|
||||
#define SO_LINGER 13
|
||||
#define SO_BSDCOMPAT 14
|
||||
/* To add :#define SO_REUSEPORT 15 */
|
||||
#define SO_REUSEPORT 15
|
||||
#define SO_PASSCRED 16
|
||||
#define SO_PEERCRED 17
|
||||
#define SO_RCVLOWAT 18
|
||||
|
@ -81,4 +81,6 @@
|
|||
/* Instruct lower device to use last 4-bytes of skb data as FCS */
|
||||
#define SO_NOFCS 43
|
||||
|
||||
#define SO_LOCK_FILTER 44
|
||||
|
||||
#endif /* _XTENSA_SOCKET_H */
|
||||
|
|
173
crypto/ctr.c
173
crypto/ctr.c
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include <crypto/algapi.h>
|
||||
#include <crypto/ctr.h>
|
||||
#include <crypto/internal/skcipher.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
|
@ -25,10 +26,15 @@ struct crypto_ctr_ctx {
|
|||
};
|
||||
|
||||
struct crypto_rfc3686_ctx {
|
||||
struct crypto_blkcipher *child;
|
||||
struct crypto_ablkcipher *child;
|
||||
u8 nonce[CTR_RFC3686_NONCE_SIZE];
|
||||
};
|
||||
|
||||
struct crypto_rfc3686_req_ctx {
|
||||
u8 iv[CTR_RFC3686_BLOCK_SIZE];
|
||||
struct ablkcipher_request subreq CRYPTO_MINALIGN_ATTR;
|
||||
};
|
||||
|
||||
static int crypto_ctr_setkey(struct crypto_tfm *parent, const u8 *key,
|
||||
unsigned int keylen)
|
||||
{
|
||||
|
@ -243,11 +249,11 @@ static struct crypto_template crypto_ctr_tmpl = {
|
|||
.module = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int crypto_rfc3686_setkey(struct crypto_tfm *parent, const u8 *key,
|
||||
unsigned int keylen)
|
||||
static int crypto_rfc3686_setkey(struct crypto_ablkcipher *parent,
|
||||
const u8 *key, unsigned int keylen)
|
||||
{
|
||||
struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(parent);
|
||||
struct crypto_blkcipher *child = ctx->child;
|
||||
struct crypto_rfc3686_ctx *ctx = crypto_ablkcipher_ctx(parent);
|
||||
struct crypto_ablkcipher *child = ctx->child;
|
||||
int err;
|
||||
|
||||
/* the nonce is stored in bytes at end of key */
|
||||
|
@ -259,59 +265,64 @@ static int crypto_rfc3686_setkey(struct crypto_tfm *parent, const u8 *key,
|
|||
|
||||
keylen -= CTR_RFC3686_NONCE_SIZE;
|
||||
|
||||
crypto_blkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
|
||||
crypto_blkcipher_set_flags(child, crypto_tfm_get_flags(parent) &
|
||||
CRYPTO_TFM_REQ_MASK);
|
||||
err = crypto_blkcipher_setkey(child, key, keylen);
|
||||
crypto_tfm_set_flags(parent, crypto_blkcipher_get_flags(child) &
|
||||
CRYPTO_TFM_RES_MASK);
|
||||
crypto_ablkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
|
||||
crypto_ablkcipher_set_flags(child, crypto_ablkcipher_get_flags(parent) &
|
||||
CRYPTO_TFM_REQ_MASK);
|
||||
err = crypto_ablkcipher_setkey(child, key, keylen);
|
||||
crypto_ablkcipher_set_flags(parent, crypto_ablkcipher_get_flags(child) &
|
||||
CRYPTO_TFM_RES_MASK);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int crypto_rfc3686_crypt(struct blkcipher_desc *desc,
|
||||
struct scatterlist *dst,
|
||||
struct scatterlist *src, unsigned int nbytes)
|
||||
static int crypto_rfc3686_crypt(struct ablkcipher_request *req)
|
||||
{
|
||||
struct crypto_blkcipher *tfm = desc->tfm;
|
||||
struct crypto_rfc3686_ctx *ctx = crypto_blkcipher_ctx(tfm);
|
||||
struct crypto_blkcipher *child = ctx->child;
|
||||
unsigned long alignmask = crypto_blkcipher_alignmask(tfm);
|
||||
u8 ivblk[CTR_RFC3686_BLOCK_SIZE + alignmask];
|
||||
u8 *iv = PTR_ALIGN(ivblk + 0, alignmask + 1);
|
||||
u8 *info = desc->info;
|
||||
int err;
|
||||
struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
|
||||
struct crypto_rfc3686_ctx *ctx = crypto_ablkcipher_ctx(tfm);
|
||||
struct crypto_ablkcipher *child = ctx->child;
|
||||
unsigned long align = crypto_ablkcipher_alignmask(tfm);
|
||||
struct crypto_rfc3686_req_ctx *rctx =
|
||||
(void *)PTR_ALIGN((u8 *)ablkcipher_request_ctx(req), align + 1);
|
||||
struct ablkcipher_request *subreq = &rctx->subreq;
|
||||
u8 *iv = rctx->iv;
|
||||
|
||||
/* set up counter block */
|
||||
memcpy(iv, ctx->nonce, CTR_RFC3686_NONCE_SIZE);
|
||||
memcpy(iv + CTR_RFC3686_NONCE_SIZE, info, CTR_RFC3686_IV_SIZE);
|
||||
memcpy(iv + CTR_RFC3686_NONCE_SIZE, req->info, CTR_RFC3686_IV_SIZE);
|
||||
|
||||
/* initialize counter portion of counter block */
|
||||
*(__be32 *)(iv + CTR_RFC3686_NONCE_SIZE + CTR_RFC3686_IV_SIZE) =
|
||||
cpu_to_be32(1);
|
||||
|
||||
desc->tfm = child;
|
||||
desc->info = iv;
|
||||
err = crypto_blkcipher_encrypt_iv(desc, dst, src, nbytes);
|
||||
desc->tfm = tfm;
|
||||
desc->info = info;
|
||||
ablkcipher_request_set_tfm(subreq, child);
|
||||
ablkcipher_request_set_callback(subreq, req->base.flags,
|
||||
req->base.complete, req->base.data);
|
||||
ablkcipher_request_set_crypt(subreq, req->src, req->dst, req->nbytes,
|
||||
iv);
|
||||
|
||||
return err;
|
||||
return crypto_ablkcipher_encrypt(subreq);
|
||||
}
|
||||
|
||||
static int crypto_rfc3686_init_tfm(struct crypto_tfm *tfm)
|
||||
{
|
||||
struct crypto_instance *inst = (void *)tfm->__crt_alg;
|
||||
struct crypto_spawn *spawn = crypto_instance_ctx(inst);
|
||||
struct crypto_skcipher_spawn *spawn = crypto_instance_ctx(inst);
|
||||
struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
struct crypto_blkcipher *cipher;
|
||||
struct crypto_ablkcipher *cipher;
|
||||
unsigned long align;
|
||||
|
||||
cipher = crypto_spawn_blkcipher(spawn);
|
||||
cipher = crypto_spawn_skcipher(spawn);
|
||||
if (IS_ERR(cipher))
|
||||
return PTR_ERR(cipher);
|
||||
|
||||
ctx->child = cipher;
|
||||
|
||||
align = crypto_tfm_alg_alignmask(tfm);
|
||||
align &= ~(crypto_tfm_ctx_alignment() - 1);
|
||||
tfm->crt_ablkcipher.reqsize = align +
|
||||
sizeof(struct crypto_rfc3686_req_ctx) +
|
||||
crypto_ablkcipher_reqsize(cipher);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -319,74 +330,110 @@ static void crypto_rfc3686_exit_tfm(struct crypto_tfm *tfm)
|
|||
{
|
||||
struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
|
||||
crypto_free_blkcipher(ctx->child);
|
||||
crypto_free_ablkcipher(ctx->child);
|
||||
}
|
||||
|
||||
static struct crypto_instance *crypto_rfc3686_alloc(struct rtattr **tb)
|
||||
{
|
||||
struct crypto_attr_type *algt;
|
||||
struct crypto_instance *inst;
|
||||
struct crypto_alg *alg;
|
||||
struct crypto_skcipher_spawn *spawn;
|
||||
const char *cipher_name;
|
||||
int err;
|
||||
|
||||
err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
|
||||
if (err)
|
||||
algt = crypto_get_attr_type(tb);
|
||||
err = PTR_ERR(algt);
|
||||
if (IS_ERR(algt))
|
||||
return ERR_PTR(err);
|
||||
|
||||
alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_BLKCIPHER,
|
||||
CRYPTO_ALG_TYPE_MASK);
|
||||
err = PTR_ERR(alg);
|
||||
if (IS_ERR(alg))
|
||||
if ((algt->type ^ CRYPTO_ALG_TYPE_BLKCIPHER) & algt->mask)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
cipher_name = crypto_attr_alg_name(tb[1]);
|
||||
err = PTR_ERR(cipher_name);
|
||||
if (IS_ERR(cipher_name))
|
||||
return ERR_PTR(err);
|
||||
|
||||
inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
|
||||
if (!inst)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
spawn = crypto_instance_ctx(inst);
|
||||
|
||||
crypto_set_skcipher_spawn(spawn, inst);
|
||||
err = crypto_grab_skcipher(spawn, cipher_name, 0,
|
||||
crypto_requires_sync(algt->type,
|
||||
algt->mask));
|
||||
if (err)
|
||||
goto err_free_inst;
|
||||
|
||||
alg = crypto_skcipher_spawn_alg(spawn);
|
||||
|
||||
/* We only support 16-byte blocks. */
|
||||
err = -EINVAL;
|
||||
if (alg->cra_blkcipher.ivsize != CTR_RFC3686_BLOCK_SIZE)
|
||||
goto out_put_alg;
|
||||
if (alg->cra_ablkcipher.ivsize != CTR_RFC3686_BLOCK_SIZE)
|
||||
goto err_drop_spawn;
|
||||
|
||||
/* Not a stream cipher? */
|
||||
if (alg->cra_blocksize != 1)
|
||||
goto out_put_alg;
|
||||
goto err_drop_spawn;
|
||||
|
||||
inst = crypto_alloc_instance("rfc3686", alg);
|
||||
if (IS_ERR(inst))
|
||||
goto out;
|
||||
err = -ENAMETOOLONG;
|
||||
if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, "rfc3686(%s)",
|
||||
alg->cra_name) >= CRYPTO_MAX_ALG_NAME)
|
||||
goto err_drop_spawn;
|
||||
if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
|
||||
"rfc3686(%s)", alg->cra_driver_name) >=
|
||||
CRYPTO_MAX_ALG_NAME)
|
||||
goto err_drop_spawn;
|
||||
|
||||
inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
|
||||
inst->alg.cra_priority = alg->cra_priority;
|
||||
inst->alg.cra_blocksize = 1;
|
||||
inst->alg.cra_alignmask = alg->cra_alignmask;
|
||||
inst->alg.cra_type = &crypto_blkcipher_type;
|
||||
|
||||
inst->alg.cra_blkcipher.ivsize = CTR_RFC3686_IV_SIZE;
|
||||
inst->alg.cra_blkcipher.min_keysize = alg->cra_blkcipher.min_keysize
|
||||
+ CTR_RFC3686_NONCE_SIZE;
|
||||
inst->alg.cra_blkcipher.max_keysize = alg->cra_blkcipher.max_keysize
|
||||
+ CTR_RFC3686_NONCE_SIZE;
|
||||
inst->alg.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
|
||||
(alg->cra_flags & CRYPTO_ALG_ASYNC);
|
||||
inst->alg.cra_type = &crypto_ablkcipher_type;
|
||||
|
||||
inst->alg.cra_blkcipher.geniv = "seqiv";
|
||||
inst->alg.cra_ablkcipher.ivsize = CTR_RFC3686_IV_SIZE;
|
||||
inst->alg.cra_ablkcipher.min_keysize =
|
||||
alg->cra_ablkcipher.min_keysize + CTR_RFC3686_NONCE_SIZE;
|
||||
inst->alg.cra_ablkcipher.max_keysize =
|
||||
alg->cra_ablkcipher.max_keysize + CTR_RFC3686_NONCE_SIZE;
|
||||
|
||||
inst->alg.cra_ablkcipher.geniv = "seqiv";
|
||||
|
||||
inst->alg.cra_ablkcipher.setkey = crypto_rfc3686_setkey;
|
||||
inst->alg.cra_ablkcipher.encrypt = crypto_rfc3686_crypt;
|
||||
inst->alg.cra_ablkcipher.decrypt = crypto_rfc3686_crypt;
|
||||
|
||||
inst->alg.cra_ctxsize = sizeof(struct crypto_rfc3686_ctx);
|
||||
|
||||
inst->alg.cra_init = crypto_rfc3686_init_tfm;
|
||||
inst->alg.cra_exit = crypto_rfc3686_exit_tfm;
|
||||
|
||||
inst->alg.cra_blkcipher.setkey = crypto_rfc3686_setkey;
|
||||
inst->alg.cra_blkcipher.encrypt = crypto_rfc3686_crypt;
|
||||
inst->alg.cra_blkcipher.decrypt = crypto_rfc3686_crypt;
|
||||
|
||||
out:
|
||||
crypto_mod_put(alg);
|
||||
return inst;
|
||||
|
||||
out_put_alg:
|
||||
inst = ERR_PTR(err);
|
||||
goto out;
|
||||
err_drop_spawn:
|
||||
crypto_drop_skcipher(spawn);
|
||||
err_free_inst:
|
||||
kfree(inst);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static void crypto_rfc3686_free(struct crypto_instance *inst)
|
||||
{
|
||||
struct crypto_skcipher_spawn *spawn = crypto_instance_ctx(inst);
|
||||
|
||||
crypto_drop_skcipher(spawn);
|
||||
kfree(inst);
|
||||
}
|
||||
|
||||
static struct crypto_template crypto_rfc3686_tmpl = {
|
||||
.name = "rfc3686",
|
||||
.alloc = crypto_rfc3686_alloc,
|
||||
.free = crypto_ctr_free,
|
||||
.free = crypto_rfc3686_free,
|
||||
.module = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
|
|
@ -1591,6 +1591,10 @@ static int do_test(int m)
|
|||
speed_template_16_24_32);
|
||||
test_acipher_speed("ofb(aes)", DECRYPT, sec, NULL, 0,
|
||||
speed_template_16_24_32);
|
||||
test_acipher_speed("rfc3686(ctr(aes))", ENCRYPT, sec, NULL, 0,
|
||||
speed_template_20_28_36);
|
||||
test_acipher_speed("rfc3686(ctr(aes))", DECRYPT, sec, NULL, 0,
|
||||
speed_template_20_28_36);
|
||||
break;
|
||||
|
||||
case 501:
|
||||
|
|
|
@ -51,6 +51,7 @@ static u8 speed_template_8_16[] = {8, 16, 0};
|
|||
static u8 speed_template_8_32[] = {8, 32, 0};
|
||||
static u8 speed_template_16_32[] = {16, 32, 0};
|
||||
static u8 speed_template_16_24_32[] = {16, 24, 32, 0};
|
||||
static u8 speed_template_20_28_36[] = {20, 28, 36, 0};
|
||||
static u8 speed_template_32_40_48[] = {32, 40, 48, 0};
|
||||
static u8 speed_template_32_48[] = {32, 48, 0};
|
||||
static u8 speed_template_32_48_64[] = {32, 48, 64, 0};
|
||||
|
|
|
@ -31,6 +31,8 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
|
|||
int bcma_bus_suspend(struct bcma_bus *bus);
|
||||
int bcma_bus_resume(struct bcma_bus *bus);
|
||||
#endif
|
||||
struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
|
||||
u8 unit);
|
||||
|
||||
/* scan.c */
|
||||
int bcma_bus_scan(struct bcma_bus *bus);
|
||||
|
@ -45,6 +47,7 @@ int bcma_sprom_get(struct bcma_bus *bus);
|
|||
/* driver_chipcommon.c */
|
||||
#ifdef CONFIG_BCMA_DRIVER_MIPS
|
||||
void bcma_chipco_serial_init(struct bcma_drv_cc *cc);
|
||||
extern struct platform_device bcma_pflash_dev;
|
||||
#endif /* CONFIG_BCMA_DRIVER_MIPS */
|
||||
|
||||
/* driver_chipcommon_pmu.c */
|
||||
|
|
|
@ -329,7 +329,7 @@ void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
|
|||
return;
|
||||
}
|
||||
|
||||
irq = bcma_core_mips_irq(cc->core);
|
||||
irq = bcma_core_irq(cc->core);
|
||||
|
||||
/* Determine the registers of the UARTs */
|
||||
cc->nr_serial_ports = (cc->capabilities & BCMA_CC_CAP_NRUART);
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
#include "bcma_private.h"
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/bcma/bcma.h>
|
||||
|
||||
#include "bcma_private.h"
|
||||
|
||||
struct platform_device bcma_nflash_dev = {
|
||||
.name = "bcma_nflash",
|
||||
.num_resources = 0,
|
||||
|
|
|
@ -264,7 +264,7 @@ static u32 bcma_pmu_pll_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m)
|
|||
}
|
||||
|
||||
/* query bus clock frequency for PMU-enabled chipcommon */
|
||||
static u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc)
|
||||
u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc)
|
||||
{
|
||||
struct bcma_bus *bus = cc->core->bus;
|
||||
|
||||
|
@ -293,6 +293,7 @@ static u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc)
|
|||
}
|
||||
return BCMA_CC_PMU_HT_CLOCK;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcma_pmu_get_bus_clock);
|
||||
|
||||
/* query cpu clock frequency for PMU-enabled chipcommon */
|
||||
u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc)
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
#include "bcma_private.h"
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/bcma/bcma.h>
|
||||
|
||||
#include "bcma_private.h"
|
||||
|
||||
static struct resource bcma_sflash_resource = {
|
||||
.name = "bcma_sflash",
|
||||
.start = BCMA_SOC_FLASH2,
|
||||
|
|
|
@ -73,6 +73,16 @@ static void bcma_gpio_free(struct gpio_chip *chip, unsigned gpio)
|
|||
bcma_chipco_gpio_pullup(cc, 1 << gpio, 0);
|
||||
}
|
||||
|
||||
static int bcma_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
|
||||
{
|
||||
struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
|
||||
|
||||
if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC)
|
||||
return bcma_core_irq(cc->core);
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int bcma_gpio_init(struct bcma_drv_cc *cc)
|
||||
{
|
||||
struct gpio_chip *chip = &cc->gpio;
|
||||
|
@ -85,6 +95,7 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
|
|||
chip->set = bcma_gpio_set_value;
|
||||
chip->direction_input = bcma_gpio_direction_input;
|
||||
chip->direction_output = bcma_gpio_direction_output;
|
||||
chip->to_irq = bcma_gpio_to_irq;
|
||||
chip->ngpio = 16;
|
||||
/* There is just one SoC in one device and its GPIO addresses should be
|
||||
* deterministic to address them more easily. The other buses could get
|
||||
|
|
|
@ -14,11 +14,33 @@
|
|||
|
||||
#include <linux/bcma/bcma.h>
|
||||
|
||||
#include <linux/mtd/physmap.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial_reg.h>
|
||||
#include <linux/time.h>
|
||||
|
||||
static const char *part_probes[] = { "bcm47xxpart", NULL };
|
||||
|
||||
static struct physmap_flash_data bcma_pflash_data = {
|
||||
.part_probe_types = part_probes,
|
||||
};
|
||||
|
||||
static struct resource bcma_pflash_resource = {
|
||||
.name = "bcma_pflash",
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
struct platform_device bcma_pflash_dev = {
|
||||
.name = "physmap-flash",
|
||||
.dev = {
|
||||
.platform_data = &bcma_pflash_data,
|
||||
},
|
||||
.resource = &bcma_pflash_resource,
|
||||
.num_resources = 1,
|
||||
};
|
||||
|
||||
/* The 47162a0 hangs when reading MIPS DMP registers registers */
|
||||
static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
|
||||
{
|
||||
|
@ -74,28 +96,41 @@ static u32 bcma_core_mips_irqflag(struct bcma_device *dev)
|
|||
return dev->core_index;
|
||||
flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30);
|
||||
|
||||
return flag & 0x1F;
|
||||
if (flag)
|
||||
return flag & 0x1F;
|
||||
else
|
||||
return 0x3f;
|
||||
}
|
||||
|
||||
/* Get the MIPS IRQ assignment for a specified device.
|
||||
* If unassigned, 0 is returned.
|
||||
* If disabled, 5 is returned.
|
||||
* If not supported, 6 is returned.
|
||||
*/
|
||||
unsigned int bcma_core_mips_irq(struct bcma_device *dev)
|
||||
static unsigned int bcma_core_mips_irq(struct bcma_device *dev)
|
||||
{
|
||||
struct bcma_device *mdev = dev->bus->drv_mips.core;
|
||||
u32 irqflag;
|
||||
unsigned int irq;
|
||||
|
||||
irqflag = bcma_core_mips_irqflag(dev);
|
||||
if (irqflag == 0x3f)
|
||||
return 6;
|
||||
|
||||
for (irq = 1; irq <= 4; irq++)
|
||||
for (irq = 0; irq <= 4; irq++)
|
||||
if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) &
|
||||
(1 << irqflag))
|
||||
return irq;
|
||||
|
||||
return 0;
|
||||
return 5;
|
||||
}
|
||||
EXPORT_SYMBOL(bcma_core_mips_irq);
|
||||
|
||||
unsigned int bcma_core_irq(struct bcma_device *dev)
|
||||
{
|
||||
unsigned int mips_irq = bcma_core_mips_irq(dev);
|
||||
return mips_irq <= 4 ? mips_irq + 2 : 0;
|
||||
}
|
||||
EXPORT_SYMBOL(bcma_core_irq);
|
||||
|
||||
static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
|
||||
{
|
||||
|
@ -114,7 +149,7 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
|
|||
bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
|
||||
bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) &
|
||||
~(1 << irqflag));
|
||||
else
|
||||
else if (oldirq != 5)
|
||||
bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0);
|
||||
|
||||
/* assign the new one */
|
||||
|
@ -123,9 +158,9 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
|
|||
bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) |
|
||||
(1 << irqflag));
|
||||
} else {
|
||||
u32 oldirqflag = bcma_read32(mdev,
|
||||
BCMA_MIPS_MIPS74K_INTMASK(irq));
|
||||
if (oldirqflag) {
|
||||
u32 irqinitmask = bcma_read32(mdev,
|
||||
BCMA_MIPS_MIPS74K_INTMASK(irq));
|
||||
if (irqinitmask) {
|
||||
struct bcma_device *core;
|
||||
|
||||
/* backplane irq line is in use, find out who uses
|
||||
|
@ -133,7 +168,7 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
|
|||
*/
|
||||
list_for_each_entry(core, &bus->cores, list) {
|
||||
if ((1 << bcma_core_mips_irqflag(core)) ==
|
||||
oldirqflag) {
|
||||
irqinitmask) {
|
||||
bcma_core_mips_set_irq(core, 0);
|
||||
break;
|
||||
}
|
||||
|
@ -143,15 +178,31 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
|
|||
1 << irqflag);
|
||||
}
|
||||
|
||||
bcma_info(bus, "set_irq: core 0x%04x, irq %d => %d\n",
|
||||
dev->id.id, oldirq + 2, irq + 2);
|
||||
bcma_debug(bus, "set_irq: core 0x%04x, irq %d => %d\n",
|
||||
dev->id.id, oldirq <= 4 ? oldirq + 2 : 0, irq + 2);
|
||||
}
|
||||
|
||||
static void bcma_core_mips_set_irq_name(struct bcma_bus *bus, unsigned int irq,
|
||||
u16 coreid, u8 unit)
|
||||
{
|
||||
struct bcma_device *core;
|
||||
|
||||
core = bcma_find_core_unit(bus, coreid, unit);
|
||||
if (!core) {
|
||||
bcma_warn(bus,
|
||||
"Can not find core (id: 0x%x, unit %i) for IRQ configuration.\n",
|
||||
coreid, unit);
|
||||
return;
|
||||
}
|
||||
|
||||
bcma_core_mips_set_irq(core, irq);
|
||||
}
|
||||
|
||||
static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
|
||||
{
|
||||
int i;
|
||||
static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
|
||||
printk(KERN_INFO KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id);
|
||||
printk(KERN_DEBUG KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id);
|
||||
for (i = 0; i <= 6; i++)
|
||||
printk(" %s%s", irq_name[i], i == irq ? "*" : " ");
|
||||
printk("\n");
|
||||
|
@ -182,6 +233,7 @@ static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
|
|||
{
|
||||
struct bcma_bus *bus = mcore->core->bus;
|
||||
struct bcma_drv_cc *cc = &bus->drv_cc;
|
||||
struct bcma_pflash *pflash = &cc->pflash;
|
||||
|
||||
switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
|
||||
case BCMA_CC_FLASHT_STSER:
|
||||
|
@ -191,15 +243,20 @@ static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
|
|||
break;
|
||||
case BCMA_CC_FLASHT_PARA:
|
||||
bcma_debug(bus, "Found parallel flash\n");
|
||||
cc->pflash.present = true;
|
||||
cc->pflash.window = BCMA_SOC_FLASH2;
|
||||
cc->pflash.window_size = BCMA_SOC_FLASH2_SZ;
|
||||
pflash->present = true;
|
||||
pflash->window = BCMA_SOC_FLASH2;
|
||||
pflash->window_size = BCMA_SOC_FLASH2_SZ;
|
||||
|
||||
if ((bcma_read32(cc->core, BCMA_CC_FLASH_CFG) &
|
||||
BCMA_CC_FLASH_CFG_DS) == 0)
|
||||
cc->pflash.buswidth = 1;
|
||||
pflash->buswidth = 1;
|
||||
else
|
||||
cc->pflash.buswidth = 2;
|
||||
pflash->buswidth = 2;
|
||||
|
||||
bcma_pflash_data.width = pflash->buswidth;
|
||||
bcma_pflash_resource.start = pflash->window;
|
||||
bcma_pflash_resource.end = pflash->window + pflash->window_size;
|
||||
|
||||
break;
|
||||
default:
|
||||
bcma_err(bus, "Flash type not supported\n");
|
||||
|
@ -227,6 +284,32 @@ void bcma_core_mips_early_init(struct bcma_drv_mips *mcore)
|
|||
mcore->early_setup_done = true;
|
||||
}
|
||||
|
||||
static void bcma_fix_i2s_irqflag(struct bcma_bus *bus)
|
||||
{
|
||||
struct bcma_device *cpu, *pcie, *i2s;
|
||||
|
||||
/* Fixup the interrupts in 4716/4748 for i2s core (2010 Broadcom SDK)
|
||||
* (IRQ flags > 7 are ignored when setting the interrupt masks)
|
||||
*/
|
||||
if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4716 &&
|
||||
bus->chipinfo.id != BCMA_CHIP_ID_BCM4748)
|
||||
return;
|
||||
|
||||
cpu = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
|
||||
pcie = bcma_find_core(bus, BCMA_CORE_PCIE);
|
||||
i2s = bcma_find_core(bus, BCMA_CORE_I2S);
|
||||
if (cpu && pcie && i2s &&
|
||||
bcma_aread32(cpu, BCMA_MIPS_OOBSELINA74) == 0x08060504 &&
|
||||
bcma_aread32(pcie, BCMA_MIPS_OOBSELINA74) == 0x08060504 &&
|
||||
bcma_aread32(i2s, BCMA_MIPS_OOBSELOUTA30) == 0x88) {
|
||||
bcma_awrite32(cpu, BCMA_MIPS_OOBSELINA74, 0x07060504);
|
||||
bcma_awrite32(pcie, BCMA_MIPS_OOBSELINA74, 0x07060504);
|
||||
bcma_awrite32(i2s, BCMA_MIPS_OOBSELOUTA30, 0x87);
|
||||
bcma_debug(bus,
|
||||
"Moved i2s interrupt to oob line 7 instead of 8\n");
|
||||
}
|
||||
}
|
||||
|
||||
void bcma_core_mips_init(struct bcma_drv_mips *mcore)
|
||||
{
|
||||
struct bcma_bus *bus;
|
||||
|
@ -236,43 +319,55 @@ void bcma_core_mips_init(struct bcma_drv_mips *mcore)
|
|||
if (mcore->setup_done)
|
||||
return;
|
||||
|
||||
bcma_info(bus, "Initializing MIPS core...\n");
|
||||
bcma_debug(bus, "Initializing MIPS core...\n");
|
||||
|
||||
bcma_core_mips_early_init(mcore);
|
||||
|
||||
mcore->assigned_irqs = 1;
|
||||
bcma_fix_i2s_irqflag(bus);
|
||||
|
||||
/* Assign IRQs to all cores on the bus */
|
||||
list_for_each_entry(core, &bus->cores, list) {
|
||||
int mips_irq;
|
||||
if (core->irq)
|
||||
continue;
|
||||
|
||||
mips_irq = bcma_core_mips_irq(core);
|
||||
if (mips_irq > 4)
|
||||
core->irq = 0;
|
||||
else
|
||||
core->irq = mips_irq + 2;
|
||||
if (core->irq > 5)
|
||||
continue;
|
||||
switch (core->id.id) {
|
||||
case BCMA_CORE_PCI:
|
||||
case BCMA_CORE_PCIE:
|
||||
case BCMA_CORE_ETHERNET:
|
||||
case BCMA_CORE_ETHERNET_GBIT:
|
||||
case BCMA_CORE_MAC_GBIT:
|
||||
case BCMA_CORE_80211:
|
||||
case BCMA_CORE_USB20_HOST:
|
||||
/* These devices get their own IRQ line if available,
|
||||
* the rest goes on IRQ0
|
||||
*/
|
||||
if (mcore->assigned_irqs <= 4)
|
||||
bcma_core_mips_set_irq(core,
|
||||
mcore->assigned_irqs++);
|
||||
break;
|
||||
switch (bus->chipinfo.id) {
|
||||
case BCMA_CHIP_ID_BCM4716:
|
||||
case BCMA_CHIP_ID_BCM4748:
|
||||
bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_PCIE, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0);
|
||||
break;
|
||||
case BCMA_CHIP_ID_BCM5356:
|
||||
case BCMA_CHIP_ID_BCM47162:
|
||||
case BCMA_CHIP_ID_BCM53572:
|
||||
bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
|
||||
break;
|
||||
case BCMA_CHIP_ID_BCM5357:
|
||||
case BCMA_CHIP_ID_BCM4749:
|
||||
bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0);
|
||||
break;
|
||||
case BCMA_CHIP_ID_BCM4706:
|
||||
bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_PCIE, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_4706_MAC_GBIT,
|
||||
0);
|
||||
bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_PCIE, 1);
|
||||
bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_USB20_HOST, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_4706_CHIPCOMMON,
|
||||
0);
|
||||
break;
|
||||
default:
|
||||
list_for_each_entry(core, &bus->cores, list) {
|
||||
core->irq = bcma_core_irq(core);
|
||||
}
|
||||
bcma_err(bus,
|
||||
"Unknown device (0x%x) found, can not configure IRQs\n",
|
||||
bus->chipinfo.id);
|
||||
}
|
||||
bcma_info(bus, "IRQ reconfiguration done\n");
|
||||
bcma_debug(bus, "IRQ reconfiguration done\n");
|
||||
bcma_core_mips_dump_irq(bus);
|
||||
|
||||
mcore->setup_done = true;
|
||||
|
|
|
@ -94,19 +94,19 @@ static int bcma_extpci_read_config(struct bcma_drv_pci *pc, unsigned int dev,
|
|||
if (dev == 0) {
|
||||
/* we support only two functions on device 0 */
|
||||
if (func > 1)
|
||||
return -EINVAL;
|
||||
goto out;
|
||||
|
||||
/* accesses to config registers with offsets >= 256
|
||||
* requires indirect access.
|
||||
*/
|
||||
if (off >= PCI_CONFIG_SPACE_SIZE) {
|
||||
addr = (func << 12);
|
||||
addr |= (off & 0x0FFF);
|
||||
addr |= (off & 0x0FFC);
|
||||
val = bcma_pcie_read_config(pc, addr);
|
||||
} else {
|
||||
addr = BCMA_CORE_PCI_PCICFG0;
|
||||
addr |= (func << 8);
|
||||
addr |= (off & 0xfc);
|
||||
addr |= (off & 0xFC);
|
||||
val = pcicore_read32(pc, addr);
|
||||
}
|
||||
} else {
|
||||
|
@ -119,11 +119,9 @@ static int bcma_extpci_read_config(struct bcma_drv_pci *pc, unsigned int dev,
|
|||
goto out;
|
||||
|
||||
if (mips_busprobe32(val, mmio)) {
|
||||
val = 0xffffffff;
|
||||
val = 0xFFFFFFFF;
|
||||
goto unmap;
|
||||
}
|
||||
|
||||
val = readl(mmio);
|
||||
}
|
||||
val >>= (8 * (off & 3));
|
||||
|
||||
|
@ -151,7 +149,7 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev,
|
|||
const void *buf, int len)
|
||||
{
|
||||
int err = -EINVAL;
|
||||
u32 addr = 0, val = 0;
|
||||
u32 addr, val;
|
||||
void __iomem *mmio = 0;
|
||||
u16 chipid = pc->core->bus->chipinfo.id;
|
||||
|
||||
|
@ -159,16 +157,22 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev,
|
|||
if (unlikely(len != 1 && len != 2 && len != 4))
|
||||
goto out;
|
||||
if (dev == 0) {
|
||||
/* we support only two functions on device 0 */
|
||||
if (func > 1)
|
||||
goto out;
|
||||
|
||||
/* accesses to config registers with offsets >= 256
|
||||
* requires indirect access.
|
||||
*/
|
||||
if (off < PCI_CONFIG_SPACE_SIZE) {
|
||||
addr = pc->core->addr + BCMA_CORE_PCI_PCICFG0;
|
||||
if (off >= PCI_CONFIG_SPACE_SIZE) {
|
||||
addr = (func << 12);
|
||||
addr |= (off & 0x0FFC);
|
||||
val = bcma_pcie_read_config(pc, addr);
|
||||
} else {
|
||||
addr = BCMA_CORE_PCI_PCICFG0;
|
||||
addr |= (func << 8);
|
||||
addr |= (off & 0xfc);
|
||||
mmio = ioremap_nocache(addr, sizeof(val));
|
||||
if (!mmio)
|
||||
goto out;
|
||||
addr |= (off & 0xFC);
|
||||
val = pcicore_read32(pc, addr);
|
||||
}
|
||||
} else {
|
||||
addr = bcma_get_cfgspace_addr(pc, dev, func, off);
|
||||
|
@ -180,19 +184,17 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev,
|
|||
goto out;
|
||||
|
||||
if (mips_busprobe32(val, mmio)) {
|
||||
val = 0xffffffff;
|
||||
val = 0xFFFFFFFF;
|
||||
goto unmap;
|
||||
}
|
||||
}
|
||||
|
||||
switch (len) {
|
||||
case 1:
|
||||
val = readl(mmio);
|
||||
val &= ~(0xFF << (8 * (off & 3)));
|
||||
val |= *((const u8 *)buf) << (8 * (off & 3));
|
||||
break;
|
||||
case 2:
|
||||
val = readl(mmio);
|
||||
val &= ~(0xFFFF << (8 * (off & 3)));
|
||||
val |= *((const u16 *)buf) << (8 * (off & 3));
|
||||
break;
|
||||
|
@ -200,13 +202,14 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev,
|
|||
val = *((const u32 *)buf);
|
||||
break;
|
||||
}
|
||||
if (dev == 0 && !addr) {
|
||||
if (dev == 0) {
|
||||
/* accesses to config registers with offsets >= 256
|
||||
* requires indirect access.
|
||||
*/
|
||||
addr = (func << 12);
|
||||
addr |= (off & 0x0FFF);
|
||||
bcma_pcie_write_config(pc, addr, val);
|
||||
if (off >= PCI_CONFIG_SPACE_SIZE)
|
||||
bcma_pcie_write_config(pc, addr, val);
|
||||
else
|
||||
pcicore_write32(pc, addr, val);
|
||||
} else {
|
||||
writel(val, mmio);
|
||||
|
||||
|
@ -276,7 +279,7 @@ static u8 bcma_find_pci_capability(struct bcma_drv_pci *pc, unsigned int dev,
|
|||
/* check for Header type 0 */
|
||||
bcma_extpci_read_config(pc, dev, func, PCI_HEADER_TYPE, &byte_val,
|
||||
sizeof(u8));
|
||||
if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL)
|
||||
if ((byte_val & 0x7F) != PCI_HEADER_TYPE_NORMAL)
|
||||
return cap_ptr;
|
||||
|
||||
/* check if the capability pointer field exists */
|
||||
|
@ -426,7 +429,7 @@ void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
|
|||
/* Reset RC */
|
||||
usleep_range(3000, 5000);
|
||||
pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE);
|
||||
usleep_range(1000, 2000);
|
||||
msleep(50);
|
||||
pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST |
|
||||
BCMA_CORE_PCI_CTL_RST_OE);
|
||||
|
||||
|
@ -488,6 +491,17 @@ void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
|
|||
|
||||
bcma_core_pci_enable_crs(pc);
|
||||
|
||||
if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706 ||
|
||||
bus->chipinfo.id == BCMA_CHIP_ID_BCM4716) {
|
||||
u16 val16;
|
||||
bcma_extpci_read_config(pc, 0, 0, BCMA_CORE_PCI_CFG_DEVCTRL,
|
||||
&val16, sizeof(val16));
|
||||
val16 |= (2 << 5); /* Max payload size of 512 */
|
||||
val16 |= (2 << 12); /* MRRS 512 */
|
||||
bcma_extpci_write_config(pc, 0, 0, BCMA_CORE_PCI_CFG_DEVCTRL,
|
||||
&val16, sizeof(val16));
|
||||
}
|
||||
|
||||
/* Enable PCI bridge BAR0 memory & master access */
|
||||
tmp = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
|
||||
bcma_extpci_write_config(pc, 0, 0, PCI_COMMAND, &tmp, sizeof(tmp));
|
||||
|
@ -576,7 +590,7 @@ int bcma_core_pci_plat_dev_init(struct pci_dev *dev)
|
|||
pr_info("PCI: Fixing up device %s\n", pci_name(dev));
|
||||
|
||||
/* Fix up interrupt lines */
|
||||
dev->irq = bcma_core_mips_irq(pc_host->pdev->core) + 2;
|
||||
dev->irq = bcma_core_irq(pc_host->pdev->core);
|
||||
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
|
||||
|
||||
return 0;
|
||||
|
@ -595,6 +609,6 @@ int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev)
|
|||
|
||||
pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host,
|
||||
pci_ops);
|
||||
return bcma_core_mips_irq(pc_host->pdev->core) + 2;
|
||||
return bcma_core_irq(pc_host->pdev->core);
|
||||
}
|
||||
EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq);
|
||||
|
|
|
@ -81,8 +81,8 @@ struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(bcma_find_core);
|
||||
|
||||
static struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
|
||||
u8 unit)
|
||||
struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
|
||||
u8 unit)
|
||||
{
|
||||
struct bcma_device *core;
|
||||
|
||||
|
@ -149,6 +149,14 @@ static int bcma_register_cores(struct bcma_bus *bus)
|
|||
dev_id++;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BCMA_DRIVER_MIPS
|
||||
if (bus->drv_cc.pflash.present) {
|
||||
err = platform_device_register(&bcma_pflash_dev);
|
||||
if (err)
|
||||
bcma_err(bus, "Error registering parallel flash\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BCMA_SFLASH
|
||||
if (bus->drv_cc.sflash.present) {
|
||||
err = platform_device_register(&bcma_sflash_dev);
|
||||
|
|
|
@ -276,7 +276,7 @@ static int cn_init(void)
|
|||
|
||||
cn_already_initialized = 1;
|
||||
|
||||
proc_net_fops_create(&init_net, "connector", S_IRUGO, &cn_file_ops);
|
||||
proc_create("connector", S_IRUGO, init_net.proc_net, &cn_file_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -287,7 +287,7 @@ static void cn_fini(void)
|
|||
|
||||
cn_already_initialized = 0;
|
||||
|
||||
proc_net_remove(&init_net, "connector");
|
||||
remove_proc_entry("connector", init_net.proc_net);
|
||||
|
||||
cn_queue_free_dev(dev->cbdev);
|
||||
netlink_kernel_release(dev->nls);
|
||||
|
|
|
@ -270,7 +270,7 @@ static int fwnet_header_cache(const struct neighbour *neigh,
|
|||
if (type == cpu_to_be16(ETH_P_802_3))
|
||||
return -1;
|
||||
net = neigh->dev;
|
||||
h = (struct fwnet_header *)((u8 *)hh->hh_data + 16 - sizeof(*h));
|
||||
h = (struct fwnet_header *)((u8 *)hh->hh_data + HH_DATA_OFF(sizeof(*h)));
|
||||
h->h_proto = type;
|
||||
memcpy(h->h_dest, neigh->ha, net->addr_len);
|
||||
hh->hh_len = FWNET_HLEN;
|
||||
|
@ -282,7 +282,7 @@ static int fwnet_header_cache(const struct neighbour *neigh,
|
|||
static void fwnet_header_cache_update(struct hh_cache *hh,
|
||||
const struct net_device *net, const unsigned char *haddr)
|
||||
{
|
||||
memcpy((u8 *)hh->hh_data + 16 - FWNET_HLEN, haddr, net->addr_len);
|
||||
memcpy((u8 *)hh->hh_data + HH_DATA_OFF(FWNET_HLEN), haddr, net->addr_len);
|
||||
}
|
||||
|
||||
static int fwnet_header_parse(const struct sk_buff *skb, unsigned char *haddr)
|
||||
|
@ -398,11 +398,11 @@ static struct fwnet_partial_datagram *fwnet_pd_new(struct net_device *net,
|
|||
|
||||
new->datagram_label = datagram_label;
|
||||
new->datagram_size = dg_size;
|
||||
new->skb = dev_alloc_skb(dg_size + net->hard_header_len + 15);
|
||||
new->skb = dev_alloc_skb(dg_size + LL_RESERVED_SPACE(net));
|
||||
if (new->skb == NULL)
|
||||
goto fail_w_fi;
|
||||
|
||||
skb_reserve(new->skb, (net->hard_header_len + 15) & ~15);
|
||||
skb_reserve(new->skb, LL_RESERVED_SPACE(net));
|
||||
new->pbuf = skb_put(new->skb, dg_size);
|
||||
memcpy(new->pbuf + frag_off, frag_buf, frag_len);
|
||||
list_add_tail(&new->pd_link, &peer->pd_list);
|
||||
|
@ -520,7 +520,7 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
|
|||
dev = netdev_priv(net);
|
||||
/* Write metadata, and then pass to the receive level */
|
||||
skb->dev = net;
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
|
||||
/*
|
||||
* Parse the encapsulation header. This actually does the job of
|
||||
|
@ -690,14 +690,14 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
|
|||
buf++;
|
||||
len -= RFC2374_UNFRAG_HDR_SIZE;
|
||||
|
||||
skb = dev_alloc_skb(len + net->hard_header_len + 15);
|
||||
skb = dev_alloc_skb(len + LL_RESERVED_SPACE(net));
|
||||
if (unlikely(!skb)) {
|
||||
dev_err(&net->dev, "out of memory\n");
|
||||
net->stats.rx_dropped++;
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
skb_reserve(skb, (net->hard_header_len + 15) & ~15);
|
||||
skb_reserve(skb, LL_RESERVED_SPACE(net));
|
||||
memcpy(skb_put(skb, len), buf, len);
|
||||
|
||||
return fwnet_finish_incoming_packet(net, skb, source_node_id,
|
||||
|
|
|
@ -135,6 +135,7 @@ static int nes_inetaddr_event(struct notifier_block *notifier,
|
|||
struct net_device *event_netdev = ifa->ifa_dev->dev;
|
||||
struct nes_device *nesdev;
|
||||
struct net_device *netdev;
|
||||
struct net_device *upper_dev;
|
||||
struct nes_vnic *nesvnic;
|
||||
unsigned int is_bonded;
|
||||
|
||||
|
@ -145,8 +146,9 @@ static int nes_inetaddr_event(struct notifier_block *notifier,
|
|||
nesdev, nesdev->netdev[0]->name);
|
||||
netdev = nesdev->netdev[0];
|
||||
nesvnic = netdev_priv(netdev);
|
||||
upper_dev = netdev_master_upper_dev_get(netdev);
|
||||
is_bonded = netif_is_bond_slave(netdev) &&
|
||||
(netdev->master == event_netdev);
|
||||
(upper_dev == event_netdev);
|
||||
if ((netdev == event_netdev) || is_bonded) {
|
||||
if (nesvnic->rdma_enabled == 0) {
|
||||
nes_debug(NES_DBG_NETDEV, "Returning without processing event for %s since"
|
||||
|
@ -179,9 +181,9 @@ static int nes_inetaddr_event(struct notifier_block *notifier,
|
|||
/* fall through */
|
||||
case NETDEV_CHANGEADDR:
|
||||
/* Add the address to the IP table */
|
||||
if (netdev->master)
|
||||
if (upper_dev)
|
||||
nesvnic->local_ipaddr =
|
||||
((struct in_device *)netdev->master->ip_ptr)->ifa_list->ifa_address;
|
||||
((struct in_device *)upper_dev->ip_ptr)->ifa_list->ifa_address;
|
||||
else
|
||||
nesvnic->local_ipaddr = ifa->ifa_address;
|
||||
|
||||
|
|
|
@ -1340,7 +1340,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
|
|||
}
|
||||
|
||||
if (netif_is_bond_slave(nesvnic->netdev))
|
||||
netdev = nesvnic->netdev->master;
|
||||
netdev = netdev_master_upper_dev_get(nesvnic->netdev);
|
||||
else
|
||||
netdev = nesvnic->netdev;
|
||||
|
||||
|
|
|
@ -1317,11 +1317,13 @@ static void nes_netdev_get_drvinfo(struct net_device *netdev,
|
|||
struct nes_vnic *nesvnic = netdev_priv(netdev);
|
||||
struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter;
|
||||
|
||||
strcpy(drvinfo->driver, DRV_NAME);
|
||||
strcpy(drvinfo->bus_info, pci_name(nesvnic->nesdev->pcidev));
|
||||
sprintf(drvinfo->fw_version, "%u.%u", nesadapter->firmware_version>>16,
|
||||
nesadapter->firmware_version & 0x000000ff);
|
||||
strcpy(drvinfo->version, DRV_VERSION);
|
||||
strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
|
||||
strlcpy(drvinfo->bus_info, pci_name(nesvnic->nesdev->pcidev),
|
||||
sizeof(drvinfo->bus_info));
|
||||
snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
|
||||
"%u.%u", nesadapter->firmware_version >> 16,
|
||||
nesadapter->firmware_version & 0x000000ff);
|
||||
strlcpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version));
|
||||
drvinfo->testinfo_len = 0;
|
||||
drvinfo->eedump_len = 0;
|
||||
drvinfo->regdump_len = 0;
|
||||
|
@ -1703,7 +1705,6 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
|
|||
netdev->dev_addr[3] = (u8)(u64temp>>16);
|
||||
netdev->dev_addr[4] = (u8)(u64temp>>8);
|
||||
netdev->dev_addr[5] = (u8)u64temp;
|
||||
memcpy(netdev->perm_addr, netdev->dev_addr, 6);
|
||||
|
||||
netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX;
|
||||
if ((nesvnic->logical_port < 2) || (nesdev->nesadapter->hw_rev != NE020_REV))
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
static void ipoib_get_drvinfo(struct net_device *netdev,
|
||||
struct ethtool_drvinfo *drvinfo)
|
||||
{
|
||||
strncpy(drvinfo->driver, "ipoib", sizeof(drvinfo->driver) - 1);
|
||||
strlcpy(drvinfo->driver, "ipoib", sizeof(drvinfo->driver));
|
||||
}
|
||||
|
||||
static int ipoib_get_coalesce(struct net_device *dev,
|
||||
|
|
|
@ -22,13 +22,13 @@ MODULE_LICENSE("GPL");
|
|||
/****************************************/
|
||||
/* structure containing interface to hl */
|
||||
/****************************************/
|
||||
isdn_divert_if divert_if =
|
||||
{ DIVERT_IF_MAGIC, /* magic value */
|
||||
DIVERT_CMD_REG, /* register cmd */
|
||||
ll_callback, /* callback routine from ll */
|
||||
NULL, /* command still not specified */
|
||||
NULL, /* drv_to_name */
|
||||
NULL, /* name_to_drv */
|
||||
isdn_divert_if divert_if = {
|
||||
DIVERT_IF_MAGIC, /* magic value */
|
||||
DIVERT_CMD_REG, /* register cmd */
|
||||
ll_callback, /* callback routine from ll */
|
||||
NULL, /* command still not specified */
|
||||
NULL, /* drv_to_name */
|
||||
NULL, /* name_to_drv */
|
||||
};
|
||||
|
||||
/*************************/
|
||||
|
@ -36,14 +36,15 @@ isdn_divert_if divert_if =
|
|||
/* no cmd line parms */
|
||||
/*************************/
|
||||
static int __init divert_init(void)
|
||||
{ int i;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (divert_dev_init())
|
||||
{ printk(KERN_WARNING "dss1_divert: cannot install device, not loaded\n");
|
||||
if (divert_dev_init()) {
|
||||
printk(KERN_WARNING "dss1_divert: cannot install device, not loaded\n");
|
||||
return (-EIO);
|
||||
}
|
||||
if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR)
|
||||
{ divert_dev_deinit();
|
||||
if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR) {
|
||||
divert_dev_deinit();
|
||||
printk(KERN_WARNING "dss1_divert: error %d registering module, not loaded\n", i);
|
||||
return (-EIO);
|
||||
}
|
||||
|
@ -61,13 +62,13 @@ static void __exit divert_exit(void)
|
|||
|
||||
spin_lock_irqsave(&divert_lock, flags);
|
||||
divert_if.cmd = DIVERT_CMD_REL; /* release */
|
||||
if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR)
|
||||
{ printk(KERN_WARNING "dss1_divert: error %d releasing module\n", i);
|
||||
if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR) {
|
||||
printk(KERN_WARNING "dss1_divert: error %d releasing module\n", i);
|
||||
spin_unlock_irqrestore(&divert_lock, flags);
|
||||
return;
|
||||
}
|
||||
if (divert_dev_deinit())
|
||||
{ printk(KERN_WARNING "dss1_divert: device busy, remove cancelled\n");
|
||||
if (divert_dev_deinit()) {
|
||||
printk(KERN_WARNING "dss1_divert: device busy, remove cancelled\n");
|
||||
spin_unlock_irqrestore(&divert_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
/**********************************/
|
||||
/* structure keeping calling info */
|
||||
/**********************************/
|
||||
struct call_struc
|
||||
{ isdn_ctrl ics; /* delivered setup + driver parameters */
|
||||
struct call_struc {
|
||||
isdn_ctrl ics; /* delivered setup + driver parameters */
|
||||
ulong divert_id; /* Id delivered to user */
|
||||
unsigned char akt_state; /* actual state */
|
||||
char deflect_dest[35]; /* deflection destination */
|
||||
|
@ -34,8 +34,8 @@ struct call_struc
|
|||
/********************************************/
|
||||
/* structure keeping deflection table entry */
|
||||
/********************************************/
|
||||
struct deflect_struc
|
||||
{ struct deflect_struc *next, *prev;
|
||||
struct deflect_struc {
|
||||
struct deflect_struc *next, *prev;
|
||||
divert_rule rule; /* used rule */
|
||||
};
|
||||
|
||||
|
@ -64,16 +64,16 @@ static void deflect_timer_expire(ulong arg)
|
|||
del_timer(&cs->timer); /* delete active timer */
|
||||
spin_unlock_irqrestore(&divert_lock, flags);
|
||||
|
||||
switch (cs->akt_state)
|
||||
{ case DEFLECT_PROCEED:
|
||||
cs->ics.command = ISDN_CMD_HANGUP; /* cancel action */
|
||||
divert_if.ll_cmd(&cs->ics);
|
||||
spin_lock_irqsave(&divert_lock, flags);
|
||||
cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
|
||||
cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
|
||||
add_timer(&cs->timer);
|
||||
spin_unlock_irqrestore(&divert_lock, flags);
|
||||
break;
|
||||
switch (cs->akt_state) {
|
||||
case DEFLECT_PROCEED:
|
||||
cs->ics.command = ISDN_CMD_HANGUP; /* cancel action */
|
||||
divert_if.ll_cmd(&cs->ics);
|
||||
spin_lock_irqsave(&divert_lock, flags);
|
||||
cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
|
||||
cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
|
||||
add_timer(&cs->timer);
|
||||
spin_unlock_irqrestore(&divert_lock, flags);
|
||||
break;
|
||||
|
||||
case DEFLECT_ALERT:
|
||||
cs->ics.command = ISDN_CMD_REDIR; /* protocol */
|
||||
|
@ -111,7 +111,8 @@ static void deflect_timer_expire(ulong arg)
|
|||
int cf_command(int drvid, int mode,
|
||||
u_char proc, char *msn,
|
||||
u_char service, char *fwd_nr, ulong *procid)
|
||||
{ unsigned long flags;
|
||||
{
|
||||
unsigned long flags;
|
||||
int retval, msnlen;
|
||||
int fwd_len;
|
||||
char *p, *ielenp, tmp[60];
|
||||
|
@ -130,8 +131,8 @@ int cf_command(int drvid, int mode,
|
|||
*p++ = 1; /* length */
|
||||
*p++ = service; /* service to handle */
|
||||
|
||||
if (mode == 1)
|
||||
{ if (!*fwd_nr) return (-EINVAL); /* destination missing */
|
||||
if (mode == 1) {
|
||||
if (!*fwd_nr) return (-EINVAL); /* destination missing */
|
||||
if (strchr(fwd_nr, '.')) return (-EINVAL); /* subaddress not allowed */
|
||||
fwd_len = strlen(fwd_nr);
|
||||
*p++ = 0x30; /* number enumeration */
|
||||
|
@ -144,12 +145,12 @@ int cf_command(int drvid, int mode,
|
|||
|
||||
msnlen = strlen(msn);
|
||||
*p++ = 0x80; /* msn number */
|
||||
if (msnlen > 1)
|
||||
{ *p++ = msnlen; /* length */
|
||||
if (msnlen > 1) {
|
||||
*p++ = msnlen; /* length */
|
||||
strcpy(p, msn);
|
||||
p += msnlen;
|
||||
}
|
||||
else *p++ = 0;
|
||||
} else
|
||||
*p++ = 0;
|
||||
|
||||
*ielenp = p - ielenp - 1; /* set total IE length */
|
||||
|
||||
|
@ -186,14 +187,13 @@ int cf_command(int drvid, int mode,
|
|||
|
||||
retval = divert_if.ll_cmd(&cs->ics); /* execute command */
|
||||
|
||||
if (!retval)
|
||||
{ cs->prev = NULL;
|
||||
if (!retval) {
|
||||
cs->prev = NULL;
|
||||
spin_lock_irqsave(&divert_lock, flags);
|
||||
cs->next = divert_head;
|
||||
divert_head = cs;
|
||||
spin_unlock_irqrestore(&divert_lock, flags);
|
||||
}
|
||||
else
|
||||
} else
|
||||
kfree(cs);
|
||||
return (retval);
|
||||
} /* cf_command */
|
||||
|
@ -203,15 +203,16 @@ int cf_command(int drvid, int mode,
|
|||
/* handle a external deflection command */
|
||||
/****************************************/
|
||||
int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
|
||||
{ struct call_struc *cs;
|
||||
{
|
||||
struct call_struc *cs;
|
||||
isdn_ctrl ic;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
if ((cmd & 0x7F) > 2) return (-EINVAL); /* invalid command */
|
||||
cs = divert_head; /* start of parameter list */
|
||||
while (cs)
|
||||
{ if (cs->divert_id == callid) break; /* found */
|
||||
while (cs) {
|
||||
if (cs->divert_id == callid) break; /* found */
|
||||
cs = cs->next;
|
||||
} /* search entry */
|
||||
if (!cs) return (-EINVAL); /* invalid callid */
|
||||
|
@ -220,32 +221,30 @@ int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
|
|||
ic.arg = cs->ics.arg;
|
||||
i = -EINVAL;
|
||||
if (cs->akt_state == DEFLECT_AUTODEL) return (i); /* no valid call */
|
||||
switch (cmd & 0x7F)
|
||||
{ case 0: /* hangup */
|
||||
del_timer(&cs->timer);
|
||||
ic.command = ISDN_CMD_HANGUP;
|
||||
i = divert_if.ll_cmd(&ic);
|
||||
spin_lock_irqsave(&divert_lock, flags);
|
||||
cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
|
||||
cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
|
||||
add_timer(&cs->timer);
|
||||
spin_unlock_irqrestore(&divert_lock, flags);
|
||||
break;
|
||||
switch (cmd & 0x7F) {
|
||||
case 0: /* hangup */
|
||||
del_timer(&cs->timer);
|
||||
ic.command = ISDN_CMD_HANGUP;
|
||||
i = divert_if.ll_cmd(&ic);
|
||||
spin_lock_irqsave(&divert_lock, flags);
|
||||
cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
|
||||
cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
|
||||
add_timer(&cs->timer);
|
||||
spin_unlock_irqrestore(&divert_lock, flags);
|
||||
break;
|
||||
|
||||
case 1: /* alert */
|
||||
if (cs->akt_state == DEFLECT_ALERT) return (0);
|
||||
cmd &= 0x7F; /* never wait */
|
||||
del_timer(&cs->timer);
|
||||
ic.command = ISDN_CMD_ALERT;
|
||||
if ((i = divert_if.ll_cmd(&ic)))
|
||||
{
|
||||
if ((i = divert_if.ll_cmd(&ic))) {
|
||||
spin_lock_irqsave(&divert_lock, flags);
|
||||
cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
|
||||
cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
|
||||
add_timer(&cs->timer);
|
||||
spin_unlock_irqrestore(&divert_lock, flags);
|
||||
}
|
||||
else
|
||||
} else
|
||||
cs->akt_state = DEFLECT_ALERT;
|
||||
break;
|
||||
|
||||
|
@ -254,15 +253,13 @@ int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
|
|||
strlcpy(cs->ics.parm.setup.phone, to_nr, sizeof(cs->ics.parm.setup.phone));
|
||||
strcpy(cs->ics.parm.setup.eazmsn, "Testtext manual");
|
||||
ic.command = ISDN_CMD_REDIR;
|
||||
if ((i = divert_if.ll_cmd(&ic)))
|
||||
{
|
||||
if ((i = divert_if.ll_cmd(&ic))) {
|
||||
spin_lock_irqsave(&divert_lock, flags);
|
||||
cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
|
||||
cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
|
||||
add_timer(&cs->timer);
|
||||
spin_unlock_irqrestore(&divert_lock, flags);
|
||||
}
|
||||
else
|
||||
} else
|
||||
cs->akt_state = DEFLECT_ALERT;
|
||||
break;
|
||||
|
||||
|
@ -274,19 +271,19 @@ int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
|
|||
/* insert a new rule before idx */
|
||||
/********************************/
|
||||
int insertrule(int idx, divert_rule *newrule)
|
||||
{ struct deflect_struc *ds, *ds1 = NULL;
|
||||
{
|
||||
struct deflect_struc *ds, *ds1 = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
if (!(ds = kmalloc(sizeof(struct deflect_struc),
|
||||
GFP_KERNEL)))
|
||||
if (!(ds = kmalloc(sizeof(struct deflect_struc), GFP_KERNEL)))
|
||||
return (-ENOMEM); /* no memory */
|
||||
|
||||
ds->rule = *newrule; /* set rule */
|
||||
|
||||
spin_lock_irqsave(&divert_lock, flags);
|
||||
|
||||
if (idx >= 0)
|
||||
{ ds1 = table_head;
|
||||
if (idx >= 0) {
|
||||
ds1 = table_head;
|
||||
while ((ds1) && (idx > 0))
|
||||
{ idx--;
|
||||
ds1 = ds1->next;
|
||||
|
@ -294,17 +291,16 @@ int insertrule(int idx, divert_rule *newrule)
|
|||
if (!ds1) idx = -1;
|
||||
}
|
||||
|
||||
if (idx < 0)
|
||||
{ ds->prev = table_tail; /* previous entry */
|
||||
if (idx < 0) {
|
||||
ds->prev = table_tail; /* previous entry */
|
||||
ds->next = NULL; /* end of chain */
|
||||
if (ds->prev)
|
||||
ds->prev->next = ds; /* last forward */
|
||||
else
|
||||
table_head = ds; /* is first entry */
|
||||
table_tail = ds; /* end of queue */
|
||||
}
|
||||
else
|
||||
{ ds->next = ds1; /* next entry */
|
||||
} else {
|
||||
ds->next = ds1; /* next entry */
|
||||
ds->prev = ds1->prev; /* prev entry */
|
||||
ds1->prev = ds; /* backward chain old element */
|
||||
if (!ds->prev)
|
||||
|
@ -319,17 +315,18 @@ int insertrule(int idx, divert_rule *newrule)
|
|||
/* delete the rule at position idx */
|
||||
/***********************************/
|
||||
int deleterule(int idx)
|
||||
{ struct deflect_struc *ds, *ds1;
|
||||
{
|
||||
struct deflect_struc *ds, *ds1;
|
||||
unsigned long flags;
|
||||
|
||||
if (idx < 0)
|
||||
{ spin_lock_irqsave(&divert_lock, flags);
|
||||
if (idx < 0) {
|
||||
spin_lock_irqsave(&divert_lock, flags);
|
||||
ds = table_head;
|
||||
table_head = NULL;
|
||||
table_tail = NULL;
|
||||
spin_unlock_irqrestore(&divert_lock, flags);
|
||||
while (ds)
|
||||
{ ds1 = ds;
|
||||
while (ds) {
|
||||
ds1 = ds;
|
||||
ds = ds->next;
|
||||
kfree(ds1);
|
||||
}
|
||||
|
@ -339,13 +336,12 @@ int deleterule(int idx)
|
|||
spin_lock_irqsave(&divert_lock, flags);
|
||||
ds = table_head;
|
||||
|
||||
while ((ds) && (idx > 0))
|
||||
{ idx--;
|
||||
while ((ds) && (idx > 0)) {
|
||||
idx--;
|
||||
ds = ds->next;
|
||||
}
|
||||
|
||||
if (!ds)
|
||||
{
|
||||
if (!ds) {
|
||||
spin_unlock_irqrestore(&divert_lock, flags);
|
||||
return (-EINVAL);
|
||||
}
|
||||
|
@ -369,12 +365,13 @@ int deleterule(int idx)
|
|||
/* get a pointer to a specific rule number */
|
||||
/*******************************************/
|
||||
divert_rule *getruleptr(int idx)
|
||||
{ struct deflect_struc *ds = table_head;
|
||||
{
|
||||
struct deflect_struc *ds = table_head;
|
||||
|
||||
if (idx < 0) return (NULL);
|
||||
while ((ds) && (idx >= 0))
|
||||
{ if (!(idx--))
|
||||
{ return (&ds->rule);
|
||||
while ((ds) && (idx >= 0)) {
|
||||
if (!(idx--)) {
|
||||
return (&ds->rule);
|
||||
break;
|
||||
}
|
||||
ds = ds->next;
|
||||
|
@ -386,7 +383,8 @@ divert_rule *getruleptr(int idx)
|
|||
/* called from common module on an incoming call */
|
||||
/*************************************************/
|
||||
static int isdn_divert_icall(isdn_ctrl *ic)
|
||||
{ int retval = 0;
|
||||
{
|
||||
int retval = 0;
|
||||
unsigned long flags;
|
||||
struct call_struc *cs = NULL;
|
||||
struct deflect_struc *dv;
|
||||
|
@ -394,8 +392,8 @@ static int isdn_divert_icall(isdn_ctrl *ic)
|
|||
u_char accept;
|
||||
|
||||
/* first check the internal deflection table */
|
||||
for (dv = table_head; dv; dv = dv->next)
|
||||
{ /* scan table */
|
||||
for (dv = table_head; dv; dv = dv->next) {
|
||||
/* scan table */
|
||||
if (((dv->rule.callopt == 1) && (ic->command == ISDN_STAT_ICALLW)) ||
|
||||
((dv->rule.callopt == 2) && (ic->command == ISDN_STAT_ICALL)))
|
||||
continue; /* call option check */
|
||||
|
@ -409,10 +407,10 @@ static int isdn_divert_icall(isdn_ctrl *ic)
|
|||
p = dv->rule.my_msn;
|
||||
p1 = ic->parm.setup.eazmsn;
|
||||
accept = 0;
|
||||
while (*p)
|
||||
{ /* complete compare */
|
||||
if (*p == '-')
|
||||
{ accept = 1; /* call accepted */
|
||||
while (*p) {
|
||||
/* complete compare */
|
||||
if (*p == '-') {
|
||||
accept = 1; /* call accepted */
|
||||
break;
|
||||
}
|
||||
if (*p++ != *p1++)
|
||||
|
@ -422,14 +420,15 @@ static int isdn_divert_icall(isdn_ctrl *ic)
|
|||
} /* complete compare */
|
||||
if (!accept) continue; /* not accepted */
|
||||
|
||||
if ((strcmp(dv->rule.caller, "0")) || (ic->parm.setup.phone[0]))
|
||||
{ p = dv->rule.caller;
|
||||
if ((strcmp(dv->rule.caller, "0")) ||
|
||||
(ic->parm.setup.phone[0])) {
|
||||
p = dv->rule.caller;
|
||||
p1 = ic->parm.setup.phone;
|
||||
accept = 0;
|
||||
while (*p)
|
||||
{ /* complete compare */
|
||||
if (*p == '-')
|
||||
{ accept = 1; /* call accepted */
|
||||
while (*p) {
|
||||
/* complete compare */
|
||||
if (*p == '-') {
|
||||
accept = 1; /* call accepted */
|
||||
break;
|
||||
}
|
||||
if (*p++ != *p1++)
|
||||
|
@ -440,10 +439,10 @@ static int isdn_divert_icall(isdn_ctrl *ic)
|
|||
if (!accept) continue; /* not accepted */
|
||||
}
|
||||
|
||||
switch (dv->rule.action)
|
||||
{ case DEFLECT_IGNORE:
|
||||
return (0);
|
||||
break;
|
||||
switch (dv->rule.action) {
|
||||
case DEFLECT_IGNORE:
|
||||
return (0);
|
||||
break;
|
||||
|
||||
case DEFLECT_ALERT:
|
||||
case DEFLECT_PROCEED:
|
||||
|
@ -465,31 +464,29 @@ static int isdn_divert_icall(isdn_ctrl *ic)
|
|||
cs->ics.parm.setup.screen = dv->rule.screen;
|
||||
if (dv->rule.waittime)
|
||||
cs->timer.expires = jiffies + (HZ * dv->rule.waittime);
|
||||
else if (dv->rule.action == DEFLECT_PROCEED)
|
||||
cs->timer.expires = jiffies + (HZ * extern_wait_max);
|
||||
else
|
||||
if (dv->rule.action == DEFLECT_PROCEED)
|
||||
cs->timer.expires = jiffies + (HZ * extern_wait_max);
|
||||
else
|
||||
cs->timer.expires = 0;
|
||||
cs->timer.expires = 0;
|
||||
cs->akt_state = dv->rule.action;
|
||||
spin_lock_irqsave(&divert_lock, flags);
|
||||
cs->divert_id = next_id++; /* new sequence number */
|
||||
spin_unlock_irqrestore(&divert_lock, flags);
|
||||
cs->prev = NULL;
|
||||
if (cs->akt_state == DEFLECT_ALERT)
|
||||
{ strcpy(cs->deflect_dest, dv->rule.to_nr);
|
||||
if (!cs->timer.expires)
|
||||
{ strcpy(ic->parm.setup.eazmsn, "Testtext direct");
|
||||
if (cs->akt_state == DEFLECT_ALERT) {
|
||||
strcpy(cs->deflect_dest, dv->rule.to_nr);
|
||||
if (!cs->timer.expires) {
|
||||
strcpy(ic->parm.setup.eazmsn,
|
||||
"Testtext direct");
|
||||
ic->parm.setup.screen = dv->rule.screen;
|
||||
strlcpy(ic->parm.setup.phone, dv->rule.to_nr, sizeof(ic->parm.setup.phone));
|
||||
cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
|
||||
cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
|
||||
retval = 5;
|
||||
}
|
||||
else
|
||||
} else
|
||||
retval = 1; /* alerting */
|
||||
}
|
||||
else
|
||||
{ cs->deflect_dest[0] = '\0';
|
||||
} else {
|
||||
cs->deflect_dest[0] = '\0';
|
||||
retval = 4; /* only proceed */
|
||||
}
|
||||
sprintf(cs->info, "%d 0x%lx %s %s %s %s 0x%x 0x%x %d %d %s\n",
|
||||
|
@ -505,8 +502,8 @@ static int isdn_divert_icall(isdn_ctrl *ic)
|
|||
dv->rule.waittime,
|
||||
cs->deflect_dest);
|
||||
if ((dv->rule.action == DEFLECT_REPORT) ||
|
||||
(dv->rule.action == DEFLECT_REJECT))
|
||||
{ put_info_buffer(cs->info);
|
||||
(dv->rule.action == DEFLECT_REJECT)) {
|
||||
put_info_buffer(cs->info);
|
||||
kfree(cs); /* remove */
|
||||
return ((dv->rule.action == DEFLECT_REPORT) ? 0 : 2); /* nothing to do */
|
||||
}
|
||||
|
@ -519,8 +516,8 @@ static int isdn_divert_icall(isdn_ctrl *ic)
|
|||
break;
|
||||
} /* scan_table */
|
||||
|
||||
if (cs)
|
||||
{ cs->prev = NULL;
|
||||
if (cs) {
|
||||
cs->prev = NULL;
|
||||
spin_lock_irqsave(&divert_lock, flags);
|
||||
cs->next = divert_head;
|
||||
divert_head = cs;
|
||||
|
@ -529,21 +526,21 @@ static int isdn_divert_icall(isdn_ctrl *ic)
|
|||
|
||||
put_info_buffer(cs->info);
|
||||
return (retval);
|
||||
}
|
||||
else
|
||||
} else
|
||||
return (0);
|
||||
} /* isdn_divert_icall */
|
||||
|
||||
|
||||
void deleteprocs(void)
|
||||
{ struct call_struc *cs, *cs1;
|
||||
{
|
||||
struct call_struc *cs, *cs1;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&divert_lock, flags);
|
||||
cs = divert_head;
|
||||
divert_head = NULL;
|
||||
while (cs)
|
||||
{ del_timer(&cs->timer);
|
||||
while (cs) {
|
||||
del_timer(&cs->timer);
|
||||
cs1 = cs;
|
||||
cs = cs->next;
|
||||
kfree(cs1);
|
||||
|
@ -555,12 +552,13 @@ void deleteprocs(void)
|
|||
/* put a address including address type into buffer */
|
||||
/****************************************************/
|
||||
static int put_address(char *st, u_char *p, int len)
|
||||
{ u_char retval = 0;
|
||||
{
|
||||
u_char retval = 0;
|
||||
u_char adr_typ = 0; /* network standard */
|
||||
|
||||
if (len < 2) return (retval);
|
||||
if (*p == 0xA1)
|
||||
{ retval = *(++p) + 2; /* total length */
|
||||
if (*p == 0xA1) {
|
||||
retval = *(++p) + 2; /* total length */
|
||||
if (retval > len) return (0); /* too short */
|
||||
len = retval - 2; /* remaining length */
|
||||
if (len < 3) return (0);
|
||||
|
@ -572,16 +570,13 @@ static int put_address(char *st, u_char *p, int len)
|
|||
if (*p++ != 0x12) return (0);
|
||||
if (*p > len) return (0); /* check number length */
|
||||
len = *p++;
|
||||
}
|
||||
else
|
||||
if (*p == 0x80)
|
||||
{ retval = *(++p) + 2; /* total length */
|
||||
if (retval > len) return (0);
|
||||
len = retval - 2;
|
||||
p++;
|
||||
}
|
||||
else
|
||||
return (0); /* invalid address information */
|
||||
} else if (*p == 0x80) {
|
||||
retval = *(++p) + 2; /* total length */
|
||||
if (retval > len) return (0);
|
||||
len = retval - 2;
|
||||
p++;
|
||||
} else
|
||||
return (0); /* invalid address information */
|
||||
|
||||
sprintf(st, "%d ", adr_typ);
|
||||
st += strlen(st);
|
||||
|
@ -598,7 +593,8 @@ static int put_address(char *st, u_char *p, int len)
|
|||
/* report a successful interrogation */
|
||||
/*************************************/
|
||||
static int interrogate_success(isdn_ctrl *ic, struct call_struc *cs)
|
||||
{ char *src = ic->parm.dss1_io.data;
|
||||
{
|
||||
char *src = ic->parm.dss1_io.data;
|
||||
int restlen = ic->parm.dss1_io.datalen;
|
||||
int cnt = 1;
|
||||
u_char n, n1;
|
||||
|
@ -608,50 +604,44 @@ static int interrogate_success(isdn_ctrl *ic, struct call_struc *cs)
|
|||
if (*src++ != 0x30) return (-101);
|
||||
if ((n = *src++) > 0x81) return (-102); /* invalid length field */
|
||||
restlen -= 2; /* remaining bytes */
|
||||
if (n == 0x80)
|
||||
{ if (restlen < 2) return (-103);
|
||||
if (n == 0x80) {
|
||||
if (restlen < 2) return (-103);
|
||||
if ((*(src + restlen - 1)) || (*(src + restlen - 2))) return (-104);
|
||||
restlen -= 2;
|
||||
}
|
||||
} else if (n == 0x81) {
|
||||
n = *src++;
|
||||
restlen--;
|
||||
if (n > restlen) return (-105);
|
||||
restlen = n;
|
||||
} else if (n > restlen)
|
||||
return (-106);
|
||||
else
|
||||
if (n == 0x81)
|
||||
{ n = *src++;
|
||||
restlen--;
|
||||
if (n > restlen) return (-105);
|
||||
restlen = n;
|
||||
}
|
||||
else
|
||||
if (n > restlen) return (-106);
|
||||
else
|
||||
restlen = n; /* standard format */
|
||||
restlen = n; /* standard format */
|
||||
if (restlen < 3) return (-107); /* no procedure */
|
||||
if ((*src++ != 2) || (*src++ != 1) || (*src++ != 0x0B)) return (-108);
|
||||
restlen -= 3;
|
||||
if (restlen < 2) return (-109); /* list missing */
|
||||
if (*src == 0x31)
|
||||
{ src++;
|
||||
if (*src == 0x31) {
|
||||
src++;
|
||||
if ((n = *src++) > 0x81) return (-110); /* invalid length field */
|
||||
restlen -= 2; /* remaining bytes */
|
||||
if (n == 0x80)
|
||||
{ if (restlen < 2) return (-111);
|
||||
if (n == 0x80) {
|
||||
if (restlen < 2) return (-111);
|
||||
if ((*(src + restlen - 1)) || (*(src + restlen - 2))) return (-112);
|
||||
restlen -= 2;
|
||||
}
|
||||
} else if (n == 0x81) {
|
||||
n = *src++;
|
||||
restlen--;
|
||||
if (n > restlen) return (-113);
|
||||
restlen = n;
|
||||
} else if (n > restlen)
|
||||
return (-114);
|
||||
else
|
||||
if (n == 0x81)
|
||||
{ n = *src++;
|
||||
restlen--;
|
||||
if (n > restlen) return (-113);
|
||||
restlen = n;
|
||||
}
|
||||
else
|
||||
if (n > restlen) return (-114);
|
||||
else
|
||||
restlen = n; /* standard format */
|
||||
restlen = n; /* standard format */
|
||||
} /* result list header */
|
||||
|
||||
while (restlen >= 2)
|
||||
{ stp = st;
|
||||
while (restlen >= 2) {
|
||||
stp = st;
|
||||
sprintf(stp, "%d 0x%lx %d %s ", DIVERT_REPORT, ic->parm.dss1_io.ll_id,
|
||||
cnt++, divert_if.drv_to_name(ic->driver));
|
||||
stp += strlen(stp);
|
||||
|
@ -674,8 +664,8 @@ static int interrogate_success(isdn_ctrl *ic, struct call_struc *cs)
|
|||
sprintf(stp, "%d ", (*p++) & 0xFF);
|
||||
stp += strlen(stp);
|
||||
n -= 6;
|
||||
if (n > 2)
|
||||
{ if (*p++ != 0x30) continue;
|
||||
if (n > 2) {
|
||||
if (*p++ != 0x30) continue;
|
||||
if (*p > (n - 2)) continue;
|
||||
n = *p++;
|
||||
if (!(n1 = put_address(stp, p, n & 0xFF))) continue;
|
||||
|
@ -692,58 +682,58 @@ static int interrogate_success(isdn_ctrl *ic, struct call_struc *cs)
|
|||
/* callback for protocol specific extensions */
|
||||
/*********************************************/
|
||||
static int prot_stat_callback(isdn_ctrl *ic)
|
||||
{ struct call_struc *cs, *cs1;
|
||||
{
|
||||
struct call_struc *cs, *cs1;
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
cs = divert_head; /* start of list */
|
||||
cs1 = NULL;
|
||||
while (cs)
|
||||
{ if (ic->driver == cs->ics.driver)
|
||||
{ switch (cs->ics.arg)
|
||||
{ case DSS1_CMD_INVOKE:
|
||||
if ((cs->ics.parm.dss1_io.ll_id == ic->parm.dss1_io.ll_id) &&
|
||||
(cs->ics.parm.dss1_io.hl_id == ic->parm.dss1_io.hl_id))
|
||||
{ switch (ic->arg)
|
||||
{ case DSS1_STAT_INVOKE_ERR:
|
||||
sprintf(cs->info, "128 0x%lx 0x%x\n",
|
||||
ic->parm.dss1_io.ll_id,
|
||||
ic->parm.dss1_io.timeout);
|
||||
put_info_buffer(cs->info);
|
||||
break;
|
||||
|
||||
case DSS1_STAT_INVOKE_RES:
|
||||
switch (cs->ics.parm.dss1_io.proc)
|
||||
{ case 7:
|
||||
case 8:
|
||||
put_info_buffer(cs->info);
|
||||
break;
|
||||
|
||||
case 11:
|
||||
i = interrogate_success(ic, cs);
|
||||
if (i)
|
||||
sprintf(cs->info, "%d 0x%lx %d\n", DIVERT_REPORT,
|
||||
ic->parm.dss1_io.ll_id, i);
|
||||
put_info_buffer(cs->info);
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_WARNING "dss1_divert: unknown proc %d\n", cs->ics.parm.dss1_io.proc);
|
||||
break;
|
||||
}
|
||||
while (cs) {
|
||||
if (ic->driver == cs->ics.driver) {
|
||||
switch (cs->ics.arg) {
|
||||
case DSS1_CMD_INVOKE:
|
||||
if ((cs->ics.parm.dss1_io.ll_id == ic->parm.dss1_io.ll_id) &&
|
||||
(cs->ics.parm.dss1_io.hl_id == ic->parm.dss1_io.hl_id)) {
|
||||
switch (ic->arg) {
|
||||
case DSS1_STAT_INVOKE_ERR:
|
||||
sprintf(cs->info, "128 0x%lx 0x%x\n",
|
||||
ic->parm.dss1_io.ll_id,
|
||||
ic->parm.dss1_io.timeout);
|
||||
put_info_buffer(cs->info);
|
||||
break;
|
||||
|
||||
case DSS1_STAT_INVOKE_RES:
|
||||
switch (cs->ics.parm.dss1_io.proc) {
|
||||
case 7:
|
||||
case 8:
|
||||
put_info_buffer(cs->info);
|
||||
break;
|
||||
|
||||
case 11:
|
||||
i = interrogate_success(ic, cs);
|
||||
if (i)
|
||||
sprintf(cs->info, "%d 0x%lx %d\n", DIVERT_REPORT,
|
||||
ic->parm.dss1_io.ll_id, i);
|
||||
put_info_buffer(cs->info);
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_WARNING "dss1_divert unknown invoke answer %lx\n", ic->arg);
|
||||
printk(KERN_WARNING "dss1_divert: unknown proc %d\n", cs->ics.parm.dss1_io.proc);
|
||||
break;
|
||||
}
|
||||
cs1 = cs; /* remember structure */
|
||||
cs = NULL;
|
||||
continue; /* abort search */
|
||||
} /* id found */
|
||||
break;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_WARNING "dss1_divert unknown invoke answer %lx\n", ic->arg);
|
||||
break;
|
||||
}
|
||||
cs1 = cs; /* remember structure */
|
||||
cs = NULL;
|
||||
continue; /* abort search */
|
||||
} /* id found */
|
||||
break;
|
||||
|
||||
case DSS1_CMD_INVOKE_ABORT:
|
||||
printk(KERN_WARNING "dss1_divert unhandled invoke abort\n");
|
||||
|
@ -757,13 +747,12 @@ static int prot_stat_callback(isdn_ctrl *ic)
|
|||
} /* driver ok */
|
||||
}
|
||||
|
||||
if (!cs1)
|
||||
{ printk(KERN_WARNING "dss1_divert unhandled process\n");
|
||||
if (!cs1) {
|
||||
printk(KERN_WARNING "dss1_divert unhandled process\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (cs1->ics.driver == -1)
|
||||
{
|
||||
if (cs1->ics.driver == -1) {
|
||||
spin_lock_irqsave(&divert_lock, flags);
|
||||
del_timer(&cs1->timer);
|
||||
if (cs1->prev)
|
||||
|
@ -784,20 +773,22 @@ static int prot_stat_callback(isdn_ctrl *ic)
|
|||
/* status callback from HL */
|
||||
/***************************/
|
||||
static int isdn_divert_stat_callback(isdn_ctrl *ic)
|
||||
{ struct call_struc *cs, *cs1;
|
||||
{
|
||||
struct call_struc *cs, *cs1;
|
||||
unsigned long flags;
|
||||
int retval;
|
||||
|
||||
retval = -1;
|
||||
cs = divert_head; /* start of list */
|
||||
while (cs)
|
||||
{ if ((ic->driver == cs->ics.driver) && (ic->arg == cs->ics.arg))
|
||||
{ switch (ic->command)
|
||||
{ case ISDN_STAT_DHUP:
|
||||
sprintf(cs->info, "129 0x%lx\n", cs->divert_id);
|
||||
del_timer(&cs->timer);
|
||||
cs->ics.driver = -1;
|
||||
break;
|
||||
while (cs) {
|
||||
if ((ic->driver == cs->ics.driver) &&
|
||||
(ic->arg == cs->ics.arg)) {
|
||||
switch (ic->command) {
|
||||
case ISDN_STAT_DHUP:
|
||||
sprintf(cs->info, "129 0x%lx\n", cs->divert_id);
|
||||
del_timer(&cs->timer);
|
||||
cs->ics.driver = -1;
|
||||
break;
|
||||
|
||||
case ISDN_STAT_CAUSE:
|
||||
sprintf(cs->info, "130 0x%lx %s\n", cs->divert_id, ic->parm.num);
|
||||
|
@ -818,8 +809,7 @@ static int isdn_divert_stat_callback(isdn_ctrl *ic)
|
|||
}
|
||||
cs1 = cs;
|
||||
cs = cs->next;
|
||||
if (cs1->ics.driver == -1)
|
||||
{
|
||||
if (cs1->ics.driver == -1) {
|
||||
spin_lock_irqsave(&divert_lock, flags);
|
||||
if (cs1->prev)
|
||||
cs1->prev->next = cs1->next; /* forward link */
|
||||
|
@ -840,20 +830,19 @@ static int isdn_divert_stat_callback(isdn_ctrl *ic)
|
|||
/********************/
|
||||
int ll_callback(isdn_ctrl *ic)
|
||||
{
|
||||
switch (ic->command)
|
||||
{ case ISDN_STAT_ICALL:
|
||||
switch (ic->command) {
|
||||
case ISDN_STAT_ICALL:
|
||||
case ISDN_STAT_ICALLW:
|
||||
return (isdn_divert_icall(ic));
|
||||
break;
|
||||
|
||||
case ISDN_STAT_PROT:
|
||||
if ((ic->arg & 0xFF) == ISDN_PTYPE_EURO)
|
||||
{ if (ic->arg != DSS1_STAT_INVOKE_BRD)
|
||||
if ((ic->arg & 0xFF) == ISDN_PTYPE_EURO) {
|
||||
if (ic->arg != DSS1_STAT_INVOKE_BRD)
|
||||
return (prot_stat_callback(ic));
|
||||
else
|
||||
return (0); /* DSS1 invoke broadcast */
|
||||
}
|
||||
else
|
||||
} else
|
||||
return (-1); /* protocol not euro */
|
||||
|
||||
default:
|
||||
|
|
|
@ -43,8 +43,8 @@
|
|||
|
||||
#define DEFLECT_ALL_IDS 0xFFFFFFFF /* all drivers selected */
|
||||
|
||||
typedef struct
|
||||
{ ulong drvid; /* driver ids, bit mapped */
|
||||
typedef struct {
|
||||
ulong drvid; /* driver ids, bit mapped */
|
||||
char my_msn[35]; /* desired msn, subaddr allowed */
|
||||
char caller[35]; /* caller id, partial string with * + subaddr allowed */
|
||||
char to_nr[35]; /* deflected to number incl. subaddress */
|
||||
|
@ -65,18 +65,18 @@ typedef struct
|
|||
u_char waittime; /* maximum wait time for proceeding */
|
||||
} divert_rule;
|
||||
|
||||
typedef union
|
||||
{ int drv_version; /* return of driver version */
|
||||
struct
|
||||
{ int drvid; /* id of driver */
|
||||
typedef union {
|
||||
int drv_version; /* return of driver version */
|
||||
struct {
|
||||
int drvid; /* id of driver */
|
||||
char drvnam[30]; /* name of driver */
|
||||
} getid;
|
||||
struct
|
||||
{ int ruleidx; /* index of rule */
|
||||
struct {
|
||||
int ruleidx; /* index of rule */
|
||||
divert_rule rule; /* rule parms */
|
||||
} getsetrule;
|
||||
struct
|
||||
{ u_char subcmd; /* 0 = hangup/reject,
|
||||
struct {
|
||||
u_char subcmd; /* 0 = hangup/reject,
|
||||
1 = alert,
|
||||
2 = deflect */
|
||||
ulong callid; /* id of call delivered by ascii output */
|
||||
|
@ -84,8 +84,8 @@ typedef union
|
|||
else uus1 string (maxlen 31),
|
||||
data from rule used if empty */
|
||||
} fwd_ctrl;
|
||||
struct
|
||||
{ int drvid; /* id of driver */
|
||||
struct {
|
||||
int drvid; /* id of driver */
|
||||
u_char cfproc; /* cfu = 0, cfb = 1, cfnr = 2 */
|
||||
ulong procid; /* process id returned when no error */
|
||||
u_char service; /* basically coded service, 0 = all */
|
||||
|
@ -104,8 +104,8 @@ typedef union
|
|||
/**************************************************/
|
||||
/* structure keeping ascii info for device output */
|
||||
/**************************************************/
|
||||
struct divert_info
|
||||
{ struct divert_info *next;
|
||||
struct divert_info {
|
||||
struct divert_info *next;
|
||||
ulong usage_cnt; /* number of files still to work */
|
||||
char info_start[2]; /* info string start */
|
||||
};
|
||||
|
|
|
@ -467,11 +467,6 @@ void gigaset_freecs(struct cardstate *cs)
|
|||
|
||||
mutex_lock(&cs->mutex);
|
||||
|
||||
if (!cs->bcs)
|
||||
goto f_cs;
|
||||
if (!cs->inbuf)
|
||||
goto f_bcs;
|
||||
|
||||
spin_lock_irqsave(&cs->lock, flags);
|
||||
cs->running = 0;
|
||||
spin_unlock_irqrestore(&cs->lock, flags); /* event handler and timer are
|
||||
|
@ -507,17 +502,16 @@ void gigaset_freecs(struct cardstate *cs)
|
|||
gig_dbg(DEBUG_INIT, "clearing at_state");
|
||||
clear_at_state(&cs->at_state);
|
||||
dealloc_temp_at_states(cs);
|
||||
clear_events(cs);
|
||||
tty_port_destroy(&cs->port);
|
||||
|
||||
/* fall through */
|
||||
case 0: /* error in basic setup */
|
||||
clear_events(cs);
|
||||
gig_dbg(DEBUG_INIT, "freeing inbuf");
|
||||
kfree(cs->inbuf);
|
||||
kfree(cs->bcs);
|
||||
}
|
||||
f_bcs: gig_dbg(DEBUG_INIT, "freeing bcs[]");
|
||||
kfree(cs->bcs);
|
||||
f_cs: gig_dbg(DEBUG_INIT, "freeing cs");
|
||||
|
||||
mutex_unlock(&cs->mutex);
|
||||
free_cs(cs);
|
||||
}
|
||||
|
@ -687,19 +681,6 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
gig_dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1);
|
||||
cs->bcs = kmalloc(channels * sizeof(struct bc_state), GFP_KERNEL);
|
||||
if (!cs->bcs) {
|
||||
pr_err("out of memory\n");
|
||||
goto error;
|
||||
}
|
||||
gig_dbg(DEBUG_INIT, "allocating inbuf");
|
||||
cs->inbuf = kmalloc(sizeof(struct inbuf_t), GFP_KERNEL);
|
||||
if (!cs->inbuf) {
|
||||
pr_err("out of memory\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
cs->cs_init = 0;
|
||||
cs->channels = channels;
|
||||
cs->onechannel = onechannel;
|
||||
|
@ -729,6 +710,12 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
|
|||
cs->mode = M_UNKNOWN;
|
||||
cs->mstate = MS_UNINITIALIZED;
|
||||
|
||||
cs->bcs = kmalloc(channels * sizeof(struct bc_state), GFP_KERNEL);
|
||||
cs->inbuf = kmalloc(sizeof(struct inbuf_t), GFP_KERNEL);
|
||||
if (!cs->bcs || !cs->inbuf) {
|
||||
pr_err("out of memory\n");
|
||||
goto error;
|
||||
}
|
||||
++cs->cs_init;
|
||||
|
||||
gig_dbg(DEBUG_INIT, "setting up at_state");
|
||||
|
|
|
@ -351,10 +351,11 @@ struct reply_t gigaset_tab_cid[] =
|
|||
|
||||
|
||||
static const struct resp_type_t {
|
||||
unsigned char *response;
|
||||
int resp_code;
|
||||
int type;
|
||||
} resp_type[] =
|
||||
char *response;
|
||||
int resp_code;
|
||||
int type;
|
||||
}
|
||||
resp_type[] =
|
||||
{
|
||||
{"OK", RSP_OK, RT_NOTHING},
|
||||
{"ERROR", RSP_ERROR, RT_NOTHING},
|
||||
|
@ -374,11 +375,12 @@ static const struct resp_type_t {
|
|||
};
|
||||
|
||||
static const struct zsau_resp_t {
|
||||
unsigned char *str;
|
||||
int code;
|
||||
} zsau_resp[] =
|
||||
char *str;
|
||||
int code;
|
||||
}
|
||||
zsau_resp[] =
|
||||
{
|
||||
{"OUTGOING_CALL_PROCEEDING", ZSAU_OUTGOING_CALL_PROCEEDING},
|
||||
{"OUTGOING_CALL_PROCEEDING", ZSAU_PROCEEDING},
|
||||
{"CALL_DELIVERED", ZSAU_CALL_DELIVERED},
|
||||
{"ACTIVE", ZSAU_ACTIVE},
|
||||
{"DISCONNECT_IND", ZSAU_DISCONNECT_IND},
|
||||
|
@ -434,7 +436,7 @@ void gigaset_handle_modem_response(struct cardstate *cs)
|
|||
len = cs->cbytes;
|
||||
if (!len) {
|
||||
/* ignore additional LFs/CRs (M10x config mode or cx100) */
|
||||
gig_dbg(DEBUG_MCMD, "skipped EOL [%02X]", cs->respdata[len]);
|
||||
gig_dbg(DEBUG_MCMD, "skipped EOL [%02X]", cs->respdata[0]);
|
||||
return;
|
||||
}
|
||||
cs->respdata[len] = 0;
|
||||
|
@ -707,27 +709,29 @@ static void schedule_init(struct cardstate *cs, int state)
|
|||
cs->commands_pending = 1;
|
||||
}
|
||||
|
||||
/* Add "AT" to a command, add the cid, dle encode it, send the result to the
|
||||
hardware. */
|
||||
static void send_command(struct cardstate *cs, const char *cmd, int cid,
|
||||
int dle, gfp_t kmallocflags)
|
||||
/* send an AT command
|
||||
* adding the "AT" prefix, cid and DLE encapsulation as appropriate
|
||||
*/
|
||||
static void send_command(struct cardstate *cs, const char *cmd,
|
||||
struct at_state_t *at_state)
|
||||
{
|
||||
int cid = at_state->cid;
|
||||
struct cmdbuf_t *cb;
|
||||
size_t buflen;
|
||||
|
||||
buflen = strlen(cmd) + 12; /* DLE ( A T 1 2 3 4 5 <cmd> DLE ) \0 */
|
||||
cb = kmalloc(sizeof(struct cmdbuf_t) + buflen, kmallocflags);
|
||||
cb = kmalloc(sizeof(struct cmdbuf_t) + buflen, GFP_ATOMIC);
|
||||
if (!cb) {
|
||||
dev_err(cs->dev, "%s: out of memory\n", __func__);
|
||||
return;
|
||||
}
|
||||
if (cid > 0 && cid <= 65535)
|
||||
cb->len = snprintf(cb->buf, buflen,
|
||||
dle ? "\020(AT%d%s\020)" : "AT%d%s",
|
||||
cs->dle ? "\020(AT%d%s\020)" : "AT%d%s",
|
||||
cid, cmd);
|
||||
else
|
||||
cb->len = snprintf(cb->buf, buflen,
|
||||
dle ? "\020(AT%s\020)" : "AT%s",
|
||||
cs->dle ? "\020(AT%s\020)" : "AT%s",
|
||||
cmd);
|
||||
cb->offset = 0;
|
||||
cb->next = NULL;
|
||||
|
@ -886,7 +890,7 @@ static void finish_shutdown(struct cardstate *cs)
|
|||
gigaset_isdn_stop(cs);
|
||||
}
|
||||
|
||||
/* The rest is done by cleanup_cs () in user mode. */
|
||||
/* The rest is done by cleanup_cs() in process context. */
|
||||
|
||||
cs->cmd_result = -ENODEV;
|
||||
cs->waiting = 0;
|
||||
|
@ -976,10 +980,9 @@ exit:
|
|||
}
|
||||
|
||||
static void handle_icall(struct cardstate *cs, struct bc_state *bcs,
|
||||
struct at_state_t **p_at_state)
|
||||
struct at_state_t *at_state)
|
||||
{
|
||||
int retval;
|
||||
struct at_state_t *at_state = *p_at_state;
|
||||
|
||||
retval = gigaset_isdn_icall(at_state);
|
||||
switch (retval) {
|
||||
|
@ -1176,7 +1179,7 @@ static void do_action(int action, struct cardstate *cs,
|
|||
spin_unlock_irqrestore(&cs->lock, flags);
|
||||
break;
|
||||
case ACT_ICALL:
|
||||
handle_icall(cs, bcs, p_at_state);
|
||||
handle_icall(cs, bcs, at_state);
|
||||
break;
|
||||
case ACT_FAILSDOWN:
|
||||
dev_warn(cs->dev, "Could not shut down the device.\n");
|
||||
|
@ -1264,7 +1267,7 @@ static void do_action(int action, struct cardstate *cs,
|
|||
cs->commands_pending = 1;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
/* bad cid: fall through */
|
||||
case ACT_FAILCID:
|
||||
cs->cur_at_seq = SEQ_NONE;
|
||||
channel = cs->curchannel;
|
||||
|
@ -1339,7 +1342,6 @@ static void do_action(int action, struct cardstate *cs,
|
|||
*p_resp_code = RSP_ERROR;
|
||||
break;
|
||||
}
|
||||
/*at_state->getstring = 1;*/
|
||||
cs->gotfwver = 0;
|
||||
break;
|
||||
case ACT_GOTVER:
|
||||
|
@ -1471,7 +1473,6 @@ static void process_event(struct cardstate *cs, struct event_t *ev)
|
|||
int rcode;
|
||||
int genresp = 0;
|
||||
int resp_code = RSP_ERROR;
|
||||
int sendcid;
|
||||
struct at_state_t *at_state;
|
||||
int index;
|
||||
int curact;
|
||||
|
@ -1499,7 +1500,6 @@ static void process_event(struct cardstate *cs, struct event_t *ev)
|
|||
at_state->ConState, ev->type);
|
||||
|
||||
bcs = at_state->bcs;
|
||||
sendcid = at_state->cid;
|
||||
|
||||
/* Setting the pointer to the dial array */
|
||||
rep = at_state->replystruct;
|
||||
|
@ -1510,10 +1510,12 @@ static void process_event(struct cardstate *cs, struct event_t *ev)
|
|||
|| !at_state->timer_active) {
|
||||
ev->type = RSP_NONE; /* old timeout */
|
||||
gig_dbg(DEBUG_EVENT, "old timeout");
|
||||
} else if (!at_state->waiting)
|
||||
gig_dbg(DEBUG_EVENT, "timeout occurred");
|
||||
else
|
||||
gig_dbg(DEBUG_EVENT, "stopped waiting");
|
||||
} else {
|
||||
if (at_state->waiting)
|
||||
gig_dbg(DEBUG_EVENT, "stopped waiting");
|
||||
else
|
||||
gig_dbg(DEBUG_EVENT, "timeout occurred");
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&cs->lock, flags);
|
||||
|
||||
|
@ -1561,45 +1563,40 @@ static void process_event(struct cardstate *cs, struct event_t *ev)
|
|||
do_action(rep->action[curact], cs, bcs, &at_state, &p_command,
|
||||
&genresp, &resp_code, ev);
|
||||
if (!at_state)
|
||||
break; /* may be freed after disconnect */
|
||||
/* at_state destroyed by disconnect */
|
||||
return;
|
||||
}
|
||||
|
||||
if (at_state) {
|
||||
/* Jump to the next con-state regarding the array */
|
||||
if (rep->new_ConState >= 0)
|
||||
at_state->ConState = rep->new_ConState;
|
||||
/* Jump to the next con-state regarding the array */
|
||||
if (rep->new_ConState >= 0)
|
||||
at_state->ConState = rep->new_ConState;
|
||||
|
||||
if (genresp) {
|
||||
spin_lock_irqsave(&cs->lock, flags);
|
||||
if (genresp) {
|
||||
spin_lock_irqsave(&cs->lock, flags);
|
||||
at_state->timer_expires = 0;
|
||||
at_state->timer_active = 0;
|
||||
spin_unlock_irqrestore(&cs->lock, flags);
|
||||
gigaset_add_event(cs, at_state, resp_code, NULL, 0, NULL);
|
||||
} else {
|
||||
/* Send command to modem if not NULL... */
|
||||
if (p_command) {
|
||||
if (cs->connected)
|
||||
send_command(cs, p_command, at_state);
|
||||
else
|
||||
gigaset_add_event(cs, at_state, RSP_NODEV,
|
||||
NULL, 0, NULL);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&cs->lock, flags);
|
||||
if (!rep->timeout) {
|
||||
at_state->timer_expires = 0;
|
||||
at_state->timer_active = 0;
|
||||
spin_unlock_irqrestore(&cs->lock, flags);
|
||||
gigaset_add_event(cs, at_state, resp_code,
|
||||
NULL, 0, NULL);
|
||||
} else {
|
||||
/* Send command to modem if not NULL... */
|
||||
if (p_command) {
|
||||
if (cs->connected)
|
||||
send_command(cs, p_command,
|
||||
sendcid, cs->dle,
|
||||
GFP_ATOMIC);
|
||||
else
|
||||
gigaset_add_event(cs, at_state,
|
||||
RSP_NODEV,
|
||||
NULL, 0, NULL);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&cs->lock, flags);
|
||||
if (!rep->timeout) {
|
||||
at_state->timer_expires = 0;
|
||||
at_state->timer_active = 0;
|
||||
} else if (rep->timeout > 0) { /* new timeout */
|
||||
at_state->timer_expires = rep->timeout * 10;
|
||||
at_state->timer_active = 1;
|
||||
++at_state->timer_index;
|
||||
}
|
||||
spin_unlock_irqrestore(&cs->lock, flags);
|
||||
} else if (rep->timeout > 0) { /* new timeout */
|
||||
at_state->timer_expires = rep->timeout * 10;
|
||||
at_state->timer_active = 1;
|
||||
++at_state->timer_index;
|
||||
}
|
||||
spin_unlock_irqrestore(&cs->lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1693,6 +1690,11 @@ static void process_command_flags(struct cardstate *cs)
|
|||
for (i = 0; i < cs->channels; ++i) {
|
||||
bcs = cs->bcs + i;
|
||||
if (bcs->at_state.pending_commands & PC_HUP) {
|
||||
if (cs->dle) {
|
||||
cs->curchannel = bcs->channel;
|
||||
schedule_sequence(cs, &cs->at_state, SEQ_DLE0);
|
||||
return;
|
||||
}
|
||||
bcs->at_state.pending_commands &= ~PC_HUP;
|
||||
if (bcs->at_state.pending_commands & PC_CID) {
|
||||
/* not yet dialing: PC_NOCID is sufficient */
|
||||
|
|
|
@ -111,11 +111,10 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
|
|||
|
||||
/* connection state */
|
||||
#define ZSAU_NONE 0
|
||||
#define ZSAU_DISCONNECT_IND 4
|
||||
#define ZSAU_OUTGOING_CALL_PROCEEDING 1
|
||||
#define ZSAU_PROCEEDING 1
|
||||
#define ZSAU_CALL_DELIVERED 2
|
||||
#define ZSAU_ACTIVE 3
|
||||
#define ZSAU_DISCONNECT_IND 4
|
||||
#define ZSAU_NULL 5
|
||||
#define ZSAU_DISCONNECT_REQ 6
|
||||
#define ZSAU_UNKNOWN -1
|
||||
|
@ -183,18 +182,22 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
|
|||
#define AT_NUM 7
|
||||
|
||||
/* variables in struct at_state_t */
|
||||
/* - numeric */
|
||||
#define VAR_ZSAU 0
|
||||
#define VAR_ZDLE 1
|
||||
#define VAR_ZCTP 2
|
||||
/* total number */
|
||||
#define VAR_NUM 3
|
||||
|
||||
/* - string */
|
||||
#define STR_NMBR 0
|
||||
#define STR_ZCPN 1
|
||||
#define STR_ZCON 2
|
||||
#define STR_ZBC 3
|
||||
#define STR_ZHLC 4
|
||||
/* total number */
|
||||
#define STR_NUM 5
|
||||
|
||||
/* event types */
|
||||
#define EV_TIMEOUT -105
|
||||
#define EV_IF_VER -106
|
||||
#define EV_PROC_CIDMODE -107
|
||||
|
|
|
@ -112,36 +112,6 @@ static int if_config(struct cardstate *cs, int *arg)
|
|||
}
|
||||
|
||||
/*** the terminal driver ***/
|
||||
/* stolen from usbserial and some other tty drivers */
|
||||
|
||||
static int if_open(struct tty_struct *tty, struct file *filp);
|
||||
static void if_close(struct tty_struct *tty, struct file *filp);
|
||||
static int if_ioctl(struct tty_struct *tty,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
static int if_write_room(struct tty_struct *tty);
|
||||
static int if_chars_in_buffer(struct tty_struct *tty);
|
||||
static void if_throttle(struct tty_struct *tty);
|
||||
static void if_unthrottle(struct tty_struct *tty);
|
||||
static void if_set_termios(struct tty_struct *tty, struct ktermios *old);
|
||||
static int if_tiocmget(struct tty_struct *tty);
|
||||
static int if_tiocmset(struct tty_struct *tty,
|
||||
unsigned int set, unsigned int clear);
|
||||
static int if_write(struct tty_struct *tty,
|
||||
const unsigned char *buf, int count);
|
||||
|
||||
static const struct tty_operations if_ops = {
|
||||
.open = if_open,
|
||||
.close = if_close,
|
||||
.ioctl = if_ioctl,
|
||||
.write = if_write,
|
||||
.write_room = if_write_room,
|
||||
.chars_in_buffer = if_chars_in_buffer,
|
||||
.set_termios = if_set_termios,
|
||||
.throttle = if_throttle,
|
||||
.unthrottle = if_unthrottle,
|
||||
.tiocmget = if_tiocmget,
|
||||
.tiocmset = if_tiocmset,
|
||||
};
|
||||
|
||||
static int if_open(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
|
@ -355,7 +325,7 @@ done:
|
|||
static int if_write_room(struct tty_struct *tty)
|
||||
{
|
||||
struct cardstate *cs = tty->driver_data;
|
||||
int retval = -ENODEV;
|
||||
int retval;
|
||||
|
||||
gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
|
||||
|
||||
|
@ -498,6 +468,20 @@ out:
|
|||
mutex_unlock(&cs->mutex);
|
||||
}
|
||||
|
||||
static const struct tty_operations if_ops = {
|
||||
.open = if_open,
|
||||
.close = if_close,
|
||||
.ioctl = if_ioctl,
|
||||
.write = if_write,
|
||||
.write_room = if_write_room,
|
||||
.chars_in_buffer = if_chars_in_buffer,
|
||||
.set_termios = if_set_termios,
|
||||
.throttle = if_throttle,
|
||||
.unthrottle = if_unthrottle,
|
||||
.tiocmget = if_tiocmget,
|
||||
.tiocmset = if_tiocmset,
|
||||
};
|
||||
|
||||
|
||||
/* wakeup tasklet for the write operation */
|
||||
static void if_wake(unsigned long data)
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#endif
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/wanrouter.h>
|
||||
#include <linux/isdn.h>
|
||||
#include <linux/concap.h>
|
||||
|
||||
|
|
|
@ -37,35 +37,14 @@
|
|||
ethernet adaptor have the name "eth[0123...]".
|
||||
*/
|
||||
|
||||
extern struct net_device *ne2_probe(int unit);
|
||||
extern struct net_device *hp100_probe(int unit);
|
||||
extern struct net_device *ultra_probe(int unit);
|
||||
extern struct net_device *ultra32_probe(int unit);
|
||||
extern struct net_device *wd_probe(int unit);
|
||||
extern struct net_device *el2_probe(int unit);
|
||||
extern struct net_device *ne_probe(int unit);
|
||||
extern struct net_device *hp_probe(int unit);
|
||||
extern struct net_device *hp_plus_probe(int unit);
|
||||
extern struct net_device *express_probe(int unit);
|
||||
extern struct net_device *eepro_probe(int unit);
|
||||
extern struct net_device *at1700_probe(int unit);
|
||||
extern struct net_device *fmv18x_probe(int unit);
|
||||
extern struct net_device *eth16i_probe(int unit);
|
||||
extern struct net_device *i82596_probe(int unit);
|
||||
extern struct net_device *ewrk3_probe(int unit);
|
||||
extern struct net_device *el1_probe(int unit);
|
||||
extern struct net_device *el16_probe(int unit);
|
||||
extern struct net_device *elmc_probe(int unit);
|
||||
extern struct net_device *elplus_probe(int unit);
|
||||
extern struct net_device *ac3200_probe(int unit);
|
||||
extern struct net_device *es_probe(int unit);
|
||||
extern struct net_device *lne390_probe(int unit);
|
||||
extern struct net_device *e2100_probe(int unit);
|
||||
extern struct net_device *ni5010_probe(int unit);
|
||||
extern struct net_device *ni52_probe(int unit);
|
||||
extern struct net_device *ni65_probe(int unit);
|
||||
extern struct net_device *sonic_probe(int unit);
|
||||
extern struct net_device *seeq8005_probe(int unit);
|
||||
extern struct net_device *smc_init(int unit);
|
||||
extern struct net_device *atarilance_probe(int unit);
|
||||
extern struct net_device *sun3lance_probe(int unit);
|
||||
|
@ -77,13 +56,9 @@ extern struct net_device *tc515_probe(int unit);
|
|||
extern struct net_device *lance_probe(int unit);
|
||||
extern struct net_device *mac8390_probe(int unit);
|
||||
extern struct net_device *mac89x0_probe(int unit);
|
||||
extern struct net_device *mc32_probe(int unit);
|
||||
extern struct net_device *cops_probe(int unit);
|
||||
extern struct net_device *ltpc_probe(void);
|
||||
|
||||
/* Detachable devices ("pocket adaptors") */
|
||||
extern struct net_device *de620_probe(int unit);
|
||||
|
||||
/* Fibre Channel adapters */
|
||||
extern int iph5526_probe(struct net_device *dev);
|
||||
|
||||
|
@ -110,29 +85,6 @@ static int __init probe_list2(int unit, struct devprobe2 *p, int autoprobe)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a bit of an artificial separation as there are PCI drivers
|
||||
* that also probe for EISA cards (in the PCI group) and there are ISA
|
||||
* drivers that probe for EISA cards (in the ISA group). These are the
|
||||
* legacy EISA only driver probes, and also the legacy PCI probes
|
||||
*/
|
||||
|
||||
static struct devprobe2 eisa_probes[] __initdata = {
|
||||
#ifdef CONFIG_ULTRA32
|
||||
{ultra32_probe, 0},
|
||||
#endif
|
||||
#ifdef CONFIG_AC3200
|
||||
{ac3200_probe, 0},
|
||||
#endif
|
||||
#ifdef CONFIG_ES3210
|
||||
{es_probe, 0},
|
||||
#endif
|
||||
#ifdef CONFIG_LNE390
|
||||
{lne390_probe, 0},
|
||||
#endif
|
||||
{NULL, 0},
|
||||
};
|
||||
|
||||
/*
|
||||
* ISA probes that touch addresses < 0x400 (including those that also
|
||||
* look for EISA/PCI cards in addition to ISA cards).
|
||||
|
@ -150,18 +102,6 @@ static struct devprobe2 isa_probes[] __initdata = {
|
|||
#ifdef CONFIG_WD80x3
|
||||
{wd_probe, 0},
|
||||
#endif
|
||||
#ifdef CONFIG_EL2 /* 3c503 */
|
||||
{el2_probe, 0},
|
||||
#endif
|
||||
#ifdef CONFIG_HPLAN
|
||||
{hp_probe, 0},
|
||||
#endif
|
||||
#ifdef CONFIG_HPLAN_PLUS
|
||||
{hp_plus_probe, 0},
|
||||
#endif
|
||||
#ifdef CONFIG_E2100 /* Cabletron E21xx series. */
|
||||
{e2100_probe, 0},
|
||||
#endif
|
||||
#if defined(CONFIG_NE2000) || \
|
||||
defined(CONFIG_NE_H8300) /* ISA (use ne2k-pci for PCI cards) */
|
||||
{ne_probe, 0},
|
||||
|
@ -172,60 +112,20 @@ static struct devprobe2 isa_probes[] __initdata = {
|
|||
#ifdef CONFIG_SMC9194
|
||||
{smc_init, 0},
|
||||
#endif
|
||||
#ifdef CONFIG_SEEQ8005
|
||||
{seeq8005_probe, 0},
|
||||
#endif
|
||||
#ifdef CONFIG_CS89x0
|
||||
#ifndef CONFIG_CS89x0_PLATFORM
|
||||
{cs89x0_probe, 0},
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CONFIG_AT1700
|
||||
{at1700_probe, 0},
|
||||
#endif
|
||||
#ifdef CONFIG_ETH16I
|
||||
{eth16i_probe, 0}, /* ICL EtherTeam 16i/32 */
|
||||
#endif
|
||||
#ifdef CONFIG_EEXPRESS /* Intel EtherExpress */
|
||||
{express_probe, 0},
|
||||
#endif
|
||||
#ifdef CONFIG_EEXPRESS_PRO /* Intel EtherExpress Pro/10 */
|
||||
{eepro_probe, 0},
|
||||
#endif
|
||||
#ifdef CONFIG_EWRK3 /* DEC EtherWORKS 3 */
|
||||
{ewrk3_probe, 0},
|
||||
#endif
|
||||
#if defined(CONFIG_APRICOT) || defined(CONFIG_MVME16x_NET) || defined(CONFIG_BVME6000_NET) /* Intel I82596 */
|
||||
#if defined(CONFIG_MVME16x_NET) || defined(CONFIG_BVME6000_NET) /* Intel I82596 */
|
||||
{i82596_probe, 0},
|
||||
#endif
|
||||
#ifdef CONFIG_EL1 /* 3c501 */
|
||||
{el1_probe, 0},
|
||||
#endif
|
||||
#ifdef CONFIG_EL16 /* 3c507 */
|
||||
{el16_probe, 0},
|
||||
#endif
|
||||
#ifdef CONFIG_ELPLUS /* 3c505 */
|
||||
{elplus_probe, 0},
|
||||
#endif
|
||||
#ifdef CONFIG_NI5010
|
||||
{ni5010_probe, 0},
|
||||
#endif
|
||||
#ifdef CONFIG_NI52
|
||||
{ni52_probe, 0},
|
||||
#endif
|
||||
#ifdef CONFIG_NI65
|
||||
{ni65_probe, 0},
|
||||
#endif
|
||||
{NULL, 0},
|
||||
};
|
||||
|
||||
static struct devprobe2 parport_probes[] __initdata = {
|
||||
#ifdef CONFIG_DE620 /* D-Link DE-620 adapter */
|
||||
{de620_probe, 0},
|
||||
#endif
|
||||
{NULL, 0},
|
||||
};
|
||||
|
||||
static struct devprobe2 m68k_probes[] __initdata = {
|
||||
#ifdef CONFIG_ATARILANCE /* Lance-based Atari ethernet boards */
|
||||
{atarilance_probe, 0},
|
||||
|
@ -264,9 +164,7 @@ static void __init ethif_probe2(int unit)
|
|||
return;
|
||||
|
||||
(void)( probe_list2(unit, m68k_probes, base_addr == 0) &&
|
||||
probe_list2(unit, eisa_probes, base_addr == 0) &&
|
||||
probe_list2(unit, isa_probes, base_addr == 0) &&
|
||||
probe_list2(unit, parport_probes, base_addr == 0));
|
||||
probe_list2(unit, isa_probes, base_addr == 0));
|
||||
}
|
||||
|
||||
/* Statically configured drivers -- order matters here. */
|
||||
|
|
|
@ -389,13 +389,13 @@ static u8 __get_duplex(struct port *port)
|
|||
|
||||
/**
|
||||
* __initialize_port_locks - initialize a port's STATE machine spinlock
|
||||
* @port: the port we're looking at
|
||||
* @port: the slave of the port we're looking at
|
||||
*
|
||||
*/
|
||||
static inline void __initialize_port_locks(struct port *port)
|
||||
static inline void __initialize_port_locks(struct slave *slave)
|
||||
{
|
||||
// make sure it isn't called twice
|
||||
spin_lock_init(&(SLAVE_AD_INFO(port->slave).state_machine_lock));
|
||||
spin_lock_init(&(SLAVE_AD_INFO(slave).state_machine_lock));
|
||||
}
|
||||
|
||||
//conversions
|
||||
|
@ -1127,7 +1127,7 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
|
|||
// INFO_RECEIVED_LOOPBACK_FRAMES
|
||||
pr_err("%s: An illegal loopback occurred on adapter (%s).\n"
|
||||
"Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n",
|
||||
port->slave->dev->master->name, port->slave->dev->name);
|
||||
port->slave->bond->dev->name, port->slave->dev->name);
|
||||
return;
|
||||
}
|
||||
__update_selected(lacpdu, port);
|
||||
|
@ -1306,7 +1306,7 @@ static void ad_port_selection_logic(struct port *port)
|
|||
}
|
||||
if (!curr_port) { // meaning: the port was related to an aggregator but was not on the aggregator port list
|
||||
pr_warning("%s: Warning: Port %d (on %s) was related to aggregator %d but was not on its port list\n",
|
||||
port->slave->dev->master->name,
|
||||
port->slave->bond->dev->name,
|
||||
port->actor_port_number,
|
||||
port->slave->dev->name,
|
||||
port->aggregator->aggregator_identifier);
|
||||
|
@ -1386,7 +1386,7 @@ static void ad_port_selection_logic(struct port *port)
|
|||
port->aggregator->aggregator_identifier);
|
||||
} else {
|
||||
pr_err("%s: Port %d (on %s) did not find a suitable aggregator\n",
|
||||
port->slave->dev->master->name,
|
||||
port->slave->bond->dev->name,
|
||||
port->actor_port_number, port->slave->dev->name);
|
||||
}
|
||||
}
|
||||
|
@ -1463,7 +1463,7 @@ static struct aggregator *ad_agg_selection_test(struct aggregator *best,
|
|||
|
||||
default:
|
||||
pr_warning("%s: Impossible agg select mode %d\n",
|
||||
curr->slave->dev->master->name,
|
||||
curr->slave->bond->dev->name,
|
||||
__get_agg_selection_mode(curr->lag_ports));
|
||||
break;
|
||||
}
|
||||
|
@ -1571,7 +1571,7 @@ static void ad_agg_selection_logic(struct aggregator *agg)
|
|||
// check if any partner replys
|
||||
if (best->is_individual) {
|
||||
pr_warning("%s: Warning: No 802.3ad response from the link partner for any adapters in the bond\n",
|
||||
best->slave ? best->slave->dev->master->name : "NULL");
|
||||
best->slave ? best->slave->bond->dev->name : "NULL");
|
||||
}
|
||||
|
||||
best->is_active = 1;
|
||||
|
@ -1898,7 +1898,7 @@ int bond_3ad_bind_slave(struct slave *slave)
|
|||
|
||||
if (bond == NULL) {
|
||||
pr_err("%s: The slave %s is not attached to its bond\n",
|
||||
slave->dev->master->name, slave->dev->name);
|
||||
slave->bond->dev->name, slave->dev->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1910,6 +1910,7 @@ int bond_3ad_bind_slave(struct slave *slave)
|
|||
|
||||
ad_initialize_port(port, bond->params.lacp_fast);
|
||||
|
||||
__initialize_port_locks(slave);
|
||||
port->slave = slave;
|
||||
port->actor_port_number = SLAVE_AD_INFO(slave).id;
|
||||
// key is determined according to the link speed, duplex and user key(which is yet not supported)
|
||||
|
@ -1932,8 +1933,6 @@ int bond_3ad_bind_slave(struct slave *slave)
|
|||
port->next_port_in_aggregator = NULL;
|
||||
|
||||
__disable_port(port);
|
||||
__initialize_port_locks(port);
|
||||
|
||||
|
||||
// aggregator initialization
|
||||
aggregator = &(SLAVE_AD_INFO(slave).aggregator);
|
||||
|
@ -1973,7 +1972,7 @@ void bond_3ad_unbind_slave(struct slave *slave)
|
|||
// if slave is null, the whole port is not initialized
|
||||
if (!port->slave) {
|
||||
pr_warning("Warning: %s: Trying to unbind an uninitialized port on %s\n",
|
||||
slave->dev->master->name, slave->dev->name);
|
||||
slave->bond->dev->name, slave->dev->name);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2009,7 +2008,7 @@ void bond_3ad_unbind_slave(struct slave *slave)
|
|||
|
||||
if ((new_aggregator->lag_ports == port) && new_aggregator->is_active) {
|
||||
pr_info("%s: Removing an active aggregator\n",
|
||||
aggregator->slave->dev->master->name);
|
||||
aggregator->slave->bond->dev->name);
|
||||
// select new active aggregator
|
||||
select_new_active_agg = 1;
|
||||
}
|
||||
|
@ -2040,7 +2039,7 @@ void bond_3ad_unbind_slave(struct slave *slave)
|
|||
ad_agg_selection_logic(__get_first_agg(port));
|
||||
} else {
|
||||
pr_warning("%s: Warning: unbinding aggregator, and could not find a new aggregator for its ports\n",
|
||||
slave->dev->master->name);
|
||||
slave->bond->dev->name);
|
||||
}
|
||||
} else { // in case that the only port related to this aggregator is the one we want to remove
|
||||
select_new_active_agg = aggregator->is_active;
|
||||
|
@ -2048,7 +2047,7 @@ void bond_3ad_unbind_slave(struct slave *slave)
|
|||
ad_clear_agg(aggregator);
|
||||
if (select_new_active_agg) {
|
||||
pr_info("%s: Removing an active aggregator\n",
|
||||
slave->dev->master->name);
|
||||
slave->bond->dev->name);
|
||||
// select new active aggregator
|
||||
ad_agg_selection_logic(__get_first_agg(port));
|
||||
}
|
||||
|
@ -2076,7 +2075,7 @@ void bond_3ad_unbind_slave(struct slave *slave)
|
|||
ad_clear_agg(temp_aggregator);
|
||||
if (select_new_active_agg) {
|
||||
pr_info("%s: Removing an active aggregator\n",
|
||||
slave->dev->master->name);
|
||||
slave->bond->dev->name);
|
||||
// select new active aggregator
|
||||
ad_agg_selection_logic(__get_first_agg(port));
|
||||
}
|
||||
|
@ -2184,7 +2183,7 @@ static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u1
|
|||
|
||||
if (!port->slave) {
|
||||
pr_warning("%s: Warning: port of slave %s is uninitialized\n",
|
||||
slave->dev->name, slave->dev->master->name);
|
||||
slave->dev->name, slave->bond->dev->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2240,7 +2239,7 @@ void bond_3ad_adapter_speed_changed(struct slave *slave)
|
|||
// if slave is null, the whole port is not initialized
|
||||
if (!port->slave) {
|
||||
pr_warning("Warning: %s: speed changed for uninitialized port on %s\n",
|
||||
slave->dev->master->name, slave->dev->name);
|
||||
slave->bond->dev->name, slave->dev->name);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2268,7 +2267,7 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
|
|||
// if slave is null, the whole port is not initialized
|
||||
if (!port->slave) {
|
||||
pr_warning("%s: Warning: duplex changed for uninitialized port on %s\n",
|
||||
slave->dev->master->name, slave->dev->name);
|
||||
slave->bond->dev->name, slave->dev->name);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2297,7 +2296,7 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
|
|||
// if slave is null, the whole port is not initialized
|
||||
if (!port->slave) {
|
||||
pr_warning("Warning: %s: link status changed for uninitialized port on %s\n",
|
||||
slave->dev->master->name, slave->dev->name);
|
||||
slave->bond->dev->name, slave->dev->name);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2494,11 +2493,13 @@ void bond_3ad_update_lacp_rate(struct bonding *bond)
|
|||
struct port *port = NULL;
|
||||
int lacp_fast;
|
||||
|
||||
read_lock(&bond->lock);
|
||||
write_lock_bh(&bond->lock);
|
||||
lacp_fast = bond->params.lacp_fast;
|
||||
|
||||
bond_for_each_slave(bond, slave, i) {
|
||||
port = &(SLAVE_AD_INFO(slave).port);
|
||||
if (port->slave == NULL)
|
||||
continue;
|
||||
__get_state_machine_lock(port);
|
||||
if (lacp_fast)
|
||||
port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT;
|
||||
|
@ -2507,5 +2508,5 @@ void bond_3ad_update_lacp_rate(struct bonding *bond)
|
|||
__release_state_machine_lock(port);
|
||||
}
|
||||
|
||||
read_unlock(&bond->lock);
|
||||
write_unlock_bh(&bond->lock);
|
||||
}
|
||||
|
|
|
@ -507,7 +507,7 @@ static void rlb_update_client(struct rlb_client_info *client_info)
|
|||
client_info->mac_dst);
|
||||
if (!skb) {
|
||||
pr_err("%s: Error: failed to create an ARP packet\n",
|
||||
client_info->slave->dev->master->name);
|
||||
client_info->slave->bond->dev->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -517,7 +517,7 @@ static void rlb_update_client(struct rlb_client_info *client_info)
|
|||
skb = vlan_put_tag(skb, client_info->vlan_id);
|
||||
if (!skb) {
|
||||
pr_err("%s: Error: failed to insert VLAN tag\n",
|
||||
client_info->slave->dev->master->name);
|
||||
client_info->slave->bond->dev->name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -1043,7 +1043,7 @@ static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[])
|
|||
if (dev_set_mac_address(dev, &s_addr)) {
|
||||
pr_err("%s: Error: dev_set_mac_address of dev %s failed!\n"
|
||||
"ALB mode requires that the base driver support setting the hw address also when the network device's interface is open\n",
|
||||
dev->master->name, dev->name);
|
||||
slave->bond->dev->name, dev->name);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -746,11 +746,9 @@ static void __bond_resend_igmp_join_requests(struct net_device *dev)
|
|||
{
|
||||
struct in_device *in_dev;
|
||||
|
||||
rcu_read_lock();
|
||||
in_dev = __in_dev_get_rcu(dev);
|
||||
if (in_dev)
|
||||
ip_mc_rejoin_groups(in_dev);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -760,9 +758,10 @@ static void __bond_resend_igmp_join_requests(struct net_device *dev)
|
|||
*/
|
||||
static void bond_resend_igmp_join_requests(struct bonding *bond)
|
||||
{
|
||||
struct net_device *bond_dev, *vlan_dev, *master_dev;
|
||||
struct net_device *bond_dev, *vlan_dev, *upper_dev;
|
||||
struct vlan_entry *vlan;
|
||||
|
||||
rcu_read_lock();
|
||||
read_lock(&bond->lock);
|
||||
|
||||
bond_dev = bond->dev;
|
||||
|
@ -774,18 +773,14 @@ static void bond_resend_igmp_join_requests(struct bonding *bond)
|
|||
* if bond is enslaved to a bridge,
|
||||
* then rejoin all groups on its master
|
||||
*/
|
||||
master_dev = bond_dev->master;
|
||||
if (master_dev)
|
||||
if ((master_dev->priv_flags & IFF_EBRIDGE)
|
||||
&& (bond_dev->priv_flags & IFF_BRIDGE_PORT))
|
||||
__bond_resend_igmp_join_requests(master_dev);
|
||||
upper_dev = netdev_master_upper_dev_get_rcu(bond_dev);
|
||||
if (upper_dev && upper_dev->priv_flags & IFF_EBRIDGE)
|
||||
__bond_resend_igmp_join_requests(upper_dev);
|
||||
|
||||
/* rejoin all groups on vlan devices */
|
||||
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
|
||||
rcu_read_lock();
|
||||
vlan_dev = __vlan_find_dev_deep(bond_dev,
|
||||
vlan->vlan_id);
|
||||
rcu_read_unlock();
|
||||
if (vlan_dev)
|
||||
__bond_resend_igmp_join_requests(vlan_dev);
|
||||
}
|
||||
|
@ -794,13 +789,16 @@ static void bond_resend_igmp_join_requests(struct bonding *bond)
|
|||
queue_delayed_work(bond->wq, &bond->mcast_work, HZ/5);
|
||||
|
||||
read_unlock(&bond->lock);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void bond_resend_igmp_join_requests_delayed(struct work_struct *work)
|
||||
{
|
||||
struct bonding *bond = container_of(work, struct bonding,
|
||||
mcast_work.work);
|
||||
rcu_read_lock();
|
||||
bond_resend_igmp_join_requests(bond);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1251,7 +1249,7 @@ static inline void slave_disable_netpoll(struct slave *slave)
|
|||
return;
|
||||
|
||||
slave->np = NULL;
|
||||
__netpoll_free_rcu(np);
|
||||
__netpoll_free_async(np);
|
||||
}
|
||||
static inline bool slave_dev_support_netpoll(struct net_device *slave_dev)
|
||||
{
|
||||
|
@ -1322,14 +1320,15 @@ static void bond_netpoll_cleanup(struct net_device *bond_dev)
|
|||
|
||||
/*---------------------------------- IOCTL ----------------------------------*/
|
||||
|
||||
static int bond_sethwaddr(struct net_device *bond_dev,
|
||||
struct net_device *slave_dev)
|
||||
static void bond_set_dev_addr(struct net_device *bond_dev,
|
||||
struct net_device *slave_dev)
|
||||
{
|
||||
pr_debug("bond_dev=%p\n", bond_dev);
|
||||
pr_debug("slave_dev=%p\n", slave_dev);
|
||||
pr_debug("slave_dev->addr_len=%d\n", slave_dev->addr_len);
|
||||
memcpy(bond_dev->dev_addr, slave_dev->dev_addr, slave_dev->addr_len);
|
||||
return 0;
|
||||
bond_dev->addr_assign_type = NET_ADDR_SET;
|
||||
call_netdevice_notifiers(NETDEV_CHANGEADDR, bond_dev);
|
||||
}
|
||||
|
||||
static netdev_features_t bond_fix_features(struct net_device *dev,
|
||||
|
@ -1493,6 +1492,27 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int bond_master_upper_dev_link(struct net_device *bond_dev,
|
||||
struct net_device *slave_dev)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = netdev_master_upper_dev_link(slave_dev, bond_dev);
|
||||
if (err)
|
||||
return err;
|
||||
slave_dev->flags |= IFF_SLAVE;
|
||||
rtmsg_ifinfo(RTM_NEWLINK, slave_dev, IFF_SLAVE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bond_upper_dev_unlink(struct net_device *bond_dev,
|
||||
struct net_device *slave_dev)
|
||||
{
|
||||
netdev_upper_dev_unlink(slave_dev, bond_dev);
|
||||
slave_dev->flags &= ~IFF_SLAVE;
|
||||
rtmsg_ifinfo(RTM_NEWLINK, slave_dev, IFF_SLAVE);
|
||||
}
|
||||
|
||||
/* enslave device <slave> to bond device <master> */
|
||||
int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
|
||||
{
|
||||
|
@ -1609,10 +1629,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
|
|||
|
||||
/* If this is the first slave, then we need to set the master's hardware
|
||||
* address to be the same as the slave's. */
|
||||
if (is_zero_ether_addr(bond->dev->dev_addr))
|
||||
memcpy(bond->dev->dev_addr, slave_dev->dev_addr,
|
||||
slave_dev->addr_len);
|
||||
|
||||
if (bond->dev_addr_from_first)
|
||||
bond_set_dev_addr(bond->dev, slave_dev);
|
||||
|
||||
new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL);
|
||||
if (!new_slave) {
|
||||
|
@ -1655,9 +1673,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
|
|||
}
|
||||
}
|
||||
|
||||
res = netdev_set_bond_master(slave_dev, bond_dev);
|
||||
res = bond_master_upper_dev_link(bond_dev, slave_dev);
|
||||
if (res) {
|
||||
pr_debug("Error %d calling netdev_set_bond_master\n", res);
|
||||
pr_debug("Error %d calling bond_master_upper_dev_link\n", res);
|
||||
goto err_restore_mac;
|
||||
}
|
||||
|
||||
|
@ -1891,7 +1909,7 @@ err_close:
|
|||
dev_close(slave_dev);
|
||||
|
||||
err_unset_master:
|
||||
netdev_set_bond_master(slave_dev, NULL);
|
||||
bond_upper_dev_unlink(bond_dev, slave_dev);
|
||||
|
||||
err_restore_mac:
|
||||
if (!bond->params.fail_over_mac) {
|
||||
|
@ -1919,7 +1937,8 @@ err_undo_flags:
|
|||
/*
|
||||
* Try to release the slave device <slave> from the bond device <master>
|
||||
* It is legal to access curr_active_slave without a lock because all the function
|
||||
* is write-locked.
|
||||
* is write-locked. If "all" is true it means that the function is being called
|
||||
* while destroying a bond interface and all slaves are being released.
|
||||
*
|
||||
* The rules for slave state should be:
|
||||
* for Active/Backup:
|
||||
|
@ -1927,7 +1946,9 @@ err_undo_flags:
|
|||
* for Bonded connections:
|
||||
* The first up interface should be left on and all others downed.
|
||||
*/
|
||||
int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
|
||||
static int __bond_release_one(struct net_device *bond_dev,
|
||||
struct net_device *slave_dev,
|
||||
bool all)
|
||||
{
|
||||
struct bonding *bond = netdev_priv(bond_dev);
|
||||
struct slave *slave, *oldcurrent;
|
||||
|
@ -1936,7 +1957,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
|
|||
|
||||
/* slave is not a slave or master is not master of this slave */
|
||||
if (!(slave_dev->flags & IFF_SLAVE) ||
|
||||
(slave_dev->master != bond_dev)) {
|
||||
!netdev_has_upper_dev(slave_dev, bond_dev)) {
|
||||
pr_err("%s: Error: cannot release %s.\n",
|
||||
bond_dev->name, slave_dev->name);
|
||||
return -EINVAL;
|
||||
|
@ -1964,7 +1985,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
|
|||
synchronize_net();
|
||||
write_lock_bh(&bond->lock);
|
||||
|
||||
if (!bond->params.fail_over_mac) {
|
||||
if (!all && !bond->params.fail_over_mac) {
|
||||
if (ether_addr_equal(bond_dev->dev_addr, slave->perm_hwaddr) &&
|
||||
bond->slave_cnt > 1)
|
||||
pr_warning("%s: Warning: the permanent HWaddr of %s - %pM - is still in use by %s. Set the HWaddr of %s to a different address to avoid conflicts.\n",
|
||||
|
@ -2010,7 +2031,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
|
|||
write_lock_bh(&bond->lock);
|
||||
}
|
||||
|
||||
if (oldcurrent == slave) {
|
||||
if (all) {
|
||||
bond->curr_active_slave = NULL;
|
||||
} else if (oldcurrent == slave) {
|
||||
/*
|
||||
* Note that we hold RTNL over this sequence, so there
|
||||
* is no concern that another slave add/remove event
|
||||
|
@ -2029,12 +2052,8 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
|
|||
|
||||
if (bond->slave_cnt == 0) {
|
||||
bond_set_carrier(bond);
|
||||
|
||||
/* if the last slave was removed, zero the mac address
|
||||
* of the master so it will be set by the application
|
||||
* to the mac address of the first slave
|
||||
*/
|
||||
memset(bond_dev->dev_addr, 0, bond_dev->addr_len);
|
||||
eth_hw_addr_random(bond_dev);
|
||||
bond->dev_addr_from_first = true;
|
||||
|
||||
if (bond_vlan_used(bond)) {
|
||||
pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n",
|
||||
|
@ -2080,7 +2099,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
|
|||
netif_addr_unlock_bh(bond_dev);
|
||||
}
|
||||
|
||||
netdev_set_bond_master(slave_dev, NULL);
|
||||
bond_upper_dev_unlink(bond_dev, slave_dev);
|
||||
|
||||
slave_disable_netpoll(slave);
|
||||
|
||||
|
@ -2103,6 +2122,12 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
|
|||
return 0; /* deletion OK */
|
||||
}
|
||||
|
||||
/* A wrapper used because of ndo_del_link */
|
||||
int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
|
||||
{
|
||||
return __bond_release_one(bond_dev, slave_dev, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* First release a slave and then destroy the bond if no more slaves are left.
|
||||
* Must be under rtnl_lock when this function is called.
|
||||
|
@ -2123,121 +2148,6 @@ static int bond_release_and_destroy(struct net_device *bond_dev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function releases all slaves.
|
||||
*/
|
||||
static int bond_release_all(struct net_device *bond_dev)
|
||||
{
|
||||
struct bonding *bond = netdev_priv(bond_dev);
|
||||
struct slave *slave;
|
||||
struct net_device *slave_dev;
|
||||
struct sockaddr addr;
|
||||
|
||||
write_lock_bh(&bond->lock);
|
||||
|
||||
netif_carrier_off(bond_dev);
|
||||
|
||||
if (bond->slave_cnt == 0)
|
||||
goto out;
|
||||
|
||||
bond->current_arp_slave = NULL;
|
||||
bond->primary_slave = NULL;
|
||||
bond_change_active_slave(bond, NULL);
|
||||
|
||||
while ((slave = bond->first_slave) != NULL) {
|
||||
/* Inform AD package of unbinding of slave
|
||||
* before slave is detached from the list.
|
||||
*/
|
||||
if (bond->params.mode == BOND_MODE_8023AD)
|
||||
bond_3ad_unbind_slave(slave);
|
||||
|
||||
slave_dev = slave->dev;
|
||||
bond_detach_slave(bond, slave);
|
||||
|
||||
/* now that the slave is detached, unlock and perform
|
||||
* all the undo steps that should not be called from
|
||||
* within a lock.
|
||||
*/
|
||||
write_unlock_bh(&bond->lock);
|
||||
|
||||
/* unregister rx_handler early so bond_handle_frame wouldn't
|
||||
* be called for this slave anymore.
|
||||
*/
|
||||
netdev_rx_handler_unregister(slave_dev);
|
||||
synchronize_net();
|
||||
|
||||
if (bond_is_lb(bond)) {
|
||||
/* must be called only after the slave
|
||||
* has been detached from the list
|
||||
*/
|
||||
bond_alb_deinit_slave(bond, slave);
|
||||
}
|
||||
|
||||
bond_destroy_slave_symlinks(bond_dev, slave_dev);
|
||||
bond_del_vlans_from_slave(bond, slave_dev);
|
||||
|
||||
/* If the mode USES_PRIMARY, then we should only remove its
|
||||
* promisc and mc settings if it was the curr_active_slave, but that was
|
||||
* already taken care of above when we detached the slave
|
||||
*/
|
||||
if (!USES_PRIMARY(bond->params.mode)) {
|
||||
/* unset promiscuity level from slave */
|
||||
if (bond_dev->flags & IFF_PROMISC)
|
||||
dev_set_promiscuity(slave_dev, -1);
|
||||
|
||||
/* unset allmulti level from slave */
|
||||
if (bond_dev->flags & IFF_ALLMULTI)
|
||||
dev_set_allmulti(slave_dev, -1);
|
||||
|
||||
/* flush master's mc_list from slave */
|
||||
netif_addr_lock_bh(bond_dev);
|
||||
bond_mc_list_flush(bond_dev, slave_dev);
|
||||
netif_addr_unlock_bh(bond_dev);
|
||||
}
|
||||
|
||||
netdev_set_bond_master(slave_dev, NULL);
|
||||
|
||||
slave_disable_netpoll(slave);
|
||||
|
||||
/* close slave before restoring its mac address */
|
||||
dev_close(slave_dev);
|
||||
|
||||
if (!bond->params.fail_over_mac) {
|
||||
/* restore original ("permanent") mac address*/
|
||||
memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
|
||||
addr.sa_family = slave_dev->type;
|
||||
dev_set_mac_address(slave_dev, &addr);
|
||||
}
|
||||
|
||||
kfree(slave);
|
||||
|
||||
/* re-acquire the lock before getting the next slave */
|
||||
write_lock_bh(&bond->lock);
|
||||
}
|
||||
|
||||
/* zero the mac address of the master so it will be
|
||||
* set by the application to the mac address of the
|
||||
* first slave
|
||||
*/
|
||||
memset(bond_dev->dev_addr, 0, bond_dev->addr_len);
|
||||
|
||||
if (bond_vlan_used(bond)) {
|
||||
pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n",
|
||||
bond_dev->name, bond_dev->name);
|
||||
pr_warning("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs'.\n",
|
||||
bond_dev->name);
|
||||
}
|
||||
|
||||
pr_info("%s: released all slaves\n", bond_dev->name);
|
||||
|
||||
out:
|
||||
write_unlock_bh(&bond->lock);
|
||||
|
||||
bond_compute_features(bond);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function changes the active slave to slave <slave_dev>.
|
||||
* It returns -EINVAL in the following cases.
|
||||
|
@ -2259,8 +2169,9 @@ static int bond_ioctl_change_active(struct net_device *bond_dev, struct net_devi
|
|||
if (!USES_PRIMARY(bond->params.mode))
|
||||
return -EINVAL;
|
||||
|
||||
/* Verify that master_dev is indeed the master of slave_dev */
|
||||
if (!(slave_dev->flags & IFF_SLAVE) || (slave_dev->master != bond_dev))
|
||||
/* Verify that bond_dev is indeed the master of slave_dev */
|
||||
if (!(slave_dev->flags & IFF_SLAVE) ||
|
||||
!netdev_has_upper_dev(slave_dev, bond_dev))
|
||||
return -EINVAL;
|
||||
|
||||
read_lock(&bond->lock);
|
||||
|
@ -3258,36 +3169,32 @@ static int bond_master_netdev_event(unsigned long event,
|
|||
static int bond_slave_netdev_event(unsigned long event,
|
||||
struct net_device *slave_dev)
|
||||
{
|
||||
struct net_device *bond_dev = slave_dev->master;
|
||||
struct bonding *bond = netdev_priv(bond_dev);
|
||||
struct slave *slave = NULL;
|
||||
struct slave *slave = bond_slave_get_rtnl(slave_dev);
|
||||
struct bonding *bond = slave->bond;
|
||||
struct net_device *bond_dev = slave->bond->dev;
|
||||
u32 old_speed;
|
||||
u8 old_duplex;
|
||||
|
||||
switch (event) {
|
||||
case NETDEV_UNREGISTER:
|
||||
if (bond_dev) {
|
||||
if (bond->setup_by_slave)
|
||||
bond_release_and_destroy(bond_dev, slave_dev);
|
||||
else
|
||||
bond_release(bond_dev, slave_dev);
|
||||
}
|
||||
if (bond->setup_by_slave)
|
||||
bond_release_and_destroy(bond_dev, slave_dev);
|
||||
else
|
||||
bond_release(bond_dev, slave_dev);
|
||||
break;
|
||||
case NETDEV_UP:
|
||||
case NETDEV_CHANGE:
|
||||
slave = bond_get_slave_by_dev(bond, slave_dev);
|
||||
if (slave) {
|
||||
u32 old_speed = slave->speed;
|
||||
u8 old_duplex = slave->duplex;
|
||||
old_speed = slave->speed;
|
||||
old_duplex = slave->duplex;
|
||||
|
||||
bond_update_speed_duplex(slave);
|
||||
bond_update_speed_duplex(slave);
|
||||
|
||||
if (bond->params.mode == BOND_MODE_8023AD) {
|
||||
if (old_speed != slave->speed)
|
||||
bond_3ad_adapter_speed_changed(slave);
|
||||
if (old_duplex != slave->duplex)
|
||||
bond_3ad_adapter_duplex_changed(slave);
|
||||
}
|
||||
if (bond->params.mode == BOND_MODE_8023AD) {
|
||||
if (old_speed != slave->speed)
|
||||
bond_3ad_adapter_speed_changed(slave);
|
||||
if (old_duplex != slave->duplex)
|
||||
bond_3ad_adapter_duplex_changed(slave);
|
||||
}
|
||||
|
||||
break;
|
||||
case NETDEV_DOWN:
|
||||
/*
|
||||
|
@ -3604,6 +3511,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
|
|||
struct ifslave k_sinfo;
|
||||
struct ifslave __user *u_sinfo = NULL;
|
||||
struct mii_ioctl_data *mii = NULL;
|
||||
struct net *net;
|
||||
int res = 0;
|
||||
|
||||
pr_debug("bond_ioctl: master=%s, cmd=%d\n", bond_dev->name, cmd);
|
||||
|
@ -3670,10 +3578,12 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
|
|||
break;
|
||||
}
|
||||
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
net = dev_net(bond_dev);
|
||||
|
||||
if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
slave_dev = dev_get_by_name(dev_net(bond_dev), ifr->ifr_slave);
|
||||
slave_dev = dev_get_by_name(net, ifr->ifr_slave);
|
||||
|
||||
pr_debug("slave_dev=%p:\n", slave_dev);
|
||||
|
||||
|
@ -3692,7 +3602,8 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
|
|||
break;
|
||||
case BOND_SETHWADDR_OLD:
|
||||
case SIOCBONDSETHWADDR:
|
||||
res = bond_sethwaddr(bond_dev, slave_dev);
|
||||
bond_set_dev_addr(bond_dev, slave_dev);
|
||||
res = 0;
|
||||
break;
|
||||
case BOND_CHANGE_ACTIVE_OLD:
|
||||
case SIOCBONDCHANGEACTIVE:
|
||||
|
@ -4314,11 +4225,12 @@ void bond_set_mode_ops(struct bonding *bond, int mode)
|
|||
}
|
||||
|
||||
static void bond_ethtool_get_drvinfo(struct net_device *bond_dev,
|
||||
struct ethtool_drvinfo *drvinfo)
|
||||
struct ethtool_drvinfo *drvinfo)
|
||||
{
|
||||
strncpy(drvinfo->driver, DRV_NAME, 32);
|
||||
strncpy(drvinfo->version, DRV_VERSION, 32);
|
||||
snprintf(drvinfo->fw_version, 32, "%d", BOND_ABI_VERSION);
|
||||
strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
|
||||
strlcpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version));
|
||||
snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "%d",
|
||||
BOND_ABI_VERSION);
|
||||
}
|
||||
|
||||
static const struct ethtool_ops bond_ethtool_ops = {
|
||||
|
@ -4352,6 +4264,10 @@ static const struct net_device_ops bond_netdev_ops = {
|
|||
.ndo_fix_features = bond_fix_features,
|
||||
};
|
||||
|
||||
static const struct device_type bond_type = {
|
||||
.name = "bond",
|
||||
};
|
||||
|
||||
static void bond_destructor(struct net_device *bond_dev)
|
||||
{
|
||||
struct bonding *bond = netdev_priv(bond_dev);
|
||||
|
@ -4382,6 +4298,8 @@ static void bond_setup(struct net_device *bond_dev)
|
|||
|
||||
bond_dev->destructor = bond_destructor;
|
||||
|
||||
SET_NETDEV_DEVTYPE(bond_dev, &bond_type);
|
||||
|
||||
/* Initialize the device options */
|
||||
bond_dev->tx_queue_len = 0;
|
||||
bond_dev->flags |= IFF_MASTER|IFF_MULTICAST;
|
||||
|
@ -4427,7 +4345,9 @@ static void bond_uninit(struct net_device *bond_dev)
|
|||
bond_netpoll_cleanup(bond_dev);
|
||||
|
||||
/* Release the bonded slaves */
|
||||
bond_release_all(bond_dev);
|
||||
while (bond->first_slave != NULL)
|
||||
__bond_release_one(bond_dev, bond->first_slave->dev, true);
|
||||
pr_info("%s: released all slaves\n", bond_dev->name);
|
||||
|
||||
list_del(&bond->bond_list);
|
||||
|
||||
|
@ -4841,6 +4761,13 @@ static int bond_init(struct net_device *bond_dev)
|
|||
|
||||
bond_debug_register(bond);
|
||||
|
||||
/* Ensure valid dev_addr */
|
||||
if (is_zero_ether_addr(bond_dev->dev_addr) &&
|
||||
bond_dev->addr_assign_type == NET_ADDR_PERM) {
|
||||
eth_hw_addr_random(bond_dev);
|
||||
bond->dev_addr_from_first = true;
|
||||
}
|
||||
|
||||
__hw_addr_init(&bond->mc_list);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -248,6 +248,7 @@ struct bonding {
|
|||
/* debugging support via debugfs */
|
||||
struct dentry *debug_dir;
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
bool dev_addr_from_first;
|
||||
};
|
||||
|
||||
static inline bool bond_vlan_used(struct bonding *bond)
|
||||
|
@ -258,6 +259,9 @@ static inline bool bond_vlan_used(struct bonding *bond)
|
|||
#define bond_slave_get_rcu(dev) \
|
||||
((struct slave *) rcu_dereference(dev->rx_handler_data))
|
||||
|
||||
#define bond_slave_get_rtnl(dev) \
|
||||
((struct slave *) rtnl_dereference(dev->rx_handler_data))
|
||||
|
||||
/**
|
||||
* Returns NULL if the net_device does not belong to any of the bond's slaves
|
||||
*
|
||||
|
@ -280,11 +284,9 @@ static inline struct slave *bond_get_slave_by_dev(struct bonding *bond,
|
|||
|
||||
static inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
|
||||
{
|
||||
if (!slave || !slave->dev->master) {
|
||||
if (!slave || !slave->bond)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return netdev_priv(slave->dev->master);
|
||||
return slave->bond;
|
||||
}
|
||||
|
||||
static inline bool bond_is_lb(const struct bonding *bond)
|
||||
|
@ -360,10 +362,9 @@ static inline void bond_netpoll_send_skb(const struct slave *slave,
|
|||
|
||||
static inline void bond_set_slave_inactive_flags(struct slave *slave)
|
||||
{
|
||||
struct bonding *bond = netdev_priv(slave->dev->master);
|
||||
if (!bond_is_lb(bond))
|
||||
if (!bond_is_lb(slave->bond))
|
||||
bond_set_backup_slave(slave);
|
||||
if (!bond->params.all_slaves_active)
|
||||
if (!slave->bond->params.all_slaves_active)
|
||||
slave->inactive = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -633,9 +633,6 @@ int caif_shmcore_probe(struct shmdev_layer *pshm_dev)
|
|||
kmalloc(sizeof(struct buf_list), GFP_KERNEL);
|
||||
|
||||
if (tx_buf == NULL) {
|
||||
pr_warn("ERROR, Could not"
|
||||
" allocate dynamic mem. for tx_buf,"
|
||||
" Bailing out ...\n");
|
||||
free_netdev(pshm_dev->pshm_netdev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -662,9 +659,6 @@ int caif_shmcore_probe(struct shmdev_layer *pshm_dev)
|
|||
kmalloc(sizeof(struct buf_list), GFP_KERNEL);
|
||||
|
||||
if (rx_buf == NULL) {
|
||||
pr_warn("ERROR, Could not"
|
||||
" allocate dynamic mem.for rx_buf,"
|
||||
" Bailing out ...\n");
|
||||
free_netdev(pshm_dev->pshm_netdev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
menu "CAN Device Drivers"
|
||||
depends on CAN
|
||||
|
||||
config CAN_VCAN
|
||||
tristate "Virtual Local CAN Interface (vcan)"
|
||||
depends on CAN
|
||||
---help---
|
||||
Similar to the network loopback devices, vcan offers a
|
||||
virtual local CAN interface.
|
||||
|
@ -13,7 +11,6 @@ config CAN_VCAN
|
|||
|
||||
config CAN_SLCAN
|
||||
tristate "Serial / USB serial CAN Adaptors (slcan)"
|
||||
depends on CAN
|
||||
---help---
|
||||
CAN driver for several 'low cost' CAN interfaces that are attached
|
||||
via serial lines or via USB-to-serial adapters using the LAWICEL
|
||||
|
@ -33,16 +30,16 @@ config CAN_SLCAN
|
|||
|
||||
config CAN_DEV
|
||||
tristate "Platform CAN drivers with Netlink support"
|
||||
depends on CAN
|
||||
default y
|
||||
---help---
|
||||
Enables the common framework for platform CAN drivers with Netlink
|
||||
support. This is the standard library for CAN drivers.
|
||||
If unsure, say Y.
|
||||
|
||||
if CAN_DEV
|
||||
|
||||
config CAN_CALC_BITTIMING
|
||||
bool "CAN bit-timing calculation"
|
||||
depends on CAN_DEV
|
||||
default y
|
||||
---help---
|
||||
If enabled, CAN bit-timing parameters will be calculated for the
|
||||
|
@ -54,15 +51,26 @@ config CAN_CALC_BITTIMING
|
|||
arguments "tq", "prop_seg", "phase_seg1", "phase_seg2" and "sjw".
|
||||
If unsure, say Y.
|
||||
|
||||
config CAN_LEDS
|
||||
bool "Enable LED triggers for Netlink based drivers"
|
||||
depends on LEDS_CLASS
|
||||
select LEDS_TRIGGERS
|
||||
---help---
|
||||
This option adds two LED triggers for packet receive and transmit
|
||||
events on each supported CAN device.
|
||||
|
||||
Say Y here if you are working on a system with led-class supported
|
||||
LEDs and you want to use them as canbus activity indicators.
|
||||
|
||||
config CAN_AT91
|
||||
tristate "Atmel AT91 onchip CAN controller"
|
||||
depends on CAN_DEV && (ARCH_AT91SAM9263 || ARCH_AT91SAM9X5)
|
||||
depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9X5
|
||||
---help---
|
||||
This is a driver for the SoC CAN controller in Atmel's AT91SAM9263
|
||||
and AT91SAM9X5 processors.
|
||||
|
||||
config CAN_TI_HECC
|
||||
depends on CAN_DEV && ARCH_OMAP3
|
||||
depends on ARCH_OMAP3
|
||||
tristate "TI High End CAN Controller"
|
||||
---help---
|
||||
Driver for TI HECC (High End CAN Controller) module found on many
|
||||
|
@ -70,12 +78,12 @@ config CAN_TI_HECC
|
|||
|
||||
config CAN_MCP251X
|
||||
tristate "Microchip MCP251x SPI CAN controllers"
|
||||
depends on CAN_DEV && SPI && HAS_DMA
|
||||
depends on SPI && HAS_DMA
|
||||
---help---
|
||||
Driver for the Microchip MCP251x SPI CAN controllers.
|
||||
|
||||
config CAN_BFIN
|
||||
depends on CAN_DEV && (BF534 || BF536 || BF537 || BF538 || BF539 || BF54x)
|
||||
depends on BF534 || BF536 || BF537 || BF538 || BF539 || BF54x
|
||||
tristate "Analog Devices Blackfin on-chip CAN"
|
||||
---help---
|
||||
Driver for the Analog Devices Blackfin on-chip CAN controllers
|
||||
|
@ -85,7 +93,7 @@ config CAN_BFIN
|
|||
|
||||
config CAN_JANZ_ICAN3
|
||||
tristate "Janz VMOD-ICAN3 Intelligent CAN controller"
|
||||
depends on CAN_DEV && MFD_JANZ_CMODIO
|
||||
depends on MFD_JANZ_CMODIO
|
||||
---help---
|
||||
Driver for Janz VMOD-ICAN3 Intelligent CAN controller module, which
|
||||
connects to a MODULbus carrier board.
|
||||
|
@ -98,13 +106,13 @@ config HAVE_CAN_FLEXCAN
|
|||
|
||||
config CAN_FLEXCAN
|
||||
tristate "Support for Freescale FLEXCAN based chips"
|
||||
depends on CAN_DEV && HAVE_CAN_FLEXCAN
|
||||
depends on HAVE_CAN_FLEXCAN
|
||||
---help---
|
||||
Say Y here if you want to support for Freescale FlexCAN.
|
||||
|
||||
config PCH_CAN
|
||||
tristate "Intel EG20T PCH CAN controller"
|
||||
depends on CAN_DEV && PCI
|
||||
depends on PCI
|
||||
---help---
|
||||
This driver is for PCH CAN of Topcliff (Intel EG20T PCH) which
|
||||
is an IOH for x86 embedded processor (Intel Atom E6xx series).
|
||||
|
@ -112,7 +120,7 @@ config PCH_CAN
|
|||
|
||||
config CAN_GRCAN
|
||||
tristate "Aeroflex Gaisler GRCAN and GRHCAN CAN devices"
|
||||
depends on CAN_DEV && OF
|
||||
depends on OF
|
||||
---help---
|
||||
Say Y here if you want to use Aeroflex Gaisler GRCAN or GRHCAN.
|
||||
Note that the driver supports little endian, even though little
|
||||
|
@ -131,9 +139,10 @@ source "drivers/net/can/usb/Kconfig"
|
|||
|
||||
source "drivers/net/can/softing/Kconfig"
|
||||
|
||||
endif
|
||||
|
||||
config CAN_DEBUG_DEVICES
|
||||
bool "CAN devices debugging messages"
|
||||
depends on CAN
|
||||
---help---
|
||||
Say Y here if you want the CAN device drivers to produce a bunch of
|
||||
debug messages to the system log. Select this if you are having
|
||||
|
|
|
@ -8,6 +8,8 @@ obj-$(CONFIG_CAN_SLCAN) += slcan.o
|
|||
obj-$(CONFIG_CAN_DEV) += can-dev.o
|
||||
can-dev-y := dev.o
|
||||
|
||||
can-dev-$(CONFIG_CAN_LEDS) += led.o
|
||||
|
||||
obj-y += usb/
|
||||
obj-y += softing/
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include <linux/can/dev.h>
|
||||
#include <linux/can/error.h>
|
||||
#include <linux/can/led.h>
|
||||
|
||||
#define AT91_MB_MASK(i) ((1 << (i)) - 1)
|
||||
|
||||
|
@ -641,6 +642,8 @@ static void at91_read_msg(struct net_device *dev, unsigned int mb)
|
|||
|
||||
stats->rx_packets++;
|
||||
stats->rx_bytes += cf->can_dlc;
|
||||
|
||||
can_led_event(dev, CAN_LED_EVENT_RX);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -875,6 +878,7 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr)
|
|||
/* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */
|
||||
can_get_echo_skb(dev, mb - get_mb_tx_first(priv));
|
||||
dev->stats.tx_packets++;
|
||||
can_led_event(dev, CAN_LED_EVENT_TX);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1128,6 +1132,8 @@ static int at91_open(struct net_device *dev)
|
|||
goto out_close;
|
||||
}
|
||||
|
||||
can_led_event(dev, CAN_LED_EVENT_OPEN);
|
||||
|
||||
/* start chip and queuing */
|
||||
at91_chip_start(dev);
|
||||
napi_enable(&priv->napi);
|
||||
|
@ -1159,6 +1165,8 @@ static int at91_close(struct net_device *dev)
|
|||
|
||||
close_candev(dev);
|
||||
|
||||
can_led_event(dev, CAN_LED_EVENT_STOP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1321,6 +1329,8 @@ static int at91_can_probe(struct platform_device *pdev)
|
|||
goto exit_free;
|
||||
}
|
||||
|
||||
devm_can_led_init(dev);
|
||||
|
||||
dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%d)\n",
|
||||
priv->reg_base, dev->irq);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
menuconfig CAN_C_CAN
|
||||
tristate "Bosch C_CAN/D_CAN devices"
|
||||
depends on CAN_DEV && HAS_IOMEM
|
||||
depends on HAS_IOMEM
|
||||
|
||||
if CAN_C_CAN
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include <linux/can.h>
|
||||
#include <linux/can/dev.h>
|
||||
#include <linux/can/error.h>
|
||||
#include <linux/can/led.h>
|
||||
|
||||
#include "c_can.h"
|
||||
|
||||
|
@ -477,6 +478,8 @@ static int c_can_read_msg_object(struct net_device *dev, int iface, int ctrl)
|
|||
stats->rx_packets++;
|
||||
stats->rx_bytes += frame->can_dlc;
|
||||
|
||||
can_led_event(dev, CAN_LED_EVENT_RX);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -755,6 +758,7 @@ static void c_can_do_tx(struct net_device *dev)
|
|||
C_CAN_IFACE(MSGCTRL_REG, 0))
|
||||
& IF_MCONT_DLC_MASK;
|
||||
stats->tx_packets++;
|
||||
can_led_event(dev, CAN_LED_EVENT_TX);
|
||||
c_can_inval_msg_object(dev, 0, msg_obj_no);
|
||||
} else {
|
||||
break;
|
||||
|
@ -1119,6 +1123,8 @@ static int c_can_open(struct net_device *dev)
|
|||
|
||||
napi_enable(&priv->napi);
|
||||
|
||||
can_led_event(dev, CAN_LED_EVENT_OPEN);
|
||||
|
||||
/* start the c_can controller */
|
||||
c_can_start(dev);
|
||||
|
||||
|
@ -1147,6 +1153,8 @@ static int c_can_close(struct net_device *dev)
|
|||
c_can_reset_ram(priv, false);
|
||||
c_can_pm_runtime_put_sync(priv);
|
||||
|
||||
can_led_event(dev, CAN_LED_EVENT_STOP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1272,6 +1280,8 @@ int register_c_can_dev(struct net_device *dev)
|
|||
err = register_candev(dev);
|
||||
if (err)
|
||||
c_can_pm_runtime_disable(priv);
|
||||
else
|
||||
devm_can_led_init(dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
menuconfig CAN_CC770
|
||||
tristate "Bosch CC770 and Intel AN82527 devices"
|
||||
depends on CAN_DEV && HAS_IOMEM
|
||||
depends on HAS_IOMEM
|
||||
|
||||
if CAN_CC770
|
||||
|
||||
|
|
|
@ -24,7 +24,9 @@
|
|||
#include <linux/if_arp.h>
|
||||
#include <linux/can.h>
|
||||
#include <linux/can/dev.h>
|
||||
#include <linux/can/skb.h>
|
||||
#include <linux/can/netlink.h>
|
||||
#include <linux/can/led.h>
|
||||
#include <net/rtnetlink.h>
|
||||
|
||||
#define MOD_DESC "CAN device driver interface"
|
||||
|
@ -501,13 +503,18 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
|
|||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = netdev_alloc_skb(dev, sizeof(struct can_frame));
|
||||
skb = netdev_alloc_skb(dev, sizeof(struct can_skb_priv) +
|
||||
sizeof(struct can_frame));
|
||||
if (unlikely(!skb))
|
||||
return NULL;
|
||||
|
||||
skb->protocol = htons(ETH_P_CAN);
|
||||
skb->pkt_type = PACKET_BROADCAST;
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
|
||||
can_skb_reserve(skb);
|
||||
can_skb_prv(skb)->ifindex = dev->ifindex;
|
||||
|
||||
*cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
|
||||
memset(*cf, 0, sizeof(struct can_frame));
|
||||
|
||||
|
@ -794,10 +801,25 @@ void unregister_candev(struct net_device *dev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(unregister_candev);
|
||||
|
||||
/*
|
||||
* Test if a network device is a candev based device
|
||||
* and return the can_priv* if so.
|
||||
*/
|
||||
struct can_priv *safe_candev_priv(struct net_device *dev)
|
||||
{
|
||||
if ((dev->type != ARPHRD_CAN) || (dev->rtnl_link_ops != &can_link_ops))
|
||||
return NULL;
|
||||
|
||||
return netdev_priv(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(safe_candev_priv);
|
||||
|
||||
static __init int can_dev_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
can_led_notifier_init();
|
||||
|
||||
err = rtnl_link_register(&can_link_ops);
|
||||
if (!err)
|
||||
printk(KERN_INFO MOD_DESC "\n");
|
||||
|
@ -809,6 +831,8 @@ module_init(can_dev_init);
|
|||
static __exit void can_dev_exit(void)
|
||||
{
|
||||
rtnl_link_unregister(&can_link_ops);
|
||||
|
||||
can_led_notifier_exit();
|
||||
}
|
||||
module_exit(can_dev_exit);
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/can.h>
|
||||
#include <linux/can/dev.h>
|
||||
#include <linux/can/error.h>
|
||||
#include <linux/can/led.h>
|
||||
#include <linux/can/platform/flexcan.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
|
@ -564,6 +565,8 @@ static int flexcan_read_frame(struct net_device *dev)
|
|||
stats->rx_packets++;
|
||||
stats->rx_bytes += cf->can_dlc;
|
||||
|
||||
can_led_event(dev, CAN_LED_EVENT_RX);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -652,6 +655,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
|
|||
if (reg_iflag1 & (1 << FLEXCAN_TX_BUF_ID)) {
|
||||
stats->tx_bytes += can_get_echo_skb(dev, 0);
|
||||
stats->tx_packets++;
|
||||
can_led_event(dev, CAN_LED_EVENT_TX);
|
||||
flexcan_write((1 << FLEXCAN_TX_BUF_ID), ®s->iflag1);
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
|
@ -865,6 +869,9 @@ static int flexcan_open(struct net_device *dev)
|
|||
err = flexcan_chip_start(dev);
|
||||
if (err)
|
||||
goto out_close;
|
||||
|
||||
can_led_event(dev, CAN_LED_EVENT_OPEN);
|
||||
|
||||
napi_enable(&priv->napi);
|
||||
netif_start_queue(dev);
|
||||
|
||||
|
@ -893,6 +900,8 @@ static int flexcan_close(struct net_device *dev)
|
|||
|
||||
close_candev(dev);
|
||||
|
||||
can_led_event(dev, CAN_LED_EVENT_STOP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1092,6 +1101,8 @@ static int flexcan_probe(struct platform_device *pdev)
|
|||
goto failed_register;
|
||||
}
|
||||
|
||||
devm_can_led_init(dev);
|
||||
|
||||
dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%d)\n",
|
||||
priv->base, dev->irq);
|
||||
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright 2012, Fabio Baltieri <fabio.baltieri@gmail.com>
|
||||
* Copyright 2012, Kurt Van Dijck <kurt.van.dijck@eia.be>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/can/dev.h>
|
||||
|
||||
#include <linux/can/led.h>
|
||||
|
||||
static unsigned long led_delay = 50;
|
||||
module_param(led_delay, ulong, 0644);
|
||||
MODULE_PARM_DESC(led_delay,
|
||||
"blink delay time for activity leds (msecs, default: 50).");
|
||||
|
||||
/* Trigger a LED event in response to a CAN device event */
|
||||
void can_led_event(struct net_device *netdev, enum can_led_event event)
|
||||
{
|
||||
struct can_priv *priv = netdev_priv(netdev);
|
||||
|
||||
switch (event) {
|
||||
case CAN_LED_EVENT_OPEN:
|
||||
led_trigger_event(priv->tx_led_trig, LED_FULL);
|
||||
led_trigger_event(priv->rx_led_trig, LED_FULL);
|
||||
break;
|
||||
case CAN_LED_EVENT_STOP:
|
||||
led_trigger_event(priv->tx_led_trig, LED_OFF);
|
||||
led_trigger_event(priv->rx_led_trig, LED_OFF);
|
||||
break;
|
||||
case CAN_LED_EVENT_TX:
|
||||
if (led_delay)
|
||||
led_trigger_blink_oneshot(priv->tx_led_trig,
|
||||
&led_delay, &led_delay, 1);
|
||||
break;
|
||||
case CAN_LED_EVENT_RX:
|
||||
if (led_delay)
|
||||
led_trigger_blink_oneshot(priv->rx_led_trig,
|
||||
&led_delay, &led_delay, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(can_led_event);
|
||||
|
||||
static void can_led_release(struct device *gendev, void *res)
|
||||
{
|
||||
struct can_priv *priv = netdev_priv(to_net_dev(gendev));
|
||||
|
||||
led_trigger_unregister_simple(priv->tx_led_trig);
|
||||
led_trigger_unregister_simple(priv->rx_led_trig);
|
||||
}
|
||||
|
||||
/* Register CAN LED triggers for a CAN device
|
||||
*
|
||||
* This is normally called from a driver's probe function
|
||||
*/
|
||||
void devm_can_led_init(struct net_device *netdev)
|
||||
{
|
||||
struct can_priv *priv = netdev_priv(netdev);
|
||||
void *res;
|
||||
|
||||
res = devres_alloc(can_led_release, 0, GFP_KERNEL);
|
||||
if (!res) {
|
||||
netdev_err(netdev, "cannot register LED triggers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(priv->tx_led_trig_name, sizeof(priv->tx_led_trig_name),
|
||||
"%s-tx", netdev->name);
|
||||
snprintf(priv->rx_led_trig_name, sizeof(priv->rx_led_trig_name),
|
||||
"%s-rx", netdev->name);
|
||||
|
||||
led_trigger_register_simple(priv->tx_led_trig_name,
|
||||
&priv->tx_led_trig);
|
||||
led_trigger_register_simple(priv->rx_led_trig_name,
|
||||
&priv->rx_led_trig);
|
||||
|
||||
devres_add(&netdev->dev, res);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_can_led_init);
|
||||
|
||||
/* NETDEV rename notifier to rename the associated led triggers too */
|
||||
static int can_led_notifier(struct notifier_block *nb, unsigned long msg,
|
||||
void *data)
|
||||
{
|
||||
struct net_device *netdev = data;
|
||||
struct can_priv *priv = safe_candev_priv(netdev);
|
||||
char name[CAN_LED_NAME_SZ];
|
||||
|
||||
if (!priv)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
if (msg == NETDEV_CHANGENAME) {
|
||||
snprintf(name, sizeof(name), "%s-tx", netdev->name);
|
||||
led_trigger_rename_static(name, priv->tx_led_trig);
|
||||
|
||||
snprintf(name, sizeof(name), "%s-rx", netdev->name);
|
||||
led_trigger_rename_static(name, priv->rx_led_trig);
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
/* notifier block for netdevice event */
|
||||
static struct notifier_block can_netdev_notifier __read_mostly = {
|
||||
.notifier_call = can_led_notifier,
|
||||
};
|
||||
|
||||
int __init can_led_notifier_init(void)
|
||||
{
|
||||
return register_netdevice_notifier(&can_netdev_notifier);
|
||||
}
|
||||
|
||||
void __exit can_led_notifier_exit(void)
|
||||
{
|
||||
unregister_netdevice_notifier(&can_netdev_notifier);
|
||||
}
|
|
@ -60,6 +60,7 @@
|
|||
|
||||
#include <linux/can/core.h>
|
||||
#include <linux/can/dev.h>
|
||||
#include <linux/can/led.h>
|
||||
#include <linux/can/platform/mcp251x.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/delay.h>
|
||||
|
@ -494,6 +495,9 @@ static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx)
|
|||
|
||||
priv->net->stats.rx_packets++;
|
||||
priv->net->stats.rx_bytes += frame->can_dlc;
|
||||
|
||||
can_led_event(priv->net, CAN_LED_EVENT_RX);
|
||||
|
||||
netif_rx_ni(skb);
|
||||
}
|
||||
|
||||
|
@ -707,6 +711,8 @@ static int mcp251x_stop(struct net_device *net)
|
|||
|
||||
mutex_unlock(&priv->mcp_lock);
|
||||
|
||||
can_led_event(net, CAN_LED_EVENT_STOP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -905,6 +911,7 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
|
|||
if (intf & CANINTF_TX) {
|
||||
net->stats.tx_packets++;
|
||||
net->stats.tx_bytes += priv->tx_len - 1;
|
||||
can_led_event(net, CAN_LED_EVENT_TX);
|
||||
if (priv->tx_len) {
|
||||
can_get_echo_skb(net, 0);
|
||||
priv->tx_len = 0;
|
||||
|
@ -968,6 +975,9 @@ static int mcp251x_open(struct net_device *net)
|
|||
mcp251x_open_clean(net);
|
||||
goto open_unlock;
|
||||
}
|
||||
|
||||
can_led_event(net, CAN_LED_EVENT_OPEN);
|
||||
|
||||
netif_wake_queue(net);
|
||||
|
||||
open_unlock:
|
||||
|
@ -1077,10 +1087,15 @@ static int mcp251x_can_probe(struct spi_device *spi)
|
|||
pdata->transceiver_enable(0);
|
||||
|
||||
ret = register_candev(net);
|
||||
if (!ret) {
|
||||
dev_info(&spi->dev, "probed\n");
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
goto error_probe;
|
||||
|
||||
devm_can_led_init(net);
|
||||
|
||||
dev_info(&spi->dev, "probed\n");
|
||||
|
||||
return ret;
|
||||
|
||||
error_probe:
|
||||
if (!mcp251x_enable_dma)
|
||||
kfree(priv->spi_rx_buf);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
config CAN_MSCAN
|
||||
depends on CAN_DEV && (PPC || M68K)
|
||||
depends on PPC || M68K
|
||||
tristate "Support for Freescale MSCAN based chips"
|
||||
---help---
|
||||
The Motorola Scalable Controller Area Network (MSCAN) definition
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
menuconfig CAN_SJA1000
|
||||
tristate "Philips/NXP SJA1000 devices"
|
||||
depends on CAN_DEV && HAS_IOMEM
|
||||
depends on HAS_IOMEM
|
||||
|
||||
if CAN_SJA1000
|
||||
|
||||
|
@ -99,11 +99,11 @@ config CAN_TSCAN1
|
|||
tristate "TS-CAN1 PC104 boards"
|
||||
depends on ISA
|
||||
help
|
||||
This driver is for Technologic Systems' TSCAN-1 PC104 boards.
|
||||
http://www.embeddedarm.com/products/board-detail.php?product=TS-CAN1
|
||||
The driver supports multiple boards and automatically configures them:
|
||||
PLD IO base addresses are read from jumpers JP1 and JP2,
|
||||
IRQ numbers are read from jumpers JP4 and JP5,
|
||||
SJA1000 IO base addresses are chosen heuristically (first that works).
|
||||
This driver is for Technologic Systems' TSCAN-1 PC104 boards.
|
||||
http://www.embeddedarm.com/products/board-detail.php?product=TS-CAN1
|
||||
The driver supports multiple boards and automatically configures them:
|
||||
PLD IO base addresses are read from jumpers JP1 and JP2,
|
||||
IRQ numbers are read from jumpers JP4 and JP5,
|
||||
SJA1000 IO base addresses are chosen heuristically (first that works).
|
||||
|
||||
endif
|
||||
|
|
|
@ -238,7 +238,6 @@ static int ems_pci_add_card(struct pci_dev *pdev,
|
|||
/* Allocating card structures to hold addresses, ... */
|
||||
card = kzalloc(sizeof(struct ems_pci_card), GFP_KERNEL);
|
||||
if (card == NULL) {
|
||||
dev_err(&pdev->dev, "Unable to allocate memory\n");
|
||||
pci_disable_device(pdev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
|
|
@ -450,11 +450,8 @@ static int peak_pciec_probe(struct pci_dev *pdev, struct net_device *dev)
|
|||
} else {
|
||||
/* create the bit banging I2C adapter structure */
|
||||
card = kzalloc(sizeof(struct peak_pciec_card), GFP_KERNEL);
|
||||
if (!card) {
|
||||
dev_err(&pdev->dev,
|
||||
"failed allocating memory for i2c chip\n");
|
||||
if (!card)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
card->cfg_base = chan->cfg_base;
|
||||
card->reg_base = priv->reg_base;
|
||||
|
|
|
@ -660,7 +660,6 @@ static int pcan_probe(struct pcmcia_device *pdev)
|
|||
|
||||
card = kzalloc(sizeof(struct pcan_pccard), GFP_KERNEL);
|
||||
if (!card) {
|
||||
dev_err(&pdev->dev, "couldn't allocate card memory\n");
|
||||
err = -ENOMEM;
|
||||
goto probe_err_2;
|
||||
}
|
||||
|
|
|
@ -508,7 +508,6 @@ static int plx_pci_add_card(struct pci_dev *pdev,
|
|||
/* Allocate card structures to hold addresses, ... */
|
||||
card = kzalloc(sizeof(*card), GFP_KERNEL);
|
||||
if (!card) {
|
||||
dev_err(&pdev->dev, "Unable to allocate memory\n");
|
||||
pci_disable_device(pdev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
|
||||
#include <linux/can/dev.h>
|
||||
#include <linux/can/error.h>
|
||||
#include <linux/can/led.h>
|
||||
|
||||
#include "sja1000.h"
|
||||
|
||||
|
@ -368,6 +369,8 @@ static void sja1000_rx(struct net_device *dev)
|
|||
|
||||
stats->rx_packets++;
|
||||
stats->rx_bytes += cf->can_dlc;
|
||||
|
||||
can_led_event(dev, CAN_LED_EVENT_RX);
|
||||
}
|
||||
|
||||
static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
|
||||
|
@ -521,6 +524,7 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
|
|||
can_get_echo_skb(dev, 0);
|
||||
}
|
||||
netif_wake_queue(dev);
|
||||
can_led_event(dev, CAN_LED_EVENT_TX);
|
||||
}
|
||||
if (isrc & IRQ_RI) {
|
||||
/* receive interrupt */
|
||||
|
@ -575,6 +579,8 @@ static int sja1000_open(struct net_device *dev)
|
|||
/* init and start chi */
|
||||
sja1000_start(dev);
|
||||
|
||||
can_led_event(dev, CAN_LED_EVENT_OPEN);
|
||||
|
||||
netif_start_queue(dev);
|
||||
|
||||
return 0;
|
||||
|
@ -592,6 +598,8 @@ static int sja1000_close(struct net_device *dev)
|
|||
|
||||
close_candev(dev);
|
||||
|
||||
can_led_event(dev, CAN_LED_EVENT_STOP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -639,6 +647,8 @@ static const struct net_device_ops sja1000_netdev_ops = {
|
|||
|
||||
int register_sja1000dev(struct net_device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!sja1000_probe_chip(dev))
|
||||
return -ENODEV;
|
||||
|
||||
|
@ -648,7 +658,12 @@ int register_sja1000dev(struct net_device *dev)
|
|||
set_reset_mode(dev);
|
||||
chipset_init(dev);
|
||||
|
||||
return register_candev(dev);
|
||||
ret = register_candev(dev);
|
||||
|
||||
if (!ret)
|
||||
devm_can_led_init(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(register_sja1000dev);
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/can.h>
|
||||
#include <linux/can/skb.h>
|
||||
|
||||
static __initconst const char banner[] =
|
||||
KERN_INFO "slcan: serial line CAN interface driver\n";
|
||||
|
@ -184,7 +185,8 @@ static void slc_bump(struct slcan *sl)
|
|||
cf.data[i] |= tmp;
|
||||
}
|
||||
|
||||
skb = dev_alloc_skb(sizeof(struct can_frame));
|
||||
skb = dev_alloc_skb(sizeof(struct can_frame) +
|
||||
sizeof(struct can_skb_priv));
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
|
@ -192,6 +194,10 @@ static void slc_bump(struct slcan *sl)
|
|||
skb->protocol = htons(ETH_P_CAN);
|
||||
skb->pkt_type = PACKET_BROADCAST;
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
|
||||
can_skb_reserve(skb);
|
||||
can_skb_prv(skb)->ifindex = sl->dev->ifindex;
|
||||
|
||||
memcpy(skb_put(skb, sizeof(struct can_frame)),
|
||||
&cf, sizeof(struct can_frame));
|
||||
netif_rx_ni(skb);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
config CAN_SOFTING
|
||||
tristate "Softing Gmbh CAN generic support"
|
||||
depends on CAN_DEV && HAS_IOMEM
|
||||
depends on HAS_IOMEM
|
||||
---help---
|
||||
Support for CAN cards from Softing Gmbh & some cards
|
||||
from Vector Gmbh.
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
|
||||
#include <linux/can/dev.h>
|
||||
#include <linux/can/error.h>
|
||||
#include <linux/can/led.h>
|
||||
#include <linux/can/platform/ti_hecc.h>
|
||||
|
||||
#define DRV_NAME "ti_hecc"
|
||||
|
@ -593,6 +594,7 @@ static int ti_hecc_rx_pkt(struct ti_hecc_priv *priv, int mbxno)
|
|||
spin_unlock_irqrestore(&priv->mbx_lock, flags);
|
||||
|
||||
stats->rx_bytes += cf->can_dlc;
|
||||
can_led_event(priv->ndev, CAN_LED_EVENT_RX);
|
||||
netif_receive_skb(skb);
|
||||
stats->rx_packets++;
|
||||
|
||||
|
@ -796,6 +798,7 @@ static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id)
|
|||
stats->tx_bytes += hecc_read_mbx(priv, mbxno,
|
||||
HECC_CANMCF) & 0xF;
|
||||
stats->tx_packets++;
|
||||
can_led_event(ndev, CAN_LED_EVENT_TX);
|
||||
can_get_echo_skb(ndev, mbxno);
|
||||
--priv->tx_tail;
|
||||
}
|
||||
|
@ -851,6 +854,8 @@ static int ti_hecc_open(struct net_device *ndev)
|
|||
return err;
|
||||
}
|
||||
|
||||
can_led_event(ndev, CAN_LED_EVENT_OPEN);
|
||||
|
||||
ti_hecc_start(ndev);
|
||||
napi_enable(&priv->napi);
|
||||
netif_start_queue(ndev);
|
||||
|
@ -869,6 +874,8 @@ static int ti_hecc_close(struct net_device *ndev)
|
|||
close_candev(ndev);
|
||||
ti_hecc_transceiver_switch(priv, 0);
|
||||
|
||||
can_led_event(ndev, CAN_LED_EVENT_STOP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -961,6 +968,9 @@ static int ti_hecc_probe(struct platform_device *pdev)
|
|||
dev_err(&pdev->dev, "register_candev() failed\n");
|
||||
goto probe_exit_clk;
|
||||
}
|
||||
|
||||
devm_can_led_init(ndev);
|
||||
|
||||
dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%u)\n",
|
||||
priv->base, (u32) ndev->irq);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
menu "CAN USB interfaces"
|
||||
depends on USB && CAN_DEV
|
||||
depends on USB
|
||||
|
||||
config CAN_EMS_USB
|
||||
tristate "EMS CPC-USB/ARM7 CAN/USB interface"
|
||||
|
@ -48,4 +48,10 @@ config CAN_PEAK_USB
|
|||
This driver supports the PCAN-USB and PCAN-USB Pro adapters
|
||||
from PEAK-System Technik (http://www.peak-system.com).
|
||||
|
||||
config CAN_8DEV_USB
|
||||
tristate "8 devices USB2CAN interface"
|
||||
---help---
|
||||
This driver supports the USB2CAN interface
|
||||
from 8 devices (http://www.8devices.com).
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -6,5 +6,6 @@ obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o
|
|||
obj-$(CONFIG_CAN_ESD_USB2) += esd_usb2.o
|
||||
obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb.o
|
||||
obj-$(CONFIG_CAN_PEAK_USB) += peak_usb/
|
||||
obj-$(CONFIG_CAN_8DEV_USB) += usb_8dev.o
|
||||
|
||||
ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
|
||||
|
|
|
@ -1014,17 +1014,13 @@ static int ems_usb_probe(struct usb_interface *intf,
|
|||
}
|
||||
|
||||
dev->intr_in_buffer = kzalloc(INTR_IN_BUFFER_SIZE, GFP_KERNEL);
|
||||
if (!dev->intr_in_buffer) {
|
||||
dev_err(&intf->dev, "Couldn't alloc Intr buffer\n");
|
||||
if (!dev->intr_in_buffer)
|
||||
goto cleanup_intr_urb;
|
||||
}
|
||||
|
||||
dev->tx_msg_buffer = kzalloc(CPC_HEADER_SIZE +
|
||||
sizeof(struct ems_cpc_msg), GFP_KERNEL);
|
||||
if (!dev->tx_msg_buffer) {
|
||||
dev_err(&intf->dev, "Couldn't alloc Tx buffer\n");
|
||||
if (!dev->tx_msg_buffer)
|
||||
goto cleanup_intr_in_buffer;
|
||||
}
|
||||
|
||||
usb_set_intfdata(intf, dev);
|
||||
|
||||
|
|
|
@ -561,7 +561,6 @@ static int kvaser_usb_simple_msg_async(struct kvaser_usb_net_priv *priv,
|
|||
|
||||
buf = kmalloc(sizeof(struct kvaser_msg), GFP_ATOMIC);
|
||||
if (!buf) {
|
||||
netdev_err(netdev, "No memory left for USB buffer\n");
|
||||
usb_free_urb(urb);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -1268,7 +1267,6 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
|
|||
|
||||
buf = kmalloc(sizeof(struct kvaser_msg), GFP_ATOMIC);
|
||||
if (!buf) {
|
||||
netdev_err(netdev, "No memory left for USB buffer\n");
|
||||
stats->tx_dropped++;
|
||||
goto nobufmem;
|
||||
}
|
||||
|
|
|
@ -386,7 +386,6 @@ static int peak_usb_start(struct peak_usb_device *dev)
|
|||
|
||||
buf = kmalloc(dev->adapter->rx_buffer_size, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
netdev_err(netdev, "No memory left for USB buffer\n");
|
||||
usb_free_urb(urb);
|
||||
err = -ENOMEM;
|
||||
break;
|
||||
|
@ -442,7 +441,6 @@ static int peak_usb_start(struct peak_usb_device *dev)
|
|||
|
||||
buf = kmalloc(dev->adapter->tx_buffer_size, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
netdev_err(netdev, "No memory left for USB buffer\n");
|
||||
usb_free_urb(urb);
|
||||
err = -ENOMEM;
|
||||
break;
|
||||
|
@ -634,7 +632,6 @@ static int peak_usb_restart(struct peak_usb_device *dev)
|
|||
/* also allocate enough space for the commands to send */
|
||||
buf = kmalloc(PCAN_USB_MAX_CMD_LEN, GFP_ATOMIC);
|
||||
if (!buf) {
|
||||
netdev_err(dev->netdev, "no memory left for async cmd\n");
|
||||
usb_free_urb(urb);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -729,8 +726,6 @@ static int peak_usb_create_dev(struct peak_usb_adapter *peak_usb_adapter,
|
|||
/* allocate a buffer large enough to send commands */
|
||||
dev->cmd_buf = kmalloc(PCAN_USB_MAX_CMD_LEN, GFP_KERNEL);
|
||||
if (!dev->cmd_buf) {
|
||||
dev_err(&intf->dev, "%s: couldn't alloc cmd buffer\n",
|
||||
PCAN_USB_DRIVER_NAME);
|
||||
err = -ENOMEM;
|
||||
goto lbl_set_intf_data;
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче