5.10.173-rc1 review
Subsystems (7)
Greg Kroah-Hartman
maintainerPATCH 148/529 drm: Fix potential null-ptr-deref due to drmm_mode_config_init()
In reply to Greg Kroah-HartmanFrom: Shang XiaoJing <[email protected]>
[ Upstream commit 834c23e4f798dcdc8af251b3c428ceef94741991 ]
drmm_mode_config_init() will call drm_mode_create_standard_properties() and won't check the ret value. When drm_mode_create_standard_properties() failed due to alloc, property will be a NULL pointer and may causes the null-ptr-deref. Fix the null-ptr-deref by adding the ret value check.
Found null-ptr-deref while testing insert module bochs:
general protection fault, probably for non-canonical address
0xdffffc000000000c: 0000 [#1] SMP KASAN PTI
KASAN: null-ptr-deref in range [0x0000000000000060-0x0000000000000067]
CPU: 3 PID: 249 Comm: modprobe Not tainted 6.1.0-rc1+ #364
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
rel-1.15.0-0-g2dd4b9b3f840-prebuilt.qemu.org 04/01/2014
RIP: 0010:drm_object_attach_property+0x73/0x3c0 [drm]
Call Trace:
<TASK>
__drm_connector_init+0xb6c/0x1100 [drm]
bochs_pci_probe.cold.11+0x4cb/0x7fe [bochs]
pci_device_probe+0x17d/0x340
really_probe+0x1db/0x5d0
__driver_probe_device+0x1e7/0x250
driver_probe_device+0x4a/0x120
__driver_attach+0xcd/0x2c0
bus_for_each_dev+0x11a/0x1b0
bus_add_driver+0x3d7/0x500
driver_register+0x18e/0x320
do_one_initcall+0xc4/0x3e0
do_init_module+0x1b4/0x630
load_module+0x5dca/0x7230
__do_sys_finit_module+0x100/0x170
do_syscall_64+0x3f/0x90
entry_SYSCALL_64_after_hwframe+0x63/0xcd
RIP: 0033:0x7ff65af9f839--- drivers/gpu/drm/drm_mode_config.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/gpu/drm/drm_mode_config.c +7 -1
@@ -398,6 +398,8 @@ static void drm_mode_config_init_release(struct drm_device *dev, void *ptr)*/ int drmm_mode_config_init (struct drm_device *dev) { +int ret; +mutex_init (&dev->mode_config.mutex);drm_modeset_lock_init (&dev->mode_config.connection_mutex);mutex_init (&dev->mode_config.idr_mutex);
@@ -419,7 +421,11 @@ int drmm_mode_config_init(struct drm_device *dev)init_llist_head (&dev->mode_config.connector_free_list);INIT_WORK (&dev->mode_config.connector_free_work, drm_connector_free_work_fn); -drm_mode_create_standard_properties (dev); + ret =drm_mode_create_standard_properties (dev); +if (ret) { +drm_mode_config_cleanup (dev); +return ret; + }/* Just to be sure */ dev->mode_config.num_fb =0 ;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 149/529 drm/fourcc: Add missing big-endian XRGB1555 and RGB565 formats
In reply to Greg Kroah-HartmanFrom: Geert Uytterhoeven <[email protected]>
[ Upstream commit 6fb6c979ca628583d4d0c59a0f8ff977e581ecc0 ]
As of commit eae06120f1974e1a ("drm: refuse ADDFB2 ioctl for broken bigendian drivers"), drivers must set the quirk_addfb_prefer_host_byte_order quirk to make the drm_mode_addfb() compat code work correctly on big-endian machines.
While that works fine for big-endian XRGB8888 and ARGB8888, which are mapped to the existing little-endian BGRX8888 and BGRA8888 formats, it does not work for big-endian XRGB1555 and RGB565, as the latter are not listed in the format database.
Fix this by adding the missing formats. Limit this to big-endian platforms, as there is currently no need to support these formats on little-endian platforms.
--- drivers/gpu/drm/drm_fourcc.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/gpu/drm/drm_fourcc.c +4 -0
@@ -178,6 +178,10 @@ const struct drm_format_info *__drm_format_info(u32 format) { .format = DRM_FORMAT_BGRA5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, { .format = DRM_FORMAT_RGB565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, { .format = DRM_FORMAT_BGR565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, +#ifdef __BIG_ENDIAN + { .format = DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, +#endif { .format = DRM_FORMAT_RGB888, .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 }, { .format = DRM_FORMAT_BGR888, .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 }, { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 150/529 drm: mxsfb: DRM_MXSFB should depend on ARCH_MXS || ARCH_MXC
In reply to Greg Kroah-HartmanFrom: Geert Uytterhoeven <[email protected]>
[ Upstream commit 7783cc67862f9166c901bfa0f80b717aa8d354dd ]
Freescale/NXP i.MX LCDIF and eLCDIF LCD controllers are only present on Freescale/NXP i.MX SoCs. Hence add a dependency on ARCH_MXS || ARCH_MXC, to prevent asking the user about this driver when configuring a kernel without Freescale/NXP i.MX support.
--- drivers/gpu/drm/mxsfb/Kconfig | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/mxsfb/Kconfig +1 -0
@@ -8,6 +8,7 @@ config DRM_MXSFB tristate "i.MX (e)LCDIF LCD controller" depends on DRM && OF depends on COMMON_CLK + depends on ARCH_MXS || ARCH_MXC || COMPILE_TEST select DRM_MXS select DRM_KMS_HELPER select DRM_KMS_CMA_HELPER
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 151/529 drm/bridge: megachips: Fix error handling in i2c_register_driver()
In reply to Greg Kroah-HartmanFrom: Yuan Can <[email protected]>
[ Upstream commit 4ecff954c370b82bce45bdca2846c5c5563e8a8a ]
A problem about insmod megachips-stdpxxxx-ge-b850v3-fw.ko failed is triggered with the following log given:
[ 4497.981497] Error: Driver 'stdp4028-ge-b850v3-fw' is already registered, aborting...
insmod: ERROR: could not insert module megachips-stdpxxxx-ge-b850v3-fw.ko: Device or resource busy
The reason is that stdpxxxx_ge_b850v3_init() returns i2c_add_driver() directly without checking its return value, if i2c_add_driver() failed, it returns without calling i2c_del_driver() on the previous i2c driver, resulting the megachips-stdpxxxx-ge-b850v3-fw can never be installed later.
A simple call graph is shown as below:
stdpxxxx_ge_b850v3_init()
i2c_add_driver(&stdp4028_ge_b850v3_fw_driver)
i2c_add_driver(&stdp2690_ge_b850v3_fw_driver)
i2c_register_driver()
driver_register()
bus_add_driver()
priv = kzalloc(...) # OOM happened
# return without delete stdp4028_ge_b850v3_fw_driver
Fix by calling i2c_del_driver() on stdp4028_ge_b850v3_fw_driver when i2c_add_driver() returns error.
--- drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c +5 -1
@@ -444,7 +444,11 @@ static int __init stdpxxxx_ge_b850v3_init(void)if (ret)return ret; -return i2c_add_driver (&stdp2690_ge_b850v3_fw_driver); + ret =i2c_add_driver (&stdp2690_ge_b850v3_fw_driver); +if (ret) +i2c_del_driver (&stdp4028_ge_b850v3_fw_driver); + +return ret; }module_init (stdpxxxx_ge_b850v3_init);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 152/529 drm/vkms: Fix null-ptr-deref in vkms_release()
In reply to Greg Kroah-HartmanFrom: Yuan Can <[email protected]>
[ Upstream commit 2fe2a8f40c21161ffe7653cc234e7934db5b7cc5 ]
A null-ptr-deref is triggered when it tries to destroy the workqueue in vkms->output.composer_workq in vkms_release().
KASAN: null-ptr-deref in range [0x0000000000000118-0x000000000000011f] CPU: 5 PID: 17193 Comm: modprobe Not tainted 6.0.0-11331-gd465bff130bf #24 RIP: 0010:destroy_workqueue+0x2f/0x710 ... Call Trace: <TASK> ? vkms_config_debugfs_init+0x50/0x50 [vkms] __devm_drm_dev_alloc+0x15a/0x1c0 [drm] vkms_init+0x245/0x1000 [vkms] do_one_initcall+0xd0/0x4f0 do_init_module+0x1a4/0x680 load_module+0x6249/0x7110 __do_sys_finit_module+0x140/0x200 do_syscall_64+0x35/0x80 entry_SYSCALL_64_after_hwframe+0x46/0xb0
The reason is that an OOM happened which triggers the destroy of the workqueue, however, the workqueue is alloced in the later process, thus a null-ptr-deref happened. A simple call graph is shown as below:
vkms_init()
vkms_create()
devm_drm_dev_alloc()
__devm_drm_dev_alloc()
devm_drm_dev_init()
devm_add_action_or_reset()
devm_add_action() # an error happened
devm_drm_dev_init_release()
drm_dev_put()
kref_put()
drm_dev_release()
vkms_release()
destroy_workqueue() # null-ptr-deref happened
vkms_modeset_init()
vkms_output_init()
vkms_crtc_init() # where the workqueue get allocatedFix this by checking if composer_workq is NULL before passing it to the destroy_workqueue() in vkms_release().
--- drivers/gpu/drm/vkms/vkms_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/vkms/vkms_drv.c +2 -1
@@ -61,7 +61,8 @@ static void vkms_release(struct drm_device *dev) { struct vkms_device *vkms = container_of(dev, struct vkms_device, drm); -destroy_workqueue (vkms->output.composer_workq); +if (vkms->output.composer_workq) +destroy_workqueue (vkms->output.composer_workq); }static void vkms_atomic_commit_tail (struct drm_atomic_state *old_state)
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 153/529 drm/vc4: dpi: Add option for inverting pixel clock and output enable
In reply to Greg Kroah-HartmanFrom: Dave Stevenson <[email protected]>
[ Upstream commit 3c2707632146b22e97b0fbf6778bab8add2eaa1d ]
DRM provides flags for inverting pixel clock and output enable signals, but these were not mapped to the relevant registers.
Add those mappings.
Stable-dep-of: 0870d86eac8a ("drm/vc4: dpi: Fix format mapping for RGB565")
--- drivers/gpu/drm/vc4/vc4_dpi.c | 66 ++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 28 deletions(-)
drivers/gpu/drm/vc4/vc4_dpi.c +38 -28
@@ -148,35 +148,45 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder) }drm_connector_list_iter_end (&conn_iter); -if (connector && connector->display_info.num_bus_formats) { -u32 bus_format = connector->display_info.bus_formats[0 ]; - -switch (bus_format) { -case MEDIA_BUS_FMT_RGB888_1X24 : - dpi_c |=VC4_SET_FIELD (DPI_FORMAT_24BIT_888_RGB , -DPI_FORMAT ); -break ; -case MEDIA_BUS_FMT_BGR888_1X24 : - dpi_c |=VC4_SET_FIELD (DPI_FORMAT_24BIT_888_RGB , -DPI_FORMAT ); - dpi_c |=VC4_SET_FIELD (DPI_ORDER_BGR ,DPI_ORDER ); -break ; -case MEDIA_BUS_FMT_RGB666_1X24_CPADHI : - dpi_c |=VC4_SET_FIELD (DPI_FORMAT_18BIT_666_RGB_2 , -DPI_FORMAT ); -break ; -case MEDIA_BUS_FMT_RGB666_1X18 : - dpi_c |=VC4_SET_FIELD (DPI_FORMAT_18BIT_666_RGB_1 , -DPI_FORMAT ); -break ; -case MEDIA_BUS_FMT_RGB565_1X16 : - dpi_c |=VC4_SET_FIELD (DPI_FORMAT_16BIT_565_RGB_3 , -DPI_FORMAT ); -break ; -default : -DRM_ERROR ("Unknown media bus format %d\n" , bus_format); -break ; +if (connector) { +if (connector->display_info.num_bus_formats) { +u32 bus_format = connector->display_info.bus_formats[0 ]; + +switch (bus_format) { +case MEDIA_BUS_FMT_RGB888_1X24 : + dpi_c |=VC4_SET_FIELD (DPI_FORMAT_24BIT_888_RGB , +DPI_FORMAT ); +break ; +case MEDIA_BUS_FMT_BGR888_1X24 : + dpi_c |=VC4_SET_FIELD (DPI_FORMAT_24BIT_888_RGB , +DPI_FORMAT ); + dpi_c |=VC4_SET_FIELD (DPI_ORDER_BGR , +DPI_ORDER ); +break ; +case MEDIA_BUS_FMT_RGB666_1X24_CPADHI : + dpi_c |=VC4_SET_FIELD (DPI_FORMAT_18BIT_666_RGB_2 , +DPI_FORMAT ); +break ; +case MEDIA_BUS_FMT_RGB666_1X18 : + dpi_c |=VC4_SET_FIELD (DPI_FORMAT_18BIT_666_RGB_1 , +DPI_FORMAT ); +break ; +case MEDIA_BUS_FMT_RGB565_1X16 : + dpi_c |=VC4_SET_FIELD (DPI_FORMAT_16BIT_565_RGB_3 , +DPI_FORMAT ); +break ; +default : +DRM_ERROR ("Unknown media bus format %d\n" , + bus_format); +break ; + } } + +if (connector->display_info.bus_flags &DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE ) + dpi_c |=DPI_PIXEL_CLK_INVERT ; + +if (connector->display_info.bus_flags &DRM_BUS_FLAG_DE_LOW ) + dpi_c |=DPI_OUTPUT_ENABLE_INVERT ; }else {/* Default to 24bit if no connector found. */ dpi_c |=VC4_SET_FIELD (DPI_FORMAT_24BIT_888_RGB ,DPI_FORMAT );
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 154/529 drm/vc4: dpi: Fix format mapping for RGB565
In reply to Greg Kroah-HartmanFrom: Dave Stevenson <[email protected]>
[ Upstream commit 0870d86eac8a9abd89a0be1b719d5dc5bac936f0 ]
The mapping is incorrect for RGB565_1X16 as it should be DPI_FORMAT_18BIT_666_RGB_1 instead of DPI_FORMAT_18BIT_666_RGB_3.
--- drivers/gpu/drm/vc4/vc4_dpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/vc4/vc4_dpi.c +1 -1
@@ -172,7 +172,7 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder) DPI_FORMAT);break ;case MEDIA_BUS_FMT_RGB565_1X16 : - dpi_c |=VC4_SET_FIELD (DPI_FORMAT_16BIT_565_RGB_3 , + dpi_c |=VC4_SET_FIELD (DPI_FORMAT_16BIT_565_RGB_1 ,DPI_FORMAT );break ;default :
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 155/529 drm: tidss: Fix pixel format definition
In reply to Greg Kroah-HartmanFrom: Randolph Sapp <[email protected]>
[ Upstream commit 2df0433b18f2735a49d2c3a968b40fa2881137c0 ]
There was a long-standing bug from a typo that created 2 ARGB1555 and ABGR1555 pixel format entries. Weston 10 has a sanity check that alerted me to this issue.
According to the Supported Pixel Data formats table we have the later entries should have been for Alpha-X instead.
--- drivers/gpu/drm/tidss/tidss_dispc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/tidss/tidss_dispc.c +2 -2
@@ -1855,8 +1855,8 @@ static const struct { { DRM_FORMAT_XBGR4444, 0x21, }, { DRM_FORMAT_RGBX4444, 0x22, }, - { DRM_FORMAT_ARGB1555, 0x25, }, - { DRM_FORMAT_ABGR1555, 0x26, }, + { DRM_FORMAT_XRGB1555, 0x25, }, + { DRM_FORMAT_XBGR1555, 0x26, }, { DRM_FORMAT_XRGB8888, 0x27, }, { DRM_FORMAT_XBGR8888, 0x28, },
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 156/529 gpu: ipu-v3: common: Add of_node_put() for reference returned by of_graph_get_port_by_id()
In reply to Greg Kroah-HartmanFrom: Liang He <[email protected]>
[ Upstream commit 9afdf98cfdfa2ba8ec068cf08c5fcdc1ed8daf3f ]
In ipu_add_client_devices(), we need to call of_node_put() for reference returned by of_graph_get_port_by_id() in fail path.
--- drivers/gpu/ipu-v3/ipu-common.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/ipu-v3/ipu-common.c +1 -0
@@ -1168,6 +1168,7 @@ static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base) pdev =platform_device_alloc (reg->name, id++);if (!pdev) { ret = -ENOMEM ; +of_node_put (of_node); goto err_register; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 157/529 drm/msm/hdmi: Add missing check for alloc_ordered_workqueue
In reply to Greg Kroah-HartmanFrom: Jiasheng Jiang <[email protected]>
[ Upstream commit afe4cb96153a0d8003e4e4ebd91b5c543e10df84 ]
Add check for the return value of alloc_ordered_workqueue as it may return NULL pointer and cause NULL pointer dereference in hdmi_hdcp.c and hdmi_hpd.c.
Patchwork: https://patchwork.freedesktop.org/patch/517211/
--- drivers/gpu/drm/msm/hdmi/hdmi.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/gpu/drm/msm/hdmi/hdmi.c +4 -0
@@ -264,6 +264,10 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev)pm_runtime_enable (&pdev->dev); hdmi->workq =alloc_ordered_workqueue ("msm_hdmi" ,0 ); +if (!hdmi->workq) { + ret = -ENOMEM ; + goto fail; + } hdmi->i2c =msm_hdmi_i2c_init (hdmi);if (IS_ERR (hdmi->i2c)) {
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 158/529 pinctrl: qcom: pinctrl-msm8976: Correct function names for wcss pins
In reply to Greg Kroah-HartmanFrom: Adam Skladowski <[email protected]>
[ Upstream commit a7cc0e2685082a0d79baec02df184dfa83cbfac3 ]
Adjust names of function for wcss pins, also fix third gpio in bt group.
--- drivers/pinctrl/qcom/pinctrl-msm8976.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/pinctrl/qcom/pinctrl-msm8976.c +4 -4
@@ -733,7 +733,7 @@ static const char * const codec_int2_groups[] = { "gpio74", };static const char *const wcss_bt_groups[] = { -"gpio39" ,"gpio47" ,"gpio88" , +"gpio39" ,"gpio47" ,"gpio48" , };static const char *const sdc3_groups[] = {"gpio39" ,"gpio40" ,"gpio41" ,
@@ -958,9 +958,9 @@ static const struct msm_pingroup msm8976_groups[] = {PINGROUP (37 ,NA ,NA ,NA , qdss_tracedata_b,NA ,NA ,NA ,NA ,NA ),PINGROUP (38 ,NA ,NA ,NA ,NA ,NA ,NA ,NA , qdss_tracedata_b,NA ),PINGROUP (39 , wcss_bt, sdc3,NA , qdss_tracedata_a,NA ,NA ,NA ,NA ,NA ), -PINGROUP (40 , wcss_wlan, sdc3,NA , qdss_tracedata_a,NA ,NA ,NA ,NA ,NA ), -PINGROUP (41 , wcss_wlan, sdc3,NA , qdss_tracedata_a,NA ,NA ,NA ,NA ,NA ), -PINGROUP (42 , wcss_wlan, sdc3,NA , qdss_tracedata_a,NA ,NA ,NA ,NA ,NA ), +PINGROUP (40 , wcss_wlan2, sdc3,NA , qdss_tracedata_a,NA ,NA ,NA ,NA ,NA ), +PINGROUP (41 , wcss_wlan1, sdc3,NA , qdss_tracedata_a,NA ,NA ,NA ,NA ,NA ), +PINGROUP (42 , wcss_wlan0, sdc3,NA , qdss_tracedata_a,NA ,NA ,NA ,NA ,NA ),PINGROUP (43 , wcss_wlan, sdc3,NA ,NA , qdss_tracedata_a,NA ,NA ,NA ,NA ),PINGROUP (44 , wcss_wlan, sdc3,NA ,NA ,NA ,NA ,NA ,NA ,NA ), PINGROUP(45, wcss_fm, NA, qdss_tracectl_a, NA, NA, NA, NA, NA, NA),
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 159/529 pinctrl: stm32: Fix refcount leak in stm32_pctrl_get_irq_domain
In reply to Greg Kroah-HartmanFrom: Miaoqian Lin <[email protected]>
[ Upstream commit dcef18c8ac40aa85bb339f64c1dd31dd458b06fb ]
of_irq_find_parent() returns a node pointer with refcount incremented, We should use of_node_put() on it when not needed anymore. Add missing of_node_put() to avoid refcount leak.
--- drivers/pinctrl/stm32/pinctrl-stm32.c | 1 + 1 file changed, 1 insertion(+)
drivers/pinctrl/stm32/pinctrl-stm32.c +1 -0
@@ -1338,6 +1338,7 @@ static struct irq_domain *stm32_pctrl_get_irq_domain(struct device_node *np)return ERR_PTR (-ENXIO ); domain =irq_find_host (parent); +of_node_put (parent);if (!domain)/* domain not registered yet */ return ERR_PTR (-EPROBE_DEFER );
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 160/529 pinctrl: rockchip: add support for rk3568
In reply to Greg Kroah-HartmanFrom: Jianqun Xu <[email protected]>
[ Upstream commit c0dadc0e47a895e95c17a4df1fa12737e1d57d6f ]
RK3568 SoCs have 5 gpio controllers, each gpio has 32 pins. GPIO supports set iomux, pull, drive strength and schmitt.
Stable-dep-of: c818ae563bf9 ("pinctrl: rockchip: Fix refcount leak in rockchip_pinctrl_parse_groups")
--- drivers/pinctrl/pinctrl-rockchip.c | 292 ++++++++++++++++++++++++++++- 1 file changed, 290 insertions(+), 2 deletions(-)
drivers/pinctrl/pinctrl-rockchip.c +290 -2
@@ -61,8 +61,17 @@ enum rockchip_pinctrl_type {RK3308 ,RK3368 ,RK3399 , + RK3568, }; + +/** +* Generate a bitmask for setting a value (v) with a write mask bit in hiword +* register 31:16 area. +*/ +#define WRITE_MASK_VAL (h, l, v) \ + (GENMASK(((h) + 16), ((l) + 16)) | (((v) << (l)) & GENMASK((h), (l)))) +/* * Encode variants of iomux registers into a type variable */
@@ -290,6 +299,25 @@ struct rockchip_pin_bank { .pull_type[3] = pull3, \ } +#define PIN_BANK_MUX_ROUTE_FLAGS (ID ,PIN ,FUNC ,REG ,VAL ,FLAG ) \ + { \ + .bank_num = ID, \ + .pin = PIN, \ + .func = FUNC, \ + .route_offset = REG, \ + .route_val = VAL, \ + .route_location = FLAG, \ + } + +#define RK_MUXROUTE_SAME (ID ,PIN ,FUNC ,REG ,VAL ) \ + PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROCKCHIP_ROUTE_SAME) + +#define RK_MUXROUTE_GRF (ID ,PIN ,FUNC ,REG ,VAL ) \ + PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROCKCHIP_ROUTE_GRF) + +#define RK_MUXROUTE_PMU (ID ,PIN ,FUNC ,REG ,VAL ) \ + PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROCKCHIP_ROUTE_PMU) +/** * struct rockchip_mux_recalced_data: represent a pin iomux data. * @num: bank number.
@@ -1409,6 +1437,102 @@ static struct rockchip_mux_route_data rk3399_mux_route_data[] = { }, }; +static struct rockchip_mux_route_data rk3568_mux_route_data[] = { +RK_MUXROUTE_PMU (0 ,RK_PB7 ,1 ,0x0110 ,WRITE_MASK_VAL (1 ,0 ,0 )),/* PWM0 IO mux M0 */ +RK_MUXROUTE_PMU (0 ,RK_PC7 ,2 ,0x0110 ,WRITE_MASK_VAL (1 ,0 ,1 )),/* PWM0 IO mux M1 */ +RK_MUXROUTE_PMU (0 ,RK_PC0 ,1 ,0x0110 ,WRITE_MASK_VAL (3 ,2 ,0 )),/* PWM1 IO mux M0 */ +RK_MUXROUTE_PMU (0 ,RK_PB5 ,4 ,0x0110 ,WRITE_MASK_VAL (3 ,2 ,1 )),/* PWM1 IO mux M1 */ +RK_MUXROUTE_PMU (0 ,RK_PC1 ,1 ,0x0110 ,WRITE_MASK_VAL (5 ,4 ,0 )),/* PWM2 IO mux M0 */ +RK_MUXROUTE_PMU (0 ,RK_PB6 ,4 ,0x0110 ,WRITE_MASK_VAL (5 ,4 ,1 )),/* PWM2 IO mux M1 */ +RK_MUXROUTE_PMU (0 ,RK_PB3 ,2 ,0x0300 ,WRITE_MASK_VAL (0 ,0 ,0 )),/* CAN0 IO mux M0 */ +RK_MUXROUTE_GRF (2 ,RK_PA1 ,4 ,0x0300 ,WRITE_MASK_VAL (0 ,0 ,1 )),/* CAN0 IO mux M1 */ +RK_MUXROUTE_GRF (1 ,RK_PA1 ,3 ,0x0300 ,WRITE_MASK_VAL (2 ,2 ,0 )),/* CAN1 IO mux M0 */ +RK_MUXROUTE_GRF (4 ,RK_PC3 ,3 ,0x0300 ,WRITE_MASK_VAL (2 ,2 ,1 )),/* CAN1 IO mux M1 */ +RK_MUXROUTE_GRF (4 ,RK_PB5 ,3 ,0x0300 ,WRITE_MASK_VAL (4 ,4 ,0 )),/* CAN2 IO mux M0 */ +RK_MUXROUTE_GRF (2 ,RK_PB2 ,4 ,0x0300 ,WRITE_MASK_VAL (4 ,4 ,1 )),/* CAN2 IO mux M1 */ +RK_MUXROUTE_GRF (4 ,RK_PC4 ,1 ,0x0300 ,WRITE_MASK_VAL (6 ,6 ,0 )),/* HPDIN IO mux M0 */ +RK_MUXROUTE_PMU (0 ,RK_PC2 ,2 ,0x0300 ,WRITE_MASK_VAL (6 ,6 ,1 )),/* HPDIN IO mux M1 */ +RK_MUXROUTE_GRF (3 ,RK_PB1 ,3 ,0x0300 ,WRITE_MASK_VAL (8 ,8 ,0 )),/* GMAC1 IO mux M0 */ +RK_MUXROUTE_GRF (4 ,RK_PA7 ,3 ,0x0300 ,WRITE_MASK_VAL (8 ,8 ,1 )),/* GMAC1 IO mux M1 */ +RK_MUXROUTE_GRF (4 ,RK_PD1 ,1 ,0x0300 ,WRITE_MASK_VAL (10 ,10 ,0 )),/* HDMITX IO mux M0 */ +RK_MUXROUTE_PMU (0 ,RK_PC7 ,1 ,0x0300 ,WRITE_MASK_VAL (10 ,10 ,1 )),/* HDMITX IO mux M1 */ +RK_MUXROUTE_PMU (0 ,RK_PB6 ,1 ,0x0300 ,WRITE_MASK_VAL (14 ,14 ,0 )),/* I2C2 IO mux M0 */ +RK_MUXROUTE_GRF (4 ,RK_PB4 ,1 ,0x0300 ,WRITE_MASK_VAL (14 ,14 ,1 )),/* I2C2 IO mux M1 */ +RK_MUXROUTE_GRF (1 ,RK_PA0 ,1 ,0x0304 ,WRITE_MASK_VAL (0 ,0 ,0 )),/* I2C3 IO mux M0 */ +RK_MUXROUTE_GRF (3 ,RK_PB6 ,4 ,0x0304 ,WRITE_MASK_VAL (0 ,0 ,1 )),/* I2C3 IO mux M1 */ +RK_MUXROUTE_GRF (4 ,RK_PB2 ,1 ,0x0304 ,WRITE_MASK_VAL (2 ,2 ,0 )),/* I2C4 IO mux M0 */ +RK_MUXROUTE_GRF (2 ,RK_PB1 ,2 ,0x0304 ,WRITE_MASK_VAL (2 ,2 ,1 )),/* I2C4 IO mux M1 */ +RK_MUXROUTE_GRF (3 ,RK_PB4 ,4 ,0x0304 ,WRITE_MASK_VAL (4 ,4 ,0 )),/* I2C5 IO mux M0 */ +RK_MUXROUTE_GRF (4 ,RK_PD0 ,2 ,0x0304 ,WRITE_MASK_VAL (4 ,4 ,1 )),/* I2C5 IO mux M1 */ +RK_MUXROUTE_GRF (3 ,RK_PB1 ,5 ,0x0304 ,WRITE_MASK_VAL (14 ,14 ,0 )),/* PWM8 IO mux M0 */ +RK_MUXROUTE_GRF (1 ,RK_PD5 ,4 ,0x0304 ,WRITE_MASK_VAL (14 ,14 ,1 )),/* PWM8 IO mux M1 */ +RK_MUXROUTE_GRF (3 ,RK_PB2 ,5 ,0x0308 ,WRITE_MASK_VAL (0 ,0 ,0 )),/* PWM9 IO mux M0 */ +RK_MUXROUTE_GRF (1 ,RK_PD6 ,4 ,0x0308 ,WRITE_MASK_VAL (0 ,0 ,1 )),/* PWM9 IO mux M1 */ +RK_MUXROUTE_GRF (3 ,RK_PB5 ,5 ,0x0308 ,WRITE_MASK_VAL (2 ,2 ,0 )),/* PWM10 IO mux M0 */ +RK_MUXROUTE_GRF (2 ,RK_PA1 ,2 ,0x0308 ,WRITE_MASK_VAL (2 ,2 ,1 )),/* PWM10 IO mux M1 */ +RK_MUXROUTE_GRF (3 ,RK_PB6 ,5 ,0x0308 ,WRITE_MASK_VAL (4 ,4 ,0 )),/* PWM11 IO mux M0 */ +RK_MUXROUTE_GRF (4 ,RK_PC0 ,3 ,0x0308 ,WRITE_MASK_VAL (4 ,4 ,1 )),/* PWM11 IO mux M1 */ +RK_MUXROUTE_GRF (3 ,RK_PB7 ,2 ,0x0308 ,WRITE_MASK_VAL (6 ,6 ,0 )),/* PWM12 IO mux M0 */ +RK_MUXROUTE_GRF (4 ,RK_PC5 ,1 ,0x0308 ,WRITE_MASK_VAL (6 ,6 ,1 )),/* PWM12 IO mux M1 */ +RK_MUXROUTE_GRF (3 ,RK_PC0 ,2 ,0x0308 ,WRITE_MASK_VAL (8 ,8 ,0 )),/* PWM13 IO mux M0 */ +RK_MUXROUTE_GRF (4 ,RK_PC6 ,1 ,0x0308 ,WRITE_MASK_VAL (8 ,8 ,1 )),/* PWM13 IO mux M1 */ +RK_MUXROUTE_GRF (3 ,RK_PC4 ,1 ,0x0308 ,WRITE_MASK_VAL (10 ,10 ,0 )),/* PWM14 IO mux M0 */ +RK_MUXROUTE_GRF (4 ,RK_PC2 ,1 ,0x0308 ,WRITE_MASK_VAL (10 ,10 ,1 )),/* PWM14 IO mux M1 */ +RK_MUXROUTE_GRF (3 ,RK_PC5 ,1 ,0x0308 ,WRITE_MASK_VAL (12 ,12 ,0 )),/* PWM15 IO mux M0 */ +RK_MUXROUTE_GRF (4 ,RK_PC3 ,1 ,0x0308 ,WRITE_MASK_VAL (12 ,12 ,1 )),/* PWM15 IO mux M1 */ +RK_MUXROUTE_GRF (3 ,RK_PD2 ,3 ,0x0308 ,WRITE_MASK_VAL (14 ,14 ,0 )),/* SDMMC2 IO mux M0 */ +RK_MUXROUTE_GRF (3 ,RK_PA5 ,5 ,0x0308 ,WRITE_MASK_VAL (14 ,14 ,1 )),/* SDMMC2 IO mux M1 */ +RK_MUXROUTE_PMU (0 ,RK_PB5 ,2 ,0x030c ,WRITE_MASK_VAL (0 ,0 ,0 )),/* SPI0 IO mux M0 */ +RK_MUXROUTE_GRF (2 ,RK_PD3 ,3 ,0x030c ,WRITE_MASK_VAL (0 ,0 ,1 )),/* SPI0 IO mux M1 */ +RK_MUXROUTE_GRF (2 ,RK_PB5 ,3 ,0x030c ,WRITE_MASK_VAL (2 ,2 ,0 )),/* SPI1 IO mux M0 */ +RK_MUXROUTE_GRF (3 ,RK_PC3 ,3 ,0x030c ,WRITE_MASK_VAL (2 ,2 ,1 )),/* SPI1 IO mux M1 */ +RK_MUXROUTE_GRF (2 ,RK_PC1 ,4 ,0x030c ,WRITE_MASK_VAL (4 ,4 ,0 )),/* SPI2 IO mux M0 */ +RK_MUXROUTE_GRF (3 ,RK_PA0 ,3 ,0x030c ,WRITE_MASK_VAL (4 ,4 ,1 )),/* SPI2 IO mux M1 */ +RK_MUXROUTE_GRF (4 ,RK_PB3 ,4 ,0x030c ,WRITE_MASK_VAL (6 ,6 ,0 )),/* SPI3 IO mux M0 */ +RK_MUXROUTE_GRF (4 ,RK_PC2 ,2 ,0x030c ,WRITE_MASK_VAL (6 ,6 ,1 )),/* SPI3 IO mux M1 */ +RK_MUXROUTE_GRF (2 ,RK_PB4 ,2 ,0x030c ,WRITE_MASK_VAL (8 ,8 ,0 )),/* UART1 IO mux M0 */ +RK_MUXROUTE_PMU (0 ,RK_PD1 ,1 ,0x030c ,WRITE_MASK_VAL (8 ,8 ,1 )),/* UART1 IO mux M1 */ +RK_MUXROUTE_PMU (0 ,RK_PD1 ,1 ,0x030c ,WRITE_MASK_VAL (10 ,10 ,0 )),/* UART2 IO mux M0 */ +RK_MUXROUTE_GRF (1 ,RK_PD5 ,2 ,0x030c ,WRITE_MASK_VAL (10 ,10 ,1 )),/* UART2 IO mux M1 */ +RK_MUXROUTE_GRF (1 ,RK_PA1 ,2 ,0x030c ,WRITE_MASK_VAL (12 ,12 ,0 )),/* UART3 IO mux M0 */ +RK_MUXROUTE_GRF (3 ,RK_PB7 ,4 ,0x030c ,WRITE_MASK_VAL (12 ,12 ,1 )),/* UART3 IO mux M1 */ +RK_MUXROUTE_GRF (1 ,RK_PA6 ,2 ,0x030c ,WRITE_MASK_VAL (14 ,14 ,0 )),/* UART4 IO mux M0 */ +RK_MUXROUTE_GRF (3 ,RK_PB2 ,4 ,0x030c ,WRITE_MASK_VAL (14 ,14 ,1 )),/* UART4 IO mux M1 */ +RK_MUXROUTE_GRF (2 ,RK_PA2 ,3 ,0x0310 ,WRITE_MASK_VAL (0 ,0 ,0 )),/* UART5 IO mux M0 */ +RK_MUXROUTE_GRF (3 ,RK_PC2 ,4 ,0x0310 ,WRITE_MASK_VAL (0 ,0 ,1 )),/* UART5 IO mux M1 */ +RK_MUXROUTE_GRF (2 ,RK_PA4 ,3 ,0x0310 ,WRITE_MASK_VAL (2 ,2 ,0 )),/* UART6 IO mux M0 */ +RK_MUXROUTE_GRF (1 ,RK_PD5 ,3 ,0x0310 ,WRITE_MASK_VAL (2 ,2 ,1 )),/* UART6 IO mux M1 */ +RK_MUXROUTE_GRF (2 ,RK_PA6 ,3 ,0x0310 ,WRITE_MASK_VAL (5 ,4 ,0 )),/* UART7 IO mux M0 */ +RK_MUXROUTE_GRF (3 ,RK_PC4 ,4 ,0x0310 ,WRITE_MASK_VAL (5 ,4 ,1 )),/* UART7 IO mux M1 */ +RK_MUXROUTE_GRF (4 ,RK_PA2 ,4 ,0x0310 ,WRITE_MASK_VAL (5 ,4 ,2 )),/* UART7 IO mux M2 */ +RK_MUXROUTE_GRF (2 ,RK_PC5 ,3 ,0x0310 ,WRITE_MASK_VAL (6 ,6 ,0 )),/* UART8 IO mux M0 */ +RK_MUXROUTE_GRF (2 ,RK_PD7 ,4 ,0x0310 ,WRITE_MASK_VAL (6 ,6 ,1 )),/* UART8 IO mux M1 */ +RK_MUXROUTE_GRF (2 ,RK_PB0 ,3 ,0x0310 ,WRITE_MASK_VAL (9 ,8 ,0 )),/* UART9 IO mux M0 */ +RK_MUXROUTE_GRF (4 ,RK_PC5 ,4 ,0x0310 ,WRITE_MASK_VAL (9 ,8 ,1 )),/* UART9 IO mux M1 */ +RK_MUXROUTE_GRF (4 ,RK_PA4 ,4 ,0x0310 ,WRITE_MASK_VAL (9 ,8 ,2 )),/* UART9 IO mux M2 */ +RK_MUXROUTE_GRF (1 ,RK_PA2 ,1 ,0x0310 ,WRITE_MASK_VAL (11 ,10 ,0 )),/* I2S1 IO mux M0 */ +RK_MUXROUTE_GRF (3 ,RK_PC6 ,4 ,0x0310 ,WRITE_MASK_VAL (11 ,10 ,1 )),/* I2S1 IO mux M1 */ +RK_MUXROUTE_GRF (2 ,RK_PD0 ,5 ,0x0310 ,WRITE_MASK_VAL (11 ,10 ,2 )),/* I2S1 IO mux M2 */ +RK_MUXROUTE_GRF (2 ,RK_PC1 ,1 ,0x0310 ,WRITE_MASK_VAL (12 ,12 ,0 )),/* I2S2 IO mux M0 */ +RK_MUXROUTE_GRF (4 ,RK_PB6 ,5 ,0x0310 ,WRITE_MASK_VAL (12 ,12 ,1 )),/* I2S2 IO mux M1 */ +RK_MUXROUTE_GRF (3 ,RK_PA2 ,4 ,0x0310 ,WRITE_MASK_VAL (14 ,14 ,0 )),/* I2S3 IO mux M0 */ +RK_MUXROUTE_GRF (4 ,RK_PC2 ,5 ,0x0310 ,WRITE_MASK_VAL (14 ,14 ,1 )),/* I2S3 IO mux M1 */ +RK_MUXROUTE_GRF (1 ,RK_PA4 ,3 ,0x0314 ,WRITE_MASK_VAL (1 ,0 ,0 )),/* PDM IO mux M0 */ +RK_MUXROUTE_GRF (1 ,RK_PA6 ,3 ,0x0314 ,WRITE_MASK_VAL (1 ,0 ,0 )),/* PDM IO mux M0 */ +RK_MUXROUTE_GRF (3 ,RK_PD6 ,5 ,0x0314 ,WRITE_MASK_VAL (1 ,0 ,1 )),/* PDM IO mux M1 */ +RK_MUXROUTE_GRF (4 ,RK_PA0 ,4 ,0x0314 ,WRITE_MASK_VAL (1 ,0 ,1 )),/* PDM IO mux M1 */ +RK_MUXROUTE_GRF (3 ,RK_PC4 ,5 ,0x0314 ,WRITE_MASK_VAL (1 ,0 ,2 )),/* PDM IO mux M2 */ +RK_MUXROUTE_PMU (0 ,RK_PA5 ,3 ,0x0314 ,WRITE_MASK_VAL (3 ,2 ,0 )),/* PCIE20 IO mux M0 */ +RK_MUXROUTE_GRF (2 ,RK_PD0 ,4 ,0x0314 ,WRITE_MASK_VAL (3 ,2 ,1 )),/* PCIE20 IO mux M1 */ +RK_MUXROUTE_GRF (1 ,RK_PB0 ,4 ,0x0314 ,WRITE_MASK_VAL (3 ,2 ,2 )),/* PCIE20 IO mux M2 */ +RK_MUXROUTE_PMU (0 ,RK_PA4 ,3 ,0x0314 ,WRITE_MASK_VAL (5 ,4 ,0 )),/* PCIE30X1 IO mux M0 */ +RK_MUXROUTE_GRF (2 ,RK_PD2 ,4 ,0x0314 ,WRITE_MASK_VAL (5 ,4 ,1 )),/* PCIE30X1 IO mux M1 */ +RK_MUXROUTE_GRF (1 ,RK_PA5 ,4 ,0x0314 ,WRITE_MASK_VAL (5 ,4 ,2 )),/* PCIE30X1 IO mux M2 */ +RK_MUXROUTE_PMU (0 ,RK_PA6 ,2 ,0x0314 ,WRITE_MASK_VAL (7 ,6 ,0 )),/* PCIE30X2 IO mux M0 */ +RK_MUXROUTE_GRF (2 ,RK_PD4 ,4 ,0x0314 ,WRITE_MASK_VAL (7 ,6 ,1 )),/* PCIE30X2 IO mux M1 */ +RK_MUXROUTE_GRF (4 ,RK_PC2 ,4 ,0x0314 ,WRITE_MASK_VAL (7 ,6 ,2 )),/* PCIE30X2 IO mux M2 */ +}; +static bool rockchip_get_mux_route (struct rockchip_pin_bank *bank,int pin,int mux,u32 *loc,u32 *reg,u32 *value) {
@@ -2117,6 +2241,68 @@ static void rk3399_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, *bit = (pin_num %8 ) *2 ; } +#define RK3568_PULL_PMU_OFFSET 0x20 +#define RK3568_PULL_GRF_OFFSET 0x80 +#define RK3568_PULL_BITS_PER_PIN 2 +#define RK3568_PULL_PINS_PER_REG 8 +#define RK3568_PULL_BANK_STRIDE 0x10 + +static void rk3568_calc_pull_reg_and_bit (struct rockchip_pin_bank *bank, +int pin_num,struct regmap **regmap, +int *reg,u8 *bit) +{ +struct rockchip_pinctrl *info = bank->drvdata; + +if (bank->bank_num ==0 ) { + *regmap = info->regmap_pmu; + *reg =RK3568_PULL_PMU_OFFSET ; + *reg += bank->bank_num *RK3568_PULL_BANK_STRIDE ; + *reg += ((pin_num /RK3568_PULL_PINS_PER_REG ) *4 ); + + *bit = pin_num %RK3568_PULL_PINS_PER_REG ; + *bit *=RK3568_PULL_BITS_PER_PIN ; + }else { + *regmap = info->regmap_base; + *reg =RK3568_PULL_GRF_OFFSET ; + *reg += (bank->bank_num -1 ) *RK3568_PULL_BANK_STRIDE ; + *reg += ((pin_num /RK3568_PULL_PINS_PER_REG ) *4 ); + + *bit = (pin_num %RK3568_PULL_PINS_PER_REG ); + *bit *=RK3568_PULL_BITS_PER_PIN ; + } +} + +#define RK3568_DRV_PMU_OFFSET 0x70 +#define RK3568_DRV_GRF_OFFSET 0x200 +#define RK3568_DRV_BITS_PER_PIN 8 +#define RK3568_DRV_PINS_PER_REG 2 +#define RK3568_DRV_BANK_STRIDE 0x40 + +static void rk3568_calc_drv_reg_and_bit (struct rockchip_pin_bank *bank, +int pin_num,struct regmap **regmap, +int *reg,u8 *bit) +{ +struct rockchip_pinctrl *info = bank->drvdata; + +/* The first 32 pins of the first bank are located in PMU */ +if (bank->bank_num ==0 ) { + *regmap = info->regmap_pmu; + *reg =RK3568_DRV_PMU_OFFSET ; + *reg += ((pin_num /RK3568_DRV_PINS_PER_REG ) *4 ); + + *bit = pin_num %RK3568_DRV_PINS_PER_REG ; + *bit *=RK3568_DRV_BITS_PER_PIN ; + }else { + *regmap = info->regmap_base; + *reg =RK3568_DRV_GRF_OFFSET ; + *reg += (bank->bank_num -1 ) *RK3568_DRV_BANK_STRIDE ; + *reg += ((pin_num /RK3568_DRV_PINS_PER_REG ) *4 ); + + *bit = (pin_num %RK3568_DRV_PINS_PER_REG ); + *bit *=RK3568_DRV_BITS_PER_PIN ; + } +} +static int rockchip_perpin_drv_list[DRV_TYPE_MAX ][8 ] = { {2 ,4 ,8 ,12 ,-1 ,-1 ,-1 ,-1 }, {3 ,6 ,9 ,12 ,-1 ,-1 ,-1 ,-1 },
@@ -2217,6 +2403,11 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank, bank->bank_num, pin_num, strength); ctrl->drv_calc_reg (bank, pin_num, ®map, ®, &bit); +if (ctrl->type ==RK3568 ) { + rmask_bits =RK3568_DRV_BITS_PER_PIN ; + ret = (1 << (strength +1 )) -1 ; + goto config; + } ret = -EINVAL ;for (i =0 ; i <ARRAY_SIZE (rockchip_perpin_drv_list[drv_type]); i++) {
@@ -2286,6 +2477,7 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,return -EINVAL ; } +config:/* enable the write to the equivalent lower bits */ data = ((1 << rmask_bits) -1 ) << (bit +16 ); rmask = data | (data >>16 );
@@ -2388,6 +2580,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,case RK3308 :case RK3368 :case RK3399 : +case RK3568 : pull_type = bank->pull_type[pin_num /8 ]; ret = -EINVAL ; for (i = 0; i < ARRAY_SIZE(rockchip_pull_list[pull_type]);
@@ -2397,6 +2590,14 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,break ; } } +/* +* In the TRM, pull-up being 1 for everything except the GPIO0_D0-D6, +* where that pull up value becomes 3. +*/ +if (ctrl->type ==RK3568 && bank->bank_num ==0 && pin_num >=27 && pin_num <=30 ) { +if (ret ==1 ) + ret =3 ; + }if (ret <0 ) { dev_err(info->dev, "unsupported pull setting %d\n",
@@ -2441,6 +2642,35 @@ static int rk3328_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,return 0 ; } +#define RK3568_SCHMITT_BITS_PER_PIN 2 +#define RK3568_SCHMITT_PINS_PER_REG 8 +#define RK3568_SCHMITT_BANK_STRIDE 0x10 +#define RK3568_SCHMITT_GRF_OFFSET 0xc0 +#define RK3568_SCHMITT_PMUGRF_OFFSET 0x30 + +static int rk3568_calc_schmitt_reg_and_bit (struct rockchip_pin_bank *bank, +int pin_num, +struct regmap **regmap, +int *reg,u8 *bit) +{ +struct rockchip_pinctrl *info = bank->drvdata; + +if (bank->bank_num ==0 ) { + *regmap = info->regmap_pmu; + *reg =RK3568_SCHMITT_PMUGRF_OFFSET ; + }else { + *regmap = info->regmap_base; + *reg =RK3568_SCHMITT_GRF_OFFSET ; + *reg += (bank->bank_num -1 ) *RK3568_SCHMITT_BANK_STRIDE ; + } + + *reg += ((pin_num /RK3568_SCHMITT_PINS_PER_REG ) *4 ); + *bit = pin_num %RK3568_SCHMITT_PINS_PER_REG ; + *bit *=RK3568_SCHMITT_BITS_PER_PIN ; + +return 0 ; +} +static int rockchip_get_schmitt (struct rockchip_pin_bank *bank,int pin_num) {struct rockchip_pinctrl *info = bank->drvdata;
@@ -2459,6 +2689,13 @@ static int rockchip_get_schmitt(struct rockchip_pin_bank *bank, int pin_num)return ret; data >>= bit; +switch (ctrl->type) { +case RK3568 : +return data & ((1 <<RK3568_SCHMITT_BITS_PER_PIN ) -1 ); +default : +break ; + } +return data &0x1 ; }
@@ -2480,8 +2717,17 @@ static int rockchip_set_schmitt(struct rockchip_pin_bank *bank,return ret;/* enable the write to the equivalent lower bits */ - data =BIT (bit +16 ) | (enable << bit); - rmask =BIT (bit +16 ) |BIT (bit); +switch (ctrl->type) { +case RK3568 : + data = ((1 <<RK3568_SCHMITT_BITS_PER_PIN ) -1 ) << (bit +16 ); + rmask = data | (data >>16 ); + data |= ((enable ?0x2 :0x1 ) << bit); +break ; +default : + data =BIT (bit +16 ) | (enable << bit); + rmask =BIT (bit +16 ) |BIT (bit); +break ; + }return regmap_update_bits (regmap, reg, rmask, data); }
@@ -2655,6 +2901,7 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl,case RK3308 :case RK3368 :case RK3399 : +case RK3568 :return (pull !=PIN_CONFIG_BIAS_PULL_PIN_DEFAULT ); }
@@ -4230,6 +4477,45 @@ static struct rockchip_pin_ctrl rk3399_pin_ctrl = { .drv_calc_reg = rk3399_calc_drv_reg_and_bit, }; +static struct rockchip_pin_bank rk3568_pin_banks[] = { +PIN_BANK_IOMUX_FLAGS (0 ,32 ,"gpio0" ,IOMUX_SOURCE_PMU |IOMUX_WIDTH_4BIT , +IOMUX_SOURCE_PMU |IOMUX_WIDTH_4BIT , +IOMUX_SOURCE_PMU |IOMUX_WIDTH_4BIT , +IOMUX_SOURCE_PMU |IOMUX_WIDTH_4BIT ), +PIN_BANK_IOMUX_FLAGS (1 ,32 ,"gpio1" ,IOMUX_WIDTH_4BIT , +IOMUX_WIDTH_4BIT , +IOMUX_WIDTH_4BIT , +IOMUX_WIDTH_4BIT ), +PIN_BANK_IOMUX_FLAGS (2 ,32 ,"gpio2" ,IOMUX_WIDTH_4BIT , +IOMUX_WIDTH_4BIT , +IOMUX_WIDTH_4BIT , +IOMUX_WIDTH_4BIT ), +PIN_BANK_IOMUX_FLAGS (3 ,32 ,"gpio3" ,IOMUX_WIDTH_4BIT , +IOMUX_WIDTH_4BIT , +IOMUX_WIDTH_4BIT , +IOMUX_WIDTH_4BIT ), +PIN_BANK_IOMUX_FLAGS (4 ,32 ,"gpio4" ,IOMUX_WIDTH_4BIT , +IOMUX_WIDTH_4BIT , +IOMUX_WIDTH_4BIT , +IOMUX_WIDTH_4BIT ), +}; + +static struct rockchip_pin_ctrl rk3568_pin_ctrl = { + .pin_banks = rk3568_pin_banks, + .nr_banks =ARRAY_SIZE (rk3568_pin_banks), + .label ="RK3568-GPIO" , + .type =RK3568 , + .grf_mux_offset =0x0 , + .pmu_mux_offset =0x0 , + .grf_drv_offset =0x0200 , + .pmu_drv_offset =0x0070 , + .iomux_routes = rk3568_mux_route_data, + .niomux_routes =ARRAY_SIZE (rk3568_mux_route_data), + .pull_calc_reg = rk3568_calc_pull_reg_and_bit, + .drv_calc_reg = rk3568_calc_drv_reg_and_bit, + .schmitt_calc_reg = rk3568_calc_schmitt_reg_and_bit, +}; +static const struct of_device_id rockchip_pinctrl_dt_match[] = { { .compatible ="rockchip,px30-pinctrl" , .data = &px30_pin_ctrl },
@@ -4259,6 +4545,8 @@ static const struct of_device_id rockchip_pinctrl_dt_match[] = { .data = &rk3368_pin_ctrl }, { .compatible = "rockchip,rk3399-pinctrl", .data = &rk3399_pin_ctrl }, + { .compatible = "rockchip,rk3568-pinctrl", + .data = &rk3568_pin_ctrl }, {}, };
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 161/529 pinctrl: rockchip: do coding style for mux route struct
In reply to Greg Kroah-HartmanFrom: Jianqun Xu <[email protected]>
[ Upstream commit fe202ea8e5b170ef7b3741da885e8cb7bae1106e ]
The mux route tables take many lines for each SoC, and it will be more instances for newly SoC, that makes the file size increase larger.
This patch only do coding style for mux route struct, by adding a new definition and replace the structs by script which supplied by [email protected]
sed -i -e "
/static struct rockchip_mux_route_data /bcheck
b
:append-next-line
N
:check
/^[^;]*$/bappend-next-line
s/[[:blank:]]*.bank_num = \([[:digit:]]*,\)\n/\tRK_MUXROUTE_SAME(\1/g
s/[[:blank:]]*.pin =[[:blank:]]*0,\n/ RK_PA0,/g
s/[[:blank:]]*.pin =[[:blank:]]*1,\n/ RK_PA1,/g
s/[[:blank:]]*.pin =[[:blank:]]*2,\n/ RK_PA2,/g
s/[[:blank:]]*.pin =[[:blank:]]*3,\n/ RK_PA3,/g
s/[[:blank:]]*.pin =[[:blank:]]*4,\n/ RK_PA4,/g
s/[[:blank:]]*.pin =[[:blank:]]*5,\n/ RK_PA5,/g
s/[[:blank:]]*.pin =[[:blank:]]*6,\n/ RK_PA6,/g
s/[[:blank:]]*.pin =[[:blank:]]*7,\n/ RK_PA7,/g
s/[[:blank:]]*.pin =[[:blank:]]*8,\n/ RK_PB0,/g
s/[[:blank:]]*.pin =[[:blank:]]*9,\n/ RK_PB1,/g
s/[[:blank:]]*.pin =[[:blank:]]*10,\n/ RK_PB2,/g
s/[[:blank:]]*.pin =[[:blank:]]*11,\n/ RK_PB3,/g
s/[[:blank:]]*.pin =[[:blank:]]*12,\n/ RK_PB4,/g
s/[[:blank:]]*.pin =[[:blank:]]*13,\n/ RK_PB5,/g
s/[[:blank:]]*.pin =[[:blank:]]*14,\n/ RK_PB6,/g
s/[[:blank:]]*.pin =[[:blank:]]*15,\n/ RK_PB7,/g
s/[[:blank:]]*.pin =[[:blank:]]*16,\n/ RK_PC0,/g
s/[[:blank:]]*.pin =[[:blank:]]*17,\n/ RK_PC1,/g
s/[[:blank:]]*.pin =[[:blank:]]*18,\n/ RK_PC2,/g
s/[[:blank:]]*.pin =[[:blank:]]*19,\n/ RK_PC3,/g
s/[[:blank:]]*.pin =[[:blank:]]*20,\n/ RK_PC4,/g
s/[[:blank:]]*.pin =[[:blank:]]*21,\n/ RK_PC5,/g
s/[[:blank:]]*.pin =[[:blank:]]*22,\n/ RK_PC6,/g
s/[[:blank:]]*.pin =[[:blank:]]*23,\n/ RK_PC7,/g
s/[[:blank:]]*.pin =[[:blank:]]*24,\n/ RK_PD0,/g
s/[[:blank:]]*.pin =[[:blank:]]*25,\n/ RK_PD1,/g
s/[[:blank:]]*.pin =[[:blank:]]*26,\n/ RK_PD2,/g
s/[[:blank:]]*.pin =[[:blank:]]*27,\n/ RK_PD3,/g
s/[[:blank:]]*.pin =[[:blank:]]*28,\n/ RK_PD4,/g
s/[[:blank:]]*.pin =[[:blank:]]*29,\n/ RK_PD5,/g
s/[[:blank:]]*.pin =[[:blank:]]*30,\n/ RK_PD6,/g
s/[[:blank:]]*.pin =[[:blank:]]*31,\n/ RK_PD7,/g
s/[[:blank:]]*.func = \([[:digit:]]*,\)\n/ \1/g
s/[[:blank:]]*.route_location =[[:blank:]]*\([[:print:]]*,\)\n//g
s/[[:blank:]]*.route_offset = \(0x[[:xdigit:]]*,\)\n/ \1/g
s/[[:blank:]]*.route_val =[[:blank:]]*\([[:print:]]*\),\n/ \1),/g
s/\t{\n//g
s/\t}, {\n//g
s/\t},//g s/[[:blank:]]*\(\/\*[[:print:]]*\*\/\)\n[[:blank:]]*RK_MUXROUTE_SAME(\([[:print:]]*\)),\n/\tRK_MUXROUTE_SAME(\2), \1\n/g s/[[:blank:]]*\(\/\*[[:print:]]*\*\/\)\n[[:blank:]]*RK_MUXROUTE_SAME(\([[:print:]]*\)),/\tRK_MUXROUTE_SAME(\2), \1\n/g " drivers/pinctrl/pinctrl-rockchip.c
Stable-dep-of: c818ae563bf9 ("pinctrl: rockchip: Fix refcount leak in rockchip_pinctrl_parse_groups")
--- drivers/pinctrl/pinctrl-rockchip.c | 650 ++++------------------------- 1 file changed, 80 insertions(+), 570 deletions(-)
drivers/pinctrl/pinctrl-rockchip.c +80 -570
@@ -844,597 +844,107 @@ static void rockchip_get_recalced_mux(struct rockchip_pin_bank *bank, int pin, }static struct rockchip_mux_route_data px30_mux_route_data[] = { - { -/* cif-d2m0 */ - .bank_num =2 , - .pin =0 , - .func =1 , - .route_offset =0x184 , - .route_val =BIT (16 +7 ), - }, { -/* cif-d2m1 */ - .bank_num =3 , - .pin =3 , - .func =3 , - .route_offset =0x184 , - .route_val =BIT (16 +7 ) |BIT (7 ), - }, { -/* pdm-m0 */ - .bank_num =3 , - .pin =22 , - .func =2 , - .route_offset =0x184 , - .route_val =BIT (16 +8 ), - }, { -/* pdm-m1 */ - .bank_num =2 , - .pin =22 , - .func =1 , - .route_offset =0x184 , - .route_val =BIT (16 +8 ) |BIT (8 ), - }, { -/* uart2-rxm0 */ - .bank_num =1 , - .pin =27 , - .func =2 , - .route_offset =0x184 , - .route_val =BIT (16 +10 ), - }, { -/* uart2-rxm1 */ - .bank_num =2 , - .pin =14 , - .func =2 , - .route_offset =0x184 , - .route_val =BIT (16 +10 ) |BIT (10 ), - }, { -/* uart3-rxm0 */ - .bank_num =0 , - .pin =17 , - .func =2 , - .route_offset =0x184 , - .route_val =BIT (16 +9 ), - }, { -/* uart3-rxm1 */ - .bank_num =1 , - .pin =15 , - .func =2 , - .route_offset =0x184 , - .route_val =BIT (16 +9 ) |BIT (9 ), - }, +RK_MUXROUTE_SAME (2 ,RK_PA0 ,1 ,0x184 ,BIT (16 +7 )),/* cif-d2m0 */ +RK_MUXROUTE_SAME (3 ,RK_PA3 ,3 ,0x184 ,BIT (16 +7 ) |BIT (7 )),/* cif-d2m1 */ +RK_MUXROUTE_SAME (3 ,RK_PC6 ,2 ,0x184 ,BIT (16 +8 )),/* pdm-m0 */ +RK_MUXROUTE_SAME (2 ,RK_PC6 ,1 ,0x184 ,BIT (16 +8 ) |BIT (8 )),/* pdm-m1 */ +RK_MUXROUTE_SAME (1 ,RK_PD3 ,2 ,0x184 ,BIT (16 +10 )),/* uart2-rxm0 */ +RK_MUXROUTE_SAME (2 ,RK_PB6 ,2 ,0x184 ,BIT (16 +10 ) |BIT (10 )),/* uart2-rxm1 */ +RK_MUXROUTE_SAME (0 ,RK_PC1 ,2 ,0x184 ,BIT (16 +9 )),/* uart3-rxm0 */ +RK_MUXROUTE_SAME (1 ,RK_PB7 ,2 ,0x184 ,BIT (16 +9 ) |BIT (9 )),/* uart3-rxm1 */ };static struct rockchip_mux_route_data rk3128_mux_route_data[] = { - { -/* spi-0 */ - .bank_num =1 , - .pin =10 , - .func =1 , - .route_offset =0x144 , - .route_val =BIT (16 +3 ) |BIT (16 +4 ), - }, { -/* spi-1 */ - .bank_num =1 , - .pin =27 , - .func =3 , - .route_offset =0x144 , - .route_val =BIT (16 +3 ) |BIT (16 +4 ) |BIT (3 ), - }, { -/* spi-2 */ - .bank_num =0 , - .pin =13 , - .func =2 , - .route_offset =0x144 , - .route_val =BIT (16 +3 ) |BIT (16 +4 ) |BIT (4 ), - }, { -/* i2s-0 */ - .bank_num =1 , - .pin =5 , - .func =1 , - .route_offset =0x144 , - .route_val =BIT (16 +5 ), - }, { -/* i2s-1 */ - .bank_num =0 , - .pin =14 , - .func =1 , - .route_offset =0x144 , - .route_val =BIT (16 +5 ) |BIT (5 ), - }, { -/* emmc-0 */ - .bank_num =1 , - .pin =22 , - .func =2 , - .route_offset =0x144 , - .route_val =BIT (16 +6 ), - }, { -/* emmc-1 */ - .bank_num =2 , - .pin =4 , - .func =2 , - .route_offset =0x144 , - .route_val =BIT (16 +6 ) |BIT (6 ), - }, +RK_MUXROUTE_SAME (1 ,RK_PB2 ,1 ,0x144 ,BIT (16 +3 ) |BIT (16 +4 )),/* spi-0 */ +RK_MUXROUTE_SAME (1 ,RK_PD3 ,3 ,0x144 ,BIT (16 +3 ) |BIT (16 +4 ) |BIT (3 )),/* spi-1 */ +RK_MUXROUTE_SAME (0 ,RK_PB5 ,2 ,0x144 ,BIT (16 +3 ) |BIT (16 +4 ) |BIT (4 )),/* spi-2 */ +RK_MUXROUTE_SAME (1 ,RK_PA5 ,1 ,0x144 ,BIT (16 +5 )),/* i2s-0 */ +RK_MUXROUTE_SAME (0 ,RK_PB6 ,1 ,0x144 ,BIT (16 +5 ) |BIT (5 )),/* i2s-1 */ +RK_MUXROUTE_SAME (1 ,RK_PC6 ,2 ,0x144 ,BIT (16 +6 )),/* emmc-0 */ +RK_MUXROUTE_SAME (2 ,RK_PA4 ,2 ,0x144 ,BIT (16 +6 ) |BIT (6 )),/* emmc-1 */ };static struct rockchip_mux_route_data rk3188_mux_route_data[] = { - { -/* non-iomuxed emmc/flash pins on flash-dqs */ - .bank_num =0 , - .pin =24 , - .func =1 , - .route_location =ROCKCHIP_ROUTE_GRF , - .route_offset =0xa0 , - .route_val =BIT (16 +11 ), - }, { -/* non-iomuxed emmc/flash pins on emmc-clk */ - .bank_num =0 , - .pin =24 , - .func =2 , - .route_location =ROCKCHIP_ROUTE_GRF , - .route_offset =0xa0 , - .route_val =BIT (16 +11 ) |BIT (11 ), - }, +RK_MUXROUTE_SAME (0 ,RK_PD0 ,1 ,0xa0 ,BIT (16 +11 )),/* non-iomuxed emmc/flash pins on flash-dqs */ +RK_MUXROUTE_SAME (0 ,RK_PD0 ,2 ,0xa0 ,BIT (16 +11 ) |BIT (11 )),/* non-iomuxed emmc/flash pins on emmc-clk */ };static struct rockchip_mux_route_data rk3228_mux_route_data[] = { - { -/* pwm0-0 */ - .bank_num =0 , - .pin =26 , - .func =1 , - .route_offset =0x50 , - .route_val =BIT (16 ), - }, { -/* pwm0-1 */ - .bank_num =3 , - .pin =21 , - .func =1 , - .route_offset =0x50 , - .route_val =BIT (16 ) |BIT (0 ), - }, { -/* pwm1-0 */ - .bank_num =0 , - .pin =27 , - .func =1 , - .route_offset =0x50 , - .route_val =BIT (16 +1 ), - }, { -/* pwm1-1 */ - .bank_num =0 , - .pin =30 , - .func =2 , - .route_offset =0x50 , - .route_val =BIT (16 +1 ) |BIT (1 ), - }, { -/* pwm2-0 */ - .bank_num =0 , - .pin =28 , - .func =1 , - .route_offset =0x50 , - .route_val =BIT (16 +2 ), - }, { -/* pwm2-1 */ - .bank_num =1 , - .pin =12 , - .func =2 , - .route_offset =0x50 , - .route_val =BIT (16 +2 ) |BIT (2 ), - }, { -/* pwm3-0 */ - .bank_num =3 , - .pin =26 , - .func =1 , - .route_offset =0x50 , - .route_val =BIT (16 +3 ), - }, { -/* pwm3-1 */ - .bank_num =1 , - .pin =11 , - .func =2 , - .route_offset =0x50 , - .route_val =BIT (16 +3 ) |BIT (3 ), - }, { -/* sdio-0_d0 */ - .bank_num =1 , - .pin =1 , - .func =1 , - .route_offset =0x50 , - .route_val =BIT (16 +4 ), - }, { -/* sdio-1_d0 */ - .bank_num =3 , - .pin =2 , - .func =1 , - .route_offset =0x50 , - .route_val =BIT (16 +4 ) |BIT (4 ), - }, { -/* spi-0_rx */ - .bank_num =0 , - .pin =13 , - .func =2 , - .route_offset =0x50 , - .route_val =BIT (16 +5 ), - }, { -/* spi-1_rx */ - .bank_num =2 , - .pin =0 , - .func =2 , - .route_offset =0x50 , - .route_val =BIT (16 +5 ) |BIT (5 ), - }, { -/* emmc-0_cmd */ - .bank_num =1 , - .pin =22 , - .func =2 , - .route_offset =0x50 , - .route_val =BIT (16 +7 ), - }, { -/* emmc-1_cmd */ - .bank_num =2 , - .pin =4 , - .func =2 , - .route_offset =0x50 , - .route_val =BIT (16 +7 ) |BIT (7 ), - }, { -/* uart2-0_rx */ - .bank_num =1 , - .pin =19 , - .func =2 , - .route_offset =0x50 , - .route_val =BIT (16 +8 ), - }, { -/* uart2-1_rx */ - .bank_num =1 , - .pin =10 , - .func =2 , - .route_offset =0x50 , - .route_val =BIT (16 +8 ) |BIT (8 ), - }, { -/* uart1-0_rx */ - .bank_num =1 , - .pin =10 , - .func =1 , - .route_offset =0x50 , - .route_val =BIT (16 +11 ), - }, { -/* uart1-1_rx */ - .bank_num =3 , - .pin =13 , - .func =1 , - .route_offset =0x50 , - .route_val =BIT (16 +11 ) |BIT (11 ), - }, +RK_MUXROUTE_SAME (0 ,RK_PD2 ,1 ,0x50 ,BIT (16 )),/* pwm0-0 */ +RK_MUXROUTE_SAME (3 ,RK_PC5 ,1 ,0x50 ,BIT (16 ) |BIT (0 )),/* pwm0-1 */ +RK_MUXROUTE_SAME (0 ,RK_PD3 ,1 ,0x50 ,BIT (16 +1 )),/* pwm1-0 */ +RK_MUXROUTE_SAME (0 ,RK_PD6 ,2 ,0x50 ,BIT (16 +1 ) |BIT (1 )),/* pwm1-1 */ +RK_MUXROUTE_SAME (0 ,RK_PD4 ,1 ,0x50 ,BIT (16 +2 )),/* pwm2-0 */ +RK_MUXROUTE_SAME (1 ,RK_PB4 ,2 ,0x50 ,BIT (16 +2 ) |BIT (2 )),/* pwm2-1 */ +RK_MUXROUTE_SAME (3 ,RK_PD2 ,1 ,0x50 ,BIT (16 +3 )),/* pwm3-0 */ +RK_MUXROUTE_SAME (1 ,RK_PB3 ,2 ,0x50 ,BIT (16 +3 ) |BIT (3 )),/* pwm3-1 */ +RK_MUXROUTE_SAME (1 ,RK_PA1 ,1 ,0x50 ,BIT (16 +4 )),/* sdio-0_d0 */ +RK_MUXROUTE_SAME (3 ,RK_PA2 ,1 ,0x50 ,BIT (16 +4 ) |BIT (4 )),/* sdio-1_d0 */ +RK_MUXROUTE_SAME (0 ,RK_PB5 ,2 ,0x50 ,BIT (16 +5 )),/* spi-0_rx */ +RK_MUXROUTE_SAME (2 ,RK_PA0 ,2 ,0x50 ,BIT (16 +5 ) |BIT (5 )),/* spi-1_rx */ +RK_MUXROUTE_SAME (1 ,RK_PC6 ,2 ,0x50 ,BIT (16 +7 )),/* emmc-0_cmd */ +RK_MUXROUTE_SAME (2 ,RK_PA4 ,2 ,0x50 ,BIT (16 +7 ) |BIT (7 )),/* emmc-1_cmd */ +RK_MUXROUTE_SAME (1 ,RK_PC3 ,2 ,0x50 ,BIT (16 +8 )),/* uart2-0_rx */ +RK_MUXROUTE_SAME (1 ,RK_PB2 ,2 ,0x50 ,BIT (16 +8 ) |BIT (8 )),/* uart2-1_rx */ +RK_MUXROUTE_SAME (1 ,RK_PB2 ,1 ,0x50 ,BIT (16 +11 )),/* uart1-0_rx */ +RK_MUXROUTE_SAME (3 ,RK_PB5 ,1 ,0x50 ,BIT (16 +11 ) |BIT (11 )),/* uart1-1_rx */ };static struct rockchip_mux_route_data rk3288_mux_route_data[] = { - { -/* edphdmi_cecinoutt1 */ - .bank_num =7 , - .pin =16 , - .func =2 , - .route_offset =0x264 , - .route_val =BIT (16 +12 ) |BIT (12 ), - }, { -/* edphdmi_cecinout */ - .bank_num =7 , - .pin =23 , - .func =4 , - .route_offset =0x264 , - .route_val =BIT (16 +12 ), - }, +RK_MUXROUTE_SAME (7 ,RK_PC0 ,2 ,0x264 ,BIT (16 +12 ) |BIT (12 )),/* edphdmi_cecinoutt1 */ +RK_MUXROUTE_SAME (7 ,RK_PC7 ,4 ,0x264 ,BIT (16 +12 )),/* edphdmi_cecinout */ };static struct rockchip_mux_route_data rk3308_mux_route_data[] = { - { -/* rtc_clk */ - .bank_num =0 , - .pin =19 , - .func =1 , - .route_offset =0x314 , - .route_val =BIT (16 +0 ) |BIT (0 ), - }, { -/* uart2_rxm0 */ - .bank_num =1 , - .pin =22 , - .func =2 , - .route_offset =0x314 , - .route_val =BIT (16 +2 ) |BIT (16 +3 ), - }, { -/* uart2_rxm1 */ - .bank_num =4 , - .pin =26 , - .func =2 , - .route_offset =0x314 , - .route_val =BIT (16 +2 ) |BIT (16 +3 ) |BIT (2 ), - }, { -/* i2c3_sdam0 */ - .bank_num =0 , - .pin =15 , - .func =2 , - .route_offset =0x608 , - .route_val =BIT (16 +8 ) |BIT (16 +9 ), - }, { -/* i2c3_sdam1 */ - .bank_num =3 , - .pin =12 , - .func =2 , - .route_offset =0x608 , - .route_val =BIT (16 +8 ) |BIT (16 +9 ) |BIT (8 ), - }, { -/* i2c3_sdam2 */ - .bank_num =2 , - .pin =0 , - .func =3 , - .route_offset =0x608 , - .route_val =BIT (16 +8 ) |BIT (16 +9 ) |BIT (9 ), - }, { -/* i2s-8ch-1-sclktxm0 */ - .bank_num =1 , - .pin =3 , - .func =2 , - .route_offset =0x308 , - .route_val =BIT (16 +3 ), - }, { -/* i2s-8ch-1-sclkrxm0 */ - .bank_num =1 , - .pin =4 , - .func =2 , - .route_offset =0x308 , - .route_val =BIT (16 +3 ), - }, { -/* i2s-8ch-1-sclktxm1 */ - .bank_num =1 , - .pin =13 , - .func =2 , - .route_offset =0x308 , - .route_val =BIT (16 +3 ) |BIT (3 ), - }, { -/* i2s-8ch-1-sclkrxm1 */ - .bank_num =1 , - .pin =14 , - .func =2 , - .route_offset =0x308 , - .route_val =BIT (16 +3 ) |BIT (3 ), - }, { -/* pdm-clkm0 */ - .bank_num =1 , - .pin =4 , - .func =3 , - .route_offset =0x308 , - .route_val =BIT (16 +12 ) |BIT (16 +13 ), - }, { -/* pdm-clkm1 */ - .bank_num =1 , - .pin =14 , - .func =4 , - .route_offset =0x308 , - .route_val =BIT (16 +12 ) |BIT (16 +13 ) |BIT (12 ), - }, { -/* pdm-clkm2 */ - .bank_num =2 , - .pin =6 , - .func =2 , - .route_offset =0x308 , - .route_val =BIT (16 +12 ) |BIT (16 +13 ) |BIT (13 ), - }, { -/* pdm-clkm-m2 */ - .bank_num =2 , - .pin =4 , - .func =3 , - .route_offset =0x600 , - .route_val =BIT (16 +2 ) |BIT (2 ), - }, { -/* spi1_miso */ - .bank_num =3 , - .pin =10 , - .func =3 , - .route_offset =0x314 , - .route_val =BIT (16 +9 ), - }, { -/* spi1_miso_m1 */ - .bank_num =2 , - .pin =4 , - .func =2 , - .route_offset =0x314 , - .route_val =BIT (16 +9 ) |BIT (9 ), - }, { -/* owire_m0 */ - .bank_num =0 , - .pin =11 , - .func =3 , - .route_offset =0x314 , - .route_val =BIT (16 +10 ) |BIT (16 +11 ), - }, { -/* owire_m1 */ - .bank_num =1 , - .pin =22 , - .func =7 , - .route_offset =0x314 , - .route_val =BIT (16 +10 ) |BIT (16 +11 ) |BIT (10 ), - }, { -/* owire_m2 */ - .bank_num =2 , - .pin =2 , - .func =5 , - .route_offset =0x314 , - .route_val =BIT (16 +10 ) |BIT (16 +11 ) |BIT (11 ), - }, { -/* can_rxd_m0 */ - .bank_num =0 , - .pin =11 , - .func =2 , - .route_offset =0x314 , - .route_val =BIT (16 +12 ) |BIT (16 +13 ), - }, { -/* can_rxd_m1 */ - .bank_num =1 , - .pin =22 , - .func =5 , - .route_offset =0x314 , - .route_val =BIT (16 +12 ) |BIT (16 +13 ) |BIT (12 ), - }, { -/* can_rxd_m2 */ - .bank_num =2 , - .pin =2 , - .func =4 , - .route_offset =0x314 , - .route_val =BIT (16 +12 ) |BIT (16 +13 ) |BIT (13 ), - }, { -/* mac_rxd0_m0 */ - .bank_num =1 , - .pin =20 , - .func =3 , - .route_offset =0x314 , - .route_val =BIT (16 +14 ), - }, { -/* mac_rxd0_m1 */ - .bank_num =4 , - .pin =2 , - .func =2 , - .route_offset =0x314 , - .route_val =BIT (16 +14 ) |BIT (14 ), - }, { -/* uart3_rx */ - .bank_num =3 , - .pin =12 , - .func =4 , - .route_offset =0x314 , - .route_val =BIT (16 +15 ), - }, { -/* uart3_rx_m1 */ - .bank_num =0 , - .pin =17 , - .func =3 , - .route_offset =0x314 , - .route_val =BIT (16 +15 ) |BIT (15 ), - }, +RK_MUXROUTE_SAME (0 ,RK_PC3 ,1 ,0x314 ,BIT (16 +0 ) |BIT (0 )),/* rtc_clk */ +RK_MUXROUTE_SAME (1 ,RK_PC6 ,2 ,0x314 ,BIT (16 +2 ) |BIT (16 +3 )),/* uart2_rxm0 */ +RK_MUXROUTE_SAME (4 ,RK_PD2 ,2 ,0x314 ,BIT (16 +2 ) |BIT (16 +3 ) |BIT (2 )),/* uart2_rxm1 */ +RK_MUXROUTE_SAME (0 ,RK_PB7 ,2 ,0x608 ,BIT (16 +8 ) |BIT (16 +9 )),/* i2c3_sdam0 */ +RK_MUXROUTE_SAME (3 ,RK_PB4 ,2 ,0x608 ,BIT (16 +8 ) |BIT (16 +9 ) |BIT (8 )),/* i2c3_sdam1 */ +RK_MUXROUTE_SAME (2 ,RK_PA0 ,3 ,0x608 ,BIT (16 +8 ) |BIT (16 +9 ) |BIT (9 )),/* i2c3_sdam2 */ +RK_MUXROUTE_SAME (1 ,RK_PA3 ,2 ,0x308 ,BIT (16 +3 )),/* i2s-8ch-1-sclktxm0 */ +RK_MUXROUTE_SAME (1 ,RK_PA4 ,2 ,0x308 ,BIT (16 +3 )),/* i2s-8ch-1-sclkrxm0 */ +RK_MUXROUTE_SAME (1 ,RK_PB5 ,2 ,0x308 ,BIT (16 +3 ) |BIT (3 )),/* i2s-8ch-1-sclktxm1 */ +RK_MUXROUTE_SAME (1 ,RK_PB6 ,2 ,0x308 ,BIT (16 +3 ) |BIT (3 )),/* i2s-8ch-1-sclkrxm1 */ +RK_MUXROUTE_SAME (1 ,RK_PA4 ,3 ,0x308 ,BIT (16 +12 ) |BIT (16 +13 )),/* pdm-clkm0 */ +RK_MUXROUTE_SAME (1 ,RK_PB6 ,4 ,0x308 ,BIT (16 +12 ) |BIT (16 +13 ) |BIT (12 )),/* pdm-clkm1 */ +RK_MUXROUTE_SAME (2 ,RK_PA6 ,2 ,0x308 ,BIT (16 +12 ) |BIT (16 +13 ) |BIT (13 )),/* pdm-clkm2 */ +RK_MUXROUTE_SAME (2 ,RK_PA4 ,3 ,0x600 ,BIT (16 +2 ) |BIT (2 )),/* pdm-clkm-m2 */ +RK_MUXROUTE_SAME (3 ,RK_PB2 ,3 ,0x314 ,BIT (16 +9 )),/* spi1_miso */ +RK_MUXROUTE_SAME (2 ,RK_PA4 ,2 ,0x314 ,BIT (16 +9 ) |BIT (9 )),/* spi1_miso_m1 */ +RK_MUXROUTE_SAME (0 ,RK_PB3 ,3 ,0x314 ,BIT (16 +10 ) |BIT (16 +11 )),/* owire_m0 */ +RK_MUXROUTE_SAME (1 ,RK_PC6 ,7 ,0x314 ,BIT (16 +10 ) |BIT (16 +11 ) |BIT (10 )),/* owire_m1 */ +RK_MUXROUTE_SAME (2 ,RK_PA2 ,5 ,0x314 ,BIT (16 +10 ) |BIT (16 +11 ) |BIT (11 )),/* owire_m2 */ +RK_MUXROUTE_SAME (0 ,RK_PB3 ,2 ,0x314 ,BIT (16 +12 ) |BIT (16 +13 )),/* can_rxd_m0 */ +RK_MUXROUTE_SAME (1 ,RK_PC6 ,5 ,0x314 ,BIT (16 +12 ) |BIT (16 +13 ) |BIT (12 )),/* can_rxd_m1 */ +RK_MUXROUTE_SAME (2 ,RK_PA2 ,4 ,0x314 ,BIT (16 +12 ) |BIT (16 +13 ) |BIT (13 )),/* can_rxd_m2 */ +RK_MUXROUTE_SAME (1 ,RK_PC4 ,3 ,0x314 ,BIT (16 +14 )),/* mac_rxd0_m0 */ +RK_MUXROUTE_SAME (4 ,RK_PA2 ,2 ,0x314 ,BIT (16 +14 ) |BIT (14 )),/* mac_rxd0_m1 */ +RK_MUXROUTE_SAME (3 ,RK_PB4 ,4 ,0x314 ,BIT (16 +15 )),/* uart3_rx */ +RK_MUXROUTE_SAME (0 ,RK_PC1 ,3 ,0x314 ,BIT (16 +15 ) |BIT (15 )),/* uart3_rx_m1 */ };static struct rockchip_mux_route_data rk3328_mux_route_data[] = { - { -/* uart2dbg_rxm0 */ - .bank_num =1 , - .pin =1 , - .func =2 , - .route_offset =0x50 , - .route_val =BIT (16 ) |BIT (16 +1 ), - }, { -/* uart2dbg_rxm1 */ - .bank_num =2 , - .pin =1 , - .func =1 , - .route_offset =0x50 , - .route_val =BIT (16 ) |BIT (16 +1 ) |BIT (0 ), - }, { -/* gmac-m1_rxd0 */ - .bank_num =1 , - .pin =11 , - .func =2 , - .route_offset =0x50 , - .route_val =BIT (16 +2 ) |BIT (2 ), - }, { -/* gmac-m1-optimized_rxd3 */ - .bank_num =1 , - .pin =14 , - .func =2 , - .route_offset =0x50 , - .route_val =BIT (16 +10 ) |BIT (10 ), - }, { -/* pdm_sdi0m0 */ - .bank_num =2 , - .pin =19 , - .func =2 , - .route_offset =0x50 , - .route_val =BIT (16 +3 ), - }, { -/* pdm_sdi0m1 */ - .bank_num =1 , - .pin =23 , - .func =3 , - .route_offset =0x50 , - .route_val =BIT (16 +3 ) |BIT (3 ), - }, { -/* spi_rxdm2 */ - .bank_num =3 , - .pin =2 , - .func =4 , - .route_offset =0x50 , - .route_val =BIT (16 +4 ) |BIT (16 +5 ) |BIT (5 ), - }, { -/* i2s2_sdim0 */ - .bank_num =1 , - .pin =24 , - .func =1 , - .route_offset =0x50 , - .route_val =BIT (16 +6 ), - }, { -/* i2s2_sdim1 */ - .bank_num =3 , - .pin =2 , - .func =6 , - .route_offset =0x50 , - .route_val =BIT (16 +6 ) |BIT (6 ), - }, { -/* card_iom1 */ - .bank_num =2 , - .pin =22 , - .func =3 , - .route_offset =0x50 , - .route_val =BIT (16 +7 ) |BIT (7 ), - }, { -/* tsp_d5m1 */ - .bank_num =2 , - .pin =16 , - .func =3 , - .route_offset =0x50 , - .route_val =BIT (16 +8 ) |BIT (8 ), - }, { -/* cif_data5m1 */ - .bank_num =2 , - .pin =16 , - .func =4 , - .route_offset =0x50 , - .route_val =BIT (16 +9 ) |BIT (9 ), - }, +RK_MUXROUTE_SAME (1 ,RK_PA1 ,2 ,0x50 ,BIT (16 ) |BIT (16 +1 )),/* uart2dbg_rxm0 */ +RK_MUXROUTE_SAME (2 ,RK_PA1 ,1 ,0x50 ,BIT (16 ) |BIT (16 +1 ) |BIT (0 )),/* uart2dbg_rxm1 */ +RK_MUXROUTE_SAME (1 ,RK_PB3 ,2 ,0x50 ,BIT (16 +2 ) |BIT (2 )),/* gmac-m1_rxd0 */ +RK_MUXROUTE_SAME (1 ,RK_PB6 ,2 ,0x50 ,BIT (16 +10 ) |BIT (10 )),/* gmac-m1-optimized_rxd3 */ +RK_MUXROUTE_SAME (2 ,RK_PC3 ,2 ,0x50 ,BIT (16 +3 )),/* pdm_sdi0m0 */ +RK_MUXROUTE_SAME (1 ,RK_PC7 ,3 ,0x50 ,BIT (16 +3 ) |BIT (3 )),/* pdm_sdi0m1 */ +RK_MUXROUTE_SAME (3 ,RK_PA2 ,4 ,0x50 ,BIT (16 +4 ) |BIT (16 +5 ) |BIT (5 )),/* spi_rxdm2 */ +RK_MUXROUTE_SAME (1 ,RK_PD0 ,1 ,0x50 ,BIT (16 +6 )),/* i2s2_sdim0 */ +RK_MUXROUTE_SAME (3 ,RK_PA2 ,6 ,0x50 ,BIT (16 +6 ) |BIT (6 )),/* i2s2_sdim1 */ +RK_MUXROUTE_SAME (2 ,RK_PC6 ,3 ,0x50 ,BIT (16 +7 ) |BIT (7 )),/* card_iom1 */ +RK_MUXROUTE_SAME (2 ,RK_PC0 ,3 ,0x50 ,BIT (16 +8 ) |BIT (8 )),/* tsp_d5m1 */ +RK_MUXROUTE_SAME (2 ,RK_PC0 ,4 ,0x50 ,BIT (16 +9 ) |BIT (9 )),/* cif_data5m1 */ };static struct rockchip_mux_route_data rk3399_mux_route_data[] = { - { -/* uart2dbga_rx */ - .bank_num =4 , - .pin =8 , - .func =2 , - .route_offset =0xe21c , - .route_val =BIT (16 +10 ) |BIT (16 +11 ), - }, { -/* uart2dbgb_rx */ - .bank_num =4 , - .pin =16 , - .func =2 , - .route_offset =0xe21c , - .route_val =BIT (16 +10 ) |BIT (16 +11 ) |BIT (10 ), - }, { -/* uart2dbgc_rx */ - .bank_num =4 , - .pin =19 , - .func =1 , - .route_offset =0xe21c , - .route_val =BIT (16 +10 ) |BIT (16 +11 ) |BIT (11 ), - }, { -/* pcie_clkreqn */ - .bank_num =2 , - .pin =26 , - .func =2 , - .route_offset =0xe21c , - .route_val =BIT (16 +14 ), - }, { -/* pcie_clkreqnb */ - .bank_num =4 , - .pin =24 , - .func =1 , - .route_offset =0xe21c , - .route_val =BIT (16 +14 ) |BIT (14 ), - }, +RK_MUXROUTE_SAME (4 ,RK_PB0 ,2 ,0xe21c ,BIT (16 +10 ) |BIT (16 +11 )),/* uart2dbga_rx */ +RK_MUXROUTE_SAME (4 ,RK_PC0 ,2 ,0xe21c ,BIT (16 +10 ) |BIT (16 +11 ) |BIT (10 )),/* uart2dbgb_rx */ +RK_MUXROUTE_SAME (4 ,RK_PC3 ,1 ,0xe21c ,BIT (16 +10 ) |BIT (16 +11 ) |BIT (11 )),/* uart2dbgc_rx */ +RK_MUXROUTE_SAME (2 ,RK_PD2 ,2 ,0xe21c ,BIT (16 +14 )),/* pcie_clkreqn */ +RK_MUXROUTE_SAME (4 ,RK_PD0 ,1 ,0xe21c ,BIT (16 +14 ) |BIT (14 )),/* pcie_clkreqnb */ };static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 162/529 pinctrl: rockchip: Fix refcount leak in rockchip_pinctrl_parse_groups
In reply to Greg Kroah-HartmanFrom: Miaoqian Lin <[email protected]>
[ Upstream commit c818ae563bf99457f02e8170aabd6b174f629f65 ]
of_find_node_by_phandle() returns a node pointer with refcount incremented, We should use of_node_put() on it when not needed anymore.
Add missing of_node_put() to avoid refcount leak.
--- drivers/pinctrl/pinctrl-rockchip.c | 1 + 1 file changed, 1 insertion(+)
drivers/pinctrl/pinctrl-rockchip.c +1 -0
@@ -2650,6 +2650,7 @@ static int rockchip_pinctrl_parse_groups(struct device_node *np, np_config =of_find_node_by_phandle (be32_to_cpup (phandle)); ret =pinconf_generic_parse_dt_config (np_config,NULL , &grp->data[j].configs, &grp->data[j].nconfigs); +of_node_put (np_config);if (ret)return ret; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 163/529 drm/vc4: hvs: Set AXI panic modes
In reply to Greg Kroah-HartmanFrom: Dave Stevenson <[email protected]>
[ Upstream commit df993fced230daa8452892406f3180c93ebf7e7b ]
The HVS can change AXI request mode based on how full the COB FIFOs are.
Until now the vc4 driver has been relying on the firmware to have set these to sensible values.
With HVS channel 2 now being used for live video, change the panic mode for all channels to be explicitly set by the driver, and the same for all channels.
--- drivers/gpu/drm/vc4/vc4_hvs.c | 11 +++++++++++ drivers/gpu/drm/vc4/vc4_regs.h | 6 ++++++ 2 files changed, 17 insertions(+)
drivers/gpu/drm/vc4/vc4_hvs.c +11 -0
@@ -677,6 +677,17 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)SCALER_DISPCTRL_DSPEISLUR (2 ) | SCALER_DISPCTRL_SCLEIRQ); +/* Set AXI panic mode. +* VC4 panics when < 2 lines in FIFO. +* VC5 panics when less than 1 line in the FIFO. +*/ + dispctrl &= ~(SCALER_DISPCTRL_PANIC0_MASK | +SCALER_DISPCTRL_PANIC1_MASK | +SCALER_DISPCTRL_PANIC2_MASK ); + dispctrl |=VC4_SET_FIELD (2 ,SCALER_DISPCTRL_PANIC0 ); + dispctrl |=VC4_SET_FIELD (2 ,SCALER_DISPCTRL_PANIC1 ); + dispctrl |=VC4_SET_FIELD (2 ,SCALER_DISPCTRL_PANIC2 ); +HVS_WRITE (SCALER_DISPCTRL , dispctrl); ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
drivers/gpu/drm/vc4/vc4_regs.h +6 -0
@@ -220,6 +220,12 @@#define SCALER_DISPCTRL 0x00000000/* Global register for clock gating the HVS */ # define SCALER_DISPCTRL_ENABLE BIT(31) +# define SCALER_DISPCTRL_PANIC0_MASK VC4_MASK(25, 24) +# define SCALER_DISPCTRL_PANIC0_SHIFT 24 +# define SCALER_DISPCTRL_PANIC1_MASK VC4_MASK(27, 26) +# define SCALER_DISPCTRL_PANIC1_SHIFT 26 +# define SCALER_DISPCTRL_PANIC2_MASK VC4_MASK(29, 28) +# define SCALER_DISPCTRL_PANIC2_SHIFT 28# define SCALER_DISPCTRL_DSP3_MUX_MASK VC4_MASK(19, 18)# define SCALER_DISPCTRL_DSP3_MUX_SHIFT 18
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 164/529 drm/vc4: hvs: Fix colour order for xRGB1555 on HVS5
In reply to Greg Kroah-HartmanFrom: Dave Stevenson <[email protected]>
[ Upstream commit 902973dc1a049c0d7bf0c222b8f2b3876f01b4a2 ]
Same as the xRGB8888 formats, HVS5 has managed to swap the colour channels for the xRGB1555 formats as well. Add the relevant config for pixel_order_hvs5.
--- drivers/gpu/drm/vc4/vc4_plane.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/gpu/drm/vc4/vc4_plane.c +2 -0
@@ -72,11 +72,13 @@ static const struct hvs_format { .drm = DRM_FORMAT_ARGB1555, .hvs = HVS_PIXEL_FORMAT_RGBA5551, .pixel_order = HVS_PIXEL_ORDER_ABGR, + .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB, }, { .drm = DRM_FORMAT_XRGB1555, .hvs = HVS_PIXEL_FORMAT_RGBA5551, .pixel_order = HVS_PIXEL_ORDER_ABGR, + .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB, }, { .drm = DRM_FORMAT_RGB888,
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 165/529 drm/vc4: hdmi: Correct interlaced timings again
In reply to Greg Kroah-HartmanFrom: Dave Stevenson <[email protected]>
[ Upstream commit 771d6539f27bd55f43d8a95d53a7eeaaffa2681c ]
The back porch timings were correct, only the sync offset was wrong. Correct timing is now reported for 1080i and 576i, but the h offset is incorrect for 480i for non-obvious reasons.
--- drivers/gpu/drm/vc4/vc4_hdmi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/gpu/drm/vc4/vc4_hdmi.c +3 -2
@@ -567,11 +567,12 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, VC4_SET_FIELD(mode->crtc_vdisplay, VC5_HDMI_VERTA_VAL));u32 vertb = (VC4_SET_FIELD (mode->htotal >> (2 - pixel_rep),VC5_HDMI_VERTB_VSPO ) | -VC4_SET_FIELD (mode->crtc_vtotal - mode->crtc_vsync_end, +VC4_SET_FIELD (mode->crtc_vtotal - mode->crtc_vsync_end + + interlaced,VC4_HDMI_VERTB_VBP ));u32 vertb_even = (VC4_SET_FIELD (0 ,VC5_HDMI_VERTB_VSPO ) |VC4_SET_FIELD (mode->crtc_vtotal - - mode->crtc_vsync_end - interlaced, + mode->crtc_vsync_end,VC4_HDMI_VERTB_VBP ));HDMI_WRITE (HDMI_VEC_INTERFACE_XBAR ,0x354021 );
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 166/529 ASoC: fsl_sai: initialize is_dsp_mode flag
In reply to Greg Kroah-HartmanFrom: Shengjiu Wang <[email protected]>
[ Upstream commit a23924b7dd7b748fff8e305e1daf590fed2af21b ]
Initialize is_dsp_mode flag in the beginning of function fsl_sai_set_dai_fmt_tr().
When the DAIFMT is DAIFMT_DSP_B the first time, is_dsp_mode is true, then the second time DAIFMT is DAIFMT_I2S, is_dsp_mode still true, which is a wrong state. So need to initialize is_dsp_mode flag every time.
--- sound/soc/fsl/fsl_sai.c | 1 + 1 file changed, 1 insertion(+)
sound/soc/fsl/fsl_sai.c +1 -0
@@ -230,6 +230,7 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,if (!sai->is_lsb_first) val_cr4 |=FSL_SAI_CR4_MF ; + sai->is_dsp_mode = false;/* DAI mode */ switch (fmt &SND_SOC_DAIFMT_FORMAT_MASK ) {case SND_SOC_DAIFMT_I2S :
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 167/529 drm/msm/adreno: Fix null ptr access in adreno_gpu_cleanup()
In reply to Greg Kroah-HartmanFrom: Akhil P Oommen <[email protected]>
[ Upstream commit dbeedbcb268d055d8895aceca427f897e12c2b50 ]
Fix the below kernel panic due to null pointer access:
[ 18.504431] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000048 [ 18.513464] Mem abort info: [ 18.516346] ESR = 0x0000000096000005 [ 18.520204] EC = 0x25: DABT (current EL), IL = 32 bits [ 18.525706] SET = 0, FnV = 0 [ 18.528878] EA = 0, S1PTW = 0 [ 18.532117] FSC = 0x05: level 1 translation fault [ 18.537138] Data abort info: [ 18.540110] ISV = 0, ISS = 0x00000005 [ 18.544060] CM = 0, WnR = 0 [ 18.547109] user pgtable: 4k pages, 39-bit VAs, pgdp=0000000112826000 [ 18.553738] [0000000000000048] pgd=0000000000000000, p4d=0000000000000000, pud=0000000000000000 [ 18.562690] Internal error: Oops: 0000000096000005 [#1] PREEMPT SMP **Snip** [ 18.696758] Call trace: [ 18.699278] adreno_gpu_cleanup+0x30/0x88 [ 18.703396] a6xx_destroy+0xc0/0x130 [ 18.707066] a6xx_gpu_init+0x308/0x424 [ 18.710921] adreno_bind+0x178/0x288 [ 18.714590] component_bind_all+0xe0/0x214 [ 18.718797] msm_drm_bind+0x1d4/0x614 [ 18.722566] try_to_bring_up_aggregate_device+0x16c/0x1b8 [ 18.728105] __component_add+0xa0/0x158 [ 18.732048] component_add+0x20/0x2c [ 18.735719] adreno_probe+0x40/0xc0 [ 18.739300] platform_probe+0xb4/0xd4 [ 18.743068] really_probe+0xfc/0x284 [ 18.746738] __driver_probe_device+0xc0/0xec [ 18.751129] driver_probe_device+0x48/0x110 [ 18.755421] __device_attach_driver+0xa8/0xd0 [ 18.759900] bus_for_each_drv+0x90/0xdc [ 18.763843] __device_attach+0xfc/0x174 [ 18.767786] device_initial_probe+0x20/0x2c [ 18.772090] bus_probe_device+0x40/0xa0 [ 18.776032] deferred_probe_work_func+0x94/0xd0 [ 18.780686] process_one_work+0x190/0x3d0 [ 18.784805] worker_thread+0x280/0x3d4 [ 18.788659] kthread+0x104/0x1c0 [ 18.791981] ret_from_fork+0x10/0x20 [ 18.795654] Code: f9400408 aa0003f3 aa1f03f4 91142015 (f9402516) [ 18.801913] ---[ end trace 0000000000000000 ]--- [ 18.809039] Kernel panic - not syncing: Oops: Fatal exception
Patchwork: https://patchwork.freedesktop.org/patch/515605/
--- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/msm/adreno/adreno_gpu.c +2 -2
@@ -954,13 +954,13 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,void adreno_gpu_cleanup (struct adreno_gpu *adreno_gpu) {struct msm_gpu *gpu = &adreno_gpu->base; -struct msm_drm_private *priv = gpu->dev->dev_private; +struct msm_drm_private *priv = gpu->dev ? gpu->dev->dev_private :NULL ;unsigned int i;for (i =0 ; i <ARRAY_SIZE (adreno_gpu->info->fw); i++)release_firmware (adreno_gpu->fw[i]); -if (pm_runtime_enabled (&priv->gpu_pdev->dev)) +if (priv &&pm_runtime_enabled (&priv->gpu_pdev->dev))pm_runtime_disable (&priv->gpu_pdev->dev);msm_gpu_cleanup (&adreno_gpu->base);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 168/529 ALSA: hda/ca0132: minor fix for allocation size
In reply to Greg Kroah-HartmanFrom: Alexey V. Vissarionov <[email protected]>
[ Upstream commit 3ee0fe7fa39b14d1cea455b7041f2df933bd97d2 ]
Although the "dma_chan" pointer occupies more or equal space compared to "*dma_chan", the allocation size should use the size of variable itself.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- sound/pci/hda/patch_ca0132.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/pci/hda/patch_ca0132.c +1 -1
@@ -2331,7 +2331,7 @@ static int dspio_set_uint_param_no_source(struct hda_codec *codec, int mod_id,static int dspio_alloc_dma_chan (struct hda_codec *codec,unsigned int *dma_chan) {int status =0 ; -unsigned int size =sizeof (dma_chan); +unsigned int size =sizeof (*dma_chan);codec_dbg (codec," dspio_alloc_dma_chan() -- begin\n" ); status = dspio_scp(codec, MASTERCONTROL, 0x20,
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 169/529 drm/msm/dpu: Disallow unallocated resources to be returned
In reply to Greg Kroah-HartmanFrom: Marijn Suijten <[email protected]>
[ Upstream commit abc40122d9a69f56c04efb5a7485795f5ac799d1 ]
In the event that the topology requests resources that have not been created by the system (because they are typically not represented in dpu_mdss_cfg ^1), the resource(s) in global_state (in this case DSC blocks, until their allocation/assignment is being sanity-checked in "drm/msm/dpu: Reject topologies for which no DSC blocks are available") remain NULL but will still be returned out of dpu_rm_get_assigned_resources, where the caller expects to get an array containing num_blks valid pointers (but instead gets these NULLs).
To prevent this from happening, where null-pointer dereferences typically result in a hard-to-debug platform lockup, num_blks shouldn't increase past NULL blocks and will print an error and break instead. After all, max_blks represents the static size of the maximum number of blocks whereas the actual amount varies per platform.
^1: which can happen after a git rebase ended up moving additions to _dpu_cfg to a different struct which has the same patch context.
Patchwork: https://patchwork.freedesktop.org/patch/517636/
--- drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +5 -0
@@ -633,6 +633,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm, blks_size, enc_id);break ; } +if (!hw_blks[i]) { +DPU_ERROR ("Allocated resource %d unavailable to assign to enc %d\n" , + type, enc_id); +break ; + } blks[num_blks++] = hw_blks[i]; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 170/529 drm/bridge: lt9611: fix sleep mode setup
In reply to Greg Kroah-HartmanFrom: Dmitry Baryshkov <[email protected]>
[ Upstream commit ae2d329f104b75a0a78dcaded29fe6283289cdf9 ]
On atomic_post_disable the bridge goes to the low power state. However the code disables too much of the chip, so the HPD event is not being detected and delivered to the host. Reduce the power saving in order to get the HPD event.
--- drivers/gpu/drm/bridge/lontium-lt9611.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/gpu/drm/bridge/lontium-lt9611.c +2 -3
@@ -446,12 +446,11 @@ static void lt9611_sleep_setup(struct lt9611 *lt9611) { 0x8023, 0x01 }, { 0x8157, 0x03 }, /* set addr pin as output */ { 0x8149, 0x0b }, - { 0x8151, 0x30 }, /* disable IRQ */ + { 0x8102, 0x48 }, /* MIPI Rx power down */ { 0x8123, 0x80 }, { 0x8130, 0x00 }, - { 0x8100, 0x01 }, /* bandgap power down */ - { 0x8101, 0x00 }, /* system clk power down */ + { 0x8011, 0x0a }, }; regmap_multi_reg_write(lt9611->regmap,
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 171/529 drm/bridge: lt9611: fix HPD reenablement
In reply to Greg Kroah-HartmanFrom: Dmitry Baryshkov <[email protected]>
[ Upstream commit a7790f6bd38f3642b60ae3504a2c749135b89451 ]
The driver will reset the bridge in the atomic_pre_enable(). However this will also drop the HPD interrupt state. Instead of resetting the bridge, properly wake it up. This fixes the HPD interrupt delivery after the disable/enable cycle.
--- drivers/gpu/drm/bridge/lontium-lt9611.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
drivers/gpu/drm/bridge/lontium-lt9611.c +8 -2
@@ -880,12 +880,18 @@ static enum drm_mode_status lt9611_bridge_mode_valid(struct drm_bridge *bridge,static void lt9611_bridge_pre_enable (struct drm_bridge *bridge) {struct lt9611 *lt9611 =bridge_to_lt9611 (bridge); +static const struct reg_sequence reg_cfg[] = { + {0x8102 ,0x12 }, + {0x8123 ,0x40 }, + {0x8130 ,0xea }, + {0x8011 ,0xfa }, + };if (!lt9611->sleep)return ; -lt9611_reset (lt9611); -regmap_write (lt9611->regmap,0x80ee ,0x01 ); +regmap_multi_reg_write (lt9611->regmap, + reg_cfg,ARRAY_SIZE (reg_cfg)); lt9611->sleep = false; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 172/529 drm/bridge: lt9611: fix polarity programming
In reply to Greg Kroah-HartmanFrom: Dmitry Baryshkov <[email protected]>
[ Upstream commit 0b157efa384ea417304b1da284ee2f603c607fc3 ]
Fix programming of hsync and vsync polarities
--- drivers/gpu/drm/bridge/lontium-lt9611.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
drivers/gpu/drm/bridge/lontium-lt9611.c +12 -5
@@ -205,7 +205,6 @@ static void lt9611_pcr_setup(struct lt9611 *lt9611, const struct drm_display_mod/* stage 2 */ { 0x834a, 0x40 }, - { 0x831d, 0x10 },/* MK limit */ { 0x832d, 0x38 },
@@ -220,11 +219,19 @@ static void lt9611_pcr_setup(struct lt9611 *lt9611, const struct drm_display_mod { 0x8325, 0x00 }, { 0x832a, 0x01 }, { 0x834a, 0x10 }, - { 0x831d, 0x10 }, - { 0x8326, 0x37 }, }; +u8 pol =0x10 ; -regmap_multi_reg_write (lt9611->regmap, reg_cfg,ARRAY_SIZE (reg_cfg)); +if (mode->flags &DRM_MODE_FLAG_NHSYNC ) + pol |=0x2 ; +if (mode->flags &DRM_MODE_FLAG_NVSYNC ) + pol |=0x1 ; +regmap_write (lt9611->regmap,0x831d , pol); + +if (mode->hdisplay ==3840 ) +regmap_multi_reg_write (lt9611->regmap, reg_cfg2,ARRAY_SIZE (reg_cfg2)); +else +regmap_multi_reg_write (lt9611->regmap, reg_cfg,ARRAY_SIZE (reg_cfg));switch (mode->hdisplay) {case 640 :
@@ -234,7 +241,7 @@ static void lt9611_pcr_setup(struct lt9611 *lt9611, const struct drm_display_modregmap_write (lt9611->regmap,0x8326 ,0x37 );break ;case 3840 : -regmap_multi_reg_write (lt9611->regmap, reg_cfg2,ARRAY_SIZE (reg_cfg2)); +regmap_write (lt9611->regmap,0x8326 ,0x37 );break ; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 173/529 drm/bridge: lt9611: fix programming of video modes
In reply to Greg Kroah-HartmanFrom: Dmitry Baryshkov <[email protected]>
[ Upstream commit ad188aa47edaa033a270e1a3efae43836ff47569 ]
Program the upper part of the hfront_porch into the proper register.
--- drivers/gpu/drm/bridge/lontium-lt9611.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/bridge/lontium-lt9611.c +2 -1
@@ -185,7 +185,8 @@ static void lt9611_mipi_video_setup(struct lt9611 *lt9611,regmap_write (lt9611->regmap,0x8319 , (u8)(hfront_porch %256 )); -regmap_write (lt9611->regmap,0x831a , (u8)(hsync_porch /256 )); +regmap_write (lt9611->regmap,0x831a , (u8)(hsync_porch /256 ) | + ((hfront_porch /256 ) <<4 ));regmap_write (lt9611->regmap,0x831b , (u8)(hsync_porch %256 )); }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 174/529 drm/bridge: lt9611: fix clock calculation
In reply to Greg Kroah-HartmanFrom: Dmitry Baryshkov <[email protected]>
[ Upstream commit 2576eb26494eb0509dd9ceb0cd27771a7a5e3674 ]
Instead of having several fixed values for the pcr register, calculate it before programming. This allows the bridge to support most of the display modes.
--- drivers/gpu/drm/bridge/lontium-lt9611.c | 32 +++++++++++-------------- 1 file changed, 14 insertions(+), 18 deletions(-)
drivers/gpu/drm/bridge/lontium-lt9611.c +14 -18
@@ -190,8 +190,9 @@ static void lt9611_mipi_video_setup(struct lt9611 *lt9611,regmap_write (lt9611->regmap,0x831b , (u8)(hsync_porch %256 )); } -static void lt9611_pcr_setup (struct lt9611 *lt9611,const struct drm_display_mode *mode) +static void lt9611_pcr_setup (struct lt9611 *lt9611,const struct drm_display_mode *mode,unsigned int postdiv) { +unsigned int pcr_m = mode->clock *5 * postdiv /27000 ;const struct reg_sequence reg_cfg[] = { {0x830b ,0x01 }, {0x830c ,0x10 },
@@ -234,24 +235,14 @@ static void lt9611_pcr_setup(struct lt9611 *lt9611, const struct drm_display_modelse regmap_multi_reg_write (lt9611->regmap, reg_cfg,ARRAY_SIZE (reg_cfg)); -switch (mode->hdisplay) { -case 640 : -regmap_write (lt9611->regmap,0x8326 ,0x14 ); -break ; -case 1920 : -regmap_write (lt9611->regmap,0x8326 ,0x37 ); -break ; -case 3840 : -regmap_write (lt9611->regmap,0x8326 ,0x37 ); -break ; - } +regmap_write (lt9611->regmap,0x8326 , pcr_m);/* pcr rst */ regmap_write (lt9611->regmap,0x8011 ,0x5a );regmap_write (lt9611->regmap,0x8011 ,0xfa ); } -static int lt9611_pll_setup (struct lt9611 *lt9611,const struct drm_display_mode *mode) +static int lt9611_pll_setup (struct lt9611 *lt9611,const struct drm_display_mode *mode,unsigned int *postdiv) {unsigned int pclk = mode->clock; const struct reg_sequence reg_cfg[] = {
@@ -269,12 +260,16 @@ static int lt9611_pll_setup(struct lt9611 *lt9611, const struct drm_display_moderegmap_multi_reg_write (lt9611->regmap, reg_cfg,ARRAY_SIZE (reg_cfg)); -if (pclk >150000 ) +if (pclk >150000 ) {regmap_write (lt9611->regmap,0x812d ,0x88 ); -else if (pclk >70000 ) + *postdiv =1 ; + }else if (pclk >70000 ) {regmap_write (lt9611->regmap,0x812d ,0x99 ); -else + *postdiv =2 ; + }else {regmap_write (lt9611->regmap,0x812d ,0xaa ); + *postdiv =4 ; + }/* * first divide pclk by 2 first
@@ -917,14 +912,15 @@ static void lt9611_bridge_mode_set(struct drm_bridge *bridge, {struct lt9611 *lt9611 =bridge_to_lt9611 (bridge);struct hdmi_avi_infoframe avi_frame; +unsigned int postdiv;int ret;lt9611_bridge_pre_enable (bridge);lt9611_mipi_input_digital (lt9611, mode); -lt9611_pll_setup (lt9611, mode); +lt9611_pll_setup (lt9611, mode, &postdiv);lt9611_mipi_video_setup (lt9611, mode); -lt9611_pcr_setup (lt9611, mode); +lt9611_pcr_setup (lt9611, mode, postdiv); ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame, <9611->connector,
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 175/529 drm/bridge: lt9611: pass a pointer to the of node
In reply to Greg Kroah-HartmanFrom: Dmitry Baryshkov <[email protected]>
[ Upstream commit b0a7f8736789935f62d6df32d441cdf05a5c05d2 ]
Pass a pointer to the OF node while registering lt9611 MIPI device.
--- drivers/gpu/drm/bridge/lontium-lt9611.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/bridge/lontium-lt9611.c +1 -1
@@ -759,7 +759,7 @@ static const struct drm_connector_funcs lt9611_bridge_connector_funcs = {static struct mipi_dsi_device *lt9611_attach_dsi (struct lt9611 *lt9611,struct device_node *dsi_node) { -const struct mipi_dsi_device_info info = {"lt9611" ,0 ,NULL }; +const struct mipi_dsi_device_info info = {"lt9611" ,0 , lt9611->dev->of_node};struct mipi_dsi_device *dsi;struct mipi_dsi_host *host;int ret;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 176/529 drm/mipi-dsi: Fix byte order of 16-bit DCS set/get brightness
In reply to Greg Kroah-HartmanFrom: Daniel Mentz <[email protected]>
[ Upstream commit c9d27c6be518b4ef2966d9564654ef99292ea1b3 ]
The MIPI DCS specification demands that brightness values are sent in big endian byte order. It also states that one parameter (i.e. one byte) shall be sent/received for 8 bit wide values, and two parameters shall be used for values that are between 9 and 16 bits wide.
Add new functions to properly handle 16-bit brightness in big endian, since the two 8- and 16-bit cases are distinct from each other.
[richard: use separate functions instead of switch/case] [richard: split into 16-bit component]
--- drivers/gpu/drm/drm_mipi_dsi.c | 52 ++++++++++++++++++++++++++++++++++ include/drm/drm_mipi_dsi.h | 4 +++ 2 files changed, 56 insertions(+)
drivers/gpu/drm/drm_mipi_dsi.c +52 -0
@@ -1143,6 +1143,58 @@ int mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device *dsi, }EXPORT_SYMBOL (mipi_dsi_dcs_get_display_brightness); +/** +* mipi_dsi_dcs_set_display_brightness_large() - sets the 16-bit brightness value +* of the display +* @dsi: DSI peripheral device +* @brightness: brightness value +* +* Return: 0 on success or a negative error code on failure. +*/ +int mipi_dsi_dcs_set_display_brightness_large (struct mipi_dsi_device *dsi, +u16 brightness) +{ +u8 payload[2 ] = { brightness >>8 , brightness &0xff }; +ssize_t err; + + err =mipi_dsi_dcs_write (dsi,MIPI_DCS_SET_DISPLAY_BRIGHTNESS , + payload,sizeof (payload)); +if (err <0 ) +return err; + +return 0 ; +} +EXPORT_SYMBOL (mipi_dsi_dcs_set_display_brightness_large); + +/** +* mipi_dsi_dcs_get_display_brightness_large() - gets the current 16-bit +* brightness value of the display +* @dsi: DSI peripheral device +* @brightness: brightness value +* +* Return: 0 on success or a negative error code on failure. +*/ +int mipi_dsi_dcs_get_display_brightness_large (struct mipi_dsi_device *dsi, +u16 *brightness) +{ +u8 brightness_be[2 ]; +ssize_t err; + + err =mipi_dsi_dcs_read (dsi,MIPI_DCS_GET_DISPLAY_BRIGHTNESS , + brightness_be,sizeof (brightness_be)); +if (err <=0 ) { +if (err ==0 ) + err = -ENODATA ; + +return err; + } + + *brightness = (brightness_be[0 ] <<8 ) | brightness_be[1 ]; + +return 0 ; +} +EXPORT_SYMBOL (mipi_dsi_dcs_get_display_brightness_large); +static int mipi_dsi_drv_probe (struct device *dev) {struct mipi_dsi_driver *drv =to_mipi_dsi_driver (dev->driver);
include/drm/drm_mipi_dsi.h +4 -0
@@ -283,6 +283,10 @@ int mipi_dsi_dcs_set_display_brightness(struct mipi_dsi_device *dsi, u16 brightness);int mipi_dsi_dcs_get_display_brightness (struct mipi_dsi_device *dsi,u16 *brightness); +int mipi_dsi_dcs_set_display_brightness_large (struct mipi_dsi_device *dsi, +u16 brightness); +int mipi_dsi_dcs_get_display_brightness_large (struct mipi_dsi_device *dsi, +u16 *brightness);/** * struct mipi_dsi_driver - DSI driver
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 177/529 drm/msm: use strscpy instead of strncpy
In reply to Greg Kroah-HartmanFrom: Dmitry Baryshkov <[email protected]>
[ Upstream commit d7fd8634f48d76aa799ed57beb7d87dab91bde80 ]
Using strncpy can result in non-NULL-terminated destination string. Use strscpy instead. This fixes following warning:
drivers/gpu/drm/msm/msm_fence.c: In function ‘msm_fence_context_alloc’:drivers/gpu/drm/msm/msm_fence.c:25:9: warning: ‘strncpy’ specified bound 32 equals destination size [-Wstringop-truncation]
25 | strncpy(fctx->name, name, sizeof(fctx->name));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Patchwork: https://patchwork.freedesktop.org/patch/518787/
--- drivers/gpu/drm/msm/msm_fence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/msm/msm_fence.c +1 -1
@@ -20,7 +20,7 @@ msm_fence_context_alloc(struct drm_device *dev, const char *name)return ERR_PTR (-ENOMEM ); fctx->dev = dev; -strncpy (fctx->name, name,sizeof (fctx->name)); +strscpy (fctx->name, name,sizeof (fctx->name)); fctx->context =dma_fence_context_alloc (1 );init_waitqueue_head (&fctx->event);spin_lock_init (&fctx->spinlock);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 178/529 drm/msm/dpu: Add check for cstate
In reply to Greg Kroah-HartmanFrom: Jiasheng Jiang <[email protected]>
[ Upstream commit c96988b7d99327bb08bd9efd29a203b22cd88ace ]
As kzalloc may fail and return NULL pointer,
it should be better to check cstate
in order to avoid the NULL pointer dereference
in __drm_atomic_helper_crtc_reset.
Patchwork: https://patchwork.freedesktop.org/patch/514163/
--- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +4 -1
@@ -682,7 +682,10 @@ static void dpu_crtc_reset(struct drm_crtc *crtc)if (crtc->state)dpu_crtc_destroy_state (crtc, crtc->state); -__drm_atomic_helper_crtc_reset (crtc, &cstate->base); +if (cstate) +__drm_atomic_helper_crtc_reset (crtc, &cstate->base); +else +__drm_atomic_helper_crtc_reset (crtc,NULL ); }/**
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 179/529 drm/msm/dpu: Add check for pstates
In reply to Greg Kroah-HartmanFrom: Jiasheng Jiang <[email protected]>
[ Upstream commit 93340e10b9c5fc86730d149636e0aa8b47bb5a34 ]
As kzalloc may fail and return NULL pointer,
it should be better to check pstates
in order to avoid the NULL pointer dereference.
Patchwork: https://patchwork.freedesktop.org/patch/514160/
--- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +2 -0
@@ -834,6 +834,8 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,struct drm_rect crtc_rect = {0 }; pstates =kzalloc (sizeof (*pstates) *DPU_STAGE_MAX *4 ,GFP_KERNEL ); +if (!pstates) +return -ENOMEM ;if (!state->enable || !state->active) { DPU_DEBUG("crtc%d -> enable %d, active %d, skip atomic_check\n",
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 180/529 drm/msm/mdp5: Add check for kzalloc
In reply to Greg Kroah-HartmanFrom: Jiasheng Jiang <[email protected]>
[ Upstream commit 13fcfcb2a9a4787fe4e49841d728f6f2e9fa6911 ]
As kzalloc may fail and return NULL pointer,
it should be better to check the return value
in order to avoid the NULL pointer dereference.
Patchwork: https://patchwork.freedesktop.org/patch/514154/
--- drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c +4 -1
@@ -1124,7 +1124,10 @@ static void mdp5_crtc_reset(struct drm_crtc *crtc)if (crtc->state)mdp5_crtc_destroy_state (crtc, crtc->state); -__drm_atomic_helper_crtc_reset (crtc, &mdp5_cstate->base); +if (mdp5_cstate) +__drm_atomic_helper_crtc_reset (crtc, &mdp5_cstate->base); +else +__drm_atomic_helper_crtc_reset (crtc,NULL ); }static const struct drm_crtc_funcs mdp5_crtc_no_lm_cursor_funcs = {
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 181/529 pinctrl: bcm2835: Remove of_node_put() in bcm2835_of_gpio_ranges_fallback()
In reply to Greg Kroah-HartmanFrom: Andy Shevchenko <[email protected]>
[ Upstream commit 2d578dd27871372f7159dd3206149ec616700d87 ]
Remove wrong of_node_put() in bcm2835_of_gpio_ranges_fallback(), there is no counterpart of_node_get() for it.
--- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 2 -- 1 file changed, 2 deletions(-)
drivers/pinctrl/bcm/pinctrl-bcm2835.c +0 -2
@@ -356,8 +356,6 @@ static int bcm2835_of_gpio_ranges_fallback(struct gpio_chip *gc, {struct pinctrl_dev *pctldev =of_pinctrl_get (np); -of_node_put (np); -if (!pctldev)return 0 ;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 182/529 pinctrl: mediatek: Initialize variable pullen and pullup to zero
In reply to Greg Kroah-HartmanFrom: Guodong Liu <[email protected]>
[ Upstream commit a298c70a10c604a6b3df5a0aa56597b705ba0f6b ]
Coverity spotted that pullen and pullup is not initialized to zero in mtk_pctrl_show_one_pin. The uninitialized variable pullen is used in assignment statement "rsel = pullen;" in mtk_pctrl_show_one_pin, and Uninitialized variable pullup is used when calling scnprintf. Fix this coverity by initializing pullen and pullup as zero.
--- drivers/pinctrl/mediatek/pinctrl-paris.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pinctrl/mediatek/pinctrl-paris.c +1 -1
@@ -574,7 +574,7 @@ static int mtk_hw_get_value_wrap(struct mtk_pinctrl *hw, unsigned int gpio, intssize_t mtk_pctrl_show_one_pin (struct mtk_pinctrl *hw,unsigned int gpio,char *buf,unsigned int bufLen) { -int pinmux, pullup, pullen, len =0 , r1 =-1 , r0 =-1 ; +int pinmux, pullup =0 , pullen =0 , len =0 , r1 =-1 , r0 =-1 ;const struct mtk_pin_desc *desc;if (gpio >= hw->soc->npins)
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 183/529 pinctrl: mediatek: Initialize variable *buf to zero
In reply to Greg Kroah-HartmanFrom: Guodong Liu <[email protected]>
[ Upstream commit 2e34f82ba214134ecf590fbe0cdbd87401645a8a ]
Coverity spotted that *buf is not initialized to zero in mtk_pctrl_dbg_show. Using uninitialized variable *buf as argument to %s when calling seq_printf. Fix this coverity by initializing *buf as zero.
--- drivers/pinctrl/mediatek/pinctrl-paris.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pinctrl/mediatek/pinctrl-paris.c +1 -1
@@ -637,7 +637,7 @@ static void mtk_pctrl_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, unsigned int gpio) {struct mtk_pinctrl *hw =pinctrl_dev_get_drvdata (pctldev); -char buf[PIN_DBG_BUF_SZ ]; +char buf[PIN_DBG_BUF_SZ ] = {0 }; (void )mtk_pctrl_show_one_pin (hw, gpio, buf,PIN_DBG_BUF_SZ );
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 184/529 gpu: host1x: Dont skip assigning syncpoints to channels
In reply to Greg Kroah-HartmanFrom: Mikko Perttunen <[email protected]>
[ Upstream commit eb258cc1fd458e584082be987dbc6ec42668c05e ]
The code to write the syncpoint channel assignment register incorrectly skips the write if hypervisor registers are not available.
The register, however, is within the guest aperture so remove the check and assign syncpoints properly even on virtualized systems.
--- drivers/gpu/host1x/hw/syncpt_hw.c | 3 --- 1 file changed, 3 deletions(-)
drivers/gpu/host1x/hw/syncpt_hw.c +0 -3
@@ -106,9 +106,6 @@ static void syncpt_assign_to_channel(struct host1x_syncpt *sp,#if HOST1X_HW >=6 struct host1x *host = sp->host; -if (!host->hv_regs) -return ; -host1x_sync_writel (host,HOST1X_SYNC_SYNCPT_CH_APP_CH (ch ? ch->id :0xff ),HOST1X_SYNC_SYNCPT_CH_APP (sp->id));
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 185/529 drm/mediatek: dsi: Reduce the time of dsi from LP11 to sending cmd
In reply to Greg Kroah-HartmanFrom: Xinlei Lee <[email protected]>
[ Upstream commit 91aeaed2c1147e3b1157dc084d23f190856a6c23 ]
According to Figure 16 Turnaround Procedure on page 36 in [1], you can see the status of LP-00 -> LP10 -> LP11. This state can correspond to the state of DSI from LP00 -> LP11 in mtk_dsi_lane_ready function in mtk_dsi.c.
LP-00 -> LP10 -> LP11 takes about 2*TLPX time (refer to [1] page 51 to see that TLPX is 50ns)
The delay at the end of the mtk_dsi_lane_ready function should be greater than the 2*TLPX specified by the DSI spec, and less than the time specified by the DSI_RX (generally 6ms to 40ms), to avoid problems caused by the RX specification
[1]:mipi_D-PHY_specification_v1-1
--- drivers/gpu/drm/mediatek/mtk_dsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/mediatek/mtk_dsi.c +1 -1
@@ -704,7 +704,7 @@ static void mtk_dsi_lane_ready(struct mtk_dsi *dsi)mtk_dsi_clk_ulp_mode_leave (dsi);mtk_dsi_lane0_ulp_mode_leave (dsi);mtk_dsi_clk_hs_mode (dsi,0 ); -msleep (20 ); +usleep_range (1000 ,3000 );/* The reaction time after pulling up the mipi signal for dsi_rx */ } }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 186/529 drm/mediatek: Use NULL instead of 0 for NULL pointer
In reply to Greg Kroah-HartmanFrom: Miles Chen <[email protected]>
[ Upstream commit 4744cde06f57dd6fbaac468663b1fe2f653eaa16 ]
Use NULL for NULL pointer to fix the following sparse warning:drivers/gpu/drm/mediatek/mtk_drm_gem.c:265:27: sparse: warning: Using plain integer as NULL pointer
--- drivers/gpu/drm/mediatek/mtk_drm_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/mediatek/mtk_drm_gem.c +1 -1
@@ -266,6 +266,6 @@ void mtk_drm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)return ;vunmap (vaddr); - mtk_gem->kvaddr =0 ; + mtk_gem->kvaddr =NULL ;kfree (mtk_gem->pages); }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 187/529 drm/mediatek: Drop unbalanced obj unref
In reply to Greg Kroah-HartmanFrom: Rob Clark <[email protected]>
[ Upstream commit 4deef811828e87e26a978d5d6433b261d4713849 ]
In the error path, mtk_drm_gem_object_mmap() is dropping an obj reference that it doesn't own.
--- drivers/gpu/drm/mediatek/mtk_drm_gem.c | 2 -- 1 file changed, 2 deletions(-)
drivers/gpu/drm/mediatek/mtk_drm_gem.c +0 -2
@@ -142,8 +142,6 @@ static int mtk_drm_gem_object_mmap(struct drm_gem_object *obj, ret =dma_mmap_attrs (priv->dma_dev, vma, mtk_gem->cookie, mtk_gem->dma_addr, obj->size, mtk_gem->dma_attrs); -if (ret) -drm_gem_vm_close (vma);return ret; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 188/529 drm/mediatek: mtk_drm_crtc: Add checks for devm_kcalloc
In reply to Greg Kroah-HartmanFrom: ruanjinjie <[email protected]>
[ Upstream commit 5bf1e3bd7da625ccf9a22c8cb7d65271e6e47f4c ]
As the devm_kcalloc may return NULL, the return value needs to be checked to avoid NULL poineter dereference.
--- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/gpu/drm/mediatek/mtk_drm_crtc.c +2 -0
@@ -803,6 +803,8 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, mtk_crtc->planes =devm_kcalloc (dev, num_comp_planes,sizeof (struct drm_plane ),GFP_KERNEL ); +if (!mtk_crtc->planes) +return -ENOMEM ;for (i =0 ; i < mtk_crtc->ddp_comp_nr; i++) { ret = mtk_drm_crtc_init_comp_planes(drm_dev, mtk_crtc, i,
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 189/529 drm/mediatek: Clean dangling pointer on bind error path
In reply to Greg Kroah-HartmanFrom: Nícolas F. R. A. Prado <[email protected]>
[ Upstream commit 36aa8c61af55675ed967900fbe5deb32d776f051 ]
mtk_drm_bind() can fail, in which case drm_dev_put() is called, destroying the drm_device object. However a pointer to it was still being held in the private object, and that pointer would be passed along to DRM in mtk_drm_sys_prepare() if a suspend were triggered at that point, resulting in a panic. Clean the pointer when destroying the object in the error path to prevent this from happening.
--- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/mediatek/mtk_drm_drv.c +1 -0
@@ -378,6 +378,7 @@ static int mtk_drm_bind(struct device *dev) err_deinit:mtk_drm_kms_deinit (drm); err_free: + private->drm =NULL ;drm_dev_put (drm);return ret; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 190/529 ASoC: soc-compress.c: fixup private_data on snd_soc_new_compress()
In reply to Greg Kroah-HartmanFrom: Kuninori Morimoto <[email protected]>
[ Upstream commit ffe4c0f0bfaa571a676a0e946d4a6a0607f94294 ]
commit d3268a40d4b19f ("ASoC: soc-compress.c: fix NULL dereference") enables DPCM capture, but it should independent from playback. This patch fixup it.
--- sound/soc/soc-compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/soc-compress.c +1 -1
@@ -822,7 +822,7 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) rtd->fe_compr =1 ;if (rtd->dai_link->dpcm_playback) be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK ].substream->private_data = rtd; -else if (rtd->dai_link->dpcm_capture) +if (rtd->dai_link->dpcm_capture) be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE ].substream->private_data = rtd;memcpy (compr->ops, &soc_compr_dyn_ops,sizeof (soc_compr_dyn_ops)); }else {
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 191/529 gpio: vf610: connect GPIO label to dev name
In reply to Greg Kroah-HartmanFrom: Haibo Chen <[email protected]>
[ Upstream commit 6f8ecb7f85f441eb7d78ba2a4df45ee8a821934e ]
Current GPIO label is fixed, so can't distinguish different GPIO controllers through labels. Use dev name instead.
--- drivers/gpio/gpio-vf610.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpio/gpio-vf610.c +1 -1
@@ -304,7 +304,7 @@ static int vf610_gpio_probe(struct platform_device *pdev) gc = &port->gc; gc->of_node = np; gc->parent = dev; - gc->label ="vf610-gpio" ; + gc->label =dev_name (dev); gc->ngpio =VF610_GPIO_PER_PORT ; gc->base =of_alias_get_id (np,"gpio" ) *VF610_GPIO_PER_PORT ;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 192/529 spi: dw_bt1: fix MUX_MMIO dependencies
In reply to Greg Kroah-HartmanFrom: Arnd Bergmann <[email protected]>
[ Upstream commit d4bde04318c0d33705e9a77d4c7df72f262011e0 ]
Selecting a symbol with additional dependencies requires adding the same dependency here:
WARNING: unmet direct dependencies detected for MUX_MMIO
Depends on [n]: MULTIPLEXER [=y] && OF [=n]
Selected by [y]:
- SPI_DW_BT1 [=y] && SPI [=y] && SPI_MASTER [=y] && SPI_DESIGNWARE [=y] && (MIPS_BAIKAL_T1 || COMPILE_TEST [=y])
Drop the 'select' here to avoid the problem. Anyone using the dw-bt1 SPI driver should make sure they include the mux driver as well now.
--- drivers/spi/Kconfig | 1 - 1 file changed, 1 deletion(-)
drivers/spi/Kconfig +0 -1
@@ -256,7 +256,6 @@ config SPI_DW_BT1 tristate "Baikal-T1 SPI driver for DW SPI core" depends on MIPS_BAIKAL_T1 || COMPILE_TEST select MULTIPLEXER - select MUX_MMIO help Baikal-T1 SoC is equipped with three DW APB SSI-based MMIO SPI controllers. Two of them are pretty much normal: with IRQ, DMA,
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 193/529 ASoC: mchp-spdifrx: fix controls which rely on rsr register
In reply to Greg Kroah-HartmanFrom: Claudiu Beznea <[email protected]>
[ Upstream commit fa09fa60385abbf99342494b280da8b4aebbc0e9 ]
The SPDIFRX block is clocked by 2 clocks: peripheral and generic clocks. Peripheral clock feeds user interface (registers) and generic clock feeds the receiver.
To enable the receiver the generic clock needs to be enabled and also the ENABLE bit of MCHP_SPDIFRX_MR register need to be set.
The signal control exported by mchp-spdifrx driver reports wrong status when the receiver is disabled. This can happen when requesting the signal and the capture was not previously started. To solve this the receiver needs to be enabled (by enabling generic clock and setting ENABLE bit of MR register) before reading the signal status.
As with this fix there are 2 paths now that need to control the generic clock and ENABLE bit of SPDIFRX_MR register (one path though controls, one path though configuration) a mutex has been introduced. We can't rely on subsystem locking as the controls are protected by
struct snd_card::controls_rwsem semaphore and configuration is protected by a different lock (embedded in snd_pcm_stream_lock_irq()).
The introduction of mutex is also extended to other controls which rely on SPDIFRX_RSR.ULOCK bit as it has been discovered experimentally that having both clocks enabled but not the receiver (through ENABLE bit of SPDIFRX.MR) leads to inconsistent values of SPDIFRX_RSR.ULOCK. Thus on some controls we rely on software state (dev->trigger_enabled protected by mutex) to retrieve proper values.
--- sound/soc/atmel/mchp-spdifrx.c | 192 ++++++++++++++++++++++++--------- 1 file changed, 142 insertions(+), 50 deletions(-)
sound/soc/atmel/mchp-spdifrx.c +142 -50
@@ -233,11 +233,13 @@ struct mchp_spdifrx_dev {struct mchp_spdifrx_mixer_control control;spinlock_t blockend_lock;/* protect access to blockend_refcount */ int blockend_refcount; +struct mutex mlock;struct device *dev;struct regmap *regmap;struct clk *pclk;struct clk *gclk;unsigned int fmt; +unsigned int trigger_enabled; unsigned int gclk_enabled:1; };
@@ -353,47 +355,40 @@ static int mchp_spdifrx_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) {struct mchp_spdifrx_dev *dev =snd_soc_dai_get_drvdata (dai); -u32 mr; -int running; -int ret; - -regmap_read (dev->regmap,SPDIFRX_MR , &mr); - running = !!(mr &SPDIFRX_MR_RXEN_ENABLE ); +int ret =0 ;switch (cmd) {case SNDRV_PCM_TRIGGER_START :case SNDRV_PCM_TRIGGER_RESUME :case SNDRV_PCM_TRIGGER_PAUSE_RELEASE : -if (!running) { - mr &= ~SPDIFRX_MR_RXEN_MASK ; - mr |=SPDIFRX_MR_RXEN_ENABLE ; -/* enable overrun interrupts */ -regmap_write (dev->regmap,SPDIFRX_IER , -SPDIFRX_IR_OVERRUN ); - } +mutex_lock (&dev->mlock); +/* Enable overrun interrupts */ +regmap_write (dev->regmap,SPDIFRX_IER ,SPDIFRX_IR_OVERRUN ); + +/* Enable receiver. */ +regmap_update_bits (dev->regmap,SPDIFRX_MR ,SPDIFRX_MR_RXEN_MASK , +SPDIFRX_MR_RXEN_ENABLE ); + dev->trigger_enabled = true; +mutex_unlock (&dev->mlock);break ;case SNDRV_PCM_TRIGGER_STOP :case SNDRV_PCM_TRIGGER_SUSPEND :case SNDRV_PCM_TRIGGER_PAUSE_PUSH : -if (running) { - mr &= ~SPDIFRX_MR_RXEN_MASK ; - mr |=SPDIFRX_MR_RXEN_DISABLE ; -/* disable overrun interrupts */ -regmap_write (dev->regmap,SPDIFRX_IDR , -SPDIFRX_IR_OVERRUN ); - } +mutex_lock (&dev->mlock); +/* Disable overrun interrupts */ +regmap_write (dev->regmap,SPDIFRX_IDR ,SPDIFRX_IR_OVERRUN ); + +/* Disable receiver. */ +regmap_update_bits (dev->regmap,SPDIFRX_MR ,SPDIFRX_MR_RXEN_MASK , +SPDIFRX_MR_RXEN_DISABLE ); + dev->trigger_enabled = false; +mutex_unlock (&dev->mlock);break ;default : -return -EINVAL ; + ret = -EINVAL ; } - ret =regmap_write (dev->regmap,SPDIFRX_MR , mr); -if (ret) { -dev_err (dev->dev,"unable to enable/disable RX: %d\n" , ret); -return ret; - } - -return 0 ; +return ret; } static int mchp_spdifrx_hw_params(struct snd_pcm_substream *substream,
@@ -413,13 +408,6 @@ static int mchp_spdifrx_hw_params(struct snd_pcm_substream *substream,return -EINVAL ; } -regmap_read (dev->regmap,SPDIFRX_MR , &mr); - -if (mr &SPDIFRX_MR_RXEN_ENABLE ) { -dev_err (dev->dev,"PCM already running\n" ); -return -EBUSY ; - } -if (params_channels (params) !=SPDIFRX_CHANNELS ) {dev_err (dev->dev,"unsupported number of channels: %d\n" ,params_channels (params));
@@ -445,6 +433,13 @@ static int mchp_spdifrx_hw_params(struct snd_pcm_substream *substream,return -EINVAL ; } +mutex_lock (&dev->mlock); +if (dev->trigger_enabled) { +dev_err (dev->dev,"PCM already running\n" ); + ret = -EBUSY ; + goto unlock; + } +if (dev->gclk_enabled) {clk_disable_unprepare (dev->gclk); dev->gclk_enabled =0 ;
@@ -455,19 +450,24 @@ static int mchp_spdifrx_hw_params(struct snd_pcm_substream *substream,dev_err (dev->dev,"unable to set gclk min rate: rate %u * ratio %u + 1\n" ,params_rate (params),SPDIFRX_GCLK_RATIO_MIN ); -return ret; + goto unlock; } ret =clk_prepare_enable (dev->gclk);if (ret) {dev_err (dev->dev,"unable to enable gclk: %d\n" , ret); -return ret; + goto unlock; } dev->gclk_enabled =1 ;dev_dbg (dev->dev,"GCLK range min set to %d\n" ,params_rate (params) *SPDIFRX_GCLK_RATIO_MIN +1 ); -return regmap_write (dev->regmap,SPDIFRX_MR , mr); + ret =regmap_write (dev->regmap,SPDIFRX_MR , mr); + +unlock: +mutex_unlock (&dev->mlock); + +return ret; } static int mchp_spdifrx_hw_free(struct snd_pcm_substream *substream,
@@ -475,10 +475,12 @@ static int mchp_spdifrx_hw_free(struct snd_pcm_substream *substream, {struct mchp_spdifrx_dev *dev =snd_soc_dai_get_drvdata (dai); +mutex_lock (&dev->mlock);if (dev->gclk_enabled) {clk_disable_unprepare (dev->gclk); dev->gclk_enabled =0 ; } +mutex_unlock (&dev->mlock);return 0 ; }
@@ -627,10 +629,24 @@ static int mchp_spdifrx_ulock_get(struct snd_kcontrol *kcontrol,u32 val;bool ulock_old = ctrl->ulock; -regmap_read (dev->regmap,SPDIFRX_RSR , &val); - ctrl->ulock = !(val &SPDIFRX_RSR_ULOCK ); +mutex_lock (&dev->mlock); + +/* +* The RSR.ULOCK has wrong value if both pclk and gclk are enabled +* and the receiver is disabled. Thus we take into account the +* dev->trigger_enabled here to return a real status. +*/ +if (dev->trigger_enabled) { +regmap_read (dev->regmap,SPDIFRX_RSR , &val); + ctrl->ulock = !(val &SPDIFRX_RSR_ULOCK ); + }else { + ctrl->ulock =0 ; + } + uvalue->value.integer.value[0 ] = ctrl->ulock; +mutex_unlock (&dev->mlock); +return ulock_old != ctrl->ulock; }
@@ -643,8 +659,22 @@ static int mchp_spdifrx_badf_get(struct snd_kcontrol *kcontrol,u32 val;bool badf_old = ctrl->badf; -regmap_read (dev->regmap,SPDIFRX_RSR , &val); - ctrl->badf = !!(val &SPDIFRX_RSR_BADF ); +mutex_lock (&dev->mlock); + +/* +* The RSR.ULOCK has wrong value if both pclk and gclk are enabled +* and the receiver is disabled. Thus we take into account the +* dev->trigger_enabled here to return a real status. +*/ +if (dev->trigger_enabled) { +regmap_read (dev->regmap,SPDIFRX_RSR , &val); + ctrl->badf = !!(val &SPDIFRX_RSR_BADF ); + }else { + ctrl->badf =0 ; + } + +mutex_unlock (&dev->mlock); + uvalue->value.integer.value[0 ] = ctrl->badf;return badf_old != ctrl->badf;
@@ -656,11 +686,48 @@ static int mchp_spdifrx_signal_get(struct snd_kcontrol *kcontrol,struct snd_soc_dai *dai =snd_kcontrol_chip (kcontrol);struct mchp_spdifrx_dev *dev =snd_soc_dai_get_drvdata (dai);struct mchp_spdifrx_mixer_control *ctrl = &dev->control; -u32 val; +u32 val = ~0U , loops =10 ; +int ret;bool signal_old = ctrl->signal; -regmap_read (dev->regmap,SPDIFRX_RSR , &val); - ctrl->signal = !(val &SPDIFRX_RSR_NOSIGNAL ); +mutex_lock (&dev->mlock); + +/* +* To get the signal we need to have receiver enabled. This +* could be enabled also from trigger() function thus we need to +* take care of not disabling the receiver when it runs. +*/ +if (!dev->trigger_enabled) { + ret =clk_prepare_enable (dev->gclk); +if (ret) + goto unlock; + +regmap_update_bits (dev->regmap,SPDIFRX_MR ,SPDIFRX_MR_RXEN_MASK , +SPDIFRX_MR_RXEN_ENABLE ); + +/* Wait for RSR.ULOCK bit. */ +while (--loops) { +regmap_read (dev->regmap,SPDIFRX_RSR , &val); +if (!(val &SPDIFRX_RSR_ULOCK )) +break ; +usleep_range (100 ,150 ); + } + +regmap_update_bits (dev->regmap,SPDIFRX_MR ,SPDIFRX_MR_RXEN_MASK , +SPDIFRX_MR_RXEN_DISABLE ); + +clk_disable_unprepare (dev->gclk); + }else { +regmap_read (dev->regmap,SPDIFRX_RSR , &val); + } + +unlock: +mutex_unlock (&dev->mlock); + +if (!(val &SPDIFRX_RSR_ULOCK )) + ctrl->signal = !(val &SPDIFRX_RSR_NOSIGNAL ); +else + ctrl->signal =0 ; uvalue->value.integer.value[0 ] = ctrl->signal;return signal_old != ctrl->signal;
@@ -685,18 +752,32 @@ static int mchp_spdifrx_rate_get(struct snd_kcontrol *kcontrol,u32 val;int rate; -regmap_read (dev->regmap,SPDIFRX_RSR , &val); - -/* if the receiver is not locked, ISF data is invalid */ -if (val &SPDIFRX_RSR_ULOCK || !(val &SPDIFRX_RSR_IFS_MASK )) { +mutex_lock (&dev->mlock); + +/* +* The RSR.ULOCK has wrong value if both pclk and gclk are enabled +* and the receiver is disabled. Thus we take into account the +* dev->trigger_enabled here to return a real status. +*/ +if (dev->trigger_enabled) { +regmap_read (dev->regmap,SPDIFRX_RSR , &val); +/* If the receiver is not locked, ISF data is invalid. */ +if (val &SPDIFRX_RSR_ULOCK || !(val &SPDIFRX_RSR_IFS_MASK )) { + ucontrol->value.integer.value[0 ] =0 ; + goto unlock; + } + }else { +/* Reveicer is not locked, IFS data is invalid. */ ucontrol->value.integer.value[0 ] =0 ; -return 0 ; + goto unlock; } rate =clk_get_rate (dev->gclk); ucontrol->value.integer.value[0 ] = rate / (32 *SPDIFRX_RSR_IFS (val)); +unlock: +mutex_unlock (&dev->mlock);return 0 ; }
@@ -912,7 +993,18 @@ static int mchp_spdifrx_probe(struct platform_device *pdev) "failed to get the PMC generated clock: %d\n", err);return err; } + +/* +* Signal control need a valid rate on gclk. hw_params() configures +* it propertly but requesting signal before any hw_params() has been +* called lead to invalid value returned for signal. Thus, configure +* gclk at a valid rate, here, in initialization, to simplify the +* control path. +*/ +clk_set_min_rate (dev->gclk,48000 *SPDIFRX_GCLK_RATIO_MIN +1 ); +spin_lock_init (&dev->blockend_lock); +mutex_init (&dev->mlock); dev->dev = &pdev->dev; dev->regmap = regmap;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 194/529 ASoC: atmel: fix spelling mistakes
In reply to Greg Kroah-HartmanFrom: Gu Shengxian <[email protected]>
[ Upstream commit 55233b22502151e0b2d9cc599e1ddf1f5584c87a ]
Fix some spelling mistakes as follows:
regaedles ==> regardless
prezent ==> present
underrrun ==> underrun
controlls ==> controls
Stable-dep-of: a4c4161d6eae ("ASoC: mchp-spdifrx: fix return value in case completion times out")
--- sound/soc/atmel/mchp-spdifrx.c | 6 +++--- sound/soc/atmel/mchp-spdiftx.c | 2 +- sound/soc/atmel/tse850-pcm5142.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-)
sound/soc/atmel/mchp-spdifrx.c +3 -3
@@ -56,7 +56,7 @@/* Validity Bit Mode */ #define SPDIFRX_MR_VBMODE_MASK GENAMSK(1, 1)#define SPDIFRX_MR_VBMODE_ALWAYS_LOAD \ - (0 << 1)/* Load sample regardles of validity bit value */ + (0 << 1)/* Load sample regardless of validity bit value */ #define SPDIFRX_MR_VBMODE_DISCARD_IF_VB1 \ (1 << 1)/* Load sample only if validity bit is 0 */
@@ -523,7 +523,7 @@ static int mchp_spdifrx_cs_get(struct mchp_spdifrx_dev *dev,/* check for new data available */ ret =wait_for_completion_interruptible_timeout (&ch_stat->done,msecs_to_jiffies (100 )); -/* IP might not be started or valid stream might not be prezent */ +/* IP might not be started or valid stream might not be present */ if (ret <0 ) {dev_dbg (dev->dev,"channel status for channel %d timeout\n" , channel);
@@ -575,7 +575,7 @@ static int mchp_spdifrx_subcode_ch_get(struct mchp_spdifrx_dev *dev,mchp_spdifrx_isr_blockend_en (dev); ret =wait_for_completion_interruptible_timeout (&user_data->done,msecs_to_jiffies (100 )); -/* IP might not be started or valid stream might not be prezent */ +/* IP might not be started or valid stream might not be present */ if (ret <=0 ) {dev_dbg (dev->dev,"user data for channel %d timeout\n" , channel);
sound/soc/atmel/mchp-spdiftx.c +1 -1
@@ -80,7 +80,7 @@#define SPDIFTX_MR_VALID1 BIT(24)#define SPDIFTX_MR_VALID2 BIT(25) -/* Disable Null Frame on underrrun */ +/* Disable Null Frame on underrun */ #define SPDIFTX_MR_DNFR_MASK GENMASK(27, 27)#define SPDIFTX_MR_DNFR_INVALID (0 << 27)#define SPDIFTX_MR_DNFR_VALID (1 << 27)
sound/soc/atmel/tse850-pcm5142.c +1 -1
@@ -23,7 +23,7 @@// IN2 +---o--+------------+--o---+ OUT2 // loop2 relays // -// The 'loop1' gpio pin controlls two relays, which are either in loop +// The 'loop1' gpio pin controls two relays, which are either in loop // position, meaning that input and output are directly connected, or // they are in mixer position, meaning that the signal is passed through // the 'Sum' mixer. Similarly for 'loop2'.
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 195/529 ASoC: mchp-spdifrx: fix return value in case completion times out
In reply to Greg Kroah-HartmanFrom: Claudiu Beznea <[email protected]>
[ Upstream commit a4c4161d6eae3ef5f486d1638ef452d9bc1376b0 ]
wait_for_completion_interruptible_timeout() returns 0 in case of timeout. Check this into account when returning from function.
--- sound/soc/atmel/mchp-spdifrx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
sound/soc/atmel/mchp-spdifrx.c +3 -2
@@ -524,9 +524,10 @@ static int mchp_spdifrx_cs_get(struct mchp_spdifrx_dev *dev, ret =wait_for_completion_interruptible_timeout (&ch_stat->done,msecs_to_jiffies (100 ));/* IP might not be started or valid stream might not be present */ -if (ret <0 ) { +if (ret <=0 ) {dev_dbg (dev->dev,"channel status for channel %d timeout\n" , channel); +return ret ? : -ETIMEDOUT ; } memcpy(uvalue->value.iec958.status, ch_stat->data,
@@ -580,7 +581,7 @@ static int mchp_spdifrx_subcode_ch_get(struct mchp_spdifrx_dev *dev,dev_dbg (dev->dev,"user data for channel %d timeout\n" , channel);mchp_spdifrx_isr_blockend_dis (dev); -return ret; +return ret ? : -ETIMEDOUT ; }spin_lock_irqsave (&user_data->lock, flags);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 196/529 ASoC: mchp-spdifrx: fix controls that works with completion mechanism
In reply to Greg Kroah-HartmanFrom: Claudiu Beznea <[email protected]>
[ Upstream commit d3681df44e856aab523a6eb7ba15b5e41efcbb1c ]
Channel status get and channel subcode get controls relies on data returned by controls when certain IRQs are raised. To achieve that completions are used b/w controls and interrupt service routine. The concurrent accesses to these controls are protected by struct snd_card::controls_rwsem.
Issues identified:
- reinit_completion() may be called while waiting for completion which should be avoided
- in case of multiple threads waiting, the complete() call in interrupt will signal only one waiting thread per interrupt which may lead to timeout for the others
- in case of channel status get as the CSC interrupt is not refcounted ISR may disable interrupt for threads that were just enabled it.
To solve these the access to controls were protected by a mutex. Along with this there is no need for spinlock to protect the software cache reads/updates b/w controls and ISR as the update is happening only when requested from control, and only one reader can reach the control.
--- sound/soc/atmel/mchp-spdifrx.c | 143 ++++++++++++++++++--------------- 1 file changed, 77 insertions(+), 66 deletions(-)
sound/soc/atmel/mchp-spdifrx.c +77 -66
@@ -217,7 +217,6 @@ struct mchp_spdifrx_ch_stat {struct mchp_spdifrx_user_data {unsigned char data[SPDIFRX_UD_BITS /8 ];struct completion done; -spinlock_t lock;/* protect access to user data */ };struct mchp_spdifrx_mixer_control {
@@ -231,8 +230,6 @@ struct mchp_spdifrx_mixer_control {struct mchp_spdifrx_dev {struct snd_dmaengine_dai_dma_data capture;struct mchp_spdifrx_mixer_control control; -spinlock_t blockend_lock;/* protect access to blockend_refcount */ -int blockend_refcount;struct mutex mlock;struct device *dev;struct regmap *regmap;
@@ -277,37 +274,11 @@ static void mchp_spdifrx_channel_user_data_read(struct mchp_spdifrx_dev *dev, } } -/* called from non-atomic context only */ -static void mchp_spdifrx_isr_blockend_en (struct mchp_spdifrx_dev *dev) -{ -unsigned long flags; - -spin_lock_irqsave (&dev->blockend_lock, flags); - dev->blockend_refcount++; -/* don't enable BLOCKEND interrupt if it's already enabled */ -if (dev->blockend_refcount ==1 ) -regmap_write (dev->regmap,SPDIFRX_IER ,SPDIFRX_IR_BLOCKEND ); -spin_unlock_irqrestore (&dev->blockend_lock, flags); -} - -/* called from atomic/non-atomic context */ -static void mchp_spdifrx_isr_blockend_dis (struct mchp_spdifrx_dev *dev) -{ -unsigned long flags; - -spin_lock_irqsave (&dev->blockend_lock, flags); - dev->blockend_refcount--; -/* don't enable BLOCKEND interrupt if it's already enabled */ -if (dev->blockend_refcount ==0 ) -regmap_write (dev->regmap,SPDIFRX_IDR ,SPDIFRX_IR_BLOCKEND ); -spin_unlock_irqrestore (&dev->blockend_lock, flags); -} -static irqreturn_t mchp_spdif_interrupt (int irq,void *dev_id) {struct mchp_spdifrx_dev *dev = dev_id;struct mchp_spdifrx_mixer_control *ctrl = &dev->control; -u32 sr, imr, pending, idr =0 ; +u32 sr, imr, pending;irqreturn_t ret =IRQ_NONE ;int ch;
@@ -322,13 +293,10 @@ static irqreturn_t mchp_spdif_interrupt(int irq, void *dev_id)if (pending &SPDIFRX_IR_BLOCKEND ) {for (ch =0 ; ch <SPDIFRX_CHANNELS ; ch++) { -spin_lock (&ctrl->user_data[ch].lock);mchp_spdifrx_channel_user_data_read (dev, ch); -spin_unlock (&ctrl->user_data[ch].lock); -complete (&ctrl->user_data[ch].done); } -mchp_spdifrx_isr_blockend_dis (dev); +regmap_write (dev->regmap,SPDIFRX_IDR ,SPDIFRX_IR_BLOCKEND ); ret =IRQ_HANDLED ; }
@@ -336,7 +304,7 @@ static irqreturn_t mchp_spdif_interrupt(int irq, void *dev_id)if (pending &SPDIFRX_IR_CSC (ch)) {mchp_spdifrx_channel_status_read (dev, ch);complete (&ctrl->ch_stat[ch].done); - idr |=SPDIFRX_IR_CSC (ch); +regmap_write (dev->regmap,SPDIFRX_IDR ,SPDIFRX_IR_CSC (ch)); ret =IRQ_HANDLED ; } }
@@ -346,8 +314,6 @@ static irqreturn_t mchp_spdif_interrupt(int irq, void *dev_id) ret =IRQ_HANDLED ; } -regmap_write (dev->regmap,SPDIFRX_IDR , idr); -return ret; }
@@ -517,23 +483,51 @@ static int mchp_spdifrx_cs_get(struct mchp_spdifrx_dev *dev, {struct mchp_spdifrx_mixer_control *ctrl = &dev->control;struct mchp_spdifrx_ch_stat *ch_stat = &ctrl->ch_stat[channel]; -int ret; +int ret =0 ; + +mutex_lock (&dev->mlock); -regmap_write (dev->regmap,SPDIFRX_IER ,SPDIFRX_IR_CSC (channel)); -/* check for new data available */ - ret =wait_for_completion_interruptible_timeout (&ch_stat->done, -msecs_to_jiffies (100 )); -/* IP might not be started or valid stream might not be present */ -if (ret <=0 ) { -dev_dbg (dev->dev,"channel status for channel %d timeout\n" , - channel); -return ret ? : -ETIMEDOUT ; +/* +* We may reach this point with both clocks enabled but the receiver +* still disabled. To void waiting for completion and return with +* timeout check the dev->trigger_enabled. +* +* To retrieve data: +* - if the receiver is enabled CSC IRQ will update the data in software +* caches (ch_stat->data) +* - otherwise we just update it here the software caches with latest +* available information and return it; in this case we don't need +* spin locking as the IRQ is disabled and will not be raised from +* anywhere else. +*/ + +if (dev->trigger_enabled) { +reinit_completion (&ch_stat->done); +regmap_write (dev->regmap,SPDIFRX_IER ,SPDIFRX_IR_CSC (channel)); +/* Check for new data available */ + ret =wait_for_completion_interruptible_timeout (&ch_stat->done, +msecs_to_jiffies (100 )); +/* Valid stream might not be present */ +if (ret <=0 ) { +dev_dbg (dev->dev,"channel status for channel %d timeout\n" , + channel); +regmap_write (dev->regmap,SPDIFRX_IDR ,SPDIFRX_IR_CSC (channel)); + ret = ret ? : -ETIMEDOUT ; + goto unlock; + }else { + ret =0 ; + } + }else { +/* Update software cache with latest channel status. */ +mchp_spdifrx_channel_status_read (dev, channel); }memcpy (uvalue->value.iec958.status, ch_stat->data,sizeof (ch_stat->data)); -return 0 ; +unlock: +mutex_unlock (&dev->mlock); +return ret; } static int mchp_spdifrx_cs1_get(struct snd_kcontrol *kcontrol,
@@ -567,29 +561,49 @@ static int mchp_spdifrx_subcode_ch_get(struct mchp_spdifrx_dev *dev,int channel, struct snd_ctl_elem_value *uvalue) { - unsigned long flags; struct mchp_spdifrx_mixer_control *ctrl = &dev->control;struct mchp_spdifrx_user_data *user_data = &ctrl->user_data[channel]; -int ret; +int ret =0 ; + +mutex_lock (&dev->mlock); + +/* +* We may reach this point with both clocks enabled but the receiver +* still disabled. To void waiting for completion to just timeout we +* check here the dev->trigger_enabled flag. +* +* To retrieve data: +* - if the receiver is enabled we need to wait for blockend IRQ to read +* data to and update it for us in software caches +* - otherwise reading the SPDIFRX_CHUD() registers is enough. +*/ -reinit_completion (&user_data->done); -mchp_spdifrx_isr_blockend_en (dev); - ret =wait_for_completion_interruptible_timeout (&user_data->done, -msecs_to_jiffies (100 )); -/* IP might not be started or valid stream might not be present */ -if (ret <=0 ) { -dev_dbg (dev->dev,"user data for channel %d timeout\n" , - channel); -mchp_spdifrx_isr_blockend_dis (dev); -return ret ? : -ETIMEDOUT ; +if (dev->trigger_enabled) { +reinit_completion (&user_data->done); +regmap_write (dev->regmap,SPDIFRX_IER ,SPDIFRX_IR_BLOCKEND ); + ret =wait_for_completion_interruptible_timeout (&user_data->done, +msecs_to_jiffies (100 )); +/* Valid stream might not be present. */ +if (ret <=0 ) { +dev_dbg (dev->dev,"user data for channel %d timeout\n" , + channel); +regmap_write (dev->regmap,SPDIFRX_IDR ,SPDIFRX_IR_BLOCKEND ); + ret = ret ? : -ETIMEDOUT ; + goto unlock; + }else { + ret =0 ; + } + }else { +/* Update software cache with last available data. */ +mchp_spdifrx_channel_user_data_read (dev, channel); } -spin_lock_irqsave (&user_data->lock, flags);memcpy (uvalue->value.iec958.subcode, user_data->data,sizeof (user_data->data)); -spin_unlock_irqrestore (&user_data->lock, flags); -return 0 ; +unlock: +mutex_unlock (&dev->mlock); +return ret; } static int mchp_spdifrx_subcode_ch1_get(struct snd_kcontrol *kcontrol,
@@ -890,11 +904,9 @@ static int mchp_spdifrx_dai_probe(struct snd_soc_dai *dai)SPDIFRX_MR_AUTORST_NOACTION | SPDIFRX_MR_PACK_DISABLED); - dev->blockend_refcount =0 ;for (ch =0 ; ch <SPDIFRX_CHANNELS ; ch++) {init_completion (&ctrl->ch_stat[ch].done);init_completion (&ctrl->user_data[ch].done); -spin_lock_init (&ctrl->user_data[ch].lock); }/* Add controls */
@@ -1004,7 +1016,6 @@ static int mchp_spdifrx_probe(struct platform_device *pdev)*/ clk_set_min_rate (dev->gclk,48000 *SPDIFRX_GCLK_RATIO_MIN +1 ); -spin_lock_init (&dev->blockend_lock);mutex_init (&dev->mlock); dev->dev = &pdev->dev;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 197/529 ASoC: mchp-spdifrx: disable all interrupts in mchp_spdifrx_dai_remove()
In reply to Greg Kroah-HartmanFrom: Claudiu Beznea <[email protected]>
[ Upstream commit aaecdc32b7e35b4f9b457fb3509414aa9a932589 ]
CSC interrupts which might be used in controls are on bits 8 and 9 of SPDIFRX_IDR register. Thus disable all the interrupts that are exported by driver.
--- sound/soc/atmel/mchp-spdifrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/atmel/mchp-spdifrx.c +1 -1
@@ -921,7 +921,7 @@ static int mchp_spdifrx_dai_remove(struct snd_soc_dai *dai)struct mchp_spdifrx_dev *dev =snd_soc_dai_get_drvdata (dai);/* Disable interrupts */ -regmap_write (dev->regmap,SPDIFRX_IDR ,0xFF ); +regmap_write (dev->regmap,SPDIFRX_IDR ,GENMASK (14 ,0 ));clk_disable_unprepare (dev->pclk);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 198/529 ASoC: mchp-spdifrx: Fix uninitialized use of mr in mchp_spdifrx_hw_params()
In reply to Greg Kroah-HartmanFrom: Nathan Chancellor <[email protected]>
[ Upstream commit 218674a45930c700486d27b765bf2f1b43f8cbf7 ]
Clang warns:
../sound/soc/atmel/mchp-spdifrx.c:455:3: error: variable 'mr' is uninitialized when used here [-Werror,-Wuninitialized]
mr |= SPDIFRX_MR_ENDIAN_BIG;
^~
../sound/soc/atmel/mchp-spdifrx.c:432:8: note: initialize the variable 'mr' to silence this warning
u32 mr;
^
= 01 error generated.
Zero initialize mr so that these bitwise OR and assignment operation works unconditionally.
--- sound/soc/atmel/mchp-spdifrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/atmel/mchp-spdifrx.c +1 -1
@@ -362,7 +362,7 @@ static int mchp_spdifrx_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) {struct mchp_spdifrx_dev *dev =snd_soc_dai_get_drvdata (dai); -u32 mr; +u32 mr =0 ;int ret; dev_dbg(dev->dev, "%s() rate=%u format=%#x width=%u channels=%u\n",
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 199/529 ASoC: dt-bindings: meson: fix gx-card codec node regex
In reply to Greg Kroah-HartmanFrom: Jerome Brunet <[email protected]>
[ Upstream commit 480b26226873c88e482575ceb0d0a38d76e1be57 ]
'codec' is a valid node name when there is a single codec in the link. Fix the node regular expression to apply this.
--- .../devicetree/bindings/sound/amlogic,gx-sound-card.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Documentation/devicetree/bindings/sound/amlogic,gx-sound-card.yaml +1 -1
@@ -61,7 +61,7 @@ patternProperties: description: phandle of the CPU DAI patternProperties: - "^codec-[0-9]+$": + "^codec(-[0-9]+)?$": type: object description: |- Codecs:
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 200/529 hwmon: (ltc2945) Handle error case in ltc2945_value_store
In reply to Greg Kroah-HartmanFrom: Jonathan Cormier <[email protected]>
[ Upstream commit 178b01eccfb0b8149682f61388400bd3d903dddc ]
ltc2945_val_to_reg errors were not being handled which would have resulted in register being set to 0 (clamped) instead of being left alone.
--- drivers/hwmon/ltc2945.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/hwmon/ltc2945.c +2 -0
@@ -248,6 +248,8 @@ static ssize_t ltc2945_value_store(struct device *dev,/* convert to register value, then clamp and write result */ regval =ltc2945_val_to_reg (dev, reg, val); +if (regval <0 ) +return regval;if (is_power_reg (reg)) { regval =clamp_val (regval,0 ,0xffffff ); regbuf[0 ] = regval >>16 ;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 201/529 drm/amdgpu: fix enum odm_combine_mode mismatch
In reply to Greg Kroah-HartmanFrom: Arnd Bergmann <[email protected]>
[ Upstream commit 087bad7eb1f6945f8232f132953ecc2bda8bd38d ]
A conversion from 'bool' to 'enum odm_combine_mode' was incomplete, and gcc warns about this with many instances of
display/dc/dml/dcn20/display_mode_vba_20.c:3899:44: warning: implicit conversion from 'enum <anonymous>' to 'enum odm_combine_mode' [-Wenum-conversion]
3899 | locals->ODMCombineEnablePerState[i][k] = false;
Change the ones that we get a warning for, using the same numerical values to leave the behavior unchanged.
--- .../amd/display/dc/dml/dcn20/display_mode_vba_20.c | 8 ++++---- .../amd/display/dc/dml/dcn20/display_mode_vba_20v2.c | 10 +++++----- .../amd/display/dc/dml/dcn21/display_mode_vba_21.c | 12 ++++++------ 3 files changed, 15 insertions(+), 15 deletions(-)
drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c +4 -4
@@ -3897,14 +3897,14 @@ void dml20_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l mode_lib->vba.PlaneRequiredDISPCLKWithODMCombine = mode_lib->vba.PixelClock[k] /2 * (1 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading /100.0 ); - locals->ODMCombineEnablePerState[i][k] = false; + locals->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_disabled; mode_lib->vba.PlaneRequiredDISPCLK = mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine;if (mode_lib->vba.ODMCapability) {if (locals->PlaneRequiredDISPCLKWithoutODMCombine > mode_lib->vba.MaxDispclkRoundedDownToDFSGranularity) { - locals->ODMCombineEnablePerState[i][k] = true; + locals->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; mode_lib->vba.PlaneRequiredDISPCLK = mode_lib->vba.PlaneRequiredDISPCLKWithODMCombine; }else if (locals->HActive[k] >DCN20_MAX_420_IMAGE_WIDTH && locals->OutputFormat[k] == dm_420) { - locals->ODMCombineEnablePerState[i][k] = true; + locals->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; mode_lib->vba.PlaneRequiredDISPCLK = mode_lib->vba.PlaneRequiredDISPCLKWithODMCombine; } }
@@ -3957,7 +3957,7 @@ void dml20_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l locals->RequiredDISPCLK[i][j] =0.0 ; locals->DISPCLK_DPPCLK_Support[i][j] = true;for (k =0 ; k <= mode_lib->vba.NumberOfActivePlanes -1 ; k++) { - locals->ODMCombineEnablePerState[i][k] = false; + locals->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_disabled;if (locals->SwathWidthYSingleDPP[k] <= locals->MaximumSwathWidth[k]) { locals->NoOfDPP[i][j][k] =1 ; locals->RequiredDPPCLK[i][j][k] = locals->MinDPPCLKUsingSingleDPP[k]
drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c +5 -5
@@ -3974,17 +3974,17 @@ void dml20v2_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode mode_lib->vba.PlaneRequiredDISPCLKWithODMCombine = mode_lib->vba.PixelClock[k] /2 * (1 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading /100.0 ); - locals->ODMCombineEnablePerState[i][k] = false; + locals->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_disabled; mode_lib->vba.PlaneRequiredDISPCLK = mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine;if (mode_lib->vba.ODMCapability) {if (locals->PlaneRequiredDISPCLKWithoutODMCombine > MaxMaxDispclkRoundedDown) { - locals->ODMCombineEnablePerState[i][k] = true; + locals->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; mode_lib->vba.PlaneRequiredDISPCLK = mode_lib->vba.PlaneRequiredDISPCLKWithODMCombine; }else if (locals->DSCEnabled[k] && (locals->HActive[k] >DCN20_MAX_DSC_IMAGE_WIDTH )) { - locals->ODMCombineEnablePerState[i][k] = true; + locals->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; mode_lib->vba.PlaneRequiredDISPCLK = mode_lib->vba.PlaneRequiredDISPCLKWithODMCombine; }else if (locals->HActive[k] >DCN20_MAX_420_IMAGE_WIDTH && locals->OutputFormat[k] == dm_420) { - locals->ODMCombineEnablePerState[i][k] = true; + locals->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; mode_lib->vba.PlaneRequiredDISPCLK = mode_lib->vba.PlaneRequiredDISPCLKWithODMCombine; } }
@@ -4037,7 +4037,7 @@ void dml20v2_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode locals->RequiredDISPCLK[i][j] =0.0 ; locals->DISPCLK_DPPCLK_Support[i][j] = true;for (k =0 ; k <= mode_lib->vba.NumberOfActivePlanes -1 ; k++) { - locals->ODMCombineEnablePerState[i][k] = false; + locals->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_disabled;if (locals->SwathWidthYSingleDPP[k] <= locals->MaximumSwathWidth[k]) { locals->NoOfDPP[i][j][k] =1 ; locals->RequiredDPPCLK[i][j][k] = locals->MinDPPCLKUsingSingleDPP[k]
drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c +6 -6
@@ -3975,17 +3975,17 @@ void dml21_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l mode_lib->vba.PlaneRequiredDISPCLKWithODMCombine = mode_lib->vba.PixelClock[k] /2 * (1 + mode_lib->vba.DISPCLKDPPCLKDSCCLKDownSpreading /100.0 ); - locals->ODMCombineEnablePerState[i][k] = false; + locals->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_disabled; mode_lib->vba.PlaneRequiredDISPCLK = mode_lib->vba.PlaneRequiredDISPCLKWithoutODMCombine;if (mode_lib->vba.ODMCapability) {if (locals->PlaneRequiredDISPCLKWithoutODMCombine > MaxMaxDispclkRoundedDown) { - locals->ODMCombineEnablePerState[i][k] = true; + locals->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; mode_lib->vba.PlaneRequiredDISPCLK = mode_lib->vba.PlaneRequiredDISPCLKWithODMCombine; }else if (locals->DSCEnabled[k] && (locals->HActive[k] >DCN21_MAX_DSC_IMAGE_WIDTH )) { - locals->ODMCombineEnablePerState[i][k] = true; + locals->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; mode_lib->vba.PlaneRequiredDISPCLK = mode_lib->vba.PlaneRequiredDISPCLKWithODMCombine; }else if (locals->HActive[k] >DCN21_MAX_420_IMAGE_WIDTH && locals->OutputFormat[k] == dm_420) { - locals->ODMCombineEnablePerState[i][k] = true; + locals->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; mode_lib->vba.PlaneRequiredDISPCLK = mode_lib->vba.PlaneRequiredDISPCLKWithODMCombine; } }
@@ -4038,7 +4038,7 @@ void dml21_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l locals->RequiredDISPCLK[i][j] =0.0 ; locals->DISPCLK_DPPCLK_Support[i][j] = true;for (k =0 ; k <= mode_lib->vba.NumberOfActivePlanes -1 ; k++) { - locals->ODMCombineEnablePerState[i][k] = false; + locals->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_disabled;if (locals->SwathWidthYSingleDPP[k] <= locals->MaximumSwathWidth[k]) { locals->NoOfDPP[i][j][k] =1 ; locals->RequiredDPPCLK[i][j][k] = locals->MinDPPCLKUsingSingleDPP[k]
@@ -5213,7 +5213,7 @@ void dml21_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l mode_lib->vba.ODMCombineEnabled[k] = locals->ODMCombineEnablePerState[mode_lib->vba.VoltageLevel][k]; }else { - mode_lib->vba.ODMCombineEnabled[k] = false; + mode_lib->vba.ODMCombineEnabled[k] = dm_odm_combine_mode_disabled; } mode_lib->vba.DSCEnabled[k] = locals->RequiresDSC[mode_lib->vba.VoltageLevel][k];
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 202/529 scsi: mpt3sas: Fix a memory leak
In reply to Greg Kroah-HartmanFrom: Tomas Henzl <[email protected]>
[ Upstream commit 54dd96015e8d7a2a07359e2dfebf05b529d1780c ]
Add a forgotten kfree().
--- drivers/scsi/mpt3sas/mpt3sas_base.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/scsi/mpt3sas/mpt3sas_base.c +3 -0
@@ -4905,6 +4905,9 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc) }dma_pool_destroy (ioc->pcie_sgl_dma_pool); } +kfree (ioc->pcie_sg_lookup); + ioc->pcie_sg_lookup =NULL ; +if (ioc->config_page) { dexitprintk(ioc, ioc_info(ioc, "config_page(0x%p): free\n",
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 203/529 scsi: aic94xx: Add missing check for dma_map_single()
In reply to Greg Kroah-HartmanFrom: Jiasheng Jiang <[email protected]>
[ Upstream commit 32fe45274edb5926abc0fac7263d9f889d02d9cf ]
Add check for dma_map_single() and return error if it fails in order to avoid invalid DMA address.
--- drivers/scsi/aic94xx/aic94xx_task.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/scsi/aic94xx/aic94xx_task.c +3 -0
@@ -50,6 +50,9 @@ static int asd_map_scatterlist(struct sas_task *task,dma_addr_t dma =dma_map_single (&asd_ha->pcidev->dev, p, task->total_xfer_len, task->data_dir); +if (dma_mapping_error (&asd_ha->pcidev->dev, dma)) +return -ENOMEM ; + sg_arr[0 ].bus_addr =cpu_to_le64 ((u64 )dma); sg_arr[0 ].size =cpu_to_le32 (task->total_xfer_len); sg_arr[0 ].flags |=ASD_SG_EL_LIST_EOL ;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 204/529 spi: bcm63xx-hsspi: fix pm_runtime
In reply to Greg Kroah-HartmanFrom: Álvaro Fernández Rojas <[email protected]>
[ Upstream commit 216e8e80057a9f0b6366327881acf88eaf9f1fd4 ]
The driver sets auto_runtime_pm to true, but it doesn't call pm_runtime_enable(), which results in "Failed to power device" when PM support is enabled.
Stable-dep-of: 811ff802aaf8 ("spi: bcm63xx-hsspi: Fix multi-bit mode setting")
--- drivers/spi/spi-bcm63xx-hsspi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/spi/spi-bcm63xx-hsspi.c +6 -1
@@ -21,6 +21,7 @@#include <linux/mutex.h> #include <linux/of.h> #include <linux/reset.h> +#include <linux/pm_runtime.h> #define HSSPI_GLOBAL_CTRL_REG 0x0#define GLOBAL_CTRL_CS_POLARITY_SHIFT 0
@@ -439,13 +440,17 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev)if (ret) goto out_put_master; +pm_runtime_enable (&pdev->dev); +/* register and we are done */ ret =devm_spi_register_master (dev, master);if (ret) - goto out_put_master; + goto out_pm_disable;return 0 ; +out_pm_disable: +pm_runtime_disable (&pdev->dev); out_put_master:spi_master_put (master); out_disable_pll_clk:
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 205/529 spi: bcm63xx-hsspi: Fix multi-bit mode setting
In reply to Greg Kroah-HartmanFrom: William Zhang <[email protected]>
[ Upstream commit 811ff802aaf878ebbbaeac0307a0164fa21e7d40 ]
Currently the driver always sets the controller to dual data bit mode for both tx and rx data in the profile mode control register even for single data bit transfer. Luckily the opcode is set correctly according to SPI transfer data bit width so it does not actually cause issues.
This change fixes the problem by setting tx and rx data bit mode field correctly according to the actual SPI transfer tx and rx data bit width.
--- drivers/spi/spi-bcm63xx-hsspi.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
drivers/spi/spi-bcm63xx-hsspi.c +9 -3
@@ -163,6 +163,7 @@ static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t)int step_size =HSSPI_BUFFER_LEN ;const u8 *tx = t->tx_buf;u8 *rx = t->rx_buf; +u32 val =0 ;bcm63xx_hsspi_set_clk (bs, spi, t->speed_hz);bcm63xx_hsspi_set_cs (bs, spi->chip_select, true);
@@ -178,11 +179,16 @@ static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t) step_size -=HSSPI_OPCODE_LEN ;if ((opcode ==HSSPI_OP_READ && t->rx_nbits ==SPI_NBITS_DUAL ) || - (opcode ==HSSPI_OP_WRITE && t->tx_nbits ==SPI_NBITS_DUAL )) + (opcode ==HSSPI_OP_WRITE && t->tx_nbits ==SPI_NBITS_DUAL )) { opcode |=HSSPI_OP_MULTIBIT ; -__raw_writel (1 <<MODE_CTRL_MULTIDATA_WR_SIZE_SHIFT | -1 <<MODE_CTRL_MULTIDATA_RD_SIZE_SHIFT |0xff , +if (t->rx_nbits ==SPI_NBITS_DUAL ) + val |=1 <<MODE_CTRL_MULTIDATA_RD_SIZE_SHIFT ; +if (t->tx_nbits ==SPI_NBITS_DUAL ) + val |=1 <<MODE_CTRL_MULTIDATA_WR_SIZE_SHIFT ; + } + +__raw_writel (val |0xff , bs->regs +HSSPI_PROFILE_MODE_CTRL_REG (chip_select));while (pending >0 ) {
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 206/529 hwmon: (mlxreg-fan) Return zero speed for broken fan
In reply to Greg Kroah-HartmanFrom: Vadim Pasternak <[email protected]>
[ Upstream commit a1ffd3c46267ee5c807acd780e15df9bb692223f ]
Currently for broken fan driver returns value calculated based on error code (0xFF) in related fan speed register.
Thus, for such fan user gets fan{n}_fault to 1 and fan{n}_input with misleading value.
Add check for fan fault prior return speed value and return zero if fault is detected.
--- drivers/hwmon/mlxreg-fan.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/hwmon/mlxreg-fan.c +6 -0
@@ -127,6 +127,12 @@ mlxreg_fan_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,if (err)return err; +if (MLXREG_FAN_GET_FAULT (regval, tacho->mask)) { +/* FAN is broken - return zero for FAN speed. */ + *val =0 ; +return 0 ; + } + *val =MLXREG_FAN_GET_RPM (regval, fan->divider, fan->samples);break ;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 207/529 ASoC: tlv320adcx140: fix ti,gpio-config DT property init
In reply to Greg Kroah-HartmanFrom: Steffen Aschbacher <[email protected]>
[ Upstream commit 771725efe5e2e5396dd9d1220437e5f9d6b9ca9d ]
When the 'ti,gpio-config' property is not defined, the device_property_count_u32() will return an error, rather than zero.
The current check, only handles a return value of zero, which assumes that the property is defined and has nothing defined.
This change extends the check to also check for an error case (most likely to be hit by the case that the 'ti,gpio-config' is not defined).
In case that the 'ti,gpio-config' and the returned 'gpio_count' is not correct, there is a 'if (gpio_count != ADCX140_NUM_GPIO_CFGS)' check, a few lines lower that will return -EINVAL.
This means that someone tried to define 'ti,gpio-config', but with the wrong number of GPIOs.
--- sound/soc/codecs/tlv320adcx140.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/codecs/tlv320adcx140.c +1 -1
@@ -870,7 +870,7 @@ static int adcx140_configure_gpio(struct adcx140_priv *adcx140) gpio_count =device_property_count_u32 (adcx140->dev,"ti,gpio-config" ); -if (gpio_count ==0 ) +if (gpio_count <=0 )return 0 ;if (gpio_count !=ADCX140_NUM_GPIO_CFGS )
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 208/529 dm: remove flush_scheduled_work() during local_exit()
In reply to Greg Kroah-HartmanFrom: Mike Snitzer <[email protected]>
[ Upstream commit 0b22ff5360f5c4e11050b89206370fdf7dc0a226 ]
Commit acfe0ad74d2e1 ("dm: allocate a special workqueue for deferred device removal") switched from using system workqueue to a single workqueue local to DM. But it didn't eliminate the call to flush_scheduled_work() that was introduced purely for the benefit of deferred device removal with commit 2c140a246dc ("dm: allow remove to be deferred").
Since DM core uses its own workqueue (and queue_work) there is no need to call flush_scheduled_work() from local_exit(). local_exit()'s destroy_workqueue(deferred_remove_workqueue) handles flushing work started with queue_work().
--- drivers/md/dm.c | 1 - 1 file changed, 1 deletion(-)
drivers/md/dm.c +0 -1
@@ -265,7 +265,6 @@ static int __init local_init(void)static void local_exit (void ) { -flush_scheduled_work ();destroy_workqueue (deferred_remove_workqueue);unregister_blkdev (_major, _name);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 209/529 NFS: Fix up handling of outstanding layoutcommit in nfs_update_inode()
In reply to Greg Kroah-HartmanFrom: Trond Myklebust <[email protected]>
[ Upstream commit 709fa5769914b377af87962bbe4ff81ffb019b2d ]
If there is an outstanding layoutcommit, then the list of attributes whose values are expected to change is not the full set. So let's be explicit about the full list.
Stable-dep-of: b46d80bd2d6e ("nfs4trace: fix state manager flag printing")
--- fs/nfs/inode.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
fs/nfs/inode.c +5 -1
@@ -1906,7 +1906,11 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)nfs_wcc_update_inode (inode, fattr);if (pnfs_layoutcommit_outstanding (inode)) { - nfsi->cache_validity |= save_cache_validity &NFS_INO_INVALID_ATTR ; + nfsi->cache_validity |= + save_cache_validity & + (NFS_INO_INVALID_CHANGE |NFS_INO_INVALID_CTIME | +NFS_INO_INVALID_MTIME |NFS_INO_INVALID_SIZE | +NFS_INO_REVAL_FORCED ); cache_revalidated = false; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 210/529 NFSv4: keep state manager thread active if swap is enabled
In reply to Greg Kroah-HartmanFrom: NeilBrown <[email protected]>
[ Upstream commit 4dc73c679114a2f408567e2e44770ed934190db2 ]
If we are swapping over NFSv4, we may not be able to allocate memory to start the state-manager thread at the time when we need it. So keep it always running when swap is enabled, and just signal it to start.
This requires updating and testing the cl_swapper count on the root rpc_clnt after following all ->cl_parent links.
Stable-dep-of: b46d80bd2d6e ("nfs4trace: fix state manager flag printing")
--- fs/nfs/file.c | 15 ++++++++++++--- fs/nfs/nfs4_fs.h | 1 + fs/nfs/nfs4proc.c | 20 ++++++++++++++++++++ fs/nfs/nfs4state.c | 40 +++++++++++++++++++++++++++++++++------- include/linux/nfs_xdr.h | 2 ++ net/sunrpc/clnt.c | 2 ++ 6 files changed, 70 insertions(+), 10 deletions(-)
fs/nfs/file.c +12 -3
@@ -487,8 +487,9 @@ static int nfs_swap_activate(struct swap_info_struct *sis, struct file *file, {unsigned long blocks;long long isize; -struct rpc_clnt *clnt =NFS_CLIENT (file->f_mapping->host); -struct inode *inode = file->f_mapping->host; +struct inode *inode =file_inode (file); +struct rpc_clnt *clnt =NFS_CLIENT (inode); +struct nfs_client *cl =NFS_SERVER (inode)->nfs_client;spin_lock (&inode->i_lock); blocks = inode->i_blocks;
@@ -501,14 +502,22 @@ static int nfs_swap_activate(struct swap_info_struct *sis, struct file *file, *span = sis->pages; + +if (cl->rpc_ops->enable_swap) + cl->rpc_ops->enable_swap (inode); +return rpc_clnt_swap_activate (clnt); }static void nfs_swap_deactivate (struct file *file) { -struct rpc_clnt *clnt =NFS_CLIENT (file->f_mapping->host); +struct inode *inode =file_inode (file); +struct rpc_clnt *clnt =NFS_CLIENT (inode); +struct nfs_client *cl =NFS_SERVER (inode)->nfs_client;rpc_clnt_swap_deactivate (clnt); +if (cl->rpc_ops->disable_swap) + cl->rpc_ops->disable_swap (file_inode (file)); }const struct address_space_operations nfs_file_aops = {
fs/nfs/nfs4_fs.h +1 -0
@@ -42,6 +42,7 @@ enum nfs4_client_state {NFS4CLNT_LEASE_MOVED ,NFS4CLNT_DELEGATION_EXPIRED ,NFS4CLNT_RUN_MANAGER , +NFS4CLNT_MANAGER_AVAILABLE ,NFS4CLNT_RECALL_RUNNING ,NFS4CLNT_RECALL_ANY_LAYOUT_READ , NFS4CLNT_RECALL_ANY_LAYOUT_RW,
fs/nfs/nfs4proc.c +20 -0
@@ -10385,6 +10385,24 @@ static ssize_t nfs4_listxattr(struct dentry *dentry, char *list, size_t size)return error + error2 + error3; } +static void nfs4_enable_swap (struct inode *inode) +{ +/* The state manager thread must always be running. +* It will notice the client is a swapper, and stay put. +*/ +struct nfs_client *clp =NFS_SERVER (inode)->nfs_client; + +nfs4_schedule_state_manager (clp); +} + +static void nfs4_disable_swap (struct inode *inode) +{ +/* The state manager thread will now exit once it is +* woken. +*/ +wake_up_var (&NFS_SERVER (inode)->nfs_client->cl_state); +} +static const struct inode_operations nfs4_dir_inode_operations = { .create = nfs_create, .lookup = nfs_lookup,
@@ -10461,6 +10479,8 @@ const struct nfs_rpc_ops nfs_v4_clientops = { .free_client = nfs4_free_client, .create_server = nfs4_create_server, .clone_server = nfs_clone_server, + .enable_swap = nfs4_enable_swap, + .disable_swap = nfs4_disable_swap, };static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = {
fs/nfs/nfs4state.c +33 -7
@@ -1208,10 +1208,17 @@ void nfs4_schedule_state_manager(struct nfs_client *clp) {struct task_struct *task;char buf[INET6_ADDRSTRLEN +sizeof ("-manager" ) +1 ]; +struct rpc_clnt *cl = clp->cl_rpcclient; + +while (cl != cl->cl_parent) + cl = cl->cl_parent;set_bit (NFS4CLNT_RUN_MANAGER , &clp->cl_state); -if (test_and_set_bit (NFS4CLNT_MANAGER_RUNNING , &clp->cl_state) !=0 ) +if (test_and_set_bit (NFS4CLNT_MANAGER_AVAILABLE , &clp->cl_state) !=0 ) { +wake_up_var (&clp->cl_state);return ; + } +set_bit (NFS4CLNT_MANAGER_RUNNING , &clp->cl_state);__module_get (THIS_MODULE );refcount_inc (&clp->cl_count);
@@ -1229,6 +1236,7 @@ void nfs4_schedule_state_manager(struct nfs_client *clp)if (!nfs_client_init_is_complete (clp))nfs_mark_client_ready (clp,PTR_ERR (task));nfs4_clear_state_manager_bit (clp); +clear_bit (NFS4CLNT_MANAGER_AVAILABLE , &clp->cl_state);nfs_put_client (clp);module_put (THIS_MODULE ); }
@@ -2680,12 +2688,8 @@ static void nfs4_state_manager(struct nfs_client *clp)clear_bit (NFS4CLNT_RECALL_RUNNING , &clp->cl_state); } -/* Did we race with an attempt to give us more work? */ -if (!test_bit (NFS4CLNT_RUN_MANAGER , &clp->cl_state)) -return ; -if (test_and_set_bit (NFS4CLNT_MANAGER_RUNNING , &clp->cl_state) !=0 ) -return ; - memflags =memalloc_nofs_save (); +return ; + }while (refcount_read (&clp->cl_count) >1 && !signalled ()); goto out_drain;
@@ -2706,9 +2710,31 @@ static void nfs4_state_manager(struct nfs_client *clp)static int nfs4_run_state_manager (void *ptr) {struct nfs_client *clp = ptr; +struct rpc_clnt *cl = clp->cl_rpcclient; + +while (cl != cl->cl_parent) + cl = cl->cl_parent;allow_signal (SIGKILL ); +again: +set_bit (NFS4CLNT_MANAGER_RUNNING , &clp->cl_state);nfs4_state_manager (clp); +if (atomic_read (&cl->cl_swapper)) { +wait_var_event_interruptible (&clp->cl_state, +test_bit (NFS4CLNT_RUN_MANAGER , + &clp->cl_state)); +if (atomic_read (&cl->cl_swapper) && +test_bit (NFS4CLNT_RUN_MANAGER , &clp->cl_state)) + goto again; +/* Either no longer a swapper, or were signalled */ + } +clear_bit (NFS4CLNT_MANAGER_AVAILABLE , &clp->cl_state); + +if (refcount_read (&clp->cl_count) >1 && !signalled () && +test_bit (NFS4CLNT_RUN_MANAGER , &clp->cl_state) && + !test_and_set_bit (NFS4CLNT_MANAGER_AVAILABLE , &clp->cl_state)) + goto again; +nfs_put_client (clp);module_put_and_exit (0 );return 0 ;
include/linux/nfs_xdr.h +2 -0
@@ -1789,6 +1789,8 @@ struct nfs_rpc_ops {struct nfs_server *(*create_server)(struct fs_context *);struct nfs_server *(*clone_server)(struct nfs_server *,struct nfs_fh *,struct nfs_fattr *,rpc_authflavor_t ); +void (*enable_swap)(struct inode *inode); +void (*disable_swap)(struct inode *inode); };/*
net/sunrpc/clnt.c +2 -0
@@ -3026,6 +3026,8 @@ rpc_clnt_swap_activate_callback(struct rpc_clnt *clnt,int rpc_clnt_swap_activate (struct rpc_clnt *clnt) { +while (clnt != clnt->cl_parent) + clnt = clnt->cl_parent;if (atomic_inc_return (&clnt->cl_swapper) ==1 )return rpc_clnt_iterate_for_each_xprt (clnt, rpc_clnt_swap_activate_callback,NULL );
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 211/529 nfs4trace: fix state manager flag printing
In reply to Greg Kroah-HartmanFrom: Benjamin Coddington <[email protected]>
[ Upstream commit b46d80bd2d6e7e063c625a20de54248afe8d4889 ]
__print_flags wants a mask, not the enum value. Add two more flags.
--- fs/nfs/nfs4trace.h | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-)
fs/nfs/nfs4trace.h +22 -20
@@ -584,32 +584,34 @@ TRACE_DEFINE_ENUM(NFS4CLNT_MOVED);TRACE_DEFINE_ENUM (NFS4CLNT_LEASE_MOVED );TRACE_DEFINE_ENUM (NFS4CLNT_DELEGATION_EXPIRED );TRACE_DEFINE_ENUM (NFS4CLNT_RUN_MANAGER ); +TRACE_DEFINE_ENUM (NFS4CLNT_MANAGER_AVAILABLE );TRACE_DEFINE_ENUM (NFS4CLNT_RECALL_RUNNING );TRACE_DEFINE_ENUM (NFS4CLNT_RECALL_ANY_LAYOUT_READ );TRACE_DEFINE_ENUM (NFS4CLNT_RECALL_ANY_LAYOUT_RW ); +TRACE_DEFINE_ENUM (NFS4CLNT_DELEGRETURN_DELAYED );#define show_nfs4_clp_state (state) \ __print_flags(state, "|", \ - { NFS4CLNT_MANAGER_RUNNING, "MANAGER_RUNNING" }, \ - { NFS4CLNT_CHECK_LEASE, "CHECK_LEASE" }, \ - { NFS4CLNT_LEASE_EXPIRED, "LEASE_EXPIRED" }, \ - { NFS4CLNT_RECLAIM_REBOOT, "RECLAIM_REBOOT" }, \ - { NFS4CLNT_RECLAIM_NOGRACE, "RECLAIM_NOGRACE" }, \ - { NFS4CLNT_DELEGRETURN, "DELEGRETURN" }, \ - { NFS4CLNT_SESSION_RESET, "SESSION_RESET" }, \ - { NFS4CLNT_LEASE_CONFIRM, "LEASE_CONFIRM" }, \ - { NFS4CLNT_SERVER_SCOPE_MISMATCH, \ - "SERVER_SCOPE_MISMATCH" }, \ - { NFS4CLNT_PURGE_STATE, "PURGE_STATE" }, \ - { NFS4CLNT_BIND_CONN_TO_SESSION, \ - "BIND_CONN_TO_SESSION" }, \ - { NFS4CLNT_MOVED, "MOVED" }, \ - { NFS4CLNT_LEASE_MOVED, "LEASE_MOVED" }, \ - { NFS4CLNT_DELEGATION_EXPIRED, "DELEGATION_EXPIRED" }, \ - { NFS4CLNT_RUN_MANAGER, "RUN_MANAGER" }, \ - { NFS4CLNT_RECALL_RUNNING, "RECALL_RUNNING" }, \ - { NFS4CLNT_RECALL_ANY_LAYOUT_READ, "RECALL_ANY_LAYOUT_READ" }, \ - { NFS4CLNT_RECALL_ANY_LAYOUT_RW, "RECALL_ANY_LAYOUT_RW" }) + { BIT(NFS4CLNT_MANAGER_RUNNING), "MANAGER_RUNNING" }, \ + { BIT(NFS4CLNT_CHECK_LEASE), "CHECK_LEASE" }, \ + { BIT(NFS4CLNT_LEASE_EXPIRED), "LEASE_EXPIRED" }, \ + { BIT(NFS4CLNT_RECLAIM_REBOOT), "RECLAIM_REBOOT" }, \ + { BIT(NFS4CLNT_RECLAIM_NOGRACE), "RECLAIM_NOGRACE" }, \ + { BIT(NFS4CLNT_DELEGRETURN), "DELEGRETURN" }, \ + { BIT(NFS4CLNT_SESSION_RESET), "SESSION_RESET" }, \ + { BIT(NFS4CLNT_LEASE_CONFIRM), "LEASE_CONFIRM" }, \ + { BIT(NFS4CLNT_SERVER_SCOPE_MISMATCH), "SERVER_SCOPE_MISMATCH" }, \ + { BIT(NFS4CLNT_PURGE_STATE), "PURGE_STATE" }, \ + { BIT(NFS4CLNT_BIND_CONN_TO_SESSION), "BIND_CONN_TO_SESSION" }, \ + { BIT(NFS4CLNT_MOVED), "MOVED" }, \ + { BIT(NFS4CLNT_LEASE_MOVED), "LEASE_MOVED" }, \ + { BIT(NFS4CLNT_DELEGATION_EXPIRED), "DELEGATION_EXPIRED" }, \ + { BIT(NFS4CLNT_RUN_MANAGER), "RUN_MANAGER" }, \ + { BIT(NFS4CLNT_MANAGER_AVAILABLE), "MANAGER_AVAILABLE" }, \ + { BIT(NFS4CLNT_RECALL_RUNNING), "RECALL_RUNNING" }, \ + { BIT(NFS4CLNT_RECALL_ANY_LAYOUT_READ), "RECALL_ANY_LAYOUT_READ" }, \ + { BIT(NFS4CLNT_RECALL_ANY_LAYOUT_RW), "RECALL_ANY_LAYOUT_RW" }, \ + { BIT(NFS4CLNT_DELEGRETURN_DELAYED), "DELERETURN_DELAYED" }) TRACE_EVENT(nfs4_state_mgr, TP_PROTO(
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 212/529 NFS: fix disabling of swap
In reply to Greg Kroah-HartmanFrom: NeilBrown <[email protected]>
[ Upstream commit 5bab56fff53ce161ed859d9559a10361d4f79578 ]
When swap is activated to a file on an NFSv4 mount we arrange that the state manager thread is always present as starting a new thread requires memory allocations that might block waiting for swap.
Unfortunately the code for allowing the state manager thread to exit when swap is disabled was not tested properly and does not work. This can be seen by examining /proc/fs/nfsfs/servers after disabling swap and unmounting the filesystem. The servers file will still list one entry. Also a "ps" listing will show the state manager thread is still present.
There are two problems.
1/ rpc_clnt_swap_deactivate() doesn't walk up the ->cl_parent list to
find the primary client on which the state manager runs.
2/ The thread is not woken up properly and it immediately goes back to
sleep without checking whether it is really needed. Using nfs4_schedule_state_manager() ensures a proper wake-up.
--- fs/nfs/nfs4proc.c | 4 +++- net/sunrpc/clnt.c | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-)
fs/nfs/nfs4proc.c +3 -1
@@ -10400,7 +10400,9 @@ static void nfs4_disable_swap(struct inode *inode)/* The state manager thread will now exit once it is * woken. */ -wake_up_var (&NFS_SERVER (inode)->nfs_client->cl_state); +struct nfs_client *clp =NFS_SERVER (inode)->nfs_client; + +nfs4_schedule_state_manager (clp); }static const struct inode_operations nfs4_dir_inode_operations = {
net/sunrpc/clnt.c +2 -0
@@ -3047,6 +3047,8 @@ rpc_clnt_swap_deactivate_callback(struct rpc_clnt *clnt,void rpc_clnt_swap_deactivate (struct rpc_clnt *clnt) { +while (clnt != clnt->cl_parent) + clnt = clnt->cl_parent;if (atomic_dec_if_positive (&clnt->cl_swapper) ==0 )rpc_clnt_iterate_for_each_xprt (clnt, rpc_clnt_swap_deactivate_callback,NULL );
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 213/529 spi: synquacer: Fix timeout handling in synquacer_spi_transfer_one()
In reply to Greg Kroah-HartmanFrom: Christophe JAILLET <[email protected]>
[ Upstream commit e6a0b671880207566e1ece983bf989dde60bc1d7 ]
wait_for_completion_timeout() never returns a <0 value. It returns either on timeout or a positive value (at least 1, or number of jiffies left till timeout)
So, fix the error handling path and return -ETIMEDOUT should a timeout occur.
--- drivers/spi/spi-synquacer.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
drivers/spi/spi-synquacer.c +3 -4
@@ -472,10 +472,9 @@ static int synquacer_spi_transfer_one(struct spi_master *master,read_fifo (sspi); } -if (status <0 ) { -dev_err (sspi->dev,"failed to transfer. status: 0x%x\n" , - status); -return status; +if (status ==0 ) { +dev_err (sspi->dev,"failed to transfer. Timeout.\n" ); +return -ETIMEDOUT ; }return 0 ;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 214/529 ASoC: soc-dapm.h: fixup warning struct snd_pcm_substream not declared
In reply to Greg Kroah-HartmanFrom: Lucas Tanure <[email protected]>
[ Upstream commit fdff966bfde7cf0c85562d2bfb1ff1ba83da5f7b ]
Add struct snd_pcm_substream forward declaration
--- include/sound/soc-dapm.h | 1 + 1 file changed, 1 insertion(+)
include/sound/soc-dapm.h +1 -0
@@ -16,6 +16,7 @@#include <sound/asoc.h> struct device ; +struct snd_pcm_substream ;struct snd_soc_pcm_runtime ;struct soc_enum ;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 215/529 HID: bigben: use spinlock to protect concurrent accesses
In reply to Greg Kroah-HartmanFrom: Pietro Borrello <[email protected]>
[ Upstream commit 9fefb6201c4f8dd9f58c581b2a66e5cde2895ea2 ]
bigben driver has a worker that may access data concurrently. Proct the accesses using a spinlock.
--- drivers/hid/hid-bigbenff.c | 52 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-)
drivers/hid/hid-bigbenff.c +50 -2
@@ -174,6 +174,7 @@ static __u8 pid0902_rdesc_fixed[] = {struct bigben_device {struct hid_device *hid;struct hid_report *report; +spinlock_t lock;bool removed;u8 led_state;/* LED1 = 1 .. LED4 = 8 */ u8 right_motor_on;/* right motor off/on 0/1 */
@@ -190,12 +191,27 @@ static void bigben_worker(struct work_struct *work)struct bigben_device *bigben =container_of (work, struct bigben_device, worker);struct hid_field *report_field = bigben->report->field[0 ]; +bool do_work_led = false; +bool do_work_ff = false; +u8 *buf; +u32 len; +unsigned long flags;if (bigben->removed || !report_field)return ; + buf =hid_alloc_report_buf (bigben->report,GFP_KERNEL ); +if (!buf) +return ; + + len =hid_report_len (bigben->report); + +/* LED work */ +spin_lock_irqsave (&bigben->lock, flags); +if (bigben->work_led) { bigben->work_led = false; + do_work_led = true; report_field->value[0 ] =0x01 ;/* 1 = led message */ report_field->value[1 ] =0x08 ;/* reserved value, always 8 */ report_field->value[2 ] = bigben->led_state;
@@ -204,11 +220,22 @@ static void bigben_worker(struct work_struct *work) report_field->value[5 ] =0x00 ;/* padding */ report_field->value[6 ] =0x00 ;/* padding */ report_field->value[7 ] =0x00 ;/* padding */ -hid_hw_request (bigben->hid, bigben->report,HID_REQ_SET_REPORT ); +hid_output_report (bigben->report, buf); + } + +spin_unlock_irqrestore (&bigben->lock, flags); + +if (do_work_led) { +hid_hw_raw_request (bigben->hid, bigben->report->id, buf, len, + bigben->report->type,HID_REQ_SET_REPORT ); } +/* FF work */ +spin_lock_irqsave (&bigben->lock, flags); +if (bigben->work_ff) { bigben->work_ff = false; + do_work_ff = true; report_field->value[0 ] =0x02 ;/* 2 = rumble effect message */ report_field->value[1 ] =0x08 ;/* reserved value, always 8 */ report_field->value[2 ] = bigben->right_motor_on;
@@ -217,8 +244,17 @@ static void bigben_worker(struct work_struct *work) report_field->value[5 ] =0x00 ;/* padding */ report_field->value[6 ] =0x00 ;/* padding */ report_field->value[7 ] =0x00 ;/* padding */ -hid_hw_request (bigben->hid, bigben->report,HID_REQ_SET_REPORT ); +hid_output_report (bigben->report, buf); + } + +spin_unlock_irqrestore (&bigben->lock, flags); + +if (do_work_ff) { +hid_hw_raw_request (bigben->hid, bigben->report->id, buf, len, + bigben->report->type,HID_REQ_SET_REPORT ); } + +kfree (buf); } static int hid_bigben_play_effect(struct input_dev *dev, void *data,
@@ -228,6 +264,7 @@ static int hid_bigben_play_effect(struct input_dev *dev, void *data,struct bigben_device *bigben =hid_get_drvdata (hid);u8 right_motor_on;u8 left_motor_force; +unsigned long flags;if (!bigben) {hid_err (hid,"no device data\n" );
@@ -242,9 +279,12 @@ static int hid_bigben_play_effect(struct input_dev *dev, void *data,if (right_motor_on != bigben->right_motor_on || left_motor_force != bigben->left_motor_force) { +spin_lock_irqsave (&bigben->lock, flags); bigben->right_motor_on = right_motor_on; bigben->left_motor_force = left_motor_force; bigben->work_ff = true; +spin_unlock_irqrestore (&bigben->lock, flags); +schedule_work (&bigben->worker); }
@@ -259,6 +299,7 @@ static void bigben_set_led(struct led_classdev *led,struct bigben_device *bigben =hid_get_drvdata (hid);int n;bool work; +unsigned long flags;if (!bigben) {hid_err (hid,"no device data\n" );
@@ -267,6 +308,7 @@ static void bigben_set_led(struct led_classdev *led,for (n =0 ; n <NUM_LEDS ; n++) {if (led == bigben->leds[n]) { +spin_lock_irqsave (&bigben->lock, flags);if (value ==LED_OFF ) { work = (bigben->led_state &BIT (n)); bigben->led_state &= ~BIT (n);
@@ -274,6 +316,7 @@ static void bigben_set_led(struct led_classdev *led, work = !(bigben->led_state &BIT (n)); bigben->led_state |=BIT (n); } +spin_unlock_irqrestore (&bigben->lock, flags);if (work) { bigben->work_led = true;
@@ -307,8 +350,12 @@ static enum led_brightness bigben_get_led(struct led_classdev *led)static void bigben_remove (struct hid_device *hid) {struct bigben_device *bigben =hid_get_drvdata (hid); +unsigned long flags; +spin_lock_irqsave (&bigben->lock, flags); bigben->removed = true; +spin_unlock_irqrestore (&bigben->lock, flags); +cancel_work_sync (&bigben->worker);hid_hw_stop (hid); }
@@ -362,6 +409,7 @@ static int bigben_probe(struct hid_device *hid,set_bit (FF_RUMBLE , hidinput->input->ffbit);INIT_WORK (&bigben->worker, bigben_worker); +spin_lock_init (&bigben->lock); error =input_ff_create_memless (hidinput->input,NULL , hid_bigben_play_effect);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 216/529 HID: bigben_worker() remove unneeded check on report_field
In reply to Greg Kroah-HartmanFrom: Pietro Borrello <[email protected]>
[ Upstream commit 27d2a2fd844ec7da70d19fabb482304fd1e0595b ]
bigben_worker() checks report_field to be non-NULL. The check has been added in commit918aa1ef104d ("HID: bigbenff: prevent null pointer dereference") to prevent a NULL pointer crash.
However, the true root cause was a missing check for output reports, patched in commitc7bf714f8755 ("HID: check empty report_list in bigben_probe()"), where the type-confused report list_entry was overlapping with a NULL pointer, which was then causing the crash.
--- drivers/hid/hid-bigbenff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/hid/hid-bigbenff.c +1 -1
@@ -197,7 +197,7 @@ static void bigben_worker(struct work_struct *work)u32 len;unsigned long flags; -if (bigben->removed || !report_field) +if (bigben->removed)return ; buf =hid_alloc_report_buf (bigben->report,GFP_KERNEL );
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 217/529 HID: bigben: use spinlock to safely schedule workers
In reply to Greg Kroah-HartmanFrom: Pietro Borrello <[email protected]>
[ Upstream commit 76ca8da989c7d97a7f76c75d475fe95a584439d7 ]
Use spinlocks to deal with workers introducing a wrapper bigben_schedule_work(), and several spinlock checks. Otherwise, bigben_set_led() may schedule bigben->worker after the structure has been freed, causing a use-after-free.
--- drivers/hid/hid-bigbenff.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
drivers/hid/hid-bigbenff.c +12 -6
@@ -185,6 +185,15 @@ struct bigben_device {struct work_struct worker; }; +static inline void bigben_schedule_work (struct bigben_device *bigben) +{ +unsigned long flags; + +spin_lock_irqsave (&bigben->lock, flags); +if (!bigben->removed) +schedule_work (&bigben->worker); +spin_unlock_irqrestore (&bigben->lock, flags); +}static void bigben_worker (struct work_struct *work) {
@@ -197,9 +206,6 @@ static void bigben_worker(struct work_struct *work)u32 len;unsigned long flags; -if (bigben->removed) -return ; - buf =hid_alloc_report_buf (bigben->report,GFP_KERNEL );if (!buf)return ;
@@ -285,7 +291,7 @@ static int hid_bigben_play_effect(struct input_dev *dev, void *data, bigben->work_ff = true;spin_unlock_irqrestore (&bigben->lock, flags); -schedule_work (&bigben->worker); +bigben_schedule_work (bigben); }return 0 ;
@@ -320,7 +326,7 @@ static void bigben_set_led(struct led_classdev *led,if (work) { bigben->work_led = true; -schedule_work (&bigben->worker); +bigben_schedule_work (bigben); }return ; }
@@ -450,7 +456,7 @@ static int bigben_probe(struct hid_device *hid, bigben->left_motor_force =0 ; bigben->work_led = true; bigben->work_ff = true; -schedule_work (&bigben->worker); +bigben_schedule_work (bigben);hid_info (hid,"LED and force feedback support for BigBen gamepad\n" );
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 218/529 hid: bigben_probe(): validate report count
In reply to Greg Kroah-HartmanFrom: Pietro Borrello <[email protected]>
[ Upstream commit b94335f899542a0da5fafc38af8edcaf90195843 ]
bigben_probe() does not validate that the output report has the needed report values in the first field.
A malicious device registering a report with one field and a single value causes an head OOB write in bigben_worker() when accessing report_field->value[1] to report_field->value[7]. Use hid_validate_values() which takes care of all the needed checks.
--- drivers/hid/hid-bigbenff.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
drivers/hid/hid-bigbenff.c +2 -5
@@ -371,7 +371,6 @@ static int bigben_probe(struct hid_device *hid, {struct bigben_device *bigben;struct hid_input *hidinput; -struct list_head *report_list;struct led_classdev *led;char *name;size_t name_sz;
@@ -396,14 +395,12 @@ static int bigben_probe(struct hid_device *hid,return error; } - report_list = &hid->report_enum[HID_OUTPUT_REPORT ].report_list; -if (list_empty (report_list)) { + bigben->report =hid_validate_values (hid,HID_OUTPUT_REPORT ,0 ,0 ,8 ); +if (!bigben->report) {hid_err (hid,"no output report found\n" ); error = -ENODEV ; goto error_hw_stop; } - bigben->report =list_entry (report_list->next, - struct hid_report, list);if (list_empty (&hid->inputs)) {hid_err (hid,"no inputs found\n" );
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 219/529 nfsd: fix race to check ls_layouts
In reply to Greg Kroah-HartmanFrom: Benjamin Coddington <[email protected]>
[ Upstream commit fb610c4dbc996415d57d7090957ecddd4fd64fb6 ]
Its possible for __break_lease to find the layout's lease before we've added the layout to the owner's ls_layouts list. In that case, setting ls_recalled = true without actually recalling the layout will cause the server to never send a recall callback.
Move the check for ls_layouts before setting ls_recalled.
--- fs/nfsd/nfs4layouts.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/nfsd/nfs4layouts.c +2 -2
@@ -322,11 +322,11 @@ nfsd4_recall_file_layout(struct nfs4_layout_stateid *ls)if (ls->ls_recalled) goto out_unlock; - ls->ls_recalled = true; -atomic_inc (&ls->ls_stid.sc_file->fi_lo_recalls);if (list_empty (&ls->ls_layouts)) goto out_unlock; + ls->ls_recalled = true; +atomic_inc (&ls->ls_stid.sc_file->fi_lo_recalls);trace_nfsd_layout_recall (&ls->ls_stid.sc_stateid);refcount_inc (&ls->ls_stid.sc_count);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 220/529 cifs: Fix lost destroy smbd connection when MR allocate failed
In reply to Greg Kroah-HartmanFrom: Zhang Xiaoxu <[email protected]>
[ Upstream commit e9d3401d95d62a9531082cd2453ed42f2740e3fd ]
If the MR allocate failed, the smb direct connection info is NULL, then smbd_destroy() will directly return, then the connection info will be leaked.
Let's set the smb direct connection info to the server before call smbd_destroy().
--- fs/cifs/smbdirect.c | 1 + 1 file changed, 1 insertion(+)
fs/cifs/smbdirect.c +1 -0
@@ -1691,6 +1691,7 @@ static struct smbd_connection *_smbd_get_connection( allocate_mr_failed:/* At this point, need to a full transport shutdown */ + server->smbd_conn = info;smbd_destroy (server);return NULL ;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 221/529 cifs: Fix warning and UAF when destroy the MR list
In reply to Greg Kroah-HartmanFrom: Zhang Xiaoxu <[email protected]>
[ Upstream commit 3e161c2791f8e661eed24a2c624087084d910215 ]
If the MR allocate failed, the MR recovery work not initialized and list not cleared. Then will be warning and UAF when release the MR:
WARNING: CPU: 4 PID: 824 at kernel/workqueue.c:3066 __flush_work.isra.0+0xf7/0x110 CPU: 4 PID: 824 Comm: mount.cifs Not tainted 6.1.0-rc5+ #82 RIP: 0010:__flush_work.isra.0+0xf7/0x110 Call Trace: <TASK> __cancel_work_timer+0x2ba/0x2e0 smbd_destroy+0x4e1/0x990 _smbd_get_connection+0x1cbd/0x2110 smbd_get_connection+0x21/0x40 cifs_get_tcp_session+0x8ef/0xda0 mount_get_conns+0x60/0x750 cifs_mount+0x103/0xd00 cifs_smb3_do_mount+0x1dd/0xcb0 smb3_get_tree+0x1d5/0x300 vfs_get_tree+0x41/0xf0 path_mount+0x9b3/0xdd0 __x64_sys_mount+0x190/0x1d0 do_syscall_64+0x35/0x80 entry_SYSCALL_64_after_hwframe+0x46/0xb0 BUG: KASAN: use-after-free in smbd_destroy+0x4fc/0x990 Read of size 8 at addr ffff88810b156a08 by task mount.cifs/824 CPU: 4 PID: 824 Comm: mount.cifs Tainted: G W 6.1.0-rc5+ #82 Call Trace: dump_stack_lvl+0x34/0x44 print_report+0x171/0x472 kasan_report+0xad/0x130 smbd_destroy+0x4fc/0x990 _smbd_get_connection+0x1cbd/0x2110 smbd_get_connection+0x21/0x40 cifs_get_tcp_session+0x8ef/0xda0 mount_get_conns+0x60/0x750 cifs_mount+0x103/0xd00 cifs_smb3_do_mount+0x1dd/0xcb0 smb3_get_tree+0x1d5/0x300 vfs_get_tree+0x41/0xf0 path_mount+0x9b3/0xdd0 __x64_sys_mount+0x190/0x1d0 do_syscall_64+0x35/0x80 entry_SYSCALL_64_after_hwframe+0x46/0xb0 Allocated by task 824: kasan_save_stack+0x1e/0x40 kasan_set_track+0x21/0x30 __kasan_kmalloc+0x7a/0x90 _smbd_get_connection+0x1b6f/0x2110 smbd_get_connection+0x21/0x40 cifs_get_tcp_session+0x8ef/0xda0 mount_get_conns+0x60/0x750 cifs_mount+0x103/0xd00 cifs_smb3_do_mount+0x1dd/0xcb0 smb3_get_tree+0x1d5/0x300 vfs_get_tree+0x41/0xf0 path_mount+0x9b3/0xdd0 __x64_sys_mount+0x190/0x1d0 do_syscall_64+0x35/0x80 entry_SYSCALL_64_after_hwframe+0x46/0xb0 Freed by task 824: kasan_save_stack+0x1e/0x40 kasan_set_track+0x21/0x30 kasan_save_free_info+0x2a/0x40 ____kasan_slab_free+0x143/0x1b0 __kmem_cache_free+0xc8/0x330 _smbd_get_connection+0x1c6a/0x2110 smbd_get_connection+0x21/0x40 cifs_get_tcp_session+0x8ef/0xda0 mount_get_conns+0x60/0x750 cifs_mount+0x103/0xd00 cifs_smb3_do_mount+0x1dd/0xcb0 smb3_get_tree+0x1d5/0x300 vfs_get_tree+0x41/0xf0 path_mount+0x9b3/0xdd0 __x64_sys_mount+0x190/0x1d0 do_syscall_64+0x35/0x80 entry_SYSCALL_64_after_hwframe+0x46/0xb0
Let's initialize the MR recovery work before MR allocate to prevent the warning, remove the MRs from the list to prevent the UAF.
--- fs/cifs/smbdirect.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/cifs/smbdirect.c +2 -1
@@ -2240,6 +2240,7 @@ static int allocate_mr_list(struct smbd_connection *info)atomic_set (&info->mr_ready_count,0 );atomic_set (&info->mr_used_count,0 );init_waitqueue_head (&info->wait_for_mr_cleanup); +INIT_WORK (&info->mr_recovery_work, smbd_mr_recovery_work);/* Allocate more MRs (2x) than hardware responder_resources */ for (i =0 ; i < info->responder_resources *2 ; i++) { smbdirect_mr =kzalloc (sizeof (*smbdirect_mr),GFP_KERNEL );
@@ -2267,13 +2268,13 @@ static int allocate_mr_list(struct smbd_connection *info)list_add_tail (&smbdirect_mr->list, &info->mr_list);atomic_inc (&info->mr_ready_count); } -INIT_WORK (&info->mr_recovery_work, smbd_mr_recovery_work);return 0 ; out:kfree (smbdirect_mr);list_for_each_entry_safe (smbdirect_mr, tmp, &info->mr_list, list) { +list_del (&smbdirect_mr->list);ib_dereg_mr (smbdirect_mr->mr);kfree (smbdirect_mr->sgl);kfree (smbdirect_mr);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 222/529 gfs2: jdata writepage fix
In reply to Greg Kroah-HartmanFrom: Andreas Gruenbacher <[email protected]>
[ Upstream commit cbb60951ce18c9b6e91d2eb97deb41d8ff616622 ]
The ->writepage() and ->writepages() operations are supposed to write entire pages. However, on filesystems with a block size smaller than PAGE_SIZE, __gfs2_jdata_writepage() only adds the first block to the current transaction instead of adding the entire page. Fix that.
--- fs/gfs2/aops.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
fs/gfs2/aops.c +1 -2
@@ -152,7 +152,6 @@ static int __gfs2_jdata_writepage(struct page *page, struct writeback_control *w {struct inode *inode = page->mapping->host;struct gfs2_inode *ip =GFS2_I (inode); -struct gfs2_sbd *sdp =GFS2_SB (inode);if (PageChecked (page)) {ClearPageChecked (page);
@@ -160,7 +159,7 @@ static int __gfs2_jdata_writepage(struct page *page, struct writeback_control *wcreate_empty_buffers (page, inode->i_sb->s_blocksize,BIT (BH_Dirty)|BIT (BH_Uptodate)); } -gfs2_page_add_databufs (ip, page,0 , sdp->sd_vfs->s_blocksize); +gfs2_page_add_databufs (ip, page,0 ,PAGE_SIZE ); }return gfs2_write_jdata_page (page, wbc); }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 223/529 perf llvm: Fix inadvertent file creation
In reply to Greg Kroah-HartmanFrom: Ian Rogers <[email protected]>
[ Upstream commit 9f19aab47ced012eddef1e2bc96007efc7713b61 ]
The LLVM template is first echo-ed into command_out and then command_out executed. The echo surrounds the template with double quotes, however, the template itself may contain quotes. This is generally innocuous but in tools/perf/tests/bpf-script-test-prologue.c we see:
...SEC("func=null_lseek file->f_mode offset orig")
...
where the first double quote ends the double quote of the echo, then the > redirects output into a file called f_mode.
To avoid this inadvertent behavior substitute redirects and similar characters to be ASCII control codes, then substitute the output in the echo back again.
--- tools/perf/util/llvm-utils.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-)
tools/perf/util/llvm-utils.c +24 -1
@@ -525,14 +525,37 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,pr_debug ("llvm compiling command template: %s\n" , template); +/* +* Below, substitute control characters for values that can cause the +* echo to misbehave, then substitute the values back. +*/ err = -ENOMEM ; -if (asprintf (&command_echo,"echo -n \"%s\"" , template) <0 ) +if (asprintf (&command_echo,"echo -n \a%s\a" , template) <0 ) goto errout; +#define SWAP_CHAR (a, b) do { if (*p == a) *p = b; } while (0) +for (char *p = command_echo; *p; p++) { +SWAP_CHAR ('<' ,'\001' ); +SWAP_CHAR ('>' ,'\002' ); +SWAP_CHAR ('"' ,'\003' ); +SWAP_CHAR ('\'' ,'\004' ); +SWAP_CHAR ('|' ,'\005' ); +SWAP_CHAR ('&' ,'\006' ); +SWAP_CHAR ('\a' ,'"' ); + } err =read_from_pipe (command_echo, (void **) &command_out,NULL );if (err) goto errout; +for (char *p = command_out; *p; p++) { +SWAP_CHAR ('\001' ,'<' ); +SWAP_CHAR ('\002' ,'>' ); +SWAP_CHAR ('\003' ,'"' ); +SWAP_CHAR ('\004' ,'\'' ); +SWAP_CHAR ('\005' ,'|' ); +SWAP_CHAR ('\006' ,'&' ); + } +#undef SWAP_CHARpr_debug ("llvm compiling command : %s\n" , command_out); err =read_from_pipe (template, &obj_buf, &obj_buf_sz);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 224/529 leds: led-core: Fix refcount leak in of_led_get()
In reply to Greg Kroah-HartmanFrom: Miaoqian Lin <[email protected]>
[ Upstream commit da1afe8e6099980fe1e2fd7436dca284af9d3f29 ]
class_find_device_by_of_node() calls class_find_device(), it will take the reference, use the put_device() to drop the reference when not need anymore.
--- drivers/leds/led-class.c | 1 + 1 file changed, 1 insertion(+)
drivers/leds/led-class.c +1 -0
@@ -236,6 +236,7 @@ struct led_classdev *of_led_get(struct device_node *np, int index) led_dev =class_find_device_by_of_node (leds_class, led_node);of_node_put (led_node); +put_device (led_dev);if (!led_dev)return ERR_PTR (-EPROBE_DEFER );
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 225/529 perf tools: Fix auto-complete on aarch64
In reply to Greg Kroah-HartmanFrom: Yicong Yang <[email protected]>
[ Upstream commit ffd1240e8f0814262ceb957dbe961f6e0aef1e7a ]
On aarch64 CPU related events are not under event_source/devices/cpu/events, they're under event_source/devices/armv8_pmuv3_0/events on my machine. Using current auto-complete script will generate below error:
[root@localhost bin]# perf stat -e
ls: cannot access '/sys/bus/event_source/devices/cpu/events': No such file or directory
Fix this by not testing /sys/bus/event_source/devices/cpu/events on aarch64 machine.
--- tools/perf/perf-completion.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
tools/perf/perf-completion.sh +8 -3
@@ -165,7 +165,12 @@ __perf_main () local cur1=${COMP_WORDS[COMP_CWORD]} local raw_evts=$($cmd list --raw-dump) - local arr s tmp result + local arr s tmp result cpu_evts + + # aarch64 doesn't have /sys/bus/event_source/devices/cpu/events + if [[ `uname -m` != aarch64 ]]; then + cpu_evts=$(ls /sys/bus/event_source/devices/cpu/events) + fi if [[ "$cur1" == */* && ${cur1#*/} =~ ^[A-Z] ]]; then OLD_IFS="$IFS"
@@ -183,9 +188,9 @@ __perf_main () fi done - evts=${result}" "$(ls /sys/bus/event_source/devices/cpu/events) + evts=${result}" "${cpu_evts} else - evts=${raw_evts}" "$(ls /sys/bus/event_source/devices/cpu/events) + evts=${raw_evts}" "${cpu_evts} fi if [[ "$cur1" == , ]]; then
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 226/529 sparc: allow PM configs for sparc32 COMPILE_TEST
In reply to Greg Kroah-HartmanFrom: Randy Dunlap <[email protected]>
[ Upstream commit 7be6a87c2473957090995b7eb541e31d57a2c801 ]
When doing randconfig builds for sparc32 with COMPILE_TEST, some (non-Sparc) drivers cause kconfig warnings with the Kconfig symbols PM, PM_GENERIC_DOMAINS, or PM_GENERIC_DOMAINS_OF.
This is due to arch/sparc/Kconfig not using the PM Kconfig for Sparc32:
if SPARC64
source "kernel/power/Kconfig"
endif
Arnd suggested adding "|| COMPILE_TEST" to the conditional, instead of trying to track down every driver that selects any of these PM symbols.
Fixes the following kconfig warnings:
WARNING: unmet direct dependencies detected for PM
Depends on [n]: SPARC64 [=n]
Selected by [y]:
- SUN20I_PPU [=y] && (ARCH_SUNXI || COMPILE_TEST [=y])
WARNING: unmet direct dependencies detected for PM
Depends on [n]: SPARC64 [=n]
Selected by [y]:
- SUN20I_PPU [=y] && (ARCH_SUNXI || COMPILE_TEST [=y])
WARNING: unmet direct dependencies detected for PM_GENERIC_DOMAINS
Depends on [n]: SPARC64 [=n] && PM [=y]
Selected by [y]:
- QCOM_GDSC [=y] && COMMON_CLK [=y] && PM [=y]
- SUN20I_PPU [=y] && (ARCH_SUNXI || COMPILE_TEST [=y])
- MESON_GX_PM_DOMAINS [=y] && (ARCH_MESON || COMPILE_TEST [=y]) && PM [=y] && OF [=y]
- BCM2835_POWER [=y] && (ARCH_BCM2835 || COMPILE_TEST [=y] && OF [=y]) && PM [=y]
- BCM_PMB [=y] && (ARCH_BCMBCA || COMPILE_TEST [=y] && OF [=y]) && PM [=y]
- ROCKCHIP_PM_DOMAINS [=y] && (ARCH_ROCKCHIP || COMPILE_TEST [=y]) && PM [=y] Selected by [m]:
- ARM_SCPI_POWER_DOMAIN [=m] && (ARM_SCPI_PROTOCOL [=m] || COMPILE_TEST [=y] && OF [=y]) && PM [=y]
- MESON_EE_PM_DOMAINS [=m] && (ARCH_MESON || COMPILE_TEST [=y]) && PM [=y] && OF [=y]
- QCOM_AOSS_QMP [=m] && (ARCH_QCOM || COMPILE_TEST [=y]) && MAILBOX [=y] && COMMON_CLK [=y] && PM [=y]
WARNING: unmet direct dependencies detected for PM_GENERIC_DOMAINS_OF
Depends on [n]: SPARC64 [=n] && PM_GENERIC_DOMAINS [=y] && OF [=y] Selected by [y]:
- MESON_GX_PM_DOMAINS [=y] && (ARCH_MESON || COMPILE_TEST [=y]) && PM [=y] && OF [=y] Selected by [m]:
- MESON_EE_PM_DOMAINS [=m] && (ARCH_MESON || COMPILE_TEST [=y]) && PM [=y] && OF [=y]
--- arch/sparc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/sparc/Kconfig +1 -1
@@ -293,7 +293,7 @@ config FORCE_MAX_ZONEORDER This config option is actually maximum order plus one. For example, a value of 13 means that the largest free memory block is 2^12 pages. -if SPARC64 +if SPARC64 || COMPILE_TEST source "kernel/power/Kconfig" endif
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 227/529 selftests/ftrace: Fix bash specific "==" operator
In reply to Greg Kroah-HartmanFrom: Masami Hiramatsu (Google) <[email protected]>
[ Upstream commit 1e6b485c922fbedf41d5a9f4e6449c5aeb923a32 ]
Since commit a1d6cd88c897 ("selftests/ftrace: event_triggers: wait longer for test_event_enable") introduced bash specific "==" comparation operator, that test will fail when we run it on a posix-shell. checkbashisms warned it as below.
possible bashism in ftrace/func_event_triggers.tc line 45 (should be 'b = a'):
if [ "$e" == $val ]; then
This replaces it with "=".
--- .../selftests/ftrace/test.d/ftrace/func_event_triggers.tc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc +1 -1
@@ -42,7 +42,7 @@ test_event_enabled() { while [ $check_times -ne 0 ]; do e=`cat $EVENT_ENABLE` - if [ "$e" == $val ]; then + if [ "$e" = $val ]; then return 0 fi sleep $SLEEP_TIME
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 228/529 printf: fix errname.c list
In reply to Greg Kroah-HartmanFrom: Arnd Bergmann <[email protected]>
[ Upstream commit 0c2baf6509af1d11310ae4c1c839481a6e9a4bc4 ]
On most architectures, gcc -Wextra warns about the list of error numbers containing both EDEADLK and EDEADLOCK:
lib/errname.c:15:67: warning: initialized field overwritten [-Woverride-init]
15 | #define E(err) [err + BUILD_BUG_ON_ZERO(err <= 0 || err > 300)] = "-" #err
| ^~~lib/errname.c:172:2: note: in expansion of macro 'E'
172 | E(EDEADLK), /* EDEADLOCK */
| ^On parisc, a similar error happens with -ECANCELLED, which is an alias for ECANCELED.
Make the EDEADLK printing conditional on the number being distinct from EDEADLOCK, and remove the -ECANCELLED bit completely as it can never be hit.
To ensure these are correct, add static_assert lines that verify all the remaining aliases are in fact identical to the canonical name.
--- lib/errname.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-)
lib/errname.c +14 -8
@@ -20,6 +20,7 @@ static const char *names_0[] = {E (EADDRNOTAVAIL ),E (EADV ),E (EAFNOSUPPORT ), +E (EAGAIN ),/* EWOULDBLOCK */ E (EALREADY ),E (EBADE ), E(EBADF),
@@ -30,15 +31,17 @@ static const char *names_0[] = {E (EBADSLT ),E (EBFONT ),E (EBUSY ), -#ifdef ECANCELLED -E (ECANCELLED ), -#endif +E (ECANCELED ),/* ECANCELLED */ E (ECHILD ),E (ECHRNG ),E (ECOMM ),E (ECONNABORTED ), +E (ECONNREFUSED ),/* EREFUSED */ E (ECONNRESET ), +E (EDEADLK ),/* EDEADLOCK */ +#if EDEADLK != EDEADLOCK /* mips, sparc, powerpc */E (EDEADLOCK ), +#endifE (EDESTADDRREQ ),E (EDOM ), E(EDOTDOT),
@@ -165,14 +168,17 @@ static const char *names_0[] = {E (EUSERS ),E (EXDEV ), E(EXFULL), - -E (ECANCELED ),/* ECANCELLED */ -E (EAGAIN ),/* EWOULDBLOCK */ -E (ECONNREFUSED ),/* EREFUSED */ - E(EDEADLK), /* EDEADLOCK */ };#undef E +#ifdef EREFUSED /* parisc */ +static_assert (EREFUSED ==ECONNREFUSED ); +#endif +#ifdef ECANCELLED /* parisc */ +static_assert (ECANCELLED ==ECANCELED ); +#endif +static_assert (EAGAIN ==EWOULDBLOCK );/* everywhere */ +#define E (err) [err - 512 + BUILD_BUG_ON_ZERO(err < 512 || err > 550)] = "-" #errstatic const char *names_512[] = {E (ERESTARTSYS ),
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 229/529 objtool: add UACCESS exceptions for __tsan_volatile_read/write
In reply to Greg Kroah-HartmanFrom: Arnd Bergmann <[email protected]>
[ Upstream commit d5d469247264e56960705dc5ae7e1d014861fe40 ]
A lot of the tsan helpers are already excempt from the UACCESS warnings, but some more functions were added that need the same thing:
kernel/kcsan/core.o: warning: objtool: __tsan_volatile_read16+0x0: call to __tsan_unaligned_read16() with UACCESS enabled kernel/kcsan/core.o: warning: objtool: __tsan_volatile_write16+0x0: call to __tsan_unaligned_write16() with UACCESS enabled vmlinux.o: warning: objtool: __tsan_unaligned_volatile_read16+0x4: call to __tsan_unaligned_read16() with UACCESS enabled vmlinux.o: warning: objtool: __tsan_unaligned_volatile_write16+0x4: call to __tsan_unaligned_write16() with UACCESS enabled
As Marco points out, these functions don't even call each other explicitly but instead gcc (but not clang) notices the functions being identical and turns one symbol into a direct branch to the other.
--- tools/objtool/check.c | 2 ++ 1 file changed, 2 insertions(+)
tools/objtool/check.c +2 -0
@@ -864,6 +864,8 @@ static const char *uaccess_safe_builtin[] = {"__tsan_atomic64_compare_exchange_val" ,"__tsan_atomic_thread_fence" ,"__tsan_atomic_signal_fence" , +"__tsan_unaligned_read16" , +"__tsan_unaligned_write16" ,/* KCOV */ "write_comp_data" , "check_kcov_mode",
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 230/529 mfd: pcf50633-adc: Fix potential memleak in pcf50633_adc_async_read()
In reply to Greg Kroah-HartmanFrom: Qiheng Lin <[email protected]>
[ Upstream commit 8b450dcff23aa254844492831a8e2b508a9d522d ]
req is allocated in pcf50633_adc_async_read(), but adc_enqueue_request() could fail to insert the req into queue. We need to check the return value and free it in the case of failure.
--- drivers/mfd/pcf50633-adc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/mfd/pcf50633-adc.c +6 -1
@@ -136,6 +136,7 @@ int pcf50633_adc_async_read(struct pcf50633 *pcf, int mux, int avg, void *callback_param) {struct pcf50633_adc_request *req; +int ret;/* req is freed when the result is ready, in interrupt handler */ req =kmalloc (sizeof (*req),GFP_KERNEL );
@@ -147,7 +148,11 @@ int pcf50633_adc_async_read(struct pcf50633 *pcf, int mux, int avg, req->callback = callback; req->callback_param = callback_param; -return adc_enqueue_request (pcf, req); + ret =adc_enqueue_request (pcf, req); +if (ret) +kfree (req); + +return ret; }EXPORT_SYMBOL_GPL (pcf50633_adc_async_read);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 231/529 clk: qcom: gcc-qcs404: disable gpll[04]_out_aux parents
In reply to Greg Kroah-HartmanFrom: Dmitry Baryshkov <[email protected]>
[ Upstream commit 712c64caf31374de57aa193a9dff57172b2f6f82 ]
On the QCS404 platform the driver for the Global Clock Controller doens't define gpll0_out_aux and gpll4_out_aux clocks, so it's not possible to use them as parents. Remove entries for these clocks.
Note: backporting this patch to earlier kernels would also require a previous patch which switches the gcc driver to use ARRAY_SIZE for parent data arrays.
--- drivers/clk/qcom/gcc-qcs404.c | 16 ---------------- 1 file changed, 16 deletions(-)
drivers/clk/qcom/gcc-qcs404.c +0 -16
@@ -25,11 +25,9 @@ enum {P_CORE_BI_PLL_TEST_SE ,P_DSI0_PHY_PLL_OUT_BYTECLK ,P_DSI0_PHY_PLL_OUT_DSICLK , -P_GPLL0_OUT_AUX ,P_GPLL0_OUT_MAIN ,P_GPLL1_OUT_MAIN ,P_GPLL3_OUT_MAIN , -P_GPLL4_OUT_AUX ,P_GPLL4_OUT_MAIN ,P_GPLL6_OUT_AUX , P_HDMI_PHY_PLL_CLK,
@@ -109,28 +107,24 @@ static const char * const gcc_parent_names_4[] = {static const struct parent_map gcc_parent_map_5[] = { {P_XO ,0 }, {P_DSI0_PHY_PLL_OUT_BYTECLK ,1 }, - {P_GPLL0_OUT_AUX ,2 }, {P_CORE_BI_PLL_TEST_SE ,7 }, };static const char *const gcc_parent_names_5[] = {"cxo" ,"dsi0pll_byteclk_src" , -"gpll0_out_aux" ,"core_bi_pll_test_se" , };static const struct parent_map gcc_parent_map_6[] = { {P_XO ,0 }, {P_DSI0_PHY_PLL_OUT_BYTECLK ,2 }, - {P_GPLL0_OUT_AUX ,3 }, {P_CORE_BI_PLL_TEST_SE ,7 }, };static const char *const gcc_parent_names_6[] = {"cxo" ,"dsi0_phy_pll_out_byteclk" , -"gpll0_out_aux" ,"core_bi_pll_test_se" , };
@@ -139,7 +133,6 @@ static const struct parent_map gcc_parent_map_7[] = { { P_GPLL0_OUT_MAIN, 1 }, { P_GPLL3_OUT_MAIN, 2 }, { P_GPLL6_OUT_AUX, 3 }, - { P_GPLL4_OUT_AUX, 4 }, { P_CORE_BI_PLL_TEST_SE, 7 }, };
@@ -148,7 +141,6 @@ static const char * const gcc_parent_names_7[] = {"gpll0_out_main" ,"gpll3_out_main" ,"gpll6_out_aux" , -"gpll4_out_aux" , "core_bi_pll_test_se", };
@@ -207,14 +199,12 @@ static const char * const gcc_parent_names_11[] = {static const struct parent_map gcc_parent_map_12[] = { {P_XO ,0 }, {P_DSI0_PHY_PLL_OUT_DSICLK ,1 }, - {P_GPLL0_OUT_AUX ,2 }, {P_CORE_BI_PLL_TEST_SE ,7 }, };static const char *const gcc_parent_names_12[] = {"cxo" ,"dsi0pll_pclk_src" , -"gpll0_out_aux" ,"core_bi_pll_test_se" , };
@@ -237,40 +227,34 @@ static const char * const gcc_parent_names_13[] = {static const struct parent_map gcc_parent_map_14[] = { {P_XO ,0 }, {P_GPLL0_OUT_MAIN ,1 }, - {P_GPLL4_OUT_AUX ,2 }, {P_CORE_BI_PLL_TEST_SE ,7 }, };static const char *const gcc_parent_names_14[] = {"cxo" ,"gpll0_out_main" , -"gpll4_out_aux" ,"core_bi_pll_test_se" , };static const struct parent_map gcc_parent_map_15[] = { {P_XO ,0 }, - {P_GPLL0_OUT_AUX ,2 }, {P_CORE_BI_PLL_TEST_SE ,7 }, };static const char *const gcc_parent_names_15[] = {"cxo" , -"gpll0_out_aux" ,"core_bi_pll_test_se" , };static const struct parent_map gcc_parent_map_16[] = { {P_XO ,0 }, {P_GPLL0_OUT_MAIN ,1 }, - {P_GPLL0_OUT_AUX ,2 }, {P_CORE_BI_PLL_TEST_SE ,7 }, };static const char *const gcc_parent_names_16[] = {"cxo" ,"gpll0_out_main" , -"gpll0_out_aux" ,"core_bi_pll_test_se" , };
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 232/529 clk: qcom: gcc-qcs404: fix names of the DSI clocks used as parents
In reply to Greg Kroah-HartmanFrom: Dmitry Baryshkov <[email protected]>
[ Upstream commit 47d94d30cd3dcc743241b4208b1eec7247610c84 ]
The QCS404 uses 28nm LPM DSI PHY, which registers dsi0pll and dsi0pllbyte clocks. Fix all DSI PHY clock names used as parents inside the GCC driver.
--- drivers/clk/qcom/gcc-qcs404.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/clk/qcom/gcc-qcs404.c +4 -4
@@ -112,7 +112,7 @@ static const struct parent_map gcc_parent_map_5[] = {static const char *const gcc_parent_names_5[] = {"cxo" , -"dsi0pll_byteclk_src" , +"dsi0pllbyte" ,"core_bi_pll_test_se" , };
@@ -124,7 +124,7 @@ static const struct parent_map gcc_parent_map_6[] = {static const char *const gcc_parent_names_6[] = {"cxo" , -"dsi0_phy_pll_out_byteclk" , +"dsi0pllbyte" ,"core_bi_pll_test_se" , };
@@ -167,7 +167,7 @@ static const struct parent_map gcc_parent_map_9[] = {static const char *const gcc_parent_names_9[] = {"cxo" ,"gpll0_out_main" , -"dsi0_phy_pll_out_dsiclk" , +"dsi0pll" ,"gpll6_out_aux" ,"core_bi_pll_test_se" , };
@@ -204,7 +204,7 @@ static const struct parent_map gcc_parent_map_12[] = {static const char *const gcc_parent_names_12[] = {"cxo" , -"dsi0pll_pclk_src" , +"dsi0pll" ,"core_bi_pll_test_se" , };
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 233/529 RISC-V: fix funct4 definition for c.jalr in parse_asm.h
In reply to Greg Kroah-HartmanFrom: Heiko Stuebner <[email protected]>
[ Upstream commit a3775634f6da23f5511d0282d7e792cf606e5f3b ]
The opcode definition for c.jalr is
c.jalr c_rs1_n0 1..0=2 15..13=4 12=1 6..2=0
This means funct4 consisting of bit [15:12] is 1001b, so the value is 0x9.
--- arch/riscv/include/asm/parse_asm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/riscv/include/asm/parse_asm.h +1 -1
@@ -125,7 +125,7 @@#define FUNCT3_C_J 0xa000#define FUNCT3_C_JAL 0x2000#define FUNCT4_C_JR 0x8000 -#define FUNCT4_C_JALR 0xf000 +#define FUNCT4_C_JALR 0x9000#define FUNCT12_SRET 0x10200000
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 234/529 mtd: rawnand: sunxi: Fix the size of the last OOB region
In reply to Greg Kroah-HartmanFrom: Samuel Holland <[email protected]>
[ Upstream commit 34569d869532b54d6e360d224a0254dcdd6a1785 ]
The previous code assigned to the wrong structure member.
--- drivers/mtd/nand/raw/sunxi_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/mtd/nand/raw/sunxi_nand.c +1 -1
@@ -1587,7 +1587,7 @@ static int sunxi_nand_ooblayout_free(struct mtd_info *mtd, int section,if (section < ecc->steps) oobregion->length =4 ;else - oobregion->offset = mtd->oobsize - oobregion->offset; + oobregion->length = mtd->oobsize - oobregion->offset;return 0 ; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 235/529 Input: iqs269a - drop unused device node references
In reply to Greg Kroah-HartmanFrom: Jeff LaBundy <[email protected]>
[ Upstream commit 59bc9cb3b80abaa42643abede0d5db8477901d9c ]
Each call to device/fwnode_get_named_child_node() must be matched with a call to fwnode_handle_put() once the corresponding node is no longer in use. This ensures a reference count remains balanced in the case of dynamic device tree support.
Currently, the driver does not call fwnode_handle_put() on nested event nodes. This patch solves this problem by adding the missing instances of fwnode_handle_put().
As part of this change, the logic which parses each channel's key code is gently refactored in order to reduce the number of places from which fwnode_handle_put() is called.
--- drivers/input/misc/iqs269a.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
drivers/input/misc/iqs269a.c +11 -1
@@ -694,6 +694,7 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269,dev_err (&client->dev,"Invalid channel %u threshold: %u\n" , reg, val); +fwnode_handle_put (ev_node);return -EINVAL ; }
@@ -707,6 +708,7 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269,dev_err (&client->dev,"Invalid channel %u hysteresis: %u\n" , reg, val); +fwnode_handle_put (ev_node);return -EINVAL ; }
@@ -721,8 +723,16 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269, } } -if (fwnode_property_read_u32 (ev_node,"linux,code" , &val)) + error =fwnode_property_read_u32 (ev_node,"linux,code" , &val); +fwnode_handle_put (ev_node); +if (error == -EINVAL ) {continue ; + }else if (error) { +dev_err (&client->dev, +"Failed to read channel %u code: %d\n" , reg, + error); +return error; + }switch (reg) {case IQS269_CHx_HALL_ACTIVE:
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 236/529 Input: iqs269a - increase interrupt handler return delay
In reply to Greg Kroah-HartmanFrom: Jeff LaBundy <[email protected]>
[ Upstream commit e023cc4abde3c01b895660b0e5a8488deb36b8c1 ]
The time the device takes to deassert its RDY output following an I2C stop condition scales with the core clock frequency.
To prevent level-triggered interrupts from being reasserted after the interrupt handler returns, increase the time before returning to account for the worst-case delay (~140 us) plus margin.
--- drivers/input/misc/iqs269a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/input/misc/iqs269a.c +1 -1
@@ -153,7 +153,7 @@#define IQS269_PWR_MODE_POLL_SLEEP_US IQS269_ATI_POLL_SLEEP_US#define IQS269_PWR_MODE_POLL_TIMEOUT_US IQS269_ATI_POLL_TIMEOUT_US -#define iqs269_irq_wait () usleep_range(100, 150) +#define iqs269_irq_wait () usleep_range(200, 250)enum iqs269_local_cap_size {IQS269_LOCAL_CAP_SIZE_0 ,
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 237/529 Input: iqs269a - configure device with a single block write
In reply to Greg Kroah-HartmanFrom: Jeff LaBundy <[email protected]>
[ Upstream commit 3689abfc4e369a643d758a02fb9ad0b2403d6d6d ]
Unless it is being done as part of servicing a soft reset interrupt, configuring channels on-the-fly (as is the case when writing to the ati_trigger attribute) may cause GPIO3 (which reflects the state of touch for a selected channel) to be inadvertently asserted.
To solve this problem, follow the vendor's recommendation and write all channel configuration as well as the REDO_ATI register field as part of a single block write. This ensures the device has been told to re-calibrate itself following an I2C stop condition, after which sensing resumes and GPIO3 may be asserted.
--- drivers/input/misc/iqs269a.c | 98 ++++++++++++++---------------------- 1 file changed, 39 insertions(+), 59 deletions(-)
drivers/input/misc/iqs269a.c +39 -59
@@ -96,8 +96,6 @@#define IQS269_MISC_B_TRACKING_UI_ENABLE BIT(4)#define IQS269_MISC_B_FILT_STR_SLIDER GENMASK(1, 0) -#define IQS269_CHx_SETTINGS 0x8C -#define IQS269_CHx_ENG_A_MEAS_CAP_SIZE BIT(15)#define IQS269_CHx_ENG_A_RX_GND_INACTIVE BIT(13)#define IQS269_CHx_ENG_A_LOCAL_CAP_SIZE BIT(12)
@@ -245,6 +243,18 @@ struct iqs269_ver_info {u8 padding; } __packed; +struct iqs269_ch_reg { +u8 rx_enable; +u8 tx_enable; +__be16 engine_a; +__be16 engine_b; +__be16 ati_comp; +u8 thresh[3 ]; +u8 hyst; +u8 assoc_select; +u8 assoc_weight; +} __packed; +struct iqs269_sys_reg {__be16 general;u8 active;
@@ -266,18 +276,7 @@ struct iqs269_sys_reg {u8 timeout_swipe;u8 thresh_swipe;u8 redo_ati; -} __packed; - -struct iqs269_ch_reg { -u8 rx_enable; -u8 tx_enable; -__be16 engine_a; -__be16 engine_b; -__be16 ati_comp; -u8 thresh[3 ]; -u8 hyst; -u8 assoc_select; -u8 assoc_weight; +struct iqs269_ch_reg ch_reg[IQS269_NUM_CH ]; } __packed;struct iqs269_flags {
@@ -292,7 +291,6 @@ struct iqs269_private {struct regmap *regmap;struct mutex lock;struct iqs269_switch_desc switches[ARRAY_SIZE (iqs269_events)]; -struct iqs269_ch_reg ch_reg[IQS269_NUM_CH ];struct iqs269_sys_reg sys_reg;struct input_dev *keypad;struct input_dev *slider[IQS269_NUM_SL ];
@@ -307,6 +305,7 @@ struct iqs269_private {static int iqs269_ati_mode_set (struct iqs269_private *iqs269,unsigned int ch_num,unsigned int mode) { +struct iqs269_ch_reg *ch_reg = iqs269->sys_reg.ch_reg;u16 engine_a;if (ch_num >=IQS269_NUM_CH )
@@ -317,12 +316,12 @@ static int iqs269_ati_mode_set(struct iqs269_private *iqs269,mutex_lock (&iqs269->lock); - engine_a =be16_to_cpu (iqs269->ch_reg[ch_num].engine_a); + engine_a =be16_to_cpu (ch_reg[ch_num].engine_a); engine_a &= ~IQS269_CHx_ENG_A_ATI_MODE_MASK; engine_a |= (mode << IQS269_CHx_ENG_A_ATI_MODE_SHIFT); - iqs269->ch_reg[ch_num].engine_a =cpu_to_be16 (engine_a); + ch_reg[ch_num].engine_a =cpu_to_be16 (engine_a); iqs269->ati_current = false;mutex_unlock (&iqs269->lock);
@@ -333,13 +332,14 @@ static int iqs269_ati_mode_set(struct iqs269_private *iqs269,static int iqs269_ati_mode_get (struct iqs269_private *iqs269,unsigned int ch_num,unsigned int *mode) { +struct iqs269_ch_reg *ch_reg = iqs269->sys_reg.ch_reg;u16 engine_a;if (ch_num >=IQS269_NUM_CH )return -EINVAL ;mutex_lock (&iqs269->lock); - engine_a =be16_to_cpu (iqs269->ch_reg[ch_num].engine_a); + engine_a =be16_to_cpu (ch_reg[ch_num].engine_a);mutex_unlock (&iqs269->lock); engine_a &= IQS269_CHx_ENG_A_ATI_MODE_MASK;
@@ -351,6 +351,7 @@ static int iqs269_ati_mode_get(struct iqs269_private *iqs269,static int iqs269_ati_base_set (struct iqs269_private *iqs269,unsigned int ch_num,unsigned int base) { +struct iqs269_ch_reg *ch_reg = iqs269->sys_reg.ch_reg;u16 engine_b;if (ch_num >=IQS269_NUM_CH )
@@ -379,12 +380,12 @@ static int iqs269_ati_base_set(struct iqs269_private *iqs269,mutex_lock (&iqs269->lock); - engine_b =be16_to_cpu (iqs269->ch_reg[ch_num].engine_b); + engine_b =be16_to_cpu (ch_reg[ch_num].engine_b); engine_b &= ~IQS269_CHx_ENG_B_ATI_BASE_MASK; engine_b |= base; - iqs269->ch_reg[ch_num].engine_b =cpu_to_be16 (engine_b); + ch_reg[ch_num].engine_b =cpu_to_be16 (engine_b); iqs269->ati_current = false;mutex_unlock (&iqs269->lock);
@@ -395,13 +396,14 @@ static int iqs269_ati_base_set(struct iqs269_private *iqs269,static int iqs269_ati_base_get (struct iqs269_private *iqs269,unsigned int ch_num,unsigned int *base) { +struct iqs269_ch_reg *ch_reg = iqs269->sys_reg.ch_reg;u16 engine_b;if (ch_num >=IQS269_NUM_CH )return -EINVAL ;mutex_lock (&iqs269->lock); - engine_b =be16_to_cpu (iqs269->ch_reg[ch_num].engine_b); + engine_b =be16_to_cpu (ch_reg[ch_num].engine_b);mutex_unlock (&iqs269->lock);switch (engine_b & IQS269_CHx_ENG_B_ATI_BASE_MASK) {
@@ -429,6 +431,7 @@ static int iqs269_ati_base_get(struct iqs269_private *iqs269,static int iqs269_ati_target_set (struct iqs269_private *iqs269,unsigned int ch_num,unsigned int target) { +struct iqs269_ch_reg *ch_reg = iqs269->sys_reg.ch_reg;u16 engine_b;if (ch_num >=IQS269_NUM_CH )
@@ -439,12 +442,12 @@ static int iqs269_ati_target_set(struct iqs269_private *iqs269,mutex_lock (&iqs269->lock); - engine_b =be16_to_cpu (iqs269->ch_reg[ch_num].engine_b); + engine_b =be16_to_cpu (ch_reg[ch_num].engine_b); engine_b &= ~IQS269_CHx_ENG_B_ATI_TARGET_MASK; engine_b |= target /32 ; - iqs269->ch_reg[ch_num].engine_b =cpu_to_be16 (engine_b); + ch_reg[ch_num].engine_b =cpu_to_be16 (engine_b); iqs269->ati_current = false;mutex_unlock (&iqs269->lock);
@@ -455,13 +458,14 @@ static int iqs269_ati_target_set(struct iqs269_private *iqs269,static int iqs269_ati_target_get (struct iqs269_private *iqs269,unsigned int ch_num,unsigned int *target) { +struct iqs269_ch_reg *ch_reg = iqs269->sys_reg.ch_reg;u16 engine_b;if (ch_num >=IQS269_NUM_CH )return -EINVAL ;mutex_lock (&iqs269->lock); - engine_b =be16_to_cpu (iqs269->ch_reg[ch_num].engine_b); + engine_b =be16_to_cpu (ch_reg[ch_num].engine_b);mutex_unlock (&iqs269->lock); *target = (engine_b & IQS269_CHx_ENG_B_ATI_TARGET_MASK) *32 ;
@@ -531,13 +535,7 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269,if (fwnode_property_present (ch_node,"azoteq,slider1-select" )) iqs269->sys_reg.slider_select[1 ] |=BIT (reg); - ch_reg = &iqs269->ch_reg[reg]; - - error =regmap_raw_read (iqs269->regmap, - IQS269_CHx_SETTINGS + reg *sizeof (*ch_reg) /2 , - ch_reg,sizeof (*ch_reg)); -if (error) -return error; + ch_reg = &iqs269->sys_reg.ch_reg[reg]; error =iqs269_parse_mask (ch_node,"azoteq,rx-enable" , &ch_reg->rx_enable);
@@ -1042,10 +1040,8 @@ static int iqs269_parse_prop(struct iqs269_private *iqs269)static int iqs269_dev_init (struct iqs269_private *iqs269) { -struct iqs269_sys_reg *sys_reg = &iqs269->sys_reg; -struct iqs269_ch_reg *ch_reg;unsigned int val; -int error, i; +int error;mutex_lock (&iqs269->lock);
@@ -1055,27 +1051,8 @@ static int iqs269_dev_init(struct iqs269_private *iqs269)if (error) goto err_mutex; -for (i =0 ; i <IQS269_NUM_CH ; i++) { -if (!(sys_reg->active &BIT (i))) -continue ; - - ch_reg = &iqs269->ch_reg[i]; - - error =regmap_raw_write (iqs269->regmap, - IQS269_CHx_SETTINGS + i * -sizeof (*ch_reg) /2 , ch_reg, -sizeof (*ch_reg)); -if (error) - goto err_mutex; - } - -/* -* The REDO-ATI and ATI channel selection fields must be written in the -* same block write, so every field between registers 0x80 through 0x8B -* (inclusive) must be written as well. -*/ - error =regmap_raw_write (iqs269->regmap,IQS269_SYS_SETTINGS , sys_reg, -sizeof (*sys_reg)); + error =regmap_raw_write (iqs269->regmap,IQS269_SYS_SETTINGS , + &iqs269->sys_reg,sizeof (iqs269->sys_reg));if (error) goto err_mutex;
@@ -1349,6 +1326,7 @@ static ssize_t hall_bin_show(struct device *dev, struct device_attribute *attr, char *buf) { struct iqs269_private *iqs269 = dev_get_drvdata(dev); +struct iqs269_ch_reg *ch_reg = iqs269->sys_reg.ch_reg;struct i2c_client *client = iqs269->client;unsigned int val;int error;
@@ -1363,8 +1341,8 @@ static ssize_t hall_bin_show(struct device *dev,if (error)return error; -switch (iqs269->ch_reg[IQS269_CHx_HALL_ACTIVE].rx_enable & - iqs269->ch_reg[IQS269_CHx_HALL_INACTIVE].rx_enable) { +switch (ch_reg[IQS269_CHx_HALL_ACTIVE].rx_enable & + ch_reg[IQS269_CHx_HALL_INACTIVE].rx_enable) {case IQS269_HALL_PAD_R : val &=IQS269_CAL_DATA_A_HALL_BIN_R_MASK ; val >>=IQS269_CAL_DATA_A_HALL_BIN_R_SHIFT ;
@@ -1444,9 +1422,10 @@ static ssize_t rx_enable_show(struct device *dev, struct device_attribute *attr, char *buf) { struct iqs269_private *iqs269 = dev_get_drvdata(dev); +struct iqs269_ch_reg *ch_reg = iqs269->sys_reg.ch_reg;return scnprintf (buf,PAGE_SIZE ,"%u\n" , - iqs269->ch_reg[iqs269->ch_num].rx_enable); + ch_reg[iqs269->ch_num].rx_enable); } static ssize_t rx_enable_store(struct device *dev,
@@ -1454,6 +1433,7 @@ static ssize_t rx_enable_store(struct device *dev, size_t count) {struct iqs269_private *iqs269 =dev_get_drvdata (dev); +struct iqs269_ch_reg *ch_reg = iqs269->sys_reg.ch_reg;unsigned int val;int error;
@@ -1466,7 +1446,7 @@ static ssize_t rx_enable_store(struct device *dev,mutex_lock (&iqs269->lock); - iqs269->ch_reg[iqs269->ch_num].rx_enable = val; + ch_reg[iqs269->ch_num].rx_enable = val; iqs269->ati_current = false;mutex_unlock (&iqs269->lock);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 238/529 linux/kconfig.h: replace IF_ENABLED() with PTR_IF() in <linux/kernel.h>
In reply to Greg Kroah-HartmanFrom: Masahiro Yamada <[email protected]>
[ Upstream commit 0ab1438bad43d95877f848b7df551bd431680270 ]
<linux/kconfig.h> is included from all the kernel-space source files, including C, assembly, linker scripts. It is intended to contain a minimal set of macros to evaluate CONFIG options.
IF_ENABLED() is an intruder here because (x ? y : z) is C code, which should not be included from assembly files or linker scripts.
Also, <linux/kconfig.h> is no longer self-contained because NULL is defined in <linux/stddef.h>.
Move IF_ENABLED() out to <linux/kernel.h> as PTR_IF(). PTF_IF() takes the general boolean expression instead of a CONFIG option so that it fits better in <linux/kernel.h>.
Stable-dep-of: 18ab69c8ca56 ("Input: iqs269a - do not poll during suspend or resume")
--- drivers/pinctrl/pinctrl-ingenic.c | 3 +++ include/linux/kernel.h | 2 ++ 2 files changed, 5 insertions(+)
drivers/pinctrl/pinctrl-ingenic.c +3 -0
@@ -11,6 +11,7 @@#include <linux/gpio/driver.h> #include <linux/interrupt.h> #include <linux/io.h> +#include <linux/kernel.h> #include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/of_platform.h>
@@ -2826,6 +2827,8 @@ static int __init ingenic_pinctrl_probe(struct platform_device *pdev)return 0 ; } +#define IF_ENABLED (cfg, ptr) PTR_IF(IS_ENABLED(cfg), (ptr)) +static const struct of_device_id ingenic_pinctrl_of_match[] = { { .compatible ="ingenic,jz4740-pinctrl" , .data = &jz4740_chip_info }, { .compatible ="ingenic,jz4725b-pinctrl" , .data = &jz4725b_chip_info },
include/linux/kernel.h +2 -0
@@ -47,6 +47,8 @@*/ #define ARRAY_SIZE (arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) +#define PTR_IF (cond, ptr) ((cond) ? (ptr) : NULL) +#define u64_to_user_ptr (x) ( \ { \ typecheck(u64, (x)); \
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 239/529 clk: renesas: cpg-mssr: Fix use after free if cpg_mssr_common_init() failed
In reply to Greg Kroah-HartmanFrom: Alexey Khoroshilov <[email protected]>
[ Upstream commit fbfd614aeaa2853c2c575299dfe2458db8eff67e ]
If cpg_mssr_common_init() fails after assigning priv to global variable cpg_mssr_priv, it deallocates priv, but cpg_mssr_priv keeps dangling pointer that potentially can be used later.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/clk/renesas/renesas-cpg-mssr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/clk/renesas/renesas-cpg-mssr.c +2 -1
@@ -960,7 +960,6 @@ static int __init cpg_mssr_common_init(struct device *dev, goto out_err; } - cpg_mssr_priv = priv; priv->num_core_clks = info->num_total_core_clks; priv->num_mod_clks = info->num_hw_mod_clks; priv->last_dt_core_clk = info->last_dt_core_clk;
@@ -990,6 +989,8 @@ static int __init cpg_mssr_common_init(struct device *dev,if (error) goto out_err; + cpg_mssr_priv = priv; +return 0 ; out_err:
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 240/529 clk: renesas: cpg-mssr: Remove superfluous check in resume code
In reply to Greg Kroah-HartmanFrom: Geert Uytterhoeven <[email protected]>
[ Upstream commit 1c052043c79af5f70e80e2acd4dd70904ae08666 ]
When the code flow arrives at printing the error message in cpg_mssr_resume_noirq(), we know for sure that we are not running on an RZ/A Soc, as the code checked for that before.
--- drivers/clk/renesas/renesas-cpg-mssr.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/clk/renesas/renesas-cpg-mssr.c +2 -3
@@ -914,9 +914,8 @@ static int cpg_mssr_resume_noirq(struct device *dev) }if (!i) -dev_warn (dev,"Failed to enable %s%u[0x%x]\n" , - priv->reg_layout ==CLK_REG_LAYOUT_RZ_A ? -"STB" :"SMSTP" , reg, oldval & mask); +dev_warn (dev,"Failed to enable SMSTP%u[0x%x]\n" , reg, + oldval & mask); }return 0 ;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 241/529 clk: imx: avoid memory leak
In reply to Greg Kroah-HartmanFrom: Peng Fan <[email protected]>
[ Upstream commit f4419db4086e8c31821da14140e81498516a3c75 ]
In case imx_register_uart_clocks return early, the imx_uart_clocks memory will be no freed. So execute kfree always to avoid memory leak.
--- drivers/clk/imx/clk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/clk/imx/clk.c +2 -1
@@ -201,9 +201,10 @@ static int __init imx_clk_disable_uart(void)clk_disable_unprepare (imx_uart_clocks[i]);clk_put (imx_uart_clocks[i]); } -kfree (imx_uart_clocks); } +kfree (imx_uart_clocks); +return 0 ; }late_initcall_sync (imx_clk_disable_uart);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 242/529 Input: ads7846 - dont report pressure for ads7845
In reply to Greg Kroah-HartmanFrom: Luca Ellero <[email protected]>
[ Upstream commit d50584d783313c8b05b84d0b07a2142f1bde46dd ]
ADS7845 doesn't support pressure.
Avoid the following error reported by libinput-list-devices:
"ADS7845 Touchscreen: kernel bug: device has min == max on ABS_PRESSURE".
--- drivers/input/touchscreen/ads7846.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/input/touchscreen/ads7846.c +3 -2
@@ -1381,8 +1381,9 @@ static int ads7846_probe(struct spi_device *spi) pdata->y_min ? :0 , pdata->y_max ? :MAX_12BIT , 0, 0); -input_set_abs_params (input_dev,ABS_PRESSURE , - pdata->pressure_min, pdata->pressure_max,0 ,0 ); +if (ts->model !=7845 ) +input_set_abs_params (input_dev,ABS_PRESSURE , + pdata->pressure_min, pdata->pressure_max,0 ,0 );/* * Parse common framework properties. Must be done here to ensure the
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 243/529 Input: ads7846 - convert to full duplex
In reply to Greg Kroah-HartmanFrom: Oleksij Rempel <[email protected]>
[ Upstream commit 9c9509717b53e701469493a8d87ed42c7d782502 ]
Starting with 3eac5c7e44f3 ("Input: ads7846 - extend the driver for ads7845 controller support"), the ads7845 was partially converted to full duplex mode.
Since it is not touchscreen controller specific, it is better to extend this conversion to cover entire driver. This will reduce CPU load and make driver more readable.
Stable-dep-of: 13f82ca3878d ("Input: ads7846 - always set last command to PWRDOWN")
--- drivers/input/touchscreen/ads7846.c | 192 +++++++++------------------- 1 file changed, 62 insertions(+), 130 deletions(-)
drivers/input/touchscreen/ads7846.c +62 -130
@@ -63,19 +63,26 @@/* this driver doesn't aim at the peak continuous sample rate */ #define SAMPLE_BITS (8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */) -struct ts_event { +struct ads7846_buf { +u8 cmd;/* -* For portability, we can't read 12 bit values using SPI (which -* would make the controller deliver them as native byte order u16 -* with msbs zeroed). Instead, we read them as two 8-bit values, -* *** WHICH NEED BYTESWAPPING *** and range adjustment. +* This union is a temporary hack. The driver does an in-place +* endianness conversion. This will be cleaned up in the next +* patch. */ -u16 x; -u16 y; -u16 z1, z2; -bool ignore; -u8 x_buf[3 ]; -u8 y_buf[3 ]; +union { +__be16 data_be16; +u16 data; + }; +} __packed; + + +struct ts_event { +bool ignore; +struct ads7846_buf x; +struct ads7846_buf y; +struct ads7846_buf z1; +struct ads7846_buf z2; };/*
@@ -84,11 +91,12 @@ struct ts_event {* systems where main memory is not DMA-coherent (most non-x86 boards). */ struct ads7846_packet { -u8 read_x, read_y, read_z1, read_z2, pwrdown; -u16 dummy;/* for the pwrdown read */ -struct ts_event tc; -/* for ads7845 with mpc5121 psc spi we use 3-byte buffers */ -u8 read_x_cmd[3 ], read_y_cmd[3 ], pwrdown_cmd[3 ]; +struct ts_event tc; +struct ads7846_buf read_x_cmd; +struct ads7846_buf read_y_cmd; +struct ads7846_buf read_z1_cmd; +struct ads7846_buf read_z2_cmd; +struct ads7846_buf pwrdown_cmd; };struct ads7846 {
@@ -687,16 +695,9 @@ static int ads7846_get_value(struct ads7846 *ts, struct spi_message *m)int value;struct spi_transfer *t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list); +struct ads7846_buf *buf = t->rx_buf; -if (ts->model ==7845 ) { - value =be16_to_cpup ((__be16 *)&(((char *)t->rx_buf)[1 ])); - }else { -/* -* adjust: on-wire is a must-ignore bit, a BE12 value, then -* padding; built from two 8 bit values written msb-first. -*/ - value =be16_to_cpup ((__be16 *)t->rx_buf); - } + value =be16_to_cpup (&buf->data_be16);/* enforce ADC output is 12 bits width */ return (value >>3 ) &0xfff ;
@@ -706,8 +707,9 @@ static void ads7846_update_value(struct spi_message *m, int val) {struct spi_transfer *t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list); +struct ads7846_buf *buf = t->rx_buf; - *(u16 *)t->rx_buf = val; + buf->data = val; }static void ads7846_read_state (struct ads7846 *ts)
@@ -775,16 +777,14 @@ static void ads7846_report_state(struct ads7846 *ts)* from on-the-wire format as part of debouncing to get stable * readings. */ + x = packet->tc.x.data; + y = packet->tc.y.data;if (ts->model ==7845 ) { - x = *(u16 *)packet->tc.x_buf; - y = *(u16 *)packet->tc.y_buf; z1 =0 ; z2 =0 ; }else { - x = packet->tc.x; - y = packet->tc.y; - z1 = packet->tc.z1; - z2 = packet->tc.z2; + z1 = packet->tc.z1.data; + z2 = packet->tc.z2.data; }/* range filtering */
@@ -1002,26 +1002,11 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,spi_message_init (m); m->context = ts; -if (ts->model ==7845 ) { - packet->read_y_cmd[0 ] =READ_Y (vref); - packet->read_y_cmd[1 ] =0 ; - packet->read_y_cmd[2 ] =0 ; - x->tx_buf = &packet->read_y_cmd[0 ]; - x->rx_buf = &packet->tc.y_buf[0 ]; - x->len =3 ; -spi_message_add_tail (x, m); - }else { -/* y- still on; turn on only y+ (and ADC) */ - packet->read_y =READ_Y (vref); - x->tx_buf = &packet->read_y; - x->len =1 ; -spi_message_add_tail (x, m); - - x++; - x->rx_buf = &packet->tc.y; - x->len =2 ; -spi_message_add_tail (x, m); - } + packet->read_y_cmd.cmd =READ_Y (vref); + x->tx_buf = &packet->read_y_cmd; + x->rx_buf = &packet->tc.y; + x->len =3 ; +spi_message_add_tail (x, m);/* * The first sample after switching drivers can be low quality;
@@ -1031,15 +1016,11 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,if (pdata->settle_delay_usecs) { x->delay.value = pdata->settle_delay_usecs; x->delay.unit =SPI_DELAY_UNIT_USECS ; - x++; - x->tx_buf = &packet->read_y; - x->len =1 ; -spi_message_add_tail (x, m); - x++; + x->tx_buf = &packet->read_y_cmd; x->rx_buf = &packet->tc.y; - x->len =2 ; + x->len =3 ;spi_message_add_tail (x, m); }
@@ -1048,28 +1029,13 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,spi_message_init (m); m->context = ts; -if (ts->model ==7845 ) { - x++; - packet->read_x_cmd[0 ] =READ_X (vref); - packet->read_x_cmd[1 ] =0 ; - packet->read_x_cmd[2 ] =0 ; - x->tx_buf = &packet->read_x_cmd[0 ]; - x->rx_buf = &packet->tc.x_buf[0 ]; - x->len =3 ; -spi_message_add_tail (x, m); - }else { -/* turn y- off, x+ on, then leave in lowpower */ - x++; - packet->read_x =READ_X (vref); - x->tx_buf = &packet->read_x; - x->len =1 ; -spi_message_add_tail (x, m); - - x++; - x->rx_buf = &packet->tc.x; - x->len =2 ; -spi_message_add_tail (x, m); - } +/* turn y- off, x+ on, then leave in lowpower */ + x++; + packet->read_x_cmd.cmd =READ_X (vref); + x->tx_buf = &packet->read_x_cmd; + x->rx_buf = &packet->tc.x; + x->len =3 ; +spi_message_add_tail (x, m);/* ... maybe discard first sample ... */ if (pdata->settle_delay_usecs) {
@@ -1077,13 +1043,9 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts, x->delay.unit =SPI_DELAY_UNIT_USECS ; x++; - x->tx_buf = &packet->read_x; - x->len =1 ; -spi_message_add_tail (x, m); - - x++; + x->tx_buf = &packet->read_x_cmd; x->rx_buf = &packet->tc.x; - x->len =2 ; + x->len =3 ;spi_message_add_tail (x, m); }
@@ -1095,14 +1057,10 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts, m->context = ts; x++; - packet->read_z1 =READ_Z1 (vref); - x->tx_buf = &packet->read_z1; - x->len =1 ; -spi_message_add_tail (x, m); - - x++; + packet->read_z1_cmd.cmd =READ_Z1 (vref); + x->tx_buf = &packet->read_z1_cmd; x->rx_buf = &packet->tc.z1; - x->len =2 ; + x->len =3 ;spi_message_add_tail (x, m);/* ... maybe discard first sample ... */
@@ -1111,13 +1069,9 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts, x->delay.unit =SPI_DELAY_UNIT_USECS ; x++; - x->tx_buf = &packet->read_z1; - x->len =1 ; -spi_message_add_tail (x, m); - - x++; + x->tx_buf = &packet->read_z1_cmd; x->rx_buf = &packet->tc.z1; - x->len =2 ; + x->len =3 ;spi_message_add_tail (x, m); }
@@ -1127,14 +1081,10 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts, m->context = ts; x++; - packet->read_z2 =READ_Z2 (vref); - x->tx_buf = &packet->read_z2; - x->len =1 ; -spi_message_add_tail (x, m); - - x++; + packet->read_z2_cmd.cmd =READ_Z2 (vref); + x->tx_buf = &packet->read_z2_cmd; x->rx_buf = &packet->tc.z2; - x->len =2 ; + x->len =3 ;spi_message_add_tail (x, m);/* ... maybe discard first sample ... */
@@ -1143,13 +1093,9 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts, x->delay.unit =SPI_DELAY_UNIT_USECS ; x++; - x->tx_buf = &packet->read_z2; - x->len =1 ; -spi_message_add_tail (x, m); - - x++; + x->tx_buf = &packet->read_z2_cmd; x->rx_buf = &packet->tc.z2; - x->len =2 ; + x->len =3 ;spi_message_add_tail (x, m); } }
@@ -1160,24 +1106,10 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,spi_message_init (m); m->context = ts; -if (ts->model ==7845 ) { - x++; - packet->pwrdown_cmd[0 ] =PWRDOWN ; - packet->pwrdown_cmd[1 ] =0 ; - packet->pwrdown_cmd[2 ] =0 ; - x->tx_buf = &packet->pwrdown_cmd[0 ]; - x->len =3 ; - }else { - x++; - packet->pwrdown =PWRDOWN ; - x->tx_buf = &packet->pwrdown; - x->len =1 ; -spi_message_add_tail (x, m); - - x++; - x->rx_buf = &packet->dummy; - x->len =2 ; - } + x++; + packet->pwrdown_cmd.cmd =PWRDOWN ; + x->tx_buf = &packet->pwrdown_cmd; + x->len =3 ;CS_CHANGE (*x);spi_message_add_tail (x, m);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 244/529 Input: ads7846 - convert to one message
In reply to Greg Kroah-HartmanFrom: Oleksij Rempel <[email protected]>
[ Upstream commit 6965eece2a89c3f1d00881c6052ee1e987870c08 ]
Convert multiple full duplex transfers in to a single transfer to reduce CPU load.
Current driver version support following filtering modes:
- ads7846_no_filter() - not filtered
- ads7846_debounce_filter() - driver specific debounce filter
- pdata->filter - platform specific debounce filter (do any platform provides such filter?)
Without filter this HW is not really usable, since the physic of resistive touchscreen can provide some bounce effects. With driver internal filter, we have constant amount of retries + debounce retries if some anomaly was detected.
High amount of tiny SPI transfers is the primer reason of high CPU load and interrupt frequency.
This patch create one SPI transfer with all fields and not optional retires. If bounce anomaly was detected, we will make more transfer if needed.
Without this patch, we will get about 10% CPU load on iMX6S on pen-down event. For example by holding stylus on the screen.
With this patch, depending in the amount of retries, the CPU load will be 1% with "ti,debounce-rep = <3>".
One buffer transfer allows us to use PIO FIFO or DMA engine, depending on the platform.
Stable-dep-of: 13f82ca3878d ("Input: ads7846 - always set last command to PWRDOWN")
--- drivers/input/touchscreen/ads7846.c | 376 ++++++++++++++-------------- 1 file changed, 193 insertions(+), 183 deletions(-)
drivers/input/touchscreen/ads7846.c +193 -183
@@ -65,24 +65,13 @@struct ads7846_buf {u8 cmd; -/* -* This union is a temporary hack. The driver does an in-place -* endianness conversion. This will be cleaned up in the next -* patch. -*/ -union { -__be16 data_be16; -u16 data; - }; +__be16 data; } __packed; - -struct ts_event { -bool ignore; -struct ads7846_buf x; -struct ads7846_buf y; -struct ads7846_buf z1; -struct ads7846_buf z2; +struct ads7846_buf_layout { +unsigned int offset; +unsigned int count; +unsigned int skip; };/*
@@ -91,12 +80,18 @@ struct ts_event {* systems where main memory is not DMA-coherent (most non-x86 boards). */ struct ads7846_packet { -struct ts_event tc; -struct ads7846_buf read_x_cmd; -struct ads7846_buf read_y_cmd; -struct ads7846_buf read_z1_cmd; -struct ads7846_buf read_z2_cmd; +unsigned int count; +unsigned int count_skip; +unsigned int cmds; +unsigned int last_cmd_idx; +struct ads7846_buf_layout l[5 ]; +struct ads7846_buf *rx; +struct ads7846_buf *tx; +struct ads7846_buf pwrdown_cmd; + +bool ignore; +u16 x, y, z1, z2; };struct ads7846 {
@@ -195,7 +190,6 @@ struct ads7846 {#define READ_Y (vref) (READ_12BIT_DFR(y, 1, vref))#define READ_Z1 (vref) (READ_12BIT_DFR(z1, 1, vref))#define READ_Z2 (vref) (READ_12BIT_DFR(z2, 1, vref)) -#define READ_X (vref) (READ_12BIT_DFR(x, 1, vref))#define PWRDOWN (READ_12BIT_DFR(y, 0, 0))/* LAST */
@@ -208,6 +202,21 @@ struct ads7846 {#define REF_ON (READ_12BIT_DFR(x, 1, 1))#define REF_OFF (READ_12BIT_DFR(y, 0, 0)) +/* Order commands in the most optimal way to reduce Vref switching and +* settling time: +* Measure: X; Vref: X+, X-; IN: Y+ +* Measure: Y; Vref: Y+, Y-; IN: X+ +* Measure: Z1; Vref: Y+, X-; IN: X+ +* Measure: Z2; Vref: Y+, X-; IN: Y- +*/ +enum ads7846_cmds { +ADS7846_X , +ADS7846_Y , +ADS7846_Z1 , +ADS7846_Z2 , +ADS7846_PWDOWN , +}; +static int get_pendown_state (struct ads7846 *ts) {if (ts->get_pendown_state)
@@ -690,26 +699,109 @@ static int ads7846_no_filter(void *ads, int data_idx, int *val)return ADS7846_FILTER_OK ; } -static int ads7846_get_value (struct ads7846 *ts,struct spi_message *m) +static int ads7846_get_value (struct ads7846_buf *buf) {int value; -struct spi_transfer *t = - list_entry(m->transfers.prev, struct spi_transfer, transfer_list); -struct ads7846_buf *buf = t->rx_buf; - value =be16_to_cpup (&buf->data_be16); + value =be16_to_cpup (&buf->data);/* enforce ADC output is 12 bits width */ return (value >>3 ) &0xfff ; } -static void ads7846_update_value (struct spi_message *m,int val) +static void ads7846_set_cmd_val (struct ads7846 *ts,enum ads7846_cmds cmd_idx, +u16 val) +{ +struct ads7846_packet *packet = ts->packet; + +switch (cmd_idx) { +case ADS7846_Y : + packet->y = val; +break ; +case ADS7846_X : + packet->x = val; +break ; +case ADS7846_Z1 : + packet->z1 = val; +break ; +case ADS7846_Z2 : + packet->z2 = val; +break ; +default : +WARN_ON_ONCE (1 ); + } +} + +static u8 ads7846_get_cmd (enum ads7846_cmds cmd_idx,int vref) +{ +switch (cmd_idx) { +case ADS7846_Y : +return READ_Y (vref); +case ADS7846_X : +return READ_X (vref); + +/* 7846 specific commands */ +case ADS7846_Z1 : +return READ_Z1 (vref); +case ADS7846_Z2 : +return READ_Z2 (vref); +case ADS7846_PWDOWN : +return PWRDOWN ; +default : +WARN_ON_ONCE (1 ); + } + +return 0 ; +} + +static bool ads7846_cmd_need_settle (enum ads7846_cmds cmd_idx) +{ +switch (cmd_idx) { +case ADS7846_X : +case ADS7846_Y : +case ADS7846_Z1 : +case ADS7846_Z2 : +return true; +case ADS7846_PWDOWN : +return false; +default : +WARN_ON_ONCE (1 ); + } + +return false; +} + +static int ads7846_filter (struct ads7846 *ts) { -struct spi_transfer *t = - list_entry(m->transfers.prev, struct spi_transfer, transfer_list); -struct ads7846_buf *buf = t->rx_buf; +struct ads7846_packet *packet = ts->packet; +int action; +int val; +unsigned int cmd_idx, b; - buf->data = val; + packet->ignore = false; +for (cmd_idx = packet->last_cmd_idx; cmd_idx < packet->cmds -1 ; cmd_idx++) { +struct ads7846_buf_layout *l = &packet->l[cmd_idx]; + + packet->last_cmd_idx = cmd_idx; + +for (b = l->skip; b < l->count; b++) { + val =ads7846_get_value (&packet->rx[l->offset + b]); + + action = ts->filter (ts->filter_data, cmd_idx, &val); +if (action ==ADS7846_FILTER_REPEAT ) { +if (b == l->count -1 ) +return -EAGAIN ; + }else if (action ==ADS7846_FILTER_OK ) { +ads7846_set_cmd_val (ts, cmd_idx, val); +break ; + }else { + packet->ignore = true; +return 0 ; + } + } + } + +return 0 ; }static void ads7846_read_state (struct ads7846 *ts)
@@ -717,52 +809,26 @@ static void ads7846_read_state(struct ads7846 *ts)struct ads7846_packet *packet = ts->packet;struct spi_message *m;int msg_idx =0 ; -int val; -int action;int error; -while (msg_idx < ts->msg_count) { + packet->last_cmd_idx =0 ; +while (true) { ts->wait_for_sync (); m = &ts->msg[msg_idx]; error =spi_sync (ts->spi, m);if (error) {dev_err (&ts->spi->dev,"spi_sync --> %d\n" , error); - packet->tc.ignore = true; + packet->ignore = true;return ; } -/* -* Last message is power down request, no need to convert -* or filter the value. -*/ -if (msg_idx < ts->msg_count -1 ) { - - val =ads7846_get_value (ts, m); - - action = ts->filter (ts->filter_data, msg_idx, &val); -switch (action) { -case ADS7846_FILTER_REPEAT : -continue ; - -case ADS7846_FILTER_IGNORE : - packet->tc.ignore = true; - msg_idx = ts->msg_count -1 ; -continue ; - -case ADS7846_FILTER_OK : -ads7846_update_value (m, val); - packet->tc.ignore = false; - msg_idx++; -break ; + error =ads7846_filter (ts); +if (error) +continue ; -default : -BUG (); - } - }else { - msg_idx++; - } +return ; } }
@@ -772,19 +838,14 @@ static void ads7846_report_state(struct ads7846 *ts)unsigned int Rt;u16 x, y, z1, z2; -/* -* ads7846_get_value() does in-place conversion (including byte swap) -* from on-the-wire format as part of debouncing to get stable -* readings. -*/ - x = packet->tc.x.data; - y = packet->tc.y.data; + x = packet->x; + y = packet->y;if (ts->model ==7845 ) { z1 =0 ; z2 =0 ; }else { - z1 = packet->tc.z1.data; - z2 = packet->tc.z2.data; + z1 = packet->z1; + z2 = packet->z2; }/* range filtering */
@@ -817,9 +878,9 @@ static void ads7846_report_state(struct ads7846 *ts)* the maximum. Don't report it to user space, repeat at least * once more the measurement */ -if (packet->tc.ignore || Rt > ts->pressure_max) { +if (packet->ignore || Rt > ts->pressure_max) {dev_vdbg (&ts->spi->dev,"ignored %d pressure %d\n" , - packet->tc.ignore, Rt); + packet->ignore, Rt);return ; }
@@ -980,13 +1041,59 @@ static int ads7846_setup_pendown(struct spi_device *spi,* Set up the transfers to read touchscreen state; this assumes we * use formula #2 for pressure, not #3. */ -static void ads7846_setup_spi_msg (struct ads7846 *ts, +static int ads7846_setup_spi_msg (struct ads7846 *ts,const struct ads7846_platform_data *pdata) {struct spi_message *m = &ts->msg[0 ];struct spi_transfer *x = ts->xfer;struct ads7846_packet *packet = ts->packet;int vref = pdata->keep_vref_on; +unsigned int count, offset =0 ; +unsigned int cmd_idx, b; +unsigned long time; +size_t size =0 ; + +/* time per bit */ + time =NSEC_PER_SEC / ts->spi->max_speed_hz; + + count = pdata->settle_delay_usecs *NSEC_PER_USEC / time; + packet->count_skip =DIV_ROUND_UP (count,24 ); + +if (ts->debounce_max && ts->debounce_rep) +/* ads7846_debounce_filter() is making ts->debounce_rep + 2 +* reads. So we need to get all samples for normal case. */ + packet->count = ts->debounce_rep +2 ; +else + packet->count =1 ; + +if (ts->model ==7846 ) + packet->cmds =5 ;/* x, y, z1, z2, pwdown */ +else + packet->cmds =3 ;/* x, y, pwdown */ + +for (cmd_idx =0 ; cmd_idx < packet->cmds; cmd_idx++) { +struct ads7846_buf_layout *l = &packet->l[cmd_idx]; +unsigned int max_count; + +if (ads7846_cmd_need_settle (cmd_idx)) + max_count = packet->count + packet->count_skip; +else + max_count = packet->count; + + l->offset = offset; + offset += max_count; + l->count = max_count; + l->skip = packet->count_skip; + size +=sizeof (*packet->tx) * max_count; + } + + packet->tx =devm_kzalloc (&ts->spi->dev, size,GFP_KERNEL ); +if (!packet->tx) +return -ENOMEM ; + + packet->rx =devm_kzalloc (&ts->spi->dev, size,GFP_KERNEL ); +if (!packet->rx) +return -ENOMEM ;if (ts->model ==7873 ) {/*
@@ -1002,117 +1109,20 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,spi_message_init (m); m->context = ts; - packet->read_y_cmd.cmd =READ_Y (vref); - x->tx_buf = &packet->read_y_cmd; - x->rx_buf = &packet->tc.y; - x->len =3 ; -spi_message_add_tail (x, m); +for (cmd_idx =0 ; cmd_idx < packet->cmds; cmd_idx++) { +struct ads7846_buf_layout *l = &packet->l[cmd_idx]; +u8 cmd =ads7846_get_cmd (cmd_idx, vref); -/* -* The first sample after switching drivers can be low quality; -* optionally discard it, using a second one after the signals -* have had enough time to stabilize. -*/ -if (pdata->settle_delay_usecs) { - x->delay.value = pdata->settle_delay_usecs; - x->delay.unit =SPI_DELAY_UNIT_USECS ; - x++; - - x->tx_buf = &packet->read_y_cmd; - x->rx_buf = &packet->tc.y; - x->len =3 ; -spi_message_add_tail (x, m); +for (b =0 ; b < l->count; b++) + packet->tx[l->offset + b].cmd = cmd; } - ts->msg_count++; - m++; -spi_message_init (m); - m->context = ts; - -/* turn y- off, x+ on, then leave in lowpower */ - x++; - packet->read_x_cmd.cmd =READ_X (vref); - x->tx_buf = &packet->read_x_cmd; - x->rx_buf = &packet->tc.x; - x->len =3 ; + x->tx_buf = packet->tx; + x->rx_buf = packet->rx; + x->len = size;spi_message_add_tail (x, m); -/* ... maybe discard first sample ... */ -if (pdata->settle_delay_usecs) { - x->delay.value = pdata->settle_delay_usecs; - x->delay.unit =SPI_DELAY_UNIT_USECS ; - - x++; - x->tx_buf = &packet->read_x_cmd; - x->rx_buf = &packet->tc.x; - x->len =3 ; -spi_message_add_tail (x, m); - } - -/* turn y+ off, x- on; we'll use formula #2 */ -if (ts->model ==7846 ) { - ts->msg_count++; - m++; -spi_message_init (m); - m->context = ts; - - x++; - packet->read_z1_cmd.cmd =READ_Z1 (vref); - x->tx_buf = &packet->read_z1_cmd; - x->rx_buf = &packet->tc.z1; - x->len =3 ; -spi_message_add_tail (x, m); - -/* ... maybe discard first sample ... */ -if (pdata->settle_delay_usecs) { - x->delay.value = pdata->settle_delay_usecs; - x->delay.unit =SPI_DELAY_UNIT_USECS ; - - x++; - x->tx_buf = &packet->read_z1_cmd; - x->rx_buf = &packet->tc.z1; - x->len =3 ; -spi_message_add_tail (x, m); - } - - ts->msg_count++; - m++; -spi_message_init (m); - m->context = ts; - - x++; - packet->read_z2_cmd.cmd =READ_Z2 (vref); - x->tx_buf = &packet->read_z2_cmd; - x->rx_buf = &packet->tc.z2; - x->len =3 ; -spi_message_add_tail (x, m); - -/* ... maybe discard first sample ... */ -if (pdata->settle_delay_usecs) { - x->delay.value = pdata->settle_delay_usecs; - x->delay.unit =SPI_DELAY_UNIT_USECS ; - - x++; - x->tx_buf = &packet->read_z2_cmd; - x->rx_buf = &packet->tc.z2; - x->len =3 ; -spi_message_add_tail (x, m); - } - } - -/* power down */ - ts->msg_count++; - m++; -spi_message_init (m); - m->context = ts; - - x++; - packet->pwrdown_cmd.cmd =PWRDOWN ; - x->tx_buf = &packet->pwrdown_cmd; - x->len =3 ; - -CS_CHANGE (*x); -spi_message_add_tail (x, m); +return 0 ; }#ifdef CONFIG_OF
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 245/529 Input: ads7846 - always set last command to PWRDOWN
In reply to Greg Kroah-HartmanFrom: Luca Ellero <[email protected]>
[ Upstream commit 13f82ca3878db8284a70ef9711d7f710a31eb562 ]
Controllers that report pressure (e.g. ADS7846) use 5 commands and the correct sequence is READ_X, READ_Y, READ_Z1, READ_Z2, PWRDOWN.
Controllers that don't report pressure (e.g. ADS7845/ADS7843) use only 3 commands and the correct sequence should be READ_X, READ_Y, PWRDOWN. But the sequence sent was incorrect: READ_X, READ_Y, READ_Z1.
Fix this by setting the third (and last) command to PWRDOWN.
--- drivers/input/touchscreen/ads7846.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
drivers/input/touchscreen/ads7846.c +9 -1
@@ -1075,6 +1075,9 @@ static int ads7846_setup_spi_msg(struct ads7846 *ts,struct ads7846_buf_layout *l = &packet->l[cmd_idx];unsigned int max_count; +if (cmd_idx == packet->cmds -1 ) + cmd_idx =ADS7846_PWDOWN ; +if (ads7846_cmd_need_settle (cmd_idx)) max_count = packet->count + packet->count_skip;else
@@ -1111,7 +1114,12 @@ static int ads7846_setup_spi_msg(struct ads7846 *ts,for (cmd_idx =0 ; cmd_idx < packet->cmds; cmd_idx++) {struct ads7846_buf_layout *l = &packet->l[cmd_idx]; -u8 cmd =ads7846_get_cmd (cmd_idx, vref); +u8 cmd; + +if (cmd_idx == packet->cmds -1 ) + cmd_idx =ADS7846_PWDOWN ; + + cmd =ads7846_get_cmd (cmd_idx, vref);for (b =0 ; b < l->count; b++) packet->tx[l->offset + b].cmd = cmd;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 246/529 Input: ads7846 - dont check penirq immediately for 7845
In reply to Greg Kroah-HartmanFrom: Luca Ellero <[email protected]>
[ Upstream commit fa9f4275b20ec7b2a8fb05c66362d10b36f9efec ]
To discard false readings, one should use "ti,penirq-recheck-delay-usecs". Checking get_pendown_state() at the beginning, most of the time fails causing malfunctioning.
--- drivers/input/touchscreen/ads7846.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-)
drivers/input/touchscreen/ads7846.c +1 -7
@@ -852,14 +852,8 @@ static void ads7846_report_state(struct ads7846 *ts)if (x ==MAX_12BIT ) x =0 ; -if (ts->model ==7843 ) { +if (ts->model ==7843 || ts->model ==7845 ) { Rt = ts->pressure_max /2 ; - }else if (ts->model ==7845 ) { -if (get_pendown_state (ts)) - Rt = ts->pressure_max /2 ; -else - Rt =0 ; -dev_vdbg (&ts->spi->dev,"x/y: %d/%d, PD %d\n" , x, y, Rt); }else if (likely (x && z1)) {/* compute touch pressure resistance using equation #2 */ Rt = z2;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 247/529 clk: qcom: gpucc-sc7180: fix clk_dis_wait being programmed for CX GDSC
In reply to Greg Kroah-HartmanFrom: Dmitry Baryshkov <[email protected]>
[ Upstream commit 658c82caffa042b351f5a1b6325819297a951a04 ]
The gdsc_init() function will rewrite the CLK_DIS_WAIT field while registering the GDSC (writing the value 0x2 by default). This will override the setting done in the driver's probe function.
Set cx_gdsc.clk_dis_wait_val to 8 to follow the intention of the probe function.
--- drivers/clk/qcom/gpucc-sc7180.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-)
drivers/clk/qcom/gpucc-sc7180.c +1 -6
@@ -21,8 +21,6 @@#define CX_GMU_CBCR_SLEEP_SHIFT 4#define CX_GMU_CBCR_WAKE_MASK 0xF#define CX_GMU_CBCR_WAKE_SHIFT 8 -#define CLK_DIS_WAIT_SHIFT 12 -#define CLK_DIS_WAIT_MASK (0xf << CLK_DIS_WAIT_SHIFT)enum {P_BI_TCXO ,
@@ -163,6 +161,7 @@ static struct clk_branch gpu_cc_cxo_clk = {static struct gdsc cx_gdsc = { .gdscr =0x106c , .gds_hw_ctrl =0x1540 , + .clk_dis_wait_val =8 , .pd = { .name ="cx_gdsc" , },
@@ -245,10 +244,6 @@ static int gpu_cc_sc7180_probe(struct platform_device *pdev) value =0xF <<CX_GMU_CBCR_WAKE_SHIFT |0xF <<CX_GMU_CBCR_SLEEP_SHIFT ;regmap_update_bits (regmap,0x1098 , mask, value); -/* Configure clk_dis_wait for gpu_cx_gdsc */ -regmap_update_bits (regmap,0x106c ,CLK_DIS_WAIT_MASK , -8 <<CLK_DIS_WAIT_SHIFT ); -return qcom_cc_really_probe (pdev, &gpu_cc_sc7180_desc, regmap); }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 248/529 clk: qcom: gpucc-sdm845: fix clk_dis_wait being programmed for CX GDSC
In reply to Greg Kroah-HartmanFrom: Dmitry Baryshkov <[email protected]>
[ Upstream commit cb81719e3c1165ef1bc33137dc628f750eed8ea4 ]
The gdsc_init() function will rewrite the CLK_DIS_WAIT field while registering the GDSC (writing the value 0x2 by default). This will override the setting done in the driver's probe function.
Set cx_gdsc.clk_dis_wait_val to 8 to follow the intention of the probe function.
--- drivers/clk/qcom/gpucc-sdm845.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-)
drivers/clk/qcom/gpucc-sdm845.c +1 -6
@@ -22,8 +22,6 @@#define CX_GMU_CBCR_SLEEP_SHIFT 4#define CX_GMU_CBCR_WAKE_MASK 0xf#define CX_GMU_CBCR_WAKE_SHIFT 8 -#define CLK_DIS_WAIT_SHIFT 12 -#define CLK_DIS_WAIT_MASK (0xf << CLK_DIS_WAIT_SHIFT)enum {P_BI_TCXO ,
@@ -124,6 +122,7 @@ static struct clk_branch gpu_cc_cxo_clk = {static struct gdsc gpu_cx_gdsc = { .gdscr =0x106c , .gds_hw_ctrl =0x1540 , + .clk_dis_wait_val =0x8 , .pd = { .name ="gpu_cx_gdsc" , },
@@ -196,10 +195,6 @@ static int gpu_cc_sdm845_probe(struct platform_device *pdev) value =0xf <<CX_GMU_CBCR_WAKE_SHIFT |0xf <<CX_GMU_CBCR_SLEEP_SHIFT ;regmap_update_bits (regmap,0x1098 , mask, value); -/* Configure clk_dis_wait for gpu_cx_gdsc */ -regmap_update_bits (regmap,0x106c ,CLK_DIS_WAIT_MASK , -8 <<CLK_DIS_WAIT_SHIFT ); -return qcom_cc_really_probe (pdev, &gpu_cc_sdm845_desc, regmap); }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 249/529 powerpc/powernv/ioda: Skip unallocated resources when mapping to PE
In reply to Greg Kroah-HartmanFrom: Frederic Barrat <[email protected]>
[ Upstream commit e64e71056f323a1e178dccf04d4c0f032d84436c ]
pnv_ioda_setup_pe_res() calls opal to map a resource with a PE. However, the code assumes the resource is allocated and it uses the resource address to find out the segment(s) which need to be mapped to the PE. In the unlikely case where the resource hasn't been allocated, the computation for the segment number is garbage, which can lead to invalid memory access and potentially a kernel crash, such as:
[ ] pci_bus 0002:02: Configuring PE for bus
[ ] pci 0002:02 : [PE# fc] Secondary bus 0x0000000000000002..0x0000000000000002 associated with PE#fc
[ ] BUG: Kernel NULL pointer dereference on write at 0x00000000
[ ] Faulting instruction address: 0xc00000000005eac4
[ ] Oops: Kernel access of bad area, sig: 7 [#1]
[ ] LE PAGE_SIZE=64K MMU=Radix SMP NR_CPUS=2048 NUMA PowerNV
[ ] Modules linked in:
[ ] CPU: 12 PID: 1 Comm: swapper/20 Not tainted 5.10.50-openpower1 #2
[ ] NIP: c00000000005eac4 LR: c00000000005ea44 CTR: 0000000030061b9c
[ ] REGS: c000200007383650 TRAP: 0300 Not tainted (5.10.50-openpower1)
[ ] MSR: 9000000000009033 <SF,HV,EE,ME,IR,DR,RI,LE> CR: 44000224 XER: 20040000 [ ] CFAR: c00000000005eaa0 DAR: 0000000000000000 DSISR: 02080000 IRQMASK: 0 [ ] GPR00: c00000000005dd98 c0002000073838e0 c00000000185de00 c000200fff018960 [ ] GPR04: 00000000000000fc 0000000000000003 0000000000000000 0000000000000000 [ ] GPR08: 0000000000000000 0000000000000000 0000000000000000 9000000000001033 [ ] GPR12: 0000000031cb0000 c000000ffffe6a80 c000000000010a58 0000000000000000 [ ] GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 [ ] GPR20: 0000000000000000 0000000000000000 0000000000000000 c00000000711e200 [ ] GPR24: 0000000000000100 c000200009501120 c00020000cee2800 00000000000003ff [ ] GPR28: c000200fff018960 0000000000000000 c000200ffcb7fd00 0000000000000000 [ ] NIP [c00000000005eac4] pnv_ioda_setup_pe_res+0x94/0x1a0
[ ] LR [c00000000005ea44] pnv_ioda_setup_pe_res+0x14/0x1a0
[ ] Call Trace:
[ ] [c0002000073838e0] [c00000000005eb98] pnv_ioda_setup_pe_res+0x168/0x1a0 (unreliable) [ ] [c000200007383970] [c00000000005dd98] pnv_pci_ioda_dma_dev_setup+0x43c/0x970 [ ] [c000200007383a60] [c000000000032cdc] pcibios_bus_add_device+0x78/0x18c [ ] [c000200007383aa0] [c00000000028f2bc] pci_bus_add_device+0x28/0xbc
[ ] [c000200007383b10] [c00000000028f3a0] pci_bus_add_devices+0x50/0x7c
[ ] [c000200007383b50] [c00000000028f3c4] pci_bus_add_devices+0x74/0x7c
[ ] [c000200007383b90] [c00000000028f3c4] pci_bus_add_devices+0x74/0x7c
[ ] [c000200007383bd0] [c00000000069ad0c] pcibios_init+0xf0/0x104
[ ] [c000200007383c50] [c0000000000106d8] do_one_initcall+0x84/0x1c4
[ ] [c000200007383d20] [c0000000006910b8] kernel_init_freeable+0x264/0x268 [ ] [c000200007383dc0] [c000000000010a68] kernel_init+0x18/0x138
[ ] [c000200007383e20] [c00000000000cbfc] ret_from_kernel_thread+0x5c/0x80 [ ] Instruction dump:
[ ] 7f89e840 409d000c 7fbbf840 409c000c 38210090 4848f448 809c002c e95e0120 [ ] 7ba91764 38a00003 57a7043e 38c00000 <7c8a492e> 5484043e e87e0018 4bff23bd
Hitting the problem is not that easy. It was seen with a (semi-bogus) PCI device with a class code of 0. The generic PCI framework doesn't allocate resources in such a case.
The patch is simply skipping resources which are still flagged with IORESOURCE_UNSET.
We don't have the problem with 64-bit mem resources, as the address of the resource is checked to be within the range of the 64-bit mmio window. See pnv_ioda_reserve_dev_m64_pe() and pnv_pci_is_m64().
--- arch/powerpc/platforms/powernv/pci-ioda.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
arch/powerpc/platforms/powernv/pci-ioda.c +2 -1
@@ -2260,7 +2260,8 @@ static void pnv_ioda_setup_pe_res(struct pnv_ioda_pe *pe,int index;int64_t rc; -if (!res || !res->flags || res->start > res->end) +if (!res || !res->flags || res->start > res->end || + res->flags &IORESOURCE_UNSET )return ;if (res->flags &IORESOURCE_IO ) {
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 250/529 clk: Honor CLK_OPS_PARENT_ENABLE in clk_core_is_enabled()
In reply to Greg Kroah-HartmanFrom: Chen-Yu Tsai <[email protected]>
[ Upstream commit 79200d5851c8e7179f68a4a6f162d8f1bde4986f ]
In the previous commits that added CLK_OPS_PARENT_ENABLE, support for this flag was only added to rate change operations (rate setting and reparent) and disabling unused subtree. It was not added to the clock gate related operations. Any hardware driver that needs it for these operations will either see bogus results, or worse, hang.
This has been seen on MT8192 and MT8195, where the imp_ii2_* clk drivers set this, but dumping debugfs clk_summary would cause it to hang.
Prepare parent on prepare and enable parent on enable dependencies are already handled automatically by the core as part of its sequencing. Whether the case for "enable parent on prepare" should be supported by this flag or not is not clear, and thus ignored for now.
This change solely fixes the handling of clk_core_is_enabled, i.e. enabling the parent clock when reading the hardware state. Unfortunately clk_core_is_enabled is called in a variety of places, sometimes with the enable clock already held. To avoid deadlocking, the core will ignore readouts and just return false if CLK_OPS_PARENT_ENABLE is set but the parent isn't currently enabled.
--- drivers/clk/clk.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
drivers/clk/clk.c +11 -0
@@ -251,6 +251,17 @@ static bool clk_core_is_enabled(struct clk_core *core) } } +/* +* This could be called with the enable lock held, or from atomic +* context. If the parent isn't enabled already, we can't do +* anything here. We can also assume this clock isn't enabled. +*/ +if ((core->flags &CLK_OPS_PARENT_ENABLE ) && core->parent) +if (!clk_core_is_enabled (core->parent)) { + ret = false; + goto done; + } + ret = core->ops->is_enabled (core->hw); done:if (core->rpm_enabled)
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 251/529 powerpc/perf/hv-24x7: add missing RTAS retry status handling
In reply to Greg Kroah-HartmanFrom: Nathan Lynch <[email protected]>
[ Upstream commit cc4b26eab1859fa1a70711872caaf6414809973f ]
The ibm,get-system-parameter RTAS function may return -2 or 990x, which indicate that the caller should try again. read_24x7_sys_info() ignores this, allowing transient failures in reporting processor module information.
Move the RTAS call into a coventional rtas_busy_delay()-based loop, along with the parsing of results on success.
--- arch/powerpc/perf/hv-24x7.c | 42 ++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 24 deletions(-)
arch/powerpc/perf/hv-24x7.c +18 -24
@@ -79,9 +79,8 @@ static u32 phys_coresperchip; /* Physical cores per chip */*/ void read_24x7_sys_info (void ) { -int call_status, len, ntypes; - -spin_lock (&rtas_data_buf_lock); +const s32 token =rtas_token ("ibm,get-system-parameter" ); +int call_status;/* * Making system parameter: chips and sockets and cores per chip
@@ -91,32 +90,27 @@ void read_24x7_sys_info(void) phys_chipspersocket =1 ; phys_coresperchip =1 ; - call_status =rtas_call (rtas_token ("ibm,get-system-parameter" ),3 ,1 , -NULL , -PROCESSOR_MODULE_INFO , -__pa (rtas_data_buf), -RTAS_DATA_BUF_SIZE ); +do { +spin_lock (&rtas_data_buf_lock); + call_status =rtas_call (token,3 ,1 ,NULL ,PROCESSOR_MODULE_INFO , +__pa (rtas_data_buf),RTAS_DATA_BUF_SIZE ); +if (call_status ==0 ) { +int ntypes =be16_to_cpup ((__be16 *)&rtas_data_buf[2 ]); +int len =be16_to_cpup ((__be16 *)&rtas_data_buf[0 ]); + +if (len >=8 && ntypes !=0 ) { + phys_sockets =be16_to_cpup ((__be16 *)&rtas_data_buf[4 ]); + phys_chipspersocket =be16_to_cpup ((__be16 *)&rtas_data_buf[6 ]); + phys_coresperchip =be16_to_cpup ((__be16 *)&rtas_data_buf[8 ]); + } + } +spin_unlock (&rtas_data_buf_lock); + }while (rtas_busy_delay (call_status));if (call_status !=0 ) {pr_err ("Error calling get-system-parameter %d\n" , call_status); - }else { - len =be16_to_cpup ((__be16 *)&rtas_data_buf[0 ]); -if (len <8 ) - goto out; - - ntypes =be16_to_cpup ((__be16 *)&rtas_data_buf[2 ]); - -if (!ntypes) - goto out; - - phys_sockets =be16_to_cpup ((__be16 *)&rtas_data_buf[4 ]); - phys_chipspersocket =be16_to_cpup ((__be16 *)&rtas_data_buf[6 ]); - phys_coresperchip =be16_to_cpup ((__be16 *)&rtas_data_buf[8 ]); } - -out: -spin_unlock (&rtas_data_buf_lock); }/* Domains for which more than one result element are returned for each event. */
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 252/529 powerpc/pseries/lpar: add missing RTAS retry status handling
In reply to Greg Kroah-HartmanFrom: Nathan Lynch <[email protected]>
[ Upstream commit daa8ab59044610aa8ef2ee45a6c157b5e11635e9 ]
The ibm,get-system-parameter RTAS function may return -2 or 990x, which indicate that the caller should try again.
pseries_lpar_read_hblkrm_characteristics() ignores this, making it possible to incorrectly detect TLB block invalidation characteristics at boot.
Move the RTAS call into a coventional rtas_busy_delay()-based loop.
--- arch/powerpc/platforms/pseries/lpar.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
arch/powerpc/platforms/pseries/lpar.c +10 -10
@@ -1433,22 +1433,22 @@ static inline void __init check_lp_set_hblkrm(unsigned int lp,void __init pseries_lpar_read_hblkrm_characteristics (void ) { +const s32 token =rtas_token ("ibm,get-system-parameter" );unsigned char local_buffer[SPLPAR_TLB_BIC_MAXLENGTH ];int call_status, len, idx, bpsize;if (!firmware_has_feature (FW_FEATURE_BLOCK_REMOVE ))return ; -spin_lock (&rtas_data_buf_lock); -memset (rtas_data_buf,0 ,RTAS_DATA_BUF_SIZE ); - call_status =rtas_call (rtas_token ("ibm,get-system-parameter" ),3 ,1 , -NULL , -SPLPAR_TLB_BIC_TOKEN , -__pa (rtas_data_buf), -RTAS_DATA_BUF_SIZE ); -memcpy (local_buffer, rtas_data_buf,SPLPAR_TLB_BIC_MAXLENGTH ); - local_buffer[SPLPAR_TLB_BIC_MAXLENGTH -1 ] ='\0' ; -spin_unlock (&rtas_data_buf_lock); +do { +spin_lock (&rtas_data_buf_lock); +memset (rtas_data_buf,0 ,RTAS_DATA_BUF_SIZE ); + call_status =rtas_call (token,3 ,1 ,NULL ,SPLPAR_TLB_BIC_TOKEN , +__pa (rtas_data_buf),RTAS_DATA_BUF_SIZE ); +memcpy (local_buffer, rtas_data_buf,SPLPAR_TLB_BIC_MAXLENGTH ); + local_buffer[SPLPAR_TLB_BIC_MAXLENGTH -1 ] ='\0' ; +spin_unlock (&rtas_data_buf_lock); + }while (rtas_busy_delay (call_status));if (call_status !=0 ) { pr_warn("%s %s Error calling get-system-parameter (0x%x)\n",
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 253/529 powerpc/pseries/lparcfg: add missing RTAS retry status handling
In reply to Greg Kroah-HartmanFrom: Nathan Lynch <[email protected]>
[ Upstream commit 5d08633e5f6564b60f1cbe09af3af40a74d66431 ]
The ibm,get-system-parameter RTAS function may return -2 or 990x, which indicate that the caller should try again.
lparcfg's parse_system_parameter_string() ignores this, making it possible to intermittently report incorrect SPLPAR characteristics.
Move the RTAS call into a coventional rtas_busy_delay()-based loop.
--- arch/powerpc/platforms/pseries/lparcfg.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
arch/powerpc/platforms/pseries/lparcfg.c +10 -10
@@ -322,6 +322,7 @@ static void parse_mpp_x_data(struct seq_file *m)*/ static void parse_system_parameter_string (struct seq_file *m) { +const s32 token =rtas_token ("ibm,get-system-parameter" );int call_status;unsigned char *local_buffer =kmalloc (SPLPAR_MAXLENGTH ,GFP_KERNEL );
@@ -331,16 +332,15 @@ static void parse_system_parameter_string(struct seq_file *m)return ; } -spin_lock (&rtas_data_buf_lock); -memset (rtas_data_buf,0 ,SPLPAR_MAXLENGTH ); - call_status =rtas_call (rtas_token ("ibm,get-system-parameter" ),3 ,1 , -NULL , -SPLPAR_CHARACTERISTICS_TOKEN , -__pa (rtas_data_buf), -RTAS_DATA_BUF_SIZE ); -memcpy (local_buffer, rtas_data_buf,SPLPAR_MAXLENGTH ); - local_buffer[SPLPAR_MAXLENGTH -1 ] ='\0' ; -spin_unlock (&rtas_data_buf_lock); +do { +spin_lock (&rtas_data_buf_lock); +memset (rtas_data_buf,0 ,SPLPAR_MAXLENGTH ); + call_status =rtas_call (token,3 ,1 ,NULL ,SPLPAR_CHARACTERISTICS_TOKEN , +__pa (rtas_data_buf),RTAS_DATA_BUF_SIZE ); +memcpy (local_buffer, rtas_data_buf,SPLPAR_MAXLENGTH ); + local_buffer[SPLPAR_MAXLENGTH -1 ] ='\0' ; +spin_unlock (&rtas_data_buf_lock); + }while (rtas_busy_delay (call_status));if (call_status !=0 ) { printk(KERN_INFO
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 254/529 powerpc/rtas: make all exports GPL
In reply to Greg Kroah-HartmanFrom: Nathan Lynch <[email protected]>
[ Upstream commit 9bce6243848dfd0ff7c2be6e8d82ab9b1e6c7858 ]
The first symbol exports of RTAS functions and data came with the (now removed) scanlog driver in 2003:
At the time this was applied, EXPORT_SYMBOL_GPL() was very new, and the exports of rtas_call() etc have remained non-GPL. As new APIs have been added to the RTAS subsystem, their symbol exports have followed the convention set by existing code.
However, the historical evidence is that RTAS function exports have been added over time only to satisfy the needs of in-kernel users, and these clients must have fairly intimate knowledge of how the APIs work to use them safely. No out of tree users are known, and future ones seem unlikely.
Arguably the default for RTAS symbols should have become EXPORT_SYMBOL_GPL once it was available. Let's make it so now, and exceptions can be evaluated as needed.
Stable-dep-of: 836b5b9fcc8e ("powerpc/rtas: ensure 4KB alignment for rtas_data_buf")
--- arch/powerpc/kernel/rtas.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
arch/powerpc/kernel/rtas.c +11 -11
@@ -52,10 +52,10 @@ struct rtas_t rtas = {EXPORT_SYMBOL (rtas);DEFINE_SPINLOCK (rtas_data_buf_lock); -EXPORT_SYMBOL (rtas_data_buf_lock); +EXPORT_SYMBOL_GPL (rtas_data_buf_lock); char rtas_data_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned; -EXPORT_SYMBOL (rtas_data_buf); +EXPORT_SYMBOL_GPL (rtas_data_buf);unsigned long rtas_rmo_buf;
@@ -64,7 +64,7 @@ unsigned long rtas_rmo_buf;* This is done like this so rtas_flash can be a module. */ void (*rtas_flash_term_hook)(int ); -EXPORT_SYMBOL (rtas_flash_term_hook); +EXPORT_SYMBOL_GPL (rtas_flash_term_hook);/* RTAS use home made raw locking instead of spin_lock_irqsave * because those can be called from within really nasty contexts
@@ -312,7 +312,7 @@ void rtas_progress(char *s, unsigned short hex)spin_unlock (&progress_lock); } -EXPORT_SYMBOL (rtas_progress);/* needed by rtas_flash module */ +EXPORT_SYMBOL_GPL (rtas_progress);/* needed by rtas_flash module */ int rtas_token (const char *service) {
@@ -322,7 +322,7 @@ int rtas_token(const char *service) tokp =of_get_property (rtas.dev, service,NULL );return tokp ?be32_to_cpu (*tokp) :RTAS_UNKNOWN_SERVICE ; } -EXPORT_SYMBOL (rtas_token); +EXPORT_SYMBOL_GPL (rtas_token);int rtas_service_present (const char *service) {
@@ -482,7 +482,7 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...) }return ret; } -EXPORT_SYMBOL (rtas_call); +EXPORT_SYMBOL_GPL (rtas_call);/* For RTAS_BUSY (-2), delay for 1 millisecond. For an extended busy status * code of 990n, perform the hinted delay of 10^n (last digit) milliseconds.
@@ -517,7 +517,7 @@ unsigned int rtas_busy_delay(int status)return ms; } -EXPORT_SYMBOL (rtas_busy_delay); +EXPORT_SYMBOL_GPL (rtas_busy_delay);static int rtas_error_rc (int rtas_rc) {
@@ -563,7 +563,7 @@ int rtas_get_power_level(int powerdomain, int *level)return rtas_error_rc (rc);return rc; } -EXPORT_SYMBOL (rtas_get_power_level); +EXPORT_SYMBOL_GPL (rtas_get_power_level);int rtas_set_power_level (int powerdomain,int level,int *setlevel) {
@@ -581,7 +581,7 @@ int rtas_set_power_level(int powerdomain, int level, int *setlevel)return rtas_error_rc (rc);return rc; } -EXPORT_SYMBOL (rtas_set_power_level); +EXPORT_SYMBOL_GPL (rtas_set_power_level);int rtas_get_sensor (int sensor,int index,int *state) {
@@ -599,7 +599,7 @@ int rtas_get_sensor(int sensor, int index, int *state)return rtas_error_rc (rc);return rc; } -EXPORT_SYMBOL (rtas_get_sensor); +EXPORT_SYMBOL_GPL (rtas_get_sensor);int rtas_get_sensor_fast (int sensor,int index,int *state) {
@@ -660,7 +660,7 @@ int rtas_set_indicator(int indicator, int index, int new_value)return rtas_error_rc (rc);return rc; } -EXPORT_SYMBOL (rtas_set_indicator); +EXPORT_SYMBOL_GPL (rtas_set_indicator);/* * Ignoring RTAS extended delay
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 255/529 powerpc/rtas: ensure 4KB alignment for rtas_data_buf
In reply to Greg Kroah-HartmanFrom: Nathan Lynch <[email protected]>
[ Upstream commit 836b5b9fcc8e09cea7e8a59a070349a00e818308 ]
Some RTAS functions that have work area parameters impose alignment requirements on the work area passed to them by the OS. Examples include:
- ibm,configure-connector
- ibm,update-nodes
- ibm,update-properties
4KB is the greatest alignment required by PAPR for such buffers. rtas_data_buf used to have a __page_aligned attribute in the arch/ppc64 days, but that was changed to __cacheline_aligned for unknown reasons by commit 033ef338b6e0 ("powerpc: Merge rtas.c into arch/powerpc/kernel"). That works out to 128-byte alignment on ppc64, which isn't right.
This was found by inspection and I'm not aware of any real problems caused by this. Either current RTAS implementations don't enforce the alignment constraints, or rtas_data_buf is always being placed at a 4KB boundary by accident (or both, perhaps).
Use __aligned(SZ_4K) to ensure the rtas_data_buf has alignment appropriate for all users.
--- arch/powerpc/kernel/rtas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/kernel/rtas.c +1 -1
@@ -54,7 +54,7 @@ EXPORT_SYMBOL(rtas);DEFINE_SPINLOCK (rtas_data_buf_lock);EXPORT_SYMBOL_GPL (rtas_data_buf_lock); -char rtas_data_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned; +char rtas_data_buf[RTAS_DATA_BUF_SIZE ]__aligned(SZ_4K) ;EXPORT_SYMBOL_GPL (rtas_data_buf);unsigned long rtas_rmo_buf;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 256/529 powerpc/eeh: Small refactor of eeh_handle_normal_event()
In reply to Greg Kroah-HartmanFrom: Daniel Axtens <[email protected]>
[ Upstream commit 10b34ece132ee46dc4e6459c765d180c422a09fa ]
The control flow of eeh_handle_normal_event() is a bit tricky.
Break out one of the error handling paths - rather than be in an else block, we'll make it part of the regular body of the function and put a 'goto out;' in the true limb of the if.
Stable-dep-of: 9efcdaac36e1 ("powerpc/eeh: Set channel state after notifying the drivers")
--- arch/powerpc/kernel/eeh_driver.c | 69 ++++++++++++++++---------------- 1 file changed, 35 insertions(+), 34 deletions(-)
arch/powerpc/kernel/eeh_driver.c +35 -34
@@ -1054,45 +1054,46 @@ void eeh_handle_normal_event(struct eeh_pe *pe) }pr_info ("EEH: Recovery successful.\n" ); - }else { -/* -* About 90% of all real-life EEH failures in the field -* are due to poorly seated PCI cards. Only 10% or so are -* due to actual, failed cards. -*/ -pr_err ("EEH: Unable to recover from failure from PHB#%x-PE#%x.\n" -"Please try reseating or replacing it\n" , - pe->phb->global_number, pe->addr); + goto out; + } -eeh_slot_error_detail (pe,EEH_LOG_PERM ); +/* +* About 90% of all real-life EEH failures in the field +* are due to poorly seated PCI cards. Only 10% or so are +* due to actual, failed cards. +*/ +pr_err ("EEH: Unable to recover from failure from PHB#%x-PE#%x.\n" +"Please try reseating or replacing it\n" , + pe->phb->global_number, pe->addr); -/* Notify all devices that they're about to go down. */ -eeh_set_channel_state (pe, pci_channel_io_perm_failure); -eeh_set_irq_state (pe, false); -eeh_pe_report ("error_detected(permanent failure)" , pe, - eeh_report_failure,NULL ); +eeh_slot_error_detail (pe,EEH_LOG_PERM ); -/* Mark the PE to be removed permanently */ -eeh_pe_state_mark (pe,EEH_PE_REMOVED ); +/* Notify all devices that they're about to go down. */ +eeh_set_channel_state (pe, pci_channel_io_perm_failure); +eeh_set_irq_state (pe, false); +eeh_pe_report ("error_detected(permanent failure)" , pe, + eeh_report_failure,NULL ); -/* -* Shut down the device drivers for good. We mark -* all removed devices correctly to avoid access -* the their PCI config any more. -*/ -if (pe->type &EEH_PE_VF ) { -eeh_pe_dev_traverse (pe, eeh_rmv_device,NULL ); -eeh_pe_dev_mode_mark (pe,EEH_DEV_REMOVED ); - }else { -eeh_pe_state_clear (pe,EEH_PE_PRI_BUS , true); -eeh_pe_dev_mode_mark (pe,EEH_DEV_REMOVED ); +/* Mark the PE to be removed permanently */ +eeh_pe_state_mark (pe,EEH_PE_REMOVED ); -pci_lock_rescan_remove (); -pci_hp_remove_devices (bus); -pci_unlock_rescan_remove (); -/* The passed PE should no longer be used */ -return ; - } +/* +* Shut down the device drivers for good. We mark +* all removed devices correctly to avoid access +* the their PCI config any more. +*/ +if (pe->type &EEH_PE_VF ) { +eeh_pe_dev_traverse (pe, eeh_rmv_device,NULL ); +eeh_pe_dev_mode_mark (pe,EEH_DEV_REMOVED ); + }else { +eeh_pe_state_clear (pe,EEH_PE_PRI_BUS , true); +eeh_pe_dev_mode_mark (pe,EEH_DEV_REMOVED ); + +pci_lock_rescan_remove (); +pci_hp_remove_devices (bus); +pci_unlock_rescan_remove (); +/* The passed PE should no longer be used */ +return ; } out:
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 257/529 powerpc/eeh: Set channel state after notifying the drivers
In reply to Greg Kroah-HartmanFrom: Ganesh Goudar <[email protected]>
[ Upstream commit 9efcdaac36e1643a1b7f5337e6143ce142d381b1 ]
When a PCI error is encountered 6th time in an hour we set the channel state to perm_failure and notify the driver about the permanent failure.
However, after upstream commit 38ddc011478e ("powerpc/eeh:
Make permanently failed devices non-actionable"), EEH handler stops calling any routine once the device is marked as permanent failure. This issue can lead to fatal consequences like kernel hang with certain PCI devices.
Following log is observed with lpfc driver, with and without this change, Without this change kernel hangs, If PCI error is encountered 6 times for a device in an hour.
Without the change
EEH: Beginning: 'error_detected(permanent failure)' PCI 0132:60:00.0#600000: EEH: not actionable (1,1,1) PCI 0132:60:00.1#600000: EEH: not actionable (1,1,1)
EEH: Finished:'error_detected(permanent failure)'
With the change
EEH: Beginning: 'error_detected(permanent failure)'
EEH: Invoking lpfc->error_detected(permanent failure)
EEH: lpfc driver reports: 'disconnect'
EEH: Invoking lpfc->error_detected(permanent failure)
EEH: lpfc driver reports: 'disconnect'
EEH: Finished:'error_detected(permanent failure)'
To fix the issue, set channel state to permanent failure after notifying the drivers.
--- arch/powerpc/kernel/eeh_driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/powerpc/kernel/eeh_driver.c +2 -2
@@ -1069,10 +1069,10 @@ void eeh_handle_normal_event(struct eeh_pe *pe)eeh_slot_error_detail (pe,EEH_LOG_PERM );/* Notify all devices that they're about to go down. */ -eeh_set_channel_state (pe, pci_channel_io_perm_failure);eeh_set_irq_state (pe, false);eeh_pe_report ("error_detected(permanent failure)" , pe, eeh_report_failure,NULL ); +eeh_set_channel_state (pe, pci_channel_io_perm_failure);/* Mark the PE to be removed permanently */ eeh_pe_state_mark (pe,EEH_PE_REMOVED );
@@ -1189,10 +1189,10 @@ void eeh_handle_special_event(void)/* Notify all devices to be down */ eeh_pe_state_clear (pe,EEH_PE_PRI_BUS , true); -eeh_set_channel_state (pe, pci_channel_io_perm_failure);eeh_pe_report ("error_detected(permanent failure)" , pe, eeh_report_failure,NULL ); +eeh_set_channel_state (pe, pci_channel_io_perm_failure);pci_lock_rescan_remove ();list_for_each_entry (hose, &hose_list, list_node) {
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 258/529 MIPS: SMP-CPS: fix build error when HOTPLUG_CPU not set
In reply to Greg Kroah-HartmanFrom: Randy Dunlap <[email protected]>
[ Upstream commit 6f02e39fa40f16c24e7a5c599a854c0d1682788d ]
When MIPS_CPS=y, MIPS_CPS_PM is not set, HOTPLUG_CPU is not set, and KEXEC=y, cps_shutdown_this_cpu() attempts to call cps_pm_enter_state(), which is not built when MIPS_CPS_PM is not set. Conditionally execute the else branch based on CONFIG_HOTPLUG_CPU to remove the build error.
This build failure is from a randconfig file.
mips-linux-ld: arch/mips/kernel/smp-cps.o: in function `$L162':
smp-cps.c:(.text.cps_kexec_nonboot_cpu+0x31c): undefined reference to `cps_pm_enter_state'
--- arch/mips/kernel/smp-cps.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
arch/mips/kernel/smp-cps.c +5 -3
@@ -423,9 +423,11 @@ static void cps_shutdown_this_cpu(enum cpu_death death)wmb (); } }else { -pr_debug ("Gating power to core %d\n" , core); -/* Power down the core */ -cps_pm_enter_state (CPS_PM_POWER_GATED ); +if (IS_ENABLED (CONFIG_HOTPLUG_CPU )) { +pr_debug ("Gating power to core %d\n" , core); +/* Power down the core */ +cps_pm_enter_state (CPS_PM_POWER_GATED ); + } } }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 259/529 MIPS: vpe-mt: drop physical_memsize
In reply to Greg Kroah-HartmanFrom: Randy Dunlap <[email protected]>
[ Upstream commit 91dc288f4edf0d768e46c2c6d33e0ab703403459 ]
When neither LANTIQ nor MIPS_MALTA is set, 'physical_memsize' is not declared. This causes the build to fail with:
mips-linux-ld: arch/mips/kernel/vpe-mt.o: in function `vpe_run':
arch/mips/kernel/vpe-mt.c:(.text.vpe_run+0x280): undefined reference to `physical_memsize'
LANTIQ is not using 'physical_memsize' and MIPS_MALTA's use of it is self-contained in mti-malta/malta-dtshim.c.
Use of physical_memsize in vpe-mt.c appears to be unused, so eliminate this loader mode completely and require VPE programs to be compiled with DFLT_STACK_SIZE and DFLT_HEAP_SIZE defined.
--- arch/mips/include/asm/vpe.h | 1 - arch/mips/kernel/vpe-mt.c | 7 +++---- arch/mips/lantiq/prom.c | 6 ------ 3 files changed, 3 insertions(+), 11 deletions(-)
arch/mips/include/asm/vpe.h +0 -1
@@ -104,7 +104,6 @@ struct vpe_control {struct list_head tc_list;/* Thread contexts */ }; -extern unsigned long physical_memsize;extern struct vpe_control vpecontrol;extern const struct file_operations vpe_fops;
arch/mips/kernel/vpe-mt.c +3 -4
@@ -92,12 +92,11 @@ int vpe_run(struct vpe *v)write_tc_c0_tchalt (read_tc_c0_tchalt () & ~TCHALT_H );/* -* The sde-kit passes 'memsize' to __start in $a3, so set something -* here... Or set $a3 to zero and define DFLT_STACK_SIZE and -* DFLT_HEAP_SIZE when you compile your program +* We don't pass the memsize here, so VPE programs need to be +* compiled with DFLT_STACK_SIZE and DFLT_HEAP_SIZE defined. */ +mttgpr (7 ,0 );mttgpr (6 , v->ntcs); -mttgpr (7 , physical_memsize);/* set up VPE1 */ /*
arch/mips/lantiq/prom.c +0 -6
@@ -22,12 +22,6 @@DEFINE_SPINLOCK (ebu_lock);EXPORT_SYMBOL_GPL (ebu_lock); -/* -* This is needed by the VPE loader code, just set it to 0 and assume -* that the firmware hardcodes this value to something useful. -*/ -unsigned long physical_memsize =0L ; -/* * this struct is filled by the soc specific detection code and holds * information about the specific soc type, revision and name
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 260/529 vdpa/mlx5: Dont clear mr struct on destroy MR
In reply to Greg Kroah-HartmanFrom: Eli Cohen <[email protected]>
[ Upstream commit aef24311bd2d8a6d39a80c34f278b0fd1692aed3 ]
Clearing the mr struct erases the lock owner and causes warnings to be emitted. It is not required to clear the mr so remove the memset call.
Message-Id: <[email protected]>
--- drivers/vdpa/mlx5/core/mr.c | 1 - 1 file changed, 1 deletion(-)
drivers/vdpa/mlx5/core/mr.c +0 -1
@@ -448,7 +448,6 @@ void mlx5_vdpa_destroy_mr(struct mlx5_vdpa_dev *mvdev)unmap_direct_mr (mvdev, dmr);kfree (dmr); } -memset (mr,0 ,sizeof (*mr)); mr->initialized = false; out:mutex_unlock (&mr->mkey_mtx);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 261/529 alpha/boot/tools/objstrip: fix the check for ELF header
In reply to Greg Kroah-HartmanFrom: Al Viro <[email protected]>
[ Upstream commit 1878787797cbb019eeefe6f905514dcd557302b6 ]
Just memcmp() with ELFMAG - that's the normal way to do it in userland code, which that thing is. Besides, that has the benefit of actually building - str_has_prefix() is *NOT* present in <string.h>.
--- arch/alpha/boot/tools/objstrip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/alpha/boot/tools/objstrip.c +1 -1
@@ -148,7 +148,7 @@ main (int argc, char *argv[])#ifdef __ELF__ elf = (struct elfhdr *) buf; -if (elf->e_ident[0 ] ==0x7f &&str_has_prefix ((char *)elf->e_ident +1 ,"ELF" )) { +if (memcmp (&elf->e_ident[EI_MAG0 ],ELFMAG ,SELFMAG ) ==0 ) {if (elf->e_type !=ET_EXEC ) {fprintf (stderr,"%s: %s is not an ELF executable\n" , prog_name, inname);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 262/529 Input: iqs269a - do not poll during suspend or resume
In reply to Greg Kroah-HartmanFrom: Jeff LaBundy <[email protected]>
[ Upstream commit 18ab69c8ca5678324efbeed874b707ce7b2feae1 ]
Polling the device while it transitions from automatic to manual power mode switching may keep the device from actually finishing the transition. The process appears to time out depending on the polling rate and the device's core clock frequency.
This is ultimately unnecessary in the first place; instead it is sufficient to write the desired mode during initialization, then disable automatic switching at suspend. This eliminates the need to ensure the device is prepared for a manual change and removes the 'suspend_mode' variable.
Similarly, polling the device while it transitions from one mode to another under manual control may time out as well. This added step does not appear to be necessary either, so drop it.
--- drivers/input/misc/iqs269a.c | 118 +++++++++-------------------------- 1 file changed, 31 insertions(+), 87 deletions(-)
drivers/input/misc/iqs269a.c +31 -87
@@ -148,9 +148,6 @@#define IQS269_ATI_POLL_TIMEOUT_US (iqs269->delay_mult * 500000)#define IQS269_ATI_STABLE_DELAY_MS (iqs269->delay_mult * 150) -#define IQS269_PWR_MODE_POLL_SLEEP_US IQS269_ATI_POLL_SLEEP_US -#define IQS269_PWR_MODE_POLL_TIMEOUT_US IQS269_ATI_POLL_TIMEOUT_US -#define iqs269_irq_wait () usleep_range(200, 250)enum iqs269_local_cap_size {
@@ -295,7 +292,6 @@ struct iqs269_private {struct input_dev *keypad;struct input_dev *slider[IQS269_NUM_SL ];unsigned int keycode[ARRAY_SIZE (iqs269_events) *IQS269_NUM_CH ]; -unsigned int suspend_mode;unsigned int delay_mult;unsigned int ch_num;bool hall_enable;
@@ -767,17 +763,6 @@ static int iqs269_parse_prop(struct iqs269_private *iqs269) iqs269->hall_enable =device_property_present (&client->dev,"azoteq,hall-enable" ); -if (!device_property_read_u32 (&client->dev,"azoteq,suspend-mode" , - &val)) { -if (val >IQS269_SYS_SETTINGS_PWR_MODE_MAX ) { -dev_err (&client->dev,"Invalid suspend mode: %u\n" , - val); -return -EINVAL ; - } - - iqs269->suspend_mode = val; - } - error =regmap_raw_read (iqs269->regmap,IQS269_SYS_SETTINGS , sys_reg,sizeof (*sys_reg));if (error)
@@ -1005,6 +990,17 @@ static int iqs269_parse_prop(struct iqs269_private *iqs269) general &= ~IQS269_SYS_SETTINGS_DIS_AUTO ; general &= ~IQS269_SYS_SETTINGS_PWR_MODE_MASK ; +if (!device_property_read_u32 (&client->dev,"azoteq,suspend-mode" , + &val)) { +if (val >IQS269_SYS_SETTINGS_PWR_MODE_MAX ) { +dev_err (&client->dev,"Invalid suspend mode: %u\n" , + val); +return -EINVAL ; + } + + general |= (val <<IQS269_SYS_SETTINGS_PWR_MODE_SHIFT ); + } +if (!device_property_read_u32 (&client->dev,"azoteq,ulp-update" , &val)) {if (val >IQS269_SYS_SETTINGS_ULP_UPDATE_MAX ) {
@@ -1687,59 +1683,30 @@ static int iqs269_probe(struct i2c_client *client)return error; } +static u16 iqs269_general_get (struct iqs269_private *iqs269) +{ +u16 general =be16_to_cpu (iqs269->sys_reg.general); + + general &= ~IQS269_SYS_SETTINGS_REDO_ATI ; + general &= ~IQS269_SYS_SETTINGS_ACK_RESET ; + +return general |IQS269_SYS_SETTINGS_DIS_AUTO ; +} +static int __maybe_unused iqs269_suspend (struct device *dev) {struct iqs269_private *iqs269 =dev_get_drvdata (dev);struct i2c_client *client = iqs269->client; -unsigned int val;int error; +u16 general =iqs269_general_get (iqs269); -if (!iqs269->suspend_mode) +if (!(general &IQS269_SYS_SETTINGS_PWR_MODE_MASK ))return 0 ;disable_irq (client->irq); -/* -* Automatic power mode switching must be disabled before the device is -* forced into any particular power mode. In this case, the device will -* transition into normal-power mode. -*/ - error =regmap_update_bits (iqs269->regmap,IQS269_SYS_SETTINGS , -IQS269_SYS_SETTINGS_DIS_AUTO , ~0 ); -if (error) - goto err_irq; - -/* -* The following check ensures the device has completed its transition -* into normal-power mode before a manual mode switch is performed. -*/ - error =regmap_read_poll_timeout (iqs269->regmap,IQS269_SYS_FLAGS , val, - !(val &IQS269_SYS_FLAGS_PWR_MODE_MASK ), -IQS269_PWR_MODE_POLL_SLEEP_US , -IQS269_PWR_MODE_POLL_TIMEOUT_US ); -if (error) - goto err_irq; - - error =regmap_update_bits (iqs269->regmap,IQS269_SYS_SETTINGS , -IQS269_SYS_SETTINGS_PWR_MODE_MASK , - iqs269->suspend_mode << -IQS269_SYS_SETTINGS_PWR_MODE_SHIFT ); -if (error) - goto err_irq; - -/* -* This last check ensures the device has completed its transition into -* the desired power mode to prevent any spurious interrupts from being -* triggered after iqs269_suspend has already returned. -*/ - error =regmap_read_poll_timeout (iqs269->regmap,IQS269_SYS_FLAGS , val, - (val &IQS269_SYS_FLAGS_PWR_MODE_MASK ) - == (iqs269->suspend_mode << -IQS269_SYS_FLAGS_PWR_MODE_SHIFT ), -IQS269_PWR_MODE_POLL_SLEEP_US , -IQS269_PWR_MODE_POLL_TIMEOUT_US ); + error =regmap_write (iqs269->regmap,IQS269_SYS_SETTINGS , general); -err_irq:iqs269_irq_wait ();enable_irq (client->irq);
@@ -1750,43 +1717,20 @@ static int __maybe_unused iqs269_resume(struct device *dev) {struct iqs269_private *iqs269 =dev_get_drvdata (dev);struct i2c_client *client = iqs269->client; -unsigned int val;int error; +u16 general =iqs269_general_get (iqs269); -if (!iqs269->suspend_mode) +if (!(general &IQS269_SYS_SETTINGS_PWR_MODE_MASK ))return 0 ;disable_irq (client->irq); - error =regmap_update_bits (iqs269->regmap,IQS269_SYS_SETTINGS , -IQS269_SYS_SETTINGS_PWR_MODE_MASK ,0 ); -if (error) - goto err_irq; - -/* -* This check ensures the device has returned to normal-power mode -* before automatic power mode switching is re-enabled. -*/ - error =regmap_read_poll_timeout (iqs269->regmap,IQS269_SYS_FLAGS , val, - !(val &IQS269_SYS_FLAGS_PWR_MODE_MASK ), -IQS269_PWR_MODE_POLL_SLEEP_US , -IQS269_PWR_MODE_POLL_TIMEOUT_US ); -if (error) - goto err_irq; - - error =regmap_update_bits (iqs269->regmap,IQS269_SYS_SETTINGS , -IQS269_SYS_SETTINGS_DIS_AUTO ,0 ); -if (error) - goto err_irq; - -/* -* This step reports any events that may have been "swallowed" as a -* result of polling PWR_MODE (which automatically acknowledges any -* pending interrupts). -*/ - error =iqs269_report (iqs269); + error =regmap_write (iqs269->regmap,IQS269_SYS_SETTINGS , + general & ~IQS269_SYS_SETTINGS_PWR_MODE_MASK ); +if (!error) + error =regmap_write (iqs269->regmap,IQS269_SYS_SETTINGS , + general & ~IQS269_SYS_SETTINGS_DIS_AUTO ); -err_irq:iqs269_irq_wait ();enable_irq (client->irq);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 263/529 Input: iqs269a - do not poll during ATI
In reply to Greg Kroah-HartmanFrom: Jeff LaBundy <[email protected]>
[ Upstream commit b08134eb254db56e9ce8170d9b82f0d7a616b6f8 ]
After initial start-up, the driver triggers ATI (calibration) with the newly loaded register configuration in place. Next, the driver polls a register field to ensure ATI completed in a timely fashion and that the device is ready to sense.
However, communicating with the device over I2C while ATI is under- way may induce noise in the device and cause ATI to fail. As such, the vendor recommends not to poll the device during ATI.
To solve this problem, let the device naturally signal to the host that ATI is complete by way of an interrupt. A completion prevents the device from successfully probing until this happens.
As an added benefit, initial switch states are now reported in the interrupt handler at the same time ATI status is checked. As such, duplicate code that reports initial switch states has been removed from iqs269_input_init().
The former logic that scaled ATI timeout and filter settling delay is not carried forward with the new implementation, as it produces overly conservative delays at the lower clock rate.
Rather, a single timeout that covers both clock rates is used. The filter settling delay does not happen to be necessary and has been removed as well.
--- drivers/input/misc/iqs269a.c | 97 +++++++++++++++++------------------- 1 file changed, 46 insertions(+), 51 deletions(-)
drivers/input/misc/iqs269a.c +46 -51
@@ -9,6 +9,7 @@* axial sliders presented by the device. */ +#include <linux/completion.h> #include <linux/delay.h> #include <linux/device.h> #include <linux/err.h>
@@ -144,10 +145,6 @@#define IQS269_NUM_CH 8#define IQS269_NUM_SL 2 -#define IQS269_ATI_POLL_SLEEP_US (iqs269->delay_mult * 10000) -#define IQS269_ATI_POLL_TIMEOUT_US (iqs269->delay_mult * 500000) -#define IQS269_ATI_STABLE_DELAY_MS (iqs269->delay_mult * 150) -#define iqs269_irq_wait () usleep_range(200, 250)enum iqs269_local_cap_size {
@@ -289,10 +286,10 @@ struct iqs269_private {struct mutex lock;struct iqs269_switch_desc switches[ARRAY_SIZE (iqs269_events)];struct iqs269_sys_reg sys_reg; +struct completion ati_done;struct input_dev *keypad;struct input_dev *slider[IQS269_NUM_SL ];unsigned int keycode[ARRAY_SIZE (iqs269_events) *IQS269_NUM_CH ]; -unsigned int delay_mult;unsigned int ch_num;bool hall_enable;bool ati_current;
@@ -973,13 +970,8 @@ static int iqs269_parse_prop(struct iqs269_private *iqs269) general =be16_to_cpu (sys_reg->general); -if (device_property_present (&client->dev,"azoteq,clk-div" )) { +if (device_property_present (&client->dev,"azoteq,clk-div" )) general |=IQS269_SYS_SETTINGS_CLK_DIV ; - iqs269->delay_mult =4 ; - }else { - general &= ~IQS269_SYS_SETTINGS_CLK_DIV ; - iqs269->delay_mult =1 ; - }/* * Configure the device to automatically switch between normal and low-
@@ -1036,7 +1028,6 @@ static int iqs269_parse_prop(struct iqs269_private *iqs269)static int iqs269_dev_init (struct iqs269_private *iqs269) { -unsigned int val;int error;mutex_lock (&iqs269->lock);
@@ -1052,14 +1043,12 @@ static int iqs269_dev_init(struct iqs269_private *iqs269)if (error) goto err_mutex; - error =regmap_read_poll_timeout (iqs269->regmap,IQS269_SYS_FLAGS , val, - !(val &IQS269_SYS_FLAGS_IN_ATI ), -IQS269_ATI_POLL_SLEEP_US , -IQS269_ATI_POLL_TIMEOUT_US ); -if (error) - goto err_mutex; +/* +* The following delay gives the device time to deassert its RDY output +* so as to prevent an interrupt from being serviced prematurely. +*/ +usleep_range (2000 ,2100 ); -msleep (IQS269_ATI_STABLE_DELAY_MS ); iqs269->ati_current = true; err_mutex:
@@ -1071,10 +1060,8 @@ static int iqs269_dev_init(struct iqs269_private *iqs269)static int iqs269_input_init (struct iqs269_private *iqs269) {struct i2c_client *client = iqs269->client; -struct iqs269_flags flags;unsigned int sw_code, keycode;int error, i, j; -u8 dir_mask, state; iqs269->keypad =devm_input_allocate_device (&client->dev);if (!iqs269->keypad)
@@ -1087,23 +1074,7 @@ static int iqs269_input_init(struct iqs269_private *iqs269) iqs269->keypad->name ="iqs269a_keypad" ; iqs269->keypad->id.bustype =BUS_I2C ; -if (iqs269->hall_enable) { - error =regmap_raw_read (iqs269->regmap,IQS269_SYS_FLAGS , - &flags,sizeof (flags)); -if (error) { -dev_err (&client->dev, -"Failed to read initial status: %d\n" , error); -return error; - } - } -for (i =0 ; i <ARRAY_SIZE (iqs269_events); i++) { - dir_mask = flags.states[IQS269_ST_OFFS_DIR ]; -if (!iqs269_events[i].dir_up) - dir_mask = ~dir_mask; - - state = flags.states[iqs269_events[i].st_offs] & dir_mask; - sw_code = iqs269->switches[i].code;for (j =0 ; j <IQS269_NUM_CH ; j++) {
@@ -1116,13 +1087,9 @@ static int iqs269_input_init(struct iqs269_private *iqs269)switch (j) {case IQS269_CHx_HALL_ACTIVE:if (iqs269->hall_enable && - iqs269->switches[i].enabled) { + iqs269->switches[i].enabled)input_set_capability (iqs269->keypad,EV_SW , sw_code); -input_report_switch (iqs269->keypad, - sw_code, - state &BIT (j)); - } fallthrough;case IQS269_CHx_HALL_INACTIVE:
@@ -1138,14 +1105,6 @@ static int iqs269_input_init(struct iqs269_private *iqs269) } } -input_sync (iqs269->keypad); - - error =input_register_device (iqs269->keypad); -if (error) { -dev_err (&client->dev,"Failed to register keypad: %d\n" , error); -return error; - } -for (i =0 ; i <IQS269_NUM_SL ; i++) {if (!iqs269->sys_reg.slider_select[i])continue ;
@@ -1205,6 +1164,9 @@ static int iqs269_report(struct iqs269_private *iqs269)return error; } +if (be16_to_cpu (flags.system) &IQS269_SYS_FLAGS_IN_ATI ) +return 0 ; + error =regmap_raw_read (iqs269->regmap,IQS269_SLIDER_X , slider_x,sizeof (slider_x));if (error) {
@@ -1267,6 +1229,12 @@ static int iqs269_report(struct iqs269_private *iqs269)input_sync (iqs269->keypad); +/* +* The following completion signals that ATI has finished, any initial +* switch states have been reported and the keypad can be registered. +*/ +complete_all (&iqs269->ati_done); +return 0 ; }
@@ -1298,6 +1266,9 @@ static ssize_t counts_show(struct device *dev,if (!iqs269->ati_current || iqs269->hall_enable)return -EPERM ; +if (!completion_done (&iqs269->ati_done)) +return -EBUSY ; +/* * Unsolicited I2C communication prompts the device to assert its RDY * pin, so disable the interrupt line until the operation is finished
@@ -1554,7 +1525,9 @@ static ssize_t ati_trigger_show(struct device *dev, {struct iqs269_private *iqs269 =dev_get_drvdata (dev); -return scnprintf (buf,PAGE_SIZE ,"%u\n" , iqs269->ati_current); +return scnprintf (buf,PAGE_SIZE ,"%u\n" , + iqs269->ati_current && +completion_done (&iqs269->ati_done)); } static ssize_t ati_trigger_store(struct device *dev,
@@ -1574,6 +1547,7 @@ static ssize_t ati_trigger_store(struct device *dev,return count;disable_irq (client->irq); +reinit_completion (&iqs269->ati_done); error =iqs269_dev_init (iqs269);
@@ -1583,6 +1557,10 @@ static ssize_t ati_trigger_store(struct device *dev,if (error)return error; +if (!wait_for_completion_timeout (&iqs269->ati_done, +msecs_to_jiffies (2000 ))) +return -ETIMEDOUT ; +return count; }
@@ -1641,6 +1619,7 @@ static int iqs269_probe(struct i2c_client *client) }mutex_init (&iqs269->lock); +init_completion (&iqs269->ati_done); error =regmap_raw_read (iqs269->regmap,IQS269_VER_INFO , &ver_info,sizeof (ver_info));
@@ -1676,6 +1655,22 @@ static int iqs269_probe(struct i2c_client *client)return error; } +if (!wait_for_completion_timeout (&iqs269->ati_done, +msecs_to_jiffies (2000 ))) { +dev_err (&client->dev,"Failed to complete ATI\n" ); +return -ETIMEDOUT ; + } + +/* +* The keypad may include one or more switches and is not registered +* until ATI is complete and the initial switch states are read. +*/ + error =input_register_device (iqs269->keypad); +if (error) { +dev_err (&client->dev,"Failed to register keypad: %d\n" , error); +return error; + } + error =devm_device_add_group (&client->dev, &iqs269_attr_group);if (error)dev_err (&client->dev,"Failed to add attributes: %d\n" , error);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 264/529 remoteproc: qcom_q6v5_mss: Use a carveout to authenticate modem headers
In reply to Greg Kroah-HartmanFrom: Sibi Sankar <[email protected]>
[ Upstream commit 57f72170a2b2a362c35bb9407fc844eac5afdec1 ]
Any access to the dynamically allocated metadata region by the application processor after assigning it to the remote Q6 will result in a XPU violation. Fix this by replacing the dynamically allocated memory region with a no-map carveout and unmap the modem metadata memory region before passing control to the remote Q6.
--- drivers/remoteproc/qcom_q6v5_mss.c | 59 +++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 6 deletions(-)
drivers/remoteproc/qcom_q6v5_mss.c +53 -6
@@ -17,6 +17,7 @@#include <linux/module.h> #include <linux/of_address.h> #include <linux/of_device.h> +#include <linux/of_reserved_mem.h> #include <linux/platform_device.h> #include <linux/pm_domain.h> #include <linux/pm_runtime.h>
@@ -190,6 +191,9 @@ struct q6v5 {size_t mba_size;size_t dp_size; +phys_addr_t mdata_phys; +size_t mdata_size; +phys_addr_t mpss_phys;phys_addr_t mpss_reloc;size_t mpss_size;
@@ -816,15 +820,35 @@ static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw)if (IS_ERR (metadata))return PTR_ERR (metadata); - ptr =dma_alloc_attrs (qproc->dev, size, &phys,GFP_KERNEL , dma_attrs); -if (!ptr) { -kfree (metadata); -dev_err (qproc->dev,"failed to allocate mdt buffer\n" ); -return -ENOMEM ; +if (qproc->mdata_phys) { +if (size > qproc->mdata_size) { + ret = -EINVAL ; +dev_err (qproc->dev,"metadata size outside memory range\n" ); + goto free_metadata; + } + + phys = qproc->mdata_phys; + ptr =memremap (qproc->mdata_phys, size,MEMREMAP_WC ); +if (!ptr) { + ret = -EBUSY ; +dev_err (qproc->dev,"unable to map memory region: %pa+%zx\n" , + &qproc->mdata_phys, size); + goto free_metadata; + } + }else { + ptr =dma_alloc_attrs (qproc->dev, size, &phys,GFP_KERNEL , dma_attrs); +if (!ptr) { + ret = -ENOMEM ; +dev_err (qproc->dev,"failed to allocate mdt buffer\n" ); + goto free_metadata; + } }memcpy (ptr, metadata, size); +if (qproc->mdata_phys) +memunmap (ptr); +/* Hypervisor mapping to access metadata by modem */ mdata_perm =BIT (QCOM_SCM_VMID_HLOS ); ret = q6v5_xfer_mem_ownership(qproc, &mdata_perm, false, true,
@@ -853,7 +877,9 @@ static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw) "mdt buffer not reclaimed system may become unstable\n"); free_dma_attrs: -dma_free_attrs (qproc->dev, size, ptr, phys, dma_attrs); +if (!qproc->mdata_phys) +dma_free_attrs (qproc->dev, size, ptr, phys, dma_attrs); +free_metadata:kfree (metadata);return ret <0 ? ret :0 ;
@@ -1585,6 +1611,7 @@ static int q6v5_init_reset(struct q6v5 *qproc)static int q6v5_alloc_memory_region (struct q6v5 *qproc) {struct device_node *child; +struct reserved_mem *rmem;struct device_node *node;struct resource r;int ret;
@@ -1637,6 +1664,26 @@ static int q6v5_alloc_memory_region(struct q6v5 *qproc) qproc->mpss_phys = qproc->mpss_reloc = r.start; qproc->mpss_size =resource_size (&r); +if (!child) { + node =of_parse_phandle (qproc->dev->of_node,"memory-region" ,2 ); + }else { + child =of_get_child_by_name (qproc->dev->of_node,"metadata" ); + node =of_parse_phandle (child,"memory-region" ,0 ); +of_node_put (child); + } + +if (!node) +return 0 ; + + rmem =of_reserved_mem_lookup (node); +if (!rmem) { +dev_err (qproc->dev,"unable to resolve metadata region\n" ); +return -EINVAL ; + } + + qproc->mdata_phys = rmem->base; + qproc->mdata_size = rmem->size; +return 0 ; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 265/529 media: ti: cal: fix possible memory leak in cal_ctx_create()
In reply to Greg Kroah-HartmanFrom: Gaosheng Cui <[email protected]>
[ Upstream commit 7acd650a0484d92985a0d6d867d980c6dd019885 ]
The memory of ctx is allocated in cal_ctx_create(), but it will not be freed when cal_ctx_v4l2_init() fails, so add kfree() when cal_ctx_v4l2_init() fails to fix it.
--- drivers/media/platform/ti-vpe/cal.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/media/platform/ti-vpe/cal.c +3 -1
@@ -624,8 +624,10 @@ static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst) ctx->cport = inst; ret =cal_ctx_v4l2_init (ctx); -if (ret) +if (ret) { +kfree (ctx);return NULL ; + }return ctx; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 266/529 media: platform: ti: Add missing check for devm_regulator_get
In reply to Greg Kroah-HartmanFrom: Jiasheng Jiang <[email protected]>
[ Upstream commit da8e05f84a11c3cc3b0ba0a3c62d20e358002d99 ]
Add check for the return value of devm_regulator_get since it may return error pointer.
--- drivers/media/platform/omap3isp/isp.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/media/platform/omap3isp/isp.c +9 -0
@@ -2297,7 +2297,16 @@ static int isp_probe(struct platform_device *pdev)/* Regulators */ isp->isp_csiphy1.vdd =devm_regulator_get (&pdev->dev,"vdd-csiphy1" ); +if (IS_ERR (isp->isp_csiphy1.vdd)) { + ret =PTR_ERR (isp->isp_csiphy1.vdd); + goto error; + } + isp->isp_csiphy2.vdd =devm_regulator_get (&pdev->dev,"vdd-csiphy2" ); +if (IS_ERR (isp->isp_csiphy2.vdd)) { + ret =PTR_ERR (isp->isp_csiphy2.vdd); + goto error; + }/* Clocks *
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 267/529 powerpc: Remove linker flag from KBUILD_AFLAGS
In reply to Greg Kroah-HartmanFrom: Nathan Chancellor <[email protected]>
[ Upstream commit 31f48f16264bc70962fb3e7ec62da64d0a2ba04a ]
When clang's -Qunused-arguments is dropped from KBUILD_CPPFLAGS, it points out that KBUILD_AFLAGS contains a linker flag, which will be unused:
clang: error: -Wl,-a32: 'linker' input unused [-Werror,-Wunused-command-line-argument]
This was likely supposed to be '-Wa,-a$(BITS)'. However, this change is unnecessary, as all supported versions of clang and gcc will pass '-a64' or '-a32' to GNU as based on the value of '-m'; the behavior of the latest stable release of the oldest supported major version of each compiler is shown below and each compiler's latest release exhibits the same behavior (GCC 12.2.0 and Clang 15.0.6).
$ powerpc64-linux-gcc --version | head -1 powerpc64-linux-gcc (GCC) 5.5.0
$ powerpc64-linux-gcc -m64 -### -x assembler-with-cpp -c -o /dev/null /dev/null &| grep 'as ' .../as -a64 -mppc64 -many -mbig -o /dev/null /tmp/cctwuBzZ.s
$ powerpc64-linux-gcc -m32 -### -x assembler-with-cpp -c -o /dev/null /dev/null &| grep 'as ' .../as -a32 -mppc -many -mbig -o /dev/null /tmp/ccaZP4mF.sg
$ clang --version | head -1 Ubuntu clang version 11.1.0-++20211011094159+1fdec59bffc1-1~exp1~20211011214622.5
$ clang --target=powerpc64-linux-gnu -fno-integrated-as -m64 -### \
-x assembler-with-cpp -c -o /dev/null /dev/null &| grep gnu-as
"/usr/bin/powerpc64-linux-gnu-as" "-a64" "-mppc64" "-many" "-o" "/dev/null" "/tmp/null-80267c.s" $ clang --target=powerpc64-linux-gnu -fno-integrated-as -m64 -### \
-x assembler-with-cpp -c -o /dev/null /dev/null &| grep gnu-as
"/usr/bin/powerpc64-linux-gnu-as" "-a32" "-mppc" "-many" "-o" "/dev/null" "/tmp/null-ab8f8d.s"Remove this flag altogether to avoid future issues.
--- arch/powerpc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/Makefile +1 -1
@@ -92,7 +92,7 @@ aflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -mlittle-endian ifeq ($(HAS_BIARCH),y) KBUILD_CFLAGS += -m$(BITS) -KBUILD_AFLAGS += -m$(BITS) -Wl,-a$(BITS) +KBUILD_AFLAGS += -m$(BITS) KBUILD_LDFLAGS += -m elf$(BITS)$(LDEMULATION) endif
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 268/529 builddeb: clean generated package content
In reply to Greg Kroah-HartmanFrom: Bastian Germann <[email protected]>
[ Upstream commit c9f9cf2560e40b62015c6c4a04be60f55ce5240e ]
For each binary Debian package, a directory with the package name is created in the debian directory. Correct the generated file matches in the package's clean target, which were renamed without adjusting the target.
--- scripts/package/mkdebian | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
scripts/package/mkdebian +1 -1
@@ -236,7 +236,7 @@ binary-arch: build-arch KBUILD_BUILD_VERSION=${revision} -f \$(srctree)/Makefile intdeb-pkg clean: - rm -rf debian/*tmp debian/files + rm -rf debian/files debian/linux-* \$(MAKE) clean binary: binary-arch
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 269/529 media: max9286: Fix memleak in max9286_v4l2_register()
In reply to Greg Kroah-HartmanFrom: Shang XiaoJing <[email protected]>
[ Upstream commit 8636c5fc7658c7c6299fb8b352d24ea4b9ba99e2 ]
There is a kmemleak when testing the media/i2c/max9286.c with bpf mock device:
kmemleak: 5 new suspected memory leaks (see /sys/kernel/debug/kmemleak)
unreferenced object 0xffff88810defc400 (size 256):
comm "python3", pid 278, jiffies 4294737563 (age 31.978s) hex dump (first 32 bytes):
28 06 a7 0a 81 88 ff ff 00 fe 22 12 81 88 ff ff (.........".....
10 c4 ef 0d 81 88 ff ff 10 c4 ef 0d 81 88 ff ff ................
backtrace:
[<00000000191de6a7>] __kmalloc_node+0x44/0x1b0
[<000000002f4912b7>] kvmalloc_node+0x34/0x180
[<0000000057dc4cae>] v4l2_ctrl_new+0x325/0x10f0 [videodev]
[<0000000026030272>] v4l2_ctrl_new_std+0x16f/0x210 [videodev]
[<00000000f0d9ea2f>] max9286_probe+0x76e/0xbff [max9286]
[<00000000ea8f6455>] i2c_device_probe+0x28d/0x680
[<0000000087529af3>] really_probe+0x17c/0x3f0
[<00000000b08be526>] __driver_probe_device+0xe3/0x170
[<000000004382edea>] driver_probe_device+0x49/0x120
[<000000007bde528a>] __device_attach_driver+0xf7/0x150
[<000000009f9c6ab4>] bus_for_each_drv+0x114/0x180
[<00000000c8aaf588>] __device_attach+0x1e5/0x2d0
[<0000000041cc06b9>] bus_probe_device+0x126/0x140
[<000000002309860d>] device_add+0x810/0x1130
[<000000002827bf98>] i2c_new_client_device+0x359/0x4f0
[<00000000593bdc85>] of_i2c_register_device+0xf1/0x110max9286_v4l2_register() calls v4l2_ctrl_new_std(), but won't free the created v412_ctrl when fwnode_graph_get_endpoint_by_id() failed, which causes the memleak. Call v4l2_ctrl_handler_free() to free the v412_ctrl.
--- drivers/media/i2c/max9286.c | 1 + 1 file changed, 1 insertion(+)
drivers/media/i2c/max9286.c +1 -0
@@ -890,6 +890,7 @@ static int max9286_v4l2_register(struct max9286_priv *priv) err_put_node:fwnode_handle_put (ep); err_async: +v4l2_ctrl_handler_free (&priv->ctrls);max9286_v4l2_notifier_unregister (priv);return ret;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 270/529 media: ov2740: Fix memleak in ov2740_init_controls()
In reply to Greg Kroah-HartmanFrom: Shang XiaoJing <[email protected]>
[ Upstream commit 2d899592ed7829d0d5140853bac4d58742a6b8af ]
There is a kmemleak when testing the media/i2c/ov2740.c with bpf mock device:
unreferenced object 0xffff8881090e19e0 (size 16):
comm "51-i2c-ov2740", pid 278, jiffies 4294781584 (age 23.613s) hex dump (first 16 bytes):
00 f3 7c 0b 81 88 ff ff 80 75 6a 09 81 88 ff ff ..|......uj.....
backtrace:
[<000000004e9fad8f>] __kmalloc_node+0x44/0x1b0
[<0000000039c802f4>] kvmalloc_node+0x34/0x180
[<000000009b8b5c63>] v4l2_ctrl_handler_init_class+0x11d/0x180
[videodev]
[<0000000038644056>] ov2740_probe+0x37d/0x84f [ov2740]
[<0000000092489f59>] i2c_device_probe+0x28d/0x680
[<000000001038babe>] really_probe+0x17c/0x3f0
[<0000000098c7af1c>] __driver_probe_device+0xe3/0x170
[<00000000e1b3dc24>] device_driver_attach+0x34/0x80
[<000000005a04a34d>] bind_store+0x10b/0x1a0
[<00000000ce25d4f2>] drv_attr_store+0x49/0x70
[<000000007d9f4e9a>] sysfs_kf_write+0x8c/0xb0
[<00000000be6cff0f>] kernfs_fop_write_iter+0x216/0x2e0
[<0000000031ddb40a>] vfs_write+0x658/0x810
[<0000000041beecdd>] ksys_write+0xd6/0x1b0
[<0000000023755840>] do_syscall_64+0x38/0x90
[<00000000b2cc2da2>] entry_SYSCALL_64_after_hwframe+0x63/0xcdov2740_init_controls() won't clean all the allocated resources in fail path, which may causes the memleaks. Add v4l2_ctrl_handler_free() to prevent memleak.
--- drivers/media/i2c/ov2740.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/media/i2c/ov2740.c +3 -1
@@ -577,8 +577,10 @@ static int ov2740_init_controls(struct ov2740 *ov2740)V4L2_CID_TEST_PATTERN ,ARRAY_SIZE (ov2740_test_pattern_menu) -1 , 0, 0, ov2740_test_pattern_menu); -if (ctrl_hdlr->error) +if (ctrl_hdlr->error) { +v4l2_ctrl_handler_free (ctrl_hdlr);return ctrl_hdlr->error; + } ov2740->sd.ctrl_handler = ctrl_hdlr;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 271/529 media: ov5675: Fix memleak in ov5675_init_controls()
In reply to Greg Kroah-HartmanFrom: Shang XiaoJing <[email protected]>
[ Upstream commit dd74ed6c213003533e3abf4c204374ef01d86978 ]
There is a kmemleak when testing the media/i2c/ov5675.c with bpf mock device:
AssertionError: unreferenced object 0xffff888107362160 (size 16):
comm "python3", pid 277, jiffies 4294832798 (age 20.722s) hex dump (first 16 bytes):
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
backtrace:
[<00000000abe7d67c>] __kmalloc_node+0x44/0x1b0
[<000000008a725aac>] kvmalloc_node+0x34/0x180
[<000000009a53cd11>] v4l2_ctrl_handler_init_class+0x11d/0x180
[videodev]
[<0000000055b46db0>] ov5675_probe+0x38b/0x897 [ov5675]
[<00000000153d886c>] i2c_device_probe+0x28d/0x680
[<000000004afb7e8f>] really_probe+0x17c/0x3f0
[<00000000ff2f18e4>] __driver_probe_device+0xe3/0x170
[<000000000a001029>] driver_probe_device+0x49/0x120
[<00000000e39743c7>] __device_attach_driver+0xf7/0x150
[<00000000d32fd070>] bus_for_each_drv+0x114/0x180
[<000000009083ac41>] __device_attach+0x1e5/0x2d0
[<0000000015b4a830>] bus_probe_device+0x126/0x140
[<000000007813deaf>] device_add+0x810/0x1130
[<000000007becb867>] i2c_new_client_device+0x386/0x540
[<000000007f9cf4b4>] of_i2c_register_device+0xf1/0x110
[<00000000ebfdd032>] of_i2c_notify+0xfc/0x1f0ov5675_init_controls() won't clean all the allocated resources in fail path, which may causes the memleaks. Add v4l2_ctrl_handler_free() to prevent memleak.
--- drivers/media/i2c/ov5675.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/media/i2c/ov5675.c +3 -1
@@ -791,8 +791,10 @@ static int ov5675_init_controls(struct ov5675 *ov5675)v4l2_ctrl_new_std (ctrl_hdlr, &ov5675_ctrl_ops,V4L2_CID_VFLIP ,0 ,1 ,1 ,0 ); -if (ctrl_hdlr->error) +if (ctrl_hdlr->error) { +v4l2_ctrl_handler_free (ctrl_hdlr);return ctrl_hdlr->error; + } ov5675->sd.ctrl_handler = ctrl_hdlr;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 272/529 media: i2c: ov772x: Fix memleak in ov772x_probe()
In reply to Greg Kroah-HartmanFrom: Yuan Can <[email protected]>
[ Upstream commit 7485edb2b6ca5960205c0a49bedfd09bba30e521 ]
A memory leak was reported when testing ov772x with bpf mock device:
AssertionError: unreferenced object 0xffff888109afa7a8 (size 8):
comm "python3", pid 279, jiffies 4294805921 (age 20.681s) hex dump (first 8 bytes):
80 22 88 15 81 88 ff ff ."......
backtrace:
[<000000009990b438>] __kmalloc_node+0x44/0x1b0
[<000000009e32f7d7>] kvmalloc_node+0x34/0x180
[<00000000faf48134>] v4l2_ctrl_handler_init_class+0x11d/0x180 [videodev]
[<00000000da376937>] ov772x_probe+0x1c3/0x68c [ov772x]
[<000000003f0d225e>] i2c_device_probe+0x28d/0x680
[<00000000e0b6db89>] really_probe+0x17c/0x3f0
[<000000001b19fcee>] __driver_probe_device+0xe3/0x170
[<0000000048370519>] driver_probe_device+0x49/0x120
[<000000005ead07a0>] __device_attach_driver+0xf7/0x150
[<0000000043f452b8>] bus_for_each_drv+0x114/0x180
[<00000000358e5596>] __device_attach+0x1e5/0x2d0
[<0000000043f83c5d>] bus_probe_device+0x126/0x140
[<00000000ee0f3046>] device_add+0x810/0x1130
[<00000000e0278184>] i2c_new_client_device+0x359/0x4f0
[<0000000070baf34f>] of_i2c_register_device+0xf1/0x110
[<00000000a9f2159d>] of_i2c_notify+0x100/0x160
unreferenced object 0xffff888119825c00 (size 256):
comm "python3", pid 279, jiffies 4294805921 (age 20.681s)
hex dump (first 32 bytes):
00 b4 a5 17 81 88 ff ff 00 5e 82 19 81 88 ff ff .........^......
10 5c 82 19 81 88 ff ff 10 5c 82 19 81 88 ff ff .\.......\......
backtrace:
[<000000009990b438>] __kmalloc_node+0x44/0x1b0
[<000000009e32f7d7>] kvmalloc_node+0x34/0x180
[<0000000073d88e0b>] v4l2_ctrl_new.cold+0x19b/0x86f [videodev]
[<00000000b1f576fb>] v4l2_ctrl_new_std+0x16f/0x210 [videodev]
[<00000000caf7ac99>] ov772x_probe+0x1fa/0x68c [ov772x]
[<000000003f0d225e>] i2c_device_probe+0x28d/0x680
[<00000000e0b6db89>] really_probe+0x17c/0x3f0
[<000000001b19fcee>] __driver_probe_device+0xe3/0x170
[<0000000048370519>] driver_probe_device+0x49/0x120
[<000000005ead07a0>] __device_attach_driver+0xf7/0x150
[<0000000043f452b8>] bus_for_each_drv+0x114/0x180
[<00000000358e5596>] __device_attach+0x1e5/0x2d0
[<0000000043f83c5d>] bus_probe_device+0x126/0x140
[<00000000ee0f3046>] device_add+0x810/0x1130
[<00000000e0278184>] i2c_new_client_device+0x359/0x4f0
[<0000000070baf34f>] of_i2c_register_device+0xf1/0x110The reason is that if priv->hdl.error is set, ov772x_probe() jumps to the error_mutex_destroy without doing v4l2_ctrl_handler_free(), and all resources allocated in v4l2_ctrl_handler_init() and v4l2_ctrl_new_std() are leaked.
--- drivers/media/i2c/ov772x.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/media/i2c/ov772x.c +1 -2
@@ -1397,7 +1397,7 @@ static int ov772x_probe(struct i2c_client *client) priv->subdev.ctrl_handler = &priv->hdl;if (priv->hdl.error) { ret = priv->hdl.error; - goto error_mutex_destroy; + goto error_ctrl_free; } priv->clk =clk_get (&client->dev,NULL );
@@ -1446,7 +1446,6 @@ static int ov772x_probe(struct i2c_client *client)clk_put (priv->clk); error_ctrl_free:v4l2_ctrl_handler_free (&priv->hdl); -error_mutex_destroy:mutex_destroy (&priv->lock);return ret;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 273/529 media: i2c: imx219: remove redundant writes
In reply to Greg Kroah-HartmanFrom: Sameer Puri <[email protected]>
[ Upstream commit fbef89886da6d7735d20fdde16a1ee6ed6c6ab56 ]
These writes to 0x162, 0x163 already appear earlier in the struct for the 1920x1080 mode and do not need to be repeated.
Stable-dep-of: ef86447e775f ("media: i2c: imx219: Fix binning for RAW8 capture")
--- drivers/media/i2c/imx219.c | 2 -- 1 file changed, 2 deletions(-)
drivers/media/i2c/imx219.c +0 -2
@@ -262,8 +262,6 @@ static const struct imx219_reg mode_1920_1080_regs[] = { {0x4793, 0x10}, {0x4797, 0x0e}, {0x479b, 0x0e}, - {0x0162, 0x0d}, - {0x0163, 0x78}, }; static const struct imx219_reg mode_1640_1232_regs[] = {
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 274/529 media: i2c: imx219: Split common registers from mode tables
In reply to Greg Kroah-HartmanFrom: Adam Ford <[email protected]>
[ Upstream commit 8508455961d5a9e8907bcfd8dcd58f19d9b6ce47 ]
There are four modes, and each mode has a table of registers. Some of the registers are common to all modes, so create new tables for these common registers to reduce duplicate code.
Stable-dep-of: ef86447e775f ("media: i2c: imx219: Fix binning for RAW8 capture")
--- drivers/media/i2c/imx219.c | 206 +++++++++++-------------------------- 1 file changed, 59 insertions(+), 147 deletions(-)
drivers/media/i2c/imx219.c +59 -147
@@ -145,23 +145,61 @@ struct imx219_mode {struct imx219_reg_list reg_list; }; -/* -* Register sets lifted off the i2C interface from the Raspberry Pi firmware -* driver. -* 3280x2464 = mode 2, 1920x1080 = mode 1, 1640x1232 = mode 4, 640x480 = mode 7. -*/ -static const struct imx219_reg mode_3280x2464_regs[] = { - {0x0100 ,0x00 }, +static const struct imx219_reg imx219_common_regs[] = { + {0x0100 ,0x00 },/* Mode Select */ + +/* To Access Addresses 3000-5fff, send the following commands */ {0x30eb ,0x0c }, {0x30eb ,0x05 }, {0x300a ,0xff }, {0x300b ,0xff }, {0x30eb ,0x05 }, {0x30eb ,0x09 }, - {0x0114 ,0x01 }, - {0x0128 ,0x00 }, - {0x012a ,0x18 }, + +/* PLL Clock Table */ + {0x0301 ,0x05 },/* VTPXCK_DIV */ + {0x0303 ,0x01 },/* VTSYSCK_DIV */ + {0x0304 ,0x03 },/* PREPLLCK_VT_DIV 0x03 = AUTO set */ + {0x0305 ,0x03 },/* PREPLLCK_OP_DIV 0x03 = AUTO set */ + {0x0306 ,0x00 },/* PLL_VT_MPY */ + {0x0307 ,0x39 }, + {0x030b ,0x01 },/* OP_SYS_CLK_DIV */ + {0x030c ,0x00 },/* PLL_OP_MPY */ + {0x030d ,0x72 }, + +/* Undocumented registers */ + {0x455e ,0x00 }, + {0x471e ,0x4b }, + {0x4767 ,0x0f }, + {0x4750 ,0x14 }, + {0x4540 ,0x00 }, + {0x47b4 ,0x14 }, + {0x4713 ,0x30 }, + {0x478b ,0x10 }, + {0x478f ,0x10 }, + {0x4793 ,0x10 }, + {0x4797 ,0x0e }, + {0x479b ,0x0e }, + +/* Frame Bank Register Group "A" */ + {0x0162 ,0x0d },/* Line_Length_A */ + {0x0163 ,0x78 }, + {0x0170 ,0x01 },/* X_ODD_INC_A */ + {0x0171 ,0x01 },/* Y_ODD_INC_A */ + +/* Output setup registers */ + {0x0114 ,0x01 },/* CSI 2-Lane Mode */ + {0x0128 ,0x00 },/* DPHY Auto Mode */ + {0x012a ,0x18 },/* EXCK_Freq */ {0x012b ,0x00 }, +}; + +/* +* Register sets lifted off the i2C interface from the Raspberry Pi firmware +* driver. +* 3280x2464 = mode 2, 1920x1080 = mode 1, 1640x1232 = mode 4, 640x480 = mode 7. +*/ +static const struct imx219_reg mode_3280x2464_regs[] = { {0x0164 ,0x00 }, {0x0165 ,0x00 }, {0x0166 ,0x0c },
@@ -174,53 +212,15 @@ static const struct imx219_reg mode_3280x2464_regs[] = { {0x016d, 0xd0}, {0x016e, 0x09}, {0x016f, 0xa0}, - {0x0170, 0x01}, - {0x0171, 0x01}, - {0x0174, 0x00}, + {0x0174, 0x00}, /* No-Binning */ {0x0175, 0x00}, - {0x0301, 0x05}, - {0x0303, 0x01}, - {0x0304, 0x03}, - {0x0305, 0x03}, - {0x0306, 0x00}, - {0x0307, 0x39}, - {0x030b, 0x01}, - {0x030c, 0x00}, - {0x030d, 0x72}, {0x0624, 0x0c}, {0x0625, 0xd0}, {0x0626, 0x09}, {0x0627, 0xa0}, - {0x455e, 0x00}, - {0x471e, 0x4b}, - {0x4767, 0x0f}, - {0x4750, 0x14}, - {0x4540, 0x00}, - {0x47b4, 0x14}, - {0x4713, 0x30}, - {0x478b, 0x10}, - {0x478f, 0x10}, - {0x4793, 0x10}, - {0x4797, 0x0e}, - {0x479b, 0x0e}, - {0x0162, 0x0d}, - {0x0163, 0x78}, };static const struct imx219_reg mode_1920_1080_regs[] = { - {0x0100 ,0x00 }, - {0x30eb ,0x05 }, - {0x30eb ,0x0c }, - {0x300a ,0xff }, - {0x300b ,0xff }, - {0x30eb ,0x05 }, - {0x30eb ,0x09 }, - {0x0114 ,0x01 }, - {0x0128 ,0x00 }, - {0x012a ,0x18 }, - {0x012b ,0x00 }, - {0x0162 ,0x0d }, - {0x0163 ,0x78 }, {0x0164 ,0x02 }, {0x0165 ,0xa8 }, {0x0166, 0x0a},
@@ -233,49 +233,15 @@ static const struct imx219_reg mode_1920_1080_regs[] = { {0x016d, 0x80}, {0x016e, 0x04}, {0x016f, 0x38}, - {0x0170, 0x01}, - {0x0171, 0x01}, - {0x0174, 0x00}, + {0x0174, 0x00}, /* No-Binning */ {0x0175, 0x00}, - {0x0301, 0x05}, - {0x0303, 0x01}, - {0x0304, 0x03}, - {0x0305, 0x03}, - {0x0306, 0x00}, - {0x0307, 0x39}, - {0x030b, 0x01}, - {0x030c, 0x00}, - {0x030d, 0x72}, {0x0624, 0x07}, {0x0625, 0x80}, {0x0626, 0x04}, {0x0627, 0x38}, - {0x455e, 0x00}, - {0x471e, 0x4b}, - {0x4767, 0x0f}, - {0x4750, 0x14}, - {0x4540, 0x00}, - {0x47b4, 0x14}, - {0x4713, 0x30}, - {0x478b, 0x10}, - {0x478f, 0x10}, - {0x4793, 0x10}, - {0x4797, 0x0e}, - {0x479b, 0x0e}, };static const struct imx219_reg mode_1640_1232_regs[] = { - {0x0100 ,0x00 }, - {0x30eb ,0x0c }, - {0x30eb ,0x05 }, - {0x300a ,0xff }, - {0x300b ,0xff }, - {0x30eb ,0x05 }, - {0x30eb ,0x09 }, - {0x0114 ,0x01 }, - {0x0128 ,0x00 }, - {0x012a ,0x18 }, - {0x012b ,0x00 }, {0x0164 ,0x00 }, {0x0165 ,0x00 }, {0x0166, 0x0c},
@@ -288,53 +254,15 @@ static const struct imx219_reg mode_1640_1232_regs[] = { {0x016d, 0x68}, {0x016e, 0x04}, {0x016f, 0xd0}, - {0x0170, 0x01}, - {0x0171, 0x01}, - {0x0174, 0x01}, + {0x0174, 0x01}, /* x2-Binning */ {0x0175, 0x01}, - {0x0301, 0x05}, - {0x0303, 0x01}, - {0x0304, 0x03}, - {0x0305, 0x03}, - {0x0306, 0x00}, - {0x0307, 0x39}, - {0x030b, 0x01}, - {0x030c, 0x00}, - {0x030d, 0x72}, {0x0624, 0x06}, {0x0625, 0x68}, {0x0626, 0x04}, {0x0627, 0xd0}, - {0x455e, 0x00}, - {0x471e, 0x4b}, - {0x4767, 0x0f}, - {0x4750, 0x14}, - {0x4540, 0x00}, - {0x47b4, 0x14}, - {0x4713, 0x30}, - {0x478b, 0x10}, - {0x478f, 0x10}, - {0x4793, 0x10}, - {0x4797, 0x0e}, - {0x479b, 0x0e}, - {0x0162, 0x0d}, - {0x0163, 0x78}, };static const struct imx219_reg mode_640_480_regs[] = { - {0x0100 ,0x00 }, - {0x30eb ,0x05 }, - {0x30eb ,0x0c }, - {0x300a ,0xff }, - {0x300b ,0xff }, - {0x30eb ,0x05 }, - {0x30eb ,0x09 }, - {0x0114 ,0x01 }, - {0x0128 ,0x00 }, - {0x012a ,0x18 }, - {0x012b ,0x00 }, - {0x0162 ,0x0d }, - {0x0163 ,0x78 }, {0x0164 ,0x03 }, {0x0165 ,0xe8 }, {0x0166, 0x08},
@@ -347,35 +275,12 @@ static const struct imx219_reg mode_640_480_regs[] = { {0x016d, 0x80}, {0x016e, 0x01}, {0x016f, 0xe0}, - {0x0170, 0x01}, - {0x0171, 0x01}, - {0x0174, 0x03}, + {0x0174, 0x03}, /* x2-analog binning */ {0x0175, 0x03}, - {0x0301, 0x05}, - {0x0303, 0x01}, - {0x0304, 0x03}, - {0x0305, 0x03}, - {0x0306, 0x00}, - {0x0307, 0x39}, - {0x030b, 0x01}, - {0x030c, 0x00}, - {0x030d, 0x72}, {0x0624, 0x06}, {0x0625, 0x68}, {0x0626, 0x04}, {0x0627, 0xd0}, - {0x455e, 0x00}, - {0x471e, 0x4b}, - {0x4767, 0x0f}, - {0x4750, 0x14}, - {0x4540, 0x00}, - {0x47b4, 0x14}, - {0x4713, 0x30}, - {0x478b, 0x10}, - {0x478f, 0x10}, - {0x4793, 0x10}, - {0x4797, 0x0e}, - {0x479b, 0x0e}, }; static const struct imx219_reg raw8_framefmt_regs[] = {
@@ -1030,6 +935,13 @@ static int imx219_start_streaming(struct imx219 *imx219)return ret; } +/* Send all registers that are common to all modes */ + ret =imx219_write_regs (imx219, imx219_common_regs,ARRAY_SIZE (imx219_common_regs)); +if (ret) { +dev_err (&client->dev,"%s failed to send mfg header\n" , __func__); + goto err_rpm_put; + } +/* Apply default values of current mode */ reg_list = &imx219->mode->reg_list; ret =imx219_write_regs (imx219, reg_list->regs, reg_list->num_of_regs);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 275/529 media: i2c: imx219: Fix binning for RAW8 capture
In reply to Greg Kroah-HartmanFrom: Jai Luthra <[email protected]>
[ Upstream commit ef86447e775fb1f2ced00d4c7fff2c0a1c63f165 ]
2x2 binning works fine for RAW10 capture, but for RAW8 1232p mode it leads to corrupted frames [1][2].
Using the special 2x2 analog binning mode fixes the issue, but causes artefacts for RAW10 1232p capture. So here we choose the binning mode depending upon the frame format selected.
As both binning modes work fine for 480p RAW8 and RAW10 capture, it can share the same code path as 1232p for selecting binning mode.
[1] https://forums.raspberrypi.com/viewtopic.php?t=332103
[2] https://github.com/raspberrypi/libcamera-apps/issues/281
--- drivers/media/i2c/imx219.c | 57 ++++++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 8 deletions(-)
drivers/media/i2c/imx219.c +49 -8
@@ -89,6 +89,12 @@#define IMX219_REG_ORIENTATION 0x0172 +/* Binning Mode */ +#define IMX219_REG_BINNING_MODE 0x0174 +#define IMX219_BINNING_NONE 0x0000 +#define IMX219_BINNING_2X2 0x0101 +#define IMX219_BINNING_2X2_ANALOG 0x0303 +/* Test Pattern Control */ #define IMX219_REG_TEST_PATTERN 0x0600#define IMX219_TEST_PATTERN_DISABLE 0
@@ -143,6 +149,9 @@ struct imx219_mode {/* Default register values */ struct imx219_reg_list reg_list; + +/* 2x2 binning is used */ +bool binning; };static const struct imx219_reg imx219_common_regs[] = {
@@ -212,8 +221,6 @@ static const struct imx219_reg mode_3280x2464_regs[] = { {0x016d, 0xd0}, {0x016e, 0x09}, {0x016f, 0xa0}, - {0x0174, 0x00}, /* No-Binning */ - {0x0175, 0x00}, {0x0624, 0x0c}, {0x0625, 0xd0}, {0x0626, 0x09},
@@ -233,8 +240,6 @@ static const struct imx219_reg mode_1920_1080_regs[] = { {0x016d, 0x80}, {0x016e, 0x04}, {0x016f, 0x38}, - {0x0174, 0x00}, /* No-Binning */ - {0x0175, 0x00}, {0x0624, 0x07}, {0x0625, 0x80}, {0x0626, 0x04},
@@ -254,8 +259,6 @@ static const struct imx219_reg mode_1640_1232_regs[] = { {0x016d, 0x68}, {0x016e, 0x04}, {0x016f, 0xd0}, - {0x0174, 0x01}, /* x2-Binning */ - {0x0175, 0x01}, {0x0624, 0x06}, {0x0625, 0x68}, {0x0626, 0x04},
@@ -275,8 +278,6 @@ static const struct imx219_reg mode_640_480_regs[] = { {0x016d, 0x80}, {0x016e, 0x01}, {0x016f, 0xe0}, - {0x0174, 0x03}, /* x2-analog binning */ - {0x0175, 0x03}, {0x0624, 0x06}, {0x0625, 0x68}, {0x0626, 0x04},
@@ -386,6 +387,7 @@ static const struct imx219_mode supported_modes[] = { .num_of_regs = ARRAY_SIZE(mode_3280x2464_regs), .regs = mode_3280x2464_regs, }, + .binning = false, }, {/* 1080P 30fps cropped */
@@ -402,6 +404,7 @@ static const struct imx219_mode supported_modes[] = { .num_of_regs = ARRAY_SIZE(mode_1920_1080_regs), .regs = mode_1920_1080_regs, }, + .binning = false, }, {/* 2x2 binned 30fps mode */
@@ -418,6 +421,7 @@ static const struct imx219_mode supported_modes[] = { .num_of_regs = ARRAY_SIZE(mode_1640_1232_regs), .regs = mode_1640_1232_regs, }, + .binning = true, }, {/* 640x480 30fps mode */
@@ -434,6 +438,7 @@ static const struct imx219_mode supported_modes[] = { .num_of_regs = ARRAY_SIZE(mode_640_480_regs), .regs = mode_640_480_regs, }, + .binning = true, }, };
@@ -872,6 +877,35 @@ static int imx219_set_framefmt(struct imx219 *imx219)return -EINVAL ; } +static int imx219_set_binning (struct imx219 *imx219) +{ +if (!imx219->mode->binning) { +return imx219_write_reg (imx219,IMX219_REG_BINNING_MODE , +IMX219_REG_VALUE_16BIT , +IMX219_BINNING_NONE ); + } + +switch (imx219->fmt.code) { +case MEDIA_BUS_FMT_SRGGB8_1X8 : +case MEDIA_BUS_FMT_SGRBG8_1X8 : +case MEDIA_BUS_FMT_SGBRG8_1X8 : +case MEDIA_BUS_FMT_SBGGR8_1X8 : +return imx219_write_reg (imx219,IMX219_REG_BINNING_MODE , +IMX219_REG_VALUE_16BIT , +IMX219_BINNING_2X2_ANALOG ); + +case MEDIA_BUS_FMT_SRGGB10_1X10 : +case MEDIA_BUS_FMT_SGRBG10_1X10 : +case MEDIA_BUS_FMT_SGBRG10_1X10 : +case MEDIA_BUS_FMT_SBGGR10_1X10 : +return imx219_write_reg (imx219,IMX219_REG_BINNING_MODE , +IMX219_REG_VALUE_16BIT , +IMX219_BINNING_2X2 ); + } + +return -EINVAL ; +} +static const struct v4l2_rect *__imx219_get_pad_crop (struct imx219 *imx219,struct v4l2_subdev_pad_config *cfg,unsigned int pad,enum v4l2_subdev_format_whence which)
@@ -957,6 +991,13 @@ static int imx219_start_streaming(struct imx219 *imx219) goto err_rpm_put; } + ret =imx219_set_binning (imx219); +if (ret) { +dev_err (&client->dev,"%s failed to set binning: %d\n" , + __func__, ret); + goto err_rpm_put; + } +/* Apply customized values from user */ ret =__v4l2_ctrl_handler_setup (imx219->sd.ctrl_handler);if (ret)
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 276/529 media: rc: Fix use-after-free bugs caused by ene_tx_irqsim()
In reply to Greg Kroah-HartmanFrom: Duoming Zhou <[email protected]>
[ Upstream commit 29b0589a865b6f66d141d79b2dd1373e4e50fe17 ]
When the ene device is detaching, function ene_remove() will be called. But there is no function to cancel tx_sim_timer in ene_remove(), the timer handler ene_tx_irqsim() could race with ene_remove(). As a result, the UAF bugs could happen, the process is shown below.
(cleanup routine) | (timer routine)
| mod_timer(&dev->tx_sim_timer, ..)
ene_remove() | (wait a time)
| ene_tx_irqsim()
| dev->hw_lock //USE
| ene_tx_sample(dev) //USEFix by adding del_timer_sync(&dev->tx_sim_timer) in ene_remove(), The tx_sim_timer could stop before ene device is deallocated.
What's more, The rc_unregister_device() and del_timer_sync() should be called first in ene_remove() and the deallocated functions such as free_irq(), release_region() and so on should be called behind them. Because the rc_unregister_device() is well synchronized. Otherwise, race conditions may happen. The situations that may lead to race conditions are shown below.
Firstly, the rx receiver is disabled with ene_rx_disable() before rc_unregister_device() in ene_remove(), which means it can be enabled again if a process opens /dev/lirc0 between ene_rx_disable() and rc_unregister_device().
Secondly, the irqaction descriptor is freed by free_irq() before the rc device is unregistered, which means irqaction descriptor may be accessed again after it is deallocated.
Thirdly, the timer can call ene_tx_sample() that can write to the io ports, which means the io ports could be accessed again after they are deallocated by release_region().
Therefore, the rc_unregister_device() and del_timer_sync() should be called first in ene_remove().
Suggested by: Sean Young <[email protected]>
--- drivers/media/rc/ene_ir.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/media/rc/ene_ir.c +2 -1
@@ -1106,6 +1106,8 @@ static void ene_remove(struct pnp_dev *pnp_dev)struct ene_device *dev =pnp_get_drvdata (pnp_dev);unsigned long flags; +rc_unregister_device (dev->rdev); +del_timer_sync (&dev->tx_sim_timer);spin_lock_irqsave (&dev->hw_lock, flags);ene_rx_disable (dev);ene_rx_restore_hw_buffer (dev);
@@ -1113,7 +1115,6 @@ static void ene_remove(struct pnp_dev *pnp_dev)free_irq (dev->irq, dev);release_region (dev->hw_io,ENE_IO_SIZE ); -rc_unregister_device (dev->rdev);kfree (dev); }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 277/529 media: i2c: ov7670: 0 instead of -EINVAL was returned
In reply to Greg Kroah-HartmanFrom: Hans Verkuil <[email protected]>
[ Upstream commit 6a4c664539e6de9b32b65ddcf767ec1bcc1d7f8a ]
If the media bus is unsupported, then return -EINVAL. Instead it returned 'ret' which happened to be 0.
This fixes a smatch warning:
ov7670.c:1843 ov7670_parse_dt() warn: missing error code? 'ret'
--- drivers/media/i2c/ov7670.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/i2c/ov7670.c +1 -1
@@ -1824,7 +1824,7 @@ static int ov7670_parse_dt(struct device *dev,if (bus_cfg.bus_type !=V4L2_MBUS_PARALLEL ) {dev_err (dev,"Unsupported media bus type\n" ); -return ret; +return -EINVAL ; } info->mbus_config = bus_cfg.bus.parallel.flags;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 278/529 media: usb: siano: Fix use after free bugs caused by do_submit_urb
In reply to Greg Kroah-HartmanFrom: Duoming Zhou <[email protected]>
[ Upstream commit ebad8e731c1c06adf04621d6fd327b860c0861b5 ]
There are UAF bugs caused by do_submit_urb(). One of the KASan reports is shown below:
[ 36.403605] BUG: KASAN: use-after-free in worker_thread+0x4a2/0x890 [ 36.406105] Read of size 8 at addr ffff8880059600e8 by task kworker/0:2/49 [ 36.408316] [ 36.408867] CPU: 0 PID: 49 Comm: kworker/0:2 Not tainted 6.2.0-rc3-15798-g5a41237ad1d4-dir8 [ 36.411696] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g15584 [ 36.416157] Workqueue: 0x0 (events) [ 36.417654] Call Trace: [ 36.418546] <TASK> [ 36.419320] dump_stack_lvl+0x96/0xd0 [ 36.420522] print_address_description+0x75/0x350 [ 36.421992] print_report+0x11b/0x250 [ 36.423174] ? _raw_spin_lock_irqsave+0x87/0xd0 [ 36.424806] ? __virt_addr_valid+0xcf/0x170 [ 36.426069] ? worker_thread+0x4a2/0x890 [ 36.427355] kasan_report+0x131/0x160 [ 36.428556] ? worker_thread+0x4a2/0x890 [ 36.430053] worker_thread+0x4a2/0x890 [ 36.431297] ? worker_clr_flags+0x90/0x90 [ 36.432479] kthread+0x166/0x190 [ 36.433493] ? kthread_blkcg+0x50/0x50 [ 36.434669] ret_from_fork+0x22/0x30 [ 36.435923] </TASK> [ 36.436684] [ 36.437215] Allocated by task 24: [ 36.438289] kasan_set_track+0x50/0x80 [ 36.439436] __kasan_kmalloc+0x89/0xa0 [ 36.440566] smsusb_probe+0x374/0xc90 [ 36.441920] usb_probe_interface+0x2d1/0x4c0 [ 36.443253] really_probe+0x1d5/0x580 [ 36.444539] __driver_probe_device+0xe3/0x130 [ 36.446085] driver_probe_device+0x49/0x220 [ 36.447423] __device_attach_driver+0x19e/0x1b0 [ 36.448931] bus_for_each_drv+0xcb/0x110 [ 36.450217] __device_attach+0x132/0x1f0 [ 36.451470] bus_probe_device+0x59/0xf0 [ 36.452563] device_add+0x4ec/0x7b0 [ 36.453830] usb_set_configuration+0xc63/0xe10 [ 36.455230] usb_generic_driver_probe+0x3b/0x80 [ 36.456166] printk: console [ttyGS0] disabled [ 36.456569] usb_probe_device+0x90/0x110 [ 36.459523] really_probe+0x1d5/0x580 [ 36.461027] __driver_probe_device+0xe3/0x130 [ 36.462465] driver_probe_device+0x49/0x220 [ 36.463847] __device_attach_driver+0x19e/0x1b0 [ 36.465229] bus_for_each_drv+0xcb/0x110 [ 36.466466] __device_attach+0x132/0x1f0 [ 36.467799] bus_probe_device+0x59/0xf0 [ 36.469010] device_add+0x4ec/0x7b0 [ 36.470125] usb_new_device+0x863/0xa00 [ 36.471374] hub_event+0x18c7/0x2220 [ 36.472746] process_one_work+0x34c/0x5b0 [ 36.474041] worker_thread+0x4b7/0x890 [ 36.475216] kthread+0x166/0x190 [ 36.476267] ret_from_fork+0x22/0x30 [ 36.477447] [ 36.478160] Freed by task 24: [ 36.479239] kasan_set_track+0x50/0x80 [ 36.480512] kasan_save_free_info+0x2b/0x40 [ 36.481808] ____kasan_slab_free+0x122/0x1a0 [ 36.483173] __kmem_cache_free+0xc4/0x200 [ 36.484563] smsusb_term_device+0xcd/0xf0 [ 36.485896] smsusb_probe+0xc85/0xc90 [ 36.486976] usb_probe_interface+0x2d1/0x4c0 [ 36.488303] really_probe+0x1d5/0x580 [ 36.489498] __driver_probe_device+0xe3/0x130 [ 36.491140] driver_probe_device+0x49/0x220 [ 36.492475] __device_attach_driver+0x19e/0x1b0 [ 36.493988] bus_for_each_drv+0xcb/0x110 [ 36.495171] __device_attach+0x132/0x1f0 [ 36.496617] bus_probe_device+0x59/0xf0 [ 36.497875] device_add+0x4ec/0x7b0 [ 36.498972] usb_set_configuration+0xc63/0xe10 [ 36.500264] usb_generic_driver_probe+0x3b/0x80 [ 36.501740] usb_probe_device+0x90/0x110 [ 36.503084] really_probe+0x1d5/0x580 [ 36.504241] __driver_probe_device+0xe3/0x130 [ 36.505548] driver_probe_device+0x49/0x220 [ 36.506766] __device_attach_driver+0x19e/0x1b0 [ 36.508368] bus_for_each_drv+0xcb/0x110 [ 36.509646] __device_attach+0x132/0x1f0 [ 36.510911] bus_probe_device+0x59/0xf0 [ 36.512103] device_add+0x4ec/0x7b0 [ 36.513215] usb_new_device+0x863/0xa00 [ 36.514736] hub_event+0x18c7/0x2220 [ 36.516130] process_one_work+0x34c/0x5b0 [ 36.517396] worker_thread+0x4b7/0x890 [ 36.518591] kthread+0x166/0x190 [ 36.519599] ret_from_fork+0x22/0x30 [ 36.520851] [ 36.521405] Last potentially related work creation: [ 36.523143] kasan_save_stack+0x3f/0x60 [ 36.524275] kasan_record_aux_stack_noalloc+0x9d/0xb0 [ 36.525831] insert_work+0x25/0x130 [ 36.527039] __queue_work+0x4d4/0x620 [ 36.528236] queue_work_on+0x72/0xb0 [ 36.529344] __usb_hcd_giveback_urb+0x13f/0x1b0 [ 36.530819] dummy_timer+0x350/0x1a40 [ 36.532149] call_timer_fn+0x2c/0x190 [ 36.533567] expire_timers+0x69/0x1f0 [ 36.534736] __run_timers+0x289/0x2d0 [ 36.535841] run_timer_softirq+0x2d/0x60 [ 36.537110] __do_softirq+0x116/0x380 [ 36.538377] [ 36.538950] Second to last potentially related work creation: [ 36.540855] kasan_save_stack+0x3f/0x60 [ 36.542084] kasan_record_aux_stack_noalloc+0x9d/0xb0 [ 36.543592] insert_work+0x25/0x130 [ 36.544891] __queue_work+0x4d4/0x620 [ 36.546168] queue_work_on+0x72/0xb0 [ 36.547328] __usb_hcd_giveback_urb+0x13f/0x1b0 [ 36.548805] dummy_timer+0x350/0x1a40 [ 36.550116] call_timer_fn+0x2c/0x190 [ 36.551570] expire_timers+0x69/0x1f0 [ 36.552762] __run_timers+0x289/0x2d0 [ 36.553916] run_timer_softirq+0x2d/0x60 [ 36.555118] __do_softirq+0x116/0x380 [ 36.556239] [ 36.556807] The buggy address belongs to the object at ffff888005960000 [ 36.556807] which belongs to the cache kmalloc-4k of size 4096 [ 36.560652] The buggy address is located 232 bytes inside of [ 36.560652] 4096-byte region [ffff888005960000, ffff888005961000) [ 36.564791] [ 36.565355] The buggy address belongs to the physical page: [ 36.567212] page:000000004f0a0731 refcount:1 mapcount:0 mapping:0000000000000000 index:0x00 [ 36.570534] head:000000004f0a0731 order:3 compound_mapcount:0 subpages_mapcount:0 compound0 [ 36.573717] flags: 0x100000000010200(slab|head|node=0|zone=1) [ 36.575481] raw: 0100000000010200 ffff888001042140 dead000000000122 0000000000000000 [ 36.577842] raw: 0000000000000000 0000000000040004 00000001ffffffff 0000000000000000 [ 36.580175] page dumped because: kasan: bad access detected [ 36.581994] [ 36.582548] Memory state around the buggy address: [ 36.583983] ffff88800595ff80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 36.586240] ffff888005960000: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 36.588884] >ffff888005960080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 36.591071] ^ [ 36.593295] ffff888005960100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 36.595705] ffff888005960180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 36.598026] ================================================================== [ 36.600224] Disabling lock debugging due to kernel taint [ 36.602681] general protection fault, probably for non-canonical address 0x43600a000000060I [ 36.607129] CPU: 0 PID: 49 Comm: kworker/0:2 Tainted: G B 6.2.0-rc3-15798-8 [ 36.611115] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g15584 [ 36.615026] Workqueue: events do_submit_urb [ 36.616290] RIP: 0010:_raw_spin_lock_irqsave+0x8a/0xd0 [ 36.618107] Code: 24 00 00 00 00 48 89 df be 04 00 00 00 e8 9e b5 c6 fe 48 89 ef be 04 00 5 [ 36.623522] RSP: 0018:ffff888004b6fcf0 EFLAGS: 00010046 [ 36.625072] RAX: 0000000000000000 RBX: 043600a000000060 RCX: ffffffff9fc0e0d7 [ 36.627206] RDX: 0000000000000000 RSI: dffffc0000000000 RDI: ffff888004b6fcf0 [ 36.629813] RBP: ffff888004b6fcf0 R08: dffffc0000000000 R09: ffffed100096df9f [ 36.631974] R10: dfffe9100096dfa0 R11: 1ffff1100096df9e R12: ffff888005960020 [ 36.634285] R13: ffff8880059600f0 R14: 0000000000000246 R15: 0000000000000001 [ 36.636438] FS: 0000000000000000(0000) GS:ffff88806d600000(0000) knlGS:0000000000000000 [ 36.639092] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 36.640951] CR2: 00007f07476819a3 CR3: 0000000004a34000 CR4: 00000000000006f0 [ 36.643411] Call Trace: [ 36.644215] <TASK> [ 36.644902] smscore_getbuffer+0x3e/0x1e0 [ 36.646147] do_submit_urb+0x4f/0x190 [ 36.647449] process_one_work+0x34c/0x5b0 [ 36.648777] worker_thread+0x4b7/0x890 [ 36.649984] ? worker_clr_flags+0x90/0x90 [ 36.651166] kthread+0x166/0x190 [ 36.652151] ? kthread_blkcg+0x50/0x50 [ 36.653547] ret_from_fork+0x22/0x30 [ 36.655051] </TASK> [ 36.655733] Modules linked in: [ 36.656787] ---[ end trace 0000000000000000 ]--- [ 36.658328] RIP: 0010:_raw_spin_lock_irqsave+0x8a/0xd0 [ 36.660045] Code: 24 00 00 00 00 48 89 df be 04 00 00 00 e8 9e b5 c6 fe 48 89 ef be 04 00 5 [ 36.665730] RSP: 0018:ffff888004b6fcf0 EFLAGS: 00010046 [ 36.667448] RAX: 0000000000000000 RBX: 043600a000000060 RCX: ffffffff9fc0e0d7 [ 36.669675] RDX: 0000000000000000 RSI: dffffc0000000000 RDI: ffff888004b6fcf0 [ 36.672645] RBP: ffff888004b6fcf0 R08: dffffc0000000000 R09: ffffed100096df9f [ 36.674921] R10: dfffe9100096dfa0 R11: 1ffff1100096df9e R12: ffff888005960020 [ 36.677034] R13: ffff8880059600f0 R14: 0000000000000246 R15: 0000000000000001 [ 36.679184] FS: 0000000000000000(0000) GS:ffff88806d600000(0000) knlGS:0000000000000000 [ 36.681655] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 36.683383] CR2: 00007f07476819a3 CR3: 0000000004a34000 CR4: 00000000000006f0 [ 36.685733] Kernel panic - not syncing: Fatal exception [ 36.688585] Kernel Offset: 0x1d400000 from 0xffffffff81000000 (relocation range: 0xfffffff) [ 36.692199] ---[ end Kernel panic - not syncing: Fatal exception ]---
When the siano device is plugged in, it may call the following functions to initialize the device.
smsusb_probe()-->smsusb_init_device()-->smscore_start_device().
When smscore_start_device() gets failed, the function smsusb_term_device() will be called and smsusb_device_t will be deallocated. Although we use usb_kill_urb() in smsusb_stop_streaming() to cancel transfer requests and wait for them to finish, the worker threads that are scheduled by smsusb_onresponse() may be still running. As a result, the UAF bugs could happen.
We add cancel_work_sync() in smsusb_stop_streaming() in order that the worker threads could finish before the smsusb_device_t is deallocated.
--- drivers/media/usb/siano/smsusb.c | 1 + 1 file changed, 1 insertion(+)
drivers/media/usb/siano/smsusb.c +1 -0
@@ -179,6 +179,7 @@ static void smsusb_stop_streaming(struct smsusb_device_t *dev)for (i =0 ; i <MAX_URBS ; i++) {usb_kill_urb (&dev->surbs[i].urb); +cancel_work_sync (&dev->surbs[i].wq);if (dev->surbs[i].cb) {smscore_putbuffer (dev->coredev, dev->surbs[i].cb);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 279/529 media: saa7134: Use video_unregister_device for radio_dev
In reply to Greg Kroah-HartmanFrom: Tasos Sahanidis <[email protected]>
[ Upstream commit bc7635c6435c77a0c168e2cc6535740adfaff4e4 ]
The radio device doesn't use vb2, thus calling vb2_video_unregister_device() which results in the following warning being printed on module unload.
WARNING: CPU: 1 PID: 215963 at drivers/media/common/videobuf2/videobuf2-v4l2.c:1236 vb2_video_unregister_device+0xc6/0xe0 [videobuf2_v4l2]
--- drivers/media/pci/saa7134/saa7134-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/pci/saa7134/saa7134-core.c +1 -1
@@ -977,7 +977,7 @@ static void saa7134_unregister_video(struct saa7134_dev *dev) }if (dev->radio_dev) {if (video_is_registered (dev->radio_dev)) -vb2_video_unregister_device (dev->radio_dev); +video_unregister_device (dev->radio_dev);else video_device_release (dev->radio_dev); dev->radio_dev =NULL ;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 280/529 rpmsg: glink: Avoid infinite loop on intent for missing channel
In reply to Greg Kroah-HartmanFrom: Bjorn Andersson <[email protected]>
[ Upstream commit 3e74ec2f39362bffbd42854acbb67c7f4cb808f9 ]
In the event that an intent advertisement arrives on an unknown channel the fifo is not advanced, resulting in the same message being handled over and over.
--- drivers/rpmsg/qcom_glink_native.c | 1 + 1 file changed, 1 insertion(+)
drivers/rpmsg/qcom_glink_native.c +1 -0
@@ -929,6 +929,7 @@ static void qcom_glink_handle_intent(struct qcom_glink *glink,spin_unlock_irqrestore (&glink->idr_lock, flags);if (!channel) {dev_err (glink->dev,"intents for non-existing channel\n" ); +qcom_glink_rx_advance (glink,ALIGN (msglen,8 ));return ; }
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 281/529 udf: Define EFSCORRUPTED error code
In reply to Greg Kroah-HartmanFrom: Jan Kara <[email protected]>
[ Upstream commit 3d2d7e61553dbcc8ba45201d8ae4f383742c8202 ]
Similarly to other filesystems define EFSCORRUPTED error code for reporting internal filesystem corruption.
--- fs/udf/udf_sb.h | 2 ++ 1 file changed, 2 insertions(+)
fs/udf/udf_sb.h +2 -0
@@ -51,6 +51,8 @@#define MF_DUPLICATE_MD 0x01#define MF_MIRROR_FE_LOADED 0x02 +#define EFSCORRUPTED EUCLEAN +struct udf_meta_data {__u32 s_meta_file_loc;__u32 s_mirror_file_loc;
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 282/529 ARM: dts: exynos: Use Exynos5420 compatible for the MIPI video phy
In reply to Greg Kroah-HartmanFrom: Markuss Broks <[email protected]>
[ Upstream commit 5d5aa219a790d61cad2c38e1aa32058f16ad2f0b ]
For some reason, the driver adding support for Exynos5420 MIPI phy back in 2016 wasn't used on Exynos5420, which caused a kernel panic. Add the proper compatible for it.
--- arch/arm/boot/dts/exynos5420.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/boot/dts/exynos5420.dtsi +1 -1
@@ -605,7 +605,7 @@ dp_phy: dp-video-phy { }; mipi_phy: mipi-video-phy { - compatible = "samsung,s5pv210-mipi-video-phy"; + compatible = "samsung,exynos5420-mipi-video-phy"; syscon = <&pmu_system_controller>; #phy-cells = <1>; };
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 283/529 blk-iocost: fix divide by 0 error in calc_lcoefs()
In reply to Greg Kroah-HartmanFrom: Li Nan <[email protected]>
[ Upstream commit 984af1e66b4126cf145153661cc24c213e2ec231 ]
echo max of u64 to cost.model can cause divide by 0 error.
# echo 8:0 rbps=18446744073709551615 > /sys/fs/cgroup/io.cost.model
divide error: 0000 [#1] PREEMPT SMP
RIP: 0010:calc_lcoefs+0x4c/0xc0 Call Trace: <TASK> ioc_refresh_params+0x2b3/0x4f0 ioc_cost_model_write+0x3cb/0x4c0 ? _copy_from_iter+0x6d/0x6c0 ? kernfs_fop_write_iter+0xfc/0x270 cgroup_file_write+0xa0/0x200 kernfs_fop_write_iter+0x17d/0x270 vfs_write+0x414/0x620 ksys_write+0x73/0x160 __x64_sys_write+0x1e/0x30 do_syscall_64+0x35/0x80 entry_SYSCALL_64_after_hwframe+0x63/0xcd
calc_lcoefs() uses the input value of cost.model in DIV_ROUND_UP_ULL, overflow would happen if bps plus IOC_PAGE_SIZE is greater than ULLONG_MAX, it can cause divide by 0 error.
Fix the problem by setting basecost
--- block/blk-iocost.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
block/blk-iocost.c +8 -3
@@ -872,9 +872,14 @@ static void calc_lcoefs(u64 bps, u64 seqiops, u64 randiops, *page = *seqio = *randio =0 ; -if (bps) - *page =DIV64_U64_ROUND_UP (VTIME_PER_SEC , -DIV_ROUND_UP_ULL (bps,IOC_PAGE_SIZE )); +if (bps) { +u64 bps_pages =DIV_ROUND_UP_ULL (bps,IOC_PAGE_SIZE ); + +if (bps_pages) + *page =DIV64_U64_ROUND_UP (VTIME_PER_SEC , bps_pages); +else + *page =1 ; + }if (seqiops) { v =DIV64_U64_ROUND_UP (VTIME_PER_SEC , seqiops);
Signature · 1 line
2.39.2
Greg Kroah-Hartman
maintainerPATCH 284/529 wifi: ath9k: Fix use-after-free in ath9k_hif_usb_disconnect()
In reply to Greg Kroah-HartmanFrom: Minsuk Kang <[email protected]>
[ Upstream commit f099c5c9e2ba08a379bd354a82e05ef839ae29ac ]
This patch fixes a use-after-free in ath9k that occurs in ath9k_hif_usb_disconnect() when ath9k_destroy_wmi() is trying to access 'drv_priv' that has already been freed by ieee80211_free_hw(), called by ath9k_htc_hw_deinit(). The patch moves ath9k_destroy_wmi() before ieee80211_free_hw(). Note that urbs from the driver should be killed before freeing 'wmi' with ath9k_destroy_wmi() as their callbacks will access 'wmi'.
Found by a modified version of syzkaller.
==================================================================
BUG: KASAN: use-after-free in ath9k_destroy_wmi+0x38/0x40
Read of size 8 at addr ffff8881069132a0 by task kworker/0:1/7
CPU: 0 PID: 7 Comm: kworker/0:1 Tainted: G O 5.14.0+ #131
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014
Workqueue: usb_hub_wq hub_event
Call Trace:
dump_stack_lvl+0x8e/0xd1
print_address_description.constprop.0.cold+0x93/0x334
? ath9k_destroy_wmi+0x38/0x40
? ath9k_destroy_wmi+0x38/0x40
kasan_report.cold+0x83/0xdf
? ath9k_destroy_wmi+0x38/0x40
ath9k_destroy_wmi+0x38/0x40
ath9k_hif_usb_disconnect+0x329/0x3f0
? ath9k_hif_usb_suspend+0x120/0x120
? usb_disable_interface+0xfc/0x180
usb_unbind_interface+0x19b/0x7e0
? usb_autoresume_device+0x50/0x50
device_release_driver_internal+0x44d/0x520
bus_remove_device+0x2e5/0x5a0
device_del+0x5b2/0xe30
? __device_link_del+0x370/0x370
? usb_remove_ep_devs+0x43/0x80
? remove_intf_ep_devs+0x112/0x1a0
usb_disable_device+0x1e3/0x5a0
usb_disconnect+0x267/0x870
hub_event+0x168d/0x3950
? rcu_read_lock_sched_held+0xa1/0xd0
? hub_port_debounce+0x2e0/0x2e0
? check_irq_usage+0x860/0xf20
? drain_workqueue+0x281/0x360
? lock_release+0x640/0x640
? rcu_read_lock_sched_held+0xa1/0xd0
? rcu_read_lock_bh_held+0xb0/0xb0
? lockdep_hardirqs_on_prepare+0x273/0x3e0
process_one_work+0x92b/0x1460
? pwq_dec_nr_in_flight+0x330/0x330
? rwlock_bug.part.0+0x90/0x90
worker_thread+0x95/0xe00
? __kthread_parkme+0x115/0x1e0
? process_one_work+0x1460/0x1460
kthread+0x3a1/0x480
? set_kthread_struct+0x120/0x120
ret_from_fork+0x1f/0x30
The buggy address belongs to the page:
page:ffffea00041a44c0 refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x106913
flags: 0x200000000000000(node=0|zone=2)
raw: 0200000000000000 0000000000000000 dead000000000122 0000000000000000
raw: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000
page dumped because: kasan: bad access detected
page_owner tracks the page as freed
page last allocated via order 3, migratetype Unmovable, gfp_mask 0x40dc0(GFP_KERNEL|__GFP_COMP|__GFP_ZERO), pid 7, ts 38347963444, free_ts 41399957635
prep_new_page+0x1aa/0x240
get_page_from_freelist+0x159a/0x27c0
__alloc_pages+0x2da/0x6a0
alloc_pages+0xec/0x1e0
kmalloc_order+0x39/0xf0
kmalloc_order_trace+0x19/0x120
__kmalloc+0x308/0x390
wiphy_new_nm+0x6f5/0x1dd0
ieee80211_alloc_hw_nm+0x36d/0x2230
ath9k_htc_probe_device+0x9d/0x1e10
ath9k_htc_hw_init+0x34/0x50
ath9k_hif_usb_firmware_cb+0x25f/0x4e0
request_firmware_work_func+0x131/0x240
process_one_work+0x92b/0x1460
worker_thread+0x95/0xe00
kthread+0x3a1/0x480
page last free stack trace:
free_pcp_prepare+0x3d3/0x7f0
free_unref_page+0x1e/0x3d0
device_release+0xa4/0x240
kobject_put+0x186/0x4c0
put_device+0x20/0x30
ath9k_htc_disconnect_device+0x1cf/0x2c0
ath9k_htc_hw_deinit+0x26/0x30
ath9k_hif_usb_disconnect+0x2d9/0x3f0
usb_unbind_interface+0x19b/0x7e0
device_release_driver_internal+0x44d/0x520
bus_remove_device+0x2e5/0x5a0
device_del+0x5b2/0xe30
usb_disable_device+0x1e3/0x5a0
usb_disconnect+0x267/0x870
hub_event+0x168d/0x3950
process_one_work+0x92b/0x1460
Memory state around the buggy address:
ffff888106913180: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ffff888106913200: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
>ffff888106913280: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
^
ffff888106913300: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ffff888106913380: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
==================================================================--- drivers/net/wireless/ath/ath9k/hif_usb.c | 2 -- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/net/wireless/ath/ath9k/hif_usb.c +0 -2
@@ -1424,8 +1424,6 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface)if (hif_dev->flags &HIF_USB_READY ) {ath9k_htc_hw_deinit (hif_dev->htc_handle, unplugged); -ath9k_hif_usb_dev_deinit (hif_dev); -ath9k_destroy_wmi (hif_dev->htc_handle->drv_priv);ath9k_htc_hw_free (hif_dev->htc_handle); }
drivers/net/wireless/ath/ath9k/htc_drv_init.c +2 -0
@@ -988,6 +988,8 @@ void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)ath9k_deinit_device (htc_handle->drv_priv);ath9k_stop_wmi (htc_handle->drv_priv); +ath9k_hif_usb_dealloc_urbs ((struct hif_device_usb *)htc_handle->hif_dev); +ath9k_destroy_wmi (htc_handle->drv_priv);ieee80211_free_hw (htc_handle->drv_priv->hw); } }
Signature · 1 line
2.39.2