Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next

Pull networking updates from Davic Miller:

 1) Support busy polling generically, for all NAPI drivers.  From Eric
    Dumazet.

 2) Add byte/packet counter support to nft_ct, from Floriani Westphal.

 3) Add RSS/XPS support to mvneta driver, from Gregory Clement.

 4) Implement IPV6_HDRINCL socket option for raw sockets, from Hannes
    Frederic Sowa.

 5) Add support for T6 adapter to cxgb4 driver, from Hariprasad Shenai.

 6) Add support for VLAN device bridging to mlxsw switch driver, from
    Ido Schimmel.

 7) Add driver for Netronome NFP4000/NFP6000, from Jakub Kicinski.

 8) Provide hwmon interface to mlxsw switch driver, from Jiri Pirko.

 9) Reorganize wireless drivers into per-vendor directories just like we
    do for ethernet drivers.  From Kalle Valo.

10) Provide a way for administrators "destroy" connected sockets via the
    SOCK_DESTROY socket netlink diag operation.  From Lorenzo Colitti.

11) Add support to add/remove multicast routes via netlink, from Nikolay
    Aleksandrov.

12) Make TCP keepalive settings per-namespace, from Nikolay Borisov.

13) Add forwarding and packet duplication facilities to nf_tables, from
    Pablo Neira Ayuso.

14) Dead route support in MPLS, from Roopa Prabhu.

15) TSO support for thunderx chips, from Sunil Goutham.

16) Add driver for IBM's System i/p VNIC protocol, from Thomas Falcon.

17) Rationalize, consolidate, and more completely document the checksum
    offloading facilities in the networking stack.  From Tom Herbert.

18) Support aborting an ongoing scan in mac80211/cfg80211, from
    Vidyullatha Kanchanapally.

19) Use per-bucket spinlock for bpf hash facility, from Tom Leiming.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1375 commits)
  net: bnxt: always return values from _bnxt_get_max_rings
  net: bpf: reject invalid shifts
  phonet: properly unshare skbs in phonet_rcv()
  dwc_eth_qos: Fix dma address for multi-fragment skbs
  phy: remove an unneeded condition
  mdio: remove an unneed condition
  mdio_bus: NULL dereference on allocation error
  net: Fix typo in netdev_intersect_features
  net: freescale: mac-fec: Fix build error from phy_device API change
  net: freescale: ucc_geth: Fix build error from phy_device API change
  bonding: Prevent IPv6 link local address on enslaved devices
  IB/mlx5: Add flow steering support
  net/mlx5_core: Export flow steering API
  net/mlx5_core: Make ipv4/ipv6 location more clear
  net/mlx5_core: Enable flow steering support for the IB driver
  net/mlx5_core: Initialize namespaces only when supported by device
  net/mlx5_core: Set priority attributes
  net/mlx5_core: Connect flow tables
  net/mlx5_core: Introduce modify flow table command
  net/mlx5_core: Managing root flow table
  ...
This commit is contained in:
Linus Torvalds 2016-01-12 18:57:02 -08:00
commit aee3bfa330
1739 changed files with 70703 additions and 25560 deletions

View File

@ -19,6 +19,25 @@ Description:
Set to 0 to pad all frames. Set greater than tx_max to
disable all padding.
What: /sys/class/net/<iface>/cdc_ncm/ndp_to_end
Date: Dec 2015
KernelVersion: 4.5
Contact: Bjørn Mork <bjorn@mork.no>
Description:
Boolean attribute showing the status of the "NDP to
end" quirk. Defaults to 'N', except for devices
already known to need it enabled.
The "NDP to end" quirk makes the driver place the NDP
(the packet index table) after the payload. The NCM
specification does not mandate this, but some devices
are known to be more restrictive. Write 'Y' to this
attribute for temporary testing of a suspect device
failing to work with the default driver settings.
A device entry should be added to the driver if this
quirk is found to be required.
What: /sys/class/net/<iface>/cdc_ncm/rx_max
Date: May 2014
KernelVersion: 3.16

View File

@ -8,7 +8,7 @@ Description:
What: /sys/class/net/<mesh_iface>/mesh/<vlan_subdir>/ap_isolation
Date: May 2011
Contact: Antonio Quartulli <antonio@meshcoding.com>
Contact: Antonio Quartulli <a@unstable.cc>
Description:
Indicates whether the data traffic going from a
wireless client to another wireless client will be
@ -70,7 +70,7 @@ Description:
What: /sys/class/net/<mesh_iface>/mesh/isolation_mark
Date: Nov 2013
Contact: Antonio Quartulli <antonio@meshcoding.com>
Contact: Antonio Quartulli <a@unstable.cc>
Description:
Defines the isolation mark (and its bitmask) which
is used to classify clients as "isolated" by the

View File

@ -0,0 +1,23 @@
What: /sys/class/net/<iface>/qmi/raw_ip
Date: Dec 2015
KernelVersion: 4.4
Contact: Bjørn Mork <bjorn@mork.no>
Description:
Boolean. Default: 'N'
Set this to 'Y' to change the network device link
framing from '802.3' to 'raw-ip'.
The netdev will change to reflect the link framing
mode. The netdev is an ordinary ethernet device in
'802.3' mode, and the driver expects to exchange
frames with an ethernet header over the USB link. The
netdev is a headerless p-t-p device in 'raw-ip' mode,
and the driver expects to echange IPv4 or IPv6 packets
without any L2 header over the USB link.
Userspace is in full control of firmware configuration
through the delegation of the QMI protocol. Userspace
is responsible for coordination of driver and firmware
link framing mode, changing this setting to 'Y' if the
firmware is configured for 'raw-ip' mode.

View File

@ -31,6 +31,8 @@ A switch child node has the following optional property:
switch. Must be set if the switch can not detect
the presence and/or size of a connected EEPROM,
otherwise optional.
- reset-gpios : phandle and specifier to a gpio line connected to
reset pin of the switch chip.
A switch may have multiple "port" children nodes
@ -114,6 +116,7 @@ Example:
#size-cells = <0>;
reg = <17 1>; /* MDIO address 17, switch 1 in tree */
mii-bus = <&mii_bus1>;
reset-gpios = <&gpio5 1 GPIO_ACTIVE_LOW>;
switch1port0: port@0 {
reg = <0>;

View File

@ -1,7 +1,12 @@
Hisilicon MDIO bus controller
Properties:
- compatible: "hisilicon,mdio","hisilicon,hns-mdio".
- compatible: can be one of:
"hisilicon,hns-mdio"
"hisilicon,mdio"
"hisilicon,hns-mdio" is recommended to be used for hip05 and later SOCs,
while "hisilicon,mdio" is optional for backwards compatibility only on
hip04 Soc.
- reg: The base address of the MDIO bus controller register bank.
- #address-cells: Must be <1>.
- #size-cells: Must be <0>. MDIO addresses have no size component.

View File

@ -0,0 +1,18 @@
* ADF7242 IEEE 802.15.4 *
Required properties:
- compatible: should be "adi,adf7242"
- spi-max-frequency: maximal bus speed (12.5 MHz)
- reg: the chipselect index
- interrupts: the interrupt generated by the device via pin IRQ1.
IRQ_TYPE_LEVEL_HIGH (4) or IRQ_TYPE_EDGE_FALLING (1)
Example:
adf7242@0 {
compatible = "adi,adf7242";
spi-max-frequency = <10000000>;
reg = <0>;
interrupts = <98 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&gpio3>;
};

View File

@ -4,6 +4,7 @@ Required properties:
- compatible: Should be "cdns,[<chip>-]{macb|gem}"
Use "cdns,at91sam9260-macb" for Atmel at91sam9 SoCs or the 10/100Mbit IP
available on sama5d3 SoCs.
Use "cdns,np4-macb" for NP4 SoC devices.
Use "cdns,at32ap7000-macb" for other 10/100 usage or use the generic form: "cdns,macb".
Use "cdns,pc302-gem" for Picochip picoXcell pc302 and later devices based on
the Cadence GEM, or the generic form: "cdns,gem".
@ -19,6 +20,9 @@ Required properties:
Optional elements: 'tx_clk'
- clocks: Phandles to input clocks.
Optional properties for PHY child node:
- reset-gpios : Should specify the gpio for phy reset
Examples:
macb0: ethernet@fffc4000 {
@ -29,4 +33,8 @@ Examples:
local-mac-address = [3a 0e 03 04 05 06];
clock-names = "pclk", "hclk", "tx_clk";
clocks = <&clkc 30>, <&clkc 30>, <&clkc 13>;
ethernet-phy@1 {
reg = <0x1>;
reset-gpios = <&pioE 6 1>;
};
};

View File

@ -1,8 +1,9 @@
Micrel KSZ9021/KSZ9031 Gigabit Ethernet PHY
Some boards require special tuning values, particularly when it comes to
clock delays. You can specify clock delay values by adding
micrel-specific properties to an Ethernet OF device node.
Some boards require special tuning values, particularly when it comes
to clock delays. You can specify clock delay values in the PHY OF
device node. Deprecated, but still supported, these properties can
also be added to an Ethernet OF device node.
Note that these settings are applied after any phy-specific fixup from
phy_fixup_list (see phy_init_hw() from drivers/net/phy/phy_device.c),
@ -57,16 +58,6 @@ KSZ9031:
Examples:
/* Attach to an Ethernet device with autodetected PHY */
&enet {
rxc-skew-ps = <3000>;
rxdv-skew-ps = <0>;
txc-skew-ps = <3000>;
txen-skew-ps = <0>;
status = "okay";
};
/* Attach to an explicitly-specified PHY */
mdio {
phy0: ethernet-phy@0 {
rxc-skew-ps = <3000>;

View File

@ -0,0 +1,50 @@
* STMicroelectronics : NFC Transceiver ST95HF
ST NFC Transceiver is required to attach with SPI bus.
ST95HF node should be defined in DT as SPI slave device of SPI
master with which ST95HF transceiver is physically connected.
The properties defined below are required to be the part of DT
to include ST95HF transceiver into the platform.
Required properties:
===================
- reg: Address of SPI slave "ST95HF transceiver" on SPI master bus.
- compatible: should be "st,st95hf" for ST95HF NFC transceiver
- spi-max-frequency: Max. operating SPI frequency for ST95HF
transceiver.
- enable-gpio: GPIO line to enable ST95HF transceiver.
- interrupt-parent : Standard way to specify the controller to which
ST95HF transceiver's interrupt is routed.
- interrupts : Standard way to define ST95HF transceiver's out
interrupt.
Optional property:
=================
- st95hfvin-supply : This is an optional property. It contains a
phandle to ST95HF transceiver's regulator supply node in DT.
Example:
=======
spi@9840000 {
reg = <0x9840000 0x110>;
#address-cells = <1>;
#size-cells = <0>;
cs-gpios = <&pio0 4>;
status = "okay";
st95hf@0{
reg = <0>;
compatible = "st,st95hf";
status = "okay";
spi-max-frequency = <1000000>;
enable-gpio = <&pio4 0>;
interrupt-parent = <&pio0>;
interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
};
};

View File

@ -5,8 +5,18 @@ interface contains.
Required properties:
- compatible: "renesas,etheravb-r8a7790" if the device is a part of R8A7790 SoC.
"renesas,etheravb-r8a7791" if the device is a part of R8A7791 SoC.
"renesas,etheravb-r8a7792" if the device is a part of R8A7792 SoC.
"renesas,etheravb-r8a7793" if the device is a part of R8A7793 SoC.
"renesas,etheravb-r8a7794" if the device is a part of R8A7794 SoC.
"renesas,etheravb-r8a7795" if the device is a part of R8A7795 SoC.
"renesas,etheravb-rcar-gen2" for generic R-Car Gen 2 compatible interface.
"renesas,etheravb-rcar-gen3" for generic R-Car Gen 3 compatible interface.
When compatible with the generic version, nodes must list the
SoC-specific version corresponding to the platform first
followed by the generic version.
- reg: offset and length of (1) the register block and (2) the stream buffer.
- interrupts: A list of interrupt-specifiers, one for each entry in
interrupt-names.
@ -37,7 +47,7 @@ Optional properties:
Example:
ethernet@e6800000 {
compatible = "renesas,etheravb-r8a7795";
compatible = "renesas,etheravb-r8a7795", "renesas,etheravb-rcar-gen3";
reg = <0 0xe6800000 0 0x800>, <0 0xe6a00000 0 0x10000>;
interrupt-parent = <&gic>;
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,

View File

@ -11,6 +11,8 @@ Required properties:
designware version numbers documented in stmmac.txt
- altr,sysmgr-syscon : Should be the phandle to the system manager node that
encompasses the glue register, the register offset, and the register shift.
- altr,f2h_ptp_ref_clk use f2h_ptp_ref_clk instead of default eosc1 clock
for ptp ref clk. This affects all emacs as the clock is common.
Optional properties:
altr,emac-splitter: Should be the phandle to the emac splitter soft IP node if

View File

@ -35,18 +35,18 @@ Optional properties:
- reset-names: Should contain the reset signal name "stmmaceth", if a
reset phandle is given
- max-frame-size: See ethernet.txt file in the same directory
- clocks: If present, the first clock should be the GMAC main clock and
the second clock should be peripheral's register interface clock. Further
clocks may be specified in derived bindings.
- clock-names: One name for each entry in the clocks property, the
first one should be "stmmaceth" and the second one should be "pclk".
- clk_ptp_ref: this is the PTP reference clock; in case of the PTP is
available this clock is used for programming the Timestamp Addend Register.
If not passed then the system clock will be used and this is fine on some
platforms.
- clocks: If present, the first clock should be the GMAC main clock
The optional second clock should be peripheral's register interface clock.
The third optional clock should be the ptp reference clock.
Further clocks may be specified in derived bindings.
- clock-names: One name for each entry in the clocks property.
The first one should be "stmmaceth".
The optional second one should be "pclk".
The optional third one should be "clk_ptp_ref".
- snps,burst_len: The AXI burst lenth value of the AXI BUS MODE register.
- tx-fifo-depth: See ethernet.txt file in the same directory
- rx-fifo-depth: See ethernet.txt file in the same directory
- mdio: with compatible = "snps,dwmac-mdio", create and register mdio bus.
Examples:
@ -65,4 +65,11 @@ Examples:
tx-fifo-depth = <16384>;
clocks = <&clock>;
clock-names = "stmmaceth";
mdio0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "snps,dwmac-mdio";
phy1: ethernet-phy@0 {
};
};
};

View File

@ -10,6 +10,7 @@ modules that can be used to test the following notifiers.
* PM notifier
* Memory hotplug notifier
* powerpc pSeries reconfig notifier
* Netdevice notifier
CPU notifier error injection module
-----------------------------------
@ -87,6 +88,30 @@ Possible pSeries reconfig notifier events to be failed are:
* PSERIES_DRCONF_MEM_ADD
* PSERIES_DRCONF_MEM_REMOVE
Netdevice notifier error injection module
----------------------------------------------
This feature is controlled through debugfs interface
/sys/kernel/debug/notifier-error-inject/netdev/actions/<notifier event>/error
Netdevice notifier events which can be failed are:
* NETDEV_REGISTER
* NETDEV_CHANGEMTU
* NETDEV_CHANGENAME
* NETDEV_PRE_UP
* NETDEV_PRE_TYPE_CHANGE
* NETDEV_POST_INIT
* NETDEV_PRECHANGEMTU
* NETDEV_PRECHANGEUPPER
* NETDEV_CHANGEUPPER
Example: Inject netdevice mtu change error (-22 == -EINVAL)
# cd /sys/kernel/debug/notifier-error-inject/netdev
# echo -22 > actions/NETDEV_CHANGEMTU/error
# ip link set eth0 mtu 1024
RTNETLINK answers: Invalid argument
For more usage examples
-----------------------
There are tools/testing/selftests using the notifier error injection features

View File

@ -115,14 +115,17 @@ The "bat0" interface can be used like any other regular inter-
face. It needs an IP address which can be either statically con-
figured or dynamically (by using DHCP or similar services):
# NodeA: ifconfig bat0 192.168.0.1
# NodeB: ifconfig bat0 192.168.0.2
# NodeA: ip link set up dev bat0
# NodeA: ip addr add 192.168.0.1/24 dev bat0
# NodeB: ip link set up dev bat0
# NodeB: ip addr add 192.168.0.2/24 dev bat0
# NodeB: ping 192.168.0.1
Note: In order to avoid problems remove all IP addresses previ-
ously assigned to interfaces now used by batman advanced, e.g.
# ifconfig eth0 0.0.0.0
# ip addr flush dev eth0
LOGGING/DEBUGGING

View File

@ -335,6 +335,14 @@ tcp_keepalive_intvl - INTEGER
after probes started. Default value: 75sec i.e. connection
will be aborted after ~11 minutes of retries.
tcp_l3mdev_accept - BOOLEAN
Enables child sockets to inherit the L3 master device index.
Enabling this option allows a "global" listen socket to work
across L3 master domains (e.g., VRFs) with connected sockets
derived from the listen socket to be bound to the L3 domain in
which the packets originated. Only valid when the kernel was
compiled with CONFIG_NET_L3_MASTER_DEV.
tcp_low_latency - BOOLEAN
If set, the TCP stack makes decisions that prefer lower
latency as opposed to higher throughput. By default, this
@ -1723,6 +1731,25 @@ addip_enable - BOOLEAN
Default: 0
pf_enable - INTEGER
Enable or disable pf (pf is short for potentially failed) state. A value
of pf_retrans > path_max_retrans also disables pf state. That is, one of
both pf_enable and pf_retrans > path_max_retrans can disable pf state.
Since pf_retrans and path_max_retrans can be changed by userspace
application, sometimes user expects to disable pf state by the value of
pf_retrans > path_max_retrans, but occasionally the value of pf_retrans
or path_max_retrans is changed by the user application, this pf state is
enabled. As such, it is necessary to add this to dynamically enable
and disable pf state. See:
https://datatracker.ietf.org/doc/draft-ietf-tsvwg-sctp-failover for
details.
1: Enable pf.
0: Disable pf.
Default: 1
addip_noauth_enable - BOOLEAN
Dynamic Address Reconfiguration (ADD-IP) requires the use of
authentication to protect the operations of adding or removing new
@ -1799,7 +1826,9 @@ pf_retrans - INTEGER
having to reduce path_max_retrans to a very low value. See:
http://www.ietf.org/id/draft-nishida-tsvwg-sctp-failover-05.txt
for details. Note also that a value of pf_retrans > path_max_retrans
disables this feature
disables this feature. Since both pf_retrans and path_max_retrans can
be changed by userspace application, a variable pf_enable is used to
disable pf state.
Default: 0

View File

@ -304,8 +304,12 @@ certain netdevs from flooding unicast traffic for which there is no FDB entry.
IGMP Snooping
^^^^^^^^^^^^^
XXX: complete this section
In order to support IGMP snooping, the port netdevs should trap to the bridge
driver all IGMP join and leave messages.
The bridge multicast module will notify port netdevs on every multicast group
changed whether it is static configured or dynamically joined/leave.
The hardware implementation should be forwarding all registered multicast
traffic groups only to the configured ports.
L3 Routing Offload
------------------

View File

@ -371,6 +371,15 @@ ADDRESS SPACE LAYOUT RANDOMIZATION (ASLR)
M: Jiri Kosina <jikos@kernel.org>
S: Maintained
ADF7242 IEEE 802.15.4 RADIO DRIVER
M: Michael Hennerich <michael.hennerich@analog.com>
W: https://wiki.analog.com/ADF7242
W: http://ez.analog.com/community/linux-device-drivers
L: linux-wpan@vger.kernel.org
S: Supported
F: drivers/net/ieee802154/adf7242.c
F: Documentation/devicetree/bindings/net/ieee802154/adf7242.txt
ADM1025 HARDWARE MONITOR DRIVER
M: Jean Delvare <jdelvare@suse.com>
L: lm-sensors@lm-sensors.org
@ -388,7 +397,7 @@ ADM8211 WIRELESS DRIVER
L: linux-wireless@vger.kernel.org
W: http://wireless.kernel.org/
S: Orphan
F: drivers/net/wireless/adm8211.*
F: drivers/net/wireless/admtek/adm8211.*
ADP1653 FLASH CONTROLLER DRIVER
M: Sakari Ailus <sakari.ailus@iki.fi>
@ -1992,7 +2001,7 @@ L: linux-wireless@vger.kernel.org
W: http://www.thekelleys.org.uk/atmel
W: http://atmelwlandriver.sourceforge.net/
S: Maintained
F: drivers/net/wireless/atmel*
F: drivers/net/wireless/atmel/atmel*
ATMEL MAXTOUCH DRIVER
M: Nick Dyer <nick.dyer@itdev.co.uk>
@ -2081,7 +2090,7 @@ L: linux-wireless@vger.kernel.org
L: b43-dev@lists.infradead.org
W: http://wireless.kernel.org/en/users/Drivers/b43
S: Odd Fixes
F: drivers/net/wireless/b43/
F: drivers/net/wireless/broadcom/b43/
B43LEGACY WIRELESS DRIVER
M: Larry Finger <Larry.Finger@lwfinger.net>
@ -2089,7 +2098,7 @@ L: linux-wireless@vger.kernel.org
L: b43-dev@lists.infradead.org
W: http://wireless.kernel.org/en/users/Drivers/b43
S: Maintained
F: drivers/net/wireless/b43legacy/
F: drivers/net/wireless/broadcom/b43legacy/
BACKLIGHT CLASS/SUBSYSTEM
M: Jingoo Han <jingoohan1@gmail.com>
@ -2101,7 +2110,7 @@ F: include/linux/backlight.h
BATMAN ADVANCED
M: Marek Lindner <mareklindner@neomailbox.ch>
M: Simon Wunderlich <sw@simonwunderlich.de>
M: Antonio Quartulli <antonio@meshcoding.com>
M: Antonio Quartulli <a@unstable.cc>
L: b.a.t.m.a.n@lists.open-mesh.org
W: http://www.open-mesh.org/
S: Maintained
@ -2391,7 +2400,7 @@ M: Hante Meuleman <meuleman@broadcom.com>
L: linux-wireless@vger.kernel.org
L: brcm80211-dev-list@broadcom.com
S: Supported
F: drivers/net/wireless/brcm80211/
F: drivers/net/wireless/broadcom/brcm80211/
BROADCOM BNX2FC 10 GIGABIT FCOE DRIVER
M: QLogic-Storage-Upstream@qlogic.com
@ -3113,7 +3122,7 @@ F: sound/pci/cs5535audio/
CW1200 WLAN driver
M: Solomon Peachy <pizza@shaftnet.org>
S: Maintained
F: drivers/net/wireless/cw1200/
F: drivers/net/wireless/st/cw1200/
CX18 VIDEO4LINUX DRIVER
M: Andy Walls <awalls@md.metrocast.net>
@ -5035,7 +5044,7 @@ L: hostap@shmoo.com (subscribers-only)
L: linux-wireless@vger.kernel.org
W: http://hostap.epitest.fi/
S: Maintained
F: drivers/net/wireless/hostap/
F: drivers/net/wireless/intersil/hostap/
HP COMPAQ TC1100 TABLET WMI EXTRAS DRIVER
L: platform-driver-x86@vger.kernel.org
@ -5273,6 +5282,13 @@ L: netdev@vger.kernel.org
S: Supported
F: drivers/net/ethernet/ibm/ibmveth.*
IBM Power SRIOV Virtual NIC Device Driver
M: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
M: John Allen <jallen@linux.vnet.ibm.com>
L: netdev@vger.kernel.org
S: Supported
F: drivers/net/ethernet/ibm/ibmvnic.*
IBM Power Virtual SCSI Device Drivers
M: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>
L: linux-scsi@vger.kernel.org
@ -5603,7 +5619,7 @@ L: linux-wireless@vger.kernel.org
S: Maintained
F: Documentation/networking/README.ipw2100
F: Documentation/networking/README.ipw2200
F: drivers/net/wireless/ipw2x00/
F: drivers/net/wireless/intel/ipw2x00/
INTEL(R) TRACE HUB
M: Alexander Shishkin <alexander.shishkin@linux.intel.com>
@ -5635,7 +5651,7 @@ INTEL WIRELESS 3945ABG/BG, 4965AGN (iwlegacy)
M: Stanislaw Gruszka <sgruszka@redhat.com>
L: linux-wireless@vger.kernel.org
S: Supported
F: drivers/net/wireless/iwlegacy/
F: drivers/net/wireless/intel/iwlegacy/
INTEL WIRELESS WIFI LINK (iwlwifi)
M: Johannes Berg <johannes.berg@intel.com>
@ -5645,7 +5661,7 @@ L: linux-wireless@vger.kernel.org
W: http://intellinuxwireless.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi.git
S: Supported
F: drivers/net/wireless/iwlwifi/
F: drivers/net/wireless/intel/iwlwifi/
INTEL MANAGEMENT ENGINE (mei)
M: Tomas Winkler <tomas.winkler@intel.com>
@ -6697,7 +6713,7 @@ F: drivers/net/ethernet/marvell/sk*
MARVELL LIBERTAS WIRELESS DRIVER
L: libertas-dev@lists.infradead.org
S: Orphan
F: drivers/net/wireless/libertas/
F: drivers/net/wireless/marvell/libertas/
MARVELL MV643XX ETHERNET DRIVER
M: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
@ -6717,13 +6733,13 @@ M: Amitkumar Karwar <akarwar@marvell.com>
M: Nishant Sarmukadam <nishants@marvell.com>
L: linux-wireless@vger.kernel.org
S: Maintained
F: drivers/net/wireless/mwifiex/
F: drivers/net/wireless/marvell/mwifiex/
MARVELL MWL8K WIRELESS DRIVER
M: Lennert Buytenhek <buytenh@wantstofly.org>
L: linux-wireless@vger.kernel.org
S: Odd Fixes
F: drivers/net/wireless/mwl8k.c
F: drivers/net/wireless/marvell/mwl8k.c
MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER
M: Nicolas Pitre <nico@fluxnic.net>
@ -7359,6 +7375,13 @@ F: include/net/netrom.h
F: include/uapi/linux/netrom.h
F: net/netrom/
NETRONOME ETHERNET DRIVERS
M: Jakub Kicinski <jakub.kicinski@netronome.com>
M: Rolf Neugebauer <rolf.neugebauer@netronome.com>
L: oss-drivers@netronome.com
S: Maintained
F: drivers/net/ethernet/netronome/
NETWORK BLOCK DEVICE (NBD)
M: Markus Pargmann <mpa@pengutronix.de>
S: Maintained
@ -7490,7 +7513,12 @@ F: net/nfc/
F: include/net/nfc/
F: include/uapi/linux/nfc.h
F: drivers/nfc/
F: include/linux/platform_data/microread.h
F: include/linux/platform_data/nfcmrvl.h
F: include/linux/platform_data/nxp-nci.h
F: include/linux/platform_data/pn544.h
F: include/linux/platform_data/st21nfca.h
F: include/linux/platform_data/st-nci.h
F: Documentation/devicetree/bindings/net/nfc/
NFS, SUNRPC, AND LOCKD CLIENTS
@ -7940,7 +7968,7 @@ L: linux-wireless@vger.kernel.org
W: http://wireless.kernel.org/en/users/Drivers/orinoco
W: http://www.nongnu.org/orinoco/
S: Orphan
F: drivers/net/wireless/orinoco/
F: drivers/net/wireless/intersil/orinoco/
OSD LIBRARY and FILESYSTEM
M: Boaz Harrosh <ooo@electrozaur.com>
@ -7966,7 +7994,7 @@ M: Christian Lamparter <chunkeey@googlemail.com>
L: linux-wireless@vger.kernel.org
W: http://wireless.kernel.org/en/users/Drivers/p54
S: Maintained
F: drivers/net/wireless/p54/
F: drivers/net/wireless/intersil/p54/
PA SEMI ETHERNET DRIVER
M: Olof Johansson <olof@lixom.net>
@ -8517,7 +8545,7 @@ M: "Luis R. Rodriguez" <mcgrof@gmail.com>
L: linux-wireless@vger.kernel.org
W: http://wireless.kernel.org/en/users/Drivers/p54
S: Obsolete
F: drivers/net/wireless/prism54/
F: drivers/net/wireless/intersil/prism54/
PS3 NETWORK SUPPORT
M: Geoff Levand <geoff@infradead.org>
@ -8821,7 +8849,7 @@ M: Stanislaw Gruszka <sgruszka@redhat.com>
M: Helmut Schaa <helmut.schaa@googlemail.com>
L: linux-wireless@vger.kernel.org
S: Maintained
F: drivers/net/wireless/rt2x00/
F: drivers/net/wireless/ralink/rt2x00/
RAMDISK RAM BLOCK DEVICE DRIVER
M: Jens Axboe <axboe@kernel.dk>
@ -9062,7 +9090,7 @@ L: linux-wireless@vger.kernel.org
W: http://wireless.kernel.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
S: Orphan
F: drivers/net/wireless/rtl818x/rtl8180/
F: drivers/net/wireless/realtek/rtl818x/rtl8180/
RTL8187 WIRELESS DRIVER
M: Herton Ronaldo Krzesinski <herton@canonical.com>
@ -9072,7 +9100,7 @@ L: linux-wireless@vger.kernel.org
W: http://wireless.kernel.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
S: Maintained
F: drivers/net/wireless/rtl818x/rtl8187/
F: drivers/net/wireless/realtek/rtl818x/rtl8187/
RTL8192CE WIRELESS DRIVER
M: Larry Finger <Larry.Finger@lwfinger.net>
@ -9081,8 +9109,8 @@ L: linux-wireless@vger.kernel.org
W: http://wireless.kernel.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
S: Maintained
F: drivers/net/wireless/rtlwifi/
F: drivers/net/wireless/rtlwifi/rtl8192ce/
F: drivers/net/wireless/realtek/rtlwifi/
F: drivers/net/wireless/realtek/rtlwifi/rtl8192ce/
RTL8XXXU WIRELESS DRIVER (rtl8xxxu)
M: Jes Sorensen <Jes.Sorensen@redhat.com>
@ -9126,7 +9154,7 @@ F: drivers/s390/block/dasd*
F: block/partitions/ibm.c
S390 NETWORK DRIVERS
M: Ursula Braun <ursula.braun@de.ibm.com>
M: Ursula Braun <ubraun@linux.vnet.ibm.com>
L: linux-s390@vger.kernel.org
W: http://www.ibm.com/developerworks/linux/linux390/
S: Supported
@ -9156,7 +9184,7 @@ S: Supported
F: drivers/s390/scsi/zfcp_*
S390 IUCV NETWORK LAYER
M: Ursula Braun <ursula.braun@de.ibm.com>
M: Ursula Braun <ubraun@linux.vnet.ibm.com>
L: linux-s390@vger.kernel.org
W: http://www.ibm.com/developerworks/linux/linux390/
S: Supported
@ -11185,6 +11213,13 @@ L: linux-usb@vger.kernel.org
S: Supported
F: drivers/usb/class/usblp.c
USB QMI WWAN NETWORK DRIVER
M: Bjørn Mork <bjorn@mork.no>
L: netdev@vger.kernel.org
S: Maintained
F: Documentation/ABI/testing/sysfs-class-net-qmi
F: drivers/net/usb/qmi_wwan.c
USB RTL8150 DRIVER
M: Petko Manolov <petkan@nucleusys.com>
L: linux-usb@vger.kernel.org
@ -11281,7 +11316,7 @@ USB ZD1201 DRIVER
L: linux-wireless@vger.kernel.org
W: http://linux-lc100020.sourceforge.net
S: Orphan
F: drivers/net/wireless/zd1201.*
F: drivers/net/wireless/zydas/zd1201.*
USB ZR364XX DRIVER
M: Antoine Jacquet <royale@zerezo.com>
@ -11912,7 +11947,7 @@ W: http://zd1211.ath.cx/wiki/DriverRewrite
L: linux-wireless@vger.kernel.org
L: zd1211-devs@lists.sourceforge.net (subscribers-only)
S: Maintained
F: drivers/net/wireless/zd1211rw/
F: drivers/net/wireless/zydas/zd1211rw/
ZPOOL COMPRESSED PAGE STORAGE API
M: Dan Streetman <ddstreet@ieee.org>

View File

@ -92,4 +92,7 @@
#define SO_ATTACH_BPF 50
#define SO_DETACH_BPF SO_DETACH_FILTER
#define SO_ATTACH_REUSEPORT_CBPF 51
#define SO_ATTACH_REUSEPORT_EBPF 52
#endif /* _UAPI_ASM_SOCKET_H */

View File

@ -152,8 +152,6 @@ static void build_prologue(struct jit_ctx *ctx)
const u8 r8 = bpf2a64[BPF_REG_8];
const u8 r9 = bpf2a64[BPF_REG_9];
const u8 fp = bpf2a64[BPF_REG_FP];
const u8 ra = bpf2a64[BPF_REG_A];
const u8 rx = bpf2a64[BPF_REG_X];
const u8 tmp1 = bpf2a64[TMP_REG_1];
const u8 tmp2 = bpf2a64[TMP_REG_2];
@ -200,10 +198,6 @@ static void build_prologue(struct jit_ctx *ctx)
/* Set up function call stack */
emit(A64_SUB_I(1, A64_SP, A64_SP, STACK_SIZE), ctx);
/* Clear registers A and X */
emit_a64_mov_i64(ra, 0, ctx);
emit_a64_mov_i64(rx, 0, ctx);
}
static void build_epilogue(struct jit_ctx *ctx)

View File

@ -85,4 +85,7 @@
#define SO_ATTACH_BPF 50
#define SO_DETACH_BPF SO_DETACH_FILTER
#define SO_ATTACH_REUSEPORT_CBPF 51
#define SO_ATTACH_REUSEPORT_EBPF 52
#endif /* _UAPI__ASM_AVR32_SOCKET_H */

View File

@ -85,5 +85,8 @@
#define SO_ATTACH_BPF 50
#define SO_DETACH_BPF SO_DETACH_FILTER
#define SO_ATTACH_REUSEPORT_CBPF 51
#define SO_ATTACH_REUSEPORT_EBPF 52
#endif /* _ASM_SOCKET_H */

View File

@ -94,4 +94,7 @@
#define SO_ATTACH_BPF 50
#define SO_DETACH_BPF SO_DETACH_FILTER
#define SO_ATTACH_REUSEPORT_CBPF 51
#define SO_ATTACH_REUSEPORT_EBPF 52
#endif /* _ASM_IA64_SOCKET_H */

View File

@ -85,4 +85,7 @@
#define SO_ATTACH_BPF 50
#define SO_DETACH_BPF SO_DETACH_FILTER
#define SO_ATTACH_REUSEPORT_CBPF 51
#define SO_ATTACH_REUSEPORT_EBPF 52
#endif /* _ASM_M32R_SOCKET_H */

View File

@ -101,50 +101,13 @@ static void bcm47xx_machine_halt(void)
}
#ifdef CONFIG_BCM47XX_SSB
static int bcm47xx_get_invariants(struct ssb_bus *bus,
struct ssb_init_invariants *iv)
{
char buf[20];
int len, err;
/* Fill boardinfo structure */
memset(&iv->boardinfo, 0 , sizeof(struct ssb_boardinfo));
len = bcm47xx_nvram_getenv("boardvendor", buf, sizeof(buf));
if (len > 0) {
err = kstrtou16(strim(buf), 0, &iv->boardinfo.vendor);
if (err)
pr_warn("Couldn't parse nvram board vendor entry with value \"%s\"\n",
buf);
}
if (!iv->boardinfo.vendor)
iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
len = bcm47xx_nvram_getenv("boardtype", buf, sizeof(buf));
if (len > 0) {
err = kstrtou16(strim(buf), 0, &iv->boardinfo.type);
if (err)
pr_warn("Couldn't parse nvram board type entry with value \"%s\"\n",
buf);
}
memset(&iv->sprom, 0, sizeof(struct ssb_sprom));
bcm47xx_fill_sprom(&iv->sprom, NULL, false);
if (bcm47xx_nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
return 0;
}
static void __init bcm47xx_register_ssb(void)
{
int err;
char buf[100];
struct ssb_mipscore *mcore;
err = ssb_bus_ssbbus_register(&bcm47xx_bus.ssb, SSB_ENUM_BASE,
bcm47xx_get_invariants);
err = ssb_bus_host_soc_register(&bcm47xx_bus.ssb, SSB_ENUM_BASE);
if (err)
panic("Failed to initialize SSB bus (err %d)", err);

View File

@ -103,4 +103,7 @@
#define SO_ATTACH_BPF 50
#define SO_DETACH_BPF SO_DETACH_FILTER
#define SO_ATTACH_REUSEPORT_CBPF 51
#define SO_ATTACH_REUSEPORT_EBPF 52
#endif /* _UAPI_ASM_SOCKET_H */

View File

@ -85,4 +85,7 @@
#define SO_ATTACH_BPF 50
#define SO_DETACH_BPF SO_DETACH_FILTER
#define SO_ATTACH_REUSEPORT_CBPF 51
#define SO_ATTACH_REUSEPORT_EBPF 52
#endif /* _ASM_SOCKET_H */

View File

@ -84,4 +84,7 @@
#define SO_ATTACH_BPF 0x402B
#define SO_DETACH_BPF SO_DETACH_FILTER
#define SO_ATTACH_REUSEPORT_CBPF 0x402C
#define SO_ATTACH_REUSEPORT_EBPF 0x402D
#endif /* _UAPI_ASM_SOCKET_H */

View File

@ -258,11 +258,16 @@
#define H_DEL_CONN 0x288
#define H_JOIN 0x298
#define H_VASI_STATE 0x2A4
#define H_VIOCTL 0x2A8
#define H_ENABLE_CRQ 0x2B0
#define H_GET_EM_PARMS 0x2B8
#define H_SET_MPP 0x2D0
#define H_GET_MPP 0x2D4
#define H_REG_SUB_CRQ 0x2DC
#define H_HOME_NODE_ASSOCIATIVITY 0x2EC
#define H_FREE_SUB_CRQ 0x2E0
#define H_SEND_SUB_CRQ 0x2E4
#define H_SEND_SUB_CRQ_INDIRECT 0x2E8
#define H_BEST_ENERGY 0x2F4
#define H_XIRR_X 0x2FC
#define H_RANDOM 0x300
@ -271,6 +276,21 @@
#define H_SET_MODE 0x31C
#define MAX_HCALL_OPCODE H_SET_MODE
/* H_VIOCTL functions */
#define H_GET_VIOA_DUMP_SIZE 0x01
#define H_GET_VIOA_DUMP 0x02
#define H_GET_ILLAN_NUM_VLAN_IDS 0x03
#define H_GET_ILLAN_VLAN_ID_LIST 0x04
#define H_GET_ILLAN_SWITCH_ID 0x05
#define H_DISABLE_MIGRATION 0x06
#define H_ENABLE_MIGRATION 0x07
#define H_GET_PARTNER_INFO 0x08
#define H_GET_PARTNER_WWPN_LIST 0x09
#define H_DISABLE_ALL_VIO_INTS 0x0A
#define H_DISABLE_VIO_INTERRUPT 0x0B
#define H_ENABLE_VIO_INTERRUPT 0x0C
/* Platform specific hcalls, used by KVM */
#define H_RTAS 0xf000

View File

@ -92,4 +92,7 @@
#define SO_ATTACH_BPF 50
#define SO_DETACH_BPF SO_DETACH_FILTER
#define SO_ATTACH_REUSEPORT_CBPF 51
#define SO_ATTACH_REUSEPORT_EBPF 52
#endif /* _ASM_POWERPC_SOCKET_H */

View File

@ -131,23 +131,15 @@ static int ep8248e_mdio_probe(struct platform_device *ofdev)
if (!bus)
return -ENOMEM;
bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
if (bus->irq == NULL) {
ret = -ENOMEM;
goto err_free_bus;
}
bus->name = "ep8248e-mdio-bitbang";
bus->parent = &ofdev->dev;
snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start);
ret = of_mdiobus_register(bus, ofdev->dev.of_node);
if (ret)
goto err_free_irq;
goto err_free_bus;
return 0;
err_free_irq:
kfree(bus->irq);
err_free_bus:
free_mdio_bitbang(bus);
return ret;

View File

@ -41,7 +41,6 @@ static void __iomem *gpio_regs;
struct gpio_priv {
int mdc_pin;
int mdio_pin;
int mdio_irqs[PHY_MAX_ADDR];
};
#define MDC_PIN(bus) (((struct gpio_priv *)bus->priv)->mdc_pin)
@ -245,8 +244,6 @@ static int gpio_mdio_probe(struct platform_device *ofdev)
snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", *prop);
new_bus->priv = priv;
new_bus->irq = priv->mdio_irqs;
prop = of_get_property(np, "mdc-pin", NULL);
priv->mdc_pin = *prop;

View File

@ -91,4 +91,7 @@
#define SO_ATTACH_BPF 50
#define SO_DETACH_BPF SO_DETACH_FILTER
#define SO_ATTACH_REUSEPORT_CBPF 51
#define SO_ATTACH_REUSEPORT_EBPF 52
#endif /* _ASM_SOCKET_H */

View File

@ -408,7 +408,7 @@ static void emit_load_skb_data_hlen(struct bpf_jit *jit)
* Save registers and create stack frame if necessary.
* See stack frame layout desription in "bpf_jit.h"!
*/
static void bpf_jit_prologue(struct bpf_jit *jit, bool is_classic)
static void bpf_jit_prologue(struct bpf_jit *jit)
{
if (jit->seen & SEEN_TAIL_CALL) {
/* xc STK_OFF_TCCNT(4,%r15),STK_OFF_TCCNT(%r15) */
@ -448,15 +448,6 @@ static void bpf_jit_prologue(struct bpf_jit *jit, bool is_classic)
/* stg %b1,ST_OFF_SKBP(%r0,%r15) */
EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0, REG_15,
STK_OFF_SKBP);
/* Clear A (%b0) and X (%b7) registers for converted BPF programs */
if (is_classic) {
if (REG_SEEN(BPF_REG_A))
/* lghi %ba,0 */
EMIT4_IMM(0xa7090000, BPF_REG_A, 0);
if (REG_SEEN(BPF_REG_X))
/* lghi %bx,0 */
EMIT4_IMM(0xa7090000, BPF_REG_X, 0);
}
}
/*
@ -1245,7 +1236,7 @@ static int bpf_jit_prog(struct bpf_jit *jit, struct bpf_prog *fp)
jit->lit = jit->lit_start;
jit->prg = 0;
bpf_jit_prologue(jit, bpf_prog_was_classic(fp));
bpf_jit_prologue(jit);
for (i = 0; i < fp->len; i += insn_count) {
insn_count = bpf_jit_insn(jit, fp, i);
if (insn_count < 0)

View File

@ -81,6 +81,9 @@
#define SO_ATTACH_BPF 0x0034
#define SO_DETACH_BPF SO_DETACH_FILTER
#define SO_ATTACH_REUSEPORT_CBPF 0x0035
#define SO_ATTACH_REUSEPORT_EBPF 0x0036
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 0x5001
#define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002

View File

@ -9,6 +9,7 @@
#include <linux/types.h>
#include <linux/init.h>
#include <linux/export.h>
#include <linux/etherdevice.h>
#include <asm/oplib.h>
#include <asm/idprom.h>
@ -60,6 +61,12 @@ static void __init display_system_type(unsigned char machtype)
{
}
#endif
unsigned char *arch_get_platform_mac_address(void)
{
return idprom->id_ethaddr;
}
/* Calculate the IDPROM checksum (xor of the data bytes). */
static unsigned char __init calc_idprom_cksum(struct idprom *idprom)
{

View File

@ -193,7 +193,7 @@ struct jit_context {
32 /* space for rbx, r13, r14, r15 */ + \
8 /* space for skb_copy_bits() buffer */)
#define PROLOGUE_SIZE 51
#define PROLOGUE_SIZE 48
/* emit x64 prologue code for BPF program and check it's size.
* bpf_tail_call helper will skip it while jumping into another program
@ -229,11 +229,15 @@ static void emit_prologue(u8 **pprog)
/* mov qword ptr [rbp-X],r15 */
EMIT3_off32(0x4C, 0x89, 0xBD, -STACKSIZE + 24);
/* clear A and X registers */
EMIT2(0x31, 0xc0); /* xor eax, eax */
EMIT3(0x4D, 0x31, 0xED); /* xor r13, r13 */
/* Clear the tail call counter (tail_call_cnt): for eBPF tail calls
* we need to reset the counter to 0. It's done in two instructions,
* resetting rax register to 0 (xor on eax gets 0 extended), and
* moving it to the counter location.
*/
/* clear tail_cnt: mov qword ptr [rbp-X], rax */
/* xor eax, eax */
EMIT2(0x31, 0xc0);
/* mov qword ptr [rbp-X], rax */
EMIT3_off32(0x48, 0x89, 0x85, -STACKSIZE + 32);
BUILD_BUG_ON(cnt != PROLOGUE_SIZE);
@ -455,6 +459,18 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
}
case BPF_ALU | BPF_MOV | BPF_K:
/* optimization: if imm32 is zero, use 'xor <dst>,<dst>'
* to save 3 bytes.
*/
if (imm32 == 0) {
if (is_ereg(dst_reg))
EMIT1(add_2mod(0x40, dst_reg, dst_reg));
b2 = 0x31; /* xor */
b3 = 0xC0;
EMIT2(b2, add_2reg(b3, dst_reg, dst_reg));
break;
}
/* mov %eax, imm32 */
if (is_ereg(dst_reg))
EMIT1(add_1mod(0x40, dst_reg));
@ -469,6 +485,20 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
return -EINVAL;
}
/* optimization: if imm64 is zero, use 'xor <dst>,<dst>'
* to save 7 bytes.
*/
if (insn[0].imm == 0 && insn[1].imm == 0) {
b1 = add_2mod(0x48, dst_reg, dst_reg);
b2 = 0x31; /* xor */
b3 = 0xC0;
EMIT3(b1, b2, add_2reg(b3, dst_reg, dst_reg));
insn++;
i++;
break;
}
/* movabsq %rax, imm64 */
EMIT2(add_1mod(0x48, dst_reg), add_1reg(0xB8, dst_reg));
EMIT(insn[0].imm, 4);

View File

@ -96,4 +96,7 @@
#define SO_ATTACH_BPF 50
#define SO_DETACH_BPF SO_DETACH_FILTER
#define SO_ATTACH_REUSEPORT_CBPF 51
#define SO_ATTACH_REUSEPORT_EBPF 52
#endif /* _XTENSA_SOCKET_H */

View File

@ -106,7 +106,7 @@ static void aead_wmem_wakeup(struct sock *sk)
rcu_read_lock();
wq = rcu_dereference(sk->sk_wq);
if (wq_has_sleeper(wq))
if (skwq_has_sleeper(wq))
wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
POLLRDNORM |
POLLRDBAND);
@ -157,7 +157,7 @@ static void aead_data_wakeup(struct sock *sk)
rcu_read_lock();
wq = rcu_dereference(sk->sk_wq);
if (wq_has_sleeper(wq))
if (skwq_has_sleeper(wq))
wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
POLLRDNORM |
POLLRDBAND);

View File

@ -238,7 +238,7 @@ static void skcipher_wmem_wakeup(struct sock *sk)
rcu_read_lock();
wq = rcu_dereference(sk->sk_wq);
if (wq_has_sleeper(wq))
if (skwq_has_sleeper(wq))
wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
POLLRDNORM |
POLLRDBAND);
@ -288,7 +288,7 @@ static void skcipher_data_wakeup(struct sock *sk)
rcu_read_lock();
wq = rcu_dereference(sk->sk_wq);
if (wq_has_sleeper(wq))
if (skwq_has_sleeper(wq))
wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
POLLRDNORM |
POLLRDBAND);

View File

@ -347,8 +347,8 @@ static char *next_string(struct sk_buff *skb)
*/
static int process_status(struct solos_card *card, int port, struct sk_buff *skb)
{
char *str, *end, *state_str, *snr, *attn;
int ver, rate_up, rate_down;
char *str, *state_str, *snr, *attn;
int ver, rate_up, rate_down, err;
if (!card->atmdev[port])
return -ENODEV;
@ -357,7 +357,11 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb
if (!str)
return -EIO;
ver = simple_strtol(str, NULL, 10);
err = kstrtoint(str, 10, &ver);
if (err) {
dev_warn(&card->dev->dev, "Unexpected status interrupt version\n");
return err;
}
if (ver < 1) {
dev_warn(&card->dev->dev, "Unexpected status interrupt version %d\n",
ver);
@ -373,16 +377,16 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb
return 0;
}
rate_down = simple_strtol(str, &end, 10);
if (*end)
return -EIO;
err = kstrtoint(str, 10, &rate_down);
if (err)
return err;
str = next_string(skb);
if (!str)
return -EIO;
rate_up = simple_strtol(str, &end, 10);
if (*end)
return -EIO;
err = kstrtoint(str, 10, &rate_up);
if (err)
return err;
state_str = next_string(skb);
if (!state_str)
@ -417,7 +421,7 @@ static int process_command(struct solos_card *card, int port, struct sk_buff *sk
struct solos_param *prm;
unsigned long flags;
int cmdpid;
int found = 0;
int found = 0, err;
if (skb->len < 7)
return 0;
@ -428,7 +432,9 @@ static int process_command(struct solos_card *card, int port, struct sk_buff *sk
skb->data[6] != '\n')
return 0;
cmdpid = simple_strtol(&skb->data[1], NULL, 10);
err = kstrtoint(&skb->data[1], 10, &cmdpid);
if (err)
return err;
spin_lock_irqsave(&card->param_queue_lock, flags);
list_for_each_entry(prm, &card->param_queue, list) {
@ -519,7 +525,7 @@ struct geos_gpio_attr {
static ssize_t geos_gpio_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
struct pci_dev *pdev = to_pci_dev(dev);
struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr);
struct solos_card *card = pci_get_drvdata(pdev);
uint32_t data32;
@ -545,7 +551,7 @@ static ssize_t geos_gpio_store(struct device *dev, struct device_attribute *attr
static ssize_t geos_gpio_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
struct pci_dev *pdev = to_pci_dev(dev);
struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr);
struct solos_card *card = pci_get_drvdata(pdev);
uint32_t data32;
@ -559,7 +565,7 @@ static ssize_t geos_gpio_show(struct device *dev, struct device_attribute *attr,
static ssize_t hardware_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
struct pci_dev *pdev = to_pci_dev(dev);
struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr);
struct solos_card *card = pci_get_drvdata(pdev);
uint32_t data32;

View File

@ -668,11 +668,36 @@ static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env)
core->id.rev, core->id.class);
}
static unsigned int bcma_bus_registered;
/*
* If built-in, bus has to be registered early, before any driver calls
* bcma_driver_register.
* Otherwise registering driver would trigger BUG in driver_register.
*/
static int __init bcma_init_bus_register(void)
{
int err;
if (bcma_bus_registered)
return 0;
err = bus_register(&bcma_bus_type);
if (!err)
bcma_bus_registered = 1;
return err;
}
#ifndef MODULE
fs_initcall(bcma_init_bus_register);
#endif
/* Main initialization has to be done with SPI/mtd/NAND/SPROM available */
static int __init bcma_modinit(void)
{
int err;
err = bus_register(&bcma_bus_type);
err = bcma_init_bus_register();
if (err)
return err;
@ -691,7 +716,7 @@ static int __init bcma_modinit(void)
return err;
}
fs_initcall(bcma_modinit);
module_init(bcma_modinit);
static void __exit bcma_modexit(void)
{

View File

@ -178,10 +178,8 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
return -ENODEV;
data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
if (!data) {
BT_ERR("Can't allocate memory for data structure");
if (!data)
return -ENOMEM;
}
data->udev = udev;
data->state = BCM203X_LOAD_MINIDRV;

View File

@ -324,7 +324,7 @@ static inline int bfusb_recv_block(struct bfusb_data *data, int hdr, unsigned ch
return -ENOMEM;
}
bt_cb(skb)->pkt_type = pkt_type;
hci_skb_pkt_type(skb) = pkt_type;
data->reassembly = skb;
} else {
@ -469,9 +469,10 @@ static int bfusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
unsigned char buf[3];
int sent = 0, size, count;
BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, bt_cb(skb)->pkt_type, skb->len);
BT_DBG("hdev %p skb %p type %d len %d", hdev, skb,
hci_skb_pkt_type(skb), skb->len);
switch (bt_cb(skb)->pkt_type) {
switch (hci_skb_pkt_type(skb)) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
break;
@ -484,7 +485,7 @@ static int bfusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
}
/* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
count = skb->len;
@ -635,10 +636,8 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
/* Initialize control structure and load firmware */
data = devm_kzalloc(&intf->dev, sizeof(struct bfusb_data), GFP_KERNEL);
if (!data) {
BT_ERR("Can't allocate memory for control structure");
goto done;
}
if (!data)
return -ENOMEM;
data->udev = udev;
data->bulk_in_ep = bulk_in_ep->desc.bEndpointAddress;

View File

@ -261,7 +261,7 @@ static void bluecard_write_wakeup(struct bluecard_info *info)
if (!skb)
break;
if (bt_cb(skb)->pkt_type & 0x80) {
if (hci_skb_pkt_type(skb) & 0x80) {
/* Disable RTS */
info->ctrl_reg |= REG_CONTROL_RTS;
outb(info->ctrl_reg, iobase + REG_CONTROL);
@ -279,13 +279,13 @@ static void bluecard_write_wakeup(struct bluecard_info *info)
/* Mark the buffer as dirty */
clear_bit(ready_bit, &(info->tx_state));
if (bt_cb(skb)->pkt_type & 0x80) {
if (hci_skb_pkt_type(skb) & 0x80) {
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
DEFINE_WAIT(wait);
unsigned char baud_reg;
switch (bt_cb(skb)->pkt_type) {
switch (hci_skb_pkt_type(skb)) {
case PKT_BAUD_RATE_460800:
baud_reg = REG_CONTROL_BAUD_RATE_460800;
break;
@ -402,9 +402,9 @@ static void bluecard_receive(struct bluecard_info *info,
if (info->rx_state == RECV_WAIT_PACKET_TYPE) {
bt_cb(info->rx_skb)->pkt_type = buf[i];
hci_skb_pkt_type(info->rx_skb) = buf[i];
switch (bt_cb(info->rx_skb)->pkt_type) {
switch (hci_skb_pkt_type(info->rx_skb)) {
case 0x00:
/* init packet */
@ -436,7 +436,8 @@ static void bluecard_receive(struct bluecard_info *info,
default:
/* unknown packet */
BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
BT_ERR("Unknown HCI packet with type 0x%02x received",
hci_skb_pkt_type(info->rx_skb));
info->hdev->stat.err_rx++;
kfree_skb(info->rx_skb);
@ -578,21 +579,21 @@ static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud)
switch (baud) {
case 460800:
cmd[4] = 0x00;
bt_cb(skb)->pkt_type = PKT_BAUD_RATE_460800;
hci_skb_pkt_type(skb) = PKT_BAUD_RATE_460800;
break;
case 230400:
cmd[4] = 0x01;
bt_cb(skb)->pkt_type = PKT_BAUD_RATE_230400;
hci_skb_pkt_type(skb) = PKT_BAUD_RATE_230400;
break;
case 115200:
cmd[4] = 0x02;
bt_cb(skb)->pkt_type = PKT_BAUD_RATE_115200;
hci_skb_pkt_type(skb) = PKT_BAUD_RATE_115200;
break;
case 57600:
/* Fall through... */
default:
cmd[4] = 0x03;
bt_cb(skb)->pkt_type = PKT_BAUD_RATE_57600;
hci_skb_pkt_type(skb) = PKT_BAUD_RATE_57600;
break;
}
@ -660,7 +661,7 @@ static int bluecard_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
{
struct bluecard_info *info = hci_get_drvdata(hdev);
switch (bt_cb(skb)->pkt_type) {
switch (hci_skb_pkt_type(skb)) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
break;
@ -673,7 +674,7 @@ static int bluecard_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
}
/* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
skb_queue_tail(&(info->txq), skb);
bluecard_write_wakeup(info);

View File

@ -295,9 +295,9 @@ static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
return -ENOMEM;
/* Prepend skb with frame type */
*skb_push(skb, 1) = bt_cb(skb)->pkt_type;
*skb_push(skb, 1) = hci_skb_pkt_type(skb);
switch (bt_cb(skb)->pkt_type) {
switch (hci_skb_pkt_type(skb)) {
case HCI_COMMAND_PKT:
dr = kmalloc(sizeof(*dr), GFP_ATOMIC);
if (!dr) {

View File

@ -246,10 +246,10 @@ static void bt3c_receive(struct bt3c_info *info)
if (info->rx_state == RECV_WAIT_PACKET_TYPE) {
bt_cb(info->rx_skb)->pkt_type = inb(iobase + DATA_L);
hci_skb_pkt_type(info->rx_skb) = inb(iobase + DATA_L);
inb(iobase + DATA_H);
switch (bt_cb(info->rx_skb)->pkt_type) {
switch (hci_skb_pkt_type(info->rx_skb)) {
case HCI_EVENT_PKT:
info->rx_state = RECV_WAIT_EVENT_HEADER;
@ -268,7 +268,8 @@ static void bt3c_receive(struct bt3c_info *info)
default:
/* Unknown packet */
BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
BT_ERR("Unknown HCI packet with type 0x%02x received",
hci_skb_pkt_type(info->rx_skb));
info->hdev->stat.err_rx++;
kfree_skb(info->rx_skb);
@ -411,7 +412,7 @@ static int bt3c_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
struct bt3c_info *info = hci_get_drvdata(hdev);
unsigned long flags;
switch (bt_cb(skb)->pkt_type) {
switch (hci_skb_pkt_type(skb)) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
break;
@ -424,7 +425,7 @@ static int bt3c_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
}
/* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
skb_queue_tail(&(info->txq), skb);
spin_lock_irqsave(&(info->lock), flags);

View File

@ -73,6 +73,48 @@ int btintel_check_bdaddr(struct hci_dev *hdev)
}
EXPORT_SYMBOL_GPL(btintel_check_bdaddr);
int btintel_enter_mfg(struct hci_dev *hdev)
{
const u8 param[] = { 0x01, 0x00 };
struct sk_buff *skb;
skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) {
bt_dev_err(hdev, "Entering manufacturer mode failed (%ld)",
PTR_ERR(skb));
return PTR_ERR(skb);
}
kfree_skb(skb);
return 0;
}
EXPORT_SYMBOL_GPL(btintel_enter_mfg);
int btintel_exit_mfg(struct hci_dev *hdev, bool reset, bool patched)
{
u8 param[] = { 0x00, 0x00 };
struct sk_buff *skb;
/* The 2nd command parameter specifies the manufacturing exit method:
* 0x00: Just disable the manufacturing mode (0x00).
* 0x01: Disable manufacturing mode and reset with patches deactivated.
* 0x02: Disable manufacturing mode and reset with patches activated.
*/
if (reset)
param[1] |= patched ? 0x02 : 0x01;
skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) {
bt_dev_err(hdev, "Exiting manufacturer mode failed (%ld)",
PTR_ERR(skb));
return PTR_ERR(skb);
}
kfree_skb(skb);
return 0;
}
EXPORT_SYMBOL_GPL(btintel_exit_mfg);
int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
{
struct sk_buff *skb;
@ -126,37 +168,19 @@ EXPORT_SYMBOL_GPL(btintel_set_diag);
int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable)
{
struct sk_buff *skb;
u8 param[2];
int err;
int err, ret;
param[0] = 0x01;
param[1] = 0x00;
err = btintel_enter_mfg(hdev);
if (err)
return err;
skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
BT_ERR("%s: Entering Intel manufacturer mode failed (%d)",
hdev->name, err);
return PTR_ERR(skb);
}
kfree_skb(skb);
ret = btintel_set_diag(hdev, enable);
err = btintel_set_diag(hdev, enable);
err = btintel_exit_mfg(hdev, false, false);
if (err)
return err;
param[0] = 0x00;
param[1] = 0x00;
skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
BT_ERR("%s: Leaving Intel manufacturer mode failed (%d)",
hdev->name, err);
return PTR_ERR(skb);
}
kfree_skb(skb);
return err;
return ret;
}
EXPORT_SYMBOL_GPL(btintel_set_diag_mfg);
@ -309,40 +333,47 @@ EXPORT_SYMBOL_GPL(btintel_set_event_mask);
int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug)
{
struct sk_buff *skb;
u8 param[2];
int err;
int err, ret;
param[0] = 0x01;
param[1] = 0x00;
err = btintel_enter_mfg(hdev);
if (err)
return err;
skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
BT_ERR("%s: Entering Intel manufacturer mode failed (%d)",
hdev->name, err);
return PTR_ERR(skb);
}
kfree_skb(skb);
ret = btintel_set_event_mask(hdev, debug);
err = btintel_set_event_mask(hdev, debug);
err = btintel_exit_mfg(hdev, false, false);
if (err)
return err;
param[0] = 0x00;
param[1] = 0x00;
skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
BT_ERR("%s: Leaving Intel manufacturer mode failed (%d)",
hdev->name, err);
return PTR_ERR(skb);
}
kfree_skb(skb);
return err;
return ret;
}
EXPORT_SYMBOL_GPL(btintel_set_event_mask_mfg);
int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver)
{
struct sk_buff *skb;
skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) {
bt_dev_err(hdev, "Reading Intel version information failed (%ld)",
PTR_ERR(skb));
return PTR_ERR(skb);
}
if (skb->len != sizeof(*ver)) {
bt_dev_err(hdev, "Intel version event size mismatch");
kfree_skb(skb);
return -EILSEQ;
}
memcpy(ver, skb->data, sizeof(*ver));
kfree_skb(skb);
return 0;
}
EXPORT_SYMBOL_GPL(btintel_read_version);
/* ------- REGMAP IBT SUPPORT ------- */
#define IBT_REG_MODE_8BIT 0x00

View File

@ -72,6 +72,8 @@ struct intel_secure_send_result {
#if IS_ENABLED(CONFIG_BT_INTEL)
int btintel_check_bdaddr(struct hci_dev *hdev);
int btintel_enter_mfg(struct hci_dev *hdev);
int btintel_exit_mfg(struct hci_dev *hdev, bool reset, bool patched);
int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr);
int btintel_set_diag(struct hci_dev *hdev, bool enable);
int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable);
@ -83,6 +85,7 @@ int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen,
int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name);
int btintel_set_event_mask(struct hci_dev *hdev, bool debug);
int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug);
int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver);
struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
u16 opcode_write);
@ -94,6 +97,16 @@ static inline int btintel_check_bdaddr(struct hci_dev *hdev)
return -EOPNOTSUPP;
}
static inline int btintel_enter_mfg(struct hci_dev *hdev)
{
return -EOPNOTSUPP;
}
static inline int btintel_exit_mfg(struct hci_dev *hdev, bool reset, bool patched)
{
return -EOPNOTSUPP;
}
static inline int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
{
return -EOPNOTSUPP;
@ -140,6 +153,12 @@ static inline int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug)
return -EOPNOTSUPP;
}
static inline int btintel_read_version(struct hci_dev *hdev,
struct intel_version *ver)
{
return -EOPNOTSUPP;
}
static inline struct regmap *btintel_regmap_init(struct hci_dev *hdev,
u16 opcode_read,
u16 opcode_write)

View File

@ -89,6 +89,7 @@ struct btmrvl_adapter {
wait_queue_head_t event_hs_wait_q;
u8 cmd_complete;
bool is_suspended;
bool is_suspending;
};
struct btmrvl_private {

View File

@ -196,7 +196,7 @@ static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 opcode,
if (len)
memcpy(skb_put(skb, len), param, len);
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
hci_skb_pkt_type(skb) = MRVL_VENDOR_PKT;
skb_queue_head(&priv->adapter->tx_queue, skb);
@ -387,7 +387,7 @@ static int btmrvl_tx_pkt(struct btmrvl_private *priv, struct sk_buff *skb)
skb->data[0] = (skb->len & 0x0000ff);
skb->data[1] = (skb->len & 0x00ff00) >> 8;
skb->data[2] = (skb->len & 0xff0000) >> 16;
skb->data[3] = bt_cb(skb)->pkt_type;
skb->data[3] = hci_skb_pkt_type(skb);
if (priv->hw_host_to_card)
ret = priv->hw_host_to_card(priv, skb->data, skb->len);
@ -434,9 +434,14 @@ static int btmrvl_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
{
struct btmrvl_private *priv = hci_get_drvdata(hdev);
BT_DBG("type=%d, len=%d", skb->pkt_type, skb->len);
BT_DBG("type=%d, len=%d", hci_skb_pkt_type(skb), skb->len);
switch (bt_cb(skb)->pkt_type) {
if (priv->adapter->is_suspending || priv->adapter->is_suspended) {
BT_ERR("%s: Device is suspending or suspended", __func__);
return -EBUSY;
}
switch (hci_skb_pkt_type(skb)) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
break;
@ -452,7 +457,8 @@ static int btmrvl_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
skb_queue_tail(&priv->adapter->tx_queue, skb);
wake_up_interruptible(&priv->main_thread.wait_q);
if (!priv->adapter->is_suspended)
wake_up_interruptible(&priv->main_thread.wait_q);
return 0;
}
@ -543,7 +549,7 @@ static int btmrvl_setup(struct hci_dev *hdev)
if (ret)
return ret;
priv->btmrvl_dev.gpio_gap = 0xffff;
priv->btmrvl_dev.gpio_gap = 0xfffe;
btmrvl_check_device_tree(priv);
@ -643,7 +649,8 @@ static int btmrvl_service_main_thread(void *data)
if (adapter->ps_state == PS_SLEEP)
continue;
if (!priv->btmrvl_dev.tx_dnld_rdy)
if (!priv->btmrvl_dev.tx_dnld_rdy ||
priv->adapter->is_suspended)
continue;
skb = skb_dequeue(&adapter->tx_queue);

View File

@ -698,7 +698,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
case HCI_ACLDATA_PKT:
case HCI_SCODATA_PKT:
case HCI_EVENT_PKT:
bt_cb(skb)->pkt_type = type;
hci_skb_pkt_type(skb) = type;
skb_put(skb, buf_len);
skb_pull(skb, SDIO_HEADER_LEN);
@ -713,7 +713,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
break;
case MRVL_VENDOR_PKT:
bt_cb(skb)->pkt_type = HCI_VENDOR_PKT;
hci_skb_pkt_type(skb) = HCI_VENDOR_PKT;
skb_put(skb, buf_len);
skb_pull(skb, SDIO_HEADER_LEN);
@ -1112,7 +1112,8 @@ static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
*/
if (btmrvl_sdio_verify_fw_download(card, pollnum)) {
BT_ERR("FW failed to be active in time!");
return -ETIMEDOUT;
ret = -ETIMEDOUT;
goto done;
}
sdio_release_host(card->func);
@ -1544,10 +1545,10 @@ static int btmrvl_sdio_suspend(struct device *dev)
}
priv = card->priv;
priv->adapter->is_suspending = true;
hcidev = priv->btmrvl_dev.hcidev;
BT_DBG("%s: SDIO suspend", hcidev->name);
hci_suspend_dev(hcidev);
skb_queue_purge(&priv->adapter->tx_queue);
if (priv->adapter->hs_state != HS_ACTIVATED) {
if (btmrvl_enable_hs(priv)) {
@ -1556,6 +1557,7 @@ static int btmrvl_sdio_suspend(struct device *dev)
}
}
priv->adapter->is_suspending = false;
priv->adapter->is_suspended = true;
/* We will keep the power when hs enabled successfully */

View File

@ -86,7 +86,7 @@ static int btsdio_tx_packet(struct btsdio_data *data, struct sk_buff *skb)
skb->data[0] = (skb->len & 0x0000ff);
skb->data[1] = (skb->len & 0x00ff00) >> 8;
skb->data[2] = (skb->len & 0xff0000) >> 16;
skb->data[3] = bt_cb(skb)->pkt_type;
skb->data[3] = hci_skb_pkt_type(skb);
err = sdio_writesb(data->func, REG_TDAT, skb->data, skb->len);
if (err < 0) {
@ -158,7 +158,7 @@ static int btsdio_rx_packet(struct btsdio_data *data)
data->hdev->stat.byte_rx += len;
bt_cb(skb)->pkt_type = hdr[3];
hci_skb_pkt_type(skb) = hdr[3];
err = hci_recv_frame(data->hdev, skb);
if (err < 0)
@ -252,7 +252,7 @@ static int btsdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s", hdev->name);
switch (bt_cb(skb)->pkt_type) {
switch (hci_skb_pkt_type(skb)) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
break;

View File

@ -200,9 +200,9 @@ static void btuart_receive(struct btuart_info *info)
if (info->rx_state == RECV_WAIT_PACKET_TYPE) {
bt_cb(info->rx_skb)->pkt_type = inb(iobase + UART_RX);
hci_skb_pkt_type(info->rx_skb) = inb(iobase + UART_RX);
switch (bt_cb(info->rx_skb)->pkt_type) {
switch (hci_skb_pkt_type(info->rx_skb)) {
case HCI_EVENT_PKT:
info->rx_state = RECV_WAIT_EVENT_HEADER;
@ -221,7 +221,8 @@ static void btuart_receive(struct btuart_info *info)
default:
/* Unknown packet */
BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
BT_ERR("Unknown HCI packet with type 0x%02x received",
hci_skb_pkt_type(info->rx_skb));
info->hdev->stat.err_rx++;
kfree_skb(info->rx_skb);
@ -424,7 +425,7 @@ static int btuart_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
{
struct btuart_info *info = hci_get_drvdata(hdev);
switch (bt_cb(skb)->pkt_type) {
switch (hci_skb_pkt_type(skb)) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
break;
@ -437,7 +438,7 @@ static int btuart_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
}
/* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
skb_queue_tail(&(info->txq), skb);
btuart_write_wakeup(info);

View File

@ -153,6 +153,10 @@ static const struct usb_device_id btusb_table[] = {
{ USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01),
.driver_info = BTUSB_BCM_PATCHRAM },
/* Toshiba Corp - Broadcom based */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0930, 0xff, 0x01, 0x01),
.driver_info = BTUSB_BCM_PATCHRAM },
/* Intel Bluetooth USB Bootloader (RAM module) */
{ USB_DEVICE(0x8087, 0x0a5a),
.driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC },
@ -437,22 +441,22 @@ static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count)
break;
}
bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
bt_cb(skb)->expect = HCI_EVENT_HDR_SIZE;
hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
hci_skb_expect(skb) = HCI_EVENT_HDR_SIZE;
}
len = min_t(uint, bt_cb(skb)->expect, count);
len = min_t(uint, hci_skb_expect(skb), count);
memcpy(skb_put(skb, len), buffer, len);
count -= len;
buffer += len;
bt_cb(skb)->expect -= len;
hci_skb_expect(skb) -= len;
if (skb->len == HCI_EVENT_HDR_SIZE) {
/* Complete event header */
bt_cb(skb)->expect = hci_event_hdr(skb)->plen;
hci_skb_expect(skb) = hci_event_hdr(skb)->plen;
if (skb_tailroom(skb) < bt_cb(skb)->expect) {
if (skb_tailroom(skb) < hci_skb_expect(skb)) {
kfree_skb(skb);
skb = NULL;
@ -461,7 +465,7 @@ static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count)
}
}
if (bt_cb(skb)->expect == 0) {
if (!hci_skb_expect(skb)) {
/* Complete frame */
data->recv_event(data->hdev, skb);
skb = NULL;
@ -492,24 +496,24 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
break;
}
bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
bt_cb(skb)->expect = HCI_ACL_HDR_SIZE;
hci_skb_pkt_type(skb) = HCI_ACLDATA_PKT;
hci_skb_expect(skb) = HCI_ACL_HDR_SIZE;
}
len = min_t(uint, bt_cb(skb)->expect, count);
len = min_t(uint, hci_skb_expect(skb), count);
memcpy(skb_put(skb, len), buffer, len);
count -= len;
buffer += len;
bt_cb(skb)->expect -= len;
hci_skb_expect(skb) -= len;
if (skb->len == HCI_ACL_HDR_SIZE) {
__le16 dlen = hci_acl_hdr(skb)->dlen;
/* Complete ACL header */
bt_cb(skb)->expect = __le16_to_cpu(dlen);
hci_skb_expect(skb) = __le16_to_cpu(dlen);
if (skb_tailroom(skb) < bt_cb(skb)->expect) {
if (skb_tailroom(skb) < hci_skb_expect(skb)) {
kfree_skb(skb);
skb = NULL;
@ -518,7 +522,7 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
}
}
if (bt_cb(skb)->expect == 0) {
if (!hci_skb_expect(skb)) {
/* Complete frame */
hci_recv_frame(data->hdev, skb);
skb = NULL;
@ -549,22 +553,22 @@ static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count)
break;
}
bt_cb(skb)->pkt_type = HCI_SCODATA_PKT;
bt_cb(skb)->expect = HCI_SCO_HDR_SIZE;
hci_skb_pkt_type(skb) = HCI_SCODATA_PKT;
hci_skb_expect(skb) = HCI_SCO_HDR_SIZE;
}
len = min_t(uint, bt_cb(skb)->expect, count);
len = min_t(uint, hci_skb_expect(skb), count);
memcpy(skb_put(skb, len), buffer, len);
count -= len;
buffer += len;
bt_cb(skb)->expect -= len;
hci_skb_expect(skb) -= len;
if (skb->len == HCI_SCO_HDR_SIZE) {
/* Complete SCO header */
bt_cb(skb)->expect = hci_sco_hdr(skb)->dlen;
hci_skb_expect(skb) = hci_sco_hdr(skb)->dlen;
if (skb_tailroom(skb) < bt_cb(skb)->expect) {
if (skb_tailroom(skb) < hci_skb_expect(skb)) {
kfree_skb(skb);
skb = NULL;
@ -573,7 +577,7 @@ static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count)
}
}
if (bt_cb(skb)->expect == 0) {
if (!hci_skb_expect(skb)) {
/* Complete frame */
hci_recv_frame(data->hdev, skb);
skb = NULL;
@ -1257,7 +1261,7 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s", hdev->name);
switch (bt_cb(skb)->pkt_type) {
switch (hci_skb_pkt_type(skb)) {
case HCI_COMMAND_PKT:
urb = alloc_ctrl_urb(hdev, skb);
if (IS_ERR(urb))
@ -1642,13 +1646,8 @@ static int btusb_setup_intel(struct hci_dev *hdev)
struct sk_buff *skb;
const struct firmware *fw;
const u8 *fw_ptr;
int disable_patch;
struct intel_version *ver;
const u8 mfg_enable[] = { 0x01, 0x00 };
const u8 mfg_disable[] = { 0x00, 0x00 };
const u8 mfg_reset_deactivate[] = { 0x00, 0x01 };
const u8 mfg_reset_activate[] = { 0x00, 0x02 };
int disable_patch, err;
struct intel_version ver;
BT_DBG("%s", hdev->name);
@ -1674,35 +1673,22 @@ static int btusb_setup_intel(struct hci_dev *hdev)
* The returned information are hardware variant and revision plus
* firmware variant, revision and build number.
*/
skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
BT_ERR("%s reading Intel fw version command failed (%ld)",
hdev->name, PTR_ERR(skb));
return PTR_ERR(skb);
}
if (skb->len != sizeof(*ver)) {
BT_ERR("%s Intel version event length mismatch", hdev->name);
kfree_skb(skb);
return -EIO;
}
ver = (struct intel_version *)skb->data;
err = btintel_read_version(hdev, &ver);
if (err)
return err;
BT_INFO("%s: read Intel version: %02x%02x%02x%02x%02x%02x%02x%02x%02x",
hdev->name, ver->hw_platform, ver->hw_variant,
ver->hw_revision, ver->fw_variant, ver->fw_revision,
ver->fw_build_num, ver->fw_build_ww, ver->fw_build_yy,
ver->fw_patch_num);
hdev->name, ver.hw_platform, ver.hw_variant, ver.hw_revision,
ver.fw_variant, ver.fw_revision, ver.fw_build_num,
ver.fw_build_ww, ver.fw_build_yy, ver.fw_patch_num);
/* fw_patch_num indicates the version of patch the device currently
* have. If there is no patch data in the device, it is always 0x00.
* So, if it is other than 0x00, no need to patch the device again.
*/
if (ver->fw_patch_num) {
if (ver.fw_patch_num) {
BT_INFO("%s: Intel device is already patched. patch num: %02x",
hdev->name, ver->fw_patch_num);
kfree_skb(skb);
hdev->name, ver.fw_patch_num);
goto complete;
}
@ -1712,31 +1698,21 @@ static int btusb_setup_intel(struct hci_dev *hdev)
* If no patch file is found, allow the device to operate without
* a patch.
*/
fw = btusb_setup_intel_get_fw(hdev, ver);
if (!fw) {
kfree_skb(skb);
fw = btusb_setup_intel_get_fw(hdev, &ver);
if (!fw)
goto complete;
}
fw_ptr = fw->data;
kfree_skb(skb);
/* This Intel specific command enables the manufacturer mode of the
* controller.
*
/* Enable the manufacturer mode of the controller.
* Only while this mode is enabled, the driver can download the
* firmware patch data and configuration parameters.
*/
skb = __hci_cmd_sync(hdev, 0xfc11, 2, mfg_enable, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
BT_ERR("%s entering Intel manufacturer mode failed (%ld)",
hdev->name, PTR_ERR(skb));
err = btintel_enter_mfg(hdev);
if (err) {
release_firmware(fw);
return PTR_ERR(skb);
return err;
}
kfree_skb(skb);
disable_patch = 1;
/* The firmware data file consists of list of Intel specific HCI
@ -1776,14 +1752,9 @@ static int btusb_setup_intel(struct hci_dev *hdev)
/* Patching completed successfully and disable the manufacturer mode
* with reset and activate the downloaded firmware patches.
*/
skb = __hci_cmd_sync(hdev, 0xfc11, sizeof(mfg_reset_activate),
mfg_reset_activate, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
BT_ERR("%s exiting Intel manufacturer mode failed (%ld)",
hdev->name, PTR_ERR(skb));
return PTR_ERR(skb);
}
kfree_skb(skb);
err = btintel_exit_mfg(hdev, true, true);
if (err)
return err;
BT_INFO("%s: Intel Bluetooth firmware patch completed and activated",
hdev->name);
@ -1792,14 +1763,9 @@ static int btusb_setup_intel(struct hci_dev *hdev)
exit_mfg_disable:
/* Disable the manufacturer mode without reset */
skb = __hci_cmd_sync(hdev, 0xfc11, sizeof(mfg_disable), mfg_disable,
HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
BT_ERR("%s exiting Intel manufacturer mode failed (%ld)",
hdev->name, PTR_ERR(skb));
return PTR_ERR(skb);
}
kfree_skb(skb);
err = btintel_exit_mfg(hdev, false, false);
if (err)
return err;
BT_INFO("%s: Intel Bluetooth firmware patch completed", hdev->name);
@ -1811,14 +1777,9 @@ exit_mfg_deactivate:
/* Patching failed. Disable the manufacturer mode with reset and
* deactivate the downloaded firmware patches.
*/
skb = __hci_cmd_sync(hdev, 0xfc11, sizeof(mfg_reset_deactivate),
mfg_reset_deactivate, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
BT_ERR("%s exiting Intel manufacturer mode failed (%ld)",
hdev->name, PTR_ERR(skb));
return PTR_ERR(skb);
}
kfree_skb(skb);
err = btintel_exit_mfg(hdev, true, false);
if (err)
return err;
BT_INFO("%s: Intel Bluetooth firmware patch completed and deactivated",
hdev->name);
@ -1853,7 +1814,7 @@ static int inject_cmd_complete(struct hci_dev *hdev, __u16 opcode)
*skb_put(skb, 1) = 0x00;
bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
return hci_recv_frame(hdev, skb);
}
@ -1945,7 +1906,7 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
BT_DBG("%s", hdev->name);
switch (bt_cb(skb)->pkt_type) {
switch (hci_skb_pkt_type(skb)) {
case HCI_COMMAND_PKT:
if (test_bit(BTUSB_BOOTLOADER, &data->flags)) {
struct hci_command_hdr *cmd = (void *)skb->data;
@ -2005,7 +1966,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
0x00, 0x08, 0x04, 0x00 };
struct btusb_data *data = hci_get_drvdata(hdev);
struct sk_buff *skb;
struct intel_version *ver;
struct intel_version ver;
struct intel_boot_params *params;
const struct firmware *fw;
const u8 *fw_ptr;
@ -2023,28 +1984,16 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
* is in bootloader mode or if it already has operational firmware
* loaded.
*/
skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
BT_ERR("%s: Reading Intel version information failed (%ld)",
hdev->name, PTR_ERR(skb));
return PTR_ERR(skb);
}
if (skb->len != sizeof(*ver)) {
BT_ERR("%s: Intel version event size mismatch", hdev->name);
kfree_skb(skb);
return -EILSEQ;
}
ver = (struct intel_version *)skb->data;
err = btintel_read_version(hdev, &ver);
if (err)
return err;
/* The hardware platform number has a fixed value of 0x37 and
* for now only accept this single value.
*/
if (ver->hw_platform != 0x37) {
if (ver.hw_platform != 0x37) {
BT_ERR("%s: Unsupported Intel hardware platform (%u)",
hdev->name, ver->hw_platform);
kfree_skb(skb);
hdev->name, ver.hw_platform);
return -EINVAL;
}
@ -2053,14 +2002,13 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
* put in place to ensure correct forward compatibility options
* when newer hardware variants come along.
*/
if (ver->hw_variant != 0x0b) {
if (ver.hw_variant != 0x0b) {
BT_ERR("%s: Unsupported Intel hardware variant (%u)",
hdev->name, ver->hw_variant);
kfree_skb(skb);
hdev->name, ver.hw_variant);
return -EINVAL;
}
btintel_version_info(hdev, ver);
btintel_version_info(hdev, &ver);
/* The firmware variant determines if the device is in bootloader
* mode or is running operational firmware. The value 0x06 identifies
@ -2075,8 +2023,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
* It is not possible to use the Secure Boot Parameters in this
* case since that command is only available in bootloader mode.
*/
if (ver->fw_variant == 0x23) {
kfree_skb(skb);
if (ver.fw_variant == 0x23) {
clear_bit(BTUSB_BOOTLOADER, &data->flags);
btintel_check_bdaddr(hdev);
return 0;
@ -2085,15 +2032,12 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
/* If the device is not in bootloader mode, then the only possible
* choice is to return an error and abort the device initialization.
*/
if (ver->fw_variant != 0x06) {
if (ver.fw_variant != 0x06) {
BT_ERR("%s: Unsupported Intel firmware variant (%u)",
hdev->name, ver->fw_variant);
kfree_skb(skb);
hdev->name, ver.fw_variant);
return -ENODEV;
}
kfree_skb(skb);
/* Read the secure boot parameters to identify the operating
* details of the bootloader.
*/

View File

@ -249,10 +249,10 @@ static int ti_st_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
hst = hci_get_drvdata(hdev);
/* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type,
skb->len);
BT_DBG("%s: type %d len %d", hdev->name, hci_skb_pkt_type(skb),
skb->len);
/* Insert skb to shared transport layer's transmit queue.
* Freeing skb memory is taken care in shared transport layer,
@ -268,7 +268,7 @@ static int ti_st_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
/* ST accepted our skb. So, Go ahead and do rest */
hdev->stat.byte_tx += len;
ti_st_tx_complete(hst, bt_cb(skb)->pkt_type);
ti_st_tx_complete(hst, hci_skb_pkt_type(skb));
return 0;
}

View File

@ -239,7 +239,7 @@ static void dtl1_receive(struct dtl1_info *info)
info->rx_count = nsh->len + (nsh->len & 0x0001);
break;
case RECV_WAIT_DATA:
bt_cb(info->rx_skb)->pkt_type = nsh->type;
hci_skb_pkt_type(info->rx_skb) = nsh->type;
/* remove PAD byte if it exists */
if (nsh->len & 0x0001) {
@ -250,7 +250,7 @@ static void dtl1_receive(struct dtl1_info *info)
/* remove NSH */
skb_pull(info->rx_skb, NSHL);
switch (bt_cb(info->rx_skb)->pkt_type) {
switch (hci_skb_pkt_type(info->rx_skb)) {
case 0x80:
/* control data for the Nokia Card */
dtl1_control(info, info->rx_skb);
@ -259,12 +259,13 @@ static void dtl1_receive(struct dtl1_info *info)
case 0x83:
case 0x84:
/* send frame to the HCI layer */
bt_cb(info->rx_skb)->pkt_type &= 0x0f;
hci_skb_pkt_type(info->rx_skb) &= 0x0f;
hci_recv_frame(info->hdev, info->rx_skb);
break;
default:
/* unknown packet */
BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
BT_ERR("Unknown HCI packet with type 0x%02x received",
hci_skb_pkt_type(info->rx_skb));
kfree_skb(info->rx_skb);
break;
}
@ -386,7 +387,7 @@ static int dtl1_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
struct sk_buff *s;
struct nsh nsh;
switch (bt_cb(skb)->pkt_type) {
switch (hci_skb_pkt_type(skb)) {
case HCI_COMMAND_PKT:
hdev->stat.cmd_tx++;
nsh.type = 0x81;

View File

@ -205,7 +205,7 @@ static int ath_enqueue(struct hci_uart *hu, struct sk_buff *skb)
{
struct ath_struct *ath = hu->priv;
if (bt_cb(skb)->pkt_type == HCI_SCODATA_PKT) {
if (hci_skb_pkt_type(skb) == HCI_SCODATA_PKT) {
kfree_skb(skb);
return 0;
}
@ -213,7 +213,7 @@ static int ath_enqueue(struct hci_uart *hu, struct sk_buff *skb)
/* Update power management enable flag with parameters of
* HCI sleep enable vendor specific HCI command.
*/
if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
if (hci_skb_pkt_type(skb) == HCI_COMMAND_PKT) {
struct hci_command_hdr *hdr = (void *)skb->data;
if (__le16_to_cpu(hdr->opcode) == HCI_OP_ATH_SLEEP)
@ -223,7 +223,7 @@ static int ath_enqueue(struct hci_uart *hu, struct sk_buff *skb)
BT_DBG("hu %p skb %p", hu, skb);
/* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
skb_queue_tail(&ath->txq, skb);
set_bit(HCI_UART_SENDING, &hu->tx_state);

View File

@ -472,7 +472,7 @@ static int bcm_enqueue(struct hci_uart *hu, struct sk_buff *skb)
bt_dev_dbg(hu->hdev, "hu %p skb %p", hu, skb);
/* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
skb_queue_tail(&bcm->txq, skb);
return 0;
@ -814,8 +814,16 @@ static const struct hci_uart_proto bcm_proto = {
#ifdef CONFIG_ACPI
static const struct acpi_device_id bcm_acpi_match[] = {
{ "BCM2E1A", 0 },
{ "BCM2E39", 0 },
{ "BCM2E3A", 0 },
{ "BCM2E3D", 0 },
{ "BCM2E3F", 0 },
{ "BCM2E40", 0 },
{ "BCM2E64", 0 },
{ "BCM2E65", 0 },
{ "BCM2E67", 0 },
{ "BCM2E7B", 0 },
{ },
};
MODULE_DEVICE_TABLE(acpi, bcm_acpi_match);

View File

@ -155,7 +155,7 @@ static int bcsp_enqueue(struct hci_uart *hu, struct sk_buff *skb)
return 0;
}
switch (bt_cb(skb)->pkt_type) {
switch (hci_skb_pkt_type(skb)) {
case HCI_ACLDATA_PKT:
case HCI_COMMAND_PKT:
skb_queue_tail(&bcsp->rel, skb);
@ -231,7 +231,7 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
if (!nskb)
return NULL;
bt_cb(nskb)->pkt_type = pkt_type;
hci_skb_pkt_type(nskb) = pkt_type;
bcsp_slip_msgdelim(nskb);
@ -291,7 +291,10 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu)
skb = skb_dequeue(&bcsp->unrel);
if (skb != NULL) {
struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, bt_cb(skb)->pkt_type);
struct sk_buff *nskb;
nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len,
hci_skb_pkt_type(skb));
if (nskb) {
kfree_skb(skb);
return nskb;
@ -310,8 +313,10 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu)
if (bcsp->unack.qlen < BCSP_TXWINSIZE) {
skb = skb_dequeue(&bcsp->rel);
if (skb != NULL) {
struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len,
bt_cb(skb)->pkt_type);
struct sk_buff *nskb;
nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len,
hci_skb_pkt_type(skb));
if (nskb) {
__skb_queue_tail(&bcsp->unack, skb);
mod_timer(&bcsp->tbcsp, jiffies + HZ / 4);
@ -412,7 +417,7 @@ static void bcsp_handle_le_pkt(struct hci_uart *hu)
if (!nskb)
return;
memcpy(skb_put(nskb, 4), conf_rsp_pkt, 4);
bt_cb(nskb)->pkt_type = BCSP_LE_PKT;
hci_skb_pkt_type(nskb) = BCSP_LE_PKT;
skb_queue_head(&bcsp->unrel, nskb);
hci_uart_tx_wakeup(hu);
@ -494,14 +499,14 @@ static void bcsp_complete_rx_pkt(struct hci_uart *hu)
bcsp_pkt_cull(bcsp);
if ((bcsp->rx_skb->data[1] & 0x0f) == 6 &&
bcsp->rx_skb->data[0] & 0x80) {
bt_cb(bcsp->rx_skb)->pkt_type = HCI_ACLDATA_PKT;
hci_skb_pkt_type(bcsp->rx_skb) = HCI_ACLDATA_PKT;
pass_up = 1;
} else if ((bcsp->rx_skb->data[1] & 0x0f) == 5 &&
bcsp->rx_skb->data[0] & 0x80) {
bt_cb(bcsp->rx_skb)->pkt_type = HCI_EVENT_PKT;
hci_skb_pkt_type(bcsp->rx_skb) = HCI_EVENT_PKT;
pass_up = 1;
} else if ((bcsp->rx_skb->data[1] & 0x0f) == 7) {
bt_cb(bcsp->rx_skb)->pkt_type = HCI_SCODATA_PKT;
hci_skb_pkt_type(bcsp->rx_skb) = HCI_SCODATA_PKT;
pass_up = 1;
} else if ((bcsp->rx_skb->data[1] & 0x0f) == 1 &&
!(bcsp->rx_skb->data[0] & 0x80)) {
@ -523,7 +528,7 @@ static void bcsp_complete_rx_pkt(struct hci_uart *hu)
hdr.evt = 0xff;
hdr.plen = bcsp->rx_skb->len;
memcpy(skb_push(bcsp->rx_skb, HCI_EVENT_HDR_SIZE), &hdr, HCI_EVENT_HDR_SIZE);
bt_cb(bcsp->rx_skb)->pkt_type = HCI_EVENT_PKT;
hci_skb_pkt_type(bcsp->rx_skb) = HCI_EVENT_PKT;
hci_recv_frame(hu->hdev, bcsp->rx_skb);
} else {

View File

@ -108,7 +108,7 @@ static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb)
BT_DBG("hu %p skb %p", hu, skb);
/* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
skb_queue_tail(&h4->txq, skb);
return 0;
@ -184,8 +184,8 @@ struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb,
if (!skb)
return ERR_PTR(-ENOMEM);
bt_cb(skb)->pkt_type = (&pkts[i])->type;
bt_cb(skb)->expect = (&pkts[i])->hlen;
hci_skb_pkt_type(skb) = (&pkts[i])->type;
hci_skb_expect(skb) = (&pkts[i])->hlen;
break;
}
@ -197,18 +197,18 @@ struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb,
buffer += 1;
}
len = min_t(uint, bt_cb(skb)->expect - skb->len, count);
len = min_t(uint, hci_skb_expect(skb) - skb->len, count);
memcpy(skb_put(skb, len), buffer, len);
count -= len;
buffer += len;
/* Check for partial packet */
if (skb->len < bt_cb(skb)->expect)
if (skb->len < hci_skb_expect(skb))
continue;
for (i = 0; i < pkts_count; i++) {
if (bt_cb(skb)->pkt_type == (&pkts[i])->type)
if (hci_skb_pkt_type(skb) == (&pkts[i])->type)
break;
}
@ -228,7 +228,7 @@ struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb,
case 1:
/* Single octet variable length */
dlen = skb->data[(&pkts[i])->loff];
bt_cb(skb)->expect += dlen;
hci_skb_expect(skb) += dlen;
if (skb_tailroom(skb) < dlen) {
kfree_skb(skb);
@ -239,7 +239,7 @@ struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb,
/* Double octet variable length */
dlen = get_unaligned_le16(skb->data +
(&pkts[i])->loff);
bt_cb(skb)->expect += dlen;
hci_skb_expect(skb) += dlen;
if (skb_tailroom(skb) < dlen) {
kfree_skb(skb);

View File

@ -51,7 +51,7 @@
#define H5_HDR_CRC(hdr) (((hdr)[0] >> 6) & 0x01)
#define H5_HDR_RELIABLE(hdr) (((hdr)[0] >> 7) & 0x01)
#define H5_HDR_PKT_TYPE(hdr) ((hdr)[1] & 0x0f)
#define H5_HDR_LEN(hdr) ((((hdr)[1] >> 4) & 0xff) + ((hdr)[2] << 4))
#define H5_HDR_LEN(hdr) ((((hdr)[1] >> 4) & 0x0f) + ((hdr)[2] << 4))
#define SLIP_DELIMITER 0xc0
#define SLIP_ESC 0xdb
@ -107,7 +107,7 @@ static void h5_link_control(struct hci_uart *hu, const void *data, size_t len)
if (!nskb)
return;
bt_cb(nskb)->pkt_type = HCI_3WIRE_LINK_PKT;
hci_skb_pkt_type(nskb) = HCI_3WIRE_LINK_PKT;
memcpy(skb_put(nskb, len), data, len);
@ -116,18 +116,14 @@ static void h5_link_control(struct hci_uart *hu, const void *data, size_t len)
static u8 h5_cfg_field(struct h5 *h5)
{
u8 field = 0;
/* Sliding window size (first 3 bits) */
field |= (h5->tx_win & 7);
return field;
return h5->tx_win & 0x07;
}
static void h5_timed_event(unsigned long arg)
{
const unsigned char sync_req[] = { 0x01, 0x7e };
unsigned char conf_req[] = { 0x03, 0xfc, 0x01 };
unsigned char conf_req[3] = { 0x03, 0xfc };
struct hci_uart *hu = (struct hci_uart *)arg;
struct h5 *h5 = hu->priv;
struct sk_buff *skb;
@ -285,7 +281,7 @@ static void h5_handle_internal_rx(struct hci_uart *hu)
struct h5 *h5 = hu->priv;
const unsigned char sync_req[] = { 0x01, 0x7e };
const unsigned char sync_rsp[] = { 0x02, 0x7d };
unsigned char conf_req[] = { 0x03, 0xfc, 0x01 };
unsigned char conf_req[3] = { 0x03, 0xfc };
const unsigned char conf_rsp[] = { 0x04, 0x7b };
const unsigned char wakeup_req[] = { 0x05, 0xfa };
const unsigned char woken_req[] = { 0x06, 0xf9 };
@ -317,7 +313,7 @@ static void h5_handle_internal_rx(struct hci_uart *hu)
h5_link_control(hu, conf_req, 3);
} else if (memcmp(data, conf_rsp, 2) == 0) {
if (H5_HDR_LEN(hdr) > 2)
h5->tx_win = (data[2] & 7);
h5->tx_win = (data[2] & 0x07);
BT_DBG("Three-wire init complete. tx_win %u", h5->tx_win);
h5->state = H5_ACTIVE;
hci_uart_init_ready(hu);
@ -360,7 +356,7 @@ static void h5_complete_rx_pkt(struct hci_uart *hu)
case HCI_EVENT_PKT:
case HCI_ACLDATA_PKT:
case HCI_SCODATA_PKT:
bt_cb(h5->rx_skb)->pkt_type = H5_HDR_PKT_TYPE(hdr);
hci_skb_pkt_type(h5->rx_skb) = H5_HDR_PKT_TYPE(hdr);
/* Remove Three-wire header */
skb_pull(h5->rx_skb, 4);
@ -562,7 +558,7 @@ static int h5_enqueue(struct hci_uart *hu, struct sk_buff *skb)
return 0;
}
switch (bt_cb(skb)->pkt_type) {
switch (hci_skb_pkt_type(skb)) {
case HCI_ACLDATA_PKT:
case HCI_COMMAND_PKT:
skb_queue_tail(&h5->rel, skb);
@ -573,7 +569,7 @@ static int h5_enqueue(struct hci_uart *hu, struct sk_buff *skb)
break;
default:
BT_ERR("Unknown packet type %u", bt_cb(skb)->pkt_type);
BT_ERR("Unknown packet type %u", hci_skb_pkt_type(skb));
kfree_skb(skb);
break;
}
@ -642,7 +638,7 @@ static struct sk_buff *h5_prepare_pkt(struct hci_uart *hu, u8 pkt_type,
if (!nskb)
return NULL;
bt_cb(nskb)->pkt_type = pkt_type;
hci_skb_pkt_type(nskb) = pkt_type;
h5_slip_delim(nskb);
@ -697,7 +693,7 @@ static struct sk_buff *h5_dequeue(struct hci_uart *hu)
skb = skb_dequeue(&h5->unrel);
if (skb) {
nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type,
nskb = h5_prepare_pkt(hu, hci_skb_pkt_type(skb),
skb->data, skb->len);
if (nskb) {
kfree_skb(skb);
@ -715,7 +711,7 @@ static struct sk_buff *h5_dequeue(struct hci_uart *hu)
skb = skb_dequeue(&h5->rel);
if (skb) {
nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type,
nskb = h5_prepare_pkt(hu, hci_skb_pkt_type(skb),
skb->data, skb->len);
if (nskb) {
__skb_queue_tail(&h5->unack, skb);

View File

@ -186,7 +186,7 @@ static int intel_lpm_suspend(struct hci_uart *hu)
}
memcpy(skb_put(skb, sizeof(suspend)), suspend, sizeof(suspend));
bt_cb(skb)->pkt_type = HCI_LPM_PKT;
hci_skb_pkt_type(skb) = HCI_LPM_PKT;
set_bit(STATE_LPM_TRANSACTION, &intel->flags);
@ -230,7 +230,7 @@ static int intel_lpm_resume(struct hci_uart *hu)
return -ENOMEM;
}
bt_cb(skb)->pkt_type = HCI_LPM_WAKE_PKT;
hci_skb_pkt_type(skb) = HCI_LPM_WAKE_PKT;
set_bit(STATE_LPM_TRANSACTION, &intel->flags);
@ -272,7 +272,7 @@ static int intel_lpm_host_wake(struct hci_uart *hu)
memcpy(skb_put(skb, sizeof(lpm_resume_ack)), lpm_resume_ack,
sizeof(lpm_resume_ack));
bt_cb(skb)->pkt_type = HCI_LPM_PKT;
hci_skb_pkt_type(skb) = HCI_LPM_PKT;
/* LPM flow is a priority, enqueue packet at list head */
skb_queue_head(&intel->txq, skb);
@ -467,7 +467,7 @@ static int inject_cmd_complete(struct hci_dev *hdev, __u16 opcode)
*skb_put(skb, 1) = 0x00;
bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
return hci_recv_frame(hdev, skb);
}
@ -502,7 +502,7 @@ static int intel_set_baudrate(struct hci_uart *hu, unsigned int speed)
/* Device will not accept speed change if Intel version has not been
* previously requested.
*/
skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_INIT_TIMEOUT);
skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) {
bt_dev_err(hdev, "Reading Intel version information failed (%ld)",
PTR_ERR(skb));
@ -517,7 +517,7 @@ static int intel_set_baudrate(struct hci_uart *hu, unsigned int speed)
}
memcpy(skb_put(skb, sizeof(speed_cmd)), speed_cmd, sizeof(speed_cmd));
bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
hci_skb_pkt_type(skb) = HCI_COMMAND_PKT;
hci_uart_set_flow_control(hu, true);
@ -542,7 +542,7 @@ static int intel_setup(struct hci_uart *hu)
struct intel_device *idev = NULL;
struct hci_dev *hdev = hu->hdev;
struct sk_buff *skb;
struct intel_version *ver;
struct intel_version ver;
struct intel_boot_params *params;
struct list_head *p;
const struct firmware *fw;
@ -590,35 +590,16 @@ static int intel_setup(struct hci_uart *hu)
* is in bootloader mode or if it already has operational firmware
* loaded.
*/
skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
bt_dev_err(hdev, "Reading Intel version information failed (%ld)",
PTR_ERR(skb));
return PTR_ERR(skb);
}
if (skb->len != sizeof(*ver)) {
bt_dev_err(hdev, "Intel version event size mismatch");
kfree_skb(skb);
return -EILSEQ;
}
ver = (struct intel_version *)skb->data;
if (ver->status) {
bt_dev_err(hdev, "Intel version command failure (%02x)",
ver->status);
err = -bt_to_errno(ver->status);
kfree_skb(skb);
err = btintel_read_version(hdev, &ver);
if (err)
return err;
}
/* The hardware platform number has a fixed value of 0x37 and
* for now only accept this single value.
*/
if (ver->hw_platform != 0x37) {
if (ver.hw_platform != 0x37) {
bt_dev_err(hdev, "Unsupported Intel hardware platform (%u)",
ver->hw_platform);
kfree_skb(skb);
ver.hw_platform);
return -EINVAL;
}
@ -627,14 +608,13 @@ static int intel_setup(struct hci_uart *hu)
* put in place to ensure correct forward compatibility options
* when newer hardware variants come along.
*/
if (ver->hw_variant != 0x0b) {
if (ver.hw_variant != 0x0b) {
bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)",
ver->hw_variant);
kfree_skb(skb);
ver.hw_variant);
return -EINVAL;
}
btintel_version_info(hdev, ver);
btintel_version_info(hdev, &ver);
/* The firmware variant determines if the device is in bootloader
* mode or is running operational firmware. The value 0x06 identifies
@ -649,8 +629,7 @@ static int intel_setup(struct hci_uart *hu)
* It is not possible to use the Secure Boot Parameters in this
* case since that command is only available in bootloader mode.
*/
if (ver->fw_variant == 0x23) {
kfree_skb(skb);
if (ver.fw_variant == 0x23) {
clear_bit(STATE_BOOTLOADER, &intel->flags);
btintel_check_bdaddr(hdev);
return 0;
@ -659,19 +638,16 @@ static int intel_setup(struct hci_uart *hu)
/* If the device is not in bootloader mode, then the only possible
* choice is to return an error and abort the device initialization.
*/
if (ver->fw_variant != 0x06) {
if (ver.fw_variant != 0x06) {
bt_dev_err(hdev, "Unsupported Intel firmware variant (%u)",
ver->fw_variant);
kfree_skb(skb);
ver.fw_variant);
return -ENODEV;
}
kfree_skb(skb);
/* Read the secure boot parameters to identify the operating
* details of the bootloader.
*/
skb = __hci_cmd_sync(hdev, 0xfc0d, 0, NULL, HCI_INIT_TIMEOUT);
skb = __hci_cmd_sync(hdev, 0xfc0d, 0, NULL, HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) {
bt_dev_err(hdev, "Reading Intel boot parameters failed (%ld)",
PTR_ERR(skb));
@ -881,7 +857,7 @@ done:
set_bit(STATE_BOOTING, &intel->flags);
skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(reset_param), reset_param,
HCI_INIT_TIMEOUT);
HCI_CMD_TIMEOUT);
if (IS_ERR(skb))
return PTR_ERR(skb);
@ -1126,7 +1102,7 @@ static struct sk_buff *intel_dequeue(struct hci_uart *hu)
return skb;
if (test_bit(STATE_BOOTLOADER, &intel->flags) &&
(bt_cb(skb)->pkt_type == HCI_COMMAND_PKT)) {
(hci_skb_pkt_type(skb) == HCI_COMMAND_PKT)) {
struct hci_command_hdr *cmd = (void *)skb->data;
__u16 opcode = le16_to_cpu(cmd->opcode);
@ -1140,7 +1116,7 @@ static struct sk_buff *intel_dequeue(struct hci_uart *hu)
}
/* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
return skb;
}

View File

@ -162,7 +162,7 @@ restart:
break;
}
hci_uart_tx_complete(hu, bt_cb(skb)->pkt_type);
hci_uart_tx_complete(hu, hci_skb_pkt_type(skb));
kfree_skb(skb);
}
@ -248,7 +248,8 @@ static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_uart *hu = hci_get_drvdata(hdev);
BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);
BT_DBG("%s: type %d len %d", hdev->name, hci_skb_pkt_type(skb),
skb->len);
hu->proto->enqueue(hu, skb);
@ -461,13 +462,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
INIT_WORK(&hu->init_ready, hci_uart_init_work);
INIT_WORK(&hu->write_work, hci_uart_write_work);
/* Flush any pending characters in the driver and line discipline. */
/* FIXME: why is this needed. Note don't use ldisc_ref here as the
open path is before the ldisc is referencable */
if (tty->ldisc->ops->flush_buffer)
tty->ldisc->ops->flush_buffer(tty);
/* Flush any pending characters in the driver */
tty_driver_flush_buffer(tty);
return 0;

View File

@ -307,7 +307,7 @@ static int ll_enqueue(struct hci_uart *hu, struct sk_buff *skb)
BT_DBG("hu %p skb %p", hu, skb);
/* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
/* lock hcill state */
spin_lock_irqsave(&ll->hcill_lock, flags);
@ -493,7 +493,7 @@ static int ll_recv(struct hci_uart *hu, const void *data, int count)
return -ENOMEM;
}
bt_cb(ll->rx_skb)->pkt_type = type;
hci_skb_pkt_type(ll->rx_skb) = type;
}
return count;

View File

@ -678,7 +678,7 @@ static int qca_enqueue(struct hci_uart *hu, struct sk_buff *skb)
qca->tx_ibs_state);
/* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
/* Don't go to sleep in middle of patch download or
* Out-Of-Band(GPIOs control) sleep is selected.
@ -873,7 +873,7 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate)
/* Assign commands to change baudrate and packet type. */
memcpy(skb_put(skb, sizeof(cmd)), cmd, sizeof(cmd));
bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
hci_skb_pkt_type(skb) = HCI_COMMAND_PKT;
skb_queue_tail(&qca->txq, skb);
hci_uart_tx_wakeup(hu);

View File

@ -80,7 +80,7 @@ static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
{
struct vhci_data *data = hci_get_drvdata(hdev);
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
skb_queue_tail(&data->readq, skb);
wake_up_interruptible(&data->read_wait);
@ -140,7 +140,7 @@ static int vhci_create_device(struct vhci_data *data, __u8 opcode)
return -EBUSY;
}
bt_cb(skb)->pkt_type = HCI_VENDOR_PKT;
hci_skb_pkt_type(skb) = HCI_VENDOR_PKT;
*skb_put(skb, 1) = 0xff;
*skb_put(skb, 1) = opcode;
@ -183,7 +183,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
return -ENODEV;
}
bt_cb(skb)->pkt_type = pkt_type;
hci_skb_pkt_type(skb) = pkt_type;
ret = hci_recv_frame(data->hdev, skb);
break;
@ -234,7 +234,7 @@ static inline ssize_t vhci_put_user(struct vhci_data *data,
data->hdev->stat.byte_tx += len;
switch (bt_cb(skb)->pkt_type) {
switch (hci_skb_pkt_type(skb)) {
case HCI_COMMAND_PKT:
data->hdev->stat.cmd_tx++;
break;

View File

@ -40,6 +40,7 @@
#include <linux/gfp.h>
#include <rdma/ib_pma.h>
#include <linux/mlx4/driver.h>
#include "mlx4_ib.h"
enum {
@ -606,8 +607,8 @@ static int mlx4_ib_demux_mad(struct ib_device *ibdev, u8 port,
struct ib_mad *mad)
{
struct mlx4_ib_dev *dev = to_mdev(ibdev);
int err;
int slave;
int err, other_port;
int slave = -1;
u8 *slave_id;
int is_eth = 0;
@ -625,7 +626,17 @@ static int mlx4_ib_demux_mad(struct ib_device *ibdev, u8 port,
mlx4_ib_warn(ibdev, "RoCE mgmt class is not CM\n");
return -EINVAL;
}
if (mlx4_get_slave_from_roce_gid(dev->dev, port, grh->dgid.raw, &slave)) {
err = mlx4_get_slave_from_roce_gid(dev->dev, port, grh->dgid.raw, &slave);
if (err && mlx4_is_mf_bonded(dev->dev)) {
other_port = (port == 1) ? 2 : 1;
err = mlx4_get_slave_from_roce_gid(dev->dev, other_port, grh->dgid.raw, &slave);
if (!err) {
port = other_port;
pr_debug("resolved slave %d from gid %pI6 wire port %d other %d\n",
slave, grh->dgid.raw, port, other_port);
}
}
if (err) {
mlx4_ib_warn(ibdev, "failed matching grh\n");
return -ENOENT;
}

View File

@ -43,6 +43,9 @@
#include <linux/mlx5/vport.h>
#include <rdma/ib_smi.h>
#include <rdma/ib_umem.h>
#include <linux/in.h>
#include <linux/etherdevice.h>
#include <linux/mlx5/fs.h>
#include "user.h"
#include "mlx5_ib.h"
@ -835,6 +838,457 @@ static int mlx5_ib_dealloc_pd(struct ib_pd *pd)
return 0;
}
static bool outer_header_zero(u32 *match_criteria)
{
int size = MLX5_ST_SZ_BYTES(fte_match_param);
char *outer_headers_c = MLX5_ADDR_OF(fte_match_param, match_criteria,
outer_headers);
return outer_headers_c[0] == 0 && !memcmp(outer_headers_c,
outer_headers_c + 1,
size - 1);
}
static int parse_flow_attr(u32 *match_c, u32 *match_v,
union ib_flow_spec *ib_spec)
{
void *outer_headers_c = MLX5_ADDR_OF(fte_match_param, match_c,
outer_headers);
void *outer_headers_v = MLX5_ADDR_OF(fte_match_param, match_v,
outer_headers);
switch (ib_spec->type) {
case IB_FLOW_SPEC_ETH:
if (ib_spec->size != sizeof(ib_spec->eth))
return -EINVAL;
ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_c,
dmac_47_16),
ib_spec->eth.mask.dst_mac);
ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_v,
dmac_47_16),
ib_spec->eth.val.dst_mac);
if (ib_spec->eth.mask.vlan_tag) {
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c,
vlan_tag, 1);
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v,
vlan_tag, 1);
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c,
first_vid, ntohs(ib_spec->eth.mask.vlan_tag));
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v,
first_vid, ntohs(ib_spec->eth.val.vlan_tag));
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c,
first_cfi,
ntohs(ib_spec->eth.mask.vlan_tag) >> 12);
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v,
first_cfi,
ntohs(ib_spec->eth.val.vlan_tag) >> 12);
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c,
first_prio,
ntohs(ib_spec->eth.mask.vlan_tag) >> 13);
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v,
first_prio,
ntohs(ib_spec->eth.val.vlan_tag) >> 13);
}
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c,
ethertype, ntohs(ib_spec->eth.mask.ether_type));
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v,
ethertype, ntohs(ib_spec->eth.val.ether_type));
break;
case IB_FLOW_SPEC_IPV4:
if (ib_spec->size != sizeof(ib_spec->ipv4))
return -EINVAL;
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c,
ethertype, 0xffff);
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v,
ethertype, ETH_P_IP);
memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_c,
src_ipv4_src_ipv6.ipv4_layout.ipv4),
&ib_spec->ipv4.mask.src_ip,
sizeof(ib_spec->ipv4.mask.src_ip));
memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_v,
src_ipv4_src_ipv6.ipv4_layout.ipv4),
&ib_spec->ipv4.val.src_ip,
sizeof(ib_spec->ipv4.val.src_ip));
memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_c,
dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
&ib_spec->ipv4.mask.dst_ip,
sizeof(ib_spec->ipv4.mask.dst_ip));
memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_v,
dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
&ib_spec->ipv4.val.dst_ip,
sizeof(ib_spec->ipv4.val.dst_ip));
break;
case IB_FLOW_SPEC_TCP:
if (ib_spec->size != sizeof(ib_spec->tcp_udp))
return -EINVAL;
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c, ip_protocol,
0xff);
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v, ip_protocol,
IPPROTO_TCP);
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c, tcp_sport,
ntohs(ib_spec->tcp_udp.mask.src_port));
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v, tcp_sport,
ntohs(ib_spec->tcp_udp.val.src_port));
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c, tcp_dport,
ntohs(ib_spec->tcp_udp.mask.dst_port));
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v, tcp_dport,
ntohs(ib_spec->tcp_udp.val.dst_port));
break;
case IB_FLOW_SPEC_UDP:
if (ib_spec->size != sizeof(ib_spec->tcp_udp))
return -EINVAL;
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c, ip_protocol,
0xff);
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v, ip_protocol,
IPPROTO_UDP);
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c, udp_sport,
ntohs(ib_spec->tcp_udp.mask.src_port));
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v, udp_sport,
ntohs(ib_spec->tcp_udp.val.src_port));
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c, udp_dport,
ntohs(ib_spec->tcp_udp.mask.dst_port));
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v, udp_dport,
ntohs(ib_spec->tcp_udp.val.dst_port));
break;
default:
return -EINVAL;
}
return 0;
}
/* If a flow could catch both multicast and unicast packets,
* it won't fall into the multicast flow steering table and this rule
* could steal other multicast packets.
*/
static bool flow_is_multicast_only(struct ib_flow_attr *ib_attr)
{
struct ib_flow_spec_eth *eth_spec;
if (ib_attr->type != IB_FLOW_ATTR_NORMAL ||
ib_attr->size < sizeof(struct ib_flow_attr) +
sizeof(struct ib_flow_spec_eth) ||
ib_attr->num_of_specs < 1)
return false;
eth_spec = (struct ib_flow_spec_eth *)(ib_attr + 1);
if (eth_spec->type != IB_FLOW_SPEC_ETH ||
eth_spec->size != sizeof(*eth_spec))
return false;
return is_multicast_ether_addr(eth_spec->mask.dst_mac) &&
is_multicast_ether_addr(eth_spec->val.dst_mac);
}
static bool is_valid_attr(struct ib_flow_attr *flow_attr)
{
union ib_flow_spec *ib_spec = (union ib_flow_spec *)(flow_attr + 1);
bool has_ipv4_spec = false;
bool eth_type_ipv4 = true;
unsigned int spec_index;
/* Validate that ethertype is correct */
for (spec_index = 0; spec_index < flow_attr->num_of_specs; spec_index++) {
if (ib_spec->type == IB_FLOW_SPEC_ETH &&
ib_spec->eth.mask.ether_type) {
if (!((ib_spec->eth.mask.ether_type == htons(0xffff)) &&
ib_spec->eth.val.ether_type == htons(ETH_P_IP)))
eth_type_ipv4 = false;
} else if (ib_spec->type == IB_FLOW_SPEC_IPV4) {
has_ipv4_spec = true;
}
ib_spec = (void *)ib_spec + ib_spec->size;
}
return !has_ipv4_spec || eth_type_ipv4;
}
static void put_flow_table(struct mlx5_ib_dev *dev,
struct mlx5_ib_flow_prio *prio, bool ft_added)
{
prio->refcount -= !!ft_added;
if (!prio->refcount) {
mlx5_destroy_flow_table(prio->flow_table);
prio->flow_table = NULL;
}
}
static int mlx5_ib_destroy_flow(struct ib_flow *flow_id)
{
struct mlx5_ib_dev *dev = to_mdev(flow_id->qp->device);
struct mlx5_ib_flow_handler *handler = container_of(flow_id,
struct mlx5_ib_flow_handler,
ibflow);
struct mlx5_ib_flow_handler *iter, *tmp;
mutex_lock(&dev->flow_db.lock);
list_for_each_entry_safe(iter, tmp, &handler->list, list) {
mlx5_del_flow_rule(iter->rule);
list_del(&iter->list);
kfree(iter);
}
mlx5_del_flow_rule(handler->rule);
put_flow_table(dev, &dev->flow_db.prios[handler->prio], true);
mutex_unlock(&dev->flow_db.lock);
kfree(handler);
return 0;
}
#define MLX5_FS_MAX_TYPES 10
#define MLX5_FS_MAX_ENTRIES 32000UL
static struct mlx5_ib_flow_prio *get_flow_table(struct mlx5_ib_dev *dev,
struct ib_flow_attr *flow_attr)
{
struct mlx5_flow_namespace *ns = NULL;
struct mlx5_ib_flow_prio *prio;
struct mlx5_flow_table *ft;
int num_entries;
int num_groups;
int priority;
int err = 0;
if (flow_attr->type == IB_FLOW_ATTR_NORMAL) {
if (flow_is_multicast_only(flow_attr))
priority = MLX5_IB_FLOW_MCAST_PRIO;
else
priority = flow_attr->priority;
ns = mlx5_get_flow_namespace(dev->mdev,
MLX5_FLOW_NAMESPACE_BYPASS);
num_entries = MLX5_FS_MAX_ENTRIES;
num_groups = MLX5_FS_MAX_TYPES;
prio = &dev->flow_db.prios[priority];
} else if (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT ||
flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT) {
ns = mlx5_get_flow_namespace(dev->mdev,
MLX5_FLOW_NAMESPACE_LEFTOVERS);
build_leftovers_ft_param(&priority,
&num_entries,
&num_groups);
prio = &dev->flow_db.prios[MLX5_IB_FLOW_LEFTOVERS_PRIO];
}
if (!ns)
return ERR_PTR(-ENOTSUPP);
ft = prio->flow_table;
if (!ft) {
ft = mlx5_create_auto_grouped_flow_table(ns, priority,
num_entries,
num_groups);
if (!IS_ERR(ft)) {
prio->refcount = 0;
prio->flow_table = ft;
} else {
err = PTR_ERR(ft);
}
}
return err ? ERR_PTR(err) : prio;
}
static struct mlx5_ib_flow_handler *create_flow_rule(struct mlx5_ib_dev *dev,
struct mlx5_ib_flow_prio *ft_prio,
struct ib_flow_attr *flow_attr,
struct mlx5_flow_destination *dst)
{
struct mlx5_flow_table *ft = ft_prio->flow_table;
struct mlx5_ib_flow_handler *handler;
void *ib_flow = flow_attr + 1;
u8 match_criteria_enable = 0;
unsigned int spec_index;
u32 *match_c;
u32 *match_v;
int err = 0;
if (!is_valid_attr(flow_attr))
return ERR_PTR(-EINVAL);
match_c = kzalloc(MLX5_ST_SZ_BYTES(fte_match_param), GFP_KERNEL);
match_v = kzalloc(MLX5_ST_SZ_BYTES(fte_match_param), GFP_KERNEL);
handler = kzalloc(sizeof(*handler), GFP_KERNEL);
if (!handler || !match_c || !match_v) {
err = -ENOMEM;
goto free;
}
INIT_LIST_HEAD(&handler->list);
for (spec_index = 0; spec_index < flow_attr->num_of_specs; spec_index++) {
err = parse_flow_attr(match_c, match_v, ib_flow);
if (err < 0)
goto free;
ib_flow += ((union ib_flow_spec *)ib_flow)->size;
}
/* Outer header support only */
match_criteria_enable = (!outer_header_zero(match_c)) << 0;
handler->rule = mlx5_add_flow_rule(ft, match_criteria_enable,
match_c, match_v,
MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
MLX5_FS_DEFAULT_FLOW_TAG,
dst);
if (IS_ERR(handler->rule)) {
err = PTR_ERR(handler->rule);
goto free;
}
handler->prio = ft_prio - dev->flow_db.prios;
ft_prio->flow_table = ft;
free:
if (err)
kfree(handler);
kfree(match_c);
kfree(match_v);
return err ? ERR_PTR(err) : handler;
}
enum {
LEFTOVERS_MC,
LEFTOVERS_UC,
};
static struct mlx5_ib_flow_handler *create_leftovers_rule(struct mlx5_ib_dev *dev,
struct mlx5_ib_flow_prio *ft_prio,
struct ib_flow_attr *flow_attr,
struct mlx5_flow_destination *dst)
{
struct mlx5_ib_flow_handler *handler_ucast = NULL;
struct mlx5_ib_flow_handler *handler = NULL;
static struct {
struct ib_flow_attr flow_attr;
struct ib_flow_spec_eth eth_flow;
} leftovers_specs[] = {
[LEFTOVERS_MC] = {
.flow_attr = {
.num_of_specs = 1,
.size = sizeof(leftovers_specs[0])
},
.eth_flow = {
.type = IB_FLOW_SPEC_ETH,
.size = sizeof(struct ib_flow_spec_eth),
.mask = {.dst_mac = {0x1} },
.val = {.dst_mac = {0x1} }
}
},
[LEFTOVERS_UC] = {
.flow_attr = {
.num_of_specs = 1,
.size = sizeof(leftovers_specs[0])
},
.eth_flow = {
.type = IB_FLOW_SPEC_ETH,
.size = sizeof(struct ib_flow_spec_eth),
.mask = {.dst_mac = {0x1} },
.val = {.dst_mac = {} }
}
}
};
handler = create_flow_rule(dev, ft_prio,
&leftovers_specs[LEFTOVERS_MC].flow_attr,
dst);
if (!IS_ERR(handler) &&
flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT) {
handler_ucast = create_flow_rule(dev, ft_prio,
&leftovers_specs[LEFTOVERS_UC].flow_attr,
dst);
if (IS_ERR(handler_ucast)) {
kfree(handler);
handler = handler_ucast;
} else {
list_add(&handler_ucast->list, &handler->list);
}
}
return handler;
}
static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp,
struct ib_flow_attr *flow_attr,
int domain)
{
struct mlx5_ib_dev *dev = to_mdev(qp->device);
struct mlx5_ib_flow_handler *handler = NULL;
struct mlx5_flow_destination *dst = NULL;
struct mlx5_ib_flow_prio *ft_prio;
int err;
if (flow_attr->priority > MLX5_IB_FLOW_LAST_PRIO)
return ERR_PTR(-ENOSPC);
if (domain != IB_FLOW_DOMAIN_USER ||
flow_attr->port > MLX5_CAP_GEN(dev->mdev, num_ports) ||
flow_attr->flags)
return ERR_PTR(-EINVAL);
dst = kzalloc(sizeof(*dst), GFP_KERNEL);
if (!dst)
return ERR_PTR(-ENOMEM);
mutex_lock(&dev->flow_db.lock);
ft_prio = get_flow_table(dev, flow_attr);
if (IS_ERR(ft_prio)) {
err = PTR_ERR(ft_prio);
goto unlock;
}
dst->type = MLX5_FLOW_DESTINATION_TYPE_TIR;
dst->tir_num = to_mqp(qp)->raw_packet_qp.rq.tirn;
if (flow_attr->type == IB_FLOW_ATTR_NORMAL) {
handler = create_flow_rule(dev, ft_prio, flow_attr,
dst);
} else if (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT ||
flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT) {
handler = create_leftovers_rule(dev, ft_prio, flow_attr,
dst);
} else {
err = -EINVAL;
goto destroy_ft;
}
if (IS_ERR(handler)) {
err = PTR_ERR(handler);
handler = NULL;
goto destroy_ft;
}
ft_prio->refcount++;
mutex_unlock(&dev->flow_db.lock);
kfree(dst);
return &handler->ibflow;
destroy_ft:
put_flow_table(dev, ft_prio, false);
unlock:
mutex_unlock(&dev->flow_db.lock);
kfree(dst);
kfree(handler);
return ERR_PTR(err);
}
static int mlx5_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
{
struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
@ -1439,10 +1893,19 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
(1ull << IB_USER_VERBS_CMD_CLOSE_XRCD);
}
if (mlx5_ib_port_link_layer(&dev->ib_dev) ==
IB_LINK_LAYER_ETHERNET) {
dev->ib_dev.create_flow = mlx5_ib_create_flow;
dev->ib_dev.destroy_flow = mlx5_ib_destroy_flow;
dev->ib_dev.uverbs_ex_cmd_mask |=
(1ull << IB_USER_VERBS_EX_CMD_CREATE_FLOW) |
(1ull << IB_USER_VERBS_EX_CMD_DESTROY_FLOW);
}
err = init_node_data(dev);
if (err)
goto err_dealloc;
mutex_init(&dev->flow_db.lock);
mutex_init(&dev->cap_mask_mutex);
err = create_dev_resources(&dev->devr);

View File

@ -105,6 +105,36 @@ struct mlx5_ib_pd {
u32 pdn;
};
#define MLX5_IB_FLOW_MCAST_PRIO (MLX5_BY_PASS_NUM_PRIOS - 1)
#define MLX5_IB_FLOW_LAST_PRIO (MLX5_IB_FLOW_MCAST_PRIO - 1)
#if (MLX5_IB_FLOW_LAST_PRIO <= 0)
#error "Invalid number of bypass priorities"
#endif
#define MLX5_IB_FLOW_LEFTOVERS_PRIO (MLX5_IB_FLOW_MCAST_PRIO + 1)
#define MLX5_IB_NUM_FLOW_FT (MLX5_IB_FLOW_LEFTOVERS_PRIO + 1)
struct mlx5_ib_flow_prio {
struct mlx5_flow_table *flow_table;
unsigned int refcount;
};
struct mlx5_ib_flow_handler {
struct list_head list;
struct ib_flow ibflow;
unsigned int prio;
struct mlx5_flow_rule *rule;
};
struct mlx5_ib_flow_db {
struct mlx5_ib_flow_prio prios[MLX5_IB_NUM_FLOW_FT];
/* Protect flow steering bypass flow tables
* when add/del flow rules.
* only single add/removal of flow steering rule could be done
* simultaneously.
*/
struct mutex lock;
};
/* Use macros here so that don't have to duplicate
* enum ib_send_flags and enum ib_qp_type for low-level driver
*/
@ -171,9 +201,21 @@ struct mlx5_ib_pfault {
struct mlx5_pagefault mpfault;
};
struct mlx5_ib_rq {
u32 tirn;
};
struct mlx5_ib_raw_packet_qp {
struct mlx5_ib_rq rq;
};
struct mlx5_ib_qp {
struct ib_qp ibqp;
struct mlx5_core_qp mqp;
union {
struct mlx5_core_qp mqp;
struct mlx5_ib_raw_packet_qp raw_packet_qp;
};
struct mlx5_buf buf;
struct mlx5_db db;
@ -431,6 +473,7 @@ struct mlx5_ib_dev {
*/
struct srcu_struct mr_srcu;
#endif
struct mlx5_ib_flow_db flow_db;
};
static inline struct mlx5_ib_cq *to_mibcq(struct mlx5_core_cq *mcq)

View File

@ -10,7 +10,6 @@ obj-$(CONFIG_ISDN_DIVERSION) += divert/
obj-$(CONFIG_ISDN_DRV_HISAX) += hisax/
obj-$(CONFIG_ISDN_DRV_ICN) += icn/
obj-$(CONFIG_ISDN_DRV_PCBIT) += pcbit/
obj-$(CONFIG_ISDN_DRV_SC) += sc/
obj-$(CONFIG_ISDN_DRV_LOOP) += isdnloop/
obj-$(CONFIG_ISDN_DRV_ACT2000) += act2000/
obj-$(CONFIG_HYSDN) += hysdn/

View File

@ -37,7 +37,7 @@ MODULE_DESCRIPTION("ISDN4Linux: Driver for IBM Active 2000 ISDN card");
MODULE_AUTHOR("Fritz Elfert");
MODULE_LICENSE("GPL");
MODULE_PARM_DESC(act_bus, "BusType of first card, 1=ISA, 2=MCA, 3=PCMCIA, currently only ISA");
MODULE_PARM_DESC(membase, "Base port address of first card");
MODULE_PARM_DESC(act_port, "Base port address of first card");
MODULE_PARM_DESC(act_irq, "IRQ of first card");
MODULE_PARM_DESC(act_id, "ID-String of first card");
module_param(act_bus, int, 0);

View File

@ -130,8 +130,6 @@ source "drivers/isdn/icn/Kconfig"
source "drivers/isdn/pcbit/Kconfig"
source "drivers/isdn/sc/Kconfig"
source "drivers/isdn/act2000/Kconfig"
endmenu

View File

@ -1,8 +0,0 @@
config ISDN_DRV_SC
tristate "Spellcaster support"
depends on ISA
help
This enables support for the Spellcaster BRI ISDN boards. This
driver currently builds only in a modularized version.
To build it, choose M here: the module will be called sc.
See <file:Documentation/isdn/README.sc> for more information.

View File

@ -1,10 +0,0 @@
# Makefile for the sc ISDN device driver
# Each configuration option enables a list of files.
obj-$(CONFIG_ISDN_DRV_SC) += sc.o
# Multipart objects.
sc-y := shmem.o init.o packet.o command.o event.o \
ioctl.o interrupt.o message.o timer.o

View File

@ -1,131 +0,0 @@
/* $Id: card.h,v 1.1.10.1 2001/09/23 22:24:59 kai Exp $
*
* Driver parameters for SpellCaster ISA ISDN adapters
*
* Copyright (C) 1996 SpellCaster Telecommunications Inc.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* For more information, please contact gpl-info@spellcast.com or write:
*
* SpellCaster Telecommunications Inc.
* 5621 Finch Avenue East, Unit #3
* Scarborough, Ontario Canada
* M1B 2T9
* +1 (416) 297-8565
* +1 (416) 297-6433 Facsimile
*/
#ifndef CARD_H
#define CARD_H
/*
* We need these if they're not already included
*/
#include <linux/timer.h>
#include <linux/time.h>
#include <linux/isdnif.h>
#include <linux/irqreturn.h>
#include "message.h"
#include "scioc.h"
/*
* Amount of time to wait for a reset to complete
*/
#define CHECKRESET_TIME msecs_to_jiffies(4000)
/*
* Amount of time between line status checks
*/
#define CHECKSTAT_TIME msecs_to_jiffies(8000)
/*
* The maximum amount of time to wait for a message response
* to arrive. Use exclusively by send_and_receive
*/
#define SAR_TIMEOUT msecs_to_jiffies(10000)
/*
* Macro to determine is a card id is valid
*/
#define IS_VALID_CARD(x) ((x >= 0) && (x <= cinst))
/*
* Per channel status and configuration
*/
typedef struct {
int l2_proto;
int l3_proto;
char dn[50];
unsigned long first_sendbuf; /* Offset of first send buffer */
unsigned int num_sendbufs; /* Number of send buffers */
unsigned int free_sendbufs; /* Number of free sendbufs */
unsigned int next_sendbuf; /* Next sequential buffer */
char eazlist[50]; /* Set with SETEAZ */
char sillist[50]; /* Set with SETSIL */
int eazclear; /* Don't accept calls if TRUE */
} bchan;
/*
* Everything you want to know about the adapter ...
*/
typedef struct {
int model;
int driverId; /* LL Id */
char devicename[20]; /* The device name */
isdn_if *card; /* ISDN4Linux structure */
bchan *channel; /* status of the B channels */
char nChannels; /* Number of channels */
unsigned int interrupt; /* Interrupt number */
int iobase; /* I/O Base address */
int ioport[MAX_IO_REGS]; /* Index to I/O ports */
int shmem_pgport; /* port for the exp mem page reg. */
int shmem_magic; /* adapter magic number */
unsigned int rambase; /* Shared RAM base address */
unsigned int ramsize; /* Size of shared memory */
RspMessage async_msg; /* Async response message */
int want_async_messages; /* Snoop the Q ? */
unsigned char seq_no; /* Next send seq. number */
struct timer_list reset_timer; /* Check reset timer */
struct timer_list stat_timer; /* Check startproc timer */
unsigned char nphystat; /* Latest PhyStat info */
unsigned char phystat; /* Last PhyStat info */
HWConfig_pl hwconfig; /* Hardware config info */
char load_ver[11]; /* CommManage Version string */
char proc_ver[11]; /* CommEngine Version */
int StartOnReset; /* Indicates startproc after reset */
int EngineUp; /* Indicates CommEngine Up */
int trace_mode; /* Indicate if tracing is on */
spinlock_t lock; /* local lock */
} board;
extern board *sc_adapter[];
extern int cinst;
void memcpy_toshmem(int card, void *dest, const void *src, size_t n);
void memcpy_fromshmem(int card, void *dest, const void *src, size_t n);
int get_card_from_id(int driver);
int indicate_status(int card, int event, ulong Channel, char *Data);
irqreturn_t interrupt_handler(int interrupt, void *cardptr);
int sndpkt(int devId, int channel, int ack, struct sk_buff *data);
void rcvpkt(int card, RspMessage *rcvmsg);
int command(isdn_ctrl *cmd);
int reset(int card);
int startproc(int card);
int send_and_receive(int card, unsigned int procid, unsigned char type,
unsigned char class, unsigned char code,
unsigned char link, unsigned char data_len,
unsigned char *data, RspMessage *mesgdata, int timeout);
void flushreadfifo(int card);
int sendmessage(int card, unsigned int procid, unsigned int type,
unsigned int class, unsigned int code, unsigned int link,
unsigned int data_len, unsigned int *data);
int receivemessage(int card, RspMessage *rspmsg);
int sc_ioctl(int card, scs_ioctl *data);
int setup_buffers(int card, int c);
void sc_check_reset(unsigned long data);
void check_phystat(unsigned long data);
#endif /* CARD_H */

View File

@ -1,363 +0,0 @@
/* $Id: command.c,v 1.4.10.1 2001/09/23 22:24:59 kai Exp $
*
* Copyright (C) 1996 SpellCaster Telecommunications Inc.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* For more information, please contact gpl-info@spellcast.com or write:
*
* SpellCaster Telecommunications Inc.
* 5621 Finch Avenue East, Unit #3
* Scarborough, Ontario Canada
* M1B 2T9
* +1 (416) 297-8565
* +1 (416) 297-6433 Facsimile
*/
#include <linux/module.h>
#include "includes.h" /* This must be first */
#include "hardware.h"
#include "message.h"
#include "card.h"
#include "scioc.h"
static int dial(int card, unsigned long channel, setup_parm setup);
static int hangup(int card, unsigned long channel);
static int answer(int card, unsigned long channel);
static int clreaz(int card, unsigned long channel);
static int seteaz(int card, unsigned long channel, char *);
static int setl2(int card, unsigned long arg);
static int setl3(int card, unsigned long arg);
static int acceptb(int card, unsigned long channel);
#ifdef DEBUG
/*
* Translate command codes to strings
*/
static char *commands[] = { "ISDN_CMD_IOCTL",
"ISDN_CMD_DIAL",
"ISDN_CMD_ACCEPTB",
"ISDN_CMD_ACCEPTB",
"ISDN_CMD_HANGUP",
"ISDN_CMD_CLREAZ",
"ISDN_CMD_SETEAZ",
NULL,
NULL,
NULL,
"ISDN_CMD_SETL2",
NULL,
"ISDN_CMD_SETL3",
NULL,
NULL,
NULL,
NULL,
NULL, };
/*
* Translates ISDN4Linux protocol codes to strings for debug messages
*/
static char *l3protos[] = { "ISDN_PROTO_L3_TRANS" };
static char *l2protos[] = { "ISDN_PROTO_L2_X75I",
"ISDN_PROTO_L2_X75UI",
"ISDN_PROTO_L2_X75BUI",
"ISDN_PROTO_L2_HDLC",
"ISDN_PROTO_L2_TRANS" };
#endif
int get_card_from_id(int driver)
{
int i;
for (i = 0; i < cinst; i++) {
if (sc_adapter[i]->driverId == driver)
return i;
}
return -ENODEV;
}
/*
* command
*/
int command(isdn_ctrl *cmd)
{
int card;
card = get_card_from_id(cmd->driver);
if (!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
return -ENODEV;
}
/*
* Dispatch the command
*/
switch (cmd->command) {
case ISDN_CMD_IOCTL:
{
unsigned long cmdptr;
scs_ioctl ioc;
memcpy(&cmdptr, cmd->parm.num, sizeof(unsigned long));
if (copy_from_user(&ioc, (scs_ioctl __user *)cmdptr,
sizeof(scs_ioctl))) {
pr_debug("%s: Failed to verify user space 0x%lx\n",
sc_adapter[card]->devicename, cmdptr);
return -EFAULT;
}
return sc_ioctl(card, &ioc);
}
case ISDN_CMD_DIAL:
return dial(card, cmd->arg, cmd->parm.setup);
case ISDN_CMD_HANGUP:
return hangup(card, cmd->arg);
case ISDN_CMD_ACCEPTD:
return answer(card, cmd->arg);
case ISDN_CMD_ACCEPTB:
return acceptb(card, cmd->arg);
case ISDN_CMD_CLREAZ:
return clreaz(card, cmd->arg);
case ISDN_CMD_SETEAZ:
return seteaz(card, cmd->arg, cmd->parm.num);
case ISDN_CMD_SETL2:
return setl2(card, cmd->arg);
case ISDN_CMD_SETL3:
return setl3(card, cmd->arg);
default:
return -EINVAL;
}
return 0;
}
/*
* start the onboard firmware
*/
int startproc(int card)
{
int status;
if (!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
return -ENODEV;
}
/*
* send start msg
*/
status = sendmessage(card, CMPID, cmReqType2,
cmReqClass0,
cmReqStartProc,
0, 0, NULL);
pr_debug("%s: Sent startProc\n", sc_adapter[card]->devicename);
return status;
}
/*
* Dials the number passed in
*/
static int dial(int card, unsigned long channel, setup_parm setup)
{
int status;
char Phone[48];
if (!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
return -ENODEV;
}
/*extract ISDN number to dial from eaz/msn string*/
strcpy(Phone, setup.phone);
/*send the connection message*/
status = sendmessage(card, CEPID, ceReqTypePhy,
ceReqClass1,
ceReqPhyConnect,
(unsigned char)channel + 1,
strlen(Phone),
(unsigned int *)Phone);
pr_debug("%s: Dialing %s on channel %lu\n",
sc_adapter[card]->devicename, Phone, channel + 1);
return status;
}
/*
* Answer an incoming call
*/
static int answer(int card, unsigned long channel)
{
if (!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
return -ENODEV;
}
if (setup_buffers(card, channel + 1)) {
hangup(card, channel + 1);
return -ENOBUFS;
}
indicate_status(card, ISDN_STAT_BCONN, channel, NULL);
pr_debug("%s: Answered incoming call on channel %lu\n",
sc_adapter[card]->devicename, channel + 1);
return 0;
}
/*
* Hangup up the call on specified channel
*/
static int hangup(int card, unsigned long channel)
{
int status;
if (!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
return -ENODEV;
}
status = sendmessage(card, CEPID, ceReqTypePhy,
ceReqClass1,
ceReqPhyDisconnect,
(unsigned char)channel + 1,
0,
NULL);
pr_debug("%s: Sent HANGUP message to channel %lu\n",
sc_adapter[card]->devicename, channel + 1);
return status;
}
/*
* Set the layer 2 protocol (X.25, HDLC, Raw)
*/
static int setl2(int card, unsigned long arg)
{
int status = 0;
int protocol, channel;
if (!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
return -ENODEV;
}
protocol = arg >> 8;
channel = arg & 0xff;
sc_adapter[card]->channel[channel].l2_proto = protocol;
/*
* check that the adapter is also set to the correct protocol
*/
pr_debug("%s: Sending GetFrameFormat for channel %d\n",
sc_adapter[card]->devicename, channel + 1);
status = sendmessage(card, CEPID, ceReqTypeCall,
ceReqClass0,
ceReqCallGetFrameFormat,
(unsigned char)channel + 1,
1,
(unsigned int *)protocol);
if (status)
return status;
return 0;
}
/*
* Set the layer 3 protocol
*/
static int setl3(int card, unsigned long channel)
{
int protocol = channel >> 8;
if (!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
return -ENODEV;
}
sc_adapter[card]->channel[channel].l3_proto = protocol;
return 0;
}
static int acceptb(int card, unsigned long channel)
{
if (!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
return -ENODEV;
}
if (setup_buffers(card, channel + 1))
{
hangup(card, channel + 1);
return -ENOBUFS;
}
pr_debug("%s: B-Channel connection accepted on channel %lu\n",
sc_adapter[card]->devicename, channel + 1);
indicate_status(card, ISDN_STAT_BCONN, channel, NULL);
return 0;
}
static int clreaz(int card, unsigned long arg)
{
if (!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
return -ENODEV;
}
strcpy(sc_adapter[card]->channel[arg].eazlist, "");
sc_adapter[card]->channel[arg].eazclear = 1;
pr_debug("%s: EAZ List cleared for channel %lu\n",
sc_adapter[card]->devicename, arg + 1);
return 0;
}
static int seteaz(int card, unsigned long arg, char *num)
{
if (!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
return -ENODEV;
}
strcpy(sc_adapter[card]->channel[arg].eazlist, num);
sc_adapter[card]->channel[arg].eazclear = 0;
pr_debug("%s: EAZ list for channel %lu set to: %s\n",
sc_adapter[card]->devicename, arg + 1,
sc_adapter[card]->channel[arg].eazlist);
return 0;
}
int reset(int card)
{
unsigned long flags;
if (!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
return -ENODEV;
}
indicate_status(card, ISDN_STAT_STOP, 0, NULL);
if (sc_adapter[card]->EngineUp) {
del_timer(&sc_adapter[card]->stat_timer);
}
sc_adapter[card]->EngineUp = 0;
spin_lock_irqsave(&sc_adapter[card]->lock, flags);
init_timer(&sc_adapter[card]->reset_timer);
sc_adapter[card]->reset_timer.function = sc_check_reset;
sc_adapter[card]->reset_timer.data = card;
sc_adapter[card]->reset_timer.expires = jiffies + CHECKRESET_TIME;
add_timer(&sc_adapter[card]->reset_timer);
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
outb(0x1, sc_adapter[card]->ioport[SFT_RESET]);
pr_debug("%s: Adapter Reset\n", sc_adapter[card]->devicename);
return 0;
}
void flushreadfifo(int card)
{
while (inb(sc_adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA)
inb(sc_adapter[card]->ioport[FIFO_READ]);
}

View File

@ -1,68 +0,0 @@
/* $Id: event.c,v 1.4.8.1 2001/09/23 22:24:59 kai Exp $
*
* Copyright (C) 1996 SpellCaster Telecommunications Inc.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* For more information, please contact gpl-info@spellcast.com or write:
*
* SpellCaster Telecommunications Inc.
* 5621 Finch Avenue East, Unit #3
* Scarborough, Ontario Canada
* M1B 2T9
* +1 (416) 297-8565
* +1 (416) 297-6433 Facsimile
*/
#include "includes.h"
#include "hardware.h"
#include "message.h"
#include "card.h"
#ifdef DEBUG
static char *events[] = { "ISDN_STAT_STAVAIL",
"ISDN_STAT_ICALL",
"ISDN_STAT_RUN",
"ISDN_STAT_STOP",
"ISDN_STAT_DCONN",
"ISDN_STAT_BCONN",
"ISDN_STAT_DHUP",
"ISDN_STAT_BHUP",
"ISDN_STAT_CINF",
"ISDN_STAT_LOAD",
"ISDN_STAT_UNLOAD",
"ISDN_STAT_BSENT",
"ISDN_STAT_NODCH",
"ISDN_STAT_ADDCH",
"ISDN_STAT_CAUSE" };
#endif
int indicate_status(int card, int event, ulong Channel, char *Data)
{
isdn_ctrl cmd;
#ifdef DEBUG
pr_debug("%s: Indicating event %s on Channel %d\n",
sc_adapter[card]->devicename, events[event - 256], Channel);
#endif
if (Data != NULL) {
pr_debug("%s: Event data: %s\n", sc_adapter[card]->devicename,
Data);
switch (event) {
case ISDN_STAT_BSENT:
memcpy(&cmd.parm.length, Data, sizeof(cmd.parm.length));
break;
case ISDN_STAT_ICALL:
memcpy(&cmd.parm.setup, Data, sizeof(cmd.parm.setup));
break;
default:
strlcpy(cmd.parm.num, Data, sizeof(cmd.parm.num));
}
}
cmd.command = event;
cmd.driver = sc_adapter[card]->driverId;
cmd.arg = Channel;
return sc_adapter[card]->card->statcallb(&cmd);
}

View File

@ -1,110 +0,0 @@
/*
* Hardware specific macros, defines and structures
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#ifndef HARDWARE_H
#define HARDWARE_H
#include <asm/param.h> /* For HZ */
/*
* General hardware parameters common to all ISA adapters
*/
#define MAX_CARDS 4 /* The maximum number of cards to
control or probe for. */
#define SIGNATURE 0x87654321 /* Board reset signature */
#define SIG_OFFSET 0x1004 /* Where to find signature in shared RAM */
#define TRACE_OFFSET 0x1008 /* Trace enable word offset in shared RAM */
#define BUFFER_OFFSET 0x1800 /* Beginning of buffers */
/* I/O Port parameters */
#define IOBASE_MIN 0x180 /* Lowest I/O port address */
#define IOBASE_MAX 0x3C0 /* Highest I/O port address */
#define IOBASE_OFFSET 0x20 /* Inter-board I/O port gap used during
probing */
#define FIFORD_OFFSET 0x0
#define FIFOWR_OFFSET 0x400
#define FIFOSTAT_OFFSET 0x1000
#define RESET_OFFSET 0x2800
#define PG0_OFFSET 0x3000 /* Offset from I/O Base for Page 0 register */
#define PG1_OFFSET 0x3400 /* Offset from I/O Base for Page 1 register */
#define PG2_OFFSET 0x3800 /* Offset from I/O Base for Page 2 register */
#define PG3_OFFSET 0x3C00 /* Offset from I/O Base for Page 3 register */
#define FIFO_READ 0 /* FIFO Read register */
#define FIFO_WRITE 1 /* FIFO Write rgister */
#define LO_ADDR_PTR 2 /* Extended RAM Low Addr Pointer */
#define HI_ADDR_PTR 3 /* Extended RAM High Addr Pointer */
#define NOT_USED_1 4
#define FIFO_STATUS 5 /* FIFO Status Register */
#define NOT_USED_2 6
#define MEM_OFFSET 7
#define SFT_RESET 10 /* Reset Register */
#define EXP_BASE 11 /* Shared RAM Base address */
#define EXP_PAGE0 12 /* Shared RAM Page0 register */
#define EXP_PAGE1 13 /* Shared RAM Page1 register */
#define EXP_PAGE2 14 /* Shared RAM Page2 register */
#define EXP_PAGE3 15 /* Shared RAM Page3 register */
#define IRQ_SELECT 16 /* IRQ selection register */
#define MAX_IO_REGS 17 /* Total number of I/O ports */
/* FIFO register values */
#define RF_HAS_DATA 0x01 /* fifo has data */
#define RF_QUART_FULL 0x02 /* fifo quarter full */
#define RF_HALF_FULL 0x04 /* fifo half full */
#define RF_NOT_FULL 0x08 /* fifo not full */
#define WF_HAS_DATA 0x10 /* fifo has data */
#define WF_QUART_FULL 0x20 /* fifo quarter full */
#define WF_HALF_FULL 0x40 /* fifo half full */
#define WF_NOT_FULL 0x80 /* fifo not full */
/* Shared RAM parameters */
#define SRAM_MIN 0xC0000 /* Lowest host shared RAM address */
#define SRAM_MAX 0xEFFFF /* Highest host shared RAM address */
#define SRAM_PAGESIZE 0x4000 /* Size of one RAM page (16K) */
/* Shared RAM buffer parameters */
#define BUFFER_SIZE 0x800 /* The size of a buffer in bytes */
#define BUFFER_BASE BUFFER_OFFSET /* Offset from start of shared RAM
where buffer start */
#define BUFFERS_MAX 16 /* Maximum number of send/receive
buffers per channel */
#define HDLC_PROTO 0x01 /* Frame Format for Layer 2 */
#define BRI_BOARD 0
#define POTS_BOARD 1
#define PRI_BOARD 2
/*
* Specific hardware parameters for the DataCommute/BRI
*/
#define BRI_CHANNELS 2 /* Number of B channels */
#define BRI_BASEPG_VAL 0x98
#define BRI_MAGIC 0x60000 /* Magic Number */
#define BRI_MEMSIZE 0x10000 /* Amount of RAM (64K) */
#define BRI_PARTNO "72-029"
#define BRI_FEATURES ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L3_TRANS;
/*
* Specific hardware parameters for the DataCommute/PRI
*/
#define PRI_CHANNELS 23 /* Number of B channels */
#define PRI_BASEPG_VAL 0x88
#define PRI_MAGIC 0x20000 /* Magic Number */
#define PRI_MEMSIZE 0x100000 /* Amount of RAM (1M) */
#define PRI_PARTNO "72-030"
#define PRI_FEATURES ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L3_TRANS;
/*
* Some handy macros
*/
/* Determine if a channel number is valid for the adapter */
#define IS_VALID_CHANNEL(y, x) ((x > 0) && (x <= sc_adapter[y]->channels))
#endif

View File

@ -1,16 +0,0 @@
/*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include <linux/errno.h>
#include <asm/io.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/timer.h>
#include <linux/wait.h>
#include <linux/isdnif.h>

View File

@ -1,549 +0,0 @@
/*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include "includes.h"
#include "hardware.h"
#include "card.h"
MODULE_DESCRIPTION("ISDN4Linux: Driver for Spellcaster card");
MODULE_AUTHOR("Spellcaster Telecommunications Inc.");
MODULE_LICENSE("GPL");
board *sc_adapter[MAX_CARDS];
int cinst;
static char devname[] = "scX";
static const char version[] = "2.0b1";
static const char *boardname[] = { "DataCommute/BRI", "DataCommute/PRI", "TeleCommute/BRI" };
/* insmod set parameters */
static unsigned int io[] = {0, 0, 0, 0};
static unsigned char irq[] = {0, 0, 0, 0};
static unsigned long ram[] = {0, 0, 0, 0};
static bool do_reset;
module_param_array(io, int, NULL, 0);
module_param_array(irq, byte, NULL, 0);
module_param_array(ram, long, NULL, 0);
module_param(do_reset, bool, 0);
static int identify_board(unsigned long, unsigned int);
static int __init sc_init(void)
{
int b = -1;
int i, j;
int status = -ENODEV;
unsigned long memsize = 0;
unsigned long features = 0;
isdn_if *interface;
unsigned char channels;
unsigned char pgport;
unsigned long magic;
int model;
int last_base = IOBASE_MIN;
int probe_exhasted = 0;
#ifdef MODULE
pr_info("SpellCaster ISA ISDN Adapter Driver rev. %s Loaded\n", version);
#else
pr_info("SpellCaster ISA ISDN Adapter Driver rev. %s\n", version);
#endif
pr_info("Copyright (C) 1996 SpellCaster Telecommunications Inc.\n");
while (b++ < MAX_CARDS - 1) {
pr_debug("Probing for adapter #%d\n", b);
/*
* Initialize reusable variables
*/
model = -1;
magic = 0;
channels = 0;
pgport = 0;
/*
* See if we should probe for IO base
*/
pr_debug("I/O Base for board %d is 0x%x, %s probe\n", b, io[b],
io[b] == 0 ? "will" : "won't");
if (io[b]) {
/*
* No, I/O Base has been provided
*/
for (i = 0; i < MAX_IO_REGS - 1; i++) {
if (!request_region(io[b] + i * 0x400, 1, "sc test")) {
pr_debug("request_region for 0x%x failed\n", io[b] + i * 0x400);
io[b] = 0;
break;
} else
release_region(io[b] + i * 0x400, 1);
}
/*
* Confirm the I/O Address with a test
*/
if (io[b] == 0) {
pr_debug("I/O Address invalid.\n");
continue;
}
outb(0x18, io[b] + 0x400 * EXP_PAGE0);
if (inb(io[b] + 0x400 * EXP_PAGE0) != 0x18) {
pr_debug("I/O Base 0x%x fails test\n",
io[b] + 0x400 * EXP_PAGE0);
continue;
}
} else {
/*
* Yes, probe for I/O Base
*/
if (probe_exhasted) {
pr_debug("All probe addresses exhausted, skipping\n");
continue;
}
pr_debug("Probing for I/O...\n");
for (i = last_base; i <= IOBASE_MAX; i += IOBASE_OFFSET) {
int found_io = 1;
if (i == IOBASE_MAX) {
probe_exhasted = 1; /* No more addresses to probe */
pr_debug("End of Probes\n");
}
last_base = i + IOBASE_OFFSET;
pr_debug(" checking 0x%x...", i);
for (j = 0; j < MAX_IO_REGS - 1; j++) {
if (!request_region(i + j * 0x400, 1, "sc test")) {
pr_debug("Failed\n");
found_io = 0;
break;
} else
release_region(i + j * 0x400, 1);
}
if (found_io) {
io[b] = i;
outb(0x18, io[b] + 0x400 * EXP_PAGE0);
if (inb(io[b] + 0x400 * EXP_PAGE0) != 0x18) {
pr_debug("Failed by test\n");
continue;
}
pr_debug("Passed\n");
break;
}
}
if (probe_exhasted) {
continue;
}
}
/*
* See if we should probe for shared RAM
*/
if (do_reset) {
pr_debug("Doing a SAFE probe reset\n");
outb(0xFF, io[b] + RESET_OFFSET);
msleep_interruptible(10000);
}
pr_debug("RAM Base for board %d is 0x%lx, %s probe\n", b,
ram[b], ram[b] == 0 ? "will" : "won't");
if (ram[b]) {
/*
* No, the RAM base has been provided
* Just look for a signature and ID the
* board model
*/
if (request_region(ram[b], SRAM_PAGESIZE, "sc test")) {
pr_debug("request_region for RAM base 0x%lx succeeded\n", ram[b]);
model = identify_board(ram[b], io[b]);
release_region(ram[b], SRAM_PAGESIZE);
}
} else {
/*
* Yes, probe for free RAM and look for
* a signature and id the board model
*/
for (i = SRAM_MIN; i < SRAM_MAX; i += SRAM_PAGESIZE) {
pr_debug("Checking RAM address 0x%x...\n", i);
if (request_region(i, SRAM_PAGESIZE, "sc test")) {
pr_debug(" request_region succeeded\n");
model = identify_board(i, io[b]);
release_region(i, SRAM_PAGESIZE);
if (model >= 0) {
pr_debug(" Identified a %s\n",
boardname[model]);
ram[b] = i;
break;
}
pr_debug(" Unidentified or inaccessible\n");
continue;
}
pr_debug(" request failed\n");
}
}
/*
* See if we found free RAM and the board model
*/
if (!ram[b] || model < 0) {
/*
* Nope, there was no place in RAM for the
* board, or it couldn't be identified
*/
pr_debug("Failed to find an adapter at 0x%lx\n", ram[b]);
continue;
}
/*
* Set the board's magic number, memory size and page register
*/
switch (model) {
case PRI_BOARD:
channels = 23;
magic = 0x20000;
memsize = 0x100000;
features = PRI_FEATURES;
break;
case BRI_BOARD:
case POTS_BOARD:
channels = 2;
magic = 0x60000;
memsize = 0x10000;
features = BRI_FEATURES;
break;
}
switch (ram[b] >> 12 & 0x0F) {
case 0x0:
pr_debug("RAM Page register set to EXP_PAGE0\n");
pgport = EXP_PAGE0;
break;
case 0x4:
pr_debug("RAM Page register set to EXP_PAGE1\n");
pgport = EXP_PAGE1;
break;
case 0x8:
pr_debug("RAM Page register set to EXP_PAGE2\n");
pgport = EXP_PAGE2;
break;
case 0xC:
pr_debug("RAM Page register set to EXP_PAGE3\n");
pgport = EXP_PAGE3;
break;
default:
pr_debug("RAM base address doesn't fall on 16K boundary\n");
continue;
}
pr_debug("current IRQ: %d b: %d\n", irq[b], b);
/*
* Make sure we got an IRQ
*/
if (!irq[b]) {
/*
* No interrupt could be used
*/
pr_debug("Failed to acquire an IRQ line\n");
continue;
}
/*
* Horray! We found a board, Make sure we can register
* it with ISDN4Linux
*/
interface = kzalloc(sizeof(isdn_if), GFP_KERNEL);
if (interface == NULL) {
/*
* Oops, can't malloc isdn_if
*/
continue;
}
interface->owner = THIS_MODULE;
interface->hl_hdrlen = 0;
interface->channels = channels;
interface->maxbufsize = BUFFER_SIZE;
interface->features = features;
interface->writebuf_skb = sndpkt;
interface->writecmd = NULL;
interface->command = command;
strcpy(interface->id, devname);
interface->id[2] = '0' + cinst;
/*
* Allocate the board structure
*/
sc_adapter[cinst] = kzalloc(sizeof(board), GFP_KERNEL);
if (sc_adapter[cinst] == NULL) {
/*
* Oops, can't alloc memory for the board
*/
kfree(interface);
continue;
}
spin_lock_init(&sc_adapter[cinst]->lock);
if (!register_isdn(interface)) {
/*
* Oops, couldn't register for some reason
*/
kfree(interface);
kfree(sc_adapter[cinst]);
continue;
}
sc_adapter[cinst]->card = interface;
sc_adapter[cinst]->driverId = interface->channels;
strcpy(sc_adapter[cinst]->devicename, interface->id);
sc_adapter[cinst]->nChannels = channels;
sc_adapter[cinst]->ramsize = memsize;
sc_adapter[cinst]->shmem_magic = magic;
sc_adapter[cinst]->shmem_pgport = pgport;
sc_adapter[cinst]->StartOnReset = 1;
/*
* Allocate channels status structures
*/
sc_adapter[cinst]->channel = kzalloc(sizeof(bchan) * channels, GFP_KERNEL);
if (sc_adapter[cinst]->channel == NULL) {
/*
* Oops, can't alloc memory for the channels
*/
indicate_status(cinst, ISDN_STAT_UNLOAD, 0, NULL); /* Fix me */
kfree(interface);
kfree(sc_adapter[cinst]);
continue;
}
/*
* Lock down the hardware resources
*/
sc_adapter[cinst]->interrupt = irq[b];
if (request_irq(sc_adapter[cinst]->interrupt, interrupt_handler,
0, interface->id,
(void *)(unsigned long) cinst)) {
kfree(sc_adapter[cinst]->channel);
indicate_status(cinst, ISDN_STAT_UNLOAD, 0, NULL); /* Fix me */
kfree(interface);
kfree(sc_adapter[cinst]);
continue;
}
sc_adapter[cinst]->iobase = io[b];
for (i = 0; i < MAX_IO_REGS - 1; i++) {
sc_adapter[cinst]->ioport[i] = io[b] + i * 0x400;
request_region(sc_adapter[cinst]->ioport[i], 1,
interface->id);
pr_debug("Requesting I/O Port %#x\n",
sc_adapter[cinst]->ioport[i]);
}
sc_adapter[cinst]->ioport[IRQ_SELECT] = io[b] + 0x2;
request_region(sc_adapter[cinst]->ioport[IRQ_SELECT], 1,
interface->id);
pr_debug("Requesting I/O Port %#x\n",
sc_adapter[cinst]->ioport[IRQ_SELECT]);
sc_adapter[cinst]->rambase = ram[b];
request_region(sc_adapter[cinst]->rambase, SRAM_PAGESIZE,
interface->id);
pr_info(" %s (%d) - %s %d channels IRQ %d, I/O Base 0x%x, RAM Base 0x%lx\n",
sc_adapter[cinst]->devicename,
sc_adapter[cinst]->driverId,
boardname[model], channels, irq[b], io[b], ram[b]);
/*
* reset the adapter to put things in motion
*/
reset(cinst);
cinst++;
status = 0;
}
if (status)
pr_info("Failed to find any adapters, driver unloaded\n");
return status;
}
static void __exit sc_exit(void)
{
int i, j;
for (i = 0; i < cinst; i++) {
pr_debug("Cleaning up after adapter %d\n", i);
/*
* kill the timers
*/
del_timer_sync(&(sc_adapter[i]->reset_timer));
del_timer_sync(&(sc_adapter[i]->stat_timer));
/*
* Tell I4L we're toast
*/
indicate_status(i, ISDN_STAT_STOP, 0, NULL);
indicate_status(i, ISDN_STAT_UNLOAD, 0, NULL);
/*
* Release shared RAM
*/
release_region(sc_adapter[i]->rambase, SRAM_PAGESIZE);
/*
* Release the IRQ
*/
free_irq(sc_adapter[i]->interrupt, NULL);
/*
* Reset for a clean start
*/
outb(0xFF, sc_adapter[i]->ioport[SFT_RESET]);
/*
* Release the I/O Port regions
*/
for (j = 0; j < MAX_IO_REGS - 1; j++) {
release_region(sc_adapter[i]->ioport[j], 1);
pr_debug("Releasing I/O Port %#x\n",
sc_adapter[i]->ioport[j]);
}
release_region(sc_adapter[i]->ioport[IRQ_SELECT], 1);
pr_debug("Releasing I/O Port %#x\n",
sc_adapter[i]->ioport[IRQ_SELECT]);
/*
* Release any memory we alloced
*/
kfree(sc_adapter[i]->channel);
kfree(sc_adapter[i]->card);
kfree(sc_adapter[i]);
}
pr_info("SpellCaster ISA ISDN Adapter Driver Unloaded.\n");
}
static int identify_board(unsigned long rambase, unsigned int iobase)
{
unsigned int pgport;
unsigned long sig;
DualPortMemory *dpm;
RspMessage rcvmsg;
ReqMessage sndmsg;
HWConfig_pl hwci;
int x;
pr_debug("Attempting to identify adapter @ 0x%lx io 0x%x\n",
rambase, iobase);
/*
* Enable the base pointer
*/
outb(rambase >> 12, iobase + 0x2c00);
switch (rambase >> 12 & 0x0F) {
case 0x0:
pgport = iobase + PG0_OFFSET;
pr_debug("Page Register offset is 0x%x\n", PG0_OFFSET);
break;
case 0x4:
pgport = iobase + PG1_OFFSET;
pr_debug("Page Register offset is 0x%x\n", PG1_OFFSET);
break;
case 0x8:
pgport = iobase + PG2_OFFSET;
pr_debug("Page Register offset is 0x%x\n", PG2_OFFSET);
break;
case 0xC:
pgport = iobase + PG3_OFFSET;
pr_debug("Page Register offset is 0x%x\n", PG3_OFFSET);
break;
default:
pr_debug("Invalid rambase 0x%lx\n", rambase);
return -1;
}
/*
* Try to identify a PRI card
*/
outb(PRI_BASEPG_VAL, pgport);
msleep_interruptible(1000);
sig = readl(rambase + SIG_OFFSET);
pr_debug("Looking for a signature, got 0x%lx\n", sig);
if (sig == SIGNATURE)
return PRI_BOARD;
/*
* Try to identify a PRI card
*/
outb(BRI_BASEPG_VAL, pgport);
msleep_interruptible(1000);
sig = readl(rambase + SIG_OFFSET);
pr_debug("Looking for a signature, got 0x%lx\n", sig);
if (sig == SIGNATURE)
return BRI_BOARD;
return -1;
/*
* Try to spot a card
*/
sig = readl(rambase + SIG_OFFSET);
pr_debug("Looking for a signature, got 0x%lx\n", sig);
if (sig != SIGNATURE)
return -1;
dpm = (DualPortMemory *) rambase;
memset(&sndmsg, 0, MSG_LEN);
sndmsg.msg_byte_cnt = 3;
sndmsg.type = cmReqType1;
sndmsg.class = cmReqClass0;
sndmsg.code = cmReqHWConfig;
memcpy_toio(&(dpm->req_queue[dpm->req_head++]), &sndmsg, MSG_LEN);
outb(0, iobase + 0x400);
pr_debug("Sent HWConfig message\n");
/*
* Wait for the response
*/
x = 0;
while ((inb(iobase + FIFOSTAT_OFFSET) & RF_HAS_DATA) && x < 100) {
schedule_timeout_interruptible(1);
x++;
}
if (x == 100) {
pr_debug("Timeout waiting for response\n");
return -1;
}
memcpy_fromio(&rcvmsg, &(dpm->rsp_queue[dpm->rsp_tail]), MSG_LEN);
pr_debug("Got HWConfig response, status = 0x%x\n", rcvmsg.rsp_status);
memcpy(&hwci, &(rcvmsg.msg_data.HWCresponse), sizeof(HWConfig_pl));
pr_debug("Hardware Config: Interface: %s, RAM Size: %ld, Serial: %s\n"
" Part: %s, Rev: %s\n",
hwci.st_u_sense ? "S/T" : "U", hwci.ram_size,
hwci.serial_no, hwci.part_no, hwci.rev_no);
if (!strncmp(PRI_PARTNO, hwci.part_no, 6))
return PRI_BOARD;
if (!strncmp(BRI_PARTNO, hwci.part_no, 6))
return BRI_BOARD;
return -1;
}
module_init(sc_init);
module_exit(sc_exit);

View File

@ -1,247 +0,0 @@
/* $Id: interrupt.c,v 1.4.8.3 2001/09/23 22:24:59 kai Exp $
*
* Copyright (C) 1996 SpellCaster Telecommunications Inc.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* For more information, please contact gpl-info@spellcast.com or write:
*
* SpellCaster Telecommunications Inc.
* 5621 Finch Avenue East, Unit #3
* Scarborough, Ontario Canada
* M1B 2T9
* +1 (416) 297-8565
* +1 (416) 297-6433 Facsimile
*/
#include "includes.h"
#include "hardware.h"
#include "message.h"
#include "card.h"
#include <linux/interrupt.h>
/*
*
*/
irqreturn_t interrupt_handler(int dummy, void *card_inst)
{
RspMessage rcvmsg;
int channel;
int card = (int)(unsigned long) card_inst;
if (!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
return IRQ_NONE;
}
pr_debug("%s: Entered Interrupt handler\n",
sc_adapter[card]->devicename);
/*
* Pull all of the waiting messages off the response queue
*/
while (!receivemessage(card, &rcvmsg)) {
/*
* Push the message to the adapter structure for
* send_and_receive to snoop
*/
if (sc_adapter[card]->want_async_messages)
memcpy(&(sc_adapter[card]->async_msg),
&rcvmsg, sizeof(RspMessage));
channel = (unsigned int) rcvmsg.phy_link_no;
/*
* Trap Invalid request messages
*/
if (IS_CM_MESSAGE(rcvmsg, 0, 0, Invalid)) {
pr_debug("%s: Invalid request Message, rsp_status = %d\n",
sc_adapter[card]->devicename,
rcvmsg.rsp_status);
break;
}
/*
* Check for a linkRead message
*/
if (IS_CE_MESSAGE(rcvmsg, Lnk, 1, Read))
{
pr_debug("%s: Received packet 0x%x bytes long at 0x%lx\n",
sc_adapter[card]->devicename,
rcvmsg.msg_data.response.msg_len,
rcvmsg.msg_data.response.buff_offset);
rcvpkt(card, &rcvmsg);
continue;
}
/*
* Handle a write acknoledgement
*/
if (IS_CE_MESSAGE(rcvmsg, Lnk, 1, Write)) {
pr_debug("%s: Packet Send ACK on channel %d\n",
sc_adapter[card]->devicename,
rcvmsg.phy_link_no);
sc_adapter[card]->channel[rcvmsg.phy_link_no - 1].free_sendbufs++;
continue;
}
/*
* Handle a connection message
*/
if (IS_CE_MESSAGE(rcvmsg, Phy, 1, Connect))
{
unsigned int callid;
setup_parm setup;
pr_debug("%s: Connect message: line %d: status %d: cause 0x%x\n",
sc_adapter[card]->devicename,
rcvmsg.phy_link_no,
rcvmsg.rsp_status,
rcvmsg.msg_data.byte_array[2]);
memcpy(&callid, rcvmsg.msg_data.byte_array, sizeof(int));
if (callid >= 0x8000 && callid <= 0xFFFF)
{
pr_debug("%s: Got Dial-Out Rsp\n",
sc_adapter[card]->devicename);
indicate_status(card, ISDN_STAT_DCONN,
(unsigned long)rcvmsg.phy_link_no - 1, NULL);
}
else if (callid >= 0x0000 && callid <= 0x7FFF)
{
int len;
pr_debug("%s: Got Incoming Call\n",
sc_adapter[card]->devicename);
len = strlcpy(setup.phone, &(rcvmsg.msg_data.byte_array[4]),
sizeof(setup.phone));
if (len >= sizeof(setup.phone))
continue;
len = strlcpy(setup.eazmsn,
sc_adapter[card]->channel[rcvmsg.phy_link_no - 1].dn,
sizeof(setup.eazmsn));
if (len >= sizeof(setup.eazmsn))
continue;
setup.si1 = 7;
setup.si2 = 0;
setup.plan = 0;
setup.screen = 0;
indicate_status(card, ISDN_STAT_ICALL, (unsigned long)rcvmsg.phy_link_no - 1, (char *)&setup);
indicate_status(card, ISDN_STAT_DCONN, (unsigned long)rcvmsg.phy_link_no - 1, NULL);
}
continue;
}
/*
* Handle a disconnection message
*/
if (IS_CE_MESSAGE(rcvmsg, Phy, 1, Disconnect))
{
pr_debug("%s: disconnect message: line %d: status %d: cause 0x%x\n",
sc_adapter[card]->devicename,
rcvmsg.phy_link_no,
rcvmsg.rsp_status,
rcvmsg.msg_data.byte_array[2]);
indicate_status(card, ISDN_STAT_BHUP, (unsigned long)rcvmsg.phy_link_no - 1, NULL);
indicate_status(card, ISDN_STAT_DHUP, (unsigned long)rcvmsg.phy_link_no - 1, NULL);
continue;
}
/*
* Handle a startProc engine up message
*/
if (IS_CM_MESSAGE(rcvmsg, 5, 0, MiscEngineUp)) {
pr_debug("%s: Received EngineUp message\n",
sc_adapter[card]->devicename);
sc_adapter[card]->EngineUp = 1;
sendmessage(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetMyNumber, 1, 0, NULL);
sendmessage(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetMyNumber, 2, 0, NULL);
init_timer(&sc_adapter[card]->stat_timer);
sc_adapter[card]->stat_timer.function = check_phystat;
sc_adapter[card]->stat_timer.data = card;
sc_adapter[card]->stat_timer.expires = jiffies + CHECKSTAT_TIME;
add_timer(&sc_adapter[card]->stat_timer);
continue;
}
/*
* Start proc response
*/
if (IS_CM_MESSAGE(rcvmsg, 2, 0, StartProc)) {
pr_debug("%s: StartProc Response Status %d\n",
sc_adapter[card]->devicename,
rcvmsg.rsp_status);
continue;
}
/*
* Handle a GetMyNumber Rsp
*/
if (IS_CE_MESSAGE(rcvmsg, Call, 0, GetMyNumber)) {
strlcpy(sc_adapter[card]->channel[rcvmsg.phy_link_no - 1].dn,
rcvmsg.msg_data.byte_array,
sizeof(rcvmsg.msg_data.byte_array));
continue;
}
/*
* PhyStatus response
*/
if (IS_CE_MESSAGE(rcvmsg, Phy, 2, Status)) {
unsigned int b1stat, b2stat;
/*
* Covert the message data to the adapter->phystat code
*/
b1stat = (unsigned int) rcvmsg.msg_data.byte_array[0];
b2stat = (unsigned int) rcvmsg.msg_data.byte_array[1];
sc_adapter[card]->nphystat = (b2stat >> 8) | b1stat; /* endian?? */
pr_debug("%s: PhyStat is 0x%2x\n",
sc_adapter[card]->devicename,
sc_adapter[card]->nphystat);
continue;
}
/*
* Handle a GetFramFormat
*/
if (IS_CE_MESSAGE(rcvmsg, Call, 0, GetFrameFormat)) {
if (rcvmsg.msg_data.byte_array[0] != HDLC_PROTO) {
unsigned int proto = HDLC_PROTO;
/*
* Set board format to HDLC if it wasn't already
*/
pr_debug("%s: current frame format: 0x%x, will change to HDLC\n",
sc_adapter[card]->devicename,
rcvmsg.msg_data.byte_array[0]);
sendmessage(card, CEPID, ceReqTypeCall,
ceReqClass0,
ceReqCallSetFrameFormat,
(unsigned char)channel + 1,
1, &proto);
}
continue;
}
/*
* Hmm...
*/
pr_debug("%s: Received unhandled message (%d,%d,%d) link %d\n",
sc_adapter[card]->devicename,
rcvmsg.type, rcvmsg.class, rcvmsg.code,
rcvmsg.phy_link_no);
} /* while */
pr_debug("%s: Exiting Interrupt Handler\n",
sc_adapter[card]->devicename);
return IRQ_HANDLED;
}

View File

@ -1,582 +0,0 @@
/*
* Copyright (C) 1996 SpellCaster Telecommunications Inc.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include "includes.h"
#include "hardware.h"
#include "message.h"
#include "card.h"
#include "scioc.h"
static int GetStatus(int card, boardInfo *);
/*
* Process private IOCTL messages (typically from scctrl)
*/
int sc_ioctl(int card, scs_ioctl *data)
{
int status;
RspMessage *rcvmsg;
char *spid;
char *dn;
char switchtype;
char speed;
rcvmsg = kmalloc(sizeof(RspMessage), GFP_KERNEL);
if (!rcvmsg)
return -ENOMEM;
switch (data->command) {
case SCIOCRESET: /* Perform a hard reset of the adapter */
{
pr_debug("%s: SCIOCRESET: ioctl received\n",
sc_adapter[card]->devicename);
sc_adapter[card]->StartOnReset = 0;
kfree(rcvmsg);
return reset(card);
}
case SCIOCLOAD:
{
char *srec;
srec = kmalloc(SCIOC_SRECSIZE, GFP_KERNEL);
if (!srec) {
kfree(rcvmsg);
return -ENOMEM;
}
pr_debug("%s: SCIOLOAD: ioctl received\n",
sc_adapter[card]->devicename);
if (sc_adapter[card]->EngineUp) {
pr_debug("%s: SCIOCLOAD: command failed, LoadProc while engine running.\n",
sc_adapter[card]->devicename);
kfree(rcvmsg);
kfree(srec);
return -1;
}
/*
* Get the SRec from user space
*/
if (copy_from_user(srec, data->dataptr, SCIOC_SRECSIZE)) {
kfree(rcvmsg);
kfree(srec);
return -EFAULT;
}
status = send_and_receive(card, CMPID, cmReqType2, cmReqClass0, cmReqLoadProc,
0, SCIOC_SRECSIZE, srec, rcvmsg, SAR_TIMEOUT);
kfree(rcvmsg);
kfree(srec);
if (status) {
pr_debug("%s: SCIOCLOAD: command failed, status = %d\n",
sc_adapter[card]->devicename, status);
return -1;
}
else {
pr_debug("%s: SCIOCLOAD: command successful\n",
sc_adapter[card]->devicename);
return 0;
}
}
case SCIOCSTART:
{
kfree(rcvmsg);
pr_debug("%s: SCIOSTART: ioctl received\n",
sc_adapter[card]->devicename);
if (sc_adapter[card]->EngineUp) {
pr_debug("%s: SCIOCSTART: command failed, engine already running.\n",
sc_adapter[card]->devicename);
return -1;
}
sc_adapter[card]->StartOnReset = 1;
startproc(card);
return 0;
}
case SCIOCSETSWITCH:
{
pr_debug("%s: SCIOSETSWITCH: ioctl received\n",
sc_adapter[card]->devicename);
/*
* Get the switch type from user space
*/
if (copy_from_user(&switchtype, data->dataptr, sizeof(char))) {
kfree(rcvmsg);
return -EFAULT;
}
pr_debug("%s: SCIOCSETSWITCH: setting switch type to %d\n",
sc_adapter[card]->devicename,
switchtype);
status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallSetSwitchType,
0, sizeof(char), &switchtype, rcvmsg, SAR_TIMEOUT);
if (!status && !(rcvmsg->rsp_status)) {
pr_debug("%s: SCIOCSETSWITCH: command successful\n",
sc_adapter[card]->devicename);
kfree(rcvmsg);
return 0;
}
else {
pr_debug("%s: SCIOCSETSWITCH: command failed (status = %d)\n",
sc_adapter[card]->devicename, status);
kfree(rcvmsg);
return status;
}
}
case SCIOCGETSWITCH:
{
pr_debug("%s: SCIOGETSWITCH: ioctl received\n",
sc_adapter[card]->devicename);
/*
* Get the switch type from the board
*/
status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
ceReqCallGetSwitchType, 0, 0, NULL, rcvmsg, SAR_TIMEOUT);
if (!status && !(rcvmsg->rsp_status)) {
pr_debug("%s: SCIOCGETSWITCH: command successful\n",
sc_adapter[card]->devicename);
}
else {
pr_debug("%s: SCIOCGETSWITCH: command failed (status = %d)\n",
sc_adapter[card]->devicename, status);
kfree(rcvmsg);
return status;
}
switchtype = rcvmsg->msg_data.byte_array[0];
/*
* Package the switch type and send to user space
*/
if (copy_to_user(data->dataptr, &switchtype,
sizeof(char))) {
kfree(rcvmsg);
return -EFAULT;
}
kfree(rcvmsg);
return 0;
}
case SCIOCGETSPID:
{
pr_debug("%s: SCIOGETSPID: ioctl received\n",
sc_adapter[card]->devicename);
spid = kzalloc(SCIOC_SPIDSIZE, GFP_KERNEL);
if (!spid) {
kfree(rcvmsg);
return -ENOMEM;
}
/*
* Get the spid from the board
*/
status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetSPID,
data->channel, 0, NULL, rcvmsg, SAR_TIMEOUT);
if (!status) {
pr_debug("%s: SCIOCGETSPID: command successful\n",
sc_adapter[card]->devicename);
} else {
pr_debug("%s: SCIOCGETSPID: command failed (status = %d)\n",
sc_adapter[card]->devicename, status);
kfree(spid);
kfree(rcvmsg);
return status;
}
strlcpy(spid, rcvmsg->msg_data.byte_array, SCIOC_SPIDSIZE);
/*
* Package the switch type and send to user space
*/
if (copy_to_user(data->dataptr, spid, SCIOC_SPIDSIZE)) {
kfree(spid);
kfree(rcvmsg);
return -EFAULT;
}
kfree(spid);
kfree(rcvmsg);
return 0;
}
case SCIOCSETSPID:
{
pr_debug("%s: DCBIOSETSPID: ioctl received\n",
sc_adapter[card]->devicename);
/*
* Get the spid from user space
*/
spid = memdup_user(data->dataptr, SCIOC_SPIDSIZE);
if (IS_ERR(spid)) {
kfree(rcvmsg);
return PTR_ERR(spid);
}
pr_debug("%s: SCIOCSETSPID: setting channel %d spid to %s\n",
sc_adapter[card]->devicename, data->channel, spid);
status = send_and_receive(card, CEPID, ceReqTypeCall,
ceReqClass0, ceReqCallSetSPID, data->channel,
strlen(spid), spid, rcvmsg, SAR_TIMEOUT);
if (!status && !(rcvmsg->rsp_status)) {
pr_debug("%s: SCIOCSETSPID: command successful\n",
sc_adapter[card]->devicename);
kfree(rcvmsg);
kfree(spid);
return 0;
}
else {
pr_debug("%s: SCIOCSETSPID: command failed (status = %d)\n",
sc_adapter[card]->devicename, status);
kfree(rcvmsg);
kfree(spid);
return status;
}
}
case SCIOCGETDN:
{
pr_debug("%s: SCIOGETDN: ioctl received\n",
sc_adapter[card]->devicename);
/*
* Get the dn from the board
*/
status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetMyNumber,
data->channel, 0, NULL, rcvmsg, SAR_TIMEOUT);
if (!status) {
pr_debug("%s: SCIOCGETDN: command successful\n",
sc_adapter[card]->devicename);
}
else {
pr_debug("%s: SCIOCGETDN: command failed (status = %d)\n",
sc_adapter[card]->devicename, status);
kfree(rcvmsg);
return status;
}
dn = kzalloc(SCIOC_DNSIZE, GFP_KERNEL);
if (!dn) {
kfree(rcvmsg);
return -ENOMEM;
}
strlcpy(dn, rcvmsg->msg_data.byte_array, SCIOC_DNSIZE);
kfree(rcvmsg);
/*
* Package the dn and send to user space
*/
if (copy_to_user(data->dataptr, dn, SCIOC_DNSIZE)) {
kfree(dn);
return -EFAULT;
}
kfree(dn);
return 0;
}
case SCIOCSETDN:
{
pr_debug("%s: SCIOSETDN: ioctl received\n",
sc_adapter[card]->devicename);
/*
* Get the spid from user space
*/
dn = memdup_user(data->dataptr, SCIOC_DNSIZE);
if (IS_ERR(dn)) {
kfree(rcvmsg);
return PTR_ERR(dn);
}
pr_debug("%s: SCIOCSETDN: setting channel %d dn to %s\n",
sc_adapter[card]->devicename, data->channel, dn);
status = send_and_receive(card, CEPID, ceReqTypeCall,
ceReqClass0, ceReqCallSetMyNumber, data->channel,
strlen(dn), dn, rcvmsg, SAR_TIMEOUT);
if (!status && !(rcvmsg->rsp_status)) {
pr_debug("%s: SCIOCSETDN: command successful\n",
sc_adapter[card]->devicename);
kfree(rcvmsg);
kfree(dn);
return 0;
}
else {
pr_debug("%s: SCIOCSETDN: command failed (status = %d)\n",
sc_adapter[card]->devicename, status);
kfree(rcvmsg);
kfree(dn);
return status;
}
}
case SCIOCTRACE:
pr_debug("%s: SCIOTRACE: ioctl received\n",
sc_adapter[card]->devicename);
/* sc_adapter[card]->trace = !sc_adapter[card]->trace;
pr_debug("%s: SCIOCTRACE: tracing turned %s\n",
sc_adapter[card]->devicename,
sc_adapter[card]->trace ? "ON" : "OFF"); */
break;
case SCIOCSTAT:
{
boardInfo *bi;
pr_debug("%s: SCIOSTAT: ioctl received\n",
sc_adapter[card]->devicename);
bi = kzalloc(sizeof(boardInfo), GFP_KERNEL);
if (!bi) {
kfree(rcvmsg);
return -ENOMEM;
}
kfree(rcvmsg);
GetStatus(card, bi);
if (copy_to_user(data->dataptr, bi, sizeof(boardInfo))) {
kfree(bi);
return -EFAULT;
}
kfree(bi);
return 0;
}
case SCIOCGETSPEED:
{
pr_debug("%s: SCIOGETSPEED: ioctl received\n",
sc_adapter[card]->devicename);
/*
* Get the speed from the board
*/
status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
ceReqCallGetCallType, data->channel, 0, NULL, rcvmsg, SAR_TIMEOUT);
if (!status && !(rcvmsg->rsp_status)) {
pr_debug("%s: SCIOCGETSPEED: command successful\n",
sc_adapter[card]->devicename);
}
else {
pr_debug("%s: SCIOCGETSPEED: command failed (status = %d)\n",
sc_adapter[card]->devicename, status);
kfree(rcvmsg);
return status;
}
speed = rcvmsg->msg_data.byte_array[0];
kfree(rcvmsg);
/*
* Package the switch type and send to user space
*/
if (copy_to_user(data->dataptr, &speed, sizeof(char)))
return -EFAULT;
return 0;
}
case SCIOCSETSPEED:
pr_debug("%s: SCIOCSETSPEED: ioctl received\n",
sc_adapter[card]->devicename);
break;
case SCIOCLOOPTST:
pr_debug("%s: SCIOCLOOPTST: ioctl received\n",
sc_adapter[card]->devicename);
break;
default:
kfree(rcvmsg);
return -1;
}
kfree(rcvmsg);
return 0;
}
static int GetStatus(int card, boardInfo *bi)
{
RspMessage rcvmsg;
int i, status;
/*
* Fill in some of the basic info about the board
*/
bi->modelid = sc_adapter[card]->model;
strcpy(bi->serial_no, sc_adapter[card]->hwconfig.serial_no);
strcpy(bi->part_no, sc_adapter[card]->hwconfig.part_no);
bi->iobase = sc_adapter[card]->iobase;
bi->rambase = sc_adapter[card]->rambase;
bi->irq = sc_adapter[card]->interrupt;
bi->ramsize = sc_adapter[card]->hwconfig.ram_size;
bi->interface = sc_adapter[card]->hwconfig.st_u_sense;
strcpy(bi->load_ver, sc_adapter[card]->load_ver);
strcpy(bi->proc_ver, sc_adapter[card]->proc_ver);
/*
* Get the current PhyStats and LnkStats
*/
status = send_and_receive(card, CEPID, ceReqTypePhy, ceReqClass2,
ceReqPhyStatus, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
if (!status) {
if (sc_adapter[card]->model < PRI_BOARD) {
bi->l1_status = rcvmsg.msg_data.byte_array[2];
for (i = 0; i < BRI_CHANNELS; i++)
bi->status.bristats[i].phy_stat =
rcvmsg.msg_data.byte_array[i];
}
else {
bi->l1_status = rcvmsg.msg_data.byte_array[0];
bi->l2_status = rcvmsg.msg_data.byte_array[1];
for (i = 0; i < PRI_CHANNELS; i++)
bi->status.pristats[i].phy_stat =
rcvmsg.msg_data.byte_array[i + 2];
}
}
/*
* Get the call types for each channel
*/
for (i = 0; i < sc_adapter[card]->nChannels; i++) {
status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
ceReqCallGetCallType, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
if (!status) {
if (sc_adapter[card]->model == PRI_BOARD) {
bi->status.pristats[i].call_type =
rcvmsg.msg_data.byte_array[0];
}
else {
bi->status.bristats[i].call_type =
rcvmsg.msg_data.byte_array[0];
}
}
}
/*
* If PRI, get the call states and service states for each channel
*/
if (sc_adapter[card]->model == PRI_BOARD) {
/*
* Get the call states
*/
status = send_and_receive(card, CEPID, ceReqTypeStat, ceReqClass2,
ceReqPhyChCallState, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
if (!status) {
for (i = 0; i < PRI_CHANNELS; i++)
bi->status.pristats[i].call_state =
rcvmsg.msg_data.byte_array[i];
}
/*
* Get the service states
*/
status = send_and_receive(card, CEPID, ceReqTypeStat, ceReqClass2,
ceReqPhyChServState, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
if (!status) {
for (i = 0; i < PRI_CHANNELS; i++)
bi->status.pristats[i].serv_state =
rcvmsg.msg_data.byte_array[i];
}
/*
* Get the link stats for the channels
*/
for (i = 1; i <= PRI_CHANNELS; i++) {
status = send_and_receive(card, CEPID, ceReqTypeLnk, ceReqClass0,
ceReqLnkGetStats, i, 0, NULL, &rcvmsg, SAR_TIMEOUT);
if (!status) {
bi->status.pristats[i - 1].link_stats.tx_good =
(unsigned long)rcvmsg.msg_data.byte_array[0];
bi->status.pristats[i - 1].link_stats.tx_bad =
(unsigned long)rcvmsg.msg_data.byte_array[4];
bi->status.pristats[i - 1].link_stats.rx_good =
(unsigned long)rcvmsg.msg_data.byte_array[8];
bi->status.pristats[i - 1].link_stats.rx_bad =
(unsigned long)rcvmsg.msg_data.byte_array[12];
}
}
/*
* Link stats for the D channel
*/
status = send_and_receive(card, CEPID, ceReqTypeLnk, ceReqClass0,
ceReqLnkGetStats, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
if (!status) {
bi->dch_stats.tx_good = (unsigned long)rcvmsg.msg_data.byte_array[0];
bi->dch_stats.tx_bad = (unsigned long)rcvmsg.msg_data.byte_array[4];
bi->dch_stats.rx_good = (unsigned long)rcvmsg.msg_data.byte_array[8];
bi->dch_stats.rx_bad = (unsigned long)rcvmsg.msg_data.byte_array[12];
}
return 0;
}
/*
* If BRI or POTS, Get SPID, DN and call types for each channel
*/
/*
* Get the link stats for the channels
*/
status = send_and_receive(card, CEPID, ceReqTypeLnk, ceReqClass0,
ceReqLnkGetStats, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
if (!status) {
bi->dch_stats.tx_good = (unsigned long)rcvmsg.msg_data.byte_array[0];
bi->dch_stats.tx_bad = (unsigned long)rcvmsg.msg_data.byte_array[4];
bi->dch_stats.rx_good = (unsigned long)rcvmsg.msg_data.byte_array[8];
bi->dch_stats.rx_bad = (unsigned long)rcvmsg.msg_data.byte_array[12];
bi->status.bristats[0].link_stats.tx_good =
(unsigned long)rcvmsg.msg_data.byte_array[16];
bi->status.bristats[0].link_stats.tx_bad =
(unsigned long)rcvmsg.msg_data.byte_array[20];
bi->status.bristats[0].link_stats.rx_good =
(unsigned long)rcvmsg.msg_data.byte_array[24];
bi->status.bristats[0].link_stats.rx_bad =
(unsigned long)rcvmsg.msg_data.byte_array[28];
bi->status.bristats[1].link_stats.tx_good =
(unsigned long)rcvmsg.msg_data.byte_array[32];
bi->status.bristats[1].link_stats.tx_bad =
(unsigned long)rcvmsg.msg_data.byte_array[36];
bi->status.bristats[1].link_stats.rx_good =
(unsigned long)rcvmsg.msg_data.byte_array[40];
bi->status.bristats[1].link_stats.rx_bad =
(unsigned long)rcvmsg.msg_data.byte_array[44];
}
/*
* Get the SPIDs
*/
for (i = 0; i < BRI_CHANNELS; i++) {
status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
ceReqCallGetSPID, i + 1, 0, NULL, &rcvmsg, SAR_TIMEOUT);
if (!status)
strcpy(bi->status.bristats[i].spid, rcvmsg.msg_data.byte_array);
}
/*
* Get the DNs
*/
for (i = 0; i < BRI_CHANNELS; i++) {
status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
ceReqCallGetMyNumber, i + 1, 0, NULL, &rcvmsg, SAR_TIMEOUT);
if (!status)
strcpy(bi->status.bristats[i].dn, rcvmsg.msg_data.byte_array);
}
return 0;
}

View File

@ -1,230 +0,0 @@
/* $Id: message.c,v 1.5.8.2 2001/09/23 22:24:59 kai Exp $
*
* functions for sending and receiving control messages
*
* Copyright (C) 1996 SpellCaster Telecommunications Inc.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* For more information, please contact gpl-info@spellcast.com or write:
*
* SpellCaster Telecommunications Inc.
* 5621 Finch Avenue East, Unit #3
* Scarborough, Ontario Canada
* M1B 2T9
* +1 (416) 297-8565
* +1 (416) 297-6433 Facsimile
*/
#include <linux/sched.h>
#include "includes.h"
#include "hardware.h"
#include "message.h"
#include "card.h"
/*
* receive a message from the board
*/
int receivemessage(int card, RspMessage *rspmsg)
{
DualPortMemory *dpm;
unsigned long flags;
if (!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
return -EINVAL;
}
pr_debug("%s: Entered receivemessage\n",
sc_adapter[card]->devicename);
/*
* See if there are messages waiting
*/
if (inb(sc_adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA) {
/*
* Map in the DPM to the base page and copy the message
*/
spin_lock_irqsave(&sc_adapter[card]->lock, flags);
outb((sc_adapter[card]->shmem_magic >> 14) | 0x80,
sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
dpm = (DualPortMemory *) sc_adapter[card]->rambase;
memcpy_fromio(rspmsg, &(dpm->rsp_queue[dpm->rsp_tail]),
MSG_LEN);
dpm->rsp_tail = (dpm->rsp_tail + 1) % MAX_MESSAGES;
inb(sc_adapter[card]->ioport[FIFO_READ]);
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
/*
* Tell the board that the message is received
*/
pr_debug("%s: Received Message seq:%d pid:%d time:%d cmd:%d "
"cnt:%d (type,class,code):(%d,%d,%d) "
"link:%d stat:0x%x\n",
sc_adapter[card]->devicename,
rspmsg->sequence_no,
rspmsg->process_id,
rspmsg->time_stamp,
rspmsg->cmd_sequence_no,
rspmsg->msg_byte_cnt,
rspmsg->type,
rspmsg->class,
rspmsg->code,
rspmsg->phy_link_no,
rspmsg->rsp_status);
return 0;
}
return -ENOMSG;
}
/*
* send a message to the board
*/
int sendmessage(int card,
unsigned int procid,
unsigned int type,
unsigned int class,
unsigned int code,
unsigned int link,
unsigned int data_len,
unsigned int *data)
{
DualPortMemory *dpm;
ReqMessage sndmsg;
unsigned long flags;
if (!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
return -EINVAL;
}
/*
* Make sure we only send CEPID messages when the engine is up
* and CMPID messages when it is down
*/
if (sc_adapter[card]->EngineUp && procid == CMPID) {
pr_debug("%s: Attempt to send CM message with engine up\n",
sc_adapter[card]->devicename);
return -ESRCH;
}
if (!sc_adapter[card]->EngineUp && procid == CEPID) {
pr_debug("%s: Attempt to send CE message with engine down\n",
sc_adapter[card]->devicename);
return -ESRCH;
}
memset(&sndmsg, 0, MSG_LEN);
sndmsg.msg_byte_cnt = 4;
sndmsg.type = type;
sndmsg.class = class;
sndmsg.code = code;
sndmsg.phy_link_no = link;
if (data_len > 0) {
if (data_len > MSG_DATA_LEN)
data_len = MSG_DATA_LEN;
memcpy(&(sndmsg.msg_data), data, data_len);
sndmsg.msg_byte_cnt = data_len + 8;
}
sndmsg.process_id = procid;
sndmsg.sequence_no = sc_adapter[card]->seq_no++ % 256;
/*
* wait for an empty slot in the queue
*/
while (!(inb(sc_adapter[card]->ioport[FIFO_STATUS]) & WF_NOT_FULL))
udelay(1);
/*
* Disable interrupts and map in shared memory
*/
spin_lock_irqsave(&sc_adapter[card]->lock, flags);
outb((sc_adapter[card]->shmem_magic >> 14) | 0x80,
sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
dpm = (DualPortMemory *) sc_adapter[card]->rambase; /* Fix me */
memcpy_toio(&(dpm->req_queue[dpm->req_head]), &sndmsg, MSG_LEN);
dpm->req_head = (dpm->req_head + 1) % MAX_MESSAGES;
outb(sndmsg.sequence_no, sc_adapter[card]->ioport[FIFO_WRITE]);
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
pr_debug("%s: Sent Message seq:%d pid:%d time:%d "
"cnt:%d (type,class,code):(%d,%d,%d) "
"link:%d\n ",
sc_adapter[card]->devicename,
sndmsg.sequence_no,
sndmsg.process_id,
sndmsg.time_stamp,
sndmsg.msg_byte_cnt,
sndmsg.type,
sndmsg.class,
sndmsg.code,
sndmsg.phy_link_no);
return 0;
}
int send_and_receive(int card,
unsigned int procid,
unsigned char type,
unsigned char class,
unsigned char code,
unsigned char link,
unsigned char data_len,
unsigned char *data,
RspMessage *mesgdata,
int timeout)
{
int retval;
int tries;
if (!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
return -EINVAL;
}
sc_adapter[card]->want_async_messages = 1;
retval = sendmessage(card, procid, type, class, code, link,
data_len, (unsigned int *) data);
if (retval) {
pr_debug("%s: SendMessage failed in SAR\n",
sc_adapter[card]->devicename);
sc_adapter[card]->want_async_messages = 0;
return -EIO;
}
tries = 0;
/* wait for the response */
while (tries < timeout) {
schedule_timeout_interruptible(1);
pr_debug("SAR waiting..\n");
/*
* See if we got our message back
*/
if ((sc_adapter[card]->async_msg.type == type) &&
(sc_adapter[card]->async_msg.class == class) &&
(sc_adapter[card]->async_msg.code == code) &&
(sc_adapter[card]->async_msg.phy_link_no == link)) {
/*
* Got it!
*/
pr_debug("%s: Got ASYNC message\n",
sc_adapter[card]->devicename);
memcpy(mesgdata, &(sc_adapter[card]->async_msg),
sizeof(RspMessage));
sc_adapter[card]->want_async_messages = 0;
return 0;
}
tries++;
}
pr_debug("%s: SAR message timeout\n", sc_adapter[card]->devicename);
sc_adapter[card]->want_async_messages = 0;
return -ETIME;
}

View File

@ -1,245 +0,0 @@
/* $Id: message.h,v 1.1.10.1 2001/09/23 22:24:59 kai Exp $
*
* Copyright (C) 1996 SpellCaster Telecommunications Inc.
*
* structures, macros and defines useful for sending
* messages to the adapter
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* For more information, please contact gpl-info@spellcast.com or write:
*
* SpellCaster Telecommunications Inc.
* 5621 Finch Avenue East, Unit #3
* Scarborough, Ontario Canada
* M1B 2T9
* +1 (416) 297-8565
* +1 (416) 297-6433 Facsimile
*/
/*
* Board message macros, defines and structures
*/
#ifndef MESSAGE_H
#define MESSAGE_H
#define MAX_MESSAGES 32 /* Maximum messages that can be
queued */
#define MSG_DATA_LEN 48 /* Maximum size of message payload */
#define MSG_LEN 64 /* Size of a message */
#define CMPID 0 /* Loader message process ID */
#define CEPID 64 /* Firmware message process ID */
/*
* Macro to determine if a message is a loader message
*/
#define IS_CM_MESSAGE(mesg, tx, cx, dx) \
((mesg.type == cmRspType##tx) \
&& (mesg.class == cmRspClass##cx) \
&& (mesg.code == cmRsp##dx))
/*
* Macro to determine if a message is a firmware message
*/
#define IS_CE_MESSAGE(mesg, tx, cx, dx) \
((mesg.type == ceRspType##tx) \
&& (mesg.class == ceRspClass##cx) \
&& (mesg.code == ceRsp##tx##dx))
/*
* Loader Request and Response Messages
*/
/* message types */
#define cmReqType1 1
#define cmReqType2 2
#define cmRspType0 0
#define cmRspType1 1
#define cmRspType2 2
#define cmRspType5 5
/* message classes */
#define cmReqClass0 0
#define cmRspClass0 0
/* message codes */
#define cmReqHWConfig 1 /* 1,0,1 */
#define cmReqMsgLpbk 2 /* 1,0,2 */
#define cmReqVersion 3 /* 1,0,3 */
#define cmReqLoadProc 1 /* 2,0,1 */
#define cmReqStartProc 2 /* 2,0,2 */
#define cmReqReadMem 6 /* 2,0,6 */
#define cmRspHWConfig cmReqHWConfig
#define cmRspMsgLpbk cmReqMsgLpbk
#define cmRspVersion cmReqVersion
#define cmRspLoadProc cmReqLoadProc
#define cmRspStartProc cmReqStartProc
#define cmRspReadMem cmReqReadMem
#define cmRspMiscEngineUp 1 /* 5,0,1 */
#define cmRspInvalid 0 /* 0,0,0 */
/*
* Firmware Request and Response Messages
*/
/* message types */
#define ceReqTypePhy 1
#define ceReqTypeLnk 2
#define ceReqTypeCall 3
#define ceReqTypeStat 1
#define ceRspTypeErr 0
#define ceRspTypePhy ceReqTypePhy
#define ceRspTypeLnk ceReqTypeLnk
#define ceRspTypeCall ceReqTypeCall
#define ceRspTypeStat ceReqTypeStat
/* message classes */
#define ceReqClass0 0
#define ceReqClass1 1
#define ceReqClass2 2
#define ceReqClass3 3
#define ceRspClass0 ceReqClass0
#define ceRspClass1 ceReqClass1
#define ceRspClass2 ceReqClass2
#define ceRspClass3 ceReqClass3
/* message codes (B) = BRI only, (P) = PRI only, (V) = POTS only */
#define ceReqPhyProcInfo 1 /* 1,0,1 */
#define ceReqPhyConnect 1 /* 1,1,1 */
#define ceReqPhyDisconnect 2 /* 1,1,2 */
#define ceReqPhySetParams 3 /* 1,1,3 (P) */
#define ceReqPhyGetParams 4 /* 1,1,4 (P) */
#define ceReqPhyStatus 1 /* 1,2,1 */
#define ceReqPhyAcfaStatus 2 /* 1,2,2 (P) */
#define ceReqPhyChCallState 3 /* 1,2,3 (P) */
#define ceReqPhyChServState 4 /* 1,2,4 (P) */
#define ceReqPhyRLoopBack 1 /* 1,3,1 */
#define ceRspPhyProcInfo ceReqPhyProcInfo
#define ceRspPhyConnect ceReqPhyConnect
#define ceRspPhyDisconnect ceReqPhyDisconnect
#define ceRspPhySetParams ceReqPhySetParams
#define ceRspPhyGetParams ceReqPhyGetParams
#define ceRspPhyStatus ceReqPhyStatus
#define ceRspPhyAcfaStatus ceReqPhyAcfaStatus
#define ceRspPhyChCallState ceReqPhyChCallState
#define ceRspPhyChServState ceReqPhyChServState
#define ceRspPhyRLoopBack ceReqphyRLoopBack
#define ceReqLnkSetParam 1 /* 2,0,1 */
#define ceReqLnkGetParam 2 /* 2,0,2 */
#define ceReqLnkGetStats 3 /* 2,0,3 */
#define ceReqLnkWrite 1 /* 2,1,1 */
#define ceReqLnkRead 2 /* 2,1,2 */
#define ceReqLnkFlush 3 /* 2,1,3 */
#define ceReqLnkWrBufTrc 4 /* 2,1,4 */
#define ceReqLnkRdBufTrc 5 /* 2,1,5 */
#define ceRspLnkSetParam ceReqLnkSetParam
#define ceRspLnkGetParam ceReqLnkGetParam
#define ceRspLnkGetStats ceReqLnkGetStats
#define ceRspLnkWrite ceReqLnkWrite
#define ceRspLnkRead ceReqLnkRead
#define ceRspLnkFlush ceReqLnkFlush
#define ceRspLnkWrBufTrc ceReqLnkWrBufTrc
#define ceRspLnkRdBufTrc ceReqLnkRdBufTrc
#define ceReqCallSetSwitchType 1 /* 3,0,1 */
#define ceReqCallGetSwitchType 2 /* 3,0,2 */
#define ceReqCallSetFrameFormat 3 /* 3,0,3 */
#define ceReqCallGetFrameFormat 4 /* 3,0,4 */
#define ceReqCallSetCallType 5 /* 3,0,5 */
#define ceReqCallGetCallType 6 /* 3,0,6 */
#define ceReqCallSetSPID 7 /* 3,0,7 (!P) */
#define ceReqCallGetSPID 8 /* 3,0,8 (!P) */
#define ceReqCallSetMyNumber 9 /* 3,0,9 (!P) */
#define ceReqCallGetMyNumber 10 /* 3,0,10 (!P) */
#define ceRspCallSetSwitchType ceReqCallSetSwitchType
#define ceRspCallGetSwitchType ceReqCallSetSwitchType
#define ceRspCallSetFrameFormat ceReqCallSetFrameFormat
#define ceRspCallGetFrameFormat ceReqCallGetFrameFormat
#define ceRspCallSetCallType ceReqCallSetCallType
#define ceRspCallGetCallType ceReqCallGetCallType
#define ceRspCallSetSPID ceReqCallSetSPID
#define ceRspCallGetSPID ceReqCallGetSPID
#define ceRspCallSetMyNumber ceReqCallSetMyNumber
#define ceRspCallGetMyNumber ceReqCallGetMyNumber
#define ceRspStatAcfaStatus 2
#define ceRspStat
#define ceRspErrError 0 /* 0,0,0 */
/*
* Call Types
*/
#define CALLTYPE_64K 0
#define CALLTYPE_56K 1
#define CALLTYPE_SPEECH 2
#define CALLTYPE_31KHZ 3
/*
* Link Level data contains a pointer to and the length of
* a buffer in shared RAM. Used by LnkRead and LnkWrite message
* types. Part of RspMsgStruct and ReqMsgStruct.
*/
typedef struct {
unsigned long buff_offset;
unsigned short msg_len;
} LLData;
/*
* Message payload template for an HWConfig message
*/
typedef struct {
char st_u_sense;
char powr_sense;
char sply_sense;
unsigned char asic_id;
long ram_size;
char serial_no[13];
char part_no[13];
char rev_no[2];
} HWConfig_pl;
/*
* A Message
*/
struct message {
unsigned char sequence_no;
unsigned char process_id;
unsigned char time_stamp;
unsigned char cmd_sequence_no; /* Rsp messages only */
unsigned char reserved1[3];
unsigned char msg_byte_cnt;
unsigned char type;
unsigned char class;
unsigned char code;
unsigned char phy_link_no;
unsigned char rsp_status; /* Rsp messages only */
unsigned char reseved2[3];
union {
unsigned char byte_array[MSG_DATA_LEN];
LLData response;
HWConfig_pl HWCresponse;
} msg_data;
};
typedef struct message ReqMessage; /* Request message */
typedef struct message RspMessage; /* Response message */
/*
* The first 5010 bytes of shared memory contain the message queues,
* indexes and other data. This structure is its template
*/
typedef struct {
volatile ReqMessage req_queue[MAX_MESSAGES];
volatile RspMessage rsp_queue[MAX_MESSAGES];
volatile unsigned char req_head;
volatile unsigned char req_tail;
volatile unsigned char rsp_head;
volatile unsigned char rsp_tail;
volatile unsigned long signature;
volatile unsigned long trace_enable;
volatile unsigned char reserved[4];
} DualPortMemory;
#endif

View File

@ -1,204 +0,0 @@
/* $Id: packet.c,v 1.5.8.1 2001/09/23 22:24:59 kai Exp $
*
* Copyright (C) 1996 SpellCaster Telecommunications Inc.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* For more information, please contact gpl-info@spellcast.com or write:
*
* SpellCaster Telecommunications Inc.
* 5621 Finch Avenue East, Unit #3
* Scarborough, Ontario Canada
* M1B 2T9
* +1 (416) 297-8565
* +1 (416) 297-6433 Facsimile
*/
#include "includes.h"
#include "hardware.h"
#include "message.h"
#include "card.h"
int sndpkt(int devId, int channel, int ack, struct sk_buff *data)
{
LLData ReqLnkWrite;
int status;
int card;
unsigned long len;
card = get_card_from_id(devId);
if (!IS_VALID_CARD(card)) {
pr_debug("invalid param: %d is not a valid card id\n", card);
return -ENODEV;
}
pr_debug("%s: sndpkt: frst = 0x%lx nxt = %d f = %d n = %d\n",
sc_adapter[card]->devicename,
sc_adapter[card]->channel[channel].first_sendbuf,
sc_adapter[card]->channel[channel].next_sendbuf,
sc_adapter[card]->channel[channel].free_sendbufs,
sc_adapter[card]->channel[channel].num_sendbufs);
if (!sc_adapter[card]->channel[channel].free_sendbufs) {
pr_debug("%s: out of TX buffers\n",
sc_adapter[card]->devicename);
return -EINVAL;
}
if (data->len > BUFFER_SIZE) {
pr_debug("%s: data overflows buffer size (data > buffer)\n",
sc_adapter[card]->devicename);
return -EINVAL;
}
ReqLnkWrite.buff_offset = sc_adapter[card]->channel[channel].next_sendbuf *
BUFFER_SIZE + sc_adapter[card]->channel[channel].first_sendbuf;
ReqLnkWrite.msg_len = data->len; /* sk_buff size */
pr_debug("%s: writing %d bytes to buffer offset 0x%lx\n",
sc_adapter[card]->devicename,
ReqLnkWrite.msg_len, ReqLnkWrite.buff_offset);
memcpy_toshmem(card, (char *)ReqLnkWrite.buff_offset, data->data, ReqLnkWrite.msg_len);
/*
* sendmessage
*/
pr_debug("%s: sndpkt size=%d, buf_offset=0x%lx buf_indx=%d\n",
sc_adapter[card]->devicename,
ReqLnkWrite.msg_len, ReqLnkWrite.buff_offset,
sc_adapter[card]->channel[channel].next_sendbuf);
status = sendmessage(card, CEPID, ceReqTypeLnk, ceReqClass1, ceReqLnkWrite,
channel + 1, sizeof(LLData), (unsigned int *)&ReqLnkWrite);
len = data->len;
if (status) {
pr_debug("%s: failed to send packet, status = %d\n",
sc_adapter[card]->devicename, status);
return -1;
}
else {
sc_adapter[card]->channel[channel].free_sendbufs--;
sc_adapter[card]->channel[channel].next_sendbuf =
++sc_adapter[card]->channel[channel].next_sendbuf ==
sc_adapter[card]->channel[channel].num_sendbufs ? 0 :
sc_adapter[card]->channel[channel].next_sendbuf;
pr_debug("%s: packet sent successfully\n", sc_adapter[card]->devicename);
dev_kfree_skb(data);
indicate_status(card, ISDN_STAT_BSENT, channel, (char *)&len);
}
return len;
}
void rcvpkt(int card, RspMessage *rcvmsg)
{
LLData newll;
struct sk_buff *skb;
if (!IS_VALID_CARD(card)) {
pr_debug("invalid param: %d is not a valid card id\n", card);
return;
}
switch (rcvmsg->rsp_status) {
case 0x01:
case 0x02:
case 0x70:
pr_debug("%s: error status code: 0x%x\n",
sc_adapter[card]->devicename, rcvmsg->rsp_status);
return;
case 0x00:
if (!(skb = dev_alloc_skb(rcvmsg->msg_data.response.msg_len))) {
printk(KERN_WARNING "%s: rcvpkt out of memory, dropping packet\n",
sc_adapter[card]->devicename);
return;
}
skb_put(skb, rcvmsg->msg_data.response.msg_len);
pr_debug("%s: getting data from offset: 0x%lx\n",
sc_adapter[card]->devicename,
rcvmsg->msg_data.response.buff_offset);
memcpy_fromshmem(card,
skb_put(skb, rcvmsg->msg_data.response.msg_len),
(char *)rcvmsg->msg_data.response.buff_offset,
rcvmsg->msg_data.response.msg_len);
sc_adapter[card]->card->rcvcallb_skb(sc_adapter[card]->driverId,
rcvmsg->phy_link_no - 1, skb);
case 0x03:
/*
* Recycle the buffer
*/
pr_debug("%s: buffer size : %d\n",
sc_adapter[card]->devicename, BUFFER_SIZE);
/* memset_shmem(card, rcvmsg->msg_data.response.buff_offset, 0, BUFFER_SIZE); */
newll.buff_offset = rcvmsg->msg_data.response.buff_offset;
newll.msg_len = BUFFER_SIZE;
pr_debug("%s: recycled buffer at offset 0x%lx size %d\n",
sc_adapter[card]->devicename,
newll.buff_offset, newll.msg_len);
sendmessage(card, CEPID, ceReqTypeLnk, ceReqClass1, ceReqLnkRead,
rcvmsg->phy_link_no, sizeof(LLData), (unsigned int *)&newll);
}
}
int setup_buffers(int card, int c)
{
unsigned int nBuffers, i, cBase;
unsigned int buffer_size;
LLData RcvBuffOffset;
if (!IS_VALID_CARD(card)) {
pr_debug("invalid param: %d is not a valid card id\n", card);
return -ENODEV;
}
/*
* Calculate the buffer offsets (send/recv/send/recv)
*/
pr_debug("%s: setting up channel buffer space in shared RAM\n",
sc_adapter[card]->devicename);
buffer_size = BUFFER_SIZE;
nBuffers = ((sc_adapter[card]->ramsize - BUFFER_BASE) / buffer_size) / 2;
nBuffers = nBuffers > BUFFERS_MAX ? BUFFERS_MAX : nBuffers;
pr_debug("%s: calculating buffer space: %d buffers, %d big\n",
sc_adapter[card]->devicename,
nBuffers, buffer_size);
if (nBuffers < 2) {
pr_debug("%s: not enough buffer space\n",
sc_adapter[card]->devicename);
return -1;
}
cBase = (nBuffers * buffer_size) * (c - 1);
pr_debug("%s: channel buffer offset from shared RAM: 0x%x\n",
sc_adapter[card]->devicename, cBase);
sc_adapter[card]->channel[c - 1].first_sendbuf = BUFFER_BASE + cBase;
sc_adapter[card]->channel[c - 1].num_sendbufs = nBuffers / 2;
sc_adapter[card]->channel[c - 1].free_sendbufs = nBuffers / 2;
sc_adapter[card]->channel[c - 1].next_sendbuf = 0;
pr_debug("%s: send buffer setup complete: first=0x%lx n=%d f=%d, nxt=%d\n",
sc_adapter[card]->devicename,
sc_adapter[card]->channel[c - 1].first_sendbuf,
sc_adapter[card]->channel[c - 1].num_sendbufs,
sc_adapter[card]->channel[c - 1].free_sendbufs,
sc_adapter[card]->channel[c - 1].next_sendbuf);
/*
* Prep the receive buffers
*/
pr_debug("%s: adding %d RecvBuffers:\n",
sc_adapter[card]->devicename, nBuffers / 2);
for (i = 0; i < nBuffers / 2; i++) {
RcvBuffOffset.buff_offset =
((sc_adapter[card]->channel[c - 1].first_sendbuf +
(nBuffers / 2) * buffer_size) + (buffer_size * i));
RcvBuffOffset.msg_len = buffer_size;
pr_debug("%s: adding RcvBuffer #%d offset=0x%lx sz=%d bufsz:%d\n",
sc_adapter[card]->devicename,
i + 1, RcvBuffOffset.buff_offset,
RcvBuffOffset.msg_len, buffer_size);
sendmessage(card, CEPID, ceReqTypeLnk, ceReqClass1, ceReqLnkRead,
c, sizeof(LLData), (unsigned int *)&RcvBuffOffset);
}
return 0;
}

View File

@ -1,110 +0,0 @@
#ifndef __ISDN_SC_SCIOC_H__
#define __ISDN_SC_SCIOC_H__
/*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*/
/*
* IOCTL Command Codes
*/
#define SCIOCLOAD 0x01 /* Load a firmware record */
#define SCIOCRESET 0x02 /* Perform hard reset */
#define SCIOCDEBUG 0x03 /* Set debug level */
#define SCIOCREV 0x04 /* Get driver revision(s) */
#define SCIOCSTART 0x05 /* Start the firmware */
#define SCIOCGETSWITCH 0x06 /* Get switch type */
#define SCIOCSETSWITCH 0x07 /* Set switch type */
#define SCIOCGETSPID 0x08 /* Get channel SPID */
#define SCIOCSETSPID 0x09 /* Set channel SPID */
#define SCIOCGETDN 0x0A /* Get channel DN */
#define SCIOCSETDN 0x0B /* Set channel DN */
#define SCIOCTRACE 0x0C /* Toggle trace mode */
#define SCIOCSTAT 0x0D /* Get line status */
#define SCIOCGETSPEED 0x0E /* Set channel speed */
#define SCIOCSETSPEED 0x0F /* Set channel speed */
#define SCIOCLOOPTST 0x10 /* Perform loopback test */
typedef struct {
int device;
int channel;
unsigned long command;
void __user *dataptr;
} scs_ioctl;
/* Size of strings */
#define SCIOC_SPIDSIZE 49
#define SCIOC_DNSIZE SCIOC_SPIDSIZE
#define SCIOC_REVSIZE SCIOC_SPIDSIZE
#define SCIOC_SRECSIZE 49
typedef struct {
unsigned long tx_good;
unsigned long tx_bad;
unsigned long rx_good;
unsigned long rx_bad;
} ChLinkStats;
typedef struct {
char spid[49];
char dn[49];
char call_type;
char phy_stat;
ChLinkStats link_stats;
} BRIStat;
typedef BRIStat POTStat;
typedef struct {
char call_type;
char call_state;
char serv_state;
char phy_stat;
ChLinkStats link_stats;
} PRIStat;
typedef char PRIInfo;
typedef char BRIInfo;
typedef char POTInfo;
typedef struct {
char acfa_nos;
char acfa_ais;
char acfa_los;
char acfa_rra;
char acfa_slpp;
char acfa_slpn;
char acfa_fsrf;
} ACFAStat;
typedef struct {
unsigned char modelid;
char serial_no[13];
char part_no[13];
char load_ver[11];
char proc_ver[11];
int iobase;
long rambase;
char irq;
long ramsize;
char interface;
char switch_type;
char l1_status;
char l2_status;
ChLinkStats dch_stats;
ACFAStat AcfaStats;
union {
PRIStat pristats[23];
BRIStat bristats[2];
POTStat potsstats[2];
} status;
union {
PRIInfo priinfo;
BRIInfo briinfo;
POTInfo potsinfo;
} info;
} boardInfo;
#endif /* __ISDN_SC_SCIOC_H__ */

View File

@ -1,138 +0,0 @@
/* $Id: shmem.c,v 1.2.10.1 2001/09/23 22:24:59 kai Exp $
*
* Copyright (C) 1996 SpellCaster Telecommunications Inc.
*
* Card functions implementing ISDN4Linux functionality
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* For more information, please contact gpl-info@spellcast.com or write:
*
* SpellCaster Telecommunications Inc.
* 5621 Finch Avenue East, Unit #3
* Scarborough, Ontario Canada
* M1B 2T9
* +1 (416) 297-8565
* +1 (416) 297-6433 Facsimile
*/
#include "includes.h" /* This must be first */
#include "hardware.h"
#include "card.h"
/*
*
*/
void memcpy_toshmem(int card, void *dest, const void *src, size_t n)
{
unsigned long flags;
unsigned char ch;
unsigned long dest_rem = ((unsigned long) dest) % 0x4000;
if (!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
return;
}
if (n > SRAM_PAGESIZE)
return;
/*
* determine the page to load from the address
*/
ch = (unsigned long) dest / SRAM_PAGESIZE;
pr_debug("%s: loaded page %d\n", sc_adapter[card]->devicename, ch);
/*
* Block interrupts and load the page
*/
spin_lock_irqsave(&sc_adapter[card]->lock, flags);
outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80,
sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
memcpy_toio((void __iomem *)(sc_adapter[card]->rambase + dest_rem), src, n);
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
pr_debug("%s: set page to %#x\n", sc_adapter[card]->devicename,
((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80);
pr_debug("%s: copying %zu bytes from %#lx to %#lx\n",
sc_adapter[card]->devicename, n,
(unsigned long) src,
sc_adapter[card]->rambase + ((unsigned long) dest % 0x4000));
}
/*
* Reverse of above
*/
void memcpy_fromshmem(int card, void *dest, const void *src, size_t n)
{
unsigned long flags;
unsigned char ch;
if (!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
return;
}
if (n > SRAM_PAGESIZE) {
return;
}
/*
* determine the page to load from the address
*/
ch = (unsigned long) src / SRAM_PAGESIZE;
pr_debug("%s: loaded page %d\n", sc_adapter[card]->devicename, ch);
/*
* Block interrupts and load the page
*/
spin_lock_irqsave(&sc_adapter[card]->lock, flags);
outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80,
sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
memcpy_fromio(dest, (void *)(sc_adapter[card]->rambase +
((unsigned long) src % 0x4000)), n);
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
pr_debug("%s: set page to %#x\n", sc_adapter[card]->devicename,
((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80);
/* pr_debug("%s: copying %d bytes from %#x to %#x\n",
sc_adapter[card]->devicename, n,
sc_adapter[card]->rambase + ((unsigned long) src %0x4000), (unsigned long) dest); */
}
#if 0
void memset_shmem(int card, void *dest, int c, size_t n)
{
unsigned long flags;
unsigned char ch;
if (!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
return;
}
if (n > SRAM_PAGESIZE) {
return;
}
/*
* determine the page to load from the address
*/
ch = (unsigned long) dest / SRAM_PAGESIZE;
pr_debug("%s: loaded page %d\n", sc_adapter[card]->devicename, ch);
/*
* Block interrupts and load the page
*/
spin_lock_irqsave(&sc_adapter[card]->lock, flags);
outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80,
sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
memset_io(sc_adapter[card]->rambase +
((unsigned long) dest % 0x4000), c, n);
pr_debug("%s: set page to %#x\n", sc_adapter[card]->devicename,
((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80);
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
}
#endif /* 0 */

View File

@ -1,122 +0,0 @@
/* $Id: timer.c,v 1.3.6.1 2001/09/23 22:24:59 kai Exp $
*
* Copyright (C) 1996 SpellCaster Telecommunications Inc.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* For more information, please contact gpl-info@spellcast.com or write:
*
* SpellCaster Telecommunications Inc.
* 5621 Finch Avenue East, Unit #3
* Scarborough, Ontario Canada
* M1B 2T9
* +1 (416) 297-8565
* +1 (416) 297-6433 Facsimile
*/
#include "includes.h"
#include "hardware.h"
#include "message.h"
#include "card.h"
/*
* Write the proper values into the I/O ports following a reset
*/
static void setup_ports(int card)
{
outb((sc_adapter[card]->rambase >> 12), sc_adapter[card]->ioport[EXP_BASE]);
/* And the IRQ */
outb((sc_adapter[card]->interrupt | 0x80),
sc_adapter[card]->ioport[IRQ_SELECT]);
}
/*
* Timed function to check the status of a previous reset
* Must be very fast as this function runs in the context of
* an interrupt handler.
*
* Setup the ioports for the board that were cleared by the reset.
* Then, check to see if the signate has been set. Next, set the
* signature to a known value and issue a startproc if needed.
*/
void sc_check_reset(unsigned long data)
{
unsigned long flags;
unsigned long sig;
int card = (unsigned int) data;
pr_debug("%s: check_timer timer called\n",
sc_adapter[card]->devicename);
/* Setup the io ports */
setup_ports(card);
spin_lock_irqsave(&sc_adapter[card]->lock, flags);
outb(sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport],
(sc_adapter[card]->shmem_magic >> 14) | 0x80);
sig = (unsigned long) *((unsigned long *)(sc_adapter[card]->rambase + SIG_OFFSET));
/* check the signature */
if (sig == SIGNATURE) {
flushreadfifo(card);
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
/* See if we need to do a startproc */
if (sc_adapter[card]->StartOnReset)
startproc(card);
} else {
pr_debug("%s: No signature yet, waiting another %lu jiffies.\n",
sc_adapter[card]->devicename, CHECKRESET_TIME);
mod_timer(&sc_adapter[card]->reset_timer, jiffies + CHECKRESET_TIME);
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
}
}
/*
* Timed function to check the status of a previous reset
* Must be very fast as this function runs in the context of
* an interrupt handler.
*
* Send check sc_adapter->phystat to see if the channels are up
* If they are, tell ISDN4Linux that the board is up. If not,
* tell IADN4Linux that it is up. Always reset the timer to
* fire again (endless loop).
*/
void check_phystat(unsigned long data)
{
unsigned long flags;
int card = (unsigned int) data;
pr_debug("%s: Checking status...\n", sc_adapter[card]->devicename);
/*
* check the results of the last PhyStat and change only if
* has changed drastically
*/
if (sc_adapter[card]->nphystat && !sc_adapter[card]->phystat) { /* All is well */
pr_debug("PhyStat transition to RUN\n");
pr_info("%s: Switch contacted, transmitter enabled\n",
sc_adapter[card]->devicename);
indicate_status(card, ISDN_STAT_RUN, 0, NULL);
}
else if (!sc_adapter[card]->nphystat && sc_adapter[card]->phystat) { /* All is not well */
pr_debug("PhyStat transition to STOP\n");
pr_info("%s: Switch connection lost, transmitter disabled\n",
sc_adapter[card]->devicename);
indicate_status(card, ISDN_STAT_STOP, 0, NULL);
}
sc_adapter[card]->phystat = sc_adapter[card]->nphystat;
/* Reinitialize the timer */
spin_lock_irqsave(&sc_adapter[card]->lock, flags);
mod_timer(&sc_adapter[card]->stat_timer, jiffies + CHECKSTAT_TIME);
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
/* Send a new cePhyStatus message */
sendmessage(card, CEPID, ceReqTypePhy, ceReqClass2,
ceReqPhyStatus, 0, 0, NULL);
}

View File

@ -93,7 +93,8 @@ enum ad_link_speed_type {
AD_LINK_SPEED_10000MBPS,
AD_LINK_SPEED_20000MBPS,
AD_LINK_SPEED_40000MBPS,
AD_LINK_SPEED_56000MBPS
AD_LINK_SPEED_56000MBPS,
AD_LINK_SPEED_100000MBPS,
};
/* compare MAC addresses */
@ -258,6 +259,7 @@ static inline int __check_agg_selection_timer(struct port *port)
* %AD_LINK_SPEED_20000MBPS
* %AD_LINK_SPEED_40000MBPS
* %AD_LINK_SPEED_56000MBPS
* %AD_LINK_SPEED_100000MBPS
*/
static u16 __get_link_speed(struct port *port)
{
@ -305,6 +307,10 @@ static u16 __get_link_speed(struct port *port)
speed = AD_LINK_SPEED_56000MBPS;
break;
case SPEED_100000:
speed = AD_LINK_SPEED_100000MBPS;
break;
default:
/* unknown speed value from ethtool. shouldn't happen */
speed = 0;
@ -681,6 +687,9 @@ static u32 __get_agg_bandwidth(struct aggregator *aggregator)
case AD_LINK_SPEED_56000MBPS:
bandwidth = aggregator->num_of_ports * 56000;
break;
case AD_LINK_SPEED_100000MBPS:
bandwidth = aggregator->num_of_ports * 100000;
break;
default:
bandwidth = 0; /* to silence the compiler */
}

View File

@ -830,7 +830,8 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
}
new_active->delay = 0;
bond_set_slave_link_state(new_active, BOND_LINK_UP);
bond_set_slave_link_state(new_active, BOND_LINK_UP,
BOND_SLAVE_NOTIFY_NOW);
if (BOND_MODE(bond) == BOND_MODE_8023AD)
bond_3ad_handle_link_change(new_active, BOND_LINK_UP);
@ -1066,12 +1067,12 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
return features;
}
#define BOND_VLAN_FEATURES (NETIF_F_ALL_CSUM | NETIF_F_SG | \
#define BOND_VLAN_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \
NETIF_F_HIGHDMA | NETIF_F_LRO)
#define BOND_ENC_FEATURES (NETIF_F_ALL_CSUM | NETIF_F_SG | NETIF_F_RXCSUM |\
NETIF_F_ALL_TSO)
#define BOND_ENC_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
NETIF_F_RXCSUM | NETIF_F_ALL_TSO)
static void bond_compute_features(struct bonding *bond)
{
@ -1198,26 +1199,42 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
return ret;
}
static int bond_master_upper_dev_link(struct net_device *bond_dev,
struct net_device *slave_dev,
struct slave *slave)
static enum netdev_lag_tx_type bond_lag_tx_type(struct bonding *bond)
{
switch (BOND_MODE(bond)) {
case BOND_MODE_ROUNDROBIN:
return NETDEV_LAG_TX_TYPE_ROUNDROBIN;
case BOND_MODE_ACTIVEBACKUP:
return NETDEV_LAG_TX_TYPE_ACTIVEBACKUP;
case BOND_MODE_BROADCAST:
return NETDEV_LAG_TX_TYPE_BROADCAST;
case BOND_MODE_XOR:
case BOND_MODE_8023AD:
return NETDEV_LAG_TX_TYPE_HASH;
default:
return NETDEV_LAG_TX_TYPE_UNKNOWN;
}
}
static int bond_master_upper_dev_link(struct bonding *bond, struct slave *slave)
{
struct netdev_lag_upper_info lag_upper_info;
int err;
err = netdev_master_upper_dev_link_private(slave_dev, bond_dev, slave);
lag_upper_info.tx_type = bond_lag_tx_type(bond);
err = netdev_master_upper_dev_link(slave->dev, bond->dev, slave,
&lag_upper_info);
if (err)
return err;
slave_dev->flags |= IFF_SLAVE;
rtmsg_ifinfo(RTM_NEWLINK, slave_dev, IFF_SLAVE, GFP_KERNEL);
rtmsg_ifinfo(RTM_NEWLINK, slave->dev, IFF_SLAVE, GFP_KERNEL);
return 0;
}
static void bond_upper_dev_unlink(struct net_device *bond_dev,
struct net_device *slave_dev)
static void bond_upper_dev_unlink(struct bonding *bond, struct slave *slave)
{
netdev_upper_dev_unlink(slave_dev, bond_dev);
slave_dev->flags &= ~IFF_SLAVE;
rtmsg_ifinfo(RTM_NEWLINK, slave_dev, IFF_SLAVE, GFP_KERNEL);
netdev_upper_dev_unlink(slave->dev, bond->dev);
slave->dev->flags &= ~IFF_SLAVE;
rtmsg_ifinfo(RTM_NEWLINK, slave->dev, IFF_SLAVE, GFP_KERNEL);
}
static struct slave *bond_alloc_slave(struct bonding *bond)
@ -1299,6 +1316,16 @@ void bond_queue_slave_event(struct slave *slave)
queue_delayed_work(slave->bond->wq, &nnw->work, 0);
}
void bond_lower_state_changed(struct slave *slave)
{
struct netdev_lag_lower_state_info info;
info.link_up = slave->link == BOND_LINK_UP ||
slave->link == BOND_LINK_FAIL;
info.tx_enabled = bond_is_active_slave(slave);
netdev_lower_state_changed(slave->dev, &info);
}
/* enslave device <slave> to bond device <master> */
int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
{
@ -1351,7 +1378,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
* the current ifenslave will set the interface down prior to
* enslaving it; the old ifenslave will not.
*/
if ((slave_dev->flags & IFF_UP)) {
if (slave_dev->flags & IFF_UP) {
netdev_err(bond_dev, "%s is up - this may be due to an out of date ifenslave\n",
slave_dev->name);
res = -EPERM;
@ -1465,6 +1492,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
}
}
/* set slave flag before open to prevent IPv6 addrconf */
slave_dev->flags |= IFF_SLAVE;
/* open the slave since the application closed it */
res = dev_open(slave_dev);
if (res) {
@ -1563,21 +1593,26 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
if (bond_check_dev_link(bond, slave_dev, 0) == BMSR_LSTATUS) {
if (bond->params.updelay) {
bond_set_slave_link_state(new_slave,
BOND_LINK_BACK);
BOND_LINK_BACK,
BOND_SLAVE_NOTIFY_NOW);
new_slave->delay = bond->params.updelay;
} else {
bond_set_slave_link_state(new_slave,
BOND_LINK_UP);
BOND_LINK_UP,
BOND_SLAVE_NOTIFY_NOW);
}
} else {
bond_set_slave_link_state(new_slave, BOND_LINK_DOWN);
bond_set_slave_link_state(new_slave, BOND_LINK_DOWN,
BOND_SLAVE_NOTIFY_NOW);
}
} else if (bond->params.arp_interval) {
bond_set_slave_link_state(new_slave,
(netif_carrier_ok(slave_dev) ?
BOND_LINK_UP : BOND_LINK_DOWN));
BOND_LINK_UP : BOND_LINK_DOWN),
BOND_SLAVE_NOTIFY_NOW);
} else {
bond_set_slave_link_state(new_slave, BOND_LINK_UP);
bond_set_slave_link_state(new_slave, BOND_LINK_UP,
BOND_SLAVE_NOTIFY_NOW);
}
if (new_slave->link != BOND_LINK_DOWN)
@ -1662,7 +1697,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
goto err_detach;
}
res = bond_master_upper_dev_link(bond_dev, slave_dev, new_slave);
res = bond_master_upper_dev_link(bond, new_slave);
if (res) {
netdev_dbg(bond_dev, "Error %d calling bond_master_upper_dev_link\n", res);
goto err_unregister;
@ -1698,7 +1733,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
/* Undo stages on error */
err_upper_unlink:
bond_upper_dev_unlink(bond_dev, slave_dev);
bond_upper_dev_unlink(bond, new_slave);
err_unregister:
netdev_rx_handler_unregister(slave_dev);
@ -1725,6 +1760,7 @@ err_close:
dev_close(slave_dev);
err_restore_mac:
slave_dev->flags &= ~IFF_SLAVE;
if (!bond->params.fail_over_mac ||
BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) {
/* XXX TODO - fom follow mode needs to change master's
@ -1799,12 +1835,14 @@ static int __bond_release_one(struct net_device *bond_dev,
return -EINVAL;
}
bond_set_slave_inactive_flags(slave, BOND_SLAVE_NOTIFY_NOW);
bond_sysfs_slave_del(slave);
/* recompute stats just before removing the slave */
bond_get_stats(bond->dev, &bond->bond_stats);
bond_upper_dev_unlink(bond_dev, slave_dev);
bond_upper_dev_unlink(bond, slave);
/* unregister rx_handler early so bond_handle_frame wouldn't be called
* for this slave anymore.
*/
@ -1996,7 +2034,8 @@ static int bond_miimon_inspect(struct bonding *bond)
if (link_state)
continue;
bond_set_slave_link_state(slave, BOND_LINK_FAIL);
bond_set_slave_link_state(slave, BOND_LINK_FAIL,
BOND_SLAVE_NOTIFY_LATER);
slave->delay = bond->params.downdelay;
if (slave->delay) {
netdev_info(bond->dev, "link status down for %sinterface %s, disabling it in %d ms\n",
@ -2011,7 +2050,8 @@ static int bond_miimon_inspect(struct bonding *bond)
case BOND_LINK_FAIL:
if (link_state) {
/* recovered before downdelay expired */
bond_set_slave_link_state(slave, BOND_LINK_UP);
bond_set_slave_link_state(slave, BOND_LINK_UP,
BOND_SLAVE_NOTIFY_LATER);
slave->last_link_up = jiffies;
netdev_info(bond->dev, "link status up again after %d ms for interface %s\n",
(bond->params.downdelay - slave->delay) *
@ -2033,7 +2073,8 @@ static int bond_miimon_inspect(struct bonding *bond)
if (!link_state)
continue;
bond_set_slave_link_state(slave, BOND_LINK_BACK);
bond_set_slave_link_state(slave, BOND_LINK_BACK,
BOND_SLAVE_NOTIFY_LATER);
slave->delay = bond->params.updelay;
if (slave->delay) {
@ -2047,7 +2088,8 @@ static int bond_miimon_inspect(struct bonding *bond)
case BOND_LINK_BACK:
if (!link_state) {
bond_set_slave_link_state(slave,
BOND_LINK_DOWN);
BOND_LINK_DOWN,
BOND_SLAVE_NOTIFY_LATER);
netdev_info(bond->dev, "link status down again after %d ms for interface %s\n",
(bond->params.updelay - slave->delay) *
bond->params.miimon,
@ -2085,7 +2127,8 @@ static void bond_miimon_commit(struct bonding *bond)
continue;
case BOND_LINK_UP:
bond_set_slave_link_state(slave, BOND_LINK_UP);
bond_set_slave_link_state(slave, BOND_LINK_UP,
BOND_SLAVE_NOTIFY_NOW);
slave->last_link_up = jiffies;
primary = rtnl_dereference(bond->primary_slave);
@ -2125,7 +2168,8 @@ static void bond_miimon_commit(struct bonding *bond)
if (slave->link_failure_count < UINT_MAX)
slave->link_failure_count++;
bond_set_slave_link_state(slave, BOND_LINK_DOWN);
bond_set_slave_link_state(slave, BOND_LINK_DOWN,
BOND_SLAVE_NOTIFY_NOW);
if (BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP ||
BOND_MODE(bond) == BOND_MODE_8023AD)
@ -2708,7 +2752,8 @@ static void bond_ab_arp_commit(struct bonding *bond)
struct slave *current_arp_slave;
current_arp_slave = rtnl_dereference(bond->current_arp_slave);
bond_set_slave_link_state(slave, BOND_LINK_UP);
bond_set_slave_link_state(slave, BOND_LINK_UP,
BOND_SLAVE_NOTIFY_NOW);
if (current_arp_slave) {
bond_set_slave_inactive_flags(
current_arp_slave,
@ -2731,7 +2776,8 @@ static void bond_ab_arp_commit(struct bonding *bond)
if (slave->link_failure_count < UINT_MAX)
slave->link_failure_count++;
bond_set_slave_link_state(slave, BOND_LINK_DOWN);
bond_set_slave_link_state(slave, BOND_LINK_DOWN,
BOND_SLAVE_NOTIFY_NOW);
bond_set_slave_inactive_flags(slave,
BOND_SLAVE_NOTIFY_NOW);
@ -2810,7 +2856,8 @@ static bool bond_ab_arp_probe(struct bonding *bond)
* up when it is actually down
*/
if (!bond_slave_is_up(slave) && slave->link == BOND_LINK_UP) {
bond_set_slave_link_state(slave, BOND_LINK_DOWN);
bond_set_slave_link_state(slave, BOND_LINK_DOWN,
BOND_SLAVE_NOTIFY_LATER);
if (slave->link_failure_count < UINT_MAX)
slave->link_failure_count++;
@ -2830,7 +2877,8 @@ static bool bond_ab_arp_probe(struct bonding *bond)
if (!new_slave)
goto check_state;
bond_set_slave_link_state(new_slave, BOND_LINK_BACK);
bond_set_slave_link_state(new_slave, BOND_LINK_BACK,
BOND_SLAVE_NOTIFY_LATER);
bond_set_slave_active_flags(new_slave, BOND_SLAVE_NOTIFY_LATER);
bond_arp_send_all(bond, new_slave);
new_slave->last_link_up = jiffies;
@ -2838,7 +2886,7 @@ static bool bond_ab_arp_probe(struct bonding *bond)
check_state:
bond_for_each_slave_rcu(bond, slave, iter) {
if (slave->should_notify) {
if (slave->should_notify || slave->should_notify_link) {
should_notify_rtnl = BOND_SLAVE_NOTIFY_NOW;
break;
}
@ -2893,8 +2941,10 @@ re_arm:
if (should_notify_peers)
call_netdevice_notifiers(NETDEV_NOTIFY_PEERS,
bond->dev);
if (should_notify_rtnl)
if (should_notify_rtnl) {
bond_slave_state_notify(bond);
bond_slave_link_notify(bond);
}
rtnl_unlock();
}
@ -4135,7 +4185,6 @@ void bond_setup(struct net_device *bond_dev)
NETIF_F_HW_VLAN_CTAG_RX |
NETIF_F_HW_VLAN_CTAG_FILTER;
bond_dev->hw_features &= ~(NETIF_F_ALL_CSUM & ~NETIF_F_HW_CSUM);
bond_dev->hw_features |= NETIF_F_GSO_ENCAP_ALL;
bond_dev->features |= bond_dev->hw_features;
}

View File

@ -42,7 +42,6 @@
#include <net/bonding.h>
#define to_dev(obj) container_of(obj, struct device, kobj)
#define to_bond(cd) ((struct bonding *)(netdev_priv(to_net_dev(cd))))
/* "show" function for the bond_masters attribute.
@ -481,7 +480,7 @@ static ssize_t bonding_show_mii_status(struct device *d,
char *buf)
{
struct bonding *bond = to_bond(d);
bool active = !!rcu_access_pointer(bond->curr_active_slave);
bool active = netif_carrier_ok(bond->dev);
return sprintf(buf, "%s\n", active ? "up" : "down");
}

View File

@ -32,6 +32,7 @@
#include <linux/can/dev.h>
#include <linux/can/error.h>
#include <linux/can/led.h>
#include <linux/pm_runtime.h>
#define DRIVER_NAME "xilinx_can"
@ -138,7 +139,7 @@ struct xcan_priv {
u32 (*read_reg)(const struct xcan_priv *priv, enum xcan_reg reg);
void (*write_reg)(const struct xcan_priv *priv, enum xcan_reg reg,
u32 val);
struct net_device *dev;
struct device *dev;
void __iomem *reg_base;
unsigned long irq_flags;
struct clk *bus_clk;
@ -840,6 +841,13 @@ static int xcan_open(struct net_device *ndev)
struct xcan_priv *priv = netdev_priv(ndev);
int ret;
ret = pm_runtime_get_sync(priv->dev);
if (ret < 0) {
netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n",
__func__, ret);
return ret;
}
ret = request_irq(ndev->irq, xcan_interrupt, priv->irq_flags,
ndev->name, ndev);
if (ret < 0) {
@ -847,29 +855,17 @@ static int xcan_open(struct net_device *ndev)
goto err;
}
ret = clk_prepare_enable(priv->can_clk);
if (ret) {
netdev_err(ndev, "unable to enable device clock\n");
goto err_irq;
}
ret = clk_prepare_enable(priv->bus_clk);
if (ret) {
netdev_err(ndev, "unable to enable bus clock\n");
goto err_can_clk;
}
/* Set chip into reset mode */
ret = set_reset_mode(ndev);
if (ret < 0) {
netdev_err(ndev, "mode resetting failed!\n");
goto err_bus_clk;
goto err_irq;
}
/* Common open */
ret = open_candev(ndev);
if (ret)
goto err_bus_clk;
goto err_irq;
ret = xcan_chip_start(ndev);
if (ret < 0) {
@ -885,13 +881,11 @@ static int xcan_open(struct net_device *ndev)
err_candev:
close_candev(ndev);
err_bus_clk:
clk_disable_unprepare(priv->bus_clk);
err_can_clk:
clk_disable_unprepare(priv->can_clk);
err_irq:
free_irq(ndev->irq, ndev);
err:
pm_runtime_put(priv->dev);
return ret;
}
@ -908,12 +902,11 @@ static int xcan_close(struct net_device *ndev)
netif_stop_queue(ndev);
napi_disable(&priv->napi);
xcan_chip_stop(ndev);
clk_disable_unprepare(priv->bus_clk);
clk_disable_unprepare(priv->can_clk);
free_irq(ndev->irq, ndev);
close_candev(ndev);
can_led_event(ndev, CAN_LED_EVENT_STOP);
pm_runtime_put(priv->dev);
return 0;
}
@ -932,27 +925,20 @@ static int xcan_get_berr_counter(const struct net_device *ndev,
struct xcan_priv *priv = netdev_priv(ndev);
int ret;
ret = clk_prepare_enable(priv->can_clk);
if (ret)
goto err;
ret = clk_prepare_enable(priv->bus_clk);
if (ret)
goto err_clk;
ret = pm_runtime_get_sync(priv->dev);
if (ret < 0) {
netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n",
__func__, ret);
return ret;
}
bec->txerr = priv->read_reg(priv, XCAN_ECR_OFFSET) & XCAN_ECR_TEC_MASK;
bec->rxerr = ((priv->read_reg(priv, XCAN_ECR_OFFSET) &
XCAN_ECR_REC_MASK) >> XCAN_ESR_REC_SHIFT);
clk_disable_unprepare(priv->bus_clk);
clk_disable_unprepare(priv->can_clk);
pm_runtime_put(priv->dev);
return 0;
err_clk:
clk_disable_unprepare(priv->can_clk);
err:
return ret;
}
@ -965,15 +951,45 @@ static const struct net_device_ops xcan_netdev_ops = {
/**
* xcan_suspend - Suspend method for the driver
* @dev: Address of the platform_device structure
* @dev: Address of the device structure
*
* Put the driver into low power mode.
* Return: 0 on success and failure value on error
*/
static int __maybe_unused xcan_suspend(struct device *dev)
{
if (!device_may_wakeup(dev))
return pm_runtime_force_suspend(dev);
return 0;
}
/**
* xcan_resume - Resume from suspend
* @dev: Address of the device structure
*
* Resume operation after suspend.
* Return: 0 on success and failure value on error
*/
static int __maybe_unused xcan_resume(struct device *dev)
{
if (!device_may_wakeup(dev))
return pm_runtime_force_resume(dev);
return 0;
}
/**
* xcan_runtime_suspend - Runtime suspend method for the driver
* @dev: Address of the device structure
*
* Put the driver into low power mode.
* Return: 0 always
*/
static int __maybe_unused xcan_suspend(struct device *dev)
static int __maybe_unused xcan_runtime_suspend(struct device *dev)
{
struct platform_device *pdev = dev_get_drvdata(dev);
struct net_device *ndev = platform_get_drvdata(pdev);
struct net_device *ndev = dev_get_drvdata(dev);
struct xcan_priv *priv = netdev_priv(ndev);
if (netif_running(ndev)) {
@ -984,43 +1000,55 @@ static int __maybe_unused xcan_suspend(struct device *dev)
priv->write_reg(priv, XCAN_MSR_OFFSET, XCAN_MSR_SLEEP_MASK);
priv->can.state = CAN_STATE_SLEEPING;
clk_disable(priv->bus_clk);
clk_disable(priv->can_clk);
clk_disable_unprepare(priv->bus_clk);
clk_disable_unprepare(priv->can_clk);
return 0;
}
/**
* xcan_resume - Resume from suspend
* @dev: Address of the platformdevice structure
* xcan_runtime_resume - Runtime resume from suspend
* @dev: Address of the device structure
*
* Resume operation after suspend.
* Return: 0 on success and failure value on error
*/
static int __maybe_unused xcan_resume(struct device *dev)
static int __maybe_unused xcan_runtime_resume(struct device *dev)
{
struct platform_device *pdev = dev_get_drvdata(dev);
struct net_device *ndev = platform_get_drvdata(pdev);
struct net_device *ndev = dev_get_drvdata(dev);
struct xcan_priv *priv = netdev_priv(ndev);
int ret;
u32 isr, status;
ret = clk_enable(priv->bus_clk);
ret = clk_prepare_enable(priv->bus_clk);
if (ret) {
dev_err(dev, "Cannot enable clock.\n");
return ret;
}
ret = clk_enable(priv->can_clk);
ret = clk_prepare_enable(priv->can_clk);
if (ret) {
dev_err(dev, "Cannot enable clock.\n");
clk_disable_unprepare(priv->bus_clk);
return ret;
}
priv->write_reg(priv, XCAN_MSR_OFFSET, 0);
priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_CEN_MASK);
priv->can.state = CAN_STATE_ERROR_ACTIVE;
priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK);
isr = priv->read_reg(priv, XCAN_ISR_OFFSET);
status = priv->read_reg(priv, XCAN_SR_OFFSET);
if (netif_running(ndev)) {
if (isr & XCAN_IXR_BSOFF_MASK) {
priv->can.state = CAN_STATE_BUS_OFF;
priv->write_reg(priv, XCAN_SRR_OFFSET,
XCAN_SRR_RESET_MASK);
} else if ((status & XCAN_SR_ESTAT_MASK) ==
XCAN_SR_ESTAT_MASK) {
priv->can.state = CAN_STATE_ERROR_PASSIVE;
} else if (status & XCAN_SR_ERRWRN_MASK) {
priv->can.state = CAN_STATE_ERROR_WARNING;
} else {
priv->can.state = CAN_STATE_ERROR_ACTIVE;
}
netif_device_attach(ndev);
netif_start_queue(ndev);
}
@ -1028,7 +1056,10 @@ static int __maybe_unused xcan_resume(struct device *dev)
return 0;
}
static SIMPLE_DEV_PM_OPS(xcan_dev_pm_ops, xcan_suspend, xcan_resume);
static const struct dev_pm_ops xcan_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(xcan_suspend, xcan_resume)
SET_RUNTIME_PM_OPS(xcan_runtime_suspend, xcan_runtime_resume, NULL)
};
/**
* xcan_probe - Platform registration call
@ -1069,7 +1100,7 @@ static int xcan_probe(struct platform_device *pdev)
return -ENOMEM;
priv = netdev_priv(ndev);
priv->dev = ndev;
priv->dev = &pdev->dev;
priv->can.bittiming_const = &xcan_bittiming_const;
priv->can.do_set_mode = xcan_do_set_mode;
priv->can.do_get_berr_counter = xcan_get_berr_counter;
@ -1111,21 +1142,17 @@ static int xcan_probe(struct platform_device *pdev)
}
}
ret = clk_prepare_enable(priv->can_clk);
if (ret) {
dev_err(&pdev->dev, "unable to enable device clock\n");
goto err_free;
}
ret = clk_prepare_enable(priv->bus_clk);
if (ret) {
dev_err(&pdev->dev, "unable to enable bus clock\n");
goto err_unprepare_disable_dev;
}
priv->write_reg = xcan_write_reg_le;
priv->read_reg = xcan_read_reg_le;
pm_runtime_enable(&pdev->dev);
ret = pm_runtime_get_sync(&pdev->dev);
if (ret < 0) {
netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n",
__func__, ret);
goto err_pmdisable;
}
if (priv->read_reg(priv, XCAN_SR_OFFSET) != XCAN_SR_CONFIG_MASK) {
priv->write_reg = xcan_write_reg_be;
priv->read_reg = xcan_read_reg_be;
@ -1138,22 +1165,23 @@ static int xcan_probe(struct platform_device *pdev)
ret = register_candev(ndev);
if (ret) {
dev_err(&pdev->dev, "fail to register failed (err=%d)\n", ret);
goto err_unprepare_disable_busclk;
goto err_disableclks;
}
devm_can_led_init(ndev);
clk_disable_unprepare(priv->bus_clk);
clk_disable_unprepare(priv->can_clk);
pm_runtime_put(&pdev->dev);
netdev_dbg(ndev, "reg_base=0x%p irq=%d clock=%d, tx fifo depth:%d\n",
priv->reg_base, ndev->irq, priv->can.clock.freq,
priv->tx_max);
return 0;
err_unprepare_disable_busclk:
clk_disable_unprepare(priv->bus_clk);
err_unprepare_disable_dev:
clk_disable_unprepare(priv->can_clk);
err_disableclks:
pm_runtime_put(priv->dev);
err_pmdisable:
pm_runtime_disable(&pdev->dev);
err_free:
free_candev(ndev);
err:
@ -1172,10 +1200,8 @@ static int xcan_remove(struct platform_device *pdev)
struct net_device *ndev = platform_get_drvdata(pdev);
struct xcan_priv *priv = netdev_priv(ndev);
if (set_reset_mode(ndev) < 0)
netdev_err(ndev, "mode resetting failed!\n");
unregister_candev(ndev);
pm_runtime_disable(&pdev->dev);
netif_napi_del(&priv->napi);
free_candev(ndev);

View File

@ -19,6 +19,7 @@
#include <linux/list.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/gpio/consumer.h>
#include <linux/phy.h>
#include <net/dsa.h>
#include <net/switchdev.h>
@ -616,98 +617,112 @@ static void _mv88e6xxx_stats_read(struct dsa_switch *ds, int stat, u32 *val)
}
static struct mv88e6xxx_hw_stat mv88e6xxx_hw_stats[] = {
{ "in_good_octets", 8, 0x00, },
{ "in_bad_octets", 4, 0x02, },
{ "in_unicast", 4, 0x04, },
{ "in_broadcasts", 4, 0x06, },
{ "in_multicasts", 4, 0x07, },
{ "in_pause", 4, 0x16, },
{ "in_undersize", 4, 0x18, },
{ "in_fragments", 4, 0x19, },
{ "in_oversize", 4, 0x1a, },
{ "in_jabber", 4, 0x1b, },
{ "in_rx_error", 4, 0x1c, },
{ "in_fcs_error", 4, 0x1d, },
{ "out_octets", 8, 0x0e, },
{ "out_unicast", 4, 0x10, },
{ "out_broadcasts", 4, 0x13, },
{ "out_multicasts", 4, 0x12, },
{ "out_pause", 4, 0x15, },
{ "excessive", 4, 0x11, },
{ "collisions", 4, 0x1e, },
{ "deferred", 4, 0x05, },
{ "single", 4, 0x14, },
{ "multiple", 4, 0x17, },
{ "out_fcs_error", 4, 0x03, },
{ "late", 4, 0x1f, },
{ "hist_64bytes", 4, 0x08, },
{ "hist_65_127bytes", 4, 0x09, },
{ "hist_128_255bytes", 4, 0x0a, },
{ "hist_256_511bytes", 4, 0x0b, },
{ "hist_512_1023bytes", 4, 0x0c, },
{ "hist_1024_max_bytes", 4, 0x0d, },
/* Not all devices have the following counters */
{ "sw_in_discards", 4, 0x110, },
{ "sw_in_filtered", 2, 0x112, },
{ "sw_out_filtered", 2, 0x113, },
{ "in_good_octets", 8, 0x00, BANK0, },
{ "in_bad_octets", 4, 0x02, BANK0, },
{ "in_unicast", 4, 0x04, BANK0, },
{ "in_broadcasts", 4, 0x06, BANK0, },
{ "in_multicasts", 4, 0x07, BANK0, },
{ "in_pause", 4, 0x16, BANK0, },
{ "in_undersize", 4, 0x18, BANK0, },
{ "in_fragments", 4, 0x19, BANK0, },
{ "in_oversize", 4, 0x1a, BANK0, },
{ "in_jabber", 4, 0x1b, BANK0, },
{ "in_rx_error", 4, 0x1c, BANK0, },
{ "in_fcs_error", 4, 0x1d, BANK0, },
{ "out_octets", 8, 0x0e, BANK0, },
{ "out_unicast", 4, 0x10, BANK0, },
{ "out_broadcasts", 4, 0x13, BANK0, },
{ "out_multicasts", 4, 0x12, BANK0, },
{ "out_pause", 4, 0x15, BANK0, },
{ "excessive", 4, 0x11, BANK0, },
{ "collisions", 4, 0x1e, BANK0, },
{ "deferred", 4, 0x05, BANK0, },
{ "single", 4, 0x14, BANK0, },
{ "multiple", 4, 0x17, BANK0, },
{ "out_fcs_error", 4, 0x03, BANK0, },
{ "late", 4, 0x1f, BANK0, },
{ "hist_64bytes", 4, 0x08, BANK0, },
{ "hist_65_127bytes", 4, 0x09, BANK0, },
{ "hist_128_255bytes", 4, 0x0a, BANK0, },
{ "hist_256_511bytes", 4, 0x0b, BANK0, },
{ "hist_512_1023bytes", 4, 0x0c, BANK0, },
{ "hist_1024_max_bytes", 4, 0x0d, BANK0, },
{ "sw_in_discards", 4, 0x10, PORT, },
{ "sw_in_filtered", 2, 0x12, PORT, },
{ "sw_out_filtered", 2, 0x13, PORT, },
{ "in_discards", 4, 0x00 | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "in_filtered", 4, 0x01 | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "in_accepted", 4, 0x02 | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "in_bad_accepted", 4, 0x03 | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "in_good_avb_class_a", 4, 0x04 | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "in_good_avb_class_b", 4, 0x05 | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "in_bad_avb_class_a", 4, 0x06 | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "in_bad_avb_class_b", 4, 0x07 | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "tcam_counter_0", 4, 0x08 | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "tcam_counter_1", 4, 0x09 | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "tcam_counter_2", 4, 0x0a | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "tcam_counter_3", 4, 0x0b | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "in_da_unknown", 4, 0x0e | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "in_management", 4, 0x0f | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "out_queue_0", 4, 0x10 | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "out_queue_1", 4, 0x11 | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "out_queue_2", 4, 0x12 | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "out_queue_3", 4, 0x13 | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "out_queue_4", 4, 0x14 | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "out_queue_5", 4, 0x15 | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "out_queue_6", 4, 0x16 | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "out_queue_7", 4, 0x17 | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "out_cut_through", 4, 0x18 | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "out_octets_a", 4, 0x1a | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "out_octets_b", 4, 0x1b | GLOBAL_STATS_OP_BANK_1, BANK1, },
{ "out_management", 4, 0x1f | GLOBAL_STATS_OP_BANK_1, BANK1, },
};
static bool have_sw_in_discards(struct dsa_switch *ds)
static bool mv88e6xxx_has_stat(struct dsa_switch *ds,
struct mv88e6xxx_hw_stat *stat)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
switch (ps->id) {
case PORT_SWITCH_ID_6095: case PORT_SWITCH_ID_6161:
case PORT_SWITCH_ID_6165: case PORT_SWITCH_ID_6171:
case PORT_SWITCH_ID_6172: case PORT_SWITCH_ID_6176:
case PORT_SWITCH_ID_6182: case PORT_SWITCH_ID_6185:
case PORT_SWITCH_ID_6352:
switch (stat->type) {
case BANK0:
return true;
default:
return false;
}
}
static void _mv88e6xxx_get_strings(struct dsa_switch *ds,
int nr_stats,
struct mv88e6xxx_hw_stat *stats,
int port, uint8_t *data)
{
int i;
for (i = 0; i < nr_stats; i++) {
memcpy(data + i * ETH_GSTRING_LEN,
stats[i].string, ETH_GSTRING_LEN);
case BANK1:
return mv88e6xxx_6320_family(ds);
case PORT:
return mv88e6xxx_6095_family(ds) ||
mv88e6xxx_6185_family(ds) ||
mv88e6xxx_6097_family(ds) ||
mv88e6xxx_6165_family(ds) ||
mv88e6xxx_6351_family(ds) ||
mv88e6xxx_6352_family(ds);
}
return false;
}
static uint64_t _mv88e6xxx_get_ethtool_stat(struct dsa_switch *ds,
int stat,
struct mv88e6xxx_hw_stat *stats,
struct mv88e6xxx_hw_stat *s,
int port)
{
struct mv88e6xxx_hw_stat *s = stats + stat;
u32 low;
u32 high = 0;
int ret;
u64 value;
if (s->reg >= 0x100) {
ret = _mv88e6xxx_reg_read(ds, REG_PORT(port),
s->reg - 0x100);
switch (s->type) {
case PORT:
ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), s->reg);
if (ret < 0)
return UINT64_MAX;
low = ret;
if (s->sizeof_stat == 4) {
ret = _mv88e6xxx_reg_read(ds, REG_PORT(port),
s->reg - 0x100 + 1);
s->reg + 1);
if (ret < 0)
return UINT64_MAX;
high = ret;
}
} else {
break;
case BANK0:
case BANK1:
_mv88e6xxx_stats_read(ds, s->reg, &low);
if (s->sizeof_stat == 8)
_mv88e6xxx_stats_read(ds, s->reg + 1, &high);
@ -716,14 +731,42 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct dsa_switch *ds,
return value;
}
static void _mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
int nr_stats,
struct mv88e6xxx_hw_stat *stats,
int port, uint64_t *data)
void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, uint8_t *data)
{
struct mv88e6xxx_hw_stat *stat;
int i, j;
for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
stat = &mv88e6xxx_hw_stats[i];
if (mv88e6xxx_has_stat(ds, stat)) {
memcpy(data + j * ETH_GSTRING_LEN, stat->string,
ETH_GSTRING_LEN);
j++;
}
}
}
int mv88e6xxx_get_sset_count(struct dsa_switch *ds)
{
struct mv88e6xxx_hw_stat *stat;
int i, j;
for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
stat = &mv88e6xxx_hw_stats[i];
if (mv88e6xxx_has_stat(ds, stat))
j++;
}
return j;
}
void
mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
int port, uint64_t *data)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
struct mv88e6xxx_hw_stat *stat;
int ret;
int i;
int i, j;
mutex_lock(&ps->smi_mutex);
@ -732,47 +775,17 @@ static void _mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
mutex_unlock(&ps->smi_mutex);
return;
}
/* Read each of the counters. */
for (i = 0; i < nr_stats; i++)
data[i] = _mv88e6xxx_get_ethtool_stat(ds, i, stats, port);
for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
stat = &mv88e6xxx_hw_stats[i];
if (mv88e6xxx_has_stat(ds, stat)) {
data[j] = _mv88e6xxx_get_ethtool_stat(ds, stat, port);
j++;
}
}
mutex_unlock(&ps->smi_mutex);
}
/* All the statistics in the table */
void
mv88e6xxx_get_strings(struct dsa_switch *ds, int port, uint8_t *data)
{
if (have_sw_in_discards(ds))
_mv88e6xxx_get_strings(ds, ARRAY_SIZE(mv88e6xxx_hw_stats),
mv88e6xxx_hw_stats, port, data);
else
_mv88e6xxx_get_strings(ds, ARRAY_SIZE(mv88e6xxx_hw_stats) - 3,
mv88e6xxx_hw_stats, port, data);
}
int mv88e6xxx_get_sset_count(struct dsa_switch *ds)
{
if (have_sw_in_discards(ds))
return ARRAY_SIZE(mv88e6xxx_hw_stats);
return ARRAY_SIZE(mv88e6xxx_hw_stats) - 3;
}
void
mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
int port, uint64_t *data)
{
if (have_sw_in_discards(ds))
_mv88e6xxx_get_ethtool_stats(
ds, ARRAY_SIZE(mv88e6xxx_hw_stats),
mv88e6xxx_hw_stats, port, data);
else
_mv88e6xxx_get_ethtool_stats(
ds, ARRAY_SIZE(mv88e6xxx_hw_stats) - 3,
mv88e6xxx_hw_stats, port, data);
}
int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
{
return 32 * sizeof(u16);
@ -2323,6 +2336,7 @@ int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
u16 is_reset = (ppu_active ? 0x8800 : 0xc800);
struct gpio_desc *gpiod = ds->pd->reset;
unsigned long timeout;
int ret;
int i;
@ -2336,6 +2350,14 @@ int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active)
/* Wait for transmit queues to drain. */
usleep_range(2000, 4000);
/* If there is a gpio connected to the reset pin, toggle it */
if (gpiod) {
gpiod_set_value_cansleep(gpiod, 1);
usleep_range(10000, 20000);
gpiod_set_value_cansleep(gpiod, 0);
usleep_range(10000, 20000);
}
/* Reset the switch. Keep the PPU active if requested. The PPU
* needs to be active to support indirect phy register access
* through global registers 0x18 and 0x19.

View File

@ -288,6 +288,7 @@
#define GLOBAL_STATS_OP_HIST_RX ((1 << 10) | GLOBAL_STATS_OP_BUSY)
#define GLOBAL_STATS_OP_HIST_TX ((2 << 10) | GLOBAL_STATS_OP_BUSY)
#define GLOBAL_STATS_OP_HIST_RX_TX ((3 << 10) | GLOBAL_STATS_OP_BUSY)
#define GLOBAL_STATS_OP_BANK_1 BIT(9)
#define GLOBAL_STATS_COUNTER_32 0x1e
#define GLOBAL_STATS_COUNTER_01 0x1f
@ -420,10 +421,17 @@ struct mv88e6xxx_priv_state {
struct work_struct bridge_work;
};
enum stat_type {
BANK0,
BANK1,
PORT,
};
struct mv88e6xxx_hw_stat {
char string[ETH_GSTRING_LEN];
int sizeof_stat;
int reg;
enum stat_type type;
};
int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active);

View File

@ -562,7 +562,7 @@ static void el3_common_remove (struct net_device *dev)
}
#ifdef CONFIG_EISA
static int __init el3_eisa_probe (struct device *device)
static int el3_eisa_probe(struct device *device)
{
short i;
int ioaddr, irq, if_port;

View File

@ -907,7 +907,7 @@ static struct eisa_device_id vortex_eisa_ids[] = {
};
MODULE_DEVICE_TABLE(eisa, vortex_eisa_ids);
static int __init vortex_eisa_probe(struct device *device)
static int vortex_eisa_probe(struct device *device)
{
void __iomem *ioaddr;
struct eisa_device *edev;

View File

@ -372,7 +372,7 @@ static int ax_mii_probe(struct net_device *dev)
ax->phy_dev = phy_dev;
netdev_info(dev, "PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
phy_dev->drv->name, dev_name(&phy_dev->dev), phy_dev->irq);
phy_dev->drv->name, phydev_name(phy_dev), phy_dev->irq);
return 0;
}
@ -627,7 +627,7 @@ static int ax_mii_init(struct net_device *dev)
struct platform_device *pdev = to_platform_device(dev->dev.parent);
struct ei_device *ei_local = netdev_priv(dev);
struct ax_device *ax = to_ax_dev(dev);
int err, i;
int err;
ax->bb_ctrl.ops = &bb_ops;
ax->addr_memr = ei_local->mem + AX_MEMR;
@ -642,23 +642,12 @@ static int ax_mii_init(struct net_device *dev)
snprintf(ax->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
pdev->name, pdev->id);
ax->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
if (!ax->mii_bus->irq) {
err = -ENOMEM;
goto out_free_mdio_bitbang;
}
for (i = 0; i < PHY_MAX_ADDR; i++)
ax->mii_bus->irq[i] = PHY_POLL;
err = mdiobus_register(ax->mii_bus);
if (err)
goto out_free_irq;
goto out_free_mdio_bitbang;
return 0;
out_free_irq:
kfree(ax->mii_bus->irq);
out_free_mdio_bitbang:
free_mdio_bitbang(ax->mii_bus);
out:

View File

@ -122,6 +122,7 @@ config FEALNX
cards. <http://www.myson.com.tw/>
source "drivers/net/ethernet/natsemi/Kconfig"
source "drivers/net/ethernet/netronome/Kconfig"
source "drivers/net/ethernet/8390/Kconfig"
config NET_NETX

View File

@ -53,6 +53,7 @@ obj-$(CONFIG_NET_VENDOR_MOXART) += moxa/
obj-$(CONFIG_NET_VENDOR_MYRI) += myricom/
obj-$(CONFIG_FEALNX) += fealnx.o
obj-$(CONFIG_NET_VENDOR_NATSEMI) += natsemi/
obj-$(CONFIG_NET_VENDOR_NETRONOME) += netronome/
obj-$(CONFIG_NET_NETX) += netx-eth.o
obj-$(CONFIG_NET_VENDOR_NUVOTON) += nuvoton/
obj-$(CONFIG_NET_VENDOR_NVIDIA) += nvidia/

View File

@ -380,9 +380,8 @@ static void bfin_mac_adjust_link(struct net_device *dev)
static int mii_probe(struct net_device *dev, int phy_mode)
{
struct bfin_mac_local *lp = netdev_priv(dev);
struct phy_device *phydev = NULL;
struct phy_device *phydev;
unsigned short sysctl;
int i;
u32 sclk, mdc_div;
/* Enable PHY output early */
@ -396,18 +395,7 @@ static int mii_probe(struct net_device *dev, int phy_mode)
sysctl = (sysctl & ~MDCDIV) | SET_MDCDIV(mdc_div);
bfin_write_EMAC_SYSCTL(sysctl);
/* search for connected PHY device */
for (i = 0; i < PHY_MAX_ADDR; ++i) {
struct phy_device *const tmp_phydev = lp->mii_bus->phy_map[i];
if (!tmp_phydev)
continue; /* no PHY here... */
phydev = tmp_phydev;
break; /* found it */
}
/* now we are supposed to have a proper phydev, to attach to... */
phydev = phy_find_first(lp->mii_bus);
if (!phydev) {
netdev_err(dev, "no phy device found\n");
return -ENODEV;
@ -419,7 +407,7 @@ static int mii_probe(struct net_device *dev, int phy_mode)
return -EINVAL;
}
phydev = phy_connect(dev, dev_name(&phydev->dev),
phydev = phy_connect(dev, phydev_name(phydev),
&bfin_mac_adjust_link, phy_mode);
if (IS_ERR(phydev)) {
@ -444,10 +432,8 @@ static int mii_probe(struct net_device *dev, int phy_mode)
lp->old_duplex = -1;
lp->phydev = phydev;
pr_info("attached PHY driver [%s] "
"(mii_bus:phy_addr=%s, irq=%d, mdc_clk=%dHz(mdc_div=%d)@sclk=%dMHz)\n",
phydev->drv->name, dev_name(&phydev->dev), phydev->irq,
MDC_CLK, mdc_div, sclk/1000000);
phy_attached_print(phydev, "mdc_clk=%dHz(mdc_div=%d)@sclk=%dMHz)\n",
MDC_CLK, mdc_div, sclk / 1000000);
return 0;
}
@ -1840,12 +1826,6 @@ static int bfin_mii_bus_probe(struct platform_device *pdev)
snprintf(miibus->id, MII_BUS_ID_SIZE, "%s-%x",
pdev->name, pdev->id);
miibus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
if (!miibus->irq)
goto out_err_irq_alloc;
for (i = rc; i < PHY_MAX_ADDR; ++i)
miibus->irq[i] = PHY_POLL;
rc = clamp(mii_bus_pd->phydev_number, 0, PHY_MAX_ADDR);
if (rc != mii_bus_pd->phydev_number)
@ -1864,14 +1844,12 @@ static int bfin_mii_bus_probe(struct platform_device *pdev)
rc = mdiobus_register(miibus);
if (rc) {
dev_err(&pdev->dev, "Cannot register MDIO bus!\n");
goto out_err_mdiobus_register;
goto out_err_irq_alloc;
}
platform_set_drvdata(pdev, miibus);
return 0;
out_err_mdiobus_register:
kfree(miibus->irq);
out_err_irq_alloc:
mdiobus_free(miibus);
out_err_alloc:
@ -1887,7 +1865,6 @@ static int bfin_mii_bus_remove(struct platform_device *pdev)
dev_get_platdata(&pdev->dev);
mdiobus_unregister(miibus);
kfree(miibus->irq);
mdiobus_free(miibus);
peripheral_free_list(mii_bus_pd->mac_peripherals);
@ -1912,21 +1889,21 @@ static struct platform_driver bfin_mac_driver = {
},
};
static struct platform_driver * const drivers[] = {
&bfin_mii_bus_driver,
&bfin_mac_driver,
};
static int __init bfin_mac_init(void)
{
int ret;
ret = platform_driver_register(&bfin_mii_bus_driver);
if (!ret)
return platform_driver_register(&bfin_mac_driver);
return -ENODEV;
return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
}
module_init(bfin_mac_init);
static void __exit bfin_mac_cleanup(void)
{
platform_driver_unregister(&bfin_mac_driver);
platform_driver_unregister(&bfin_mii_bus_driver);
platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
}
module_exit(bfin_mac_cleanup);

Some files were not shown because too many files have changed in this diff Show More