提交 6ba74014 编写于 作者: L Linus Torvalds

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

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1443 commits)
  phy/marvell: add 88ec048 support
  igb: Program MDICNFG register prior to PHY init
  e1000e: correct MAC-PHY interconnect register offset for 82579
  hso: Add new product ID
  can: Add driver for esd CAN-USB/2 device
  l2tp: fix export of header file for userspace
  can-raw: Fix skb_orphan_try handling
  Revert "net: remove zap_completion_queue"
  net: cleanup inclusion
  phy/marvell: add 88e1121 interface mode support
  u32: negative offset fix
  net: Fix a typo from "dev" to "ndev"
  igb: Use irq_synchronize per vector when using MSI-X
  ixgbevf: fix null pointer dereference due to filter being set for VLAN 0
  e1000e: Fix irq_synchronize in MSI-X case
  e1000e: register pm_qos request on hardware activation
  ip_fragment: fix subtracting PPPOE_SES_HLEN from mtu twice
  net: Add getsockopt support for TCP thin-streams
  cxgb4: update driver version
  cxgb4: add new PCI IDs
  ...

Manually fix up conflicts in:
 - drivers/net/e1000e/netdev.c: due to pm_qos registration
   infrastructure changes
 - drivers/net/phy/marvell.c: conflict between adding 88ec048 support
   and cleaning up the IDs
 - drivers/net/wireless/ipw2x00/ipw2100.c: trivial ipw2100_pm_qos_req
   conflict (registration change vs marking it static)
无相关合并请求

要显示的变更太多。

To preserve performance only 1000 of 1000+ files are displayed.
......@@ -303,15 +303,6 @@ Who: Johannes Berg <johannes@sipsolutions.net>
---------------------------
What: CONFIG_NF_CT_ACCT
When: 2.6.29
Why: Accounting can now be enabled/disabled without kernel recompilation.
Currently used only to set a default value for a feature that is also
controlled by a kernel/module/sysfs/sysctl parameter.
Who: Krzysztof Piotr Oledzki <ole@ans.pl>
---------------------------
What: sysfs ui for changing p4-clockmod parameters
When: September 2009
Why: See commits 129f8ae9b1b5be94517da76009ea956e89104ce8 and
......
......@@ -124,6 +124,8 @@ ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>
<hostname> Name of the client. May be supplied by autoconfiguration,
but its absence will not trigger autoconfiguration.
If specified and DHCP is used, the user provided hostname will
be carried in the DHCP request to hopefully update DNS record.
Default: Client IP address is used in ASCII notation.
......
......@@ -113,12 +113,16 @@ char *driver_name
int (*load_firmware)(struct capi_ctr *ctrlr, capiloaddata *ldata)
(optional) pointer to a callback function for sending firmware and
configuration data to the device
The function may return before the operation has completed.
Completion must be signalled by a call to capi_ctr_ready().
Return value: 0 on success, error code on error
Called in process context.
void (*reset_ctr)(struct capi_ctr *ctrlr)
(optional) pointer to a callback function for performing a reset on
the device, releasing all registered applications
(optional) pointer to a callback function for stopping the device,
releasing all registered applications
The function may return before the operation has completed.
Completion must be signalled by a call to capi_ctr_down().
Called in process context.
void (*register_appl)(struct capi_ctr *ctrlr, u16 applid,
......
......@@ -47,9 +47,9 @@ GigaSet 307x Device Driver
1.2. Software
--------
The driver works with ISDN4linux and so can be used with any software
which is able to use ISDN4linux for ISDN connections (voice or data).
Experimental Kernel CAPI support is available as a compilation option.
The driver works with the Kernel CAPI subsystem as well as the old
ISDN4Linux subsystem, so it can be used with any software which is able
to use CAPI 2.0 or ISDN4Linux for ISDN connections (voice or data).
There are some user space tools available at
http://sourceforge.net/projects/gigaset307x/
......@@ -152,61 +152,42 @@ GigaSet 307x Device Driver
- GIGVER_FWBASE: retrieve the firmware version of the base
Upon return, version[] is filled with the requested version information.
2.3. ISDN4linux
----------
This is the "normal" mode of operation. After loading the module you can
set up the ISDN system just as you'd do with any ISDN card supported by
the ISDN4Linux subsystem. Most distributions provide some configuration
utility. If not, you can use some HOWTOs like
http://www.linuxhaven.de/dlhp/HOWTO/DE-ISDN-HOWTO-5.html
If this doesn't work, because you have some device like SX100 where
debug output (see section 3.2.) shows something like this when dialing
CMD Received: ERROR
Available Params: 0
Connection State: 0, Response: -1
gigaset_process_response: resp_code -1 in ConState 0 !
Timeout occurred
you probably need to use unimodem mode. (see section 2.5.)
2.4. CAPI
2.3. CAPI
----
If the driver is compiled with CAPI support (kernel configuration option
GIGASET_CAPI, experimental) it can also be used with CAPI 2.0 kernel and
user space applications. For user space access, the module capi.ko must
be loaded. The capiinit command (included in the capi4k-utils package)
does this for you.
The CAPI variant of the driver supports legacy ISDN4Linux applications
via the capidrv compatibility driver. The kernel module capidrv.ko must
be loaded explicitly with the command
GIGASET_CAPI) the devices will show up as CAPI controllers as soon as the
corresponding driver module is loaded, and can then be used with CAPI 2.0
kernel and user space applications. For user space access, the module
capi.ko must be loaded.
Legacy ISDN4Linux applications are supported via the capidrv
compatibility driver. The kernel module capidrv.ko must be loaded
explicitly with the command
modprobe capidrv
if needed, and cannot be unloaded again without unloading the driver
first. (These are limitations of capidrv.)
The note about unimodem mode in the preceding section applies here, too.
2.5. Unimodem mode
-------------
This is needed for some devices [e.g. SX100] as they have problems with
the "normal" commands.
Most distributions handle loading and unloading of the various CAPI
modules automatically via the command capiinit(1) from the capi4k-utils
package or a similar mechanism. Note that capiinit(1) cannot unload the
Gigaset drivers because it doesn't support more than one module per
driver.
If you have installed the command line tool gigacontr, you can enter
unimodem mode using
gigacontr --mode unimodem
You can switch back using
gigacontr --mode isdn
2.4. ISDN4Linux
----------
If the driver is compiled without CAPI support (native ISDN4Linux
variant), it registers the device with the legacy ISDN4Linux subsystem
after loading the module. It can then be used with ISDN4Linux
applications only. Most distributions provide some configuration utility
for setting up that subsystem. Otherwise you can use some HOWTOs like
http://www.linuxhaven.de/dlhp/HOWTO/DE-ISDN-HOWTO-5.html
You can also put the driver directly into Unimodem mode when it's loaded,
by passing the module parameter startmode=0 to the hardware specific
module, e.g.
modprobe usb_gigaset startmode=0
or by adding a line like
options usb_gigaset startmode=0
to an appropriate module configuration file, like /etc/modprobe.d/gigaset
or /etc/modprobe.conf.local.
2.5. Unimodem mode
-------------
In this mode the device works like a modem connected to a serial port
(the /dev/ttyGU0, ... mentioned above) which understands the commands
ATZ init, reset
=> OK or ERROR
ATD
......@@ -234,6 +215,31 @@ GigaSet 307x Device Driver
to an appropriate module configuration file, like /etc/modprobe.d/gigaset
or /etc/modprobe.conf.local.
Unimodem mode is needed for making some devices [e.g. SX100] work which
do not support the regular Gigaset command set. If debug output (see
section 3.2.) shows something like this when dialing:
CMD Received: ERROR
Available Params: 0
Connection State: 0, Response: -1
gigaset_process_response: resp_code -1 in ConState 0 !
Timeout occurred
then switching to unimodem mode may help.
If you have installed the command line tool gigacontr, you can enter
unimodem mode using
gigacontr --mode unimodem
You can switch back using
gigacontr --mode isdn
You can also put the driver directly into Unimodem mode when it's loaded,
by passing the module parameter startmode=0 to the hardware specific
module, e.g.
modprobe usb_gigaset startmode=0
or by adding a line like
options usb_gigaset startmode=0
to an appropriate module configuration file, like /etc/modprobe.d/gigaset
or /etc/modprobe.conf.local.
2.6. Call-ID (CID) mode
------------------
Call-IDs are numbers used to tag commands to, and responses from, the
......@@ -263,7 +269,22 @@ GigaSet 307x Device Driver
change its CID mode while the driver is loaded, eg.
echo 0 > /sys/class/tty/ttyGU0/cidmode
2.7. Unregistered Wireless Devices (M101/M105)
2.7. Dialing Numbers
---------------
The called party number provided by an application for dialing out must
be a public network number according to the local dialing plan, without
any dial prefix for getting an outside line.
Internal calls can be made by providing an internal extension number
prefixed with "**" (two asterisks) as the called party number. So to dial
eg. the first registered DECT handset, give "**11" as the called party
number. Dialing "***" (three asterisks) calls all extensions
simultaneously (global call).
This holds for both CAPI 2.0 and ISDN4Linux applications. Unimodem mode
does not support internal calls.
2.8. Unregistered Wireless Devices (M101/M105)
-----------------------------------------
The main purpose of the ser_gigaset and usb_gigaset drivers is to allow
the M101 and M105 wireless devices to be used as ISDN devices for ISDN
......
......@@ -1598,8 +1598,7 @@ and is between 256 and 4096 characters. It is defined in the file
[NETFILTER] Enable connection tracking flow accounting
0 to disable accounting
1 to enable accounting
Default value depends on CONFIG_NF_CT_ACCT that is
going to be removed in 2.6.29.
Default value is 0.
nfsaddrs= [NFS]
See Documentation/filesystems/nfs/nfsroot.txt.
......
......@@ -171,7 +171,7 @@ Where the supported parameter are:
led
Can be used to turn on experimental LED code.
0 = Off, 1 = On. Default is 0.
0 = Off, 1 = On. Default is 1.
mode
Can be used to set the default mode of the adapter.
......
......@@ -49,6 +49,7 @@ Table of Contents
3.3 Configuring Bonding Manually with Ifenslave
3.3.1 Configuring Multiple Bonds Manually
3.4 Configuring Bonding Manually via Sysfs
3.5 Overriding Configuration for Special Cases
4. Querying Bonding Configuration
4.1 Bonding Configuration
......@@ -1318,8 +1319,87 @@ echo 2000 > /sys/class/net/bond1/bonding/arp_interval
echo +eth2 > /sys/class/net/bond1/bonding/slaves
echo +eth3 > /sys/class/net/bond1/bonding/slaves
4. Querying Bonding Configuration
3.5 Overriding Configuration for Special Cases
----------------------------------------------
When using the bonding driver, the physical port which transmits a frame is
typically selected by the bonding driver, and is not relevant to the user or
system administrator. The output port is simply selected using the policies of
the selected bonding mode. On occasion however, it is helpful to direct certain
classes of traffic to certain physical interfaces on output to implement
slightly more complex policies. For example, to reach a web server over a
bonded interface in which eth0 connects to a private network, while eth1
connects via a public network, it may be desirous to bias the bond to send said
traffic over eth0 first, using eth1 only as a fall back, while all other traffic
can safely be sent over either interface. Such configurations may be achieved
using the traffic control utilities inherent in linux.
By default the bonding driver is multiqueue aware and 16 queues are created
when the driver initializes (see Documentation/networking/multiqueue.txt
for details). If more or less queues are desired the module parameter
tx_queues can be used to change this value. There is no sysfs parameter
available as the allocation is done at module init time.
The output of the file /proc/net/bonding/bondX has changed so the output Queue
ID is now printed for each slave:
Bonding Mode: fault-tolerance (active-backup)
Primary Slave: None
Currently Active Slave: eth0
MII Status: up
MII Polling Interval (ms): 0
Up Delay (ms): 0
Down Delay (ms): 0
Slave Interface: eth0
MII Status: up
Link Failure Count: 0
Permanent HW addr: 00:1a:a0:12:8f:cb
Slave queue ID: 0
Slave Interface: eth1
MII Status: up
Link Failure Count: 0
Permanent HW addr: 00:1a:a0:12:8f:cc
Slave queue ID: 2
The queue_id for a slave can be set using the command:
# echo "eth1:2" > /sys/class/net/bond0/bonding/queue_id
Any interface that needs a queue_id set should set it with multiple calls
like the one above until proper priorities are set for all interfaces. On
distributions that allow configuration via initscripts, multiple 'queue_id'
arguments can be added to BONDING_OPTS to set all needed slave queues.
These queue id's can be used in conjunction with the tc utility to configure
a multiqueue qdisc and filters to bias certain traffic to transmit on certain
slave devices. For instance, say we wanted, in the above configuration to
force all traffic bound to 192.168.1.100 to use eth1 in the bond as its output
device. The following commands would accomplish this:
# tc qdisc add dev bond0 handle 1 root multiq
# tc filter add dev bond0 protocol ip parent 1: prio 1 u32 match ip dst \
192.168.1.100 action skbedit queue_mapping 2
These commands tell the kernel to attach a multiqueue queue discipline to the
bond0 interface and filter traffic enqueued to it, such that packets with a dst
ip of 192.168.1.100 have their output queue mapping value overwritten to 2.
This value is then passed into the driver, causing the normal output path
selection policy to be overridden, selecting instead qid 2, which maps to eth1.
Note that qid values begin at 1. Qid 0 is reserved to initiate to the driver
that normal output policy selection should take place. One benefit to simply
leaving the qid for a slave to 0 is the multiqueue awareness in the bonding
driver that is now present. This awareness allows tc filters to be placed on
slave devices as well as bond devices and the bonding driver will simply act as
a pass-through for selecting output queues on the slave device rather than
output port selection.
This feature first appeared in bonding driver version 3.7.0 and support for
output slave selection was limited to round-robin and active-backup modes.
4 Querying Bonding Configuration
=================================
4.1 Bonding Configuration
......
- CAIF SPI porting -
- CAIF SPI basics:
Running CAIF over SPI needs some extra setup, owing to the nature of SPI.
Two extra GPIOs have been added in order to negotiate the transfers
between the master and the slave. The minimum requirement for running
CAIF over SPI is a SPI slave chip and two GPIOs (more details below).
Please note that running as a slave implies that you need to keep up
with the master clock. An overrun or underrun event is fatal.
- CAIF SPI framework:
To make porting as easy as possible, the CAIF SPI has been divided in
two parts. The first part (called the interface part) deals with all
generic functionality such as length framing, SPI frame negotiation
and SPI frame delivery and transmission. The other part is the CAIF
SPI slave device part, which is the module that you have to write if
you want to run SPI CAIF on a new hardware. This part takes care of
the physical hardware, both with regard to SPI and to GPIOs.
- Implementing a CAIF SPI device:
- Functionality provided by the CAIF SPI slave device:
In order to implement a SPI device you will, as a minimum,
need to implement the following
functions:
int (*init_xfer) (struct cfspi_xfer * xfer, struct cfspi_dev *dev):
This function is called by the CAIF SPI interface to give
you a chance to set up your hardware to be ready to receive
a stream of data from the master. The xfer structure contains
both physical and logical adresses, as well as the total length
of the transfer in both directions.The dev parameter can be used
to map to different CAIF SPI slave devices.
void (*sig_xfer) (bool xfer, struct cfspi_dev *dev):
This function is called by the CAIF SPI interface when the output
(SPI_INT) GPIO needs to change state. The boolean value of the xfer
variable indicates whether the GPIO should be asserted (HIGH) or
deasserted (LOW). The dev parameter can be used to map to different CAIF
SPI slave devices.
- Functionality provided by the CAIF SPI interface:
void (*ss_cb) (bool assert, struct cfspi_ifc *ifc);
This function is called by the CAIF SPI slave device in order to
signal a change of state of the input GPIO (SS) to the interface.
Only active edges are mandatory to be reported.
This function can be called from IRQ context (recommended in order
not to introduce latency). The ifc parameter should be the pointer
returned from the platform probe function in the SPI device structure.
void (*xfer_done_cb) (struct cfspi_ifc *ifc);
This function is called by the CAIF SPI slave device in order to
report that a transfer is completed. This function should only be
called once both the transmission and the reception are completed.
This function can be called from IRQ context (recommended in order
not to introduce latency). The ifc parameter should be the pointer
returned from the platform probe function in the SPI device structure.
- Connecting the bits and pieces:
- Filling in the SPI slave device structure:
Connect the necessary callback functions.
Indicate clock speed (used to calculate toggle delays).
Chose a suitable name (helps debugging if you use several CAIF
SPI slave devices).
Assign your private data (can be used to map to your structure).
- Filling in the SPI slave platform device structure:
Add name of driver to connect to ("cfspi_sspi").
Assign the SPI slave device structure as platform data.
- Padding:
In order to optimize throughput, a number of SPI padding options are provided.
Padding can be enabled independently for uplink and downlink transfers.
Padding can be enabled for the head, the tail and for the total frame size.
The padding needs to be correctly configured on both sides of the link.
The padding can be changed via module parameters in cfspi_sspi.c or via
the sysfs directory of the cfspi_sspi driver (before device registration).
- CAIF SPI device template:
/*
* Copyright (C) ST-Ericsson AB 2010
* Author: Daniel Martensson / Daniel.Martensson@stericsson.com
* License terms: GNU General Public License (GPL), version 2.
*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/wait.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <net/caif/caif_spi.h>
MODULE_LICENSE("GPL");
struct sspi_struct {
struct cfspi_dev sdev;
struct cfspi_xfer *xfer;
};
static struct sspi_struct slave;
static struct platform_device slave_device;
static irqreturn_t sspi_irq(int irq, void *arg)
{
/* You only need to trigger on an edge to the active state of the
* SS signal. Once a edge is detected, the ss_cb() function should be
* called with the parameter assert set to true. It is OK
* (and even advised) to call the ss_cb() function in IRQ context in
* order not to add any delay. */
return IRQ_HANDLED;
}
static void sspi_complete(void *context)
{
/* Normally the DMA or the SPI framework will call you back
* in something similar to this. The only thing you need to
* do is to call the xfer_done_cb() function, providing the pointer
* to the CAIF SPI interface. It is OK to call this function
* from IRQ context. */
}
static int sspi_init_xfer(struct cfspi_xfer *xfer, struct cfspi_dev *dev)
{
/* Store transfer info. For a normal implementation you should
* set up your DMA here and make sure that you are ready to
* receive the data from the master SPI. */
struct sspi_struct *sspi = (struct sspi_struct *)dev->priv;
sspi->xfer = xfer;
return 0;
}
void sspi_sig_xfer(bool xfer, struct cfspi_dev *dev)
{
/* If xfer is true then you should assert the SPI_INT to indicate to
* the master that you are ready to recieve the data from the master
* SPI. If xfer is false then you should de-assert SPI_INT to indicate
* that the transfer is done.
*/
struct sspi_struct *sspi = (struct sspi_struct *)dev->priv;
}
static void sspi_release(struct device *dev)
{
/*
* Here you should release your SPI device resources.
*/
}
static int __init sspi_init(void)
{
/* Here you should initialize your SPI device by providing the
* necessary functions, clock speed, name and private data. Once
* done, you can register your device with the
* platform_device_register() function. This function will return
* with the CAIF SPI interface initialized. This is probably also
* the place where you should set up your GPIOs, interrupts and SPI
* resources. */
int res = 0;
/* Initialize slave device. */
slave.sdev.init_xfer = sspi_init_xfer;
slave.sdev.sig_xfer = sspi_sig_xfer;
slave.sdev.clk_mhz = 13;
slave.sdev.priv = &slave;
slave.sdev.name = "spi_sspi";
slave_device.dev.release = sspi_release;
/* Initialize platform device. */
slave_device.name = "cfspi_sspi";
slave_device.dev.platform_data = &slave.sdev;
/* Register platform device. */
res = platform_device_register(&slave_device);
if (res) {
printk(KERN_WARNING "sspi_init: failed to register dev.\n");
return -ENODEV;
}
return res;
}
static void __exit sspi_exit(void)
{
platform_device_del(&slave_device);
}
module_init(sspi_init);
module_exit(sspi_exit);
......@@ -903,7 +903,7 @@ arp_ignore - INTEGER
arp_notify - BOOLEAN
Define mode for notification of address and device changes.
0 - (default): do nothing
1 - Generate gratuitous arp replies when device is brought up
1 - Generate gratuitous arp requests when device is brought up
or hardware address changes.
arp_accept - BOOLEAN
......
......@@ -493,6 +493,32 @@ The user can also use poll() to check if a buffer is available:
pfd.events = POLLOUT;
retval = poll(&pfd, 1, timeout);
-------------------------------------------------------------------------------
+ PACKET_TIMESTAMP
-------------------------------------------------------------------------------
The PACKET_TIMESTAMP setting determines the source of the timestamp in
the packet meta information. If your NIC is capable of timestamping
packets in hardware, you can request those hardware timestamps to used.
Note: you may need to enable the generation of hardware timestamps with
SIOCSHWTSTAMP.
PACKET_TIMESTAMP accepts the same integer bit field as
SO_TIMESTAMPING. However, only the SOF_TIMESTAMPING_SYS_HARDWARE
and SOF_TIMESTAMPING_RAW_HARDWARE values are recognized by
PACKET_TIMESTAMP. SOF_TIMESTAMPING_SYS_HARDWARE takes precedence over
SOF_TIMESTAMPING_RAW_HARDWARE if both bits are set.
int req = 0;
req |= SOF_TIMESTAMPING_SYS_HARDWARE;
setsockopt(fd, SOL_PACKET, PACKET_TIMESTAMP, (void *) &req, sizeof(req))
If PACKET_TIMESTAMP is not set, a software timestamp generated inside
the networking stack is used (the behavior before this setting was added).
See include/linux/net_tstamp.h and Documentation/networking/timestamping
for more information on hardware timestamps.
--------------------------------------------------------------------------------
+ THANKS
--------------------------------------------------------------------------------
......
......@@ -151,6 +151,8 @@ Examples:
pgset stop aborts injection. Also, ^C aborts generator.
pgset "rate 300M" set rate to 300 Mb/s
pgset "ratep 1000000" set rate to 1Mpps
Example scripts
===============
......@@ -241,6 +243,9 @@ src6
flows
flowlen
rate
ratep
References:
ftp://robur.slu.se/pub/Linux/net-development/pktgen-testing/
ftp://robur.slu.se/pub/Linux/net-development/pktgen-testing/examples/
......
......@@ -313,11 +313,9 @@ S: Maintained
F: drivers/hwmon/adm1029.c
ADM8211 WIRELESS DRIVER
M: Michael Wu <flamingice@sourmilk.net>
L: linux-wireless@vger.kernel.org
W: http://linuxwireless.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mwu/mac80211-drivers.git
S: Maintained
S: Orphan
F: drivers/net/wireless/adm8211.*
ADT746X FAN DRIVER
......@@ -1369,7 +1367,7 @@ BROADCOM BNX2X 10 GIGABIT ETHERNET DRIVER
M: Eilon Greenstein <eilong@broadcom.com>
L: netdev@vger.kernel.org
S: Supported
F: drivers/net/bnx2x*
F: drivers/net/bnx2x/
BROADCOM TG3 GIGABIT ETHERNET DRIVER
M: Matt Carlson <mcarlson@broadcom.com>
......@@ -1771,6 +1769,13 @@ W: http://www.openfabrics.org
S: Supported
F: drivers/infiniband/hw/cxgb4/
CXGB4VF ETHERNET DRIVER (CXGB4VF)
M: Casey Leedom <leedom@chelsio.com>
L: netdev@vger.kernel.org
W: http://www.chelsio.com
S: Supported
F: drivers/net/cxgb4vf/
CYBERPRO FB DRIVER
M: Russell King <linux@arm.linux.org.uk>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
......@@ -3686,7 +3691,7 @@ F: include/linux/mv643xx.h
MARVELL MWL8K WIRELESS DRIVER
M: Lennert Buytenhek <buytenh@wantstofly.org>
L: linux-wireless@vger.kernel.org
S: Maintained
S: Odd Fixes
F: drivers/net/wireless/mwl8k.c
MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER
......@@ -3915,17 +3920,19 @@ L: netem@lists.linux-foundation.org
S: Maintained
F: net/sched/sch_netem.c
NETERION (S2IO) 10GbE DRIVER (xframe/vxge)
M: Ramkrishna Vepa <ram.vepa@neterion.com>
M: Rastapur Santosh <santosh.rastapur@neterion.com>
M: Sivakumar Subramani <sivakumar.subramani@neterion.com>
M: Sreenivasa Honnur <sreenivasa.honnur@neterion.com>
NETERION 10GbE DRIVERS (s2io/vxge)
M: Ramkrishna Vepa <ramkrishna.vepa@exar.com>
M: Sivakumar Subramani <sivakumar.subramani@exar.com>
M: Sreenivasa Honnur <sreenivasa.honnur@exar.com>
M: Jon Mason <jon.mason@exar.com>
L: netdev@vger.kernel.org
W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/Linux?Anonymous
W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/X3100Linux?Anonymous
S: Supported
F: Documentation/networking/s2io.txt
F: drivers/net/s2io*
F: Documentation/networking/vxge.txt
F: drivers/net/vxge/
NETFILTER/IPTABLES/IPCHAINS
P: Rusty Russell
......@@ -4272,10 +4279,9 @@ F: include/scsi/osd_*
F: fs/exofs/
P54 WIRELESS DRIVER
M: Michael Wu <flamingice@sourmilk.net>
M: Christian Lamparter <chunkeey@googlemail.com>
L: linux-wireless@vger.kernel.org
W: http://prism54.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mwu/mac80211-drivers.git
W: http://wireless.kernel.org/en/users/Drivers/p54
S: Maintained
F: drivers/net/wireless/p54/
......@@ -4537,7 +4543,7 @@ PRISM54 WIRELESS DRIVER
M: "Luis R. Rodriguez" <mcgrof@gmail.com>
L: linux-wireless@vger.kernel.org
W: http://prism54.org
S: Maintained
S: Obsolete
F: drivers/net/wireless/prism54/
PROMISE DC4030 CACHING DISK CONTROLLER DRIVER
......@@ -4733,9 +4739,8 @@ S: Maintained
F: drivers/rapidio/
RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER
M: Corey Thomas <coreythomas@charter.net>
L: linux-wireless@vger.kernel.org
S: Maintained
S: Orphan
F: drivers/net/wireless/ray*
RCUTORTURE MODULE
......@@ -6068,10 +6073,9 @@ F: Documentation/video4linux/zc0301.txt
F: drivers/media/video/zc0301/
USB ZD1201 DRIVER
M: Jeroen Vreeken <pe1rxq@amsat.org>
L: linux-usb@vger.kernel.org
L: linux-wireless@vger.kernel.org
W: http://linux-lc100020.sourceforge.net
S: Maintained
S: Orphan
F: drivers/net/wireless/zd1201.*
USB ZR364XX DRIVER
......@@ -6259,14 +6263,6 @@ F: Documentation/watchdog/
F: drivers/watchdog/
F: include/linux/watchdog.h
WAVELAN NETWORK DRIVER & WIRELESS EXTENSIONS
M: Jean Tourrilhes <jt@hpl.hp.com>
L: linux-wireless@vger.kernel.org
W: http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/
S: Maintained
F: Documentation/networking/wavelan.txt
F: drivers/staging/wavelan/
WD7000 SCSI DRIVER
M: Miroslav Zagorac <zaga@fly.cc.fer.hr>
L: linux-scsi@vger.kernel.org
......
......@@ -101,10 +101,7 @@ extern struct dentry *of_debugfs_root;
* MicroBlaze doesn't handle unaligned accesses in hardware.
*
* Based on this we force the IP header alignment in network drivers.
* We also modify NET_SKB_PAD to be a cacheline in size, thus maintaining
* cacheline alignment of buffers.
*/
#define NET_IP_ALIGN 2
#define NET_SKB_PAD L1_CACHE_BYTES
#endif /* _ASM_MICROBLAZE_SYSTEM_H */
......@@ -515,11 +515,8 @@ __cmpxchg_local(volatile void *ptr, unsigned long old, unsigned long new,
* powers of 2 writes until it reaches sufficient alignment).
*
* Based on this we disable the IP header alignment in network drivers.
* We also modify NET_SKB_PAD to be a cacheline in size, thus maintaining
* cacheline alignment of buffers.
*/
#define NET_IP_ALIGN 0
#define NET_SKB_PAD L1_CACHE_BYTES
#define cmpxchg64(ptr, o, n) \
({ \
......
......@@ -85,7 +85,8 @@ static void appldata_get_net_sum_data(void *data)
rcu_read_lock();
for_each_netdev_rcu(&init_net, dev) {
const struct net_device_stats *stats = dev_get_stats(dev);
struct rtnl_link_stats64 temp;
const struct net_device_stats *stats = dev_get_stats(dev, &temp);
rx_packets += stats->rx_packets;
tx_packets += stats->tx_packets;
......
......@@ -25,11 +25,6 @@
#include "net_kern.h"
#include "net_user.h"
static inline void set_ether_mac(struct net_device *dev, unsigned char *addr)
{
memcpy(dev->dev_addr, addr, ETH_ALEN);
}
#define DRIVER_NAME "uml-netdev"
static DEFINE_SPINLOCK(opened_lock);
......@@ -266,7 +261,7 @@ static int uml_net_set_mac(struct net_device *dev, void *addr)
struct sockaddr *hwaddr = addr;
spin_lock_irq(&lp->lock);
set_ether_mac(dev, hwaddr->sa_data);
eth_mac_addr(dev, hwaddr->sa_data);
spin_unlock_irq(&lp->lock);
return 0;
......@@ -380,7 +375,6 @@ static const struct net_device_ops uml_netdev_ops = {
.ndo_tx_timeout = uml_net_tx_timeout,
.ndo_set_mac_address = uml_net_set_mac,
.ndo_change_mtu = uml_net_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
};
......@@ -478,7 +472,7 @@ static void eth_configure(int n, void *init, char *mac,
((*transport->user->init)(&lp->user, dev) != 0))
goto out_unregister;
set_ether_mac(dev, device->mac);
eth_mac_addr(dev, device->mac);
dev->mtu = transport->user->mtu;
dev->netdev_ops = &uml_netdev_ops;
dev->ethtool_ops = &uml_net_ethtool_ops;
......
......@@ -457,4 +457,11 @@ static __always_inline void rdtsc_barrier(void)
alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
}
/*
* We handle most unaligned accesses in hardware. On the other hand
* unaligned DMA can be quite expensive on some Nehalem processors.
*
* Based on this we disable the IP header alignment in network drivers.
*/
#define NET_IP_ALIGN 0
#endif /* _ASM_X86_SYSTEM_H */
......@@ -177,7 +177,7 @@ config ATM_ZATM_DEBUG
config ATM_NICSTAR
tristate "IDT 77201 (NICStAR) (ForeRunnerLE)"
depends on PCI && !64BIT && VIRT_TO_BUS
depends on PCI
help
The NICStAR chipset family is used in a large number of ATM NICs for
25 and for 155 Mbps, including IDT cards and the Fore ForeRunnerLE
......
......@@ -40,6 +40,42 @@ struct adummy_dev {
static LIST_HEAD(adummy_devs);
static ssize_t __set_signal(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
struct atm_dev *atm_dev = container_of(dev, struct atm_dev, class_dev);
int signal;
if (sscanf(buf, "%d", &signal) == 1) {
if (signal < ATM_PHY_SIG_LOST || signal > ATM_PHY_SIG_FOUND)
signal = ATM_PHY_SIG_UNKNOWN;
atm_dev_signal_change(atm_dev, signal);
return 1;
}
return -EINVAL;
}
static ssize_t __show_signal(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct atm_dev *atm_dev = container_of(dev, struct atm_dev, class_dev);
return sprintf(buf, "%d\n", atm_dev->signal);
}
static DEVICE_ATTR(signal, 0644, __show_signal, __set_signal);
static struct attribute *adummy_attrs[] = {
&dev_attr_signal.attr,
NULL
};
static struct attribute_group adummy_group_attrs = {
.name = NULL, /* We want them in dev's root folder */
.attrs = adummy_attrs
};
static int __init
adummy_start(struct atm_dev *dev)
{
......@@ -128,6 +164,9 @@ static int __init adummy_init(void)
adummy_dev->atm_dev = atm_dev;
atm_dev->dev_data = adummy_dev;
if (sysfs_create_group(&atm_dev->class_dev.kobj, &adummy_group_attrs))
dev_err(&atm_dev->class_dev, "Could not register attrs for adummy\n");
if (adummy_start(atm_dev)) {
printk(KERN_ERR DEV_LABEL ": adummy_start() failed\n");
err = -ENODEV;
......
......@@ -2371,10 +2371,8 @@ MODULE_PARM_DESC(pci_lat, "PCI latency in bus cycles");
/********** module entry **********/
static struct pci_device_id amb_pci_tbl[] = {
{ PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_AMBASSADOR, PCI_ANY_ID, PCI_ANY_ID,
0, 0, 0 },
{ PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_AMBASSADOR_BAD, PCI_ANY_ID, PCI_ANY_ID,
0, 0, 0 },
{ PCI_VDEVICE(MADGE, PCI_DEVICE_ID_MADGE_AMBASSADOR), 0 },
{ PCI_VDEVICE(MADGE, PCI_DEVICE_ID_MADGE_AMBASSADOR_BAD), 0 },
{ 0, }
};
......
......@@ -2269,10 +2269,8 @@ static int __devinit eni_init_one(struct pci_dev *pci_dev,
static struct pci_device_id eni_pci_tbl[] = {
{ PCI_VENDOR_ID_EF, PCI_DEVICE_ID_EF_ATM_FPGA, PCI_ANY_ID, PCI_ANY_ID,
0, 0, 0 /* FPGA */ },
{ PCI_VENDOR_ID_EF, PCI_DEVICE_ID_EF_ATM_ASIC, PCI_ANY_ID, PCI_ANY_ID,
0, 0, 1 /* ASIC */ },
{ PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_FPGA), 0 /* FPGA */ },
{ PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_ASIC), 1 /* ASIC */ },
{ 0, }
};
MODULE_DEVICE_TABLE(pci,eni_pci_tbl);
......
......@@ -2027,10 +2027,8 @@ static void __devexit firestream_remove_one (struct pci_dev *pdev)
}
static struct pci_device_id firestream_pci_tbl[] = {
{ PCI_VENDOR_ID_FUJITSU_ME, PCI_DEVICE_ID_FUJITSU_FS50,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, FS_IS50},
{ PCI_VENDOR_ID_FUJITSU_ME, PCI_DEVICE_ID_FUJITSU_FS155,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, FS_IS155},
{ PCI_VDEVICE(FUJITSU_ME, PCI_DEVICE_ID_FUJITSU_FS50), FS_IS50},
{ PCI_VDEVICE(FUJITSU_ME, PCI_DEVICE_ID_FUJITSU_FS155), FS_IS155},
{ 0, }
};
......
......@@ -67,6 +67,7 @@
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/bitmap.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <asm/byteorder.h>
......@@ -778,61 +779,39 @@ he_init_cs_block_rcm(struct he_dev *he_dev)
static int __devinit
he_init_group(struct he_dev *he_dev, int group)
{
struct he_buff *heb, *next;
dma_addr_t mapping;
int i;
/* small buffer pool */
he_dev->rbps_pool = pci_pool_create("rbps", he_dev->pci_dev,
CONFIG_RBPS_BUFSIZE, 8, 0);
if (he_dev->rbps_pool == NULL) {
hprintk("unable to create rbps pages\n");
he_writel(he_dev, 0x0, G0_RBPS_S + (group * 32));
he_writel(he_dev, 0x0, G0_RBPS_T + (group * 32));
he_writel(he_dev, 0x0, G0_RBPS_QI + (group * 32));
he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0),
G0_RBPS_BS + (group * 32));
/* bitmap table */
he_dev->rbpl_table = kmalloc(BITS_TO_LONGS(RBPL_TABLE_SIZE)
* sizeof(unsigned long), GFP_KERNEL);
if (!he_dev->rbpl_table) {
hprintk("unable to allocate rbpl bitmap table\n");
return -ENOMEM;
}
bitmap_zero(he_dev->rbpl_table, RBPL_TABLE_SIZE);
he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev,
CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys);
if (he_dev->rbps_base == NULL) {
hprintk("failed to alloc rbps_base\n");
goto out_destroy_rbps_pool;
/* rbpl_virt 64-bit pointers */
he_dev->rbpl_virt = kmalloc(RBPL_TABLE_SIZE
* sizeof(struct he_buff *), GFP_KERNEL);
if (!he_dev->rbpl_virt) {
hprintk("unable to allocate rbpl virt table\n");
goto out_free_rbpl_table;
}
memset(he_dev->rbps_base, 0, CONFIG_RBPS_SIZE * sizeof(struct he_rbp));
he_dev->rbps_virt = kmalloc(CONFIG_RBPS_SIZE * sizeof(struct he_virt), GFP_KERNEL);
if (he_dev->rbps_virt == NULL) {
hprintk("failed to alloc rbps_virt\n");
goto out_free_rbps_base;
}
for (i = 0; i < CONFIG_RBPS_SIZE; ++i) {
dma_addr_t dma_handle;
void *cpuaddr;
cpuaddr = pci_pool_alloc(he_dev->rbps_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
if (cpuaddr == NULL)
goto out_free_rbps_virt;
he_dev->rbps_virt[i].virt = cpuaddr;
he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF);
he_dev->rbps_base[i].phys = dma_handle;
}
he_dev->rbps_tail = &he_dev->rbps_base[CONFIG_RBPS_SIZE - 1];
he_writel(he_dev, he_dev->rbps_phys, G0_RBPS_S + (group * 32));
he_writel(he_dev, RBPS_MASK(he_dev->rbps_tail),
G0_RBPS_T + (group * 32));
he_writel(he_dev, CONFIG_RBPS_BUFSIZE/4,
G0_RBPS_BS + (group * 32));
he_writel(he_dev,
RBP_THRESH(CONFIG_RBPS_THRESH) |
RBP_QSIZE(CONFIG_RBPS_SIZE - 1) |
RBP_INT_ENB,
G0_RBPS_QI + (group * 32));
/* large buffer pool */
he_dev->rbpl_pool = pci_pool_create("rbpl", he_dev->pci_dev,
CONFIG_RBPL_BUFSIZE, 8, 0);
CONFIG_RBPL_BUFSIZE, 64, 0);
if (he_dev->rbpl_pool == NULL) {
hprintk("unable to create rbpl pool\n");
goto out_free_rbps_virt;
goto out_free_rbpl_virt;
}
he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev,
......@@ -842,30 +821,29 @@ he_init_group(struct he_dev *he_dev, int group)
goto out_destroy_rbpl_pool;
}
memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp));
he_dev->rbpl_virt = kmalloc(CONFIG_RBPL_SIZE * sizeof(struct he_virt), GFP_KERNEL);
if (he_dev->rbpl_virt == NULL) {
hprintk("failed to alloc rbpl_virt\n");
goto out_free_rbpl_base;
}
INIT_LIST_HEAD(&he_dev->rbpl_outstanding);
for (i = 0; i < CONFIG_RBPL_SIZE; ++i) {
dma_addr_t dma_handle;
void *cpuaddr;
cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
if (cpuaddr == NULL)
goto out_free_rbpl_virt;
heb = pci_pool_alloc(he_dev->rbpl_pool, GFP_KERNEL|GFP_DMA, &mapping);
if (!heb)
goto out_free_rbpl;
heb->mapping = mapping;
list_add(&heb->entry, &he_dev->rbpl_outstanding);
he_dev->rbpl_virt[i].virt = cpuaddr;
he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF);
he_dev->rbpl_base[i].phys = dma_handle;
set_bit(i, he_dev->rbpl_table);
he_dev->rbpl_virt[i] = heb;
he_dev->rbpl_hint = i + 1;
he_dev->rbpl_base[i].idx = i << RBP_IDX_OFFSET;
he_dev->rbpl_base[i].phys = mapping + offsetof(struct he_buff, data);
}
he_dev->rbpl_tail = &he_dev->rbpl_base[CONFIG_RBPL_SIZE - 1];
he_writel(he_dev, he_dev->rbpl_phys, G0_RBPL_S + (group * 32));
he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail),
G0_RBPL_T + (group * 32));
he_writel(he_dev, CONFIG_RBPL_BUFSIZE/4,
he_writel(he_dev, (CONFIG_RBPL_BUFSIZE - sizeof(struct he_buff))/4,
G0_RBPL_BS + (group * 32));
he_writel(he_dev,
RBP_THRESH(CONFIG_RBPL_THRESH) |
......@@ -879,7 +857,7 @@ he_init_group(struct he_dev *he_dev, int group)
CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys);
if (he_dev->rbrq_base == NULL) {
hprintk("failed to allocate rbrq\n");
goto out_free_rbpl_virt;
goto out_free_rbpl;
}
memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq));
......@@ -920,33 +898,20 @@ he_init_group(struct he_dev *he_dev, int group)
pci_free_consistent(he_dev->pci_dev, CONFIG_RBRQ_SIZE *
sizeof(struct he_rbrq), he_dev->rbrq_base,
he_dev->rbrq_phys);
i = CONFIG_RBPL_SIZE;
out_free_rbpl_virt:
while (i--)
pci_pool_free(he_dev->rbpl_pool, he_dev->rbpl_virt[i].virt,
he_dev->rbpl_base[i].phys);
kfree(he_dev->rbpl_virt);
out_free_rbpl:
list_for_each_entry_safe(heb, next, &he_dev->rbpl_outstanding, entry)
pci_pool_free(he_dev->rbpl_pool, heb, heb->mapping);
out_free_rbpl_base:
pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE *
sizeof(struct he_rbp), he_dev->rbpl_base,
he_dev->rbpl_phys);
out_destroy_rbpl_pool:
pci_pool_destroy(he_dev->rbpl_pool);
out_free_rbpl_virt:
kfree(he_dev->rbpl_virt);
out_free_rbpl_table:
kfree(he_dev->rbpl_table);
i = CONFIG_RBPS_SIZE;
out_free_rbps_virt:
while (i--)
pci_pool_free(he_dev->rbps_pool, he_dev->rbps_virt[i].virt,
he_dev->rbps_base[i].phys);
kfree(he_dev->rbps_virt);
out_free_rbps_base:
pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE *
sizeof(struct he_rbp), he_dev->rbps_base,
he_dev->rbps_phys);
out_destroy_rbps_pool:
pci_pool_destroy(he_dev->rbps_pool);
return -ENOMEM;
}
......@@ -1002,7 +967,8 @@ he_init_irq(struct he_dev *he_dev)
he_writel(he_dev, 0x0, GRP_54_MAP);
he_writel(he_dev, 0x0, GRP_76_MAP);
if (request_irq(he_dev->pci_dev->irq, he_irq_handler, IRQF_DISABLED|IRQF_SHARED, DEV_LABEL, he_dev)) {
if (request_irq(he_dev->pci_dev->irq,
he_irq_handler, IRQF_SHARED, DEV_LABEL, he_dev)) {
hprintk("irq %d already in use\n", he_dev->pci_dev->irq);
return -EINVAL;
}
......@@ -1576,9 +1542,10 @@ he_start(struct atm_dev *dev)
static void
he_stop(struct he_dev *he_dev)
{
u16 command;
u32 gen_cntl_0, reg;
struct he_buff *heb, *next;
struct pci_dev *pci_dev;
u32 gen_cntl_0, reg;
u16 command;
pci_dev = he_dev->pci_dev;
......@@ -1619,37 +1586,19 @@ he_stop(struct he_dev *he_dev)
he_dev->hsp, he_dev->hsp_phys);
if (he_dev->rbpl_base) {
int i;
for (i = 0; i < CONFIG_RBPL_SIZE; ++i) {
void *cpuaddr = he_dev->rbpl_virt[i].virt;
dma_addr_t dma_handle = he_dev->rbpl_base[i].phys;
list_for_each_entry_safe(heb, next, &he_dev->rbpl_outstanding, entry)
pci_pool_free(he_dev->rbpl_pool, heb, heb->mapping);
pci_pool_free(he_dev->rbpl_pool, cpuaddr, dma_handle);
}
pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE
* sizeof(struct he_rbp), he_dev->rbpl_base, he_dev->rbpl_phys);
}
kfree(he_dev->rbpl_virt);
kfree(he_dev->rbpl_table);
if (he_dev->rbpl_pool)
pci_pool_destroy(he_dev->rbpl_pool);
if (he_dev->rbps_base) {
int i;
for (i = 0; i < CONFIG_RBPS_SIZE; ++i) {
void *cpuaddr = he_dev->rbps_virt[i].virt;
dma_addr_t dma_handle = he_dev->rbps_base[i].phys;
pci_pool_free(he_dev->rbps_pool, cpuaddr, dma_handle);
}
pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE
* sizeof(struct he_rbp), he_dev->rbps_base, he_dev->rbps_phys);
}
if (he_dev->rbps_pool)
pci_pool_destroy(he_dev->rbps_pool);
if (he_dev->rbrq_base)
pci_free_consistent(he_dev->pci_dev, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq),
he_dev->rbrq_base, he_dev->rbrq_phys);
......@@ -1679,13 +1628,13 @@ static struct he_tpd *
__alloc_tpd(struct he_dev *he_dev)
{
struct he_tpd *tpd;
dma_addr_t dma_handle;
dma_addr_t mapping;
tpd = pci_pool_alloc(he_dev->tpd_pool, GFP_ATOMIC|GFP_DMA, &dma_handle);
tpd = pci_pool_alloc(he_dev->tpd_pool, GFP_ATOMIC|GFP_DMA, &mapping);
if (tpd == NULL)
return NULL;
tpd->status = TPD_ADDR(dma_handle);
tpd->status = TPD_ADDR(mapping);
tpd->reserved = 0;
tpd->iovec[0].addr = 0; tpd->iovec[0].len = 0;
tpd->iovec[1].addr = 0; tpd->iovec[1].len = 0;
......@@ -1714,13 +1663,12 @@ he_service_rbrq(struct he_dev *he_dev, int group)
struct he_rbrq *rbrq_tail = (struct he_rbrq *)
((unsigned long)he_dev->rbrq_base |
he_dev->hsp->group[group].rbrq_tail);
struct he_rbp *rbp = NULL;
unsigned cid, lastcid = -1;
unsigned buf_len = 0;
struct sk_buff *skb;
struct atm_vcc *vcc = NULL;
struct he_vcc *he_vcc;
struct he_iovec *iov;
struct he_buff *heb, *next;
int i;
int pdus_assembled = 0;
int updated = 0;
......@@ -1740,44 +1688,35 @@ he_service_rbrq(struct he_dev *he_dev, int group)
RBRQ_CON_CLOSED(he_dev->rbrq_head) ? " CON_CLOSED" : "",
RBRQ_HBUF_ERR(he_dev->rbrq_head) ? " HBUF_ERR" : "");
if (RBRQ_ADDR(he_dev->rbrq_head) & RBP_SMALLBUF)
rbp = &he_dev->rbps_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))];
else
rbp = &he_dev->rbpl_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))];
buf_len = RBRQ_BUFLEN(he_dev->rbrq_head) * 4;
cid = RBRQ_CID(he_dev->rbrq_head);
i = RBRQ_ADDR(he_dev->rbrq_head) >> RBP_IDX_OFFSET;
heb = he_dev->rbpl_virt[i];
cid = RBRQ_CID(he_dev->rbrq_head);
if (cid != lastcid)
vcc = __find_vcc(he_dev, cid);
lastcid = cid;
if (vcc == NULL) {
hprintk("vcc == NULL (cid 0x%x)\n", cid);
if (!RBRQ_HBUF_ERR(he_dev->rbrq_head))
rbp->status &= ~RBP_LOANED;
if (vcc == NULL || (he_vcc = HE_VCC(vcc)) == NULL) {
hprintk("vcc/he_vcc == NULL (cid 0x%x)\n", cid);
if (!RBRQ_HBUF_ERR(he_dev->rbrq_head)) {
clear_bit(i, he_dev->rbpl_table);
list_del(&heb->entry);
pci_pool_free(he_dev->rbpl_pool, heb, heb->mapping);
}
goto next_rbrq_entry;
}
he_vcc = HE_VCC(vcc);
if (he_vcc == NULL) {
hprintk("he_vcc == NULL (cid 0x%x)\n", cid);
if (!RBRQ_HBUF_ERR(he_dev->rbrq_head))
rbp->status &= ~RBP_LOANED;
goto next_rbrq_entry;
}
if (RBRQ_HBUF_ERR(he_dev->rbrq_head)) {
hprintk("HBUF_ERR! (cid 0x%x)\n", cid);
atomic_inc(&vcc->stats->rx_drop);
goto return_host_buffers;
}
he_vcc->iov_tail->iov_base = RBRQ_ADDR(he_dev->rbrq_head);
he_vcc->iov_tail->iov_len = buf_len;
he_vcc->pdu_len += buf_len;
++he_vcc->iov_tail;
heb->len = RBRQ_BUFLEN(he_dev->rbrq_head) * 4;
clear_bit(i, he_dev->rbpl_table);
list_move_tail(&heb->entry, &he_vcc->buffers);
he_vcc->pdu_len += heb->len;
if (RBRQ_CON_CLOSED(he_dev->rbrq_head)) {
lastcid = -1;
......@@ -1786,12 +1725,6 @@ he_service_rbrq(struct he_dev *he_dev, int group)
goto return_host_buffers;
}
#ifdef notdef
if ((he_vcc->iov_tail - he_vcc->iov_head) > HE_MAXIOV) {
hprintk("iovec full! cid 0x%x\n", cid);
goto return_host_buffers;
}
#endif
if (!RBRQ_END_PDU(he_dev->rbrq_head))
goto next_rbrq_entry;
......@@ -1819,15 +1752,8 @@ he_service_rbrq(struct he_dev *he_dev, int group)
__net_timestamp(skb);
for (iov = he_vcc->iov_head;
iov < he_vcc->iov_tail; ++iov) {
if (iov->iov_base & RBP_SMALLBUF)
memcpy(skb_put(skb, iov->iov_len),
he_dev->rbps_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len);
else
memcpy(skb_put(skb, iov->iov_len),
he_dev->rbpl_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len);
}
list_for_each_entry(heb, &he_vcc->buffers, entry)
memcpy(skb_put(skb, heb->len), &heb->data, heb->len);
switch (vcc->qos.aal) {
case ATM_AAL0:
......@@ -1867,17 +1793,9 @@ he_service_rbrq(struct he_dev *he_dev, int group)
return_host_buffers:
++pdus_assembled;
for (iov = he_vcc->iov_head;
iov < he_vcc->iov_tail; ++iov) {
if (iov->iov_base & RBP_SMALLBUF)
rbp = &he_dev->rbps_base[RBP_INDEX(iov->iov_base)];
else
rbp = &he_dev->rbpl_base[RBP_INDEX(iov->iov_base)];
rbp->status &= ~RBP_LOANED;
}
he_vcc->iov_tail = he_vcc->iov_head;
list_for_each_entry_safe(heb, next, &he_vcc->buffers, entry)
pci_pool_free(he_dev->rbpl_pool, heb, heb->mapping);
INIT_LIST_HEAD(&he_vcc->buffers);
he_vcc->pdu_len = 0;
next_rbrq_entry:
......@@ -1978,59 +1896,51 @@ he_service_tbrq(struct he_dev *he_dev, int group)
}
}
static void
he_service_rbpl(struct he_dev *he_dev, int group)
{
struct he_rbp *newtail;
struct he_rbp *new_tail;
struct he_rbp *rbpl_head;
struct he_buff *heb;
dma_addr_t mapping;
int i;
int moved = 0;
rbpl_head = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base |
RBPL_MASK(he_readl(he_dev, G0_RBPL_S)));
for (;;) {
newtail = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base |
new_tail = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base |
RBPL_MASK(he_dev->rbpl_tail+1));
/* table 3.42 -- rbpl_tail should never be set to rbpl_head */
if ((newtail == rbpl_head) || (newtail->status & RBP_LOANED))
if (new_tail == rbpl_head)
break;
newtail->status |= RBP_LOANED;
he_dev->rbpl_tail = newtail;
++moved;
}
if (moved)
he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail), G0_RBPL_T);
}
static void
he_service_rbps(struct he_dev *he_dev, int group)
{
struct he_rbp *newtail;
struct he_rbp *rbps_head;
int moved = 0;
rbps_head = (struct he_rbp *) ((unsigned long)he_dev->rbps_base |
RBPS_MASK(he_readl(he_dev, G0_RBPS_S)));
for (;;) {
newtail = (struct he_rbp *) ((unsigned long)he_dev->rbps_base |
RBPS_MASK(he_dev->rbps_tail+1));
i = find_next_zero_bit(he_dev->rbpl_table, RBPL_TABLE_SIZE, he_dev->rbpl_hint);
if (i > (RBPL_TABLE_SIZE - 1)) {
i = find_first_zero_bit(he_dev->rbpl_table, RBPL_TABLE_SIZE);
if (i > (RBPL_TABLE_SIZE - 1))
break;
}
he_dev->rbpl_hint = i + 1;
/* table 3.42 -- rbps_tail should never be set to rbps_head */
if ((newtail == rbps_head) || (newtail->status & RBP_LOANED))
heb = pci_pool_alloc(he_dev->rbpl_pool, GFP_ATOMIC|GFP_DMA, &mapping);
if (!heb)
break;
newtail->status |= RBP_LOANED;
he_dev->rbps_tail = newtail;
heb->mapping = mapping;
list_add(&heb->entry, &he_dev->rbpl_outstanding);
he_dev->rbpl_virt[i] = heb;
set_bit(i, he_dev->rbpl_table);
new_tail->idx = i << RBP_IDX_OFFSET;
new_tail->phys = mapping + offsetof(struct he_buff, data);
he_dev->rbpl_tail = new_tail;
++moved;
}
if (moved)
he_writel(he_dev, RBPS_MASK(he_dev->rbps_tail), G0_RBPS_T);
he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail), G0_RBPL_T);
}
static void
......@@ -2055,10 +1965,8 @@ he_tasklet(unsigned long data)
HPRINTK("rbrq%d threshold\n", group);
/* fall through */
case ITYPE_RBRQ_TIMER:
if (he_service_rbrq(he_dev, group)) {
if (he_service_rbrq(he_dev, group))
he_service_rbpl(he_dev, group);
he_service_rbps(he_dev, group);
}
break;
case ITYPE_TBRQ_THRESH:
HPRINTK("tbrq%d threshold\n", group);
......@@ -2070,7 +1978,7 @@ he_tasklet(unsigned long data)
he_service_rbpl(he_dev, group);
break;
case ITYPE_RBPS_THRESH:
he_service_rbps(he_dev, group);
/* shouldn't happen unless small buffers enabled */
break;
case ITYPE_PHY:
HPRINTK("phy interrupt\n");
......@@ -2098,7 +2006,6 @@ he_tasklet(unsigned long data)
he_service_rbrq(he_dev, 0);
he_service_rbpl(he_dev, 0);
he_service_rbps(he_dev, 0);
he_service_tbrq(he_dev, 0);
break;
default:
......@@ -2252,7 +2159,7 @@ he_open(struct atm_vcc *vcc)
return -ENOMEM;
}
he_vcc->iov_tail = he_vcc->iov_head;
INIT_LIST_HEAD(&he_vcc->buffers);
he_vcc->pdu_len = 0;
he_vcc->rc_index = -1;
......@@ -2406,8 +2313,8 @@ he_open(struct atm_vcc *vcc)
goto open_failed;
}
rsr1 = RSR1_GROUP(0);
rsr4 = RSR4_GROUP(0);
rsr1 = RSR1_GROUP(0) | RSR1_RBPL_ONLY;
rsr4 = RSR4_GROUP(0) | RSR4_RBPL_ONLY;
rsr0 = vcc->qos.rxtp.traffic_class == ATM_UBR ?
(RSR0_EPD_ENABLE|RSR0_PPD_ENABLE) : 0;
......@@ -2963,8 +2870,7 @@ module_param(sdh, bool, 0);
MODULE_PARM_DESC(sdh, "use SDH framing (default 0)");
static struct pci_device_id he_pci_tbl[] = {
{ PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_HE, PCI_ANY_ID, PCI_ANY_ID,
0, 0, 0 },
{ PCI_VDEVICE(FORE, PCI_DEVICE_ID_FORE_HE), 0 },
{ 0, }
};
......
......@@ -67,11 +67,6 @@
#define CONFIG_RBPL_BUFSIZE 4096
#define RBPL_MASK(x) (((unsigned long)(x))&((CONFIG_RBPL_SIZE<<3)-1))
#define CONFIG_RBPS_SIZE 1024
#define CONFIG_RBPS_THRESH 64
#define CONFIG_RBPS_BUFSIZE 128
#define RBPS_MASK(x) (((unsigned long)(x))&((CONFIG_RBPS_SIZE<<3)-1))
/* 5.1.3 initialize connection memory */
#define CONFIG_RSRA 0x00000
......@@ -203,36 +198,37 @@ struct he_hsp {
} group[HE_NUM_GROUPS];
};
/* figure 2.9 receive buffer pools */
/*
* figure 2.9 receive buffer pools
*
* since a virtual address might be more than 32 bits, we store an index
* in the virt member of he_rbp. NOTE: the lower six bits in the rbrq
* addr member are used for buffer status further limiting us to 26 bits.
*/
struct he_rbp {
volatile u32 phys;
volatile u32 status;
volatile u32 idx; /* virt */
};
/* NOTE: it is suggested that virt be the virtual address of the host
buffer. on a 64-bit machine, this would not work. Instead, we
store the real virtual address in another list, and store an index
(and buffer status) in the virt member.
*/
#define RBP_IDX_OFFSET 6
#define RBP_INDEX_OFF 6
#define RBP_INDEX(x) (((long)(x) >> RBP_INDEX_OFF) & 0xffff)
#define RBP_LOANED 0x80000000
#define RBP_SMALLBUF 0x40000000
/*
* the he dma engine will try to hold an extra 16 buffers in its local
* caches. and add a couple buffers for safety.
*/
struct he_virt {
void *virt;
};
#define RBPL_TABLE_SIZE (CONFIG_RBPL_SIZE + 16 + 2)
#define RBPL_ALIGNMENT CONFIG_RBPL_SIZE
#define RBPS_ALIGNMENT CONFIG_RBPS_SIZE
struct he_buff {
struct list_head entry;
dma_addr_t mapping;
unsigned long len;
u8 data[];
};
#ifdef notyet
struct he_group {
u32 rpbs_size, rpbs_qsize;
struct he_rbp rbps_ba;
u32 rpbl_size, rpbl_qsize;
struct he_rpb_entry *rbpl_ba;
};
......@@ -297,18 +293,15 @@ struct he_dev {
struct he_rbrq *rbrq_base, *rbrq_head;
int rbrq_peak;
struct he_buff **rbpl_virt;
unsigned long *rbpl_table;
unsigned long rbpl_hint;
struct pci_pool *rbpl_pool;
dma_addr_t rbpl_phys;
struct he_rbp *rbpl_base, *rbpl_tail;
struct he_virt *rbpl_virt;
struct list_head rbpl_outstanding;
int rbpl_peak;
struct pci_pool *rbps_pool;
dma_addr_t rbps_phys;
struct he_rbp *rbps_base, *rbps_tail;
struct he_virt *rbps_virt;
int rbps_peak;
dma_addr_t tbrq_phys;
struct he_tbrq *tbrq_base, *tbrq_head;
int tbrq_peak;
......@@ -321,20 +314,12 @@ struct he_dev {
struct he_dev *next;
};
struct he_iovec
{
u32 iov_base;
u32 iov_len;
};
#define HE_MAXIOV 20
struct he_vcc
{
struct he_iovec iov_head[HE_MAXIOV];
struct he_iovec *iov_tail;
struct list_head buffers;
int pdu_len;
int rc_index;
wait_queue_head_t rx_waitq;
......
......@@ -126,7 +126,7 @@ static void idt77105_restart_timer_func(unsigned long dummy)
istat = GET(ISTAT); /* side effect: clears all interrupt status bits */
if (istat & IDT77105_ISTAT_GOODSIG) {
/* Found signal again */
dev->signal = ATM_PHY_SIG_FOUND;
atm_dev_signal_change(dev, ATM_PHY_SIG_FOUND);
printk(KERN_NOTICE "%s(itf %d): signal detected again\n",
dev->type,dev->number);
/* flush the receive FIFO */
......@@ -222,7 +222,7 @@ static void idt77105_int(struct atm_dev *dev)
/* Rx Signal Condition Change - line went up or down */
if (istat & IDT77105_ISTAT_GOODSIG) { /* signal detected again */
/* This should not happen (restart timer does it) but JIC */
dev->signal = ATM_PHY_SIG_FOUND;
atm_dev_signal_change(dev, ATM_PHY_SIG_FOUND);
} else { /* signal lost */
/*
* Disable interrupts and stop all transmission and
......@@ -235,7 +235,7 @@ static void idt77105_int(struct atm_dev *dev)
IDT77105_MCR_DRIC|
IDT77105_MCR_HALTTX
) & ~IDT77105_MCR_EIP, MCR);
dev->signal = ATM_PHY_SIG_LOST;
atm_dev_signal_change(dev, ATM_PHY_SIG_LOST);
printk(KERN_NOTICE "%s(itf %d): signal lost\n",
dev->type,dev->number);
}
......@@ -272,8 +272,9 @@ static int idt77105_start(struct atm_dev *dev)
memset(&PRIV(dev)->stats,0,sizeof(struct idt77105_stats));
/* initialise dev->signal from Good Signal Bit */
dev->signal = GET(ISTAT) & IDT77105_ISTAT_GOODSIG ? ATM_PHY_SIG_FOUND :
ATM_PHY_SIG_LOST;
atm_dev_signal_change(dev,
GET(ISTAT) & IDT77105_ISTAT_GOODSIG ?
ATM_PHY_SIG_FOUND : ATM_PHY_SIG_LOST);
if (dev->signal == ATM_PHY_SIG_LOST)
printk(KERN_WARNING "%s(itf %d): no signal\n",dev->type,
dev->number);
......
......@@ -3364,7 +3364,7 @@ init_card(struct atm_dev *dev)
writel(SAR_STAT_TMROF, SAR_REG_STAT);
}
IPRINTK("%s: Request IRQ ... ", card->name);
if (request_irq(pcidev->irq, idt77252_interrupt, IRQF_DISABLED|IRQF_SHARED,
if (request_irq(pcidev->irq, idt77252_interrupt, IRQF_SHARED,
card->name, card) != 0) {
printk("%s: can't allocate IRQ.\n", card->name);
deinit_card(card);
......@@ -3779,8 +3779,7 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
static struct pci_device_id idt77252_pci_tbl[] =
{
{ PCI_VENDOR_ID_IDT, PCI_DEVICE_ID_IDT_IDT77252,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VDEVICE(IDT, PCI_DEVICE_ID_IDT_IDT77252), 0 },
{ 0, }
};
......
此差异已折叠。
此差异已折叠。
......@@ -13,15 +13,15 @@ typedef void __iomem *virt_addr_t;
#define CYCLE_DELAY 5
/* This was the original definition
/*
This was the original definition
#define osp_MicroDelay(microsec) \
do { int _i = 4*microsec; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
*/
#define osp_MicroDelay(microsec) {unsigned long useconds = (microsec); \
udelay((useconds));}
/* The following tables represent the timing diagrams found in
/*
* The following tables represent the timing diagrams found in
* the Data Sheet for the Xicor X25020 EEProm. The #defines below
* represent the bits in the NICStAR's General Purpose register
* that must be toggled for the corresponding actions on the EEProm
......@@ -31,86 +31,80 @@ typedef void __iomem *virt_addr_t;
/* Write Data To EEProm from SI line on rising edge of CLK */
/* Read Data From EEProm on falling edge of CLK */
#define CS_HIGH 0x0002 /* Chip select high */
#define CS_LOW 0x0000 /* Chip select low (active low)*/
#define CLK_HIGH 0x0004 /* Clock high */
#define CLK_LOW 0x0000 /* Clock low */
#define SI_HIGH 0x0001 /* Serial input data high */
#define SI_LOW 0x0000 /* Serial input data low */
#define CS_HIGH 0x0002 /* Chip select high */
#define CS_LOW 0x0000 /* Chip select low (active low) */
#define CLK_HIGH 0x0004 /* Clock high */
#define CLK_LOW 0x0000 /* Clock low */
#define SI_HIGH 0x0001 /* Serial input data high */
#define SI_LOW 0x0000 /* Serial input data low */
/* Read Status Register = 0000 0101b */
#if 0
static u_int32_t rdsrtab[] =
{
CS_HIGH | CLK_HIGH,
CS_LOW | CLK_LOW,
CLK_HIGH, /* 0 */
CLK_LOW,
CLK_HIGH, /* 0 */
CLK_LOW,
CLK_HIGH, /* 0 */
CLK_LOW,
CLK_HIGH, /* 0 */
CLK_LOW,
CLK_HIGH, /* 0 */
CLK_LOW | SI_HIGH,
CLK_HIGH | SI_HIGH, /* 1 */
CLK_LOW | SI_LOW,
CLK_HIGH, /* 0 */
CLK_LOW | SI_HIGH,
CLK_HIGH | SI_HIGH /* 1 */
static u_int32_t rdsrtab[] = {
CS_HIGH | CLK_HIGH,
CS_LOW | CLK_LOW,
CLK_HIGH, /* 0 */
CLK_LOW,
CLK_HIGH, /* 0 */
CLK_LOW,
CLK_HIGH, /* 0 */
CLK_LOW,
CLK_HIGH, /* 0 */
CLK_LOW,
CLK_HIGH, /* 0 */
CLK_LOW | SI_HIGH,
CLK_HIGH | SI_HIGH, /* 1 */
CLK_LOW | SI_LOW,
CLK_HIGH, /* 0 */
CLK_LOW | SI_HIGH,
CLK_HIGH | SI_HIGH /* 1 */
};
#endif /* 0 */
#endif /* 0 */
/* Read from EEPROM = 0000 0011b */
static u_int32_t readtab[] =
{
/*
CS_HIGH | CLK_HIGH,
*/
CS_LOW | CLK_LOW,
CLK_HIGH, /* 0 */
CLK_LOW,
CLK_HIGH, /* 0 */
CLK_LOW,
CLK_HIGH, /* 0 */
CLK_LOW,
CLK_HIGH, /* 0 */
CLK_LOW,
CLK_HIGH, /* 0 */
CLK_LOW,
CLK_HIGH, /* 0 */
CLK_LOW | SI_HIGH,
CLK_HIGH | SI_HIGH, /* 1 */
CLK_LOW | SI_HIGH,
CLK_HIGH | SI_HIGH /* 1 */
static u_int32_t readtab[] = {
/*
CS_HIGH | CLK_HIGH,
*/
CS_LOW | CLK_LOW,
CLK_HIGH, /* 0 */
CLK_LOW,
CLK_HIGH, /* 0 */
CLK_LOW,
CLK_HIGH, /* 0 */
CLK_LOW,
CLK_HIGH, /* 0 */
CLK_LOW,
CLK_HIGH, /* 0 */
CLK_LOW,
CLK_HIGH, /* 0 */
CLK_LOW | SI_HIGH,
CLK_HIGH | SI_HIGH, /* 1 */
CLK_LOW | SI_HIGH,
CLK_HIGH | SI_HIGH /* 1 */
};
/* Clock to read from/write to the eeprom */
static u_int32_t clocktab[] =
{
CLK_LOW,
CLK_HIGH,
CLK_LOW,
CLK_HIGH,
CLK_LOW,
CLK_HIGH,
CLK_LOW,
CLK_HIGH,
CLK_LOW,
CLK_HIGH,
CLK_LOW,
CLK_HIGH,
CLK_LOW,
CLK_HIGH,
CLK_LOW,
CLK_HIGH,
CLK_LOW
static u_int32_t clocktab[] = {
CLK_LOW,
CLK_HIGH,
CLK_LOW,
CLK_HIGH,
CLK_LOW,
CLK_HIGH,
CLK_LOW,
CLK_HIGH,
CLK_LOW,
CLK_HIGH,
CLK_LOW,
CLK_HIGH,
CLK_LOW,
CLK_HIGH,
CLK_LOW,
CLK_HIGH,
CLK_LOW
};
#define NICSTAR_REG_WRITE(bs, reg, val) \
while ( readl(bs + STAT) & 0x0200 ) ; \
writel((val),(base)+(reg))
......@@ -124,153 +118,131 @@ static u_int32_t clocktab[] =
* register.
*/
#if 0
u_int32_t
nicstar_read_eprom_status( virt_addr_t base )
u_int32_t nicstar_read_eprom_status(virt_addr_t base)
{
u_int32_t val;
u_int32_t rbyte;
int32_t i, j;
/* Send read instruction */
val = NICSTAR_REG_READ( base, NICSTAR_REG_GENERAL_PURPOSE ) & 0xFFFFFFF0;
for (i=0; i<ARRAY_SIZE(rdsrtab); i++)
{
NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE,
(val | rdsrtab[i]) );
osp_MicroDelay( CYCLE_DELAY );
}
/* Done sending instruction - now pull data off of bit 16, MSB first */
/* Data clocked out of eeprom on falling edge of clock */
rbyte = 0;
for (i=7, j=0; i>=0; i--)
{
NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE,
(val | clocktab[j++]) );
rbyte |= (((NICSTAR_REG_READ( base, NICSTAR_REG_GENERAL_PURPOSE)
& 0x00010000) >> 16) << i);
NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE,
(val | clocktab[j++]) );
osp_MicroDelay( CYCLE_DELAY );
}
NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, 2 );
osp_MicroDelay( CYCLE_DELAY );
return rbyte;
u_int32_t val;
u_int32_t rbyte;
int32_t i, j;
/* Send read instruction */
val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0;
for (i = 0; i < ARRAY_SIZE(rdsrtab); i++) {
NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
(val | rdsrtab[i]));
osp_MicroDelay(CYCLE_DELAY);
}
/* Done sending instruction - now pull data off of bit 16, MSB first */
/* Data clocked out of eeprom on falling edge of clock */
rbyte = 0;
for (i = 7, j = 0; i >= 0; i--) {
NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
(val | clocktab[j++]));
rbyte |= (((NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE)
& 0x00010000) >> 16) << i);
NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
(val | clocktab[j++]));
osp_MicroDelay(CYCLE_DELAY);
}
NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, 2);
osp_MicroDelay(CYCLE_DELAY);
return rbyte;
}
#endif /* 0 */
#endif /* 0 */
/*
* This routine will clock the Read_data function into the X2520
* eeprom, followed by the address to read from, through the NicSTaR's General
* Purpose register.
*/
static u_int8_t
read_eprom_byte(virt_addr_t base, u_int8_t offset)
static u_int8_t read_eprom_byte(virt_addr_t base, u_int8_t offset)
{
u_int32_t val = 0;
int i,j=0;
u_int8_t tempread = 0;
val = NICSTAR_REG_READ( base, NICSTAR_REG_GENERAL_PURPOSE ) & 0xFFFFFFF0;
/* Send READ instruction */
for (i=0; i<ARRAY_SIZE(readtab); i++)
{
NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE,
(val | readtab[i]) );
osp_MicroDelay( CYCLE_DELAY );
}
/* Next, we need to send the byte address to read from */
for (i=7; i>=0; i--)
{
NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE,
(val | clocktab[j++] | ((offset >> i) & 1) ) );
osp_MicroDelay(CYCLE_DELAY);
NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE,
(val | clocktab[j++] | ((offset >> i) & 1) ) );
osp_MicroDelay( CYCLE_DELAY );
}
j = 0;
/* Now, we can read data from the eeprom by clocking it in */
for (i=7; i>=0; i--)
{
NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE,
(val | clocktab[j++]) );
osp_MicroDelay( CYCLE_DELAY );
tempread |= (((NICSTAR_REG_READ( base, NICSTAR_REG_GENERAL_PURPOSE )
& 0x00010000) >> 16) << i);
NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE,
(val | clocktab[j++]) );
osp_MicroDelay( CYCLE_DELAY );
}
NICSTAR_REG_WRITE( base, NICSTAR_REG_GENERAL_PURPOSE, 2 );
osp_MicroDelay( CYCLE_DELAY );
return tempread;
u_int32_t val = 0;
int i, j = 0;
u_int8_t tempread = 0;
val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0;
/* Send READ instruction */
for (i = 0; i < ARRAY_SIZE(readtab); i++) {
NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
(val | readtab[i]));
osp_MicroDelay(CYCLE_DELAY);
}
/* Next, we need to send the byte address to read from */
for (i = 7; i >= 0; i--) {
NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
(val | clocktab[j++] | ((offset >> i) & 1)));
osp_MicroDelay(CYCLE_DELAY);
NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
(val | clocktab[j++] | ((offset >> i) & 1)));
osp_MicroDelay(CYCLE_DELAY);
}
j = 0;
/* Now, we can read data from the eeprom by clocking it in */
for (i = 7; i >= 0; i--) {
NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
(val | clocktab[j++]));
osp_MicroDelay(CYCLE_DELAY);
tempread |=
(((NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE)
& 0x00010000) >> 16) << i);
NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
(val | clocktab[j++]));
osp_MicroDelay(CYCLE_DELAY);
}
NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, 2);
osp_MicroDelay(CYCLE_DELAY);
return tempread;
}
static void
nicstar_init_eprom( virt_addr_t base )
static void nicstar_init_eprom(virt_addr_t base)
{
u_int32_t val;
u_int32_t val;
/*
* turn chip select off
*/
val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0;
/*
* turn chip select off
*/
val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0;
NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
(val | CS_HIGH | CLK_HIGH));
osp_MicroDelay( CYCLE_DELAY );
NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
(val | CS_HIGH | CLK_HIGH));
osp_MicroDelay(CYCLE_DELAY);
NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
(val | CS_HIGH | CLK_LOW));
osp_MicroDelay( CYCLE_DELAY );
NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
(val | CS_HIGH | CLK_LOW));
osp_MicroDelay(CYCLE_DELAY);
NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
(val | CS_HIGH | CLK_HIGH));
osp_MicroDelay( CYCLE_DELAY );
NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
(val | CS_HIGH | CLK_HIGH));
osp_MicroDelay(CYCLE_DELAY);
NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
(val | CS_HIGH | CLK_LOW));
osp_MicroDelay( CYCLE_DELAY );
NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
(val | CS_HIGH | CLK_LOW));
osp_MicroDelay(CYCLE_DELAY);
}
/*
* This routine will be the interface to the ReadPromByte function
* above.
*/
*/
static void
nicstar_read_eprom(
virt_addr_t base,
u_int8_t prom_offset,
u_int8_t *buffer,
u_int32_t nbytes )
nicstar_read_eprom(virt_addr_t base,
u_int8_t prom_offset, u_int8_t * buffer, u_int32_t nbytes)
{
u_int i;
for (i=0; i<nbytes; i++)
{
buffer[i] = read_eprom_byte( base, prom_offset );
++prom_offset;
osp_MicroDelay( CYCLE_DELAY );
}
}
u_int i;
/*
void osp_MicroDelay(int x) {
for (i = 0; i < nbytes; i++) {
buffer[i] = read_eprom_byte(base, prom_offset);
++prom_offset;
osp_MicroDelay(CYCLE_DELAY);
}
}
*/
......@@ -383,7 +383,7 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb
/* Anything but 'Showtime' is down */
if (strcmp(state_str, "Showtime")) {
card->atmdev[port]->signal = ATM_PHY_SIG_LOST;
atm_dev_signal_change(card->atmdev[port], ATM_PHY_SIG_LOST);
release_vccs(card->atmdev[port]);
dev_info(&card->dev->dev, "Port %d: %s\n", port, state_str);
return 0;
......@@ -401,7 +401,7 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb
snr[0]?", SNR ":"", snr, attn[0]?", Attn ":"", attn);
card->atmdev[port]->link_rate = rate_down / 424;
card->atmdev[port]->signal = ATM_PHY_SIG_FOUND;
atm_dev_signal_change(card->atmdev[port], ATM_PHY_SIG_FOUND);
return 0;
}
......@@ -1246,7 +1246,7 @@ static int atm_init(struct solos_card *card)
card->atmdev[i]->ci_range.vci_bits = 16;
card->atmdev[i]->dev_data = card;
card->atmdev[i]->phy_data = (void *)(unsigned long)i;
card->atmdev[i]->signal = ATM_PHY_SIG_UNKNOWN;
atm_dev_signal_change(card->atmdev[i], ATM_PHY_SIG_UNKNOWN);
skb = alloc_skb(sizeof(*header), GFP_ATOMIC);
if (!skb) {
......
......@@ -291,8 +291,9 @@ static int suni_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg)
static void poll_los(struct atm_dev *dev)
{
dev->signal = GET(RSOP_SIS) & SUNI_RSOP_SIS_LOSV ? ATM_PHY_SIG_LOST :
ATM_PHY_SIG_FOUND;
atm_dev_signal_change(dev,
GET(RSOP_SIS) & SUNI_RSOP_SIS_LOSV ?
ATM_PHY_SIG_LOST : ATM_PHY_SIG_FOUND);
}
......
......@@ -1637,10 +1637,8 @@ static int __devinit zatm_init_one(struct pci_dev *pci_dev,
MODULE_LICENSE("GPL");
static struct pci_device_id zatm_pci_tbl[] __devinitdata = {
{ PCI_VENDOR_ID_ZEITNET, PCI_DEVICE_ID_ZEITNET_1221,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, ZATM_COPPER },
{ PCI_VENDOR_ID_ZEITNET, PCI_DEVICE_ID_ZEITNET_1225,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VDEVICE(ZEITNET, PCI_DEVICE_ID_ZEITNET_1221), ZATM_COPPER },
{ PCI_VDEVICE(ZEITNET, PCI_DEVICE_ID_ZEITNET_1225), 0 },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, zatm_pci_tbl);
......
......@@ -1819,3 +1819,67 @@ void device_shutdown(void)
spin_unlock(&devices_kset->list_lock);
async_synchronize_full();
}
/*
* Device logging functions
*/
#ifdef CONFIG_PRINTK
static int __dev_printk(const char *level, const struct device *dev,
struct va_format *vaf)
{
if (!dev)
return printk("%s(NULL device *): %pV", level, vaf);
return printk("%s%s %s: %pV",
level, dev_driver_string(dev), dev_name(dev), vaf);
}
int dev_printk(const char *level, const struct device *dev,
const char *fmt, ...)
{
struct va_format vaf;
va_list args;
int r;
va_start(args, fmt);
vaf.fmt = fmt;
vaf.va = &args;
r = __dev_printk(level, dev, &vaf);
va_end(args);
return r;
}
EXPORT_SYMBOL(dev_printk);
#define define_dev_printk_level(func, kern_level) \
int func(const struct device *dev, const char *fmt, ...) \
{ \
struct va_format vaf; \
va_list args; \
int r; \
\
va_start(args, fmt); \
\
vaf.fmt = fmt; \
vaf.va = &args; \
\
r = __dev_printk(kern_level, dev, &vaf); \
va_end(args); \
\
return r; \
} \
EXPORT_SYMBOL(func);
define_dev_printk_level(dev_emerg, KERN_EMERG);
define_dev_printk_level(dev_alert, KERN_ALERT);
define_dev_printk_level(dev_crit, KERN_CRIT);
define_dev_printk_level(dev_err, KERN_ERR);
define_dev_printk_level(dev_warn, KERN_WARNING);
define_dev_printk_level(dev_notice, KERN_NOTICE);
define_dev_printk_level(_dev_info, KERN_INFO);
#endif
......@@ -58,6 +58,18 @@ config BT_HCIUART_BCSP
Say Y here to compile support for HCI BCSP protocol.
config BT_HCIUART_ATH3K
bool "Atheros AR300x serial support"
depends on BT_HCIUART
help
HCIATH3K (HCI Atheros AR300x) is a serial protocol for
communication between host and Atheros AR300x Bluetooth devices.
This protocol enables AR300x chips to be enabled with
power management support.
Enable this if you have Atheros AR300x serial Bluetooth device.
Say Y here to compile support for HCI UART ATH3K protocol.
config BT_HCIUART_LL
bool "HCILL protocol support"
depends on BT_HCIUART
......
......@@ -26,4 +26,5 @@ hci_uart-y := hci_ldisc.o
hci_uart-$(CONFIG_BT_HCIUART_H4) += hci_h4.o
hci_uart-$(CONFIG_BT_HCIUART_BCSP) += hci_bcsp.o
hci_uart-$(CONFIG_BT_HCIUART_LL) += hci_ll.o
hci_uart-$(CONFIG_BT_HCIUART_ATH3K) += hci_ath.o
hci_uart-objs := $(hci_uart-y)
......@@ -224,7 +224,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
BT_DBG("firmware data %p size %zu", firmware->data, firmware->size);
data->fw_data = kmalloc(firmware->size, GFP_KERNEL);
data->fw_data = kmemdup(firmware->data, firmware->size, GFP_KERNEL);
if (!data->fw_data) {
BT_ERR("Can't allocate memory for firmware image");
release_firmware(firmware);
......@@ -234,7 +234,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
return -ENOMEM;
}
memcpy(data->fw_data, firmware->data, firmware->size);
data->fw_size = firmware->size;
data->fw_sent = 0;
......
......@@ -62,7 +62,7 @@ struct hci_vendor_hdr {
__u8 type;
__le16 snum;
__le16 dlen;
} __attribute__ ((packed));
} __packed;
static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count)
{
......
......@@ -216,7 +216,7 @@ static const struct file_operations btmrvl_gpiogap_fops = {
static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf,
size_t count, loff_t *ppos)
{
struct btmrvl_private *priv = (struct btmrvl_private *) file->private_data;
struct btmrvl_private *priv = file->private_data;
char buf[16];
long result, ret;
......
......@@ -76,6 +76,7 @@ struct btmrvl_private {
int (*hw_host_to_card) (struct btmrvl_private *priv,
u8 *payload, u16 nb);
int (*hw_wakeup_firmware) (struct btmrvl_private *priv);
int (*hw_process_int_status) (struct btmrvl_private *priv);
spinlock_t driver_lock; /* spinlock used by driver */
#ifdef CONFIG_DEBUG_FS
void *debugfs_data;
......@@ -118,13 +119,13 @@ struct btmrvl_cmd {
__le16 ocf_ogf;
u8 length;
u8 data[4];
} __attribute__ ((packed));
} __packed;
struct btmrvl_event {
u8 ec; /* event counter */
u8 length;
u8 data[4];
} __attribute__ ((packed));
} __packed;
/* Prototype of global function */
......
......@@ -502,14 +502,17 @@ static int btmrvl_service_main_thread(void *data)
spin_lock_irqsave(&priv->driver_lock, flags);
if (adapter->int_count) {
adapter->int_count = 0;
spin_unlock_irqrestore(&priv->driver_lock, flags);
priv->hw_process_int_status(priv);
} else if (adapter->ps_state == PS_SLEEP &&
!skb_queue_empty(&adapter->tx_queue)) {
spin_unlock_irqrestore(&priv->driver_lock, flags);
adapter->wakeup_tries++;
priv->hw_wakeup_firmware(priv);
continue;
} else {
spin_unlock_irqrestore(&priv->driver_lock, flags);
}
spin_unlock_irqrestore(&priv->driver_lock, flags);
if (adapter->ps_state == PS_SLEEP)
continue;
......
......@@ -47,6 +47,7 @@
* module_exit function is called.
*/
static u8 user_rmmod;
static u8 sdio_ireg;
static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = {
.helper = "sd8688_helper.bin",
......@@ -83,10 +84,10 @@ static int btmrvl_sdio_read_fw_status(struct btmrvl_sdio_card *card, u16 *dat)
*dat = 0;
fws0 = sdio_readb(card->func, CARD_FW_STATUS0_REG, &ret);
if (ret)
return -EIO;
if (!ret)
fws1 = sdio_readb(card->func, CARD_FW_STATUS1_REG, &ret);
fws1 = sdio_readb(card->func, CARD_FW_STATUS1_REG, &ret);
if (ret)
return -EIO;
......@@ -216,7 +217,7 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card)
tmphlprbufsz = ALIGN_SZ(BTM_UPLD_SIZE, BTSDIO_DMA_ALIGN);
tmphlprbuf = kmalloc(tmphlprbufsz, GFP_KERNEL);
tmphlprbuf = kzalloc(tmphlprbufsz, GFP_KERNEL);
if (!tmphlprbuf) {
BT_ERR("Unable to allocate buffer for helper."
" Terminating download");
......@@ -224,8 +225,6 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card)
goto done;
}
memset(tmphlprbuf, 0, tmphlprbufsz);
helperbuf = (u8 *) ALIGN_ADDR(tmphlprbuf, BTSDIO_DMA_ALIGN);
/* Perform helper data transfer */
......@@ -318,7 +317,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
BT_DBG("Downloading FW image (%d bytes)", firmwarelen);
tmpfwbufsz = ALIGN_SZ(BTM_UPLD_SIZE, BTSDIO_DMA_ALIGN);
tmpfwbuf = kmalloc(tmpfwbufsz, GFP_KERNEL);
tmpfwbuf = kzalloc(tmpfwbufsz, GFP_KERNEL);
if (!tmpfwbuf) {
BT_ERR("Unable to allocate buffer for firmware."
" Terminating download");
......@@ -326,8 +325,6 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
goto done;
}
memset(tmpfwbuf, 0, tmpfwbufsz);
/* Ensure aligned firmware buffer */
fwbuf = (u8 *) ALIGN_ADDR(tmpfwbuf, BTSDIO_DMA_ALIGN);
......@@ -555,78 +552,79 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
return ret;
}
static int btmrvl_sdio_get_int_status(struct btmrvl_private *priv, u8 * ireg)
static int btmrvl_sdio_process_int_status(struct btmrvl_private *priv)
{
int ret;
u8 sdio_ireg = 0;
ulong flags;
u8 ireg;
struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
*ireg = 0;
sdio_ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret);
if (ret) {
BT_ERR("sdio_readb: read int status register failed");
ret = -EIO;
goto done;
}
if (sdio_ireg != 0) {
/*
* DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
* Clear the interrupt status register and re-enable the
* interrupt.
*/
BT_DBG("sdio_ireg = 0x%x", sdio_ireg);
sdio_writeb(card->func, ~(sdio_ireg) & (DN_LD_HOST_INT_STATUS |
UP_LD_HOST_INT_STATUS),
HOST_INTSTATUS_REG, &ret);
if (ret) {
BT_ERR("sdio_writeb: clear int status register "
"failed");
ret = -EIO;
goto done;
}
}
spin_lock_irqsave(&priv->driver_lock, flags);
ireg = sdio_ireg;
sdio_ireg = 0;
spin_unlock_irqrestore(&priv->driver_lock, flags);
if (sdio_ireg & DN_LD_HOST_INT_STATUS) {
sdio_claim_host(card->func);
if (ireg & DN_LD_HOST_INT_STATUS) {
if (priv->btmrvl_dev.tx_dnld_rdy)
BT_DBG("tx_done already received: "
" int_status=0x%x", sdio_ireg);
" int_status=0x%x", ireg);
else
priv->btmrvl_dev.tx_dnld_rdy = true;
}
if (sdio_ireg & UP_LD_HOST_INT_STATUS)
if (ireg & UP_LD_HOST_INT_STATUS)
btmrvl_sdio_card_to_host(priv);
*ireg = sdio_ireg;
ret = 0;
sdio_release_host(card->func);
done:
return ret;
return 0;
}
static void btmrvl_sdio_interrupt(struct sdio_func *func)
{
struct btmrvl_private *priv;
struct hci_dev *hcidev;
struct btmrvl_sdio_card *card;
ulong flags;
u8 ireg = 0;
int ret;
card = sdio_get_drvdata(func);
if (card && card->priv) {
priv = card->priv;
hcidev = priv->btmrvl_dev.hcidev;
if (!card || !card->priv) {
BT_ERR("sbi_interrupt(%p) card or priv is "
"NULL, card=%p\n", func, card);
return;
}
if (btmrvl_sdio_get_int_status(priv, &ireg))
BT_ERR("reading HOST_INT_STATUS_REG failed");
else
BT_DBG("HOST_INT_STATUS_REG %#x", ireg);
priv = card->priv;
ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret);
if (ret) {
BT_ERR("sdio_readb: read int status register failed");
return;
}
if (ireg != 0) {
/*
* DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
* Clear the interrupt status register and re-enable the
* interrupt.
*/
BT_DBG("ireg = 0x%x", ireg);
btmrvl_interrupt(priv);
sdio_writeb(card->func, ~(ireg) & (DN_LD_HOST_INT_STATUS |
UP_LD_HOST_INT_STATUS),
HOST_INTSTATUS_REG, &ret);
if (ret) {
BT_ERR("sdio_writeb: clear int status register failed");
return;
}
}
spin_lock_irqsave(&priv->driver_lock, flags);
sdio_ireg |= ireg;
spin_unlock_irqrestore(&priv->driver_lock, flags);
btmrvl_interrupt(priv);
}
static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
......@@ -930,6 +928,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
/* Initialize the interface specific function pointers */
priv->hw_host_to_card = btmrvl_sdio_host_to_card;
priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw;
priv->hw_process_int_status = btmrvl_sdio_process_int_status;
if (btmrvl_register_hdev(priv)) {
BT_ERR("Register hdev failed!");
......
......@@ -59,6 +59,9 @@ static struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
/* Apple iMac11,1 */
{ USB_DEVICE(0x05ac, 0x8215) },
/* AVM BlueFRITZ! USB v2.0 */
{ USB_DEVICE(0x057c, 0x3800) },
......@@ -146,6 +149,7 @@ static struct usb_device_id blacklist_table[] = {
#define BTUSB_BULK_RUNNING 1
#define BTUSB_ISOC_RUNNING 2
#define BTUSB_SUSPENDING 3
#define BTUSB_DID_ISO_RESUME 4
struct btusb_data {
struct hci_dev *hdev;
......@@ -179,7 +183,6 @@ struct btusb_data {
unsigned int sco_num;
int isoc_altsetting;
int suspend_count;
int did_iso_resume:1;
};
static int inc_tx(struct btusb_data *data)
......@@ -807,7 +810,7 @@ static void btusb_work(struct work_struct *work)
int err;
if (hdev->conn_hash.sco_num > 0) {
if (!data->did_iso_resume) {
if (!test_bit(BTUSB_DID_ISO_RESUME, &data->flags)) {
err = usb_autopm_get_interface(data->isoc);
if (err < 0) {
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
......@@ -815,7 +818,7 @@ static void btusb_work(struct work_struct *work)
return;
}
data->did_iso_resume = 1;
set_bit(BTUSB_DID_ISO_RESUME, &data->flags);
}
if (data->isoc_altsetting != 2) {
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
......@@ -836,10 +839,8 @@ static void btusb_work(struct work_struct *work)
usb_kill_anchored_urbs(&data->isoc_anchor);
__set_isoc_interface(hdev, 0);
if (data->did_iso_resume) {
data->did_iso_resume = 0;
if (test_and_clear_bit(BTUSB_DID_ISO_RESUME, &data->flags))
usb_autopm_put_interface(data->isoc);
}
}
}
......
......@@ -104,7 +104,7 @@ typedef struct {
u8 type;
u8 zero;
u16 len;
} __attribute__ ((packed)) nsh_t; /* Nokia Specific Header */
} __packed nsh_t; /* Nokia Specific Header */
#define NSHL 4 /* Nokia Specific Header Length */
......
/*
* Atheros Communication Bluetooth HCIATH3K UART protocol
*
* HCIATH3K (HCI Atheros AR300x Protocol) is a Atheros Communication's
* power management protocol extension to H4 to support AR300x Bluetooth Chip.
*
* Copyright (c) 2009-2010 Atheros Communications Inc.
*
* Acknowledgements:
* This file is based on hci_h4.c, which was written
* by Maxim Krasnyansky and Marcel Holtmann.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/skbuff.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include "hci_uart.h"
struct ath_struct {
struct hci_uart *hu;
unsigned int cur_sleep;
struct sk_buff_head txq;
struct work_struct ctxtsw;
};
static int ath_wakeup_ar3k(struct tty_struct *tty)
{
struct termios settings;
int status = tty->driver->ops->tiocmget(tty, NULL);
if (status & TIOCM_CTS)
return status;
/* Disable Automatic RTSCTS */
n_tty_ioctl_helper(tty, NULL, TCGETS, (unsigned long)&settings);
settings.c_cflag &= ~CRTSCTS;
n_tty_ioctl_helper(tty, NULL, TCSETS, (unsigned long)&settings);
/* Clear RTS first */
status = tty->driver->ops->tiocmget(tty, NULL);
tty->driver->ops->tiocmset(tty, NULL, 0x00, TIOCM_RTS);
mdelay(20);
/* Set RTS, wake up board */
status = tty->driver->ops->tiocmget(tty, NULL);
tty->driver->ops->tiocmset(tty, NULL, TIOCM_RTS, 0x00);
mdelay(20);
status = tty->driver->ops->tiocmget(tty, NULL);
n_tty_ioctl_helper(tty, NULL, TCGETS, (unsigned long)&settings);
settings.c_cflag |= CRTSCTS;
n_tty_ioctl_helper(tty, NULL, TCSETS, (unsigned long)&settings);
return status;
}
static void ath_hci_uart_work(struct work_struct *work)
{
int status;
struct ath_struct *ath;
struct hci_uart *hu;
struct tty_struct *tty;
ath = container_of(work, struct ath_struct, ctxtsw);
hu = ath->hu;
tty = hu->tty;
/* verify and wake up controller */
if (ath->cur_sleep) {
status = ath_wakeup_ar3k(tty);
if (!(status & TIOCM_CTS))
return;
}
/* Ready to send Data */
clear_bit(HCI_UART_SENDING, &hu->tx_state);
hci_uart_tx_wakeup(hu);
}
/* Initialize protocol */
static int ath_open(struct hci_uart *hu)
{
struct ath_struct *ath;
BT_DBG("hu %p", hu);
ath = kzalloc(sizeof(*ath), GFP_ATOMIC);
if (!ath)
return -ENOMEM;
skb_queue_head_init(&ath->txq);
hu->priv = ath;
ath->hu = hu;
INIT_WORK(&ath->ctxtsw, ath_hci_uart_work);
return 0;
}
/* Flush protocol data */
static int ath_flush(struct hci_uart *hu)
{
struct ath_struct *ath = hu->priv;
BT_DBG("hu %p", hu);
skb_queue_purge(&ath->txq);
return 0;
}
/* Close protocol */
static int ath_close(struct hci_uart *hu)
{
struct ath_struct *ath = hu->priv;
BT_DBG("hu %p", hu);
skb_queue_purge(&ath->txq);
cancel_work_sync(&ath->ctxtsw);
hu->priv = NULL;
kfree(ath);
return 0;
}
#define HCI_OP_ATH_SLEEP 0xFC04
/* Enqueue frame for transmittion */
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) {
kfree_skb(skb);
return 0;
}
/*
* Update power management enable flag with parameters of
* HCI sleep enable vendor specific HCI command.
*/
if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
struct hci_command_hdr *hdr = (void *)skb->data;
if (__le16_to_cpu(hdr->opcode) == HCI_OP_ATH_SLEEP)
ath->cur_sleep = skb->data[HCI_COMMAND_HDR_SIZE];
}
BT_DBG("hu %p skb %p", hu, skb);
/* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
skb_queue_tail(&ath->txq, skb);
set_bit(HCI_UART_SENDING, &hu->tx_state);
schedule_work(&ath->ctxtsw);
return 0;
}
static struct sk_buff *ath_dequeue(struct hci_uart *hu)
{
struct ath_struct *ath = hu->priv;
return skb_dequeue(&ath->txq);
}
/* Recv data */
static int ath_recv(struct hci_uart *hu, void *data, int count)
{
if (hci_recv_stream_fragment(hu->hdev, data, count) < 0)
BT_ERR("Frame Reassembly Failed");
return count;
}
static struct hci_uart_proto athp = {
.id = HCI_UART_ATH3K,
.open = ath_open,
.close = ath_close,
.recv = ath_recv,
.enqueue = ath_enqueue,
.dequeue = ath_dequeue,
.flush = ath_flush,
};
int __init ath_init(void)
{
int err = hci_uart_register_proto(&athp);
if (!err)
BT_INFO("HCIATH3K protocol initialized");
else
BT_ERR("HCIATH3K protocol registration failed");
return err;
}
int __exit ath_deinit(void)
{
return hci_uart_unregister_proto(&athp);
}
......@@ -739,7 +739,7 @@ static struct hci_uart_proto bcsp = {
.flush = bcsp_flush
};
int bcsp_init(void)
int __init bcsp_init(void)
{
int err = hci_uart_register_proto(&bcsp);
......@@ -751,7 +751,7 @@ int bcsp_init(void)
return err;
}
int bcsp_deinit(void)
int __exit bcsp_deinit(void)
{
return hci_uart_unregister_proto(&bcsp);
}
......
......@@ -151,107 +151,8 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len)
/* Recv data */
static int h4_recv(struct hci_uart *hu, void *data, int count)
{
struct h4_struct *h4 = hu->priv;
register char *ptr;
struct hci_event_hdr *eh;
struct hci_acl_hdr *ah;
struct hci_sco_hdr *sh;
register int len, type, dlen;
BT_DBG("hu %p count %d rx_state %ld rx_count %ld",
hu, count, h4->rx_state, h4->rx_count);
ptr = data;
while (count) {
if (h4->rx_count) {
len = min_t(unsigned int, h4->rx_count, count);
memcpy(skb_put(h4->rx_skb, len), ptr, len);
h4->rx_count -= len; count -= len; ptr += len;
if (h4->rx_count)
continue;
switch (h4->rx_state) {
case H4_W4_DATA:
BT_DBG("Complete data");
hci_recv_frame(h4->rx_skb);
h4->rx_state = H4_W4_PACKET_TYPE;
h4->rx_skb = NULL;
continue;
case H4_W4_EVENT_HDR:
eh = hci_event_hdr(h4->rx_skb);
BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen);
h4_check_data_len(h4, eh->plen);
continue;
case H4_W4_ACL_HDR:
ah = hci_acl_hdr(h4->rx_skb);
dlen = __le16_to_cpu(ah->dlen);
BT_DBG("ACL header: dlen %d", dlen);
h4_check_data_len(h4, dlen);
continue;
case H4_W4_SCO_HDR:
sh = hci_sco_hdr(h4->rx_skb);
BT_DBG("SCO header: dlen %d", sh->dlen);
h4_check_data_len(h4, sh->dlen);
continue;
}
}
/* H4_W4_PACKET_TYPE */
switch (*ptr) {
case HCI_EVENT_PKT:
BT_DBG("Event packet");
h4->rx_state = H4_W4_EVENT_HDR;
h4->rx_count = HCI_EVENT_HDR_SIZE;
type = HCI_EVENT_PKT;
break;
case HCI_ACLDATA_PKT:
BT_DBG("ACL packet");
h4->rx_state = H4_W4_ACL_HDR;
h4->rx_count = HCI_ACL_HDR_SIZE;
type = HCI_ACLDATA_PKT;
break;
case HCI_SCODATA_PKT:
BT_DBG("SCO packet");
h4->rx_state = H4_W4_SCO_HDR;
h4->rx_count = HCI_SCO_HDR_SIZE;
type = HCI_SCODATA_PKT;
break;
default:
BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr);
hu->hdev->stat.err_rx++;
ptr++; count--;
continue;
};
ptr++; count--;
/* Allocate packet */
h4->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
if (!h4->rx_skb) {
BT_ERR("Can't allocate mem for new packet");
h4->rx_state = H4_W4_PACKET_TYPE;
h4->rx_count = 0;
return -ENOMEM;
}
h4->rx_skb->dev = (void *) hu->hdev;
bt_cb(h4->rx_skb)->pkt_type = type;
}
if (hci_recv_stream_fragment(hu->hdev, data, count) < 0)
BT_ERR("Frame Reassembly Failed");
return count;
}
......@@ -272,7 +173,7 @@ static struct hci_uart_proto h4p = {
.flush = h4_flush,
};
int h4_init(void)
int __init h4_init(void)
{
int err = hci_uart_register_proto(&h4p);
......@@ -284,7 +185,7 @@ int h4_init(void)
return err;
}
int h4_deinit(void)
int __exit h4_deinit(void)
{
return hci_uart_unregister_proto(&h4p);
}
......@@ -210,7 +210,6 @@ static int hci_uart_close(struct hci_dev *hdev)
static int hci_uart_send_frame(struct sk_buff *skb)
{
struct hci_dev* hdev = (struct hci_dev *) skb->dev;
struct tty_struct *tty;
struct hci_uart *hu;
if (!hdev) {
......@@ -222,7 +221,6 @@ static int hci_uart_send_frame(struct sk_buff *skb)
return -EBUSY;
hu = (struct hci_uart *) hdev->driver_data;
tty = hu->tty;
BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);
......@@ -397,6 +395,9 @@ static int hci_uart_register_dev(struct hci_uart *hu)
if (!reset)
set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags))
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device");
hci_free_dev(hdev);
......@@ -477,6 +478,15 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
return hu->hdev->id;
return -EUNATCH;
case HCIUARTSETFLAGS:
if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
return -EBUSY;
hu->hdev_flags = arg;
break;
case HCIUARTGETFLAGS:
return hu->hdev_flags;
default:
err = n_tty_ioctl_helper(tty, file, cmd, arg);
break;
......@@ -542,6 +552,9 @@ static int __init hci_uart_init(void)
#ifdef CONFIG_BT_HCIUART_LL
ll_init();
#endif
#ifdef CONFIG_BT_HCIUART_ATH3K
ath_init();
#endif
return 0;
}
......@@ -559,6 +572,9 @@ static void __exit hci_uart_exit(void)
#ifdef CONFIG_BT_HCIUART_LL
ll_deinit();
#endif
#ifdef CONFIG_BT_HCIUART_ATH3K
ath_deinit();
#endif
/* Release tty registration of line discipline */
if ((err = tty_unregister_ldisc(N_HCI)))
......
......@@ -74,7 +74,7 @@ enum hcill_states_e {
struct hcill_cmd {
u8 cmd;
} __attribute__((packed));
} __packed;
struct ll_struct {
unsigned long rx_state;
......@@ -517,7 +517,7 @@ static struct hci_uart_proto llp = {
.flush = ll_flush,
};
int ll_init(void)
int __init ll_init(void)
{
int err = hci_uart_register_proto(&llp);
......@@ -529,7 +529,7 @@ int ll_init(void)
return err;
}
int ll_deinit(void)
int __exit ll_deinit(void)
{
return hci_uart_unregister_proto(&llp);
}
......@@ -31,15 +31,20 @@
#define HCIUARTSETPROTO _IOW('U', 200, int)
#define HCIUARTGETPROTO _IOR('U', 201, int)
#define HCIUARTGETDEVICE _IOR('U', 202, int)
#define HCIUARTSETFLAGS _IOW('U', 203, int)
#define HCIUARTGETFLAGS _IOR('U', 204, int)
/* UART protocols */
#define HCI_UART_MAX_PROTO 5
#define HCI_UART_MAX_PROTO 6
#define HCI_UART_H4 0
#define HCI_UART_BCSP 1
#define HCI_UART_3WIRE 2
#define HCI_UART_H4DS 3
#define HCI_UART_LL 4
#define HCI_UART_ATH3K 5
#define HCI_UART_RAW_DEVICE 0
struct hci_uart;
......@@ -57,6 +62,7 @@ struct hci_uart {
struct tty_struct *tty;
struct hci_dev *hdev;
unsigned long flags;
unsigned long hdev_flags;
struct hci_uart_proto *proto;
void *priv;
......@@ -66,7 +72,7 @@ struct hci_uart {
spinlock_t rx_lock;
};
/* HCI_UART flag bits */
/* HCI_UART proto flag bits */
#define HCI_UART_PROTO_SET 0
/* TX states */
......@@ -91,3 +97,8 @@ int bcsp_deinit(void);
int ll_init(void);
int ll_deinit(void);
#endif
#ifdef CONFIG_BT_HCIUART_ATH3K
int ath_init(void);
int ath_deinit(void);
#endif
......@@ -215,7 +215,7 @@ static int addr4_resolve(struct sockaddr_in *src_in,
neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->idev->dev);
if (!neigh || !(neigh->nud_state & NUD_VALID)) {
neigh_event_send(rt->u.dst.neighbour, NULL);
neigh_event_send(rt->dst.neighbour, NULL);
ret = -ENODATA;
if (neigh)
goto release;
......
......@@ -1364,7 +1364,7 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
__func__);
goto reject;
}
dst = &rt->u.dst;
dst = &rt->dst;
l2t = t3_l2t_get(tdev, dst->neighbour, dst->neighbour->dev);
if (!l2t) {
printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
......@@ -1932,7 +1932,7 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
err = -EHOSTUNREACH;
goto fail3;
}
ep->dst = &rt->u.dst;
ep->dst = &rt->dst;
/* get a l2t entry */
ep->l2t = t3_l2t_get(ep->com.tdev, ep->dst->neighbour,
......
......@@ -1365,7 +1365,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
__func__);
goto reject;
}
dst = &rt->u.dst;
dst = &rt->dst;
if (dst->neighbour->dev->flags & IFF_LOOPBACK) {
pdev = ip_dev_find(&init_net, peer_ip);
BUG_ON(!pdev);
......@@ -1939,7 +1939,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
err = -EHOSTUNREACH;
goto fail3;
}
ep->dst = &rt->u.dst;
ep->dst = &rt->dst;
/* get a l2t entry */
if (ep->dst->neighbour->dev->flags & IFF_LOOPBACK) {
......
......@@ -1146,7 +1146,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
}
if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID)))
neigh_event_send(rt->u.dst.neighbour, NULL);
neigh_event_send(rt->dst.neighbour, NULL);
ip_rt_put(rt);
return rc;
......
......@@ -1567,6 +1567,12 @@ static int nes_netdev_set_settings(struct net_device *netdev, struct ethtool_cmd
}
static int nes_netdev_set_flags(struct net_device *netdev, u32 flags)
{
return ethtool_op_set_flags(netdev, flags, ETH_FLAG_LRO);
}
static const struct ethtool_ops nes_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_settings = nes_netdev_get_settings,
......@@ -1588,7 +1594,7 @@ static const struct ethtool_ops nes_ethtool_ops = {
.get_tso = ethtool_op_get_tso,
.set_tso = ethtool_op_set_tso,
.get_flags = ethtool_op_get_flags,
.set_flags = ethtool_op_set_flags,
.set_flags = nes_netdev_set_flags,
};
......
......@@ -147,6 +147,11 @@ static void ipoib_get_ethtool_stats(struct net_device *dev,
data[index++] = priv->lro.lro_mgr.stats.no_desc;
}
static int ipoib_set_flags(struct net_device *dev, u32 flags)
{
return ethtool_op_set_flags(dev, flags, ETH_FLAG_LRO);
}
static const struct ethtool_ops ipoib_ethtool_ops = {
.get_drvinfo = ipoib_get_drvinfo,
.get_rx_csum = ipoib_get_rx_csum,
......@@ -154,7 +159,7 @@ static const struct ethtool_ops ipoib_ethtool_ops = {
.get_coalesce = ipoib_get_coalesce,
.set_coalesce = ipoib_set_coalesce,
.get_flags = ethtool_op_get_flags,
.set_flags = ethtool_op_set_flags,
.set_flags = ipoib_set_flags,
.get_strings = ipoib_get_strings,
.get_sset_count = ipoib_get_sset_count,
.get_ethtool_stats = ipoib_get_ethtool_stats,
......
......@@ -20,7 +20,6 @@
#include <linux/signal.h>
#include <linux/mutex.h>
#include <linux/mm.h>
#include <linux/smp_lock.h>
#include <linux/timer.h>
#include <linux/wait.h>
#include <linux/tty.h>
......@@ -50,6 +49,7 @@ MODULE_LICENSE("GPL");
/* -------- driver information -------------------------------------- */
static DEFINE_MUTEX(capi_mutex);
static struct class *capi_class;
static int capi_major = 68; /* allocated */
......@@ -691,7 +691,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
static ssize_t
capi_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
struct capidev *cdev = (struct capidev *)file->private_data;
struct capidev *cdev = file->private_data;
struct sk_buff *skb;
size_t copied;
int err;
......@@ -726,7 +726,7 @@ capi_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
static ssize_t
capi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
struct capidev *cdev = (struct capidev *)file->private_data;
struct capidev *cdev = file->private_data;
struct sk_buff *skb;
u16 mlen;
......@@ -773,7 +773,7 @@ capi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos
static unsigned int
capi_poll(struct file *file, poll_table * wait)
{
struct capidev *cdev = (struct capidev *)file->private_data;
struct capidev *cdev = file->private_data;
unsigned int mask = 0;
if (!cdev->ap.applid)
......@@ -985,9 +985,9 @@ capi_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int ret;
lock_kernel();
mutex_lock(&capi_mutex);
ret = capi_ioctl(file, cmd, arg);
unlock_kernel();
mutex_unlock(&capi_mutex);
return ret;
}
......
......@@ -1450,12 +1450,9 @@ static void handle_dtrace_data(capidrv_contr *card,
}
for (p = data, end = data+len; p < end; p++) {
u8 w;
PUTBYTE_TO_STATUS(card, ' ');
w = (*p >> 4) & 0xf;
PUTBYTE_TO_STATUS(card, (w < 10) ? '0'+w : 'A'-10+w);
w = *p & 0xf;
PUTBYTE_TO_STATUS(card, (w < 10) ? '0'+w : 'A'-10+w);
PUTBYTE_TO_STATUS(card, hex_asc_hi(*p));
PUTBYTE_TO_STATUS(card, hex_asc_lo(*p));
}
PUTBYTE_TO_STATUS(card, '\n');
......
......@@ -20,7 +20,7 @@
#include <linux/sched.h>
#include <linux/isdnif.h>
#include <net/net_namespace.h>
#include <linux/smp_lock.h>
#include <linux/mutex.h>
#include "isdn_divert.h"
......@@ -28,6 +28,7 @@
/* Variables for interface queue */
/*********************************/
ulong if_used = 0; /* number of interface users */
static DEFINE_MUTEX(isdn_divert_mutex);
static struct divert_info *divert_info_head = NULL; /* head of queue */
static struct divert_info *divert_info_tail = NULL; /* pointer to last entry */
static DEFINE_SPINLOCK(divert_info_lock);/* lock for queue */
......@@ -261,9 +262,9 @@ static long isdn_divert_ioctl(struct file *file, uint cmd, ulong arg)
{
long ret;
lock_kernel();
mutex_lock(&isdn_divert_mutex);
ret = isdn_divert_ioctl_unlocked(file, cmd, arg);
unlock_kernel();
mutex_unlock(&isdn_divert_mutex);
return ret;
}
......
......@@ -17,8 +17,7 @@ menuconfig ISDN_DRV_GIGASET
if ISDN_DRV_GIGASET
config GIGASET_CAPI
bool "Gigaset CAPI support (EXPERIMENTAL)"
depends on EXPERIMENTAL
bool "Gigaset CAPI support"
depends on ISDN_CAPI='y'||(ISDN_CAPI='m'&&ISDN_DRV_GIGASET='m')
default ISDN_I4L='n'
help
......@@ -27,6 +26,7 @@ config GIGASET_CAPI
subsystem you'll have to enable the capidrv glue driver.
(select ISDN_CAPI_CAPIDRV.)
Say N to build the old native ISDN4Linux variant.
If unsure, say Y.
config GIGASET_I4L
bool
......
......@@ -1188,24 +1188,6 @@ static void write_iso_tasklet(unsigned long data)
break;
}
}
#ifdef CONFIG_GIGASET_DEBUG
/* check assumption on remaining frames */
for (; i < BAS_NUMFRAMES; i++) {
ifd = &urb->iso_frame_desc[i];
if (ifd->status != -EINPROGRESS
|| ifd->actual_length != 0) {
dev_warn(cs->dev,
"isochronous write: frame %d: %s, "
"%d of %d bytes sent\n",
i, get_usb_statmsg(ifd->status),
ifd->actual_length, ifd->length);
offset = (ifd->offset +
ifd->actual_length)
% BAS_OUTBUFSIZE;
break;
}
}
#endif
break;
case -EPIPE: /* stall - probably underrun */
dev_err(cs->dev, "isochronous write stalled\n");
......@@ -1913,65 +1895,41 @@ static int start_cbsend(struct cardstate *cs)
* USB transmission is started if necessary.
* parameters:
* cs controller state structure
* buf command string to send
* len number of bytes to send (max. IF_WRITEBUF)
* wake_tasklet tasklet to run when transmission is completed
* (NULL if none)
* cb command buffer structure
* return value:
* number of bytes queued on success
* error code < 0 on error
*/
static int gigaset_write_cmd(struct cardstate *cs,
const unsigned char *buf, int len,
struct tasklet_struct *wake_tasklet)
static int gigaset_write_cmd(struct cardstate *cs, struct cmdbuf_t *cb)
{
struct cmdbuf_t *cb;
unsigned long flags;
int rc;
gigaset_dbg_buffer(cs->mstate != MS_LOCKED ?
DEBUG_TRANSCMD : DEBUG_LOCKCMD,
"CMD Transmit", len, buf);
if (len <= 0) {
/* nothing to do */
rc = 0;
goto notqueued;
}
"CMD Transmit", cb->len, cb->buf);
/* translate "+++" escape sequence sent as a single separate command
* into "close AT channel" command for error recovery
* The next command will reopen the AT channel automatically.
*/
if (len == 3 && !memcmp(buf, "+++", 3)) {
if (cb->len == 3 && !memcmp(cb->buf, "+++", 3)) {
kfree(cb);
rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT);
goto notqueued;
if (cb->wake_tasklet)
tasklet_schedule(cb->wake_tasklet);
return rc < 0 ? rc : cb->len;
}
if (len > IF_WRITEBUF)
len = IF_WRITEBUF;
cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC);
if (!cb) {
dev_err(cs->dev, "%s: out of memory\n", __func__);
rc = -ENOMEM;
goto notqueued;
}
memcpy(cb->buf, buf, len);
cb->len = len;
cb->offset = 0;
cb->next = NULL;
cb->wake_tasklet = wake_tasklet;
spin_lock_irqsave(&cs->cmdlock, flags);
cb->prev = cs->lastcmdbuf;
if (cs->lastcmdbuf)
cs->lastcmdbuf->next = cb;
else {
cs->cmdbuf = cb;
cs->curlen = len;
cs->curlen = cb->len;
}
cs->cmdbytes += len;
cs->cmdbytes += cb->len;
cs->lastcmdbuf = cb;
spin_unlock_irqrestore(&cs->cmdlock, flags);
......@@ -1988,12 +1946,7 @@ static int gigaset_write_cmd(struct cardstate *cs,
}
rc = start_cbsend(cs);
spin_unlock_irqrestore(&cs->lock, flags);
return rc < 0 ? rc : len;
notqueued: /* request handled without queuing */
if (wake_tasklet)
tasklet_schedule(wake_tasklet);
return rc;
return rc < 0 ? rc : cb->len;
}
/* gigaset_write_room
......
......@@ -45,6 +45,7 @@
#define CAPI_FACILITY_LI 0x0005
#define CAPI_SUPPSVC_GETSUPPORTED 0x0000
#define CAPI_SUPPSVC_LISTEN 0x0001
/* missing from capiutil.h */
#define CAPIMSG_PLCI_PART(m) CAPIMSG_U8(m, 9)
......@@ -270,9 +271,13 @@ static inline void dump_rawmsg(enum debuglevel level, const char *tag,
kfree(dbgline);
if (CAPIMSG_COMMAND(data) == CAPI_DATA_B3 &&
(CAPIMSG_SUBCOMMAND(data) == CAPI_REQ ||
CAPIMSG_SUBCOMMAND(data) == CAPI_IND) &&
CAPIMSG_DATALEN(data) > 0) {
CAPIMSG_SUBCOMMAND(data) == CAPI_IND)) {
l = CAPIMSG_DATALEN(data);
gig_dbg(level, " DataLength=%d", l);
if (l <= 0 || !(gigaset_debuglevel & DEBUG_LLDATA))
return;
if (l > 64)
l = 64; /* arbitrary limit */
dbgline = kmalloc(3*l, GFP_ATOMIC);
if (!dbgline)
return;
......@@ -378,13 +383,13 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb)
++bcs->trans_up;
if (!ap) {
dev_err(cs->dev, "%s: no application\n", __func__);
gig_dbg(DEBUG_MCMD, "%s: application gone", __func__);
return;
}
/* don't send further B3 messages if disconnected */
if (bcs->apconnstate < APCONN_ACTIVE) {
gig_dbg(DEBUG_LLDATA, "disconnected, discarding ack");
gig_dbg(DEBUG_MCMD, "%s: disconnected", __func__);
return;
}
......@@ -422,13 +427,14 @@ void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb)
bcs->trans_down++;
if (!ap) {
dev_err(cs->dev, "%s: no application\n", __func__);
gig_dbg(DEBUG_MCMD, "%s: application gone", __func__);
dev_kfree_skb_any(skb);
return;
}
/* don't send further B3 messages if disconnected */
if (bcs->apconnstate < APCONN_ACTIVE) {
gig_dbg(DEBUG_LLDATA, "disconnected, discarding data");
gig_dbg(DEBUG_MCMD, "%s: disconnected", __func__);
dev_kfree_skb_any(skb);
return;
}
......@@ -454,7 +460,7 @@ void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb)
/* Data64 parameter not present */
/* emit message */
dump_rawmsg(DEBUG_LLDATA, "DATA_B3_IND", skb->data);
dump_rawmsg(DEBUG_MCMD, __func__, skb->data);
capi_ctr_handle_message(&iif->ctr, ap->id, skb);
}
EXPORT_SYMBOL_GPL(gigaset_skb_rcvd);
......@@ -747,7 +753,7 @@ void gigaset_isdn_connD(struct bc_state *bcs)
ap = bcs->ap;
if (!ap) {
spin_unlock_irqrestore(&bcs->aplock, flags);
dev_err(cs->dev, "%s: no application\n", __func__);
gig_dbg(DEBUG_CMD, "%s: application gone", __func__);
return;
}
if (bcs->apconnstate == APCONN_NONE) {
......@@ -843,7 +849,7 @@ void gigaset_isdn_connB(struct bc_state *bcs)
ap = bcs->ap;
if (!ap) {
spin_unlock_irqrestore(&bcs->aplock, flags);
dev_err(cs->dev, "%s: no application\n", __func__);
gig_dbg(DEBUG_CMD, "%s: application gone", __func__);
return;
}
if (!bcs->apconnstate) {
......@@ -901,13 +907,12 @@ void gigaset_isdn_connB(struct bc_state *bcs)
*/
void gigaset_isdn_hupB(struct bc_state *bcs)
{
struct cardstate *cs = bcs->cs;
struct gigaset_capi_appl *ap = bcs->ap;
/* ToDo: assure order of DISCONNECT_B3_IND and DISCONNECT_IND ? */
if (!ap) {
dev_err(cs->dev, "%s: no application\n", __func__);
gig_dbg(DEBUG_CMD, "%s: application gone", __func__);
return;
}
......@@ -978,6 +983,9 @@ static void gigaset_register_appl(struct capi_ctr *ctr, u16 appl,
struct cardstate *cs = ctr->driverdata;
struct gigaset_capi_appl *ap;
gig_dbg(DEBUG_CMD, "%s [%u] l3cnt=%u blkcnt=%u blklen=%u",
__func__, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen);
list_for_each_entry(ap, &iif->appls, ctrlist)
if (ap->id == appl) {
dev_notice(cs->dev,
......@@ -1062,6 +1070,8 @@ static void gigaset_release_appl(struct capi_ctr *ctr, u16 appl)
struct gigaset_capi_appl *ap, *tmp;
unsigned ch;
gig_dbg(DEBUG_CMD, "%s [%u]", __func__, appl);
list_for_each_entry_safe(ap, tmp, &iif->appls, ctrlist)
if (ap->id == appl) {
/* remove from any channels */
......@@ -1142,7 +1152,7 @@ static void do_facility_req(struct gigaset_capi_ctr *iif,
case CAPI_FACILITY_SUPPSVC:
/* decode Function parameter */
pparam = cmsg->FacilityRequestParameter;
if (pparam == NULL || *pparam < 2) {
if (pparam == NULL || pparam[0] < 2) {
dev_notice(cs->dev, "%s: %s missing\n", "FACILITY_REQ",
"Facility Request Parameter");
send_conf(iif, ap, skb, CapiIllMessageParmCoding);
......@@ -1159,8 +1169,32 @@ static void do_facility_req(struct gigaset_capi_ctr *iif,
/* Supported Services: none */
capimsg_setu32(confparam, 6, 0);
break;
case CAPI_SUPPSVC_LISTEN:
if (pparam[0] < 7 || pparam[3] < 4) {
dev_notice(cs->dev, "%s: %s missing\n",
"FACILITY_REQ", "Notification Mask");
send_conf(iif, ap, skb,
CapiIllMessageParmCoding);
return;
}
if (CAPIMSG_U32(pparam, 4) != 0) {
dev_notice(cs->dev,
"%s: unsupported supplementary service notification mask 0x%x\n",
"FACILITY_REQ", CAPIMSG_U32(pparam, 4));
info = CapiFacilitySpecificFunctionNotSupported;
confparam[3] = 2; /* length */
capimsg_setu16(confparam, 4,
CapiSupplementaryServiceNotSupported);
}
info = CapiSuccess;
confparam[3] = 2; /* length */
capimsg_setu16(confparam, 4, CapiSuccess);
break;
/* ToDo: add supported services */
default:
dev_notice(cs->dev,
"%s: unsupported supplementary service function 0x%04x\n",
"FACILITY_REQ", function);
info = CapiFacilitySpecificFunctionNotSupported;
/* Supplementary Service specific parameter */
confparam[3] = 2; /* length */
......@@ -1951,11 +1985,7 @@ static void do_data_b3_req(struct gigaset_capi_ctr *iif,
u16 handle = CAPIMSG_HANDLE_REQ(skb->data);
/* frequent message, avoid _cmsg overhead */
dump_rawmsg(DEBUG_LLDATA, "DATA_B3_REQ", skb->data);
gig_dbg(DEBUG_LLDATA,
"Receiving data from LL (ch: %d, flg: %x, sz: %d|%d)",
channel, flags, msglen, datalen);
dump_rawmsg(DEBUG_MCMD, __func__, skb->data);
/* check parameters */
if (channel == 0 || channel > cs->channels || ncci != 1) {
......@@ -2064,7 +2094,7 @@ static void do_data_b3_resp(struct gigaset_capi_ctr *iif,
struct gigaset_capi_appl *ap,
struct sk_buff *skb)
{
dump_rawmsg(DEBUG_LLDATA, __func__, skb->data);
dump_rawmsg(DEBUG_MCMD, __func__, skb->data);
dev_kfree_skb_any(skb);
}
......
......@@ -791,8 +791,6 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
spin_unlock_irqrestore(&cs->lock, flags);
setup_timer(&cs->timer, timer_tick, (unsigned long) cs);
cs->timer.expires = jiffies + msecs_to_jiffies(GIG_TICK);
/* FIXME: can jiffies increase too much until the timer is added?
* Same problem(?) with mod_timer() in timer_tick(). */
add_timer(&cs->timer);
gig_dbg(DEBUG_INIT, "cs initialized");
......
......@@ -35,53 +35,40 @@
#define RT_RING 2
#define RT_NUMBER 3
#define RT_STRING 4
#define RT_HEX 5
#define RT_ZCAU 6
/* Possible ASCII responses */
#define RSP_OK 0
#define RSP_BUSY 1
#define RSP_CONNECT 2
#define RSP_ERROR 1
#define RSP_ZGCI 3
#define RSP_RING 4
#define RSP_ZAOC 5
#define RSP_ZCSTR 6
#define RSP_ZCFGT 7
#define RSP_ZCFG 8
#define RSP_ZCCR 9
#define RSP_EMPTY 10
#define RSP_ZLOG 11
#define RSP_ZCAU 12
#define RSP_ZMWI 13
#define RSP_ZABINFO 14
#define RSP_ZSMLSTCHG 15
#define RSP_ZVLS 5
#define RSP_ZCAU 6
/* responses with values to store in at_state */
/* - numeric */
#define RSP_VAR 100
#define RSP_ZSAU (RSP_VAR + VAR_ZSAU)
#define RSP_ZDLE (RSP_VAR + VAR_ZDLE)
#define RSP_ZVLS (RSP_VAR + VAR_ZVLS)
#define RSP_ZCTP (RSP_VAR + VAR_ZCTP)
/* - string */
#define RSP_STR (RSP_VAR + VAR_NUM)
#define RSP_NMBR (RSP_STR + STR_NMBR)
#define RSP_ZCPN (RSP_STR + STR_ZCPN)
#define RSP_ZCON (RSP_STR + STR_ZCON)
#define RSP_ZBC (RSP_STR + STR_ZBC)
#define RSP_ZHLC (RSP_STR + STR_ZHLC)
#define RSP_ERROR -1 /* ERROR */
#define RSP_WRONG_CID -2 /* unknown cid in cmd */
#define RSP_UNKNOWN -4 /* unknown response */
#define RSP_FAIL -5 /* internal error */
#define RSP_INVAL -6 /* invalid response */
#define RSP_NODEV -9 /* device not connected */
#define RSP_NONE -19
#define RSP_STRING -20
#define RSP_NULL -21
#define RSP_RETRYFAIL -22
#define RSP_RETRY -23
#define RSP_SKIP -24
#define RSP_INIT -27
#define RSP_ANY -26
#define RSP_LAST -28
#define RSP_NODEV -9
/* actions for process_response */
#define ACT_NOTHING 0
......@@ -259,13 +246,6 @@ struct reply_t gigaset_tab_nocid[] =
/* misc. */
{RSP_ERROR, -1, -1, -1, -1, -1, {ACT_ERROR} },
{RSP_ZCFGT, -1, -1, -1, -1, -1, {ACT_DEBUG} },
{RSP_ZCFG, -1, -1, -1, -1, -1, {ACT_DEBUG} },
{RSP_ZLOG, -1, -1, -1, -1, -1, {ACT_DEBUG} },
{RSP_ZMWI, -1, -1, -1, -1, -1, {ACT_DEBUG} },
{RSP_ZABINFO, -1, -1, -1, -1, -1, {ACT_DEBUG} },
{RSP_ZSMLSTCHG, -1, -1, -1, -1, -1, {ACT_DEBUG} },
{RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} },
{RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} },
{RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} },
......@@ -361,10 +341,6 @@ struct reply_t gigaset_tab_cid[] =
/* misc. */
{RSP_ZCON, -1, -1, -1, -1, -1, {ACT_DEBUG} },
{RSP_ZCCR, -1, -1, -1, -1, -1, {ACT_DEBUG} },
{RSP_ZAOC, -1, -1, -1, -1, -1, {ACT_DEBUG} },
{RSP_ZCSTR, -1, -1, -1, -1, -1, {ACT_DEBUG} },
{RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} },
{RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} },
{RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} },
......@@ -387,20 +363,11 @@ static const struct resp_type_t {
{"ZVLS", RSP_ZVLS, RT_NUMBER},
{"ZCTP", RSP_ZCTP, RT_NUMBER},
{"ZDLE", RSP_ZDLE, RT_NUMBER},
{"ZCFGT", RSP_ZCFGT, RT_NUMBER},
{"ZCCR", RSP_ZCCR, RT_NUMBER},
{"ZMWI", RSP_ZMWI, RT_NUMBER},
{"ZHLC", RSP_ZHLC, RT_STRING},
{"ZBC", RSP_ZBC, RT_STRING},
{"NMBR", RSP_NMBR, RT_STRING},
{"ZCPN", RSP_ZCPN, RT_STRING},
{"ZCON", RSP_ZCON, RT_STRING},
{"ZAOC", RSP_ZAOC, RT_STRING},
{"ZCSTR", RSP_ZCSTR, RT_STRING},
{"ZCFG", RSP_ZCFG, RT_HEX},
{"ZLOG", RSP_ZLOG, RT_NOTHING},
{"ZABINFO", RSP_ZABINFO, RT_NOTHING},
{"ZSMLSTCHG", RSP_ZSMLSTCHG, RT_NOTHING},
{NULL, 0, 0}
};
......@@ -418,64 +385,18 @@ static const struct zsau_resp_t {
{NULL, ZSAU_UNKNOWN}
};
/*
* Get integer from char-pointer
*/
static int isdn_getnum(char *p)
{
int v = -1;
gig_dbg(DEBUG_EVENT, "string: %s", p);
while (*p >= '0' && *p <= '9')
v = ((v < 0) ? 0 : (v * 10)) + (int) ((*p++) - '0');
if (*p)
v = -1; /* invalid Character */
return v;
}
/*
* Get integer from char-pointer
*/
static int isdn_gethex(char *p)
{
int v = 0;
int c;
gig_dbg(DEBUG_EVENT, "string: %s", p);
if (!*p)
return -1;
do {
if (v > (INT_MAX - 15) / 16)
return -1;
c = *p;
if (c >= '0' && c <= '9')
c -= '0';
else if (c >= 'a' && c <= 'f')
c -= 'a' - 10;
else if (c >= 'A' && c <= 'F')
c -= 'A' - 10;
else
return -1;
v = v * 16 + c;
} while (*++p);
return v;
}
/* retrieve CID from parsed response
* returns 0 if no CID, -1 if invalid CID, or CID value 1..65535
*/
static int cid_of_response(char *s)
{
int cid;
unsigned long cid;
int rc;
if (s[-1] != ';')
return 0; /* no CID separator */
cid = isdn_getnum(s);
if (cid < 0)
rc = strict_strtoul(s, 10, &cid);
if (rc)
return 0; /* CID not numeric */
if (cid < 1 || cid > 65535)
return -1; /* CID out of range */
......@@ -588,10 +509,10 @@ void gigaset_handle_modem_response(struct cardstate *cs)
break;
if (!rt->response) {
event->type = RSP_UNKNOWN;
dev_warn(cs->dev,
"unknown modem response: %s\n",
argv[curarg]);
event->type = RSP_NONE;
gig_dbg(DEBUG_EVENT,
"unknown modem response: '%s'\n",
argv[curarg]);
break;
}
......@@ -645,27 +566,27 @@ void gigaset_handle_modem_response(struct cardstate *cs)
case RT_ZCAU:
event->parameter = -1;
if (curarg + 1 < params) {
i = isdn_gethex(argv[curarg]);
j = isdn_gethex(argv[curarg + 1]);
if (i >= 0 && i < 256 && j >= 0 && j < 256)
event->parameter = (unsigned) i << 8
| j;
curarg += 2;
unsigned long type, value;
i = strict_strtoul(argv[curarg++], 16, &type);
j = strict_strtoul(argv[curarg++], 16, &value);
if (i == 0 && type < 256 &&
j == 0 && value < 256)
event->parameter = (type << 8) | value;
} else
curarg = params - 1;
break;
case RT_NUMBER:
case RT_HEX:
event->parameter = -1;
if (curarg < params) {
if (param_type == RT_HEX)
event->parameter =
isdn_gethex(argv[curarg]);
else
event->parameter =
isdn_getnum(argv[curarg]);
++curarg;
} else
event->parameter = -1;
unsigned long res;
int rc;
rc = strict_strtoul(argv[curarg++], 10, &res);
if (rc == 0)
event->parameter = res;
}
gig_dbg(DEBUG_EVENT, "parameter==%d", event->parameter);
break;
}
......@@ -797,48 +718,27 @@ static void schedule_init(struct cardstate *cs, int state)
static void send_command(struct cardstate *cs, const char *cmd, int cid,
int dle, gfp_t kmallocflags)
{
size_t cmdlen, buflen;
char *cmdpos, *cmdbuf, *cmdtail;
struct cmdbuf_t *cb;
size_t buflen;
cmdlen = strlen(cmd);
buflen = 11 + cmdlen;
if (unlikely(buflen <= cmdlen)) {
dev_err(cs->dev, "integer overflow in buflen\n");
buflen = strlen(cmd) + 12; /* DLE ( A T 1 2 3 4 5 <cmd> DLE ) \0 */
cb = kmalloc(sizeof(struct cmdbuf_t) + buflen, kmallocflags);
if (!cb) {
dev_err(cs->dev, "%s: out of memory\n", __func__);
return;
}
cmdbuf = kmalloc(buflen, kmallocflags);
if (unlikely(!cmdbuf)) {
dev_err(cs->dev, "out of memory\n");
return;
}
cmdpos = cmdbuf + 9;
cmdtail = cmdpos + cmdlen;
memcpy(cmdpos, cmd, cmdlen);
if (cid > 0 && cid <= 65535) {
do {
*--cmdpos = '0' + cid % 10;
cid /= 10;
++cmdlen;
} while (cid);
}
cmdlen += 2;
*--cmdpos = 'T';
*--cmdpos = 'A';
if (dle) {
cmdlen += 4;
*--cmdpos = '(';
*--cmdpos = 0x10;
*cmdtail++ = 0x10;
*cmdtail++ = ')';
}
cs->ops->write_cmd(cs, cmdpos, cmdlen, NULL);
kfree(cmdbuf);
if (cid > 0 && cid <= 65535)
cb->len = snprintf(cb->buf, buflen,
dle ? "\020(AT%d%s\020)" : "AT%d%s",
cid, cmd);
else
cb->len = snprintf(cb->buf, buflen,
dle ? "\020(AT%s\020)" : "AT%s",
cmd);
cb->offset = 0;
cb->next = NULL;
cb->wake_tasklet = NULL;
cs->ops->write_cmd(cs, cb);
}
static struct at_state_t *at_state_from_cid(struct cardstate *cs, int cid)
......@@ -1240,8 +1140,22 @@ static void do_action(int action, struct cardstate *cs,
break;
case ACT_HUPMODEM:
/* send "+++" (hangup in unimodem mode) */
if (cs->connected)
cs->ops->write_cmd(cs, "+++", 3, NULL);
if (cs->connected) {
struct cmdbuf_t *cb;
cb = kmalloc(sizeof(struct cmdbuf_t) + 3, GFP_ATOMIC);
if (!cb) {
dev_err(cs->dev, "%s: out of memory\n",
__func__);
return;
}
memcpy(cb->buf, "+++", 3);
cb->len = 3;
cb->offset = 0;
cb->next = NULL;
cb->wake_tasklet = NULL;
cs->ops->write_cmd(cs, cb);
}
break;
case ACT_RING:
/* get fresh AT state structure for new CID */
......@@ -1855,19 +1769,13 @@ static void process_command_flags(struct cardstate *cs)
gig_dbg(DEBUG_EVENT, "Scheduling PC_CIDMODE");
cs->commands_pending = 1;
return;
#ifdef GIG_MAYINITONDIAL
case M_UNKNOWN:
schedule_init(cs, MS_INIT);
return;
#endif
}
bcs->at_state.pending_commands &= ~PC_CID;
cs->curchannel = bcs->channel;
#ifdef GIG_RETRYCID
cs->retry_count = 2;
#else
cs->retry_count = 1;
#endif
schedule_sequence(cs, &cs->at_state, SEQ_CID);
return;
}
......
......@@ -46,13 +46,6 @@
#define RBUFSIZE 8192
/* compile time options */
#define GIG_MAJOR 0
#define GIG_MAYINITONDIAL
#define GIG_RETRYCID
#define GIG_X75
#define GIG_TICK 100 /* in milliseconds */
/* timeout values (unit: 1 sec) */
......@@ -193,9 +186,8 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
/* variables in struct at_state_t */
#define VAR_ZSAU 0
#define VAR_ZDLE 1
#define VAR_ZVLS 2
#define VAR_ZCTP 3
#define VAR_NUM 4
#define VAR_ZCTP 2
#define VAR_NUM 3
#define STR_NMBR 0
#define STR_ZCPN 1
......@@ -574,9 +566,7 @@ struct bas_bc_state {
struct gigaset_ops {
/* Called from ev-layer.c/interface.c for sending AT commands to the
device */
int (*write_cmd)(struct cardstate *cs,
const unsigned char *buf, int len,
struct tasklet_struct *wake_tasklet);
int (*write_cmd)(struct cardstate *cs, struct cmdbuf_t *cb);
/* Called from interface.c for additional device control */
int (*write_room)(struct cardstate *cs);
......
......@@ -419,6 +419,8 @@ static int command_from_LL(isdn_ctrl *cntrl)
dev_err(bcs->cs->dev, "out of memory\n");
for (i = 0; i < AT_NUM; ++i)
kfree(commands[i]);
kfree(commands);
gigaset_free_channel(bcs);
return -ENOMEM;
}
......@@ -643,9 +645,7 @@ int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
iif->maxbufsize = MAX_BUF_SIZE;
iif->features = ISDN_FEATURE_L2_TRANS |
ISDN_FEATURE_L2_HDLC |
#ifdef GIG_X75
ISDN_FEATURE_L2_X75I |
#endif
ISDN_FEATURE_L3_TRANS |
ISDN_FEATURE_P_EURO;
iif->hl_hdrlen = HW_HDR_LEN; /* Area for storing ack */
......
......@@ -339,7 +339,8 @@ static int if_tiocmset(struct tty_struct *tty, struct file *file,
static int if_write(struct tty_struct *tty, const unsigned char *buf, int count)
{
struct cardstate *cs;
int retval = -ENODEV;
struct cmdbuf_t *cb;
int retval;
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
......@@ -355,18 +356,39 @@ static int if_write(struct tty_struct *tty, const unsigned char *buf, int count)
if (!cs->connected) {
gig_dbg(DEBUG_IF, "not connected");
retval = -ENODEV;
} else if (!cs->open_count)
goto done;
}
if (!cs->open_count) {
dev_warn(cs->dev, "%s: device not opened\n", __func__);
else if (cs->mstate != MS_LOCKED) {
retval = -ENODEV;
goto done;
}
if (cs->mstate != MS_LOCKED) {
dev_warn(cs->dev, "can't write to unlocked device\n");
retval = -EBUSY;
} else {
retval = cs->ops->write_cmd(cs, buf, count,
&cs->if_wake_tasklet);
goto done;
}
if (count <= 0) {
/* nothing to do */
retval = 0;
goto done;
}
mutex_unlock(&cs->mutex);
cb = kmalloc(sizeof(struct cmdbuf_t) + count, GFP_KERNEL);
if (!cb) {
dev_err(cs->dev, "%s: out of memory\n", __func__);
retval = -ENOMEM;
goto done;
}
memcpy(cb->buf, buf, count);
cb->len = count;
cb->offset = 0;
cb->next = NULL;
cb->wake_tasklet = &cs->if_wake_tasklet;
retval = cs->ops->write_cmd(cs, cb);
done:
mutex_unlock(&cs->mutex);
return retval;
}
......@@ -655,7 +677,6 @@ void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname,
goto enomem;
tty->magic = TTY_DRIVER_MAGIC,
tty->major = GIG_MAJOR,
tty->type = TTY_DRIVER_TYPE_SERIAL,
tty->subtype = SERIAL_TYPE_NORMAL,
tty->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
......
......@@ -241,30 +241,13 @@ static void flush_send_queue(struct cardstate *cs)
* return value:
* number of bytes queued, or error code < 0
*/
static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
int len, struct tasklet_struct *wake_tasklet)
static int gigaset_write_cmd(struct cardstate *cs, struct cmdbuf_t *cb)
{
struct cmdbuf_t *cb;
unsigned long flags;
gigaset_dbg_buffer(cs->mstate != MS_LOCKED ?
DEBUG_TRANSCMD : DEBUG_LOCKCMD,
"CMD Transmit", len, buf);
if (len <= 0)
return 0;
cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC);
if (!cb) {
dev_err(cs->dev, "%s: out of memory!\n", __func__);
return -ENOMEM;
}
memcpy(cb->buf, buf, len);
cb->len = len;
cb->offset = 0;
cb->next = NULL;
cb->wake_tasklet = wake_tasklet;
"CMD Transmit", cb->len, cb->buf);
spin_lock_irqsave(&cs->cmdlock, flags);
cb->prev = cs->lastcmdbuf;
......@@ -272,9 +255,9 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
cs->lastcmdbuf->next = cb;
else {
cs->cmdbuf = cb;
cs->curlen = len;
cs->curlen = cb->len;
}
cs->cmdbytes += len;
cs->cmdbytes += cb->len;
cs->lastcmdbuf = cb;
spin_unlock_irqrestore(&cs->cmdlock, flags);
......@@ -282,7 +265,7 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
if (cs->connected)
tasklet_schedule(&cs->write_tasklet);
spin_unlock_irqrestore(&cs->lock, flags);
return len;
return cb->len;
}
/*
......
......@@ -39,7 +39,8 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode");
#define GIGASET_MODULENAME "usb_gigaset"
#define GIGASET_DEVNAME "ttyGU"
#define IF_WRITEBUF 2000 /* arbitrary limit */
/* length limit according to Siemens 3070usb-protokoll.doc ch. 2.1 */
#define IF_WRITEBUF 264
/* Values for the Gigaset M105 Data */
#define USB_M105_VENDOR_ID 0x0681
......@@ -493,29 +494,13 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
}
/* Send command to device. */
static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
int len, struct tasklet_struct *wake_tasklet)
static int gigaset_write_cmd(struct cardstate *cs, struct cmdbuf_t *cb)
{
struct cmdbuf_t *cb;
unsigned long flags;
gigaset_dbg_buffer(cs->mstate != MS_LOCKED ?
DEBUG_TRANSCMD : DEBUG_LOCKCMD,
"CMD Transmit", len, buf);
if (len <= 0)
return 0;
cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC);
if (!cb) {
dev_err(cs->dev, "%s: out of memory\n", __func__);
return -ENOMEM;
}
memcpy(cb->buf, buf, len);
cb->len = len;
cb->offset = 0;
cb->next = NULL;
cb->wake_tasklet = wake_tasklet;
"CMD Transmit", cb->len, cb->buf);
spin_lock_irqsave(&cs->cmdlock, flags);
cb->prev = cs->lastcmdbuf;
......@@ -523,9 +508,9 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
cs->lastcmdbuf->next = cb;
else {
cs->cmdbuf = cb;
cs->curlen = len;
cs->curlen = cb->len;
}
cs->cmdbytes += len;
cs->cmdbytes += cb->len;
cs->lastcmdbuf = cb;
spin_unlock_irqrestore(&cs->cmdlock, flags);
......@@ -533,7 +518,7 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
if (cs->connected)
tasklet_schedule(&cs->write_tasklet);
spin_unlock_irqrestore(&cs->lock, flags);
return len;
return cb->len;
}
static int gigaset_write_room(struct cardstate *cs)
......
......@@ -14,7 +14,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/poll.h>
#include <linux/smp_lock.h>
#include <linux/mutex.h>
#include <asm/uaccess.h>
#include "platform.h"
......@@ -22,6 +22,7 @@
#include "divasync.h"
#include "debug_if.h"
static DEFINE_MUTEX(maint_mutex);
static char *main_revision = "$Revision: 1.32.6.10 $";
static int major;
......@@ -130,7 +131,7 @@ static int maint_open(struct inode *ino, struct file *filep)
{
int ret;
lock_kernel();
mutex_lock(&maint_mutex);
/* only one open is allowed, so we test
it atomically */
if (test_and_set_bit(0, &opened))
......@@ -139,7 +140,7 @@ static int maint_open(struct inode *ino, struct file *filep)
filep->private_data = NULL;
ret = nonseekable_open(ino, filep);
}
unlock_kernel();
mutex_unlock(&maint_mutex);
return ret;
}
......
......@@ -18,7 +18,6 @@
#include <linux/proc_fs.h>
#include <linux/skbuff.h>
#include <linux/seq_file.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include "platform.h"
......@@ -402,7 +401,6 @@ static unsigned int um_idi_poll(struct file *file, poll_table * wait)
static int um_idi_open(struct inode *inode, struct file *file)
{
cycle_kernel_lock();
return (0);
}
......
......@@ -21,7 +21,6 @@
#include <linux/list.h>
#include <linux/poll.h>
#include <linux/kmod.h>
#include <linux/smp_lock.h>
#include "platform.h"
#undef ID_MASK
......@@ -113,41 +112,40 @@ typedef struct _diva_os_thread_dpc {
This table should be sorted by PCI device ID
*/
static struct pci_device_id divas_pci_tbl[] = {
/* Diva Server BRI-2M PCI 0xE010 */
{PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_MAESTRA,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_MAESTRA_PCI},
/* Diva Server 4BRI-8M PCI 0xE012 */
{PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_MAESTRAQ,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_Q_8M_PCI},
/* Diva Server 4BRI-8M 2.0 PCI 0xE013 */
{PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_MAESTRAQ_U,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_Q_8M_V2_PCI},
/* Diva Server PRI-30M PCI 0xE014 */
{PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_MAESTRAP,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_P_30M_PCI},
/* Diva Server PRI 2.0 adapter 0xE015 */
{PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_MAESTRAP_2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_P_30M_V2_PCI},
/* Diva Server Voice 4BRI-8M PCI 0xE016 */
{PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_4BRI_VOIP,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_VOICE_Q_8M_PCI},
/* Diva Server Voice 4BRI-8M 2.0 PCI 0xE017 */
{PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_4BRI_2_VOIP,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI},
/* Diva Server BRI-2M 2.0 PCI 0xE018 */
{PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_BRI2M_2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_B_2M_V2_PCI},
/* Diva Server Voice PRI 2.0 PCI 0xE019 */
{PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_MAESTRAP_2_VOIP,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
CARDTYPE_DIVASRV_VOICE_P_30M_V2_PCI},
/* Diva Server 2FX 0xE01A */
{PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_2F,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_B_2F_PCI},
/* Diva Server Voice BRI-2M 2.0 PCI 0xE01B */
{PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_BRI2M_2_VOIP,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI},
{0,} /* 0 terminated list. */
/* Diva Server BRI-2M PCI 0xE010 */
{ PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_MAESTRA),
CARDTYPE_MAESTRA_PCI },
/* Diva Server 4BRI-8M PCI 0xE012 */
{ PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_MAESTRAQ),
CARDTYPE_DIVASRV_Q_8M_PCI },
/* Diva Server 4BRI-8M 2.0 PCI 0xE013 */
{ PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_MAESTRAQ_U),
CARDTYPE_DIVASRV_Q_8M_V2_PCI },
/* Diva Server PRI-30M PCI 0xE014 */
{ PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_MAESTRAP),
CARDTYPE_DIVASRV_P_30M_PCI },
/* Diva Server PRI 2.0 adapter 0xE015 */
{ PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_MAESTRAP_2),
CARDTYPE_DIVASRV_P_30M_V2_PCI },
/* Diva Server Voice 4BRI-8M PCI 0xE016 */
{ PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_4BRI_VOIP),
CARDTYPE_DIVASRV_VOICE_Q_8M_PCI },
/* Diva Server Voice 4BRI-8M 2.0 PCI 0xE017 */
{ PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_4BRI_2_VOIP),
CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI },
/* Diva Server BRI-2M 2.0 PCI 0xE018 */
{ PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_BRI2M_2),
CARDTYPE_DIVASRV_B_2M_V2_PCI },
/* Diva Server Voice PRI 2.0 PCI 0xE019 */
{ PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_MAESTRAP_2_VOIP),
CARDTYPE_DIVASRV_VOICE_P_30M_V2_PCI },
/* Diva Server 2FX 0xE01A */
{ PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_2F),
CARDTYPE_DIVASRV_B_2F_PCI },
/* Diva Server Voice BRI-2M 2.0 PCI 0xE01B */
{ PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_BRI2M_2_VOIP),
CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI },
{ 0, } /* 0 terminated list. */
};
MODULE_DEVICE_TABLE(pci, divas_pci_tbl);
......@@ -581,7 +579,6 @@ xdi_copy_from_user(void *os_handle, void *dst, const void __user *src, int lengt
*/
static int divas_open(struct inode *inode, struct file *file)
{
cycle_kernel_lock();
return (0);
}
......
......@@ -5354,12 +5354,9 @@ static struct pci_device_id hfmultipci_ids[] __devinitdata = {
{ PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFCE1, PCI_VENDOR_ID_CCD,
PCI_SUBDEVICE_ID_CCD_JHSE1, 0, 0, H(25)}, /* Junghanns E1 */
{ PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_ANY_ID, PCI_ANY_ID,
0, 0, 0},
{ PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_ANY_ID, PCI_ANY_ID,
0, 0, 0},
{ PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFCE1, PCI_ANY_ID, PCI_ANY_ID,
0, 0, 0},
{ PCI_VDEVICE(CCD, PCI_DEVICE_ID_CCD_HFC4S), 0 },
{ PCI_VDEVICE(CCD, PCI_DEVICE_ID_CCD_HFC8S), 0 },
{ PCI_VDEVICE(CCD, PCI_DEVICE_ID_CCD_HFCE1), 0 },
{0, }
};
#undef H
......
此差异已折叠。
......@@ -1152,20 +1152,11 @@ QuickHex(char *txt, u_char * p, int cnt)
{
register int i;
register char *t = txt;
register u_char w;
for (i = 0; i < cnt; i++) {
*t++ = ' ';
w = (p[i] >> 4) & 0x0f;
if (w < 10)
*t++ = '0' + w;
else
*t++ = 'A' - 10 + w;
w = p[i] & 0x0f;
if (w < 10)
*t++ = '0' + w;
else
*t++ = 'A' - 10 + w;
*t++ = hex_asc_hi(p[i]);
*t++ = hex_asc_lo(p[i]);
}
*t++ = 0;
return (t - txt);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
文件已移动
此差异已折叠。
文件已移动
文件已移动
文件已移动
文件已移动
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
新手
引导
客服 返回
顶部