Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
This merge resolves conflicts with 75aec9df3a
("bridge: Remove
br_nf_push_frag_xmit_sk") as part of Eric Biederman's effort to improve
netns support in the network stack that reached upstream via David's
net-next tree.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Conflicts:
net/bridge/br_netfilter_hooks.c
This commit is contained in:
commit
f0a0a978b6
|
@ -0,0 +1,23 @@
|
|||
* Broadcom iProc MDIO bus controller
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "brcm,iproc-mdio"
|
||||
- reg: address and length of the register set for the MDIO interface
|
||||
- #size-cells: must be 1
|
||||
- #address-cells: must be 0
|
||||
|
||||
Child nodes of this MDIO bus controller node are standard Ethernet PHY device
|
||||
nodes as described in Documentation/devicetree/bindings/net/phy.txt
|
||||
|
||||
Example:
|
||||
|
||||
mdio@18002000 {
|
||||
compatible = "brcm,iproc-mdio";
|
||||
reg = <0x18002000 0x8>;
|
||||
#size-cells = <1>;
|
||||
#address-cells = <0>;
|
||||
|
||||
enet-gphy@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
|
@ -57,6 +57,10 @@ Properties:
|
|||
"rgmii-id", as all other connection types are detected by hardware.
|
||||
- fsl,magic-packet : If present, indicates that the hardware supports
|
||||
waking up via magic packet.
|
||||
- fsl,wake-on-filer : If present, indicates that the hardware supports
|
||||
waking up by Filer General Purpose Interrupt (FGPI) asserted on the
|
||||
Rx int line. This is an advanced power management capability allowing
|
||||
certain packet types (user) defined by filer rules to wake up the system.
|
||||
- bd-stash : If present, indicates that the hardware supports stashing
|
||||
buffer descriptors in the L2.
|
||||
- rx-stash-len : Denotes the number of bytes of a received buffer to stash
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
* MRF24J40 IEEE 802.15.4 *
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "microchip,mrf24j40", "microchip,mrf24j40ma",
|
||||
or "microchip,mrf24j40mc" depends on your transceiver
|
||||
board
|
||||
- spi-max-frequency: maximal bus speed, should be set something under or equal
|
||||
10000000
|
||||
- reg: the chipselect index
|
||||
- interrupts: the interrupt generated by the device.
|
||||
|
||||
Example:
|
||||
|
||||
mrf24j40ma@0 {
|
||||
compatible = "microchip,mrf24j40ma";
|
||||
spi-max-frequency = <8500000>;
|
||||
reg = <0>;
|
||||
interrupts = <19 8>;
|
||||
interrupt-parent = <&gpio3>;
|
||||
};
|
|
@ -90,7 +90,304 @@ or to specify the output device using cmsg and IP_PKTINFO.
|
|||
|
||||
Limitations
|
||||
-----------
|
||||
VRF device currently only works for IPv4. Support for IPv6 is under development.
|
||||
|
||||
Index of original ingress interface is not available via cmsg. Will address
|
||||
soon.
|
||||
|
||||
################################################################################
|
||||
|
||||
Using iproute2 for VRFs
|
||||
=======================
|
||||
VRF devices do *not* have to start with 'vrf-'. That is a convention used here
|
||||
for emphasis of the device type, similar to use of 'br' in bridge names.
|
||||
|
||||
1. Create a VRF
|
||||
|
||||
To instantiate a VRF device and associate it with a table:
|
||||
$ ip link add dev NAME type vrf table ID
|
||||
|
||||
Remember to add the ip rules as well:
|
||||
$ ip ru add oif NAME table 10
|
||||
$ ip ru add iif NAME table 10
|
||||
$ ip -6 ru add oif NAME table 10
|
||||
$ ip -6 ru add iif NAME table 10
|
||||
|
||||
Without the rules route lookups are not directed to the table.
|
||||
|
||||
For example:
|
||||
$ ip link add dev vrf-blue type vrf table 10
|
||||
$ ip ru add pref 200 oif vrf-blue table 10
|
||||
$ ip ru add pref 200 iif vrf-blue table 10
|
||||
$ ip -6 ru add pref 200 oif vrf-blue table 10
|
||||
$ ip -6 ru add pref 200 iif vrf-blue table 10
|
||||
|
||||
|
||||
2. List VRFs
|
||||
|
||||
To list VRFs that have been created:
|
||||
$ ip [-d] link show type vrf
|
||||
NOTE: The -d option is needed to show the table id
|
||||
|
||||
For example:
|
||||
$ ip -d link show type vrf
|
||||
11: vrf-mgmt: <NOARP,MASTER,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
|
||||
link/ether 72:b3:ba:91:e2:24 brd ff:ff:ff:ff:ff:ff promiscuity 0
|
||||
vrf table 1 addrgenmode eui64
|
||||
12: vrf-red: <NOARP,MASTER,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
|
||||
link/ether b6:6f:6e:f6:da:73 brd ff:ff:ff:ff:ff:ff promiscuity 0
|
||||
vrf table 10 addrgenmode eui64
|
||||
13: vrf-blue: <NOARP,MASTER,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
|
||||
link/ether 36:62:e8:7d:bb:8c brd ff:ff:ff:ff:ff:ff promiscuity 0
|
||||
vrf table 66 addrgenmode eui64
|
||||
14: vrf-green: <NOARP,MASTER,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
|
||||
link/ether e6:28:b8:63:70:bb brd ff:ff:ff:ff:ff:ff promiscuity 0
|
||||
vrf table 81 addrgenmode eui64
|
||||
|
||||
|
||||
Or in brief output:
|
||||
|
||||
$ ip -br link show type vrf
|
||||
vrf-mgmt UP 72:b3:ba:91:e2:24 <NOARP,MASTER,UP,LOWER_UP>
|
||||
vrf-red UP b6:6f:6e:f6:da:73 <NOARP,MASTER,UP,LOWER_UP>
|
||||
vrf-blue UP 36:62:e8:7d:bb:8c <NOARP,MASTER,UP,LOWER_UP>
|
||||
vrf-green UP e6:28:b8:63:70:bb <NOARP,MASTER,UP,LOWER_UP>
|
||||
|
||||
|
||||
3. Assign a Network Interface to a VRF
|
||||
|
||||
Network interfaces are assigned to a VRF by enslaving the netdevice to a
|
||||
VRF device:
|
||||
$ ip link set dev NAME master VRF-NAME
|
||||
|
||||
On enslavement connected and local routes are automatically moved to the
|
||||
table associated with the VRF device.
|
||||
|
||||
For example:
|
||||
$ ip link set dev eth0 master vrf-mgmt
|
||||
|
||||
|
||||
4. Show Devices Assigned to a VRF
|
||||
|
||||
To show devices that have been assigned to a specific VRF add the master
|
||||
option to the ip command:
|
||||
$ ip link show master VRF-NAME
|
||||
|
||||
For example:
|
||||
$ ip link show master vrf-red
|
||||
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master vrf-red state UP mode DEFAULT group default qlen 1000
|
||||
link/ether 02:00:00:00:02:02 brd ff:ff:ff:ff:ff:ff
|
||||
4: eth2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master vrf-red state UP mode DEFAULT group default qlen 1000
|
||||
link/ether 02:00:00:00:02:03 brd ff:ff:ff:ff:ff:ff
|
||||
7: eth5: <BROADCAST,MULTICAST> mtu 1500 qdisc noop master vrf-red state DOWN mode DEFAULT group default qlen 1000
|
||||
link/ether 02:00:00:00:02:06 brd ff:ff:ff:ff:ff:ff
|
||||
|
||||
|
||||
Or using the brief output:
|
||||
$ ip -br link show master vrf-red
|
||||
eth1 UP 02:00:00:00:02:02 <BROADCAST,MULTICAST,UP,LOWER_UP>
|
||||
eth2 UP 02:00:00:00:02:03 <BROADCAST,MULTICAST,UP,LOWER_UP>
|
||||
eth5 DOWN 02:00:00:00:02:06 <BROADCAST,MULTICAST>
|
||||
|
||||
|
||||
5. Show Neighbor Entries for a VRF
|
||||
|
||||
To list neighbor entries associated with devices enslaved to a VRF device
|
||||
add the master option to the ip command:
|
||||
$ ip [-6] neigh show master VRF-NAME
|
||||
|
||||
For example:
|
||||
$ ip neigh show master vrf-red
|
||||
10.2.1.254 dev eth1 lladdr a6:d9:c7:4f:06:23 REACHABLE
|
||||
10.2.2.254 dev eth2 lladdr 5e:54:01:6a:ee:80 REACHABLE
|
||||
|
||||
$ ip -6 neigh show master vrf-red
|
||||
2002:1::64 dev eth1 lladdr a6:d9:c7:4f:06:23 REACHABLE
|
||||
|
||||
|
||||
6. Show Addresses for a VRF
|
||||
|
||||
To show addresses for interfaces associated with a VRF add the master
|
||||
option to the ip command:
|
||||
$ ip addr show master VRF-NAME
|
||||
|
||||
For example:
|
||||
$ ip addr show master vrf-red
|
||||
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master vrf-red state UP group default qlen 1000
|
||||
link/ether 02:00:00:00:02:02 brd ff:ff:ff:ff:ff:ff
|
||||
inet 10.2.1.2/24 brd 10.2.1.255 scope global eth1
|
||||
valid_lft forever preferred_lft forever
|
||||
inet6 2002:1::2/120 scope global
|
||||
valid_lft forever preferred_lft forever
|
||||
inet6 fe80::ff:fe00:202/64 scope link
|
||||
valid_lft forever preferred_lft forever
|
||||
4: eth2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master vrf-red state UP group default qlen 1000
|
||||
link/ether 02:00:00:00:02:03 brd ff:ff:ff:ff:ff:ff
|
||||
inet 10.2.2.2/24 brd 10.2.2.255 scope global eth2
|
||||
valid_lft forever preferred_lft forever
|
||||
inet6 2002:2::2/120 scope global
|
||||
valid_lft forever preferred_lft forever
|
||||
inet6 fe80::ff:fe00:203/64 scope link
|
||||
valid_lft forever preferred_lft forever
|
||||
7: eth5: <BROADCAST,MULTICAST> mtu 1500 qdisc noop master vrf-red state DOWN group default qlen 1000
|
||||
link/ether 02:00:00:00:02:06 brd ff:ff:ff:ff:ff:ff
|
||||
|
||||
Or in brief format:
|
||||
$ ip -br addr show master vrf-red
|
||||
eth1 UP 10.2.1.2/24 2002:1::2/120 fe80::ff:fe00:202/64
|
||||
eth2 UP 10.2.2.2/24 2002:2::2/120 fe80::ff:fe00:203/64
|
||||
eth5 DOWN
|
||||
|
||||
|
||||
7. Show Routes for a VRF
|
||||
|
||||
To show routes for a VRF use the ip command to display the table associated
|
||||
with the VRF device:
|
||||
$ ip [-6] route show table ID
|
||||
|
||||
For example:
|
||||
$ ip route show table vrf-red
|
||||
prohibit default
|
||||
broadcast 10.2.1.0 dev eth1 proto kernel scope link src 10.2.1.2
|
||||
10.2.1.0/24 dev eth1 proto kernel scope link src 10.2.1.2
|
||||
local 10.2.1.2 dev eth1 proto kernel scope host src 10.2.1.2
|
||||
broadcast 10.2.1.255 dev eth1 proto kernel scope link src 10.2.1.2
|
||||
broadcast 10.2.2.0 dev eth2 proto kernel scope link src 10.2.2.2
|
||||
10.2.2.0/24 dev eth2 proto kernel scope link src 10.2.2.2
|
||||
local 10.2.2.2 dev eth2 proto kernel scope host src 10.2.2.2
|
||||
broadcast 10.2.2.255 dev eth2 proto kernel scope link src 10.2.2.2
|
||||
|
||||
$ ip -6 route show table vrf-red
|
||||
local 2002:1:: dev lo proto none metric 0 pref medium
|
||||
local 2002:1::2 dev lo proto none metric 0 pref medium
|
||||
2002:1::/120 dev eth1 proto kernel metric 256 pref medium
|
||||
local 2002:2:: dev lo proto none metric 0 pref medium
|
||||
local 2002:2::2 dev lo proto none metric 0 pref medium
|
||||
2002:2::/120 dev eth2 proto kernel metric 256 pref medium
|
||||
local fe80:: dev lo proto none metric 0 pref medium
|
||||
local fe80:: dev lo proto none metric 0 pref medium
|
||||
local fe80::ff:fe00:202 dev lo proto none metric 0 pref medium
|
||||
local fe80::ff:fe00:203 dev lo proto none metric 0 pref medium
|
||||
fe80::/64 dev eth1 proto kernel metric 256 pref medium
|
||||
fe80::/64 dev eth2 proto kernel metric 256 pref medium
|
||||
ff00::/8 dev vrf-red metric 256 pref medium
|
||||
ff00::/8 dev eth1 metric 256 pref medium
|
||||
ff00::/8 dev eth2 metric 256 pref medium
|
||||
|
||||
|
||||
8. Route Lookup for a VRF
|
||||
|
||||
A test route lookup can be done for a VRF by adding the oif option to ip:
|
||||
$ ip [-6] route get oif VRF-NAME ADDRESS
|
||||
|
||||
For example:
|
||||
$ ip route get 10.2.1.40 oif vrf-red
|
||||
10.2.1.40 dev eth1 table vrf-red src 10.2.1.2
|
||||
cache
|
||||
|
||||
$ ip -6 route get 2002:1::32 oif vrf-red
|
||||
2002:1::32 from :: dev eth1 table vrf-red proto kernel src 2002:1::2 metric 256 pref medium
|
||||
|
||||
|
||||
9. Removing Network Interface from a VRF
|
||||
|
||||
Network interfaces are removed from a VRF by breaking the enslavement to
|
||||
the VRF device:
|
||||
$ ip link set dev NAME nomaster
|
||||
|
||||
Connected routes are moved back to the default table and local entries are
|
||||
moved to the local table.
|
||||
|
||||
For example:
|
||||
$ ip link set dev eth0 nomaster
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Commands used in this example:
|
||||
|
||||
cat >> /etc/iproute2/rt_tables <<EOF
|
||||
1 vrf-mgmt
|
||||
10 vrf-red
|
||||
66 vrf-blue
|
||||
81 vrf-green
|
||||
EOF
|
||||
|
||||
function vrf_create
|
||||
{
|
||||
VRF=$1
|
||||
TBID=$2
|
||||
# create VRF device
|
||||
ip link add vrf-${VRF} type vrf table ${TBID}
|
||||
|
||||
# add rules that direct lookups to vrf table
|
||||
ip ru add pref 200 oif vrf-${VRF} table ${TBID}
|
||||
ip ru add pref 200 iif vrf-${VRF} table ${TBID}
|
||||
ip -6 ru add pref 200 oif vrf-${VRF} table ${TBID}
|
||||
ip -6 ru add pref 200 iif vrf-${VRF} table ${TBID}
|
||||
|
||||
if [ "${VRF}" != "mgmt" ]; then
|
||||
ip route add table ${TBID} prohibit default
|
||||
fi
|
||||
ip link set dev vrf-${VRF} up
|
||||
ip link set dev vrf-${VRF} state up
|
||||
}
|
||||
|
||||
vrf_create mgmt 1
|
||||
ip link set dev eth0 master vrf-mgmt
|
||||
|
||||
vrf_create red 10
|
||||
ip link set dev eth1 master vrf-red
|
||||
ip link set dev eth2 master vrf-red
|
||||
ip link set dev eth5 master vrf-red
|
||||
|
||||
vrf_create blue 66
|
||||
ip link set dev eth3 master vrf-blue
|
||||
|
||||
vrf_create green 81
|
||||
ip link set dev eth4 master vrf-green
|
||||
|
||||
|
||||
Interface addresses from /etc/network/interfaces:
|
||||
auto eth0
|
||||
iface eth0 inet static
|
||||
address 10.0.0.2
|
||||
netmask 255.255.255.0
|
||||
gateway 10.0.0.254
|
||||
|
||||
iface eth0 inet6 static
|
||||
address 2000:1::2
|
||||
netmask 120
|
||||
|
||||
auto eth1
|
||||
iface eth1 inet static
|
||||
address 10.2.1.2
|
||||
netmask 255.255.255.0
|
||||
|
||||
iface eth1 inet6 static
|
||||
address 2002:1::2
|
||||
netmask 120
|
||||
|
||||
auto eth2
|
||||
iface eth2 inet static
|
||||
address 10.2.2.2
|
||||
netmask 255.255.255.0
|
||||
|
||||
iface eth2 inet6 static
|
||||
address 2002:2::2
|
||||
netmask 120
|
||||
|
||||
auto eth3
|
||||
iface eth3 inet static
|
||||
address 10.2.3.2
|
||||
netmask 255.255.255.0
|
||||
|
||||
iface eth3 inet6 static
|
||||
address 2002:3::2
|
||||
netmask 120
|
||||
|
||||
auto eth4
|
||||
iface eth4 inet static
|
||||
address 10.2.4.2
|
||||
netmask 255.255.255.0
|
||||
|
||||
iface eth4 inet6 static
|
||||
address 2002:4::2
|
||||
netmask 120
|
||||
|
|
|
@ -5546,7 +5546,7 @@ F: drivers/net/wireless/iwlegacy/
|
|||
INTEL WIRELESS WIFI LINK (iwlwifi)
|
||||
M: Johannes Berg <johannes.berg@intel.com>
|
||||
M: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
M: Intel Linux Wireless <linuxwifi@intel.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://intellinuxwireless.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi.git
|
||||
|
@ -6978,6 +6978,7 @@ M: Alan Ott <alan@signal11.us>
|
|||
L: linux-wpan@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/ieee802154/mrf24j40.c
|
||||
F: Documentation/devicetree/bindings/net/ieee802154/mrf24j40.txt
|
||||
|
||||
MSI LAPTOP SUPPORT
|
||||
M: "Lee, Chun-Yi" <jlee@suse.com>
|
||||
|
|
|
@ -125,7 +125,7 @@ static u64 jit_get_skb_w(struct sk_buff *skb, int offset)
|
|||
}
|
||||
|
||||
/*
|
||||
* Wrapper that handles both OABI and EABI and assures Thumb2 interworking
|
||||
* Wrappers which handle both OABI and EABI and assures Thumb2 interworking
|
||||
* (where the assembly routines like __aeabi_uidiv could cause problems).
|
||||
*/
|
||||
static u32 jit_udiv(u32 dividend, u32 divisor)
|
||||
|
@ -133,6 +133,11 @@ static u32 jit_udiv(u32 dividend, u32 divisor)
|
|||
return dividend / divisor;
|
||||
}
|
||||
|
||||
static u32 jit_mod(u32 dividend, u32 divisor)
|
||||
{
|
||||
return dividend % divisor;
|
||||
}
|
||||
|
||||
static inline void _emit(int cond, u32 inst, struct jit_ctx *ctx)
|
||||
{
|
||||
inst |= (cond << 28);
|
||||
|
@ -471,11 +476,17 @@ static inline void emit_blx_r(u8 tgt_reg, struct jit_ctx *ctx)
|
|||
#endif
|
||||
}
|
||||
|
||||
static inline void emit_udiv(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx)
|
||||
static inline void emit_udivmod(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx,
|
||||
int bpf_op)
|
||||
{
|
||||
#if __LINUX_ARM_ARCH__ == 7
|
||||
if (elf_hwcap & HWCAP_IDIVA) {
|
||||
if (bpf_op == BPF_DIV)
|
||||
emit(ARM_UDIV(rd, rm, rn), ctx);
|
||||
else {
|
||||
emit(ARM_UDIV(ARM_R3, rm, rn), ctx);
|
||||
emit(ARM_MLS(rd, rn, ARM_R3, rm), ctx);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
@ -496,7 +507,8 @@ static inline void emit_udiv(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx)
|
|||
emit(ARM_MOV_R(ARM_R0, rm), ctx);
|
||||
|
||||
ctx->seen |= SEEN_CALL;
|
||||
emit_mov_i(ARM_R3, (u32)jit_udiv, ctx);
|
||||
emit_mov_i(ARM_R3, bpf_op == BPF_DIV ? (u32)jit_udiv : (u32)jit_mod,
|
||||
ctx);
|
||||
emit_blx_r(ARM_R3, ctx);
|
||||
|
||||
if (rd != ARM_R0)
|
||||
|
@ -697,13 +709,27 @@ load_ind:
|
|||
if (k == 1)
|
||||
break;
|
||||
emit_mov_i(r_scratch, k, ctx);
|
||||
emit_udiv(r_A, r_A, r_scratch, ctx);
|
||||
emit_udivmod(r_A, r_A, r_scratch, ctx, BPF_DIV);
|
||||
break;
|
||||
case BPF_ALU | BPF_DIV | BPF_X:
|
||||
update_on_xread(ctx);
|
||||
emit(ARM_CMP_I(r_X, 0), ctx);
|
||||
emit_err_ret(ARM_COND_EQ, ctx);
|
||||
emit_udiv(r_A, r_A, r_X, ctx);
|
||||
emit_udivmod(r_A, r_A, r_X, ctx, BPF_DIV);
|
||||
break;
|
||||
case BPF_ALU | BPF_MOD | BPF_K:
|
||||
if (k == 1) {
|
||||
emit_mov_i(r_A, 0, ctx);
|
||||
break;
|
||||
}
|
||||
emit_mov_i(r_scratch, k, ctx);
|
||||
emit_udivmod(r_A, r_A, r_scratch, ctx, BPF_MOD);
|
||||
break;
|
||||
case BPF_ALU | BPF_MOD | BPF_X:
|
||||
update_on_xread(ctx);
|
||||
emit(ARM_CMP_I(r_X, 0), ctx);
|
||||
emit_err_ret(ARM_COND_EQ, ctx);
|
||||
emit_udivmod(r_A, r_A, r_X, ctx, BPF_MOD);
|
||||
break;
|
||||
case BPF_ALU | BPF_OR | BPF_K:
|
||||
/* A |= K */
|
||||
|
|
|
@ -115,6 +115,8 @@
|
|||
|
||||
#define ARM_INST_UMULL 0x00800090
|
||||
|
||||
#define ARM_INST_MLS 0x00600090
|
||||
|
||||
/*
|
||||
* Use a suitable undefined instruction to use for ARM/Thumb2 faulting.
|
||||
* We need to be careful not to conflict with those used by other modules
|
||||
|
@ -210,4 +212,7 @@
|
|||
#define ARM_UMULL(rd_lo, rd_hi, rn, rm) (ARM_INST_UMULL | (rd_hi) << 16 \
|
||||
| (rd_lo) << 12 | (rm) << 8 | rn)
|
||||
|
||||
#define ARM_MLS(rd, rn, rm, ra) (ARM_INST_MLS | (rd) << 16 | (rn) | (rm) << 8 \
|
||||
| (ra) << 12)
|
||||
|
||||
#endif /* PFILTER_OPCODES_ARM_H */
|
||||
|
|
|
@ -224,10 +224,12 @@
|
|||
|
||||
/include/ "pq3-etsec2-0.dtsi"
|
||||
enet0: enet0_grp2: ethernet@b0000 {
|
||||
fsl,wake-on-filer;
|
||||
};
|
||||
|
||||
/include/ "pq3-etsec2-1.dtsi"
|
||||
enet1: enet1_grp2: ethernet@b1000 {
|
||||
fsl,wake-on-filer;
|
||||
};
|
||||
|
||||
global-utilities@e0000 {
|
||||
|
|
|
@ -112,7 +112,8 @@ static void ia_enque_head_rtn_q (IARTN_Q *que, IARTN_Q * data)
|
|||
|
||||
static int ia_enque_rtn_q (IARTN_Q *que, struct desc_tbl_t data) {
|
||||
IARTN_Q *entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
|
||||
if (!entry) return -1;
|
||||
if (!entry)
|
||||
return -ENOMEM;
|
||||
entry->data = data;
|
||||
entry->next = NULL;
|
||||
if (que->next == NULL)
|
||||
|
|
|
@ -98,6 +98,8 @@ struct regmap {
|
|||
|
||||
int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
|
||||
int (*reg_write)(void *context, unsigned int reg, unsigned int val);
|
||||
int (*reg_update_bits)(void *context, unsigned int reg,
|
||||
unsigned int mask, unsigned int val);
|
||||
|
||||
bool defer_caching;
|
||||
|
||||
|
|
|
@ -619,6 +619,7 @@ struct regmap *__regmap_init(struct device *dev,
|
|||
goto skip_format_initialization;
|
||||
} else {
|
||||
map->reg_read = _regmap_bus_read;
|
||||
map->reg_update_bits = bus->reg_update_bits;
|
||||
}
|
||||
|
||||
reg_endian = regmap_get_reg_endian(bus, config);
|
||||
|
@ -2509,6 +2510,14 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
|
|||
int ret;
|
||||
unsigned int tmp, orig;
|
||||
|
||||
if (change)
|
||||
*change = false;
|
||||
|
||||
if (regmap_volatile(map, reg) && map->reg_update_bits) {
|
||||
ret = map->reg_update_bits(map->bus_context, reg, mask, val);
|
||||
if (ret == 0 && change)
|
||||
*change = true;
|
||||
} else {
|
||||
ret = _regmap_read(map, reg, &orig);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
@ -2518,11 +2527,9 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
|
|||
|
||||
if (force_write || (tmp != orig)) {
|
||||
ret = _regmap_write(map, reg, tmp);
|
||||
if (change)
|
||||
if (ret == 0 && change)
|
||||
*change = true;
|
||||
} else {
|
||||
if (change)
|
||||
*change = false;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -436,13 +436,8 @@ int bcma_bus_register(struct bcma_bus *bus)
|
|||
}
|
||||
|
||||
dev = bcma_bus_get_host_dev(bus);
|
||||
/* TODO: remove check for IS_BUILTIN(CONFIG_BCMA) check when
|
||||
* of_default_bus_match_table is exported or in some other way
|
||||
* accessible. This is just a temporary workaround.
|
||||
*/
|
||||
if (IS_BUILTIN(CONFIG_BCMA) && dev) {
|
||||
of_platform_populate(dev->of_node, of_default_bus_match_table,
|
||||
NULL, dev);
|
||||
if (dev) {
|
||||
of_platform_default_populate(dev->of_node, NULL, dev);
|
||||
}
|
||||
|
||||
/* Cores providing flash access go before SPROM init */
|
||||
|
|
|
@ -4,6 +4,7 @@ menu "Bluetooth device drivers"
|
|||
|
||||
config BT_INTEL
|
||||
tristate
|
||||
select REGMAP
|
||||
|
||||
config BT_BCM
|
||||
tristate
|
||||
|
@ -183,6 +184,7 @@ config BT_HCIBCM203X
|
|||
config BT_HCIBPA10X
|
||||
tristate "HCI BPA10x USB driver"
|
||||
depends on USB
|
||||
select BT_HCIUART_H4
|
||||
help
|
||||
Bluetooth HCI BPA10x USB driver.
|
||||
This driver provides support for the Digianswer BPA 100/105 Bluetooth
|
||||
|
@ -275,7 +277,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/8787/8797/8887/8897.
|
||||
Marvell Bluetooth devices, such as 8688/8787/8797/8887/8897/8997.
|
||||
|
||||
Say Y here to compile Marvell Bluetooth driver
|
||||
into the kernel or say M to compile it as module.
|
||||
|
@ -289,7 +291,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 SD8688/SD8787/SD8797/SD8887/SD8897
|
||||
devices with SDIO interface. Currently SD8688/SD8787/SD8797/SD8887/SD8897/SD8997
|
||||
chipsets are supported.
|
||||
|
||||
Say Y here to compile support for Marvell BT-over-SDIO driver
|
||||
|
|
|
@ -422,17 +422,12 @@ static int bfusb_open(struct hci_dev *hdev)
|
|||
|
||||
BT_DBG("hdev %p bfusb %p", hdev, data);
|
||||
|
||||
if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
|
||||
return 0;
|
||||
|
||||
write_lock_irqsave(&data->lock, flags);
|
||||
|
||||
err = bfusb_rx_submit(data, NULL);
|
||||
if (!err) {
|
||||
for (i = 1; i < BFUSB_MAX_BULK_RX; i++)
|
||||
bfusb_rx_submit(data, NULL);
|
||||
} else {
|
||||
clear_bit(HCI_RUNNING, &hdev->flags);
|
||||
}
|
||||
|
||||
write_unlock_irqrestore(&data->lock, flags);
|
||||
|
@ -458,9 +453,6 @@ static int bfusb_close(struct hci_dev *hdev)
|
|||
|
||||
BT_DBG("hdev %p bfusb %p", hdev, data);
|
||||
|
||||
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
|
||||
return 0;
|
||||
|
||||
write_lock_irqsave(&data->lock, flags);
|
||||
write_unlock_irqrestore(&data->lock, flags);
|
||||
|
||||
|
@ -479,9 +471,6 @@ static int bfusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
|
||||
BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, bt_cb(skb)->pkt_type, skb->len);
|
||||
|
||||
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
||||
return -EBUSY;
|
||||
|
||||
switch (bt_cb(skb)->pkt_type) {
|
||||
case HCI_COMMAND_PKT:
|
||||
hdev->stat.cmd_tx++;
|
||||
|
|
|
@ -390,7 +390,7 @@ static void bluecard_receive(struct bluecard_info *info,
|
|||
for (i = 0; i < len; i++) {
|
||||
|
||||
/* Allocate packet */
|
||||
if (info->rx_skb == NULL) {
|
||||
if (!info->rx_skb) {
|
||||
info->rx_state = RECV_WAIT_PACKET_TYPE;
|
||||
info->rx_count = 0;
|
||||
info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
|
||||
|
@ -628,9 +628,6 @@ static int bluecard_hci_open(struct hci_dev *hdev)
|
|||
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
|
||||
bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE);
|
||||
|
||||
if (test_and_set_bit(HCI_RUNNING, &(hdev->flags)))
|
||||
return 0;
|
||||
|
||||
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) {
|
||||
unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
|
||||
|
@ -646,9 +643,6 @@ static int bluecard_hci_close(struct hci_dev *hdev)
|
|||
{
|
||||
struct bluecard_info *info = hci_get_drvdata(hdev);
|
||||
|
||||
if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
|
||||
return 0;
|
||||
|
||||
bluecard_hci_flush(hdev);
|
||||
|
||||
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) {
|
||||
|
|
|
@ -35,7 +35,9 @@
|
|||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
|
||||
#define VERSION "0.10"
|
||||
#include "hci_uart.h"
|
||||
|
||||
#define VERSION "0.11"
|
||||
|
||||
static const struct usb_device_id bpa10x_table[] = {
|
||||
/* Tektronix BPA 100/105 (Digianswer) */
|
||||
|
@ -56,112 +58,6 @@ struct bpa10x_data {
|
|||
struct sk_buff *rx_skb[2];
|
||||
};
|
||||
|
||||
#define HCI_VENDOR_HDR_SIZE 5
|
||||
|
||||
struct hci_vendor_hdr {
|
||||
__u8 type;
|
||||
__le16 snum;
|
||||
__le16 dlen;
|
||||
} __packed;
|
||||
|
||||
static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count)
|
||||
{
|
||||
struct bpa10x_data *data = hci_get_drvdata(hdev);
|
||||
|
||||
BT_DBG("%s queue %d buffer %p count %d", hdev->name,
|
||||
queue, buf, count);
|
||||
|
||||
if (queue < 0 || queue > 1)
|
||||
return -EILSEQ;
|
||||
|
||||
hdev->stat.byte_rx += count;
|
||||
|
||||
while (count) {
|
||||
struct sk_buff *skb = data->rx_skb[queue];
|
||||
struct { __u8 type; int expect; } *scb;
|
||||
int type, len = 0;
|
||||
|
||||
if (!skb) {
|
||||
/* Start of the frame */
|
||||
|
||||
type = *((__u8 *) buf);
|
||||
count--; buf++;
|
||||
|
||||
switch (type) {
|
||||
case HCI_EVENT_PKT:
|
||||
if (count >= HCI_EVENT_HDR_SIZE) {
|
||||
struct hci_event_hdr *h = buf;
|
||||
len = HCI_EVENT_HDR_SIZE + h->plen;
|
||||
} else
|
||||
return -EILSEQ;
|
||||
break;
|
||||
|
||||
case HCI_ACLDATA_PKT:
|
||||
if (count >= HCI_ACL_HDR_SIZE) {
|
||||
struct hci_acl_hdr *h = buf;
|
||||
len = HCI_ACL_HDR_SIZE +
|
||||
__le16_to_cpu(h->dlen);
|
||||
} else
|
||||
return -EILSEQ;
|
||||
break;
|
||||
|
||||
case HCI_SCODATA_PKT:
|
||||
if (count >= HCI_SCO_HDR_SIZE) {
|
||||
struct hci_sco_hdr *h = buf;
|
||||
len = HCI_SCO_HDR_SIZE + h->dlen;
|
||||
} else
|
||||
return -EILSEQ;
|
||||
break;
|
||||
|
||||
case HCI_VENDOR_PKT:
|
||||
if (count >= HCI_VENDOR_HDR_SIZE) {
|
||||
struct hci_vendor_hdr *h = buf;
|
||||
len = HCI_VENDOR_HDR_SIZE +
|
||||
__le16_to_cpu(h->dlen);
|
||||
} else
|
||||
return -EILSEQ;
|
||||
break;
|
||||
}
|
||||
|
||||
skb = bt_skb_alloc(len, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
BT_ERR("%s no memory for packet", hdev->name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
data->rx_skb[queue] = skb;
|
||||
|
||||
scb = (void *) skb->cb;
|
||||
scb->type = type;
|
||||
scb->expect = len;
|
||||
} else {
|
||||
/* Continuation */
|
||||
|
||||
scb = (void *) skb->cb;
|
||||
len = scb->expect;
|
||||
}
|
||||
|
||||
len = min(len, count);
|
||||
|
||||
memcpy(skb_put(skb, len), buf, len);
|
||||
|
||||
scb->expect -= len;
|
||||
|
||||
if (scb->expect == 0) {
|
||||
/* Complete frame */
|
||||
|
||||
data->rx_skb[queue] = NULL;
|
||||
|
||||
bt_cb(skb)->pkt_type = scb->type;
|
||||
hci_recv_frame(hdev, skb);
|
||||
}
|
||||
|
||||
count -= len; buf += len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bpa10x_tx_complete(struct urb *urb)
|
||||
{
|
||||
struct sk_buff *skb = urb->context;
|
||||
|
@ -184,6 +80,22 @@ done:
|
|||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
#define HCI_VENDOR_HDR_SIZE 5
|
||||
|
||||
#define HCI_RECV_VENDOR \
|
||||
.type = HCI_VENDOR_PKT, \
|
||||
.hlen = HCI_VENDOR_HDR_SIZE, \
|
||||
.loff = 3, \
|
||||
.lsize = 2, \
|
||||
.maxlen = HCI_MAX_FRAME_SIZE
|
||||
|
||||
static const struct h4_recv_pkt bpa10x_recv_pkts[] = {
|
||||
{ H4_RECV_ACL, .recv = hci_recv_frame },
|
||||
{ H4_RECV_SCO, .recv = hci_recv_frame },
|
||||
{ H4_RECV_EVENT, .recv = hci_recv_frame },
|
||||
{ HCI_RECV_VENDOR, .recv = hci_recv_diag },
|
||||
};
|
||||
|
||||
static void bpa10x_rx_complete(struct urb *urb)
|
||||
{
|
||||
struct hci_dev *hdev = urb->context;
|
||||
|
@ -197,11 +109,17 @@ static void bpa10x_rx_complete(struct urb *urb)
|
|||
return;
|
||||
|
||||
if (urb->status == 0) {
|
||||
if (bpa10x_recv(hdev, usb_pipebulk(urb->pipe),
|
||||
bool idx = usb_pipebulk(urb->pipe);
|
||||
|
||||
data->rx_skb[idx] = h4_recv_buf(hdev, data->rx_skb[idx],
|
||||
urb->transfer_buffer,
|
||||
urb->actual_length) < 0) {
|
||||
urb->actual_length,
|
||||
bpa10x_recv_pkts,
|
||||
ARRAY_SIZE(bpa10x_recv_pkts));
|
||||
if (IS_ERR(data->rx_skb[idx])) {
|
||||
BT_ERR("%s corrupted event packet", hdev->name);
|
||||
hdev->stat.err_rx++;
|
||||
data->rx_skb[idx] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,9 +222,6 @@ static int bpa10x_open(struct hci_dev *hdev)
|
|||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
|
||||
return 0;
|
||||
|
||||
err = bpa10x_submit_intr_urb(hdev);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
@ -320,8 +235,6 @@ static int bpa10x_open(struct hci_dev *hdev)
|
|||
error:
|
||||
usb_kill_anchored_urbs(&data->rx_anchor);
|
||||
|
||||
clear_bit(HCI_RUNNING, &hdev->flags);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -331,9 +244,6 @@ static int bpa10x_close(struct hci_dev *hdev)
|
|||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
|
||||
return 0;
|
||||
|
||||
usb_kill_anchored_urbs(&data->rx_anchor);
|
||||
|
||||
return 0;
|
||||
|
@ -350,6 +260,24 @@ static int bpa10x_flush(struct hci_dev *hdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int bpa10x_setup(struct hci_dev *hdev)
|
||||
{
|
||||
const u8 req[] = { 0x07 };
|
||||
struct sk_buff *skb;
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
/* Read revision string */
|
||||
skb = __hci_cmd_sync(hdev, 0xfc0e, sizeof(req), req, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1));
|
||||
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct bpa10x_data *data = hci_get_drvdata(hdev);
|
||||
|
@ -360,9 +288,6 @@ static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
||||
return -EBUSY;
|
||||
|
||||
skb->dev = (void *) hdev;
|
||||
|
||||
urb = usb_alloc_urb(0, GFP_ATOMIC);
|
||||
|
@ -431,6 +356,25 @@ static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int bpa10x_set_diag(struct hci_dev *hdev, bool enable)
|
||||
{
|
||||
const u8 req[] = { 0x00, enable };
|
||||
struct sk_buff *skb;
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
||||
return -ENETDOWN;
|
||||
|
||||
/* Enable sniffer operation */
|
||||
skb = __hci_cmd_sync(hdev, 0xfc0e, sizeof(req), req, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
{
|
||||
struct bpa10x_data *data;
|
||||
|
@ -465,7 +409,9 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
|
|||
hdev->open = bpa10x_open;
|
||||
hdev->close = bpa10x_close;
|
||||
hdev->flush = bpa10x_flush;
|
||||
hdev->setup = bpa10x_setup;
|
||||
hdev->send = bpa10x_send_frame;
|
||||
hdev->set_diag = bpa10x_set_diag;
|
||||
|
||||
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
|
||||
|
||||
|
|
|
@ -233,7 +233,7 @@ static void bt3c_receive(struct bt3c_info *info)
|
|||
info->hdev->stat.byte_rx++;
|
||||
|
||||
/* Allocate packet */
|
||||
if (info->rx_skb == NULL) {
|
||||
if (!info->rx_skb) {
|
||||
info->rx_state = RECV_WAIT_PACKET_TYPE;
|
||||
info->rx_count = 0;
|
||||
info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
|
||||
|
@ -270,7 +270,6 @@ static void bt3c_receive(struct bt3c_info *info)
|
|||
/* Unknown packet */
|
||||
BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
|
||||
info->hdev->stat.err_rx++;
|
||||
clear_bit(HCI_RUNNING, &(info->hdev->flags));
|
||||
|
||||
kfree_skb(info->rx_skb);
|
||||
info->rx_skb = NULL;
|
||||
|
@ -395,17 +394,12 @@ static int bt3c_hci_flush(struct hci_dev *hdev)
|
|||
|
||||
static int bt3c_hci_open(struct hci_dev *hdev)
|
||||
{
|
||||
set_bit(HCI_RUNNING, &(hdev->flags));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int bt3c_hci_close(struct hci_dev *hdev)
|
||||
{
|
||||
if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
|
||||
return 0;
|
||||
|
||||
bt3c_hci_flush(hdev);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -181,6 +181,27 @@ static int btbcm_reset(struct hci_dev *hdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct sk_buff *btbcm_read_local_name(struct hci_dev *hdev)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL,
|
||||
HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
BT_ERR("%s: BCM: Reading local name failed (%ld)",
|
||||
hdev->name, PTR_ERR(skb));
|
||||
return skb;
|
||||
}
|
||||
|
||||
if (skb->len != sizeof(struct hci_rp_read_local_name)) {
|
||||
BT_ERR("%s: BCM: Local name length mismatch", hdev->name);
|
||||
kfree_skb(skb);
|
||||
return ERR_PTR(-EIO);
|
||||
}
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
static struct sk_buff *btbcm_read_local_version(struct hci_dev *hdev)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
@ -393,6 +414,14 @@ int btbcm_setup_patchram(struct hci_dev *hdev)
|
|||
BT_INFO("%s: BCM: chip id %u", hdev->name, skb->data[1]);
|
||||
kfree_skb(skb);
|
||||
|
||||
/* Read Local Name */
|
||||
skb = btbcm_read_local_name(hdev);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1));
|
||||
kfree_skb(skb);
|
||||
|
||||
switch ((rev & 0xf000) >> 12) {
|
||||
case 0:
|
||||
case 3:
|
||||
|
@ -464,6 +493,14 @@ int btbcm_setup_patchram(struct hci_dev *hdev)
|
|||
hw_name ? : "BCM", (subver & 0x7000) >> 13,
|
||||
(subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff);
|
||||
|
||||
/* Read Local Name */
|
||||
skb = btbcm_read_local_name(hdev);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1));
|
||||
kfree_skb(skb);
|
||||
|
||||
btbcm_check_bdaddr(hdev);
|
||||
|
||||
set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
|
||||
|
@ -475,12 +512,25 @@ EXPORT_SYMBOL_GPL(btbcm_setup_patchram);
|
|||
int btbcm_setup_apple(struct hci_dev *hdev)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
int err;
|
||||
|
||||
/* Reset */
|
||||
err = btbcm_reset(hdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Read Verbose Config Version Info */
|
||||
skb = btbcm_read_verbose_config(hdev);
|
||||
if (!IS_ERR(skb)) {
|
||||
BT_INFO("%s: BCM: chip id %u build %4.4u", hdev->name, skb->data[1],
|
||||
get_unaligned_le16(skb->data + 5));
|
||||
BT_INFO("%s: BCM: chip id %u build %4.4u", hdev->name,
|
||||
skb->data[1], get_unaligned_le16(skb->data + 5));
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
/* Read Local Name */
|
||||
skb = btbcm_read_local_name(hdev);
|
||||
if (!IS_ERR(skb)) {
|
||||
BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1));
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include <linux/module.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
|
@ -215,6 +216,201 @@ int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(btintel_load_ddc_config);
|
||||
|
||||
/* ------- REGMAP IBT SUPPORT ------- */
|
||||
|
||||
#define IBT_REG_MODE_8BIT 0x00
|
||||
#define IBT_REG_MODE_16BIT 0x01
|
||||
#define IBT_REG_MODE_32BIT 0x02
|
||||
|
||||
struct regmap_ibt_context {
|
||||
struct hci_dev *hdev;
|
||||
__u16 op_write;
|
||||
__u16 op_read;
|
||||
};
|
||||
|
||||
struct ibt_cp_reg_access {
|
||||
__le32 addr;
|
||||
__u8 mode;
|
||||
__u8 len;
|
||||
__u8 data[0];
|
||||
} __packed;
|
||||
|
||||
struct ibt_rp_reg_access {
|
||||
__u8 status;
|
||||
__le32 addr;
|
||||
__u8 data[0];
|
||||
} __packed;
|
||||
|
||||
static int regmap_ibt_read(void *context, const void *addr, size_t reg_size,
|
||||
void *val, size_t val_size)
|
||||
{
|
||||
struct regmap_ibt_context *ctx = context;
|
||||
struct ibt_cp_reg_access cp;
|
||||
struct ibt_rp_reg_access *rp;
|
||||
struct sk_buff *skb;
|
||||
int err = 0;
|
||||
|
||||
if (reg_size != sizeof(__le32))
|
||||
return -EINVAL;
|
||||
|
||||
switch (val_size) {
|
||||
case 1:
|
||||
cp.mode = IBT_REG_MODE_8BIT;
|
||||
break;
|
||||
case 2:
|
||||
cp.mode = IBT_REG_MODE_16BIT;
|
||||
break;
|
||||
case 4:
|
||||
cp.mode = IBT_REG_MODE_32BIT;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* regmap provides a little-endian formatted addr */
|
||||
cp.addr = *(__le32 *)addr;
|
||||
cp.len = val_size;
|
||||
|
||||
bt_dev_dbg(ctx->hdev, "Register (0x%x) read", le32_to_cpu(cp.addr));
|
||||
|
||||
skb = hci_cmd_sync(ctx->hdev, ctx->op_read, sizeof(cp), &cp,
|
||||
HCI_CMD_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
err = PTR_ERR(skb);
|
||||
bt_dev_err(ctx->hdev, "regmap: Register (0x%x) read error (%d)",
|
||||
le32_to_cpu(cp.addr), err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (skb->len != sizeof(*rp) + val_size) {
|
||||
bt_dev_err(ctx->hdev, "regmap: Register (0x%x) read error, bad len",
|
||||
le32_to_cpu(cp.addr));
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
rp = (struct ibt_rp_reg_access *)skb->data;
|
||||
|
||||
if (rp->addr != cp.addr) {
|
||||
bt_dev_err(ctx->hdev, "regmap: Register (0x%x) read error, bad addr",
|
||||
le32_to_cpu(rp->addr));
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
memcpy(val, rp->data, val_size);
|
||||
|
||||
done:
|
||||
kfree_skb(skb);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int regmap_ibt_gather_write(void *context,
|
||||
const void *addr, size_t reg_size,
|
||||
const void *val, size_t val_size)
|
||||
{
|
||||
struct regmap_ibt_context *ctx = context;
|
||||
struct ibt_cp_reg_access *cp;
|
||||
struct sk_buff *skb;
|
||||
int plen = sizeof(*cp) + val_size;
|
||||
u8 mode;
|
||||
int err = 0;
|
||||
|
||||
if (reg_size != sizeof(__le32))
|
||||
return -EINVAL;
|
||||
|
||||
switch (val_size) {
|
||||
case 1:
|
||||
mode = IBT_REG_MODE_8BIT;
|
||||
break;
|
||||
case 2:
|
||||
mode = IBT_REG_MODE_16BIT;
|
||||
break;
|
||||
case 4:
|
||||
mode = IBT_REG_MODE_32BIT;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cp = kmalloc(plen, GFP_KERNEL);
|
||||
if (!cp)
|
||||
return -ENOMEM;
|
||||
|
||||
/* regmap provides a little-endian formatted addr/value */
|
||||
cp->addr = *(__le32 *)addr;
|
||||
cp->mode = mode;
|
||||
cp->len = val_size;
|
||||
memcpy(&cp->data, val, val_size);
|
||||
|
||||
bt_dev_dbg(ctx->hdev, "Register (0x%x) write", le32_to_cpu(cp->addr));
|
||||
|
||||
skb = hci_cmd_sync(ctx->hdev, ctx->op_write, plen, cp, HCI_CMD_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
err = PTR_ERR(skb);
|
||||
bt_dev_err(ctx->hdev, "regmap: Register (0x%x) write error (%d)",
|
||||
le32_to_cpu(cp->addr), err);
|
||||
goto done;
|
||||
}
|
||||
kfree_skb(skb);
|
||||
|
||||
done:
|
||||
kfree(cp);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int regmap_ibt_write(void *context, const void *data, size_t count)
|
||||
{
|
||||
/* data contains register+value, since we only support 32bit addr,
|
||||
* minimum data size is 4 bytes.
|
||||
*/
|
||||
if (WARN_ONCE(count < 4, "Invalid register access"))
|
||||
return -EINVAL;
|
||||
|
||||
return regmap_ibt_gather_write(context, data, 4, data + 4, count - 4);
|
||||
}
|
||||
|
||||
static void regmap_ibt_free_context(void *context)
|
||||
{
|
||||
kfree(context);
|
||||
}
|
||||
|
||||
static struct regmap_bus regmap_ibt = {
|
||||
.read = regmap_ibt_read,
|
||||
.write = regmap_ibt_write,
|
||||
.gather_write = regmap_ibt_gather_write,
|
||||
.free_context = regmap_ibt_free_context,
|
||||
.reg_format_endian_default = REGMAP_ENDIAN_LITTLE,
|
||||
.val_format_endian_default = REGMAP_ENDIAN_LITTLE,
|
||||
};
|
||||
|
||||
/* Config is the same for all register regions */
|
||||
static const struct regmap_config regmap_ibt_cfg = {
|
||||
.name = "btintel_regmap",
|
||||
.reg_bits = 32,
|
||||
.val_bits = 32,
|
||||
};
|
||||
|
||||
struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
|
||||
u16 opcode_write)
|
||||
{
|
||||
struct regmap_ibt_context *ctx;
|
||||
|
||||
bt_dev_info(hdev, "regmap: Init R%x-W%x region", opcode_read,
|
||||
opcode_write);
|
||||
|
||||
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ctx->op_read = opcode_read;
|
||||
ctx->op_write = opcode_write;
|
||||
ctx->hdev = hdev;
|
||||
|
||||
return regmap_init(&hdev->dev, ®map_ibt, ctx, ®map_ibt_cfg);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btintel_regmap_init);
|
||||
|
||||
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
|
||||
MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION);
|
||||
MODULE_VERSION(VERSION);
|
||||
|
|
|
@ -80,6 +80,9 @@ int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen,
|
|||
const void *param);
|
||||
int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name);
|
||||
|
||||
struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
|
||||
u16 opcode_write);
|
||||
|
||||
#else
|
||||
|
||||
static inline int btintel_check_bdaddr(struct hci_dev *hdev)
|
||||
|
@ -113,4 +116,10 @@ static inline int btintel_load_ddc_config(struct hci_dev *hdev,
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline struct regmap *btintel_regmap_init(struct hci_dev *hdev,
|
||||
u16 opcode_read,
|
||||
u16 opcode_write)
|
||||
{
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -184,7 +184,7 @@ static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 opcode,
|
|||
}
|
||||
|
||||
skb = bt_skb_alloc(HCI_COMMAND_HDR_SIZE + len, GFP_ATOMIC);
|
||||
if (skb == NULL) {
|
||||
if (!skb) {
|
||||
BT_ERR("No free skb");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -436,13 +436,6 @@ static int btmrvl_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
|
||||
BT_DBG("type=%d, len=%d", skb->pkt_type, skb->len);
|
||||
|
||||
if (!test_bit(HCI_RUNNING, &hdev->flags)) {
|
||||
BT_ERR("Failed testing HCI_RUNING, flags=%lx", hdev->flags);
|
||||
print_hex_dump_bytes("data: ", DUMP_PREFIX_OFFSET,
|
||||
skb->data, skb->len);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
switch (bt_cb(skb)->pkt_type) {
|
||||
case HCI_COMMAND_PKT:
|
||||
hdev->stat.cmd_tx++;
|
||||
|
@ -477,9 +470,6 @@ static int btmrvl_close(struct hci_dev *hdev)
|
|||
{
|
||||
struct btmrvl_private *priv = hci_get_drvdata(hdev);
|
||||
|
||||
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
|
||||
return 0;
|
||||
|
||||
skb_queue_purge(&priv->adapter->tx_queue);
|
||||
|
||||
return 0;
|
||||
|
@ -487,8 +477,6 @@ static int btmrvl_close(struct hci_dev *hdev)
|
|||
|
||||
static int btmrvl_open(struct hci_dev *hdev)
|
||||
{
|
||||
set_bit(HCI_RUNNING, &hdev->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -146,6 +146,29 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8897 = {
|
|||
.fw_dump_end = 0xea,
|
||||
};
|
||||
|
||||
static const struct btmrvl_sdio_card_reg btmrvl_reg_8997 = {
|
||||
.cfg = 0x00,
|
||||
.host_int_mask = 0x08,
|
||||
.host_intstatus = 0x0c,
|
||||
.card_status = 0x5c,
|
||||
.sq_read_base_addr_a0 = 0xf8,
|
||||
.sq_read_base_addr_a1 = 0xf9,
|
||||
.card_revision = 0xc8,
|
||||
.card_fw_status0 = 0xe8,
|
||||
.card_fw_status1 = 0xe9,
|
||||
.card_rx_len = 0xea,
|
||||
.card_rx_unit = 0xeb,
|
||||
.io_port_0 = 0xe4,
|
||||
.io_port_1 = 0xe5,
|
||||
.io_port_2 = 0xe6,
|
||||
.int_read_to_clear = true,
|
||||
.host_int_rsr = 0x04,
|
||||
.card_misc_cfg = 0xD8,
|
||||
.fw_dump_ctrl = 0xf0,
|
||||
.fw_dump_start = 0xf1,
|
||||
.fw_dump_end = 0xf8,
|
||||
};
|
||||
|
||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
|
||||
.helper = "mrvl/sd8688_helper.bin",
|
||||
.firmware = "mrvl/sd8688.bin",
|
||||
|
@ -191,25 +214,37 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
|
|||
.supports_fw_dump = true,
|
||||
};
|
||||
|
||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd8997 = {
|
||||
.helper = NULL,
|
||||
.firmware = "mrvl/sd8997_uapsta.bin",
|
||||
.reg = &btmrvl_reg_8997,
|
||||
.support_pscan_win_report = true,
|
||||
.sd_blksz_fw_dl = 256,
|
||||
.supports_fw_dump = true,
|
||||
};
|
||||
|
||||
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_sd8688 },
|
||||
.driver_data = (unsigned long)&btmrvl_sdio_sd8688 },
|
||||
/* Marvell SD8787 Bluetooth device */
|
||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A),
|
||||
.driver_data = (unsigned long) &btmrvl_sdio_sd8787 },
|
||||
.driver_data = (unsigned long)&btmrvl_sdio_sd8787 },
|
||||
/* Marvell SD8787 Bluetooth AMP device */
|
||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911B),
|
||||
.driver_data = (unsigned long) &btmrvl_sdio_sd8787 },
|
||||
.driver_data = (unsigned long)&btmrvl_sdio_sd8787 },
|
||||
/* Marvell SD8797 Bluetooth device */
|
||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A),
|
||||
.driver_data = (unsigned long) &btmrvl_sdio_sd8797 },
|
||||
.driver_data = (unsigned long)&btmrvl_sdio_sd8797 },
|
||||
/* Marvell SD8887 Bluetooth device */
|
||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9136),
|
||||
.driver_data = (unsigned long)&btmrvl_sdio_sd8887 },
|
||||
/* Marvell SD8897 Bluetooth device */
|
||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912E),
|
||||
.driver_data = (unsigned long) &btmrvl_sdio_sd8897 },
|
||||
.driver_data = (unsigned long)&btmrvl_sdio_sd8897 },
|
||||
/* Marvell SD8997 Bluetooth device */
|
||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9142),
|
||||
.driver_data = (unsigned long)&btmrvl_sdio_sd8997 },
|
||||
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
@ -619,7 +654,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
|
|||
|
||||
/* Allocate buffer */
|
||||
skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC);
|
||||
if (skb == NULL) {
|
||||
if (!skb) {
|
||||
BT_ERR("No free skb");
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
|
@ -1278,6 +1313,12 @@ static void btmrvl_sdio_dump_firmware(struct btmrvl_private *priv)
|
|||
|
||||
if (memory_size == 0) {
|
||||
BT_INFO("Firmware dump finished!");
|
||||
sdio_writeb(card->func, FW_DUMP_READ_DONE,
|
||||
card->reg->fw_dump_ctrl, &ret);
|
||||
if (ret) {
|
||||
BT_ERR("SDIO Write MEMDUMP_FINISH ERR");
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1616,3 +1657,4 @@ MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
|
|||
MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
|
||||
MODULE_FIRMWARE("mrvl/sd8887_uapsta.bin");
|
||||
MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin");
|
||||
MODULE_FIRMWARE("mrvl/sd8997_uapsta.bin");
|
||||
|
|
|
@ -194,21 +194,15 @@ static int btsdio_open(struct hci_dev *hdev)
|
|||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
|
||||
return 0;
|
||||
|
||||
sdio_claim_host(data->func);
|
||||
|
||||
err = sdio_enable_func(data->func);
|
||||
if (err < 0) {
|
||||
clear_bit(HCI_RUNNING, &hdev->flags);
|
||||
if (err < 0)
|
||||
goto release;
|
||||
}
|
||||
|
||||
err = sdio_claim_irq(data->func, btsdio_interrupt);
|
||||
if (err < 0) {
|
||||
sdio_disable_func(data->func);
|
||||
clear_bit(HCI_RUNNING, &hdev->flags);
|
||||
goto release;
|
||||
}
|
||||
|
||||
|
@ -229,9 +223,6 @@ static int btsdio_close(struct hci_dev *hdev)
|
|||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
|
||||
return 0;
|
||||
|
||||
sdio_claim_host(data->func);
|
||||
|
||||
sdio_writeb(data->func, 0x00, REG_EN_INTRD, NULL);
|
||||
|
@ -261,9 +252,6 @@ static int btsdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
||||
return -EBUSY;
|
||||
|
||||
switch (bt_cb(skb)->pkt_type) {
|
||||
case HCI_COMMAND_PKT:
|
||||
hdev->stat.cmd_tx++;
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
#include <linux/serial.h>
|
||||
#include <linux/serial_reg.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <pcmcia/cistpl.h>
|
||||
#include <pcmcia/ciscode.h>
|
||||
|
@ -188,7 +188,7 @@ static void btuart_receive(struct btuart_info *info)
|
|||
info->hdev->stat.byte_rx++;
|
||||
|
||||
/* Allocate packet */
|
||||
if (info->rx_skb == NULL) {
|
||||
if (!info->rx_skb) {
|
||||
info->rx_state = RECV_WAIT_PACKET_TYPE;
|
||||
info->rx_count = 0;
|
||||
info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
|
||||
|
@ -223,7 +223,6 @@ static void btuart_receive(struct btuart_info *info)
|
|||
/* Unknown packet */
|
||||
BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
|
||||
info->hdev->stat.err_rx++;
|
||||
clear_bit(HCI_RUNNING, &(info->hdev->flags));
|
||||
|
||||
kfree_skb(info->rx_skb);
|
||||
info->rx_skb = NULL;
|
||||
|
@ -409,17 +408,12 @@ static int btuart_hci_flush(struct hci_dev *hdev)
|
|||
|
||||
static int btuart_hci_open(struct hci_dev *hdev)
|
||||
{
|
||||
set_bit(HCI_RUNNING, &(hdev->flags));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int btuart_hci_close(struct hci_dev *hdev)
|
||||
{
|
||||
if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
|
||||
return 0;
|
||||
|
||||
btuart_hci_flush(hdev);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -940,9 +940,6 @@ static int btusb_open(struct hci_dev *hdev)
|
|||
|
||||
data->intf->needs_remote_wakeup = 1;
|
||||
|
||||
if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
|
||||
goto done;
|
||||
|
||||
if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags))
|
||||
goto done;
|
||||
|
||||
|
@ -965,7 +962,6 @@ done:
|
|||
|
||||
failed:
|
||||
clear_bit(BTUSB_INTR_RUNNING, &data->flags);
|
||||
clear_bit(HCI_RUNNING, &hdev->flags);
|
||||
usb_autopm_put_interface(data->intf);
|
||||
return err;
|
||||
}
|
||||
|
@ -984,9 +980,6 @@ static int btusb_close(struct hci_dev *hdev)
|
|||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
|
||||
return 0;
|
||||
|
||||
cancel_work_sync(&data->work);
|
||||
cancel_work_sync(&data->waker);
|
||||
|
||||
|
@ -1156,9 +1149,6 @@ static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
||||
return -EBUSY;
|
||||
|
||||
switch (bt_cb(skb)->pkt_type) {
|
||||
case HCI_COMMAND_PKT:
|
||||
urb = alloc_ctrl_urb(hdev, skb);
|
||||
|
@ -1843,9 +1833,6 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
||||
return -EBUSY;
|
||||
|
||||
switch (bt_cb(skb)->pkt_type) {
|
||||
case HCI_COMMAND_PKT:
|
||||
if (test_bit(BTUSB_BOOTLOADER, &data->flags)) {
|
||||
|
|
|
@ -155,9 +155,6 @@ static int ti_st_open(struct hci_dev *hdev)
|
|||
|
||||
BT_DBG("%s %p", hdev->name, hdev);
|
||||
|
||||
if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
|
||||
return -EBUSY;
|
||||
|
||||
/* provide contexts for callbacks from ST */
|
||||
hst = hci_get_drvdata(hdev);
|
||||
|
||||
|
@ -181,7 +178,6 @@ static int ti_st_open(struct hci_dev *hdev)
|
|||
goto done;
|
||||
|
||||
if (err != -EINPROGRESS) {
|
||||
clear_bit(HCI_RUNNING, &hdev->flags);
|
||||
BT_ERR("st_register failed %d", err);
|
||||
return err;
|
||||
}
|
||||
|
@ -195,7 +191,6 @@ static int ti_st_open(struct hci_dev *hdev)
|
|||
(&hst->wait_reg_completion,
|
||||
msecs_to_jiffies(BT_REGISTER_TIMEOUT));
|
||||
if (!timeleft) {
|
||||
clear_bit(HCI_RUNNING, &hdev->flags);
|
||||
BT_ERR("Timeout(%d sec),didn't get reg "
|
||||
"completion signal from ST",
|
||||
BT_REGISTER_TIMEOUT / 1000);
|
||||
|
@ -205,7 +200,6 @@ static int ti_st_open(struct hci_dev *hdev)
|
|||
/* Is ST registration callback
|
||||
* called with ERROR status? */
|
||||
if (hst->reg_status != 0) {
|
||||
clear_bit(HCI_RUNNING, &hdev->flags);
|
||||
BT_ERR("ST registration completed with invalid "
|
||||
"status %d", hst->reg_status);
|
||||
return -EAGAIN;
|
||||
|
@ -215,7 +209,6 @@ done:
|
|||
hst->st_write = ti_st_proto[i].write;
|
||||
if (!hst->st_write) {
|
||||
BT_ERR("undefined ST write function");
|
||||
clear_bit(HCI_RUNNING, &hdev->flags);
|
||||
for (i = 0; i < MAX_BT_CHNL_IDS; i++) {
|
||||
/* Undo registration with ST */
|
||||
err = st_unregister(&ti_st_proto[i]);
|
||||
|
@ -236,9 +229,6 @@ static int ti_st_close(struct hci_dev *hdev)
|
|||
int err, i;
|
||||
struct ti_st *hst = hci_get_drvdata(hdev);
|
||||
|
||||
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
|
||||
return 0;
|
||||
|
||||
for (i = MAX_BT_CHNL_IDS-1; i >= 0; i--) {
|
||||
err = st_unregister(&ti_st_proto[i]);
|
||||
if (err)
|
||||
|
@ -256,9 +246,6 @@ static int ti_st_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
struct ti_st *hst;
|
||||
long len;
|
||||
|
||||
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
||||
return -EBUSY;
|
||||
|
||||
hst = hci_get_drvdata(hdev);
|
||||
|
||||
/* Prepend skb with frame type */
|
||||
|
|
|
@ -357,8 +357,6 @@ static irqreturn_t dtl1_interrupt(int irq, void *dev_inst)
|
|||
|
||||
static int dtl1_hci_open(struct hci_dev *hdev)
|
||||
{
|
||||
set_bit(HCI_RUNNING, &(hdev->flags));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -376,9 +374,6 @@ static int dtl1_hci_flush(struct hci_dev *hdev)
|
|||
|
||||
static int dtl1_hci_close(struct hci_dev *hdev)
|
||||
{
|
||||
if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
|
||||
return 0;
|
||||
|
||||
dtl1_hci_flush(hdev);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
|
@ -39,6 +41,11 @@
|
|||
#include "btbcm.h"
|
||||
#include "hci_uart.h"
|
||||
|
||||
#define BCM_LM_DIAG_PKT 0x07
|
||||
#define BCM_LM_DIAG_SIZE 63
|
||||
|
||||
#define BCM_AUTOSUSPEND_DELAY 5000 /* default autosleep delay */
|
||||
|
||||
struct bcm_device {
|
||||
struct list_head list;
|
||||
|
||||
|
@ -55,7 +62,7 @@ struct bcm_device {
|
|||
int irq;
|
||||
u8 irq_polarity;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
#ifdef CONFIG_PM
|
||||
struct hci_uart *hu;
|
||||
bool is_suspended; /* suspend/resume flag */
|
||||
#endif
|
||||
|
@ -152,13 +159,17 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
#ifdef CONFIG_PM
|
||||
static irqreturn_t bcm_host_wake(int irq, void *data)
|
||||
{
|
||||
struct bcm_device *bdev = data;
|
||||
|
||||
bt_dev_dbg(bdev, "Host wake IRQ");
|
||||
|
||||
pm_runtime_get(&bdev->pdev->dev);
|
||||
pm_runtime_mark_last_busy(&bdev->pdev->dev);
|
||||
pm_runtime_put_autosuspend(&bdev->pdev->dev);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -182,6 +193,12 @@ static int bcm_request_irq(struct bcm_data *bcm)
|
|||
goto unlock;
|
||||
|
||||
device_init_wakeup(&bdev->pdev->dev, true);
|
||||
|
||||
pm_runtime_set_autosuspend_delay(&bdev->pdev->dev,
|
||||
BCM_AUTOSUSPEND_DELAY);
|
||||
pm_runtime_use_autosuspend(&bdev->pdev->dev);
|
||||
pm_runtime_set_active(&bdev->pdev->dev);
|
||||
pm_runtime_enable(&bdev->pdev->dev);
|
||||
}
|
||||
|
||||
unlock:
|
||||
|
@ -197,7 +214,7 @@ static const struct bcm_set_sleep_mode default_sleep_params = {
|
|||
.bt_wake_active = 1, /* BT_WAKE active mode: 1 = high, 0 = low */
|
||||
.host_wake_active = 0, /* HOST_WAKE active mode: 1 = high, 0 = low */
|
||||
.allow_host_sleep = 1, /* Allow host sleep in SCO flag */
|
||||
.combine_modes = 0, /* Combine sleep and LPM flag */
|
||||
.combine_modes = 1, /* Combine sleep and LPM flag */
|
||||
.tristate_control = 0, /* Allow tri-state control of UART tx flag */
|
||||
/* Irrelevant USB flags */
|
||||
.usb_auto_sleep = 0,
|
||||
|
@ -232,6 +249,29 @@ static inline int bcm_request_irq(struct bcm_data *bcm) { return 0; }
|
|||
static inline int bcm_setup_sleep(struct hci_uart *hu) { return 0; }
|
||||
#endif
|
||||
|
||||
static int bcm_set_diag(struct hci_dev *hdev, bool enable)
|
||||
{
|
||||
struct hci_uart *hu = hci_get_drvdata(hdev);
|
||||
struct bcm_data *bcm = hu->priv;
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
||||
return -ENETDOWN;
|
||||
|
||||
skb = bt_skb_alloc(3, GFP_KERNEL);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
*skb_put(skb, 1) = BCM_LM_DIAG_PKT;
|
||||
*skb_put(skb, 1) = 0xf0;
|
||||
*skb_put(skb, 1) = enable;
|
||||
|
||||
skb_queue_tail(&bcm->txq, skb);
|
||||
hci_uart_tx_wakeup(hu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm_open(struct hci_uart *hu)
|
||||
{
|
||||
struct bcm_data *bcm;
|
||||
|
@ -258,7 +298,7 @@ static int bcm_open(struct hci_uart *hu)
|
|||
if (hu->tty->dev->parent == dev->pdev->dev.parent) {
|
||||
bcm->dev = dev;
|
||||
hu->init_speed = dev->init_speed;
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
#ifdef CONFIG_PM
|
||||
dev->hu = hu;
|
||||
#endif
|
||||
bcm_gpio_set_power(bcm->dev, true);
|
||||
|
@ -282,7 +322,10 @@ static int bcm_close(struct hci_uart *hu)
|
|||
mutex_lock(&bcm_device_lock);
|
||||
if (bcm_device_exists(bdev)) {
|
||||
bcm_gpio_set_power(bdev, false);
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
#ifdef CONFIG_PM
|
||||
pm_runtime_disable(&bdev->pdev->dev);
|
||||
pm_runtime_set_suspended(&bdev->pdev->dev);
|
||||
|
||||
if (device_can_wakeup(&bdev->pdev->dev)) {
|
||||
devm_free_irq(&bdev->pdev->dev, bdev->irq, bdev);
|
||||
device_init_wakeup(&bdev->pdev->dev, false);
|
||||
|
@ -322,6 +365,7 @@ static int bcm_setup(struct hci_uart *hu)
|
|||
|
||||
bt_dev_dbg(hu->hdev, "hu %p", hu);
|
||||
|
||||
hu->hdev->set_diag = bcm_set_diag;
|
||||
hu->hdev->set_bdaddr = btbcm_set_bdaddr;
|
||||
|
||||
err = btbcm_initialize(hu->hdev, fw_name, sizeof(fw_name));
|
||||
|
@ -379,10 +423,18 @@ finalize:
|
|||
return err;
|
||||
}
|
||||
|
||||
#define BCM_RECV_LM_DIAG \
|
||||
.type = BCM_LM_DIAG_PKT, \
|
||||
.hlen = BCM_LM_DIAG_SIZE, \
|
||||
.loff = 0, \
|
||||
.lsize = 0, \
|
||||
.maxlen = BCM_LM_DIAG_SIZE
|
||||
|
||||
static const struct h4_recv_pkt bcm_recv_pkts[] = {
|
||||
{ H4_RECV_ACL, .recv = hci_recv_frame },
|
||||
{ H4_RECV_SCO, .recv = hci_recv_frame },
|
||||
{ H4_RECV_EVENT, .recv = hci_recv_frame },
|
||||
{ BCM_RECV_LM_DIAG, .recv = hci_recv_diag },
|
||||
};
|
||||
|
||||
static int bcm_recv(struct hci_uart *hu, const void *data, int count)
|
||||
|
@ -399,6 +451,15 @@ static int bcm_recv(struct hci_uart *hu, const void *data, int count)
|
|||
bt_dev_err(hu->hdev, "Frame reassembly failed (%d)", err);
|
||||
bcm->rx_skb = NULL;
|
||||
return err;
|
||||
} else if (!bcm->rx_skb) {
|
||||
/* Delay auto-suspend when receiving completed packet */
|
||||
mutex_lock(&bcm_device_lock);
|
||||
if (bcm->dev && bcm_device_exists(bcm->dev)) {
|
||||
pm_runtime_get(&bcm->dev->pdev->dev);
|
||||
pm_runtime_mark_last_busy(&bcm->dev->pdev->dev);
|
||||
pm_runtime_put_autosuspend(&bcm->dev->pdev->dev);
|
||||
}
|
||||
mutex_unlock(&bcm_device_lock);
|
||||
}
|
||||
|
||||
return count;
|
||||
|
@ -420,10 +481,76 @@ static int bcm_enqueue(struct hci_uart *hu, struct sk_buff *skb)
|
|||
static struct sk_buff *bcm_dequeue(struct hci_uart *hu)
|
||||
{
|
||||
struct bcm_data *bcm = hu->priv;
|
||||
struct sk_buff *skb = NULL;
|
||||
struct bcm_device *bdev = NULL;
|
||||
|
||||
return skb_dequeue(&bcm->txq);
|
||||
mutex_lock(&bcm_device_lock);
|
||||
|
||||
if (bcm_device_exists(bcm->dev)) {
|
||||
bdev = bcm->dev;
|
||||
pm_runtime_get_sync(&bdev->pdev->dev);
|
||||
/* Shall be resumed here */
|
||||
}
|
||||
|
||||
skb = skb_dequeue(&bcm->txq);
|
||||
|
||||
if (bdev) {
|
||||
pm_runtime_mark_last_busy(&bdev->pdev->dev);
|
||||
pm_runtime_put_autosuspend(&bdev->pdev->dev);
|
||||
}
|
||||
|
||||
mutex_unlock(&bcm_device_lock);
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int bcm_suspend_device(struct device *dev)
|
||||
{
|
||||
struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev));
|
||||
|
||||
bt_dev_dbg(bdev, "");
|
||||
|
||||
if (!bdev->is_suspended && bdev->hu) {
|
||||
hci_uart_set_flow_control(bdev->hu, true);
|
||||
|
||||
/* Once this returns, driver suspends BT via GPIO */
|
||||
bdev->is_suspended = true;
|
||||
}
|
||||
|
||||
/* Suspend the device */
|
||||
if (bdev->device_wakeup) {
|
||||
gpiod_set_value(bdev->device_wakeup, false);
|
||||
bt_dev_dbg(bdev, "suspend, delaying 15 ms");
|
||||
mdelay(15);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm_resume_device(struct device *dev)
|
||||
{
|
||||
struct bcm_device *bdev = platform_get_drvdata(to_platform_device(dev));
|
||||
|
||||
bt_dev_dbg(bdev, "");
|
||||
|
||||
if (bdev->device_wakeup) {
|
||||
gpiod_set_value(bdev->device_wakeup, true);
|
||||
bt_dev_dbg(bdev, "resume, delaying 15 ms");
|
||||
mdelay(15);
|
||||
}
|
||||
|
||||
/* When this executes, the device has woken up already */
|
||||
if (bdev->is_suspended && bdev->hu) {
|
||||
bdev->is_suspended = false;
|
||||
|
||||
hci_uart_set_flow_control(bdev->hu, false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
/* Platform suspend callback */
|
||||
static int bcm_suspend(struct device *dev)
|
||||
|
@ -433,24 +560,17 @@ static int bcm_suspend(struct device *dev)
|
|||
|
||||
bt_dev_dbg(bdev, "suspend: is_suspended %d", bdev->is_suspended);
|
||||
|
||||
/* bcm_suspend can be called at any time as long as platform device is
|
||||
* bound, so it should use bcm_device_lock to protect access to hci_uart
|
||||
* and device_wake-up GPIO.
|
||||
*/
|
||||
mutex_lock(&bcm_device_lock);
|
||||
|
||||
if (!bdev->hu)
|
||||
goto unlock;
|
||||
|
||||
if (!bdev->is_suspended) {
|
||||
hci_uart_set_flow_control(bdev->hu, true);
|
||||
|
||||
/* Once this callback returns, driver suspends BT via GPIO */
|
||||
bdev->is_suspended = true;
|
||||
}
|
||||
|
||||
/* Suspend the device */
|
||||
if (bdev->device_wakeup) {
|
||||
gpiod_set_value(bdev->device_wakeup, false);
|
||||
bt_dev_dbg(bdev, "suspend, delaying 15 ms");
|
||||
mdelay(15);
|
||||
}
|
||||
if (pm_runtime_active(dev))
|
||||
bcm_suspend_device(dev);
|
||||
|
||||
if (device_may_wakeup(&bdev->pdev->dev)) {
|
||||
error = enable_irq_wake(bdev->irq);
|
||||
|
@ -471,6 +591,10 @@ static int bcm_resume(struct device *dev)
|
|||
|
||||
bt_dev_dbg(bdev, "resume: is_suspended %d", bdev->is_suspended);
|
||||
|
||||
/* bcm_resume can be called at any time as long as platform device is
|
||||
* bound, so it should use bcm_device_lock to protect access to hci_uart
|
||||
* and device_wake-up GPIO.
|
||||
*/
|
||||
mutex_lock(&bcm_device_lock);
|
||||
|
||||
if (!bdev->hu)
|
||||
|
@ -481,22 +605,15 @@ static int bcm_resume(struct device *dev)
|
|||
bt_dev_dbg(bdev, "BCM irq: disabled");
|
||||
}
|
||||
|
||||
if (bdev->device_wakeup) {
|
||||
gpiod_set_value(bdev->device_wakeup, true);
|
||||
bt_dev_dbg(bdev, "resume, delaying 15 ms");
|
||||
mdelay(15);
|
||||
}
|
||||
|
||||
/* When this callback executes, the device has woken up already */
|
||||
if (bdev->is_suspended) {
|
||||
bdev->is_suspended = false;
|
||||
|
||||
hci_uart_set_flow_control(bdev->hu, false);
|
||||
}
|
||||
bcm_resume_device(dev);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&bcm_device_lock);
|
||||
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -513,6 +630,22 @@ static const struct acpi_gpio_mapping acpi_bcm_default_gpios[] = {
|
|||
};
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static u8 acpi_active_low = ACPI_ACTIVE_LOW;
|
||||
|
||||
/* IRQ polarity of some chipsets are not defined correctly in ACPI table. */
|
||||
static const struct dmi_system_id bcm_wrong_irq_dmi_table[] = {
|
||||
{
|
||||
.ident = "Asus T100TA",
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR,
|
||||
"ASUSTeK COMPUTER INC."),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"),
|
||||
},
|
||||
.driver_data = &acpi_active_low,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static int bcm_resource(struct acpi_resource *ares, void *data)
|
||||
{
|
||||
struct bcm_device *dev = data;
|
||||
|
@ -549,15 +682,10 @@ static int bcm_resource(struct acpi_resource *ares, void *data)
|
|||
static int bcm_acpi_probe(struct bcm_device *dev)
|
||||
{
|
||||
struct platform_device *pdev = dev->pdev;
|
||||
const struct acpi_device_id *id;
|
||||
struct acpi_device *adev;
|
||||
LIST_HEAD(resources);
|
||||
const struct dmi_system_id *dmi_id;
|
||||
int ret;
|
||||
|
||||
id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
|
||||
if (!id)
|
||||
return -ENODEV;
|
||||
|
||||
/* Retrieve GPIO data */
|
||||
dev->name = dev_name(&pdev->dev);
|
||||
ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(&pdev->dev),
|
||||
|
@ -602,11 +730,18 @@ static int bcm_acpi_probe(struct bcm_device *dev)
|
|||
}
|
||||
|
||||
/* Retrieve UART ACPI info */
|
||||
adev = ACPI_COMPANION(&dev->pdev->dev);
|
||||
if (!adev)
|
||||
return 0;
|
||||
ret = acpi_dev_get_resources(ACPI_COMPANION(&dev->pdev->dev),
|
||||
&resources, bcm_resource, dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
acpi_dev_free_resource_list(&resources);
|
||||
|
||||
acpi_dev_get_resources(adev, &resources, bcm_resource, dev);
|
||||
dmi_id = dmi_first_match(bcm_wrong_irq_dmi_table);
|
||||
if (dmi_id) {
|
||||
bt_dev_warn(dev, "%s: Overwriting IRQ polarity to active low",
|
||||
dmi_id->ident);
|
||||
dev->irq_polarity = *(u8 *)dmi_id->driver_data;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -620,7 +755,6 @@ static int bcm_acpi_probe(struct bcm_device *dev)
|
|||
static int bcm_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct bcm_device *dev;
|
||||
struct acpi_device_id *pdata = pdev->dev.platform_data;
|
||||
int ret;
|
||||
|
||||
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
|
||||
|
@ -629,15 +763,9 @@ static int bcm_probe(struct platform_device *pdev)
|
|||
|
||||
dev->pdev = pdev;
|
||||
|
||||
if (ACPI_HANDLE(&pdev->dev)) {
|
||||
ret = bcm_acpi_probe(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else if (pdata) {
|
||||
dev->name = pdata->id;
|
||||
} else {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, dev);
|
||||
|
||||
|
@ -693,7 +821,10 @@ MODULE_DEVICE_TABLE(acpi, bcm_acpi_match);
|
|||
#endif
|
||||
|
||||
/* Platform suspend and resume callbacks */
|
||||
static SIMPLE_DEV_PM_OPS(bcm_pm_ops, bcm_suspend, bcm_resume);
|
||||
static const struct dev_pm_ops bcm_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(bcm_suspend, bcm_resume)
|
||||
SET_RUNTIME_PM_OPS(bcm_suspend_device, bcm_resume_device, NULL)
|
||||
};
|
||||
|
||||
static struct platform_driver bcm_driver = {
|
||||
.probe = bcm_probe,
|
||||
|
|
|
@ -266,3 +266,4 @@ struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb,
|
|||
|
||||
return skb;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(h4_recv_buf);
|
||||
|
|
|
@ -128,7 +128,7 @@ static void h5_timed_event(unsigned long arg)
|
|||
{
|
||||
const unsigned char sync_req[] = { 0x01, 0x7e };
|
||||
unsigned char conf_req[] = { 0x03, 0xfc, 0x01 };
|
||||
struct hci_uart *hu = (struct hci_uart *) arg;
|
||||
struct hci_uart *hu = (struct hci_uart *)arg;
|
||||
struct h5 *h5 = hu->priv;
|
||||
struct sk_buff *skb;
|
||||
unsigned long flags;
|
||||
|
@ -210,7 +210,7 @@ static int h5_open(struct hci_uart *hu)
|
|||
|
||||
init_timer(&h5->timer);
|
||||
h5->timer.function = h5_timed_event;
|
||||
h5->timer.data = (unsigned long) hu;
|
||||
h5->timer.data = (unsigned long)hu;
|
||||
|
||||
h5->tx_win = H5_TX_WIN_MAX;
|
||||
|
||||
|
@ -453,7 +453,7 @@ static int h5_rx_pkt_start(struct hci_uart *hu, unsigned char c)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
h5->rx_skb->dev = (void *) hu->hdev;
|
||||
h5->rx_skb->dev = (void *)hu->hdev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -696,7 +696,7 @@ static struct sk_buff *h5_dequeue(struct hci_uart *hu)
|
|||
}
|
||||
|
||||
skb = skb_dequeue(&h5->unrel);
|
||||
if (skb != NULL) {
|
||||
if (skb) {
|
||||
nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type,
|
||||
skb->data, skb->len);
|
||||
if (nskb) {
|
||||
|
@ -714,7 +714,7 @@ static struct sk_buff *h5_dequeue(struct hci_uart *hu)
|
|||
goto unlock;
|
||||
|
||||
skb = skb_dequeue(&h5->rel);
|
||||
if (skb != NULL) {
|
||||
if (skb) {
|
||||
nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type,
|
||||
skb->data, skb->len);
|
||||
if (nskb) {
|
||||
|
|
|
@ -1165,22 +1165,6 @@ static const struct acpi_device_id intel_acpi_match[] = {
|
|||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, intel_acpi_match);
|
||||
|
||||
static int intel_acpi_probe(struct intel_device *idev)
|
||||
{
|
||||
const struct acpi_device_id *id;
|
||||
|
||||
id = acpi_match_device(intel_acpi_match, &idev->pdev->dev);
|
||||
if (!id)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int intel_acpi_probe(struct intel_device *idev)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
@ -1248,14 +1232,6 @@ static int intel_probe(struct platform_device *pdev)
|
|||
|
||||
idev->pdev = pdev;
|
||||
|
||||
if (ACPI_HANDLE(&pdev->dev)) {
|
||||
int err = intel_acpi_probe(idev);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
idev->reset = devm_gpiod_get_optional(&pdev->dev, "reset",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(idev->reset)) {
|
||||
|
|
|
@ -208,9 +208,6 @@ static int hci_uart_open(struct hci_dev *hdev)
|
|||
BT_DBG("%s %p", hdev->name, hdev);
|
||||
|
||||
/* Nothing to do for UART driver */
|
||||
|
||||
set_bit(HCI_RUNNING, &hdev->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -241,9 +238,6 @@ static int hci_uart_close(struct hci_dev *hdev)
|
|||
{
|
||||
BT_DBG("hdev %p", hdev);
|
||||
|
||||
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
|
||||
return 0;
|
||||
|
||||
hci_uart_flush(hdev);
|
||||
hdev->flush = NULL;
|
||||
return 0;
|
||||
|
@ -254,9 +248,6 @@ static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
{
|
||||
struct hci_uart *hu = hci_get_drvdata(hdev);
|
||||
|
||||
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
||||
return -EBUSY;
|
||||
|
||||
BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);
|
||||
|
||||
hu->proto->enqueue(hu, skb);
|
||||
|
@ -470,8 +461,6 @@ static int hci_uart_tty_open(struct tty_struct *tty)
|
|||
INIT_WORK(&hu->init_ready, hci_uart_init_work);
|
||||
INIT_WORK(&hu->write_work, hci_uart_write_work);
|
||||
|
||||
spin_lock_init(&hu->rx_lock);
|
||||
|
||||
/* Flush any pending characters in the driver and line discipline. */
|
||||
|
||||
/* FIXME: why is this needed. Note don't use ldisc_ref here as the
|
||||
|
@ -569,14 +558,14 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data,
|
|||
if (!test_bit(HCI_UART_PROTO_SET, &hu->flags))
|
||||
return;
|
||||
|
||||
spin_lock(&hu->rx_lock);
|
||||
/* It does not need a lock here as it is already protected by a mutex in
|
||||
* tty caller
|
||||
*/
|
||||
hu->proto->recv(hu, data, count);
|
||||
|
||||
if (hu->hdev)
|
||||
hu->hdev->stat.byte_rx += count;
|
||||
|
||||
spin_unlock(&hu->rx_lock);
|
||||
|
||||
tty_unthrottle(tty);
|
||||
}
|
||||
|
||||
|
|
|
@ -347,7 +347,7 @@ static void hci_ibs_wake_retrans_timeout(unsigned long arg)
|
|||
struct hci_uart *hu = (struct hci_uart *)arg;
|
||||
struct qca_data *qca = hu->priv;
|
||||
unsigned long flags, retrans_delay;
|
||||
unsigned long retransmit = 0;
|
||||
bool retransmit = false;
|
||||
|
||||
BT_DBG("hu %p wake retransmit timeout in %d state",
|
||||
hu, qca->tx_ibs_state);
|
||||
|
@ -358,7 +358,7 @@ static void hci_ibs_wake_retrans_timeout(unsigned long arg)
|
|||
switch (qca->tx_ibs_state) {
|
||||
case HCI_IBS_TX_WAKING:
|
||||
/* No WAKE_ACK, retransmit WAKE */
|
||||
retransmit = 1;
|
||||
retransmit = true;
|
||||
if (send_hci_ibs_cmd(HCI_IBS_WAKE_IND, hu) < 0) {
|
||||
BT_ERR("Failed to acknowledge device wake up");
|
||||
break;
|
||||
|
|
|
@ -85,7 +85,6 @@ struct hci_uart {
|
|||
|
||||
struct sk_buff *tx_skb;
|
||||
unsigned long tx_state;
|
||||
spinlock_t rx_lock;
|
||||
|
||||
unsigned int init_speed;
|
||||
unsigned int oper_speed;
|
||||
|
|
|
@ -55,8 +55,6 @@ struct vhci_data {
|
|||
|
||||
static int vhci_open_dev(struct hci_dev *hdev)
|
||||
{
|
||||
set_bit(HCI_RUNNING, &hdev->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -64,9 +62,6 @@ static int vhci_close_dev(struct hci_dev *hdev)
|
|||
{
|
||||
struct vhci_data *data = hci_get_drvdata(hdev);
|
||||
|
||||
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
|
||||
return 0;
|
||||
|
||||
skb_queue_purge(&data->readq);
|
||||
|
||||
return 0;
|
||||
|
@ -85,9 +80,6 @@ static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
{
|
||||
struct vhci_data *data = hci_get_drvdata(hdev);
|
||||
|
||||
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
||||
return -EBUSY;
|
||||
|
||||
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
|
||||
skb_queue_tail(&data->readq, skb);
|
||||
|
||||
|
|
|
@ -1325,9 +1325,6 @@ static void nes_netdev_get_drvinfo(struct net_device *netdev,
|
|||
"%u.%u", nesadapter->firmware_version >> 16,
|
||||
nesadapter->firmware_version & 0x000000ff);
|
||||
strlcpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version));
|
||||
drvinfo->testinfo_len = 0;
|
||||
drvinfo->eedump_len = 0;
|
||||
drvinfo->regdump_len = 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -235,7 +235,7 @@ void dsp_pipeline_destroy(struct dsp_pipeline *pipeline)
|
|||
|
||||
int dsp_pipeline_build(struct dsp_pipeline *pipeline, const char *cfg)
|
||||
{
|
||||
int len, incomplete = 0, found = 0;
|
||||
int incomplete = 0, found = 0;
|
||||
char *dup, *tok, *name, *args;
|
||||
struct dsp_element_entry *entry, *n;
|
||||
struct dsp_pipeline_entry *pipeline_entry;
|
||||
|
@ -247,17 +247,9 @@ int dsp_pipeline_build(struct dsp_pipeline *pipeline, const char *cfg)
|
|||
if (!list_empty(&pipeline->list))
|
||||
_dsp_pipeline_destroy(pipeline);
|
||||
|
||||
if (!cfg)
|
||||
return 0;
|
||||
|
||||
len = strlen(cfg);
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
dup = kmalloc(len + 1, GFP_ATOMIC);
|
||||
dup = kstrdup(cfg, GFP_ATOMIC);
|
||||
if (!dup)
|
||||
return 0;
|
||||
strcpy(dup, cfg);
|
||||
while ((tok = strsep(&dup, "|"))) {
|
||||
if (!strlen(tok))
|
||||
continue;
|
||||
|
|
|
@ -298,8 +298,10 @@ config NLMON
|
|||
|
||||
config NET_VRF
|
||||
tristate "Virtual Routing and Forwarding (Lite)"
|
||||
depends on IP_MULTIPLE_TABLES && IPV6_MULTIPLE_TABLES
|
||||
depends on IP_MULTIPLE_TABLES
|
||||
depends on NET_L3_MASTER_DEV
|
||||
depends on IPV6 || IPV6=n
|
||||
depends on IPV6_MULTIPLE_TABLES || IPV6=n
|
||||
---help---
|
||||
This option enables the support for mapping interfaces into VRF's. The
|
||||
support enables VRF devices.
|
||||
|
|
|
@ -1071,7 +1071,7 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
|
|||
NETIF_F_HIGHDMA | NETIF_F_LRO)
|
||||
|
||||
#define BOND_ENC_FEATURES (NETIF_F_ALL_CSUM | NETIF_F_SG | NETIF_F_RXCSUM |\
|
||||
NETIF_F_TSO)
|
||||
NETIF_F_ALL_TSO)
|
||||
|
||||
static void bond_compute_features(struct bonding *bond)
|
||||
{
|
||||
|
|
|
@ -8,15 +8,6 @@
|
|||
* Public License ("GPL") version 2 as distributed in the 'COPYING'
|
||||
* file from the main directory of the linux kernel source.
|
||||
*
|
||||
*
|
||||
* Your platform definition file should specify something like:
|
||||
*
|
||||
* static struct at91_can_data ek_can_data = {
|
||||
* transceiver_switch = sam9263ek_transceiver_switch,
|
||||
* };
|
||||
*
|
||||
* at91_add_device_can(&ek_can_data);
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
|
@ -33,7 +24,6 @@
|
|||
#include <linux/spinlock.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/platform_data/atmel.h>
|
||||
|
||||
#include <linux/can/dev.h>
|
||||
#include <linux/can/error.h>
|
||||
|
@ -324,15 +314,6 @@ static inline u32 at91_can_id_to_reg_mid(canid_t can_id)
|
|||
return reg_mid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Swtich transceiver on or off
|
||||
*/
|
||||
static void at91_transceiver_switch(const struct at91_priv *priv, int on)
|
||||
{
|
||||
if (priv->pdata && priv->pdata->transceiver_switch)
|
||||
priv->pdata->transceiver_switch(on);
|
||||
}
|
||||
|
||||
static void at91_setup_mailboxes(struct net_device *dev)
|
||||
{
|
||||
struct at91_priv *priv = netdev_priv(dev);
|
||||
|
@ -416,7 +397,6 @@ static void at91_chip_start(struct net_device *dev)
|
|||
|
||||
at91_set_bittiming(dev);
|
||||
at91_setup_mailboxes(dev);
|
||||
at91_transceiver_switch(priv, 1);
|
||||
|
||||
/* enable chip */
|
||||
if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
|
||||
|
@ -444,7 +424,6 @@ static void at91_chip_stop(struct net_device *dev, enum can_state state)
|
|||
reg_mr = at91_read(priv, AT91_MR);
|
||||
at91_write(priv, AT91_MR, reg_mr & ~AT91_MR_CANEN);
|
||||
|
||||
at91_transceiver_switch(priv, 0);
|
||||
priv->can.state = state;
|
||||
}
|
||||
|
||||
|
|
|
@ -601,7 +601,7 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status)
|
|||
stats->tx_errors++;
|
||||
if (likely(skb)) {
|
||||
cf->can_id |= CAN_ERR_LOSTARB;
|
||||
cf->data[0] = (alc & 0x1f) >> 8;
|
||||
cf->data[0] = (alc >> 8) & 0x1f;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -854,4 +854,4 @@ module_platform_driver(sun4i_can_driver);
|
|||
MODULE_AUTHOR("Peter Chen <xingkongcp@gmail.com>");
|
||||
MODULE_AUTHOR("Gerhard Bertelsmann <info@gerhard-bertelsmann.de>");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_DESCRIPTION(DRV_NAME "CAN driver for Allwinner SoCs (A10/A20)");
|
||||
MODULE_DESCRIPTION("CAN driver for Allwinner SoCs (A10/A20)");
|
||||
|
|
|
@ -125,7 +125,6 @@ struct dsa_switch_driver mv88e6123_61_65_switch_driver = {
|
|||
.set_addr = mv88e6xxx_set_addr_indirect,
|
||||
.phy_read = mv88e6xxx_phy_read,
|
||||
.phy_write = mv88e6xxx_phy_write,
|
||||
.poll_link = mv88e6xxx_poll_link,
|
||||
.get_strings = mv88e6xxx_get_strings,
|
||||
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
|
||||
.get_sset_count = mv88e6xxx_get_sset_count,
|
||||
|
|
|
@ -178,7 +178,6 @@ struct dsa_switch_driver mv88e6131_switch_driver = {
|
|||
.set_addr = mv88e6xxx_set_addr_direct,
|
||||
.phy_read = mv88e6131_phy_read,
|
||||
.phy_write = mv88e6131_phy_write,
|
||||
.poll_link = mv88e6xxx_poll_link,
|
||||
.get_strings = mv88e6xxx_get_strings,
|
||||
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
|
||||
.get_sset_count = mv88e6xxx_get_sset_count,
|
||||
|
|
|
@ -104,7 +104,6 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
|
|||
.set_addr = mv88e6xxx_set_addr_indirect,
|
||||
.phy_read = mv88e6xxx_phy_read_indirect,
|
||||
.phy_write = mv88e6xxx_phy_write_indirect,
|
||||
.poll_link = mv88e6xxx_poll_link,
|
||||
.get_strings = mv88e6xxx_get_strings,
|
||||
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
|
||||
.get_sset_count = mv88e6xxx_get_sset_count,
|
||||
|
@ -114,14 +113,13 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
|
|||
#endif
|
||||
.get_regs_len = mv88e6xxx_get_regs_len,
|
||||
.get_regs = mv88e6xxx_get_regs,
|
||||
.port_join_bridge = mv88e6xxx_join_bridge,
|
||||
.port_leave_bridge = mv88e6xxx_leave_bridge,
|
||||
.port_stp_update = mv88e6xxx_port_stp_update,
|
||||
.port_pvid_get = mv88e6xxx_port_pvid_get,
|
||||
.port_pvid_set = mv88e6xxx_port_pvid_set,
|
||||
.port_vlan_add = mv88e6xxx_port_vlan_add,
|
||||
.port_vlan_del = mv88e6xxx_port_vlan_del,
|
||||
.vlan_getnext = mv88e6xxx_vlan_getnext,
|
||||
.port_fdb_prepare = mv88e6xxx_port_fdb_prepare,
|
||||
.port_fdb_add = mv88e6xxx_port_fdb_add,
|
||||
.port_fdb_del = mv88e6xxx_port_fdb_del,
|
||||
.port_fdb_getnext = mv88e6xxx_port_fdb_getnext,
|
||||
|
|
|
@ -324,7 +324,6 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
|
|||
.set_addr = mv88e6xxx_set_addr_indirect,
|
||||
.phy_read = mv88e6xxx_phy_read_indirect,
|
||||
.phy_write = mv88e6xxx_phy_write_indirect,
|
||||
.poll_link = mv88e6xxx_poll_link,
|
||||
.get_strings = mv88e6xxx_get_strings,
|
||||
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
|
||||
.get_sset_count = mv88e6xxx_get_sset_count,
|
||||
|
@ -341,14 +340,13 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
|
|||
.set_eeprom = mv88e6352_set_eeprom,
|
||||
.get_regs_len = mv88e6xxx_get_regs_len,
|
||||
.get_regs = mv88e6xxx_get_regs,
|
||||
.port_join_bridge = mv88e6xxx_join_bridge,
|
||||
.port_leave_bridge = mv88e6xxx_leave_bridge,
|
||||
.port_stp_update = mv88e6xxx_port_stp_update,
|
||||
.port_pvid_get = mv88e6xxx_port_pvid_get,
|
||||
.port_pvid_set = mv88e6xxx_port_pvid_set,
|
||||
.port_vlan_add = mv88e6xxx_port_vlan_add,
|
||||
.port_vlan_del = mv88e6xxx_port_vlan_del,
|
||||
.vlan_getnext = mv88e6xxx_vlan_getnext,
|
||||
.port_fdb_prepare = mv88e6xxx_port_fdb_prepare,
|
||||
.port_fdb_add = mv88e6xxx_port_fdb_add,
|
||||
.port_fdb_del = mv88e6xxx_port_fdb_del,
|
||||
.port_fdb_getnext = mv88e6xxx_port_fdb_getnext,
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/phy.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <net/dsa.h>
|
||||
#include <net/switchdev.h>
|
||||
#include "mv88e6xxx.h"
|
||||
|
||||
/* MDIO bus access can be nested in the case of PHYs connected to the
|
||||
|
@ -388,73 +389,6 @@ int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
|
|||
}
|
||||
#endif
|
||||
|
||||
void mv88e6xxx_poll_link(struct dsa_switch *ds)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DSA_MAX_PORTS; i++) {
|
||||
struct net_device *dev;
|
||||
int uninitialized_var(port_status);
|
||||
int pcs_ctrl;
|
||||
int link;
|
||||
int speed;
|
||||
int duplex;
|
||||
int fc;
|
||||
|
||||
dev = ds->ports[i];
|
||||
if (dev == NULL)
|
||||
continue;
|
||||
|
||||
pcs_ctrl = mv88e6xxx_reg_read(ds, REG_PORT(i), PORT_PCS_CTRL);
|
||||
if (pcs_ctrl < 0 || pcs_ctrl & PORT_PCS_CTRL_FORCE_LINK)
|
||||
continue;
|
||||
|
||||
link = 0;
|
||||
if (dev->flags & IFF_UP) {
|
||||
port_status = mv88e6xxx_reg_read(ds, REG_PORT(i),
|
||||
PORT_STATUS);
|
||||
if (port_status < 0)
|
||||
continue;
|
||||
|
||||
link = !!(port_status & PORT_STATUS_LINK);
|
||||
}
|
||||
|
||||
if (!link) {
|
||||
if (netif_carrier_ok(dev)) {
|
||||
netdev_info(dev, "link down\n");
|
||||
netif_carrier_off(dev);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (port_status & PORT_STATUS_SPEED_MASK) {
|
||||
case PORT_STATUS_SPEED_10:
|
||||
speed = 10;
|
||||
break;
|
||||
case PORT_STATUS_SPEED_100:
|
||||
speed = 100;
|
||||
break;
|
||||
case PORT_STATUS_SPEED_1000:
|
||||
speed = 1000;
|
||||
break;
|
||||
default:
|
||||
speed = -1;
|
||||
break;
|
||||
}
|
||||
duplex = (port_status & PORT_STATUS_DUPLEX) ? 1 : 0;
|
||||
fc = (port_status & PORT_STATUS_PAUSE_EN) ? 1 : 0;
|
||||
|
||||
if (!netif_carrier_ok(dev)) {
|
||||
netdev_info(dev,
|
||||
"link up, %d Mb/s, %s duplex, flow control %sabled\n",
|
||||
speed,
|
||||
duplex ? "full" : "half",
|
||||
fc ? "en" : "dis");
|
||||
netif_carrier_on(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool mv88e6xxx_6065_family(struct dsa_switch *ds)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
|
@ -1112,11 +1046,6 @@ static int _mv88e6xxx_atu_flush(struct dsa_switch *ds, u16 fid, bool static_too)
|
|||
return _mv88e6xxx_atu_flush_move(ds, &entry, static_too);
|
||||
}
|
||||
|
||||
static int _mv88e6xxx_flush_fid(struct dsa_switch *ds, int fid)
|
||||
{
|
||||
return _mv88e6xxx_atu_flush(ds, fid, false);
|
||||
}
|
||||
|
||||
static int _mv88e6xxx_atu_move(struct dsa_switch *ds, u16 fid, int from_port,
|
||||
int to_port, bool static_too)
|
||||
{
|
||||
|
@ -1178,132 +1107,23 @@ abort:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Must be called with smi lock held */
|
||||
static int _mv88e6xxx_update_port_config(struct dsa_switch *ds, int port)
|
||||
static int _mv88e6xxx_port_vlan_map_set(struct dsa_switch *ds, int port,
|
||||
u16 output_ports)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
u8 fid = ps->fid[port];
|
||||
u16 reg = fid << 12;
|
||||
const u16 mask = (1 << ps->num_ports) - 1;
|
||||
int reg;
|
||||
|
||||
if (dsa_is_cpu_port(ds, port))
|
||||
reg |= ds->phys_port_mask;
|
||||
else
|
||||
reg |= (ps->bridge_mask[fid] |
|
||||
(1 << dsa_upstream_port(ds))) & ~(1 << port);
|
||||
reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_BASE_VLAN);
|
||||
if (reg < 0)
|
||||
return reg;
|
||||
|
||||
reg &= ~mask;
|
||||
reg |= output_ports & mask;
|
||||
|
||||
return _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_BASE_VLAN, reg);
|
||||
}
|
||||
|
||||
/* Must be called with smi lock held */
|
||||
static int _mv88e6xxx_update_bridge_config(struct dsa_switch *ds, int fid)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
int port;
|
||||
u32 mask;
|
||||
int ret;
|
||||
|
||||
mask = ds->phys_port_mask;
|
||||
while (mask) {
|
||||
port = __ffs(mask);
|
||||
mask &= ~(1 << port);
|
||||
if (ps->fid[port] != fid)
|
||||
continue;
|
||||
|
||||
ret = _mv88e6xxx_update_port_config(ds, port);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return _mv88e6xxx_flush_fid(ds, fid);
|
||||
}
|
||||
|
||||
/* Bridge handling functions */
|
||||
|
||||
int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
int ret = 0;
|
||||
u32 nmask;
|
||||
int fid;
|
||||
|
||||
/* If the bridge group is not empty, join that group.
|
||||
* Otherwise create a new group.
|
||||
*/
|
||||
fid = ps->fid[port];
|
||||
nmask = br_port_mask & ~(1 << port);
|
||||
if (nmask)
|
||||
fid = ps->fid[__ffs(nmask)];
|
||||
|
||||
nmask = ps->bridge_mask[fid] | (1 << port);
|
||||
if (nmask != br_port_mask) {
|
||||
netdev_err(ds->ports[port],
|
||||
"join: Bridge port mask mismatch fid=%d mask=0x%x expected 0x%x\n",
|
||||
fid, br_port_mask, nmask);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&ps->smi_mutex);
|
||||
|
||||
ps->bridge_mask[fid] = br_port_mask;
|
||||
|
||||
if (fid != ps->fid[port]) {
|
||||
clear_bit(ps->fid[port], ps->fid_bitmap);
|
||||
ps->fid[port] = fid;
|
||||
ret = _mv88e6xxx_update_bridge_config(ds, fid);
|
||||
}
|
||||
|
||||
mutex_unlock(&ps->smi_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
u8 fid, newfid;
|
||||
int ret;
|
||||
|
||||
fid = ps->fid[port];
|
||||
|
||||
if (ps->bridge_mask[fid] != br_port_mask) {
|
||||
netdev_err(ds->ports[port],
|
||||
"leave: Bridge port mask mismatch fid=%d mask=0x%x expected 0x%x\n",
|
||||
fid, br_port_mask, ps->bridge_mask[fid]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* If the port was the last port of a bridge, we are done.
|
||||
* Otherwise assign a new fid to the port, and fix up
|
||||
* the bridge configuration.
|
||||
*/
|
||||
if (br_port_mask == (1 << port))
|
||||
return 0;
|
||||
|
||||
mutex_lock(&ps->smi_mutex);
|
||||
|
||||
newfid = find_next_zero_bit(ps->fid_bitmap, VLAN_N_VID, 1);
|
||||
if (unlikely(newfid > ps->num_ports)) {
|
||||
netdev_err(ds->ports[port], "all first %d FIDs are used\n",
|
||||
ps->num_ports);
|
||||
ret = -ENOSPC;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ps->fid[port] = newfid;
|
||||
set_bit(newfid, ps->fid_bitmap);
|
||||
ps->bridge_mask[fid] &= ~(1 << port);
|
||||
ps->bridge_mask[newfid] = 1 << port;
|
||||
|
||||
ret = _mv88e6xxx_update_bridge_config(ds, fid);
|
||||
if (!ret)
|
||||
ret = _mv88e6xxx_update_bridge_config(ds, newfid);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&ps->smi_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
|
@ -1613,6 +1433,7 @@ static int _mv88e6xxx_vlan_init(struct dsa_switch *ds, u16 vid,
|
|||
struct mv88e6xxx_vtu_stu_entry vlan = {
|
||||
.valid = true,
|
||||
.vid = vid,
|
||||
.fid = vid, /* We use one FID per VLAN */
|
||||
};
|
||||
int i;
|
||||
|
||||
|
@ -1646,22 +1467,10 @@ static int _mv88e6xxx_vlan_init(struct dsa_switch *ds, u16 vid,
|
|||
return err;
|
||||
}
|
||||
|
||||
/* Non-bridged ports and bridge groups use FIDs from 1 to
|
||||
* num_ports; VLANs use FIDs from num_ports+1 to 4095.
|
||||
*/
|
||||
vlan.fid = find_next_zero_bit(ps->fid_bitmap, VLAN_N_VID,
|
||||
ps->num_ports + 1);
|
||||
if (unlikely(vlan.fid == VLAN_N_VID)) {
|
||||
pr_err("no more FID available for VLAN %d\n", vid);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
/* Clear all MAC addresses from the new database */
|
||||
err = _mv88e6xxx_atu_flush(ds, vlan.fid, true);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
set_bit(vlan.fid, ps->fid_bitmap);
|
||||
}
|
||||
|
||||
*entry = vlan;
|
||||
|
@ -1701,7 +1510,6 @@ int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid)
|
|||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
struct mv88e6xxx_vtu_stu_entry vlan;
|
||||
bool keep = false;
|
||||
int i, err;
|
||||
|
||||
mutex_lock(&ps->smi_mutex);
|
||||
|
@ -1719,28 +1527,22 @@ int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid)
|
|||
vlan.data[port] = GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER;
|
||||
|
||||
/* keep the VLAN unless all ports are excluded */
|
||||
vlan.valid = false;
|
||||
for (i = 0; i < ps->num_ports; ++i) {
|
||||
if (dsa_is_cpu_port(ds, i))
|
||||
continue;
|
||||
|
||||
if (vlan.data[i] != GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER) {
|
||||
keep = true;
|
||||
vlan.valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vlan.valid = keep;
|
||||
err = _mv88e6xxx_vtu_loadpurge(ds, &vlan);
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
err = _mv88e6xxx_atu_remove(ds, vlan.fid, port, false);
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
if (!keep)
|
||||
clear_bit(vlan.fid, ps->fid_bitmap);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&ps->smi_mutex);
|
||||
|
||||
|
@ -1867,37 +1669,13 @@ static int _mv88e6xxx_atu_load(struct dsa_switch *ds,
|
|||
return _mv88e6xxx_atu_cmd(ds, GLOBAL_ATU_OP_LOAD_DB);
|
||||
}
|
||||
|
||||
static int _mv88e6xxx_port_vid_to_fid(struct dsa_switch *ds, int port, u16 vid)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
struct mv88e6xxx_vtu_stu_entry vlan;
|
||||
int err;
|
||||
|
||||
if (vid == 0)
|
||||
return ps->fid[port];
|
||||
|
||||
err = _mv88e6xxx_port_vtu_getnext(ds, port, vid - 1, &vlan);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (vlan.vid == vid)
|
||||
return vlan.fid;
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int _mv88e6xxx_port_fdb_load(struct dsa_switch *ds, int port,
|
||||
const unsigned char *addr, u16 vid,
|
||||
u8 state)
|
||||
{
|
||||
struct mv88e6xxx_atu_entry entry = { 0 };
|
||||
int ret;
|
||||
|
||||
ret = _mv88e6xxx_port_vid_to_fid(ds, port, vid);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
entry.fid = ret;
|
||||
entry.fid = vid; /* We use one FID per VLAN */
|
||||
entry.state = state;
|
||||
ether_addr_copy(entry.mac, addr);
|
||||
if (state != GLOBAL_ATU_DATA_STATE_UNUSED) {
|
||||
|
@ -1908,30 +1686,45 @@ static int _mv88e6xxx_port_fdb_load(struct dsa_switch *ds, int port,
|
|||
return _mv88e6xxx_atu_load(ds, &entry);
|
||||
}
|
||||
|
||||
int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
|
||||
const unsigned char *addr, u16 vid)
|
||||
int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port,
|
||||
const struct switchdev_obj_port_fdb *fdb,
|
||||
struct switchdev_trans *trans)
|
||||
{
|
||||
int state = is_multicast_ether_addr(addr) ?
|
||||
/* We don't use per-port FDB */
|
||||
if (fdb->vid == 0)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* We don't need any dynamic resource from the kernel (yet),
|
||||
* so skip the prepare phase.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
|
||||
const struct switchdev_obj_port_fdb *fdb,
|
||||
struct switchdev_trans *trans)
|
||||
{
|
||||
int state = is_multicast_ether_addr(fdb->addr) ?
|
||||
GLOBAL_ATU_DATA_STATE_MC_STATIC :
|
||||
GLOBAL_ATU_DATA_STATE_UC_STATIC;
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ps->smi_mutex);
|
||||
ret = _mv88e6xxx_port_fdb_load(ds, port, addr, vid, state);
|
||||
ret = _mv88e6xxx_port_fdb_load(ds, port, fdb->addr, fdb->vid, state);
|
||||
mutex_unlock(&ps->smi_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
|
||||
const unsigned char *addr, u16 vid)
|
||||
const struct switchdev_obj_port_fdb *fdb)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ps->smi_mutex);
|
||||
ret = _mv88e6xxx_port_fdb_load(ds, port, addr, vid,
|
||||
ret = _mv88e6xxx_port_fdb_load(ds, port, fdb->addr, fdb->vid,
|
||||
GLOBAL_ATU_DATA_STATE_UNUSED);
|
||||
mutex_unlock(&ps->smi_mutex);
|
||||
|
||||
|
@ -1998,16 +1791,11 @@ int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port,
|
|||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
struct mv88e6xxx_atu_entry next;
|
||||
u16 fid;
|
||||
u16 fid = *vid; /* We use one FID per VLAN */
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ps->smi_mutex);
|
||||
|
||||
ret = _mv88e6xxx_port_vid_to_fid(ds, port, *vid);
|
||||
if (ret < 0)
|
||||
goto unlock;
|
||||
fid = ret;
|
||||
|
||||
do {
|
||||
if (is_broadcast_ether_addr(addr)) {
|
||||
struct mv88e6xxx_vtu_stu_entry vtu;
|
||||
|
@ -2058,7 +1846,7 @@ static void mv88e6xxx_bridge_work(struct work_struct *work)
|
|||
static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
|
||||
{
|
||||
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
|
||||
int ret, fid;
|
||||
int ret;
|
||||
u16 reg;
|
||||
|
||||
mutex_lock(&ps->smi_mutex);
|
||||
|
@ -2184,7 +1972,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
|
|||
reg |= PORT_CONTROL_2_FORWARD_UNKNOWN;
|
||||
}
|
||||
|
||||
reg |= PORT_CONTROL_2_8021Q_FALLBACK;
|
||||
reg |= PORT_CONTROL_2_8021Q_SECURE;
|
||||
|
||||
if (reg) {
|
||||
ret = _mv88e6xxx_reg_write(ds, REG_PORT(port),
|
||||
|
@ -2277,19 +2065,11 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
|
|||
if (ret)
|
||||
goto abort;
|
||||
|
||||
/* Port based VLAN map: give each port its own address
|
||||
* database, allow the CPU port to talk to each of the 'real'
|
||||
* ports, and allow each of the 'real' ports to only talk to
|
||||
* the upstream port.
|
||||
/* Port based VLAN map: do not give each port its own address
|
||||
* database, and allow every port to egress frames on all other ports.
|
||||
*/
|
||||
fid = port + 1;
|
||||
ps->fid[port] = fid;
|
||||
set_bit(fid, ps->fid_bitmap);
|
||||
|
||||
if (!dsa_is_cpu_port(ds, port))
|
||||
ps->bridge_mask[fid] = 1 << port;
|
||||
|
||||
ret = _mv88e6xxx_update_port_config(ds, port);
|
||||
reg = BIT(ps->num_ports) - 1; /* all ports */
|
||||
ret = _mv88e6xxx_port_vlan_map_set(ds, port, reg & ~port);
|
||||
if (ret)
|
||||
goto abort;
|
||||
|
||||
|
|
|
@ -402,12 +402,6 @@ struct mv88e6xxx_priv_state {
|
|||
int id; /* switch product id */
|
||||
int num_ports; /* number of switch ports */
|
||||
|
||||
/* hw bridging */
|
||||
|
||||
DECLARE_BITMAP(fid_bitmap, VLAN_N_VID); /* FIDs 1 to 4095 available */
|
||||
u16 fid[DSA_MAX_PORTS]; /* per (non-bridged) port FID */
|
||||
u16 bridge_mask[DSA_MAX_PORTS]; /* br groups (indexed by FID) */
|
||||
|
||||
unsigned long port_state_update_mask;
|
||||
u8 port_state[DSA_MAX_PORTS];
|
||||
|
||||
|
@ -442,7 +436,6 @@ void mv88e6xxx_ppu_state_init(struct dsa_switch *ds);
|
|||
int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum);
|
||||
int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
|
||||
int regnum, u16 val);
|
||||
void mv88e6xxx_poll_link(struct dsa_switch *ds);
|
||||
void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, uint8_t *data);
|
||||
void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
|
||||
uint64_t *data);
|
||||
|
@ -465,8 +458,6 @@ int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr, int regnum,
|
|||
int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e);
|
||||
int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
|
||||
struct phy_device *phydev, struct ethtool_eee *e);
|
||||
int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask);
|
||||
int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask);
|
||||
int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state);
|
||||
int mv88e6xxx_port_pvid_get(struct dsa_switch *ds, int port, u16 *vid);
|
||||
int mv88e6xxx_port_pvid_set(struct dsa_switch *ds, int port, u16 vid);
|
||||
|
@ -475,10 +466,14 @@ int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, u16 vid,
|
|||
int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid);
|
||||
int mv88e6xxx_vlan_getnext(struct dsa_switch *ds, u16 *vid,
|
||||
unsigned long *ports, unsigned long *untagged);
|
||||
int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port,
|
||||
const struct switchdev_obj_port_fdb *fdb,
|
||||
struct switchdev_trans *trans);
|
||||
int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
|
||||
const unsigned char *addr, u16 vid);
|
||||
const struct switchdev_obj_port_fdb *fdb,
|
||||
struct switchdev_trans *trans);
|
||||
int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
|
||||
const unsigned char *addr, u16 vid);
|
||||
const struct switchdev_obj_port_fdb *fdb);
|
||||
int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port,
|
||||
unsigned char *addr, u16 *vid, bool *is_static);
|
||||
int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg);
|
||||
|
|
|
@ -1141,8 +1141,6 @@ static void greth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *in
|
|||
strlcpy(info->version, "revision: 1.0", sizeof(info->version));
|
||||
strlcpy(info->bus_info, greth->dev->bus->name, sizeof(info->bus_info));
|
||||
strlcpy(info->fw_version, "N/A", sizeof(info->fw_version));
|
||||
info->eedump_len = 0;
|
||||
info->regdump_len = sizeof(struct greth_regs);
|
||||
}
|
||||
|
||||
static void greth_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
|
||||
|
|
|
@ -714,7 +714,6 @@ au1000_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
|
|||
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
|
||||
snprintf(info->bus_info, sizeof(info->bus_info), "%s %d", DRV_NAME,
|
||||
aup->mac_id);
|
||||
info->regdump_len = 0;
|
||||
}
|
||||
|
||||
static void au1000_set_msglevel(struct net_device *dev, u32 value)
|
||||
|
|
|
@ -1940,84 +1940,31 @@ static void xgbe_config_mtl_mode(struct xgbe_prv_data *pdata)
|
|||
static unsigned int xgbe_calculate_per_queue_fifo(unsigned int fifo_size,
|
||||
unsigned int queue_count)
|
||||
{
|
||||
unsigned int q_fifo_size = 0;
|
||||
enum xgbe_mtl_fifo_size p_fifo = XGMAC_MTL_FIFO_SIZE_256;
|
||||
unsigned int q_fifo_size;
|
||||
unsigned int p_fifo;
|
||||
|
||||
/* Calculate Tx/Rx fifo share per queue */
|
||||
switch (fifo_size) {
|
||||
case 0:
|
||||
q_fifo_size = XGBE_FIFO_SIZE_B(128);
|
||||
break;
|
||||
case 1:
|
||||
q_fifo_size = XGBE_FIFO_SIZE_B(256);
|
||||
break;
|
||||
case 2:
|
||||
q_fifo_size = XGBE_FIFO_SIZE_B(512);
|
||||
break;
|
||||
case 3:
|
||||
q_fifo_size = XGBE_FIFO_SIZE_KB(1);
|
||||
break;
|
||||
case 4:
|
||||
q_fifo_size = XGBE_FIFO_SIZE_KB(2);
|
||||
break;
|
||||
case 5:
|
||||
q_fifo_size = XGBE_FIFO_SIZE_KB(4);
|
||||
break;
|
||||
case 6:
|
||||
q_fifo_size = XGBE_FIFO_SIZE_KB(8);
|
||||
break;
|
||||
case 7:
|
||||
q_fifo_size = XGBE_FIFO_SIZE_KB(16);
|
||||
break;
|
||||
case 8:
|
||||
q_fifo_size = XGBE_FIFO_SIZE_KB(32);
|
||||
break;
|
||||
case 9:
|
||||
q_fifo_size = XGBE_FIFO_SIZE_KB(64);
|
||||
break;
|
||||
case 10:
|
||||
q_fifo_size = XGBE_FIFO_SIZE_KB(128);
|
||||
break;
|
||||
case 11:
|
||||
q_fifo_size = XGBE_FIFO_SIZE_KB(256);
|
||||
break;
|
||||
}
|
||||
/* Calculate the configured fifo size */
|
||||
q_fifo_size = 1 << (fifo_size + 7);
|
||||
|
||||
/* The configured value is not the actual amount of fifo RAM */
|
||||
/* The configured value may not be the actual amount of fifo RAM */
|
||||
q_fifo_size = min_t(unsigned int, XGBE_FIFO_MAX, q_fifo_size);
|
||||
|
||||
q_fifo_size = q_fifo_size / queue_count;
|
||||
|
||||
/* Set the queue fifo size programmable value */
|
||||
if (q_fifo_size >= XGBE_FIFO_SIZE_KB(256))
|
||||
p_fifo = XGMAC_MTL_FIFO_SIZE_256K;
|
||||
else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(128))
|
||||
p_fifo = XGMAC_MTL_FIFO_SIZE_128K;
|
||||
else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(64))
|
||||
p_fifo = XGMAC_MTL_FIFO_SIZE_64K;
|
||||
else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(32))
|
||||
p_fifo = XGMAC_MTL_FIFO_SIZE_32K;
|
||||
else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(16))
|
||||
p_fifo = XGMAC_MTL_FIFO_SIZE_16K;
|
||||
else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(8))
|
||||
p_fifo = XGMAC_MTL_FIFO_SIZE_8K;
|
||||
else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(4))
|
||||
p_fifo = XGMAC_MTL_FIFO_SIZE_4K;
|
||||
else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(2))
|
||||
p_fifo = XGMAC_MTL_FIFO_SIZE_2K;
|
||||
else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(1))
|
||||
p_fifo = XGMAC_MTL_FIFO_SIZE_1K;
|
||||
else if (q_fifo_size >= XGBE_FIFO_SIZE_B(512))
|
||||
p_fifo = XGMAC_MTL_FIFO_SIZE_512;
|
||||
else if (q_fifo_size >= XGBE_FIFO_SIZE_B(256))
|
||||
p_fifo = XGMAC_MTL_FIFO_SIZE_256;
|
||||
/* Each increment in the queue fifo size represents 256 bytes of
|
||||
* fifo, with 0 representing 256 bytes. Distribute the fifo equally
|
||||
* between the queues.
|
||||
*/
|
||||
p_fifo = q_fifo_size / 256;
|
||||
if (p_fifo)
|
||||
p_fifo--;
|
||||
|
||||
return p_fifo;
|
||||
}
|
||||
|
||||
static void xgbe_config_tx_fifo_size(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
enum xgbe_mtl_fifo_size fifo_size;
|
||||
unsigned int fifo_size;
|
||||
unsigned int i;
|
||||
|
||||
fifo_size = xgbe_calculate_per_queue_fifo(pdata->hw_feat.tx_fifo_size,
|
||||
|
@ -2033,7 +1980,7 @@ static void xgbe_config_tx_fifo_size(struct xgbe_prv_data *pdata)
|
|||
|
||||
static void xgbe_config_rx_fifo_size(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
enum xgbe_mtl_fifo_size fifo_size;
|
||||
unsigned int fifo_size;
|
||||
unsigned int i;
|
||||
|
||||
fifo_size = xgbe_calculate_per_queue_fifo(pdata->hw_feat.rx_fifo_size,
|
||||
|
@ -2224,7 +2171,7 @@ static u64 xgbe_mmc_read(struct xgbe_prv_data *pdata, unsigned int reg_lo)
|
|||
|
||||
default:
|
||||
read_hi = false;
|
||||
};
|
||||
}
|
||||
|
||||
val = XGMAC_IOREAD(pdata, reg_lo);
|
||||
|
||||
|
|
|
@ -360,6 +360,9 @@ static irqreturn_t xgbe_isr(int irq, void *data)
|
|||
}
|
||||
}
|
||||
|
||||
if (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, RBU))
|
||||
pdata->ext_stats.rx_buffer_unavailable++;
|
||||
|
||||
/* Restart the device on a Fatal Bus Error */
|
||||
if (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, FBE))
|
||||
schedule_work(&pdata->restart_work);
|
||||
|
@ -384,7 +387,8 @@ static irqreturn_t xgbe_isr(int irq, void *data)
|
|||
/* Read Tx Timestamp to clear interrupt */
|
||||
pdata->tx_tstamp =
|
||||
hw_if->get_tx_tstamp(pdata);
|
||||
schedule_work(&pdata->tx_tstamp_work);
|
||||
queue_work(pdata->dev_workqueue,
|
||||
&pdata->tx_tstamp_work);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -450,7 +454,7 @@ static void xgbe_service_timer(unsigned long data)
|
|||
{
|
||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
|
||||
|
||||
schedule_work(&pdata->service_work);
|
||||
queue_work(pdata->dev_workqueue, &pdata->service_work);
|
||||
|
||||
mod_timer(&pdata->service_timer, jiffies + HZ);
|
||||
}
|
||||
|
@ -891,7 +895,7 @@ static int xgbe_start(struct xgbe_prv_data *pdata)
|
|||
netif_tx_start_all_queues(netdev);
|
||||
|
||||
xgbe_start_timers(pdata);
|
||||
schedule_work(&pdata->service_work);
|
||||
queue_work(pdata->dev_workqueue, &pdata->service_work);
|
||||
|
||||
DBGPR("<--xgbe_start\n");
|
||||
|
||||
|
|
|
@ -179,6 +179,7 @@ static const struct xgbe_stats xgbe_gstring_stats[] = {
|
|||
XGMAC_MMC_STAT("rx_watchdog_errors", rxwatchdogerror),
|
||||
XGMAC_MMC_STAT("rx_pause_frames", rxpauseframes),
|
||||
XGMAC_EXT_STAT("rx_split_header_packets", rx_split_header_packets),
|
||||
XGMAC_EXT_STAT("rx_buffer_unavailable", rx_buffer_unavailable),
|
||||
};
|
||||
|
||||
#define XGBE_STATS_COUNT ARRAY_SIZE(xgbe_gstring_stats)
|
||||
|
@ -187,8 +188,6 @@ static void xgbe_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
|
|||
{
|
||||
int i;
|
||||
|
||||
DBGPR("-->%s\n", __func__);
|
||||
|
||||
switch (stringset) {
|
||||
case ETH_SS_STATS:
|
||||
for (i = 0; i < XGBE_STATS_COUNT; i++) {
|
||||
|
@ -198,8 +197,6 @@ static void xgbe_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
DBGPR("<--%s\n", __func__);
|
||||
}
|
||||
|
||||
static void xgbe_get_ethtool_stats(struct net_device *netdev,
|
||||
|
@ -209,23 +206,17 @@ static void xgbe_get_ethtool_stats(struct net_device *netdev,
|
|||
u8 *stat;
|
||||
int i;
|
||||
|
||||
DBGPR("-->%s\n", __func__);
|
||||
|
||||
pdata->hw_if.read_mmc_stats(pdata);
|
||||
for (i = 0; i < XGBE_STATS_COUNT; i++) {
|
||||
stat = (u8 *)pdata + xgbe_gstring_stats[i].stat_offset;
|
||||
*data++ = *(u64 *)stat;
|
||||
}
|
||||
|
||||
DBGPR("<--%s\n", __func__);
|
||||
}
|
||||
|
||||
static int xgbe_get_sset_count(struct net_device *netdev, int stringset)
|
||||
{
|
||||
int ret;
|
||||
|
||||
DBGPR("-->%s\n", __func__);
|
||||
|
||||
switch (stringset) {
|
||||
case ETH_SS_STATS:
|
||||
ret = XGBE_STATS_COUNT;
|
||||
|
@ -235,8 +226,6 @@ static int xgbe_get_sset_count(struct net_device *netdev, int stringset)
|
|||
ret = -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
DBGPR("<--%s\n", __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -245,13 +234,9 @@ static void xgbe_get_pauseparam(struct net_device *netdev,
|
|||
{
|
||||
struct xgbe_prv_data *pdata = netdev_priv(netdev);
|
||||
|
||||
DBGPR("-->xgbe_get_pauseparam\n");
|
||||
|
||||
pause->autoneg = pdata->phy.pause_autoneg;
|
||||
pause->tx_pause = pdata->phy.tx_pause;
|
||||
pause->rx_pause = pdata->phy.rx_pause;
|
||||
|
||||
DBGPR("<--xgbe_get_pauseparam\n");
|
||||
}
|
||||
|
||||
static int xgbe_set_pauseparam(struct net_device *netdev,
|
||||
|
@ -260,13 +245,11 @@ static int xgbe_set_pauseparam(struct net_device *netdev,
|
|||
struct xgbe_prv_data *pdata = netdev_priv(netdev);
|
||||
int ret = 0;
|
||||
|
||||
DBGPR("-->xgbe_set_pauseparam\n");
|
||||
|
||||
DBGPR(" autoneg = %d, tx_pause = %d, rx_pause = %d\n",
|
||||
pause->autoneg, pause->tx_pause, pause->rx_pause);
|
||||
|
||||
if (pause->autoneg && (pdata->phy.autoneg != AUTONEG_ENABLE))
|
||||
if (pause->autoneg && (pdata->phy.autoneg != AUTONEG_ENABLE)) {
|
||||
netdev_err(netdev,
|
||||
"autoneg disabled, pause autoneg not avialable\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pdata->phy.pause_autoneg = pause->autoneg;
|
||||
pdata->phy.tx_pause = pause->tx_pause;
|
||||
|
@ -286,8 +269,6 @@ static int xgbe_set_pauseparam(struct net_device *netdev,
|
|||
if (netif_running(netdev))
|
||||
ret = pdata->phy_if.phy_config_aneg(pdata);
|
||||
|
||||
DBGPR("<--xgbe_set_pauseparam\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -296,8 +277,6 @@ static int xgbe_get_settings(struct net_device *netdev,
|
|||
{
|
||||
struct xgbe_prv_data *pdata = netdev_priv(netdev);
|
||||
|
||||
DBGPR("-->xgbe_get_settings\n");
|
||||
|
||||
cmd->phy_address = pdata->phy.address;
|
||||
|
||||
cmd->supported = pdata->phy.supported;
|
||||
|
@ -311,8 +290,6 @@ static int xgbe_get_settings(struct net_device *netdev,
|
|||
cmd->port = PORT_NONE;
|
||||
cmd->transceiver = XCVR_INTERNAL;
|
||||
|
||||
DBGPR("<--xgbe_get_settings\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -323,16 +300,20 @@ static int xgbe_set_settings(struct net_device *netdev,
|
|||
u32 speed;
|
||||
int ret;
|
||||
|
||||
DBGPR("-->xgbe_set_settings\n");
|
||||
|
||||
speed = ethtool_cmd_speed(cmd);
|
||||
|
||||
if (cmd->phy_address != pdata->phy.address)
|
||||
if (cmd->phy_address != pdata->phy.address) {
|
||||
netdev_err(netdev, "invalid phy address %hhu\n",
|
||||
cmd->phy_address);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((cmd->autoneg != AUTONEG_ENABLE) &&
|
||||
(cmd->autoneg != AUTONEG_DISABLE))
|
||||
(cmd->autoneg != AUTONEG_DISABLE)) {
|
||||
netdev_err(netdev, "unsupported autoneg %hhu\n",
|
||||
cmd->autoneg);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cmd->autoneg == AUTONEG_DISABLE) {
|
||||
switch (speed) {
|
||||
|
@ -341,16 +322,27 @@ static int xgbe_set_settings(struct net_device *netdev,
|
|||
case SPEED_1000:
|
||||
break;
|
||||
default:
|
||||
netdev_err(netdev, "unsupported speed %u\n", speed);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cmd->duplex != DUPLEX_FULL)
|
||||
if (cmd->duplex != DUPLEX_FULL) {
|
||||
netdev_err(netdev, "unsupported duplex %hhu\n",
|
||||
cmd->duplex);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
netif_dbg(pdata, link, netdev,
|
||||
"requested advertisement %#x, phy supported %#x\n",
|
||||
cmd->advertising, pdata->phy.supported);
|
||||
|
||||
cmd->advertising &= pdata->phy.supported;
|
||||
if ((cmd->autoneg == AUTONEG_ENABLE) && !cmd->advertising)
|
||||
if ((cmd->autoneg == AUTONEG_ENABLE) && !cmd->advertising) {
|
||||
netdev_err(netdev,
|
||||
"unsupported requested advertisement\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
pdata->phy.autoneg = cmd->autoneg;
|
||||
|
@ -366,8 +358,6 @@ static int xgbe_set_settings(struct net_device *netdev,
|
|||
if (netif_running(netdev))
|
||||
ret = pdata->phy_if.phy_config_aneg(pdata);
|
||||
|
||||
DBGPR("<--xgbe_set_settings\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -385,7 +375,20 @@ static void xgbe_get_drvinfo(struct net_device *netdev,
|
|||
XGMAC_GET_BITS(hw_feat->version, MAC_VR, USERVER),
|
||||
XGMAC_GET_BITS(hw_feat->version, MAC_VR, DEVID),
|
||||
XGMAC_GET_BITS(hw_feat->version, MAC_VR, SNPSVER));
|
||||
drvinfo->n_stats = XGBE_STATS_COUNT;
|
||||
}
|
||||
|
||||
static u32 xgbe_get_msglevel(struct net_device *netdev)
|
||||
{
|
||||
struct xgbe_prv_data *pdata = netdev_priv(netdev);
|
||||
|
||||
return pdata->msg_enable;
|
||||
}
|
||||
|
||||
static void xgbe_set_msglevel(struct net_device *netdev, u32 msglevel)
|
||||
{
|
||||
struct xgbe_prv_data *pdata = netdev_priv(netdev);
|
||||
|
||||
pdata->msg_enable = msglevel;
|
||||
}
|
||||
|
||||
static int xgbe_get_coalesce(struct net_device *netdev,
|
||||
|
@ -393,8 +396,6 @@ static int xgbe_get_coalesce(struct net_device *netdev,
|
|||
{
|
||||
struct xgbe_prv_data *pdata = netdev_priv(netdev);
|
||||
|
||||
DBGPR("-->xgbe_get_coalesce\n");
|
||||
|
||||
memset(ec, 0, sizeof(struct ethtool_coalesce));
|
||||
|
||||
ec->rx_coalesce_usecs = pdata->rx_usecs;
|
||||
|
@ -402,8 +403,6 @@ static int xgbe_get_coalesce(struct net_device *netdev,
|
|||
|
||||
ec->tx_max_coalesced_frames = pdata->tx_frames;
|
||||
|
||||
DBGPR("<--xgbe_get_coalesce\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -415,8 +414,6 @@ static int xgbe_set_coalesce(struct net_device *netdev,
|
|||
unsigned int rx_frames, rx_riwt, rx_usecs;
|
||||
unsigned int tx_frames;
|
||||
|
||||
DBGPR("-->xgbe_set_coalesce\n");
|
||||
|
||||
/* Check for not supported parameters */
|
||||
if ((ec->rx_coalesce_usecs_irq) ||
|
||||
(ec->rx_max_coalesced_frames_irq) ||
|
||||
|
@ -436,8 +433,10 @@ static int xgbe_set_coalesce(struct net_device *netdev,
|
|||
(ec->rx_max_coalesced_frames_high) ||
|
||||
(ec->tx_coalesce_usecs_high) ||
|
||||
(ec->tx_max_coalesced_frames_high) ||
|
||||
(ec->rate_sample_interval))
|
||||
(ec->rate_sample_interval)) {
|
||||
netdev_err(netdev, "unsupported coalescing parameter\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
rx_riwt = hw_if->usec_to_riwt(pdata, ec->rx_coalesce_usecs);
|
||||
rx_usecs = ec->rx_coalesce_usecs;
|
||||
|
@ -449,12 +448,12 @@ static int xgbe_set_coalesce(struct net_device *netdev,
|
|||
|
||||
/* Check the bounds of values for Rx */
|
||||
if (rx_riwt > XGMAC_MAX_DMA_RIWT) {
|
||||
netdev_alert(netdev, "rx-usec is limited to %d usecs\n",
|
||||
netdev_err(netdev, "rx-usec is limited to %d usecs\n",
|
||||
hw_if->riwt_to_usec(pdata, XGMAC_MAX_DMA_RIWT));
|
||||
return -EINVAL;
|
||||
}
|
||||
if (rx_frames > pdata->rx_desc_count) {
|
||||
netdev_alert(netdev, "rx-frames is limited to %d frames\n",
|
||||
netdev_err(netdev, "rx-frames is limited to %d frames\n",
|
||||
pdata->rx_desc_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -463,7 +462,7 @@ static int xgbe_set_coalesce(struct net_device *netdev,
|
|||
|
||||
/* Check the bounds of values for Tx */
|
||||
if (tx_frames > pdata->tx_desc_count) {
|
||||
netdev_alert(netdev, "tx-frames is limited to %d frames\n",
|
||||
netdev_err(netdev, "tx-frames is limited to %d frames\n",
|
||||
pdata->tx_desc_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -476,8 +475,6 @@ static int xgbe_set_coalesce(struct net_device *netdev,
|
|||
pdata->tx_frames = tx_frames;
|
||||
hw_if->config_tx_coalesce(pdata);
|
||||
|
||||
DBGPR("<--xgbe_set_coalesce\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -539,8 +536,10 @@ static int xgbe_set_rxfh(struct net_device *netdev, const u32 *indir,
|
|||
struct xgbe_hw_if *hw_if = &pdata->hw_if;
|
||||
unsigned int ret;
|
||||
|
||||
if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
|
||||
if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) {
|
||||
netdev_err(netdev, "unsupported hash function\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (indir) {
|
||||
ret = hw_if->set_rss_lookup_table(pdata, indir);
|
||||
|
@ -594,6 +593,8 @@ static const struct ethtool_ops xgbe_ethtool_ops = {
|
|||
.get_settings = xgbe_get_settings,
|
||||
.set_settings = xgbe_set_settings,
|
||||
.get_drvinfo = xgbe_get_drvinfo,
|
||||
.get_msglevel = xgbe_get_msglevel,
|
||||
.set_msglevel = xgbe_set_msglevel,
|
||||
.get_link = ethtool_op_get_link,
|
||||
.get_coalesce = xgbe_get_coalesce,
|
||||
.set_coalesce = xgbe_set_coalesce,
|
||||
|
|
|
@ -371,7 +371,7 @@ static int xgbe_probe(struct platform_device *pdev)
|
|||
set_bit(XGBE_DOWN, &pdata->dev_state);
|
||||
|
||||
/* Check if we should use ACPI or DT */
|
||||
pdata->use_acpi = (!pdata->adev || acpi_disabled) ? 0 : 1;
|
||||
pdata->use_acpi = dev->of_node ? 0 : 1;
|
||||
|
||||
phy_pdev = xgbe_get_phy_pdev(pdata);
|
||||
if (!phy_pdev) {
|
||||
|
|
|
@ -1115,7 +1115,6 @@ static void xgbe_phy_status(struct xgbe_prv_data *pdata)
|
|||
unsigned int reg, link_aneg;
|
||||
|
||||
if (test_bit(XGBE_LINK_ERR, &pdata->dev_state)) {
|
||||
if (test_and_clear_bit(XGBE_LINK, &pdata->dev_state))
|
||||
netif_carrier_off(pdata->netdev);
|
||||
|
||||
pdata->phy.link = 0;
|
||||
|
@ -1142,10 +1141,7 @@ static void xgbe_phy_status(struct xgbe_prv_data *pdata)
|
|||
if (test_bit(XGBE_LINK_INIT, &pdata->dev_state))
|
||||
clear_bit(XGBE_LINK_INIT, &pdata->dev_state);
|
||||
|
||||
if (!test_bit(XGBE_LINK, &pdata->dev_state)) {
|
||||
set_bit(XGBE_LINK, &pdata->dev_state);
|
||||
netif_carrier_on(pdata->netdev);
|
||||
}
|
||||
} else {
|
||||
if (test_bit(XGBE_LINK_INIT, &pdata->dev_state)) {
|
||||
xgbe_check_link_timeout(pdata);
|
||||
|
@ -1156,11 +1152,8 @@ static void xgbe_phy_status(struct xgbe_prv_data *pdata)
|
|||
|
||||
xgbe_phy_status_aneg(pdata);
|
||||
|
||||
if (test_bit(XGBE_LINK, &pdata->dev_state)) {
|
||||
clear_bit(XGBE_LINK, &pdata->dev_state);
|
||||
netif_carrier_off(pdata->netdev);
|
||||
}
|
||||
}
|
||||
|
||||
adjust_link:
|
||||
xgbe_phy_adjust_link(pdata);
|
||||
|
@ -1179,7 +1172,6 @@ static void xgbe_phy_stop(struct xgbe_prv_data *pdata)
|
|||
devm_free_irq(pdata->dev, pdata->an_irq, pdata);
|
||||
|
||||
pdata->phy.link = 0;
|
||||
if (test_and_clear_bit(XGBE_LINK, &pdata->dev_state))
|
||||
netif_carrier_off(pdata->netdev);
|
||||
|
||||
xgbe_phy_adjust_link(pdata);
|
||||
|
|
|
@ -209,8 +209,6 @@
|
|||
#define XGMAC_IOCTL_CONTEXT 2
|
||||
|
||||
#define XGBE_FIFO_MAX 81920
|
||||
#define XGBE_FIFO_SIZE_B(x) (x)
|
||||
#define XGBE_FIFO_SIZE_KB(x) (x * 1024)
|
||||
|
||||
#define XGBE_TC_MIN_QUANTUM 10
|
||||
|
||||
|
@ -461,7 +459,6 @@ struct xgbe_channel {
|
|||
|
||||
enum xgbe_state {
|
||||
XGBE_DOWN,
|
||||
XGBE_LINK,
|
||||
XGBE_LINK_INIT,
|
||||
XGBE_LINK_ERR,
|
||||
};
|
||||
|
@ -483,20 +480,6 @@ enum xgbe_int_state {
|
|||
XGMAC_INT_STATE_RESTORE,
|
||||
};
|
||||
|
||||
enum xgbe_mtl_fifo_size {
|
||||
XGMAC_MTL_FIFO_SIZE_256 = 0x00,
|
||||
XGMAC_MTL_FIFO_SIZE_512 = 0x01,
|
||||
XGMAC_MTL_FIFO_SIZE_1K = 0x03,
|
||||
XGMAC_MTL_FIFO_SIZE_2K = 0x07,
|
||||
XGMAC_MTL_FIFO_SIZE_4K = 0x0f,
|
||||
XGMAC_MTL_FIFO_SIZE_8K = 0x1f,
|
||||
XGMAC_MTL_FIFO_SIZE_16K = 0x3f,
|
||||
XGMAC_MTL_FIFO_SIZE_32K = 0x7f,
|
||||
XGMAC_MTL_FIFO_SIZE_64K = 0xff,
|
||||
XGMAC_MTL_FIFO_SIZE_128K = 0x1ff,
|
||||
XGMAC_MTL_FIFO_SIZE_256K = 0x3ff,
|
||||
};
|
||||
|
||||
enum xgbe_speed {
|
||||
XGBE_SPEED_1000 = 0,
|
||||
XGBE_SPEED_2500,
|
||||
|
@ -598,6 +581,7 @@ struct xgbe_mmc_stats {
|
|||
struct xgbe_ext_stats {
|
||||
u64 tx_tso_packets;
|
||||
u64 rx_split_header_packets;
|
||||
u64 rx_buffer_unavailable;
|
||||
};
|
||||
|
||||
struct xgbe_hw_if {
|
||||
|
|
|
@ -233,10 +233,6 @@ static void atl1c_get_drvinfo(struct net_device *netdev,
|
|||
sizeof(drvinfo->version));
|
||||
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
|
||||
sizeof(drvinfo->bus_info));
|
||||
drvinfo->n_stats = 0;
|
||||
drvinfo->testinfo_len = 0;
|
||||
drvinfo->regdump_len = atl1c_get_regs_len(netdev);
|
||||
drvinfo->eedump_len = atl1c_get_eeprom_len(netdev);
|
||||
}
|
||||
|
||||
static void atl1c_get_wol(struct net_device *netdev,
|
||||
|
|
|
@ -316,10 +316,6 @@ static void atl1e_get_drvinfo(struct net_device *netdev,
|
|||
strlcpy(drvinfo->fw_version, "L1e", sizeof(drvinfo->fw_version));
|
||||
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
|
||||
sizeof(drvinfo->bus_info));
|
||||
drvinfo->n_stats = 0;
|
||||
drvinfo->testinfo_len = 0;
|
||||
drvinfo->regdump_len = atl1e_get_regs_len(netdev);
|
||||
drvinfo->eedump_len = atl1e_get_eeprom_len(netdev);
|
||||
}
|
||||
|
||||
static void atl1e_get_wol(struct net_device *netdev,
|
||||
|
|
|
@ -3388,7 +3388,6 @@ static void atl1_get_drvinfo(struct net_device *netdev,
|
|||
sizeof(drvinfo->version));
|
||||
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
|
||||
sizeof(drvinfo->bus_info));
|
||||
drvinfo->eedump_len = ATL1_EEDUMP_LEN;
|
||||
}
|
||||
|
||||
static void atl1_get_wol(struct net_device *netdev,
|
||||
|
|
|
@ -2030,10 +2030,6 @@ static void atl2_get_drvinfo(struct net_device *netdev,
|
|||
strlcpy(drvinfo->fw_version, "L2", sizeof(drvinfo->fw_version));
|
||||
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
|
||||
sizeof(drvinfo->bus_info));
|
||||
drvinfo->n_stats = 0;
|
||||
drvinfo->testinfo_len = 0;
|
||||
drvinfo->regdump_len = atl2_get_regs_len(netdev);
|
||||
drvinfo->eedump_len = atl2_get_eeprom_len(netdev);
|
||||
}
|
||||
|
||||
static void atl2_get_wol(struct net_device *netdev,
|
||||
|
|
|
@ -1333,7 +1333,6 @@ static void bcm_enet_get_drvinfo(struct net_device *netdev,
|
|||
sizeof(drvinfo->version));
|
||||
strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
|
||||
strlcpy(drvinfo->bus_info, "bcm63xx", sizeof(drvinfo->bus_info));
|
||||
drvinfo->n_stats = BCM_ENET_STATS_LEN;
|
||||
}
|
||||
|
||||
static int bcm_enet_get_sset_count(struct net_device *netdev,
|
||||
|
@ -2597,7 +2596,6 @@ static void bcm_enetsw_get_drvinfo(struct net_device *netdev,
|
|||
strncpy(drvinfo->version, bcm_enet_driver_version, 32);
|
||||
strncpy(drvinfo->fw_version, "N/A", 32);
|
||||
strncpy(drvinfo->bus_info, "bcm63xx", 32);
|
||||
drvinfo->n_stats = BCM_ENETSW_STATS_LEN;
|
||||
}
|
||||
|
||||
static void bcm_enetsw_get_ethtool_stats(struct net_device *netdev,
|
||||
|
|
|
@ -287,7 +287,6 @@ static void bcm_sysport_get_drvinfo(struct net_device *dev,
|
|||
strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
|
||||
strlcpy(info->version, "0.1", sizeof(info->version));
|
||||
strlcpy(info->bus_info, "platform", sizeof(info->bus_info));
|
||||
info->n_stats = BCM_SYSPORT_STATS_LEN;
|
||||
}
|
||||
|
||||
static u32 bcm_sysport_get_msglvl(struct net_device *dev)
|
||||
|
|
|
@ -812,6 +812,46 @@ bnx2_alloc_rx_mem(struct bnx2 *bp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
bnx2_free_stats_blk(struct net_device *dev)
|
||||
{
|
||||
struct bnx2 *bp = netdev_priv(dev);
|
||||
|
||||
if (bp->status_blk) {
|
||||
dma_free_coherent(&bp->pdev->dev, bp->status_stats_size,
|
||||
bp->status_blk,
|
||||
bp->status_blk_mapping);
|
||||
bp->status_blk = NULL;
|
||||
bp->stats_blk = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
bnx2_alloc_stats_blk(struct net_device *dev)
|
||||
{
|
||||
int status_blk_size;
|
||||
void *status_blk;
|
||||
struct bnx2 *bp = netdev_priv(dev);
|
||||
|
||||
/* Combine status and statistics blocks into one allocation. */
|
||||
status_blk_size = L1_CACHE_ALIGN(sizeof(struct status_block));
|
||||
if (bp->flags & BNX2_FLAG_MSIX_CAP)
|
||||
status_blk_size = L1_CACHE_ALIGN(BNX2_MAX_MSIX_HW_VEC *
|
||||
BNX2_SBLK_MSIX_ALIGN_SIZE);
|
||||
bp->status_stats_size = status_blk_size +
|
||||
sizeof(struct statistics_block);
|
||||
status_blk = dma_zalloc_coherent(&bp->pdev->dev, bp->status_stats_size,
|
||||
&bp->status_blk_mapping, GFP_KERNEL);
|
||||
if (status_blk == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
bp->status_blk = status_blk;
|
||||
bp->stats_blk = status_blk + status_blk_size;
|
||||
bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
bnx2_free_mem(struct bnx2 *bp)
|
||||
{
|
||||
|
@ -829,37 +869,19 @@ bnx2_free_mem(struct bnx2 *bp)
|
|||
bp->ctx_blk[i] = NULL;
|
||||
}
|
||||
}
|
||||
if (bnapi->status_blk.msi) {
|
||||
dma_free_coherent(&bp->pdev->dev, bp->status_stats_size,
|
||||
bnapi->status_blk.msi,
|
||||
bp->status_blk_mapping);
|
||||
|
||||
if (bnapi->status_blk.msi)
|
||||
bnapi->status_blk.msi = NULL;
|
||||
bp->stats_blk = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
bnx2_alloc_mem(struct bnx2 *bp)
|
||||
{
|
||||
int i, status_blk_size, err;
|
||||
int i, err;
|
||||
struct bnx2_napi *bnapi;
|
||||
void *status_blk;
|
||||
|
||||
/* Combine status and statistics blocks into one allocation. */
|
||||
status_blk_size = L1_CACHE_ALIGN(sizeof(struct status_block));
|
||||
if (bp->flags & BNX2_FLAG_MSIX_CAP)
|
||||
status_blk_size = L1_CACHE_ALIGN(BNX2_MAX_MSIX_HW_VEC *
|
||||
BNX2_SBLK_MSIX_ALIGN_SIZE);
|
||||
bp->status_stats_size = status_blk_size +
|
||||
sizeof(struct statistics_block);
|
||||
|
||||
status_blk = dma_zalloc_coherent(&bp->pdev->dev, bp->status_stats_size,
|
||||
&bp->status_blk_mapping, GFP_KERNEL);
|
||||
if (status_blk == NULL)
|
||||
goto alloc_mem_err;
|
||||
|
||||
bnapi = &bp->bnx2_napi[0];
|
||||
bnapi->status_blk.msi = status_blk;
|
||||
bnapi->status_blk.msi = bp->status_blk;
|
||||
bnapi->hw_tx_cons_ptr =
|
||||
&bnapi->status_blk.msi->status_tx_quick_consumer_index0;
|
||||
bnapi->hw_rx_cons_ptr =
|
||||
|
@ -870,7 +892,7 @@ bnx2_alloc_mem(struct bnx2 *bp)
|
|||
|
||||
bnapi = &bp->bnx2_napi[i];
|
||||
|
||||
sblk = (status_blk + BNX2_SBLK_MSIX_ALIGN_SIZE * i);
|
||||
sblk = (bp->status_blk + BNX2_SBLK_MSIX_ALIGN_SIZE * i);
|
||||
bnapi->status_blk.msix = sblk;
|
||||
bnapi->hw_tx_cons_ptr =
|
||||
&sblk->status_tx_quick_consumer_index;
|
||||
|
@ -880,10 +902,6 @@ bnx2_alloc_mem(struct bnx2 *bp)
|
|||
}
|
||||
}
|
||||
|
||||
bp->stats_blk = status_blk + status_blk_size;
|
||||
|
||||
bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size;
|
||||
|
||||
if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
|
||||
bp->ctx_pages = 0x2000 / BNX2_PAGE_SIZE;
|
||||
if (bp->ctx_pages == 0)
|
||||
|
@ -8330,6 +8348,11 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
|
|||
|
||||
bp->phy_addr = 1;
|
||||
|
||||
/* allocate stats_blk */
|
||||
rc = bnx2_alloc_stats_blk(dev);
|
||||
if (rc)
|
||||
goto err_out_unmap;
|
||||
|
||||
/* Disable WOL support if we are running on a SERDES chip. */
|
||||
if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
|
||||
bnx2_get_5709_media(bp);
|
||||
|
@ -8453,6 +8476,8 @@ err_out_disable:
|
|||
pci_disable_device(pdev);
|
||||
|
||||
err_out:
|
||||
kfree(bp->temp_stats_blk);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -8586,6 +8611,7 @@ error:
|
|||
pci_release_regions(pdev);
|
||||
pci_disable_device(pdev);
|
||||
err_free:
|
||||
bnx2_free_stats_blk(dev);
|
||||
free_netdev(dev);
|
||||
return rc;
|
||||
}
|
||||
|
@ -8603,6 +8629,7 @@ bnx2_remove_one(struct pci_dev *pdev)
|
|||
|
||||
pci_iounmap(bp->pdev, bp->regview);
|
||||
|
||||
bnx2_free_stats_blk(dev);
|
||||
kfree(bp->temp_stats_blk);
|
||||
|
||||
if (bp->flags & BNX2_FLAG_AER_ENABLED) {
|
||||
|
|
|
@ -6928,6 +6928,7 @@ struct bnx2 {
|
|||
|
||||
dma_addr_t status_blk_mapping;
|
||||
|
||||
void *status_blk;
|
||||
struct statistics_block *stats_blk;
|
||||
struct statistics_block *temp_stats_blk;
|
||||
dma_addr_t stats_blk_mapping;
|
||||
|
|
|
@ -1090,10 +1090,6 @@ static void bnx2x_get_drvinfo(struct net_device *dev,
|
|||
bnx2x_fill_fw_str(bp, info->fw_version, sizeof(info->fw_version));
|
||||
|
||||
strlcpy(info->bus_info, pci_name(bp->pdev), sizeof(info->bus_info));
|
||||
info->n_stats = BNX2X_NUM_STATS;
|
||||
info->testinfo_len = BNX2X_NUM_TESTS(bp);
|
||||
info->eedump_len = bp->common.flash_size;
|
||||
info->regdump_len = bnx2x_get_regs_len(dev);
|
||||
}
|
||||
|
||||
static void bnx2x_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
||||
|
|
|
@ -793,7 +793,6 @@ static void bcmgenet_get_drvinfo(struct net_device *dev,
|
|||
{
|
||||
strlcpy(info->driver, "bcmgenet", sizeof(info->driver));
|
||||
strlcpy(info->version, "v2.0", sizeof(info->version));
|
||||
info->n_stats = BCMGENET_STATS_LEN;
|
||||
}
|
||||
|
||||
static int bcmgenet_get_sset_count(struct net_device *dev, int string_set)
|
||||
|
|
|
@ -153,7 +153,6 @@ lio_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
|
|||
strncpy(drvinfo->fw_version, oct->fw_info.liquidio_firmware_version,
|
||||
ETHTOOL_FWVERS_LEN);
|
||||
strncpy(drvinfo->bus_info, pci_name(oct->pci_dev), 32);
|
||||
drvinfo->regdump_len = OCT_ETHTOOL_REGDUMP_LEN;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -940,6 +940,7 @@ static const char * const devlog_level_strings[] = {
|
|||
|
||||
static const char * const devlog_facility_strings[] = {
|
||||
[FW_DEVLOG_FACILITY_CORE] = "CORE",
|
||||
[FW_DEVLOG_FACILITY_CF] = "CF",
|
||||
[FW_DEVLOG_FACILITY_SCHED] = "SCHED",
|
||||
[FW_DEVLOG_FACILITY_TIMER] = "TIMER",
|
||||
[FW_DEVLOG_FACILITY_RES] = "RES",
|
||||
|
@ -1128,18 +1129,26 @@ static const struct file_operations devlog_fops = {
|
|||
static int mbox_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
static const char * const owner[] = { "none", "FW", "driver",
|
||||
"unknown" };
|
||||
"unknown", "<unread>" };
|
||||
|
||||
int i;
|
||||
unsigned int mbox = (uintptr_t)seq->private & 7;
|
||||
struct adapter *adap = seq->private - mbox;
|
||||
void __iomem *addr = adap->regs + PF_REG(mbox, CIM_PF_MAILBOX_DATA_A);
|
||||
unsigned int ctrl_reg = (is_t4(adap->params.chip)
|
||||
? CIM_PF_MAILBOX_CTRL_A
|
||||
: CIM_PF_MAILBOX_CTRL_SHADOW_COPY_A);
|
||||
|
||||
/* For T4 we don't have a shadow copy of the Mailbox Control register.
|
||||
* And since reading that real register causes a side effect of
|
||||
* granting ownership, we're best of simply not reading it at all.
|
||||
*/
|
||||
if (is_t4(adap->params.chip)) {
|
||||
i = 4; /* index of "<unread>" */
|
||||
} else {
|
||||
unsigned int ctrl_reg = CIM_PF_MAILBOX_CTRL_SHADOW_COPY_A;
|
||||
void __iomem *ctrl = adap->regs + PF_REG(mbox, ctrl_reg);
|
||||
|
||||
i = MBOWNER_G(readl(ctrl));
|
||||
}
|
||||
|
||||
seq_printf(seq, "mailbox owned by %s\n\n", owner[i]);
|
||||
|
||||
for (i = 0; i < MBOX_LEN; i += 8)
|
||||
|
|
|
@ -275,7 +275,7 @@ static void link_report(struct net_device *dev)
|
|||
else {
|
||||
static const char *fc[] = { "no", "Rx", "Tx", "Tx/Rx" };
|
||||
|
||||
const char *s = "10Mbps";
|
||||
const char *s;
|
||||
const struct port_info *p = netdev_priv(dev);
|
||||
|
||||
switch (p->link_cfg.speed) {
|
||||
|
@ -291,6 +291,10 @@ static void link_report(struct net_device *dev)
|
|||
case 40000:
|
||||
s = "40Gbps";
|
||||
break;
|
||||
default:
|
||||
pr_info("%s: unsupported speed: %d\n",
|
||||
dev->name, p->link_cfg.speed);
|
||||
return;
|
||||
}
|
||||
|
||||
netdev_info(dev, "link up, %s, full-duplex, %s PAUSE\n", s,
|
||||
|
@ -3694,7 +3698,7 @@ static int adap_init0(struct adapter *adap)
|
|||
t4_get_tp_version(adap, &adap->params.tp_vers);
|
||||
ret = t4_check_fw_version(adap);
|
||||
/* If firmware is too old (not supported by driver) force an update. */
|
||||
if (ret == -EFAULT)
|
||||
if (ret)
|
||||
state = DEV_STATE_UNINIT;
|
||||
if ((adap->flags & MASTER_PF) && state != DEV_STATE_INIT) {
|
||||
struct fw_info *fw_info;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -143,6 +143,7 @@ struct enic {
|
|||
struct vnic_dev *vdev;
|
||||
struct timer_list notify_timer;
|
||||
struct work_struct reset;
|
||||
struct work_struct tx_hang_reset;
|
||||
struct work_struct change_mtu_work;
|
||||
struct msix_entry msix_entry[ENIC_INTR_MAX];
|
||||
struct enic_msix_entry msix[ENIC_INTR_MAX];
|
||||
|
|
|
@ -178,13 +178,15 @@ static int enic_wq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void enic_log_q_error(struct enic *enic)
|
||||
static bool enic_log_q_error(struct enic *enic)
|
||||
{
|
||||
unsigned int i;
|
||||
u32 error_status;
|
||||
bool err = false;
|
||||
|
||||
for (i = 0; i < enic->wq_count; i++) {
|
||||
error_status = vnic_wq_error_status(&enic->wq[i]);
|
||||
err |= error_status;
|
||||
if (error_status)
|
||||
netdev_err(enic->netdev, "WQ[%d] error_status %d\n",
|
||||
i, error_status);
|
||||
|
@ -192,10 +194,13 @@ static void enic_log_q_error(struct enic *enic)
|
|||
|
||||
for (i = 0; i < enic->rq_count; i++) {
|
||||
error_status = vnic_rq_error_status(&enic->rq[i]);
|
||||
err |= error_status;
|
||||
if (error_status)
|
||||
netdev_err(enic->netdev, "RQ[%d] error_status %d\n",
|
||||
i, error_status);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void enic_msglvl_check(struct enic *enic)
|
||||
|
@ -333,8 +338,7 @@ static irqreturn_t enic_isr_msix_err(int irq, void *data)
|
|||
|
||||
vnic_intr_return_all_credits(&enic->intr[intr]);
|
||||
|
||||
enic_log_q_error(enic);
|
||||
|
||||
if (enic_log_q_error(enic))
|
||||
/* schedule recovery from WQ/RQ error */
|
||||
schedule_work(&enic->reset);
|
||||
|
||||
|
@ -804,7 +808,7 @@ static void enic_set_rx_mode(struct net_device *netdev)
|
|||
static void enic_tx_timeout(struct net_device *netdev)
|
||||
{
|
||||
struct enic *enic = netdev_priv(netdev);
|
||||
schedule_work(&enic->reset);
|
||||
schedule_work(&enic->tx_hang_reset);
|
||||
}
|
||||
|
||||
static int enic_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
|
||||
|
@ -1924,6 +1928,19 @@ static int enic_dev_open(struct enic *enic)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int enic_dev_soft_reset(struct enic *enic)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = enic_dev_wait(enic->vdev, vnic_dev_soft_reset,
|
||||
vnic_dev_soft_reset_done, 0);
|
||||
if (err)
|
||||
netdev_err(enic->netdev, "vNIC soft reset failed, err %d\n",
|
||||
err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int enic_dev_hang_reset(struct enic *enic)
|
||||
{
|
||||
int err;
|
||||
|
@ -2059,6 +2076,26 @@ static void enic_reset(struct work_struct *work)
|
|||
|
||||
rtnl_lock();
|
||||
|
||||
spin_lock(&enic->enic_api_lock);
|
||||
enic_stop(enic->netdev);
|
||||
enic_dev_soft_reset(enic);
|
||||
enic_reset_addr_lists(enic);
|
||||
enic_init_vnic_resources(enic);
|
||||
enic_set_rss_nic_cfg(enic);
|
||||
enic_dev_set_ig_vlan_rewrite_mode(enic);
|
||||
enic_open(enic->netdev);
|
||||
spin_unlock(&enic->enic_api_lock);
|
||||
call_netdevice_notifiers(NETDEV_REBOOT, enic->netdev);
|
||||
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
static void enic_tx_hang_reset(struct work_struct *work)
|
||||
{
|
||||
struct enic *enic = container_of(work, struct enic, tx_hang_reset);
|
||||
|
||||
rtnl_lock();
|
||||
|
||||
spin_lock(&enic->enic_api_lock);
|
||||
enic_dev_hang_notify(enic);
|
||||
enic_stop(enic->netdev);
|
||||
|
@ -2583,6 +2620,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
|
||||
enic_set_rx_coal_setting(enic);
|
||||
INIT_WORK(&enic->reset, enic_reset);
|
||||
INIT_WORK(&enic->tx_hang_reset, enic_tx_hang_reset);
|
||||
INIT_WORK(&enic->change_mtu_work, enic_change_mtu_work);
|
||||
|
||||
for (i = 0; i < enic->wq_count; i++)
|
||||
|
|
|
@ -659,14 +659,14 @@ int vnic_dev_open_done(struct vnic_dev *vdev, int *done)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg)
|
||||
int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg)
|
||||
{
|
||||
u64 a0 = (u32)arg, a1 = 0;
|
||||
int wait = 1000;
|
||||
return vnic_dev_cmd(vdev, CMD_SOFT_RESET, &a0, &a1, wait);
|
||||
}
|
||||
|
||||
static int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done)
|
||||
int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done)
|
||||
{
|
||||
u64 a0 = 0, a1 = 0;
|
||||
int wait = 1000;
|
||||
|
|
|
@ -155,7 +155,9 @@ int vnic_dev_deinit(struct vnic_dev *vdev);
|
|||
void vnic_dev_intr_coal_timer_info_default(struct vnic_dev *vdev);
|
||||
int vnic_dev_intr_coal_timer_info(struct vnic_dev *vdev);
|
||||
int vnic_dev_hang_reset(struct vnic_dev *vdev, int arg);
|
||||
int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg);
|
||||
int vnic_dev_hang_reset_done(struct vnic_dev *vdev, int *done);
|
||||
int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done);
|
||||
void vnic_dev_set_intr_mode(struct vnic_dev *vdev,
|
||||
enum vnic_dev_intr_mode intr_mode);
|
||||
enum vnic_dev_intr_mode vnic_dev_get_intr_mode(struct vnic_dev *vdev);
|
||||
|
|
|
@ -1597,7 +1597,6 @@ static void de_get_drvinfo (struct net_device *dev,struct ethtool_drvinfo *info)
|
|||
strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
|
||||
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
|
||||
strlcpy(info->bus_info, pci_name(de->pdev), sizeof(info->bus_info));
|
||||
info->eedump_len = DE_EEPROM_SIZE;
|
||||
}
|
||||
|
||||
static int de_get_regs_len(struct net_device *dev)
|
||||
|
|
|
@ -234,9 +234,6 @@ static void be_get_drvinfo(struct net_device *netdev,
|
|||
|
||||
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
|
||||
sizeof(drvinfo->bus_info));
|
||||
drvinfo->testinfo_len = 0;
|
||||
drvinfo->regdump_len = 0;
|
||||
drvinfo->eedump_len = 0;
|
||||
}
|
||||
|
||||
static u32 lancer_cmd_get_file_len(struct be_adapter *adapter, u8 *file_name)
|
||||
|
|
|
@ -112,9 +112,8 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable)
|
|||
unsigned long flags;
|
||||
u32 val, tempval;
|
||||
int inc;
|
||||
struct timespec ts;
|
||||
struct timespec64 ts;
|
||||
u64 ns;
|
||||
u32 remainder;
|
||||
val = 0;
|
||||
|
||||
if (!(fep->hwts_tx_en || fep->hwts_rx_en)) {
|
||||
|
@ -163,8 +162,7 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable)
|
|||
tempval = readl(fep->hwp + FEC_ATIME);
|
||||
/* Convert the ptp local counter to 1588 timestamp */
|
||||
ns = timecounter_cyc2time(&fep->tc, tempval);
|
||||
ts.tv_sec = div_u64_rem(ns, 1000000000ULL, &remainder);
|
||||
ts.tv_nsec = remainder;
|
||||
ts = ns_to_timespec64(ns);
|
||||
|
||||
/* The tempval is less than 3 seconds, and so val is less than
|
||||
* 4 seconds. No overflow for 32bit calculation.
|
||||
|
|
|
@ -907,6 +907,9 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
|
|||
if (of_find_property(np, "fsl,magic-packet", NULL))
|
||||
priv->device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET;
|
||||
|
||||
if (of_get_property(np, "fsl,wake-on-filer", NULL))
|
||||
priv->device_flags |= FSL_GIANFAR_DEV_HAS_WAKE_ON_FILER;
|
||||
|
||||
priv->phy_node = of_parse_phandle(np, "phy-handle", 0);
|
||||
|
||||
/* In the case of a fixed PHY, the DT node associated
|
||||
|
@ -1415,8 +1418,14 @@ static int gfar_probe(struct platform_device *ofdev)
|
|||
goto register_fail;
|
||||
}
|
||||
|
||||
device_set_wakeup_capable(&dev->dev, priv->device_flags &
|
||||
FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
|
||||
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET)
|
||||
priv->wol_supported |= GFAR_WOL_MAGIC;
|
||||
|
||||
if ((priv->device_flags & FSL_GIANFAR_DEV_HAS_WAKE_ON_FILER) &&
|
||||
priv->rx_filer_enable)
|
||||
priv->wol_supported |= GFAR_WOL_FILER_UCAST;
|
||||
|
||||
device_set_wakeup_capable(&ofdev->dev, priv->wol_supported);
|
||||
|
||||
/* fill out IRQ number and name fields */
|
||||
for (i = 0; i < priv->num_grps; i++) {
|
||||
|
@ -1479,15 +1488,122 @@ static int gfar_remove(struct platform_device *ofdev)
|
|||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static void __gfar_filer_disable(struct gfar_private *priv)
|
||||
{
|
||||
struct gfar __iomem *regs = priv->gfargrp[0].regs;
|
||||
u32 temp;
|
||||
|
||||
temp = gfar_read(®s->rctrl);
|
||||
temp &= ~(RCTRL_FILREN | RCTRL_PRSDEP_INIT);
|
||||
gfar_write(®s->rctrl, temp);
|
||||
}
|
||||
|
||||
static void __gfar_filer_enable(struct gfar_private *priv)
|
||||
{
|
||||
struct gfar __iomem *regs = priv->gfargrp[0].regs;
|
||||
u32 temp;
|
||||
|
||||
temp = gfar_read(®s->rctrl);
|
||||
temp |= RCTRL_FILREN | RCTRL_PRSDEP_INIT;
|
||||
gfar_write(®s->rctrl, temp);
|
||||
}
|
||||
|
||||
/* Filer rules implementing wol capabilities */
|
||||
static void gfar_filer_config_wol(struct gfar_private *priv)
|
||||
{
|
||||
unsigned int i;
|
||||
u32 rqfcr;
|
||||
|
||||
__gfar_filer_disable(priv);
|
||||
|
||||
/* clear the filer table, reject any packet by default */
|
||||
rqfcr = RQFCR_RJE | RQFCR_CMP_MATCH;
|
||||
for (i = 0; i <= MAX_FILER_IDX; i++)
|
||||
gfar_write_filer(priv, i, rqfcr, 0);
|
||||
|
||||
i = 0;
|
||||
if (priv->wol_opts & GFAR_WOL_FILER_UCAST) {
|
||||
/* unicast packet, accept it */
|
||||
struct net_device *ndev = priv->ndev;
|
||||
/* get the default rx queue index */
|
||||
u8 qindex = (u8)priv->gfargrp[0].rx_queue->qindex;
|
||||
u32 dest_mac_addr = (ndev->dev_addr[0] << 16) |
|
||||
(ndev->dev_addr[1] << 8) |
|
||||
ndev->dev_addr[2];
|
||||
|
||||
rqfcr = (qindex << 10) | RQFCR_AND |
|
||||
RQFCR_CMP_EXACT | RQFCR_PID_DAH;
|
||||
|
||||
gfar_write_filer(priv, i++, rqfcr, dest_mac_addr);
|
||||
|
||||
dest_mac_addr = (ndev->dev_addr[3] << 16) |
|
||||
(ndev->dev_addr[4] << 8) |
|
||||
ndev->dev_addr[5];
|
||||
rqfcr = (qindex << 10) | RQFCR_GPI |
|
||||
RQFCR_CMP_EXACT | RQFCR_PID_DAL;
|
||||
gfar_write_filer(priv, i++, rqfcr, dest_mac_addr);
|
||||
}
|
||||
|
||||
__gfar_filer_enable(priv);
|
||||
}
|
||||
|
||||
static void gfar_filer_restore_table(struct gfar_private *priv)
|
||||
{
|
||||
u32 rqfcr, rqfpr;
|
||||
unsigned int i;
|
||||
|
||||
__gfar_filer_disable(priv);
|
||||
|
||||
for (i = 0; i <= MAX_FILER_IDX; i++) {
|
||||
rqfcr = priv->ftp_rqfcr[i];
|
||||
rqfpr = priv->ftp_rqfpr[i];
|
||||
gfar_write_filer(priv, i, rqfcr, rqfpr);
|
||||
}
|
||||
|
||||
__gfar_filer_enable(priv);
|
||||
}
|
||||
|
||||
/* gfar_start() for Rx only and with the FGPI filer interrupt enabled */
|
||||
static void gfar_start_wol_filer(struct gfar_private *priv)
|
||||
{
|
||||
struct gfar __iomem *regs = priv->gfargrp[0].regs;
|
||||
u32 tempval;
|
||||
int i = 0;
|
||||
|
||||
/* Enable Rx hw queues */
|
||||
gfar_write(®s->rqueue, priv->rqueue);
|
||||
|
||||
/* Initialize DMACTRL to have WWR and WOP */
|
||||
tempval = gfar_read(®s->dmactrl);
|
||||
tempval |= DMACTRL_INIT_SETTINGS;
|
||||
gfar_write(®s->dmactrl, tempval);
|
||||
|
||||
/* Make sure we aren't stopped */
|
||||
tempval = gfar_read(®s->dmactrl);
|
||||
tempval &= ~DMACTRL_GRS;
|
||||
gfar_write(®s->dmactrl, tempval);
|
||||
|
||||
for (i = 0; i < priv->num_grps; i++) {
|
||||
regs = priv->gfargrp[i].regs;
|
||||
/* Clear RHLT, so that the DMA starts polling now */
|
||||
gfar_write(®s->rstat, priv->gfargrp[i].rstat);
|
||||
/* enable the Filer General Purpose Interrupt */
|
||||
gfar_write(®s->imask, IMASK_FGPI);
|
||||
}
|
||||
|
||||
/* Enable Rx DMA */
|
||||
tempval = gfar_read(®s->maccfg1);
|
||||
tempval |= MACCFG1_RX_EN;
|
||||
gfar_write(®s->maccfg1, tempval);
|
||||
}
|
||||
|
||||
static int gfar_suspend(struct device *dev)
|
||||
{
|
||||
struct gfar_private *priv = dev_get_drvdata(dev);
|
||||
struct net_device *ndev = priv->ndev;
|
||||
struct gfar __iomem *regs = priv->gfargrp[0].regs;
|
||||
u32 tempval;
|
||||
int magic_packet = priv->wol_en &&
|
||||
(priv->device_flags &
|
||||
FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
|
||||
u16 wol = priv->wol_opts;
|
||||
|
||||
if (!netif_running(ndev))
|
||||
return 0;
|
||||
|
@ -1499,7 +1615,7 @@ static int gfar_suspend(struct device *dev)
|
|||
|
||||
gfar_halt(priv);
|
||||
|
||||
if (magic_packet) {
|
||||
if (wol & GFAR_WOL_MAGIC) {
|
||||
/* Enable interrupt on Magic Packet */
|
||||
gfar_write(®s->imask, IMASK_MAG);
|
||||
|
||||
|
@ -1513,6 +1629,10 @@ static int gfar_suspend(struct device *dev)
|
|||
tempval |= MACCFG1_RX_EN;
|
||||
gfar_write(®s->maccfg1, tempval);
|
||||
|
||||
} else if (wol & GFAR_WOL_FILER_UCAST) {
|
||||
gfar_filer_config_wol(priv);
|
||||
gfar_start_wol_filer(priv);
|
||||
|
||||
} else {
|
||||
phy_stop(priv->phydev);
|
||||
}
|
||||
|
@ -1526,18 +1646,22 @@ static int gfar_resume(struct device *dev)
|
|||
struct net_device *ndev = priv->ndev;
|
||||
struct gfar __iomem *regs = priv->gfargrp[0].regs;
|
||||
u32 tempval;
|
||||
int magic_packet = priv->wol_en &&
|
||||
(priv->device_flags &
|
||||
FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
|
||||
u16 wol = priv->wol_opts;
|
||||
|
||||
if (!netif_running(ndev))
|
||||
return 0;
|
||||
|
||||
if (magic_packet) {
|
||||
if (wol & GFAR_WOL_MAGIC) {
|
||||
/* Disable Magic Packet mode */
|
||||
tempval = gfar_read(®s->maccfg2);
|
||||
tempval &= ~MACCFG2_MPEN;
|
||||
gfar_write(®s->maccfg2, tempval);
|
||||
|
||||
} else if (wol & GFAR_WOL_FILER_UCAST) {
|
||||
/* need to stop rx only, tx is already down */
|
||||
gfar_halt(priv);
|
||||
gfar_filer_restore_table(priv);
|
||||
|
||||
} else {
|
||||
phy_start(priv->phydev);
|
||||
}
|
||||
|
@ -1998,6 +2122,8 @@ static int register_grp_irqs(struct gfar_priv_grp *grp)
|
|||
gfar_irq(grp, RX)->irq);
|
||||
goto rx_irq_fail;
|
||||
}
|
||||
enable_irq_wake(gfar_irq(grp, RX)->irq);
|
||||
|
||||
} else {
|
||||
err = request_irq(gfar_irq(grp, TX)->irq, gfar_interrupt, 0,
|
||||
gfar_irq(grp, TX)->name, grp);
|
||||
|
@ -2743,7 +2869,14 @@ irqreturn_t gfar_receive(int irq, void *grp_id)
|
|||
{
|
||||
struct gfar_priv_grp *grp = (struct gfar_priv_grp *)grp_id;
|
||||
unsigned long flags;
|
||||
u32 imask;
|
||||
u32 imask, ievent;
|
||||
|
||||
ievent = gfar_read(&grp->regs->ievent);
|
||||
|
||||
if (unlikely(ievent & IEVENT_FGPI)) {
|
||||
gfar_write(&grp->regs->ievent, IEVENT_FGPI);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
if (likely(napi_schedule_prep(&grp->napi_rx))) {
|
||||
spin_lock_irqsave(&grp->grplock, flags);
|
||||
|
|
|
@ -340,6 +340,7 @@ extern const char gfar_driver_version[];
|
|||
#define IEVENT_MAG 0x00000800
|
||||
#define IEVENT_GRSC 0x00000100
|
||||
#define IEVENT_RXF0 0x00000080
|
||||
#define IEVENT_FGPI 0x00000010
|
||||
#define IEVENT_FIR 0x00000008
|
||||
#define IEVENT_FIQ 0x00000004
|
||||
#define IEVENT_DPE 0x00000002
|
||||
|
@ -372,6 +373,7 @@ extern const char gfar_driver_version[];
|
|||
#define IMASK_MAG 0x00000800
|
||||
#define IMASK_GRSC 0x00000100
|
||||
#define IMASK_RXFEN0 0x00000080
|
||||
#define IMASK_FGPI 0x00000010
|
||||
#define IMASK_FIR 0x00000008
|
||||
#define IMASK_FIQ 0x00000004
|
||||
#define IMASK_DPE 0x00000002
|
||||
|
@ -540,6 +542,9 @@ extern const char gfar_driver_version[];
|
|||
|
||||
#define GFAR_INT_NAME_MAX (IFNAMSIZ + 6) /* '_g#_xx' */
|
||||
|
||||
#define GFAR_WOL_MAGIC 0x00000001
|
||||
#define GFAR_WOL_FILER_UCAST 0x00000002
|
||||
|
||||
struct txbd8
|
||||
{
|
||||
union {
|
||||
|
@ -917,6 +922,7 @@ struct gfar {
|
|||
#define FSL_GIANFAR_DEV_HAS_BD_STASHING 0x00000200
|
||||
#define FSL_GIANFAR_DEV_HAS_BUF_STASHING 0x00000400
|
||||
#define FSL_GIANFAR_DEV_HAS_TIMER 0x00000800
|
||||
#define FSL_GIANFAR_DEV_HAS_WAKE_ON_FILER 0x00001000
|
||||
|
||||
#if (MAXGROUPS == 2)
|
||||
#define DEFAULT_MAPPING 0xAA
|
||||
|
@ -1161,8 +1167,6 @@ struct gfar_private {
|
|||
extended_hash:1,
|
||||
bd_stash_en:1,
|
||||
rx_filer_enable:1,
|
||||
/* Wake-on-LAN enabled */
|
||||
wol_en:1,
|
||||
/* Enable priorty based Tx scheduling in Hw */
|
||||
prio_sched_en:1,
|
||||
/* Flow control flags */
|
||||
|
@ -1191,6 +1195,10 @@ struct gfar_private {
|
|||
u32 __iomem *hash_regs[16];
|
||||
int hash_width;
|
||||
|
||||
/* wake-on-lan settings */
|
||||
u16 wol_opts;
|
||||
u16 wol_supported;
|
||||
|
||||
/*Filer table*/
|
||||
unsigned int ftp_rqfpr[MAX_FILER_IDX + 1];
|
||||
unsigned int ftp_rqfcr[MAX_FILER_IDX + 1];
|
||||
|
|
|
@ -182,8 +182,6 @@ static void gfar_gdrvinfo(struct net_device *dev,
|
|||
sizeof(drvinfo->version));
|
||||
strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
|
||||
strlcpy(drvinfo->bus_info, "N/A", sizeof(drvinfo->bus_info));
|
||||
drvinfo->regdump_len = 0;
|
||||
drvinfo->eedump_len = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -644,28 +642,49 @@ static void gfar_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
|||
{
|
||||
struct gfar_private *priv = netdev_priv(dev);
|
||||
|
||||
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) {
|
||||
wol->supported = WAKE_MAGIC;
|
||||
wol->wolopts = priv->wol_en ? WAKE_MAGIC : 0;
|
||||
} else {
|
||||
wol->supported = wol->wolopts = 0;
|
||||
}
|
||||
wol->supported = 0;
|
||||
wol->wolopts = 0;
|
||||
|
||||
if (priv->wol_supported & GFAR_WOL_MAGIC)
|
||||
wol->supported |= WAKE_MAGIC;
|
||||
|
||||
if (priv->wol_supported & GFAR_WOL_FILER_UCAST)
|
||||
wol->supported |= WAKE_UCAST;
|
||||
|
||||
if (priv->wol_opts & GFAR_WOL_MAGIC)
|
||||
wol->wolopts |= WAKE_MAGIC;
|
||||
|
||||
if (priv->wol_opts & GFAR_WOL_FILER_UCAST)
|
||||
wol->wolopts |= WAKE_UCAST;
|
||||
}
|
||||
|
||||
static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct gfar_private *priv = netdev_priv(dev);
|
||||
u16 wol_opts = 0;
|
||||
int err;
|
||||
|
||||
if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) &&
|
||||
wol->wolopts != 0)
|
||||
if (!priv->wol_supported && wol->wolopts)
|
||||
return -EINVAL;
|
||||
|
||||
if (wol->wolopts & ~WAKE_MAGIC)
|
||||
if (wol->wolopts & ~(WAKE_MAGIC | WAKE_UCAST))
|
||||
return -EINVAL;
|
||||
|
||||
device_set_wakeup_enable(&dev->dev, wol->wolopts & WAKE_MAGIC);
|
||||
if (wol->wolopts & WAKE_MAGIC) {
|
||||
wol_opts |= GFAR_WOL_MAGIC;
|
||||
} else {
|
||||
if (wol->wolopts & WAKE_UCAST)
|
||||
wol_opts |= GFAR_WOL_FILER_UCAST;
|
||||
}
|
||||
|
||||
priv->wol_en = !!device_may_wakeup(&dev->dev);
|
||||
wol_opts &= priv->wol_supported;
|
||||
priv->wol_opts = 0;
|
||||
|
||||
err = device_set_wakeup_enable(priv->dev, wol_opts);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
priv->wol_opts = wol_opts;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -351,8 +351,6 @@ uec_get_drvinfo(struct net_device *netdev,
|
|||
strlcpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version));
|
||||
strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
|
||||
strlcpy(drvinfo->bus_info, "QUICC ENGINE", sizeof(drvinfo->bus_info));
|
||||
drvinfo->eedump_len = 0;
|
||||
drvinfo->regdump_len = uec_get_regs_len(netdev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
|
|
@ -24,7 +24,6 @@ config HIX5HD2_GMAC
|
|||
|
||||
config HIP04_ETH
|
||||
tristate "HISILICON P04 Ethernet support"
|
||||
select PHYLIB
|
||||
select MARVELL_PHY
|
||||
select MFD_SYSCON
|
||||
select HNS_MDIO
|
||||
|
@ -33,8 +32,8 @@ config HIP04_ETH
|
|||
want to use the internal ethernet then you should answer Y to this.
|
||||
|
||||
config HNS_MDIO
|
||||
tristate "Hisilicon HNS MDIO device Support"
|
||||
select MDIO
|
||||
tristate
|
||||
select PHYLIB
|
||||
---help---
|
||||
This selects the HNS MDIO support. It is needed by HNS_DSAF to access
|
||||
the PHY
|
||||
|
|
|
@ -448,12 +448,12 @@ static ssize_t handles_show(struct device *dev,
|
|||
s += sprintf(buf + s, "handle %d (eport_id=%u from %s):\n",
|
||||
i++, h->eport_id, h->dev->name);
|
||||
for (j = 0; j < h->q_num; j++) {
|
||||
s += sprintf(buf + s, "\tqueue[%d] on 0x%llx\n",
|
||||
j, (u64)h->qs[i]->io_base);
|
||||
#define HANDEL_TX_MSG "\t\ttx_ring on 0x%llx:%u,%u,%u,%u,%u,%llu,%llu\n"
|
||||
s += sprintf(buf + s, "\tqueue[%d] on %p\n",
|
||||
j, h->qs[i]->io_base);
|
||||
#define HANDEL_TX_MSG "\t\ttx_ring on %p:%u,%u,%u,%u,%u,%llu,%llu\n"
|
||||
s += sprintf(buf + s,
|
||||
HANDEL_TX_MSG,
|
||||
(u64)h->qs[i]->tx_ring.io_base,
|
||||
h->qs[i]->tx_ring.io_base,
|
||||
h->qs[i]->tx_ring.buf_size,
|
||||
h->qs[i]->tx_ring.desc_num,
|
||||
h->qs[i]->tx_ring.max_desc_num_per_pkt,
|
||||
|
@ -462,8 +462,8 @@ static ssize_t handles_show(struct device *dev,
|
|||
h->qs[i]->tx_ring.stats.sw_err_cnt,
|
||||
h->qs[i]->tx_ring.stats.io_err_cnt);
|
||||
s += sprintf(buf + s,
|
||||
"\t\trx_ring on 0x%llx:%u,%u,%llu,%llu,%llu\n",
|
||||
(u64)h->qs[i]->rx_ring.io_base,
|
||||
"\t\trx_ring on %p:%u,%u,%llu,%llu,%llu\n",
|
||||
h->qs[i]->rx_ring.io_base,
|
||||
h->qs[i]->rx_ring.buf_size,
|
||||
h->qs[i]->rx_ring.desc_num,
|
||||
h->qs[i]->rx_ring.stats.sw_err_cnt,
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define HNAE_DRIVER_VERSION "1.3.0"
|
||||
|
@ -429,6 +430,7 @@ struct hnae_ae_ops {
|
|||
void (*set_coalesce_usecs)(struct hnae_handle *handle, u32 timeout);
|
||||
int (*set_coalesce_frames)(struct hnae_handle *handle,
|
||||
u32 coalesce_frames);
|
||||
void (*set_promisc_mode)(struct hnae_handle *handle, u32 en);
|
||||
int (*get_mac_addr)(struct hnae_handle *handle, void **p);
|
||||
int (*set_mac_addr)(struct hnae_handle *handle, void *p);
|
||||
int (*set_mc_addr)(struct hnae_handle *handle, void *addr);
|
||||
|
|
|
@ -392,6 +392,11 @@ static int hns_ae_set_autoneg(struct hnae_handle *handle, u8 enable)
|
|||
return hns_mac_set_autoneg(hns_get_mac_cb(handle), enable);
|
||||
}
|
||||
|
||||
static void hns_ae_set_promisc_mode(struct hnae_handle *handle, u32 en)
|
||||
{
|
||||
hns_dsaf_set_promisc_mode(hns_ae_get_dsaf_dev(handle->dev), en);
|
||||
}
|
||||
|
||||
static int hns_ae_get_autoneg(struct hnae_handle *handle)
|
||||
{
|
||||
u32 auto_neg;
|
||||
|
@ -748,6 +753,7 @@ static struct hnae_ae_ops hns_dsaf_ops = {
|
|||
.get_rx_max_coalesced_frames = hns_ae_get_rx_max_coalesced_frames,
|
||||
.set_coalesce_usecs = hns_ae_set_coalesce_usecs,
|
||||
.set_coalesce_frames = hns_ae_set_coalesce_frames,
|
||||
.set_promisc_mode = hns_ae_set_promisc_mode,
|
||||
.set_mac_addr = hns_ae_set_mac_address,
|
||||
.set_mc_addr = hns_ae_set_multicast_one,
|
||||
.set_mtu = hns_ae_set_mtu,
|
||||
|
|
|
@ -744,9 +744,11 @@ int hns_mac_get_cfg(struct dsaf_device *dsaf_dev, int mac_idx)
|
|||
mac_cb->serdes_vaddr = dsaf_dev->sds_base;
|
||||
|
||||
if (dsaf_dev->cpld_base &&
|
||||
mac_idx < DSAF_SERVICE_PORT_NUM_PER_DSAF)
|
||||
mac_idx < DSAF_SERVICE_PORT_NUM_PER_DSAF) {
|
||||
mac_cb->cpld_vaddr = dsaf_dev->cpld_base +
|
||||
mac_cb->mac_id * CPLD_ADDR_PORT_OFFSET;
|
||||
cpld_led_reset(mac_cb);
|
||||
}
|
||||
mac_cb->sfp_prsnt = 0;
|
||||
mac_cb->txpkt_for_led = 0;
|
||||
mac_cb->rxpkt_for_led = 0;
|
||||
|
|
|
@ -217,6 +217,25 @@ hns_dsaf_ppe_qid_cfg(struct dsaf_device *dsaf_dev, u32 qid_cfg)
|
|||
}
|
||||
}
|
||||
|
||||
static void hns_dsaf_mix_def_qid_cfg(struct dsaf_device *dsaf_dev)
|
||||
{
|
||||
u16 max_q_per_vf, max_vfn;
|
||||
u32 q_id, q_num_per_port;
|
||||
u32 i;
|
||||
|
||||
hns_rcb_get_queue_mode(dsaf_dev->dsaf_mode,
|
||||
HNS_DSAF_COMM_SERVICE_NW_IDX,
|
||||
&max_vfn, &max_q_per_vf);
|
||||
q_num_per_port = max_vfn * max_q_per_vf;
|
||||
|
||||
for (i = 0, q_id = 0; i < DSAF_SERVICE_NW_NUM; i++) {
|
||||
dsaf_set_dev_field(dsaf_dev,
|
||||
DSAF_MIX_DEF_QID_0_REG + 0x0004 * i,
|
||||
0xff, 0, q_id);
|
||||
q_id += q_num_per_port;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* hns_dsaf_sw_port_type_cfg - cfg sw type
|
||||
* @dsaf_id: dsa fabric id
|
||||
|
@ -592,6 +611,11 @@ static void hns_dsaf_tbl_tcam_data_ucast_pul(
|
|||
dsaf_write_dev(dsaf_dev, DSAF_TBL_PUL_0_REG, o_tbl_pul);
|
||||
}
|
||||
|
||||
void hns_dsaf_set_promisc_mode(struct dsaf_device *dsaf_dev, u32 en)
|
||||
{
|
||||
dsaf_set_dev_bit(dsaf_dev, DSAF_CFG_0_REG, DSAF_CFG_MIX_MODE_S, !!en);
|
||||
}
|
||||
|
||||
/**
|
||||
* hns_dsaf_tbl_stat_en - tbl
|
||||
* @dsaf_id: dsa fabric id
|
||||
|
@ -920,6 +944,9 @@ static void hns_dsaf_comm_init(struct dsaf_device *dsaf_dev)
|
|||
/* set 22 queue per tx ppe engine, only used in switch mode */
|
||||
hns_dsaf_ppe_qid_cfg(dsaf_dev, DSAF_DEFAUTL_QUEUE_NUM_PER_PPE);
|
||||
|
||||
/* set promisc def queue id */
|
||||
hns_dsaf_mix_def_qid_cfg(dsaf_dev);
|
||||
|
||||
/* in non switch mode, set all port to access mode */
|
||||
hns_dsaf_sw_port_type_cfg(dsaf_dev, DSAF_SW_PORT_TYPE_NON_VLAN);
|
||||
|
||||
|
|
|
@ -423,5 +423,6 @@ void hns_dsaf_get_strings(int stringset, u8 *data, int port);
|
|||
|
||||
void hns_dsaf_get_regs(struct dsaf_device *ddev, u32 port, void *data);
|
||||
int hns_dsaf_get_regs_count(void);
|
||||
void hns_dsaf_set_promisc_mode(struct dsaf_device *dsaf_dev, u32 en);
|
||||
|
||||
#endif /* __HNS_DSAF_MAIN_H__ */
|
||||
|
|
|
@ -575,7 +575,7 @@ int hns_rcb_set_coalesced_frames(struct dsaf_device *dsaf_dev,
|
|||
*@max_vfn : max vfn number
|
||||
*@max_q_per_vf:max ring number per vm
|
||||
*/
|
||||
static void hns_rcb_get_queue_mode(enum dsaf_mode dsaf_mode, int comm_index,
|
||||
void hns_rcb_get_queue_mode(enum dsaf_mode dsaf_mode, int comm_index,
|
||||
u16 *max_vfn, u16 *max_q_per_vf)
|
||||
{
|
||||
if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) {
|
||||
|
|
|
@ -107,6 +107,8 @@ int hns_rcb_common_init_hw(struct rcb_common_cb *rcb_common);
|
|||
void hns_rcb_start(struct hnae_queue *q, u32 val);
|
||||
void hns_rcb_get_cfg(struct rcb_common_cb *rcb_common);
|
||||
void hns_rcb_common_init_commit_hw(struct rcb_common_cb *rcb_common);
|
||||
void hns_rcb_get_queue_mode(enum dsaf_mode dsaf_mode, int comm_index,
|
||||
u16 *max_vfn, u16 *max_q_per_vf);
|
||||
|
||||
void hns_rcb_ring_enable_hw(struct hnae_queue *q, u32 val);
|
||||
void hns_rcb_int_clr_hw(struct hnae_queue *q, u32 flag);
|
||||
|
|
|
@ -51,9 +51,9 @@ static const struct mac_stats_string g_xgmac_stats_string[] = {
|
|||
{"xgmac_rx_bad_pkt_from_dsaf", MAC_STATS_FIELD_OFF(rx_bad_from_sw)},
|
||||
{"xgmac_tx_bad_pkt_64tomax", MAC_STATS_FIELD_OFF(tx_bad_pkts)},
|
||||
|
||||
{"xgmac_rx_not_well_pkt", MAC_STATS_FIELD_OFF(rx_fragment_err)},
|
||||
{"xgmac_rx_good_well_pkt", MAC_STATS_FIELD_OFF(rx_undersize)},
|
||||
{"xgmac_rx_total_pkt", MAC_STATS_FIELD_OFF(rx_under_min)},
|
||||
{"xgmac_rx_bad_pkts_minto64", MAC_STATS_FIELD_OFF(rx_fragment_err)},
|
||||
{"xgmac_rx_good_pkts_minto64", MAC_STATS_FIELD_OFF(rx_undersize)},
|
||||
{"xgmac_rx_total_pkts_minto64", MAC_STATS_FIELD_OFF(rx_under_min)},
|
||||
{"xgmac_rx_pkt_64", MAC_STATS_FIELD_OFF(rx_64bytes)},
|
||||
{"xgmac_rx_pkt_65to127", MAC_STATS_FIELD_OFF(rx_65to127)},
|
||||
{"xgmac_rx_pkt_128to255", MAC_STATS_FIELD_OFF(rx_128to255)},
|
||||
|
|
|
@ -1161,6 +1161,21 @@ void hns_set_multicast_list(struct net_device *ndev)
|
|||
}
|
||||
}
|
||||
|
||||
void hns_nic_set_rx_mode(struct net_device *ndev)
|
||||
{
|
||||
struct hns_nic_priv *priv = netdev_priv(ndev);
|
||||
struct hnae_handle *h = priv->ae_handle;
|
||||
|
||||
if (h->dev->ops->set_promisc_mode) {
|
||||
if (ndev->flags & IFF_PROMISC)
|
||||
h->dev->ops->set_promisc_mode(h, 1);
|
||||
else
|
||||
h->dev->ops->set_promisc_mode(h, 0);
|
||||
}
|
||||
|
||||
hns_set_multicast_list(ndev);
|
||||
}
|
||||
|
||||
struct rtnl_link_stats64 *hns_nic_get_stats64(struct net_device *ndev,
|
||||
struct rtnl_link_stats64 *stats)
|
||||
{
|
||||
|
@ -1220,7 +1235,7 @@ static const struct net_device_ops hns_nic_netdev_ops = {
|
|||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
.ndo_poll_controller = hns_nic_poll_controller,
|
||||
#endif
|
||||
.ndo_set_rx_mode = hns_set_multicast_list,
|
||||
.ndo_set_rx_mode = hns_nic_set_rx_mode,
|
||||
};
|
||||
|
||||
static void hns_nic_update_link_status(struct net_device *netdev)
|
||||
|
|
|
@ -682,7 +682,6 @@ static void hns_nic_get_drvinfo(struct net_device *net_dev,
|
|||
drvinfo->bus_info[ETHTOOL_BUSINFO_LEN - 1] = '\0';
|
||||
|
||||
strncpy(drvinfo->fw_version, "N/A", ETHTOOL_FWVERS_LEN);
|
||||
drvinfo->eedump_len = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2204,7 +2204,6 @@ static void emac_ethtool_get_drvinfo(struct net_device *ndev,
|
|||
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
|
||||
snprintf(info->bus_info, sizeof(info->bus_info), "PPC 4xx EMAC-%d %s",
|
||||
dev->cell_index, dev->ofdev->dev.of_node->full_name);
|
||||
info->regdump_len = emac_ethtool_get_regs_len(ndev);
|
||||
}
|
||||
|
||||
static const struct ethtool_ops emac_ethtool_ops = {
|
||||
|
|
|
@ -559,8 +559,6 @@ static void e1000_get_drvinfo(struct net_device *netdev,
|
|||
|
||||
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
|
||||
sizeof(drvinfo->bus_info));
|
||||
drvinfo->regdump_len = e1000_get_regs_len(netdev);
|
||||
drvinfo->eedump_len = e1000_get_eeprom_len(netdev);
|
||||
}
|
||||
|
||||
static void e1000_get_ringparam(struct net_device *netdev,
|
||||
|
|
|
@ -3820,7 +3820,7 @@ static int e1000_clean(struct napi_struct *napi, int budget)
|
|||
if (work_done < budget) {
|
||||
if (likely(adapter->itr_setting & 3))
|
||||
e1000_set_itr(adapter);
|
||||
napi_complete(napi);
|
||||
napi_complete_done(napi, work_done);
|
||||
if (!test_bit(__E1000_DOWN, &adapter->flags))
|
||||
e1000_irq_enable(adapter);
|
||||
}
|
||||
|
|
|
@ -648,8 +648,6 @@ static void e1000_get_drvinfo(struct net_device *netdev,
|
|||
|
||||
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
|
||||
sizeof(drvinfo->bus_info));
|
||||
drvinfo->regdump_len = e1000_get_regs_len(netdev);
|
||||
drvinfo->eedump_len = e1000_get_eeprom_len(netdev);
|
||||
}
|
||||
|
||||
static void e1000_get_ringparam(struct net_device *netdev,
|
||||
|
|
|
@ -2693,7 +2693,7 @@ static int e1000e_poll(struct napi_struct *napi, int weight)
|
|||
if (work_done < weight) {
|
||||
if (adapter->itr_setting & 3)
|
||||
e1000_set_itr(adapter);
|
||||
napi_complete(napi);
|
||||
napi_complete_done(napi, work_done);
|
||||
if (!test_bit(__E1000_DOWN, &adapter->state)) {
|
||||
if (adapter->msix_entries)
|
||||
ew32(IMS, adapter->rx_ring->ims_val);
|
||||
|
|
|
@ -176,7 +176,7 @@ void fm10k_dbg_q_vector_init(struct fm10k_q_vector *q_vector)
|
|||
return;
|
||||
|
||||
/* Generate a folder for each q_vector */
|
||||
sprintf(name, "q_vector.%03d", q_vector->v_idx);
|
||||
snprintf(name, sizeof(name), "q_vector.%03d", q_vector->v_idx);
|
||||
|
||||
q_vector->dbg_q_vector = debugfs_create_dir(name, interface->dbg_intfc);
|
||||
if (!q_vector->dbg_q_vector)
|
||||
|
@ -186,7 +186,7 @@ void fm10k_dbg_q_vector_init(struct fm10k_q_vector *q_vector)
|
|||
for (i = 0; i < q_vector->tx.count; i++) {
|
||||
struct fm10k_ring *ring = &q_vector->tx.ring[i];
|
||||
|
||||
sprintf(name, "tx_ring.%03d", ring->queue_index);
|
||||
snprintf(name, sizeof(name), "tx_ring.%03d", ring->queue_index);
|
||||
|
||||
debugfs_create_file(name, 0600,
|
||||
q_vector->dbg_q_vector, ring,
|
||||
|
@ -197,7 +197,7 @@ void fm10k_dbg_q_vector_init(struct fm10k_q_vector *q_vector)
|
|||
for (i = 0; i < q_vector->rx.count; i++) {
|
||||
struct fm10k_ring *ring = &q_vector->rx.ring[i];
|
||||
|
||||
sprintf(name, "rx_ring.%03d", ring->queue_index);
|
||||
snprintf(name, sizeof(name), "rx_ring.%03d", ring->queue_index);
|
||||
|
||||
debugfs_create_file(name, 0600,
|
||||
q_vector->dbg_q_vector, ring,
|
||||
|
|
|
@ -206,13 +206,13 @@ static void fm10k_get_stat_strings(struct net_device *dev, u8 *data)
|
|||
}
|
||||
|
||||
for (i = 0; i < interface->hw.mac.max_queues; i++) {
|
||||
sprintf(p, "tx_queue_%u_packets", i);
|
||||
snprintf(p, ETH_GSTRING_LEN, "tx_queue_%u_packets", i);
|
||||
p += ETH_GSTRING_LEN;
|
||||
sprintf(p, "tx_queue_%u_bytes", i);
|
||||
snprintf(p, ETH_GSTRING_LEN, "tx_queue_%u_bytes", i);
|
||||
p += ETH_GSTRING_LEN;
|
||||
sprintf(p, "rx_queue_%u_packets", i);
|
||||
snprintf(p, ETH_GSTRING_LEN, "rx_queue_%u_packets", i);
|
||||
p += ETH_GSTRING_LEN;
|
||||
sprintf(p, "rx_queue_%u_bytes", i);
|
||||
snprintf(p, ETH_GSTRING_LEN, "rx_queue_%u_bytes", i);
|
||||
p += ETH_GSTRING_LEN;
|
||||
}
|
||||
}
|
||||
|
@ -515,10 +515,6 @@ static void fm10k_get_drvinfo(struct net_device *dev,
|
|||
sizeof(info->version) - 1);
|
||||
strncpy(info->bus_info, pci_name(interface->pdev),
|
||||
sizeof(info->bus_info) - 1);
|
||||
|
||||
info->n_stats = fm10k_get_sset_count(dev, ETH_SS_STATS);
|
||||
|
||||
info->regdump_len = fm10k_get_regs_len(dev);
|
||||
}
|
||||
|
||||
static void fm10k_get_pauseparam(struct net_device *dev,
|
||||
|
|
|
@ -593,7 +593,7 @@ static void fm10k_receive_skb(struct fm10k_q_vector *q_vector,
|
|||
napi_gro_receive(&q_vector->napi, skb);
|
||||
}
|
||||
|
||||
static bool fm10k_clean_rx_irq(struct fm10k_q_vector *q_vector,
|
||||
static int fm10k_clean_rx_irq(struct fm10k_q_vector *q_vector,
|
||||
struct fm10k_ring *rx_ring,
|
||||
int budget)
|
||||
{
|
||||
|
@ -662,7 +662,7 @@ static bool fm10k_clean_rx_irq(struct fm10k_q_vector *q_vector,
|
|||
q_vector->rx.total_packets += total_packets;
|
||||
q_vector->rx.total_bytes += total_bytes;
|
||||
|
||||
return total_packets < budget;
|
||||
return total_packets;
|
||||
}
|
||||
|
||||
#define VXLAN_HLEN (sizeof(struct udphdr) + 8)
|
||||
|
@ -1422,7 +1422,7 @@ static int fm10k_poll(struct napi_struct *napi, int budget)
|
|||
struct fm10k_q_vector *q_vector =
|
||||
container_of(napi, struct fm10k_q_vector, napi);
|
||||
struct fm10k_ring *ring;
|
||||
int per_ring_budget;
|
||||
int per_ring_budget, work_done = 0;
|
||||
bool clean_complete = true;
|
||||
|
||||
fm10k_for_each_ring(ring, q_vector->tx)
|
||||
|
@ -1436,16 +1436,19 @@ static int fm10k_poll(struct napi_struct *napi, int budget)
|
|||
else
|
||||
per_ring_budget = budget;
|
||||
|
||||
fm10k_for_each_ring(ring, q_vector->rx)
|
||||
clean_complete &= fm10k_clean_rx_irq(q_vector, ring,
|
||||
per_ring_budget);
|
||||
fm10k_for_each_ring(ring, q_vector->rx) {
|
||||
int work = fm10k_clean_rx_irq(q_vector, ring, per_ring_budget);
|
||||
|
||||
work_done += work;
|
||||
clean_complete &= !!(work < per_ring_budget);
|
||||
}
|
||||
|
||||
/* If all work not completed, return budget and keep polling */
|
||||
if (!clean_complete)
|
||||
return budget;
|
||||
|
||||
/* all work done, exit the polling mode */
|
||||
napi_complete(napi);
|
||||
napi_complete_done(napi, work_done);
|
||||
|
||||
/* re-enable the q_vector */
|
||||
fm10k_qv_enable(q_vector);
|
||||
|
@ -1905,7 +1908,7 @@ static void fm10k_init_reta(struct fm10k_intfc *interface)
|
|||
u32 reta, base;
|
||||
|
||||
/* If the netdev is initialized we have to maintain table if possible */
|
||||
if (interface->netdev->reg_state) {
|
||||
if (interface->netdev->reg_state != NETREG_UNINITIALIZED) {
|
||||
for (i = FM10K_RETA_SIZE; i--;) {
|
||||
reta = interface->reta[i];
|
||||
if ((((reta << 24) >> 24) < rss_i) &&
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue