Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Conflicts: drivers/net/ethernet/freescale/fec_main.c6ead9c98ca
("net: fec: remove the xdp_return_frame when lack of tx BDs")144470c88c
("net: fec: using the standard return codes when xdp xmit errors") Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
90223c1136
5
.mailmap
5
.mailmap
@ -364,6 +364,11 @@ Nicolas Pitre <nico@fluxnic.net> <nico@linaro.org>
|
||||
Nicolas Saenz Julienne <nsaenz@kernel.org> <nsaenzjulienne@suse.de>
|
||||
Nicolas Saenz Julienne <nsaenz@kernel.org> <nsaenzjulienne@suse.com>
|
||||
Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
|
||||
Nikolay Aleksandrov <razor@blackwall.org> <naleksan@redhat.com>
|
||||
Nikolay Aleksandrov <razor@blackwall.org> <nikolay@redhat.com>
|
||||
Nikolay Aleksandrov <razor@blackwall.org> <nikolay@cumulusnetworks.com>
|
||||
Nikolay Aleksandrov <razor@blackwall.org> <nikolay@nvidia.com>
|
||||
Nikolay Aleksandrov <razor@blackwall.org> <nikolay@isovalent.com>
|
||||
Oleksandr Natalenko <oleksandr@natalenko.name> <oleksandr@redhat.com>
|
||||
Oleksij Rempel <linux@rempel-privat.de> <bug-track@fisher-privat.net>
|
||||
Oleksij Rempel <linux@rempel-privat.de> <external.Oleksij.Rempel@de.bosch.com>
|
||||
|
4
CREDITS
4
CREDITS
@ -1706,6 +1706,10 @@ S: Panoramastrasse 18
|
||||
S: D-69126 Heidelberg
|
||||
S: Germany
|
||||
|
||||
N: Neil Horman
|
||||
M: nhorman@tuxdriver.com
|
||||
D: SCTP protocol maintainer.
|
||||
|
||||
N: Simon Horman
|
||||
M: horms@verge.net.au
|
||||
D: Renesas ARM/ARM64 SoC maintainer
|
||||
|
@ -18,7 +18,6 @@ Block
|
||||
kyber-iosched
|
||||
null_blk
|
||||
pr
|
||||
request
|
||||
stat
|
||||
switching-sched
|
||||
writeback_cache_control
|
||||
|
@ -1,99 +0,0 @@
|
||||
============================
|
||||
struct request documentation
|
||||
============================
|
||||
|
||||
Jens Axboe <jens.axboe@oracle.com> 27/05/02
|
||||
|
||||
|
||||
.. FIXME:
|
||||
No idea about what does mean - seems just some noise, so comment it
|
||||
|
||||
1.0
|
||||
Index
|
||||
|
||||
2.0 Struct request members classification
|
||||
|
||||
2.1 struct request members explanation
|
||||
|
||||
3.0
|
||||
|
||||
|
||||
2.0
|
||||
|
||||
|
||||
|
||||
Short explanation of request members
|
||||
====================================
|
||||
|
||||
Classification flags:
|
||||
|
||||
= ====================
|
||||
D driver member
|
||||
B block layer member
|
||||
I I/O scheduler member
|
||||
= ====================
|
||||
|
||||
Unless an entry contains a D classification, a device driver must not access
|
||||
this member. Some members may contain D classifications, but should only be
|
||||
access through certain macros or functions (eg ->flags).
|
||||
|
||||
<linux/blkdev.h>
|
||||
|
||||
=============================== ======= =======================================
|
||||
Member Flag Comment
|
||||
=============================== ======= =======================================
|
||||
struct list_head queuelist BI Organization on various internal
|
||||
queues
|
||||
|
||||
``void *elevator_private`` I I/O scheduler private data
|
||||
|
||||
unsigned char cmd[16] D Driver can use this for setting up
|
||||
a cdb before execution, see
|
||||
blk_queue_prep_rq
|
||||
|
||||
unsigned long flags DBI Contains info about data direction,
|
||||
request type, etc.
|
||||
|
||||
int rq_status D Request status bits
|
||||
|
||||
kdev_t rq_dev DBI Target device
|
||||
|
||||
int errors DB Error counts
|
||||
|
||||
sector_t sector DBI Target location
|
||||
|
||||
unsigned long hard_nr_sectors B Used to keep sector sane
|
||||
|
||||
unsigned long nr_sectors DBI Total number of sectors in request
|
||||
|
||||
unsigned long hard_nr_sectors B Used to keep nr_sectors sane
|
||||
|
||||
unsigned short nr_phys_segments DB Number of physical scatter gather
|
||||
segments in a request
|
||||
|
||||
unsigned short nr_hw_segments DB Number of hardware scatter gather
|
||||
segments in a request
|
||||
|
||||
unsigned int current_nr_sectors DB Number of sectors in first segment
|
||||
of request
|
||||
|
||||
unsigned int hard_cur_sectors B Used to keep current_nr_sectors sane
|
||||
|
||||
int tag DB TCQ tag, if assigned
|
||||
|
||||
``void *special`` D Free to be used by driver
|
||||
|
||||
``char *buffer`` D Map of first segment, also see
|
||||
section on bouncing SECTION
|
||||
|
||||
``struct completion *waiting`` D Can be used by driver to get signalled
|
||||
on request completion
|
||||
|
||||
``struct bio *bio`` DBI First bio in request
|
||||
|
||||
``struct bio *biotail`` DBI Last bio in request
|
||||
|
||||
``struct request_queue *q`` DB Request queue this request belongs to
|
||||
|
||||
``struct request_list *rl`` B Request list this request came from
|
||||
=============================== ======= =======================================
|
@ -49,6 +49,7 @@ properties:
|
||||
|
||||
properties:
|
||||
data-lanes:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
required:
|
||||
|
@ -21,11 +21,22 @@ properties:
|
||||
|
||||
st,can-primary:
|
||||
description:
|
||||
Primary and secondary mode of the bxCAN peripheral is only relevant
|
||||
if the chip has two CAN peripherals. In that case they share some
|
||||
of the required logic.
|
||||
Primary mode of the bxCAN peripheral is only relevant if the chip has
|
||||
two CAN peripherals in dual CAN configuration. In that case they share
|
||||
some of the required logic.
|
||||
Not to be used if the peripheral is in single CAN configuration.
|
||||
To avoid misunderstandings, it should be noted that ST documentation
|
||||
uses the terms master/slave instead of primary/secondary.
|
||||
uses the terms master instead of primary.
|
||||
type: boolean
|
||||
|
||||
st,can-secondary:
|
||||
description:
|
||||
Secondary mode of the bxCAN peripheral is only relevant if the chip
|
||||
has two CAN peripherals in dual CAN configuration. In that case they
|
||||
share some of the required logic.
|
||||
Not to be used if the peripheral is in single CAN configuration.
|
||||
To avoid misunderstandings, it should be noted that ST documentation
|
||||
uses the terms slave instead of secondary.
|
||||
type: boolean
|
||||
|
||||
reg:
|
||||
|
@ -17,20 +17,11 @@ description:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 3
|
||||
items:
|
||||
- description: PCIe bridge clock.
|
||||
- description: PCIe bus clock.
|
||||
- description: PCIe PHY clock.
|
||||
- description: Additional required clock entry for imx6sx-pcie,
|
||||
imx6sx-pcie-ep, imx8mq-pcie, imx8mq-pcie-ep.
|
||||
maxItems: 4
|
||||
|
||||
clock-names:
|
||||
minItems: 3
|
||||
items:
|
||||
- const: pcie
|
||||
- const: pcie_bus
|
||||
- enum: [ pcie_phy, pcie_aux ]
|
||||
- enum: [ pcie_inbound_axi, pcie_aux ]
|
||||
maxItems: 4
|
||||
|
||||
num-lanes:
|
||||
const: 1
|
||||
|
@ -31,6 +31,19 @@ properties:
|
||||
- const: dbi
|
||||
- const: addr_space
|
||||
|
||||
clocks:
|
||||
minItems: 3
|
||||
items:
|
||||
- description: PCIe bridge clock.
|
||||
- description: PCIe bus clock.
|
||||
- description: PCIe PHY clock.
|
||||
- description: Additional required clock entry for imx6sx-pcie,
|
||||
imx6sx-pcie-ep, imx8mq-pcie, imx8mq-pcie-ep.
|
||||
|
||||
clock-names:
|
||||
minItems: 3
|
||||
maxItems: 4
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: builtin eDMA interrupter.
|
||||
@ -49,6 +62,31 @@ required:
|
||||
allOf:
|
||||
- $ref: /schemas/pci/snps,dw-pcie-ep.yaml#
|
||||
- $ref: /schemas/pci/fsl,imx6q-pcie-common.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- fsl,imx8mq-pcie-ep
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 4
|
||||
clock-names:
|
||||
items:
|
||||
- const: pcie
|
||||
- const: pcie_bus
|
||||
- const: pcie_phy
|
||||
- const: pcie_aux
|
||||
else:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 3
|
||||
clock-names:
|
||||
items:
|
||||
- const: pcie
|
||||
- const: pcie_bus
|
||||
- const: pcie_aux
|
||||
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
|
@ -40,6 +40,19 @@ properties:
|
||||
- const: dbi
|
||||
- const: config
|
||||
|
||||
clocks:
|
||||
minItems: 3
|
||||
items:
|
||||
- description: PCIe bridge clock.
|
||||
- description: PCIe bus clock.
|
||||
- description: PCIe PHY clock.
|
||||
- description: Additional required clock entry for imx6sx-pcie,
|
||||
imx6sx-pcie-ep, imx8mq-pcie, imx8mq-pcie-ep.
|
||||
|
||||
clock-names:
|
||||
minItems: 3
|
||||
maxItems: 4
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: builtin MSI controller.
|
||||
@ -77,6 +90,70 @@ required:
|
||||
allOf:
|
||||
- $ref: /schemas/pci/snps,dw-pcie.yaml#
|
||||
- $ref: /schemas/pci/fsl,imx6q-pcie-common.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- fsl,imx6sx-pcie
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 4
|
||||
clock-names:
|
||||
items:
|
||||
- const: pcie
|
||||
- const: pcie_bus
|
||||
- const: pcie_phy
|
||||
- const: pcie_inbound_axi
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- fsl,imx8mq-pcie
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 4
|
||||
clock-names:
|
||||
items:
|
||||
- const: pcie
|
||||
- const: pcie_bus
|
||||
- const: pcie_phy
|
||||
- const: pcie_aux
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- fsl,imx6q-pcie
|
||||
- fsl,imx6qp-pcie
|
||||
- fsl,imx7d-pcie
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 3
|
||||
clock-names:
|
||||
items:
|
||||
- const: pcie
|
||||
- const: pcie_bus
|
||||
- const: pcie_phy
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- fsl,imx8mm-pcie
|
||||
- fsl,imx8mp-pcie
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 3
|
||||
clock-names:
|
||||
items:
|
||||
- const: pcie
|
||||
- const: pcie_bus
|
||||
- const: pcie_aux
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
|
@ -1970,7 +1970,7 @@ F: Documentation/devicetree/bindings/nvmem/apple,efuses.yaml
|
||||
F: Documentation/devicetree/bindings/pci/apple,pcie.yaml
|
||||
F: Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
|
||||
F: Documentation/devicetree/bindings/power/apple*
|
||||
F: Documentation/devicetree/bindings/pwm/pwm-apple.yaml
|
||||
F: Documentation/devicetree/bindings/pwm/apple,s5l-fpwm.yaml
|
||||
F: Documentation/devicetree/bindings/watchdog/apple,wdt.yaml
|
||||
F: arch/arm64/boot/dts/apple/
|
||||
F: drivers/bluetooth/hci_bcm4377.c
|
||||
@ -6211,6 +6211,7 @@ X: Documentation/devicetree/
|
||||
X: Documentation/driver-api/media/
|
||||
X: Documentation/firmware-guide/acpi/
|
||||
X: Documentation/i2c/
|
||||
X: Documentation/netlink/
|
||||
X: Documentation/power/
|
||||
X: Documentation/spi/
|
||||
X: Documentation/userspace-api/media/
|
||||
@ -14572,6 +14573,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
|
||||
F: Documentation/devicetree/bindings/net/
|
||||
F: drivers/connector/
|
||||
F: drivers/net/
|
||||
X: drivers/net/wireless/
|
||||
F: include/dt-bindings/net/
|
||||
F: include/linux/etherdevice.h
|
||||
F: include/linux/fcdevice.h
|
||||
@ -14621,6 +14623,7 @@ B: mailto:netdev@vger.kernel.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
|
||||
F: Documentation/core-api/netlink.rst
|
||||
F: Documentation/netlink/
|
||||
F: Documentation/networking/
|
||||
F: Documentation/process/maintainer-netdev.rst
|
||||
F: Documentation/userspace-api/netlink/
|
||||
@ -14635,6 +14638,7 @@ F: include/uapi/linux/netdevice.h
|
||||
F: lib/net_utils.c
|
||||
F: lib/random32.c
|
||||
F: net/
|
||||
X: net/bluetooth/
|
||||
F: tools/net/
|
||||
F: tools/testing/selftests/net/
|
||||
|
||||
@ -18848,12 +18852,11 @@ F: drivers/target/
|
||||
F: include/target/
|
||||
|
||||
SCTP PROTOCOL
|
||||
M: Neil Horman <nhorman@tuxdriver.com>
|
||||
M: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
|
||||
M: Xin Long <lucien.xin@gmail.com>
|
||||
L: linux-sctp@vger.kernel.org
|
||||
S: Maintained
|
||||
W: http://lksctp.sourceforge.net
|
||||
W: https://github.com/sctp/lksctp-tools/wiki
|
||||
F: Documentation/networking/sctp.rst
|
||||
F: include/linux/sctp.h
|
||||
F: include/net/sctp/
|
||||
|
2
Makefile
2
Makefile
@ -2,7 +2,7 @@
|
||||
VERSION = 6
|
||||
PATCHLEVEL = 4
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc1
|
||||
EXTRAVERSION = -rc2
|
||||
NAME = Hurr durr I'ma ninja sloth
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
@ -387,6 +387,7 @@
|
||||
interrupt-names = "tx", "rx0", "rx1", "sce";
|
||||
resets = <&rcc STM32F4_APB1_RESET(CAN2)>;
|
||||
clocks = <&rcc 0 STM32F4_APB1_CLOCK(CAN2)>;
|
||||
st,can-secondary;
|
||||
st,gcan = <&gcan>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
@ -283,6 +283,88 @@
|
||||
slew-rate = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
can1_pins_a: can1-0 {
|
||||
pins1 {
|
||||
pinmux = <STM32_PINMUX('A', 12, AF9)>; /* CAN1_TX */
|
||||
};
|
||||
pins2 {
|
||||
pinmux = <STM32_PINMUX('A', 11, AF9)>; /* CAN1_RX */
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
can1_pins_b: can1-1 {
|
||||
pins1 {
|
||||
pinmux = <STM32_PINMUX('B', 9, AF9)>; /* CAN1_TX */
|
||||
};
|
||||
pins2 {
|
||||
pinmux = <STM32_PINMUX('B', 8, AF9)>; /* CAN1_RX */
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
can1_pins_c: can1-2 {
|
||||
pins1 {
|
||||
pinmux = <STM32_PINMUX('D', 1, AF9)>; /* CAN1_TX */
|
||||
};
|
||||
pins2 {
|
||||
pinmux = <STM32_PINMUX('D', 0, AF9)>; /* CAN1_RX */
|
||||
bias-pull-up;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
can1_pins_d: can1-3 {
|
||||
pins1 {
|
||||
pinmux = <STM32_PINMUX('H', 13, AF9)>; /* CAN1_TX */
|
||||
};
|
||||
pins2 {
|
||||
pinmux = <STM32_PINMUX('H', 14, AF9)>; /* CAN1_RX */
|
||||
bias-pull-up;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
can2_pins_a: can2-0 {
|
||||
pins1 {
|
||||
pinmux = <STM32_PINMUX('B', 6, AF9)>; /* CAN2_TX */
|
||||
};
|
||||
pins2 {
|
||||
pinmux = <STM32_PINMUX('B', 5, AF9)>; /* CAN2_RX */
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
can2_pins_b: can2-1 {
|
||||
pins1 {
|
||||
pinmux = <STM32_PINMUX('B', 13, AF9)>; /* CAN2_TX */
|
||||
};
|
||||
pins2 {
|
||||
pinmux = <STM32_PINMUX('B', 12, AF9)>; /* CAN2_RX */
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
can3_pins_a: can3-0 {
|
||||
pins1 {
|
||||
pinmux = <STM32_PINMUX('A', 15, AF11)>; /* CAN3_TX */
|
||||
};
|
||||
pins2 {
|
||||
pinmux = <STM32_PINMUX('A', 8, AF11)>; /* CAN3_RX */
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
can3_pins_b: can3-1 {
|
||||
pins1 {
|
||||
pinmux = <STM32_PINMUX('B', 4, AF11)>; /* CAN3_TX */
|
||||
};
|
||||
pins2 {
|
||||
pinmux = <STM32_PINMUX('B', 3, AF11)>; /* CAN3_RX */
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -308,6 +308,29 @@ static int unwind_exec_pop_subset_r0_to_r3(struct unwind_ctrl_block *ctrl,
|
||||
return URC_OK;
|
||||
}
|
||||
|
||||
static unsigned long unwind_decode_uleb128(struct unwind_ctrl_block *ctrl)
|
||||
{
|
||||
unsigned long bytes = 0;
|
||||
unsigned long insn;
|
||||
unsigned long result = 0;
|
||||
|
||||
/*
|
||||
* unwind_get_byte() will advance `ctrl` one instruction at a time, so
|
||||
* loop until we get an instruction byte where bit 7 is not set.
|
||||
*
|
||||
* Note: This decodes a maximum of 4 bytes to output 28 bits data where
|
||||
* max is 0xfffffff: that will cover a vsp increment of 1073742336, hence
|
||||
* it is sufficient for unwinding the stack.
|
||||
*/
|
||||
do {
|
||||
insn = unwind_get_byte(ctrl);
|
||||
result |= (insn & 0x7f) << (bytes * 7);
|
||||
bytes++;
|
||||
} while (!!(insn & 0x80) && (bytes != sizeof(result)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute the current unwind instruction.
|
||||
*/
|
||||
@ -361,7 +384,7 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl)
|
||||
if (ret)
|
||||
goto error;
|
||||
} else if (insn == 0xb2) {
|
||||
unsigned long uleb128 = unwind_get_byte(ctrl);
|
||||
unsigned long uleb128 = unwind_decode_uleb128(ctrl);
|
||||
|
||||
ctrl->vrs[SP] += 0x204 + (uleb128 << 2);
|
||||
} else {
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/**
|
||||
/*
|
||||
* arch/arm/mac-sa1100/jornada720_ssp.c
|
||||
*
|
||||
* Copyright (C) 2006/2007 Kristoffer Ericson <Kristoffer.Ericson@gmail.com>
|
||||
@ -26,6 +26,7 @@ static unsigned long jornada_ssp_flags;
|
||||
|
||||
/**
|
||||
* jornada_ssp_reverse - reverses input byte
|
||||
* @byte: input byte to reverse
|
||||
*
|
||||
* we need to reverse all data we receive from the mcu due to its physical location
|
||||
* returns : 01110111 -> 11101110
|
||||
@ -46,6 +47,7 @@ EXPORT_SYMBOL(jornada_ssp_reverse);
|
||||
|
||||
/**
|
||||
* jornada_ssp_byte - waits for ready ssp bus and sends byte
|
||||
* @byte: input byte to transmit
|
||||
*
|
||||
* waits for fifo buffer to clear and then transmits, if it doesn't then we will
|
||||
* timeout after <timeout> rounds. Needs mcu running before its called.
|
||||
@ -77,6 +79,7 @@ EXPORT_SYMBOL(jornada_ssp_byte);
|
||||
|
||||
/**
|
||||
* jornada_ssp_inout - decide if input is command or trading byte
|
||||
* @byte: input byte to send (may be %TXDUMMY)
|
||||
*
|
||||
* returns : (jornada_ssp_byte(byte)) on success
|
||||
* : %-ETIMEDOUT on timeout failure
|
||||
|
@ -23,6 +23,9 @@
|
||||
@
|
||||
ENTRY(do_vfp)
|
||||
mov r1, r10
|
||||
mov r3, r9
|
||||
b vfp_entry
|
||||
str lr, [sp, #-8]!
|
||||
add r3, sp, #4
|
||||
str r9, [r3]
|
||||
bl vfp_entry
|
||||
ldr pc, [sp], #8
|
||||
ENDPROC(do_vfp)
|
||||
|
@ -172,13 +172,14 @@ vfp_hw_state_valid:
|
||||
@ out before setting an FPEXC that
|
||||
@ stops us reading stuff
|
||||
VFPFMXR FPEXC, r1 @ Restore FPEXC last
|
||||
mov sp, r3 @ we think we have handled things
|
||||
pop {lr}
|
||||
sub r2, r2, #4 @ Retry current instruction - if Thumb
|
||||
str r2, [sp, #S_PC] @ mode it's two 16-bit instructions,
|
||||
@ else it's one 32-bit instruction, so
|
||||
@ always subtract 4 from the following
|
||||
@ instruction address.
|
||||
|
||||
mov lr, r3 @ we think we have handled things
|
||||
local_bh_enable_and_ret:
|
||||
adr r0, .
|
||||
mov r1, #SOFTIRQ_DISABLE_OFFSET
|
||||
@ -209,8 +210,9 @@ skip:
|
||||
|
||||
process_exception:
|
||||
DBGSTR "bounce"
|
||||
mov sp, r3 @ setup for a return to the user code.
|
||||
pop {lr}
|
||||
mov r2, sp @ nothing stacked - regdump is at TOS
|
||||
mov lr, r3 @ setup for a return to the user code.
|
||||
|
||||
@ Now call the C code to package up the bounce to the support code
|
||||
@ r0 holds the trigger instruction
|
||||
|
@ -413,12 +413,12 @@ extern void paging_init (void);
|
||||
* For the 64bit version, the offset is extended by 32bit.
|
||||
*/
|
||||
#define __swp_type(x) ((x).val & 0x1f)
|
||||
#define __swp_offset(x) ( (((x).val >> 6) & 0x7) | \
|
||||
(((x).val >> 8) & ~0x7) )
|
||||
#define __swp_offset(x) ( (((x).val >> 5) & 0x7) | \
|
||||
(((x).val >> 10) << 3) )
|
||||
#define __swp_entry(type, offset) ((swp_entry_t) { \
|
||||
((type) & 0x1f) | \
|
||||
((offset & 0x7) << 6) | \
|
||||
((offset & ~0x7) << 8) })
|
||||
((offset & 0x7) << 5) | \
|
||||
((offset >> 3) << 10) })
|
||||
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
|
||||
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
|
||||
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include <linux/console.h>
|
||||
#include <linux/kexec.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/sections.h>
|
||||
|
||||
|
@ -22,7 +22,7 @@ KCOV_INSTRUMENT := n
|
||||
|
||||
$(obj)/%.pi.o: OBJCOPYFLAGS := --prefix-symbols=__pi_ \
|
||||
--remove-section=.note.gnu.property \
|
||||
--prefix-alloc-sections=.init
|
||||
--prefix-alloc-sections=.init.pi
|
||||
$(obj)/%.pi.o: $(obj)/%.o FORCE
|
||||
$(call if_changed,objcopy)
|
||||
|
||||
|
@ -84,11 +84,8 @@ SECTIONS
|
||||
__init_data_begin = .;
|
||||
INIT_DATA_SECTION(16)
|
||||
|
||||
/* Those sections result from the compilation of kernel/pi/string.c */
|
||||
.init.pidata : {
|
||||
*(.init.srodata.cst8*)
|
||||
*(.init__bug_table*)
|
||||
*(.init.sdata*)
|
||||
.init.pi : {
|
||||
*(.init.pi*)
|
||||
}
|
||||
|
||||
.init.bss : {
|
||||
|
@ -1703,10 +1703,8 @@ int x86_pmu_handle_irq(struct pt_regs *regs)
|
||||
|
||||
perf_sample_data_init(&data, 0, event->hw.last_period);
|
||||
|
||||
if (has_branch_stack(event)) {
|
||||
data.br_stack = &cpuc->lbr_stack;
|
||||
data.sample_flags |= PERF_SAMPLE_BRANCH_STACK;
|
||||
}
|
||||
if (has_branch_stack(event))
|
||||
perf_sample_save_brstack(&data, event, &cpuc->lbr_stack);
|
||||
|
||||
if (perf_event_overflow(event, &data, regs))
|
||||
x86_pmu_stop(event, 0);
|
||||
|
@ -1229,12 +1229,14 @@ pebs_update_state(bool needed_cb, struct cpu_hw_events *cpuc,
|
||||
struct perf_event *event, bool add)
|
||||
{
|
||||
struct pmu *pmu = event->pmu;
|
||||
|
||||
/*
|
||||
* Make sure we get updated with the first PEBS
|
||||
* event. It will trigger also during removal, but
|
||||
* that does not hurt:
|
||||
*/
|
||||
bool update = cpuc->n_pebs == 1;
|
||||
if (cpuc->n_pebs == 1)
|
||||
cpuc->pebs_data_cfg = PEBS_UPDATE_DS_SW;
|
||||
|
||||
if (needed_cb != pebs_needs_sched_cb(cpuc)) {
|
||||
if (!needed_cb)
|
||||
@ -1242,7 +1244,7 @@ pebs_update_state(bool needed_cb, struct cpu_hw_events *cpuc,
|
||||
else
|
||||
perf_sched_cb_dec(pmu);
|
||||
|
||||
update = true;
|
||||
cpuc->pebs_data_cfg |= PEBS_UPDATE_DS_SW;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1252,24 +1254,13 @@ pebs_update_state(bool needed_cb, struct cpu_hw_events *cpuc,
|
||||
if (x86_pmu.intel_cap.pebs_baseline && add) {
|
||||
u64 pebs_data_cfg;
|
||||
|
||||
/* Clear pebs_data_cfg and pebs_record_size for first PEBS. */
|
||||
if (cpuc->n_pebs == 1) {
|
||||
cpuc->pebs_data_cfg = 0;
|
||||
cpuc->pebs_record_size = sizeof(struct pebs_basic);
|
||||
}
|
||||
|
||||
pebs_data_cfg = pebs_update_adaptive_cfg(event);
|
||||
|
||||
/* Update pebs_record_size if new event requires more data. */
|
||||
if (pebs_data_cfg & ~cpuc->pebs_data_cfg) {
|
||||
cpuc->pebs_data_cfg |= pebs_data_cfg;
|
||||
adaptive_pebs_record_size_update();
|
||||
update = true;
|
||||
}
|
||||
/*
|
||||
* Be sure to update the thresholds when we change the record.
|
||||
*/
|
||||
if (pebs_data_cfg & ~cpuc->pebs_data_cfg)
|
||||
cpuc->pebs_data_cfg |= pebs_data_cfg | PEBS_UPDATE_DS_SW;
|
||||
}
|
||||
|
||||
if (update)
|
||||
pebs_update_threshold(cpuc);
|
||||
}
|
||||
|
||||
void intel_pmu_pebs_add(struct perf_event *event)
|
||||
@ -1326,9 +1317,17 @@ static void intel_pmu_pebs_via_pt_enable(struct perf_event *event)
|
||||
wrmsrl(base + idx, value);
|
||||
}
|
||||
|
||||
static inline void intel_pmu_drain_large_pebs(struct cpu_hw_events *cpuc)
|
||||
{
|
||||
if (cpuc->n_pebs == cpuc->n_large_pebs &&
|
||||
cpuc->n_pebs != cpuc->n_pebs_via_pt)
|
||||
intel_pmu_drain_pebs_buffer();
|
||||
}
|
||||
|
||||
void intel_pmu_pebs_enable(struct perf_event *event)
|
||||
{
|
||||
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
|
||||
u64 pebs_data_cfg = cpuc->pebs_data_cfg & ~PEBS_UPDATE_DS_SW;
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
struct debug_store *ds = cpuc->ds;
|
||||
unsigned int idx = hwc->idx;
|
||||
@ -1344,11 +1343,22 @@ void intel_pmu_pebs_enable(struct perf_event *event)
|
||||
|
||||
if (x86_pmu.intel_cap.pebs_baseline) {
|
||||
hwc->config |= ICL_EVENTSEL_ADAPTIVE;
|
||||
if (cpuc->pebs_data_cfg != cpuc->active_pebs_data_cfg) {
|
||||
wrmsrl(MSR_PEBS_DATA_CFG, cpuc->pebs_data_cfg);
|
||||
cpuc->active_pebs_data_cfg = cpuc->pebs_data_cfg;
|
||||
if (pebs_data_cfg != cpuc->active_pebs_data_cfg) {
|
||||
/*
|
||||
* drain_pebs() assumes uniform record size;
|
||||
* hence we need to drain when changing said
|
||||
* size.
|
||||
*/
|
||||
intel_pmu_drain_large_pebs(cpuc);
|
||||
adaptive_pebs_record_size_update();
|
||||
wrmsrl(MSR_PEBS_DATA_CFG, pebs_data_cfg);
|
||||
cpuc->active_pebs_data_cfg = pebs_data_cfg;
|
||||
}
|
||||
}
|
||||
if (cpuc->pebs_data_cfg & PEBS_UPDATE_DS_SW) {
|
||||
cpuc->pebs_data_cfg = pebs_data_cfg;
|
||||
pebs_update_threshold(cpuc);
|
||||
}
|
||||
|
||||
if (idx >= INTEL_PMC_IDX_FIXED) {
|
||||
if (x86_pmu.intel_cap.pebs_format < 5)
|
||||
@ -1391,9 +1401,7 @@ void intel_pmu_pebs_disable(struct perf_event *event)
|
||||
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
|
||||
if (cpuc->n_pebs == cpuc->n_large_pebs &&
|
||||
cpuc->n_pebs != cpuc->n_pebs_via_pt)
|
||||
intel_pmu_drain_pebs_buffer();
|
||||
intel_pmu_drain_large_pebs(cpuc);
|
||||
|
||||
cpuc->pebs_enabled &= ~(1ULL << hwc->idx);
|
||||
|
||||
|
@ -121,6 +121,9 @@
|
||||
#define PEBS_DATACFG_LBRS BIT_ULL(3)
|
||||
#define PEBS_DATACFG_LBR_SHIFT 24
|
||||
|
||||
/* Steal the highest bit of pebs_data_cfg for SW usage */
|
||||
#define PEBS_UPDATE_DS_SW BIT_ULL(63)
|
||||
|
||||
/*
|
||||
* Intel "Architectural Performance Monitoring" CPUID
|
||||
* detection/enumeration details:
|
||||
|
@ -36,6 +36,7 @@
|
||||
#define PCI_DEVICE_ID_AMD_19H_M50H_DF_F4 0x166e
|
||||
#define PCI_DEVICE_ID_AMD_19H_M60H_DF_F4 0x14e4
|
||||
#define PCI_DEVICE_ID_AMD_19H_M70H_DF_F4 0x14f4
|
||||
#define PCI_DEVICE_ID_AMD_19H_M78H_DF_F4 0x12fc
|
||||
|
||||
/* Protect the PCI config register pairs used for SMN. */
|
||||
static DEFINE_MUTEX(smn_mutex);
|
||||
@ -79,6 +80,7 @@ static const struct pci_device_id amd_nb_misc_ids[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M50H_DF_F3) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M60H_DF_F3) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M70H_DF_F3) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M78H_DF_F3) },
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -144,8 +144,8 @@ SYM_CODE_END(__x86_indirect_jump_thunk_array)
|
||||
*/
|
||||
.align 64
|
||||
.skip 63, 0xcc
|
||||
SYM_FUNC_START_NOALIGN(zen_untrain_ret);
|
||||
|
||||
SYM_START(zen_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE)
|
||||
ANNOTATE_NOENDBR
|
||||
/*
|
||||
* As executed from zen_untrain_ret, this is:
|
||||
*
|
||||
|
@ -1666,7 +1666,7 @@ static int nbd_dev_dbg_init(struct nbd_device *nbd)
|
||||
return -EIO;
|
||||
|
||||
dir = debugfs_create_dir(nbd_name(nbd), nbd_dbg_dir);
|
||||
if (!dir) {
|
||||
if (IS_ERR(dir)) {
|
||||
dev_err(nbd_to_dev(nbd), "Failed to create debugfs dir for '%s'\n",
|
||||
nbd_name(nbd));
|
||||
return -EIO;
|
||||
@ -1692,7 +1692,7 @@ static int nbd_dbg_init(void)
|
||||
struct dentry *dbg_dir;
|
||||
|
||||
dbg_dir = debugfs_create_dir("nbd", NULL);
|
||||
if (!dbg_dir)
|
||||
if (IS_ERR(dbg_dir))
|
||||
return -EIO;
|
||||
|
||||
nbd_dbg_dir = dbg_dir;
|
||||
|
@ -241,7 +241,7 @@ static inline blk_opf_t rnbd_to_bio_flags(u32 rnbd_opf)
|
||||
bio_opf = REQ_OP_WRITE;
|
||||
break;
|
||||
case RNBD_OP_FLUSH:
|
||||
bio_opf = REQ_OP_FLUSH | REQ_PREFLUSH;
|
||||
bio_opf = REQ_OP_WRITE | REQ_PREFLUSH;
|
||||
break;
|
||||
case RNBD_OP_DISCARD:
|
||||
bio_opf = REQ_OP_DISCARD;
|
||||
|
@ -1281,7 +1281,7 @@ static inline int ublk_check_cmd_op(u32 cmd_op)
|
||||
{
|
||||
u32 ioc_type = _IOC_TYPE(cmd_op);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BLKDEV_UBLK_LEGACY_OPCODES) && ioc_type != 'u')
|
||||
if (!IS_ENABLED(CONFIG_BLKDEV_UBLK_LEGACY_OPCODES) && ioc_type != 'u')
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (ioc_type != 'u' && ioc_type != 0)
|
||||
|
@ -571,6 +571,10 @@ static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
|
||||
{
|
||||
struct tpm_chip *chip = container_of(rng, struct tpm_chip, hwrng);
|
||||
|
||||
/* Give back zero bytes, as TPM chip has not yet fully resumed: */
|
||||
if (chip->flags & TPM_CHIP_FLAG_SUSPENDED)
|
||||
return 0;
|
||||
|
||||
return tpm_get_random(chip, data, max);
|
||||
}
|
||||
|
||||
|
@ -412,6 +412,8 @@ int tpm_pm_suspend(struct device *dev)
|
||||
}
|
||||
|
||||
suspended:
|
||||
chip->flags |= TPM_CHIP_FLAG_SUSPENDED;
|
||||
|
||||
if (rc)
|
||||
dev_err(dev, "Ignoring error %d while suspending\n", rc);
|
||||
return 0;
|
||||
@ -429,6 +431,14 @@ int tpm_pm_resume(struct device *dev)
|
||||
if (chip == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
chip->flags &= ~TPM_CHIP_FLAG_SUSPENDED;
|
||||
|
||||
/*
|
||||
* Guarantee that SUSPENDED is written last, so that hwrng does not
|
||||
* activate before the chip has been fully resumed.
|
||||
*/
|
||||
wmb();
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tpm_pm_resume);
|
||||
|
@ -122,6 +122,22 @@ static const struct dmi_system_id tpm_tis_dmi_table[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T490s"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = tpm_tis_disable_irq,
|
||||
.ident = "ThinkStation P360 Tiny",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkStation P360 Tiny"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = tpm_tis_disable_irq,
|
||||
.ident = "ThinkPad L490",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L490"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -1209,25 +1209,20 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
|
||||
u32 intmask;
|
||||
int rc;
|
||||
|
||||
if (chip->ops->clk_enable != NULL)
|
||||
chip->ops->clk_enable(chip, true);
|
||||
|
||||
/* reenable interrupts that device may have lost or
|
||||
* BIOS/firmware may have disabled
|
||||
/*
|
||||
* Re-enable interrupts that device may have lost or BIOS/firmware may
|
||||
* have disabled.
|
||||
*/
|
||||
rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), priv->irq);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
if (rc < 0) {
|
||||
dev_err(&chip->dev, "Setting IRQ failed.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
intmask = priv->int_mask | TPM_GLOBAL_INT_ENABLE;
|
||||
|
||||
tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
|
||||
|
||||
out:
|
||||
if (chip->ops->clk_enable != NULL)
|
||||
chip->ops->clk_enable(chip, false);
|
||||
|
||||
return;
|
||||
rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
|
||||
if (rc < 0)
|
||||
dev_err(&chip->dev, "Enabling interrupts failed.\n");
|
||||
}
|
||||
|
||||
int tpm_tis_resume(struct device *dev)
|
||||
@ -1235,27 +1230,27 @@ int tpm_tis_resume(struct device *dev)
|
||||
struct tpm_chip *chip = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = tpm_tis_request_locality(chip, 0);
|
||||
if (ret < 0)
|
||||
ret = tpm_chip_start(chip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (chip->flags & TPM_CHIP_FLAG_IRQ)
|
||||
tpm_tis_reenable_interrupts(chip);
|
||||
|
||||
ret = tpm_pm_resume(dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* TPM 1.2 requires self-test on resume. This function actually returns
|
||||
* an error code but for unknown reason it isn't handled.
|
||||
*/
|
||||
if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
|
||||
tpm1_do_selftest(chip);
|
||||
out:
|
||||
tpm_tis_relinquish_locality(chip, 0);
|
||||
|
||||
return ret;
|
||||
tpm_chip_stop(chip);
|
||||
|
||||
ret = tpm_pm_resume(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tpm_tis_resume);
|
||||
#endif
|
||||
|
@ -571,6 +571,7 @@ void read_cdat_data(struct cxl_port *port)
|
||||
/* Don't leave table data allocated on error */
|
||||
devm_kfree(dev, cdat_table);
|
||||
dev_err(dev, "CDAT data read error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
port->cdat.table = cdat_table + sizeof(__le32);
|
||||
|
@ -706,21 +706,22 @@ static void fwnet_receive_packet(struct fw_card *card, struct fw_request *r,
|
||||
int rcode;
|
||||
|
||||
if (destination == IEEE1394_ALL_NODES) {
|
||||
kfree(r);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (offset != dev->handler.offset)
|
||||
// Although the response to the broadcast packet is not necessarily required, the
|
||||
// fw_send_response() function should still be called to maintain the reference
|
||||
// counting of the object. In the case, the call of function just releases the
|
||||
// object as a result to decrease the reference counting.
|
||||
rcode = RCODE_COMPLETE;
|
||||
} else if (offset != dev->handler.offset) {
|
||||
rcode = RCODE_ADDRESS_ERROR;
|
||||
else if (tcode != TCODE_WRITE_BLOCK_REQUEST)
|
||||
} else if (tcode != TCODE_WRITE_BLOCK_REQUEST) {
|
||||
rcode = RCODE_TYPE_ERROR;
|
||||
else if (fwnet_incoming_packet(dev, payload, length,
|
||||
source, generation, false) != 0) {
|
||||
} else if (fwnet_incoming_packet(dev, payload, length,
|
||||
source, generation, false) != 0) {
|
||||
dev_err(&dev->netdev->dev, "incoming packet failure\n");
|
||||
rcode = RCODE_CONFLICT_ERROR;
|
||||
} else
|
||||
} else {
|
||||
rcode = RCODE_COMPLETE;
|
||||
}
|
||||
|
||||
fw_send_response(card, r, rcode);
|
||||
}
|
||||
|
@ -51,7 +51,8 @@ __init bool sysfb_parse_mode(const struct screen_info *si,
|
||||
*
|
||||
* It's not easily possible to fix this in struct screen_info,
|
||||
* as this could break UAPI. The best solution is to compute
|
||||
* bits_per_pixel here and ignore lfb_depth. In the loop below,
|
||||
* bits_per_pixel from the color bits, reserved bits and
|
||||
* reported lfb_depth, whichever is highest. In the loop below,
|
||||
* ignore simplefb formats with alpha bits, as EFI and VESA
|
||||
* don't specify alpha channels.
|
||||
*/
|
||||
@ -60,6 +61,7 @@ __init bool sysfb_parse_mode(const struct screen_info *si,
|
||||
si->green_size + si->green_pos,
|
||||
si->blue_size + si->blue_pos),
|
||||
si->rsvd_size + si->rsvd_pos);
|
||||
bits_per_pixel = max_t(u32, bits_per_pixel, si->lfb_depth);
|
||||
} else {
|
||||
bits_per_pixel = si->lfb_depth;
|
||||
}
|
||||
|
@ -3757,6 +3757,12 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
||||
adev->have_atomics_support = ((struct amd_sriov_msg_pf2vf_info *)
|
||||
adev->virt.fw_reserve.p_pf2vf)->pcie_atomic_ops_support_flags ==
|
||||
(PCI_EXP_DEVCAP2_ATOMIC_COMP32 | PCI_EXP_DEVCAP2_ATOMIC_COMP64);
|
||||
/* APUs w/ gfx9 onwards doesn't reply on PCIe atomics, rather it is a
|
||||
* internal path natively support atomics, set have_atomics_support to true.
|
||||
*/
|
||||
else if ((adev->flags & AMD_IS_APU) &&
|
||||
(adev->ip_versions[GC_HWIP][0] > IP_VERSION(9, 0, 0)))
|
||||
adev->have_atomics_support = true;
|
||||
else
|
||||
adev->have_atomics_support =
|
||||
!pci_enable_atomic_ops_to_root(adev->pdev,
|
||||
@ -4506,7 +4512,11 @@ static int amdgpu_device_recover_vram(struct amdgpu_device *adev)
|
||||
dev_info(adev->dev, "recover vram bo from shadow start\n");
|
||||
mutex_lock(&adev->shadow_list_lock);
|
||||
list_for_each_entry(vmbo, &adev->shadow_list, shadow_list) {
|
||||
shadow = &vmbo->bo;
|
||||
/* If vm is compute context or adev is APU, shadow will be NULL */
|
||||
if (!vmbo->shadow)
|
||||
continue;
|
||||
shadow = vmbo->shadow;
|
||||
|
||||
/* No need to recover an evicted BO */
|
||||
if (shadow->tbo.resource->mem_type != TTM_PL_TT ||
|
||||
shadow->tbo.resource->start == AMDGPU_BO_INVALID_OFFSET ||
|
||||
|
@ -687,9 +687,11 @@ int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *r
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_irq_get(adev, &adev->gfx.cp_ecc_error_irq, 0);
|
||||
if (r)
|
||||
goto late_fini;
|
||||
if (adev->gfx.cp_ecc_error_irq.funcs) {
|
||||
r = amdgpu_irq_get(adev, &adev->gfx.cp_ecc_error_irq, 0);
|
||||
if (r)
|
||||
goto late_fini;
|
||||
}
|
||||
} else {
|
||||
amdgpu_ras_feature_enable_on_boot(adev, ras_block, 0);
|
||||
}
|
||||
|
@ -1315,13 +1315,6 @@ static int gfx_v11_0_sw_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* ECC error */
|
||||
r = amdgpu_irq_add_id(adev, SOC21_IH_CLIENTID_GRBM_CP,
|
||||
GFX_11_0_0__SRCID__CP_ECC_ERROR,
|
||||
&adev->gfx.cp_ecc_error_irq);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* FED error */
|
||||
r = amdgpu_irq_add_id(adev, SOC21_IH_CLIENTID_GFX,
|
||||
GFX_11_0_0__SRCID__RLC_GC_FED_INTERRUPT,
|
||||
@ -4444,7 +4437,6 @@ static int gfx_v11_0_hw_fini(void *handle)
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int r;
|
||||
|
||||
amdgpu_irq_put(adev, &adev->gfx.cp_ecc_error_irq, 0);
|
||||
amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
|
||||
amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
|
||||
|
||||
@ -5897,36 +5889,6 @@ static void gfx_v11_0_set_compute_eop_interrupt_state(struct amdgpu_device *adev
|
||||
}
|
||||
}
|
||||
|
||||
#define CP_ME1_PIPE_INST_ADDR_INTERVAL 0x1
|
||||
#define SET_ECC_ME_PIPE_STATE(reg_addr, state) \
|
||||
do { \
|
||||
uint32_t tmp = RREG32_SOC15_IP(GC, reg_addr); \
|
||||
tmp = REG_SET_FIELD(tmp, CP_ME1_PIPE0_INT_CNTL, CP_ECC_ERROR_INT_ENABLE, state); \
|
||||
WREG32_SOC15_IP(GC, reg_addr, tmp); \
|
||||
} while (0)
|
||||
|
||||
static int gfx_v11_0_set_cp_ecc_error_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned type,
|
||||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
uint32_t ecc_irq_state = 0;
|
||||
uint32_t pipe0_int_cntl_addr = 0;
|
||||
int i = 0;
|
||||
|
||||
ecc_irq_state = (state == AMDGPU_IRQ_STATE_ENABLE) ? 1 : 0;
|
||||
|
||||
pipe0_int_cntl_addr = SOC15_REG_OFFSET(GC, 0, regCP_ME1_PIPE0_INT_CNTL);
|
||||
|
||||
WREG32_FIELD15_PREREG(GC, 0, CP_INT_CNTL_RING0, CP_ECC_ERROR_INT_ENABLE, ecc_irq_state);
|
||||
|
||||
for (i = 0; i < adev->gfx.mec.num_pipe_per_mec; i++)
|
||||
SET_ECC_ME_PIPE_STATE(pipe0_int_cntl_addr + i * CP_ME1_PIPE_INST_ADDR_INTERVAL,
|
||||
ecc_irq_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gfx_v11_0_set_eop_interrupt_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *src,
|
||||
unsigned type,
|
||||
@ -6341,11 +6303,6 @@ static const struct amdgpu_irq_src_funcs gfx_v11_0_priv_inst_irq_funcs = {
|
||||
.process = gfx_v11_0_priv_inst_irq,
|
||||
};
|
||||
|
||||
static const struct amdgpu_irq_src_funcs gfx_v11_0_cp_ecc_error_irq_funcs = {
|
||||
.set = gfx_v11_0_set_cp_ecc_error_state,
|
||||
.process = amdgpu_gfx_cp_ecc_error_irq,
|
||||
};
|
||||
|
||||
static const struct amdgpu_irq_src_funcs gfx_v11_0_rlc_gc_fed_irq_funcs = {
|
||||
.process = gfx_v11_0_rlc_gc_fed_irq,
|
||||
};
|
||||
@ -6361,9 +6318,6 @@ static void gfx_v11_0_set_irq_funcs(struct amdgpu_device *adev)
|
||||
adev->gfx.priv_inst_irq.num_types = 1;
|
||||
adev->gfx.priv_inst_irq.funcs = &gfx_v11_0_priv_inst_irq_funcs;
|
||||
|
||||
adev->gfx.cp_ecc_error_irq.num_types = 1; /* CP ECC error */
|
||||
adev->gfx.cp_ecc_error_irq.funcs = &gfx_v11_0_cp_ecc_error_irq_funcs;
|
||||
|
||||
adev->gfx.rlc_gc_fed_irq.num_types = 1; /* 0x80 FED error */
|
||||
adev->gfx.rlc_gc_fed_irq.funcs = &gfx_v11_0_rlc_gc_fed_irq_funcs;
|
||||
|
||||
|
@ -3764,7 +3764,8 @@ static int gfx_v9_0_hw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
amdgpu_irq_put(adev, &adev->gfx.cp_ecc_error_irq, 0);
|
||||
if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX))
|
||||
amdgpu_irq_put(adev, &adev->gfx.cp_ecc_error_irq, 0);
|
||||
amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
|
||||
amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
|
||||
|
||||
|
@ -54,6 +54,7 @@ static int jpeg_v3_0_early_init(void *handle)
|
||||
|
||||
switch (adev->ip_versions[UVD_HWIP][0]) {
|
||||
case IP_VERSION(3, 1, 1):
|
||||
case IP_VERSION(3, 1, 2):
|
||||
break;
|
||||
default:
|
||||
harvest = RREG32_SOC15(JPEG, 0, mmCC_UVD_HARVESTING);
|
||||
|
@ -98,6 +98,16 @@ static const struct amdgpu_video_codecs nv_video_codecs_decode =
|
||||
};
|
||||
|
||||
/* Sienna Cichlid */
|
||||
static const struct amdgpu_video_codec_info sc_video_codecs_encode_array[] = {
|
||||
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2160, 0)},
|
||||
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 7680, 4352, 0)},
|
||||
};
|
||||
|
||||
static const struct amdgpu_video_codecs sc_video_codecs_encode = {
|
||||
.codec_count = ARRAY_SIZE(sc_video_codecs_encode_array),
|
||||
.codec_array = sc_video_codecs_encode_array,
|
||||
};
|
||||
|
||||
static const struct amdgpu_video_codec_info sc_video_codecs_decode_array_vcn0[] =
|
||||
{
|
||||
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)},
|
||||
@ -136,8 +146,8 @@ static const struct amdgpu_video_codecs sc_video_codecs_decode_vcn1 =
|
||||
/* SRIOV Sienna Cichlid, not const since data is controlled by host */
|
||||
static struct amdgpu_video_codec_info sriov_sc_video_codecs_encode_array[] =
|
||||
{
|
||||
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2304, 0)},
|
||||
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 2304, 0)},
|
||||
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2160, 0)},
|
||||
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 7680, 4352, 0)},
|
||||
};
|
||||
|
||||
static struct amdgpu_video_codec_info sriov_sc_video_codecs_decode_array_vcn0[] =
|
||||
@ -237,12 +247,12 @@ static int nv_query_video_codecs(struct amdgpu_device *adev, bool encode,
|
||||
} else {
|
||||
if (adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) {
|
||||
if (encode)
|
||||
*codecs = &nv_video_codecs_encode;
|
||||
*codecs = &sc_video_codecs_encode;
|
||||
else
|
||||
*codecs = &sc_video_codecs_decode_vcn1;
|
||||
} else {
|
||||
if (encode)
|
||||
*codecs = &nv_video_codecs_encode;
|
||||
*codecs = &sc_video_codecs_encode;
|
||||
else
|
||||
*codecs = &sc_video_codecs_decode_vcn0;
|
||||
}
|
||||
@ -251,14 +261,14 @@ static int nv_query_video_codecs(struct amdgpu_device *adev, bool encode,
|
||||
case IP_VERSION(3, 0, 16):
|
||||
case IP_VERSION(3, 0, 2):
|
||||
if (encode)
|
||||
*codecs = &nv_video_codecs_encode;
|
||||
*codecs = &sc_video_codecs_encode;
|
||||
else
|
||||
*codecs = &sc_video_codecs_decode_vcn0;
|
||||
return 0;
|
||||
case IP_VERSION(3, 1, 1):
|
||||
case IP_VERSION(3, 1, 2):
|
||||
if (encode)
|
||||
*codecs = &nv_video_codecs_encode;
|
||||
*codecs = &sc_video_codecs_encode;
|
||||
else
|
||||
*codecs = &yc_video_codecs_decode;
|
||||
return 0;
|
||||
|
@ -1917,9 +1917,11 @@ static int sdma_v4_0_hw_fini(void *handle)
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < adev->sdma.num_instances; i++) {
|
||||
amdgpu_irq_put(adev, &adev->sdma.ecc_irq,
|
||||
AMDGPU_SDMA_IRQ_INSTANCE0 + i);
|
||||
if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__SDMA)) {
|
||||
for (i = 0; i < adev->sdma.num_instances; i++) {
|
||||
amdgpu_irq_put(adev, &adev->sdma.ecc_irq,
|
||||
AMDGPU_SDMA_IRQ_INSTANCE0 + i);
|
||||
}
|
||||
}
|
||||
|
||||
sdma_v4_0_ctx_switch_enable(adev, false);
|
||||
|
@ -711,7 +711,7 @@ static int soc21_common_early_init(void *handle)
|
||||
AMD_PG_SUPPORT_VCN_DPG |
|
||||
AMD_PG_SUPPORT_GFX_PG |
|
||||
AMD_PG_SUPPORT_JPEG;
|
||||
adev->external_rev_id = adev->rev_id + 0x1;
|
||||
adev->external_rev_id = adev->rev_id + 0x80;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -423,3 +423,68 @@ void dcn314_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool
|
||||
|
||||
PERF_TRACE();
|
||||
}
|
||||
static void apply_symclk_on_tx_off_wa(struct dc_link *link)
|
||||
{
|
||||
/* There are use cases where SYMCLK is referenced by OTG. For instance
|
||||
* for TMDS signal, OTG relies SYMCLK even if TX video output is off.
|
||||
* However current link interface will power off PHY when disabling link
|
||||
* output. This will turn off SYMCLK generated by PHY. The workaround is
|
||||
* to identify such case where SYMCLK is still in use by OTG when we
|
||||
* power off PHY. When this is detected, we will temporarily power PHY
|
||||
* back on and move PHY's SYMCLK state to SYMCLK_ON_TX_OFF by calling
|
||||
* program_pix_clk interface. When OTG is disabled, we will then power
|
||||
* off PHY by calling disable link output again.
|
||||
*
|
||||
* In future dcn generations, we plan to rework transmitter control
|
||||
* interface so that we could have an option to set SYMCLK ON TX OFF
|
||||
* state in one step without this workaround
|
||||
*/
|
||||
|
||||
struct dc *dc = link->ctx->dc;
|
||||
struct pipe_ctx *pipe_ctx = NULL;
|
||||
uint8_t i;
|
||||
|
||||
if (link->phy_state.symclk_ref_cnts.otg > 0) {
|
||||
for (i = 0; i < MAX_PIPES; i++) {
|
||||
pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
|
||||
if (pipe_ctx->stream && pipe_ctx->stream->link == link && pipe_ctx->top_pipe == NULL) {
|
||||
pipe_ctx->clock_source->funcs->program_pix_clk(
|
||||
pipe_ctx->clock_source,
|
||||
&pipe_ctx->stream_res.pix_clk_params,
|
||||
dc->link_srv->dp_get_encoding_format(
|
||||
&pipe_ctx->link_config.dp_link_settings),
|
||||
&pipe_ctx->pll_settings);
|
||||
link->phy_state.symclk_state = SYMCLK_ON_TX_OFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dcn314_disable_link_output(struct dc_link *link,
|
||||
const struct link_resource *link_res,
|
||||
enum signal_type signal)
|
||||
{
|
||||
struct dc *dc = link->ctx->dc;
|
||||
const struct link_hwss *link_hwss = get_link_hwss(link, link_res);
|
||||
struct dmcu *dmcu = dc->res_pool->dmcu;
|
||||
|
||||
if (signal == SIGNAL_TYPE_EDP &&
|
||||
link->dc->hwss.edp_backlight_control)
|
||||
link->dc->hwss.edp_backlight_control(link, false);
|
||||
else if (dmcu != NULL && dmcu->funcs->lock_phy)
|
||||
dmcu->funcs->lock_phy(dmcu);
|
||||
|
||||
link_hwss->disable_link_output(link, link_res, signal);
|
||||
link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF;
|
||||
/*
|
||||
* Add the logic to extract BOTH power up and power down sequences
|
||||
* from enable/disable link output and only call edp panel control
|
||||
* in enable_link_dp and disable_link_dp once.
|
||||
*/
|
||||
if (dmcu != NULL && dmcu->funcs->lock_phy)
|
||||
dmcu->funcs->unlock_phy(dmcu);
|
||||
dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY);
|
||||
|
||||
apply_symclk_on_tx_off_wa(link);
|
||||
}
|
||||
|
@ -45,4 +45,6 @@ void dcn314_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool
|
||||
|
||||
void dcn314_dpp_root_clock_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool clock_on);
|
||||
|
||||
void dcn314_disable_link_output(struct dc_link *link, const struct link_resource *link_res, enum signal_type signal);
|
||||
|
||||
#endif /* __DC_HWSS_DCN314_H__ */
|
||||
|
@ -105,7 +105,7 @@ static const struct hw_sequencer_funcs dcn314_funcs = {
|
||||
.enable_lvds_link_output = dce110_enable_lvds_link_output,
|
||||
.enable_tmds_link_output = dce110_enable_tmds_link_output,
|
||||
.enable_dp_link_output = dce110_enable_dp_link_output,
|
||||
.disable_link_output = dce110_disable_link_output,
|
||||
.disable_link_output = dcn314_disable_link_output,
|
||||
.z10_restore = dcn31_z10_restore,
|
||||
.z10_save_init = dcn31_z10_save_init,
|
||||
.set_disp_pattern_generator = dcn30_set_disp_pattern_generator,
|
||||
|
@ -810,7 +810,8 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
|
||||
v->SwathHeightY[k],
|
||||
v->SwathHeightC[k],
|
||||
TWait,
|
||||
v->DRAMSpeedPerState[mode_lib->vba.VoltageLevel] <= MEM_STROBE_FREQ_MHZ ?
|
||||
(v->DRAMSpeedPerState[mode_lib->vba.VoltageLevel] <= MEM_STROBE_FREQ_MHZ ||
|
||||
v->DCFCLKPerState[mode_lib->vba.VoltageLevel] <= MIN_DCFCLK_FREQ_MHZ) ?
|
||||
mode_lib->vba.ip.min_prefetch_in_strobe_us : 0,
|
||||
/* Output */
|
||||
&v->DSTXAfterScaler[k],
|
||||
@ -3310,7 +3311,7 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
|
||||
v->swath_width_chroma_ub_this_state[k],
|
||||
v->SwathHeightYThisState[k],
|
||||
v->SwathHeightCThisState[k], v->TWait,
|
||||
v->DRAMSpeedPerState[i] <= MEM_STROBE_FREQ_MHZ ?
|
||||
(v->DRAMSpeedPerState[i] <= MEM_STROBE_FREQ_MHZ || v->DCFCLKState[i][j] <= MIN_DCFCLK_FREQ_MHZ) ?
|
||||
mode_lib->vba.ip.min_prefetch_in_strobe_us : 0,
|
||||
|
||||
/* Output */
|
||||
|
@ -53,6 +53,7 @@
|
||||
#define BPP_BLENDED_PIPE 0xffffffff
|
||||
|
||||
#define MEM_STROBE_FREQ_MHZ 1600
|
||||
#define MIN_DCFCLK_FREQ_MHZ 200
|
||||
#define MEM_STROBE_MAX_DELIVERY_TIME_US 60.0
|
||||
|
||||
struct display_mode_lib;
|
||||
|
@ -36,6 +36,8 @@
|
||||
#define amdgpu_dpm_enable_bapm(adev, e) \
|
||||
((adev)->powerplay.pp_funcs->enable_bapm((adev)->powerplay.pp_handle, (e)))
|
||||
|
||||
#define amdgpu_dpm_is_legacy_dpm(adev) ((adev)->powerplay.pp_handle == (adev))
|
||||
|
||||
int amdgpu_dpm_get_sclk(struct amdgpu_device *adev, bool low)
|
||||
{
|
||||
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
|
||||
@ -1460,15 +1462,24 @@ int amdgpu_dpm_get_smu_prv_buf_details(struct amdgpu_device *adev,
|
||||
|
||||
int amdgpu_dpm_is_overdrive_supported(struct amdgpu_device *adev)
|
||||
{
|
||||
struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
|
||||
struct smu_context *smu = adev->powerplay.pp_handle;
|
||||
if (is_support_sw_smu(adev)) {
|
||||
struct smu_context *smu = adev->powerplay.pp_handle;
|
||||
|
||||
if ((is_support_sw_smu(adev) && smu->od_enabled) ||
|
||||
(is_support_sw_smu(adev) && smu->is_apu) ||
|
||||
(!is_support_sw_smu(adev) && hwmgr->od_enabled))
|
||||
return true;
|
||||
return (smu->od_enabled || smu->is_apu);
|
||||
} else {
|
||||
struct pp_hwmgr *hwmgr;
|
||||
|
||||
return false;
|
||||
/*
|
||||
* dpm on some legacy asics don't carry od_enabled member
|
||||
* as its pp_handle is casted directly from adev.
|
||||
*/
|
||||
if (amdgpu_dpm_is_legacy_dpm(adev))
|
||||
return false;
|
||||
|
||||
hwmgr = (struct pp_hwmgr *)adev->powerplay.pp_handle;
|
||||
|
||||
return hwmgr->od_enabled;
|
||||
}
|
||||
}
|
||||
|
||||
int amdgpu_dpm_set_pp_table(struct amdgpu_device *adev,
|
||||
|
@ -425,11 +425,12 @@ struct ast_device *ast_device_create(const struct drm_driver *drv,
|
||||
return ERR_PTR(-EIO);
|
||||
|
||||
/*
|
||||
* If we don't have IO space at all, use MMIO now and
|
||||
* assume the chip has MMIO enabled by default (rev 0x20
|
||||
* and higher).
|
||||
* After AST2500, MMIO is enabled by default, and it should be adopted
|
||||
* to be compatible with Arm.
|
||||
*/
|
||||
if (!(pci_resource_flags(pdev, 2) & IORESOURCE_IO)) {
|
||||
if (pdev->revision >= 0x40) {
|
||||
ast->ioregs = ast->regs + AST_IO_MM_OFFSET;
|
||||
} else if (!(pci_resource_flags(pdev, 2) & IORESOURCE_IO)) {
|
||||
drm_info(dev, "platform has no IO space, trying MMIO\n");
|
||||
ast->ioregs = ast->regs + AST_IO_MM_OFFSET;
|
||||
}
|
||||
|
@ -641,19 +641,27 @@ static void drm_fb_helper_damage(struct drm_fb_helper *helper, u32 x, u32 y,
|
||||
static void drm_fb_helper_memory_range_to_clip(struct fb_info *info, off_t off, size_t len,
|
||||
struct drm_rect *clip)
|
||||
{
|
||||
u32 line_length = info->fix.line_length;
|
||||
u32 fb_height = info->var.yres;
|
||||
off_t end = off + len;
|
||||
u32 x1 = 0;
|
||||
u32 y1 = off / info->fix.line_length;
|
||||
u32 y1 = off / line_length;
|
||||
u32 x2 = info->var.xres;
|
||||
u32 y2 = DIV_ROUND_UP(end, info->fix.line_length);
|
||||
u32 y2 = DIV_ROUND_UP(end, line_length);
|
||||
|
||||
/* Don't allow any of them beyond the bottom bound of display area */
|
||||
if (y1 > fb_height)
|
||||
y1 = fb_height;
|
||||
if (y2 > fb_height)
|
||||
y2 = fb_height;
|
||||
|
||||
if ((y2 - y1) == 1) {
|
||||
/*
|
||||
* We've only written to a single scanline. Try to reduce
|
||||
* the number of horizontal pixels that need an update.
|
||||
*/
|
||||
off_t bit_off = (off % info->fix.line_length) * 8;
|
||||
off_t bit_end = (end % info->fix.line_length) * 8;
|
||||
off_t bit_off = (off % line_length) * 8;
|
||||
off_t bit_end = (end % line_length) * 8;
|
||||
|
||||
x1 = bit_off / info->var.bits_per_pixel;
|
||||
x2 = DIV_ROUND_UP(bit_end, info->var.bits_per_pixel);
|
||||
|
@ -221,7 +221,7 @@ mipi_dsi_device_register_full(struct mipi_dsi_host *host,
|
||||
return dsi;
|
||||
}
|
||||
|
||||
dsi->dev.of_node = info->node;
|
||||
device_set_node(&dsi->dev, of_fwnode_handle(info->node));
|
||||
dsi->channel = info->channel;
|
||||
strlcpy(dsi->name, info->type, sizeof(dsi->name));
|
||||
|
||||
|
@ -62,10 +62,11 @@ config DRM_I915_FORCE_PROBE
|
||||
This is the default value for the i915.force_probe module
|
||||
parameter. Using the module parameter overrides this option.
|
||||
|
||||
Force probe the i915 for Intel graphics devices that are
|
||||
recognized but not properly supported by this kernel version. It is
|
||||
recommended to upgrade to a kernel version with proper support as soon
|
||||
as it is available.
|
||||
Force probe the i915 driver for Intel graphics devices that are
|
||||
recognized but not properly supported by this kernel version. Force
|
||||
probing an unsupported device taints the kernel. It is recommended to
|
||||
upgrade to a kernel version with proper support as soon as it is
|
||||
available.
|
||||
|
||||
It can also be used to block the probe of recognized and fully
|
||||
supported devices.
|
||||
@ -75,7 +76,8 @@ config DRM_I915_FORCE_PROBE
|
||||
Use "<pci-id>[,<pci-id>,...]" to force probe the i915 for listed
|
||||
devices. For example, "4500" or "4500,4571".
|
||||
|
||||
Use "*" to force probe the driver for all known devices.
|
||||
Use "*" to force probe the driver for all known devices. Not
|
||||
recommended.
|
||||
|
||||
Use "!" right before the ID to block the probe of the device. For
|
||||
example, "4500,!4571" forces the probe of 4500 and blocks the probe of
|
||||
|
@ -1028,7 +1028,7 @@ intel_prepare_plane_fb(struct drm_plane *_plane,
|
||||
int ret;
|
||||
|
||||
if (old_obj) {
|
||||
const struct intel_crtc_state *crtc_state =
|
||||
const struct intel_crtc_state *new_crtc_state =
|
||||
intel_atomic_get_new_crtc_state(state,
|
||||
to_intel_crtc(old_plane_state->hw.crtc));
|
||||
|
||||
@ -1043,7 +1043,7 @@ intel_prepare_plane_fb(struct drm_plane *_plane,
|
||||
* This should only fail upon a hung GPU, in which case we
|
||||
* can safely continue.
|
||||
*/
|
||||
if (intel_crtc_needs_modeset(crtc_state)) {
|
||||
if (new_crtc_state && intel_crtc_needs_modeset(new_crtc_state)) {
|
||||
ret = i915_sw_fence_await_reservation(&state->commit_ready,
|
||||
old_obj->base.resv,
|
||||
false, 0,
|
||||
|
@ -1601,6 +1601,11 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
|
||||
pipe_config->dsc.slice_count =
|
||||
drm_dp_dsc_sink_max_slice_count(intel_dp->dsc_dpcd,
|
||||
true);
|
||||
if (!pipe_config->dsc.slice_count) {
|
||||
drm_dbg_kms(&dev_priv->drm, "Unsupported Slice Count %d\n",
|
||||
pipe_config->dsc.slice_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
u16 dsc_max_output_bpp = 0;
|
||||
u8 dsc_dp_slice_count;
|
||||
|
@ -31,12 +31,14 @@
|
||||
{ FORCEWAKE_MT, 0, 0, "FORCEWAKE" }
|
||||
|
||||
#define COMMON_GEN9BASE_GLOBAL \
|
||||
{ GEN8_FAULT_TLB_DATA0, 0, 0, "GEN8_FAULT_TLB_DATA0" }, \
|
||||
{ GEN8_FAULT_TLB_DATA1, 0, 0, "GEN8_FAULT_TLB_DATA1" }, \
|
||||
{ ERROR_GEN6, 0, 0, "ERROR_GEN6" }, \
|
||||
{ DONE_REG, 0, 0, "DONE_REG" }, \
|
||||
{ HSW_GTT_CACHE_EN, 0, 0, "HSW_GTT_CACHE_EN" }
|
||||
|
||||
#define GEN9_GLOBAL \
|
||||
{ GEN8_FAULT_TLB_DATA0, 0, 0, "GEN8_FAULT_TLB_DATA0" }, \
|
||||
{ GEN8_FAULT_TLB_DATA1, 0, 0, "GEN8_FAULT_TLB_DATA1" }
|
||||
|
||||
#define COMMON_GEN12BASE_GLOBAL \
|
||||
{ GEN12_FAULT_TLB_DATA0, 0, 0, "GEN12_FAULT_TLB_DATA0" }, \
|
||||
{ GEN12_FAULT_TLB_DATA1, 0, 0, "GEN12_FAULT_TLB_DATA1" }, \
|
||||
@ -142,6 +144,7 @@ static const struct __guc_mmio_reg_descr xe_lpd_gsc_inst_regs[] = {
|
||||
static const struct __guc_mmio_reg_descr default_global_regs[] = {
|
||||
COMMON_BASE_GLOBAL,
|
||||
COMMON_GEN9BASE_GLOBAL,
|
||||
GEN9_GLOBAL,
|
||||
};
|
||||
|
||||
static const struct __guc_mmio_reg_descr default_rc_class_regs[] = {
|
||||
|
@ -1344,6 +1344,12 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (intel_info->require_force_probe) {
|
||||
dev_info(&pdev->dev, "Force probing unsupported Device ID %04x, tainting kernel\n",
|
||||
pdev->device);
|
||||
add_taint(TAINT_USER, LOCKDEP_STILL_OK);
|
||||
}
|
||||
|
||||
/* Only bind to function 0 of the device. Early generations
|
||||
* used function 1 as a placeholder for multi-head. This causes
|
||||
* us confusion instead, especially on the systems where both
|
||||
|
@ -2,6 +2,8 @@
|
||||
#ifndef __NVIF_IF0012_H__
|
||||
#define __NVIF_IF0012_H__
|
||||
|
||||
#include <drm/display/drm_dp.h>
|
||||
|
||||
union nvif_outp_args {
|
||||
struct nvif_outp_v0 {
|
||||
__u8 version;
|
||||
@ -63,7 +65,7 @@ union nvif_outp_acquire_args {
|
||||
__u8 hda;
|
||||
__u8 mst;
|
||||
__u8 pad04[4];
|
||||
__u8 dpcd[16];
|
||||
__u8 dpcd[DP_RECEIVER_CAP_SIZE];
|
||||
} dp;
|
||||
};
|
||||
} v0;
|
||||
|
@ -3,6 +3,7 @@
|
||||
#define __NVKM_DISP_OUTP_H__
|
||||
#include "priv.h"
|
||||
|
||||
#include <drm/display/drm_dp.h>
|
||||
#include <subdev/bios.h>
|
||||
#include <subdev/bios/dcb.h>
|
||||
#include <subdev/bios/dp.h>
|
||||
@ -42,7 +43,7 @@ struct nvkm_outp {
|
||||
bool aux_pwr_pu;
|
||||
u8 lttpr[6];
|
||||
u8 lttprs;
|
||||
u8 dpcd[16];
|
||||
u8 dpcd[DP_RECEIVER_CAP_SIZE];
|
||||
|
||||
struct {
|
||||
int dpcd; /* -1, or index into SUPPORTED_LINK_RATES table */
|
||||
|
@ -146,7 +146,7 @@ nvkm_uoutp_mthd_release(struct nvkm_outp *outp, void *argv, u32 argc)
|
||||
}
|
||||
|
||||
static int
|
||||
nvkm_uoutp_mthd_acquire_dp(struct nvkm_outp *outp, u8 dpcd[16],
|
||||
nvkm_uoutp_mthd_acquire_dp(struct nvkm_outp *outp, u8 dpcd[DP_RECEIVER_CAP_SIZE],
|
||||
u8 link_nr, u8 link_bw, bool hda, bool mst)
|
||||
{
|
||||
int ret;
|
||||
|
@ -309,7 +309,7 @@ static void drm_sched_start_timeout(struct drm_gpu_scheduler *sched)
|
||||
*/
|
||||
void drm_sched_fault(struct drm_gpu_scheduler *sched)
|
||||
{
|
||||
if (sched->ready)
|
||||
if (sched->timeout_wq)
|
||||
mod_delayed_work(sched->timeout_wq, &sched->work_tdr, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_sched_fault);
|
||||
|
@ -507,6 +507,7 @@ static const struct pci_device_id k10temp_id_table[] = {
|
||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_M50H_DF_F3) },
|
||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_M60H_DF_F3) },
|
||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_M70H_DF_F3) },
|
||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_M78H_DF_F3) },
|
||||
{ PCI_VDEVICE(HYGON, PCI_DEVICE_ID_AMD_17H_DF_F3) },
|
||||
{}
|
||||
};
|
||||
|
@ -151,6 +151,12 @@ struct dvb_ca_private {
|
||||
|
||||
/* mutex serializing ioctls */
|
||||
struct mutex ioctl_mutex;
|
||||
|
||||
/* A mutex used when a device is disconnected */
|
||||
struct mutex remove_mutex;
|
||||
|
||||
/* Whether the device is disconnected */
|
||||
int exit;
|
||||
};
|
||||
|
||||
static void dvb_ca_private_free(struct dvb_ca_private *ca)
|
||||
@ -187,7 +193,7 @@ static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca);
|
||||
static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot,
|
||||
u8 *ebuf, int ecount);
|
||||
static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
|
||||
u8 *ebuf, int ecount);
|
||||
u8 *ebuf, int ecount, int size_write_flag);
|
||||
|
||||
/**
|
||||
* findstr - Safely find needle in haystack.
|
||||
@ -370,7 +376,7 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot)
|
||||
ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ / 10);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = dvb_ca_en50221_write_data(ca, slot, buf, 2);
|
||||
ret = dvb_ca_en50221_write_data(ca, slot, buf, 2, CMDREG_SW);
|
||||
if (ret != 2)
|
||||
return -EIO;
|
||||
ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN);
|
||||
@ -778,11 +784,13 @@ exit:
|
||||
* @buf: The data in this buffer is treated as a complete link-level packet to
|
||||
* be written.
|
||||
* @bytes_write: Size of ebuf.
|
||||
* @size_write_flag: A flag on Command Register which says whether the link size
|
||||
* information will be writen or not.
|
||||
*
|
||||
* return: Number of bytes written, or < 0 on error.
|
||||
*/
|
||||
static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
|
||||
u8 *buf, int bytes_write)
|
||||
u8 *buf, int bytes_write, int size_write_flag)
|
||||
{
|
||||
struct dvb_ca_slot *sl = &ca->slot_info[slot];
|
||||
int status;
|
||||
@ -817,7 +825,7 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
|
||||
|
||||
/* OK, set HC bit */
|
||||
status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND,
|
||||
IRQEN | CMDREG_HC);
|
||||
IRQEN | CMDREG_HC | size_write_flag);
|
||||
if (status)
|
||||
goto exit;
|
||||
|
||||
@ -1508,7 +1516,7 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
|
||||
|
||||
mutex_lock(&sl->slot_lock);
|
||||
status = dvb_ca_en50221_write_data(ca, slot, fragbuf,
|
||||
fraglen + 2);
|
||||
fraglen + 2, 0);
|
||||
mutex_unlock(&sl->slot_lock);
|
||||
if (status == (fraglen + 2)) {
|
||||
written = 1;
|
||||
@ -1709,12 +1717,22 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
|
||||
|
||||
dprintk("%s\n", __func__);
|
||||
|
||||
if (!try_module_get(ca->pub->owner))
|
||||
mutex_lock(&ca->remove_mutex);
|
||||
|
||||
if (ca->exit) {
|
||||
mutex_unlock(&ca->remove_mutex);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!try_module_get(ca->pub->owner)) {
|
||||
mutex_unlock(&ca->remove_mutex);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
err = dvb_generic_open(inode, file);
|
||||
if (err < 0) {
|
||||
module_put(ca->pub->owner);
|
||||
mutex_unlock(&ca->remove_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1739,6 +1757,7 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
|
||||
|
||||
dvb_ca_private_get(ca);
|
||||
|
||||
mutex_unlock(&ca->remove_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1758,6 +1777,8 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
|
||||
|
||||
dprintk("%s\n", __func__);
|
||||
|
||||
mutex_lock(&ca->remove_mutex);
|
||||
|
||||
/* mark the CA device as closed */
|
||||
ca->open = 0;
|
||||
dvb_ca_en50221_thread_update_delay(ca);
|
||||
@ -1768,6 +1789,13 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
|
||||
|
||||
dvb_ca_private_put(ca);
|
||||
|
||||
if (dvbdev->users == 1 && ca->exit == 1) {
|
||||
mutex_unlock(&ca->remove_mutex);
|
||||
wake_up(&dvbdev->wait_queue);
|
||||
} else {
|
||||
mutex_unlock(&ca->remove_mutex);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1891,6 +1919,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
|
||||
}
|
||||
|
||||
mutex_init(&ca->ioctl_mutex);
|
||||
mutex_init(&ca->remove_mutex);
|
||||
|
||||
if (signal_pending(current)) {
|
||||
ret = -EINTR;
|
||||
@ -1933,6 +1962,14 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
|
||||
|
||||
dprintk("%s\n", __func__);
|
||||
|
||||
mutex_lock(&ca->remove_mutex);
|
||||
ca->exit = 1;
|
||||
mutex_unlock(&ca->remove_mutex);
|
||||
|
||||
if (ca->dvbdev->users < 1)
|
||||
wait_event(ca->dvbdev->wait_queue,
|
||||
ca->dvbdev->users == 1);
|
||||
|
||||
/* shutdown the thread if there was one */
|
||||
kthread_stop(ca->thread);
|
||||
|
||||
|
@ -115,12 +115,12 @@ static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed,
|
||||
|
||||
cc = buf[3] & 0x0f;
|
||||
ccok = ((feed->cc + 1) & 0x0f) == cc;
|
||||
feed->cc = cc;
|
||||
if (!ccok) {
|
||||
set_buf_flags(feed, DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
|
||||
dprintk_sect_loss("missed packet: %d instead of %d!\n",
|
||||
cc, (feed->cc + 1) & 0x0f);
|
||||
}
|
||||
feed->cc = cc;
|
||||
|
||||
if (buf[1] & 0x40) // PUSI ?
|
||||
feed->peslen = 0xfffa;
|
||||
@ -300,7 +300,6 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
|
||||
|
||||
cc = buf[3] & 0x0f;
|
||||
ccok = ((feed->cc + 1) & 0x0f) == cc;
|
||||
feed->cc = cc;
|
||||
|
||||
if (buf[3] & 0x20) {
|
||||
/* adaption field present, check for discontinuity_indicator */
|
||||
@ -336,6 +335,7 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
|
||||
feed->pusi_seen = false;
|
||||
dvb_dmx_swfilter_section_new(feed);
|
||||
}
|
||||
feed->cc = cc;
|
||||
|
||||
if (buf[1] & 0x40) {
|
||||
/* PUSI=1 (is set), section boundary is here */
|
||||
|
@ -293,14 +293,22 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe,
|
||||
}
|
||||
|
||||
if (events->eventw == events->eventr) {
|
||||
int ret;
|
||||
struct wait_queue_entry wait;
|
||||
int ret = 0;
|
||||
|
||||
if (flags & O_NONBLOCK)
|
||||
return -EWOULDBLOCK;
|
||||
|
||||
ret = wait_event_interruptible(events->wait_queue,
|
||||
dvb_frontend_test_event(fepriv, events));
|
||||
|
||||
init_waitqueue_entry(&wait, current);
|
||||
add_wait_queue(&events->wait_queue, &wait);
|
||||
while (!dvb_frontend_test_event(fepriv, events)) {
|
||||
wait_woken(&wait, TASK_INTERRUPTIBLE, 0);
|
||||
if (signal_pending(current)) {
|
||||
ret = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
remove_wait_queue(&events->wait_queue, &wait);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
@ -809,15 +817,26 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
|
||||
|
||||
dev_dbg(fe->dvb->device, "%s:\n", __func__);
|
||||
|
||||
mutex_lock(&fe->remove_mutex);
|
||||
|
||||
if (fe->exit != DVB_FE_DEVICE_REMOVED)
|
||||
fe->exit = DVB_FE_NORMAL_EXIT;
|
||||
mb();
|
||||
|
||||
if (!fepriv->thread)
|
||||
if (!fepriv->thread) {
|
||||
mutex_unlock(&fe->remove_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
kthread_stop(fepriv->thread);
|
||||
|
||||
mutex_unlock(&fe->remove_mutex);
|
||||
|
||||
if (fepriv->dvbdev->users < -1) {
|
||||
wait_event(fepriv->dvbdev->wait_queue,
|
||||
fepriv->dvbdev->users == -1);
|
||||
}
|
||||
|
||||
sema_init(&fepriv->sem, 1);
|
||||
fepriv->state = FESTATE_IDLE;
|
||||
|
||||
@ -2761,9 +2780,13 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
|
||||
struct dvb_adapter *adapter = fe->dvb;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&fe->remove_mutex);
|
||||
|
||||
dev_dbg(fe->dvb->device, "%s:\n", __func__);
|
||||
if (fe->exit == DVB_FE_DEVICE_REMOVED)
|
||||
return -ENODEV;
|
||||
if (fe->exit == DVB_FE_DEVICE_REMOVED) {
|
||||
ret = -ENODEV;
|
||||
goto err_remove_mutex;
|
||||
}
|
||||
|
||||
if (adapter->mfe_shared == 2) {
|
||||
mutex_lock(&adapter->mfe_lock);
|
||||
@ -2771,7 +2794,8 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
|
||||
if (adapter->mfe_dvbdev &&
|
||||
!adapter->mfe_dvbdev->writers) {
|
||||
mutex_unlock(&adapter->mfe_lock);
|
||||
return -EBUSY;
|
||||
ret = -EBUSY;
|
||||
goto err_remove_mutex;
|
||||
}
|
||||
adapter->mfe_dvbdev = dvbdev;
|
||||
}
|
||||
@ -2794,8 +2818,10 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
|
||||
while (mferetry-- && (mfedev->users != -1 ||
|
||||
mfepriv->thread)) {
|
||||
if (msleep_interruptible(500)) {
|
||||
if (signal_pending(current))
|
||||
return -EINTR;
|
||||
if (signal_pending(current)) {
|
||||
ret = -EINTR;
|
||||
goto err_remove_mutex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2807,7 +2833,8 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
|
||||
if (mfedev->users != -1 ||
|
||||
mfepriv->thread) {
|
||||
mutex_unlock(&adapter->mfe_lock);
|
||||
return -EBUSY;
|
||||
ret = -EBUSY;
|
||||
goto err_remove_mutex;
|
||||
}
|
||||
adapter->mfe_dvbdev = dvbdev;
|
||||
}
|
||||
@ -2866,6 +2893,8 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
|
||||
|
||||
if (adapter->mfe_shared)
|
||||
mutex_unlock(&adapter->mfe_lock);
|
||||
|
||||
mutex_unlock(&fe->remove_mutex);
|
||||
return ret;
|
||||
|
||||
err3:
|
||||
@ -2887,6 +2916,9 @@ err1:
|
||||
err0:
|
||||
if (adapter->mfe_shared)
|
||||
mutex_unlock(&adapter->mfe_lock);
|
||||
|
||||
err_remove_mutex:
|
||||
mutex_unlock(&fe->remove_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2897,6 +2929,8 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
|
||||
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&fe->remove_mutex);
|
||||
|
||||
dev_dbg(fe->dvb->device, "%s:\n", __func__);
|
||||
|
||||
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
|
||||
@ -2918,10 +2952,18 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
|
||||
}
|
||||
mutex_unlock(&fe->dvb->mdev_lock);
|
||||
#endif
|
||||
if (fe->exit != DVB_FE_NO_EXIT)
|
||||
wake_up(&dvbdev->wait_queue);
|
||||
if (fe->ops.ts_bus_ctrl)
|
||||
fe->ops.ts_bus_ctrl(fe, 0);
|
||||
|
||||
if (fe->exit != DVB_FE_NO_EXIT) {
|
||||
mutex_unlock(&fe->remove_mutex);
|
||||
wake_up(&dvbdev->wait_queue);
|
||||
} else {
|
||||
mutex_unlock(&fe->remove_mutex);
|
||||
}
|
||||
|
||||
} else {
|
||||
mutex_unlock(&fe->remove_mutex);
|
||||
}
|
||||
|
||||
dvb_frontend_put(fe);
|
||||
@ -3022,6 +3064,7 @@ int dvb_register_frontend(struct dvb_adapter *dvb,
|
||||
fepriv = fe->frontend_priv;
|
||||
|
||||
kref_init(&fe->refcount);
|
||||
mutex_init(&fe->remove_mutex);
|
||||
|
||||
/*
|
||||
* After initialization, there need to be two references: one
|
||||
|
@ -1564,15 +1564,43 @@ static long dvb_net_ioctl(struct file *file,
|
||||
return dvb_usercopy(file, cmd, arg, dvb_net_do_ioctl);
|
||||
}
|
||||
|
||||
static int locked_dvb_net_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct dvb_device *dvbdev = file->private_data;
|
||||
struct dvb_net *dvbnet = dvbdev->priv;
|
||||
int ret;
|
||||
|
||||
if (mutex_lock_interruptible(&dvbnet->remove_mutex))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
if (dvbnet->exit) {
|
||||
mutex_unlock(&dvbnet->remove_mutex);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = dvb_generic_open(inode, file);
|
||||
|
||||
mutex_unlock(&dvbnet->remove_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dvb_net_close(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct dvb_device *dvbdev = file->private_data;
|
||||
struct dvb_net *dvbnet = dvbdev->priv;
|
||||
|
||||
mutex_lock(&dvbnet->remove_mutex);
|
||||
|
||||
dvb_generic_release(inode, file);
|
||||
|
||||
if(dvbdev->users == 1 && dvbnet->exit == 1)
|
||||
if (dvbdev->users == 1 && dvbnet->exit == 1) {
|
||||
mutex_unlock(&dvbnet->remove_mutex);
|
||||
wake_up(&dvbdev->wait_queue);
|
||||
} else {
|
||||
mutex_unlock(&dvbnet->remove_mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1580,7 +1608,7 @@ static int dvb_net_close(struct inode *inode, struct file *file)
|
||||
static const struct file_operations dvb_net_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.unlocked_ioctl = dvb_net_ioctl,
|
||||
.open = dvb_generic_open,
|
||||
.open = locked_dvb_net_open,
|
||||
.release = dvb_net_close,
|
||||
.llseek = noop_llseek,
|
||||
};
|
||||
@ -1599,10 +1627,13 @@ void dvb_net_release (struct dvb_net *dvbnet)
|
||||
{
|
||||
int i;
|
||||
|
||||
mutex_lock(&dvbnet->remove_mutex);
|
||||
dvbnet->exit = 1;
|
||||
mutex_unlock(&dvbnet->remove_mutex);
|
||||
|
||||
if (dvbnet->dvbdev->users < 1)
|
||||
wait_event(dvbnet->dvbdev->wait_queue,
|
||||
dvbnet->dvbdev->users==1);
|
||||
dvbnet->dvbdev->users == 1);
|
||||
|
||||
dvb_unregister_device(dvbnet->dvbdev);
|
||||
|
||||
@ -1621,6 +1652,7 @@ int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet,
|
||||
int i;
|
||||
|
||||
mutex_init(&dvbnet->ioctl_mutex);
|
||||
mutex_init(&dvbnet->remove_mutex);
|
||||
dvbnet->demux = dmx;
|
||||
|
||||
for (i=0; i<DVB_NET_DEVICES_MAX; i++)
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <media/tuner.h>
|
||||
|
||||
static DEFINE_MUTEX(dvbdev_mutex);
|
||||
static LIST_HEAD(dvbdevfops_list);
|
||||
static int dvbdev_debug;
|
||||
|
||||
module_param(dvbdev_debug, int, 0644);
|
||||
@ -453,14 +454,15 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
||||
enum dvb_device_type type, int demux_sink_pads)
|
||||
{
|
||||
struct dvb_device *dvbdev;
|
||||
struct file_operations *dvbdevfops;
|
||||
struct file_operations *dvbdevfops = NULL;
|
||||
struct dvbdevfops_node *node = NULL, *new_node = NULL;
|
||||
struct device *clsdev;
|
||||
int minor;
|
||||
int id, ret;
|
||||
|
||||
mutex_lock(&dvbdev_register_lock);
|
||||
|
||||
if ((id = dvbdev_get_free_id (adap, type)) < 0){
|
||||
if ((id = dvbdev_get_free_id (adap, type)) < 0) {
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
*pdvbdev = NULL;
|
||||
pr_err("%s: couldn't find free device id\n", __func__);
|
||||
@ -468,18 +470,45 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
||||
}
|
||||
|
||||
*pdvbdev = dvbdev = kzalloc(sizeof(*dvbdev), GFP_KERNEL);
|
||||
|
||||
if (!dvbdev){
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), GFP_KERNEL);
|
||||
/*
|
||||
* When a device of the same type is probe()d more than once,
|
||||
* the first allocated fops are used. This prevents memory leaks
|
||||
* that can occur when the same device is probe()d repeatedly.
|
||||
*/
|
||||
list_for_each_entry(node, &dvbdevfops_list, list_head) {
|
||||
if (node->fops->owner == adap->module &&
|
||||
node->type == type &&
|
||||
node->template == template) {
|
||||
dvbdevfops = node->fops;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dvbdevfops){
|
||||
kfree (dvbdev);
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
return -ENOMEM;
|
||||
if (dvbdevfops == NULL) {
|
||||
dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), GFP_KERNEL);
|
||||
if (!dvbdevfops) {
|
||||
kfree(dvbdev);
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
new_node = kzalloc(sizeof(struct dvbdevfops_node), GFP_KERNEL);
|
||||
if (!new_node) {
|
||||
kfree(dvbdevfops);
|
||||
kfree(dvbdev);
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
new_node->fops = dvbdevfops;
|
||||
new_node->type = type;
|
||||
new_node->template = template;
|
||||
list_add_tail (&new_node->list_head, &dvbdevfops_list);
|
||||
}
|
||||
|
||||
memcpy(dvbdev, template, sizeof(struct dvb_device));
|
||||
@ -490,20 +519,20 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
||||
dvbdev->priv = priv;
|
||||
dvbdev->fops = dvbdevfops;
|
||||
init_waitqueue_head (&dvbdev->wait_queue);
|
||||
|
||||
dvbdevfops->owner = adap->module;
|
||||
|
||||
list_add_tail (&dvbdev->list_head, &adap->device_list);
|
||||
|
||||
down_write(&minor_rwsem);
|
||||
#ifdef CONFIG_DVB_DYNAMIC_MINORS
|
||||
for (minor = 0; minor < MAX_DVB_MINORS; minor++)
|
||||
if (dvb_minors[minor] == NULL)
|
||||
break;
|
||||
|
||||
if (minor == MAX_DVB_MINORS) {
|
||||
if (new_node) {
|
||||
list_del (&new_node->list_head);
|
||||
kfree(dvbdevfops);
|
||||
kfree(new_node);
|
||||
}
|
||||
list_del (&dvbdev->list_head);
|
||||
kfree(dvbdevfops);
|
||||
kfree(dvbdev);
|
||||
up_write(&minor_rwsem);
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
@ -512,41 +541,47 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
||||
#else
|
||||
minor = nums2minor(adap->num, type, id);
|
||||
#endif
|
||||
|
||||
dvbdev->minor = minor;
|
||||
dvb_minors[minor] = dvb_device_get(dvbdev);
|
||||
up_write(&minor_rwsem);
|
||||
|
||||
ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads);
|
||||
if (ret) {
|
||||
pr_err("%s: dvb_register_media_device failed to create the mediagraph\n",
|
||||
__func__);
|
||||
|
||||
if (new_node) {
|
||||
list_del (&new_node->list_head);
|
||||
kfree(dvbdevfops);
|
||||
kfree(new_node);
|
||||
}
|
||||
dvb_media_device_free(dvbdev);
|
||||
list_del (&dvbdev->list_head);
|
||||
kfree(dvbdevfops);
|
||||
kfree(dvbdev);
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
|
||||
clsdev = device_create(dvb_class, adap->device,
|
||||
MKDEV(DVB_MAJOR, minor),
|
||||
dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id);
|
||||
if (IS_ERR(clsdev)) {
|
||||
pr_err("%s: failed to create device dvb%d.%s%d (%ld)\n",
|
||||
__func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
|
||||
if (new_node) {
|
||||
list_del (&new_node->list_head);
|
||||
kfree(dvbdevfops);
|
||||
kfree(new_node);
|
||||
}
|
||||
dvb_media_device_free(dvbdev);
|
||||
list_del (&dvbdev->list_head);
|
||||
kfree(dvbdevfops);
|
||||
kfree(dvbdev);
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
return PTR_ERR(clsdev);
|
||||
}
|
||||
|
||||
dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
|
||||
adap->num, dnames[type], id, minor, minor);
|
||||
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_register_device);
|
||||
@ -575,7 +610,6 @@ static void dvb_free_device(struct kref *ref)
|
||||
{
|
||||
struct dvb_device *dvbdev = container_of(ref, struct dvb_device, ref);
|
||||
|
||||
kfree (dvbdev->fops);
|
||||
kfree (dvbdev);
|
||||
}
|
||||
|
||||
@ -1081,9 +1115,17 @@ error:
|
||||
|
||||
static void __exit exit_dvbdev(void)
|
||||
{
|
||||
struct dvbdevfops_node *node, *next;
|
||||
|
||||
class_destroy(dvb_class);
|
||||
cdev_del(&dvb_device_cdev);
|
||||
unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS);
|
||||
|
||||
list_for_each_entry_safe(node, next, &dvbdevfops_list, list_head) {
|
||||
list_del (&node->list_head);
|
||||
kfree(node->fops);
|
||||
kfree(node);
|
||||
}
|
||||
}
|
||||
|
||||
subsys_initcall(init_dvbdev);
|
||||
|
@ -798,7 +798,7 @@ MODULE_DEVICE_TABLE(i2c, mn88443x_i2c_id);
|
||||
static struct i2c_driver mn88443x_driver = {
|
||||
.driver = {
|
||||
.name = "mn88443x",
|
||||
.of_match_table = of_match_ptr(mn88443x_of_match),
|
||||
.of_match_table = mn88443x_of_match,
|
||||
},
|
||||
.probe_new = mn88443x_probe,
|
||||
.remove = mn88443x_remove,
|
||||
|
@ -697,7 +697,7 @@ static void netup_unidvb_dma_fini(struct netup_unidvb_dev *ndev, int num)
|
||||
netup_unidvb_dma_enable(dma, 0);
|
||||
msleep(50);
|
||||
cancel_work_sync(&dma->work);
|
||||
del_timer(&dma->timeout);
|
||||
del_timer_sync(&dma->timeout);
|
||||
}
|
||||
|
||||
static int netup_unidvb_dma_setup(struct netup_unidvb_dev *ndev)
|
||||
@ -887,12 +887,7 @@ static int netup_unidvb_initdev(struct pci_dev *pci_dev,
|
||||
ndev->lmmio0, (u32)pci_resource_len(pci_dev, 0),
|
||||
ndev->lmmio1, (u32)pci_resource_len(pci_dev, 1),
|
||||
pci_dev->irq);
|
||||
if (request_irq(pci_dev->irq, netup_unidvb_isr, IRQF_SHARED,
|
||||
"netup_unidvb", pci_dev) < 0) {
|
||||
dev_err(&pci_dev->dev,
|
||||
"%s(): can't get IRQ %d\n", __func__, pci_dev->irq);
|
||||
goto irq_request_err;
|
||||
}
|
||||
|
||||
ndev->dma_size = 2 * 188 *
|
||||
NETUP_DMA_BLOCKS_COUNT * NETUP_DMA_PACKETS_COUNT;
|
||||
ndev->dma_virt = dma_alloc_coherent(&pci_dev->dev,
|
||||
@ -933,6 +928,14 @@ static int netup_unidvb_initdev(struct pci_dev *pci_dev,
|
||||
dev_err(&pci_dev->dev, "netup_unidvb: DMA setup failed\n");
|
||||
goto dma_setup_err;
|
||||
}
|
||||
|
||||
if (request_irq(pci_dev->irq, netup_unidvb_isr, IRQF_SHARED,
|
||||
"netup_unidvb", pci_dev) < 0) {
|
||||
dev_err(&pci_dev->dev,
|
||||
"%s(): can't get IRQ %d\n", __func__, pci_dev->irq);
|
||||
goto dma_setup_err;
|
||||
}
|
||||
|
||||
dev_info(&pci_dev->dev,
|
||||
"netup_unidvb: device has been initialized\n");
|
||||
return 0;
|
||||
@ -951,8 +954,6 @@ spi_setup_err:
|
||||
dma_free_coherent(&pci_dev->dev, ndev->dma_size,
|
||||
ndev->dma_virt, ndev->dma_phys);
|
||||
dma_alloc_err:
|
||||
free_irq(pci_dev->irq, pci_dev);
|
||||
irq_request_err:
|
||||
iounmap(ndev->lmmio1);
|
||||
pci_bar1_error:
|
||||
iounmap(ndev->lmmio0);
|
||||
|
@ -101,6 +101,10 @@ static int ce6230_i2c_master_xfer(struct i2c_adapter *adap,
|
||||
if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
|
||||
if (msg[i].addr ==
|
||||
ce6230_zl10353_config.demod_address) {
|
||||
if (msg[i].len < 1) {
|
||||
i = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
req.cmd = DEMOD_READ;
|
||||
req.value = msg[i].addr >> 1;
|
||||
req.index = msg[i].buf[0];
|
||||
@ -117,6 +121,10 @@ static int ce6230_i2c_master_xfer(struct i2c_adapter *adap,
|
||||
} else {
|
||||
if (msg[i].addr ==
|
||||
ce6230_zl10353_config.demod_address) {
|
||||
if (msg[i].len < 1) {
|
||||
i = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
req.cmd = DEMOD_WRITE;
|
||||
req.value = msg[i].addr >> 1;
|
||||
req.index = msg[i].buf[0];
|
||||
|
@ -115,6 +115,10 @@ static int ec168_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
||||
while (i < num) {
|
||||
if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
|
||||
if (msg[i].addr == ec168_ec100_config.demod_address) {
|
||||
if (msg[i].len < 1) {
|
||||
i = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
req.cmd = READ_DEMOD;
|
||||
req.value = 0;
|
||||
req.index = 0xff00 + msg[i].buf[0]; /* reg */
|
||||
@ -131,6 +135,10 @@ static int ec168_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
||||
}
|
||||
} else {
|
||||
if (msg[i].addr == ec168_ec100_config.demod_address) {
|
||||
if (msg[i].len < 1) {
|
||||
i = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
req.cmd = WRITE_DEMOD;
|
||||
req.value = msg[i].buf[1]; /* val */
|
||||
req.index = 0xff00 + msg[i].buf[0]; /* reg */
|
||||
@ -139,6 +147,10 @@ static int ec168_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
||||
ret = ec168_ctrl_msg(d, &req);
|
||||
i += 1;
|
||||
} else {
|
||||
if (msg[i].len < 1) {
|
||||
i = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
req.cmd = WRITE_I2C;
|
||||
req.value = msg[i].buf[0]; /* val */
|
||||
req.index = 0x0100 + msg[i].addr; /* I2C addr */
|
||||
|
@ -176,6 +176,10 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
||||
ret = -EOPNOTSUPP;
|
||||
goto err_mutex_unlock;
|
||||
} else if (msg[0].addr == 0x10) {
|
||||
if (msg[0].len < 1 || msg[1].len < 1) {
|
||||
ret = -EOPNOTSUPP;
|
||||
goto err_mutex_unlock;
|
||||
}
|
||||
/* method 1 - integrated demod */
|
||||
if (msg[0].buf[0] == 0x00) {
|
||||
/* return demod page from driver cache */
|
||||
@ -189,6 +193,10 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
||||
ret = rtl28xxu_ctrl_msg(d, &req);
|
||||
}
|
||||
} else if (msg[0].len < 2) {
|
||||
if (msg[0].len < 1) {
|
||||
ret = -EOPNOTSUPP;
|
||||
goto err_mutex_unlock;
|
||||
}
|
||||
/* method 2 - old I2C */
|
||||
req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1);
|
||||
req.index = CMD_I2C_RD;
|
||||
@ -217,8 +225,16 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
||||
ret = -EOPNOTSUPP;
|
||||
goto err_mutex_unlock;
|
||||
} else if (msg[0].addr == 0x10) {
|
||||
if (msg[0].len < 1) {
|
||||
ret = -EOPNOTSUPP;
|
||||
goto err_mutex_unlock;
|
||||
}
|
||||
/* method 1 - integrated demod */
|
||||
if (msg[0].buf[0] == 0x00) {
|
||||
if (msg[0].len < 2) {
|
||||
ret = -EOPNOTSUPP;
|
||||
goto err_mutex_unlock;
|
||||
}
|
||||
/* save demod page for later demod access */
|
||||
dev->page = msg[0].buf[1];
|
||||
ret = 0;
|
||||
@ -231,6 +247,10 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
||||
ret = rtl28xxu_ctrl_msg(d, &req);
|
||||
}
|
||||
} else if ((msg[0].len < 23) && (!dev->new_i2c_write)) {
|
||||
if (msg[0].len < 1) {
|
||||
ret = -EOPNOTSUPP;
|
||||
goto err_mutex_unlock;
|
||||
}
|
||||
/* method 2 - old I2C */
|
||||
req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1);
|
||||
req.index = CMD_I2C_WR;
|
||||
|
@ -988,6 +988,10 @@ static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int n
|
||||
/* write/read request */
|
||||
if (i + 1 < num && (msg[i + 1].flags & I2C_M_RD)) {
|
||||
req = 0xB9;
|
||||
if (msg[i].len < 1) {
|
||||
i = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff));
|
||||
value = msg[i].addr + (msg[i].len << 8);
|
||||
length = msg[i + 1].len + 6;
|
||||
@ -1001,6 +1005,10 @@ static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int n
|
||||
|
||||
/* demod 16bit addr */
|
||||
req = 0xBD;
|
||||
if (msg[i].len < 1) {
|
||||
i = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff));
|
||||
value = msg[i].addr + (2 << 8);
|
||||
length = msg[i].len - 2;
|
||||
@ -1026,6 +1034,10 @@ static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int n
|
||||
} else {
|
||||
|
||||
req = 0xBD;
|
||||
if (msg[i].len < 1) {
|
||||
i = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
index = msg[i].buf[0] & 0x00FF;
|
||||
value = msg[i].addr + (1 << 8);
|
||||
length = msg[i].len - 1;
|
||||
|
@ -63,6 +63,10 @@ static int digitv_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num
|
||||
warn("more than 2 i2c messages at a time is not handled yet. TODO.");
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
if (msg[i].len < 1) {
|
||||
i = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
/* write/read request */
|
||||
if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
|
||||
if (digitv_ctrl_msg(d, USB_READ_COFDM, msg[i].buf[0], NULL, 0,
|
||||
|
@ -946,7 +946,7 @@ static int su3000_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
|
||||
for (i = 0; i < 6; i++) {
|
||||
obuf[1] = 0xf0 + i;
|
||||
if (i2c_transfer(&d->i2c_adap, msg, 2) != 2)
|
||||
break;
|
||||
return -1;
|
||||
else
|
||||
mac[i] = ibuf[0];
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ config VIDEO_PVRUSB2_DVB
|
||||
bool "pvrusb2 ATSC/DVB support"
|
||||
default y
|
||||
depends on VIDEO_PVRUSB2 && DVB_CORE
|
||||
depends on VIDEO_PVRUSB2=m || DVB_CORE=y
|
||||
select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_S5H1409 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT
|
||||
|
@ -1544,8 +1544,7 @@ static void ttusb_dec_exit_dvb(struct ttusb_dec *dec)
|
||||
dvb_dmx_release(&dec->demux);
|
||||
if (dec->fe) {
|
||||
dvb_unregister_frontend(dec->fe);
|
||||
if (dec->fe->ops.release)
|
||||
dec->fe->ops.release(dec->fe);
|
||||
dvb_frontend_detach(dec->fe);
|
||||
}
|
||||
dvb_unregister_adapter(&dec->adapter);
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ config CAN_AT91
|
||||
|
||||
config CAN_BXCAN
|
||||
tristate "STM32 Basic Extended CAN (bxCAN) devices"
|
||||
depends on OF || ARCH_STM32 || COMPILE_TEST
|
||||
depends on ARCH_STM32 || COMPILE_TEST
|
||||
depends on HAS_IOMEM
|
||||
select CAN_RX_OFFLOAD
|
||||
help
|
||||
|
@ -118,7 +118,7 @@
|
||||
#define BXCAN_FiR1_REG(b) (0x40 + (b) * 8)
|
||||
#define BXCAN_FiR2_REG(b) (0x44 + (b) * 8)
|
||||
|
||||
#define BXCAN_FILTER_ID(primary) (primary ? 0 : 14)
|
||||
#define BXCAN_FILTER_ID(cfg) ((cfg) == BXCAN_CFG_DUAL_SECONDARY ? 14 : 0)
|
||||
|
||||
/* Filter primary register (FMR) bits */
|
||||
#define BXCAN_FMR_CANSB_MASK GENMASK(13, 8)
|
||||
@ -135,6 +135,12 @@ enum bxcan_lec_code {
|
||||
BXCAN_LEC_UNUSED
|
||||
};
|
||||
|
||||
enum bxcan_cfg {
|
||||
BXCAN_CFG_SINGLE = 0,
|
||||
BXCAN_CFG_DUAL_PRIMARY,
|
||||
BXCAN_CFG_DUAL_SECONDARY
|
||||
};
|
||||
|
||||
/* Structure of the message buffer */
|
||||
struct bxcan_mb {
|
||||
u32 id; /* can identifier */
|
||||
@ -167,7 +173,7 @@ struct bxcan_priv {
|
||||
struct regmap *gcan;
|
||||
int tx_irq;
|
||||
int sce_irq;
|
||||
bool primary;
|
||||
enum bxcan_cfg cfg;
|
||||
struct clk *clk;
|
||||
spinlock_t rmw_lock; /* lock for read-modify-write operations */
|
||||
unsigned int tx_head;
|
||||
@ -202,17 +208,17 @@ static inline void bxcan_rmw(struct bxcan_priv *priv, void __iomem *addr,
|
||||
spin_unlock_irqrestore(&priv->rmw_lock, flags);
|
||||
}
|
||||
|
||||
static void bxcan_disable_filters(struct bxcan_priv *priv, bool primary)
|
||||
static void bxcan_disable_filters(struct bxcan_priv *priv, enum bxcan_cfg cfg)
|
||||
{
|
||||
unsigned int fid = BXCAN_FILTER_ID(primary);
|
||||
unsigned int fid = BXCAN_FILTER_ID(cfg);
|
||||
u32 fmask = BIT(fid);
|
||||
|
||||
regmap_update_bits(priv->gcan, BXCAN_FA1R_REG, fmask, 0);
|
||||
}
|
||||
|
||||
static void bxcan_enable_filters(struct bxcan_priv *priv, bool primary)
|
||||
static void bxcan_enable_filters(struct bxcan_priv *priv, enum bxcan_cfg cfg)
|
||||
{
|
||||
unsigned int fid = BXCAN_FILTER_ID(primary);
|
||||
unsigned int fid = BXCAN_FILTER_ID(cfg);
|
||||
u32 fmask = BIT(fid);
|
||||
|
||||
/* Filter settings:
|
||||
@ -680,7 +686,7 @@ static int bxcan_chip_start(struct net_device *ndev)
|
||||
BXCAN_BTR_BRP_MASK | BXCAN_BTR_TS1_MASK | BXCAN_BTR_TS2_MASK |
|
||||
BXCAN_BTR_SJW_MASK, set);
|
||||
|
||||
bxcan_enable_filters(priv, priv->primary);
|
||||
bxcan_enable_filters(priv, priv->cfg);
|
||||
|
||||
/* Clear all internal status */
|
||||
priv->tx_head = 0;
|
||||
@ -806,7 +812,7 @@ static void bxcan_chip_stop(struct net_device *ndev)
|
||||
BXCAN_IER_EPVIE | BXCAN_IER_EWGIE | BXCAN_IER_FOVIE1 |
|
||||
BXCAN_IER_FFIE1 | BXCAN_IER_FMPIE1 | BXCAN_IER_FOVIE0 |
|
||||
BXCAN_IER_FFIE0 | BXCAN_IER_FMPIE0 | BXCAN_IER_TMEIE, 0);
|
||||
bxcan_disable_filters(priv, priv->primary);
|
||||
bxcan_disable_filters(priv, priv->cfg);
|
||||
bxcan_enter_sleep_mode(priv);
|
||||
priv->can.state = CAN_STATE_STOPPED;
|
||||
}
|
||||
@ -931,7 +937,7 @@ static int bxcan_probe(struct platform_device *pdev)
|
||||
struct clk *clk = NULL;
|
||||
void __iomem *regs;
|
||||
struct regmap *gcan;
|
||||
bool primary;
|
||||
enum bxcan_cfg cfg;
|
||||
int err, rx_irq, tx_irq, sce_irq;
|
||||
|
||||
regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
@ -946,7 +952,13 @@ static int bxcan_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(gcan);
|
||||
}
|
||||
|
||||
primary = of_property_read_bool(np, "st,can-primary");
|
||||
if (of_property_read_bool(np, "st,can-primary"))
|
||||
cfg = BXCAN_CFG_DUAL_PRIMARY;
|
||||
else if (of_property_read_bool(np, "st,can-secondary"))
|
||||
cfg = BXCAN_CFG_DUAL_SECONDARY;
|
||||
else
|
||||
cfg = BXCAN_CFG_SINGLE;
|
||||
|
||||
clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(clk)) {
|
||||
dev_err(dev, "failed to get clock\n");
|
||||
@ -986,7 +998,7 @@ static int bxcan_probe(struct platform_device *pdev)
|
||||
priv->clk = clk;
|
||||
priv->tx_irq = tx_irq;
|
||||
priv->sce_irq = sce_irq;
|
||||
priv->primary = primary;
|
||||
priv->cfg = cfg;
|
||||
priv->can.clock.freq = clk_get_rate(clk);
|
||||
spin_lock_init(&priv->rmw_lock);
|
||||
priv->tx_head = 0;
|
||||
|
@ -54,7 +54,8 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
|
||||
/* check flag whether this packet has to be looped back */
|
||||
if (!(dev->flags & IFF_ECHO) ||
|
||||
(skb->protocol != htons(ETH_P_CAN) &&
|
||||
skb->protocol != htons(ETH_P_CANFD))) {
|
||||
skb->protocol != htons(ETH_P_CANFD) &&
|
||||
skb->protocol != htons(ETH_P_CANXL))) {
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
@ -71,10 +71,12 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices");
|
||||
#define KVASER_PCIEFD_SYSID_BUILD_REG (KVASER_PCIEFD_SYSID_BASE + 0x14)
|
||||
/* Shared receive buffer registers */
|
||||
#define KVASER_PCIEFD_SRB_BASE 0x1f200
|
||||
#define KVASER_PCIEFD_SRB_FIFO_LAST_REG (KVASER_PCIEFD_SRB_BASE + 0x1f4)
|
||||
#define KVASER_PCIEFD_SRB_CMD_REG (KVASER_PCIEFD_SRB_BASE + 0x200)
|
||||
#define KVASER_PCIEFD_SRB_IEN_REG (KVASER_PCIEFD_SRB_BASE + 0x204)
|
||||
#define KVASER_PCIEFD_SRB_IRQ_REG (KVASER_PCIEFD_SRB_BASE + 0x20c)
|
||||
#define KVASER_PCIEFD_SRB_STAT_REG (KVASER_PCIEFD_SRB_BASE + 0x210)
|
||||
#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG (KVASER_PCIEFD_SRB_BASE + 0x214)
|
||||
#define KVASER_PCIEFD_SRB_CTRL_REG (KVASER_PCIEFD_SRB_BASE + 0x218)
|
||||
/* EPCS flash controller registers */
|
||||
#define KVASER_PCIEFD_SPI_BASE 0x1fc00
|
||||
@ -111,6 +113,9 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices");
|
||||
/* DMA support */
|
||||
#define KVASER_PCIEFD_SRB_STAT_DMA BIT(24)
|
||||
|
||||
/* SRB current packet level */
|
||||
#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK 0xff
|
||||
|
||||
/* DMA Enable */
|
||||
#define KVASER_PCIEFD_SRB_CTRL_DMA_ENABLE BIT(0)
|
||||
|
||||
@ -526,7 +531,7 @@ static int kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can *can)
|
||||
KVASER_PCIEFD_KCAN_IRQ_TOF | KVASER_PCIEFD_KCAN_IRQ_ABD |
|
||||
KVASER_PCIEFD_KCAN_IRQ_TAE | KVASER_PCIEFD_KCAN_IRQ_TAL |
|
||||
KVASER_PCIEFD_KCAN_IRQ_FDIC | KVASER_PCIEFD_KCAN_IRQ_BPP |
|
||||
KVASER_PCIEFD_KCAN_IRQ_TAR | KVASER_PCIEFD_KCAN_IRQ_TFD;
|
||||
KVASER_PCIEFD_KCAN_IRQ_TAR;
|
||||
|
||||
iowrite32(msk, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
|
||||
|
||||
@ -554,6 +559,8 @@ static void kvaser_pciefd_setup_controller(struct kvaser_pciefd_can *can)
|
||||
|
||||
if (can->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
|
||||
mode |= KVASER_PCIEFD_KCAN_MODE_LOM;
|
||||
else
|
||||
mode &= ~KVASER_PCIEFD_KCAN_MODE_LOM;
|
||||
|
||||
mode |= KVASER_PCIEFD_KCAN_MODE_EEN;
|
||||
mode |= KVASER_PCIEFD_KCAN_MODE_EPEN;
|
||||
@ -572,7 +579,7 @@ static void kvaser_pciefd_start_controller_flush(struct kvaser_pciefd_can *can)
|
||||
|
||||
spin_lock_irqsave(&can->lock, irq);
|
||||
iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
|
||||
iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD | KVASER_PCIEFD_KCAN_IRQ_TFD,
|
||||
iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
|
||||
can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
|
||||
|
||||
status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG);
|
||||
@ -615,7 +622,7 @@ static int kvaser_pciefd_bus_on(struct kvaser_pciefd_can *can)
|
||||
iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
|
||||
iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
|
||||
|
||||
iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD | KVASER_PCIEFD_KCAN_IRQ_TFD,
|
||||
iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
|
||||
can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
|
||||
|
||||
mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
|
||||
@ -719,6 +726,7 @@ static int kvaser_pciefd_stop(struct net_device *netdev)
|
||||
iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
|
||||
del_timer(&can->bec_poll_timer);
|
||||
}
|
||||
can->can.state = CAN_STATE_STOPPED;
|
||||
close_candev(netdev);
|
||||
|
||||
return ret;
|
||||
@ -1007,8 +1015,7 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie)
|
||||
SET_NETDEV_DEV(netdev, &pcie->pci->dev);
|
||||
|
||||
iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
|
||||
iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD |
|
||||
KVASER_PCIEFD_KCAN_IRQ_TFD,
|
||||
iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
|
||||
can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
|
||||
|
||||
pcie->can[i] = can;
|
||||
@ -1058,6 +1065,7 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie)
|
||||
{
|
||||
int i;
|
||||
u32 srb_status;
|
||||
u32 srb_packet_count;
|
||||
dma_addr_t dma_addr[KVASER_PCIEFD_DMA_COUNT];
|
||||
|
||||
/* Disable the DMA */
|
||||
@ -1085,6 +1093,15 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie)
|
||||
KVASER_PCIEFD_SRB_CMD_RDB1,
|
||||
pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG);
|
||||
|
||||
/* Empty Rx FIFO */
|
||||
srb_packet_count = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG) &
|
||||
KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK;
|
||||
while (srb_packet_count) {
|
||||
/* Drop current packet in FIFO */
|
||||
ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_FIFO_LAST_REG);
|
||||
srb_packet_count--;
|
||||
}
|
||||
|
||||
srb_status = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_STAT_REG);
|
||||
if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DI)) {
|
||||
dev_err(&pcie->pci->dev, "DMA not idle before enabling\n");
|
||||
@ -1425,9 +1442,6 @@ static int kvaser_pciefd_handle_status_packet(struct kvaser_pciefd *pcie,
|
||||
cmd = KVASER_PCIEFD_KCAN_CMD_AT;
|
||||
cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT;
|
||||
iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG);
|
||||
|
||||
iowrite32(KVASER_PCIEFD_KCAN_IRQ_TFD,
|
||||
can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
|
||||
} else if (p->header[0] & KVASER_PCIEFD_SPACK_IDET &&
|
||||
p->header[0] & KVASER_PCIEFD_SPACK_IRM &&
|
||||
cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK) &&
|
||||
@ -1714,15 +1728,6 @@ static int kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can)
|
||||
if (irq & KVASER_PCIEFD_KCAN_IRQ_TOF)
|
||||
netdev_err(can->can.dev, "Tx FIFO overflow\n");
|
||||
|
||||
if (irq & KVASER_PCIEFD_KCAN_IRQ_TFD) {
|
||||
u8 count = ioread32(can->reg_base +
|
||||
KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff;
|
||||
|
||||
if (count == 0)
|
||||
iowrite32(KVASER_PCIEFD_KCAN_CTRL_EFLUSH,
|
||||
can->reg_base + KVASER_PCIEFD_KCAN_CTRL_REG);
|
||||
}
|
||||
|
||||
if (irq & KVASER_PCIEFD_KCAN_IRQ_BPP)
|
||||
netdev_err(can->can.dev,
|
||||
"Fail to change bittiming, when not in reset mode\n");
|
||||
@ -1824,6 +1829,11 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev,
|
||||
if (err)
|
||||
goto err_teardown_can_ctrls;
|
||||
|
||||
err = request_irq(pcie->pci->irq, kvaser_pciefd_irq_handler,
|
||||
IRQF_SHARED, KVASER_PCIEFD_DRV_NAME, pcie);
|
||||
if (err)
|
||||
goto err_teardown_can_ctrls;
|
||||
|
||||
iowrite32(KVASER_PCIEFD_SRB_IRQ_DPD0 | KVASER_PCIEFD_SRB_IRQ_DPD1,
|
||||
pcie->reg_base + KVASER_PCIEFD_SRB_IRQ_REG);
|
||||
|
||||
@ -1844,11 +1854,6 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev,
|
||||
iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1,
|
||||
pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG);
|
||||
|
||||
err = request_irq(pcie->pci->irq, kvaser_pciefd_irq_handler,
|
||||
IRQF_SHARED, KVASER_PCIEFD_DRV_NAME, pcie);
|
||||
if (err)
|
||||
goto err_teardown_can_ctrls;
|
||||
|
||||
err = kvaser_pciefd_reg_candev(pcie);
|
||||
if (err)
|
||||
goto err_free_irq;
|
||||
@ -1856,6 +1861,8 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev,
|
||||
return 0;
|
||||
|
||||
err_free_irq:
|
||||
/* Disable PCI interrupts */
|
||||
iowrite32(0, pcie->reg_base + KVASER_PCIEFD_IEN_REG);
|
||||
free_irq(pcie->pci->irq, pcie);
|
||||
|
||||
err_teardown_can_ctrls:
|
||||
|
@ -276,7 +276,7 @@
|
||||
/* Offset 0x10: Extended Port Control Command */
|
||||
#define MV88E6393X_PORT_EPC_CMD 0x10
|
||||
#define MV88E6393X_PORT_EPC_CMD_BUSY 0x8000
|
||||
#define MV88E6393X_PORT_EPC_CMD_WRITE 0x0300
|
||||
#define MV88E6393X_PORT_EPC_CMD_WRITE 0x3000
|
||||
#define MV88E6393X_PORT_EPC_INDEX_PORT_ETYPE 0x02
|
||||
|
||||
/* Offset 0x11: Extended Port Control Data */
|
||||
|
@ -120,6 +120,22 @@ static void a5psw_port_mgmtfwd_set(struct a5psw *a5psw, int port, bool enable)
|
||||
a5psw_port_pattern_set(a5psw, port, A5PSW_PATTERN_MGMTFWD, enable);
|
||||
}
|
||||
|
||||
static void a5psw_port_tx_enable(struct a5psw *a5psw, int port, bool enable)
|
||||
{
|
||||
u32 mask = A5PSW_PORT_ENA_TX(port);
|
||||
u32 reg = enable ? mask : 0;
|
||||
|
||||
/* Even though the port TX is disabled through TXENA bit in the
|
||||
* PORT_ENA register, it can still send BPDUs. This depends on the tag
|
||||
* configuration added when sending packets from the CPU port to the
|
||||
* switch port. Indeed, when using forced forwarding without filtering,
|
||||
* even disabled ports will be able to send packets that are tagged.
|
||||
* This allows to implement STP support when ports are in a state where
|
||||
* forwarding traffic should be stopped but BPDUs should still be sent.
|
||||
*/
|
||||
a5psw_reg_rmw(a5psw, A5PSW_PORT_ENA, mask, reg);
|
||||
}
|
||||
|
||||
static void a5psw_port_enable_set(struct a5psw *a5psw, int port, bool enable)
|
||||
{
|
||||
u32 port_ena = 0;
|
||||
@ -292,6 +308,22 @@ static int a5psw_set_ageing_time(struct dsa_switch *ds, unsigned int msecs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void a5psw_port_learning_set(struct a5psw *a5psw, int port, bool learn)
|
||||
{
|
||||
u32 mask = A5PSW_INPUT_LEARN_DIS(port);
|
||||
u32 reg = !learn ? mask : 0;
|
||||
|
||||
a5psw_reg_rmw(a5psw, A5PSW_INPUT_LEARN, mask, reg);
|
||||
}
|
||||
|
||||
static void a5psw_port_rx_block_set(struct a5psw *a5psw, int port, bool block)
|
||||
{
|
||||
u32 mask = A5PSW_INPUT_LEARN_BLOCK(port);
|
||||
u32 reg = block ? mask : 0;
|
||||
|
||||
a5psw_reg_rmw(a5psw, A5PSW_INPUT_LEARN, mask, reg);
|
||||
}
|
||||
|
||||
static void a5psw_flooding_set_resolution(struct a5psw *a5psw, int port,
|
||||
bool set)
|
||||
{
|
||||
@ -308,6 +340,14 @@ static void a5psw_flooding_set_resolution(struct a5psw *a5psw, int port,
|
||||
a5psw_reg_writel(a5psw, offsets[i], a5psw->bridged_ports);
|
||||
}
|
||||
|
||||
static void a5psw_port_set_standalone(struct a5psw *a5psw, int port,
|
||||
bool standalone)
|
||||
{
|
||||
a5psw_port_learning_set(a5psw, port, !standalone);
|
||||
a5psw_flooding_set_resolution(a5psw, port, !standalone);
|
||||
a5psw_port_mgmtfwd_set(a5psw, port, standalone);
|
||||
}
|
||||
|
||||
static int a5psw_port_bridge_join(struct dsa_switch *ds, int port,
|
||||
struct dsa_bridge bridge,
|
||||
bool *tx_fwd_offload,
|
||||
@ -323,8 +363,7 @@ static int a5psw_port_bridge_join(struct dsa_switch *ds, int port,
|
||||
}
|
||||
|
||||
a5psw->br_dev = bridge.dev;
|
||||
a5psw_flooding_set_resolution(a5psw, port, true);
|
||||
a5psw_port_mgmtfwd_set(a5psw, port, false);
|
||||
a5psw_port_set_standalone(a5psw, port, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -334,8 +373,7 @@ static void a5psw_port_bridge_leave(struct dsa_switch *ds, int port,
|
||||
{
|
||||
struct a5psw *a5psw = ds->priv;
|
||||
|
||||
a5psw_flooding_set_resolution(a5psw, port, false);
|
||||
a5psw_port_mgmtfwd_set(a5psw, port, true);
|
||||
a5psw_port_set_standalone(a5psw, port, true);
|
||||
|
||||
/* No more ports bridged */
|
||||
if (a5psw->bridged_ports == BIT(A5PSW_CPU_PORT))
|
||||
@ -344,28 +382,35 @@ static void a5psw_port_bridge_leave(struct dsa_switch *ds, int port,
|
||||
|
||||
static void a5psw_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
|
||||
{
|
||||
u32 mask = A5PSW_INPUT_LEARN_DIS(port) | A5PSW_INPUT_LEARN_BLOCK(port);
|
||||
bool learning_enabled, rx_enabled, tx_enabled;
|
||||
struct a5psw *a5psw = ds->priv;
|
||||
u32 reg = 0;
|
||||
|
||||
switch (state) {
|
||||
case BR_STATE_DISABLED:
|
||||
case BR_STATE_BLOCKING:
|
||||
reg |= A5PSW_INPUT_LEARN_DIS(port);
|
||||
reg |= A5PSW_INPUT_LEARN_BLOCK(port);
|
||||
break;
|
||||
case BR_STATE_LISTENING:
|
||||
reg |= A5PSW_INPUT_LEARN_DIS(port);
|
||||
rx_enabled = false;
|
||||
tx_enabled = false;
|
||||
learning_enabled = false;
|
||||
break;
|
||||
case BR_STATE_LEARNING:
|
||||
reg |= A5PSW_INPUT_LEARN_BLOCK(port);
|
||||
rx_enabled = false;
|
||||
tx_enabled = false;
|
||||
learning_enabled = true;
|
||||
break;
|
||||
case BR_STATE_FORWARDING:
|
||||
default:
|
||||
rx_enabled = true;
|
||||
tx_enabled = true;
|
||||
learning_enabled = true;
|
||||
break;
|
||||
default:
|
||||
dev_err(ds->dev, "invalid STP state: %d\n", state);
|
||||
return;
|
||||
}
|
||||
|
||||
a5psw_reg_rmw(a5psw, A5PSW_INPUT_LEARN, mask, reg);
|
||||
a5psw_port_learning_set(a5psw, port, learning_enabled);
|
||||
a5psw_port_rx_block_set(a5psw, port, !rx_enabled);
|
||||
a5psw_port_tx_enable(a5psw, port, tx_enabled);
|
||||
}
|
||||
|
||||
static void a5psw_port_fast_age(struct dsa_switch *ds, int port)
|
||||
@ -673,7 +718,7 @@ static int a5psw_setup(struct dsa_switch *ds)
|
||||
}
|
||||
|
||||
/* Configure management port */
|
||||
reg = A5PSW_CPU_PORT | A5PSW_MGMT_CFG_DISCARD;
|
||||
reg = A5PSW_CPU_PORT | A5PSW_MGMT_CFG_ENABLE;
|
||||
a5psw_reg_writel(a5psw, A5PSW_MGMT_CFG, reg);
|
||||
|
||||
/* Set pattern 0 to forward all frame to mgmt port */
|
||||
@ -722,13 +767,15 @@ static int a5psw_setup(struct dsa_switch *ds)
|
||||
if (dsa_port_is_unused(dp))
|
||||
continue;
|
||||
|
||||
/* Enable egress flooding for CPU port */
|
||||
if (dsa_port_is_cpu(dp))
|
||||
/* Enable egress flooding and learning for CPU port */
|
||||
if (dsa_port_is_cpu(dp)) {
|
||||
a5psw_flooding_set_resolution(a5psw, port, true);
|
||||
a5psw_port_learning_set(a5psw, port, true);
|
||||
}
|
||||
|
||||
/* Enable management forward only for user ports */
|
||||
/* Enable standalone mode for user ports */
|
||||
if (dsa_port_is_user(dp))
|
||||
a5psw_port_mgmtfwd_set(a5psw, port, true);
|
||||
a5psw_port_set_standalone(a5psw, port, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#define A5PSW_PORT_OFFSET(port) (0x400 * (port))
|
||||
|
||||
#define A5PSW_PORT_ENA 0x8
|
||||
#define A5PSW_PORT_ENA_TX(port) BIT(port)
|
||||
#define A5PSW_PORT_ENA_RX_SHIFT 16
|
||||
#define A5PSW_PORT_ENA_TX_RX(port) (BIT((port) + A5PSW_PORT_ENA_RX_SHIFT) | \
|
||||
BIT(port))
|
||||
@ -36,7 +37,7 @@
|
||||
#define A5PSW_INPUT_LEARN_BLOCK(p) BIT(p)
|
||||
|
||||
#define A5PSW_MGMT_CFG 0x20
|
||||
#define A5PSW_MGMT_CFG_DISCARD BIT(7)
|
||||
#define A5PSW_MGMT_CFG_ENABLE BIT(6)
|
||||
|
||||
#define A5PSW_MODE_CFG 0x24
|
||||
#define A5PSW_MODE_STATS_RESET BIT(31)
|
||||
|
@ -66,8 +66,10 @@ static int max_interrupt_work = 20;
|
||||
#include <linux/timer.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <net/Space.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/dma.h>
|
||||
|
||||
|
@ -50,6 +50,7 @@ static const char version2[] =
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <net/Space.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
|
@ -64,6 +64,7 @@ static const char version[] =
|
||||
#include <linux/isapnp.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <net/Space.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
|
@ -35,6 +35,7 @@ static const char version[] =
|
||||
#include <linux/delay.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <net/Space.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
|
@ -59,6 +59,7 @@ static const char version[] = "lance.c:v1.16 2006/11/09 dplatt@3do.com, becker@c
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <net/Space.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/dma.h>
|
||||
|
@ -3450,7 +3450,7 @@ err_clk_disable:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void bcmgenet_netif_stop(struct net_device *dev)
|
||||
static void bcmgenet_netif_stop(struct net_device *dev, bool stop_phy)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
|
||||
@ -3465,6 +3465,8 @@ static void bcmgenet_netif_stop(struct net_device *dev)
|
||||
/* Disable MAC transmit. TX DMA disabled must be done before this */
|
||||
umac_enable_set(priv, CMD_TX_EN, false);
|
||||
|
||||
if (stop_phy)
|
||||
phy_stop(dev->phydev);
|
||||
bcmgenet_disable_rx_napi(priv);
|
||||
bcmgenet_intr_disable(priv);
|
||||
|
||||
@ -3485,7 +3487,7 @@ static int bcmgenet_close(struct net_device *dev)
|
||||
|
||||
netif_dbg(priv, ifdown, dev, "bcmgenet_close\n");
|
||||
|
||||
bcmgenet_netif_stop(dev);
|
||||
bcmgenet_netif_stop(dev, false);
|
||||
|
||||
/* Really kill the PHY state machine and disconnect from it */
|
||||
phy_disconnect(dev->phydev);
|
||||
@ -4303,7 +4305,7 @@ static int bcmgenet_suspend(struct device *d)
|
||||
|
||||
netif_device_detach(dev);
|
||||
|
||||
bcmgenet_netif_stop(dev);
|
||||
bcmgenet_netif_stop(dev, true);
|
||||
|
||||
if (!device_may_wakeup(d))
|
||||
phy_suspend(dev->phydev);
|
||||
|
@ -72,6 +72,8 @@
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <net/Space.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <linux/atomic.h>
|
||||
#if ALLOW_DMA
|
||||
|
@ -3798,7 +3798,6 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep,
|
||||
entries_free = fec_enet_get_free_txdesc_num(txq);
|
||||
if (entries_free < MAX_SKB_FRAGS + 1) {
|
||||
netdev_err(fep->netdev, "NOT enough BD for SG!\n");
|
||||
xdp_return_frame(frame);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
@ -4478,9 +4477,11 @@ fec_drv_remove(struct platform_device *pdev)
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_resume_and_get(&pdev->dev);
|
||||
ret = pm_runtime_get_sync(&pdev->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
dev_err(&pdev->dev,
|
||||
"Failed to resume device in remove callback (%pe)\n",
|
||||
ERR_PTR(ret));
|
||||
|
||||
cancel_work_sync(&fep->tx_timeout_work);
|
||||
fec_ptp_stop(pdev);
|
||||
@ -4493,8 +4494,13 @@ fec_drv_remove(struct platform_device *pdev)
|
||||
of_phy_deregister_fixed_link(np);
|
||||
of_node_put(fep->phy_node);
|
||||
|
||||
clk_disable_unprepare(fep->clk_ahb);
|
||||
clk_disable_unprepare(fep->clk_ipg);
|
||||
/* After pm_runtime_get_sync() failed, the clks are still off, so skip
|
||||
* disabling them again.
|
||||
*/
|
||||
if (ret >= 0) {
|
||||
clk_disable_unprepare(fep->clk_ahb);
|
||||
clk_disable_unprepare(fep->clk_ipg);
|
||||
}
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
|
@ -331,9 +331,25 @@ static int hclge_comm_cmd_csq_done(struct hclge_comm_hw *hw)
|
||||
return head == hw->cmq.csq.next_to_use;
|
||||
}
|
||||
|
||||
static void hclge_comm_wait_for_resp(struct hclge_comm_hw *hw,
|
||||
static u32 hclge_get_cmdq_tx_timeout(u16 opcode, u32 tx_timeout)
|
||||
{
|
||||
static const struct hclge_cmdq_tx_timeout_map cmdq_tx_timeout_map[] = {
|
||||
{HCLGE_OPC_CFG_RST_TRIGGER, HCLGE_COMM_CMDQ_TX_TIMEOUT_500MS},
|
||||
};
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cmdq_tx_timeout_map); i++)
|
||||
if (cmdq_tx_timeout_map[i].opcode == opcode)
|
||||
return cmdq_tx_timeout_map[i].tx_timeout;
|
||||
|
||||
return tx_timeout;
|
||||
}
|
||||
|
||||
static void hclge_comm_wait_for_resp(struct hclge_comm_hw *hw, u16 opcode,
|
||||
bool *is_completed)
|
||||
{
|
||||
u32 cmdq_tx_timeout = hclge_get_cmdq_tx_timeout(opcode,
|
||||
hw->cmq.tx_timeout);
|
||||
u32 timeout = 0;
|
||||
|
||||
do {
|
||||
@ -343,7 +359,7 @@ static void hclge_comm_wait_for_resp(struct hclge_comm_hw *hw,
|
||||
}
|
||||
udelay(1);
|
||||
timeout++;
|
||||
} while (timeout < hw->cmq.tx_timeout);
|
||||
} while (timeout < cmdq_tx_timeout);
|
||||
}
|
||||
|
||||
static int hclge_comm_cmd_convert_err_code(u16 desc_ret)
|
||||
@ -407,7 +423,8 @@ static int hclge_comm_cmd_check_result(struct hclge_comm_hw *hw,
|
||||
* if multi descriptors to be sent, use the first one to check
|
||||
*/
|
||||
if (HCLGE_COMM_SEND_SYNC(le16_to_cpu(desc->flag)))
|
||||
hclge_comm_wait_for_resp(hw, &is_completed);
|
||||
hclge_comm_wait_for_resp(hw, le16_to_cpu(desc->opcode),
|
||||
&is_completed);
|
||||
|
||||
if (!is_completed)
|
||||
ret = -EBADE;
|
||||
@ -529,7 +546,7 @@ int hclge_comm_cmd_queue_init(struct pci_dev *pdev, struct hclge_comm_hw *hw)
|
||||
cmdq->crq.desc_num = HCLGE_COMM_NIC_CMQ_DESC_NUM;
|
||||
|
||||
/* Setup Tx write back timeout */
|
||||
cmdq->tx_timeout = HCLGE_COMM_CMDQ_TX_TIMEOUT;
|
||||
cmdq->tx_timeout = HCLGE_COMM_CMDQ_TX_TIMEOUT_DEFAULT;
|
||||
|
||||
/* Setup queue rings */
|
||||
ret = hclge_comm_alloc_cmd_queue(hw, HCLGE_COMM_TYPE_CSQ);
|
||||
|
@ -54,7 +54,8 @@
|
||||
#define HCLGE_COMM_NIC_SW_RST_RDY BIT(HCLGE_COMM_NIC_SW_RST_RDY_B)
|
||||
#define HCLGE_COMM_NIC_CMQ_DESC_NUM_S 3
|
||||
#define HCLGE_COMM_NIC_CMQ_DESC_NUM 1024
|
||||
#define HCLGE_COMM_CMDQ_TX_TIMEOUT 30000
|
||||
#define HCLGE_COMM_CMDQ_TX_TIMEOUT_DEFAULT 30000
|
||||
#define HCLGE_COMM_CMDQ_TX_TIMEOUT_500MS 500000
|
||||
|
||||
enum hclge_opcode_type {
|
||||
/* Generic commands */
|
||||
@ -360,6 +361,11 @@ struct hclge_comm_caps_bit_map {
|
||||
u16 local_bit;
|
||||
};
|
||||
|
||||
struct hclge_cmdq_tx_timeout_map {
|
||||
u32 opcode;
|
||||
u32 tx_timeout;
|
||||
};
|
||||
|
||||
struct hclge_comm_firmware_compat_cmd {
|
||||
__le32 compat;
|
||||
u8 rsv[20];
|
||||
|
@ -130,7 +130,7 @@ static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = {
|
||||
.name = "tx_bd_queue",
|
||||
.cmd = HNAE3_DBG_CMD_TX_BD,
|
||||
.dentry = HNS3_DBG_DENTRY_TX_BD,
|
||||
.buf_len = HNS3_DBG_READ_LEN_4MB,
|
||||
.buf_len = HNS3_DBG_READ_LEN_5MB,
|
||||
.init = hns3_dbg_bd_file_init,
|
||||
},
|
||||
{
|
||||
|
@ -10,6 +10,7 @@
|
||||
#define HNS3_DBG_READ_LEN_128KB 0x20000
|
||||
#define HNS3_DBG_READ_LEN_1MB 0x100000
|
||||
#define HNS3_DBG_READ_LEN_4MB 0x400000
|
||||
#define HNS3_DBG_READ_LEN_5MB 0x500000
|
||||
#define HNS3_DBG_WRITE_LEN 1024
|
||||
|
||||
#define HNS3_DBG_DATA_STR_LEN 32
|
||||
|
@ -8053,12 +8053,15 @@ static void hclge_ae_stop(struct hnae3_handle *handle)
|
||||
/* If it is not PF reset or FLR, the firmware will disable the MAC,
|
||||
* so it only need to stop phy here.
|
||||
*/
|
||||
if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state) &&
|
||||
hdev->reset_type != HNAE3_FUNC_RESET &&
|
||||
hdev->reset_type != HNAE3_FLR_RESET) {
|
||||
hclge_mac_stop_phy(hdev);
|
||||
hclge_update_link_status(hdev);
|
||||
return;
|
||||
if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) {
|
||||
hclge_pfc_pause_en_cfg(hdev, HCLGE_PFC_TX_RX_DISABLE,
|
||||
HCLGE_PFC_DISABLE);
|
||||
if (hdev->reset_type != HNAE3_FUNC_RESET &&
|
||||
hdev->reset_type != HNAE3_FLR_RESET) {
|
||||
hclge_mac_stop_phy(hdev);
|
||||
hclge_update_link_status(hdev);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
hclge_reset_tqp(handle);
|
||||
|
@ -171,8 +171,8 @@ int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx)
|
||||
return hclge_cmd_send(&hdev->hw, &desc, 1);
|
||||
}
|
||||
|
||||
static int hclge_pfc_pause_en_cfg(struct hclge_dev *hdev, u8 tx_rx_bitmap,
|
||||
u8 pfc_bitmap)
|
||||
int hclge_pfc_pause_en_cfg(struct hclge_dev *hdev, u8 tx_rx_bitmap,
|
||||
u8 pfc_bitmap)
|
||||
{
|
||||
struct hclge_desc desc;
|
||||
struct hclge_pfc_en_cmd *pfc = (struct hclge_pfc_en_cmd *)desc.data;
|
||||
|
@ -164,6 +164,9 @@ struct hclge_bp_to_qs_map_cmd {
|
||||
u32 rsvd1;
|
||||
};
|
||||
|
||||
#define HCLGE_PFC_DISABLE 0
|
||||
#define HCLGE_PFC_TX_RX_DISABLE 0
|
||||
|
||||
struct hclge_pfc_en_cmd {
|
||||
u8 tx_rx_en_bitmap;
|
||||
u8 pri_en_bitmap;
|
||||
@ -235,6 +238,8 @@ void hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc);
|
||||
void hclge_tm_pfc_info_update(struct hclge_dev *hdev);
|
||||
int hclge_tm_dwrr_cfg(struct hclge_dev *hdev);
|
||||
int hclge_tm_init_hw(struct hclge_dev *hdev, bool init);
|
||||
int hclge_pfc_pause_en_cfg(struct hclge_dev *hdev, u8 tx_rx_bitmap,
|
||||
u8 pfc_bitmap);
|
||||
int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx);
|
||||
int hclge_pause_addr_cfg(struct hclge_dev *hdev, const u8 *mac_addr);
|
||||
void hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user