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: (1446 commits) macvlan: fix panic if lowerdev in a bond tg3: Add braces around 5906 workaround. tg3: Fix NETIF_F_LOOPBACK error macvlan: remove one synchronize_rcu() call networking: NET_CLS_ROUTE4 depends on INET irda: Fix error propagation in ircomm_lmp_connect_response() irda: Kill set but unused variable 'bytes' in irlan_check_command_param() irda: Kill set but unused variable 'clen' in ircomm_connect_indication() rxrpc: Fix set but unused variable 'usage' in rxrpc_get_transport() be2net: Kill set but unused variable 'req' in lancer_fw_download() irda: Kill set but unused vars 'saddr' and 'daddr' in irlan_provider_connect_indication() atl1c: atl1c_resume() is only used when CONFIG_PM_SLEEP is defined. rxrpc: Fix set but unused variable 'usage' in rxrpc_get_peer(). rxrpc: Kill set but unused variable 'local' in rxrpc_UDP_error_handler() rxrpc: Kill set but unused variable 'sp' in rxrpc_process_connection() rxrpc: Kill set but unused variable 'sp' in rxrpc_rotate_tx_window() pkt_sched: Kill set but unused variable 'protocol' in tc_classify() isdn: capi: Use pr_debug() instead of ifdefs. tg3: Update version to 3.119 tg3: Apply rx_discards fix to 5719/5720 ... Fix up trivial conflicts in arch/x86/Kconfig and net/mac80211/agg-tx.c as per Davem.
This commit is contained in:
commit
06f4e926d2
|
@ -0,0 +1,31 @@
|
|||
What: /sys/bus/bcma/devices/.../manuf
|
||||
Date: May 2011
|
||||
KernelVersion: 2.6.40
|
||||
Contact: Rafał Miłecki <zajec5@gmail.com>
|
||||
Description:
|
||||
Each BCMA core has it's manufacturer id. See
|
||||
include/linux/bcma/bcma.h for possible values.
|
||||
|
||||
What: /sys/bus/bcma/devices/.../id
|
||||
Date: May 2011
|
||||
KernelVersion: 2.6.40
|
||||
Contact: Rafał Miłecki <zajec5@gmail.com>
|
||||
Description:
|
||||
There are a few types of BCMA cores, they can be identified by
|
||||
id field.
|
||||
|
||||
What: /sys/bus/bcma/devices/.../rev
|
||||
Date: May 2011
|
||||
KernelVersion: 2.6.40
|
||||
Contact: Rafał Miłecki <zajec5@gmail.com>
|
||||
Description:
|
||||
BCMA cores of the same type can still slightly differ depending
|
||||
on their revision. Use it for detailed programming.
|
||||
|
||||
What: /sys/bus/bcma/devices/.../class
|
||||
Date: May 2011
|
||||
KernelVersion: 2.6.40
|
||||
Contact: Rafał Miłecki <zajec5@gmail.com>
|
||||
Description:
|
||||
Each BCMA core is identified by few fields, including class it
|
||||
belongs to. See include/linux/bcma/bcma.h for possible values.
|
|
@ -35,17 +35,6 @@ Who: Luis R. Rodriguez <lrodriguez@atheros.com>
|
|||
|
||||
---------------------------
|
||||
|
||||
What: AR9170USB
|
||||
When: 2.6.40
|
||||
|
||||
Why: This driver is deprecated and the firmware is no longer
|
||||
maintained. The replacement driver "carl9170" has been
|
||||
around for a while, so the devices are still supported.
|
||||
|
||||
Who: Christian Lamparter <chunkeey@googlemail.com>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: IRQF_SAMPLE_RANDOM
|
||||
Check: IRQF_SAMPLE_RANDOM
|
||||
When: July 2009
|
||||
|
@ -405,16 +394,6 @@ Who: anybody or Florian Mickler <florian@mickler.org>
|
|||
|
||||
----------------------------
|
||||
|
||||
What: capifs
|
||||
When: February 2011
|
||||
Files: drivers/isdn/capi/capifs.*
|
||||
Why: udev fully replaces this special file system that only contains CAPI
|
||||
NCCI TTY device nodes. User space (pppdcapiplugin) works without
|
||||
noticing the difference.
|
||||
Who: Jan Kiszka <jan.kiszka@web.de>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: KVM paravirt mmu host support
|
||||
When: January 2011
|
||||
Why: The paravirt mmu host support is slower than non-paravirt mmu, both
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[state: 27-01-2011]
|
||||
[state: 17-04-2011]
|
||||
|
||||
BATMAN-ADV
|
||||
----------
|
||||
|
@ -19,6 +19,7 @@ duce the overhead to a minimum. It does not depend on any (other)
|
|||
network driver, and can be used on wifi as well as ethernet lan,
|
||||
vpn, etc ... (anything with ethernet-style layer 2).
|
||||
|
||||
|
||||
CONFIGURATION
|
||||
-------------
|
||||
|
||||
|
@ -160,13 +161,13 @@ face. Each entry can/has to have the following values:
|
|||
-> "TQ mac value" - src mac's link quality towards mac address
|
||||
of a neighbor originator's interface which
|
||||
is being used for routing
|
||||
-> "HNA mac" - HNA announced by source mac
|
||||
-> "TT mac" - TT announced by source mac
|
||||
-> "PRIMARY" - this is a primary interface
|
||||
-> "SEC mac" - secondary mac address of source
|
||||
(requires preceding PRIMARY)
|
||||
|
||||
The TQ value has a range from 4 to 255 with 255 being the best.
|
||||
The HNA entries are showing which hosts are connected to the mesh
|
||||
The TT entries are showing which hosts are connected to the mesh
|
||||
via bat0 or being bridged into the mesh network. The PRIMARY/SEC
|
||||
values are only applied on primary interfaces
|
||||
|
||||
|
@ -199,7 +200,7 @@ abled during run time. Following log_levels are defined:
|
|||
|
||||
0 - All debug output disabled
|
||||
1 - Enable messages related to routing / flooding / broadcasting
|
||||
2 - Enable route or hna added / changed / deleted
|
||||
2 - Enable route or tt entry added / changed / deleted
|
||||
3 - Enable all messages
|
||||
|
||||
The debug output can be changed at runtime using the file
|
||||
|
@ -207,7 +208,7 @@ The debug output can be changed at runtime using the file
|
|||
|
||||
# echo 2 > /sys/class/net/bat0/mesh/log_level
|
||||
|
||||
will enable debug messages for when routes or HNAs change.
|
||||
will enable debug messages for when routes or TTs change.
|
||||
|
||||
|
||||
BATCTL
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
Linux Ethernet Bonding Driver HOWTO
|
||||
|
||||
Latest update: 23 September 2009
|
||||
Latest update: 27 April 2011
|
||||
|
||||
Initial release : Thomas Davis <tadavis at lbl.gov>
|
||||
Corrections, HA extensions : 2000/10/03-15 :
|
||||
|
@ -585,25 +585,23 @@ mode
|
|||
chosen.
|
||||
|
||||
num_grat_arp
|
||||
|
||||
Specifies the number of gratuitous ARPs to be issued after a
|
||||
failover event. One gratuitous ARP is issued immediately after
|
||||
the failover, subsequent ARPs are sent at a rate of one per link
|
||||
monitor interval (arp_interval or miimon, whichever is active).
|
||||
|
||||
The valid range is 0 - 255; the default value is 1. This option
|
||||
affects only the active-backup mode. This option was added for
|
||||
bonding version 3.3.0.
|
||||
|
||||
num_unsol_na
|
||||
|
||||
Specifies the number of unsolicited IPv6 Neighbor Advertisements
|
||||
to be issued after a failover event. One unsolicited NA is issued
|
||||
immediately after the failover.
|
||||
Specify the number of peer notifications (gratuitous ARPs and
|
||||
unsolicited IPv6 Neighbor Advertisements) to be issued after a
|
||||
failover event. As soon as the link is up on the new slave
|
||||
(possibly immediately) a peer notification is sent on the
|
||||
bonding device and each VLAN sub-device. This is repeated at
|
||||
each link monitor interval (arp_interval or miimon, whichever
|
||||
is active) if the number is greater than 1.
|
||||
|
||||
The valid range is 0 - 255; the default value is 1. This option
|
||||
affects only the active-backup mode. This option was added for
|
||||
bonding version 3.4.0.
|
||||
The valid range is 0 - 255; the default value is 1. These options
|
||||
affect only the active-backup mode. These options were added for
|
||||
bonding versions 3.3.0 and 3.4.0 respectively.
|
||||
|
||||
From Linux 2.6.40 and bonding version 3.7.1, these notifications
|
||||
are generated by the ipv4 and ipv6 code and the numbers of
|
||||
repetitions cannot be set independently.
|
||||
|
||||
primary
|
||||
|
||||
|
|
|
@ -93,6 +93,19 @@ Additional Configurations
|
|||
REQUIREMENTS: MSI-X support is required for Multiqueue. If MSI-X is not
|
||||
found, the system will fallback to MSI or to Legacy interrupts.
|
||||
|
||||
MAC and VLAN anti-spoofing feature
|
||||
----------------------------------
|
||||
When a malicious driver attempts to send a spoofed packet, it is dropped by
|
||||
the hardware and not transmitted. An interrupt is sent to the PF driver
|
||||
notifying it of the spoof attempt.
|
||||
|
||||
When a spoofed packet is detected the PF driver will send the following
|
||||
message to the system log (displayed by the "dmesg" command):
|
||||
|
||||
Spoof event(s) detected on VF(n)
|
||||
|
||||
Where n=the VF that attempted to do the spoofing.
|
||||
|
||||
Support
|
||||
=======
|
||||
|
||||
|
|
|
@ -32,6 +32,17 @@ Table : Subdirectories in /proc/sys/net
|
|||
1. /proc/sys/net/core - Network core options
|
||||
-------------------------------------------------------
|
||||
|
||||
bpf_jit_enable
|
||||
--------------
|
||||
|
||||
This enables Berkeley Packet Filter Just in Time compiler.
|
||||
Currently supported on x86_64 architecture, bpf_jit provides a framework
|
||||
to speed packet filtering, the one used by tcpdump/libpcap for example.
|
||||
Values :
|
||||
0 - disable the JIT (default value)
|
||||
1 - enable the JIT
|
||||
2 - enable the JIT and ask the compiler to emit traces on kernel log.
|
||||
|
||||
rmem_default
|
||||
------------
|
||||
|
||||
|
|
21
MAINTAINERS
21
MAINTAINERS
|
@ -1232,13 +1232,6 @@ W: http://wireless.kernel.org/en/users/Drivers/ath9k
|
|||
S: Supported
|
||||
F: drivers/net/wireless/ath/ath9k/
|
||||
|
||||
ATHEROS AR9170 WIRELESS DRIVER
|
||||
M: Christian Lamparter <chunkeey@web.de>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://wireless.kernel.org/en/users/Drivers/ar9170
|
||||
S: Obsolete
|
||||
F: drivers/net/wireless/ath/ar9170/
|
||||
|
||||
CARL9170 LINUX COMMUNITY WIRELESS DRIVER
|
||||
M: Christian Lamparter <chunkeey@googlemail.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
|
@ -3363,6 +3356,12 @@ F: Documentation/wimax/README.i2400m
|
|||
F: drivers/net/wimax/i2400m/
|
||||
F: include/linux/wimax/i2400m.h
|
||||
|
||||
INTEL WIRELESS 3945ABG/BG, 4965AGN (iwlegacy)
|
||||
M: Stanislaw Gruszka <sgruszka@redhat.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/net/wireless/iwlegacy/
|
||||
|
||||
INTEL WIRELESS WIFI LINK (iwlwifi)
|
||||
M: Wey-Yi Guy <wey-yi.w.guy@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -4385,6 +4384,7 @@ S: Maintained
|
|||
F: net/ipv4/
|
||||
F: net/ipv6/
|
||||
F: include/net/ip*
|
||||
F: arch/x86/net/*
|
||||
|
||||
NETWORKING [LABELED] (NetLabel, CIPSO, Labeled IPsec, SECMARK)
|
||||
M: Paul Moore <paul.moore@hp.com>
|
||||
|
@ -5832,6 +5832,13 @@ S: Maintained
|
|||
F: drivers/ssb/
|
||||
F: include/linux/ssb/
|
||||
|
||||
BROADCOM SPECIFIC AMBA DRIVER (BCMA)
|
||||
M: Rafał Miłecki <zajec5@gmail.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/bcma/
|
||||
F: include/linux/bcma/
|
||||
|
||||
SONY VAIO CONTROL DEVICE DRIVER
|
||||
M: Mattia Dongili <malattia@linux.it>
|
||||
L: platform-driver-x86@vger.kernel.org
|
||||
|
|
|
@ -318,19 +318,15 @@ void __init tx4939_sio_init(unsigned int sclk, unsigned int cts_mask)
|
|||
}
|
||||
|
||||
#if defined(CONFIG_TC35815) || defined(CONFIG_TC35815_MODULE)
|
||||
static int tx4939_get_eth_speed(struct net_device *dev)
|
||||
static u32 tx4939_get_eth_speed(struct net_device *dev)
|
||||
{
|
||||
struct ethtool_cmd cmd = { ETHTOOL_GSET };
|
||||
int speed = 100; /* default 100Mbps */
|
||||
int err;
|
||||
if (!dev->ethtool_ops || !dev->ethtool_ops->get_settings)
|
||||
return speed;
|
||||
err = dev->ethtool_ops->get_settings(dev, &cmd);
|
||||
if (err < 0)
|
||||
return speed;
|
||||
speed = cmd.speed == SPEED_100 ? 100 : 10;
|
||||
return speed;
|
||||
struct ethtool_cmd cmd;
|
||||
if (dev_ethtool_get_settings(dev, &cmd))
|
||||
return 100; /* default 100Mbps */
|
||||
|
||||
return ethtool_cmd_speed(&cmd);
|
||||
}
|
||||
|
||||
static int tx4939_netdev_event(struct notifier_block *this,
|
||||
unsigned long event,
|
||||
void *ptr)
|
||||
|
@ -343,8 +339,7 @@ static int tx4939_netdev_event(struct notifier_block *this,
|
|||
else if (dev->irq == TXX9_IRQ_BASE + TX4939_IR_ETH(1))
|
||||
bit = TX4939_PCFG_SPEED1;
|
||||
if (bit) {
|
||||
int speed = tx4939_get_eth_speed(dev);
|
||||
if (speed == 100)
|
||||
if (tx4939_get_eth_speed(dev) == 100)
|
||||
txx9_set64(&tx4939_ccfgptr->pcfg, bit);
|
||||
else
|
||||
txx9_clear64(&tx4939_ccfgptr->pcfg, bit);
|
||||
|
|
|
@ -352,3 +352,4 @@ SYSCALL_SPU(name_to_handle_at)
|
|||
COMPAT_SYS_SPU(open_by_handle_at)
|
||||
COMPAT_SYS_SPU(clock_adjtime)
|
||||
SYSCALL_SPU(syncfs)
|
||||
COMPAT_SYS_SPU(sendmmsg)
|
||||
|
|
|
@ -371,10 +371,11 @@
|
|||
#define __NR_open_by_handle_at 346
|
||||
#define __NR_clock_adjtime 347
|
||||
#define __NR_syncfs 348
|
||||
#define __NR_sendmmsg 349
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define __NR_syscalls 349
|
||||
#define __NR_syscalls 350
|
||||
|
||||
#define __NR__exit __NR_exit
|
||||
#define NR_syscalls __NR_syscalls
|
||||
|
|
|
@ -404,8 +404,9 @@
|
|||
#define __NR_open_by_handle_at 333
|
||||
#define __NR_clock_adjtime 334
|
||||
#define __NR_syncfs 335
|
||||
#define __NR_sendmmsg 336
|
||||
|
||||
#define NR_syscalls 336
|
||||
#define NR_syscalls 337
|
||||
|
||||
#ifdef __32bit_syscall_numbers__
|
||||
/* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
|
||||
|
|
|
@ -84,4 +84,4 @@ sys_call_table:
|
|||
/*320*/ .long sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv
|
||||
/*325*/ .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
|
||||
/*330*/ .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
|
||||
/*335*/ .long sys_syncfs
|
||||
/*335*/ .long sys_syncfs, sys_sendmmsg
|
||||
|
|
|
@ -85,7 +85,7 @@ sys_call_table32:
|
|||
/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, compat_sys_preadv
|
||||
.word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init
|
||||
/*330*/ .word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime
|
||||
.word sys_syncfs
|
||||
.word sys_syncfs, compat_sys_sendmmsg
|
||||
|
||||
#endif /* CONFIG_COMPAT */
|
||||
|
||||
|
@ -162,4 +162,4 @@ sys_call_table:
|
|||
/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv
|
||||
.word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
|
||||
/*330*/ .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
|
||||
.word sys_syncfs
|
||||
.word sys_syncfs, sys_sendmmsg
|
||||
|
|
|
@ -15,3 +15,4 @@ obj-y += vdso/
|
|||
obj-$(CONFIG_IA32_EMULATION) += ia32/
|
||||
|
||||
obj-y += platform/
|
||||
obj-y += net/
|
||||
|
|
|
@ -72,6 +72,7 @@ config X86
|
|||
select GENERIC_IRQ_SHOW
|
||||
select IRQ_FORCED_THREADING
|
||||
select USE_GENERIC_SMP_HELPERS if SMP
|
||||
select HAVE_BPF_JIT if (X86_64 && NET)
|
||||
|
||||
config INSTRUCTION_DECODER
|
||||
def_bool (KPROBES || PERF_EVENTS)
|
||||
|
|
|
@ -848,4 +848,5 @@ ia32_sys_call_table:
|
|||
.quad compat_sys_open_by_handle_at
|
||||
.quad compat_sys_clock_adjtime
|
||||
.quad sys_syncfs
|
||||
.quad compat_sys_sendmmsg /* 345 */
|
||||
ia32_syscall_end:
|
||||
|
|
|
@ -350,10 +350,11 @@
|
|||
#define __NR_open_by_handle_at 342
|
||||
#define __NR_clock_adjtime 343
|
||||
#define __NR_syncfs 344
|
||||
#define __NR_sendmmsg 345
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define NR_syscalls 345
|
||||
#define NR_syscalls 346
|
||||
|
||||
#define __ARCH_WANT_IPC_PARSE_VERSION
|
||||
#define __ARCH_WANT_OLD_READDIR
|
||||
|
|
|
@ -677,6 +677,8 @@ __SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at)
|
|||
__SYSCALL(__NR_clock_adjtime, sys_clock_adjtime)
|
||||
#define __NR_syncfs 306
|
||||
__SYSCALL(__NR_syncfs, sys_syncfs)
|
||||
#define __NR_sendmmsg 307
|
||||
__SYSCALL(__NR_sendmmsg, sys_sendmmsg)
|
||||
|
||||
#ifndef __NO_STUBS
|
||||
#define __ARCH_WANT_OLD_READDIR
|
||||
|
|
|
@ -344,3 +344,4 @@ ENTRY(sys_call_table)
|
|||
.long sys_open_by_handle_at
|
||||
.long sys_clock_adjtime
|
||||
.long sys_syncfs
|
||||
.long sys_sendmmsg /* 345 */
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
#
|
||||
# Arch-specific network modules
|
||||
#
|
||||
obj-$(CONFIG_BPF_JIT) += bpf_jit.o bpf_jit_comp.o
|
|
@ -0,0 +1,140 @@
|
|||
/* bpf_jit.S : BPF JIT helper functions
|
||||
*
|
||||
* Copyright (C) 2011 Eric Dumazet (eric.dumazet@gmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; version 2
|
||||
* of the License.
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/dwarf2.h>
|
||||
|
||||
/*
|
||||
* Calling convention :
|
||||
* rdi : skb pointer
|
||||
* esi : offset of byte(s) to fetch in skb (can be scratched)
|
||||
* r8 : copy of skb->data
|
||||
* r9d : hlen = skb->len - skb->data_len
|
||||
*/
|
||||
#define SKBDATA %r8
|
||||
|
||||
sk_load_word_ind:
|
||||
.globl sk_load_word_ind
|
||||
|
||||
add %ebx,%esi /* offset += X */
|
||||
# test %esi,%esi /* if (offset < 0) goto bpf_error; */
|
||||
js bpf_error
|
||||
|
||||
sk_load_word:
|
||||
.globl sk_load_word
|
||||
|
||||
mov %r9d,%eax # hlen
|
||||
sub %esi,%eax # hlen - offset
|
||||
cmp $3,%eax
|
||||
jle bpf_slow_path_word
|
||||
mov (SKBDATA,%rsi),%eax
|
||||
bswap %eax /* ntohl() */
|
||||
ret
|
||||
|
||||
|
||||
sk_load_half_ind:
|
||||
.globl sk_load_half_ind
|
||||
|
||||
add %ebx,%esi /* offset += X */
|
||||
js bpf_error
|
||||
|
||||
sk_load_half:
|
||||
.globl sk_load_half
|
||||
|
||||
mov %r9d,%eax
|
||||
sub %esi,%eax # hlen - offset
|
||||
cmp $1,%eax
|
||||
jle bpf_slow_path_half
|
||||
movzwl (SKBDATA,%rsi),%eax
|
||||
rol $8,%ax # ntohs()
|
||||
ret
|
||||
|
||||
sk_load_byte_ind:
|
||||
.globl sk_load_byte_ind
|
||||
add %ebx,%esi /* offset += X */
|
||||
js bpf_error
|
||||
|
||||
sk_load_byte:
|
||||
.globl sk_load_byte
|
||||
|
||||
cmp %esi,%r9d /* if (offset >= hlen) goto bpf_slow_path_byte */
|
||||
jle bpf_slow_path_byte
|
||||
movzbl (SKBDATA,%rsi),%eax
|
||||
ret
|
||||
|
||||
/**
|
||||
* sk_load_byte_msh - BPF_S_LDX_B_MSH helper
|
||||
*
|
||||
* Implements BPF_S_LDX_B_MSH : ldxb 4*([offset]&0xf)
|
||||
* Must preserve A accumulator (%eax)
|
||||
* Inputs : %esi is the offset value, already known positive
|
||||
*/
|
||||
ENTRY(sk_load_byte_msh)
|
||||
CFI_STARTPROC
|
||||
cmp %esi,%r9d /* if (offset >= hlen) goto bpf_slow_path_byte_msh */
|
||||
jle bpf_slow_path_byte_msh
|
||||
movzbl (SKBDATA,%rsi),%ebx
|
||||
and $15,%bl
|
||||
shl $2,%bl
|
||||
ret
|
||||
CFI_ENDPROC
|
||||
ENDPROC(sk_load_byte_msh)
|
||||
|
||||
bpf_error:
|
||||
# force a return 0 from jit handler
|
||||
xor %eax,%eax
|
||||
mov -8(%rbp),%rbx
|
||||
leaveq
|
||||
ret
|
||||
|
||||
/* rsi contains offset and can be scratched */
|
||||
#define bpf_slow_path_common(LEN) \
|
||||
push %rdi; /* save skb */ \
|
||||
push %r9; \
|
||||
push SKBDATA; \
|
||||
/* rsi already has offset */ \
|
||||
mov $LEN,%ecx; /* len */ \
|
||||
lea -12(%rbp),%rdx; \
|
||||
call skb_copy_bits; \
|
||||
test %eax,%eax; \
|
||||
pop SKBDATA; \
|
||||
pop %r9; \
|
||||
pop %rdi
|
||||
|
||||
|
||||
bpf_slow_path_word:
|
||||
bpf_slow_path_common(4)
|
||||
js bpf_error
|
||||
mov -12(%rbp),%eax
|
||||
bswap %eax
|
||||
ret
|
||||
|
||||
bpf_slow_path_half:
|
||||
bpf_slow_path_common(2)
|
||||
js bpf_error
|
||||
mov -12(%rbp),%ax
|
||||
rol $8,%ax
|
||||
movzwl %ax,%eax
|
||||
ret
|
||||
|
||||
bpf_slow_path_byte:
|
||||
bpf_slow_path_common(1)
|
||||
js bpf_error
|
||||
movzbl -12(%rbp),%eax
|
||||
ret
|
||||
|
||||
bpf_slow_path_byte_msh:
|
||||
xchg %eax,%ebx /* dont lose A , X is about to be scratched */
|
||||
bpf_slow_path_common(1)
|
||||
js bpf_error
|
||||
movzbl -12(%rbp),%eax
|
||||
and $15,%al
|
||||
shl $2,%al
|
||||
xchg %eax,%ebx
|
||||
ret
|
|
@ -0,0 +1,654 @@
|
|||
/* bpf_jit_comp.c : BPF JIT compiler
|
||||
*
|
||||
* Copyright (C) 2011 Eric Dumazet (eric.dumazet@gmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; version 2
|
||||
* of the License.
|
||||
*/
|
||||
#include <linux/moduleloader.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/filter.h>
|
||||
|
||||
/*
|
||||
* Conventions :
|
||||
* EAX : BPF A accumulator
|
||||
* EBX : BPF X accumulator
|
||||
* RDI : pointer to skb (first argument given to JIT function)
|
||||
* RBP : frame pointer (even if CONFIG_FRAME_POINTER=n)
|
||||
* ECX,EDX,ESI : scratch registers
|
||||
* r9d : skb->len - skb->data_len (headlen)
|
||||
* r8 : skb->data
|
||||
* -8(RBP) : saved RBX value
|
||||
* -16(RBP)..-80(RBP) : BPF_MEMWORDS values
|
||||
*/
|
||||
int bpf_jit_enable __read_mostly;
|
||||
|
||||
/*
|
||||
* assembly code in arch/x86/net/bpf_jit.S
|
||||
*/
|
||||
extern u8 sk_load_word[], sk_load_half[], sk_load_byte[], sk_load_byte_msh[];
|
||||
extern u8 sk_load_word_ind[], sk_load_half_ind[], sk_load_byte_ind[];
|
||||
|
||||
static inline u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len)
|
||||
{
|
||||
if (len == 1)
|
||||
*ptr = bytes;
|
||||
else if (len == 2)
|
||||
*(u16 *)ptr = bytes;
|
||||
else {
|
||||
*(u32 *)ptr = bytes;
|
||||
barrier();
|
||||
}
|
||||
return ptr + len;
|
||||
}
|
||||
|
||||
#define EMIT(bytes, len) do { prog = emit_code(prog, bytes, len); } while (0)
|
||||
|
||||
#define EMIT1(b1) EMIT(b1, 1)
|
||||
#define EMIT2(b1, b2) EMIT((b1) + ((b2) << 8), 2)
|
||||
#define EMIT3(b1, b2, b3) EMIT((b1) + ((b2) << 8) + ((b3) << 16), 3)
|
||||
#define EMIT4(b1, b2, b3, b4) EMIT((b1) + ((b2) << 8) + ((b3) << 16) + ((b4) << 24), 4)
|
||||
#define EMIT1_off32(b1, off) do { EMIT1(b1); EMIT(off, 4);} while (0)
|
||||
|
||||
#define CLEAR_A() EMIT2(0x31, 0xc0) /* xor %eax,%eax */
|
||||
#define CLEAR_X() EMIT2(0x31, 0xdb) /* xor %ebx,%ebx */
|
||||
|
||||
static inline bool is_imm8(int value)
|
||||
{
|
||||
return value <= 127 && value >= -128;
|
||||
}
|
||||
|
||||
static inline bool is_near(int offset)
|
||||
{
|
||||
return offset <= 127 && offset >= -128;
|
||||
}
|
||||
|
||||
#define EMIT_JMP(offset) \
|
||||
do { \
|
||||
if (offset) { \
|
||||
if (is_near(offset)) \
|
||||
EMIT2(0xeb, offset); /* jmp .+off8 */ \
|
||||
else \
|
||||
EMIT1_off32(0xe9, offset); /* jmp .+off32 */ \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* list of x86 cond jumps opcodes (. + s8)
|
||||
* Add 0x10 (and an extra 0x0f) to generate far jumps (. + s32)
|
||||
*/
|
||||
#define X86_JB 0x72
|
||||
#define X86_JAE 0x73
|
||||
#define X86_JE 0x74
|
||||
#define X86_JNE 0x75
|
||||
#define X86_JBE 0x76
|
||||
#define X86_JA 0x77
|
||||
|
||||
#define EMIT_COND_JMP(op, offset) \
|
||||
do { \
|
||||
if (is_near(offset)) \
|
||||
EMIT2(op, offset); /* jxx .+off8 */ \
|
||||
else { \
|
||||
EMIT2(0x0f, op + 0x10); \
|
||||
EMIT(offset, 4); /* jxx .+off32 */ \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define COND_SEL(CODE, TOP, FOP) \
|
||||
case CODE: \
|
||||
t_op = TOP; \
|
||||
f_op = FOP; \
|
||||
goto cond_branch
|
||||
|
||||
|
||||
#define SEEN_DATAREF 1 /* might call external helpers */
|
||||
#define SEEN_XREG 2 /* ebx is used */
|
||||
#define SEEN_MEM 4 /* use mem[] for temporary storage */
|
||||
|
||||
static inline void bpf_flush_icache(void *start, void *end)
|
||||
{
|
||||
mm_segment_t old_fs = get_fs();
|
||||
|
||||
set_fs(KERNEL_DS);
|
||||
smp_wmb();
|
||||
flush_icache_range((unsigned long)start, (unsigned long)end);
|
||||
set_fs(old_fs);
|
||||
}
|
||||
|
||||
|
||||
void bpf_jit_compile(struct sk_filter *fp)
|
||||
{
|
||||
u8 temp[64];
|
||||
u8 *prog;
|
||||
unsigned int proglen, oldproglen = 0;
|
||||
int ilen, i;
|
||||
int t_offset, f_offset;
|
||||
u8 t_op, f_op, seen = 0, pass;
|
||||
u8 *image = NULL;
|
||||
u8 *func;
|
||||
int pc_ret0 = -1; /* bpf index of first RET #0 instruction (if any) */
|
||||
unsigned int cleanup_addr; /* epilogue code offset */
|
||||
unsigned int *addrs;
|
||||
const struct sock_filter *filter = fp->insns;
|
||||
int flen = fp->len;
|
||||
|
||||
if (!bpf_jit_enable)
|
||||
return;
|
||||
|
||||
addrs = kmalloc(flen * sizeof(*addrs), GFP_KERNEL);
|
||||
if (addrs == NULL)
|
||||
return;
|
||||
|
||||
/* Before first pass, make a rough estimation of addrs[]
|
||||
* each bpf instruction is translated to less than 64 bytes
|
||||
*/
|
||||
for (proglen = 0, i = 0; i < flen; i++) {
|
||||
proglen += 64;
|
||||
addrs[i] = proglen;
|
||||
}
|
||||
cleanup_addr = proglen; /* epilogue address */
|
||||
|
||||
for (pass = 0; pass < 10; pass++) {
|
||||
/* no prologue/epilogue for trivial filters (RET something) */
|
||||
proglen = 0;
|
||||
prog = temp;
|
||||
|
||||
if (seen) {
|
||||
EMIT4(0x55, 0x48, 0x89, 0xe5); /* push %rbp; mov %rsp,%rbp */
|
||||
EMIT4(0x48, 0x83, 0xec, 96); /* subq $96,%rsp */
|
||||
/* note : must save %rbx in case bpf_error is hit */
|
||||
if (seen & (SEEN_XREG | SEEN_DATAREF))
|
||||
EMIT4(0x48, 0x89, 0x5d, 0xf8); /* mov %rbx, -8(%rbp) */
|
||||
if (seen & SEEN_XREG)
|
||||
CLEAR_X(); /* make sure we dont leek kernel memory */
|
||||
|
||||
/*
|
||||
* If this filter needs to access skb data,
|
||||
* loads r9 and r8 with :
|
||||
* r9 = skb->len - skb->data_len
|
||||
* r8 = skb->data
|
||||
*/
|
||||
if (seen & SEEN_DATAREF) {
|
||||
if (offsetof(struct sk_buff, len) <= 127)
|
||||
/* mov off8(%rdi),%r9d */
|
||||
EMIT4(0x44, 0x8b, 0x4f, offsetof(struct sk_buff, len));
|
||||
else {
|
||||
/* mov off32(%rdi),%r9d */
|
||||
EMIT3(0x44, 0x8b, 0x8f);
|
||||
EMIT(offsetof(struct sk_buff, len), 4);
|
||||
}
|
||||
if (is_imm8(offsetof(struct sk_buff, data_len)))
|
||||
/* sub off8(%rdi),%r9d */
|
||||
EMIT4(0x44, 0x2b, 0x4f, offsetof(struct sk_buff, data_len));
|
||||
else {
|
||||
EMIT3(0x44, 0x2b, 0x8f);
|
||||
EMIT(offsetof(struct sk_buff, data_len), 4);
|
||||
}
|
||||
|
||||
if (is_imm8(offsetof(struct sk_buff, data)))
|
||||
/* mov off8(%rdi),%r8 */
|
||||
EMIT4(0x4c, 0x8b, 0x47, offsetof(struct sk_buff, data));
|
||||
else {
|
||||
/* mov off32(%rdi),%r8 */
|
||||
EMIT3(0x4c, 0x8b, 0x87);
|
||||
EMIT(offsetof(struct sk_buff, data), 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (filter[0].code) {
|
||||
case BPF_S_RET_K:
|
||||
case BPF_S_LD_W_LEN:
|
||||
case BPF_S_ANC_PROTOCOL:
|
||||
case BPF_S_ANC_IFINDEX:
|
||||
case BPF_S_ANC_MARK:
|
||||
case BPF_S_ANC_RXHASH:
|
||||
case BPF_S_ANC_CPU:
|
||||
case BPF_S_ANC_QUEUE:
|
||||
case BPF_S_LD_W_ABS:
|
||||
case BPF_S_LD_H_ABS:
|
||||
case BPF_S_LD_B_ABS:
|
||||
/* first instruction sets A register (or is RET 'constant') */
|
||||
break;
|
||||
default:
|
||||
/* make sure we dont leak kernel information to user */
|
||||
CLEAR_A(); /* A = 0 */
|
||||
}
|
||||
|
||||
for (i = 0; i < flen; i++) {
|
||||
unsigned int K = filter[i].k;
|
||||
|
||||
switch (filter[i].code) {
|
||||
case BPF_S_ALU_ADD_X: /* A += X; */
|
||||
seen |= SEEN_XREG;
|
||||
EMIT2(0x01, 0xd8); /* add %ebx,%eax */
|
||||
break;
|
||||
case BPF_S_ALU_ADD_K: /* A += K; */
|
||||
if (!K)
|
||||
break;
|
||||
if (is_imm8(K))
|
||||
EMIT3(0x83, 0xc0, K); /* add imm8,%eax */
|
||||
else
|
||||
EMIT1_off32(0x05, K); /* add imm32,%eax */
|
||||
break;
|
||||
case BPF_S_ALU_SUB_X: /* A -= X; */
|
||||
seen |= SEEN_XREG;
|
||||
EMIT2(0x29, 0xd8); /* sub %ebx,%eax */
|
||||
break;
|
||||
case BPF_S_ALU_SUB_K: /* A -= K */
|
||||
if (!K)
|
||||
break;
|
||||
if (is_imm8(K))
|
||||
EMIT3(0x83, 0xe8, K); /* sub imm8,%eax */
|
||||
else
|
||||
EMIT1_off32(0x2d, K); /* sub imm32,%eax */
|
||||
break;
|
||||
case BPF_S_ALU_MUL_X: /* A *= X; */
|
||||
seen |= SEEN_XREG;
|
||||
EMIT3(0x0f, 0xaf, 0xc3); /* imul %ebx,%eax */
|
||||
break;
|
||||
case BPF_S_ALU_MUL_K: /* A *= K */
|
||||
if (is_imm8(K))
|
||||
EMIT3(0x6b, 0xc0, K); /* imul imm8,%eax,%eax */
|
||||
else {
|
||||
EMIT2(0x69, 0xc0); /* imul imm32,%eax */
|
||||
EMIT(K, 4);
|
||||
}
|
||||
break;
|
||||
case BPF_S_ALU_DIV_X: /* A /= X; */
|
||||
seen |= SEEN_XREG;
|
||||
EMIT2(0x85, 0xdb); /* test %ebx,%ebx */
|
||||
if (pc_ret0 != -1)
|
||||
EMIT_COND_JMP(X86_JE, addrs[pc_ret0] - (addrs[i] - 4));
|
||||
else {
|
||||
EMIT_COND_JMP(X86_JNE, 2 + 5);
|
||||
CLEAR_A();
|
||||
EMIT1_off32(0xe9, cleanup_addr - (addrs[i] - 4)); /* jmp .+off32 */
|
||||
}
|
||||
EMIT4(0x31, 0xd2, 0xf7, 0xf3); /* xor %edx,%edx; div %ebx */
|
||||
break;
|
||||
case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */
|
||||
EMIT3(0x48, 0x69, 0xc0); /* imul imm32,%rax,%rax */
|
||||
EMIT(K, 4);
|
||||
EMIT4(0x48, 0xc1, 0xe8, 0x20); /* shr $0x20,%rax */
|
||||
break;
|
||||
case BPF_S_ALU_AND_X:
|
||||
seen |= SEEN_XREG;
|
||||
EMIT2(0x21, 0xd8); /* and %ebx,%eax */
|
||||
break;
|
||||
case BPF_S_ALU_AND_K:
|
||||
if (K >= 0xFFFFFF00) {
|
||||
EMIT2(0x24, K & 0xFF); /* and imm8,%al */
|
||||
} else if (K >= 0xFFFF0000) {
|
||||
EMIT2(0x66, 0x25); /* and imm16,%ax */
|
||||
EMIT2(K, 2);
|
||||
} else {
|
||||
EMIT1_off32(0x25, K); /* and imm32,%eax */
|
||||
}
|
||||
break;
|
||||
case BPF_S_ALU_OR_X:
|
||||
seen |= SEEN_XREG;
|
||||
EMIT2(0x09, 0xd8); /* or %ebx,%eax */
|
||||
break;
|
||||
case BPF_S_ALU_OR_K:
|
||||
if (is_imm8(K))
|
||||
EMIT3(0x83, 0xc8, K); /* or imm8,%eax */
|
||||
else
|
||||
EMIT1_off32(0x0d, K); /* or imm32,%eax */
|
||||
break;
|
||||
case BPF_S_ALU_LSH_X: /* A <<= X; */
|
||||
seen |= SEEN_XREG;
|
||||
EMIT4(0x89, 0xd9, 0xd3, 0xe0); /* mov %ebx,%ecx; shl %cl,%eax */
|
||||
break;
|
||||
case BPF_S_ALU_LSH_K:
|
||||
if (K == 0)
|
||||
break;
|
||||
else if (K == 1)
|
||||
EMIT2(0xd1, 0xe0); /* shl %eax */
|
||||
else
|
||||
EMIT3(0xc1, 0xe0, K);
|
||||
break;
|
||||
case BPF_S_ALU_RSH_X: /* A >>= X; */
|
||||
seen |= SEEN_XREG;
|
||||
EMIT4(0x89, 0xd9, 0xd3, 0xe8); /* mov %ebx,%ecx; shr %cl,%eax */
|
||||
break;
|
||||
case BPF_S_ALU_RSH_K: /* A >>= K; */
|
||||
if (K == 0)
|
||||
break;
|
||||
else if (K == 1)
|
||||
EMIT2(0xd1, 0xe8); /* shr %eax */
|
||||
else
|
||||
EMIT3(0xc1, 0xe8, K);
|
||||
break;
|
||||
case BPF_S_ALU_NEG:
|
||||
EMIT2(0xf7, 0xd8); /* neg %eax */
|
||||
break;
|
||||
case BPF_S_RET_K:
|
||||
if (!K) {
|
||||
if (pc_ret0 == -1)
|
||||
pc_ret0 = i;
|
||||
CLEAR_A();
|
||||
} else {
|
||||
EMIT1_off32(0xb8, K); /* mov $imm32,%eax */
|
||||
}
|
||||
/* fallinto */
|
||||
case BPF_S_RET_A:
|
||||
if (seen) {
|
||||
if (i != flen - 1) {
|
||||
EMIT_JMP(cleanup_addr - addrs[i]);
|
||||
break;
|
||||
}
|
||||
if (seen & SEEN_XREG)
|
||||
EMIT4(0x48, 0x8b, 0x5d, 0xf8); /* mov -8(%rbp),%rbx */
|
||||
EMIT1(0xc9); /* leaveq */
|
||||
}
|
||||
EMIT1(0xc3); /* ret */
|
||||
break;
|
||||
case BPF_S_MISC_TAX: /* X = A */
|
||||
seen |= SEEN_XREG;
|
||||
EMIT2(0x89, 0xc3); /* mov %eax,%ebx */
|
||||
break;
|
||||
case BPF_S_MISC_TXA: /* A = X */
|
||||
seen |= SEEN_XREG;
|
||||
EMIT2(0x89, 0xd8); /* mov %ebx,%eax */
|
||||
break;
|
||||
case BPF_S_LD_IMM: /* A = K */
|
||||
if (!K)
|
||||
CLEAR_A();
|
||||
else
|
||||
EMIT1_off32(0xb8, K); /* mov $imm32,%eax */
|
||||
break;
|
||||
case BPF_S_LDX_IMM: /* X = K */
|
||||
seen |= SEEN_XREG;
|
||||
if (!K)
|
||||
CLEAR_X();
|
||||
else
|
||||
EMIT1_off32(0xbb, K); /* mov $imm32,%ebx */
|
||||
break;
|
||||
case BPF_S_LD_MEM: /* A = mem[K] : mov off8(%rbp),%eax */
|
||||
seen |= SEEN_MEM;
|
||||
EMIT3(0x8b, 0x45, 0xf0 - K*4);
|
||||
break;
|
||||
case BPF_S_LDX_MEM: /* X = mem[K] : mov off8(%rbp),%ebx */
|
||||
seen |= SEEN_XREG | SEEN_MEM;
|
||||
EMIT3(0x8b, 0x5d, 0xf0 - K*4);
|
||||
break;
|
||||
case BPF_S_ST: /* mem[K] = A : mov %eax,off8(%rbp) */
|
||||
seen |= SEEN_MEM;
|
||||
EMIT3(0x89, 0x45, 0xf0 - K*4);
|
||||
break;
|
||||
case BPF_S_STX: /* mem[K] = X : mov %ebx,off8(%rbp) */
|
||||
seen |= SEEN_XREG | SEEN_MEM;
|
||||
EMIT3(0x89, 0x5d, 0xf0 - K*4);
|
||||
break;
|
||||
case BPF_S_LD_W_LEN: /* A = skb->len; */
|
||||
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, len) != 4);
|
||||
if (is_imm8(offsetof(struct sk_buff, len)))
|
||||
/* mov off8(%rdi),%eax */
|
||||
EMIT3(0x8b, 0x47, offsetof(struct sk_buff, len));
|
||||
else {
|
||||
EMIT2(0x8b, 0x87);
|
||||
EMIT(offsetof(struct sk_buff, len), 4);
|
||||
}
|
||||
break;
|
||||
case BPF_S_LDX_W_LEN: /* X = skb->len; */
|
||||
seen |= SEEN_XREG;
|
||||
if (is_imm8(offsetof(struct sk_buff, len)))
|
||||
/* mov off8(%rdi),%ebx */
|
||||
EMIT3(0x8b, 0x5f, offsetof(struct sk_buff, len));
|
||||
else {
|
||||
EMIT2(0x8b, 0x9f);
|
||||
EMIT(offsetof(struct sk_buff, len), 4);
|
||||
}
|
||||
break;
|
||||
case BPF_S_ANC_PROTOCOL: /* A = ntohs(skb->protocol); */
|
||||
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, protocol) != 2);
|
||||
if (is_imm8(offsetof(struct sk_buff, protocol))) {
|
||||
/* movzwl off8(%rdi),%eax */
|
||||
EMIT4(0x0f, 0xb7, 0x47, offsetof(struct sk_buff, protocol));
|
||||
} else {
|
||||
EMIT3(0x0f, 0xb7, 0x87); /* movzwl off32(%rdi),%eax */
|
||||
EMIT(offsetof(struct sk_buff, protocol), 4);
|
||||
}
|
||||
EMIT2(0x86, 0xc4); /* ntohs() : xchg %al,%ah */
|
||||
break;
|
||||
case BPF_S_ANC_IFINDEX:
|
||||
if (is_imm8(offsetof(struct sk_buff, dev))) {
|
||||
/* movq off8(%rdi),%rax */
|
||||
EMIT4(0x48, 0x8b, 0x47, offsetof(struct sk_buff, dev));
|
||||
} else {
|
||||
EMIT3(0x48, 0x8b, 0x87); /* movq off32(%rdi),%rax */
|
||||
EMIT(offsetof(struct sk_buff, dev), 4);
|
||||
}
|
||||
EMIT3(0x48, 0x85, 0xc0); /* test %rax,%rax */
|
||||
EMIT_COND_JMP(X86_JE, cleanup_addr - (addrs[i] - 6));
|
||||
BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, ifindex) != 4);
|
||||
EMIT2(0x8b, 0x80); /* mov off32(%rax),%eax */
|
||||
EMIT(offsetof(struct net_device, ifindex), 4);
|
||||
break;
|
||||
case BPF_S_ANC_MARK:
|
||||
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4);
|
||||
if (is_imm8(offsetof(struct sk_buff, mark))) {
|
||||
/* mov off8(%rdi),%eax */
|
||||
EMIT3(0x8b, 0x47, offsetof(struct sk_buff, mark));
|
||||
} else {
|
||||
EMIT2(0x8b, 0x87);
|
||||
EMIT(offsetof(struct sk_buff, mark), 4);
|
||||
}
|
||||
break;
|
||||
case BPF_S_ANC_RXHASH:
|
||||
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, rxhash) != 4);
|
||||
if (is_imm8(offsetof(struct sk_buff, rxhash))) {
|
||||
/* mov off8(%rdi),%eax */
|
||||
EMIT3(0x8b, 0x47, offsetof(struct sk_buff, rxhash));
|
||||
} else {
|
||||
EMIT2(0x8b, 0x87);
|
||||
EMIT(offsetof(struct sk_buff, rxhash), 4);
|
||||
}
|
||||
break;
|
||||
case BPF_S_ANC_QUEUE:
|
||||
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, queue_mapping) != 2);
|
||||
if (is_imm8(offsetof(struct sk_buff, queue_mapping))) {
|
||||
/* movzwl off8(%rdi),%eax */
|
||||
EMIT4(0x0f, 0xb7, 0x47, offsetof(struct sk_buff, queue_mapping));
|
||||
} else {
|
||||
EMIT3(0x0f, 0xb7, 0x87); /* movzwl off32(%rdi),%eax */
|
||||
EMIT(offsetof(struct sk_buff, queue_mapping), 4);
|
||||
}
|
||||
break;
|
||||
case BPF_S_ANC_CPU:
|
||||
#ifdef CONFIG_SMP
|
||||
EMIT4(0x65, 0x8b, 0x04, 0x25); /* mov %gs:off32,%eax */
|
||||
EMIT((u32)(unsigned long)&cpu_number, 4); /* A = smp_processor_id(); */
|
||||
#else
|
||||
CLEAR_A();
|
||||
#endif
|
||||
break;
|
||||
case BPF_S_LD_W_ABS:
|
||||
func = sk_load_word;
|
||||
common_load: seen |= SEEN_DATAREF;
|
||||
if ((int)K < 0)
|
||||
goto out;
|
||||
t_offset = func - (image + addrs[i]);
|
||||
EMIT1_off32(0xbe, K); /* mov imm32,%esi */
|
||||
EMIT1_off32(0xe8, t_offset); /* call */
|
||||
break;
|
||||
case BPF_S_LD_H_ABS:
|
||||
func = sk_load_half;
|
||||
goto common_load;
|
||||
case BPF_S_LD_B_ABS:
|
||||
func = sk_load_byte;
|
||||
goto common_load;
|
||||
case BPF_S_LDX_B_MSH:
|
||||
if ((int)K < 0) {
|
||||
if (pc_ret0 != -1) {
|
||||
EMIT_JMP(addrs[pc_ret0] - addrs[i]);
|
||||
break;
|
||||
}
|
||||
CLEAR_A();
|
||||
EMIT_JMP(cleanup_addr - addrs[i]);
|
||||
break;
|
||||
}
|
||||
seen |= SEEN_DATAREF | SEEN_XREG;
|
||||
t_offset = sk_load_byte_msh - (image + addrs[i]);
|
||||
EMIT1_off32(0xbe, K); /* mov imm32,%esi */
|
||||
EMIT1_off32(0xe8, t_offset); /* call sk_load_byte_msh */
|
||||
break;
|
||||
case BPF_S_LD_W_IND:
|
||||
func = sk_load_word_ind;
|
||||
common_load_ind: seen |= SEEN_DATAREF | SEEN_XREG;
|
||||
t_offset = func - (image + addrs[i]);
|
||||
EMIT1_off32(0xbe, K); /* mov imm32,%esi */
|
||||
EMIT1_off32(0xe8, t_offset); /* call sk_load_xxx_ind */
|
||||
break;
|
||||
case BPF_S_LD_H_IND:
|
||||
func = sk_load_half_ind;
|
||||
goto common_load_ind;
|
||||
case BPF_S_LD_B_IND:
|
||||
func = sk_load_byte_ind;
|
||||
goto common_load_ind;
|
||||
case BPF_S_JMP_JA:
|
||||
t_offset = addrs[i + K] - addrs[i];
|
||||
EMIT_JMP(t_offset);
|
||||
break;
|
||||
COND_SEL(BPF_S_JMP_JGT_K, X86_JA, X86_JBE);
|
||||
COND_SEL(BPF_S_JMP_JGE_K, X86_JAE, X86_JB);
|
||||
COND_SEL(BPF_S_JMP_JEQ_K, X86_JE, X86_JNE);
|
||||
COND_SEL(BPF_S_JMP_JSET_K,X86_JNE, X86_JE);
|
||||
COND_SEL(BPF_S_JMP_JGT_X, X86_JA, X86_JBE);
|
||||
COND_SEL(BPF_S_JMP_JGE_X, X86_JAE, X86_JB);
|
||||
COND_SEL(BPF_S_JMP_JEQ_X, X86_JE, X86_JNE);
|
||||
COND_SEL(BPF_S_JMP_JSET_X,X86_JNE, X86_JE);
|
||||
|
||||
cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i];
|
||||
t_offset = addrs[i + filter[i].jt] - addrs[i];
|
||||
|
||||
/* same targets, can avoid doing the test :) */
|
||||
if (filter[i].jt == filter[i].jf) {
|
||||
EMIT_JMP(t_offset);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (filter[i].code) {
|
||||
case BPF_S_JMP_JGT_X:
|
||||
case BPF_S_JMP_JGE_X:
|
||||
case BPF_S_JMP_JEQ_X:
|
||||
seen |= SEEN_XREG;
|
||||
EMIT2(0x39, 0xd8); /* cmp %ebx,%eax */
|
||||
break;
|
||||
case BPF_S_JMP_JSET_X:
|
||||
seen |= SEEN_XREG;
|
||||
EMIT2(0x85, 0xd8); /* test %ebx,%eax */
|
||||
break;
|
||||
case BPF_S_JMP_JEQ_K:
|
||||
if (K == 0) {
|
||||
EMIT2(0x85, 0xc0); /* test %eax,%eax */
|
||||
break;
|
||||
}
|
||||
case BPF_S_JMP_JGT_K:
|
||||
case BPF_S_JMP_JGE_K:
|
||||
if (K <= 127)
|
||||
EMIT3(0x83, 0xf8, K); /* cmp imm8,%eax */
|
||||
else
|
||||
EMIT1_off32(0x3d, K); /* cmp imm32,%eax */
|
||||
break;
|
||||
case BPF_S_JMP_JSET_K:
|
||||
if (K <= 0xFF)
|
||||
EMIT2(0xa8, K); /* test imm8,%al */
|
||||
else if (!(K & 0xFFFF00FF))
|
||||
EMIT3(0xf6, 0xc4, K >> 8); /* test imm8,%ah */
|
||||
else if (K <= 0xFFFF) {
|
||||
EMIT2(0x66, 0xa9); /* test imm16,%ax */
|
||||
EMIT(K, 2);
|
||||
} else {
|
||||
EMIT1_off32(0xa9, K); /* test imm32,%eax */
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (filter[i].jt != 0) {
|
||||
if (filter[i].jf)
|
||||
t_offset += is_near(f_offset) ? 2 : 6;
|
||||
EMIT_COND_JMP(t_op, t_offset);
|
||||
if (filter[i].jf)
|
||||
EMIT_JMP(f_offset);
|
||||
break;
|
||||
}
|
||||
EMIT_COND_JMP(f_op, f_offset);
|
||||
break;
|
||||
default:
|
||||
/* hmm, too complex filter, give up with jit compiler */
|
||||
goto out;
|
||||
}
|
||||
ilen = prog - temp;
|
||||
if (image) {
|
||||
if (unlikely(proglen + ilen > oldproglen)) {
|
||||
pr_err("bpb_jit_compile fatal error\n");
|
||||
kfree(addrs);
|
||||
module_free(NULL, image);
|
||||
return;
|
||||
}
|
||||
memcpy(image + proglen, temp, ilen);
|
||||
}
|
||||
proglen += ilen;
|
||||
addrs[i] = proglen;
|
||||
prog = temp;
|
||||
}
|
||||
/* last bpf instruction is always a RET :
|
||||
* use it to give the cleanup instruction(s) addr
|
||||
*/
|
||||
cleanup_addr = proglen - 1; /* ret */
|
||||
if (seen)
|
||||
cleanup_addr -= 1; /* leaveq */
|
||||
if (seen & SEEN_XREG)
|
||||
cleanup_addr -= 4; /* mov -8(%rbp),%rbx */
|
||||
|
||||
if (image) {
|
||||
WARN_ON(proglen != oldproglen);
|
||||
break;
|
||||
}
|
||||
if (proglen == oldproglen) {
|
||||
image = module_alloc(max_t(unsigned int,
|
||||
proglen,
|
||||
sizeof(struct work_struct)));
|
||||
if (!image)
|
||||
goto out;
|
||||
}
|
||||
oldproglen = proglen;
|
||||
}
|
||||
if (bpf_jit_enable > 1)
|
||||
pr_err("flen=%d proglen=%u pass=%d image=%p\n",
|
||||
flen, proglen, pass, image);
|
||||
|
||||
if (image) {
|
||||
if (bpf_jit_enable > 1)
|
||||
print_hex_dump(KERN_ERR, "JIT code: ", DUMP_PREFIX_ADDRESS,
|
||||
16, 1, image, proglen, false);
|
||||
|
||||
bpf_flush_icache(image, image + proglen);
|
||||
|
||||
fp->bpf_func = (void *)image;
|
||||
}
|
||||
out:
|
||||
kfree(addrs);
|
||||
return;
|
||||
}
|
||||
|
||||
static void jit_free_defer(struct work_struct *arg)
|
||||
{
|
||||
module_free(NULL, arg);
|
||||
}
|
||||
|
||||
/* run from softirq, we must use a work_struct to call
|
||||
* module_free() from process context
|
||||
*/
|
||||
void bpf_jit_free(struct sk_filter *fp)
|
||||
{
|
||||
if (fp->bpf_func != sk_run_filter) {
|
||||
struct work_struct *work = (struct work_struct *)fp->bpf_func;
|
||||
|
||||
INIT_WORK(work, jit_free_defer);
|
||||
schedule_work(work);
|
||||
}
|
||||
}
|
|
@ -68,6 +68,8 @@ source "drivers/watchdog/Kconfig"
|
|||
|
||||
source "drivers/ssb/Kconfig"
|
||||
|
||||
source "drivers/bcma/Kconfig"
|
||||
|
||||
source "drivers/mfd/Kconfig"
|
||||
|
||||
source "drivers/regulator/Kconfig"
|
||||
|
|
|
@ -110,6 +110,7 @@ obj-$(CONFIG_HID) += hid/
|
|||
obj-$(CONFIG_PPC_PS3) += ps3/
|
||||
obj-$(CONFIG_OF) += of/
|
||||
obj-$(CONFIG_SSB) += ssb/
|
||||
obj-$(CONFIG_BCMA) += bcma/
|
||||
obj-$(CONFIG_VHOST_NET) += vhost/
|
||||
obj-$(CONFIG_VLYNQ) += vlynq/
|
||||
obj-$(CONFIG_STAGING) += staging/
|
||||
|
|
|
@ -1469,10 +1469,7 @@ if (eni_boards) printk(KERN_INFO "loss: %ld\n",ENI_DEV(eni_boards)->lost);
|
|||
|
||||
static void bug_int(struct atm_dev *dev,unsigned long reason)
|
||||
{
|
||||
struct eni_dev *eni_dev;
|
||||
|
||||
DPRINTK(">bug_int\n");
|
||||
eni_dev = ENI_DEV(dev);
|
||||
if (reason & MID_DMA_ERR_ACK)
|
||||
printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - DMA "
|
||||
"error\n",dev->number);
|
||||
|
@ -1900,7 +1897,6 @@ static void eni_close(struct atm_vcc *vcc)
|
|||
|
||||
static int eni_open(struct atm_vcc *vcc)
|
||||
{
|
||||
struct eni_dev *eni_dev;
|
||||
struct eni_vcc *eni_vcc;
|
||||
int error;
|
||||
short vpi = vcc->vpi;
|
||||
|
@ -1910,7 +1906,6 @@ static int eni_open(struct atm_vcc *vcc)
|
|||
EVENT("eni_open\n",0,0);
|
||||
if (!test_bit(ATM_VF_PARTIAL,&vcc->flags))
|
||||
vcc->dev_data = NULL;
|
||||
eni_dev = ENI_DEV(vcc->dev);
|
||||
if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC)
|
||||
set_bit(ATM_VF_ADDR,&vcc->flags);
|
||||
if (vcc->qos.aal != ATM_AAL0 && vcc->qos.aal != ATM_AAL5)
|
||||
|
|
|
@ -1801,7 +1801,7 @@ return_host_buffers:
|
|||
next_rbrq_entry:
|
||||
he_dev->rbrq_head = (struct he_rbrq *)
|
||||
((unsigned long) he_dev->rbrq_base |
|
||||
RBRQ_MASK(++he_dev->rbrq_head));
|
||||
RBRQ_MASK(he_dev->rbrq_head + 1));
|
||||
|
||||
}
|
||||
read_unlock(&vcc_sklist_lock);
|
||||
|
@ -1884,7 +1884,7 @@ next_tbrq_entry:
|
|||
pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status));
|
||||
he_dev->tbrq_head = (struct he_tbrq *)
|
||||
((unsigned long) he_dev->tbrq_base |
|
||||
TBRQ_MASK(++he_dev->tbrq_head));
|
||||
TBRQ_MASK(he_dev->tbrq_head + 1));
|
||||
}
|
||||
|
||||
if (updated) {
|
||||
|
|
|
@ -1261,14 +1261,13 @@ idt77252_rx_raw(struct idt77252_dev *card)
|
|||
PCI_DMA_FROMDEVICE);
|
||||
|
||||
while (head != tail) {
|
||||
unsigned int vpi, vci, pti;
|
||||
unsigned int vpi, vci;
|
||||
u32 header;
|
||||
|
||||
header = le32_to_cpu(*(u32 *) &queue->data[0]);
|
||||
|
||||
vpi = (header & ATM_HDR_VPI_MASK) >> ATM_HDR_VPI_SHIFT;
|
||||
vci = (header & ATM_HDR_VCI_MASK) >> ATM_HDR_VCI_SHIFT;
|
||||
pti = (header & ATM_HDR_PTI_MASK) >> ATM_HDR_PTI_SHIFT;
|
||||
|
||||
#ifdef CONFIG_ATM_IDT77252_DEBUG
|
||||
if (debug & DBG_RAW_CELL) {
|
||||
|
@ -2709,53 +2708,10 @@ idt77252_proc_read(struct atm_dev *dev, loff_t * pos, char *page)
|
|||
static void
|
||||
idt77252_collect_stat(struct idt77252_dev *card)
|
||||
{
|
||||
u32 cdc, vpec, icc;
|
||||
(void) readl(SAR_REG_CDC);
|
||||
(void) readl(SAR_REG_VPEC);
|
||||
(void) readl(SAR_REG_ICC);
|
||||
|
||||
cdc = readl(SAR_REG_CDC);
|
||||
vpec = readl(SAR_REG_VPEC);
|
||||
icc = readl(SAR_REG_ICC);
|
||||
|
||||
#ifdef NOTDEF
|
||||
printk("%s:", card->name);
|
||||
|
||||
if (cdc & 0x7f0000) {
|
||||
char *s = "";
|
||||
|
||||
printk(" [");
|
||||
if (cdc & (1 << 22)) {
|
||||
printk("%sRM ID", s);
|
||||
s = " | ";
|
||||
}
|
||||
if (cdc & (1 << 21)) {
|
||||
printk("%sCON TAB", s);
|
||||
s = " | ";
|
||||
}
|
||||
if (cdc & (1 << 20)) {
|
||||
printk("%sNO FB", s);
|
||||
s = " | ";
|
||||
}
|
||||
if (cdc & (1 << 19)) {
|
||||
printk("%sOAM CRC", s);
|
||||
s = " | ";
|
||||
}
|
||||
if (cdc & (1 << 18)) {
|
||||
printk("%sRM CRC", s);
|
||||
s = " | ";
|
||||
}
|
||||
if (cdc & (1 << 17)) {
|
||||
printk("%sRM FIFO", s);
|
||||
s = " | ";
|
||||
}
|
||||
if (cdc & (1 << 16)) {
|
||||
printk("%sRX FIFO", s);
|
||||
s = " | ";
|
||||
}
|
||||
printk("]");
|
||||
}
|
||||
|
||||
printk(" CDC %04x, VPEC %04x, ICC: %04x\n",
|
||||
cdc & 0xffff, vpec & 0xffff, icc & 0xffff);
|
||||
#endif
|
||||
}
|
||||
|
||||
static irqreturn_t
|
||||
|
|
|
@ -613,7 +613,6 @@ static int ia_que_tx (IADEV *iadev) {
|
|||
struct sk_buff *skb;
|
||||
int num_desc;
|
||||
struct atm_vcc *vcc;
|
||||
struct ia_vcc *iavcc;
|
||||
num_desc = ia_avail_descs(iadev);
|
||||
|
||||
while (num_desc && (skb = skb_dequeue(&iadev->tx_backlog))) {
|
||||
|
@ -627,7 +626,6 @@ static int ia_que_tx (IADEV *iadev) {
|
|||
printk("Free the SKB on closed vci %d \n", vcc->vci);
|
||||
break;
|
||||
}
|
||||
iavcc = INPH_IA_VCC(vcc);
|
||||
if (ia_pkt_tx (vcc, skb)) {
|
||||
skb_queue_head(&iadev->tx_backlog, skb);
|
||||
}
|
||||
|
@ -823,8 +821,6 @@ static void IaFrontEndIntr(IADEV *iadev) {
|
|||
volatile IA_SUNI *suni;
|
||||
volatile ia_mb25_t *mb25;
|
||||
volatile suni_pm7345_t *suni_pm7345;
|
||||
u32 intr_status;
|
||||
u_int frmr_intr;
|
||||
|
||||
if(iadev->phy_type & FE_25MBIT_PHY) {
|
||||
mb25 = (ia_mb25_t*)iadev->phy;
|
||||
|
@ -832,18 +828,18 @@ static void IaFrontEndIntr(IADEV *iadev) {
|
|||
} else if (iadev->phy_type & FE_DS3_PHY) {
|
||||
suni_pm7345 = (suni_pm7345_t *)iadev->phy;
|
||||
/* clear FRMR interrupts */
|
||||
frmr_intr = suni_pm7345->suni_ds3_frm_intr_stat;
|
||||
(void) suni_pm7345->suni_ds3_frm_intr_stat;
|
||||
iadev->carrier_detect =
|
||||
Boolean(!(suni_pm7345->suni_ds3_frm_stat & SUNI_DS3_LOSV));
|
||||
} else if (iadev->phy_type & FE_E3_PHY ) {
|
||||
suni_pm7345 = (suni_pm7345_t *)iadev->phy;
|
||||
frmr_intr = suni_pm7345->suni_e3_frm_maint_intr_ind;
|
||||
(void) suni_pm7345->suni_e3_frm_maint_intr_ind;
|
||||
iadev->carrier_detect =
|
||||
Boolean(!(suni_pm7345->suni_e3_frm_fram_intr_ind_stat&SUNI_E3_LOS));
|
||||
}
|
||||
else {
|
||||
suni = (IA_SUNI *)iadev->phy;
|
||||
intr_status = suni->suni_rsop_status & 0xff;
|
||||
(void) suni->suni_rsop_status;
|
||||
iadev->carrier_detect = Boolean(!(suni->suni_rsop_status & SUNI_LOSV));
|
||||
}
|
||||
if (iadev->carrier_detect)
|
||||
|
@ -2660,7 +2656,6 @@ static void ia_close(struct atm_vcc *vcc)
|
|||
|
||||
static int ia_open(struct atm_vcc *vcc)
|
||||
{
|
||||
IADEV *iadev;
|
||||
struct ia_vcc *ia_vcc;
|
||||
int error;
|
||||
if (!test_bit(ATM_VF_PARTIAL,&vcc->flags))
|
||||
|
@ -2668,7 +2663,6 @@ static int ia_open(struct atm_vcc *vcc)
|
|||
IF_EVENT(printk("ia: not partially allocated resources\n");)
|
||||
vcc->dev_data = NULL;
|
||||
}
|
||||
iadev = INPH_IA_DEV(vcc->dev);
|
||||
if (vcc->vci != ATM_VPI_UNSPEC && vcc->vpi != ATM_VCI_UNSPEC)
|
||||
{
|
||||
IF_EVENT(printk("iphase open: unspec part\n");)
|
||||
|
@ -3052,11 +3046,9 @@ static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) {
|
|||
static int ia_send(struct atm_vcc *vcc, struct sk_buff *skb)
|
||||
{
|
||||
IADEV *iadev;
|
||||
struct ia_vcc *iavcc;
|
||||
unsigned long flags;
|
||||
|
||||
iadev = INPH_IA_DEV(vcc->dev);
|
||||
iavcc = INPH_IA_VCC(vcc);
|
||||
if ((!skb)||(skb->len>(iadev->tx_buf_sz-sizeof(struct cpcs_trailer))))
|
||||
{
|
||||
if (!skb)
|
||||
|
|
|
@ -527,7 +527,6 @@ static int flash_upgrade(struct solos_card *card, int chip)
|
|||
{
|
||||
const struct firmware *fw;
|
||||
const char *fw_name;
|
||||
uint32_t data32 = 0;
|
||||
int blocksize = 0;
|
||||
int numblocks = 0;
|
||||
int offset;
|
||||
|
@ -576,7 +575,7 @@ static int flash_upgrade(struct solos_card *card, int chip)
|
|||
|
||||
dev_info(&card->dev->dev, "Changing FPGA to Update mode\n");
|
||||
iowrite32(1, card->config_regs + FPGA_MODE);
|
||||
data32 = ioread32(card->config_regs + FPGA_MODE);
|
||||
(void) ioread32(card->config_regs + FPGA_MODE);
|
||||
|
||||
/* Set mode to Chip Erase */
|
||||
if(chip == 0 || chip == 2)
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
config BCMA_POSSIBLE
|
||||
bool
|
||||
depends on HAS_IOMEM && HAS_DMA
|
||||
default y
|
||||
|
||||
menu "Broadcom specific AMBA"
|
||||
depends on BCMA_POSSIBLE
|
||||
|
||||
config BCMA
|
||||
tristate "BCMA support"
|
||||
depends on BCMA_POSSIBLE
|
||||
help
|
||||
Bus driver for Broadcom specific Advanced Microcontroller Bus
|
||||
Architecture.
|
||||
|
||||
config BCMA_HOST_PCI_POSSIBLE
|
||||
bool
|
||||
depends on BCMA && PCI = y
|
||||
default y
|
||||
|
||||
config BCMA_HOST_PCI
|
||||
bool "Support for BCMA on PCI-host bus"
|
||||
depends on BCMA_HOST_PCI_POSSIBLE
|
||||
|
||||
config BCMA_DEBUG
|
||||
bool "BCMA debugging"
|
||||
depends on BCMA
|
||||
help
|
||||
This turns on additional debugging messages.
|
||||
|
||||
If unsure, say N
|
||||
|
||||
endmenu
|
|
@ -0,0 +1,7 @@
|
|||
bcma-y += main.o scan.o core.o
|
||||
bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
|
||||
bcma-y += driver_pci.o
|
||||
bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
|
||||
obj-$(CONFIG_BCMA) += bcma.o
|
||||
|
||||
ccflags-$(CONFIG_BCMA_DEBUG) := -DDEBUG
|
|
@ -0,0 +1,19 @@
|
|||
Broadcom introduced new bus as replacement for older SSB. It is based on AMBA,
|
||||
however from programming point of view there is nothing AMBA specific we use.
|
||||
|
||||
Standard AMBA drivers are platform specific, have hardcoded addresses and use
|
||||
AMBA standard fields like CID and PID.
|
||||
|
||||
In case of Broadcom's cards every device consists of:
|
||||
1) Broadcom specific AMBA device. It is put on AMBA bus, but can not be treated
|
||||
as standard AMBA device. Reading it's CID or PID can cause machine lockup.
|
||||
2) AMBA standard devices called ports or wrappers. They have CIDs (AMBA_CID)
|
||||
and PIDs (0x103BB369), but we do not use that info for anything. One of that
|
||||
devices is used for managing Broadcom specific core.
|
||||
|
||||
Addresses of AMBA devices are not hardcoded in driver and have to be read from
|
||||
EPROM.
|
||||
|
||||
In this situation we decided to introduce separated bus. It can contain up to
|
||||
16 devices identified by Broadcom specific fields: manufacturer, id, revision
|
||||
and class.
|
|
@ -0,0 +1,3 @@
|
|||
- Interrupts
|
||||
- Defines for PCI core driver
|
||||
- Create kernel Documentation (use info from README)
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef LINUX_BCMA_PRIVATE_H_
|
||||
#define LINUX_BCMA_PRIVATE_H_
|
||||
|
||||
#ifndef pr_fmt
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
#endif
|
||||
|
||||
#include <linux/bcma/bcma.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#define BCMA_CORE_SIZE 0x1000
|
||||
|
||||
struct bcma_bus;
|
||||
|
||||
/* main.c */
|
||||
extern int bcma_bus_register(struct bcma_bus *bus);
|
||||
extern void bcma_bus_unregister(struct bcma_bus *bus);
|
||||
|
||||
/* scan.c */
|
||||
int bcma_bus_scan(struct bcma_bus *bus);
|
||||
|
||||
#ifdef CONFIG_BCMA_HOST_PCI
|
||||
/* host_pci.c */
|
||||
extern int __init bcma_host_pci_init(void);
|
||||
extern void __exit bcma_host_pci_exit(void);
|
||||
#endif /* CONFIG_BCMA_HOST_PCI */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Broadcom specific AMBA
|
||||
* Core ops
|
||||
*
|
||||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
#include "bcma_private.h"
|
||||
#include <linux/bcma/bcma.h>
|
||||
|
||||
bool bcma_core_is_enabled(struct bcma_device *core)
|
||||
{
|
||||
if ((bcma_aread32(core, BCMA_IOCTL) & (BCMA_IOCTL_CLK | BCMA_IOCTL_FGC))
|
||||
!= BCMA_IOCTL_CLK)
|
||||
return false;
|
||||
if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcma_core_is_enabled);
|
||||
|
||||
static void bcma_core_disable(struct bcma_device *core, u32 flags)
|
||||
{
|
||||
if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET)
|
||||
return;
|
||||
|
||||
bcma_awrite32(core, BCMA_IOCTL, flags);
|
||||
bcma_aread32(core, BCMA_IOCTL);
|
||||
udelay(10);
|
||||
|
||||
bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
int bcma_core_enable(struct bcma_device *core, u32 flags)
|
||||
{
|
||||
bcma_core_disable(core, flags);
|
||||
|
||||
bcma_awrite32(core, BCMA_IOCTL, (BCMA_IOCTL_CLK | BCMA_IOCTL_FGC | flags));
|
||||
bcma_aread32(core, BCMA_IOCTL);
|
||||
|
||||
bcma_awrite32(core, BCMA_RESET_CTL, 0);
|
||||
udelay(1);
|
||||
|
||||
bcma_awrite32(core, BCMA_IOCTL, (BCMA_IOCTL_CLK | flags));
|
||||
bcma_aread32(core, BCMA_IOCTL);
|
||||
udelay(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcma_core_enable);
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Broadcom specific AMBA
|
||||
* ChipCommon core driver
|
||||
*
|
||||
* Copyright 2005, Broadcom Corporation
|
||||
* Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
|
||||
*
|
||||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
#include "bcma_private.h"
|
||||
#include <linux/bcma/bcma.h>
|
||||
|
||||
static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset,
|
||||
u32 mask, u32 value)
|
||||
{
|
||||
value &= mask;
|
||||
value |= bcma_cc_read32(cc, offset) & ~mask;
|
||||
bcma_cc_write32(cc, offset, value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
|
||||
{
|
||||
if (cc->core->id.rev >= 11)
|
||||
cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
|
||||
cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
|
||||
if (cc->core->id.rev >= 35)
|
||||
cc->capabilities_ext = bcma_cc_read32(cc, BCMA_CC_CAP_EXT);
|
||||
|
||||
if (cc->core->id.rev >= 20) {
|
||||
bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, 0);
|
||||
bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, 0);
|
||||
}
|
||||
|
||||
if (cc->capabilities & BCMA_CC_CAP_PMU)
|
||||
bcma_pmu_init(cc);
|
||||
if (cc->capabilities & BCMA_CC_CAP_PCTL)
|
||||
pr_err("Power control not implemented!\n");
|
||||
}
|
||||
|
||||
/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
|
||||
void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks)
|
||||
{
|
||||
/* instant NMI */
|
||||
bcma_cc_write32(cc, BCMA_CC_WATCHDOG, ticks);
|
||||
}
|
||||
|
||||
void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value)
|
||||
{
|
||||
bcma_cc_write32_masked(cc, BCMA_CC_IRQMASK, mask, value);
|
||||
}
|
||||
|
||||
u32 bcma_chipco_irq_status(struct bcma_drv_cc *cc, u32 mask)
|
||||
{
|
||||
return bcma_cc_read32(cc, BCMA_CC_IRQSTAT) & mask;
|
||||
}
|
||||
|
||||
u32 bcma_chipco_gpio_in(struct bcma_drv_cc *cc, u32 mask)
|
||||
{
|
||||
return bcma_cc_read32(cc, BCMA_CC_GPIOIN) & mask;
|
||||
}
|
||||
|
||||
u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value)
|
||||
{
|
||||
return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value);
|
||||
}
|
||||
|
||||
u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value)
|
||||
{
|
||||
return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value);
|
||||
}
|
||||
|
||||
u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value)
|
||||
{
|
||||
return bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control);
|
||||
|
||||
u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value)
|
||||
{
|
||||
return bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value);
|
||||
}
|
||||
|
||||
u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value)
|
||||
{
|
||||
return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Broadcom specific AMBA
|
||||
* ChipCommon Power Management Unit driver
|
||||
*
|
||||
* Copyright 2009, Michael Buesch <mb@bu3sch.de>
|
||||
* Copyright 2007, Broadcom Corporation
|
||||
*
|
||||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
#include "bcma_private.h"
|
||||
#include <linux/bcma/bcma.h>
|
||||
|
||||
static void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
|
||||
u32 offset, u32 mask, u32 set)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR);
|
||||
bcma_cc_write32(cc, BCMA_CC_CHIPCTL_ADDR, offset);
|
||||
bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR);
|
||||
value = bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA);
|
||||
value &= mask;
|
||||
value |= set;
|
||||
bcma_cc_write32(cc, BCMA_CC_CHIPCTL_DATA, value);
|
||||
bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA);
|
||||
}
|
||||
|
||||
static void bcma_pmu_pll_init(struct bcma_drv_cc *cc)
|
||||
{
|
||||
struct bcma_bus *bus = cc->core->bus;
|
||||
|
||||
switch (bus->chipinfo.id) {
|
||||
case 0x4313:
|
||||
case 0x4331:
|
||||
case 43224:
|
||||
case 43225:
|
||||
break;
|
||||
default:
|
||||
pr_err("PLL init unknown for device 0x%04X\n",
|
||||
bus->chipinfo.id);
|
||||
}
|
||||
}
|
||||
|
||||
static void bcma_pmu_resources_init(struct bcma_drv_cc *cc)
|
||||
{
|
||||
struct bcma_bus *bus = cc->core->bus;
|
||||
u32 min_msk = 0, max_msk = 0;
|
||||
|
||||
switch (bus->chipinfo.id) {
|
||||
case 0x4313:
|
||||
min_msk = 0x200D;
|
||||
max_msk = 0xFFFF;
|
||||
break;
|
||||
case 43224:
|
||||
break;
|
||||
default:
|
||||
pr_err("PMU resource config unknown for device 0x%04X\n",
|
||||
bus->chipinfo.id);
|
||||
}
|
||||
|
||||
/* Set the resource masks. */
|
||||
if (min_msk)
|
||||
bcma_cc_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk);
|
||||
if (max_msk)
|
||||
bcma_cc_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk);
|
||||
}
|
||||
|
||||
void bcma_pmu_swreg_init(struct bcma_drv_cc *cc)
|
||||
{
|
||||
struct bcma_bus *bus = cc->core->bus;
|
||||
|
||||
switch (bus->chipinfo.id) {
|
||||
case 0x4313:
|
||||
case 0x4331:
|
||||
case 43224:
|
||||
break;
|
||||
default:
|
||||
pr_err("PMU switch/regulators init unknown for device "
|
||||
"0x%04X\n", bus->chipinfo.id);
|
||||
}
|
||||
}
|
||||
|
||||
void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
|
||||
{
|
||||
struct bcma_bus *bus = cc->core->bus;
|
||||
|
||||
switch (bus->chipinfo.id) {
|
||||
case 0x4313:
|
||||
bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7);
|
||||
break;
|
||||
case 0x4331:
|
||||
pr_err("Enabling Ext PA lines not implemented\n");
|
||||
break;
|
||||
case 43224:
|
||||
if (bus->chipinfo.rev == 0) {
|
||||
pr_err("Workarounds for 43224 rev 0 not fully "
|
||||
"implemented\n");
|
||||
bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0);
|
||||
} else {
|
||||
bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pr_err("Workarounds unknown for device 0x%04X\n",
|
||||
bus->chipinfo.id);
|
||||
}
|
||||
}
|
||||
|
||||
void bcma_pmu_init(struct bcma_drv_cc *cc)
|
||||
{
|
||||
u32 pmucap;
|
||||
|
||||
pmucap = bcma_cc_read32(cc, BCMA_CC_PMU_CAP);
|
||||
cc->pmu.rev = (pmucap & BCMA_CC_PMU_CAP_REVISION);
|
||||
|
||||
pr_debug("Found rev %u PMU (capabilities 0x%08X)\n", cc->pmu.rev,
|
||||
pmucap);
|
||||
|
||||
if (cc->pmu.rev == 1)
|
||||
bcma_cc_mask32(cc, BCMA_CC_PMU_CTL,
|
||||
~BCMA_CC_PMU_CTL_NOILPONW);
|
||||
else
|
||||
bcma_cc_set32(cc, BCMA_CC_PMU_CTL,
|
||||
BCMA_CC_PMU_CTL_NOILPONW);
|
||||
|
||||
if (cc->core->id.id == 0x4329 && cc->core->id.rev == 2)
|
||||
pr_err("Fix for 4329b0 bad LPOM state not implemented!\n");
|
||||
|
||||
bcma_pmu_pll_init(cc);
|
||||
bcma_pmu_resources_init(cc);
|
||||
bcma_pmu_swreg_init(cc);
|
||||
bcma_pmu_workarounds(cc);
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* Broadcom specific AMBA
|
||||
* PCI Core
|
||||
*
|
||||
* Copyright 2005, Broadcom Corporation
|
||||
* Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
|
||||
*
|
||||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
#include "bcma_private.h"
|
||||
#include <linux/bcma/bcma.h>
|
||||
|
||||
/**************************************************
|
||||
* R/W ops.
|
||||
**************************************************/
|
||||
|
||||
static u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address)
|
||||
{
|
||||
pcicore_write32(pc, 0x130, address);
|
||||
pcicore_read32(pc, 0x130);
|
||||
return pcicore_read32(pc, 0x134);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data)
|
||||
{
|
||||
pcicore_write32(pc, 0x130, address);
|
||||
pcicore_read32(pc, 0x130);
|
||||
pcicore_write32(pc, 0x134, data);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy)
|
||||
{
|
||||
const u16 mdio_control = 0x128;
|
||||
const u16 mdio_data = 0x12C;
|
||||
u32 v;
|
||||
int i;
|
||||
|
||||
v = (1 << 30); /* Start of Transaction */
|
||||
v |= (1 << 28); /* Write Transaction */
|
||||
v |= (1 << 17); /* Turnaround */
|
||||
v |= (0x1F << 18);
|
||||
v |= (phy << 4);
|
||||
pcicore_write32(pc, mdio_data, v);
|
||||
|
||||
udelay(10);
|
||||
for (i = 0; i < 200; i++) {
|
||||
v = pcicore_read32(pc, mdio_control);
|
||||
if (v & 0x100 /* Trans complete */)
|
||||
break;
|
||||
msleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address)
|
||||
{
|
||||
const u16 mdio_control = 0x128;
|
||||
const u16 mdio_data = 0x12C;
|
||||
int max_retries = 10;
|
||||
u16 ret = 0;
|
||||
u32 v;
|
||||
int i;
|
||||
|
||||
v = 0x80; /* Enable Preamble Sequence */
|
||||
v |= 0x2; /* MDIO Clock Divisor */
|
||||
pcicore_write32(pc, mdio_control, v);
|
||||
|
||||
if (pc->core->id.rev >= 10) {
|
||||
max_retries = 200;
|
||||
bcma_pcie_mdio_set_phy(pc, device);
|
||||
}
|
||||
|
||||
v = (1 << 30); /* Start of Transaction */
|
||||
v |= (1 << 29); /* Read Transaction */
|
||||
v |= (1 << 17); /* Turnaround */
|
||||
if (pc->core->id.rev < 10)
|
||||
v |= (u32)device << 22;
|
||||
v |= (u32)address << 18;
|
||||
pcicore_write32(pc, mdio_data, v);
|
||||
/* Wait for the device to complete the transaction */
|
||||
udelay(10);
|
||||
for (i = 0; i < max_retries; i++) {
|
||||
v = pcicore_read32(pc, mdio_control);
|
||||
if (v & 0x100 /* Trans complete */) {
|
||||
udelay(10);
|
||||
ret = pcicore_read32(pc, mdio_data);
|
||||
break;
|
||||
}
|
||||
msleep(1);
|
||||
}
|
||||
pcicore_write32(pc, mdio_control, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device,
|
||||
u8 address, u16 data)
|
||||
{
|
||||
const u16 mdio_control = 0x128;
|
||||
const u16 mdio_data = 0x12C;
|
||||
int max_retries = 10;
|
||||
u32 v;
|
||||
int i;
|
||||
|
||||
v = 0x80; /* Enable Preamble Sequence */
|
||||
v |= 0x2; /* MDIO Clock Divisor */
|
||||
pcicore_write32(pc, mdio_control, v);
|
||||
|
||||
if (pc->core->id.rev >= 10) {
|
||||
max_retries = 200;
|
||||
bcma_pcie_mdio_set_phy(pc, device);
|
||||
}
|
||||
|
||||
v = (1 << 30); /* Start of Transaction */
|
||||
v |= (1 << 28); /* Write Transaction */
|
||||
v |= (1 << 17); /* Turnaround */
|
||||
if (pc->core->id.rev < 10)
|
||||
v |= (u32)device << 22;
|
||||
v |= (u32)address << 18;
|
||||
v |= data;
|
||||
pcicore_write32(pc, mdio_data, v);
|
||||
/* Wait for the device to complete the transaction */
|
||||
udelay(10);
|
||||
for (i = 0; i < max_retries; i++) {
|
||||
v = pcicore_read32(pc, mdio_control);
|
||||
if (v & 0x100 /* Trans complete */)
|
||||
break;
|
||||
msleep(1);
|
||||
}
|
||||
pcicore_write32(pc, mdio_control, 0);
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Workarounds.
|
||||
**************************************************/
|
||||
|
||||
static u8 bcma_pcicore_polarity_workaround(struct bcma_drv_pci *pc)
|
||||
{
|
||||
return (bcma_pcie_read(pc, 0x204) & 0x10) ? 0xC0 : 0x80;
|
||||
}
|
||||
|
||||
static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc)
|
||||
{
|
||||
const u8 serdes_pll_device = 0x1D;
|
||||
const u8 serdes_rx_device = 0x1F;
|
||||
u16 tmp;
|
||||
|
||||
bcma_pcie_mdio_write(pc, serdes_rx_device, 1 /* Control */,
|
||||
bcma_pcicore_polarity_workaround(pc));
|
||||
tmp = bcma_pcie_mdio_read(pc, serdes_pll_device, 1 /* Control */);
|
||||
if (tmp & 0x4000)
|
||||
bcma_pcie_mdio_write(pc, serdes_pll_device, 1, tmp & ~0x4000);
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Init.
|
||||
**************************************************/
|
||||
|
||||
void bcma_core_pci_init(struct bcma_drv_pci *pc)
|
||||
{
|
||||
bcma_pcicore_serdes_workaround(pc);
|
||||
}
|
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* Broadcom specific AMBA
|
||||
* PCI Host
|
||||
*
|
||||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
#include "bcma_private.h"
|
||||
#include <linux/bcma/bcma.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
static void bcma_host_pci_switch_core(struct bcma_device *core)
|
||||
{
|
||||
pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN,
|
||||
core->addr);
|
||||
pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN2,
|
||||
core->wrap);
|
||||
core->bus->mapped_core = core;
|
||||
pr_debug("Switched to core: 0x%X\n", core->id.id);
|
||||
}
|
||||
|
||||
static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset)
|
||||
{
|
||||
if (core->bus->mapped_core != core)
|
||||
bcma_host_pci_switch_core(core);
|
||||
return ioread8(core->bus->mmio + offset);
|
||||
}
|
||||
|
||||
static u16 bcma_host_pci_read16(struct bcma_device *core, u16 offset)
|
||||
{
|
||||
if (core->bus->mapped_core != core)
|
||||
bcma_host_pci_switch_core(core);
|
||||
return ioread16(core->bus->mmio + offset);
|
||||
}
|
||||
|
||||
static u32 bcma_host_pci_read32(struct bcma_device *core, u16 offset)
|
||||
{
|
||||
if (core->bus->mapped_core != core)
|
||||
bcma_host_pci_switch_core(core);
|
||||
return ioread32(core->bus->mmio + offset);
|
||||
}
|
||||
|
||||
static void bcma_host_pci_write8(struct bcma_device *core, u16 offset,
|
||||
u8 value)
|
||||
{
|
||||
if (core->bus->mapped_core != core)
|
||||
bcma_host_pci_switch_core(core);
|
||||
iowrite8(value, core->bus->mmio + offset);
|
||||
}
|
||||
|
||||
static void bcma_host_pci_write16(struct bcma_device *core, u16 offset,
|
||||
u16 value)
|
||||
{
|
||||
if (core->bus->mapped_core != core)
|
||||
bcma_host_pci_switch_core(core);
|
||||
iowrite16(value, core->bus->mmio + offset);
|
||||
}
|
||||
|
||||
static void bcma_host_pci_write32(struct bcma_device *core, u16 offset,
|
||||
u32 value)
|
||||
{
|
||||
if (core->bus->mapped_core != core)
|
||||
bcma_host_pci_switch_core(core);
|
||||
iowrite32(value, core->bus->mmio + offset);
|
||||
}
|
||||
|
||||
static u32 bcma_host_pci_aread32(struct bcma_device *core, u16 offset)
|
||||
{
|
||||
if (core->bus->mapped_core != core)
|
||||
bcma_host_pci_switch_core(core);
|
||||
return ioread32(core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset);
|
||||
}
|
||||
|
||||
static void bcma_host_pci_awrite32(struct bcma_device *core, u16 offset,
|
||||
u32 value)
|
||||
{
|
||||
if (core->bus->mapped_core != core)
|
||||
bcma_host_pci_switch_core(core);
|
||||
iowrite32(value, core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset);
|
||||
}
|
||||
|
||||
const struct bcma_host_ops bcma_host_pci_ops = {
|
||||
.read8 = bcma_host_pci_read8,
|
||||
.read16 = bcma_host_pci_read16,
|
||||
.read32 = bcma_host_pci_read32,
|
||||
.write8 = bcma_host_pci_write8,
|
||||
.write16 = bcma_host_pci_write16,
|
||||
.write32 = bcma_host_pci_write32,
|
||||
.aread32 = bcma_host_pci_aread32,
|
||||
.awrite32 = bcma_host_pci_awrite32,
|
||||
};
|
||||
|
||||
static int bcma_host_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
struct bcma_bus *bus;
|
||||
int err = -ENOMEM;
|
||||
const char *name;
|
||||
u32 val;
|
||||
|
||||
/* Alloc */
|
||||
bus = kzalloc(sizeof(*bus), GFP_KERNEL);
|
||||
if (!bus)
|
||||
goto out;
|
||||
|
||||
/* Basic PCI configuration */
|
||||
err = pci_enable_device(dev);
|
||||
if (err)
|
||||
goto err_kfree_bus;
|
||||
|
||||
name = dev_name(&dev->dev);
|
||||
if (dev->driver && dev->driver->name)
|
||||
name = dev->driver->name;
|
||||
err = pci_request_regions(dev, name);
|
||||
if (err)
|
||||
goto err_pci_disable;
|
||||
pci_set_master(dev);
|
||||
|
||||
/* Disable the RETRY_TIMEOUT register (0x41) to keep
|
||||
* PCI Tx retries from interfering with C3 CPU state */
|
||||
pci_read_config_dword(dev, 0x40, &val);
|
||||
if ((val & 0x0000ff00) != 0)
|
||||
pci_write_config_dword(dev, 0x40, val & 0xffff00ff);
|
||||
|
||||
/* SSB needed additional powering up, do we have any AMBA PCI cards? */
|
||||
if (!pci_is_pcie(dev))
|
||||
pr_err("PCI card detected, report problems.\n");
|
||||
|
||||
/* Map MMIO */
|
||||
err = -ENOMEM;
|
||||
bus->mmio = pci_iomap(dev, 0, ~0UL);
|
||||
if (!bus->mmio)
|
||||
goto err_pci_release_regions;
|
||||
|
||||
/* Host specific */
|
||||
bus->host_pci = dev;
|
||||
bus->hosttype = BCMA_HOSTTYPE_PCI;
|
||||
bus->ops = &bcma_host_pci_ops;
|
||||
|
||||
/* Register */
|
||||
err = bcma_bus_register(bus);
|
||||
if (err)
|
||||
goto err_pci_unmap_mmio;
|
||||
|
||||
pci_set_drvdata(dev, bus);
|
||||
|
||||
out:
|
||||
return err;
|
||||
|
||||
err_pci_unmap_mmio:
|
||||
pci_iounmap(dev, bus->mmio);
|
||||
err_pci_release_regions:
|
||||
pci_release_regions(dev);
|
||||
err_pci_disable:
|
||||
pci_disable_device(dev);
|
||||
err_kfree_bus:
|
||||
kfree(bus);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void bcma_host_pci_remove(struct pci_dev *dev)
|
||||
{
|
||||
struct bcma_bus *bus = pci_get_drvdata(dev);
|
||||
|
||||
bcma_bus_unregister(bus);
|
||||
pci_iounmap(dev, bus->mmio);
|
||||
pci_release_regions(dev);
|
||||
pci_disable_device(dev);
|
||||
kfree(bus);
|
||||
pci_set_drvdata(dev, NULL);
|
||||
}
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
|
||||
{ 0, },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl);
|
||||
|
||||
static struct pci_driver bcma_pci_bridge_driver = {
|
||||
.name = "bcma-pci-bridge",
|
||||
.id_table = bcma_pci_bridge_tbl,
|
||||
.probe = bcma_host_pci_probe,
|
||||
.remove = bcma_host_pci_remove,
|
||||
};
|
||||
|
||||
int __init bcma_host_pci_init(void)
|
||||
{
|
||||
return pci_register_driver(&bcma_pci_bridge_driver);
|
||||
}
|
||||
|
||||
void __exit bcma_host_pci_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&bcma_pci_bridge_driver);
|
||||
}
|
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
* Broadcom specific AMBA
|
||||
* Bus subsystem
|
||||
*
|
||||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
#include "bcma_private.h"
|
||||
#include <linux/bcma/bcma.h>
|
||||
|
||||
MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int bcma_bus_match(struct device *dev, struct device_driver *drv);
|
||||
static int bcma_device_probe(struct device *dev);
|
||||
static int bcma_device_remove(struct device *dev);
|
||||
|
||||
static ssize_t manuf_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct bcma_device *core = container_of(dev, struct bcma_device, dev);
|
||||
return sprintf(buf, "0x%03X\n", core->id.manuf);
|
||||
}
|
||||
static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct bcma_device *core = container_of(dev, struct bcma_device, dev);
|
||||
return sprintf(buf, "0x%03X\n", core->id.id);
|
||||
}
|
||||
static ssize_t rev_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct bcma_device *core = container_of(dev, struct bcma_device, dev);
|
||||
return sprintf(buf, "0x%02X\n", core->id.rev);
|
||||
}
|
||||
static ssize_t class_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct bcma_device *core = container_of(dev, struct bcma_device, dev);
|
||||
return sprintf(buf, "0x%X\n", core->id.class);
|
||||
}
|
||||
static struct device_attribute bcma_device_attrs[] = {
|
||||
__ATTR_RO(manuf),
|
||||
__ATTR_RO(id),
|
||||
__ATTR_RO(rev),
|
||||
__ATTR_RO(class),
|
||||
__ATTR_NULL,
|
||||
};
|
||||
|
||||
static struct bus_type bcma_bus_type = {
|
||||
.name = "bcma",
|
||||
.match = bcma_bus_match,
|
||||
.probe = bcma_device_probe,
|
||||
.remove = bcma_device_remove,
|
||||
.dev_attrs = bcma_device_attrs,
|
||||
};
|
||||
|
||||
static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
|
||||
{
|
||||
struct bcma_device *core;
|
||||
|
||||
list_for_each_entry(core, &bus->cores, list) {
|
||||
if (core->id.id == coreid)
|
||||
return core;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void bcma_release_core_dev(struct device *dev)
|
||||
{
|
||||
struct bcma_device *core = container_of(dev, struct bcma_device, dev);
|
||||
kfree(core);
|
||||
}
|
||||
|
||||
static int bcma_register_cores(struct bcma_bus *bus)
|
||||
{
|
||||
struct bcma_device *core;
|
||||
int err, dev_id = 0;
|
||||
|
||||
list_for_each_entry(core, &bus->cores, list) {
|
||||
/* We support that cores ourself */
|
||||
switch (core->id.id) {
|
||||
case BCMA_CORE_CHIPCOMMON:
|
||||
case BCMA_CORE_PCI:
|
||||
case BCMA_CORE_PCIE:
|
||||
continue;
|
||||
}
|
||||
|
||||
core->dev.release = bcma_release_core_dev;
|
||||
core->dev.bus = &bcma_bus_type;
|
||||
dev_set_name(&core->dev, "bcma%d:%d", 0/*bus->num*/, dev_id);
|
||||
|
||||
switch (bus->hosttype) {
|
||||
case BCMA_HOSTTYPE_PCI:
|
||||
core->dev.parent = &bus->host_pci->dev;
|
||||
break;
|
||||
case BCMA_HOSTTYPE_NONE:
|
||||
case BCMA_HOSTTYPE_SDIO:
|
||||
break;
|
||||
}
|
||||
|
||||
err = device_register(&core->dev);
|
||||
if (err) {
|
||||
pr_err("Could not register dev for core 0x%03X\n",
|
||||
core->id.id);
|
||||
continue;
|
||||
}
|
||||
core->dev_registered = true;
|
||||
dev_id++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bcma_unregister_cores(struct bcma_bus *bus)
|
||||
{
|
||||
struct bcma_device *core;
|
||||
|
||||
list_for_each_entry(core, &bus->cores, list) {
|
||||
if (core->dev_registered)
|
||||
device_unregister(&core->dev);
|
||||
}
|
||||
}
|
||||
|
||||
int bcma_bus_register(struct bcma_bus *bus)
|
||||
{
|
||||
int err;
|
||||
struct bcma_device *core;
|
||||
|
||||
/* Scan for devices (cores) */
|
||||
err = bcma_bus_scan(bus);
|
||||
if (err) {
|
||||
pr_err("Failed to scan: %d\n", err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Init CC core */
|
||||
core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
|
||||
if (core) {
|
||||
bus->drv_cc.core = core;
|
||||
bcma_core_chipcommon_init(&bus->drv_cc);
|
||||
}
|
||||
|
||||
/* Init PCIE core */
|
||||
core = bcma_find_core(bus, BCMA_CORE_PCIE);
|
||||
if (core) {
|
||||
bus->drv_pci.core = core;
|
||||
bcma_core_pci_init(&bus->drv_pci);
|
||||
}
|
||||
|
||||
/* Register found cores */
|
||||
bcma_register_cores(bus);
|
||||
|
||||
pr_info("Bus registered\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcma_bus_register);
|
||||
|
||||
void bcma_bus_unregister(struct bcma_bus *bus)
|
||||
{
|
||||
bcma_unregister_cores(bus);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcma_bus_unregister);
|
||||
|
||||
int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
|
||||
{
|
||||
drv->drv.name = drv->name;
|
||||
drv->drv.bus = &bcma_bus_type;
|
||||
drv->drv.owner = owner;
|
||||
|
||||
return driver_register(&drv->drv);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__bcma_driver_register);
|
||||
|
||||
void bcma_driver_unregister(struct bcma_driver *drv)
|
||||
{
|
||||
driver_unregister(&drv->drv);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcma_driver_unregister);
|
||||
|
||||
static int bcma_bus_match(struct device *dev, struct device_driver *drv)
|
||||
{
|
||||
struct bcma_device *core = container_of(dev, struct bcma_device, dev);
|
||||
struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
|
||||
const struct bcma_device_id *cid = &core->id;
|
||||
const struct bcma_device_id *did;
|
||||
|
||||
for (did = adrv->id_table; did->manuf || did->id || did->rev; did++) {
|
||||
if ((did->manuf == cid->manuf || did->manuf == BCMA_ANY_MANUF) &&
|
||||
(did->id == cid->id || did->id == BCMA_ANY_ID) &&
|
||||
(did->rev == cid->rev || did->rev == BCMA_ANY_REV) &&
|
||||
(did->class == cid->class || did->class == BCMA_ANY_CLASS))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcma_device_probe(struct device *dev)
|
||||
{
|
||||
struct bcma_device *core = container_of(dev, struct bcma_device, dev);
|
||||
struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
|
||||
drv);
|
||||
int err = 0;
|
||||
|
||||
if (adrv->probe)
|
||||
err = adrv->probe(core);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int bcma_device_remove(struct device *dev)
|
||||
{
|
||||
struct bcma_device *core = container_of(dev, struct bcma_device, dev);
|
||||
struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
|
||||
drv);
|
||||
|
||||
if (adrv->remove)
|
||||
adrv->remove(core);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init bcma_modinit(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bus_register(&bcma_bus_type);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
#ifdef CONFIG_BCMA_HOST_PCI
|
||||
err = bcma_host_pci_init();
|
||||
if (err) {
|
||||
pr_err("PCI host initialization failed\n");
|
||||
err = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return err;
|
||||
}
|
||||
fs_initcall(bcma_modinit);
|
||||
|
||||
static void __exit bcma_modexit(void)
|
||||
{
|
||||
#ifdef CONFIG_BCMA_HOST_PCI
|
||||
bcma_host_pci_exit();
|
||||
#endif
|
||||
bus_unregister(&bcma_bus_type);
|
||||
}
|
||||
module_exit(bcma_modexit)
|
|
@ -0,0 +1,360 @@
|
|||
/*
|
||||
* Broadcom specific AMBA
|
||||
* Bus scanning
|
||||
*
|
||||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
#include "scan.h"
|
||||
#include "bcma_private.h"
|
||||
|
||||
#include <linux/bcma/bcma.h>
|
||||
#include <linux/bcma/bcma_regs.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
struct bcma_device_id_name {
|
||||
u16 id;
|
||||
const char *name;
|
||||
};
|
||||
struct bcma_device_id_name bcma_device_names[] = {
|
||||
{ BCMA_CORE_OOB_ROUTER, "OOB Router" },
|
||||
{ BCMA_CORE_INVALID, "Invalid" },
|
||||
{ BCMA_CORE_CHIPCOMMON, "ChipCommon" },
|
||||
{ BCMA_CORE_ILINE20, "ILine 20" },
|
||||
{ BCMA_CORE_SRAM, "SRAM" },
|
||||
{ BCMA_CORE_SDRAM, "SDRAM" },
|
||||
{ BCMA_CORE_PCI, "PCI" },
|
||||
{ BCMA_CORE_MIPS, "MIPS" },
|
||||
{ BCMA_CORE_ETHERNET, "Fast Ethernet" },
|
||||
{ BCMA_CORE_V90, "V90" },
|
||||
{ BCMA_CORE_USB11_HOSTDEV, "USB 1.1 Hostdev" },
|
||||
{ BCMA_CORE_ADSL, "ADSL" },
|
||||
{ BCMA_CORE_ILINE100, "ILine 100" },
|
||||
{ BCMA_CORE_IPSEC, "IPSEC" },
|
||||
{ BCMA_CORE_UTOPIA, "UTOPIA" },
|
||||
{ BCMA_CORE_PCMCIA, "PCMCIA" },
|
||||
{ BCMA_CORE_INTERNAL_MEM, "Internal Memory" },
|
||||
{ BCMA_CORE_MEMC_SDRAM, "MEMC SDRAM" },
|
||||
{ BCMA_CORE_OFDM, "OFDM" },
|
||||
{ BCMA_CORE_EXTIF, "EXTIF" },
|
||||
{ BCMA_CORE_80211, "IEEE 802.11" },
|
||||
{ BCMA_CORE_PHY_A, "PHY A" },
|
||||
{ BCMA_CORE_PHY_B, "PHY B" },
|
||||
{ BCMA_CORE_PHY_G, "PHY G" },
|
||||
{ BCMA_CORE_MIPS_3302, "MIPS 3302" },
|
||||
{ BCMA_CORE_USB11_HOST, "USB 1.1 Host" },
|
||||
{ BCMA_CORE_USB11_DEV, "USB 1.1 Device" },
|
||||
{ BCMA_CORE_USB20_HOST, "USB 2.0 Host" },
|
||||
{ BCMA_CORE_USB20_DEV, "USB 2.0 Device" },
|
||||
{ BCMA_CORE_SDIO_HOST, "SDIO Host" },
|
||||
{ BCMA_CORE_ROBOSWITCH, "Roboswitch" },
|
||||
{ BCMA_CORE_PARA_ATA, "PATA" },
|
||||
{ BCMA_CORE_SATA_XORDMA, "SATA XOR-DMA" },
|
||||
{ BCMA_CORE_ETHERNET_GBIT, "GBit Ethernet" },
|
||||
{ BCMA_CORE_PCIE, "PCIe" },
|
||||
{ BCMA_CORE_PHY_N, "PHY N" },
|
||||
{ BCMA_CORE_SRAM_CTL, "SRAM Controller" },
|
||||
{ BCMA_CORE_MINI_MACPHY, "Mini MACPHY" },
|
||||
{ BCMA_CORE_ARM_1176, "ARM 1176" },
|
||||
{ BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" },
|
||||
{ BCMA_CORE_PHY_LP, "PHY LP" },
|
||||
{ BCMA_CORE_PMU, "PMU" },
|
||||
{ BCMA_CORE_PHY_SSN, "PHY SSN" },
|
||||
{ BCMA_CORE_SDIO_DEV, "SDIO Device" },
|
||||
{ BCMA_CORE_ARM_CM3, "ARM CM3" },
|
||||
{ BCMA_CORE_PHY_HT, "PHY HT" },
|
||||
{ BCMA_CORE_MIPS_74K, "MIPS 74K" },
|
||||
{ BCMA_CORE_MAC_GBIT, "GBit MAC" },
|
||||
{ BCMA_CORE_DDR12_MEM_CTL, "DDR1/DDR2 Memory Controller" },
|
||||
{ BCMA_CORE_PCIE_RC, "PCIe Root Complex" },
|
||||
{ BCMA_CORE_OCP_OCP_BRIDGE, "OCP to OCP Bridge" },
|
||||
{ BCMA_CORE_SHARED_COMMON, "Common Shared" },
|
||||
{ BCMA_CORE_OCP_AHB_BRIDGE, "OCP to AHB Bridge" },
|
||||
{ BCMA_CORE_SPI_HOST, "SPI Host" },
|
||||
{ BCMA_CORE_I2S, "I2S" },
|
||||
{ BCMA_CORE_SDR_DDR1_MEM_CTL, "SDR/DDR1 Memory Controller" },
|
||||
{ BCMA_CORE_SHIM, "SHIM" },
|
||||
{ BCMA_CORE_DEFAULT, "Default" },
|
||||
};
|
||||
const char *bcma_device_name(struct bcma_device_id *id)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (id->manuf == BCMA_MANUF_BCM) {
|
||||
for (i = 0; i < ARRAY_SIZE(bcma_device_names); i++) {
|
||||
if (bcma_device_names[i].id == id->id)
|
||||
return bcma_device_names[i].name;
|
||||
}
|
||||
}
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
static u32 bcma_scan_read32(struct bcma_bus *bus, u8 current_coreidx,
|
||||
u16 offset)
|
||||
{
|
||||
return readl(bus->mmio + offset);
|
||||
}
|
||||
|
||||
static void bcma_scan_switch_core(struct bcma_bus *bus, u32 addr)
|
||||
{
|
||||
if (bus->hosttype == BCMA_HOSTTYPE_PCI)
|
||||
pci_write_config_dword(bus->host_pci, BCMA_PCI_BAR0_WIN,
|
||||
addr);
|
||||
}
|
||||
|
||||
static u32 bcma_erom_get_ent(struct bcma_bus *bus, u32 **eromptr)
|
||||
{
|
||||
u32 ent = readl(*eromptr);
|
||||
(*eromptr)++;
|
||||
return ent;
|
||||
}
|
||||
|
||||
static void bcma_erom_push_ent(u32 **eromptr)
|
||||
{
|
||||
(*eromptr)--;
|
||||
}
|
||||
|
||||
static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 **eromptr)
|
||||
{
|
||||
u32 ent = bcma_erom_get_ent(bus, eromptr);
|
||||
if (!(ent & SCAN_ER_VALID))
|
||||
return -ENOENT;
|
||||
if ((ent & SCAN_ER_TAG) != SCAN_ER_TAG_CI)
|
||||
return -ENOENT;
|
||||
return ent;
|
||||
}
|
||||
|
||||
static bool bcma_erom_is_end(struct bcma_bus *bus, u32 **eromptr)
|
||||
{
|
||||
u32 ent = bcma_erom_get_ent(bus, eromptr);
|
||||
bcma_erom_push_ent(eromptr);
|
||||
return (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID));
|
||||
}
|
||||
|
||||
static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 **eromptr)
|
||||
{
|
||||
u32 ent = bcma_erom_get_ent(bus, eromptr);
|
||||
bcma_erom_push_ent(eromptr);
|
||||
return (((ent & SCAN_ER_VALID)) &&
|
||||
((ent & SCAN_ER_TAGX) == SCAN_ER_TAG_ADDR) &&
|
||||
((ent & SCAN_ADDR_TYPE) == SCAN_ADDR_TYPE_BRIDGE));
|
||||
}
|
||||
|
||||
static void bcma_erom_skip_component(struct bcma_bus *bus, u32 **eromptr)
|
||||
{
|
||||
u32 ent;
|
||||
while (1) {
|
||||
ent = bcma_erom_get_ent(bus, eromptr);
|
||||
if ((ent & SCAN_ER_VALID) &&
|
||||
((ent & SCAN_ER_TAG) == SCAN_ER_TAG_CI))
|
||||
break;
|
||||
if (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID))
|
||||
break;
|
||||
}
|
||||
bcma_erom_push_ent(eromptr);
|
||||
}
|
||||
|
||||
static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 **eromptr)
|
||||
{
|
||||
u32 ent = bcma_erom_get_ent(bus, eromptr);
|
||||
if (!(ent & SCAN_ER_VALID))
|
||||
return -ENOENT;
|
||||
if ((ent & SCAN_ER_TAG) != SCAN_ER_TAG_MP)
|
||||
return -ENOENT;
|
||||
return ent;
|
||||
}
|
||||
|
||||
static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 **eromptr,
|
||||
u32 type, u8 port)
|
||||
{
|
||||
u32 addrl, addrh, sizel, sizeh = 0;
|
||||
u32 size;
|
||||
|
||||
u32 ent = bcma_erom_get_ent(bus, eromptr);
|
||||
if ((!(ent & SCAN_ER_VALID)) ||
|
||||
((ent & SCAN_ER_TAGX) != SCAN_ER_TAG_ADDR) ||
|
||||
((ent & SCAN_ADDR_TYPE) != type) ||
|
||||
(((ent & SCAN_ADDR_PORT) >> SCAN_ADDR_PORT_SHIFT) != port)) {
|
||||
bcma_erom_push_ent(eromptr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
addrl = ent & SCAN_ADDR_ADDR;
|
||||
if (ent & SCAN_ADDR_AG32)
|
||||
addrh = bcma_erom_get_ent(bus, eromptr);
|
||||
else
|
||||
addrh = 0;
|
||||
|
||||
if ((ent & SCAN_ADDR_SZ) == SCAN_ADDR_SZ_SZD) {
|
||||
size = bcma_erom_get_ent(bus, eromptr);
|
||||
sizel = size & SCAN_SIZE_SZ;
|
||||
if (size & SCAN_SIZE_SG32)
|
||||
sizeh = bcma_erom_get_ent(bus, eromptr);
|
||||
} else
|
||||
sizel = SCAN_ADDR_SZ_BASE <<
|
||||
((ent & SCAN_ADDR_SZ) >> SCAN_ADDR_SZ_SHIFT);
|
||||
|
||||
return addrl;
|
||||
}
|
||||
|
||||
int bcma_bus_scan(struct bcma_bus *bus)
|
||||
{
|
||||
u32 erombase;
|
||||
u32 __iomem *eromptr, *eromend;
|
||||
|
||||
s32 cia, cib;
|
||||
u8 ports[2], wrappers[2];
|
||||
|
||||
s32 tmp;
|
||||
u8 i, j;
|
||||
|
||||
int err;
|
||||
|
||||
INIT_LIST_HEAD(&bus->cores);
|
||||
bus->nr_cores = 0;
|
||||
|
||||
bcma_scan_switch_core(bus, BCMA_ADDR_BASE);
|
||||
|
||||
tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID);
|
||||
bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
|
||||
bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
|
||||
bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
|
||||
|
||||
erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
|
||||
eromptr = bus->mmio;
|
||||
eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
|
||||
|
||||
bcma_scan_switch_core(bus, erombase);
|
||||
|
||||
while (eromptr < eromend) {
|
||||
struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL);
|
||||
if (!core)
|
||||
return -ENOMEM;
|
||||
INIT_LIST_HEAD(&core->list);
|
||||
core->bus = bus;
|
||||
|
||||
/* get CIs */
|
||||
cia = bcma_erom_get_ci(bus, &eromptr);
|
||||
if (cia < 0) {
|
||||
bcma_erom_push_ent(&eromptr);
|
||||
if (bcma_erom_is_end(bus, &eromptr))
|
||||
break;
|
||||
err= -EILSEQ;
|
||||
goto out;
|
||||
}
|
||||
cib = bcma_erom_get_ci(bus, &eromptr);
|
||||
if (cib < 0) {
|
||||
err= -EILSEQ;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* parse CIs */
|
||||
core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT;
|
||||
core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT;
|
||||
core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT;
|
||||
ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT;
|
||||
ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT;
|
||||
wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT;
|
||||
wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT;
|
||||
core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT;
|
||||
|
||||
if (((core->id.manuf == BCMA_MANUF_ARM) &&
|
||||
(core->id.id == 0xFFF)) ||
|
||||
(ports[1] == 0)) {
|
||||
bcma_erom_skip_component(bus, &eromptr);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check if component is a core at all */
|
||||
if (wrappers[0] + wrappers[1] == 0) {
|
||||
/* we could save addrl of the router
|
||||
if (cid == BCMA_CORE_OOB_ROUTER)
|
||||
*/
|
||||
bcma_erom_skip_component(bus, &eromptr);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bcma_erom_is_bridge(bus, &eromptr)) {
|
||||
bcma_erom_skip_component(bus, &eromptr);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* get & parse master ports */
|
||||
for (i = 0; i < ports[0]; i++) {
|
||||
u32 mst_port_d = bcma_erom_get_mst_port(bus, &eromptr);
|
||||
if (mst_port_d < 0) {
|
||||
err= -EILSEQ;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* get & parse slave ports */
|
||||
for (i = 0; i < ports[1]; i++) {
|
||||
for (j = 0; ; j++) {
|
||||
tmp = bcma_erom_get_addr_desc(bus, &eromptr,
|
||||
SCAN_ADDR_TYPE_SLAVE, i);
|
||||
if (tmp < 0) {
|
||||
/* no more entries for port _i_ */
|
||||
/* pr_debug("erom: slave port %d "
|
||||
* "has %d descriptors\n", i, j); */
|
||||
break;
|
||||
} else {
|
||||
if (i == 0 && j == 0)
|
||||
core->addr = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* get & parse master wrappers */
|
||||
for (i = 0; i < wrappers[0]; i++) {
|
||||
for (j = 0; ; j++) {
|
||||
tmp = bcma_erom_get_addr_desc(bus, &eromptr,
|
||||
SCAN_ADDR_TYPE_MWRAP, i);
|
||||
if (tmp < 0) {
|
||||
/* no more entries for port _i_ */
|
||||
/* pr_debug("erom: master wrapper %d "
|
||||
* "has %d descriptors\n", i, j); */
|
||||
break;
|
||||
} else {
|
||||
if (i == 0 && j == 0)
|
||||
core->wrap = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* get & parse slave wrappers */
|
||||
for (i = 0; i < wrappers[1]; i++) {
|
||||
u8 hack = (ports[1] == 1) ? 0 : 1;
|
||||
for (j = 0; ; j++) {
|
||||
tmp = bcma_erom_get_addr_desc(bus, &eromptr,
|
||||
SCAN_ADDR_TYPE_SWRAP, i + hack);
|
||||
if (tmp < 0) {
|
||||
/* no more entries for port _i_ */
|
||||
/* pr_debug("erom: master wrapper %d "
|
||||
* has %d descriptors\n", i, j); */
|
||||
break;
|
||||
} else {
|
||||
if (wrappers[0] == 0 && !i && !j)
|
||||
core->wrap = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pr_info("Core %d found: %s "
|
||||
"(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
|
||||
bus->nr_cores, bcma_device_name(&core->id),
|
||||
core->id.manuf, core->id.id, core->id.rev,
|
||||
core->id.class);
|
||||
|
||||
core->core_index = bus->nr_cores++;
|
||||
list_add(&core->list, &bus->cores);
|
||||
continue;
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
#ifndef BCMA_SCAN_H_
|
||||
#define BCMA_SCAN_H_
|
||||
|
||||
#define BCMA_ADDR_BASE 0x18000000
|
||||
#define BCMA_WRAP_BASE 0x18100000
|
||||
|
||||
#define SCAN_ER_VALID 0x00000001
|
||||
#define SCAN_ER_TAGX 0x00000006 /* we have to ignore 0x8 bit when checking tag for SCAN_ER_TAG_ADDR */
|
||||
#define SCAN_ER_TAG 0x0000000E
|
||||
#define SCAN_ER_TAG_CI 0x00000000
|
||||
#define SCAN_ER_TAG_MP 0x00000002
|
||||
#define SCAN_ER_TAG_ADDR 0x00000004
|
||||
#define SCAN_ER_TAG_END 0x0000000E
|
||||
#define SCAN_ER_BAD 0xFFFFFFFF
|
||||
|
||||
#define SCAN_CIA_CLASS 0x000000F0
|
||||
#define SCAN_CIA_CLASS_SHIFT 4
|
||||
#define SCAN_CIA_ID 0x000FFF00
|
||||
#define SCAN_CIA_ID_SHIFT 8
|
||||
#define SCAN_CIA_MANUF 0xFFF00000
|
||||
#define SCAN_CIA_MANUF_SHIFT 20
|
||||
|
||||
#define SCAN_CIB_NMP 0x000001F0
|
||||
#define SCAN_CIB_NMP_SHIFT 4
|
||||
#define SCAN_CIB_NSP 0x00003E00
|
||||
#define SCAN_CIB_NSP_SHIFT 9
|
||||
#define SCAN_CIB_NMW 0x0007C000
|
||||
#define SCAN_CIB_NMW_SHIFT 14
|
||||
#define SCAN_CIB_NSW 0x00F80000
|
||||
#define SCAN_CIB_NSW_SHIFT 17
|
||||
#define SCAN_CIB_REV 0xFF000000
|
||||
#define SCAN_CIB_REV_SHIFT 24
|
||||
|
||||
#define SCAN_ADDR_AG32 0x00000008
|
||||
#define SCAN_ADDR_SZ 0x00000030
|
||||
#define SCAN_ADDR_SZ_SHIFT 4
|
||||
#define SCAN_ADDR_SZ_4K 0x00000000
|
||||
#define SCAN_ADDR_SZ_8K 0x00000010
|
||||
#define SCAN_ADDR_SZ_16K 0x00000020
|
||||
#define SCAN_ADDR_SZ_SZD 0x00000030
|
||||
#define SCAN_ADDR_TYPE 0x000000C0
|
||||
#define SCAN_ADDR_TYPE_SLAVE 0x00000000
|
||||
#define SCAN_ADDR_TYPE_BRIDGE 0x00000040
|
||||
#define SCAN_ADDR_TYPE_SWRAP 0x00000080
|
||||
#define SCAN_ADDR_TYPE_MWRAP 0x000000C0
|
||||
#define SCAN_ADDR_PORT 0x00000F00
|
||||
#define SCAN_ADDR_PORT_SHIFT 8
|
||||
#define SCAN_ADDR_ADDR 0xFFFFF000
|
||||
|
||||
#define SCAN_ADDR_SZ_BASE 0x00001000 /* 4KB */
|
||||
|
||||
#define SCAN_SIZE_SZ_ALIGN 0x00000FFF
|
||||
#define SCAN_SIZE_SZ 0xFFFFF000
|
||||
#define SCAN_SIZE_SG32 0x00000008
|
||||
|
||||
#endif /* BCMA_SCAN_H_ */
|
|
@ -188,7 +188,7 @@ config BT_MRVL
|
|||
The core driver to support Marvell Bluetooth devices.
|
||||
|
||||
This driver is required if you want to support
|
||||
Marvell Bluetooth devices, such as 8688.
|
||||
Marvell Bluetooth devices, such as 8688/8787.
|
||||
|
||||
Say Y here to compile Marvell Bluetooth driver
|
||||
into the kernel or say M to compile it as module.
|
||||
|
@ -201,7 +201,7 @@ config BT_MRVL_SDIO
|
|||
The driver for Marvell Bluetooth chipsets with SDIO interface.
|
||||
|
||||
This driver is required if you want to use Marvell Bluetooth
|
||||
devices with SDIO interface. Currently only SD8688 chipset is
|
||||
devices with SDIO interface. Currently SD8688/SD8787 chipsets are
|
||||
supported.
|
||||
|
||||
Say Y here to compile support for Marvell BT-over-SDIO driver
|
||||
|
|
|
@ -62,6 +62,7 @@ static struct usb_device_id ath3k_table[] = {
|
|||
|
||||
/* Atheros AR3011 with sflash firmware*/
|
||||
{ USB_DEVICE(0x0CF3, 0x3002) },
|
||||
{ USB_DEVICE(0x13d3, 0x3304) },
|
||||
|
||||
/* Atheros AR9285 Malbec with sflash firmware */
|
||||
{ USB_DEVICE(0x03F0, 0x311D) },
|
||||
|
@ -138,9 +139,6 @@ static int ath3k_load_firmware(struct usb_device *udev,
|
|||
count -= size;
|
||||
}
|
||||
|
||||
kfree(send_buf);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
kfree(send_buf);
|
||||
return err;
|
||||
|
|
|
@ -49,15 +49,59 @@
|
|||
static u8 user_rmmod;
|
||||
static u8 sdio_ireg;
|
||||
|
||||
static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = {
|
||||
.cfg = 0x03,
|
||||
.host_int_mask = 0x04,
|
||||
.host_intstatus = 0x05,
|
||||
.card_status = 0x20,
|
||||
.sq_read_base_addr_a0 = 0x10,
|
||||
.sq_read_base_addr_a1 = 0x11,
|
||||
.card_fw_status0 = 0x40,
|
||||
.card_fw_status1 = 0x41,
|
||||
.card_rx_len = 0x42,
|
||||
.card_rx_unit = 0x43,
|
||||
.io_port_0 = 0x00,
|
||||
.io_port_1 = 0x01,
|
||||
.io_port_2 = 0x02,
|
||||
};
|
||||
static const struct btmrvl_sdio_card_reg btmrvl_reg_8787 = {
|
||||
.cfg = 0x00,
|
||||
.host_int_mask = 0x02,
|
||||
.host_intstatus = 0x03,
|
||||
.card_status = 0x30,
|
||||
.sq_read_base_addr_a0 = 0x40,
|
||||
.sq_read_base_addr_a1 = 0x41,
|
||||
.card_revision = 0x5c,
|
||||
.card_fw_status0 = 0x60,
|
||||
.card_fw_status1 = 0x61,
|
||||
.card_rx_len = 0x62,
|
||||
.card_rx_unit = 0x63,
|
||||
.io_port_0 = 0x78,
|
||||
.io_port_1 = 0x79,
|
||||
.io_port_2 = 0x7a,
|
||||
};
|
||||
|
||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = {
|
||||
.helper = "sd8688_helper.bin",
|
||||
.firmware = "sd8688.bin",
|
||||
.reg = &btmrvl_reg_8688,
|
||||
.sd_blksz_fw_dl = 64,
|
||||
};
|
||||
|
||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
|
||||
.helper = NULL,
|
||||
.firmware = "mrvl/sd8787_uapsta.bin",
|
||||
.reg = &btmrvl_reg_8787,
|
||||
.sd_blksz_fw_dl = 256,
|
||||
};
|
||||
|
||||
static const struct sdio_device_id btmrvl_sdio_ids[] = {
|
||||
/* Marvell SD8688 Bluetooth device */
|
||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105),
|
||||
.driver_data = (unsigned long) &btmrvl_sdio_sd6888 },
|
||||
/* Marvell SD8787 Bluetooth device */
|
||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A),
|
||||
.driver_data = (unsigned long) &btmrvl_sdio_sd8787 },
|
||||
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
@ -69,7 +113,7 @@ static int btmrvl_sdio_get_rx_unit(struct btmrvl_sdio_card *card)
|
|||
u8 reg;
|
||||
int ret;
|
||||
|
||||
reg = sdio_readb(card->func, CARD_RX_UNIT_REG, &ret);
|
||||
reg = sdio_readb(card->func, card->reg->card_rx_unit, &ret);
|
||||
if (!ret)
|
||||
card->rx_unit = reg;
|
||||
|
||||
|
@ -83,11 +127,11 @@ 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);
|
||||
fws0 = sdio_readb(card->func, card->reg->card_fw_status0, &ret);
|
||||
if (ret)
|
||||
return -EIO;
|
||||
|
||||
fws1 = sdio_readb(card->func, CARD_FW_STATUS1_REG, &ret);
|
||||
fws1 = sdio_readb(card->func, card->reg->card_fw_status1, &ret);
|
||||
if (ret)
|
||||
return -EIO;
|
||||
|
||||
|
@ -101,7 +145,7 @@ static int btmrvl_sdio_read_rx_len(struct btmrvl_sdio_card *card, u16 *dat)
|
|||
u8 reg;
|
||||
int ret;
|
||||
|
||||
reg = sdio_readb(card->func, CARD_RX_LEN_REG, &ret);
|
||||
reg = sdio_readb(card->func, card->reg->card_rx_len, &ret);
|
||||
if (!ret)
|
||||
*dat = (u16) reg << card->rx_unit;
|
||||
|
||||
|
@ -113,7 +157,7 @@ static int btmrvl_sdio_enable_host_int_mask(struct btmrvl_sdio_card *card,
|
|||
{
|
||||
int ret;
|
||||
|
||||
sdio_writeb(card->func, mask, HOST_INT_MASK_REG, &ret);
|
||||
sdio_writeb(card->func, mask, card->reg->host_int_mask, &ret);
|
||||
if (ret) {
|
||||
BT_ERR("Unable to enable the host interrupt!");
|
||||
ret = -EIO;
|
||||
|
@ -128,13 +172,13 @@ static int btmrvl_sdio_disable_host_int_mask(struct btmrvl_sdio_card *card,
|
|||
u8 host_int_mask;
|
||||
int ret;
|
||||
|
||||
host_int_mask = sdio_readb(card->func, HOST_INT_MASK_REG, &ret);
|
||||
host_int_mask = sdio_readb(card->func, card->reg->host_int_mask, &ret);
|
||||
if (ret)
|
||||
return -EIO;
|
||||
|
||||
host_int_mask &= ~mask;
|
||||
|
||||
sdio_writeb(card->func, host_int_mask, HOST_INT_MASK_REG, &ret);
|
||||
sdio_writeb(card->func, host_int_mask, card->reg->host_int_mask, &ret);
|
||||
if (ret < 0) {
|
||||
BT_ERR("Unable to disable the host interrupt!");
|
||||
return -EIO;
|
||||
|
@ -150,7 +194,7 @@ static int btmrvl_sdio_poll_card_status(struct btmrvl_sdio_card *card, u8 bits)
|
|||
int ret;
|
||||
|
||||
for (tries = 0; tries < MAX_POLL_TRIES * 1000; tries++) {
|
||||
status = sdio_readb(card->func, CARD_STATUS_REG, &ret);
|
||||
status = sdio_readb(card->func, card->reg->card_status, &ret);
|
||||
if (ret)
|
||||
goto failed;
|
||||
if ((status & bits) == bits)
|
||||
|
@ -299,7 +343,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
|
|||
u8 base0, base1;
|
||||
void *tmpfwbuf = NULL;
|
||||
u8 *fwbuf;
|
||||
u16 len;
|
||||
u16 len, blksz_dl = card->sd_blksz_fw_dl;
|
||||
int txlen = 0, tx_blocks = 0, count = 0;
|
||||
|
||||
ret = request_firmware(&fw_firmware, card->firmware,
|
||||
|
@ -345,7 +389,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
|
|||
|
||||
for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
|
||||
base0 = sdio_readb(card->func,
|
||||
SQ_READ_BASE_ADDRESS_A0_REG, &ret);
|
||||
card->reg->sq_read_base_addr_a0, &ret);
|
||||
if (ret) {
|
||||
BT_ERR("BASE0 register read failed:"
|
||||
" base0 = 0x%04X(%d)."
|
||||
|
@ -355,7 +399,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
|
|||
goto done;
|
||||
}
|
||||
base1 = sdio_readb(card->func,
|
||||
SQ_READ_BASE_ADDRESS_A1_REG, &ret);
|
||||
card->reg->sq_read_base_addr_a1, &ret);
|
||||
if (ret) {
|
||||
BT_ERR("BASE1 register read failed:"
|
||||
" base1 = 0x%04X(%d)."
|
||||
|
@ -403,20 +447,19 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
|
|||
if (firmwarelen - offset < txlen)
|
||||
txlen = firmwarelen - offset;
|
||||
|
||||
tx_blocks =
|
||||
(txlen + SDIO_BLOCK_SIZE - 1) / SDIO_BLOCK_SIZE;
|
||||
tx_blocks = (txlen + blksz_dl - 1) / blksz_dl;
|
||||
|
||||
memcpy(fwbuf, &firmware[offset], txlen);
|
||||
}
|
||||
|
||||
ret = sdio_writesb(card->func, card->ioport, fwbuf,
|
||||
tx_blocks * SDIO_BLOCK_SIZE);
|
||||
tx_blocks * blksz_dl);
|
||||
|
||||
if (ret < 0) {
|
||||
BT_ERR("FW download, writesb(%d) failed @%d",
|
||||
count, offset);
|
||||
sdio_writeb(card->func, HOST_CMD53_FIN, CONFIG_REG,
|
||||
&ret);
|
||||
sdio_writeb(card->func, HOST_CMD53_FIN,
|
||||
card->reg->cfg, &ret);
|
||||
if (ret)
|
||||
BT_ERR("writeb failed (CFG)");
|
||||
}
|
||||
|
@ -597,7 +640,7 @@ static void btmrvl_sdio_interrupt(struct sdio_func *func)
|
|||
|
||||
priv = card->priv;
|
||||
|
||||
ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret);
|
||||
ireg = sdio_readb(card->func, card->reg->host_intstatus, &ret);
|
||||
if (ret) {
|
||||
BT_ERR("sdio_readb: read int status register failed");
|
||||
return;
|
||||
|
@ -613,7 +656,7 @@ static void btmrvl_sdio_interrupt(struct sdio_func *func)
|
|||
|
||||
sdio_writeb(card->func, ~(ireg) & (DN_LD_HOST_INT_STATUS |
|
||||
UP_LD_HOST_INT_STATUS),
|
||||
HOST_INTSTATUS_REG, &ret);
|
||||
card->reg->host_intstatus, &ret);
|
||||
if (ret) {
|
||||
BT_ERR("sdio_writeb: clear int status register failed");
|
||||
return;
|
||||
|
@ -664,7 +707,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
|
|||
goto release_irq;
|
||||
}
|
||||
|
||||
reg = sdio_readb(func, IO_PORT_0_REG, &ret);
|
||||
reg = sdio_readb(func, card->reg->io_port_0, &ret);
|
||||
if (ret < 0) {
|
||||
ret = -EIO;
|
||||
goto release_irq;
|
||||
|
@ -672,7 +715,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
|
|||
|
||||
card->ioport = reg;
|
||||
|
||||
reg = sdio_readb(func, IO_PORT_1_REG, &ret);
|
||||
reg = sdio_readb(func, card->reg->io_port_1, &ret);
|
||||
if (ret < 0) {
|
||||
ret = -EIO;
|
||||
goto release_irq;
|
||||
|
@ -680,7 +723,7 @@ static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
|
|||
|
||||
card->ioport |= (reg << 8);
|
||||
|
||||
reg = sdio_readb(func, IO_PORT_2_REG, &ret);
|
||||
reg = sdio_readb(func, card->reg->io_port_2, &ret);
|
||||
if (ret < 0) {
|
||||
ret = -EIO;
|
||||
goto release_irq;
|
||||
|
@ -815,6 +858,8 @@ exit:
|
|||
static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 fws0;
|
||||
int pollnum = MAX_POLL_TRIES;
|
||||
|
||||
if (!card || !card->func) {
|
||||
BT_ERR("card or function is NULL!");
|
||||
|
@ -827,20 +872,36 @@ static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
|
|||
goto done;
|
||||
}
|
||||
|
||||
ret = btmrvl_sdio_download_helper(card);
|
||||
/* Check if other function driver is downloading the firmware */
|
||||
fws0 = sdio_readb(card->func, card->reg->card_fw_status0, &ret);
|
||||
if (ret) {
|
||||
BT_ERR("Failed to download helper!");
|
||||
BT_ERR("Failed to read FW downloading status!");
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
if (fws0) {
|
||||
BT_DBG("BT not the winner (%#x). Skip FW downloading", fws0);
|
||||
|
||||
if (btmrvl_sdio_download_fw_w_helper(card)) {
|
||||
BT_ERR("Failed to download firmware!");
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
/* Give other function more time to download the firmware */
|
||||
pollnum *= 10;
|
||||
} else {
|
||||
if (card->helper) {
|
||||
ret = btmrvl_sdio_download_helper(card);
|
||||
if (ret) {
|
||||
BT_ERR("Failed to download helper!");
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (btmrvl_sdio_download_fw_w_helper(card)) {
|
||||
BT_ERR("Failed to download firmware!");
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (btmrvl_sdio_verify_fw_download(card, MAX_POLL_TRIES)) {
|
||||
if (btmrvl_sdio_verify_fw_download(card, pollnum)) {
|
||||
BT_ERR("FW failed to be active in time!");
|
||||
ret = -ETIMEDOUT;
|
||||
goto done;
|
||||
|
@ -864,7 +925,7 @@ static int btmrvl_sdio_wakeup_fw(struct btmrvl_private *priv)
|
|||
|
||||
sdio_claim_host(card->func);
|
||||
|
||||
sdio_writeb(card->func, HOST_POWER_UP, CONFIG_REG, &ret);
|
||||
sdio_writeb(card->func, HOST_POWER_UP, card->reg->cfg, &ret);
|
||||
|
||||
sdio_release_host(card->func);
|
||||
|
||||
|
@ -893,8 +954,10 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
|
|||
|
||||
if (id->driver_data) {
|
||||
struct btmrvl_sdio_device *data = (void *) id->driver_data;
|
||||
card->helper = data->helper;
|
||||
card->helper = data->helper;
|
||||
card->firmware = data->firmware;
|
||||
card->reg = data->reg;
|
||||
card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;
|
||||
}
|
||||
|
||||
if (btmrvl_sdio_register_dev(card) < 0) {
|
||||
|
@ -1011,3 +1074,4 @@ MODULE_VERSION(VERSION);
|
|||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_FIRMWARE("sd8688_helper.bin");
|
||||
MODULE_FIRMWARE("sd8688.bin");
|
||||
MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
|
||||
|
|
|
@ -47,44 +47,46 @@
|
|||
/* Max retry number of CMD53 write */
|
||||
#define MAX_WRITE_IOMEM_RETRY 2
|
||||
|
||||
/* Host Control Registers */
|
||||
#define IO_PORT_0_REG 0x00
|
||||
#define IO_PORT_1_REG 0x01
|
||||
#define IO_PORT_2_REG 0x02
|
||||
/* register bitmasks */
|
||||
#define HOST_POWER_UP BIT(1)
|
||||
#define HOST_CMD53_FIN BIT(2)
|
||||
|
||||
#define CONFIG_REG 0x03
|
||||
#define HOST_POWER_UP BIT(1)
|
||||
#define HOST_CMD53_FIN BIT(2)
|
||||
#define HIM_DISABLE 0xff
|
||||
#define HIM_ENABLE (BIT(0) | BIT(1))
|
||||
|
||||
#define HOST_INT_MASK_REG 0x04
|
||||
#define HIM_DISABLE 0xff
|
||||
#define HIM_ENABLE (BIT(0) | BIT(1))
|
||||
#define UP_LD_HOST_INT_STATUS BIT(0)
|
||||
#define DN_LD_HOST_INT_STATUS BIT(1)
|
||||
|
||||
#define HOST_INTSTATUS_REG 0x05
|
||||
#define UP_LD_HOST_INT_STATUS BIT(0)
|
||||
#define DN_LD_HOST_INT_STATUS BIT(1)
|
||||
#define DN_LD_CARD_RDY BIT(0)
|
||||
#define CARD_IO_READY BIT(3)
|
||||
|
||||
/* Card Control Registers */
|
||||
#define SQ_READ_BASE_ADDRESS_A0_REG 0x10
|
||||
#define SQ_READ_BASE_ADDRESS_A1_REG 0x11
|
||||
#define FIRMWARE_READY 0xfedc
|
||||
|
||||
#define CARD_STATUS_REG 0x20
|
||||
#define DN_LD_CARD_RDY BIT(0)
|
||||
#define CARD_IO_READY BIT(3)
|
||||
|
||||
#define CARD_FW_STATUS0_REG 0x40
|
||||
#define CARD_FW_STATUS1_REG 0x41
|
||||
#define FIRMWARE_READY 0xfedc
|
||||
|
||||
#define CARD_RX_LEN_REG 0x42
|
||||
#define CARD_RX_UNIT_REG 0x43
|
||||
|
||||
struct btmrvl_sdio_card_reg {
|
||||
u8 cfg;
|
||||
u8 host_int_mask;
|
||||
u8 host_intstatus;
|
||||
u8 card_status;
|
||||
u8 sq_read_base_addr_a0;
|
||||
u8 sq_read_base_addr_a1;
|
||||
u8 card_revision;
|
||||
u8 card_fw_status0;
|
||||
u8 card_fw_status1;
|
||||
u8 card_rx_len;
|
||||
u8 card_rx_unit;
|
||||
u8 io_port_0;
|
||||
u8 io_port_1;
|
||||
u8 io_port_2;
|
||||
};
|
||||
|
||||
struct btmrvl_sdio_card {
|
||||
struct sdio_func *func;
|
||||
u32 ioport;
|
||||
const char *helper;
|
||||
const char *firmware;
|
||||
const struct btmrvl_sdio_card_reg *reg;
|
||||
u16 sd_blksz_fw_dl;
|
||||
u8 rx_unit;
|
||||
struct btmrvl_private *priv;
|
||||
};
|
||||
|
@ -92,6 +94,8 @@ struct btmrvl_sdio_card {
|
|||
struct btmrvl_sdio_device {
|
||||
const char *helper;
|
||||
const char *firmware;
|
||||
const struct btmrvl_sdio_card_reg *reg;
|
||||
u16 sd_blksz_fw_dl;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -104,6 +104,7 @@ static struct usb_device_id blacklist_table[] = {
|
|||
|
||||
/* Atheros 3011 with sflash firmware */
|
||||
{ USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
|
||||
{ USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
|
||||
|
||||
/* Atheros AR9285 Malbec with sflash firmware */
|
||||
{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
|
||||
|
|
|
@ -201,8 +201,13 @@ static struct sk_buff *ath_dequeue(struct hci_uart *hu)
|
|||
/* Recv data */
|
||||
static int ath_recv(struct hci_uart *hu, void *data, int count)
|
||||
{
|
||||
if (hci_recv_stream_fragment(hu->hdev, data, count) < 0)
|
||||
int ret;
|
||||
|
||||
ret = hci_recv_stream_fragment(hu->hdev, data, count);
|
||||
if (ret < 0) {
|
||||
BT_ERR("Frame Reassembly Failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
|
|
@ -151,8 +151,13 @@ 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)
|
||||
{
|
||||
if (hci_recv_stream_fragment(hu->hdev, data, count) < 0)
|
||||
int ret;
|
||||
|
||||
ret = hci_recv_stream_fragment(hu->hdev, data, count);
|
||||
if (ret < 0) {
|
||||
BT_ERR("Frame Reassembly Failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
|
|
@ -359,6 +359,7 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)
|
|||
*/
|
||||
static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
|
||||
{
|
||||
int ret;
|
||||
struct hci_uart *hu = (void *)tty->disc_data;
|
||||
|
||||
if (!hu || tty != hu->tty)
|
||||
|
@ -368,8 +369,9 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *f
|
|||
return;
|
||||
|
||||
spin_lock(&hu->rx_lock);
|
||||
hu->proto->recv(hu, (void *) data, count);
|
||||
hu->hdev->stat.byte_rx += count;
|
||||
ret = hu->proto->recv(hu, (void *) data, count);
|
||||
if (ret > 0)
|
||||
hu->hdev->stat.byte_rx += count;
|
||||
spin_unlock(&hu->rx_lock);
|
||||
|
||||
tty_unthrottle(tty);
|
||||
|
|
|
@ -393,16 +393,6 @@ static int __devinit ieee802154fake_probe(struct platform_device *pdev)
|
|||
priv = netdev_priv(dev);
|
||||
priv->phy = phy;
|
||||
|
||||
/*
|
||||
* If the name is a format string the caller wants us to do a
|
||||
* name allocation.
|
||||
*/
|
||||
if (strchr(dev->name, '%')) {
|
||||
err = dev_alloc_name(dev, dev->name);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
wpan_phy_set_dev(phy, &pdev->dev);
|
||||
SET_NETDEV_DEV(dev, &phy->dev);
|
||||
|
||||
|
|
|
@ -185,15 +185,20 @@ static int addr4_resolve(struct sockaddr_in *src_in,
|
|||
__be32 dst_ip = dst_in->sin_addr.s_addr;
|
||||
struct rtable *rt;
|
||||
struct neighbour *neigh;
|
||||
struct flowi4 fl4;
|
||||
int ret;
|
||||
|
||||
rt = ip_route_output(&init_net, dst_ip, src_ip, 0, addr->bound_dev_if);
|
||||
memset(&fl4, 0, sizeof(fl4));
|
||||
fl4.daddr = dst_ip;
|
||||
fl4.saddr = src_ip;
|
||||
fl4.flowi4_oif = addr->bound_dev_if;
|
||||
rt = ip_route_output_key(&init_net, &fl4);
|
||||
if (IS_ERR(rt)) {
|
||||
ret = PTR_ERR(rt);
|
||||
goto out;
|
||||
}
|
||||
src_in->sin_family = AF_INET;
|
||||
src_in->sin_addr.s_addr = rt->rt_src;
|
||||
src_in->sin_addr.s_addr = fl4.saddr;
|
||||
|
||||
if (rt->dst.dev->flags & IFF_LOOPBACK) {
|
||||
ret = rdma_translate_ip((struct sockaddr *) dst_in, addr);
|
||||
|
|
|
@ -338,8 +338,9 @@ static struct rtable *find_route(struct t3cdev *dev, __be32 local_ip,
|
|||
__be16 peer_port, u8 tos)
|
||||
{
|
||||
struct rtable *rt;
|
||||
struct flowi4 fl4;
|
||||
|
||||
rt = ip_route_output_ports(&init_net, NULL, peer_ip, local_ip,
|
||||
rt = ip_route_output_ports(&init_net, &fl4, NULL, peer_ip, local_ip,
|
||||
peer_port, local_port, IPPROTO_TCP,
|
||||
tos, 0);
|
||||
if (IS_ERR(rt))
|
||||
|
|
|
@ -315,8 +315,9 @@ static struct rtable *find_route(struct c4iw_dev *dev, __be32 local_ip,
|
|||
__be16 peer_port, u8 tos)
|
||||
{
|
||||
struct rtable *rt;
|
||||
struct flowi4 fl4;
|
||||
|
||||
rt = ip_route_output_ports(&init_net, NULL, peer_ip, local_ip,
|
||||
rt = ip_route_output_ports(&init_net, &fl4, NULL, peer_ip, local_ip,
|
||||
peer_port, local_port, IPPROTO_TCP,
|
||||
tos, 0);
|
||||
if (IS_ERR(rt))
|
||||
|
|
|
@ -2885,9 +2885,8 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
|
|||
if ((cqe_errv &
|
||||
(NES_NIC_ERRV_BITS_IPV4_CSUM_ERR | NES_NIC_ERRV_BITS_TCPUDP_CSUM_ERR |
|
||||
NES_NIC_ERRV_BITS_IPH_ERR | NES_NIC_ERRV_BITS_WQE_OVERRUN)) == 0) {
|
||||
if (nesvnic->rx_checksum_disabled == 0) {
|
||||
if (nesvnic->netdev->features & NETIF_F_RXCSUM)
|
||||
rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
}
|
||||
} else
|
||||
nes_debug(NES_DBG_CQ, "%s: unsuccessfully checksummed TCP or UDP packet."
|
||||
" errv = 0x%X, pkt_type = 0x%X.\n",
|
||||
|
@ -2897,7 +2896,7 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
|
|||
if ((cqe_errv &
|
||||
(NES_NIC_ERRV_BITS_IPV4_CSUM_ERR | NES_NIC_ERRV_BITS_IPH_ERR |
|
||||
NES_NIC_ERRV_BITS_WQE_OVERRUN)) == 0) {
|
||||
if (nesvnic->rx_checksum_disabled == 0) {
|
||||
if (nesvnic->netdev->features & NETIF_F_RXCSUM) {
|
||||
rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
/* nes_debug(NES_DBG_CQ, "%s: Reporting successfully checksummed IPv4 packet.\n",
|
||||
nesvnic->netdev->name); */
|
||||
|
|
|
@ -1245,7 +1245,6 @@ struct nes_vnic {
|
|||
u8 next_qp_nic_index;
|
||||
u8 of_device_registered;
|
||||
u8 rdma_enabled;
|
||||
u8 rx_checksum_disabled;
|
||||
u32 lro_max_aggr;
|
||||
struct net_lro_mgr lro_mgr;
|
||||
struct net_lro_desc lro_desc[NES_MAX_LRO_DESCRIPTORS];
|
||||
|
|
|
@ -1093,34 +1093,6 @@ static const char nes_ethtool_stringset[][ETH_GSTRING_LEN] = {
|
|||
};
|
||||
#define NES_ETHTOOL_STAT_COUNT ARRAY_SIZE(nes_ethtool_stringset)
|
||||
|
||||
/**
|
||||
* nes_netdev_get_rx_csum
|
||||
*/
|
||||
static u32 nes_netdev_get_rx_csum (struct net_device *netdev)
|
||||
{
|
||||
struct nes_vnic *nesvnic = netdev_priv(netdev);
|
||||
|
||||
if (nesvnic->rx_checksum_disabled)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* nes_netdev_set_rc_csum
|
||||
*/
|
||||
static int nes_netdev_set_rx_csum(struct net_device *netdev, u32 enable)
|
||||
{
|
||||
struct nes_vnic *nesvnic = netdev_priv(netdev);
|
||||
|
||||
if (enable)
|
||||
nesvnic->rx_checksum_disabled = 0;
|
||||
else
|
||||
nesvnic->rx_checksum_disabled = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* nes_netdev_get_sset_count
|
||||
|
@ -1521,7 +1493,7 @@ static int nes_netdev_get_settings(struct net_device *netdev, struct ethtool_cmd
|
|||
et_cmd->maxrxpkt = 511;
|
||||
|
||||
if (nesadapter->OneG_Mode) {
|
||||
et_cmd->speed = SPEED_1000;
|
||||
ethtool_cmd_speed_set(et_cmd, SPEED_1000);
|
||||
if (phy_type == NES_PHY_TYPE_PUMA_1G) {
|
||||
et_cmd->supported = SUPPORTED_1000baseT_Full;
|
||||
et_cmd->advertising = ADVERTISED_1000baseT_Full;
|
||||
|
@ -1560,7 +1532,7 @@ static int nes_netdev_get_settings(struct net_device *netdev, struct ethtool_cmd
|
|||
et_cmd->advertising = ADVERTISED_10000baseT_Full;
|
||||
et_cmd->phy_address = mac_index;
|
||||
}
|
||||
et_cmd->speed = SPEED_10000;
|
||||
ethtool_cmd_speed_set(et_cmd, SPEED_10000);
|
||||
et_cmd->autoneg = AUTONEG_DISABLE;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1598,19 +1570,10 @@ 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,
|
||||
.set_settings = nes_netdev_set_settings,
|
||||
.get_tx_csum = ethtool_op_get_tx_csum,
|
||||
.get_rx_csum = nes_netdev_get_rx_csum,
|
||||
.get_sg = ethtool_op_get_sg,
|
||||
.get_strings = nes_netdev_get_strings,
|
||||
.get_sset_count = nes_netdev_get_sset_count,
|
||||
.get_ethtool_stats = nes_netdev_get_ethtool_stats,
|
||||
|
@ -1619,13 +1582,6 @@ static const struct ethtool_ops nes_ethtool_ops = {
|
|||
.set_coalesce = nes_netdev_set_coalesce,
|
||||
.get_pauseparam = nes_netdev_get_pauseparam,
|
||||
.set_pauseparam = nes_netdev_set_pauseparam,
|
||||
.set_tx_csum = ethtool_op_set_tx_csum,
|
||||
.set_rx_csum = nes_netdev_set_rx_csum,
|
||||
.set_sg = ethtool_op_set_sg,
|
||||
.get_tso = ethtool_op_get_tso,
|
||||
.set_tso = ethtool_op_set_tso,
|
||||
.get_flags = ethtool_op_get_flags,
|
||||
.set_flags = nes_netdev_set_flags,
|
||||
};
|
||||
|
||||
|
||||
|
@ -1727,12 +1683,11 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
|
|||
netdev->dev_addr[5] = (u8)u64temp;
|
||||
memcpy(netdev->perm_addr, netdev->dev_addr, 6);
|
||||
|
||||
if ((nesvnic->logical_port < 2) || (nesdev->nesadapter->hw_rev != NE020_REV)) {
|
||||
netdev->features |= NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM;
|
||||
netdev->features |= NETIF_F_GSO | NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM;
|
||||
} else {
|
||||
netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
|
||||
}
|
||||
netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM;
|
||||
if ((nesvnic->logical_port < 2) || (nesdev->nesadapter->hw_rev != NE020_REV))
|
||||
netdev->hw_features |= NETIF_F_TSO;
|
||||
netdev->features |= netdev->hw_features;
|
||||
netdev->hw_features |= NETIF_F_LRO;
|
||||
|
||||
nes_debug(NES_DBG_INIT, "nesvnic = %p, reported features = 0x%lX, QPid = %d,"
|
||||
" nic_index = %d, logical_port = %d, mac_index = %d.\n",
|
||||
|
|
|
@ -91,7 +91,6 @@ enum {
|
|||
IPOIB_STOP_REAPER = 7,
|
||||
IPOIB_FLAG_ADMIN_CM = 9,
|
||||
IPOIB_FLAG_UMCAST = 10,
|
||||
IPOIB_FLAG_CSUM = 11,
|
||||
|
||||
IPOIB_MAX_BACKOFF_SECONDS = 16,
|
||||
|
||||
|
|
|
@ -1463,8 +1463,7 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr,
|
|||
set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
|
||||
ipoib_warn(priv, "enabling connected mode "
|
||||
"will cause multicast packet drops\n");
|
||||
|
||||
dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO);
|
||||
netdev_update_features(dev);
|
||||
rtnl_unlock();
|
||||
priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM;
|
||||
|
||||
|
@ -1474,13 +1473,7 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr,
|
|||
|
||||
if (!strcmp(buf, "datagram\n")) {
|
||||
clear_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
|
||||
|
||||
if (test_bit(IPOIB_FLAG_CSUM, &priv->flags)) {
|
||||
dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
|
||||
priv->dev->features |= NETIF_F_GRO;
|
||||
if (priv->hca_caps & IB_DEVICE_UD_TSO)
|
||||
dev->features |= NETIF_F_TSO;
|
||||
}
|
||||
netdev_update_features(dev);
|
||||
dev_set_mtu(dev, min(priv->mcast_mtu, dev->mtu));
|
||||
rtnl_unlock();
|
||||
ipoib_flush_paths(dev);
|
||||
|
|
|
@ -42,32 +42,6 @@ static void ipoib_get_drvinfo(struct net_device *netdev,
|
|||
strncpy(drvinfo->driver, "ipoib", sizeof(drvinfo->driver) - 1);
|
||||
}
|
||||
|
||||
static u32 ipoib_get_rx_csum(struct net_device *dev)
|
||||
{
|
||||
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
||||
return test_bit(IPOIB_FLAG_CSUM, &priv->flags) &&
|
||||
!test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
|
||||
}
|
||||
|
||||
static int ipoib_set_tso(struct net_device *dev, u32 data)
|
||||
{
|
||||
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
||||
|
||||
if (data) {
|
||||
if (!test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags) &&
|
||||
(dev->features & NETIF_F_SG) &&
|
||||
(priv->hca_caps & IB_DEVICE_UD_TSO)) {
|
||||
dev->features |= NETIF_F_TSO;
|
||||
} else {
|
||||
ipoib_warn(priv, "can't set TSO on\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
} else
|
||||
dev->features &= ~NETIF_F_TSO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipoib_get_coalesce(struct net_device *dev,
|
||||
struct ethtool_coalesce *coal)
|
||||
{
|
||||
|
@ -108,8 +82,6 @@ static int ipoib_set_coalesce(struct net_device *dev,
|
|||
|
||||
static const struct ethtool_ops ipoib_ethtool_ops = {
|
||||
.get_drvinfo = ipoib_get_drvinfo,
|
||||
.get_rx_csum = ipoib_get_rx_csum,
|
||||
.set_tso = ipoib_set_tso,
|
||||
.get_coalesce = ipoib_get_coalesce,
|
||||
.set_coalesce = ipoib_set_coalesce,
|
||||
};
|
||||
|
|
|
@ -292,7 +292,7 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
|
|||
dev->stats.rx_bytes += skb->len;
|
||||
|
||||
skb->dev = dev;
|
||||
if (test_bit(IPOIB_FLAG_CSUM, &priv->flags) && likely(wc->csum_ok))
|
||||
if ((dev->features & NETIF_F_RXCSUM) && likely(wc->csum_ok))
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
|
||||
napi_gro_receive(&priv->napi, skb);
|
||||
|
|
|
@ -171,6 +171,16 @@ static int ipoib_stop(struct net_device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static u32 ipoib_fix_features(struct net_device *dev, u32 features)
|
||||
{
|
||||
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
||||
|
||||
if (test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags))
|
||||
features &= ~(NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO);
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
static int ipoib_change_mtu(struct net_device *dev, int new_mtu)
|
||||
{
|
||||
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
||||
|
@ -970,6 +980,7 @@ static const struct net_device_ops ipoib_netdev_ops = {
|
|||
.ndo_open = ipoib_open,
|
||||
.ndo_stop = ipoib_stop,
|
||||
.ndo_change_mtu = ipoib_change_mtu,
|
||||
.ndo_fix_features = ipoib_fix_features,
|
||||
.ndo_start_xmit = ipoib_start_xmit,
|
||||
.ndo_tx_timeout = ipoib_timeout,
|
||||
.ndo_set_multicast_list = ipoib_set_mcast_list,
|
||||
|
@ -1154,19 +1165,18 @@ int ipoib_set_dev_features(struct ipoib_dev_priv *priv, struct ib_device *hca)
|
|||
kfree(device_attr);
|
||||
|
||||
if (priv->hca_caps & IB_DEVICE_UD_IP_CSUM) {
|
||||
set_bit(IPOIB_FLAG_CSUM, &priv->flags);
|
||||
priv->dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
|
||||
priv->dev->hw_features = NETIF_F_SG |
|
||||
NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
|
||||
|
||||
if (priv->hca_caps & IB_DEVICE_UD_TSO)
|
||||
priv->dev->hw_features |= NETIF_F_TSO;
|
||||
|
||||
priv->dev->features |= priv->dev->hw_features;
|
||||
}
|
||||
|
||||
priv->dev->features |= NETIF_F_GRO;
|
||||
|
||||
if (priv->dev->features & NETIF_F_SG && priv->hca_caps & IB_DEVICE_UD_TSO)
|
||||
priv->dev->features |= NETIF_F_TSO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct net_device *ipoib_add_port(const char *format,
|
||||
struct ib_device *hca, u8 port)
|
||||
{
|
||||
|
|
|
@ -33,21 +33,6 @@ config ISDN_CAPI_CAPI20
|
|||
standardized libcapi20 to access this functionality. You should say
|
||||
Y/M here.
|
||||
|
||||
config ISDN_CAPI_CAPIFS_BOOL
|
||||
bool "CAPI2.0 filesystem support (DEPRECATED)"
|
||||
depends on ISDN_CAPI_MIDDLEWARE && ISDN_CAPI_CAPI20
|
||||
help
|
||||
This option provides a special file system, similar to /dev/pts with
|
||||
device nodes for the special ttys established by using the
|
||||
middleware extension above.
|
||||
You no longer need this, udev fully replaces it. This feature is
|
||||
scheduled for removal.
|
||||
|
||||
config ISDN_CAPI_CAPIFS
|
||||
tristate
|
||||
depends on ISDN_CAPI_CAPIFS_BOOL
|
||||
default ISDN_CAPI_CAPI20
|
||||
|
||||
config ISDN_CAPI_CAPIDRV
|
||||
tristate "CAPI2.0 capidrv interface support"
|
||||
depends on ISDN_I4L
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
obj-$(CONFIG_ISDN_CAPI) += kernelcapi.o
|
||||
obj-$(CONFIG_ISDN_CAPI_CAPI20) += capi.o
|
||||
obj-$(CONFIG_ISDN_CAPI_CAPIDRV) += capidrv.o
|
||||
obj-$(CONFIG_ISDN_CAPI_CAPIFS) += capifs.o
|
||||
|
||||
# Multipart objects.
|
||||
|
||||
|
|
|
@ -38,15 +38,10 @@
|
|||
#include <linux/isdn/capiutil.h>
|
||||
#include <linux/isdn/capicmd.h>
|
||||
|
||||
#include "capifs.h"
|
||||
|
||||
MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface");
|
||||
MODULE_AUTHOR("Carsten Paeth");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#undef _DEBUG_TTYFUNCS /* call to tty_driver */
|
||||
#undef _DEBUG_DATAFLOW /* data flow */
|
||||
|
||||
/* -------- driver information -------------------------------------- */
|
||||
|
||||
static DEFINE_MUTEX(capi_mutex);
|
||||
|
@ -85,7 +80,6 @@ struct capiminor {
|
|||
struct kref kref;
|
||||
|
||||
unsigned int minor;
|
||||
struct dentry *capifs_dentry;
|
||||
|
||||
struct capi20_appl *ap;
|
||||
u32 ncci;
|
||||
|
@ -300,17 +294,8 @@ static void capiminor_free(struct capiminor *mp)
|
|||
|
||||
static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np)
|
||||
{
|
||||
struct capiminor *mp;
|
||||
dev_t device;
|
||||
|
||||
if (!(cdev->userflags & CAPIFLAG_HIGHJACKING))
|
||||
return;
|
||||
|
||||
mp = np->minorp = capiminor_alloc(&cdev->ap, np->ncci);
|
||||
if (mp) {
|
||||
device = MKDEV(capinc_tty_driver->major, mp->minor);
|
||||
mp->capifs_dentry = capifs_new_ncci(mp->minor, device);
|
||||
}
|
||||
if (cdev->userflags & CAPIFLAG_HIGHJACKING)
|
||||
np->minorp = capiminor_alloc(&cdev->ap, np->ncci);
|
||||
}
|
||||
|
||||
static void capincci_free_minor(struct capincci *np)
|
||||
|
@ -319,8 +304,6 @@ static void capincci_free_minor(struct capincci *np)
|
|||
struct tty_struct *tty;
|
||||
|
||||
if (mp) {
|
||||
capifs_free_ncci(mp->capifs_dentry);
|
||||
|
||||
tty = tty_port_tty_get(&mp->port);
|
||||
if (tty) {
|
||||
tty_vhangup(tty);
|
||||
|
@ -432,9 +415,7 @@ static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
|
|||
|
||||
tty = tty_port_tty_get(&mp->port);
|
||||
if (!tty) {
|
||||
#ifdef _DEBUG_DATAFLOW
|
||||
printk(KERN_DEBUG "capi: currently no receiver\n");
|
||||
#endif
|
||||
pr_debug("capi: currently no receiver\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -447,23 +428,17 @@ static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
|
|||
}
|
||||
|
||||
if (ld->ops->receive_buf == NULL) {
|
||||
#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
|
||||
printk(KERN_DEBUG "capi: ldisc has no receive_buf function\n");
|
||||
#endif
|
||||
pr_debug("capi: ldisc has no receive_buf function\n");
|
||||
/* fatal error, do not requeue */
|
||||
goto free_skb;
|
||||
}
|
||||
if (mp->ttyinstop) {
|
||||
#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
|
||||
printk(KERN_DEBUG "capi: recv tty throttled\n");
|
||||
#endif
|
||||
pr_debug("capi: recv tty throttled\n");
|
||||
goto deref_ldisc;
|
||||
}
|
||||
|
||||
if (tty->receive_room < datalen) {
|
||||
#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
|
||||
printk(KERN_DEBUG "capi: no room in tty\n");
|
||||
#endif
|
||||
pr_debug("capi: no room in tty\n");
|
||||
goto deref_ldisc;
|
||||
}
|
||||
|
||||
|
@ -479,10 +454,8 @@ static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
|
|||
|
||||
if (errcode == CAPI_NOERROR) {
|
||||
skb_pull(skb, CAPIMSG_LEN(skb->data));
|
||||
#ifdef _DEBUG_DATAFLOW
|
||||
printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n",
|
||||
datahandle, skb->len);
|
||||
#endif
|
||||
pr_debug("capi: DATA_B3_RESP %u len=%d => ldisc\n",
|
||||
datahandle, skb->len);
|
||||
ld->ops->receive_buf(tty, skb->data, NULL, skb->len);
|
||||
} else {
|
||||
printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n",
|
||||
|
@ -529,9 +502,7 @@ static void handle_minor_send(struct capiminor *mp)
|
|||
return;
|
||||
|
||||
if (mp->ttyoutstop) {
|
||||
#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
|
||||
printk(KERN_DEBUG "capi: send: tty stopped\n");
|
||||
#endif
|
||||
pr_debug("capi: send: tty stopped\n");
|
||||
tty_kref_put(tty);
|
||||
return;
|
||||
}
|
||||
|
@ -573,10 +544,8 @@ static void handle_minor_send(struct capiminor *mp)
|
|||
}
|
||||
errcode = capi20_put_message(mp->ap, skb);
|
||||
if (errcode == CAPI_NOERROR) {
|
||||
#ifdef _DEBUG_DATAFLOW
|
||||
printk(KERN_DEBUG "capi: DATA_B3_REQ %u len=%u\n",
|
||||
datahandle, len);
|
||||
#endif
|
||||
pr_debug("capi: DATA_B3_REQ %u len=%u\n",
|
||||
datahandle, len);
|
||||
continue;
|
||||
}
|
||||
capiminor_del_ack(mp, datahandle);
|
||||
|
@ -650,10 +619,8 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
|
|||
}
|
||||
if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) {
|
||||
datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+4+2);
|
||||
#ifdef _DEBUG_DATAFLOW
|
||||
printk(KERN_DEBUG "capi_signal: DATA_B3_IND %u len=%d\n",
|
||||
datahandle, skb->len-CAPIMSG_LEN(skb->data));
|
||||
#endif
|
||||
pr_debug("capi_signal: DATA_B3_IND %u len=%d\n",
|
||||
datahandle, skb->len-CAPIMSG_LEN(skb->data));
|
||||
skb_queue_tail(&mp->inqueue, skb);
|
||||
|
||||
handle_minor_recv(mp);
|
||||
|
@ -661,11 +628,9 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
|
|||
} else if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF) {
|
||||
|
||||
datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4);
|
||||
#ifdef _DEBUG_DATAFLOW
|
||||
printk(KERN_DEBUG "capi_signal: DATA_B3_CONF %u 0x%x\n",
|
||||
datahandle,
|
||||
CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+2));
|
||||
#endif
|
||||
pr_debug("capi_signal: DATA_B3_CONF %u 0x%x\n",
|
||||
datahandle,
|
||||
CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+2));
|
||||
kfree_skb(skb);
|
||||
capiminor_del_ack(mp, datahandle);
|
||||
tty = tty_port_tty_get(&mp->port);
|
||||
|
@ -1095,9 +1060,7 @@ static int capinc_tty_write(struct tty_struct *tty,
|
|||
struct capiminor *mp = tty->driver_data;
|
||||
struct sk_buff *skb;
|
||||
|
||||
#ifdef _DEBUG_TTYFUNCS
|
||||
printk(KERN_DEBUG "capinc_tty_write(count=%d)\n", count);
|
||||
#endif
|
||||
pr_debug("capinc_tty_write(count=%d)\n", count);
|
||||
|
||||
spin_lock_bh(&mp->outlock);
|
||||
skb = mp->outskb;
|
||||
|
@ -1133,9 +1096,7 @@ static int capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
|
|||
struct sk_buff *skb;
|
||||
int ret = 1;
|
||||
|
||||
#ifdef _DEBUG_TTYFUNCS
|
||||
printk(KERN_DEBUG "capinc_put_char(%u)\n", ch);
|
||||
#endif
|
||||
pr_debug("capinc_put_char(%u)\n", ch);
|
||||
|
||||
spin_lock_bh(&mp->outlock);
|
||||
skb = mp->outskb;
|
||||
|
@ -1174,9 +1135,7 @@ static void capinc_tty_flush_chars(struct tty_struct *tty)
|
|||
struct capiminor *mp = tty->driver_data;
|
||||
struct sk_buff *skb;
|
||||
|
||||
#ifdef _DEBUG_TTYFUNCS
|
||||
printk(KERN_DEBUG "capinc_tty_flush_chars\n");
|
||||
#endif
|
||||
pr_debug("capinc_tty_flush_chars\n");
|
||||
|
||||
spin_lock_bh(&mp->outlock);
|
||||
skb = mp->outskb;
|
||||
|
@ -1200,9 +1159,7 @@ static int capinc_tty_write_room(struct tty_struct *tty)
|
|||
|
||||
room = CAPINC_MAX_SENDQUEUE-skb_queue_len(&mp->outqueue);
|
||||
room *= CAPI_MAX_BLKSIZE;
|
||||
#ifdef _DEBUG_TTYFUNCS
|
||||
printk(KERN_DEBUG "capinc_tty_write_room = %d\n", room);
|
||||
#endif
|
||||
pr_debug("capinc_tty_write_room = %d\n", room);
|
||||
return room;
|
||||
}
|
||||
|
||||
|
@ -1210,12 +1167,10 @@ static int capinc_tty_chars_in_buffer(struct tty_struct *tty)
|
|||
{
|
||||
struct capiminor *mp = tty->driver_data;
|
||||
|
||||
#ifdef _DEBUG_TTYFUNCS
|
||||
printk(KERN_DEBUG "capinc_tty_chars_in_buffer = %d nack=%d sq=%d rq=%d\n",
|
||||
mp->outbytes, mp->nack,
|
||||
skb_queue_len(&mp->outqueue),
|
||||
skb_queue_len(&mp->inqueue));
|
||||
#endif
|
||||
pr_debug("capinc_tty_chars_in_buffer = %d nack=%d sq=%d rq=%d\n",
|
||||
mp->outbytes, mp->nack,
|
||||
skb_queue_len(&mp->outqueue),
|
||||
skb_queue_len(&mp->inqueue));
|
||||
return mp->outbytes;
|
||||
}
|
||||
|
||||
|
@ -1227,17 +1182,13 @@ static int capinc_tty_ioctl(struct tty_struct *tty,
|
|||
|
||||
static void capinc_tty_set_termios(struct tty_struct *tty, struct ktermios * old)
|
||||
{
|
||||
#ifdef _DEBUG_TTYFUNCS
|
||||
printk(KERN_DEBUG "capinc_tty_set_termios\n");
|
||||
#endif
|
||||
pr_debug("capinc_tty_set_termios\n");
|
||||
}
|
||||
|
||||
static void capinc_tty_throttle(struct tty_struct *tty)
|
||||
{
|
||||
struct capiminor *mp = tty->driver_data;
|
||||
#ifdef _DEBUG_TTYFUNCS
|
||||
printk(KERN_DEBUG "capinc_tty_throttle\n");
|
||||
#endif
|
||||
pr_debug("capinc_tty_throttle\n");
|
||||
mp->ttyinstop = 1;
|
||||
}
|
||||
|
||||
|
@ -1245,9 +1196,7 @@ static void capinc_tty_unthrottle(struct tty_struct *tty)
|
|||
{
|
||||
struct capiminor *mp = tty->driver_data;
|
||||
|
||||
#ifdef _DEBUG_TTYFUNCS
|
||||
printk(KERN_DEBUG "capinc_tty_unthrottle\n");
|
||||
#endif
|
||||
pr_debug("capinc_tty_unthrottle\n");
|
||||
mp->ttyinstop = 0;
|
||||
handle_minor_recv(mp);
|
||||
}
|
||||
|
@ -1256,9 +1205,7 @@ static void capinc_tty_stop(struct tty_struct *tty)
|
|||
{
|
||||
struct capiminor *mp = tty->driver_data;
|
||||
|
||||
#ifdef _DEBUG_TTYFUNCS
|
||||
printk(KERN_DEBUG "capinc_tty_stop\n");
|
||||
#endif
|
||||
pr_debug("capinc_tty_stop\n");
|
||||
mp->ttyoutstop = 1;
|
||||
}
|
||||
|
||||
|
@ -1266,9 +1213,7 @@ static void capinc_tty_start(struct tty_struct *tty)
|
|||
{
|
||||
struct capiminor *mp = tty->driver_data;
|
||||
|
||||
#ifdef _DEBUG_TTYFUNCS
|
||||
printk(KERN_DEBUG "capinc_tty_start\n");
|
||||
#endif
|
||||
pr_debug("capinc_tty_start\n");
|
||||
mp->ttyoutstop = 0;
|
||||
handle_minor_send(mp);
|
||||
}
|
||||
|
@ -1277,39 +1222,29 @@ static void capinc_tty_hangup(struct tty_struct *tty)
|
|||
{
|
||||
struct capiminor *mp = tty->driver_data;
|
||||
|
||||
#ifdef _DEBUG_TTYFUNCS
|
||||
printk(KERN_DEBUG "capinc_tty_hangup\n");
|
||||
#endif
|
||||
pr_debug("capinc_tty_hangup\n");
|
||||
tty_port_hangup(&mp->port);
|
||||
}
|
||||
|
||||
static int capinc_tty_break_ctl(struct tty_struct *tty, int state)
|
||||
{
|
||||
#ifdef _DEBUG_TTYFUNCS
|
||||
printk(KERN_DEBUG "capinc_tty_break_ctl(%d)\n", state);
|
||||
#endif
|
||||
pr_debug("capinc_tty_break_ctl(%d)\n", state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void capinc_tty_flush_buffer(struct tty_struct *tty)
|
||||
{
|
||||
#ifdef _DEBUG_TTYFUNCS
|
||||
printk(KERN_DEBUG "capinc_tty_flush_buffer\n");
|
||||
#endif
|
||||
pr_debug("capinc_tty_flush_buffer\n");
|
||||
}
|
||||
|
||||
static void capinc_tty_set_ldisc(struct tty_struct *tty)
|
||||
{
|
||||
#ifdef _DEBUG_TTYFUNCS
|
||||
printk(KERN_DEBUG "capinc_tty_set_ldisc\n");
|
||||
#endif
|
||||
pr_debug("capinc_tty_set_ldisc\n");
|
||||
}
|
||||
|
||||
static void capinc_tty_send_xchar(struct tty_struct *tty, char ch)
|
||||
{
|
||||
#ifdef _DEBUG_TTYFUNCS
|
||||
printk(KERN_DEBUG "capinc_tty_send_xchar(%d)\n", ch);
|
||||
#endif
|
||||
pr_debug("capinc_tty_send_xchar(%d)\n", ch);
|
||||
}
|
||||
|
||||
static const struct tty_operations capinc_ops = {
|
||||
|
@ -1514,10 +1449,8 @@ static int __init capi_init(void)
|
|||
|
||||
proc_init();
|
||||
|
||||
#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)
|
||||
compileinfo = " (middleware+capifs)";
|
||||
#elif defined(CONFIG_ISDN_CAPI_MIDDLEWARE)
|
||||
compileinfo = " (no capifs)";
|
||||
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
|
||||
compileinfo = " (middleware)";
|
||||
#else
|
||||
compileinfo = " (no middleware)";
|
||||
#endif
|
||||
|
|
|
@ -1,239 +0,0 @@
|
|||
/* $Id: capifs.c,v 1.1.2.3 2004/01/16 21:09:26 keil Exp $
|
||||
*
|
||||
* Copyright 2000 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* Heavily based on devpts filesystem from H. Peter Anvin
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/namei.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/sched.h> /* current */
|
||||
|
||||
#include "capifs.h"
|
||||
|
||||
MODULE_DESCRIPTION("CAPI4Linux: /dev/capi/ filesystem");
|
||||
MODULE_AUTHOR("Carsten Paeth");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
#define CAPIFS_SUPER_MAGIC (('C'<<8)|'N')
|
||||
|
||||
static struct vfsmount *capifs_mnt;
|
||||
static int capifs_mnt_count;
|
||||
|
||||
static struct {
|
||||
int setuid;
|
||||
int setgid;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
umode_t mode;
|
||||
} config = {.mode = 0600};
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static int capifs_remount(struct super_block *s, int *flags, char *data)
|
||||
{
|
||||
int setuid = 0;
|
||||
int setgid = 0;
|
||||
uid_t uid = 0;
|
||||
gid_t gid = 0;
|
||||
umode_t mode = 0600;
|
||||
char *this_char;
|
||||
char *new_opt = kstrdup(data, GFP_KERNEL);
|
||||
|
||||
this_char = NULL;
|
||||
while ((this_char = strsep(&data, ",")) != NULL) {
|
||||
int n;
|
||||
char dummy;
|
||||
if (!*this_char)
|
||||
continue;
|
||||
if (sscanf(this_char, "uid=%i%c", &n, &dummy) == 1) {
|
||||
setuid = 1;
|
||||
uid = n;
|
||||
} else if (sscanf(this_char, "gid=%i%c", &n, &dummy) == 1) {
|
||||
setgid = 1;
|
||||
gid = n;
|
||||
} else if (sscanf(this_char, "mode=%o%c", &n, &dummy) == 1)
|
||||
mode = n & ~S_IFMT;
|
||||
else {
|
||||
kfree(new_opt);
|
||||
printk("capifs: called with bogus options\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&s->s_root->d_inode->i_mutex);
|
||||
|
||||
replace_mount_options(s, new_opt);
|
||||
config.setuid = setuid;
|
||||
config.setgid = setgid;
|
||||
config.uid = uid;
|
||||
config.gid = gid;
|
||||
config.mode = mode;
|
||||
|
||||
mutex_unlock(&s->s_root->d_inode->i_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct super_operations capifs_sops =
|
||||
{
|
||||
.statfs = simple_statfs,
|
||||
.remount_fs = capifs_remount,
|
||||
.show_options = generic_show_options,
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
capifs_fill_super(struct super_block *s, void *data, int silent)
|
||||
{
|
||||
struct inode * inode;
|
||||
|
||||
s->s_blocksize = 1024;
|
||||
s->s_blocksize_bits = 10;
|
||||
s->s_magic = CAPIFS_SUPER_MAGIC;
|
||||
s->s_op = &capifs_sops;
|
||||
s->s_time_gran = 1;
|
||||
|
||||
inode = new_inode(s);
|
||||
if (!inode)
|
||||
goto fail;
|
||||
inode->i_ino = 1;
|
||||
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
|
||||
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
|
||||
inode->i_op = &simple_dir_inode_operations;
|
||||
inode->i_fop = &simple_dir_operations;
|
||||
inode->i_nlink = 2;
|
||||
|
||||
s->s_root = d_alloc_root(inode);
|
||||
if (s->s_root)
|
||||
return 0;
|
||||
|
||||
printk("capifs: get root dentry failed\n");
|
||||
iput(inode);
|
||||
fail:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static struct dentry *capifs_mount(struct file_system_type *fs_type,
|
||||
int flags, const char *dev_name, void *data)
|
||||
{
|
||||
return mount_single(fs_type, flags, data, capifs_fill_super);
|
||||
}
|
||||
|
||||
static struct file_system_type capifs_fs_type = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "capifs",
|
||||
.mount = capifs_mount,
|
||||
.kill_sb = kill_anon_super,
|
||||
};
|
||||
|
||||
static struct dentry *new_ncci(unsigned int number, dev_t device)
|
||||
{
|
||||
struct super_block *s = capifs_mnt->mnt_sb;
|
||||
struct dentry *root = s->s_root;
|
||||
struct dentry *dentry;
|
||||
struct inode *inode;
|
||||
char name[10];
|
||||
int namelen;
|
||||
|
||||
mutex_lock(&root->d_inode->i_mutex);
|
||||
|
||||
namelen = sprintf(name, "%d", number);
|
||||
dentry = lookup_one_len(name, root, namelen);
|
||||
if (IS_ERR(dentry)) {
|
||||
dentry = NULL;
|
||||
goto unlock_out;
|
||||
}
|
||||
|
||||
if (dentry->d_inode) {
|
||||
dput(dentry);
|
||||
dentry = NULL;
|
||||
goto unlock_out;
|
||||
}
|
||||
|
||||
inode = new_inode(s);
|
||||
if (!inode) {
|
||||
dput(dentry);
|
||||
dentry = NULL;
|
||||
goto unlock_out;
|
||||
}
|
||||
|
||||
/* config contents is protected by root's i_mutex */
|
||||
inode->i_uid = config.setuid ? config.uid : current_fsuid();
|
||||
inode->i_gid = config.setgid ? config.gid : current_fsgid();
|
||||
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
|
||||
inode->i_ino = number + 2;
|
||||
init_special_inode(inode, S_IFCHR|config.mode, device);
|
||||
|
||||
d_instantiate(dentry, inode);
|
||||
dget(dentry);
|
||||
|
||||
unlock_out:
|
||||
mutex_unlock(&root->d_inode->i_mutex);
|
||||
|
||||
return dentry;
|
||||
}
|
||||
|
||||
struct dentry *capifs_new_ncci(unsigned int number, dev_t device)
|
||||
{
|
||||
struct dentry *dentry;
|
||||
|
||||
if (simple_pin_fs(&capifs_fs_type, &capifs_mnt, &capifs_mnt_count) < 0)
|
||||
return NULL;
|
||||
|
||||
dentry = new_ncci(number, device);
|
||||
if (!dentry)
|
||||
simple_release_fs(&capifs_mnt, &capifs_mnt_count);
|
||||
|
||||
return dentry;
|
||||
}
|
||||
|
||||
void capifs_free_ncci(struct dentry *dentry)
|
||||
{
|
||||
struct dentry *root = capifs_mnt->mnt_sb->s_root;
|
||||
struct inode *inode;
|
||||
|
||||
if (!dentry)
|
||||
return;
|
||||
|
||||
mutex_lock(&root->d_inode->i_mutex);
|
||||
|
||||
inode = dentry->d_inode;
|
||||
if (inode) {
|
||||
drop_nlink(inode);
|
||||
d_delete(dentry);
|
||||
dput(dentry);
|
||||
}
|
||||
dput(dentry);
|
||||
|
||||
mutex_unlock(&root->d_inode->i_mutex);
|
||||
|
||||
simple_release_fs(&capifs_mnt, &capifs_mnt_count);
|
||||
}
|
||||
|
||||
static int __init capifs_init(void)
|
||||
{
|
||||
return register_filesystem(&capifs_fs_type);
|
||||
}
|
||||
|
||||
static void __exit capifs_exit(void)
|
||||
{
|
||||
unregister_filesystem(&capifs_fs_type);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(capifs_new_ncci);
|
||||
EXPORT_SYMBOL(capifs_free_ncci);
|
||||
|
||||
module_init(capifs_init);
|
||||
module_exit(capifs_exit);
|
|
@ -1,28 +0,0 @@
|
|||
/* $Id: capifs.h,v 1.1.2.2 2004/01/16 21:09:26 keil Exp $
|
||||
*
|
||||
* Copyright 2000 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/dcache.h>
|
||||
|
||||
#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)
|
||||
|
||||
struct dentry *capifs_new_ncci(unsigned int num, dev_t device);
|
||||
void capifs_free_ncci(struct dentry *dentry);
|
||||
|
||||
#else
|
||||
|
||||
static inline struct dentry *capifs_new_ncci(unsigned int num, dev_t device)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void capifs_free_ncci(struct dentry *dentry)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1157,7 +1157,6 @@ static void write_iso_tasklet(unsigned long data)
|
|||
struct urb *urb;
|
||||
int status;
|
||||
struct usb_iso_packet_descriptor *ifd;
|
||||
int offset;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
struct sk_buff *skb;
|
||||
|
@ -1225,7 +1224,6 @@ static void write_iso_tasklet(unsigned long data)
|
|||
* successfully sent
|
||||
* - all following frames are not sent at all
|
||||
*/
|
||||
offset = done->limit; /* default (no error) */
|
||||
for (i = 0; i < BAS_NUMFRAMES; i++) {
|
||||
ifd = &urb->iso_frame_desc[i];
|
||||
if (ifd->status ||
|
||||
|
@ -1235,9 +1233,6 @@ static void write_iso_tasklet(unsigned long data)
|
|||
i, ifd->actual_length,
|
||||
ifd->length,
|
||||
get_usb_statmsg(ifd->status));
|
||||
offset = (ifd->offset +
|
||||
ifd->actual_length)
|
||||
% BAS_OUTBUFSIZE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -390,12 +390,12 @@ static const struct zsau_resp_t {
|
|||
*/
|
||||
static int cid_of_response(char *s)
|
||||
{
|
||||
unsigned long cid;
|
||||
int cid;
|
||||
int rc;
|
||||
|
||||
if (s[-1] != ';')
|
||||
return 0; /* no CID separator */
|
||||
rc = strict_strtoul(s, 10, &cid);
|
||||
rc = kstrtoint(s, 10, &cid);
|
||||
if (rc)
|
||||
return 0; /* CID not numeric */
|
||||
if (cid < 1 || cid > 65535)
|
||||
|
@ -566,27 +566,19 @@ void gigaset_handle_modem_response(struct cardstate *cs)
|
|||
case RT_ZCAU:
|
||||
event->parameter = -1;
|
||||
if (curarg + 1 < params) {
|
||||
unsigned long type, value;
|
||||
u8 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)
|
||||
i = kstrtou8(argv[curarg++], 16, &type);
|
||||
j = kstrtou8(argv[curarg++], 16, &value);
|
||||
if (i == 0 && j == 0)
|
||||
event->parameter = (type << 8) | value;
|
||||
} else
|
||||
curarg = params - 1;
|
||||
break;
|
||||
case RT_NUMBER:
|
||||
event->parameter = -1;
|
||||
if (curarg < params) {
|
||||
unsigned long res;
|
||||
int rc;
|
||||
|
||||
rc = strict_strtoul(argv[curarg++], 10, &res);
|
||||
if (rc == 0)
|
||||
event->parameter = res;
|
||||
}
|
||||
if (curarg >= params ||
|
||||
kstrtoint(argv[curarg++], 10, &event->parameter))
|
||||
event->parameter = -1;
|
||||
gig_dbg(DEBUG_EVENT, "parameter==%d", event->parameter);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -861,7 +861,7 @@ static int diva_get_idi_adapter_info (IDI_CALL request, dword* serial, dword* lo
|
|||
void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) {
|
||||
diva_os_spin_lock_magic_t old_irql, old_irql1;
|
||||
dword sec, usec, logical, serial, org_mask;
|
||||
int id, best_id = 0, free_id = -1;
|
||||
int id, free_id = -1;
|
||||
char tmp[128];
|
||||
diva_dbg_entry_head_t* pmsg = NULL;
|
||||
int len;
|
||||
|
@ -906,7 +906,6 @@ void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) {
|
|||
and slot is still free - reuse it
|
||||
*/
|
||||
free_id = id;
|
||||
best_id = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1198,7 +1198,6 @@ static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
|
|||
word ch;
|
||||
word i;
|
||||
word Info;
|
||||
word CIP;
|
||||
byte LinkLayer;
|
||||
API_PARSE * ai;
|
||||
API_PARSE * bp;
|
||||
|
@ -1340,7 +1339,6 @@ static byte connect_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
|
|||
add_s(plci,BC,&parms[6]);
|
||||
add_s(plci,LLC,&parms[7]);
|
||||
add_s(plci,HLC,&parms[8]);
|
||||
CIP = GET_WORD(parms[0].info);
|
||||
if (a->Info_Mask[appl->Id-1] & 0x200)
|
||||
{
|
||||
/* early B3 connect (CIP mask bit 9) no release after a disc */
|
||||
|
@ -4830,7 +4828,6 @@ static void sig_ind(PLCI *plci)
|
|||
dword x_Id;
|
||||
dword Id;
|
||||
dword rId;
|
||||
word Number = 0;
|
||||
word i;
|
||||
word cip;
|
||||
dword cip_mask;
|
||||
|
@ -5106,7 +5103,7 @@ static void sig_ind(PLCI *plci)
|
|||
}
|
||||
}
|
||||
|
||||
if(plci->appl) Number = plci->appl->Number++;
|
||||
if(plci->appl) plci->appl->Number++;
|
||||
|
||||
switch(plci->Sig.Ind) {
|
||||
/* Response to Get_Supported_Services request */
|
||||
|
@ -5894,7 +5891,6 @@ static void sig_ind(PLCI *plci)
|
|||
break;
|
||||
|
||||
case TEL_CTRL:
|
||||
Number = 0;
|
||||
ie = multi_fac_parms[0]; /* inspect the facility hook indications */
|
||||
if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
|
||||
switch (ie[1]&0x91) {
|
||||
|
@ -10119,14 +10115,12 @@ static byte dtmf_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI
|
|||
|
||||
static void dtmf_confirmation (dword Id, PLCI *plci)
|
||||
{
|
||||
word Info;
|
||||
word i;
|
||||
byte result[4];
|
||||
|
||||
dbug (1, dprintf ("[%06lx] %s,%d: dtmf_confirmation",
|
||||
UnMapId (Id), (char *)(FILE_), __LINE__));
|
||||
|
||||
Info = GOOD;
|
||||
result[0] = 2;
|
||||
PUT_WORD (&result[1], DTMF_SUCCESS);
|
||||
if (plci->dtmf_send_requests != 0)
|
||||
|
@ -11520,13 +11514,12 @@ static word mixer_restore_config (dword Id, PLCI *plci, byte Rc)
|
|||
static void mixer_command (dword Id, PLCI *plci, byte Rc)
|
||||
{
|
||||
DIVA_CAPI_ADAPTER *a;
|
||||
word i, internal_command, Info;
|
||||
word i, internal_command;
|
||||
|
||||
dbug (1, dprintf ("[%06lx] %s,%d: mixer_command %02x %04x %04x",
|
||||
UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command,
|
||||
plci->li_cmd));
|
||||
|
||||
Info = GOOD;
|
||||
a = plci->adapter;
|
||||
internal_command = plci->internal_command;
|
||||
plci->internal_command = 0;
|
||||
|
@ -11550,7 +11543,6 @@ static void mixer_command (dword Id, PLCI *plci, byte Rc)
|
|||
{
|
||||
dbug (1, dprintf ("[%06lx] %s,%d: Load mixer failed",
|
||||
UnMapId (Id), (char *)(FILE_), __LINE__));
|
||||
Info = _FACILITY_NOT_SUPPORTED;
|
||||
break;
|
||||
}
|
||||
if (plci->internal_command)
|
||||
|
@ -11592,7 +11584,6 @@ static void mixer_command (dword Id, PLCI *plci, byte Rc)
|
|||
} while ((plci->li_plci_b_write_pos != plci->li_plci_b_req_pos)
|
||||
&& !(plci->li_plci_b_queue[i] & LI_PLCI_B_LAST_FLAG));
|
||||
}
|
||||
Info = _FACILITY_NOT_SUPPORTED;
|
||||
break;
|
||||
}
|
||||
if (plci->internal_command)
|
||||
|
@ -11610,7 +11601,6 @@ static void mixer_command (dword Id, PLCI *plci, byte Rc)
|
|||
{
|
||||
dbug (1, dprintf ("[%06lx] %s,%d: Unload mixer failed",
|
||||
UnMapId (Id), (char *)(FILE_), __LINE__));
|
||||
Info = _FACILITY_NOT_SUPPORTED;
|
||||
break;
|
||||
}
|
||||
if (plci->internal_command)
|
||||
|
@ -12448,13 +12438,11 @@ static byte mixer_request (dword Id, word Number, DIVA_CAPI_ADAPTER *a, PLCI
|
|||
static void mixer_indication_coefs_set (dword Id, PLCI *plci)
|
||||
{
|
||||
dword d;
|
||||
DIVA_CAPI_ADAPTER *a;
|
||||
byte result[12];
|
||||
|
||||
dbug (1, dprintf ("[%06lx] %s,%d: mixer_indication_coefs_set",
|
||||
UnMapId (Id), (char *)(FILE_), __LINE__));
|
||||
|
||||
a = plci->adapter;
|
||||
if (plci->li_plci_b_read_pos != plci->li_plci_b_req_pos)
|
||||
{
|
||||
do
|
||||
|
@ -14111,13 +14099,11 @@ static void select_b_command (dword Id, PLCI *plci, byte Rc)
|
|||
|
||||
static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc)
|
||||
{
|
||||
word Info;
|
||||
word internal_command;
|
||||
|
||||
dbug (1, dprintf ("[%06lx] %s,%d: fax_connect_ack_command %02x %04x",
|
||||
UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
|
||||
|
||||
Info = GOOD;
|
||||
internal_command = plci->internal_command;
|
||||
plci->internal_command = 0;
|
||||
switch (internal_command)
|
||||
|
@ -14160,13 +14146,11 @@ static void fax_connect_ack_command (dword Id, PLCI *plci, byte Rc)
|
|||
|
||||
static void fax_edata_ack_command (dword Id, PLCI *plci, byte Rc)
|
||||
{
|
||||
word Info;
|
||||
word internal_command;
|
||||
|
||||
dbug (1, dprintf ("[%06lx] %s,%d: fax_edata_ack_command %02x %04x",
|
||||
UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
|
||||
|
||||
Info = GOOD;
|
||||
internal_command = plci->internal_command;
|
||||
plci->internal_command = 0;
|
||||
switch (internal_command)
|
||||
|
@ -14395,13 +14379,11 @@ static void rtp_connect_b3_req_command (dword Id, PLCI *plci, byte Rc)
|
|||
|
||||
static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc)
|
||||
{
|
||||
word Info;
|
||||
word internal_command;
|
||||
|
||||
dbug (1, dprintf ("[%06lx] %s,%d: rtp_connect_b3_res_command %02x %04x",
|
||||
UnMapId (Id), (char *)(FILE_), __LINE__, Rc, plci->internal_command));
|
||||
|
||||
Info = GOOD;
|
||||
internal_command = plci->internal_command;
|
||||
plci->internal_command = 0;
|
||||
switch (internal_command)
|
||||
|
@ -14423,7 +14405,6 @@ static void rtp_connect_b3_res_command (dword Id, PLCI *plci, byte Rc)
|
|||
{
|
||||
dbug (1, dprintf ("[%06lx] %s,%d: RTP setting connect resp info failed %02x",
|
||||
UnMapId (Id), (char *)(FILE_), __LINE__, Rc));
|
||||
Info = _WRONG_STATE;
|
||||
break;
|
||||
}
|
||||
if (plci_nl_busy (plci))
|
||||
|
|
|
@ -405,7 +405,7 @@ hfcpci_empty_bfifo(struct bchannel *bch, struct bzfifo *bz,
|
|||
u_char *bdata, int count)
|
||||
{
|
||||
u_char *ptr, *ptr1, new_f2;
|
||||
int total, maxlen, new_z2;
|
||||
int maxlen, new_z2;
|
||||
struct zt *zp;
|
||||
|
||||
if ((bch->debug & DEBUG_HW_BCHANNEL) && !(bch->debug & DEBUG_HW_BFIFO))
|
||||
|
@ -431,7 +431,6 @@ hfcpci_empty_bfifo(struct bchannel *bch, struct bzfifo *bz,
|
|||
printk(KERN_WARNING "HFCPCI: receive out of memory\n");
|
||||
return;
|
||||
}
|
||||
total = count;
|
||||
count -= 3;
|
||||
ptr = skb_put(bch->rx_skb, count);
|
||||
|
||||
|
@ -968,7 +967,6 @@ static void
|
|||
ph_state_nt(struct dchannel *dch)
|
||||
{
|
||||
struct hfc_pci *hc = dch->hw;
|
||||
u_char val;
|
||||
|
||||
if (dch->debug)
|
||||
printk(KERN_DEBUG "%s: NT newstate %x\n",
|
||||
|
@ -982,7 +980,7 @@ ph_state_nt(struct dchannel *dch)
|
|||
hc->hw.int_m1 &= ~HFCPCI_INTS_TIMER;
|
||||
Write_hfc(hc, HFCPCI_INT_M1, hc->hw.int_m1);
|
||||
/* Clear already pending ints */
|
||||
val = Read_hfc(hc, HFCPCI_INT_S1);
|
||||
(void) Read_hfc(hc, HFCPCI_INT_S1);
|
||||
Write_hfc(hc, HFCPCI_STATES, 4 | HFCPCI_LOAD_STATE);
|
||||
udelay(10);
|
||||
Write_hfc(hc, HFCPCI_STATES, 4);
|
||||
|
|
|
@ -118,14 +118,12 @@ static void
|
|||
ctrl_complete(struct urb *urb)
|
||||
{
|
||||
struct hfcsusb *hw = (struct hfcsusb *) urb->context;
|
||||
struct ctrl_buf *buf;
|
||||
|
||||
if (debug & DBG_HFC_CALL_TRACE)
|
||||
printk(KERN_DEBUG "%s: %s\n", hw->name, __func__);
|
||||
|
||||
urb->dev = hw->dev;
|
||||
if (hw->ctrl_cnt) {
|
||||
buf = &hw->ctrl_buff[hw->ctrl_out_idx];
|
||||
hw->ctrl_cnt--; /* decrement actual count */
|
||||
if (++hw->ctrl_out_idx >= HFC_CTRL_BUFSIZE)
|
||||
hw->ctrl_out_idx = 0; /* pointer wrap */
|
||||
|
@ -1726,7 +1724,6 @@ hfcsusb_stop_endpoint(struct hfcsusb *hw, int channel)
|
|||
static int
|
||||
setup_hfcsusb(struct hfcsusb *hw)
|
||||
{
|
||||
int err;
|
||||
u_char b;
|
||||
|
||||
if (debug & DBG_HFC_CALL_TRACE)
|
||||
|
@ -1745,7 +1742,7 @@ setup_hfcsusb(struct hfcsusb *hw)
|
|||
}
|
||||
|
||||
/* first set the needed config, interface and alternate */
|
||||
err = usb_set_interface(hw->dev, hw->if_used, hw->alt_used);
|
||||
(void) usb_set_interface(hw->dev, hw->if_used, hw->alt_used);
|
||||
|
||||
hw->led_state = 0;
|
||||
|
||||
|
|
|
@ -30,8 +30,6 @@ add_arcofi_timer(struct IsdnCardState *cs) {
|
|||
|
||||
static void
|
||||
send_arcofi(struct IsdnCardState *cs) {
|
||||
u_char val;
|
||||
|
||||
add_arcofi_timer(cs);
|
||||
cs->dc.isac.mon_txp = 0;
|
||||
cs->dc.isac.mon_txc = cs->dc.isac.arcofi_list->len;
|
||||
|
@ -45,7 +43,7 @@ send_arcofi(struct IsdnCardState *cs) {
|
|||
cs->dc.isac.mocr &= 0x0f;
|
||||
cs->dc.isac.mocr |= 0xa0;
|
||||
cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
|
||||
val = cs->readisac(cs, ISAC_MOSR);
|
||||
(void) cs->readisac(cs, ISAC_MOSR);
|
||||
cs->writeisac(cs, ISAC_MOX1, cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]);
|
||||
cs->dc.isac.mocr |= 0x10;
|
||||
cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
|
||||
|
|
|
@ -129,12 +129,10 @@ static int elsa_cs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
|
|||
|
||||
static int __devinit elsa_cs_config(struct pcmcia_device *link)
|
||||
{
|
||||
local_info_t *dev;
|
||||
int i;
|
||||
IsdnCard_t icard;
|
||||
|
||||
dev_dbg(&link->dev, "elsa_config(0x%p)\n", link);
|
||||
dev = link->priv;
|
||||
|
||||
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
|
||||
|
||||
|
|
|
@ -109,11 +109,10 @@ static void change_speed(struct IsdnCardState *cs, int baud)
|
|||
{
|
||||
int quot = 0, baud_base;
|
||||
unsigned cval, fcr = 0;
|
||||
int bits;
|
||||
|
||||
|
||||
/* byte size and parity */
|
||||
cval = 0x03; bits = 10;
|
||||
cval = 0x03;
|
||||
/* Determine divisor based on baud rate */
|
||||
baud_base = BASE_BAUD;
|
||||
quot = baud_base / baud;
|
||||
|
|
|
@ -258,11 +258,9 @@ static void
|
|||
ctrl_complete(struct urb *urb)
|
||||
{
|
||||
hfcusb_data *hfc = (hfcusb_data *) urb->context;
|
||||
ctrl_buft *buf;
|
||||
|
||||
urb->dev = hfc->dev;
|
||||
if (hfc->ctrl_cnt) {
|
||||
buf = &hfc->ctrl_buff[hfc->ctrl_out_idx];
|
||||
hfc->ctrl_cnt--; /* decrement actual count */
|
||||
if (++hfc->ctrl_out_idx >= HFC_CTRL_BUFSIZE)
|
||||
hfc->ctrl_out_idx = 0; /* pointer wrap */
|
||||
|
@ -1097,7 +1095,7 @@ static int
|
|||
hfc_usb_init(hfcusb_data * hfc)
|
||||
{
|
||||
usb_fifo *fifo;
|
||||
int i, err;
|
||||
int i;
|
||||
u_char b;
|
||||
struct hisax_b_if *p_b_if[2];
|
||||
|
||||
|
@ -1112,7 +1110,7 @@ hfc_usb_init(hfcusb_data * hfc)
|
|||
}
|
||||
|
||||
/* first set the needed config, interface and alternate */
|
||||
err = usb_set_interface(hfc->dev, hfc->if_used, hfc->alt_used);
|
||||
usb_set_interface(hfc->dev, hfc->if_used, hfc->alt_used);
|
||||
|
||||
/* do Chip reset */
|
||||
write_usb(hfc, HFCUSB_CIRM, 8);
|
||||
|
|
|
@ -96,7 +96,7 @@ dch_l2l1(struct PStack *st, int pr, void *arg)
|
|||
{
|
||||
struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
|
||||
struct sk_buff *skb = arg;
|
||||
u_char cda1_cr, cda2_cr;
|
||||
u_char cda1_cr;
|
||||
|
||||
switch (pr) {
|
||||
case (PH_DATA |REQUEST):
|
||||
|
@ -163,7 +163,7 @@ dch_l2l1(struct PStack *st, int pr, void *arg)
|
|||
cs->writeisac(cs, IPACX_CDA_TSDP10, 0x80); // Timeslot 0 is B1
|
||||
cs->writeisac(cs, IPACX_CDA_TSDP11, 0x81); // Timeslot 0 is B1
|
||||
cda1_cr = cs->readisac(cs, IPACX_CDA1_CR);
|
||||
cda2_cr = cs->readisac(cs, IPACX_CDA2_CR);
|
||||
(void) cs->readisac(cs, IPACX_CDA2_CR);
|
||||
if ((long)arg &1) { // loop B1
|
||||
cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr |0x0a);
|
||||
}
|
||||
|
|
|
@ -23,10 +23,9 @@
|
|||
int
|
||||
JadeVersion(struct IsdnCardState *cs, char *s)
|
||||
{
|
||||
int ver,i;
|
||||
int ver;
|
||||
int to = 50;
|
||||
cs->BC_Write_Reg(cs, -1, 0x50, 0x19);
|
||||
i=0;
|
||||
while (to) {
|
||||
udelay(1);
|
||||
ver = cs->BC_Read_Reg(cs, -1, 0x60);
|
||||
|
|
|
@ -2943,7 +2943,7 @@ global_handler(struct PStack *st, int mt, struct sk_buff *skb)
|
|||
static void
|
||||
dss1up(struct PStack *st, int pr, void *arg)
|
||||
{
|
||||
int i, mt, cr, cause, callState;
|
||||
int i, mt, cr, callState;
|
||||
char *ptr;
|
||||
u_char *p;
|
||||
struct sk_buff *skb = arg;
|
||||
|
@ -3034,12 +3034,10 @@ dss1up(struct PStack *st, int pr, void *arg)
|
|||
return;
|
||||
}
|
||||
} else if (mt == MT_STATUS) {
|
||||
cause = 0;
|
||||
if ((ptr = findie(skb->data, skb->len, IE_CAUSE, 0)) != NULL) {
|
||||
ptr++;
|
||||
if (*ptr++ == 2)
|
||||
ptr++;
|
||||
cause = *ptr & 0x7f;
|
||||
}
|
||||
callState = 0;
|
||||
if ((ptr = findie(skb->data, skb->len, IE_CALL_STATE, 0)) != NULL) {
|
||||
|
|
|
@ -2883,7 +2883,7 @@ global_handler(struct PStack *st, int mt, struct sk_buff *skb)
|
|||
static void
|
||||
ni1up(struct PStack *st, int pr, void *arg)
|
||||
{
|
||||
int i, mt, cr, cause, callState;
|
||||
int i, mt, cr, callState;
|
||||
char *ptr;
|
||||
u_char *p;
|
||||
struct sk_buff *skb = arg;
|
||||
|
@ -2986,12 +2986,10 @@ ni1up(struct PStack *st, int pr, void *arg)
|
|||
return;
|
||||
}
|
||||
} else if (mt == MT_STATUS) {
|
||||
cause = 0;
|
||||
if ((ptr = findie(skb->data, skb->len, IE_CAUSE, 0)) != NULL) {
|
||||
ptr++;
|
||||
if (*ptr++ == 2)
|
||||
ptr++;
|
||||
cause = *ptr & 0x7f;
|
||||
}
|
||||
callState = 0;
|
||||
if ((ptr = findie(skb->data, skb->len, IE_CALL_STATE, 0)) != NULL) {
|
||||
|
|
|
@ -377,7 +377,6 @@ struct st5481_bcs {
|
|||
};
|
||||
|
||||
struct st5481_adapter {
|
||||
struct list_head list;
|
||||
int number_of_leds;
|
||||
struct usb_device *usb_dev;
|
||||
struct hisax_d_if hisax_d_if;
|
||||
|
|
|
@ -46,8 +46,6 @@ module_param(debug, int, 0);
|
|||
#endif
|
||||
int st5481_debug;
|
||||
|
||||
static LIST_HEAD(adapter_list);
|
||||
|
||||
/* ======================================================================
|
||||
* registration/deregistration with the USB layer
|
||||
*/
|
||||
|
@ -86,7 +84,6 @@ static int probe_st5481(struct usb_interface *intf,
|
|||
adapter->bcs[i].b_if.ifc.priv = &adapter->bcs[i];
|
||||
adapter->bcs[i].b_if.ifc.l2l1 = st5481_b_l2l1;
|
||||
}
|
||||
list_add(&adapter->list, &adapter_list);
|
||||
|
||||
retval = st5481_setup_usb(adapter);
|
||||
if (retval < 0)
|
||||
|
@ -125,6 +122,7 @@ static int probe_st5481(struct usb_interface *intf,
|
|||
err_usb:
|
||||
st5481_release_usb(adapter);
|
||||
err:
|
||||
kfree(adapter);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -142,8 +140,6 @@ static void disconnect_st5481(struct usb_interface *intf)
|
|||
if (!adapter)
|
||||
return;
|
||||
|
||||
list_del(&adapter->list);
|
||||
|
||||
st5481_stop(adapter);
|
||||
st5481_release_b(&adapter->bcs[1]);
|
||||
st5481_release_b(&adapter->bcs[0]);
|
||||
|
|
|
@ -111,12 +111,10 @@ static int teles_cs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
|
|||
|
||||
static int __devinit teles_cs_config(struct pcmcia_device *link)
|
||||
{
|
||||
local_info_t *dev;
|
||||
int i;
|
||||
IsdnCard_t icard;
|
||||
|
||||
dev_dbg(&link->dev, "teles_config(0x%p)\n", link);
|
||||
dev = link->priv;
|
||||
|
||||
i = pcmcia_loop_config(link, teles_cs_configcheck, NULL);
|
||||
if (i != 0)
|
||||
|
|
|
@ -155,7 +155,6 @@ put_log_buffer(hysdn_card * card, char *cp)
|
|||
static ssize_t
|
||||
hysdn_log_write(struct file *file, const char __user *buf, size_t count, loff_t * off)
|
||||
{
|
||||
unsigned long u = 0;
|
||||
int rc;
|
||||
unsigned char valbuf[128];
|
||||
hysdn_card *card = file->private_data;
|
||||
|
@ -167,12 +166,10 @@ hysdn_log_write(struct file *file, const char __user *buf, size_t count, loff_t
|
|||
|
||||
valbuf[count] = 0; /* terminating 0 */
|
||||
|
||||
rc = strict_strtoul(valbuf, 0, &u);
|
||||
|
||||
if (rc == 0) {
|
||||
card->debug_flags = u; /* remember debug flags */
|
||||
hysdn_addlog(card, "debug set to 0x%lx", card->debug_flags);
|
||||
}
|
||||
rc = kstrtoul(valbuf, 0, &card->debug_flags);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
hysdn_addlog(card, "debug set to 0x%lx", card->debug_flags);
|
||||
return (count);
|
||||
} /* hysdn_log_write */
|
||||
|
||||
|
|
|
@ -399,13 +399,8 @@ isdn_all_eaz(int di, int ch)
|
|||
#include <linux/isdn/capicmd.h>
|
||||
|
||||
static int
|
||||
isdn_capi_rec_hl_msg(capi_msg *cm) {
|
||||
|
||||
int di;
|
||||
int ch;
|
||||
|
||||
di = (cm->adr.Controller & 0x7f) -1;
|
||||
ch = isdn_dc2minor(di, (cm->adr.Controller>>8)& 0x7f);
|
||||
isdn_capi_rec_hl_msg(capi_msg *cm)
|
||||
{
|
||||
switch(cm->Command) {
|
||||
case CAPI_FACILITY:
|
||||
/* in the moment only handled in tty */
|
||||
|
@ -1278,7 +1273,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
|
|||
uint minor = iminor(file->f_path.dentry->d_inode);
|
||||
isdn_ctrl c;
|
||||
int drvidx;
|
||||
int chidx;
|
||||
int ret;
|
||||
int i;
|
||||
char __user *p;
|
||||
|
@ -1340,7 +1334,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
|
|||
drvidx = isdn_minor2drv(minor);
|
||||
if (drvidx < 0)
|
||||
return -ENODEV;
|
||||
chidx = isdn_minor2chan(minor);
|
||||
if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
|
||||
return -ENODEV;
|
||||
return 0;
|
||||
|
|
|
@ -1678,7 +1678,6 @@ isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb)
|
|||
u32 your_seq;
|
||||
__be32 local;
|
||||
__be32 *addr, *mask;
|
||||
u16 unused;
|
||||
|
||||
if (skb->len < 14)
|
||||
return;
|
||||
|
@ -1722,7 +1721,6 @@ isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb)
|
|||
lp->cisco_last_slarp_in = jiffies;
|
||||
my_seq = be32_to_cpup((__be32 *)(p + 0));
|
||||
your_seq = be32_to_cpup((__be32 *)(p + 4));
|
||||
unused = be16_to_cpup((__be16 *)(p + 8));
|
||||
p += 10;
|
||||
lp->cisco_yourseq = my_seq;
|
||||
lp->cisco_mineseen = your_seq;
|
||||
|
|
|
@ -998,7 +998,6 @@ isdn_tty_change_speed(modem_info * info)
|
|||
{
|
||||
uint cflag,
|
||||
cval,
|
||||
fcr,
|
||||
quot;
|
||||
int i;
|
||||
|
||||
|
@ -1037,7 +1036,6 @@ isdn_tty_change_speed(modem_info * info)
|
|||
cval |= UART_LCR_PARITY;
|
||||
if (!(cflag & PARODD))
|
||||
cval |= UART_LCR_EPAR;
|
||||
fcr = 0;
|
||||
|
||||
/* CTS flow control flag and modem status interrupts */
|
||||
if (cflag & CRTSCTS) {
|
||||
|
|
|
@ -1640,7 +1640,7 @@ l2_tei_remove(struct FsmInst *fi, int event, void *arg)
|
|||
}
|
||||
|
||||
static void
|
||||
l2_st14_persistant_da(struct FsmInst *fi, int event, void *arg)
|
||||
l2_st14_persistent_da(struct FsmInst *fi, int event, void *arg)
|
||||
{
|
||||
struct layer2 *l2 = fi->userdata;
|
||||
struct sk_buff *skb = arg;
|
||||
|
@ -1654,7 +1654,7 @@ l2_st14_persistant_da(struct FsmInst *fi, int event, void *arg)
|
|||
}
|
||||
|
||||
static void
|
||||
l2_st5_persistant_da(struct FsmInst *fi, int event, void *arg)
|
||||
l2_st5_persistent_da(struct FsmInst *fi, int event, void *arg)
|
||||
{
|
||||
struct layer2 *l2 = fi->userdata;
|
||||
struct sk_buff *skb = arg;
|
||||
|
@ -1671,7 +1671,7 @@ l2_st5_persistant_da(struct FsmInst *fi, int event, void *arg)
|
|||
}
|
||||
|
||||
static void
|
||||
l2_st6_persistant_da(struct FsmInst *fi, int event, void *arg)
|
||||
l2_st6_persistent_da(struct FsmInst *fi, int event, void *arg)
|
||||
{
|
||||
struct layer2 *l2 = fi->userdata;
|
||||
struct sk_buff *skb = arg;
|
||||
|
@ -1685,7 +1685,7 @@ l2_st6_persistant_da(struct FsmInst *fi, int event, void *arg)
|
|||
}
|
||||
|
||||
static void
|
||||
l2_persistant_da(struct FsmInst *fi, int event, void *arg)
|
||||
l2_persistent_da(struct FsmInst *fi, int event, void *arg)
|
||||
{
|
||||
struct layer2 *l2 = fi->userdata;
|
||||
struct sk_buff *skb = arg;
|
||||
|
@ -1829,14 +1829,14 @@ static struct FsmNode L2FnList[] =
|
|||
{ST_L2_6, EV_L2_FRAME_ERROR, l2_frame_error},
|
||||
{ST_L2_7, EV_L2_FRAME_ERROR, l2_frame_error_reest},
|
||||
{ST_L2_8, EV_L2_FRAME_ERROR, l2_frame_error_reest},
|
||||
{ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistant_da},
|
||||
{ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistent_da},
|
||||
{ST_L2_2, EV_L1_DEACTIVATE, l2_st24_tei_remove},
|
||||
{ST_L2_3, EV_L1_DEACTIVATE, l2_st3_tei_remove},
|
||||
{ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistant_da},
|
||||
{ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistant_da},
|
||||
{ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistant_da},
|
||||
{ST_L2_7, EV_L1_DEACTIVATE, l2_persistant_da},
|
||||
{ST_L2_8, EV_L1_DEACTIVATE, l2_persistant_da},
|
||||
{ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistent_da},
|
||||
{ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistent_da},
|
||||
{ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistent_da},
|
||||
{ST_L2_7, EV_L1_DEACTIVATE, l2_persistent_da},
|
||||
{ST_L2_8, EV_L1_DEACTIVATE, l2_persistent_da},
|
||||
};
|
||||
|
||||
static int
|
||||
|
|
|
@ -457,6 +457,9 @@ static int data_sock_getsockopt(struct socket *sock, int level, int optname,
|
|||
if (get_user(len, optlen))
|
||||
return -EFAULT;
|
||||
|
||||
if (len != sizeof(char))
|
||||
return -EINVAL;
|
||||
|
||||
switch (optname) {
|
||||
case MISDN_TIME_STAMP:
|
||||
if (_pms(sk)->cmask & MISDN_TIME_STAMP)
|
||||
|
|
|
@ -185,7 +185,7 @@ static int max_interrupt_work = 10;
|
|||
static int nopnp;
|
||||
#endif
|
||||
|
||||
static int __devinit el3_common_init(struct net_device *dev);
|
||||
static int el3_common_init(struct net_device *dev);
|
||||
static void el3_common_remove(struct net_device *dev);
|
||||
static ushort id_read_eeprom(int index);
|
||||
static ushort read_eeprom(int ioaddr, int index);
|
||||
|
@ -395,7 +395,7 @@ static struct isa_driver el3_isa_driver = {
|
|||
static int isa_registered;
|
||||
|
||||
#ifdef CONFIG_PNP
|
||||
static struct pnp_device_id el3_pnp_ids[] = {
|
||||
static const struct pnp_device_id el3_pnp_ids[] __devinitconst = {
|
||||
{ .id = "TCM5090" }, /* 3Com Etherlink III (TP) */
|
||||
{ .id = "TCM5091" }, /* 3Com Etherlink III */
|
||||
{ .id = "TCM5094" }, /* 3Com Etherlink III (combo) */
|
||||
|
@ -478,7 +478,7 @@ static int pnp_registered;
|
|||
#endif /* CONFIG_PNP */
|
||||
|
||||
#ifdef CONFIG_EISA
|
||||
static struct eisa_device_id el3_eisa_ids[] = {
|
||||
static const struct eisa_device_id el3_eisa_ids[] __devinitconst = {
|
||||
{ "TCM5090" },
|
||||
{ "TCM5091" },
|
||||
{ "TCM5092" },
|
||||
|
@ -508,7 +508,7 @@ static int eisa_registered;
|
|||
#ifdef CONFIG_MCA
|
||||
static int el3_mca_probe(struct device *dev);
|
||||
|
||||
static short el3_mca_adapter_ids[] __initdata = {
|
||||
static const short el3_mca_adapter_ids[] __devinitconst = {
|
||||
0x627c,
|
||||
0x627d,
|
||||
0x62db,
|
||||
|
@ -517,7 +517,7 @@ static short el3_mca_adapter_ids[] __initdata = {
|
|||
0x0000
|
||||
};
|
||||
|
||||
static char *el3_mca_adapter_names[] __initdata = {
|
||||
static const char *const el3_mca_adapter_names[] __devinitconst = {
|
||||
"3Com 3c529 EtherLink III (10base2)",
|
||||
"3Com 3c529 EtherLink III (10baseT)",
|
||||
"3Com 3c529 EtherLink III (test mode)",
|
||||
|
@ -601,7 +601,7 @@ static void el3_common_remove (struct net_device *dev)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_MCA
|
||||
static int __init el3_mca_probe(struct device *device)
|
||||
static int __devinit el3_mca_probe(struct device *device)
|
||||
{
|
||||
/* Based on Erik Nygren's (nygren@mit.edu) 3c529 patch,
|
||||
* heavily modified by Chris Beauregard
|
||||
|
@ -671,7 +671,7 @@ static int __init el3_mca_probe(struct device *device)
|
|||
#endif /* CONFIG_MCA */
|
||||
|
||||
#ifdef CONFIG_EISA
|
||||
static int __init el3_eisa_probe (struct device *device)
|
||||
static int __devinit el3_eisa_probe (struct device *device)
|
||||
{
|
||||
short i;
|
||||
int ioaddr, irq, if_port;
|
||||
|
@ -1207,7 +1207,7 @@ el3_netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
|
|||
ecmd->duplex = DUPLEX_FULL;
|
||||
}
|
||||
|
||||
ecmd->speed = SPEED_10;
|
||||
ethtool_cmd_speed_set(ecmd, SPEED_10);
|
||||
EL3WINDOW(1);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -901,14 +901,14 @@ static const struct dev_pm_ops vortex_pm_ops = {
|
|||
#endif /* !CONFIG_PM */
|
||||
|
||||
#ifdef CONFIG_EISA
|
||||
static struct eisa_device_id vortex_eisa_ids[] = {
|
||||
static const struct eisa_device_id vortex_eisa_ids[] __devinitconst = {
|
||||
{ "TCM5920", CH_3C592 },
|
||||
{ "TCM5970", CH_3C597 },
|
||||
{ "" }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(eisa, vortex_eisa_ids);
|
||||
|
||||
static int __init vortex_eisa_probe(struct device *device)
|
||||
static int __devinit vortex_eisa_probe(struct device *device)
|
||||
{
|
||||
void __iomem *ioaddr;
|
||||
struct eisa_device *edev;
|
||||
|
|
|
@ -758,8 +758,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
|
|||
|
||||
entry = cp->tx_head;
|
||||
eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
|
||||
if (dev->features & NETIF_F_TSO)
|
||||
mss = skb_shinfo(skb)->gso_size;
|
||||
mss = skb_shinfo(skb)->gso_size;
|
||||
|
||||
if (skb_shinfo(skb)->nr_frags == 0) {
|
||||
struct cp_desc *txd = &cp->tx_ring[entry];
|
||||
|
@ -1416,32 +1415,23 @@ static void cp_set_msglevel(struct net_device *dev, u32 value)
|
|||
cp->msg_enable = value;
|
||||
}
|
||||
|
||||
static u32 cp_get_rx_csum(struct net_device *dev)
|
||||
static int cp_set_features(struct net_device *dev, u32 features)
|
||||
{
|
||||
struct cp_private *cp = netdev_priv(dev);
|
||||
return (cpr16(CpCmd) & RxChkSum) ? 1 : 0;
|
||||
}
|
||||
unsigned long flags;
|
||||
|
||||
static int cp_set_rx_csum(struct net_device *dev, u32 data)
|
||||
{
|
||||
struct cp_private *cp = netdev_priv(dev);
|
||||
u16 cmd = cp->cpcmd, newcmd;
|
||||
if (!((dev->features ^ features) & NETIF_F_RXCSUM))
|
||||
return 0;
|
||||
|
||||
newcmd = cmd;
|
||||
spin_lock_irqsave(&cp->lock, flags);
|
||||
|
||||
if (data)
|
||||
newcmd |= RxChkSum;
|
||||
if (features & NETIF_F_RXCSUM)
|
||||
cp->cpcmd |= RxChkSum;
|
||||
else
|
||||
newcmd &= ~RxChkSum;
|
||||
cp->cpcmd &= ~RxChkSum;
|
||||
|
||||
if (newcmd != cmd) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&cp->lock, flags);
|
||||
cp->cpcmd = newcmd;
|
||||
cpw16_f(CpCmd, newcmd);
|
||||
spin_unlock_irqrestore(&cp->lock, flags);
|
||||
}
|
||||
cpw16_f(CpCmd, cp->cpcmd);
|
||||
spin_unlock_irqrestore(&cp->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1554,11 +1544,6 @@ static const struct ethtool_ops cp_ethtool_ops = {
|
|||
.get_link = ethtool_op_get_link,
|
||||
.get_msglevel = cp_get_msglevel,
|
||||
.set_msglevel = cp_set_msglevel,
|
||||
.get_rx_csum = cp_get_rx_csum,
|
||||
.set_rx_csum = cp_set_rx_csum,
|
||||
.set_tx_csum = ethtool_op_set_tx_csum, /* local! */
|
||||
.set_sg = ethtool_op_set_sg,
|
||||
.set_tso = ethtool_op_set_tso,
|
||||
.get_regs = cp_get_regs,
|
||||
.get_wol = cp_get_wol,
|
||||
.set_wol = cp_set_wol,
|
||||
|
@ -1831,6 +1816,7 @@ static const struct net_device_ops cp_netdev_ops = {
|
|||
.ndo_do_ioctl = cp_ioctl,
|
||||
.ndo_start_xmit = cp_start_xmit,
|
||||
.ndo_tx_timeout = cp_tx_timeout,
|
||||
.ndo_set_features = cp_set_features,
|
||||
#if CP_VLAN_TAG_USED
|
||||
.ndo_vlan_rx_register = cp_vlan_rx_register,
|
||||
#endif
|
||||
|
@ -1934,6 +1920,9 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
cp->cpcmd = (pci_using_dac ? PCIDAC : 0) |
|
||||
PCIMulRW | RxChkSum | CpRxOn | CpTxOn;
|
||||
|
||||
dev->features |= NETIF_F_RXCSUM;
|
||||
dev->hw_features |= NETIF_F_RXCSUM;
|
||||
|
||||
regs = ioremap(pciaddr, CP_REGS_SIZE);
|
||||
if (!regs) {
|
||||
rc = -EIO;
|
||||
|
@ -1966,9 +1955,8 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
if (pci_using_dac)
|
||||
dev->features |= NETIF_F_HIGHDMA;
|
||||
|
||||
#if 0 /* disabled by default until verified */
|
||||
dev->features |= NETIF_F_TSO;
|
||||
#endif
|
||||
/* disabled by default until verified */
|
||||
dev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
|
||||
|
||||
dev->irq = pdev->irq;
|
||||
|
||||
|
|
|
@ -2659,15 +2659,15 @@ static int ace_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
|
|||
|
||||
link = readl(®s->GigLnkState);
|
||||
if (link & LNK_1000MB)
|
||||
ecmd->speed = SPEED_1000;
|
||||
ethtool_cmd_speed_set(ecmd, SPEED_1000);
|
||||
else {
|
||||
link = readl(®s->FastLnkState);
|
||||
if (link & LNK_100MB)
|
||||
ecmd->speed = SPEED_100;
|
||||
ethtool_cmd_speed_set(ecmd, SPEED_100);
|
||||
else if (link & LNK_10MB)
|
||||
ecmd->speed = SPEED_10;
|
||||
ethtool_cmd_speed_set(ecmd, SPEED_10);
|
||||
else
|
||||
ecmd->speed = 0;
|
||||
ethtool_cmd_speed_set(ecmd, 0);
|
||||
}
|
||||
if (link & LNK_FULL_DUPLEX)
|
||||
ecmd->duplex = DUPLEX_FULL;
|
||||
|
@ -2719,9 +2719,9 @@ static int ace_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
|
|||
link |= LNK_TX_FLOW_CTL_Y;
|
||||
if (ecmd->autoneg == AUTONEG_ENABLE)
|
||||
link |= LNK_NEGOTIATE;
|
||||
if (ecmd->speed != speed) {
|
||||
if (ethtool_cmd_speed(ecmd) != speed) {
|
||||
link &= ~(LNK_1000MB | LNK_100MB | LNK_10MB);
|
||||
switch (speed) {
|
||||
switch (ethtool_cmd_speed(ecmd)) {
|
||||
case SPEED_1000:
|
||||
link |= LNK_1000MB;
|
||||
break;
|
||||
|
|
|
@ -591,10 +591,11 @@ static void etherh_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *i
|
|||
static int etherh_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
||||
{
|
||||
cmd->supported = etherh_priv(dev)->supported;
|
||||
cmd->speed = SPEED_10;
|
||||
ethtool_cmd_speed_set(cmd, SPEED_10);
|
||||
cmd->duplex = DUPLEX_HALF;
|
||||
cmd->port = dev->if_port == IF_PORT_10BASET ? PORT_TP : PORT_BNC;
|
||||
cmd->autoneg = dev->flags & IFF_AUTOMEDIA ? AUTONEG_ENABLE : AUTONEG_DISABLE;
|
||||
cmd->autoneg = (dev->flags & IFF_AUTOMEDIA ?
|
||||
AUTONEG_ENABLE : AUTONEG_DISABLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -891,15 +891,16 @@ ks8695_wan_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
|
|||
cmd->advertising |= ADVERTISED_Pause;
|
||||
cmd->autoneg = AUTONEG_ENABLE;
|
||||
|
||||
cmd->speed = (ctrl & WMC_WSS) ? SPEED_100 : SPEED_10;
|
||||
ethtool_cmd_speed_set(cmd,
|
||||
(ctrl & WMC_WSS) ? SPEED_100 : SPEED_10);
|
||||
cmd->duplex = (ctrl & WMC_WDS) ?
|
||||
DUPLEX_FULL : DUPLEX_HALF;
|
||||
} else {
|
||||
/* auto-negotiation is disabled */
|
||||
cmd->autoneg = AUTONEG_DISABLE;
|
||||
|
||||
cmd->speed = (ctrl & WMC_WANF100) ?
|
||||
SPEED_100 : SPEED_10;
|
||||
ethtool_cmd_speed_set(cmd, ((ctrl & WMC_WANF100) ?
|
||||
SPEED_100 : SPEED_10));
|
||||
cmd->duplex = (ctrl & WMC_WANFF) ?
|
||||
DUPLEX_FULL : DUPLEX_HALF;
|
||||
}
|
||||
|
|
|
@ -50,13 +50,13 @@ static int atl1c_get_settings(struct net_device *netdev,
|
|||
ecmd->transceiver = XCVR_INTERNAL;
|
||||
|
||||
if (adapter->link_speed != SPEED_0) {
|
||||
ecmd->speed = adapter->link_speed;
|
||||
ethtool_cmd_speed_set(ecmd, adapter->link_speed);
|
||||
if (adapter->link_duplex == FULL_DUPLEX)
|
||||
ecmd->duplex = DUPLEX_FULL;
|
||||
else
|
||||
ecmd->duplex = DUPLEX_HALF;
|
||||
} else {
|
||||
ecmd->speed = -1;
|
||||
ethtool_cmd_speed_set(ecmd, -1);
|
||||
ecmd->duplex = -1;
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,8 @@ static int atl1c_set_settings(struct net_device *netdev,
|
|||
if (ecmd->autoneg == AUTONEG_ENABLE) {
|
||||
autoneg_advertised = ADVERTISED_Autoneg;
|
||||
} else {
|
||||
if (ecmd->speed == SPEED_1000) {
|
||||
u32 speed = ethtool_cmd_speed(ecmd);
|
||||
if (speed == SPEED_1000) {
|
||||
if (ecmd->duplex != DUPLEX_FULL) {
|
||||
if (netif_msg_link(adapter))
|
||||
dev_warn(&adapter->pdev->dev,
|
||||
|
@ -86,7 +87,7 @@ static int atl1c_set_settings(struct net_device *netdev,
|
|||
return -EINVAL;
|
||||
}
|
||||
autoneg_advertised = ADVERTISED_1000baseT_Full;
|
||||
} else if (ecmd->speed == SPEED_100) {
|
||||
} else if (speed == SPEED_100) {
|
||||
if (ecmd->duplex == DUPLEX_FULL)
|
||||
autoneg_advertised = ADVERTISED_100baseT_Full;
|
||||
else
|
||||
|
@ -113,11 +114,6 @@ static int atl1c_set_settings(struct net_device *netdev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static u32 atl1c_get_tx_csum(struct net_device *netdev)
|
||||
{
|
||||
return (netdev->features & NETIF_F_HW_CSUM) != 0;
|
||||
}
|
||||
|
||||
static u32 atl1c_get_msglevel(struct net_device *netdev)
|
||||
{
|
||||
struct atl1c_adapter *adapter = netdev_priv(netdev);
|
||||
|
@ -307,9 +303,6 @@ static const struct ethtool_ops atl1c_ethtool_ops = {
|
|||
.get_link = ethtool_op_get_link,
|
||||
.get_eeprom_len = atl1c_get_eeprom_len,
|
||||
.get_eeprom = atl1c_get_eeprom,
|
||||
.get_tx_csum = atl1c_get_tx_csum,
|
||||
.get_sg = ethtool_op_get_sg,
|
||||
.set_sg = ethtool_op_set_sg,
|
||||
};
|
||||
|
||||
void atl1c_set_ethtool_ops(struct net_device *netdev)
|
||||
|
|
|
@ -480,6 +480,15 @@ static void atl1c_set_rxbufsize(struct atl1c_adapter *adapter,
|
|||
adapter->rx_buffer_len = mtu > AT_RX_BUF_SIZE ?
|
||||
roundup(mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN, 8) : AT_RX_BUF_SIZE;
|
||||
}
|
||||
|
||||
static u32 atl1c_fix_features(struct net_device *netdev, u32 features)
|
||||
{
|
||||
if (netdev->mtu > MAX_TSO_FRAME_SIZE)
|
||||
features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
/*
|
||||
* atl1c_change_mtu - Change the Maximum Transfer Unit
|
||||
* @netdev: network interface device structure
|
||||
|
@ -506,14 +515,8 @@ static int atl1c_change_mtu(struct net_device *netdev, int new_mtu)
|
|||
netdev->mtu = new_mtu;
|
||||
adapter->hw.max_frame_size = new_mtu;
|
||||
atl1c_set_rxbufsize(adapter, netdev);
|
||||
if (new_mtu > MAX_TSO_FRAME_SIZE) {
|
||||
adapter->netdev->features &= ~NETIF_F_TSO;
|
||||
adapter->netdev->features &= ~NETIF_F_TSO6;
|
||||
} else {
|
||||
adapter->netdev->features |= NETIF_F_TSO;
|
||||
adapter->netdev->features |= NETIF_F_TSO6;
|
||||
}
|
||||
atl1c_down(adapter);
|
||||
netdev_update_features(netdev);
|
||||
atl1c_up(adapter);
|
||||
clear_bit(__AT_RESETTING, &adapter->flags);
|
||||
if (adapter->hw.ctrl_flags & ATL1C_FPGA_VERSION) {
|
||||
|
@ -1088,10 +1091,8 @@ static void atl1c_configure_tx(struct atl1c_adapter *adapter)
|
|||
u32 max_pay_load;
|
||||
u16 tx_offload_thresh;
|
||||
u32 txq_ctrl_data;
|
||||
u32 extra_size = 0; /* Jumbo frame threshold in QWORD unit */
|
||||
u32 max_pay_load_data;
|
||||
|
||||
extra_size = ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN;
|
||||
tx_offload_thresh = MAX_TX_OFFLOAD_THRESH;
|
||||
AT_WRITE_REG(hw, REG_TX_TSO_OFFLOAD_THRESH,
|
||||
(tx_offload_thresh >> 3) & TX_TSO_OFFLOAD_THRESH_MASK);
|
||||
|
@ -2536,6 +2537,7 @@ static int atl1c_suspend(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int atl1c_resume(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
|
@ -2562,6 +2564,7 @@ static int atl1c_resume(struct device *dev)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void atl1c_shutdown(struct pci_dev *pdev)
|
||||
{
|
||||
|
@ -2581,6 +2584,7 @@ static const struct net_device_ops atl1c_netdev_ops = {
|
|||
.ndo_set_mac_address = atl1c_set_mac_addr,
|
||||
.ndo_set_multicast_list = atl1c_set_multi,
|
||||
.ndo_change_mtu = atl1c_change_mtu,
|
||||
.ndo_fix_features = atl1c_fix_features,
|
||||
.ndo_do_ioctl = atl1c_ioctl,
|
||||
.ndo_tx_timeout = atl1c_tx_timeout,
|
||||
.ndo_get_stats = atl1c_get_stats,
|
||||
|
@ -2601,12 +2605,13 @@ static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
|
|||
atl1c_set_ethtool_ops(netdev);
|
||||
|
||||
/* TODO: add when ready */
|
||||
netdev->features = NETIF_F_SG |
|
||||
netdev->hw_features = NETIF_F_SG |
|
||||
NETIF_F_HW_CSUM |
|
||||
NETIF_F_HW_VLAN_TX |
|
||||
NETIF_F_HW_VLAN_RX |
|
||||
NETIF_F_TSO |
|
||||
NETIF_F_TSO6;
|
||||
netdev->features = netdev->hw_features |
|
||||
NETIF_F_HW_VLAN_RX;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,13 +51,13 @@ static int atl1e_get_settings(struct net_device *netdev,
|
|||
ecmd->transceiver = XCVR_INTERNAL;
|
||||
|
||||
if (adapter->link_speed != SPEED_0) {
|
||||
ecmd->speed = adapter->link_speed;
|
||||
ethtool_cmd_speed_set(ecmd, adapter->link_speed);
|
||||
if (adapter->link_duplex == FULL_DUPLEX)
|
||||
ecmd->duplex = DUPLEX_FULL;
|
||||
else
|
||||
ecmd->duplex = DUPLEX_HALF;
|
||||
} else {
|
||||
ecmd->speed = -1;
|
||||
ethtool_cmd_speed_set(ecmd, -1);
|
||||
ecmd->duplex = -1;
|
||||
}
|
||||
|
||||
|
@ -382,9 +382,6 @@ static const struct ethtool_ops atl1e_ethtool_ops = {
|
|||
.get_eeprom_len = atl1e_get_eeprom_len,
|
||||
.get_eeprom = atl1e_get_eeprom,
|
||||
.set_eeprom = atl1e_set_eeprom,
|
||||
.set_tx_csum = ethtool_op_set_tx_hw_csum,
|
||||
.set_sg = ethtool_op_set_sg,
|
||||
.set_tso = ethtool_op_set_tso,
|
||||
};
|
||||
|
||||
void atl1e_set_ethtool_ops(struct net_device *netdev)
|
||||
|
|
|
@ -691,10 +691,8 @@ static void atl1e_cal_ring_size(struct atl1e_adapter *adapter, u32 *ring_size)
|
|||
|
||||
static void atl1e_init_ring_resources(struct atl1e_adapter *adapter)
|
||||
{
|
||||
struct atl1e_tx_ring *tx_ring = NULL;
|
||||
struct atl1e_rx_ring *rx_ring = NULL;
|
||||
|
||||
tx_ring = &adapter->tx_ring;
|
||||
rx_ring = &adapter->rx_ring;
|
||||
|
||||
rx_ring->real_page_size = adapter->rx_ring.page_size
|
||||
|
@ -1927,11 +1925,7 @@ void atl1e_down(struct atl1e_adapter *adapter)
|
|||
* reschedule our watchdog timer */
|
||||
set_bit(__AT_DOWN, &adapter->flags);
|
||||
|
||||
#ifdef NETIF_F_LLTX
|
||||
netif_stop_queue(netdev);
|
||||
#else
|
||||
netif_tx_disable(netdev);
|
||||
#endif
|
||||
|
||||
/* reset MAC to disable all RX/TX */
|
||||
atl1e_reset_hw(&adapter->hw);
|
||||
|
@ -2223,10 +2217,10 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
|
|||
netdev->watchdog_timeo = AT_TX_WATCHDOG;
|
||||
atl1e_set_ethtool_ops(netdev);
|
||||
|
||||
netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM |
|
||||
NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
|
||||
netdev->features |= NETIF_F_LLTX;
|
||||
netdev->features |= NETIF_F_TSO;
|
||||
netdev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO |
|
||||
NETIF_F_HW_VLAN_TX;
|
||||
netdev->features = netdev->hw_features |
|
||||
NETIF_F_HW_VLAN_RX | NETIF_F_LLTX;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue