Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking changes from David Miller: 1) Get rid of the error prone NLA_PUT*() macros that used an embedded goto. 2) Kill off the token-ring and MCA networking drivers, from Paul Gortmaker. 3) Reduce high-order allocations made by datagram AF_UNIX sockets, from Eric Dumazet. 4) Add PTP hardware clock support to IGB and IXGBE, from Richard Cochran and Jacob Keller. 5) Allow users to query timestamping capabilities of a card via ethtool, from Richard Cochran. 6) Add loadbalance mode to the teaming driver, from Jiri Pirko. Part of this is that we can now have BPF filters not attached to sockets, and the loadbalancing function is calculated using one. 7) Francois Romieu went through the network drivers removing gratuitous uses of netdev->base_addr, perhaps some day we can remove it completely but it's used for ISA probing still. 8) Add a BPF JIT for sparc. I know, who cares, right? :-) 9) Move networking sysctl registry away from using the compatability mode interfaces in the sysctl code. From Eric W Biederman. 10) Pavel Emelyanov added a way to save and restore TCP socket state via TCP_REPAIR, TCP_REPAIR_QUEUE, and TCP_QUEUE_SEQ socket options as well as a way to forcefully bind a socket to a port via the sk->sk_reuse value SK_FORCE_REUSE. There is also a TCP_REPAIR_OPTIONS which allows to reinstante the TCP options enabled on the connection. 11) Several enhancements from Eric Dumazet that, in particular, can enhance splice performance on TCP sockets significantly. a) Reset the offset of the per-socket sendmsg page when we know we're the only use of the page in linear_to_page(). b) Add facilities such that skb->data can be backed a page rather than SLAB kmalloc'd memory. In particular devices which were receiving into linear RX buffers can now end up providing paged data. The big result is that code like splice and GRO do not have to copy any more. 12) Allow a pure sender to more gracefully handle ACK backlogs in TCP. What can happen at high rates is that the sender hasn't grown his receive buffer limits at all (he's not receiving data so really doesn't need to), but the non-data ACKs consume receive buffer space. sk_add_backlog() is too aggressive in dropping frames in this case, so relax it's requirements by using the receive buffer plus the send buffer limit as the backlog limit instead of just the former. Also from Eric Dumazet. 13) Add ipv6 support to L2TP, from Benjamin LaHaise, James Chapman, and Chris Elston. 14) Implement TCP early retransmit (RFC 5827), from Yuchung Cheng. Basically, we can start fast retransmit before hiting the dupack threshold under certain conditions. 15) New CODEL active queue management packet scheduler, from Eric Dumazet based upon initial work by Dave Taht. Basically, the big feature is that packets are dropped (or ECN bits are set) based upon how long packets live in the queue, rather than the queue length (which is what RED uses). * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1341 commits) drivers/net/stmmac: seq_file fix memory leak ipv6/exthdrs: strict Pad1 and PadN check USB: qmi_wwan: Add ZTE (Vodafone) K3520-Z USB: qmi_wwan: Add ZTE (Vodafone) K3765-Z USB: qmi_wwan: Make forced int 4 whitelist generic net/ipv4: replace simple_strtoul with kstrtoul net/ipv4/ipconfig: neaten __setup placement net: qmi_wwan: Add Vodafone/Huawei K5005 support net: cdc_ether: Add ZTE WWAN matches before generic Ethernet ipv6: use skb coalescing in reassembly ipv4: use skb coalescing in defragmentation net: introduce skb_try_coalesce() net:ipv6:fixed space issues relating to operators. net:ipv6:fixed a trailing white space issue. ipv6: disable GSO on sockets hitting dst_allfrag tg3: use netdev_alloc_frag() API net: napi_frags_skb() is static ppp: avoid false drop_monitor false positives ipv6: bool/const conversions phase2 ipx: Remove spurious NULL checking in ipx_ioctl(). ...
This commit is contained in:
commit
cb62ab71fe
9
Documentation/ABI/removed/ip_queue
Normal file
9
Documentation/ABI/removed/ip_queue
Normal file
|
@ -0,0 +1,9 @@
|
|||
What: ip_queue
|
||||
Date: finally removed in kernel v3.5.0
|
||||
Contact: Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
Description:
|
||||
ip_queue has been replaced by nfnetlink_queue which provides
|
||||
more advanced queueing mechanism to user-space. The ip_queue
|
||||
module was already announced to become obsolete years ago.
|
||||
|
||||
Users:
|
|
@ -14,6 +14,15 @@ Description:
|
|||
mesh will be sent using multiple interfaces at the
|
||||
same time (if available).
|
||||
|
||||
What: /sys/class/net/<mesh_iface>/mesh/bridge_loop_avoidance
|
||||
Date: November 2011
|
||||
Contact: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
|
||||
Description:
|
||||
Indicates whether the bridge loop avoidance feature
|
||||
is enabled. This feature detects and avoids loops
|
||||
between the mesh and devices bridged with the soft
|
||||
interface <mesh_iface>.
|
||||
|
||||
What: /sys/class/net/<mesh_iface>/mesh/fragmentation
|
||||
Date: October 2010
|
||||
Contact: Andreas Langer <an.langer@gmx.de>
|
||||
|
|
|
@ -516,7 +516,7 @@
|
|||
!Finclude/net/mac80211.h ieee80211_start_tx_ba_cb_irqsafe
|
||||
!Finclude/net/mac80211.h ieee80211_stop_tx_ba_session
|
||||
!Finclude/net/mac80211.h ieee80211_stop_tx_ba_cb_irqsafe
|
||||
!Finclude/net/mac80211.h rate_control_changed
|
||||
!Finclude/net/mac80211.h ieee80211_rate_control_changed
|
||||
!Finclude/net/mac80211.h ieee80211_tx_rate_control
|
||||
!Finclude/net/mac80211.h rate_control_send_low
|
||||
</chapter>
|
||||
|
|
127
Documentation/devicetree/bindings/net/mdio-mux-gpio.txt
Normal file
127
Documentation/devicetree/bindings/net/mdio-mux-gpio.txt
Normal file
|
@ -0,0 +1,127 @@
|
|||
Properties for an MDIO bus multiplexer/switch controlled by GPIO pins.
|
||||
|
||||
This is a special case of a MDIO bus multiplexer. One or more GPIO
|
||||
lines are used to control which child bus is connected.
|
||||
|
||||
Required properties in addition to the generic multiplexer properties:
|
||||
|
||||
- compatible : mdio-mux-gpio.
|
||||
- gpios : GPIO specifiers for each GPIO line. One or more must be specified.
|
||||
|
||||
|
||||
Example :
|
||||
|
||||
/* The parent MDIO bus. */
|
||||
smi1: mdio@1180000001900 {
|
||||
compatible = "cavium,octeon-3860-mdio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x11800 0x00001900 0x0 0x40>;
|
||||
};
|
||||
|
||||
/*
|
||||
An NXP sn74cbtlv3253 dual 1-of-4 switch controlled by a
|
||||
pair of GPIO lines. Child busses 2 and 3 populated with 4
|
||||
PHYs each.
|
||||
*/
|
||||
mdio-mux {
|
||||
compatible = "mdio-mux-gpio";
|
||||
gpios = <&gpio1 3 0>, <&gpio1 4 0>;
|
||||
mdio-parent-bus = <&smi1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
mdio@2 {
|
||||
reg = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
phy11: ethernet-phy@1 {
|
||||
reg = <1>;
|
||||
compatible = "marvell,88e1149r";
|
||||
marvell,reg-init = <3 0x10 0 0x5777>,
|
||||
<3 0x11 0 0x00aa>,
|
||||
<3 0x12 0 0x4105>,
|
||||
<3 0x13 0 0x0a60>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <10 8>; /* Pin 10, active low */
|
||||
};
|
||||
phy12: ethernet-phy@2 {
|
||||
reg = <2>;
|
||||
compatible = "marvell,88e1149r";
|
||||
marvell,reg-init = <3 0x10 0 0x5777>,
|
||||
<3 0x11 0 0x00aa>,
|
||||
<3 0x12 0 0x4105>,
|
||||
<3 0x13 0 0x0a60>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <10 8>; /* Pin 10, active low */
|
||||
};
|
||||
phy13: ethernet-phy@3 {
|
||||
reg = <3>;
|
||||
compatible = "marvell,88e1149r";
|
||||
marvell,reg-init = <3 0x10 0 0x5777>,
|
||||
<3 0x11 0 0x00aa>,
|
||||
<3 0x12 0 0x4105>,
|
||||
<3 0x13 0 0x0a60>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <10 8>; /* Pin 10, active low */
|
||||
};
|
||||
phy14: ethernet-phy@4 {
|
||||
reg = <4>;
|
||||
compatible = "marvell,88e1149r";
|
||||
marvell,reg-init = <3 0x10 0 0x5777>,
|
||||
<3 0x11 0 0x00aa>,
|
||||
<3 0x12 0 0x4105>,
|
||||
<3 0x13 0 0x0a60>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <10 8>; /* Pin 10, active low */
|
||||
};
|
||||
};
|
||||
|
||||
mdio@3 {
|
||||
reg = <3>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
phy21: ethernet-phy@1 {
|
||||
reg = <1>;
|
||||
compatible = "marvell,88e1149r";
|
||||
marvell,reg-init = <3 0x10 0 0x5777>,
|
||||
<3 0x11 0 0x00aa>,
|
||||
<3 0x12 0 0x4105>,
|
||||
<3 0x13 0 0x0a60>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <12 8>; /* Pin 12, active low */
|
||||
};
|
||||
phy22: ethernet-phy@2 {
|
||||
reg = <2>;
|
||||
compatible = "marvell,88e1149r";
|
||||
marvell,reg-init = <3 0x10 0 0x5777>,
|
||||
<3 0x11 0 0x00aa>,
|
||||
<3 0x12 0 0x4105>,
|
||||
<3 0x13 0 0x0a60>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <12 8>; /* Pin 12, active low */
|
||||
};
|
||||
phy23: ethernet-phy@3 {
|
||||
reg = <3>;
|
||||
compatible = "marvell,88e1149r";
|
||||
marvell,reg-init = <3 0x10 0 0x5777>,
|
||||
<3 0x11 0 0x00aa>,
|
||||
<3 0x12 0 0x4105>,
|
||||
<3 0x13 0 0x0a60>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <12 8>; /* Pin 12, active low */
|
||||
};
|
||||
phy24: ethernet-phy@4 {
|
||||
reg = <4>;
|
||||
compatible = "marvell,88e1149r";
|
||||
marvell,reg-init = <3 0x10 0 0x5777>,
|
||||
<3 0x11 0 0x00aa>,
|
||||
<3 0x12 0 0x4105>,
|
||||
<3 0x13 0 0x0a60>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <12 8>; /* Pin 12, active low */
|
||||
};
|
||||
};
|
||||
};
|
136
Documentation/devicetree/bindings/net/mdio-mux.txt
Normal file
136
Documentation/devicetree/bindings/net/mdio-mux.txt
Normal file
|
@ -0,0 +1,136 @@
|
|||
Common MDIO bus multiplexer/switch properties.
|
||||
|
||||
An MDIO bus multiplexer/switch will have several child busses that are
|
||||
numbered uniquely in a device dependent manner. The nodes for an MDIO
|
||||
bus multiplexer/switch will have one child node for each child bus.
|
||||
|
||||
Required properties:
|
||||
- mdio-parent-bus : phandle to the parent MDIO bus.
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <0>;
|
||||
|
||||
Optional properties:
|
||||
- Other properties specific to the multiplexer/switch hardware.
|
||||
|
||||
Required properties for child nodes:
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <0>;
|
||||
- reg : The sub-bus number.
|
||||
|
||||
|
||||
Example :
|
||||
|
||||
/* The parent MDIO bus. */
|
||||
smi1: mdio@1180000001900 {
|
||||
compatible = "cavium,octeon-3860-mdio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x11800 0x00001900 0x0 0x40>;
|
||||
};
|
||||
|
||||
/*
|
||||
An NXP sn74cbtlv3253 dual 1-of-4 switch controlled by a
|
||||
pair of GPIO lines. Child busses 2 and 3 populated with 4
|
||||
PHYs each.
|
||||
*/
|
||||
mdio-mux {
|
||||
compatible = "mdio-mux-gpio";
|
||||
gpios = <&gpio1 3 0>, <&gpio1 4 0>;
|
||||
mdio-parent-bus = <&smi1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
mdio@2 {
|
||||
reg = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
phy11: ethernet-phy@1 {
|
||||
reg = <1>;
|
||||
compatible = "marvell,88e1149r";
|
||||
marvell,reg-init = <3 0x10 0 0x5777>,
|
||||
<3 0x11 0 0x00aa>,
|
||||
<3 0x12 0 0x4105>,
|
||||
<3 0x13 0 0x0a60>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <10 8>; /* Pin 10, active low */
|
||||
};
|
||||
phy12: ethernet-phy@2 {
|
||||
reg = <2>;
|
||||
compatible = "marvell,88e1149r";
|
||||
marvell,reg-init = <3 0x10 0 0x5777>,
|
||||
<3 0x11 0 0x00aa>,
|
||||
<3 0x12 0 0x4105>,
|
||||
<3 0x13 0 0x0a60>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <10 8>; /* Pin 10, active low */
|
||||
};
|
||||
phy13: ethernet-phy@3 {
|
||||
reg = <3>;
|
||||
compatible = "marvell,88e1149r";
|
||||
marvell,reg-init = <3 0x10 0 0x5777>,
|
||||
<3 0x11 0 0x00aa>,
|
||||
<3 0x12 0 0x4105>,
|
||||
<3 0x13 0 0x0a60>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <10 8>; /* Pin 10, active low */
|
||||
};
|
||||
phy14: ethernet-phy@4 {
|
||||
reg = <4>;
|
||||
compatible = "marvell,88e1149r";
|
||||
marvell,reg-init = <3 0x10 0 0x5777>,
|
||||
<3 0x11 0 0x00aa>,
|
||||
<3 0x12 0 0x4105>,
|
||||
<3 0x13 0 0x0a60>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <10 8>; /* Pin 10, active low */
|
||||
};
|
||||
};
|
||||
|
||||
mdio@3 {
|
||||
reg = <3>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
phy21: ethernet-phy@1 {
|
||||
reg = <1>;
|
||||
compatible = "marvell,88e1149r";
|
||||
marvell,reg-init = <3 0x10 0 0x5777>,
|
||||
<3 0x11 0 0x00aa>,
|
||||
<3 0x12 0 0x4105>,
|
||||
<3 0x13 0 0x0a60>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <12 8>; /* Pin 12, active low */
|
||||
};
|
||||
phy22: ethernet-phy@2 {
|
||||
reg = <2>;
|
||||
compatible = "marvell,88e1149r";
|
||||
marvell,reg-init = <3 0x10 0 0x5777>,
|
||||
<3 0x11 0 0x00aa>,
|
||||
<3 0x12 0 0x4105>,
|
||||
<3 0x13 0 0x0a60>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <12 8>; /* Pin 12, active low */
|
||||
};
|
||||
phy23: ethernet-phy@3 {
|
||||
reg = <3>;
|
||||
compatible = "marvell,88e1149r";
|
||||
marvell,reg-init = <3 0x10 0 0x5777>,
|
||||
<3 0x11 0 0x00aa>,
|
||||
<3 0x12 0 0x4105>,
|
||||
<3 0x13 0 0x0a60>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <12 8>; /* Pin 12, active low */
|
||||
};
|
||||
phy24: ethernet-phy@4 {
|
||||
reg = <4>;
|
||||
compatible = "marvell,88e1149r";
|
||||
marvell,reg-init = <3 0x10 0 0x5777>,
|
||||
<3 0x11 0 0x00aa>,
|
||||
<3 0x12 0 0x4105>,
|
||||
<3 0x13 0 0x0a60>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <12 8>; /* Pin 12, active low */
|
||||
};
|
||||
};
|
||||
};
|
|
@ -996,7 +996,6 @@ Table 1-9: Network info in /proc/net
|
|||
snmp SNMP data
|
||||
sockstat Socket statistics
|
||||
tcp TCP sockets
|
||||
tr_rif Token ring RIF routing table
|
||||
udp UDP sockets
|
||||
unix UNIX domain sockets
|
||||
wireless Wireless interface data (Wavelan etc)
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
00-INDEX
|
||||
- this file
|
||||
3c359.txt
|
||||
- information on the 3Com TokenLink Velocity XL (3c5359) driver.
|
||||
3c505.txt
|
||||
- information on the 3Com EtherLink Plus (3c505) driver.
|
||||
3c509.txt
|
||||
|
@ -142,8 +140,6 @@ netif-msg.txt
|
|||
- Design of the network interface message level setting (NETIF_MSG_*).
|
||||
nfc.txt
|
||||
- The Linux Near Field Communication (NFS) subsystem.
|
||||
olympic.txt
|
||||
- IBM PCI Pit/Pit-Phy/Olympic Token Ring driver info.
|
||||
openvswitch.txt
|
||||
- Open vSwitch developer documentation.
|
||||
operstates.txt
|
||||
|
@ -184,8 +180,6 @@ skfp.txt
|
|||
- SysKonnect FDDI (SK-5xxx, Compaq Netelligent) driver info.
|
||||
smc9.txt
|
||||
- the driver for SMC's 9000 series of Ethernet cards
|
||||
smctr.txt
|
||||
- SMC TokenCard TokenRing Linux driver info.
|
||||
spider-net.txt
|
||||
- README for the Spidernet Driver (as found in PS3 / Cell BE).
|
||||
stmmac.txt
|
||||
|
@ -200,8 +194,6 @@ tcp-thin.txt
|
|||
- kernel tuning options for low rate 'thin' TCP streams.
|
||||
tlan.txt
|
||||
- ThunderLAN (Compaq Netelligent 10/100, Olicom OC-2xxx) driver info.
|
||||
tms380tr.txt
|
||||
- SysKonnect Token Ring ISA/PCI adapter driver info.
|
||||
tproxy.txt
|
||||
- Transparent proxy support user guide.
|
||||
tuntap.txt
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
|
||||
3COM PCI TOKEN LINK VELOCITY XL TOKEN RING CARDS README
|
||||
|
||||
Release 0.9.0 - Release
|
||||
Jul 17th 2000 Mike Phillips
|
||||
|
||||
1.2.0 - Final
|
||||
Feb 17th 2002 Mike Phillips
|
||||
Updated for submission to the 2.4.x kernel.
|
||||
|
||||
Thanks:
|
||||
Terry Murphy from 3Com for tech docs and support,
|
||||
Adam D. Ligas for testing the driver.
|
||||
|
||||
Note:
|
||||
This driver will NOT work with the 3C339 Token Ring cards, you need
|
||||
to use the tms380 driver instead.
|
||||
|
||||
Options:
|
||||
|
||||
The driver accepts three options: ringspeed, pkt_buf_sz and message_level.
|
||||
|
||||
These options can be specified differently for each card found.
|
||||
|
||||
ringspeed: Has one of three settings 0 (default), 4 or 16. 0 will
|
||||
make the card autosense the ringspeed and join at the appropriate speed,
|
||||
this will be the default option for most people. 4 or 16 allow you to
|
||||
explicitly force the card to operate at a certain speed. The card will fail
|
||||
if you try to insert it at the wrong speed. (Although some hubs will allow
|
||||
this so be *very* careful). The main purpose for explicitly setting the ring
|
||||
speed is for when the card is first on the ring. In autosense mode, if the card
|
||||
cannot detect any active monitors on the ring it will open at the same speed as
|
||||
its last opening. This can be hazardous if this speed does not match the speed
|
||||
you want the ring to operate at.
|
||||
|
||||
pkt_buf_sz: This is this initial receive buffer allocation size. This will
|
||||
default to 4096 if no value is entered. You may increase performance of the
|
||||
driver by setting this to a value larger than the network packet size, although
|
||||
the driver now re-sizes buffers based on MTU settings as well.
|
||||
|
||||
message_level: Controls level of messages created by the driver. Defaults to 0:
|
||||
which only displays start-up and critical messages. Presently any non-zero
|
||||
value will display all soft messages as well. NB This does not turn
|
||||
debugging messages on, that must be done by modified the source code.
|
||||
|
||||
Variable MTU size:
|
||||
|
||||
The driver can handle a MTU size up to either 4500 or 18000 depending upon
|
||||
ring speed. The driver also changes the size of the receive buffers as part
|
||||
of the mtu re-sizing, so if you set mtu = 18000, you will need to be able
|
||||
to allocate 16 * (sk_buff with 18000 buffer size) call it 18500 bytes per ring
|
||||
position = 296,000 bytes of memory space, plus of course anything
|
||||
necessary for the tx sk_buff's. Remember this is per card, so if you are
|
||||
building routers, gateway's etc, you could start to use a lot of memory
|
||||
real fast.
|
||||
|
||||
2/17/02 Mike Phillips
|
||||
|
|
@ -25,7 +25,6 @@ models:
|
|||
3c509B (later revision of the ISA card; supports full-duplex)
|
||||
3c589 (PCMCIA)
|
||||
3c589B (later revision of the 3c589; supports full-duplex)
|
||||
3c529 (MCA)
|
||||
3c579 (EISA)
|
||||
|
||||
Large portions of this documentation were heavily borrowed from the guide
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
[state: 21-08-2011]
|
||||
|
||||
BATMAN-ADV
|
||||
----------
|
||||
|
||||
|
@ -67,18 +65,19 @@ To deactivate an interface you have to write "none" into its
|
|||
All mesh wide settings can be found in batman's own interface
|
||||
folder:
|
||||
|
||||
# ls /sys/class/net/bat0/mesh/
|
||||
# aggregated_ogms fragmentation gw_sel_class vis_mode
|
||||
# ap_isolation gw_bandwidth hop_penalty
|
||||
# bonding gw_mode orig_interval
|
||||
# ls /sys/class/net/bat0/mesh/
|
||||
# aggregated_ogms gw_bandwidth log_level
|
||||
# ap_isolation gw_mode orig_interval
|
||||
# bonding gw_sel_class routing_algo
|
||||
# bridge_loop_avoidance hop_penalty vis_mode
|
||||
# fragmentation
|
||||
|
||||
|
||||
There is a special folder for debugging information:
|
||||
|
||||
# ls /sys/kernel/debug/batman_adv/bat0/
|
||||
# gateways socket transtable_global vis_data
|
||||
# originators softif_neigh transtable_local
|
||||
|
||||
# bla_claim_table log socket transtable_local
|
||||
# gateways originators transtable_global vis_data
|
||||
|
||||
Some of the files contain all sort of status information regard-
|
||||
ing the mesh network. For example, you can view the table of
|
||||
|
@ -202,12 +201,13 @@ abled during run time. Following log_levels are defined:
|
|||
1 - Enable messages related to routing / flooding / broadcasting
|
||||
2 - Enable messages related to route added / changed / deleted
|
||||
4 - Enable messages related to translation table operations
|
||||
7 - Enable all messages
|
||||
8 - Enable messages related to bridge loop avoidance
|
||||
15 - enable all messages
|
||||
|
||||
The debug output can be changed at runtime using the file
|
||||
/sys/class/net/bat0/mesh/log_level. e.g.
|
||||
|
||||
# echo 2 > /sys/class/net/bat0/mesh/log_level
|
||||
# echo 6 > /sys/class/net/bat0/mesh/log_level
|
||||
|
||||
will enable debug messages for when routes change.
|
||||
|
||||
|
|
|
@ -11,12 +11,10 @@ i386, alpha (untested), powerpc, sparc and sparc64 archs.
|
|||
|
||||
The intent is to enable the use of different models of FORE adapters at the
|
||||
same time, by hosts that have several bus interfaces (such as PCI+SBUS,
|
||||
PCI+MCA or PCI+EISA).
|
||||
or PCI+EISA).
|
||||
|
||||
Only PCI and SBUS devices are currently supported by the driver, but support
|
||||
for other bus interfaces such as EISA should not be too hard to add (this may
|
||||
be more tricky for the MCA bus, though, as FORE made some MCA-specific
|
||||
modifications to the adapter's AALI interface).
|
||||
for other bus interfaces such as EISA should not be too hard to add.
|
||||
|
||||
|
||||
Firmware Copyright Notice
|
||||
|
|
|
@ -4,15 +4,22 @@
|
|||
|
||||
Introduction
|
||||
============
|
||||
The IEEE 802.15.4 working group focuses on standartization of bottom
|
||||
two layers: Medium Accsess Control (MAC) and Physical (PHY). And there
|
||||
are mainly two options available for upper layers:
|
||||
- ZigBee - proprietary protocol from ZigBee Alliance
|
||||
- 6LowPAN - IPv6 networking over low rate personal area networks
|
||||
|
||||
The Linux-ZigBee project goal is to provide complete implementation
|
||||
of IEEE 802.15.4 / ZigBee / 6LoWPAN protocols. IEEE 802.15.4 is a stack
|
||||
of IEEE 802.15.4 and 6LoWPAN protocols. IEEE 802.15.4 is a stack
|
||||
of protocols for organizing Low-Rate Wireless Personal Area Networks.
|
||||
|
||||
Currently only IEEE 802.15.4 layer is implemented. We have chosen
|
||||
to use plain Berkeley socket API, the generic Linux networking stack
|
||||
to transfer IEEE 802.15.4 messages and a special protocol over genetlink
|
||||
for configuration/management
|
||||
The stack is composed of three main parts:
|
||||
- IEEE 802.15.4 layer; We have chosen to use plain Berkeley socket API,
|
||||
the generic Linux networking stack to transfer IEEE 802.15.4 messages
|
||||
and a special protocol over genetlink for configuration/management
|
||||
- MAC - provides access to shared channel and reliable data delivery
|
||||
- PHY - represents device drivers
|
||||
|
||||
|
||||
Socket API
|
||||
|
@ -29,15 +36,6 @@ or git tree at git://linux-zigbee.git.sourceforge.net/gitroot/linux-zigbee).
|
|||
One can use SOCK_RAW for passing raw data towards device xmit function. YMMV.
|
||||
|
||||
|
||||
MLME - MAC Level Management
|
||||
============================
|
||||
|
||||
Most of IEEE 802.15.4 MLME interfaces are directly mapped on netlink commands.
|
||||
See the include/net/nl802154.h header. Our userspace tools package
|
||||
(see above) provides CLI configuration utility for radio interfaces and simple
|
||||
coordinator for IEEE 802.15.4 networks as an example users of MLME protocol.
|
||||
|
||||
|
||||
Kernel side
|
||||
=============
|
||||
|
||||
|
@ -51,6 +49,15 @@ Like with WiFi, there are several types of devices implementing IEEE 802.15.4.
|
|||
Those types of devices require different approach to be hooked into Linux kernel.
|
||||
|
||||
|
||||
MLME - MAC Level Management
|
||||
============================
|
||||
|
||||
Most of IEEE 802.15.4 MLME interfaces are directly mapped on netlink commands.
|
||||
See the include/net/nl802154.h header. Our userspace tools package
|
||||
(see above) provides CLI configuration utility for radio interfaces and simple
|
||||
coordinator for IEEE 802.15.4 networks as an example users of MLME protocol.
|
||||
|
||||
|
||||
HardMAC
|
||||
=======
|
||||
|
||||
|
@ -73,11 +80,47 @@ We provide an example of simple HardMAC driver at drivers/ieee802154/fakehard.c
|
|||
SoftMAC
|
||||
=======
|
||||
|
||||
We are going to provide intermediate layer implementing IEEE 802.15.4 MAC
|
||||
in software. This is currently WIP.
|
||||
The MAC is the middle layer in the IEEE 802.15.4 Linux stack. This moment it
|
||||
provides interface for drivers registration and management of slave interfaces.
|
||||
|
||||
NOTE: Currently the only monitor device type is supported - it's IEEE 802.15.4
|
||||
stack interface for network sniffers (e.g. WireShark).
|
||||
|
||||
This layer is going to be extended soon.
|
||||
|
||||
See header include/net/mac802154.h and several drivers in drivers/ieee802154/.
|
||||
|
||||
|
||||
Device drivers API
|
||||
==================
|
||||
|
||||
The include/net/mac802154.h defines following functions:
|
||||
- struct ieee802154_dev *ieee802154_alloc_device
|
||||
(size_t priv_size, struct ieee802154_ops *ops):
|
||||
allocation of IEEE 802.15.4 compatible device
|
||||
|
||||
- void ieee802154_free_device(struct ieee802154_dev *dev):
|
||||
freeing allocated device
|
||||
|
||||
- int ieee802154_register_device(struct ieee802154_dev *dev):
|
||||
register PHY in the system
|
||||
|
||||
- void ieee802154_unregister_device(struct ieee802154_dev *dev):
|
||||
freeing registered PHY
|
||||
|
||||
Moreover IEEE 802.15.4 device operations structure should be filled.
|
||||
|
||||
Fake drivers
|
||||
============
|
||||
|
||||
In addition there are two drivers available which simulate real devices with
|
||||
HardMAC (fakehard) and SoftMAC (fakelb - IEEE 802.15.4 loopback driver)
|
||||
interfaces. This option provides possibility to test and debug stack without
|
||||
usage of real hardware.
|
||||
|
||||
See sources in drivers/ieee802154 folder for more details.
|
||||
|
||||
|
||||
6LoWPAN Linux implementation
|
||||
============================
|
||||
|
||||
|
|
|
@ -190,6 +190,20 @@ tcp_cookie_size - INTEGER
|
|||
tcp_dsack - BOOLEAN
|
||||
Allows TCP to send "duplicate" SACKs.
|
||||
|
||||
tcp_early_retrans - INTEGER
|
||||
Enable Early Retransmit (ER), per RFC 5827. ER lowers the threshold
|
||||
for triggering fast retransmit when the amount of outstanding data is
|
||||
small and when no previously unsent data can be transmitted (such
|
||||
that limited transmit could be used).
|
||||
Possible values:
|
||||
0 disables ER
|
||||
1 enables ER
|
||||
2 enables ER but delays fast recovery and fast retransmit
|
||||
by a fourth of RTT. This mitigates connection falsely
|
||||
recovers when network has a small degree of reordering
|
||||
(less than 3 packets).
|
||||
Default: 2
|
||||
|
||||
tcp_ecn - INTEGER
|
||||
Enable Explicit Congestion Notification (ECN) in TCP. ECN is only
|
||||
used when both ends of the TCP flow support it. It is useful to
|
||||
|
@ -1287,13 +1301,22 @@ bridge-nf-call-ip6tables - BOOLEAN
|
|||
bridge-nf-filter-vlan-tagged - BOOLEAN
|
||||
1 : pass bridged vlan-tagged ARP/IP/IPv6 traffic to {arp,ip,ip6}tables.
|
||||
0 : disable this.
|
||||
Default: 1
|
||||
Default: 0
|
||||
|
||||
bridge-nf-filter-pppoe-tagged - BOOLEAN
|
||||
1 : pass bridged pppoe-tagged IP/IPv6 traffic to {ip,ip6}tables.
|
||||
0 : disable this.
|
||||
Default: 1
|
||||
Default: 0
|
||||
|
||||
bridge-nf-pass-vlan-input-dev - BOOLEAN
|
||||
1: if bridge-nf-filter-vlan-tagged is enabled, try to find a vlan
|
||||
interface on the bridge and set the netfilter input device to the vlan.
|
||||
This allows use of e.g. "iptables -i br0.1" and makes the REDIRECT
|
||||
target work with vlan-on-top-of-bridge interfaces. When no matching
|
||||
vlan interface is found, or this switch is off, the input device is
|
||||
set to the bridge interface.
|
||||
0: disable bridge netfilter vlan interface lookup.
|
||||
Default: 0
|
||||
|
||||
proc/sys/net/sctp/* Variables:
|
||||
|
||||
|
@ -1484,11 +1507,8 @@ addr_scope_policy - INTEGER
|
|||
|
||||
|
||||
/proc/sys/net/core/*
|
||||
dev_weight - INTEGER
|
||||
The maximum number of packets that kernel can handle on a NAPI
|
||||
interrupt, it's a Per-CPU variable.
|
||||
Please see: Documentation/sysctl/net.txt for descriptions of these entries.
|
||||
|
||||
Default: 64
|
||||
|
||||
/proc/sys/net/unix/*
|
||||
max_dgram_qlen - INTEGER
|
||||
|
|
|
@ -23,7 +23,7 @@ BA session stop & deauth/disassoc frames
|
|||
end note
|
||||
end
|
||||
|
||||
mac80211->driver: config(channel, non-HT)
|
||||
mac80211->driver: config(channel, channel type)
|
||||
mac80211->driver: bss_info_changed(set BSSID, basic rate bitmap)
|
||||
mac80211->driver: sta_state(AP, exists)
|
||||
|
||||
|
@ -51,7 +51,7 @@ note over mac80211,driver: cleanup like for authenticate
|
|||
end
|
||||
|
||||
alt not previously authenticated (FT)
|
||||
mac80211->driver: config(channel, non-HT)
|
||||
mac80211->driver: config(channel, channel type)
|
||||
mac80211->driver: bss_info_changed(set BSSID, basic rate bitmap)
|
||||
mac80211->driver: sta_state(AP, exists)
|
||||
mac80211->driver: sta_state(AP, authenticated)
|
||||
|
@ -67,10 +67,6 @@ end
|
|||
|
||||
mac80211->driver: set up QoS parameters
|
||||
|
||||
alt is HT channel
|
||||
mac80211->driver: config(channel, HT params)
|
||||
end
|
||||
|
||||
mac80211->driver: bss_info_changed(QoS, HT, associated with AID)
|
||||
mac80211->userspace: associated
|
||||
|
||||
|
@ -95,5 +91,5 @@ mac80211->driver: sta_state(AP,exists)
|
|||
mac80211->driver: sta_state(AP,not-exists)
|
||||
mac80211->driver: turn off powersave
|
||||
mac80211->driver: bss_info_changed(clear BSSID, not associated, no QoS, ...)
|
||||
mac80211->driver: config(non-HT channel type)
|
||||
mac80211->driver: config(channel type to non-HT)
|
||||
mac80211->userspace: disconnected
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
|
||||
IBM PCI Pit/Pit-Phy/Olympic CHIPSET BASED TOKEN RING CARDS README
|
||||
|
||||
Release 0.2.0 - Release
|
||||
June 8th 1999 Peter De Schrijver & Mike Phillips
|
||||
Release 0.9.C - Release
|
||||
April 18th 2001 Mike Phillips
|
||||
|
||||
Thanks:
|
||||
Erik De Cock, Adrian Bridgett and Frank Fiene for their
|
||||
patience and testing.
|
||||
Donald Champion for the cardbus support
|
||||
Kyle Lucke for the dma api changes.
|
||||
Jonathon Bitner for hardware support.
|
||||
Everybody on linux-tr for their continued support.
|
||||
|
||||
Options:
|
||||
|
||||
The driver accepts four options: ringspeed, pkt_buf_sz,
|
||||
message_level and network_monitor.
|
||||
|
||||
These options can be specified differently for each card found.
|
||||
|
||||
ringspeed: Has one of three settings 0 (default), 4 or 16. 0 will
|
||||
make the card autosense the ringspeed and join at the appropriate speed,
|
||||
this will be the default option for most people. 4 or 16 allow you to
|
||||
explicitly force the card to operate at a certain speed. The card will fail
|
||||
if you try to insert it at the wrong speed. (Although some hubs will allow
|
||||
this so be *very* careful). The main purpose for explicitly setting the ring
|
||||
speed is for when the card is first on the ring. In autosense mode, if the card
|
||||
cannot detect any active monitors on the ring it will not open, so you must
|
||||
re-init the card at the appropriate speed. Unfortunately at present the only
|
||||
way of doing this is rmmod and insmod which is a bit tough if it is compiled
|
||||
in the kernel.
|
||||
|
||||
pkt_buf_sz: This is this initial receive buffer allocation size. This will
|
||||
default to 4096 if no value is entered. You may increase performance of the
|
||||
driver by setting this to a value larger than the network packet size, although
|
||||
the driver now re-sizes buffers based on MTU settings as well.
|
||||
|
||||
message_level: Controls level of messages created by the driver. Defaults to 0:
|
||||
which only displays start-up and critical messages. Presently any non-zero
|
||||
value will display all soft messages as well. NB This does not turn
|
||||
debugging messages on, that must be done by modified the source code.
|
||||
|
||||
network_monitor: Any non-zero value will provide a quasi network monitoring
|
||||
mode. All unexpected MAC frames (beaconing etc.) will be received
|
||||
by the driver and the source and destination addresses printed.
|
||||
Also an entry will be added in /proc/net called olympic_tr%d, where tr%d
|
||||
is the registered device name, i.e tr0, tr1, etc. This displays low
|
||||
level information about the configuration of the ring and the adapter.
|
||||
This feature has been designed for network administrators to assist in
|
||||
the diagnosis of network / ring problems. (This used to OLYMPIC_NETWORK_MONITOR,
|
||||
but has now changed to allow each adapter to be configured differently and
|
||||
to alleviate the necessity to re-compile olympic to turn the option on).
|
||||
|
||||
Multi-card:
|
||||
|
||||
The driver will detect multiple cards and will work with shared interrupts,
|
||||
each card is assigned the next token ring device, i.e. tr0 , tr1, tr2. The
|
||||
driver should also happily reside in the system with other drivers. It has
|
||||
been tested with ibmtr.c running, and I personally have had one Olicom PCI
|
||||
card and two IBM olympic cards (all on the same interrupt), all running
|
||||
together.
|
||||
|
||||
Variable MTU size:
|
||||
|
||||
The driver can handle a MTU size up to either 4500 or 18000 depending upon
|
||||
ring speed. The driver also changes the size of the receive buffers as part
|
||||
of the mtu re-sizing, so if you set mtu = 18000, you will need to be able
|
||||
to allocate 16 * (sk_buff with 18000 buffer size) call it 18500 bytes per ring
|
||||
position = 296,000 bytes of memory space, plus of course anything
|
||||
necessary for the tx sk_buff's. Remember this is per card, so if you are
|
||||
building routers, gateway's etc, you could start to use a lot of memory
|
||||
real fast.
|
||||
|
||||
|
||||
6/8/99 Peter De Schrijver and Mike Phillips
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
Text File for the SMC TokenCard TokenRing Linux driver (smctr.c).
|
||||
By Jay Schulist <jschlst@samba.org>
|
||||
|
||||
The Linux SMC Token Ring driver works with the SMC TokenCard Elite (8115T)
|
||||
ISA and SMC TokenCard Elite/A (8115T/A) MCA adapters.
|
||||
|
||||
Latest information on this driver can be obtained on the Linux-SNA WWW site.
|
||||
Please point your browser to: http://www.linux-sna.org
|
||||
|
||||
This driver is rather simple to use. Select Y to Token Ring adapter support
|
||||
in the kernel configuration. A choice for SMC Token Ring adapters will
|
||||
appear. This drives supports all SMC ISA/MCA adapters. Choose this
|
||||
option. I personally recommend compiling the driver as a module (M), but if you
|
||||
you would like to compile it statically answer Y instead.
|
||||
|
||||
This driver supports multiple adapters without the need to load multiple copies
|
||||
of the driver. You should be able to load up to 7 adapters without any kernel
|
||||
modifications, if you are in need of more please contact the maintainer of this
|
||||
driver.
|
||||
|
||||
Load the driver either by lilo/loadlin or as a module. When a module using the
|
||||
following command will suffice for most:
|
||||
|
||||
# modprobe smctr
|
||||
smctr.c: v1.00 12/6/99 by jschlst@samba.org
|
||||
tr0: SMC TokenCard 8115T at Io 0x300, Irq 10, Rom 0xd8000, Ram 0xcc000.
|
||||
|
||||
Now just setup the device via ifconfig and set and routes you may have. After
|
||||
this you are ready to start sending some tokens.
|
||||
|
||||
Errata:
|
||||
1). For anyone wondering where to pick up the SMC adapters please browse
|
||||
to http://www.smc.com
|
||||
|
||||
2). If you are the first/only Token Ring Client on a Token Ring LAN, please
|
||||
specify the ringspeed with the ringspeed=[4/16] module option. If no
|
||||
ringspeed is specified the driver will attempt to autodetect the ring
|
||||
speed and/or if the adapter is the first/only station on the ring take
|
||||
the appropriate actions.
|
||||
|
||||
NOTE: Default ring speed is 16MB UTP.
|
||||
|
||||
3). PnP support for this adapter sucks. I recommend hard setting the
|
||||
IO/MEM/IRQ by the jumpers on the adapter. If this is not possible
|
||||
load the module with the following io=[ioaddr] mem=[mem_addr]
|
||||
irq=[irq_num].
|
||||
|
||||
The following IRQ, IO, and MEM settings are supported.
|
||||
|
||||
IO ports:
|
||||
0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, 0x300,
|
||||
0x320, 0x340, 0x360, 0x380.
|
||||
|
||||
IRQs:
|
||||
2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15
|
||||
|
||||
Memory addresses:
|
||||
0xA0000, 0xA4000, 0xA8000, 0xAC000, 0xB0000, 0xB4000,
|
||||
0xB8000, 0xBC000, 0xC0000, 0xC4000, 0xC8000, 0xCC000,
|
||||
0xD0000, 0xD4000, 0xD8000, 0xDC000, 0xE0000, 0xE4000,
|
||||
0xE8000, 0xEC000, 0xF0000, 0xF4000, 0xF8000, 0xFC000
|
||||
|
||||
This driver is under the GNU General Public License. Its Firmware image is
|
||||
included as an initialized C-array and is licensed by SMC to the Linux
|
||||
users of this driver. However no warranty about its fitness is expressed or
|
||||
implied by SMC.
|
|
@ -111,11 +111,12 @@ and detailed below as well:
|
|||
int phy_addr;
|
||||
int interface;
|
||||
struct stmmac_mdio_bus_data *mdio_bus_data;
|
||||
int pbl;
|
||||
struct stmmac_dma_cfg *dma_cfg;
|
||||
int clk_csr;
|
||||
int has_gmac;
|
||||
int enh_desc;
|
||||
int tx_coe;
|
||||
int rx_coe;
|
||||
int bugged_jumbo;
|
||||
int pmt;
|
||||
int force_sf_dma_mode;
|
||||
|
@ -136,10 +137,12 @@ Where:
|
|||
o pbl: the Programmable Burst Length is maximum number of beats to
|
||||
be transferred in one DMA transaction.
|
||||
GMAC also enables the 4xPBL by default.
|
||||
o clk_csr: CSR Clock range selection.
|
||||
o clk_csr: fixed CSR Clock range selection.
|
||||
o has_gmac: uses the GMAC core.
|
||||
o enh_desc: if sets the MAC will use the enhanced descriptor structure.
|
||||
o tx_coe: core is able to perform the tx csum in HW.
|
||||
o rx_coe: the supports three check sum offloading engine types:
|
||||
type_1, type_2 (full csum) and no RX coe.
|
||||
o bugged_jumbo: some HWs are not able to perform the csum in HW for
|
||||
over-sized frames due to limited buffer sizes.
|
||||
Setting this flag the csum will be done in SW on
|
||||
|
@ -160,7 +163,7 @@ Where:
|
|||
o custom_cfg: this is a custom configuration that can be passed while
|
||||
initialising the resources.
|
||||
|
||||
The we have:
|
||||
For MDIO bus The we have:
|
||||
|
||||
struct stmmac_mdio_bus_data {
|
||||
int bus_id;
|
||||
|
@ -177,10 +180,28 @@ Where:
|
|||
o irqs: list of IRQs, one per PHY.
|
||||
o probed_phy_irq: if irqs is NULL, use this for probed PHY.
|
||||
|
||||
|
||||
For DMA engine we have the following internal fields that should be
|
||||
tuned according to the HW capabilities.
|
||||
|
||||
struct stmmac_dma_cfg {
|
||||
int pbl;
|
||||
int fixed_burst;
|
||||
int burst_len_supported;
|
||||
};
|
||||
|
||||
Where:
|
||||
o pbl: Programmable Burst Length
|
||||
o fixed_burst: program the DMA to use the fixed burst mode
|
||||
o burst_len: this is the value we put in the register
|
||||
supported values are provided as macros in
|
||||
linux/stmmac.h header file.
|
||||
|
||||
---
|
||||
|
||||
Below an example how the structures above are using on ST platforms.
|
||||
|
||||
static struct plat_stmmacenet_data stxYYY_ethernet_platform_data = {
|
||||
.pbl = 32,
|
||||
.has_gmac = 0,
|
||||
.enh_desc = 0,
|
||||
.fix_mac_speed = stxYYY_ethernet_fix_mac_speed,
|
||||
|
|
|
@ -1,147 +0,0 @@
|
|||
Text file for the Linux SysKonnect Token Ring ISA/PCI Adapter Driver.
|
||||
Text file by: Jay Schulist <jschlst@samba.org>
|
||||
|
||||
The Linux SysKonnect Token Ring driver works with the SysKonnect TR4/16(+) ISA,
|
||||
SysKonnect TR4/16(+) PCI, SysKonnect TR4/16 PCI, and older revisions of the
|
||||
SK NET TR4/16 ISA card.
|
||||
|
||||
Latest information on this driver can be obtained on the Linux-SNA WWW site.
|
||||
Please point your browser to:
|
||||
http://www.linux-sna.org
|
||||
|
||||
Many thanks to Christoph Goos for his excellent work on this driver and
|
||||
SysKonnect for donating the adapters to Linux-SNA for the testing and
|
||||
maintenance of this device driver.
|
||||
|
||||
Important information to be noted:
|
||||
1. Adapters can be slow to open (~20 secs) and close (~5 secs), please be
|
||||
patient.
|
||||
2. This driver works very well when autoprobing for adapters. Why even
|
||||
think about those nasty io/int/dma settings of modprobe when the driver
|
||||
will do it all for you!
|
||||
|
||||
This driver is rather simple to use. Select Y to Token Ring adapter support
|
||||
in the kernel configuration. A choice for SysKonnect Token Ring adapters will
|
||||
appear. This drives supports all SysKonnect ISA and PCI adapters. Choose this
|
||||
option. I personally recommend compiling the driver as a module (M), but if you
|
||||
you would like to compile it statically answer Y instead.
|
||||
|
||||
This driver supports multiple adapters without the need to load multiple copies
|
||||
of the driver. You should be able to load up to 7 adapters without any kernel
|
||||
modifications, if you are in need of more please contact the maintainer of this
|
||||
driver.
|
||||
|
||||
Load the driver either by lilo/loadlin or as a module. When a module using the
|
||||
following command will suffice for most:
|
||||
|
||||
# modprobe sktr
|
||||
|
||||
This will produce output similar to the following: (Output is user specific)
|
||||
|
||||
sktr.c: v1.01 08/29/97 by Christoph Goos
|
||||
tr0: SK NET TR 4/16 PCI found at 0x6100, using IRQ 17.
|
||||
tr1: SK NET TR 4/16 PCI found at 0x6200, using IRQ 16.
|
||||
tr2: SK NET TR 4/16 ISA found at 0xa20, using IRQ 10 and DMA 5.
|
||||
|
||||
Now just setup the device via ifconfig and set and routes you may have. After
|
||||
this you are ready to start sending some tokens.
|
||||
|
||||
Errata:
|
||||
For anyone wondering where to pick up the SysKonnect adapters please browse
|
||||
to http://www.syskonnect.com
|
||||
|
||||
This driver is under the GNU General Public License. Its Firmware image is
|
||||
included as an initialized C-array and is licensed by SysKonnect to the Linux
|
||||
users of this driver. However no warranty about its fitness is expressed or
|
||||
implied by SysKonnect.
|
||||
|
||||
Below find attached the setting for the SK NET TR 4/16 ISA adapters
|
||||
-------------------------------------------------------------------
|
||||
|
||||
***************************
|
||||
*** C O N T E N T S ***
|
||||
***************************
|
||||
|
||||
1) Location of DIP-Switch W1
|
||||
2) Default settings
|
||||
3) DIP-Switch W1 description
|
||||
|
||||
|
||||
==============================================================
|
||||
CHAPTER 1 LOCATION OF DIP-SWITCH
|
||||
==============================================================
|
||||
|
||||
UÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
||||
þUÄÄÄÄÄÄ¿ UÄÄÄÄÄ¿ UÄÄÄ¿ þ
|
||||
þAÄÄÄÄÄÄU W1 AÄÄÄÄÄU UÄÄÄÄ¿ þ þ þ
|
||||
þUÄÄÄÄÄÄ¿ þ þ þ þ UÄÄÅ¿
|
||||
þAÄÄÄÄÄÄU UÄÄÄÄÄÄÄÄÄÄÄ¿ AÄÄÄÄU þ þ þ þþ
|
||||
þUÄÄÄÄÄÄ¿ þ þ UÄÄÄ¿ AÄÄÄU AÄÄÅU
|
||||
þAÄÄÄÄÄÄU þ TMS380C26 þ þ þ þ
|
||||
þUÄÄÄÄÄÄ¿ þ þ AÄÄÄU AÄ¿
|
||||
þAÄÄÄÄÄÄU þ þ þ þ
|
||||
þ AÄÄÄÄÄÄÄÄÄÄÄU þ þ
|
||||
þ þ þ
|
||||
þ AÄU
|
||||
þ þ
|
||||
þ þ
|
||||
þ þ
|
||||
þ þ
|
||||
AÄÄÄÄÄÄÄÄÄÄÄÄAÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄAÄÄAÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄAÄÄÄÄÄÄÄÄÄU
|
||||
AÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄU AÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄU
|
||||
|
||||
==============================================================
|
||||
CHAPTER 2 DEFAULT SETTINGS
|
||||
==============================================================
|
||||
|
||||
W1 1 2 3 4 5 6 7 8
|
||||
+------------------------------+
|
||||
| ON X |
|
||||
| OFF X X X X X X X |
|
||||
+------------------------------+
|
||||
|
||||
W1.1 = ON Adapter drives address lines SA17..19
|
||||
W1.2 - 1.5 = OFF BootROM disabled
|
||||
W1.6 - 1.8 = OFF I/O address 0A20h
|
||||
|
||||
==============================================================
|
||||
CHAPTER 3 DIP SWITCH W1 DESCRIPTION
|
||||
==============================================================
|
||||
|
||||
UÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄ¿ ON
|
||||
þ 1 þ 2 þ 3 þ 4 þ 5 þ 6 þ 7 þ 8 þ
|
||||
AÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄU OFF
|
||||
|AD | BootROM Addr. | I/O |
|
||||
+-+-+-------+-------+-----+-----+
|
||||
| | |
|
||||
| | +------ 6 7 8
|
||||
| | ON ON ON 1900h
|
||||
| | ON ON OFF 0900h
|
||||
| | ON OFF ON 1980h
|
||||
| | ON OFF OFF 0980h
|
||||
| | OFF ON ON 1b20h
|
||||
| | OFF ON OFF 0b20h
|
||||
| | OFF OFF ON 1a20h
|
||||
| | OFF OFF OFF 0a20h (+)
|
||||
| |
|
||||
| |
|
||||
| +-------- 2 3 4 5
|
||||
| OFF x x x disabled (+)
|
||||
| ON ON ON ON C0000
|
||||
| ON ON ON OFF C4000
|
||||
| ON ON OFF ON C8000
|
||||
| ON ON OFF OFF CC000
|
||||
| ON OFF ON ON D0000
|
||||
| ON OFF ON OFF D4000
|
||||
| ON OFF OFF ON D8000
|
||||
| ON OFF OFF OFF DC000
|
||||
|
|
||||
|
|
||||
+----- 1
|
||||
OFF adapter does NOT drive SA<17..19>
|
||||
ON adapter drives SA<17..19> (+)
|
||||
|
||||
|
||||
(+) means default setting
|
||||
|
||||
********************************
|
155
Documentation/nfc/nfc-hci.txt
Normal file
155
Documentation/nfc/nfc-hci.txt
Normal file
|
@ -0,0 +1,155 @@
|
|||
HCI backend for NFC Core
|
||||
|
||||
Author: Eric Lapuyade, Samuel Ortiz
|
||||
Contact: eric.lapuyade@intel.com, samuel.ortiz@intel.com
|
||||
|
||||
General
|
||||
-------
|
||||
|
||||
The HCI layer implements much of the ETSI TS 102 622 V10.2.0 specification. It
|
||||
enables easy writing of HCI-based NFC drivers. The HCI layer runs as an NFC Core
|
||||
backend, implementing an abstract nfc device and translating NFC Core API
|
||||
to HCI commands and events.
|
||||
|
||||
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.
|
||||
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.
|
||||
HCI uses 2 execution contexts:
|
||||
- one if for executing commands : nfc_hci_msg_tx_work(). Only one command
|
||||
can be executing at any given moment.
|
||||
- one if for dispatching received events and responses : nfc_hci_msg_rx_work()
|
||||
|
||||
HCI Session initialization:
|
||||
---------------------------
|
||||
|
||||
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.
|
||||
|
||||
HCI Gates and Pipes
|
||||
-------------------
|
||||
|
||||
A gate defines the 'port' where some service can be found. In order to access
|
||||
a service, one must create a pipe to that gate and open it. In this
|
||||
implementation, pipes are totally hidden. The public API only knows gates.
|
||||
This is consistent with the driver need to send commands to proprietary gates
|
||||
without knowing the pipe connected to it.
|
||||
|
||||
Driver interface
|
||||
----------------
|
||||
|
||||
A driver would normally register itself with HCI and provide the following
|
||||
entry points:
|
||||
|
||||
struct nfc_hci_ops {
|
||||
int (*open)(struct nfc_hci_dev *hdev);
|
||||
void (*close)(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);
|
||||
};
|
||||
|
||||
open() and close() shall turn the hardware on and off. xmit() shall simply
|
||||
write a frame to the chip. 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.
|
||||
target_from_gate() is another optional entrypoint to return the protocols
|
||||
corresponding to a proprietary gate.
|
||||
|
||||
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
|
||||
-----
|
||||
|
||||
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.
|
||||
|
||||
Included Drivers
|
||||
----------------
|
||||
|
||||
An HCI based driver for an NXP PN544, connected through I2C bus, and using
|
||||
shdlc is included.
|
||||
|
||||
Execution Contexts
|
||||
------------------
|
||||
|
||||
The execution contexts are the following:
|
||||
- IRQ handler (IRQH):
|
||||
fast, cannot sleep. stores incoming frames into an shdlc rx queue
|
||||
|
||||
- SHDLC State Machine worker (SMW)
|
||||
handles shdlc rx & tx queues. Dispatches HCI cmd responses.
|
||||
|
||||
- HCI Tx Cmd worker (MSGTXWQ)
|
||||
Serialize execution of HCI commands. Complete execution in case of resp timeout.
|
||||
|
||||
- HCI Rx worker (MSGRXWQ)
|
||||
Dispatches incoming HCI commands or events.
|
||||
|
||||
- Syscall context from a userspace call (SYSCALL)
|
||||
Any entrypoint in HCI called from NFC Core
|
||||
|
||||
Workflow executing an HCI command (using shdlc)
|
||||
-----------------------------------------------
|
||||
|
||||
Executing an HCI command can easily be performed synchronously using the
|
||||
following API:
|
||||
|
||||
int nfc_hci_send_cmd (struct nfc_hci_dev *hdev, u8 gate, u8 cmd,
|
||||
const u8 *param, size_t param_len, struct sk_buff **skb)
|
||||
|
||||
The API must be invoked from a context that can sleep. Most of the time, this
|
||||
will be the syscall context. skb will return the result that was received in
|
||||
the response.
|
||||
|
||||
Internally, execution is asynchronous. So all this API does is to enqueue the
|
||||
HCI command, setup a local wait queue on stack, and wait_event() for completion.
|
||||
The wait is not interruptible because it is guaranteed that the command will
|
||||
complete after some short timeout anyway.
|
||||
|
||||
MSGTXWQ context will then be scheduled and invoke nfc_hci_msg_tx_work().
|
||||
This function will dequeue the next pending command and send its HCP fragments
|
||||
to the lower layer which happens to be shdlc. It will then start a timer to be
|
||||
able to complete the command with a timeout error if no response arrive.
|
||||
|
||||
SMW context gets scheduled and invokes nfc_shdlc_sm_work(). This function
|
||||
handles shdlc framing in and out. It uses the driver xmit to send frames and
|
||||
receives incoming frames in an skb queue filled from the driver IRQ handler.
|
||||
SHDLC I(nformation) frames payload are HCP fragments. They are agregated to
|
||||
form complete HCI frames, which can be a response, command, or event.
|
||||
|
||||
HCI Responses are dispatched immediately from this context to unblock
|
||||
waiting command execution. Reponse 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.
|
||||
|
||||
Workflow receiving an HCI event or command
|
||||
------------------------------------------
|
||||
|
||||
HCI commands or events are not dispatched from SMW context. Instead, they are
|
||||
queued to HCI rx_queue and will be dispatched from HCI rx worker
|
||||
context (MSGRXWQ). This is done this way to allow a cmd or event handler
|
||||
to also execute other commands (for example, handling the
|
||||
NFC_HCI_EVT_TARGET_DISCOVERED event from PN544 requires to issue an
|
||||
ANY_GET_PARAMETER to the reader A gate to get information on the target
|
||||
that was discovered).
|
||||
|
||||
Typically, such an event will be propagated to NFC Core from MSGRXWQ context.
|
|
@ -43,6 +43,13 @@ Values :
|
|||
1 - enable the JIT
|
||||
2 - enable the JIT and ask the compiler to emit traces on kernel log.
|
||||
|
||||
dev_weight
|
||||
--------------
|
||||
|
||||
The maximum number of packets that kernel can handle on a NAPI interrupt,
|
||||
it's a Per-CPU variable.
|
||||
Default: 64
|
||||
|
||||
rmem_default
|
||||
------------
|
||||
|
||||
|
|
36
MAINTAINERS
36
MAINTAINERS
|
@ -1431,6 +1431,7 @@ F: include/linux/backlight.h
|
|||
BATMAN ADVANCED
|
||||
M: Marek Lindner <lindner_marek@yahoo.de>
|
||||
M: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
|
||||
M: Antonio Quartulli <ordex@autistici.org>
|
||||
L: b.a.t.m.a.n@lists.open-mesh.org
|
||||
W: http://www.open-mesh.org/
|
||||
S: Maintained
|
||||
|
@ -3518,12 +3519,6 @@ M: Deepak Saxena <dsaxena@plexity.net>
|
|||
S: Maintained
|
||||
F: drivers/char/hw_random/ixp4xx-rng.c
|
||||
|
||||
INTEL IXP2000 ETHERNET DRIVER
|
||||
M: Lennert Buytenhek <kernel@wantstofly.org>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/ethernet/xscale/ixp2000/
|
||||
|
||||
INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/igbvf/ixgb/ixgbe/ixgbevf)
|
||||
M: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
|
||||
M: Jesse Brandeburg <jesse.brandeburg@intel.com>
|
||||
|
@ -5208,7 +5203,7 @@ S: Maintained
|
|||
F: include/linux/personality.h
|
||||
|
||||
PHONET PROTOCOL
|
||||
M: Remi Denis-Courmont <remi.denis-courmont@nokia.com>
|
||||
M: Remi Denis-Courmont <courmisch@gmail.com>
|
||||
S: Supported
|
||||
F: Documentation/networking/phonet.txt
|
||||
F: include/linux/phonet.h
|
||||
|
@ -6676,6 +6671,16 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
|||
S: Maintained
|
||||
F: sound/soc/codecs/twl4030*
|
||||
|
||||
TI WILINK WIRELESS DRIVERS
|
||||
M: Luciano Coelho <coelho@ti.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://wireless.kernel.org/en/users/Drivers/wl12xx
|
||||
W: http://wireless.kernel.org/en/users/Drivers/wl1251
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git
|
||||
S: Maintained
|
||||
F: drivers/net/wireless/ti/
|
||||
F: include/linux/wl12xx.h
|
||||
|
||||
TIPC NETWORK LAYER
|
||||
M: Jon Maloy <jon.maloy@ericsson.com>
|
||||
M: Allan Stephens <allan.stephens@windriver.com>
|
||||
|
@ -7432,23 +7437,6 @@ M: Miloslav Trmac <mitr@volny.cz>
|
|||
S: Maintained
|
||||
F: drivers/input/misc/wistron_btns.c
|
||||
|
||||
WL1251 WIRELESS DRIVER
|
||||
M: Luciano Coelho <coelho@ti.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://wireless.kernel.org/en/users/Drivers/wl1251
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
|
||||
S: Maintained
|
||||
F: drivers/net/wireless/wl1251/*
|
||||
|
||||
WL1271 WIRELESS DRIVER
|
||||
M: Luciano Coelho <coelho@ti.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://wireless.kernel.org/en/users/Drivers/wl12xx
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git
|
||||
S: Maintained
|
||||
F: drivers/net/wireless/wl12xx/
|
||||
F: include/linux/wl12xx.h
|
||||
|
||||
WL3501 WIRELESS PCMCIA CARD DRIVER
|
||||
M: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
|
|
|
@ -26,15 +26,6 @@
|
|||
#include "clock.h"
|
||||
#include "sam9_smc.h"
|
||||
|
||||
static struct map_desc at91rm9200_io_desc[] __initdata = {
|
||||
{
|
||||
.virtual = AT91_VA_BASE_EMAC,
|
||||
.pfn = __phys_to_pfn(AT91RM9200_BASE_EMAC),
|
||||
.length = SZ_16K,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Clocks
|
||||
* -------------------------------------------------------------------- */
|
||||
|
@ -315,7 +306,6 @@ static void __init at91rm9200_map_io(void)
|
|||
{
|
||||
/* Map peripherals */
|
||||
at91_init_sram(0, AT91RM9200_SRAM_BASE, AT91RM9200_SRAM_SIZE);
|
||||
iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc));
|
||||
}
|
||||
|
||||
static void __init at91rm9200_ioremap_registers(void)
|
||||
|
|
|
@ -140,8 +140,8 @@ static struct macb_platform_data eth_data;
|
|||
|
||||
static struct resource eth_resources[] = {
|
||||
[0] = {
|
||||
.start = AT91_VA_BASE_EMAC,
|
||||
.end = AT91_VA_BASE_EMAC + SZ_16K - 1,
|
||||
.start = AT91RM9200_BASE_EMAC,
|
||||
.end = AT91RM9200_BASE_EMAC + SZ_16K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
|
|
|
@ -94,7 +94,6 @@
|
|||
* Virtual to Physical Address mapping for IO devices.
|
||||
*/
|
||||
#define AT91_VA_BASE_SYS AT91_IO_P2V(AT91_BASE_SYS)
|
||||
#define AT91_VA_BASE_EMAC AT91_IO_P2V(AT91RM9200_BASE_EMAC)
|
||||
|
||||
/* Internal SRAM is mapped below the IO devices */
|
||||
#define AT91_SRAM_MAX SZ_1M
|
||||
|
|
|
@ -75,4 +75,7 @@ struct ixp46x_ts_regs {
|
|||
#define TX_SNAPSHOT_LOCKED (1<<0)
|
||||
#define RX_SNAPSHOT_LOCKED (1<<1)
|
||||
|
||||
/* The ptp_ixp46x module will set this variable */
|
||||
extern int ixp46x_phc_index;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -346,11 +346,8 @@ CONFIG_CHELSIO_T1=m
|
|||
CONFIG_IXGB=m
|
||||
CONFIG_S2IO=m
|
||||
CONFIG_MYRI10GE=m
|
||||
CONFIG_TR=y
|
||||
CONFIG_IBMOL=m
|
||||
CONFIG_IBMLS=m
|
||||
CONFIG_3C359=m
|
||||
CONFIG_TMS380TR=m
|
||||
CONFIG_TMSPCI=m
|
||||
CONFIG_ABYSS=m
|
||||
CONFIG_USB_CATC=m
|
||||
|
@ -376,7 +373,6 @@ CONFIG_PCMCIA_SMC91C92=m
|
|||
CONFIG_PCMCIA_XIRC2PS=m
|
||||
CONFIG_PCMCIA_AXNET=m
|
||||
CONFIG_ARCNET_COM20020_CS=m
|
||||
CONFIG_PCMCIA_IBMTR=m
|
||||
CONFIG_WAN=y
|
||||
CONFIG_LANMEDIA=m
|
||||
CONFIG_HDLC=m
|
||||
|
|
|
@ -30,6 +30,7 @@ config SPARC
|
|||
select USE_GENERIC_SMP_HELPERS if SMP
|
||||
select GENERIC_PCI_IOMAP
|
||||
select HAVE_NMI_WATCHDOG if SPARC64
|
||||
select HAVE_BPF_JIT
|
||||
|
||||
config SPARC32
|
||||
def_bool !64BIT
|
||||
|
|
|
@ -66,6 +66,7 @@ head-y += arch/sparc/kernel/init_task.o
|
|||
|
||||
core-y += arch/sparc/kernel/
|
||||
core-y += arch/sparc/mm/ arch/sparc/math-emu/
|
||||
core-y += arch/sparc/net/
|
||||
|
||||
libs-y += arch/sparc/prom/
|
||||
libs-y += arch/sparc/lib/
|
||||
|
|
4
arch/sparc/net/Makefile
Normal file
4
arch/sparc/net/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
|||
#
|
||||
# Arch-specific network modules
|
||||
#
|
||||
obj-$(CONFIG_BPF_JIT) += bpf_jit_asm.o bpf_jit_comp.o
|
68
arch/sparc/net/bpf_jit.h
Normal file
68
arch/sparc/net/bpf_jit.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
#ifndef _BPF_JIT_H
|
||||
#define _BPF_JIT_H
|
||||
|
||||
/* Conventions:
|
||||
* %g1 : temporary
|
||||
* %g2 : Secondary temporary used by SKB data helper stubs.
|
||||
* %g3 : packet offset passed into SKB data helper stubs.
|
||||
* %o0 : pointer to skb (first argument given to JIT function)
|
||||
* %o1 : BPF A accumulator
|
||||
* %o2 : BPF X accumulator
|
||||
* %o3 : Holds saved %o7 so we can call helper functions without needing
|
||||
* to allocate a register window.
|
||||
* %o4 : skb->len - skb->data_len
|
||||
* %o5 : skb->data
|
||||
*/
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#define G0 0x00
|
||||
#define G1 0x01
|
||||
#define G3 0x03
|
||||
#define G6 0x06
|
||||
#define O0 0x08
|
||||
#define O1 0x09
|
||||
#define O2 0x0a
|
||||
#define O3 0x0b
|
||||
#define O4 0x0c
|
||||
#define O5 0x0d
|
||||
#define SP 0x0e
|
||||
#define O7 0x0f
|
||||
#define FP 0x1e
|
||||
|
||||
#define r_SKB O0
|
||||
#define r_A O1
|
||||
#define r_X O2
|
||||
#define r_saved_O7 O3
|
||||
#define r_HEADLEN O4
|
||||
#define r_SKB_DATA O5
|
||||
#define r_TMP G1
|
||||
#define r_TMP2 G2
|
||||
#define r_OFF G3
|
||||
|
||||
/* assembly code in arch/sparc/net/bpf_jit_asm.S */
|
||||
extern u32 bpf_jit_load_word[];
|
||||
extern u32 bpf_jit_load_half[];
|
||||
extern u32 bpf_jit_load_byte[];
|
||||
extern u32 bpf_jit_load_byte_msh[];
|
||||
extern u32 bpf_jit_load_word_positive_offset[];
|
||||
extern u32 bpf_jit_load_half_positive_offset[];
|
||||
extern u32 bpf_jit_load_byte_positive_offset[];
|
||||
extern u32 bpf_jit_load_byte_msh_positive_offset[];
|
||||
extern u32 bpf_jit_load_word_negative_offset[];
|
||||
extern u32 bpf_jit_load_half_negative_offset[];
|
||||
extern u32 bpf_jit_load_byte_negative_offset[];
|
||||
extern u32 bpf_jit_load_byte_msh_negative_offset[];
|
||||
|
||||
#else
|
||||
#define r_SKB %o0
|
||||
#define r_A %o1
|
||||
#define r_X %o2
|
||||
#define r_saved_O7 %o3
|
||||
#define r_HEADLEN %o4
|
||||
#define r_SKB_DATA %o5
|
||||
#define r_TMP %g1
|
||||
#define r_TMP2 %g2
|
||||
#define r_OFF %g3
|
||||
#endif
|
||||
|
||||
#endif /* _BPF_JIT_H */
|
205
arch/sparc/net/bpf_jit_asm.S
Normal file
205
arch/sparc/net/bpf_jit_asm.S
Normal file
|
@ -0,0 +1,205 @@
|
|||
#include <asm/ptrace.h>
|
||||
|
||||
#include "bpf_jit.h"
|
||||
|
||||
#ifdef CONFIG_SPARC64
|
||||
#define SAVE_SZ 176
|
||||
#define SCRATCH_OFF STACK_BIAS + 128
|
||||
#define BE_PTR(label) be,pn %xcc, label
|
||||
#else
|
||||
#define SAVE_SZ 96
|
||||
#define SCRATCH_OFF 72
|
||||
#define BE_PTR(label) be label
|
||||
#endif
|
||||
|
||||
#define SKF_MAX_NEG_OFF (-0x200000) /* SKF_LL_OFF from filter.h */
|
||||
|
||||
.text
|
||||
.globl bpf_jit_load_word
|
||||
bpf_jit_load_word:
|
||||
cmp r_OFF, 0
|
||||
bl bpf_slow_path_word_neg
|
||||
nop
|
||||
.globl bpf_jit_load_word_positive_offset
|
||||
bpf_jit_load_word_positive_offset:
|
||||
sub r_HEADLEN, r_OFF, r_TMP
|
||||
cmp r_TMP, 3
|
||||
ble bpf_slow_path_word
|
||||
add r_SKB_DATA, r_OFF, r_TMP
|
||||
andcc r_TMP, 3, %g0
|
||||
bne load_word_unaligned
|
||||
nop
|
||||
retl
|
||||
ld [r_TMP], r_A
|
||||
load_word_unaligned:
|
||||
ldub [r_TMP + 0x0], r_OFF
|
||||
ldub [r_TMP + 0x1], r_TMP2
|
||||
sll r_OFF, 8, r_OFF
|
||||
or r_OFF, r_TMP2, r_OFF
|
||||
ldub [r_TMP + 0x2], r_TMP2
|
||||
sll r_OFF, 8, r_OFF
|
||||
or r_OFF, r_TMP2, r_OFF
|
||||
ldub [r_TMP + 0x3], r_TMP2
|
||||
sll r_OFF, 8, r_OFF
|
||||
retl
|
||||
or r_OFF, r_TMP2, r_A
|
||||
|
||||
.globl bpf_jit_load_half
|
||||
bpf_jit_load_half:
|
||||
cmp r_OFF, 0
|
||||
bl bpf_slow_path_half_neg
|
||||
nop
|
||||
.globl bpf_jit_load_half_positive_offset
|
||||
bpf_jit_load_half_positive_offset:
|
||||
sub r_HEADLEN, r_OFF, r_TMP
|
||||
cmp r_TMP, 1
|
||||
ble bpf_slow_path_half
|
||||
add r_SKB_DATA, r_OFF, r_TMP
|
||||
andcc r_TMP, 1, %g0
|
||||
bne load_half_unaligned
|
||||
nop
|
||||
retl
|
||||
lduh [r_TMP], r_A
|
||||
load_half_unaligned:
|
||||
ldub [r_TMP + 0x0], r_OFF
|
||||
ldub [r_TMP + 0x1], r_TMP2
|
||||
sll r_OFF, 8, r_OFF
|
||||
retl
|
||||
or r_OFF, r_TMP2, r_A
|
||||
|
||||
.globl bpf_jit_load_byte
|
||||
bpf_jit_load_byte:
|
||||
cmp r_OFF, 0
|
||||
bl bpf_slow_path_byte_neg
|
||||
nop
|
||||
.globl bpf_jit_load_byte_positive_offset
|
||||
bpf_jit_load_byte_positive_offset:
|
||||
cmp r_OFF, r_HEADLEN
|
||||
bge bpf_slow_path_byte
|
||||
nop
|
||||
retl
|
||||
ldub [r_SKB_DATA + r_OFF], r_A
|
||||
|
||||
.globl bpf_jit_load_byte_msh
|
||||
bpf_jit_load_byte_msh:
|
||||
cmp r_OFF, 0
|
||||
bl bpf_slow_path_byte_msh_neg
|
||||
nop
|
||||
.globl bpf_jit_load_byte_msh_positive_offset
|
||||
bpf_jit_load_byte_msh_positive_offset:
|
||||
cmp r_OFF, r_HEADLEN
|
||||
bge bpf_slow_path_byte_msh
|
||||
nop
|
||||
ldub [r_SKB_DATA + r_OFF], r_OFF
|
||||
and r_OFF, 0xf, r_OFF
|
||||
retl
|
||||
sll r_OFF, 2, r_X
|
||||
|
||||
#define bpf_slow_path_common(LEN) \
|
||||
save %sp, -SAVE_SZ, %sp; \
|
||||
mov %i0, %o0; \
|
||||
mov r_OFF, %o1; \
|
||||
add %fp, SCRATCH_OFF, %o2; \
|
||||
call skb_copy_bits; \
|
||||
mov (LEN), %o3; \
|
||||
cmp %o0, 0; \
|
||||
restore;
|
||||
|
||||
bpf_slow_path_word:
|
||||
bpf_slow_path_common(4)
|
||||
bl bpf_error
|
||||
ld [%sp + SCRATCH_OFF], r_A
|
||||
retl
|
||||
nop
|
||||
bpf_slow_path_half:
|
||||
bpf_slow_path_common(2)
|
||||
bl bpf_error
|
||||
lduh [%sp + SCRATCH_OFF], r_A
|
||||
retl
|
||||
nop
|
||||
bpf_slow_path_byte:
|
||||
bpf_slow_path_common(1)
|
||||
bl bpf_error
|
||||
ldub [%sp + SCRATCH_OFF], r_A
|
||||
retl
|
||||
nop
|
||||
bpf_slow_path_byte_msh:
|
||||
bpf_slow_path_common(1)
|
||||
bl bpf_error
|
||||
ldub [%sp + SCRATCH_OFF], r_A
|
||||
and r_OFF, 0xf, r_OFF
|
||||
retl
|
||||
sll r_OFF, 2, r_X
|
||||
|
||||
#define bpf_negative_common(LEN) \
|
||||
save %sp, -SAVE_SZ, %sp; \
|
||||
mov %i0, %o0; \
|
||||
mov r_OFF, %o1; \
|
||||
call bpf_internal_load_pointer_neg_helper; \
|
||||
mov (LEN), %o2; \
|
||||
mov %o0, r_TMP; \
|
||||
cmp %o0, 0; \
|
||||
BE_PTR(bpf_error); \
|
||||
restore;
|
||||
|
||||
bpf_slow_path_word_neg:
|
||||
sethi %hi(SKF_MAX_NEG_OFF), r_TMP
|
||||
cmp r_OFF, r_TMP
|
||||
bl bpf_error
|
||||
nop
|
||||
.globl bpf_jit_load_word_negative_offset
|
||||
bpf_jit_load_word_negative_offset:
|
||||
bpf_negative_common(4)
|
||||
andcc r_TMP, 3, %g0
|
||||
bne load_word_unaligned
|
||||
nop
|
||||
retl
|
||||
ld [r_TMP], r_A
|
||||
|
||||
bpf_slow_path_half_neg:
|
||||
sethi %hi(SKF_MAX_NEG_OFF), r_TMP
|
||||
cmp r_OFF, r_TMP
|
||||
bl bpf_error
|
||||
nop
|
||||
.globl bpf_jit_load_half_negative_offset
|
||||
bpf_jit_load_half_negative_offset:
|
||||
bpf_negative_common(2)
|
||||
andcc r_TMP, 1, %g0
|
||||
bne load_half_unaligned
|
||||
nop
|
||||
retl
|
||||
lduh [r_TMP], r_A
|
||||
|
||||
bpf_slow_path_byte_neg:
|
||||
sethi %hi(SKF_MAX_NEG_OFF), r_TMP
|
||||
cmp r_OFF, r_TMP
|
||||
bl bpf_error
|
||||
nop
|
||||
.globl bpf_jit_load_byte_negative_offset
|
||||
bpf_jit_load_byte_negative_offset:
|
||||
bpf_negative_common(1)
|
||||
retl
|
||||
ldub [r_TMP], r_A
|
||||
|
||||
bpf_slow_path_byte_msh_neg:
|
||||
sethi %hi(SKF_MAX_NEG_OFF), r_TMP
|
||||
cmp r_OFF, r_TMP
|
||||
bl bpf_error
|
||||
nop
|
||||
.globl bpf_jit_load_byte_msh_negative_offset
|
||||
bpf_jit_load_byte_msh_negative_offset:
|
||||
bpf_negative_common(1)
|
||||
ldub [r_TMP], r_OFF
|
||||
and r_OFF, 0xf, r_OFF
|
||||
retl
|
||||
sll r_OFF, 2, r_X
|
||||
|
||||
bpf_error:
|
||||
/* Make the JIT program return zero. The JIT epilogue
|
||||
* stores away the original %o7 into r_saved_O7. The
|
||||
* normal leaf function return is to use "retl" which
|
||||
* would evalute to "jmpl %o7 + 8, %g0" but we want to
|
||||
* use the saved value thus the sequence you see here.
|
||||
*/
|
||||
jmpl r_saved_O7 + 8, %g0
|
||||
clr %o0
|
802
arch/sparc/net/bpf_jit_comp.c
Normal file
802
arch/sparc/net/bpf_jit_comp.c
Normal file
|
@ -0,0 +1,802 @@
|
|||
#include <linux/moduleloader.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/cache.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
#include "bpf_jit.h"
|
||||
|
||||
int bpf_jit_enable __read_mostly;
|
||||
|
||||
static inline bool is_simm13(unsigned int value)
|
||||
{
|
||||
return value + 0x1000 < 0x2000;
|
||||
}
|
||||
|
||||
static void bpf_flush_icache(void *start_, void *end_)
|
||||
{
|
||||
#ifdef CONFIG_SPARC64
|
||||
/* Cheetah's I-cache is fully coherent. */
|
||||
if (tlb_type == spitfire) {
|
||||
unsigned long start = (unsigned long) start_;
|
||||
unsigned long end = (unsigned long) end_;
|
||||
|
||||
start &= ~7UL;
|
||||
end = (end + 7UL) & ~7UL;
|
||||
while (start < end) {
|
||||
flushi(start);
|
||||
start += 32;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#define SEEN_DATAREF 1 /* might call external helpers */
|
||||
#define SEEN_XREG 2 /* ebx is used */
|
||||
#define SEEN_MEM 4 /* use mem[] for temporary storage */
|
||||
|
||||
#define S13(X) ((X) & 0x1fff)
|
||||
#define IMMED 0x00002000
|
||||
#define RD(X) ((X) << 25)
|
||||
#define RS1(X) ((X) << 14)
|
||||
#define RS2(X) ((X))
|
||||
#define OP(X) ((X) << 30)
|
||||
#define OP2(X) ((X) << 22)
|
||||
#define OP3(X) ((X) << 19)
|
||||
#define COND(X) ((X) << 25)
|
||||
#define F1(X) OP(X)
|
||||
#define F2(X, Y) (OP(X) | OP2(Y))
|
||||
#define F3(X, Y) (OP(X) | OP3(Y))
|
||||
|
||||
#define CONDN COND(0x0)
|
||||
#define CONDE COND(0x1)
|
||||
#define CONDLE COND(0x2)
|
||||
#define CONDL COND(0x3)
|
||||
#define CONDLEU COND(0x4)
|
||||
#define CONDCS COND(0x5)
|
||||
#define CONDNEG COND(0x6)
|
||||
#define CONDVC COND(0x7)
|
||||
#define CONDA COND(0x8)
|
||||
#define CONDNE COND(0x9)
|
||||
#define CONDG COND(0xa)
|
||||
#define CONDGE COND(0xb)
|
||||
#define CONDGU COND(0xc)
|
||||
#define CONDCC COND(0xd)
|
||||
#define CONDPOS COND(0xe)
|
||||
#define CONDVS COND(0xf)
|
||||
|
||||
#define CONDGEU CONDCC
|
||||
#define CONDLU CONDCS
|
||||
|
||||
#define WDISP22(X) (((X) >> 2) & 0x3fffff)
|
||||
|
||||
#define BA (F2(0, 2) | CONDA)
|
||||
#define BGU (F2(0, 2) | CONDGU)
|
||||
#define BLEU (F2(0, 2) | CONDLEU)
|
||||
#define BGEU (F2(0, 2) | CONDGEU)
|
||||
#define BLU (F2(0, 2) | CONDLU)
|
||||
#define BE (F2(0, 2) | CONDE)
|
||||
#define BNE (F2(0, 2) | CONDNE)
|
||||
|
||||
#ifdef CONFIG_SPARC64
|
||||
#define BNE_PTR (F2(0, 1) | CONDNE | (2 << 20))
|
||||
#else
|
||||
#define BNE_PTR BNE
|
||||
#endif
|
||||
|
||||
#define SETHI(K, REG) \
|
||||
(F2(0, 0x4) | RD(REG) | (((K) >> 10) & 0x3fffff))
|
||||
#define OR_LO(K, REG) \
|
||||
(F3(2, 0x02) | IMMED | RS1(REG) | ((K) & 0x3ff) | RD(REG))
|
||||
|
||||
#define ADD F3(2, 0x00)
|
||||
#define AND F3(2, 0x01)
|
||||
#define ANDCC F3(2, 0x11)
|
||||
#define OR F3(2, 0x02)
|
||||
#define SUB F3(2, 0x04)
|
||||
#define SUBCC F3(2, 0x14)
|
||||
#define MUL F3(2, 0x0a) /* umul */
|
||||
#define DIV F3(2, 0x0e) /* udiv */
|
||||
#define SLL F3(2, 0x25)
|
||||
#define SRL F3(2, 0x26)
|
||||
#define JMPL F3(2, 0x38)
|
||||
#define CALL F1(1)
|
||||
#define BR F2(0, 0x01)
|
||||
#define RD_Y F3(2, 0x28)
|
||||
#define WR_Y F3(2, 0x30)
|
||||
|
||||
#define LD32 F3(3, 0x00)
|
||||
#define LD8 F3(3, 0x01)
|
||||
#define LD16 F3(3, 0x02)
|
||||
#define LD64 F3(3, 0x0b)
|
||||
#define ST32 F3(3, 0x04)
|
||||
|
||||
#ifdef CONFIG_SPARC64
|
||||
#define LDPTR LD64
|
||||
#define BASE_STACKFRAME 176
|
||||
#else
|
||||
#define LDPTR LD32
|
||||
#define BASE_STACKFRAME 96
|
||||
#endif
|
||||
|
||||
#define LD32I (LD32 | IMMED)
|
||||
#define LD8I (LD8 | IMMED)
|
||||
#define LD16I (LD16 | IMMED)
|
||||
#define LD64I (LD64 | IMMED)
|
||||
#define LDPTRI (LDPTR | IMMED)
|
||||
#define ST32I (ST32 | IMMED)
|
||||
|
||||
#define emit_nop() \
|
||||
do { \
|
||||
*prog++ = SETHI(0, G0); \
|
||||
} while (0)
|
||||
|
||||
#define emit_neg() \
|
||||
do { /* sub %g0, r_A, r_A */ \
|
||||
*prog++ = SUB | RS1(G0) | RS2(r_A) | RD(r_A); \
|
||||
} while (0)
|
||||
|
||||
#define emit_reg_move(FROM, TO) \
|
||||
do { /* or %g0, FROM, TO */ \
|
||||
*prog++ = OR | RS1(G0) | RS2(FROM) | RD(TO); \
|
||||
} while (0)
|
||||
|
||||
#define emit_clear(REG) \
|
||||
do { /* or %g0, %g0, REG */ \
|
||||
*prog++ = OR | RS1(G0) | RS2(G0) | RD(REG); \
|
||||
} while (0)
|
||||
|
||||
#define emit_set_const(K, REG) \
|
||||
do { /* sethi %hi(K), REG */ \
|
||||
*prog++ = SETHI(K, REG); \
|
||||
/* or REG, %lo(K), REG */ \
|
||||
*prog++ = OR_LO(K, REG); \
|
||||
} while (0)
|
||||
|
||||
/* Emit
|
||||
*
|
||||
* OP r_A, r_X, r_A
|
||||
*/
|
||||
#define emit_alu_X(OPCODE) \
|
||||
do { \
|
||||
seen |= SEEN_XREG; \
|
||||
*prog++ = OPCODE | RS1(r_A) | RS2(r_X) | RD(r_A); \
|
||||
} while (0)
|
||||
|
||||
/* Emit either:
|
||||
*
|
||||
* OP r_A, K, r_A
|
||||
*
|
||||
* or
|
||||
*
|
||||
* sethi %hi(K), r_TMP
|
||||
* or r_TMP, %lo(K), r_TMP
|
||||
* OP r_A, r_TMP, r_A
|
||||
*
|
||||
* depending upon whether K fits in a signed 13-bit
|
||||
* immediate instruction field. Emit nothing if K
|
||||
* is zero.
|
||||
*/
|
||||
#define emit_alu_K(OPCODE, K) \
|
||||
do { \
|
||||
if (K) { \
|
||||
unsigned int _insn = OPCODE; \
|
||||
_insn |= RS1(r_A) | RD(r_A); \
|
||||
if (is_simm13(K)) { \
|
||||
*prog++ = _insn | IMMED | S13(K); \
|
||||
} else { \
|
||||
emit_set_const(K, r_TMP); \
|
||||
*prog++ = _insn | RS2(r_TMP); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define emit_loadimm(K, DEST) \
|
||||
do { \
|
||||
if (is_simm13(K)) { \
|
||||
/* or %g0, K, DEST */ \
|
||||
*prog++ = OR | IMMED | RS1(G0) | S13(K) | RD(DEST); \
|
||||
} else { \
|
||||
emit_set_const(K, DEST); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define emit_loadptr(BASE, STRUCT, FIELD, DEST) \
|
||||
do { unsigned int _off = offsetof(STRUCT, FIELD); \
|
||||
BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(void *)); \
|
||||
*prog++ = LDPTRI | RS1(BASE) | S13(_off) | RD(DEST); \
|
||||
} while (0)
|
||||
|
||||
#define emit_load32(BASE, STRUCT, FIELD, DEST) \
|
||||
do { unsigned int _off = offsetof(STRUCT, FIELD); \
|
||||
BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u32)); \
|
||||
*prog++ = LD32I | RS1(BASE) | S13(_off) | RD(DEST); \
|
||||
} while (0)
|
||||
|
||||
#define emit_load16(BASE, STRUCT, FIELD, DEST) \
|
||||
do { unsigned int _off = offsetof(STRUCT, FIELD); \
|
||||
BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u16)); \
|
||||
*prog++ = LD16I | RS1(BASE) | S13(_off) | RD(DEST); \
|
||||
} while (0)
|
||||
|
||||
#define __emit_load8(BASE, STRUCT, FIELD, DEST) \
|
||||
do { unsigned int _off = offsetof(STRUCT, FIELD); \
|
||||
*prog++ = LD8I | RS1(BASE) | S13(_off) | RD(DEST); \
|
||||
} while (0)
|
||||
|
||||
#define emit_load8(BASE, STRUCT, FIELD, DEST) \
|
||||
do { BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u8)); \
|
||||
__emit_load8(BASE, STRUCT, FIELD, DEST); \
|
||||
} while (0)
|
||||
|
||||
#define emit_ldmem(OFF, DEST) \
|
||||
do { *prog++ = LD32I | RS1(FP) | S13(-(OFF)) | RD(DEST); \
|
||||
} while (0)
|
||||
|
||||
#define emit_stmem(OFF, SRC) \
|
||||
do { *prog++ = LD32I | RS1(FP) | S13(-(OFF)) | RD(SRC); \
|
||||
} while (0)
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#ifdef CONFIG_SPARC64
|
||||
#define emit_load_cpu(REG) \
|
||||
emit_load16(G6, struct thread_info, cpu, REG)
|
||||
#else
|
||||
#define emit_load_cpu(REG) \
|
||||
emit_load32(G6, struct thread_info, cpu, REG)
|
||||
#endif
|
||||
#else
|
||||
#define emit_load_cpu(REG) emit_clear(REG)
|
||||
#endif
|
||||
|
||||
#define emit_skb_loadptr(FIELD, DEST) \
|
||||
emit_loadptr(r_SKB, struct sk_buff, FIELD, DEST)
|
||||
#define emit_skb_load32(FIELD, DEST) \
|
||||
emit_load32(r_SKB, struct sk_buff, FIELD, DEST)
|
||||
#define emit_skb_load16(FIELD, DEST) \
|
||||
emit_load16(r_SKB, struct sk_buff, FIELD, DEST)
|
||||
#define __emit_skb_load8(FIELD, DEST) \
|
||||
__emit_load8(r_SKB, struct sk_buff, FIELD, DEST)
|
||||
#define emit_skb_load8(FIELD, DEST) \
|
||||
emit_load8(r_SKB, struct sk_buff, FIELD, DEST)
|
||||
|
||||
#define emit_jmpl(BASE, IMM_OFF, LREG) \
|
||||
*prog++ = (JMPL | IMMED | RS1(BASE) | S13(IMM_OFF) | RD(LREG))
|
||||
|
||||
#define emit_call(FUNC) \
|
||||
do { void *_here = image + addrs[i] - 8; \
|
||||
unsigned int _off = (void *)(FUNC) - _here; \
|
||||
*prog++ = CALL | (((_off) >> 2) & 0x3fffffff); \
|
||||
emit_nop(); \
|
||||
} while (0)
|
||||
|
||||
#define emit_branch(BR_OPC, DEST) \
|
||||
do { unsigned int _here = addrs[i] - 8; \
|
||||
*prog++ = BR_OPC | WDISP22((DEST) - _here); \
|
||||
} while (0)
|
||||
|
||||
#define emit_branch_off(BR_OPC, OFF) \
|
||||
do { *prog++ = BR_OPC | WDISP22(OFF); \
|
||||
} while (0)
|
||||
|
||||
#define emit_jump(DEST) emit_branch(BA, DEST)
|
||||
|
||||
#define emit_read_y(REG) *prog++ = RD_Y | RD(REG)
|
||||
#define emit_write_y(REG) *prog++ = WR_Y | IMMED | RS1(REG) | S13(0)
|
||||
|
||||
#define emit_cmp(R1, R2) \
|
||||
*prog++ = (SUBCC | RS1(R1) | RS2(R2) | RD(G0))
|
||||
|
||||
#define emit_cmpi(R1, IMM) \
|
||||
*prog++ = (SUBCC | IMMED | RS1(R1) | S13(IMM) | RD(G0));
|
||||
|
||||
#define emit_btst(R1, R2) \
|
||||
*prog++ = (ANDCC | RS1(R1) | RS2(R2) | RD(G0))
|
||||
|
||||
#define emit_btsti(R1, IMM) \
|
||||
*prog++ = (ANDCC | IMMED | RS1(R1) | S13(IMM) | RD(G0));
|
||||
|
||||
#define emit_sub(R1, R2, R3) \
|
||||
*prog++ = (SUB | RS1(R1) | RS2(R2) | RD(R3))
|
||||
|
||||
#define emit_subi(R1, IMM, R3) \
|
||||
*prog++ = (SUB | IMMED | RS1(R1) | S13(IMM) | RD(R3))
|
||||
|
||||
#define emit_add(R1, R2, R3) \
|
||||
*prog++ = (ADD | RS1(R1) | RS2(R2) | RD(R3))
|
||||
|
||||
#define emit_addi(R1, IMM, R3) \
|
||||
*prog++ = (ADD | IMMED | RS1(R1) | S13(IMM) | RD(R3))
|
||||
|
||||
#define emit_alloc_stack(SZ) \
|
||||
*prog++ = (SUB | IMMED | RS1(SP) | S13(SZ) | RD(SP))
|
||||
|
||||
#define emit_release_stack(SZ) \
|
||||
*prog++ = (ADD | IMMED | RS1(SP) | S13(SZ) | RD(SP))
|
||||
|
||||
/* A note about branch offset calculations. The addrs[] array,
|
||||
* indexed by BPF instruction, records the address after all the
|
||||
* sparc instructions emitted for that BPF instruction.
|
||||
*
|
||||
* The most common case is to emit a branch at the end of such
|
||||
* a code sequence. So this would be two instructions, the
|
||||
* branch and it's delay slot.
|
||||
*
|
||||
* Therefore by default the branch emitters calculate the branch
|
||||
* offset field as:
|
||||
*
|
||||
* destination - (addrs[i] - 8)
|
||||
*
|
||||
* This "addrs[i] - 8" is the address of the branch itself or
|
||||
* what "." would be in assembler notation. The "8" part is
|
||||
* how we take into consideration the branch and it's delay
|
||||
* slot mentioned above.
|
||||
*
|
||||
* Sometimes we need to emit a branch earlier in the code
|
||||
* sequence. And in these situations we adjust "destination"
|
||||
* to accomodate this difference. For example, if we needed
|
||||
* to emit a branch (and it's delay slot) right before the
|
||||
* final instruction emitted for a BPF opcode, we'd use
|
||||
* "destination + 4" instead of just plain "destination" above.
|
||||
*
|
||||
* This is why you see all of these funny emit_branch() and
|
||||
* emit_jump() calls with adjusted offsets.
|
||||
*/
|
||||
|
||||
void bpf_jit_compile(struct sk_filter *fp)
|
||||
{
|
||||
unsigned int cleanup_addr, proglen, oldproglen = 0;
|
||||
u32 temp[8], *prog, *func, seen = 0, pass;
|
||||
const struct sock_filter *filter = fp->insns;
|
||||
int i, flen = fp->len, pc_ret0 = -1;
|
||||
unsigned int *addrs;
|
||||
void *image;
|
||||
|
||||
if (!bpf_jit_enable)
|
||||
return;
|
||||
|
||||
addrs = kmalloc(flen * sizeof(*addrs), GFP_KERNEL);
|
||||
if (addrs == NULL)
|
||||
return;
|
||||
|
||||
/* Before first pass, make a rough estimation of addrs[]
|
||||
* each bpf instruction is translated to less than 64 bytes
|
||||
*/
|
||||
for (proglen = 0, i = 0; i < flen; i++) {
|
||||
proglen += 64;
|
||||
addrs[i] = proglen;
|
||||
}
|
||||
cleanup_addr = proglen; /* epilogue address */
|
||||
image = NULL;
|
||||
for (pass = 0; pass < 10; pass++) {
|
||||
u8 seen_or_pass0 = (pass == 0) ? (SEEN_XREG | SEEN_DATAREF | SEEN_MEM) : seen;
|
||||
|
||||
/* no prologue/epilogue for trivial filters (RET something) */
|
||||
proglen = 0;
|
||||
prog = temp;
|
||||
|
||||
/* Prologue */
|
||||
if (seen_or_pass0) {
|
||||
if (seen_or_pass0 & SEEN_MEM) {
|
||||
unsigned int sz = BASE_STACKFRAME;
|
||||
sz += BPF_MEMWORDS * sizeof(u32);
|
||||
emit_alloc_stack(sz);
|
||||
}
|
||||
|
||||
/* Make sure we dont leek kernel memory. */
|
||||
if (seen_or_pass0 & SEEN_XREG)
|
||||
emit_clear(r_X);
|
||||
|
||||
/* If this filter needs to access skb data,
|
||||
* load %o4 and %o5 with:
|
||||
* %o4 = skb->len - skb->data_len
|
||||
* %o5 = skb->data
|
||||
* And also back up %o7 into r_saved_O7 so we can
|
||||
* invoke the stubs using 'call'.
|
||||
*/
|
||||
if (seen_or_pass0 & SEEN_DATAREF) {
|
||||
emit_load32(r_SKB, struct sk_buff, len, r_HEADLEN);
|
||||
emit_load32(r_SKB, struct sk_buff, data_len, r_TMP);
|
||||
emit_sub(r_HEADLEN, r_TMP, r_HEADLEN);
|
||||
emit_loadptr(r_SKB, struct sk_buff, data, r_SKB_DATA);
|
||||
}
|
||||
}
|
||||
emit_reg_move(O7, r_saved_O7);
|
||||
|
||||
switch (filter[0].code) {
|
||||
case BPF_S_RET_K:
|
||||
case BPF_S_LD_W_LEN:
|
||||
case BPF_S_ANC_PROTOCOL:
|
||||
case BPF_S_ANC_PKTTYPE:
|
||||
case BPF_S_ANC_IFINDEX:
|
||||
case BPF_S_ANC_MARK:
|
||||
case BPF_S_ANC_RXHASH:
|
||||
case BPF_S_ANC_CPU:
|
||||
case BPF_S_ANC_QUEUE:
|
||||
case BPF_S_LD_W_ABS:
|
||||
case BPF_S_LD_H_ABS:
|
||||
case BPF_S_LD_B_ABS:
|
||||
/* The first instruction sets the A register (or is
|
||||
* a "RET 'constant'")
|
||||
*/
|
||||
break;
|
||||
default:
|
||||
/* Make sure we dont leak kernel information to the
|
||||
* user.
|
||||
*/
|
||||
emit_clear(r_A); /* A = 0 */
|
||||
}
|
||||
|
||||
for (i = 0; i < flen; i++) {
|
||||
unsigned int K = filter[i].k;
|
||||
unsigned int t_offset;
|
||||
unsigned int f_offset;
|
||||
u32 t_op, f_op;
|
||||
int ilen;
|
||||
|
||||
switch (filter[i].code) {
|
||||
case BPF_S_ALU_ADD_X: /* A += X; */
|
||||
emit_alu_X(ADD);
|
||||
break;
|
||||
case BPF_S_ALU_ADD_K: /* A += K; */
|
||||
emit_alu_K(ADD, K);
|
||||
break;
|
||||
case BPF_S_ALU_SUB_X: /* A -= X; */
|
||||
emit_alu_X(SUB);
|
||||
break;
|
||||
case BPF_S_ALU_SUB_K: /* A -= K */
|
||||
emit_alu_K(SUB, K);
|
||||
break;
|
||||
case BPF_S_ALU_AND_X: /* A &= X */
|
||||
emit_alu_X(AND);
|
||||
break;
|
||||
case BPF_S_ALU_AND_K: /* A &= K */
|
||||
emit_alu_K(AND, K);
|
||||
break;
|
||||
case BPF_S_ALU_OR_X: /* A |= X */
|
||||
emit_alu_X(OR);
|
||||
break;
|
||||
case BPF_S_ALU_OR_K: /* A |= K */
|
||||
emit_alu_K(OR, K);
|
||||
break;
|
||||
case BPF_S_ALU_LSH_X: /* A <<= X */
|
||||
emit_alu_X(SLL);
|
||||
break;
|
||||
case BPF_S_ALU_LSH_K: /* A <<= K */
|
||||
emit_alu_K(SLL, K);
|
||||
break;
|
||||
case BPF_S_ALU_RSH_X: /* A >>= X */
|
||||
emit_alu_X(SRL);
|
||||
break;
|
||||
case BPF_S_ALU_RSH_K: /* A >>= K */
|
||||
emit_alu_K(SRL, K);
|
||||
break;
|
||||
case BPF_S_ALU_MUL_X: /* A *= X; */
|
||||
emit_alu_X(MUL);
|
||||
break;
|
||||
case BPF_S_ALU_MUL_K: /* A *= K */
|
||||
emit_alu_K(MUL, K);
|
||||
break;
|
||||
case BPF_S_ALU_DIV_K: /* A /= K */
|
||||
emit_alu_K(MUL, K);
|
||||
emit_read_y(r_A);
|
||||
break;
|
||||
case BPF_S_ALU_DIV_X: /* A /= X; */
|
||||
emit_cmpi(r_X, 0);
|
||||
if (pc_ret0 > 0) {
|
||||
t_offset = addrs[pc_ret0 - 1];
|
||||
#ifdef CONFIG_SPARC32
|
||||
emit_branch(BE, t_offset + 20);
|
||||
#else
|
||||
emit_branch(BE, t_offset + 8);
|
||||
#endif
|
||||
emit_nop(); /* delay slot */
|
||||
} else {
|
||||
emit_branch_off(BNE, 16);
|
||||
emit_nop();
|
||||
#ifdef CONFIG_SPARC32
|
||||
emit_jump(cleanup_addr + 20);
|
||||
#else
|
||||
emit_jump(cleanup_addr + 8);
|
||||
#endif
|
||||
emit_clear(r_A);
|
||||
}
|
||||
emit_write_y(G0);
|
||||
#ifdef CONFIG_SPARC32
|
||||
/* The Sparc v8 architecture requires
|
||||
* three instructions between a %y
|
||||
* register write and the first use.
|
||||
*/
|
||||
emit_nop();
|
||||
emit_nop();
|
||||
emit_nop();
|
||||
#endif
|
||||
emit_alu_X(DIV);
|
||||
break;
|
||||
case BPF_S_ALU_NEG:
|
||||
emit_neg();
|
||||
break;
|
||||
case BPF_S_RET_K:
|
||||
if (!K) {
|
||||
if (pc_ret0 == -1)
|
||||
pc_ret0 = i;
|
||||
emit_clear(r_A);
|
||||
} else {
|
||||
emit_loadimm(K, r_A);
|
||||
}
|
||||
/* Fallthrough */
|
||||
case BPF_S_RET_A:
|
||||
if (seen_or_pass0) {
|
||||
if (i != flen - 1) {
|
||||
emit_jump(cleanup_addr);
|
||||
emit_nop();
|
||||
break;
|
||||
}
|
||||
if (seen_or_pass0 & SEEN_MEM) {
|
||||
unsigned int sz = BASE_STACKFRAME;
|
||||
sz += BPF_MEMWORDS * sizeof(u32);
|
||||
emit_release_stack(sz);
|
||||
}
|
||||
}
|
||||
/* jmpl %r_saved_O7 + 8, %g0 */
|
||||
emit_jmpl(r_saved_O7, 8, G0);
|
||||
emit_reg_move(r_A, O0); /* delay slot */
|
||||
break;
|
||||
case BPF_S_MISC_TAX:
|
||||
seen |= SEEN_XREG;
|
||||
emit_reg_move(r_A, r_X);
|
||||
break;
|
||||
case BPF_S_MISC_TXA:
|
||||
seen |= SEEN_XREG;
|
||||
emit_reg_move(r_X, r_A);
|
||||
break;
|
||||
case BPF_S_ANC_CPU:
|
||||
emit_load_cpu(r_A);
|
||||
break;
|
||||
case BPF_S_ANC_PROTOCOL:
|
||||
emit_skb_load16(protocol, r_A);
|
||||
break;
|
||||
#if 0
|
||||
/* GCC won't let us take the address of
|
||||
* a bit field even though we very much
|
||||
* know what we are doing here.
|
||||
*/
|
||||
case BPF_S_ANC_PKTTYPE:
|
||||
__emit_skb_load8(pkt_type, r_A);
|
||||
emit_alu_K(SRL, 5);
|
||||
break;
|
||||
#endif
|
||||
case BPF_S_ANC_IFINDEX:
|
||||
emit_skb_loadptr(dev, r_A);
|
||||
emit_cmpi(r_A, 0);
|
||||
emit_branch(BNE_PTR, cleanup_addr + 4);
|
||||
emit_nop();
|
||||
emit_load32(r_A, struct net_device, ifindex, r_A);
|
||||
break;
|
||||
case BPF_S_ANC_MARK:
|
||||
emit_skb_load32(mark, r_A);
|
||||
break;
|
||||
case BPF_S_ANC_QUEUE:
|
||||
emit_skb_load16(queue_mapping, r_A);
|
||||
break;
|
||||
case BPF_S_ANC_HATYPE:
|
||||
emit_skb_loadptr(dev, r_A);
|
||||
emit_cmpi(r_A, 0);
|
||||
emit_branch(BNE_PTR, cleanup_addr + 4);
|
||||
emit_nop();
|
||||
emit_load16(r_A, struct net_device, type, r_A);
|
||||
break;
|
||||
case BPF_S_ANC_RXHASH:
|
||||
emit_skb_load32(rxhash, r_A);
|
||||
break;
|
||||
|
||||
case BPF_S_LD_IMM:
|
||||
emit_loadimm(K, r_A);
|
||||
break;
|
||||
case BPF_S_LDX_IMM:
|
||||
emit_loadimm(K, r_X);
|
||||
break;
|
||||
case BPF_S_LD_MEM:
|
||||
emit_ldmem(K * 4, r_A);
|
||||
break;
|
||||
case BPF_S_LDX_MEM:
|
||||
emit_ldmem(K * 4, r_X);
|
||||
break;
|
||||
case BPF_S_ST:
|
||||
emit_stmem(K * 4, r_A);
|
||||
break;
|
||||
case BPF_S_STX:
|
||||
emit_stmem(K * 4, r_X);
|
||||
break;
|
||||
|
||||
#define CHOOSE_LOAD_FUNC(K, func) \
|
||||
((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset)
|
||||
|
||||
case BPF_S_LD_W_ABS:
|
||||
func = CHOOSE_LOAD_FUNC(K, bpf_jit_load_word);
|
||||
common_load: seen |= SEEN_DATAREF;
|
||||
emit_loadimm(K, r_OFF);
|
||||
emit_call(func);
|
||||
break;
|
||||
case BPF_S_LD_H_ABS:
|
||||
func = CHOOSE_LOAD_FUNC(K, bpf_jit_load_half);
|
||||
goto common_load;
|
||||
case BPF_S_LD_B_ABS:
|
||||
func = CHOOSE_LOAD_FUNC(K, bpf_jit_load_byte);
|
||||
goto common_load;
|
||||
case BPF_S_LDX_B_MSH:
|
||||
func = CHOOSE_LOAD_FUNC(K, bpf_jit_load_byte_msh);
|
||||
goto common_load;
|
||||
case BPF_S_LD_W_IND:
|
||||
func = bpf_jit_load_word;
|
||||
common_load_ind: seen |= SEEN_DATAREF | SEEN_XREG;
|
||||
if (K) {
|
||||
if (is_simm13(K)) {
|
||||
emit_addi(r_X, K, r_OFF);
|
||||
} else {
|
||||
emit_loadimm(K, r_TMP);
|
||||
emit_add(r_X, r_TMP, r_OFF);
|
||||
}
|
||||
} else {
|
||||
emit_reg_move(r_X, r_OFF);
|
||||
}
|
||||
emit_call(func);
|
||||
break;
|
||||
case BPF_S_LD_H_IND:
|
||||
func = bpf_jit_load_half;
|
||||
goto common_load_ind;
|
||||
case BPF_S_LD_B_IND:
|
||||
func = bpf_jit_load_byte;
|
||||
goto common_load_ind;
|
||||
case BPF_S_JMP_JA:
|
||||
emit_jump(addrs[i + K]);
|
||||
emit_nop();
|
||||
break;
|
||||
|
||||
#define COND_SEL(CODE, TOP, FOP) \
|
||||
case CODE: \
|
||||
t_op = TOP; \
|
||||
f_op = FOP; \
|
||||
goto cond_branch
|
||||
|
||||
COND_SEL(BPF_S_JMP_JGT_K, BGU, BLEU);
|
||||
COND_SEL(BPF_S_JMP_JGE_K, BGEU, BLU);
|
||||
COND_SEL(BPF_S_JMP_JEQ_K, BE, BNE);
|
||||
COND_SEL(BPF_S_JMP_JSET_K, BNE, BE);
|
||||
COND_SEL(BPF_S_JMP_JGT_X, BGU, BLEU);
|
||||
COND_SEL(BPF_S_JMP_JGE_X, BGEU, BLU);
|
||||
COND_SEL(BPF_S_JMP_JEQ_X, BE, BNE);
|
||||
COND_SEL(BPF_S_JMP_JSET_X, BNE, BE);
|
||||
|
||||
cond_branch: f_offset = addrs[i + filter[i].jf];
|
||||
t_offset = addrs[i + filter[i].jt];
|
||||
|
||||
/* same targets, can avoid doing the test :) */
|
||||
if (filter[i].jt == filter[i].jf) {
|
||||
emit_jump(t_offset);
|
||||
emit_nop();
|
||||
break;
|
||||
}
|
||||
|
||||
switch (filter[i].code) {
|
||||
case BPF_S_JMP_JGT_X:
|
||||
case BPF_S_JMP_JGE_X:
|
||||
case BPF_S_JMP_JEQ_X:
|
||||
seen |= SEEN_XREG;
|
||||
emit_cmp(r_A, r_X);
|
||||
break;
|
||||
case BPF_S_JMP_JSET_X:
|
||||
seen |= SEEN_XREG;
|
||||
emit_btst(r_A, r_X);
|
||||
break;
|
||||
case BPF_S_JMP_JEQ_K:
|
||||
case BPF_S_JMP_JGT_K:
|
||||
case BPF_S_JMP_JGE_K:
|
||||
if (is_simm13(K)) {
|
||||
emit_cmpi(r_A, K);
|
||||
} else {
|
||||
emit_loadimm(K, r_TMP);
|
||||
emit_cmp(r_A, r_TMP);
|
||||
}
|
||||
break;
|
||||
case BPF_S_JMP_JSET_K:
|
||||
if (is_simm13(K)) {
|
||||
emit_btsti(r_A, K);
|
||||
} else {
|
||||
emit_loadimm(K, r_TMP);
|
||||
emit_btst(r_A, r_TMP);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (filter[i].jt != 0) {
|
||||
if (filter[i].jf)
|
||||
t_offset += 8;
|
||||
emit_branch(t_op, t_offset);
|
||||
emit_nop(); /* delay slot */
|
||||
if (filter[i].jf) {
|
||||
emit_jump(f_offset);
|
||||
emit_nop();
|
||||
}
|
||||
break;
|
||||
}
|
||||
emit_branch(f_op, f_offset);
|
||||
emit_nop(); /* delay slot */
|
||||
break;
|
||||
|
||||
default:
|
||||
/* hmm, too complex filter, give up with jit compiler */
|
||||
goto out;
|
||||
}
|
||||
ilen = (void *) prog - (void *) temp;
|
||||
if (image) {
|
||||
if (unlikely(proglen + ilen > oldproglen)) {
|
||||
pr_err("bpb_jit_compile fatal error\n");
|
||||
kfree(addrs);
|
||||
module_free(NULL, image);
|
||||
return;
|
||||
}
|
||||
memcpy(image + proglen, temp, ilen);
|
||||
}
|
||||
proglen += ilen;
|
||||
addrs[i] = proglen;
|
||||
prog = temp;
|
||||
}
|
||||
/* last bpf instruction is always a RET :
|
||||
* use it to give the cleanup instruction(s) addr
|
||||
*/
|
||||
cleanup_addr = proglen - 8; /* jmpl; mov r_A,%o0; */
|
||||
if (seen_or_pass0 & SEEN_MEM)
|
||||
cleanup_addr -= 4; /* add %sp, X, %sp; */
|
||||
|
||||
if (image) {
|
||||
if (proglen != oldproglen)
|
||||
pr_err("bpb_jit_compile proglen=%u != oldproglen=%u\n",
|
||||
proglen, oldproglen);
|
||||
break;
|
||||
}
|
||||
if (proglen == oldproglen) {
|
||||
image = module_alloc(max_t(unsigned int,
|
||||
proglen,
|
||||
sizeof(struct work_struct)));
|
||||
if (!image)
|
||||
goto out;
|
||||
}
|
||||
oldproglen = proglen;
|
||||
}
|
||||
|
||||
if (bpf_jit_enable > 1)
|
||||
pr_err("flen=%d proglen=%u pass=%d image=%p\n",
|
||||
flen, proglen, pass, image);
|
||||
|
||||
if (image) {
|
||||
if (bpf_jit_enable > 1)
|
||||
print_hex_dump(KERN_ERR, "JIT code: ", DUMP_PREFIX_ADDRESS,
|
||||
16, 1, image, proglen, false);
|
||||
bpf_flush_icache(image, image + proglen);
|
||||
fp->bpf_func = (void *)image;
|
||||
}
|
||||
out:
|
||||
kfree(addrs);
|
||||
return;
|
||||
}
|
||||
|
||||
static void jit_free_defer(struct work_struct *arg)
|
||||
{
|
||||
module_free(NULL, arg);
|
||||
}
|
||||
|
||||
/* run from softirq, we must use a work_struct to call
|
||||
* module_free() from process context
|
||||
*/
|
||||
void bpf_jit_free(struct sk_filter *fp)
|
||||
{
|
||||
if (fp->bpf_func != sk_run_filter) {
|
||||
struct work_struct *work = (struct work_struct *)fp->bpf_func;
|
||||
|
||||
INIT_WORK(work, jit_free_defer);
|
||||
schedule_work(work);
|
||||
}
|
||||
}
|
|
@ -332,11 +332,6 @@ CONFIG_XT2000_SONIC=y
|
|||
# CONFIG_IXGB is not set
|
||||
# CONFIG_S2IO is not set
|
||||
|
||||
#
|
||||
# Token Ring devices
|
||||
#
|
||||
# CONFIG_TR is not set
|
||||
|
||||
#
|
||||
# Wireless LAN (non-hamradio)
|
||||
#
|
||||
|
|
|
@ -397,9 +397,9 @@ static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
|
|||
rblkcipher.max_keysize = alg->cra_ablkcipher.max_keysize;
|
||||
rblkcipher.ivsize = alg->cra_ablkcipher.ivsize;
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
|
||||
sizeof(struct crypto_report_blkcipher), &rblkcipher);
|
||||
|
||||
if (nla_put(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
|
||||
sizeof(struct crypto_report_blkcipher), &rblkcipher))
|
||||
goto nla_put_failure;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
|
@ -478,9 +478,9 @@ static int crypto_givcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
|
|||
rblkcipher.max_keysize = alg->cra_ablkcipher.max_keysize;
|
||||
rblkcipher.ivsize = alg->cra_ablkcipher.ivsize;
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
|
||||
sizeof(struct crypto_report_blkcipher), &rblkcipher);
|
||||
|
||||
if (nla_put(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
|
||||
sizeof(struct crypto_report_blkcipher), &rblkcipher))
|
||||
goto nla_put_failure;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
|
|
|
@ -125,9 +125,9 @@ static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
|
|||
raead.maxauthsize = aead->maxauthsize;
|
||||
raead.ivsize = aead->ivsize;
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_AEAD,
|
||||
sizeof(struct crypto_report_aead), &raead);
|
||||
|
||||
if (nla_put(skb, CRYPTOCFGA_REPORT_AEAD,
|
||||
sizeof(struct crypto_report_aead), &raead))
|
||||
goto nla_put_failure;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
|
@ -210,9 +210,9 @@ static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg)
|
|||
raead.maxauthsize = aead->maxauthsize;
|
||||
raead.ivsize = aead->ivsize;
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_AEAD,
|
||||
sizeof(struct crypto_report_aead), &raead);
|
||||
|
||||
if (nla_put(skb, CRYPTOCFGA_REPORT_AEAD,
|
||||
sizeof(struct crypto_report_aead), &raead))
|
||||
goto nla_put_failure;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
|
|
|
@ -409,9 +409,9 @@ static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg)
|
|||
rhash.blocksize = alg->cra_blocksize;
|
||||
rhash.digestsize = __crypto_hash_alg_common(alg)->digestsize;
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_HASH,
|
||||
sizeof(struct crypto_report_hash), &rhash);
|
||||
|
||||
if (nla_put(skb, CRYPTOCFGA_REPORT_HASH,
|
||||
sizeof(struct crypto_report_hash), &rhash))
|
||||
goto nla_put_failure;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
|
|
|
@ -508,9 +508,9 @@ static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
|
|||
rblkcipher.max_keysize = alg->cra_blkcipher.max_keysize;
|
||||
rblkcipher.ivsize = alg->cra_blkcipher.ivsize;
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
|
||||
sizeof(struct crypto_report_blkcipher), &rblkcipher);
|
||||
|
||||
if (nla_put(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
|
||||
sizeof(struct crypto_report_blkcipher), &rblkcipher))
|
||||
goto nla_put_failure;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
|
|
|
@ -81,9 +81,9 @@ static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg)
|
|||
rcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
|
||||
rcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_CIPHER,
|
||||
sizeof(struct crypto_report_cipher), &rcipher);
|
||||
|
||||
if (nla_put(skb, CRYPTOCFGA_REPORT_CIPHER,
|
||||
sizeof(struct crypto_report_cipher), &rcipher))
|
||||
goto nla_put_failure;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
|
@ -96,9 +96,9 @@ static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg)
|
|||
|
||||
snprintf(rcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "compression");
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_COMPRESS,
|
||||
sizeof(struct crypto_report_comp), &rcomp);
|
||||
|
||||
if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS,
|
||||
sizeof(struct crypto_report_comp), &rcomp))
|
||||
goto nla_put_failure;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
|
@ -117,16 +117,16 @@ static int crypto_report_one(struct crypto_alg *alg,
|
|||
ualg->cru_flags = alg->cra_flags;
|
||||
ualg->cru_refcnt = atomic_read(&alg->cra_refcnt);
|
||||
|
||||
NLA_PUT_U32(skb, CRYPTOCFGA_PRIORITY_VAL, alg->cra_priority);
|
||||
|
||||
if (nla_put_u32(skb, CRYPTOCFGA_PRIORITY_VAL, alg->cra_priority))
|
||||
goto nla_put_failure;
|
||||
if (alg->cra_flags & CRYPTO_ALG_LARVAL) {
|
||||
struct crypto_report_larval rl;
|
||||
|
||||
snprintf(rl.type, CRYPTO_MAX_ALG_NAME, "%s", "larval");
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_LARVAL,
|
||||
sizeof(struct crypto_report_larval), &rl);
|
||||
|
||||
if (nla_put(skb, CRYPTOCFGA_REPORT_LARVAL,
|
||||
sizeof(struct crypto_report_larval), &rl))
|
||||
goto nla_put_failure;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,9 +55,9 @@ static int crypto_pcomp_report(struct sk_buff *skb, struct crypto_alg *alg)
|
|||
|
||||
snprintf(rpcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "pcomp");
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_COMPRESS,
|
||||
sizeof(struct crypto_report_comp), &rpcomp);
|
||||
|
||||
if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS,
|
||||
sizeof(struct crypto_report_comp), &rpcomp))
|
||||
goto nla_put_failure;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
|
|
|
@ -69,9 +69,9 @@ static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
|
|||
|
||||
rrng.seedsize = alg->cra_rng.seedsize;
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_RNG,
|
||||
sizeof(struct crypto_report_rng), &rrng);
|
||||
|
||||
if (nla_put(skb, CRYPTOCFGA_REPORT_RNG,
|
||||
sizeof(struct crypto_report_rng), &rrng))
|
||||
goto nla_put_failure;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
|
|
|
@ -534,9 +534,9 @@ static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
|
|||
rhash.blocksize = alg->cra_blocksize;
|
||||
rhash.digestsize = salg->digestsize;
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_HASH,
|
||||
sizeof(struct crypto_report_hash), &rhash);
|
||||
|
||||
if (nla_put(skb, CRYPTOCFGA_REPORT_HASH,
|
||||
sizeof(struct crypto_report_hash), &rhash))
|
||||
goto nla_put_failure;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
|
|
|
@ -802,7 +802,7 @@ static void fill_rx_pool (amb_dev * dev, unsigned char pool,
|
|||
}
|
||||
// cast needed as there is no %? for pointer differences
|
||||
PRINTD (DBG_SKB, "allocated skb at %p, head %p, area %li",
|
||||
skb, skb->head, (long) (skb_end_pointer(skb) - skb->head));
|
||||
skb, skb->head, (long) skb_end_offset(skb));
|
||||
rx.handle = virt_to_bus (skb);
|
||||
rx.host_address = cpu_to_be32 (virt_to_bus (skb->data));
|
||||
if (rx_give (dev, &rx, pool))
|
||||
|
|
|
@ -2182,7 +2182,6 @@ static int hrz_open (struct atm_vcc *atm_vcc)
|
|||
default:
|
||||
PRINTD (DBG_QOS|DBG_VCC, "Bad AAL!");
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
// TX traffic parameters
|
||||
|
@ -2357,7 +2356,6 @@ static int hrz_open (struct atm_vcc *atm_vcc)
|
|||
default: {
|
||||
PRINTD (DBG_QOS, "unsupported TX traffic class");
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2433,7 +2431,6 @@ static int hrz_open (struct atm_vcc *atm_vcc)
|
|||
default: {
|
||||
PRINTD (DBG_QOS, "unsupported RX traffic class");
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2581,7 +2578,6 @@ static int hrz_getsockopt (struct atm_vcc * atm_vcc, int level, int optname,
|
|||
// break;
|
||||
default:
|
||||
return -ENOPROTOOPT;
|
||||
break;
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
@ -2601,7 +2597,6 @@ static int hrz_setsockopt (struct atm_vcc * atm_vcc, int level, int optname,
|
|||
// break;
|
||||
default:
|
||||
return -ENOPROTOOPT;
|
||||
break;
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1258,7 +1258,7 @@ idt77252_rx_raw(struct idt77252_dev *card)
|
|||
tail = readl(SAR_REG_RAWCT);
|
||||
|
||||
pci_dma_sync_single_for_cpu(card->pcidev, IDT77252_PRV_PADDR(queue),
|
||||
skb_end_pointer(queue) - queue->head - 16,
|
||||
skb_end_offset(queue) - 16,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
|
||||
while (head != tail) {
|
||||
|
|
|
@ -664,7 +664,7 @@ static struct socket *drbd_wait_for_connect(struct drbd_conf *mdev)
|
|||
timeo = mdev->net_conf->try_connect_int * HZ;
|
||||
timeo += (random32() & 1) ? timeo / 7 : -timeo / 7; /* 28.5% random jitter */
|
||||
|
||||
s_listen->sk->sk_reuse = 1; /* SO_REUSEADDR */
|
||||
s_listen->sk->sk_reuse = SK_CAN_REUSE; /* SO_REUSEADDR */
|
||||
s_listen->sk->sk_rcvtimeo = timeo;
|
||||
s_listen->sk->sk_sndtimeo = timeo;
|
||||
drbd_setbufsize(s_listen, mdev->net_conf->sndbuf_size,
|
||||
|
@ -841,8 +841,8 @@ retry:
|
|||
}
|
||||
} while (1);
|
||||
|
||||
msock->sk->sk_reuse = 1; /* SO_REUSEADDR */
|
||||
sock->sk->sk_reuse = 1; /* SO_REUSEADDR */
|
||||
msock->sk->sk_reuse = SK_CAN_REUSE; /* SO_REUSEADDR */
|
||||
sock->sk->sk_reuse = SK_CAN_REUSE; /* SO_REUSEADDR */
|
||||
|
||||
sock->sk->sk_allocation = GFP_NOIO;
|
||||
msock->sk->sk_allocation = GFP_NOIO;
|
||||
|
|
|
@ -30,37 +30,6 @@
|
|||
#include "hyperv_vmbus.h"
|
||||
|
||||
|
||||
/* #defines */
|
||||
|
||||
|
||||
/* Amount of space to write to */
|
||||
#define BYTES_AVAIL_TO_WRITE(r, w, z) \
|
||||
((w) >= (r)) ? ((z) - ((w) - (r))) : ((r) - (w))
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* hv_get_ringbuffer_availbytes()
|
||||
*
|
||||
* Get number of bytes available to read and to write to
|
||||
* for the specified ring buffer
|
||||
*/
|
||||
static inline void
|
||||
hv_get_ringbuffer_availbytes(struct hv_ring_buffer_info *rbi,
|
||||
u32 *read, u32 *write)
|
||||
{
|
||||
u32 read_loc, write_loc;
|
||||
|
||||
smp_read_barrier_depends();
|
||||
|
||||
/* Capture the read/write indices before they changed */
|
||||
read_loc = rbi->ring_buffer->read_index;
|
||||
write_loc = rbi->ring_buffer->write_index;
|
||||
|
||||
*write = BYTES_AVAIL_TO_WRITE(read_loc, write_loc, rbi->ring_datasize);
|
||||
*read = rbi->ring_datasize - *write;
|
||||
}
|
||||
|
||||
/*
|
||||
* hv_get_next_write_location()
|
||||
*
|
||||
|
|
|
@ -19,4 +19,12 @@ config IEEE802154_FAKEHARD
|
|||
|
||||
This driver can also be built as a module. To do so say M here.
|
||||
The module will be called 'fakehard'.
|
||||
config IEEE802154_FAKELB
|
||||
depends on IEEE802154_DRIVERS && MAC802154
|
||||
tristate "IEEE 802.15.4 loopback driver"
|
||||
---help---
|
||||
Say Y here to enable the fake driver that can emulate a net
|
||||
of several interconnected radio devices.
|
||||
|
||||
This driver can also be built as a module. To do so say M here.
|
||||
The module will be called 'fakelb'.
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
obj-$(CONFIG_IEEE802154_FAKEHARD) += fakehard.o
|
||||
obj-$(CONFIG_IEEE802154_FAKELB) += fakelb.o
|
||||
|
|
294
drivers/ieee802154/fakelb.c
Normal file
294
drivers/ieee802154/fakelb.c
Normal file
|
@ -0,0 +1,294 @@
|
|||
/*
|
||||
* Loopback IEEE 802.15.4 interface
|
||||
*
|
||||
* Copyright 2007-2012 Siemens AG
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Written by:
|
||||
* Sergey Lapin <slapin@ossfans.org>
|
||||
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
|
||||
* Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <net/mac802154.h>
|
||||
#include <net/wpan-phy.h>
|
||||
|
||||
static int numlbs = 1;
|
||||
|
||||
struct fakelb_dev_priv {
|
||||
struct ieee802154_dev *dev;
|
||||
|
||||
struct list_head list;
|
||||
struct fakelb_priv *fake;
|
||||
|
||||
spinlock_t lock;
|
||||
bool working;
|
||||
};
|
||||
|
||||
struct fakelb_priv {
|
||||
struct list_head list;
|
||||
rwlock_t lock;
|
||||
};
|
||||
|
||||
static int
|
||||
fakelb_hw_ed(struct ieee802154_dev *dev, u8 *level)
|
||||
{
|
||||
might_sleep();
|
||||
BUG_ON(!level);
|
||||
*level = 0xbe;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
fakelb_hw_channel(struct ieee802154_dev *dev, int page, int channel)
|
||||
{
|
||||
pr_debug("set channel to %d\n", channel);
|
||||
|
||||
might_sleep();
|
||||
dev->phy->current_page = page;
|
||||
dev->phy->current_channel = channel;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
fakelb_hw_deliver(struct fakelb_dev_priv *priv, struct sk_buff *skb)
|
||||
{
|
||||
struct sk_buff *newskb;
|
||||
|
||||
spin_lock(&priv->lock);
|
||||
if (priv->working) {
|
||||
newskb = pskb_copy(skb, GFP_ATOMIC);
|
||||
ieee802154_rx_irqsafe(priv->dev, newskb, 0xcc);
|
||||
}
|
||||
spin_unlock(&priv->lock);
|
||||
}
|
||||
|
||||
static int
|
||||
fakelb_hw_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct fakelb_dev_priv *priv = dev->priv;
|
||||
struct fakelb_priv *fake = priv->fake;
|
||||
|
||||
might_sleep();
|
||||
|
||||
read_lock_bh(&fake->lock);
|
||||
if (priv->list.next == priv->list.prev) {
|
||||
/* we are the only one device */
|
||||
fakelb_hw_deliver(priv, skb);
|
||||
} else {
|
||||
struct fakelb_dev_priv *dp;
|
||||
list_for_each_entry(dp, &priv->fake->list, list) {
|
||||
if (dp != priv &&
|
||||
(dp->dev->phy->current_channel ==
|
||||
priv->dev->phy->current_channel))
|
||||
fakelb_hw_deliver(dp, skb);
|
||||
}
|
||||
}
|
||||
read_unlock_bh(&fake->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
fakelb_hw_start(struct ieee802154_dev *dev) {
|
||||
struct fakelb_dev_priv *priv = dev->priv;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock(&priv->lock);
|
||||
if (priv->working)
|
||||
ret = -EBUSY;
|
||||
else
|
||||
priv->working = 1;
|
||||
spin_unlock(&priv->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
fakelb_hw_stop(struct ieee802154_dev *dev) {
|
||||
struct fakelb_dev_priv *priv = dev->priv;
|
||||
|
||||
spin_lock(&priv->lock);
|
||||
priv->working = 0;
|
||||
spin_unlock(&priv->lock);
|
||||
}
|
||||
|
||||
static struct ieee802154_ops fakelb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.xmit = fakelb_hw_xmit,
|
||||
.ed = fakelb_hw_ed,
|
||||
.set_channel = fakelb_hw_channel,
|
||||
.start = fakelb_hw_start,
|
||||
.stop = fakelb_hw_stop,
|
||||
};
|
||||
|
||||
/* Number of dummy devices to be set up by this module. */
|
||||
module_param(numlbs, int, 0);
|
||||
MODULE_PARM_DESC(numlbs, " number of pseudo devices");
|
||||
|
||||
static int fakelb_add_one(struct device *dev, struct fakelb_priv *fake)
|
||||
{
|
||||
struct fakelb_dev_priv *priv;
|
||||
int err;
|
||||
struct ieee802154_dev *ieee;
|
||||
|
||||
ieee = ieee802154_alloc_device(sizeof(*priv), &fakelb_ops);
|
||||
if (!ieee)
|
||||
return -ENOMEM;
|
||||
|
||||
priv = ieee->priv;
|
||||
priv->dev = ieee;
|
||||
|
||||
/* 868 MHz BPSK 802.15.4-2003 */
|
||||
ieee->phy->channels_supported[0] |= 1;
|
||||
/* 915 MHz BPSK 802.15.4-2003 */
|
||||
ieee->phy->channels_supported[0] |= 0x7fe;
|
||||
/* 2.4 GHz O-QPSK 802.15.4-2003 */
|
||||
ieee->phy->channels_supported[0] |= 0x7FFF800;
|
||||
/* 868 MHz ASK 802.15.4-2006 */
|
||||
ieee->phy->channels_supported[1] |= 1;
|
||||
/* 915 MHz ASK 802.15.4-2006 */
|
||||
ieee->phy->channels_supported[1] |= 0x7fe;
|
||||
/* 868 MHz O-QPSK 802.15.4-2006 */
|
||||
ieee->phy->channels_supported[2] |= 1;
|
||||
/* 915 MHz O-QPSK 802.15.4-2006 */
|
||||
ieee->phy->channels_supported[2] |= 0x7fe;
|
||||
/* 2.4 GHz CSS 802.15.4a-2007 */
|
||||
ieee->phy->channels_supported[3] |= 0x3fff;
|
||||
/* UWB Sub-gigahertz 802.15.4a-2007 */
|
||||
ieee->phy->channels_supported[4] |= 1;
|
||||
/* UWB Low band 802.15.4a-2007 */
|
||||
ieee->phy->channels_supported[4] |= 0x1e;
|
||||
/* UWB High band 802.15.4a-2007 */
|
||||
ieee->phy->channels_supported[4] |= 0xffe0;
|
||||
/* 750 MHz O-QPSK 802.15.4c-2009 */
|
||||
ieee->phy->channels_supported[5] |= 0xf;
|
||||
/* 750 MHz MPSK 802.15.4c-2009 */
|
||||
ieee->phy->channels_supported[5] |= 0xf0;
|
||||
/* 950 MHz BPSK 802.15.4d-2009 */
|
||||
ieee->phy->channels_supported[6] |= 0x3ff;
|
||||
/* 950 MHz GFSK 802.15.4d-2009 */
|
||||
ieee->phy->channels_supported[6] |= 0x3ffc00;
|
||||
|
||||
INIT_LIST_HEAD(&priv->list);
|
||||
priv->fake = fake;
|
||||
|
||||
spin_lock_init(&priv->lock);
|
||||
|
||||
ieee->parent = dev;
|
||||
|
||||
err = ieee802154_register_device(ieee);
|
||||
if (err)
|
||||
goto err_reg;
|
||||
|
||||
write_lock_bh(&fake->lock);
|
||||
list_add_tail(&priv->list, &fake->list);
|
||||
write_unlock_bh(&fake->lock);
|
||||
|
||||
return 0;
|
||||
|
||||
err_reg:
|
||||
ieee802154_free_device(priv->dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void fakelb_del(struct fakelb_dev_priv *priv)
|
||||
{
|
||||
write_lock_bh(&priv->fake->lock);
|
||||
list_del(&priv->list);
|
||||
write_unlock_bh(&priv->fake->lock);
|
||||
|
||||
ieee802154_unregister_device(priv->dev);
|
||||
ieee802154_free_device(priv->dev);
|
||||
}
|
||||
|
||||
static int __devinit fakelb_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct fakelb_priv *priv;
|
||||
struct fakelb_dev_priv *dp;
|
||||
int err = -ENOMEM;
|
||||
int i;
|
||||
|
||||
priv = kzalloc(sizeof(struct fakelb_priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
goto err_alloc;
|
||||
|
||||
INIT_LIST_HEAD(&priv->list);
|
||||
rwlock_init(&priv->lock);
|
||||
|
||||
for (i = 0; i < numlbs; i++) {
|
||||
err = fakelb_add_one(&pdev->dev, priv);
|
||||
if (err < 0)
|
||||
goto err_slave;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, priv);
|
||||
dev_info(&pdev->dev, "added ieee802154 hardware\n");
|
||||
return 0;
|
||||
|
||||
err_slave:
|
||||
list_for_each_entry(dp, &priv->list, list)
|
||||
fakelb_del(dp);
|
||||
kfree(priv);
|
||||
err_alloc:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit fakelb_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct fakelb_priv *priv = platform_get_drvdata(pdev);
|
||||
struct fakelb_dev_priv *dp, *temp;
|
||||
|
||||
list_for_each_entry_safe(dp, temp, &priv->list, list)
|
||||
fakelb_del(dp);
|
||||
kfree(priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_device *ieee802154fake_dev;
|
||||
|
||||
static struct platform_driver ieee802154fake_driver = {
|
||||
.probe = fakelb_probe,
|
||||
.remove = __devexit_p(fakelb_remove),
|
||||
.driver = {
|
||||
.name = "ieee802154fakelb",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static __init int fakelb_init_module(void)
|
||||
{
|
||||
ieee802154fake_dev = platform_device_register_simple(
|
||||
"ieee802154fakelb", -1, NULL, 0);
|
||||
return platform_driver_register(&ieee802154fake_driver);
|
||||
}
|
||||
|
||||
static __exit void fake_remove_module(void)
|
||||
{
|
||||
platform_driver_unregister(&ieee802154fake_driver);
|
||||
platform_device_unregister(ieee802154fake_dev);
|
||||
}
|
||||
|
||||
module_init(fakelb_init_module);
|
||||
module_exit(fake_remove_module);
|
||||
MODULE_LICENSE("GPL");
|
|
@ -42,6 +42,7 @@
|
|||
#include <linux/inetdevice.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <net/tcp.h>
|
||||
#include <net/ipv6.h>
|
||||
|
@ -1826,7 +1827,10 @@ static int cma_resolve_iboe_route(struct rdma_id_private *id_priv)
|
|||
route->path_rec->reversible = 1;
|
||||
route->path_rec->pkey = cpu_to_be16(0xffff);
|
||||
route->path_rec->mtu_selector = IB_SA_EQ;
|
||||
route->path_rec->sl = id_priv->tos >> 5;
|
||||
route->path_rec->sl = netdev_get_prio_tc_map(
|
||||
ndev->priv_flags & IFF_802_1Q_VLAN ?
|
||||
vlan_dev_real_dev(ndev) : ndev,
|
||||
rt_tos2priority(id_priv->tos));
|
||||
|
||||
route->path_rec->mtu = iboe_get_mtu(ndev->mtu);
|
||||
route->path_rec->rate_selector = IB_SA_EQ;
|
||||
|
|
|
@ -125,7 +125,8 @@ int ibnl_put_attr(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
unsigned char *prev_tail;
|
||||
|
||||
prev_tail = skb_tail_pointer(skb);
|
||||
NLA_PUT(skb, type, len, data);
|
||||
if (nla_put(skb, type, len, data))
|
||||
goto nla_put_failure;
|
||||
nlh->nlmsg_len += skb_tail_pointer(skb) - prev_tail;
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -66,12 +66,6 @@ static ctl_table ucma_ctl_table[] = {
|
|||
{ }
|
||||
};
|
||||
|
||||
static struct ctl_path ucma_ctl_path[] = {
|
||||
{ .procname = "net" },
|
||||
{ .procname = "rdma_ucm" },
|
||||
{ }
|
||||
};
|
||||
|
||||
struct ucma_file {
|
||||
struct mutex mut;
|
||||
struct file *filp;
|
||||
|
@ -1392,7 +1386,7 @@ static int __init ucma_init(void)
|
|||
goto err1;
|
||||
}
|
||||
|
||||
ucma_ctl_table_hdr = register_sysctl_paths(ucma_ctl_path, ucma_ctl_table);
|
||||
ucma_ctl_table_hdr = register_net_sysctl(&init_net, "net/rdma_ucm", ucma_ctl_table);
|
||||
if (!ucma_ctl_table_hdr) {
|
||||
printk(KERN_ERR "rdma_ucm: couldn't register sysctl paths\n");
|
||||
ret = -ENOMEM;
|
||||
|
@ -1408,7 +1402,7 @@ err1:
|
|||
|
||||
static void __exit ucma_cleanup(void)
|
||||
{
|
||||
unregister_sysctl_table(ucma_ctl_table_hdr);
|
||||
unregister_net_sysctl_table(ucma_ctl_table_hdr);
|
||||
device_remove_file(ucma_misc.this_device, &dev_attr_abi_version);
|
||||
misc_deregister(&ucma_misc);
|
||||
idr_destroy(&ctx_idr);
|
||||
|
|
|
@ -336,11 +336,6 @@ static inline void
|
|||
capincci_alloc_minor(struct capidev *cdev, struct capincci *np) { }
|
||||
static inline void capincci_free_minor(struct capincci *np) { }
|
||||
|
||||
static inline unsigned int capincci_minor_opencount(struct capincci *np)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_ISDN_CAPI_MIDDLEWARE */
|
||||
|
||||
static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci)
|
||||
|
@ -372,6 +367,7 @@ static void capincci_free(struct capidev *cdev, u32 ncci)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
|
||||
static struct capincci *capincci_find(struct capidev *cdev, u32 ncci)
|
||||
{
|
||||
struct capincci *np;
|
||||
|
@ -382,7 +378,6 @@ static struct capincci *capincci_find(struct capidev *cdev, u32 ncci)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
|
||||
/* -------- handle data queue --------------------------------------- */
|
||||
|
||||
static struct sk_buff *
|
||||
|
@ -578,8 +573,8 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
|
|||
struct tty_struct *tty;
|
||||
struct capiminor *mp;
|
||||
u16 datahandle;
|
||||
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
|
||||
struct capincci *np;
|
||||
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
|
||||
|
||||
mutex_lock(&cdev->lock);
|
||||
|
||||
|
@ -597,6 +592,12 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
|
|||
goto unlock_out;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_ISDN_CAPI_MIDDLEWARE
|
||||
skb_queue_tail(&cdev->recvqueue, skb);
|
||||
wake_up_interruptible(&cdev->recvwait);
|
||||
|
||||
#else /* CONFIG_ISDN_CAPI_MIDDLEWARE */
|
||||
|
||||
np = capincci_find(cdev, CAPIMSG_CONTROL(skb->data));
|
||||
if (!np) {
|
||||
printk(KERN_ERR "BUG: capi_signal: ncci not found\n");
|
||||
|
@ -605,12 +606,6 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
|
|||
goto unlock_out;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_ISDN_CAPI_MIDDLEWARE
|
||||
skb_queue_tail(&cdev->recvqueue, skb);
|
||||
wake_up_interruptible(&cdev->recvwait);
|
||||
|
||||
#else /* CONFIG_ISDN_CAPI_MIDDLEWARE */
|
||||
|
||||
mp = np->minorp;
|
||||
if (!mp) {
|
||||
skb_queue_tail(&cdev->recvqueue, skb);
|
||||
|
@ -786,7 +781,6 @@ register_out:
|
|||
return retval;
|
||||
|
||||
case CAPI_GET_VERSION:
|
||||
{
|
||||
if (copy_from_user(&data.contr, argp,
|
||||
sizeof(data.contr)))
|
||||
return -EFAULT;
|
||||
|
@ -796,11 +790,9 @@ register_out:
|
|||
if (copy_to_user(argp, &data.version,
|
||||
sizeof(data.version)))
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
case CAPI_GET_SERIAL:
|
||||
{
|
||||
if (copy_from_user(&data.contr, argp,
|
||||
sizeof(data.contr)))
|
||||
return -EFAULT;
|
||||
|
@ -810,10 +802,9 @@ register_out:
|
|||
if (copy_to_user(argp, data.serial,
|
||||
sizeof(data.serial)))
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
case CAPI_GET_PROFILE:
|
||||
{
|
||||
if (copy_from_user(&data.contr, argp,
|
||||
sizeof(data.contr)))
|
||||
return -EFAULT;
|
||||
|
@ -837,11 +828,9 @@ register_out:
|
|||
}
|
||||
if (retval)
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
case CAPI_GET_MANUFACTURER:
|
||||
{
|
||||
if (copy_from_user(&data.contr, argp,
|
||||
sizeof(data.contr)))
|
||||
return -EFAULT;
|
||||
|
@ -853,8 +842,8 @@ register_out:
|
|||
sizeof(data.manufacturer)))
|
||||
return -EFAULT;
|
||||
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
case CAPI_GET_ERRCODE:
|
||||
data.errcode = cdev->errcode;
|
||||
cdev->errcode = CAPI_NOERROR;
|
||||
|
@ -870,8 +859,7 @@ register_out:
|
|||
return 0;
|
||||
return -ENXIO;
|
||||
|
||||
case CAPI_MANUFACTURER_CMD:
|
||||
{
|
||||
case CAPI_MANUFACTURER_CMD: {
|
||||
struct capi_manufacturer_cmd mcmd;
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
@ -879,8 +867,6 @@ register_out:
|
|||
return -EFAULT;
|
||||
return capi20_manufacturer(mcmd.cmd, mcmd.data);
|
||||
}
|
||||
return 0;
|
||||
|
||||
case CAPI_SET_FLAGS:
|
||||
case CAPI_CLR_FLAGS: {
|
||||
unsigned userflags;
|
||||
|
@ -902,6 +888,11 @@ register_out:
|
|||
return -EFAULT;
|
||||
return 0;
|
||||
|
||||
#ifndef CONFIG_ISDN_CAPI_MIDDLEWARE
|
||||
case CAPI_NCCI_OPENCOUNT:
|
||||
return 0;
|
||||
|
||||
#else /* CONFIG_ISDN_CAPI_MIDDLEWARE */
|
||||
case CAPI_NCCI_OPENCOUNT: {
|
||||
struct capincci *nccip;
|
||||
unsigned ncci;
|
||||
|
@ -918,7 +909,6 @@ register_out:
|
|||
return count;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
|
||||
case CAPI_NCCI_GETUNIT: {
|
||||
struct capincci *nccip;
|
||||
struct capiminor *mp;
|
||||
|
|
|
@ -1593,7 +1593,7 @@ static int capidrv_command(isdn_ctrl *c, capidrv_contr *card)
|
|||
return capidrv_ioctl(c, card);
|
||||
|
||||
switch (c->command) {
|
||||
case ISDN_CMD_DIAL:{
|
||||
case ISDN_CMD_DIAL: {
|
||||
u8 calling[ISDN_MSNLEN + 3];
|
||||
u8 called[ISDN_MSNLEN + 2];
|
||||
|
||||
|
@ -2072,7 +2072,8 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp)
|
|||
card->interface.writebuf_skb = if_sendbuf;
|
||||
card->interface.writecmd = NULL;
|
||||
card->interface.readstat = if_readstat;
|
||||
card->interface.features = ISDN_FEATURE_L2_HDLC |
|
||||
card->interface.features =
|
||||
ISDN_FEATURE_L2_HDLC |
|
||||
ISDN_FEATURE_L2_TRANS |
|
||||
ISDN_FEATURE_L3_TRANS |
|
||||
ISDN_FEATURE_P_UNKNOWN |
|
||||
|
@ -2080,7 +2081,8 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp)
|
|||
ISDN_FEATURE_L2_X75UI |
|
||||
ISDN_FEATURE_L2_X75BUI;
|
||||
if (profp->support1 & (1 << 2))
|
||||
card->interface.features |= ISDN_FEATURE_L2_V11096 |
|
||||
card->interface.features |=
|
||||
ISDN_FEATURE_L2_V11096 |
|
||||
ISDN_FEATURE_L2_V11019 |
|
||||
ISDN_FEATURE_L2_V11038;
|
||||
if (profp->support1 & (1 << 8))
|
||||
|
|
|
@ -410,10 +410,10 @@ static void check_pending(struct bas_cardstate *ucs)
|
|||
if (!(ucs->basstate & BS_RESETTING))
|
||||
ucs->pending = 0;
|
||||
break;
|
||||
/*
|
||||
* HD_READ_ATMESSAGE and HD_WRITE_ATMESSAGE are handled separately
|
||||
* and should never end up here
|
||||
*/
|
||||
/*
|
||||
* HD_READ_ATMESSAGE and HD_WRITE_ATMESSAGE are handled separately
|
||||
* and should never end up here
|
||||
*/
|
||||
default:
|
||||
dev_warn(&ucs->interface->dev,
|
||||
"unknown pending request 0x%02x cleared\n",
|
||||
|
@ -877,8 +877,7 @@ static void read_iso_callback(struct urb *urb)
|
|||
for (i = 0; i < BAS_NUMFRAMES; i++) {
|
||||
ubc->isoinlost += urb->iso_frame_desc[i].actual_length;
|
||||
if (unlikely(urb->iso_frame_desc[i].status != 0 &&
|
||||
urb->iso_frame_desc[i].status !=
|
||||
-EINPROGRESS))
|
||||
urb->iso_frame_desc[i].status != -EINPROGRESS))
|
||||
ubc->loststatus = urb->iso_frame_desc[i].status;
|
||||
urb->iso_frame_desc[i].status = 0;
|
||||
urb->iso_frame_desc[i].actual_length = 0;
|
||||
|
@ -2078,16 +2077,14 @@ static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6])
|
|||
/* Free hardware dependent part of the B channel structure
|
||||
* parameter:
|
||||
* bcs B channel structure
|
||||
* return value:
|
||||
* !=0 on success
|
||||
*/
|
||||
static int gigaset_freebcshw(struct bc_state *bcs)
|
||||
static void gigaset_freebcshw(struct bc_state *bcs)
|
||||
{
|
||||
struct bas_bc_state *ubc = bcs->hw.bas;
|
||||
int i;
|
||||
|
||||
if (!ubc)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
/* kill URBs and tasklets before freeing - better safe than sorry */
|
||||
ubc->running = 0;
|
||||
|
@ -2105,14 +2102,13 @@ static int gigaset_freebcshw(struct bc_state *bcs)
|
|||
kfree(ubc->isooutbuf);
|
||||
kfree(ubc);
|
||||
bcs->hw.bas = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Initialize hardware dependent part of the B channel structure
|
||||
* parameter:
|
||||
* bcs B channel structure
|
||||
* return value:
|
||||
* !=0 on success
|
||||
* 0 on success, error code < 0 on failure
|
||||
*/
|
||||
static int gigaset_initbcshw(struct bc_state *bcs)
|
||||
{
|
||||
|
@ -2122,7 +2118,7 @@ static int gigaset_initbcshw(struct bc_state *bcs)
|
|||
bcs->hw.bas = ubc = kmalloc(sizeof(struct bas_bc_state), GFP_KERNEL);
|
||||
if (!ubc) {
|
||||
pr_err("out of memory\n");
|
||||
return 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ubc->running = 0;
|
||||
|
@ -2139,7 +2135,7 @@ static int gigaset_initbcshw(struct bc_state *bcs)
|
|||
pr_err("out of memory\n");
|
||||
kfree(ubc);
|
||||
bcs->hw.bas = NULL;
|
||||
return 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
tasklet_init(&ubc->sent_tasklet,
|
||||
write_iso_tasklet, (unsigned long) bcs);
|
||||
|
@ -2164,7 +2160,7 @@ static int gigaset_initbcshw(struct bc_state *bcs)
|
|||
ubc->stolen0s = 0;
|
||||
tasklet_init(&ubc->rcvd_tasklet,
|
||||
read_iso_tasklet, (unsigned long) bcs);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gigaset_reinitbcshw(struct bc_state *bcs)
|
||||
|
@ -2187,6 +2183,12 @@ static void gigaset_freecshw(struct cardstate *cs)
|
|||
cs->hw.bas = NULL;
|
||||
}
|
||||
|
||||
/* Initialize hardware dependent part of the cardstate structure
|
||||
* parameter:
|
||||
* cs cardstate structure
|
||||
* return value:
|
||||
* 0 on success, error code < 0 on failure
|
||||
*/
|
||||
static int gigaset_initcshw(struct cardstate *cs)
|
||||
{
|
||||
struct bas_cardstate *ucs;
|
||||
|
@ -2194,13 +2196,13 @@ static int gigaset_initcshw(struct cardstate *cs)
|
|||
cs->hw.bas = ucs = kmalloc(sizeof *ucs, GFP_KERNEL);
|
||||
if (!ucs) {
|
||||
pr_err("out of memory\n");
|
||||
return 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
ucs->int_in_buf = kmalloc(IP_MSGSIZE, GFP_KERNEL);
|
||||
if (!ucs->int_in_buf) {
|
||||
kfree(ucs);
|
||||
pr_err("out of memory\n");
|
||||
return 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ucs->urb_cmd_in = NULL;
|
||||
|
@ -2219,7 +2221,7 @@ static int gigaset_initcshw(struct cardstate *cs)
|
|||
init_waitqueue_head(&ucs->waitqueue);
|
||||
INIT_WORK(&ucs->int_in_wq, int_in_work);
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* freeurbs
|
||||
|
@ -2379,18 +2381,20 @@ static int gigaset_probe(struct usb_interface *interface,
|
|||
/* save address of controller structure */
|
||||
usb_set_intfdata(interface, cs);
|
||||
|
||||
if (!gigaset_start(cs))
|
||||
rc = gigaset_start(cs);
|
||||
if (rc < 0)
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
|
||||
allocerr:
|
||||
dev_err(cs->dev, "could not allocate URBs\n");
|
||||
rc = -ENOMEM;
|
||||
error:
|
||||
freeurbs(cs);
|
||||
usb_set_intfdata(interface, NULL);
|
||||
gigaset_freecs(cs);
|
||||
return -ENODEV;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* gigaset_disconnect
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "gigaset.h"
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/ratelimit.h>
|
||||
#include <linux/isdn/capilli.h>
|
||||
#include <linux/isdn/capicmd.h>
|
||||
#include <linux/isdn/capiutil.h>
|
||||
|
@ -108,51 +109,35 @@ static struct {
|
|||
u8 *bc;
|
||||
u8 *hlc;
|
||||
} cip2bchlc[] = {
|
||||
[1] = { "8090A3", NULL },
|
||||
/* Speech (A-law) */
|
||||
[2] = { "8890", NULL },
|
||||
/* Unrestricted digital information */
|
||||
[3] = { "8990", NULL },
|
||||
/* Restricted digital information */
|
||||
[4] = { "9090A3", NULL },
|
||||
/* 3,1 kHz audio (A-law) */
|
||||
[5] = { "9190", NULL },
|
||||
/* 7 kHz audio */
|
||||
[6] = { "9890", NULL },
|
||||
/* Video */
|
||||
[7] = { "88C0C6E6", NULL },
|
||||
/* Packet mode */
|
||||
[8] = { "8890218F", NULL },
|
||||
/* 56 kbit/s rate adaptation */
|
||||
[9] = { "9190A5", NULL },
|
||||
/* Unrestricted digital information with tones/announcements */
|
||||
[16] = { "8090A3", "9181" },
|
||||
/* Telephony */
|
||||
[17] = { "9090A3", "9184" },
|
||||
/* Group 2/3 facsimile */
|
||||
[18] = { "8890", "91A1" },
|
||||
/* Group 4 facsimile Class 1 */
|
||||
[19] = { "8890", "91A4" },
|
||||
/* Teletex service basic and mixed mode
|
||||
and Group 4 facsimile service Classes II and III */
|
||||
[20] = { "8890", "91A8" },
|
||||
/* Teletex service basic and processable mode */
|
||||
[21] = { "8890", "91B1" },
|
||||
/* Teletex service basic mode */
|
||||
[22] = { "8890", "91B2" },
|
||||
/* International interworking for Videotex */
|
||||
[23] = { "8890", "91B5" },
|
||||
/* Telex */
|
||||
[24] = { "8890", "91B8" },
|
||||
/* Message Handling Systems in accordance with X.400 */
|
||||
[25] = { "8890", "91C1" },
|
||||
/* OSI application in accordance with X.200 */
|
||||
[26] = { "9190A5", "9181" },
|
||||
/* 7 kHz telephony */
|
||||
[27] = { "9190A5", "916001" },
|
||||
/* Video telephony, first connection */
|
||||
[28] = { "8890", "916002" },
|
||||
/* Video telephony, second connection */
|
||||
[1] = { "8090A3", NULL }, /* Speech (A-law) */
|
||||
[2] = { "8890", NULL }, /* Unrestricted digital information */
|
||||
[3] = { "8990", NULL }, /* Restricted digital information */
|
||||
[4] = { "9090A3", NULL }, /* 3,1 kHz audio (A-law) */
|
||||
[5] = { "9190", NULL }, /* 7 kHz audio */
|
||||
[6] = { "9890", NULL }, /* Video */
|
||||
[7] = { "88C0C6E6", NULL }, /* Packet mode */
|
||||
[8] = { "8890218F", NULL }, /* 56 kbit/s rate adaptation */
|
||||
[9] = { "9190A5", NULL }, /* Unrestricted digital information
|
||||
* with tones/announcements */
|
||||
[16] = { "8090A3", "9181" }, /* Telephony */
|
||||
[17] = { "9090A3", "9184" }, /* Group 2/3 facsimile */
|
||||
[18] = { "8890", "91A1" }, /* Group 4 facsimile Class 1 */
|
||||
[19] = { "8890", "91A4" }, /* Teletex service basic and mixed mode
|
||||
* and Group 4 facsimile service
|
||||
* Classes II and III */
|
||||
[20] = { "8890", "91A8" }, /* Teletex service basic and
|
||||
* processable mode */
|
||||
[21] = { "8890", "91B1" }, /* Teletex service basic mode */
|
||||
[22] = { "8890", "91B2" }, /* International interworking for
|
||||
* Videotex */
|
||||
[23] = { "8890", "91B5" }, /* Telex */
|
||||
[24] = { "8890", "91B8" }, /* Message Handling Systems
|
||||
* in accordance with X.400 */
|
||||
[25] = { "8890", "91C1" }, /* OSI application
|
||||
* in accordance with X.200 */
|
||||
[26] = { "9190A5", "9181" }, /* 7 kHz telephony */
|
||||
[27] = { "9190A5", "916001" }, /* Video telephony, first connection */
|
||||
[28] = { "8890", "916002" }, /* Video telephony, second connection */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -223,10 +208,14 @@ get_appl(struct gigaset_capi_ctr *iif, u16 appl)
|
|||
static inline void dump_cmsg(enum debuglevel level, const char *tag, _cmsg *p)
|
||||
{
|
||||
#ifdef CONFIG_GIGASET_DEBUG
|
||||
/* dump at most 20 messages in 20 secs */
|
||||
static DEFINE_RATELIMIT_STATE(msg_dump_ratelimit, 20 * HZ, 20);
|
||||
_cdebbuf *cdb;
|
||||
|
||||
if (!(gigaset_debuglevel & level))
|
||||
return;
|
||||
if (!___ratelimit(&msg_dump_ratelimit, tag))
|
||||
return;
|
||||
|
||||
cdb = capi_cmsg2str(p);
|
||||
if (cdb) {
|
||||
|
@ -1192,7 +1181,9 @@ static void do_facility_req(struct gigaset_capi_ctr *iif,
|
|||
confparam[3] = 2; /* length */
|
||||
capimsg_setu16(confparam, 4, CapiSuccess);
|
||||
break;
|
||||
/* ToDo: add supported services */
|
||||
|
||||
/* ToDo: add supported services */
|
||||
|
||||
default:
|
||||
dev_notice(cs->dev,
|
||||
"%s: unsupported supplementary service function 0x%04x\n",
|
||||
|
@ -1766,7 +1757,8 @@ static void do_connect_b3_req(struct gigaset_capi_ctr *iif,
|
|||
|
||||
/* NCPI parameter: not applicable for B3 Transparent */
|
||||
ignore_cstruct_param(cs, cmsg->NCPI, "CONNECT_B3_REQ", "NCPI");
|
||||
send_conf(iif, ap, skb, (cmsg->NCPI && cmsg->NCPI[0]) ?
|
||||
send_conf(iif, ap, skb,
|
||||
(cmsg->NCPI && cmsg->NCPI[0]) ?
|
||||
CapiNcpiNotSupportedByProtocol : CapiSuccess);
|
||||
}
|
||||
|
||||
|
@ -1882,6 +1874,9 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif,
|
|||
|
||||
/* check for active logical connection */
|
||||
if (bcs->apconnstate >= APCONN_ACTIVE) {
|
||||
/* clear it */
|
||||
bcs->apconnstate = APCONN_SETUP;
|
||||
|
||||
/*
|
||||
* emit DISCONNECT_B3_IND with cause 0x3301
|
||||
* use separate cmsg structure, as the content of iif->acmsg
|
||||
|
@ -1906,6 +1901,7 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif,
|
|||
}
|
||||
capi_cmsg2message(b3cmsg,
|
||||
__skb_put(b3skb, CAPI_DISCONNECT_B3_IND_BASELEN));
|
||||
dump_cmsg(DEBUG_CMD, __func__, b3cmsg);
|
||||
kfree(b3cmsg);
|
||||
capi_ctr_handle_message(&iif->ctr, ap->id, b3skb);
|
||||
}
|
||||
|
@ -1966,7 +1962,8 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif,
|
|||
/* NCPI parameter: not applicable for B3 Transparent */
|
||||
ignore_cstruct_param(cs, cmsg->NCPI,
|
||||
"DISCONNECT_B3_REQ", "NCPI");
|
||||
send_conf(iif, ap, skb, (cmsg->NCPI && cmsg->NCPI[0]) ?
|
||||
send_conf(iif, ap, skb,
|
||||
(cmsg->NCPI && cmsg->NCPI[0]) ?
|
||||
CapiNcpiNotSupportedByProtocol : CapiSuccess);
|
||||
}
|
||||
|
||||
|
@ -2058,12 +2055,6 @@ static void do_reset_b3_req(struct gigaset_capi_ctr *iif,
|
|||
CapiResetProcedureNotSupportedByCurrentProtocol);
|
||||
}
|
||||
|
||||
/*
|
||||
* dump unsupported/ignored messages at most twice per minute,
|
||||
* some apps send those very frequently
|
||||
*/
|
||||
static unsigned long ignored_msg_dump_time;
|
||||
|
||||
/*
|
||||
* unsupported CAPI message handler
|
||||
*/
|
||||
|
@ -2073,8 +2064,7 @@ static void do_unsupported(struct gigaset_capi_ctr *iif,
|
|||
{
|
||||
/* decode message */
|
||||
capi_message2cmsg(&iif->acmsg, skb->data);
|
||||
if (printk_timed_ratelimit(&ignored_msg_dump_time, 30 * 1000))
|
||||
dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
|
||||
dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
|
||||
send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState);
|
||||
}
|
||||
|
||||
|
@ -2085,11 +2075,9 @@ static void do_nothing(struct gigaset_capi_ctr *iif,
|
|||
struct gigaset_capi_appl *ap,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
if (printk_timed_ratelimit(&ignored_msg_dump_time, 30 * 1000)) {
|
||||
/* decode message */
|
||||
capi_message2cmsg(&iif->acmsg, skb->data);
|
||||
dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
|
||||
}
|
||||
/* decode message */
|
||||
capi_message2cmsg(&iif->acmsg, skb->data);
|
||||
dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
|
@ -2358,7 +2346,7 @@ static const struct file_operations gigaset_proc_fops = {
|
|||
* @cs: device descriptor structure.
|
||||
* @isdnid: device name.
|
||||
*
|
||||
* Return value: 1 for success, 0 for failure
|
||||
* Return value: 0 on success, error code < 0 on failure
|
||||
*/
|
||||
int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
|
||||
{
|
||||
|
@ -2368,7 +2356,7 @@ int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
|
|||
iif = kmalloc(sizeof(*iif), GFP_KERNEL);
|
||||
if (!iif) {
|
||||
pr_err("%s: out of memory\n", __func__);
|
||||
return 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* prepare controller structure */
|
||||
|
@ -2392,12 +2380,12 @@ int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
|
|||
if (rc) {
|
||||
pr_err("attach_capi_ctr failed (%d)\n", rc);
|
||||
kfree(iif);
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
cs->iif = iif;
|
||||
cs->hw_hdr_len = CAPI_DATA_B3_REQ_LEN;
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -194,13 +194,13 @@ int gigaset_get_channel(struct bc_state *bcs)
|
|||
gig_dbg(DEBUG_CHANNEL, "could not allocate channel %d",
|
||||
bcs->channel);
|
||||
spin_unlock_irqrestore(&bcs->cs->lock, flags);
|
||||
return 0;
|
||||
return -EBUSY;
|
||||
}
|
||||
++bcs->use_count;
|
||||
bcs->busy = 1;
|
||||
gig_dbg(DEBUG_CHANNEL, "allocated channel %d", bcs->channel);
|
||||
spin_unlock_irqrestore(&bcs->cs->lock, flags);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct bc_state *gigaset_get_free_channel(struct cardstate *cs)
|
||||
|
@ -258,7 +258,7 @@ int gigaset_get_channels(struct cardstate *cs)
|
|||
spin_unlock_irqrestore(&cs->lock, flags);
|
||||
gig_dbg(DEBUG_CHANNEL,
|
||||
"could not allocate all channels");
|
||||
return 0;
|
||||
return -EBUSY;
|
||||
}
|
||||
for (i = 0; i < cs->channels; ++i)
|
||||
++cs->bcs[i].use_count;
|
||||
|
@ -266,7 +266,7 @@ int gigaset_get_channels(struct cardstate *cs)
|
|||
|
||||
gig_dbg(DEBUG_CHANNEL, "allocated all channels");
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gigaset_free_channels(struct cardstate *cs)
|
||||
|
@ -362,7 +362,7 @@ struct event_t *gigaset_add_event(struct cardstate *cs,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(gigaset_add_event);
|
||||
|
||||
static void free_strings(struct at_state_t *at_state)
|
||||
static void clear_at_state(struct at_state_t *at_state)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -372,18 +372,13 @@ static void free_strings(struct at_state_t *at_state)
|
|||
}
|
||||
}
|
||||
|
||||
static void clear_at_state(struct at_state_t *at_state)
|
||||
{
|
||||
free_strings(at_state);
|
||||
}
|
||||
|
||||
static void dealloc_at_states(struct cardstate *cs)
|
||||
static void dealloc_temp_at_states(struct cardstate *cs)
|
||||
{
|
||||
struct at_state_t *cur, *next;
|
||||
|
||||
list_for_each_entry_safe(cur, next, &cs->temp_at_states, list) {
|
||||
list_del(&cur->list);
|
||||
free_strings(cur);
|
||||
clear_at_state(cur);
|
||||
kfree(cur);
|
||||
}
|
||||
}
|
||||
|
@ -393,8 +388,7 @@ static void gigaset_freebcs(struct bc_state *bcs)
|
|||
int i;
|
||||
|
||||
gig_dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel);
|
||||
if (!bcs->cs->ops->freebcshw(bcs))
|
||||
gig_dbg(DEBUG_INIT, "failed");
|
||||
bcs->cs->ops->freebcshw(bcs);
|
||||
|
||||
gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel);
|
||||
clear_at_state(&bcs->at_state);
|
||||
|
@ -512,7 +506,7 @@ void gigaset_freecs(struct cardstate *cs)
|
|||
case 1: /* error when registering to LL */
|
||||
gig_dbg(DEBUG_INIT, "clearing at_state");
|
||||
clear_at_state(&cs->at_state);
|
||||
dealloc_at_states(cs);
|
||||
dealloc_temp_at_states(cs);
|
||||
|
||||
/* fall through */
|
||||
case 0: /* error in basic setup */
|
||||
|
@ -571,6 +565,8 @@ static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct cardstate *cs)
|
|||
* @inbuf: buffer structure.
|
||||
* @src: received data.
|
||||
* @numbytes: number of bytes received.
|
||||
*
|
||||
* Return value: !=0 if some data was appended
|
||||
*/
|
||||
int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
|
||||
unsigned numbytes)
|
||||
|
@ -614,8 +610,8 @@ int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
|
|||
EXPORT_SYMBOL_GPL(gigaset_fill_inbuf);
|
||||
|
||||
/* Initialize the b-channel structure */
|
||||
static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
|
||||
struct cardstate *cs, int channel)
|
||||
static int gigaset_initbcs(struct bc_state *bcs, struct cardstate *cs,
|
||||
int channel)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -654,11 +650,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
|
|||
bcs->apconnstate = 0;
|
||||
|
||||
gig_dbg(DEBUG_INIT, " setting up bcs[%d]->hw", channel);
|
||||
if (cs->ops->initbcshw(bcs))
|
||||
return bcs;
|
||||
|
||||
gig_dbg(DEBUG_INIT, " failed");
|
||||
return NULL;
|
||||
return cs->ops->initbcshw(bcs);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -757,7 +749,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
|
|||
cs->cmdbytes = 0;
|
||||
|
||||
gig_dbg(DEBUG_INIT, "setting up iif");
|
||||
if (!gigaset_isdn_regdev(cs, modulename)) {
|
||||
if (gigaset_isdn_regdev(cs, modulename) < 0) {
|
||||
pr_err("error registering ISDN device\n");
|
||||
goto error;
|
||||
}
|
||||
|
@ -765,7 +757,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
|
|||
make_valid(cs, VALID_ID);
|
||||
++cs->cs_init;
|
||||
gig_dbg(DEBUG_INIT, "setting up hw");
|
||||
if (!cs->ops->initcshw(cs))
|
||||
if (cs->ops->initcshw(cs) < 0)
|
||||
goto error;
|
||||
|
||||
++cs->cs_init;
|
||||
|
@ -779,7 +771,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
|
|||
/* set up channel data structures */
|
||||
for (i = 0; i < channels; ++i) {
|
||||
gig_dbg(DEBUG_INIT, "setting up bcs[%d]", i);
|
||||
if (!gigaset_initbcs(cs->bcs + i, cs, i)) {
|
||||
if (gigaset_initbcs(cs->bcs + i, cs, i) < 0) {
|
||||
pr_err("could not allocate channel %d data\n", i);
|
||||
goto error;
|
||||
}
|
||||
|
@ -848,8 +840,7 @@ static void cleanup_cs(struct cardstate *cs)
|
|||
cs->mstate = MS_UNINITIALIZED;
|
||||
|
||||
clear_at_state(&cs->at_state);
|
||||
dealloc_at_states(cs);
|
||||
free_strings(&cs->at_state);
|
||||
dealloc_temp_at_states(cs);
|
||||
gigaset_at_init(&cs->at_state, NULL, cs, 0);
|
||||
|
||||
cs->inbuf->inputstate = INS_command;
|
||||
|
@ -875,7 +866,7 @@ static void cleanup_cs(struct cardstate *cs)
|
|||
|
||||
for (i = 0; i < cs->channels; ++i) {
|
||||
gigaset_freebcs(cs->bcs + i);
|
||||
if (!gigaset_initbcs(cs->bcs + i, cs, i))
|
||||
if (gigaset_initbcs(cs->bcs + i, cs, i) < 0)
|
||||
pr_err("could not allocate channel %d data\n", i);
|
||||
}
|
||||
|
||||
|
@ -896,14 +887,14 @@ static void cleanup_cs(struct cardstate *cs)
|
|||
* waiting for completion of the initialization.
|
||||
*
|
||||
* Return value:
|
||||
* 1 - success, 0 - error
|
||||
* 0 on success, error code < 0 on failure
|
||||
*/
|
||||
int gigaset_start(struct cardstate *cs)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (mutex_lock_interruptible(&cs->mutex))
|
||||
return 0;
|
||||
return -EBUSY;
|
||||
|
||||
spin_lock_irqsave(&cs->lock, flags);
|
||||
cs->connected = 1;
|
||||
|
@ -927,11 +918,11 @@ int gigaset_start(struct cardstate *cs)
|
|||
wait_event(cs->waitqueue, !cs->waiting);
|
||||
|
||||
mutex_unlock(&cs->mutex);
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
mutex_unlock(&cs->mutex);
|
||||
return 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gigaset_start);
|
||||
|
||||
|
@ -943,7 +934,7 @@ EXPORT_SYMBOL_GPL(gigaset_start);
|
|||
* waiting for completion of the shutdown.
|
||||
*
|
||||
* Return value:
|
||||
* 0 - success, -1 - error (no device associated)
|
||||
* 0 - success, -ENODEV - error (no device associated)
|
||||
*/
|
||||
int gigaset_shutdown(struct cardstate *cs)
|
||||
{
|
||||
|
@ -951,7 +942,7 @@ int gigaset_shutdown(struct cardstate *cs)
|
|||
|
||||
if (!(cs->flags & VALID_MINOR)) {
|
||||
mutex_unlock(&cs->mutex);
|
||||
return -1;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
cs->waiting = 1;
|
||||
|
|
|
@ -60,7 +60,7 @@ void gigaset_isdn_stop(struct cardstate *cs)
|
|||
|
||||
int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
|
||||
{
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gigaset_isdn_unregdev(struct cardstate *cs)
|
||||
|
|
|
@ -153,103 +153,104 @@ struct reply_t gigaset_tab_nocid[] =
|
|||
* action, command */
|
||||
|
||||
/* initialize device, set cid mode if possible */
|
||||
{RSP_INIT, -1, -1, SEQ_INIT, 100, 1, {ACT_TIMEOUT} },
|
||||
{RSP_INIT, -1, -1, SEQ_INIT, 100, 1, {ACT_TIMEOUT} },
|
||||
|
||||
{EV_TIMEOUT, 100, 100, -1, 101, 3, {0}, "Z\r"},
|
||||
{RSP_OK, 101, 103, -1, 120, 5, {ACT_GETSTRING},
|
||||
"+GMR\r"},
|
||||
{EV_TIMEOUT, 100, 100, -1, 101, 3, {0}, "Z\r"},
|
||||
{RSP_OK, 101, 103, -1, 120, 5, {ACT_GETSTRING},
|
||||
"+GMR\r"},
|
||||
|
||||
{EV_TIMEOUT, 101, 101, -1, 102, 5, {0}, "Z\r"},
|
||||
{RSP_ERROR, 101, 101, -1, 102, 5, {0}, "Z\r"},
|
||||
{EV_TIMEOUT, 101, 101, -1, 102, 5, {0}, "Z\r"},
|
||||
{RSP_ERROR, 101, 101, -1, 102, 5, {0}, "Z\r"},
|
||||
|
||||
{EV_TIMEOUT, 102, 102, -1, 108, 5, {ACT_SETDLE1},
|
||||
"^SDLE=0\r"},
|
||||
{RSP_OK, 108, 108, -1, 104, -1},
|
||||
{RSP_ZDLE, 104, 104, 0, 103, 5, {0}, "Z\r"},
|
||||
{EV_TIMEOUT, 104, 104, -1, 0, 0, {ACT_FAILINIT} },
|
||||
{RSP_ERROR, 108, 108, -1, 0, 0, {ACT_FAILINIT} },
|
||||
{EV_TIMEOUT, 102, 102, -1, 108, 5, {ACT_SETDLE1},
|
||||
"^SDLE=0\r"},
|
||||
{RSP_OK, 108, 108, -1, 104, -1},
|
||||
{RSP_ZDLE, 104, 104, 0, 103, 5, {0}, "Z\r"},
|
||||
{EV_TIMEOUT, 104, 104, -1, 0, 0, {ACT_FAILINIT} },
|
||||
{RSP_ERROR, 108, 108, -1, 0, 0, {ACT_FAILINIT} },
|
||||
|
||||
{EV_TIMEOUT, 108, 108, -1, 105, 2, {ACT_SETDLE0,
|
||||
ACT_HUPMODEM,
|
||||
ACT_TIMEOUT} },
|
||||
{EV_TIMEOUT, 105, 105, -1, 103, 5, {0}, "Z\r"},
|
||||
{EV_TIMEOUT, 108, 108, -1, 105, 2, {ACT_SETDLE0,
|
||||
ACT_HUPMODEM,
|
||||
ACT_TIMEOUT} },
|
||||
{EV_TIMEOUT, 105, 105, -1, 103, 5, {0}, "Z\r"},
|
||||
|
||||
{RSP_ERROR, 102, 102, -1, 107, 5, {0}, "^GETPRE\r"},
|
||||
{RSP_OK, 107, 107, -1, 0, 0, {ACT_CONFIGMODE} },
|
||||
{RSP_ERROR, 107, 107, -1, 0, 0, {ACT_FAILINIT} },
|
||||
{EV_TIMEOUT, 107, 107, -1, 0, 0, {ACT_FAILINIT} },
|
||||
{RSP_ERROR, 102, 102, -1, 107, 5, {0}, "^GETPRE\r"},
|
||||
{RSP_OK, 107, 107, -1, 0, 0, {ACT_CONFIGMODE} },
|
||||
{RSP_ERROR, 107, 107, -1, 0, 0, {ACT_FAILINIT} },
|
||||
{EV_TIMEOUT, 107, 107, -1, 0, 0, {ACT_FAILINIT} },
|
||||
|
||||
{RSP_ERROR, 103, 103, -1, 0, 0, {ACT_FAILINIT} },
|
||||
{EV_TIMEOUT, 103, 103, -1, 0, 0, {ACT_FAILINIT} },
|
||||
{RSP_ERROR, 103, 103, -1, 0, 0, {ACT_FAILINIT} },
|
||||
{EV_TIMEOUT, 103, 103, -1, 0, 0, {ACT_FAILINIT} },
|
||||
|
||||
{RSP_STRING, 120, 120, -1, 121, -1, {ACT_SETVER} },
|
||||
{RSP_STRING, 120, 120, -1, 121, -1, {ACT_SETVER} },
|
||||
|
||||
{EV_TIMEOUT, 120, 121, -1, 0, 0, {ACT_FAILVER,
|
||||
ACT_INIT} },
|
||||
{RSP_ERROR, 120, 121, -1, 0, 0, {ACT_FAILVER,
|
||||
ACT_INIT} },
|
||||
{RSP_OK, 121, 121, -1, 0, 0, {ACT_GOTVER,
|
||||
ACT_INIT} },
|
||||
{EV_TIMEOUT, 120, 121, -1, 0, 0, {ACT_FAILVER,
|
||||
ACT_INIT} },
|
||||
{RSP_ERROR, 120, 121, -1, 0, 0, {ACT_FAILVER,
|
||||
ACT_INIT} },
|
||||
{RSP_OK, 121, 121, -1, 0, 0, {ACT_GOTVER,
|
||||
ACT_INIT} },
|
||||
{RSP_NONE, 121, 121, -1, 120, 0, {ACT_GETSTRING} },
|
||||
|
||||
/* leave dle mode */
|
||||
{RSP_INIT, 0, 0, SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"},
|
||||
{RSP_OK, 201, 201, -1, 202, -1},
|
||||
{RSP_ZDLE, 202, 202, 0, 0, 0, {ACT_DLE0} },
|
||||
{RSP_NODEV, 200, 249, -1, 0, 0, {ACT_FAKEDLE0} },
|
||||
{RSP_ERROR, 200, 249, -1, 0, 0, {ACT_FAILDLE0} },
|
||||
{EV_TIMEOUT, 200, 249, -1, 0, 0, {ACT_FAILDLE0} },
|
||||
{RSP_INIT, 0, 0, SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"},
|
||||
{RSP_OK, 201, 201, -1, 202, -1},
|
||||
{RSP_ZDLE, 202, 202, 0, 0, 0, {ACT_DLE0} },
|
||||
{RSP_NODEV, 200, 249, -1, 0, 0, {ACT_FAKEDLE0} },
|
||||
{RSP_ERROR, 200, 249, -1, 0, 0, {ACT_FAILDLE0} },
|
||||
{EV_TIMEOUT, 200, 249, -1, 0, 0, {ACT_FAILDLE0} },
|
||||
|
||||
/* enter dle mode */
|
||||
{RSP_INIT, 0, 0, SEQ_DLE1, 251, 5, {0}, "^SDLE=1\r"},
|
||||
{RSP_OK, 251, 251, -1, 252, -1},
|
||||
{RSP_ZDLE, 252, 252, 1, 0, 0, {ACT_DLE1} },
|
||||
{RSP_ERROR, 250, 299, -1, 0, 0, {ACT_FAILDLE1} },
|
||||
{EV_TIMEOUT, 250, 299, -1, 0, 0, {ACT_FAILDLE1} },
|
||||
{RSP_INIT, 0, 0, SEQ_DLE1, 251, 5, {0}, "^SDLE=1\r"},
|
||||
{RSP_OK, 251, 251, -1, 252, -1},
|
||||
{RSP_ZDLE, 252, 252, 1, 0, 0, {ACT_DLE1} },
|
||||
{RSP_ERROR, 250, 299, -1, 0, 0, {ACT_FAILDLE1} },
|
||||
{EV_TIMEOUT, 250, 299, -1, 0, 0, {ACT_FAILDLE1} },
|
||||
|
||||
/* incoming call */
|
||||
{RSP_RING, -1, -1, -1, -1, -1, {ACT_RING} },
|
||||
{RSP_RING, -1, -1, -1, -1, -1, {ACT_RING} },
|
||||
|
||||
/* get cid */
|
||||
{RSP_INIT, 0, 0, SEQ_CID, 301, 5, {0}, "^SGCI?\r"},
|
||||
{RSP_OK, 301, 301, -1, 302, -1},
|
||||
{RSP_ZGCI, 302, 302, -1, 0, 0, {ACT_CID} },
|
||||
{RSP_ERROR, 301, 349, -1, 0, 0, {ACT_FAILCID} },
|
||||
{EV_TIMEOUT, 301, 349, -1, 0, 0, {ACT_FAILCID} },
|
||||
{RSP_INIT, 0, 0, SEQ_CID, 301, 5, {0}, "^SGCI?\r"},
|
||||
{RSP_OK, 301, 301, -1, 302, -1},
|
||||
{RSP_ZGCI, 302, 302, -1, 0, 0, {ACT_CID} },
|
||||
{RSP_ERROR, 301, 349, -1, 0, 0, {ACT_FAILCID} },
|
||||
{EV_TIMEOUT, 301, 349, -1, 0, 0, {ACT_FAILCID} },
|
||||
|
||||
/* enter cid mode */
|
||||
{RSP_INIT, 0, 0, SEQ_CIDMODE, 150, 5, {0}, "^SGCI=1\r"},
|
||||
{RSP_OK, 150, 150, -1, 0, 0, {ACT_CMODESET} },
|
||||
{RSP_ERROR, 150, 150, -1, 0, 0, {ACT_FAILCMODE} },
|
||||
{EV_TIMEOUT, 150, 150, -1, 0, 0, {ACT_FAILCMODE} },
|
||||
{RSP_INIT, 0, 0, SEQ_CIDMODE, 150, 5, {0}, "^SGCI=1\r"},
|
||||
{RSP_OK, 150, 150, -1, 0, 0, {ACT_CMODESET} },
|
||||
{RSP_ERROR, 150, 150, -1, 0, 0, {ACT_FAILCMODE} },
|
||||
{EV_TIMEOUT, 150, 150, -1, 0, 0, {ACT_FAILCMODE} },
|
||||
|
||||
/* leave cid mode */
|
||||
{RSP_INIT, 0, 0, SEQ_UMMODE, 160, 5, {0}, "Z\r"},
|
||||
{RSP_OK, 160, 160, -1, 0, 0, {ACT_UMODESET} },
|
||||
{RSP_ERROR, 160, 160, -1, 0, 0, {ACT_FAILUMODE} },
|
||||
{EV_TIMEOUT, 160, 160, -1, 0, 0, {ACT_FAILUMODE} },
|
||||
{RSP_INIT, 0, 0, SEQ_UMMODE, 160, 5, {0}, "Z\r"},
|
||||
{RSP_OK, 160, 160, -1, 0, 0, {ACT_UMODESET} },
|
||||
{RSP_ERROR, 160, 160, -1, 0, 0, {ACT_FAILUMODE} },
|
||||
{EV_TIMEOUT, 160, 160, -1, 0, 0, {ACT_FAILUMODE} },
|
||||
|
||||
/* abort getting cid */
|
||||
{RSP_INIT, 0, 0, SEQ_NOCID, 0, 0, {ACT_ABORTCID} },
|
||||
{RSP_INIT, 0, 0, SEQ_NOCID, 0, 0, {ACT_ABORTCID} },
|
||||
|
||||
/* reset */
|
||||
{RSP_INIT, 0, 0, SEQ_SHUTDOWN, 504, 5, {0}, "Z\r"},
|
||||
{RSP_OK, 504, 504, -1, 0, 0, {ACT_SDOWN} },
|
||||
{RSP_ERROR, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} },
|
||||
{EV_TIMEOUT, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} },
|
||||
{RSP_NODEV, 501, 599, -1, 0, 0, {ACT_FAKESDOWN} },
|
||||
{RSP_INIT, 0, 0, SEQ_SHUTDOWN, 504, 5, {0}, "Z\r"},
|
||||
{RSP_OK, 504, 504, -1, 0, 0, {ACT_SDOWN} },
|
||||
{RSP_ERROR, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} },
|
||||
{EV_TIMEOUT, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} },
|
||||
{RSP_NODEV, 501, 599, -1, 0, 0, {ACT_FAKESDOWN} },
|
||||
|
||||
{EV_PROC_CIDMODE, -1, -1, -1, -1, -1, {ACT_PROC_CIDMODE} },
|
||||
{EV_IF_LOCK, -1, -1, -1, -1, -1, {ACT_IF_LOCK} },
|
||||
{EV_IF_VER, -1, -1, -1, -1, -1, {ACT_IF_VER} },
|
||||
{EV_START, -1, -1, -1, -1, -1, {ACT_START} },
|
||||
{EV_STOP, -1, -1, -1, -1, -1, {ACT_STOP} },
|
||||
{EV_SHUTDOWN, -1, -1, -1, -1, -1, {ACT_SHUTDOWN} },
|
||||
{EV_PROC_CIDMODE, -1, -1, -1, -1, -1, {ACT_PROC_CIDMODE} },
|
||||
{EV_IF_LOCK, -1, -1, -1, -1, -1, {ACT_IF_LOCK} },
|
||||
{EV_IF_VER, -1, -1, -1, -1, -1, {ACT_IF_VER} },
|
||||
{EV_START, -1, -1, -1, -1, -1, {ACT_START} },
|
||||
{EV_STOP, -1, -1, -1, -1, -1, {ACT_STOP} },
|
||||
{EV_SHUTDOWN, -1, -1, -1, -1, -1, {ACT_SHUTDOWN} },
|
||||
|
||||
/* misc. */
|
||||
{RSP_ERROR, -1, -1, -1, -1, -1, {ACT_ERROR} },
|
||||
{RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} },
|
||||
{RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} },
|
||||
{RSP_ERROR, -1, -1, -1, -1, -1, {ACT_ERROR} },
|
||||
{RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} },
|
||||
{RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} },
|
||||
{RSP_LAST}
|
||||
};
|
||||
|
||||
|
@ -261,90 +262,90 @@ struct reply_t gigaset_tab_cid[] =
|
|||
* action, command */
|
||||
|
||||
/* dial */
|
||||
{EV_DIAL, -1, -1, -1, -1, -1, {ACT_DIAL} },
|
||||
{RSP_INIT, 0, 0, SEQ_DIAL, 601, 5, {ACT_CMD + AT_BC} },
|
||||
{RSP_OK, 601, 601, -1, 603, 5, {ACT_CMD + AT_PROTO} },
|
||||
{RSP_OK, 603, 603, -1, 604, 5, {ACT_CMD + AT_TYPE} },
|
||||
{RSP_OK, 604, 604, -1, 605, 5, {ACT_CMD + AT_MSN} },
|
||||
{RSP_NULL, 605, 605, -1, 606, 5, {ACT_CMD + AT_CLIP} },
|
||||
{RSP_OK, 605, 605, -1, 606, 5, {ACT_CMD + AT_CLIP} },
|
||||
{RSP_NULL, 606, 606, -1, 607, 5, {ACT_CMD + AT_ISO} },
|
||||
{RSP_OK, 606, 606, -1, 607, 5, {ACT_CMD + AT_ISO} },
|
||||
{RSP_OK, 607, 607, -1, 608, 5, {0}, "+VLS=17\r"},
|
||||
{RSP_OK, 608, 608, -1, 609, -1},
|
||||
{RSP_ZSAU, 609, 609, ZSAU_PROCEEDING, 610, 5, {ACT_CMD + AT_DIAL} },
|
||||
{RSP_OK, 610, 610, -1, 650, 0, {ACT_DIALING} },
|
||||
{EV_DIAL, -1, -1, -1, -1, -1, {ACT_DIAL} },
|
||||
{RSP_INIT, 0, 0, SEQ_DIAL, 601, 5, {ACT_CMD + AT_BC} },
|
||||
{RSP_OK, 601, 601, -1, 603, 5, {ACT_CMD + AT_PROTO} },
|
||||
{RSP_OK, 603, 603, -1, 604, 5, {ACT_CMD + AT_TYPE} },
|
||||
{RSP_OK, 604, 604, -1, 605, 5, {ACT_CMD + AT_MSN} },
|
||||
{RSP_NULL, 605, 605, -1, 606, 5, {ACT_CMD + AT_CLIP} },
|
||||
{RSP_OK, 605, 605, -1, 606, 5, {ACT_CMD + AT_CLIP} },
|
||||
{RSP_NULL, 606, 606, -1, 607, 5, {ACT_CMD + AT_ISO} },
|
||||
{RSP_OK, 606, 606, -1, 607, 5, {ACT_CMD + AT_ISO} },
|
||||
{RSP_OK, 607, 607, -1, 608, 5, {0}, "+VLS=17\r"},
|
||||
{RSP_OK, 608, 608, -1, 609, -1},
|
||||
{RSP_ZSAU, 609, 609, ZSAU_PROCEEDING, 610, 5, {ACT_CMD + AT_DIAL} },
|
||||
{RSP_OK, 610, 610, -1, 650, 0, {ACT_DIALING} },
|
||||
|
||||
{RSP_ERROR, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} },
|
||||
{EV_TIMEOUT, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} },
|
||||
{RSP_ERROR, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} },
|
||||
{EV_TIMEOUT, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} },
|
||||
|
||||
/* optional dialing responses */
|
||||
{EV_BC_OPEN, 650, 650, -1, 651, -1},
|
||||
{RSP_ZVLS, 609, 651, 17, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ZCTP, 610, 651, -1, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ZCPN, 610, 651, -1, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ZSAU, 650, 651, ZSAU_CALL_DELIVERED, -1, -1, {ACT_DEBUG} },
|
||||
{EV_BC_OPEN, 650, 650, -1, 651, -1},
|
||||
{RSP_ZVLS, 609, 651, 17, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ZCTP, 610, 651, -1, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ZCPN, 610, 651, -1, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ZSAU, 650, 651, ZSAU_CALL_DELIVERED, -1, -1, {ACT_DEBUG} },
|
||||
|
||||
/* connect */
|
||||
{RSP_ZSAU, 650, 650, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} },
|
||||
{RSP_ZSAU, 651, 651, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT,
|
||||
ACT_NOTIFY_BC_UP} },
|
||||
{RSP_ZSAU, 750, 750, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} },
|
||||
{RSP_ZSAU, 751, 751, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT,
|
||||
ACT_NOTIFY_BC_UP} },
|
||||
{EV_BC_OPEN, 800, 800, -1, 800, -1, {ACT_NOTIFY_BC_UP} },
|
||||
{RSP_ZSAU, 650, 650, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} },
|
||||
{RSP_ZSAU, 651, 651, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT,
|
||||
ACT_NOTIFY_BC_UP} },
|
||||
{RSP_ZSAU, 750, 750, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} },
|
||||
{RSP_ZSAU, 751, 751, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT,
|
||||
ACT_NOTIFY_BC_UP} },
|
||||
{EV_BC_OPEN, 800, 800, -1, 800, -1, {ACT_NOTIFY_BC_UP} },
|
||||
|
||||
/* remote hangup */
|
||||
{RSP_ZSAU, 650, 651, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT} },
|
||||
{RSP_ZSAU, 750, 751, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} },
|
||||
{RSP_ZSAU, 800, 800, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} },
|
||||
{RSP_ZSAU, 650, 651, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT} },
|
||||
{RSP_ZSAU, 750, 751, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} },
|
||||
{RSP_ZSAU, 800, 800, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} },
|
||||
|
||||
/* hangup */
|
||||
{EV_HUP, -1, -1, -1, -1, -1, {ACT_HUP} },
|
||||
{RSP_INIT, -1, -1, SEQ_HUP, 401, 5, {0}, "+VLS=0\r"},
|
||||
{RSP_OK, 401, 401, -1, 402, 5},
|
||||
{RSP_ZVLS, 402, 402, 0, 403, 5},
|
||||
{RSP_ZSAU, 403, 403, ZSAU_DISCONNECT_REQ, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ZSAU, 403, 403, ZSAU_NULL, 0, 0, {ACT_DISCONNECT} },
|
||||
{RSP_NODEV, 401, 403, -1, 0, 0, {ACT_FAKEHUP} },
|
||||
{RSP_ERROR, 401, 401, -1, 0, 0, {ACT_ABORTHUP} },
|
||||
{EV_TIMEOUT, 401, 403, -1, 0, 0, {ACT_ABORTHUP} },
|
||||
{EV_HUP, -1, -1, -1, -1, -1, {ACT_HUP} },
|
||||
{RSP_INIT, -1, -1, SEQ_HUP, 401, 5, {0}, "+VLS=0\r"},
|
||||
{RSP_OK, 401, 401, -1, 402, 5},
|
||||
{RSP_ZVLS, 402, 402, 0, 403, 5},
|
||||
{RSP_ZSAU, 403, 403, ZSAU_DISCONNECT_REQ, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ZSAU, 403, 403, ZSAU_NULL, 0, 0, {ACT_DISCONNECT} },
|
||||
{RSP_NODEV, 401, 403, -1, 0, 0, {ACT_FAKEHUP} },
|
||||
{RSP_ERROR, 401, 401, -1, 0, 0, {ACT_ABORTHUP} },
|
||||
{EV_TIMEOUT, 401, 403, -1, 0, 0, {ACT_ABORTHUP} },
|
||||
|
||||
{EV_BC_CLOSED, 0, 0, -1, 0, -1, {ACT_NOTIFY_BC_DOWN} },
|
||||
{EV_BC_CLOSED, 0, 0, -1, 0, -1, {ACT_NOTIFY_BC_DOWN} },
|
||||
|
||||
/* ring */
|
||||
{RSP_ZBC, 700, 700, -1, -1, -1, {0} },
|
||||
{RSP_ZHLC, 700, 700, -1, -1, -1, {0} },
|
||||
{RSP_NMBR, 700, 700, -1, -1, -1, {0} },
|
||||
{RSP_ZCPN, 700, 700, -1, -1, -1, {0} },
|
||||
{RSP_ZCTP, 700, 700, -1, -1, -1, {0} },
|
||||
{EV_TIMEOUT, 700, 700, -1, 720, 720, {ACT_ICALL} },
|
||||
{EV_BC_CLOSED, 720, 720, -1, 0, -1, {ACT_NOTIFY_BC_DOWN} },
|
||||
{RSP_ZBC, 700, 700, -1, -1, -1, {0} },
|
||||
{RSP_ZHLC, 700, 700, -1, -1, -1, {0} },
|
||||
{RSP_NMBR, 700, 700, -1, -1, -1, {0} },
|
||||
{RSP_ZCPN, 700, 700, -1, -1, -1, {0} },
|
||||
{RSP_ZCTP, 700, 700, -1, -1, -1, {0} },
|
||||
{EV_TIMEOUT, 700, 700, -1, 720, 720, {ACT_ICALL} },
|
||||
{EV_BC_CLOSED, 720, 720, -1, 0, -1, {ACT_NOTIFY_BC_DOWN} },
|
||||
|
||||
/*accept icall*/
|
||||
{EV_ACCEPT, -1, -1, -1, -1, -1, {ACT_ACCEPT} },
|
||||
{RSP_INIT, 720, 720, SEQ_ACCEPT, 721, 5, {ACT_CMD + AT_PROTO} },
|
||||
{RSP_OK, 721, 721, -1, 722, 5, {ACT_CMD + AT_ISO} },
|
||||
{RSP_OK, 722, 722, -1, 723, 5, {0}, "+VLS=17\r"},
|
||||
{RSP_OK, 723, 723, -1, 724, 5, {0} },
|
||||
{RSP_ZVLS, 724, 724, 17, 750, 50, {ACT_ACCEPTED} },
|
||||
{RSP_ERROR, 721, 729, -1, 0, 0, {ACT_ABORTACCEPT} },
|
||||
{EV_TIMEOUT, 721, 729, -1, 0, 0, {ACT_ABORTACCEPT} },
|
||||
{RSP_ZSAU, 700, 729, ZSAU_NULL, 0, 0, {ACT_ABORTACCEPT} },
|
||||
{RSP_ZSAU, 700, 729, ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT} },
|
||||
{RSP_ZSAU, 700, 729, ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT} },
|
||||
{EV_ACCEPT, -1, -1, -1, -1, -1, {ACT_ACCEPT} },
|
||||
{RSP_INIT, 720, 720, SEQ_ACCEPT, 721, 5, {ACT_CMD + AT_PROTO} },
|
||||
{RSP_OK, 721, 721, -1, 722, 5, {ACT_CMD + AT_ISO} },
|
||||
{RSP_OK, 722, 722, -1, 723, 5, {0}, "+VLS=17\r"},
|
||||
{RSP_OK, 723, 723, -1, 724, 5, {0} },
|
||||
{RSP_ZVLS, 724, 724, 17, 750, 50, {ACT_ACCEPTED} },
|
||||
{RSP_ERROR, 721, 729, -1, 0, 0, {ACT_ABORTACCEPT} },
|
||||
{EV_TIMEOUT, 721, 729, -1, 0, 0, {ACT_ABORTACCEPT} },
|
||||
{RSP_ZSAU, 700, 729, ZSAU_NULL, 0, 0, {ACT_ABORTACCEPT} },
|
||||
{RSP_ZSAU, 700, 729, ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT} },
|
||||
{RSP_ZSAU, 700, 729, ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT} },
|
||||
|
||||
{EV_BC_OPEN, 750, 750, -1, 751, -1},
|
||||
{EV_TIMEOUT, 750, 751, -1, 0, 0, {ACT_CONNTIMEOUT} },
|
||||
{EV_BC_OPEN, 750, 750, -1, 751, -1},
|
||||
{EV_TIMEOUT, 750, 751, -1, 0, 0, {ACT_CONNTIMEOUT} },
|
||||
|
||||
/* B channel closed (general case) */
|
||||
{EV_BC_CLOSED, -1, -1, -1, -1, -1, {ACT_NOTIFY_BC_DOWN} },
|
||||
{EV_BC_CLOSED, -1, -1, -1, -1, -1, {ACT_NOTIFY_BC_DOWN} },
|
||||
|
||||
/* misc. */
|
||||
{RSP_ZCON, -1, -1, -1, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} },
|
||||
{RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} },
|
||||
{RSP_ZCON, -1, -1, -1, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} },
|
||||
{RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} },
|
||||
{RSP_LAST}
|
||||
};
|
||||
|
||||
|
@ -648,16 +649,16 @@ static void disconnect(struct at_state_t **at_state_p)
|
|||
static inline struct at_state_t *get_free_channel(struct cardstate *cs,
|
||||
int cid)
|
||||
/* cids: >0: siemens-cid
|
||||
0: without cid
|
||||
-1: no cid assigned yet
|
||||
*/
|
||||
* 0: without cid
|
||||
* -1: no cid assigned yet
|
||||
*/
|
||||
{
|
||||
unsigned long flags;
|
||||
int i;
|
||||
struct at_state_t *ret;
|
||||
|
||||
for (i = 0; i < cs->channels; ++i)
|
||||
if (gigaset_get_channel(cs->bcs + i)) {
|
||||
if (gigaset_get_channel(cs->bcs + i) >= 0) {
|
||||
ret = &cs->bcs[i].at_state;
|
||||
ret->cid = cid;
|
||||
return ret;
|
||||
|
@ -922,18 +923,18 @@ static void do_stop(struct cardstate *cs)
|
|||
* channel >= 0: getting cid for the channel failed
|
||||
* channel < 0: entering cid mode failed
|
||||
*
|
||||
* returns 0 on failure
|
||||
* returns 0 on success, <0 on failure
|
||||
*/
|
||||
static int reinit_and_retry(struct cardstate *cs, int channel)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (--cs->retry_count <= 0)
|
||||
return 0;
|
||||
return -EFAULT;
|
||||
|
||||
for (i = 0; i < cs->channels; ++i)
|
||||
if (cs->bcs[i].at_state.cid > 0)
|
||||
return 0;
|
||||
return -EBUSY;
|
||||
|
||||
if (channel < 0)
|
||||
dev_warn(cs->dev,
|
||||
|
@ -944,7 +945,7 @@ static int reinit_and_retry(struct cardstate *cs, int channel)
|
|||
cs->bcs[channel].at_state.pending_commands |= PC_CID;
|
||||
}
|
||||
schedule_init(cs, MS_INIT);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int at_state_invalid(struct cardstate *cs,
|
||||
|
@ -1015,7 +1016,7 @@ static int do_lock(struct cardstate *cs)
|
|||
if (cs->bcs[i].at_state.pending_commands)
|
||||
return -EBUSY;
|
||||
|
||||
if (!gigaset_get_channels(cs))
|
||||
if (gigaset_get_channels(cs) < 0)
|
||||
return -EBUSY;
|
||||
|
||||
break;
|
||||
|
@ -1124,7 +1125,7 @@ static void do_action(int action, struct cardstate *cs,
|
|||
init_failed(cs, M_UNKNOWN);
|
||||
break;
|
||||
}
|
||||
if (!reinit_and_retry(cs, -1))
|
||||
if (reinit_and_retry(cs, -1) < 0)
|
||||
schedule_init(cs, MS_RECOVER);
|
||||
break;
|
||||
case ACT_FAILUMODE:
|
||||
|
@ -1267,7 +1268,7 @@ static void do_action(int action, struct cardstate *cs,
|
|||
case ACT_FAILCID:
|
||||
cs->cur_at_seq = SEQ_NONE;
|
||||
channel = cs->curchannel;
|
||||
if (!reinit_and_retry(cs, channel)) {
|
||||
if (reinit_and_retry(cs, channel) < 0) {
|
||||
dev_warn(cs->dev,
|
||||
"Could not get a call ID. Cannot dial.\n");
|
||||
at_state2 = &cs->bcs[channel].at_state;
|
||||
|
@ -1314,8 +1315,9 @@ static void do_action(int action, struct cardstate *cs,
|
|||
s = ev->ptr;
|
||||
|
||||
if (!strcmp(s, "OK")) {
|
||||
/* OK without version string: assume old response */
|
||||
*p_genresp = 1;
|
||||
*p_resp_code = RSP_ERROR;
|
||||
*p_resp_code = RSP_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1372,7 +1374,8 @@ static void do_action(int action, struct cardstate *cs,
|
|||
ev->parameter, at_state->ConState);
|
||||
break;
|
||||
|
||||
/* events from the LL */
|
||||
/* events from the LL */
|
||||
|
||||
case ACT_DIAL:
|
||||
start_dial(at_state, ev->ptr, ev->parameter);
|
||||
break;
|
||||
|
@ -1385,7 +1388,8 @@ static void do_action(int action, struct cardstate *cs,
|
|||
cs->commands_pending = 1;
|
||||
break;
|
||||
|
||||
/* hotplug events */
|
||||
/* hotplug events */
|
||||
|
||||
case ACT_STOP:
|
||||
do_stop(cs);
|
||||
break;
|
||||
|
@ -1393,7 +1397,8 @@ static void do_action(int action, struct cardstate *cs,
|
|||
do_start(cs);
|
||||
break;
|
||||
|
||||
/* events from the interface */
|
||||
/* events from the interface */
|
||||
|
||||
case ACT_IF_LOCK:
|
||||
cs->cmd_result = ev->parameter ? do_lock(cs) : do_unlock(cs);
|
||||
cs->waiting = 0;
|
||||
|
@ -1412,7 +1417,8 @@ static void do_action(int action, struct cardstate *cs,
|
|||
wake_up(&cs->waitqueue);
|
||||
break;
|
||||
|
||||
/* events from the proc file system */
|
||||
/* events from the proc file system */
|
||||
|
||||
case ACT_PROC_CIDMODE:
|
||||
spin_lock_irqsave(&cs->lock, flags);
|
||||
if (ev->parameter != cs->cidmode) {
|
||||
|
@ -1431,7 +1437,8 @@ static void do_action(int action, struct cardstate *cs,
|
|||
wake_up(&cs->waitqueue);
|
||||
break;
|
||||
|
||||
/* events from the hardware drivers */
|
||||
/* events from the hardware drivers */
|
||||
|
||||
case ACT_NOTIFY_BC_DOWN:
|
||||
bchannel_down(bcs);
|
||||
break;
|
||||
|
|
|
@ -163,8 +163,8 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
|
|||
#define BAS_LOWFRAME 5 /* " " with negative flow control */
|
||||
#define BAS_CORRFRAMES 4 /* flow control multiplicator */
|
||||
|
||||
#define BAS_INBUFSIZE (BAS_MAXFRAME * BAS_NUMFRAMES)
|
||||
/* size of isoc in buf per URB */
|
||||
#define BAS_INBUFSIZE (BAS_MAXFRAME * BAS_NUMFRAMES) /* size of isoc in buf
|
||||
* per URB */
|
||||
#define BAS_OUTBUFSIZE 4096 /* size of common isoc out buffer */
|
||||
#define BAS_OUTBUFPAD BAS_MAXFRAME /* size of pad area for isoc out buf */
|
||||
|
||||
|
@ -471,18 +471,18 @@ struct cardstate {
|
|||
for */
|
||||
int commands_pending; /* flag(s) in xxx.commands_pending have
|
||||
been set */
|
||||
struct tasklet_struct event_tasklet;
|
||||
/* tasklet for serializing AT commands.
|
||||
* Scheduled
|
||||
* -> for modem reponses (and
|
||||
* incoming data for M10x)
|
||||
* -> on timeout
|
||||
* -> after setting bits in
|
||||
* xxx.at_state.pending_command
|
||||
* (e.g. command from LL) */
|
||||
struct tasklet_struct write_tasklet;
|
||||
/* tasklet for serial output
|
||||
* (not used in base driver) */
|
||||
struct tasklet_struct
|
||||
event_tasklet; /* tasklet for serializing AT commands.
|
||||
* Scheduled
|
||||
* -> for modem reponses (and
|
||||
* incoming data for M10x)
|
||||
* -> on timeout
|
||||
* -> after setting bits in
|
||||
* xxx.at_state.pending_command
|
||||
* (e.g. command from LL) */
|
||||
struct tasklet_struct
|
||||
write_tasklet; /* tasklet for serial output
|
||||
* (not used in base driver) */
|
||||
|
||||
/* event queue */
|
||||
struct event_t events[MAX_EVENTS];
|
||||
|
@ -583,7 +583,7 @@ struct gigaset_ops {
|
|||
int (*initbcshw)(struct bc_state *bcs);
|
||||
|
||||
/* Called by gigaset_freecs() for freeing bcs->hw.xxx */
|
||||
int (*freebcshw)(struct bc_state *bcs);
|
||||
void (*freebcshw)(struct bc_state *bcs);
|
||||
|
||||
/* Called by gigaset_bchannel_down() for resetting bcs->hw.xxx */
|
||||
void (*reinitbcshw)(struct bc_state *bcs);
|
||||
|
|
|
@ -229,7 +229,7 @@ static int command_from_LL(isdn_ctrl *cntrl)
|
|||
return -EINVAL;
|
||||
}
|
||||
bcs = cs->bcs + ch;
|
||||
if (!gigaset_get_channel(bcs)) {
|
||||
if (gigaset_get_channel(bcs) < 0) {
|
||||
dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
@ -618,7 +618,7 @@ void gigaset_isdn_stop(struct cardstate *cs)
|
|||
* @cs: device descriptor structure.
|
||||
* @isdnid: device name.
|
||||
*
|
||||
* Return value: 1 for success, 0 for failure
|
||||
* Return value: 0 on success, error code < 0 on failure
|
||||
*/
|
||||
int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
|
||||
{
|
||||
|
@ -627,14 +627,14 @@ int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
|
|||
iif = kmalloc(sizeof *iif, GFP_KERNEL);
|
||||
if (!iif) {
|
||||
pr_err("out of memory\n");
|
||||
return 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (snprintf(iif->id, sizeof iif->id, "%s_%u", isdnid, cs->minor_index)
|
||||
>= sizeof iif->id) {
|
||||
pr_err("ID too long: %s\n", isdnid);
|
||||
kfree(iif);
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
iif->owner = THIS_MODULE;
|
||||
|
@ -656,13 +656,13 @@ int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
|
|||
if (!register_isdn(iif)) {
|
||||
pr_err("register_isdn failed\n");
|
||||
kfree(iif);
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cs->iif = iif;
|
||||
cs->myid = iif->channels; /* Set my device id */
|
||||
cs->hw_hdr_len = HW_HDR_LEN;
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -56,7 +56,7 @@ static inline int isowbuf_freebytes(struct isowbuf_t *iwb)
|
|||
|
||||
/* start writing
|
||||
* acquire the write semaphore
|
||||
* return true if acquired, false if busy
|
||||
* return 0 if acquired, <0 if busy
|
||||
*/
|
||||
static inline int isowbuf_startwrite(struct isowbuf_t *iwb)
|
||||
{
|
||||
|
@ -64,12 +64,12 @@ static inline int isowbuf_startwrite(struct isowbuf_t *iwb)
|
|||
atomic_inc(&iwb->writesem);
|
||||
gig_dbg(DEBUG_ISO, "%s: couldn't acquire iso write semaphore",
|
||||
__func__);
|
||||
return 0;
|
||||
return -EBUSY;
|
||||
}
|
||||
gig_dbg(DEBUG_ISO,
|
||||
"%s: acquired iso write semaphore, data[write]=%02x, nbits=%d",
|
||||
__func__, iwb->data[iwb->write], iwb->wbits);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* finish writing
|
||||
|
@ -158,7 +158,7 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size)
|
|||
/* no wraparound in valid data */
|
||||
if (limit >= write) {
|
||||
/* append idle frame */
|
||||
if (!isowbuf_startwrite(iwb))
|
||||
if (isowbuf_startwrite(iwb) < 0)
|
||||
return -EBUSY;
|
||||
/* write position could have changed */
|
||||
write = iwb->write;
|
||||
|
@ -403,7 +403,7 @@ static inline int hdlc_buildframe(struct isowbuf_t *iwb,
|
|||
unsigned char c;
|
||||
|
||||
if (isowbuf_freebytes(iwb) < count + count / 5 + 6 ||
|
||||
!isowbuf_startwrite(iwb)) {
|
||||
isowbuf_startwrite(iwb) < 0) {
|
||||
gig_dbg(DEBUG_ISO, "%s: %d bytes free -> -EAGAIN",
|
||||
__func__, isowbuf_freebytes(iwb));
|
||||
return -EAGAIN;
|
||||
|
@ -457,7 +457,7 @@ static inline int trans_buildframe(struct isowbuf_t *iwb,
|
|||
return iwb->write;
|
||||
|
||||
if (isowbuf_freebytes(iwb) < count ||
|
||||
!isowbuf_startwrite(iwb)) {
|
||||
isowbuf_startwrite(iwb) < 0) {
|
||||
gig_dbg(DEBUG_ISO, "can't put %d bytes", count);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
|
|
@ -340,17 +340,16 @@ static int gigaset_initbcshw(struct bc_state *bcs)
|
|||
{
|
||||
/* unused */
|
||||
bcs->hw.ser = NULL;
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free B channel structure
|
||||
* Called by "gigaset_freebcs" in common.c
|
||||
*/
|
||||
static int gigaset_freebcshw(struct bc_state *bcs)
|
||||
static void gigaset_freebcshw(struct bc_state *bcs)
|
||||
{
|
||||
/* unused */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -398,7 +397,7 @@ static int gigaset_initcshw(struct cardstate *cs)
|
|||
scs = kzalloc(sizeof(struct ser_cardstate), GFP_KERNEL);
|
||||
if (!scs) {
|
||||
pr_err("out of memory\n");
|
||||
return 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
cs->hw.ser = scs;
|
||||
|
||||
|
@ -410,13 +409,13 @@ static int gigaset_initcshw(struct cardstate *cs)
|
|||
pr_err("error %d registering platform device\n", rc);
|
||||
kfree(cs->hw.ser);
|
||||
cs->hw.ser = NULL;
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
dev_set_drvdata(&cs->hw.ser->dev.dev, cs);
|
||||
|
||||
tasklet_init(&cs->write_tasklet,
|
||||
gigaset_modem_fill, (unsigned long) cs);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -503,6 +502,7 @@ static int
|
|||
gigaset_tty_open(struct tty_struct *tty)
|
||||
{
|
||||
struct cardstate *cs;
|
||||
int rc;
|
||||
|
||||
gig_dbg(DEBUG_INIT, "Starting HLL for Gigaset M101");
|
||||
|
||||
|
@ -515,8 +515,10 @@ gigaset_tty_open(struct tty_struct *tty)
|
|||
|
||||
/* allocate memory for our device state and initialize it */
|
||||
cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME);
|
||||
if (!cs)
|
||||
if (!cs) {
|
||||
rc = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
|
||||
cs->dev = &cs->hw.ser->dev.dev;
|
||||
cs->hw.ser->tty = tty;
|
||||
|
@ -530,7 +532,8 @@ gigaset_tty_open(struct tty_struct *tty)
|
|||
*/
|
||||
if (startmode == SM_LOCKED)
|
||||
cs->mstate = MS_LOCKED;
|
||||
if (!gigaset_start(cs)) {
|
||||
rc = gigaset_start(cs);
|
||||
if (rc < 0) {
|
||||
tasklet_kill(&cs->write_tasklet);
|
||||
goto error;
|
||||
}
|
||||
|
@ -542,7 +545,7 @@ error:
|
|||
gig_dbg(DEBUG_INIT, "Startup of HLL failed");
|
||||
tty->disc_data = NULL;
|
||||
gigaset_freecs(cs);
|
||||
return -ENODEV;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -549,10 +549,9 @@ static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6])
|
|||
0, 0, &buf, 6, 2000);
|
||||
}
|
||||
|
||||
static int gigaset_freebcshw(struct bc_state *bcs)
|
||||
static void gigaset_freebcshw(struct bc_state *bcs)
|
||||
{
|
||||
/* unused */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Initialize the b-channel structure */
|
||||
|
@ -560,7 +559,7 @@ static int gigaset_initbcshw(struct bc_state *bcs)
|
|||
{
|
||||
/* unused */
|
||||
bcs->hw.usb = NULL;
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gigaset_reinitbcshw(struct bc_state *bcs)
|
||||
|
@ -582,7 +581,7 @@ static int gigaset_initcshw(struct cardstate *cs)
|
|||
kmalloc(sizeof(struct usb_cardstate), GFP_KERNEL);
|
||||
if (!ucs) {
|
||||
pr_err("out of memory\n");
|
||||
return 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ucs->bchars[0] = 0;
|
||||
|
@ -597,7 +596,7 @@ static int gigaset_initcshw(struct cardstate *cs)
|
|||
tasklet_init(&cs->write_tasklet,
|
||||
gigaset_modem_fill, (unsigned long) cs);
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Send data from current skb to the device. */
|
||||
|
@ -766,9 +765,9 @@ static int gigaset_probe(struct usb_interface *interface,
|
|||
if (startmode == SM_LOCKED)
|
||||
cs->mstate = MS_LOCKED;
|
||||
|
||||
if (!gigaset_start(cs)) {
|
||||
retval = gigaset_start(cs);
|
||||
if (retval < 0) {
|
||||
tasklet_kill(&cs->write_tasklet);
|
||||
retval = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
return 0;
|
||||
|
@ -898,8 +897,10 @@ static int __init usb_gigaset_init(void)
|
|||
driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
|
||||
GIGASET_MODULENAME, GIGASET_DEVNAME,
|
||||
&ops, THIS_MODULE);
|
||||
if (driver == NULL)
|
||||
if (driver == NULL) {
|
||||
result = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* register this driver with the USB subsystem */
|
||||
result = usb_register(&gigaset_usb_driver);
|
||||
|
@ -915,7 +916,7 @@ error:
|
|||
if (driver)
|
||||
gigaset_freedriver(driver);
|
||||
driver = NULL;
|
||||
return -1;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1120,7 +1120,7 @@ int fax_head_line_time(char *buffer)
|
|||
/*
|
||||
* init (alloc) main structures
|
||||
*/
|
||||
static int DIVA_INIT_FUNCTION init_main_structs(void)
|
||||
static int __init init_main_structs(void)
|
||||
{
|
||||
if (!(mapped_msg = (CAPI_MSG *) diva_os_malloc(0, MAX_MSG_SIZE))) {
|
||||
DBG_ERR(("init: failed alloc mapped_msg."))
|
||||
|
@ -1181,7 +1181,7 @@ static void do_api_remove_start(void)
|
|||
/*
|
||||
* init
|
||||
*/
|
||||
int DIVA_INIT_FUNCTION init_capifunc(void)
|
||||
int __init init_capifunc(void)
|
||||
{
|
||||
diva_os_initialize_spin_lock(&api_lock, "capifunc");
|
||||
memset(ControllerMap, 0, MAX_DESCRIPTORS + 1);
|
||||
|
@ -1209,7 +1209,7 @@ int DIVA_INIT_FUNCTION init_capifunc(void)
|
|||
/*
|
||||
* finit
|
||||
*/
|
||||
void DIVA_EXIT_FUNCTION finit_capifunc(void)
|
||||
void __exit finit_capifunc(void)
|
||||
{
|
||||
do_api_remove_start();
|
||||
divacapi_disconnect_didd();
|
||||
|
|
|
@ -118,7 +118,7 @@ void diva_os_set_controller_struct(struct capi_ctr *ctrl)
|
|||
/*
|
||||
* module init
|
||||
*/
|
||||
static int DIVA_INIT_FUNCTION divacapi_init(void)
|
||||
static int __init divacapi_init(void)
|
||||
{
|
||||
char tmprev[32];
|
||||
int ret = 0;
|
||||
|
@ -144,7 +144,7 @@ static int DIVA_INIT_FUNCTION divacapi_init(void)
|
|||
/*
|
||||
* module exit
|
||||
*/
|
||||
static void DIVA_EXIT_FUNCTION divacapi_exit(void)
|
||||
static void __exit divacapi_exit(void)
|
||||
{
|
||||
finit_capifunc();
|
||||
printk(KERN_INFO "%s: module unloaded.\n", DRIVERLNAME);
|
||||
|
|
|
@ -47,7 +47,7 @@ static void *didd_callback(void *context, DESCRIPTOR *adapter,
|
|||
/*
|
||||
* connect to didd
|
||||
*/
|
||||
static int DIVA_INIT_FUNCTION connect_didd(void)
|
||||
static int __init connect_didd(void)
|
||||
{
|
||||
int x = 0;
|
||||
int dadapter = 0;
|
||||
|
@ -79,7 +79,7 @@ static int DIVA_INIT_FUNCTION connect_didd(void)
|
|||
/*
|
||||
* disconnect from didd
|
||||
*/
|
||||
static void DIVA_EXIT_FUNCTION disconnect_didd(void)
|
||||
static void __exit disconnect_didd(void)
|
||||
{
|
||||
IDI_SYNC_REQ req;
|
||||
|
||||
|
@ -92,7 +92,7 @@ static void DIVA_EXIT_FUNCTION disconnect_didd(void)
|
|||
/*
|
||||
* init
|
||||
*/
|
||||
int DIVA_INIT_FUNCTION diddfunc_init(void)
|
||||
int __init diddfunc_init(void)
|
||||
{
|
||||
diva_didd_load_time_init();
|
||||
|
||||
|
@ -107,7 +107,7 @@ int DIVA_INIT_FUNCTION diddfunc_init(void)
|
|||
/*
|
||||
* finit
|
||||
*/
|
||||
void DIVA_EXIT_FUNCTION diddfunc_finit(void)
|
||||
void __exit diddfunc_finit(void)
|
||||
{
|
||||
DbgDeregister();
|
||||
disconnect_didd();
|
||||
|
|
|
@ -91,7 +91,7 @@ static const struct file_operations divadidd_proc_fops = {
|
|||
.release = single_release,
|
||||
};
|
||||
|
||||
static int DIVA_INIT_FUNCTION create_proc(void)
|
||||
static int __init create_proc(void)
|
||||
{
|
||||
proc_net_eicon = proc_mkdir("eicon", init_net.proc_net);
|
||||
|
||||
|
@ -109,7 +109,7 @@ static void remove_proc(void)
|
|||
remove_proc_entry("eicon", init_net.proc_net);
|
||||
}
|
||||
|
||||
static int DIVA_INIT_FUNCTION divadidd_init(void)
|
||||
static int __init divadidd_init(void)
|
||||
{
|
||||
char tmprev[32];
|
||||
int ret = 0;
|
||||
|
@ -141,7 +141,7 @@ out:
|
|||
return (ret);
|
||||
}
|
||||
|
||||
static void DIVA_EXIT_FUNCTION divadidd_exit(void)
|
||||
static void __exit divadidd_exit(void)
|
||||
{
|
||||
diddfunc_finit();
|
||||
remove_proc();
|
||||
|
|
|
@ -184,7 +184,7 @@ static void divas_maint_unregister_chrdev(void)
|
|||
unregister_chrdev(major, DEVNAME);
|
||||
}
|
||||
|
||||
static int DIVA_INIT_FUNCTION divas_maint_register_chrdev(void)
|
||||
static int __init divas_maint_register_chrdev(void)
|
||||
{
|
||||
if ((major = register_chrdev(0, DEVNAME, &divas_maint_fops)) < 0)
|
||||
{
|
||||
|
@ -207,7 +207,7 @@ void diva_maint_wakeup_read(void)
|
|||
/*
|
||||
* Driver Load
|
||||
*/
|
||||
static int DIVA_INIT_FUNCTION maint_init(void)
|
||||
static int __init maint_init(void)
|
||||
{
|
||||
char tmprev[50];
|
||||
int ret = 0;
|
||||
|
@ -245,7 +245,7 @@ out:
|
|||
/*
|
||||
** Driver Unload
|
||||
*/
|
||||
static void DIVA_EXIT_FUNCTION maint_exit(void)
|
||||
static void __exit maint_exit(void)
|
||||
{
|
||||
divas_maint_unregister_chrdev();
|
||||
mntfunc_finit();
|
||||
|
|
|
@ -153,7 +153,7 @@ static void *didd_callback(void *context, DESCRIPTOR *adapter,
|
|||
/*
|
||||
* connect to didd
|
||||
*/
|
||||
static int DIVA_INIT_FUNCTION connect_didd(void)
|
||||
static int __init connect_didd(void)
|
||||
{
|
||||
int x = 0;
|
||||
int dadapter = 0;
|
||||
|
@ -209,7 +209,7 @@ static void disconnect_didd(void)
|
|||
/*
|
||||
* init
|
||||
*/
|
||||
int DIVA_INIT_FUNCTION divasfunc_init(int dbgmask)
|
||||
int __init divasfunc_init(int dbgmask)
|
||||
{
|
||||
char *version;
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ static const struct file_operations um_idi_proc_fops = {
|
|||
.release = single_release,
|
||||
};
|
||||
|
||||
static int DIVA_INIT_FUNCTION create_um_idi_proc(void)
|
||||
static int __init create_um_idi_proc(void)
|
||||
{
|
||||
um_idi_proc_entry = proc_create(DRIVERLNAME, S_IRUGO, proc_net_eicon,
|
||||
&um_idi_proc_fops);
|
||||
|
@ -146,7 +146,7 @@ static void divas_idi_unregister_chrdev(void)
|
|||
unregister_chrdev(major, DEVNAME);
|
||||
}
|
||||
|
||||
static int DIVA_INIT_FUNCTION divas_idi_register_chrdev(void)
|
||||
static int __init divas_idi_register_chrdev(void)
|
||||
{
|
||||
if ((major = register_chrdev(0, DEVNAME, &divas_idi_fops)) < 0)
|
||||
{
|
||||
|
@ -161,7 +161,7 @@ static int DIVA_INIT_FUNCTION divas_idi_register_chrdev(void)
|
|||
/*
|
||||
** Driver Load
|
||||
*/
|
||||
static int DIVA_INIT_FUNCTION divasi_init(void)
|
||||
static int __init divasi_init(void)
|
||||
{
|
||||
char tmprev[50];
|
||||
int ret = 0;
|
||||
|
@ -202,7 +202,7 @@ out:
|
|||
/*
|
||||
** Driver Unload
|
||||
*/
|
||||
static void DIVA_EXIT_FUNCTION divasi_exit(void)
|
||||
static void __exit divasi_exit(void)
|
||||
{
|
||||
idifunc_finit();
|
||||
remove_um_idi_proc();
|
||||
|
|
|
@ -673,7 +673,7 @@ static void divas_unregister_chrdev(void)
|
|||
unregister_chrdev(major, DEVNAME);
|
||||
}
|
||||
|
||||
static int DIVA_INIT_FUNCTION divas_register_chrdev(void)
|
||||
static int __init divas_register_chrdev(void)
|
||||
{
|
||||
if ((major = register_chrdev(0, DEVNAME, &divas_fops)) < 0)
|
||||
{
|
||||
|
@ -767,7 +767,7 @@ static void __devexit divas_remove_one(struct pci_dev *pdev)
|
|||
/* --------------------------------------------------------------------------
|
||||
Driver Load / Startup
|
||||
-------------------------------------------------------------------------- */
|
||||
static int DIVA_INIT_FUNCTION divas_init(void)
|
||||
static int __init divas_init(void)
|
||||
{
|
||||
char tmprev[50];
|
||||
int ret = 0;
|
||||
|
@ -831,7 +831,7 @@ out:
|
|||
/* --------------------------------------------------------------------------
|
||||
Driver Unload
|
||||
-------------------------------------------------------------------------- */
|
||||
static void DIVA_EXIT_FUNCTION divas_exit(void)
|
||||
static void __exit divas_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&diva_pci_driver);
|
||||
remove_divas_proc();
|
||||
|
|
|
@ -133,7 +133,7 @@ static void um_remove_card(DESCRIPTOR *d)
|
|||
/*
|
||||
* remove all adapter
|
||||
*/
|
||||
static void DIVA_EXIT_FUNCTION remove_all_idi_proc(void)
|
||||
static void __exit remove_all_idi_proc(void)
|
||||
{
|
||||
udiva_card *card;
|
||||
diva_os_spin_lock_magic_t old_irql;
|
||||
|
@ -181,7 +181,7 @@ static void *didd_callback(void *context, DESCRIPTOR *adapter,
|
|||
/*
|
||||
* connect DIDD
|
||||
*/
|
||||
static int DIVA_INIT_FUNCTION connect_didd(void)
|
||||
static int __init connect_didd(void)
|
||||
{
|
||||
int x = 0;
|
||||
int dadapter = 0;
|
||||
|
@ -225,7 +225,7 @@ static int DIVA_INIT_FUNCTION connect_didd(void)
|
|||
/*
|
||||
* Disconnect from DIDD
|
||||
*/
|
||||
static void DIVA_EXIT_FUNCTION disconnect_didd(void)
|
||||
static void __exit disconnect_didd(void)
|
||||
{
|
||||
IDI_SYNC_REQ req;
|
||||
|
||||
|
@ -240,7 +240,7 @@ static void DIVA_EXIT_FUNCTION disconnect_didd(void)
|
|||
/*
|
||||
* init
|
||||
*/
|
||||
int DIVA_INIT_FUNCTION idifunc_init(void)
|
||||
int __init idifunc_init(void)
|
||||
{
|
||||
diva_os_initialize_spin_lock(&ll_lock, "idifunc");
|
||||
|
||||
|
@ -260,7 +260,7 @@ int DIVA_INIT_FUNCTION idifunc_init(void)
|
|||
/*
|
||||
* finit
|
||||
*/
|
||||
void DIVA_EXIT_FUNCTION idifunc_finit(void)
|
||||
void __exit idifunc_finit(void)
|
||||
{
|
||||
diva_user_mode_idi_finit();
|
||||
disconnect_didd();
|
||||
|
|
|
@ -72,7 +72,7 @@ static void *didd_callback(void *context, DESCRIPTOR *adapter,
|
|||
/*
|
||||
* connect to didd
|
||||
*/
|
||||
static int DIVA_INIT_FUNCTION connect_didd(void)
|
||||
static int __init connect_didd(void)
|
||||
{
|
||||
int x = 0;
|
||||
int dadapter = 0;
|
||||
|
@ -114,7 +114,7 @@ static int DIVA_INIT_FUNCTION connect_didd(void)
|
|||
/*
|
||||
* disconnect from didd
|
||||
*/
|
||||
static void DIVA_EXIT_FUNCTION disconnect_didd(void)
|
||||
static void __exit disconnect_didd(void)
|
||||
{
|
||||
IDI_SYNC_REQ req;
|
||||
|
||||
|
@ -300,7 +300,7 @@ int maint_read_write(void __user *buf, int count)
|
|||
/*
|
||||
* init
|
||||
*/
|
||||
int DIVA_INIT_FUNCTION mntfunc_init(int *buffer_length, void **buffer,
|
||||
int __init mntfunc_init(int *buffer_length, void **buffer,
|
||||
unsigned long diva_dbg_mem)
|
||||
{
|
||||
if (*buffer_length < 64) {
|
||||
|
@ -348,7 +348,7 @@ int DIVA_INIT_FUNCTION mntfunc_init(int *buffer_length, void **buffer,
|
|||
/*
|
||||
* exit
|
||||
*/
|
||||
void DIVA_EXIT_FUNCTION mntfunc_finit(void)
|
||||
void __exit mntfunc_finit(void)
|
||||
{
|
||||
void *buffer;
|
||||
int i = 100;
|
||||
|
|
|
@ -38,9 +38,6 @@
|
|||
#define DIVA_NO_DEBUGLIB
|
||||
#endif
|
||||
|
||||
#define DIVA_INIT_FUNCTION __init
|
||||
#define DIVA_EXIT_FUNCTION __exit
|
||||
|
||||
#define DIVA_USER_MODE_CARD_CONFIG 1
|
||||
#define USE_EXTENDED_DEBUGS 1
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include "ipac.h"
|
||||
|
||||
|
||||
#define AVMFRITZ_REV "2.1"
|
||||
#define AVMFRITZ_REV "2.3"
|
||||
|
||||
static int AVM_cnt;
|
||||
static int debug;
|
||||
|
@ -69,6 +69,7 @@ enum {
|
|||
#define HDLC_MODE_TRANS 0x02
|
||||
#define HDLC_MODE_CCR_7 0x04
|
||||
#define HDLC_MODE_CCR_16 0x08
|
||||
#define HDLC_FIFO_SIZE_128 0x20
|
||||
#define HDLC_MODE_TESTLOOP 0x80
|
||||
|
||||
#define HDLC_INT_XPR 0x80
|
||||
|
@ -80,13 +81,16 @@ enum {
|
|||
#define HDLC_STAT_RDO 0x10
|
||||
#define HDLC_STAT_CRCVFRRAB 0x0E
|
||||
#define HDLC_STAT_CRCVFR 0x06
|
||||
#define HDLC_STAT_RML_MASK 0x3f00
|
||||
#define HDLC_STAT_RML_MASK_V1 0x3f00
|
||||
#define HDLC_STAT_RML_MASK_V2 0x7f00
|
||||
|
||||
#define HDLC_CMD_XRS 0x80
|
||||
#define HDLC_CMD_XME 0x01
|
||||
#define HDLC_CMD_RRS 0x20
|
||||
#define HDLC_CMD_XML_MASK 0x3f00
|
||||
#define HDLC_FIFO_SIZE 32
|
||||
|
||||
#define HDLC_FIFO_SIZE_V1 32
|
||||
#define HDLC_FIFO_SIZE_V2 128
|
||||
|
||||
/* Fritz PCI v2.0 */
|
||||
|
||||
|
@ -346,11 +350,14 @@ modehdlc(struct bchannel *bch, int protocol)
|
|||
{
|
||||
struct fritzcard *fc = bch->hw;
|
||||
struct hdlc_hw *hdlc;
|
||||
u8 mode;
|
||||
|
||||
hdlc = &fc->hdlc[(bch->nr - 1) & 1];
|
||||
pr_debug("%s: hdlc %c protocol %x-->%x ch %d\n", fc->name,
|
||||
'@' + bch->nr, bch->state, protocol, bch->nr);
|
||||
hdlc->ctrl.ctrl = 0;
|
||||
mode = (fc->type == AVM_FRITZ_PCIV2) ? HDLC_FIFO_SIZE_128 : 0;
|
||||
|
||||
switch (protocol) {
|
||||
case -1: /* used for init */
|
||||
bch->state = -1;
|
||||
|
@ -358,7 +365,7 @@ modehdlc(struct bchannel *bch, int protocol)
|
|||
if (bch->state == ISDN_P_NONE)
|
||||
break;
|
||||
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
|
||||
hdlc->ctrl.sr.mode = HDLC_MODE_TRANS;
|
||||
hdlc->ctrl.sr.mode = mode | HDLC_MODE_TRANS;
|
||||
write_ctrl(bch, 5);
|
||||
bch->state = ISDN_P_NONE;
|
||||
test_and_clear_bit(FLG_HDLC, &bch->Flags);
|
||||
|
@ -367,7 +374,7 @@ modehdlc(struct bchannel *bch, int protocol)
|
|||
case ISDN_P_B_RAW:
|
||||
bch->state = protocol;
|
||||
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
|
||||
hdlc->ctrl.sr.mode = HDLC_MODE_TRANS;
|
||||
hdlc->ctrl.sr.mode = mode | HDLC_MODE_TRANS;
|
||||
write_ctrl(bch, 5);
|
||||
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;
|
||||
write_ctrl(bch, 1);
|
||||
|
@ -377,7 +384,7 @@ modehdlc(struct bchannel *bch, int protocol)
|
|||
case ISDN_P_B_HDLC:
|
||||
bch->state = protocol;
|
||||
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS;
|
||||
hdlc->ctrl.sr.mode = HDLC_MODE_ITF_FLG;
|
||||
hdlc->ctrl.sr.mode = mode | HDLC_MODE_ITF_FLG;
|
||||
write_ctrl(bch, 5);
|
||||
hdlc->ctrl.sr.cmd = HDLC_CMD_XRS;
|
||||
write_ctrl(bch, 1);
|
||||
|
@ -397,39 +404,40 @@ hdlc_empty_fifo(struct bchannel *bch, int count)
|
|||
u32 *ptr;
|
||||
u8 *p;
|
||||
u32 val, addr;
|
||||
int cnt = 0;
|
||||
int cnt;
|
||||
struct fritzcard *fc = bch->hw;
|
||||
|
||||
pr_debug("%s: %s %d\n", fc->name, __func__, count);
|
||||
if (!bch->rx_skb) {
|
||||
bch->rx_skb = mI_alloc_skb(bch->maxlen, GFP_ATOMIC);
|
||||
if (!bch->rx_skb) {
|
||||
pr_info("%s: B receive out of memory\n",
|
||||
fc->name);
|
||||
if (test_bit(FLG_RX_OFF, &bch->Flags)) {
|
||||
p = NULL;
|
||||
bch->dropcnt += count;
|
||||
} else {
|
||||
cnt = bchannel_get_rxbuf(bch, count);
|
||||
if (cnt < 0) {
|
||||
pr_warning("%s.B%d: No bufferspace for %d bytes\n",
|
||||
fc->name, bch->nr, count);
|
||||
return;
|
||||
}
|
||||
p = skb_put(bch->rx_skb, count);
|
||||
}
|
||||
if ((bch->rx_skb->len + count) > bch->maxlen) {
|
||||
pr_debug("%s: overrun %d\n", fc->name,
|
||||
bch->rx_skb->len + count);
|
||||
return;
|
||||
}
|
||||
p = skb_put(bch->rx_skb, count);
|
||||
ptr = (u32 *)p;
|
||||
if (AVM_FRITZ_PCIV2 == fc->type)
|
||||
if (fc->type == AVM_FRITZ_PCIV2)
|
||||
addr = fc->addr + (bch->nr == 2 ?
|
||||
AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1);
|
||||
else {
|
||||
addr = fc->addr + CHIP_WINDOW;
|
||||
outl(bch->nr == 2 ? AVM_HDLC_2 : AVM_HDLC_1, fc->addr);
|
||||
}
|
||||
cnt = 0;
|
||||
while (cnt < count) {
|
||||
val = le32_to_cpu(inl(addr));
|
||||
put_unaligned(val, ptr);
|
||||
ptr++;
|
||||
if (p) {
|
||||
put_unaligned(val, ptr);
|
||||
ptr++;
|
||||
}
|
||||
cnt += 4;
|
||||
}
|
||||
if (debug & DEBUG_HW_BFIFO) {
|
||||
if (p && (debug & DEBUG_HW_BFIFO)) {
|
||||
snprintf(fc->log, LOG_SIZE, "B%1d-recv %s %d ",
|
||||
bch->nr, fc->name, count);
|
||||
print_hex_dump_bytes(fc->log, DUMP_PREFIX_OFFSET, p, count);
|
||||
|
@ -441,30 +449,43 @@ hdlc_fill_fifo(struct bchannel *bch)
|
|||
{
|
||||
struct fritzcard *fc = bch->hw;
|
||||
struct hdlc_hw *hdlc;
|
||||
int count, cnt = 0;
|
||||
int count, fs, cnt = 0, idx, fillempty = 0;
|
||||
u8 *p;
|
||||
u32 *ptr, val, addr;
|
||||
|
||||
hdlc = &fc->hdlc[(bch->nr - 1) & 1];
|
||||
if (!bch->tx_skb)
|
||||
return;
|
||||
count = bch->tx_skb->len - bch->tx_idx;
|
||||
if (count <= 0)
|
||||
return;
|
||||
p = bch->tx_skb->data + bch->tx_idx;
|
||||
idx = (bch->nr - 1) & 1;
|
||||
hdlc = &fc->hdlc[idx];
|
||||
fs = (fc->type == AVM_FRITZ_PCIV2) ?
|
||||
HDLC_FIFO_SIZE_V2 : HDLC_FIFO_SIZE_V1;
|
||||
if (!bch->tx_skb) {
|
||||
if (!test_bit(FLG_TX_EMPTY, &bch->Flags))
|
||||
return;
|
||||
count = fs;
|
||||
p = bch->fill;
|
||||
fillempty = 1;
|
||||
} else {
|
||||
count = bch->tx_skb->len - bch->tx_idx;
|
||||
if (count <= 0)
|
||||
return;
|
||||
p = bch->tx_skb->data + bch->tx_idx;
|
||||
}
|
||||
hdlc->ctrl.sr.cmd &= ~HDLC_CMD_XME;
|
||||
if (count > HDLC_FIFO_SIZE) {
|
||||
count = HDLC_FIFO_SIZE;
|
||||
if (count > fs) {
|
||||
count = fs;
|
||||
} else {
|
||||
if (test_bit(FLG_HDLC, &bch->Flags))
|
||||
hdlc->ctrl.sr.cmd |= HDLC_CMD_XME;
|
||||
}
|
||||
pr_debug("%s: %s %d/%d/%d", fc->name, __func__, count,
|
||||
bch->tx_idx, bch->tx_skb->len);
|
||||
ptr = (u32 *)p;
|
||||
bch->tx_idx += count;
|
||||
hdlc->ctrl.sr.xml = ((count == HDLC_FIFO_SIZE) ? 0 : count);
|
||||
if (AVM_FRITZ_PCIV2 == fc->type) {
|
||||
if (fillempty) {
|
||||
pr_debug("%s.B%d: %d/%d/%d", fc->name, bch->nr, count,
|
||||
bch->tx_idx, bch->tx_skb->len);
|
||||
bch->tx_idx += count;
|
||||
} else {
|
||||
pr_debug("%s.B%d: fillempty %d\n", fc->name, bch->nr, count);
|
||||
}
|
||||
hdlc->ctrl.sr.xml = ((count == fs) ? 0 : count);
|
||||
if (fc->type == AVM_FRITZ_PCIV2) {
|
||||
__write_ctrl_pciv2(fc, hdlc, bch->nr);
|
||||
addr = fc->addr + (bch->nr == 2 ?
|
||||
AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1);
|
||||
|
@ -472,13 +493,21 @@ hdlc_fill_fifo(struct bchannel *bch)
|
|||
__write_ctrl_pci(fc, hdlc, bch->nr);
|
||||
addr = fc->addr + CHIP_WINDOW;
|
||||
}
|
||||
while (cnt < count) {
|
||||
val = get_unaligned(ptr);
|
||||
outl(cpu_to_le32(val), addr);
|
||||
ptr++;
|
||||
cnt += 4;
|
||||
if (fillempty) {
|
||||
while (cnt < count) {
|
||||
/* all bytes the same - no worry about endian */
|
||||
outl(*ptr, addr);
|
||||
cnt += 4;
|
||||
}
|
||||
} else {
|
||||
while (cnt < count) {
|
||||
val = get_unaligned(ptr);
|
||||
outl(cpu_to_le32(val), addr);
|
||||
ptr++;
|
||||
cnt += 4;
|
||||
}
|
||||
}
|
||||
if (debug & DEBUG_HW_BFIFO) {
|
||||
if ((debug & DEBUG_HW_BFIFO) && !fillempty) {
|
||||
snprintf(fc->log, LOG_SIZE, "B%1d-send %s %d ",
|
||||
bch->nr, fc->name, count);
|
||||
print_hex_dump_bytes(fc->log, DUMP_PREFIX_OFFSET, p, count);
|
||||
|
@ -488,17 +517,17 @@ hdlc_fill_fifo(struct bchannel *bch)
|
|||
static void
|
||||
HDLC_irq_xpr(struct bchannel *bch)
|
||||
{
|
||||
if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len)
|
||||
if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len) {
|
||||
hdlc_fill_fifo(bch);
|
||||
else {
|
||||
if (bch->tx_skb) {
|
||||
/* send confirm, on trans, free on hdlc. */
|
||||
if (test_bit(FLG_TRANSPARENT, &bch->Flags))
|
||||
confirm_Bsend(bch);
|
||||
} else {
|
||||
if (bch->tx_skb)
|
||||
dev_kfree_skb(bch->tx_skb);
|
||||
}
|
||||
if (get_next_bframe(bch))
|
||||
if (get_next_bframe(bch)) {
|
||||
hdlc_fill_fifo(bch);
|
||||
test_and_clear_bit(FLG_TX_EMPTY, &bch->Flags);
|
||||
} else if (test_bit(FLG_TX_EMPTY, &bch->Flags)) {
|
||||
hdlc_fill_fifo(bch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -506,13 +535,23 @@ static void
|
|||
HDLC_irq(struct bchannel *bch, u32 stat)
|
||||
{
|
||||
struct fritzcard *fc = bch->hw;
|
||||
int len;
|
||||
int len, fs;
|
||||
u32 rmlMask;
|
||||
struct hdlc_hw *hdlc;
|
||||
|
||||
hdlc = &fc->hdlc[(bch->nr - 1) & 1];
|
||||
pr_debug("%s: ch%d stat %#x\n", fc->name, bch->nr, stat);
|
||||
if (fc->type == AVM_FRITZ_PCIV2) {
|
||||
rmlMask = HDLC_STAT_RML_MASK_V2;
|
||||
fs = HDLC_FIFO_SIZE_V2;
|
||||
} else {
|
||||
rmlMask = HDLC_STAT_RML_MASK_V1;
|
||||
fs = HDLC_FIFO_SIZE_V1;
|
||||
}
|
||||
if (stat & HDLC_INT_RPR) {
|
||||
if (stat & HDLC_STAT_RDO) {
|
||||
pr_warning("%s: ch%d stat %x RDO\n",
|
||||
fc->name, bch->nr, stat);
|
||||
hdlc->ctrl.sr.xml = 0;
|
||||
hdlc->ctrl.sr.cmd |= HDLC_CMD_RRS;
|
||||
write_ctrl(bch, 1);
|
||||
|
@ -521,21 +560,21 @@ HDLC_irq(struct bchannel *bch, u32 stat)
|
|||
if (bch->rx_skb)
|
||||
skb_trim(bch->rx_skb, 0);
|
||||
} else {
|
||||
len = (stat & HDLC_STAT_RML_MASK) >> 8;
|
||||
len = (stat & rmlMask) >> 8;
|
||||
if (!len)
|
||||
len = 32;
|
||||
len = fs;
|
||||
hdlc_empty_fifo(bch, len);
|
||||
if (!bch->rx_skb)
|
||||
goto handle_tx;
|
||||
if ((stat & HDLC_STAT_RME) || test_bit(FLG_TRANSPARENT,
|
||||
&bch->Flags)) {
|
||||
if (((stat & HDLC_STAT_CRCVFRRAB) ==
|
||||
HDLC_STAT_CRCVFR) ||
|
||||
test_bit(FLG_TRANSPARENT, &bch->Flags)) {
|
||||
recv_Bchannel(bch, 0);
|
||||
if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {
|
||||
recv_Bchannel(bch, 0, false);
|
||||
} else if (stat & HDLC_STAT_RME) {
|
||||
if ((stat & HDLC_STAT_CRCVFRRAB) ==
|
||||
HDLC_STAT_CRCVFR) {
|
||||
recv_Bchannel(bch, 0, false);
|
||||
} else {
|
||||
pr_debug("%s: got invalid frame\n",
|
||||
fc->name);
|
||||
pr_warning("%s: got invalid frame\n",
|
||||
fc->name);
|
||||
skb_trim(bch->rx_skb, 0);
|
||||
}
|
||||
}
|
||||
|
@ -547,16 +586,13 @@ handle_tx:
|
|||
* restart transmitting the whole frame on HDLC
|
||||
* in transparent mode we send the next data
|
||||
*/
|
||||
if (bch->tx_skb)
|
||||
pr_debug("%s: ch%d XDU len(%d) idx(%d) Flags(%lx)\n",
|
||||
fc->name, bch->nr, bch->tx_skb->len,
|
||||
bch->tx_idx, bch->Flags);
|
||||
else
|
||||
pr_debug("%s: ch%d XDU no tx_skb Flags(%lx)\n",
|
||||
fc->name, bch->nr, bch->Flags);
|
||||
pr_warning("%s: ch%d stat %x XDU %s\n", fc->name, bch->nr,
|
||||
stat, bch->tx_skb ? "tx_skb" : "no tx_skb");
|
||||
if (bch->tx_skb && bch->tx_skb->len) {
|
||||
if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
|
||||
bch->tx_idx = 0;
|
||||
} else if (test_bit(FLG_FILLEMPTY, &bch->Flags)) {
|
||||
test_and_set_bit(FLG_TX_EMPTY, &bch->Flags);
|
||||
}
|
||||
hdlc->ctrl.sr.xml = 0;
|
||||
hdlc->ctrl.sr.cmd |= HDLC_CMD_XRS;
|
||||
|
@ -659,22 +695,17 @@ avm_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
|
|||
struct fritzcard *fc = bch->hw;
|
||||
int ret = -EINVAL;
|
||||
struct mISDNhead *hh = mISDN_HEAD_P(skb);
|
||||
u32 id;
|
||||
u_long flags;
|
||||
unsigned long flags;
|
||||
|
||||
switch (hh->prim) {
|
||||
case PH_DATA_REQ:
|
||||
spin_lock_irqsave(&fc->lock, flags);
|
||||
ret = bchannel_senddata(bch, skb);
|
||||
if (ret > 0) { /* direct TX */
|
||||
id = hh->id; /* skb can be freed */
|
||||
hdlc_fill_fifo(bch);
|
||||
ret = 0;
|
||||
spin_unlock_irqrestore(&fc->lock, flags);
|
||||
if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
|
||||
queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
|
||||
} else
|
||||
spin_unlock_irqrestore(&fc->lock, flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&fc->lock, flags);
|
||||
return ret;
|
||||
case PH_ACTIVATE_REQ:
|
||||
spin_lock_irqsave(&fc->lock, flags);
|
||||
|
@ -783,7 +814,7 @@ init_card(struct fritzcard *fc)
|
|||
inithdlc(fc);
|
||||
enable_hwirq(fc);
|
||||
/* RESET Receiver and Transmitter */
|
||||
if (AVM_FRITZ_PCIV2 == fc->type) {
|
||||
if (fc->type == AVM_FRITZ_PCIV2) {
|
||||
WriteISAC_V2(fc, ISACX_MASK, 0);
|
||||
WriteISAC_V2(fc, ISACX_CMDRD, 0x41);
|
||||
} else {
|
||||
|
@ -810,21 +841,7 @@ init_card(struct fritzcard *fc)
|
|||
static int
|
||||
channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
|
||||
{
|
||||
int ret = 0;
|
||||
struct fritzcard *fc = bch->hw;
|
||||
|
||||
switch (cq->op) {
|
||||
case MISDN_CTRL_GETOP:
|
||||
cq->op = 0;
|
||||
break;
|
||||
/* Nothing implemented yet */
|
||||
case MISDN_CTRL_FILL_EMPTY:
|
||||
default:
|
||||
pr_info("%s: %s unknown Op %x\n", fc->name, __func__, cq->op);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
return mISDN_ctrl_bchannel(bch, cq);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -839,14 +856,10 @@ avm_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
|
|||
switch (cmd) {
|
||||
case CLOSE_CHANNEL:
|
||||
test_and_clear_bit(FLG_OPEN, &bch->Flags);
|
||||
if (test_bit(FLG_ACTIVE, &bch->Flags)) {
|
||||
spin_lock_irqsave(&fc->lock, flags);
|
||||
mISDN_freebchannel(bch);
|
||||
test_and_clear_bit(FLG_TX_BUSY, &bch->Flags);
|
||||
test_and_clear_bit(FLG_ACTIVE, &bch->Flags);
|
||||
modehdlc(bch, ISDN_P_NONE);
|
||||
spin_unlock_irqrestore(&fc->lock, flags);
|
||||
}
|
||||
spin_lock_irqsave(&fc->lock, flags);
|
||||
mISDN_freebchannel(bch);
|
||||
modehdlc(bch, ISDN_P_NONE);
|
||||
spin_unlock_irqrestore(&fc->lock, flags);
|
||||
ch->protocol = ISDN_P_NONE;
|
||||
ch->peer = NULL;
|
||||
module_put(THIS_MODULE);
|
||||
|
@ -868,7 +881,7 @@ channel_ctrl(struct fritzcard *fc, struct mISDN_ctrl_req *cq)
|
|||
|
||||
switch (cq->op) {
|
||||
case MISDN_CTRL_GETOP:
|
||||
cq->op = MISDN_CTRL_LOOP;
|
||||
cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_L1_TIMER3;
|
||||
break;
|
||||
case MISDN_CTRL_LOOP:
|
||||
/* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
|
||||
|
@ -878,6 +891,9 @@ channel_ctrl(struct fritzcard *fc, struct mISDN_ctrl_req *cq)
|
|||
}
|
||||
ret = fc->isac.ctrl(&fc->isac, HW_TESTLOOP, cq->channel);
|
||||
break;
|
||||
case MISDN_CTRL_L1_TIMER3:
|
||||
ret = fc->isac.ctrl(&fc->isac, HW_TIMER3_VALUE, cq->p1);
|
||||
break;
|
||||
default:
|
||||
pr_info("%s: %s unknown Op %x\n", fc->name, __func__, cq->op);
|
||||
ret = -EINVAL;
|
||||
|
@ -898,7 +914,6 @@ open_bchannel(struct fritzcard *fc, struct channel_req *rq)
|
|||
bch = &fc->bch[rq->adr.channel - 1];
|
||||
if (test_and_set_bit(FLG_OPEN, &bch->Flags))
|
||||
return -EBUSY; /* b-channel can be only open once */
|
||||
test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
|
||||
bch->ch.protocol = rq->protocol;
|
||||
rq->ch = &bch->ch;
|
||||
return 0;
|
||||
|
@ -1021,6 +1036,7 @@ static int __devinit
|
|||
setup_instance(struct fritzcard *card)
|
||||
{
|
||||
int i, err;
|
||||
unsigned short minsize;
|
||||
u_long flags;
|
||||
|
||||
snprintf(card->name, MISDN_MAX_IDLEN - 1, "AVM.%d", AVM_cnt + 1);
|
||||
|
@ -1040,7 +1056,11 @@ setup_instance(struct fritzcard *card)
|
|||
for (i = 0; i < 2; i++) {
|
||||
card->bch[i].nr = i + 1;
|
||||
set_channelmap(i + 1, card->isac.dch.dev.channelmap);
|
||||
mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM);
|
||||
if (AVM_FRITZ_PCIV2 == card->type)
|
||||
minsize = HDLC_FIFO_SIZE_V2;
|
||||
else
|
||||
minsize = HDLC_FIFO_SIZE_V1;
|
||||
mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM, minsize);
|
||||
card->bch[i].hw = card;
|
||||
card->bch[i].ch.send = avm_l2l1B;
|
||||
card->bch[i].ch.ctrl = avm_bctrl;
|
||||
|
|
|
@ -205,18 +205,22 @@ struct hfc_multi {
|
|||
|
||||
u_int slots; /* number of PCM slots */
|
||||
u_int leds; /* type of leds */
|
||||
u_int ledcount; /* used to animate leds */
|
||||
u_long ledstate; /* save last state of leds */
|
||||
int opticalsupport; /* has the e1 board */
|
||||
/* an optical Interface */
|
||||
int dslot; /* channel # of d-channel (E1) default 16 */
|
||||
|
||||
u_int bmask[32]; /* bitmask of bchannels for port */
|
||||
u_char dnum[32]; /* array of used dchannel numbers for port */
|
||||
u_char created[32]; /* what port is created */
|
||||
u_int activity_tx; /* if there is data TX / RX */
|
||||
u_int activity_rx; /* bitmask according to port number */
|
||||
/* (will be cleared after */
|
||||
/* showing led-states) */
|
||||
u_int flash[8]; /* counter for flashing 8 leds on activity */
|
||||
|
||||
u_long wdcount; /* every 500 ms we need to */
|
||||
/* send the watchdog a signal */
|
||||
u_char wdbyte; /* watchdog toggle byte */
|
||||
u_int activity[8]; /* if there is any action on this */
|
||||
/* port (will be cleared after */
|
||||
/* showing led-states) */
|
||||
int e1_state; /* keep track of last state */
|
||||
int e1_getclock; /* if sync is retrieved from interface */
|
||||
int syncronized; /* keep track of existing sync interface */
|
||||
|
@ -233,7 +237,6 @@ struct hfc_multi {
|
|||
* the bch->channel is equvalent to the hfc-channel
|
||||
*/
|
||||
struct hfc_chan chan[32];
|
||||
u_char created[8]; /* what port is created */
|
||||
signed char slot_owner[256]; /* owner channel of slot */
|
||||
};
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -453,7 +453,7 @@ hfcpci_empty_bfifo(struct bchannel *bch, struct bzfifo *bz,
|
|||
}
|
||||
bz->za[new_f2].z2 = cpu_to_le16(new_z2);
|
||||
bz->f2 = new_f2; /* next buffer */
|
||||
recv_Bchannel(bch, MISDN_ID_ANY);
|
||||
recv_Bchannel(bch, MISDN_ID_ANY, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -565,11 +565,6 @@ hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *rxbz,
|
|||
if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
|
||||
new_z2 -= B_FIFO_SIZE; /* buffer wrap */
|
||||
|
||||
if (fcnt_rx > MAX_DATA_SIZE) { /* flush, if oversized */
|
||||
*z2r = cpu_to_le16(new_z2); /* new position */
|
||||
return;
|
||||
}
|
||||
|
||||
fcnt_tx = le16_to_cpu(*z2t) - le16_to_cpu(*z1t);
|
||||
if (fcnt_tx <= 0)
|
||||
fcnt_tx += B_FIFO_SIZE;
|
||||
|
@ -577,8 +572,16 @@ hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *rxbz,
|
|||
fcnt_tx = B_FIFO_SIZE - fcnt_tx;
|
||||
/* remaining bytes to send (bytes in tx-fifo) */
|
||||
|
||||
bch->rx_skb = mI_alloc_skb(fcnt_rx, GFP_ATOMIC);
|
||||
if (bch->rx_skb) {
|
||||
if (test_bit(FLG_RX_OFF, &bch->Flags)) {
|
||||
bch->dropcnt += fcnt_rx;
|
||||
*z2r = cpu_to_le16(new_z2);
|
||||
return;
|
||||
}
|
||||
maxlen = bchannel_get_rxbuf(bch, fcnt_rx);
|
||||
if (maxlen < 0) {
|
||||
pr_warning("B%d: No bufferspace for %d bytes\n",
|
||||
bch->nr, fcnt_rx);
|
||||
} else {
|
||||
ptr = skb_put(bch->rx_skb, fcnt_rx);
|
||||
if (le16_to_cpu(*z2r) + fcnt_rx <= B_FIFO_SIZE + B_SUB_VAL)
|
||||
maxlen = fcnt_rx; /* complete transfer */
|
||||
|
@ -596,10 +599,8 @@ hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *rxbz,
|
|||
ptr1 = bdata; /* start of buffer */
|
||||
memcpy(ptr, ptr1, fcnt_rx); /* rest */
|
||||
}
|
||||
recv_Bchannel(bch, fcnt_tx); /* bch, id */
|
||||
} else
|
||||
printk(KERN_WARNING "HFCPCI: receive out of memory\n");
|
||||
|
||||
recv_Bchannel(bch, fcnt_tx, false); /* bch, id, !force */
|
||||
}
|
||||
*z2r = cpu_to_le16(new_z2); /* new position */
|
||||
}
|
||||
|
||||
|
@ -760,9 +761,14 @@ hfcpci_fill_fifo(struct bchannel *bch)
|
|||
|
||||
if ((bch->debug & DEBUG_HW_BCHANNEL) && !(bch->debug & DEBUG_HW_BFIFO))
|
||||
printk(KERN_DEBUG "%s\n", __func__);
|
||||
if ((!bch->tx_skb) || bch->tx_skb->len <= 0)
|
||||
return;
|
||||
count = bch->tx_skb->len - bch->tx_idx;
|
||||
if ((!bch->tx_skb) || bch->tx_skb->len == 0) {
|
||||
if (!test_bit(FLG_FILLEMPTY, &bch->Flags) &&
|
||||
!test_bit(FLG_TRANSPARENT, &bch->Flags))
|
||||
return;
|
||||
count = HFCPCI_FILLEMPTY;
|
||||
} else {
|
||||
count = bch->tx_skb->len - bch->tx_idx;
|
||||
}
|
||||
if ((bch->nr & 2) && (!hc->hw.bswapped)) {
|
||||
bz = &((union fifo_area *)(hc->hw.fifos))->b_chans.txbz_b2;
|
||||
bdata = ((union fifo_area *)(hc->hw.fifos))->b_chans.txdat_b2;
|
||||
|
@ -781,16 +787,10 @@ hfcpci_fill_fifo(struct bchannel *bch)
|
|||
fcnt = le16_to_cpu(*z2t) - le16_to_cpu(*z1t);
|
||||
if (fcnt <= 0)
|
||||
fcnt += B_FIFO_SIZE;
|
||||
/* fcnt contains available bytes in fifo */
|
||||
fcnt = B_FIFO_SIZE - fcnt;
|
||||
/* remaining bytes to send (bytes in fifo) */
|
||||
|
||||
/* "fill fifo if empty" feature */
|
||||
if (test_bit(FLG_FILLEMPTY, &bch->Flags) && !fcnt) {
|
||||
/* printk(KERN_DEBUG "%s: buffer empty, so we have "
|
||||
"underrun\n", __func__); */
|
||||
/* fill buffer, to prevent future underrun */
|
||||
count = HFCPCI_FILLEMPTY;
|
||||
if (test_bit(FLG_FILLEMPTY, &bch->Flags)) {
|
||||
/* fcnt contains available bytes in fifo */
|
||||
if (count > fcnt)
|
||||
count = fcnt;
|
||||
new_z1 = le16_to_cpu(*z1t) + count;
|
||||
/* new buffer Position */
|
||||
if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL))
|
||||
|
@ -802,17 +802,20 @@ hfcpci_fill_fifo(struct bchannel *bch)
|
|||
printk(KERN_DEBUG "hfcpci_FFt fillempty "
|
||||
"fcnt(%d) maxl(%d) nz1(%x) dst(%p)\n",
|
||||
fcnt, maxlen, new_z1, dst);
|
||||
fcnt += count;
|
||||
if (maxlen > count)
|
||||
maxlen = count; /* limit size */
|
||||
memset(dst, 0x2a, maxlen); /* first copy */
|
||||
memset(dst, bch->fill[0], maxlen); /* first copy */
|
||||
count -= maxlen; /* remaining bytes */
|
||||
if (count) {
|
||||
dst = bdata; /* start of buffer */
|
||||
memset(dst, 0x2a, count);
|
||||
memset(dst, bch->fill[0], count);
|
||||
}
|
||||
*z1t = cpu_to_le16(new_z1); /* now send data */
|
||||
return;
|
||||
}
|
||||
/* fcnt contains available bytes in fifo */
|
||||
fcnt = B_FIFO_SIZE - fcnt;
|
||||
/* remaining bytes to send (bytes in fifo) */
|
||||
|
||||
next_t_frame:
|
||||
count = bch->tx_skb->len - bch->tx_idx;
|
||||
|
@ -849,9 +852,6 @@ hfcpci_fill_fifo(struct bchannel *bch)
|
|||
*z1t = cpu_to_le16(new_z1); /* now send data */
|
||||
if (bch->tx_idx < bch->tx_skb->len)
|
||||
return;
|
||||
/* send confirm, on trans, free on hdlc. */
|
||||
if (test_bit(FLG_TRANSPARENT, &bch->Flags))
|
||||
confirm_Bsend(bch);
|
||||
dev_kfree_skb(bch->tx_skb);
|
||||
if (get_next_bframe(bch))
|
||||
goto next_t_frame;
|
||||
|
@ -1533,24 +1533,7 @@ deactivate_bchannel(struct bchannel *bch)
|
|||
static int
|
||||
channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (cq->op) {
|
||||
case MISDN_CTRL_GETOP:
|
||||
cq->op = MISDN_CTRL_FILL_EMPTY;
|
||||
break;
|
||||
case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */
|
||||
test_and_set_bit(FLG_FILLEMPTY, &bch->Flags);
|
||||
if (debug & DEBUG_HW_OPEN)
|
||||
printk(KERN_DEBUG "%s: FILL_EMPTY request (nr=%d "
|
||||
"off=%d)\n", __func__, bch->nr, !!cq->p1);
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING "%s: unknown Op %x\n", __func__, cq->op);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
return mISDN_ctrl_bchannel(bch, cq);
|
||||
}
|
||||
static int
|
||||
hfc_bctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
|
||||
|
@ -1581,8 +1564,7 @@ hfc_bctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
|
|||
break;
|
||||
case CLOSE_CHANNEL:
|
||||
test_and_clear_bit(FLG_OPEN, &bch->Flags);
|
||||
if (test_bit(FLG_ACTIVE, &bch->Flags))
|
||||
deactivate_bchannel(bch);
|
||||
deactivate_bchannel(bch);
|
||||
ch->protocol = ISDN_P_NONE;
|
||||
ch->peer = NULL;
|
||||
module_put(THIS_MODULE);
|
||||
|
@ -1692,22 +1674,17 @@ hfcpci_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
|
|||
struct hfc_pci *hc = bch->hw;
|
||||
int ret = -EINVAL;
|
||||
struct mISDNhead *hh = mISDN_HEAD_P(skb);
|
||||
unsigned int id;
|
||||
u_long flags;
|
||||
unsigned long flags;
|
||||
|
||||
switch (hh->prim) {
|
||||
case PH_DATA_REQ:
|
||||
spin_lock_irqsave(&hc->lock, flags);
|
||||
ret = bchannel_senddata(bch, skb);
|
||||
if (ret > 0) { /* direct TX */
|
||||
id = hh->id; /* skb can be freed */
|
||||
hfcpci_fill_fifo(bch);
|
||||
ret = 0;
|
||||
spin_unlock_irqrestore(&hc->lock, flags);
|
||||
if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
|
||||
queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
|
||||
} else
|
||||
spin_unlock_irqrestore(&hc->lock, flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&hc->lock, flags);
|
||||
return ret;
|
||||
case PH_ACTIVATE_REQ:
|
||||
spin_lock_irqsave(&hc->lock, flags);
|
||||
|
@ -1819,7 +1796,7 @@ channel_ctrl(struct hfc_pci *hc, struct mISDN_ctrl_req *cq)
|
|||
switch (cq->op) {
|
||||
case MISDN_CTRL_GETOP:
|
||||
cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_CONNECT |
|
||||
MISDN_CTRL_DISCONNECT;
|
||||
MISDN_CTRL_DISCONNECT | MISDN_CTRL_L1_TIMER3;
|
||||
break;
|
||||
case MISDN_CTRL_LOOP:
|
||||
/* channel 0 disabled loop */
|
||||
|
@ -1896,6 +1873,9 @@ channel_ctrl(struct hfc_pci *hc, struct mISDN_ctrl_req *cq)
|
|||
Write_hfc(hc, HFCPCI_CONNECT, hc->hw.conn);
|
||||
hc->hw.trm &= 0x7f; /* disable IOM-loop */
|
||||
break;
|
||||
case MISDN_CTRL_L1_TIMER3:
|
||||
ret = l1_event(hc->dch.l1, HW_TIMER3_VALUE | (cq->p1 & 0xff));
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING "%s: unknown Op %x\n",
|
||||
__func__, cq->op);
|
||||
|
@ -1969,7 +1949,6 @@ open_bchannel(struct hfc_pci *hc, struct channel_req *rq)
|
|||
bch = &hc->bch[rq->adr.channel - 1];
|
||||
if (test_and_set_bit(FLG_OPEN, &bch->Flags))
|
||||
return -EBUSY; /* b-channel can be only open once */
|
||||
test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
|
||||
bch->ch.protocol = rq->protocol;
|
||||
rq->ch = &bch->ch; /* TODO: E-channel */
|
||||
if (!try_module_get(THIS_MODULE))
|
||||
|
@ -2121,7 +2100,7 @@ setup_card(struct hfc_pci *card)
|
|||
card->bch[i].nr = i + 1;
|
||||
set_channelmap(i + 1, card->dch.dev.channelmap);
|
||||
card->bch[i].debug = debug;
|
||||
mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM);
|
||||
mISDN_initbchannel(&card->bch[i], MAX_DATA_MEM, poll >> 1);
|
||||
card->bch[i].hw = card;
|
||||
card->bch[i].ch.send = hfcpci_l2l1B;
|
||||
card->bch[i].ch.ctrl = hfc_bctrl;
|
||||
|
|
|
@ -226,19 +226,12 @@ hfcusb_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
|
|||
if (debug & DBG_HFC_CALL_TRACE)
|
||||
printk(KERN_DEBUG "%s: %s PH_DATA_REQ ret(%i)\n",
|
||||
hw->name, __func__, ret);
|
||||
if (ret > 0) {
|
||||
/*
|
||||
* other l1 drivers don't send early confirms on
|
||||
* transp data, but hfcsusb does because tx_next
|
||||
* skb is needed in tx_iso_complete()
|
||||
*/
|
||||
queue_ch_frame(ch, PH_DATA_CNF, hh->id, NULL);
|
||||
if (ret > 0)
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
case PH_ACTIVATE_REQ:
|
||||
if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags)) {
|
||||
hfcsusb_start_endpoint(hw, bch->nr);
|
||||
hfcsusb_start_endpoint(hw, bch->nr - 1);
|
||||
ret = hfcsusb_setup_bch(bch, ch->protocol);
|
||||
} else
|
||||
ret = 0;
|
||||
|
@ -498,16 +491,9 @@ open_bchannel(struct hfcsusb *hw, struct channel_req *rq)
|
|||
bch = &hw->bch[rq->adr.channel - 1];
|
||||
if (test_and_set_bit(FLG_OPEN, &bch->Flags))
|
||||
return -EBUSY; /* b-channel can be only open once */
|
||||
test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
|
||||
bch->ch.protocol = rq->protocol;
|
||||
rq->ch = &bch->ch;
|
||||
|
||||
/* start USB endpoint for bchannel */
|
||||
if (rq->adr.channel == 1)
|
||||
hfcsusb_start_endpoint(hw, HFC_CHAN_B1);
|
||||
else
|
||||
hfcsusb_start_endpoint(hw, HFC_CHAN_B2);
|
||||
|
||||
if (!try_module_get(THIS_MODULE))
|
||||
printk(KERN_WARNING "%s: %s:cannot get module\n",
|
||||
hw->name, __func__);
|
||||
|
@ -819,24 +805,7 @@ hfcsusb_ph_command(struct hfcsusb *hw, u_char command)
|
|||
static int
|
||||
channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (cq->op) {
|
||||
case MISDN_CTRL_GETOP:
|
||||
cq->op = MISDN_CTRL_FILL_EMPTY;
|
||||
break;
|
||||
case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */
|
||||
test_and_set_bit(FLG_FILLEMPTY, &bch->Flags);
|
||||
if (debug & DEBUG_HW_OPEN)
|
||||
printk(KERN_DEBUG "%s: FILL_EMPTY request (nr=%d "
|
||||
"off=%d)\n", __func__, bch->nr, !!cq->p1);
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING "%s: unknown Op %x\n", __func__, cq->op);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
return mISDN_ctrl_bchannel(bch, cq);
|
||||
}
|
||||
|
||||
/* collect data from incoming interrupt or isochron USB data */
|
||||
|
@ -873,7 +842,21 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
|
|||
hdlc = 1;
|
||||
}
|
||||
if (fifo->bch) {
|
||||
if (test_bit(FLG_RX_OFF, &fifo->bch->Flags)) {
|
||||
fifo->bch->dropcnt += len;
|
||||
spin_unlock(&hw->lock);
|
||||
return;
|
||||
}
|
||||
maxlen = bchannel_get_rxbuf(fifo->bch, len);
|
||||
rx_skb = fifo->bch->rx_skb;
|
||||
if (maxlen < 0) {
|
||||
if (rx_skb)
|
||||
skb_trim(rx_skb, 0);
|
||||
pr_warning("%s.B%d: No bufferspace for %d bytes\n",
|
||||
hw->name, fifo->bch->nr, len);
|
||||
spin_unlock(&hw->lock);
|
||||
return;
|
||||
}
|
||||
maxlen = fifo->bch->maxlen;
|
||||
hdlc = test_bit(FLG_HDLC, &fifo->bch->Flags);
|
||||
}
|
||||
|
@ -883,25 +866,22 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
|
|||
hdlc = 1;
|
||||
}
|
||||
|
||||
if (!rx_skb) {
|
||||
rx_skb = mI_alloc_skb(maxlen, GFP_ATOMIC);
|
||||
if (rx_skb) {
|
||||
if (fifo->dch)
|
||||
fifo->dch->rx_skb = rx_skb;
|
||||
if (fifo->bch)
|
||||
fifo->bch->rx_skb = rx_skb;
|
||||
if (fifo->ech)
|
||||
fifo->ech->rx_skb = rx_skb;
|
||||
skb_trim(rx_skb, 0);
|
||||
} else {
|
||||
printk(KERN_DEBUG "%s: %s: No mem for rx_skb\n",
|
||||
hw->name, __func__);
|
||||
spin_unlock(&hw->lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (fifo->dch || fifo->ech) {
|
||||
if (!rx_skb) {
|
||||
rx_skb = mI_alloc_skb(maxlen, GFP_ATOMIC);
|
||||
if (rx_skb) {
|
||||
if (fifo->dch)
|
||||
fifo->dch->rx_skb = rx_skb;
|
||||
if (fifo->ech)
|
||||
fifo->ech->rx_skb = rx_skb;
|
||||
skb_trim(rx_skb, 0);
|
||||
} else {
|
||||
printk(KERN_DEBUG "%s: %s: No mem for rx_skb\n",
|
||||
hw->name, __func__);
|
||||
spin_unlock(&hw->lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* D/E-Channel SKB range check */
|
||||
if ((rx_skb->len + len) >= MAX_DFRAME_LEN_L1) {
|
||||
printk(KERN_DEBUG "%s: %s: sbk mem exceeded "
|
||||
|
@ -911,16 +891,6 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
|
|||
spin_unlock(&hw->lock);
|
||||
return;
|
||||
}
|
||||
} else if (fifo->bch) {
|
||||
/* B-Channel SKB range check */
|
||||
if ((rx_skb->len + len) >= (MAX_BCH_SIZE + 3)) {
|
||||
printk(KERN_DEBUG "%s: %s: sbk mem exceeded "
|
||||
"for fifo(%d) HFCUSB_B_RX\n",
|
||||
hw->name, __func__, fifon);
|
||||
skb_trim(rx_skb, 0);
|
||||
spin_unlock(&hw->lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(skb_put(rx_skb, len), data, len);
|
||||
|
@ -948,7 +918,8 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
|
|||
if (fifo->dch)
|
||||
recv_Dchannel(fifo->dch);
|
||||
if (fifo->bch)
|
||||
recv_Bchannel(fifo->bch, MISDN_ID_ANY);
|
||||
recv_Bchannel(fifo->bch, MISDN_ID_ANY,
|
||||
0);
|
||||
if (fifo->ech)
|
||||
recv_Echannel(fifo->ech,
|
||||
&hw->dch);
|
||||
|
@ -969,8 +940,7 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
|
|||
}
|
||||
} else {
|
||||
/* deliver transparent data to layer2 */
|
||||
if (rx_skb->len >= poll)
|
||||
recv_Bchannel(fifo->bch, MISDN_ID_ANY);
|
||||
recv_Bchannel(fifo->bch, MISDN_ID_ANY, false);
|
||||
}
|
||||
spin_unlock(&hw->lock);
|
||||
}
|
||||
|
@ -1200,8 +1170,8 @@ tx_iso_complete(struct urb *urb)
|
|||
int k, tx_offset, num_isoc_packets, sink, remain, current_len,
|
||||
errcode, hdlc, i;
|
||||
int *tx_idx;
|
||||
int frame_complete, fifon, status;
|
||||
__u8 threshbit;
|
||||
int frame_complete, fifon, status, fillempty = 0;
|
||||
__u8 threshbit, *p;
|
||||
|
||||
spin_lock(&hw->lock);
|
||||
if (fifo->stop_gracefull) {
|
||||
|
@ -1219,6 +1189,9 @@ tx_iso_complete(struct urb *urb)
|
|||
tx_skb = fifo->bch->tx_skb;
|
||||
tx_idx = &fifo->bch->tx_idx;
|
||||
hdlc = test_bit(FLG_HDLC, &fifo->bch->Flags);
|
||||
if (!tx_skb && !hdlc &&
|
||||
test_bit(FLG_FILLEMPTY, &fifo->bch->Flags))
|
||||
fillempty = 1;
|
||||
} else {
|
||||
printk(KERN_DEBUG "%s: %s: neither BCH nor DCH\n",
|
||||
hw->name, __func__);
|
||||
|
@ -1277,6 +1250,8 @@ tx_iso_complete(struct urb *urb)
|
|||
/* Generate next ISO Packets */
|
||||
if (tx_skb)
|
||||
remain = tx_skb->len - *tx_idx;
|
||||
else if (fillempty)
|
||||
remain = 15; /* > not complete */
|
||||
else
|
||||
remain = 0;
|
||||
|
||||
|
@ -1307,15 +1282,20 @@ tx_iso_complete(struct urb *urb)
|
|||
}
|
||||
|
||||
/* copy tx data to iso-urb buffer */
|
||||
memcpy(context_iso_urb->buffer + tx_offset + 1,
|
||||
(tx_skb->data + *tx_idx), current_len);
|
||||
*tx_idx += current_len;
|
||||
|
||||
p = context_iso_urb->buffer + tx_offset + 1;
|
||||
if (fillempty) {
|
||||
memset(p, fifo->bch->fill[0],
|
||||
current_len);
|
||||
} else {
|
||||
memcpy(p, (tx_skb->data + *tx_idx),
|
||||
current_len);
|
||||
*tx_idx += current_len;
|
||||
}
|
||||
urb->iso_frame_desc[k].offset = tx_offset;
|
||||
urb->iso_frame_desc[k].length = current_len + 1;
|
||||
|
||||
/* USB data log for every D ISO out */
|
||||
if ((fifon == HFCUSB_D_RX) &&
|
||||
if ((fifon == HFCUSB_D_RX) && !fillempty &&
|
||||
(debug & DBG_HFC_USB_VERBOSE)) {
|
||||
printk(KERN_DEBUG
|
||||
"%s: %s (%d/%d) offs(%d) len(%d) ",
|
||||
|
@ -1365,12 +1345,8 @@ tx_iso_complete(struct urb *urb)
|
|||
if (fifo->dch && get_next_dframe(fifo->dch))
|
||||
tx_skb = fifo->dch->tx_skb;
|
||||
else if (fifo->bch &&
|
||||
get_next_bframe(fifo->bch)) {
|
||||
if (test_bit(FLG_TRANSPARENT,
|
||||
&fifo->bch->Flags))
|
||||
confirm_Bsend(fifo->bch);
|
||||
get_next_bframe(fifo->bch))
|
||||
tx_skb = fifo->bch->tx_skb;
|
||||
}
|
||||
}
|
||||
}
|
||||
errcode = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
|
@ -1812,7 +1788,7 @@ deactivate_bchannel(struct bchannel *bch)
|
|||
mISDN_clear_bchannel(bch);
|
||||
spin_unlock_irqrestore(&hw->lock, flags);
|
||||
hfcsusb_setup_bch(bch, ISDN_P_NONE);
|
||||
hfcsusb_stop_endpoint(hw, bch->nr);
|
||||
hfcsusb_stop_endpoint(hw, bch->nr - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1836,8 +1812,7 @@ hfc_bctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
|
|||
|
||||
case CLOSE_CHANNEL:
|
||||
test_and_clear_bit(FLG_OPEN, &bch->Flags);
|
||||
if (test_bit(FLG_ACTIVE, &bch->Flags))
|
||||
deactivate_bchannel(bch);
|
||||
deactivate_bchannel(bch);
|
||||
ch->protocol = ISDN_P_NONE;
|
||||
ch->peer = NULL;
|
||||
module_put(THIS_MODULE);
|
||||
|
@ -1883,7 +1858,7 @@ setup_instance(struct hfcsusb *hw, struct device *parent)
|
|||
hw->bch[i].nr = i + 1;
|
||||
set_channelmap(i + 1, hw->dch.dev.channelmap);
|
||||
hw->bch[i].debug = debug;
|
||||
mISDN_initbchannel(&hw->bch[i], MAX_DATA_MEM);
|
||||
mISDN_initbchannel(&hw->bch[i], MAX_DATA_MEM, poll >> 1);
|
||||
hw->bch[i].hw = hw;
|
||||
hw->bch[i].ch.send = hfcusb_l2l1B;
|
||||
hw->bch[i].ch.ctrl = hfc_bctrl;
|
||||
|
|
|
@ -603,10 +603,11 @@ isac_l1hw(struct mISDNchannel *ch, struct sk_buff *skb)
|
|||
}
|
||||
|
||||
static int
|
||||
isac_ctrl(struct isac_hw *isac, u32 cmd, u_long para)
|
||||
isac_ctrl(struct isac_hw *isac, u32 cmd, unsigned long para)
|
||||
{
|
||||
u8 tl = 0;
|
||||
u_long flags;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case HW_TESTLOOP:
|
||||
|
@ -626,12 +627,15 @@ isac_ctrl(struct isac_hw *isac, u32 cmd, u_long para)
|
|||
}
|
||||
spin_unlock_irqrestore(isac->hwlock, flags);
|
||||
break;
|
||||
case HW_TIMER3_VALUE:
|
||||
ret = l1_event(isac->dch.l1, HW_TIMER3_VALUE | (para & 0xff));
|
||||
break;
|
||||
default:
|
||||
pr_debug("%s: %s unknown command %x %lx\n", isac->name,
|
||||
__func__, cmd, para);
|
||||
return -1;
|
||||
ret = -1;
|
||||
}
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -929,24 +933,23 @@ static void
|
|||
hscx_empty_fifo(struct hscx_hw *hscx, u8 count)
|
||||
{
|
||||
u8 *p;
|
||||
int maxlen;
|
||||
|
||||
pr_debug("%s: B%1d %d\n", hscx->ip->name, hscx->bch.nr, count);
|
||||
if (!hscx->bch.rx_skb) {
|
||||
hscx->bch.rx_skb = mI_alloc_skb(hscx->bch.maxlen, GFP_ATOMIC);
|
||||
if (!hscx->bch.rx_skb) {
|
||||
pr_info("%s: B receive out of memory\n",
|
||||
hscx->ip->name);
|
||||
hscx_cmdr(hscx, 0x80); /* RMC */
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ((hscx->bch.rx_skb->len + count) > hscx->bch.maxlen) {
|
||||
pr_debug("%s: overrun %d\n", hscx->ip->name,
|
||||
hscx->bch.rx_skb->len + count);
|
||||
skb_trim(hscx->bch.rx_skb, 0);
|
||||
if (test_bit(FLG_RX_OFF, &hscx->bch.Flags)) {
|
||||
hscx->bch.dropcnt += count;
|
||||
hscx_cmdr(hscx, 0x80); /* RMC */
|
||||
return;
|
||||
}
|
||||
maxlen = bchannel_get_rxbuf(&hscx->bch, count);
|
||||
if (maxlen < 0) {
|
||||
hscx_cmdr(hscx, 0x80); /* RMC */
|
||||
if (hscx->bch.rx_skb)
|
||||
skb_trim(hscx->bch.rx_skb, 0);
|
||||
pr_warning("%s.B%d: No bufferspace for %d bytes\n",
|
||||
hscx->ip->name, hscx->bch.nr, count);
|
||||
return;
|
||||
}
|
||||
p = skb_put(hscx->bch.rx_skb, count);
|
||||
|
||||
if (hscx->ip->type & IPAC_TYPE_IPACX)
|
||||
|
@ -971,22 +974,28 @@ hscx_fill_fifo(struct hscx_hw *hscx)
|
|||
int count, more;
|
||||
u8 *p;
|
||||
|
||||
if (!hscx->bch.tx_skb)
|
||||
return;
|
||||
count = hscx->bch.tx_skb->len - hscx->bch.tx_idx;
|
||||
if (count <= 0)
|
||||
return;
|
||||
p = hscx->bch.tx_skb->data + hscx->bch.tx_idx;
|
||||
|
||||
more = test_bit(FLG_TRANSPARENT, &hscx->bch.Flags) ? 1 : 0;
|
||||
if (count > hscx->fifo_size) {
|
||||
if (!hscx->bch.tx_skb) {
|
||||
if (!test_bit(FLG_TX_EMPTY, &hscx->bch.Flags))
|
||||
return;
|
||||
count = hscx->fifo_size;
|
||||
more = 1;
|
||||
}
|
||||
pr_debug("%s: B%1d %d/%d/%d\n", hscx->ip->name, hscx->bch.nr, count,
|
||||
hscx->bch.tx_idx, hscx->bch.tx_skb->len);
|
||||
hscx->bch.tx_idx += count;
|
||||
p = hscx->log;
|
||||
memset(p, hscx->bch.fill[0], count);
|
||||
} else {
|
||||
count = hscx->bch.tx_skb->len - hscx->bch.tx_idx;
|
||||
if (count <= 0)
|
||||
return;
|
||||
p = hscx->bch.tx_skb->data + hscx->bch.tx_idx;
|
||||
|
||||
more = test_bit(FLG_TRANSPARENT, &hscx->bch.Flags) ? 1 : 0;
|
||||
if (count > hscx->fifo_size) {
|
||||
count = hscx->fifo_size;
|
||||
more = 1;
|
||||
}
|
||||
pr_debug("%s: B%1d %d/%d/%d\n", hscx->ip->name, hscx->bch.nr,
|
||||
count, hscx->bch.tx_idx, hscx->bch.tx_skb->len);
|
||||
hscx->bch.tx_idx += count;
|
||||
}
|
||||
if (hscx->ip->type & IPAC_TYPE_IPACX)
|
||||
hscx->ip->write_fifo(hscx->ip->hw,
|
||||
hscx->off + IPACX_XFIFOB, p, count);
|
||||
|
@ -997,7 +1006,7 @@ hscx_fill_fifo(struct hscx_hw *hscx)
|
|||
}
|
||||
hscx_cmdr(hscx, more ? 0x08 : 0x0a);
|
||||
|
||||
if (hscx->bch.debug & DEBUG_HW_BFIFO) {
|
||||
if (hscx->bch.tx_skb && (hscx->bch.debug & DEBUG_HW_BFIFO)) {
|
||||
snprintf(hscx->log, 64, "B%1d-send %s %d ",
|
||||
hscx->bch.nr, hscx->ip->name, count);
|
||||
print_hex_dump_bytes(hscx->log, DUMP_PREFIX_OFFSET, p, count);
|
||||
|
@ -1007,17 +1016,17 @@ hscx_fill_fifo(struct hscx_hw *hscx)
|
|||
static void
|
||||
hscx_xpr(struct hscx_hw *hx)
|
||||
{
|
||||
if (hx->bch.tx_skb && hx->bch.tx_idx < hx->bch.tx_skb->len)
|
||||
if (hx->bch.tx_skb && hx->bch.tx_idx < hx->bch.tx_skb->len) {
|
||||
hscx_fill_fifo(hx);
|
||||
else {
|
||||
if (hx->bch.tx_skb) {
|
||||
/* send confirm, on trans, free on hdlc. */
|
||||
if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags))
|
||||
confirm_Bsend(&hx->bch);
|
||||
} else {
|
||||
if (hx->bch.tx_skb)
|
||||
dev_kfree_skb(hx->bch.tx_skb);
|
||||
}
|
||||
if (get_next_bframe(&hx->bch))
|
||||
if (get_next_bframe(&hx->bch)) {
|
||||
hscx_fill_fifo(hx);
|
||||
test_and_clear_bit(FLG_TX_EMPTY, &hx->bch.Flags);
|
||||
} else if (test_bit(FLG_TX_EMPTY, &hx->bch.Flags)) {
|
||||
hscx_fill_fifo(hx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1069,7 +1078,7 @@ ipac_rme(struct hscx_hw *hx)
|
|||
skb_trim(hx->bch.rx_skb, 0);
|
||||
} else {
|
||||
skb_trim(hx->bch.rx_skb, hx->bch.rx_skb->len - 1);
|
||||
recv_Bchannel(&hx->bch, 0);
|
||||
recv_Bchannel(&hx->bch, 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1120,11 +1129,8 @@ ipac_irq(struct hscx_hw *hx, u8 ista)
|
|||
|
||||
if (istab & IPACX_B_RPF) {
|
||||
hscx_empty_fifo(hx, hx->fifo_size);
|
||||
if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags)) {
|
||||
/* receive transparent audio data */
|
||||
if (hx->bch.rx_skb)
|
||||
recv_Bchannel(&hx->bch, 0);
|
||||
}
|
||||
if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags))
|
||||
recv_Bchannel(&hx->bch, 0, false);
|
||||
}
|
||||
|
||||
if (istab & IPACX_B_RFO) {
|
||||
|
@ -1137,7 +1143,9 @@ ipac_irq(struct hscx_hw *hx, u8 ista)
|
|||
|
||||
if (istab & IPACX_B_XDU) {
|
||||
if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags)) {
|
||||
hscx_fill_fifo(hx);
|
||||
if (test_bit(FLG_FILLEMPTY, &hx->bch.Flags))
|
||||
test_and_set_bit(FLG_TX_EMPTY, &hx->bch.Flags);
|
||||
hscx_xpr(hx);
|
||||
return;
|
||||
}
|
||||
pr_debug("%s: B%1d XDU error at len %d\n", hx->ip->name,
|
||||
|
@ -1338,22 +1346,17 @@ hscx_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
|
|||
struct hscx_hw *hx = container_of(bch, struct hscx_hw, bch);
|
||||
int ret = -EINVAL;
|
||||
struct mISDNhead *hh = mISDN_HEAD_P(skb);
|
||||
u32 id;
|
||||
u_long flags;
|
||||
unsigned long flags;
|
||||
|
||||
switch (hh->prim) {
|
||||
case PH_DATA_REQ:
|
||||
spin_lock_irqsave(hx->ip->hwlock, flags);
|
||||
ret = bchannel_senddata(bch, skb);
|
||||
if (ret > 0) { /* direct TX */
|
||||
id = hh->id; /* skb can be freed */
|
||||
ret = 0;
|
||||
hscx_fill_fifo(hx);
|
||||
spin_unlock_irqrestore(hx->ip->hwlock, flags);
|
||||
if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
|
||||
queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
|
||||
} else
|
||||
spin_unlock_irqrestore(hx->ip->hwlock, flags);
|
||||
}
|
||||
spin_unlock_irqrestore(hx->ip->hwlock, flags);
|
||||
return ret;
|
||||
case PH_ACTIVATE_REQ:
|
||||
spin_lock_irqsave(hx->ip->hwlock, flags);
|
||||
|
@ -1388,20 +1391,7 @@ hscx_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
|
|||
static int
|
||||
channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (cq->op) {
|
||||
case MISDN_CTRL_GETOP:
|
||||
cq->op = 0;
|
||||
break;
|
||||
/* Nothing implemented yet */
|
||||
case MISDN_CTRL_FILL_EMPTY:
|
||||
default:
|
||||
pr_info("%s: unknown Op %x\n", __func__, cq->op);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
return mISDN_ctrl_bchannel(bch, cq);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1416,15 +1406,10 @@ hscx_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
|
|||
switch (cmd) {
|
||||
case CLOSE_CHANNEL:
|
||||
test_and_clear_bit(FLG_OPEN, &bch->Flags);
|
||||
if (test_bit(FLG_ACTIVE, &bch->Flags)) {
|
||||
spin_lock_irqsave(hx->ip->hwlock, flags);
|
||||
mISDN_freebchannel(bch);
|
||||
hscx_mode(hx, ISDN_P_NONE);
|
||||
spin_unlock_irqrestore(hx->ip->hwlock, flags);
|
||||
} else {
|
||||
skb_queue_purge(&bch->rqueue);
|
||||
bch->rcount = 0;
|
||||
}
|
||||
spin_lock_irqsave(hx->ip->hwlock, flags);
|
||||
mISDN_freebchannel(bch);
|
||||
hscx_mode(hx, ISDN_P_NONE);
|
||||
spin_unlock_irqrestore(hx->ip->hwlock, flags);
|
||||
ch->protocol = ISDN_P_NONE;
|
||||
ch->peer = NULL;
|
||||
module_put(hx->ip->owner);
|
||||
|
@ -1526,7 +1511,7 @@ channel_ctrl(struct ipac_hw *ipac, struct mISDN_ctrl_req *cq)
|
|||
|
||||
switch (cq->op) {
|
||||
case MISDN_CTRL_GETOP:
|
||||
cq->op = MISDN_CTRL_LOOP;
|
||||
cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_L1_TIMER3;
|
||||
break;
|
||||
case MISDN_CTRL_LOOP:
|
||||
/* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
|
||||
|
@ -1536,6 +1521,9 @@ channel_ctrl(struct ipac_hw *ipac, struct mISDN_ctrl_req *cq)
|
|||
}
|
||||
ret = ipac->ctrl(ipac, HW_TESTLOOP, cq->channel);
|
||||
break;
|
||||
case MISDN_CTRL_L1_TIMER3:
|
||||
ret = ipac->isac.ctrl(&ipac->isac, HW_TIMER3_VALUE, cq->p1);
|
||||
break;
|
||||
default:
|
||||
pr_info("%s: unknown CTRL OP %x\n", ipac->name, cq->op);
|
||||
ret = -EINVAL;
|
||||
|
@ -1621,7 +1609,8 @@ mISDNipac_init(struct ipac_hw *ipac, void *hw)
|
|||
set_channelmap(i + 1, ipac->isac.dch.dev.channelmap);
|
||||
list_add(&ipac->hscx[i].bch.ch.list,
|
||||
&ipac->isac.dch.dev.bchannels);
|
||||
mISDN_initbchannel(&ipac->hscx[i].bch, MAX_DATA_MEM);
|
||||
mISDN_initbchannel(&ipac->hscx[i].bch, MAX_DATA_MEM,
|
||||
ipac->hscx[i].fifo_size);
|
||||
ipac->hscx[i].bch.ch.nr = i + 1;
|
||||
ipac->hscx[i].bch.ch.send = &hscx_l2l1;
|
||||
ipac->hscx[i].bch.ch.ctrl = hscx_bctrl;
|
||||
|
|
|
@ -421,13 +421,19 @@ deliver_status(struct isar_ch *ch, int status)
|
|||
static inline void
|
||||
isar_rcv_frame(struct isar_ch *ch)
|
||||
{
|
||||
u8 *ptr;
|
||||
u8 *ptr;
|
||||
int maxlen;
|
||||
|
||||
if (!ch->is->clsb) {
|
||||
pr_debug("%s; ISAR zero len frame\n", ch->is->name);
|
||||
ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
|
||||
return;
|
||||
}
|
||||
if (test_bit(FLG_RX_OFF, &ch->bch.Flags)) {
|
||||
ch->bch.dropcnt += ch->is->clsb;
|
||||
ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
|
||||
return;
|
||||
}
|
||||
switch (ch->bch.state) {
|
||||
case ISDN_P_NONE:
|
||||
pr_debug("%s: ISAR protocol 0 spurious IIS_RDATA %x/%x/%x\n",
|
||||
|
@ -437,36 +443,22 @@ isar_rcv_frame(struct isar_ch *ch)
|
|||
case ISDN_P_B_RAW:
|
||||
case ISDN_P_B_L2DTMF:
|
||||
case ISDN_P_B_MODEM_ASYNC:
|
||||
if (!ch->bch.rx_skb) {
|
||||
ch->bch.rx_skb = mI_alloc_skb(ch->bch.maxlen,
|
||||
GFP_ATOMIC);
|
||||
if (unlikely(!ch->bch.rx_skb)) {
|
||||
pr_info("%s: B receive out of memory\n",
|
||||
ch->is->name);
|
||||
ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
|
||||
break;
|
||||
}
|
||||
maxlen = bchannel_get_rxbuf(&ch->bch, ch->is->clsb);
|
||||
if (maxlen < 0) {
|
||||
pr_warning("%s.B%d: No bufferspace for %d bytes\n",
|
||||
ch->is->name, ch->bch.nr, ch->is->clsb);
|
||||
ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
|
||||
break;
|
||||
}
|
||||
rcv_mbox(ch->is, skb_put(ch->bch.rx_skb, ch->is->clsb));
|
||||
recv_Bchannel(&ch->bch, 0);
|
||||
recv_Bchannel(&ch->bch, 0, false);
|
||||
break;
|
||||
case ISDN_P_B_HDLC:
|
||||
if (!ch->bch.rx_skb) {
|
||||
ch->bch.rx_skb = mI_alloc_skb(ch->bch.maxlen,
|
||||
GFP_ATOMIC);
|
||||
if (unlikely(!ch->bch.rx_skb)) {
|
||||
pr_info("%s: B receive out of memory\n",
|
||||
ch->is->name);
|
||||
ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((ch->bch.rx_skb->len + ch->is->clsb) >
|
||||
(ch->bch.maxlen + 2)) {
|
||||
pr_debug("%s: incoming packet too large\n",
|
||||
ch->is->name);
|
||||
maxlen = bchannel_get_rxbuf(&ch->bch, ch->is->clsb);
|
||||
if (maxlen < 0) {
|
||||
pr_warning("%s.B%d: No bufferspace for %d bytes\n",
|
||||
ch->is->name, ch->bch.nr, ch->is->clsb);
|
||||
ch->is->write_reg(ch->is->hw, ISAR_IIA, 0);
|
||||
skb_trim(ch->bch.rx_skb, 0);
|
||||
break;
|
||||
}
|
||||
if (ch->is->cmsb & HDLC_ERROR) {
|
||||
|
@ -494,7 +486,7 @@ isar_rcv_frame(struct isar_ch *ch)
|
|||
break;
|
||||
}
|
||||
skb_trim(ch->bch.rx_skb, ch->bch.rx_skb->len - 2);
|
||||
recv_Bchannel(&ch->bch, 0);
|
||||
recv_Bchannel(&ch->bch, 0, false);
|
||||
}
|
||||
break;
|
||||
case ISDN_P_B_T30_FAX:
|
||||
|
@ -530,7 +522,7 @@ isar_rcv_frame(struct isar_ch *ch)
|
|||
ch->state = STFAX_ESCAPE;
|
||||
/* set_skb_flag(skb, DF_NOMOREDATA); */
|
||||
}
|
||||
recv_Bchannel(&ch->bch, 0);
|
||||
recv_Bchannel(&ch->bch, 0, false);
|
||||
if (ch->is->cmsb & SART_NMD)
|
||||
deliver_status(ch, HW_MOD_NOCARR);
|
||||
break;
|
||||
|
@ -570,7 +562,7 @@ isar_rcv_frame(struct isar_ch *ch)
|
|||
break;
|
||||
}
|
||||
skb_trim(ch->bch.rx_skb, ch->bch.rx_skb->len - 2);
|
||||
recv_Bchannel(&ch->bch, 0);
|
||||
recv_Bchannel(&ch->bch, 0, false);
|
||||
}
|
||||
if (ch->is->cmsb & SART_NMD) { /* ABORT */
|
||||
pr_debug("%s: isar_rcv_frame: no more data\n",
|
||||
|
@ -598,16 +590,25 @@ isar_fill_fifo(struct isar_ch *ch)
|
|||
u8 msb;
|
||||
u8 *ptr;
|
||||
|
||||
pr_debug("%s: ch%d tx_skb %p tx_idx %d\n",
|
||||
ch->is->name, ch->bch.nr, ch->bch.tx_skb, ch->bch.tx_idx);
|
||||
if (!ch->bch.tx_skb)
|
||||
return;
|
||||
count = ch->bch.tx_skb->len - ch->bch.tx_idx;
|
||||
if (count <= 0)
|
||||
return;
|
||||
pr_debug("%s: ch%d tx_skb %d tx_idx %d\n", ch->is->name, ch->bch.nr,
|
||||
ch->bch.tx_skb ? ch->bch.tx_skb->len : -1, ch->bch.tx_idx);
|
||||
if (!(ch->is->bstat &
|
||||
(ch->dpath == 1 ? BSTAT_RDM1 : BSTAT_RDM2)))
|
||||
return;
|
||||
if (!ch->bch.tx_skb) {
|
||||
if (!test_bit(FLG_TX_EMPTY, &ch->bch.Flags) ||
|
||||
(ch->bch.state != ISDN_P_B_RAW))
|
||||
return;
|
||||
count = ch->mml;
|
||||
/* use the card buffer */
|
||||
memset(ch->is->buf, ch->bch.fill[0], count);
|
||||
send_mbox(ch->is, SET_DPS(ch->dpath) | ISAR_HIS_SDATA,
|
||||
0, count, ch->is->buf);
|
||||
return;
|
||||
}
|
||||
count = ch->bch.tx_skb->len - ch->bch.tx_idx;
|
||||
if (count <= 0)
|
||||
return;
|
||||
if (count > ch->mml) {
|
||||
msb = 0;
|
||||
count = ch->mml;
|
||||
|
@ -686,9 +687,9 @@ sel_bch_isar(struct isar_hw *isar, u8 dpath)
|
|||
static void
|
||||
send_next(struct isar_ch *ch)
|
||||
{
|
||||
pr_debug("%s: %s ch%d tx_skb %p tx_idx %d\n",
|
||||
ch->is->name, __func__, ch->bch.nr,
|
||||
ch->bch.tx_skb, ch->bch.tx_idx);
|
||||
pr_debug("%s: %s ch%d tx_skb %d tx_idx %d\n", ch->is->name, __func__,
|
||||
ch->bch.nr, ch->bch.tx_skb ? ch->bch.tx_skb->len : -1,
|
||||
ch->bch.tx_idx);
|
||||
if (ch->bch.state == ISDN_P_B_T30_FAX) {
|
||||
if (ch->cmd == PCTRL_CMD_FTH) {
|
||||
if (test_bit(FLG_LASTDATA, &ch->bch.Flags)) {
|
||||
|
@ -702,15 +703,14 @@ send_next(struct isar_ch *ch)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (ch->bch.tx_skb) {
|
||||
/* send confirm, on trans, free on hdlc. */
|
||||
if (test_bit(FLG_TRANSPARENT, &ch->bch.Flags))
|
||||
confirm_Bsend(&ch->bch);
|
||||
if (ch->bch.tx_skb)
|
||||
dev_kfree_skb(ch->bch.tx_skb);
|
||||
}
|
||||
if (get_next_bframe(&ch->bch))
|
||||
if (get_next_bframe(&ch->bch)) {
|
||||
isar_fill_fifo(ch);
|
||||
else {
|
||||
test_and_clear_bit(FLG_TX_EMPTY, &ch->bch.Flags);
|
||||
} else if (test_bit(FLG_TX_EMPTY, &ch->bch.Flags)) {
|
||||
isar_fill_fifo(ch);
|
||||
} else {
|
||||
if (test_and_clear_bit(FLG_DLEETX, &ch->bch.Flags)) {
|
||||
if (test_and_clear_bit(FLG_LASTDATA,
|
||||
&ch->bch.Flags)) {
|
||||
|
@ -724,6 +724,8 @@ send_next(struct isar_ch *ch)
|
|||
} else {
|
||||
deliver_status(ch, HW_MOD_CONNECT);
|
||||
}
|
||||
} else if (test_bit(FLG_FILLEMPTY, &ch->bch.Flags)) {
|
||||
test_and_set_bit(FLG_TX_EMPTY, &ch->bch.Flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1487,14 +1489,10 @@ isar_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
|
|||
spin_lock_irqsave(ich->is->hwlock, flags);
|
||||
ret = bchannel_senddata(bch, skb);
|
||||
if (ret > 0) { /* direct TX */
|
||||
id = hh->id; /* skb can be freed */
|
||||
ret = 0;
|
||||
isar_fill_fifo(ich);
|
||||
spin_unlock_irqrestore(ich->is->hwlock, flags);
|
||||
if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
|
||||
queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
|
||||
} else
|
||||
spin_unlock_irqrestore(ich->is->hwlock, flags);
|
||||
}
|
||||
spin_unlock_irqrestore(ich->is->hwlock, flags);
|
||||
return ret;
|
||||
case PH_ACTIVATE_REQ:
|
||||
spin_lock_irqsave(ich->is->hwlock, flags);
|
||||
|
@ -1575,20 +1573,7 @@ isar_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
|
|||
static int
|
||||
channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (cq->op) {
|
||||
case MISDN_CTRL_GETOP:
|
||||
cq->op = 0;
|
||||
break;
|
||||
/* Nothing implemented yet */
|
||||
case MISDN_CTRL_FILL_EMPTY:
|
||||
default:
|
||||
pr_info("%s: unknown Op %x\n", __func__, cq->op);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
return mISDN_ctrl_bchannel(bch, cq);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1603,15 +1588,10 @@ isar_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
|
|||
switch (cmd) {
|
||||
case CLOSE_CHANNEL:
|
||||
test_and_clear_bit(FLG_OPEN, &bch->Flags);
|
||||
if (test_bit(FLG_ACTIVE, &bch->Flags)) {
|
||||
spin_lock_irqsave(ich->is->hwlock, flags);
|
||||
mISDN_freebchannel(bch);
|
||||
modeisar(ich, ISDN_P_NONE);
|
||||
spin_unlock_irqrestore(ich->is->hwlock, flags);
|
||||
} else {
|
||||
skb_queue_purge(&bch->rqueue);
|
||||
bch->rcount = 0;
|
||||
}
|
||||
spin_lock_irqsave(ich->is->hwlock, flags);
|
||||
mISDN_freebchannel(bch);
|
||||
modeisar(ich, ISDN_P_NONE);
|
||||
spin_unlock_irqrestore(ich->is->hwlock, flags);
|
||||
ch->protocol = ISDN_P_NONE;
|
||||
ch->peer = NULL;
|
||||
module_put(ich->is->owner);
|
||||
|
@ -1677,7 +1657,6 @@ isar_open(struct isar_hw *isar, struct channel_req *rq)
|
|||
bch = &isar->ch[rq->adr.channel - 1].bch;
|
||||
if (test_and_set_bit(FLG_OPEN, &bch->Flags))
|
||||
return -EBUSY; /* b-channel can be only open once */
|
||||
test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
|
||||
bch->ch.protocol = rq->protocol;
|
||||
rq->ch = &bch->ch;
|
||||
return 0;
|
||||
|
@ -1691,7 +1670,7 @@ mISDNisar_init(struct isar_hw *isar, void *hw)
|
|||
isar->hw = hw;
|
||||
for (i = 0; i < 2; i++) {
|
||||
isar->ch[i].bch.nr = i + 1;
|
||||
mISDN_initbchannel(&isar->ch[i].bch, MAX_DATA_MEM);
|
||||
mISDN_initbchannel(&isar->ch[i].bch, MAX_DATA_MEM, 32);
|
||||
isar->ch[i].bch.ch.nr = i + 1;
|
||||
isar->ch[i].bch.ch.send = &isar_l2l1;
|
||||
isar->ch[i].bch.ch.ctrl = isar_bctrl;
|
||||
|
|
|
@ -386,24 +386,20 @@ read_dma(struct tiger_ch *bc, u32 idx, int cnt)
|
|||
bc->bch.nr, idx);
|
||||
}
|
||||
bc->lastrx = idx;
|
||||
if (!bc->bch.rx_skb) {
|
||||
bc->bch.rx_skb = mI_alloc_skb(bc->bch.maxlen, GFP_ATOMIC);
|
||||
if (!bc->bch.rx_skb) {
|
||||
pr_info("%s: B%1d receive out of memory\n",
|
||||
card->name, bc->bch.nr);
|
||||
return;
|
||||
}
|
||||
if (test_bit(FLG_RX_OFF, &bc->bch.Flags)) {
|
||||
bc->bch.dropcnt += cnt;
|
||||
return;
|
||||
}
|
||||
|
||||
if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags)) {
|
||||
if ((bc->bch.rx_skb->len + cnt) > bc->bch.maxlen) {
|
||||
pr_debug("%s: B%1d overrun %d\n", card->name,
|
||||
bc->bch.nr, bc->bch.rx_skb->len + cnt);
|
||||
skb_trim(bc->bch.rx_skb, 0);
|
||||
return;
|
||||
}
|
||||
stat = bchannel_get_rxbuf(&bc->bch, cnt);
|
||||
/* only transparent use the count here, HDLC overun is detected later */
|
||||
if (stat == ENOMEM) {
|
||||
pr_warning("%s.B%d: No memory for %d bytes\n",
|
||||
card->name, bc->bch.nr, cnt);
|
||||
return;
|
||||
}
|
||||
if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags))
|
||||
p = skb_put(bc->bch.rx_skb, cnt);
|
||||
} else
|
||||
else
|
||||
p = bc->hrbuf;
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
|
@ -414,48 +410,45 @@ read_dma(struct tiger_ch *bc, u32 idx, int cnt)
|
|||
idx = 0;
|
||||
p[i] = val & 0xff;
|
||||
}
|
||||
|
||||
if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags)) {
|
||||
recv_Bchannel(&bc->bch, 0, false);
|
||||
return;
|
||||
}
|
||||
|
||||
pn = bc->hrbuf;
|
||||
next_frame:
|
||||
if (test_bit(FLG_HDLC, &bc->bch.Flags)) {
|
||||
while (cnt > 0) {
|
||||
stat = isdnhdlc_decode(&bc->hrecv, pn, cnt, &i,
|
||||
bc->bch.rx_skb->data, bc->bch.maxlen);
|
||||
if (stat > 0) /* valid frame received */
|
||||
if (stat > 0) { /* valid frame received */
|
||||
p = skb_put(bc->bch.rx_skb, stat);
|
||||
else if (stat == -HDLC_CRC_ERROR)
|
||||
pr_info("%s: B%1d receive frame CRC error\n",
|
||||
card->name, bc->bch.nr);
|
||||
else if (stat == -HDLC_FRAMING_ERROR)
|
||||
pr_info("%s: B%1d receive framing error\n",
|
||||
card->name, bc->bch.nr);
|
||||
else if (stat == -HDLC_LENGTH_ERROR)
|
||||
pr_info("%s: B%1d receive frame too long (> %d)\n",
|
||||
card->name, bc->bch.nr, bc->bch.maxlen);
|
||||
} else
|
||||
stat = cnt;
|
||||
|
||||
if (stat > 0) {
|
||||
if (debug & DEBUG_HW_BFIFO) {
|
||||
snprintf(card->log, LOG_SIZE, "B%1d-recv %s %d ",
|
||||
bc->bch.nr, card->name, stat);
|
||||
print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET,
|
||||
p, stat);
|
||||
}
|
||||
recv_Bchannel(&bc->bch, 0);
|
||||
}
|
||||
if (test_bit(FLG_HDLC, &bc->bch.Flags)) {
|
||||
pn += i;
|
||||
cnt -= i;
|
||||
if (!bc->bch.rx_skb) {
|
||||
bc->bch.rx_skb = mI_alloc_skb(bc->bch.maxlen,
|
||||
GFP_ATOMIC);
|
||||
if (!bc->bch.rx_skb) {
|
||||
pr_info("%s: B%1d receive out of memory\n",
|
||||
card->name, bc->bch.nr);
|
||||
if (debug & DEBUG_HW_BFIFO) {
|
||||
snprintf(card->log, LOG_SIZE,
|
||||
"B%1d-recv %s %d ", bc->bch.nr,
|
||||
card->name, stat);
|
||||
print_hex_dump_bytes(card->log,
|
||||
DUMP_PREFIX_OFFSET, p,
|
||||
stat);
|
||||
}
|
||||
recv_Bchannel(&bc->bch, 0, false);
|
||||
stat = bchannel_get_rxbuf(&bc->bch, bc->bch.maxlen);
|
||||
if (stat < 0) {
|
||||
pr_warning("%s.B%d: No memory for %d bytes\n",
|
||||
card->name, bc->bch.nr, cnt);
|
||||
return;
|
||||
}
|
||||
} else if (stat == -HDLC_CRC_ERROR) {
|
||||
pr_info("%s: B%1d receive frame CRC error\n",
|
||||
card->name, bc->bch.nr);
|
||||
} else if (stat == -HDLC_FRAMING_ERROR) {
|
||||
pr_info("%s: B%1d receive framing error\n",
|
||||
card->name, bc->bch.nr);
|
||||
} else if (stat == -HDLC_LENGTH_ERROR) {
|
||||
pr_info("%s: B%1d receive frame too long (> %d)\n",
|
||||
card->name, bc->bch.nr, bc->bch.maxlen);
|
||||
}
|
||||
if (cnt > 0)
|
||||
goto next_frame;
|
||||
pn += i;
|
||||
cnt -= i;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -544,22 +537,31 @@ static void
|
|||
fill_dma(struct tiger_ch *bc)
|
||||
{
|
||||
struct tiger_hw *card = bc->bch.hw;
|
||||
int count, i;
|
||||
u32 m, v;
|
||||
int count, i, fillempty = 0;
|
||||
u32 m, v, n = 0;
|
||||
u8 *p;
|
||||
|
||||
if (bc->free == 0)
|
||||
return;
|
||||
count = bc->bch.tx_skb->len - bc->bch.tx_idx;
|
||||
if (count <= 0)
|
||||
return;
|
||||
pr_debug("%s: %s B%1d %d/%d/%d/%d state %x idx %d/%d\n", card->name,
|
||||
__func__, bc->bch.nr, count, bc->free, bc->bch.tx_idx,
|
||||
bc->bch.tx_skb->len, bc->txstate, bc->idx, card->send.idx);
|
||||
if (!bc->bch.tx_skb) {
|
||||
if (!test_bit(FLG_TX_EMPTY, &bc->bch.Flags))
|
||||
return;
|
||||
fillempty = 1;
|
||||
count = card->send.size >> 1;
|
||||
p = bc->bch.fill;
|
||||
} else {
|
||||
count = bc->bch.tx_skb->len - bc->bch.tx_idx;
|
||||
if (count <= 0)
|
||||
return;
|
||||
pr_debug("%s: %s B%1d %d/%d/%d/%d state %x idx %d/%d\n",
|
||||
card->name, __func__, bc->bch.nr, count, bc->free,
|
||||
bc->bch.tx_idx, bc->bch.tx_skb->len, bc->txstate,
|
||||
bc->idx, card->send.idx);
|
||||
p = bc->bch.tx_skb->data + bc->bch.tx_idx;
|
||||
}
|
||||
if (bc->txstate & (TX_IDLE | TX_INIT | TX_UNDERRUN))
|
||||
resync(bc, card);
|
||||
p = bc->bch.tx_skb->data + bc->bch.tx_idx;
|
||||
if (test_bit(FLG_HDLC, &bc->bch.Flags)) {
|
||||
if (test_bit(FLG_HDLC, &bc->bch.Flags) && !fillempty) {
|
||||
count = isdnhdlc_encode(&bc->hsend, p, count, &i,
|
||||
bc->hsbuf, bc->free);
|
||||
pr_debug("%s: B%1d hdlc encoded %d in %d\n", card->name,
|
||||
|
@ -570,17 +572,33 @@ fill_dma(struct tiger_ch *bc)
|
|||
} else {
|
||||
if (count > bc->free)
|
||||
count = bc->free;
|
||||
bc->bch.tx_idx += count;
|
||||
if (!fillempty)
|
||||
bc->bch.tx_idx += count;
|
||||
bc->free -= count;
|
||||
}
|
||||
m = (bc->bch.nr & 1) ? 0xffffff00 : 0xffff00ff;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (bc->idx >= card->send.size)
|
||||
bc->idx = 0;
|
||||
v = card->send.start[bc->idx];
|
||||
v &= m;
|
||||
v |= (bc->bch.nr & 1) ? (u32)(p[i]) : ((u32)(p[i])) << 8;
|
||||
card->send.start[bc->idx++] = v;
|
||||
if (fillempty) {
|
||||
n = p[0];
|
||||
if (!(bc->bch.nr & 1))
|
||||
n <<= 8;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (bc->idx >= card->send.size)
|
||||
bc->idx = 0;
|
||||
v = card->send.start[bc->idx];
|
||||
v &= m;
|
||||
v |= n;
|
||||
card->send.start[bc->idx++] = v;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < count; i++) {
|
||||
if (bc->idx >= card->send.size)
|
||||
bc->idx = 0;
|
||||
v = card->send.start[bc->idx];
|
||||
v &= m;
|
||||
n = p[i];
|
||||
v |= (bc->bch.nr & 1) ? n : n << 8;
|
||||
card->send.start[bc->idx++] = v;
|
||||
}
|
||||
}
|
||||
if (debug & DEBUG_HW_BFIFO) {
|
||||
snprintf(card->log, LOG_SIZE, "B%1d-send %s %d ",
|
||||
|
@ -595,21 +613,26 @@ fill_dma(struct tiger_ch *bc)
|
|||
static int
|
||||
bc_next_frame(struct tiger_ch *bc)
|
||||
{
|
||||
if (bc->bch.tx_skb && bc->bch.tx_idx < bc->bch.tx_skb->len)
|
||||
int ret = 1;
|
||||
|
||||
if (bc->bch.tx_skb && bc->bch.tx_idx < bc->bch.tx_skb->len) {
|
||||
fill_dma(bc);
|
||||
else {
|
||||
if (bc->bch.tx_skb) {
|
||||
/* send confirm, on trans, free on hdlc. */
|
||||
if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags))
|
||||
confirm_Bsend(&bc->bch);
|
||||
} else {
|
||||
if (bc->bch.tx_skb)
|
||||
dev_kfree_skb(bc->bch.tx_skb);
|
||||
}
|
||||
if (get_next_bframe(&bc->bch))
|
||||
if (get_next_bframe(&bc->bch)) {
|
||||
fill_dma(bc);
|
||||
else
|
||||
return 0;
|
||||
test_and_clear_bit(FLG_TX_EMPTY, &bc->bch.Flags);
|
||||
} else if (test_bit(FLG_TX_EMPTY, &bc->bch.Flags)) {
|
||||
fill_dma(bc);
|
||||
} else if (test_bit(FLG_FILLEMPTY, &bc->bch.Flags)) {
|
||||
test_and_set_bit(FLG_TX_EMPTY, &bc->bch.Flags);
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -732,22 +755,17 @@ nj_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
|
|||
struct tiger_ch *bc = container_of(bch, struct tiger_ch, bch);
|
||||
struct tiger_hw *card = bch->hw;
|
||||
struct mISDNhead *hh = mISDN_HEAD_P(skb);
|
||||
u32 id;
|
||||
u_long flags;
|
||||
unsigned long flags;
|
||||
|
||||
switch (hh->prim) {
|
||||
case PH_DATA_REQ:
|
||||
spin_lock_irqsave(&card->lock, flags);
|
||||
ret = bchannel_senddata(bch, skb);
|
||||
if (ret > 0) { /* direct TX */
|
||||
id = hh->id; /* skb can be freed */
|
||||
fill_dma(bc);
|
||||
ret = 0;
|
||||
spin_unlock_irqrestore(&card->lock, flags);
|
||||
if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
|
||||
queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
|
||||
} else
|
||||
spin_unlock_irqrestore(&card->lock, flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&card->lock, flags);
|
||||
return ret;
|
||||
case PH_ACTIVATE_REQ:
|
||||
spin_lock_irqsave(&card->lock, flags);
|
||||
|
@ -778,21 +796,7 @@ nj_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
|
|||
static int
|
||||
channel_bctrl(struct tiger_ch *bc, struct mISDN_ctrl_req *cq)
|
||||
{
|
||||
int ret = 0;
|
||||
struct tiger_hw *card = bc->bch.hw;
|
||||
|
||||
switch (cq->op) {
|
||||
case MISDN_CTRL_GETOP:
|
||||
cq->op = 0;
|
||||
break;
|
||||
/* Nothing implemented yet */
|
||||
case MISDN_CTRL_FILL_EMPTY:
|
||||
default:
|
||||
pr_info("%s: %s unknown Op %x\n", card->name, __func__, cq->op);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
return mISDN_ctrl_bchannel(&bc->bch, cq);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -808,14 +812,10 @@ nj_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
|
|||
switch (cmd) {
|
||||
case CLOSE_CHANNEL:
|
||||
test_and_clear_bit(FLG_OPEN, &bch->Flags);
|
||||
if (test_bit(FLG_ACTIVE, &bch->Flags)) {
|
||||
spin_lock_irqsave(&card->lock, flags);
|
||||
mISDN_freebchannel(bch);
|
||||
test_and_clear_bit(FLG_TX_BUSY, &bch->Flags);
|
||||
test_and_clear_bit(FLG_ACTIVE, &bch->Flags);
|
||||
mode_tiger(bc, ISDN_P_NONE);
|
||||
spin_unlock_irqrestore(&card->lock, flags);
|
||||
}
|
||||
spin_lock_irqsave(&card->lock, flags);
|
||||
mISDN_freebchannel(bch);
|
||||
mode_tiger(bc, ISDN_P_NONE);
|
||||
spin_unlock_irqrestore(&card->lock, flags);
|
||||
ch->protocol = ISDN_P_NONE;
|
||||
ch->peer = NULL;
|
||||
module_put(THIS_MODULE);
|
||||
|
@ -837,7 +837,7 @@ channel_ctrl(struct tiger_hw *card, struct mISDN_ctrl_req *cq)
|
|||
|
||||
switch (cq->op) {
|
||||
case MISDN_CTRL_GETOP:
|
||||
cq->op = MISDN_CTRL_LOOP;
|
||||
cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_L1_TIMER3;
|
||||
break;
|
||||
case MISDN_CTRL_LOOP:
|
||||
/* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
|
||||
|
@ -847,6 +847,9 @@ channel_ctrl(struct tiger_hw *card, struct mISDN_ctrl_req *cq)
|
|||
}
|
||||
ret = card->isac.ctrl(&card->isac, HW_TESTLOOP, cq->channel);
|
||||
break;
|
||||
case MISDN_CTRL_L1_TIMER3:
|
||||
ret = card->isac.ctrl(&card->isac, HW_TIMER3_VALUE, cq->p1);
|
||||
break;
|
||||
default:
|
||||
pr_info("%s: %s unknown Op %x\n", card->name, __func__, cq->op);
|
||||
ret = -EINVAL;
|
||||
|
@ -1027,7 +1030,8 @@ setup_instance(struct tiger_hw *card)
|
|||
for (i = 0; i < 2; i++) {
|
||||
card->bc[i].bch.nr = i + 1;
|
||||
set_channelmap(i + 1, card->isac.dch.dev.channelmap);
|
||||
mISDN_initbchannel(&card->bc[i].bch, MAX_DATA_MEM);
|
||||
mISDN_initbchannel(&card->bc[i].bch, MAX_DATA_MEM,
|
||||
NJ_DMA_RXSIZE >> 1);
|
||||
card->bc[i].bch.hw = card;
|
||||
card->bc[i].bch.ch.send = nj_l2l1B;
|
||||
card->bc[i].bch.ch.ctrl = nj_bctrl;
|
||||
|
|
|
@ -224,7 +224,7 @@ channel_ctrl(struct sfax_hw *sf, struct mISDN_ctrl_req *cq)
|
|||
|
||||
switch (cq->op) {
|
||||
case MISDN_CTRL_GETOP:
|
||||
cq->op = MISDN_CTRL_LOOP;
|
||||
cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_L1_TIMER3;
|
||||
break;
|
||||
case MISDN_CTRL_LOOP:
|
||||
/* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
|
||||
|
@ -234,6 +234,9 @@ channel_ctrl(struct sfax_hw *sf, struct mISDN_ctrl_req *cq)
|
|||
}
|
||||
ret = sf->isac.ctrl(&sf->isac, HW_TESTLOOP, cq->channel);
|
||||
break;
|
||||
case MISDN_CTRL_L1_TIMER3:
|
||||
ret = sf->isac.ctrl(&sf->isac, HW_TIMER3_VALUE, cq->p1);
|
||||
break;
|
||||
default:
|
||||
pr_info("%s: unknown Op %x\n", sf->name, cq->op);
|
||||
ret = -EINVAL;
|
||||
|
|
|
@ -465,6 +465,7 @@ W6692_empty_Bfifo(struct w6692_ch *wch, int count)
|
|||
{
|
||||
struct w6692_hw *card = wch->bch.hw;
|
||||
u8 *ptr;
|
||||
int maxlen;
|
||||
|
||||
pr_debug("%s: empty_Bfifo %d\n", card->name, count);
|
||||
if (unlikely(wch->bch.state == ISDN_P_NONE)) {
|
||||
|
@ -474,20 +475,18 @@ W6692_empty_Bfifo(struct w6692_ch *wch, int count)
|
|||
skb_trim(wch->bch.rx_skb, 0);
|
||||
return;
|
||||
}
|
||||
if (!wch->bch.rx_skb) {
|
||||
wch->bch.rx_skb = mI_alloc_skb(wch->bch.maxlen, GFP_ATOMIC);
|
||||
if (unlikely(!wch->bch.rx_skb)) {
|
||||
pr_info("%s: B receive out of memory\n", card->name);
|
||||
WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK |
|
||||
W_B_CMDR_RACT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (wch->bch.rx_skb->len + count > wch->bch.maxlen) {
|
||||
pr_debug("%s: empty_Bfifo incoming packet too large\n",
|
||||
card->name);
|
||||
if (test_bit(FLG_RX_OFF, &wch->bch.Flags)) {
|
||||
wch->bch.dropcnt += count;
|
||||
WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
|
||||
skb_trim(wch->bch.rx_skb, 0);
|
||||
return;
|
||||
}
|
||||
maxlen = bchannel_get_rxbuf(&wch->bch, count);
|
||||
if (maxlen < 0) {
|
||||
WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
|
||||
if (wch->bch.rx_skb)
|
||||
skb_trim(wch->bch.rx_skb, 0);
|
||||
pr_warning("%s.B%d: No bufferspace for %d bytes\n",
|
||||
card->name, wch->bch.nr, count);
|
||||
return;
|
||||
}
|
||||
ptr = skb_put(wch->bch.rx_skb, count);
|
||||
|
@ -504,16 +503,22 @@ static void
|
|||
W6692_fill_Bfifo(struct w6692_ch *wch)
|
||||
{
|
||||
struct w6692_hw *card = wch->bch.hw;
|
||||
int count;
|
||||
int count, fillempty = 0;
|
||||
u8 *ptr, cmd = W_B_CMDR_RACT | W_B_CMDR_XMS;
|
||||
|
||||
pr_debug("%s: fill Bfifo\n", card->name);
|
||||
if (!wch->bch.tx_skb)
|
||||
return;
|
||||
count = wch->bch.tx_skb->len - wch->bch.tx_idx;
|
||||
if (count <= 0)
|
||||
return;
|
||||
ptr = wch->bch.tx_skb->data + wch->bch.tx_idx;
|
||||
if (!wch->bch.tx_skb) {
|
||||
if (!test_bit(FLG_TX_EMPTY, &wch->bch.Flags))
|
||||
return;
|
||||
ptr = wch->bch.fill;
|
||||
count = W_B_FIFO_THRESH;
|
||||
fillempty = 1;
|
||||
} else {
|
||||
count = wch->bch.tx_skb->len - wch->bch.tx_idx;
|
||||
if (count <= 0)
|
||||
return;
|
||||
ptr = wch->bch.tx_skb->data + wch->bch.tx_idx;
|
||||
}
|
||||
if (count > W_B_FIFO_THRESH)
|
||||
count = W_B_FIFO_THRESH;
|
||||
else if (test_bit(FLG_HDLC, &wch->bch.Flags))
|
||||
|
@ -522,9 +527,16 @@ W6692_fill_Bfifo(struct w6692_ch *wch)
|
|||
pr_debug("%s: fill Bfifo%d/%d\n", card->name,
|
||||
count, wch->bch.tx_idx);
|
||||
wch->bch.tx_idx += count;
|
||||
outsb(wch->addr + W_B_XFIFO, ptr, count);
|
||||
if (fillempty) {
|
||||
while (count > 0) {
|
||||
outsb(wch->addr + W_B_XFIFO, ptr, MISDN_BCH_FILL_SIZE);
|
||||
count -= MISDN_BCH_FILL_SIZE;
|
||||
}
|
||||
} else {
|
||||
outsb(wch->addr + W_B_XFIFO, ptr, count);
|
||||
}
|
||||
WriteW6692B(wch, W_B_CMDR, cmd);
|
||||
if (debug & DEBUG_HW_DFIFO) {
|
||||
if ((debug & DEBUG_HW_BFIFO) && !fillempty) {
|
||||
snprintf(card->log, 63, "B%1d-send %s %d ",
|
||||
wch->bch.nr, card->name, count);
|
||||
print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, ptr, count);
|
||||
|
@ -638,17 +650,17 @@ w6692_mode(struct w6692_ch *wch, u32 pr)
|
|||
static void
|
||||
send_next(struct w6692_ch *wch)
|
||||
{
|
||||
if (wch->bch.tx_skb && wch->bch.tx_idx < wch->bch.tx_skb->len)
|
||||
if (wch->bch.tx_skb && wch->bch.tx_idx < wch->bch.tx_skb->len) {
|
||||
W6692_fill_Bfifo(wch);
|
||||
else {
|
||||
if (wch->bch.tx_skb) {
|
||||
/* send confirm, on trans, free on hdlc. */
|
||||
if (test_bit(FLG_TRANSPARENT, &wch->bch.Flags))
|
||||
confirm_Bsend(&wch->bch);
|
||||
} else {
|
||||
if (wch->bch.tx_skb)
|
||||
dev_kfree_skb(wch->bch.tx_skb);
|
||||
}
|
||||
if (get_next_bframe(&wch->bch))
|
||||
if (get_next_bframe(&wch->bch)) {
|
||||
W6692_fill_Bfifo(wch);
|
||||
test_and_clear_bit(FLG_TX_EMPTY, &wch->bch.Flags);
|
||||
} else if (test_bit(FLG_TX_EMPTY, &wch->bch.Flags)) {
|
||||
W6692_fill_Bfifo(wch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -698,7 +710,7 @@ W6692B_interrupt(struct w6692_hw *card, int ch)
|
|||
if (count == 0)
|
||||
count = W_B_FIFO_THRESH;
|
||||
W6692_empty_Bfifo(wch, count);
|
||||
recv_Bchannel(&wch->bch, 0);
|
||||
recv_Bchannel(&wch->bch, 0, false);
|
||||
}
|
||||
}
|
||||
if (stat & W_B_EXI_RMR) {
|
||||
|
@ -714,9 +726,8 @@ W6692B_interrupt(struct w6692_hw *card, int ch)
|
|||
W_B_CMDR_RRST | W_B_CMDR_RACT);
|
||||
} else {
|
||||
W6692_empty_Bfifo(wch, W_B_FIFO_THRESH);
|
||||
if (test_bit(FLG_TRANSPARENT, &wch->bch.Flags) &&
|
||||
wch->bch.rx_skb && (wch->bch.rx_skb->len > 0))
|
||||
recv_Bchannel(&wch->bch, 0);
|
||||
if (test_bit(FLG_TRANSPARENT, &wch->bch.Flags))
|
||||
recv_Bchannel(&wch->bch, 0, false);
|
||||
}
|
||||
}
|
||||
if (stat & W_B_EXI_RDOV) {
|
||||
|
@ -738,8 +749,8 @@ W6692B_interrupt(struct w6692_hw *card, int ch)
|
|||
wch->bch.nr, star);
|
||||
}
|
||||
if (star & W_B_STAR_XDOW) {
|
||||
pr_debug("%s: B%d XDOW proto=%x\n", card->name,
|
||||
wch->bch.nr, wch->bch.state);
|
||||
pr_warning("%s: B%d XDOW proto=%x\n", card->name,
|
||||
wch->bch.nr, wch->bch.state);
|
||||
#ifdef ERROR_STATISTIC
|
||||
wch->bch.err_xdu++;
|
||||
#endif
|
||||
|
@ -752,20 +763,21 @@ W6692B_interrupt(struct w6692_hw *card, int ch)
|
|||
}
|
||||
}
|
||||
send_next(wch);
|
||||
if (stat & W_B_EXI_XDUN)
|
||||
if (star & W_B_STAR_XDOW)
|
||||
return; /* handle XDOW only once */
|
||||
}
|
||||
if (stat & W_B_EXI_XDUN) {
|
||||
pr_debug("%s: B%d XDUN proto=%x\n", card->name,
|
||||
wch->bch.nr, wch->bch.state);
|
||||
pr_warning("%s: B%d XDUN proto=%x\n", card->name,
|
||||
wch->bch.nr, wch->bch.state);
|
||||
#ifdef ERROR_STATISTIC
|
||||
wch->bch.err_xdu++;
|
||||
#endif
|
||||
WriteW6692B(wch, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT);
|
||||
/* resend */
|
||||
/* resend - no XRST needed */
|
||||
if (wch->bch.tx_skb) {
|
||||
if (!test_bit(FLG_TRANSPARENT, &wch->bch.Flags))
|
||||
wch->bch.tx_idx = 0;
|
||||
} else if (test_bit(FLG_FILLEMPTY, &wch->bch.Flags)) {
|
||||
test_and_set_bit(FLG_TX_EMPTY, &wch->bch.Flags);
|
||||
}
|
||||
send_next(wch);
|
||||
}
|
||||
|
@ -944,22 +956,17 @@ w6692_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
|
|||
struct w6692_hw *card = bch->hw;
|
||||
int ret = -EINVAL;
|
||||
struct mISDNhead *hh = mISDN_HEAD_P(skb);
|
||||
u32 id;
|
||||
u_long flags;
|
||||
unsigned long flags;
|
||||
|
||||
switch (hh->prim) {
|
||||
case PH_DATA_REQ:
|
||||
spin_lock_irqsave(&card->lock, flags);
|
||||
ret = bchannel_senddata(bch, skb);
|
||||
if (ret > 0) { /* direct TX */
|
||||
id = hh->id; /* skb can be freed */
|
||||
ret = 0;
|
||||
W6692_fill_Bfifo(bc);
|
||||
spin_unlock_irqrestore(&card->lock, flags);
|
||||
if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
|
||||
queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
|
||||
} else
|
||||
spin_unlock_irqrestore(&card->lock, flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&card->lock, flags);
|
||||
return ret;
|
||||
case PH_ACTIVATE_REQ:
|
||||
spin_lock_irqsave(&card->lock, flags);
|
||||
|
@ -994,20 +1001,7 @@ w6692_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
|
|||
static int
|
||||
channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (cq->op) {
|
||||
case MISDN_CTRL_GETOP:
|
||||
cq->op = 0;
|
||||
break;
|
||||
/* Nothing implemented yet */
|
||||
case MISDN_CTRL_FILL_EMPTY:
|
||||
default:
|
||||
pr_info("%s: unknown Op %x\n", __func__, cq->op);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
return mISDN_ctrl_bchannel(bch, cq);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1022,7 +1016,6 @@ open_bchannel(struct w6692_hw *card, struct channel_req *rq)
|
|||
bch = &card->bc[rq->adr.channel - 1].bch;
|
||||
if (test_and_set_bit(FLG_OPEN, &bch->Flags))
|
||||
return -EBUSY; /* b-channel can be only open once */
|
||||
test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
|
||||
bch->ch.protocol = rq->protocol;
|
||||
rq->ch = &bch->ch;
|
||||
return 0;
|
||||
|
@ -1035,7 +1028,10 @@ channel_ctrl(struct w6692_hw *card, struct mISDN_ctrl_req *cq)
|
|||
|
||||
switch (cq->op) {
|
||||
case MISDN_CTRL_GETOP:
|
||||
cq->op = 0;
|
||||
cq->op = MISDN_CTRL_L1_TIMER3;
|
||||
break;
|
||||
case MISDN_CTRL_L1_TIMER3:
|
||||
ret = l1_event(card->dch.l1, HW_TIMER3_VALUE | (cq->p1 & 0xff));
|
||||
break;
|
||||
default:
|
||||
pr_info("%s: unknown CTRL OP %x\n", card->name, cq->op);
|
||||
|
@ -1058,15 +1054,10 @@ w6692_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
|
|||
switch (cmd) {
|
||||
case CLOSE_CHANNEL:
|
||||
test_and_clear_bit(FLG_OPEN, &bch->Flags);
|
||||
if (test_bit(FLG_ACTIVE, &bch->Flags)) {
|
||||
spin_lock_irqsave(&card->lock, flags);
|
||||
mISDN_freebchannel(bch);
|
||||
w6692_mode(bc, ISDN_P_NONE);
|
||||
spin_unlock_irqrestore(&card->lock, flags);
|
||||
} else {
|
||||
skb_queue_purge(&bch->rqueue);
|
||||
bch->rcount = 0;
|
||||
}
|
||||
spin_lock_irqsave(&card->lock, flags);
|
||||
mISDN_freebchannel(bch);
|
||||
w6692_mode(bc, ISDN_P_NONE);
|
||||
spin_unlock_irqrestore(&card->lock, flags);
|
||||
ch->protocol = ISDN_P_NONE;
|
||||
ch->peer = NULL;
|
||||
module_put(THIS_MODULE);
|
||||
|
@ -1320,7 +1311,8 @@ setup_instance(struct w6692_hw *card)
|
|||
card->dch.hw = card;
|
||||
card->dch.dev.nrbchan = 2;
|
||||
for (i = 0; i < 2; i++) {
|
||||
mISDN_initbchannel(&card->bc[i].bch, MAX_DATA_MEM);
|
||||
mISDN_initbchannel(&card->bc[i].bch, MAX_DATA_MEM,
|
||||
W_B_FIFO_THRESH);
|
||||
card->bc[i].bch.hw = card;
|
||||
card->bc[i].bch.nr = i + 1;
|
||||
card->bc[i].bch.ch.nr = i + 1;
|
||||
|
|
|
@ -156,17 +156,9 @@ static ssize_t
|
|||
hysdn_log_write(struct file *file, const char __user *buf, size_t count, loff_t *off)
|
||||
{
|
||||
int rc;
|
||||
unsigned char valbuf[128];
|
||||
hysdn_card *card = file->private_data;
|
||||
|
||||
if (count > (sizeof(valbuf) - 1))
|
||||
count = sizeof(valbuf) - 1; /* limit length */
|
||||
if (copy_from_user(valbuf, buf, count))
|
||||
return (-EFAULT); /* copy failed */
|
||||
|
||||
valbuf[count] = 0; /* terminating 0 */
|
||||
|
||||
rc = kstrtoul(valbuf, 0, &card->debug_flags);
|
||||
rc = kstrtoul_from_user(buf, count, 0, &card->debug_flags);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
hysdn_addlog(card, "debug set to 0x%lx", card->debug_flags);
|
||||
|
|
|
@ -612,7 +612,7 @@ static int bsd_compress(void *state, struct sk_buff *skb_in, struct sk_buff *skb
|
|||
db->n_bits++;
|
||||
|
||||
/* If output length is too large then this is an incompressible frame. */
|
||||
if (!skb_out || (skb_out && skb_out->len >= skb_in->len)) {
|
||||
if (!skb_out || skb_out->len >= skb_in->len) {
|
||||
++db->incomp_count;
|
||||
db->incomp_bytes += isize;
|
||||
return 0;
|
||||
|
|
|
@ -355,6 +355,22 @@ mISDN_unregister_Bprotocol(struct Bprotocol *bp)
|
|||
}
|
||||
EXPORT_SYMBOL(mISDN_unregister_Bprotocol);
|
||||
|
||||
static const char *msg_no_channel = "<no channel>";
|
||||
static const char *msg_no_stack = "<no stack>";
|
||||
static const char *msg_no_stackdev = "<no stack device>";
|
||||
|
||||
const char *mISDNDevName4ch(struct mISDNchannel *ch)
|
||||
{
|
||||
if (!ch)
|
||||
return msg_no_channel;
|
||||
if (!ch->st)
|
||||
return msg_no_stack;
|
||||
if (!ch->st->dev)
|
||||
return msg_no_stackdev;
|
||||
return dev_name(&ch->st->dev->dev);
|
||||
};
|
||||
EXPORT_SYMBOL(mISDNDevName4ch);
|
||||
|
||||
static int
|
||||
mISDNInit(void)
|
||||
{
|
||||
|
|
|
@ -76,7 +76,9 @@ extern u8 dsp_silence;
|
|||
#define MAX_SECONDS_JITTER_CHECK 5
|
||||
|
||||
extern struct timer_list dsp_spl_tl;
|
||||
extern u32 dsp_spl_jiffies;
|
||||
|
||||
/* the datatype need to match jiffies datatype */
|
||||
extern unsigned long dsp_spl_jiffies;
|
||||
|
||||
/* the structure of conferences:
|
||||
*
|
||||
|
|
|
@ -742,8 +742,8 @@ dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp)
|
|||
member->dsp->pcm_slot_tx,
|
||||
member->dsp->pcm_bank_tx,
|
||||
member->dsp->pcm_bank_rx);
|
||||
conf->hardware = 0;
|
||||
conf->software = 1;
|
||||
conf->hardware = 1;
|
||||
conf->software = tx_data;
|
||||
return;
|
||||
}
|
||||
/* find a new slot */
|
||||
|
@ -834,8 +834,8 @@ dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp)
|
|||
nextm->dsp->name,
|
||||
member->dsp->pcm_slot_tx,
|
||||
member->dsp->pcm_slot_rx);
|
||||
conf->hardware = 0;
|
||||
conf->software = 1;
|
||||
conf->hardware = 1;
|
||||
conf->software = tx_data;
|
||||
return;
|
||||
}
|
||||
/* find two new slot */
|
||||
|
@ -939,8 +939,11 @@ dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp)
|
|||
/* for more than two members.. */
|
||||
|
||||
/* if all members already have the same conference */
|
||||
if (all_conf)
|
||||
if (all_conf) {
|
||||
conf->hardware = 1;
|
||||
conf->software = tx_data;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* if there is an existing conference, but not all members have joined
|
||||
|
@ -1013,6 +1016,8 @@ dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp)
|
|||
dsp_cmx_hw_message(member->dsp,
|
||||
MISDN_CTRL_HFC_CONF_JOIN, current_conf, 0, 0, 0);
|
||||
}
|
||||
conf->hardware = 1;
|
||||
conf->software = tx_data;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1328,7 +1333,7 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members)
|
|||
}
|
||||
if (dsp->conf && dsp->conf->software && dsp->conf->hardware)
|
||||
tx_data_only = 1;
|
||||
if (dsp->conf->software && dsp->echo.hardware)
|
||||
if (dsp->echo.software && dsp->echo.hardware)
|
||||
tx_data_only = 1;
|
||||
}
|
||||
|
||||
|
@ -1619,7 +1624,7 @@ send_packet:
|
|||
|
||||
static u32 jittercount; /* counter for jitter check */
|
||||
struct timer_list dsp_spl_tl;
|
||||
u32 dsp_spl_jiffies; /* calculate the next time to fire */
|
||||
unsigned long dsp_spl_jiffies; /* calculate the next time to fire */
|
||||
static u16 dsp_count; /* last sample count */
|
||||
static int dsp_count_valid; /* if we have last sample count */
|
||||
|
||||
|
|
|
@ -268,6 +268,7 @@ dsp_fill_empty(struct dsp *dsp)
|
|||
}
|
||||
cq.op = MISDN_CTRL_FILL_EMPTY;
|
||||
cq.p1 = 1;
|
||||
cq.p2 = dsp_silence;
|
||||
if (dsp->ch.peer->ctrl(dsp->ch.peer, CONTROL_CHANNEL, &cq)) {
|
||||
printk(KERN_DEBUG "%s: CONTROL_CHANNEL failed\n",
|
||||
__func__);
|
||||
|
|
|
@ -222,16 +222,25 @@ coefficients:
|
|||
goto storedigit;
|
||||
}
|
||||
|
||||
if (dsp_debug & DEBUG_DSP_DTMFCOEFF)
|
||||
if (dsp_debug & DEBUG_DSP_DTMFCOEFF) {
|
||||
s32 tresh_100 = tresh/100;
|
||||
|
||||
if (tresh_100 == 0) {
|
||||
tresh_100 = 1;
|
||||
printk(KERN_DEBUG
|
||||
"tresh(%d) too small set tresh/100 to 1\n",
|
||||
tresh);
|
||||
}
|
||||
printk(KERN_DEBUG "a %3d %3d %3d %3d %3d %3d %3d %3d"
|
||||
" tr:%3d r %3d %3d %3d %3d %3d %3d %3d %3d\n",
|
||||
result[0] / 10000, result[1] / 10000, result[2] / 10000,
|
||||
result[3] / 10000, result[4] / 10000, result[5] / 10000,
|
||||
result[6] / 10000, result[7] / 10000, tresh / 10000,
|
||||
result[0] / (tresh / 100), result[1] / (tresh / 100),
|
||||
result[2] / (tresh / 100), result[3] / (tresh / 100),
|
||||
result[4] / (tresh / 100), result[5] / (tresh / 100),
|
||||
result[6] / (tresh / 100), result[7] / (tresh / 100));
|
||||
result[0] / (tresh_100), result[1] / (tresh_100),
|
||||
result[2] / (tresh_100), result[3] / (tresh_100),
|
||||
result[4] / (tresh_100), result[5] / (tresh_100),
|
||||
result[6] / (tresh_100), result[7] / (tresh_100));
|
||||
}
|
||||
|
||||
/* calc digit (lowgroup/highgroup) */
|
||||
lowgroup = -1;
|
||||
|
|
|
@ -81,10 +81,16 @@ mISDN_initdchannel(struct dchannel *ch, int maxlen, void *phf)
|
|||
EXPORT_SYMBOL(mISDN_initdchannel);
|
||||
|
||||
int
|
||||
mISDN_initbchannel(struct bchannel *ch, int maxlen)
|
||||
mISDN_initbchannel(struct bchannel *ch, unsigned short maxlen,
|
||||
unsigned short minlen)
|
||||
{
|
||||
ch->Flags = 0;
|
||||
ch->minlen = minlen;
|
||||
ch->next_minlen = minlen;
|
||||
ch->init_minlen = minlen;
|
||||
ch->maxlen = maxlen;
|
||||
ch->next_maxlen = maxlen;
|
||||
ch->init_maxlen = maxlen;
|
||||
ch->hw = NULL;
|
||||
ch->rx_skb = NULL;
|
||||
ch->tx_skb = NULL;
|
||||
|
@ -134,6 +140,14 @@ mISDN_clear_bchannel(struct bchannel *ch)
|
|||
test_and_clear_bit(FLG_TX_BUSY, &ch->Flags);
|
||||
test_and_clear_bit(FLG_TX_NEXT, &ch->Flags);
|
||||
test_and_clear_bit(FLG_ACTIVE, &ch->Flags);
|
||||
test_and_clear_bit(FLG_FILLEMPTY, &ch->Flags);
|
||||
test_and_clear_bit(FLG_TX_EMPTY, &ch->Flags);
|
||||
test_and_clear_bit(FLG_RX_OFF, &ch->Flags);
|
||||
ch->dropcnt = 0;
|
||||
ch->minlen = ch->init_minlen;
|
||||
ch->next_minlen = ch->init_minlen;
|
||||
ch->maxlen = ch->init_maxlen;
|
||||
ch->next_maxlen = ch->init_maxlen;
|
||||
}
|
||||
EXPORT_SYMBOL(mISDN_clear_bchannel);
|
||||
|
||||
|
@ -148,6 +162,51 @@ mISDN_freebchannel(struct bchannel *ch)
|
|||
}
|
||||
EXPORT_SYMBOL(mISDN_freebchannel);
|
||||
|
||||
int
|
||||
mISDN_ctrl_bchannel(struct bchannel *bch, struct mISDN_ctrl_req *cq)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (cq->op) {
|
||||
case MISDN_CTRL_GETOP:
|
||||
cq->op = MISDN_CTRL_RX_BUFFER | MISDN_CTRL_FILL_EMPTY |
|
||||
MISDN_CTRL_RX_OFF;
|
||||
break;
|
||||
case MISDN_CTRL_FILL_EMPTY:
|
||||
if (cq->p1) {
|
||||
memset(bch->fill, cq->p2 & 0xff, MISDN_BCH_FILL_SIZE);
|
||||
test_and_set_bit(FLG_FILLEMPTY, &bch->Flags);
|
||||
} else {
|
||||
test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
|
||||
}
|
||||
break;
|
||||
case MISDN_CTRL_RX_OFF:
|
||||
/* read back dropped byte count */
|
||||
cq->p2 = bch->dropcnt;
|
||||
if (cq->p1)
|
||||
test_and_set_bit(FLG_RX_OFF, &bch->Flags);
|
||||
else
|
||||
test_and_clear_bit(FLG_RX_OFF, &bch->Flags);
|
||||
bch->dropcnt = 0;
|
||||
break;
|
||||
case MISDN_CTRL_RX_BUFFER:
|
||||
if (cq->p2 > MISDN_CTRL_RX_SIZE_IGNORE)
|
||||
bch->next_maxlen = cq->p2;
|
||||
if (cq->p1 > MISDN_CTRL_RX_SIZE_IGNORE)
|
||||
bch->next_minlen = cq->p1;
|
||||
/* we return the old values */
|
||||
cq->p1 = bch->minlen;
|
||||
cq->p2 = bch->maxlen;
|
||||
break;
|
||||
default:
|
||||
pr_info("mISDN unhandled control %x operation\n", cq->op);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(mISDN_ctrl_bchannel);
|
||||
|
||||
static inline u_int
|
||||
get_sapi_tei(u_char *p)
|
||||
{
|
||||
|
@ -197,24 +256,37 @@ recv_Echannel(struct dchannel *ech, struct dchannel *dch)
|
|||
EXPORT_SYMBOL(recv_Echannel);
|
||||
|
||||
void
|
||||
recv_Bchannel(struct bchannel *bch, unsigned int id)
|
||||
recv_Bchannel(struct bchannel *bch, unsigned int id, bool force)
|
||||
{
|
||||
struct mISDNhead *hh;
|
||||
|
||||
hh = mISDN_HEAD_P(bch->rx_skb);
|
||||
hh->prim = PH_DATA_IND;
|
||||
hh->id = id;
|
||||
if (bch->rcount >= 64) {
|
||||
printk(KERN_WARNING "B-channel %p receive queue overflow, "
|
||||
"flushing!\n", bch);
|
||||
skb_queue_purge(&bch->rqueue);
|
||||
bch->rcount = 0;
|
||||
/* if allocation did fail upper functions still may call us */
|
||||
if (unlikely(!bch->rx_skb))
|
||||
return;
|
||||
if (unlikely(!bch->rx_skb->len)) {
|
||||
/* we have no data to send - this may happen after recovery
|
||||
* from overflow or too small allocation.
|
||||
* We need to free the buffer here */
|
||||
dev_kfree_skb(bch->rx_skb);
|
||||
bch->rx_skb = NULL;
|
||||
} else {
|
||||
if (test_bit(FLG_TRANSPARENT, &bch->Flags) &&
|
||||
(bch->rx_skb->len < bch->minlen) && !force)
|
||||
return;
|
||||
hh = mISDN_HEAD_P(bch->rx_skb);
|
||||
hh->prim = PH_DATA_IND;
|
||||
hh->id = id;
|
||||
if (bch->rcount >= 64) {
|
||||
printk(KERN_WARNING
|
||||
"B%d receive queue overflow - flushing!\n",
|
||||
bch->nr);
|
||||
skb_queue_purge(&bch->rqueue);
|
||||
}
|
||||
bch->rcount++;
|
||||
skb_queue_tail(&bch->rqueue, bch->rx_skb);
|
||||
bch->rx_skb = NULL;
|
||||
schedule_event(bch, FLG_RECVQUEUE);
|
||||
}
|
||||
bch->rcount++;
|
||||
skb_queue_tail(&bch->rqueue, bch->rx_skb);
|
||||
bch->rx_skb = NULL;
|
||||
schedule_event(bch, FLG_RECVQUEUE);
|
||||
}
|
||||
EXPORT_SYMBOL(recv_Bchannel);
|
||||
|
||||
|
@ -272,7 +344,7 @@ get_next_dframe(struct dchannel *dch)
|
|||
}
|
||||
EXPORT_SYMBOL(get_next_dframe);
|
||||
|
||||
void
|
||||
static void
|
||||
confirm_Bsend(struct bchannel *bch)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
@ -294,7 +366,6 @@ confirm_Bsend(struct bchannel *bch)
|
|||
skb_queue_tail(&bch->rqueue, skb);
|
||||
schedule_event(bch, FLG_RECVQUEUE);
|
||||
}
|
||||
EXPORT_SYMBOL(confirm_Bsend);
|
||||
|
||||
int
|
||||
get_next_bframe(struct bchannel *bch)
|
||||
|
@ -305,8 +376,8 @@ get_next_bframe(struct bchannel *bch)
|
|||
if (bch->tx_skb) {
|
||||
bch->next_skb = NULL;
|
||||
test_and_clear_bit(FLG_TX_NEXT, &bch->Flags);
|
||||
if (!test_bit(FLG_TRANSPARENT, &bch->Flags))
|
||||
confirm_Bsend(bch); /* not for transparent */
|
||||
/* confirm imediately to allow next data */
|
||||
confirm_Bsend(bch);
|
||||
return 1;
|
||||
} else {
|
||||
test_and_clear_bit(FLG_TX_NEXT, &bch->Flags);
|
||||
|
@ -395,7 +466,62 @@ bchannel_senddata(struct bchannel *ch, struct sk_buff *skb)
|
|||
/* write to fifo */
|
||||
ch->tx_skb = skb;
|
||||
ch->tx_idx = 0;
|
||||
confirm_Bsend(ch);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(bchannel_senddata);
|
||||
|
||||
/* The function allocates a new receive skb on demand with a size for the
|
||||
* requirements of the current protocol. It returns the tailroom of the
|
||||
* receive skb or an error.
|
||||
*/
|
||||
int
|
||||
bchannel_get_rxbuf(struct bchannel *bch, int reqlen)
|
||||
{
|
||||
int len;
|
||||
|
||||
if (bch->rx_skb) {
|
||||
len = skb_tailroom(bch->rx_skb);
|
||||
if (len < reqlen) {
|
||||
pr_warning("B%d no space for %d (only %d) bytes\n",
|
||||
bch->nr, reqlen, len);
|
||||
if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {
|
||||
/* send what we have now and try a new buffer */
|
||||
recv_Bchannel(bch, 0, true);
|
||||
} else {
|
||||
/* on HDLC we have to drop too big frames */
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
} else {
|
||||
return len;
|
||||
}
|
||||
}
|
||||
/* update current min/max length first */
|
||||
if (unlikely(bch->maxlen != bch->next_maxlen))
|
||||
bch->maxlen = bch->next_maxlen;
|
||||
if (unlikely(bch->minlen != bch->next_minlen))
|
||||
bch->minlen = bch->next_minlen;
|
||||
if (unlikely(reqlen > bch->maxlen))
|
||||
return -EMSGSIZE;
|
||||
if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {
|
||||
if (reqlen >= bch->minlen) {
|
||||
len = reqlen;
|
||||
} else {
|
||||
len = 2 * bch->minlen;
|
||||
if (len > bch->maxlen)
|
||||
len = bch->maxlen;
|
||||
}
|
||||
} else {
|
||||
/* with HDLC we do not know the length yet */
|
||||
len = bch->maxlen;
|
||||
}
|
||||
bch->rx_skb = mI_alloc_skb(len, GFP_ATOMIC);
|
||||
if (!bch->rx_skb) {
|
||||
pr_warning("B%d receive no memory for %d bytes\n",
|
||||
bch->nr, len);
|
||||
len = -ENOMEM;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
EXPORT_SYMBOL(bchannel_get_rxbuf);
|
||||
|
|
|
@ -1420,7 +1420,7 @@ init_card(struct l1oip *hc, int pri, int bundle)
|
|||
bch->nr = i + ch;
|
||||
bch->slot = i + ch;
|
||||
bch->debug = debug;
|
||||
mISDN_initbchannel(bch, MAX_DATA_MEM);
|
||||
mISDN_initbchannel(bch, MAX_DATA_MEM, 0);
|
||||
bch->hw = hc;
|
||||
bch->ch.send = handle_bmsg;
|
||||
bch->ch.ctrl = l1oip_bctrl;
|
||||
|
|
|
@ -28,13 +28,15 @@ static u_int *debug;
|
|||
struct layer1 {
|
||||
u_long Flags;
|
||||
struct FsmInst l1m;
|
||||
struct FsmTimer timer;
|
||||
struct FsmTimer timer3;
|
||||
struct FsmTimer timerX;
|
||||
int delay;
|
||||
int t3_value;
|
||||
struct dchannel *dch;
|
||||
dchannel_l1callback *dcb;
|
||||
};
|
||||
|
||||
#define TIMER3_VALUE 7000
|
||||
#define TIMER3_DEFAULT_VALUE 7000
|
||||
|
||||
static
|
||||
struct Fsm l1fsm_s = {NULL, 0, 0, NULL, NULL};
|
||||
|
@ -134,7 +136,7 @@ l1_deact_req_s(struct FsmInst *fi, int event, void *arg)
|
|||
struct layer1 *l1 = fi->userdata;
|
||||
|
||||
mISDN_FsmChangeState(fi, ST_L1_F3);
|
||||
mISDN_FsmRestartTimer(&l1->timer, 550, EV_TIMER_DEACT, NULL, 2);
|
||||
mISDN_FsmRestartTimer(&l1->timerX, 550, EV_TIMER_DEACT, NULL, 2);
|
||||
test_and_set_bit(FLG_L1_DEACTTIMER, &l1->Flags);
|
||||
}
|
||||
|
||||
|
@ -179,11 +181,11 @@ l1_info4_ind(struct FsmInst *fi, int event, void *arg)
|
|||
mISDN_FsmChangeState(fi, ST_L1_F7);
|
||||
l1->dcb(l1->dch, INFO3_P8);
|
||||
if (test_and_clear_bit(FLG_L1_DEACTTIMER, &l1->Flags))
|
||||
mISDN_FsmDelTimer(&l1->timer, 4);
|
||||
mISDN_FsmDelTimer(&l1->timerX, 4);
|
||||
if (!test_bit(FLG_L1_ACTIVATED, &l1->Flags)) {
|
||||
if (test_and_clear_bit(FLG_L1_T3RUN, &l1->Flags))
|
||||
mISDN_FsmDelTimer(&l1->timer, 3);
|
||||
mISDN_FsmRestartTimer(&l1->timer, 110, EV_TIMER_ACT, NULL, 2);
|
||||
mISDN_FsmDelTimer(&l1->timer3, 3);
|
||||
mISDN_FsmRestartTimer(&l1->timerX, 110, EV_TIMER_ACT, NULL, 2);
|
||||
test_and_set_bit(FLG_L1_ACTTIMER, &l1->Flags);
|
||||
}
|
||||
}
|
||||
|
@ -201,7 +203,7 @@ l1_timer3(struct FsmInst *fi, int event, void *arg)
|
|||
}
|
||||
if (l1->l1m.state != ST_L1_F6) {
|
||||
mISDN_FsmChangeState(fi, ST_L1_F3);
|
||||
l1->dcb(l1->dch, HW_POWERUP_REQ);
|
||||
/* do not force anything here, we need send INFO 0 */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -233,8 +235,9 @@ l1_activate_s(struct FsmInst *fi, int event, void *arg)
|
|||
{
|
||||
struct layer1 *l1 = fi->userdata;
|
||||
|
||||
mISDN_FsmRestartTimer(&l1->timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
|
||||
mISDN_FsmRestartTimer(&l1->timer3, l1->t3_value, EV_TIMER3, NULL, 2);
|
||||
test_and_set_bit(FLG_L1_T3RUN, &l1->Flags);
|
||||
/* Tell HW to send INFO 1 */
|
||||
l1->dcb(l1->dch, HW_RESET_REQ);
|
||||
}
|
||||
|
||||
|
@ -302,7 +305,8 @@ static struct FsmNode L1SFnList[] =
|
|||
|
||||
static void
|
||||
release_l1(struct layer1 *l1) {
|
||||
mISDN_FsmDelTimer(&l1->timer, 0);
|
||||
mISDN_FsmDelTimer(&l1->timerX, 0);
|
||||
mISDN_FsmDelTimer(&l1->timer3, 0);
|
||||
if (l1->dch)
|
||||
l1->dch->l1 = NULL;
|
||||
module_put(THIS_MODULE);
|
||||
|
@ -356,6 +360,16 @@ l1_event(struct layer1 *l1, u_int event)
|
|||
release_l1(l1);
|
||||
break;
|
||||
default:
|
||||
if ((event & ~HW_TIMER3_VMASK) == HW_TIMER3_VALUE) {
|
||||
int val = event & HW_TIMER3_VMASK;
|
||||
|
||||
if (val < 5)
|
||||
val = 5;
|
||||
if (val > 30)
|
||||
val = 30;
|
||||
l1->t3_value = val;
|
||||
break;
|
||||
}
|
||||
if (*debug & DEBUG_L1)
|
||||
printk(KERN_DEBUG "%s %x unhandled\n",
|
||||
__func__, event);
|
||||
|
@ -377,13 +391,15 @@ create_l1(struct dchannel *dch, dchannel_l1callback *dcb) {
|
|||
nl1->l1m.fsm = &l1fsm_s;
|
||||
nl1->l1m.state = ST_L1_F3;
|
||||
nl1->Flags = 0;
|
||||
nl1->t3_value = TIMER3_DEFAULT_VALUE;
|
||||
nl1->l1m.debug = *debug & DEBUG_L1_FSM;
|
||||
nl1->l1m.userdata = nl1;
|
||||
nl1->l1m.userint = 0;
|
||||
nl1->l1m.printdebug = l1m_debug;
|
||||
nl1->dch = dch;
|
||||
nl1->dcb = dcb;
|
||||
mISDN_FsmInitTimer(&nl1->l1m, &nl1->timer);
|
||||
mISDN_FsmInitTimer(&nl1->l1m, &nl1->timer3);
|
||||
mISDN_FsmInitTimer(&nl1->l1m, &nl1->timerX);
|
||||
__module_get(THIS_MODULE);
|
||||
dch->l1 = nl1;
|
||||
return 0;
|
||||
|
|
|
@ -58,6 +58,8 @@ enum {
|
|||
EV_L1_DEACTIVATE,
|
||||
EV_L2_T200,
|
||||
EV_L2_T203,
|
||||
EV_L2_T200I,
|
||||
EV_L2_T203I,
|
||||
EV_L2_SET_OWN_BUSY,
|
||||
EV_L2_CLEAR_OWN_BUSY,
|
||||
EV_L2_FRAME_ERROR,
|
||||
|
@ -86,6 +88,8 @@ static char *strL2Event[] =
|
|||
"EV_L1_DEACTIVATE",
|
||||
"EV_L2_T200",
|
||||
"EV_L2_T203",
|
||||
"EV_L2_T200I",
|
||||
"EV_L2_T203I",
|
||||
"EV_L2_SET_OWN_BUSY",
|
||||
"EV_L2_CLEAR_OWN_BUSY",
|
||||
"EV_L2_FRAME_ERROR",
|
||||
|
@ -106,8 +110,8 @@ l2m_debug(struct FsmInst *fi, char *fmt, ...)
|
|||
vaf.fmt = fmt;
|
||||
vaf.va = &va;
|
||||
|
||||
printk(KERN_DEBUG "l2 (sapi %d tei %d): %pV\n",
|
||||
l2->sapi, l2->tei, &vaf);
|
||||
printk(KERN_DEBUG "%s l2 (sapi %d tei %d): %pV\n",
|
||||
mISDNDevName4ch(&l2->ch), l2->sapi, l2->tei, &vaf);
|
||||
|
||||
va_end(va);
|
||||
}
|
||||
|
@ -150,7 +154,8 @@ l2up(struct layer2 *l2, u_int prim, struct sk_buff *skb)
|
|||
mISDN_HEAD_ID(skb) = (l2->ch.nr << 16) | l2->ch.addr;
|
||||
err = l2->up->send(l2->up, skb);
|
||||
if (err) {
|
||||
printk(KERN_WARNING "%s: err=%d\n", __func__, err);
|
||||
printk(KERN_WARNING "%s: dev %s err=%d\n", __func__,
|
||||
mISDNDevName4ch(&l2->ch), err);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
}
|
||||
|
@ -174,7 +179,8 @@ l2up_create(struct layer2 *l2, u_int prim, int len, void *arg)
|
|||
memcpy(skb_put(skb, len), arg, len);
|
||||
err = l2->up->send(l2->up, skb);
|
||||
if (err) {
|
||||
printk(KERN_WARNING "%s: err=%d\n", __func__, err);
|
||||
printk(KERN_WARNING "%s: dev %s err=%d\n", __func__,
|
||||
mISDNDevName4ch(&l2->ch), err);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
}
|
||||
|
@ -185,7 +191,8 @@ l2down_skb(struct layer2 *l2, struct sk_buff *skb) {
|
|||
|
||||
ret = l2->ch.recv(l2->ch.peer, skb);
|
||||
if (ret && (*debug & DEBUG_L2_RECV))
|
||||
printk(KERN_DEBUG "l2down_skb: ret(%d)\n", ret);
|
||||
printk(KERN_DEBUG "l2down_skb: dev %s ret(%d)\n",
|
||||
mISDNDevName4ch(&l2->ch), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -276,12 +283,37 @@ ph_data_confirm(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
l2_timeout(struct FsmInst *fi, int event, void *arg)
|
||||
{
|
||||
struct layer2 *l2 = fi->userdata;
|
||||
struct sk_buff *skb;
|
||||
struct mISDNhead *hh;
|
||||
|
||||
skb = mI_alloc_skb(0, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
printk(KERN_WARNING "%s: L2(%d,%d) nr:%x timer %s no skb\n",
|
||||
mISDNDevName4ch(&l2->ch), l2->sapi, l2->tei,
|
||||
l2->ch.nr, event == EV_L2_T200 ? "T200" : "T203");
|
||||
return;
|
||||
}
|
||||
hh = mISDN_HEAD_P(skb);
|
||||
hh->prim = event == EV_L2_T200 ? DL_TIMER200_IND : DL_TIMER203_IND;
|
||||
hh->id = l2->ch.nr;
|
||||
if (*debug & DEBUG_TIMER)
|
||||
printk(KERN_DEBUG "%s: L2(%d,%d) nr:%x timer %s expired\n",
|
||||
mISDNDevName4ch(&l2->ch), l2->sapi, l2->tei,
|
||||
l2->ch.nr, event == EV_L2_T200 ? "T200" : "T203");
|
||||
if (l2->ch.st)
|
||||
l2->ch.st->own.recv(&l2->ch.st->own, skb);
|
||||
}
|
||||
|
||||
static int
|
||||
l2mgr(struct layer2 *l2, u_int prim, void *arg) {
|
||||
long c = (long)arg;
|
||||
|
||||
printk(KERN_WARNING
|
||||
"l2mgr: addr:%x prim %x %c\n", l2->id, prim, (char)c);
|
||||
printk(KERN_WARNING "l2mgr: dev %s addr:%x prim %x %c\n",
|
||||
mISDNDevName4ch(&l2->ch), l2->id, prim, (char)c);
|
||||
if (test_bit(FLG_LAPD, &l2->flag) &&
|
||||
!test_bit(FLG_FIXED_TEI, &l2->flag)) {
|
||||
switch (c) {
|
||||
|
@ -603,8 +635,8 @@ send_uframe(struct layer2 *l2, struct sk_buff *skb, u_char cmd, u_char cr)
|
|||
else {
|
||||
skb = mI_alloc_skb(i, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
printk(KERN_WARNING "%s: can't alloc skbuff\n",
|
||||
__func__);
|
||||
printk(KERN_WARNING "%s: can't alloc skbuff in %s\n",
|
||||
mISDNDevName4ch(&l2->ch), __func__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1089,8 +1121,8 @@ enquiry_cr(struct layer2 *l2, u_char typ, u_char cr, u_char pf)
|
|||
tmp[i++] = (l2->vr << 5) | typ | (pf ? 0x10 : 0);
|
||||
skb = mI_alloc_skb(i, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
printk(KERN_WARNING
|
||||
"isdnl2 can't alloc sbbuff for enquiry_cr\n");
|
||||
printk(KERN_WARNING "%s: isdnl2 can't alloc sbbuff in %s\n",
|
||||
mISDNDevName4ch(&l2->ch), __func__);
|
||||
return;
|
||||
}
|
||||
memcpy(skb_put(skb, i), tmp, i);
|
||||
|
@ -1150,7 +1182,7 @@ invoke_retransmission(struct layer2 *l2, unsigned int nr)
|
|||
else
|
||||
printk(KERN_WARNING
|
||||
"%s: windowar[%d] is NULL\n",
|
||||
__func__, p1);
|
||||
mISDNDevName4ch(&l2->ch), p1);
|
||||
l2->windowar[p1] = NULL;
|
||||
}
|
||||
mISDN_FsmEvent(&l2->l2m, EV_L2_ACK_PULL, NULL);
|
||||
|
@ -1461,8 +1493,8 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
|
|||
p1 = (l2->vs - l2->va) % 8;
|
||||
p1 = (p1 + l2->sow) % l2->window;
|
||||
if (l2->windowar[p1]) {
|
||||
printk(KERN_WARNING "isdnl2 try overwrite ack queue entry %d\n",
|
||||
p1);
|
||||
printk(KERN_WARNING "%s: l2 try overwrite ack queue entry %d\n",
|
||||
mISDNDevName4ch(&l2->ch), p1);
|
||||
dev_kfree_skb(l2->windowar[p1]);
|
||||
}
|
||||
l2->windowar[p1] = skb;
|
||||
|
@ -1482,12 +1514,14 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
|
|||
memcpy(skb_push(nskb, i), header, i);
|
||||
else {
|
||||
printk(KERN_WARNING
|
||||
"isdnl2 pull_iqueue skb header(%d/%d) too short\n", i, p1);
|
||||
"%s: L2 pull_iqueue skb header(%d/%d) too short\n",
|
||||
mISDNDevName4ch(&l2->ch), i, p1);
|
||||
oskb = nskb;
|
||||
nskb = mI_alloc_skb(oskb->len + i, GFP_ATOMIC);
|
||||
if (!nskb) {
|
||||
dev_kfree_skb(oskb);
|
||||
printk(KERN_WARNING "%s: no skb mem\n", __func__);
|
||||
printk(KERN_WARNING "%s: no skb mem in %s\n",
|
||||
mISDNDevName4ch(&l2->ch), __func__);
|
||||
return;
|
||||
}
|
||||
memcpy(skb_put(nskb, i), header, i);
|
||||
|
@ -1814,11 +1848,16 @@ static struct FsmNode L2FnList[] =
|
|||
{ST_L2_8, EV_L2_SUPER, l2_st8_got_super},
|
||||
{ST_L2_7, EV_L2_I, l2_got_iframe},
|
||||
{ST_L2_8, EV_L2_I, l2_got_iframe},
|
||||
{ST_L2_5, EV_L2_T200, l2_st5_tout_200},
|
||||
{ST_L2_6, EV_L2_T200, l2_st6_tout_200},
|
||||
{ST_L2_7, EV_L2_T200, l2_st7_tout_200},
|
||||
{ST_L2_8, EV_L2_T200, l2_st8_tout_200},
|
||||
{ST_L2_7, EV_L2_T203, l2_st7_tout_203},
|
||||
{ST_L2_5, EV_L2_T200, l2_timeout},
|
||||
{ST_L2_6, EV_L2_T200, l2_timeout},
|
||||
{ST_L2_7, EV_L2_T200, l2_timeout},
|
||||
{ST_L2_8, EV_L2_T200, l2_timeout},
|
||||
{ST_L2_7, EV_L2_T203, l2_timeout},
|
||||
{ST_L2_5, EV_L2_T200I, l2_st5_tout_200},
|
||||
{ST_L2_6, EV_L2_T200I, l2_st6_tout_200},
|
||||
{ST_L2_7, EV_L2_T200I, l2_st7_tout_200},
|
||||
{ST_L2_8, EV_L2_T200I, l2_st8_tout_200},
|
||||
{ST_L2_7, EV_L2_T203I, l2_st7_tout_203},
|
||||
{ST_L2_7, EV_L2_ACK_PULL, l2_pull_iqueue},
|
||||
{ST_L2_7, EV_L2_SET_OWN_BUSY, l2_set_own_busy},
|
||||
{ST_L2_8, EV_L2_SET_OWN_BUSY, l2_set_own_busy},
|
||||
|
@ -1858,7 +1897,8 @@ ph_data_indication(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb)
|
|||
ptei = *datap++;
|
||||
if ((psapi & 1) || !(ptei & 1)) {
|
||||
printk(KERN_WARNING
|
||||
"l2 D-channel frame wrong EA0/EA1\n");
|
||||
"%s l2 D-channel frame wrong EA0/EA1\n",
|
||||
mISDNDevName4ch(&l2->ch));
|
||||
return ret;
|
||||
}
|
||||
psapi >>= 2;
|
||||
|
@ -1867,7 +1907,8 @@ ph_data_indication(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb)
|
|||
/* not our business */
|
||||
if (*debug & DEBUG_L2)
|
||||
printk(KERN_DEBUG "%s: sapi %d/%d mismatch\n",
|
||||
__func__, psapi, l2->sapi);
|
||||
mISDNDevName4ch(&l2->ch), psapi,
|
||||
l2->sapi);
|
||||
dev_kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1875,7 +1916,7 @@ ph_data_indication(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb)
|
|||
/* not our business */
|
||||
if (*debug & DEBUG_L2)
|
||||
printk(KERN_DEBUG "%s: tei %d/%d mismatch\n",
|
||||
__func__, ptei, l2->tei);
|
||||
mISDNDevName4ch(&l2->ch), ptei, l2->tei);
|
||||
dev_kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1916,7 +1957,8 @@ ph_data_indication(struct layer2 *l2, struct mISDNhead *hh, struct sk_buff *skb)
|
|||
} else
|
||||
c = 'L';
|
||||
if (c) {
|
||||
printk(KERN_WARNING "l2 D-channel frame error %c\n", c);
|
||||
printk(KERN_WARNING "%s:l2 D-channel frame error %c\n",
|
||||
mISDNDevName4ch(&l2->ch), c);
|
||||
mISDN_FsmEvent(&l2->l2m, EV_L2_FRAME_ERROR, (void *)(long)c);
|
||||
}
|
||||
return ret;
|
||||
|
@ -1930,8 +1972,17 @@ l2_send(struct mISDNchannel *ch, struct sk_buff *skb)
|
|||
int ret = -EINVAL;
|
||||
|
||||
if (*debug & DEBUG_L2_RECV)
|
||||
printk(KERN_DEBUG "%s: prim(%x) id(%x) sapi(%d) tei(%d)\n",
|
||||
__func__, hh->prim, hh->id, l2->sapi, l2->tei);
|
||||
printk(KERN_DEBUG "%s: %s prim(%x) id(%x) sapi(%d) tei(%d)\n",
|
||||
__func__, mISDNDevName4ch(&l2->ch), hh->prim, hh->id,
|
||||
l2->sapi, l2->tei);
|
||||
if (hh->prim == DL_INTERN_MSG) {
|
||||
struct mISDNhead *chh = hh + 1; /* saved copy */
|
||||
|
||||
*hh = *chh;
|
||||
if (*debug & DEBUG_L2_RECV)
|
||||
printk(KERN_DEBUG "%s: prim(%x) id(%x) internal msg\n",
|
||||
mISDNDevName4ch(&l2->ch), hh->prim, hh->id);
|
||||
}
|
||||
switch (hh->prim) {
|
||||
case PH_DATA_IND:
|
||||
ret = ph_data_indication(l2, hh, skb);
|
||||
|
@ -1987,6 +2038,12 @@ l2_send(struct mISDNchannel *ch, struct sk_buff *skb)
|
|||
ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DL_RELEASE_REQ,
|
||||
skb);
|
||||
break;
|
||||
case DL_TIMER200_IND:
|
||||
mISDN_FsmEvent(&l2->l2m, EV_L2_T200I, NULL);
|
||||
break;
|
||||
case DL_TIMER203_IND:
|
||||
mISDN_FsmEvent(&l2->l2m, EV_L2_T203I, NULL);
|
||||
break;
|
||||
default:
|
||||
if (*debug & DEBUG_L2)
|
||||
l2m_debug(&l2->l2m, "l2 unknown pr %04x",
|
||||
|
@ -2005,7 +2062,8 @@ tei_l2(struct layer2 *l2, u_int cmd, u_long arg)
|
|||
int ret = -EINVAL;
|
||||
|
||||
if (*debug & DEBUG_L2_TEI)
|
||||
printk(KERN_DEBUG "%s: cmd(%x)\n", __func__, cmd);
|
||||
printk(KERN_DEBUG "%s: cmd(%x) in %s\n",
|
||||
mISDNDevName4ch(&l2->ch), cmd, __func__);
|
||||
switch (cmd) {
|
||||
case (MDL_ASSIGN_REQ):
|
||||
ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_ASSIGN, (void *)arg);
|
||||
|
@ -2018,7 +2076,8 @@ tei_l2(struct layer2 *l2, u_int cmd, u_long arg)
|
|||
break;
|
||||
case (MDL_ERROR_RSP):
|
||||
/* ETS 300-125 5.3.2.1 Test: TC13010 */
|
||||
printk(KERN_NOTICE "MDL_ERROR|REQ (tei_l2)\n");
|
||||
printk(KERN_NOTICE "%s: MDL_ERROR|REQ (tei_l2)\n",
|
||||
mISDNDevName4ch(&l2->ch));
|
||||
ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_ERROR, NULL);
|
||||
break;
|
||||
}
|
||||
|
@ -2050,7 +2109,8 @@ l2_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
|
|||
u_int info;
|
||||
|
||||
if (*debug & DEBUG_L2_CTRL)
|
||||
printk(KERN_DEBUG "%s:(%x)\n", __func__, cmd);
|
||||
printk(KERN_DEBUG "%s: %s cmd(%x)\n",
|
||||
mISDNDevName4ch(ch), __func__, cmd);
|
||||
|
||||
switch (cmd) {
|
||||
case OPEN_CHANNEL:
|
||||
|
|
|
@ -790,18 +790,23 @@ tei_ph_data_ind(struct teimgr *tm, u_int mt, u_char *dp, int len)
|
|||
static struct layer2 *
|
||||
create_new_tei(struct manager *mgr, int tei, int sapi)
|
||||
{
|
||||
u_long opt = 0;
|
||||
u_long flags;
|
||||
int id;
|
||||
struct layer2 *l2;
|
||||
unsigned long opt = 0;
|
||||
unsigned long flags;
|
||||
int id;
|
||||
struct layer2 *l2;
|
||||
struct channel_req rq;
|
||||
|
||||
if (!mgr->up)
|
||||
return NULL;
|
||||
if ((tei >= 0) && (tei < 64))
|
||||
test_and_set_bit(OPTION_L2_FIXEDTEI, &opt);
|
||||
if (mgr->ch.st->dev->Dprotocols
|
||||
& ((1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1)))
|
||||
if (mgr->ch.st->dev->Dprotocols & ((1 << ISDN_P_TE_E1) |
|
||||
(1 << ISDN_P_NT_E1))) {
|
||||
test_and_set_bit(OPTION_L2_PMX, &opt);
|
||||
rq.protocol = ISDN_P_NT_E1;
|
||||
} else {
|
||||
rq.protocol = ISDN_P_NT_S0;
|
||||
}
|
||||
l2 = create_l2(mgr->up, ISDN_P_LAPD_NT, opt, tei, sapi);
|
||||
if (!l2) {
|
||||
printk(KERN_WARNING "%s:no memory for layer2\n", __func__);
|
||||
|
@ -836,6 +841,14 @@ create_new_tei(struct manager *mgr, int tei, int sapi)
|
|||
l2->ch.recv = mgr->ch.recv;
|
||||
l2->ch.peer = mgr->ch.peer;
|
||||
l2->ch.ctrl(&l2->ch, OPEN_CHANNEL, NULL);
|
||||
/* We need open here L1 for the manager as well (refcounting) */
|
||||
rq.adr.dev = mgr->ch.st->dev->id;
|
||||
id = mgr->ch.st->own.ctrl(&mgr->ch.st->own, OPEN_CHANNEL, &rq);
|
||||
if (id < 0) {
|
||||
printk(KERN_WARNING "%s: cannot open L1\n", __func__);
|
||||
l2->ch.ctrl(&l2->ch, CLOSE_CHANNEL, NULL);
|
||||
l2 = NULL;
|
||||
}
|
||||
}
|
||||
return l2;
|
||||
}
|
||||
|
@ -978,10 +991,11 @@ TEIrelease(struct layer2 *l2)
|
|||
static int
|
||||
create_teimgr(struct manager *mgr, struct channel_req *crq)
|
||||
{
|
||||
struct layer2 *l2;
|
||||
u_long opt = 0;
|
||||
u_long flags;
|
||||
int id;
|
||||
struct layer2 *l2;
|
||||
unsigned long opt = 0;
|
||||
unsigned long flags;
|
||||
int id;
|
||||
struct channel_req l1rq;
|
||||
|
||||
if (*debug & DEBUG_L2_TEI)
|
||||
printk(KERN_DEBUG "%s: %s proto(%x) adr(%d %d %d %d)\n",
|
||||
|
@ -1016,6 +1030,7 @@ create_teimgr(struct manager *mgr, struct channel_req *crq)
|
|||
if (crq->protocol == ISDN_P_LAPD_TE)
|
||||
test_and_set_bit(MGR_OPT_USER, &mgr->options);
|
||||
}
|
||||
l1rq.adr = crq->adr;
|
||||
if (mgr->ch.st->dev->Dprotocols
|
||||
& ((1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1)))
|
||||
test_and_set_bit(OPTION_L2_PMX, &opt);
|
||||
|
@ -1023,6 +1038,8 @@ create_teimgr(struct manager *mgr, struct channel_req *crq)
|
|||
mgr->up = crq->ch;
|
||||
id = DL_INFO_L2_CONNECT;
|
||||
teiup_create(mgr, DL_INFORMATION_IND, sizeof(id), &id);
|
||||
if (test_bit(MGR_PH_ACTIVE, &mgr->options))
|
||||
teiup_create(mgr, PH_ACTIVATE_IND, 0, NULL);
|
||||
crq->ch = NULL;
|
||||
if (!list_empty(&mgr->layer2)) {
|
||||
read_lock_irqsave(&mgr->lock, flags);
|
||||
|
@ -1053,24 +1070,34 @@ create_teimgr(struct manager *mgr, struct channel_req *crq)
|
|||
l2->tm->tei_m.fsm = &teifsmu;
|
||||
l2->tm->tei_m.state = ST_TEI_NOP;
|
||||
l2->tm->tval = 1000; /* T201 1 sec */
|
||||
if (test_bit(OPTION_L2_PMX, &opt))
|
||||
l1rq.protocol = ISDN_P_TE_E1;
|
||||
else
|
||||
l1rq.protocol = ISDN_P_TE_S0;
|
||||
} else {
|
||||
l2->tm->tei_m.fsm = &teifsmn;
|
||||
l2->tm->tei_m.state = ST_TEI_NOP;
|
||||
l2->tm->tval = 2000; /* T202 2 sec */
|
||||
if (test_bit(OPTION_L2_PMX, &opt))
|
||||
l1rq.protocol = ISDN_P_NT_E1;
|
||||
else
|
||||
l1rq.protocol = ISDN_P_NT_S0;
|
||||
}
|
||||
mISDN_FsmInitTimer(&l2->tm->tei_m, &l2->tm->timer);
|
||||
write_lock_irqsave(&mgr->lock, flags);
|
||||
id = get_free_id(mgr);
|
||||
list_add_tail(&l2->list, &mgr->layer2);
|
||||
write_unlock_irqrestore(&mgr->lock, flags);
|
||||
if (id < 0) {
|
||||
l2->ch.ctrl(&l2->ch, CLOSE_CHANNEL, NULL);
|
||||
} else {
|
||||
if (id >= 0) {
|
||||
l2->ch.nr = id;
|
||||
l2->up->nr = id;
|
||||
crq->ch = &l2->ch;
|
||||
id = 0;
|
||||
/* We need open here L1 for the manager as well (refcounting) */
|
||||
id = mgr->ch.st->own.ctrl(&mgr->ch.st->own, OPEN_CHANNEL,
|
||||
&l1rq);
|
||||
}
|
||||
if (id < 0)
|
||||
l2->ch.ctrl(&l2->ch, CLOSE_CHANNEL, NULL);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
@ -1096,12 +1123,16 @@ mgr_send(struct mISDNchannel *ch, struct sk_buff *skb)
|
|||
break;
|
||||
case PH_ACTIVATE_IND:
|
||||
test_and_set_bit(MGR_PH_ACTIVE, &mgr->options);
|
||||
if (mgr->up)
|
||||
teiup_create(mgr, PH_ACTIVATE_IND, 0, NULL);
|
||||
mISDN_FsmEvent(&mgr->deact, EV_ACTIVATE_IND, NULL);
|
||||
do_send(mgr);
|
||||
ret = 0;
|
||||
break;
|
||||
case PH_DEACTIVATE_IND:
|
||||
test_and_clear_bit(MGR_PH_ACTIVE, &mgr->options);
|
||||
if (mgr->up)
|
||||
teiup_create(mgr, PH_DEACTIVATE_IND, 0, NULL);
|
||||
mISDN_FsmEvent(&mgr->deact, EV_DEACTIVATE_IND, NULL);
|
||||
ret = 0;
|
||||
break;
|
||||
|
@ -1263,7 +1294,7 @@ static int
|
|||
mgr_bcast(struct mISDNchannel *ch, struct sk_buff *skb)
|
||||
{
|
||||
struct manager *mgr = container_of(ch, struct manager, bcast);
|
||||
struct mISDNhead *hh = mISDN_HEAD_P(skb);
|
||||
struct mISDNhead *hhc, *hh = mISDN_HEAD_P(skb);
|
||||
struct sk_buff *cskb = NULL;
|
||||
struct layer2 *l2;
|
||||
u_long flags;
|
||||
|
@ -1278,10 +1309,17 @@ mgr_bcast(struct mISDNchannel *ch, struct sk_buff *skb)
|
|||
skb = NULL;
|
||||
} else {
|
||||
if (!cskb)
|
||||
cskb = skb_copy(skb, GFP_KERNEL);
|
||||
cskb = skb_copy(skb, GFP_ATOMIC);
|
||||
}
|
||||
if (cskb) {
|
||||
ret = l2->ch.send(&l2->ch, cskb);
|
||||
hhc = mISDN_HEAD_P(cskb);
|
||||
/* save original header behind normal header */
|
||||
hhc++;
|
||||
*hhc = *hh;
|
||||
hhc--;
|
||||
hhc->prim = DL_INTERN_MSG;
|
||||
hhc->id = l2->ch.nr;
|
||||
ret = ch->st->own.recv(&ch->st->own, cskb);
|
||||
if (ret) {
|
||||
if (*debug & DEBUG_SEND_ERR)
|
||||
printk(KERN_DEBUG
|
||||
|
|
|
@ -69,7 +69,6 @@
|
|||
#include <linux/spinlock.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/delay.h>
|
||||
// #include <linux/trdevice.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/io.h>
|
||||
|
|
|
@ -66,10 +66,7 @@ config DUMMY
|
|||
<http://www.tldp.org/docs.html#guide>.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called dummy. If you want to use more than one dummy
|
||||
device at a time, you need to compile this driver as a module.
|
||||
Instead of 'dummy', the devices will then be called 'dummy0',
|
||||
'dummy1' etc.
|
||||
will be called dummy.
|
||||
|
||||
config EQUALIZER
|
||||
tristate "EQL (serial line load balancing) support"
|
||||
|
@ -285,8 +282,6 @@ source "drivers/net/slip/Kconfig"
|
|||
|
||||
source "drivers/s390/net/Kconfig"
|
||||
|
||||
source "drivers/net/tokenring/Kconfig"
|
||||
|
||||
source "drivers/net/usb/Kconfig"
|
||||
|
||||
source "drivers/net/wireless/Kconfig"
|
||||
|
|
|
@ -50,7 +50,6 @@ obj-$(CONFIG_SLIP) += slip/
|
|||
obj-$(CONFIG_SLHC) += slip/
|
||||
obj-$(CONFIG_NET_SB1000) += sb1000.o
|
||||
obj-$(CONFIG_SUNGEM_PHY) += sungem_phy.o
|
||||
obj-$(CONFIG_TR) += tokenring/
|
||||
obj-$(CONFIG_WAN) += wan/
|
||||
obj-$(CONFIG_WLAN) += wireless/
|
||||
obj-$(CONFIG_WIMAX) += wimax/
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue