From: Arnd Bergmann arnd@arndb.de
[ Upstream commit 8d46603eeeb4c6abff1d2e49f2a6ae289dac765e ]
It appears that do_div() once more gets confused by a complex expression that ends up not quite being constant despite __builtin_constant_p() thinking it is:
ERROR: modpost: "__aeabi_uldivmod" [drivers/media/dvb-frontends/cxd2841er.ko] undefined!
Use div_u64() instead, forcing the expression to be evaluated first, and making it a bit more readable.
Cc: Dan Carpenter dan.carpenter@linaro.org Reported-by: Naresh Kamboju naresh.kamboju@linaro.org Closes: https://lore.kernel.org/linux-media/CA+G9fYvvNm-aYodLaAwwTjEGtX0YxR-1R14FOA5... Reported-by: Linux Kernel Functional Testing lkft@linaro.org Closes: https://lore.kernel.org/linux-media/CA+G9fYvvNm-aYodLaAwwTjEGtX0YxR-1R14FOA5... Signed-off-by: Arnd Bergmann arnd@arndb.de Signed-off-by: Hans Verkuil hverkuil@xs4all.nl [hverkuil: added Closes tags] Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/dvb-frontends/cxd2841er.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/drivers/media/dvb-frontends/cxd2841er.c b/drivers/media/dvb-frontends/cxd2841er.c index d925ca24183b5..415f1f91cc307 100644 --- a/drivers/media/dvb-frontends/cxd2841er.c +++ b/drivers/media/dvb-frontends/cxd2841er.c @@ -311,12 +311,8 @@ static int cxd2841er_set_reg_bits(struct cxd2841er_priv *priv,
static u32 cxd2841er_calc_iffreq_xtal(enum cxd2841er_xtal xtal, u32 ifhz) { - u64 tmp; - - tmp = (u64) ifhz * 16777216; - do_div(tmp, ((xtal == SONY_XTAL_24000) ? 48000000 : 41000000)); - - return (u32) tmp; + return div_u64(ifhz * 16777216ull, + (xtal == SONY_XTAL_24000) ? 48000000 : 41000000); }
static u32 cxd2841er_calc_iffreq(u32 ifhz)
From: Niklas Cassel cassel@kernel.org
[ Upstream commit f015b53d634a10fbceba545de70c3e109665c379 ]
A BAR of type BAR_FIXED has a fixed BAR size (the size cannot be changed).
When using pci_epf_alloc_space() to allocate backing memory for a BAR, pci_epf_alloc_space() will always set the size to the fixed BAR size if the BAR type is BAR_FIXED (and will give an error if you the requested size is larger than the fixed BAR size).
However, some drivers might not call pci_epf_alloc_space() before calling pci_epc_set_bar(), so add a check in pci_epc_set_bar() to ensure that an EPF driver cannot set a size different from the fixed BAR size, if the BAR type is BAR_FIXED.
The pci_epc_function_is_valid() check is removed because this check is now done by pci_epc_get_features().
Link: https://lore.kernel.org/r/20241213143301.4158431-13-cassel@kernel.org Signed-off-by: Niklas Cassel cassel@kernel.org Signed-off-by: Krzysztof Wilczyński kwilczynski@kernel.org Reviewed-by: Frank Li Frank.Li@nxp.com Reviewed-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pci/endpoint/pci-epc-core.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c index bed7c7d1fe3c3..c69c133701c92 100644 --- a/drivers/pci/endpoint/pci-epc-core.c +++ b/drivers/pci/endpoint/pci-epc-core.c @@ -609,10 +609,17 @@ EXPORT_SYMBOL_GPL(pci_epc_clear_bar); int pci_epc_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no, struct pci_epf_bar *epf_bar) { - int ret; + const struct pci_epc_features *epc_features; + enum pci_barno bar = epf_bar->barno; int flags = epf_bar->flags; + int ret;
- if (!pci_epc_function_is_valid(epc, func_no, vfunc_no)) + epc_features = pci_epc_get_features(epc, func_no, vfunc_no); + if (!epc_features) + return -EINVAL; + + if (epc_features->bar[bar].type == BAR_FIXED && + (epc_features->bar[bar].fixed_size != epf_bar->size)) return -EINVAL;
if ((epf_bar->barno == BAR_5 && flags & PCI_BASE_ADDRESS_MEM_TYPE_64) ||
From: Tomi Valkeinen tomi.valkeinen@ideasonboard.com
[ Upstream commit acd8f58d7a3bce0fbd3263961cd09555c00464ba ]
Add error handling to ub913_hw_init() using a new helper function, ub913_update_bits().
Reported-by: Sakari Ailus sakari.ailus@linux.intel.com Closes: https://lore.kernel.org/all/Zv40EQSR__JDN_0M@kekkonen.localdomain/ Reviewed-by: Jai Luthra jai.luthra@ideasonboard.com Signed-off-by: Tomi Valkeinen tomi.valkeinen@ideasonboard.com Signed-off-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/i2c/ds90ub913.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-)
diff --git a/drivers/media/i2c/ds90ub913.c b/drivers/media/i2c/ds90ub913.c index 79bddfee2e2ec..abfeff5c86068 100644 --- a/drivers/media/i2c/ds90ub913.c +++ b/drivers/media/i2c/ds90ub913.c @@ -8,6 +8,7 @@ * Copyright (c) 2023 Tomi Valkeinen tomi.valkeinen@ideasonboard.com */
+#include <linux/bitfield.h> #include <linux/clk-provider.h> #include <linux/clk.h> #include <linux/delay.h> @@ -146,6 +147,19 @@ static int ub913_write(const struct ub913_data *priv, u8 reg, u8 val) return ret; }
+static int ub913_update_bits(const struct ub913_data *priv, u8 reg, u8 mask, + u8 val) +{ + int ret; + + ret = regmap_update_bits(priv->regmap, reg, mask, val); + if (ret < 0) + dev_err(&priv->client->dev, + "Cannot update register 0x%02x %d!\n", reg, ret); + + return ret; +} + /* * GPIO chip */ @@ -733,10 +747,13 @@ static int ub913_hw_init(struct ub913_data *priv) if (ret) return dev_err_probe(dev, ret, "i2c master init failed\n");
- ub913_read(priv, UB913_REG_GENERAL_CFG, &v); - v &= ~UB913_REG_GENERAL_CFG_PCLK_RISING; - v |= priv->pclk_polarity_rising ? UB913_REG_GENERAL_CFG_PCLK_RISING : 0; - ub913_write(priv, UB913_REG_GENERAL_CFG, v); + ret = ub913_update_bits(priv, UB913_REG_GENERAL_CFG, + UB913_REG_GENERAL_CFG_PCLK_RISING, + FIELD_PREP(UB913_REG_GENERAL_CFG_PCLK_RISING, + priv->pclk_polarity_rising)); + + if (ret) + return ret;
return 0; }
From: Tomi Valkeinen tomi.valkeinen@ideasonboard.com
[ Upstream commit 0794c43ea1e451007e80246e1288ebbf44139397 ]
Add error handling for i2c reads/writes in various places.
Reported-by: Sakari Ailus sakari.ailus@linux.intel.com Closes: https://lore.kernel.org/all/Zv40EQSR__JDN_0M@kekkonen.localdomain/ Reviewed-by: Jai Luthra jai.luthra@ideasonboard.com Signed-off-by: Tomi Valkeinen tomi.valkeinen@ideasonboard.com Signed-off-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/i2c/ds90ub953.c | 46 ++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 14 deletions(-)
diff --git a/drivers/media/i2c/ds90ub953.c b/drivers/media/i2c/ds90ub953.c index 725589b3e1c58..9baea95cc204f 100644 --- a/drivers/media/i2c/ds90ub953.c +++ b/drivers/media/i2c/ds90ub953.c @@ -397,8 +397,13 @@ static int ub953_gpiochip_probe(struct ub953_data *priv) int ret;
/* Set all GPIOs to local input mode */ - ub953_write(priv, UB953_REG_LOCAL_GPIO_DATA, 0); - ub953_write(priv, UB953_REG_GPIO_INPUT_CTRL, 0xf); + ret = ub953_write(priv, UB953_REG_LOCAL_GPIO_DATA, 0); + if (ret) + return ret; + + ret = ub953_write(priv, UB953_REG_GPIO_INPUT_CTRL, 0xf); + if (ret) + return ret;
gc->label = dev_name(dev); gc->parent = dev; @@ -958,10 +963,11 @@ static void ub953_calc_clkout_params(struct ub953_data *priv, clkout_data->rate = clkout_rate; }
-static void ub953_write_clkout_regs(struct ub953_data *priv, - const struct ub953_clkout_data *clkout_data) +static int ub953_write_clkout_regs(struct ub953_data *priv, + const struct ub953_clkout_data *clkout_data) { u8 clkout_ctrl0, clkout_ctrl1; + int ret;
if (priv->hw_data->is_ub971) clkout_ctrl0 = clkout_data->m; @@ -971,8 +977,15 @@ static void ub953_write_clkout_regs(struct ub953_data *priv,
clkout_ctrl1 = clkout_data->n;
- ub953_write(priv, UB953_REG_CLKOUT_CTRL0, clkout_ctrl0); - ub953_write(priv, UB953_REG_CLKOUT_CTRL1, clkout_ctrl1); + ret = ub953_write(priv, UB953_REG_CLKOUT_CTRL0, clkout_ctrl0); + if (ret) + return ret; + + ret = ub953_write(priv, UB953_REG_CLKOUT_CTRL1, clkout_ctrl1); + if (ret) + return ret; + + return 0; }
static unsigned long ub953_clkout_recalc_rate(struct clk_hw *hw, @@ -1052,9 +1065,7 @@ static int ub953_clkout_set_rate(struct clk_hw *hw, unsigned long rate, dev_dbg(&priv->client->dev, "%s %lu (requested %lu)\n", __func__, clkout_data.rate, rate);
- ub953_write_clkout_regs(priv, &clkout_data); - - return 0; + return ub953_write_clkout_regs(priv, &clkout_data); }
static const struct clk_ops ub953_clkout_ops = { @@ -1079,7 +1090,9 @@ static int ub953_register_clkout(struct ub953_data *priv)
/* Initialize clkout to 25MHz by default */ ub953_calc_clkout_params(priv, UB953_DEFAULT_CLKOUT_RATE, &clkout_data); - ub953_write_clkout_regs(priv, &clkout_data); + ret = ub953_write_clkout_regs(priv, &clkout_data); + if (ret) + return ret;
priv->clkout_clk_hw.init = &init;
@@ -1226,10 +1239,15 @@ static int ub953_hw_init(struct ub953_data *priv) if (ret) return dev_err_probe(dev, ret, "i2c init failed\n");
- ub953_write(priv, UB953_REG_GENERAL_CFG, - (priv->non_continous_clk ? 0 : UB953_REG_GENERAL_CFG_CONT_CLK) | - ((priv->num_data_lanes - 1) << UB953_REG_GENERAL_CFG_CSI_LANE_SEL_SHIFT) | - UB953_REG_GENERAL_CFG_CRC_TX_GEN_ENABLE); + v = 0; + v |= priv->non_continous_clk ? 0 : UB953_REG_GENERAL_CFG_CONT_CLK; + v |= (priv->num_data_lanes - 1) << + UB953_REG_GENERAL_CFG_CSI_LANE_SEL_SHIFT; + v |= UB953_REG_GENERAL_CFG_CRC_TX_GEN_ENABLE; + + ret = ub953_write(priv, UB953_REG_GENERAL_CFG, v); + if (ret) + return ret;
return 0; }
From: Naushir Patuck naush@raspberrypi.com
[ Upstream commit 697a252bb2ea414cc1c0b4cf4e3d94a879eaf162 ]
The imx219/imx708 sensors frequently generate a single corrupt frame (image or embedded data) when the sensor first starts. This can either be a missing line, or invalid samples within the line. This only occurrs using the upstream Unicam kernel driver.
Disabling trigger mode elimiates this corruption. Since trigger mode is a legacy feature copied from the firmware driver and not expected to be needed, remove it. Tested on the Raspberry Pi cameras and shows no ill effects.
Signed-off-by: Naushir Patuck naush@raspberrypi.com Reviewed-by: Jacopo Mondi jacopo.mondi@ideasonboard.com Signed-off-by: Sakari Ailus sakari.ailus@linux.intel.com Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/platform/broadcom/bcm2835-unicam.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/drivers/media/platform/broadcom/bcm2835-unicam.c b/drivers/media/platform/broadcom/bcm2835-unicam.c index 3aed0e493c81f..4090a8e477402 100644 --- a/drivers/media/platform/broadcom/bcm2835-unicam.c +++ b/drivers/media/platform/broadcom/bcm2835-unicam.c @@ -816,11 +816,6 @@ static irqreturn_t unicam_isr(int irq, void *dev) } }
- if (unicam_reg_read(unicam, UNICAM_ICTL) & UNICAM_FCM) { - /* Switch out of trigger mode if selected */ - unicam_reg_write_field(unicam, UNICAM_ICTL, 1, UNICAM_TFC); - unicam_reg_write_field(unicam, UNICAM_ICTL, 0, UNICAM_FCM); - } return IRQ_HANDLED; }
@@ -984,8 +979,7 @@ static void unicam_start_rx(struct unicam_device *unicam,
unicam_reg_write_field(unicam, UNICAM_ANA, 0, UNICAM_DDL);
- /* Always start in trigger frame capture mode (UNICAM_FCM set) */ - val = UNICAM_FSIE | UNICAM_FEIE | UNICAM_FCM | UNICAM_IBOB; + val = UNICAM_FSIE | UNICAM_FEIE | UNICAM_IBOB; line_int_freq = max(fmt->height >> 2, 128); unicam_set_field(&val, line_int_freq, UNICAM_LCIE_MASK); unicam_reg_write(unicam, UNICAM_ICTL, val);
From: Isaac Scott isaac.scott@ideasonboard.com
[ Upstream commit c2eda35e675b6ea4a0a21a4b1167b121571a9036 ]
Some cameras, such as the Sonix Technology Co. 292A, exhibit issues when running two parallel streams, causing USB packets to be dropped when an H.264 stream posts a keyframe while an MJPEG stream is running simultaneously. This occasionally causes the driver to erroneously output two consecutive JPEG images as a single frame.
To fix this, we inspect the buffer, and trigger a new frame when we find an SOI.
Signed-off-by: Isaac Scott isaac.scott@ideasonboard.com Reviewed-by: Ricardo Ribalda ribalda@chromium.org Link: https://lore.kernel.org/r/20241128145144.61475-2-isaac.scott@ideasonboard.co... Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/usb/uvc/uvc_video.c | 27 ++++++++++++++++++++++++++- drivers/media/usb/uvc/uvcvideo.h | 1 + 2 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index e00f38dd07d93..6d800a0997493 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -20,6 +20,7 @@ #include <linux/atomic.h> #include <linux/unaligned.h>
+#include <media/jpeg.h> #include <media/v4l2-common.h>
#include "uvcvideo.h" @@ -1116,6 +1117,7 @@ static void uvc_video_stats_stop(struct uvc_streaming *stream) static int uvc_video_decode_start(struct uvc_streaming *stream, struct uvc_buffer *buf, const u8 *data, int len) { + u8 header_len; u8 fid;
/* @@ -1129,6 +1131,7 @@ static int uvc_video_decode_start(struct uvc_streaming *stream, return -EINVAL; }
+ header_len = data[0]; fid = data[1] & UVC_STREAM_FID;
/* @@ -1210,9 +1213,31 @@ static int uvc_video_decode_start(struct uvc_streaming *stream, return -EAGAIN; }
+ /* + * Some cameras, when running two parallel streams (one MJPEG alongside + * another non-MJPEG stream), are known to lose the EOF packet for a frame. + * We can detect the end of a frame by checking for a new SOI marker, as + * the SOI always lies on the packet boundary between two frames for + * these devices. + */ + if (stream->dev->quirks & UVC_QUIRK_MJPEG_NO_EOF && + (stream->cur_format->fcc == V4L2_PIX_FMT_MJPEG || + stream->cur_format->fcc == V4L2_PIX_FMT_JPEG)) { + const u8 *packet = data + header_len; + + if (len >= header_len + 2 && + packet[0] == 0xff && packet[1] == JPEG_MARKER_SOI && + buf->bytesused != 0) { + buf->state = UVC_BUF_STATE_READY; + buf->error = 1; + stream->last_fid ^= UVC_STREAM_FID; + return -EAGAIN; + } + } + stream->last_fid = fid;
- return data[0]; + return header_len; }
static inline enum dma_data_direction uvc_stream_dir( diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 07f9921d83f2d..a73a8d3596aa0 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -76,6 +76,7 @@ #define UVC_QUIRK_NO_RESET_RESUME 0x00004000 #define UVC_QUIRK_DISABLE_AUTOSUSPEND 0x00008000 #define UVC_QUIRK_INVALID_DEVICE_SOF 0x00010000 +#define UVC_QUIRK_MJPEG_NO_EOF 0x00020000
/* Format flags */ #define UVC_FMT_FLAG_COMPRESSED 0x00000001
From: Isaac Scott isaac.scott@ideasonboard.com
[ Upstream commit 81f8c0e138c43610cf09b8d2a533068aa58e538e ]
The Sonix Technology Co. 292A camera (which uses an AR0330 sensor), can produce MJPEG and H.264 streams concurrently. When doing so, it drops the last packets of MJPEG frames every time the H.264 stream generates a key frame. Set the UVC_QUIRK_MJPEG_NO_EOF quirk to work around the issue.
Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Isaac Scott isaac.scott@ideasonboard.com Link: https://lore.kernel.org/r/20241128145144.61475-3-isaac.scott@ideasonboard.co... Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/usb/uvc/uvc_driver.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index b3c8411dc05c9..f76289bd8bb3c 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -2802,6 +2802,15 @@ static const struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = (kernel_ulong_t)&uvc_quirk_probe_minmax }, + /* Sonix Technology Co. Ltd. - 292A IPC AR0330 */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x0c45, + .idProduct = 0x6366, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_MJPEG_NO_EOF) }, /* MT6227 */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
From: Isaac Scott isaac.scott@ideasonboard.com
[ Upstream commit 2762eab6d4140781840f253f9a04b8627017248b ]
Add support for the Kurokesu C1 PRO camera. This camera experiences the same issues faced by the Sonix Technology Co. 292A IPC AR0330. As such, enable the UVC_QUIRK_MJPEG_NO_EOF quirk for this device to prevent frames from being erroneously dropped.
Signed-off-by: Isaac Scott isaac.scott@ideasonboard.com Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/usb/uvc/uvc_driver.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index f76289bd8bb3c..cc5981c3be3a4 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -2839,6 +2839,15 @@ static const struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = (kernel_ulong_t)&uvc_quirk_probe_minmax }, + /* Kurokesu C1 PRO */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x16d0, + .idProduct = 0x0ed1, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_MJPEG_NO_EOF) }, /* Syntek (HP Spartan) */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
From: Edward Adam Davis eadavis@qq.com
[ Upstream commit 1221989555db711578a327a9367f1be46500cb48 ]
syzbot report a null-ptr-deref in vidtv_mux_stop_thread. [1]
If dvb->mux is not initialized successfully by vidtv_mux_init() in the vidtv_start_streaming(), it will trigger null pointer dereference about mux in vidtv_mux_stop_thread().
Adjust the timing of streaming initialization and check it before stopping it.
[1] KASAN: null-ptr-deref in range [0x0000000000000128-0x000000000000012f] CPU: 0 UID: 0 PID: 5842 Comm: syz-executor248 Not tainted 6.13.0-rc4-syzkaller-00012-g9b2ffa6148b1 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024 RIP: 0010:vidtv_mux_stop_thread+0x26/0x80 drivers/media/test-drivers/vidtv/vidtv_mux.c:471 Code: 90 90 90 90 66 0f 1f 00 55 53 48 89 fb e8 82 2e c8 f9 48 8d bb 28 01 00 00 48 b8 00 00 00 00 00 fc ff df 48 89 fa 48 c1 ea 03 <0f> b6 04 02 84 c0 74 02 7e 3b 0f b6 ab 28 01 00 00 31 ff 89 ee e8 RSP: 0018:ffffc90003f2faa8 EFLAGS: 00010202 RAX: dffffc0000000000 RBX: 0000000000000000 RCX: ffffffff87cfb125 RDX: 0000000000000025 RSI: ffffffff87d120ce RDI: 0000000000000128 RBP: ffff888029b8d220 R08: 0000000000000005 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000003 R12: ffff888029b8d188 R13: ffffffff8f590aa0 R14: ffffc9000581c5c8 R15: ffff888029a17710 FS: 00007f7eef5156c0(0000) GS:ffff8880b8600000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f7eef5e635c CR3: 0000000076ca6000 CR4: 00000000003526f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: <TASK> vidtv_stop_streaming drivers/media/test-drivers/vidtv/vidtv_bridge.c:209 [inline] vidtv_stop_feed+0x151/0x250 drivers/media/test-drivers/vidtv/vidtv_bridge.c:252 dmx_section_feed_stop_filtering+0x90/0x160 drivers/media/dvb-core/dvb_demux.c:1000 dvb_dmxdev_feed_stop.isra.0+0x1ee/0x270 drivers/media/dvb-core/dmxdev.c:486 dvb_dmxdev_filter_stop+0x22a/0x3a0 drivers/media/dvb-core/dmxdev.c:559 dvb_dmxdev_filter_free drivers/media/dvb-core/dmxdev.c:840 [inline] dvb_demux_release+0x92/0x550 drivers/media/dvb-core/dmxdev.c:1246 __fput+0x3f8/0xb60 fs/file_table.c:450 task_work_run+0x14e/0x250 kernel/task_work.c:239 get_signal+0x1d3/0x2610 kernel/signal.c:2790 arch_do_signal_or_restart+0x90/0x7e0 arch/x86/kernel/signal.c:337 exit_to_user_mode_loop kernel/entry/common.c:111 [inline] exit_to_user_mode_prepare include/linux/entry-common.h:329 [inline] __syscall_exit_to_user_mode_work kernel/entry/common.c:207 [inline] syscall_exit_to_user_mode+0x150/0x2a0 kernel/entry/common.c:218 do_syscall_64+0xda/0x250 arch/x86/entry/common.c:89 entry_SYSCALL_64_after_hwframe+0x77/0x7f
Reported-by: syzbot+5e248227c80a3be8e96a@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=5e248227c80a3be8e96a Signed-off-by: Edward Adam Davis eadavis@qq.com Signed-off-by: Hans Verkuil hverkuil@xs4all.nl Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/test-drivers/vidtv/vidtv_bridge.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/media/test-drivers/vidtv/vidtv_bridge.c b/drivers/media/test-drivers/vidtv/vidtv_bridge.c index e1dd8adeba469..438483c62facc 100644 --- a/drivers/media/test-drivers/vidtv/vidtv_bridge.c +++ b/drivers/media/test-drivers/vidtv/vidtv_bridge.c @@ -191,10 +191,11 @@ static int vidtv_start_streaming(struct vidtv_dvb *dvb)
mux_args.mux_buf_sz = mux_buf_sz;
- dvb->streaming = true; dvb->mux = vidtv_mux_init(dvb->fe[0], dev, &mux_args); if (!dvb->mux) return -ENOMEM; + + dvb->streaming = true; vidtv_mux_start_thread(dvb->mux);
dev_dbg_ratelimited(dev, "Started streaming\n"); @@ -205,6 +206,11 @@ static int vidtv_stop_streaming(struct vidtv_dvb *dvb) { struct device *dev = &dvb->pdev->dev;
+ if (!dvb->streaming) { + dev_warn_ratelimited(dev, "No streaming. Skipping.\n"); + return 0; + } + dvb->streaming = false; vidtv_mux_stop_thread(dvb->mux); vidtv_mux_destroy(dvb->mux);
From: Naman Jain namjain@linux.microsoft.com
[ Upstream commit 113386ca981c3997db6b83272c7ecf47456aeddb ]
Channel offers are requested during VMBus initialization and resume from hibernation. Add support to wait for all boot-time channel offers to be delivered and processed before returning from vmbus_request_offers.
This is in analogy to a PCI bus not returning from probe until it has scanned all devices on the bus.
Without this, user mode can race with VMBus initialization and miss channel offers. User mode has no way to work around this other than sleeping for a while, since there is no way to know when VMBus has finished processing boot-time offers.
With this added functionality, remove earlier logic which keeps track of count of offered channels post resume from hibernation. Once all offers delivered message is received, no further boot-time offers are going to be received. Consequently, logic to prevent suspend from happening after previous resume had missing offers, is also removed.
Co-developed-by: John Starks jostarks@microsoft.com Signed-off-by: John Starks jostarks@microsoft.com Signed-off-by: Naman Jain namjain@linux.microsoft.com Reviewed-by: Easwar Hariharan eahariha@linux.microsoft.com Reviewed-by: Saurabh Sengar ssengar@linux.microsoft.com Reviewed-by: Michael Kelley mhklinux@outlook.com Link: https://lore.kernel.org/r/20250102130712.1661-2-namjain@linux.microsoft.com Signed-off-by: Wei Liu wei.liu@kernel.org Message-ID: 20250102130712.1661-2-namjain@linux.microsoft.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/hv/channel_mgmt.c | 61 +++++++++++++++++++++++++++++---------- drivers/hv/connection.c | 4 +-- drivers/hv/hyperv_vmbus.h | 14 ++------- drivers/hv/vmbus_drv.c | 16 ---------- 4 files changed, 51 insertions(+), 44 deletions(-)
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 3c6011a48dabe..6e084c2074141 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -944,16 +944,6 @@ void vmbus_initiate_unload(bool crash) vmbus_wait_for_unload(); }
-static void check_ready_for_resume_event(void) -{ - /* - * If all the old primary channels have been fixed up, then it's safe - * to resume. - */ - if (atomic_dec_and_test(&vmbus_connection.nr_chan_fixup_on_resume)) - complete(&vmbus_connection.ready_for_resume_event); -} - static void vmbus_setup_channel_state(struct vmbus_channel *channel, struct vmbus_channel_offer_channel *offer) { @@ -1109,8 +1099,6 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr)
/* Add the channel back to the array of channels. */ vmbus_channel_map_relid(oldchannel); - check_ready_for_resume_event(); - mutex_unlock(&vmbus_connection.channel_mutex); return; } @@ -1296,13 +1284,28 @@ EXPORT_SYMBOL_GPL(vmbus_hvsock_device_unregister);
/* * vmbus_onoffers_delivered - - * This is invoked when all offers have been delivered. + * The CHANNELMSG_ALLOFFERS_DELIVERED message arrives after all + * boot-time offers are delivered. A boot-time offer is for the primary + * channel for any virtual hardware configured in the VM at the time it boots. + * Boot-time offers include offers for physical devices assigned to the VM + * via Hyper-V's Discrete Device Assignment (DDA) functionality that are + * handled as virtual PCI devices in Linux (e.g., NVMe devices and GPUs). + * Boot-time offers do not include offers for VMBus sub-channels. Because + * devices can be hot-added to the VM after it is booted, additional channel + * offers that aren't boot-time offers can be received at any time after the + * all-offers-delivered message. * - * Nothing to do here. + * SR-IOV NIC Virtual Functions (VFs) assigned to a VM are not considered + * to be assigned to the VM at boot-time, and offers for VFs may occur after + * the all-offers-delivered message. VFs are optional accelerators to the + * synthetic VMBus NIC and are effectively hot-added only after the VMBus + * NIC channel is opened (once it knows the guest can support it, via the + * sriov bit in the netvsc protocol). */ static void vmbus_onoffers_delivered( struct vmbus_channel_message_header *hdr) { + complete(&vmbus_connection.all_offers_delivered_event); }
/* @@ -1578,7 +1581,8 @@ void vmbus_onmessage(struct vmbus_channel_message_header *hdr) }
/* - * vmbus_request_offers - Send a request to get all our pending offers. + * vmbus_request_offers - Send a request to get all our pending offers + * and wait for all boot-time offers to arrive. */ int vmbus_request_offers(void) { @@ -1596,6 +1600,10 @@ int vmbus_request_offers(void)
msg->msgtype = CHANNELMSG_REQUESTOFFERS;
+ /* + * This REQUESTOFFERS message will result in the host sending an all + * offers delivered message after all the boot-time offers are sent. + */ ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_message_header), true);
@@ -1607,6 +1615,29 @@ int vmbus_request_offers(void) goto cleanup; }
+ /* + * Wait for the host to send all boot-time offers. + * Keeping it as a best-effort mechanism, where a warning is + * printed if a timeout occurs, and execution is resumed. + */ + if (!wait_for_completion_timeout(&vmbus_connection.all_offers_delivered_event, + secs_to_jiffies(60))) { + pr_warn("timed out waiting for all boot-time offers to be delivered.\n"); + } + + /* + * Flush handling of offer messages (which may initiate work on + * other work queues). + */ + flush_workqueue(vmbus_connection.work_queue); + + /* + * Flush workqueue for processing the incoming offers. Subchannel + * offers and their processing can happen later, so there is no need to + * flush that workqueue here. + */ + flush_workqueue(vmbus_connection.handle_primary_chan_wq); + cleanup: kfree(msginfo);
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index f001ae880e1db..8351360bba161 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -34,8 +34,8 @@ struct vmbus_connection vmbus_connection = {
.ready_for_suspend_event = COMPLETION_INITIALIZER( vmbus_connection.ready_for_suspend_event), - .ready_for_resume_event = COMPLETION_INITIALIZER( - vmbus_connection.ready_for_resume_event), + .all_offers_delivered_event = COMPLETION_INITIALIZER( + vmbus_connection.all_offers_delivered_event), }; EXPORT_SYMBOL_GPL(vmbus_connection);
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 52cb744b4d7fd..e4058af987316 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -287,18 +287,10 @@ struct vmbus_connection { struct completion ready_for_suspend_event;
/* - * The number of primary channels that should be "fixed up" - * upon resume: these channels are re-offered upon resume, and some - * fields of the channel offers (i.e. child_relid and connection_id) - * can change, so the old offermsg must be fixed up, before the resume - * callbacks of the VSC drivers start to further touch the channels. + * Completed once the host has offered all boot-time channels. + * Note that some channels may still be under process on a workqueue. */ - atomic_t nr_chan_fixup_on_resume; - /* - * vmbus_bus_resume() waits for "nr_chan_fixup_on_resume" to - * drop to zero. - */ - struct completion ready_for_resume_event; + struct completion all_offers_delivered_event; };
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 2892b8da20a5e..bf5608a740561 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -2427,11 +2427,6 @@ static int vmbus_bus_suspend(struct device *dev) if (atomic_read(&vmbus_connection.nr_chan_close_on_suspend) > 0) wait_for_completion(&vmbus_connection.ready_for_suspend_event);
- if (atomic_read(&vmbus_connection.nr_chan_fixup_on_resume) != 0) { - pr_err("Can not suspend due to a previous failed resuming\n"); - return -EBUSY; - } - mutex_lock(&vmbus_connection.channel_mutex);
list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { @@ -2456,17 +2451,12 @@ static int vmbus_bus_suspend(struct device *dev) pr_err("Sub-channel not deleted!\n"); WARN_ON_ONCE(1); } - - atomic_inc(&vmbus_connection.nr_chan_fixup_on_resume); }
mutex_unlock(&vmbus_connection.channel_mutex);
vmbus_initiate_unload(false);
- /* Reset the event for the next resume. */ - reinit_completion(&vmbus_connection.ready_for_resume_event); - return 0; }
@@ -2502,14 +2492,8 @@ static int vmbus_bus_resume(struct device *dev) if (ret != 0) return ret;
- WARN_ON(atomic_read(&vmbus_connection.nr_chan_fixup_on_resume) == 0); - vmbus_request_offers();
- if (wait_for_completion_timeout( - &vmbus_connection.ready_for_resume_event, secs_to_jiffies(10)) == 0) - pr_err("Some vmbus device is missing after suspending?\n"); - /* Reset the event for the next suspend. */ reinit_completion(&vmbus_connection.ready_for_suspend_event);
From: Roman Kisel romank@linux.microsoft.com
[ Upstream commit f285d995743269aa9f893e5e9a1065604137c1f6 ]
The Top-Level Functional Specification for Hyper-V, Section 3.6 [1, 2], disallows overlapping of the input and output hypercall areas, and hv_vtl_apicid_to_vp_id() overlaps them.
Use the output hypercall page of the current vCPU for the hypercall.
[1] https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/hyp... [2] https://github.com/MicrosoftDocs/Virtualization-Documentation/tree/main/tlfs
Reported-by: Michael Kelley mhklinux@outlook.com Closes: https://lore.kernel.org/lkml/SN6PR02MB4157B98CD34781CC87A9D921D40D2@SN6PR02M... Signed-off-by: Roman Kisel romank@linux.microsoft.com Reviewed-by: Easwar Hariharan eahariha@linux.microsoft.com Reviewed-by: Nuno Das Neves nunodasneves@linux.microsoft.com Link: https://lore.kernel.org/r/20250108222138.1623703-6-romank@linux.microsoft.co... Signed-off-by: Wei Liu wei.liu@kernel.org Message-ID: 20250108222138.1623703-6-romank@linux.microsoft.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/x86/hyperv/hv_vtl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/hyperv/hv_vtl.c b/arch/x86/hyperv/hv_vtl.c index 04775346369c5..4e1b1e3b56584 100644 --- a/arch/x86/hyperv/hv_vtl.c +++ b/arch/x86/hyperv/hv_vtl.c @@ -189,7 +189,7 @@ static int hv_vtl_apicid_to_vp_id(u32 apic_id) input->partition_id = HV_PARTITION_ID_SELF; input->apic_ids[0] = apic_id;
- output = (u32 *)input; + output = *this_cpu_ptr(hyperv_pcpu_output_arg);
control = HV_HYPERCALL_REP_COMP_1 | HVCALL_GET_VP_ID_FROM_APIC_ID; status = hv_do_hypercall(control, input, output);
Hi Sasha,
The patch picked up for the stable tree will need this bit "[PATCH v6 3/5] hyperv: Enable the hypercall output page for the VTL mode"
https://lore.kernel.org/linux-hyperv/20250108222138.1623703-4-romank@linux.m...
On 1/28/2025 9:53 AM, Sasha Levin wrote:
From: Roman Kisel romank@linux.microsoft.com
[ Upstream commit f285d995743269aa9f893e5e9a1065604137c1f6 ]
The Top-Level Functional Specification for Hyper-V, Section 3.6 [1, 2], disallows overlapping of the input and output hypercall areas, and hv_vtl_apicid_to_vp_id() overlaps them.
Use the output hypercall page of the current vCPU for the hypercall.
[1] https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/hyp... [2] https://github.com/MicrosoftDocs/Virtualization-Documentation/tree/main/tlfs
Reported-by: Michael Kelley mhklinux@outlook.com Closes: https://lore.kernel.org/lkml/SN6PR02MB4157B98CD34781CC87A9D921D40D2@SN6PR02M... Signed-off-by: Roman Kisel romank@linux.microsoft.com Reviewed-by: Easwar Hariharan eahariha@linux.microsoft.com Reviewed-by: Nuno Das Neves nunodasneves@linux.microsoft.com Link: https://lore.kernel.org/r/20250108222138.1623703-6-romank@linux.microsoft.co... Signed-off-by: Wei Liu wei.liu@kernel.org Message-ID: 20250108222138.1623703-6-romank@linux.microsoft.com Signed-off-by: Sasha Levin sashal@kernel.org
arch/x86/hyperv/hv_vtl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/hyperv/hv_vtl.c b/arch/x86/hyperv/hv_vtl.c index 04775346369c5..4e1b1e3b56584 100644 --- a/arch/x86/hyperv/hv_vtl.c +++ b/arch/x86/hyperv/hv_vtl.c @@ -189,7 +189,7 @@ static int hv_vtl_apicid_to_vp_id(u32 apic_id) input->partition_id = HV_PARTITION_ID_SELF; input->apic_ids[0] = apic_id;
- output = (u32 *)input;
- output = *this_cpu_ptr(hyperv_pcpu_output_arg);
control = HV_HYPERCALL_REP_COMP_1 | HVCALL_GET_VP_ID_FROM_APIC_ID; status = hv_do_hypercall(control, input, output);
From: Lorenzo Bianconi lorenzo@kernel.org
[ Upstream commit 491cb9c5084790aafa02e843349492c284373231 ]
Airoha EN7581 has a hw bug asserting/releasing PERST# signal causing occasional PCIe link down issues. In order to overcome the problem, PERST# signal is not asserted/released during device probe or suspend/resume phase and the PCIe block is reset using en7523_reset_assert() and en7581_pci_enable().
Introduce flags field in the mtk_gen3_pcie_pdata struct in order to specify per-SoC capabilities.
Link: https://lore.kernel.org/r/20250109-pcie-en7581-rst-fix-v4-1-4a45c89fb143@ker... Tested-by: Hui Ma hui.ma@airoha.com Signed-off-by: Lorenzo Bianconi lorenzo@kernel.org Signed-off-by: Krzysztof Wilczyński kwilczynski@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pci/controller/pcie-mediatek-gen3.c | 59 ++++++++++++++------- 1 file changed, 41 insertions(+), 18 deletions(-)
diff --git a/drivers/pci/controller/pcie-mediatek-gen3.c b/drivers/pci/controller/pcie-mediatek-gen3.c index be52e3a123abd..74dfef8ce9ec1 100644 --- a/drivers/pci/controller/pcie-mediatek-gen3.c +++ b/drivers/pci/controller/pcie-mediatek-gen3.c @@ -133,10 +133,18 @@ struct mtk_gen3_pcie; #define PCIE_CONF_LINK2_CTL_STS (PCIE_CFG_OFFSET_ADDR + 0xb0) #define PCIE_CONF_LINK2_LCR2_LINK_SPEED GENMASK(3, 0)
+enum mtk_gen3_pcie_flags { + SKIP_PCIE_RSTB = BIT(0), /* Skip PERST# assertion during device + * probing or suspend/resume phase to + * avoid hw bugs/issues. + */ +}; + /** * struct mtk_gen3_pcie_pdata - differentiate between host generations * @power_up: pcie power_up callback * @phy_resets: phy reset lines SoC data. + * @flags: pcie device flags. */ struct mtk_gen3_pcie_pdata { int (*power_up)(struct mtk_gen3_pcie *pcie); @@ -144,6 +152,7 @@ struct mtk_gen3_pcie_pdata { const char *id[MAX_NUM_PHY_RESETS]; int num_resets; } phy_resets; + u32 flags; };
/** @@ -438,22 +447,33 @@ static int mtk_pcie_startup_port(struct mtk_gen3_pcie *pcie) val |= PCIE_DISABLE_DVFSRC_VLT_REQ; writel_relaxed(val, pcie->base + PCIE_MISC_CTRL_REG);
- /* Assert all reset signals */ - val = readl_relaxed(pcie->base + PCIE_RST_CTRL_REG); - val |= PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | PCIE_PE_RSTB; - writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG); - /* - * Described in PCIe CEM specification sections 2.2 (PERST# Signal) - * and 2.2.1 (Initial Power-Up (G3 to S0)). - * The deassertion of PERST# should be delayed 100ms (TPVPERL) - * for the power and clock to become stable. + * Airoha EN7581 has a hw bug asserting/releasing PCIE_PE_RSTB signal + * causing occasional PCIe link down. In order to overcome the issue, + * PCIE_RSTB signals are not asserted/released at this stage and the + * PCIe block is reset using en7523_reset_assert() and + * en7581_pci_enable(). */ - msleep(100); - - /* De-assert reset signals */ - val &= ~(PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | PCIE_PE_RSTB); - writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG); + if (!(pcie->soc->flags & SKIP_PCIE_RSTB)) { + /* Assert all reset signals */ + val = readl_relaxed(pcie->base + PCIE_RST_CTRL_REG); + val |= PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | + PCIE_PE_RSTB; + writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG); + + /* + * Described in PCIe CEM specification revision 6.0. + * + * The deassertion of PERST# should be delayed 100ms (TPVPERL) + * for the power and clock to become stable. + */ + msleep(PCIE_T_PVPERL_MS); + + /* De-assert reset signals */ + val &= ~(PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | + PCIE_PE_RSTB); + writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG); + }
/* Check if the link is up or not */ err = readl_poll_timeout(pcie->base + PCIE_LINK_STATUS_REG, val, @@ -1231,10 +1251,12 @@ static int mtk_pcie_suspend_noirq(struct device *dev) return err; }
- /* Pull down the PERST# pin */ - val = readl_relaxed(pcie->base + PCIE_RST_CTRL_REG); - val |= PCIE_PE_RSTB; - writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG); + if (!(pcie->soc->flags & SKIP_PCIE_RSTB)) { + /* Assert the PERST# pin */ + val = readl_relaxed(pcie->base + PCIE_RST_CTRL_REG); + val |= PCIE_PE_RSTB; + writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG); + }
dev_dbg(pcie->dev, "entered L2 states successfully");
@@ -1285,6 +1307,7 @@ static const struct mtk_gen3_pcie_pdata mtk_pcie_soc_en7581 = { .id[2] = "phy-lane2", .num_resets = 3, }, + .flags = SKIP_PCIE_RSTB, };
static const struct of_device_id mtk_pcie_of_match[] = {
From: Ilpo Järvinen ilpo.jarvinen@linux.intel.com
[ Upstream commit e5321ae10e1323359a5067a26dfe98b5f44cc5e6 ]
eetlp_prefix_path in the struct pci_dev tells if End-End TLP Prefixes are supported by the path or not, and the value is only calculated if CONFIG_PCI_PASID is set.
The Max End-End TLP Prefixes field in the Device Capabilities Register 2 also tells how many (1-4) End-End TLP Prefixes are supported (PCIe r6.2 sec 7.5.3.15). The number of supported End-End Prefixes is useful for reading correct number of DWORDs from TLP Prefix Log register in AER capability (PCIe r6.2 sec 7.8.4.12).
Replace eetlp_prefix_path with eetlp_prefix_max and determine the number of supported End-End Prefixes regardless of CONFIG_PCI_PASID so that an upcoming commit generalizing TLP Prefix Log register reading does not have to read extra DWORDs for End-End Prefixes that never will be there.
The value stored into eetlp_prefix_max is directly derived from device's Max End-End TLP Prefixes and does not consider limitations imposed by bridges or the Root Port beyond supported/not supported flags. This is intentional for two reasons:
1) PCIe r6.2 spec sections 2.2.10.4 & 6.2.4.4 indicate that a TLP is malformed only if the number of prefixes exceed the number of Max End-End TLP Prefixes, which seems to be the case even if the device could never receive that many prefixes due to smaller maximum imposed by a bridge or the Root Port. If TLP parsing is later added, this distinction is significant in interpreting what is logged by the TLP Prefix Log registers and the value matching to the Malformed TLP threshold is going to be more useful.
2) TLP Prefix handling happens autonomously on a low layer and the value in eetlp_prefix_max is not programmed anywhere by the kernel (i.e., there is no limiter OS can control to prevent sending more than N TLP Prefixes).
Link: https://lore.kernel.org/r/20250114170840.1633-7-ilpo.jarvinen@linux.intel.co... Signed-off-by: Ilpo Järvinen ilpo.jarvinen@linux.intel.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Reviewed-by: Jonathan Cameron Jonathan.Cameron@huawei.com Reviewed-by: Yazen Ghannam yazen.ghannam@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pci/ats.c | 2 +- drivers/pci/probe.c | 14 +++++++++----- include/linux/pci.h | 2 +- include/uapi/linux/pci_regs.h | 1 + 4 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c index 6afff1f1b1430..c6b266c772c81 100644 --- a/drivers/pci/ats.c +++ b/drivers/pci/ats.c @@ -410,7 +410,7 @@ int pci_enable_pasid(struct pci_dev *pdev, int features) if (WARN_ON(pdev->pasid_enabled)) return -EBUSY;
- if (!pdev->eetlp_prefix_path && !pdev->pasid_no_tlp) + if (!pdev->eetlp_prefix_max && !pdev->pasid_no_tlp) return -EINVAL;
if (!pasid) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 2e81ab0f5a25c..381c22e3ccdbf 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2251,8 +2251,8 @@ static void pci_configure_relaxed_ordering(struct pci_dev *dev)
static void pci_configure_eetlp_prefix(struct pci_dev *dev) { -#ifdef CONFIG_PCI_PASID struct pci_dev *bridge; + unsigned int eetlp_max; int pcie_type; u32 cap;
@@ -2264,15 +2264,19 @@ static void pci_configure_eetlp_prefix(struct pci_dev *dev) return;
pcie_type = pci_pcie_type(dev); + + eetlp_max = FIELD_GET(PCI_EXP_DEVCAP2_EE_PREFIX_MAX, cap); + /* 00b means 4 */ + eetlp_max = eetlp_max ?: 4; + if (pcie_type == PCI_EXP_TYPE_ROOT_PORT || pcie_type == PCI_EXP_TYPE_RC_END) - dev->eetlp_prefix_path = 1; + dev->eetlp_prefix_max = eetlp_max; else { bridge = pci_upstream_bridge(dev); - if (bridge && bridge->eetlp_prefix_path) - dev->eetlp_prefix_path = 1; + if (bridge && bridge->eetlp_prefix_max) + dev->eetlp_prefix_max = eetlp_max; } -#endif }
static void pci_configure_serr(struct pci_dev *dev) diff --git a/include/linux/pci.h b/include/linux/pci.h index db9b47ce3eefd..21be5a1edf1ad 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -407,7 +407,7 @@ struct pci_dev { supported from root to here */ #endif unsigned int pasid_no_tlp:1; /* PASID works without TLP Prefix */ - unsigned int eetlp_prefix_path:1; /* End-to-End TLP Prefix */ + unsigned int eetlp_prefix_max:3; /* Max # of End-End TLP Prefixes, 0=not supported */
pci_channel_state_t error_state; /* Current connectivity state */ struct device dev; /* Generic device interface */ diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h index 1601c7ed5fab7..14a6306c4ce18 100644 --- a/include/uapi/linux/pci_regs.h +++ b/include/uapi/linux/pci_regs.h @@ -665,6 +665,7 @@ #define PCI_EXP_DEVCAP2_OBFF_MSG 0x00040000 /* New message signaling */ #define PCI_EXP_DEVCAP2_OBFF_WAKE 0x00080000 /* Re-use WAKE# for OBFF */ #define PCI_EXP_DEVCAP2_EE_PREFIX 0x00200000 /* End-End TLP Prefix */ +#define PCI_EXP_DEVCAP2_EE_PREFIX_MAX 0x00c00000 /* Max End-End TLP Prefixes */ #define PCI_EXP_DEVCTL2 0x28 /* Device Control 2 */ #define PCI_EXP_DEVCTL2_COMP_TIMEOUT 0x000f /* Completion Timeout Value */ #define PCI_EXP_DEVCTL2_COMP_TMOUT_DIS 0x0010 /* Completion Timeout Disable */
On Tue, 28 Jan 2025, Sasha Levin wrote:
From: Ilpo Järvinen ilpo.jarvinen@linux.intel.com
[ Upstream commit e5321ae10e1323359a5067a26dfe98b5f44cc5e6 ]
eetlp_prefix_path in the struct pci_dev tells if End-End TLP Prefixes are supported by the path or not, and the value is only calculated if CONFIG_PCI_PASID is set.
The Max End-End TLP Prefixes field in the Device Capabilities Register 2 also tells how many (1-4) End-End TLP Prefixes are supported (PCIe r6.2 sec 7.5.3.15). The number of supported End-End Prefixes is useful for reading correct number of DWORDs from TLP Prefix Log register in AER capability (PCIe r6.2 sec 7.8.4.12).
Replace eetlp_prefix_path with eetlp_prefix_max and determine the number of supported End-End Prefixes regardless of CONFIG_PCI_PASID so that an upcoming commit generalizing TLP Prefix Log register reading does not have to read extra DWORDs for End-End Prefixes that never will be there.
The value stored into eetlp_prefix_max is directly derived from device's Max End-End TLP Prefixes and does not consider limitations imposed by bridges or the Root Port beyond supported/not supported flags. This is intentional for two reasons:
PCIe r6.2 spec sections 2.2.10.4 & 6.2.4.4 indicate that a TLP is malformed only if the number of prefixes exceed the number of Max End-End TLP Prefixes, which seems to be the case even if the device could never receive that many prefixes due to smaller maximum imposed by a bridge or the Root Port. If TLP parsing is later added, this distinction is significant in interpreting what is logged by the TLP Prefix Log registers and the value matching to the Malformed TLP threshold is going to be more useful.
TLP Prefix handling happens autonomously on a low layer and the value in eetlp_prefix_max is not programmed anywhere by the kernel (i.e., there is no limiter OS can control to prevent sending more than N TLP Prefixes).
Link: https://lore.kernel.org/r/20250114170840.1633-7-ilpo.jarvinen@linux.intel.co... Signed-off-by: Ilpo Järvinen ilpo.jarvinen@linux.intel.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Reviewed-by: Jonathan Cameron Jonathan.Cameron@huawei.com Reviewed-by: Yazen Ghannam yazen.ghannam@amd.com Signed-off-by: Sasha Levin sashal@kernel.org
Hi,
Why is this being auto selected? It's not a fix nor do I see any dependency related tags. Unless the entire TLP consolidation would be going into stable, I don't see much value for this change in stable kernels.
On Tue, Jan 28, 2025 at 08:00:39PM +0200, Ilpo Järvinen wrote:
On Tue, 28 Jan 2025, Sasha Levin wrote:
From: Ilpo Järvinen ilpo.jarvinen@linux.intel.com
[ Upstream commit e5321ae10e1323359a5067a26dfe98b5f44cc5e6 ]
eetlp_prefix_path in the struct pci_dev tells if End-End TLP Prefixes are supported by the path or not, and the value is only calculated if CONFIG_PCI_PASID is set.
The Max End-End TLP Prefixes field in the Device Capabilities Register 2 also tells how many (1-4) End-End TLP Prefixes are supported (PCIe r6.2 sec 7.5.3.15). The number of supported End-End Prefixes is useful for reading correct number of DWORDs from TLP Prefix Log register in AER capability (PCIe r6.2 sec 7.8.4.12).
Replace eetlp_prefix_path with eetlp_prefix_max and determine the number of supported End-End Prefixes regardless of CONFIG_PCI_PASID so that an upcoming commit generalizing TLP Prefix Log register reading does not have to read extra DWORDs for End-End Prefixes that never will be there.
The value stored into eetlp_prefix_max is directly derived from device's Max End-End TLP Prefixes and does not consider limitations imposed by bridges or the Root Port beyond supported/not supported flags. This is intentional for two reasons:
PCIe r6.2 spec sections 2.2.10.4 & 6.2.4.4 indicate that a TLP is malformed only if the number of prefixes exceed the number of Max End-End TLP Prefixes, which seems to be the case even if the device could never receive that many prefixes due to smaller maximum imposed by a bridge or the Root Port. If TLP parsing is later added, this distinction is significant in interpreting what is logged by the TLP Prefix Log registers and the value matching to the Malformed TLP threshold is going to be more useful.
TLP Prefix handling happens autonomously on a low layer and the value in eetlp_prefix_max is not programmed anywhere by the kernel (i.e., there is no limiter OS can control to prevent sending more than N TLP Prefixes).
Link: https://lore.kernel.org/r/20250114170840.1633-7-ilpo.jarvinen@linux.intel.co... Signed-off-by: Ilpo Järvinen ilpo.jarvinen@linux.intel.com Signed-off-by: Bjorn Helgaas bhelgaas@google.com Reviewed-by: Jonathan Cameron Jonathan.Cameron@huawei.com Reviewed-by: Yazen Ghannam yazen.ghannam@amd.com Signed-off-by: Sasha Levin sashal@kernel.org
Hi,
Why is this being auto selected? It's not a fix nor do I see any dependency related tags. Unless the entire TLP consolidation would be going into stable, I don't see much value for this change in stable kernels.
I wasn't too sure about it either. My thinking was that there is a spec compatibility issue here, but looks like I was wrong.
I'll drop it, thanks!
From: Takashi Iwai tiwai@suse.de
[ Upstream commit b198499c7d2508a76243b98e7cca992f6fd2b7f7 ]
Apparently the Raptor Lake-P reference firmware configures the PIO log size correctly, but some vendor BIOSes, including at least ASUSTeK COMPUTER INC. Zenbook UX3402VA_UX3402VA, do not.
Apply the quirk for Raptor Lake-P. This prevents kernel complaints like:
DPC: RP PIO log size 0 is invalid
and also enables the DPC driver to dump the RP PIO Log registers when DPC is triggered.
Note that the bug report also mentions 8086:a76e, which has been already added by 627c6db20703 ("PCI/DPC: Quirk PIO log size for Intel Raptor Lake Root Ports").
Link: https://lore.kernel.org/r/20250102164315.7562-1-tiwai@suse.de Link: https://bugzilla.suse.com/show_bug.cgi?id=1234623 Signed-off-by: Takashi Iwai tiwai@suse.de [bhelgaas: commit log] Signed-off-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Krzysztof Wilczyński kwilczynski@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pci/quirks.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 76f4df75b08a1..4ed3704ce92e8 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -6253,6 +6253,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a2b, dpc_log_size); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a2d, dpc_log_size); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a2f, dpc_log_size); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a31, dpc_log_size); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0xa72f, dpc_log_size); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0xa73f, dpc_log_size); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0xa76e, dpc_log_size); #endif
From: Rakesh Babu Saladi Saladi.Rakeshbabu@microchip.com
[ Upstream commit a3282f84b2151d254dc4abf24d1255c6382be774 ]
Add Microchip parts to the Device ID table so the driver supports PCI100x devices.
Add a new macro to quirk the Microchip Switchtec PCI100x parts to allow DMA access via NTB to work when the IOMMU is turned on.
PCI100x family has 6 variants; each variant is designed for different application usages, different port counts and lane counts:
PCI1001 has 1 x4 upstream port and 3 x4 downstream ports PCI1002 has 1 x4 upstream port and 4 x2 downstream ports PCI1003 has 2 x4 upstream ports, 2 x2 upstream ports, and 2 x2 downstream ports PCI1004 has 4 x4 upstream ports PCI1005 has 1 x4 upstream port and 6 x2 downstream ports PCI1006 has 6 x2 upstream ports and 2 x2 downstream ports
[Historical note: these parts use PCI_VENDOR_ID_EFAR (0x1055), from EFAR Microsystems, which was acquired in 1996 by Standard Microsystems Corp, which was acquired by Microchip Technology in 2012. The PCI-SIG confirms that Vendor ID 0x1055 is assigned to Microchip even though it's not visible via https://pcisig.com/membership/member-companies]
Link: https://lore.kernel.org/r/20250120095524.243103-1-Saladi.Rakeshbabu@microchi... Signed-off-by: Rakesh Babu Saladi Saladi.Rakeshbabu@microchip.com [bhelgaas: Vendor ID history] Signed-off-by: Bjorn Helgaas bhelgaas@google.com Acked-By: Logan Gunthorpe logang@deltatee.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pci/quirks.c | 11 +++++++++++ drivers/pci/switch/switchtec.c | 26 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+)
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 4ed3704ce92e8..6446291f92d0b 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -5984,6 +5984,17 @@ SWITCHTEC_QUIRK(0x5552); /* PAXA 52XG5 */ SWITCHTEC_QUIRK(0x5536); /* PAXA 36XG5 */ SWITCHTEC_QUIRK(0x5528); /* PAXA 28XG5 */
+#define SWITCHTEC_PCI100X_QUIRK(vid) \ + DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_EFAR, vid, \ + PCI_CLASS_BRIDGE_OTHER, 8, quirk_switchtec_ntb_dma_alias) +SWITCHTEC_PCI100X_QUIRK(0x1001); /* PCI1001XG4 */ +SWITCHTEC_PCI100X_QUIRK(0x1002); /* PCI1002XG4 */ +SWITCHTEC_PCI100X_QUIRK(0x1003); /* PCI1003XG4 */ +SWITCHTEC_PCI100X_QUIRK(0x1004); /* PCI1004XG4 */ +SWITCHTEC_PCI100X_QUIRK(0x1005); /* PCI1005XG4 */ +SWITCHTEC_PCI100X_QUIRK(0x1006); /* PCI1006XG4 */ + + /* * The PLX NTB uses devfn proxy IDs to move TLPs between NT endpoints. * These IDs are used to forward responses to the originator on the other diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c index c7e1089ffdafc..b14dfab04d846 100644 --- a/drivers/pci/switch/switchtec.c +++ b/drivers/pci/switch/switchtec.c @@ -1739,6 +1739,26 @@ static void switchtec_pci_remove(struct pci_dev *pdev) .driver_data = gen, \ }
+#define SWITCHTEC_PCI100X_DEVICE(device_id, gen) \ + { \ + .vendor = PCI_VENDOR_ID_EFAR, \ + .device = device_id, \ + .subvendor = PCI_ANY_ID, \ + .subdevice = PCI_ANY_ID, \ + .class = (PCI_CLASS_MEMORY_OTHER << 8), \ + .class_mask = 0xFFFFFFFF, \ + .driver_data = gen, \ + }, \ + { \ + .vendor = PCI_VENDOR_ID_EFAR, \ + .device = device_id, \ + .subvendor = PCI_ANY_ID, \ + .subdevice = PCI_ANY_ID, \ + .class = (PCI_CLASS_BRIDGE_OTHER << 8), \ + .class_mask = 0xFFFFFFFF, \ + .driver_data = gen, \ + } + static const struct pci_device_id switchtec_pci_tbl[] = { SWITCHTEC_PCI_DEVICE(0x8531, SWITCHTEC_GEN3), /* PFX 24xG3 */ SWITCHTEC_PCI_DEVICE(0x8532, SWITCHTEC_GEN3), /* PFX 32xG3 */ @@ -1833,6 +1853,12 @@ static const struct pci_device_id switchtec_pci_tbl[] = { SWITCHTEC_PCI_DEVICE(0x5552, SWITCHTEC_GEN5), /* PAXA 52XG5 */ SWITCHTEC_PCI_DEVICE(0x5536, SWITCHTEC_GEN5), /* PAXA 36XG5 */ SWITCHTEC_PCI_DEVICE(0x5528, SWITCHTEC_GEN5), /* PAXA 28XG5 */ + SWITCHTEC_PCI100X_DEVICE(0x1001, SWITCHTEC_GEN4), /* PCI1001 16XG4 */ + SWITCHTEC_PCI100X_DEVICE(0x1002, SWITCHTEC_GEN4), /* PCI1002 12XG4 */ + SWITCHTEC_PCI100X_DEVICE(0x1003, SWITCHTEC_GEN4), /* PCI1003 16XG4 */ + SWITCHTEC_PCI100X_DEVICE(0x1004, SWITCHTEC_GEN4), /* PCI1004 16XG4 */ + SWITCHTEC_PCI100X_DEVICE(0x1005, SWITCHTEC_GEN4), /* PCI1005 16XG4 */ + SWITCHTEC_PCI100X_DEVICE(0x1006, SWITCHTEC_GEN4), /* PCI1006 16XG4 */ {0} }; MODULE_DEVICE_TABLE(pci, switchtec_pci_tbl);
linux-stable-mirror@lists.linaro.org