Compare commits

...

29 Commits

Author SHA1 Message Date
Phil Elwell
3ed6d34d53 fixup! overlays: mcp23017: allow specification of the i2c bus
The incorrect fragment order (*) caused broke the interrupt usage, and
while it was being fixed the lack of a reference to the pinctrl
declaration was noticed.

See: https://github.com/raspberrypi/linux/issues/5677

Signed-off-by: Phil Elwell <phil@raspberrypi.com>

(*) Ideally all fragments would appear in the file in the order in which
they should be merged, but that is easy to forget and can be awkward, so
the firmware merges all "intra" fragments (those that target other
fragments in the overlay) before "inter" fragments (those that target
the base DTB). However, intra fragments that target other intra
fragments is a level of nesting too far for this logic to cope, so they
must appear before the fragments they target.
2023-10-24 12:09:30 +01:00
Dave Stevenson
eccaa8588f dt: Add drm_fbN_vc4 overrides for Pi0-4
Follows up '61b138adaead ("dt: Add overrides for drm framebuffer
allocations on Pi5")' with an equivalent for Pi0-4.

These will have no effect on most normal systems, but drm_fb0_vc4
will stop SPI displays jumping in and claiming /dev/fb0.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
2023-10-23 14:57:16 +01:00
Naushir Patuck
f075893e9b drivers: media: imx477: Disable the scaler
The horizontal scaler was enabled for the 2028x1520 and 2028x1080 modes,
with a scale factor of 1. It caused a single column of bad pixels on the
right edge of the image. Since scaling is not needed for these modes,
disable it entirely.

Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
2023-10-23 12:37:21 +01:00
Dave Stevenson
5a52cae54a dt: Switch bcm2712 firmware-kms node to using the 2712 compatible
With the new compatible to handle the interrupts correctly, switch
the base dt to use it.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
2023-10-20 20:18:41 +01:00
Dave Stevenson
4137b49989 drm/vc4_fkms: Fix up interrupt handler for both 2835/2711 and 2712
2712 has switched from using the SMI peripheral to another interrupt
source for the vsync interrupt, so handle both sources cleanly.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
2023-10-20 20:18:41 +01:00
Dave Stevenson
93b52ae53a Revert "vc4/fkms: Remove use of SMI peripheral"
This reverts commit 3fb20da9f3.
2023-10-20 20:18:41 +01:00
Phil Elwell
4cb97982f8 dts: bcm2712: Add the krnbt parameter
Add a Pi 5 implementation of the krnbt parameter, for symmetry and
for tinkering purposes.

Signed-off-by: Phil Elwell <phil@raspberrypi.com>
2023-10-20 17:15:25 +01:00
Andrew Scheller
cb8a4adb58 Typo in overlays README
touchscreen-size-y for rpi-ft5406 defaults to 480, not 600
2023-10-19 16:14:49 +01:00
Phil Elwell
74d906b6ca fixup! overlays: Add Pi 5 version of dwc2
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
2023-10-19 16:12:07 +01:00
Dave Stevenson
87be940591 dt: Alter alias names from _ to - for drm_fbN_* overrides
Fixes: 61b138adae ("dt: Add overrides for drm framebuffer allocations on Pi5")
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
2023-10-19 12:27:03 +01:00
Dave Stevenson
0e9e925112 drm/fb_helper: Change query for FB designation from drm_fb to drm-fb
Fixes: 1216ea56c2 ("drm/fb-helper: Look up preferred fbdev node number from DT")
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
2023-10-19 12:27:03 +01:00
Dave Stevenson
e33170e214 dt: Alter alias names from _ to - for drm_dsiN
Fixes: 7ec42740a4 ("dt: Add DSI1 and DSI2 aliases to 2712")
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
2023-10-19 12:27:03 +01:00
Dave Stevenson
f429fc1a07 drm/connector: Change DRM card alias from underscore to hyphen
Apparently aliases are only allowed lower case and hyphens,
so swap the use of underscore to hyphen.

Fixes: 3aa1f24775 ("drm: Look for an alias for the displays to use as the DRM device name")
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
2023-10-19 12:27:03 +01:00
Phil Elwell
ff2db5847b overlays: Add Pi 5 version of dwc2
Most bus masters on Pi 5 have access to at least the lower 4GB, but
the old DWC OTG controller is still restricted to the first 1GB.
Create a Pi 5-specific version of the overlay including a fragment
that ensures the swiotlb bounce buffers are allocated in that
area.

Signed-off-by: Phil Elwell <phil@raspberrypi.com>
2023-10-19 12:21:13 +01:00
Dave Stevenson
61b138adae dt: Add overrides for drm framebuffer allocations on Pi5
Adds dtparam overrides to the base Pi5 DT such that vc4,
DSI0, DSI1, or DPI can be requested to be /dev/fb[012].
No override is specified by default, so the order will be
based on probe order (aka semi-random). Any device that
doesn't have an override specified will be placed above
all specified overrides. Having an fb1 or fb2 override but
no fb0 one will result in no console via fbcon.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
2023-10-18 23:02:34 +01:00
Dave Stevenson
1216ea56c2 drm/fb-helper: Look up preferred fbdev node number from DT
For situations where there are multiple DRM cards in a system,
add a query of DT for "drm_fb" designations for cards to set
their preferred /dev/fbN designation.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
2023-10-18 23:02:34 +01:00
Dave Stevenson
0c7fb448e0 fbdev: Allow client to request a particular /dev/fbN node
Add a flag custom_fb_num to denote that the client has
requested a specific fbdev node number via node.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
2023-10-18 23:02:34 +01:00
Phil Elwell
b6bfece0d9 dts: bcm2712: Use the new model name
"Model B" is no more - "Raspberry Pi 5" is the official name.

Signed-off-by: Phil Elwell <phil@raspberrypi.com>
2023-10-17 17:28:11 +01:00
Naushir Patuck
c145506588 drivers: media: rp1_cfe: Fix link validate test for pixel format
Now that we have removed unique PISP media bus codes, the cfe format
table has multiple entries with the same media bus code for 16-bit
formats. The test in cfe_video_link_validate() did not account for this.
Fix it by testing the media bus code and the V4L2 pixelformat 4cc
together.

As a drive-by, ensure we have a valid CSI2 datatype id when programming
the hardware block.

Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
2023-10-17 15:27:26 +01:00
Dom Cobley
0f51aa6afb Merge remote-tracking branch 'stable/linux-6.1.y' into rpi-6.1.y 2023-10-17 14:53:07 +01:00
Dave Stevenson
6ab30a5dd3 drm/vc4: Correct address offset for planes with src_[xy] offsets
11cf37e741 switched to using drm_fb_dma_get_gem_addr instead of
drm_fb_dma_get_gem_obj and adding fb->offset[].

However the tiled formats need to compute the offset in a more
involved manner than drm_fb_dma_get_gem_addr applies, and we
were ending up with the offset for src_[xy] being applied twice.

Switch back to using drm_fb_dma_get_gem_obj and fully computing
the offsets ourselves.

Fixes: 11cf37e741 ("drm/vc4: Move the buffer offset out of the vc4_plane_state")
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
2023-10-17 14:49:43 +01:00
Phil Elwell
2a47ccf97c vc_mem: Add the DMA memcpy support from bcm2708_fb
bcm2708_fb is disabled by the vc4-kms-v3d overlay, which means that the
DMA memcpy support it provides is not available to allow vclog to read
the VC logs from the top 16MB on Pi 2 and Pi 3. Add the code to the
vc_mem driver, which will still be enabled.

It ought to be possible to do a proper DMA_MEM_TO_MEM copy via the
generic DMA customer API, but that can be a later step.

Signed-off-by: Phil Elwell <phil@raspberrypi.com>
2023-10-16 17:00:41 +01:00
Greg Kroah-Hartman
adc4d740ad Linux 6.1.58
Link: https://lore.kernel.org/r/20231012180030.112560642@linuxfoundation.org
Tested-by: Florian Fainelli <florian.fainelli@broadcom.com>
Tested-by: Pavel Machek (CIP) <pavel@denx.de>
Tested-by: Guenter Roeck <linux@roeck-us.net>
Tested-by: Bagas Sanjaya <bagasdotme@gmail.com>
Tested-by: Takeshi Ogasawara <takeshi.ogasawara@futuring-girl.com>
Tested-by: Ron Economos <re@w6rz.net>
Tested-by: Ricardo B. Marliere <ricardo@marliere.net>
Tested-by: Linux Kernel Functional Testing <lkft@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2023-10-15 18:32:41 +02:00
Greg Kroah-Hartman
38fd36728f lib/test_meminit: fix off-by-one error in test_pages()
commit efb78fa86e ("lib/test_meminit: allocate pages up to order
MAX_ORDER") works great in kernels 6.4 and newer thanks to commit
23baf831a3 ("mm, treewide: redefine MAX_ORDER sanely"), but for older
kernels, the loop is off by one, which causes crashes when the test
runs.

Fix this up by changing "<= MAX_ORDER" "< MAX_ORDER" to allow the test
to work properly for older kernel branches.

Fixes: 421855d0d2 ("lib/test_meminit: allocate pages up to order MAX_ORDER")
Cc: Andrew Donnellan <ajd@linux.ibm.com>
Cc: Alexander Potapenko <glider@google.com>
Cc: Xiaoke Wang <xkernel.wang@foxmail.com>
Cc: <stable@vger.kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2023-10-15 18:32:41 +02:00
Greg Kroah-Hartman
ff74bdc838 Revert "NFS: Fix error handling for O_DIRECT write scheduling"
This reverts commit f16fd0b11f which is
commit 954998b60c upstream.

There are reported NFS problems in the 6.1.56 release, so revert a set
of NFS patches to hopefully resolve the issue.

Reported-by: poester <poester@internetbrands.com>
Link: https://lore.kernel.org/r/20231012165439.137237-2-kernel@linuxace.com
Reported-by: Daniel Díaz <daniel.diaz@linaro.org>
Link: https://lore.kernel.org/r/2023100755-livestock-barcode-fe41@gregkh
Cc: Trond Myklebust <trond.myklebust@hammerspace.com>
Cc: Anna Schumaker <Anna.Schumaker@Netapp.com>
Cc: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2023-10-15 18:32:41 +02:00
Greg Kroah-Hartman
b0cee281c4 Revert "NFS: Fix O_DIRECT locking issues"
This reverts commit 4d98038e5b which is
commit 7c6339322c upstream.

There are reported NFS problems in the 6.1.56 release, so revert a set
of NFS patches to hopefully resolve the issue.

Reported-by: poester <poester@internetbrands.com>
Link: https://lore.kernel.org/r/20231012165439.137237-2-kernel@linuxace.com
Reported-by: Daniel Díaz <daniel.diaz@linaro.org>
Link: https://lore.kernel.org/r/2023100755-livestock-barcode-fe41@gregkh
Cc: Trond Myklebust <trond.myklebust@hammerspace.com>
Cc: Anna Schumaker <Anna.Schumaker@Netapp.com>
Cc: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2023-10-15 18:32:41 +02:00
Greg Kroah-Hartman
ebf5841ac1 Revert "NFS: More O_DIRECT accounting fixes for error paths"
This reverts commit 1f49386d67 which is
commit 8982f7aff3 upstream.

There are reported NFS problems in the 6.1.56 release, so revert a set
of NFS patches to hopefully resolve the issue.

Reported-by: poester <poester@internetbrands.com>
Link: https://lore.kernel.org/r/20231012165439.137237-2-kernel@linuxace.com
Reported-by: Daniel Díaz <daniel.diaz@linaro.org>
Link: https://lore.kernel.org/r/2023100755-livestock-barcode-fe41@gregkh
Cc: Trond Myklebust <trond.myklebust@hammerspace.com>
Cc: Anna Schumaker <Anna.Schumaker@Netapp.com>
Cc: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2023-10-15 18:32:41 +02:00
Greg Kroah-Hartman
506cf335d9 Revert "NFS: Use the correct commit info in nfs_join_page_group()"
This reverts commit d4729af1c7 which is
commit b193a78ddb upstream.

There are reported NFS problems in the 6.1.56 release, so revert a set
of NFS patches to hopefully resolve the issue.

Reported-by: poester <poester@internetbrands.com>
Link: https://lore.kernel.org/r/20231012165439.137237-2-kernel@linuxace.com
Reported-by: Daniel Díaz <daniel.diaz@linaro.org>
Link: https://lore.kernel.org/r/2023100755-livestock-barcode-fe41@gregkh
Cc: Trond Myklebust <trond.myklebust@hammerspace.com>
Cc: Anna Schumaker <Anna.Schumaker@Netapp.com>
Cc: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2023-10-15 18:32:41 +02:00
Greg Kroah-Hartman
e8db8b5581 Revert "NFS: More fixes for nfs_direct_write_reschedule_io()"
This reverts commit edd1f06145 which is
commit b11243f720 upstream.

There are reported NFS problems in the 6.1.56 release, so revert a set
of NFS patches to hopefully resolve the issue.

Reported-by: poester <poester@internetbrands.com>
Link: https://lore.kernel.org/r/20231012165439.137237-2-kernel@linuxace.com
Reported-by: Daniel Díaz <daniel.diaz@linaro.org>
Link: https://lore.kernel.org/r/2023100755-livestock-barcode-fe41@gregkh
Cc: Trond Myklebust <trond.myklebust@hammerspace.com>
Cc: Anna Schumaker <Anna.Schumaker@Netapp.com>
Cc: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2023-10-15 18:32:41 +02:00
22 changed files with 523 additions and 173 deletions

View File

@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 6
PATCHLEVEL = 1
SUBLEVEL = 57
SUBLEVEL = 58
EXTRAVERSION =
NAME = Curry Ramen

View File

@@ -1,7 +1,7 @@
/* Downstream modifications to bcm2835-rpi.dtsi */
/ {
aliases {
aliases: aliases {
aux = &aux;
sound = &sound;
soc = &soc;
@@ -98,6 +98,9 @@
sdio_overclock = <&mmc>,"brcm,overclock-50:0",
<&mmcnr>,"brcm,overclock-50:0";
axiperf = <&axiperf>,"status";
drm_fb0_vc4 = <&aliases>, "drm-fb0=",&vc4;
drm_fb1_vc4 = <&aliases>, "drm-fb1=",&vc4;
drm_fb2_vc4 = <&aliases>, "drm-fb2=",&vc4;
};
};

View File

@@ -52,7 +52,7 @@
/ {
compatible = "raspberrypi,5-model-b", "brcm,bcm2712";
model = "Raspberry Pi 5 Model B";
model = "Raspberry Pi 5";
/* Will be filled by the bootloader */
memory@0 {
@@ -787,8 +787,8 @@ spi10_cs_pins: &spi10_cs_gpio1 {};
gpio4 = &pinctrl_aon;
usb0 = &rp1_usb0;
usb1 = &rp1_usb1;
drm_dsi1 = &dsi0;
drm_dsi2 = &dsi1;
drm-dsi1 = &dsi0;
drm-dsi2 = &dsi1;
};
__overrides__ {
@@ -809,6 +809,7 @@ spi10_cs_pins: &spi10_cs_gpio1 {};
i2c_baudrate = <&i2c_arm>, "clock-frequency:0";
i2c_arm_baudrate = <&i2c_arm>, "clock-frequency:0";
i2c_vc_baudrate = <&i2c_vc>, "clock-frequency:0";
krnbt = <&bluetooth>, "status";
nvme = <&pciex1>, "status";
pciex1 = <&pciex1>, "status";
pciex1_gen = <&pciex1> , "max-link-speed:0";
@@ -824,5 +825,17 @@ spi10_cs_pins: &spi10_cs_gpio1 {};
act_led_trigger = <&act_led>, "linux,default-trigger";
pwr_led_activelow = <&pwr_led>, "gpios:8";
pwr_led_trigger = <&pwr_led>, "linux,default-trigger";
drm_fb0_rp1_dsi0 = <&aliases>, "drm-fb0=",&dsi0;
drm_fb0_rp1_dsi1 = <&aliases>, "drm-fb0=",&dsi1;
drm_fb0_rp1_dpi = <&aliases>, "drm-fb0=",&dpi;
drm_fb0_vc4 = <&aliases>, "drm-fb0=",&vc4;
drm_fb1_rp1_dsi0 = <&aliases>, "drm-fb1=",&dsi0;
drm_fb1_rp1_dsi1 = <&aliases>, "drm-fb1=",&dsi1;
drm_fb1_rp1_dpi = <&aliases>, "drm-fb1=",&dpi;
drm_fb1_vc4 = <&aliases>, "drm-fb1=",&vc4;
drm_fb2_rp1_dsi0 = <&aliases>, "drm-fb2=",&dsi0;
drm_fb2_rp1_dsi1 = <&aliases>, "drm-fb2=",&dsi1;
drm_fb2_rp1_dpi = <&aliases>, "drm-fb2=",&dpi;
drm_fb2_vc4 = <&aliases>, "drm-fb2=",&vc4;
};
};

View File

@@ -103,7 +103,7 @@
};
firmwarekms: firmwarekms@7d503000 {
compatible = "raspberrypi,rpi-firmware-kms";
compatible = "raspberrypi,rpi-firmware-kms-2712";
/* SUN_L2 interrupt reg */
reg = <0x7d503000 0x18>;
interrupt-parent = <&cpu_l2_irq>;

View File

@@ -59,6 +59,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
draws.dtbo \
dwc-otg.dtbo \
dwc2.dtbo \
dwc2-pi5.dtbo \
edt-ft5406.dtbo \
enc28j60.dtbo \
enc28j60-spi2.dtbo \

View File

@@ -173,6 +173,30 @@ Params:
cooling_fan Enables the Pi 5 cooling fan (enabled
automatically by the firmware)
drm_fb0_rp1_dpi Assign /dev/fb0 to the RP1 DPI output
drm_fb0_rp1_dsi0 Assign /dev/fb0 to the RP1 DSI0 output
drm_fb0_rp1_dsi1 Assign /dev/fb0 to the RP1 DSI1 output
drm_fb0_vc4 Assign /dev/fb0 to the vc4 outputs
drm_fb1_rp1_dpi Assign /dev/fb1 to the RP1 DPI output
drm_fb1_rp1_dsi0 Assign /dev/fb1 to the RP1 DSI0 output
drm_fb1_rp1_dsi1 Assign /dev/fb1 to the RP1 DSI1 output
drm_fb1_vc4 Assign /dev/fb1 to the vc4 outputs
drm_fb2_rp1_dpi Assign /dev/fb2 to the RP1 DPI output
drm_fb2_rp1_dsi0 Assign /dev/fb2 to the RP1 DSI0 output
drm_fb2_rp1_dsi1 Assign /dev/fb2 to the RP1 DSI1 output
drm_fb2_vc4 Assign /dev/fb2 to the vc4 outputs
eee Enable Energy Efficient Ethernet support for
compatible devices (default "on"). See also
"tx_lpi_timer". Pi3B+ only.
@@ -1083,6 +1107,10 @@ Params: dr_mode Dual role mode: "host", "peripheral" or "otg"
mode
Name: dwc2-pi5
Info: See dwc2 (this is the Pi 5 version)
[ The ds1307-rtc overlay has been deleted. See i2c-rtc. ]
@@ -3714,7 +3742,7 @@ Name: rpi-ft5406
Info: Official Raspberry Pi display touchscreen
Load: dtoverlay=rpi-ft5406,<param>=<val>
Params: touchscreen-size-x Touchscreen X resolution (default 800)
touchscreen-size-y Touchscreen Y resolution (default 600);
touchscreen-size-y Touchscreen Y resolution (default 480);
touchscreen-inverted-x Invert touchscreen X coordinates (default 0);
touchscreen-inverted-y Invert touchscreen Y coordinates (default 0);
touchscreen-swapped-x-y Swap X and Y cordinates (default 0);

View File

@@ -0,0 +1,18 @@
#include "dwc2-overlay.dts"
/{
fragment@1 {
target-path = "/";
__overlay__ {
/*
* Add a node with a dma-ranges value that exists only to be found
* by of_dma_get_max_cpu_address, and hence limit the DMA zone.
*/
zone_dma {
#address-cells = <1>;
#size-cells = <1>;
dma-ranges = <0x0 0x0 0x0 0x40000000>;
};
};
};
};

View File

@@ -24,30 +24,13 @@
};
fragment@2 {
target = <&i2cbus>;
__overlay__ {
#address-cells = <1>;
#size-cells = <0>;
mcp23017: mcp@20 {
compatible = "microchip,mcp23017";
reg = <0x20>;
gpio-controller;
#gpio-cells = <2>;
status = "okay";
};
};
};
fragment@3 {
target = <&mcp23017>;
__dormant__ {
compatible = "microchip,mcp23008";
};
};
fragment@4 {
fragment@3 {
target = <&mcp23017>;
mcp23017_irq: __overlay__ {
#interrupt-cells=<2>;
@@ -58,6 +41,25 @@
};
};
fragment@4 {
target = <&i2cbus>;
__overlay__ {
#address-cells = <1>;
#size-cells = <0>;
mcp23017: mcp@20 {
compatible = "microchip,mcp23017";
pinctrl-name = "default";
pinctrl-0 = <&mcp23017_pins>;
reg = <0x20>;
gpio-controller;
#gpio-cells = <2>;
status = "okay";
};
};
};
frag100: fragment@100 {
target = <&i2c1>;
i2cbus: __overlay__ {
@@ -83,8 +85,8 @@
gpiopin = <&mcp23017_pins>,"brcm,pins:0",
<&mcp23017_irq>,"interrupts:0";
addr = <&mcp23017>,"reg:0", <&mcp23017_pins>,"reg:0";
mcp23008 = <0>,"=3";
noints = <0>,"!1!4";
mcp23008 = <0>,"=2";
noints = <0>,"!1!3";
i2c0 = <&frag100>, "target:0=",<&i2c0>;
i2c_csi_dsi = <&frag100>, "target:0=",<&i2c_csi_dsi>,
<0>,"+101+102";

View File

@@ -48,6 +48,16 @@
bcm2712;
};
dwc2 {
bcm2835;
bcm2711;
bcm2712 = "dwc2-pi5";
};
dwc2-pi5 {
bcm2712;
};
highperi {
bcm2711;
};

View File

@@ -23,9 +23,21 @@
#include <linux/uaccess.h>
#include <linux/dma-mapping.h>
#include <linux/broadcom/vc_mem.h>
#include <linux/compat.h>
#include <linux/platform_data/dma-bcm2708.h>
#include <soc/bcm2835/raspberrypi-firmware.h>
#define DRIVER_NAME "vc-mem"
/* N.B. These use a different magic value for compatibility with bmc7208_fb */
#define VC_MEM_IOC_DMACOPY _IOW('z', 0x22, struct vc_mem_dmacopy)
#define VC_MEM_IOC_DMACOPY32 _IOW('z', 0x22, struct vc_mem_dmacopy32)
/* address with no aliases */
#define INTALIAS_NORMAL(x) ((x) & ~0xc0000000)
/* cache coherent but non-allocating in L1 and L2 */
#define INTALIAS_L1L2_NONALLOCATING(x) (((x) & ~0xc0000000) | 0x80000000)
/* Device (/dev) related variables */
static dev_t vc_mem_devnum;
static struct class *vc_mem_class;
@@ -36,6 +48,20 @@ static int vc_mem_inited;
static struct dentry *vc_mem_debugfs_entry;
#endif
struct vc_mem_dmacopy {
void *dst;
__u32 src;
__u32 length;
};
#ifdef CONFIG_COMPAT
struct vc_mem_dmacopy32 {
compat_uptr_t dst;
__u32 src;
__u32 length;
};
#endif
/*
* Videocore memory addresses and size
*
@@ -62,6 +88,20 @@ static uint phys_addr;
static uint mem_size;
static uint mem_base;
struct vc_mem_dma {
struct device *dev;
int dma_chan;
int dma_irq;
void __iomem *dma_chan_base;
wait_queue_head_t dma_waitq;
void *cb_base; /* DMA control blocks */
dma_addr_t cb_handle;
};
struct { u32 base, length; } gpu_mem;
static struct mutex dma_mutex;
static struct vc_mem_dma vc_mem_dma;
static int
vc_mem_open(struct inode *inode, struct file *file)
{
@@ -99,6 +139,189 @@ vc_mem_get_current_size(void)
}
EXPORT_SYMBOL_GPL(vc_mem_get_current_size);
static int
vc_mem_dma_init(void)
{
struct vc_mem_dma *vcdma = &vc_mem_dma;
struct platform_device *pdev;
struct device_node *fwnode;
struct rpi_firmware *fw;
struct device *dev;
u32 revision;
int rc;
if (vcdma->dev)
return 0;
fwnode = of_find_node_by_path("/system");
rc = of_property_read_u32(fwnode, "linux,revision", &revision);
revision = (revision >> 12) & 0xf;
if (revision != 1 && revision != 2) {
/* Only BCM2709 and BCM2710 may have logs where the ARMs
* can't see them.
*/
return -ENXIO;
}
fwnode = rpi_firmware_find_node();
if (!fwnode)
return -ENXIO;
pdev = of_find_device_by_node(fwnode);
dev = &pdev->dev;
rc = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
if (rc)
return rc;
fw = rpi_firmware_get(fwnode);
if (!fw)
return -ENXIO;
rc = rpi_firmware_property(fw, RPI_FIRMWARE_GET_VC_MEMORY,
&gpu_mem, sizeof(gpu_mem));
if (rc)
return rc;
gpu_mem.base = INTALIAS_NORMAL(gpu_mem.base);
if (!gpu_mem.base || !gpu_mem.length) {
dev_err(dev, "%s: unable to determine gpu memory (%x,%x)\n",
__func__, gpu_mem.base, gpu_mem.length);
return -EFAULT;
}
vcdma->cb_base = dma_alloc_wc(dev, SZ_4K, &vcdma->cb_handle, GFP_KERNEL);
if (!vcdma->cb_base) {
dev_err(dev, "failed to allocate DMA CBs\n");
return -ENOMEM;
}
rc = bcm_dma_chan_alloc(BCM_DMA_FEATURE_BULK,
&vcdma->dma_chan_base,
&vcdma->dma_irq);
if (rc < 0) {
dev_err(dev, "failed to allocate a DMA channel\n");
goto free_cb;
}
vcdma->dma_chan = rc;
init_waitqueue_head(&vcdma->dma_waitq);
vcdma->dev = dev;
return 0;
free_cb:
dma_free_wc(dev, SZ_4K, vcdma->cb_base, vcdma->cb_handle);
return rc;
}
static void
vc_mem_dma_uninit(void)
{
struct vc_mem_dma *vcdma = &vc_mem_dma;
if (vcdma->dev) {
bcm_dma_chan_free(vcdma->dma_chan);
dma_free_wc(vcdma->dev, SZ_4K, vcdma->cb_base, vcdma->cb_handle);
vcdma->dev = NULL;
}
}
static int dma_memcpy(struct vc_mem_dma *vcdma, dma_addr_t dst, dma_addr_t src,
int size)
{
struct bcm2708_dma_cb *cb = vcdma->cb_base;
int burst_size = (vcdma->dma_chan == 0) ? 8 : 2;
cb->info = BCM2708_DMA_BURST(burst_size) | BCM2708_DMA_S_WIDTH |
BCM2708_DMA_S_INC | BCM2708_DMA_D_WIDTH |
BCM2708_DMA_D_INC;
cb->dst = dst;
cb->src = src;
cb->length = size;
cb->stride = 0;
cb->pad[0] = 0;
cb->pad[1] = 0;
cb->next = 0;
bcm_dma_start(vcdma->dma_chan_base, vcdma->cb_handle);
bcm_dma_wait_idle(vcdma->dma_chan_base);
return 0;
}
static long vc_mem_copy(struct vc_mem_dmacopy *ioparam)
{
struct vc_mem_dma *vcdma = &vc_mem_dma;
size_t size = PAGE_SIZE;
const u32 dma_xfer_chunk = 256;
u32 *buf = NULL;
dma_addr_t bus_addr;
long rc = 0;
size_t offset;
/* restrict this to root user */
if (!uid_eq(current_euid(), GLOBAL_ROOT_UID))
return -EFAULT;
if (mutex_lock_interruptible(&dma_mutex))
return -EINTR;
rc = vc_mem_dma_init();
if (rc)
goto out;
vcdma = &vc_mem_dma;
if (INTALIAS_NORMAL(ioparam->src) < gpu_mem.base ||
INTALIAS_NORMAL(ioparam->src) >= gpu_mem.base + gpu_mem.length) {
pr_err("%s: invalid memory access %x (%x-%x)", __func__,
INTALIAS_NORMAL(ioparam->src), gpu_mem.base,
gpu_mem.base + gpu_mem.length);
rc = -EFAULT;
goto out;
}
buf = dma_alloc_coherent(vcdma->dev, PAGE_ALIGN(size), &bus_addr,
GFP_ATOMIC);
if (!buf) {
rc = -ENOMEM;
goto out;
}
for (offset = 0; offset < ioparam->length; offset += size) {
size_t remaining = ioparam->length - offset;
size_t s = min(size, remaining);
u8 *p = (u8 *)((uintptr_t)ioparam->src + offset);
u8 *q = (u8 *)ioparam->dst + offset;
rc = dma_memcpy(vcdma, bus_addr,
INTALIAS_L1L2_NONALLOCATING((u32)(uintptr_t)p),
(s + dma_xfer_chunk - 1) & ~(dma_xfer_chunk - 1));
if (rc) {
dev_err(vcdma->dev, "dma_memcpy failed\n");
break;
}
if (copy_to_user(q, buf, s) != 0) {
pr_err("%s: copy_to_user failed\n", __func__);
rc = -EFAULT;
break;
}
}
out:
if (buf)
dma_free_coherent(vcdma->dev, PAGE_ALIGN(size), buf,
bus_addr);
mutex_unlock(&dma_mutex);
return rc;
}
static long
vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
@@ -163,6 +386,21 @@ vc_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
break;
}
case VC_MEM_IOC_DMACOPY:
{
struct vc_mem_dmacopy ioparam;
/* Get the parameter data.
*/
if (copy_from_user
(&ioparam, (void *)arg, sizeof(ioparam))) {
pr_err("%s: copy_from_user failed\n", __func__);
rc = -EFAULT;
break;
}
rc = vc_mem_copy(&ioparam);
break;
}
default:
{
return -ENOTTY;
@@ -193,6 +431,24 @@ vc_mem_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break;
case VC_MEM_IOC_DMACOPY32:
{
struct vc_mem_dmacopy32 param32;
struct vc_mem_dmacopy param;
/* Get the parameter data.
*/
if (copy_from_user(&param32, (void *)arg, sizeof(param32))) {
pr_err("%s: copy_from_user failed\n", __func__);
rc = -EFAULT;
break;
}
param.dst = compat_ptr(param32.dst);
param.src = param32.src;
param.length = param32.length;
rc = vc_mem_copy(&param);
break;
}
default:
rc = vc_mem_ioctl(file, cmd, arg);
break;
@@ -330,6 +586,7 @@ vc_mem_init(void)
vc_mem_debugfs_init(dev);
#endif
mutex_init(&dma_mutex);
vc_mem_inited = 1;
return 0;
@@ -352,6 +609,7 @@ vc_mem_exit(void)
{
pr_debug("%s: called\n", __func__);
vc_mem_dma_uninit();
if (vc_mem_inited) {
#ifdef CONFIG_DEBUG_FS
vc_mem_debugfs_deinit();
@@ -360,6 +618,7 @@ vc_mem_exit(void)
class_destroy(vc_mem_class);
cdev_del(&vc_mem_cdev);
unregister_chrdev_region(vc_mem_devnum, 1);
vc_mem_inited = 0;
}
}

View File

@@ -112,7 +112,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] = {
};
#define MAX_DT_NODE_NAME_LEN 20
#define DT_DRM_NODE_PREFIX "drm_"
#define DT_DRM_NODE_PREFIX "drm-"
static void drm_connector_get_of_name(int type, char *node_name, int length)
{

View File

@@ -1932,7 +1932,7 @@ __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper,
struct drm_device *dev = fb_helper->dev;
struct fb_info *info;
unsigned int width, height;
int ret;
int ret, id;
width = dev->mode_config.max_width;
height = dev->mode_config.max_height;
@@ -1967,6 +1967,15 @@ __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper,
* register the fbdev emulation instance in kernel_fb_helper_list. */
mutex_unlock(&fb_helper->lock);
id = of_alias_get_highest_id("drm-fb");
if (id >= 0)
fb_set_lowest_dynamic_fb(id + 1);
id = of_alias_get_id(dev->dev->of_node, "drm-fb");
if (id >= 0) {
info->node = id;
info->custom_fb_num = true;
}
ret = register_framebuffer(info);
if (ret < 0)
return ret;

View File

@@ -47,9 +47,15 @@ struct get_display_cfg {
u32 max_pixel_clock[2]; //Max pixel clock for each display
};
enum vc4_fkms_revision {
BCM2835_6_7,
BCM2711,
BCM2712,
};
struct vc4_fkms {
struct get_display_cfg cfg;
bool bcm2711;
enum vc4_fkms_revision revision;
};
#define PLANES_PER_CRTC 8
@@ -255,6 +261,13 @@ static const struct vc_image_format *vc4_get_vc_image_fmt(u32 drm_format)
/* The firmware delivers a vblank interrupt to us through the SMI
* hardware, which has only this one register.
*/
#define SMICS 0x0
#define SMIDSW0 0x14
#define SMIDSW1 0x1C
#define SMICS_INTERRUPTS (BIT(9) | BIT(10) | BIT(11))
/* Flag to denote that the firmware is giving multiple display callbacks */
#define SMI_NEW 0xabcd0000
#define vc4_crtc vc4_kms_crtc
#define to_vc4_crtc to_vc4_kms_crtc
@@ -1142,7 +1155,7 @@ vc4_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
/* Pi4 can't generate odd horizontal timings on HDMI, so reject modes
* that would set them.
*/
if (fkms->bcm2711 &&
if (fkms->revision >= BCM2711 &&
(vc4_crtc->display_number == 2 || vc4_crtc->display_number == 7) &&
!(mode->flags & DRM_MODE_FLAG_DBLCLK) &&
((mode->hdisplay | /* active */
@@ -1214,13 +1227,16 @@ static irqreturn_t vc4_crtc_irq_handler(int irq, void *data)
{
struct vc4_crtc **crtc_list = data;
int i;
u32 stat = readl(crtc_list[0]->regs + SMICS);
irqreturn_t ret = IRQ_NONE;
u32 chan;
if (1) {
chan = 0;
if (stat & SMICS_INTERRUPTS) {
writel(0, crtc_list[0]->regs + SMICS);
if (1) {
chan = readl(crtc_list[0]->regs + SMIDSW0);
if ((chan & 0xFFFF0000) != SMI_NEW) {
/* Older firmware. Treat the one interrupt as vblank/
* complete for all crtcs.
*/
@@ -1231,7 +1247,7 @@ static irqreturn_t vc4_crtc_irq_handler(int irq, void *data)
}
} else {
if (chan & 1) {
//writel(SMI_NEW, crtc_list[0]->regs + SMIDSW0);
writel(SMI_NEW, crtc_list[0]->regs + SMIDSW0);
if (crtc_list[0]->vblank_enabled)
drm_crtc_handle_vblank(&crtc_list[0]->base);
vc4_crtc_handle_page_flip(crtc_list[0]);
@@ -1239,10 +1255,10 @@ static irqreturn_t vc4_crtc_irq_handler(int irq, void *data)
if (crtc_list[1]) {
/* Check for the secondary display too */
//chan = readl(crtc_list[0]->regs + SMIDSW1);
chan = readl(crtc_list[0]->regs + SMIDSW1);
if (chan & 1) {
//writel(SMI_NEW, crtc_list[0]->regs + SMIDSW1);
writel(SMI_NEW, crtc_list[0]->regs + SMIDSW1);
if (crtc_list[1]->vblank_enabled)
drm_crtc_handle_vblank(&crtc_list[1]->base);
@@ -1257,6 +1273,20 @@ static irqreturn_t vc4_crtc_irq_handler(int irq, void *data)
return ret;
}
static irqreturn_t vc4_crtc2712_irq_handler(int irq, void *data)
{
struct vc4_crtc **crtc_list = data;
int i;
for (i = 0; crtc_list[i]; i++) {
if (crtc_list[i]->vblank_enabled)
drm_crtc_handle_vblank(&crtc_list[i]->base);
vc4_crtc_handle_page_flip(crtc_list[i]);
}
return IRQ_HANDLED;
}
static int vc4_fkms_page_flip(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
@@ -1342,9 +1372,12 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
};
static const struct of_device_id vc4_firmware_kms_dt_match[] = {
{ .compatible = "raspberrypi,rpi-firmware-kms" },
{ .compatible = "raspberrypi,rpi-firmware-kms",
.data = (void *)BCM2835_6_7 },
{ .compatible = "raspberrypi,rpi-firmware-kms-2711",
.data = (void *)1 },
.data = (void *)BCM2711 },
{ .compatible = "raspberrypi,rpi-firmware-kms-2712",
.data = (void *)BCM2712 },
{}
};
@@ -1914,8 +1947,7 @@ static int vc4_fkms_bind(struct device *dev, struct device *master, void *data)
match = of_match_device(vc4_firmware_kms_dt_match, dev);
if (!match)
return -ENODEV;
if (match->data)
fkms->bcm2711 = true;
fkms->revision = (enum vc4_fkms_revision)match->data;
firmware_node = of_parse_phandle(dev->of_node, "brcm,firmware", 0);
vc4->firmware = devm_rpi_firmware_get(&pdev->dev, firmware_node);
@@ -1982,10 +2014,16 @@ static int vc4_fkms_bind(struct device *dev, struct device *master, void *data)
if (IS_ERR(crtc_list[0]->regs))
DRM_ERROR("Oh dear, failed to map registers\n");
//writel(0, crtc_list[0]->regs + SMICS);
ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
vc4_crtc_irq_handler, 0,
"vc4 firmware kms", crtc_list);
if (fkms->revision >= BCM2712) {
ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
vc4_crtc2712_irq_handler, 0,
"vc4 firmware kms", crtc_list);
} else {
writel(0, crtc_list[0]->regs + SMICS);
ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
vc4_crtc_irq_handler, 0,
"vc4 firmware kms", crtc_list);
}
if (ret)
DRM_ERROR("Oh dear, failed to register IRQ\n");
} else {

View File

@@ -1447,9 +1447,9 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
vc4_state->ptr0_offset[0] = vc4_state->dlist_count;
for (i = 0; i < num_planes; i++) {
dma_addr_t paddr = drm_fb_dma_get_gem_addr(fb, state, i);
struct drm_gem_dma_object *bo = drm_fb_dma_get_gem_obj(fb, i);
vc4_dlist_write(vc4_state, paddr + offsets[i]);
vc4_dlist_write(vc4_state, bo->dma_addr + fb->offsets[i] + offsets[i]);
}
/* Pointer Context Word 0/1/2: Written by the HVS */
@@ -1842,9 +1842,8 @@ static int vc6_plane_mode_set(struct drm_plane *plane,
* TODO: This only covers Raster Scan Order planes
*/
for (i = 0; i < num_planes; i++) {
dma_addr_t paddr = drm_fb_dma_get_gem_addr(fb, state, i);
paddr += offsets[i];
struct drm_gem_dma_object *bo = drm_fb_dma_get_gem_obj(fb, i);
dma_addr_t paddr = bo->dma_addr + fb->offsets[i] + offsets[i];
/* Pointer Word 0 */
vc4_state->ptr0_offset[i] = vc4_state->dlist_count;

View File

@@ -632,7 +632,7 @@ static const struct imx477_reg mode_2028x1520_regs[] = {
{0x9e9f, 0x00},
{0xa2a9, 0x60},
{0xa2b7, 0x00},
{0x0401, 0x01},
{0x0401, 0x00},
{0x0404, 0x00},
{0x0405, 0x20},
{0x0408, 0x00},
@@ -733,7 +733,7 @@ static const struct imx477_reg mode_2028x1080_regs[] = {
{0x9e9f, 0x00},
{0xa2a9, 0x60},
{0xa2b7, 0x00},
{0x0401, 0x01},
{0x0401, 0x00},
{0x0404, 0x00},
{0x0405, 0x20},
{0x0408, 0x00},

View File

@@ -786,6 +786,9 @@ static void cfe_start_channel(struct cfe_node *node)
width = source_fmt->width;
height = source_fmt->height;
/* Must have a valid CSI2 datatype. */
WARN_ON(!fmt->csi_dt);
/*
* Start the associated CSI2 Channel as well.
*
@@ -809,6 +812,9 @@ static void cfe_start_channel(struct cfe_node *node)
node_desc[node->id].link_pad - CSI2_NUM_CHANNELS);
fmt = find_format_by_code(source_fmt->code);
/* Must have a valid CSI2 datatype. */
WARN_ON(!fmt->csi_dt);
if (is_image_output_node(node)) {
width = source_fmt->width;
height = source_fmt->height;
@@ -1504,7 +1510,8 @@ static int cfe_video_link_validate(struct media_link *link)
if (is_image_output_node(node)) {
struct v4l2_pix_format *pix_fmt = &node->fmt.fmt.pix;
const struct cfe_fmt *fmt;
const struct cfe_fmt *fmt = NULL;
unsigned int i;
if (source_fmt->width != pix_fmt->width ||
source_fmt->height != pix_fmt->height) {
@@ -1516,8 +1523,14 @@ static int cfe_video_link_validate(struct media_link *link)
goto out;
}
fmt = find_format_by_code(source_fmt->code);
if (!fmt || fmt->fourcc != pix_fmt->pixelformat) {
for (i = 0; i < ARRAY_SIZE(formats); i++) {
if (formats[i].code == source_fmt->code &&
formats[i].fourcc == pix_fmt->pixelformat) {
fmt = &formats[i];
break;
}
}
if (!fmt) {
cfe_err("Format mismatch!\n");
ret = -EINVAL;
goto out;

View File

@@ -52,6 +52,7 @@ static DEFINE_MUTEX(registration_lock);
struct fb_info *registered_fb[FB_MAX] __read_mostly;
int num_registered_fb __read_mostly;
int min_dynamic_fb __read_mostly;
#define for_each_registered_fb(i) \
for (i = 0; i < FB_MAX; i++) \
if (!registered_fb[i]) {} else
@@ -1579,19 +1580,22 @@ static int do_register_framebuffer(struct fb_info *fb_info)
return -ENXIO;
num_registered_fb++;
for (i = 0 ; i < FB_MAX; i++)
if (!registered_fb[i])
break;
fb_info->node = i;
if (!fb_info->custom_fb_num || fb_info->node >= FB_MAX || registered_fb[fb_info->node]) {
for (i = min_dynamic_fb ; i < FB_MAX; i++)
if (!registered_fb[i])
break;
fb_info->node = i;
}
refcount_set(&fb_info->count, 1);
mutex_init(&fb_info->lock);
mutex_init(&fb_info->mm_lock);
fb_info->dev = device_create(fb_class, fb_info->device,
MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
MKDEV(FB_MAJOR, fb_info->node), NULL, "fb%d", fb_info->node);
if (IS_ERR(fb_info->dev)) {
/* Not fatal */
printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));
printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n",
fb_info->node, PTR_ERR(fb_info->dev));
fb_info->dev = NULL;
} else
fb_init_device(fb_info);
@@ -1624,7 +1628,7 @@ static int do_register_framebuffer(struct fb_info *fb_info)
fb_var_to_videomode(&mode, &fb_info->var);
fb_add_videomode(&mode, &fb_info->modelist);
registered_fb[i] = fb_info;
registered_fb[fb_info->node] = fb_info;
#ifdef CONFIG_GUMSTIX_AM200EPD
{
@@ -1719,6 +1723,12 @@ static int fb_aperture_acquire_for_platform_device(struct fb_info *fb_info)
return ret;
}
void fb_set_lowest_dynamic_fb(int min_fb_dev)
{
min_dynamic_fb = min_fb_dev;
}
EXPORT_SYMBOL(fb_set_lowest_dynamic_fb);
/**
* register_framebuffer - registers a frame buffer device
* @fb_info: frame buffer info structure

View File

@@ -93,10 +93,12 @@ nfs_direct_handle_truncated(struct nfs_direct_req *dreq,
dreq->max_count = dreq_len;
if (dreq->count > dreq_len)
dreq->count = dreq_len;
}
if (test_bit(NFS_IOHDR_ERROR, &hdr->flags) && !dreq->error)
dreq->error = hdr->error;
if (test_bit(NFS_IOHDR_ERROR, &hdr->flags))
dreq->error = hdr->error;
else /* Clear outstanding error if this is EOF */
dreq->error = 0;
}
}
static void
@@ -118,18 +120,6 @@ nfs_direct_count_bytes(struct nfs_direct_req *dreq,
dreq->count = dreq_len;
}
static void nfs_direct_truncate_request(struct nfs_direct_req *dreq,
struct nfs_page *req)
{
loff_t offs = req_offset(req);
size_t req_start = (size_t)(offs - dreq->io_start);
if (req_start < dreq->max_count)
dreq->max_count = req_start;
if (req_start < dreq->count)
dreq->count = req_start;
}
/**
* nfs_swap_rw - NFS address space operation for swap I/O
* @iocb: target I/O control block
@@ -500,9 +490,7 @@ static void nfs_direct_add_page_head(struct list_head *list,
kref_get(&head->wb_kref);
}
static void nfs_direct_join_group(struct list_head *list,
struct nfs_commit_info *cinfo,
struct inode *inode)
static void nfs_direct_join_group(struct list_head *list, struct inode *inode)
{
struct nfs_page *req, *subreq;
@@ -524,7 +512,7 @@ static void nfs_direct_join_group(struct list_head *list,
nfs_release_request(subreq);
}
} while ((subreq = subreq->wb_this_page) != req);
nfs_join_page_group(req, cinfo, inode);
nfs_join_page_group(req, inode);
}
}
@@ -542,15 +530,20 @@ nfs_direct_write_scan_commit_list(struct inode *inode,
static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
{
struct nfs_pageio_descriptor desc;
struct nfs_page *req;
struct nfs_page *req, *tmp;
LIST_HEAD(reqs);
struct nfs_commit_info cinfo;
LIST_HEAD(failed);
nfs_init_cinfo_from_dreq(&cinfo, dreq);
nfs_direct_write_scan_commit_list(dreq->inode, &reqs, &cinfo);
nfs_direct_join_group(&reqs, &cinfo, dreq->inode);
nfs_direct_join_group(&reqs, dreq->inode);
dreq->count = 0;
dreq->max_count = 0;
list_for_each_entry(req, &reqs, wb_list)
dreq->max_count += req->wb_bytes;
nfs_clear_pnfs_ds_commit_verifiers(&dreq->ds_cinfo);
get_dreq(dreq);
@@ -558,40 +551,27 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
&nfs_direct_write_completion_ops);
desc.pg_dreq = dreq;
while (!list_empty(&reqs)) {
req = nfs_list_entry(reqs.next);
list_for_each_entry_safe(req, tmp, &reqs, wb_list) {
/* Bump the transmission count */
req->wb_nio++;
if (!nfs_pageio_add_request(&desc, req)) {
spin_lock(&dreq->lock);
if (dreq->error < 0) {
desc.pg_error = dreq->error;
} else if (desc.pg_error != -EAGAIN) {
dreq->flags = 0;
if (!desc.pg_error)
desc.pg_error = -EIO;
nfs_list_move_request(req, &failed);
spin_lock(&cinfo.inode->i_lock);
dreq->flags = 0;
if (desc.pg_error < 0)
dreq->error = desc.pg_error;
} else
dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
spin_unlock(&dreq->lock);
break;
else
dreq->error = -EIO;
spin_unlock(&cinfo.inode->i_lock);
}
nfs_release_request(req);
}
nfs_pageio_complete(&desc);
while (!list_empty(&reqs)) {
req = nfs_list_entry(reqs.next);
while (!list_empty(&failed)) {
req = nfs_list_entry(failed.next);
nfs_list_remove_request(req);
nfs_unlock_and_release_request(req);
if (desc.pg_error == -EAGAIN) {
nfs_mark_request_commit(req, NULL, &cinfo, 0);
} else {
spin_lock(&dreq->lock);
nfs_direct_truncate_request(dreq, req);
spin_unlock(&dreq->lock);
nfs_release_request(req);
}
}
if (put_dreq(dreq))
@@ -611,6 +591,8 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
if (status < 0) {
/* Errors in commit are fatal */
dreq->error = status;
dreq->max_count = 0;
dreq->count = 0;
dreq->flags = NFS_ODIRECT_DONE;
} else {
status = dreq->error;
@@ -621,12 +603,7 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
while (!list_empty(&data->pages)) {
req = nfs_list_entry(data->pages.next);
nfs_list_remove_request(req);
if (status < 0) {
spin_lock(&dreq->lock);
nfs_direct_truncate_request(dreq, req);
spin_unlock(&dreq->lock);
nfs_release_request(req);
} else if (!nfs_write_match_verf(verf, req)) {
if (status >= 0 && !nfs_write_match_verf(verf, req)) {
dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
/*
* Despite the reboot, the write was successful,
@@ -634,7 +611,7 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
*/
req->wb_nio = 0;
nfs_mark_request_commit(req, NULL, &cinfo, 0);
} else
} else /* Error or match */
nfs_release_request(req);
nfs_unlock_and_release_request(req);
}
@@ -687,7 +664,6 @@ static void nfs_direct_write_clear_reqs(struct nfs_direct_req *dreq)
while (!list_empty(&reqs)) {
req = nfs_list_entry(reqs.next);
nfs_list_remove_request(req);
nfs_direct_truncate_request(dreq, req);
nfs_release_request(req);
nfs_unlock_and_release_request(req);
}
@@ -737,8 +713,7 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
}
nfs_direct_count_bytes(dreq, hdr);
if (test_bit(NFS_IOHDR_UNSTABLE_WRITES, &hdr->flags) &&
!test_bit(NFS_IOHDR_ERROR, &hdr->flags)) {
if (test_bit(NFS_IOHDR_UNSTABLE_WRITES, &hdr->flags)) {
if (!dreq->flags)
dreq->flags = NFS_ODIRECT_DO_COMMIT;
flags = dreq->flags;
@@ -782,23 +757,18 @@ static void nfs_write_sync_pgio_error(struct list_head *head, int error)
static void nfs_direct_write_reschedule_io(struct nfs_pgio_header *hdr)
{
struct nfs_direct_req *dreq = hdr->dreq;
struct nfs_page *req;
struct nfs_commit_info cinfo;
trace_nfs_direct_write_reschedule_io(dreq);
nfs_init_cinfo_from_dreq(&cinfo, dreq);
spin_lock(&dreq->lock);
if (dreq->error == 0)
if (dreq->error == 0) {
dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
set_bit(NFS_IOHDR_REDO, &hdr->flags);
spin_unlock(&dreq->lock);
while (!list_empty(&hdr->pages)) {
req = nfs_list_entry(hdr->pages.next);
nfs_list_remove_request(req);
nfs_unlock_request(req);
nfs_mark_request_commit(req, NULL, &cinfo, 0);
/* fake unstable write to let common nfs resend pages */
hdr->verf.committed = NFS_UNSTABLE;
hdr->good_bytes = hdr->args.offset + hdr->args.count -
hdr->io_start;
}
spin_unlock(&dreq->lock);
}
static const struct nfs_pgio_completion_ops nfs_direct_write_completion_ops = {
@@ -826,11 +796,9 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
{
struct nfs_pageio_descriptor desc;
struct inode *inode = dreq->inode;
struct nfs_commit_info cinfo;
ssize_t result = 0;
size_t requested_bytes = 0;
size_t wsize = max_t(size_t, NFS_SERVER(inode)->wsize, PAGE_SIZE);
bool defer = false;
trace_nfs_direct_write_schedule_iovec(dreq);
@@ -871,39 +839,19 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
break;
}
nfs_lock_request(req);
req->wb_index = pos >> PAGE_SHIFT;
req->wb_offset = pos & ~PAGE_MASK;
if (!nfs_pageio_add_request(&desc, req)) {
result = desc.pg_error;
nfs_unlock_and_release_request(req);
break;
}
pgbase = 0;
bytes -= req_len;
requested_bytes += req_len;
pos += req_len;
dreq->bytes_left -= req_len;
if (defer) {
nfs_mark_request_commit(req, NULL, &cinfo, 0);
continue;
}
nfs_lock_request(req);
req->wb_index = pos >> PAGE_SHIFT;
req->wb_offset = pos & ~PAGE_MASK;
if (nfs_pageio_add_request(&desc, req))
continue;
/* Exit on hard errors */
if (desc.pg_error < 0 && desc.pg_error != -EAGAIN) {
result = desc.pg_error;
nfs_unlock_and_release_request(req);
break;
}
/* If the error is soft, defer remaining requests */
nfs_init_cinfo_from_dreq(&cinfo, dreq);
spin_lock(&dreq->lock);
dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
spin_unlock(&dreq->lock);
nfs_unlock_request(req);
nfs_mark_request_commit(req, NULL, &cinfo, 0);
desc.pg_error = 0;
defer = true;
}
nfs_direct_release_pages(pagevec, npages);
kvfree(pagevec);

View File

@@ -58,8 +58,7 @@ static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops;
static const struct nfs_commit_completion_ops nfs_commit_completion_ops;
static const struct nfs_rw_ops nfs_rw_write_ops;
static void nfs_inode_remove_request(struct nfs_page *req);
static void nfs_clear_request_commit(struct nfs_commit_info *cinfo,
struct nfs_page *req);
static void nfs_clear_request_commit(struct nfs_page *req);
static void nfs_init_cinfo_from_inode(struct nfs_commit_info *cinfo,
struct inode *inode);
static struct nfs_page *
@@ -503,8 +502,8 @@ nfs_destroy_unlinked_subrequests(struct nfs_page *destroy_list,
* the (former) group. All subrequests are removed from any write or commit
* lists, unlinked from the group and destroyed.
*/
void nfs_join_page_group(struct nfs_page *head, struct nfs_commit_info *cinfo,
struct inode *inode)
void
nfs_join_page_group(struct nfs_page *head, struct inode *inode)
{
struct nfs_page *subreq;
struct nfs_page *destroy_list = NULL;
@@ -534,7 +533,7 @@ void nfs_join_page_group(struct nfs_page *head, struct nfs_commit_info *cinfo,
* Commit list removal accounting is done after locks are dropped */
subreq = head;
do {
nfs_clear_request_commit(cinfo, subreq);
nfs_clear_request_commit(subreq);
subreq = subreq->wb_this_page;
} while (subreq != head);
@@ -568,10 +567,8 @@ nfs_lock_and_join_requests(struct page *page)
{
struct inode *inode = page_file_mapping(page)->host;
struct nfs_page *head;
struct nfs_commit_info cinfo;
int ret;
nfs_init_cinfo_from_inode(&cinfo, inode);
/*
* A reference is taken only on the head request which acts as a
* reference to the whole page group - the group will not be destroyed
@@ -588,7 +585,7 @@ nfs_lock_and_join_requests(struct page *page)
return ERR_PTR(ret);
}
nfs_join_page_group(head, &cinfo, inode);
nfs_join_page_group(head, inode);
return head;
}
@@ -959,16 +956,18 @@ nfs_clear_page_commit(struct page *page)
}
/* Called holding the request lock on @req */
static void nfs_clear_request_commit(struct nfs_commit_info *cinfo,
struct nfs_page *req)
static void
nfs_clear_request_commit(struct nfs_page *req)
{
if (test_bit(PG_CLEAN, &req->wb_flags)) {
struct nfs_open_context *ctx = nfs_req_openctx(req);
struct inode *inode = d_inode(ctx->dentry);
struct nfs_commit_info cinfo;
nfs_init_cinfo_from_inode(&cinfo, inode);
mutex_lock(&NFS_I(inode)->commit_mutex);
if (!pnfs_clear_request_commit(req, cinfo)) {
nfs_request_remove_commit_list(req, cinfo);
if (!pnfs_clear_request_commit(req, &cinfo)) {
nfs_request_remove_commit_list(req, &cinfo);
}
mutex_unlock(&NFS_I(inode)->commit_mutex);
nfs_clear_page_commit(req->wb_page);

View File

@@ -512,6 +512,7 @@ struct fb_info {
} *apertures;
bool skip_vt_switch; /* no VT switch on suspend/resume required */
bool custom_fb_num; /* Use value in node as the preferred node number */
};
static inline struct apertures_struct *alloc_apertures(unsigned int max_num) {
@@ -614,6 +615,7 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
size_t count, loff_t *ppos);
/* drivers/video/fbmem.c */
extern void fb_set_lowest_dynamic_fb(int min_fb_dev);
extern int register_framebuffer(struct fb_info *fb_info);
extern void unregister_framebuffer(struct fb_info *fb_info);
extern int fb_prepare_logo(struct fb_info *fb_info, int rotate);

View File

@@ -145,9 +145,7 @@ extern void nfs_unlock_request(struct nfs_page *req);
extern void nfs_unlock_and_release_request(struct nfs_page *);
extern struct nfs_page *nfs_page_group_lock_head(struct nfs_page *req);
extern int nfs_page_group_lock_subrequests(struct nfs_page *head);
extern void nfs_join_page_group(struct nfs_page *head,
struct nfs_commit_info *cinfo,
struct inode *inode);
extern void nfs_join_page_group(struct nfs_page *head, struct inode *inode);
extern int nfs_page_group_lock(struct nfs_page *);
extern void nfs_page_group_unlock(struct nfs_page *);
extern bool nfs_page_group_sync_on_bit(struct nfs_page *, unsigned int);

View File

@@ -93,7 +93,7 @@ static int __init test_pages(int *total_failures)
int failures = 0, num_tests = 0;
int i;
for (i = 0; i <= MAX_ORDER; i++)
for (i = 0; i < MAX_ORDER; i++)
num_tests += do_alloc_pages_order(i, &failures);
REPORT_FAILURES_IN_FN();