Merge e28c0d7c92
("Merge branch 'akpm' (patches from Andrew)") into android-mainline
Steps on the way to 5.10-rc4 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: Id86ac2ef339902d7ea3689767ef52744c6fa0d9e
This commit is contained in:
5
.mailmap
5
.mailmap
@@ -82,7 +82,10 @@ Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@gmail.com>
|
|||||||
Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@imgtec.com>
|
Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@imgtec.com>
|
||||||
Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@mips.com>
|
Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@mips.com>
|
||||||
<dev.kurt@vandijck-laurijssen.be> <kurt.van.dijck@eia.be>
|
<dev.kurt@vandijck-laurijssen.be> <kurt.van.dijck@eia.be>
|
||||||
Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
|
Dmitry Baryshkov <dbaryshkov@gmail.com>
|
||||||
|
Dmitry Baryshkov <dbaryshkov@gmail.com> <[dbaryshkov@gmail.com]>
|
||||||
|
Dmitry Baryshkov <dbaryshkov@gmail.com> <dmitry_baryshkov@mentor.com>
|
||||||
|
Dmitry Baryshkov <dbaryshkov@gmail.com> <dmitry_eremin@mentor.com>
|
||||||
Dmitry Safonov <0x7f454c46@gmail.com> <dima@arista.com>
|
Dmitry Safonov <0x7f454c46@gmail.com> <dima@arista.com>
|
||||||
Dmitry Safonov <0x7f454c46@gmail.com> <d.safonov@partner.samsung.com>
|
Dmitry Safonov <0x7f454c46@gmail.com> <d.safonov@partner.samsung.com>
|
||||||
Dmitry Safonov <0x7f454c46@gmail.com> <dsafonov@virtuozzo.com>
|
Dmitry Safonov <0x7f454c46@gmail.com> <dsafonov@virtuozzo.com>
|
||||||
|
@@ -33,7 +33,13 @@ do { \
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#ifdef CONFIG_3_LEVEL_PGTABLES
|
#ifdef CONFIG_3_LEVEL_PGTABLES
|
||||||
#define __pmd_free_tlb(tlb,x, address) tlb_remove_page((tlb),virt_to_page(x))
|
|
||||||
|
#define __pmd_free_tlb(tlb, pmd, address) \
|
||||||
|
do { \
|
||||||
|
pgtable_pmd_page_dtor(virt_to_page(pmd)); \
|
||||||
|
tlb_remove_page((tlb),virt_to_page(pmd)); \
|
||||||
|
} while (0) \
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -443,9 +443,9 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
|
|||||||
hws[IMX8MM_CLK_A53_CORE] = imx_clk_hw_mux2("arm_a53_core", base + 0x9880, 24, 1, imx8mm_a53_core_sels, ARRAY_SIZE(imx8mm_a53_core_sels));
|
hws[IMX8MM_CLK_A53_CORE] = imx_clk_hw_mux2("arm_a53_core", base + 0x9880, 24, 1, imx8mm_a53_core_sels, ARRAY_SIZE(imx8mm_a53_core_sels));
|
||||||
|
|
||||||
/* BUS */
|
/* BUS */
|
||||||
hws[IMX8MM_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi", imx8mm_main_axi_sels, base + 0x8800);
|
hws[IMX8MM_CLK_MAIN_AXI] = imx8m_clk_hw_composite_bus_critical("main_axi", imx8mm_main_axi_sels, base + 0x8800);
|
||||||
hws[IMX8MM_CLK_ENET_AXI] = imx8m_clk_hw_composite_bus("enet_axi", imx8mm_enet_axi_sels, base + 0x8880);
|
hws[IMX8MM_CLK_ENET_AXI] = imx8m_clk_hw_composite_bus("enet_axi", imx8mm_enet_axi_sels, base + 0x8880);
|
||||||
hws[IMX8MM_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite_critical("nand_usdhc_bus", imx8mm_nand_usdhc_sels, base + 0x8900);
|
hws[IMX8MM_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite_bus_critical("nand_usdhc_bus", imx8mm_nand_usdhc_sels, base + 0x8900);
|
||||||
hws[IMX8MM_CLK_VPU_BUS] = imx8m_clk_hw_composite_bus("vpu_bus", imx8mm_vpu_bus_sels, base + 0x8980);
|
hws[IMX8MM_CLK_VPU_BUS] = imx8m_clk_hw_composite_bus("vpu_bus", imx8mm_vpu_bus_sels, base + 0x8980);
|
||||||
hws[IMX8MM_CLK_DISP_AXI] = imx8m_clk_hw_composite_bus("disp_axi", imx8mm_disp_axi_sels, base + 0x8a00);
|
hws[IMX8MM_CLK_DISP_AXI] = imx8m_clk_hw_composite_bus("disp_axi", imx8mm_disp_axi_sels, base + 0x8a00);
|
||||||
hws[IMX8MM_CLK_DISP_APB] = imx8m_clk_hw_composite_bus("disp_apb", imx8mm_disp_apb_sels, base + 0x8a80);
|
hws[IMX8MM_CLK_DISP_APB] = imx8m_clk_hw_composite_bus("disp_apb", imx8mm_disp_apb_sels, base + 0x8a80);
|
||||||
@@ -453,11 +453,11 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
|
|||||||
hws[IMX8MM_CLK_USB_BUS] = imx8m_clk_hw_composite_bus("usb_bus", imx8mm_usb_bus_sels, base + 0x8b80);
|
hws[IMX8MM_CLK_USB_BUS] = imx8m_clk_hw_composite_bus("usb_bus", imx8mm_usb_bus_sels, base + 0x8b80);
|
||||||
hws[IMX8MM_CLK_GPU_AXI] = imx8m_clk_hw_composite_bus("gpu_axi", imx8mm_gpu_axi_sels, base + 0x8c00);
|
hws[IMX8MM_CLK_GPU_AXI] = imx8m_clk_hw_composite_bus("gpu_axi", imx8mm_gpu_axi_sels, base + 0x8c00);
|
||||||
hws[IMX8MM_CLK_GPU_AHB] = imx8m_clk_hw_composite_bus("gpu_ahb", imx8mm_gpu_ahb_sels, base + 0x8c80);
|
hws[IMX8MM_CLK_GPU_AHB] = imx8m_clk_hw_composite_bus("gpu_ahb", imx8mm_gpu_ahb_sels, base + 0x8c80);
|
||||||
hws[IMX8MM_CLK_NOC] = imx8m_clk_hw_composite_critical("noc", imx8mm_noc_sels, base + 0x8d00);
|
hws[IMX8MM_CLK_NOC] = imx8m_clk_hw_composite_bus_critical("noc", imx8mm_noc_sels, base + 0x8d00);
|
||||||
hws[IMX8MM_CLK_NOC_APB] = imx8m_clk_hw_composite_critical("noc_apb", imx8mm_noc_apb_sels, base + 0x8d80);
|
hws[IMX8MM_CLK_NOC_APB] = imx8m_clk_hw_composite_bus_critical("noc_apb", imx8mm_noc_apb_sels, base + 0x8d80);
|
||||||
|
|
||||||
/* AHB */
|
/* AHB */
|
||||||
hws[IMX8MM_CLK_AHB] = imx8m_clk_hw_composite_critical("ahb", imx8mm_ahb_sels, base + 0x9000);
|
hws[IMX8MM_CLK_AHB] = imx8m_clk_hw_composite_bus_critical("ahb", imx8mm_ahb_sels, base + 0x9000);
|
||||||
hws[IMX8MM_CLK_AUDIO_AHB] = imx8m_clk_hw_composite_bus("audio_ahb", imx8mm_audio_ahb_sels, base + 0x9100);
|
hws[IMX8MM_CLK_AUDIO_AHB] = imx8m_clk_hw_composite_bus("audio_ahb", imx8mm_audio_ahb_sels, base + 0x9100);
|
||||||
|
|
||||||
/* IPG */
|
/* IPG */
|
||||||
|
@@ -431,7 +431,7 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
|
|||||||
hws[IMX8MN_CLK_A53_CORE] = imx_clk_hw_mux2("arm_a53_core", base + 0x9880, 24, 1, imx8mn_a53_core_sels, ARRAY_SIZE(imx8mn_a53_core_sels));
|
hws[IMX8MN_CLK_A53_CORE] = imx_clk_hw_mux2("arm_a53_core", base + 0x9880, 24, 1, imx8mn_a53_core_sels, ARRAY_SIZE(imx8mn_a53_core_sels));
|
||||||
|
|
||||||
/* BUS */
|
/* BUS */
|
||||||
hws[IMX8MN_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi", imx8mn_main_axi_sels, base + 0x8800);
|
hws[IMX8MN_CLK_MAIN_AXI] = imx8m_clk_hw_composite_bus_critical("main_axi", imx8mn_main_axi_sels, base + 0x8800);
|
||||||
hws[IMX8MN_CLK_ENET_AXI] = imx8m_clk_hw_composite_bus("enet_axi", imx8mn_enet_axi_sels, base + 0x8880);
|
hws[IMX8MN_CLK_ENET_AXI] = imx8m_clk_hw_composite_bus("enet_axi", imx8mn_enet_axi_sels, base + 0x8880);
|
||||||
hws[IMX8MN_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite_bus("nand_usdhc_bus", imx8mn_nand_usdhc_sels, base + 0x8900);
|
hws[IMX8MN_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite_bus("nand_usdhc_bus", imx8mn_nand_usdhc_sels, base + 0x8900);
|
||||||
hws[IMX8MN_CLK_DISP_AXI] = imx8m_clk_hw_composite_bus("disp_axi", imx8mn_disp_axi_sels, base + 0x8a00);
|
hws[IMX8MN_CLK_DISP_AXI] = imx8m_clk_hw_composite_bus("disp_axi", imx8mn_disp_axi_sels, base + 0x8a00);
|
||||||
@@ -439,9 +439,9 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
|
|||||||
hws[IMX8MN_CLK_USB_BUS] = imx8m_clk_hw_composite_bus("usb_bus", imx8mn_usb_bus_sels, base + 0x8b80);
|
hws[IMX8MN_CLK_USB_BUS] = imx8m_clk_hw_composite_bus("usb_bus", imx8mn_usb_bus_sels, base + 0x8b80);
|
||||||
hws[IMX8MN_CLK_GPU_AXI] = imx8m_clk_hw_composite_bus("gpu_axi", imx8mn_gpu_axi_sels, base + 0x8c00);
|
hws[IMX8MN_CLK_GPU_AXI] = imx8m_clk_hw_composite_bus("gpu_axi", imx8mn_gpu_axi_sels, base + 0x8c00);
|
||||||
hws[IMX8MN_CLK_GPU_AHB] = imx8m_clk_hw_composite_bus("gpu_ahb", imx8mn_gpu_ahb_sels, base + 0x8c80);
|
hws[IMX8MN_CLK_GPU_AHB] = imx8m_clk_hw_composite_bus("gpu_ahb", imx8mn_gpu_ahb_sels, base + 0x8c80);
|
||||||
hws[IMX8MN_CLK_NOC] = imx8m_clk_hw_composite_critical("noc", imx8mn_noc_sels, base + 0x8d00);
|
hws[IMX8MN_CLK_NOC] = imx8m_clk_hw_composite_bus_critical("noc", imx8mn_noc_sels, base + 0x8d00);
|
||||||
|
|
||||||
hws[IMX8MN_CLK_AHB] = imx8m_clk_hw_composite_critical("ahb", imx8mn_ahb_sels, base + 0x9000);
|
hws[IMX8MN_CLK_AHB] = imx8m_clk_hw_composite_bus_critical("ahb", imx8mn_ahb_sels, base + 0x9000);
|
||||||
hws[IMX8MN_CLK_AUDIO_AHB] = imx8m_clk_hw_composite_bus("audio_ahb", imx8mn_audio_ahb_sels, base + 0x9100);
|
hws[IMX8MN_CLK_AUDIO_AHB] = imx8m_clk_hw_composite_bus("audio_ahb", imx8mn_audio_ahb_sels, base + 0x9100);
|
||||||
hws[IMX8MN_CLK_IPG_ROOT] = imx_clk_hw_divider2("ipg_root", "ahb", base + 0x9080, 0, 1);
|
hws[IMX8MN_CLK_IPG_ROOT] = imx_clk_hw_divider2("ipg_root", "ahb", base + 0x9080, 0, 1);
|
||||||
hws[IMX8MN_CLK_IPG_AUDIO_ROOT] = imx_clk_hw_divider2("ipg_audio_root", "audio_ahb", base + 0x9180, 0, 1);
|
hws[IMX8MN_CLK_IPG_AUDIO_ROOT] = imx_clk_hw_divider2("ipg_audio_root", "audio_ahb", base + 0x9180, 0, 1);
|
||||||
|
@@ -557,9 +557,9 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
|
|||||||
/* CORE SEL */
|
/* CORE SEL */
|
||||||
hws[IMX8MP_CLK_A53_CORE] = imx_clk_hw_mux2("arm_a53_core", ccm_base + 0x9880, 24, 1, imx8mp_a53_core_sels, ARRAY_SIZE(imx8mp_a53_core_sels));
|
hws[IMX8MP_CLK_A53_CORE] = imx_clk_hw_mux2("arm_a53_core", ccm_base + 0x9880, 24, 1, imx8mp_a53_core_sels, ARRAY_SIZE(imx8mp_a53_core_sels));
|
||||||
|
|
||||||
hws[IMX8MP_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi", imx8mp_main_axi_sels, ccm_base + 0x8800);
|
hws[IMX8MP_CLK_MAIN_AXI] = imx8m_clk_hw_composite_bus_critical("main_axi", imx8mp_main_axi_sels, ccm_base + 0x8800);
|
||||||
hws[IMX8MP_CLK_ENET_AXI] = imx8m_clk_hw_composite_bus("enet_axi", imx8mp_enet_axi_sels, ccm_base + 0x8880);
|
hws[IMX8MP_CLK_ENET_AXI] = imx8m_clk_hw_composite_bus("enet_axi", imx8mp_enet_axi_sels, ccm_base + 0x8880);
|
||||||
hws[IMX8MP_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite_critical("nand_usdhc_bus", imx8mp_nand_usdhc_sels, ccm_base + 0x8900);
|
hws[IMX8MP_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite_bus_critical("nand_usdhc_bus", imx8mp_nand_usdhc_sels, ccm_base + 0x8900);
|
||||||
hws[IMX8MP_CLK_VPU_BUS] = imx8m_clk_hw_composite_bus("vpu_bus", imx8mp_vpu_bus_sels, ccm_base + 0x8980);
|
hws[IMX8MP_CLK_VPU_BUS] = imx8m_clk_hw_composite_bus("vpu_bus", imx8mp_vpu_bus_sels, ccm_base + 0x8980);
|
||||||
hws[IMX8MP_CLK_MEDIA_AXI] = imx8m_clk_hw_composite_bus("media_axi", imx8mp_media_axi_sels, ccm_base + 0x8a00);
|
hws[IMX8MP_CLK_MEDIA_AXI] = imx8m_clk_hw_composite_bus("media_axi", imx8mp_media_axi_sels, ccm_base + 0x8a00);
|
||||||
hws[IMX8MP_CLK_MEDIA_APB] = imx8m_clk_hw_composite_bus("media_apb", imx8mp_media_apb_sels, ccm_base + 0x8a80);
|
hws[IMX8MP_CLK_MEDIA_APB] = imx8m_clk_hw_composite_bus("media_apb", imx8mp_media_apb_sels, ccm_base + 0x8a80);
|
||||||
@@ -567,12 +567,12 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
|
|||||||
hws[IMX8MP_CLK_HDMI_AXI] = imx8m_clk_hw_composite_bus("hdmi_axi", imx8mp_media_axi_sels, ccm_base + 0x8b80);
|
hws[IMX8MP_CLK_HDMI_AXI] = imx8m_clk_hw_composite_bus("hdmi_axi", imx8mp_media_axi_sels, ccm_base + 0x8b80);
|
||||||
hws[IMX8MP_CLK_GPU_AXI] = imx8m_clk_hw_composite_bus("gpu_axi", imx8mp_gpu_axi_sels, ccm_base + 0x8c00);
|
hws[IMX8MP_CLK_GPU_AXI] = imx8m_clk_hw_composite_bus("gpu_axi", imx8mp_gpu_axi_sels, ccm_base + 0x8c00);
|
||||||
hws[IMX8MP_CLK_GPU_AHB] = imx8m_clk_hw_composite_bus("gpu_ahb", imx8mp_gpu_ahb_sels, ccm_base + 0x8c80);
|
hws[IMX8MP_CLK_GPU_AHB] = imx8m_clk_hw_composite_bus("gpu_ahb", imx8mp_gpu_ahb_sels, ccm_base + 0x8c80);
|
||||||
hws[IMX8MP_CLK_NOC] = imx8m_clk_hw_composite_critical("noc", imx8mp_noc_sels, ccm_base + 0x8d00);
|
hws[IMX8MP_CLK_NOC] = imx8m_clk_hw_composite_bus_critical("noc", imx8mp_noc_sels, ccm_base + 0x8d00);
|
||||||
hws[IMX8MP_CLK_NOC_IO] = imx8m_clk_hw_composite_critical("noc_io", imx8mp_noc_io_sels, ccm_base + 0x8d80);
|
hws[IMX8MP_CLK_NOC_IO] = imx8m_clk_hw_composite_bus_critical("noc_io", imx8mp_noc_io_sels, ccm_base + 0x8d80);
|
||||||
hws[IMX8MP_CLK_ML_AXI] = imx8m_clk_hw_composite_bus("ml_axi", imx8mp_ml_axi_sels, ccm_base + 0x8e00);
|
hws[IMX8MP_CLK_ML_AXI] = imx8m_clk_hw_composite_bus("ml_axi", imx8mp_ml_axi_sels, ccm_base + 0x8e00);
|
||||||
hws[IMX8MP_CLK_ML_AHB] = imx8m_clk_hw_composite_bus("ml_ahb", imx8mp_ml_ahb_sels, ccm_base + 0x8e80);
|
hws[IMX8MP_CLK_ML_AHB] = imx8m_clk_hw_composite_bus("ml_ahb", imx8mp_ml_ahb_sels, ccm_base + 0x8e80);
|
||||||
|
|
||||||
hws[IMX8MP_CLK_AHB] = imx8m_clk_hw_composite_critical("ahb_root", imx8mp_ahb_sels, ccm_base + 0x9000);
|
hws[IMX8MP_CLK_AHB] = imx8m_clk_hw_composite_bus_critical("ahb_root", imx8mp_ahb_sels, ccm_base + 0x9000);
|
||||||
hws[IMX8MP_CLK_AUDIO_AHB] = imx8m_clk_hw_composite_bus("audio_ahb", imx8mp_audio_ahb_sels, ccm_base + 0x9100);
|
hws[IMX8MP_CLK_AUDIO_AHB] = imx8m_clk_hw_composite_bus("audio_ahb", imx8mp_audio_ahb_sels, ccm_base + 0x9100);
|
||||||
hws[IMX8MP_CLK_MIPI_DSI_ESC_RX] = imx8m_clk_hw_composite_bus("mipi_dsi_esc_rx", imx8mp_mipi_dsi_esc_rx_sels, ccm_base + 0x9200);
|
hws[IMX8MP_CLK_MIPI_DSI_ESC_RX] = imx8m_clk_hw_composite_bus("mipi_dsi_esc_rx", imx8mp_mipi_dsi_esc_rx_sels, ccm_base + 0x9200);
|
||||||
|
|
||||||
|
@@ -431,7 +431,7 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
|
|||||||
hws[IMX8MQ_CLK_A53_CORE] = imx_clk_hw_mux2("arm_a53_core", base + 0x9880, 24, 1, imx8mq_a53_core_sels, ARRAY_SIZE(imx8mq_a53_core_sels));
|
hws[IMX8MQ_CLK_A53_CORE] = imx_clk_hw_mux2("arm_a53_core", base + 0x9880, 24, 1, imx8mq_a53_core_sels, ARRAY_SIZE(imx8mq_a53_core_sels));
|
||||||
|
|
||||||
/* BUS */
|
/* BUS */
|
||||||
hws[IMX8MQ_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi", imx8mq_main_axi_sels, base + 0x8800);
|
hws[IMX8MQ_CLK_MAIN_AXI] = imx8m_clk_hw_composite_bus_critical("main_axi", imx8mq_main_axi_sels, base + 0x8800);
|
||||||
hws[IMX8MQ_CLK_ENET_AXI] = imx8m_clk_hw_composite_bus("enet_axi", imx8mq_enet_axi_sels, base + 0x8880);
|
hws[IMX8MQ_CLK_ENET_AXI] = imx8m_clk_hw_composite_bus("enet_axi", imx8mq_enet_axi_sels, base + 0x8880);
|
||||||
hws[IMX8MQ_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite_bus("nand_usdhc_bus", imx8mq_nand_usdhc_sels, base + 0x8900);
|
hws[IMX8MQ_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite_bus("nand_usdhc_bus", imx8mq_nand_usdhc_sels, base + 0x8900);
|
||||||
hws[IMX8MQ_CLK_VPU_BUS] = imx8m_clk_hw_composite_bus("vpu_bus", imx8mq_vpu_bus_sels, base + 0x8980);
|
hws[IMX8MQ_CLK_VPU_BUS] = imx8m_clk_hw_composite_bus("vpu_bus", imx8mq_vpu_bus_sels, base + 0x8980);
|
||||||
@@ -441,12 +441,12 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
|
|||||||
hws[IMX8MQ_CLK_USB_BUS] = imx8m_clk_hw_composite_bus("usb_bus", imx8mq_usb_bus_sels, base + 0x8b80);
|
hws[IMX8MQ_CLK_USB_BUS] = imx8m_clk_hw_composite_bus("usb_bus", imx8mq_usb_bus_sels, base + 0x8b80);
|
||||||
hws[IMX8MQ_CLK_GPU_AXI] = imx8m_clk_hw_composite_bus("gpu_axi", imx8mq_gpu_axi_sels, base + 0x8c00);
|
hws[IMX8MQ_CLK_GPU_AXI] = imx8m_clk_hw_composite_bus("gpu_axi", imx8mq_gpu_axi_sels, base + 0x8c00);
|
||||||
hws[IMX8MQ_CLK_GPU_AHB] = imx8m_clk_hw_composite_bus("gpu_ahb", imx8mq_gpu_ahb_sels, base + 0x8c80);
|
hws[IMX8MQ_CLK_GPU_AHB] = imx8m_clk_hw_composite_bus("gpu_ahb", imx8mq_gpu_ahb_sels, base + 0x8c80);
|
||||||
hws[IMX8MQ_CLK_NOC] = imx8m_clk_hw_composite_critical("noc", imx8mq_noc_sels, base + 0x8d00);
|
hws[IMX8MQ_CLK_NOC] = imx8m_clk_hw_composite_bus_critical("noc", imx8mq_noc_sels, base + 0x8d00);
|
||||||
hws[IMX8MQ_CLK_NOC_APB] = imx8m_clk_hw_composite_critical("noc_apb", imx8mq_noc_apb_sels, base + 0x8d80);
|
hws[IMX8MQ_CLK_NOC_APB] = imx8m_clk_hw_composite_bus_critical("noc_apb", imx8mq_noc_apb_sels, base + 0x8d80);
|
||||||
|
|
||||||
/* AHB */
|
/* AHB */
|
||||||
/* AHB clock is used by the AHB bus therefore marked as critical */
|
/* AHB clock is used by the AHB bus therefore marked as critical */
|
||||||
hws[IMX8MQ_CLK_AHB] = imx8m_clk_hw_composite_critical("ahb", imx8mq_ahb_sels, base + 0x9000);
|
hws[IMX8MQ_CLK_AHB] = imx8m_clk_hw_composite_bus_critical("ahb", imx8mq_ahb_sels, base + 0x9000);
|
||||||
hws[IMX8MQ_CLK_AUDIO_AHB] = imx8m_clk_hw_composite_bus("audio_ahb", imx8mq_audio_ahb_sels, base + 0x9100);
|
hws[IMX8MQ_CLK_AUDIO_AHB] = imx8m_clk_hw_composite_bus("audio_ahb", imx8mq_audio_ahb_sels, base + 0x9100);
|
||||||
|
|
||||||
/* IPG */
|
/* IPG */
|
||||||
|
@@ -549,6 +549,11 @@ struct clk_hw *imx8m_clk_hw_composite_flags(const char *name,
|
|||||||
IMX_COMPOSITE_BUS, \
|
IMX_COMPOSITE_BUS, \
|
||||||
CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE)
|
CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE)
|
||||||
|
|
||||||
|
#define imx8m_clk_hw_composite_bus_critical(name, parent_names, reg) \
|
||||||
|
imx8m_clk_hw_composite_flags(name, parent_names, ARRAY_SIZE(parent_names), reg, \
|
||||||
|
IMX_COMPOSITE_BUS, \
|
||||||
|
CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE | CLK_IS_CRITICAL)
|
||||||
|
|
||||||
#define imx8m_clk_hw_composite_core(name, parent_names, reg) \
|
#define imx8m_clk_hw_composite_core(name, parent_names, reg) \
|
||||||
imx8m_clk_hw_composite_flags(name, parent_names, \
|
imx8m_clk_hw_composite_flags(name, parent_names, \
|
||||||
ARRAY_SIZE(parent_names), reg, \
|
ARRAY_SIZE(parent_names), reg, \
|
||||||
|
@@ -26,7 +26,10 @@ struct clk_regmap {
|
|||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define to_clk_regmap(_hw) container_of(_hw, struct clk_regmap, hw)
|
static inline struct clk_regmap *to_clk_regmap(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
return container_of(hw, struct clk_regmap, hw);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct clk_regmap_gate_data - regmap backed gate specific data
|
* struct clk_regmap_gate_data - regmap backed gate specific data
|
||||||
|
@@ -24,7 +24,11 @@ struct clk_regmap {
|
|||||||
unsigned int enable_mask;
|
unsigned int enable_mask;
|
||||||
bool enable_is_inverted;
|
bool enable_is_inverted;
|
||||||
};
|
};
|
||||||
#define to_clk_regmap(_hw) container_of(_hw, struct clk_regmap, hw)
|
|
||||||
|
static inline struct clk_regmap *to_clk_regmap(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
return container_of(hw, struct clk_regmap, hw);
|
||||||
|
}
|
||||||
|
|
||||||
int clk_is_enabled_regmap(struct clk_hw *hw);
|
int clk_is_enabled_regmap(struct clk_hw *hw);
|
||||||
int clk_enable_regmap(struct clk_hw *hw);
|
int clk_enable_regmap(struct clk_hw *hw);
|
||||||
|
@@ -171,7 +171,7 @@ static umode_t amd_energy_is_visible(const void *_data,
|
|||||||
enum hwmon_sensor_types type,
|
enum hwmon_sensor_types type,
|
||||||
u32 attr, int channel)
|
u32 attr, int channel)
|
||||||
{
|
{
|
||||||
return 0444;
|
return 0440;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int energy_accumulator(void *p)
|
static int energy_accumulator(void *p)
|
||||||
|
@@ -32,6 +32,7 @@
|
|||||||
#include <linux/hwmon.h>
|
#include <linux/hwmon.h>
|
||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
|
#include <linux/bits.h>
|
||||||
|
|
||||||
/* data port used by Apple SMC */
|
/* data port used by Apple SMC */
|
||||||
#define APPLESMC_DATA_PORT 0x300
|
#define APPLESMC_DATA_PORT 0x300
|
||||||
@@ -42,10 +43,13 @@
|
|||||||
|
|
||||||
#define APPLESMC_MAX_DATA_LENGTH 32
|
#define APPLESMC_MAX_DATA_LENGTH 32
|
||||||
|
|
||||||
/* wait up to 128 ms for a status change. */
|
/* Apple SMC status bits */
|
||||||
#define APPLESMC_MIN_WAIT 0x0010
|
#define SMC_STATUS_AWAITING_DATA BIT(0) /* SMC has data waiting to be read */
|
||||||
#define APPLESMC_RETRY_WAIT 0x0100
|
#define SMC_STATUS_IB_CLOSED BIT(1) /* Will ignore any input */
|
||||||
#define APPLESMC_MAX_WAIT 0x20000
|
#define SMC_STATUS_BUSY BIT(2) /* Command in progress */
|
||||||
|
|
||||||
|
/* Initial wait is 8us */
|
||||||
|
#define APPLESMC_MIN_WAIT 0x0008
|
||||||
|
|
||||||
#define APPLESMC_READ_CMD 0x10
|
#define APPLESMC_READ_CMD 0x10
|
||||||
#define APPLESMC_WRITE_CMD 0x11
|
#define APPLESMC_WRITE_CMD 0x11
|
||||||
@@ -151,65 +155,84 @@ static unsigned int key_at_index;
|
|||||||
static struct workqueue_struct *applesmc_led_wq;
|
static struct workqueue_struct *applesmc_led_wq;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* wait_read - Wait for a byte to appear on SMC port. Callers must
|
* Wait for specific status bits with a mask on the SMC.
|
||||||
* hold applesmc_lock.
|
* Used before all transactions.
|
||||||
|
* This does 10 fast loops of 8us then exponentially backs off for a
|
||||||
|
* minimum total wait of 262ms. Depending on usleep_range this could
|
||||||
|
* run out past 500ms.
|
||||||
*/
|
*/
|
||||||
static int wait_read(void)
|
|
||||||
|
static int wait_status(u8 val, u8 mask)
|
||||||
{
|
{
|
||||||
unsigned long end = jiffies + (APPLESMC_MAX_WAIT * HZ) / USEC_PER_SEC;
|
|
||||||
u8 status;
|
u8 status;
|
||||||
int us;
|
int us;
|
||||||
|
int i;
|
||||||
|
|
||||||
for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
|
us = APPLESMC_MIN_WAIT;
|
||||||
usleep_range(us, us * 16);
|
for (i = 0; i < 24 ; i++) {
|
||||||
status = inb(APPLESMC_CMD_PORT);
|
status = inb(APPLESMC_CMD_PORT);
|
||||||
/* read: wait for smc to settle */
|
if ((status & mask) == val)
|
||||||
if (status & 0x01)
|
|
||||||
return 0;
|
return 0;
|
||||||
/* timeout: give up */
|
usleep_range(us, us * 2);
|
||||||
if (time_after(jiffies, end))
|
if (i > 9)
|
||||||
break;
|
us <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_warn("wait_read() fail: 0x%02x\n", status);
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* send_byte - Write to SMC data port. Callers must hold applesmc_lock. */
|
||||||
* send_byte - Write to SMC port, retrying when necessary. Callers
|
|
||||||
* must hold applesmc_lock.
|
|
||||||
*/
|
|
||||||
static int send_byte(u8 cmd, u16 port)
|
static int send_byte(u8 cmd, u16 port)
|
||||||
{
|
{
|
||||||
u8 status;
|
int status;
|
||||||
int us;
|
|
||||||
unsigned long end = jiffies + (APPLESMC_MAX_WAIT * HZ) / USEC_PER_SEC;
|
status = wait_status(0, SMC_STATUS_IB_CLOSED);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
/*
|
||||||
|
* This needs to be a separate read looking for bit 0x04
|
||||||
|
* after bit 0x02 falls. If consolidated with the wait above
|
||||||
|
* this extra read may not happen if status returns both
|
||||||
|
* simultaneously and this would appear to be required.
|
||||||
|
*/
|
||||||
|
status = wait_status(SMC_STATUS_BUSY, SMC_STATUS_BUSY);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
outb(cmd, port);
|
outb(cmd, port);
|
||||||
for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
|
|
||||||
usleep_range(us, us * 16);
|
|
||||||
status = inb(APPLESMC_CMD_PORT);
|
|
||||||
/* write: wait for smc to settle */
|
|
||||||
if (status & 0x02)
|
|
||||||
continue;
|
|
||||||
/* ready: cmd accepted, return */
|
|
||||||
if (status & 0x04)
|
|
||||||
return 0;
|
return 0;
|
||||||
/* timeout: give up */
|
|
||||||
if (time_after(jiffies, end))
|
|
||||||
break;
|
|
||||||
/* busy: long wait and resend */
|
|
||||||
udelay(APPLESMC_RETRY_WAIT);
|
|
||||||
outb(cmd, port);
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_warn("send_byte(0x%02x, 0x%04x) fail: 0x%02x\n", cmd, port, status);
|
|
||||||
return -EIO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* send_command - Write a command to the SMC. Callers must hold applesmc_lock. */
|
||||||
|
|
||||||
static int send_command(u8 cmd)
|
static int send_command(u8 cmd)
|
||||||
{
|
{
|
||||||
return send_byte(cmd, APPLESMC_CMD_PORT);
|
int ret;
|
||||||
|
|
||||||
|
ret = wait_status(0, SMC_STATUS_IB_CLOSED);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
outb(cmd, APPLESMC_CMD_PORT);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Based on logic from the Apple driver. This is issued before any interaction
|
||||||
|
* If busy is stuck high, issue a read command to reset the SMC state machine.
|
||||||
|
* If busy is stuck high after the command then the SMC is jammed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int smc_sane(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = wait_status(0, SMC_STATUS_BUSY);
|
||||||
|
if (!ret)
|
||||||
|
return ret;
|
||||||
|
ret = send_command(APPLESMC_READ_CMD);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
return wait_status(0, SMC_STATUS_BUSY);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int send_argument(const char *key)
|
static int send_argument(const char *key)
|
||||||
@@ -226,6 +249,11 @@ static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
|
|||||||
{
|
{
|
||||||
u8 status, data = 0;
|
u8 status, data = 0;
|
||||||
int i;
|
int i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = smc_sane();
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
if (send_command(cmd) || send_argument(key)) {
|
if (send_command(cmd) || send_argument(key)) {
|
||||||
pr_warn("%.4s: read arg fail\n", key);
|
pr_warn("%.4s: read arg fail\n", key);
|
||||||
@@ -239,7 +267,8 @@ static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
if (wait_read()) {
|
if (wait_status(SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY,
|
||||||
|
SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY)) {
|
||||||
pr_warn("%.4s: read data[%d] fail\n", key, i);
|
pr_warn("%.4s: read data[%d] fail\n", key, i);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
@@ -250,19 +279,24 @@ static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
|
|||||||
for (i = 0; i < 16; i++) {
|
for (i = 0; i < 16; i++) {
|
||||||
udelay(APPLESMC_MIN_WAIT);
|
udelay(APPLESMC_MIN_WAIT);
|
||||||
status = inb(APPLESMC_CMD_PORT);
|
status = inb(APPLESMC_CMD_PORT);
|
||||||
if (!(status & 0x01))
|
if (!(status & SMC_STATUS_AWAITING_DATA))
|
||||||
break;
|
break;
|
||||||
data = inb(APPLESMC_DATA_PORT);
|
data = inb(APPLESMC_DATA_PORT);
|
||||||
}
|
}
|
||||||
if (i)
|
if (i)
|
||||||
pr_warn("flushed %d bytes, last value is: %d\n", i, data);
|
pr_warn("flushed %d bytes, last value is: %d\n", i, data);
|
||||||
|
|
||||||
return 0;
|
return wait_status(0, SMC_STATUS_BUSY);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len)
|
static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = smc_sane();
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
if (send_command(cmd) || send_argument(key)) {
|
if (send_command(cmd) || send_argument(key)) {
|
||||||
pr_warn("%s: write arg fail\n", key);
|
pr_warn("%s: write arg fail\n", key);
|
||||||
@@ -281,7 +315,7 @@ static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return wait_status(0, SMC_STATUS_BUSY);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_register_count(unsigned int *count)
|
static int read_register_count(unsigned int *count)
|
||||||
|
@@ -122,7 +122,7 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
|
|||||||
switch (idx) {
|
switch (idx) {
|
||||||
case MAX20730_DEBUGFS_VOUT_MIN:
|
case MAX20730_DEBUGFS_VOUT_MIN:
|
||||||
ret = VOLT_FROM_REG(data->mfr_voutmin * 10000);
|
ret = VOLT_FROM_REG(data->mfr_voutmin * 10000);
|
||||||
len = snprintf(tbuf, DEBUG_FS_DATA_MAX, "%d.%d\n",
|
len = scnprintf(tbuf, DEBUG_FS_DATA_MAX, "%d.%d\n",
|
||||||
ret / 10000, ret % 10000);
|
ret / 10000, ret % 10000);
|
||||||
break;
|
break;
|
||||||
case MAX20730_DEBUGFS_FREQUENCY:
|
case MAX20730_DEBUGFS_FREQUENCY:
|
||||||
@@ -141,7 +141,7 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
|
|||||||
ret = 800;
|
ret = 800;
|
||||||
else
|
else
|
||||||
ret = 900;
|
ret = 900;
|
||||||
len = snprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
|
len = scnprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
|
||||||
break;
|
break;
|
||||||
case MAX20730_DEBUGFS_PG_DELAY:
|
case MAX20730_DEBUGFS_PG_DELAY:
|
||||||
val = (data->mfr_devset1 & MAX20730_MFR_DEVSET1_TSTAT_MASK)
|
val = (data->mfr_devset1 & MAX20730_MFR_DEVSET1_TSTAT_MASK)
|
||||||
@@ -223,7 +223,7 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
|
|||||||
case MAX20730_DEBUGFS_OC_PROTECT_MODE:
|
case MAX20730_DEBUGFS_OC_PROTECT_MODE:
|
||||||
ret = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_OCPM_MASK)
|
ret = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_OCPM_MASK)
|
||||||
>> MAX20730_MFR_DEVSET2_OCPM_BIT_POS;
|
>> MAX20730_MFR_DEVSET2_OCPM_BIT_POS;
|
||||||
len = snprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
|
len = scnprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
|
||||||
break;
|
break;
|
||||||
case MAX20730_DEBUGFS_SS_TIMING:
|
case MAX20730_DEBUGFS_SS_TIMING:
|
||||||
val = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_SS_MASK)
|
val = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_SS_MASK)
|
||||||
@@ -241,32 +241,32 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
|
|||||||
case MAX20730_DEBUGFS_IMAX:
|
case MAX20730_DEBUGFS_IMAX:
|
||||||
ret = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_IMAX_MASK)
|
ret = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_IMAX_MASK)
|
||||||
>> MAX20730_MFR_DEVSET2_IMAX_BIT_POS;
|
>> MAX20730_MFR_DEVSET2_IMAX_BIT_POS;
|
||||||
len = snprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
|
len = scnprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
|
||||||
break;
|
break;
|
||||||
case MAX20730_DEBUGFS_OPERATION:
|
case MAX20730_DEBUGFS_OPERATION:
|
||||||
ret = i2c_smbus_read_byte_data(psu->client, PMBUS_OPERATION);
|
ret = i2c_smbus_read_byte_data(psu->client, PMBUS_OPERATION);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
len = snprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
|
len = scnprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
|
||||||
break;
|
break;
|
||||||
case MAX20730_DEBUGFS_ON_OFF_CONFIG:
|
case MAX20730_DEBUGFS_ON_OFF_CONFIG:
|
||||||
ret = i2c_smbus_read_byte_data(psu->client, PMBUS_ON_OFF_CONFIG);
|
ret = i2c_smbus_read_byte_data(psu->client, PMBUS_ON_OFF_CONFIG);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
len = snprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
|
len = scnprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
|
||||||
break;
|
break;
|
||||||
case MAX20730_DEBUGFS_SMBALERT_MASK:
|
case MAX20730_DEBUGFS_SMBALERT_MASK:
|
||||||
ret = i2c_smbus_read_word_data(psu->client,
|
ret = i2c_smbus_read_word_data(psu->client,
|
||||||
PMBUS_SMB_ALERT_MASK);
|
PMBUS_SMB_ALERT_MASK);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
len = snprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
|
len = scnprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
|
||||||
break;
|
break;
|
||||||
case MAX20730_DEBUGFS_VOUT_MODE:
|
case MAX20730_DEBUGFS_VOUT_MODE:
|
||||||
ret = i2c_smbus_read_byte_data(psu->client, PMBUS_VOUT_MODE);
|
ret = i2c_smbus_read_byte_data(psu->client, PMBUS_VOUT_MODE);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
len = snprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
|
len = scnprintf(tbuf, DEBUG_FS_DATA_MAX, "%d\n", ret);
|
||||||
break;
|
break;
|
||||||
case MAX20730_DEBUGFS_VOUT_COMMAND:
|
case MAX20730_DEBUGFS_VOUT_COMMAND:
|
||||||
ret = i2c_smbus_read_word_data(psu->client, PMBUS_VOUT_COMMAND);
|
ret = i2c_smbus_read_word_data(psu->client, PMBUS_VOUT_COMMAND);
|
||||||
@@ -274,7 +274,7 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = VOLT_FROM_REG(ret * 10000);
|
ret = VOLT_FROM_REG(ret * 10000);
|
||||||
len = snprintf(tbuf, DEBUG_FS_DATA_MAX,
|
len = scnprintf(tbuf, DEBUG_FS_DATA_MAX,
|
||||||
"%d.%d\n", ret / 10000, ret % 10000);
|
"%d.%d\n", ret / 10000, ret % 10000);
|
||||||
break;
|
break;
|
||||||
case MAX20730_DEBUGFS_VOUT_MAX:
|
case MAX20730_DEBUGFS_VOUT_MAX:
|
||||||
@@ -283,7 +283,7 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = VOLT_FROM_REG(ret * 10000);
|
ret = VOLT_FROM_REG(ret * 10000);
|
||||||
len = snprintf(tbuf, DEBUG_FS_DATA_MAX,
|
len = scnprintf(tbuf, DEBUG_FS_DATA_MAX,
|
||||||
"%d.%d\n", ret / 10000, ret % 10000);
|
"%d.%d\n", ret / 10000, ret % 10000);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@@ -941,12 +941,16 @@ static ssize_t pmbus_show_sensor(struct device *dev,
|
|||||||
struct i2c_client *client = to_i2c_client(dev->parent);
|
struct i2c_client *client = to_i2c_client(dev->parent);
|
||||||
struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
|
struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
|
||||||
struct pmbus_data *data = i2c_get_clientdata(client);
|
struct pmbus_data *data = i2c_get_clientdata(client);
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
mutex_lock(&data->update_lock);
|
||||||
pmbus_update_sensor_data(client, sensor);
|
pmbus_update_sensor_data(client, sensor);
|
||||||
if (sensor->data < 0)
|
if (sensor->data < 0)
|
||||||
return sensor->data;
|
ret = sensor->data;
|
||||||
|
else
|
||||||
return snprintf(buf, PAGE_SIZE, "%lld\n", pmbus_reg2data(data, sensor));
|
ret = snprintf(buf, PAGE_SIZE, "%lld\n", pmbus_reg2data(data, sensor));
|
||||||
|
mutex_unlock(&data->update_lock);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t pmbus_set_sensor(struct device *dev,
|
static ssize_t pmbus_set_sensor(struct device *dev,
|
||||||
@@ -2012,8 +2016,11 @@ static ssize_t pmbus_show_samples(struct device *dev,
|
|||||||
int val;
|
int val;
|
||||||
struct i2c_client *client = to_i2c_client(dev->parent);
|
struct i2c_client *client = to_i2c_client(dev->parent);
|
||||||
struct pmbus_samples_reg *reg = to_samples_reg(devattr);
|
struct pmbus_samples_reg *reg = to_samples_reg(devattr);
|
||||||
|
struct pmbus_data *data = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
mutex_lock(&data->update_lock);
|
||||||
val = _pmbus_read_word_data(client, reg->page, 0xff, reg->attr->reg);
|
val = _pmbus_read_word_data(client, reg->page, 0xff, reg->attr->reg);
|
||||||
|
mutex_unlock(&data->update_lock);
|
||||||
if (val < 0)
|
if (val < 0)
|
||||||
return val;
|
return val;
|
||||||
|
|
||||||
|
@@ -54,16 +54,18 @@ static irqreturn_t pulse_handler(int irq, void *dev_id)
|
|||||||
static void sample_timer(struct timer_list *t)
|
static void sample_timer(struct timer_list *t)
|
||||||
{
|
{
|
||||||
struct pwm_fan_ctx *ctx = from_timer(ctx, t, rpm_timer);
|
struct pwm_fan_ctx *ctx = from_timer(ctx, t, rpm_timer);
|
||||||
|
unsigned int delta = ktime_ms_delta(ktime_get(), ctx->sample_start);
|
||||||
int pulses;
|
int pulses;
|
||||||
u64 tmp;
|
|
||||||
|
|
||||||
|
if (delta) {
|
||||||
pulses = atomic_read(&ctx->pulses);
|
pulses = atomic_read(&ctx->pulses);
|
||||||
atomic_sub(pulses, &ctx->pulses);
|
atomic_sub(pulses, &ctx->pulses);
|
||||||
tmp = (u64)pulses * ktime_ms_delta(ktime_get(), ctx->sample_start) * 60;
|
ctx->rpm = (unsigned int)(pulses * 1000 * 60) /
|
||||||
do_div(tmp, ctx->pulses_per_revolution * 1000);
|
(ctx->pulses_per_revolution * delta);
|
||||||
ctx->rpm = tmp;
|
|
||||||
|
|
||||||
ctx->sample_start = ktime_get();
|
ctx->sample_start = ktime_get();
|
||||||
|
}
|
||||||
|
|
||||||
mod_timer(&ctx->rpm_timer, jiffies + HZ);
|
mod_timer(&ctx->rpm_timer, jiffies + HZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1633,12 +1633,12 @@ start:
|
|||||||
*/
|
*/
|
||||||
fallthrough;
|
fallthrough;
|
||||||
case CLKS_OFF:
|
case CLKS_OFF:
|
||||||
ufshcd_scsi_block_requests(hba);
|
|
||||||
hba->clk_gating.state = REQ_CLKS_ON;
|
hba->clk_gating.state = REQ_CLKS_ON;
|
||||||
trace_ufshcd_clk_gating(dev_name(hba->dev),
|
trace_ufshcd_clk_gating(dev_name(hba->dev),
|
||||||
hba->clk_gating.state);
|
hba->clk_gating.state);
|
||||||
queue_work(hba->clk_gating.clk_gating_workq,
|
if (queue_work(hba->clk_gating.clk_gating_workq,
|
||||||
&hba->clk_gating.ungate_work);
|
&hba->clk_gating.ungate_work))
|
||||||
|
ufshcd_scsi_block_requests(hba);
|
||||||
/*
|
/*
|
||||||
* fall through to check if we should wait for this
|
* fall through to check if we should wait for this
|
||||||
* work to be done or not.
|
* work to be done or not.
|
||||||
@@ -2123,10 +2123,20 @@ ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
|
|||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (wait_for_completion_timeout(&uic_cmd->done,
|
if (wait_for_completion_timeout(&uic_cmd->done,
|
||||||
msecs_to_jiffies(UIC_CMD_TIMEOUT)))
|
msecs_to_jiffies(UIC_CMD_TIMEOUT))) {
|
||||||
ret = uic_cmd->argument2 & MASK_UIC_COMMAND_RESULT;
|
ret = uic_cmd->argument2 & MASK_UIC_COMMAND_RESULT;
|
||||||
else
|
} else {
|
||||||
ret = -ETIMEDOUT;
|
ret = -ETIMEDOUT;
|
||||||
|
dev_err(hba->dev,
|
||||||
|
"uic cmd 0x%x with arg3 0x%x completion timeout\n",
|
||||||
|
uic_cmd->command, uic_cmd->argument3);
|
||||||
|
|
||||||
|
if (!uic_cmd->cmd_active) {
|
||||||
|
dev_err(hba->dev, "%s: UIC cmd has been completed, return the result\n",
|
||||||
|
__func__);
|
||||||
|
ret = uic_cmd->argument2 & MASK_UIC_COMMAND_RESULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(hba->host->host_lock, flags);
|
spin_lock_irqsave(hba->host->host_lock, flags);
|
||||||
hba->active_uic_cmd = NULL;
|
hba->active_uic_cmd = NULL;
|
||||||
@@ -2158,6 +2168,7 @@ __ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd,
|
|||||||
if (completion)
|
if (completion)
|
||||||
init_completion(&uic_cmd->done);
|
init_completion(&uic_cmd->done);
|
||||||
|
|
||||||
|
uic_cmd->cmd_active = 1;
|
||||||
ufshcd_dispatch_uic_cmd(hba, uic_cmd);
|
ufshcd_dispatch_uic_cmd(hba, uic_cmd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -3829,10 +3840,18 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd)
|
|||||||
dev_err(hba->dev,
|
dev_err(hba->dev,
|
||||||
"pwr ctrl cmd 0x%x with mode 0x%x completion timeout\n",
|
"pwr ctrl cmd 0x%x with mode 0x%x completion timeout\n",
|
||||||
cmd->command, cmd->argument3);
|
cmd->command, cmd->argument3);
|
||||||
|
|
||||||
|
if (!cmd->cmd_active) {
|
||||||
|
dev_err(hba->dev, "%s: Power Mode Change operation has been completed, go check UPMCRS\n",
|
||||||
|
__func__);
|
||||||
|
goto check_upmcrs;
|
||||||
|
}
|
||||||
|
|
||||||
ret = -ETIMEDOUT;
|
ret = -ETIMEDOUT;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_upmcrs:
|
||||||
status = ufshcd_get_upmcrs(hba);
|
status = ufshcd_get_upmcrs(hba);
|
||||||
if (status != PWR_LOCAL) {
|
if (status != PWR_LOCAL) {
|
||||||
dev_err(hba->dev,
|
dev_err(hba->dev,
|
||||||
@@ -4925,11 +4944,14 @@ static irqreturn_t ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status)
|
|||||||
ufshcd_get_uic_cmd_result(hba);
|
ufshcd_get_uic_cmd_result(hba);
|
||||||
hba->active_uic_cmd->argument3 =
|
hba->active_uic_cmd->argument3 =
|
||||||
ufshcd_get_dme_attr_val(hba);
|
ufshcd_get_dme_attr_val(hba);
|
||||||
|
if (!hba->uic_async_done)
|
||||||
|
hba->active_uic_cmd->cmd_active = 0;
|
||||||
complete(&hba->active_uic_cmd->done);
|
complete(&hba->active_uic_cmd->done);
|
||||||
retval = IRQ_HANDLED;
|
retval = IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((intr_status & UFSHCD_UIC_PWR_MASK) && hba->uic_async_done) {
|
if ((intr_status & UFSHCD_UIC_PWR_MASK) && hba->uic_async_done) {
|
||||||
|
hba->active_uic_cmd->cmd_active = 0;
|
||||||
complete(hba->uic_async_done);
|
complete(hba->uic_async_done);
|
||||||
retval = IRQ_HANDLED;
|
retval = IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
@@ -8991,6 +9013,7 @@ void ufshcd_remove(struct ufs_hba *hba)
|
|||||||
blk_mq_free_tag_set(&hba->tmf_tag_set);
|
blk_mq_free_tag_set(&hba->tmf_tag_set);
|
||||||
blk_cleanup_queue(hba->cmd_queue);
|
blk_cleanup_queue(hba->cmd_queue);
|
||||||
scsi_remove_host(hba->host);
|
scsi_remove_host(hba->host);
|
||||||
|
destroy_workqueue(hba->eh_wq);
|
||||||
/* disable interrupts */
|
/* disable interrupts */
|
||||||
ufshcd_disable_intr(hba, hba->intr_mask);
|
ufshcd_disable_intr(hba, hba->intr_mask);
|
||||||
ufshcd_hba_stop(hba);
|
ufshcd_hba_stop(hba);
|
||||||
@@ -9292,6 +9315,7 @@ out_remove_scsi_host:
|
|||||||
exit_gating:
|
exit_gating:
|
||||||
ufshcd_exit_clk_scaling(hba);
|
ufshcd_exit_clk_scaling(hba);
|
||||||
ufshcd_exit_clk_gating(hba);
|
ufshcd_exit_clk_gating(hba);
|
||||||
|
destroy_workqueue(hba->eh_wq);
|
||||||
out_disable:
|
out_disable:
|
||||||
hba->is_irq_enabled = false;
|
hba->is_irq_enabled = false;
|
||||||
ufshcd_hba_exit(hba);
|
ufshcd_hba_exit(hba);
|
||||||
|
@@ -64,6 +64,7 @@ enum dev_cmd_type {
|
|||||||
* @argument1: UIC command argument 1
|
* @argument1: UIC command argument 1
|
||||||
* @argument2: UIC command argument 2
|
* @argument2: UIC command argument 2
|
||||||
* @argument3: UIC command argument 3
|
* @argument3: UIC command argument 3
|
||||||
|
* @cmd_active: Indicate if UIC command is outstanding
|
||||||
* @done: UIC command completion
|
* @done: UIC command completion
|
||||||
*/
|
*/
|
||||||
struct uic_command {
|
struct uic_command {
|
||||||
@@ -71,6 +72,7 @@ struct uic_command {
|
|||||||
u32 argument1;
|
u32 argument1;
|
||||||
u32 argument2;
|
u32 argument2;
|
||||||
u32 argument3;
|
u32 argument3;
|
||||||
|
int cmd_active;
|
||||||
struct completion done;
|
struct completion done;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -169,11 +169,14 @@ int afs_write_end(struct file *file, struct address_space *mapping,
|
|||||||
unsigned int f, from = pos & (PAGE_SIZE - 1);
|
unsigned int f, from = pos & (PAGE_SIZE - 1);
|
||||||
unsigned int t, to = from + copied;
|
unsigned int t, to = from + copied;
|
||||||
loff_t i_size, maybe_i_size;
|
loff_t i_size, maybe_i_size;
|
||||||
int ret;
|
int ret = 0;
|
||||||
|
|
||||||
_enter("{%llx:%llu},{%lx}",
|
_enter("{%llx:%llu},{%lx}",
|
||||||
vnode->fid.vid, vnode->fid.vnode, page->index);
|
vnode->fid.vid, vnode->fid.vnode, page->index);
|
||||||
|
|
||||||
|
if (copied == 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
maybe_i_size = pos + copied;
|
maybe_i_size = pos + copied;
|
||||||
|
|
||||||
i_size = i_size_read(&vnode->vfs_inode);
|
i_size = i_size_read(&vnode->vfs_inode);
|
||||||
|
@@ -1713,6 +1713,7 @@ static void ocfs2_inode_init_once(void *data)
|
|||||||
|
|
||||||
oi->ip_blkno = 0ULL;
|
oi->ip_blkno = 0ULL;
|
||||||
oi->ip_clusters = 0;
|
oi->ip_clusters = 0;
|
||||||
|
oi->ip_next_orphan = NULL;
|
||||||
|
|
||||||
ocfs2_resv_init_once(&oi->ip_la_data_resv);
|
ocfs2_resv_init_once(&oi->ip_la_data_resv);
|
||||||
|
|
||||||
|
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
#include <linux/compiler.h>
|
||||||
#include <asm/rwonce.h>
|
#include <asm/rwonce.h>
|
||||||
|
|
||||||
#ifndef nop
|
#ifndef nop
|
||||||
|
@@ -60,12 +60,6 @@
|
|||||||
#define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
|
#define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The following are for compatibility with GCC, from compiler-gcc.h,
|
|
||||||
* and may be redefined here because they should not be shared with other
|
|
||||||
* compilers, like ICC.
|
|
||||||
*/
|
|
||||||
#define barrier() __asm__ __volatile__("" : : : "memory")
|
|
||||||
|
|
||||||
#if __has_feature(shadow_call_stack)
|
#if __has_feature(shadow_call_stack)
|
||||||
# define __noscs __attribute__((__no_sanitize__("shadow-call-stack")))
|
# define __noscs __attribute__((__no_sanitize__("shadow-call-stack")))
|
||||||
#endif
|
#endif
|
||||||
|
@@ -15,25 +15,6 @@
|
|||||||
# error Sorry, your version of GCC is too old - please use 4.9 or newer.
|
# error Sorry, your version of GCC is too old - please use 4.9 or newer.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Optimization barrier */
|
|
||||||
|
|
||||||
/* The "volatile" is due to gcc bugs */
|
|
||||||
#define barrier() __asm__ __volatile__("": : :"memory")
|
|
||||||
/*
|
|
||||||
* This version is i.e. to prevent dead stores elimination on @ptr
|
|
||||||
* where gcc and llvm may behave differently when otherwise using
|
|
||||||
* normal barrier(): while gcc behavior gets along with a normal
|
|
||||||
* barrier(), llvm needs an explicit input variable to be assumed
|
|
||||||
* clobbered. The issue is as follows: while the inline asm might
|
|
||||||
* access any memory it wants, the compiler could have fit all of
|
|
||||||
* @ptr into memory registers instead, and since @ptr never escaped
|
|
||||||
* from that, it proved that the inline asm wasn't touching any of
|
|
||||||
* it. This version works well with both compilers, i.e. we're telling
|
|
||||||
* the compiler that the inline asm absolutely may see the contents
|
|
||||||
* of @ptr. See also: https://llvm.org/bugs/show_bug.cgi?id=15495
|
|
||||||
*/
|
|
||||||
#define barrier_data(ptr) __asm__ __volatile__("": :"r"(ptr) :"memory")
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This macro obfuscates arithmetic on a variable address so that gcc
|
* This macro obfuscates arithmetic on a variable address so that gcc
|
||||||
* shouldn't recognize the original var, and make assumptions about it.
|
* shouldn't recognize the original var, and make assumptions about it.
|
||||||
|
@@ -80,11 +80,25 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
|
|||||||
|
|
||||||
/* Optimization barrier */
|
/* Optimization barrier */
|
||||||
#ifndef barrier
|
#ifndef barrier
|
||||||
# define barrier() __memory_barrier()
|
/* The "volatile" is due to gcc bugs */
|
||||||
|
# define barrier() __asm__ __volatile__("": : :"memory")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef barrier_data
|
#ifndef barrier_data
|
||||||
# define barrier_data(ptr) barrier()
|
/*
|
||||||
|
* This version is i.e. to prevent dead stores elimination on @ptr
|
||||||
|
* where gcc and llvm may behave differently when otherwise using
|
||||||
|
* normal barrier(): while gcc behavior gets along with a normal
|
||||||
|
* barrier(), llvm needs an explicit input variable to be assumed
|
||||||
|
* clobbered. The issue is as follows: while the inline asm might
|
||||||
|
* access any memory it wants, the compiler could have fit all of
|
||||||
|
* @ptr into memory registers instead, and since @ptr never escaped
|
||||||
|
* from that, it proved that the inline asm wasn't touching any of
|
||||||
|
* it. This version works well with both compilers, i.e. we're telling
|
||||||
|
* the compiler that the inline asm absolutely may see the contents
|
||||||
|
* of @ptr. See also: https://llvm.org/bugs/show_bug.cgi?id=15495
|
||||||
|
*/
|
||||||
|
# define barrier_data(ptr) __asm__ __volatile__("": :"r"(ptr) :"memory")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* workaround for GCC PR82365 if needed */
|
/* workaround for GCC PR82365 if needed */
|
||||||
|
@@ -900,11 +900,18 @@ static inline void count_memcg_event_mm(struct mm_struct *mm,
|
|||||||
static inline void memcg_memory_event(struct mem_cgroup *memcg,
|
static inline void memcg_memory_event(struct mem_cgroup *memcg,
|
||||||
enum memcg_memory_event event)
|
enum memcg_memory_event event)
|
||||||
{
|
{
|
||||||
|
bool swap_event = event == MEMCG_SWAP_HIGH || event == MEMCG_SWAP_MAX ||
|
||||||
|
event == MEMCG_SWAP_FAIL;
|
||||||
|
|
||||||
atomic_long_inc(&memcg->memory_events_local[event]);
|
atomic_long_inc(&memcg->memory_events_local[event]);
|
||||||
|
if (!swap_event)
|
||||||
cgroup_file_notify(&memcg->events_local_file);
|
cgroup_file_notify(&memcg->events_local_file);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
atomic_long_inc(&memcg->memory_events[event]);
|
atomic_long_inc(&memcg->memory_events[event]);
|
||||||
|
if (swap_event)
|
||||||
|
cgroup_file_notify(&memcg->swap_events_file);
|
||||||
|
else
|
||||||
cgroup_file_notify(&memcg->events_file);
|
cgroup_file_notify(&memcg->events_file);
|
||||||
|
|
||||||
if (!cgroup_subsys_on_dfl(memory_cgrp_subsys))
|
if (!cgroup_subsys_on_dfl(memory_cgrp_subsys))
|
||||||
|
@@ -605,6 +605,7 @@ void __warn(const char *file, int line, void *caller, unsigned taint,
|
|||||||
panic("panic_on_warn set ...\n");
|
panic("panic_on_warn set ...\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!regs)
|
||||||
dump_stack();
|
dump_stack();
|
||||||
|
|
||||||
print_irqtrace_events(current);
|
print_irqtrace_events(current);
|
||||||
|
@@ -553,22 +553,22 @@ static int __init reboot_setup(char *str)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
{
|
if (isdigit(*(str+1)))
|
||||||
int rc;
|
reboot_cpu = simple_strtoul(str+1, NULL, 0);
|
||||||
|
else if (str[1] == 'm' && str[2] == 'p' &&
|
||||||
if (isdigit(*(str+1))) {
|
isdigit(*(str+3)))
|
||||||
rc = kstrtoint(str+1, 0, &reboot_cpu);
|
reboot_cpu = simple_strtoul(str+3, NULL, 0);
|
||||||
if (rc)
|
else
|
||||||
return rc;
|
|
||||||
} else if (str[1] == 'm' && str[2] == 'p' &&
|
|
||||||
isdigit(*(str+3))) {
|
|
||||||
rc = kstrtoint(str+3, 0, &reboot_cpu);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
} else
|
|
||||||
*mode = REBOOT_SOFT;
|
*mode = REBOOT_SOFT;
|
||||||
|
if (reboot_cpu >= num_possible_cpus()) {
|
||||||
|
pr_err("Ignoring the CPU number in reboot= option. "
|
||||||
|
"CPU %d exceeds possible cpu number %d\n",
|
||||||
|
reboot_cpu, num_possible_cpus());
|
||||||
|
reboot_cpu = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 'g':
|
case 'g':
|
||||||
*mode = REBOOT_GPIO;
|
*mode = REBOOT_GPIO;
|
||||||
break;
|
break;
|
||||||
|
@@ -44,8 +44,6 @@ int __read_mostly soft_watchdog_user_enabled = 1;
|
|||||||
int __read_mostly watchdog_thresh = 10;
|
int __read_mostly watchdog_thresh = 10;
|
||||||
static int __read_mostly nmi_watchdog_available;
|
static int __read_mostly nmi_watchdog_available;
|
||||||
|
|
||||||
static struct cpumask watchdog_allowed_mask __read_mostly;
|
|
||||||
|
|
||||||
struct cpumask watchdog_cpumask __read_mostly;
|
struct cpumask watchdog_cpumask __read_mostly;
|
||||||
unsigned long *watchdog_cpumask_bits = cpumask_bits(&watchdog_cpumask);
|
unsigned long *watchdog_cpumask_bits = cpumask_bits(&watchdog_cpumask);
|
||||||
|
|
||||||
@@ -162,6 +160,8 @@ static void lockup_detector_update_enable(void)
|
|||||||
int __read_mostly sysctl_softlockup_all_cpu_backtrace;
|
int __read_mostly sysctl_softlockup_all_cpu_backtrace;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static struct cpumask watchdog_allowed_mask __read_mostly;
|
||||||
|
|
||||||
/* Global variables, exported for sysctl */
|
/* Global variables, exported for sysctl */
|
||||||
unsigned int __read_mostly softlockup_panic =
|
unsigned int __read_mostly softlockup_panic =
|
||||||
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE;
|
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE;
|
||||||
|
@@ -817,6 +817,10 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
|
|||||||
* delay for some time until fewer pages are isolated
|
* delay for some time until fewer pages are isolated
|
||||||
*/
|
*/
|
||||||
while (unlikely(too_many_isolated(pgdat))) {
|
while (unlikely(too_many_isolated(pgdat))) {
|
||||||
|
/* stop isolation if there are still pages not migrated */
|
||||||
|
if (cc->nr_migratepages)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* async migration should just abort */
|
/* async migration should just abort */
|
||||||
if (cc->mode == MIGRATE_ASYNC)
|
if (cc->mode == MIGRATE_ASYNC)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1012,8 +1016,8 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
|
|||||||
|
|
||||||
isolate_success:
|
isolate_success:
|
||||||
list_add(&page->lru, &cc->migratepages);
|
list_add(&page->lru, &cc->migratepages);
|
||||||
cc->nr_migratepages++;
|
cc->nr_migratepages += compound_nr(page);
|
||||||
nr_isolated++;
|
nr_isolated += compound_nr(page);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Avoid isolating too much unless this block is being
|
* Avoid isolating too much unless this block is being
|
||||||
@@ -1021,7 +1025,7 @@ isolate_success:
|
|||||||
* or a lock is contended. For contention, isolate quickly to
|
* or a lock is contended. For contention, isolate quickly to
|
||||||
* potentially remove one source of contention.
|
* potentially remove one source of contention.
|
||||||
*/
|
*/
|
||||||
if (cc->nr_migratepages == COMPACT_CLUSTER_MAX &&
|
if (cc->nr_migratepages >= COMPACT_CLUSTER_MAX &&
|
||||||
!cc->rescan && !cc->contended) {
|
!cc->rescan && !cc->contended) {
|
||||||
++low_pfn;
|
++low_pfn;
|
||||||
break;
|
break;
|
||||||
@@ -1132,7 +1136,7 @@ isolate_migratepages_range(struct compact_control *cc, unsigned long start_pfn,
|
|||||||
if (!pfn)
|
if (!pfn)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (cc->nr_migratepages == COMPACT_CLUSTER_MAX)
|
if (cc->nr_migratepages >= COMPACT_CLUSTER_MAX)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
6
mm/gup.c
6
mm/gup.c
@@ -1647,6 +1647,9 @@ check_again:
|
|||||||
/*
|
/*
|
||||||
* drop the above get_user_pages reference.
|
* drop the above get_user_pages reference.
|
||||||
*/
|
*/
|
||||||
|
if (gup_flags & FOLL_PIN)
|
||||||
|
unpin_user_pages(pages, nr_pages);
|
||||||
|
else
|
||||||
for (i = 0; i < nr_pages; i++)
|
for (i = 0; i < nr_pages; i++)
|
||||||
put_page(pages[i]);
|
put_page(pages[i]);
|
||||||
|
|
||||||
@@ -1728,6 +1731,9 @@ static long __gup_longterm_locked(struct mm_struct *mm,
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (check_dax_vmas(vmas_tmp, rc)) {
|
if (check_dax_vmas(vmas_tmp, rc)) {
|
||||||
|
if (gup_flags & FOLL_PIN)
|
||||||
|
unpin_user_pages(pages, rc);
|
||||||
|
else
|
||||||
for (i = 0; i < rc; i++)
|
for (i = 0; i < rc; i++)
|
||||||
put_page(pages[i]);
|
put_page(pages[i]);
|
||||||
rc = -EOPNOTSUPP;
|
rc = -EOPNOTSUPP;
|
||||||
|
88
mm/hugetlb.c
88
mm/hugetlb.c
@@ -1567,104 +1567,24 @@ int PageHeadHuge(struct page *page_head)
|
|||||||
return page_head[1].compound_dtor == HUGETLB_PAGE_DTOR;
|
return page_head[1].compound_dtor == HUGETLB_PAGE_DTOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Find address_space associated with hugetlbfs page.
|
|
||||||
* Upon entry page is locked and page 'was' mapped although mapped state
|
|
||||||
* could change. If necessary, use anon_vma to find vma and associated
|
|
||||||
* address space. The returned mapping may be stale, but it can not be
|
|
||||||
* invalid as page lock (which is held) is required to destroy mapping.
|
|
||||||
*/
|
|
||||||
static struct address_space *_get_hugetlb_page_mapping(struct page *hpage)
|
|
||||||
{
|
|
||||||
struct anon_vma *anon_vma;
|
|
||||||
pgoff_t pgoff_start, pgoff_end;
|
|
||||||
struct anon_vma_chain *avc;
|
|
||||||
struct address_space *mapping = page_mapping(hpage);
|
|
||||||
|
|
||||||
/* Simple file based mapping */
|
|
||||||
if (mapping)
|
|
||||||
return mapping;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Even anonymous hugetlbfs mappings are associated with an
|
|
||||||
* underlying hugetlbfs file (see hugetlb_file_setup in mmap
|
|
||||||
* code). Find a vma associated with the anonymous vma, and
|
|
||||||
* use the file pointer to get address_space.
|
|
||||||
*/
|
|
||||||
anon_vma = page_lock_anon_vma_read(hpage);
|
|
||||||
if (!anon_vma)
|
|
||||||
return mapping; /* NULL */
|
|
||||||
|
|
||||||
/* Use first found vma */
|
|
||||||
pgoff_start = page_to_pgoff(hpage);
|
|
||||||
pgoff_end = pgoff_start + pages_per_huge_page(page_hstate(hpage)) - 1;
|
|
||||||
anon_vma_interval_tree_foreach(avc, &anon_vma->rb_root,
|
|
||||||
pgoff_start, pgoff_end) {
|
|
||||||
struct vm_area_struct *vma = avc->vma;
|
|
||||||
|
|
||||||
mapping = vma->vm_file->f_mapping;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
anon_vma_unlock_read(anon_vma);
|
|
||||||
return mapping;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find and lock address space (mapping) in write mode.
|
* Find and lock address space (mapping) in write mode.
|
||||||
*
|
*
|
||||||
* Upon entry, the page is locked which allows us to find the mapping
|
* Upon entry, the page is locked which means that page_mapping() is
|
||||||
* even in the case of an anon page. However, locking order dictates
|
* stable. Due to locking order, we can only trylock_write. If we can
|
||||||
* the i_mmap_rwsem be acquired BEFORE the page lock. This is hugetlbfs
|
* not get the lock, simply return NULL to caller.
|
||||||
* specific. So, we first try to lock the sema while still holding the
|
|
||||||
* page lock. If this works, great! If not, then we need to drop the
|
|
||||||
* page lock and then acquire i_mmap_rwsem and reacquire page lock. Of
|
|
||||||
* course, need to revalidate state along the way.
|
|
||||||
*/
|
*/
|
||||||
struct address_space *hugetlb_page_mapping_lock_write(struct page *hpage)
|
struct address_space *hugetlb_page_mapping_lock_write(struct page *hpage)
|
||||||
{
|
{
|
||||||
struct address_space *mapping, *mapping2;
|
struct address_space *mapping = page_mapping(hpage);
|
||||||
|
|
||||||
mapping = _get_hugetlb_page_mapping(hpage);
|
|
||||||
retry:
|
|
||||||
if (!mapping)
|
if (!mapping)
|
||||||
return mapping;
|
return mapping;
|
||||||
|
|
||||||
/*
|
|
||||||
* If no contention, take lock and return
|
|
||||||
*/
|
|
||||||
if (i_mmap_trylock_write(mapping))
|
if (i_mmap_trylock_write(mapping))
|
||||||
return mapping;
|
return mapping;
|
||||||
|
|
||||||
/*
|
|
||||||
* Must drop page lock and wait on mapping sema.
|
|
||||||
* Note: Once page lock is dropped, mapping could become invalid.
|
|
||||||
* As a hack, increase map count until we lock page again.
|
|
||||||
*/
|
|
||||||
atomic_inc(&hpage->_mapcount);
|
|
||||||
unlock_page(hpage);
|
|
||||||
i_mmap_lock_write(mapping);
|
|
||||||
lock_page(hpage);
|
|
||||||
atomic_add_negative(-1, &hpage->_mapcount);
|
|
||||||
|
|
||||||
/* verify page is still mapped */
|
|
||||||
if (!page_mapped(hpage)) {
|
|
||||||
i_mmap_unlock_write(mapping);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get address space again and verify it is the same one
|
|
||||||
* we locked. If not, drop lock and retry.
|
|
||||||
*/
|
|
||||||
mapping2 = _get_hugetlb_page_mapping(hpage);
|
|
||||||
if (mapping2 != mapping) {
|
|
||||||
i_mmap_unlock_write(mapping);
|
|
||||||
mapping = mapping2;
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mapping;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pgoff_t __basepage_index(struct page *page)
|
pgoff_t __basepage_index(struct page *page)
|
||||||
|
@@ -1057,28 +1057,26 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
|
|||||||
if (!PageHuge(hpage)) {
|
if (!PageHuge(hpage)) {
|
||||||
unmap_success = try_to_unmap(hpage, ttu);
|
unmap_success = try_to_unmap(hpage, ttu);
|
||||||
} else {
|
} else {
|
||||||
|
if (!PageAnon(hpage)) {
|
||||||
/*
|
/*
|
||||||
* For hugetlb pages, try_to_unmap could potentially call
|
* For hugetlb pages in shared mappings, try_to_unmap
|
||||||
* huge_pmd_unshare. Because of this, take semaphore in
|
* could potentially call huge_pmd_unshare. Because of
|
||||||
* write mode here and set TTU_RMAP_LOCKED to indicate we
|
* this, take semaphore in write mode here and set
|
||||||
* have taken the lock at this higer level.
|
* TTU_RMAP_LOCKED to indicate we have taken the lock
|
||||||
*
|
* at this higer level.
|
||||||
* Note that the call to hugetlb_page_mapping_lock_write
|
|
||||||
* is necessary even if mapping is already set. It handles
|
|
||||||
* ugliness of potentially having to drop page lock to obtain
|
|
||||||
* i_mmap_rwsem.
|
|
||||||
*/
|
*/
|
||||||
mapping = hugetlb_page_mapping_lock_write(hpage);
|
mapping = hugetlb_page_mapping_lock_write(hpage);
|
||||||
|
|
||||||
if (mapping) {
|
if (mapping) {
|
||||||
unmap_success = try_to_unmap(hpage,
|
unmap_success = try_to_unmap(hpage,
|
||||||
ttu|TTU_RMAP_LOCKED);
|
ttu|TTU_RMAP_LOCKED);
|
||||||
i_mmap_unlock_write(mapping);
|
i_mmap_unlock_write(mapping);
|
||||||
} else {
|
} else {
|
||||||
pr_info("Memory failure: %#lx: could not find mapping for mapped huge page\n",
|
pr_info("Memory failure: %#lx: could not lock mapping for mapped huge page\n", pfn);
|
||||||
pfn);
|
|
||||||
unmap_success = false;
|
unmap_success = false;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
unmap_success = try_to_unmap(hpage, ttu);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!unmap_success)
|
if (!unmap_success)
|
||||||
pr_err("Memory failure: %#lx: failed to unmap page (mapcount=%d)\n",
|
pr_err("Memory failure: %#lx: failed to unmap page (mapcount=%d)\n",
|
||||||
|
34
mm/migrate.c
34
mm/migrate.c
@@ -1328,34 +1328,38 @@ static int unmap_and_move_huge_page(new_page_t get_new_page,
|
|||||||
goto put_anon;
|
goto put_anon;
|
||||||
|
|
||||||
if (page_mapped(hpage)) {
|
if (page_mapped(hpage)) {
|
||||||
|
bool mapping_locked = false;
|
||||||
|
enum ttu_flags ttu = TTU_MIGRATION|TTU_IGNORE_MLOCK|
|
||||||
|
TTU_IGNORE_ACCESS;
|
||||||
|
|
||||||
|
if (!PageAnon(hpage)) {
|
||||||
/*
|
/*
|
||||||
* try_to_unmap could potentially call huge_pmd_unshare.
|
* In shared mappings, try_to_unmap could potentially
|
||||||
* Because of this, take semaphore in write mode here and
|
* call huge_pmd_unshare. Because of this, take
|
||||||
* set TTU_RMAP_LOCKED to let lower levels know we have
|
* semaphore in write mode here and set TTU_RMAP_LOCKED
|
||||||
* taken the lock.
|
* to let lower levels know we have taken the lock.
|
||||||
*/
|
*/
|
||||||
mapping = hugetlb_page_mapping_lock_write(hpage);
|
mapping = hugetlb_page_mapping_lock_write(hpage);
|
||||||
if (unlikely(!mapping))
|
if (unlikely(!mapping))
|
||||||
goto unlock_put_anon;
|
goto unlock_put_anon;
|
||||||
|
|
||||||
try_to_unmap(hpage,
|
mapping_locked = true;
|
||||||
TTU_MIGRATION|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS|
|
ttu |= TTU_RMAP_LOCKED;
|
||||||
TTU_RMAP_LOCKED);
|
}
|
||||||
|
|
||||||
|
try_to_unmap(hpage, ttu);
|
||||||
page_was_mapped = 1;
|
page_was_mapped = 1;
|
||||||
/*
|
|
||||||
* Leave mapping locked until after subsequent call to
|
if (mapping_locked)
|
||||||
* remove_migration_ptes()
|
i_mmap_unlock_write(mapping);
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!page_mapped(hpage))
|
if (!page_mapped(hpage))
|
||||||
rc = move_to_new_page(new_hpage, hpage, mode);
|
rc = move_to_new_page(new_hpage, hpage, mode);
|
||||||
|
|
||||||
if (page_was_mapped) {
|
if (page_was_mapped)
|
||||||
remove_migration_ptes(hpage,
|
remove_migration_ptes(hpage,
|
||||||
rc == MIGRATEPAGE_SUCCESS ? new_hpage : hpage, true);
|
rc == MIGRATEPAGE_SUCCESS ? new_hpage : hpage, false);
|
||||||
i_mmap_unlock_write(mapping);
|
|
||||||
}
|
|
||||||
|
|
||||||
unlock_put_anon:
|
unlock_put_anon:
|
||||||
unlock_page(new_hpage);
|
unlock_page(new_hpage);
|
||||||
|
@@ -1413,9 +1413,6 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
|
|||||||
/*
|
/*
|
||||||
* If sharing is possible, start and end will be adjusted
|
* If sharing is possible, start and end will be adjusted
|
||||||
* accordingly.
|
* accordingly.
|
||||||
*
|
|
||||||
* If called for a huge page, caller must hold i_mmap_rwsem
|
|
||||||
* in write mode as it is possible to call huge_pmd_unshare.
|
|
||||||
*/
|
*/
|
||||||
adjust_range_if_pmd_sharing_possible(vma, &range.start,
|
adjust_range_if_pmd_sharing_possible(vma, &range.start,
|
||||||
&range.end);
|
&range.end);
|
||||||
@@ -1462,7 +1459,7 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
|
|||||||
subpage = page - page_to_pfn(page) + pte_pfn(*pvmw.pte);
|
subpage = page - page_to_pfn(page) + pte_pfn(*pvmw.pte);
|
||||||
address = pvmw.address;
|
address = pvmw.address;
|
||||||
|
|
||||||
if (PageHuge(page)) {
|
if (PageHuge(page) && !PageAnon(page)) {
|
||||||
/*
|
/*
|
||||||
* To call huge_pmd_unshare, i_mmap_rwsem must be
|
* To call huge_pmd_unshare, i_mmap_rwsem must be
|
||||||
* held in write mode. Caller needs to explicitly
|
* held in write mode. Caller needs to explicitly
|
||||||
|
@@ -2852,7 +2852,7 @@ redo:
|
|||||||
|
|
||||||
object = c->freelist;
|
object = c->freelist;
|
||||||
page = c->page;
|
page = c->page;
|
||||||
if (unlikely(!object || !node_match(page, node))) {
|
if (unlikely(!object || !page || !node_match(page, node))) {
|
||||||
object = __slab_alloc(s, gfpflags, node, addr, c);
|
object = __slab_alloc(s, gfpflags, node, addr, c);
|
||||||
} else {
|
} else {
|
||||||
void *next_object = get_freepointer_safe(s, object);
|
void *next_object = get_freepointer_safe(s, object);
|
||||||
|
@@ -1516,7 +1516,8 @@ unsigned int reclaim_clean_pages_from_list(struct zone *zone,
|
|||||||
nr_reclaimed = shrink_page_list(&clean_pages, zone->zone_pgdat, &sc,
|
nr_reclaimed = shrink_page_list(&clean_pages, zone->zone_pgdat, &sc,
|
||||||
TTU_IGNORE_ACCESS, &stat, true);
|
TTU_IGNORE_ACCESS, &stat, true);
|
||||||
list_splice(&clean_pages, page_list);
|
list_splice(&clean_pages, page_list);
|
||||||
mod_node_page_state(zone->zone_pgdat, NR_ISOLATED_FILE, -nr_reclaimed);
|
mod_node_page_state(zone->zone_pgdat, NR_ISOLATED_FILE,
|
||||||
|
-(long)nr_reclaimed);
|
||||||
/*
|
/*
|
||||||
* Since lazyfree pages are isolated from file LRU from the beginning,
|
* Since lazyfree pages are isolated from file LRU from the beginning,
|
||||||
* they will rotate back to anonymous LRU in the end if it failed to
|
* they will rotate back to anonymous LRU in the end if it failed to
|
||||||
@@ -1526,7 +1527,7 @@ unsigned int reclaim_clean_pages_from_list(struct zone *zone,
|
|||||||
mod_node_page_state(zone->zone_pgdat, NR_ISOLATED_ANON,
|
mod_node_page_state(zone->zone_pgdat, NR_ISOLATED_ANON,
|
||||||
stat.nr_lazyfree_fail);
|
stat.nr_lazyfree_fail);
|
||||||
mod_node_page_state(zone->zone_pgdat, NR_ISOLATED_FILE,
|
mod_node_page_state(zone->zone_pgdat, NR_ISOLATED_FILE,
|
||||||
-stat.nr_lazyfree_fail);
|
-(long)stat.nr_lazyfree_fail);
|
||||||
return nr_reclaimed;
|
return nr_reclaimed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -151,8 +151,10 @@ static int sel_ib_pkey_sid_slow(u64 subnet_prefix, u16 pkey_num, u32 *sid)
|
|||||||
* is valid, it just won't be added to the cache.
|
* is valid, it just won't be added to the cache.
|
||||||
*/
|
*/
|
||||||
new = kzalloc(sizeof(*new), GFP_ATOMIC);
|
new = kzalloc(sizeof(*new), GFP_ATOMIC);
|
||||||
if (!new)
|
if (!new) {
|
||||||
|
ret = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
new->psec.subnet_prefix = subnet_prefix;
|
new->psec.subnet_prefix = subnet_prefix;
|
||||||
new->psec.pkey = pkey_num;
|
new->psec.pkey = pkey_num;
|
||||||
|
Reference in New Issue
Block a user