From 08dcc57fcd240922347c8a9f14d18e67a3f9f1a9 Mon Sep 17 00:00:00 2001 From: Ben Goz Date: Fri, 2 Jan 2015 23:43:19 +0200 Subject: [PATCH 0001/3023] drm/radeon: Initialize compute vmid This patch moves to radeon the initialization of compute vmid. That initializations was done in kfd-->kgd interface, but doing it in radeon as part of radeon's H/W initialization routines is more appropriate. In addition, this simplifies the kfd-->kgd interface. The patch removes the function from the interface file and from the interface declaration file. The function initializes memory apertures to fixed base/limit address and non cached memory types. Signed-off-by: Ben Goz Signed-off-by: Oded Gabbay Reviewed-by: Alex Deucher --- .../gpu/drm/amd/include/kgd_kfd_interface.h | 4 -- drivers/gpu/drm/radeon/cik.c | 24 ++++++++++++ drivers/gpu/drm/radeon/radeon_kfd.c | 39 ------------------- 3 files changed, 24 insertions(+), 43 deletions(-) diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h index cd3878fe6f77a9..883499740e3314 100644 --- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h @@ -129,9 +129,6 @@ struct kgd2kfd_calls { * @set_pasid_vmid_mapping: Exposes pasid/vmid pair to the H/W for no cp * scheduling mode. Only used for no cp scheduling mode. * - * @init_memory: Initializes memory apertures to fixed base/limit address - * and non cached memory types. - * * @init_pipeline: Initialized the compute pipelines. * * @hqd_load: Loads the mqd structure to a H/W hqd slot. used only for no cp @@ -175,7 +172,6 @@ struct kfd2kgd_calls { int (*set_pasid_vmid_mapping)(struct kgd_dev *kgd, unsigned int pasid, unsigned int vmid); - int (*init_memory)(struct kgd_dev *kgd); int (*init_pipeline)(struct kgd_dev *kgd, uint32_t pipe_id, uint32_t hpd_size, uint64_t hpd_gpu_addr); diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 6dcde3798b45a0..14d173e2a8f7e5 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -5707,6 +5707,28 @@ void cik_pcie_gart_tlb_flush(struct radeon_device *rdev) WREG32(VM_INVALIDATE_REQUEST, 0x1); } +static void cik_pcie_init_compute_vmid(struct radeon_device *rdev) +{ + int i; + uint32_t sh_mem_bases, sh_mem_config; + + sh_mem_bases = 0x6000 | 0x6000 << 16; + sh_mem_config = ALIGNMENT_MODE(SH_MEM_ALIGNMENT_MODE_UNALIGNED); + sh_mem_config |= DEFAULT_MTYPE(MTYPE_NONCACHED); + + mutex_lock(&rdev->srbm_mutex); + for (i = 8; i < 16; i++) { + cik_srbm_select(rdev, 0, 0, 0, i); + /* CP and shaders */ + WREG32(SH_MEM_CONFIG, sh_mem_config); + WREG32(SH_MEM_APE1_BASE, 1); + WREG32(SH_MEM_APE1_LIMIT, 0); + WREG32(SH_MEM_BASES, sh_mem_bases); + } + cik_srbm_select(rdev, 0, 0, 0, 0); + mutex_unlock(&rdev->srbm_mutex); +} + /** * cik_pcie_gart_enable - gart enable * @@ -5820,6 +5842,8 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev) cik_srbm_select(rdev, 0, 0, 0, 0); mutex_unlock(&rdev->srbm_mutex); + cik_pcie_init_compute_vmid(rdev); + cik_pcie_gart_tlb_flush(rdev); DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", (unsigned)(rdev->mc.gtt_size >> 20), diff --git a/drivers/gpu/drm/radeon/radeon_kfd.c b/drivers/gpu/drm/radeon/radeon_kfd.c index cae11eefecf088..13e8066aef70a0 100644 --- a/drivers/gpu/drm/radeon/radeon_kfd.c +++ b/drivers/gpu/drm/radeon/radeon_kfd.c @@ -63,8 +63,6 @@ static void kgd_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid, static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid, unsigned int vmid); -static int kgd_init_memory(struct kgd_dev *kgd); - static int kgd_init_pipeline(struct kgd_dev *kgd, uint32_t pipe_id, uint32_t hpd_size, uint64_t hpd_gpu_addr); @@ -89,7 +87,6 @@ static const struct kfd2kgd_calls kfd2kgd = { .get_max_engine_clock_in_mhz = get_max_engine_clock_in_mhz, .program_sh_mem_settings = kgd_program_sh_mem_settings, .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping, - .init_memory = kgd_init_memory, .init_pipeline = kgd_init_pipeline, .hqd_load = kgd_hqd_load, .hqd_sdma_load = kgd_hqd_sdma_load, @@ -375,42 +372,6 @@ static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid, return 0; } -static int kgd_init_memory(struct kgd_dev *kgd) -{ - /* - * Configure apertures: - * LDS: 0x60000000'00000000 - 0x60000001'00000000 (4GB) - * Scratch: 0x60000001'00000000 - 0x60000002'00000000 (4GB) - * GPUVM: 0x60010000'00000000 - 0x60020000'00000000 (1TB) - */ - int i; - uint32_t sh_mem_bases = PRIVATE_BASE(0x6000) | SHARED_BASE(0x6000); - - for (i = 8; i < 16; i++) { - uint32_t sh_mem_config; - - lock_srbm(kgd, 0, 0, 0, i); - - sh_mem_config = ALIGNMENT_MODE(SH_MEM_ALIGNMENT_MODE_UNALIGNED); - sh_mem_config |= DEFAULT_MTYPE(MTYPE_NONCACHED); - - write_register(kgd, SH_MEM_CONFIG, sh_mem_config); - - write_register(kgd, SH_MEM_BASES, sh_mem_bases); - - /* Scratch aperture is not supported for now. */ - write_register(kgd, SH_STATIC_MEM_CONFIG, 0); - - /* APE1 disabled for now. */ - write_register(kgd, SH_MEM_APE1_BASE, 1); - write_register(kgd, SH_MEM_APE1_LIMIT, 0); - - unlock_srbm(kgd); - } - - return 0; -} - static int kgd_init_pipeline(struct kgd_dev *kgd, uint32_t pipe_id, uint32_t hpd_size, uint64_t hpd_gpu_addr) { From fe502804205e4103bdff4854bb41cd78fa82b099 Mon Sep 17 00:00:00 2001 From: Ben Goz Date: Sun, 26 Oct 2014 18:07:34 +0200 Subject: [PATCH 0002/3023] drm/amdkfd: Remove call to deprecated init_memory interface This patch removes a call to kfd-->kgd interface function that is doing H/W initialization. That function is moved into radeon to be part of the common H/W initialization sequence. The interface function will be deleted. Signed-off-by: Ben Goz Signed-off-by: Oded Gabbay Reviewed-by: Alex Deucher --- .../drm/amd/amdkfd/kfd_device_queue_manager.c | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 6806e64c5ffd91..60f4ccbbb30165 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -37,9 +37,6 @@ #define CIK_HPD_EOP_BYTES_LOG2 11 #define CIK_HPD_EOP_BYTES (1U << CIK_HPD_EOP_BYTES_LOG2) -static bool is_mem_initialized; - -static int init_memory(struct device_queue_manager *dqm); static int set_pasid_vmid_mapping(struct device_queue_manager *dqm, unsigned int pasid, unsigned int vmid); @@ -486,20 +483,6 @@ static uint32_t compute_sh_mem_bases_64bit(unsigned int top_address_nybble) SHARED_BASE(top_address_nybble << 12); } -static int init_memory(struct device_queue_manager *dqm) -{ - int i, retval; - - for (i = 8; i < 16; i++) - set_pasid_vmid_mapping(dqm, 0, i); - - retval = kfd2kgd->init_memory(dqm->dev->kgd); - if (retval == 0) - is_mem_initialized = true; - return retval; -} - - static int init_pipelines(struct device_queue_manager *dqm, unsigned int pipes_num, unsigned int first_pipe) { @@ -560,10 +543,6 @@ static int init_scheduler(struct device_queue_manager *dqm) pr_debug("kfd: In %s\n", __func__); retval = init_pipelines(dqm, get_pipes_num(dqm), KFD_DQM_FIRST_PIPE); - if (retval != 0) - return retval; - - retval = init_memory(dqm); return retval; } From 23d6cbe616b66ef85cee2ad8b9d9e7873bb81ed3 Mon Sep 17 00:00:00 2001 From: Oded Gabbay Date: Fri, 2 Jan 2015 23:32:49 +0200 Subject: [PATCH 0003/3023] drm/radeon: Don't use relative paths in #include Signed-off-by: Oded Gabbay Reviewed-by: Alex Deucher --- drivers/gpu/drm/radeon/Makefile | 2 +- drivers/gpu/drm/radeon/radeon_kfd.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile index 12bc21219a0ea1..c58cfd3c391784 100644 --- a/drivers/gpu/drm/radeon/Makefile +++ b/drivers/gpu/drm/radeon/Makefile @@ -2,7 +2,7 @@ # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. -ccflags-y := -Iinclude/drm +ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/amd/include hostprogs-y := mkregtable clean-files := rn50_reg_safe.h r100_reg_safe.h r200_reg_safe.h rv515_reg_safe.h r300_reg_safe.h r420_reg_safe.h rs600_reg_safe.h r600_reg_safe.h evergreen_reg_safe.h cayman_reg_safe.h diff --git a/drivers/gpu/drm/radeon/radeon_kfd.h b/drivers/gpu/drm/radeon/radeon_kfd.h index f90e161ca507c5..1103f9082f6b06 100644 --- a/drivers/gpu/drm/radeon/radeon_kfd.h +++ b/drivers/gpu/drm/radeon/radeon_kfd.h @@ -29,7 +29,7 @@ #define RADEON_KFD_H_INCLUDED #include -#include "../amd/include/kgd_kfd_interface.h" +#include "kgd_kfd_interface.h" struct radeon_device; From bd7fbd38e58046d8b2e37003e01b9fa0f545e5ae Mon Sep 17 00:00:00 2001 From: Ben Goz Date: Fri, 2 Jan 2015 23:18:39 +0200 Subject: [PATCH 0004/3023] drm/amd: Put cik structures in a common place This patch creates a new file, cik_structs.h, and puts the cik_mqd and cik_sdma_rlc_registers structures in that file. The new file is placed in a common include folder under the drm/amd folder, so it will be shared among all amd drm drivers. Signed-off-by: Ben Goz Signed-off-by: Oded Gabbay Reviewed-by: Alex Deucher --- drivers/gpu/drm/amd/include/cik_structs.h | 293 ++++++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 drivers/gpu/drm/amd/include/cik_structs.h diff --git a/drivers/gpu/drm/amd/include/cik_structs.h b/drivers/gpu/drm/amd/include/cik_structs.h new file mode 100644 index 00000000000000..749eab94e335d7 --- /dev/null +++ b/drivers/gpu/drm/amd/include/cik_structs.h @@ -0,0 +1,293 @@ +/* + * Copyright 2012 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef CIK_STRUCTS_H_ +#define CIK_STRUCTS_H_ + +struct cik_mqd { + uint32_t header; + uint32_t compute_dispatch_initiator; + uint32_t compute_dim_x; + uint32_t compute_dim_y; + uint32_t compute_dim_z; + uint32_t compute_start_x; + uint32_t compute_start_y; + uint32_t compute_start_z; + uint32_t compute_num_thread_x; + uint32_t compute_num_thread_y; + uint32_t compute_num_thread_z; + uint32_t compute_pipelinestat_enable; + uint32_t compute_perfcount_enable; + uint32_t compute_pgm_lo; + uint32_t compute_pgm_hi; + uint32_t compute_tba_lo; + uint32_t compute_tba_hi; + uint32_t compute_tma_lo; + uint32_t compute_tma_hi; + uint32_t compute_pgm_rsrc1; + uint32_t compute_pgm_rsrc2; + uint32_t compute_vmid; + uint32_t compute_resource_limits; + uint32_t compute_static_thread_mgmt_se0; + uint32_t compute_static_thread_mgmt_se1; + uint32_t compute_tmpring_size; + uint32_t compute_static_thread_mgmt_se2; + uint32_t compute_static_thread_mgmt_se3; + uint32_t compute_restart_x; + uint32_t compute_restart_y; + uint32_t compute_restart_z; + uint32_t compute_thread_trace_enable; + uint32_t compute_misc_reserved; + uint32_t compute_user_data_0; + uint32_t compute_user_data_1; + uint32_t compute_user_data_2; + uint32_t compute_user_data_3; + uint32_t compute_user_data_4; + uint32_t compute_user_data_5; + uint32_t compute_user_data_6; + uint32_t compute_user_data_7; + uint32_t compute_user_data_8; + uint32_t compute_user_data_9; + uint32_t compute_user_data_10; + uint32_t compute_user_data_11; + uint32_t compute_user_data_12; + uint32_t compute_user_data_13; + uint32_t compute_user_data_14; + uint32_t compute_user_data_15; + uint32_t cp_compute_csinvoc_count_lo; + uint32_t cp_compute_csinvoc_count_hi; + uint32_t cp_mqd_base_addr_lo; + uint32_t cp_mqd_base_addr_hi; + uint32_t cp_hqd_active; + uint32_t cp_hqd_vmid; + uint32_t cp_hqd_persistent_state; + uint32_t cp_hqd_pipe_priority; + uint32_t cp_hqd_queue_priority; + uint32_t cp_hqd_quantum; + uint32_t cp_hqd_pq_base_lo; + uint32_t cp_hqd_pq_base_hi; + uint32_t cp_hqd_pq_rptr; + uint32_t cp_hqd_pq_rptr_report_addr_lo; + uint32_t cp_hqd_pq_rptr_report_addr_hi; + uint32_t cp_hqd_pq_wptr_poll_addr_lo; + uint32_t cp_hqd_pq_wptr_poll_addr_hi; + uint32_t cp_hqd_pq_doorbell_control; + uint32_t cp_hqd_pq_wptr; + uint32_t cp_hqd_pq_control; + uint32_t cp_hqd_ib_base_addr_lo; + uint32_t cp_hqd_ib_base_addr_hi; + uint32_t cp_hqd_ib_rptr; + uint32_t cp_hqd_ib_control; + uint32_t cp_hqd_iq_timer; + uint32_t cp_hqd_iq_rptr; + uint32_t cp_hqd_dequeue_request; + uint32_t cp_hqd_dma_offload; + uint32_t cp_hqd_sema_cmd; + uint32_t cp_hqd_msg_type; + uint32_t cp_hqd_atomic0_preop_lo; + uint32_t cp_hqd_atomic0_preop_hi; + uint32_t cp_hqd_atomic1_preop_lo; + uint32_t cp_hqd_atomic1_preop_hi; + uint32_t cp_hqd_hq_status0; + uint32_t cp_hqd_hq_control0; + uint32_t cp_mqd_control; + uint32_t cp_mqd_query_time_lo; + uint32_t cp_mqd_query_time_hi; + uint32_t cp_mqd_connect_start_time_lo; + uint32_t cp_mqd_connect_start_time_hi; + uint32_t cp_mqd_connect_end_time_lo; + uint32_t cp_mqd_connect_end_time_hi; + uint32_t cp_mqd_connect_end_wf_count; + uint32_t cp_mqd_connect_end_pq_rptr; + uint32_t cp_mqd_connect_end_pq_wptr; + uint32_t cp_mqd_connect_end_ib_rptr; + uint32_t reserved_96; + uint32_t reserved_97; + uint32_t reserved_98; + uint32_t reserved_99; + uint32_t iqtimer_pkt_header; + uint32_t iqtimer_pkt_dw0; + uint32_t iqtimer_pkt_dw1; + uint32_t iqtimer_pkt_dw2; + uint32_t iqtimer_pkt_dw3; + uint32_t iqtimer_pkt_dw4; + uint32_t iqtimer_pkt_dw5; + uint32_t iqtimer_pkt_dw6; + uint32_t reserved_108; + uint32_t reserved_109; + uint32_t reserved_110; + uint32_t reserved_111; + uint32_t queue_doorbell_id0; + uint32_t queue_doorbell_id1; + uint32_t queue_doorbell_id2; + uint32_t queue_doorbell_id3; + uint32_t queue_doorbell_id4; + uint32_t queue_doorbell_id5; + uint32_t queue_doorbell_id6; + uint32_t queue_doorbell_id7; + uint32_t queue_doorbell_id8; + uint32_t queue_doorbell_id9; + uint32_t queue_doorbell_id10; + uint32_t queue_doorbell_id11; + uint32_t queue_doorbell_id12; + uint32_t queue_doorbell_id13; + uint32_t queue_doorbell_id14; + uint32_t queue_doorbell_id15; +}; + +struct cik_sdma_rlc_registers { + uint32_t sdma_rlc_rb_cntl; + uint32_t sdma_rlc_rb_base; + uint32_t sdma_rlc_rb_base_hi; + uint32_t sdma_rlc_rb_rptr; + uint32_t sdma_rlc_rb_wptr; + uint32_t sdma_rlc_rb_wptr_poll_cntl; + uint32_t sdma_rlc_rb_wptr_poll_addr_hi; + uint32_t sdma_rlc_rb_wptr_poll_addr_lo; + uint32_t sdma_rlc_rb_rptr_addr_hi; + uint32_t sdma_rlc_rb_rptr_addr_lo; + uint32_t sdma_rlc_ib_cntl; + uint32_t sdma_rlc_ib_rptr; + uint32_t sdma_rlc_ib_offset; + uint32_t sdma_rlc_ib_base_lo; + uint32_t sdma_rlc_ib_base_hi; + uint32_t sdma_rlc_ib_size; + uint32_t sdma_rlc_skip_cntl; + uint32_t sdma_rlc_context_status; + uint32_t sdma_rlc_doorbell; + uint32_t sdma_rlc_virtual_addr; + uint32_t sdma_rlc_ape1_cntl; + uint32_t sdma_rlc_doorbell_log; + uint32_t reserved_22; + uint32_t reserved_23; + uint32_t reserved_24; + uint32_t reserved_25; + uint32_t reserved_26; + uint32_t reserved_27; + uint32_t reserved_28; + uint32_t reserved_29; + uint32_t reserved_30; + uint32_t reserved_31; + uint32_t reserved_32; + uint32_t reserved_33; + uint32_t reserved_34; + uint32_t reserved_35; + uint32_t reserved_36; + uint32_t reserved_37; + uint32_t reserved_38; + uint32_t reserved_39; + uint32_t reserved_40; + uint32_t reserved_41; + uint32_t reserved_42; + uint32_t reserved_43; + uint32_t reserved_44; + uint32_t reserved_45; + uint32_t reserved_46; + uint32_t reserved_47; + uint32_t reserved_48; + uint32_t reserved_49; + uint32_t reserved_50; + uint32_t reserved_51; + uint32_t reserved_52; + uint32_t reserved_53; + uint32_t reserved_54; + uint32_t reserved_55; + uint32_t reserved_56; + uint32_t reserved_57; + uint32_t reserved_58; + uint32_t reserved_59; + uint32_t reserved_60; + uint32_t reserved_61; + uint32_t reserved_62; + uint32_t reserved_63; + uint32_t reserved_64; + uint32_t reserved_65; + uint32_t reserved_66; + uint32_t reserved_67; + uint32_t reserved_68; + uint32_t reserved_69; + uint32_t reserved_70; + uint32_t reserved_71; + uint32_t reserved_72; + uint32_t reserved_73; + uint32_t reserved_74; + uint32_t reserved_75; + uint32_t reserved_76; + uint32_t reserved_77; + uint32_t reserved_78; + uint32_t reserved_79; + uint32_t reserved_80; + uint32_t reserved_81; + uint32_t reserved_82; + uint32_t reserved_83; + uint32_t reserved_84; + uint32_t reserved_85; + uint32_t reserved_86; + uint32_t reserved_87; + uint32_t reserved_88; + uint32_t reserved_89; + uint32_t reserved_90; + uint32_t reserved_91; + uint32_t reserved_92; + uint32_t reserved_93; + uint32_t reserved_94; + uint32_t reserved_95; + uint32_t reserved_96; + uint32_t reserved_97; + uint32_t reserved_98; + uint32_t reserved_99; + uint32_t reserved_100; + uint32_t reserved_101; + uint32_t reserved_102; + uint32_t reserved_103; + uint32_t reserved_104; + uint32_t reserved_105; + uint32_t reserved_106; + uint32_t reserved_107; + uint32_t reserved_108; + uint32_t reserved_109; + uint32_t reserved_110; + uint32_t reserved_111; + uint32_t reserved_112; + uint32_t reserved_113; + uint32_t reserved_114; + uint32_t reserved_115; + uint32_t reserved_116; + uint32_t reserved_117; + uint32_t reserved_118; + uint32_t reserved_119; + uint32_t reserved_120; + uint32_t reserved_121; + uint32_t reserved_122; + uint32_t reserved_123; + uint32_t reserved_124; + uint32_t reserved_125; + uint32_t reserved_126; + uint32_t reserved_127; + uint32_t sdma_engine_id; + uint32_t sdma_queue_id; +}; + + + +#endif /* CIK_STRUCTS_H_ */ From 71273adc52fafcda181e62cef64ddffd76d91944 Mon Sep 17 00:00:00 2001 From: Oded Gabbay Date: Fri, 2 Jan 2015 23:18:54 +0200 Subject: [PATCH 0005/3023] drm/amdkfd: Don't include header files from radeon Because amdkfd will need to work both with radeon and amdgpu, don't include header files that are in radeon's folder. Instead, use the common amd include folder and move amdkfd specific defines to amdkfd header files. Signed-off-by: Oded Gabbay Reviewed-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/cik_regs.h | 13 +++++++++++++ .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 1 - drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c | 3 +-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/cik_regs.h b/drivers/gpu/drm/amd/amdkfd/cik_regs.h index 607fc5ceadbeff..01ff332fabd4b8 100644 --- a/drivers/gpu/drm/amd/amdkfd/cik_regs.h +++ b/drivers/gpu/drm/amd/amdkfd/cik_regs.h @@ -168,6 +168,8 @@ #define IB_ATC_EN (1U << 23) #define DEFAULT_MIN_IB_AVAIL_SIZE (3U << 20) +#define AQL_ENABLE 1 + #define CP_HQD_DEQUEUE_REQUEST 0xC974 #define DEQUEUE_REQUEST_DRAIN 1 #define DEQUEUE_REQUEST_RESET 2 @@ -188,6 +190,17 @@ #define MQD_VMID_MASK (0xf << 0) #define MQD_CONTROL_PRIV_STATE_EN (1U << 8) +#define SDMA_RB_VMID(x) (x << 24) +#define SDMA_RB_ENABLE (1 << 0) +#define SDMA_RB_SIZE(x) ((x) << 1) /* log2 */ +#define SDMA_RPTR_WRITEBACK_ENABLE (1 << 12) +#define SDMA_RPTR_WRITEBACK_TIMER(x) ((x) << 16) /* log2 */ +#define SDMA_OFFSET(x) (x << 0) +#define SDMA_DB_ENABLE (1 << 28) +#define SDMA_ATC (1 << 0) +#define SDMA_VA_PTR32 (1 << 4) +#define SDMA_VA_SHARED_BASE(x) (x << 8) + #define GRBM_GFX_INDEX 0x30800 #define INSTANCE_INDEX(x) ((x) << 0) #define SH_INDEX(x) ((x) << 8) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 60f4ccbbb30165..fead2d7c087775 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -31,7 +31,6 @@ #include "kfd_mqd_manager.h" #include "cik_regs.h" #include "kfd_kernel_queue.h" -#include "../../radeon/cik_reg.h" /* Size of the per-pipe EOP queue */ #define CIK_HPD_EOP_BYTES_LOG2 11 diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c index 678c33f0a1b8ee..155e33ceda9ac3 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c @@ -26,8 +26,7 @@ #include "kfd_priv.h" #include "kfd_mqd_manager.h" #include "cik_regs.h" -#include "../../radeon/cikd.h" -#include "../../radeon/cik_reg.h" +#include "cik_structs.h" inline void busy_wait(unsigned long ms) { From 836aabc0d4e2a5c5c375c3f44da4096b1073a525 Mon Sep 17 00:00:00 2001 From: Oded Gabbay Date: Fri, 2 Jan 2015 23:33:20 +0200 Subject: [PATCH 0006/3023] drm/radeon: Use new cik_structs.h file Signed-off-by: Oded Gabbay Reviewed-by: Alex Deucher --- drivers/gpu/drm/radeon/cik_reg.h | 264 ---------------------------- drivers/gpu/drm/radeon/radeon_kfd.c | 1 + 2 files changed, 1 insertion(+), 264 deletions(-) diff --git a/drivers/gpu/drm/radeon/cik_reg.h b/drivers/gpu/drm/radeon/cik_reg.h index bbb8f2e4363771..f667347d8157ce 100644 --- a/drivers/gpu/drm/radeon/cik_reg.h +++ b/drivers/gpu/drm/radeon/cik_reg.h @@ -184,268 +184,4 @@ #define SDMA0_CNTL 0xD010 #define SDMA1_CNTL 0xD810 -struct cik_mqd { - uint32_t header; - uint32_t compute_dispatch_initiator; - uint32_t compute_dim_x; - uint32_t compute_dim_y; - uint32_t compute_dim_z; - uint32_t compute_start_x; - uint32_t compute_start_y; - uint32_t compute_start_z; - uint32_t compute_num_thread_x; - uint32_t compute_num_thread_y; - uint32_t compute_num_thread_z; - uint32_t compute_pipelinestat_enable; - uint32_t compute_perfcount_enable; - uint32_t compute_pgm_lo; - uint32_t compute_pgm_hi; - uint32_t compute_tba_lo; - uint32_t compute_tba_hi; - uint32_t compute_tma_lo; - uint32_t compute_tma_hi; - uint32_t compute_pgm_rsrc1; - uint32_t compute_pgm_rsrc2; - uint32_t compute_vmid; - uint32_t compute_resource_limits; - uint32_t compute_static_thread_mgmt_se0; - uint32_t compute_static_thread_mgmt_se1; - uint32_t compute_tmpring_size; - uint32_t compute_static_thread_mgmt_se2; - uint32_t compute_static_thread_mgmt_se3; - uint32_t compute_restart_x; - uint32_t compute_restart_y; - uint32_t compute_restart_z; - uint32_t compute_thread_trace_enable; - uint32_t compute_misc_reserved; - uint32_t compute_user_data_0; - uint32_t compute_user_data_1; - uint32_t compute_user_data_2; - uint32_t compute_user_data_3; - uint32_t compute_user_data_4; - uint32_t compute_user_data_5; - uint32_t compute_user_data_6; - uint32_t compute_user_data_7; - uint32_t compute_user_data_8; - uint32_t compute_user_data_9; - uint32_t compute_user_data_10; - uint32_t compute_user_data_11; - uint32_t compute_user_data_12; - uint32_t compute_user_data_13; - uint32_t compute_user_data_14; - uint32_t compute_user_data_15; - uint32_t cp_compute_csinvoc_count_lo; - uint32_t cp_compute_csinvoc_count_hi; - uint32_t cp_mqd_base_addr_lo; - uint32_t cp_mqd_base_addr_hi; - uint32_t cp_hqd_active; - uint32_t cp_hqd_vmid; - uint32_t cp_hqd_persistent_state; - uint32_t cp_hqd_pipe_priority; - uint32_t cp_hqd_queue_priority; - uint32_t cp_hqd_quantum; - uint32_t cp_hqd_pq_base_lo; - uint32_t cp_hqd_pq_base_hi; - uint32_t cp_hqd_pq_rptr; - uint32_t cp_hqd_pq_rptr_report_addr_lo; - uint32_t cp_hqd_pq_rptr_report_addr_hi; - uint32_t cp_hqd_pq_wptr_poll_addr_lo; - uint32_t cp_hqd_pq_wptr_poll_addr_hi; - uint32_t cp_hqd_pq_doorbell_control; - uint32_t cp_hqd_pq_wptr; - uint32_t cp_hqd_pq_control; - uint32_t cp_hqd_ib_base_addr_lo; - uint32_t cp_hqd_ib_base_addr_hi; - uint32_t cp_hqd_ib_rptr; - uint32_t cp_hqd_ib_control; - uint32_t cp_hqd_iq_timer; - uint32_t cp_hqd_iq_rptr; - uint32_t cp_hqd_dequeue_request; - uint32_t cp_hqd_dma_offload; - uint32_t cp_hqd_sema_cmd; - uint32_t cp_hqd_msg_type; - uint32_t cp_hqd_atomic0_preop_lo; - uint32_t cp_hqd_atomic0_preop_hi; - uint32_t cp_hqd_atomic1_preop_lo; - uint32_t cp_hqd_atomic1_preop_hi; - uint32_t cp_hqd_hq_status0; - uint32_t cp_hqd_hq_control0; - uint32_t cp_mqd_control; - uint32_t cp_mqd_query_time_lo; - uint32_t cp_mqd_query_time_hi; - uint32_t cp_mqd_connect_start_time_lo; - uint32_t cp_mqd_connect_start_time_hi; - uint32_t cp_mqd_connect_end_time_lo; - uint32_t cp_mqd_connect_end_time_hi; - uint32_t cp_mqd_connect_end_wf_count; - uint32_t cp_mqd_connect_end_pq_rptr; - uint32_t cp_mqd_connect_end_pq_wptr; - uint32_t cp_mqd_connect_end_ib_rptr; - uint32_t reserved_96; - uint32_t reserved_97; - uint32_t reserved_98; - uint32_t reserved_99; - uint32_t iqtimer_pkt_header; - uint32_t iqtimer_pkt_dw0; - uint32_t iqtimer_pkt_dw1; - uint32_t iqtimer_pkt_dw2; - uint32_t iqtimer_pkt_dw3; - uint32_t iqtimer_pkt_dw4; - uint32_t iqtimer_pkt_dw5; - uint32_t iqtimer_pkt_dw6; - uint32_t reserved_108; - uint32_t reserved_109; - uint32_t reserved_110; - uint32_t reserved_111; - uint32_t queue_doorbell_id0; - uint32_t queue_doorbell_id1; - uint32_t queue_doorbell_id2; - uint32_t queue_doorbell_id3; - uint32_t queue_doorbell_id4; - uint32_t queue_doorbell_id5; - uint32_t queue_doorbell_id6; - uint32_t queue_doorbell_id7; - uint32_t queue_doorbell_id8; - uint32_t queue_doorbell_id9; - uint32_t queue_doorbell_id10; - uint32_t queue_doorbell_id11; - uint32_t queue_doorbell_id12; - uint32_t queue_doorbell_id13; - uint32_t queue_doorbell_id14; - uint32_t queue_doorbell_id15; -}; - -struct cik_sdma_rlc_registers { - uint32_t sdma_rlc_rb_cntl; - uint32_t sdma_rlc_rb_base; - uint32_t sdma_rlc_rb_base_hi; - uint32_t sdma_rlc_rb_rptr; - uint32_t sdma_rlc_rb_wptr; - uint32_t sdma_rlc_rb_wptr_poll_cntl; - uint32_t sdma_rlc_rb_wptr_poll_addr_hi; - uint32_t sdma_rlc_rb_wptr_poll_addr_lo; - uint32_t sdma_rlc_rb_rptr_addr_hi; - uint32_t sdma_rlc_rb_rptr_addr_lo; - uint32_t sdma_rlc_ib_cntl; - uint32_t sdma_rlc_ib_rptr; - uint32_t sdma_rlc_ib_offset; - uint32_t sdma_rlc_ib_base_lo; - uint32_t sdma_rlc_ib_base_hi; - uint32_t sdma_rlc_ib_size; - uint32_t sdma_rlc_skip_cntl; - uint32_t sdma_rlc_context_status; - uint32_t sdma_rlc_doorbell; - uint32_t sdma_rlc_virtual_addr; - uint32_t sdma_rlc_ape1_cntl; - uint32_t sdma_rlc_doorbell_log; - uint32_t reserved_22; - uint32_t reserved_23; - uint32_t reserved_24; - uint32_t reserved_25; - uint32_t reserved_26; - uint32_t reserved_27; - uint32_t reserved_28; - uint32_t reserved_29; - uint32_t reserved_30; - uint32_t reserved_31; - uint32_t reserved_32; - uint32_t reserved_33; - uint32_t reserved_34; - uint32_t reserved_35; - uint32_t reserved_36; - uint32_t reserved_37; - uint32_t reserved_38; - uint32_t reserved_39; - uint32_t reserved_40; - uint32_t reserved_41; - uint32_t reserved_42; - uint32_t reserved_43; - uint32_t reserved_44; - uint32_t reserved_45; - uint32_t reserved_46; - uint32_t reserved_47; - uint32_t reserved_48; - uint32_t reserved_49; - uint32_t reserved_50; - uint32_t reserved_51; - uint32_t reserved_52; - uint32_t reserved_53; - uint32_t reserved_54; - uint32_t reserved_55; - uint32_t reserved_56; - uint32_t reserved_57; - uint32_t reserved_58; - uint32_t reserved_59; - uint32_t reserved_60; - uint32_t reserved_61; - uint32_t reserved_62; - uint32_t reserved_63; - uint32_t reserved_64; - uint32_t reserved_65; - uint32_t reserved_66; - uint32_t reserved_67; - uint32_t reserved_68; - uint32_t reserved_69; - uint32_t reserved_70; - uint32_t reserved_71; - uint32_t reserved_72; - uint32_t reserved_73; - uint32_t reserved_74; - uint32_t reserved_75; - uint32_t reserved_76; - uint32_t reserved_77; - uint32_t reserved_78; - uint32_t reserved_79; - uint32_t reserved_80; - uint32_t reserved_81; - uint32_t reserved_82; - uint32_t reserved_83; - uint32_t reserved_84; - uint32_t reserved_85; - uint32_t reserved_86; - uint32_t reserved_87; - uint32_t reserved_88; - uint32_t reserved_89; - uint32_t reserved_90; - uint32_t reserved_91; - uint32_t reserved_92; - uint32_t reserved_93; - uint32_t reserved_94; - uint32_t reserved_95; - uint32_t reserved_96; - uint32_t reserved_97; - uint32_t reserved_98; - uint32_t reserved_99; - uint32_t reserved_100; - uint32_t reserved_101; - uint32_t reserved_102; - uint32_t reserved_103; - uint32_t reserved_104; - uint32_t reserved_105; - uint32_t reserved_106; - uint32_t reserved_107; - uint32_t reserved_108; - uint32_t reserved_109; - uint32_t reserved_110; - uint32_t reserved_111; - uint32_t reserved_112; - uint32_t reserved_113; - uint32_t reserved_114; - uint32_t reserved_115; - uint32_t reserved_116; - uint32_t reserved_117; - uint32_t reserved_118; - uint32_t reserved_119; - uint32_t reserved_120; - uint32_t reserved_121; - uint32_t reserved_122; - uint32_t reserved_123; - uint32_t reserved_124; - uint32_t reserved_125; - uint32_t reserved_126; - uint32_t reserved_127; - uint32_t sdma_engine_id; - uint32_t sdma_queue_id; -}; - #endif diff --git a/drivers/gpu/drm/radeon/radeon_kfd.c b/drivers/gpu/drm/radeon/radeon_kfd.c index 13e8066aef70a0..ddbabab5d87524 100644 --- a/drivers/gpu/drm/radeon/radeon_kfd.c +++ b/drivers/gpu/drm/radeon/radeon_kfd.c @@ -30,6 +30,7 @@ #include "radeon_kfd.h" #include "radeon_ucode.h" #include +#include "cik_structs.h" #define CIK_PIPE_PER_MEC (4) From ff3d04a17117ed0825076c0e9edd0fe232daec9f Mon Sep 17 00:00:00 2001 From: Ben Goz Date: Sun, 4 Jan 2015 10:37:18 +0200 Subject: [PATCH 0007/3023] drm/amdkfd: Add new VI-specific queue properties This patch adds new fields to the queue_properties structure. The new fields are relevant only for queues running on AMD GPU VI architecture. The eop_ring_buffer_address and eop_ring_buffer_size describe an end-of-pipe queue which is assigned to the MQD. In CI, the EOP queue was per pipeline and in VI it is per queue. The ctx_save_restore_area_address and ctx_save_restore_area_size describe a memory area that is designated to allow the CP to do context save/restore in mid-wave state. This patch also modifies the set_queue_properties_from_user() (called from kfd_ioctl_create_queue()) to check and copy those new parameters. Signed-off-by: Ben Goz Signed-off-by: Oded Gabbay Reviewed-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 31 +++++++++++++++++++++++- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 5 ++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 4c0b1e42e405c6..b008fd67ace9ea 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -145,6 +145,8 @@ static long kfd_ioctl_get_version(struct file *filep, struct kfd_process *p, static int set_queue_properties_from_user(struct queue_properties *q_properties, struct kfd_ioctl_create_queue_args *args) { + void *tmp; + if (args->queue_percentage > KFD_MAX_QUEUE_PERCENTAGE) { pr_err("kfd: queue percentage must be between 0 to KFD_MAX_QUEUE_PERCENTAGE\n"); return -EINVAL; @@ -182,6 +184,20 @@ static int set_queue_properties_from_user(struct queue_properties *q_properties, return -EFAULT; } + tmp = (void *)(uintptr_t)args->eop_buffer_address; + if (tmp != NULL && + !access_ok(VERIFY_WRITE, tmp, sizeof(uint32_t))) { + pr_debug("kfd: can't access eop buffer"); + return -EFAULT; + } + + tmp = (void *)(uintptr_t)args->ctx_save_restore_address; + if (tmp != NULL && + !access_ok(VERIFY_WRITE, tmp, sizeof(uint32_t))) { + pr_debug("kfd: can't access ctx save restore buffer"); + return -EFAULT; + } + q_properties->is_interop = false; q_properties->queue_percent = args->queue_percentage; q_properties->priority = args->queue_priority; @@ -189,6 +205,11 @@ static int set_queue_properties_from_user(struct queue_properties *q_properties, q_properties->queue_size = args->ring_size; q_properties->read_ptr = (uint32_t *) args->read_pointer_address; q_properties->write_ptr = (uint32_t *) args->write_pointer_address; + q_properties->eop_ring_buffer_address = args->eop_buffer_address; + q_properties->eop_ring_buffer_size = args->eop_buffer_size; + q_properties->ctx_save_restore_area_address = + args->ctx_save_restore_address; + q_properties->ctx_save_restore_area_size = args->ctx_save_restore_size; if (args->queue_type == KFD_IOC_QUEUE_TYPE_COMPUTE || args->queue_type == KFD_IOC_QUEUE_TYPE_COMPUTE_AQL) q_properties->type = KFD_QUEUE_TYPE_COMPUTE; @@ -220,6 +241,11 @@ static int set_queue_properties_from_user(struct queue_properties *q_properties, pr_debug("Queue Format (%d)\n", q_properties->format); + pr_debug("Queue EOP (0x%llX)\n", q_properties->eop_ring_buffer_address); + + pr_debug("Queue CTX save arex (0x%llX)\n", + q_properties->ctx_save_restore_area_address); + return 0; } @@ -244,9 +270,12 @@ static long kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, if (err) return err; + pr_debug("kfd: looking for gpu id 0x%x\n", args.gpu_id); dev = kfd_device_by_id(args.gpu_id); - if (dev == NULL) + if (dev == NULL) { + pr_debug("kfd: gpu id 0x%x was not found\n", args.gpu_id); return -EINVAL; + } mutex_lock(&p->mutex); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index a79c21781d3b5b..3ba34b7bb122ca 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -299,6 +299,11 @@ struct queue_properties { uint32_t sdma_engine_id; uint32_t sdma_queue_id; uint32_t sdma_vm_addr; + /* Relevant only for VI */ + uint64_t eop_ring_buffer_address; + uint32_t eop_ring_buffer_size; + uint64_t ctx_save_restore_area_address; + uint32_t ctx_save_restore_area_size; }; /** From 85d258f9a7e827dc321d54d15ce1c6d5b0048a17 Mon Sep 17 00:00:00 2001 From: Ben Goz Date: Sun, 4 Jan 2015 10:36:30 +0200 Subject: [PATCH 0008/3023] drm/amdkfd: Make KFD_MQD_TYPE enum types H/W agnostic As the MQD types are common across all AMD GPUs/APUs, let's remove the CIK part from the name. Signed-off-by: Ben Goz Signed-off-by: Oded Gabbay Reviewed-by: Alex Deucher --- .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 14 +++++++------- drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c | 8 ++++---- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index fead2d7c087775..3d5f71a6e1479e 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -57,8 +57,8 @@ static inline enum KFD_MQD_TYPE get_mqd_type_from_queue_type(enum kfd_queue_type type) { if (type == KFD_QUEUE_TYPE_SDMA) - return KFD_MQD_TYPE_CIK_SDMA; - return KFD_MQD_TYPE_CIK_CP; + return KFD_MQD_TYPE_SDMA; + return KFD_MQD_TYPE_CP; } static inline unsigned int get_pipes_num(struct device_queue_manager *dqm) @@ -271,7 +271,7 @@ static int create_compute_queue_nocpsch(struct device_queue_manager *dqm, BUG_ON(!dqm || !q || !qpd); - mqd = dqm->get_mqd_manager(dqm, KFD_MQD_TYPE_CIK_COMPUTE); + mqd = dqm->get_mqd_manager(dqm, KFD_MQD_TYPE_COMPUTE); if (mqd == NULL) return -ENOMEM; @@ -302,13 +302,13 @@ static int destroy_queue_nocpsch(struct device_queue_manager *dqm, pr_debug("kfd: In Func %s\n", __func__); mutex_lock(&dqm->lock); - mqd = dqm->get_mqd_manager(dqm, KFD_MQD_TYPE_CIK_COMPUTE); + mqd = dqm->get_mqd_manager(dqm, KFD_MQD_TYPE_COMPUTE); if (mqd == NULL) { retval = -ENOMEM; goto out; } - mqd_sdma = dqm->get_mqd_manager(dqm, KFD_MQD_TYPE_CIK_SDMA); + mqd_sdma = dqm->get_mqd_manager(dqm, KFD_MQD_TYPE_SDMA); if (mqd_sdma == NULL) { mutex_unlock(&dqm->lock); return -ENOMEM; @@ -515,7 +515,7 @@ static int init_pipelines(struct device_queue_manager *dqm, memset(hpdptr, 0, CIK_HPD_EOP_BYTES * pipes_num); - mqd = dqm->get_mqd_manager(dqm, KFD_MQD_TYPE_CIK_COMPUTE); + mqd = dqm->get_mqd_manager(dqm, KFD_MQD_TYPE_COMPUTE); if (mqd == NULL) { kfd_gtt_sa_free(dqm->dev, dqm->pipeline_mem); return -ENOMEM; @@ -646,7 +646,7 @@ static int create_sdma_queue_nocpsch(struct device_queue_manager *dqm, struct mqd_manager *mqd; int retval; - mqd = dqm->get_mqd_manager(dqm, KFD_MQD_TYPE_CIK_SDMA); + mqd = dqm->get_mqd_manager(dqm, KFD_MQD_TYPE_SDMA); if (!mqd) return -ENOMEM; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c index 0fd8bb7c863e00..773c213f2f9ae6 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c @@ -57,7 +57,7 @@ static bool initialize(struct kernel_queue *kq, struct kfd_dev *dev, case KFD_QUEUE_TYPE_DIQ: case KFD_QUEUE_TYPE_HIQ: kq->mqd = dev->dqm->get_mqd_manager(dev->dqm, - KFD_MQD_TYPE_CIK_HIQ); + KFD_MQD_TYPE_HIQ); break; default: BUG(); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c index 155e33ceda9ac3..be989fb2284623 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c @@ -423,8 +423,8 @@ struct mqd_manager *mqd_manager_init(enum KFD_MQD_TYPE type, mqd->dev = dev; switch (type) { - case KFD_MQD_TYPE_CIK_CP: - case KFD_MQD_TYPE_CIK_COMPUTE: + case KFD_MQD_TYPE_CP: + case KFD_MQD_TYPE_COMPUTE: mqd->init_mqd = init_mqd; mqd->uninit_mqd = uninit_mqd; mqd->load_mqd = load_mqd; @@ -432,7 +432,7 @@ struct mqd_manager *mqd_manager_init(enum KFD_MQD_TYPE type, mqd->destroy_mqd = destroy_mqd; mqd->is_occupied = is_occupied; break; - case KFD_MQD_TYPE_CIK_HIQ: + case KFD_MQD_TYPE_HIQ: mqd->init_mqd = init_mqd_hiq; mqd->uninit_mqd = uninit_mqd; mqd->load_mqd = load_mqd; @@ -440,7 +440,7 @@ struct mqd_manager *mqd_manager_init(enum KFD_MQD_TYPE type, mqd->destroy_mqd = destroy_mqd; mqd->is_occupied = is_occupied; break; - case KFD_MQD_TYPE_CIK_SDMA: + case KFD_MQD_TYPE_SDMA: mqd->init_mqd = init_mqd_sdma; mqd->uninit_mqd = uninit_mqd_sdma; mqd->load_mqd = load_mqd_sdma; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 3ba34b7bb122ca..a4e0ddd5677812 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -356,10 +356,10 @@ struct queue { * Please read the kfd_mqd_manager.h description. */ enum KFD_MQD_TYPE { - KFD_MQD_TYPE_CIK_COMPUTE = 0, /* for no cp scheduling */ - KFD_MQD_TYPE_CIK_HIQ, /* for hiq */ - KFD_MQD_TYPE_CIK_CP, /* for cp queues and diq */ - KFD_MQD_TYPE_CIK_SDMA, /* for sdma queues */ + KFD_MQD_TYPE_COMPUTE = 0, /* for no cp scheduling */ + KFD_MQD_TYPE_HIQ, /* for hiq */ + KFD_MQD_TYPE_CP, /* for cp queues and diq */ + KFD_MQD_TYPE_SDMA, /* for sdma queues */ KFD_MQD_TYPE_MAX }; From 0da7558c690708259617417d3ddc5b5042f1cca4 Mon Sep 17 00:00:00 2001 From: Ben Goz Date: Thu, 1 Jan 2015 17:10:01 +0200 Subject: [PATCH 0009/3023] drm/amdkfd: Add asic property to kfd_device_info This patch adds a new property to kfd_device_info structure. That structure holds information that is H/W specific. The new property is called asic_family and its purpose is to distinguish between different asic families in amdkfd operations, mainly in QCM (queue control & management) This patch also adds a new enum, to select different ASICs. We set the current kfd_device_info instance as Kaveri and create a new instance which describes the new AMD APU, codenamed 'Carrizo'. Signed-off-by: Ben Goz Signed-off-by: Oded Gabbay Reviewed-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 10 +++++++++- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 6 ++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 994a9c1bdd0477..24b37ffad5c6bf 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -31,6 +31,14 @@ #define MQD_SIZE_ALIGNED 768 static const struct kfd_device_info kaveri_device_info = { + .asic_family = CHIP_KAVERI, + .max_pasid_bits = 16, + .ih_ring_entry_size = 4 * sizeof(uint32_t), + .mqd_size_aligned = MQD_SIZE_ALIGNED +}; + +static const struct kfd_device_info carrizo_device_info = { + .asic_family = CHIP_CARRIZO, .max_pasid_bits = 16, .ih_ring_entry_size = 4 * sizeof(uint32_t), .num_of_watch_points = 4, @@ -65,7 +73,7 @@ static const struct kfd_deviceid supported_devices[] = { { 0x1318, &kaveri_device_info }, /* Kaveri */ { 0x131B, &kaveri_device_info }, /* Kaveri */ { 0x131C, &kaveri_device_info }, /* Kaveri */ - { 0x131D, &kaveri_device_info }, /* Kaveri */ + { 0x131D, &kaveri_device_info } /* Kaveri */ }; static int kfd_gtt_sa_init(struct kfd_dev *kfd, unsigned int buf_size, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index a4e0ddd5677812..872a1da4c02eea 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -104,7 +104,13 @@ enum cache_policy { cache_policy_noncoherent }; +enum asic_family_type { + CHIP_KAVERI = 0, + CHIP_CARRIZO +}; + struct kfd_device_info { + unsigned int asic_family; unsigned int max_pasid_bits; size_t ih_ring_entry_size; uint8_t num_of_watch_points; From 4b8f589b052fe800e36f11eb2d29d4cf364bbed0 Mon Sep 17 00:00:00 2001 From: Ben Goz Date: Sun, 4 Jan 2015 11:24:25 +0200 Subject: [PATCH 0010/3023] drm/amdkfd: Change MQD manager to be H/W specific The MQDs for CI and VI are different. Therefore, the MQD manager module need to be H/W specific. This patch splits the current MQD manager into three files: - kfd_mqd_manager.c, which contains common functions and initializes the specific mqd manager module according to the H/W - kfd_mqd_manager_cik.c, which contains Kaveri specific functions. This is basically the old kfd_mqd_manager.c - kfd_mqd_manager_vi.c, which will contain VI specific functions. Currently it is not implemented except for returning NULL on initialization. Signed-off-by: Ben Goz Signed-off-by: Oded Gabbay Reviewed-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/Makefile | 1 + drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c | 434 +---------------- .../gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c | 454 ++++++++++++++++++ .../gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c | 33 ++ drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 4 + 5 files changed, 498 insertions(+), 428 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c create mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c diff --git a/drivers/gpu/drm/amd/amdkfd/Makefile b/drivers/gpu/drm/amd/amdkfd/Makefile index be6246de5091d0..bc6053f8b84340 100644 --- a/drivers/gpu/drm/amd/amdkfd/Makefile +++ b/drivers/gpu/drm/amd/amdkfd/Makefile @@ -7,6 +7,7 @@ ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/amd/include/ amdkfd-y := kfd_module.o kfd_device.o kfd_chardev.o kfd_topology.o \ kfd_pasid.o kfd_doorbell.o kfd_flat_memory.o \ kfd_process.o kfd_queue.o kfd_mqd_manager.o \ + kfd_mqd_manager_cik.o kfd_mqd_manager_vi.o \ kfd_kernel_queue.o kfd_packet_manager.o \ kfd_process_queue_manager.o kfd_device_queue_manager.o \ kfd_interrupt.o diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c index be989fb2284623..b1ef1368c3bbb0 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c @@ -21,439 +21,17 @@ * */ -#include -#include #include "kfd_priv.h" -#include "kfd_mqd_manager.h" -#include "cik_regs.h" -#include "cik_structs.h" - -inline void busy_wait(unsigned long ms) -{ - while (time_before(jiffies, ms)) - cpu_relax(); -} - -static inline struct cik_mqd *get_mqd(void *mqd) -{ - return (struct cik_mqd *)mqd; -} - -static int init_mqd(struct mqd_manager *mm, void **mqd, - struct kfd_mem_obj **mqd_mem_obj, uint64_t *gart_addr, - struct queue_properties *q) -{ - uint64_t addr; - struct cik_mqd *m; - int retval; - - BUG_ON(!mm || !q || !mqd); - - pr_debug("kfd: In func %s\n", __func__); - - retval = kfd_gtt_sa_allocate(mm->dev, sizeof(struct cik_mqd), - mqd_mem_obj); - - if (retval != 0) - return -ENOMEM; - - m = (struct cik_mqd *) (*mqd_mem_obj)->cpu_ptr; - addr = (*mqd_mem_obj)->gpu_addr; - - memset(m, 0, ALIGN(sizeof(struct cik_mqd), 256)); - - m->header = 0xC0310800; - m->compute_pipelinestat_enable = 1; - m->compute_static_thread_mgmt_se0 = 0xFFFFFFFF; - m->compute_static_thread_mgmt_se1 = 0xFFFFFFFF; - m->compute_static_thread_mgmt_se2 = 0xFFFFFFFF; - m->compute_static_thread_mgmt_se3 = 0xFFFFFFFF; - - /* - * Make sure to use the last queue state saved on mqd when the cp - * reassigns the queue, so when queue is switched on/off (e.g over - * subscription or quantum timeout) the context will be consistent - */ - m->cp_hqd_persistent_state = - DEFAULT_CP_HQD_PERSISTENT_STATE | PRELOAD_REQ; - - m->cp_mqd_control = MQD_CONTROL_PRIV_STATE_EN; - m->cp_mqd_base_addr_lo = lower_32_bits(addr); - m->cp_mqd_base_addr_hi = upper_32_bits(addr); - - m->cp_hqd_ib_control = DEFAULT_MIN_IB_AVAIL_SIZE | IB_ATC_EN; - /* Although WinKFD writes this, I suspect it should not be necessary */ - m->cp_hqd_ib_control = IB_ATC_EN | DEFAULT_MIN_IB_AVAIL_SIZE; - - m->cp_hqd_quantum = QUANTUM_EN | QUANTUM_SCALE_1MS | - QUANTUM_DURATION(10); - - /* - * Pipe Priority - * Identifies the pipe relative priority when this queue is connected - * to the pipeline. The pipe priority is against the GFX pipe and HP3D. - * In KFD we are using a fixed pipe priority set to CS_MEDIUM. - * 0 = CS_LOW (typically below GFX) - * 1 = CS_MEDIUM (typically between HP3D and GFX - * 2 = CS_HIGH (typically above HP3D) - */ - m->cp_hqd_pipe_priority = 1; - m->cp_hqd_queue_priority = 15; - - *mqd = m; - if (gart_addr != NULL) - *gart_addr = addr; - retval = mm->update_mqd(mm, m, q); - - return retval; -} - -static int init_mqd_sdma(struct mqd_manager *mm, void **mqd, - struct kfd_mem_obj **mqd_mem_obj, uint64_t *gart_addr, - struct queue_properties *q) -{ - int retval; - struct cik_sdma_rlc_registers *m; - - BUG_ON(!mm || !mqd || !mqd_mem_obj); - - retval = kfd_gtt_sa_allocate(mm->dev, - sizeof(struct cik_sdma_rlc_registers), - mqd_mem_obj); - - if (retval != 0) - return -ENOMEM; - - m = (struct cik_sdma_rlc_registers *) (*mqd_mem_obj)->cpu_ptr; - - memset(m, 0, sizeof(struct cik_sdma_rlc_registers)); - - *mqd = m; - if (gart_addr != NULL) - *gart_addr = (*mqd_mem_obj)->gpu_addr; - - retval = mm->update_mqd(mm, m, q); - - return retval; -} - -static void uninit_mqd(struct mqd_manager *mm, void *mqd, - struct kfd_mem_obj *mqd_mem_obj) -{ - BUG_ON(!mm || !mqd); - kfd_gtt_sa_free(mm->dev, mqd_mem_obj); -} - -static void uninit_mqd_sdma(struct mqd_manager *mm, void *mqd, - struct kfd_mem_obj *mqd_mem_obj) -{ - BUG_ON(!mm || !mqd); - kfd_gtt_sa_free(mm->dev, mqd_mem_obj); -} - -static int load_mqd(struct mqd_manager *mm, void *mqd, uint32_t pipe_id, - uint32_t queue_id, uint32_t __user *wptr) -{ - return kfd2kgd->hqd_load(mm->dev->kgd, mqd, pipe_id, queue_id, wptr); -} - -static int load_mqd_sdma(struct mqd_manager *mm, void *mqd, - uint32_t pipe_id, uint32_t queue_id, - uint32_t __user *wptr) -{ - return kfd2kgd->hqd_sdma_load(mm->dev->kgd, mqd); -} - -static int update_mqd(struct mqd_manager *mm, void *mqd, - struct queue_properties *q) -{ - struct cik_mqd *m; - - BUG_ON(!mm || !q || !mqd); - - pr_debug("kfd: In func %s\n", __func__); - - m = get_mqd(mqd); - m->cp_hqd_pq_control = DEFAULT_RPTR_BLOCK_SIZE | - DEFAULT_MIN_AVAIL_SIZE | PQ_ATC_EN; - - /* - * Calculating queue size which is log base 2 of actual queue size -1 - * dwords and another -1 for ffs - */ - m->cp_hqd_pq_control |= ffs(q->queue_size / sizeof(unsigned int)) - - 1 - 1; - m->cp_hqd_pq_base_lo = lower_32_bits((uint64_t)q->queue_address >> 8); - m->cp_hqd_pq_base_hi = upper_32_bits((uint64_t)q->queue_address >> 8); - m->cp_hqd_pq_rptr_report_addr_lo = lower_32_bits((uint64_t)q->read_ptr); - m->cp_hqd_pq_rptr_report_addr_hi = upper_32_bits((uint64_t)q->read_ptr); - m->cp_hqd_pq_doorbell_control = DOORBELL_EN | - DOORBELL_OFFSET(q->doorbell_off); - - m->cp_hqd_vmid = q->vmid; - - if (q->format == KFD_QUEUE_FORMAT_AQL) { - m->cp_hqd_iq_rptr = AQL_ENABLE; - m->cp_hqd_pq_control |= NO_UPDATE_RPTR; - } - - m->cp_hqd_active = 0; - q->is_active = false; - if (q->queue_size > 0 && - q->queue_address != 0 && - q->queue_percent > 0) { - m->cp_hqd_active = 1; - q->is_active = true; - } - - return 0; -} - -static int update_mqd_sdma(struct mqd_manager *mm, void *mqd, - struct queue_properties *q) -{ - struct cik_sdma_rlc_registers *m; - - BUG_ON(!mm || !mqd || !q); - - m = get_sdma_mqd(mqd); - m->sdma_rlc_rb_cntl = - SDMA_RB_SIZE((ffs(q->queue_size / sizeof(unsigned int)))) | - SDMA_RB_VMID(q->vmid) | - SDMA_RPTR_WRITEBACK_ENABLE | - SDMA_RPTR_WRITEBACK_TIMER(6); - - m->sdma_rlc_rb_base = lower_32_bits(q->queue_address >> 8); - m->sdma_rlc_rb_base_hi = upper_32_bits(q->queue_address >> 8); - m->sdma_rlc_rb_rptr_addr_lo = lower_32_bits((uint64_t)q->read_ptr); - m->sdma_rlc_rb_rptr_addr_hi = upper_32_bits((uint64_t)q->read_ptr); - m->sdma_rlc_doorbell = SDMA_OFFSET(q->doorbell_off) | SDMA_DB_ENABLE; - m->sdma_rlc_virtual_addr = q->sdma_vm_addr; - - m->sdma_engine_id = q->sdma_engine_id; - m->sdma_queue_id = q->sdma_queue_id; - - q->is_active = false; - if (q->queue_size > 0 && - q->queue_address != 0 && - q->queue_percent > 0) { - m->sdma_rlc_rb_cntl |= SDMA_RB_ENABLE; - q->is_active = true; - } - - return 0; -} - -static int destroy_mqd(struct mqd_manager *mm, void *mqd, - enum kfd_preempt_type type, - unsigned int timeout, uint32_t pipe_id, - uint32_t queue_id) -{ - return kfd2kgd->hqd_destroy(mm->dev->kgd, type, timeout, - pipe_id, queue_id); -} - -/* - * preempt type here is ignored because there is only one way - * to preempt sdma queue - */ -static int destroy_mqd_sdma(struct mqd_manager *mm, void *mqd, - enum kfd_preempt_type type, - unsigned int timeout, uint32_t pipe_id, - uint32_t queue_id) -{ - return kfd2kgd->hqd_sdma_destroy(mm->dev->kgd, mqd, timeout); -} - -static bool is_occupied(struct mqd_manager *mm, void *mqd, - uint64_t queue_address, uint32_t pipe_id, - uint32_t queue_id) -{ - - return kfd2kgd->hqd_is_occupies(mm->dev->kgd, queue_address, - pipe_id, queue_id); - -} - -static bool is_occupied_sdma(struct mqd_manager *mm, void *mqd, - uint64_t queue_address, uint32_t pipe_id, - uint32_t queue_id) -{ - return kfd2kgd->hqd_sdma_is_occupied(mm->dev->kgd, mqd); -} - -/* - * HIQ MQD Implementation, concrete implementation for HIQ MQD implementation. - * The HIQ queue in Kaveri is using the same MQD structure as all the user mode - * queues but with different initial values. - */ - -static int init_mqd_hiq(struct mqd_manager *mm, void **mqd, - struct kfd_mem_obj **mqd_mem_obj, uint64_t *gart_addr, - struct queue_properties *q) -{ - uint64_t addr; - struct cik_mqd *m; - int retval; - - BUG_ON(!mm || !q || !mqd || !mqd_mem_obj); - - pr_debug("kfd: In func %s\n", __func__); - - retval = kfd_gtt_sa_allocate(mm->dev, sizeof(struct cik_mqd), - mqd_mem_obj); - - if (retval != 0) - return -ENOMEM; - - m = (struct cik_mqd *) (*mqd_mem_obj)->cpu_ptr; - addr = (*mqd_mem_obj)->gpu_addr; - - memset(m, 0, ALIGN(sizeof(struct cik_mqd), 256)); - - m->header = 0xC0310800; - m->compute_pipelinestat_enable = 1; - m->compute_static_thread_mgmt_se0 = 0xFFFFFFFF; - m->compute_static_thread_mgmt_se1 = 0xFFFFFFFF; - m->compute_static_thread_mgmt_se2 = 0xFFFFFFFF; - m->compute_static_thread_mgmt_se3 = 0xFFFFFFFF; - - m->cp_hqd_persistent_state = DEFAULT_CP_HQD_PERSISTENT_STATE | - PRELOAD_REQ; - m->cp_hqd_quantum = QUANTUM_EN | QUANTUM_SCALE_1MS | - QUANTUM_DURATION(10); - - m->cp_mqd_control = MQD_CONTROL_PRIV_STATE_EN; - m->cp_mqd_base_addr_lo = lower_32_bits(addr); - m->cp_mqd_base_addr_hi = upper_32_bits(addr); - - m->cp_hqd_ib_control = DEFAULT_MIN_IB_AVAIL_SIZE; - - /* - * Pipe Priority - * Identifies the pipe relative priority when this queue is connected - * to the pipeline. The pipe priority is against the GFX pipe and HP3D. - * In KFD we are using a fixed pipe priority set to CS_MEDIUM. - * 0 = CS_LOW (typically below GFX) - * 1 = CS_MEDIUM (typically between HP3D and GFX - * 2 = CS_HIGH (typically above HP3D) - */ - m->cp_hqd_pipe_priority = 1; - m->cp_hqd_queue_priority = 15; - - *mqd = m; - if (gart_addr) - *gart_addr = addr; - retval = mm->update_mqd(mm, m, q); - - return retval; -} - -static int update_mqd_hiq(struct mqd_manager *mm, void *mqd, - struct queue_properties *q) -{ - struct cik_mqd *m; - - BUG_ON(!mm || !q || !mqd); - - pr_debug("kfd: In func %s\n", __func__); - - m = get_mqd(mqd); - m->cp_hqd_pq_control = DEFAULT_RPTR_BLOCK_SIZE | - DEFAULT_MIN_AVAIL_SIZE | - PRIV_STATE | - KMD_QUEUE; - - /* - * Calculating queue size which is log base 2 of actual queue - * size -1 dwords - */ - m->cp_hqd_pq_control |= ffs(q->queue_size / sizeof(unsigned int)) - - 1 - 1; - m->cp_hqd_pq_base_lo = lower_32_bits((uint64_t)q->queue_address >> 8); - m->cp_hqd_pq_base_hi = upper_32_bits((uint64_t)q->queue_address >> 8); - m->cp_hqd_pq_rptr_report_addr_lo = lower_32_bits((uint64_t)q->read_ptr); - m->cp_hqd_pq_rptr_report_addr_hi = upper_32_bits((uint64_t)q->read_ptr); - m->cp_hqd_pq_doorbell_control = DOORBELL_EN | - DOORBELL_OFFSET(q->doorbell_off); - - m->cp_hqd_vmid = q->vmid; - - m->cp_hqd_active = 0; - q->is_active = false; - if (q->queue_size > 0 && - q->queue_address != 0 && - q->queue_percent > 0) { - m->cp_hqd_active = 1; - q->is_active = true; - } - - return 0; -} - -/* - * SDMA MQD Implementation - */ - -struct cik_sdma_rlc_registers *get_sdma_mqd(void *mqd) -{ - struct cik_sdma_rlc_registers *m; - - BUG_ON(!mqd); - - m = (struct cik_sdma_rlc_registers *)mqd; - - return m; -} struct mqd_manager *mqd_manager_init(enum KFD_MQD_TYPE type, struct kfd_dev *dev) { - struct mqd_manager *mqd; - - BUG_ON(!dev); - BUG_ON(type >= KFD_MQD_TYPE_MAX); - - pr_debug("kfd: In func %s\n", __func__); - - mqd = kzalloc(sizeof(struct mqd_manager), GFP_KERNEL); - if (!mqd) - return NULL; - - mqd->dev = dev; - - switch (type) { - case KFD_MQD_TYPE_CP: - case KFD_MQD_TYPE_COMPUTE: - mqd->init_mqd = init_mqd; - mqd->uninit_mqd = uninit_mqd; - mqd->load_mqd = load_mqd; - mqd->update_mqd = update_mqd; - mqd->destroy_mqd = destroy_mqd; - mqd->is_occupied = is_occupied; - break; - case KFD_MQD_TYPE_HIQ: - mqd->init_mqd = init_mqd_hiq; - mqd->uninit_mqd = uninit_mqd; - mqd->load_mqd = load_mqd; - mqd->update_mqd = update_mqd_hiq; - mqd->destroy_mqd = destroy_mqd; - mqd->is_occupied = is_occupied; - break; - case KFD_MQD_TYPE_SDMA: - mqd->init_mqd = init_mqd_sdma; - mqd->uninit_mqd = uninit_mqd_sdma; - mqd->load_mqd = load_mqd_sdma; - mqd->update_mqd = update_mqd_sdma; - mqd->destroy_mqd = destroy_mqd_sdma; - mqd->is_occupied = is_occupied_sdma; - break; - default: - kfree(mqd); - return NULL; + switch (dev->device_info->asic_family) { + case CHIP_KAVERI: + return mqd_manager_init_cik(type, dev); + case CHIP_CARRIZO: + return mqd_manager_init_vi(type, dev); } - return mqd; + return NULL; } - -/* SDMA queues should be implemented here when the cp will supports them */ diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c new file mode 100644 index 00000000000000..7b28f6e74c321e --- /dev/null +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c @@ -0,0 +1,454 @@ +/* + * Copyright 2014 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include +#include +#include "kfd_priv.h" +#include "kfd_mqd_manager.h" +#include "cik_regs.h" +#include "cik_structs.h" + +inline void busy_wait(unsigned long ms) +{ + while (time_before(jiffies, ms)) + cpu_relax(); +} + +static inline struct cik_mqd *get_mqd(void *mqd) +{ + return (struct cik_mqd *)mqd; +} + +static int init_mqd(struct mqd_manager *mm, void **mqd, + struct kfd_mem_obj **mqd_mem_obj, uint64_t *gart_addr, + struct queue_properties *q) +{ + uint64_t addr; + struct cik_mqd *m; + int retval; + + BUG_ON(!mm || !q || !mqd); + + pr_debug("kfd: In func %s\n", __func__); + + retval = kfd_gtt_sa_allocate(mm->dev, sizeof(struct cik_mqd), + mqd_mem_obj); + + if (retval != 0) + return -ENOMEM; + + m = (struct cik_mqd *) (*mqd_mem_obj)->cpu_ptr; + addr = (*mqd_mem_obj)->gpu_addr; + + memset(m, 0, ALIGN(sizeof(struct cik_mqd), 256)); + + m->header = 0xC0310800; + m->compute_pipelinestat_enable = 1; + m->compute_static_thread_mgmt_se0 = 0xFFFFFFFF; + m->compute_static_thread_mgmt_se1 = 0xFFFFFFFF; + m->compute_static_thread_mgmt_se2 = 0xFFFFFFFF; + m->compute_static_thread_mgmt_se3 = 0xFFFFFFFF; + + /* + * Make sure to use the last queue state saved on mqd when the cp + * reassigns the queue, so when queue is switched on/off (e.g over + * subscription or quantum timeout) the context will be consistent + */ + m->cp_hqd_persistent_state = + DEFAULT_CP_HQD_PERSISTENT_STATE | PRELOAD_REQ; + + m->cp_mqd_control = MQD_CONTROL_PRIV_STATE_EN; + m->cp_mqd_base_addr_lo = lower_32_bits(addr); + m->cp_mqd_base_addr_hi = upper_32_bits(addr); + + m->cp_hqd_ib_control = DEFAULT_MIN_IB_AVAIL_SIZE | IB_ATC_EN; + /* Although WinKFD writes this, I suspect it should not be necessary */ + m->cp_hqd_ib_control = IB_ATC_EN | DEFAULT_MIN_IB_AVAIL_SIZE; + + m->cp_hqd_quantum = QUANTUM_EN | QUANTUM_SCALE_1MS | + QUANTUM_DURATION(10); + + /* + * Pipe Priority + * Identifies the pipe relative priority when this queue is connected + * to the pipeline. The pipe priority is against the GFX pipe and HP3D. + * In KFD we are using a fixed pipe priority set to CS_MEDIUM. + * 0 = CS_LOW (typically below GFX) + * 1 = CS_MEDIUM (typically between HP3D and GFX + * 2 = CS_HIGH (typically above HP3D) + */ + m->cp_hqd_pipe_priority = 1; + m->cp_hqd_queue_priority = 15; + + *mqd = m; + if (gart_addr != NULL) + *gart_addr = addr; + retval = mm->update_mqd(mm, m, q); + + return retval; +} + +static int init_mqd_sdma(struct mqd_manager *mm, void **mqd, + struct kfd_mem_obj **mqd_mem_obj, uint64_t *gart_addr, + struct queue_properties *q) +{ + int retval; + struct cik_sdma_rlc_registers *m; + + BUG_ON(!mm || !mqd || !mqd_mem_obj); + + retval = kfd_gtt_sa_allocate(mm->dev, + sizeof(struct cik_sdma_rlc_registers), + mqd_mem_obj); + + if (retval != 0) + return -ENOMEM; + + m = (struct cik_sdma_rlc_registers *) (*mqd_mem_obj)->cpu_ptr; + + memset(m, 0, sizeof(struct cik_sdma_rlc_registers)); + + *mqd = m; + if (gart_addr != NULL) + *gart_addr = (*mqd_mem_obj)->gpu_addr; + + retval = mm->update_mqd(mm, m, q); + + return retval; +} + +static void uninit_mqd(struct mqd_manager *mm, void *mqd, + struct kfd_mem_obj *mqd_mem_obj) +{ + BUG_ON(!mm || !mqd); + kfd_gtt_sa_free(mm->dev, mqd_mem_obj); +} + +static void uninit_mqd_sdma(struct mqd_manager *mm, void *mqd, + struct kfd_mem_obj *mqd_mem_obj) +{ + BUG_ON(!mm || !mqd); + kfd_gtt_sa_free(mm->dev, mqd_mem_obj); +} + +static int load_mqd(struct mqd_manager *mm, void *mqd, uint32_t pipe_id, + uint32_t queue_id, uint32_t __user *wptr) +{ + return kfd2kgd->hqd_load(mm->dev->kgd, mqd, pipe_id, queue_id, wptr); +} + +static int load_mqd_sdma(struct mqd_manager *mm, void *mqd, + uint32_t pipe_id, uint32_t queue_id, + uint32_t __user *wptr) +{ + return kfd2kgd->hqd_sdma_load(mm->dev->kgd, mqd); +} + +static int update_mqd(struct mqd_manager *mm, void *mqd, + struct queue_properties *q) +{ + struct cik_mqd *m; + + BUG_ON(!mm || !q || !mqd); + + pr_debug("kfd: In func %s\n", __func__); + + m = get_mqd(mqd); + m->cp_hqd_pq_control = DEFAULT_RPTR_BLOCK_SIZE | + DEFAULT_MIN_AVAIL_SIZE | PQ_ATC_EN; + + /* + * Calculating queue size which is log base 2 of actual queue size -1 + * dwords and another -1 for ffs + */ + m->cp_hqd_pq_control |= ffs(q->queue_size / sizeof(unsigned int)) + - 1 - 1; + m->cp_hqd_pq_base_lo = lower_32_bits((uint64_t)q->queue_address >> 8); + m->cp_hqd_pq_base_hi = upper_32_bits((uint64_t)q->queue_address >> 8); + m->cp_hqd_pq_rptr_report_addr_lo = lower_32_bits((uint64_t)q->read_ptr); + m->cp_hqd_pq_rptr_report_addr_hi = upper_32_bits((uint64_t)q->read_ptr); + m->cp_hqd_pq_doorbell_control = DOORBELL_EN | + DOORBELL_OFFSET(q->doorbell_off); + + m->cp_hqd_vmid = q->vmid; + + if (q->format == KFD_QUEUE_FORMAT_AQL) { + m->cp_hqd_iq_rptr = AQL_ENABLE; + m->cp_hqd_pq_control |= NO_UPDATE_RPTR; + } + + m->cp_hqd_active = 0; + q->is_active = false; + if (q->queue_size > 0 && + q->queue_address != 0 && + q->queue_percent > 0) { + m->cp_hqd_active = 1; + q->is_active = true; + } + + return 0; +} + +static int update_mqd_sdma(struct mqd_manager *mm, void *mqd, + struct queue_properties *q) +{ + struct cik_sdma_rlc_registers *m; + + BUG_ON(!mm || !mqd || !q); + + m = get_sdma_mqd(mqd); + m->sdma_rlc_rb_cntl = + SDMA_RB_SIZE((ffs(q->queue_size / sizeof(unsigned int)))) | + SDMA_RB_VMID(q->vmid) | + SDMA_RPTR_WRITEBACK_ENABLE | + SDMA_RPTR_WRITEBACK_TIMER(6); + + m->sdma_rlc_rb_base = lower_32_bits(q->queue_address >> 8); + m->sdma_rlc_rb_base_hi = upper_32_bits(q->queue_address >> 8); + m->sdma_rlc_rb_rptr_addr_lo = lower_32_bits((uint64_t)q->read_ptr); + m->sdma_rlc_rb_rptr_addr_hi = upper_32_bits((uint64_t)q->read_ptr); + m->sdma_rlc_doorbell = SDMA_OFFSET(q->doorbell_off) | SDMA_DB_ENABLE; + m->sdma_rlc_virtual_addr = q->sdma_vm_addr; + + m->sdma_engine_id = q->sdma_engine_id; + m->sdma_queue_id = q->sdma_queue_id; + + q->is_active = false; + if (q->queue_size > 0 && + q->queue_address != 0 && + q->queue_percent > 0) { + m->sdma_rlc_rb_cntl |= SDMA_RB_ENABLE; + q->is_active = true; + } + + return 0; +} + +static int destroy_mqd(struct mqd_manager *mm, void *mqd, + enum kfd_preempt_type type, + unsigned int timeout, uint32_t pipe_id, + uint32_t queue_id) +{ + return kfd2kgd->hqd_destroy(mm->dev->kgd, type, timeout, + pipe_id, queue_id); +} + +/* + * preempt type here is ignored because there is only one way + * to preempt sdma queue + */ +static int destroy_mqd_sdma(struct mqd_manager *mm, void *mqd, + enum kfd_preempt_type type, + unsigned int timeout, uint32_t pipe_id, + uint32_t queue_id) +{ + return kfd2kgd->hqd_sdma_destroy(mm->dev->kgd, mqd, timeout); +} + +static bool is_occupied(struct mqd_manager *mm, void *mqd, + uint64_t queue_address, uint32_t pipe_id, + uint32_t queue_id) +{ + + return kfd2kgd->hqd_is_occupies(mm->dev->kgd, queue_address, + pipe_id, queue_id); + +} + +static bool is_occupied_sdma(struct mqd_manager *mm, void *mqd, + uint64_t queue_address, uint32_t pipe_id, + uint32_t queue_id) +{ + return kfd2kgd->hqd_sdma_is_occupied(mm->dev->kgd, mqd); +} + +/* + * HIQ MQD Implementation, concrete implementation for HIQ MQD implementation. + * The HIQ queue in Kaveri is using the same MQD structure as all the user mode + * queues but with different initial values. + */ + +static int init_mqd_hiq(struct mqd_manager *mm, void **mqd, + struct kfd_mem_obj **mqd_mem_obj, uint64_t *gart_addr, + struct queue_properties *q) +{ + uint64_t addr; + struct cik_mqd *m; + int retval; + + BUG_ON(!mm || !q || !mqd || !mqd_mem_obj); + + pr_debug("kfd: In func %s\n", __func__); + + retval = kfd_gtt_sa_allocate(mm->dev, sizeof(struct cik_mqd), + mqd_mem_obj); + + if (retval != 0) + return -ENOMEM; + + m = (struct cik_mqd *) (*mqd_mem_obj)->cpu_ptr; + addr = (*mqd_mem_obj)->gpu_addr; + + memset(m, 0, ALIGN(sizeof(struct cik_mqd), 256)); + + m->header = 0xC0310800; + m->compute_pipelinestat_enable = 1; + m->compute_static_thread_mgmt_se0 = 0xFFFFFFFF; + m->compute_static_thread_mgmt_se1 = 0xFFFFFFFF; + m->compute_static_thread_mgmt_se2 = 0xFFFFFFFF; + m->compute_static_thread_mgmt_se3 = 0xFFFFFFFF; + + m->cp_hqd_persistent_state = DEFAULT_CP_HQD_PERSISTENT_STATE | + PRELOAD_REQ; + m->cp_hqd_quantum = QUANTUM_EN | QUANTUM_SCALE_1MS | + QUANTUM_DURATION(10); + + m->cp_mqd_control = MQD_CONTROL_PRIV_STATE_EN; + m->cp_mqd_base_addr_lo = lower_32_bits(addr); + m->cp_mqd_base_addr_hi = upper_32_bits(addr); + + m->cp_hqd_ib_control = DEFAULT_MIN_IB_AVAIL_SIZE; + + /* + * Pipe Priority + * Identifies the pipe relative priority when this queue is connected + * to the pipeline. The pipe priority is against the GFX pipe and HP3D. + * In KFD we are using a fixed pipe priority set to CS_MEDIUM. + * 0 = CS_LOW (typically below GFX) + * 1 = CS_MEDIUM (typically between HP3D and GFX + * 2 = CS_HIGH (typically above HP3D) + */ + m->cp_hqd_pipe_priority = 1; + m->cp_hqd_queue_priority = 15; + + *mqd = m; + if (gart_addr) + *gart_addr = addr; + retval = mm->update_mqd(mm, m, q); + + return retval; +} + +static int update_mqd_hiq(struct mqd_manager *mm, void *mqd, + struct queue_properties *q) +{ + struct cik_mqd *m; + + BUG_ON(!mm || !q || !mqd); + + pr_debug("kfd: In func %s\n", __func__); + + m = get_mqd(mqd); + m->cp_hqd_pq_control = DEFAULT_RPTR_BLOCK_SIZE | + DEFAULT_MIN_AVAIL_SIZE | + PRIV_STATE | + KMD_QUEUE; + + /* + * Calculating queue size which is log base 2 of actual queue + * size -1 dwords + */ + m->cp_hqd_pq_control |= ffs(q->queue_size / sizeof(unsigned int)) + - 1 - 1; + m->cp_hqd_pq_base_lo = lower_32_bits((uint64_t)q->queue_address >> 8); + m->cp_hqd_pq_base_hi = upper_32_bits((uint64_t)q->queue_address >> 8); + m->cp_hqd_pq_rptr_report_addr_lo = lower_32_bits((uint64_t)q->read_ptr); + m->cp_hqd_pq_rptr_report_addr_hi = upper_32_bits((uint64_t)q->read_ptr); + m->cp_hqd_pq_doorbell_control = DOORBELL_EN | + DOORBELL_OFFSET(q->doorbell_off); + + m->cp_hqd_vmid = q->vmid; + + m->cp_hqd_active = 0; + q->is_active = false; + if (q->queue_size > 0 && + q->queue_address != 0 && + q->queue_percent > 0) { + m->cp_hqd_active = 1; + q->is_active = true; + } + + return 0; +} + +struct cik_sdma_rlc_registers *get_sdma_mqd(void *mqd) +{ + struct cik_sdma_rlc_registers *m; + + BUG_ON(!mqd); + + m = (struct cik_sdma_rlc_registers *)mqd; + + return m; +} + +struct mqd_manager *mqd_manager_init_cik(enum KFD_MQD_TYPE type, + struct kfd_dev *dev) +{ + struct mqd_manager *mqd; + + BUG_ON(!dev); + BUG_ON(type >= KFD_MQD_TYPE_MAX); + + pr_debug("kfd: In func %s\n", __func__); + + mqd = kzalloc(sizeof(struct mqd_manager), GFP_KERNEL); + if (!mqd) + return NULL; + + mqd->dev = dev; + + switch (type) { + case KFD_MQD_TYPE_CP: + case KFD_MQD_TYPE_COMPUTE: + mqd->init_mqd = init_mqd; + mqd->uninit_mqd = uninit_mqd; + mqd->load_mqd = load_mqd; + mqd->update_mqd = update_mqd; + mqd->destroy_mqd = destroy_mqd; + mqd->is_occupied = is_occupied; + break; + case KFD_MQD_TYPE_HIQ: + mqd->init_mqd = init_mqd_hiq; + mqd->uninit_mqd = uninit_mqd; + mqd->load_mqd = load_mqd; + mqd->update_mqd = update_mqd_hiq; + mqd->destroy_mqd = destroy_mqd; + mqd->is_occupied = is_occupied; + break; + case KFD_MQD_TYPE_SDMA: + mqd->init_mqd = init_mqd_sdma; + mqd->uninit_mqd = uninit_mqd_sdma; + mqd->load_mqd = load_mqd_sdma; + mqd->update_mqd = update_mqd_sdma; + mqd->destroy_mqd = destroy_mqd_sdma; + mqd->is_occupied = is_occupied_sdma; + break; + default: + kfree(mqd); + return NULL; + } + + return mqd; +} + diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c new file mode 100644 index 00000000000000..b3a7e3ba1e380c --- /dev/null +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c @@ -0,0 +1,33 @@ +/* + * Copyright 2014 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include +#include "kfd_priv.h" +#include "kfd_mqd_manager.h" + +struct mqd_manager *mqd_manager_init_vi(enum KFD_MQD_TYPE type, + struct kfd_dev *dev) +{ + pr_warn("amdkfd: VI MQD is not currently supported\n"); + return NULL; +} diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 872a1da4c02eea..bfcf45f30b7693 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -573,6 +573,10 @@ void print_queue(struct queue *q); struct mqd_manager *mqd_manager_init(enum KFD_MQD_TYPE type, struct kfd_dev *dev); +struct mqd_manager *mqd_manager_init_cik(enum KFD_MQD_TYPE type, + struct kfd_dev *dev); +struct mqd_manager *mqd_manager_init_vi(enum KFD_MQD_TYPE type, + struct kfd_dev *dev); struct device_queue_manager *device_queue_manager_init(struct kfd_dev *dev); void device_queue_manager_uninit(struct device_queue_manager *dqm); struct kernel_queue *kernel_queue_init(struct kfd_dev *dev, From 04df25d123945a2261a7755673962257241b1394 Mon Sep 17 00:00:00 2001 From: Oded Gabbay Date: Mon, 5 Jan 2015 18:15:45 +0200 Subject: [PATCH 0011/3023] MAINTAINERS: Update amdkfd files Add two files under amdkfd section. Signed-off-by: Oded Gabbay Reviewed-by: Alex Deucher --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index ddb9ac8d32b3ed..23fa31dc939036 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -624,6 +624,8 @@ L: dri-devel@lists.freedesktop.org T: git git://people.freedesktop.org/~gabbayo/linux.git S: Supported F: drivers/gpu/drm/amd/amdkfd/ +F: drivers/gpu/drm/amd/include/cik_structs.h +F: drivers/gpu/drm/amd/include/kgd_kfd_interface.h F: drivers/gpu/drm/radeon/radeon_kfd.c F: drivers/gpu/drm/radeon/radeon_kfd.h F: include/uapi/linux/kfd_ioctl.h From c2e1b3a496332b90d073bc9dddd3324d660fca24 Mon Sep 17 00:00:00 2001 From: Ben Goz Date: Mon, 18 Aug 2014 14:55:59 +0300 Subject: [PATCH 0012/3023] drm/amdkfd: Fix logic of destroy_queue_nocpsch() This patch rewrites destroy_queue_nocpsch() as the current logic that is implemented in the function is completely flawed. This function is used only in non-HWS mode. Signed-off-by: Ben Goz Signed-off-by: Oded Gabbay Acked-by: Alex Deucher --- .../drm/amd/amdkfd/kfd_device_queue_manager.c | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 3d5f71a6e1479e..c83f011534401e 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -294,7 +294,8 @@ static int destroy_queue_nocpsch(struct device_queue_manager *dqm, struct queue *q) { int retval; - struct mqd_manager *mqd, *mqd_sdma; + struct mqd_manager *mqd; + BUG_ON(!dqm || !q || !q->mqd || !qpd); retval = 0; @@ -302,33 +303,32 @@ static int destroy_queue_nocpsch(struct device_queue_manager *dqm, pr_debug("kfd: In Func %s\n", __func__); mutex_lock(&dqm->lock); - mqd = dqm->get_mqd_manager(dqm, KFD_MQD_TYPE_COMPUTE); - if (mqd == NULL) { - retval = -ENOMEM; - goto out; - } - mqd_sdma = dqm->get_mqd_manager(dqm, KFD_MQD_TYPE_SDMA); - if (mqd_sdma == NULL) { - mutex_unlock(&dqm->lock); - return -ENOMEM; + if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE) { + mqd = dqm->get_mqd_manager(dqm, KFD_MQD_TYPE_COMPUTE); + if (mqd == NULL) { + retval = -ENOMEM; + goto out; + } + deallocate_hqd(dqm, q); + } else if (q->properties.type == KFD_QUEUE_TYPE_SDMA) { + mqd = dqm->get_mqd_manager(dqm, KFD_MQD_TYPE_SDMA); + if (mqd == NULL) { + retval = -ENOMEM; + goto out; + } + dqm->sdma_queue_count--; + deallocate_sdma_queue(dqm, q->sdma_id); } retval = mqd->destroy_mqd(mqd, q->mqd, - KFD_PREEMPT_TYPE_WAVEFRONT, + KFD_PREEMPT_TYPE_WAVEFRONT_RESET, QUEUE_PREEMPT_DEFAULT_TIMEOUT_MS, q->pipe, q->queue); if (retval != 0) goto out; - if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE) - deallocate_hqd(dqm, q); - else if (q->properties.type == KFD_QUEUE_TYPE_SDMA) { - dqm->sdma_queue_count--; - deallocate_sdma_queue(dqm, q->sdma_id); - } - mqd->uninit_mqd(mqd, q->mqd, q->mqd_mem_obj); list_del(&q->list); From 995863cc8e3e2ab08a8ff18dc937c7a32a7479e0 Mon Sep 17 00:00:00 2001 From: Kuppuswamy Sathyanarayanan Date: Tue, 16 Sep 2014 04:54:00 +0100 Subject: [PATCH 0013/3023] iio: jsa1212: Add JSA1212 proximity/ALS sensor This patch adds a new driver for solteam opto JSA1212 proximity and ambient light sensor. Basic details of the chip can be found here. http://www.solteamopto.com.tw/detail.php?ms=3&po_unit=2&pt_unit=29&p_unit=120 Signed-off-by: Kuppuswamy Sathyanarayanan Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/light/Kconfig | 10 + drivers/iio/light/Makefile | 1 + drivers/iio/light/jsa1212.c | 471 ++++++++++++++++++++++++++++++++++++ 3 files changed, 482 insertions(+) create mode 100644 drivers/iio/light/jsa1212.c diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 5bea821adcaeae..2e2ba12f55fcb6 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -109,6 +109,16 @@ config HID_SENSOR_PROX To compile this driver as a module, choose M here: the module will be called hid-sensor-prox. +config JSA1212 + tristate "JSA1212 ALS and proximity sensor driver" + depends on I2C + help + Say Y here if you want to build a IIO driver for JSA1212 + proximity & ALS sensor device. + + To compile this driver as a module, choose M here: + the module will be called jsa1212. + config SENSORS_LM3533 tristate "LM3533 ambient light sensor" depends on MFD_LM3533 diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index 47877a36cc1286..74656c19a89910 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_GP2AP020A00F) += gp2ap020a00f.o obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o obj-$(CONFIG_HID_SENSOR_PROX) += hid-sensor-prox.o obj-$(CONFIG_ISL29125) += isl29125.o +obj-$(CONFIG_JSA1212) += jsa1212.o obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o obj-$(CONFIG_LTR501) += ltr501.o obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o diff --git a/drivers/iio/light/jsa1212.c b/drivers/iio/light/jsa1212.c new file mode 100644 index 00000000000000..29de7e7d956242 --- /dev/null +++ b/drivers/iio/light/jsa1212.c @@ -0,0 +1,471 @@ +/* + * JSA1212 Ambient Light & Proximity Sensor Driver + * + * Copyright (c) 2014, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * JSA1212 I2C slave address: 0x44(ADDR tied to GND), 0x45(ADDR tied to VDD) + * + * TODO: Interrupt support, thresholds, range support. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* JSA1212 reg address */ +#define JSA1212_CONF_REG 0x01 +#define JSA1212_INT_REG 0x02 +#define JSA1212_PXS_LT_REG 0x03 +#define JSA1212_PXS_HT_REG 0x04 +#define JSA1212_ALS_TH1_REG 0x05 +#define JSA1212_ALS_TH2_REG 0x06 +#define JSA1212_ALS_TH3_REG 0x07 +#define JSA1212_PXS_DATA_REG 0x08 +#define JSA1212_ALS_DT1_REG 0x09 +#define JSA1212_ALS_DT2_REG 0x0A +#define JSA1212_ALS_RNG_REG 0x0B +#define JSA1212_MAX_REG 0x0C + +/* JSA1212 reg masks */ +#define JSA1212_CONF_MASK 0xFF +#define JSA1212_INT_MASK 0xFF +#define JSA1212_PXS_LT_MASK 0xFF +#define JSA1212_PXS_HT_MASK 0xFF +#define JSA1212_ALS_TH1_MASK 0xFF +#define JSA1212_ALS_TH2_LT_MASK 0x0F +#define JSA1212_ALS_TH2_HT_MASK 0xF0 +#define JSA1212_ALS_TH3_MASK 0xFF +#define JSA1212_PXS_DATA_MASK 0xFF +#define JSA1212_ALS_DATA_MASK 0x0FFF +#define JSA1212_ALS_DT1_MASK 0xFF +#define JSA1212_ALS_DT2_MASK 0x0F +#define JSA1212_ALS_RNG_MASK 0x07 + +/* JSA1212 CONF REG bits */ +#define JSA1212_CONF_PXS_MASK 0x80 +#define JSA1212_CONF_PXS_ENABLE 0x80 +#define JSA1212_CONF_PXS_DISABLE 0x00 +#define JSA1212_CONF_ALS_MASK 0x04 +#define JSA1212_CONF_ALS_ENABLE 0x04 +#define JSA1212_CONF_ALS_DISABLE 0x00 +#define JSA1212_CONF_IRDR_MASK 0x08 +/* Proxmity sensing IRDR current sink settings */ +#define JSA1212_CONF_IRDR_200MA 0x08 +#define JSA1212_CONF_IRDR_100MA 0x00 +#define JSA1212_CONF_PXS_SLP_MASK 0x70 +#define JSA1212_CONF_PXS_SLP_0MS 0x70 +#define JSA1212_CONF_PXS_SLP_12MS 0x60 +#define JSA1212_CONF_PXS_SLP_50MS 0x50 +#define JSA1212_CONF_PXS_SLP_75MS 0x40 +#define JSA1212_CONF_PXS_SLP_100MS 0x30 +#define JSA1212_CONF_PXS_SLP_200MS 0x20 +#define JSA1212_CONF_PXS_SLP_400MS 0x10 +#define JSA1212_CONF_PXS_SLP_800MS 0x00 + +/* JSA1212 INT REG bits */ +#define JSA1212_INT_CTRL_MASK 0x01 +#define JSA1212_INT_CTRL_EITHER 0x00 +#define JSA1212_INT_CTRL_BOTH 0x01 +#define JSA1212_INT_ALS_PRST_MASK 0x06 +#define JSA1212_INT_ALS_PRST_1CONV 0x00 +#define JSA1212_INT_ALS_PRST_4CONV 0x02 +#define JSA1212_INT_ALS_PRST_8CONV 0x04 +#define JSA1212_INT_ALS_PRST_16CONV 0x06 +#define JSA1212_INT_ALS_FLAG_MASK 0x08 +#define JSA1212_INT_ALS_FLAG_CLR 0x00 +#define JSA1212_INT_PXS_PRST_MASK 0x60 +#define JSA1212_INT_PXS_PRST_1CONV 0x00 +#define JSA1212_INT_PXS_PRST_4CONV 0x20 +#define JSA1212_INT_PXS_PRST_8CONV 0x40 +#define JSA1212_INT_PXS_PRST_16CONV 0x60 +#define JSA1212_INT_PXS_FLAG_MASK 0x80 +#define JSA1212_INT_PXS_FLAG_CLR 0x00 + +/* JSA1212 ALS RNG REG bits */ +#define JSA1212_ALS_RNG_0_2048 0x00 +#define JSA1212_ALS_RNG_0_1024 0x01 +#define JSA1212_ALS_RNG_0_512 0x02 +#define JSA1212_ALS_RNG_0_256 0x03 +#define JSA1212_ALS_RNG_0_128 0x04 + +/* JSA1212 INT threshold range */ +#define JSA1212_ALS_TH_MIN 0x0000 +#define JSA1212_ALS_TH_MAX 0x0FFF +#define JSA1212_PXS_TH_MIN 0x00 +#define JSA1212_PXS_TH_MAX 0xFF + +#define JSA1212_ALS_DELAY_MS 200 +#define JSA1212_PXS_DELAY_MS 100 + +#define JSA1212_DRIVER_NAME "jsa1212" +#define JSA1212_REGMAP_NAME "jsa1212_regmap" + +enum jsa1212_op_mode { + JSA1212_OPMODE_ALS_EN, + JSA1212_OPMODE_PXS_EN, +}; + +struct jsa1212_data { + struct i2c_client *client; + struct mutex lock; + u8 als_rng_idx; + bool als_en; /* ALS enable status */ + bool pxs_en; /* proximity enable status */ + struct regmap *regmap; +}; + +/* ALS range idx to val mapping */ +static const int jsa1212_als_range_val[] = {2048, 1024, 512, 256, 128, + 128, 128, 128}; + +/* Enables or disables ALS function based on status */ +static int jsa1212_als_enable(struct jsa1212_data *data, u8 status) +{ + int ret; + + ret = regmap_update_bits(data->regmap, JSA1212_CONF_REG, + JSA1212_CONF_ALS_MASK, + status); + if (ret < 0) + return ret; + + data->als_en = !!status; + + return 0; +} + +/* Enables or disables PXS function based on status */ +static int jsa1212_pxs_enable(struct jsa1212_data *data, u8 status) +{ + int ret; + + ret = regmap_update_bits(data->regmap, JSA1212_CONF_REG, + JSA1212_CONF_PXS_MASK, + status); + if (ret < 0) + return ret; + + data->pxs_en = !!status; + + return 0; +} + +static int jsa1212_read_als_data(struct jsa1212_data *data, + unsigned int *val) +{ + int ret; + __le16 als_data; + + ret = jsa1212_als_enable(data, JSA1212_CONF_ALS_ENABLE); + if (ret < 0) + return ret; + + /* Delay for data output */ + msleep(JSA1212_ALS_DELAY_MS); + + /* Read 12 bit data */ + ret = regmap_bulk_read(data->regmap, JSA1212_ALS_DT1_REG, &als_data, 2); + if (ret < 0) { + dev_err(&data->client->dev, "als data read err\n"); + goto als_data_read_err; + } + + *val = le16_to_cpu(als_data); + +als_data_read_err: + return jsa1212_als_enable(data, JSA1212_CONF_ALS_DISABLE); +} + +static int jsa1212_read_pxs_data(struct jsa1212_data *data, + unsigned int *val) +{ + int ret; + unsigned int pxs_data; + + ret = jsa1212_pxs_enable(data, JSA1212_CONF_PXS_ENABLE); + if (ret < 0) + return ret; + + /* Delay for data output */ + msleep(JSA1212_PXS_DELAY_MS); + + /* Read out all data */ + ret = regmap_read(data->regmap, JSA1212_PXS_DATA_REG, &pxs_data); + if (ret < 0) { + dev_err(&data->client->dev, "pxs data read err\n"); + goto pxs_data_read_err; + } + + *val = pxs_data & JSA1212_PXS_DATA_MASK; + +pxs_data_read_err: + return jsa1212_pxs_enable(data, JSA1212_CONF_PXS_DISABLE); +} + +static int jsa1212_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + int ret; + struct jsa1212_data *data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&data->lock); + switch (chan->type) { + case IIO_LIGHT: + ret = jsa1212_read_als_data(data, val); + break; + case IIO_PROXIMITY: + ret = jsa1212_read_pxs_data(data, val); + break; + default: + ret = -EINVAL; + break; + } + mutex_unlock(&data->lock); + return ret < 0 ? ret : IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_LIGHT: + *val = jsa1212_als_range_val[data->als_rng_idx]; + *val2 = BIT(12); /* Max 12 bit value */ + return IIO_VAL_FRACTIONAL; + default: + break; + } + break; + default: + break; + } + + return -EINVAL; +} + +static const struct iio_chan_spec jsa1212_channels[] = { + { + .type = IIO_LIGHT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + }, + { + .type = IIO_PROXIMITY, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + } +}; + +static const struct iio_info jsa1212_info = { + .driver_module = THIS_MODULE, + .read_raw = &jsa1212_read_raw, +}; + +static int jsa1212_chip_init(struct jsa1212_data *data) +{ + int ret; + + ret = regmap_write(data->regmap, JSA1212_CONF_REG, + (JSA1212_CONF_PXS_SLP_50MS | + JSA1212_CONF_IRDR_200MA)); + if (ret < 0) + return ret; + + ret = regmap_write(data->regmap, JSA1212_INT_REG, + JSA1212_INT_ALS_PRST_4CONV); + if (ret < 0) + return ret; + + data->als_rng_idx = JSA1212_ALS_RNG_0_2048; + + return 0; +} + +static bool jsa1212_is_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case JSA1212_PXS_DATA_REG: + case JSA1212_ALS_DT1_REG: + case JSA1212_ALS_DT2_REG: + case JSA1212_INT_REG: + return true; + default: + return false; + } +} + +static struct regmap_config jsa1212_regmap_config = { + .name = JSA1212_REGMAP_NAME, + .reg_bits = 8, + .val_bits = 8, + .max_register = JSA1212_MAX_REG, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = jsa1212_is_volatile_reg, +}; + +static int jsa1212_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct jsa1212_data *data; + struct iio_dev *indio_dev; + struct regmap *regmap; + int ret; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + regmap = devm_regmap_init_i2c(client, &jsa1212_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&client->dev, "Regmap initialization failed.\n"); + return PTR_ERR(regmap); + } + + data = iio_priv(indio_dev); + + i2c_set_clientdata(client, indio_dev); + data->client = client; + data->regmap = regmap; + + mutex_init(&data->lock); + + ret = jsa1212_chip_init(data); + if (ret < 0) + return ret; + + indio_dev->dev.parent = &client->dev; + indio_dev->channels = jsa1212_channels; + indio_dev->num_channels = ARRAY_SIZE(jsa1212_channels); + indio_dev->name = JSA1212_DRIVER_NAME; + indio_dev->modes = INDIO_DIRECT_MODE; + + indio_dev->info = &jsa1212_info; + + ret = iio_device_register(indio_dev); + if (ret < 0) + dev_err(&client->dev, "%s: register device failed\n", __func__); + + return ret; +} + + /* power off the device */ +static int jsa1212_power_off(struct jsa1212_data *data) +{ + int ret; + + mutex_lock(&data->lock); + + ret = regmap_update_bits(data->regmap, JSA1212_CONF_REG, + JSA1212_CONF_ALS_MASK | + JSA1212_CONF_PXS_MASK, + JSA1212_CONF_ALS_DISABLE | + JSA1212_CONF_PXS_DISABLE); + + if (ret < 0) + dev_err(&data->client->dev, "power off cmd failed\n"); + + mutex_unlock(&data->lock); + + return ret; +} + +static int jsa1212_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct jsa1212_data *data = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + return jsa1212_power_off(data); +} + +#ifdef CONFIG_PM_SLEEP +static int jsa1212_suspend(struct device *dev) +{ + struct jsa1212_data *data; + + data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); + + return jsa1212_power_off(data); +} + +static int jsa1212_resume(struct device *dev) +{ + int ret = 0; + struct jsa1212_data *data; + + data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); + + mutex_lock(&data->lock); + + if (data->als_en) { + ret = jsa1212_als_enable(data, JSA1212_CONF_ALS_ENABLE); + if (ret < 0) { + dev_err(dev, "als resume failed\n"); + goto unlock_and_ret; + } + } + + if (data->pxs_en) { + ret = jsa1212_pxs_enable(data, JSA1212_CONF_PXS_ENABLE); + if (ret < 0) + dev_err(dev, "pxs resume failed\n"); + } + +unlock_and_ret: + mutex_unlock(&data->lock); + return ret; +} + +static SIMPLE_DEV_PM_OPS(jsa1212_pm_ops, jsa1212_suspend, jsa1212_resume); + +#define JSA1212_PM_OPS (&jsa1212_pm_ops) +#else +#define JSA1212_PM_OPS NULL +#endif + +static const struct acpi_device_id jsa1212_acpi_match[] = { + {"JSA1212", 0}, + { }, +}; +MODULE_DEVICE_TABLE(acpi, jsa1212_acpi_match); + +static const struct i2c_device_id jsa1212_id[] = { + { JSA1212_DRIVER_NAME, 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, jsa1212_id); + +static struct i2c_driver jsa1212_driver = { + .driver = { + .name = JSA1212_DRIVER_NAME, + .pm = JSA1212_PM_OPS, + .owner = THIS_MODULE, + .acpi_match_table = ACPI_PTR(jsa1212_acpi_match), + }, + .probe = jsa1212_probe, + .remove = jsa1212_remove, + .id_table = jsa1212_id, +}; +module_i2c_driver(jsa1212_driver); + +MODULE_AUTHOR("Sathya Kuppuswamy "); +MODULE_DESCRIPTION("JSA1212 proximity/ambient light sensor driver"); +MODULE_LICENSE("GPL v2"); From 3bfa74f86006ff8cc1c3cf71f3bdaa885e952f39 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Sun, 11 May 2014 22:09:00 +0100 Subject: [PATCH 0014/3023] iio:kxcjk-1013: Add support for SMO8500 device The Onda v975w tablet contains an accelerometer that's advertised over ACPI as SMO8500. This device is however a KXCJ9 accelerometer as can be seen in the Windows driver's INF file, and from the etching on the chipset ("KXCJ9 41566 0414"). This patch also removes the attempt to get the IRQ for the "data ready" signal, as it does not seem to be supported by this device on this platform. Signed-off-by: Bastien Nocera Signed-off-by: Jonathan Cameron --- drivers/iio/accel/kxcjk-1013.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index 98909a9e284e40..1720e9a547ffec 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -108,6 +108,7 @@ struct kxcjk1013_data { bool motion_trigger_on; int64_t timestamp; enum kx_chipset chipset; + bool is_smo8500_device; }; enum kxcjk1013_axis { @@ -1129,12 +1130,15 @@ static irqreturn_t kxcjk1013_data_rdy_trig_poll(int irq, void *private) } static const char *kxcjk1013_match_acpi_device(struct device *dev, - enum kx_chipset *chipset) + enum kx_chipset *chipset, + bool *is_smo8500_device) { const struct acpi_device_id *id; id = acpi_match_device(dev->driver->acpi_match_table, dev); if (!id) return NULL; + if (strcmp(id->id, "SMO8500") == 0) + *is_smo8500_device = true; *chipset = (enum kx_chipset)id->driver_data; return dev_name(dev); @@ -1149,6 +1153,8 @@ static int kxcjk1013_gpio_probe(struct i2c_client *client, if (!client) return -EINVAL; + if (data->is_smo8500_device) + return -ENOTSUPP; dev = &client->dev; @@ -1198,7 +1204,8 @@ static int kxcjk1013_probe(struct i2c_client *client, name = id->name; } else if (ACPI_HANDLE(&client->dev)) { name = kxcjk1013_match_acpi_device(&client->dev, - &data->chipset); + &data->chipset, + &data->is_smo8500_device); } else return -ENODEV; @@ -1397,6 +1404,7 @@ static const struct acpi_device_id kx_acpi_match[] = { {"KXCJ1013", KXCJK1013}, {"KXCJ1008", KXCJ91008}, {"KXTJ1009", KXTJ21009}, + {"SMO8500", KXCJ91008}, { }, }; MODULE_DEVICE_TABLE(acpi, kx_acpi_match); @@ -1405,6 +1413,7 @@ static const struct i2c_device_id kxcjk1013_id[] = { {"kxcjk1013", KXCJK1013}, {"kxcj91008", KXCJ91008}, {"kxtj21009", KXTJ21009}, + {"SMO8500", KXCJ91008}, {} }; From 11c2f16d1daf64bd0b2d4ce919c2b4f6690fb79a Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 11 Nov 2014 14:36:00 +0000 Subject: [PATCH 0015/3023] MAINTAINERS: Add IIO include files Files under include/linux/iio were not reported as part of the IIO subsystem. Reported-by: Cristina Ciocan Signed-off-by: Daniel Baluta Reviewed-by: Jingoo Han Signed-off-by: Jonathan Cameron --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index df2aecf260790d..264f3cc6e1b6af 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4707,6 +4707,7 @@ L: linux-iio@vger.kernel.org S: Maintained F: drivers/iio/ F: drivers/staging/iio/ +F: include/linux/iio/ IKANOS/ADI EAGLE ADSL USB DRIVER M: Matthieu Castet From d7d787d29148cde12958c2e3765ad3a55dc55eaf Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 18 Nov 2014 18:47:55 +0200 Subject: [PATCH 0016/3023] iio: imu: Add support for Kionix KMX61 sensor Minimal implementation for KMX61 6-axis accelerometer/magnetometer. It exports raw accel/magn readings together with scale and sampling frequency. Datasheet will be available at: http://www.kionix.com/6-axis-accelerometer-magnetometer/kmx61 Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/imu/Kconfig | 9 + drivers/iio/imu/Makefile | 2 + drivers/iio/imu/kmx61.c | 766 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 777 insertions(+) create mode 100644 drivers/iio/imu/kmx61.c diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig index 2b0e45133e9d12..d675f43cb76a5d 100644 --- a/drivers/iio/imu/Kconfig +++ b/drivers/iio/imu/Kconfig @@ -25,6 +25,15 @@ config ADIS16480 Say yes here to build support for Analog Devices ADIS16375, ADIS16480, ADIS16485, ADIS16488 inertial sensors. +config KMX61 + tristate "Kionix KMX61 6-axis accelerometer and magnetometer" + depends on I2C + help + Say Y here if you want to build a driver for Kionix KMX61 6-axis accelerometer + and magnetometer. + To compile this driver as module, choose M here: the module will be called + kmx61. + source "drivers/iio/imu/inv_mpu6050/Kconfig" endmenu diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile index 114d2c17cbe204..e1e6e3d70e26df 100644 --- a/drivers/iio/imu/Makefile +++ b/drivers/iio/imu/Makefile @@ -14,3 +14,5 @@ adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o obj-y += inv_mpu6050/ + +obj-$(CONFIG_KMX61) += kmx61.o diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c new file mode 100644 index 00000000000000..f68b3ef1a57560 --- /dev/null +++ b/drivers/iio/imu/kmx61.c @@ -0,0 +1,766 @@ +/* + * KMX61 - Kionix 6-axis Accelerometer/Magnetometer + * + * Copyright (c) 2014, Intel Corporation. + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * IIO driver for KMX61 (7-bit I2C slave address 0x0E or 0x0F). + * + * TODO: buffer, interrupt, thresholds, acpi, temperature sensor + * + */ + +#include +#include +#include +#include +#include +#include + +#define KMX61_DRV_NAME "kmx61" + +#define KMX61_REG_WHO_AM_I 0x00 + +/* + * three 16-bit accelerometer output registers for X/Y/Z axis + * we use only XOUT_L as a base register, all other addresses + * can be obtained by applying an offset and are provided here + * only for clarity. + */ +#define KMX61_ACC_XOUT_L 0x0A +#define KMX61_ACC_XOUT_H 0x0B +#define KMX61_ACC_YOUT_L 0x0C +#define KMX61_ACC_YOUT_H 0x0D +#define KMX61_ACC_ZOUT_L 0x0E +#define KMX61_ACC_ZOUT_H 0x0F + +/* + * one 16-bit temperature output register + */ +#define KMX61_TEMP_L 0x10 +#define KMX61_TEMP_H 0x11 + +/* + * three 16-bit magnetometer output registers for X/Y/Z axis + */ +#define KMX61_MAG_XOUT_L 0x12 +#define KMX61_MAG_XOUT_H 0x13 +#define KMX61_MAG_YOUT_L 0x14 +#define KMX61_MAG_YOUT_H 0x15 +#define KMX61_MAG_ZOUT_L 0x16 +#define KMX61_MAG_ZOUT_H 0x17 + +#define KMX61_REG_ODCNTL 0x2C +#define KMX61_REG_STBY 0x29 +#define KMX61_REG_CTRL1 0x2A + +#define KMX61_ACC_STBY_BIT BIT(0) +#define KMX61_MAG_STBY_BIT BIT(1) +#define KMX61_ACT_STBY_BIT BIT(7) + +#define KMX61_ALL_STBY (KMX61_ACC_STBY_BIT | KMX61_MAG_STBY_BIT) + +#define KMX61_REG_CTRL1_GSEL0_SHIFT 0 +#define KMX61_REG_CTRL1_GSEL1_SHIFT 1 +#define KMX61_REG_CTRL1_GSEL0_MASK 0x01 +#define KMX61_REG_CTRL1_GSEL1_MASK 0x02 + +#define KMX61_REG_CTRL1_BIT_RES BIT(4) + +#define KMX61_ACC_ODR_SHIFT 0 +#define KMX61_MAG_ODR_SHIFT 4 +#define KMX61_ACC_ODR_MASK 0x0F +#define KMX61_MAG_ODR_MASK 0xF0 + +#define KMX61_SLEEP_DELAY_MS 2000 + +#define KMX61_CHIP_ID 0x12 + +struct kmx61_data { + struct i2c_client *client; + + /* serialize access to non-atomic ops, e.g set_mode */ + struct mutex lock; + u8 range; + u8 odr_bits; + + /* standby state */ + u8 acc_stby; + u8 mag_stby; + + /* power state */ + bool acc_ps; + bool mag_ps; +}; + +enum kmx61_range { + KMX61_RANGE_2G, + KMX61_RANGE_4G, + KMX61_RANGE_8G, +}; + +enum kmx61_scan { + KMX61_SCAN_ACC_X, + KMX61_SCAN_ACC_Y, + KMX61_SCAN_ACC_Z, + KMX61_SCAN_TEMP, + KMX61_SCAN_MAG_X, + KMX61_SCAN_MAG_Y, + KMX61_SCAN_MAG_Z, +}; + +static const struct { + u16 uscale; + u8 gsel0; + u8 gsel1; +} kmx61_scale_table[] = { + {9582, 0, 0}, + {19163, 1, 0}, + {38326, 0, 1}, +}; + +/* KMX61 devices */ +#define KMX61_ACC 0x01 +#define KMX61_MAG 0x02 + +static const struct { + int val; + int val2; + u8 odr_bits; +} kmx61_samp_freq_table[] = { {12, 500000, 0x00}, + {25, 0, 0x01}, + {50, 0, 0x02}, + {100, 0, 0x03}, + {200, 0, 0x04}, + {400, 0, 0x05}, + {800, 0, 0x06}, + {1600, 0, 0x07}, + {0, 781000, 0x08}, + {1, 563000, 0x09}, + {3, 125000, 0x0A}, + {6, 250000, 0x0B} }; + +static IIO_CONST_ATTR(accel_scale_available, "0.009582 0.019163 0.038326"); +static IIO_CONST_ATTR(magn_scale_available, "0.001465"); +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( + "0.781000 1.563000 3.125000 6.250000 12.500000 25 50 100 200 400 800"); + +static struct attribute *kmx61_attributes[] = { + &iio_const_attr_accel_scale_available.dev_attr.attr, + &iio_const_attr_magn_scale_available.dev_attr.attr, + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group kmx61_attribute_group = { + .attrs = kmx61_attributes, +}; + +#define KMX61_ACC_CHAN(_axis, _index) { \ + .type = IIO_ACCEL, \ + .modified = 1, \ + .channel2 = IIO_MOD_ ## _axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .address = KMX61_ACC, \ + .scan_index = _index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 12, \ + .storagebits = 16, \ + .shift = 4, \ + .endianness = IIO_LE, \ + }, \ +} + +#define KMX61_MAG_CHAN(_axis, _index) { \ + .type = IIO_MAGN, \ + .modified = 1, \ + .channel2 = IIO_MOD_ ## _axis, \ + .address = KMX61_MAG, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index = _index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 14, \ + .storagebits = 16, \ + .shift = 2, \ + .endianness = IIO_LE, \ + }, \ +} + +static const struct iio_chan_spec kmx61_channels[] = { + KMX61_ACC_CHAN(X, KMX61_SCAN_ACC_X), + KMX61_ACC_CHAN(Y, KMX61_SCAN_ACC_Y), + KMX61_ACC_CHAN(Z, KMX61_SCAN_ACC_Z), + KMX61_MAG_CHAN(X, KMX61_SCAN_MAG_X), + KMX61_MAG_CHAN(Y, KMX61_SCAN_MAG_Y), + KMX61_MAG_CHAN(Z, KMX61_SCAN_MAG_Z), +}; + +static int kmx61_convert_freq_to_bit(int val, int val2) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++) + if (val == kmx61_samp_freq_table[i].val && + val2 == kmx61_samp_freq_table[i].val2) + return kmx61_samp_freq_table[i].odr_bits; + return -EINVAL; +} +/** + * kmx61_set_mode() - set KMX61 device operating mode + * @data - kmx61 device private data pointer + * @mode - bitmask, indicating operating mode for @device + * @device - bitmask, indicating device for which @mode needs to be set + * @update - update stby bits stored in device's private @data + * + * For each sensor (accelerometer/magnetometer) there are two operating modes + * STANDBY and OPERATION. Neither accel nor magn can be disabled independently + * if they are both enabled. Internal sensors state is saved in acc_stby and + * mag_stby members of driver's private @data. + */ +static int kmx61_set_mode(struct kmx61_data *data, u8 mode, u8 device, + bool update) +{ + int ret; + int acc_stby = -1, mag_stby = -1; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_STBY); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_stby\n"); + return ret; + } + if (device & KMX61_ACC) { + if (mode & KMX61_ACC_STBY_BIT) { + ret |= KMX61_ACC_STBY_BIT; + acc_stby = 1; + } else { + ret &= ~KMX61_ACC_STBY_BIT; + acc_stby = 0; + } + } + + if (device & KMX61_MAG) { + if (mode & KMX61_MAG_STBY_BIT) { + ret |= KMX61_MAG_STBY_BIT; + mag_stby = 1; + } else { + ret &= ~KMX61_MAG_STBY_BIT; + mag_stby = 0; + } + } + + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_STBY, ret); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_stby\n"); + return ret; + } + + if (acc_stby != -1 && update) + data->acc_stby = !!acc_stby; + if (mag_stby != -1 && update) + data->mag_stby = !!mag_stby; + + return ret; +} + +static int kmx61_get_mode(struct kmx61_data *data, u8 *mode, u8 device) +{ + int ret; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_STBY); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_stby\n"); + return ret; + } + *mode = 0; + + if (device & KMX61_ACC) { + if (ret & KMX61_ACC_STBY_BIT) + *mode |= KMX61_ACC_STBY_BIT; + else + *mode &= ~KMX61_ACC_STBY_BIT; + } + + if (device & KMX61_MAG) { + if (ret & KMX61_MAG_STBY_BIT) + *mode |= KMX61_MAG_STBY_BIT; + else + *mode &= ~KMX61_MAG_STBY_BIT; + } + + return 0; +} + +static int kmx61_set_odr(struct kmx61_data *data, int val, int val2, u8 device) +{ + int ret; + u8 mode; + int lodr_bits, odr_bits; + + ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG); + if (ret < 0) + return ret; + + lodr_bits = kmx61_convert_freq_to_bit(val, val2); + if (lodr_bits < 0) + return lodr_bits; + + /* To change ODR, accel and magn must be in STDBY */ + ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, + true); + if (ret < 0) + return ret; + + odr_bits = 0; + if (device & KMX61_ACC) + odr_bits |= lodr_bits; + if (device & KMX61_MAG) + odr_bits |= (lodr_bits << KMX61_MAG_ODR_SHIFT); + + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_ODCNTL, + odr_bits); + if (ret < 0) + return ret; + + ret = kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); + if (ret < 0) + return ret; + + data->odr_bits = lodr_bits; + + return 0; +} + +static +int kmx61_get_odr(struct kmx61_data *data, int *val, int *val2, u8 device) +{ int i; + u8 lodr_bits; + + if (device & KMX61_ACC) + lodr_bits = (data->odr_bits >> KMX61_ACC_ODR_SHIFT) & + KMX61_ACC_ODR_MASK; + else if (device & KMX61_MAG) + lodr_bits = (data->odr_bits >> KMX61_MAG_ODR_SHIFT) & + KMX61_MAG_ODR_MASK; + else + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++) + if (lodr_bits == kmx61_samp_freq_table[i].odr_bits) { + *val = kmx61_samp_freq_table[i].val; + *val2 = kmx61_samp_freq_table[i].val2; + return 0; + } + return -EINVAL; +} + +static int kmx61_set_range(struct kmx61_data *data, int range) +{ + int ret; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); + return ret; + } + + ret &= ~(KMX61_REG_CTRL1_GSEL0_MASK | KMX61_REG_CTRL1_GSEL1_MASK); + ret |= kmx61_scale_table[range].gsel0 << KMX61_REG_CTRL1_GSEL0_SHIFT; + ret |= kmx61_scale_table[range].gsel1 << KMX61_REG_CTRL1_GSEL1_SHIFT; + + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); + return ret; + } + + data->range = range; + + return 0; +} + +static int kmx61_set_scale(struct kmx61_data *data, int uscale) +{ + int ret, i; + u8 mode; + + for (i = 0; i < ARRAY_SIZE(kmx61_scale_table); i++) { + if (kmx61_scale_table[i].uscale == uscale) { + ret = kmx61_get_mode(data, &mode, + KMX61_ACC | KMX61_MAG); + if (ret < 0) + return ret; + + ret = kmx61_set_mode(data, KMX61_ALL_STBY, + KMX61_ACC | KMX61_MAG, true); + if (ret < 0) + return ret; + + ret = kmx61_set_range(data, i); + if (ret < 0) + return ret; + + return kmx61_set_mode(data, mode, + KMX61_ACC | KMX61_MAG, true); + } + } + return -EINVAL; +} + +static int kmx61_chip_init(struct kmx61_data *data) +{ + int ret; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_WHO_AM_I); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading who_am_i\n"); + return ret; + } + + if (ret != KMX61_CHIP_ID) { + dev_err(&data->client->dev, + "Wrong chip id, got %x expected %x\n", + ret, KMX61_CHIP_ID); + return -EINVAL; + } + + /* set accel 12bit, 4g range */ + ret = kmx61_set_range(data, KMX61_RANGE_4G); + if (ret < 0) + return ret; + + /* set acc/magn to OPERATION mode */ + ret = kmx61_set_mode(data, 0, KMX61_ACC | KMX61_MAG, true); + if (ret < 0) + return ret; + + return 0; +} +/** + * kmx61_set_power_state() - set power state for kmx61 @device + * @data - kmx61 device private pointer + * @on - power state to be set for @device + * @device - bitmask indicating device for which @on state needs to be set + * + * Notice that when ACC power state needs to be set to ON and MAG is in + * OPERATION then we know that kmx61_runtime_resume was already called + * so we must set ACC OPERATION mode here. The same happens when MAG power + * state needs to be set to ON and ACC is in OPERATION. + */ +static int kmx61_set_power_state(struct kmx61_data *data, bool on, u8 device) +{ +#ifdef CONFIG_PM_RUNTIME + int ret; + + if (device & KMX61_ACC) { + if (on && !data->acc_ps && !data->mag_stby) + kmx61_set_mode(data, 0, KMX61_ACC, true); + data->acc_ps = on; + } + if (device & KMX61_MAG) { + if (on && !data->mag_ps && !data->acc_stby) + kmx61_set_mode(data, 0, KMX61_MAG, true); + data->mag_ps = on; + } + + if (on) { + ret = pm_runtime_get_sync(&data->client->dev); + } else { + pm_runtime_mark_last_busy(&data->client->dev); + ret = pm_runtime_put_autosuspend(&data->client->dev); + } + if (ret < 0) { + dev_err(&data->client->dev, + "Failed: kmx61_set_power_state for %d, ret %d\n", + on, ret); + return ret; + } +#endif + return 0; +} + +static int kmx61_read_measurement(struct kmx61_data *data, int base, int offset) +{ + int ret; + u8 reg = base + offset * 2; + + ret = i2c_smbus_read_word_data(data->client, reg); + if (ret < 0) { + dev_err(&data->client->dev, "failed to read reg at %x\n", reg); + return ret; + } + + return ret; +} + +static int kmx61_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long mask) +{ + struct kmx61_data *data = iio_priv(indio_dev); + int ret; + u8 base_reg; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_ACCEL: + case IIO_MAGN: + base_reg = KMX61_ACC_XOUT_L; + break; + default: + return -EINVAL; + } + mutex_lock(&data->lock); + + kmx61_set_power_state(data, true, chan->address); + ret = kmx61_read_measurement(data, base_reg, chan->scan_index); + if (ret < 0) { + kmx61_set_power_state(data, false, chan->address); + mutex_unlock(&data->lock); + return ret; + } + *val = sign_extend32(ret >> chan->scan_type.shift, + chan->scan_type.realbits - 1); + kmx61_set_power_state(data, false, chan->address); + + mutex_unlock(&data->lock); + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ACCEL: + *val = 0; + *val2 = kmx61_scale_table[data->range].uscale; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_MAGN: + /* 14 bits res, 1465 microGauss per magn count */ + *val = 0; + *val2 = 1465; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SAMP_FREQ: + if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN) + return -EINVAL; + + mutex_lock(&data->lock); + ret = kmx61_get_odr(data, val, val2, chan->address); + mutex_unlock(&data->lock); + if (ret) + return -EINVAL; + return IIO_VAL_INT_PLUS_MICRO; + } + return -EINVAL; +} + +static int kmx61_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, + int val2, long mask) +{ + struct kmx61_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN) + return -EINVAL; + + mutex_lock(&data->lock); + ret = kmx61_set_odr(data, val, val2, chan->address); + mutex_unlock(&data->lock); + return ret; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ACCEL: + if (val != 0) + return -EINVAL; + mutex_lock(&data->lock); + ret = kmx61_set_scale(data, val2); + mutex_unlock(&data->lock); + return ret; + default: + return -EINVAL; + } + return ret; + default: + return -EINVAL; + } + return ret; +} + +static const struct iio_info kmx61_info = { + .driver_module = THIS_MODULE, + .read_raw = kmx61_read_raw, + .write_raw = kmx61_write_raw, + .attrs = &kmx61_attribute_group, +}; + +static int kmx61_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct kmx61_data *data; + struct iio_dev *indio_dev; + int ret; + const char *name = NULL; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client = client; + + if (id) + name = id->name; + + indio_dev->dev.parent = &client->dev; + indio_dev->channels = kmx61_channels; + indio_dev->num_channels = ARRAY_SIZE(kmx61_channels); + indio_dev->name = name; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &kmx61_info; + + mutex_init(&data->lock); + + ret = kmx61_chip_init(data); + if (ret < 0) + return ret; + + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(&client->dev, "Failed to register iio device\n"); + goto err_iio_device_register; + } + + ret = pm_runtime_set_active(&client->dev); + if (ret < 0) + goto err_pm_runtime_set_active; + + pm_runtime_enable(&client->dev); + pm_runtime_set_autosuspend_delay(&client->dev, KMX61_SLEEP_DELAY_MS); + pm_runtime_use_autosuspend(&client->dev); + + return 0; + +err_pm_runtime_set_active: + iio_device_unregister(indio_dev); +err_iio_device_register: + kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); + return ret; +} + +static int kmx61_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct kmx61_data *data = iio_priv(indio_dev); + int ret; + + pm_runtime_disable(&client->dev); + pm_runtime_set_suspended(&client->dev); + pm_runtime_put_noidle(&client->dev); + + iio_device_unregister(indio_dev); + + mutex_lock(&data->lock); + ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); + mutex_unlock(&data->lock); + + return ret; +} + +#ifdef CONFIG_PM_SLEEP +static int kmx61_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct kmx61_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->lock); + ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, + false); + mutex_unlock(&data->lock); + + return ret; +} + +static int kmx61_resume(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct kmx61_data *data = iio_priv(indio_dev); + u8 stby = 0; + + if (data->acc_stby) + stby |= KMX61_ACC_STBY_BIT; + if (data->mag_stby) + stby |= KMX61_MAG_STBY_BIT; + + return kmx61_set_mode(data, stby, KMX61_ACC | KMX61_MAG, true); +} +#endif + +#ifdef CONFIG_PM_RUNTIME +static int kmx61_runtime_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct kmx61_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->lock); + ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); + mutex_unlock(&data->lock); + + return ret; +} + +static int kmx61_runtime_resume(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct kmx61_data *data = iio_priv(indio_dev); + u8 stby = 0; + + if (!data->acc_ps) + stby |= KMX61_ACC_STBY_BIT; + if (!data->mag_ps) + stby |= KMX61_MAG_STBY_BIT; + + return kmx61_set_mode(data, stby, KMX61_ACC | KMX61_MAG, true); +} +#endif + +static const struct dev_pm_ops kmx61_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(kmx61_suspend, kmx61_resume) + SET_RUNTIME_PM_OPS(kmx61_runtime_suspend, kmx61_runtime_resume, NULL) +}; + +static const struct i2c_device_id kmx61_id[] = { + {"kmx611021", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, kmx61_id); + +static struct i2c_driver kmx61_driver = { + .driver = { + .name = KMX61_DRV_NAME, + .pm = &kmx61_pm_ops, + }, + .probe = kmx61_probe, + .remove = kmx61_remove, + .id_table = kmx61_id, +}; + +module_i2c_driver(kmx61_driver); + +MODULE_AUTHOR("Daniel Baluta "); +MODULE_DESCRIPTION("KMX61 accelerometer/magnetometer driver"); +MODULE_LICENSE("GPL v2"); From 356ae946f9945997213b19279bc2e84bb61cc26a Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Mon, 10 Nov 2014 14:45:29 +0200 Subject: [PATCH 0017/3023] iio: dummy: Add virtual registers for dummy device We need a way to store events generated by iio_dummy_evgen module, in order to correctly process IRQs in iio_simple_dummy_events. For the moment, we add two registers: * id_reg - ID register, stores the source of the event * id_data - DATA register, stores the type of the event e.g echo 4 > /sys/bus/iio/devices/iio_evgen/poke2 id_reg 0x02, id_data 0x04 This means, event of type 4 was generated by fake device 2. We currently use a hardcoded mapping of virtual events to IIO events. Signed-off-by: Irina Tirdea Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/staging/iio/iio_dummy_evgen.c | 17 ++++++++++++++ drivers/staging/iio/iio_dummy_evgen.h | 6 +++++ drivers/staging/iio/iio_simple_dummy.h | 2 ++ drivers/staging/iio/iio_simple_dummy_events.c | 23 +++++++++++++++---- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/drivers/staging/iio/iio_dummy_evgen.c b/drivers/staging/iio/iio_dummy_evgen.c index 5a804f16ec2fbe..59ad5a3efe9cb3 100644 --- a/drivers/staging/iio/iio_dummy_evgen.c +++ b/drivers/staging/iio/iio_dummy_evgen.c @@ -33,6 +33,7 @@ * @base: base of irq range * @enabled: mask of which irqs are enabled * @inuse: mask of which irqs are connected + * @regs: irq regs we are faking * @lock: protect the evgen state */ struct iio_dummy_eventgen { @@ -40,6 +41,7 @@ struct iio_dummy_eventgen { int base; bool enabled[IIO_EVENTGEN_NO]; bool inuse[IIO_EVENTGEN_NO]; + struct iio_dummy_regs regs[IIO_EVENTGEN_NO]; struct mutex lock; }; @@ -136,6 +138,12 @@ int iio_dummy_evgen_release_irq(int irq) } EXPORT_SYMBOL_GPL(iio_dummy_evgen_release_irq); +struct iio_dummy_regs *iio_dummy_evgen_get_regs(int irq) +{ + return &iio_evgen->regs[irq - iio_evgen->base]; +} +EXPORT_SYMBOL_GPL(iio_dummy_evgen_get_regs); + static void iio_dummy_evgen_free(void) { irq_free_descs(iio_evgen->base, IIO_EVENTGEN_NO); @@ -153,6 +161,15 @@ static ssize_t iio_evgen_poke(struct device *dev, size_t len) { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + unsigned long event; + int ret; + + ret = kstrtoul(buf, 10, &event); + if (ret) + return ret; + + iio_evgen->regs[this_attr->address].reg_id = this_attr->address; + iio_evgen->regs[this_attr->address].reg_data = event; if (iio_evgen->enabled[this_attr->address]) handle_nested_irq(iio_evgen->base + this_attr->address); diff --git a/drivers/staging/iio/iio_dummy_evgen.h b/drivers/staging/iio/iio_dummy_evgen.h index 3a180811b315df..2ac293ab7c8fbd 100644 --- a/drivers/staging/iio/iio_dummy_evgen.h +++ b/drivers/staging/iio/iio_dummy_evgen.h @@ -1,6 +1,12 @@ #ifndef _IIO_DUMMY_EVGEN_H_ #define _IIO_DUMMY_EVGEN_H_ +struct iio_dummy_regs { + u32 reg_id; + u32 reg_data; +}; + +struct iio_dummy_regs *iio_dummy_evgen_get_regs(int irq); int iio_dummy_evgen_get_irq(void); int iio_dummy_evgen_release_irq(int irq); diff --git a/drivers/staging/iio/iio_simple_dummy.h b/drivers/staging/iio/iio_simple_dummy.h index 3027aed7909373..ad898424d9bdc7 100644 --- a/drivers/staging/iio/iio_simple_dummy.h +++ b/drivers/staging/iio/iio_simple_dummy.h @@ -13,6 +13,7 @@ #include struct iio_dummy_accel_calibscale; +struct iio_dummy_regs; /** * struct iio_dummy_state - device instance specific state. @@ -35,6 +36,7 @@ struct iio_dummy_state { int accel_calibbias; const struct iio_dummy_accel_calibscale *accel_calibscale; struct mutex lock; + struct iio_dummy_regs *regs; #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS int event_irq; int event_val; diff --git a/drivers/staging/iio/iio_simple_dummy_events.c b/drivers/staging/iio/iio_simple_dummy_events.c index 64b45b07754942..719dfa5ae7dfb5 100644 --- a/drivers/staging/iio/iio_simple_dummy_events.c +++ b/drivers/staging/iio/iio_simple_dummy_events.c @@ -148,12 +148,23 @@ int iio_simple_dummy_write_event_value(struct iio_dev *indio_dev, static irqreturn_t iio_simple_dummy_event_handler(int irq, void *private) { struct iio_dev *indio_dev = private; + struct iio_dummy_state *st = iio_priv(indio_dev); + + dev_dbg(&indio_dev->dev, "id %x event %x\n", + st->regs->reg_id, st->regs->reg_data); + + switch (st->regs->reg_data) { + case 0: + iio_push_event(indio_dev, + IIO_EVENT_CODE(IIO_VOLTAGE, 0, 0, + IIO_EV_DIR_RISING, + IIO_EV_TYPE_THRESH, 0, 0, 0), + iio_get_time_ns()); + break; + default: + break; + } - iio_push_event(indio_dev, - IIO_EVENT_CODE(IIO_VOLTAGE, 0, 0, - IIO_EV_DIR_RISING, - IIO_EV_TYPE_THRESH, 0, 0, 0), - iio_get_time_ns()); return IRQ_HANDLED; } @@ -179,6 +190,8 @@ int iio_simple_dummy_events_register(struct iio_dev *indio_dev) ret = st->event_irq; goto error_ret; } + st->regs = iio_dummy_evgen_get_regs(st->event_irq); + ret = request_threaded_irq(st->event_irq, NULL, &iio_simple_dummy_event_handler, From 55aebeb926b6f93a540328e7ac770ef536b09b77 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Mon, 10 Nov 2014 14:45:30 +0200 Subject: [PATCH 0018/3023] iio: core: Introduce IIO_ACTIVITY channel This channel will be used for exposing information about activity composite sensors. Activities supported so far: * running * jogging * walking * still THRESHOLD event is used to signal a change in the activity state. We associate a confidence interval for each activity expressed as a percentage from 0 to 100. * 0, means the sensor IS NOT reporting that activity. * 100, means the sensor IS reporting that activity. Users of this interface have two possible means to gather information about the ongoing activities. 1. Event based, via event file descriptor * sensor may report an event when ENTERING an activity or LEAVING an activity based on a threshold value. * drivers will wake up applications waiting data on the event fd 2. Polling, by reading the sysfs associated attribute files: * /sys/bus/iio/devices/iio:device0/in_activity_running_input expressed as percentage confidence value from 0 to 100. This will offer an interface for Android significant motion composite sensor defined here: http://source.android.com/devices/sensors/composite_sensors.html Activities listed above are supported by Freescale's MMA9553 sensor: http://freescale.com/files/sensors/doc/ref_manual/MMA9553LSWRM.pdf Signed-off-by: Irina Tirdea Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 44 +++++++++++++++++++++++++ drivers/iio/industrialio-core.c | 5 +++ include/linux/iio/types.h | 7 +++- 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 117521dbf2b3eb..7bf49ad8fd821f 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -790,6 +790,40 @@ Description: met before an event is generated. If direction is not specified then this period applies to both directions. +What: /sys/.../events/in_activity_still_thresh_rising_en +What: /sys/.../events/in_activity_still_thresh_falling_en +What: /sys/.../events/in_activity_walking_thresh_rising_en +What: /sys/.../events/in_activity_walking_thresh_falling_en +What: /sys/.../events/in_activity_jogging_thresh_rising_en +What: /sys/.../events/in_activity_jogging_thresh_falling_en +What: /sys/.../events/in_activity_running_thresh_rising_en +What: /sys/.../events/in_activity_running_thresh_falling_en +KernelVersion: 3.19 +Contact: linux-iio@vger.kernel.org +Description: + Enables or disables activitity events. Depending on direction + an event is generated when sensor ENTERS or LEAVES a given state. + +What: /sys/.../events/in_activity_still_thresh_rising_value +What: /sys/.../events/in_activity_still_thresh_falling_value +What: /sys/.../events/in_activity_walking_thresh_rising_value +What: /sys/.../events/in_activity_walking_thresh_falling_value +What: /sys/.../events/in_activity_jogging_thresh_rising_value +What: /sys/.../events/in_activity_jogging_thresh_falling_value +What: /sys/.../events/in_activity_running_thresh_rising_value +What: /sys/.../events/in_activity_running_thresh_falling_value +KernelVersion: 3.19 +Contact: linux-iio@vger.kernel.org +Description: + Confidence value (in units as percentage) to be used + for deciding when an event should be generated. E.g for + running: If the confidence value reported by the sensor + is greater than in_activity_running_thresh_rising_value + then the sensor ENTERS running state. Conversely, if the + confidence value reported by the sensor is lower than + in_activity_running_thresh_falling_value then the sensor + is LEAVING running state. + What: /sys/.../iio:deviceX/events/in_accel_mag_en What: /sys/.../iio:deviceX/events/in_accel_mag_rising_en What: /sys/.../iio:deviceX/events/in_accel_mag_falling_en @@ -956,6 +990,16 @@ Description: and the relevant _type attributes to establish the data storage format. +What: /sys/.../iio:deviceX/in_activity_still_input +What: /sys/.../iio:deviceX/in_activity_walking_input +What: /sys/.../iio:deviceX/in_activity_jogging_input +What: /sys/.../iio:deviceX/in_activity_running_input +KernelVersion: 3.19 +Contact: linux-iio@vger.kernel.org +Description: + This attribute is used to read the confidence for an activity + expressed in units as percentage. + What: /sys/.../iio:deviceX/in_anglvel_z_quadrature_correction_raw KernelVersion: 2.6.38 Contact: linux-iio@vger.kernel.org diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index af3e76d652ba0a..e453ef9e0c3627 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -70,6 +70,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_CCT] = "cct", [IIO_PRESSURE] = "pressure", [IIO_HUMIDITYRELATIVE] = "humidityrelative", + [IIO_ACTIVITY] = "activity", }; static const char * const iio_modifier_names[] = { @@ -91,6 +92,10 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_NORTH_TRUE] = "from_north_true", [IIO_MOD_NORTH_MAGN_TILT_COMP] = "from_north_magnetic_tilt_comp", [IIO_MOD_NORTH_TRUE_TILT_COMP] = "from_north_true_tilt_comp", + [IIO_MOD_RUNNING] = "running", + [IIO_MOD_JOGGING] = "jogging", + [IIO_MOD_WALKING] = "walking", + [IIO_MOD_STILL] = "still", }; /* relies on pairs of these shared then separate */ diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index 4a2af8adf87461..b3a241d53b5410 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -30,6 +30,7 @@ enum iio_chan_type { IIO_CCT, IIO_PRESSURE, IIO_HUMIDITYRELATIVE, + IIO_ACTIVITY, }; enum iio_modifier { @@ -59,7 +60,11 @@ enum iio_modifier { IIO_MOD_NORTH_MAGN, IIO_MOD_NORTH_TRUE, IIO_MOD_NORTH_MAGN_TILT_COMP, - IIO_MOD_NORTH_TRUE_TILT_COMP + IIO_MOD_NORTH_TRUE_TILT_COMP, + IIO_MOD_RUNNING, + IIO_MOD_JOGGING, + IIO_MOD_WALKING, + IIO_MOD_STILL, }; enum iio_event_type { From 1843c2f3def16740eb6d129a9790c32dd21aa5ea Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Mon, 10 Nov 2014 14:45:31 +0200 Subject: [PATCH 0019/3023] iio: core: Introduce IIO_EV_DIR_NONE For some events (e.g.: step detector) a direction does not make sense. Add IIO_EV_DIR_NONE to be used with such events and generate sysfs event attributes that do not contain direction. Signed-off-by: Irina Tirdea Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-event.c | 12 +++++++++--- include/linux/iio/types.h | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index 0c1e37e3120a40..1290290adcb583 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -327,9 +327,15 @@ static int iio_device_add_event(struct iio_dev *indio_dev, for_each_set_bit(i, mask, sizeof(*mask)*8) { if (i >= ARRAY_SIZE(iio_ev_info_text)) return -EINVAL; - postfix = kasprintf(GFP_KERNEL, "%s_%s_%s", - iio_ev_type_text[type], iio_ev_dir_text[dir], - iio_ev_info_text[i]); + if (dir != IIO_EV_DIR_NONE) + postfix = kasprintf(GFP_KERNEL, "%s_%s_%s", + iio_ev_type_text[type], + iio_ev_dir_text[dir], + iio_ev_info_text[i]); + else + postfix = kasprintf(GFP_KERNEL, "%s_%s", + iio_ev_type_text[type], + iio_ev_info_text[i]); if (postfix == NULL) return -ENOMEM; diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index b3a241d53b5410..52cb5329407b98 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -86,6 +86,7 @@ enum iio_event_direction { IIO_EV_DIR_EITHER, IIO_EV_DIR_RISING, IIO_EV_DIR_FALLING, + IIO_EV_DIR_NONE, }; #define IIO_VAL_INT 1 From a88bfe78583026eb9f21d4014ba481b22b66cee3 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Mon, 10 Nov 2014 14:45:32 +0200 Subject: [PATCH 0020/3023] iio: core: Introduce STEPS channel, ENABLE mask and INSTANCE event These changes are needed to support the functionality of a pedometer. A pedometer has two basic functionalities: step counter and step detector. The step counter needs to be enabled and then it will count the steps in its hardware register. Whenever the application needs to check the step count, it will read the step counter register. To support the step counter a new channel type STEPS is added. Since the pedometer needs to be enabled first so that the hardware can count and store the steps, we need a specific ENABLE channel info mask. The step detector will generate an interrupt each time a step is detected. To support this functionality we add a new event type INSTANCE. For more information on the Android requirements for step counter and step detector see: http://source.android.com/devices/sensors/composite_sensors.html#counter and http://source.android.com/devices/sensors/composite_sensors.html#detector. A device that has the pedometer functionality this interface needs to support is Freescale's MMA9553L: http://www.freescale.com/files/sensors/doc/ref_manual/MMA9553LSWRM.pdf Signed-off-by: Irina Tirdea Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 22 ++++++++++++++++++++++ drivers/iio/industrialio-core.c | 2 ++ drivers/iio/industrialio-event.c | 1 + include/linux/iio/iio.h | 1 + include/linux/iio/types.h | 2 ++ 5 files changed, 28 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 7bf49ad8fd821f..c60b0a1af83974 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -856,6 +856,13 @@ Description: number or direction is not specified, applies to all channels of this type. +What: /sys/.../events/in_steps_instance_en +KernelVersion: 3.19 +Contact: linux-iio@vger.kernel.org +Description: + Enables or disables step detection. Each time the user takes a step an + event of this type will be generated. + What: /sys/bus/iio/devices/iio:deviceX/trigger/current_trigger KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org @@ -1095,3 +1102,18 @@ Description: after application of scale and offset. If no offset or scale is present, output should be considered as processed with the unit in milliamps. + +What: /sys/.../iio:deviceX/in_steps_en +KernelVersion: 3.19 +Contact: linux-iio@vger.kernel.org +Description: + Activates the step counter. After activation, the number of steps + taken by the user will be counted in hardware and exported through + in_steps_input. + +What: /sys/.../iio:deviceX/in_steps_input +KernelVersion: 3.19 +Contact: linux-iio@vger.kernel.org +Description: + This attribute is used to read the number of steps taken by the user + since the last reboot while activated. diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index e453ef9e0c3627..1e060f390b084f 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -71,6 +71,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_PRESSURE] = "pressure", [IIO_HUMIDITYRELATIVE] = "humidityrelative", [IIO_ACTIVITY] = "activity", + [IIO_STEPS] = "steps", }; static const char * const iio_modifier_names[] = { @@ -118,6 +119,7 @@ static const char * const iio_chan_info_postfix[] = { [IIO_CHAN_INFO_HARDWAREGAIN] = "hardwaregain", [IIO_CHAN_INFO_HYSTERESIS] = "hysteresis", [IIO_CHAN_INFO_INT_TIME] = "integration_time", + [IIO_CHAN_INFO_ENABLE] = "en", }; /** diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index 1290290adcb583..3f5cee0295c5c0 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -197,6 +197,7 @@ static const char * const iio_ev_type_text[] = { [IIO_EV_TYPE_ROC] = "roc", [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive", [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive", + [IIO_EV_TYPE_INSTANCE] = "instance", }; static const char * const iio_ev_dir_text[] = { diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 3642ce7ef512cb..f45a400a5e3ea1 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -38,6 +38,7 @@ enum iio_chan_info_enum { IIO_CHAN_INFO_HARDWAREGAIN, IIO_CHAN_INFO_HYSTERESIS, IIO_CHAN_INFO_INT_TIME, + IIO_CHAN_INFO_ENABLE, }; enum iio_shared_by { diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index 52cb5329407b98..904dcbbf0e6fed 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -31,6 +31,7 @@ enum iio_chan_type { IIO_PRESSURE, IIO_HUMIDITYRELATIVE, IIO_ACTIVITY, + IIO_STEPS, }; enum iio_modifier { @@ -73,6 +74,7 @@ enum iio_event_type { IIO_EV_TYPE_ROC, IIO_EV_TYPE_THRESH_ADAPTIVE, IIO_EV_TYPE_MAG_ADAPTIVE, + IIO_EV_TYPE_INSTANCE, }; enum iio_event_info { From bcdf28fb1b8badf3cdba18d349f6251057e36a45 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Mon, 10 Nov 2014 14:45:33 +0200 Subject: [PATCH 0021/3023] iio: core: Introduce IIO_CHAN_INFO_CALIBHEIGHT Some devices need the height of the user to compute various parameters. One of this devices is Freescale's MMA9553L (http://www.freescale.com/files/sensors/doc/ref_manual/MMA9553LSWRM.pdf) that needs the height of the user to compute the stride length which is used further to determine distance, speed and activity type. Signed-off-by: Irina Tirdea Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 8 ++++++++ drivers/iio/industrialio-core.c | 1 + include/linux/iio/iio.h | 1 + 3 files changed, 10 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index c60b0a1af83974..4a9e29a3c2dc4d 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -323,6 +323,14 @@ Description: production inaccuracies). If shared across all channels, _calibscale is used. +What: /sys/bus/iio/devices/iio:deviceX/in_steps_calibheight +KernelVersion: 3.19 +Contact: linux-iio@vger.kernel.org +Description: + Height of the user (in centimeters) used by some pedometers + to compute the stride length, distance, speed and activity + type. + What: /sys/bus/iio/devices/iio:deviceX/in_accel_scale_available What: /sys/.../iio:deviceX/in_voltageX_scale_available What: /sys/.../iio:deviceX/in_voltage-voltage_scale_available diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 1e060f390b084f..45bb3a43afacdf 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -120,6 +120,7 @@ static const char * const iio_chan_info_postfix[] = { [IIO_CHAN_INFO_HYSTERESIS] = "hysteresis", [IIO_CHAN_INFO_INT_TIME] = "integration_time", [IIO_CHAN_INFO_ENABLE] = "en", + [IIO_CHAN_INFO_CALIBHEIGHT] = "calibheight", }; /** diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index f45a400a5e3ea1..878d861b061059 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -39,6 +39,7 @@ enum iio_chan_info_enum { IIO_CHAN_INFO_HYSTERESIS, IIO_CHAN_INFO_INT_TIME, IIO_CHAN_INFO_ENABLE, + IIO_CHAN_INFO_CALIBHEIGHT, }; enum iio_shared_by { From 3e34e650db19708b1c27421e8d3d749a09adbb0c Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Mon, 10 Nov 2014 14:45:34 +0200 Subject: [PATCH 0022/3023] iio: dummy: Demonstrate the usage of new channel types Adds support for the new channel types in the dummy driver: * a new channel IIO_ACTIVITY * two state transition events (running and walking) * a new channel IIO_STEPS and support for reading and writing pedometer step counter * step detect event * a new IIO_CHAN_INFO_CALIBHEIGHT mask bit for reading and writing user's height. Signed-off-by: Irina Tirdea Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/staging/iio/iio_simple_dummy.c | 199 ++++++++++++++++-- drivers/staging/iio/iio_simple_dummy.h | 5 + drivers/staging/iio/iio_simple_dummy_events.c | 43 ++++ 3 files changed, 229 insertions(+), 18 deletions(-) diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c index bf78e6f0311ff3..10a9e0882bbc58 100644 --- a/drivers/staging/iio/iio_simple_dummy.c +++ b/drivers/staging/iio/iio_simple_dummy.c @@ -69,6 +69,34 @@ static const struct iio_event_spec iio_dummy_event = { .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), }; +/* + * simple step detect event - triggered when a step is detected + */ +static const struct iio_event_spec step_detect_event = { + .type = IIO_EV_TYPE_INSTANCE, + .dir = IIO_EV_DIR_NONE, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), +}; + +/* + * simple transition event - triggered when the reported running confidence + * value rises above a threshold value + */ +static const struct iio_event_spec iio_running_event = { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), +}; + +/* + * simple transition event - triggered when the reported walking confidence + * value falls under a threshold value + */ +static const struct iio_event_spec iio_walking_event = { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), +}; #endif /* @@ -215,6 +243,37 @@ static const struct iio_chan_spec iio_dummy_channels[] = { .indexed = 1, .channel = 0, }, + { + .type = IIO_STEPS, + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_ENABLE) | + BIT(IIO_CHAN_INFO_CALIBHEIGHT), + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .scan_index = -1, +#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS + .event_spec = &step_detect_event, + .num_event_specs = 1, +#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ + }, + { + .type = IIO_ACTIVITY, + .modified = 1, + .channel2 = IIO_MOD_RUNNING, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), +#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS + .event_spec = &iio_running_event, + .num_event_specs = 1, +#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ + }, + { + .type = IIO_ACTIVITY, + .modified = 1, + .channel2 = IIO_MOD_WALKING, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), +#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS + .event_spec = &iio_walking_event, + .num_event_specs = 1, +#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ + }, }; /** @@ -263,24 +322,55 @@ static int iio_dummy_read_raw(struct iio_dev *indio_dev, break; } break; + case IIO_CHAN_INFO_PROCESSED: + switch (chan->type) { + case IIO_STEPS: + *val = st->steps; + ret = IIO_VAL_INT; + break; + case IIO_ACTIVITY: + switch (chan->channel2) { + case IIO_MOD_RUNNING: + *val = st->activity_running; + ret = IIO_VAL_INT; + break; + case IIO_MOD_WALKING: + *val = st->activity_walking; + ret = IIO_VAL_INT; + break; + default: + break; + } + break; + default: + break; + } + break; case IIO_CHAN_INFO_OFFSET: /* only single ended adc -> 7 */ *val = 7; ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_SCALE: - switch (chan->differential) { - case 0: - /* only single ended adc -> 0.001333 */ - *val = 0; - *val2 = 1333; - ret = IIO_VAL_INT_PLUS_MICRO; + switch (chan->type) { + case IIO_VOLTAGE: + switch (chan->differential) { + case 0: + /* only single ended adc -> 0.001333 */ + *val = 0; + *val2 = 1333; + ret = IIO_VAL_INT_PLUS_MICRO; + break; + case 1: + /* all differential adc channels -> + * 0.000001344 */ + *val = 0; + *val2 = 1344; + ret = IIO_VAL_INT_PLUS_NANO; + } + break; + default: break; - case 1: - /* all differential adc channels -> 0.000001344 */ - *val = 0; - *val2 = 1344; - ret = IIO_VAL_INT_PLUS_NANO; } break; case IIO_CHAN_INFO_CALIBBIAS: @@ -298,6 +388,27 @@ static int iio_dummy_read_raw(struct iio_dev *indio_dev, *val2 = 33; ret = IIO_VAL_INT_PLUS_NANO; break; + case IIO_CHAN_INFO_ENABLE: + switch (chan->type) { + case IIO_STEPS: + *val = st->steps_enabled; + ret = IIO_VAL_INT; + break; + default: + break; + } + break; + case IIO_CHAN_INFO_CALIBHEIGHT: + switch (chan->type) { + case IIO_STEPS: + *val = st->height; + ret = IIO_VAL_INT; + break; + default: + break; + } + break; + default: break; } @@ -330,14 +441,45 @@ static int iio_dummy_write_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - if (chan->output == 0) + switch (chan->type) { + case IIO_VOLTAGE: + if (chan->output == 0) + return -EINVAL; + + /* Locking not required as writing single value */ + mutex_lock(&st->lock); + st->dac_val = val; + mutex_unlock(&st->lock); + return 0; + default: return -EINVAL; - - /* Locking not required as writing single value */ - mutex_lock(&st->lock); - st->dac_val = val; - mutex_unlock(&st->lock); - return 0; + } + case IIO_CHAN_INFO_PROCESSED: + switch (chan->type) { + case IIO_STEPS: + mutex_lock(&st->lock); + st->steps = val; + mutex_unlock(&st->lock); + return 0; + case IIO_ACTIVITY: + if (val < 0) + val = 0; + if (val > 100) + val = 100; + switch (chan->channel2) { + case IIO_MOD_RUNNING: + st->activity_running = val; + return 0; + case IIO_MOD_WALKING: + st->activity_walking = val; + return 0; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } case IIO_CHAN_INFO_CALIBSCALE: mutex_lock(&st->lock); /* Compare against table - hard matching here */ @@ -356,6 +498,24 @@ static int iio_dummy_write_raw(struct iio_dev *indio_dev, st->accel_calibbias = val; mutex_unlock(&st->lock); return 0; + case IIO_CHAN_INFO_ENABLE: + switch (chan->type) { + case IIO_STEPS: + mutex_lock(&st->lock); + st->steps_enabled = val; + mutex_unlock(&st->lock); + return 0; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_CALIBHEIGHT: + switch (chan->type) { + case IIO_STEPS: + st->height = val; + return 0; + default: + return -EINVAL; + } default: return -EINVAL; @@ -395,6 +555,9 @@ static int iio_dummy_init_device(struct iio_dev *indio_dev) st->accel_val = 34; st->accel_calibbias = -7; st->accel_calibscale = &dummy_scales[0]; + st->steps = 47; + st->activity_running = 98; + st->activity_walking = 4; return 0; } diff --git a/drivers/staging/iio/iio_simple_dummy.h b/drivers/staging/iio/iio_simple_dummy.h index ad898424d9bdc7..3b714b486f5e40 100644 --- a/drivers/staging/iio/iio_simple_dummy.h +++ b/drivers/staging/iio/iio_simple_dummy.h @@ -34,9 +34,14 @@ struct iio_dummy_state { int differential_adc_val[2]; int accel_val; int accel_calibbias; + int activity_running; + int activity_walking; const struct iio_dummy_accel_calibscale *accel_calibscale; struct mutex lock; struct iio_dummy_regs *regs; + int steps_enabled; + int steps; + int height; #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS int event_irq; int event_val; diff --git a/drivers/staging/iio/iio_simple_dummy_events.c b/drivers/staging/iio/iio_simple_dummy_events.c index 719dfa5ae7dfb5..ac15a44ba27132 100644 --- a/drivers/staging/iio/iio_simple_dummy_events.c +++ b/drivers/staging/iio/iio_simple_dummy_events.c @@ -72,6 +72,22 @@ int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev, st->event_en = state; else return -EINVAL; + default: + return -EINVAL; + } + break; + case IIO_ACTIVITY: + switch (type) { + case IIO_EV_TYPE_THRESH: + st->event_en = state; + break; + default: + return -EINVAL; + } + case IIO_STEPS: + switch (type) { + case IIO_EV_TYPE_INSTANCE: + st->event_en = state; break; default: return -EINVAL; @@ -161,6 +177,33 @@ static irqreturn_t iio_simple_dummy_event_handler(int irq, void *private) IIO_EV_TYPE_THRESH, 0, 0, 0), iio_get_time_ns()); break; + case 1: + if (st->activity_running > st->event_val) + iio_push_event(indio_dev, + IIO_EVENT_CODE(IIO_ACTIVITY, 0, + IIO_MOD_RUNNING, + IIO_EV_DIR_RISING, + IIO_EV_TYPE_THRESH, + 0, 0, 0), + iio_get_time_ns()); + break; + case 2: + if (st->activity_walking < st->event_val) + iio_push_event(indio_dev, + IIO_EVENT_CODE(IIO_ACTIVITY, 0, + IIO_MOD_WALKING, + IIO_EV_DIR_FALLING, + IIO_EV_TYPE_THRESH, + 0, 0, 0), + iio_get_time_ns()); + break; + case 3: + iio_push_event(indio_dev, + IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD, + IIO_EV_DIR_NONE, + IIO_EV_TYPE_INSTANCE, 0, 0, 0), + iio_get_time_ns()); + break; default: break; } From 282a5663930ba79af9ec38884580c140fedf8aaa Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Mon, 10 Nov 2014 14:45:35 +0200 Subject: [PATCH 0023/3023] iio: event_monitor: Add support for new channel types We have the following testing scenario: $ insmod iio_dummy_evgen.ko $ insmod iio_dummy.ko ./iio_event_monitor /dev/iio:device0 Event: time: 1412786467971335337, type: activity(running), channel: 0, evtype: thresh, direction: rising Event: time: 1412786530792974091, type: activity(walking), channel: 0, evtype: thresh, direction: falling Event: time: 1412764319184761765, type: steps, channel: 0, evtype: instance $ echo 1 > /sys/bus/iio/devices/iio_evgen/poke_ev0 $ echo 2 > /sys/bus/iio/devices/iio_evgen/poke_ev0 $ echo 3 > /sys/bus/iio/devices/iio_evgen/poke_ev0 Signed-off-by: Irina Tirdea Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- .../iio/Documentation/iio_event_monitor.c | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/staging/iio/Documentation/iio_event_monitor.c b/drivers/staging/iio/Documentation/iio_event_monitor.c index 940ed2399e73f6..def236abcb3e12 100644 --- a/drivers/staging/iio/Documentation/iio_event_monitor.c +++ b/drivers/staging/iio/Documentation/iio_event_monitor.c @@ -49,6 +49,8 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_CCT] = "cct", [IIO_PRESSURE] = "pressure", [IIO_HUMIDITYRELATIVE] = "humidityrelative", + [IIO_ACTIVITY] = "activity", + [IIO_STEPS] = "steps", }; static const char * const iio_ev_type_text[] = { @@ -57,6 +59,7 @@ static const char * const iio_ev_type_text[] = { [IIO_EV_TYPE_ROC] = "roc", [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive", [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive", + [IIO_EV_TYPE_INSTANCE] = "instance", }; static const char * const iio_ev_dir_text[] = { @@ -92,6 +95,10 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_NORTH_TRUE] = "from_north_true", [IIO_MOD_NORTH_MAGN_TILT_COMP] = "from_north_magnetic_tilt_comp", [IIO_MOD_NORTH_TRUE_TILT_COMP] = "from_north_true_tilt_comp", + [IIO_MOD_RUNNING] = "running", + [IIO_MOD_JOGGING] = "jogging", + [IIO_MOD_WALKING] = "walking", + [IIO_MOD_STILL] = "still", }; static bool event_is_known(struct iio_event_data *event) @@ -121,6 +128,8 @@ static bool event_is_known(struct iio_event_data *event) case IIO_CCT: case IIO_PRESSURE: case IIO_HUMIDITYRELATIVE: + case IIO_ACTIVITY: + case IIO_STEPS: break; default: return false; @@ -154,6 +163,10 @@ static bool event_is_known(struct iio_event_data *event) case IIO_MOD_NORTH_TRUE: case IIO_MOD_NORTH_MAGN_TILT_COMP: case IIO_MOD_NORTH_TRUE_TILT_COMP: + case IIO_MOD_RUNNING: + case IIO_MOD_JOGGING: + case IIO_MOD_WALKING: + case IIO_MOD_STILL: break; default: return false; @@ -165,6 +178,7 @@ static bool event_is_known(struct iio_event_data *event) case IIO_EV_TYPE_ROC: case IIO_EV_TYPE_THRESH_ADAPTIVE: case IIO_EV_TYPE_MAG_ADAPTIVE: + case IIO_EV_TYPE_INSTANCE: break; default: return false; @@ -174,6 +188,7 @@ static bool event_is_known(struct iio_event_data *event) case IIO_EV_DIR_EITHER: case IIO_EV_DIR_RISING: case IIO_EV_DIR_FALLING: + case IIO_EV_DIR_NONE: break; default: return false; @@ -214,9 +229,11 @@ static void print_event(struct iio_event_data *event) else if (chan >= 0) printf("channel: %d, ", chan); - printf("evtype: %s, direction: %s\n", - iio_ev_type_text[ev_type], - iio_ev_dir_text[dir]); + printf("evtype: %s", iio_ev_type_text[ev_type]); + + if (dir != IIO_EV_DIR_NONE) + printf(", direction: %s", iio_ev_dir_text[dir]); + printf("\n"); } int main(int argc, char **argv) From 56ae98a20591fcb45c6161fc80cf213e47b8ac04 Mon Sep 17 00:00:00 2001 From: Zachary Warren Date: Sat, 22 Nov 2014 22:19:31 +1100 Subject: [PATCH 0024/3023] drivers:staging:iio: fix checkpatch complaint about space before comma Fixes: drivers/staging/iio/adc/ad7192.c:615: ERROR: space prohibited before that ',' drivers/staging/iio/meter/ade7759.c:119: ERROR: space prohibited before that ',' Signed-off-by: Zachary Warren Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7192.c | 2 +- drivers/staging/iio/meter/ade7759.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index f6526aa22e8a15..6f8ce6c6574bab 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -612,7 +612,7 @@ static int ad7192_probe(struct spi_device *spi) const struct ad7192_platform_data *pdata = spi->dev.platform_data; struct ad7192_state *st; struct iio_dev *indio_dev; - int ret , voltage_uv = 0; + int ret, voltage_uv = 0; if (!pdata) { dev_err(&spi->dev, "no platform data?\n"); diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c index 7d217430616a3a..b0c7dbc8a4283c 100644 --- a/drivers/staging/iio/meter/ade7759.c +++ b/drivers/staging/iio/meter/ade7759.c @@ -116,7 +116,7 @@ static int ade7759_spi_read_reg_40(struct device *dev, mutex_lock(&st->buf_lock); st->tx[0] = ADE7759_READ_REG(reg_address); - memset(&st->tx[1], 0 , 5); + memset(&st->tx[1], 0, 5); ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { From 71222bf5412c78d96bf73d09475d3077ce0789f8 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Fri, 21 Nov 2014 10:45:47 -0800 Subject: [PATCH 0025/3023] iio: ak8975: minor fixes Fixes code duplication, return of function. Check client->irq properly when setting up optional irq handler. Signed-off-by: Gwendal Grignou Reviewed-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/ak8975.c | 35 +++++++++++++------------------ 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index bf5ef077e791df..4e69480e67b5c1 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -64,10 +64,10 @@ #define AK8975_REG_CNTL 0x0A #define AK8975_REG_CNTL_MODE_SHIFT 0 #define AK8975_REG_CNTL_MODE_MASK (0xF << AK8975_REG_CNTL_MODE_SHIFT) -#define AK8975_REG_CNTL_MODE_POWER_DOWN 0 -#define AK8975_REG_CNTL_MODE_ONCE 1 -#define AK8975_REG_CNTL_MODE_SELF_TEST 8 -#define AK8975_REG_CNTL_MODE_FUSE_ROM 0xF +#define AK8975_REG_CNTL_MODE_POWER_DOWN 0x00 +#define AK8975_REG_CNTL_MODE_ONCE 0x01 +#define AK8975_REG_CNTL_MODE_SELF_TEST 0x08 +#define AK8975_REG_CNTL_MODE_FUSE_ROM 0x0F #define AK8975_REG_RSVC 0x0B #define AK8975_REG_ASTC 0x0C @@ -166,8 +166,8 @@ static int ak8975_setup_irq(struct ak8975_data *data) irq = gpio_to_irq(data->eoc_gpio); rc = devm_request_irq(&client->dev, irq, ak8975_irq_handler, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, - dev_name(&client->dev), data); + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + dev_name(&client->dev), data); if (rc < 0) { dev_err(&client->dev, "irq %d request failed, (gpio %d): %d\n", @@ -231,8 +231,12 @@ static int ak8975_setup(struct i2c_client *client) AK8975_REG_CNTL_MODE_POWER_DOWN, AK8975_REG_CNTL_MODE_MASK, AK8975_REG_CNTL_MODE_SHIFT); + if (ret < 0) { + dev_err(&client->dev, "Error in setting power-down mode\n"); + return ret; + } - if (data->eoc_gpio > 0 || client->irq) { + if (data->eoc_gpio > 0 || client->irq > 0) { ret = ak8975_setup_irq(data); if (ret < 0) { dev_err(&client->dev, @@ -241,11 +245,6 @@ static int ak8975_setup(struct i2c_client *client) } } - if (ret < 0) { - dev_err(&client->dev, "Error in setting power-down mode\n"); - return ret; - } - /* * Precalculate scale factor (in Gauss units) for each axis and * store in the device data. @@ -550,24 +549,18 @@ static int ak8975_probe(struct i2c_client *client, /* Perform some basic start-of-day setup of the device. */ err = ak8975_setup(client); if (err < 0) { - dev_err(&client->dev, "AK8975 initialization fails\n"); + dev_err(&client->dev, "%s initialization fails\n", name); return err; } - data->client = client; mutex_init(&data->lock); - data->eoc_gpio = eoc_gpio; indio_dev->dev.parent = &client->dev; indio_dev->channels = ak8975_channels; indio_dev->num_channels = ARRAY_SIZE(ak8975_channels); indio_dev->info = &ak8975_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->name = name; - err = devm_iio_device_register(&client->dev, indio_dev); - if (err < 0) - return err; - - return 0; + return devm_iio_device_register(&client->dev, indio_dev); } static const struct i2c_device_id ak8975_id[] = { @@ -588,7 +581,7 @@ MODULE_DEVICE_TABLE(of, ak8975_of_match); static struct i2c_driver ak8975_driver = { .driver = { .name = "ak8975", - .of_match_table = ak8975_of_match, + .of_match_table = of_match_ptr(ak8975_of_match), .acpi_match_table = ACPI_PTR(ak_acpi_match), }, .probe = ak8975_probe, From 9216ed294053be68a673754a0f8da88aa7fb7941 Mon Sep 17 00:00:00 2001 From: Oded Gabbay Date: Mon, 12 Jan 2015 22:34:21 +0200 Subject: [PATCH 0026/3023] drm/amdkfd: Don't BUG on freeing GART sub-allocation Instead of creating a BUG if trying to free a NULL GART sub-allocation object, just return 0 (success). This is done to mirror behavior of kfree. Signed-off-by: Oded Gabbay --- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 24b37ffad5c6bf..a23ed2440080ea 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -511,7 +511,10 @@ int kfd_gtt_sa_free(struct kfd_dev *kfd, struct kfd_mem_obj *mem_obj) unsigned int bit; BUG_ON(!kfd); - BUG_ON(!mem_obj); + + /* Act like kfree when trying to free a NULL object */ + if (!mem_obj) + return 0; pr_debug("kfd: free mem_obj = %p, range_start = %d, range_end = %d\n", mem_obj, mem_obj->range_start, mem_obj->range_end); From 45c9a5e4297b9a07d94ff8195ff6f21ba3581ad6 Mon Sep 17 00:00:00 2001 From: Oded Gabbay Date: Mon, 12 Jan 2015 14:26:10 +0200 Subject: [PATCH 0027/3023] drm/amdkfd: Encapsulate DQM functions in ops structure This patch does some re-org on the device_queue_manager structure. It takes out all the function pointers from the structure and puts them in a new structure, called device_queue_manager_ops. Then, it puts an instance of that structure inside device_queue_manager. This re-org is done to prepare the DQM module to support more than one AMD APU (Kaveri). Signed-off-by: Oded Gabbay Reviewed-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 6 +- .../drm/amd/amdkfd/kfd_device_queue_manager.c | 68 +++++++++---------- .../drm/amd/amdkfd/kfd_device_queue_manager.h | 25 ++++--- drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c | 2 +- .../amd/amdkfd/kfd_process_queue_manager.c | 16 +++-- 6 files changed, 65 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index b008fd67ace9ea..38b6150a19eeb5 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -439,7 +439,7 @@ static long kfd_ioctl_set_memory_policy(struct file *filep, (args.alternate_policy == KFD_IOC_CACHE_POLICY_COHERENT) ? cache_policy_coherent : cache_policy_noncoherent; - if (!dev->dqm->set_cache_memory_policy(dev->dqm, + if (!dev->dqm->ops.set_cache_memory_policy(dev->dqm, &pdd->qpd, default_policy, alternate_policy, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index a23ed2440080ea..a770ec6f22cad2 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -253,7 +253,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, goto device_queue_manager_error; } - if (kfd->dqm->start(kfd->dqm) != 0) { + if (kfd->dqm->ops.start(kfd->dqm) != 0) { dev_err(kfd_device, "Error starting queuen manager for device (%x:%x)\n", kfd->pdev->vendor, kfd->pdev->device); @@ -307,7 +307,7 @@ void kgd2kfd_suspend(struct kfd_dev *kfd) BUG_ON(kfd == NULL); if (kfd->init_complete) { - kfd->dqm->stop(kfd->dqm); + kfd->dqm->ops.stop(kfd->dqm); amd_iommu_set_invalidate_ctx_cb(kfd->pdev, NULL); amd_iommu_free_device(kfd->pdev); } @@ -328,7 +328,7 @@ int kgd2kfd_resume(struct kfd_dev *kfd) return -ENXIO; amd_iommu_set_invalidate_ctx_cb(kfd->pdev, iommu_pasid_shutdown_callback); - kfd->dqm->start(kfd->dqm); + kfd->dqm->ops.start(kfd->dqm); } return 0; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index c83f011534401e..12c84488551e80 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -271,7 +271,7 @@ static int create_compute_queue_nocpsch(struct device_queue_manager *dqm, BUG_ON(!dqm || !q || !qpd); - mqd = dqm->get_mqd_manager(dqm, KFD_MQD_TYPE_COMPUTE); + mqd = dqm->ops.get_mqd_manager(dqm, KFD_MQD_TYPE_COMPUTE); if (mqd == NULL) return -ENOMEM; @@ -305,14 +305,14 @@ static int destroy_queue_nocpsch(struct device_queue_manager *dqm, mutex_lock(&dqm->lock); if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE) { - mqd = dqm->get_mqd_manager(dqm, KFD_MQD_TYPE_COMPUTE); + mqd = dqm->ops.get_mqd_manager(dqm, KFD_MQD_TYPE_COMPUTE); if (mqd == NULL) { retval = -ENOMEM; goto out; } deallocate_hqd(dqm, q); } else if (q->properties.type == KFD_QUEUE_TYPE_SDMA) { - mqd = dqm->get_mqd_manager(dqm, KFD_MQD_TYPE_SDMA); + mqd = dqm->ops.get_mqd_manager(dqm, KFD_MQD_TYPE_SDMA); if (mqd == NULL) { retval = -ENOMEM; goto out; @@ -348,7 +348,7 @@ static int update_queue(struct device_queue_manager *dqm, struct queue *q) BUG_ON(!dqm || !q || !q->mqd); mutex_lock(&dqm->lock); - mqd = dqm->get_mqd_manager(dqm, q->properties.type); + mqd = dqm->ops.get_mqd_manager(dqm, q->properties.type); if (mqd == NULL) { mutex_unlock(&dqm->lock); return -ENOMEM; @@ -515,7 +515,7 @@ static int init_pipelines(struct device_queue_manager *dqm, memset(hpdptr, 0, CIK_HPD_EOP_BYTES * pipes_num); - mqd = dqm->get_mqd_manager(dqm, KFD_MQD_TYPE_COMPUTE); + mqd = dqm->ops.get_mqd_manager(dqm, KFD_MQD_TYPE_COMPUTE); if (mqd == NULL) { kfd_gtt_sa_free(dqm->dev, dqm->pipeline_mem); return -ENOMEM; @@ -646,7 +646,7 @@ static int create_sdma_queue_nocpsch(struct device_queue_manager *dqm, struct mqd_manager *mqd; int retval; - mqd = dqm->get_mqd_manager(dqm, KFD_MQD_TYPE_SDMA); + mqd = dqm->ops.get_mqd_manager(dqm, KFD_MQD_TYPE_SDMA); if (!mqd) return -ENOMEM; @@ -849,7 +849,7 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q, if (q->properties.type == KFD_QUEUE_TYPE_SDMA) select_sdma_engine_id(q); - mqd = dqm->get_mqd_manager(dqm, + mqd = dqm->ops.get_mqd_manager(dqm, get_mqd_type_from_queue_type(q->properties.type)); if (mqd == NULL) { @@ -994,7 +994,7 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm, /* remove queue from list to prevent rescheduling after preemption */ mutex_lock(&dqm->lock); - mqd = dqm->get_mqd_manager(dqm, + mqd = dqm->ops.get_mqd_manager(dqm, get_mqd_type_from_queue_type(q->properties.type)); if (!mqd) { retval = -ENOMEM; @@ -1116,40 +1116,40 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_dev *dev) case KFD_SCHED_POLICY_HWS: case KFD_SCHED_POLICY_HWS_NO_OVERSUBSCRIPTION: /* initialize dqm for cp scheduling */ - dqm->create_queue = create_queue_cpsch; - dqm->initialize = initialize_cpsch; - dqm->start = start_cpsch; - dqm->stop = stop_cpsch; - dqm->destroy_queue = destroy_queue_cpsch; - dqm->update_queue = update_queue; - dqm->get_mqd_manager = get_mqd_manager_nocpsch; - dqm->register_process = register_process_nocpsch; - dqm->unregister_process = unregister_process_nocpsch; - dqm->uninitialize = uninitialize_nocpsch; - dqm->create_kernel_queue = create_kernel_queue_cpsch; - dqm->destroy_kernel_queue = destroy_kernel_queue_cpsch; - dqm->set_cache_memory_policy = set_cache_memory_policy; + dqm->ops.create_queue = create_queue_cpsch; + dqm->ops.initialize = initialize_cpsch; + dqm->ops.start = start_cpsch; + dqm->ops.stop = stop_cpsch; + dqm->ops.destroy_queue = destroy_queue_cpsch; + dqm->ops.update_queue = update_queue; + dqm->ops.get_mqd_manager = get_mqd_manager_nocpsch; + dqm->ops.register_process = register_process_nocpsch; + dqm->ops.unregister_process = unregister_process_nocpsch; + dqm->ops.uninitialize = uninitialize_nocpsch; + dqm->ops.create_kernel_queue = create_kernel_queue_cpsch; + dqm->ops.destroy_kernel_queue = destroy_kernel_queue_cpsch; + dqm->ops.set_cache_memory_policy = set_cache_memory_policy; break; case KFD_SCHED_POLICY_NO_HWS: /* initialize dqm for no cp scheduling */ - dqm->start = start_nocpsch; - dqm->stop = stop_nocpsch; - dqm->create_queue = create_queue_nocpsch; - dqm->destroy_queue = destroy_queue_nocpsch; - dqm->update_queue = update_queue; - dqm->get_mqd_manager = get_mqd_manager_nocpsch; - dqm->register_process = register_process_nocpsch; - dqm->unregister_process = unregister_process_nocpsch; - dqm->initialize = initialize_nocpsch; - dqm->uninitialize = uninitialize_nocpsch; - dqm->set_cache_memory_policy = set_cache_memory_policy; + dqm->ops.start = start_nocpsch; + dqm->ops.stop = stop_nocpsch; + dqm->ops.create_queue = create_queue_nocpsch; + dqm->ops.destroy_queue = destroy_queue_nocpsch; + dqm->ops.update_queue = update_queue; + dqm->ops.get_mqd_manager = get_mqd_manager_nocpsch; + dqm->ops.register_process = register_process_nocpsch; + dqm->ops.unregister_process = unregister_process_nocpsch; + dqm->ops.initialize = initialize_nocpsch; + dqm->ops.uninitialize = uninitialize_nocpsch; + dqm->ops.set_cache_memory_policy = set_cache_memory_policy; break; default: BUG(); break; } - if (dqm->initialize(dqm) != 0) { + if (dqm->ops.initialize(dqm) != 0) { kfree(dqm); return NULL; } @@ -1161,7 +1161,7 @@ void device_queue_manager_uninit(struct device_queue_manager *dqm) { BUG_ON(!dqm); - dqm->uninitialize(dqm); + dqm->ops.uninitialize(dqm); kfree(dqm); } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h index 554c06ee8892ef..72d2ca056e1916 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h @@ -46,7 +46,7 @@ struct device_process_node { }; /** - * struct device_queue_manager + * struct device_queue_manager_ops * * @create_queue: Queue creation routine. * @@ -81,15 +81,9 @@ struct device_process_node { * @set_cache_memory_policy: Sets memory policy (cached/ non cached) for the * memory apertures. * - * This struct is a base class for the kfd queues scheduler in the - * device level. The device base class should expose the basic operations - * for queue creation and queue destruction. This base class hides the - * scheduling mode of the driver and the specific implementation of the - * concrete device. This class is the only class in the queues scheduler - * that configures the H/W. */ -struct device_queue_manager { +struct device_queue_manager_ops { int (*create_queue)(struct device_queue_manager *dqm, struct queue *q, struct qcm_process_device *qpd, @@ -124,7 +118,22 @@ struct device_queue_manager { enum cache_policy alternate_policy, void __user *alternate_aperture_base, uint64_t alternate_aperture_size); +}; + +/** + * struct device_queue_manager + * + * This struct is a base class for the kfd queues scheduler in the + * device level. The device base class should expose the basic operations + * for queue creation and queue destruction. This base class hides the + * scheduling mode of the driver and the specific implementation of the + * concrete device. This class is the only class in the queues scheduler + * that configures the H/W. + * + */ +struct device_queue_manager { + struct device_queue_manager_ops ops; struct mqd_manager *mqds[KFD_MQD_TYPE_MAX]; struct packet_manager packets; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c index 773c213f2f9ae6..add0fb4cc6589e 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c @@ -56,7 +56,7 @@ static bool initialize(struct kernel_queue *kq, struct kfd_dev *dev, switch (type) { case KFD_QUEUE_TYPE_DIQ: case KFD_QUEUE_TYPE_HIQ: - kq->mqd = dev->dqm->get_mqd_manager(dev->dqm, + kq->mqd = dev->dqm->ops.get_mqd_manager(dev->dqm, KFD_MQD_TYPE_HIQ); break; default: diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index 948b1ca8e7a242..513eeb6e402a85 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -178,7 +178,7 @@ int pqm_create_queue(struct process_queue_manager *pqm, if (list_empty(&pqm->queues)) { pdd->qpd.pqm = pqm; - dev->dqm->register_process(dev->dqm, &pdd->qpd); + dev->dqm->ops.register_process(dev->dqm, &pdd->qpd); } pqn = kzalloc(sizeof(struct process_queue_node), GFP_KERNEL); @@ -204,7 +204,7 @@ int pqm_create_queue(struct process_queue_manager *pqm, goto err_create_queue; pqn->q = q; pqn->kq = NULL; - retval = dev->dqm->create_queue(dev->dqm, q, &pdd->qpd, + retval = dev->dqm->ops.create_queue(dev->dqm, q, &pdd->qpd, &q->properties.vmid); print_queue(q); break; @@ -217,7 +217,8 @@ int pqm_create_queue(struct process_queue_manager *pqm, kq->queue->properties.queue_id = *qid; pqn->kq = kq; pqn->q = NULL; - retval = dev->dqm->create_kernel_queue(dev->dqm, kq, &pdd->qpd); + retval = dev->dqm->ops.create_kernel_queue(dev->dqm, + kq, &pdd->qpd); break; default: BUG(); @@ -285,13 +286,13 @@ int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid) if (pqn->kq) { /* destroy kernel queue (DIQ) */ dqm = pqn->kq->dev->dqm; - dqm->destroy_kernel_queue(dqm, pqn->kq, &pdd->qpd); + dqm->ops.destroy_kernel_queue(dqm, pqn->kq, &pdd->qpd); kernel_queue_uninit(pqn->kq); } if (pqn->q) { dqm = pqn->q->device->dqm; - retval = dqm->destroy_queue(dqm, &pdd->qpd, pqn->q); + retval = dqm->ops.destroy_queue(dqm, &pdd->qpd, pqn->q); if (retval != 0) return retval; @@ -303,7 +304,7 @@ int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid) clear_bit(qid, pqm->queue_slot_bitmap); if (list_empty(&pqm->queues)) - dqm->unregister_process(dqm, &pdd->qpd); + dqm->ops.unregister_process(dqm, &pdd->qpd); return retval; } @@ -324,7 +325,8 @@ int pqm_update_queue(struct process_queue_manager *pqm, unsigned int qid, pqn->q->properties.queue_percent = p->queue_percent; pqn->q->properties.priority = p->priority; - retval = pqn->q->device->dqm->update_queue(pqn->q->device->dqm, pqn->q); + retval = pqn->q->device->dqm->ops.update_queue(pqn->q->device->dqm, + pqn->q); if (retval != 0) return retval; From a22fc85495575d81c36db24b12f66fd314b7ced1 Mon Sep 17 00:00:00 2001 From: Ben Goz Date: Mon, 12 Jan 2015 14:28:46 +0200 Subject: [PATCH 0028/3023] drm/amdkfd: Add initial VI support for DQM This patch starts to add support for the VI APU in the DQM module. Because most (more than 90%) of the DQM code is shared among AMD's APUs, we chose a design that performs most/all the code in the shared DQM file (kfd_device_queue_manager.c). If there is H/W specific code to be executed, than it is written in an asic-specific extension function for that H/W. That asic-specific extension function is called from the shared function at the appropriate time. This requires that for every asic-specific extension function that is implemented in a specific ASIC, there will be an equivalent implementation in ALL ASICs, even if those implementations are just stubs. That way we achieve: - Maintainability: by having one copy of most of the code, we only need to fix bugs at one locations - Readability: very clear what is the shared code and what is done per ASIC - Extensibility: very easy to add new H/W specific files/functions Signed-off-by: Ben Goz Signed-off-by: Oded Gabbay Reviewed-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/Makefile | 1 + .../drm/amd/amdkfd/kfd_device_queue_manager.c | 113 ++++----------- .../drm/amd/amdkfd/kfd_device_queue_manager.h | 11 +- .../amd/amdkfd/kfd_device_queue_manager_cik.c | 135 ++++++++++++++++++ .../amd/amdkfd/kfd_device_queue_manager_vi.c | 64 +++++++++ 5 files changed, 238 insertions(+), 86 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c create mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c diff --git a/drivers/gpu/drm/amd/amdkfd/Makefile b/drivers/gpu/drm/amd/amdkfd/Makefile index bc6053f8b84340..7558683c6935ad 100644 --- a/drivers/gpu/drm/amd/amdkfd/Makefile +++ b/drivers/gpu/drm/amd/amdkfd/Makefile @@ -10,6 +10,7 @@ amdkfd-y := kfd_module.o kfd_device.o kfd_chardev.o kfd_topology.o \ kfd_mqd_manager_cik.o kfd_mqd_manager_vi.o \ kfd_kernel_queue.o kfd_packet_manager.o \ kfd_process_queue_manager.o kfd_device_queue_manager.o \ + kfd_device_queue_manager_cik.o kfd_device_queue_manager_vi.o \ kfd_interrupt.o obj-$(CONFIG_HSA_AMD) += amdkfd.o diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 12c84488551e80..b2016245073e16 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -61,7 +61,7 @@ enum KFD_MQD_TYPE get_mqd_type_from_queue_type(enum kfd_queue_type type) return KFD_MQD_TYPE_CP; } -static inline unsigned int get_pipes_num(struct device_queue_manager *dqm) +inline unsigned int get_pipes_num(struct device_queue_manager *dqm) { BUG_ON(!dqm || !dqm->dev); return dqm->dev->shared_resources.compute_pipe_count; @@ -78,7 +78,7 @@ static inline unsigned int get_pipes_num_cpsch(void) return PIPE_PER_ME_CP_SCHEDULING; } -static inline unsigned int +inline unsigned int get_sh_mem_bases_nybble_64(struct kfd_process_device *pdd) { uint32_t nybble; @@ -88,7 +88,7 @@ get_sh_mem_bases_nybble_64(struct kfd_process_device *pdd) return nybble; } -static inline unsigned int get_sh_mem_bases_32(struct kfd_process_device *pdd) +inline unsigned int get_sh_mem_bases_32(struct kfd_process_device *pdd) { unsigned int shared_base; @@ -97,41 +97,7 @@ static inline unsigned int get_sh_mem_bases_32(struct kfd_process_device *pdd) return shared_base; } -static uint32_t compute_sh_mem_bases_64bit(unsigned int top_address_nybble); -static void init_process_memory(struct device_queue_manager *dqm, - struct qcm_process_device *qpd) -{ - struct kfd_process_device *pdd; - unsigned int temp; - - BUG_ON(!dqm || !qpd); - - pdd = qpd_to_pdd(qpd); - - /* check if sh_mem_config register already configured */ - if (qpd->sh_mem_config == 0) { - qpd->sh_mem_config = - ALIGNMENT_MODE(SH_MEM_ALIGNMENT_MODE_UNALIGNED) | - DEFAULT_MTYPE(MTYPE_NONCACHED) | - APE1_MTYPE(MTYPE_NONCACHED); - qpd->sh_mem_ape1_limit = 0; - qpd->sh_mem_ape1_base = 0; - } - - if (qpd->pqm->process->is_32bit_user_mode) { - temp = get_sh_mem_bases_32(pdd); - qpd->sh_mem_bases = SHARED_BASE(temp); - qpd->sh_mem_config |= PTR32; - } else { - temp = get_sh_mem_bases_nybble_64(pdd); - qpd->sh_mem_bases = compute_sh_mem_bases_64bit(temp); - } - - pr_debug("kfd: is32bit process: %d sh_mem_bases nybble: 0x%X and register 0x%X\n", - qpd->pqm->process->is_32bit_user_mode, temp, qpd->sh_mem_bases); -} - -static void program_sh_mem_settings(struct device_queue_manager *dqm, +void program_sh_mem_settings(struct device_queue_manager *dqm, struct qcm_process_device *qpd) { return kfd2kgd->program_sh_mem_settings(dqm->dev->kgd, qpd->vmid, @@ -391,6 +357,7 @@ static int register_process_nocpsch(struct device_queue_manager *dqm, struct qcm_process_device *qpd) { struct device_process_node *n; + int retval; BUG_ON(!dqm || !qpd); @@ -405,12 +372,13 @@ static int register_process_nocpsch(struct device_queue_manager *dqm, mutex_lock(&dqm->lock); list_add(&n->list, &dqm->queues); - init_process_memory(dqm, qpd); + retval = dqm->ops_asic_specific.register_process(dqm, qpd); + dqm->processes_count++; mutex_unlock(&dqm->lock); - return 0; + return retval; } static int unregister_process_nocpsch(struct device_queue_manager *dqm, @@ -455,34 +423,7 @@ set_pasid_vmid_mapping(struct device_queue_manager *dqm, unsigned int pasid, vmid); } -static uint32_t compute_sh_mem_bases_64bit(unsigned int top_address_nybble) -{ - /* In 64-bit mode, we can only control the top 3 bits of the LDS, - * scratch and GPUVM apertures. - * The hardware fills in the remaining 59 bits according to the - * following pattern: - * LDS: X0000000'00000000 - X0000001'00000000 (4GB) - * Scratch: X0000001'00000000 - X0000002'00000000 (4GB) - * GPUVM: Y0010000'00000000 - Y0020000'00000000 (1TB) - * - * (where X/Y is the configurable nybble with the low-bit 0) - * - * LDS and scratch will have the same top nybble programmed in the - * top 3 bits of SH_MEM_BASES.PRIVATE_BASE. - * GPUVM can have a different top nybble programmed in the - * top 3 bits of SH_MEM_BASES.SHARED_BASE. - * We don't bother to support different top nybbles - * for LDS/Scratch and GPUVM. - */ - - BUG_ON((top_address_nybble & 1) || top_address_nybble > 0xE || - top_address_nybble == 0); - - return PRIVATE_BASE(top_address_nybble << 12) | - SHARED_BASE(top_address_nybble << 12); -} - -static int init_pipelines(struct device_queue_manager *dqm, +int init_pipelines(struct device_queue_manager *dqm, unsigned int pipes_num, unsigned int first_pipe) { void *hpdptr; @@ -715,7 +656,7 @@ static int initialize_cpsch(struct device_queue_manager *dqm) dqm->queue_count = dqm->processes_count = 0; dqm->sdma_queue_count = 0; dqm->active_runlist = false; - retval = init_pipelines(dqm, get_pipes_num(dqm), 0); + retval = dqm->ops_asic_specific.initialize(dqm); if (retval != 0) goto fail_init_pipelines; @@ -1035,8 +976,7 @@ static bool set_cache_memory_policy(struct device_queue_manager *dqm, void __user *alternate_aperture_base, uint64_t alternate_aperture_size) { - uint32_t default_mtype; - uint32_t ape1_mtype; + bool retval; pr_debug("kfd: In func %s\n", __func__); @@ -1073,18 +1013,13 @@ static bool set_cache_memory_policy(struct device_queue_manager *dqm, qpd->sh_mem_ape1_limit = limit >> 16; } - default_mtype = (default_policy == cache_policy_coherent) ? - MTYPE_NONCACHED : - MTYPE_CACHED; - - ape1_mtype = (alternate_policy == cache_policy_coherent) ? - MTYPE_NONCACHED : - MTYPE_CACHED; - - qpd->sh_mem_config = (qpd->sh_mem_config & PTR32) - | ALIGNMENT_MODE(SH_MEM_ALIGNMENT_MODE_UNALIGNED) - | DEFAULT_MTYPE(default_mtype) - | APE1_MTYPE(ape1_mtype); + retval = dqm->ops_asic_specific.set_cache_memory_policy( + dqm, + qpd, + default_policy, + alternate_policy, + alternate_aperture_base, + alternate_aperture_size); if ((sched_policy == KFD_SCHED_POLICY_NO_HWS) && (qpd->vmid != 0)) program_sh_mem_settings(dqm, qpd); @@ -1094,7 +1029,7 @@ static bool set_cache_memory_policy(struct device_queue_manager *dqm, qpd->sh_mem_ape1_limit); mutex_unlock(&dqm->lock); - return true; + return retval; out: mutex_unlock(&dqm->lock); @@ -1107,6 +1042,8 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_dev *dev) BUG_ON(!dev); + pr_debug("kfd: loading device queue manager\n"); + dqm = kzalloc(sizeof(struct device_queue_manager), GFP_KERNEL); if (!dqm) return NULL; @@ -1149,6 +1086,13 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_dev *dev) break; } + switch (dev->device_info->asic_family) { + case CHIP_CARRIZO: + device_queue_manager_init_vi(&dqm->ops_asic_specific); + case CHIP_KAVERI: + device_queue_manager_init_cik(&dqm->ops_asic_specific); + } + if (dqm->ops.initialize(dqm) != 0) { kfree(dqm); return NULL; @@ -1164,4 +1108,3 @@ void device_queue_manager_uninit(struct device_queue_manager *dqm) dqm->ops.uninitialize(dqm); kfree(dqm); } - diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h index 72d2ca056e1916..19347956eeb9c9 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h @@ -134,6 +134,7 @@ struct device_queue_manager_ops { struct device_queue_manager { struct device_queue_manager_ops ops; + struct device_queue_manager_ops ops_asic_specific; struct mqd_manager *mqds[KFD_MQD_TYPE_MAX]; struct packet_manager packets; @@ -155,6 +156,14 @@ struct device_queue_manager { bool active_runlist; }; - +void device_queue_manager_init_cik(struct device_queue_manager_ops *ops); +void device_queue_manager_init_vi(struct device_queue_manager_ops *ops); +void program_sh_mem_settings(struct device_queue_manager *dqm, + struct qcm_process_device *qpd); +inline unsigned int get_sh_mem_bases_32(struct kfd_process_device *qpd); +inline unsigned int get_sh_mem_bases_nybble_64(struct kfd_process_device *pdd); +int init_pipelines(struct device_queue_manager *dqm, + unsigned int pipes_num, unsigned int first_pipe); +inline unsigned int get_pipes_num(struct device_queue_manager *dqm); #endif /* KFD_DEVICE_QUEUE_MANAGER_H_ */ diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c new file mode 100644 index 00000000000000..6b072466e2a6f6 --- /dev/null +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c @@ -0,0 +1,135 @@ +/* + * Copyright 2014 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "kfd_device_queue_manager.h" +#include "cik_regs.h" + +static bool set_cache_memory_policy_cik(struct device_queue_manager *dqm, + struct qcm_process_device *qpd, + enum cache_policy default_policy, + enum cache_policy alternate_policy, + void __user *alternate_aperture_base, + uint64_t alternate_aperture_size); +static int register_process_cik(struct device_queue_manager *dqm, + struct qcm_process_device *qpd); +static int initialize_cpsch_cik(struct device_queue_manager *dqm); + +void device_queue_manager_init_cik(struct device_queue_manager_ops *ops) +{ + ops->set_cache_memory_policy = set_cache_memory_policy_cik; + ops->register_process = register_process_cik; + ops->initialize = initialize_cpsch_cik; +} + +static uint32_t compute_sh_mem_bases_64bit(unsigned int top_address_nybble) +{ + /* In 64-bit mode, we can only control the top 3 bits of the LDS, + * scratch and GPUVM apertures. + * The hardware fills in the remaining 59 bits according to the + * following pattern: + * LDS: X0000000'00000000 - X0000001'00000000 (4GB) + * Scratch: X0000001'00000000 - X0000002'00000000 (4GB) + * GPUVM: Y0010000'00000000 - Y0020000'00000000 (1TB) + * + * (where X/Y is the configurable nybble with the low-bit 0) + * + * LDS and scratch will have the same top nybble programmed in the + * top 3 bits of SH_MEM_BASES.PRIVATE_BASE. + * GPUVM can have a different top nybble programmed in the + * top 3 bits of SH_MEM_BASES.SHARED_BASE. + * We don't bother to support different top nybbles + * for LDS/Scratch and GPUVM. + */ + + BUG_ON((top_address_nybble & 1) || top_address_nybble > 0xE || + top_address_nybble == 0); + + return PRIVATE_BASE(top_address_nybble << 12) | + SHARED_BASE(top_address_nybble << 12); +} + +static bool set_cache_memory_policy_cik(struct device_queue_manager *dqm, + struct qcm_process_device *qpd, + enum cache_policy default_policy, + enum cache_policy alternate_policy, + void __user *alternate_aperture_base, + uint64_t alternate_aperture_size) +{ + uint32_t default_mtype; + uint32_t ape1_mtype; + + default_mtype = (default_policy == cache_policy_coherent) ? + MTYPE_NONCACHED : + MTYPE_CACHED; + + ape1_mtype = (alternate_policy == cache_policy_coherent) ? + MTYPE_NONCACHED : + MTYPE_CACHED; + + qpd->sh_mem_config = (qpd->sh_mem_config & PTR32) + | ALIGNMENT_MODE(SH_MEM_ALIGNMENT_MODE_UNALIGNED) + | DEFAULT_MTYPE(default_mtype) + | APE1_MTYPE(ape1_mtype); + + return true; +} + +static int register_process_cik(struct device_queue_manager *dqm, + struct qcm_process_device *qpd) +{ + struct kfd_process_device *pdd; + unsigned int temp; + + BUG_ON(!dqm || !qpd); + + pdd = qpd_to_pdd(qpd); + + /* check if sh_mem_config register already configured */ + if (qpd->sh_mem_config == 0) { + qpd->sh_mem_config = + ALIGNMENT_MODE(SH_MEM_ALIGNMENT_MODE_UNALIGNED) | + DEFAULT_MTYPE(MTYPE_NONCACHED) | + APE1_MTYPE(MTYPE_NONCACHED); + qpd->sh_mem_ape1_limit = 0; + qpd->sh_mem_ape1_base = 0; + } + + if (qpd->pqm->process->is_32bit_user_mode) { + temp = get_sh_mem_bases_32(pdd); + qpd->sh_mem_bases = SHARED_BASE(temp); + qpd->sh_mem_config |= PTR32; + } else { + temp = get_sh_mem_bases_nybble_64(pdd); + qpd->sh_mem_bases = compute_sh_mem_bases_64bit(temp); + } + + pr_debug("kfd: is32bit process: %d sh_mem_bases nybble: 0x%X and register 0x%X\n", + qpd->pqm->process->is_32bit_user_mode, temp, qpd->sh_mem_bases); + + return 0; +} + +static int initialize_cpsch_cik(struct device_queue_manager *dqm) +{ + return init_pipelines(dqm, get_pipes_num(dqm), 0); +} diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c new file mode 100644 index 00000000000000..20553dcd257d86 --- /dev/null +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c @@ -0,0 +1,64 @@ +/* + * Copyright 2014 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "kfd_device_queue_manager.h" + +static bool set_cache_memory_policy_vi(struct device_queue_manager *dqm, + struct qcm_process_device *qpd, + enum cache_policy default_policy, + enum cache_policy alternate_policy, + void __user *alternate_aperture_base, + uint64_t alternate_aperture_size); +static int register_process_vi(struct device_queue_manager *dqm, + struct qcm_process_device *qpd); +static int initialize_cpsch_vi(struct device_queue_manager *dqm); + +void device_queue_manager_init_vi(struct device_queue_manager_ops *ops) +{ + pr_warn("amdkfd: VI DQM is not currently supported\n"); + + ops->set_cache_memory_policy = set_cache_memory_policy_vi; + ops->register_process = register_process_vi; + ops->initialize = initialize_cpsch_vi; +} + +static bool set_cache_memory_policy_vi(struct device_queue_manager *dqm, + struct qcm_process_device *qpd, + enum cache_policy default_policy, + enum cache_policy alternate_policy, + void __user *alternate_aperture_base, + uint64_t alternate_aperture_size) +{ + return false; +} + +static int register_process_vi(struct device_queue_manager *dqm, + struct qcm_process_device *qpd) +{ + return -1; +} + +static int initialize_cpsch_vi(struct device_queue_manager *dqm) +{ + return 0; +} From 443fbd5f115feba160a8d7ed6ac708cb91e3b955 Mon Sep 17 00:00:00 2001 From: Oded Gabbay Date: Mon, 12 Jan 2015 15:53:44 +0200 Subject: [PATCH 0029/3023] drm/amdkfd: Encapsulate KQ functions in ops structure This patch does some re-org on the kernel_queue structure. It takes out all the function pointers from the structure and puts them in a new structure, called kernel_queue_ops. Then, it puts an instance of that structure inside kernel_queue. This re-org is done to prepare the KQ module to support more than one AMD APU (Kaveri). Signed-off-by: Oded Gabbay Reviewed-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c | 24 +++++++------- drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.h | 31 +++++++++++++++++-- .../gpu/drm/amd/amdkfd/kfd_packet_manager.c | 26 ++++++++-------- 3 files changed, 54 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c index add0fb4cc6589e..731635dace90fb 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c @@ -293,14 +293,14 @@ struct kernel_queue *kernel_queue_init(struct kfd_dev *dev, if (!kq) return NULL; - kq->initialize = initialize; - kq->uninitialize = uninitialize; - kq->acquire_packet_buffer = acquire_packet_buffer; - kq->submit_packet = submit_packet; - kq->sync_with_hw = sync_with_hw; - kq->rollback_packet = rollback_packet; - - if (kq->initialize(kq, dev, type, KFD_KERNEL_QUEUE_SIZE) == false) { + kq->ops.initialize = initialize; + kq->ops.uninitialize = uninitialize; + kq->ops.acquire_packet_buffer = acquire_packet_buffer; + kq->ops.submit_packet = submit_packet; + kq->ops.sync_with_hw = sync_with_hw; + kq->ops.rollback_packet = rollback_packet; + + if (kq->ops.initialize(kq, dev, type, KFD_KERNEL_QUEUE_SIZE) == false) { pr_err("kfd: failed to init kernel queue\n"); kfree(kq); return NULL; @@ -312,7 +312,7 @@ void kernel_queue_uninit(struct kernel_queue *kq) { BUG_ON(!kq); - kq->uninitialize(kq); + kq->ops.uninitialize(kq); kfree(kq); } @@ -329,12 +329,12 @@ static __attribute__((unused)) void test_kq(struct kfd_dev *dev) kq = kernel_queue_init(dev, KFD_QUEUE_TYPE_HIQ); BUG_ON(!kq); - retval = kq->acquire_packet_buffer(kq, 5, &buffer); + retval = kq->ops.acquire_packet_buffer(kq, 5, &buffer); BUG_ON(retval != 0); for (i = 0; i < 5; i++) buffer[i] = kq->nop_packet; - kq->submit_packet(kq); - kq->sync_with_hw(kq, 1000); + kq->ops.submit_packet(kq); + kq->ops.sync_with_hw(kq, 1000); pr_debug("kfd: ending kernel queue test\n"); } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.h b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.h index dcd2bdb68d44f2..e01b77b2850029 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.h @@ -28,8 +28,31 @@ #include #include "kfd_priv.h" -struct kernel_queue { - /* interface */ +/** + * struct kernel_queue_ops + * + * @initialize: Initialize a kernel queue, including allocations of GART memory + * needed for the queue. + * + * @uninitialize: Uninitialize a kernel queue and free all its memory usages. + * + * @acquire_packet_buffer: Returns a pointer to the location in the kernel + * queue ring buffer where the calling function can write its packet. It is + * Guaranteed that there is enough space for that packet. It also updates the + * pending write pointer to that location so subsequent calls to + * acquire_packet_buffer will get a correct write pointer + * + * @submit_packet: Update the write pointer and doorbell of a kernel queue. + * + * @sync_with_hw: Wait until the write pointer and the read pointer of a kernel + * queue are equal, which means the CP has read all the submitted packets. + * + * @rollback_packet: This routine is called if we failed to build an acquired + * packet for some reason. It just overwrites the pending wptr with the current + * one + * + */ +struct kernel_queue_ops { bool (*initialize)(struct kernel_queue *kq, struct kfd_dev *dev, enum kfd_queue_type type, unsigned int queue_size); void (*uninitialize)(struct kernel_queue *kq); @@ -41,6 +64,10 @@ struct kernel_queue { int (*sync_with_hw)(struct kernel_queue *kq, unsigned long timeout_ms); void (*rollback_packet)(struct kernel_queue *kq); +}; + +struct kernel_queue { + struct kernel_queue_ops ops; /* data */ struct kfd_dev *dev; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c index 3cda952ac2f81b..5fb5c032d5d8d5 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c @@ -348,7 +348,7 @@ int pm_send_set_resources(struct packet_manager *pm, pr_debug("kfd: In func %s\n", __func__); mutex_lock(&pm->lock); - pm->priv_queue->acquire_packet_buffer(pm->priv_queue, + pm->priv_queue->ops.acquire_packet_buffer(pm->priv_queue, sizeof(*packet) / sizeof(uint32_t), (unsigned int **)&packet); if (packet == NULL) { @@ -375,8 +375,8 @@ int pm_send_set_resources(struct packet_manager *pm, packet->queue_mask_lo = lower_32_bits(res->queue_mask); packet->queue_mask_hi = upper_32_bits(res->queue_mask); - pm->priv_queue->submit_packet(pm->priv_queue); - pm->priv_queue->sync_with_hw(pm->priv_queue, KFD_HIQ_TIMEOUT); + pm->priv_queue->ops.submit_packet(pm->priv_queue); + pm->priv_queue->ops.sync_with_hw(pm->priv_queue, KFD_HIQ_TIMEOUT); mutex_unlock(&pm->lock); @@ -402,7 +402,7 @@ int pm_send_runlist(struct packet_manager *pm, struct list_head *dqm_queues) packet_size_dwords = sizeof(struct pm4_runlist) / sizeof(uint32_t); mutex_lock(&pm->lock); - retval = pm->priv_queue->acquire_packet_buffer(pm->priv_queue, + retval = pm->priv_queue->ops.acquire_packet_buffer(pm->priv_queue, packet_size_dwords, &rl_buffer); if (retval != 0) goto fail_acquire_packet_buffer; @@ -412,15 +412,15 @@ int pm_send_runlist(struct packet_manager *pm, struct list_head *dqm_queues) if (retval != 0) goto fail_create_runlist; - pm->priv_queue->submit_packet(pm->priv_queue); - pm->priv_queue->sync_with_hw(pm->priv_queue, KFD_HIQ_TIMEOUT); + pm->priv_queue->ops.submit_packet(pm->priv_queue); + pm->priv_queue->ops.sync_with_hw(pm->priv_queue, KFD_HIQ_TIMEOUT); mutex_unlock(&pm->lock); return retval; fail_create_runlist: - pm->priv_queue->rollback_packet(pm->priv_queue); + pm->priv_queue->ops.rollback_packet(pm->priv_queue); fail_acquire_packet_buffer: mutex_unlock(&pm->lock); fail_create_runlist_ib: @@ -438,7 +438,7 @@ int pm_send_query_status(struct packet_manager *pm, uint64_t fence_address, BUG_ON(!pm || !fence_address); mutex_lock(&pm->lock); - retval = pm->priv_queue->acquire_packet_buffer( + retval = pm->priv_queue->ops.acquire_packet_buffer( pm->priv_queue, sizeof(struct pm4_query_status) / sizeof(uint32_t), (unsigned int **)&packet); @@ -459,8 +459,8 @@ int pm_send_query_status(struct packet_manager *pm, uint64_t fence_address, packet->data_hi = upper_32_bits((uint64_t)fence_value); packet->data_lo = lower_32_bits((uint64_t)fence_value); - pm->priv_queue->submit_packet(pm->priv_queue); - pm->priv_queue->sync_with_hw(pm->priv_queue, KFD_HIQ_TIMEOUT); + pm->priv_queue->ops.submit_packet(pm->priv_queue); + pm->priv_queue->ops.sync_with_hw(pm->priv_queue, KFD_HIQ_TIMEOUT); mutex_unlock(&pm->lock); return 0; @@ -482,7 +482,7 @@ int pm_send_unmap_queue(struct packet_manager *pm, enum kfd_queue_type type, BUG_ON(!pm); mutex_lock(&pm->lock); - retval = pm->priv_queue->acquire_packet_buffer( + retval = pm->priv_queue->ops.acquire_packet_buffer( pm->priv_queue, sizeof(struct pm4_unmap_queues) / sizeof(uint32_t), &buffer); @@ -537,8 +537,8 @@ int pm_send_unmap_queue(struct packet_manager *pm, enum kfd_queue_type type, break; }; - pm->priv_queue->submit_packet(pm->priv_queue); - pm->priv_queue->sync_with_hw(pm->priv_queue, KFD_HIQ_TIMEOUT); + pm->priv_queue->ops.submit_packet(pm->priv_queue); + pm->priv_queue->ops.sync_with_hw(pm->priv_queue, KFD_HIQ_TIMEOUT); mutex_unlock(&pm->lock); return 0; From 6898f0a568742b3d751e82899b8e1b0fe1b134f5 Mon Sep 17 00:00:00 2001 From: Ben Goz Date: Tue, 2 Dec 2014 16:38:57 +0200 Subject: [PATCH 0030/3023] drm/amdkfd: Add initial VI support for KQ This patch starts to add support for the VI APU in the KQ (kernel queue) module. Because most (more than 90%) of the KQ code is shared among AMD's APUs, we chose a design that performs most/all the code in the shared KQ file (kfd_kernel_queue.c). If there is H/W specific code to be executed, than it is written in an asic-specific extension function for that H/W. That asic-specific extension function is called from the shared function at the appropriate time. This requires that for every asic-specific extension function that is implemented in a specific ASIC, there will be an equivalent implementation in ALL ASICs, even if those implementations are just stubs. That way we achieve: - Maintainability: by having one copy of most of the code, we only need to fix bugs at one locations - Readability: very clear what is the shared code and what is done per ASIC - Extensibility: very easy to add new H/W specific files/functions Signed-off-by: Ben Goz Signed-off-by: Oded Gabbay Reviewed-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/Makefile | 3 +- drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c | 21 ++++++- drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.h | 7 +++ .../gpu/drm/amd/amdkfd/kfd_kernel_queue_cik.c | 44 +++++++++++++++ .../gpu/drm/amd/amdkfd/kfd_kernel_queue_vi.c | 56 +++++++++++++++++++ 5 files changed, 127 insertions(+), 4 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue_cik.c create mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue_vi.c diff --git a/drivers/gpu/drm/amd/amdkfd/Makefile b/drivers/gpu/drm/amd/amdkfd/Makefile index 7558683c6935ad..cd09c05ee7e4bc 100644 --- a/drivers/gpu/drm/amd/amdkfd/Makefile +++ b/drivers/gpu/drm/amd/amdkfd/Makefile @@ -8,7 +8,8 @@ amdkfd-y := kfd_module.o kfd_device.o kfd_chardev.o kfd_topology.o \ kfd_pasid.o kfd_doorbell.o kfd_flat_memory.o \ kfd_process.o kfd_queue.o kfd_mqd_manager.o \ kfd_mqd_manager_cik.o kfd_mqd_manager_vi.o \ - kfd_kernel_queue.o kfd_packet_manager.o \ + kfd_kernel_queue.o kfd_kernel_queue_cik.o \ + kfd_kernel_queue_vi.o kfd_packet_manager.o \ kfd_process_queue_manager.o kfd_device_queue_manager.o \ kfd_device_queue_manager_cik.o kfd_device_queue_manager_vi.o \ kfd_interrupt.o diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c index 731635dace90fb..75950ed7a1bce5 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c @@ -73,13 +73,16 @@ static bool initialize(struct kernel_queue *kq, struct kfd_dev *dev, goto err_get_kernel_doorbell; retval = kfd_gtt_sa_allocate(dev, queue_size, &kq->pq); - if (retval != 0) goto err_pq_allocate_vidmem; kq->pq_kernel_addr = kq->pq->cpu_ptr; kq->pq_gpu_addr = kq->pq->gpu_addr; + retval = kq->ops_asic_specific.initialize(kq, dev, type, queue_size); + if (retval == false) + goto err_eop_allocate_vidmem; + retval = kfd_gtt_sa_allocate(dev, sizeof(*kq->rptr_kernel), &kq->rptr_mem); @@ -111,6 +114,8 @@ static bool initialize(struct kernel_queue *kq, struct kfd_dev *dev, prop.queue_address = kq->pq_gpu_addr; prop.read_ptr = (uint32_t *) kq->rptr_gpu_addr; prop.write_ptr = (uint32_t *) kq->wptr_gpu_addr; + prop.eop_ring_buffer_address = kq->eop_gpu_addr; + prop.eop_ring_buffer_size = PAGE_SIZE; if (init_queue(&kq->queue, prop) != 0) goto err_init_queue; @@ -156,6 +161,8 @@ static bool initialize(struct kernel_queue *kq, struct kfd_dev *dev, err_wptr_allocate_vidmem: kfd_gtt_sa_free(dev, kq->rptr_mem); err_rptr_allocate_vidmem: + kfd_gtt_sa_free(dev, kq->eop_mem); +err_eop_allocate_vidmem: kfd_gtt_sa_free(dev, kq->pq); err_pq_allocate_vidmem: pr_err("kfd: error init pq\n"); @@ -182,6 +189,7 @@ static void uninitialize(struct kernel_queue *kq) kfd_gtt_sa_free(kq->dev, kq->rptr_mem); kfd_gtt_sa_free(kq->dev, kq->wptr_mem); + kq->ops_asic_specific.uninitialize(kq); kfd_gtt_sa_free(kq->dev, kq->pq); kfd_release_kernel_doorbell(kq->dev, kq->queue->properties.doorbell_ptr); @@ -300,6 +308,13 @@ struct kernel_queue *kernel_queue_init(struct kfd_dev *dev, kq->ops.sync_with_hw = sync_with_hw; kq->ops.rollback_packet = rollback_packet; + switch (dev->device_info->asic_family) { + case CHIP_CARRIZO: + kernel_queue_init_vi(&kq->ops_asic_specific); + case CHIP_KAVERI: + kernel_queue_init_cik(&kq->ops_asic_specific); + } + if (kq->ops.initialize(kq, dev, type, KFD_KERNEL_QUEUE_SIZE) == false) { pr_err("kfd: failed to init kernel queue\n"); kfree(kq); @@ -324,7 +339,7 @@ static __attribute__((unused)) void test_kq(struct kfd_dev *dev) BUG_ON(!dev); - pr_debug("kfd: starting kernel queue test\n"); + pr_err("kfd: starting kernel queue test\n"); kq = kernel_queue_init(dev, KFD_QUEUE_TYPE_HIQ); BUG_ON(!kq); @@ -336,7 +351,7 @@ static __attribute__((unused)) void test_kq(struct kfd_dev *dev) kq->ops.submit_packet(kq); kq->ops.sync_with_hw(kq, 1000); - pr_debug("kfd: ending kernel queue test\n"); + pr_err("kfd: ending kernel queue test\n"); } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.h b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.h index e01b77b2850029..2659d936ba7321 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.h @@ -68,6 +68,7 @@ struct kernel_queue_ops { struct kernel_queue { struct kernel_queue_ops ops; + struct kernel_queue_ops ops_asic_specific; /* data */ struct kfd_dev *dev; @@ -85,6 +86,9 @@ struct kernel_queue { struct kfd_mem_obj *pq; uint64_t pq_gpu_addr; uint32_t *pq_kernel_addr; + struct kfd_mem_obj *eop_mem; + uint64_t eop_gpu_addr; + uint32_t *eop_kernel_addr; struct kfd_mem_obj *fence_mem_obj; uint64_t fence_gpu_addr; @@ -93,4 +97,7 @@ struct kernel_queue { struct list_head list; }; +void kernel_queue_init_cik(struct kernel_queue_ops *ops); +void kernel_queue_init_vi(struct kernel_queue_ops *ops); + #endif /* KFD_KERNEL_QUEUE_H_ */ diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue_cik.c b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue_cik.c new file mode 100644 index 00000000000000..a90eb440b1fbbb --- /dev/null +++ b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue_cik.c @@ -0,0 +1,44 @@ +/* + * Copyright 2014 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "kfd_kernel_queue.h" + +static bool initialize_cik(struct kernel_queue *kq, struct kfd_dev *dev, + enum kfd_queue_type type, unsigned int queue_size); +static void uninitialize_cik(struct kernel_queue *kq); + +void kernel_queue_init_cik(struct kernel_queue_ops *ops) +{ + ops->initialize = initialize_cik; + ops->uninitialize = uninitialize_cik; +} + +static bool initialize_cik(struct kernel_queue *kq, struct kfd_dev *dev, + enum kfd_queue_type type, unsigned int queue_size) +{ + return true; +} + +static void uninitialize_cik(struct kernel_queue *kq) +{ +} diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue_vi.c b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue_vi.c new file mode 100644 index 00000000000000..f1d48281e322ab --- /dev/null +++ b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue_vi.c @@ -0,0 +1,56 @@ +/* + * Copyright 2014 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "kfd_kernel_queue.h" + +static bool initialize_vi(struct kernel_queue *kq, struct kfd_dev *dev, + enum kfd_queue_type type, unsigned int queue_size); +static void uninitialize_vi(struct kernel_queue *kq); + +void kernel_queue_init_vi(struct kernel_queue_ops *ops) +{ + ops->initialize = initialize_vi; + ops->uninitialize = uninitialize_vi; +} + +static bool initialize_vi(struct kernel_queue *kq, struct kfd_dev *dev, + enum kfd_queue_type type, unsigned int queue_size) +{ + int retval; + + retval = kfd_gtt_sa_allocate(dev, PAGE_SIZE, &kq->eop_mem); + if (retval != 0) + return false; + + kq->eop_gpu_addr = kq->eop_mem->gpu_addr; + kq->eop_kernel_addr = kq->eop_mem->cpu_ptr; + + memset(kq->eop_kernel_addr, 0, PAGE_SIZE); + + return true; +} + +static void uninitialize_vi(struct kernel_queue *kq) +{ + kfd_gtt_sa_free(kq->dev, kq->eop_mem); +} From 3148ade72806e7bd1e4784798c2d5645dd13618a Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Fri, 21 Nov 2014 16:14:56 +0000 Subject: [PATCH 0031/3023] drm/i915/skl: Read out crtl1 for eDP/DPLL0 v2: Put the DPLL0 state readout in skylake_get_ddi_pll(), closer to where the PLL assignement read out is done rather than the frequency readout function. (Daniel) v3: Remove stray new line (Damien) Add Paulo's r-b tag for v1 Reviewed-by: Paulo Zanoni (v1) Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 6289babd03b05a..9d38423b69c1a0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8058,12 +8058,21 @@ static void skylake_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, struct intel_crtc_config *pipe_config) { - u32 temp; + u32 temp, dpll_ctl1; temp = I915_READ(DPLL_CTRL2) & DPLL_CTRL2_DDI_CLK_SEL_MASK(port); pipe_config->ddi_pll_sel = temp >> (port * 3 + 1); switch (pipe_config->ddi_pll_sel) { + case SKL_DPLL0: + /* + * On SKL the eDP DPLL (DPLL0 as we don't use SSC) is not part + * of the shared DPLL framework and thus needs to be read out + * separately + */ + dpll_ctl1 = I915_READ(DPLL_CTRL1); + pipe_config->dpll_hw_state.ctrl1 = dpll_ctl1 & 0x3f; + break; case SKL_DPLL1: pipe_config->shared_dpll = DPLL_ID_SKL_DPLL1; break; From ff94456453409e013aadf0fdaa38d6dd339456f4 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Thu, 20 Nov 2014 14:58:16 +0000 Subject: [PATCH 0032/3023] drm/i915/skl: Implement the skl version of MMIO flips MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Because the plane registers are different in Skylake we need to adapt the MMIO code as well. v2: Don't introduce yet another vfunc when the direction is do consolidate the plane updates to use the same code path (Daniel) v3: - Use enum pipe instead of int (Ville) - Also update PLANE_STRIDE when the tiling has changed (Ville) - Put intel_mark_page_flip_active() in the shared code (Damien) v4: - Remove unused variable v5: - Fix whitespace Vs tabs (Ville) Reviewed-by: Ville Syrjälä Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 64 +++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9d38423b69c1a0..d54716655d3240 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9526,22 +9526,50 @@ static bool use_mmio_flip(struct intel_engine_cs *ring, return ring != obj->ring; } -static void intel_do_mmio_flip(struct intel_crtc *intel_crtc) +static void skl_do_mmio_flip(struct intel_crtc *intel_crtc) +{ + struct drm_device *dev = intel_crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_framebuffer *fb = intel_crtc->base.primary->fb; + struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); + struct drm_i915_gem_object *obj = intel_fb->obj; + const enum pipe pipe = intel_crtc->pipe; + u32 ctl, stride; + + ctl = I915_READ(PLANE_CTL(pipe, 0)); + ctl &= ~PLANE_CTL_TILED_MASK; + if (obj->tiling_mode == I915_TILING_X) + ctl |= PLANE_CTL_TILED_X; + + /* + * The stride is either expressed as a multiple of 64 bytes chunks for + * linear buffers or in number of tiles for tiled buffers. + */ + stride = fb->pitches[0] >> 6; + if (obj->tiling_mode == I915_TILING_X) + stride = fb->pitches[0] >> 9; /* X tiles are 512 bytes wide */ + + /* + * Both PLANE_CTL and PLANE_STRIDE are not updated on vblank but on + * PLANE_SURF updates, the update is then guaranteed to be atomic. + */ + I915_WRITE(PLANE_CTL(pipe, 0), ctl); + I915_WRITE(PLANE_STRIDE(pipe, 0), stride); + + I915_WRITE(PLANE_SURF(pipe, 0), intel_crtc->unpin_work->gtt_offset); + POSTING_READ(PLANE_SURF(pipe, 0)); +} + +static void ilk_do_mmio_flip(struct intel_crtc *intel_crtc) { struct drm_device *dev = intel_crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_framebuffer *intel_fb = to_intel_framebuffer(intel_crtc->base.primary->fb); struct drm_i915_gem_object *obj = intel_fb->obj; - bool atomic_update; - u32 start_vbl_count; u32 dspcntr; u32 reg; - intel_mark_page_flip_active(intel_crtc); - - atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count); - reg = DSPCNTR(intel_crtc->plane); dspcntr = I915_READ(reg); @@ -9556,6 +9584,28 @@ static void intel_do_mmio_flip(struct intel_crtc *intel_crtc) intel_crtc->unpin_work->gtt_offset); POSTING_READ(DSPSURF(intel_crtc->plane)); +} + +/* + * XXX: This is the temporary way to update the plane registers until we get + * around to using the usual plane update functions for MMIO flips + */ +static void intel_do_mmio_flip(struct intel_crtc *intel_crtc) +{ + struct drm_device *dev = intel_crtc->base.dev; + bool atomic_update; + u32 start_vbl_count; + + intel_mark_page_flip_active(intel_crtc); + + atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count); + + if (INTEL_INFO(dev)->gen >= 9) + skl_do_mmio_flip(intel_crtc); + else + /* use_mmio_flip() retricts MMIO flips to ilk+ */ + ilk_do_mmio_flip(intel_crtc); + if (atomic_update) intel_pipe_update_end(intel_crtc, start_vbl_count); } From bfd7ebdac3c303ea2ee1abd781ee3fda82321a92 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 14 Nov 2014 08:52:30 -0800 Subject: [PATCH 0033/3023] drm/i915: Parse VBT PSR block. PSR (aka SRD) block is defined at VBT and currently being used. Mainly/At-least to configure the amount of idle_frames require to get back to PSR Entry. Signed-off-by: Rodrigo Vivi Reviewed-by: Durgadoss R Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 16 +++++++++++ drivers/gpu/drm/i915/intel_bios.c | 45 +++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_bios.h | 22 ++++++++++++++- 3 files changed, 82 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bb1892d72efefe..c7f00a452f5599 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1306,6 +1306,13 @@ enum drrs_support_type { SEAMLESS_DRRS_SUPPORT = 2 }; +enum psr_lines_to_wait { + PSR_0_LINES_TO_WAIT = 0, + PSR_1_LINE_TO_WAIT, + PSR_4_LINES_TO_WAIT, + PSR_8_LINES_TO_WAIT +}; + struct intel_vbt_data { struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */ struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */ @@ -1334,6 +1341,15 @@ struct intel_vbt_data { int edp_bpp; struct edp_power_seq edp_pps; + struct { + bool full_link; + bool require_aux_wakeup; + int idle_frames; + enum psr_lines_to_wait lines_to_wait; + int tp1_wakeup_time; + int tp2_tp3_wakeup_time; + } psr; + struct { u16 pwm_freq_hz; bool present; diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index a4bd90f36a0339..3f178258d9f9ce 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -664,6 +664,50 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) } } +static void +parse_psr(struct drm_i915_private *dev_priv, struct bdb_header *bdb) +{ + struct bdb_psr *psr; + struct psr_table *psr_table; + + psr = find_section(bdb, BDB_PSR); + if (!psr) { + DRM_DEBUG_KMS("No PSR BDB found.\n"); + return; + } + + psr_table = &psr->psr_table[panel_type]; + + dev_priv->vbt.psr.full_link = psr_table->full_link; + dev_priv->vbt.psr.require_aux_wakeup = psr_table->require_aux_to_wakeup; + + /* Allowed VBT values goes from 0 to 15 */ + dev_priv->vbt.psr.idle_frames = psr_table->idle_frames < 0 ? 0 : + psr_table->idle_frames > 15 ? 15 : psr_table->idle_frames; + + switch (psr_table->lines_to_wait) { + case 0: + dev_priv->vbt.psr.lines_to_wait = PSR_0_LINES_TO_WAIT; + break; + case 1: + dev_priv->vbt.psr.lines_to_wait = PSR_1_LINE_TO_WAIT; + break; + case 2: + dev_priv->vbt.psr.lines_to_wait = PSR_4_LINES_TO_WAIT; + break; + case 3: + dev_priv->vbt.psr.lines_to_wait = PSR_8_LINES_TO_WAIT; + break; + default: + DRM_DEBUG_KMS("VBT has unknown PSR lines to wait %u\n", + psr_table->lines_to_wait); + break; + } + + dev_priv->vbt.psr.tp1_wakeup_time = psr_table->tp1_wakeup_time; + dev_priv->vbt.psr.tp2_tp3_wakeup_time = psr_table->tp2_tp3_wakeup_time; +} + static u8 *goto_next_sequence(u8 *data, int *size) { u16 len; @@ -1241,6 +1285,7 @@ intel_parse_bios(struct drm_device *dev) parse_device_mapping(dev_priv, bdb); parse_driver_features(dev_priv, bdb); parse_edp(dev_priv, bdb); + parse_psr(dev_priv, bdb); parse_mipi(dev_priv, bdb); parse_ddi_ports(dev_priv, bdb); diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 7603765c91fc0f..de01167d8a51b9 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -80,7 +80,7 @@ struct vbios_data { #define BDB_EXT_MMIO_REGS 6 #define BDB_SWF_IO 7 #define BDB_SWF_MMIO 8 -#define BDB_DOT_CLOCK_TABLE 9 +#define BDB_PSR 9 #define BDB_MODE_REMOVAL_TABLE 10 #define BDB_CHILD_DEVICE_TABLE 11 #define BDB_DRIVER_FEATURES 12 @@ -556,6 +556,26 @@ struct bdb_edp { u16 edp_t3_optimization; } __packed; +struct psr_table { + /* Feature bits */ + u8 full_link:1; + u8 require_aux_to_wakeup:1; + u8 feature_bits_rsvd:6; + + /* Wait times */ + u8 idle_frames:4; + u8 lines_to_wait:3; + u8 wait_times_rsvd:1; + + /* TP wake up time in multiple of 100 */ + u16 tp1_wakeup_time; + u16 tp2_tp3_wakeup_time; +} __packed; + +struct bdb_psr { + struct psr_table psr_table[16]; +} __packed; + void intel_setup_bios(struct drm_device *dev); int intel_parse_bios(struct drm_device *dev); From d44b4dcbd1b44737462b77971d216d21a9413341 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 14 Nov 2014 08:52:31 -0800 Subject: [PATCH 0034/3023] drm/i915: HSW/BDW PSR Set idle_frames = VBT + 1 Let's use VBT + 1 now we parse it. v2: fix subject v3: rebase over intel_psr and without counting on previous fix Cc: Arthur Runyan Signed-off-by: Rodrigo Vivi Reviewed-by: Durgadoss R Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_psr.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 716b8a961eea9a..576568eb075925 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -163,7 +163,12 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp) struct drm_device *dev = dig_port->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; uint32_t max_sleep_time = 0x1f; - uint32_t idle_frames = 1; + /* Lately it was identified that depending on panel idle frame count + * calculated at HW can be off by 1. So let's use what came + * from VBT + 1 and at minimum 2 to be on the safe side. + */ + uint32_t idle_frames = dev_priv->vbt.psr.idle_frames ? + dev_priv->vbt.psr.idle_frames + 1 : 2; uint32_t val = 0x0; const uint32_t link_entry_time = EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES; bool only_standby = false; From 8cc726c9387e751d6081f1083c0ff1fde0ab6071 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 14 Nov 2014 08:52:32 -0800 Subject: [PATCH 0035/3023] drm/i915: PSR get full link off x standby from VBT OEMs can specify if full_link might be always enabled, i.e. only_standby over VBT. Signed-off-by: Rodrigo Vivi Reviewed-by: Durgadoss R Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_psr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 576568eb075925..e706c9d8308487 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -120,7 +120,7 @@ static void intel_psr_enable_sink(struct intel_dp *intel_dp) struct drm_i915_private *dev_priv = dev->dev_private; uint32_t aux_clock_divider; int precharge = 0x3; - bool only_standby = false; + bool only_standby = dev_priv->vbt.psr.full_link; static const uint8_t aux_msg[] = { [0] = DP_AUX_NATIVE_WRITE << 4, [1] = DP_SET_POWER >> 8, From d298ce5e25c1719cc32a2fd9373e1e72c50329f0 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Wed, 19 Nov 2014 07:34:04 -0800 Subject: [PATCH 0036/3023] drm/i915: remove PSR BDW single frame update. Single frame update is a feature available on BDW for PSR that allows Source to send Sink only one frame and get it updated. Usually useful when page flipping. However with our frontbuffer tracking where we force psr exit on flips we don't need this feature. Also after it got added here many workaround was added to documentation to mask some bits when using single frame update. So the safest thing is to just stop using it. v2: Rebase after removing skip aux one and fixing typo on commit message. Reviewed-by: Durgadoss R Signed-off-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_psr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index e706c9d8308487..843762a841a3d6 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -181,7 +181,6 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp) val |= EDP_PSR_TP2_TP3_TIME_0us; val |= EDP_PSR_TP1_TIME_0us; val |= EDP_PSR_SKIP_AUX_EXIT; - val |= IS_BROADWELL(dev) ? BDW_PSR_SINGLE_FRAME : 0; } else val |= EDP_PSR_LINK_DISABLE; From e4d59f6b0f51d0c46fbd7e15a653045ad63161a8 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 20 Nov 2014 02:22:08 -0800 Subject: [PATCH 0037/3023] drm/i915: Remove intel_psr_is_enabled function. This function was in use to check if PSR feature got enabled. However on HSW and BDW we currently force psr exit by disabling EDP_PSR_ENABLE bit at EDP_PSR_CTL(dev). So this function was actually returning the active/inactive state that is different from the enable/disable meaning and had the risk of false negative. But anyway this check with DRRS was dangerous, since DRRS could try to get enabled before PSR gets there. So let's just remove it for now. A proper synchronization mechanism must be implemented later probably using pipe config. Cc: Daniel Vetter Reviewed-by: Durgadoss R Signed-off-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 9 ++------- drivers/gpu/drm/i915/intel_drv.h | 1 - drivers/gpu/drm/i915/intel_psr.c | 10 ---------- 3 files changed, 2 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 5cecc20efa71df..fa509db3e1f928 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4763,14 +4763,9 @@ void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate) } /* - * FIXME: This needs proper synchronization with psr state. But really - * hard to tell without seeing the user of this function of this code. - * Check locking and ordering once that lands. + * FIXME: This needs proper synchronization with psr state for some + * platforms that cannot have PSR and DRRS enabled at the same time. */ - if (INTEL_INFO(dev)->gen < 8 && intel_psr_is_enabled(dev)) { - DRM_DEBUG_KMS("DRRS is disabled as PSR is enabled\n"); - return; - } encoder = intel_attached_encoder(&intel_connector->base); intel_dp = enc_to_intel_dp(&encoder->base); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 25fdbb16d4e0de..5e81f097132c1e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1115,7 +1115,6 @@ void intel_backlight_unregister(struct drm_device *dev); /* intel_psr.c */ -bool intel_psr_is_enabled(struct drm_device *dev); void intel_psr_enable(struct intel_dp *intel_dp); void intel_psr_disable(struct intel_dp *intel_dp); void intel_psr_invalidate(struct drm_device *dev, diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 843762a841a3d6..576ad022222180 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -61,16 +61,6 @@ static bool is_edp_psr(struct intel_dp *intel_dp) return intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED; } -bool intel_psr_is_enabled(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - if (!HAS_PSR(dev)) - return false; - - return I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE; -} - static void intel_psr_write_vsc(struct intel_dp *intel_dp, struct edp_vsc_psr *vsc_psr) { From c8f7df58f711e02b0788b75c054c6d32056ea170 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 14 Nov 2014 08:52:36 -0800 Subject: [PATCH 0038/3023] drm/i915: Add PSR registers for PSR VLV/CHV. Baytrail (Valleyview) and Braswell (Cherryview) uses a complete different implementation of PSR that we currently have supported for Haswell and Broadwell. So let's start by adding registers definitions. I usually don't like commit that adds just registers without using, but after I put all in one commit I realized that no one would want to take the AR to review it so I decided to split in order to make reviewer's life easier. Only last commit in this series will actually enable the PSR on intel enable panel path. But as it happens currently with HSW/BDW the plan is to let it disabled by default (protected by kernel parameter) while we are able to fully validate it. v2: Remove a unused bit definition that isn't used on vlv and reserved on chv as pointed out by Durgadoss. Cc: Durgadoss R Signed-off-by: Rodrigo Vivi Reviewed-by: Durgadoss R Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 36 +++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 544675895c8dff..a96552251383c6 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2524,6 +2524,42 @@ enum punit_power_well { #define PIPESRC(trans) _TRANSCODER2(trans, _PIPEASRC) #define PIPE_MULT(trans) _TRANSCODER2(trans, _PIPE_MULT_A) +/* VLV eDP PSR registers */ +#define _PSRCTLA (VLV_DISPLAY_BASE + 0x60090) +#define _PSRCTLB (VLV_DISPLAY_BASE + 0x61090) +#define VLV_EDP_PSR_ENABLE (1<<0) +#define VLV_EDP_PSR_RESET (1<<1) +#define VLV_EDP_PSR_MODE_MASK (7<<2) +#define VLV_EDP_PSR_MODE_HW_TIMER (1<<3) +#define VLV_EDP_PSR_MODE_SW_TIMER (1<<2) +#define VLV_EDP_PSR_SINGLE_FRAME_UPDATE (1<<7) +#define VLV_EDP_PSR_ACTIVE_ENTRY (1<<8) +#define VLV_EDP_PSR_SRC_TRANSMITTER_STATE (1<<9) +#define VLV_EDP_PSR_DBL_FRAME (1<<10) +#define VLV_EDP_PSR_FRAME_COUNT_MASK (0xff<<16) +#define VLV_EDP_PSR_IDLE_FRAME_SHIFT 16 +#define VLV_PSRCTL(pipe) _PIPE(pipe, _PSRCTLA, _PSRCTLB) + +#define _VSCSDPA (VLV_DISPLAY_BASE + 0x600a0) +#define _VSCSDPB (VLV_DISPLAY_BASE + 0x610a0) +#define VLV_EDP_PSR_SDP_FREQ_MASK (3<<30) +#define VLV_EDP_PSR_SDP_FREQ_ONCE (1<<31) +#define VLV_EDP_PSR_SDP_FREQ_EVFRAME (1<<30) +#define VLV_VSCSDP(pipe) _PIPE(pipe, _VSCSDPA, _VSCSDPB) + +#define _PSRSTATA (VLV_DISPLAY_BASE + 0x60094) +#define _PSRSTATB (VLV_DISPLAY_BASE + 0x61094) +#define VLV_EDP_PSR_LAST_STATE_MASK (7<<3) +#define VLV_EDP_PSR_CURR_STATE_MASK 7 +#define VLV_EDP_PSR_DISABLED (0<<0) +#define VLV_EDP_PSR_INACTIVE (1<<0) +#define VLV_EDP_PSR_IN_TRANS_TO_ACTIVE (2<<0) +#define VLV_EDP_PSR_ACTIVE_NORFB_UP (3<<0) +#define VLV_EDP_PSR_ACTIVE_SF_UPDATE (4<<0) +#define VLV_EDP_PSR_EXIT (5<<0) +#define VLV_EDP_PSR_IN_TRANS (1<<7) +#define VLV_PSRSTAT(pipe) _PIPE(pipe, _PSRSTATA, _PSRSTATB) + /* HSW+ eDP PSR registers */ #define EDP_PSR_BASE(dev) (IS_HASWELL(dev) ? 0x64800 : 0x6f800) #define EDP_PSR_CTL(dev) (EDP_PSR_BASE(dev) + 0) From e2bbc343de8ea463af9da810b6e5e32dbd636b44 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Wed, 19 Nov 2014 07:37:00 -0800 Subject: [PATCH 0039/3023] drm/i915: PSR VLV/CHV: Introduce setup, enable and disable functions The biggest difference from HSW/BDW PSR here is that VLV enable_source function enables PSR but let it in Inactive state. So it might be called on early stage along with setup and enable_sink ones. v2: Rebase over intel_psr.c; Remove docs from static functions; Merge vlv_psr_active_on_pipe; Timeout for psr transition is 250us; Remove SRC_TRASMITTER_STATE; v3: Rebase after is_psr_enabled function got removed; Get SRC_TRANSMITTER_STATE back to be on the safe side since default for panels is to require link training on exit when main link off; As pointed out by Durgadoss msecs_to_jiffies used on wait_for only uses int, so let's use 1 instead. Althought the 1/4 of this is needed for the transition let's use 1 for simplicity; Cc: Durgadoss R Signed-off-by: Rodrigo Vivi Reviewed-by: Durgadoss R Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_psr.c | 155 ++++++++++++++++++++++++++----- 1 file changed, 130 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 576ad022222180..30f341ace83d29 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -61,6 +61,17 @@ static bool is_edp_psr(struct intel_dp *intel_dp) return intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED; } +static bool vlv_is_psr_active_on_pipe(struct drm_device *dev, int pipe) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t val; + + val = I915_READ(VLV_PSRSTAT(pipe)) & + VLV_EDP_PSR_CURR_STATE_MASK; + return (val == VLV_EDP_PSR_ACTIVE_NORFB_UP) || + (val == VLV_EDP_PSR_ACTIVE_SF_UPDATE); +} + static void intel_psr_write_vsc(struct intel_dp *intel_dp, struct edp_vsc_psr *vsc_psr) { @@ -90,7 +101,23 @@ static void intel_psr_write_vsc(struct intel_dp *intel_dp, POSTING_READ(ctl_reg); } -static void intel_psr_setup_vsc(struct intel_dp *intel_dp) +static void vlv_psr_setup_vsc(struct intel_dp *intel_dp) +{ + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = intel_dig_port->base.base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_crtc *crtc = intel_dig_port->base.base.crtc; + enum pipe pipe = to_intel_crtc(crtc)->pipe; + uint32_t val; + + /* VLV auto-generate VSC package as per EDP 1.3 spec, Table 3.10 */ + val = I915_READ(VLV_VSCSDP(pipe)); + val &= ~VLV_EDP_PSR_SDP_FREQ_MASK; + val |= VLV_EDP_PSR_SDP_FREQ_EVFRAME; + I915_WRITE(VLV_VSCSDP(pipe), val); +} + +static void hsw_psr_setup_vsc(struct intel_dp *intel_dp) { struct edp_vsc_psr psr_vsc; @@ -103,7 +130,13 @@ static void intel_psr_setup_vsc(struct intel_dp *intel_dp) intel_psr_write_vsc(intel_dp, &psr_vsc); } -static void intel_psr_enable_sink(struct intel_dp *intel_dp) +static void vlv_psr_enable_sink(struct intel_dp *intel_dp) +{ + drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, + DP_PSR_ENABLE); +} + +static void hsw_psr_enable_sink(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = dig_port->base.base.dev; @@ -147,7 +180,22 @@ static void intel_psr_enable_sink(struct intel_dp *intel_dp) (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT)); } -static void intel_psr_enable_source(struct intel_dp *intel_dp) +static void vlv_psr_enable_source(struct intel_dp *intel_dp) +{ + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = dig_port->base.base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_crtc *crtc = dig_port->base.base.crtc; + enum pipe pipe = to_intel_crtc(crtc)->pipe; + + /* Transition from PSR_state 0 to PSR_state 1, i.e. PSR Inactive */ + I915_WRITE(VLV_PSRCTL(pipe), + VLV_EDP_PSR_MODE_SW_TIMER | + VLV_EDP_PSR_SRC_TRANSMITTER_STATE | + VLV_EDP_PSR_ENABLE); +} + +static void hsw_psr_enable_source(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = dig_port->base.base.dev; @@ -225,7 +273,7 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp) return true; } -static void intel_psr_do_enable(struct intel_dp *intel_dp) +static void intel_psr_activate(struct intel_dp *intel_dp) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = intel_dig_port->base.base.dev; @@ -235,9 +283,12 @@ static void intel_psr_do_enable(struct intel_dp *intel_dp) WARN_ON(dev_priv->psr.active); lockdep_assert_held(&dev_priv->psr.lock); - /* Enable/Re-enable PSR on the host */ - intel_psr_enable_source(intel_dp); - + /* Enable/Re-enable PSR on the host + * On HSW+ after we enable PSR on source it will activate it + * as soon as it match configure idle_frame count. So + * we just actually enable it here on activation time. + */ + hsw_psr_enable_source(intel_dp); dev_priv->psr.active = true; } @@ -274,37 +325,67 @@ void intel_psr_enable(struct intel_dp *intel_dp) dev_priv->psr.busy_frontbuffer_bits = 0; - intel_psr_setup_vsc(intel_dp); + if (HAS_DDI(dev)) { + hsw_psr_setup_vsc(intel_dp); - /* Avoid continuous PSR exit by masking memup and hpd */ - I915_WRITE(EDP_PSR_DEBUG_CTL(dev), EDP_PSR_DEBUG_MASK_MEMUP | - EDP_PSR_DEBUG_MASK_HPD | EDP_PSR_DEBUG_MASK_LPSP); + /* Avoid continuous PSR exit by masking memup and hpd */ + I915_WRITE(EDP_PSR_DEBUG_CTL(dev), EDP_PSR_DEBUG_MASK_MEMUP | + EDP_PSR_DEBUG_MASK_HPD | EDP_PSR_DEBUG_MASK_LPSP); - /* Enable PSR on the panel */ - intel_psr_enable_sink(intel_dp); + /* Enable PSR on the panel */ + hsw_psr_enable_sink(intel_dp); + } else { + vlv_psr_setup_vsc(intel_dp); + + /* Enable PSR on the panel */ + vlv_psr_enable_sink(intel_dp); + + /* On HSW+ enable_source also means go to PSR entry/active + * state as soon as idle_frame achieved and here would be + * to soon. However on VLV enable_source just enable PSR + * but let it on inactive state. So we might do this prior + * to active transition, i.e. here. + */ + vlv_psr_enable_source(intel_dp); + } dev_priv->psr.enabled = intel_dp; unlock: mutex_unlock(&dev_priv->psr.lock); } -/** - * intel_psr_disable - Disable PSR - * @intel_dp: Intel DP - * - * This function needs to be called before disabling pipe. - */ -void intel_psr_disable(struct intel_dp *intel_dp) +static void vlv_psr_disable(struct intel_dp *intel_dp) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = + to_intel_crtc(intel_dig_port->base.base.crtc); + uint32_t val; - mutex_lock(&dev_priv->psr.lock); - if (!dev_priv->psr.enabled) { - mutex_unlock(&dev_priv->psr.lock); - return; + if (dev_priv->psr.active) { + /* Put VLV PSR back to PSR_state 0 that is PSR Disabled. */ + if (wait_for((I915_READ(VLV_PSRSTAT(intel_crtc->pipe)) & + VLV_EDP_PSR_IN_TRANS) == 0, 1)) + WARN(1, "PSR transition took longer than expected\n"); + + val = I915_READ(VLV_PSRCTL(intel_crtc->pipe)); + val &= ~VLV_EDP_PSR_ACTIVE_ENTRY; + val &= ~VLV_EDP_PSR_ENABLE; + val &= ~VLV_EDP_PSR_MODE_MASK; + I915_WRITE(VLV_PSRCTL(intel_crtc->pipe), val); + + dev_priv->psr.active = false; + } else { + WARN_ON(vlv_is_psr_active_on_pipe(dev, intel_crtc->pipe)); } +} + +static void hsw_psr_disable(struct intel_dp *intel_dp) +{ + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = intel_dig_port->base.base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; if (dev_priv->psr.active) { I915_WRITE(EDP_PSR_CTL(dev), @@ -319,6 +400,30 @@ void intel_psr_disable(struct intel_dp *intel_dp) } else { WARN_ON(I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE); } +} + +/** + * intel_psr_disable - Disable PSR + * @intel_dp: Intel DP + * + * This function needs to be called before disabling pipe. + */ +void intel_psr_disable(struct intel_dp *intel_dp) +{ + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = intel_dig_port->base.base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + mutex_lock(&dev_priv->psr.lock); + if (!dev_priv->psr.enabled) { + mutex_unlock(&dev_priv->psr.lock); + return; + } + + if (HAS_DDI(dev)) + hsw_psr_disable(intel_dp); + else + vlv_psr_disable(intel_dp); dev_priv->psr.enabled = NULL; mutex_unlock(&dev_priv->psr.lock); @@ -357,7 +462,7 @@ static void intel_psr_work(struct work_struct *work) if (dev_priv->psr.busy_frontbuffer_bits) goto unlock; - intel_psr_do_enable(intel_dp); + intel_psr_activate(intel_dp); unlock: mutex_unlock(&dev_priv->psr.lock); } From 995d304774966bf1e3013b5bf7df554b3d807b17 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Wed, 19 Nov 2014 07:37:47 -0800 Subject: [PATCH 0040/3023] drm/i915: VLV/CHV PSR Software timer mode This patch introduces exit/activate functions for PSR on VLV+. Since on VLV+ HW cannot track frame updates and force PSR exit let's use fully SW tracking available. v2: Rebase over intel_psr.c; Remove Single Frame update transitioning from state 3 to 5 directly; Fake a software invalidation for sprites and cursor so we don't miss any screen update; v3: As pointed out by Durgadoss msecs_to_jiffies used on wait_for only uses int, so let's use 1 instead. Althought the 1/4 of this is needed for the transition let's use 1 for simplicity; Also fix comments as suggested by Durgadoss Cc: Durgadoss R Signed-off-by: Rodrigo Vivi Reviewed-by: Durgadoss R Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_psr.c | 97 +++++++++++++++++++++++++++----- 1 file changed, 84 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 30f341ace83d29..dd0e6e0447d493 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -195,6 +195,23 @@ static void vlv_psr_enable_source(struct intel_dp *intel_dp) VLV_EDP_PSR_ENABLE); } +static void vlv_psr_activate(struct intel_dp *intel_dp) +{ + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = dig_port->base.base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_crtc *crtc = dig_port->base.base.crtc; + enum pipe pipe = to_intel_crtc(crtc)->pipe; + + /* Let's do the transition from PSR_state 1 to PSR_state 2 + * that is PSR transition to active - static frame transmission. + * Then Hardware is responsible for the transition to PSR_state 3 + * that is PSR active - no Remote Frame Buffer (RFB) update. + */ + I915_WRITE(VLV_PSRCTL(pipe), I915_READ(VLV_PSRCTL(pipe)) | + VLV_EDP_PSR_ACTIVE_ENTRY); +} + static void hsw_psr_enable_source(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); @@ -283,12 +300,16 @@ static void intel_psr_activate(struct intel_dp *intel_dp) WARN_ON(dev_priv->psr.active); lockdep_assert_held(&dev_priv->psr.lock); - /* Enable/Re-enable PSR on the host - * On HSW+ after we enable PSR on source it will activate it - * as soon as it match configure idle_frame count. So - * we just actually enable it here on activation time. - */ - hsw_psr_enable_source(intel_dp); + /* Enable/Re-enable PSR on the host */ + if (HAS_DDI(dev)) + /* On HSW+ after we enable PSR on source it will activate it + * as soon as it match configure idle_frame count. So + * we just actually enable it here on activation time. + */ + hsw_psr_enable_source(intel_dp); + else + vlv_psr_activate(intel_dp); + dev_priv->psr.active = true; } @@ -436,18 +457,27 @@ static void intel_psr_work(struct work_struct *work) struct drm_i915_private *dev_priv = container_of(work, typeof(*dev_priv), psr.work.work); struct intel_dp *intel_dp = dev_priv->psr.enabled; + struct drm_crtc *crtc = dp_to_dig_port(intel_dp)->base.base.crtc; + enum pipe pipe = to_intel_crtc(crtc)->pipe; /* We have to make sure PSR is ready for re-enable * otherwise it keeps disabled until next full enable/disable cycle. * PSR might take some time to get fully disabled * and be ready for re-enable. */ - if (wait_for((I915_READ(EDP_PSR_STATUS_CTL(dev_priv->dev)) & - EDP_PSR_STATUS_STATE_MASK) == 0, 50)) { - DRM_ERROR("Timed out waiting for PSR Idle for re-enable\n"); - return; + if (HAS_DDI(dev_priv->dev)) { + if (wait_for((I915_READ(EDP_PSR_STATUS_CTL(dev_priv->dev)) & + EDP_PSR_STATUS_STATE_MASK) == 0, 50)) { + DRM_ERROR("Timed out waiting for PSR Idle for re-enable\n"); + return; + } + } else { + if (wait_for((I915_READ(VLV_PSRSTAT(pipe)) & + VLV_EDP_PSR_IN_TRANS) == 0, 1)) { + DRM_ERROR("Timed out waiting for PSR Idle for re-enable\n"); + return; + } } - mutex_lock(&dev_priv->psr.lock); intel_dp = dev_priv->psr.enabled; @@ -470,17 +500,47 @@ static void intel_psr_work(struct work_struct *work) static void intel_psr_exit(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_dp *intel_dp = dev_priv->psr.enabled; + struct drm_crtc *crtc = dp_to_dig_port(intel_dp)->base.base.crtc; + enum pipe pipe = to_intel_crtc(crtc)->pipe; + u32 val; - if (dev_priv->psr.active) { - u32 val = I915_READ(EDP_PSR_CTL(dev)); + if (!dev_priv->psr.active) + return; + + if (HAS_DDI(dev)) { + val = I915_READ(EDP_PSR_CTL(dev)); WARN_ON(!(val & EDP_PSR_ENABLE)); I915_WRITE(EDP_PSR_CTL(dev), val & ~EDP_PSR_ENABLE); dev_priv->psr.active = false; + } else { + val = I915_READ(VLV_PSRCTL(pipe)); + + /* Here we do the transition from PSR_state 3 to PSR_state 5 + * directly once PSR State 4 that is active with single frame + * update can be skipped. PSR_state 5 that is PSR exit then + * Hardware is responsible to transition back to PSR_state 1 + * that is PSR inactive. Same state after + * vlv_edp_psr_enable_source. + */ + val &= ~VLV_EDP_PSR_ACTIVE_ENTRY; + I915_WRITE(VLV_PSRCTL(pipe), val); + + /* Send AUX wake up - Spec says after transitioning to PSR + * active we have to send AUX wake up by writing 01h in DPCD + * 600h of sink device. + * XXX: This might slow down the transition, but without this + * HW doesn't complete the transition to PSR_state 1 and we + * never get the screen updated. + */ + drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, + DP_SET_POWER_D0); } + dev_priv->psr.active = false; } /** @@ -558,6 +618,17 @@ void intel_psr_flush(struct drm_device *dev, (frontbuffer_bits & INTEL_FRONTBUFFER_SPRITE(pipe))) intel_psr_exit(dev); + /* + * On Valleyview and Cherryview we don't use hardware tracking so + * sprite plane updates or cursor moves don't result in a PSR + * invalidating. Which means we need to manually fake this in + * software for all flushes, not just when we've seen a preceding + * invalidation through frontbuffer rendering. */ + if (!HAS_DDI(dev) && + ((frontbuffer_bits & INTEL_FRONTBUFFER_SPRITE(pipe)) || + (frontbuffer_bits & INTEL_FRONTBUFFER_CURSOR(pipe)))) + intel_psr_exit(dev); + if (!dev_priv->psr.active && !dev_priv->psr.busy_frontbuffer_bits) schedule_delayed_work(&dev_priv->psr.work, msecs_to_jiffies(100)); From a6cbdb8e37d65bbf827fc31ee68b50b1e562a8ba Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 14 Nov 2014 08:52:40 -0800 Subject: [PATCH 0041/3023] drm/i915: VLV/CHV PSR debugfs. Add debugfs support for Valleyview and Cherryview considering that we have PSR per pipe and we don't have any kind of performance counter as we have on other platforms that support PSR. Signed-off-by: Rodrigo Vivi Reviewed-by: Durgadoss R Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 34 ++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 779a275eb1fd34..eed74025294554 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2155,6 +2155,8 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 psrperf = 0; + u32 stat[3]; + enum pipe pipe; bool enabled = false; intel_runtime_pm_get(dev_priv); @@ -2169,14 +2171,36 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) seq_printf(m, "Re-enable work scheduled: %s\n", yesno(work_busy(&dev_priv->psr.work.work))); - enabled = HAS_PSR(dev) && - I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE; - seq_printf(m, "HW Enabled & Active bit: %s\n", yesno(enabled)); + if (HAS_PSR(dev)) { + if (HAS_DDI(dev)) + enabled = I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE; + else { + for_each_pipe(dev_priv, pipe) { + stat[pipe] = I915_READ(VLV_PSRSTAT(pipe)) & + VLV_EDP_PSR_CURR_STATE_MASK; + if ((stat[pipe] == VLV_EDP_PSR_ACTIVE_NORFB_UP) || + (stat[pipe] == VLV_EDP_PSR_ACTIVE_SF_UPDATE)) + enabled = true; + } + } + } + seq_printf(m, "HW Enabled & Active bit: %s", yesno(enabled)); - if (HAS_PSR(dev)) + if (!HAS_DDI(dev)) + for_each_pipe(dev_priv, pipe) { + if ((stat[pipe] == VLV_EDP_PSR_ACTIVE_NORFB_UP) || + (stat[pipe] == VLV_EDP_PSR_ACTIVE_SF_UPDATE)) + seq_printf(m, " pipe %c", pipe_name(pipe)); + } + seq_puts(m, "\n"); + + /* CHV PSR has no kind of performance counter */ + if (HAS_PSR(dev) && HAS_DDI(dev)) { psrperf = I915_READ(EDP_PSR_PERF_CNT(dev)) & EDP_PSR_PERF_CNT_MASK; - seq_printf(m, "Performance_Counter: %u\n", psrperf); + + seq_printf(m, "Performance_Counter: %u\n", psrperf); + } mutex_unlock(&dev_priv->psr.lock); intel_runtime_pm_put(dev_priv); From b32c6f482dc56c52169cad7c9d35908c020dd22d Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 20 Nov 2014 03:44:37 -0800 Subject: [PATCH 0042/3023] drm/i915: Enable PSR for Baytrail and Braswell. This patch is the last in series of VLV/CHV PSR, that finally enable PSR by adding it to HAS_PSR and calling the proper enable and disable functions on the right places. Although it is still disabled by default. v2: Rebase over intel_psr and merge Durgadoss's fixes. v3: Fix typo. Signed-off-by: Rodrigo Vivi Reviewed-by: Durgadoss R Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/intel_dp.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c7f00a452f5599..f6f92f16c2cf71 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2257,7 +2257,8 @@ struct drm_i915_cmd_table { #define HAS_DDI(dev) (INTEL_INFO(dev)->has_ddi) #define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg) -#define HAS_PSR(dev) (IS_HASWELL(dev) || IS_BROADWELL(dev)) +#define HAS_PSR(dev) (IS_HASWELL(dev) || IS_BROADWELL(dev) || \ + IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) #define HAS_RUNTIME_PM(dev) (IS_GEN6(dev) || IS_HASWELL(dev) || \ IS_BROADWELL(dev) || IS_VALLEYVIEW(dev)) #define HAS_RC6(dev) (INTEL_INFO(dev)->gen >= 6) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index fa509db3e1f928..3fc32968252762 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2105,6 +2105,9 @@ static void intel_disable_dp(struct intel_encoder *encoder) if (crtc->config.has_audio) intel_audio_codec_disable(encoder); + if (HAS_PSR(dev) && !HAS_DDI(dev)) + intel_psr_disable(intel_dp); + /* Make sure the panel is off before trying to change the mode. But also * ensure that we have vdd while we switch off the panel. */ intel_edp_panel_vdd_on(intel_dp); @@ -2329,6 +2332,7 @@ static void vlv_enable_dp(struct intel_encoder *encoder) struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); intel_edp_backlight_on(intel_dp); + intel_psr_enable(intel_dp); } static void g4x_pre_enable_dp(struct intel_encoder *encoder) From 57e215135f8ad7519fb079a0234e91a94bddd2f9 Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Tue, 18 Nov 2014 20:07:20 +0000 Subject: [PATCH 0043/3023] drm/i915: Check for matching ringbuffer in logical_ring_wait_request() The request queue is per-engine, and may therefore contain requests from several different contexts/ringbuffers. In determining which request to wait for, this function should only consider requests from the ringbuffer that it's checking for space, and ignore any that it finds that belong to other contexts. Signed-off-by: Dave Gordon Reviewed-by: Deepak S Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index e588376227eaf6..047d8f065b9938 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -930,6 +930,16 @@ static int logical_ring_wait_request(struct intel_ringbuffer *ringbuf, } list_for_each_entry(request, &ring->request_list, list) { + /* + * The request queue is per-engine, so can contain requests + * from multiple ringbuffers. Here, we must ignore any that + * aren't from the ringbuffer we're considering. + */ + struct intel_context *ctx = request->ctx; + if (ctx->engine[ring->id].ringbuf != ringbuf) + continue; + + /* Would completion of this request free enough space? */ if (__intel_ring_space(request->tail, ringbuf->tail, ringbuf->size) >= bytes) { seqno = request->seqno; From d65621c496a2afe6c6724cbd7150e2ec60b42f13 Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Tue, 18 Nov 2014 20:07:21 +0000 Subject: [PATCH 0044/3023] drm/i915: Don't read 'HEAD' MMIO register in LRC mode The logical ring code was updating the software ring 'head' value by reading the hardware 'HEAD' register. In LRC mode, this is not valid as the hardware is not necessarily executing the same context that is being processed by the software. Thus reading the h/w HEAD could put an unrelated (undefined, effectively random) value into the s/w 'head' -- A Bad Thing for the free space calculations. Signed-off-by: Dave Gordon Reviewed-by: Deepak S Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 047d8f065b9938..03b5c04b6ee152 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -986,7 +986,6 @@ static int logical_ring_wait_for_space(struct intel_ringbuffer *ringbuf, end = jiffies + 60 * HZ; do { - ringbuf->head = I915_READ_HEAD(ring); ringbuf->space = intel_ring_space(ringbuf); if (ringbuf->space >= bytes) { ret = 0; From 4feb765943c42dbc706dac348e8a893325b1153f Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 24 Nov 2014 11:21:52 +0100 Subject: [PATCH 0045/3023] drm/i915: Remove user pinning code Now unused. Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 4 +- drivers/gpu/drm/i915/i915_dma.c | 11 ++- drivers/gpu/drm/i915/i915_drv.h | 8 -- drivers/gpu/drm/i915/i915_gem.c | 106 +------------------------- drivers/gpu/drm/i915/i915_gem_gtt.h | 9 +-- drivers/gpu/drm/i915/i915_gpu_error.c | 2 - 6 files changed, 17 insertions(+), 123 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index eed74025294554..a47fc25e6bb446 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -96,9 +96,7 @@ static int i915_capabilities(struct seq_file *m, void *data) static const char *get_pin_flag(struct drm_i915_gem_object *obj) { - if (obj->user_pin_count > 0) - return "P"; - else if (i915_gem_obj_is_pinned(obj)) + if (i915_gem_obj_is_pinned(obj)) return "p"; else return " "; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index ecee3bcc877290..887d88f4c68829 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1004,6 +1004,13 @@ void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) kfree(file_priv); } +static int +i915_gem_reject_pin_ioctl(struct drm_device *dev, void *data, + struct drm_file *file) +{ + return -ENODEV; +} + const struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF_DRV(I915_INIT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF_DRV(I915_FLUSH, drm_noop, DRM_AUTH), @@ -1025,8 +1032,8 @@ const struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF_DRV(I915_GEM_INIT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH|DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_PIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_UNPIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_SET_CACHING, i915_gem_set_caching_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_GET_CACHING, i915_gem_get_caching_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f6f92f16c2cf71..7a81ae2f00f90d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1958,10 +1958,6 @@ struct drm_i915_gem_object { /** Record of address bit 17 of each page at last unbind. */ unsigned long *bit_17; - /** User space pin count and filp owning the pin */ - unsigned long user_pin_count; - struct drm_file *pin_filp; - union { /** for phy allocated objects */ struct drm_dma_handle *phys_handle; @@ -2428,10 +2424,6 @@ int i915_gem_execbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_execbuffer2(struct drm_device *dev, void *data, struct drm_file *file_priv); -int i915_gem_pin_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -int i915_gem_unpin_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); int i915_gem_busy_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_get_caching_ioctl(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d2ba315f4c92c8..c630d4986376bd 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3903,18 +3903,14 @@ static bool is_pin_display(struct drm_i915_gem_object *obj) if (!vma) return false; - /* There are 3 sources that pin objects: + /* There are 2 sources that pin objects: * 1. The display engine (scanouts, sprites, cursors); * 2. Reservations for execbuffer; - * 3. The user. * * We can ignore reservations as we hold the struct_mutex and - * are only called outside of the reservation path. The user - * can only increment pin_count once, and so if after - * subtracting the potential reference by the user, any pin_count - * remains, it must be due to another use by the display engine. + * are only called outside of the reservation path. */ - return vma->pin_count - !!obj->user_pin_count; + return vma->pin_count; } /* @@ -4257,102 +4253,6 @@ i915_gem_object_unpin_fence(struct drm_i915_gem_object *obj) } } -int -i915_gem_pin_ioctl(struct drm_device *dev, void *data, - struct drm_file *file) -{ - struct drm_i915_gem_pin *args = data; - struct drm_i915_gem_object *obj; - int ret; - - if (drm_core_check_feature(dev, DRIVER_MODESET)) - return -ENODEV; - - ret = i915_mutex_lock_interruptible(dev); - if (ret) - return ret; - - obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); - if (&obj->base == NULL) { - ret = -ENOENT; - goto unlock; - } - - if (obj->madv != I915_MADV_WILLNEED) { - DRM_DEBUG("Attempting to pin a purgeable buffer\n"); - ret = -EFAULT; - goto out; - } - - if (obj->pin_filp != NULL && obj->pin_filp != file) { - DRM_DEBUG("Already pinned in i915_gem_pin_ioctl(): %d\n", - args->handle); - ret = -EINVAL; - goto out; - } - - if (obj->user_pin_count == ULONG_MAX) { - ret = -EBUSY; - goto out; - } - - if (obj->user_pin_count == 0) { - ret = i915_gem_obj_ggtt_pin(obj, args->alignment, PIN_MAPPABLE); - if (ret) - goto out; - } - - obj->user_pin_count++; - obj->pin_filp = file; - - args->offset = i915_gem_obj_ggtt_offset(obj); -out: - drm_gem_object_unreference(&obj->base); -unlock: - mutex_unlock(&dev->struct_mutex); - return ret; -} - -int -i915_gem_unpin_ioctl(struct drm_device *dev, void *data, - struct drm_file *file) -{ - struct drm_i915_gem_pin *args = data; - struct drm_i915_gem_object *obj; - int ret; - - if (drm_core_check_feature(dev, DRIVER_MODESET)) - return -ENODEV; - - ret = i915_mutex_lock_interruptible(dev); - if (ret) - return ret; - - obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); - if (&obj->base == NULL) { - ret = -ENOENT; - goto unlock; - } - - if (obj->pin_filp != file) { - DRM_DEBUG("Not pinned by caller in i915_gem_pin_ioctl(): %d\n", - args->handle); - ret = -EINVAL; - goto out; - } - obj->user_pin_count--; - if (obj->user_pin_count == 0) { - obj->pin_filp = NULL; - i915_gem_object_ggtt_unpin(obj); - } - -out: - drm_gem_object_unreference(&obj->base); -unlock: - mutex_unlock(&dev->struct_mutex); - return ret; -} - int i915_gem_busy_ioctl(struct drm_device *dev, void *data, struct drm_file *file) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index beaf4bcfdac8d8..92db6654f93ba4 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -146,11 +146,10 @@ struct i915_vma { /** * How many users have pinned this object in GTT space. The following - * users can each hold at most one reference: pwrite/pread, pin_ioctl - * (via user_pin_count), execbuffer (objects are not allowed multiple - * times for the same batchbuffer), and the framebuffer code. When - * switching/pageflipping, the framebuffer code has at most two buffers - * pinned per crtc. + * users can each hold at most one reference: pwrite/pread, execbuffer + * (objects are not allowed multiple times for the same batchbuffer), + * and the framebuffer code. When switching/pageflipping, the + * framebuffer code has at most two buffers pinned per crtc. * * In the worst case this is 1 + 1 + 1 + 2*2 = 7. That would fit into 3 * bits with absolutely no headroom. So use 4 bits. */ diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index cdaee6ce05f84c..eea98d56743107 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -679,8 +679,6 @@ static void capture_bo(struct drm_i915_error_buffer *err, err->pinned = 0; if (i915_gem_obj_is_pinned(obj)) err->pinned = 1; - if (obj->user_pin_count > 0) - err->pinned = -1; err->tiling = obj->tiling_mode; err->dirty = obj->dirty; err->purgeable = obj->madv != I915_MADV_WILLNEED; From bdcf120bfcb7e3b9356e96cdd7a6ac3c28062ffc Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 25 Nov 2014 11:56:33 +0000 Subject: [PATCH 0046/3023] drm/i915: Assert that we successfully downclock the GPU before suspend Before suspending, we wait upon the outstanding GPU requests and flush our pending idle handlers. This should downclock the GPU to its lowest power state. Add a WARN to check that the delayed tasks were run and did their job properly. Suggested-by: Akash Goel Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c630d4986376bd..fa3f907ce22940 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4581,6 +4581,11 @@ i915_gem_suspend(struct drm_device *dev) cancel_delayed_work_sync(&dev_priv->mm.retire_work); flush_delayed_work(&dev_priv->mm.idle_work); + /* Assert that we sucessfully flushed all the work and + * reset the GPU back to its idle, low power state. + */ + WARN_ON(dev_priv->mm.busy); + return 0; err: From f61ccae333c6f523adf75aa61605c14a275d2aca Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Tue, 25 Nov 2014 13:45:41 +0000 Subject: [PATCH 0047/3023] drm/i915: Fix short description of intel_display_power_is_enabled() That's the version actually taking the dev_priv->power_domains lock. Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_runtime_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index f5a78d53e2978e..8a2bd1869fd807 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -118,7 +118,7 @@ bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv, } /** - * intel_display_power_is_enabled - unlocked check for a power domain + * intel_display_power_is_enabled - check for a power domain * @dev_priv: i915 device instance * @domain: power domain to check * From 9eba5d4a1d79d5094321469479b4dbe418f60110 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 24 Nov 2014 18:49:23 +0000 Subject: [PATCH 0048/3023] drm/i915: Ensure OLS & PLR are always in sync The aim is to replace seqno values with request structures. A step along the way is to switch to using the PLR in preference to the OLS. That requires the PLR to only be valid when and only when the OLS is also valid. I.e., the two must be kept in lock step. Then, code which was using the OLS can be safely switched over to using the PLR instead. For: VIZ-4377 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 55 +++++++++++++++---------- drivers/gpu/drm/i915/intel_ringbuffer.c | 29 +++++++++---- 2 files changed, 54 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 03b5c04b6ee152..cc49b8492ee4ce 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -879,37 +879,48 @@ void intel_lr_context_unpin(struct intel_engine_cs *ring, static int logical_ring_alloc_seqno(struct intel_engine_cs *ring, struct intel_context *ctx) { + struct drm_i915_gem_request *request; int ret; - if (ring->outstanding_lazy_seqno) - return 0; + /* XXX: The aim is to replace seqno values with request structures. + * A step along the way is to switch to using the PLR in preference + * to the OLS. That requires the PLR to only be valid when the OLS is + * also valid. I.e., the two must be kept in step. */ - if (ring->preallocated_lazy_request == NULL) { - struct drm_i915_gem_request *request; + if (ring->outstanding_lazy_seqno) { + WARN_ON(ring->preallocated_lazy_request == NULL); + return 0; + } + WARN_ON(ring->preallocated_lazy_request != NULL); - request = kmalloc(sizeof(*request), GFP_KERNEL); - if (request == NULL) - return -ENOMEM; + request = kmalloc(sizeof(*request), GFP_KERNEL); + if (request == NULL) + return -ENOMEM; - if (ctx != ring->default_context) { - ret = intel_lr_context_pin(ring, ctx); - if (ret) { - kfree(request); - return ret; - } + if (ctx != ring->default_context) { + ret = intel_lr_context_pin(ring, ctx); + if (ret) { + kfree(request); + return ret; } + } - /* Hold a reference to the context this request belongs to - * (we will need it when the time comes to emit/retire the - * request). - */ - request->ctx = ctx; - i915_gem_context_reference(request->ctx); - - ring->preallocated_lazy_request = request; + ret = i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_seqno); + if (ret) { + intel_lr_context_unpin(ring, ctx); + kfree(request); + return ret; } - return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_seqno); + /* Hold a reference to the context this request belongs to + * (we will need it when the time comes to emit/retire the + * request). + */ + request->ctx = ctx; + i915_gem_context_reference(request->ctx); + + ring->preallocated_lazy_request = request; + return 0; } static int logical_ring_wait_request(struct intel_ringbuffer *ringbuf, diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 1d01b51ff058bd..9fe13075e5f95a 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -2024,20 +2024,33 @@ int intel_ring_idle(struct intel_engine_cs *ring) static int intel_ring_alloc_seqno(struct intel_engine_cs *ring) { - if (ring->outstanding_lazy_seqno) + int ret; + struct drm_i915_gem_request *request; + + /* XXX: The aim is to replace seqno values with request structures. + * A step along the way is to switch to using the PLR in preference + * to the OLS. That requires the PLR to only be valid when the OLS + * is also valid. I.e., the two must be kept in step. */ + + if (ring->outstanding_lazy_seqno) { + WARN_ON(ring->preallocated_lazy_request == NULL); return 0; + } - if (ring->preallocated_lazy_request == NULL) { - struct drm_i915_gem_request *request; + WARN_ON(ring->preallocated_lazy_request != NULL); - request = kmalloc(sizeof(*request), GFP_KERNEL); - if (request == NULL) - return -ENOMEM; + request = kmalloc(sizeof(*request), GFP_KERNEL); + if (request == NULL) + return -ENOMEM; - ring->preallocated_lazy_request = request; + ret = i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_seqno); + if (ret) { + kfree(request); + return ret; } - return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_seqno); + ring->preallocated_lazy_request = request; + return 0; } static int __intel_ring_prepare(struct intel_engine_cs *ring, From abfe262ae76246434fc427db855d716e575d0c1f Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 24 Nov 2014 18:49:24 +0000 Subject: [PATCH 0049/3023] drm/i915: Add reference count to request structure The plan is to use request structures everywhere that seqno values were previously used. This means saving pointers to structures in places that used to be simple integers. In turn, that means that the target structure now needs much more stringent lifetime tracking. That is, it must not be freed while some other random object still holds a pointer to it. To achieve this tracking, a reference count needs to be added. Whenever a pointer to the structure is saved away, the count must be incremented and the free must only occur when all references have been released. For: VIZ-4377 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 28 +++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_gem.c | 20 ++++++++++++------ drivers/gpu/drm/i915/intel_lrc.c | 4 +++- drivers/gpu/drm/i915/intel_ringbuffer.c | 4 +++- 4 files changed, 48 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7a81ae2f00f90d..36d407848f28d5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1991,6 +1991,8 @@ void i915_gem_track_fb(struct drm_i915_gem_object *old, * an emission time with seqnos for tracking how far ahead of the GPU we are. */ struct drm_i915_gem_request { + struct kref ref; + /** On Which ring this request was generated */ struct intel_engine_cs *ring; @@ -2020,6 +2022,32 @@ struct drm_i915_gem_request { struct list_head client_list; }; +void i915_gem_request_free(struct kref *req_ref); + +static inline void +i915_gem_request_reference(struct drm_i915_gem_request *req) +{ + kref_get(&req->ref); +} + +static inline void +i915_gem_request_unreference(struct drm_i915_gem_request *req) +{ + kref_put(&req->ref, i915_gem_request_free); +} + +static inline void i915_gem_request_assign(struct drm_i915_gem_request **pdst, + struct drm_i915_gem_request *src) +{ + if (src) + i915_gem_request_reference(src); + + if (*pdst) + i915_gem_request_unreference(*pdst); + + *pdst = src; +} + struct drm_i915_file_private { struct drm_i915_private *dev_priv; struct drm_file *file; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index fa3f907ce22940..ef45e2eac95230 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2569,21 +2569,30 @@ static void i915_set_reset_status(struct drm_i915_private *dev_priv, static void i915_gem_free_request(struct drm_i915_gem_request *request) { - struct intel_context *ctx = request->ctx; - list_del(&request->list); i915_gem_request_remove_from_client(request); + i915_gem_request_unreference(request); +} + +void i915_gem_request_free(struct kref *req_ref) +{ + struct drm_i915_gem_request *req = container_of(req_ref, + typeof(*req), ref); + struct intel_context *ctx = req->ctx; + if (ctx) { if (i915.enable_execlists) { - struct intel_engine_cs *ring = request->ring; + struct intel_engine_cs *ring = req->ring; if (ctx != ring->default_context) intel_lr_context_unpin(ring, ctx); } + i915_gem_context_unreference(ctx); } - kfree(request); + + kfree(req); } struct drm_i915_gem_request * @@ -2671,8 +2680,7 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv, } /* These may not have been flush before the reset, do so now */ - kfree(ring->preallocated_lazy_request); - ring->preallocated_lazy_request = NULL; + i915_gem_request_assign(&ring->preallocated_lazy_request, NULL); ring->outstanding_lazy_seqno = 0; } diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index cc49b8492ee4ce..56c275d0a61021 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -905,6 +905,8 @@ static int logical_ring_alloc_seqno(struct intel_engine_cs *ring, } } + kref_init(&request->ref); + ret = i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_seqno); if (ret) { intel_lr_context_unpin(ring, ctx); @@ -1374,7 +1376,7 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *ring) intel_logical_ring_stop(ring); WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0); - ring->preallocated_lazy_request = NULL; + i915_gem_request_assign(&ring->preallocated_lazy_request, NULL); ring->outstanding_lazy_seqno = 0; if (ring->cleanup) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 9fe13075e5f95a..fbeaa3ad6208aa 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1870,7 +1870,7 @@ void intel_cleanup_ring_buffer(struct intel_engine_cs *ring) intel_unpin_ringbuffer_obj(ringbuf); intel_destroy_ringbuffer_obj(ringbuf); - ring->preallocated_lazy_request = NULL; + i915_gem_request_assign(&ring->preallocated_lazy_request, NULL); ring->outstanding_lazy_seqno = 0; if (ring->cleanup) @@ -2043,6 +2043,8 @@ intel_ring_alloc_seqno(struct intel_engine_cs *ring) if (request == NULL) return -ENOMEM; + kref_init(&request->ref); + ret = i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_seqno); if (ret) { kfree(request); From b793a00a57da8d5057168aace0695a823bbb6e02 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 24 Nov 2014 18:49:25 +0000 Subject: [PATCH 0050/3023] drm/i915: Add helper functions to aid seqno -> request transition Added helper functions for retrieving the ring and seqno entries from a request structure. This allows the internal workings of the request structure to be hidden from code that is using these. It also allows for useful workarounds/debug code to be added as or when necessary. Note that it is intended that the majority (if not all) uses of the seqno accessor will disappear eventually as code is updated to use the request structure itself rather than working with seqno values. For: VIZ-4377 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 12 ++++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 7 +++++++ 2 files changed, 19 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 36d407848f28d5..48c0c4a60364d6 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2024,6 +2024,18 @@ struct drm_i915_gem_request { void i915_gem_request_free(struct kref *req_ref); +static inline uint32_t +i915_gem_request_get_seqno(struct drm_i915_gem_request *req) +{ + return req ? req->seqno : 0; +} + +static inline struct intel_engine_cs * +i915_gem_request_get_ring(struct drm_i915_gem_request *req) +{ + return req ? req->ring : NULL; +} + static inline void i915_gem_request_reference(struct drm_i915_gem_request *req) { diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index fe426cff598ba5..20636e0e9b53b2 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -442,6 +442,13 @@ static inline u32 intel_ring_get_seqno(struct intel_engine_cs *ring) return ring->outstanding_lazy_seqno; } +static inline struct drm_i915_gem_request * +intel_ring_get_request(struct intel_engine_cs *ring) +{ + BUG_ON(ring->preallocated_lazy_request == NULL); + return ring->preallocated_lazy_request; +} + static inline void i915_trace_irq_get(struct intel_engine_cs *ring, u32 seqno) { if (ring->trace_irq_seqno == 0 && ring->irq_get(ring)) From 97b2a6a10a1aef6f32832fcbc9d6a27650354904 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 24 Nov 2014 18:49:26 +0000 Subject: [PATCH 0051/3023] drm/i915: Replace last_[rwf]_seqno with last_[rwf]_req The object structure contains the last read, write and fenced seqno values for use in syncrhonisation operations. These have now been replaced with their request structure counterparts. Note that to ensure that objects do not end up with dangling pointers, the assignments of last_*_req include reference count updates. Thus a request cannot be freed if an object is still hanging on to it for any reason. v2: Corrected 'last_rendering_' to 'last_read_' in a number of comments that did not get updated when 'last_rendering_seqno' became 'last_read|write_seqno' several millenia ago. For: VIZ-4377 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 6 +- drivers/gpu/drm/i915/i915_drv.h | 13 ++-- drivers/gpu/drm/i915/i915_gem.c | 71 +++++++++++++--------- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 6 +- drivers/gpu/drm/i915/i915_gem_gtt.h | 4 +- drivers/gpu/drm/i915/i915_gem_tiling.c | 2 +- drivers/gpu/drm/i915/i915_gpu_error.c | 4 +- drivers/gpu/drm/i915/intel_display.c | 6 +- drivers/gpu/drm/i915/intel_ringbuffer.h | 2 +- 9 files changed, 64 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index a47fc25e6bb446..4619873f96202e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -131,9 +131,9 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) obj->base.size / 1024, obj->base.read_domains, obj->base.write_domain, - obj->last_read_seqno, - obj->last_write_seqno, - obj->last_fenced_seqno, + i915_gem_request_get_seqno(obj->last_read_req), + i915_gem_request_get_seqno(obj->last_write_req), + i915_gem_request_get_seqno(obj->last_fenced_req), i915_cache_level_str(to_i915(obj->base.dev), obj->cache_level), obj->dirty ? " dirty" : "", obj->madv == I915_MADV_DONTNEED ? " purgeable" : ""); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 48c0c4a60364d6..4924f1d3d4b415 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1944,10 +1944,10 @@ struct drm_i915_gem_object { struct intel_engine_cs *ring; /** Breadcrumb of last rendering to the buffer. */ - uint32_t last_read_seqno; - uint32_t last_write_seqno; + struct drm_i915_gem_request *last_read_req; + struct drm_i915_gem_request *last_write_req; /** Breadcrumb of last fenced GPU access to the buffer. */ - uint32_t last_fenced_seqno; + struct drm_i915_gem_request *last_fenced_req; /** Current tiling stride for the object, if it's tiled. */ uint32_t stride; @@ -1986,9 +1986,10 @@ void i915_gem_track_fb(struct drm_i915_gem_object *old, * The request queue allows us to note sequence numbers that have been emitted * and may be associated with active buffers to be retired. * - * By keeping this list, we can avoid having to do questionable - * sequence-number comparisons on buffer last_rendering_seqnos, and associate - * an emission time with seqnos for tracking how far ahead of the GPU we are. + * By keeping this list, we can avoid having to do questionable sequence + * number comparisons on buffer last_read|write_seqno. It also allows an + * emission time to be associated with the request for tracking how far ahead + * of the GPU the submission is. */ struct drm_i915_gem_request { struct kref ref; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index ef45e2eac95230..a1110fb7e583b6 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1346,11 +1346,11 @@ i915_gem_object_wait_rendering__tail(struct drm_i915_gem_object *obj) /* Manually manage the write flush as we may have not yet * retired the buffer. * - * Note that the last_write_seqno is always the earlier of - * the two (read/write) seqno, so if we haved successfully waited, + * Note that the last_write_req is always the earlier of + * the two (read/write) requests, so if we haved successfully waited, * we know we have passed the last write. */ - obj->last_write_seqno = 0; + i915_gem_request_assign(&obj->last_write_req, NULL); return 0; } @@ -1363,14 +1363,18 @@ static __must_check int i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj, bool readonly) { + struct drm_i915_gem_request *req; struct intel_engine_cs *ring = obj->ring; u32 seqno; int ret; - seqno = readonly ? obj->last_write_seqno : obj->last_read_seqno; - if (seqno == 0) + req = readonly ? obj->last_write_req : obj->last_read_req; + if (!req) return 0; + seqno = i915_gem_request_get_seqno(req); + WARN_ON(seqno == 0); + ret = i915_wait_seqno(ring, seqno); if (ret) return ret; @@ -1386,6 +1390,7 @@ i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj, struct drm_i915_file_private *file_priv, bool readonly) { + struct drm_i915_gem_request *req; struct drm_device *dev = obj->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *ring = obj->ring; @@ -1396,10 +1401,13 @@ i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj, BUG_ON(!mutex_is_locked(&dev->struct_mutex)); BUG_ON(!dev_priv->mm.interruptible); - seqno = readonly ? obj->last_write_seqno : obj->last_read_seqno; - if (seqno == 0) + req = readonly ? obj->last_write_req : obj->last_read_req; + if (!req) return 0; + seqno = i915_gem_request_get_seqno(req); + WARN_ON(seqno == 0); + ret = i915_gem_check_wedge(&dev_priv->gpu_error, true); if (ret) return ret; @@ -2257,12 +2265,12 @@ static void i915_gem_object_move_to_active(struct drm_i915_gem_object *obj, struct intel_engine_cs *ring) { - u32 seqno = intel_ring_get_seqno(ring); + struct drm_i915_gem_request *req = intel_ring_get_request(ring); BUG_ON(ring == NULL); - if (obj->ring != ring && obj->last_write_seqno) { - /* Keep the seqno relative to the current ring */ - obj->last_write_seqno = seqno; + if (obj->ring != ring && obj->last_write_req) { + /* Keep the request relative to the current ring */ + i915_gem_request_assign(&obj->last_write_req, req); } obj->ring = ring; @@ -2274,7 +2282,7 @@ i915_gem_object_move_to_active(struct drm_i915_gem_object *obj, list_move_tail(&obj->ring_list, &ring->active_list); - obj->last_read_seqno = seqno; + i915_gem_request_assign(&obj->last_read_req, req); } void i915_vma_move_to_active(struct i915_vma *vma, @@ -2305,11 +2313,11 @@ i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj) list_del_init(&obj->ring_list); obj->ring = NULL; - obj->last_read_seqno = 0; - obj->last_write_seqno = 0; + i915_gem_request_assign(&obj->last_read_req, NULL); + i915_gem_request_assign(&obj->last_write_req, NULL); obj->base.write_domain = 0; - obj->last_fenced_seqno = 0; + i915_gem_request_assign(&obj->last_fenced_req, NULL); obj->active = 0; drm_gem_object_unreference(&obj->base); @@ -2326,7 +2334,7 @@ i915_gem_object_retire(struct drm_i915_gem_object *obj) return; if (i915_seqno_passed(ring->get_seqno(ring, true), - obj->last_read_seqno)) + i915_gem_request_get_seqno(obj->last_read_req))) i915_gem_object_move_to_inactive(obj); } @@ -2753,7 +2761,8 @@ i915_gem_retire_requests_ring(struct intel_engine_cs *ring) struct drm_i915_gem_object, ring_list); - if (!i915_seqno_passed(seqno, obj->last_read_seqno)) + if (!i915_seqno_passed(seqno, + i915_gem_request_get_seqno(obj->last_read_req))) break; i915_gem_object_move_to_inactive(obj); @@ -2872,7 +2881,8 @@ i915_gem_object_flush_active(struct drm_i915_gem_object *obj) int ret; if (obj->active) { - ret = i915_gem_check_olr(obj->ring, obj->last_read_seqno); + ret = i915_gem_check_olr(obj->ring, + i915_gem_request_get_seqno(obj->last_read_req)); if (ret) return ret; @@ -2933,13 +2943,12 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) if (ret) goto out; - if (obj->active) { - seqno = obj->last_read_seqno; - ring = obj->ring; - } + if (!obj->active || !obj->last_read_req) + goto out; - if (seqno == 0) - goto out; + seqno = i915_gem_request_get_seqno(obj->last_read_req); + WARN_ON(seqno == 0); + ring = obj->ring; /* Do this after OLR check to make sure we make forward progress polling * on this IOCTL with a timeout <=0 (like busy ioctl) @@ -2990,7 +2999,7 @@ i915_gem_object_sync(struct drm_i915_gem_object *obj, idx = intel_ring_sync_index(from, to); - seqno = obj->last_read_seqno; + seqno = i915_gem_request_get_seqno(obj->last_read_req); /* Optimization: Avoid semaphore sync when we are sure we already * waited for an object with higher seqno */ if (seqno <= from->semaphore.sync_seqno[idx]) @@ -3003,11 +3012,12 @@ i915_gem_object_sync(struct drm_i915_gem_object *obj, trace_i915_gem_ring_sync_to(from, to, seqno); ret = to->semaphore.sync_to(to, from, seqno); if (!ret) - /* We use last_read_seqno because sync_to() + /* We use last_read_req because sync_to() * might have just caused seqno wrap under * the radar. */ - from->semaphore.sync_seqno[idx] = obj->last_read_seqno; + from->semaphore.sync_seqno[idx] = + i915_gem_request_get_seqno(obj->last_read_req); return ret; } @@ -3321,12 +3331,13 @@ static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj, static int i915_gem_object_wait_fence(struct drm_i915_gem_object *obj) { - if (obj->last_fenced_seqno) { - int ret = i915_wait_seqno(obj->ring, obj->last_fenced_seqno); + if (obj->last_fenced_req) { + int ret = i915_wait_seqno(obj->ring, + i915_gem_request_get_seqno(obj->last_fenced_req)); if (ret) return ret; - obj->last_fenced_seqno = 0; + i915_gem_request_assign(&obj->last_fenced_req, NULL); } return 0; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index f06027ba3ee551..4d9baef28e309a 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -946,7 +946,7 @@ void i915_gem_execbuffer_move_to_active(struct list_head *vmas, struct intel_engine_cs *ring) { - u32 seqno = intel_ring_get_seqno(ring); + struct drm_i915_gem_request *req = intel_ring_get_request(ring); struct i915_vma *vma; list_for_each_entry(vma, vmas, exec_list) { @@ -963,7 +963,7 @@ i915_gem_execbuffer_move_to_active(struct list_head *vmas, i915_vma_move_to_active(vma, ring); if (obj->base.write_domain) { obj->dirty = 1; - obj->last_write_seqno = seqno; + i915_gem_request_assign(&obj->last_write_req, req); intel_fb_obj_invalidate(obj, ring); @@ -971,7 +971,7 @@ i915_gem_execbuffer_move_to_active(struct list_head *vmas, obj->base.write_domain &= ~I915_GEM_GPU_DOMAINS; } if (entry->flags & EXEC_OBJECT_NEEDS_FENCE) { - obj->last_fenced_seqno = seqno; + i915_gem_request_assign(&obj->last_fenced_req, req); if (entry->flags & __EXEC_OBJECT_HAS_FENCE) { struct drm_i915_private *dev_priv = to_i915(ring->dev); list_move_tail(&dev_priv->fence_regs[obj->fence_reg].lru_list, diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 92db6654f93ba4..dd849df6a26863 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -181,7 +181,7 @@ struct i915_address_space { * List of objects currently involved in rendering. * * Includes buffers having the contents of their GPU caches - * flushed, not necessarily primitives. last_rendering_seqno + * flushed, not necessarily primitives. last_read_req * represents when the rendering involved will be completed. * * A reference is held on the buffer while on this list. @@ -192,7 +192,7 @@ struct i915_address_space { * LRU list of objects which are not in the ringbuffer and * are ready to unbind, but are still in the GTT. * - * last_rendering_seqno is 0 while an object is in this list. + * last_read_req is NULL while an object is in this list. * * A reference is not held on the buffer while on this list, * as merely being GTT-bound shouldn't prevent its being diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 4727a4e2c87c98..7a24bd1a51f648 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -399,7 +399,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, } obj->fence_dirty = - obj->last_fenced_seqno || + obj->last_fenced_req || obj->fence_reg != I915_FENCE_REG_NONE; obj->tiling_mode = args->tiling_mode; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index eea98d56743107..af0ceeedda9bda 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -670,8 +670,8 @@ static void capture_bo(struct drm_i915_error_buffer *err, err->size = obj->base.size; err->name = obj->base.name; - err->rseqno = obj->last_read_seqno; - err->wseqno = obj->last_write_seqno; + err->rseqno = i915_gem_request_get_seqno(obj->last_read_req); + err->wseqno = i915_gem_request_get_seqno(obj->last_write_req); err->gtt_offset = vma->node.start; err->read_domains = obj->base.read_domains; err->write_domain = obj->base.write_domain; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d54716655d3240..70e75805994bcf 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9637,7 +9637,8 @@ static int intel_queue_mmio_flip(struct drm_device *dev, { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - intel_crtc->mmio_flip.seqno = obj->last_write_seqno; + intel_crtc->mmio_flip.seqno = + i915_gem_request_get_seqno(obj->last_write_req); intel_crtc->mmio_flip.ring = obj->ring; schedule_work(&intel_crtc->mmio_flip.work); @@ -9900,7 +9901,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, if (ret) goto cleanup_unpin; - work->flip_queued_seqno = obj->last_write_seqno; + work->flip_queued_seqno = + i915_gem_request_get_seqno(obj->last_write_req); work->flip_queued_ring = obj->ring; } else { ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, ring, diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 20636e0e9b53b2..dbac132a5cdf56 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -251,7 +251,7 @@ struct intel_engine_cs { * ringbuffer. * * Includes buffers having the contents of their GPU caches - * flushed, not necessarily primitives. last_rendering_seqno + * flushed, not necessarily primitives. last_read_req * represents when the rendering involved will be completed. * * A reference is held on the buffer while on this list. From 54fb2411dd0b4d7d91e9d77536ac84295607a93b Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 24 Nov 2014 18:49:27 +0000 Subject: [PATCH 0052/3023] drm/i915: Convert i915_gem_ring_throttle to use requests Convert the throttle code to use the request structure rather than extracting a ring/seqno pair from it and using those. This is in preparation for __wait_seqno() becoming __wait_request(). For: VIZ-4377 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a1110fb7e583b6..bf0135815a9604 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4098,10 +4098,8 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_file_private *file_priv = file->driver_priv; unsigned long recent_enough = jiffies - msecs_to_jiffies(20); - struct drm_i915_gem_request *request; - struct intel_engine_cs *ring = NULL; + struct drm_i915_gem_request *request, *target = NULL; unsigned reset_counter; - u32 seqno = 0; int ret; ret = i915_gem_wait_for_error(&dev_priv->gpu_error); @@ -4117,16 +4115,17 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) if (time_after_eq(request->emitted_jiffies, recent_enough)) break; - ring = request->ring; - seqno = request->seqno; + target = request; } reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter); spin_unlock(&file_priv->mm.lock); - if (seqno == 0) + if (target == NULL) return 0; - ret = __i915_wait_seqno(ring, seqno, reset_counter, true, NULL, NULL); + ret = __i915_wait_seqno(i915_gem_request_get_ring(target), + i915_gem_request_get_seqno(target), + reset_counter, true, NULL, NULL); if (ret == 0) queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0); From ff8658850aa9bdb5bc308ff8cce60c2558c58566 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 24 Nov 2014 18:49:28 +0000 Subject: [PATCH 0053/3023] drm/i915: Ensure requests stick around during waits Added reference counting of the request structure around __wait_seqno() calls. This is a precursor to updating the wait code itself to take the request rather than a seqno. At that point, it would be a Bad Idea for a request object to be retired and freed while the wait code is still using it. v3: Note that even though the mutex lock is held during a call to i915_wait_seqno(), it is still necessary to explicitly bump the reference count. It appears that the shrinker can asynchronously retire items even though the mutex is locked. For: VIZ-4377 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel [danvet: Remove wrongly squashed hunk which breaks the build.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index bf0135815a9604..8ec07853b35c5f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1417,10 +1417,12 @@ i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj, return ret; reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter); + i915_gem_request_reference(req); mutex_unlock(&dev->struct_mutex); ret = __i915_wait_seqno(ring, seqno, reset_counter, true, NULL, file_priv); mutex_lock(&dev->struct_mutex); + i915_gem_request_unreference(req); if (ret) return ret; @@ -2920,6 +2922,7 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_wait *args = data; struct drm_i915_gem_object *obj; + struct drm_i915_gem_request *req; struct intel_engine_cs *ring = NULL; unsigned reset_counter; u32 seqno = 0; @@ -2946,7 +2949,8 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) if (!obj->active || !obj->last_read_req) goto out; - seqno = i915_gem_request_get_seqno(obj->last_read_req); + req = obj->last_read_req; + seqno = i915_gem_request_get_seqno(req); WARN_ON(seqno == 0); ring = obj->ring; @@ -2960,10 +2964,15 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) drm_gem_object_unreference(&obj->base); reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter); + i915_gem_request_reference(req); mutex_unlock(&dev->struct_mutex); - return __i915_wait_seqno(ring, seqno, reset_counter, true, - &args->timeout_ns, file->driver_priv); + ret = __i915_wait_seqno(ring, seqno, reset_counter, true, &args->timeout_ns, + file->driver_priv); + mutex_lock(&dev->struct_mutex); + i915_gem_request_unreference(req); + mutex_unlock(&dev->struct_mutex); + return ret; out: drm_gem_object_unreference(&obj->base); @@ -4118,6 +4127,8 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) target = request; } reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter); + if (target) + i915_gem_request_reference(target); spin_unlock(&file_priv->mm.lock); if (target == NULL) @@ -4129,6 +4140,10 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) if (ret == 0) queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0); + mutex_lock(&dev->struct_mutex); + i915_gem_request_unreference(target); + mutex_unlock(&dev->struct_mutex); + return ret; } From 6259cead57ebc19325183f8fd9968e19fc2fbe53 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 24 Nov 2014 18:49:29 +0000 Subject: [PATCH 0054/3023] drm/i915: Remove 'outstanding_lazy_seqno' The OLS value is now obsolete. Exactly the same value is guarateed to be always available as PLR->seqno. Thus it is safe to remove the OLS completely. And also to rename the PLR to OLR to keep the 'outstanding lazy ...' naming convention valid. For: VIZ-4377 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 13 +++--- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 4 +- drivers/gpu/drm/i915/intel_display.c | 3 +- drivers/gpu/drm/i915/intel_lrc.c | 26 ++++------- drivers/gpu/drm/i915/intel_ringbuffer.c | 52 +++++++++++----------- drivers/gpu/drm/i915/intel_ringbuffer.h | 13 ++---- 6 files changed, 49 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8ec07853b35c5f..fba22a56650b3d 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1164,7 +1164,7 @@ i915_gem_check_olr(struct intel_engine_cs *ring, u32 seqno) BUG_ON(!mutex_is_locked(&ring->dev->struct_mutex)); ret = 0; - if (seqno == ring->outstanding_lazy_seqno) + if (seqno == i915_gem_request_get_seqno(ring->outstanding_lazy_request)) ret = i915_add_request(ring, NULL); return ret; @@ -2421,7 +2421,7 @@ int __i915_add_request(struct intel_engine_cs *ring, u32 request_ring_position, request_start; int ret; - request = ring->preallocated_lazy_request; + request = ring->outstanding_lazy_request; if (WARN_ON(request == NULL)) return -ENOMEM; @@ -2466,7 +2466,6 @@ int __i915_add_request(struct intel_engine_cs *ring, return ret; } - request->seqno = intel_ring_get_seqno(ring); request->ring = ring; request->head = request_start; request->tail = request_ring_position; @@ -2503,8 +2502,7 @@ int __i915_add_request(struct intel_engine_cs *ring, } trace_i915_gem_request_add(ring, request->seqno); - ring->outstanding_lazy_seqno = 0; - ring->preallocated_lazy_request = NULL; + ring->outstanding_lazy_request = NULL; i915_queue_hangcheck(ring->dev); @@ -2689,9 +2687,8 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv, i915_gem_free_request(request); } - /* These may not have been flush before the reset, do so now */ - i915_gem_request_assign(&ring->preallocated_lazy_request, NULL); - ring->outstanding_lazy_seqno = 0; + /* This may not have been flushed before the reset, so clean it now */ + i915_gem_request_assign(&ring->outstanding_lazy_request, NULL); } void i915_gem_restore_fences(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 4d9baef28e309a..7ecfa918e114ee 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1211,7 +1211,9 @@ i915_gem_ringbuffer_submission(struct drm_device *dev, struct drm_file *file, return ret; } - trace_i915_gem_ring_dispatch(ring, intel_ring_get_seqno(ring), flags); + trace_i915_gem_ring_dispatch(ring, + i915_gem_request_get_seqno(intel_ring_get_request(ring)), + flags); i915_gem_execbuffer_move_to_active(vmas, ring); i915_gem_execbuffer_retire_commands(dev, file, ring, batch_obj); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 70e75805994bcf..30857318df712c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9910,7 +9910,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, if (ret) goto cleanup_unpin; - work->flip_queued_seqno = intel_ring_get_seqno(ring); + work->flip_queued_seqno = + i915_gem_request_get_seqno(intel_ring_get_request(ring)); work->flip_queued_ring = ring; } diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 56c275d0a61021..2f944c48ab923a 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -876,22 +876,14 @@ void intel_lr_context_unpin(struct intel_engine_cs *ring, } } -static int logical_ring_alloc_seqno(struct intel_engine_cs *ring, - struct intel_context *ctx) +static int logical_ring_alloc_request(struct intel_engine_cs *ring, + struct intel_context *ctx) { struct drm_i915_gem_request *request; int ret; - /* XXX: The aim is to replace seqno values with request structures. - * A step along the way is to switch to using the PLR in preference - * to the OLS. That requires the PLR to only be valid when the OLS is - * also valid. I.e., the two must be kept in step. */ - - if (ring->outstanding_lazy_seqno) { - WARN_ON(ring->preallocated_lazy_request == NULL); + if (ring->outstanding_lazy_request) return 0; - } - WARN_ON(ring->preallocated_lazy_request != NULL); request = kmalloc(sizeof(*request), GFP_KERNEL); if (request == NULL) @@ -907,7 +899,7 @@ static int logical_ring_alloc_seqno(struct intel_engine_cs *ring, kref_init(&request->ref); - ret = i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_seqno); + ret = i915_gem_get_seqno(ring->dev, &request->seqno); if (ret) { intel_lr_context_unpin(ring, ctx); kfree(request); @@ -921,7 +913,7 @@ static int logical_ring_alloc_seqno(struct intel_engine_cs *ring, request->ctx = ctx; i915_gem_context_reference(request->ctx); - ring->preallocated_lazy_request = request; + ring->outstanding_lazy_request = request; return 0; } @@ -1098,7 +1090,7 @@ int intel_logical_ring_begin(struct intel_ringbuffer *ringbuf, int num_dwords) return ret; /* Preallocate the olr before touching the ring */ - ret = logical_ring_alloc_seqno(ring, ringbuf->FIXME_lrc_ctx); + ret = logical_ring_alloc_request(ring, ringbuf->FIXME_lrc_ctx); if (ret) return ret; @@ -1351,7 +1343,8 @@ static int gen8_emit_request(struct intel_ringbuffer *ringbuf) (ring->status_page.gfx_addr + (I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT))); intel_logical_ring_emit(ringbuf, 0); - intel_logical_ring_emit(ringbuf, ring->outstanding_lazy_seqno); + intel_logical_ring_emit(ringbuf, + i915_gem_request_get_seqno(ring->outstanding_lazy_request)); intel_logical_ring_emit(ringbuf, MI_USER_INTERRUPT); intel_logical_ring_emit(ringbuf, MI_NOOP); intel_logical_ring_advance_and_submit(ringbuf); @@ -1376,8 +1369,7 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *ring) intel_logical_ring_stop(ring); WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0); - i915_gem_request_assign(&ring->preallocated_lazy_request, NULL); - ring->outstanding_lazy_seqno = 0; + i915_gem_request_assign(&ring->outstanding_lazy_request, NULL); if (ring->cleanup) ring->cleanup(ring); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index fbeaa3ad6208aa..accfc893876582 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -911,17 +911,20 @@ static int gen8_rcs_signal(struct intel_engine_cs *signaller, return ret; for_each_ring(waiter, dev_priv, i) { + u32 seqno; u64 gtt_offset = signaller->semaphore.signal_ggtt[i]; if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) continue; + seqno = i915_gem_request_get_seqno( + signaller->outstanding_lazy_request); intel_ring_emit(signaller, GFX_OP_PIPE_CONTROL(6)); intel_ring_emit(signaller, PIPE_CONTROL_GLOBAL_GTT_IVB | PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_FLUSH_ENABLE); intel_ring_emit(signaller, lower_32_bits(gtt_offset)); intel_ring_emit(signaller, upper_32_bits(gtt_offset)); - intel_ring_emit(signaller, signaller->outstanding_lazy_seqno); + intel_ring_emit(signaller, seqno); intel_ring_emit(signaller, 0); intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL | MI_SEMAPHORE_TARGET(waiter->id)); @@ -949,16 +952,19 @@ static int gen8_xcs_signal(struct intel_engine_cs *signaller, return ret; for_each_ring(waiter, dev_priv, i) { + u32 seqno; u64 gtt_offset = signaller->semaphore.signal_ggtt[i]; if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) continue; + seqno = i915_gem_request_get_seqno( + signaller->outstanding_lazy_request); intel_ring_emit(signaller, (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW); intel_ring_emit(signaller, lower_32_bits(gtt_offset) | MI_FLUSH_DW_USE_GTT); intel_ring_emit(signaller, upper_32_bits(gtt_offset)); - intel_ring_emit(signaller, signaller->outstanding_lazy_seqno); + intel_ring_emit(signaller, seqno); intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL | MI_SEMAPHORE_TARGET(waiter->id)); intel_ring_emit(signaller, 0); @@ -987,9 +993,11 @@ static int gen6_signal(struct intel_engine_cs *signaller, for_each_ring(useless, dev_priv, i) { u32 mbox_reg = signaller->semaphore.mbox.signal[i]; if (mbox_reg != GEN6_NOSYNC) { + u32 seqno = i915_gem_request_get_seqno( + signaller->outstanding_lazy_request); intel_ring_emit(signaller, MI_LOAD_REGISTER_IMM(1)); intel_ring_emit(signaller, mbox_reg); - intel_ring_emit(signaller, signaller->outstanding_lazy_seqno); + intel_ring_emit(signaller, seqno); } } @@ -1024,7 +1032,8 @@ gen6_add_request(struct intel_engine_cs *ring) intel_ring_emit(ring, MI_STORE_DWORD_INDEX); intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); - intel_ring_emit(ring, ring->outstanding_lazy_seqno); + intel_ring_emit(ring, + i915_gem_request_get_seqno(ring->outstanding_lazy_request)); intel_ring_emit(ring, MI_USER_INTERRUPT); __intel_ring_advance(ring); @@ -1142,7 +1151,8 @@ pc_render_add_request(struct intel_engine_cs *ring) PIPE_CONTROL_WRITE_FLUSH | PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE); intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); - intel_ring_emit(ring, ring->outstanding_lazy_seqno); + intel_ring_emit(ring, + i915_gem_request_get_seqno(ring->outstanding_lazy_request)); intel_ring_emit(ring, 0); PIPE_CONTROL_FLUSH(ring, scratch_addr); scratch_addr += 2 * CACHELINE_BYTES; /* write to separate cachelines */ @@ -1161,7 +1171,8 @@ pc_render_add_request(struct intel_engine_cs *ring) PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | PIPE_CONTROL_NOTIFY); intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); - intel_ring_emit(ring, ring->outstanding_lazy_seqno); + intel_ring_emit(ring, + i915_gem_request_get_seqno(ring->outstanding_lazy_request)); intel_ring_emit(ring, 0); __intel_ring_advance(ring); @@ -1401,7 +1412,8 @@ i9xx_add_request(struct intel_engine_cs *ring) intel_ring_emit(ring, MI_STORE_DWORD_INDEX); intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); - intel_ring_emit(ring, ring->outstanding_lazy_seqno); + intel_ring_emit(ring, + i915_gem_request_get_seqno(ring->outstanding_lazy_request)); intel_ring_emit(ring, MI_USER_INTERRUPT); __intel_ring_advance(ring); @@ -1870,8 +1882,7 @@ void intel_cleanup_ring_buffer(struct intel_engine_cs *ring) intel_unpin_ringbuffer_obj(ringbuf); intel_destroy_ringbuffer_obj(ringbuf); - i915_gem_request_assign(&ring->preallocated_lazy_request, NULL); - ring->outstanding_lazy_seqno = 0; + i915_gem_request_assign(&ring->outstanding_lazy_request, NULL); if (ring->cleanup) ring->cleanup(ring); @@ -2004,7 +2015,7 @@ int intel_ring_idle(struct intel_engine_cs *ring) int ret; /* We need to add any requests required to flush the objects and ring */ - if (ring->outstanding_lazy_seqno) { + if (ring->outstanding_lazy_request) { ret = i915_add_request(ring, NULL); if (ret) return ret; @@ -2022,22 +2033,13 @@ int intel_ring_idle(struct intel_engine_cs *ring) } static int -intel_ring_alloc_seqno(struct intel_engine_cs *ring) +intel_ring_alloc_request(struct intel_engine_cs *ring) { int ret; struct drm_i915_gem_request *request; - /* XXX: The aim is to replace seqno values with request structures. - * A step along the way is to switch to using the PLR in preference - * to the OLS. That requires the PLR to only be valid when the OLS - * is also valid. I.e., the two must be kept in step. */ - - if (ring->outstanding_lazy_seqno) { - WARN_ON(ring->preallocated_lazy_request == NULL); + if (ring->outstanding_lazy_request) return 0; - } - - WARN_ON(ring->preallocated_lazy_request != NULL); request = kmalloc(sizeof(*request), GFP_KERNEL); if (request == NULL) @@ -2045,13 +2047,13 @@ intel_ring_alloc_seqno(struct intel_engine_cs *ring) kref_init(&request->ref); - ret = i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_seqno); + ret = i915_gem_get_seqno(ring->dev, &request->seqno); if (ret) { kfree(request); return ret; } - ring->preallocated_lazy_request = request; + ring->outstanding_lazy_request = request; return 0; } @@ -2092,7 +2094,7 @@ int intel_ring_begin(struct intel_engine_cs *ring, return ret; /* Preallocate the olr before touching the ring */ - ret = intel_ring_alloc_seqno(ring); + ret = intel_ring_alloc_request(ring); if (ret) return ret; @@ -2127,7 +2129,7 @@ void intel_ring_init_seqno(struct intel_engine_cs *ring, u32 seqno) struct drm_device *dev = ring->dev; struct drm_i915_private *dev_priv = dev->dev_private; - BUG_ON(ring->outstanding_lazy_seqno); + BUG_ON(ring->outstanding_lazy_request); if (INTEL_INFO(dev)->gen == 6 || INTEL_INFO(dev)->gen == 7) { I915_WRITE(RING_SYNC_0(ring->mmio_base), 0); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index dbac132a5cdf56..2a84bd9688a871 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -267,8 +267,7 @@ struct intel_engine_cs { /** * Do we have some not yet emitted requests outstanding? */ - struct drm_i915_gem_request *preallocated_lazy_request; - u32 outstanding_lazy_seqno; + struct drm_i915_gem_request *outstanding_lazy_request; bool gpu_caches_dirty; bool fbc_dirty; @@ -436,17 +435,11 @@ static inline u32 intel_ring_get_tail(struct intel_ringbuffer *ringbuf) return ringbuf->tail; } -static inline u32 intel_ring_get_seqno(struct intel_engine_cs *ring) -{ - BUG_ON(ring->outstanding_lazy_seqno == 0); - return ring->outstanding_lazy_seqno; -} - static inline struct drm_i915_gem_request * intel_ring_get_request(struct intel_engine_cs *ring) { - BUG_ON(ring->preallocated_lazy_request == NULL); - return ring->preallocated_lazy_request; + BUG_ON(ring->outstanding_lazy_request == NULL); + return ring->outstanding_lazy_request; } static inline void i915_trace_irq_get(struct intel_engine_cs *ring, u32 seqno) From b6660d59f66835e4e99eaa772ea4cb74f96f4de3 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 24 Nov 2014 18:49:30 +0000 Subject: [PATCH 0055/3023] drm/i915: Make 'i915_gem_check_olr' actually check by request not seqno Updated the _check_olr() function to actually take a request object and compare it to the OLR rather than extracting seqnos and comparing those. Note that there is one use case where the request object being processed is no longer available at that point in the call stack. Hence a temporary copy of the original function is still present (but called _check_ols() instead). This will be removed in a subsequent patch. Also, downgraded a BUG_ON to a WARN_ON as apparently the former is frowned upon for shipping code. For: VIZ-4377 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 18 +++++++++++++++++- drivers/gpu/drm/i915/i915_gem.c | 28 +++++++++++----------------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4924f1d3d4b415..e6a997cd0cd0a7 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2577,7 +2577,7 @@ bool i915_gem_retire_requests(struct drm_device *dev); void i915_gem_retire_requests_ring(struct intel_engine_cs *ring); int __must_check i915_gem_check_wedge(struct i915_gpu_error *error, bool interruptible); -int __must_check i915_gem_check_olr(struct intel_engine_cs *ring, u32 seqno); +int __must_check i915_gem_check_olr(struct drm_i915_gem_request *req); static inline bool i915_reset_in_progress(struct i915_gpu_error *error) { @@ -3117,4 +3117,20 @@ wait_remaining_ms_from_jiffies(unsigned long timestamp_jiffies, int to_wait_ms) } } +/* XXX: Temporary solution to be removed later in patch series. */ +static inline int __must_check i915_gem_check_ols( + struct intel_engine_cs *ring, u32 seqno) +{ + int ret; + + WARN_ON(!mutex_is_locked(&ring->dev->struct_mutex)); + + ret = 0; + if (seqno == i915_gem_request_get_seqno(ring->outstanding_lazy_request)) + ret = i915_add_request(ring, NULL); + + return ret; +} +/* XXX: Temporary solution to be removed later in patch series. */ + #endif diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index fba22a56650b3d..7d6f9bc9ebb57e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1153,19 +1153,18 @@ i915_gem_check_wedge(struct i915_gpu_error *error, } /* - * Compare seqno against outstanding lazy request. Emit a request if they are - * equal. + * Compare arbitrary request against outstanding lazy request. Emit on match. */ int -i915_gem_check_olr(struct intel_engine_cs *ring, u32 seqno) +i915_gem_check_olr(struct drm_i915_gem_request *req) { int ret; - BUG_ON(!mutex_is_locked(&ring->dev->struct_mutex)); + WARN_ON(!mutex_is_locked(&req->ring->dev->struct_mutex)); ret = 0; - if (seqno == i915_gem_request_get_seqno(ring->outstanding_lazy_request)) - ret = i915_add_request(ring, NULL); + if (req == req->ring->outstanding_lazy_request) + ret = i915_add_request(req->ring, NULL); return ret; } @@ -1328,7 +1327,7 @@ i915_wait_seqno(struct intel_engine_cs *ring, uint32_t seqno) if (ret) return ret; - ret = i915_gem_check_olr(ring, seqno); + ret = i915_gem_check_ols(ring, seqno); if (ret) return ret; @@ -1395,7 +1394,6 @@ i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj, struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *ring = obj->ring; unsigned reset_counter; - u32 seqno; int ret; BUG_ON(!mutex_is_locked(&dev->struct_mutex)); @@ -1405,22 +1403,19 @@ i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj, if (!req) return 0; - seqno = i915_gem_request_get_seqno(req); - WARN_ON(seqno == 0); - ret = i915_gem_check_wedge(&dev_priv->gpu_error, true); if (ret) return ret; - ret = i915_gem_check_olr(ring, seqno); + ret = i915_gem_check_olr(req); if (ret) return ret; reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter); i915_gem_request_reference(req); mutex_unlock(&dev->struct_mutex); - ret = __i915_wait_seqno(ring, seqno, reset_counter, true, NULL, - file_priv); + ret = __i915_wait_seqno(ring, i915_gem_request_get_seqno(req), + reset_counter, true, NULL, file_priv); mutex_lock(&dev->struct_mutex); i915_gem_request_unreference(req); if (ret) @@ -2880,8 +2875,7 @@ i915_gem_object_flush_active(struct drm_i915_gem_object *obj) int ret; if (obj->active) { - ret = i915_gem_check_olr(obj->ring, - i915_gem_request_get_seqno(obj->last_read_req)); + ret = i915_gem_check_olr(obj->last_read_req); if (ret) return ret; @@ -3011,7 +3005,7 @@ i915_gem_object_sync(struct drm_i915_gem_object *obj, if (seqno <= from->semaphore.sync_seqno[idx]) return 0; - ret = i915_gem_check_olr(obj->ring, seqno); + ret = i915_gem_check_olr(obj->last_read_req); if (ret) return ret; From 9bfc01a29b7d4d6b965a596b047b405bf6f58be1 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 24 Nov 2014 18:49:31 +0000 Subject: [PATCH 0056/3023] drm/i915: Convert 'last_flip_req' to be a request not a seqno Converted 'last_flip_req' to be an actual request rather than a seqno value as part of the on going seqno to request changes. This includes reference counting the request being saved away to ensure it can not be retired and freed while the overlay code is still waiting on it. For: VIZ-4377 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_overlay.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index dc2f4f26c961e0..5defc37d8adb10 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -182,7 +182,7 @@ struct intel_overlay { u32 flip_addr; struct drm_i915_gem_object *reg_bo; /* flip handling */ - uint32_t last_flip_req; + struct drm_i915_gem_request *last_flip_req; void (*flip_tail)(struct intel_overlay *); }; @@ -217,17 +217,20 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay, int ret; BUG_ON(overlay->last_flip_req); - ret = i915_add_request(ring, &overlay->last_flip_req); + i915_gem_request_assign(&overlay->last_flip_req, + ring->outstanding_lazy_request); + ret = i915_add_request(ring, NULL); if (ret) return ret; overlay->flip_tail = tail; - ret = i915_wait_seqno(ring, overlay->last_flip_req); + ret = i915_wait_seqno(ring, + i915_gem_request_get_seqno(overlay->last_flip_req)); if (ret) return ret; i915_gem_retire_requests(dev); - overlay->last_flip_req = 0; + i915_gem_request_assign(&overlay->last_flip_req, NULL); return 0; } @@ -286,7 +289,10 @@ static int intel_overlay_continue(struct intel_overlay *overlay, intel_ring_emit(ring, flip_addr); intel_ring_advance(ring); - return i915_add_request(ring, &overlay->last_flip_req); + WARN_ON(overlay->last_flip_req); + i915_gem_request_assign(&overlay->last_flip_req, + ring->outstanding_lazy_request); + return i915_add_request(ring, NULL); } static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay) @@ -366,10 +372,11 @@ static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay) struct intel_engine_cs *ring = &dev_priv->ring[RCS]; int ret; - if (overlay->last_flip_req == 0) + if (overlay->last_flip_req == NULL) return 0; - ret = i915_wait_seqno(ring, overlay->last_flip_req); + ret = i915_wait_seqno(ring, + i915_gem_request_get_seqno(overlay->last_flip_req)); if (ret) return ret; i915_gem_retire_requests(dev); @@ -377,7 +384,7 @@ static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay) if (overlay->flip_tail) overlay->flip_tail(overlay); - overlay->last_flip_req = 0; + i915_gem_request_assign(&overlay->last_flip_req, NULL); return 0; } From a4b3a5713d9f1ca94762b468117f918d3b15e5c4 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 26 Nov 2014 14:17:05 +0100 Subject: [PATCH 0057/3023] drm/i915: Convert i915_wait_seqno to i915_wait_request Updated i915_wait_seqno() to take a request structure instead of a seqno value and renamed it accordingly. Internally, it just pulls the seqno out of the request and calls on to __wait_seqno() as before. However, all the code further up the stack is now simplified as it can just pass the request object straight through without having to peek inside. For: VIZ-4377 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel [danvet: Squash in hunk from an earlier patch which was rebased wrongly.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 19 +------------ drivers/gpu/drm/i915/i915_gem.c | 36 +++++++++++++------------ drivers/gpu/drm/i915/intel_lrc.c | 6 ++--- drivers/gpu/drm/i915/intel_overlay.c | 11 +++----- drivers/gpu/drm/i915/intel_ringbuffer.c | 14 +++++----- 5 files changed, 31 insertions(+), 55 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e6a997cd0cd0a7..23a1afd2f7cab7 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2629,8 +2629,7 @@ int __i915_wait_seqno(struct intel_engine_cs *ring, u32 seqno, bool interruptible, s64 *timeout, struct drm_i915_file_private *file_priv); -int __must_check i915_wait_seqno(struct intel_engine_cs *ring, - uint32_t seqno); +int __must_check i915_wait_request(struct drm_i915_gem_request *req); int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); int __must_check i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, @@ -3117,20 +3116,4 @@ wait_remaining_ms_from_jiffies(unsigned long timestamp_jiffies, int to_wait_ms) } } -/* XXX: Temporary solution to be removed later in patch series. */ -static inline int __must_check i915_gem_check_ols( - struct intel_engine_cs *ring, u32 seqno) -{ - int ret; - - WARN_ON(!mutex_is_locked(&ring->dev->struct_mutex)); - - ret = 0; - if (seqno == i915_gem_request_get_seqno(ring->outstanding_lazy_request)) - ret = i915_add_request(ring, NULL); - - return ret; -} -/* XXX: Temporary solution to be removed later in patch series. */ - #endif diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 7d6f9bc9ebb57e..1089f0ff5ee3f6 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1308,32 +1308,40 @@ int __i915_wait_seqno(struct intel_engine_cs *ring, u32 seqno, } /** - * Waits for a sequence number to be signaled, and cleans up the + * Waits for a request to be signaled, and cleans up the * request and object lists appropriately for that event. */ int -i915_wait_seqno(struct intel_engine_cs *ring, uint32_t seqno) +i915_wait_request(struct drm_i915_gem_request *req) { - struct drm_device *dev = ring->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - bool interruptible = dev_priv->mm.interruptible; + struct drm_device *dev; + struct drm_i915_private *dev_priv; + bool interruptible; unsigned reset_counter; int ret; + BUG_ON(req == NULL); + + dev = req->ring->dev; + dev_priv = dev->dev_private; + interruptible = dev_priv->mm.interruptible; + BUG_ON(!mutex_is_locked(&dev->struct_mutex)); - BUG_ON(seqno == 0); ret = i915_gem_check_wedge(&dev_priv->gpu_error, interruptible); if (ret) return ret; - ret = i915_gem_check_ols(ring, seqno); + ret = i915_gem_check_olr(req); if (ret) return ret; reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter); - return __i915_wait_seqno(ring, seqno, reset_counter, interruptible, - NULL, NULL); + i915_gem_request_reference(req); + ret = __i915_wait_seqno(req->ring, i915_gem_request_get_seqno(req), + reset_counter, interruptible, NULL, NULL); + i915_gem_request_unreference(req); + return ret; } static int @@ -1363,18 +1371,13 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj, bool readonly) { struct drm_i915_gem_request *req; - struct intel_engine_cs *ring = obj->ring; - u32 seqno; int ret; req = readonly ? obj->last_write_req : obj->last_read_req; if (!req) return 0; - seqno = i915_gem_request_get_seqno(req); - WARN_ON(seqno == 0); - - ret = i915_wait_seqno(ring, seqno); + ret = i915_wait_request(req); if (ret) return ret; @@ -3332,8 +3335,7 @@ static int i915_gem_object_wait_fence(struct drm_i915_gem_object *obj) { if (obj->last_fenced_req) { - int ret = i915_wait_seqno(obj->ring, - i915_gem_request_get_seqno(obj->last_fenced_req)); + int ret = i915_wait_request(obj->last_fenced_req); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 2f944c48ab923a..8d0b8ac2748a49 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -922,7 +922,6 @@ static int logical_ring_wait_request(struct intel_ringbuffer *ringbuf, { struct intel_engine_cs *ring = ringbuf->ring; struct drm_i915_gem_request *request; - u32 seqno = 0; int ret; if (ringbuf->last_retired_head != -1) { @@ -947,15 +946,14 @@ static int logical_ring_wait_request(struct intel_ringbuffer *ringbuf, /* Would completion of this request free enough space? */ if (__intel_ring_space(request->tail, ringbuf->tail, ringbuf->size) >= bytes) { - seqno = request->seqno; break; } } - if (seqno == 0) + if (&request->list == &ring->request_list) return -ENOSPC; - ret = i915_wait_seqno(ring, seqno); + ret = i915_wait_request(request); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 5defc37d8adb10..6c530e298b649b 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -224,8 +224,7 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay, return ret; overlay->flip_tail = tail; - ret = i915_wait_seqno(ring, - i915_gem_request_get_seqno(overlay->last_flip_req)); + ret = i915_wait_request(overlay->last_flip_req); if (ret) return ret; i915_gem_retire_requests(dev); @@ -367,19 +366,15 @@ static int intel_overlay_off(struct intel_overlay *overlay) * We have to be careful not to repeat work forever an make forward progess. */ static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay) { - struct drm_device *dev = overlay->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring = &dev_priv->ring[RCS]; int ret; if (overlay->last_flip_req == NULL) return 0; - ret = i915_wait_seqno(ring, - i915_gem_request_get_seqno(overlay->last_flip_req)); + ret = i915_wait_request(overlay->last_flip_req); if (ret) return ret; - i915_gem_retire_requests(dev); + i915_gem_retire_requests(overlay->dev); if (overlay->flip_tail) overlay->flip_tail(overlay); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index accfc893876582..b9d0d29f83430a 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1899,7 +1899,6 @@ static int intel_ring_wait_request(struct intel_engine_cs *ring, int n) { struct intel_ringbuffer *ringbuf = ring->buffer; struct drm_i915_gem_request *request; - u32 seqno = 0; int ret; if (ringbuf->last_retired_head != -1) { @@ -1914,15 +1913,14 @@ static int intel_ring_wait_request(struct intel_engine_cs *ring, int n) list_for_each_entry(request, &ring->request_list, list) { if (__intel_ring_space(request->tail, ringbuf->tail, ringbuf->size) >= n) { - seqno = request->seqno; break; } } - if (seqno == 0) + if (&request->list == &ring->request_list) return -ENOSPC; - ret = i915_wait_seqno(ring, seqno); + ret = i915_wait_request(request); if (ret) return ret; @@ -2011,7 +2009,7 @@ static int intel_wrap_ring_buffer(struct intel_engine_cs *ring) int intel_ring_idle(struct intel_engine_cs *ring) { - u32 seqno; + struct drm_i915_gem_request *req; int ret; /* We need to add any requests required to flush the objects and ring */ @@ -2025,11 +2023,11 @@ int intel_ring_idle(struct intel_engine_cs *ring) if (list_empty(&ring->request_list)) return 0; - seqno = list_entry(ring->request_list.prev, + req = list_entry(ring->request_list.prev, struct drm_i915_gem_request, - list)->seqno; + list); - return i915_wait_seqno(ring, seqno); + return i915_wait_request(req); } static int From f245860ece9b18394b679c2c55738babc904f506 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 26 Nov 2014 10:26:05 +0100 Subject: [PATCH 0058/3023] drm/i915: Check locking in i915_gem_request_unreference With refcounting it looks like you can just drop that refcount, but that's not really the case. So make sure no one forgets. Motivated by the unlocked call in the mmio flip code. Cc: John Harrison Cc: Thomas Daniel Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 23a1afd2f7cab7..9a9372a42c97a3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2046,6 +2046,7 @@ i915_gem_request_reference(struct drm_i915_gem_request *req) static inline void i915_gem_request_unreference(struct drm_i915_gem_request *req) { + WARN_ON(!mutex_is_locked(&req->ring->dev->struct_mutex)); kref_put(&req->ref, i915_gem_request_free); } From cc8c4cc2a0cee06ecdd27aa654e26ec3b2b05048 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 24 Nov 2014 18:49:34 +0000 Subject: [PATCH 0059/3023] drm/i915: Convert mmio_flip::seqno to struct request Converted the mmio_flip 'seqno' value to be a request structure as part of the on going seqno to request changes. This includes reference counting the request being saved away to ensure it can not be retired and freed while the flip code is still waiting on it. v2: Used the IRQ friendly request dereference call in the notify handler as that code is called asynchronously without holding any useful mutex locks. For: VIZ-4377 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel [danvet: Drop the _irq variant and use the normal reques unref, wrapped in dev->struct_mutex per the discussion on the m-l.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 29 +++++++++++++++------------- drivers/gpu/drm/i915/intel_drv.h | 3 +-- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 30857318df712c..61c402485f36b2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9612,20 +9612,24 @@ static void intel_do_mmio_flip(struct intel_crtc *intel_crtc) static void intel_mmio_flip_work_func(struct work_struct *work) { - struct intel_crtc *intel_crtc = + struct intel_crtc *crtc = container_of(work, struct intel_crtc, mmio_flip.work); - struct intel_engine_cs *ring; - uint32_t seqno; + struct intel_mmio_flip *mmio_flip; - seqno = intel_crtc->mmio_flip.seqno; - ring = intel_crtc->mmio_flip.ring; - - if (seqno) - WARN_ON(__i915_wait_seqno(ring, seqno, - intel_crtc->reset_counter, + mmio_flip = &crtc->mmio_flip; + if (mmio_flip->req) + WARN_ON(__i915_wait_seqno(i915_gem_request_get_ring(mmio_flip->req), + i915_gem_request_get_seqno(mmio_flip->req), + crtc->reset_counter, false, NULL, NULL) != 0); - intel_do_mmio_flip(intel_crtc); + intel_do_mmio_flip(crtc); + if (mmio_flip->req) { + mutex_lock(&crtc->base.dev->struct_mutex); + i915_gem_request_unreference(mmio_flip->req); + mutex_unlock(&crtc->base.dev->struct_mutex); + } + mmio_flip->req = NULL; } static int intel_queue_mmio_flip(struct drm_device *dev, @@ -9637,9 +9641,8 @@ static int intel_queue_mmio_flip(struct drm_device *dev, { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - intel_crtc->mmio_flip.seqno = - i915_gem_request_get_seqno(obj->last_write_req); - intel_crtc->mmio_flip.ring = obj->ring; + i915_gem_request_assign(&intel_crtc->mmio_flip.req, + obj->last_write_req); schedule_work(&intel_crtc->mmio_flip.work); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 5e81f097132c1e..6f87e3cbd68d45 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -406,8 +406,7 @@ struct intel_pipe_wm { }; struct intel_mmio_flip { - u32 seqno; - struct intel_engine_cs *ring; + struct drm_i915_gem_request *req; struct work_struct work; }; From 9c654818295eee21720e62040e235e6951b05b40 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 24 Nov 2014 18:49:35 +0000 Subject: [PATCH 0060/3023] drm/i915: Convert __wait_seqno() to __wait_request() Now that all code above is using request structures instead of seqno values, it is possible to convert __wait_seqno() itself. Internally, it is still calling i915_seqno_passed(), this will be updated later in the series. This step is just changing the parameter list and function name. For: VIZ-4377 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 45 +++++++++++++--------------- drivers/gpu/drm/i915/intel_display.c | 7 ++--- 3 files changed, 24 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9a9372a42c97a3..69a0e00039c677 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2625,7 +2625,7 @@ int __i915_add_request(struct intel_engine_cs *ring, u32 *seqno); #define i915_add_request(ring, seqno) \ __i915_add_request(ring, NULL, NULL, seqno) -int __i915_wait_seqno(struct intel_engine_cs *ring, u32 seqno, +int __i915_wait_request(struct drm_i915_gem_request *req, unsigned reset_counter, bool interruptible, s64 *timeout, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 1089f0ff5ee3f6..3f56f50900bd95 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1189,10 +1189,9 @@ static bool can_wait_boost(struct drm_i915_file_private *file_priv) } /** - * __i915_wait_seqno - wait until execution of seqno has finished - * @ring: the ring expected to report seqno - * @seqno: duh! - * @reset_counter: reset sequence associated with the given seqno + * __i915_wait_request - wait until execution of request has finished + * @req: duh! + * @reset_counter: reset sequence associated with the given request * @interruptible: do an interruptible wait (normally yes) * @timeout: in - how long to wait (NULL forever); out - how much time remaining * @@ -1203,15 +1202,16 @@ static bool can_wait_boost(struct drm_i915_file_private *file_priv) * reset_counter _must_ be read before, and an appropriate smp_rmb must be * inserted. * - * Returns 0 if the seqno was found within the alloted time. Else returns the + * Returns 0 if the request was found within the alloted time. Else returns the * errno with remaining time filled in timeout argument. */ -int __i915_wait_seqno(struct intel_engine_cs *ring, u32 seqno, +int __i915_wait_request(struct drm_i915_gem_request *req, unsigned reset_counter, bool interruptible, s64 *timeout, struct drm_i915_file_private *file_priv) { + struct intel_engine_cs *ring = i915_gem_request_get_ring(req); struct drm_device *dev = ring->dev; struct drm_i915_private *dev_priv = dev->dev_private; const bool irq_test_in_progress = @@ -1223,7 +1223,8 @@ int __i915_wait_seqno(struct intel_engine_cs *ring, u32 seqno, WARN(!intel_irqs_enabled(dev_priv), "IRQs disabled"); - if (i915_seqno_passed(ring->get_seqno(ring, true), seqno)) + if (i915_seqno_passed(ring->get_seqno(ring, true), + i915_gem_request_get_seqno(req))) return 0; timeout_expire = timeout ? jiffies + nsecs_to_jiffies((u64)*timeout) : 0; @@ -1240,7 +1241,8 @@ int __i915_wait_seqno(struct intel_engine_cs *ring, u32 seqno, return -ENODEV; /* Record current time in case interrupted by signal, or wedged */ - trace_i915_gem_request_wait_begin(ring, seqno); + trace_i915_gem_request_wait_begin(i915_gem_request_get_ring(req), + i915_gem_request_get_seqno(req)); before = ktime_get_raw_ns(); for (;;) { struct timer_list timer; @@ -1259,7 +1261,8 @@ int __i915_wait_seqno(struct intel_engine_cs *ring, u32 seqno, break; } - if (i915_seqno_passed(ring->get_seqno(ring, false), seqno)) { + if (i915_seqno_passed(ring->get_seqno(ring, false), + i915_gem_request_get_seqno(req))) { ret = 0; break; } @@ -1291,7 +1294,8 @@ int __i915_wait_seqno(struct intel_engine_cs *ring, u32 seqno, } } now = ktime_get_raw_ns(); - trace_i915_gem_request_wait_end(ring, seqno); + trace_i915_gem_request_wait_end(i915_gem_request_get_ring(req), + i915_gem_request_get_seqno(req)); if (!irq_test_in_progress) ring->irq_put(ring); @@ -1338,8 +1342,8 @@ i915_wait_request(struct drm_i915_gem_request *req) reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter); i915_gem_request_reference(req); - ret = __i915_wait_seqno(req->ring, i915_gem_request_get_seqno(req), - reset_counter, interruptible, NULL, NULL); + ret = __i915_wait_request(req, reset_counter, + interruptible, NULL, NULL); i915_gem_request_unreference(req); return ret; } @@ -1395,7 +1399,6 @@ i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj, struct drm_i915_gem_request *req; struct drm_device *dev = obj->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring = obj->ring; unsigned reset_counter; int ret; @@ -1417,8 +1420,7 @@ i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj, reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter); i915_gem_request_reference(req); mutex_unlock(&dev->struct_mutex); - ret = __i915_wait_seqno(ring, i915_gem_request_get_seqno(req), - reset_counter, true, NULL, file_priv); + ret = __i915_wait_request(req, reset_counter, true, NULL, file_priv); mutex_lock(&dev->struct_mutex); i915_gem_request_unreference(req); if (ret) @@ -2917,9 +2919,7 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) struct drm_i915_gem_wait *args = data; struct drm_i915_gem_object *obj; struct drm_i915_gem_request *req; - struct intel_engine_cs *ring = NULL; unsigned reset_counter; - u32 seqno = 0; int ret = 0; if (args->flags != 0) @@ -2944,9 +2944,6 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) goto out; req = obj->last_read_req; - seqno = i915_gem_request_get_seqno(req); - WARN_ON(seqno == 0); - ring = obj->ring; /* Do this after OLR check to make sure we make forward progress polling * on this IOCTL with a timeout <=0 (like busy ioctl) @@ -2961,8 +2958,8 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) i915_gem_request_reference(req); mutex_unlock(&dev->struct_mutex); - ret = __i915_wait_seqno(ring, seqno, reset_counter, true, &args->timeout_ns, - file->driver_priv); + ret = __i915_wait_request(req, reset_counter, true, &args->timeout_ns, + file->driver_priv); mutex_lock(&dev->struct_mutex); i915_gem_request_unreference(req); mutex_unlock(&dev->struct_mutex); @@ -4127,9 +4124,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) if (target == NULL) return 0; - ret = __i915_wait_seqno(i915_gem_request_get_ring(target), - i915_gem_request_get_seqno(target), - reset_counter, true, NULL, NULL); + ret = __i915_wait_request(target, reset_counter, true, NULL, NULL); if (ret == 0) queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 61c402485f36b2..0eaa1f48efcfbf 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9618,10 +9618,9 @@ static void intel_mmio_flip_work_func(struct work_struct *work) mmio_flip = &crtc->mmio_flip; if (mmio_flip->req) - WARN_ON(__i915_wait_seqno(i915_gem_request_get_ring(mmio_flip->req), - i915_gem_request_get_seqno(mmio_flip->req), - crtc->reset_counter, - false, NULL, NULL) != 0); + WARN_ON(__i915_wait_request(mmio_flip->req, + crtc->reset_counter, + false, NULL, NULL) != 0); intel_do_mmio_flip(crtc); if (mmio_flip->req) { From 9400ae5c8248dd29c55f2c2355b71e55995774d3 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 24 Nov 2014 18:49:36 +0000 Subject: [PATCH 0061/3023] drm/i915: Remove obsolete seqno parameter from 'i915_add_request' There is no longer any need to retrieve a seqno value from an i915_add_request() call. The calling code already knows which request structure is being processed (it can only be ring->OLR). And as the request itself is now used in preference to the basic seqno value, the latter is now redundant in this situation. For: VIZ-4377 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 7 +++---- drivers/gpu/drm/i915/i915_gem.c | 7 ++----- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 +- drivers/gpu/drm/i915/i915_gem_render_state.c | 2 +- drivers/gpu/drm/i915/intel_lrc.c | 2 +- drivers/gpu/drm/i915/intel_overlay.c | 4 ++-- drivers/gpu/drm/i915/intel_ringbuffer.c | 2 +- 7 files changed, 11 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 69a0e00039c677..d4e1fa757a34e4 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2621,10 +2621,9 @@ int __must_check i915_gpu_idle(struct drm_device *dev); int __must_check i915_gem_suspend(struct drm_device *dev); int __i915_add_request(struct intel_engine_cs *ring, struct drm_file *file, - struct drm_i915_gem_object *batch_obj, - u32 *seqno); -#define i915_add_request(ring, seqno) \ - __i915_add_request(ring, NULL, NULL, seqno) + struct drm_i915_gem_object *batch_obj); +#define i915_add_request(ring) \ + __i915_add_request(ring, NULL, NULL) int __i915_wait_request(struct drm_i915_gem_request *req, unsigned reset_counter, bool interruptible, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 3f56f50900bd95..c403bacee16151 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1164,7 +1164,7 @@ i915_gem_check_olr(struct drm_i915_gem_request *req) ret = 0; if (req == req->ring->outstanding_lazy_request) - ret = i915_add_request(req->ring, NULL); + ret = i915_add_request(req->ring); return ret; } @@ -2412,8 +2412,7 @@ i915_gem_get_seqno(struct drm_device *dev, u32 *seqno) int __i915_add_request(struct intel_engine_cs *ring, struct drm_file *file, - struct drm_i915_gem_object *obj, - u32 *out_seqno) + struct drm_i915_gem_object *obj) { struct drm_i915_private *dev_priv = ring->dev->dev_private; struct drm_i915_gem_request *request; @@ -2512,8 +2511,6 @@ int __i915_add_request(struct intel_engine_cs *ring, round_jiffies_up_relative(HZ)); intel_mark_busy(dev_priv->dev); - if (out_seqno) - *out_seqno = request->seqno; return 0; } diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 7ecfa918e114ee..faada754405083 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -993,7 +993,7 @@ i915_gem_execbuffer_retire_commands(struct drm_device *dev, ring->gpu_caches_dirty = true; /* Add a breadcrumb for the completion of the batch buffer */ - (void)__i915_add_request(ring, file, obj, NULL); + (void)__i915_add_request(ring, file, obj); } static int diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c index 98dcd94acba8f2..521548a0857823 100644 --- a/drivers/gpu/drm/i915/i915_gem_render_state.c +++ b/drivers/gpu/drm/i915/i915_gem_render_state.c @@ -173,7 +173,7 @@ int i915_gem_render_state_init(struct intel_engine_cs *ring) i915_vma_move_to_active(i915_gem_obj_to_ggtt(so.obj), ring); - ret = __i915_add_request(ring, NULL, so.obj, NULL); + ret = __i915_add_request(ring, NULL, so.obj); /* __i915_add_request moves object to inactive if it fails */ out: i915_gem_render_state_fini(&so); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 8d0b8ac2748a49..1ed25a120159c3 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1628,7 +1628,7 @@ int intel_lr_context_render_state_init(struct intel_engine_cs *ring, i915_vma_move_to_active(i915_gem_obj_to_ggtt(so.obj), ring); - ret = __i915_add_request(ring, file, so.obj, NULL); + ret = __i915_add_request(ring, file, so.obj); /* intel_logical_ring_add_request moves object to inactive if it * fails */ out: diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 6c530e298b649b..c1abf49ea5b85e 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -219,7 +219,7 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay, BUG_ON(overlay->last_flip_req); i915_gem_request_assign(&overlay->last_flip_req, ring->outstanding_lazy_request); - ret = i915_add_request(ring, NULL); + ret = i915_add_request(ring); if (ret) return ret; @@ -291,7 +291,7 @@ static int intel_overlay_continue(struct intel_overlay *overlay, WARN_ON(overlay->last_flip_req); i915_gem_request_assign(&overlay->last_flip_req, ring->outstanding_lazy_request); - return i915_add_request(ring, NULL); + return i915_add_request(ring); } static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index b9d0d29f83430a..abdaafd73c77dc 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -2014,7 +2014,7 @@ int intel_ring_idle(struct intel_engine_cs *ring) /* We need to add any requests required to flush the objects and ring */ if (ring->outstanding_lazy_request) { - ret = i915_add_request(ring, NULL); + ret = i915_add_request(ring); if (ret) return ret; } From f06cc1b9401cf0b60f3cd30d8127a8a4f088d4c3 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 24 Nov 2014 18:49:37 +0000 Subject: [PATCH 0062/3023] drm/i915: Convert 'flip_queued_seqno' into 'flip_queued_request' Converted the flip_queued_seqno value to be a request structure as part of the on going seqno to request changes. This includes reference counting the request being saved away to ensure it can not be retired and freed while the flip code is still waiting on it. For: VIZ-4377 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel [danvet: Again get rid of the _irq request unref by simply moving that into the unpin worker. Doesn't matter when we hang onto the request for a bit longer, and in the unpin worker we already grab the dev->struct_mutex anyway.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 4 ++-- drivers/gpu/drm/i915/intel_display.c | 25 +++++++++++++++++-------- drivers/gpu/drm/i915/intel_drv.h | 2 +- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 4619873f96202e..3a25a7bee2e7ae 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -544,11 +544,11 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data) if (work->flip_queued_ring) { seq_printf(m, "Flip queued on %s at seqno %u, next seqno %u [current breadcrumb %u], completed? %d\n", work->flip_queued_ring->name, - work->flip_queued_seqno, + i915_gem_request_get_seqno(work->flip_queued_req), dev_priv->next_seqno, work->flip_queued_ring->get_seqno(work->flip_queued_ring, true), i915_seqno_passed(work->flip_queued_ring->get_seqno(work->flip_queued_ring, true), - work->flip_queued_seqno)); + i915_gem_request_get_seqno(work->flip_queued_req))); } else seq_printf(m, "Flip not associated with any ring\n"); seq_printf(m, "Flip queued on frame %d, (was ready on frame %d), now %d\n", diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0eaa1f48efcfbf..766cea7472d575 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9128,6 +9128,11 @@ static void intel_unpin_work_fn(struct work_struct *__work) drm_gem_object_unreference(&work->old_fb_obj->base); intel_update_fbc(dev); + + if (work->flip_queued_req) + i915_gem_request_unreference(work->flip_queued_req); + work->flip_queued_req = NULL; + work->flip_queued_ring = NULL; mutex_unlock(&dev->struct_mutex); intel_frontbuffer_flip_complete(dev, INTEL_FRONTBUFFER_PRIMARY(pipe)); @@ -9736,10 +9741,14 @@ static bool __intel_pageflip_stall_check(struct drm_device *dev, return false; if (work->flip_ready_vblank == 0) { - if (work->flip_queued_ring && - !i915_seqno_passed(work->flip_queued_ring->get_seqno(work->flip_queued_ring, true), - work->flip_queued_seqno)) - return false; + if (work->flip_queued_ring) { + uint32_t s1 = work->flip_queued_ring->get_seqno( + work->flip_queued_ring, true); + uint32_t s2 = i915_gem_request_get_seqno( + work->flip_queued_req); + if (!i915_seqno_passed(s1, s2)) + return false; + } work->flip_ready_vblank = drm_vblank_count(dev, intel_crtc->pipe); } @@ -9903,8 +9912,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, if (ret) goto cleanup_unpin; - work->flip_queued_seqno = - i915_gem_request_get_seqno(obj->last_write_req); + i915_gem_request_assign(&work->flip_queued_req, + obj->last_write_req); work->flip_queued_ring = obj->ring; } else { ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, ring, @@ -9912,8 +9921,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, if (ret) goto cleanup_unpin; - work->flip_queued_seqno = - i915_gem_request_get_seqno(intel_ring_get_request(ring)); + i915_gem_request_assign(&work->flip_queued_req, + intel_ring_get_request(ring)); work->flip_queued_ring = ring; } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 6f87e3cbd68d45..a3c7e14fb1dd55 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -708,7 +708,7 @@ struct intel_unpin_work { u32 flip_count; u32 gtt_offset; struct intel_engine_cs *flip_queued_ring; - u32 flip_queued_seqno; + struct drm_i915_gem_request *flip_queued_req; int flip_queued_vblank; int flip_ready_vblank; bool enable_stall_check; From 74328ee51051e73e4952876cc9061ff01530267c Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 24 Nov 2014 18:49:38 +0000 Subject: [PATCH 0063/3023] drm/i915: Convert trace functions from seqno to request All the code above is now using requests not seqnos so it is possible to convert the trace functions across. Note that rather than get into problematic reference counting issues, the trace code only saves the seqno and ring values from the request structure not the structure pointer itself. For: VIZ-4377 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 12 +++--- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 4 +- drivers/gpu/drm/i915/i915_trace.h | 47 +++++++++++++--------- 3 files changed, 33 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c403bacee16151..e79815531e1a8e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1241,8 +1241,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req, return -ENODEV; /* Record current time in case interrupted by signal, or wedged */ - trace_i915_gem_request_wait_begin(i915_gem_request_get_ring(req), - i915_gem_request_get_seqno(req)); + trace_i915_gem_request_wait_begin(req); before = ktime_get_raw_ns(); for (;;) { struct timer_list timer; @@ -1294,8 +1293,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req, } } now = ktime_get_raw_ns(); - trace_i915_gem_request_wait_end(i915_gem_request_get_ring(req), - i915_gem_request_get_seqno(req)); + trace_i915_gem_request_wait_end(req); if (!irq_test_in_progress) ring->irq_put(ring); @@ -2500,7 +2498,7 @@ int __i915_add_request(struct intel_engine_cs *ring, spin_unlock(&file_priv->mm.lock); } - trace_i915_gem_request_add(ring, request->seqno); + trace_i915_gem_request_add(request); ring->outstanding_lazy_request = NULL; i915_queue_hangcheck(ring->dev); @@ -2776,7 +2774,7 @@ i915_gem_retire_requests_ring(struct intel_engine_cs *ring) if (!i915_seqno_passed(seqno, request->seqno)) break; - trace_i915_gem_request_retire(ring, request->seqno); + trace_i915_gem_request_retire(request); /* This is one of the few common intersection points * between legacy ringbuffer submission and execlists: @@ -3006,7 +3004,7 @@ i915_gem_object_sync(struct drm_i915_gem_object *obj, if (ret) return ret; - trace_i915_gem_ring_sync_to(from, to, seqno); + trace_i915_gem_ring_sync_to(from, to, obj->last_read_req); ret = to->semaphore.sync_to(to, from, seqno); if (!ret) /* We use last_read_req because sync_to() diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index faada754405083..0c25f6202ca4bb 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1211,9 +1211,7 @@ i915_gem_ringbuffer_submission(struct drm_device *dev, struct drm_file *file, return ret; } - trace_i915_gem_ring_dispatch(ring, - i915_gem_request_get_seqno(intel_ring_get_request(ring)), - flags); + trace_i915_gem_ring_dispatch(intel_ring_get_request(ring), flags); i915_gem_execbuffer_move_to_active(vmas, ring); i915_gem_execbuffer_retire_commands(dev, file, ring, batch_obj); diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index 751d4ad14d6224..2c0327b6661863 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -328,8 +328,8 @@ TRACE_EVENT(i915_gem_evict_vm, TRACE_EVENT(i915_gem_ring_sync_to, TP_PROTO(struct intel_engine_cs *from, struct intel_engine_cs *to, - u32 seqno), - TP_ARGS(from, to, seqno), + struct drm_i915_gem_request *req), + TP_ARGS(from, to, req), TP_STRUCT__entry( __field(u32, dev) @@ -342,7 +342,7 @@ TRACE_EVENT(i915_gem_ring_sync_to, __entry->dev = from->dev->primary->index; __entry->sync_from = from->id; __entry->sync_to = to->id; - __entry->seqno = seqno; + __entry->seqno = i915_gem_request_get_seqno(req); ), TP_printk("dev=%u, sync-from=%u, sync-to=%u, seqno=%u", @@ -352,8 +352,8 @@ TRACE_EVENT(i915_gem_ring_sync_to, ); TRACE_EVENT(i915_gem_ring_dispatch, - TP_PROTO(struct intel_engine_cs *ring, u32 seqno, u32 flags), - TP_ARGS(ring, seqno, flags), + TP_PROTO(struct drm_i915_gem_request *req, u32 flags), + TP_ARGS(req, flags), TP_STRUCT__entry( __field(u32, dev) @@ -363,11 +363,13 @@ TRACE_EVENT(i915_gem_ring_dispatch, ), TP_fast_assign( + struct intel_engine_cs *ring = + i915_gem_request_get_ring(req); __entry->dev = ring->dev->primary->index; __entry->ring = ring->id; - __entry->seqno = seqno; + __entry->seqno = i915_gem_request_get_seqno(req); __entry->flags = flags; - i915_trace_irq_get(ring, seqno); + i915_trace_irq_get(ring, __entry->seqno); ), TP_printk("dev=%u, ring=%u, seqno=%u, flags=%x", @@ -398,8 +400,8 @@ TRACE_EVENT(i915_gem_ring_flush, ); DECLARE_EVENT_CLASS(i915_gem_request, - TP_PROTO(struct intel_engine_cs *ring, u32 seqno), - TP_ARGS(ring, seqno), + TP_PROTO(struct drm_i915_gem_request *req), + TP_ARGS(req), TP_STRUCT__entry( __field(u32, dev) @@ -408,9 +410,11 @@ DECLARE_EVENT_CLASS(i915_gem_request, ), TP_fast_assign( + struct intel_engine_cs *ring = + i915_gem_request_get_ring(req); __entry->dev = ring->dev->primary->index; __entry->ring = ring->id; - __entry->seqno = seqno; + __entry->seqno = i915_gem_request_get_seqno(req); ), TP_printk("dev=%u, ring=%u, seqno=%u", @@ -418,8 +422,8 @@ DECLARE_EVENT_CLASS(i915_gem_request, ); DEFINE_EVENT(i915_gem_request, i915_gem_request_add, - TP_PROTO(struct intel_engine_cs *ring, u32 seqno), - TP_ARGS(ring, seqno) + TP_PROTO(struct drm_i915_gem_request *req), + TP_ARGS(req) ); TRACE_EVENT(i915_gem_request_complete, @@ -443,13 +447,13 @@ TRACE_EVENT(i915_gem_request_complete, ); DEFINE_EVENT(i915_gem_request, i915_gem_request_retire, - TP_PROTO(struct intel_engine_cs *ring, u32 seqno), - TP_ARGS(ring, seqno) + TP_PROTO(struct drm_i915_gem_request *req), + TP_ARGS(req) ); TRACE_EVENT(i915_gem_request_wait_begin, - TP_PROTO(struct intel_engine_cs *ring, u32 seqno), - TP_ARGS(ring, seqno), + TP_PROTO(struct drm_i915_gem_request *req), + TP_ARGS(req), TP_STRUCT__entry( __field(u32, dev) @@ -465,10 +469,13 @@ TRACE_EVENT(i915_gem_request_wait_begin, * less desirable. */ TP_fast_assign( + struct intel_engine_cs *ring = + i915_gem_request_get_ring(req); __entry->dev = ring->dev->primary->index; __entry->ring = ring->id; - __entry->seqno = seqno; - __entry->blocking = mutex_is_locked(&ring->dev->struct_mutex); + __entry->seqno = i915_gem_request_get_seqno(req); + __entry->blocking = + mutex_is_locked(&ring->dev->struct_mutex); ), TP_printk("dev=%u, ring=%u, seqno=%u, blocking=%s", @@ -477,8 +484,8 @@ TRACE_EVENT(i915_gem_request_wait_begin, ); DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_end, - TP_PROTO(struct intel_engine_cs *ring, u32 seqno), - TP_ARGS(ring, seqno) + TP_PROTO(struct drm_i915_gem_request *req), + TP_ARGS(req) ); DECLARE_EVENT_CLASS(i915_ring, From 44cdd6d219bc64f6810b8ed0023a4d4db9e0fe68 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 24 Nov 2014 18:49:40 +0000 Subject: [PATCH 0064/3023] drm/i915: Convert 'ring_idle()' to use requests not seqnos More seqno value to request structure conversions. Note, this change temporarily moves the 'get_seqno()' call inside ring_idle() but this will disappear again in a later patch when i915_seqno_passed() itself is converted. For: VIZ-4377 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 981834b0f9b630..1bb315a6cbb14a 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2749,18 +2749,19 @@ static void gen8_disable_vblank(struct drm_device *dev, int pipe) spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } -static u32 -ring_last_seqno(struct intel_engine_cs *ring) +static struct drm_i915_gem_request * +ring_last_request(struct intel_engine_cs *ring) { return list_entry(ring->request_list.prev, - struct drm_i915_gem_request, list)->seqno; + struct drm_i915_gem_request, list); } static bool -ring_idle(struct intel_engine_cs *ring, u32 seqno) +ring_idle(struct intel_engine_cs *ring) { return (list_empty(&ring->request_list) || - i915_seqno_passed(seqno, ring_last_seqno(ring))); + i915_seqno_passed(ring->get_seqno(ring, false), + i915_gem_request_get_seqno(ring_last_request(ring)))); } static bool @@ -2980,7 +2981,7 @@ static void i915_hangcheck_elapsed(unsigned long data) acthd = intel_ring_get_active_head(ring); if (ring->hangcheck.seqno == seqno) { - if (ring_idle(ring, seqno)) { + if (ring_idle(ring)) { ring->hangcheck.action = HANGCHECK_IDLE; if (waitqueue_active(&ring->irq_queue)) { From ff79e857024143f54aff5257c14595e949f46d8a Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 24 Nov 2014 18:49:41 +0000 Subject: [PATCH 0065/3023] drm/i915: Connect requests to rings at creation not submission It makes a lot more sense (and makes future seqno -> request conversion patches simpler) to fill in the 'ring' field of the request structure at the point of creation rather than submission. Given that the request structure is assigned by ring specific code and thus is locked to a ring from the start, there really is no reason to defer this assignment. For: VIZ-4377 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 1 - drivers/gpu/drm/i915/intel_lrc.c | 1 + drivers/gpu/drm/i915/intel_ringbuffer.c | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index e79815531e1a8e..8285c08d78c1ac 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2463,7 +2463,6 @@ int __i915_add_request(struct intel_engine_cs *ring, return ret; } - request->ring = ring; request->head = request_start; request->tail = request_ring_position; diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 1ed25a120159c3..b13221b86b05bb 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -898,6 +898,7 @@ static int logical_ring_alloc_request(struct intel_engine_cs *ring, } kref_init(&request->ref); + request->ring = ring; ret = i915_gem_get_seqno(ring->dev, &request->seqno); if (ret) { diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index abdaafd73c77dc..788e1b6648ac0d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -2044,6 +2044,7 @@ intel_ring_alloc_request(struct intel_engine_cs *ring) return -ENOMEM; kref_init(&request->ref); + request->ring = ring; ret = i915_gem_get_seqno(ring->dev, &request->seqno); if (ret) { From 1b5a433a4dd967b125131da42b89b5cc0d5b1f57 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 24 Nov 2014 18:49:42 +0000 Subject: [PATCH 0066/3023] drm/i915: Convert 'i915_seqno_passed' calls into 'i915_gem_request_completed' Almost everywhere that caled i915_seqno_passed() was really asking 'has the given seqno popped out of the hardware yet?'. Thus it had to query the current hardware seqno and then do a signed delta comparison (which copes with wrapping around zero but not with seqno values more than 2GB apart, although the latter is unlikely!). Now that the majority of seqno instances have been replaced with request structures, it is possible to convert this test to be request based as well. There is now a 'i915_gem_request_completed()' function which takes a request and returns true or false as appropriate. Note that this currently just wraps up the original _passed() test but a later patch in the series will reduce this to simply returning a cached internal value, i.e.: _completed(req) { return req->completed; }' This checkin converts almost all _seqno_passed() calls. The only one left is in the semaphore code which still requires seqnos not request structures. For: VIZ-4377 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel [danvet: Drop hunk touching the trace_irq code since I've dropped the patch which converts that, and resolve resulting conflict.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 3 +-- drivers/gpu/drm/i915/i915_drv.h | 18 ++++++++++++++++++ drivers/gpu/drm/i915/i915_gem.c | 26 ++++++++------------------ drivers/gpu/drm/i915/i915_irq.c | 3 +-- drivers/gpu/drm/i915/intel_display.c | 6 +----- 5 files changed, 29 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 3a25a7bee2e7ae..a76aa31dd1cf8d 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -547,8 +547,7 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data) i915_gem_request_get_seqno(work->flip_queued_req), dev_priv->next_seqno, work->flip_queued_ring->get_seqno(work->flip_queued_ring, true), - i915_seqno_passed(work->flip_queued_ring->get_seqno(work->flip_queued_ring, true), - i915_gem_request_get_seqno(work->flip_queued_req))); + i915_gem_request_completed(work->flip_queued_req, true)); } else seq_printf(m, "Flip not associated with any ring\n"); seq_printf(m, "Flip queued on frame %d, (was ready on frame %d), now %d\n", diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d4e1fa757a34e4..04fb96e670937c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2062,6 +2062,12 @@ static inline void i915_gem_request_assign(struct drm_i915_gem_request **pdst, *pdst = src; } +/* + * XXX: i915_gem_request_completed should be here but currently needs the + * definition of i915_seqno_passed() which is below. It will be moved in + * a later patch when the call to i915_seqno_passed() is obsoleted... + */ + struct drm_i915_file_private { struct drm_i915_private *dev_priv; struct drm_file *file; @@ -2563,6 +2569,18 @@ i915_seqno_passed(uint32_t seq1, uint32_t seq2) return (int32_t)(seq1 - seq2) >= 0; } +static inline bool i915_gem_request_completed(struct drm_i915_gem_request *req, + bool lazy_coherency) +{ + u32 seqno; + + BUG_ON(req == NULL); + + seqno = req->ring->get_seqno(req->ring, lazy_coherency); + + return i915_seqno_passed(seqno, req->seqno); +} + int __must_check i915_gem_get_seqno(struct drm_device *dev, u32 *seqno); int __must_check i915_gem_set_seqno(struct drm_device *dev, u32 seqno); int __must_check i915_gem_object_get_fence(struct drm_i915_gem_object *obj); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8285c08d78c1ac..16a8445403a71b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1223,8 +1223,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req, WARN(!intel_irqs_enabled(dev_priv), "IRQs disabled"); - if (i915_seqno_passed(ring->get_seqno(ring, true), - i915_gem_request_get_seqno(req))) + if (i915_gem_request_completed(req, true)) return 0; timeout_expire = timeout ? jiffies + nsecs_to_jiffies((u64)*timeout) : 0; @@ -1260,8 +1259,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req, break; } - if (i915_seqno_passed(ring->get_seqno(ring, false), - i915_gem_request_get_seqno(req))) { + if (i915_gem_request_completed(req, false)) { ret = 0; break; } @@ -2333,8 +2331,7 @@ i915_gem_object_retire(struct drm_i915_gem_object *obj) if (ring == NULL) return; - if (i915_seqno_passed(ring->get_seqno(ring, true), - i915_gem_request_get_seqno(obj->last_read_req))) + if (i915_gem_request_completed(obj->last_read_req, true)) i915_gem_object_move_to_inactive(obj); } @@ -2601,12 +2598,9 @@ struct drm_i915_gem_request * i915_gem_find_active_request(struct intel_engine_cs *ring) { struct drm_i915_gem_request *request; - u32 completed_seqno; - - completed_seqno = ring->get_seqno(ring, false); list_for_each_entry(request, &ring->request_list, list) { - if (i915_seqno_passed(completed_seqno, request->seqno)) + if (i915_gem_request_completed(request, false)) continue; return request; @@ -2734,15 +2728,11 @@ void i915_gem_reset(struct drm_device *dev) void i915_gem_retire_requests_ring(struct intel_engine_cs *ring) { - uint32_t seqno; - if (list_empty(&ring->request_list)) return; WARN_ON(i915_verify_lists(ring->dev)); - seqno = ring->get_seqno(ring, true); - /* Move any buffers on the active list that are no longer referenced * by the ringbuffer to the flushing/inactive lists as appropriate, * before we free the context associated with the requests. @@ -2754,8 +2744,7 @@ i915_gem_retire_requests_ring(struct intel_engine_cs *ring) struct drm_i915_gem_object, ring_list); - if (!i915_seqno_passed(seqno, - i915_gem_request_get_seqno(obj->last_read_req))) + if (!i915_gem_request_completed(obj->last_read_req, true)) break; i915_gem_object_move_to_inactive(obj); @@ -2770,7 +2759,7 @@ i915_gem_retire_requests_ring(struct intel_engine_cs *ring) struct drm_i915_gem_request, list); - if (!i915_seqno_passed(seqno, request->seqno)) + if (!i915_gem_request_completed(request, true)) break; trace_i915_gem_request_retire(request); @@ -2797,7 +2786,8 @@ i915_gem_retire_requests_ring(struct intel_engine_cs *ring) } if (unlikely(ring->trace_irq_seqno && - i915_seqno_passed(seqno, ring->trace_irq_seqno))) { + i915_seqno_passed(ring->get_seqno(ring, true), + ring->trace_irq_seqno))) { ring->irq_put(ring); ring->trace_irq_seqno = 0; } diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 1bb315a6cbb14a..7913a72ce30ac0 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2760,8 +2760,7 @@ static bool ring_idle(struct intel_engine_cs *ring) { return (list_empty(&ring->request_list) || - i915_seqno_passed(ring->get_seqno(ring, false), - i915_gem_request_get_seqno(ring_last_request(ring)))); + i915_gem_request_completed(ring_last_request(ring), false)); } static bool diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 766cea7472d575..92a0350c1df971 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9742,11 +9742,7 @@ static bool __intel_pageflip_stall_check(struct drm_device *dev, if (work->flip_ready_vblank == 0) { if (work->flip_queued_ring) { - uint32_t s1 = work->flip_queued_ring->get_seqno( - work->flip_queued_ring, true); - uint32_t s2 = i915_gem_request_get_seqno( - work->flip_queued_req); - if (!i915_seqno_passed(s1, s2)) + if (!i915_gem_request_completed(work->flip_queued_req, true)) return false; } From 41c5241555d762810f975d5d9d70143aa93834cd Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 24 Nov 2014 18:49:43 +0000 Subject: [PATCH 0067/3023] drm/i915: Remove the now redundant 'obj->ring' The ring member of the object structure was always updated with the last_read_seqno member. Thus with the conversion to last_read_req, obj->ring is now a direct copy of obj->last_read_req->ring. This makes it somewhat redundant and potentially misleading (especially as there was no comment to explain its purpose). This checkin removes the redundant field. Many uses were simply testing for non-null to see if the object is active on the GPU. Some of these have been converted to check 'obj->active' instead. Others (where the last_read_req is about to be used anyway) have been changed to check obj->last_read_req. The rest simply pull the ring out from the request structure and proceed as before. For: VIZ-4377 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 9 +++---- drivers/gpu/drm/i915/i915_drv.h | 2 -- drivers/gpu/drm/i915/i915_gem.c | 32 +++++++++++++++---------- drivers/gpu/drm/i915/i915_gem_context.c | 3 ++- drivers/gpu/drm/i915/i915_gpu_error.c | 3 ++- drivers/gpu/drm/i915/intel_display.c | 7 +++--- 6 files changed, 33 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index a76aa31dd1cf8d..b2dca46989e0d9 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -166,8 +166,9 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) *t = '\0'; seq_printf(m, " (%s mappable)", s); } - if (obj->ring != NULL) - seq_printf(m, " (%s)", obj->ring->name); + if (obj->last_read_req != NULL) + seq_printf(m, " (%s)", + i915_gem_request_get_ring(obj->last_read_req)->name); if (obj->frontbuffer_bits) seq_printf(m, " (frontbuffer: 0x%03x)", obj->frontbuffer_bits); } @@ -334,7 +335,7 @@ static int per_file_stats(int id, void *ptr, void *data) if (ppgtt->file_priv != stats->file_priv) continue; - if (obj->ring) /* XXX per-vma statistic */ + if (obj->active) /* XXX per-vma statistic */ stats->active += obj->base.size; else stats->inactive += obj->base.size; @@ -344,7 +345,7 @@ static int per_file_stats(int id, void *ptr, void *data) } else { if (i915_gem_obj_ggtt_bound(obj)) { stats->global += obj->base.size; - if (obj->ring) + if (obj->active) stats->active += obj->base.size; else stats->inactive += obj->base.size; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 04fb96e670937c..97804a3be67c84 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1941,8 +1941,6 @@ struct drm_i915_gem_object { void *dma_buf_vmapping; int vmapping_count; - struct intel_engine_cs *ring; - /** Breadcrumb of last rendering to the buffer. */ struct drm_i915_gem_request *last_read_req; struct drm_i915_gem_request *last_write_req; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 16a8445403a71b..b9222a76e52fc5 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2263,14 +2263,18 @@ static void i915_gem_object_move_to_active(struct drm_i915_gem_object *obj, struct intel_engine_cs *ring) { - struct drm_i915_gem_request *req = intel_ring_get_request(ring); + struct drm_i915_gem_request *req; + struct intel_engine_cs *old_ring; BUG_ON(ring == NULL); - if (obj->ring != ring && obj->last_write_req) { + + req = intel_ring_get_request(ring); + old_ring = i915_gem_request_get_ring(obj->last_read_req); + + if (old_ring != ring && obj->last_write_req) { /* Keep the request relative to the current ring */ i915_gem_request_assign(&obj->last_write_req, req); } - obj->ring = ring; /* Add a reference if we're newly entering the active list. */ if (!obj->active) { @@ -2309,7 +2313,6 @@ i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj) intel_fb_obj_flush(obj, true); list_del_init(&obj->ring_list); - obj->ring = NULL; i915_gem_request_assign(&obj->last_read_req, NULL); i915_gem_request_assign(&obj->last_write_req, NULL); @@ -2326,9 +2329,7 @@ i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj) static void i915_gem_object_retire(struct drm_i915_gem_object *obj) { - struct intel_engine_cs *ring = obj->ring; - - if (ring == NULL) + if (obj->last_read_req == NULL) return; if (i915_gem_request_completed(obj->last_read_req, true)) @@ -2861,14 +2862,17 @@ i915_gem_idle_work_handler(struct work_struct *work) static int i915_gem_object_flush_active(struct drm_i915_gem_object *obj) { + struct intel_engine_cs *ring; int ret; if (obj->active) { + ring = i915_gem_request_get_ring(obj->last_read_req); + ret = i915_gem_check_olr(obj->last_read_req); if (ret) return ret; - i915_gem_retire_requests_ring(obj->ring); + i915_gem_retire_requests_ring(ring); } return 0; @@ -2971,10 +2975,12 @@ int i915_gem_object_sync(struct drm_i915_gem_object *obj, struct intel_engine_cs *to) { - struct intel_engine_cs *from = obj->ring; + struct intel_engine_cs *from; u32 seqno; int ret, idx; + from = i915_gem_request_get_ring(obj->last_read_req); + if (from == NULL || to == from) return 0; @@ -3929,7 +3935,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, bool was_pin_display; int ret; - if (pipelined != obj->ring) { + if (pipelined != i915_gem_request_get_ring(obj->last_read_req)) { ret = i915_gem_object_sync(obj, pipelined); if (ret) return ret; @@ -4284,9 +4290,11 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, ret = i915_gem_object_flush_active(obj); args->busy = obj->active; - if (obj->ring) { + if (obj->last_read_req) { + struct intel_engine_cs *ring; BUILD_BUG_ON(I915_NUM_RINGS > 16); - args->busy |= intel_ring_flag(obj->ring) << 16; + ring = i915_gem_request_get_ring(obj->last_read_req); + args->busy |= intel_ring_flag(ring) << 16; } drm_gem_object_unreference(&obj->base); diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index d17ff435f2767f..3c3a9ff9eb5446 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -619,7 +619,8 @@ static int do_switch(struct intel_engine_cs *ring, * swapped, but there is no way to do that yet. */ from->legacy_hw_ctx.rcs_state->dirty = 1; - BUG_ON(from->legacy_hw_ctx.rcs_state->ring != ring); + BUG_ON(i915_gem_request_get_ring( + from->legacy_hw_ctx.rcs_state->last_read_req) != ring); /* obj is kept alive until the next request by its active ref */ i915_gem_object_ggtt_unpin(from->legacy_hw_ctx.rcs_state); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index af0ceeedda9bda..c4536e185b7506 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -683,7 +683,8 @@ static void capture_bo(struct drm_i915_error_buffer *err, err->dirty = obj->dirty; err->purgeable = obj->madv != I915_MADV_WILLNEED; err->userptr = obj->userptr.mm != NULL; - err->ring = obj->ring ? obj->ring->id : -1; + err->ring = obj->last_read_req ? + i915_gem_request_get_ring(obj->last_read_req)->id : -1; err->cache_level = obj->cache_level; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 92a0350c1df971..e216cb7d87296c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9528,7 +9528,7 @@ static bool use_mmio_flip(struct intel_engine_cs *ring, else if (i915.enable_execlists) return true; else - return ring != obj->ring; + return ring != i915_gem_request_get_ring(obj->last_read_req); } static void skl_do_mmio_flip(struct intel_crtc *intel_crtc) @@ -9888,7 +9888,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, } else if (IS_IVYBRIDGE(dev)) { ring = &dev_priv->ring[BCS]; } else if (INTEL_INFO(dev)->gen >= 7) { - ring = obj->ring; + ring = i915_gem_request_get_ring(obj->last_read_req); if (ring == NULL || ring->id != RCS) ring = &dev_priv->ring[BCS]; } else { @@ -9910,7 +9910,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, i915_gem_request_assign(&work->flip_queued_req, obj->last_write_req); - work->flip_queued_ring = obj->ring; + work->flip_queued_ring = + i915_gem_request_get_ring(obj->last_write_req); } else { ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, ring, page_flip_flags); From 3a8a946efbe0312f7a3d074163499f13d38dfb08 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 26 Nov 2014 14:39:48 +0100 Subject: [PATCH 0068/3023] drm/i915: Remove redundant flip_work->flip_queued_ring Similar to the patch from John which removed obj->ring. Cc: John Harrison Cc: Thomas Daniel Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 9 ++++++--- drivers/gpu/drm/i915/intel_display.c | 11 +++-------- drivers/gpu/drm/i915/intel_drv.h | 1 - 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index b2dca46989e0d9..6c169392f70109 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -542,12 +542,15 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data) seq_printf(m, "Flip pending (waiting for vsync) on pipe %c (plane %c)\n", pipe, plane); } - if (work->flip_queued_ring) { + if (work->flip_queued_req) { + struct intel_engine_cs *ring = + i915_gem_request_get_ring(work->flip_queued_req); + seq_printf(m, "Flip queued on %s at seqno %u, next seqno %u [current breadcrumb %u], completed? %d\n", - work->flip_queued_ring->name, + ring->name, i915_gem_request_get_seqno(work->flip_queued_req), dev_priv->next_seqno, - work->flip_queued_ring->get_seqno(work->flip_queued_ring, true), + ring->get_seqno(ring, true), i915_gem_request_completed(work->flip_queued_req, true)); } else seq_printf(m, "Flip not associated with any ring\n"); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e216cb7d87296c..376ec890c8fac2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9132,7 +9132,6 @@ static void intel_unpin_work_fn(struct work_struct *__work) if (work->flip_queued_req) i915_gem_request_unreference(work->flip_queued_req); work->flip_queued_req = NULL; - work->flip_queued_ring = NULL; mutex_unlock(&dev->struct_mutex); intel_frontbuffer_flip_complete(dev, INTEL_FRONTBUFFER_PRIMARY(pipe)); @@ -9741,10 +9740,9 @@ static bool __intel_pageflip_stall_check(struct drm_device *dev, return false; if (work->flip_ready_vblank == 0) { - if (work->flip_queued_ring) { - if (!i915_gem_request_completed(work->flip_queued_req, true)) - return false; - } + if (work->flip_queued_req && + !i915_gem_request_completed(work->flip_queued_req, true)) + return false; work->flip_ready_vblank = drm_vblank_count(dev, intel_crtc->pipe); } @@ -9910,8 +9908,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, i915_gem_request_assign(&work->flip_queued_req, obj->last_write_req); - work->flip_queued_ring = - i915_gem_request_get_ring(obj->last_write_req); } else { ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, ring, page_flip_flags); @@ -9920,7 +9916,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, i915_gem_request_assign(&work->flip_queued_req, intel_ring_get_request(ring)); - work->flip_queued_ring = ring; } work->flip_queued_vblank = drm_vblank_count(dev, intel_crtc->pipe); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a3c7e14fb1dd55..1a9c70fed91818 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -707,7 +707,6 @@ struct intel_unpin_work { #define INTEL_FLIP_COMPLETE 2 u32 flip_count; u32 gtt_offset; - struct intel_engine_cs *flip_queued_ring; struct drm_i915_gem_request *flip_queued_req; int flip_queued_vblank; int flip_ready_vblank; From 581c26e8a26482eb9d8072a35978034e2dd16b9d Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 24 Nov 2014 18:49:39 +0000 Subject: [PATCH 0069/3023] drm/i915: Convert 'trace_irq' to use requests rather than seqnos Updated the trace_irq code to use requests instead of seqnos. This includes reference counting the request object to ensure it sticks around when required. Note that getting access to the reference counting functions means moving the inline i915_trace_irq_get() function from intel_ringbuffer.h to i915_drv.h. For: VIZ-4377 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel [danvet: Resolve conflict due to shuffled merge order.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 7 +++++++ drivers/gpu/drm/i915/i915_gem.c | 7 +++---- drivers/gpu/drm/i915/i915_trace.h | 2 +- drivers/gpu/drm/i915/intel_ringbuffer.h | 8 +------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 97804a3be67c84..049482f5d9ac14 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3132,4 +3132,11 @@ wait_remaining_ms_from_jiffies(unsigned long timestamp_jiffies, int to_wait_ms) } } +static inline void i915_trace_irq_get(struct intel_engine_cs *ring, + struct drm_i915_gem_request *req) +{ + if (ring->trace_irq_req == NULL && ring->irq_get(ring)) + i915_gem_request_assign(&ring->trace_irq_req, req); +} + #endif diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index b9222a76e52fc5..0751ec9a96f1c4 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2786,11 +2786,10 @@ i915_gem_retire_requests_ring(struct intel_engine_cs *ring) i915_gem_free_request(request); } - if (unlikely(ring->trace_irq_seqno && - i915_seqno_passed(ring->get_seqno(ring, true), - ring->trace_irq_seqno))) { + if (unlikely(ring->trace_irq_req && + i915_gem_request_completed(ring->trace_irq_req, true))) { ring->irq_put(ring); - ring->trace_irq_seqno = 0; + i915_gem_request_assign(&ring->trace_irq_req, NULL); } WARN_ON(i915_verify_lists(ring->dev)); diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index 2c0327b6661863..2ade958f28f835 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -369,7 +369,7 @@ TRACE_EVENT(i915_gem_ring_dispatch, __entry->ring = ring->id; __entry->seqno = i915_gem_request_get_seqno(req); __entry->flags = flags; - i915_trace_irq_get(ring, __entry->seqno); + i915_trace_irq_get(ring, req); ), TP_printk("dev=%u, ring=%u, seqno=%u, flags=%x", diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 2a84bd9688a871..39e303d83e915b 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -142,7 +142,7 @@ struct intel_engine_cs { unsigned irq_refcount; /* protected by dev_priv->irq_lock */ u32 irq_enable_mask; /* bitmask to enable ring interrupt */ - u32 trace_irq_seqno; + struct drm_i915_gem_request *trace_irq_req; bool __must_check (*irq_get)(struct intel_engine_cs *ring); void (*irq_put)(struct intel_engine_cs *ring); @@ -442,10 +442,4 @@ intel_ring_get_request(struct intel_engine_cs *ring) return ring->outstanding_lazy_request; } -static inline void i915_trace_irq_get(struct intel_engine_cs *ring, u32 seqno) -{ - if (ring->trace_irq_seqno == 0 && ring->irq_get(ring)) - ring->trace_irq_seqno = seqno; -} - #endif /* _INTEL_RINGBUFFER_H_ */ From 1362b7764088d49cedf87cd9d0b6ac2f16306dbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 26 Nov 2014 17:07:29 +0200 Subject: [PATCH 0070/3023] drm/i915: Deal with video overlay on GPU reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clear the video overlay state on GPU reset. Any pending overlay request in the ring has been nuked, and the display itself gets reset. So we pretty much lose all state here. Adjust the software state to match so that the next "putimage" will restore things to working order. v2: Ass a locking check into intel_overlay_release_old_vid() (Daniel) Cc: Daniel Vetter Signed-off-by: Ville Syrjälä [danvet: s/0/NULL/ to appease sparse, reported by 0-day tester.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 2 ++ drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_overlay.c | 18 ++++++++++++++++++ 3 files changed, 21 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 1e9c136a874cf1..71be3c930a0ee4 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -838,6 +838,8 @@ int i915_reset(struct drm_device *dev) return ret; } + intel_overlay_reset(dev_priv); + /* Ok, now get things going again... */ /* diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1a9c70fed91818..abb2cf4162b202 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1081,6 +1081,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, struct drm_file *file_priv); int intel_overlay_attrs(struct drm_device *dev, void *data, struct drm_file *file_priv); +void intel_overlay_reset(struct drm_i915_private *dev_priv); /* intel_panel.c */ diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index c1abf49ea5b85e..973c9de3b87da4 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -394,6 +394,8 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay) struct intel_engine_cs *ring = &dev_priv->ring[RCS]; int ret; + WARN_ON(!mutex_is_locked(&dev->struct_mutex)); + /* Only wait if there is actually an old frame to release to * guarantee forward progress. */ @@ -424,6 +426,22 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay) return 0; } +void intel_overlay_reset(struct drm_i915_private *dev_priv) +{ + struct intel_overlay *overlay = dev_priv->overlay; + + if (!overlay) + return; + + intel_overlay_release_old_vid(overlay); + + overlay->last_flip_req = NULL; + overlay->old_xscale = 0; + overlay->old_yscale = 0; + overlay->crtc = NULL; + overlay->active = false; +} + struct put_image_params { int format; short dst_x; From e7d7cad08d35329a5a783a0aa620560223fe0eb8 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 14 Nov 2014 16:54:21 +0200 Subject: [PATCH 0071/3023] drm/i915/dsi: clean up MIPI DSI pipe vs. port usage MIPI DSI works on ports A and C, which map to pipes A and B, respectively. Things are going to get more complicated with the introduction of dual link DSI support, so clean up the register defines and code to match reality. Signed-off-by: Jani Nikula Reviewed-by: Gaurav K Singh Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 303 ++++++++++++++------------- drivers/gpu/drm/i915/intel_dsi.c | 148 ++++++------- drivers/gpu/drm/i915/intel_dsi.h | 16 ++ drivers/gpu/drm/i915/intel_dsi_cmd.c | 64 +++--- 4 files changed, 277 insertions(+), 254 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index a96552251383c6..dc03facd587a6f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -31,6 +31,8 @@ #define _PORT(port, a, b) ((a) + (port)*((b)-(a))) #define _PIPE3(pipe, a, b, c) ((pipe) == PIPE_A ? (a) : \ (pipe) == PIPE_B ? (b) : (c)) +#define _PORT3(port, a, b, c) ((port) == PORT_A ? (a) : \ + (port) == PORT_B ? (b) : (c)) #define _MASKED_BIT_ENABLE(a) (((a) << 16) | (a)) #define _MASKED_BIT_DISABLE(a) ((a) << 16) @@ -1494,7 +1496,7 @@ enum punit_power_well { #define I915_ISP_INTERRUPT (1<<22) #define I915_LPE_PIPE_B_INTERRUPT (1<<21) #define I915_LPE_PIPE_A_INTERRUPT (1<<20) -#define I915_MIPIB_INTERRUPT (1<<19) +#define I915_MIPIC_INTERRUPT (1<<19) #define I915_MIPIA_INTERRUPT (1<<18) #define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18) #define I915_DISPLAY_PORT_INTERRUPT (1<<17) @@ -6652,29 +6654,30 @@ enum punit_power_well { #define PIPE_CSC_POSTOFF_ME(pipe) _PIPE(pipe, _PIPE_A_CSC_POSTOFF_ME, _PIPE_B_CSC_POSTOFF_ME) #define PIPE_CSC_POSTOFF_LO(pipe) _PIPE(pipe, _PIPE_A_CSC_POSTOFF_LO, _PIPE_B_CSC_POSTOFF_LO) -/* VLV MIPI registers */ +/* MIPI DSI registers */ + +#define _MIPI_PORT(port, a, c) _PORT3(port, a, 0, c) /* ports A and C only */ #define _MIPIA_PORT_CTRL (VLV_DISPLAY_BASE + 0x61190) -#define _MIPIB_PORT_CTRL (VLV_DISPLAY_BASE + 0x61700) -#define MIPI_PORT_CTRL(tc) _TRANSCODER(tc, _MIPIA_PORT_CTRL, \ - _MIPIB_PORT_CTRL) -#define DPI_ENABLE (1 << 31) /* A + B */ +#define _MIPIC_PORT_CTRL (VLV_DISPLAY_BASE + 0x61700) +#define MIPI_PORT_CTRL(port) _MIPI_PORT(port, _MIPIA_PORT_CTRL, _MIPIC_PORT_CTRL) +#define DPI_ENABLE (1 << 31) /* A + C */ #define MIPIA_MIPI4DPHY_DELAY_COUNT_SHIFT 27 #define MIPIA_MIPI4DPHY_DELAY_COUNT_MASK (0xf << 27) #define DUAL_LINK_MODE_MASK (1 << 26) #define DUAL_LINK_MODE_FRONT_BACK (0 << 26) #define DUAL_LINK_MODE_PIXEL_ALTERNATIVE (1 << 26) -#define DITHERING_ENABLE (1 << 25) /* A + B */ +#define DITHERING_ENABLE (1 << 25) /* A + C */ #define FLOPPED_HSTX (1 << 23) #define DE_INVERT (1 << 19) /* XXX */ #define MIPIA_FLISDSI_DELAY_COUNT_SHIFT 18 #define MIPIA_FLISDSI_DELAY_COUNT_MASK (0xf << 18) #define AFE_LATCHOUT (1 << 17) #define LP_OUTPUT_HOLD (1 << 16) -#define MIPIB_FLISDSI_DELAY_COUNT_HIGH_SHIFT 15 -#define MIPIB_FLISDSI_DELAY_COUNT_HIGH_MASK (1 << 15) -#define MIPIB_MIPI4DPHY_DELAY_COUNT_SHIFT 11 -#define MIPIB_MIPI4DPHY_DELAY_COUNT_MASK (0xf << 11) +#define MIPIC_FLISDSI_DELAY_COUNT_HIGH_SHIFT 15 +#define MIPIC_FLISDSI_DELAY_COUNT_HIGH_MASK (1 << 15) +#define MIPIC_MIPI4DPHY_DELAY_COUNT_SHIFT 11 +#define MIPIC_MIPI4DPHY_DELAY_COUNT_MASK (0xf << 11) #define CSB_SHIFT 9 #define CSB_MASK (3 << 9) #define CSB_20MHZ (0 << 9) @@ -6683,10 +6686,10 @@ enum punit_power_well { #define BANDGAP_MASK (1 << 8) #define BANDGAP_PNW_CIRCUIT (0 << 8) #define BANDGAP_LNC_CIRCUIT (1 << 8) -#define MIPIB_FLISDSI_DELAY_COUNT_LOW_SHIFT 5 -#define MIPIB_FLISDSI_DELAY_COUNT_LOW_MASK (7 << 5) -#define TEARING_EFFECT_DELAY (1 << 4) /* A + B */ -#define TEARING_EFFECT_SHIFT 2 /* A + B */ +#define MIPIC_FLISDSI_DELAY_COUNT_LOW_SHIFT 5 +#define MIPIC_FLISDSI_DELAY_COUNT_LOW_MASK (7 << 5) +#define TEARING_EFFECT_DELAY (1 << 4) /* A + C */ +#define TEARING_EFFECT_SHIFT 2 /* A + C */ #define TEARING_EFFECT_MASK (3 << 2) #define TEARING_EFFECT_OFF (0 << 2) #define TEARING_EFFECT_DSI (1 << 2) @@ -6698,9 +6701,9 @@ enum punit_power_well { #define LANE_CONFIGURATION_DUAL_LINK_B (2 << 0) #define _MIPIA_TEARING_CTRL (VLV_DISPLAY_BASE + 0x61194) -#define _MIPIB_TEARING_CTRL (VLV_DISPLAY_BASE + 0x61704) -#define MIPI_TEARING_CTRL(tc) _TRANSCODER(tc, \ - _MIPIA_TEARING_CTRL, _MIPIB_TEARING_CTRL) +#define _MIPIC_TEARING_CTRL (VLV_DISPLAY_BASE + 0x61704) +#define MIPI_TEARING_CTRL(port) _MIPI_PORT(port, \ + _MIPIA_TEARING_CTRL, _MIPIC_TEARING_CTRL) #define TEARING_EFFECT_DELAY_SHIFT 0 #define TEARING_EFFECT_DELAY_MASK (0xffff << 0) @@ -6710,9 +6713,9 @@ enum punit_power_well { /* MIPI DSI Controller and D-PHY registers */ #define _MIPIA_DEVICE_READY (dev_priv->mipi_mmio_base + 0xb000) -#define _MIPIB_DEVICE_READY (dev_priv->mipi_mmio_base + 0xb800) -#define MIPI_DEVICE_READY(tc) _TRANSCODER(tc, _MIPIA_DEVICE_READY, \ - _MIPIB_DEVICE_READY) +#define _MIPIC_DEVICE_READY (dev_priv->mipi_mmio_base + 0xb800) +#define MIPI_DEVICE_READY(port) _MIPI_PORT(port, _MIPIA_DEVICE_READY, \ + _MIPIC_DEVICE_READY) #define BUS_POSSESSION (1 << 3) /* set to give bus to receiver */ #define ULPS_STATE_MASK (3 << 1) #define ULPS_STATE_ENTER (2 << 1) @@ -6721,13 +6724,13 @@ enum punit_power_well { #define DEVICE_READY (1 << 0) #define _MIPIA_INTR_STAT (dev_priv->mipi_mmio_base + 0xb004) -#define _MIPIB_INTR_STAT (dev_priv->mipi_mmio_base + 0xb804) -#define MIPI_INTR_STAT(tc) _TRANSCODER(tc, _MIPIA_INTR_STAT, \ - _MIPIB_INTR_STAT) +#define _MIPIC_INTR_STAT (dev_priv->mipi_mmio_base + 0xb804) +#define MIPI_INTR_STAT(port) _MIPI_PORT(port, _MIPIA_INTR_STAT, \ + _MIPIC_INTR_STAT) #define _MIPIA_INTR_EN (dev_priv->mipi_mmio_base + 0xb008) -#define _MIPIB_INTR_EN (dev_priv->mipi_mmio_base + 0xb808) -#define MIPI_INTR_EN(tc) _TRANSCODER(tc, _MIPIA_INTR_EN, \ - _MIPIB_INTR_EN) +#define _MIPIC_INTR_EN (dev_priv->mipi_mmio_base + 0xb808) +#define MIPI_INTR_EN(port) _MIPI_PORT(port, _MIPIA_INTR_EN, \ + _MIPIC_INTR_EN) #define TEARING_EFFECT (1 << 31) #define SPL_PKT_SENT_INTERRUPT (1 << 30) #define GEN_READ_DATA_AVAIL (1 << 29) @@ -6762,9 +6765,9 @@ enum punit_power_well { #define RXSOT_ERROR (1 << 0) #define _MIPIA_DSI_FUNC_PRG (dev_priv->mipi_mmio_base + 0xb00c) -#define _MIPIB_DSI_FUNC_PRG (dev_priv->mipi_mmio_base + 0xb80c) -#define MIPI_DSI_FUNC_PRG(tc) _TRANSCODER(tc, _MIPIA_DSI_FUNC_PRG, \ - _MIPIB_DSI_FUNC_PRG) +#define _MIPIC_DSI_FUNC_PRG (dev_priv->mipi_mmio_base + 0xb80c) +#define MIPI_DSI_FUNC_PRG(port) _MIPI_PORT(port, _MIPIA_DSI_FUNC_PRG, \ + _MIPIC_DSI_FUNC_PRG) #define CMD_MODE_DATA_WIDTH_MASK (7 << 13) #define CMD_MODE_NOT_SUPPORTED (0 << 13) #define CMD_MODE_DATA_WIDTH_16_BIT (1 << 13) @@ -6786,93 +6789,93 @@ enum punit_power_well { #define DATA_LANES_PRG_REG_MASK (7 << 0) #define _MIPIA_HS_TX_TIMEOUT (dev_priv->mipi_mmio_base + 0xb010) -#define _MIPIB_HS_TX_TIMEOUT (dev_priv->mipi_mmio_base + 0xb810) -#define MIPI_HS_TX_TIMEOUT(tc) _TRANSCODER(tc, _MIPIA_HS_TX_TIMEOUT, \ - _MIPIB_HS_TX_TIMEOUT) +#define _MIPIC_HS_TX_TIMEOUT (dev_priv->mipi_mmio_base + 0xb810) +#define MIPI_HS_TX_TIMEOUT(port) _MIPI_PORT(port, _MIPIA_HS_TX_TIMEOUT, \ + _MIPIC_HS_TX_TIMEOUT) #define HIGH_SPEED_TX_TIMEOUT_COUNTER_MASK 0xffffff #define _MIPIA_LP_RX_TIMEOUT (dev_priv->mipi_mmio_base + 0xb014) -#define _MIPIB_LP_RX_TIMEOUT (dev_priv->mipi_mmio_base + 0xb814) -#define MIPI_LP_RX_TIMEOUT(tc) _TRANSCODER(tc, _MIPIA_LP_RX_TIMEOUT, \ - _MIPIB_LP_RX_TIMEOUT) +#define _MIPIC_LP_RX_TIMEOUT (dev_priv->mipi_mmio_base + 0xb814) +#define MIPI_LP_RX_TIMEOUT(port) _MIPI_PORT(port, _MIPIA_LP_RX_TIMEOUT, \ + _MIPIC_LP_RX_TIMEOUT) #define LOW_POWER_RX_TIMEOUT_COUNTER_MASK 0xffffff #define _MIPIA_TURN_AROUND_TIMEOUT (dev_priv->mipi_mmio_base + 0xb018) -#define _MIPIB_TURN_AROUND_TIMEOUT (dev_priv->mipi_mmio_base + 0xb818) -#define MIPI_TURN_AROUND_TIMEOUT(tc) _TRANSCODER(tc, \ - _MIPIA_TURN_AROUND_TIMEOUT, _MIPIB_TURN_AROUND_TIMEOUT) +#define _MIPIC_TURN_AROUND_TIMEOUT (dev_priv->mipi_mmio_base + 0xb818) +#define MIPI_TURN_AROUND_TIMEOUT(port) _MIPI_PORT(port, \ + _MIPIA_TURN_AROUND_TIMEOUT, _MIPIC_TURN_AROUND_TIMEOUT) #define TURN_AROUND_TIMEOUT_MASK 0x3f #define _MIPIA_DEVICE_RESET_TIMER (dev_priv->mipi_mmio_base + 0xb01c) -#define _MIPIB_DEVICE_RESET_TIMER (dev_priv->mipi_mmio_base + 0xb81c) -#define MIPI_DEVICE_RESET_TIMER(tc) _TRANSCODER(tc, \ - _MIPIA_DEVICE_RESET_TIMER, _MIPIB_DEVICE_RESET_TIMER) +#define _MIPIC_DEVICE_RESET_TIMER (dev_priv->mipi_mmio_base + 0xb81c) +#define MIPI_DEVICE_RESET_TIMER(port) _MIPI_PORT(port, \ + _MIPIA_DEVICE_RESET_TIMER, _MIPIC_DEVICE_RESET_TIMER) #define DEVICE_RESET_TIMER_MASK 0xffff #define _MIPIA_DPI_RESOLUTION (dev_priv->mipi_mmio_base + 0xb020) -#define _MIPIB_DPI_RESOLUTION (dev_priv->mipi_mmio_base + 0xb820) -#define MIPI_DPI_RESOLUTION(tc) _TRANSCODER(tc, _MIPIA_DPI_RESOLUTION, \ - _MIPIB_DPI_RESOLUTION) +#define _MIPIC_DPI_RESOLUTION (dev_priv->mipi_mmio_base + 0xb820) +#define MIPI_DPI_RESOLUTION(port) _MIPI_PORT(port, _MIPIA_DPI_RESOLUTION, \ + _MIPIC_DPI_RESOLUTION) #define VERTICAL_ADDRESS_SHIFT 16 #define VERTICAL_ADDRESS_MASK (0xffff << 16) #define HORIZONTAL_ADDRESS_SHIFT 0 #define HORIZONTAL_ADDRESS_MASK 0xffff #define _MIPIA_DBI_FIFO_THROTTLE (dev_priv->mipi_mmio_base + 0xb024) -#define _MIPIB_DBI_FIFO_THROTTLE (dev_priv->mipi_mmio_base + 0xb824) -#define MIPI_DBI_FIFO_THROTTLE(tc) _TRANSCODER(tc, \ - _MIPIA_DBI_FIFO_THROTTLE, _MIPIB_DBI_FIFO_THROTTLE) +#define _MIPIC_DBI_FIFO_THROTTLE (dev_priv->mipi_mmio_base + 0xb824) +#define MIPI_DBI_FIFO_THROTTLE(port) _MIPI_PORT(port, \ + _MIPIA_DBI_FIFO_THROTTLE, _MIPIC_DBI_FIFO_THROTTLE) #define DBI_FIFO_EMPTY_HALF (0 << 0) #define DBI_FIFO_EMPTY_QUARTER (1 << 0) #define DBI_FIFO_EMPTY_7_LOCATIONS (2 << 0) /* regs below are bits 15:0 */ #define _MIPIA_HSYNC_PADDING_COUNT (dev_priv->mipi_mmio_base + 0xb028) -#define _MIPIB_HSYNC_PADDING_COUNT (dev_priv->mipi_mmio_base + 0xb828) -#define MIPI_HSYNC_PADDING_COUNT(tc) _TRANSCODER(tc, \ - _MIPIA_HSYNC_PADDING_COUNT, _MIPIB_HSYNC_PADDING_COUNT) +#define _MIPIC_HSYNC_PADDING_COUNT (dev_priv->mipi_mmio_base + 0xb828) +#define MIPI_HSYNC_PADDING_COUNT(port) _MIPI_PORT(port, \ + _MIPIA_HSYNC_PADDING_COUNT, _MIPIC_HSYNC_PADDING_COUNT) #define _MIPIA_HBP_COUNT (dev_priv->mipi_mmio_base + 0xb02c) -#define _MIPIB_HBP_COUNT (dev_priv->mipi_mmio_base + 0xb82c) -#define MIPI_HBP_COUNT(tc) _TRANSCODER(tc, _MIPIA_HBP_COUNT, \ - _MIPIB_HBP_COUNT) +#define _MIPIC_HBP_COUNT (dev_priv->mipi_mmio_base + 0xb82c) +#define MIPI_HBP_COUNT(port) _MIPI_PORT(port, _MIPIA_HBP_COUNT, \ + _MIPIC_HBP_COUNT) #define _MIPIA_HFP_COUNT (dev_priv->mipi_mmio_base + 0xb030) -#define _MIPIB_HFP_COUNT (dev_priv->mipi_mmio_base + 0xb830) -#define MIPI_HFP_COUNT(tc) _TRANSCODER(tc, _MIPIA_HFP_COUNT, \ - _MIPIB_HFP_COUNT) +#define _MIPIC_HFP_COUNT (dev_priv->mipi_mmio_base + 0xb830) +#define MIPI_HFP_COUNT(port) _MIPI_PORT(port, _MIPIA_HFP_COUNT, \ + _MIPIC_HFP_COUNT) #define _MIPIA_HACTIVE_AREA_COUNT (dev_priv->mipi_mmio_base + 0xb034) -#define _MIPIB_HACTIVE_AREA_COUNT (dev_priv->mipi_mmio_base + 0xb834) -#define MIPI_HACTIVE_AREA_COUNT(tc) _TRANSCODER(tc, \ - _MIPIA_HACTIVE_AREA_COUNT, _MIPIB_HACTIVE_AREA_COUNT) +#define _MIPIC_HACTIVE_AREA_COUNT (dev_priv->mipi_mmio_base + 0xb834) +#define MIPI_HACTIVE_AREA_COUNT(port) _MIPI_PORT(port, \ + _MIPIA_HACTIVE_AREA_COUNT, _MIPIC_HACTIVE_AREA_COUNT) #define _MIPIA_VSYNC_PADDING_COUNT (dev_priv->mipi_mmio_base + 0xb038) -#define _MIPIB_VSYNC_PADDING_COUNT (dev_priv->mipi_mmio_base + 0xb838) -#define MIPI_VSYNC_PADDING_COUNT(tc) _TRANSCODER(tc, \ - _MIPIA_VSYNC_PADDING_COUNT, _MIPIB_VSYNC_PADDING_COUNT) +#define _MIPIC_VSYNC_PADDING_COUNT (dev_priv->mipi_mmio_base + 0xb838) +#define MIPI_VSYNC_PADDING_COUNT(port) _MIPI_PORT(port, \ + _MIPIA_VSYNC_PADDING_COUNT, _MIPIC_VSYNC_PADDING_COUNT) #define _MIPIA_VBP_COUNT (dev_priv->mipi_mmio_base + 0xb03c) -#define _MIPIB_VBP_COUNT (dev_priv->mipi_mmio_base + 0xb83c) -#define MIPI_VBP_COUNT(tc) _TRANSCODER(tc, _MIPIA_VBP_COUNT, \ - _MIPIB_VBP_COUNT) +#define _MIPIC_VBP_COUNT (dev_priv->mipi_mmio_base + 0xb83c) +#define MIPI_VBP_COUNT(port) _MIPI_PORT(port, _MIPIA_VBP_COUNT, \ + _MIPIC_VBP_COUNT) #define _MIPIA_VFP_COUNT (dev_priv->mipi_mmio_base + 0xb040) -#define _MIPIB_VFP_COUNT (dev_priv->mipi_mmio_base + 0xb840) -#define MIPI_VFP_COUNT(tc) _TRANSCODER(tc, _MIPIA_VFP_COUNT, \ - _MIPIB_VFP_COUNT) +#define _MIPIC_VFP_COUNT (dev_priv->mipi_mmio_base + 0xb840) +#define MIPI_VFP_COUNT(port) _MIPI_PORT(port, _MIPIA_VFP_COUNT, \ + _MIPIC_VFP_COUNT) #define _MIPIA_HIGH_LOW_SWITCH_COUNT (dev_priv->mipi_mmio_base + 0xb044) -#define _MIPIB_HIGH_LOW_SWITCH_COUNT (dev_priv->mipi_mmio_base + 0xb844) -#define MIPI_HIGH_LOW_SWITCH_COUNT(tc) _TRANSCODER(tc, \ - _MIPIA_HIGH_LOW_SWITCH_COUNT, _MIPIB_HIGH_LOW_SWITCH_COUNT) +#define _MIPIC_HIGH_LOW_SWITCH_COUNT (dev_priv->mipi_mmio_base + 0xb844) +#define MIPI_HIGH_LOW_SWITCH_COUNT(port) _MIPI_PORT(port, \ + _MIPIA_HIGH_LOW_SWITCH_COUNT, _MIPIC_HIGH_LOW_SWITCH_COUNT) /* regs above are bits 15:0 */ #define _MIPIA_DPI_CONTROL (dev_priv->mipi_mmio_base + 0xb048) -#define _MIPIB_DPI_CONTROL (dev_priv->mipi_mmio_base + 0xb848) -#define MIPI_DPI_CONTROL(tc) _TRANSCODER(tc, _MIPIA_DPI_CONTROL, \ - _MIPIB_DPI_CONTROL) +#define _MIPIC_DPI_CONTROL (dev_priv->mipi_mmio_base + 0xb848) +#define MIPI_DPI_CONTROL(port) _MIPI_PORT(port, _MIPIA_DPI_CONTROL, \ + _MIPIC_DPI_CONTROL) #define DPI_LP_MODE (1 << 6) #define BACKLIGHT_OFF (1 << 5) #define BACKLIGHT_ON (1 << 4) @@ -6882,30 +6885,30 @@ enum punit_power_well { #define SHUTDOWN (1 << 0) #define _MIPIA_DPI_DATA (dev_priv->mipi_mmio_base + 0xb04c) -#define _MIPIB_DPI_DATA (dev_priv->mipi_mmio_base + 0xb84c) -#define MIPI_DPI_DATA(tc) _TRANSCODER(tc, _MIPIA_DPI_DATA, \ - _MIPIB_DPI_DATA) +#define _MIPIC_DPI_DATA (dev_priv->mipi_mmio_base + 0xb84c) +#define MIPI_DPI_DATA(port) _MIPI_PORT(port, _MIPIA_DPI_DATA, \ + _MIPIC_DPI_DATA) #define COMMAND_BYTE_SHIFT 0 #define COMMAND_BYTE_MASK (0x3f << 0) #define _MIPIA_INIT_COUNT (dev_priv->mipi_mmio_base + 0xb050) -#define _MIPIB_INIT_COUNT (dev_priv->mipi_mmio_base + 0xb850) -#define MIPI_INIT_COUNT(tc) _TRANSCODER(tc, _MIPIA_INIT_COUNT, \ - _MIPIB_INIT_COUNT) +#define _MIPIC_INIT_COUNT (dev_priv->mipi_mmio_base + 0xb850) +#define MIPI_INIT_COUNT(port) _MIPI_PORT(port, _MIPIA_INIT_COUNT, \ + _MIPIC_INIT_COUNT) #define MASTER_INIT_TIMER_SHIFT 0 #define MASTER_INIT_TIMER_MASK (0xffff << 0) #define _MIPIA_MAX_RETURN_PKT_SIZE (dev_priv->mipi_mmio_base + 0xb054) -#define _MIPIB_MAX_RETURN_PKT_SIZE (dev_priv->mipi_mmio_base + 0xb854) -#define MIPI_MAX_RETURN_PKT_SIZE(tc) _TRANSCODER(tc, \ - _MIPIA_MAX_RETURN_PKT_SIZE, _MIPIB_MAX_RETURN_PKT_SIZE) +#define _MIPIC_MAX_RETURN_PKT_SIZE (dev_priv->mipi_mmio_base + 0xb854) +#define MIPI_MAX_RETURN_PKT_SIZE(port) _MIPI_PORT(port, \ + _MIPIA_MAX_RETURN_PKT_SIZE, _MIPIC_MAX_RETURN_PKT_SIZE) #define MAX_RETURN_PKT_SIZE_SHIFT 0 #define MAX_RETURN_PKT_SIZE_MASK (0x3ff << 0) #define _MIPIA_VIDEO_MODE_FORMAT (dev_priv->mipi_mmio_base + 0xb058) -#define _MIPIB_VIDEO_MODE_FORMAT (dev_priv->mipi_mmio_base + 0xb858) -#define MIPI_VIDEO_MODE_FORMAT(tc) _TRANSCODER(tc, \ - _MIPIA_VIDEO_MODE_FORMAT, _MIPIB_VIDEO_MODE_FORMAT) +#define _MIPIC_VIDEO_MODE_FORMAT (dev_priv->mipi_mmio_base + 0xb858) +#define MIPI_VIDEO_MODE_FORMAT(port) _MIPI_PORT(port, \ + _MIPIA_VIDEO_MODE_FORMAT, _MIPIC_VIDEO_MODE_FORMAT) #define RANDOM_DPI_DISPLAY_RESOLUTION (1 << 4) #define DISABLE_VIDEO_BTA (1 << 3) #define IP_TG_CONFIG (1 << 2) @@ -6914,9 +6917,9 @@ enum punit_power_well { #define VIDEO_MODE_BURST (3 << 0) #define _MIPIA_EOT_DISABLE (dev_priv->mipi_mmio_base + 0xb05c) -#define _MIPIB_EOT_DISABLE (dev_priv->mipi_mmio_base + 0xb85c) -#define MIPI_EOT_DISABLE(tc) _TRANSCODER(tc, _MIPIA_EOT_DISABLE, \ - _MIPIB_EOT_DISABLE) +#define _MIPIC_EOT_DISABLE (dev_priv->mipi_mmio_base + 0xb85c) +#define MIPI_EOT_DISABLE(port) _MIPI_PORT(port, _MIPIA_EOT_DISABLE, \ + _MIPIC_EOT_DISABLE) #define LP_RX_TIMEOUT_ERROR_RECOVERY_DISABLE (1 << 7) #define HS_RX_TIMEOUT_ERROR_RECOVERY_DISABLE (1 << 6) #define LOW_CONTENTION_RECOVERY_DISABLE (1 << 5) @@ -6927,32 +6930,32 @@ enum punit_power_well { #define EOT_DISABLE (1 << 0) #define _MIPIA_LP_BYTECLK (dev_priv->mipi_mmio_base + 0xb060) -#define _MIPIB_LP_BYTECLK (dev_priv->mipi_mmio_base + 0xb860) -#define MIPI_LP_BYTECLK(tc) _TRANSCODER(tc, _MIPIA_LP_BYTECLK, \ - _MIPIB_LP_BYTECLK) +#define _MIPIC_LP_BYTECLK (dev_priv->mipi_mmio_base + 0xb860) +#define MIPI_LP_BYTECLK(port) _MIPI_PORT(port, _MIPIA_LP_BYTECLK, \ + _MIPIC_LP_BYTECLK) #define LP_BYTECLK_SHIFT 0 #define LP_BYTECLK_MASK (0xffff << 0) /* bits 31:0 */ #define _MIPIA_LP_GEN_DATA (dev_priv->mipi_mmio_base + 0xb064) -#define _MIPIB_LP_GEN_DATA (dev_priv->mipi_mmio_base + 0xb864) -#define MIPI_LP_GEN_DATA(tc) _TRANSCODER(tc, _MIPIA_LP_GEN_DATA, \ - _MIPIB_LP_GEN_DATA) +#define _MIPIC_LP_GEN_DATA (dev_priv->mipi_mmio_base + 0xb864) +#define MIPI_LP_GEN_DATA(port) _MIPI_PORT(port, _MIPIA_LP_GEN_DATA, \ + _MIPIC_LP_GEN_DATA) /* bits 31:0 */ #define _MIPIA_HS_GEN_DATA (dev_priv->mipi_mmio_base + 0xb068) -#define _MIPIB_HS_GEN_DATA (dev_priv->mipi_mmio_base + 0xb868) -#define MIPI_HS_GEN_DATA(tc) _TRANSCODER(tc, _MIPIA_HS_GEN_DATA, \ - _MIPIB_HS_GEN_DATA) +#define _MIPIC_HS_GEN_DATA (dev_priv->mipi_mmio_base + 0xb868) +#define MIPI_HS_GEN_DATA(port) _MIPI_PORT(port, _MIPIA_HS_GEN_DATA, \ + _MIPIC_HS_GEN_DATA) #define _MIPIA_LP_GEN_CTRL (dev_priv->mipi_mmio_base + 0xb06c) -#define _MIPIB_LP_GEN_CTRL (dev_priv->mipi_mmio_base + 0xb86c) -#define MIPI_LP_GEN_CTRL(tc) _TRANSCODER(tc, _MIPIA_LP_GEN_CTRL, \ - _MIPIB_LP_GEN_CTRL) +#define _MIPIC_LP_GEN_CTRL (dev_priv->mipi_mmio_base + 0xb86c) +#define MIPI_LP_GEN_CTRL(port) _MIPI_PORT(port, _MIPIA_LP_GEN_CTRL, \ + _MIPIC_LP_GEN_CTRL) #define _MIPIA_HS_GEN_CTRL (dev_priv->mipi_mmio_base + 0xb070) -#define _MIPIB_HS_GEN_CTRL (dev_priv->mipi_mmio_base + 0xb870) -#define MIPI_HS_GEN_CTRL(tc) _TRANSCODER(tc, _MIPIA_HS_GEN_CTRL, \ - _MIPIB_HS_GEN_CTRL) +#define _MIPIC_HS_GEN_CTRL (dev_priv->mipi_mmio_base + 0xb870) +#define MIPI_HS_GEN_CTRL(port) _MIPI_PORT(port, _MIPIA_HS_GEN_CTRL, \ + _MIPIC_HS_GEN_CTRL) #define LONG_PACKET_WORD_COUNT_SHIFT 8 #define LONG_PACKET_WORD_COUNT_MASK (0xffff << 8) #define SHORT_PACKET_PARAM_SHIFT 8 @@ -6964,9 +6967,9 @@ enum punit_power_well { /* data type values, see include/video/mipi_display.h */ #define _MIPIA_GEN_FIFO_STAT (dev_priv->mipi_mmio_base + 0xb074) -#define _MIPIB_GEN_FIFO_STAT (dev_priv->mipi_mmio_base + 0xb874) -#define MIPI_GEN_FIFO_STAT(tc) _TRANSCODER(tc, _MIPIA_GEN_FIFO_STAT, \ - _MIPIB_GEN_FIFO_STAT) +#define _MIPIC_GEN_FIFO_STAT (dev_priv->mipi_mmio_base + 0xb874) +#define MIPI_GEN_FIFO_STAT(port) _MIPI_PORT(port, _MIPIA_GEN_FIFO_STAT, \ + _MIPIC_GEN_FIFO_STAT) #define DPI_FIFO_EMPTY (1 << 28) #define DBI_FIFO_EMPTY (1 << 27) #define LP_CTRL_FIFO_EMPTY (1 << 26) @@ -6983,17 +6986,17 @@ enum punit_power_well { #define HS_DATA_FIFO_FULL (1 << 0) #define _MIPIA_HS_LS_DBI_ENABLE (dev_priv->mipi_mmio_base + 0xb078) -#define _MIPIB_HS_LS_DBI_ENABLE (dev_priv->mipi_mmio_base + 0xb878) -#define MIPI_HS_LP_DBI_ENABLE(tc) _TRANSCODER(tc, \ - _MIPIA_HS_LS_DBI_ENABLE, _MIPIB_HS_LS_DBI_ENABLE) +#define _MIPIC_HS_LS_DBI_ENABLE (dev_priv->mipi_mmio_base + 0xb878) +#define MIPI_HS_LP_DBI_ENABLE(port) _MIPI_PORT(port, \ + _MIPIA_HS_LS_DBI_ENABLE, _MIPIC_HS_LS_DBI_ENABLE) #define DBI_HS_LP_MODE_MASK (1 << 0) #define DBI_LP_MODE (1 << 0) #define DBI_HS_MODE (0 << 0) #define _MIPIA_DPHY_PARAM (dev_priv->mipi_mmio_base + 0xb080) -#define _MIPIB_DPHY_PARAM (dev_priv->mipi_mmio_base + 0xb880) -#define MIPI_DPHY_PARAM(tc) _TRANSCODER(tc, _MIPIA_DPHY_PARAM, \ - _MIPIB_DPHY_PARAM) +#define _MIPIC_DPHY_PARAM (dev_priv->mipi_mmio_base + 0xb880) +#define MIPI_DPHY_PARAM(port) _MIPI_PORT(port, _MIPIA_DPHY_PARAM, \ + _MIPIC_DPHY_PARAM) #define EXIT_ZERO_COUNT_SHIFT 24 #define EXIT_ZERO_COUNT_MASK (0x3f << 24) #define TRAIL_COUNT_SHIFT 16 @@ -7005,36 +7008,36 @@ enum punit_power_well { /* bits 31:0 */ #define _MIPIA_DBI_BW_CTRL (dev_priv->mipi_mmio_base + 0xb084) -#define _MIPIB_DBI_BW_CTRL (dev_priv->mipi_mmio_base + 0xb884) -#define MIPI_DBI_BW_CTRL(tc) _TRANSCODER(tc, _MIPIA_DBI_BW_CTRL, \ - _MIPIB_DBI_BW_CTRL) +#define _MIPIC_DBI_BW_CTRL (dev_priv->mipi_mmio_base + 0xb884) +#define MIPI_DBI_BW_CTRL(port) _MIPI_PORT(port, _MIPIA_DBI_BW_CTRL, \ + _MIPIC_DBI_BW_CTRL) #define _MIPIA_CLK_LANE_SWITCH_TIME_CNT (dev_priv->mipi_mmio_base \ + 0xb088) -#define _MIPIB_CLK_LANE_SWITCH_TIME_CNT (dev_priv->mipi_mmio_base \ +#define _MIPIC_CLK_LANE_SWITCH_TIME_CNT (dev_priv->mipi_mmio_base \ + 0xb888) -#define MIPI_CLK_LANE_SWITCH_TIME_CNT(tc) _TRANSCODER(tc, \ - _MIPIA_CLK_LANE_SWITCH_TIME_CNT, _MIPIB_CLK_LANE_SWITCH_TIME_CNT) +#define MIPI_CLK_LANE_SWITCH_TIME_CNT(port) _MIPI_PORT(port, \ + _MIPIA_CLK_LANE_SWITCH_TIME_CNT, _MIPIC_CLK_LANE_SWITCH_TIME_CNT) #define LP_HS_SSW_CNT_SHIFT 16 #define LP_HS_SSW_CNT_MASK (0xffff << 16) #define HS_LP_PWR_SW_CNT_SHIFT 0 #define HS_LP_PWR_SW_CNT_MASK (0xffff << 0) #define _MIPIA_STOP_STATE_STALL (dev_priv->mipi_mmio_base + 0xb08c) -#define _MIPIB_STOP_STATE_STALL (dev_priv->mipi_mmio_base + 0xb88c) -#define MIPI_STOP_STATE_STALL(tc) _TRANSCODER(tc, \ - _MIPIA_STOP_STATE_STALL, _MIPIB_STOP_STATE_STALL) +#define _MIPIC_STOP_STATE_STALL (dev_priv->mipi_mmio_base + 0xb88c) +#define MIPI_STOP_STATE_STALL(port) _MIPI_PORT(port, \ + _MIPIA_STOP_STATE_STALL, _MIPIC_STOP_STATE_STALL) #define STOP_STATE_STALL_COUNTER_SHIFT 0 #define STOP_STATE_STALL_COUNTER_MASK (0xff << 0) #define _MIPIA_INTR_STAT_REG_1 (dev_priv->mipi_mmio_base + 0xb090) -#define _MIPIB_INTR_STAT_REG_1 (dev_priv->mipi_mmio_base + 0xb890) -#define MIPI_INTR_STAT_REG_1(tc) _TRANSCODER(tc, \ - _MIPIA_INTR_STAT_REG_1, _MIPIB_INTR_STAT_REG_1) +#define _MIPIC_INTR_STAT_REG_1 (dev_priv->mipi_mmio_base + 0xb890) +#define MIPI_INTR_STAT_REG_1(port) _MIPI_PORT(port, \ + _MIPIA_INTR_STAT_REG_1, _MIPIC_INTR_STAT_REG_1) #define _MIPIA_INTR_EN_REG_1 (dev_priv->mipi_mmio_base + 0xb094) -#define _MIPIB_INTR_EN_REG_1 (dev_priv->mipi_mmio_base + 0xb894) -#define MIPI_INTR_EN_REG_1(tc) _TRANSCODER(tc, _MIPIA_INTR_EN_REG_1, \ - _MIPIB_INTR_EN_REG_1) +#define _MIPIC_INTR_EN_REG_1 (dev_priv->mipi_mmio_base + 0xb894) +#define MIPI_INTR_EN_REG_1(port) _MIPI_PORT(port, _MIPIA_INTR_EN_REG_1, \ + _MIPIC_INTR_EN_REG_1) #define RX_CONTENTION_DETECTED (1 << 0) /* XXX: only pipe A ?!? */ @@ -7053,9 +7056,9 @@ enum punit_power_well { /* MIPI adapter registers */ #define _MIPIA_CTRL (dev_priv->mipi_mmio_base + 0xb104) -#define _MIPIB_CTRL (dev_priv->mipi_mmio_base + 0xb904) -#define MIPI_CTRL(tc) _TRANSCODER(tc, _MIPIA_CTRL, \ - _MIPIB_CTRL) +#define _MIPIC_CTRL (dev_priv->mipi_mmio_base + 0xb904) +#define MIPI_CTRL(port) _MIPI_PORT(port, _MIPIA_CTRL, \ + _MIPIC_CTRL) #define ESCAPE_CLOCK_DIVIDER_SHIFT 5 /* A only */ #define ESCAPE_CLOCK_DIVIDER_MASK (3 << 5) #define ESCAPE_CLOCK_DIVIDER_1 (0 << 5) @@ -7068,24 +7071,24 @@ enum punit_power_well { #define RGB_FLIP_TO_BGR (1 << 2) #define _MIPIA_DATA_ADDRESS (dev_priv->mipi_mmio_base + 0xb108) -#define _MIPIB_DATA_ADDRESS (dev_priv->mipi_mmio_base + 0xb908) -#define MIPI_DATA_ADDRESS(tc) _TRANSCODER(tc, _MIPIA_DATA_ADDRESS, \ - _MIPIB_DATA_ADDRESS) +#define _MIPIC_DATA_ADDRESS (dev_priv->mipi_mmio_base + 0xb908) +#define MIPI_DATA_ADDRESS(port) _MIPI_PORT(port, _MIPIA_DATA_ADDRESS, \ + _MIPIC_DATA_ADDRESS) #define DATA_MEM_ADDRESS_SHIFT 5 #define DATA_MEM_ADDRESS_MASK (0x7ffffff << 5) #define DATA_VALID (1 << 0) #define _MIPIA_DATA_LENGTH (dev_priv->mipi_mmio_base + 0xb10c) -#define _MIPIB_DATA_LENGTH (dev_priv->mipi_mmio_base + 0xb90c) -#define MIPI_DATA_LENGTH(tc) _TRANSCODER(tc, _MIPIA_DATA_LENGTH, \ - _MIPIB_DATA_LENGTH) +#define _MIPIC_DATA_LENGTH (dev_priv->mipi_mmio_base + 0xb90c) +#define MIPI_DATA_LENGTH(port) _MIPI_PORT(port, _MIPIA_DATA_LENGTH, \ + _MIPIC_DATA_LENGTH) #define DATA_LENGTH_SHIFT 0 #define DATA_LENGTH_MASK (0xfffff << 0) #define _MIPIA_COMMAND_ADDRESS (dev_priv->mipi_mmio_base + 0xb110) -#define _MIPIB_COMMAND_ADDRESS (dev_priv->mipi_mmio_base + 0xb910) -#define MIPI_COMMAND_ADDRESS(tc) _TRANSCODER(tc, \ - _MIPIA_COMMAND_ADDRESS, _MIPIB_COMMAND_ADDRESS) +#define _MIPIC_COMMAND_ADDRESS (dev_priv->mipi_mmio_base + 0xb910) +#define MIPI_COMMAND_ADDRESS(port) _MIPI_PORT(port, \ + _MIPIA_COMMAND_ADDRESS, _MIPIC_COMMAND_ADDRESS) #define COMMAND_MEM_ADDRESS_SHIFT 5 #define COMMAND_MEM_ADDRESS_MASK (0x7ffffff << 5) #define AUTO_PWG_ENABLE (1 << 2) @@ -7093,22 +7096,22 @@ enum punit_power_well { #define COMMAND_VALID (1 << 0) #define _MIPIA_COMMAND_LENGTH (dev_priv->mipi_mmio_base + 0xb114) -#define _MIPIB_COMMAND_LENGTH (dev_priv->mipi_mmio_base + 0xb914) -#define MIPI_COMMAND_LENGTH(tc) _TRANSCODER(tc, _MIPIA_COMMAND_LENGTH, \ - _MIPIB_COMMAND_LENGTH) +#define _MIPIC_COMMAND_LENGTH (dev_priv->mipi_mmio_base + 0xb914) +#define MIPI_COMMAND_LENGTH(port) _MIPI_PORT(port, _MIPIA_COMMAND_LENGTH, \ + _MIPIC_COMMAND_LENGTH) #define COMMAND_LENGTH_SHIFT(n) (8 * (n)) /* n: 0...3 */ #define COMMAND_LENGTH_MASK(n) (0xff << (8 * (n))) #define _MIPIA_READ_DATA_RETURN0 (dev_priv->mipi_mmio_base + 0xb118) -#define _MIPIB_READ_DATA_RETURN0 (dev_priv->mipi_mmio_base + 0xb918) -#define MIPI_READ_DATA_RETURN(tc, n) \ - (_TRANSCODER(tc, _MIPIA_READ_DATA_RETURN0, _MIPIB_READ_DATA_RETURN0) \ +#define _MIPIC_READ_DATA_RETURN0 (dev_priv->mipi_mmio_base + 0xb918) +#define MIPI_READ_DATA_RETURN(port, n) \ + (_MIPI_PORT(port, _MIPIA_READ_DATA_RETURN0, _MIPIC_READ_DATA_RETURN0) \ + 4 * (n)) /* n: 0...7 */ #define _MIPIA_READ_DATA_VALID (dev_priv->mipi_mmio_base + 0xb138) -#define _MIPIB_READ_DATA_VALID (dev_priv->mipi_mmio_base + 0xb938) -#define MIPI_READ_DATA_VALID(tc) _TRANSCODER(tc, \ - _MIPIA_READ_DATA_VALID, _MIPIB_READ_DATA_VALID) +#define _MIPIC_READ_DATA_VALID (dev_priv->mipi_mmio_base + 0xb938) +#define MIPI_READ_DATA_VALID(port) _MIPI_PORT(port, \ + _MIPIA_READ_DATA_VALID, _MIPIC_READ_DATA_VALID) #define READ_DATA_VALID(n) (1 << (n)) /* For UMS only (deprecated): */ diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 0b184079de1488..35842a6687d8de 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -106,7 +106,7 @@ static void intel_dsi_device_ready(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - int pipe = intel_crtc->pipe; + enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); u32 val; DRM_DEBUG_KMS("\n"); @@ -120,17 +120,17 @@ static void intel_dsi_device_ready(struct intel_encoder *encoder) /* bandgap reset is needed after everytime we do power gate */ band_gap_reset(dev_priv); - I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER); + I915_WRITE(MIPI_DEVICE_READY(port), ULPS_STATE_ENTER); usleep_range(2500, 3000); - val = I915_READ(MIPI_PORT_CTRL(pipe)); - I915_WRITE(MIPI_PORT_CTRL(pipe), val | LP_OUTPUT_HOLD); + val = I915_READ(MIPI_PORT_CTRL(port)); + I915_WRITE(MIPI_PORT_CTRL(port), val | LP_OUTPUT_HOLD); usleep_range(1000, 1500); - I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_EXIT); + I915_WRITE(MIPI_DEVICE_READY(port), ULPS_STATE_EXIT); usleep_range(2500, 3000); - I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY); + I915_WRITE(MIPI_DEVICE_READY(port), DEVICE_READY); usleep_range(2500, 3000); } @@ -140,13 +140,13 @@ static void intel_dsi_enable(struct intel_encoder *encoder) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); - int pipe = intel_crtc->pipe; + enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); u32 temp; DRM_DEBUG_KMS("\n"); if (is_cmd_mode(intel_dsi)) - I915_WRITE(MIPI_MAX_RETURN_PKT_SIZE(pipe), 8 * 4); + I915_WRITE(MIPI_MAX_RETURN_PKT_SIZE(port), 8 * 4); else { msleep(20); /* XXX */ dpi_send_cmd(intel_dsi, TURN_ON, DPI_LP_MODE_EN); @@ -158,10 +158,10 @@ static void intel_dsi_enable(struct intel_encoder *encoder) wait_for_dsi_fifo_empty(intel_dsi); /* assert ip_tg_enable signal */ - temp = I915_READ(MIPI_PORT_CTRL(pipe)) & ~LANE_CONFIGURATION_MASK; + temp = I915_READ(MIPI_PORT_CTRL(port)) & ~LANE_CONFIGURATION_MASK; temp = temp | intel_dsi->port_bits; - I915_WRITE(MIPI_PORT_CTRL(pipe), temp | DPI_ENABLE); - POSTING_READ(MIPI_PORT_CTRL(pipe)); + I915_WRITE(MIPI_PORT_CTRL(port), temp | DPI_ENABLE); + POSTING_READ(MIPI_PORT_CTRL(port)); } } @@ -237,7 +237,7 @@ static void intel_dsi_disable(struct intel_encoder *encoder) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); - int pipe = intel_crtc->pipe; + enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); u32 temp; DRM_DEBUG_KMS("\n"); @@ -246,29 +246,29 @@ static void intel_dsi_disable(struct intel_encoder *encoder) wait_for_dsi_fifo_empty(intel_dsi); /* de-assert ip_tg_enable signal */ - temp = I915_READ(MIPI_PORT_CTRL(pipe)); - I915_WRITE(MIPI_PORT_CTRL(pipe), temp & ~DPI_ENABLE); - POSTING_READ(MIPI_PORT_CTRL(pipe)); + temp = I915_READ(MIPI_PORT_CTRL(port)); + I915_WRITE(MIPI_PORT_CTRL(port), temp & ~DPI_ENABLE); + POSTING_READ(MIPI_PORT_CTRL(port)); msleep(2); } /* Panel commands can be sent when clock is in LP11 */ - I915_WRITE(MIPI_DEVICE_READY(pipe), 0x0); + I915_WRITE(MIPI_DEVICE_READY(port), 0x0); - temp = I915_READ(MIPI_CTRL(pipe)); + temp = I915_READ(MIPI_CTRL(port)); temp &= ~ESCAPE_CLOCK_DIVIDER_MASK; - I915_WRITE(MIPI_CTRL(pipe), temp | + I915_WRITE(MIPI_CTRL(port), temp | intel_dsi->escape_clk_div << ESCAPE_CLOCK_DIVIDER_SHIFT); - I915_WRITE(MIPI_EOT_DISABLE(pipe), CLOCKSTOP); + I915_WRITE(MIPI_EOT_DISABLE(port), CLOCKSTOP); - temp = I915_READ(MIPI_DSI_FUNC_PRG(pipe)); + temp = I915_READ(MIPI_DSI_FUNC_PRG(port)); temp &= ~VID_MODE_FORMAT_MASK; - I915_WRITE(MIPI_DSI_FUNC_PRG(pipe), temp); + I915_WRITE(MIPI_DSI_FUNC_PRG(port), temp); - I915_WRITE(MIPI_DEVICE_READY(pipe), 0x1); + I915_WRITE(MIPI_DEVICE_READY(port), 0x1); /* if disable packets are sent before sending shutdown packet then in * some next enable sequence send turn on packet error is observed */ @@ -282,29 +282,29 @@ static void intel_dsi_clear_device_ready(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - int pipe = intel_crtc->pipe; + enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); u32 val; DRM_DEBUG_KMS("\n"); - I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY | ULPS_STATE_ENTER); + I915_WRITE(MIPI_DEVICE_READY(port), DEVICE_READY | ULPS_STATE_ENTER); usleep_range(2000, 2500); - I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY | ULPS_STATE_EXIT); + I915_WRITE(MIPI_DEVICE_READY(port), DEVICE_READY | ULPS_STATE_EXIT); usleep_range(2000, 2500); - I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY | ULPS_STATE_ENTER); + I915_WRITE(MIPI_DEVICE_READY(port), DEVICE_READY | ULPS_STATE_ENTER); usleep_range(2000, 2500); - if (wait_for(((I915_READ(MIPI_PORT_CTRL(pipe)) & AFE_LATCHOUT) + if (wait_for(((I915_READ(MIPI_PORT_CTRL(port)) & AFE_LATCHOUT) == 0x00000), 30)) DRM_ERROR("DSI LP not going Low\n"); - val = I915_READ(MIPI_PORT_CTRL(pipe)); - I915_WRITE(MIPI_PORT_CTRL(pipe), val & ~LP_OUTPUT_HOLD); + val = I915_READ(MIPI_PORT_CTRL(port)); + I915_WRITE(MIPI_PORT_CTRL(port), val & ~LP_OUTPUT_HOLD); usleep_range(1000, 1500); - I915_WRITE(MIPI_DEVICE_READY(pipe), 0x00); + I915_WRITE(MIPI_DEVICE_READY(port), 0x00); usleep_range(2000, 2500); vlv_disable_dsi_pll(encoder); @@ -338,8 +338,8 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; enum intel_display_power_domain power_domain; - u32 port, func; - enum pipe p; + u32 port_ctl, func; + enum port port; DRM_DEBUG_KMS("\n"); @@ -348,13 +348,13 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, return false; /* XXX: this only works for one DSI output */ - for (p = PIPE_A; p <= PIPE_B; p++) { - port = I915_READ(MIPI_PORT_CTRL(p)); - func = I915_READ(MIPI_DSI_FUNC_PRG(p)); + for_each_dsi_port(port, (1 << PORT_A) | (1 << PORT_C)) { + port_ctl = I915_READ(MIPI_PORT_CTRL(port)); + func = I915_READ(MIPI_DSI_FUNC_PRG(port)); - if ((port & DPI_ENABLE) || (func & CMD_MODE_DATA_WIDTH_MASK)) { - if (I915_READ(MIPI_DEVICE_READY(p)) & DEVICE_READY) { - *pipe = p; + if ((port_ctl & DPI_ENABLE) || (func & CMD_MODE_DATA_WIDTH_MASK)) { + if (I915_READ(MIPI_DEVICE_READY(port)) & DEVICE_READY) { + *pipe = port == PORT_A ? PIPE_A : PIPE_C; return true; } } @@ -437,7 +437,7 @@ static void set_dsi_timings(struct drm_encoder *encoder, struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); - int pipe = intel_crtc->pipe; + enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); unsigned int bpp = intel_crtc->config.pipe_bpp; unsigned int lane_count = intel_dsi->lane_count; @@ -460,18 +460,18 @@ static void set_dsi_timings(struct drm_encoder *encoder, intel_dsi->burst_mode_ratio); hbp = txbyteclkhs(hbp, bpp, lane_count, intel_dsi->burst_mode_ratio); - I915_WRITE(MIPI_HACTIVE_AREA_COUNT(pipe), hactive); - I915_WRITE(MIPI_HFP_COUNT(pipe), hfp); + I915_WRITE(MIPI_HACTIVE_AREA_COUNT(port), hactive); + I915_WRITE(MIPI_HFP_COUNT(port), hfp); /* meaningful for video mode non-burst sync pulse mode only, can be zero * for non-burst sync events and burst modes */ - I915_WRITE(MIPI_HSYNC_PADDING_COUNT(pipe), hsync); - I915_WRITE(MIPI_HBP_COUNT(pipe), hbp); + I915_WRITE(MIPI_HSYNC_PADDING_COUNT(port), hsync); + I915_WRITE(MIPI_HBP_COUNT(port), hbp); /* vertical values are in terms of lines */ - I915_WRITE(MIPI_VFP_COUNT(pipe), vfp); - I915_WRITE(MIPI_VSYNC_PADDING_COUNT(pipe), vsync); - I915_WRITE(MIPI_VBP_COUNT(pipe), vbp); + I915_WRITE(MIPI_VFP_COUNT(port), vfp); + I915_WRITE(MIPI_VSYNC_PADDING_COUNT(port), vsync); + I915_WRITE(MIPI_VBP_COUNT(port), vbp); } static void intel_dsi_prepare(struct intel_encoder *intel_encoder) @@ -483,30 +483,30 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder) struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); struct drm_display_mode *adjusted_mode = &intel_crtc->config.adjusted_mode; - int pipe = intel_crtc->pipe; + enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); unsigned int bpp = intel_crtc->config.pipe_bpp; u32 val, tmp; - DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe)); + DRM_DEBUG_KMS("pipe %c\n", pipe_name(intel_crtc->pipe)); /* escape clock divider, 20MHz, shared for A and C. device ready must be * off when doing this! txclkesc? */ - tmp = I915_READ(MIPI_CTRL(0)); + tmp = I915_READ(MIPI_CTRL(PORT_A)); tmp &= ~ESCAPE_CLOCK_DIVIDER_MASK; - I915_WRITE(MIPI_CTRL(0), tmp | ESCAPE_CLOCK_DIVIDER_1); + I915_WRITE(MIPI_CTRL(PORT_A), tmp | ESCAPE_CLOCK_DIVIDER_1); /* read request priority is per pipe */ - tmp = I915_READ(MIPI_CTRL(pipe)); + tmp = I915_READ(MIPI_CTRL(port)); tmp &= ~READ_REQUEST_PRIORITY_MASK; - I915_WRITE(MIPI_CTRL(pipe), tmp | READ_REQUEST_PRIORITY_HIGH); + I915_WRITE(MIPI_CTRL(port), tmp | READ_REQUEST_PRIORITY_HIGH); /* XXX: why here, why like this? handling in irq handler?! */ - I915_WRITE(MIPI_INTR_STAT(pipe), 0xffffffff); - I915_WRITE(MIPI_INTR_EN(pipe), 0xffffffff); + I915_WRITE(MIPI_INTR_STAT(port), 0xffffffff); + I915_WRITE(MIPI_INTR_EN(port), 0xffffffff); - I915_WRITE(MIPI_DPHY_PARAM(pipe), intel_dsi->dphy_reg); + I915_WRITE(MIPI_DPHY_PARAM(port), intel_dsi->dphy_reg); - I915_WRITE(MIPI_DPI_RESOLUTION(pipe), + I915_WRITE(MIPI_DPI_RESOLUTION(port), adjusted_mode->vdisplay << VERTICAL_ADDRESS_SHIFT | adjusted_mode->hdisplay << HORIZONTAL_ADDRESS_SHIFT); @@ -522,7 +522,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder) /* XXX: cross-check bpp vs. pixel format? */ val |= intel_dsi->pixel_format; } - I915_WRITE(MIPI_DSI_FUNC_PRG(pipe), val); + I915_WRITE(MIPI_DSI_FUNC_PRG(port), val); /* timeouts for recovery. one frame IIUC. if counter expires, EOT and * stop state. */ @@ -543,25 +543,25 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder) if (is_vid_mode(intel_dsi) && intel_dsi->video_mode_format == VIDEO_MODE_BURST) { - I915_WRITE(MIPI_HS_TX_TIMEOUT(pipe), + I915_WRITE(MIPI_HS_TX_TIMEOUT(port), txbyteclkhs(adjusted_mode->htotal, bpp, intel_dsi->lane_count, intel_dsi->burst_mode_ratio) + 1); } else { - I915_WRITE(MIPI_HS_TX_TIMEOUT(pipe), + I915_WRITE(MIPI_HS_TX_TIMEOUT(port), txbyteclkhs(adjusted_mode->vtotal * adjusted_mode->htotal, bpp, intel_dsi->lane_count, intel_dsi->burst_mode_ratio) + 1); } - I915_WRITE(MIPI_LP_RX_TIMEOUT(pipe), intel_dsi->lp_rx_timeout); - I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(pipe), intel_dsi->turn_arnd_val); - I915_WRITE(MIPI_DEVICE_RESET_TIMER(pipe), intel_dsi->rst_timer_val); + I915_WRITE(MIPI_LP_RX_TIMEOUT(port), intel_dsi->lp_rx_timeout); + I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(port), intel_dsi->turn_arnd_val); + I915_WRITE(MIPI_DEVICE_RESET_TIMER(port), intel_dsi->rst_timer_val); /* dphy stuff */ /* in terms of low power clock */ - I915_WRITE(MIPI_INIT_COUNT(pipe), txclkesc(intel_dsi->escape_clk_div, 100)); + I915_WRITE(MIPI_INIT_COUNT(port), txclkesc(intel_dsi->escape_clk_div, 100)); val = 0; if (intel_dsi->eotp_pkt == 0) @@ -571,17 +571,17 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder) val |= CLOCKSTOP; /* recovery disables */ - I915_WRITE(MIPI_EOT_DISABLE(pipe), val); + I915_WRITE(MIPI_EOT_DISABLE(port), val); /* in terms of low power clock */ - I915_WRITE(MIPI_INIT_COUNT(pipe), intel_dsi->init_count); + I915_WRITE(MIPI_INIT_COUNT(port), intel_dsi->init_count); /* in terms of txbyteclkhs. actual high to low switch + * MIPI_STOP_STATE_STALL * MIPI_LP_BYTECLK. * * XXX: write MIPI_STOP_STATE_STALL? */ - I915_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT(pipe), + I915_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT(port), intel_dsi->hs_to_lp_count); /* XXX: low power clock equivalence in terms of byte clock. the number @@ -589,16 +589,16 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder) * and txclkesc. txclkesc time / txbyteclk time * (105 + * MIPI_STOP_STATE_STALL) / 105.??? */ - I915_WRITE(MIPI_LP_BYTECLK(pipe), intel_dsi->lp_byte_clk); + I915_WRITE(MIPI_LP_BYTECLK(port), intel_dsi->lp_byte_clk); /* the bw essential for transmitting 16 long packets containing 252 * bytes meant for dcs write memory command is programmed in this * register in terms of byte clocks. based on dsi transfer rate and the * number of lanes configured the time taken to transmit 16 long packets * in a dsi stream varies. */ - I915_WRITE(MIPI_DBI_BW_CTRL(pipe), intel_dsi->bw_timer); + I915_WRITE(MIPI_DBI_BW_CTRL(port), intel_dsi->bw_timer); - I915_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT(pipe), + I915_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT(port), intel_dsi->clk_lp_to_hs_count << LP_HS_SSW_CNT_SHIFT | intel_dsi->clk_hs_to_lp_count << HS_LP_PWR_SW_CNT_SHIFT); @@ -606,7 +606,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder) /* Some panels might have resolution which is not a multiple of * 64 like 1366 x 768. Enable RANDOM resolution support for such * panels by default */ - I915_WRITE(MIPI_VIDEO_MODE_FORMAT(pipe), + I915_WRITE(MIPI_VIDEO_MODE_FORMAT(port), intel_dsi->video_frmt_cfg_bits | intel_dsi->video_mode_format | IP_TG_CONFIG | @@ -748,6 +748,12 @@ void intel_dsi_init(struct drm_device *dev) intel_connector->get_hw_state = intel_connector_get_hw_state; intel_connector->unregister = intel_connector_unregister; + /* Pipe A maps to MIPI DSI port A, pipe B maps to MIPI DSI port C */ + if (dev_priv->vbt.dsi.port == DVO_PORT_MIPIA) + intel_encoder->crtc_mask = (1 << PIPE_A); + else if (dev_priv->vbt.dsi.port == DVO_PORT_MIPIC) + intel_encoder->crtc_mask = (1 << PIPE_B); + for (i = 0; i < ARRAY_SIZE(intel_dsi_devices); i++) { dsi = &intel_dsi_devices[i]; intel_dsi->dev = *dsi; @@ -762,8 +768,6 @@ void intel_dsi_init(struct drm_device *dev) } intel_encoder->type = INTEL_OUTPUT_DSI; - intel_encoder->crtc_mask = (1 << 0); /* XXX */ - intel_encoder->cloneable = 0; drm_connector_init(dev, connector, &intel_dsi_connector_funcs, DRM_MODE_CONNECTOR_DSI); diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index 657eb5c1b9d80d..97a6f621774fc9 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -127,6 +127,22 @@ struct intel_dsi { u16 panel_pwr_cycle_delay; }; +/* XXX: Transitional before dual port configuration */ +static inline enum port intel_dsi_pipe_to_port(enum pipe pipe) +{ + if (pipe == PIPE_A) + return PORT_A; + else if (pipe == PIPE_B) + return PORT_C; + + WARN(1, "DSI on pipe %c, assuming port C\n", pipe_name(pipe)); + return PORT_C; +} + +#define for_each_dsi_port(__port, __ports_mask) \ + for ((__port) = PORT_A; (__port) < I915_MAX_PORTS; (__port)++) \ + if ((__ports_mask) & (1 << (__port))) + static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder) { return container_of(encoder, struct intel_dsi, base.base); diff --git a/drivers/gpu/drm/i915/intel_dsi_cmd.c b/drivers/gpu/drm/i915/intel_dsi_cmd.c index f4767fd2ebeb0e..004fa918ca035f 100644 --- a/drivers/gpu/drm/i915/intel_dsi_cmd.c +++ b/drivers/gpu/drm/i915/intel_dsi_cmd.c @@ -54,15 +54,15 @@ static void print_stat(struct intel_dsi *intel_dsi) struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum pipe pipe = intel_crtc->pipe; + enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); u32 val; - val = I915_READ(MIPI_INTR_STAT(pipe)); + val = I915_READ(MIPI_INTR_STAT(port)); #define STAT_BIT(val, bit) (val) & (bit) ? " " #bit : "" - DRM_DEBUG_KMS("MIPI_INTR_STAT(%d) = %08x" + DRM_DEBUG_KMS("MIPI_INTR_STAT(%c) = %08x" "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" - "\n", pipe, val, + "\n", port_name(port), val, STAT_BIT(val, TEARING_EFFECT), STAT_BIT(val, SPL_PKT_SENT_INTERRUPT), STAT_BIT(val, GEN_READ_DATA_AVAIL), @@ -110,16 +110,16 @@ void dsi_hs_mode_enable(struct intel_dsi *intel_dsi, bool enable) struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum pipe pipe = intel_crtc->pipe; + enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); u32 temp; u32 mask = DBI_FIFO_EMPTY; - if (wait_for((I915_READ(MIPI_GEN_FIFO_STAT(pipe)) & mask) == mask, 50)) + if (wait_for((I915_READ(MIPI_GEN_FIFO_STAT(port)) & mask) == mask, 50)) DRM_ERROR("Timeout waiting for DBI FIFO empty\n"); - temp = I915_READ(MIPI_HS_LP_DBI_ENABLE(pipe)); + temp = I915_READ(MIPI_HS_LP_DBI_ENABLE(port)); temp &= DBI_HS_LP_MODE_MASK; - I915_WRITE(MIPI_HS_LP_DBI_ENABLE(pipe), enable ? DBI_HS_MODE : DBI_LP_MODE); + I915_WRITE(MIPI_HS_LP_DBI_ENABLE(port), enable ? DBI_HS_MODE : DBI_LP_MODE); intel_dsi->hs = enable; } @@ -131,7 +131,7 @@ static int dsi_vc_send_short(struct intel_dsi *intel_dsi, int channel, struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum pipe pipe = intel_crtc->pipe; + enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); u32 ctrl_reg; u32 ctrl; u32 mask; @@ -140,14 +140,14 @@ static int dsi_vc_send_short(struct intel_dsi *intel_dsi, int channel, channel, data_type, data); if (intel_dsi->hs) { - ctrl_reg = MIPI_HS_GEN_CTRL(pipe); + ctrl_reg = MIPI_HS_GEN_CTRL(port); mask = HS_CTRL_FIFO_FULL; } else { - ctrl_reg = MIPI_LP_GEN_CTRL(pipe); + ctrl_reg = MIPI_LP_GEN_CTRL(port); mask = LP_CTRL_FIFO_FULL; } - if (wait_for((I915_READ(MIPI_GEN_FIFO_STAT(pipe)) & mask) == 0, 50)) { + if (wait_for((I915_READ(MIPI_GEN_FIFO_STAT(port)) & mask) == 0, 50)) { DRM_ERROR("Timeout waiting for HS/LP CTRL FIFO !full\n"); print_stat(intel_dsi); } @@ -173,7 +173,7 @@ static int dsi_vc_send_long(struct intel_dsi *intel_dsi, int channel, struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum pipe pipe = intel_crtc->pipe; + enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); u32 data_reg; int i, j, n; u32 mask; @@ -182,14 +182,14 @@ static int dsi_vc_send_long(struct intel_dsi *intel_dsi, int channel, channel, data_type, len); if (intel_dsi->hs) { - data_reg = MIPI_HS_GEN_DATA(pipe); + data_reg = MIPI_HS_GEN_DATA(port); mask = HS_DATA_FIFO_FULL; } else { - data_reg = MIPI_LP_GEN_DATA(pipe); + data_reg = MIPI_LP_GEN_DATA(port); mask = LP_DATA_FIFO_FULL; } - if (wait_for((I915_READ(MIPI_GEN_FIFO_STAT(pipe)) & mask) == 0, 50)) + if (wait_for((I915_READ(MIPI_GEN_FIFO_STAT(port)) & mask) == 0, 50)) DRM_ERROR("Timeout waiting for HS/LP DATA FIFO !full\n"); for (i = 0; i < len; i += n) { @@ -292,14 +292,14 @@ static int dsi_read_data_return(struct intel_dsi *intel_dsi, struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum pipe pipe = intel_crtc->pipe; + enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); int i, len = 0; u32 data_reg, val; if (intel_dsi->hs) { - data_reg = MIPI_HS_GEN_DATA(pipe); + data_reg = MIPI_HS_GEN_DATA(port); } else { - data_reg = MIPI_LP_GEN_DATA(pipe); + data_reg = MIPI_LP_GEN_DATA(port); } while (len < buflen) { @@ -318,7 +318,7 @@ int dsi_vc_dcs_read(struct intel_dsi *intel_dsi, int channel, u8 dcs_cmd, struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum pipe pipe = intel_crtc->pipe; + enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); u32 mask; int ret; @@ -327,14 +327,14 @@ int dsi_vc_dcs_read(struct intel_dsi *intel_dsi, int channel, u8 dcs_cmd, * longer than MIPI_MAX_RETURN_PKT_SIZE */ - I915_WRITE(MIPI_INTR_STAT(pipe), GEN_READ_DATA_AVAIL); + I915_WRITE(MIPI_INTR_STAT(port), GEN_READ_DATA_AVAIL); ret = dsi_vc_dcs_send_read_request(intel_dsi, channel, dcs_cmd); if (ret) return ret; mask = GEN_READ_DATA_AVAIL; - if (wait_for((I915_READ(MIPI_INTR_STAT(pipe)) & mask) == mask, 50)) + if (wait_for((I915_READ(MIPI_INTR_STAT(port)) & mask) == mask, 50)) DRM_ERROR("Timeout waiting for read data.\n"); ret = dsi_read_data_return(intel_dsi, buf, buflen); @@ -354,7 +354,7 @@ int dsi_vc_generic_read(struct intel_dsi *intel_dsi, int channel, struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum pipe pipe = intel_crtc->pipe; + enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); u32 mask; int ret; @@ -363,7 +363,7 @@ int dsi_vc_generic_read(struct intel_dsi *intel_dsi, int channel, * longer than MIPI_MAX_RETURN_PKT_SIZE */ - I915_WRITE(MIPI_INTR_STAT(pipe), GEN_READ_DATA_AVAIL); + I915_WRITE(MIPI_INTR_STAT(port), GEN_READ_DATA_AVAIL); ret = dsi_vc_generic_send_read_request(intel_dsi, channel, reqdata, reqlen); @@ -371,7 +371,7 @@ int dsi_vc_generic_read(struct intel_dsi *intel_dsi, int channel, return ret; mask = GEN_READ_DATA_AVAIL; - if (wait_for((I915_READ(MIPI_INTR_STAT(pipe)) & mask) == mask, 50)) + if (wait_for((I915_READ(MIPI_INTR_STAT(port)) & mask) == mask, 50)) DRM_ERROR("Timeout waiting for read data.\n"); ret = dsi_read_data_return(intel_dsi, buf, buflen); @@ -395,7 +395,7 @@ int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd, bool hs) struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum pipe pipe = intel_crtc->pipe; + enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); u32 mask; /* XXX: pipe, hs */ @@ -405,16 +405,16 @@ int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd, bool hs) cmd |= DPI_LP_MODE; /* clear bit */ - I915_WRITE(MIPI_INTR_STAT(pipe), SPL_PKT_SENT_INTERRUPT); + I915_WRITE(MIPI_INTR_STAT(port), SPL_PKT_SENT_INTERRUPT); /* XXX: old code skips write if control unchanged */ - if (cmd == I915_READ(MIPI_DPI_CONTROL(pipe))) + if (cmd == I915_READ(MIPI_DPI_CONTROL(port))) DRM_ERROR("Same special packet %02x twice in a row.\n", cmd); - I915_WRITE(MIPI_DPI_CONTROL(pipe), cmd); + I915_WRITE(MIPI_DPI_CONTROL(port), cmd); mask = SPL_PKT_SENT_INTERRUPT; - if (wait_for((I915_READ(MIPI_INTR_STAT(pipe)) & mask) == mask, 100)) + if (wait_for((I915_READ(MIPI_INTR_STAT(port)) & mask) == mask, 100)) DRM_ERROR("Video mode command 0x%08x send failed.\n", cmd); return 0; @@ -426,12 +426,12 @@ void wait_for_dsi_fifo_empty(struct intel_dsi *intel_dsi) struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum pipe pipe = intel_crtc->pipe; + enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); u32 mask; mask = LP_CTRL_FIFO_EMPTY | HS_CTRL_FIFO_EMPTY | LP_DATA_FIFO_EMPTY | HS_DATA_FIFO_EMPTY; - if (wait_for((I915_READ(MIPI_GEN_FIFO_STAT(pipe)) & mask) == mask, 100)) + if (wait_for((I915_READ(MIPI_GEN_FIFO_STAT(port)) & mask) == mask, 100)) DRM_ERROR("DPI FIFOs are not empty\n"); } From 17af40a835f1805e8d0523dddf1fbabe06abf230 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 14 Nov 2014 16:54:22 +0200 Subject: [PATCH 0072/3023] drm/i915/dsi: add ports to intel_dsi to describe the ports being driven Later on this can include multiple ports (e.g. (1 << PORT_A) | (1 << PORT_C)) to describe dual link DSI. Signed-off-by: Jani Nikula Reviewed-by: Gaurav K Singh Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dsi.c | 7 +++++-- drivers/gpu/drm/i915/intel_dsi.h | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 35842a6687d8de..259cb4ab20676c 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -749,10 +749,13 @@ void intel_dsi_init(struct drm_device *dev) intel_connector->unregister = intel_connector_unregister; /* Pipe A maps to MIPI DSI port A, pipe B maps to MIPI DSI port C */ - if (dev_priv->vbt.dsi.port == DVO_PORT_MIPIA) + if (dev_priv->vbt.dsi.port == DVO_PORT_MIPIA) { intel_encoder->crtc_mask = (1 << PIPE_A); - else if (dev_priv->vbt.dsi.port == DVO_PORT_MIPIC) + intel_dsi->ports = (1 << PORT_A); + } else if (dev_priv->vbt.dsi.port == DVO_PORT_MIPIC) { intel_encoder->crtc_mask = (1 << PIPE_B); + intel_dsi->ports = (1 << PORT_C); + } for (i = 0; i < ARRAY_SIZE(intel_dsi_devices); i++) { dsi = &intel_dsi_devices[i]; diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index 97a6f621774fc9..7f5d0280b9d78a 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -78,6 +78,9 @@ struct intel_dsi { struct intel_connector *attached_connector; + /* bit mask of ports being driven */ + u16 ports; + /* if true, use HS mode, otherwise LP */ bool hs; From 4f54741e07f9c4791f06a3d151b56ece08b27c20 Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Thu, 27 Nov 2014 11:22:48 +0000 Subject: [PATCH 0073/3023] drm/i915: Make ring freespace calculation more robust The used space in a ring is given by the cyclic distance from the consumer (HEAD) to the producer (TAIL), i.e. ((tail-head) MOD size); conversely, the available space in a ring is the cyclic distance from the producer to the consumer, MINUS the amount reserved for a "gap" that is supposed to guarantee that the producer never catches up with or overruns the consumer. Note that some GEN h/w requires that TAIL never approach to within one cacheline of HEAD, so the gap is usually set to twice the cacheline size to ensure this. While the existing code gives the correct answer for correct inputs, if the producer HAS overrun into the reserved space, the result can be a value larger than the maximum valid value (size-reserved). We can improve this by reorganising the calculation, so that in the event of overrun the result will be negative rather than over-large. This means that the commonly-used test (available >= required) will then reject further writes into the ring after an overrun, giving some chance that we can recover from or at least diagnose the original problem; whereas allowing more writes would likely both confuse the h/w and destroy the evidence of what went wrong. Signed-off-by: Dave Gordon Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 788e1b6648ac0d..2ac382ac6bbb6f 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -52,10 +52,10 @@ intel_ring_initialized(struct intel_engine_cs *ring) int __intel_ring_space(int head, int tail, int size) { - int space = head - (tail + I915_RING_FREE_SPACE); - if (space < 0) + int space = head - tail; + if (space <= 0) space += size; - return space; + return space - I915_RING_FREE_SPACE; } int intel_ring_space(struct intel_ringbuffer *ringbuf) From ebd0fd4bef6384dd422d6480b0d5b10b7bfe829a Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Thu, 27 Nov 2014 11:22:49 +0000 Subject: [PATCH 0074/3023] drm/i915: Consolidate ring freespace calculations There are numerous places in the code where the driver's idea of how much space is left in a ring is updated using the driver's latest notions of the positions of 'head' and 'tail' for the ring. Among them are some that update one or both of these values before (re)doing the calculation. In particular, there are four different places in the code where 'last_retired_head' is copied to 'head' and then set to -1; and two of these do not have a guard to check that it has actually been updated since last time it was consumed, leaving the possibility that the dummy -1 can be transferred from 'last_retired_head' to 'head', causing the space calculation to produce 'impossible' results (previously seen on Android/VLV). This code therefore consolidates all the calculation and updating of these values, such that there is only one place where the ring space is updated, and it ALWAYS uses (and consumes) 'last_retired_head' if (and ONLY if) it has been updated since the last call. Signed-off-by: Dave Gordon Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 25 +++++---------- drivers/gpu/drm/i915/intel_ringbuffer.c | 42 +++++++++++++------------ drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + 3 files changed, 30 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index b13221b86b05bb..828cba49cf0106 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -925,14 +925,8 @@ static int logical_ring_wait_request(struct intel_ringbuffer *ringbuf, struct drm_i915_gem_request *request; int ret; - if (ringbuf->last_retired_head != -1) { - ringbuf->head = ringbuf->last_retired_head; - ringbuf->last_retired_head = -1; - - ringbuf->space = intel_ring_space(ringbuf); - if (ringbuf->space >= bytes) - return 0; - } + if (intel_ring_space(ringbuf) >= bytes) + return 0; list_for_each_entry(request, &ring->request_list, list) { /* @@ -959,11 +953,8 @@ static int logical_ring_wait_request(struct intel_ringbuffer *ringbuf, return ret; i915_gem_retire_requests_ring(ring); - ringbuf->head = ringbuf->last_retired_head; - ringbuf->last_retired_head = -1; - ringbuf->space = intel_ring_space(ringbuf); - return 0; + return intel_ring_space(ringbuf) >= bytes ? 0 : -ENOSPC; } static int logical_ring_wait_for_space(struct intel_ringbuffer *ringbuf, @@ -989,12 +980,10 @@ static int logical_ring_wait_for_space(struct intel_ringbuffer *ringbuf, * case by choosing an insanely large timeout. */ end = jiffies + 60 * HZ; + ret = 0; do { - ringbuf->space = intel_ring_space(ringbuf); - if (ringbuf->space >= bytes) { - ret = 0; + if (intel_ring_space(ringbuf) >= bytes) break; - } msleep(1); @@ -1035,7 +1024,7 @@ static int logical_ring_wrap_buffer(struct intel_ringbuffer *ringbuf) iowrite32(MI_NOOP, virt++); ringbuf->tail = 0; - ringbuf->space = intel_ring_space(ringbuf); + intel_ring_update_space(ringbuf); return 0; } @@ -1885,8 +1874,8 @@ int intel_lr_context_deferred_create(struct intel_context *ctx, ringbuf->effective_size = ringbuf->size; ringbuf->head = 0; ringbuf->tail = 0; - ringbuf->space = ringbuf->size; ringbuf->last_retired_head = -1; + intel_ring_update_space(ringbuf); if (ringbuf->obj == NULL) { ret = intel_alloc_ringbuffer_obj(dev, ringbuf); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 2ac382ac6bbb6f..e0b76fff8df2a6 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -58,10 +58,21 @@ int __intel_ring_space(int head, int tail, int size) return space - I915_RING_FREE_SPACE; } +void intel_ring_update_space(struct intel_ringbuffer *ringbuf) +{ + if (ringbuf->last_retired_head != -1) { + ringbuf->head = ringbuf->last_retired_head; + ringbuf->last_retired_head = -1; + } + + ringbuf->space = __intel_ring_space(ringbuf->head & HEAD_ADDR, + ringbuf->tail, ringbuf->size); +} + int intel_ring_space(struct intel_ringbuffer *ringbuf) { - return __intel_ring_space(ringbuf->head & HEAD_ADDR, - ringbuf->tail, ringbuf->size); + intel_ring_update_space(ringbuf); + return ringbuf->space; } bool intel_ring_stopped(struct intel_engine_cs *ring) @@ -589,10 +600,10 @@ static int init_ring_common(struct intel_engine_cs *ring) goto out; } + ringbuf->last_retired_head = -1; ringbuf->head = I915_READ_HEAD(ring); ringbuf->tail = I915_READ_TAIL(ring) & TAIL_ADDR; - ringbuf->space = intel_ring_space(ringbuf); - ringbuf->last_retired_head = -1; + intel_ring_update_space(ringbuf); memset(&ring->hangcheck, 0, sizeof(ring->hangcheck)); @@ -1901,14 +1912,8 @@ static int intel_ring_wait_request(struct intel_engine_cs *ring, int n) struct drm_i915_gem_request *request; int ret; - if (ringbuf->last_retired_head != -1) { - ringbuf->head = ringbuf->last_retired_head; - ringbuf->last_retired_head = -1; - - ringbuf->space = intel_ring_space(ringbuf); - if (ringbuf->space >= n) - return 0; - } + if (intel_ring_space(ringbuf) >= n) + return 0; list_for_each_entry(request, &ring->request_list, list) { if (__intel_ring_space(request->tail, ringbuf->tail, @@ -1925,10 +1930,7 @@ static int intel_ring_wait_request(struct intel_engine_cs *ring, int n) return ret; i915_gem_retire_requests_ring(ring); - ringbuf->head = ringbuf->last_retired_head; - ringbuf->last_retired_head = -1; - ringbuf->space = intel_ring_space(ringbuf); return 0; } @@ -1954,14 +1956,14 @@ static int ring_wait_for_space(struct intel_engine_cs *ring, int n) * case by choosing an insanely large timeout. */ end = jiffies + 60 * HZ; + ret = 0; trace_i915_ring_wait_begin(ring); do { + if (intel_ring_space(ringbuf) >= n) + break; ringbuf->head = I915_READ_HEAD(ring); - ringbuf->space = intel_ring_space(ringbuf); - if (ringbuf->space >= n) { - ret = 0; + if (intel_ring_space(ringbuf) >= n) break; - } msleep(1); @@ -2002,7 +2004,7 @@ static int intel_wrap_ring_buffer(struct intel_engine_cs *ring) iowrite32(MI_NOOP, virt++); ringbuf->tail = 0; - ringbuf->space = intel_ring_space(ringbuf); + intel_ring_update_space(ringbuf); return 0; } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 39e303d83e915b..17e9011dff22b7 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -407,6 +407,7 @@ static inline void intel_ring_advance(struct intel_engine_cs *ring) ringbuf->tail &= ringbuf->size - 1; } int __intel_ring_space(int head, int tail, int size); +void intel_ring_update_space(struct intel_ringbuffer *ringbuf); int intel_ring_space(struct intel_ringbuffer *ringbuf); bool intel_ring_stopped(struct intel_engine_cs *ring); void __intel_ring_advance(struct intel_engine_cs *ring); From ecfe00d802d47af797f09cf8c88ad5ee7aa8d11b Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 20 Nov 2014 00:33:04 +0100 Subject: [PATCH 0075/3023] drm/i915: s/init()/init_hw()/ in intel_engine_cs This is (mostly, some exceptions that need fixing) the hw setup function which starts the ring. And not the function which allocates all the resources. Make this clear by giving it a better name. Signed-off-by: Daniel Vetter Reviewed-by: Dave Gordon Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 14 +++++++------- drivers/gpu/drm/i915/intel_ringbuffer.c | 12 ++++++------ drivers/gpu/drm/i915/intel_ringbuffer.h | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 828cba49cf0106..5e9bb531aeef4e 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1391,8 +1391,8 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rin if (ret) return ret; - if (ring->init) { - ret = ring->init(ring); + if (ring->init_hw) { + ret = ring->init_hw(ring); if (ret) return ret; } @@ -1417,7 +1417,7 @@ static int logical_render_ring_init(struct drm_device *dev) if (HAS_L3_DPF(dev)) ring->irq_keep_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT; - ring->init = gen8_init_render_ring; + ring->init_hw = gen8_init_render_ring; ring->init_context = intel_logical_ring_workarounds_emit; ring->cleanup = intel_fini_pipe_control; ring->get_seqno = gen8_get_seqno; @@ -1444,7 +1444,7 @@ static int logical_bsd_ring_init(struct drm_device *dev) ring->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; - ring->init = gen8_init_common_ring; + ring->init_hw = gen8_init_common_ring; ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; @@ -1469,7 +1469,7 @@ static int logical_bsd2_ring_init(struct drm_device *dev) ring->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS2_IRQ_SHIFT; - ring->init = gen8_init_common_ring; + ring->init_hw = gen8_init_common_ring; ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; @@ -1494,7 +1494,7 @@ static int logical_blt_ring_init(struct drm_device *dev) ring->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT; - ring->init = gen8_init_common_ring; + ring->init_hw = gen8_init_common_ring; ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; @@ -1519,7 +1519,7 @@ static int logical_vebox_ring_init(struct drm_device *dev) ring->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT; - ring->init = gen8_init_common_ring; + ring->init_hw = gen8_init_common_ring; ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index e0b76fff8df2a6..2a87b226135095 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1865,7 +1865,7 @@ static int intel_init_ring_buffer(struct drm_device *dev, if (ret) goto error; - ret = ring->init(ring); + ret = ring->init_hw(ring); if (ret) goto error; @@ -2437,7 +2437,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev) ring->dispatch_execbuffer = i830_dispatch_execbuffer; else ring->dispatch_execbuffer = i915_dispatch_execbuffer; - ring->init = init_render_ring; + ring->init_hw = init_render_ring; ring->cleanup = render_ring_cleanup; /* Workaround batchbuffer to combat CS tlb bug. */ @@ -2530,7 +2530,7 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev) } ring->dispatch_execbuffer = i965_dispatch_execbuffer; } - ring->init = init_ring_common; + ring->init_hw = init_ring_common; return intel_init_ring_buffer(dev, ring); } @@ -2569,7 +2569,7 @@ int intel_init_bsd2_ring_buffer(struct drm_device *dev) ring->semaphore.signal = gen8_xcs_signal; GEN8_RING_SEMAPHORE_INIT; } - ring->init = init_ring_common; + ring->init_hw = init_ring_common; return intel_init_ring_buffer(dev, ring); } @@ -2626,7 +2626,7 @@ int intel_init_blt_ring_buffer(struct drm_device *dev) ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; } } - ring->init = init_ring_common; + ring->init_hw = init_ring_common; return intel_init_ring_buffer(dev, ring); } @@ -2677,7 +2677,7 @@ int intel_init_vebox_ring_buffer(struct drm_device *dev) ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; } } - ring->init = init_ring_common; + ring->init_hw = init_ring_common; return intel_init_ring_buffer(dev, ring); } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 17e9011dff22b7..6dbb6f4620074d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -146,7 +146,7 @@ struct intel_engine_cs { bool __must_check (*irq_get)(struct intel_engine_cs *ring); void (*irq_put)(struct intel_engine_cs *ring); - int (*init)(struct intel_engine_cs *ring); + int (*init_hw)(struct intel_engine_cs *ring); int (*init_context)(struct intel_engine_cs *ring, struct intel_context *ctx); From 99be1dfe06e56b6e32f522979e9cf354dad5dc2e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 20 Nov 2014 00:33:06 +0100 Subject: [PATCH 0076/3023] drm/i915: Move intel_init_pipe_control out of engine->init_hw With this all the ->init_hw hooks really only set up hw state needed to start the ring, all the software state setup and memory/buffer allocations happen beforehand. v2: We need to call intel_init_pipe_control after the ring init since otherwise engine->dev is NULL and it falls over. Currently that's now after the hw ring is enabled but a) we'll be fine as long as no one submits a batch b) this will change soon. Signed-off-by: Daniel Vetter Reviewed-by: Dave Gordon Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 12 +++++++----- drivers/gpu/drm/i915/intel_ringbuffer.c | 18 +++++++++++------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 5e9bb531aeef4e..542382f2b1d5c5 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1161,10 +1161,6 @@ static int gen8_init_render_ring(struct intel_engine_cs *ring) */ I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); - ret = intel_init_pipe_control(ring); - if (ret) - return ret; - I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); return init_workarounds_ring(ring); @@ -1406,6 +1402,7 @@ static int logical_render_ring_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *ring = &dev_priv->ring[RCS]; + int ret; ring->name = "render ring"; ring->id = RCS; @@ -1428,7 +1425,12 @@ static int logical_render_ring_init(struct drm_device *dev) ring->irq_put = gen8_logical_ring_put_irq; ring->emit_bb_start = gen8_emit_bb_start; - return logical_ring_init(dev, ring); + ring->dev = dev; + ret = logical_ring_init(dev, ring); + if (ret) + return ret; + + return intel_init_pipe_control(ring); } static int logical_bsd_ring_init(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 2a87b226135095..f0ffcf7c7eb386 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -865,12 +865,6 @@ static int init_render_ring(struct intel_engine_cs *ring) _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_EXPLICIT) | _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); - if (INTEL_INFO(dev)->gen >= 5) { - ret = intel_init_pipe_control(ring); - if (ret) - return ret; - } - if (IS_GEN6(dev)) { /* From the Sandybridge PRM, volume 1 part 3, page 24: * "If this bit is set, STCunit will have LRA as replacement @@ -2459,7 +2453,17 @@ int intel_init_render_ring_buffer(struct drm_device *dev) ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(obj); } - return intel_init_ring_buffer(dev, ring); + ret = intel_init_ring_buffer(dev, ring); + if (ret) + return ret; + + if (INTEL_INFO(dev)->gen >= 5) { + ret = intel_init_pipe_control(ring); + if (ret) + return ret; + } + + return 0; } int intel_init_bsd_ring_buffer(struct drm_device *dev) From 35a57ffbb10840af219eeaf64718434242bb7c76 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 20 Nov 2014 00:33:07 +0100 Subject: [PATCH 0077/3023] drm/i915: Only init engines once We can do this. And now there's finally the clean split between software setup and hardware setup I kinda wanted since multi-ring support was merged aeons ago. It only took almost 5 years. Signed-off-by: Daniel Vetter Reviewed-by: Dave Gordon Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 13 ++++++++++--- drivers/gpu/drm/i915/intel_lrc.c | 6 ------ drivers/gpu/drm/i915/intel_ringbuffer.c | 4 ---- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 0751ec9a96f1c4..7a83a9fa76b329 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4769,6 +4769,7 @@ int i915_gem_init_hw(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_engine_cs *ring; int ret, i; if (INTEL_INFO(dev)->gen < 6 && !intel_enable_gtt()) @@ -4795,9 +4796,11 @@ i915_gem_init_hw(struct drm_device *dev) i915_gem_init_swizzling(dev); - ret = dev_priv->gt.init_rings(dev); - if (ret) - return ret; + for_each_ring(ring, dev_priv, i) { + ret = ring->init_hw(ring); + if (ret) + return ret; + } for (i = 0; i < NUM_L3_SLICES(dev); i++) i915_gem_l3_remap(&dev_priv->ring[RCS], i); @@ -4870,6 +4873,10 @@ int i915_gem_init(struct drm_device *dev) return ret; } + ret = dev_priv->gt.init_rings(dev); + if (ret) + return ret; + ret = i915_gem_init_hw(dev); if (ret == -EIO) { /* Allow ring initialisation to fail by marking the GPU as diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 542382f2b1d5c5..4ffb08cca98376 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1387,12 +1387,6 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rin if (ret) return ret; - if (ring->init_hw) { - ret = ring->init_hw(ring); - if (ret) - return ret; - } - ret = intel_lr_context_deferred_create(ring->default_context, ring); return ret; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index f0ffcf7c7eb386..590b7c38292f8d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1859,10 +1859,6 @@ static int intel_init_ring_buffer(struct drm_device *dev, if (ret) goto error; - ret = ring->init_hw(ring); - if (ret) - goto error; - return 0; error: From 36d0a82ef4dbe8a586b1ca538cbd37c889829340 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Thu, 27 Nov 2014 15:32:34 +0200 Subject: [PATCH 0078/3023] drm/i915: Remove unnecessary goto in intel_primary_plane_disable() The same logic can be implemented without it, and it even saves a line of code. Signed-off-by: Ander Conselvan de Oliveira Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 376ec890c8fac2..3a088c03d7b9ae 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11850,13 +11850,11 @@ intel_primary_plane_disable(struct drm_plane *plane) * In either case, we need to unpin the FB and let the fb pointer get * updated, but otherwise we don't need to touch the hardware. */ - if (!intel_crtc->primary_enabled) - goto disable_unpin; - - intel_crtc_wait_for_pending_flips(plane->crtc); - intel_disable_primary_hw_plane(plane, plane->crtc); + if (intel_crtc->primary_enabled) { + intel_crtc_wait_for_pending_flips(plane->crtc); + intel_disable_primary_hw_plane(plane, plane->crtc); + } -disable_unpin: mutex_lock(&dev->struct_mutex); i915_gem_track_fb(intel_fb_obj(plane->fb), NULL, INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe)); From bfc882b4e30fbc169ecfe3508378623743806f56 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 20 Nov 2014 00:33:08 +0100 Subject: [PATCH 0079/3023] drm/i915: Flatten engine init control flow Now that sanity prevails and we have the clean split between software init and starting the engines we can drop all the "have we allocate this struct already?" nonsense. Execlist code could benefit quite a bit more still, but that's for another patch. Reviewed-by: Dave Gordon Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_cmd_parser.c | 14 ++++---- drivers/gpu/drm/i915/intel_lrc.c | 3 +- drivers/gpu/drm/i915/intel_ringbuffer.c | 45 ++++++++++++------------- 3 files changed, 30 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 22c992a78ac6a8..6e9eac4b175790 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -716,13 +716,13 @@ int i915_cmd_parser_init_ring(struct intel_engine_cs *ring) BUG_ON(!validate_cmds_sorted(ring, cmd_tables, cmd_table_count)); BUG_ON(!validate_regs_sorted(ring)); - if (hash_empty(ring->cmd_hash)) { - ret = init_hash_table(ring, cmd_tables, cmd_table_count); - if (ret) { - DRM_ERROR("CMD: cmd_parser_init failed!\n"); - fini_hash_table(ring); - return ret; - } + WARN_ON(!hash_empty(ring->cmd_hash)); + + ret = init_hash_table(ring, cmd_tables, cmd_table_count); + if (ret) { + DRM_ERROR("CMD: cmd_parser_init failed!\n"); + fini_hash_table(ring); + return ret; } ring->needs_cmd_parser = true; diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 4ffb08cca98376..d6f82532ac1d62 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1833,8 +1833,7 @@ int intel_lr_context_deferred_create(struct intel_context *ctx, int ret; WARN_ON(ctx->legacy_hw_ctx.rcs_state != NULL); - if (ctx->engine[ring->id].state) - return 0; + WARN_ON(ctx->engine[ring->id].state); context_size = round_up(get_lr_context_size(ring), 4096); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 590b7c38292f8d..79b4ca5dc65f29 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -635,8 +635,7 @@ intel_init_pipe_control(struct intel_engine_cs *ring) { int ret; - if (ring->scratch.obj) - return 0; + WARN_ON(ring->scratch.obj); ring->scratch.obj = i915_gem_alloc_object(ring->dev, 4096); if (ring->scratch.obj == NULL) { @@ -1799,15 +1798,15 @@ int intel_alloc_ringbuffer_obj(struct drm_device *dev, static int intel_init_ring_buffer(struct drm_device *dev, struct intel_engine_cs *ring) { - struct intel_ringbuffer *ringbuf = ring->buffer; + struct intel_ringbuffer *ringbuf; int ret; - if (ringbuf == NULL) { - ringbuf = kzalloc(sizeof(*ringbuf), GFP_KERNEL); - if (!ringbuf) - return -ENOMEM; - ring->buffer = ringbuf; - } + WARN_ON(ring->buffer); + + ringbuf = kzalloc(sizeof(*ringbuf), GFP_KERNEL); + if (!ringbuf) + return -ENOMEM; + ring->buffer = ringbuf; ring->dev = dev; INIT_LIST_HEAD(&ring->active_list); @@ -1830,21 +1829,21 @@ static int intel_init_ring_buffer(struct drm_device *dev, goto error; } - if (ringbuf->obj == NULL) { - ret = intel_alloc_ringbuffer_obj(dev, ringbuf); - if (ret) { - DRM_ERROR("Failed to allocate ringbuffer %s: %d\n", - ring->name, ret); - goto error; - } + WARN_ON(ringbuf->obj); - ret = intel_pin_and_map_ringbuffer_obj(dev, ringbuf); - if (ret) { - DRM_ERROR("Failed to pin and map ringbuffer %s: %d\n", - ring->name, ret); - intel_destroy_ringbuffer_obj(ringbuf); - goto error; - } + ret = intel_alloc_ringbuffer_obj(dev, ringbuf); + if (ret) { + DRM_ERROR("Failed to allocate ringbuffer %s: %d\n", + ring->name, ret); + goto error; + } + + ret = intel_pin_and_map_ringbuffer_obj(dev, ringbuf); + if (ret) { + DRM_ERROR("Failed to pin and map ringbuffer %s: %d\n", + ring->name, ret); + intel_destroy_ringbuffer_obj(ringbuf); + goto error; } /* Workaround an erratum on the i830 which causes a hang if From d972d6ee55102f1acb48c55537fb5989136358b7 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Mon, 1 Dec 2014 18:01:05 +0200 Subject: [PATCH 0080/3023] drm/i915: Convert pxvid to extvid lookup table to a function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The conversion table can be replaced with simple enough function. text data bss dec hex filename 839688 10987 24 850699 cfb0b drivers/gpu/drm/i915/i915.ko 839224 10987 24 850235 cf93b drivers/gpu/drm/i915/i915.ko Result is 494 saved bytes (.05525%). v2: - no run on sentences from subject (Chris, Jani) - be verbose about the savings (Chris, Daniel) Reviewed-by: Ville Syrjälä (v1) Signed-off-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 155 ++++---------------------------- 1 file changed, 18 insertions(+), 137 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 9af0af49382e6b..78911e29439c1c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5681,146 +5681,27 @@ unsigned long i915_mch_val(struct drm_i915_private *dev_priv) return ((m * x) / 127) - b; } -static u16 pvid_to_extvid(struct drm_i915_private *dev_priv, u8 pxvid) +static int _pxvid_to_vd(u8 pxvid) +{ + if (pxvid == 0) + return 0; + + if (pxvid >= 8 && pxvid < 31) + pxvid = 31; + + return (pxvid + 2) * 125; +} + +static u32 pvid_to_extvid(struct drm_i915_private *dev_priv, u8 pxvid) { struct drm_device *dev = dev_priv->dev; - static const struct v_table { - u16 vd; /* in .1 mil */ - u16 vm; /* in .1 mil */ - } v_table[] = { - { 0, 0, }, - { 375, 0, }, - { 500, 0, }, - { 625, 0, }, - { 750, 0, }, - { 875, 0, }, - { 1000, 0, }, - { 1125, 0, }, - { 4125, 3000, }, - { 4125, 3000, }, - { 4125, 3000, }, - { 4125, 3000, }, - { 4125, 3000, }, - { 4125, 3000, }, - { 4125, 3000, }, - { 4125, 3000, }, - { 4125, 3000, }, - { 4125, 3000, }, - { 4125, 3000, }, - { 4125, 3000, }, - { 4125, 3000, }, - { 4125, 3000, }, - { 4125, 3000, }, - { 4125, 3000, }, - { 4125, 3000, }, - { 4125, 3000, }, - { 4125, 3000, }, - { 4125, 3000, }, - { 4125, 3000, }, - { 4125, 3000, }, - { 4125, 3000, }, - { 4125, 3000, }, - { 4250, 3125, }, - { 4375, 3250, }, - { 4500, 3375, }, - { 4625, 3500, }, - { 4750, 3625, }, - { 4875, 3750, }, - { 5000, 3875, }, - { 5125, 4000, }, - { 5250, 4125, }, - { 5375, 4250, }, - { 5500, 4375, }, - { 5625, 4500, }, - { 5750, 4625, }, - { 5875, 4750, }, - { 6000, 4875, }, - { 6125, 5000, }, - { 6250, 5125, }, - { 6375, 5250, }, - { 6500, 5375, }, - { 6625, 5500, }, - { 6750, 5625, }, - { 6875, 5750, }, - { 7000, 5875, }, - { 7125, 6000, }, - { 7250, 6125, }, - { 7375, 6250, }, - { 7500, 6375, }, - { 7625, 6500, }, - { 7750, 6625, }, - { 7875, 6750, }, - { 8000, 6875, }, - { 8125, 7000, }, - { 8250, 7125, }, - { 8375, 7250, }, - { 8500, 7375, }, - { 8625, 7500, }, - { 8750, 7625, }, - { 8875, 7750, }, - { 9000, 7875, }, - { 9125, 8000, }, - { 9250, 8125, }, - { 9375, 8250, }, - { 9500, 8375, }, - { 9625, 8500, }, - { 9750, 8625, }, - { 9875, 8750, }, - { 10000, 8875, }, - { 10125, 9000, }, - { 10250, 9125, }, - { 10375, 9250, }, - { 10500, 9375, }, - { 10625, 9500, }, - { 10750, 9625, }, - { 10875, 9750, }, - { 11000, 9875, }, - { 11125, 10000, }, - { 11250, 10125, }, - { 11375, 10250, }, - { 11500, 10375, }, - { 11625, 10500, }, - { 11750, 10625, }, - { 11875, 10750, }, - { 12000, 10875, }, - { 12125, 11000, }, - { 12250, 11125, }, - { 12375, 11250, }, - { 12500, 11375, }, - { 12625, 11500, }, - { 12750, 11625, }, - { 12875, 11750, }, - { 13000, 11875, }, - { 13125, 12000, }, - { 13250, 12125, }, - { 13375, 12250, }, - { 13500, 12375, }, - { 13625, 12500, }, - { 13750, 12625, }, - { 13875, 12750, }, - { 14000, 12875, }, - { 14125, 13000, }, - { 14250, 13125, }, - { 14375, 13250, }, - { 14500, 13375, }, - { 14625, 13500, }, - { 14750, 13625, }, - { 14875, 13750, }, - { 15000, 13875, }, - { 15125, 14000, }, - { 15250, 14125, }, - { 15375, 14250, }, - { 15500, 14375, }, - { 15625, 14500, }, - { 15750, 14625, }, - { 15875, 14750, }, - { 16000, 14875, }, - { 16125, 15000, }, - }; + const int vd = _pxvid_to_vd(pxvid); + const int vm = vd - 1125; + if (INTEL_INFO(dev)->is_mobile) - return v_table[pxvid].vm; - else - return v_table[pxvid].vd; + return vm > 0 ? vm : 0; + + return vd; } static void __i915_update_gfx_val(struct drm_i915_private *dev_priv) From e7778be1eab918274f79603d7c17b3ec8be77386 Mon Sep 17 00:00:00 2001 From: Thomas Daniel Date: Tue, 2 Dec 2014 12:50:48 +0000 Subject: [PATCH 0081/3023] drm/i915: Fix startup failure in LRC mode after recent init changes A previous commit introduced engine init changes: commit 372ee59699d9 ("drm/i915: Only init engines once") This broke execlists as intel_lr_context_render_state_init was trying to emit commands to the RCS for the default context before the ring->init_hw was called. Made a new gen8_init_rcs_context function and assign in to render ring init_context. Moved call to intel_logical_ring_workarounds_emit into gen8_init_rcs_context to maintain previous functionality. Moved call to render_state_init from lr_context_deferred_create into gen8_init_rcs_context, and modified deferred_create to call ring->init_context for non-default contexts. Modified i915_gem_context_enable to call ring->init_context for the default context. So init_context will now always be called when the hw is ready - in i915_gem_context_enable for the default context and in lr_context_deferred_create for other contexts. Signed-off-by: Thomas Daniel Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_context.c | 25 +++++++++++++++------ drivers/gpu/drm/i915/intel_lrc.c | 30 ++++++++++++++++--------- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 3c3a9ff9eb5446..5cd2b97aa76e53 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -408,14 +408,25 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv) BUG_ON(!dev_priv->ring[RCS].default_context); - if (i915.enable_execlists) - return 0; + if (i915.enable_execlists) { + for_each_ring(ring, dev_priv, i) { + if (ring->init_context) { + ret = ring->init_context(ring, + ring->default_context); + if (ret) { + DRM_ERROR("ring init context: %d\n", + ret); + return ret; + } + } + } - for_each_ring(ring, dev_priv, i) { - ret = i915_switch_context(ring, ring->default_context); - if (ret) - return ret; - } + } else + for_each_ring(ring, dev_priv, i) { + ret = i915_switch_context(ring, ring->default_context); + if (ret) + return ret; + } return 0; } diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index d6f82532ac1d62..52e9952206d9da 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1336,6 +1336,18 @@ static int gen8_emit_request(struct intel_ringbuffer *ringbuf) return 0; } +static int gen8_init_rcs_context(struct intel_engine_cs *ring, + struct intel_context *ctx) +{ + int ret; + + ret = intel_logical_ring_workarounds_emit(ring, ctx); + if (ret) + return ret; + + return intel_lr_context_render_state_init(ring, ctx); +} + /** * intel_logical_ring_cleanup() - deallocate the Engine Command Streamer * @@ -1409,7 +1421,7 @@ static int logical_render_ring_init(struct drm_device *dev) ring->irq_keep_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT; ring->init_hw = gen8_init_render_ring; - ring->init_context = intel_logical_ring_workarounds_emit; + ring->init_context = gen8_init_rcs_context; ring->cleanup = intel_fini_pipe_control; ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; @@ -1904,21 +1916,17 @@ int intel_lr_context_deferred_create(struct intel_context *ctx, if (ctx == ring->default_context) lrc_setup_hardware_status_page(ring, ctx_obj); - - if (ring->id == RCS && !ctx->rcs_initialized) { + else if (ring->id == RCS && !ctx->rcs_initialized) { if (ring->init_context) { ret = ring->init_context(ring, ctx); - if (ret) + if (ret) { DRM_ERROR("ring init context: %d\n", ret); + ctx->engine[ring->id].ringbuf = NULL; + ctx->engine[ring->id].state = NULL; + goto error; + } } - ret = intel_lr_context_render_state_init(ring, ctx); - if (ret) { - DRM_ERROR("Init render state failed: %d\n", ret); - ctx->engine[ring->id].ringbuf = NULL; - ctx->engine[ring->id].state = NULL; - goto error; - } ctx->rcs_initialized = true; } From d5abdfda91228349e7410e7a98f67fe044bfea7c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 20 Nov 2014 09:45:19 +0100 Subject: [PATCH 0082/3023] drm/i915: Move init_unused_rings to gem_init_hw We need to do that every time we resume the rings, not just at load. I've overlooked this in my untangling of the ring init code. Signed-off-by: Daniel Vetter Reviewed-by: Dave Gordon Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 7a83a9fa76b329..9d362d320d824c 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4709,14 +4709,6 @@ int i915_gem_init_rings(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; int ret; - /* - * At least 830 can leave some of the unused rings - * "active" (ie. head != tail) after resume which - * will prevent c3 entry. Makes sure all unused rings - * are totally idle. - */ - init_unused_rings(dev); - ret = intel_init_render_ring_buffer(dev); if (ret) return ret; @@ -4796,6 +4788,14 @@ i915_gem_init_hw(struct drm_device *dev) i915_gem_init_swizzling(dev); + /* + * At least 830 can leave some of the unused rings + * "active" (ie. head != tail) after resume which + * will prevent c3 entry. Makes sure all unused rings + * are totally idle. + */ + init_unused_rings(dev); + for_each_ring(ring, dev_priv, i) { ret = ring->init_hw(ring); if (ret) From 6c930688cb04e81ca71092baf585f7ea1c670368 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Wed, 26 Nov 2014 13:37:26 +0000 Subject: [PATCH 0083/3023] drm/i915/skl: Update the DDI translation values for DP/eDP 1.3 Hardware team updated the recommended translation values for DP/eDP 1.3. This should help with some stability and HBR2 issues. Signed-off-by: Damien Lespiau Reviewed-by: Satheeshakrishna M Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index e6b45cd150d387..4e2e8608b46bb6 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -128,15 +128,15 @@ static const struct ddi_buf_trans bdw_ddi_translations_hdmi[] = { }; static const struct ddi_buf_trans skl_ddi_translations_dp[] = { - { 0x00000018, 0x000000a0 }, - { 0x00004014, 0x00000098 }, + { 0x00000018, 0x000000a2 }, + { 0x00004014, 0x0000009B }, { 0x00006012, 0x00000088 }, - { 0x00008010, 0x00000080 }, - { 0x00000018, 0x00000098 }, + { 0x00008010, 0x00000087 }, + { 0x00000018, 0x0000009B }, { 0x00004014, 0x00000088 }, - { 0x00006012, 0x00000080 }, + { 0x00006012, 0x00000087 }, { 0x00000018, 0x00000088 }, - { 0x00004014, 0x00000080 }, + { 0x00004014, 0x00000087 }, }; static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = { From f763566992bb004a27d620c9ad90ec9a4dff34c3 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Wed, 3 Dec 2014 14:59:24 +0000 Subject: [PATCH 0084/3023] drm/i915: Stop putting GGTT VMA at the head of the list Multiple GGTT VMAs per object will be introduced in the near future which will make it impossible to guarantee normal GGTT view is at the head of the list. Purpose of this patch is to break this assumption straight away so any potential hidden assumptions in the code base can be bisected to this simple patch. For: VIZ-4544 Signed-off-by: Tvrtko Ursulin Suggested-by: Daniel Vetter Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 10 ++++++---- drivers/gpu/drm/i915/i915_gem_gtt.c | 8 ++------ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 9d362d320d824c..c1c11418231bd0 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -5303,11 +5303,13 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr) struct i915_vma *i915_gem_obj_to_ggtt(struct drm_i915_gem_object *obj) { + struct i915_address_space *ggtt = i915_obj_to_ggtt(obj); struct i915_vma *vma; - vma = list_first_entry(&obj->vma_list, typeof(*vma), vma_link); - if (vma->vm != i915_obj_to_ggtt(obj)) - return NULL; + list_for_each_entry(vma, &obj->vma_list, vma_link) { + if (vma->vm == ggtt) + return vma; + } - return vma; + return NULL; } diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 171f6eafdeee30..ac03a382000b62 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2202,13 +2202,9 @@ static struct i915_vma *__i915_gem_vma_create(struct drm_i915_gem_object *obj, BUG(); } - /* Keep GGTT vmas first to make debug easier */ - if (i915_is_ggtt(vm)) - list_add(&vma->vma_link, &obj->vma_list); - else { - list_add_tail(&vma->vma_link, &obj->vma_list); + list_add_tail(&vma->vma_link, &obj->vma_list); + if (!i915_is_ggtt(vm)) i915_ppgtt_get(i915_vm_to_ppgtt(vm)); - } return vma; } From 2fcffe195ed3329082ce22f2118543871bfbbcf0 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Wed, 3 Dec 2014 17:33:24 +0000 Subject: [PATCH 0085/3023] drm/i915: Don't display nonsensical values in i915_ddb_info on gen < 9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When playing around with debugfs and a HSW machine I noticed that we were displaying some garbled value in i915_ddb_info. This debugfs file is only meaningful for gen9+, so don't display anything on earlier platforms. Signed-off-by: Damien Lespiau Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 6c169392f70109..d0e445eca9ce5f 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2743,6 +2743,9 @@ static int i915_ddb_info(struct seq_file *m, void *unused) enum pipe pipe; int plane; + if (INTEL_INFO(dev)->gen < 9) + return 0; + drm_modeset_lock_all(dev); ddb = &dev_priv->wm.skl_hw.ddb; From 5505a244901f28e21d7267246511a1ca2ce79bcc Mon Sep 17 00:00:00 2001 From: Gaurav K Singh Date: Thu, 4 Dec 2014 10:58:47 +0530 Subject: [PATCH 0086/3023] drm/i915: New functions added for enabling & disabling MIPI Port Ctrl reg This patch is in preparation for the DSI dual link port enable and disable related changes. Signed-off-by: Gaurav K Singh Signed-off-by: Shobhit Kumar Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dsi.c | 43 ++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 259cb4ab20676c..693736b8808032 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -102,6 +102,36 @@ static bool intel_dsi_compute_config(struct intel_encoder *encoder, return true; } +static void intel_dsi_port_enable(struct intel_encoder *encoder) +{ + struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); + struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); + enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); + u32 temp; + + /* assert ip_tg_enable signal */ + temp = I915_READ(MIPI_PORT_CTRL(port)) & ~LANE_CONFIGURATION_MASK; + temp = temp | intel_dsi->port_bits; + I915_WRITE(MIPI_PORT_CTRL(port), temp | DPI_ENABLE); + POSTING_READ(MIPI_PORT_CTRL(port)); +} + +static void intel_dsi_port_disable(struct intel_encoder *encoder) +{ + struct drm_device *dev = encoder->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); + enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); + u32 temp; + + /* de-assert ip_tg_enable signal */ + temp = I915_READ(MIPI_PORT_CTRL(port)); + I915_WRITE(MIPI_PORT_CTRL(port), temp & ~DPI_ENABLE); + POSTING_READ(MIPI_PORT_CTRL(port)); +} + static void intel_dsi_device_ready(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; @@ -141,7 +171,6 @@ static void intel_dsi_enable(struct intel_encoder *encoder) struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); - u32 temp; DRM_DEBUG_KMS("\n"); @@ -157,11 +186,7 @@ static void intel_dsi_enable(struct intel_encoder *encoder) wait_for_dsi_fifo_empty(intel_dsi); - /* assert ip_tg_enable signal */ - temp = I915_READ(MIPI_PORT_CTRL(port)) & ~LANE_CONFIGURATION_MASK; - temp = temp | intel_dsi->port_bits; - I915_WRITE(MIPI_PORT_CTRL(port), temp | DPI_ENABLE); - POSTING_READ(MIPI_PORT_CTRL(port)); + intel_dsi_port_enable(encoder); } } @@ -245,11 +270,7 @@ static void intel_dsi_disable(struct intel_encoder *encoder) if (is_vid_mode(intel_dsi)) { wait_for_dsi_fifo_empty(intel_dsi); - /* de-assert ip_tg_enable signal */ - temp = I915_READ(MIPI_PORT_CTRL(port)); - I915_WRITE(MIPI_PORT_CTRL(port), temp & ~DPI_ENABLE); - POSTING_READ(MIPI_PORT_CTRL(port)); - + intel_dsi_port_disable(encoder); msleep(2); } From 8f4d2683b02ad8059bf1861acef64c022b9d5ce6 Mon Sep 17 00:00:00 2001 From: Gaurav K Singh Date: Thu, 4 Dec 2014 10:58:48 +0530 Subject: [PATCH 0087/3023] drm/i915: Added port as parameter to the functions which does read/write of DSI Controller This patch is in preparation of DSI dual link panels. For dual link panels, few packets needs to be sent to Port A or Port C or both. Based on the portno from MIPI Sequence Block#53, these sequences needs to be sent accordingly. v2: Addressed review comments by Jani - port variables named properly Signed-off-by: Gaurav K Singh Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dsi_cmd.c | 75 ++++++++++------------ drivers/gpu/drm/i915/intel_dsi_cmd.h | 46 +++++++------ drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 25 +++++--- 3 files changed, 74 insertions(+), 72 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dsi_cmd.c b/drivers/gpu/drm/i915/intel_dsi_cmd.c index 004fa918ca035f..8e3068451568fb 100644 --- a/drivers/gpu/drm/i915/intel_dsi_cmd.c +++ b/drivers/gpu/drm/i915/intel_dsi_cmd.c @@ -48,13 +48,11 @@ * For memory writes, these should probably be used for performance. */ -static void print_stat(struct intel_dsi *intel_dsi) +static void print_stat(struct intel_dsi *intel_dsi, enum port port) { struct drm_encoder *encoder = &intel_dsi->base.base; struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); u32 val; val = I915_READ(MIPI_INTR_STAT(port)); @@ -104,13 +102,12 @@ enum dsi_type { }; /* enable or disable command mode hs transmissions */ -void dsi_hs_mode_enable(struct intel_dsi *intel_dsi, bool enable) +void dsi_hs_mode_enable(struct intel_dsi *intel_dsi, bool enable, + enum port port) { struct drm_encoder *encoder = &intel_dsi->base.base; struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); u32 temp; u32 mask = DBI_FIFO_EMPTY; @@ -125,13 +122,11 @@ void dsi_hs_mode_enable(struct intel_dsi *intel_dsi, bool enable) } static int dsi_vc_send_short(struct intel_dsi *intel_dsi, int channel, - u8 data_type, u16 data) + u8 data_type, u16 data, enum port port) { struct drm_encoder *encoder = &intel_dsi->base.base; struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); u32 ctrl_reg; u32 ctrl; u32 mask; @@ -149,7 +144,7 @@ static int dsi_vc_send_short(struct intel_dsi *intel_dsi, int channel, if (wait_for((I915_READ(MIPI_GEN_FIFO_STAT(port)) & mask) == 0, 50)) { DRM_ERROR("Timeout waiting for HS/LP CTRL FIFO !full\n"); - print_stat(intel_dsi); + print_stat(intel_dsi, port); } /* @@ -167,13 +162,11 @@ static int dsi_vc_send_short(struct intel_dsi *intel_dsi, int channel, } static int dsi_vc_send_long(struct intel_dsi *intel_dsi, int channel, - u8 data_type, const u8 *data, int len) + u8 data_type, const u8 *data, int len, enum port port) { struct drm_encoder *encoder = &intel_dsi->base.base; struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); u32 data_reg; int i, j, n; u32 mask; @@ -204,12 +197,12 @@ static int dsi_vc_send_long(struct intel_dsi *intel_dsi, int channel, * dwords, then wait for not set, then continue. */ } - return dsi_vc_send_short(intel_dsi, channel, data_type, len); + return dsi_vc_send_short(intel_dsi, channel, data_type, len, port); } static int dsi_vc_write_common(struct intel_dsi *intel_dsi, int channel, const u8 *data, int len, - enum dsi_type type) + enum dsi_type type, enum port port) { int ret; @@ -217,50 +210,54 @@ static int dsi_vc_write_common(struct intel_dsi *intel_dsi, BUG_ON(type == DSI_GENERIC); ret = dsi_vc_send_short(intel_dsi, channel, MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM, - 0); + 0, port); } else if (len == 1) { ret = dsi_vc_send_short(intel_dsi, channel, type == DSI_GENERIC ? MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM : - MIPI_DSI_DCS_SHORT_WRITE, data[0]); + MIPI_DSI_DCS_SHORT_WRITE, data[0], + port); } else if (len == 2) { ret = dsi_vc_send_short(intel_dsi, channel, type == DSI_GENERIC ? MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM : MIPI_DSI_DCS_SHORT_WRITE_PARAM, - (data[1] << 8) | data[0]); + (data[1] << 8) | data[0], port); } else { ret = dsi_vc_send_long(intel_dsi, channel, - type == DSI_GENERIC ? - MIPI_DSI_GENERIC_LONG_WRITE : - MIPI_DSI_DCS_LONG_WRITE, data, len); + type == DSI_GENERIC ? + MIPI_DSI_GENERIC_LONG_WRITE : + MIPI_DSI_DCS_LONG_WRITE, data, len, + port); } return ret; } int dsi_vc_dcs_write(struct intel_dsi *intel_dsi, int channel, - const u8 *data, int len) + const u8 *data, int len, enum port port) { - return dsi_vc_write_common(intel_dsi, channel, data, len, DSI_DCS); + return dsi_vc_write_common(intel_dsi, channel, data, len, DSI_DCS, + port); } int dsi_vc_generic_write(struct intel_dsi *intel_dsi, int channel, - const u8 *data, int len) + const u8 *data, int len, enum port port) { - return dsi_vc_write_common(intel_dsi, channel, data, len, DSI_GENERIC); + return dsi_vc_write_common(intel_dsi, channel, data, len, DSI_GENERIC, + port); } static int dsi_vc_dcs_send_read_request(struct intel_dsi *intel_dsi, - int channel, u8 dcs_cmd) + int channel, u8 dcs_cmd, enum port port) { return dsi_vc_send_short(intel_dsi, channel, MIPI_DSI_DCS_READ, - dcs_cmd); + dcs_cmd, port); } static int dsi_vc_generic_send_read_request(struct intel_dsi *intel_dsi, int channel, u8 *reqdata, - int reqlen) + int reqlen, enum port port) { u16 data; u8 data_type; @@ -282,17 +279,15 @@ static int dsi_vc_generic_send_read_request(struct intel_dsi *intel_dsi, BUG(); } - return dsi_vc_send_short(intel_dsi, channel, data_type, data); + return dsi_vc_send_short(intel_dsi, channel, data_type, data, port); } static int dsi_read_data_return(struct intel_dsi *intel_dsi, - u8 *buf, int buflen) + u8 *buf, int buflen, enum port port) { struct drm_encoder *encoder = &intel_dsi->base.base; struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); int i, len = 0; u32 data_reg, val; @@ -312,13 +307,11 @@ static int dsi_read_data_return(struct intel_dsi *intel_dsi, } int dsi_vc_dcs_read(struct intel_dsi *intel_dsi, int channel, u8 dcs_cmd, - u8 *buf, int buflen) + u8 *buf, int buflen, enum port port) { struct drm_encoder *encoder = &intel_dsi->base.base; struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); u32 mask; int ret; @@ -329,7 +322,7 @@ int dsi_vc_dcs_read(struct intel_dsi *intel_dsi, int channel, u8 dcs_cmd, I915_WRITE(MIPI_INTR_STAT(port), GEN_READ_DATA_AVAIL); - ret = dsi_vc_dcs_send_read_request(intel_dsi, channel, dcs_cmd); + ret = dsi_vc_dcs_send_read_request(intel_dsi, channel, dcs_cmd, port); if (ret) return ret; @@ -337,7 +330,7 @@ int dsi_vc_dcs_read(struct intel_dsi *intel_dsi, int channel, u8 dcs_cmd, if (wait_for((I915_READ(MIPI_INTR_STAT(port)) & mask) == mask, 50)) DRM_ERROR("Timeout waiting for read data.\n"); - ret = dsi_read_data_return(intel_dsi, buf, buflen); + ret = dsi_read_data_return(intel_dsi, buf, buflen, port); if (ret < 0) return ret; @@ -348,13 +341,11 @@ int dsi_vc_dcs_read(struct intel_dsi *intel_dsi, int channel, u8 dcs_cmd, } int dsi_vc_generic_read(struct intel_dsi *intel_dsi, int channel, - u8 *reqdata, int reqlen, u8 *buf, int buflen) + u8 *reqdata, int reqlen, u8 *buf, int buflen, enum port port) { struct drm_encoder *encoder = &intel_dsi->base.base; struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); u32 mask; int ret; @@ -366,7 +357,7 @@ int dsi_vc_generic_read(struct intel_dsi *intel_dsi, int channel, I915_WRITE(MIPI_INTR_STAT(port), GEN_READ_DATA_AVAIL); ret = dsi_vc_generic_send_read_request(intel_dsi, channel, reqdata, - reqlen); + reqlen, port); if (ret) return ret; @@ -374,7 +365,7 @@ int dsi_vc_generic_read(struct intel_dsi *intel_dsi, int channel, if (wait_for((I915_READ(MIPI_INTR_STAT(port)) & mask) == mask, 50)) DRM_ERROR("Timeout waiting for read data.\n"); - ret = dsi_read_data_return(intel_dsi, buf, buflen); + ret = dsi_read_data_return(intel_dsi, buf, buflen, port); if (ret < 0) return ret; diff --git a/drivers/gpu/drm/i915/intel_dsi_cmd.h b/drivers/gpu/drm/i915/intel_dsi_cmd.h index 46aa1acc00eba5..326a5ac555616a 100644 --- a/drivers/gpu/drm/i915/intel_dsi_cmd.h +++ b/drivers/gpu/drm/i915/intel_dsi_cmd.h @@ -36,77 +36,81 @@ #define DPI_LP_MODE_EN false #define DPI_HS_MODE_EN true -void dsi_hs_mode_enable(struct intel_dsi *intel_dsi, bool enable); +void dsi_hs_mode_enable(struct intel_dsi *intel_dsi, bool enable, + enum port port); int dsi_vc_dcs_write(struct intel_dsi *intel_dsi, int channel, - const u8 *data, int len); + const u8 *data, int len, enum port port); int dsi_vc_generic_write(struct intel_dsi *intel_dsi, int channel, - const u8 *data, int len); + const u8 *data, int len, enum port port); int dsi_vc_dcs_read(struct intel_dsi *intel_dsi, int channel, u8 dcs_cmd, - u8 *buf, int buflen); + u8 *buf, int buflen, enum port port); int dsi_vc_generic_read(struct intel_dsi *intel_dsi, int channel, - u8 *reqdata, int reqlen, u8 *buf, int buflen); + u8 *reqdata, int reqlen, u8 *buf, int buflen, enum port port); int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd, bool hs); void wait_for_dsi_fifo_empty(struct intel_dsi *intel_dsi); /* XXX: questionable write helpers */ static inline int dsi_vc_dcs_write_0(struct intel_dsi *intel_dsi, - int channel, u8 dcs_cmd) + int channel, u8 dcs_cmd, enum port port) { - return dsi_vc_dcs_write(intel_dsi, channel, &dcs_cmd, 1); + return dsi_vc_dcs_write(intel_dsi, channel, &dcs_cmd, 1, port); } static inline int dsi_vc_dcs_write_1(struct intel_dsi *intel_dsi, - int channel, u8 dcs_cmd, u8 param) + int channel, u8 dcs_cmd, u8 param, enum port port) { u8 buf[2] = { dcs_cmd, param }; - return dsi_vc_dcs_write(intel_dsi, channel, buf, 2); + return dsi_vc_dcs_write(intel_dsi, channel, buf, 2, port); } static inline int dsi_vc_generic_write_0(struct intel_dsi *intel_dsi, - int channel) + int channel, enum port port) { - return dsi_vc_generic_write(intel_dsi, channel, NULL, 0); + return dsi_vc_generic_write(intel_dsi, channel, NULL, 0, port); } static inline int dsi_vc_generic_write_1(struct intel_dsi *intel_dsi, - int channel, u8 param) + int channel, u8 param, enum port port) { - return dsi_vc_generic_write(intel_dsi, channel, ¶m, 1); + return dsi_vc_generic_write(intel_dsi, channel, ¶m, 1, port); } static inline int dsi_vc_generic_write_2(struct intel_dsi *intel_dsi, - int channel, u8 param1, u8 param2) + int channel, u8 param1, u8 param2, enum port port) { u8 buf[2] = { param1, param2 }; - return dsi_vc_generic_write(intel_dsi, channel, buf, 2); + return dsi_vc_generic_write(intel_dsi, channel, buf, 2, port); } /* XXX: questionable read helpers */ static inline int dsi_vc_generic_read_0(struct intel_dsi *intel_dsi, - int channel, u8 *buf, int buflen) + int channel, u8 *buf, int buflen, enum port port) { - return dsi_vc_generic_read(intel_dsi, channel, NULL, 0, buf, buflen); + return dsi_vc_generic_read(intel_dsi, channel, NULL, 0, buf, buflen, + port); } static inline int dsi_vc_generic_read_1(struct intel_dsi *intel_dsi, int channel, u8 param, u8 *buf, - int buflen) + int buflen, enum port port) { - return dsi_vc_generic_read(intel_dsi, channel, ¶m, 1, buf, buflen); + return dsi_vc_generic_read(intel_dsi, channel, ¶m, 1, buf, buflen, + port); } static inline int dsi_vc_generic_read_2(struct intel_dsi *intel_dsi, int channel, u8 param1, u8 param2, - u8 *buf, int buflen) + u8 *buf, int buflen, enum port port) { u8 req[2] = { param1, param2 }; - return dsi_vc_generic_read(intel_dsi, channel, req, 2, buf, buflen); + return dsi_vc_generic_read(intel_dsi, channel, req, 2, buf, buflen, + port); } diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index f6bdd44069cec7..7766c420f6b480 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -94,16 +94,23 @@ static struct gpio_table gtable[] = { { GPIO_NC_11_PCONF0, GPIO_NC_11_PAD, 0} }; +static inline enum port intel_dsi_seq_port_to_port(u8 port) +{ + return port ? PORT_C : PORT_A; +} + static u8 *mipi_exec_send_packet(struct intel_dsi *intel_dsi, u8 *data) { - u8 type, byte, mode, vc, port; + u8 type, byte, mode, vc, seq_port; u16 len; + enum port port; byte = *data++; mode = (byte >> MIPI_TRANSFER_MODE_SHIFT) & 0x1; vc = (byte >> MIPI_VIRTUAL_CHANNEL_SHIFT) & 0x3; - port = (byte >> MIPI_PORT_SHIFT) & 0x3; + seq_port = (byte >> MIPI_PORT_SHIFT) & 0x3; + port = intel_dsi_seq_port_to_port(seq_port); /* LP or HS mode */ intel_dsi->hs = mode; @@ -115,13 +122,13 @@ static u8 *mipi_exec_send_packet(struct intel_dsi *intel_dsi, u8 *data) switch (type) { case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM: - dsi_vc_generic_write_0(intel_dsi, vc); + dsi_vc_generic_write_0(intel_dsi, vc, port); break; case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM: - dsi_vc_generic_write_1(intel_dsi, vc, *data); + dsi_vc_generic_write_1(intel_dsi, vc, *data, port); break; case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM: - dsi_vc_generic_write_2(intel_dsi, vc, *data, *(data + 1)); + dsi_vc_generic_write_2(intel_dsi, vc, *data, *(data + 1), port); break; case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM: case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM: @@ -129,19 +136,19 @@ static u8 *mipi_exec_send_packet(struct intel_dsi *intel_dsi, u8 *data) DRM_DEBUG_DRIVER("Generic Read not yet implemented or used\n"); break; case MIPI_DSI_GENERIC_LONG_WRITE: - dsi_vc_generic_write(intel_dsi, vc, data, len); + dsi_vc_generic_write(intel_dsi, vc, data, len, port); break; case MIPI_DSI_DCS_SHORT_WRITE: - dsi_vc_dcs_write_0(intel_dsi, vc, *data); + dsi_vc_dcs_write_0(intel_dsi, vc, *data, port); break; case MIPI_DSI_DCS_SHORT_WRITE_PARAM: - dsi_vc_dcs_write_1(intel_dsi, vc, *data, *(data + 1)); + dsi_vc_dcs_write_1(intel_dsi, vc, *data, *(data + 1), port); break; case MIPI_DSI_DCS_READ: DRM_DEBUG_DRIVER("DCS Read not yet implemented or used\n"); break; case MIPI_DSI_DCS_LONG_WRITE: - dsi_vc_dcs_write(intel_dsi, vc, data, len); + dsi_vc_dcs_write(intel_dsi, vc, data, len, port); break; } From 7bcc3777b12a05687e5080e4de3c108f35d6aec8 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 5 Dec 2014 14:17:42 +0200 Subject: [PATCH 0088/3023] drm/i915: release struct_mutex on the i915_gem_init_hw fail path Release struct_mutex if init_rings() fails. This is a regression introduced in commit 35a57ffbb10840af219eeaf64718434242bb7c76 Author: Daniel Vetter Date: Thu Nov 20 00:33:07 2014 +0100 drm/i915: Only init engines once Reported-by: Wei Yongjun Signed-off-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c1c11418231bd0..e3ce4bef22a366 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4860,22 +4860,18 @@ int i915_gem_init(struct drm_device *dev) } ret = i915_gem_init_userptr(dev); - if (ret) { - mutex_unlock(&dev->struct_mutex); - return ret; - } + if (ret) + goto out_unlock; i915_gem_init_global_gtt(dev); ret = i915_gem_context_init(dev); - if (ret) { - mutex_unlock(&dev->struct_mutex); - return ret; - } + if (ret) + goto out_unlock; ret = dev_priv->gt.init_rings(dev); if (ret) - return ret; + goto out_unlock; ret = i915_gem_init_hw(dev); if (ret == -EIO) { @@ -4887,6 +4883,8 @@ int i915_gem_init(struct drm_device *dev) atomic_set_mask(I915_WEDGED, &dev_priv->gpu_error.reset_counter); ret = 0; } + +out_unlock: mutex_unlock(&dev->struct_mutex); return ret; From 8edfbb8bfc7ef291b12f683f40de8cf274ae8ed3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 14 Nov 2014 18:16:56 +0200 Subject: [PATCH 0089/3023] drm/i915: s/MI_STORE_DWORD_IMM_GEN8/MI_STORE_DWORD_IMM_GEN4/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MI_STORE_DWORD_IMM length has been the same ever since gen4. Rename the define to avoid potential confusion if someone tries to use this on pre-gen8. Also correct the comment on MI_MEM_VIRTUAL bit. It's present on 945,g33 and 965 only. Cc: Oscar Mateo Signed-off-by: Ville Syrjälä [danvet: Add USE_GGTT define for g4x+ too.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 5 +++-- drivers/gpu/drm/i915/intel_lrc.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index dc03facd587a6f..82da2323896c12 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -293,8 +293,9 @@ #define MI_SEMAPHORE_POLL (1<<15) #define MI_SEMAPHORE_SAD_GTE_SDD (1<<12) #define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1) -#define MI_STORE_DWORD_IMM_GEN8 MI_INSTR(0x20, 2) -#define MI_MEM_VIRTUAL (1 << 22) /* 965+ only */ +#define MI_STORE_DWORD_IMM_GEN4 MI_INSTR(0x20, 2) +#define MI_MEM_VIRTUAL (1 << 22) /* 945,g33,965 */ +#define MI_USE_GGTT (1 << 22) /* g4x+ */ #define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1) #define MI_STORE_DWORD_INDEX_SHIFT 2 /* Official intel docs are somewhat sloppy concerning MI_LOAD_REGISTER_IMM: diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 52e9952206d9da..7986eb3e502737 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1319,7 +1319,7 @@ static int gen8_emit_request(struct intel_ringbuffer *ringbuf) if (ret) return ret; - cmd = MI_STORE_DWORD_IMM_GEN8; + cmd = MI_STORE_DWORD_IMM_GEN4; cmd |= MI_GLOBAL_GTT; intel_logical_ring_emit(ringbuf, cmd); From 369602d370fac9d3bda125c8cc36c8f779910bf1 Mon Sep 17 00:00:00 2001 From: Gaurav K Singh Date: Fri, 5 Dec 2014 14:09:28 +0530 Subject: [PATCH 0090/3023] drm/i915: Add support for port enable/disable for dual link configuration For Dual Link MIPI Panels, both Port A and Port C should be enabled during the MIPI encoder enabling sequence. Similarly, during the disabling sequence, both ports needs to be disabled. v2: Used for_each_dsi_port macro instead of for loop v3: Used intel_dsi->ports instead of dual_link var for dual link configuration check v4: Masking of the required MIPI port bits before writing proper values Signed-off-by: Gaurav K Singh Signed-off-by: Shobhit Kumar Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_dsi.c | 37 +++++++++++++++------- drivers/gpu/drm/i915/intel_dsi.h | 1 + drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 4 +++ 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 82da2323896c12..b4a11ab7cb632f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6665,6 +6665,7 @@ enum punit_power_well { #define DPI_ENABLE (1 << 31) /* A + C */ #define MIPIA_MIPI4DPHY_DELAY_COUNT_SHIFT 27 #define MIPIA_MIPI4DPHY_DELAY_COUNT_MASK (0xf << 27) +#define DUAL_LINK_MODE_SHIFT 26 #define DUAL_LINK_MODE_MASK (1 << 26) #define DUAL_LINK_MODE_FRONT_BACK (0 << 26) #define DUAL_LINK_MODE_PIXEL_ALTERNATIVE (1 << 26) diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 693736b8808032..fd4d3972c8cda9 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -108,28 +108,41 @@ static void intel_dsi_port_enable(struct intel_encoder *encoder) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); - enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); + enum port port; u32 temp; - /* assert ip_tg_enable signal */ - temp = I915_READ(MIPI_PORT_CTRL(port)) & ~LANE_CONFIGURATION_MASK; - temp = temp | intel_dsi->port_bits; - I915_WRITE(MIPI_PORT_CTRL(port), temp | DPI_ENABLE); - POSTING_READ(MIPI_PORT_CTRL(port)); + for_each_dsi_port(port, intel_dsi->ports) { + temp = I915_READ(MIPI_PORT_CTRL(port)); + temp &= ~LANE_CONFIGURATION_MASK; + temp &= ~DUAL_LINK_MODE_MASK; + + if (intel_dsi->ports == ((1 << PORT_A) | (1 << PORT_C))) { + temp |= (intel_dsi->dual_link - 1) + << DUAL_LINK_MODE_SHIFT; + temp |= intel_crtc->pipe ? + LANE_CONFIGURATION_DUAL_LINK_B : + LANE_CONFIGURATION_DUAL_LINK_A; + } + /* assert ip_tg_enable signal */ + I915_WRITE(MIPI_PORT_CTRL(port), temp | DPI_ENABLE); + POSTING_READ(MIPI_PORT_CTRL(port)); + } } static void intel_dsi_port_disable(struct intel_encoder *encoder) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); + struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); + enum port port; u32 temp; - /* de-assert ip_tg_enable signal */ - temp = I915_READ(MIPI_PORT_CTRL(port)); - I915_WRITE(MIPI_PORT_CTRL(port), temp & ~DPI_ENABLE); - POSTING_READ(MIPI_PORT_CTRL(port)); + for_each_dsi_port(port, intel_dsi->ports) { + /* de-assert ip_tg_enable signal */ + temp = I915_READ(MIPI_PORT_CTRL(port)); + I915_WRITE(MIPI_PORT_CTRL(port), temp & ~DPI_ENABLE); + POSTING_READ(MIPI_PORT_CTRL(port)); + } } static void intel_dsi_device_ready(struct intel_encoder *encoder) diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index 7f5d0280b9d78a..f2cc2fc8c979dc 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -104,6 +104,7 @@ struct intel_dsi { u8 clock_stop; u8 escape_clk_div; + u8 dual_link; u32 port_bits; u32 bw_timer; u32 dphy_reg; diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index 7766c420f6b480..f60146f84467fc 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -287,6 +287,10 @@ static bool generic_init(struct intel_dsi_device *dsi) intel_dsi->clock_stop = mipi_config->enable_clk_stop ? 1 : 0; intel_dsi->lane_count = mipi_config->lane_cnt + 1; intel_dsi->pixel_format = mipi_config->videomode_color_format << 7; + intel_dsi->dual_link = mipi_config->dual_link; + + if (intel_dsi->dual_link) + intel_dsi->ports = ((1 << PORT_A) | (1 << PORT_C)); if (intel_dsi->pixel_format == VID_MODE_FORMAT_RGB666) bits_per_pixel = 18; From a9da9bce88ee842c7904b5670c035ca759e77238 Mon Sep 17 00:00:00 2001 From: Gaurav K Singh Date: Fri, 5 Dec 2014 14:13:41 +0530 Subject: [PATCH 0091/3023] drm/i915: Pixel Clock changes for DSI dual link For dual link MIPI Panels, each port needs half of pixel clock. Pixel overlap can be enabled if needed by panel, then in that case, pixel clock will be increased for extra pixels. v2 : Address review comments by Jani - Removed the bit mask used for ->dual_link - Used DSI instead of MIPI for #define variables v3: Added the VLV_DISPLAY_BASE to VLV_CHICKEN_3 register Signed-off-by: Gaurav K Singh Signed-off-by: Shobhit Kumar Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 4 ++++ drivers/gpu/drm/i915/intel_bios.h | 3 ++- drivers/gpu/drm/i915/intel_dsi.c | 8 ++++++++ drivers/gpu/drm/i915/intel_dsi.h | 6 ++++++ drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 21 +++++++++++++++++++++ 5 files changed, 41 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b4a11ab7cb632f..869e5ae1b011a0 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6030,6 +6030,10 @@ enum punit_power_well { #define GEN8_PMINTR_REDIRECT_TO_NON_DISP (1<<31) #define VLV_PWRDWNUPCTL 0xA294 +#define VLV_CHICKEN_3 (VLV_DISPLAY_BASE + 0x7040C) +#define PIXEL_OVERLAP_CNT_MASK (3 << 30) +#define PIXEL_OVERLAP_CNT_SHIFT 30 + #define GEN6_PMISR 0x44020 #define GEN6_PMIMR 0x44024 /* rps_lock */ #define GEN6_PMIIR 0x44028 diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index de01167d8a51b9..a6a8710f665f5c 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -818,7 +818,8 @@ struct mipi_config { #define DUAL_LINK_PIXEL_ALT 2 u16 dual_link:2; u16 lane_cnt:2; - u16 rsvd3:12; + u16 pixel_overlap:3; + u16 rsvd3:9; u16 rsvd4; diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index fd4d3972c8cda9..a1b93c55902560 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -111,6 +111,14 @@ static void intel_dsi_port_enable(struct intel_encoder *encoder) enum port port; u32 temp; + if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) { + temp = I915_READ(VLV_CHICKEN_3); + temp &= ~PIXEL_OVERLAP_CNT_MASK | + intel_dsi->pixel_overlap << + PIXEL_OVERLAP_CNT_SHIFT; + I915_WRITE(VLV_CHICKEN_3, temp); + } + for_each_dsi_port(port, intel_dsi->ports) { temp = I915_READ(MIPI_PORT_CTRL(port)); temp &= ~LANE_CONFIGURATION_MASK; diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index f2cc2fc8c979dc..8fe2064dd8045c 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -28,6 +28,11 @@ #include #include "intel_drv.h" +/* Dual Link support */ +#define DSI_DUAL_LINK_NONE 0 +#define DSI_DUAL_LINK_FRONT_BACK 1 +#define DSI_DUAL_LINK_PIXEL_ALT 2 + struct intel_dsi_device { unsigned int panel_id; const char *name; @@ -105,6 +110,7 @@ struct intel_dsi { u8 escape_clk_div; u8 dual_link; + u8 pixel_overlap; u32 port_bits; u32 bw_timer; u32 dphy_reg; diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index f60146f84467fc..f8c2269c434ce2 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -288,6 +288,7 @@ static bool generic_init(struct intel_dsi_device *dsi) intel_dsi->lane_count = mipi_config->lane_cnt + 1; intel_dsi->pixel_format = mipi_config->videomode_color_format << 7; intel_dsi->dual_link = mipi_config->dual_link; + intel_dsi->pixel_overlap = mipi_config->pixel_overlap; if (intel_dsi->dual_link) intel_dsi->ports = ((1 << PORT_A) | (1 << PORT_C)); @@ -310,6 +311,20 @@ static bool generic_init(struct intel_dsi_device *dsi) pclk = mode->clock; + /* In dual link mode each port needs half of pixel clock */ + if (intel_dsi->dual_link) { + pclk = pclk / 2; + + /* we can enable pixel_overlap if needed by panel. In this + * case we need to increase the pixelclock for extra pixels + */ + if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) { + pclk += DIV_ROUND_UP(mode->vtotal * + intel_dsi->pixel_overlap * + 60, 1000); + } + } + /* Burst Mode Ratio * Target ddr frequency from VBT / non burst ddr freq * multiply by 100 to preserve remainder @@ -504,6 +519,12 @@ static bool generic_init(struct intel_dsi_device *dsi) DRM_DEBUG_KMS("Clockstop %s\n", intel_dsi->clock_stop ? "disabled" : "enabled"); DRM_DEBUG_KMS("Mode %s\n", intel_dsi->operation_mode ? "command" : "video"); + if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) + DRM_DEBUG_KMS("Dual link: DSI_DUAL_LINK_FRONT_BACK\n"); + else if (intel_dsi->dual_link == DSI_DUAL_LINK_PIXEL_ALT) + DRM_DEBUG_KMS("Dual link: DSI_DUAL_LINK_PIXEL_ALT\n"); + else + DRM_DEBUG_KMS("Dual link: NONE\n"); DRM_DEBUG_KMS("Pixel Format %d\n", intel_dsi->pixel_format); DRM_DEBUG_KMS("TLPX %d\n", intel_dsi->escape_clk_div); DRM_DEBUG_KMS("LP RX Timeout 0x%x\n", intel_dsi->lp_rx_timeout); From 4510cd779e5897eeb8691aecbd639bb62ec27d55 Mon Sep 17 00:00:00 2001 From: Gaurav K Singh Date: Thu, 4 Dec 2014 10:58:51 +0530 Subject: [PATCH 0092/3023] drm/i915: Dual link needs Shutdown and Turn on packet for both ports For dual link MIPI panels, SHUTDOWN packet needs to send to both Ports A & C during MIPI encoder disabling sequence. Similarly, TURN ON packet to be sent to both Ports during MIPI encoder enabling sequence. v2: Address review comments by Jani - Used a for loop instead of do-while loop. v3: Used for_each_dsi_port macro instead of for loop Signed-off-by: Gaurav K Singh Signed-off-by: Shobhit Kumar Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dsi_cmd.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dsi_cmd.c b/drivers/gpu/drm/i915/intel_dsi_cmd.c index 8e3068451568fb..562811c1a9d2ba 100644 --- a/drivers/gpu/drm/i915/intel_dsi_cmd.c +++ b/drivers/gpu/drm/i915/intel_dsi_cmd.c @@ -385,8 +385,7 @@ int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd, bool hs) struct drm_encoder *encoder = &intel_dsi->base.base; struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); - enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); + enum port port; u32 mask; /* XXX: pipe, hs */ @@ -395,18 +394,23 @@ int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd, bool hs) else cmd |= DPI_LP_MODE; - /* clear bit */ - I915_WRITE(MIPI_INTR_STAT(port), SPL_PKT_SENT_INTERRUPT); + for_each_dsi_port(port, intel_dsi->ports) { + /* clear bit */ + I915_WRITE(MIPI_INTR_STAT(port), SPL_PKT_SENT_INTERRUPT); - /* XXX: old code skips write if control unchanged */ - if (cmd == I915_READ(MIPI_DPI_CONTROL(port))) - DRM_ERROR("Same special packet %02x twice in a row.\n", cmd); + /* XXX: old code skips write if control unchanged */ + if (cmd == I915_READ(MIPI_DPI_CONTROL(port))) + DRM_ERROR("Same special packet %02x twice in a row.\n", + cmd); - I915_WRITE(MIPI_DPI_CONTROL(port), cmd); + I915_WRITE(MIPI_DPI_CONTROL(port), cmd); - mask = SPL_PKT_SENT_INTERRUPT; - if (wait_for((I915_READ(MIPI_INTR_STAT(port)) & mask) == mask, 100)) - DRM_ERROR("Video mode command 0x%08x send failed.\n", cmd); + mask = SPL_PKT_SENT_INTERRUPT; + if (wait_for((I915_READ(MIPI_INTR_STAT(port)) & mask) == mask, + 100)) + DRM_ERROR("Video mode command 0x%08x send failed.\n", + cmd); + } return 0; } From 58cf8887c94d8dfe42206af7de57163ce0f46cf2 Mon Sep 17 00:00:00 2001 From: Gaurav K Singh Date: Thu, 4 Dec 2014 10:58:52 +0530 Subject: [PATCH 0093/3023] drm/i915: Enable DSI PLL for both DSI0 and DSI1 in case of dual link For Dual link MIPI Panels, dsipll clock for both DSI0 and DSI1 needs to be enabled. v2: Address review comments by Jani - Added wait time for PLL to be locked. v3: separate patch created for cck read for checking PLL to be locked Signed-off-by: Gaurav K Singh Signed-off-by: Shobhit Kumar Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dsi_pll.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c index fa7a6ca34cd654..636d72f7dd42c3 100644 --- a/drivers/gpu/drm/i915/intel_dsi_pll.c +++ b/drivers/gpu/drm/i915/intel_dsi_pll.c @@ -243,6 +243,9 @@ static void vlv_configure_dsi_pll(struct intel_encoder *encoder) dsi_mnp.dsi_pll_ctrl |= DSI_PLL_CLK_GATE_DSI0_DSIPLL; + if (intel_dsi->dual_link) + dsi_mnp.dsi_pll_ctrl |= DSI_PLL_CLK_GATE_DSI1_DSIPLL; + DRM_DEBUG_KMS("dsi pll div %08x, ctrl %08x\n", dsi_mnp.dsi_pll_div, dsi_mnp.dsi_pll_ctrl); From 3770f0eec40cb9f1fb7af6453f7bcb420a8a86bc Mon Sep 17 00:00:00 2001 From: Gaurav K Singh Date: Fri, 5 Dec 2014 14:16:58 +0530 Subject: [PATCH 0094/3023] drm/i915: cck reg used for checking DSI Pll locked Instead of pipe configuration reg, cck reg to be used for checking whether DSI Pll is getting locked or not. v2: dpio_lock unlocked now in case DSI PLL lock fails Signed-off-by: Gaurav K Singh Signed-off-by: Shobhit Kumar Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dsi_pll.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c index 636d72f7dd42c3..8957f1099a1f41 100644 --- a/drivers/gpu/drm/i915/intel_dsi_pll.c +++ b/drivers/gpu/drm/i915/intel_dsi_pll.c @@ -272,12 +272,14 @@ void vlv_enable_dsi_pll(struct intel_encoder *encoder) tmp |= DSI_PLL_VCO_EN; vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, tmp); - mutex_unlock(&dev_priv->dpio_lock); + if (wait_for(vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL) & + DSI_PLL_LOCK, 20)) { - if (wait_for(I915_READ(PIPECONF(PIPE_A)) & PIPECONF_DSI_PLL_LOCKED, 20)) { + mutex_unlock(&dev_priv->dpio_lock); DRM_ERROR("DSI PLL lock failed\n"); return; } + mutex_unlock(&dev_priv->dpio_lock); DRM_DEBUG_KMS("DSI PLL locked\n"); } From aa102d286a022fb0f42238c62c2b05cdac12109d Mon Sep 17 00:00:00 2001 From: Gaurav K Singh Date: Thu, 4 Dec 2014 10:58:54 +0530 Subject: [PATCH 0095/3023] drm/i915: MIPI Timings related changes for dual link hactive, hfp, hbp, hsync needs to be halved for dual link MIPI Panels. Accordingly timing related mmio regs needs to be programmed for both MIPI Ports. v2: Address review comments by Jani - Used a for loop instead of do-while loop v3: Used for_each_dsi_port macro instead of for loop Signed-off-by: Gaurav K Singh Signed-off-by: Shobhit Kumar Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dsi.c | 37 +++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index a1b93c55902560..585538bccb1ae8 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -479,7 +479,7 @@ static void set_dsi_timings(struct drm_encoder *encoder, struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); - enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); + enum port port; unsigned int bpp = intel_crtc->config.pipe_bpp; unsigned int lane_count = intel_dsi->lane_count; @@ -490,6 +490,15 @@ static void set_dsi_timings(struct drm_encoder *encoder, hsync = mode->hsync_end - mode->hsync_start; hbp = mode->htotal - mode->hsync_end; + if (intel_dsi->dual_link) { + hactive /= 2; + if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) + hactive += intel_dsi->pixel_overlap; + hfp /= 2; + hsync /= 2; + hbp /= 2; + } + vfp = mode->vsync_start - mode->vdisplay; vsync = mode->vsync_end - mode->vsync_start; vbp = mode->vtotal - mode->vsync_end; @@ -502,18 +511,20 @@ static void set_dsi_timings(struct drm_encoder *encoder, intel_dsi->burst_mode_ratio); hbp = txbyteclkhs(hbp, bpp, lane_count, intel_dsi->burst_mode_ratio); - I915_WRITE(MIPI_HACTIVE_AREA_COUNT(port), hactive); - I915_WRITE(MIPI_HFP_COUNT(port), hfp); - - /* meaningful for video mode non-burst sync pulse mode only, can be zero - * for non-burst sync events and burst modes */ - I915_WRITE(MIPI_HSYNC_PADDING_COUNT(port), hsync); - I915_WRITE(MIPI_HBP_COUNT(port), hbp); - - /* vertical values are in terms of lines */ - I915_WRITE(MIPI_VFP_COUNT(port), vfp); - I915_WRITE(MIPI_VSYNC_PADDING_COUNT(port), vsync); - I915_WRITE(MIPI_VBP_COUNT(port), vbp); + for_each_dsi_port(port, intel_dsi->ports) { + I915_WRITE(MIPI_HACTIVE_AREA_COUNT(port), hactive); + I915_WRITE(MIPI_HFP_COUNT(port), hfp); + + /* meaningful for video mode non-burst sync pulse mode only, + * can be zero for non-burst sync events and burst modes */ + I915_WRITE(MIPI_HSYNC_PADDING_COUNT(port), hsync); + I915_WRITE(MIPI_HBP_COUNT(port), hbp); + + /* vertical values are in terms of lines */ + I915_WRITE(MIPI_VFP_COUNT(port), vfp); + I915_WRITE(MIPI_VSYNC_PADDING_COUNT(port), vsync); + I915_WRITE(MIPI_VBP_COUNT(port), vbp); + } } static void intel_dsi_prepare(struct intel_encoder *intel_encoder) From 384f02a2c4551fc785477d1808a59d717fd70420 Mon Sep 17 00:00:00 2001 From: Gaurav K Singh Date: Fri, 5 Dec 2014 14:22:44 +0530 Subject: [PATCH 0096/3023] drm/i915: Update the DSI disable path to support dual link panel disabling We need to program both port registers during dual link disable path. v2: Address review comments by Jani - Used a for loop instead of do-while loop. v3: Used for_each_dsi_port macro instead of for loop v4: Added comments for the usage of AFE latchout bit Signed-off-by: Gaurav K Singh Signed-off-by: Shobhit Kumar Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dsi.c | 83 ++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 585538bccb1ae8..80549284023147 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -281,9 +281,8 @@ static void intel_dsi_disable(struct intel_encoder *encoder) { struct drm_device *dev = encoder->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); - enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); + enum port port; u32 temp; DRM_DEBUG_KMS("\n"); @@ -295,23 +294,24 @@ static void intel_dsi_disable(struct intel_encoder *encoder) msleep(2); } - /* Panel commands can be sent when clock is in LP11 */ - I915_WRITE(MIPI_DEVICE_READY(port), 0x0); - - temp = I915_READ(MIPI_CTRL(port)); - temp &= ~ESCAPE_CLOCK_DIVIDER_MASK; - I915_WRITE(MIPI_CTRL(port), temp | - intel_dsi->escape_clk_div << - ESCAPE_CLOCK_DIVIDER_SHIFT); + for_each_dsi_port(port, intel_dsi->ports) { + /* Panel commands can be sent when clock is in LP11 */ + I915_WRITE(MIPI_DEVICE_READY(port), 0x0); - I915_WRITE(MIPI_EOT_DISABLE(port), CLOCKSTOP); + temp = I915_READ(MIPI_CTRL(port)); + temp &= ~ESCAPE_CLOCK_DIVIDER_MASK; + I915_WRITE(MIPI_CTRL(port), temp | + intel_dsi->escape_clk_div << + ESCAPE_CLOCK_DIVIDER_SHIFT); - temp = I915_READ(MIPI_DSI_FUNC_PRG(port)); - temp &= ~VID_MODE_FORMAT_MASK; - I915_WRITE(MIPI_DSI_FUNC_PRG(port), temp); + I915_WRITE(MIPI_EOT_DISABLE(port), CLOCKSTOP); - I915_WRITE(MIPI_DEVICE_READY(port), 0x1); + temp = I915_READ(MIPI_DSI_FUNC_PRG(port)); + temp &= ~VID_MODE_FORMAT_MASK; + I915_WRITE(MIPI_DSI_FUNC_PRG(port), temp); + I915_WRITE(MIPI_DEVICE_READY(port), 0x1); + } /* if disable packets are sent before sending shutdown packet then in * some next enable sequence send turn on packet error is observed */ if (intel_dsi->dev.dev_ops->disable) @@ -323,31 +323,42 @@ static void intel_dsi_disable(struct intel_encoder *encoder) static void intel_dsi_clear_device_ready(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); + struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); + enum port port; u32 val; DRM_DEBUG_KMS("\n"); + for_each_dsi_port(port, intel_dsi->ports) { - I915_WRITE(MIPI_DEVICE_READY(port), DEVICE_READY | ULPS_STATE_ENTER); - usleep_range(2000, 2500); - - I915_WRITE(MIPI_DEVICE_READY(port), DEVICE_READY | ULPS_STATE_EXIT); - usleep_range(2000, 2500); - - I915_WRITE(MIPI_DEVICE_READY(port), DEVICE_READY | ULPS_STATE_ENTER); - usleep_range(2000, 2500); - - if (wait_for(((I915_READ(MIPI_PORT_CTRL(port)) & AFE_LATCHOUT) - == 0x00000), 30)) - DRM_ERROR("DSI LP not going Low\n"); - - val = I915_READ(MIPI_PORT_CTRL(port)); - I915_WRITE(MIPI_PORT_CTRL(port), val & ~LP_OUTPUT_HOLD); - usleep_range(1000, 1500); - - I915_WRITE(MIPI_DEVICE_READY(port), 0x00); - usleep_range(2000, 2500); + I915_WRITE(MIPI_DEVICE_READY(port), DEVICE_READY | + ULPS_STATE_ENTER); + usleep_range(2000, 2500); + + I915_WRITE(MIPI_DEVICE_READY(port), DEVICE_READY | + ULPS_STATE_EXIT); + usleep_range(2000, 2500); + + I915_WRITE(MIPI_DEVICE_READY(port), DEVICE_READY | + ULPS_STATE_ENTER); + usleep_range(2000, 2500); + + /* Wait till Clock lanes are in LP-00 state for MIPI Port A + * only. MIPI Port C has no similar bit for checking + */ + if (wait_for(((I915_READ(MIPI_PORT_CTRL(PORT_A)) & AFE_LATCHOUT) + == 0x00000), 30)) + DRM_ERROR("DSI LP not going Low\n"); + + val = I915_READ(MIPI_PORT_CTRL(port)); + /* Disable MIPI PHY transparent latch + * Common bit for both MIPI Port A & MIPI Port C + */ + I915_WRITE(MIPI_PORT_CTRL(PORT_A), val & ~LP_OUTPUT_HOLD); + usleep_range(1000, 1500); + + I915_WRITE(MIPI_DEVICE_READY(port), 0x00); + usleep_range(2000, 2500); + } vlv_disable_dsi_pll(encoder); } From 24ee0e64909bf7f1953d87d3e1e29d93eafcad73 Mon Sep 17 00:00:00 2001 From: Gaurav K Singh Date: Fri, 5 Dec 2014 14:24:21 +0530 Subject: [PATCH 0097/3023] drm/i915: Update the DSI enable path to support dual We need to program both port registers during dual link enable path. v2: Address review comments by Jani - Used a for loop instead of do-while loop. v3: Used for_each_dsi_port macro instead of for loop v4: Renamed mode_hactive variable to mode_hdisplay Signed-off-by: Gaurav K Singh Signed-off-by: Shobhit Kumar Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dsi.c | 241 +++++++++++++++++-------------- 1 file changed, 131 insertions(+), 110 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 80549284023147..8f8b952eaa9259 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -156,8 +156,8 @@ static void intel_dsi_port_disable(struct intel_encoder *encoder) static void intel_dsi_device_ready(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); - enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); + struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); + enum port port; u32 val; DRM_DEBUG_KMS("\n"); @@ -171,18 +171,21 @@ static void intel_dsi_device_ready(struct intel_encoder *encoder) /* bandgap reset is needed after everytime we do power gate */ band_gap_reset(dev_priv); - I915_WRITE(MIPI_DEVICE_READY(port), ULPS_STATE_ENTER); - usleep_range(2500, 3000); + for_each_dsi_port(port, intel_dsi->ports) { - val = I915_READ(MIPI_PORT_CTRL(port)); - I915_WRITE(MIPI_PORT_CTRL(port), val | LP_OUTPUT_HOLD); - usleep_range(1000, 1500); + I915_WRITE(MIPI_DEVICE_READY(port), ULPS_STATE_ENTER); + usleep_range(2500, 3000); - I915_WRITE(MIPI_DEVICE_READY(port), ULPS_STATE_EXIT); - usleep_range(2500, 3000); + val = I915_READ(MIPI_PORT_CTRL(port)); + I915_WRITE(MIPI_PORT_CTRL(port), val | LP_OUTPUT_HOLD); + usleep_range(1000, 1500); - I915_WRITE(MIPI_DEVICE_READY(port), DEVICE_READY); - usleep_range(2500, 3000); + I915_WRITE(MIPI_DEVICE_READY(port), ULPS_STATE_EXIT); + usleep_range(2500, 3000); + + I915_WRITE(MIPI_DEVICE_READY(port), DEVICE_READY); + usleep_range(2500, 3000); + } } static void intel_dsi_enable(struct intel_encoder *encoder) @@ -547,32 +550,43 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder) struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); struct drm_display_mode *adjusted_mode = &intel_crtc->config.adjusted_mode; - enum port port = intel_dsi_pipe_to_port(intel_crtc->pipe); + enum port port; unsigned int bpp = intel_crtc->config.pipe_bpp; u32 val, tmp; + u16 mode_hdisplay; DRM_DEBUG_KMS("pipe %c\n", pipe_name(intel_crtc->pipe)); - /* escape clock divider, 20MHz, shared for A and C. device ready must be - * off when doing this! txclkesc? */ - tmp = I915_READ(MIPI_CTRL(PORT_A)); - tmp &= ~ESCAPE_CLOCK_DIVIDER_MASK; - I915_WRITE(MIPI_CTRL(PORT_A), tmp | ESCAPE_CLOCK_DIVIDER_1); - - /* read request priority is per pipe */ - tmp = I915_READ(MIPI_CTRL(port)); - tmp &= ~READ_REQUEST_PRIORITY_MASK; - I915_WRITE(MIPI_CTRL(port), tmp | READ_REQUEST_PRIORITY_HIGH); + mode_hdisplay = adjusted_mode->hdisplay; - /* XXX: why here, why like this? handling in irq handler?! */ - I915_WRITE(MIPI_INTR_STAT(port), 0xffffffff); - I915_WRITE(MIPI_INTR_EN(port), 0xffffffff); - - I915_WRITE(MIPI_DPHY_PARAM(port), intel_dsi->dphy_reg); + if (intel_dsi->dual_link) { + mode_hdisplay /= 2; + if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) + mode_hdisplay += intel_dsi->pixel_overlap; + } - I915_WRITE(MIPI_DPI_RESOLUTION(port), - adjusted_mode->vdisplay << VERTICAL_ADDRESS_SHIFT | - adjusted_mode->hdisplay << HORIZONTAL_ADDRESS_SHIFT); + for_each_dsi_port(port, intel_dsi->ports) { + /* escape clock divider, 20MHz, shared for A and C. + * device ready must be off when doing this! txclkesc? */ + tmp = I915_READ(MIPI_CTRL(PORT_A)); + tmp &= ~ESCAPE_CLOCK_DIVIDER_MASK; + I915_WRITE(MIPI_CTRL(PORT_A), tmp | ESCAPE_CLOCK_DIVIDER_1); + + /* read request priority is per pipe */ + tmp = I915_READ(MIPI_CTRL(port)); + tmp &= ~READ_REQUEST_PRIORITY_MASK; + I915_WRITE(MIPI_CTRL(port), tmp | READ_REQUEST_PRIORITY_HIGH); + + /* XXX: why here, why like this? handling in irq handler?! */ + I915_WRITE(MIPI_INTR_STAT(port), 0xffffffff); + I915_WRITE(MIPI_INTR_EN(port), 0xffffffff); + + I915_WRITE(MIPI_DPHY_PARAM(port), intel_dsi->dphy_reg); + + I915_WRITE(MIPI_DPI_RESOLUTION(port), + adjusted_mode->vdisplay << VERTICAL_ADDRESS_SHIFT | + mode_hdisplay << HORIZONTAL_ADDRESS_SHIFT); + } set_dsi_timings(encoder, adjusted_mode); @@ -586,95 +600,102 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder) /* XXX: cross-check bpp vs. pixel format? */ val |= intel_dsi->pixel_format; } - I915_WRITE(MIPI_DSI_FUNC_PRG(port), val); - /* timeouts for recovery. one frame IIUC. if counter expires, EOT and - * stop state. */ - - /* - * In burst mode, value greater than one DPI line Time in byte clock - * (txbyteclkhs) To timeout this timer 1+ of the above said value is - * recommended. - * - * In non-burst mode, Value greater than one DPI frame time in byte - * clock(txbyteclkhs) To timeout this timer 1+ of the above said value - * is recommended. - * - * In DBI only mode, value greater than one DBI frame time in byte - * clock(txbyteclkhs) To timeout this timer 1+ of the above said value - * is recommended. - */ - - if (is_vid_mode(intel_dsi) && - intel_dsi->video_mode_format == VIDEO_MODE_BURST) { - I915_WRITE(MIPI_HS_TX_TIMEOUT(port), - txbyteclkhs(adjusted_mode->htotal, bpp, - intel_dsi->lane_count, - intel_dsi->burst_mode_ratio) + 1); - } else { - I915_WRITE(MIPI_HS_TX_TIMEOUT(port), - txbyteclkhs(adjusted_mode->vtotal * - adjusted_mode->htotal, - bpp, intel_dsi->lane_count, - intel_dsi->burst_mode_ratio) + 1); - } - I915_WRITE(MIPI_LP_RX_TIMEOUT(port), intel_dsi->lp_rx_timeout); - I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(port), intel_dsi->turn_arnd_val); - I915_WRITE(MIPI_DEVICE_RESET_TIMER(port), intel_dsi->rst_timer_val); + tmp = 0; + if (intel_dsi->eotp_pkt == 0) + tmp |= EOT_DISABLE; + if (intel_dsi->clock_stop) + tmp |= CLOCKSTOP; - /* dphy stuff */ + for_each_dsi_port(port, intel_dsi->ports) { + I915_WRITE(MIPI_DSI_FUNC_PRG(port), val); + + /* timeouts for recovery. one frame IIUC. if counter expires, + * EOT and stop state. */ + + /* + * In burst mode, value greater than one DPI line Time in byte + * clock (txbyteclkhs) To timeout this timer 1+ of the above + * said value is recommended. + * + * In non-burst mode, Value greater than one DPI frame time in + * byte clock(txbyteclkhs) To timeout this timer 1+ of the above + * said value is recommended. + * + * In DBI only mode, value greater than one DBI frame time in + * byte clock(txbyteclkhs) To timeout this timer 1+ of the above + * said value is recommended. + */ - /* in terms of low power clock */ - I915_WRITE(MIPI_INIT_COUNT(port), txclkesc(intel_dsi->escape_clk_div, 100)); + if (is_vid_mode(intel_dsi) && + intel_dsi->video_mode_format == VIDEO_MODE_BURST) { + I915_WRITE(MIPI_HS_TX_TIMEOUT(port), + txbyteclkhs(adjusted_mode->htotal, bpp, + intel_dsi->lane_count, + intel_dsi->burst_mode_ratio) + 1); + } else { + I915_WRITE(MIPI_HS_TX_TIMEOUT(port), + txbyteclkhs(adjusted_mode->vtotal * + adjusted_mode->htotal, + bpp, intel_dsi->lane_count, + intel_dsi->burst_mode_ratio) + 1); + } + I915_WRITE(MIPI_LP_RX_TIMEOUT(port), intel_dsi->lp_rx_timeout); + I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(port), + intel_dsi->turn_arnd_val); + I915_WRITE(MIPI_DEVICE_RESET_TIMER(port), + intel_dsi->rst_timer_val); - val = 0; - if (intel_dsi->eotp_pkt == 0) - val |= EOT_DISABLE; + /* dphy stuff */ - if (intel_dsi->clock_stop) - val |= CLOCKSTOP; + /* in terms of low power clock */ + I915_WRITE(MIPI_INIT_COUNT(port), + txclkesc(intel_dsi->escape_clk_div, 100)); - /* recovery disables */ - I915_WRITE(MIPI_EOT_DISABLE(port), val); - /* in terms of low power clock */ - I915_WRITE(MIPI_INIT_COUNT(port), intel_dsi->init_count); + /* recovery disables */ + I915_WRITE(MIPI_EOT_DISABLE(port), val); - /* in terms of txbyteclkhs. actual high to low switch + - * MIPI_STOP_STATE_STALL * MIPI_LP_BYTECLK. - * - * XXX: write MIPI_STOP_STATE_STALL? - */ - I915_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT(port), - intel_dsi->hs_to_lp_count); + /* in terms of low power clock */ + I915_WRITE(MIPI_INIT_COUNT(port), intel_dsi->init_count); - /* XXX: low power clock equivalence in terms of byte clock. the number - * of byte clocks occupied in one low power clock. based on txbyteclkhs - * and txclkesc. txclkesc time / txbyteclk time * (105 + - * MIPI_STOP_STATE_STALL) / 105.??? - */ - I915_WRITE(MIPI_LP_BYTECLK(port), intel_dsi->lp_byte_clk); - - /* the bw essential for transmitting 16 long packets containing 252 - * bytes meant for dcs write memory command is programmed in this - * register in terms of byte clocks. based on dsi transfer rate and the - * number of lanes configured the time taken to transmit 16 long packets - * in a dsi stream varies. */ - I915_WRITE(MIPI_DBI_BW_CTRL(port), intel_dsi->bw_timer); - - I915_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT(port), - intel_dsi->clk_lp_to_hs_count << LP_HS_SSW_CNT_SHIFT | - intel_dsi->clk_hs_to_lp_count << HS_LP_PWR_SW_CNT_SHIFT); - - if (is_vid_mode(intel_dsi)) - /* Some panels might have resolution which is not a multiple of - * 64 like 1366 x 768. Enable RANDOM resolution support for such - * panels by default */ - I915_WRITE(MIPI_VIDEO_MODE_FORMAT(port), - intel_dsi->video_frmt_cfg_bits | - intel_dsi->video_mode_format | - IP_TG_CONFIG | - RANDOM_DPI_DISPLAY_RESOLUTION); + /* in terms of txbyteclkhs. actual high to low switch + + * MIPI_STOP_STATE_STALL * MIPI_LP_BYTECLK. + * + * XXX: write MIPI_STOP_STATE_STALL? + */ + I915_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT(port), + intel_dsi->hs_to_lp_count); + + /* XXX: low power clock equivalence in terms of byte clock. + * the number of byte clocks occupied in one low power clock. + * based on txbyteclkhs and txclkesc. + * txclkesc time / txbyteclk time * (105 + MIPI_STOP_STATE_STALL + * ) / 105.??? + */ + I915_WRITE(MIPI_LP_BYTECLK(port), intel_dsi->lp_byte_clk); + + /* the bw essential for transmitting 16 long packets containing + * 252 bytes meant for dcs write memory command is programmed in + * this register in terms of byte clocks. based on dsi transfer + * rate and the number of lanes configured the time taken to + * transmit 16 long packets in a dsi stream varies. */ + I915_WRITE(MIPI_DBI_BW_CTRL(port), intel_dsi->bw_timer); + + I915_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT(port), + intel_dsi->clk_lp_to_hs_count << LP_HS_SSW_CNT_SHIFT | + intel_dsi->clk_hs_to_lp_count << HS_LP_PWR_SW_CNT_SHIFT); + + if (is_vid_mode(intel_dsi)) + /* Some panels might have resolution which is not a + * multiple of 64 like 1366 x 768. Enable RANDOM + * resolution support for such panels by default */ + I915_WRITE(MIPI_VIDEO_MODE_FORMAT(port), + intel_dsi->video_frmt_cfg_bits | + intel_dsi->video_mode_format | + IP_TG_CONFIG | + RANDOM_DPI_DISPLAY_RESOLUTION); + } } static void intel_dsi_pre_pll_enable(struct intel_encoder *encoder) From f3f32360b6d9e22ece894a4d49abdd2d9a82fe81 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Thu, 4 Dec 2014 15:07:52 +0000 Subject: [PATCH 0098/3023] drm/i915/bdw: Add WaHdcDisableFetchWhenMasked MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We already have it for chv, but was missing for bdw. Signed-off-by: Michel Thierry Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 79b4ca5dc65f29..f52101521653a2 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -766,9 +766,11 @@ static int bdw_init_workarounds(struct intel_engine_cs *ring) * workaround for for a possible hang in the unlikely event a TLB * invalidation occurs during a PSD flush. */ + /* WaHdcDisableFetchWhenMasked:bdw */ /* WaDisableFenceDestinationToSLM:bdw (GT3 pre-production) */ WA_SET_BIT_MASKED(HDC_CHICKEN0, HDC_FORCE_NON_COHERENT | + HDC_DONOT_FETCH_MEM_WHEN_MASKED | (IS_BDW_GT3(dev) ? HDC_FENCE_DEST_SLM_DISABLE : 0)); /* Wa4x4STCOptimizationDisable:bdw */ From 93dc1b6529eb8acd98243caaf399daf3c2c665bd Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 5 Dec 2014 15:59:16 +0100 Subject: [PATCH 0099/3023] drm/i915: Update DRIVER_DATE to 20141205 Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 049482f5d9ac14..502a01bef1ed65 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -55,7 +55,7 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20141121" +#define DRIVER_DATE "20141205" #undef WARN_ON #define WARN_ON(x) WARN(x, "WARN_ON(" #x ")") From ecb7e16bf187bc369cf6a5cd108582c01329980d Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Mon, 1 Dec 2014 15:40:09 -0800 Subject: [PATCH 0100/3023] drm: add helper to get crtc timings (v5) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to get hdisplay and vdisplay in a few places so create a helper to make our job easier. Note that drm_crtc_check_viewport() and intel_modeset_pipe_config() were previously making adjustments for doublescan modes and vscan > 1 modes, which was incorrect. Using our new helper fixes this mistake. v2 (by Matt): Use new stereo doubling function (suggested by Ville) v3 (by Matt): - Add missing kerneldoc (Daniel) - Use drm_mode_copy() (Jani) v4 (by Matt): - Drop stereo doubling function again; add 'stereo only' flag to drm_mode_set_crtcinfo() instead (Ville) v5 (by Matt): - Note behavioral change in drm_crtc_check_viewport() and intel_modeset_pipe_config(). (Ander) - Describe new adjustment flags in drm_mode_set_crtcinfo()'s kerneldoc. (Ander) Cc: dri-devel@lists.freedesktop.org Suggested-by: Ville Syrjälä Signed-off-by: Gustavo Padovan Signed-off-by: Matt Roper Acked-by: Dave Airlie Reviewed-by: Ander Conselvan de Oliveira Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 32 +++++++++++++++++++--------- drivers/gpu/drm/drm_modes.c | 26 +++++++++++++--------- drivers/gpu/drm/i915/intel_display.c | 6 +++--- include/drm/drm_crtc.h | 2 ++ include/drm/drm_modes.h | 3 +++ 5 files changed, 46 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index de79283eaea720..2985e3ff364f47 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2549,6 +2549,27 @@ int drm_mode_set_config_internal(struct drm_mode_set *set) } EXPORT_SYMBOL(drm_mode_set_config_internal); +/** + * drm_crtc_get_hv_timing - Fetches hdisplay/vdisplay for given mode + * @mode: mode to query + * @hdisplay: hdisplay value to fill in + * @vdisplay: vdisplay value to fill in + * + * The vdisplay value will be doubled if the specified mode is a stereo mode of + * the appropriate layout. + */ +void drm_crtc_get_hv_timing(const struct drm_display_mode *mode, + int *hdisplay, int *vdisplay) +{ + struct drm_display_mode adjusted; + + drm_mode_copy(&adjusted, mode); + drm_mode_set_crtcinfo(&adjusted, CRTC_STEREO_DOUBLE_ONLY); + *hdisplay = adjusted.crtc_hdisplay; + *vdisplay = adjusted.crtc_vdisplay; +} +EXPORT_SYMBOL(drm_crtc_get_hv_timing); + /** * drm_crtc_check_viewport - Checks that a framebuffer is big enough for the * CRTC viewport @@ -2566,16 +2587,7 @@ int drm_crtc_check_viewport(const struct drm_crtc *crtc, { int hdisplay, vdisplay; - hdisplay = mode->hdisplay; - vdisplay = mode->vdisplay; - - if (drm_mode_is_stereo(mode)) { - struct drm_display_mode adjusted = *mode; - - drm_mode_set_crtcinfo(&adjusted, CRTC_STEREO_DOUBLE); - hdisplay = adjusted.crtc_hdisplay; - vdisplay = adjusted.crtc_vdisplay; - } + drm_crtc_get_hv_timing(mode, &hdisplay, &vdisplay); if (crtc->invert_dimensions) swap(hdisplay, vdisplay); diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 6d8b941c820041..7689c14f2f09b2 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -739,6 +739,8 @@ EXPORT_SYMBOL(drm_mode_vrefresh); * - The CRTC_STEREO_DOUBLE flag can be used to compute the timings for * buffers containing two eyes (only adjust the timings when needed, eg. for * "frame packing" or "side by side full"). + * - The CRTC_NO_DBLSCAN and CRTC_NO_VSCAN flags request that adjustment *not* + * be performed for doublescan and vscan > 1 modes respectively. */ void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags) { @@ -765,18 +767,22 @@ void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags) } } - if (p->flags & DRM_MODE_FLAG_DBLSCAN) { - p->crtc_vdisplay *= 2; - p->crtc_vsync_start *= 2; - p->crtc_vsync_end *= 2; - p->crtc_vtotal *= 2; + if (!(adjust_flags & CRTC_NO_DBLSCAN)) { + if (p->flags & DRM_MODE_FLAG_DBLSCAN) { + p->crtc_vdisplay *= 2; + p->crtc_vsync_start *= 2; + p->crtc_vsync_end *= 2; + p->crtc_vtotal *= 2; + } } - if (p->vscan > 1) { - p->crtc_vdisplay *= p->vscan; - p->crtc_vsync_start *= p->vscan; - p->crtc_vsync_end *= p->vscan; - p->crtc_vtotal *= p->vscan; + if (!(adjust_flags & CRTC_NO_VSCAN)) { + if (p->vscan > 1) { + p->crtc_vdisplay *= p->vscan; + p->crtc_vsync_start *= p->vscan; + p->crtc_vsync_end *= p->vscan; + p->crtc_vtotal *= p->vscan; + } } if (adjust_flags & CRTC_STEREO_DOUBLE) { diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3a088c03d7b9ae..9eee2c950ab3d4 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10322,9 +10322,9 @@ intel_modeset_pipe_config(struct drm_crtc *crtc, * computation to clearly distinguish it from the adjusted mode, which * can be changed by the connectors in the below retry loop. */ - drm_mode_set_crtcinfo(&pipe_config->requested_mode, CRTC_STEREO_DOUBLE); - pipe_config->pipe_src_w = pipe_config->requested_mode.crtc_hdisplay; - pipe_config->pipe_src_h = pipe_config->requested_mode.crtc_vdisplay; + drm_crtc_get_hv_timing(&pipe_config->requested_mode, + &pipe_config->pipe_src_w, + &pipe_config->pipe_src_h); encoder_retry: /* Ensure the port clock defaults are reset when retrying. */ diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index dd2c16e4333312..969da0f1ded8ec 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1161,6 +1161,8 @@ extern int drm_plane_init(struct drm_device *dev, extern void drm_plane_cleanup(struct drm_plane *plane); extern unsigned int drm_plane_index(struct drm_plane *plane); extern void drm_plane_force_disable(struct drm_plane *plane); +extern void drm_crtc_get_hv_timing(const struct drm_display_mode *mode, + int *hdisplay, int *vdisplay); extern int drm_crtc_check_viewport(const struct drm_crtc *crtc, int x, int y, const struct drm_display_mode *mode, diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index 91d0582f924e3e..8f17811d27f505 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -90,6 +90,9 @@ enum drm_mode_status { #define CRTC_INTERLACE_HALVE_V (1 << 0) /* halve V values for interlacing */ #define CRTC_STEREO_DOUBLE (1 << 1) /* adjust timings for stereo modes */ +#define CRTC_NO_DBLSCAN (1 << 2) /* don't adjust doublescan */ +#define CRTC_NO_VSCAN (1 << 3) /* don't adjust doublescan */ +#define CRTC_STEREO_DOUBLE_ONLY (CRTC_NO_DBLSCAN | CRTC_NO_VSCAN) #define DRM_MODE_FLAG_3D_MAX DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF From a912f12fe8f2c386007d9f0776fd12dcba5c96cf Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Mon, 1 Dec 2014 15:40:10 -0800 Subject: [PATCH 0101/3023] drm/i915: remove intel_crtc_cursor_set_obj() (v5) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge it into the plane update_plane() callback and make other users use the update_plane() functions instead. The fb != crtc->cursor->fb was already inside intel_crtc_cursor_set_obj() so we fold intel_crtc_cursor_set_obj() inside intel_commit_cursor_plane() and merge both paths into one. v5 (by Matt): - Rebase onto latest di-nightly codebase - Drop extra unreference call when we fail to pin (Ville) Reviewed-by(v4): Ville Syrjälä Signed-off-by: Gustavo Padovan Signed-off-by: Matt Roper Reviewed-by: Ander Conselvan de Oliveira Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 215 ++++++++++++--------------- 1 file changed, 99 insertions(+), 116 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9eee2c950ab3d4..3342eb7f315bb7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8417,109 +8417,6 @@ static bool cursor_size_ok(struct drm_device *dev, return true; } -static int intel_crtc_cursor_set_obj(struct drm_crtc *crtc, - struct drm_i915_gem_object *obj, - uint32_t width, uint32_t height) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe; - unsigned old_width; - uint32_t addr; - int ret; - - /* if we want to turn off the cursor ignore width and height */ - if (!obj) { - DRM_DEBUG_KMS("cursor off\n"); - addr = 0; - mutex_lock(&dev->struct_mutex); - goto finish; - } - - /* we only need to pin inside GTT if cursor is non-phy */ - mutex_lock(&dev->struct_mutex); - if (!INTEL_INFO(dev)->cursor_needs_physical) { - unsigned alignment; - - /* - * Global gtt pte registers are special registers which actually - * forward writes to a chunk of system memory. Which means that - * there is no risk that the register values disappear as soon - * as we call intel_runtime_pm_put(), so it is correct to wrap - * only the pin/unpin/fence and not more. - */ - intel_runtime_pm_get(dev_priv); - - /* Note that the w/a also requires 2 PTE of padding following - * the bo. We currently fill all unused PTE with the shadow - * page and so we should always have valid PTE following the - * cursor preventing the VT-d warning. - */ - alignment = 0; - if (need_vtd_wa(dev)) - alignment = 64*1024; - - ret = i915_gem_object_pin_to_display_plane(obj, alignment, NULL); - if (ret) { - DRM_DEBUG_KMS("failed to move cursor bo into the GTT\n"); - intel_runtime_pm_put(dev_priv); - goto fail_locked; - } - - ret = i915_gem_object_put_fence(obj); - if (ret) { - DRM_DEBUG_KMS("failed to release fence for cursor"); - intel_runtime_pm_put(dev_priv); - goto fail_unpin; - } - - addr = i915_gem_obj_ggtt_offset(obj); - - intel_runtime_pm_put(dev_priv); - } else { - int align = IS_I830(dev) ? 16 * 1024 : 256; - ret = i915_gem_object_attach_phys(obj, align); - if (ret) { - DRM_DEBUG_KMS("failed to attach phys object\n"); - goto fail_locked; - } - addr = obj->phys_handle->busaddr; - } - - finish: - if (intel_crtc->cursor_bo) { - if (!INTEL_INFO(dev)->cursor_needs_physical) - i915_gem_object_unpin_from_display_plane(intel_crtc->cursor_bo); - } - - i915_gem_track_fb(intel_crtc->cursor_bo, obj, - INTEL_FRONTBUFFER_CURSOR(pipe)); - mutex_unlock(&dev->struct_mutex); - - old_width = intel_crtc->cursor_width; - - intel_crtc->cursor_addr = addr; - intel_crtc->cursor_bo = obj; - intel_crtc->cursor_width = width; - intel_crtc->cursor_height = height; - - if (intel_crtc->active) { - if (old_width != width) - intel_update_watermarks(crtc); - intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL); - - intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_CURSOR(pipe)); - } - - return 0; -fail_unpin: - i915_gem_object_unpin_from_display_plane(obj); -fail_locked: - mutex_unlock(&dev->struct_mutex); - return ret; -} - static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, uint32_t start, uint32_t size) { @@ -12129,7 +12026,8 @@ intel_cursor_plane_disable(struct drm_plane *plane) BUG_ON(!plane->crtc); - return intel_crtc_cursor_set_obj(plane->crtc, NULL, 0, 0); + return plane->funcs->update_plane(plane, plane->crtc, NULL, + 0, 0, 0, 0, 0, 0, 0, 0); } static int @@ -12193,12 +12091,15 @@ intel_commit_cursor_plane(struct drm_plane *plane, struct intel_plane_state *state) { struct drm_crtc *crtc = state->crtc; - struct drm_framebuffer *fb = state->fb; + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_plane *intel_plane = to_intel_plane(plane); - struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); - struct drm_i915_gem_object *obj = intel_fb->obj; - int crtc_w, crtc_h; + struct drm_i915_gem_object *obj = intel_fb_obj(state->fb); + enum pipe pipe = intel_crtc->pipe; + unsigned old_width; + uint32_t addr; + int ret; crtc->cursor_x = state->orig_dst.x1; crtc->cursor_y = state->orig_dst.y1; @@ -12213,18 +12114,100 @@ intel_commit_cursor_plane(struct drm_plane *plane, intel_plane->src_h = drm_rect_height(&state->orig_src); intel_plane->obj = obj; - if (fb != crtc->cursor->fb) { - crtc_w = drm_rect_width(&state->orig_dst); - crtc_h = drm_rect_height(&state->orig_dst); - return intel_crtc_cursor_set_obj(crtc, obj, crtc_w, crtc_h); + if (intel_crtc->cursor_bo == obj) + goto update; + + /* if we want to turn off the cursor ignore width and height */ + if (!obj) { + DRM_DEBUG_KMS("cursor off\n"); + addr = 0; + mutex_lock(&dev->struct_mutex); + goto finish; + } + + /* we only need to pin inside GTT if cursor is non-phy */ + mutex_lock(&dev->struct_mutex); + if (!INTEL_INFO(dev)->cursor_needs_physical) { + unsigned alignment; + + /* + * Global gtt pte registers are special registers which actually + * forward writes to a chunk of system memory. Which means that + * there is no risk that the register values disappear as soon + * as we call intel_runtime_pm_put(), so it is correct to wrap + * only the pin/unpin/fence and not more. + */ + intel_runtime_pm_get(dev_priv); + + /* Note that the w/a also requires 2 PTE of padding following + * the bo. We currently fill all unused PTE with the shadow + * page and so we should always have valid PTE following the + * cursor preventing the VT-d warning. + */ + alignment = 0; + if (need_vtd_wa(dev)) + alignment = 64*1024; + + ret = i915_gem_object_pin_to_display_plane(obj, alignment, NULL); + if (ret) { + DRM_DEBUG_KMS("failed to move cursor bo into the GTT\n"); + intel_runtime_pm_put(dev_priv); + goto fail_locked; + } + + ret = i915_gem_object_put_fence(obj); + if (ret) { + DRM_DEBUG_KMS("failed to release fence for cursor"); + intel_runtime_pm_put(dev_priv); + goto fail_unpin; + } + + addr = i915_gem_obj_ggtt_offset(obj); + + intel_runtime_pm_put(dev_priv); + } else { - intel_crtc_update_cursor(crtc, state->visible); + int align = IS_I830(dev) ? 16 * 1024 : 256; + ret = i915_gem_object_attach_phys(obj, align); + if (ret) { + DRM_DEBUG_KMS("failed to attach phys object\n"); + goto fail_locked; + } + addr = obj->phys_handle->busaddr; + } - intel_frontbuffer_flip(crtc->dev, - INTEL_FRONTBUFFER_CURSOR(intel_crtc->pipe)); +finish: + if (intel_crtc->cursor_bo) { + if (!INTEL_INFO(dev)->cursor_needs_physical) + i915_gem_object_unpin_from_display_plane(intel_crtc->cursor_bo); + } - return 0; + i915_gem_track_fb(intel_crtc->cursor_bo, obj, + INTEL_FRONTBUFFER_CURSOR(pipe)); + mutex_unlock(&dev->struct_mutex); + + intel_crtc->cursor_addr = addr; + intel_crtc->cursor_bo = obj; +update: + old_width = intel_crtc->cursor_width; + + intel_crtc->cursor_width = drm_rect_width(&state->orig_dst); + intel_crtc->cursor_height = drm_rect_height(&state->orig_dst); + + if (intel_crtc->active) { + if (old_width != intel_crtc->cursor_width) + intel_update_watermarks(crtc); + intel_crtc_update_cursor(crtc, state->visible); + + intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_CURSOR(pipe)); } + + return 0; +fail_unpin: + i915_gem_object_unpin_from_display_plane(obj); +fail_locked: + mutex_unlock(&dev->struct_mutex); + return ret; } static int From 455a68086d1dfb801ad7c867d5ca0ed0e0f758b0 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Mon, 1 Dec 2014 15:40:11 -0800 Subject: [PATCH 0102/3023] drm/i915: remove intel_pipe_set_base() (v4) After some refactor intel_primary_plane_setplane() does the same as intel_pipe_set_base() so we can get rid of it and replace the calls with intel_primary_plane_setplane(). v2: take Ville's comments: - get the right arguments for update_plane() - use drm_crtc_get_hv_timing() v3 (by Matt): - Rebase to latest di-nightly codebase - Use primary->funcs->update_plane() in __intel_set_mode() - Use primary->funcs->disable_plane() in intel_crtc_disable() v4 (by Matt): - Drop redundant calls to intel_crtc_wait_for_pending_flips() before calling update_plane() (Ville) Signed-off-by: Gustavo Padovan Signed-off-by: Matt Roper Acked-and-mourned-by: Jesse Barnes Reviewed-by: Ander Conselvan de Oliveira Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 129 ++++++--------------------- 1 file changed, 28 insertions(+), 101 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3342eb7f315bb7..76896e8c09ee28 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2954,71 +2954,6 @@ static void intel_update_pipe_size(struct intel_crtc *crtc) crtc->config.pipe_src_h = adjusted_mode->crtc_vdisplay; } -static int -intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, - struct drm_framebuffer *fb) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe; - struct drm_framebuffer *old_fb = crtc->primary->fb; - struct drm_i915_gem_object *old_obj = intel_fb_obj(old_fb); - int ret; - - if (intel_crtc_has_pending_flip(crtc)) { - DRM_ERROR("pipe is still busy with an old pageflip\n"); - return -EBUSY; - } - - /* no fb bound */ - if (!fb) { - DRM_ERROR("No FB bound\n"); - return 0; - } - - if (intel_crtc->plane > INTEL_INFO(dev)->num_pipes) { - DRM_ERROR("no plane for crtc: plane %c, num_pipes %d\n", - plane_name(intel_crtc->plane), - INTEL_INFO(dev)->num_pipes); - return -EINVAL; - } - - mutex_lock(&dev->struct_mutex); - ret = intel_pin_and_fence_fb_obj(crtc->primary, fb, NULL); - if (ret == 0) - i915_gem_track_fb(old_obj, intel_fb_obj(fb), - INTEL_FRONTBUFFER_PRIMARY(pipe)); - mutex_unlock(&dev->struct_mutex); - if (ret != 0) { - DRM_ERROR("pin & fence failed\n"); - return ret; - } - - dev_priv->display.update_primary_plane(crtc, fb, x, y); - - if (intel_crtc->active) - intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_PRIMARY(pipe)); - - crtc->primary->fb = fb; - crtc->x = x; - crtc->y = y; - - if (old_fb) { - if (intel_crtc->active && old_fb != fb) - intel_wait_for_vblank(dev, intel_crtc->pipe); - mutex_lock(&dev->struct_mutex); - intel_unpin_fb_obj(old_obj); - mutex_unlock(&dev->struct_mutex); - } - - mutex_lock(&dev->struct_mutex); - intel_update_fbc(dev); - mutex_unlock(&dev->struct_mutex); - - return 0; -} - static void intel_fdi_normal_train(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -5312,8 +5247,6 @@ static void intel_crtc_disable(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct drm_connector *connector; struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_object *old_obj = intel_fb_obj(crtc->primary->fb); - enum pipe pipe = to_intel_crtc(crtc)->pipe; /* crtc should still be enabled when we disable it. */ WARN_ON(!crtc->enabled); @@ -5321,14 +5254,7 @@ static void intel_crtc_disable(struct drm_crtc *crtc) dev_priv->display.crtc_disable(crtc); dev_priv->display.off(crtc); - if (crtc->primary->fb) { - mutex_lock(&dev->struct_mutex); - intel_unpin_fb_obj(old_obj); - i915_gem_track_fb(old_obj, NULL, - INTEL_FRONTBUFFER_PRIMARY(pipe)); - mutex_unlock(&dev->struct_mutex); - crtc->primary->fb = NULL; - } + crtc->primary->funcs->disable_plane(crtc->primary); /* Update computed state. */ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { @@ -9691,6 +9617,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *old_fb = crtc->primary->fb; struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct drm_plane *primary = crtc->primary; + struct intel_plane *intel_plane = to_intel_plane(primary); enum pipe pipe = intel_crtc->pipe; struct intel_unpin_work *work; struct intel_engine_cs *ring; @@ -9849,8 +9777,15 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, if (ret == -EIO) { out_hang: - intel_crtc_wait_for_pending_flips(crtc); - ret = intel_pipe_set_base(crtc, crtc->x, crtc->y, fb); + ret = primary->funcs->update_plane(primary, crtc, fb, + intel_plane->crtc_x, + intel_plane->crtc_y, + intel_plane->crtc_h, + intel_plane->crtc_w, + intel_plane->src_x, + intel_plane->src_y, + intel_plane->src_h, + intel_plane->src_w); if (ret == 0 && event) { spin_lock_irq(&dev->event_lock); drm_send_vblank_event(dev, pipe, event); @@ -11079,26 +11014,15 @@ static int __intel_set_mode(struct drm_crtc *crtc, * on the DPLL. */ for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) { - struct drm_framebuffer *old_fb = crtc->primary->fb; - struct drm_i915_gem_object *old_obj = intel_fb_obj(old_fb); - struct drm_i915_gem_object *obj = intel_fb_obj(fb); + struct drm_plane *primary = intel_crtc->base.primary; + int vdisplay, hdisplay; - mutex_lock(&dev->struct_mutex); - ret = intel_pin_and_fence_fb_obj(crtc->primary, fb, NULL); - if (ret != 0) { - DRM_ERROR("pin & fence failed\n"); - mutex_unlock(&dev->struct_mutex); - goto done; - } - if (old_fb) - intel_unpin_fb_obj(old_obj); - i915_gem_track_fb(old_obj, obj, - INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe)); - mutex_unlock(&dev->struct_mutex); - - crtc->primary->fb = fb; - crtc->x = x; - crtc->y = y; + drm_crtc_get_hv_timing(mode, &hdisplay, &vdisplay); + ret = primary->funcs->update_plane(primary, &intel_crtc->base, + fb, 0, 0, + hdisplay, vdisplay, + x << 16, y << 16, + hdisplay << 16, vdisplay << 16); } /* Now enable the clocks, plane, pipe, and connectors that we set up. */ @@ -11564,11 +11488,14 @@ static int intel_crtc_set_config(struct drm_mode_set *set) disable_pipes); } else if (config->fb_changed) { struct intel_crtc *intel_crtc = to_intel_crtc(set->crtc); - - intel_crtc_wait_for_pending_flips(set->crtc); - - ret = intel_pipe_set_base(set->crtc, - set->x, set->y, set->fb); + struct drm_plane *primary = set->crtc->primary; + int vdisplay, hdisplay; + + drm_crtc_get_hv_timing(set->mode, &hdisplay, &vdisplay); + ret = primary->funcs->update_plane(primary, set->crtc, set->fb, + 0, 0, hdisplay, vdisplay, + set->x << 16, set->y << 16, + hdisplay << 16, vdisplay << 16); /* * We need to make sure the primary plane is re-enabled if it From f4a2cf295d07b1fba9fc3599c1579681132b658a Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Mon, 1 Dec 2014 15:40:12 -0800 Subject: [PATCH 0103/3023] drm/i915: Introduce intel_prepare_cursor_plane() (v2) Primary and sprite planes have already been refactored to include a 'prepare' step which handles all the commit-time operations that could fail (i.e., pinning buffers and such). Refactor the cursor commit in a similar manner. For simplicity and consistency with other plane types, we also switch to using intel_pin_and_fence_fb_obj() to perform our pinning for non-physical cursors. This will allow us to more easily migrate the code into the atomic 'begin' handler in a plane-agnostic manner in a future patchset. v2: - Update GEM fb tracking for physical cursors too. (Ander) - Use intel_unpin_fb_obj() rather than i915_gem_object_unpin_from_display_plane() and do so while holding struct_mutex. (Ander) - Update plane->fb in commit_cursor_plane. This isn't really necessary since the DRM core does this for us in __setplane_internal(), but doing it in our driver once we know we're going to succeed helps avoid confusion. (Ander) Signed-off-by: Matt Roper Reviewed-by: Ander Conselvan de Oliveira Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 124 +++++++++++---------------- 1 file changed, 52 insertions(+), 72 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 76896e8c09ee28..78c0e1c10c441b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12014,20 +12014,55 @@ intel_check_cursor_plane(struct drm_plane *plane, } static int +intel_prepare_cursor_plane(struct drm_plane *plane, + struct intel_plane_state *state) +{ + struct drm_device *dev = plane->dev; + struct drm_framebuffer *fb = state->fb; + struct intel_crtc *intel_crtc = to_intel_crtc(state->crtc); + struct drm_i915_gem_object *obj = intel_fb_obj(fb); + struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb); + enum pipe pipe = intel_crtc->pipe; + int ret = 0; + + if (old_obj != obj) { + /* we only need to pin inside GTT if cursor is non-phy */ + mutex_lock(&dev->struct_mutex); + if (!INTEL_INFO(dev)->cursor_needs_physical) { + if (obj) + ret = intel_pin_and_fence_fb_obj(plane, fb, NULL); + } else { + int align = IS_I830(dev) ? 16 * 1024 : 256; + if (obj) + ret = i915_gem_object_attach_phys(obj, align); + if (ret) + DRM_DEBUG_KMS("failed to attach phys object\n"); + } + + if (ret == 0) + i915_gem_track_fb(intel_crtc->cursor_bo, obj, + INTEL_FRONTBUFFER_CURSOR(pipe)); + + mutex_unlock(&dev->struct_mutex); + } + + return ret; +} + +static void intel_commit_cursor_plane(struct drm_plane *plane, struct intel_plane_state *state) { struct drm_crtc *crtc = state->crtc; struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_plane *intel_plane = to_intel_plane(plane); struct drm_i915_gem_object *obj = intel_fb_obj(state->fb); enum pipe pipe = intel_crtc->pipe; unsigned old_width; uint32_t addr; - int ret; + plane->fb = state->fb; crtc->cursor_x = state->orig_dst.x1; crtc->cursor_y = state->orig_dst.y1; @@ -12044,75 +12079,21 @@ intel_commit_cursor_plane(struct drm_plane *plane, if (intel_crtc->cursor_bo == obj) goto update; - /* if we want to turn off the cursor ignore width and height */ - if (!obj) { - DRM_DEBUG_KMS("cursor off\n"); + if (!obj) addr = 0; - mutex_lock(&dev->struct_mutex); - goto finish; - } - - /* we only need to pin inside GTT if cursor is non-phy */ - mutex_lock(&dev->struct_mutex); - if (!INTEL_INFO(dev)->cursor_needs_physical) { - unsigned alignment; - - /* - * Global gtt pte registers are special registers which actually - * forward writes to a chunk of system memory. Which means that - * there is no risk that the register values disappear as soon - * as we call intel_runtime_pm_put(), so it is correct to wrap - * only the pin/unpin/fence and not more. - */ - intel_runtime_pm_get(dev_priv); - - /* Note that the w/a also requires 2 PTE of padding following - * the bo. We currently fill all unused PTE with the shadow - * page and so we should always have valid PTE following the - * cursor preventing the VT-d warning. - */ - alignment = 0; - if (need_vtd_wa(dev)) - alignment = 64*1024; - - ret = i915_gem_object_pin_to_display_plane(obj, alignment, NULL); - if (ret) { - DRM_DEBUG_KMS("failed to move cursor bo into the GTT\n"); - intel_runtime_pm_put(dev_priv); - goto fail_locked; - } - - ret = i915_gem_object_put_fence(obj); - if (ret) { - DRM_DEBUG_KMS("failed to release fence for cursor"); - intel_runtime_pm_put(dev_priv); - goto fail_unpin; - } - + else if (!INTEL_INFO(dev)->cursor_needs_physical) addr = i915_gem_obj_ggtt_offset(obj); - - intel_runtime_pm_put(dev_priv); - - } else { - int align = IS_I830(dev) ? 16 * 1024 : 256; - ret = i915_gem_object_attach_phys(obj, align); - if (ret) { - DRM_DEBUG_KMS("failed to attach phys object\n"); - goto fail_locked; - } + else addr = obj->phys_handle->busaddr; - } -finish: if (intel_crtc->cursor_bo) { - if (!INTEL_INFO(dev)->cursor_needs_physical) - i915_gem_object_unpin_from_display_plane(intel_crtc->cursor_bo); + if (!INTEL_INFO(dev)->cursor_needs_physical) { + mutex_lock(&dev->struct_mutex); + intel_unpin_fb_obj(intel_crtc->cursor_bo); + mutex_unlock(&dev->struct_mutex); + } } - i915_gem_track_fb(intel_crtc->cursor_bo, obj, - INTEL_FRONTBUFFER_CURSOR(pipe)); - mutex_unlock(&dev->struct_mutex); - intel_crtc->cursor_addr = addr; intel_crtc->cursor_bo = obj; update: @@ -12128,13 +12109,6 @@ intel_commit_cursor_plane(struct drm_plane *plane, intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_CURSOR(pipe)); } - - return 0; -fail_unpin: - i915_gem_object_unpin_from_display_plane(obj); -fail_locked: - mutex_unlock(&dev->struct_mutex); - return ret; } static int @@ -12175,7 +12149,13 @@ intel_cursor_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, if (ret) return ret; - return intel_commit_cursor_plane(plane, &state); + ret = intel_prepare_cursor_plane(plane, &state); + if (ret) + return ret; + + intel_commit_cursor_plane(plane, &state); + + return 0; } static const struct drm_plane_funcs intel_cursor_plane_funcs = { From 2b875c22fa77dfc895d3cf8287a553813d3e64c8 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Mon, 1 Dec 2014 15:40:13 -0800 Subject: [PATCH 0104/3023] drm/i915: Make intel_plane_state subclass drm_plane_state Reviewed-by: Bob Paauwe Signed-off-by: Matt Roper Reviewed-by: Ander Conselvan de Oliveira Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 36 ++++++++++++++-------------- drivers/gpu/drm/i915/intel_drv.h | 3 +-- drivers/gpu/drm/i915/intel_sprite.c | 16 ++++++------- 3 files changed, 27 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 78c0e1c10c441b..de6768f3846657 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11693,8 +11693,8 @@ static int intel_check_primary_plane(struct drm_plane *plane, struct intel_plane_state *state) { - struct drm_crtc *crtc = state->crtc; - struct drm_framebuffer *fb = state->fb; + struct drm_crtc *crtc = state->base.crtc; + struct drm_framebuffer *fb = state->base.fb; struct drm_rect *dest = &state->dst; struct drm_rect *src = &state->src; const struct drm_rect *clip = &state->clip; @@ -11710,8 +11710,8 @@ static int intel_prepare_primary_plane(struct drm_plane *plane, struct intel_plane_state *state) { - struct drm_crtc *crtc = state->crtc; - struct drm_framebuffer *fb = state->fb; + struct drm_crtc *crtc = state->base.crtc; + struct drm_framebuffer *fb = state->base.fb; struct drm_device *dev = crtc->dev; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum pipe pipe = intel_crtc->pipe; @@ -11746,9 +11746,9 @@ static void intel_commit_primary_plane(struct drm_plane *plane, struct intel_plane_state *state) { - struct drm_crtc *crtc = state->crtc; - struct drm_framebuffer *fb = state->fb; - struct drm_device *dev = crtc->dev; + struct drm_crtc *crtc = state->base.crtc; + struct drm_framebuffer *fb = state->base.fb; + struct drm_device *dev = plane->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum pipe pipe = intel_crtc->pipe; @@ -11847,8 +11847,8 @@ intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int ret; - state.crtc = crtc; - state.fb = fb; + state.base.crtc = crtc; + state.base.fb = fb; /* sample coordinates in 16.16 fixed point */ state.src.x1 = src_x; @@ -11961,9 +11961,9 @@ static int intel_check_cursor_plane(struct drm_plane *plane, struct intel_plane_state *state) { - struct drm_crtc *crtc = state->crtc; + struct drm_crtc *crtc = state->base.crtc; struct drm_device *dev = crtc->dev; - struct drm_framebuffer *fb = state->fb; + struct drm_framebuffer *fb = state->base.fb; struct drm_rect *dest = &state->dst; struct drm_rect *src = &state->src; const struct drm_rect *clip = &state->clip; @@ -12018,8 +12018,8 @@ intel_prepare_cursor_plane(struct drm_plane *plane, struct intel_plane_state *state) { struct drm_device *dev = plane->dev; - struct drm_framebuffer *fb = state->fb; - struct intel_crtc *intel_crtc = to_intel_crtc(state->crtc); + struct drm_framebuffer *fb = state->base.fb; + struct intel_crtc *intel_crtc = to_intel_crtc(state->base.crtc); struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb); enum pipe pipe = intel_crtc->pipe; @@ -12053,16 +12053,16 @@ static void intel_commit_cursor_plane(struct drm_plane *plane, struct intel_plane_state *state) { - struct drm_crtc *crtc = state->crtc; + struct drm_crtc *crtc = state->base.crtc; struct drm_device *dev = crtc->dev; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_plane *intel_plane = to_intel_plane(plane); - struct drm_i915_gem_object *obj = intel_fb_obj(state->fb); + struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb); enum pipe pipe = intel_crtc->pipe; unsigned old_width; uint32_t addr; - plane->fb = state->fb; + plane->fb = state->base.fb; crtc->cursor_x = state->orig_dst.x1; crtc->cursor_y = state->orig_dst.y1; @@ -12122,8 +12122,8 @@ intel_cursor_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, struct intel_plane_state state; int ret; - state.crtc = crtc; - state.fb = fb; + state.base.crtc = crtc; + state.base.fb = fb; /* sample coordinates in 16.16 fixed point */ state.src.x1 = src_x; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index abb2cf4162b202..b4d181fd94125b 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -244,8 +244,7 @@ typedef struct dpll { } intel_clock_t; struct intel_plane_state { - struct drm_crtc *crtc; - struct drm_framebuffer *fb; + struct drm_plane_state base; struct drm_rect src; struct drm_rect dst; struct drm_rect clip; diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 7d9c340f7693a8..fc96d1326310e8 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1096,9 +1096,9 @@ static int intel_check_sprite_plane(struct drm_plane *plane, struct intel_plane_state *state) { - struct intel_crtc *intel_crtc = to_intel_crtc(state->crtc); + struct intel_crtc *intel_crtc = to_intel_crtc(state->base.crtc); struct intel_plane *intel_plane = to_intel_plane(plane); - struct drm_framebuffer *fb = state->fb; + struct drm_framebuffer *fb = state->base.fb; struct drm_i915_gem_object *obj = intel_fb_obj(fb); int crtc_x, crtc_y; unsigned int crtc_w, crtc_h; @@ -1262,11 +1262,11 @@ intel_prepare_sprite_plane(struct drm_plane *plane, struct intel_plane_state *state) { struct drm_device *dev = plane->dev; - struct drm_crtc *crtc = state->crtc; + struct drm_crtc *crtc = state->base.crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_plane *intel_plane = to_intel_plane(plane); enum pipe pipe = intel_crtc->pipe; - struct drm_framebuffer *fb = state->fb; + struct drm_framebuffer *fb = state->base.fb; struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct drm_i915_gem_object *old_obj = intel_plane->obj; int ret; @@ -1297,11 +1297,11 @@ intel_commit_sprite_plane(struct drm_plane *plane, struct intel_plane_state *state) { struct drm_device *dev = plane->dev; - struct drm_crtc *crtc = state->crtc; + struct drm_crtc *crtc = state->base.crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_plane *intel_plane = to_intel_plane(plane); enum pipe pipe = intel_crtc->pipe; - struct drm_framebuffer *fb = state->fb; + struct drm_framebuffer *fb = state->base.fb; struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct drm_i915_gem_object *old_obj = intel_plane->obj; int crtc_x, crtc_y; @@ -1391,8 +1391,8 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int ret; - state.crtc = crtc; - state.fb = fb; + state.base.crtc = crtc; + state.base.fb = fb; /* sample coordinates in 16.16 fixed point */ state.src.x1 = src_x; From 6beb8c23ebcc3d3287d8a247d11b73d7d0eaa475 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Mon, 1 Dec 2014 15:40:14 -0800 Subject: [PATCH 0105/3023] drm/i915: Consolidate plane 'prepare' functions (v2) The 'prepare' step for all types of planes are pretty similar; consolidate the three 'prepare' functions into a single function. This paves the way for future integration with the atomic plane handlers. Note that we pull the 'wait for pending flips' functionality out of the primary plane's prepare step and place it directly in the 'setplane' code. When we move to the atomic plane handlers, this code will be in the 'atomic begin' step. v2: Update GEM fb tracking for physical cursors also (Ander) Signed-off-by: Matt Roper Reviewed-by: Ander Conselvan de Oliveira Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 168 ++++++++++++++------------- drivers/gpu/drm/i915/intel_drv.h | 2 + drivers/gpu/drm/i915/intel_sprite.c | 44 +------ 3 files changed, 98 insertions(+), 116 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index de6768f3846657..262e8904769e5b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11689,6 +11689,65 @@ intel_primary_plane_disable(struct drm_plane *plane) return 0; } +/** + * intel_prepare_plane_fb - Prepare fb for usage on plane + * @plane: drm plane to prepare for + * @fb: framebuffer to prepare for presentation + * + * Prepares a framebuffer for usage on a display plane. Generally this + * involves pinning the underlying object and updating the frontbuffer tracking + * bits. Some older platforms need special physical address handling for + * cursor planes. + * + * Returns 0 on success, negative error code on failure. + */ +int +intel_prepare_plane_fb(struct drm_plane *plane, + struct drm_framebuffer *fb) +{ + struct drm_device *dev = plane->dev; + struct intel_plane *intel_plane = to_intel_plane(plane); + enum pipe pipe = intel_plane->pipe; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); + struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb); + unsigned frontbuffer_bits = 0; + int ret = 0; + + if (WARN_ON(fb == plane->fb || !obj)) + return 0; + + switch (plane->type) { + case DRM_PLANE_TYPE_PRIMARY: + frontbuffer_bits = INTEL_FRONTBUFFER_PRIMARY(pipe); + break; + case DRM_PLANE_TYPE_CURSOR: + frontbuffer_bits = INTEL_FRONTBUFFER_CURSOR(pipe); + break; + case DRM_PLANE_TYPE_OVERLAY: + frontbuffer_bits = INTEL_FRONTBUFFER_SPRITE(pipe); + break; + } + + mutex_lock(&dev->struct_mutex); + + if (plane->type == DRM_PLANE_TYPE_CURSOR && + INTEL_INFO(dev)->cursor_needs_physical) { + int align = IS_I830(dev) ? 16 * 1024 : 256; + ret = i915_gem_object_attach_phys(obj, align); + if (ret) + DRM_DEBUG_KMS("failed to attach phys object\n"); + } else { + ret = intel_pin_and_fence_fb_obj(plane, fb, NULL); + } + + if (ret == 0) + i915_gem_track_fb(old_obj, obj, frontbuffer_bits); + + mutex_unlock(&dev->struct_mutex); + + return ret; +} + static int intel_check_primary_plane(struct drm_plane *plane, struct intel_plane_state *state) @@ -11706,42 +11765,6 @@ intel_check_primary_plane(struct drm_plane *plane, false, true, &state->visible); } -static int -intel_prepare_primary_plane(struct drm_plane *plane, - struct intel_plane_state *state) -{ - struct drm_crtc *crtc = state->base.crtc; - struct drm_framebuffer *fb = state->base.fb; - struct drm_device *dev = crtc->dev; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe; - struct drm_i915_gem_object *obj = intel_fb_obj(fb); - struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb); - int ret; - - intel_crtc_wait_for_pending_flips(crtc); - - if (intel_crtc_has_pending_flip(crtc)) { - DRM_ERROR("pipe is still busy with an old pageflip\n"); - return -EBUSY; - } - - if (old_obj != obj) { - mutex_lock(&dev->struct_mutex); - ret = intel_pin_and_fence_fb_obj(plane, fb, NULL); - if (ret == 0) - i915_gem_track_fb(old_obj, obj, - INTEL_FRONTBUFFER_PRIMARY(pipe)); - mutex_unlock(&dev->struct_mutex); - if (ret != 0) { - DRM_DEBUG_KMS("pin & fence failed\n"); - return ret; - } - } - - return 0; -} - static void intel_commit_primary_plane(struct drm_plane *plane, struct intel_plane_state *state) @@ -11843,6 +11866,7 @@ intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) { + struct drm_framebuffer *old_fb = plane->fb; struct intel_plane_state state; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int ret; @@ -11874,9 +11898,18 @@ intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc, if (ret) return ret; - ret = intel_prepare_primary_plane(plane, &state); - if (ret) - return ret; + intel_crtc_wait_for_pending_flips(crtc); + + if (intel_crtc_has_pending_flip(crtc)) { + DRM_ERROR("pipe is still busy with an old pageflip\n"); + return -EBUSY; + } + + if (fb != old_fb && fb) { + ret = intel_prepare_plane_fb(plane, fb); + if (ret) + return ret; + } intel_commit_primary_plane(plane, &state); @@ -12013,42 +12046,6 @@ intel_check_cursor_plane(struct drm_plane *plane, return ret; } -static int -intel_prepare_cursor_plane(struct drm_plane *plane, - struct intel_plane_state *state) -{ - struct drm_device *dev = plane->dev; - struct drm_framebuffer *fb = state->base.fb; - struct intel_crtc *intel_crtc = to_intel_crtc(state->base.crtc); - struct drm_i915_gem_object *obj = intel_fb_obj(fb); - struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb); - enum pipe pipe = intel_crtc->pipe; - int ret = 0; - - if (old_obj != obj) { - /* we only need to pin inside GTT if cursor is non-phy */ - mutex_lock(&dev->struct_mutex); - if (!INTEL_INFO(dev)->cursor_needs_physical) { - if (obj) - ret = intel_pin_and_fence_fb_obj(plane, fb, NULL); - } else { - int align = IS_I830(dev) ? 16 * 1024 : 256; - if (obj) - ret = i915_gem_object_attach_phys(obj, align); - if (ret) - DRM_DEBUG_KMS("failed to attach phys object\n"); - } - - if (ret == 0) - i915_gem_track_fb(intel_crtc->cursor_bo, obj, - INTEL_FRONTBUFFER_CURSOR(pipe)); - - mutex_unlock(&dev->struct_mutex); - } - - return ret; -} - static void intel_commit_cursor_plane(struct drm_plane *plane, struct intel_plane_state *state) @@ -12058,6 +12055,7 @@ intel_commit_cursor_plane(struct drm_plane *plane, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_plane *intel_plane = to_intel_plane(plane); struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb); + struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb); enum pipe pipe = intel_crtc->pipe; unsigned old_width; uint32_t addr; @@ -12079,6 +12077,17 @@ intel_commit_cursor_plane(struct drm_plane *plane, if (intel_crtc->cursor_bo == obj) goto update; + /* + * 'prepare' is only called when fb != NULL; we still need to update + * frontbuffer tracking for the 'disable' case here. + */ + if (!obj) { + mutex_lock(&dev->struct_mutex); + i915_gem_track_fb(old_obj, NULL, + INTEL_FRONTBUFFER_CURSOR(pipe)); + mutex_unlock(&dev->struct_mutex); + } + if (!obj) addr = 0; else if (!INTEL_INFO(dev)->cursor_needs_physical) @@ -12118,6 +12127,7 @@ intel_cursor_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) { + struct drm_framebuffer *old_fb = plane->fb; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_plane_state state; int ret; @@ -12149,9 +12159,11 @@ intel_cursor_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, if (ret) return ret; - ret = intel_prepare_cursor_plane(plane, &state); - if (ret) - return ret; + if (fb != old_fb && fb) { + ret = intel_prepare_plane_fb(plane, fb); + if (ret) + return ret; + } intel_commit_cursor_plane(plane, &state); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index b4d181fd94125b..a36f696e23519a 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -922,6 +922,8 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane); void intel_finish_page_flip(struct drm_device *dev, int pipe); void intel_finish_page_flip_plane(struct drm_device *dev, int plane); void intel_check_page_flip(struct drm_device *dev, int pipe); +int intel_prepare_plane_fb(struct drm_plane *plane, + struct drm_framebuffer *fb); /* shared dpll functions */ struct intel_shared_dpll *intel_crtc_to_shared_dpll(struct intel_crtc *crtc); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index fc96d1326310e8..5d8c2e07f986e7 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1257,41 +1257,6 @@ intel_check_sprite_plane(struct drm_plane *plane, return 0; } -static int -intel_prepare_sprite_plane(struct drm_plane *plane, - struct intel_plane_state *state) -{ - struct drm_device *dev = plane->dev; - struct drm_crtc *crtc = state->base.crtc; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_plane *intel_plane = to_intel_plane(plane); - enum pipe pipe = intel_crtc->pipe; - struct drm_framebuffer *fb = state->base.fb; - struct drm_i915_gem_object *obj = intel_fb_obj(fb); - struct drm_i915_gem_object *old_obj = intel_plane->obj; - int ret; - - if (old_obj != obj) { - mutex_lock(&dev->struct_mutex); - - /* Note that this will apply the VT-d workaround for scanouts, - * which is more restrictive than required for sprites. (The - * primary plane requires 256KiB alignment with 64 PTE padding, - * the sprite planes only require 128KiB alignment and 32 PTE - * padding. - */ - ret = intel_pin_and_fence_fb_obj(plane, fb, NULL); - if (ret == 0) - i915_gem_track_fb(old_obj, obj, - INTEL_FRONTBUFFER_SPRITE(pipe)); - mutex_unlock(&dev->struct_mutex); - if (ret) - return ret; - } - - return 0; -} - static void intel_commit_sprite_plane(struct drm_plane *plane, struct intel_plane_state *state) @@ -1387,6 +1352,7 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) { + struct drm_framebuffer *old_fb = plane->fb; struct intel_plane_state state; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int ret; @@ -1417,9 +1383,11 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, if (ret) return ret; - ret = intel_prepare_sprite_plane(plane, &state); - if (ret) - return ret; + if (fb != old_fb && fb) { + ret = intel_prepare_plane_fb(plane, fb); + if (ret) + return ret; + } intel_commit_sprite_plane(plane, &state); return 0; From 38f3ce3af5742eb5a3e9b01997f5ab85109c5762 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 2 Dec 2014 07:45:25 -0800 Subject: [PATCH 0106/3023] drm/i915: Consolidate plane 'cleanup' operations (v3) All plane update functions need to unpin the old framebuffer when flipping to a new one. Pull this logic into a separate function to ease the integration with atomic plane helpers. v2: Don't wait for vblank if we don't have an old fb to cleanup (Ander) v3: Really don't wait for vblank if we don't have an old fb to cleanup. Previous version only handled this for primary planes; we need the same change on cursors/sprites too! (Ander) Signed-off-by: Matt Roper Reviewed-by: Ander Conselvan de Oliveira Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 58 +++++++++++++++++++--------- drivers/gpu/drm/i915/intel_drv.h | 2 + drivers/gpu/drm/i915/intel_sprite.c | 26 ++++--------- 3 files changed, 49 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 262e8904769e5b..0488700b10f75d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11748,6 +11748,31 @@ intel_prepare_plane_fb(struct drm_plane *plane, return ret; } +/** + * intel_cleanup_plane_fb - Cleans up an fb after plane use + * @plane: drm plane to clean up for + * @fb: old framebuffer that was on plane + * + * Cleans up a framebuffer that has just been removed from a plane. + */ +void +intel_cleanup_plane_fb(struct drm_plane *plane, + struct drm_framebuffer *fb) +{ + struct drm_device *dev = plane->dev; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); + + if (WARN_ON(!obj)) + return; + + if (plane->type != DRM_PLANE_TYPE_CURSOR || + !INTEL_INFO(dev)->cursor_needs_physical) { + mutex_lock(&dev->struct_mutex); + intel_unpin_fb_obj(obj); + mutex_unlock(&dev->struct_mutex); + } +} + static int intel_check_primary_plane(struct drm_plane *plane, struct intel_plane_state *state) @@ -11775,9 +11800,7 @@ intel_commit_primary_plane(struct drm_plane *plane, struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum pipe pipe = intel_crtc->pipe; - struct drm_framebuffer *old_fb = plane->fb; struct drm_i915_gem_object *obj = intel_fb_obj(fb); - struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb); struct intel_plane *intel_plane = to_intel_plane(plane); struct drm_rect *src = &state->src; @@ -11848,15 +11871,6 @@ intel_commit_primary_plane(struct drm_plane *plane, intel_update_fbc(dev); mutex_unlock(&dev->struct_mutex); } - - if (old_fb && old_fb != fb) { - if (intel_crtc->active) - intel_wait_for_vblank(dev, intel_crtc->pipe); - - mutex_lock(&dev->struct_mutex); - intel_unpin_fb_obj(old_obj); - mutex_unlock(&dev->struct_mutex); - } } static int @@ -11866,6 +11880,7 @@ intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) { + struct drm_device *dev = plane->dev; struct drm_framebuffer *old_fb = plane->fb; struct intel_plane_state state; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -11913,6 +11928,12 @@ intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc, intel_commit_primary_plane(plane, &state); + if (fb != old_fb && old_fb) { + if (intel_crtc->active) + intel_wait_for_vblank(dev, intel_crtc->pipe); + intel_cleanup_plane_fb(plane, old_fb); + } + return 0; } @@ -12095,14 +12116,6 @@ intel_commit_cursor_plane(struct drm_plane *plane, else addr = obj->phys_handle->busaddr; - if (intel_crtc->cursor_bo) { - if (!INTEL_INFO(dev)->cursor_needs_physical) { - mutex_lock(&dev->struct_mutex); - intel_unpin_fb_obj(intel_crtc->cursor_bo); - mutex_unlock(&dev->struct_mutex); - } - } - intel_crtc->cursor_addr = addr; intel_crtc->cursor_bo = obj; update: @@ -12127,6 +12140,7 @@ intel_cursor_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) { + struct drm_device *dev = plane->dev; struct drm_framebuffer *old_fb = plane->fb; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_plane_state state; @@ -12167,6 +12181,12 @@ intel_cursor_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, intel_commit_cursor_plane(plane, &state); + if (fb != old_fb && old_fb) { + if (intel_crtc->active) + intel_wait_for_vblank(dev, intel_crtc->pipe); + intel_cleanup_plane_fb(plane, old_fb); + } + return 0; } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a36f696e23519a..38cb5535cd391e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -924,6 +924,8 @@ void intel_finish_page_flip_plane(struct drm_device *dev, int plane); void intel_check_page_flip(struct drm_device *dev, int pipe); int intel_prepare_plane_fb(struct drm_plane *plane, struct drm_framebuffer *fb); +void intel_cleanup_plane_fb(struct drm_plane *plane, + struct drm_framebuffer *fb); /* shared dpll functions */ struct intel_shared_dpll *intel_crtc_to_shared_dpll(struct intel_crtc *crtc); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 5d8c2e07f986e7..031f95e259fb0f 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1268,7 +1268,6 @@ intel_commit_sprite_plane(struct drm_plane *plane, enum pipe pipe = intel_crtc->pipe; struct drm_framebuffer *fb = state->base.fb; struct drm_i915_gem_object *obj = intel_fb_obj(fb); - struct drm_i915_gem_object *old_obj = intel_plane->obj; int crtc_x, crtc_y; unsigned int crtc_w, crtc_h; uint32_t src_x, src_y, src_w, src_h; @@ -1326,23 +1325,6 @@ intel_commit_sprite_plane(struct drm_plane *plane, if (!primary_was_enabled && primary_enabled) intel_post_enable_primary(crtc); } - - /* Unpin old obj after new one is active to avoid ugliness */ - if (old_obj && old_obj != obj) { - - /* - * It's fairly common to simply update the position of - * an existing object. In that case, we don't need to - * wait for vblank to avoid ugliness, we only need to - * do the pin & ref bookkeeping. - */ - if (intel_crtc->active) - intel_wait_for_vblank(dev, intel_crtc->pipe); - - mutex_lock(&dev->struct_mutex); - intel_unpin_fb_obj(old_obj); - mutex_unlock(&dev->struct_mutex); - } } static int @@ -1352,6 +1334,7 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) { + struct drm_device *dev = plane->dev; struct drm_framebuffer *old_fb = plane->fb; struct intel_plane_state state; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -1390,6 +1373,13 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, } intel_commit_sprite_plane(plane, &state); + + if (fb != old_fb && old_fb) { + if (intel_crtc->active) + intel_wait_for_vblank(dev, intel_crtc->pipe); + intel_cleanup_plane_fb(plane, old_fb); + } + return 0; } From c59cb179aaf444931cf9c547a514e383da3d2526 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Mon, 1 Dec 2014 15:40:16 -0800 Subject: [PATCH 0107/3023] drm/i915: Consolidate top-level .update_plane() handlers Our .update_plane() handlers do the same check/prepare/commit/cleanup steps regardless of plane type. Consolidate them all into a single function that calls check/commit through a vtable. Signed-off-by: Matt Roper Reviewed-by: Ander Conselvan de Oliveira Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 112 ++++++++------------------- drivers/gpu/drm/i915/intel_drv.h | 9 +++ drivers/gpu/drm/i915/intel_sprite.c | 58 +------------- 3 files changed, 44 insertions(+), 135 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0488700b10f75d..f6334e6b378a09 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11782,12 +11782,23 @@ intel_check_primary_plane(struct drm_plane *plane, struct drm_rect *dest = &state->dst; struct drm_rect *src = &state->src; const struct drm_rect *clip = &state->clip; + int ret; + + ret = drm_plane_helper_check_update(plane, crtc, fb, + src, dest, clip, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + false, true, &state->visible); + if (ret) + return ret; - return drm_plane_helper_check_update(plane, crtc, fb, - src, dest, clip, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, - false, true, &state->visible); + intel_crtc_wait_for_pending_flips(crtc); + if (intel_crtc_has_pending_flip(crtc)) { + DRM_ERROR("pipe is still busy with an old pageflip\n"); + return -EBUSY; + } + + return 0; } static void @@ -11873,16 +11884,17 @@ intel_commit_primary_plane(struct drm_plane *plane, } } -static int -intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc, - struct drm_framebuffer *fb, int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h) +int +intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, + struct drm_framebuffer *fb, int crtc_x, int crtc_y, + unsigned int crtc_w, unsigned int crtc_h, + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h) { struct drm_device *dev = plane->dev; struct drm_framebuffer *old_fb = plane->fb; struct intel_plane_state state; + struct intel_plane *intel_plane = to_intel_plane(plane); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int ret; @@ -11909,24 +11921,17 @@ intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc, state.orig_src = state.src; state.orig_dst = state.dst; - ret = intel_check_primary_plane(plane, &state); + ret = intel_plane->check_plane(plane, &state); if (ret) return ret; - intel_crtc_wait_for_pending_flips(crtc); - - if (intel_crtc_has_pending_flip(crtc)) { - DRM_ERROR("pipe is still busy with an old pageflip\n"); - return -EBUSY; - } - if (fb != old_fb && fb) { ret = intel_prepare_plane_fb(plane, fb); if (ret) return ret; } - intel_commit_primary_plane(plane, &state); + intel_plane->commit_plane(plane, &state); if (fb != old_fb && old_fb) { if (intel_crtc->active) @@ -11934,6 +11939,8 @@ intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc, intel_cleanup_plane_fb(plane, old_fb); } + plane->fb = fb; + return 0; } @@ -11946,7 +11953,7 @@ static void intel_plane_destroy(struct drm_plane *plane) } static const struct drm_plane_funcs intel_primary_plane_funcs = { - .update_plane = intel_primary_plane_setplane, + .update_plane = intel_update_plane, .disable_plane = intel_primary_plane_disable, .destroy = intel_plane_destroy, .set_property = intel_plane_set_property @@ -11968,6 +11975,8 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, primary->pipe = pipe; primary->plane = pipe; primary->rotation = BIT(DRM_ROTATE_0); + primary->check_plane = intel_check_primary_plane; + primary->commit_plane = intel_commit_primary_plane; if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4) primary->plane = !pipe; @@ -12133,65 +12142,8 @@ intel_commit_cursor_plane(struct drm_plane *plane, } } -static int -intel_cursor_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, - struct drm_framebuffer *fb, int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h) -{ - struct drm_device *dev = plane->dev; - struct drm_framebuffer *old_fb = plane->fb; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_plane_state state; - int ret; - - state.base.crtc = crtc; - state.base.fb = fb; - - /* sample coordinates in 16.16 fixed point */ - state.src.x1 = src_x; - state.src.x2 = src_x + src_w; - state.src.y1 = src_y; - state.src.y2 = src_y + src_h; - - /* integer pixels */ - state.dst.x1 = crtc_x; - state.dst.x2 = crtc_x + crtc_w; - state.dst.y1 = crtc_y; - state.dst.y2 = crtc_y + crtc_h; - - state.clip.x1 = 0; - state.clip.y1 = 0; - state.clip.x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0; - state.clip.y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0; - - state.orig_src = state.src; - state.orig_dst = state.dst; - - ret = intel_check_cursor_plane(plane, &state); - if (ret) - return ret; - - if (fb != old_fb && fb) { - ret = intel_prepare_plane_fb(plane, fb); - if (ret) - return ret; - } - - intel_commit_cursor_plane(plane, &state); - - if (fb != old_fb && old_fb) { - if (intel_crtc->active) - intel_wait_for_vblank(dev, intel_crtc->pipe); - intel_cleanup_plane_fb(plane, old_fb); - } - - return 0; -} - static const struct drm_plane_funcs intel_cursor_plane_funcs = { - .update_plane = intel_cursor_plane_update, + .update_plane = intel_update_plane, .disable_plane = intel_cursor_plane_disable, .destroy = intel_plane_destroy, .set_property = intel_plane_set_property, @@ -12211,6 +12163,8 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev, cursor->pipe = pipe; cursor->plane = pipe; cursor->rotation = BIT(DRM_ROTATE_0); + cursor->check_plane = intel_check_cursor_plane; + cursor->commit_plane = intel_commit_cursor_plane; drm_universal_plane_init(dev, &cursor->base, 0, &intel_cursor_plane_funcs, diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 38cb5535cd391e..f7b661969ad090 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -508,6 +508,10 @@ struct intel_plane { uint32_t src_w, uint32_t src_h); void (*disable_plane)(struct drm_plane *plane, struct drm_crtc *crtc); + int (*check_plane)(struct drm_plane *plane, + struct intel_plane_state *state); + void (*commit_plane)(struct drm_plane *plane, + struct intel_plane_state *state); int (*update_colorkey)(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key); void (*get_colorkey)(struct drm_plane *plane, @@ -1011,6 +1015,11 @@ void intel_dp_hot_plug(struct intel_encoder *intel_encoder); void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv); uint32_t intel_dp_pack_aux(const uint8_t *src, int src_bytes); void intel_dp_unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes); +int intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, + struct drm_framebuffer *fb, int crtc_x, int crtc_y, + unsigned int crtc_w, unsigned int crtc_h, + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h); /* intel_dp_mst.c */ int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 031f95e259fb0f..bfd5270bdbd5ff 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1327,62 +1327,6 @@ intel_commit_sprite_plane(struct drm_plane *plane, } } -static int -intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, - struct drm_framebuffer *fb, int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h) -{ - struct drm_device *dev = plane->dev; - struct drm_framebuffer *old_fb = plane->fb; - struct intel_plane_state state; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int ret; - - state.base.crtc = crtc; - state.base.fb = fb; - - /* sample coordinates in 16.16 fixed point */ - state.src.x1 = src_x; - state.src.x2 = src_x + src_w; - state.src.y1 = src_y; - state.src.y2 = src_y + src_h; - - /* integer pixels */ - state.dst.x1 = crtc_x; - state.dst.x2 = crtc_x + crtc_w; - state.dst.y1 = crtc_y; - state.dst.y2 = crtc_y + crtc_h; - - state.clip.x1 = 0; - state.clip.y1 = 0; - state.clip.x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0; - state.clip.y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0; - state.orig_src = state.src; - state.orig_dst = state.dst; - - ret = intel_check_sprite_plane(plane, &state); - if (ret) - return ret; - - if (fb != old_fb && fb) { - ret = intel_prepare_plane_fb(plane, fb); - if (ret) - return ret; - } - - intel_commit_sprite_plane(plane, &state); - - if (fb != old_fb && old_fb) { - if (intel_crtc->active) - intel_wait_for_vblank(dev, intel_crtc->pipe); - intel_cleanup_plane_fb(plane, old_fb); - } - - return 0; -} - static int intel_disable_plane(struct drm_plane *plane) { @@ -1678,6 +1622,8 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) intel_plane->pipe = pipe; intel_plane->plane = plane; intel_plane->rotation = BIT(DRM_ROTATE_0); + intel_plane->check_plane = intel_check_sprite_plane; + intel_plane->commit_plane = intel_commit_sprite_plane; possible_crtcs = (1 << pipe); ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs, &intel_plane_funcs, From e614c3c946ae5b50a679d65d2c981615d8ceccab Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Mon, 1 Dec 2014 15:40:17 -0800 Subject: [PATCH 0108/3023] drm/i915: Ensure state->crtc is non-NULL for plane updates When disabling a plane, it is legal to pass crtc = NULL. Since planes on Intel hardware are tied to a fixed CRTC, go ahead and set state->crtc to the appropriate crtc in cases where it is passed to us as NULL. In a future patch, we will start using the update handler for plane disables, so this will help ensure we always have a non-NULL crtc pointer to work with. Signed-off-by: Matt Roper Reviewed-by: Ander Conselvan de Oliveira Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f6334e6b378a09..4f24cce0fe385f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11898,7 +11898,7 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int ret; - state.base.crtc = crtc; + state.base.crtc = crtc ? crtc : plane->crtc; state.base.fb = fb; /* sample coordinates in 16.16 fixed point */ From cf4c7c12258ed9367f4fc45238f5f50d2db892c1 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Thu, 4 Dec 2014 10:27:42 -0800 Subject: [PATCH 0109/3023] drm/i915: Make all plane disables use 'update_plane' (v5) If we extend the commit_plane handlers for each plane type to be able to handle fb=0, then we can easily implement plane disable via the update_plane handler. The cursor plane already works this way, and this is the direction we need to go to integrate with the atomic plane handler. We can now kill off the type-specific disable functions, as well as the redundant intel_plane_disable() (not to be confused with intel_disable_plane()). Note that prepare_plane_fb() only gets called as part of update_plane when fb!=NULL (by design, to match the semantics of the atomic plane helpers); this means that our commit_plane handlers need to handle the frontbuffer tracking for the disable case, even though they don't handle it for normal updates. v2: - Change BUG_ON to WARN_ON (Ander/Daniel) v3: - Drop unnecessary plane->crtc check since a previous patch to plane update ensures that plane->crtc will always be non-NULL, even for disable calls that might pass NULL from userspace. (Ander) - Drop a s/crtc/plane->crtc/ hunk that was unnecessary. (Ander) v4: - Fix missing whitespace (Ander) v5: - Use state's crtc rather than plane's crtc in intel_check_primary_plane(). plane->crtc could be NULL, but we've already fixed up state->crtc to ensure it's non-NULL (even if userspace passed it as NULL during a disable call). (Ander) Signed-off-by: Matt Roper Reviewed-by: Ander Conselvan de Oliveira Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 89 +++++++++++----------------- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_sprite.c | 71 ++++++---------------- 3 files changed, 54 insertions(+), 108 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 4f24cce0fe385f..c17419bb8bc09e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4060,7 +4060,7 @@ static void intel_disable_planes(struct drm_crtc *crtc) drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) { intel_plane = to_intel_plane(plane); if (intel_plane->pipe == pipe) - intel_plane_disable(&intel_plane->base); + plane->funcs->disable_plane(plane); } } @@ -11652,43 +11652,6 @@ static void intel_shared_dpll_init(struct drm_device *dev) BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS); } -static int -intel_primary_plane_disable(struct drm_plane *plane) -{ - struct drm_device *dev = plane->dev; - struct intel_crtc *intel_crtc; - - if (!plane->fb) - return 0; - - BUG_ON(!plane->crtc); - - intel_crtc = to_intel_crtc(plane->crtc); - - /* - * Even though we checked plane->fb above, it's still possible that - * the primary plane has been implicitly disabled because the crtc - * coordinates given weren't visible, or because we detected - * that it was 100% covered by a sprite plane. Or, the CRTC may be - * off and we've set a fb, but haven't actually turned on the CRTC yet. - * In either case, we need to unpin the FB and let the fb pointer get - * updated, but otherwise we don't need to touch the hardware. - */ - if (intel_crtc->primary_enabled) { - intel_crtc_wait_for_pending_flips(plane->crtc); - intel_disable_primary_hw_plane(plane, plane->crtc); - } - - mutex_lock(&dev->struct_mutex); - i915_gem_track_fb(intel_fb_obj(plane->fb), NULL, - INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe)); - intel_unpin_fb_obj(intel_fb_obj(plane->fb)); - mutex_unlock(&dev->struct_mutex); - plane->fb = NULL; - - return 0; -} - /** * intel_prepare_plane_fb - Prepare fb for usage on plane * @plane: drm plane to prepare for @@ -11810,12 +11773,23 @@ intel_commit_primary_plane(struct drm_plane *plane, struct drm_device *dev = plane->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe; struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct intel_plane *intel_plane = to_intel_plane(plane); struct drm_rect *src = &state->src; + enum pipe pipe = intel_plane->pipe; - crtc->primary->fb = fb; + if (!fb) { + /* + * 'prepare' is never called when plane is being disabled, so + * we need to handle frontbuffer tracking here + */ + mutex_lock(&dev->struct_mutex); + i915_gem_track_fb(intel_fb_obj(plane->fb), NULL, + INTEL_FRONTBUFFER_PRIMARY(pipe)); + mutex_unlock(&dev->struct_mutex); + } + + plane->fb = fb; crtc->x = src->x1 >> 16; crtc->y = src->y1 >> 16; @@ -11944,6 +11918,25 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, return 0; } +/** + * intel_disable_plane - disable a plane + * @plane: plane to disable + * + * General disable handler for all plane types. + */ +int +intel_disable_plane(struct drm_plane *plane) +{ + if (!plane->fb) + return 0; + + if (WARN_ON(!plane->crtc)) + return -EINVAL; + + return plane->funcs->update_plane(plane, plane->crtc, NULL, + 0, 0, 0, 0, 0, 0, 0, 0); +} + /* Common destruction function for both primary and cursor planes */ static void intel_plane_destroy(struct drm_plane *plane) { @@ -11954,7 +11947,7 @@ static void intel_plane_destroy(struct drm_plane *plane) static const struct drm_plane_funcs intel_primary_plane_funcs = { .update_plane = intel_update_plane, - .disable_plane = intel_primary_plane_disable, + .disable_plane = intel_disable_plane, .destroy = intel_plane_destroy, .set_property = intel_plane_set_property }; @@ -12008,18 +12001,6 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, return &primary->base; } -static int -intel_cursor_plane_disable(struct drm_plane *plane) -{ - if (!plane->fb) - return 0; - - BUG_ON(!plane->crtc); - - return plane->funcs->update_plane(plane, plane->crtc, NULL, - 0, 0, 0, 0, 0, 0, 0, 0); -} - static int intel_check_cursor_plane(struct drm_plane *plane, struct intel_plane_state *state) @@ -12144,7 +12125,7 @@ intel_commit_cursor_plane(struct drm_plane *plane, static const struct drm_plane_funcs intel_cursor_plane_funcs = { .update_plane = intel_update_plane, - .disable_plane = intel_cursor_plane_disable, + .disable_plane = intel_disable_plane, .destroy = intel_plane_destroy, .set_property = intel_plane_set_property, }; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index f7b661969ad090..53b696e841cd4e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1020,6 +1020,7 @@ int intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, unsigned int crtc_w, unsigned int crtc_h, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h); +int intel_disable_plane(struct drm_plane *plane); /* intel_dp_mst.c */ int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id); @@ -1201,7 +1202,6 @@ int intel_plane_set_property(struct drm_plane *plane, struct drm_property *prop, uint64_t val); int intel_plane_restore(struct drm_plane *plane); -void intel_plane_disable(struct drm_plane *plane); int intel_sprite_set_colorkey(struct drm_device *dev, void *data, struct drm_file *file_priv); int intel_sprite_get_colorkey(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index bfd5270bdbd5ff..bc5834bba2ae86 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1109,7 +1109,12 @@ intel_check_sprite_plane(struct drm_plane *plane, const struct drm_rect *clip = &state->clip; int hscale, vscale; int max_scale, min_scale; - int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); + int pixel_size; + + if (!fb) { + state->visible = false; + return 0; + } /* Don't modify another pipe's plane */ if (intel_plane->pipe != intel_crtc->pipe) { @@ -1232,6 +1237,7 @@ intel_check_sprite_plane(struct drm_plane *plane, if (src_w < 3 || src_h < 3) state->visible = false; + pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); width_bytes = ((src_x * pixel_size) & 63) + src_w * pixel_size; @@ -1275,6 +1281,17 @@ intel_commit_sprite_plane(struct drm_plane *plane, const struct drm_rect *clip = &state->clip; bool primary_enabled; + /* + * 'prepare' is never called when plane is being disabled, so we need + * to handle frontbuffer tracking here + */ + if (!fb) { + mutex_lock(&dev->struct_mutex); + i915_gem_track_fb(intel_fb_obj(plane->fb), NULL, + INTEL_FRONTBUFFER_SPRITE(pipe)); + mutex_unlock(&dev->struct_mutex); + } + /* * If the sprite is completely covering the primary plane, * we can disable the primary and save power. @@ -1327,50 +1344,6 @@ intel_commit_sprite_plane(struct drm_plane *plane, } } -static int -intel_disable_plane(struct drm_plane *plane) -{ - struct drm_device *dev = plane->dev; - struct intel_plane *intel_plane = to_intel_plane(plane); - struct intel_crtc *intel_crtc; - enum pipe pipe; - - if (!plane->fb) - return 0; - - if (WARN_ON(!plane->crtc)) - return -EINVAL; - - intel_crtc = to_intel_crtc(plane->crtc); - pipe = intel_crtc->pipe; - - if (intel_crtc->active) { - bool primary_was_enabled = intel_crtc->primary_enabled; - - intel_crtc->primary_enabled = true; - - intel_plane->disable_plane(plane, plane->crtc); - - if (!primary_was_enabled && intel_crtc->primary_enabled) - intel_post_enable_primary(plane->crtc); - } - - if (intel_plane->obj) { - if (intel_crtc->active) - intel_wait_for_vblank(dev, intel_plane->pipe); - - mutex_lock(&dev->struct_mutex); - intel_unpin_fb_obj(intel_plane->obj); - i915_gem_track_fb(intel_plane->obj, NULL, - INTEL_FRONTBUFFER_SPRITE(pipe)); - mutex_unlock(&dev->struct_mutex); - - intel_plane->obj = NULL; - } - - return 0; -} - static void intel_destroy_plane(struct drm_plane *plane) { struct intel_plane *intel_plane = to_intel_plane(plane); @@ -1478,14 +1451,6 @@ int intel_plane_restore(struct drm_plane *plane) intel_plane->src_w, intel_plane->src_h); } -void intel_plane_disable(struct drm_plane *plane) -{ - if (!plane->crtc || !plane->fb) - return; - - intel_disable_plane(plane); -} - static const struct drm_plane_funcs intel_plane_funcs = { .update_plane = intel_update_plane, .disable_plane = intel_disable_plane, From 146d84f0f2707bfe2c67114eeefac30da8584b3b Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 5 Dec 2014 13:49:33 +0000 Subject: [PATCH 0110/3023] drm/i915: Fix up seqno -> request merge issues The display related patches earlier in this series were edited during merge to improve the request unreferencing. Specifically, the need for de-referencing at interrupt time was removed. However, the resulting code did a 'deref(req) ; req = NULL' sequence rather than using the 'req_assign(req, NULL)' wrapper. The two are functionally equivalent, but using the wrapper is more consistent with all the other places where requests are assigned. Note that the whole point of the wrapper is that using it everywhere that request pointers are assigned means that the reference counting is done automatically and can't be accidentally forgotten about. Plus it allows simpler future maintainance if the reference counting mechanisms ever need to change. For: VIZ-4377 Signed-off-by: John Harrison Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c17419bb8bc09e..42e661e05a3248 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8953,8 +8953,7 @@ static void intel_unpin_work_fn(struct work_struct *__work) intel_update_fbc(dev); if (work->flip_queued_req) - i915_gem_request_unreference(work->flip_queued_req); - work->flip_queued_req = NULL; + i915_gem_request_assign(&work->flip_queued_req, NULL); mutex_unlock(&dev->struct_mutex); intel_frontbuffer_flip_complete(dev, INTEL_FRONTBUFFER_PRIMARY(pipe)); @@ -9452,10 +9451,9 @@ static void intel_mmio_flip_work_func(struct work_struct *work) intel_do_mmio_flip(crtc); if (mmio_flip->req) { mutex_lock(&crtc->base.dev->struct_mutex); - i915_gem_request_unreference(mmio_flip->req); + i915_gem_request_assign(&mmio_flip->req, NULL); mutex_unlock(&crtc->base.dev->struct_mutex); } - mmio_flip->req = NULL; } static int intel_queue_mmio_flip(struct drm_device *dev, From aaeb1ba041aedf2b58cd1303fd5fa9cf9173fa9b Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 5 Dec 2014 13:49:34 +0000 Subject: [PATCH 0111/3023] drm/i915: Zero fill the request structure There is a general theory that kzmalloc is better/safer than kmalloc, especially for interesting data structures. This change updates the request structure allocation to be zero filled. This also fixes crashes in the reset code. Quoting Mika's patch: "Clean the request structure on alloc. Otherwise we might end up referencing uninitialized fields. This is apparent when we try to cleanup the preallocated request on ring reset, before any request has been submitted to the ring. The request->ctx is foobar and we end up freeing the foobarness." Note that this fixes a regression introduced in commit 9eba5d4a1d79d5094321469479b4dbe418f60110 Author: John Harrison Date: Mon Nov 24 18:49:23 2014 +0000 drm/i915: Ensure OLS & PLR are always in sync References: https://bugs.freedesktop.org/show_bug.cgi?id=86959 References: https://bugs.freedesktop.org/show_bug.cgi?id=86962 References: https://bugs.freedesktop.org/show_bug.cgi?id=86992 Change-Id: I68715ef758025fab8db763941ef63bf60d7031e2 For: VIZ-4377 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel Cc: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 2 +- drivers/gpu/drm/i915/intel_ringbuffer.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 7986eb3e502737..782e97638ed8bb 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -885,7 +885,7 @@ static int logical_ring_alloc_request(struct intel_engine_cs *ring, if (ring->outstanding_lazy_request) return 0; - request = kmalloc(sizeof(*request), GFP_KERNEL); + request = kzalloc(sizeof(*request), GFP_KERNEL); if (request == NULL) return -ENOMEM; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index f52101521653a2..8828219139374a 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -2032,7 +2032,7 @@ intel_ring_alloc_request(struct intel_engine_cs *ring) if (ring->outstanding_lazy_request) return 0; - request = kmalloc(sizeof(*request), GFP_KERNEL); + request = kzalloc(sizeof(*request), GFP_KERNEL); if (request == NULL) return -ENOMEM; From 67e2937bf470718b3a7812de80c8a3dc2c2136f9 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 5 Dec 2014 13:49:35 +0000 Subject: [PATCH 0112/3023] drm/i915: Add unique id to the request structure for debugging For debugging purposes, it is useful to be able to uniquely identify a given request structure as it works its way through the system. This becomes especially tricky once the seqno value is lazily allocated as then the request has nothing but its pointer to identify it for much of its life. Change-Id: Ie76b2268b940467f4cdf5a4ba6f5a54cbb96445d For: VIZ-4377 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 4 ++++ drivers/gpu/drm/i915/intel_lrc.c | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.c | 2 ++ 3 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 502a01bef1ed65..95dfa2dd35b921 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1787,6 +1787,8 @@ struct drm_i915_private { void (*stop_ring)(struct intel_engine_cs *ring); } gt; + uint32_t request_uniq; + /* * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch * will be rejected. Instead look for a better place. @@ -2019,6 +2021,8 @@ struct drm_i915_gem_request { struct drm_i915_file_private *file_priv; /** file_priv list entry for this request */ struct list_head client_list; + + uint32_t uniq; }; void i915_gem_request_free(struct kref *req_ref); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 782e97638ed8bb..a82020ea9d0a98 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -880,6 +880,7 @@ static int logical_ring_alloc_request(struct intel_engine_cs *ring, struct intel_context *ctx) { struct drm_i915_gem_request *request; + struct drm_i915_private *dev_private = ring->dev->dev_private; int ret; if (ring->outstanding_lazy_request) @@ -899,6 +900,7 @@ static int logical_ring_alloc_request(struct intel_engine_cs *ring, kref_init(&request->ref); request->ring = ring; + request->uniq = dev_private->request_uniq++; ret = i915_gem_get_seqno(ring->dev, &request->seqno); if (ret) { diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 8828219139374a..3887f1aaf057ff 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -2028,6 +2028,7 @@ intel_ring_alloc_request(struct intel_engine_cs *ring) { int ret; struct drm_i915_gem_request *request; + struct drm_i915_private *dev_private = ring->dev->dev_private; if (ring->outstanding_lazy_request) return 0; @@ -2038,6 +2039,7 @@ intel_ring_alloc_request(struct intel_engine_cs *ring) kref_init(&request->ref); request->ring = ring; + request->uniq = dev_private->request_uniq++; ret = i915_gem_get_seqno(ring->dev, &request->seqno); if (ret) { From bcfcc8ba29c933ee98c7f498ee7ccfa17be400dd Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 5 Dec 2014 13:49:36 +0000 Subject: [PATCH 0113/3023] drm/i915: Additional request structure tracing Added the request structure's 'uniq' identifier to the trace information. Also renamed the '_complete' trace event to '_notify' as it actually happens in the IRQ 'notify_ring()' function. The intention is to add a new '_complete' trace event which occurs when a request structure is actually marked as complete. However, at the moment the completion status is re-tested every time the query is made so there isn't a completion event as such. v2: New patch added to series. v3: Rebased to remove completion caching as that is apparently contentious. Change-Id: Ic9bcde67d175c6c03b96217cdcb6e4cc4aa45d67 For: VIZ-4377 Signed-off-by: John Harrison Reviewed-by: Thomas Daniel Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 2 +- drivers/gpu/drm/i915/i915_trace.h | 22 ++++++++++++++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 7913a72ce30ac0..08a5a4ba52acd0 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1013,7 +1013,7 @@ static void notify_ring(struct drm_device *dev, if (!intel_ring_initialized(ring)) return; - trace_i915_gem_request_complete(ring); + trace_i915_gem_request_notify(ring); wake_up_all(&ring->irq_queue); } diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index 2ade958f28f835..6058a01b444334 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -406,6 +406,7 @@ DECLARE_EVENT_CLASS(i915_gem_request, TP_STRUCT__entry( __field(u32, dev) __field(u32, ring) + __field(u32, uniq) __field(u32, seqno) ), @@ -414,11 +415,13 @@ DECLARE_EVENT_CLASS(i915_gem_request, i915_gem_request_get_ring(req); __entry->dev = ring->dev->primary->index; __entry->ring = ring->id; + __entry->uniq = req ? req->uniq : 0; __entry->seqno = i915_gem_request_get_seqno(req); ), - TP_printk("dev=%u, ring=%u, seqno=%u", - __entry->dev, __entry->ring, __entry->seqno) + TP_printk("dev=%u, ring=%u, uniq=%u, seqno=%u", + __entry->dev, __entry->ring, __entry->uniq, + __entry->seqno) ); DEFINE_EVENT(i915_gem_request, i915_gem_request_add, @@ -426,7 +429,7 @@ DEFINE_EVENT(i915_gem_request, i915_gem_request_add, TP_ARGS(req) ); -TRACE_EVENT(i915_gem_request_complete, +TRACE_EVENT(i915_gem_request_notify, TP_PROTO(struct intel_engine_cs *ring), TP_ARGS(ring), @@ -451,6 +454,11 @@ DEFINE_EVENT(i915_gem_request, i915_gem_request_retire, TP_ARGS(req) ); +DEFINE_EVENT(i915_gem_request, i915_gem_request_complete, + TP_PROTO(struct drm_i915_gem_request *req), + TP_ARGS(req) +); + TRACE_EVENT(i915_gem_request_wait_begin, TP_PROTO(struct drm_i915_gem_request *req), TP_ARGS(req), @@ -458,6 +466,7 @@ TRACE_EVENT(i915_gem_request_wait_begin, TP_STRUCT__entry( __field(u32, dev) __field(u32, ring) + __field(u32, uniq) __field(u32, seqno) __field(bool, blocking) ), @@ -473,14 +482,15 @@ TRACE_EVENT(i915_gem_request_wait_begin, i915_gem_request_get_ring(req); __entry->dev = ring->dev->primary->index; __entry->ring = ring->id; + __entry->uniq = req ? req->uniq : 0; __entry->seqno = i915_gem_request_get_seqno(req); __entry->blocking = mutex_is_locked(&ring->dev->struct_mutex); ), - TP_printk("dev=%u, ring=%u, seqno=%u, blocking=%s", - __entry->dev, __entry->ring, __entry->seqno, - __entry->blocking ? "yes (NB)" : "no") + TP_printk("dev=%u, ring=%u, uniq=%u, seqno=%u, blocking=%s", + __entry->dev, __entry->ring, __entry->uniq, + __entry->seqno, __entry->blocking ? "yes (NB)" : "no") ); DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_end, From b05ddd4dfb6303ee9dde359ec913aa7a918fd813 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 7 Dec 2014 19:29:17 +0100 Subject: [PATCH 0114/3023] gpu: drm: i915: intel_display.c: Remove unused function Remove the function intel_output_name() that is not used anywhere. This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 22 ---------------------- drivers/gpu/drm/i915/intel_drv.h | 1 - 2 files changed, 23 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 42e661e05a3248..d5153a4f90fec4 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12302,28 +12302,6 @@ static bool has_edp_a(struct drm_device *dev) return true; } -const char *intel_output_name(int output) -{ - static const char *names[] = { - [INTEL_OUTPUT_UNUSED] = "Unused", - [INTEL_OUTPUT_ANALOG] = "Analog", - [INTEL_OUTPUT_DVO] = "DVO", - [INTEL_OUTPUT_SDVO] = "SDVO", - [INTEL_OUTPUT_LVDS] = "LVDS", - [INTEL_OUTPUT_TVOUT] = "TV", - [INTEL_OUTPUT_HDMI] = "HDMI", - [INTEL_OUTPUT_DISPLAYPORT] = "DisplayPort", - [INTEL_OUTPUT_EDP] = "eDP", - [INTEL_OUTPUT_DSI] = "DSI", - [INTEL_OUTPUT_UNKNOWN] = "Unknown", - }; - - if (output < 0 || output >= ARRAY_SIZE(names) || !names[output]) - return "Invalid"; - - return names[output]; -} - static bool intel_crt_present(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 53b696e841cd4e..61a88fa6997831 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -875,7 +875,6 @@ void intel_audio_codec_enable(struct intel_encoder *encoder); void intel_audio_codec_disable(struct intel_encoder *encoder); /* intel_display.c */ -const char *intel_output_name(int output); bool intel_has_pending_fb_unpin(struct drm_device *dev); int intel_pch_rawclk(struct drm_device *dev); void intel_mark_busy(struct drm_device *dev); From 8f0e2b9d95a88ca5d8349deef2375644faf184ae Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 2 Dec 2014 16:19:07 +0100 Subject: [PATCH 0115/3023] drm/i915: Move golden context init into ->init_context Similar to a patch from Thomas Daniel for lrc contexts. This keeps both sides somewhat in sync and should make Dave Gordon happy. Note that both the wa and the golden context init code suffer a bit from an inssuficient split into driver load and hw init code. Which means we have a bunch of tests all over the place to check whether the one-time initialization has been done already or not. All that one-tim code should be moved into the one-time ring setup code, but that's work for later. Cc: Dave Gordon Cc: Thomas Daniel Signed-off-by: Daniel Vetter Reviewed-by: Dave Gordon Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_context.c | 4 ---- drivers/gpu/drm/i915/intel_ringbuffer.c | 18 +++++++++++++++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 5cd2b97aa76e53..2acf5803cf3221 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -651,10 +651,6 @@ static int do_switch(struct intel_engine_cs *ring, if (ret) DRM_ERROR("ring init context: %d\n", ret); } - - ret = i915_gem_render_state_init(ring); - if (ret) - DRM_ERROR("init render state: %d\n", ret); } return 0; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 3887f1aaf057ff..a8dc158f33be90 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -710,6 +710,22 @@ static int intel_ring_workarounds_emit(struct intel_engine_cs *ring, return 0; } +static int intel_rcs_ctx_init(struct intel_engine_cs *ring, + struct intel_context *ctx) +{ + int ret; + + ret = intel_ring_workarounds_emit(ring, ctx); + if (ret != 0) + return ret; + + ret = i915_gem_render_state_init(ring); + if (ret) + DRM_ERROR("init render state: %d\n", ret); + + return ret; +} + static int wa_add(struct drm_i915_private *dev_priv, const u32 addr, const u32 val, const u32 mask) { @@ -2345,7 +2361,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev) } } - ring->init_context = intel_ring_workarounds_emit; + ring->init_context = intel_rcs_ctx_init; ring->add_request = gen6_add_request; ring->flush = gen8_render_ring_flush; ring->irq_get = gen8_ring_get_irq; From 15a17aae5f803551981a7acc6a4058b247a7452c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 8 Dec 2014 16:30:00 +0100 Subject: [PATCH 0116/3023] drm/i915: Check mask/bit helper functions After a bit of irc discussion we've concluded that it would be prudent to check that callers use the mask/enable paramters correctly. So add a WARN_ON. Spurred by Damien's bugfix which added _MASKED_FIELD. v2: We use WARN_ON(1) a lot to catch default cases in switch blocks which should always be extended. So this doesn't work really. Dunno why gcc only started complaining when I've moved the WARN out of the static inline helper to address a feedback from Jani. Cc: Damien Lespiau Cc: Chris Wilson Cc: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 08a5a4ba52acd0..e6a1db36928e97 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -183,6 +183,8 @@ static void ilk_update_gt_irq(struct drm_i915_private *dev_priv, { assert_spin_locked(&dev_priv->irq_lock); + WARN_ON(enabled_irq_mask & ~interrupt_mask); + if (WARN_ON(!intel_irqs_enabled(dev_priv))) return; @@ -229,6 +231,8 @@ static void snb_update_pm_irq(struct drm_i915_private *dev_priv, { uint32_t new_val; + WARN_ON(enabled_irq_mask & ~interrupt_mask); + assert_spin_locked(&dev_priv->irq_lock); new_val = dev_priv->pm_irq_mask; @@ -328,6 +332,8 @@ void ibx_display_interrupt_update(struct drm_i915_private *dev_priv, sdeimr &= ~interrupt_mask; sdeimr |= (~enabled_irq_mask & interrupt_mask); + WARN_ON(enabled_irq_mask & ~interrupt_mask); + assert_spin_locked(&dev_priv->irq_lock); if (WARN_ON(!intel_irqs_enabled(dev_priv))) From e1f69e615f18b2cd31b04a4773a5438f6c4a797b Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 10 Dec 2014 12:29:58 +0100 Subject: [PATCH 0117/3023] drm/armada: Remove dummy ->load_lut() implementation The ->load_lut() callback is optional, therefore a dummy implementation is not needed. Cc: Russell King Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter --- drivers/gpu/drm/armada/armada_crtc.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index e3a7a5078e5ce1..42d2ffa087169f 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -653,10 +653,6 @@ static int armada_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, return 0; } -static void armada_drm_crtc_load_lut(struct drm_crtc *crtc) -{ -} - /* The mode_config.mutex will be held for this call */ static void armada_drm_crtc_disable(struct drm_crtc *crtc) { @@ -678,7 +674,6 @@ static const struct drm_crtc_helper_funcs armada_crtc_helper_funcs = { .mode_fixup = armada_drm_crtc_mode_fixup, .mode_set = armada_drm_crtc_mode_set, .mode_set_base = armada_drm_crtc_mode_set_base, - .load_lut = armada_drm_crtc_load_lut, .disable = armada_drm_crtc_disable, }; From d2e2b26bb5606763593b341476a9f5baf95ccad6 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 10 Dec 2014 12:29:59 +0100 Subject: [PATCH 0118/3023] drm/bochs: Remove dummy ->load_lut() implementation The ->load_lut() callback is optional, therefore a dummy implementation is not needed. Cc: Gerd Hoffmann Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter --- drivers/gpu/drm/bochs/bochs_kms.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c index 85f0f8cf1fb829..26bcd03a8cb657 100644 --- a/drivers/gpu/drm/bochs/bochs_kms.c +++ b/drivers/gpu/drm/bochs/bochs_kms.c @@ -18,10 +18,6 @@ MODULE_PARM_DESC(defy, "default y resolution"); /* ---------------------------------------------------------------------- */ -static void bochs_crtc_load_lut(struct drm_crtc *crtc) -{ -} - static void bochs_crtc_dpms(struct drm_crtc *crtc, int mode) { switch (mode) { @@ -144,7 +140,6 @@ static const struct drm_crtc_helper_funcs bochs_helper_funcs = { .mode_set_base = bochs_crtc_mode_set_base, .prepare = bochs_crtc_prepare, .commit = bochs_crtc_commit, - .load_lut = bochs_crtc_load_lut, }; static void bochs_crtc_init(struct drm_device *dev) From 6f6f0929e2d86779c6fe796495d4f73b026128f8 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 10 Dec 2014 12:30:00 +0100 Subject: [PATCH 0119/3023] drm/msm: Remove dummy ->load_lut() implementation The ->load_lut() callback is optional, therefore a dummy implementation is not needed. Cc: Rob Clark Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter --- drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 5 ----- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 5 ----- 2 files changed, 10 deletions(-) diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c index a7672e100d8b5b..ac2a6ebce674ee 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c @@ -323,10 +323,6 @@ static void mdp4_crtc_commit(struct drm_crtc *crtc) drm_crtc_vblank_put(crtc); } -static void mdp4_crtc_load_lut(struct drm_crtc *crtc) -{ -} - static int mdp4_crtc_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { @@ -524,7 +520,6 @@ static const struct drm_crtc_helper_funcs mdp4_crtc_helper_funcs = { .mode_set_base = drm_helper_crtc_mode_set_base, .prepare = mdp4_crtc_prepare, .commit = mdp4_crtc_commit, - .load_lut = mdp4_crtc_load_lut, .atomic_check = mdp4_crtc_atomic_check, .atomic_begin = mdp4_crtc_atomic_begin, .atomic_flush = mdp4_crtc_atomic_flush, diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index 0e9a2e3a82d76e..92d52a56b3b8b6 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -275,10 +275,6 @@ static void mdp5_crtc_commit(struct drm_crtc *crtc) mdp5_disable(get_kms(crtc)); } -static void mdp5_crtc_load_lut(struct drm_crtc *crtc) -{ -} - struct plane_state { struct drm_plane *plane; struct mdp5_plane_state *state; @@ -407,7 +403,6 @@ static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = { .mode_set_base = drm_helper_crtc_mode_set_base, .prepare = mdp5_crtc_prepare, .commit = mdp5_crtc_commit, - .load_lut = mdp5_crtc_load_lut, .atomic_check = mdp5_crtc_atomic_check, .atomic_begin = mdp5_crtc_atomic_begin, .atomic_flush = mdp5_crtc_atomic_flush, From e6966da2ac1d4b7e52772378f0292255ea92617c Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 10 Dec 2014 12:30:01 +0100 Subject: [PATCH 0120/3023] drm/sti: Remove dummy ->load_lut() implementation The ->load_lut() callback is optional, therefore a dummy implementation is not needed. Cc: Benjamin Gaignard Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter --- drivers/gpu/drm/sti/sti_drm_crtc.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/sti/sti_drm_crtc.c b/drivers/gpu/drm/sti/sti_drm_crtc.c index 36a1ad3c482319..70e6e97a850ee1 100644 --- a/drivers/gpu/drm/sti/sti_drm_crtc.c +++ b/drivers/gpu/drm/sti/sti_drm_crtc.c @@ -184,11 +184,6 @@ static int sti_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, return ret; } -static void sti_drm_crtc_load_lut(struct drm_crtc *crtc) -{ - /* do nothing */ -} - static void sti_drm_crtc_disable(struct drm_crtc *crtc) { struct sti_mixer *mixer = to_sti_mixer(crtc); @@ -243,7 +238,6 @@ static struct drm_crtc_helper_funcs sti_crtc_helper_funcs = { .mode_fixup = sti_drm_crtc_mode_fixup, .mode_set = sti_drm_crtc_mode_set, .mode_set_base = sti_drm_crtc_mode_set_base, - .load_lut = sti_drm_crtc_load_lut, .disable = sti_drm_crtc_disable, }; From c422f31d5654a4787a226bb684bd601d4db9558d Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 10 Dec 2014 12:30:02 +0100 Subject: [PATCH 0121/3023] drm/tegra: Remove dummy ->load_lut() implementation The ->load_lut() callback is optional, therefore a dummy implementation is not needed. Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter --- drivers/gpu/drm/tegra/dc.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index b957908aec73d6..d9076a10cb75bb 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -1095,10 +1095,6 @@ static void tegra_crtc_commit(struct drm_crtc *crtc) tegra_dc_commit(dc); } -static void tegra_crtc_load_lut(struct drm_crtc *crtc) -{ -} - static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = { .disable = tegra_crtc_disable, .mode_fixup = tegra_crtc_mode_fixup, @@ -1106,7 +1102,6 @@ static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = { .mode_set_base = tegra_crtc_mode_set_base, .prepare = tegra_crtc_prepare, .commit = tegra_crtc_commit, - .load_lut = tegra_crtc_load_lut, }; static irqreturn_t tegra_dc_irq(int irq, void *data) From 4dfd909f92d623d79a23985526314bb31bdd110a Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 10 Dec 2014 13:03:34 +0100 Subject: [PATCH 0122/3023] drm: Miscellaneous checkpatch whitespace cleanups A couple of whitespace changes required to silent various errors and warnings flagged by checkpatch. checkpatch requires that the opening brace be on the same line as a variable declaration. Furthermore an empty line is required after a block of variable declarations. Trailing whitespace as well as using spaces before tabs is considered an error or warning, respectively. Finally, the closing parenthesis of an if condition and the opening brace of the conditional block should be separated by a space. Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 42 ++++++++++++++++++-------------------- drivers/gpu/drm/drm_irq.c | 3 ++- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 632e6eaf4c7453..76aa8fb787dca6 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -61,8 +61,8 @@ static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev, /* * Global properties */ -static const struct drm_prop_enum_list drm_dpms_enum_list[] = -{ { DRM_MODE_DPMS_ON, "On" }, +static const struct drm_prop_enum_list drm_dpms_enum_list[] = { + { DRM_MODE_DPMS_ON, "On" }, { DRM_MODE_DPMS_STANDBY, "Standby" }, { DRM_MODE_DPMS_SUSPEND, "Suspend" }, { DRM_MODE_DPMS_OFF, "Off" } @@ -70,8 +70,7 @@ static const struct drm_prop_enum_list drm_dpms_enum_list[] = DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list) -static const struct drm_prop_enum_list drm_plane_type_enum_list[] = -{ +static const struct drm_prop_enum_list drm_plane_type_enum_list[] = { { DRM_PLANE_TYPE_OVERLAY, "Overlay" }, { DRM_PLANE_TYPE_PRIMARY, "Primary" }, { DRM_PLANE_TYPE_CURSOR, "Cursor" }, @@ -80,8 +79,7 @@ static const struct drm_prop_enum_list drm_plane_type_enum_list[] = /* * Optional properties */ -static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = -{ +static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = { { DRM_MODE_SCALE_NONE, "None" }, { DRM_MODE_SCALE_FULLSCREEN, "Full" }, { DRM_MODE_SCALE_CENTER, "Center" }, @@ -97,8 +95,7 @@ static const struct drm_prop_enum_list drm_aspect_ratio_enum_list[] = { /* * Non-global properties, but "required" for certain connectors. */ -static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = -{ +static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = { { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ @@ -106,8 +103,7 @@ static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list) -static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = -{ +static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = { { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ @@ -116,8 +112,7 @@ static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name, drm_dvi_i_subconnector_enum_list) -static const struct drm_prop_enum_list drm_tv_select_enum_list[] = -{ +static const struct drm_prop_enum_list drm_tv_select_enum_list[] = { { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ @@ -127,8 +122,7 @@ static const struct drm_prop_enum_list drm_tv_select_enum_list[] = DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list) -static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = -{ +static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = { { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ @@ -154,8 +148,8 @@ struct drm_conn_prop_enum_list { /* * Connector and encoder types. */ -static struct drm_conn_prop_enum_list drm_connector_enum_list[] = -{ { DRM_MODE_CONNECTOR_Unknown, "Unknown" }, +static struct drm_conn_prop_enum_list drm_connector_enum_list[] = { + { DRM_MODE_CONNECTOR_Unknown, "Unknown" }, { DRM_MODE_CONNECTOR_VGA, "VGA" }, { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, @@ -174,8 +168,8 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] = { DRM_MODE_CONNECTOR_DSI, "DSI" }, }; -static const struct drm_prop_enum_list drm_encoder_enum_list[] = -{ { DRM_MODE_ENCODER_NONE, "None" }, +static const struct drm_prop_enum_list drm_encoder_enum_list[] = { + { DRM_MODE_ENCODER_NONE, "None" }, { DRM_MODE_ENCODER_DAC, "DAC" }, { DRM_MODE_ENCODER_TMDS, "TMDS" }, { DRM_MODE_ENCODER_LVDS, "LVDS" }, @@ -185,8 +179,7 @@ static const struct drm_prop_enum_list drm_encoder_enum_list[] = { DRM_MODE_ENCODER_DPMST, "DP MST" }, }; -static const struct drm_prop_enum_list drm_subpixel_enum_list[] = -{ +static const struct drm_prop_enum_list drm_subpixel_enum_list[] = { { SubPixelUnknown, "Unknown" }, { SubPixelHorizontalRGB, "Horizontal RGB" }, { SubPixelHorizontalBGR, "Horizontal BGR" }, @@ -1137,6 +1130,7 @@ EXPORT_SYMBOL(drm_encoder_init); void drm_encoder_cleanup(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; + drm_modeset_lock_all(dev); drm_mode_object_put(dev, &encoder->base); kfree(encoder->name); @@ -2519,7 +2513,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data, * * This is a little helper to wrap internal calls to the ->set_config driver * interface. The only thing it adds is correct refcounting dance. - * + * * Returns: * Zero on success, negative errno on failure. */ @@ -2958,6 +2952,7 @@ int drm_mode_cursor2_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_cursor2 *req = data; + return drm_mode_cursor_common(dev, req, file_priv); } @@ -4047,7 +4042,7 @@ int drm_mode_getblob_ioctl(struct drm_device *dev, if (out_resp->length == blob->length) { blob_ptr = (void __user *)(unsigned long)out_resp->data; - if (copy_to_user(blob_ptr, blob->data, blob->length)){ + if (copy_to_user(blob_ptr, blob->data, blob->length)) { ret = -EFAULT; goto done; } @@ -4149,6 +4144,7 @@ static bool drm_property_change_is_valid(struct drm_property *property, return true; } else if (drm_property_type_is(property, DRM_MODE_PROP_SIGNED_RANGE)) { int64_t svalue = U642I64(value); + if (svalue < U642I64(property->values[0]) || svalue > U642I64(property->values[1])) return false; @@ -4156,6 +4152,7 @@ static bool drm_property_change_is_valid(struct drm_property *property, } else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) { int i; uint64_t valid_mask = 0; + for (i = 0; i < property->num_values; i++) valid_mask |= (1ULL << property->values[i]); return !(value & ~valid_mask); @@ -4164,6 +4161,7 @@ static bool drm_property_change_is_valid(struct drm_property *property, return true; } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) { struct drm_mode_object *obj; + /* a zero value for an object property translates to null: */ if (value == 0) return true; diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index f5a5f18efa5bf2..fadcd16d2300d1 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -778,7 +778,7 @@ static struct timeval get_drm_timestamp(void) /** * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent - * vblank interval + * vblank interval * @dev: DRM device * @crtc: which CRTC's vblank timestamp to retrieve * @tvblank: Pointer to target struct timeval which should receive the timestamp @@ -910,6 +910,7 @@ void drm_send_vblank_event(struct drm_device *dev, int crtc, { struct timeval now; unsigned int seq; + if (crtc >= 0) { seq = drm_vblank_count_and_time(dev, crtc, &now); } else { From bd3f0ff98a849e04dc2c0236f32cc75b8c8630db Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 10 Dec 2014 13:03:35 +0100 Subject: [PATCH 0123/3023] drm: Prefer kcalloc() over kzalloc() with multiply Fixes a couple of checkpatch warnings regarding the use of kzalloc() with a multiplication. kcalloc() is the preferred API. Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 76aa8fb787dca6..45e17df41f22f3 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1583,7 +1583,7 @@ static int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *gr total_objects += dev->mode_config.num_encoder; total_objects += dev->mode_config.num_bridge; - group->id_list = kzalloc(total_objects * sizeof(uint32_t), GFP_KERNEL); + group->id_list = kcalloc(total_objects, sizeof(uint32_t), GFP_KERNEL); if (!group->id_list) return -ENOMEM; @@ -3400,7 +3400,7 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev, ret = -EINVAL; goto out_err1; } - clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL); + clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL); if (!clips) { ret = -ENOMEM; goto out_err1; @@ -3501,7 +3501,8 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags, property->dev = dev; if (num_values) { - property->values = kzalloc(sizeof(uint64_t)*num_values, GFP_KERNEL); + property->values = kcalloc(num_values, sizeof(uint64_t), + GFP_KERNEL); if (!property->values) goto fail; } @@ -4468,7 +4469,8 @@ int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, { crtc->gamma_size = gamma_size; - crtc->gamma_store = kzalloc(gamma_size * sizeof(uint16_t) * 3, GFP_KERNEL); + crtc->gamma_store = kcalloc(gamma_size, sizeof(uint16_t) * 3, + GFP_KERNEL); if (!crtc->gamma_store) { crtc->gamma_size = 0; return -ENOMEM; From 2f6c538924108fbffb72a0696f28537b364080fa Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 10 Dec 2014 13:03:36 +0100 Subject: [PATCH 0124/3023] drm: Prefer kmalloc_array() over kmalloc() with multiply Fixes a couple of checkpatch warnings regarding the use of kmalloc() with a multiplication. kmalloc_array() is the preferred API. Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 45e17df41f22f3..0d3a4105f4e88f 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1174,8 +1174,8 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, plane->base.properties = &plane->properties; plane->dev = dev; plane->funcs = funcs; - plane->format_types = kmalloc(sizeof(uint32_t) * format_count, - GFP_KERNEL); + plane->format_types = kmalloc_array(format_count, sizeof(uint32_t), + GFP_KERNEL); if (!plane->format_types) { DRM_DEBUG_KMS("out of memory when allocating plane\n"); drm_mode_object_put(dev, &plane->base); @@ -2705,9 +2705,9 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, goto out; } - connector_set = kmalloc(crtc_req->count_connectors * - sizeof(struct drm_connector *), - GFP_KERNEL); + connector_set = kmalloc_array(crtc_req->count_connectors, + sizeof(struct drm_connector *), + GFP_KERNEL); if (!connector_set) { ret = -ENOMEM; goto out; From 0cc0b223e7c9b4642c86d46f20d3d4a4a89bede3 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 10 Dec 2014 13:03:37 +0100 Subject: [PATCH 0125/3023] drm: Do not assign in if condition checkpatch requires the assignment and the check to be separate statements. Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 0d3a4105f4e88f..e8036fd38aee12 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1613,7 +1613,8 @@ int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_bridge *bridge; int ret; - if ((ret = drm_mode_group_init(dev, group))) + ret = drm_mode_group_init(dev, group); + if (ret) return ret; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) From 01073b0846c7c13438ef9b4d62e0747aed2db15d Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 10 Dec 2014 13:03:38 +0100 Subject: [PATCH 0126/3023] drm: Remove unneeded braces for single statement blocks Single statement blocks don't need to be enclosed in a pair of braces. Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index e8036fd38aee12..fa1b1a5b833008 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2030,11 +2030,9 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, props_count = connector->properties.count; - for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { - if (connector->encoder_ids[i] != 0) { + for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) + if (connector->encoder_ids[i] != 0) encoders_count++; - } - } if (out_resp->count_modes == 0) { connector->funcs->fill_modes(connector, From 2ca651d15aff0f613d11913e8a10e3b86b3dc44a Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 10 Dec 2014 13:03:39 +0100 Subject: [PATCH 0127/3023] drm: Remove useless else block All prior conditional blocks return from the function, so the else block can be at the top level of the function. Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index fa1b1a5b833008..4f4fcd37f1107a 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -4135,6 +4135,8 @@ EXPORT_SYMBOL(drm_mode_connector_update_edid_property); static bool drm_property_change_is_valid(struct drm_property *property, uint64_t value) { + int i; + if (property->flags & DRM_MODE_PROP_IMMUTABLE) return false; @@ -4150,7 +4152,6 @@ static bool drm_property_change_is_valid(struct drm_property *property, return false; return true; } else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) { - int i; uint64_t valid_mask = 0; for (i = 0; i < property->num_values; i++) @@ -4174,13 +4175,12 @@ static bool drm_property_change_is_valid(struct drm_property *property, */ obj = _object_find(property->dev, value, property->values[0]); return obj != NULL; - } else { - int i; - for (i = 0; i < property->num_values; i++) - if (property->values[i] == value) - return true; - return false; } + + for (i = 0; i < property->num_values; i++) + if (property->values[i] == value) + return true; + return false; } /** From f76511b97237f159b6b9a951a4f7fdd773d9698d Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 10 Dec 2014 13:03:40 +0100 Subject: [PATCH 0128/3023] drm: Prefer sizeof(type) over sizeof type sizeof(type) is the variant used most commonly and required by checkpatch. Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 12 ++++++------ drivers/gpu/drm/drm_irq.c | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 4f4fcd37f1107a..6700ebafef1677 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -4684,23 +4684,23 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { ret = -ENOMEM; spin_lock_irqsave(&dev->event_lock, flags); - if (file_priv->event_space < sizeof e->event) { + if (file_priv->event_space < sizeof(e->event)) { spin_unlock_irqrestore(&dev->event_lock, flags); goto out; } - file_priv->event_space -= sizeof e->event; + file_priv->event_space -= sizeof(e->event); spin_unlock_irqrestore(&dev->event_lock, flags); - e = kzalloc(sizeof *e, GFP_KERNEL); + e = kzalloc(sizeof(*e), GFP_KERNEL); if (e == NULL) { spin_lock_irqsave(&dev->event_lock, flags); - file_priv->event_space += sizeof e->event; + file_priv->event_space += sizeof(e->event); spin_unlock_irqrestore(&dev->event_lock, flags); goto out; } e->event.base.type = DRM_EVENT_FLIP_COMPLETE; - e->event.base.length = sizeof e->event; + e->event.base.length = sizeof(e->event); e->event.user_data = page_flip->user_data; e->base.event = &e->event.base; e->base.file_priv = file_priv; @@ -4713,7 +4713,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, if (ret) { if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { spin_lock_irqsave(&dev->event_lock, flags); - file_priv->event_space += sizeof e->event; + file_priv->event_space += sizeof(e->event); spin_unlock_irqrestore(&dev->event_lock, flags); kfree(e); } diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index fadcd16d2300d1..920cdb91e9d0eb 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -1383,7 +1383,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe, unsigned int seq; int ret; - e = kzalloc(sizeof *e, GFP_KERNEL); + e = kzalloc(sizeof(*e), GFP_KERNEL); if (e == NULL) { ret = -ENOMEM; goto err_put; @@ -1392,7 +1392,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe, e->pipe = pipe; e->base.pid = current->pid; e->event.base.type = DRM_EVENT_VBLANK; - e->event.base.length = sizeof e->event; + e->event.base.length = sizeof(e->event); e->event.user_data = vblwait->request.signal; e->base.event = &e->event.base; e->base.file_priv = file_priv; @@ -1412,12 +1412,12 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe, goto err_unlock; } - if (file_priv->event_space < sizeof e->event) { + if (file_priv->event_space < sizeof(e->event)) { ret = -EBUSY; goto err_unlock; } - file_priv->event_space -= sizeof e->event; + file_priv->event_space -= sizeof(e->event); seq = drm_vblank_count_and_time(dev, pipe, &now); if ((vblwait->request.type & _DRM_VBLANK_NEXTONMISS) && From 7ff0ebcc1e30e3216c8c62ee71f59ac830b10364 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Mon, 8 Dec 2014 14:09:10 -0200 Subject: [PATCH 0129/3023] drm/i915: Move FBC stuff to intel_fbc.c No functional changes. This is just the begin of a FBC rework. v2 (Paulo): - Revert intel_fbc_init() changed parameter. - Revert set_no_fbc_reason() rename. - Rebase. Cc: Paulo Zanoni Signed-off-by: Rodrigo Vivi Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/i915_drv.h | 3 - drivers/gpu/drm/i915/i915_suspend.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 22 +- drivers/gpu/drm/i915/intel_drv.h | 9 +- drivers/gpu/drm/i915/intel_fbc.c | 675 +++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_pm.c | 651 +------------------------- drivers/gpu/drm/i915/intel_sprite.c | 4 +- 8 files changed, 698 insertions(+), 669 deletions(-) create mode 100644 drivers/gpu/drm/i915/intel_fbc.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index e4083e41a600e2..3cf70a61b44f39 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -47,6 +47,7 @@ i915-y += intel_renderstate_gen6.o \ i915-y += intel_audio.o \ intel_bios.o \ intel_display.o \ + intel_fbc.o \ intel_fifo_underrun.o \ intel_frontbuffer.o \ intel_modes.o \ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 95dfa2dd35b921..c74dc946cbf63d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2963,9 +2963,6 @@ extern void intel_modeset_setup_hw_state(struct drm_device *dev, bool force_restore); extern void i915_redisable_vga(struct drm_device *dev); extern void i915_redisable_vga_power_on(struct drm_device *dev); -extern bool intel_fbc_enabled(struct drm_device *dev); -extern void bdw_fbc_sw_flush(struct drm_device *dev, u32 value); -extern void intel_disable_fbc(struct drm_device *dev); extern bool ironlake_set_drps(struct drm_device *dev, u8 val); extern void intel_init_pch_refclk(struct drm_device *dev); extern void gen6_set_rps(struct drm_device *dev, u8 val); diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index dfe661743398b1..1e4999dd3ed540 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -264,7 +264,7 @@ static void i915_restore_display(struct drm_device *dev) } /* only restore FBC info on the platform that supports FBC*/ - intel_disable_fbc(dev); + intel_fbc_disable(dev); /* restore FBC interval */ if (HAS_FBC(dev) && INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev)) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d5153a4f90fec4..841af6c1f50be9 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4201,7 +4201,7 @@ static void intel_crtc_enable_planes(struct drm_crtc *crtc) hsw_enable_ips(intel_crtc); mutex_lock(&dev->struct_mutex); - intel_update_fbc(dev); + intel_fbc_update(dev); mutex_unlock(&dev->struct_mutex); /* @@ -4223,7 +4223,7 @@ static void intel_crtc_disable_planes(struct drm_crtc *crtc) intel_crtc_wait_for_pending_flips(crtc); if (dev_priv->fbc.plane == plane) - intel_disable_fbc(dev); + intel_fbc_disable(dev); hsw_disable_ips(intel_crtc); @@ -4527,7 +4527,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) intel_update_watermarks(crtc); mutex_lock(&dev->struct_mutex); - intel_update_fbc(dev); + intel_fbc_update(dev); mutex_unlock(&dev->struct_mutex); } @@ -4584,7 +4584,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) intel_update_watermarks(crtc); mutex_lock(&dev->struct_mutex); - intel_update_fbc(dev); + intel_fbc_update(dev); mutex_unlock(&dev->struct_mutex); if (intel_crtc_to_shared_dpll(intel_crtc)) @@ -5189,7 +5189,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) intel_update_watermarks(crtc); mutex_lock(&dev->struct_mutex); - intel_update_fbc(dev); + intel_fbc_update(dev); mutex_unlock(&dev->struct_mutex); } @@ -8950,7 +8950,7 @@ static void intel_unpin_work_fn(struct work_struct *__work) drm_gem_object_unreference(&work->pending_flip_obj->base); drm_gem_object_unreference(&work->old_fb_obj->base); - intel_update_fbc(dev); + intel_fbc_update(dev); if (work->flip_queued_req) i915_gem_request_assign(&work->flip_queued_req, NULL); @@ -9747,7 +9747,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, i915_gem_track_fb(work->old_fb_obj, obj, INTEL_FRONTBUFFER_PRIMARY(pipe)); - intel_disable_fbc(dev); + intel_fbc_disable(dev); intel_frontbuffer_flip_prepare(dev, INTEL_FRONTBUFFER_PRIMARY(pipe)); mutex_unlock(&dev->struct_mutex); @@ -11816,7 +11816,7 @@ intel_commit_primary_plane(struct drm_plane *plane, INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) && dev_priv->fbc.plane == intel_crtc->plane && intel_plane->rotation != BIT(DRM_ROTATE_0)) { - intel_disable_fbc(dev); + intel_fbc_disable(dev); } if (state->visible) { @@ -11851,7 +11851,7 @@ intel_commit_primary_plane(struct drm_plane *plane, intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_PRIMARY(pipe)); mutex_lock(&dev->struct_mutex); - intel_update_fbc(dev); + intel_fbc_update(dev); mutex_unlock(&dev->struct_mutex); } } @@ -13050,7 +13050,7 @@ void intel_modeset_init(struct drm_device *dev) intel_setup_outputs(dev); /* Just in case the BIOS is doing something questionable. */ - intel_disable_fbc(dev); + intel_fbc_disable(dev); drm_modeset_lock_all(dev); intel_modeset_setup_hw_state(dev, false); @@ -13567,7 +13567,7 @@ void intel_modeset_cleanup(struct drm_device *dev) intel_unregister_dsm_handler(); - intel_disable_fbc(dev); + intel_fbc_disable(dev); ironlake_teardown_rc6(dev); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 61a88fa6997831..588b618ab668fc 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1063,6 +1063,13 @@ static inline void intel_fbdev_restore_mode(struct drm_device *dev) } #endif +/* intel_fbc.c */ +bool intel_fbc_enabled(struct drm_device *dev); +void intel_fbc_update(struct drm_device *dev); +void intel_fbc_init(struct drm_i915_private *dev_priv); +void intel_fbc_disable(struct drm_device *dev); +void bdw_fbc_sw_flush(struct drm_device *dev, u32 value); + /* intel_hdmi.c */ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port); void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, @@ -1169,8 +1176,6 @@ void intel_update_sprite_watermarks(struct drm_plane *plane, bool enabled, bool scaled); void intel_init_pm(struct drm_device *dev); void intel_pm_setup(struct drm_device *dev); -bool intel_fbc_enabled(struct drm_device *dev); -void intel_update_fbc(struct drm_device *dev); void intel_gpu_ips_init(struct drm_i915_private *dev_priv); void intel_gpu_ips_teardown(void); void intel_init_gt_powersave(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c new file mode 100644 index 00000000000000..f1eeb86a3d1bad --- /dev/null +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -0,0 +1,675 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "intel_drv.h" +#include "i915_drv.h" + +/* FBC, or Frame Buffer Compression, is a technique employed to compress the + * framebuffer contents in-memory, aiming at reducing the required bandwidth + * during in-memory transfers and, therefore, reduce the power packet. + * + * The benefits of FBC are mostly visible with solid backgrounds and + * variation-less patterns. + * + * FBC-related functionality can be enabled by the means of the + * i915.i915_fbc_enable parameter + */ + +static void i8xx_fbc_disable(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 fbc_ctl; + + dev_priv->fbc.enabled = false; + + /* Disable compression */ + fbc_ctl = I915_READ(FBC_CONTROL); + if ((fbc_ctl & FBC_CTL_EN) == 0) + return; + + fbc_ctl &= ~FBC_CTL_EN; + I915_WRITE(FBC_CONTROL, fbc_ctl); + + /* Wait for compressing bit to clear */ + if (wait_for((I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) == 0, 10)) { + DRM_DEBUG_KMS("FBC idle timed out\n"); + return; + } + + DRM_DEBUG_KMS("disabled FBC\n"); +} + +static void i8xx_fbc_enable(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_framebuffer *fb = crtc->primary->fb; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int cfb_pitch; + int i; + u32 fbc_ctl; + + dev_priv->fbc.enabled = true; + + cfb_pitch = dev_priv->fbc.size / FBC_LL_SIZE; + if (fb->pitches[0] < cfb_pitch) + cfb_pitch = fb->pitches[0]; + + /* FBC_CTL wants 32B or 64B units */ + if (IS_GEN2(dev)) + cfb_pitch = (cfb_pitch / 32) - 1; + else + cfb_pitch = (cfb_pitch / 64) - 1; + + /* Clear old tags */ + for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++) + I915_WRITE(FBC_TAG + (i * 4), 0); + + if (IS_GEN4(dev)) { + u32 fbc_ctl2; + + /* Set it up... */ + fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE; + fbc_ctl2 |= FBC_CTL_PLANE(intel_crtc->plane); + I915_WRITE(FBC_CONTROL2, fbc_ctl2); + I915_WRITE(FBC_FENCE_OFF, crtc->y); + } + + /* enable it... */ + fbc_ctl = I915_READ(FBC_CONTROL); + fbc_ctl &= 0x3fff << FBC_CTL_INTERVAL_SHIFT; + fbc_ctl |= FBC_CTL_EN | FBC_CTL_PERIODIC; + if (IS_I945GM(dev)) + fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */ + fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT; + fbc_ctl |= obj->fence_reg; + I915_WRITE(FBC_CONTROL, fbc_ctl); + + DRM_DEBUG_KMS("enabled FBC, pitch %d, yoff %d, plane %c\n", + cfb_pitch, crtc->y, plane_name(intel_crtc->plane)); +} + +static bool i8xx_fbc_enabled(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + return I915_READ(FBC_CONTROL) & FBC_CTL_EN; +} + +static void g4x_fbc_enable(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_framebuffer *fb = crtc->primary->fb; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + u32 dpfc_ctl; + + dev_priv->fbc.enabled = true; + + dpfc_ctl = DPFC_CTL_PLANE(intel_crtc->plane) | DPFC_SR_EN; + if (drm_format_plane_cpp(fb->pixel_format, 0) == 2) + dpfc_ctl |= DPFC_CTL_LIMIT_2X; + else + dpfc_ctl |= DPFC_CTL_LIMIT_1X; + dpfc_ctl |= DPFC_CTL_FENCE_EN | obj->fence_reg; + + I915_WRITE(DPFC_FENCE_YOFF, crtc->y); + + /* enable it... */ + I915_WRITE(DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); + + DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(intel_crtc->plane)); +} + +static void g4x_fbc_disable(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 dpfc_ctl; + + dev_priv->fbc.enabled = false; + + /* Disable compression */ + dpfc_ctl = I915_READ(DPFC_CONTROL); + if (dpfc_ctl & DPFC_CTL_EN) { + dpfc_ctl &= ~DPFC_CTL_EN; + I915_WRITE(DPFC_CONTROL, dpfc_ctl); + + DRM_DEBUG_KMS("disabled FBC\n"); + } +} + +static bool g4x_fbc_enabled(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN; +} + +static void snb_fbc_blit_update(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 blt_ecoskpd; + + /* Make sure blitter notifies FBC of writes */ + + /* Blitter is part of Media powerwell on VLV. No impact of + * his param in other platforms for now */ + gen6_gt_force_wake_get(dev_priv, FORCEWAKE_MEDIA); + + blt_ecoskpd = I915_READ(GEN6_BLITTER_ECOSKPD); + blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY << + GEN6_BLITTER_LOCK_SHIFT; + I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd); + blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY; + I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd); + blt_ecoskpd &= ~(GEN6_BLITTER_FBC_NOTIFY << + GEN6_BLITTER_LOCK_SHIFT); + I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd); + POSTING_READ(GEN6_BLITTER_ECOSKPD); + + gen6_gt_force_wake_put(dev_priv, FORCEWAKE_MEDIA); +} + +static void ilk_fbc_enable(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_framebuffer *fb = crtc->primary->fb; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + u32 dpfc_ctl; + + dev_priv->fbc.enabled = true; + + dpfc_ctl = DPFC_CTL_PLANE(intel_crtc->plane); + if (drm_format_plane_cpp(fb->pixel_format, 0) == 2) + dev_priv->fbc.threshold++; + + switch (dev_priv->fbc.threshold) { + case 4: + case 3: + dpfc_ctl |= DPFC_CTL_LIMIT_4X; + break; + case 2: + dpfc_ctl |= DPFC_CTL_LIMIT_2X; + break; + case 1: + dpfc_ctl |= DPFC_CTL_LIMIT_1X; + break; + } + dpfc_ctl |= DPFC_CTL_FENCE_EN; + if (IS_GEN5(dev)) + dpfc_ctl |= obj->fence_reg; + + I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->y); + I915_WRITE(ILK_FBC_RT_BASE, i915_gem_obj_ggtt_offset(obj) | ILK_FBC_RT_VALID); + /* enable it... */ + I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); + + if (IS_GEN6(dev)) { + I915_WRITE(SNB_DPFC_CTL_SA, + SNB_CPU_FENCE_ENABLE | obj->fence_reg); + I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y); + snb_fbc_blit_update(dev); + } + + DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(intel_crtc->plane)); +} + +static void ilk_fbc_disable(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 dpfc_ctl; + + dev_priv->fbc.enabled = false; + + /* Disable compression */ + dpfc_ctl = I915_READ(ILK_DPFC_CONTROL); + if (dpfc_ctl & DPFC_CTL_EN) { + dpfc_ctl &= ~DPFC_CTL_EN; + I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl); + + DRM_DEBUG_KMS("disabled FBC\n"); + } +} + +static bool ilk_fbc_enabled(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN; +} + +static void gen7_fbc_enable(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_framebuffer *fb = crtc->primary->fb; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + u32 dpfc_ctl; + + dev_priv->fbc.enabled = true; + + dpfc_ctl = IVB_DPFC_CTL_PLANE(intel_crtc->plane); + if (drm_format_plane_cpp(fb->pixel_format, 0) == 2) + dev_priv->fbc.threshold++; + + switch (dev_priv->fbc.threshold) { + case 4: + case 3: + dpfc_ctl |= DPFC_CTL_LIMIT_4X; + break; + case 2: + dpfc_ctl |= DPFC_CTL_LIMIT_2X; + break; + case 1: + dpfc_ctl |= DPFC_CTL_LIMIT_1X; + break; + } + + dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN; + + if (dev_priv->fbc.false_color) + dpfc_ctl |= FBC_CTL_FALSE_COLOR; + + I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); + + if (IS_IVYBRIDGE(dev)) { + /* WaFbcAsynchFlipDisableFbcQueue:ivb */ + I915_WRITE(ILK_DISPLAY_CHICKEN1, + I915_READ(ILK_DISPLAY_CHICKEN1) | + ILK_FBCQ_DIS); + } else { + /* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */ + I915_WRITE(CHICKEN_PIPESL_1(intel_crtc->pipe), + I915_READ(CHICKEN_PIPESL_1(intel_crtc->pipe)) | + HSW_FBCQ_DIS); + } + + I915_WRITE(SNB_DPFC_CTL_SA, + SNB_CPU_FENCE_ENABLE | obj->fence_reg); + I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y); + + snb_fbc_blit_update(dev); + + DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(intel_crtc->plane)); +} + +bool intel_fbc_enabled(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + return dev_priv->fbc.enabled; +} + +void bdw_fbc_sw_flush(struct drm_device *dev, u32 value) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (!IS_GEN8(dev)) + return; + + if (!intel_fbc_enabled(dev)) + return; + + I915_WRITE(MSG_FBC_REND_STATE, value); +} + +static void intel_fbc_work_fn(struct work_struct *__work) +{ + struct intel_fbc_work *work = + container_of(to_delayed_work(__work), + struct intel_fbc_work, work); + struct drm_device *dev = work->crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + mutex_lock(&dev->struct_mutex); + if (work == dev_priv->fbc.fbc_work) { + /* Double check that we haven't switched fb without cancelling + * the prior work. + */ + if (work->crtc->primary->fb == work->fb) { + dev_priv->display.enable_fbc(work->crtc); + + dev_priv->fbc.plane = to_intel_crtc(work->crtc)->plane; + dev_priv->fbc.fb_id = work->crtc->primary->fb->base.id; + dev_priv->fbc.y = work->crtc->y; + } + + dev_priv->fbc.fbc_work = NULL; + } + mutex_unlock(&dev->struct_mutex); + + kfree(work); +} + +static void intel_fbc_cancel_work(struct drm_i915_private *dev_priv) +{ + if (dev_priv->fbc.fbc_work == NULL) + return; + + DRM_DEBUG_KMS("cancelling pending FBC enable\n"); + + /* Synchronisation is provided by struct_mutex and checking of + * dev_priv->fbc.fbc_work, so we can perform the cancellation + * entirely asynchronously. + */ + if (cancel_delayed_work(&dev_priv->fbc.fbc_work->work)) + /* tasklet was killed before being run, clean up */ + kfree(dev_priv->fbc.fbc_work); + + /* Mark the work as no longer wanted so that if it does + * wake-up (because the work was already running and waiting + * for our mutex), it will discover that is no longer + * necessary to run. + */ + dev_priv->fbc.fbc_work = NULL; +} + +static void intel_fbc_enable(struct drm_crtc *crtc) +{ + struct intel_fbc_work *work; + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + if (!dev_priv->display.enable_fbc) + return; + + intel_fbc_cancel_work(dev_priv); + + work = kzalloc(sizeof(*work), GFP_KERNEL); + if (work == NULL) { + DRM_ERROR("Failed to allocate FBC work structure\n"); + dev_priv->display.enable_fbc(crtc); + return; + } + + work->crtc = crtc; + work->fb = crtc->primary->fb; + INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn); + + dev_priv->fbc.fbc_work = work; + + /* Delay the actual enabling to let pageflipping cease and the + * display to settle before starting the compression. Note that + * this delay also serves a second purpose: it allows for a + * vblank to pass after disabling the FBC before we attempt + * to modify the control registers. + * + * A more complicated solution would involve tracking vblanks + * following the termination of the page-flipping sequence + * and indeed performing the enable as a co-routine and not + * waiting synchronously upon the vblank. + * + * WaFbcWaitForVBlankBeforeEnable:ilk,snb + */ + schedule_delayed_work(&work->work, msecs_to_jiffies(50)); +} + +void intel_fbc_disable(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + intel_fbc_cancel_work(dev_priv); + + if (!dev_priv->display.disable_fbc) + return; + + dev_priv->display.disable_fbc(dev); + dev_priv->fbc.plane = -1; +} + +static bool set_no_fbc_reason(struct drm_i915_private *dev_priv, + enum no_fbc_reason reason) +{ + if (dev_priv->fbc.no_fbc_reason == reason) + return false; + + dev_priv->fbc.no_fbc_reason = reason; + return true; +} + +/** + * intel_fbc_update - enable/disable FBC as needed + * @dev: the drm_device + * + * Set up the framebuffer compression hardware at mode set time. We + * enable it if possible: + * - plane A only (on pre-965) + * - no pixel mulitply/line duplication + * - no alpha buffer discard + * - no dual wide + * - framebuffer <= max_hdisplay in width, max_vdisplay in height + * + * We can't assume that any compression will take place (worst case), + * so the compressed buffer has to be the same size as the uncompressed + * one. It also must reside (along with the line length buffer) in + * stolen memory. + * + * We need to enable/disable FBC on a global basis. + */ +void intel_fbc_update(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_crtc *crtc = NULL, *tmp_crtc; + struct intel_crtc *intel_crtc; + struct drm_framebuffer *fb; + struct drm_i915_gem_object *obj; + const struct drm_display_mode *adjusted_mode; + unsigned int max_width, max_height; + + if (!HAS_FBC(dev)) { + set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED); + return; + } + + if (!i915.powersave) { + if (set_no_fbc_reason(dev_priv, FBC_MODULE_PARAM)) + DRM_DEBUG_KMS("fbc disabled per module param\n"); + return; + } + + /* + * If FBC is already on, we just have to verify that we can + * keep it that way... + * Need to disable if: + * - more than one pipe is active + * - changing FBC params (stride, fence, mode) + * - new fb is too large to fit in compressed buffer + * - going to an unsupported config (interlace, pixel multiply, etc.) + */ + for_each_crtc(dev, tmp_crtc) { + if (intel_crtc_active(tmp_crtc) && + to_intel_crtc(tmp_crtc)->primary_enabled) { + if (crtc) { + if (set_no_fbc_reason(dev_priv, FBC_MULTIPLE_PIPES)) + DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); + goto out_disable; + } + crtc = tmp_crtc; + } + } + + if (!crtc || crtc->primary->fb == NULL) { + if (set_no_fbc_reason(dev_priv, FBC_NO_OUTPUT)) + DRM_DEBUG_KMS("no output, disabling\n"); + goto out_disable; + } + + intel_crtc = to_intel_crtc(crtc); + fb = crtc->primary->fb; + obj = intel_fb_obj(fb); + adjusted_mode = &intel_crtc->config.adjusted_mode; + + if (i915.enable_fbc < 0) { + if (set_no_fbc_reason(dev_priv, FBC_CHIP_DEFAULT)) + DRM_DEBUG_KMS("disabled per chip default\n"); + goto out_disable; + } + if (!i915.enable_fbc) { + if (set_no_fbc_reason(dev_priv, FBC_MODULE_PARAM)) + DRM_DEBUG_KMS("fbc disabled per module param\n"); + goto out_disable; + } + if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) || + (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)) { + if (set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED_MODE)) + DRM_DEBUG_KMS("mode incompatible with compression, " + "disabling\n"); + goto out_disable; + } + + if (INTEL_INFO(dev)->gen >= 8 || IS_HASWELL(dev)) { + max_width = 4096; + max_height = 4096; + } else if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) { + max_width = 4096; + max_height = 2048; + } else { + max_width = 2048; + max_height = 1536; + } + if (intel_crtc->config.pipe_src_w > max_width || + intel_crtc->config.pipe_src_h > max_height) { + if (set_no_fbc_reason(dev_priv, FBC_MODE_TOO_LARGE)) + DRM_DEBUG_KMS("mode too large for compression, disabling\n"); + goto out_disable; + } + if ((INTEL_INFO(dev)->gen < 4 || HAS_DDI(dev)) && + intel_crtc->plane != PLANE_A) { + if (set_no_fbc_reason(dev_priv, FBC_BAD_PLANE)) + DRM_DEBUG_KMS("plane not A, disabling compression\n"); + goto out_disable; + } + + /* The use of a CPU fence is mandatory in order to detect writes + * by the CPU to the scanout and trigger updates to the FBC. + */ + if (obj->tiling_mode != I915_TILING_X || + obj->fence_reg == I915_FENCE_REG_NONE) { + if (set_no_fbc_reason(dev_priv, FBC_NOT_TILED)) + DRM_DEBUG_KMS("framebuffer not tiled or fenced, disabling compression\n"); + goto out_disable; + } + if (INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) && + to_intel_plane(crtc->primary)->rotation != BIT(DRM_ROTATE_0)) { + if (set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED_MODE)) + DRM_DEBUG_KMS("Rotation unsupported, disabling\n"); + goto out_disable; + } + + /* If the kernel debugger is active, always disable compression */ + if (in_dbg_master()) + goto out_disable; + + if (i915_gem_stolen_setup_compression(dev, obj->base.size, + drm_format_plane_cpp(fb->pixel_format, 0))) { + if (set_no_fbc_reason(dev_priv, FBC_STOLEN_TOO_SMALL)) + DRM_DEBUG_KMS("framebuffer too large, disabling compression\n"); + goto out_disable; + } + + /* If the scanout has not changed, don't modify the FBC settings. + * Note that we make the fundamental assumption that the fb->obj + * cannot be unpinned (and have its GTT offset and fence revoked) + * without first being decoupled from the scanout and FBC disabled. + */ + if (dev_priv->fbc.plane == intel_crtc->plane && + dev_priv->fbc.fb_id == fb->base.id && + dev_priv->fbc.y == crtc->y) + return; + + if (intel_fbc_enabled(dev)) { + /* We update FBC along two paths, after changing fb/crtc + * configuration (modeswitching) and after page-flipping + * finishes. For the latter, we know that not only did + * we disable the FBC at the start of the page-flip + * sequence, but also more than one vblank has passed. + * + * For the former case of modeswitching, it is possible + * to switch between two FBC valid configurations + * instantaneously so we do need to disable the FBC + * before we can modify its control registers. We also + * have to wait for the next vblank for that to take + * effect. However, since we delay enabling FBC we can + * assume that a vblank has passed since disabling and + * that we can safely alter the registers in the deferred + * callback. + * + * In the scenario that we go from a valid to invalid + * and then back to valid FBC configuration we have + * no strict enforcement that a vblank occurred since + * disabling the FBC. However, along all current pipe + * disabling paths we do need to wait for a vblank at + * some point. And we wait before enabling FBC anyway. + */ + DRM_DEBUG_KMS("disabling active FBC for update\n"); + intel_fbc_disable(dev); + } + + intel_fbc_enable(crtc); + dev_priv->fbc.no_fbc_reason = FBC_OK; + return; + +out_disable: + /* Multiple disables should be harmless */ + if (intel_fbc_enabled(dev)) { + DRM_DEBUG_KMS("unsupported config, disabling FBC\n"); + intel_fbc_disable(dev); + } + i915_gem_stolen_cleanup_compression(dev); +} + +void intel_fbc_init(struct drm_i915_private *dev_priv) +{ + if (!HAS_FBC(dev_priv)) { + dev_priv->fbc.enabled = false; + return; + } + + if (INTEL_INFO(dev_priv)->gen >= 7) { + dev_priv->display.fbc_enabled = ilk_fbc_enabled; + dev_priv->display.enable_fbc = gen7_fbc_enable; + dev_priv->display.disable_fbc = ilk_fbc_disable; + } else if (INTEL_INFO(dev_priv)->gen >= 5) { + dev_priv->display.fbc_enabled = ilk_fbc_enabled; + dev_priv->display.enable_fbc = ilk_fbc_enable; + dev_priv->display.disable_fbc = ilk_fbc_disable; + } else if (IS_GM45(dev_priv)) { + dev_priv->display.fbc_enabled = g4x_fbc_enabled; + dev_priv->display.enable_fbc = g4x_fbc_enable; + dev_priv->display.disable_fbc = g4x_fbc_disable; + } else { + dev_priv->display.fbc_enabled = i8xx_fbc_enabled; + dev_priv->display.enable_fbc = i8xx_fbc_enable; + dev_priv->display.disable_fbc = i8xx_fbc_disable; + + /* This value was pulled out of someone's hat */ + I915_WRITE(FBC_CONTROL, 500 << FBC_CTL_INTERVAL_SHIFT); + } + + dev_priv->fbc.enabled = dev_priv->display.fbc_enabled(dev_priv->dev); +} diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 78911e29439c1c..99865c046c8a5c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -52,17 +52,6 @@ #define INTEL_RC6p_ENABLE (1<<1) #define INTEL_RC6pp_ENABLE (1<<2) -/* FBC, or Frame Buffer Compression, is a technique employed to compress the - * framebuffer contents in-memory, aiming at reducing the required bandwidth - * during in-memory transfers and, therefore, reduce the power packet. - * - * The benefits of FBC are mostly visible with solid backgrounds and - * variation-less patterns. - * - * FBC-related functionality can be enabled by the means of the - * i915.i915_enable_fbc parameter - */ - static void gen9_init_clock_gating(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -87,613 +76,6 @@ static void gen9_init_clock_gating(struct drm_device *dev) _MASKED_BIT_ENABLE(GEN8_4x4_STC_OPTIMIZATION_DISABLE)); } -static void i8xx_disable_fbc(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - u32 fbc_ctl; - - dev_priv->fbc.enabled = false; - - /* Disable compression */ - fbc_ctl = I915_READ(FBC_CONTROL); - if ((fbc_ctl & FBC_CTL_EN) == 0) - return; - - fbc_ctl &= ~FBC_CTL_EN; - I915_WRITE(FBC_CONTROL, fbc_ctl); - - /* Wait for compressing bit to clear */ - if (wait_for((I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) == 0, 10)) { - DRM_DEBUG_KMS("FBC idle timed out\n"); - return; - } - - DRM_DEBUG_KMS("disabled FBC\n"); -} - -static void i8xx_enable_fbc(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_framebuffer *fb = crtc->primary->fb; - struct drm_i915_gem_object *obj = intel_fb_obj(fb); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int cfb_pitch; - int i; - u32 fbc_ctl; - - dev_priv->fbc.enabled = true; - - cfb_pitch = dev_priv->fbc.size / FBC_LL_SIZE; - if (fb->pitches[0] < cfb_pitch) - cfb_pitch = fb->pitches[0]; - - /* FBC_CTL wants 32B or 64B units */ - if (IS_GEN2(dev)) - cfb_pitch = (cfb_pitch / 32) - 1; - else - cfb_pitch = (cfb_pitch / 64) - 1; - - /* Clear old tags */ - for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++) - I915_WRITE(FBC_TAG + (i * 4), 0); - - if (IS_GEN4(dev)) { - u32 fbc_ctl2; - - /* Set it up... */ - fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE; - fbc_ctl2 |= FBC_CTL_PLANE(intel_crtc->plane); - I915_WRITE(FBC_CONTROL2, fbc_ctl2); - I915_WRITE(FBC_FENCE_OFF, crtc->y); - } - - /* enable it... */ - fbc_ctl = I915_READ(FBC_CONTROL); - fbc_ctl &= 0x3fff << FBC_CTL_INTERVAL_SHIFT; - fbc_ctl |= FBC_CTL_EN | FBC_CTL_PERIODIC; - if (IS_I945GM(dev)) - fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */ - fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT; - fbc_ctl |= obj->fence_reg; - I915_WRITE(FBC_CONTROL, fbc_ctl); - - DRM_DEBUG_KMS("enabled FBC, pitch %d, yoff %d, plane %c\n", - cfb_pitch, crtc->y, plane_name(intel_crtc->plane)); -} - -static bool i8xx_fbc_enabled(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - return I915_READ(FBC_CONTROL) & FBC_CTL_EN; -} - -static void g4x_enable_fbc(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_framebuffer *fb = crtc->primary->fb; - struct drm_i915_gem_object *obj = intel_fb_obj(fb); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - u32 dpfc_ctl; - - dev_priv->fbc.enabled = true; - - dpfc_ctl = DPFC_CTL_PLANE(intel_crtc->plane) | DPFC_SR_EN; - if (drm_format_plane_cpp(fb->pixel_format, 0) == 2) - dpfc_ctl |= DPFC_CTL_LIMIT_2X; - else - dpfc_ctl |= DPFC_CTL_LIMIT_1X; - dpfc_ctl |= DPFC_CTL_FENCE_EN | obj->fence_reg; - - I915_WRITE(DPFC_FENCE_YOFF, crtc->y); - - /* enable it... */ - I915_WRITE(DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); - - DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(intel_crtc->plane)); -} - -static void g4x_disable_fbc(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - u32 dpfc_ctl; - - dev_priv->fbc.enabled = false; - - /* Disable compression */ - dpfc_ctl = I915_READ(DPFC_CONTROL); - if (dpfc_ctl & DPFC_CTL_EN) { - dpfc_ctl &= ~DPFC_CTL_EN; - I915_WRITE(DPFC_CONTROL, dpfc_ctl); - - DRM_DEBUG_KMS("disabled FBC\n"); - } -} - -static bool g4x_fbc_enabled(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN; -} - -static void sandybridge_blit_fbc_update(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - u32 blt_ecoskpd; - - /* Make sure blitter notifies FBC of writes */ - - /* Blitter is part of Media powerwell on VLV. No impact of - * his param in other platforms for now */ - gen6_gt_force_wake_get(dev_priv, FORCEWAKE_MEDIA); - - blt_ecoskpd = I915_READ(GEN6_BLITTER_ECOSKPD); - blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY << - GEN6_BLITTER_LOCK_SHIFT; - I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd); - blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY; - I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd); - blt_ecoskpd &= ~(GEN6_BLITTER_FBC_NOTIFY << - GEN6_BLITTER_LOCK_SHIFT); - I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd); - POSTING_READ(GEN6_BLITTER_ECOSKPD); - - gen6_gt_force_wake_put(dev_priv, FORCEWAKE_MEDIA); -} - -static void ironlake_enable_fbc(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_framebuffer *fb = crtc->primary->fb; - struct drm_i915_gem_object *obj = intel_fb_obj(fb); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - u32 dpfc_ctl; - - dev_priv->fbc.enabled = true; - - dpfc_ctl = DPFC_CTL_PLANE(intel_crtc->plane); - if (drm_format_plane_cpp(fb->pixel_format, 0) == 2) - dev_priv->fbc.threshold++; - - switch (dev_priv->fbc.threshold) { - case 4: - case 3: - dpfc_ctl |= DPFC_CTL_LIMIT_4X; - break; - case 2: - dpfc_ctl |= DPFC_CTL_LIMIT_2X; - break; - case 1: - dpfc_ctl |= DPFC_CTL_LIMIT_1X; - break; - } - dpfc_ctl |= DPFC_CTL_FENCE_EN; - if (IS_GEN5(dev)) - dpfc_ctl |= obj->fence_reg; - - I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->y); - I915_WRITE(ILK_FBC_RT_BASE, i915_gem_obj_ggtt_offset(obj) | ILK_FBC_RT_VALID); - /* enable it... */ - I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); - - if (IS_GEN6(dev)) { - I915_WRITE(SNB_DPFC_CTL_SA, - SNB_CPU_FENCE_ENABLE | obj->fence_reg); - I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y); - sandybridge_blit_fbc_update(dev); - } - - DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(intel_crtc->plane)); -} - -static void ironlake_disable_fbc(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - u32 dpfc_ctl; - - dev_priv->fbc.enabled = false; - - /* Disable compression */ - dpfc_ctl = I915_READ(ILK_DPFC_CONTROL); - if (dpfc_ctl & DPFC_CTL_EN) { - dpfc_ctl &= ~DPFC_CTL_EN; - I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl); - - DRM_DEBUG_KMS("disabled FBC\n"); - } -} - -static bool ironlake_fbc_enabled(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN; -} - -static void gen7_enable_fbc(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_framebuffer *fb = crtc->primary->fb; - struct drm_i915_gem_object *obj = intel_fb_obj(fb); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - u32 dpfc_ctl; - - dev_priv->fbc.enabled = true; - - dpfc_ctl = IVB_DPFC_CTL_PLANE(intel_crtc->plane); - if (drm_format_plane_cpp(fb->pixel_format, 0) == 2) - dev_priv->fbc.threshold++; - - switch (dev_priv->fbc.threshold) { - case 4: - case 3: - dpfc_ctl |= DPFC_CTL_LIMIT_4X; - break; - case 2: - dpfc_ctl |= DPFC_CTL_LIMIT_2X; - break; - case 1: - dpfc_ctl |= DPFC_CTL_LIMIT_1X; - break; - } - - dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN; - - if (dev_priv->fbc.false_color) - dpfc_ctl |= FBC_CTL_FALSE_COLOR; - - I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); - - if (IS_IVYBRIDGE(dev)) { - /* WaFbcAsynchFlipDisableFbcQueue:ivb */ - I915_WRITE(ILK_DISPLAY_CHICKEN1, - I915_READ(ILK_DISPLAY_CHICKEN1) | - ILK_FBCQ_DIS); - } else { - /* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */ - I915_WRITE(CHICKEN_PIPESL_1(intel_crtc->pipe), - I915_READ(CHICKEN_PIPESL_1(intel_crtc->pipe)) | - HSW_FBCQ_DIS); - } - - I915_WRITE(SNB_DPFC_CTL_SA, - SNB_CPU_FENCE_ENABLE | obj->fence_reg); - I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y); - - sandybridge_blit_fbc_update(dev); - - DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(intel_crtc->plane)); -} - -bool intel_fbc_enabled(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - return dev_priv->fbc.enabled; -} - -void bdw_fbc_sw_flush(struct drm_device *dev, u32 value) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - if (!IS_GEN8(dev)) - return; - - if (!intel_fbc_enabled(dev)) - return; - - I915_WRITE(MSG_FBC_REND_STATE, value); -} - -static void intel_fbc_work_fn(struct work_struct *__work) -{ - struct intel_fbc_work *work = - container_of(to_delayed_work(__work), - struct intel_fbc_work, work); - struct drm_device *dev = work->crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - - mutex_lock(&dev->struct_mutex); - if (work == dev_priv->fbc.fbc_work) { - /* Double check that we haven't switched fb without cancelling - * the prior work. - */ - if (work->crtc->primary->fb == work->fb) { - dev_priv->display.enable_fbc(work->crtc); - - dev_priv->fbc.plane = to_intel_crtc(work->crtc)->plane; - dev_priv->fbc.fb_id = work->crtc->primary->fb->base.id; - dev_priv->fbc.y = work->crtc->y; - } - - dev_priv->fbc.fbc_work = NULL; - } - mutex_unlock(&dev->struct_mutex); - - kfree(work); -} - -static void intel_cancel_fbc_work(struct drm_i915_private *dev_priv) -{ - if (dev_priv->fbc.fbc_work == NULL) - return; - - DRM_DEBUG_KMS("cancelling pending FBC enable\n"); - - /* Synchronisation is provided by struct_mutex and checking of - * dev_priv->fbc.fbc_work, so we can perform the cancellation - * entirely asynchronously. - */ - if (cancel_delayed_work(&dev_priv->fbc.fbc_work->work)) - /* tasklet was killed before being run, clean up */ - kfree(dev_priv->fbc.fbc_work); - - /* Mark the work as no longer wanted so that if it does - * wake-up (because the work was already running and waiting - * for our mutex), it will discover that is no longer - * necessary to run. - */ - dev_priv->fbc.fbc_work = NULL; -} - -static void intel_enable_fbc(struct drm_crtc *crtc) -{ - struct intel_fbc_work *work; - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - - if (!dev_priv->display.enable_fbc) - return; - - intel_cancel_fbc_work(dev_priv); - - work = kzalloc(sizeof(*work), GFP_KERNEL); - if (work == NULL) { - DRM_ERROR("Failed to allocate FBC work structure\n"); - dev_priv->display.enable_fbc(crtc); - return; - } - - work->crtc = crtc; - work->fb = crtc->primary->fb; - INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn); - - dev_priv->fbc.fbc_work = work; - - /* Delay the actual enabling to let pageflipping cease and the - * display to settle before starting the compression. Note that - * this delay also serves a second purpose: it allows for a - * vblank to pass after disabling the FBC before we attempt - * to modify the control registers. - * - * A more complicated solution would involve tracking vblanks - * following the termination of the page-flipping sequence - * and indeed performing the enable as a co-routine and not - * waiting synchronously upon the vblank. - * - * WaFbcWaitForVBlankBeforeEnable:ilk,snb - */ - schedule_delayed_work(&work->work, msecs_to_jiffies(50)); -} - -void intel_disable_fbc(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - intel_cancel_fbc_work(dev_priv); - - if (!dev_priv->display.disable_fbc) - return; - - dev_priv->display.disable_fbc(dev); - dev_priv->fbc.plane = -1; -} - -static bool set_no_fbc_reason(struct drm_i915_private *dev_priv, - enum no_fbc_reason reason) -{ - if (dev_priv->fbc.no_fbc_reason == reason) - return false; - - dev_priv->fbc.no_fbc_reason = reason; - return true; -} - -/** - * intel_update_fbc - enable/disable FBC as needed - * @dev: the drm_device - * - * Set up the framebuffer compression hardware at mode set time. We - * enable it if possible: - * - plane A only (on pre-965) - * - no pixel mulitply/line duplication - * - no alpha buffer discard - * - no dual wide - * - framebuffer <= max_hdisplay in width, max_vdisplay in height - * - * We can't assume that any compression will take place (worst case), - * so the compressed buffer has to be the same size as the uncompressed - * one. It also must reside (along with the line length buffer) in - * stolen memory. - * - * We need to enable/disable FBC on a global basis. - */ -void intel_update_fbc(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_crtc *crtc = NULL, *tmp_crtc; - struct intel_crtc *intel_crtc; - struct drm_framebuffer *fb; - struct drm_i915_gem_object *obj; - const struct drm_display_mode *adjusted_mode; - unsigned int max_width, max_height; - - if (!HAS_FBC(dev)) { - set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED); - return; - } - - if (!i915.powersave) { - if (set_no_fbc_reason(dev_priv, FBC_MODULE_PARAM)) - DRM_DEBUG_KMS("fbc disabled per module param\n"); - return; - } - - /* - * If FBC is already on, we just have to verify that we can - * keep it that way... - * Need to disable if: - * - more than one pipe is active - * - changing FBC params (stride, fence, mode) - * - new fb is too large to fit in compressed buffer - * - going to an unsupported config (interlace, pixel multiply, etc.) - */ - for_each_crtc(dev, tmp_crtc) { - if (intel_crtc_active(tmp_crtc) && - to_intel_crtc(tmp_crtc)->primary_enabled) { - if (crtc) { - if (set_no_fbc_reason(dev_priv, FBC_MULTIPLE_PIPES)) - DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); - goto out_disable; - } - crtc = tmp_crtc; - } - } - - if (!crtc || crtc->primary->fb == NULL) { - if (set_no_fbc_reason(dev_priv, FBC_NO_OUTPUT)) - DRM_DEBUG_KMS("no output, disabling\n"); - goto out_disable; - } - - intel_crtc = to_intel_crtc(crtc); - fb = crtc->primary->fb; - obj = intel_fb_obj(fb); - adjusted_mode = &intel_crtc->config.adjusted_mode; - - if (i915.enable_fbc < 0) { - if (set_no_fbc_reason(dev_priv, FBC_CHIP_DEFAULT)) - DRM_DEBUG_KMS("disabled per chip default\n"); - goto out_disable; - } - if (!i915.enable_fbc) { - if (set_no_fbc_reason(dev_priv, FBC_MODULE_PARAM)) - DRM_DEBUG_KMS("fbc disabled per module param\n"); - goto out_disable; - } - if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) || - (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)) { - if (set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED_MODE)) - DRM_DEBUG_KMS("mode incompatible with compression, " - "disabling\n"); - goto out_disable; - } - - if (INTEL_INFO(dev)->gen >= 8 || IS_HASWELL(dev)) { - max_width = 4096; - max_height = 4096; - } else if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) { - max_width = 4096; - max_height = 2048; - } else { - max_width = 2048; - max_height = 1536; - } - if (intel_crtc->config.pipe_src_w > max_width || - intel_crtc->config.pipe_src_h > max_height) { - if (set_no_fbc_reason(dev_priv, FBC_MODE_TOO_LARGE)) - DRM_DEBUG_KMS("mode too large for compression, disabling\n"); - goto out_disable; - } - if ((INTEL_INFO(dev)->gen < 4 || HAS_DDI(dev)) && - intel_crtc->plane != PLANE_A) { - if (set_no_fbc_reason(dev_priv, FBC_BAD_PLANE)) - DRM_DEBUG_KMS("plane not A, disabling compression\n"); - goto out_disable; - } - - /* The use of a CPU fence is mandatory in order to detect writes - * by the CPU to the scanout and trigger updates to the FBC. - */ - if (obj->tiling_mode != I915_TILING_X || - obj->fence_reg == I915_FENCE_REG_NONE) { - if (set_no_fbc_reason(dev_priv, FBC_NOT_TILED)) - DRM_DEBUG_KMS("framebuffer not tiled or fenced, disabling compression\n"); - goto out_disable; - } - if (INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) && - to_intel_plane(crtc->primary)->rotation != BIT(DRM_ROTATE_0)) { - if (set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED_MODE)) - DRM_DEBUG_KMS("Rotation unsupported, disabling\n"); - goto out_disable; - } - - /* If the kernel debugger is active, always disable compression */ - if (in_dbg_master()) - goto out_disable; - - if (i915_gem_stolen_setup_compression(dev, obj->base.size, - drm_format_plane_cpp(fb->pixel_format, 0))) { - if (set_no_fbc_reason(dev_priv, FBC_STOLEN_TOO_SMALL)) - DRM_DEBUG_KMS("framebuffer too large, disabling compression\n"); - goto out_disable; - } - - /* If the scanout has not changed, don't modify the FBC settings. - * Note that we make the fundamental assumption that the fb->obj - * cannot be unpinned (and have its GTT offset and fence revoked) - * without first being decoupled from the scanout and FBC disabled. - */ - if (dev_priv->fbc.plane == intel_crtc->plane && - dev_priv->fbc.fb_id == fb->base.id && - dev_priv->fbc.y == crtc->y) - return; - - if (intel_fbc_enabled(dev)) { - /* We update FBC along two paths, after changing fb/crtc - * configuration (modeswitching) and after page-flipping - * finishes. For the latter, we know that not only did - * we disable the FBC at the start of the page-flip - * sequence, but also more than one vblank has passed. - * - * For the former case of modeswitching, it is possible - * to switch between two FBC valid configurations - * instantaneously so we do need to disable the FBC - * before we can modify its control registers. We also - * have to wait for the next vblank for that to take - * effect. However, since we delay enabling FBC we can - * assume that a vblank has passed since disabling and - * that we can safely alter the registers in the deferred - * callback. - * - * In the scenario that we go from a valid to invalid - * and then back to valid FBC configuration we have - * no strict enforcement that a vblank occurred since - * disabling the FBC. However, along all current pipe - * disabling paths we do need to wait for a vblank at - * some point. And we wait before enabling FBC anyway. - */ - DRM_DEBUG_KMS("disabling active FBC for update\n"); - intel_disable_fbc(dev); - } - - intel_enable_fbc(crtc); - dev_priv->fbc.no_fbc_reason = FBC_OK; - return; - -out_disable: - /* Multiple disables should be harmless */ - if (intel_fbc_enabled(dev)) { - DRM_DEBUG_KMS("unsupported config, disabling FBC\n"); - intel_disable_fbc(dev); - } - i915_gem_stolen_cleanup_compression(dev); -} static void i915_pineview_get_mem_freq(struct drm_device *dev) { @@ -6922,43 +6304,12 @@ void intel_suspend_hw(struct drm_device *dev) lpt_suspend_hw(dev); } -static void intel_init_fbc(struct drm_i915_private *dev_priv) -{ - if (!HAS_FBC(dev_priv)) { - dev_priv->fbc.enabled = false; - return; - } - - if (INTEL_INFO(dev_priv)->gen >= 7) { - dev_priv->display.fbc_enabled = ironlake_fbc_enabled; - dev_priv->display.enable_fbc = gen7_enable_fbc; - dev_priv->display.disable_fbc = ironlake_disable_fbc; - } else if (INTEL_INFO(dev_priv)->gen >= 5) { - dev_priv->display.fbc_enabled = ironlake_fbc_enabled; - dev_priv->display.enable_fbc = ironlake_enable_fbc; - dev_priv->display.disable_fbc = ironlake_disable_fbc; - } else if (IS_GM45(dev_priv)) { - dev_priv->display.fbc_enabled = g4x_fbc_enabled; - dev_priv->display.enable_fbc = g4x_enable_fbc; - dev_priv->display.disable_fbc = g4x_disable_fbc; - } else { - dev_priv->display.fbc_enabled = i8xx_fbc_enabled; - dev_priv->display.enable_fbc = i8xx_enable_fbc; - dev_priv->display.disable_fbc = i8xx_disable_fbc; - - /* This value was pulled out of someone's hat */ - I915_WRITE(FBC_CONTROL, 500 << FBC_CTL_INTERVAL_SHIFT); - } - - dev_priv->fbc.enabled = dev_priv->display.fbc_enabled(dev_priv->dev); -} - /* Set up chip specific power management-related functions */ void intel_init_pm(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - intel_init_fbc(dev_priv); + intel_fbc_init(dev_priv); /* For cxsr */ if (IS_PINEVIEW(dev)) diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index bc5834bba2ae86..c18e57d36c2cbd 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1004,7 +1004,7 @@ intel_post_enable_primary(struct drm_crtc *crtc) hsw_enable_ips(intel_crtc); mutex_lock(&dev->struct_mutex); - intel_update_fbc(dev); + intel_fbc_update(dev); mutex_unlock(&dev->struct_mutex); } @@ -1017,7 +1017,7 @@ intel_pre_disable_primary(struct drm_crtc *crtc) mutex_lock(&dev->struct_mutex); if (dev_priv->fbc.plane == intel_crtc->plane) - intel_disable_fbc(dev); + intel_fbc_disable(dev); mutex_unlock(&dev->struct_mutex); /* From 86ef630d53d6ae93f4a83fc3bfebaa111f8f83ce Mon Sep 17 00:00:00 2001 From: "Michael H. Nguyen" Date: Fri, 21 Nov 2014 09:35:36 -0800 Subject: [PATCH 0130/3023] drm/i915: Add MI_SET_APPID cmd to cmd parser tables Was missing. Issue: VIZ-4701 Signed-off-by: Michael H. Nguyen Reviewed-by: Jon Bloomfield Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_cmd_parser.c | 14 +++++++++++--- drivers/gpu/drm/i915/i915_reg.h | 3 +++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 6e9eac4b175790..b882bf2a238828 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -152,6 +152,7 @@ static const struct drm_i915_cmd_descriptor render_cmds[] = { CMD( MI_PREDICATE, SMI, F, 1, S ), CMD( MI_TOPOLOGY_FILTER, SMI, F, 1, S ), CMD( MI_DISPLAY_FLIP, SMI, !F, 0xFF, R ), + CMD( MI_SET_APPID, SMI, F, 1, S ), CMD( MI_SET_CONTEXT, SMI, !F, 0xFF, R ), CMD( MI_URB_CLEAR, SMI, !F, 0xFF, S ), CMD( MI_STORE_DWORD_IMM, SMI, !F, 0x3F, B, @@ -210,6 +211,7 @@ static const struct drm_i915_cmd_descriptor hsw_render_cmds[] = { CMD( MI_SET_PREDICATE, SMI, F, 1, S ), CMD( MI_RS_CONTROL, SMI, F, 1, S ), CMD( MI_URB_ATOMIC_ALLOC, SMI, F, 1, S ), + CMD( MI_SET_APPID, SMI, F, 1, S ), CMD( MI_RS_CONTEXT, SMI, F, 1, S ), CMD( MI_LOAD_SCAN_LINES_INCL, SMI, !F, 0x3F, M ), CMD( MI_LOAD_SCAN_LINES_EXCL, SMI, !F, 0x3F, R ), @@ -229,6 +231,7 @@ static const struct drm_i915_cmd_descriptor hsw_render_cmds[] = { static const struct drm_i915_cmd_descriptor video_cmds[] = { CMD( MI_ARB_ON_OFF, SMI, F, 1, R ), + CMD( MI_SET_APPID, SMI, F, 1, S ), CMD( MI_STORE_DWORD_IMM, SMI, !F, 0xFF, B, .bits = {{ .offset = 0, @@ -272,6 +275,7 @@ static const struct drm_i915_cmd_descriptor video_cmds[] = { static const struct drm_i915_cmd_descriptor vecs_cmds[] = { CMD( MI_ARB_ON_OFF, SMI, F, 1, R ), + CMD( MI_SET_APPID, SMI, F, 1, S ), CMD( MI_STORE_DWORD_IMM, SMI, !F, 0xFF, B, .bits = {{ .offset = 0, @@ -481,13 +485,17 @@ static u32 gen7_bsd_get_cmd_length_mask(u32 cmd_header) u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT; u32 subclient = (cmd_header & INSTR_SUBCLIENT_MASK) >> INSTR_SUBCLIENT_SHIFT; + u32 op = (cmd_header & INSTR_26_TO_24_MASK) >> INSTR_26_TO_24_SHIFT; if (client == INSTR_MI_CLIENT) return 0x3F; else if (client == INSTR_RC_CLIENT) { - if (subclient == INSTR_MEDIA_SUBCLIENT) - return 0xFFF; - else + if (subclient == INSTR_MEDIA_SUBCLIENT) { + if (op == 6) + return 0xFFFF; + else + return 0xFFF; + } else return 0xFF; } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 869e5ae1b011a0..aa628998f83601 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -207,6 +207,8 @@ #define INSTR_SUBCLIENT_SHIFT 27 #define INSTR_SUBCLIENT_MASK 0x18000000 #define INSTR_MEDIA_SUBCLIENT 0x2 +#define INSTR_26_TO_24_MASK 0x7000000 +#define INSTR_26_TO_24_SHIFT 24 /* * Memory interface instructions used by the kernel @@ -236,6 +238,7 @@ #define MI_BATCH_BUFFER_END MI_INSTR(0x0a, 0) #define MI_SUSPEND_FLUSH MI_INSTR(0x0b, 0) #define MI_SUSPEND_FLUSH_EN (1<<0) +#define MI_SET_APPID MI_INSTR(0x0e, 0) #define MI_OVERLAY_FLIP MI_INSTR(0x11, 0) #define MI_OVERLAY_CONTINUE (0x0<<21) #define MI_OVERLAY_ON (0x1<<21) From 3c860ab40cf1719977b78ef58942b9be46013319 Mon Sep 17 00:00:00 2001 From: Gaurav K Singh Date: Tue, 9 Dec 2014 10:57:00 +0530 Subject: [PATCH 0131/3023] drm/i915: Use DSI Pll1 for enabling MIPI DSI on Port C DSI Pll1 is used for enabling DSI on Port C. v2: Addressed review comments of Jani - Used & operator instead of == for intel_dsi->ports Signed-off-by: Gaurav K Singh Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dsi_pll.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c index 8957f1099a1f41..3622d0bafdf8ad 100644 --- a/drivers/gpu/drm/i915/intel_dsi_pll.c +++ b/drivers/gpu/drm/i915/intel_dsi_pll.c @@ -241,9 +241,10 @@ static void vlv_configure_dsi_pll(struct intel_encoder *encoder) return; } - dsi_mnp.dsi_pll_ctrl |= DSI_PLL_CLK_GATE_DSI0_DSIPLL; + if (intel_dsi->ports & (1 << PORT_A)) + dsi_mnp.dsi_pll_ctrl |= DSI_PLL_CLK_GATE_DSI0_DSIPLL; - if (intel_dsi->dual_link) + if (intel_dsi->ports & (1 << PORT_C)) dsi_mnp.dsi_pll_ctrl |= DSI_PLL_CLK_GATE_DSI1_DSIPLL; DRM_DEBUG_KMS("dsi pll div %08x, ctrl %08x\n", From bf344e8090110a70bd630563e1324b103bdfecb2 Mon Sep 17 00:00:00 2001 From: Gaurav K Singh Date: Sun, 7 Dec 2014 16:13:54 +0530 Subject: [PATCH 0132/3023] drm/i915: Enable MIPI PHY transparent latch for DSI Port C Common bit to be used for both DSI Port A & DSI Port C. Signed-off-by: Gaurav K Singh Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dsi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 8f8b952eaa9259..215d00429b0490 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -177,7 +177,12 @@ static void intel_dsi_device_ready(struct intel_encoder *encoder) usleep_range(2500, 3000); val = I915_READ(MIPI_PORT_CTRL(port)); - I915_WRITE(MIPI_PORT_CTRL(port), val | LP_OUTPUT_HOLD); + + /* Enable MIPI PHY transparent latch + * Common bit for both MIPI Port A & MIPI Port C + * No similar bit in MIPI Port C reg + */ + I915_WRITE(MIPI_PORT_CTRL(PORT_A), val | LP_OUTPUT_HOLD); usleep_range(1000, 1500); I915_WRITE(MIPI_DEVICE_READY(port), ULPS_STATE_EXIT); From c0beefd29fcb1ca998f0f9ba41be8539f8eeba9b Mon Sep 17 00:00:00 2001 From: Gaurav K Singh Date: Tue, 9 Dec 2014 10:59:20 +0530 Subject: [PATCH 0133/3023] drm/i915: Software workaround for getting the HW status of DSI Port C on BYT Due to hardware limitations on BYT, MIPI Port C DPI Enable bit does not get set. To check whether DSI Port C was enabled in BIOS, check the Pipe B enable bit for DSI Port C. In hardware, DSI Port C is linked with Pipe B. v2: Addressed review comments of Jani, Nikula - Used platform checks for this software workaround for BYT Signed-off-by: Gaurav K Singh Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dsi.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 215d00429b0490..42b6d6f5cecccb 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -398,8 +398,10 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; + struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); + struct drm_device *dev = encoder->base.dev; enum intel_display_power_domain power_domain; - u32 port_ctl, func; + u32 dpi_enabled, func; enum port port; DRM_DEBUG_KMS("\n"); @@ -409,13 +411,23 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, return false; /* XXX: this only works for one DSI output */ - for_each_dsi_port(port, (1 << PORT_A) | (1 << PORT_C)) { - port_ctl = I915_READ(MIPI_PORT_CTRL(port)); + for_each_dsi_port(port, intel_dsi->ports) { func = I915_READ(MIPI_DSI_FUNC_PRG(port)); + dpi_enabled = I915_READ(MIPI_PORT_CTRL(port)) & + DPI_ENABLE; + + /* Due to some hardware limitations on BYT, MIPI Port C DPI + * Enable bit does not get set. To check whether DSI Port C + * was enabled in BIOS, check the Pipe B enable bit + */ + if (IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && + (port == PORT_C)) + dpi_enabled = I915_READ(PIPECONF(PIPE_B)) & + PIPECONF_ENABLE; - if ((port_ctl & DPI_ENABLE) || (func & CMD_MODE_DATA_WIDTH_MASK)) { + if (dpi_enabled || (func & CMD_MODE_DATA_WIDTH_MASK)) { if (I915_READ(MIPI_DEVICE_READY(port)) & DEVICE_READY) { - *pipe = port == PORT_A ? PIPE_A : PIPE_C; + *pipe = port == PORT_A ? PIPE_A : PIPE_B; return true; } } From 94b8395755cca629d9f8fc66912cd56e13f35bf6 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Mon, 8 Dec 2014 06:46:31 -0800 Subject: [PATCH 0134/3023] drm/i915: Introduce FBC DocBook. No functional changes. v2 (Paulo): Rebase. v3: Accept Daniel's suggestions: * remove unclear and duplicated explanation. * remove marketing like doc and replace by a simple one. * remove bdw_fbc_sw_flush documentation. Signed-off-by: Rodrigo Vivi Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- Documentation/DocBook/drm.tmpl | 5 ++++ drivers/gpu/drm/i915/intel_fbc.c | 44 +++++++++++++++++++++++++------- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 56e2a9b65c6857..4fc5d730959b47 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -3924,6 +3924,11 @@ int num_ioctls; Panel Self Refresh PSR (PSR/SRD) !Pdrivers/gpu/drm/i915/intel_psr.c Panel Self Refresh (PSR/SRD) !Idrivers/gpu/drm/i915/intel_psr.c + + + Frame Buffer Compression (FBC) +!Pdrivers/gpu/drm/i915/intel_fbc.c Frame Buffer Compression (FBC) +!Idrivers/gpu/drm/i915/intel_fbc.c DPIO diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index f1eeb86a3d1bad..4daceaeeb30d09 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -21,20 +21,26 @@ * DEALINGS IN THE SOFTWARE. */ -#include "intel_drv.h" -#include "i915_drv.h" - -/* FBC, or Frame Buffer Compression, is a technique employed to compress the - * framebuffer contents in-memory, aiming at reducing the required bandwidth - * during in-memory transfers and, therefore, reduce the power packet. +/** + * DOC: Frame Buffer Compression (FBC) + * + * FBC tries to save memory bandwidth (and so power consumption) by + * compressing the amount of memory used by the display. It is total + * transparent to user space and completely handled in the kernel. * * The benefits of FBC are mostly visible with solid backgrounds and - * variation-less patterns. + * variation-less patterns. It comes from keeping the memory footprint small + * and having fewer memory pages opened and accessed for refreshing the display. * - * FBC-related functionality can be enabled by the means of the - * i915.i915_fbc_enable parameter + * i915 is responsible to reserve stolen memory for FBC and configure its + * offset on proper registers. The hardware takes care of all + * compress/decompress. However there are many known cases where we have to + * forcibly disable it to allow proper screen updates. */ +#include "intel_drv.h" +#include "i915_drv.h" + static void i8xx_fbc_disable(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -318,6 +324,14 @@ static void gen7_fbc_enable(struct drm_crtc *crtc) DRM_DEBUG_KMS("enabled fbc on plane %c\n", plane_name(intel_crtc->plane)); } +/** + * intel_fbc_enabled - Is FBC enabled? + * @dev: the drm_device + * + * This function is used to verify the current state of FBC. + * FIXME: This should be tracked in the plane config eventually + * instead of queried at runtime for most callers. + */ bool intel_fbc_enabled(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -429,6 +443,12 @@ static void intel_fbc_enable(struct drm_crtc *crtc) schedule_delayed_work(&work->work, msecs_to_jiffies(50)); } +/** + * intel_fbc_disable - disable FBC + * @dev: the drm_device + * + * This function disables FBC. + */ void intel_fbc_disable(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -643,6 +663,12 @@ void intel_fbc_update(struct drm_device *dev) i915_gem_stolen_cleanup_compression(dev); } +/** + * intel_fbc_init - Initialize FBC + * @dev_priv: the i915 device + * + * This function might be called during PM init process. + */ void intel_fbc_init(struct drm_i915_private *dev_priv) { if (!HAS_FBC(dev_priv)) { From 16e5ab14d7828c461c346e78f9ba1e9bdd0257aa Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Tue, 9 Dec 2014 17:23:22 +0000 Subject: [PATCH 0135/3023] drm/i915: Add headers to the various render state intel-gpu-tools now generates the render state with license headers and the version of i-g-t that generated the files. A similar patch was previously sent but wasn't actually generated with the make target so was lacking the i-g-t revision. So here another version before we totally forget about this. Cc: Armin Reese Cc: Mika Kuoppala Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_renderstate_gen6.c | 25 +++++++++++++++++++ drivers/gpu/drm/i915/intel_renderstate_gen7.c | 25 +++++++++++++++++++ drivers/gpu/drm/i915/intel_renderstate_gen8.c | 25 +++++++++++++++++++ drivers/gpu/drm/i915/intel_renderstate_gen9.c | 25 +++++++++++++++++++ 4 files changed, 100 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_renderstate_gen6.c b/drivers/gpu/drm/i915/intel_renderstate_gen6.c index 56c1429d8a60d2..11c8e7b3dd7c21 100644 --- a/drivers/gpu/drm/i915/intel_renderstate_gen6.c +++ b/drivers/gpu/drm/i915/intel_renderstate_gen6.c @@ -1,3 +1,28 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Generated by: intel-gpu-tools-1.8-220-g01153e7 + */ + #include "intel_renderstate.h" static const u32 gen6_null_state_relocs[] = { diff --git a/drivers/gpu/drm/i915/intel_renderstate_gen7.c b/drivers/gpu/drm/i915/intel_renderstate_gen7.c index 419e35a7b0ff39..655180646152bc 100644 --- a/drivers/gpu/drm/i915/intel_renderstate_gen7.c +++ b/drivers/gpu/drm/i915/intel_renderstate_gen7.c @@ -1,3 +1,28 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Generated by: intel-gpu-tools-1.8-220-g01153e7 + */ + #include "intel_renderstate.h" static const u32 gen7_null_state_relocs[] = { diff --git a/drivers/gpu/drm/i915/intel_renderstate_gen8.c b/drivers/gpu/drm/i915/intel_renderstate_gen8.c index 78011d73fa9f5a..95288a34c15dce 100644 --- a/drivers/gpu/drm/i915/intel_renderstate_gen8.c +++ b/drivers/gpu/drm/i915/intel_renderstate_gen8.c @@ -1,3 +1,28 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Generated by: intel-gpu-tools-1.8-220-g01153e7 + */ + #include "intel_renderstate.h" static const u32 gen8_null_state_relocs[] = { diff --git a/drivers/gpu/drm/i915/intel_renderstate_gen9.c b/drivers/gpu/drm/i915/intel_renderstate_gen9.c index 8750753738073a..16a7ec273bd94d 100644 --- a/drivers/gpu/drm/i915/intel_renderstate_gen9.c +++ b/drivers/gpu/drm/i915/intel_renderstate_gen9.c @@ -1,3 +1,28 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Generated by: intel-gpu-tools-1.8-220-g01153e7 + */ + #include "intel_renderstate.h" static const u32 gen9_null_state_relocs[] = { From eb736679aa7e6d6de647909fdf13075605927b3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 9 Dec 2014 21:28:28 +0200 Subject: [PATCH 0136/3023] drm/i915: Engage the DP scramble reset for pipe C on CHV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To get stable CRCs from the DP CRC source we need to reset the scrambler for each frame. Enable the reset feature when grabbing CRCs for pipe C on CHV. Pipes A and B were already covered due sharing the code with VLV. We can safely extend PIPE_SCRAMBLE_RESET_MASK to deal with CHV since the extra bit was MBZ on the older platforms. Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 27 ++++++++++++++++++++++----- drivers/gpu/drm/i915/i915_reg.h | 3 ++- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index d0e445eca9ce5f..d74b62d0ec72fb 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3120,11 +3120,19 @@ static int vlv_pipe_crc_ctl_reg(struct drm_device *dev, uint32_t tmp = I915_READ(PORT_DFT2_G4X); tmp |= DC_BALANCE_RESET_VLV; - if (pipe == PIPE_A) + switch (pipe) { + case PIPE_A: tmp |= PIPE_A_SCRAMBLE_RESET; - else + break; + case PIPE_B: tmp |= PIPE_B_SCRAMBLE_RESET; - + break; + case PIPE_C: + tmp |= PIPE_C_SCRAMBLE_RESET; + break; + default: + return -EINVAL; + } I915_WRITE(PORT_DFT2_G4X, tmp); } @@ -3213,10 +3221,19 @@ static void vlv_undo_pipe_scramble_reset(struct drm_device *dev, struct drm_i915_private *dev_priv = dev->dev_private; uint32_t tmp = I915_READ(PORT_DFT2_G4X); - if (pipe == PIPE_A) + switch (pipe) { + case PIPE_A: tmp &= ~PIPE_A_SCRAMBLE_RESET; - else + break; + case PIPE_B: tmp &= ~PIPE_B_SCRAMBLE_RESET; + break; + case PIPE_C: + tmp &= ~PIPE_C_SCRAMBLE_RESET; + break; + default: + return; + } if (!(tmp & PIPE_SCRAMBLE_RESET_MASK)) tmp &= ~DC_BALANCE_RESET_VLV; I915_WRITE(PORT_DFT2_G4X, tmp); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index aa628998f83601..451d526ea5d548 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2789,7 +2789,8 @@ enum punit_power_well { #define DC_BALANCE_RESET (1 << 25) #define PORT_DFT2_G4X (dev_priv->info.display_mmio_offset + 0x61154) #define DC_BALANCE_RESET_VLV (1 << 31) -#define PIPE_SCRAMBLE_RESET_MASK (0x3 << 0) +#define PIPE_SCRAMBLE_RESET_MASK ((1 << 14) | (0x3 << 0)) +#define PIPE_C_SCRAMBLE_RESET (1 << 14) /* chv */ #define PIPE_B_SCRAMBLE_RESET (1 << 1) #define PIPE_A_SCRAMBLE_RESET (1 << 0) From 2be57922d46fdec4360ced2eb108832c5a90bc0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 9 Dec 2014 21:28:29 +0200 Subject: [PATCH 0137/3023] drm/i915: Fix CRC support for DP port D on CHV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the missing CRC control register value for DP port D on CHV. Untested as I don't have a CHV machine with DP on port D. Signed-off-by: Ville Syrjälä [danvet: Add a check to only allow DP D on chv, not vlv.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index d74b62d0ec72fb..0779e7f33f4239 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3100,6 +3100,12 @@ static int vlv_pipe_crc_ctl_reg(struct drm_device *dev, *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_C_VLV; need_stable_symbols = true; break; + case INTEL_PIPE_CRC_SOURCE_DP_D: + if (!IS_CHERRYVIEW(dev)) + return -EINVAL; + *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_D_VLV; + need_stable_symbols = true; + break; case INTEL_PIPE_CRC_SOURCE_NONE: *val = 0; break; From 4252fbc3d4d3abd09ccc7598342cc930d09aac27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 9 Dec 2014 21:28:30 +0200 Subject: [PATCH 0138/3023] drm/i915: Protect pipe_crc->entries update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set the pipe_crc->entries pointer while holding the relevant spinlock. Doesn't matter too much since a spurious pipe crc interrupt would then just update one entry but later that entry would get cleared when head and tail are both set to 0. But being a bit more paranoid doesn't hurt. Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 0779e7f33f4239..218e27cb3e2fb2 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3410,13 +3410,15 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, /* none -> real source transition */ if (source) { + struct intel_pipe_crc_entry *entries; + DRM_DEBUG_DRIVER("collecting CRCs for pipe %c, %s\n", pipe_name(pipe), pipe_crc_source_name(source)); - pipe_crc->entries = kzalloc(sizeof(*pipe_crc->entries) * - INTEL_PIPE_CRC_ENTRIES_NR, - GFP_KERNEL); - if (!pipe_crc->entries) + entries = kzalloc(sizeof(*pipe_crc->entries) * + INTEL_PIPE_CRC_ENTRIES_NR, + GFP_KERNEL); + if (!entries) return -ENOMEM; /* @@ -3428,6 +3430,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, hsw_disable_ips(crtc); spin_lock_irq(&pipe_crc->lock); + pipe_crc->entries = entries; pipe_crc->head = 0; pipe_crc->tail = 0; spin_unlock_irq(&pipe_crc->lock); From 3cf54b34dafe800d9522b93249b6f4c1bfb50de2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 9 Dec 2014 21:28:31 +0200 Subject: [PATCH 0139/3023] drm/i915: Allocate the pipe_crc->entires with kcalloc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pipe_crc->entries[] is an array so allocate with kcalloc() instead of kzalloc(). Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 218e27cb3e2fb2..95829ebecf21b8 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3415,8 +3415,8 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, DRM_DEBUG_DRIVER("collecting CRCs for pipe %c, %s\n", pipe_name(pipe), pipe_crc_source_name(source)); - entries = kzalloc(sizeof(*pipe_crc->entries) * - INTEL_PIPE_CRC_ENTRIES_NR, + entries = kcalloc(INTEL_PIPE_CRC_ENTRIES_NR, + sizeof(pipe_crc->entries[0]), GFP_KERNEL); if (!entries) return -ENOMEM; From 9ad6d99f189c274b42bedd6efc2b31a17ce733a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 9 Dec 2014 21:28:32 +0200 Subject: [PATCH 0140/3023] drm/i915: Make i915_pipe_crc_read() oops proof MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently i915_pipe_crc_read() will drop pipe_crc->lock for the entire duration of the copy_to_user() loop, which means it'll access pipe_crc->entries without any protection. If another thread sneaks in and frees pipe_crc->entries the code will oops. Reorganize the code to hold the lock around everything except copy_to_user(). After the copy the lock is reacquired and the the number of available entries is rechecked. Since this is a debug feature simplify the error handling a bit by consuming the crc entry even if copy_to_user() would fail. Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 39 ++++++++++++++++------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 95829ebecf21b8..252b0b2b514cad 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2858,7 +2858,7 @@ i915_pipe_crc_read(struct file *filep, char __user *user_buf, size_t count, struct drm_i915_private *dev_priv = dev->dev_private; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe]; char buf[PIPE_CRC_BUFFER_LEN]; - int head, tail, n_entries, n; + int n_entries; ssize_t bytes_read; /* @@ -2890,36 +2890,39 @@ i915_pipe_crc_read(struct file *filep, char __user *user_buf, size_t count, } /* We now have one or more entries to read */ - head = pipe_crc->head; - tail = pipe_crc->tail; - n_entries = min((size_t)CIRC_CNT(head, tail, INTEL_PIPE_CRC_ENTRIES_NR), - count / PIPE_CRC_LINE_LEN); - spin_unlock_irq(&pipe_crc->lock); + n_entries = count / PIPE_CRC_LINE_LEN; bytes_read = 0; - n = 0; - do { - struct intel_pipe_crc_entry *entry = &pipe_crc->entries[tail]; + while (n_entries > 0) { + struct intel_pipe_crc_entry *entry = + &pipe_crc->entries[pipe_crc->tail]; int ret; + if (CIRC_CNT(pipe_crc->head, pipe_crc->tail, + INTEL_PIPE_CRC_ENTRIES_NR) < 1) + break; + + BUILD_BUG_ON_NOT_POWER_OF_2(INTEL_PIPE_CRC_ENTRIES_NR); + pipe_crc->tail = (pipe_crc->tail + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1); + bytes_read += snprintf(buf, PIPE_CRC_BUFFER_LEN, "%8u %8x %8x %8x %8x %8x\n", entry->frame, entry->crc[0], entry->crc[1], entry->crc[2], entry->crc[3], entry->crc[4]); - ret = copy_to_user(user_buf + n * PIPE_CRC_LINE_LEN, - buf, PIPE_CRC_LINE_LEN); + spin_unlock_irq(&pipe_crc->lock); + + ret = copy_to_user(user_buf, buf, PIPE_CRC_LINE_LEN); if (ret == PIPE_CRC_LINE_LEN) return -EFAULT; - BUILD_BUG_ON_NOT_POWER_OF_2(INTEL_PIPE_CRC_ENTRIES_NR); - tail = (tail + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1); - n++; - } while (--n_entries); + user_buf += PIPE_CRC_LINE_LEN; + n_entries--; + + spin_lock_irq(&pipe_crc->lock); + } - spin_lock_irq(&pipe_crc->lock); - pipe_crc->tail = tail; spin_unlock_irq(&pipe_crc->lock); return bytes_read; @@ -3458,6 +3461,8 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, spin_lock_irq(&pipe_crc->lock); entries = pipe_crc->entries; pipe_crc->entries = NULL; + pipe_crc->head = 0; + pipe_crc->tail = 0; spin_unlock_irq(&pipe_crc->lock); kfree(entries); From 64387b613a43713d0e03d9d43bfbb1727e8475e1 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 10 Dec 2014 11:00:29 +0100 Subject: [PATCH 0141/3023] drm/i915: Protect against leaks in pipe_crc_set_source MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stupid userspace (there is no evil userspace in debugfs by assumption) might provoke a leak since we allocate the new array without holding any locks. Drop in an unconditional kfree to deal with this - kfree can handle NULL. Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 252b0b2b514cad..165a38f3600984 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3433,6 +3433,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, hsw_disable_ips(crtc); spin_lock_irq(&pipe_crc->lock); + kfree(pipe_crc->entries); pipe_crc->entries = entries; pipe_crc->head = 0; pipe_crc->tail = 0; From 1a2520582ec7e7f802a4a22b6ff6db8e49cf6929 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 10 Dec 2014 09:43:37 +0000 Subject: [PATCH 0142/3023] drm/i915/bdw: Add WaForceEnableNonCoherent label MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We already implement this workaround, but it was missing its name. Reviewed-by: Ville Syrjälä Signed-off-by: Michel Thierry Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index a8dc158f33be90..f1ce16997a7959 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -782,6 +782,7 @@ static int bdw_init_workarounds(struct intel_engine_cs *ring) * workaround for for a possible hang in the unlikely event a TLB * invalidation occurs during a PSD flush. */ + /* WaForceEnableNonCoherent:bdw */ /* WaHdcDisableFetchWhenMasked:bdw */ /* WaDisableFenceDestinationToSLM:bdw (GT3 pre-production) */ WA_SET_BIT_MASKED(HDC_CHICKEN0, From ae28290be3871969fc3f64b480d42575a16ae990 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 10 Dec 2014 12:17:41 -0500 Subject: [PATCH 0143/3023] drm: bit of spell-check / editorializing. Signed-off-by: Rob Clark Signed-off-by: Daniel Vetter --- include/uapi/drm/drm_mode.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 86574b0005ff0a..aae71cb32123ee 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -338,7 +338,7 @@ struct drm_mode_fb_cmd2 { /* * In case of planar formats, this ioctl allows up to 4 - * buffer objects with offets and pitches per plane. + * buffer objects with offsets and pitches per plane. * The pitch and offset order is dictated by the fourcc, * e.g. NV12 (http://fourcc.org/yuv.php#NV12) is described as: * @@ -346,9 +346,9 @@ struct drm_mode_fb_cmd2 { * followed by an interleaved U/V plane containing * 8 bit 2x2 subsampled colour difference samples. * - * So it would consist of Y as offset[0] and UV as - * offeset[1]. Note that offset[0] will generally - * be 0. + * So it would consist of Y as offsets[0] and UV as + * offsets[1]. Note that offsets[0] will generally + * be 0 (but this is not required). */ __u32 handles[4]; __u32 pitches[4]; /* pitch for each plane */ From c631c7156fc6dc50758ad99b5600c1eebd88c6a6 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 10 Dec 2014 21:11:31 +0200 Subject: [PATCH 0144/3023] drm/doc: Document drm_add_modes_noedid() usage And fix a spelling mistake. Signed-off-by: Laurent Pinchart Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter --- Documentation/DocBook/drm.tmpl | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index b344bc3b0d77ce..3e212b90351075 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -1947,10 +1947,16 @@ void intel_crt_init(struct drm_device *dev) and then retrieves a list of modes by calling the connector get_modes helper operation. + + If the helper operation returns no mode, and if the connector status + is connector_status_connected, standard VESA DMT modes up to + 1024x768 are automatically added to the modes list by a call to + drm_add_modes_noedid. + - The function filters out modes larger than + The function then filters out modes larger than max_width and max_height - if specified. It then calls the optional connector + if specified. It finally calls the optional connector mode_valid helper operation for each mode in the probed list to check whether the mode is valid for the connector. @@ -2090,11 +2096,19 @@ void intel_crt_init(struct drm_device *dev) int (*get_modes)(struct drm_connector *connector); Fill the connector's probed_modes list - by parsing EDID data with drm_add_edid_modes or - calling drm_mode_probed_add directly for every + by parsing EDID data with drm_add_edid_modes, + adding standard VESA DMT modes with drm_add_modes_noedid, + or calling drm_mode_probed_add directly for every supported mode and return the number of modes it has detected. This operation is mandatory. + + Note that the caller function will automatically add standard VESA + DMT modes up to 1024x768 if the get_modes + helper operation returns no mode and if the connector status is + connector_status_connected. There is no need to call + drm_add_edid_modes manually in that case. + When adding modes manually the driver creates each mode with a call to drm_mode_create and must fill the following fields. @@ -2292,7 +2306,7 @@ void intel_crt_init(struct drm_device *dev) drm_helper_probe_single_connector_modes. - When parsing EDID data, drm_add_edid_modes fill the + When parsing EDID data, drm_add_edid_modes fills the connector display_info width_mm and height_mm fields. When creating modes From 7432ca5acec8a24a7e576c92d28449e2d790b734 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Thu, 11 Dec 2014 07:20:57 -0800 Subject: [PATCH 0145/3023] drm/plane-helper: Test for plane disable earlier drm_plane_helper_check_update() currently uses crtc before testing whether we're disabling the plane (fb == NULL). Move the fb test before the first crtc usage so that crtc == NULL doesn't have to be handled by the caller. Signed-off-by: Matt Roper Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_plane_helper.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index 18a1ac6ac22f39..391dfb7d1086e8 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -142,6 +142,17 @@ int drm_plane_helper_check_update(struct drm_plane *plane, { int hscale, vscale; + if (!fb) { + *visible = false; + return 0; + } + + /* crtc should only be NULL when disabling (i.e., !fb) */ + if (WARN_ON(!crtc)) { + *visible = false; + return 0; + } + if (!crtc->enabled && !can_update_disabled) { DRM_DEBUG_KMS("Cannot update plane of a disabled CRTC.\n"); return -EINVAL; @@ -155,11 +166,6 @@ int drm_plane_helper_check_update(struct drm_plane *plane, return -ERANGE; } - if (!fb) { - *visible = false; - return 0; - } - *visible = drm_rect_clip_scaled(src, dest, clip, hscale, vscale); if (!*visible) /* From 286f74c2533ac44419819bb3c885ab9f6291d2c3 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Fri, 21 Nov 2014 10:45:48 -0800 Subject: [PATCH 0146/3023] iio: ak8975: add definition structure per compass type For each type of compass supported (AK8975 and AK8963), add a definition structure for register masks, important registers, raw data interpretation. This change will make integrating new type of devices easier. Remove i2c register cache. It is only used for one single register. Signed-off-by: Gwendal Grignou Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/ak8975.c | 281 ++++++++++++++++++++---------- 1 file changed, 186 insertions(+), 95 deletions(-) diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 4e69480e67b5c1..0f86a8e72034b9 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -86,13 +86,155 @@ #define AK8975_MAX_CONVERSION_TIMEOUT 500 #define AK8975_CONVERSION_DONE_POLL_TIME 10 #define AK8975_DATA_READY_TIMEOUT ((100*HZ)/1000) -#define RAW_TO_GAUSS_8975(asa) ((((asa) + 128) * 3000) / 256) -#define RAW_TO_GAUSS_8963(asa) ((((asa) + 128) * 6000) / 256) + +/* + * Precalculate scale factor (in Gauss units) for each axis and + * store in the device data. + * + * This scale factor is axis-dependent, and is derived from 3 calibration + * factors ASA(x), ASA(y), and ASA(z). + * + * These ASA values are read from the sensor device at start of day, and + * cached in the device context struct. + * + * Adjusting the flux value with the sensitivity adjustment value should be + * done via the following formula: + * + * Hadj = H * ( ( ( (ASA-128)*0.5 ) / 128 ) + 1 ) + * where H is the raw value, ASA is the sensitivity adjustment, and Hadj + * is the resultant adjusted value. + * + * We reduce the formula to: + * + * Hadj = H * (ASA + 128) / 256 + * + * H is in the range of -4096 to 4095. The magnetometer has a range of + * +-1229uT. To go from the raw value to uT is: + * + * HuT = H * 1229/4096, or roughly, 3/10. + * + * Since 1uT = 0.01 gauss, our final scale factor becomes: + * + * Hadj = H * ((ASA + 128) / 256) * 3/10 * 1/100 + * Hadj = H * ((ASA + 128) * 0.003) / 256 + * + * Since ASA doesn't change, we cache the resultant scale factor into the + * device context in ak8975_setup(). + * + * Given we use IIO_VAL_INT_PLUS_MICRO bit when displaying the scale, we + * multiply the stored scale value by 1e6. + */ +static long ak8975_raw_to_gauss(u16 data) +{ + return (((long)data + 128) * 3000) / 256; +} + +/* + * For AK8963, same calculation, but the device is less sensitive: + * + * H is in the range of +-8190. The magnetometer has a range of + * +-4912uT. To go from the raw value to uT is: + * + * HuT = H * 4912/8190, or roughly, 6/10, instead of 3/10. + */ +static long ak8963_raw_to_gauss(u16 data) +{ + return (((long)data + 128) * 6000) / 256; +} /* Compatible Asahi Kasei Compass parts */ enum asahi_compass_chipset { AK8975, AK8963, + AK_MAX_TYPE +}; + +enum ak_ctrl_reg_addr { + ST1, + ST2, + CNTL, + ASA_BASE, + MAX_REGS, + REGS_END, +}; + +enum ak_ctrl_reg_mask { + ST1_DRDY, + ST2_HOFL, + ST2_DERR, + CNTL_MODE, + MASK_END, +}; + +enum ak_ctrl_mode { + POWER_DOWN, + MODE_ONCE, + SELF_TEST, + FUSE_ROM, + MODE_END, +}; + +struct ak_def { + enum asahi_compass_chipset type; + long (*raw_to_gauss)(u16 data); + u16 range; + u8 ctrl_regs[REGS_END]; + u8 ctrl_masks[MASK_END]; + u8 ctrl_modes[MODE_END]; + u8 data_regs[3]; +}; + +static struct ak_def ak_def_array[AK_MAX_TYPE] = { + { + .type = AK8975, + .raw_to_gauss = ak8975_raw_to_gauss, + .range = 4096, + .ctrl_regs = { + AK8975_REG_ST1, + AK8975_REG_ST2, + AK8975_REG_CNTL, + AK8975_REG_ASAX, + AK8975_MAX_REGS}, + .ctrl_masks = { + AK8975_REG_ST1_DRDY_MASK, + AK8975_REG_ST2_HOFL_MASK, + AK8975_REG_ST2_DERR_MASK, + AK8975_REG_CNTL_MODE_MASK}, + .ctrl_modes = { + AK8975_REG_CNTL_MODE_POWER_DOWN, + AK8975_REG_CNTL_MODE_ONCE, + AK8975_REG_CNTL_MODE_SELF_TEST, + AK8975_REG_CNTL_MODE_FUSE_ROM}, + .data_regs = { + AK8975_REG_HXL, + AK8975_REG_HYL, + AK8975_REG_HZL}, + }, + { + .type = AK8963, + .raw_to_gauss = ak8963_raw_to_gauss, + .range = 8190, + .ctrl_regs = { + AK8975_REG_ST1, + AK8975_REG_ST2, + AK8975_REG_CNTL, + AK8975_REG_ASAX, + AK8975_MAX_REGS}, + .ctrl_masks = { + AK8975_REG_ST1_DRDY_MASK, + AK8975_REG_ST2_HOFL_MASK, + 0, + AK8975_REG_CNTL_MODE_MASK}, + .ctrl_modes = { + AK8975_REG_CNTL_MODE_POWER_DOWN, + AK8975_REG_CNTL_MODE_ONCE, + AK8975_REG_CNTL_MODE_SELF_TEST, + AK8975_REG_CNTL_MODE_FUSE_ROM}, + .data_regs = { + AK8975_REG_HXL, + AK8975_REG_HYL, + AK8975_REG_HZL}, + }, }; /* @@ -100,40 +242,36 @@ enum asahi_compass_chipset { */ struct ak8975_data { struct i2c_client *client; + struct ak_def *def; struct attribute_group attrs; struct mutex lock; u8 asa[3]; long raw_to_gauss[3]; - u8 reg_cache[AK8975_MAX_REGS]; int eoc_gpio; int eoc_irq; wait_queue_head_t data_ready_queue; unsigned long flags; - enum asahi_compass_chipset chipset; -}; - -static const int ak8975_index_to_reg[] = { - AK8975_REG_HXL, AK8975_REG_HYL, AK8975_REG_HZL, + u8 cntl_cache; }; /* - * Helper function to write to the I2C device's registers. + * Helper function to write to CNTL register. */ -static int ak8975_write_data(struct i2c_client *client, - u8 reg, u8 val, u8 mask, u8 shift) +static int ak8975_set_mode(struct ak8975_data *data, enum ak_ctrl_mode mode) { - struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct ak8975_data *data = iio_priv(indio_dev); u8 regval; int ret; - regval = (data->reg_cache[reg] & ~mask) | (val << shift); - ret = i2c_smbus_write_byte_data(client, reg, regval); + regval = (data->cntl_cache & ~data->def->ctrl_masks[CNTL_MODE]) | + data->def->ctrl_modes[mode]; + ret = i2c_smbus_write_byte_data(data->client, + data->def->ctrl_regs[CNTL], regval); if (ret < 0) { - dev_err(&client->dev, "Write to device fails status %x\n", ret); return ret; } - data->reg_cache[reg] = regval; + data->cntl_cache = regval; + /* After mode change wait atleast 100us */ + usleep_range(100, 500); return 0; } @@ -207,18 +345,15 @@ static int ak8975_setup(struct i2c_client *client) } /* Write the fused rom access mode. */ - ret = ak8975_write_data(client, - AK8975_REG_CNTL, - AK8975_REG_CNTL_MODE_FUSE_ROM, - AK8975_REG_CNTL_MODE_MASK, - AK8975_REG_CNTL_MODE_SHIFT); + ret = ak8975_set_mode(data, FUSE_ROM); if (ret < 0) { dev_err(&client->dev, "Error in setting fuse access mode\n"); return ret; } /* Get asa data and store in the device data. */ - ret = i2c_smbus_read_i2c_block_data(client, AK8975_REG_ASAX, + ret = i2c_smbus_read_i2c_block_data(client, + data->def->ctrl_regs[ASA_BASE], 3, data->asa); if (ret < 0) { dev_err(&client->dev, "Not able to read asa data\n"); @@ -226,11 +361,7 @@ static int ak8975_setup(struct i2c_client *client) } /* After reading fuse ROM data set power-down mode */ - ret = ak8975_write_data(client, - AK8975_REG_CNTL, - AK8975_REG_CNTL_MODE_POWER_DOWN, - AK8975_REG_CNTL_MODE_MASK, - AK8975_REG_CNTL_MODE_SHIFT); + ret = ak8975_set_mode(data, POWER_DOWN); if (ret < 0) { dev_err(&client->dev, "Error in setting power-down mode\n"); return ret; @@ -245,56 +376,9 @@ static int ak8975_setup(struct i2c_client *client) } } -/* - * Precalculate scale factor (in Gauss units) for each axis and - * store in the device data. - * - * This scale factor is axis-dependent, and is derived from 3 calibration - * factors ASA(x), ASA(y), and ASA(z). - * - * These ASA values are read from the sensor device at start of day, and - * cached in the device context struct. - * - * Adjusting the flux value with the sensitivity adjustment value should be - * done via the following formula: - * - * Hadj = H * ( ( ( (ASA-128)*0.5 ) / 128 ) + 1 ) - * - * where H is the raw value, ASA is the sensitivity adjustment, and Hadj - * is the resultant adjusted value. - * - * We reduce the formula to: - * - * Hadj = H * (ASA + 128) / 256 - * - * H is in the range of -4096 to 4095. The magnetometer has a range of - * +-1229uT. To go from the raw value to uT is: - * - * HuT = H * 1229/4096, or roughly, 3/10. - * - * Since 1uT = 0.01 gauss, our final scale factor becomes: - * - * Hadj = H * ((ASA + 128) / 256) * 3/10 * 1/100 - * Hadj = H * ((ASA + 128) * 0.003) / 256 - * - * Since ASA doesn't change, we cache the resultant scale factor into the - * device context in ak8975_setup(). - */ - if (data->chipset == AK8963) { - /* - * H range is +-8190 and magnetometer range is +-4912. - * So HuT using the above explanation for 8975, - * 4912/8190 = ~ 6/10. - * So the Hadj should use 6/10 instead of 3/10. - */ - data->raw_to_gauss[0] = RAW_TO_GAUSS_8963(data->asa[0]); - data->raw_to_gauss[1] = RAW_TO_GAUSS_8963(data->asa[1]); - data->raw_to_gauss[2] = RAW_TO_GAUSS_8963(data->asa[2]); - } else { - data->raw_to_gauss[0] = RAW_TO_GAUSS_8975(data->asa[0]); - data->raw_to_gauss[1] = RAW_TO_GAUSS_8975(data->asa[1]); - data->raw_to_gauss[2] = RAW_TO_GAUSS_8975(data->asa[2]); - } + data->raw_to_gauss[0] = data->def->raw_to_gauss(data->asa[0]); + data->raw_to_gauss[1] = data->def->raw_to_gauss(data->asa[1]); + data->raw_to_gauss[2] = data->def->raw_to_gauss(data->asa[2]); return 0; } @@ -317,7 +401,7 @@ static int wait_conversion_complete_gpio(struct ak8975_data *data) return -EINVAL; } - ret = i2c_smbus_read_byte_data(client, AK8975_REG_ST1); + ret = i2c_smbus_read_byte_data(client, data->def->ctrl_regs[ST1]); if (ret < 0) dev_err(&client->dev, "Error in reading ST1\n"); @@ -334,7 +418,8 @@ static int wait_conversion_complete_polled(struct ak8975_data *data) /* Wait for the conversion to complete. */ while (timeout_ms) { msleep(AK8975_CONVERSION_DONE_POLL_TIME); - ret = i2c_smbus_read_byte_data(client, AK8975_REG_ST1); + ret = i2c_smbus_read_byte_data(client, + data->def->ctrl_regs[ST1]); if (ret < 0) { dev_err(&client->dev, "Error in reading ST1\n"); return ret; @@ -377,11 +462,7 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) mutex_lock(&data->lock); /* Set up the device for taking a sample. */ - ret = ak8975_write_data(client, - AK8975_REG_CNTL, - AK8975_REG_CNTL_MODE_ONCE, - AK8975_REG_CNTL_MODE_MASK, - AK8975_REG_CNTL_MODE_SHIFT); + ret = ak8975_set_mode(data, MODE_ONCE); if (ret < 0) { dev_err(&client->dev, "Error in setting operating mode\n"); goto exit; @@ -398,14 +479,15 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) goto exit; /* This will be executed only for non-interrupt based waiting case */ - if (ret & AK8975_REG_ST1_DRDY_MASK) { - ret = i2c_smbus_read_byte_data(client, AK8975_REG_ST2); + if (ret & data->def->ctrl_masks[ST1_DRDY]) { + ret = i2c_smbus_read_byte_data(client, + data->def->ctrl_regs[ST2]); if (ret < 0) { dev_err(&client->dev, "Error in reading ST2\n"); goto exit; } - if (ret & (AK8975_REG_ST2_DERR_MASK | - AK8975_REG_ST2_HOFL_MASK)) { + if (ret & (data->def->ctrl_masks[ST2_DERR] | + data->def->ctrl_masks[ST2_HOFL])) { dev_err(&client->dev, "ST2 status error 0x%x\n", ret); ret = -EINVAL; goto exit; @@ -414,7 +496,7 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) /* Read the flux value from the appropriate register (the register is specified in the iio device attributes). */ - ret = i2c_smbus_read_word_data(client, ak8975_index_to_reg[index]); + ret = i2c_smbus_read_word_data(client, data->def->data_regs[index]); if (ret < 0) { dev_err(&client->dev, "Read axis data fails\n"); goto exit; @@ -423,7 +505,7 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) mutex_unlock(&data->lock); /* Clamp to valid range. */ - *val = clamp_t(s16, ret, -4096, 4095); + *val = clamp_t(s16, ret, -data->def->range, data->def->range); return IIO_VAL_INT; exit: @@ -497,6 +579,7 @@ static int ak8975_probe(struct i2c_client *client, int eoc_gpio; int err; const char *name = NULL; + enum asahi_compass_chipset chipset; /* Grab and set up the supplied GPIO. */ if (client->dev.platform_data) @@ -536,14 +619,20 @@ static int ak8975_probe(struct i2c_client *client, /* id will be NULL when enumerated via ACPI */ if (id) { - data->chipset = - (enum asahi_compass_chipset)(id->driver_data); + chipset = (enum asahi_compass_chipset)(id->driver_data); name = id->name; } else if (ACPI_HANDLE(&client->dev)) - name = ak8975_match_acpi_device(&client->dev, &data->chipset); + name = ak8975_match_acpi_device(&client->dev, &chipset); else return -ENOSYS; + if (chipset >= AK_MAX_TYPE) { + dev_err(&client->dev, "AKM device type unsupported: %d\n", + chipset); + return -ENODEV; + } + + data->def = &ak_def_array[chipset]; dev_dbg(&client->dev, "Asahi compass chip %s\n", name); /* Perform some basic start-of-day setup of the device. */ @@ -574,7 +663,9 @@ MODULE_DEVICE_TABLE(i2c, ak8975_id); static const struct of_device_id ak8975_of_match[] = { { .compatible = "asahi-kasei,ak8975", }, { .compatible = "ak8975", }, - { } + { .compatible = "asahi-kasei,ak8963", }, + { .compatible = "ak8963", }, + {} }; MODULE_DEVICE_TABLE(of, ak8975_of_match); From 57e73a423b1e85f9b1b0f58e10d38ec00d0c8489 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Fri, 21 Nov 2014 10:45:49 -0800 Subject: [PATCH 0147/3023] iio: ak8975: add ak09911 and ak09912 support Add 2 new definition entries to support ak0991x compass. Add a more advanced function to check we are dealing with the expected device. Remove standalone driver for ak09911. Signed-off-by: Gwendal Grignou Tested-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/Kconfig | 15 +- drivers/iio/magnetometer/Makefile | 1 - drivers/iio/magnetometer/ak09911.c | 326 ----------------------------- drivers/iio/magnetometer/ak8975.c | 196 +++++++++++++++-- 4 files changed, 185 insertions(+), 353 deletions(-) delete mode 100644 drivers/iio/magnetometer/ak09911.c diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig index b2dba9e506ab12..4c7a4c52dd06bf 100644 --- a/drivers/iio/magnetometer/Kconfig +++ b/drivers/iio/magnetometer/Kconfig @@ -6,26 +6,21 @@ menu "Magnetometer sensors" config AK8975 - tristate "Asahi Kasei AK8975 3-Axis Magnetometer" + tristate "Asahi Kasei AK 3-Axis Magnetometer" depends on I2C depends on GPIOLIB help - Say yes here to build support for Asahi Kasei AK8975 3-Axis - Magnetometer. This driver can also support AK8963, if i2c - device name is identified as ak8963. + Say yes here to build support for Asahi Kasei AK8975, AK8963, + AK09911 or AK09912 3-Axis Magnetometer. To compile this driver as a module, choose M here: the module will be called ak8975. config AK09911 tristate "Asahi Kasei AK09911 3-axis Compass" - depends on I2C + select AK8975 help - Say yes here to build support for Asahi Kasei AK09911 3-Axis - Magnetometer. - - To compile this driver as a module, choose M here: the module - will be called ak09911. + Deprecated: AK09911 is now supported by AK8975 driver. config MAG3110 tristate "Freescale MAG3110 3-Axis Magnetometer" diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile index b91315e0b82669..0f5d3c98579924 100644 --- a/drivers/iio/magnetometer/Makefile +++ b/drivers/iio/magnetometer/Makefile @@ -3,7 +3,6 @@ # # When adding new entries keep the list in alphabetical order -obj-$(CONFIG_AK09911) += ak09911.o obj-$(CONFIG_AK8975) += ak8975.o obj-$(CONFIG_MAG3110) += mag3110.o obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o diff --git a/drivers/iio/magnetometer/ak09911.c b/drivers/iio/magnetometer/ak09911.c deleted file mode 100644 index b2bc942ff6b811..00000000000000 --- a/drivers/iio/magnetometer/ak09911.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - * AK09911 3-axis compass driver - * Copyright (c) 2014, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define AK09911_REG_WIA1 0x00 -#define AK09911_REG_WIA2 0x01 -#define AK09911_WIA1_VALUE 0x48 -#define AK09911_WIA2_VALUE 0x05 - -#define AK09911_REG_ST1 0x10 -#define AK09911_REG_HXL 0x11 -#define AK09911_REG_HXH 0x12 -#define AK09911_REG_HYL 0x13 -#define AK09911_REG_HYH 0x14 -#define AK09911_REG_HZL 0x15 -#define AK09911_REG_HZH 0x16 - -#define AK09911_REG_ASAX 0x60 -#define AK09911_REG_ASAY 0x61 -#define AK09911_REG_ASAZ 0x62 - -#define AK09911_REG_CNTL1 0x30 -#define AK09911_REG_CNTL2 0x31 -#define AK09911_REG_CNTL3 0x32 - -#define AK09911_MODE_SNG_MEASURE 0x01 -#define AK09911_MODE_SELF_TEST 0x10 -#define AK09911_MODE_FUSE_ACCESS 0x1F -#define AK09911_MODE_POWERDOWN 0x00 -#define AK09911_RESET_DATA 0x01 - -#define AK09911_REG_CNTL1 0x30 -#define AK09911_REG_CNTL2 0x31 -#define AK09911_REG_CNTL3 0x32 - -#define AK09911_RAW_TO_GAUSS(asa) ((((asa) + 128) * 6000) / 256) - -#define AK09911_MAX_CONVERSION_TIMEOUT_MS 500 -#define AK09911_CONVERSION_DONE_POLL_TIME_MS 10 - -struct ak09911_data { - struct i2c_client *client; - struct mutex lock; - u8 asa[3]; - long raw_to_gauss[3]; -}; - -static const int ak09911_index_to_reg[] = { - AK09911_REG_HXL, AK09911_REG_HYL, AK09911_REG_HZL, -}; - -static int ak09911_set_mode(struct i2c_client *client, u8 mode) -{ - int ret; - - switch (mode) { - case AK09911_MODE_SNG_MEASURE: - case AK09911_MODE_SELF_TEST: - case AK09911_MODE_FUSE_ACCESS: - case AK09911_MODE_POWERDOWN: - ret = i2c_smbus_write_byte_data(client, - AK09911_REG_CNTL2, mode); - if (ret < 0) { - dev_err(&client->dev, "set_mode error\n"); - return ret; - } - /* After mode change wait atleast 100us */ - usleep_range(100, 500); - break; - default: - dev_err(&client->dev, - "%s: Unknown mode(%d).", __func__, mode); - return -EINVAL; - } - - return ret; -} - -/* Get Sensitivity Adjustment value */ -static int ak09911_get_asa(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct ak09911_data *data = iio_priv(indio_dev); - int ret; - - ret = ak09911_set_mode(client, AK09911_MODE_FUSE_ACCESS); - if (ret < 0) - return ret; - - /* Get asa data and store in the device data. */ - ret = i2c_smbus_read_i2c_block_data(client, AK09911_REG_ASAX, - 3, data->asa); - if (ret < 0) { - dev_err(&client->dev, "Not able to read asa data\n"); - return ret; - } - - ret = ak09911_set_mode(client, AK09911_MODE_POWERDOWN); - if (ret < 0) - return ret; - - data->raw_to_gauss[0] = AK09911_RAW_TO_GAUSS(data->asa[0]); - data->raw_to_gauss[1] = AK09911_RAW_TO_GAUSS(data->asa[1]); - data->raw_to_gauss[2] = AK09911_RAW_TO_GAUSS(data->asa[2]); - - return 0; -} - -static int ak09911_verify_chip_id(struct i2c_client *client) -{ - u8 wia_val[2]; - int ret; - - ret = i2c_smbus_read_i2c_block_data(client, AK09911_REG_WIA1, - 2, wia_val); - if (ret < 0) { - dev_err(&client->dev, "Error reading WIA\n"); - return ret; - } - - dev_dbg(&client->dev, "WIA %02x %02x\n", wia_val[0], wia_val[1]); - - if (wia_val[0] != AK09911_WIA1_VALUE || - wia_val[1] != AK09911_WIA2_VALUE) { - dev_err(&client->dev, "Device ak09911 not found\n"); - return -ENODEV; - } - - return 0; -} - -static int wait_conversion_complete_polled(struct ak09911_data *data) -{ - struct i2c_client *client = data->client; - u8 read_status; - u32 timeout_ms = AK09911_MAX_CONVERSION_TIMEOUT_MS; - int ret; - - /* Wait for the conversion to complete. */ - while (timeout_ms) { - msleep_interruptible(AK09911_CONVERSION_DONE_POLL_TIME_MS); - ret = i2c_smbus_read_byte_data(client, AK09911_REG_ST1); - if (ret < 0) { - dev_err(&client->dev, "Error in reading ST1\n"); - return ret; - } - read_status = ret & 0x01; - if (read_status) - break; - timeout_ms -= AK09911_CONVERSION_DONE_POLL_TIME_MS; - } - if (!timeout_ms) { - dev_err(&client->dev, "Conversion timeout happened\n"); - return -EIO; - } - - return read_status; -} - -static int ak09911_read_axis(struct iio_dev *indio_dev, int index, int *val) -{ - struct ak09911_data *data = iio_priv(indio_dev); - struct i2c_client *client = data->client; - int ret; - - mutex_lock(&data->lock); - - ret = ak09911_set_mode(client, AK09911_MODE_SNG_MEASURE); - if (ret < 0) - goto fn_exit; - - ret = wait_conversion_complete_polled(data); - if (ret < 0) - goto fn_exit; - - /* Read data */ - ret = i2c_smbus_read_word_data(client, ak09911_index_to_reg[index]); - if (ret < 0) { - dev_err(&client->dev, "Read axis data fails\n"); - goto fn_exit; - } - - mutex_unlock(&data->lock); - - /* Clamp to valid range. */ - *val = sign_extend32(clamp_t(s16, ret, -8192, 8191), 13); - - return IIO_VAL_INT; - -fn_exit: - mutex_unlock(&data->lock); - - return ret; -} - -static int ak09911_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) -{ - struct ak09911_data *data = iio_priv(indio_dev); - - switch (mask) { - case IIO_CHAN_INFO_RAW: - return ak09911_read_axis(indio_dev, chan->address, val); - case IIO_CHAN_INFO_SCALE: - *val = 0; - *val2 = data->raw_to_gauss[chan->address]; - return IIO_VAL_INT_PLUS_MICRO; - } - - return -EINVAL; -} - -#define AK09911_CHANNEL(axis, index) \ - { \ - .type = IIO_MAGN, \ - .modified = 1, \ - .channel2 = IIO_MOD_##axis, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ - BIT(IIO_CHAN_INFO_SCALE), \ - .address = index, \ - } - -static const struct iio_chan_spec ak09911_channels[] = { - AK09911_CHANNEL(X, 0), AK09911_CHANNEL(Y, 1), AK09911_CHANNEL(Z, 2), -}; - -static const struct iio_info ak09911_info = { - .read_raw = &ak09911_read_raw, - .driver_module = THIS_MODULE, -}; - -static const struct acpi_device_id ak_acpi_match[] = { - {"AK009911", 0}, - { }, -}; -MODULE_DEVICE_TABLE(acpi, ak_acpi_match); - -static int ak09911_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct iio_dev *indio_dev; - struct ak09911_data *data; - const char *name; - int ret; - - ret = ak09911_verify_chip_id(client); - if (ret) { - dev_err(&client->dev, "AK00911 not detected\n"); - return -ENODEV; - } - - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); - if (indio_dev == NULL) - return -ENOMEM; - - data = iio_priv(indio_dev); - i2c_set_clientdata(client, indio_dev); - - data->client = client; - mutex_init(&data->lock); - - ret = ak09911_get_asa(client); - if (ret) - return ret; - - if (id) - name = id->name; - else if (ACPI_HANDLE(&client->dev)) - name = dev_name(&client->dev); - else - return -ENODEV; - - dev_dbg(&client->dev, "Asahi compass chip %s\n", name); - - indio_dev->dev.parent = &client->dev; - indio_dev->channels = ak09911_channels; - indio_dev->num_channels = ARRAY_SIZE(ak09911_channels); - indio_dev->info = &ak09911_info; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->name = name; - - return devm_iio_device_register(&client->dev, indio_dev); -} - -static const struct i2c_device_id ak09911_id[] = { - {"ak09911", 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, ak09911_id); - -static struct i2c_driver ak09911_driver = { - .driver = { - .name = "ak09911", - .acpi_match_table = ACPI_PTR(ak_acpi_match), - }, - .probe = ak09911_probe, - .id_table = ak09911_id, -}; -module_i2c_driver(ak09911_driver); - -MODULE_AUTHOR("Srinivas Pandruvada "); -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("AK09911 Compass driver"); diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 0f86a8e72034b9..0d10a4baceb673 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -80,6 +80,58 @@ #define AK8975_MAX_REGS AK8975_REG_ASAZ +/* + * AK09912 Register definitions + */ +#define AK09912_REG_WIA1 0x00 +#define AK09912_REG_WIA2 0x01 +#define AK09912_DEVICE_ID 0x04 +#define AK09911_DEVICE_ID 0x05 + +#define AK09911_REG_INFO1 0x02 +#define AK09911_REG_INFO2 0x03 + +#define AK09912_REG_ST1 0x10 + +#define AK09912_REG_ST1_DRDY_SHIFT 0 +#define AK09912_REG_ST1_DRDY_MASK (1 << AK09912_REG_ST1_DRDY_SHIFT) + +#define AK09912_REG_HXL 0x11 +#define AK09912_REG_HXH 0x12 +#define AK09912_REG_HYL 0x13 +#define AK09912_REG_HYH 0x14 +#define AK09912_REG_HZL 0x15 +#define AK09912_REG_HZH 0x16 +#define AK09912_REG_TMPS 0x17 + +#define AK09912_REG_ST2 0x18 +#define AK09912_REG_ST2_HOFL_SHIFT 3 +#define AK09912_REG_ST2_HOFL_MASK (1 << AK09912_REG_ST2_HOFL_SHIFT) + +#define AK09912_REG_CNTL1 0x30 + +#define AK09912_REG_CNTL2 0x31 +#define AK09912_REG_CNTL_MODE_POWER_DOWN 0x00 +#define AK09912_REG_CNTL_MODE_ONCE 0x01 +#define AK09912_REG_CNTL_MODE_SELF_TEST 0x10 +#define AK09912_REG_CNTL_MODE_FUSE_ROM 0x1F +#define AK09912_REG_CNTL2_MODE_SHIFT 0 +#define AK09912_REG_CNTL2_MODE_MASK (0x1F << AK09912_REG_CNTL2_MODE_SHIFT) + +#define AK09912_REG_CNTL3 0x32 + +#define AK09912_REG_TS1 0x33 +#define AK09912_REG_TS2 0x34 +#define AK09912_REG_TS3 0x35 +#define AK09912_REG_I2CDIS 0x36 +#define AK09912_REG_TS4 0x37 + +#define AK09912_REG_ASAX 0x60 +#define AK09912_REG_ASAY 0x61 +#define AK09912_REG_ASAZ 0x62 + +#define AK09912_MAX_REGS AK09912_REG_ASAZ + /* * Miscellaneous values. */ @@ -130,22 +182,38 @@ static long ak8975_raw_to_gauss(u16 data) } /* - * For AK8963, same calculation, but the device is less sensitive: + * For AK8963 and AK09911, same calculation, but the device is less sensitive: * * H is in the range of +-8190. The magnetometer has a range of * +-4912uT. To go from the raw value to uT is: * * HuT = H * 4912/8190, or roughly, 6/10, instead of 3/10. */ -static long ak8963_raw_to_gauss(u16 data) + +static long ak8963_09911_raw_to_gauss(u16 data) { return (((long)data + 128) * 6000) / 256; } +/* + * For AK09912, same calculation, except the device is more sensitive: + * + * H is in the range of -32752 to 32752. The magnetometer has a range of + * +-4912uT. To go from the raw value to uT is: + * + * HuT = H * 4912/32752, or roughly, 3/20, instead of 3/10. + */ +static long ak09912_raw_to_gauss(u16 data) +{ + return (((long)data + 128) * 1500) / 256; +} + /* Compatible Asahi Kasei Compass parts */ enum asahi_compass_chipset { AK8975, AK8963, + AK09911, + AK09912, AK_MAX_TYPE }; @@ -212,7 +280,7 @@ static struct ak_def ak_def_array[AK_MAX_TYPE] = { }, { .type = AK8963, - .raw_to_gauss = ak8963_raw_to_gauss, + .raw_to_gauss = ak8963_09911_raw_to_gauss, .range = 8190, .ctrl_regs = { AK8975_REG_ST1, @@ -235,6 +303,56 @@ static struct ak_def ak_def_array[AK_MAX_TYPE] = { AK8975_REG_HYL, AK8975_REG_HZL}, }, + { + .type = AK09911, + .raw_to_gauss = ak8963_09911_raw_to_gauss, + .range = 8192, + .ctrl_regs = { + AK09912_REG_ST1, + AK09912_REG_ST2, + AK09912_REG_CNTL2, + AK09912_REG_ASAX, + AK09912_MAX_REGS}, + .ctrl_masks = { + AK09912_REG_ST1_DRDY_MASK, + AK09912_REG_ST2_HOFL_MASK, + 0, + AK09912_REG_CNTL2_MODE_MASK}, + .ctrl_modes = { + AK09912_REG_CNTL_MODE_POWER_DOWN, + AK09912_REG_CNTL_MODE_ONCE, + AK09912_REG_CNTL_MODE_SELF_TEST, + AK09912_REG_CNTL_MODE_FUSE_ROM}, + .data_regs = { + AK09912_REG_HXL, + AK09912_REG_HYL, + AK09912_REG_HZL}, + }, + { + .type = AK09912, + .raw_to_gauss = ak09912_raw_to_gauss, + .range = 32752, + .ctrl_regs = { + AK09912_REG_ST1, + AK09912_REG_ST2, + AK09912_REG_CNTL2, + AK09912_REG_ASAX, + AK09912_MAX_REGS}, + .ctrl_masks = { + AK09912_REG_ST1_DRDY_MASK, + AK09912_REG_ST2_HOFL_MASK, + 0, + AK09912_REG_CNTL2_MODE_MASK}, + .ctrl_modes = { + AK09912_REG_CNTL_MODE_POWER_DOWN, + AK09912_REG_CNTL_MODE_ONCE, + AK09912_REG_CNTL_MODE_SELF_TEST, + AK09912_REG_CNTL_MODE_FUSE_ROM}, + .data_regs = { + AK09912_REG_HXL, + AK09912_REG_HYL, + AK09912_REG_HZL}, + } }; /* @@ -254,6 +372,52 @@ struct ak8975_data { u8 cntl_cache; }; +/* + * Return 0 if the i2c device is the one we expect. + * return a negative error number otherwise + */ +static int ak8975_who_i_am(struct i2c_client *client, + enum asahi_compass_chipset type) +{ + u8 wia_val[2]; + int ret; + + /* + * Signature for each device: + * Device | WIA1 | WIA2 + * AK09912 | DEVICE_ID | AK09912_DEVICE_ID + * AK09911 | DEVICE_ID | AK09911_DEVICE_ID + * AK8975 | DEVICE_ID | NA + * AK8963 | DEVICE_ID | NA + */ + ret = i2c_smbus_read_i2c_block_data(client, AK09912_REG_WIA1, + 2, wia_val); + if (ret < 0) { + dev_err(&client->dev, "Error reading WIA\n"); + return ret; + } + + if (wia_val[0] != AK8975_DEVICE_ID) + return -ENODEV; + + switch (type) { + case AK8975: + case AK8963: + return 0; + case AK09911: + if (wia_val[1] == AK09911_DEVICE_ID) + return 0; + break; + case AK09912: + if (wia_val[1] == AK09912_DEVICE_ID) + return 0; + break; + default: + dev_err(&client->dev, "Type %d unknown\n", type); + } + return -ENODEV; +} + /* * Helper function to write to CNTL register. */ @@ -329,21 +493,8 @@ static int ak8975_setup(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); struct ak8975_data *data = iio_priv(indio_dev); - u8 device_id; int ret; - /* Confirm that the device we're talking to is really an AK8975. */ - ret = i2c_smbus_read_byte_data(client, AK8975_REG_WIA); - if (ret < 0) { - dev_err(&client->dev, "Error reading WIA\n"); - return ret; - } - device_id = ret; - if (device_id != AK8975_DEVICE_ID) { - dev_err(&client->dev, "Device ak8975 not found\n"); - return -ENODEV; - } - /* Write the fused rom access mode. */ ret = ak8975_set_mode(data, FUSE_ROM); if (ret < 0) { @@ -554,6 +705,8 @@ static const struct acpi_device_id ak_acpi_match[] = { {"AK8975", AK8975}, {"AK8963", AK8963}, {"INVN6500", AK8963}, + {"AK09911", AK09911}, + {"AK09912", AK09912}, { }, }; MODULE_DEVICE_TABLE(acpi, ak_acpi_match); @@ -633,6 +786,11 @@ static int ak8975_probe(struct i2c_client *client, } data->def = &ak_def_array[chipset]; + err = ak8975_who_i_am(client, data->def->type); + if (err < 0) { + dev_err(&client->dev, "Unexpected device\n"); + return err; + } dev_dbg(&client->dev, "Asahi compass chip %s\n", name); /* Perform some basic start-of-day setup of the device. */ @@ -655,6 +813,8 @@ static int ak8975_probe(struct i2c_client *client, static const struct i2c_device_id ak8975_id[] = { {"ak8975", AK8975}, {"ak8963", AK8963}, + {"ak09911", AK09911}, + {"ak09912", AK09912}, {} }; @@ -665,6 +825,10 @@ static const struct of_device_id ak8975_of_match[] = { { .compatible = "ak8975", }, { .compatible = "asahi-kasei,ak8963", }, { .compatible = "ak8963", }, + { .compatible = "asahi-kasei,ak09911", }, + { .compatible = "ak09911", }, + { .compatible = "asahi-kasei,ak09912", }, + { .compatible = "ak09912", }, {} }; MODULE_DEVICE_TABLE(of, ak8975_of_match); From 8f6eb02596cc297c12ee16c86b9bbe1c186dda15 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Sun, 16 Nov 2014 13:33:24 +0100 Subject: [PATCH 0148/3023] iio: common: remove unnecessary sizeof(u8) sizeof(u8) is always 1. Signed-off-by: Fabian Frederick Acked-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/common/st_sensors/st_sensors_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/common/st_sensors/st_sensors_spi.c b/drivers/iio/common/st_sensors/st_sensors_spi.c index 78a6a1ab3ece00..5b377373f48d14 100644 --- a/drivers/iio/common/st_sensors/st_sensors_spi.c +++ b/drivers/iio/common/st_sensors/st_sensors_spi.c @@ -54,7 +54,7 @@ static int st_sensors_spi_read(struct st_sensor_transfer_buffer *tb, if (err) goto acc_spi_read_error; - memcpy(data, tb->rx_buf, len*sizeof(u8)); + memcpy(data, tb->rx_buf, len); mutex_unlock(&tb->buf_lock); return len; From 0f8994b18afc47fd0cda20ba6162c21a093173da Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Thu, 20 Nov 2014 14:00:48 +0200 Subject: [PATCH 0149/3023] iio: bmp280: refactor compensation code This version of the code avoids extra memory copy operations and is somewhat smaller in code size. Signed-off-by: Vlad Dogaru Acked-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/bmp280.c | 140 +++++++++++++--------------------- 1 file changed, 52 insertions(+), 88 deletions(-) diff --git a/drivers/iio/pressure/bmp280.c b/drivers/iio/pressure/bmp280.c index 75038dacfff184..47dfd347f66f88 100644 --- a/drivers/iio/pressure/bmp280.c +++ b/drivers/iio/pressure/bmp280.c @@ -80,16 +80,12 @@ struct bmp280_data { s32 t_fine; }; -/* Compensation parameters. */ -struct bmp280_comp_temp { - u16 dig_t1; - s16 dig_t2, dig_t3; -}; - -struct bmp280_comp_press { - u16 dig_p1; - s16 dig_p2, dig_p3, dig_p4, dig_p5, dig_p6, dig_p7, dig_p8, dig_p9; -}; +/* + * These enums are used for indexing into the array of compensation + * parameters. + */ +enum { T1, T2, T3 }; +enum { P1, P2, P3, P4, P5, P6, P7, P8, P9 }; static const struct iio_chan_spec bmp280_channels[] = { { @@ -141,54 +137,6 @@ static const struct regmap_config bmp280_regmap_config = { .volatile_reg = bmp280_is_volatile_reg, }; -static int bmp280_read_compensation_temp(struct bmp280_data *data, - struct bmp280_comp_temp *comp) -{ - int ret; - __le16 buf[BMP280_COMP_TEMP_REG_COUNT / 2]; - - ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_TEMP_START, - buf, BMP280_COMP_TEMP_REG_COUNT); - if (ret < 0) { - dev_err(&data->client->dev, - "failed to read temperature calibration parameters\n"); - return ret; - } - - comp->dig_t1 = (u16) le16_to_cpu(buf[0]); - comp->dig_t2 = (s16) le16_to_cpu(buf[1]); - comp->dig_t3 = (s16) le16_to_cpu(buf[2]); - - return 0; -} - -static int bmp280_read_compensation_press(struct bmp280_data *data, - struct bmp280_comp_press *comp) -{ - int ret; - __le16 buf[BMP280_COMP_PRESS_REG_COUNT / 2]; - - ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_PRESS_START, - buf, BMP280_COMP_PRESS_REG_COUNT); - if (ret < 0) { - dev_err(&data->client->dev, - "failed to read pressure calibration parameters\n"); - return ret; - } - - comp->dig_p1 = (u16) le16_to_cpu(buf[0]); - comp->dig_p2 = (s16) le16_to_cpu(buf[1]); - comp->dig_p3 = (s16) le16_to_cpu(buf[2]); - comp->dig_p4 = (s16) le16_to_cpu(buf[3]); - comp->dig_p5 = (s16) le16_to_cpu(buf[4]); - comp->dig_p6 = (s16) le16_to_cpu(buf[5]); - comp->dig_p7 = (s16) le16_to_cpu(buf[6]); - comp->dig_p8 = (s16) le16_to_cpu(buf[7]); - comp->dig_p9 = (s16) le16_to_cpu(buf[8]); - - return 0; -} - /* * Returns temperature in DegC, resolution is 0.01 DegC. Output value of * "5123" equals 51.23 DegC. t_fine carries fine temperature as global @@ -197,16 +145,33 @@ static int bmp280_read_compensation_press(struct bmp280_data *data, * Taken from datasheet, Section 3.11.3, "Compensation formula". */ static s32 bmp280_compensate_temp(struct bmp280_data *data, - struct bmp280_comp_temp *comp, s32 adc_temp) { + int ret; s32 var1, var2, t; + __le16 buf[BMP280_COMP_TEMP_REG_COUNT / 2]; + + ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_TEMP_START, + buf, BMP280_COMP_TEMP_REG_COUNT); + if (ret < 0) { + dev_err(&data->client->dev, + "failed to read temperature calibration parameters\n"); + return ret; + } - var1 = (((adc_temp >> 3) - ((s32) comp->dig_t1 << 1)) * - ((s32) comp->dig_t2)) >> 11; - var2 = (((((adc_temp >> 4) - ((s32) comp->dig_t1)) * - ((adc_temp >> 4) - ((s32) comp->dig_t1))) >> 12) * - ((s32) comp->dig_t3)) >> 14; + /* + * The double casts are necessary because le16_to_cpu returns an + * unsigned 16-bit value. Casting that value directly to a + * signed 32-bit will not do proper sign extension. + * + * Conversely, T1 and P1 are unsigned values, so they can be + * cast straight to the larger type. + */ + var1 = (((adc_temp >> 3) - ((s32)le16_to_cpu(buf[T1]) << 1)) * + ((s32)(s16)le16_to_cpu(buf[T2]))) >> 11; + var2 = (((((adc_temp >> 4) - ((s32)le16_to_cpu(buf[T1]))) * + ((adc_temp >> 4) - ((s32)le16_to_cpu(buf[T1])))) >> 12) * + ((s32)(s16)le16_to_cpu(buf[T3]))) >> 14; data->t_fine = var1 + var2; t = (data->t_fine * 5 + 128) >> 8; @@ -222,27 +187,36 @@ static s32 bmp280_compensate_temp(struct bmp280_data *data, * Taken from datasheet, Section 3.11.3, "Compensation formula". */ static u32 bmp280_compensate_press(struct bmp280_data *data, - struct bmp280_comp_press *comp, s32 adc_press) { + int ret; s64 var1, var2, p; + __le16 buf[BMP280_COMP_PRESS_REG_COUNT / 2]; + + ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_PRESS_START, + buf, BMP280_COMP_PRESS_REG_COUNT); + if (ret < 0) { + dev_err(&data->client->dev, + "failed to read pressure calibration parameters\n"); + return ret; + } - var1 = ((s64) data->t_fine) - 128000; - var2 = var1 * var1 * (s64) comp->dig_p6; - var2 = var2 + ((var1 * (s64) comp->dig_p5) << 17); - var2 = var2 + (((s64) comp->dig_p4) << 35); - var1 = ((var1 * var1 * (s64) comp->dig_p3) >> 8) + - ((var1 * (s64) comp->dig_p2) << 12); - var1 = (((((s64) 1) << 47) + var1)) * ((s64) comp->dig_p1) >> 33; + var1 = ((s64)data->t_fine) - 128000; + var2 = var1 * var1 * (s64)(s16)le16_to_cpu(buf[P6]); + var2 = var2 + ((var1 * (s64)(s16)le16_to_cpu(buf[P5])) << 17); + var2 = var2 + (((s64)(s16)le16_to_cpu(buf[P4])) << 35); + var1 = ((var1 * var1 * (s64)(s16)le16_to_cpu(buf[P3])) >> 8) + + ((var1 * (s64)(s16)le16_to_cpu(buf[P2])) << 12); + var1 = ((((s64)1) << 47) + var1) * ((s64)le16_to_cpu(buf[P1])) >> 33; if (var1 == 0) return 0; - p = ((((s64) 1048576 - adc_press) << 31) - var2) * 3125; + p = ((((s64)1048576 - adc_press) << 31) - var2) * 3125; p = div64_s64(p, var1); - var1 = (((s64) comp->dig_p9) * (p >> 13) * (p >> 13)) >> 25; - var2 = (((s64) comp->dig_p8) * p) >> 19; - p = ((p + var1 + var2) >> 8) + (((s64) comp->dig_p7) << 4); + var1 = (((s64)(s16)le16_to_cpu(buf[P9])) * (p >> 13) * (p >> 13)) >> 25; + var2 = (((s64)(s16)le16_to_cpu(buf[P8])) * p) >> 19; + p = ((p + var1 + var2) >> 8) + (((s64)(s16)le16_to_cpu(buf[P7])) << 4); return (u32) p; } @@ -253,11 +227,6 @@ static int bmp280_read_temp(struct bmp280_data *data, int ret; __be32 tmp = 0; s32 adc_temp, comp_temp; - struct bmp280_comp_temp comp; - - ret = bmp280_read_compensation_temp(data, &comp); - if (ret < 0) - return ret; ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB, (u8 *) &tmp, 3); @@ -267,7 +236,7 @@ static int bmp280_read_temp(struct bmp280_data *data, } adc_temp = be32_to_cpu(tmp) >> 12; - comp_temp = bmp280_compensate_temp(data, &comp, adc_temp); + comp_temp = bmp280_compensate_temp(data, adc_temp); /* * val might be NULL if we're called by the read_press routine, @@ -288,11 +257,6 @@ static int bmp280_read_press(struct bmp280_data *data, __be32 tmp = 0; s32 adc_press; u32 comp_press; - struct bmp280_comp_press comp; - - ret = bmp280_read_compensation_press(data, &comp); - if (ret < 0) - return ret; /* Read and compensate temperature so we get a reading of t_fine. */ ret = bmp280_read_temp(data, NULL); @@ -307,7 +271,7 @@ static int bmp280_read_press(struct bmp280_data *data, } adc_press = be32_to_cpu(tmp) >> 12; - comp_press = bmp280_compensate_press(data, &comp, adc_press); + comp_press = bmp280_compensate_press(data, adc_press); *val = comp_press; *val2 = 256000; From 3a2ecc3d2dce6e051b6afc319bb380c829e4e4fd Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Fri, 5 Dec 2014 14:52:09 -0800 Subject: [PATCH 0150/3023] iio: imu: inv_mpu6050: Add i2c mux for by pass This chip allows some limited number of sensors connected to it as slaves, which can be directly accessed by register interface of this driver.But the current upstream driver doesn't support such mode. To attach such slaves to main processor i2c bus, chip has to be set up in bypass mode. This change adds i2c mux, which will enable/disable this mode for transaction to/from such slave devices. This was discussed for a while in mailing list, this was the outcome: Reference: http://www.spinics.net/lists/linux-iio/msg12126.html http://comments.gmane.org/gmane.linux.kernel.iio/11470 Signed-off-by: Srinivas Pandruvada Reviewed-by: Wolfram Sang Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/Kconfig | 1 + drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 115 +++++++++++++++++++-- drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 6 ++ 3 files changed, 116 insertions(+), 6 deletions(-) diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig index 2d0608ba88d7d6..48fbc0bc7e2a1d 100644 --- a/drivers/iio/imu/inv_mpu6050/Kconfig +++ b/drivers/iio/imu/inv_mpu6050/Kconfig @@ -7,6 +7,7 @@ config INV_MPU6050_IIO depends on I2C && SYSFS select IIO_BUFFER select IIO_TRIGGERED_BUFFER + select I2C_MUX help This driver supports the Invensense MPU6050 devices. This driver can also support MPU6500 in MPU6050 compatibility mode diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index b75519deac1a8f..6d2c115f39b4c6 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "inv_mpu_iio.h" /* @@ -52,6 +53,7 @@ static const struct inv_mpu6050_reg_map reg_set_6050 = { .int_enable = INV_MPU6050_REG_INT_ENABLE, .pwr_mgmt_1 = INV_MPU6050_REG_PWR_MGMT_1, .pwr_mgmt_2 = INV_MPU6050_REG_PWR_MGMT_2, + .int_pin_cfg = INV_MPU6050_REG_INT_PIN_CFG, }; static const struct inv_mpu6050_chip_config chip_config_6050 = { @@ -77,6 +79,83 @@ int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 d) return i2c_smbus_write_i2c_block_data(st->client, reg, 1, &d); } +/* + * The i2c read/write needs to happen in unlocked mode. As the parent + * adapter is common. If we use locked versions, it will fail as + * the mux adapter will lock the parent i2c adapter, while calling + * select/deselect functions. + */ +static int inv_mpu6050_write_reg_unlocked(struct inv_mpu6050_state *st, + u8 reg, u8 d) +{ + int ret; + u8 buf[2]; + struct i2c_msg msg[1] = { + { + .addr = st->client->addr, + .flags = 0, + .len = sizeof(buf), + .buf = buf, + } + }; + + buf[0] = reg; + buf[1] = d; + ret = __i2c_transfer(st->client->adapter, msg, 1); + if (ret != 1) + return ret; + + return 0; +} + +static int inv_mpu6050_select_bypass(struct i2c_adapter *adap, void *mux_priv, + u32 chan_id) +{ + struct iio_dev *indio_dev = mux_priv; + struct inv_mpu6050_state *st = iio_priv(indio_dev); + int ret = 0; + + /* Use the same mutex which was used everywhere to protect power-op */ + mutex_lock(&indio_dev->mlock); + if (!st->powerup_count) { + ret = inv_mpu6050_write_reg_unlocked(st, st->reg->pwr_mgmt_1, + 0); + if (ret) + goto write_error; + + msleep(INV_MPU6050_REG_UP_TIME); + } + if (!ret) { + st->powerup_count++; + ret = inv_mpu6050_write_reg_unlocked(st, st->reg->int_pin_cfg, + st->client->irq | + INV_MPU6050_BIT_BYPASS_EN); + } +write_error: + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap, + void *mux_priv, u32 chan_id) +{ + struct iio_dev *indio_dev = mux_priv; + struct inv_mpu6050_state *st = iio_priv(indio_dev); + + mutex_lock(&indio_dev->mlock); + /* It doesn't really mattter, if any of the calls fails */ + inv_mpu6050_write_reg_unlocked(st, st->reg->int_pin_cfg, + st->client->irq); + st->powerup_count--; + if (!st->powerup_count) + inv_mpu6050_write_reg_unlocked(st, st->reg->pwr_mgmt_1, + INV_MPU6050_BIT_SLEEP); + mutex_unlock(&indio_dev->mlock); + + return 0; +} + int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask) { u8 d, mgmt_1; @@ -133,13 +212,22 @@ int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask) int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on) { - int result; + int result = 0; + + if (power_on) { + /* Already under indio-dev->mlock mutex */ + if (!st->powerup_count) + result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, + 0); + if (!result) + st->powerup_count++; + } else { + st->powerup_count--; + if (!st->powerup_count) + result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, + INV_MPU6050_BIT_SLEEP); + } - if (power_on) - result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, 0); - else - result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, - INV_MPU6050_BIT_SLEEP); if (result) return result; @@ -673,6 +761,7 @@ static int inv_mpu_probe(struct i2c_client *client, st = iio_priv(indio_dev); st->client = client; + st->powerup_count = 0; pdata = dev_get_platdata(&client->dev); if (pdata) st->plat_data = *pdata; @@ -720,8 +809,21 @@ static int inv_mpu_probe(struct i2c_client *client, goto out_remove_trigger; } + st->mux_adapter = i2c_add_mux_adapter(client->adapter, + &client->dev, + indio_dev, + 0, 0, 0, + inv_mpu6050_select_bypass, + inv_mpu6050_deselect_bypass); + if (!st->mux_adapter) { + result = -ENODEV; + goto out_unreg_device; + } + return 0; +out_unreg_device: + iio_device_unregister(indio_dev); out_remove_trigger: inv_mpu6050_remove_trigger(st); out_unreg_ring: @@ -734,6 +836,7 @@ static int inv_mpu_remove(struct i2c_client *client) struct iio_dev *indio_dev = i2c_get_clientdata(client); struct inv_mpu6050_state *st = iio_priv(indio_dev); + i2c_del_mux_adapter(st->mux_adapter); iio_device_unregister(indio_dev); inv_mpu6050_remove_trigger(st); iio_triggered_buffer_cleanup(indio_dev); diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h index e7799315d4dc1c..aa837de57079ed 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h @@ -54,6 +54,7 @@ struct inv_mpu6050_reg_map { u8 int_enable; u8 pwr_mgmt_1; u8 pwr_mgmt_2; + u8 int_pin_cfg; }; /*device enum */ @@ -119,6 +120,8 @@ struct inv_mpu6050_state { enum inv_devices chip_type; spinlock_t time_stamp_lock; struct i2c_client *client; + struct i2c_adapter *mux_adapter; + unsigned int powerup_count; struct inv_mpu6050_platform_data plat_data; DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE); }; @@ -179,6 +182,9 @@ struct inv_mpu6050_state { /* 6 + 6 round up and plus 8 */ #define INV_MPU6050_OUTPUT_DATA_SIZE 24 +#define INV_MPU6050_REG_INT_PIN_CFG 0x37 +#define INV_MPU6050_BIT_BYPASS_EN 0x2 + /* init parameters */ #define INV_MPU6050_INIT_FIFO_RATE 50 #define INV_MPU6050_TIME_STAMP_TOR 5 From d3653d09891b57f2e8089b8908f24a2e97576a49 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Sat, 6 Dec 2014 00:18:07 +0200 Subject: [PATCH 0151/3023] iio: accel: kxcjk-1013: always power on device in resume When the system resumes, it will first call system resume and then runtime suspend (if CONFIG_RUNTIME_PM is enabled). There is no need to conditionally power on the device in system resume, so always power it on and leave runtime suspend to power it off if needed. Suggested-by: Srinivas Pandruvada Signed-off-by: Irina Tirdea Reviewed-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/accel/kxcjk-1013.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index 1720e9a547ffec..aed377797ded1f 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -1354,10 +1354,7 @@ static int kxcjk1013_resume(struct device *dev) int ret = 0; mutex_lock(&data->mutex); - /* Check, if the suspend occured while active */ - if (data->dready_trigger_on || data->motion_trigger_on || - data->ev_enable_state) - ret = kxcjk1013_set_mode(data, OPERATION); + ret = kxcjk1013_set_mode(data, OPERATION); mutex_unlock(&data->mutex); return ret; From c75b8dc84fd28511224a4cd2bfa791bb56a06172 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Sat, 6 Dec 2014 00:18:08 +0200 Subject: [PATCH 0152/3023] iio: accel: kxcjk-1013: only set power state if CONFIG_PM is defined When CONFIG_PM is not defined and the driver tries to power off the device, kxcjk1013_set_power_state will call pm_runtime_put_autosuspend, which is not implemented (wil return -ENOSYS). Only call pm_runtime calls to change power state when CONFIG_PM is defined. Signed-off-by: Irina Tirdea Reviewed-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/accel/kxcjk-1013.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index aed377797ded1f..7b0a9dac7ae317 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -376,6 +376,7 @@ static int kxcjk1013_get_startup_times(struct kxcjk1013_data *data) static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on) { +#ifdef CONFIG_PM int ret; if (on) @@ -389,6 +390,7 @@ static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on) "Failed: kxcjk1013_set_power_state for %d\n", on); return ret; } +#endif return 0; } From f9380e7123863a4cb0627d940533be954a0a15df Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Thu, 27 Nov 2014 01:42:45 +0300 Subject: [PATCH 0153/3023] iio: inkern: add iio_write_channel_raw Introduce API for easy in-kernel setting of DAC values. Signed-off-by: Dmitry Eremin-Solenikov Signed-off-by: Jonathan Cameron --- drivers/iio/inkern.c | 25 +++++++++++++++++++++++++ include/linux/iio/consumer.h | 10 ++++++++++ 2 files changed, 35 insertions(+) diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index 866fe904cba29e..21655fd1465c48 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -631,3 +631,28 @@ int iio_get_channel_type(struct iio_channel *chan, enum iio_chan_type *type) return ret; } EXPORT_SYMBOL_GPL(iio_get_channel_type); + +static int iio_channel_write(struct iio_channel *chan, int val, int val2, + enum iio_chan_info_enum info) +{ + return chan->indio_dev->info->write_raw(chan->indio_dev, + chan->channel, val, val2, info); +} + +int iio_write_channel_raw(struct iio_channel *chan, int val) +{ + int ret; + + mutex_lock(&chan->indio_dev->info_exist_lock); + if (chan->indio_dev->info == NULL) { + ret = -ENODEV; + goto err_unlock; + } + + ret = iio_channel_write(chan, val, 0, IIO_CHAN_INFO_RAW); +err_unlock: + mutex_unlock(&chan->indio_dev->info_exist_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(iio_write_channel_raw); diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index 651f9a0e2765fa..6f64624f329b4b 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h @@ -150,6 +150,16 @@ int iio_read_channel_average_raw(struct iio_channel *chan, int *val); */ int iio_read_channel_processed(struct iio_channel *chan, int *val); +/** + * iio_write_channel_raw() - write to a given channel + * @chan: The channel being queried. + * @val: Value being written. + * + * Note raw writes to iio channels are in dac counts and hence + * scale will need to be applied if standard units required. + */ +int iio_write_channel_raw(struct iio_channel *chan, int val); + /** * iio_get_channel_type() - get the type of a channel * @channel: The channel being queried. From db38b9f9dddb10772329de6a26b416f6e3f7be41 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:07 +0100 Subject: [PATCH 0154/3023] staging:iio:ad5933: Don't enable channels by default The convention for IIO devices is that all channels are disabled by default. Signed-off-by: Lars-Peter Clausen Reviewed-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/staging/iio/impedance-analyzer/ad5933.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index b6bd609c3655f9..aa6a368506cd41 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -757,10 +757,6 @@ static int ad5933_probe(struct i2c_client *client, if (ret) goto error_unreg_ring; - /* enable both REAL and IMAG channels by default */ - iio_scan_mask_set(indio_dev, indio_dev->buffer, 0); - iio_scan_mask_set(indio_dev, indio_dev->buffer, 1); - ret = ad5933_setup(st); if (ret) goto error_uninitialize_ring; From 00d52334857c36fe52f8fc15a6fe3f0644fb73bc Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:08 +0100 Subject: [PATCH 0155/3023] staging:iio:sca3000: Don't enable channels by default The convention for IIO devices is that all channels are disabled by default. Signed-off-by: Lars-Peter Clausen Reviewed-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/sca3000_core.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index e4e56391487aad..cd46a616043b2f 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -1159,11 +1159,6 @@ static int sca3000_probe(struct spi_device *spi) ARRAY_SIZE(sca3000_channels)); if (ret < 0) goto error_unregister_dev; - if (indio_dev->buffer) { - iio_scan_mask_set(indio_dev, indio_dev->buffer, 0); - iio_scan_mask_set(indio_dev, indio_dev->buffer, 1); - iio_scan_mask_set(indio_dev, indio_dev->buffer, 2); - } if (spi->irq) { ret = request_threaded_irq(spi->irq, From 217a5cf0a1100264ced523e437e2e22c442dca7c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:09 +0100 Subject: [PATCH 0156/3023] iio: Unexport iio_scan_mask_set() Individual drivers should not be messing with the scan mask that contains the list of enabled channels. This is something that is supposed to be managed by the core. Now that the last few drivers that used it to configure a default scan mask have been updated to not do this anymore we can unexport the function. Note, this patch also requires moving a few functions around so they are all declared before the first internal user. Signed-off-by: Lars-Peter Clausen Reviewed-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-buffer.c | 149 +++++++++++++++--------------- include/linux/iio/buffer.h | 9 -- 2 files changed, 74 insertions(+), 84 deletions(-) diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index f971f79103ecd9..f667e4e7ea6d79 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -178,6 +178,80 @@ static ssize_t iio_scan_el_show(struct device *dev, return sprintf(buf, "%d\n", ret); } +/* Note NULL used as error indicator as it doesn't make sense. */ +static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks, + unsigned int masklength, + const unsigned long *mask) +{ + if (bitmap_empty(mask, masklength)) + return NULL; + while (*av_masks) { + if (bitmap_subset(mask, av_masks, masklength)) + return av_masks; + av_masks += BITS_TO_LONGS(masklength); + } + return NULL; +} + +static bool iio_validate_scan_mask(struct iio_dev *indio_dev, + const unsigned long *mask) +{ + if (!indio_dev->setup_ops->validate_scan_mask) + return true; + + return indio_dev->setup_ops->validate_scan_mask(indio_dev, mask); +} + +/** + * iio_scan_mask_set() - set particular bit in the scan mask + * @indio_dev: the iio device + * @buffer: the buffer whose scan mask we are interested in + * @bit: the bit to be set. + * + * Note that at this point we have no way of knowing what other + * buffers might request, hence this code only verifies that the + * individual buffers request is plausible. + */ +static int iio_scan_mask_set(struct iio_dev *indio_dev, + struct iio_buffer *buffer, int bit) +{ + const unsigned long *mask; + unsigned long *trialmask; + + trialmask = kmalloc(sizeof(*trialmask)* + BITS_TO_LONGS(indio_dev->masklength), + GFP_KERNEL); + + if (trialmask == NULL) + return -ENOMEM; + if (!indio_dev->masklength) { + WARN_ON("Trying to set scanmask prior to registering buffer\n"); + goto err_invalid_mask; + } + bitmap_copy(trialmask, buffer->scan_mask, indio_dev->masklength); + set_bit(bit, trialmask); + + if (!iio_validate_scan_mask(indio_dev, trialmask)) + goto err_invalid_mask; + + if (indio_dev->available_scan_masks) { + mask = iio_scan_mask_match(indio_dev->available_scan_masks, + indio_dev->masklength, + trialmask); + if (!mask) + goto err_invalid_mask; + } + bitmap_copy(buffer->scan_mask, trialmask, indio_dev->masklength); + + kfree(trialmask); + + return 0; + +err_invalid_mask: + kfree(trialmask); + return -EINVAL; +} + static int iio_scan_mask_clear(struct iio_buffer *buffer, int bit) { clear_bit(bit, buffer->scan_mask); @@ -455,21 +529,6 @@ ssize_t iio_buffer_show_enable(struct device *dev, } EXPORT_SYMBOL(iio_buffer_show_enable); -/* Note NULL used as error indicator as it doesn't make sense. */ -static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks, - unsigned int masklength, - const unsigned long *mask) -{ - if (bitmap_empty(mask, masklength)) - return NULL; - while (*av_masks) { - if (bitmap_subset(mask, av_masks, masklength)) - return av_masks; - av_masks += BITS_TO_LONGS(masklength); - } - return NULL; -} - static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const unsigned long *mask, bool timestamp) { @@ -808,66 +867,6 @@ bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev, } EXPORT_SYMBOL_GPL(iio_validate_scan_mask_onehot); -static bool iio_validate_scan_mask(struct iio_dev *indio_dev, - const unsigned long *mask) -{ - if (!indio_dev->setup_ops->validate_scan_mask) - return true; - - return indio_dev->setup_ops->validate_scan_mask(indio_dev, mask); -} - -/** - * iio_scan_mask_set() - set particular bit in the scan mask - * @indio_dev: the iio device - * @buffer: the buffer whose scan mask we are interested in - * @bit: the bit to be set. - * - * Note that at this point we have no way of knowing what other - * buffers might request, hence this code only verifies that the - * individual buffers request is plausible. - */ -int iio_scan_mask_set(struct iio_dev *indio_dev, - struct iio_buffer *buffer, int bit) -{ - const unsigned long *mask; - unsigned long *trialmask; - - trialmask = kmalloc(sizeof(*trialmask)* - BITS_TO_LONGS(indio_dev->masklength), - GFP_KERNEL); - - if (trialmask == NULL) - return -ENOMEM; - if (!indio_dev->masklength) { - WARN_ON("Trying to set scanmask prior to registering buffer\n"); - goto err_invalid_mask; - } - bitmap_copy(trialmask, buffer->scan_mask, indio_dev->masklength); - set_bit(bit, trialmask); - - if (!iio_validate_scan_mask(indio_dev, trialmask)) - goto err_invalid_mask; - - if (indio_dev->available_scan_masks) { - mask = iio_scan_mask_match(indio_dev->available_scan_masks, - indio_dev->masklength, - trialmask); - if (!mask) - goto err_invalid_mask; - } - bitmap_copy(buffer->scan_mask, trialmask, indio_dev->masklength); - - kfree(trialmask); - - return 0; - -err_invalid_mask: - kfree(trialmask); - return -EINVAL; -} -EXPORT_SYMBOL_GPL(iio_scan_mask_set); - int iio_scan_mask_query(struct iio_dev *indio_dev, struct iio_buffer *buffer, int bit) { diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index 51939276339383..8c8ce611949ccf 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -116,15 +116,6 @@ void iio_buffer_init(struct iio_buffer *buffer); int iio_scan_mask_query(struct iio_dev *indio_dev, struct iio_buffer *buffer, int bit); -/** - * iio_scan_mask_set() - set particular bit in the scan mask - * @indio_dev IIO device structure - * @buffer: the buffer whose scan mask we are interested in - * @bit: the bit to be set. - **/ -int iio_scan_mask_set(struct iio_dev *indio_dev, - struct iio_buffer *buffer, int bit); - /** * iio_push_to_buffers() - push to a registered buffer. * @indio_dev: iio_dev structure for device. From 131e97d3faf2df29a6a488b94890481351f18aea Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:10 +0100 Subject: [PATCH 0157/3023] staging:iio:sca3000: Register same channels for device and buffer In preparation for moving the buffer registration to the core make sure to register the same channel array for the device and the buffer. Currently the temperature channel is not registered for the buffer, setting its scan index to -1 will make sure that it is skipped for the buffer. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/sca3000_core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index cd46a616043b2f..aef8c916e07bf2 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -459,6 +459,8 @@ static const struct iio_chan_spec sca3000_channels_with_temp[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET), + /* No buffer support */ + .scan_index = -1, }, }; @@ -1154,9 +1156,8 @@ static int sca3000_probe(struct spi_device *spi) if (ret < 0) return ret; - ret = iio_buffer_register(indio_dev, - sca3000_channels, - ARRAY_SIZE(sca3000_channels)); + ret = iio_buffer_register(indio_dev, indio_dev->channels, + indio_dev->num_channels); if (ret < 0) goto error_unregister_dev; From 4ae03019923f7dd5785b69a513b74ccc1c3f7766 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:11 +0100 Subject: [PATCH 0158/3023] staging:iio:dummy: Register same channels for device and buffer In preparation for moving the buffer registration to the core make sure to register the same channel array for the device and the buffer. Currently the output voltage and the activity channels are not registered for the buffer, setting its scan index to -1 will make sure that it is skipped for the buffer. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/iio_simple_dummy.c | 13 +++++-------- drivers/staging/iio/iio_simple_dummy.h | 3 +-- drivers/staging/iio/iio_simple_dummy_buffer.c | 6 +++--- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c index 10a9e0882bbc58..0b8611ac100308 100644 --- a/drivers/staging/iio/iio_simple_dummy.c +++ b/drivers/staging/iio/iio_simple_dummy.c @@ -239,6 +239,7 @@ static const struct iio_chan_spec iio_dummy_channels[] = { { .type = IIO_VOLTAGE, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .scan_index = -1, /* No buffer support */ .output = 1, .indexed = 1, .channel = 0, @@ -248,7 +249,7 @@ static const struct iio_chan_spec iio_dummy_channels[] = { .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_ENABLE) | BIT(IIO_CHAN_INFO_CALIBHEIGHT), .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), - .scan_index = -1, + .scan_index = -1, /* No buffer support */ #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS .event_spec = &step_detect_event, .num_event_specs = 1, @@ -259,6 +260,7 @@ static const struct iio_chan_spec iio_dummy_channels[] = { .modified = 1, .channel2 = IIO_MOD_RUNNING, .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .scan_index = -1, /* No buffer support */ #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS .event_spec = &iio_running_event, .num_event_specs = 1, @@ -269,6 +271,7 @@ static const struct iio_chan_spec iio_dummy_channels[] = { .modified = 1, .channel2 = IIO_MOD_WALKING, .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .scan_index = -1, /* No buffer support */ #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS .event_spec = &iio_walking_event, .num_event_specs = 1, @@ -638,13 +641,7 @@ static int iio_dummy_probe(int index) if (ret < 0) goto error_free_device; - /* - * Configure buffered capture support and register the channels with the - * buffer, but avoid the output channel being registered by reducing the - * number of channels by 1. - */ - ret = iio_simple_dummy_configure_buffer(indio_dev, - iio_dummy_channels, 5); + ret = iio_simple_dummy_configure_buffer(indio_dev); if (ret < 0) goto error_unregister_events; diff --git a/drivers/staging/iio/iio_simple_dummy.h b/drivers/staging/iio/iio_simple_dummy.h index 3b714b486f5e40..af7012618be63c 100644 --- a/drivers/staging/iio/iio_simple_dummy.h +++ b/drivers/staging/iio/iio_simple_dummy.h @@ -114,8 +114,7 @@ enum iio_simple_dummy_scan_elements { }; #ifdef CONFIG_IIO_SIMPLE_DUMMY_BUFFER -int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, unsigned int num_channels); +int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev); void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev); #else static inline int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev, diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c index fd74f9166a5f92..35d60d5045dcbc 100644 --- a/drivers/staging/iio/iio_simple_dummy_buffer.c +++ b/drivers/staging/iio/iio_simple_dummy_buffer.c @@ -115,8 +115,7 @@ static const struct iio_buffer_setup_ops iio_simple_dummy_buffer_setup_ops = { .predisable = &iio_triggered_buffer_predisable, }; -int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, unsigned int num_channels) +int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) { int ret; struct iio_buffer *buffer; @@ -173,7 +172,8 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev, */ indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - ret = iio_buffer_register(indio_dev, channels, num_channels); + ret = iio_buffer_register(indio_dev, indio_dev->channels, + indio_dev->num_channels); if (ret) goto error_dealloc_pollfunc; From 3e1b6c95b990c93f4aa3b17e9f66221e2fa44bee Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:12 +0100 Subject: [PATCH 0159/3023] iio: Move buffer registration to the core Originally device and buffer registration were kept as separate operations in IIO to allow to register two distinct sets of channels for buffered and non-buffered operations. This has since already been further restricted and the channel set registered for the buffer needs to be a subset of the channel set registered for the device. Additionally the possibility to not have a raw (or processed) attribute for a channel which was registered for the device was added a while ago. This means it is possible to not register any device level attributes for a channel even if it is registered for the device. Also if a channel's scan_index is set to -1 and the channel is registered for the buffer it is ignored. So in summary it means it is possible to register the same channel array for both the device and the buffer yet still end up with distinctive sets of channels for both of them. This makes the argument for having to have to manually register the channels for both the device and the buffer invalid. Considering that the vast majority of all drivers want to register the same set of channels for both the buffer and the device it makes sense to move the buffer registration into the core to avoid some boiler-plate code in the device driver setup path. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti_am335x_adc.c | 9 ------- drivers/iio/iio_core.h | 9 +++++++ drivers/iio/industrialio-buffer.c | 18 ++++++++----- drivers/iio/industrialio-core.c | 14 +++++++++- drivers/iio/industrialio-triggered-buffer.c | 11 +------- drivers/staging/iio/accel/lis3l02dq_core.c | 13 +--------- drivers/staging/iio/accel/sca3000_core.c | 10 +------ drivers/staging/iio/iio_simple_dummy_buffer.c | 8 ------ .../staging/iio/impedance-analyzer/ad5933.c | 12 ++------- drivers/staging/iio/meter/ade7758.h | 1 - drivers/staging/iio/meter/ade7758_core.c | 15 ++--------- drivers/staging/iio/meter/ade7758_ring.c | 5 ---- include/linux/iio/buffer.h | 26 ------------------- 13 files changed, 40 insertions(+), 111 deletions(-) diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index b730864731e8b8..d550ac7d23659a 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -264,16 +264,8 @@ static int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev, indio_dev->setup_ops = setup_ops; indio_dev->modes |= INDIO_BUFFER_HARDWARE; - ret = iio_buffer_register(indio_dev, - indio_dev->channels, - indio_dev->num_channels); - if (ret) - goto error_free_irq; - return 0; -error_free_irq: - free_irq(irq, indio_dev); error_kfifo_free: iio_kfifo_free(indio_dev->buffer); return ret; @@ -285,7 +277,6 @@ static void tiadc_iio_buffered_hardware_remove(struct iio_dev *indio_dev) free_irq(adc_dev->mfd_tscadc->irq, indio_dev); iio_kfifo_free(indio_dev->buffer); - iio_buffer_unregister(indio_dev); } diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h index 5f0ea77fe7176e..359883525ab72b 100644 --- a/drivers/iio/iio_core.h +++ b/drivers/iio/iio_core.h @@ -48,6 +48,8 @@ unsigned int iio_buffer_poll(struct file *filp, ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, size_t n, loff_t *f_ps); +int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev); +void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev); #define iio_buffer_poll_addr (&iio_buffer_poll) #define iio_buffer_read_first_n_outer_addr (&iio_buffer_read_first_n_outer) @@ -60,6 +62,13 @@ void iio_buffer_wakeup_poll(struct iio_dev *indio_dev); #define iio_buffer_poll_addr NULL #define iio_buffer_read_first_n_outer_addr NULL +static inline int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev) {} + static inline void iio_disable_all_buffers(struct iio_dev *indio_dev) {} static inline void iio_buffer_wakeup_poll(struct iio_dev *indio_dev) {} diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index f667e4e7ea6d79..8bb3e64eaf2cc0 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -385,14 +385,16 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev, static const char * const iio_scan_elements_group_name = "scan_elements"; -int iio_buffer_register(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, - int num_channels) +int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) { struct iio_dev_attr *p; struct attribute **attr; struct iio_buffer *buffer = indio_dev->buffer; int ret, i, attrn, attrcount, attrcount_orig = 0; + const struct iio_chan_spec *channels; + + if (!buffer) + return 0; if (buffer->attrs) indio_dev->groups[indio_dev->groupcounter++] = buffer->attrs; @@ -404,9 +406,10 @@ int iio_buffer_register(struct iio_dev *indio_dev, } attrcount = attrcount_orig; INIT_LIST_HEAD(&buffer->scan_el_dev_attr_list); + channels = indio_dev->channels; if (channels) { /* new magic */ - for (i = 0; i < num_channels; i++) { + for (i = 0; i < indio_dev->num_channels; i++) { if (channels[i].scan_index < 0) continue; @@ -463,15 +466,16 @@ int iio_buffer_register(struct iio_dev *indio_dev, return ret; } -EXPORT_SYMBOL(iio_buffer_register); -void iio_buffer_unregister(struct iio_dev *indio_dev) +void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev) { + if (!indio_dev->buffer) + return; + kfree(indio_dev->buffer->scan_mask); kfree(indio_dev->buffer->scan_el_group.attrs); iio_free_chan_devattr_list(&indio_dev->buffer->scan_el_dev_attr_list); } -EXPORT_SYMBOL(iio_buffer_unregister); ssize_t iio_buffer_read_length(struct device *dev, struct device_attribute *attr, diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 45bb3a43afacdf..ee442ee482abd0 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -1158,11 +1158,19 @@ int iio_device_register(struct iio_dev *indio_dev) "Failed to register debugfs interfaces\n"); return ret; } + + ret = iio_buffer_alloc_sysfs_and_mask(indio_dev); + if (ret) { + dev_err(indio_dev->dev.parent, + "Failed to create buffer sysfs interfaces\n"); + goto error_unreg_debugfs; + } + ret = iio_device_register_sysfs(indio_dev); if (ret) { dev_err(indio_dev->dev.parent, "Failed to register sysfs interfaces\n"); - goto error_unreg_debugfs; + goto error_buffer_free_sysfs; } ret = iio_device_register_eventset(indio_dev); if (ret) { @@ -1195,6 +1203,8 @@ int iio_device_register(struct iio_dev *indio_dev) iio_device_unregister_eventset(indio_dev); error_free_sysfs: iio_device_unregister_sysfs(indio_dev); +error_buffer_free_sysfs: + iio_buffer_free_sysfs_and_mask(indio_dev); error_unreg_debugfs: iio_device_unregister_debugfs(indio_dev); return ret; @@ -1223,6 +1233,8 @@ void iio_device_unregister(struct iio_dev *indio_dev) iio_buffer_wakeup_poll(indio_dev); mutex_unlock(&indio_dev->info_exist_lock); + + iio_buffer_free_sysfs_and_mask(indio_dev); } EXPORT_SYMBOL(iio_device_unregister); diff --git a/drivers/iio/industrialio-triggered-buffer.c b/drivers/iio/industrialio-triggered-buffer.c index d6f54930b34af4..61a5d0404edf95 100644 --- a/drivers/iio/industrialio-triggered-buffer.c +++ b/drivers/iio/industrialio-triggered-buffer.c @@ -32,7 +32,7 @@ static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = { * * This function combines some common tasks which will normally be performed * when setting up a triggered buffer. It will allocate the buffer and the - * pollfunc, as well as register the buffer with the IIO core. + * pollfunc. * * Before calling this function the indio_dev structure should already be * completely initialized, but not yet registered. In practice this means that @@ -78,16 +78,8 @@ int iio_triggered_buffer_setup(struct iio_dev *indio_dev, /* Flag that polled ring buffering is possible */ indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - ret = iio_buffer_register(indio_dev, - indio_dev->channels, - indio_dev->num_channels); - if (ret) - goto error_dealloc_pollfunc; - return 0; -error_dealloc_pollfunc: - iio_dealloc_pollfunc(indio_dev->pollfunc); error_kfifo_free: iio_kfifo_free(indio_dev->buffer); error_ret: @@ -101,7 +93,6 @@ EXPORT_SYMBOL(iio_triggered_buffer_setup); */ void iio_triggered_buffer_cleanup(struct iio_dev *indio_dev) { - iio_buffer_unregister(indio_dev); iio_dealloc_pollfunc(indio_dev->pollfunc); iio_kfifo_free(indio_dev->buffer); } diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c index f5e145caffa9bc..b78c9c5d55886d 100644 --- a/drivers/staging/iio/accel/lis3l02dq_core.c +++ b/drivers/staging/iio/accel/lis3l02dq_core.c @@ -716,14 +716,6 @@ static int lis3l02dq_probe(struct spi_device *spi) if (ret) return ret; - ret = iio_buffer_register(indio_dev, - lis3l02dq_channels, - ARRAY_SIZE(lis3l02dq_channels)); - if (ret) { - dev_err(&spi->dev, "failed to initialize the buffer\n"); - goto error_unreg_buffer_funcs; - } - if (spi->irq) { ret = request_threaded_irq(st->us->irq, &lis3l02dq_th, @@ -732,7 +724,7 @@ static int lis3l02dq_probe(struct spi_device *spi) "lis3l02dq", indio_dev); if (ret) - goto error_uninitialize_buffer; + goto error_unreg_buffer_funcs; ret = lis3l02dq_probe_trigger(indio_dev); if (ret) @@ -756,8 +748,6 @@ static int lis3l02dq_probe(struct spi_device *spi) error_free_interrupt: if (spi->irq) free_irq(st->us->irq, indio_dev); -error_uninitialize_buffer: - iio_buffer_unregister(indio_dev); error_unreg_buffer_funcs: lis3l02dq_unconfigure_buffer(indio_dev); return ret; @@ -804,7 +794,6 @@ static int lis3l02dq_remove(struct spi_device *spi) free_irq(st->us->irq, indio_dev); lis3l02dq_remove_trigger(indio_dev); - iio_buffer_unregister(indio_dev); lis3l02dq_unconfigure_buffer(indio_dev); return 0; diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index aef8c916e07bf2..9cd04c7147c8f1 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -1156,11 +1156,6 @@ static int sca3000_probe(struct spi_device *spi) if (ret < 0) return ret; - ret = iio_buffer_register(indio_dev, indio_dev->channels, - indio_dev->num_channels); - if (ret < 0) - goto error_unregister_dev; - if (spi->irq) { ret = request_threaded_irq(spi->irq, NULL, @@ -1169,7 +1164,7 @@ static int sca3000_probe(struct spi_device *spi) "sca3000", indio_dev); if (ret) - goto error_unregister_ring; + goto error_unregister_dev; } sca3000_register_ring_funcs(indio_dev); ret = sca3000_clean_setup(st); @@ -1180,8 +1175,6 @@ static int sca3000_probe(struct spi_device *spi) error_free_irq: if (spi->irq) free_irq(spi->irq, indio_dev); -error_unregister_ring: - iio_buffer_unregister(indio_dev); error_unregister_dev: iio_device_unregister(indio_dev); return ret; @@ -1215,7 +1208,6 @@ static int sca3000_remove(struct spi_device *spi) if (spi->irq) free_irq(spi->irq, indio_dev); iio_device_unregister(indio_dev); - iio_buffer_unregister(indio_dev); sca3000_unconfigure_ring(indio_dev); return 0; diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c index 35d60d5045dcbc..a2d72c10211976 100644 --- a/drivers/staging/iio/iio_simple_dummy_buffer.c +++ b/drivers/staging/iio/iio_simple_dummy_buffer.c @@ -172,15 +172,8 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) */ indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - ret = iio_buffer_register(indio_dev, indio_dev->channels, - indio_dev->num_channels); - if (ret) - goto error_dealloc_pollfunc; - return 0; -error_dealloc_pollfunc: - iio_dealloc_pollfunc(indio_dev->pollfunc); error_free_buffer: iio_kfifo_free(indio_dev->buffer); error_ret: @@ -194,7 +187,6 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) */ void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev) { - iio_buffer_unregister(indio_dev); iio_dealloc_pollfunc(indio_dev->pollfunc); iio_kfifo_free(indio_dev->buffer); } diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index aa6a368506cd41..c50b1380b9aa3c 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -752,23 +752,16 @@ static int ad5933_probe(struct i2c_client *client, if (ret) goto error_disable_reg; - ret = iio_buffer_register(indio_dev, ad5933_channels, - ARRAY_SIZE(ad5933_channels)); - if (ret) - goto error_unreg_ring; - ret = ad5933_setup(st); if (ret) - goto error_uninitialize_ring; + goto error_unreg_ring; ret = iio_device_register(indio_dev); if (ret) - goto error_uninitialize_ring; + goto error_unreg_ring; return 0; -error_uninitialize_ring: - iio_buffer_unregister(indio_dev); error_unreg_ring: iio_kfifo_free(indio_dev->buffer); error_disable_reg: @@ -784,7 +777,6 @@ static int ad5933_remove(struct i2c_client *client) struct ad5933_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - iio_buffer_unregister(indio_dev); iio_kfifo_free(indio_dev->buffer); if (!IS_ERR(st->reg)) regulator_disable(st->reg); diff --git a/drivers/staging/iio/meter/ade7758.h b/drivers/staging/iio/meter/ade7758.h index 07318203a836e8..762d7dc0e6e2f0 100644 --- a/drivers/staging/iio/meter/ade7758.h +++ b/drivers/staging/iio/meter/ade7758.h @@ -146,7 +146,6 @@ ssize_t ade7758_read_data_from_ring(struct device *dev, int ade7758_configure_ring(struct iio_dev *indio_dev); void ade7758_unconfigure_ring(struct iio_dev *indio_dev); -void ade7758_uninitialize_ring(struct iio_dev *indio_dev); int ade7758_set_irq(struct device *dev, bool enable); int ade7758_spi_write_reg_8(struct device *dev, diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c index abc60067cd7202..6e8b01104a68f1 100644 --- a/drivers/staging/iio/meter/ade7758_core.c +++ b/drivers/staging/iio/meter/ade7758_core.c @@ -885,23 +885,15 @@ static int ade7758_probe(struct spi_device *spi) if (ret) goto error_free_tx; - ret = iio_buffer_register(indio_dev, - &ade7758_channels[0], - ARRAY_SIZE(ade7758_channels)); - if (ret) { - dev_err(&spi->dev, "failed to initialize the ring\n"); - goto error_unreg_ring_funcs; - } - /* Get the device into a sane initial state */ ret = ade7758_initial_setup(indio_dev); if (ret) - goto error_uninitialize_ring; + goto error_unreg_ring_funcs; if (spi->irq) { ret = ade7758_probe_trigger(indio_dev); if (ret) - goto error_uninitialize_ring; + goto error_unreg_ring_funcs; } ret = iio_device_register(indio_dev); @@ -913,8 +905,6 @@ static int ade7758_probe(struct spi_device *spi) error_remove_trigger: if (spi->irq) ade7758_remove_trigger(indio_dev); -error_uninitialize_ring: - ade7758_uninitialize_ring(indio_dev); error_unreg_ring_funcs: ade7758_unconfigure_ring(indio_dev); error_free_tx: @@ -932,7 +922,6 @@ static int ade7758_remove(struct spi_device *spi) iio_device_unregister(indio_dev); ade7758_stop_device(&indio_dev->dev); ade7758_remove_trigger(indio_dev); - ade7758_uninitialize_ring(indio_dev); ade7758_unconfigure_ring(indio_dev); kfree(st->tx); kfree(st->rx); diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c index c0accf8cce93f1..27c3ed6ca468d5 100644 --- a/drivers/staging/iio/meter/ade7758_ring.c +++ b/drivers/staging/iio/meter/ade7758_ring.c @@ -181,8 +181,3 @@ int ade7758_configure_ring(struct iio_dev *indio_dev) iio_kfifo_free(indio_dev->buffer); return ret; } - -void ade7758_uninitialize_ring(struct iio_dev *indio_dev) -{ - iio_buffer_unregister(indio_dev); -} diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index 8c8ce611949ccf..b0e006c3db43a5 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -150,22 +150,6 @@ static inline int iio_push_to_buffers_with_timestamp(struct iio_dev *indio_dev, int iio_update_demux(struct iio_dev *indio_dev); -/** - * iio_buffer_register() - register the buffer with IIO core - * @indio_dev: device with the buffer to be registered - * @channels: the channel descriptions used to construct buffer - * @num_channels: the number of channels - **/ -int iio_buffer_register(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, - int num_channels); - -/** - * iio_buffer_unregister() - unregister the buffer from IIO core - * @indio_dev: the device with the buffer to be unregistered - **/ -void iio_buffer_unregister(struct iio_dev *indio_dev); - /** * iio_buffer_read_length() - attr func to get number of datums in the buffer **/ @@ -223,16 +207,6 @@ static inline void iio_device_attach_buffer(struct iio_dev *indio_dev, #else /* CONFIG_IIO_BUFFER */ -static inline int iio_buffer_register(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, - int num_channels) -{ - return 0; -} - -static inline void iio_buffer_unregister(struct iio_dev *indio_dev) -{} - static inline void iio_buffer_get(struct iio_buffer *buffer) {} static inline void iio_buffer_put(struct iio_buffer *buffer) {} From 616dde2a1ea3df9398b1fcc7d6d6516c5fab6183 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:13 +0100 Subject: [PATCH 0160/3023] iio: Remove get_bytes_per_datum() from iio_buffer_access_funcs There haven't been any users of the get_bytes_per_datum() callback for a while. The core assumes that the number of bytes per datum can be calculated based on the enabled channels and the storage size of the channel and iio_compute_scan_bytes() is used to compute this number. So remove the callback. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/kfifo_buf.c | 6 ------ drivers/staging/iio/Documentation/ring.txt | 4 ++-- drivers/staging/iio/accel/sca3000_ring.c | 7 ------- include/linux/iio/buffer.h | 2 -- 4 files changed, 2 insertions(+), 17 deletions(-) diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c index 7134e8ada09ac5..1258b4e0a722c1 100644 --- a/drivers/iio/kfifo_buf.c +++ b/drivers/iio/kfifo_buf.c @@ -66,11 +66,6 @@ static struct attribute_group iio_kfifo_attribute_group = { .name = "buffer", }; -static int iio_get_bytes_per_datum_kfifo(struct iio_buffer *r) -{ - return r->bytes_per_datum; -} - static int iio_mark_update_needed_kfifo(struct iio_buffer *r) { struct iio_kfifo *kf = iio_to_kfifo(r); @@ -159,7 +154,6 @@ static const struct iio_buffer_access_funcs kfifo_access_funcs = { .read_first_n = &iio_read_first_n_kfifo, .data_available = iio_kfifo_buf_data_available, .request_update = &iio_request_update_kfifo, - .get_bytes_per_datum = &iio_get_bytes_per_datum_kfifo, .set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo, .get_length = &iio_get_length_kfifo, .set_length = &iio_set_length_kfifo, diff --git a/drivers/staging/iio/Documentation/ring.txt b/drivers/staging/iio/Documentation/ring.txt index e1da43381d0e69..434d63a6123a59 100644 --- a/drivers/staging/iio/Documentation/ring.txt +++ b/drivers/staging/iio/Documentation/ring.txt @@ -39,8 +39,8 @@ request_update If parameters have changed that require reinitialization or configuration of the buffer this will trigger it. -get_bytes_per_datum, set_bytes_per_datum - Get/set the number of bytes for a complete scan. (All samples + timestamp) +set_bytes_per_datum + Set the number of bytes for a complete scan. (All samples + timestamp) get_length / set_length Get/set the number of complete scans that may be held by the buffer. diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c index 157827651bfa79..aa0e5d85bfe2e7 100644 --- a/drivers/staging/iio/accel/sca3000_ring.c +++ b/drivers/staging/iio/accel/sca3000_ring.c @@ -135,12 +135,6 @@ static int sca3000_ring_get_length(struct iio_buffer *r) return 64; } -/* only valid if resolution is kept at 11bits */ -static int sca3000_ring_get_bytes_per_datum(struct iio_buffer *r) -{ - return 6; -} - static bool sca3000_ring_buf_data_available(struct iio_buffer *r) { return r->stufftoread; @@ -278,7 +272,6 @@ static void sca3000_ring_release(struct iio_buffer *r) static const struct iio_buffer_access_funcs sca3000_ring_access_funcs = { .read_first_n = &sca3000_read_first_n_hw_rb, .get_length = &sca3000_ring_get_length, - .get_bytes_per_datum = &sca3000_ring_get_bytes_per_datum, .data_available = sca3000_ring_buf_data_available, .release = sca3000_ring_release, }; diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index b0e006c3db43a5..79cdb3d1b1bc41 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -25,7 +25,6 @@ struct iio_buffer; * available. * @request_update: if a parameter change has been marked, update underlying * storage. - * @get_bytes_per_datum:get current bytes per datum * @set_bytes_per_datum:set number of bytes per datum * @get_length: get number of datums in buffer * @set_length: set number of datums in buffer @@ -49,7 +48,6 @@ struct iio_buffer_access_funcs { int (*request_update)(struct iio_buffer *buffer); - int (*get_bytes_per_datum)(struct iio_buffer *buffer); int (*set_bytes_per_datum)(struct iio_buffer *buffer, size_t bpd); int (*get_length)(struct iio_buffer *buffer); int (*set_length)(struct iio_buffer *buffer, int length); From d967cb6bd4e79c0cd7b150f1382d3d04e00408a0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:14 +0100 Subject: [PATCH 0161/3023] iio: buffer: Move iio_buffer_alloc_sysfs and iio_buffer_free_sysfs The next patch will introduce new dependencies in iio_buffer_alloc_sysfs() to functions which are currently defined after iio_buffer_alloc_sysfs(). To avoid forward declarations move both iio_buffer_alloc_sysfs() and iio_buffer_free_sysfs() after those function. This is split into two patches one moving the functions and one adding the dependencies to make review of the actual changes easier. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-buffer.c | 185 +++++++++++++++--------------- 1 file changed, 91 insertions(+), 94 deletions(-) diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 8bb3e64eaf2cc0..8cd89eb269c53d 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -383,100 +383,6 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev, return ret; } -static const char * const iio_scan_elements_group_name = "scan_elements"; - -int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) -{ - struct iio_dev_attr *p; - struct attribute **attr; - struct iio_buffer *buffer = indio_dev->buffer; - int ret, i, attrn, attrcount, attrcount_orig = 0; - const struct iio_chan_spec *channels; - - if (!buffer) - return 0; - - if (buffer->attrs) - indio_dev->groups[indio_dev->groupcounter++] = buffer->attrs; - - if (buffer->scan_el_attrs != NULL) { - attr = buffer->scan_el_attrs->attrs; - while (*attr++ != NULL) - attrcount_orig++; - } - attrcount = attrcount_orig; - INIT_LIST_HEAD(&buffer->scan_el_dev_attr_list); - channels = indio_dev->channels; - if (channels) { - /* new magic */ - for (i = 0; i < indio_dev->num_channels; i++) { - if (channels[i].scan_index < 0) - continue; - - /* Establish necessary mask length */ - if (channels[i].scan_index > - (int)indio_dev->masklength - 1) - indio_dev->masklength - = channels[i].scan_index + 1; - - ret = iio_buffer_add_channel_sysfs(indio_dev, - &channels[i]); - if (ret < 0) - goto error_cleanup_dynamic; - attrcount += ret; - if (channels[i].type == IIO_TIMESTAMP) - indio_dev->scan_index_timestamp = - channels[i].scan_index; - } - if (indio_dev->masklength && buffer->scan_mask == NULL) { - buffer->scan_mask = kcalloc(BITS_TO_LONGS(indio_dev->masklength), - sizeof(*buffer->scan_mask), - GFP_KERNEL); - if (buffer->scan_mask == NULL) { - ret = -ENOMEM; - goto error_cleanup_dynamic; - } - } - } - - buffer->scan_el_group.name = iio_scan_elements_group_name; - - buffer->scan_el_group.attrs = kcalloc(attrcount + 1, - sizeof(buffer->scan_el_group.attrs[0]), - GFP_KERNEL); - if (buffer->scan_el_group.attrs == NULL) { - ret = -ENOMEM; - goto error_free_scan_mask; - } - if (buffer->scan_el_attrs) - memcpy(buffer->scan_el_group.attrs, buffer->scan_el_attrs, - sizeof(buffer->scan_el_group.attrs[0])*attrcount_orig); - attrn = attrcount_orig; - - list_for_each_entry(p, &buffer->scan_el_dev_attr_list, l) - buffer->scan_el_group.attrs[attrn++] = &p->dev_attr.attr; - indio_dev->groups[indio_dev->groupcounter++] = &buffer->scan_el_group; - - return 0; - -error_free_scan_mask: - kfree(buffer->scan_mask); -error_cleanup_dynamic: - iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list); - - return ret; -} - -void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev) -{ - if (!indio_dev->buffer) - return; - - kfree(indio_dev->buffer->scan_mask); - kfree(indio_dev->buffer->scan_el_group.attrs); - iio_free_chan_devattr_list(&indio_dev->buffer->scan_el_dev_attr_list); -} - ssize_t iio_buffer_read_length(struct device *dev, struct device_attribute *attr, char *buf) @@ -855,6 +761,97 @@ ssize_t iio_buffer_store_enable(struct device *dev, } EXPORT_SYMBOL(iio_buffer_store_enable); +static const char * const iio_scan_elements_group_name = "scan_elements"; + +int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) +{ + struct iio_dev_attr *p; + struct attribute **attr; + struct iio_buffer *buffer = indio_dev->buffer; + int ret, i, attrn, attrcount, attrcount_orig = 0; + const struct iio_chan_spec *channels; + + if (!buffer) + return 0; + + if (buffer->scan_el_attrs != NULL) { + attr = buffer->scan_el_attrs->attrs; + while (*attr++ != NULL) + attrcount_orig++; + } + attrcount = attrcount_orig; + INIT_LIST_HEAD(&buffer->scan_el_dev_attr_list); + channels = indio_dev->channels; + if (channels) { + /* new magic */ + for (i = 0; i < indio_dev->num_channels; i++) { + if (channels[i].scan_index < 0) + continue; + + /* Establish necessary mask length */ + if (channels[i].scan_index > + (int)indio_dev->masklength - 1) + indio_dev->masklength + = channels[i].scan_index + 1; + + ret = iio_buffer_add_channel_sysfs(indio_dev, + &channels[i]); + if (ret < 0) + goto error_cleanup_dynamic; + attrcount += ret; + if (channels[i].type == IIO_TIMESTAMP) + indio_dev->scan_index_timestamp = + channels[i].scan_index; + } + if (indio_dev->masklength && buffer->scan_mask == NULL) { + buffer->scan_mask = kcalloc(BITS_TO_LONGS(indio_dev->masklength), + sizeof(*buffer->scan_mask), + GFP_KERNEL); + if (buffer->scan_mask == NULL) { + ret = -ENOMEM; + goto error_cleanup_dynamic; + } + } + } + + buffer->scan_el_group.name = iio_scan_elements_group_name; + + buffer->scan_el_group.attrs = kcalloc(attrcount + 1, + sizeof(buffer->scan_el_group.attrs[0]), + GFP_KERNEL); + if (buffer->scan_el_group.attrs == NULL) { + ret = -ENOMEM; + goto error_free_scan_mask; + } + if (buffer->scan_el_attrs) + memcpy(buffer->scan_el_group.attrs, buffer->scan_el_attrs, + sizeof(buffer->scan_el_group.attrs[0])*attrcount_orig); + attrn = attrcount_orig; + + list_for_each_entry(p, &buffer->scan_el_dev_attr_list, l) + buffer->scan_el_group.attrs[attrn++] = &p->dev_attr.attr; + indio_dev->groups[indio_dev->groupcounter++] = &buffer->scan_el_group; + + return 0; + +error_free_scan_mask: + kfree(buffer->scan_mask); +error_cleanup_dynamic: + iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list); + + return ret; +} + +void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev) +{ + if (!indio_dev->buffer) + return; + + kfree(indio_dev->buffer->scan_mask); + kfree(indio_dev->buffer->scan_el_group.attrs); + iio_free_chan_devattr_list(&indio_dev->buffer->scan_el_dev_attr_list); +} + /** * iio_validate_scan_mask_onehot() - Validates that exactly one channel is selected * @indio_dev: the iio device From 08e7e0adaa17205f86894157d86c4bee3c714330 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:15 +0100 Subject: [PATCH 0162/3023] iio: buffer: Allocate standard attributes in the core All buffers want at least the length and the enable attribute. Move the creation of those attributes to the core instead of having to do this in each individual buffer implementation. This allows us to get rid of some boiler-plate code. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-buffer.c | 59 ++++++++++++++++-------- drivers/iio/kfifo_buf.c | 15 ------ drivers/staging/iio/accel/sca3000_ring.c | 14 +----- include/linux/iio/buffer.h | 37 +-------------- 4 files changed, 45 insertions(+), 80 deletions(-) diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 8cd89eb269c53d..ba89357fc096d2 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -383,9 +383,9 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev, return ret; } -ssize_t iio_buffer_read_length(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t iio_buffer_read_length(struct device *dev, + struct device_attribute *attr, + char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_buffer *buffer = indio_dev->buffer; @@ -396,12 +396,10 @@ ssize_t iio_buffer_read_length(struct device *dev, return 0; } -EXPORT_SYMBOL(iio_buffer_read_length); -ssize_t iio_buffer_write_length(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) +static ssize_t iio_buffer_write_length(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_buffer *buffer = indio_dev->buffer; @@ -428,16 +426,14 @@ ssize_t iio_buffer_write_length(struct device *dev, return ret ? ret : len; } -EXPORT_SYMBOL(iio_buffer_write_length); -ssize_t iio_buffer_show_enable(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t iio_buffer_show_enable(struct device *dev, + struct device_attribute *attr, + char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); return sprintf(buf, "%d\n", iio_buffer_is_active(indio_dev->buffer)); } -EXPORT_SYMBOL(iio_buffer_show_enable); static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const unsigned long *mask, bool timestamp) @@ -724,10 +720,10 @@ int iio_update_buffers(struct iio_dev *indio_dev, } EXPORT_SYMBOL_GPL(iio_update_buffers); -ssize_t iio_buffer_store_enable(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) +static ssize_t iio_buffer_store_enable(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) { int ret; bool requested_state; @@ -759,10 +755,14 @@ ssize_t iio_buffer_store_enable(struct device *dev, mutex_unlock(&indio_dev->mlock); return (ret < 0) ? ret : len; } -EXPORT_SYMBOL(iio_buffer_store_enable); static const char * const iio_scan_elements_group_name = "scan_elements"; +static DEVICE_ATTR(length, S_IRUGO | S_IWUSR, iio_buffer_read_length, + iio_buffer_write_length); +static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, + iio_buffer_show_enable, iio_buffer_store_enable); + int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) { struct iio_dev_attr *p; @@ -774,6 +774,27 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) if (!buffer) return 0; + attrcount = 0; + if (buffer->attrs) { + while (buffer->attrs[attrcount] != NULL) + attrcount++; + } + + buffer->buffer_group.name = "buffer"; + buffer->buffer_group.attrs = kcalloc(attrcount + 3, + sizeof(*buffer->buffer_group.attrs), GFP_KERNEL); + if (!buffer->buffer_group.attrs) + return -ENOMEM; + + buffer->buffer_group.attrs[0] = &dev_attr_length.attr; + buffer->buffer_group.attrs[1] = &dev_attr_enable.attr; + if (buffer->attrs) + memcpy(&buffer->buffer_group.attrs[2], buffer->attrs, + sizeof(*&buffer->buffer_group.attrs) * (attrcount - 2)); + buffer->buffer_group.attrs[attrcount+2] = NULL; + + indio_dev->groups[indio_dev->groupcounter++] = &buffer->buffer_group; + if (buffer->scan_el_attrs != NULL) { attr = buffer->scan_el_attrs->attrs; while (*attr++ != NULL) @@ -838,6 +859,7 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) kfree(buffer->scan_mask); error_cleanup_dynamic: iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list); + kfree(indio_dev->buffer->buffer_group.attrs); return ret; } @@ -848,6 +870,7 @@ void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev) return; kfree(indio_dev->buffer->scan_mask); + kfree(indio_dev->buffer->buffer_group.attrs); kfree(indio_dev->buffer->scan_el_group.attrs); iio_free_chan_devattr_list(&indio_dev->buffer->scan_el_dev_attr_list); } diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c index 1258b4e0a722c1..3b0a3bc4f0adcc 100644 --- a/drivers/iio/kfifo_buf.c +++ b/drivers/iio/kfifo_buf.c @@ -52,20 +52,6 @@ static int iio_get_length_kfifo(struct iio_buffer *r) return r->length; } -static IIO_BUFFER_ENABLE_ATTR; -static IIO_BUFFER_LENGTH_ATTR; - -static struct attribute *iio_kfifo_attributes[] = { - &dev_attr_length.attr, - &dev_attr_enable.attr, - NULL, -}; - -static struct attribute_group iio_kfifo_attribute_group = { - .attrs = iio_kfifo_attributes, - .name = "buffer", -}; - static int iio_mark_update_needed_kfifo(struct iio_buffer *r) { struct iio_kfifo *kf = iio_to_kfifo(r); @@ -169,7 +155,6 @@ struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev) return NULL; kf->update_needed = true; iio_buffer_init(&kf->buffer); - kf->buffer.attrs = &iio_kfifo_attribute_group; kf->buffer.access = &kfifo_access_funcs; kf->buffer.length = 2; mutex_init(&kf->user_lock); diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c index aa0e5d85bfe2e7..f2f260e015504a 100644 --- a/drivers/staging/iio/accel/sca3000_ring.c +++ b/drivers/staging/iio/accel/sca3000_ring.c @@ -140,9 +140,6 @@ static bool sca3000_ring_buf_data_available(struct iio_buffer *r) return r->stufftoread; } -static IIO_BUFFER_ENABLE_ATTR; -static IIO_BUFFER_LENGTH_ATTR; - /** * sca3000_query_ring_int() is the hardware ring status interrupt enabled **/ @@ -232,20 +229,13 @@ static IIO_DEVICE_ATTR(in_accel_scale, * only apply to the ring buffer. At all times full rate and accuracy * is available via direct reading from registers. */ -static struct attribute *sca3000_ring_attributes[] = { - &dev_attr_length.attr, - &dev_attr_enable.attr, +static const struct attribute *sca3000_ring_attributes[] = { &iio_dev_attr_50_percent.dev_attr.attr, &iio_dev_attr_75_percent.dev_attr.attr, &iio_dev_attr_in_accel_scale.dev_attr.attr, NULL, }; -static struct attribute_group sca3000_ring_attr = { - .attrs = sca3000_ring_attributes, - .name = "buffer", -}; - static struct iio_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev) { struct iio_buffer *buf; @@ -258,7 +248,7 @@ static struct iio_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev) ring->private = indio_dev; buf = &ring->buf; buf->stufftoread = 0; - buf->attrs = &sca3000_ring_attr; + buf->attrs = sca3000_ring_attributes; iio_buffer_init(buf); return buf; diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index 79cdb3d1b1bc41..16b7663036f25a 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -83,10 +83,11 @@ struct iio_buffer { bool scan_timestamp; const struct iio_buffer_access_funcs *access; struct list_head scan_el_dev_attr_list; + struct attribute_group buffer_group; struct attribute_group scan_el_group; wait_queue_head_t pollq; bool stufftoread; - const struct attribute_group *attrs; + const struct attribute **attrs; struct list_head demux_list; void *demux_bounce; struct list_head buffer_list; @@ -148,40 +149,6 @@ static inline int iio_push_to_buffers_with_timestamp(struct iio_dev *indio_dev, int iio_update_demux(struct iio_dev *indio_dev); -/** - * iio_buffer_read_length() - attr func to get number of datums in the buffer - **/ -ssize_t iio_buffer_read_length(struct device *dev, - struct device_attribute *attr, - char *buf); -/** - * iio_buffer_write_length() - attr func to set number of datums in the buffer - **/ -ssize_t iio_buffer_write_length(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len); -/** - * iio_buffer_store_enable() - attr to turn the buffer on - **/ -ssize_t iio_buffer_store_enable(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len); -/** - * iio_buffer_show_enable() - attr to see if the buffer is on - **/ -ssize_t iio_buffer_show_enable(struct device *dev, - struct device_attribute *attr, - char *buf); -#define IIO_BUFFER_LENGTH_ATTR DEVICE_ATTR(length, S_IRUGO | S_IWUSR, \ - iio_buffer_read_length, \ - iio_buffer_write_length) - -#define IIO_BUFFER_ENABLE_ATTR DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, \ - iio_buffer_show_enable, \ - iio_buffer_store_enable) - bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev, const unsigned long *mask); From 8d92db2827b68206f6930e79132243416183e083 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:16 +0100 Subject: [PATCH 0163/3023] iio: buffer: Make length attribute read only for buffers without set_length If a buffer implementation does not implement the set_length() callback the length will be static and can not be changed by userspace. Mark the length attribute as a read only property in this case so userspace is aware of this rather than just silently accepting any length value. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-buffer.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index ba89357fc096d2..4ca4c0a0992356 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -418,8 +418,7 @@ static ssize_t iio_buffer_write_length(struct device *dev, if (iio_buffer_is_active(indio_dev->buffer)) { ret = -EBUSY; } else { - if (buffer->access->set_length) - buffer->access->set_length(buffer, val); + buffer->access->set_length(buffer, val); ret = 0; } mutex_unlock(&indio_dev->mlock); @@ -760,6 +759,8 @@ static const char * const iio_scan_elements_group_name = "scan_elements"; static DEVICE_ATTR(length, S_IRUGO | S_IWUSR, iio_buffer_read_length, iio_buffer_write_length); +static struct device_attribute dev_attr_length_ro = __ATTR(length, + S_IRUGO, iio_buffer_read_length, NULL); static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, iio_buffer_show_enable, iio_buffer_store_enable); @@ -786,7 +787,10 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) if (!buffer->buffer_group.attrs) return -ENOMEM; - buffer->buffer_group.attrs[0] = &dev_attr_length.attr; + if (buffer->access->set_length) + buffer->buffer_group.attrs[0] = &dev_attr_length.attr; + else + buffer->buffer_group.attrs[0] = &dev_attr_length_ro.attr; buffer->buffer_group.attrs[1] = &dev_attr_enable.attr; if (buffer->attrs) memcpy(&buffer->buffer_group.attrs[2], buffer->attrs, From 374956600ecbedf5ca29c76bde114160eb805091 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:17 +0100 Subject: [PATCH 0164/3023] iio: buffer: Drop get_length callback We already do have the length field in the struct iio_buffer which is expected to be in sync with the current size of the buffer. And currently all implementations of the get_length callback either return this field or a constant number. This patch removes the get_length callback and replaces all occurrences in the IIO core with directly accessing the length field of the buffer. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-buffer.c | 11 +++-------- drivers/iio/kfifo_buf.c | 6 ------ drivers/staging/iio/Documentation/ring.txt | 4 ++-- drivers/staging/iio/accel/sca3000_ring.c | 8 +------- include/linux/iio/buffer.h | 2 -- 5 files changed, 6 insertions(+), 25 deletions(-) diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 4ca4c0a0992356..2bd8d399f2ecce 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -390,11 +390,7 @@ static ssize_t iio_buffer_read_length(struct device *dev, struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_buffer *buffer = indio_dev->buffer; - if (buffer->access->get_length) - return sprintf(buf, "%d\n", - buffer->access->get_length(buffer)); - - return 0; + return sprintf(buf, "%d\n", buffer->length); } static ssize_t iio_buffer_write_length(struct device *dev, @@ -410,9 +406,8 @@ static ssize_t iio_buffer_write_length(struct device *dev, if (ret) return ret; - if (buffer->access->get_length) - if (val == buffer->access->get_length(buffer)) - return len; + if (val == buffer->length) + return len; mutex_lock(&indio_dev->mlock); if (iio_buffer_is_active(indio_dev->buffer)) { diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c index 3b0a3bc4f0adcc..b20a9cfbc8edd8 100644 --- a/drivers/iio/kfifo_buf.c +++ b/drivers/iio/kfifo_buf.c @@ -47,11 +47,6 @@ static int iio_request_update_kfifo(struct iio_buffer *r) return ret; } -static int iio_get_length_kfifo(struct iio_buffer *r) -{ - return r->length; -} - static int iio_mark_update_needed_kfifo(struct iio_buffer *r) { struct iio_kfifo *kf = iio_to_kfifo(r); @@ -141,7 +136,6 @@ static const struct iio_buffer_access_funcs kfifo_access_funcs = { .data_available = iio_kfifo_buf_data_available, .request_update = &iio_request_update_kfifo, .set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo, - .get_length = &iio_get_length_kfifo, .set_length = &iio_set_length_kfifo, .release = &iio_kfifo_buffer_release, }; diff --git a/drivers/staging/iio/Documentation/ring.txt b/drivers/staging/iio/Documentation/ring.txt index 434d63a6123a59..18718fcaf25990 100644 --- a/drivers/staging/iio/Documentation/ring.txt +++ b/drivers/staging/iio/Documentation/ring.txt @@ -42,6 +42,6 @@ request_update set_bytes_per_datum Set the number of bytes for a complete scan. (All samples + timestamp) -get_length / set_length - Get/set the number of complete scans that may be held by the buffer. +set_length + Set the number of complete scans that may be held by the buffer. diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c index f2f260e015504a..f76a2688580801 100644 --- a/drivers/staging/iio/accel/sca3000_ring.c +++ b/drivers/staging/iio/accel/sca3000_ring.c @@ -129,12 +129,6 @@ static int sca3000_read_first_n_hw_rb(struct iio_buffer *r, return ret ? ret : num_read; } -/* This is only valid with all 3 elements enabled */ -static int sca3000_ring_get_length(struct iio_buffer *r) -{ - return 64; -} - static bool sca3000_ring_buf_data_available(struct iio_buffer *r) { return r->stufftoread; @@ -248,6 +242,7 @@ static struct iio_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev) ring->private = indio_dev; buf = &ring->buf; buf->stufftoread = 0; + buf->length = 64; buf->attrs = sca3000_ring_attributes; iio_buffer_init(buf); @@ -261,7 +256,6 @@ static void sca3000_ring_release(struct iio_buffer *r) static const struct iio_buffer_access_funcs sca3000_ring_access_funcs = { .read_first_n = &sca3000_read_first_n_hw_rb, - .get_length = &sca3000_ring_get_length, .data_available = sca3000_ring_buf_data_available, .release = sca3000_ring_release, }; diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index 16b7663036f25a..b65850a411274b 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -26,7 +26,6 @@ struct iio_buffer; * @request_update: if a parameter change has been marked, update underlying * storage. * @set_bytes_per_datum:set number of bytes per datum - * @get_length: get number of datums in buffer * @set_length: set number of datums in buffer * @release: called when the last reference to the buffer is dropped, * should free all resources allocated by the buffer. @@ -49,7 +48,6 @@ struct iio_buffer_access_funcs { int (*request_update)(struct iio_buffer *buffer); int (*set_bytes_per_datum)(struct iio_buffer *buffer, size_t bpd); - int (*get_length)(struct iio_buffer *buffer); int (*set_length)(struct iio_buffer *buffer, int length); void (*release)(struct iio_buffer *buffer); From fbd123e913ed25ec861ce3be10725b5beb27ab48 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Wed, 10 Dec 2014 18:23:53 +0200 Subject: [PATCH 0165/3023] iio: accel: kxcjk-1013: error handling when set mode fails If there is an error in set mode at runtime resume, reset the state of the runtime usage count. If there is an error in set mode at runtime suspend, make sure the framework retries to suspend the device. Signed-off-by: Irina Tirdea Reviewed-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/accel/kxcjk-1013.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index 7b0a9dac7ae317..0dc6ccfbee4616 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -388,6 +388,8 @@ static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on) if (ret < 0) { dev_err(&data->client->dev, "Failed: kxcjk1013_set_power_state for %d\n", on); + if (on) + pm_runtime_put_noidle(&data->client->dev); return ret; } #endif @@ -859,6 +861,8 @@ static int kxcjk1013_write_event_config(struct iio_dev *indio_dev, ret = kxcjk1013_setup_any_motion_interrupt(data, state); if (ret < 0) { + kxcjk1013_set_power_state(data, false); + data->ev_enable_state = 0; mutex_unlock(&data->mutex); return ret; } @@ -1009,6 +1013,7 @@ static int kxcjk1013_data_rdy_trigger_set_state(struct iio_trigger *trig, else ret = kxcjk1013_setup_new_data_interrupt(data, state); if (ret < 0) { + kxcjk1013_set_power_state(data, false); mutex_unlock(&data->mutex); return ret; } @@ -1368,8 +1373,14 @@ static int kxcjk1013_runtime_suspend(struct device *dev) { struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); struct kxcjk1013_data *data = iio_priv(indio_dev); + int ret; - return kxcjk1013_set_mode(data, STANDBY); + ret = kxcjk1013_set_mode(data, STANDBY); + if (ret < 0) { + dev_err(&data->client->dev, "powering off device failed\n"); + return -EAGAIN; + } + return 0; } static int kxcjk1013_runtime_resume(struct device *dev) From 9d02daf738bf01b9d89d4de2b74ed3bc9bebbb40 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Wed, 10 Dec 2014 18:23:54 +0200 Subject: [PATCH 0166/3023] iio: accel: kxcjk-1013: power off device if probe fails When the device is initialized in probe, it is also powered on. If there is an error after the initialization, the device will remain powered on. Power off the device in case probe fails after device initialization. Signed-off-by: Irina Tirdea Suggested-by: Daniel Baluta Reviewed-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/accel/kxcjk-1013.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index 0dc6ccfbee4616..a5e7d30bc36829 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -1240,21 +1240,25 @@ static int kxcjk1013_probe(struct i2c_client *client, KXCJK1013_IRQ_NAME, indio_dev); if (ret) - return ret; + goto err_poweroff; data->dready_trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", indio_dev->name, indio_dev->id); - if (!data->dready_trig) - return -ENOMEM; + if (!data->dready_trig) { + ret = -ENOMEM; + goto err_poweroff; + } data->motion_trig = devm_iio_trigger_alloc(&client->dev, "%s-any-motion-dev%d", indio_dev->name, indio_dev->id); - if (!data->motion_trig) - return -ENOMEM; + if (!data->motion_trig) { + ret = -ENOMEM; + goto err_poweroff; + } data->dready_trig->dev.parent = &client->dev; data->dready_trig->ops = &kxcjk1013_trigger_ops; @@ -1263,7 +1267,7 @@ static int kxcjk1013_probe(struct i2c_client *client, iio_trigger_get(indio_dev->trig); ret = iio_trigger_register(data->dready_trig); if (ret) - return ret; + goto err_poweroff; data->motion_trig->dev.parent = &client->dev; data->motion_trig->ops = &kxcjk1013_trigger_ops; @@ -1312,6 +1316,8 @@ static int kxcjk1013_probe(struct i2c_client *client, iio_trigger_unregister(data->dready_trig); if (data->motion_trig) iio_trigger_unregister(data->motion_trig); +err_poweroff: + kxcjk1013_set_mode(data, STANDBY); return ret; } From 09546a30632fd35996373146657d5a0296fd37ca Mon Sep 17 00:00:00 2001 From: "Ivan T. Ivanov" Date: Tue, 23 Sep 2014 15:51:42 +0300 Subject: [PATCH 0167/3023] iio: consumer.h: Fix scale factor in function comment 1 milivolt is equal to 1000000 nanovolts. Signed-off-by: Ivan T. Ivanov Signed-off-by: Jonathan Cameron --- include/linux/iio/consumer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index 6f64624f329b4b..26fb8f6342bb52 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h @@ -201,7 +201,7 @@ int iio_read_channel_scale(struct iio_channel *chan, int *val, * The scale factor allows to increase the precession of the returned value. For * a scale factor of 1 the function will return the result in the normal IIO * unit for the channel type. E.g. millivolt for voltage channels, if you want - * nanovolts instead pass 1000 as the scale factor. + * nanovolts instead pass 1000000 as the scale factor. */ int iio_convert_raw_to_processed(struct iio_channel *chan, int raw, int *processed, unsigned int scale); From 7f1c2cbbdaf7da1036bfbf13615081bae72ed33a Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Tue, 25 Nov 2014 18:25:39 +0000 Subject: [PATCH 0168/3023] iio: Add ABI documentation for input current readings Add information on in_current related readings. Signed-off-by: Adam Thomson Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 4a9e29a3c2dc4d..df5e69e6247c44 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -92,6 +92,18 @@ Description: is required is a consistent labeling. Units after application of scale and offset are millivolts. +What: /sys/bus/iio/devices/iio:deviceX/in_currentY_raw +What: /sys/bus/iio/devices/iio:deviceX/in_currentY_supply_raw +KernelVersion: 3.17 +Contact: linux-iio@vger.kernel.org +Description: + Raw (unscaled no bias removal etc.) current measurement from + channel Y. In special cases where the channel does not + correspond to externally available input one of the named + versions may be used. The number must always be specified and + unique to allow association with event codes. Units after + application of scale and offset are milliamps. + What: /sys/bus/iio/devices/iio:deviceX/in_capacitanceY_raw KernelVersion: 3.2 Contact: linux-iio@vger.kernel.org @@ -234,6 +246,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_accel_y_offset What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_offset What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_offset What: /sys/bus/iio/devices/iio:deviceX/in_voltage_offset +What: /sys/bus/iio/devices/iio:deviceX/in_currentY_offset +What: /sys/bus/iio/devices/iio:deviceX/in_current_offset What: /sys/bus/iio/devices/iio:deviceX/in_tempY_offset What: /sys/bus/iio/devices/iio:deviceX/in_temp_offset What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_offset @@ -262,6 +276,9 @@ What: /sys/bus/iio/devices/iio:deviceX/in_voltage_scale What: /sys/bus/iio/devices/iio:deviceX/in_voltage-voltage_scale What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_scale What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_scale +What: /sys/bus/iio/devices/iio:deviceX/in_currentY_scale +What: /sys/bus/iio/devices/iio:deviceX/in_currentY_supply_scale +What: /sys/bus/iio/devices/iio:deviceX/in_current_scale What: /sys/bus/iio/devices/iio:deviceX/in_accel_scale What: /sys/bus/iio/devices/iio:deviceX/in_accel_peak_scale What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_scale From c78b91716340da82f57b974ee5f52d33103f9231 Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Mon, 24 Nov 2014 11:43:15 +0200 Subject: [PATCH 0169/3023] iio: add driver for Freescale MMA9551L Add support for Freescale MMA9551L Intelligent Motion-Sensing Platform. The driver supports raw reads for acceleration and inclination, as well as configuring inclination rate-of-change events. The events can be used similarly to an Android sensor Tilt event. The specifications can be downloaded from: http://www.freescale.com/files/sensors/doc/ref_manual/MMA955xLSWRM.pdf Signed-off-by: Irina Tirdea Signed-off-by: Vlad Dogaru Reviewed-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/accel/Kconfig | 10 + drivers/iio/accel/Makefile | 1 + drivers/iio/accel/mma9551.c | 954 ++++++++++++++++++++++++++++++++++++ 3 files changed, 965 insertions(+) create mode 100644 drivers/iio/accel/mma9551.c diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 9b9be8725e9d44..d80616d77034b9 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -105,4 +105,14 @@ config KXCJK1013 To compile this driver as a module, choose M here: the module will be called kxcjk-1013. +config MMA9551 + tristate "Freescale MMA9551L Intelligent Motion-Sensing Platform Driver" + depends on I2C + help + Say yes here to build support for the Freescale MMA9551L + Intelligent Motion-Sensing Platform Driver. + + To compile this driver as a module, choose M here: the module + will be called mma9551. + endmenu diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index a593996c653922..de5b9cb9670f93 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o obj-$(CONFIG_KXSD9) += kxsd9.o obj-$(CONFIG_MMA8452) += mma8452.o +obj-$(CONFIG_MMA9551) += mma9551.o obj-$(CONFIG_IIO_ST_ACCEL_3AXIS) += st_accel.o st_accel-y := st_accel_core.o diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c new file mode 100644 index 00000000000000..1be125bb916129 --- /dev/null +++ b/drivers/iio/accel/mma9551.c @@ -0,0 +1,954 @@ +/* + * Freescale MMA9551L Intelligent Motion-Sensing Platform driver + * Copyright (c) 2014, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MMA9551_DRV_NAME "mma9551" +#define MMA9551_IRQ_NAME "mma9551_event" +#define MMA9551_GPIO_NAME "mma9551_int" +#define MMA9551_GPIO_COUNT 4 + +/* Applications IDs */ +#define MMA9551_APPID_VERSION 0x00 +#define MMA9551_APPID_GPIO 0x03 +#define MMA9551_APPID_AFE 0x06 +#define MMA9551_APPID_TILT 0x0B +#define MMA9551_APPID_SLEEP_WAKE 0x12 +#define MMA9551_APPID_RESET 0x17 +#define MMA9551_APPID_NONE 0xff + +/* Command masks for mailbox write command */ +#define MMA9551_CMD_READ_VERSION_INFO 0x00 +#define MMA9551_CMD_READ_CONFIG 0x10 +#define MMA9551_CMD_WRITE_CONFIG 0x20 +#define MMA9551_CMD_READ_STATUS 0x30 + +enum mma9551_gpio_pin { + mma9551_gpio6 = 0, + mma9551_gpio7, + mma9551_gpio8, + mma9551_gpio9, + mma9551_gpio_max = mma9551_gpio9, +}; + +/* Mailbox read command */ +#define MMA9551_RESPONSE_COCO BIT(7) + +/* Error-Status codes returned in mailbox read command */ +#define MMA9551_MCI_ERROR_NONE 0x00 +#define MMA9551_MCI_ERROR_PARAM 0x04 +#define MMA9551_MCI_INVALID_COUNT 0x19 +#define MMA9551_MCI_ERROR_COMMAND 0x1C +#define MMA9551_MCI_ERROR_INVALID_LENGTH 0x21 +#define MMA9551_MCI_ERROR_FIFO_BUSY 0x22 +#define MMA9551_MCI_ERROR_FIFO_ALLOCATED 0x23 +#define MMA9551_MCI_ERROR_FIFO_OVERSIZE 0x24 + +/* GPIO Application */ +#define MMA9551_GPIO_POL_MSB 0x08 +#define MMA9551_GPIO_POL_LSB 0x09 + +/* Sleep/Wake application */ +#define MMA9551_SLEEP_CFG 0x06 +#define MMA9551_SLEEP_CFG_SNCEN BIT(0) +#define MMA9551_SLEEP_CFG_SCHEN BIT(2) + +/* AFE application */ +#define MMA9551_AFE_X_ACCEL_REG 0x00 +#define MMA9551_AFE_Y_ACCEL_REG 0x02 +#define MMA9551_AFE_Z_ACCEL_REG 0x04 + +/* Tilt application (inclination in IIO terms). */ +#define MMA9551_TILT_XZ_ANG_REG 0x00 +#define MMA9551_TILT_YZ_ANG_REG 0x01 +#define MMA9551_TILT_XY_ANG_REG 0x02 +#define MMA9551_TILT_ANGFLG BIT(7) +#define MMA9551_TILT_QUAD_REG 0x03 +#define MMA9551_TILT_XY_QUAD_SHIFT 0 +#define MMA9551_TILT_YZ_QUAD_SHIFT 2 +#define MMA9551_TILT_XZ_QUAD_SHIFT 4 +#define MMA9551_TILT_CFG_REG 0x01 +#define MMA9551_TILT_ANG_THRESH_MASK GENMASK(3, 0) + +/* Tilt events are mapped to the first three GPIO pins. */ +enum mma9551_tilt_axis { + mma9551_x = 0, + mma9551_y, + mma9551_z, +}; + +/* + * A response is composed of: + * - control registers: MB0-3 + * - data registers: MB4-31 + * + * A request is composed of: + * - mbox to write to (always 0) + * - control registers: MB1-4 + * - data registers: MB5-31 + */ +#define MMA9551_MAILBOX_CTRL_REGS 4 +#define MMA9551_MAX_MAILBOX_DATA_REGS 28 +#define MMA9551_MAILBOX_REGS 32 + +#define MMA9551_I2C_READ_RETRIES 5 +#define MMA9551_I2C_READ_DELAY 50 /* us */ + +struct mma9551_mbox_request { + u8 start_mbox; /* Always 0. */ + u8 app_id; + /* + * See Section 5.3.1 of the MMA955xL Software Reference Manual. + * + * Bit 7: reserved, always 0 + * Bits 6-4: command + * Bits 3-0: upper bits of register offset + */ + u8 cmd_off; + u8 lower_off; + u8 nbytes; + u8 buf[MMA9551_MAX_MAILBOX_DATA_REGS - 1]; +} __packed; + +struct mma9551_mbox_response { + u8 app_id; + /* + * See Section 5.3.3 of the MMA955xL Software Reference Manual. + * + * Bit 7: COCO + * Bits 6-0: Error code. + */ + u8 coco_err; + u8 nbytes; + u8 req_bytes; + u8 buf[MMA9551_MAX_MAILBOX_DATA_REGS]; +} __packed; + +struct mma9551_version_info { + __be32 device_id; + u8 rom_version[2]; + u8 fw_version[2]; + u8 hw_version[2]; + u8 fw_build[2]; +}; + +struct mma9551_data { + struct i2c_client *client; + struct mutex mutex; + int event_enabled[3]; + int irqs[MMA9551_GPIO_COUNT]; +}; + +static int mma9551_transfer(struct i2c_client *client, + u8 app_id, u8 command, u16 offset, + u8 *inbytes, int num_inbytes, + u8 *outbytes, int num_outbytes) +{ + struct mma9551_mbox_request req; + struct mma9551_mbox_response rsp; + struct i2c_msg in, out; + u8 req_len, err_code; + int ret, retries; + + if (offset >= 1 << 12) { + dev_err(&client->dev, "register offset too large\n"); + return -EINVAL; + } + + req_len = 1 + MMA9551_MAILBOX_CTRL_REGS + num_inbytes; + req.start_mbox = 0; + req.app_id = app_id; + req.cmd_off = command | (offset >> 8); + req.lower_off = offset; + + if (command == MMA9551_CMD_WRITE_CONFIG) + req.nbytes = num_inbytes; + else + req.nbytes = num_outbytes; + if (num_inbytes) + memcpy(req.buf, inbytes, num_inbytes); + + out.addr = client->addr; + out.flags = 0; + out.len = req_len; + out.buf = (u8 *)&req; + + ret = i2c_transfer(client->adapter, &out, 1); + if (ret < 0) { + dev_err(&client->dev, "i2c write failed\n"); + return ret; + } + + retries = MMA9551_I2C_READ_RETRIES; + do { + udelay(MMA9551_I2C_READ_DELAY); + + in.addr = client->addr; + in.flags = I2C_M_RD; + in.len = sizeof(rsp); + in.buf = (u8 *)&rsp; + + ret = i2c_transfer(client->adapter, &in, 1); + if (ret < 0) { + dev_err(&client->dev, "i2c read failed\n"); + return ret; + } + + if (rsp.coco_err & MMA9551_RESPONSE_COCO) + break; + } while (--retries > 0); + + if (retries == 0) { + dev_err(&client->dev, + "timed out while waiting for command response\n"); + return -ETIMEDOUT; + } + + if (rsp.app_id != app_id) { + dev_err(&client->dev, + "app_id mismatch in response got %02x expected %02x\n", + rsp.app_id, app_id); + return -EINVAL; + } + + err_code = rsp.coco_err & ~MMA9551_RESPONSE_COCO; + if (err_code != MMA9551_MCI_ERROR_NONE) { + dev_err(&client->dev, "read returned error %x\n", err_code); + return -EINVAL; + } + + if (rsp.nbytes != rsp.req_bytes) { + dev_err(&client->dev, + "output length mismatch got %d expected %d\n", + rsp.nbytes, rsp.req_bytes); + return -EINVAL; + } + + if (num_outbytes) + memcpy(outbytes, rsp.buf, num_outbytes); + + return 0; +} + +static int mma9551_read_config_byte(struct i2c_client *client, u8 app_id, + u16 reg, u8 *val) +{ + return mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG, + reg, NULL, 0, val, 1); +} + +static int mma9551_write_config_byte(struct i2c_client *client, u8 app_id, + u16 reg, u8 val) +{ + return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG, reg, + &val, 1, NULL, 0); +} + +static int mma9551_read_status_byte(struct i2c_client *client, u8 app_id, + u16 reg, u8 *val) +{ + return mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS, + reg, NULL, 0, val, 1); +} + +static int mma9551_read_status_word(struct i2c_client *client, u8 app_id, + u16 reg, u16 *val) +{ + int ret; + __be16 v; + + ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS, + reg, NULL, 0, (u8 *)&v, 2); + *val = be16_to_cpu(v); + + return ret; +} + +static int mma9551_update_config_bits(struct i2c_client *client, u8 app_id, + u16 reg, u8 mask, u8 val) +{ + int ret; + u8 tmp, orig; + + ret = mma9551_read_config_byte(client, app_id, reg, &orig); + if (ret < 0) + return ret; + + tmp = orig & ~mask; + tmp |= val & mask; + + if (tmp == orig) + return 0; + + return mma9551_write_config_byte(client, app_id, reg, tmp); +} + +/* + * The polarity parameter is described in section 6.2.2, page 66, of the + * Software Reference Manual. Basically, polarity=0 means the interrupt + * line has the same value as the selected bit, while polarity=1 means + * the line is inverted. + */ +static int mma9551_gpio_config(struct i2c_client *client, + enum mma9551_gpio_pin pin, + u8 app_id, u8 bitnum, int polarity) +{ + u8 reg, pol_mask, pol_val; + int ret; + + if (pin > mma9551_gpio_max) { + dev_err(&client->dev, "bad GPIO pin\n"); + return -EINVAL; + } + + /* + * Pin 6 is configured by regs 0x00 and 0x01, pin 7 by 0x02 and + * 0x03, and so on. + */ + reg = pin * 2; + + ret = mma9551_write_config_byte(client, MMA9551_APPID_GPIO, + reg, app_id); + if (ret < 0) { + dev_err(&client->dev, "error setting GPIO app_id\n"); + return ret; + } + + ret = mma9551_write_config_byte(client, MMA9551_APPID_GPIO, + reg + 1, bitnum); + if (ret < 0) { + dev_err(&client->dev, "error setting GPIO bit number\n"); + return ret; + } + + switch (pin) { + case mma9551_gpio6: + reg = MMA9551_GPIO_POL_LSB; + pol_mask = 1 << 6; + break; + case mma9551_gpio7: + reg = MMA9551_GPIO_POL_LSB; + pol_mask = 1 << 7; + break; + case mma9551_gpio8: + reg = MMA9551_GPIO_POL_MSB; + pol_mask = 1 << 0; + break; + case mma9551_gpio9: + reg = MMA9551_GPIO_POL_MSB; + pol_mask = 1 << 1; + break; + } + pol_val = polarity ? pol_mask : 0; + + ret = mma9551_update_config_bits(client, MMA9551_APPID_GPIO, reg, + pol_mask, pol_val); + if (ret < 0) + dev_err(&client->dev, "error setting GPIO polarity\n"); + + return ret; +} + +static int mma9551_read_version(struct i2c_client *client) +{ + struct mma9551_version_info info; + int ret; + + ret = mma9551_transfer(client, MMA9551_APPID_VERSION, 0x00, 0x00, + NULL, 0, (u8 *)&info, sizeof(info)); + if (ret < 0) + return ret; + + dev_info(&client->dev, "Device ID 0x%x, firmware version %02x.%02x\n", + be32_to_cpu(info.device_id), info.fw_version[0], + info.fw_version[1]); + + return 0; +} + +/* + * Use 'false' as the second parameter to cause the device to enter + * sleep. + */ +static int mma9551_set_device_state(struct i2c_client *client, + bool enable) +{ + return mma9551_update_config_bits(client, MMA9551_APPID_SLEEP_WAKE, + MMA9551_SLEEP_CFG, + MMA9551_SLEEP_CFG_SNCEN, + enable ? 0 : MMA9551_SLEEP_CFG_SNCEN); +} + +static int mma9551_read_incli_chan(struct i2c_client *client, + const struct iio_chan_spec *chan, + int *val) +{ + u8 quad_shift, angle, quadrant; + u16 reg_addr; + int ret; + + switch (chan->channel2) { + case IIO_MOD_X: + reg_addr = MMA9551_TILT_YZ_ANG_REG; + quad_shift = MMA9551_TILT_YZ_QUAD_SHIFT; + break; + case IIO_MOD_Y: + reg_addr = MMA9551_TILT_XZ_ANG_REG; + quad_shift = MMA9551_TILT_XZ_QUAD_SHIFT; + break; + case IIO_MOD_Z: + reg_addr = MMA9551_TILT_XY_ANG_REG; + quad_shift = MMA9551_TILT_XY_QUAD_SHIFT; + break; + default: + return -EINVAL; + } + + ret = mma9551_read_status_byte(client, MMA9551_APPID_TILT, + reg_addr, &angle); + if (ret < 0) + return ret; + + ret = mma9551_read_status_byte(client, MMA9551_APPID_TILT, + MMA9551_TILT_QUAD_REG, &quadrant); + if (ret < 0) + return ret; + + angle &= ~MMA9551_TILT_ANGFLG; + quadrant = (quadrant >> quad_shift) & 0x03; + + if (quadrant == 1 || quadrant == 3) + *val = 90 * (quadrant + 1) - angle; + else + *val = angle + 90 * quadrant; + + return IIO_VAL_INT; +} + +static int mma9551_read_accel_chan(struct i2c_client *client, + const struct iio_chan_spec *chan, + int *val, int *val2) +{ + u16 reg_addr; + s16 raw_accel; + int ret; + + switch (chan->channel2) { + case IIO_MOD_X: + reg_addr = MMA9551_AFE_X_ACCEL_REG; + break; + case IIO_MOD_Y: + reg_addr = MMA9551_AFE_Y_ACCEL_REG; + break; + case IIO_MOD_Z: + reg_addr = MMA9551_AFE_Z_ACCEL_REG; + break; + default: + return -EINVAL; + } + + ret = mma9551_read_status_word(client, MMA9551_APPID_AFE, + reg_addr, &raw_accel); + if (ret < 0) + return ret; + + *val = raw_accel; + + return IIO_VAL_INT; +} + +static int mma9551_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct mma9551_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_PROCESSED: + switch (chan->type) { + case IIO_INCLI: + mutex_lock(&data->mutex); + ret = mma9551_read_incli_chan(data->client, chan, val); + mutex_unlock(&data->mutex); + return ret; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_ACCEL: + mutex_lock(&data->mutex); + ret = mma9551_read_accel_chan(data->client, + chan, val, val2); + mutex_unlock(&data->mutex); + return ret; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ACCEL: + *val = 0; + *val2 = 2440; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int mma9551_read_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct mma9551_data *data = iio_priv(indio_dev); + + switch (chan->type) { + case IIO_INCLI: + /* IIO counts axes from 1, because IIO_NO_MOD is 0. */ + return data->event_enabled[chan->channel2 - 1]; + default: + return -EINVAL; + } +} + +static int mma9551_config_incli_event(struct iio_dev *indio_dev, + enum iio_modifier axis, + int state) +{ + struct mma9551_data *data = iio_priv(indio_dev); + enum mma9551_tilt_axis mma_axis; + int ret; + + /* IIO counts axes from 1, because IIO_NO_MOD is 0. */ + mma_axis = axis - 1; + + if (data->event_enabled[mma_axis] == state) + return 0; + + if (state == 0) { + ret = mma9551_gpio_config(data->client, mma_axis, + MMA9551_APPID_NONE, 0, 0); + if (ret < 0) + return ret; + } else { + int bitnum; + + /* Bit 7 of each angle register holds the angle flag. */ + switch (axis) { + case IIO_MOD_X: + bitnum = 7 + 8 * MMA9551_TILT_YZ_ANG_REG; + break; + case IIO_MOD_Y: + bitnum = 7 + 8 * MMA9551_TILT_XZ_ANG_REG; + break; + case IIO_MOD_Z: + bitnum = 7 + 8 * MMA9551_TILT_XY_ANG_REG; + break; + default: + return -EINVAL; + } + + ret = mma9551_gpio_config(data->client, mma_axis, + MMA9551_APPID_TILT, bitnum, 0); + if (ret < 0) + return ret; + } + + data->event_enabled[mma_axis] = state; + + return ret; +} + +static int mma9551_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + int state) +{ + struct mma9551_data *data = iio_priv(indio_dev); + int ret; + + switch (chan->type) { + case IIO_INCLI: + mutex_lock(&data->mutex); + ret = mma9551_config_incli_event(indio_dev, + chan->channel2, state); + mutex_unlock(&data->mutex); + return ret; + default: + return -EINVAL; + } +} + +static int mma9551_write_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) +{ + struct mma9551_data *data = iio_priv(indio_dev); + int ret; + + switch (chan->type) { + case IIO_INCLI: + if (val2 != 0 || val < 1 || val > 10) + return -EINVAL; + mutex_lock(&data->mutex); + ret = mma9551_update_config_bits(data->client, + MMA9551_APPID_TILT, + MMA9551_TILT_CFG_REG, + MMA9551_TILT_ANG_THRESH_MASK, + val); + mutex_unlock(&data->mutex); + return ret; + default: + return -EINVAL; + } +} + +static int mma9551_read_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) +{ + struct mma9551_data *data = iio_priv(indio_dev); + int ret; + u8 tmp; + + switch (chan->type) { + case IIO_INCLI: + mutex_lock(&data->mutex); + ret = mma9551_read_config_byte(data->client, + MMA9551_APPID_TILT, + MMA9551_TILT_CFG_REG, &tmp); + mutex_unlock(&data->mutex); + if (ret < 0) + return ret; + *val = tmp & MMA9551_TILT_ANG_THRESH_MASK; + *val2 = 0; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static const struct iio_event_spec mma9551_incli_event = { + .type = IIO_EV_TYPE_ROC, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE), +}; + +#define MMA9551_ACCEL_CHANNEL(axis) { \ + .type = IIO_ACCEL, \ + .modified = 1, \ + .channel2 = axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ +} + +#define MMA9551_INCLI_CHANNEL(axis) { \ + .type = IIO_INCLI, \ + .modified = 1, \ + .channel2 = axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ + .event_spec = &mma9551_incli_event, \ + .num_event_specs = 1, \ +} + +static const struct iio_chan_spec mma9551_channels[] = { + MMA9551_ACCEL_CHANNEL(IIO_MOD_X), + MMA9551_ACCEL_CHANNEL(IIO_MOD_Y), + MMA9551_ACCEL_CHANNEL(IIO_MOD_Z), + + MMA9551_INCLI_CHANNEL(IIO_MOD_X), + MMA9551_INCLI_CHANNEL(IIO_MOD_Y), + MMA9551_INCLI_CHANNEL(IIO_MOD_Z), +}; + +static const struct iio_info mma9551_info = { + .driver_module = THIS_MODULE, + .read_raw = mma9551_read_raw, + .read_event_config = mma9551_read_event_config, + .write_event_config = mma9551_write_event_config, + .read_event_value = mma9551_read_event_value, + .write_event_value = mma9551_write_event_value, +}; + +static irqreturn_t mma9551_event_handler(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct mma9551_data *data = iio_priv(indio_dev); + int i, ret, mma_axis = -1; + u16 reg; + u8 val; + + mutex_lock(&data->mutex); + + for (i = 0; i < 3; i++) + if (irq == data->irqs[i]) { + mma_axis = i; + break; + } + + if (mma_axis == -1) { + /* IRQ was triggered on 4th line, which we don't use. */ + dev_warn(&data->client->dev, + "irq triggered on unused line %d\n", data->irqs[3]); + goto out; + } + + switch (mma_axis) { + case mma9551_x: + reg = MMA9551_TILT_YZ_ANG_REG; + break; + case mma9551_y: + reg = MMA9551_TILT_XZ_ANG_REG; + break; + case mma9551_z: + reg = MMA9551_TILT_XY_ANG_REG; + break; + } + + /* + * Read the angle even though we don't use it, otherwise we + * won't get any further interrupts. + */ + ret = mma9551_read_status_byte(data->client, MMA9551_APPID_TILT, + reg, &val); + if (ret < 0) { + dev_err(&data->client->dev, + "error %d reading tilt register in IRQ\n", ret); + goto out; + } + + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_INCLI, 0, (mma_axis + 1), + IIO_EV_TYPE_ROC, IIO_EV_DIR_RISING), + iio_get_time_ns()); + +out: + mutex_unlock(&data->mutex); + + return IRQ_HANDLED; +} + +static int mma9551_init(struct mma9551_data *data) +{ + int ret; + + ret = mma9551_read_version(data->client); + if (ret) + return ret; + + /* Power on chip and enable doze mode. */ + return mma9551_update_config_bits(data->client, + MMA9551_APPID_SLEEP_WAKE, + MMA9551_SLEEP_CFG, + MMA9551_SLEEP_CFG_SCHEN | MMA9551_SLEEP_CFG_SNCEN, + MMA9551_SLEEP_CFG_SCHEN); +} + +static int mma9551_gpio_probe(struct iio_dev *indio_dev) +{ + struct gpio_desc *gpio; + int i, ret; + struct mma9551_data *data = iio_priv(indio_dev); + struct device *dev = &data->client->dev; + + for (i = 0; i < MMA9551_GPIO_COUNT; i++) { + gpio = devm_gpiod_get_index(dev, MMA9551_GPIO_NAME, i); + if (IS_ERR(gpio)) { + dev_err(dev, "acpi gpio get index failed\n"); + return PTR_ERR(gpio); + } + + ret = gpiod_direction_input(gpio); + if (ret) + return ret; + + data->irqs[i] = gpiod_to_irq(gpio); + ret = devm_request_threaded_irq(dev, data->irqs[i], + NULL, mma9551_event_handler, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + MMA9551_IRQ_NAME, indio_dev); + if (ret < 0) { + dev_err(dev, "request irq %d failed\n", data->irqs[i]); + return ret; + } + + dev_dbg(dev, "gpio resource, no:%d irq:%d\n", + desc_to_gpio(gpio), data->irqs[i]); + } + + return 0; +} + +static const char *mma9551_match_acpi_device(struct device *dev) +{ + const struct acpi_device_id *id; + + id = acpi_match_device(dev->driver->acpi_match_table, dev); + if (!id) + return NULL; + + return dev_name(dev); +} + +static int mma9551_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct mma9551_data *data; + struct iio_dev *indio_dev; + const char *name = NULL; + int ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client = client; + + if (id) + name = id->name; + else if (ACPI_HANDLE(&client->dev)) + name = mma9551_match_acpi_device(&client->dev); + + ret = mma9551_init(data); + if (ret < 0) + return ret; + + mutex_init(&data->mutex); + + indio_dev->dev.parent = &client->dev; + indio_dev->channels = mma9551_channels; + indio_dev->num_channels = ARRAY_SIZE(mma9551_channels); + indio_dev->name = name; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &mma9551_info; + + ret = mma9551_gpio_probe(indio_dev); + if (ret < 0) + goto out_poweroff; + + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(&client->dev, "unable to register iio device\n"); + goto out_poweroff; + } + + return 0; + +out_poweroff: + mma9551_set_device_state(client, false); + + return ret; +} + +static int mma9551_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct mma9551_data *data = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + mutex_lock(&data->mutex); + mma9551_set_device_state(data->client, false); + mutex_unlock(&data->mutex); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int mma9551_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct mma9551_data *data = iio_priv(indio_dev); + + mutex_lock(&data->mutex); + mma9551_set_device_state(data->client, false); + mutex_unlock(&data->mutex); + + return 0; +} + +static int mma9551_resume(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct mma9551_data *data = iio_priv(indio_dev); + + mutex_lock(&data->mutex); + mma9551_set_device_state(data->client, true); + mutex_unlock(&data->mutex); + + return 0; +} +#else +#define mma9551_suspend NULL +#define mma9551_resume NULL +#endif + +static const struct dev_pm_ops mma9551_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(mma9551_suspend, mma9551_resume) +}; + +static const struct acpi_device_id mma9551_acpi_match[] = { + {"MMA9551", 0}, + {}, +}; + +MODULE_DEVICE_TABLE(acpi, mma9551_acpi_match); + +static const struct i2c_device_id mma9551_id[] = { + {"mma9551", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, mma9551_id); + +static struct i2c_driver mma9551_driver = { + .driver = { + .name = MMA9551_DRV_NAME, + .acpi_match_table = ACPI_PTR(mma9551_acpi_match), + .pm = &mma9551_pm_ops, + }, + .probe = mma9551_probe, + .remove = mma9551_remove, + .id_table = mma9551_id, +}; + +module_i2c_driver(mma9551_driver); + +MODULE_AUTHOR("Irina Tirdea "); +MODULE_AUTHOR("Vlad Dogaru "); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("MMA9551L motion-sensing platform driver"); From 3909a0713e19e75410c3ae2ea7dd1242af78b026 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Fri, 12 Dec 2014 13:30:04 +0000 Subject: [PATCH 0170/3023] Revert "iio: imu: Add support for Kionix KMX61 sensor" The two halves of this part can run largely independently. Hence a version 4 of this patch followed that reorganized things completely. This reverts commit d7d787d29148cde12958c2e3765ad3a55dc55eaf. --- drivers/iio/imu/Kconfig | 9 - drivers/iio/imu/Makefile | 2 - drivers/iio/imu/kmx61.c | 766 --------------------------------------- 3 files changed, 777 deletions(-) delete mode 100644 drivers/iio/imu/kmx61.c diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig index d675f43cb76a5d..2b0e45133e9d12 100644 --- a/drivers/iio/imu/Kconfig +++ b/drivers/iio/imu/Kconfig @@ -25,15 +25,6 @@ config ADIS16480 Say yes here to build support for Analog Devices ADIS16375, ADIS16480, ADIS16485, ADIS16488 inertial sensors. -config KMX61 - tristate "Kionix KMX61 6-axis accelerometer and magnetometer" - depends on I2C - help - Say Y here if you want to build a driver for Kionix KMX61 6-axis accelerometer - and magnetometer. - To compile this driver as module, choose M here: the module will be called - kmx61. - source "drivers/iio/imu/inv_mpu6050/Kconfig" endmenu diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile index e1e6e3d70e26df..114d2c17cbe204 100644 --- a/drivers/iio/imu/Makefile +++ b/drivers/iio/imu/Makefile @@ -14,5 +14,3 @@ adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o obj-y += inv_mpu6050/ - -obj-$(CONFIG_KMX61) += kmx61.o diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c deleted file mode 100644 index f68b3ef1a57560..00000000000000 --- a/drivers/iio/imu/kmx61.c +++ /dev/null @@ -1,766 +0,0 @@ -/* - * KMX61 - Kionix 6-axis Accelerometer/Magnetometer - * - * Copyright (c) 2014, Intel Corporation. - * - * This file is subject to the terms and conditions of version 2 of - * the GNU General Public License. See the file COPYING in the main - * directory of this archive for more details. - * - * IIO driver for KMX61 (7-bit I2C slave address 0x0E or 0x0F). - * - * TODO: buffer, interrupt, thresholds, acpi, temperature sensor - * - */ - -#include -#include -#include -#include -#include -#include - -#define KMX61_DRV_NAME "kmx61" - -#define KMX61_REG_WHO_AM_I 0x00 - -/* - * three 16-bit accelerometer output registers for X/Y/Z axis - * we use only XOUT_L as a base register, all other addresses - * can be obtained by applying an offset and are provided here - * only for clarity. - */ -#define KMX61_ACC_XOUT_L 0x0A -#define KMX61_ACC_XOUT_H 0x0B -#define KMX61_ACC_YOUT_L 0x0C -#define KMX61_ACC_YOUT_H 0x0D -#define KMX61_ACC_ZOUT_L 0x0E -#define KMX61_ACC_ZOUT_H 0x0F - -/* - * one 16-bit temperature output register - */ -#define KMX61_TEMP_L 0x10 -#define KMX61_TEMP_H 0x11 - -/* - * three 16-bit magnetometer output registers for X/Y/Z axis - */ -#define KMX61_MAG_XOUT_L 0x12 -#define KMX61_MAG_XOUT_H 0x13 -#define KMX61_MAG_YOUT_L 0x14 -#define KMX61_MAG_YOUT_H 0x15 -#define KMX61_MAG_ZOUT_L 0x16 -#define KMX61_MAG_ZOUT_H 0x17 - -#define KMX61_REG_ODCNTL 0x2C -#define KMX61_REG_STBY 0x29 -#define KMX61_REG_CTRL1 0x2A - -#define KMX61_ACC_STBY_BIT BIT(0) -#define KMX61_MAG_STBY_BIT BIT(1) -#define KMX61_ACT_STBY_BIT BIT(7) - -#define KMX61_ALL_STBY (KMX61_ACC_STBY_BIT | KMX61_MAG_STBY_BIT) - -#define KMX61_REG_CTRL1_GSEL0_SHIFT 0 -#define KMX61_REG_CTRL1_GSEL1_SHIFT 1 -#define KMX61_REG_CTRL1_GSEL0_MASK 0x01 -#define KMX61_REG_CTRL1_GSEL1_MASK 0x02 - -#define KMX61_REG_CTRL1_BIT_RES BIT(4) - -#define KMX61_ACC_ODR_SHIFT 0 -#define KMX61_MAG_ODR_SHIFT 4 -#define KMX61_ACC_ODR_MASK 0x0F -#define KMX61_MAG_ODR_MASK 0xF0 - -#define KMX61_SLEEP_DELAY_MS 2000 - -#define KMX61_CHIP_ID 0x12 - -struct kmx61_data { - struct i2c_client *client; - - /* serialize access to non-atomic ops, e.g set_mode */ - struct mutex lock; - u8 range; - u8 odr_bits; - - /* standby state */ - u8 acc_stby; - u8 mag_stby; - - /* power state */ - bool acc_ps; - bool mag_ps; -}; - -enum kmx61_range { - KMX61_RANGE_2G, - KMX61_RANGE_4G, - KMX61_RANGE_8G, -}; - -enum kmx61_scan { - KMX61_SCAN_ACC_X, - KMX61_SCAN_ACC_Y, - KMX61_SCAN_ACC_Z, - KMX61_SCAN_TEMP, - KMX61_SCAN_MAG_X, - KMX61_SCAN_MAG_Y, - KMX61_SCAN_MAG_Z, -}; - -static const struct { - u16 uscale; - u8 gsel0; - u8 gsel1; -} kmx61_scale_table[] = { - {9582, 0, 0}, - {19163, 1, 0}, - {38326, 0, 1}, -}; - -/* KMX61 devices */ -#define KMX61_ACC 0x01 -#define KMX61_MAG 0x02 - -static const struct { - int val; - int val2; - u8 odr_bits; -} kmx61_samp_freq_table[] = { {12, 500000, 0x00}, - {25, 0, 0x01}, - {50, 0, 0x02}, - {100, 0, 0x03}, - {200, 0, 0x04}, - {400, 0, 0x05}, - {800, 0, 0x06}, - {1600, 0, 0x07}, - {0, 781000, 0x08}, - {1, 563000, 0x09}, - {3, 125000, 0x0A}, - {6, 250000, 0x0B} }; - -static IIO_CONST_ATTR(accel_scale_available, "0.009582 0.019163 0.038326"); -static IIO_CONST_ATTR(magn_scale_available, "0.001465"); -static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( - "0.781000 1.563000 3.125000 6.250000 12.500000 25 50 100 200 400 800"); - -static struct attribute *kmx61_attributes[] = { - &iio_const_attr_accel_scale_available.dev_attr.attr, - &iio_const_attr_magn_scale_available.dev_attr.attr, - &iio_const_attr_sampling_frequency_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group kmx61_attribute_group = { - .attrs = kmx61_attributes, -}; - -#define KMX61_ACC_CHAN(_axis, _index) { \ - .type = IIO_ACCEL, \ - .modified = 1, \ - .channel2 = IIO_MOD_ ## _axis, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ - BIT(IIO_CHAN_INFO_SAMP_FREQ), \ - .address = KMX61_ACC, \ - .scan_index = _index, \ - .scan_type = { \ - .sign = 's', \ - .realbits = 12, \ - .storagebits = 16, \ - .shift = 4, \ - .endianness = IIO_LE, \ - }, \ -} - -#define KMX61_MAG_CHAN(_axis, _index) { \ - .type = IIO_MAGN, \ - .modified = 1, \ - .channel2 = IIO_MOD_ ## _axis, \ - .address = KMX61_MAG, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ - BIT(IIO_CHAN_INFO_SAMP_FREQ), \ - .scan_index = _index, \ - .scan_type = { \ - .sign = 's', \ - .realbits = 14, \ - .storagebits = 16, \ - .shift = 2, \ - .endianness = IIO_LE, \ - }, \ -} - -static const struct iio_chan_spec kmx61_channels[] = { - KMX61_ACC_CHAN(X, KMX61_SCAN_ACC_X), - KMX61_ACC_CHAN(Y, KMX61_SCAN_ACC_Y), - KMX61_ACC_CHAN(Z, KMX61_SCAN_ACC_Z), - KMX61_MAG_CHAN(X, KMX61_SCAN_MAG_X), - KMX61_MAG_CHAN(Y, KMX61_SCAN_MAG_Y), - KMX61_MAG_CHAN(Z, KMX61_SCAN_MAG_Z), -}; - -static int kmx61_convert_freq_to_bit(int val, int val2) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++) - if (val == kmx61_samp_freq_table[i].val && - val2 == kmx61_samp_freq_table[i].val2) - return kmx61_samp_freq_table[i].odr_bits; - return -EINVAL; -} -/** - * kmx61_set_mode() - set KMX61 device operating mode - * @data - kmx61 device private data pointer - * @mode - bitmask, indicating operating mode for @device - * @device - bitmask, indicating device for which @mode needs to be set - * @update - update stby bits stored in device's private @data - * - * For each sensor (accelerometer/magnetometer) there are two operating modes - * STANDBY and OPERATION. Neither accel nor magn can be disabled independently - * if they are both enabled. Internal sensors state is saved in acc_stby and - * mag_stby members of driver's private @data. - */ -static int kmx61_set_mode(struct kmx61_data *data, u8 mode, u8 device, - bool update) -{ - int ret; - int acc_stby = -1, mag_stby = -1; - - ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_STBY); - if (ret < 0) { - dev_err(&data->client->dev, "Error reading reg_stby\n"); - return ret; - } - if (device & KMX61_ACC) { - if (mode & KMX61_ACC_STBY_BIT) { - ret |= KMX61_ACC_STBY_BIT; - acc_stby = 1; - } else { - ret &= ~KMX61_ACC_STBY_BIT; - acc_stby = 0; - } - } - - if (device & KMX61_MAG) { - if (mode & KMX61_MAG_STBY_BIT) { - ret |= KMX61_MAG_STBY_BIT; - mag_stby = 1; - } else { - ret &= ~KMX61_MAG_STBY_BIT; - mag_stby = 0; - } - } - - ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_STBY, ret); - if (ret < 0) { - dev_err(&data->client->dev, "Error writing reg_stby\n"); - return ret; - } - - if (acc_stby != -1 && update) - data->acc_stby = !!acc_stby; - if (mag_stby != -1 && update) - data->mag_stby = !!mag_stby; - - return ret; -} - -static int kmx61_get_mode(struct kmx61_data *data, u8 *mode, u8 device) -{ - int ret; - - ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_STBY); - if (ret < 0) { - dev_err(&data->client->dev, "Error reading reg_stby\n"); - return ret; - } - *mode = 0; - - if (device & KMX61_ACC) { - if (ret & KMX61_ACC_STBY_BIT) - *mode |= KMX61_ACC_STBY_BIT; - else - *mode &= ~KMX61_ACC_STBY_BIT; - } - - if (device & KMX61_MAG) { - if (ret & KMX61_MAG_STBY_BIT) - *mode |= KMX61_MAG_STBY_BIT; - else - *mode &= ~KMX61_MAG_STBY_BIT; - } - - return 0; -} - -static int kmx61_set_odr(struct kmx61_data *data, int val, int val2, u8 device) -{ - int ret; - u8 mode; - int lodr_bits, odr_bits; - - ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG); - if (ret < 0) - return ret; - - lodr_bits = kmx61_convert_freq_to_bit(val, val2); - if (lodr_bits < 0) - return lodr_bits; - - /* To change ODR, accel and magn must be in STDBY */ - ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, - true); - if (ret < 0) - return ret; - - odr_bits = 0; - if (device & KMX61_ACC) - odr_bits |= lodr_bits; - if (device & KMX61_MAG) - odr_bits |= (lodr_bits << KMX61_MAG_ODR_SHIFT); - - ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_ODCNTL, - odr_bits); - if (ret < 0) - return ret; - - ret = kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); - if (ret < 0) - return ret; - - data->odr_bits = lodr_bits; - - return 0; -} - -static -int kmx61_get_odr(struct kmx61_data *data, int *val, int *val2, u8 device) -{ int i; - u8 lodr_bits; - - if (device & KMX61_ACC) - lodr_bits = (data->odr_bits >> KMX61_ACC_ODR_SHIFT) & - KMX61_ACC_ODR_MASK; - else if (device & KMX61_MAG) - lodr_bits = (data->odr_bits >> KMX61_MAG_ODR_SHIFT) & - KMX61_MAG_ODR_MASK; - else - return -EINVAL; - - for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++) - if (lodr_bits == kmx61_samp_freq_table[i].odr_bits) { - *val = kmx61_samp_freq_table[i].val; - *val2 = kmx61_samp_freq_table[i].val2; - return 0; - } - return -EINVAL; -} - -static int kmx61_set_range(struct kmx61_data *data, int range) -{ - int ret; - - ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1); - if (ret < 0) { - dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); - return ret; - } - - ret &= ~(KMX61_REG_CTRL1_GSEL0_MASK | KMX61_REG_CTRL1_GSEL1_MASK); - ret |= kmx61_scale_table[range].gsel0 << KMX61_REG_CTRL1_GSEL0_SHIFT; - ret |= kmx61_scale_table[range].gsel1 << KMX61_REG_CTRL1_GSEL1_SHIFT; - - ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret); - if (ret < 0) { - dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); - return ret; - } - - data->range = range; - - return 0; -} - -static int kmx61_set_scale(struct kmx61_data *data, int uscale) -{ - int ret, i; - u8 mode; - - for (i = 0; i < ARRAY_SIZE(kmx61_scale_table); i++) { - if (kmx61_scale_table[i].uscale == uscale) { - ret = kmx61_get_mode(data, &mode, - KMX61_ACC | KMX61_MAG); - if (ret < 0) - return ret; - - ret = kmx61_set_mode(data, KMX61_ALL_STBY, - KMX61_ACC | KMX61_MAG, true); - if (ret < 0) - return ret; - - ret = kmx61_set_range(data, i); - if (ret < 0) - return ret; - - return kmx61_set_mode(data, mode, - KMX61_ACC | KMX61_MAG, true); - } - } - return -EINVAL; -} - -static int kmx61_chip_init(struct kmx61_data *data) -{ - int ret; - - ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_WHO_AM_I); - if (ret < 0) { - dev_err(&data->client->dev, "Error reading who_am_i\n"); - return ret; - } - - if (ret != KMX61_CHIP_ID) { - dev_err(&data->client->dev, - "Wrong chip id, got %x expected %x\n", - ret, KMX61_CHIP_ID); - return -EINVAL; - } - - /* set accel 12bit, 4g range */ - ret = kmx61_set_range(data, KMX61_RANGE_4G); - if (ret < 0) - return ret; - - /* set acc/magn to OPERATION mode */ - ret = kmx61_set_mode(data, 0, KMX61_ACC | KMX61_MAG, true); - if (ret < 0) - return ret; - - return 0; -} -/** - * kmx61_set_power_state() - set power state for kmx61 @device - * @data - kmx61 device private pointer - * @on - power state to be set for @device - * @device - bitmask indicating device for which @on state needs to be set - * - * Notice that when ACC power state needs to be set to ON and MAG is in - * OPERATION then we know that kmx61_runtime_resume was already called - * so we must set ACC OPERATION mode here. The same happens when MAG power - * state needs to be set to ON and ACC is in OPERATION. - */ -static int kmx61_set_power_state(struct kmx61_data *data, bool on, u8 device) -{ -#ifdef CONFIG_PM_RUNTIME - int ret; - - if (device & KMX61_ACC) { - if (on && !data->acc_ps && !data->mag_stby) - kmx61_set_mode(data, 0, KMX61_ACC, true); - data->acc_ps = on; - } - if (device & KMX61_MAG) { - if (on && !data->mag_ps && !data->acc_stby) - kmx61_set_mode(data, 0, KMX61_MAG, true); - data->mag_ps = on; - } - - if (on) { - ret = pm_runtime_get_sync(&data->client->dev); - } else { - pm_runtime_mark_last_busy(&data->client->dev); - ret = pm_runtime_put_autosuspend(&data->client->dev); - } - if (ret < 0) { - dev_err(&data->client->dev, - "Failed: kmx61_set_power_state for %d, ret %d\n", - on, ret); - return ret; - } -#endif - return 0; -} - -static int kmx61_read_measurement(struct kmx61_data *data, int base, int offset) -{ - int ret; - u8 reg = base + offset * 2; - - ret = i2c_smbus_read_word_data(data->client, reg); - if (ret < 0) { - dev_err(&data->client->dev, "failed to read reg at %x\n", reg); - return ret; - } - - return ret; -} - -static int kmx61_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, int *val, - int *val2, long mask) -{ - struct kmx61_data *data = iio_priv(indio_dev); - int ret; - u8 base_reg; - - switch (mask) { - case IIO_CHAN_INFO_RAW: - switch (chan->type) { - case IIO_ACCEL: - case IIO_MAGN: - base_reg = KMX61_ACC_XOUT_L; - break; - default: - return -EINVAL; - } - mutex_lock(&data->lock); - - kmx61_set_power_state(data, true, chan->address); - ret = kmx61_read_measurement(data, base_reg, chan->scan_index); - if (ret < 0) { - kmx61_set_power_state(data, false, chan->address); - mutex_unlock(&data->lock); - return ret; - } - *val = sign_extend32(ret >> chan->scan_type.shift, - chan->scan_type.realbits - 1); - kmx61_set_power_state(data, false, chan->address); - - mutex_unlock(&data->lock); - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - switch (chan->type) { - case IIO_ACCEL: - *val = 0; - *val2 = kmx61_scale_table[data->range].uscale; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_MAGN: - /* 14 bits res, 1465 microGauss per magn count */ - *val = 0; - *val2 = 1465; - return IIO_VAL_INT_PLUS_MICRO; - default: - return -EINVAL; - } - case IIO_CHAN_INFO_SAMP_FREQ: - if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN) - return -EINVAL; - - mutex_lock(&data->lock); - ret = kmx61_get_odr(data, val, val2, chan->address); - mutex_unlock(&data->lock); - if (ret) - return -EINVAL; - return IIO_VAL_INT_PLUS_MICRO; - } - return -EINVAL; -} - -static int kmx61_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, int val, - int val2, long mask) -{ - struct kmx61_data *data = iio_priv(indio_dev); - int ret; - - switch (mask) { - case IIO_CHAN_INFO_SAMP_FREQ: - if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN) - return -EINVAL; - - mutex_lock(&data->lock); - ret = kmx61_set_odr(data, val, val2, chan->address); - mutex_unlock(&data->lock); - return ret; - case IIO_CHAN_INFO_SCALE: - switch (chan->type) { - case IIO_ACCEL: - if (val != 0) - return -EINVAL; - mutex_lock(&data->lock); - ret = kmx61_set_scale(data, val2); - mutex_unlock(&data->lock); - return ret; - default: - return -EINVAL; - } - return ret; - default: - return -EINVAL; - } - return ret; -} - -static const struct iio_info kmx61_info = { - .driver_module = THIS_MODULE, - .read_raw = kmx61_read_raw, - .write_raw = kmx61_write_raw, - .attrs = &kmx61_attribute_group, -}; - -static int kmx61_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct kmx61_data *data; - struct iio_dev *indio_dev; - int ret; - const char *name = NULL; - - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); - if (!indio_dev) - return -ENOMEM; - - data = iio_priv(indio_dev); - i2c_set_clientdata(client, indio_dev); - data->client = client; - - if (id) - name = id->name; - - indio_dev->dev.parent = &client->dev; - indio_dev->channels = kmx61_channels; - indio_dev->num_channels = ARRAY_SIZE(kmx61_channels); - indio_dev->name = name; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->info = &kmx61_info; - - mutex_init(&data->lock); - - ret = kmx61_chip_init(data); - if (ret < 0) - return ret; - - ret = iio_device_register(indio_dev); - if (ret < 0) { - dev_err(&client->dev, "Failed to register iio device\n"); - goto err_iio_device_register; - } - - ret = pm_runtime_set_active(&client->dev); - if (ret < 0) - goto err_pm_runtime_set_active; - - pm_runtime_enable(&client->dev); - pm_runtime_set_autosuspend_delay(&client->dev, KMX61_SLEEP_DELAY_MS); - pm_runtime_use_autosuspend(&client->dev); - - return 0; - -err_pm_runtime_set_active: - iio_device_unregister(indio_dev); -err_iio_device_register: - kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); - return ret; -} - -static int kmx61_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct kmx61_data *data = iio_priv(indio_dev); - int ret; - - pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); - pm_runtime_put_noidle(&client->dev); - - iio_device_unregister(indio_dev); - - mutex_lock(&data->lock); - ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); - mutex_unlock(&data->lock); - - return ret; -} - -#ifdef CONFIG_PM_SLEEP -static int kmx61_suspend(struct device *dev) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); - struct kmx61_data *data = iio_priv(indio_dev); - int ret; - - mutex_lock(&data->lock); - ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, - false); - mutex_unlock(&data->lock); - - return ret; -} - -static int kmx61_resume(struct device *dev) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); - struct kmx61_data *data = iio_priv(indio_dev); - u8 stby = 0; - - if (data->acc_stby) - stby |= KMX61_ACC_STBY_BIT; - if (data->mag_stby) - stby |= KMX61_MAG_STBY_BIT; - - return kmx61_set_mode(data, stby, KMX61_ACC | KMX61_MAG, true); -} -#endif - -#ifdef CONFIG_PM_RUNTIME -static int kmx61_runtime_suspend(struct device *dev) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); - struct kmx61_data *data = iio_priv(indio_dev); - int ret; - - mutex_lock(&data->lock); - ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); - mutex_unlock(&data->lock); - - return ret; -} - -static int kmx61_runtime_resume(struct device *dev) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); - struct kmx61_data *data = iio_priv(indio_dev); - u8 stby = 0; - - if (!data->acc_ps) - stby |= KMX61_ACC_STBY_BIT; - if (!data->mag_ps) - stby |= KMX61_MAG_STBY_BIT; - - return kmx61_set_mode(data, stby, KMX61_ACC | KMX61_MAG, true); -} -#endif - -static const struct dev_pm_ops kmx61_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(kmx61_suspend, kmx61_resume) - SET_RUNTIME_PM_OPS(kmx61_runtime_suspend, kmx61_runtime_resume, NULL) -}; - -static const struct i2c_device_id kmx61_id[] = { - {"kmx611021", 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, kmx61_id); - -static struct i2c_driver kmx61_driver = { - .driver = { - .name = KMX61_DRV_NAME, - .pm = &kmx61_pm_ops, - }, - .probe = kmx61_probe, - .remove = kmx61_remove, - .id_table = kmx61_id, -}; - -module_i2c_driver(kmx61_driver); - -MODULE_AUTHOR("Daniel Baluta "); -MODULE_DESCRIPTION("KMX61 accelerometer/magnetometer driver"); -MODULE_LICENSE("GPL v2"); From 20ffac278ebd64ad031149628560f47990910dd7 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 3 Dec 2014 15:31:48 +0200 Subject: [PATCH 0171/3023] iio: imu: Add support for Kionix KMX61 sensor Minimal implementation for KMX61 6-axis accelerometer/magnetometer. It exports raw accel/magn readings together with scale and sampling frequency. This driver uses two IIO devices one for accelerometer and one for magnetometer. Datasheet will be available at: http://www.kionix.com/6-axis-accelerometer-magnetometer/kmx61 Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/imu/Kconfig | 9 + drivers/iio/imu/Makefile | 2 + drivers/iio/imu/kmx61.c | 691 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 702 insertions(+) create mode 100644 drivers/iio/imu/kmx61.c diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig index 2b0e45133e9d12..db4221db10f20f 100644 --- a/drivers/iio/imu/Kconfig +++ b/drivers/iio/imu/Kconfig @@ -25,6 +25,15 @@ config ADIS16480 Say yes here to build support for Analog Devices ADIS16375, ADIS16480, ADIS16485, ADIS16488 inertial sensors. +config KMX61 + tristate "Kionix KMX61 6-axis accelerometer and magnetometer" + depends on I2C + help + Say Y here if you want to build a driver for Kionix KMX61 6-axis + accelerometer and magnetometer. + To compile this driver as module, choose M here: the module will + be called kmx61. + source "drivers/iio/imu/inv_mpu6050/Kconfig" endmenu diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile index 114d2c17cbe204..e1e6e3d70e26df 100644 --- a/drivers/iio/imu/Makefile +++ b/drivers/iio/imu/Makefile @@ -14,3 +14,5 @@ adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o obj-y += inv_mpu6050/ + +obj-$(CONFIG_KMX61) += kmx61.o diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c new file mode 100644 index 00000000000000..5231d8f3b1671f --- /dev/null +++ b/drivers/iio/imu/kmx61.c @@ -0,0 +1,691 @@ +/* + * KMX61 - Kionix 6-axis Accelerometer/Magnetometer + * + * Copyright (c) 2014, Intel Corporation. + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * IIO driver for KMX61 (7-bit I2C slave address 0x0E or 0x0F). + * + */ + +#include +#include +#include +#include + +#define KMX61_DRV_NAME "kmx61" + +#define KMX61_REG_WHO_AM_I 0x00 + +/* + * three 16-bit accelerometer output registers for X/Y/Z axis + * we use only XOUT_L as a base register, all other addresses + * can be obtained by applying an offset and are provided here + * only for clarity. + */ +#define KMX61_ACC_XOUT_L 0x0A +#define KMX61_ACC_XOUT_H 0x0B +#define KMX61_ACC_YOUT_L 0x0C +#define KMX61_ACC_YOUT_H 0x0D +#define KMX61_ACC_ZOUT_L 0x0E +#define KMX61_ACC_ZOUT_H 0x0F + +/* + * one 16-bit temperature output register + */ +#define KMX61_TEMP_L 0x10 +#define KMX61_TEMP_H 0x11 + +/* + * three 16-bit magnetometer output registers for X/Y/Z axis + */ +#define KMX61_MAG_XOUT_L 0x12 +#define KMX61_MAG_XOUT_H 0x13 +#define KMX61_MAG_YOUT_L 0x14 +#define KMX61_MAG_YOUT_H 0x15 +#define KMX61_MAG_ZOUT_L 0x16 +#define KMX61_MAG_ZOUT_H 0x17 + +#define KMX61_REG_STBY 0x29 +#define KMX61_REG_CTRL1 0x2A +#define KMX61_REG_ODCNTL 0x2C + +#define KMX61_ACC_STBY_BIT BIT(0) +#define KMX61_MAG_STBY_BIT BIT(1) +#define KMX61_ACT_STBY_BIT BIT(7) + +#define KMX61_ALL_STBY (KMX61_ACC_STBY_BIT | KMX61_MAG_STBY_BIT) + +#define KMX61_REG_CTRL1_GSEL_MASK 0x03 + +#define KMX61_ACC_ODR_SHIFT 0 +#define KMX61_MAG_ODR_SHIFT 4 +#define KMX61_ACC_ODR_MASK 0x0F +#define KMX61_MAG_ODR_MASK 0xF0 + +#define KMX61_CHIP_ID 0x12 + +/* KMX61 devices */ +#define KMX61_ACC 0x01 +#define KMX61_MAG 0x02 + +struct kmx61_data { + struct i2c_client *client; + + /* serialize access to non-atomic ops, e.g set_mode */ + struct mutex lock; + + /* standby state */ + bool acc_stby; + bool mag_stby; + + /* config bits */ + u8 range; + u8 odr_bits; + + /* accelerometer specific data */ + struct iio_dev *acc_indio_dev; + + /* magnetometer specific data */ + struct iio_dev *mag_indio_dev; +}; + +enum kmx61_range { + KMX61_RANGE_2G, + KMX61_RANGE_4G, + KMX61_RANGE_8G, +}; + +enum kmx61_axis { + KMX61_AXIS_X, + KMX61_AXIS_Y, + KMX61_AXIS_Z, +}; + +static const u16 kmx61_uscale_table[] = {9582, 19163, 38326}; + +static const struct { + int val; + int val2; + u8 odr_bits; +} kmx61_samp_freq_table[] = { {12, 500000, 0x00}, + {25, 0, 0x01}, + {50, 0, 0x02}, + {100, 0, 0x03}, + {200, 0, 0x04}, + {400, 0, 0x05}, + {800, 0, 0x06}, + {1600, 0, 0x07}, + {0, 781000, 0x08}, + {1, 563000, 0x09}, + {3, 125000, 0x0A}, + {6, 250000, 0x0B} }; + +static IIO_CONST_ATTR(accel_scale_available, "0.009582 0.019163 0.038326"); +static IIO_CONST_ATTR(magn_scale_available, "0.001465"); +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( + "0.781000 1.563000 3.125000 6.250000 12.500000 25 50 100 200 400 800"); + +static struct attribute *kmx61_acc_attributes[] = { + &iio_const_attr_accel_scale_available.dev_attr.attr, + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + NULL, +}; + +static struct attribute *kmx61_mag_attributes[] = { + &iio_const_attr_magn_scale_available.dev_attr.attr, + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group kmx61_acc_attribute_group = { + .attrs = kmx61_acc_attributes, +}; + +static const struct attribute_group kmx61_mag_attribute_group = { + .attrs = kmx61_mag_attributes, +}; + +#define KMX61_ACC_CHAN(_axis) { \ + .type = IIO_ACCEL, \ + .modified = 1, \ + .channel2 = IIO_MOD_ ## _axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .address = KMX61_ACC, \ + .scan_index = KMX61_AXIS_ ## _axis, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 12, \ + .storagebits = 16, \ + .shift = 4, \ + .endianness = IIO_LE, \ + }, \ +} + +#define KMX61_MAG_CHAN(_axis) { \ + .type = IIO_MAGN, \ + .modified = 1, \ + .channel2 = IIO_MOD_ ## _axis, \ + .address = KMX61_MAG, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index = KMX61_AXIS_ ## _axis, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 14, \ + .storagebits = 16, \ + .shift = 2, \ + .endianness = IIO_LE, \ + }, \ +} + +static const struct iio_chan_spec kmx61_acc_channels[] = { + KMX61_ACC_CHAN(X), + KMX61_ACC_CHAN(Y), + KMX61_ACC_CHAN(Z), +}; + +static const struct iio_chan_spec kmx61_mag_channels[] = { + KMX61_MAG_CHAN(X), + KMX61_MAG_CHAN(Y), + KMX61_MAG_CHAN(Z), +}; + +static void kmx61_set_data(struct iio_dev *indio_dev, struct kmx61_data *data) +{ + struct kmx61_data **priv = iio_priv(indio_dev); + + *priv = data; +} + +static struct kmx61_data *kmx61_get_data(struct iio_dev *indio_dev) +{ + return *(struct kmx61_data **)iio_priv(indio_dev); +} + +static int kmx61_convert_freq_to_bit(int val, int val2) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++) + if (val == kmx61_samp_freq_table[i].val && + val2 == kmx61_samp_freq_table[i].val2) + return kmx61_samp_freq_table[i].odr_bits; + return -EINVAL; +} + +/** + * kmx61_set_mode() - set KMX61 device operating mode + * @data - kmx61 device private data pointer + * @mode - bitmask, indicating operating mode for @device + * @device - bitmask, indicating device for which @mode needs to be set + * @update - update stby bits stored in device's private @data + * + * For each sensor (accelerometer/magnetometer) there are two operating modes + * STANDBY and OPERATION. Neither accel nor magn can be disabled independently + * if they are both enabled. Internal sensors state is saved in acc_stby and + * mag_stby members of driver's private @data. + */ +static int kmx61_set_mode(struct kmx61_data *data, u8 mode, u8 device, + bool update) +{ + int ret; + int acc_stby = -1, mag_stby = -1; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_STBY); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_stby\n"); + return ret; + } + if (device & KMX61_ACC) { + if (mode & KMX61_ACC_STBY_BIT) { + ret |= KMX61_ACC_STBY_BIT; + acc_stby = 1; + } else { + ret &= ~KMX61_ACC_STBY_BIT; + acc_stby = 0; + } + } + + if (device & KMX61_MAG) { + if (mode & KMX61_MAG_STBY_BIT) { + ret |= KMX61_MAG_STBY_BIT; + mag_stby = 1; + } else { + ret &= ~KMX61_MAG_STBY_BIT; + mag_stby = 0; + } + } + + if (mode & KMX61_ACT_STBY_BIT) + ret |= KMX61_ACT_STBY_BIT; + + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_STBY, ret); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_stby\n"); + return ret; + } + + if (acc_stby != -1 && update) + data->acc_stby = acc_stby; + if (mag_stby != -1 && update) + data->mag_stby = mag_stby; + + return 0; +} + +static int kmx61_get_mode(struct kmx61_data *data, u8 *mode, u8 device) +{ + int ret; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_STBY); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_stby\n"); + return ret; + } + *mode = 0; + + if (device & KMX61_ACC) { + if (ret & KMX61_ACC_STBY_BIT) + *mode |= KMX61_ACC_STBY_BIT; + else + *mode &= ~KMX61_ACC_STBY_BIT; + } + + if (device & KMX61_MAG) { + if (ret & KMX61_MAG_STBY_BIT) + *mode |= KMX61_MAG_STBY_BIT; + else + *mode &= ~KMX61_MAG_STBY_BIT; + } + + return 0; +} + +static int kmx61_set_odr(struct kmx61_data *data, int val, int val2, u8 device) +{ + int ret; + u8 mode; + int lodr_bits, odr_bits; + + ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG); + if (ret < 0) + return ret; + + lodr_bits = kmx61_convert_freq_to_bit(val, val2); + if (lodr_bits < 0) + return lodr_bits; + + /* To change ODR, accel and magn must be in STDBY */ + ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, + true); + if (ret < 0) + return ret; + + odr_bits = 0; + if (device & KMX61_ACC) + odr_bits |= lodr_bits << KMX61_ACC_ODR_SHIFT; + if (device & KMX61_MAG) + odr_bits |= lodr_bits << KMX61_MAG_ODR_SHIFT; + + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_ODCNTL, + odr_bits); + if (ret < 0) + return ret; + + return kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); +} + +static int kmx61_get_odr(struct kmx61_data *data, int *val, int *val2, + u8 device) +{ int i; + u8 lodr_bits; + + if (device & KMX61_ACC) + lodr_bits = (data->odr_bits >> KMX61_ACC_ODR_SHIFT) & + KMX61_ACC_ODR_MASK; + else if (device & KMX61_MAG) + lodr_bits = (data->odr_bits >> KMX61_MAG_ODR_SHIFT) & + KMX61_MAG_ODR_MASK; + else + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++) + if (lodr_bits == kmx61_samp_freq_table[i].odr_bits) { + *val = kmx61_samp_freq_table[i].val; + *val2 = kmx61_samp_freq_table[i].val2; + return 0; + } + return -EINVAL; +} + +static int kmx61_set_range(struct kmx61_data *data, u8 range) +{ + int ret; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); + return ret; + } + + ret &= ~KMX61_REG_CTRL1_GSEL_MASK; + ret |= range & KMX61_REG_CTRL1_GSEL_MASK; + + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); + return ret; + } + + data->range = range; + + return 0; +} + +static int kmx61_set_scale(struct kmx61_data *data, u16 uscale) +{ + int ret, i; + u8 mode; + + for (i = 0; i < ARRAY_SIZE(kmx61_uscale_table); i++) { + if (kmx61_uscale_table[i] == uscale) { + ret = kmx61_get_mode(data, &mode, + KMX61_ACC | KMX61_MAG); + if (ret < 0) + return ret; + + ret = kmx61_set_mode(data, KMX61_ALL_STBY, + KMX61_ACC | KMX61_MAG, true); + if (ret < 0) + return ret; + + ret = kmx61_set_range(data, i); + if (ret < 0) + return ret; + + return kmx61_set_mode(data, mode, + KMX61_ACC | KMX61_MAG, true); + } + } + return -EINVAL; +} + +static int kmx61_chip_init(struct kmx61_data *data) +{ + int ret; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_WHO_AM_I); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading who_am_i\n"); + return ret; + } + + if (ret != KMX61_CHIP_ID) { + dev_err(&data->client->dev, + "Wrong chip id, got %x expected %x\n", + ret, KMX61_CHIP_ID); + return -EINVAL; + } + + /* set accel 12bit, 4g range */ + ret = kmx61_set_range(data, KMX61_RANGE_4G); + if (ret < 0) + return ret; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_ODCNTL); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_odcntl\n"); + return ret; + } + data->odr_bits = ret; + + /* set acc/magn to OPERATION mode */ + ret = kmx61_set_mode(data, 0, KMX61_ACC | KMX61_MAG, true); + if (ret < 0) + return ret; + + return 0; +} + +static int kmx61_read_measurement(struct kmx61_data *data, u8 base, u8 offset) +{ + int ret; + u8 reg = base + offset * 2; + + ret = i2c_smbus_read_word_data(data->client, reg); + if (ret < 0) + dev_err(&data->client->dev, "failed to read reg at %x\n", reg); + + return ret; +} + +static int kmx61_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long mask) +{ + int ret; + u8 base_reg; + struct kmx61_data *data = kmx61_get_data(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_ACCEL: + base_reg = KMX61_ACC_XOUT_L; + break; + case IIO_MAGN: + base_reg = KMX61_MAG_XOUT_L; + break; + default: + return -EINVAL; + } + mutex_lock(&data->lock); + + ret = kmx61_read_measurement(data, base_reg, chan->scan_index); + if (ret < 0) { + mutex_unlock(&data->lock); + return ret; + } + *val = sign_extend32(ret >> chan->scan_type.shift, + chan->scan_type.realbits - 1); + + mutex_unlock(&data->lock); + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ACCEL: + *val = 0; + *val2 = kmx61_uscale_table[data->range]; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_MAGN: + /* 14 bits res, 1465 microGauss per magn count */ + *val = 0; + *val2 = 1465; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SAMP_FREQ: + if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN) + return -EINVAL; + + mutex_lock(&data->lock); + ret = kmx61_get_odr(data, val, val2, chan->address); + mutex_unlock(&data->lock); + if (ret) + return -EINVAL; + return IIO_VAL_INT_PLUS_MICRO; + } + return -EINVAL; +} + +static int kmx61_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, + int val2, long mask) +{ + int ret; + struct kmx61_data *data = kmx61_get_data(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN) + return -EINVAL; + + mutex_lock(&data->lock); + ret = kmx61_set_odr(data, val, val2, chan->address); + mutex_unlock(&data->lock); + return ret; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ACCEL: + if (val != 0) + return -EINVAL; + mutex_lock(&data->lock); + ret = kmx61_set_scale(data, val2); + mutex_unlock(&data->lock); + return ret; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static const struct iio_info kmx61_acc_info = { + .driver_module = THIS_MODULE, + .read_raw = kmx61_read_raw, + .write_raw = kmx61_write_raw, + .attrs = &kmx61_acc_attribute_group, +}; + +static const struct iio_info kmx61_mag_info = { + .driver_module = THIS_MODULE, + .read_raw = kmx61_read_raw, + .write_raw = kmx61_write_raw, + .attrs = &kmx61_mag_attribute_group, +}; + +static struct iio_dev *kmx61_indiodev_setup(struct kmx61_data *data, + const struct iio_info *info, + const struct iio_chan_spec *chan, + int num_channels, + const char *name) +{ + struct iio_dev *indio_dev; + + indio_dev = devm_iio_device_alloc(&data->client->dev, sizeof(data)); + if (!indio_dev) + return ERR_PTR(-ENOMEM); + + kmx61_set_data(indio_dev, data); + + indio_dev->dev.parent = &data->client->dev; + indio_dev->channels = chan; + indio_dev->num_channels = num_channels; + indio_dev->name = name; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = info; + + return indio_dev; +} + +static int kmx61_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret; + struct kmx61_data *data; + const char *name = NULL; + + data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + data->client = client; + + mutex_init(&data->lock); + + data->acc_indio_dev = + kmx61_indiodev_setup(data, &kmx61_acc_info, + kmx61_acc_channels, + ARRAY_SIZE(kmx61_acc_channels), + name); + if (IS_ERR(data->acc_indio_dev)) + return PTR_ERR(data->acc_indio_dev); + + data->mag_indio_dev = + kmx61_indiodev_setup(data, &kmx61_mag_info, + kmx61_mag_channels, + ARRAY_SIZE(kmx61_mag_channels), + name); + if (IS_ERR(data->mag_indio_dev)) + return PTR_ERR(data->mag_indio_dev); + + ret = kmx61_chip_init(data); + if (ret < 0) + return ret; + + ret = iio_device_register(data->acc_indio_dev); + if (ret < 0) { + dev_err(&client->dev, "Failed to register acc iio device\n"); + goto err_chip_uninit; + } + + ret = iio_device_register(data->mag_indio_dev); + if (ret < 0) { + dev_err(&client->dev, "Failed to register mag iio device\n"); + goto err_iio_unregister; + } + + return 0; + +err_iio_unregister: + iio_device_unregister(data->acc_indio_dev); +err_chip_uninit: + kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); + return ret; +} + +static int kmx61_remove(struct i2c_client *client) +{ + struct kmx61_data *data = i2c_get_clientdata(client); + + iio_device_unregister(data->acc_indio_dev); + iio_device_unregister(data->mag_indio_dev); + + mutex_lock(&data->lock); + kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); + mutex_unlock(&data->lock); + + return 0; +} + +static const struct i2c_device_id kmx61_id[] = { + {"kmx611021", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, kmx61_id); + +static struct i2c_driver kmx61_driver = { + .driver = { + .name = KMX61_DRV_NAME, + }, + .probe = kmx61_probe, + .remove = kmx61_remove, + .id_table = kmx61_id, +}; + +module_i2c_driver(kmx61_driver); + +MODULE_AUTHOR("Daniel Baluta "); +MODULE_DESCRIPTION("KMX61 accelerometer/magnetometer driver"); +MODULE_LICENSE("GPL v2"); From b25862c577979659020f3575838d366f480ec3bf Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 3 Dec 2014 15:31:49 +0200 Subject: [PATCH 0172/3023] iio: imu: kmx61: Add acpi support Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/imu/kmx61.c | 59 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index 5231d8f3b1671f..efb2f8b450c15c 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -13,10 +13,13 @@ #include #include +#include +#include #include #include #define KMX61_DRV_NAME "kmx61" +#define KMX61_GPIO_NAME "kmx61_int" #define KMX61_REG_WHO_AM_I 0x00 @@ -573,6 +576,44 @@ static const struct iio_info kmx61_mag_info = { .attrs = &kmx61_mag_attribute_group, }; +static const char *kmx61_match_acpi_device(struct device *dev) +{ + const struct acpi_device_id *id; + + id = acpi_match_device(dev->driver->acpi_match_table, dev); + if (!id) + return NULL; + return dev_name(dev); +} + +static int kmx61_gpio_probe(struct i2c_client *client, struct kmx61_data *data) +{ + struct device *dev; + struct gpio_desc *gpio; + int ret; + + if (!client) + return -EINVAL; + + dev = &client->dev; + + /* data ready gpio interrupt pin */ + gpio = devm_gpiod_get_index(dev, KMX61_GPIO_NAME, 0); + if (IS_ERR(gpio)) { + dev_err(dev, "acpi gpio get index failed\n"); + return PTR_ERR(gpio); + } + + ret = gpiod_direction_input(gpio); + if (ret) + return ret; + + ret = gpiod_to_irq(gpio); + + dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); + return ret; +} + static struct iio_dev *kmx61_indiodev_setup(struct kmx61_data *data, const struct iio_info *info, const struct iio_chan_spec *chan, @@ -613,6 +654,13 @@ static int kmx61_probe(struct i2c_client *client, mutex_init(&data->lock); + if (id) + name = id->name; + else if (ACPI_HANDLE(&client->dev)) + name = kmx61_match_acpi_device(&client->dev); + else + return -ENODEV; + data->acc_indio_dev = kmx61_indiodev_setup(data, &kmx61_acc_info, kmx61_acc_channels, @@ -633,6 +681,9 @@ static int kmx61_probe(struct i2c_client *client, if (ret < 0) return ret; + if (client->irq < 0) + client->irq = kmx61_gpio_probe(client, data); + ret = iio_device_register(data->acc_indio_dev); if (ret < 0) { dev_err(&client->dev, "Failed to register acc iio device\n"); @@ -668,6 +719,13 @@ static int kmx61_remove(struct i2c_client *client) return 0; } +static const struct acpi_device_id kmx61_acpi_match[] = { + {"KMX61021", 0}, + {} +}; + +MODULE_DEVICE_TABLE(acpi, kmx61_acpi_match); + static const struct i2c_device_id kmx61_id[] = { {"kmx611021", 0}, {} @@ -678,6 +736,7 @@ MODULE_DEVICE_TABLE(i2c, kmx61_id); static struct i2c_driver kmx61_driver = { .driver = { .name = KMX61_DRV_NAME, + .acpi_match_table = ACPI_PTR(kmx61_acpi_match), }, .probe = kmx61_probe, .remove = kmx61_remove, From aff8609addd00efa3d907f3523823693f95686fd Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 3 Dec 2014 15:31:50 +0200 Subject: [PATCH 0173/3023] iio: imu: kmx61: Add PM runtime support By default both sensors are ACTIVE, in this way the driver will work even if CONFIG_PM_RUNTIME is not selected. Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/imu/kmx61.c | 114 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 2 deletions(-) diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index efb2f8b450c15c..f3007dd664fcae 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include @@ -69,6 +71,8 @@ #define KMX61_ACC_ODR_MASK 0x0F #define KMX61_MAG_ODR_MASK 0xF0 +#define KMX61_SLEEP_DELAY_MS 2000 + #define KMX61_CHIP_ID 0x12 /* KMX61 devices */ @@ -85,6 +89,10 @@ struct kmx61_data { bool acc_stby; bool mag_stby; + /* power state */ + bool acc_ps; + bool mag_ps; + /* config bits */ u8 range; u8 odr_bits; @@ -457,6 +465,58 @@ static int kmx61_chip_init(struct kmx61_data *data) return 0; } +/** + * kmx61_set_power_state() - set power state for kmx61 @device + * @data - kmx61 device private pointer + * @on - power state to be set for @device + * @device - bitmask indicating device for which @on state needs to be set + * + * Notice that when ACC power state needs to be set to ON and MAG is in + * OPERATION then we know that kmx61_runtime_resume was already called + * so we must set ACC OPERATION mode here. The same happens when MAG power + * state needs to be set to ON and ACC is in OPERATION. + */ +static int kmx61_set_power_state(struct kmx61_data *data, bool on, u8 device) +{ +#ifdef CONFIG_PM_RUNTIME + int ret; + + if (device & KMX61_ACC) { + if (on && !data->acc_ps && !data->mag_stby) { + ret = kmx61_set_mode(data, 0, KMX61_ACC, true); + if (ret < 0) + return ret; + } + data->acc_ps = on; + } + if (device & KMX61_MAG) { + if (on && !data->mag_ps && !data->acc_stby) { + ret = kmx61_set_mode(data, 0, KMX61_MAG, true); + if (ret < 0) + return ret; + } + data->mag_ps = on; + } + + if (on) { + ret = pm_runtime_get_sync(&data->client->dev); + } else { + pm_runtime_mark_last_busy(&data->client->dev); + ret = pm_runtime_put_autosuspend(&data->client->dev); + } + if (ret < 0) { + dev_err(&data->client->dev, + "Failed: kmx61_set_power_state for %d, ret %d\n", + on, ret); + if (on) + pm_runtime_put_noidle(&data->client->dev); + + return ret; + } +#endif + return 0; +} + static int kmx61_read_measurement(struct kmx61_data *data, u8 base, u8 offset) { int ret; @@ -491,13 +551,16 @@ static int kmx61_read_raw(struct iio_dev *indio_dev, } mutex_lock(&data->lock); + kmx61_set_power_state(data, true, chan->address); ret = kmx61_read_measurement(data, base_reg, chan->scan_index); if (ret < 0) { + kmx61_set_power_state(data, false, chan->address); mutex_unlock(&data->lock); return ret; } *val = sign_extend32(ret >> chan->scan_type.shift, chan->scan_type.realbits - 1); + kmx61_set_power_state(data, false, chan->address); mutex_unlock(&data->lock); return IIO_VAL_INT; @@ -693,12 +756,22 @@ static int kmx61_probe(struct i2c_client *client, ret = iio_device_register(data->mag_indio_dev); if (ret < 0) { dev_err(&client->dev, "Failed to register mag iio device\n"); - goto err_iio_unregister; + goto err_iio_unregister_acc; } + ret = pm_runtime_set_active(&client->dev); + if (ret < 0) + goto err_iio_unregister_mag; + + pm_runtime_enable(&client->dev); + pm_runtime_set_autosuspend_delay(&client->dev, KMX61_SLEEP_DELAY_MS); + pm_runtime_use_autosuspend(&client->dev); + return 0; -err_iio_unregister: +err_iio_unregister_mag: + iio_device_unregister(data->mag_indio_dev); +err_iio_unregister_acc: iio_device_unregister(data->acc_indio_dev); err_chip_uninit: kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); @@ -709,6 +782,10 @@ static int kmx61_remove(struct i2c_client *client) { struct kmx61_data *data = i2c_get_clientdata(client); + pm_runtime_disable(&client->dev); + pm_runtime_set_suspended(&client->dev); + pm_runtime_put_noidle(&client->dev); + iio_device_unregister(data->acc_indio_dev); iio_device_unregister(data->mag_indio_dev); @@ -719,6 +796,38 @@ static int kmx61_remove(struct i2c_client *client) return 0; } + +#ifdef CONFIG_PM_RUNTIME +static int kmx61_runtime_suspend(struct device *dev) +{ + struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev)); + int ret; + + mutex_lock(&data->lock); + ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); + mutex_unlock(&data->lock); + + return ret; +} + +static int kmx61_runtime_resume(struct device *dev) +{ + struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev)); + u8 stby = 0; + + if (!data->acc_ps) + stby |= KMX61_ACC_STBY_BIT; + if (!data->mag_ps) + stby |= KMX61_MAG_STBY_BIT; + + return kmx61_set_mode(data, stby, KMX61_ACC | KMX61_MAG, true); +} +#endif + +static const struct dev_pm_ops kmx61_pm_ops = { + SET_RUNTIME_PM_OPS(kmx61_runtime_suspend, kmx61_runtime_resume, NULL) +}; + static const struct acpi_device_id kmx61_acpi_match[] = { {"KMX61021", 0}, {} @@ -737,6 +846,7 @@ static struct i2c_driver kmx61_driver = { .driver = { .name = KMX61_DRV_NAME, .acpi_match_table = ACPI_PTR(kmx61_acpi_match), + .pm = &kmx61_pm_ops, }, .probe = kmx61_probe, .remove = kmx61_remove, From 3b9c40e604ee61e69a8aff6e1a426a6250ff4361 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 3 Dec 2014 15:31:51 +0200 Subject: [PATCH 0174/3023] iio: imu: kmx61: Add PM sleep support Per sensor state (ACTIVE/STANDBY) is saved in driver's private data (acc_stby/mag_stby) and restored when resume is called. Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/imu/kmx61.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index f3007dd664fcae..98d58e1b6c6b05 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -796,6 +797,33 @@ static int kmx61_remove(struct i2c_client *client) return 0; } +#ifdef CONFIG_PM_SLEEP +static int kmx61_suspend(struct device *dev) +{ + int ret; + struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev)); + + mutex_lock(&data->lock); + ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, + false); + mutex_unlock(&data->lock); + + return ret; +} + +static int kmx61_resume(struct device *dev) +{ + u8 stby = 0; + struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev)); + + if (data->acc_stby) + stby |= KMX61_ACC_STBY_BIT; + if (data->mag_stby) + stby |= KMX61_MAG_STBY_BIT; + + return kmx61_set_mode(data, stby, KMX61_ACC | KMX61_MAG, true); +} +#endif #ifdef CONFIG_PM_RUNTIME static int kmx61_runtime_suspend(struct device *dev) @@ -825,6 +853,7 @@ static int kmx61_runtime_resume(struct device *dev) #endif static const struct dev_pm_ops kmx61_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(kmx61_suspend, kmx61_resume) SET_RUNTIME_PM_OPS(kmx61_runtime_suspend, kmx61_runtime_resume, NULL) }; From c3a23ecc0901f624b681bbfbc4829766c5aa3070 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 3 Dec 2014 15:31:52 +0200 Subject: [PATCH 0175/3023] iio: imu: kmx61: Add support for data ready triggers This creates a data ready trigger per IIO device. Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/imu/Kconfig | 2 + drivers/iio/imu/kmx61.c | 295 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 296 insertions(+), 1 deletion(-) diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig index db4221db10f20f..5e610f7de5aa2b 100644 --- a/drivers/iio/imu/Kconfig +++ b/drivers/iio/imu/Kconfig @@ -28,6 +28,8 @@ config ADIS16480 config KMX61 tristate "Kionix KMX61 6-axis accelerometer and magnetometer" depends on I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER help Say Y here if you want to build a driver for Kionix KMX61 6-axis accelerometer and magnetometer. diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index 98d58e1b6c6b05..b8080fc54a767a 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -20,9 +20,14 @@ #include #include #include +#include +#include +#include +#include #define KMX61_DRV_NAME "kmx61" #define KMX61_GPIO_NAME "kmx61_int" +#define KMX61_IRQ_NAME "kmx61_event" #define KMX61_REG_WHO_AM_I 0x00 @@ -55,9 +60,11 @@ #define KMX61_MAG_ZOUT_L 0x16 #define KMX61_MAG_ZOUT_H 0x17 +#define KMX61_REG_INL 0x28 #define KMX61_REG_STBY 0x29 #define KMX61_REG_CTRL1 0x2A #define KMX61_REG_ODCNTL 0x2C +#define KMX61_REG_INC1 0x2D #define KMX61_ACC_STBY_BIT BIT(0) #define KMX61_MAG_STBY_BIT BIT(1) @@ -67,6 +74,13 @@ #define KMX61_REG_CTRL1_GSEL_MASK 0x03 +#define KMX61_REG_CTRL1_BIT_RES BIT(4) +#define KMX61_REG_CTRL1_BIT_DRDYE BIT(5) + +#define KMX61_REG_INC1_BIT_DRDYM BIT(1) +#define KMX61_REG_INC1_BIT_DRDYA BIT(2) +#define KMX61_REG_INC1_BIT_IEN BIT(5) + #define KMX61_ACC_ODR_SHIFT 0 #define KMX61_MAG_ODR_SHIFT 4 #define KMX61_ACC_ODR_MASK 0x0F @@ -100,9 +114,13 @@ struct kmx61_data { /* accelerometer specific data */ struct iio_dev *acc_indio_dev; + struct iio_trigger *acc_dready_trig; + bool acc_dready_trig_on; /* magnetometer specific data */ struct iio_dev *mag_indio_dev; + struct iio_trigger *mag_dready_trig; + bool mag_dready_trig_on; }; enum kmx61_range { @@ -466,6 +484,69 @@ static int kmx61_chip_init(struct kmx61_data *data) return 0; } +static int kmx61_setup_new_data_interrupt(struct kmx61_data *data, + bool status, u8 device) +{ + u8 mode; + int ret; + + ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG); + if (ret < 0) + return ret; + + ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); + if (ret < 0) + return ret; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INC1); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); + return ret; + } + + if (status) { + ret |= KMX61_REG_INC1_BIT_IEN; + if (device & KMX61_ACC) + ret |= KMX61_REG_INC1_BIT_DRDYA; + if (device & KMX61_MAG) + ret |= KMX61_REG_INC1_BIT_DRDYM; + } else { + ret &= ~KMX61_REG_INC1_BIT_IEN; + if (device & KMX61_ACC) + ret &= ~KMX61_REG_INC1_BIT_DRDYA; + if (device & KMX61_MAG) + ret &= ~KMX61_REG_INC1_BIT_DRDYM; + } + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_INC1, ret); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); + return ret; + } + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); + return ret; + } + + if (status) + ret |= KMX61_REG_CTRL1_BIT_DRDYE; + else + ret &= ~KMX61_REG_CTRL1_BIT_DRDYE; + + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); + return ret; + } + + ret = kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); + if (ret) + return ret; + + return 0; +} + /** * kmx61_set_power_state() - set power state for kmx61 @device * @data - kmx61 device private pointer @@ -626,11 +707,34 @@ static int kmx61_write_raw(struct iio_dev *indio_dev, } } +static int kmx61_acc_validate_trigger(struct iio_dev *indio_dev, + struct iio_trigger *trig) +{ + struct kmx61_data *data = kmx61_get_data(indio_dev); + + if (data->acc_dready_trig != trig) + return -EINVAL; + + return 0; +} + +static int kmx61_mag_validate_trigger(struct iio_dev *indio_dev, + struct iio_trigger *trig) +{ + struct kmx61_data *data = kmx61_get_data(indio_dev); + + if (data->mag_dready_trig != trig) + return -EINVAL; + + return 0; +} + static const struct iio_info kmx61_acc_info = { .driver_module = THIS_MODULE, .read_raw = kmx61_read_raw, .write_raw = kmx61_write_raw, .attrs = &kmx61_acc_attribute_group, + .validate_trigger = kmx61_acc_validate_trigger, }; static const struct iio_info kmx61_mag_info = { @@ -638,8 +742,109 @@ static const struct iio_info kmx61_mag_info = { .read_raw = kmx61_read_raw, .write_raw = kmx61_write_raw, .attrs = &kmx61_mag_attribute_group, + .validate_trigger = kmx61_mag_validate_trigger, +}; + + +static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, + bool state) +{ + int ret = 0; + u8 device; + + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct kmx61_data *data = iio_priv(indio_dev); + + mutex_lock(&data->lock); + + if (data->acc_dready_trig == trig) + device = KMX61_ACC; + else + device = KMX61_MAG; + + ret = kmx61_set_power_state(data, state, device); + if (ret < 0) { + mutex_unlock(&data->lock); + return ret; + } + + ret = kmx61_setup_new_data_interrupt(data, state, device); + if (ret < 0) { + kmx61_set_power_state(data, false, device); + mutex_unlock(&data->lock); + return ret; + } + + if (data->acc_dready_trig == trig) + data->acc_dready_trig_on = state; + else + data->mag_dready_trig_on = state; + + mutex_unlock(&data->lock); + + return 0; +} + +static int kmx61_trig_try_reenable(struct iio_trigger *trig) +{ + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct kmx61_data *data = kmx61_get_data(indio_dev); + int ret; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INL); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_inl\n"); + return ret; + } + + return 0; +} + +static const struct iio_trigger_ops kmx61_trigger_ops = { + .set_trigger_state = kmx61_data_rdy_trigger_set_state, + .try_reenable = kmx61_trig_try_reenable, + .owner = THIS_MODULE, }; +static irqreturn_t kmx61_data_rdy_trig_poll(int irq, void *private) +{ + struct kmx61_data *data = private; + + if (data->acc_dready_trig_on) + iio_trigger_poll(data->acc_dready_trig); + if (data->mag_dready_trig_on) + iio_trigger_poll(data->mag_dready_trig); + + return IRQ_HANDLED; +} + +static irqreturn_t kmx61_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct kmx61_data *data = kmx61_get_data(indio_dev); + int bit, ret, i = 0; + s16 buffer[8]; + + mutex_lock(&data->lock); + for_each_set_bit(bit, indio_dev->buffer->scan_mask, + indio_dev->masklength) { + ret = kmx61_read_measurement(data, KMX61_ACC_XOUT_L, bit); + if (ret < 0) { + mutex_unlock(&data->lock); + goto err; + } + buffer[i++] = ret; + } + mutex_unlock(&data->lock); + + iio_push_to_buffers(indio_dev, buffer); +err: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + static const char *kmx61_match_acpi_device(struct device *dev) { const struct acpi_device_id *id; @@ -702,6 +907,32 @@ static struct iio_dev *kmx61_indiodev_setup(struct kmx61_data *data, return indio_dev; } +static struct iio_trigger *kmx61_trigger_setup(struct kmx61_data *data, + struct iio_dev *indio_dev, + const char *tag) +{ + struct iio_trigger *trig; + int ret; + + trig = devm_iio_trigger_alloc(&data->client->dev, + "%s-%s-dev%d", + indio_dev->name, + tag, + indio_dev->id); + if (!trig) + return ERR_PTR(-ENOMEM); + + trig->dev.parent = &data->client->dev; + trig->ops = &kmx61_trigger_ops; + iio_trigger_set_drvdata(trig, indio_dev); + + ret = iio_trigger_register(trig); + if (ret) + return ERR_PTR(ret); + + return trig; +} + static int kmx61_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -748,10 +979,55 @@ static int kmx61_probe(struct i2c_client *client, if (client->irq < 0) client->irq = kmx61_gpio_probe(client, data); + if (client->irq >= 0) { + ret = devm_request_threaded_irq(&client->dev, client->irq, + kmx61_data_rdy_trig_poll, + NULL, + IRQF_TRIGGER_RISING, + KMX61_IRQ_NAME, + data); + if (ret) + goto err_chip_uninit; + + data->acc_dready_trig = + kmx61_trigger_setup(data, data->acc_indio_dev, + "dready"); + if (IS_ERR(data->acc_dready_trig)) + return PTR_ERR(data->acc_dready_trig); + + data->mag_dready_trig = + kmx61_trigger_setup(data, data->mag_indio_dev, + "dready"); + if (IS_ERR(data->mag_dready_trig)) { + ret = PTR_ERR(data->mag_dready_trig); + goto err_trigger_unregister; + } + + ret = iio_triggered_buffer_setup(data->acc_indio_dev, + &iio_pollfunc_store_time, + kmx61_trigger_handler, + NULL); + if (ret < 0) { + dev_err(&data->client->dev, + "Failed to setup acc triggered buffer\n"); + goto err_trigger_unregister; + } + + ret = iio_triggered_buffer_setup(data->mag_indio_dev, + &iio_pollfunc_store_time, + kmx61_trigger_handler, + NULL); + if (ret < 0) { + dev_err(&data->client->dev, + "Failed to setup mag triggered buffer\n"); + goto err_trigger_unregister; + } + } + ret = iio_device_register(data->acc_indio_dev); if (ret < 0) { dev_err(&client->dev, "Failed to register acc iio device\n"); - goto err_chip_uninit; + goto err_buffer_cleanup; } ret = iio_device_register(data->mag_indio_dev); @@ -774,6 +1050,16 @@ static int kmx61_probe(struct i2c_client *client, iio_device_unregister(data->mag_indio_dev); err_iio_unregister_acc: iio_device_unregister(data->acc_indio_dev); +err_buffer_cleanup: + if (client->irq >= 0) { + iio_triggered_buffer_cleanup(data->acc_indio_dev); + iio_triggered_buffer_cleanup(data->mag_indio_dev); + } +err_trigger_unregister: + if (data->acc_dready_trig) + iio_trigger_unregister(data->acc_dready_trig); + if (data->mag_dready_trig) + iio_trigger_unregister(data->mag_dready_trig); err_chip_uninit: kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); return ret; @@ -790,6 +1076,13 @@ static int kmx61_remove(struct i2c_client *client) iio_device_unregister(data->acc_indio_dev); iio_device_unregister(data->mag_indio_dev); + if (client->irq >= 0) { + iio_triggered_buffer_cleanup(data->acc_indio_dev); + iio_triggered_buffer_cleanup(data->mag_indio_dev); + iio_trigger_unregister(data->acc_dready_trig); + iio_trigger_unregister(data->mag_dready_trig); + } + mutex_lock(&data->lock); kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); mutex_unlock(&data->lock); From fd3ae7a9f21c2a51a1d220bc7a7c3b45ab5e6ad1 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 3 Dec 2014 15:31:53 +0200 Subject: [PATCH 0176/3023] iio: imu: kmx61: Add support for any motion trigger We use WUFE (Wake Up from Sleep Engine) and BTSE (Back to Sleep Engine) to detect general motion input. Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/imu/kmx61.c | 433 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 426 insertions(+), 7 deletions(-) diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index b8080fc54a767a..bda9c40c020b13 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,8 @@ #define KMX61_IRQ_NAME "kmx61_event" #define KMX61_REG_WHO_AM_I 0x00 +#define KMX61_REG_INS1 0x01 +#define KMX61_REG_INS2 0x02 /* * three 16-bit accelerometer output registers for X/Y/Z axis @@ -63,20 +66,36 @@ #define KMX61_REG_INL 0x28 #define KMX61_REG_STBY 0x29 #define KMX61_REG_CTRL1 0x2A +#define KMX61_REG_CTRL2 0x2B #define KMX61_REG_ODCNTL 0x2C #define KMX61_REG_INC1 0x2D +#define KMX61_REG_WUF_THRESH 0x3D +#define KMX61_REG_WUF_TIMER 0x3E + #define KMX61_ACC_STBY_BIT BIT(0) #define KMX61_MAG_STBY_BIT BIT(1) #define KMX61_ACT_STBY_BIT BIT(7) #define KMX61_ALL_STBY (KMX61_ACC_STBY_BIT | KMX61_MAG_STBY_BIT) +#define KMX61_REG_INS1_BIT_WUFS BIT(1) + +#define KMX61_REG_INS2_BIT_ZP BIT(0) +#define KMX61_REG_INS2_BIT_ZN BIT(1) +#define KMX61_REG_INS2_BIT_YP BIT(2) +#define KMX61_REG_INS2_BIT_YN BIT(3) +#define KMX61_REG_INS2_BIT_XP BIT(4) +#define KMX61_REG_INS2_BIT_XN BIT(5) + #define KMX61_REG_CTRL1_GSEL_MASK 0x03 #define KMX61_REG_CTRL1_BIT_RES BIT(4) #define KMX61_REG_CTRL1_BIT_DRDYE BIT(5) +#define KMX61_REG_CTRL1_BIT_WUFE BIT(6) +#define KMX61_REG_CTRL1_BIT_BTSE BIT(7) +#define KMX61_REG_INC1_BIT_WUFS BIT(0) #define KMX61_REG_INC1_BIT_DRDYM BIT(1) #define KMX61_REG_INC1_BIT_DRDYA BIT(2) #define KMX61_REG_INC1_BIT_IEN BIT(5) @@ -86,6 +105,11 @@ #define KMX61_ACC_ODR_MASK 0x0F #define KMX61_MAG_ODR_MASK 0xF0 +#define KMX61_OWUF_MASK 0x7 + +#define KMX61_DEFAULT_WAKE_THRESH 1 +#define KMX61_DEFAULT_WAKE_DURATION 1 + #define KMX61_SLEEP_DELAY_MS 2000 #define KMX61_CHIP_ID 0x12 @@ -111,11 +135,16 @@ struct kmx61_data { /* config bits */ u8 range; u8 odr_bits; + u8 wake_thresh; + u8 wake_duration; /* accelerometer specific data */ struct iio_dev *acc_indio_dev; struct iio_trigger *acc_dready_trig; + struct iio_trigger *motion_trig; bool acc_dready_trig_on; + bool motion_trig_on; + bool ev_enable_state; /* magnetometer specific data */ struct iio_dev *mag_indio_dev; @@ -154,6 +183,23 @@ static const struct { {3, 125000, 0x0A}, {6, 250000, 0x0B} }; +static const struct { + int val; + int val2; + int odr_bits; +} kmx61_wake_up_odr_table[] = { {0, 781000, 0x00}, + {1, 563000, 0x01}, + {3, 125000, 0x02}, + {6, 250000, 0x03}, + {12, 500000, 0x04}, + {25, 0, 0x05}, + {50, 0, 0x06}, + {100, 0, 0x06}, + {200, 0, 0x06}, + {400, 0, 0x06}, + {800, 0, 0x06}, + {1600, 0, 0x06} }; + static IIO_CONST_ATTR(accel_scale_available, "0.009582 0.019163 0.038326"); static IIO_CONST_ATTR(magn_scale_available, "0.001465"); static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( @@ -179,6 +225,14 @@ static const struct attribute_group kmx61_mag_attribute_group = { .attrs = kmx61_mag_attributes, }; +static const struct iio_event_spec kmx61_event = { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_EITHER, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_PERIOD), +}; + #define KMX61_ACC_CHAN(_axis) { \ .type = IIO_ACCEL, \ .modified = 1, \ @@ -195,6 +249,8 @@ static const struct attribute_group kmx61_mag_attribute_group = { .shift = 4, \ .endianness = IIO_LE, \ }, \ + .event_spec = &kmx61_event, \ + .num_event_specs = 1 \ } #define KMX61_MAG_CHAN(_axis) { \ @@ -250,6 +306,31 @@ static int kmx61_convert_freq_to_bit(int val, int val2) return -EINVAL; } +static int kmx61_convert_bit_to_freq(u8 odr_bits, int *val, int *val2) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++) + if (odr_bits == kmx61_samp_freq_table[i].odr_bits) { + *val = kmx61_samp_freq_table[i].val; + *val2 = kmx61_samp_freq_table[i].val2; + return 0; + } + return -EINVAL; +} + + +static int kmx61_convert_wake_up_odr_to_bit(int val, int val2) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(kmx61_wake_up_odr_table); ++i) + if (kmx61_wake_up_odr_table[i].val == val && + kmx61_wake_up_odr_table[i].val2 == val2) + return kmx61_wake_up_odr_table[i].odr_bits; + return -EINVAL; +} + /** * kmx61_set_mode() - set KMX61 device operating mode * @data - kmx61 device private data pointer @@ -338,6 +419,21 @@ static int kmx61_get_mode(struct kmx61_data *data, u8 *mode, u8 device) return 0; } +int kmx61_set_wake_up_odr(struct kmx61_data *data, int val, int val2) +{ + int ret, odr_bits; + + odr_bits = kmx61_convert_wake_up_odr_to_bit(val, val2); + if (odr_bits < 0) + return odr_bits; + + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL2, + odr_bits); + if (ret < 0) + dev_err(&data->client->dev, "Error writing reg_ctrl2\n"); + return ret; +} + static int kmx61_set_odr(struct kmx61_data *data, int val, int val2, u8 device) { int ret; @@ -369,6 +465,12 @@ static int kmx61_set_odr(struct kmx61_data *data, int val, int val2, u8 device) if (ret < 0) return ret; + if (device & KMX61_ACC) { + ret = kmx61_set_wake_up_odr(data, val, val2); + if (ret) + return ret; + } + return kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); } @@ -449,7 +551,7 @@ static int kmx61_set_scale(struct kmx61_data *data, u16 uscale) static int kmx61_chip_init(struct kmx61_data *data) { - int ret; + int ret, val, val2; ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_WHO_AM_I); if (ret < 0) { @@ -476,11 +578,23 @@ static int kmx61_chip_init(struct kmx61_data *data) } data->odr_bits = ret; + /* set output data rate for wake up (motion detection) function */ + ret = kmx61_convert_bit_to_freq(data->odr_bits, &val, &val2); + if (ret < 0) + return ret; + + ret = kmx61_set_wake_up_odr(data, val, val2); + if (ret < 0) + return ret; + /* set acc/magn to OPERATION mode */ ret = kmx61_set_mode(data, 0, KMX61_ACC | KMX61_MAG, true); if (ret < 0) return ret; + data->wake_thresh = KMX61_DEFAULT_WAKE_THRESH; + data->wake_duration = KMX61_DEFAULT_WAKE_DURATION; + return 0; } @@ -547,6 +661,87 @@ static int kmx61_setup_new_data_interrupt(struct kmx61_data *data, return 0; } +static int kmx61_chip_update_thresholds(struct kmx61_data *data) +{ + int ret; + + ret = i2c_smbus_write_byte_data(data->client, + KMX61_REG_WUF_TIMER, + data->wake_duration); + if (ret < 0) { + dev_err(&data->client->dev, "Errow writing reg_wuf_timer\n"); + return ret; + } + + ret = i2c_smbus_write_byte_data(data->client, + KMX61_REG_WUF_THRESH, + data->wake_thresh); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_wuf_thresh\n"); + return ret; + } + + return 0; +} + +static int kmx61_setup_any_motion_interrupt(struct kmx61_data *data, + bool status, u8 device) +{ + u8 mode; + int ret; + + ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG); + if (ret < 0) + return ret; + + ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); + if (ret < 0) + return ret; + + ret = kmx61_chip_update_thresholds(data); + if (ret < 0) + return ret; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INC1); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_inc1\n"); + return ret; + } + if (status) + ret |= (KMX61_REG_INC1_BIT_IEN | KMX61_REG_INC1_BIT_WUFS); + else + ret &= ~(KMX61_REG_INC1_BIT_IEN | KMX61_REG_INC1_BIT_WUFS); + + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_INC1, ret); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_inc1\n"); + return ret; + } + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); + return ret; + } + + if (status) + ret |= KMX61_REG_CTRL1_BIT_WUFE | KMX61_REG_CTRL1_BIT_BTSE; + else + ret &= ~(KMX61_REG_CTRL1_BIT_WUFE | KMX61_REG_CTRL1_BIT_BTSE); + + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); + return ret; + } + mode |= KMX61_ACT_STBY_BIT; + ret = kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); + if (ret) + return ret; + + return 0; +} + /** * kmx61_set_power_state() - set power state for kmx61 @device * @data - kmx61 device private pointer @@ -707,12 +902,111 @@ static int kmx61_write_raw(struct iio_dev *indio_dev, } } +static int kmx61_read_event(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) +{ + struct kmx61_data *data = kmx61_get_data(indio_dev); + + *val2 = 0; + switch (info) { + case IIO_EV_INFO_VALUE: + *val = data->wake_thresh; + break; + case IIO_EV_INFO_PERIOD: + *val = data->wake_duration; + break; + default: + return -EINVAL; + } + + return IIO_VAL_INT; +} + +static int kmx61_write_event(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) +{ + struct kmx61_data *data = kmx61_get_data(indio_dev); + + if (data->ev_enable_state) + return -EBUSY; + + switch (info) { + case IIO_EV_INFO_VALUE: + data->wake_thresh = val; + break; + case IIO_EV_INFO_PERIOD: + data->wake_duration = val; + break; + default: + return -EINVAL; + } + + return IIO_VAL_INT; +} + +static int kmx61_read_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct kmx61_data *data = kmx61_get_data(indio_dev); + + return data->ev_enable_state; +} + +static int kmx61_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + int state) +{ + struct kmx61_data *data = kmx61_get_data(indio_dev); + int ret; + + if (state && data->ev_enable_state) + return 0; + + mutex_lock(&data->lock); + + if (!state && data->motion_trig_on) { + data->ev_enable_state = 0; + mutex_unlock(&data->lock); + return 0; + } + + ret = kmx61_set_power_state(data, state, KMX61_ACC); + if (ret < 0) { + mutex_unlock(&data->lock); + return ret; + } + + ret = kmx61_setup_any_motion_interrupt(data, state, KMX61_ACC); + if (ret < 0) { + kmx61_set_power_state(data, false, KMX61_ACC); + mutex_unlock(&data->lock); + return ret; + } + + data->ev_enable_state = state; + mutex_unlock(&data->lock); + + return 0; +} + static int kmx61_acc_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig) { struct kmx61_data *data = kmx61_get_data(indio_dev); - if (data->acc_dready_trig != trig) + if (data->acc_dready_trig != trig && data->motion_trig != trig) return -EINVAL; return 0; @@ -734,6 +1028,10 @@ static const struct iio_info kmx61_acc_info = { .read_raw = kmx61_read_raw, .write_raw = kmx61_write_raw, .attrs = &kmx61_acc_attribute_group, + .read_event_value = kmx61_read_event, + .write_event_value = kmx61_write_event, + .read_event_config = kmx61_read_event_config, + .write_event_config = kmx61_write_event_config, .validate_trigger = kmx61_acc_validate_trigger, }; @@ -753,11 +1051,18 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, u8 device; struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); - struct kmx61_data *data = iio_priv(indio_dev); + struct kmx61_data *data = kmx61_get_data(indio_dev); mutex_lock(&data->lock); - if (data->acc_dready_trig == trig) + if (!state && data->ev_enable_state && data->motion_trig_on) { + data->motion_trig_on = false; + mutex_unlock(&data->lock); + return 0; + } + + + if (data->acc_dready_trig == trig || data->motion_trig) device = KMX61_ACC; else device = KMX61_MAG; @@ -768,7 +1073,10 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, return ret; } - ret = kmx61_setup_new_data_interrupt(data, state, device); + if (data->acc_dready_trig == trig || data->mag_dready_trig == trig) + ret = kmx61_setup_new_data_interrupt(data, state, device); + else + ret = kmx61_setup_any_motion_interrupt(data, state, KMX61_ACC); if (ret < 0) { kmx61_set_power_state(data, false, device); mutex_unlock(&data->lock); @@ -777,8 +1085,10 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, if (data->acc_dready_trig == trig) data->acc_dready_trig_on = state; - else + else if (data->mag_dready_trig == trig) data->mag_dready_trig_on = state; + else + data->motion_trig_on = state; mutex_unlock(&data->lock); @@ -806,6 +1116,99 @@ static const struct iio_trigger_ops kmx61_trigger_ops = { .owner = THIS_MODULE, }; +static irqreturn_t kmx61_event_handler(int irq, void *private) +{ + struct kmx61_data *data = private; + struct iio_dev *indio_dev = data->acc_indio_dev; + int ret; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INS1); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_ins1\n"); + goto ack_intr; + } + + if (ret & KMX61_REG_INS1_BIT_WUFS) { + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INS2); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_ins2\n"); + goto ack_intr; + } + + if (ret & KMX61_REG_INS2_BIT_XN) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, + 0, + IIO_MOD_X, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + 0); + + if (ret & KMX61_REG_INS2_BIT_XP) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, + 0, + IIO_MOD_X, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + 0); + + if (ret & KMX61_REG_INS2_BIT_YN) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, + 0, + IIO_MOD_Y, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + 0); + + if (ret & KMX61_REG_INS2_BIT_YP) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, + 0, + IIO_MOD_Y, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + 0); + + if (ret & KMX61_REG_INS2_BIT_ZN) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, + 0, + IIO_MOD_Z, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + 0); + + if (ret & KMX61_REG_INS2_BIT_ZP) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, + 0, + IIO_MOD_Z, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + 0); + } + +ack_intr: + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1); + if (ret < 0) + dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); + + ret |= KMX61_REG_CTRL1_BIT_RES; + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret); + if (ret < 0) + dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INL); + if (ret < 0) + dev_err(&data->client->dev, "Error reading reg_inl\n"); + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INS1); + + return IRQ_HANDLED; +} + static irqreturn_t kmx61_data_rdy_trig_poll(int irq, void *private) { struct kmx61_data *data = private; @@ -815,6 +1218,11 @@ static irqreturn_t kmx61_data_rdy_trig_poll(int irq, void *private) if (data->mag_dready_trig_on) iio_trigger_poll(data->mag_dready_trig); + if (data->motion_trig_on) + iio_trigger_poll(data->motion_trig); + + if (data->ev_enable_state) + return IRQ_WAKE_THREAD; return IRQ_HANDLED; } @@ -982,7 +1390,7 @@ static int kmx61_probe(struct i2c_client *client, if (client->irq >= 0) { ret = devm_request_threaded_irq(&client->dev, client->irq, kmx61_data_rdy_trig_poll, - NULL, + kmx61_event_handler, IRQF_TRIGGER_RISING, KMX61_IRQ_NAME, data); @@ -1003,6 +1411,14 @@ static int kmx61_probe(struct i2c_client *client, goto err_trigger_unregister; } + data->motion_trig = + kmx61_trigger_setup(data, data->acc_indio_dev, + "any-motion"); + if (IS_ERR(data->motion_trig)) { + ret = PTR_ERR(data->motion_trig); + goto err_trigger_unregister; + } + ret = iio_triggered_buffer_setup(data->acc_indio_dev, &iio_pollfunc_store_time, kmx61_trigger_handler, @@ -1060,6 +1476,8 @@ static int kmx61_probe(struct i2c_client *client, iio_trigger_unregister(data->acc_dready_trig); if (data->mag_dready_trig) iio_trigger_unregister(data->mag_dready_trig); + if (data->motion_trig) + iio_trigger_unregister(data->motion_trig); err_chip_uninit: kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); return ret; @@ -1081,6 +1499,7 @@ static int kmx61_remove(struct i2c_client *client) iio_triggered_buffer_cleanup(data->mag_indio_dev); iio_trigger_unregister(data->acc_dready_trig); iio_trigger_unregister(data->mag_dready_trig); + iio_trigger_unregister(data->motion_trig); } mutex_lock(&data->lock); From ebd163660675534dd5f27c8d3fa426b8253a98f4 Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Sat, 13 Dec 2014 00:28:52 +0800 Subject: [PATCH 0177/3023] iio: imu: kmx61: kmx61_set_wake_up_odr() can be static drivers/iio/imu/kmx61.c:422:5: sparse: symbol 'kmx61_set_wake_up_odr' was not declared. Should it be static? Signed-off-by: Fengguang Wu Reviewed-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/imu/kmx61.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index bda9c40c020b13..9b32f012ca0fe2 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -419,7 +419,7 @@ static int kmx61_get_mode(struct kmx61_data *data, u8 *mode, u8 device) return 0; } -int kmx61_set_wake_up_odr(struct kmx61_data *data, int val, int val2) +static int kmx61_set_wake_up_odr(struct kmx61_data *data, int val, int val2) { int ret, odr_bits; From 3f7531c3b37d232122d5b7c8564d4ea800adaa88 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 10 Dec 2014 17:41:43 +0100 Subject: [PATCH 0178/3023] drm/i915: Name the lrc irq handler correctly We consistently use the _irq_handler postfix for functions called in hardirq context. Especially when it's a non-static function hardirq is a crazy enough calling context to warrant this level of ocd. So rename it. Cc: Thomas Daniel Reviewed-by: Thomas Daniel Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 10 +++++----- drivers/gpu/drm/i915/intel_lrc.c | 4 ++-- drivers/gpu/drm/i915/intel_lrc.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index e6a1db36928e97..e3dd2d62c99217 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1385,14 +1385,14 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, if (rcs & GT_RENDER_USER_INTERRUPT) notify_ring(dev, ring); if (rcs & GT_CONTEXT_SWITCH_INTERRUPT) - intel_execlists_handle_ctx_events(ring); + intel_lrc_irq_handler(ring); bcs = tmp >> GEN8_BCS_IRQ_SHIFT; ring = &dev_priv->ring[BCS]; if (bcs & GT_RENDER_USER_INTERRUPT) notify_ring(dev, ring); if (bcs & GT_CONTEXT_SWITCH_INTERRUPT) - intel_execlists_handle_ctx_events(ring); + intel_lrc_irq_handler(ring); } else DRM_ERROR("The master control interrupt lied (GT0)!\n"); } @@ -1408,14 +1408,14 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, if (vcs & GT_RENDER_USER_INTERRUPT) notify_ring(dev, ring); if (vcs & GT_CONTEXT_SWITCH_INTERRUPT) - intel_execlists_handle_ctx_events(ring); + intel_lrc_irq_handler(ring); vcs = tmp >> GEN8_VCS2_IRQ_SHIFT; ring = &dev_priv->ring[VCS2]; if (vcs & GT_RENDER_USER_INTERRUPT) notify_ring(dev, ring); if (vcs & GT_CONTEXT_SWITCH_INTERRUPT) - intel_execlists_handle_ctx_events(ring); + intel_lrc_irq_handler(ring); } else DRM_ERROR("The master control interrupt lied (GT1)!\n"); } @@ -1442,7 +1442,7 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, if (vcs & GT_RENDER_USER_INTERRUPT) notify_ring(dev, ring); if (vcs & GT_CONTEXT_SWITCH_INTERRUPT) - intel_execlists_handle_ctx_events(ring); + intel_lrc_irq_handler(ring); } else DRM_ERROR("The master control interrupt lied (GT3)!\n"); } diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index a82020ea9d0a98..89b5577afe71ed 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -474,13 +474,13 @@ static bool execlists_check_remove_request(struct intel_engine_cs *ring, } /** - * intel_execlists_handle_ctx_events() - handle Context Switch interrupts + * intel_lrc_irq_handler() - handle Context Switch interrupts * @ring: Engine Command Streamer to handle. * * Check the unread Context Status Buffers and manage the submission of new * contexts to the ELSP accordingly. */ -void intel_execlists_handle_ctx_events(struct intel_engine_cs *ring) +void intel_lrc_irq_handler(struct intel_engine_cs *ring) { struct drm_i915_private *dev_priv = ring->dev->dev_private; u32 status_pointer; diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index 14b216b9be7f2f..960fcbd2c98ae8 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -112,7 +112,7 @@ struct intel_ctx_submit_request { int elsp_submitted; }; -void intel_execlists_handle_ctx_events(struct intel_engine_cs *ring); +void intel_lrc_irq_handler(struct intel_engine_cs *ring); void intel_execlists_retire_requests(struct intel_engine_cs *ring); #endif /* _INTEL_LRC_H_ */ From 5f77eeb05c9ee1de03fbe695b41362aae401726a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 8 Dec 2014 16:40:10 +0100 Subject: [PATCH 0179/3023] drm/i915: Use BUILD_BUG if possible in the i915 WARN_ON Faster feedback to errors is always better. This is inspired by the addition to WARN_ONs to mask/enable helpers for registers to make sure callers have the arguments ordered correctly: Pretty much always the arguments are static. We use WARN_ON(1) a lot in default switch statements though where we should always handle all cases. So add a new macro specifically for that. The idea to use __builtin_constant_p is from Chris Wilson. v2: Use the ({}) gcc-ism to avoid the static inline, suggested by Dave. My first attempt used __cond as the temp var, which is the same used by BUILD_BUG_ON, but with inverted sense. Hilarity ensued, so sprinkle i915 into the name. Also use a temporary variable to only evaluate the condition once, suggested by Damien. v3: It's crazy but apparently 32bit gcc can't compile out the BUILD_BUG_ON in a lot of cases and just falls over. I have no idea why, but until clue grows just disable this nifty idea on 32bit builds. Reported by 0-day builder. v4: Got it all wrong, apparently its the gcc version. We need 4.9+. Now reported by Imre. v5: Chris suggested to add the case to MISSING_CASE for speedier debug. v6: Even some gcc 4.9 versions don't see through the maze, so give up for now. Keep the skeleton and MISSING_CASE stuff though. Cc: Imre Deak Cc: Damien Lespiau Cc: Chris Wilson Cc: Jani Nikula Cc: Dave Gordon Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 14 +++++++++++++- drivers/gpu/drm/i915/i915_gem_gtt.c | 6 +++--- drivers/gpu/drm/i915/intel_display.c | 4 ++-- drivers/gpu/drm/i915/intel_uncore.c | 4 ++-- 5 files changed, 21 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 165a38f3600984..479e0c11911160 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2347,7 +2347,7 @@ static const char *power_domain_str(enum intel_display_power_domain domain) case POWER_DOMAIN_INIT: return "INIT"; default: - WARN_ON(1); + MISSING_CASE(domain); return "?"; } } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c74dc946cbf63d..5f4cca3ef01c0d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -58,7 +58,19 @@ #define DRIVER_DATE "20141205" #undef WARN_ON -#define WARN_ON(x) WARN(x, "WARN_ON(" #x ")") +/* Many gcc seem to no see through this and fall over :( */ +#if 0 +#define WARN_ON(x) ({ \ + bool __i915_warn_cond = (x); \ + if (__builtin_constant_p(__i915_warn_cond)) \ + BUILD_BUG_ON(__i915_warn_cond); \ + WARN(__i915_warn_cond, "WARN_ON(" #x ")"); }) +#else +#define WARN_ON(x) WARN((x), "WARN_ON(" #x ")") +#endif + +#define MISSING_CASE(x) WARN(1, "Missing switch case (%lu) in %s\n", \ + (long) (x), __func__); enum pipe { INVALID_PIPE = -1, diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index ac03a382000b62..ce4e46c443a1a2 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -132,7 +132,7 @@ static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr, pte |= GEN6_PTE_UNCACHED; break; default: - WARN_ON(1); + MISSING_CASE(level); } return pte; @@ -156,7 +156,7 @@ static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr, pte |= GEN6_PTE_UNCACHED; break; default: - WARN_ON(1); + MISSING_CASE(level); } return pte; @@ -1146,7 +1146,7 @@ int i915_ppgtt_init_hw(struct drm_device *dev) else if (INTEL_INFO(dev)->gen >= 8) gen8_ppgtt_enable(dev); else - WARN_ON(1); + MISSING_CASE(INTEL_INFO(dev)->gen); if (ppgtt) { for_each_ring(ring, dev_priv, i) { diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 841af6c1f50be9..878c4857ff4923 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4847,7 +4847,7 @@ static void cherryview_set_cdclk(struct drm_device *dev, int cdclk) cmd = 0; break; default: - WARN_ON(1); + MISSING_CASE(cdclk); return; } @@ -8224,7 +8224,7 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base) cntl |= CURSOR_MODE_256_ARGB_AX; break; default: - WARN_ON(1); + MISSING_CASE(intel_crtc->cursor_width); return; } cntl |= pipe << 28; /* Connect to correct pipe */ diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 46de8d75b4bf6f..883d2febb7058e 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1202,7 +1202,7 @@ void intel_uncore_init(struct drm_device *dev) switch (INTEL_INFO(dev)->gen) { default: - WARN_ON(1); + MISSING_CASE(INTEL_INFO(dev)->gen); return; case 9: ASSIGN_WRITE_MMIO_VFUNCS(gen9); @@ -1300,7 +1300,7 @@ int i915_reg_read_ioctl(struct drm_device *dev, reg->val = I915_READ8(reg->offset); break; default: - WARN_ON(1); + MISSING_CASE(entry->size); ret = -EINVAL; goto out; } From f915084edc5aad351d6a4675b0bcdded9a00090d Mon Sep 17 00:00:00 2001 From: Gaurav K Singh Date: Wed, 10 Dec 2014 22:07:40 +0530 Subject: [PATCH 0180/3023] drm/i915: Changes related to the sequence port no for From now on for both DSI Ports A & C, the seq_port value has been set to 0. seq_port value is parsed from Sequence block#53 of VBT. So, for packets that needs to be read/write for DSI single link on Port A and Port C will now be based on the DVO port from VBT block 2, instead of seq_port. Signed-off-by: Gaurav K Singh Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index f8c2269c434ce2..5493aef5a6a320 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -110,7 +110,15 @@ static u8 *mipi_exec_send_packet(struct intel_dsi *intel_dsi, u8 *data) vc = (byte >> MIPI_VIRTUAL_CHANNEL_SHIFT) & 0x3; seq_port = (byte >> MIPI_PORT_SHIFT) & 0x3; - port = intel_dsi_seq_port_to_port(seq_port); + /* For DSI single link on Port A & C, the seq_port value which is + * parsed from Sequence Block#53 of VBT has been set to 0 + * Now, read/write of packets for the DSI single link on Port A and + * Port C will based on the DVO port from VBT block 2. + */ + if (intel_dsi->ports == (1 << PORT_C)) + port = PORT_C; + else + port = intel_dsi_seq_port_to_port(seq_port); /* LP or HS mode */ intel_dsi->hs = mode; From db5ff4ac97f6602360645414b698a05f91b40542 Mon Sep 17 00:00:00 2001 From: Deepak S Date: Thu, 11 Dec 2014 21:42:49 +0530 Subject: [PATCH 0181/3023] drm/i915: Forcewake Register Range changes for CHV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to updated BSpec, Render/Common/media Wells register range changed. Updating the same to match the spec and avoid extra forcewake for none forcewake range. v2: Update media forcewake range (Ville) Signed-off-by: Deepak S Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_uncore.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 883d2febb7058e..e9561de382aa4c 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -647,9 +647,9 @@ void assert_force_wake_inactive(struct drm_i915_private *dev_priv) #define FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg) \ (REG_RANGE((reg), 0x2000, 0x4000) || \ - REG_RANGE((reg), 0x5000, 0x8000) || \ + REG_RANGE((reg), 0x5200, 0x8000) || \ REG_RANGE((reg), 0x8300, 0x8500) || \ - REG_RANGE((reg), 0xB000, 0xC000) || \ + REG_RANGE((reg), 0xB000, 0xB480) || \ REG_RANGE((reg), 0xE000, 0xE800)) #define FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg) \ @@ -658,17 +658,14 @@ void assert_force_wake_inactive(struct drm_i915_private *dev_priv) REG_RANGE((reg), 0x12000, 0x14000) || \ REG_RANGE((reg), 0x1A000, 0x1C000) || \ REG_RANGE((reg), 0x1E800, 0x1EA00) || \ - REG_RANGE((reg), 0x30000, 0x40000)) + REG_RANGE((reg), 0x30000, 0x38000)) #define FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg) \ (REG_RANGE((reg), 0x4000, 0x5000) || \ REG_RANGE((reg), 0x8000, 0x8300) || \ REG_RANGE((reg), 0x8500, 0x8600) || \ REG_RANGE((reg), 0x9000, 0xB000) || \ - REG_RANGE((reg), 0xC000, 0xC800) || \ - REG_RANGE((reg), 0xF000, 0x10000) || \ - REG_RANGE((reg), 0x14000, 0x14400) || \ - REG_RANGE((reg), 0x22000, 0x24000)) + REG_RANGE((reg), 0xF000, 0x10000)) #define FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg) \ REG_RANGE((reg), 0xB00, 0x2000) From fe14d5f4e5468c5b80a24f1a64abcbe116143670 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Wed, 10 Dec 2014 17:27:58 +0000 Subject: [PATCH 0182/3023] drm/i915: Infrastructure for supporting different GGTT views per object Things like reliable GGTT mappings and mirrored 2d-on-3d display will need to map objects into the same address space multiple times. Added a GGTT view concept and linked it with the VMA to distinguish between multiple instances per address space. New objects and GEM functions which do not take this new view as a parameter assume the default of zero (I915_GGTT_VIEW_NORMAL) which preserves the previous behaviour. This now means that objects can have multiple VMA entries so the code which assumed there will only be one also had to be modified. Alternative GGTT views are supposed to borrow DMA addresses from obj->pages which is DMA mapped on first VMA instantiation and unmapped on the last one going away. v2: * Removed per view special casing in i915_gem_ggtt_prepare / finish_object in favour of creating and destroying DMA mappings on first VMA instantiation and last VMA destruction. (Daniel Vetter) * Simplified i915_vma_unbind which does not need to count the GGTT views. (Daniel Vetter) * Also moved obj->map_and_fenceable reset under the same check. * Checkpatch cleanups. v3: * Only retire objects once the last VMA is unbound. v4: * Keep scatter-gather table for alternative views persistent for the lifetime of the VMA. * Propagate binding errors to callers and handle appropriately. v5: * Explicitly look for normal GGTT view in i915_gem_obj_bound to align usage in i915_gem_object_ggtt_unpin. (Michel Thierry) * Change to single if statement in i915_gem_obj_to_ggtt. (Michel Thierry) * Removed stray semi-colon in i915_gem_object_set_cache_level. For: VIZ-4544 Signed-off-by: Tvrtko Ursulin Cc: Daniel Vetter Reviewed-by: Michel Thierry [danvet: Drop hunk from i915_gem_shrink since it's just prettification but upsets a __must_check warning.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 5 +- drivers/gpu/drm/i915/i915_drv.h | 56 ++++++++++- drivers/gpu/drm/i915/i915_gem.c | 109 +++++++++++++-------- drivers/gpu/drm/i915/i915_gem_context.c | 11 ++- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 9 +- drivers/gpu/drm/i915/i915_gem_gtt.c | 70 +++++++++++-- drivers/gpu/drm/i915/i915_gem_gtt.h | 22 +++++ drivers/gpu/drm/i915/i915_gpu_error.c | 8 +- 8 files changed, 220 insertions(+), 70 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 479e0c11911160..8d2988ae3c4600 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -152,8 +152,9 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) seq_puts(m, " (pp"); else seq_puts(m, " (g"); - seq_printf(m, "gtt offset: %08lx, size: %08lx)", - vma->node.start, vma->node.size); + seq_printf(m, "gtt offset: %08lx, size: %08lx, type: %u)", + vma->node.start, vma->node.size, + vma->ggtt_view.type); } if (obj->stolen) seq_printf(m, " (stolen: %08lx)", obj->stolen->start); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5f4cca3ef01c0d..eb47990f827c41 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2530,10 +2530,23 @@ void i915_gem_vma_destroy(struct i915_vma *vma); #define PIN_GLOBAL 0x4 #define PIN_OFFSET_BIAS 0x8 #define PIN_OFFSET_MASK (~4095) +int __must_check i915_gem_object_pin_view(struct drm_i915_gem_object *obj, + struct i915_address_space *vm, + uint32_t alignment, + uint64_t flags, + const struct i915_ggtt_view *view); +static inline int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj, struct i915_address_space *vm, uint32_t alignment, - uint64_t flags); + uint64_t flags) +{ + return i915_gem_object_pin_view(obj, vm, alignment, flags, + &i915_ggtt_view_normal); +} + +int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level, + u32 flags); int __must_check i915_vma_unbind(struct i915_vma *vma); int i915_gem_object_put_pages(struct drm_i915_gem_object *obj); void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv); @@ -2695,18 +2708,51 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev, void i915_gem_restore_fences(struct drm_device *dev); +unsigned long i915_gem_obj_offset_view(struct drm_i915_gem_object *o, + struct i915_address_space *vm, + enum i915_ggtt_view_type view); +static inline unsigned long i915_gem_obj_offset(struct drm_i915_gem_object *o, - struct i915_address_space *vm); + struct i915_address_space *vm) +{ + return i915_gem_obj_offset_view(o, vm, I915_GGTT_VIEW_NORMAL); +} bool i915_gem_obj_bound_any(struct drm_i915_gem_object *o); +bool i915_gem_obj_bound_view(struct drm_i915_gem_object *o, + struct i915_address_space *vm, + enum i915_ggtt_view_type view); +static inline bool i915_gem_obj_bound(struct drm_i915_gem_object *o, - struct i915_address_space *vm); + struct i915_address_space *vm) +{ + return i915_gem_obj_bound_view(o, vm, I915_GGTT_VIEW_NORMAL); +} + unsigned long i915_gem_obj_size(struct drm_i915_gem_object *o, struct i915_address_space *vm); +struct i915_vma *i915_gem_obj_to_vma_view(struct drm_i915_gem_object *obj, + struct i915_address_space *vm, + const struct i915_ggtt_view *view); +static inline struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj, - struct i915_address_space *vm); + struct i915_address_space *vm) +{ + return i915_gem_obj_to_vma_view(obj, vm, &i915_ggtt_view_normal); +} + +struct i915_vma * +i915_gem_obj_lookup_or_create_vma_view(struct drm_i915_gem_object *obj, + struct i915_address_space *vm, + const struct i915_ggtt_view *view); + +static inline struct i915_vma * i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj, - struct i915_address_space *vm); + struct i915_address_space *vm) +{ + return i915_gem_obj_lookup_or_create_vma_view(obj, vm, + &i915_ggtt_view_normal); +} struct i915_vma *i915_gem_obj_to_ggtt(struct drm_i915_gem_object *obj); static inline bool i915_gem_obj_is_pinned(struct drm_i915_gem_object *obj) { diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index e3ce4bef22a366..c26d4ccd183afa 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2297,17 +2297,14 @@ void i915_vma_move_to_active(struct i915_vma *vma, static void i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj) { - struct drm_i915_private *dev_priv = obj->base.dev->dev_private; - struct i915_address_space *vm; struct i915_vma *vma; BUG_ON(obj->base.write_domain & ~I915_GEM_GPU_DOMAINS); BUG_ON(!obj->active); - list_for_each_entry(vm, &dev_priv->vm_list, global_link) { - vma = i915_gem_obj_to_vma(obj, vm); - if (vma && !list_empty(&vma->mm_list)) - list_move_tail(&vma->mm_list, &vm->inactive_list); + list_for_each_entry(vma, &obj->vma_list, vma_link) { + if (!list_empty(&vma->mm_list)) + list_move_tail(&vma->mm_list, &vma->vm->inactive_list); } intel_fb_obj_flush(obj, true); @@ -3062,10 +3059,8 @@ int i915_vma_unbind(struct i915_vma *vma) * cause memory corruption through use-after-free. */ - /* Throw away the active reference before moving to the unbound list */ - i915_gem_object_retire(obj); - - if (i915_is_ggtt(vma->vm)) { + if (i915_is_ggtt(vma->vm) && + vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL) { i915_gem_object_finish_gtt(obj); /* release the fence reg _after_ flushing */ @@ -3079,8 +3074,15 @@ int i915_vma_unbind(struct i915_vma *vma) vma->unbind_vma(vma); list_del_init(&vma->mm_list); - if (i915_is_ggtt(vma->vm)) - obj->map_and_fenceable = false; + if (i915_is_ggtt(vma->vm)) { + if (vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL) { + obj->map_and_fenceable = false; + } else if (vma->ggtt_view.pages) { + sg_free_table(vma->ggtt_view.pages); + kfree(vma->ggtt_view.pages); + vma->ggtt_view.pages = NULL; + } + } drm_mm_remove_node(&vma->node); i915_gem_vma_destroy(vma); @@ -3088,6 +3090,10 @@ int i915_vma_unbind(struct i915_vma *vma) /* Since the unbound list is global, only move to that list if * no more VMAs exist. */ if (list_empty(&obj->vma_list)) { + /* Throw away the active reference before + * moving to the unbound list. */ + i915_gem_object_retire(obj); + i915_gem_gtt_finish_object(obj); list_move_tail(&obj->global_list, &dev_priv->mm.unbound_list); } @@ -3498,7 +3504,8 @@ static struct i915_vma * i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, struct i915_address_space *vm, unsigned alignment, - uint64_t flags) + uint64_t flags, + const struct i915_ggtt_view *view) { struct drm_device *dev = obj->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -3548,7 +3555,7 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, i915_gem_object_pin_pages(obj); - vma = i915_gem_obj_lookup_or_create_vma(obj, vm); + vma = i915_gem_obj_lookup_or_create_vma_view(obj, vm, view); if (IS_ERR(vma)) goto err_unpin; @@ -3578,15 +3585,19 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, if (ret) goto err_remove_node; + trace_i915_vma_bind(vma, flags); + ret = i915_vma_bind(vma, obj->cache_level, + flags & PIN_GLOBAL ? GLOBAL_BIND : 0); + if (ret) + goto err_finish_gtt; + list_move_tail(&obj->global_list, &dev_priv->mm.bound_list); list_add_tail(&vma->mm_list, &vm->inactive_list); - trace_i915_vma_bind(vma, flags); - vma->bind_vma(vma, obj->cache_level, - flags & PIN_GLOBAL ? GLOBAL_BIND : 0); - return vma; +err_finish_gtt: + i915_gem_gtt_finish_object(obj); err_remove_node: drm_mm_remove_node(&vma->node); err_free_vma: @@ -3789,9 +3800,12 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, } list_for_each_entry(vma, &obj->vma_list, vma_link) - if (drm_mm_node_allocated(&vma->node)) - vma->bind_vma(vma, cache_level, - vma->bound & GLOBAL_BIND); + if (drm_mm_node_allocated(&vma->node)) { + ret = i915_vma_bind(vma, cache_level, + vma->bound & GLOBAL_BIND); + if (ret) + return ret; + } } list_for_each_entry(vma, &obj->vma_list, vma_link) @@ -4144,10 +4158,11 @@ i915_vma_misplaced(struct i915_vma *vma, uint32_t alignment, uint64_t flags) } int -i915_gem_object_pin(struct drm_i915_gem_object *obj, - struct i915_address_space *vm, - uint32_t alignment, - uint64_t flags) +i915_gem_object_pin_view(struct drm_i915_gem_object *obj, + struct i915_address_space *vm, + uint32_t alignment, + uint64_t flags, + const struct i915_ggtt_view *view) { struct drm_i915_private *dev_priv = obj->base.dev->dev_private; struct i915_vma *vma; @@ -4163,7 +4178,7 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj, if (WARN_ON((flags & (PIN_MAPPABLE | PIN_GLOBAL)) == PIN_MAPPABLE)) return -EINVAL; - vma = i915_gem_obj_to_vma(obj, vm); + vma = i915_gem_obj_to_vma_view(obj, vm, view); if (vma) { if (WARN_ON(vma->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT)) return -EBUSY; @@ -4173,7 +4188,8 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj, "bo is already pinned with incorrect alignment:" " offset=%lx, req.alignment=%x, req.map_and_fenceable=%d," " obj->map_and_fenceable=%d\n", - i915_gem_obj_offset(obj, vm), alignment, + i915_gem_obj_offset_view(obj, vm, view->type), + alignment, !!(flags & PIN_MAPPABLE), obj->map_and_fenceable); ret = i915_vma_unbind(vma); @@ -4186,13 +4202,17 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj, bound = vma ? vma->bound : 0; if (vma == NULL || !drm_mm_node_allocated(&vma->node)) { - vma = i915_gem_object_bind_to_vm(obj, vm, alignment, flags); + vma = i915_gem_object_bind_to_vm(obj, vm, alignment, + flags, view); if (IS_ERR(vma)) return PTR_ERR(vma); } - if (flags & PIN_GLOBAL && !(vma->bound & GLOBAL_BIND)) - vma->bind_vma(vma, obj->cache_level, GLOBAL_BIND); + if (flags & PIN_GLOBAL && !(vma->bound & GLOBAL_BIND)) { + ret = i915_vma_bind(vma, obj->cache_level, GLOBAL_BIND); + if (ret) + return ret; + } if ((bound ^ vma->bound) & GLOBAL_BIND) { bool mappable, fenceable; @@ -4528,12 +4548,13 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) intel_runtime_pm_put(dev_priv); } -struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj, - struct i915_address_space *vm) +struct i915_vma *i915_gem_obj_to_vma_view(struct drm_i915_gem_object *obj, + struct i915_address_space *vm, + const struct i915_ggtt_view *view) { struct i915_vma *vma; list_for_each_entry(vma, &obj->vma_list, vma_link) - if (vma->vm == vm) + if (vma->vm == vm && vma->ggtt_view.type == view->type) return vma; return NULL; @@ -5145,8 +5166,9 @@ i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc) } /* All the new VM stuff */ -unsigned long i915_gem_obj_offset(struct drm_i915_gem_object *o, - struct i915_address_space *vm) +unsigned long i915_gem_obj_offset_view(struct drm_i915_gem_object *o, + struct i915_address_space *vm, + enum i915_ggtt_view_type view) { struct drm_i915_private *dev_priv = o->base.dev->dev_private; struct i915_vma *vma; @@ -5154,7 +5176,7 @@ unsigned long i915_gem_obj_offset(struct drm_i915_gem_object *o, WARN_ON(vm == &dev_priv->mm.aliasing_ppgtt->base); list_for_each_entry(vma, &o->vma_list, vma_link) { - if (vma->vm == vm) + if (vma->vm == vm && vma->ggtt_view.type == view) return vma->node.start; } @@ -5163,13 +5185,16 @@ unsigned long i915_gem_obj_offset(struct drm_i915_gem_object *o, return -1; } -bool i915_gem_obj_bound(struct drm_i915_gem_object *o, - struct i915_address_space *vm) +bool i915_gem_obj_bound_view(struct drm_i915_gem_object *o, + struct i915_address_space *vm, + enum i915_ggtt_view_type view) { struct i915_vma *vma; list_for_each_entry(vma, &o->vma_list, vma_link) - if (vma->vm == vm && drm_mm_node_allocated(&vma->node)) + if (vma->vm == vm && + vma->ggtt_view.type == view && + drm_mm_node_allocated(&vma->node)) return true; return false; @@ -5304,10 +5329,10 @@ struct i915_vma *i915_gem_obj_to_ggtt(struct drm_i915_gem_object *obj) struct i915_address_space *ggtt = i915_obj_to_ggtt(obj); struct i915_vma *vma; - list_for_each_entry(vma, &obj->vma_list, vma_link) { - if (vma->vm == ggtt) + list_for_each_entry(vma, &obj->vma_list, vma_link) + if (vma->vm == ggtt && + vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL) return vma; - } return NULL; } diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 2acf5803cf3221..b9deade53f2e27 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -590,9 +590,14 @@ static int do_switch(struct intel_engine_cs *ring, goto unpin_out; vma = i915_gem_obj_to_ggtt(to->legacy_hw_ctx.rcs_state); - if (!(vma->bound & GLOBAL_BIND)) - vma->bind_vma(vma, to->legacy_hw_ctx.rcs_state->cache_level, - GLOBAL_BIND); + if (!(vma->bound & GLOBAL_BIND)) { + ret = i915_vma_bind(vma, + to->legacy_hw_ctx.rcs_state->cache_level, + GLOBAL_BIND); + /* This shouldn't ever fail. */ + if (WARN_ONCE(ret, "GGTT context bind failed!")) + goto unpin_out; + } if (!to->legacy_hw_ctx.initialized || i915_gem_context_is_default(to)) hw_flags |= MI_RESTORE_INHIBIT; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 0c25f6202ca4bb..3927d931ad730d 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -360,9 +360,12 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, * through the ppgtt for non_secure batchbuffers. */ if (unlikely(IS_GEN6(dev) && reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION && - !(target_vma->bound & GLOBAL_BIND))) - target_vma->bind_vma(target_vma, target_i915_obj->cache_level, - GLOBAL_BIND); + !(target_vma->bound & GLOBAL_BIND))) { + ret = i915_vma_bind(target_vma, target_i915_obj->cache_level, + GLOBAL_BIND); + if (WARN_ONCE(ret, "Unexpected failure to bind target VMA!")) + return ret; + } /* Validate that the target is in a valid r/w GPU domain */ if (unlikely(reloc->write_domain & (reloc->write_domain - 1))) { diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index ce4e46c443a1a2..9821a6095e53fd 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -30,6 +30,8 @@ #include "i915_trace.h" #include "intel_drv.h" +const struct i915_ggtt_view i915_ggtt_view_normal; + static void bdw_setup_private_ppat(struct drm_i915_private *dev_priv); static void chv_setup_private_ppat(struct drm_i915_private *dev_priv); @@ -1341,9 +1343,12 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev) /* The bind_vma code tries to be smart about tracking mappings. * Unfortunately above, we've just wiped out the mappings * without telling our object about it. So we need to fake it. + * + * Bind is not expected to fail since this is only called on + * resume and assumption is all requirements exist already. */ vma->bound &= ~GLOBAL_BIND; - vma->bind_vma(vma, obj->cache_level, GLOBAL_BIND); + WARN_ON(i915_vma_bind(vma, obj->cache_level, GLOBAL_BIND)); } @@ -1538,7 +1543,7 @@ static void i915_ggtt_bind_vma(struct i915_vma *vma, AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY; BUG_ON(!i915_is_ggtt(vma->vm)); - intel_gtt_insert_sg_entries(vma->obj->pages, entry, flags); + intel_gtt_insert_sg_entries(vma->ggtt_view.pages, entry, flags); vma->bound = GLOBAL_BIND; } @@ -1588,7 +1593,7 @@ static void ggtt_bind_vma(struct i915_vma *vma, if (!dev_priv->mm.aliasing_ppgtt || flags & GLOBAL_BIND) { if (!(vma->bound & GLOBAL_BIND) || (cache_level != obj->cache_level)) { - vma->vm->insert_entries(vma->vm, obj->pages, + vma->vm->insert_entries(vma->vm, vma->ggtt_view.pages, vma->node.start, cache_level, flags); vma->bound |= GLOBAL_BIND; @@ -1600,7 +1605,7 @@ static void ggtt_bind_vma(struct i915_vma *vma, (cache_level != obj->cache_level))) { struct i915_hw_ppgtt *appgtt = dev_priv->mm.aliasing_ppgtt; appgtt->base.insert_entries(&appgtt->base, - vma->obj->pages, + vma->ggtt_view.pages, vma->node.start, cache_level, flags); vma->bound |= LOCAL_BIND; @@ -2165,7 +2170,8 @@ int i915_gem_gtt_init(struct drm_device *dev) } static struct i915_vma *__i915_gem_vma_create(struct drm_i915_gem_object *obj, - struct i915_address_space *vm) + struct i915_address_space *vm, + const struct i915_ggtt_view *view) { struct i915_vma *vma = kzalloc(sizeof(*vma), GFP_KERNEL); if (vma == NULL) @@ -2176,6 +2182,7 @@ static struct i915_vma *__i915_gem_vma_create(struct drm_i915_gem_object *obj, INIT_LIST_HEAD(&vma->exec_list); vma->vm = vm; vma->obj = obj; + vma->ggtt_view = *view; switch (INTEL_INFO(vm->dev)->gen) { case 9: @@ -2210,14 +2217,59 @@ static struct i915_vma *__i915_gem_vma_create(struct drm_i915_gem_object *obj, } struct i915_vma * -i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj, - struct i915_address_space *vm) +i915_gem_obj_lookup_or_create_vma_view(struct drm_i915_gem_object *obj, + struct i915_address_space *vm, + const struct i915_ggtt_view *view) { struct i915_vma *vma; - vma = i915_gem_obj_to_vma(obj, vm); + vma = i915_gem_obj_to_vma_view(obj, vm, view); if (!vma) - vma = __i915_gem_vma_create(obj, vm); + vma = __i915_gem_vma_create(obj, vm, view); return vma; } + +static inline +int i915_get_vma_pages(struct i915_vma *vma) +{ + if (vma->ggtt_view.pages) + return 0; + + if (vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL) + vma->ggtt_view.pages = vma->obj->pages; + else + WARN_ONCE(1, "GGTT view %u not implemented!\n", + vma->ggtt_view.type); + + if (!vma->ggtt_view.pages) { + DRM_ERROR("Failed to get pages for VMA view type %u!\n", + vma->ggtt_view.type); + return -EINVAL; + } + + return 0; +} + +/** + * i915_vma_bind - Sets up PTEs for an VMA in it's corresponding address space. + * @vma: VMA to map + * @cache_level: mapping cache level + * @flags: flags like global or local mapping + * + * DMA addresses are taken from the scatter-gather table of this object (or of + * this VMA in case of non-default GGTT views) and PTE entries set up. + * Note that DMA addresses are also the only part of the SG table we care about. + */ +int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level, + u32 flags) +{ + int ret = i915_get_vma_pages(vma); + + if (ret) + return ret; + + vma->bind_vma(vma, cache_level, flags); + + return 0; +} diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index dd849df6a26863..e377c7d27bd422 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -109,7 +109,20 @@ typedef gen8_gtt_pte_t gen8_ppgtt_pde_t; #define GEN8_PPAT_ELLC_OVERRIDE (0<<2) #define GEN8_PPAT(i, x) ((uint64_t) (x) << ((i) * 8)) +enum i915_ggtt_view_type { + I915_GGTT_VIEW_NORMAL = 0, +}; + +struct i915_ggtt_view { + enum i915_ggtt_view_type type; + + struct sg_table *pages; +}; + +extern const struct i915_ggtt_view i915_ggtt_view_normal; + enum i915_cache_level; + /** * A VMA represents a GEM BO that is bound into an address space. Therefore, a * VMA's presence cannot be guaranteed before binding, or after unbinding the @@ -129,6 +142,15 @@ struct i915_vma { #define PTE_READ_ONLY (1<<2) unsigned int bound : 4; + /** + * Support different GGTT views into the same object. + * This means there can be multiple VMA mappings per object and per VM. + * i915_ggtt_view_type is used to distinguish between those entries. + * The default one of zero (I915_GGTT_VIEW_NORMAL) is default and also + * assumed in GEM functions which take no ggtt view parameter. + */ + struct i915_ggtt_view ggtt_view; + /** This object's place on the active/inactive lists */ struct list_head mm_list; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index c4536e185b7506..f97479a2ea6f0d 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -718,10 +718,8 @@ static u32 capture_pinned_bo(struct drm_i915_error_buffer *err, break; list_for_each_entry(vma, &obj->vma_list, vma_link) - if (vma->vm == vm && vma->pin_count > 0) { + if (vma->vm == vm && vma->pin_count > 0) capture_bo(err++, vma); - break; - } } return err - first; @@ -1096,10 +1094,8 @@ static void i915_gem_capture_vm(struct drm_i915_private *dev_priv, list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { list_for_each_entry(vma, &obj->vma_list, vma_link) - if (vma->vm == vm && vma->pin_count > 0) { + if (vma->vm == vm && vma->pin_count > 0) i++; - break; - } } error->pinned_bo_count[ndx] = i - error->active_bo_count[ndx]; From 45f8f69abc789acea7f0b06e604644945794c709 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Wed, 10 Dec 2014 17:27:59 +0000 Subject: [PATCH 0183/3023] drm/i915: Documentation for multiple GGTT views A short section describing background, implementation and intended usage. v2: * Align section name between template and DOC comment. (Michel Thierry) For: VIZ-4544 Signed-off-by: Tvrtko Ursulin Reviewed-by: Michel Thierry Signed-off-by: Daniel Vetter --- Documentation/DocBook/drm.tmpl | 5 +++ drivers/gpu/drm/i915/i915_gem_gtt.c | 60 +++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 4fc5d730959b47..f931b3decccdbf 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -4038,6 +4038,11 @@ int num_ioctls; !Pdrivers/gpu/drm/i915/intel_lrc.c Logical Rings, Logical Ring Contexts and Execlists !Idrivers/gpu/drm/i915/intel_lrc.c + + Global GTT views +!Pdrivers/gpu/drm/i915/i915_gem_gtt.c Global GTT views +!Idrivers/gpu/drm/i915/i915_gem_gtt.c + diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 9821a6095e53fd..cc3056f2c7f4a6 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -30,6 +30,66 @@ #include "i915_trace.h" #include "intel_drv.h" +/** + * DOC: Global GTT views + * + * Background and previous state + * + * Historically objects could exists (be bound) in global GTT space only as + * singular instances with a view representing all of the object's backing pages + * in a linear fashion. This view will be called a normal view. + * + * To support multiple views of the same object, where the number of mapped + * pages is not equal to the backing store, or where the layout of the pages + * is not linear, concept of a GGTT view was added. + * + * One example of an alternative view is a stereo display driven by a single + * image. In this case we would have a framebuffer looking like this + * (2x2 pages): + * + * 12 + * 34 + * + * Above would represent a normal GGTT view as normally mapped for GPU or CPU + * rendering. In contrast, fed to the display engine would be an alternative + * view which could look something like this: + * + * 1212 + * 3434 + * + * In this example both the size and layout of pages in the alternative view is + * different from the normal view. + * + * Implementation and usage + * + * GGTT views are implemented using VMAs and are distinguished via enum + * i915_ggtt_view_type and struct i915_ggtt_view. + * + * A new flavour of core GEM functions which work with GGTT bound objects were + * added with the _view suffix. They take the struct i915_ggtt_view parameter + * encapsulating all metadata required to implement a view. + * + * As a helper for callers which are only interested in the normal view, + * globally const i915_ggtt_view_normal singleton instance exists. All old core + * GEM API functions, the ones not taking the view parameter, are operating on, + * or with the normal GGTT view. + * + * Code wanting to add or use a new GGTT view needs to: + * + * 1. Add a new enum with a suitable name. + * 2. Extend the metadata in the i915_ggtt_view structure if required. + * 3. Add support to i915_get_vma_pages(). + * + * New views are required to build a scatter-gather table from within the + * i915_get_vma_pages function. This table is stored in the vma.ggtt_view and + * exists for the lifetime of an VMA. + * + * Core API is designed to have copy semantics which means that passed in + * struct i915_ggtt_view does not need to be persistent (left around after + * calling the core API functions). + * + */ + const struct i915_ggtt_view i915_ggtt_view_normal; static void bdw_setup_private_ppat(struct drm_i915_private *dev_priv); From a712f8ebf80319e29eac117dc614eabecdc31c71 Mon Sep 17 00:00:00 2001 From: Sonika Jindal Date: Tue, 9 Dec 2014 10:59:15 +0530 Subject: [PATCH 0184/3023] drm/i915/skl: Correctly updating sprite wm parameter The pipe wm parameters is not correctly updated with sprite parameters because it copies them for each plane from plane_list to the sprite offset in pipe wm parameters. Since plane_list also contains primary and cursor planes, we end up updating wrong params for sprites. Signed-off-by: Sonika Jindal Reviewed-by: Tvrtko Ursulin Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 99865c046c8a5c..0f7ceba2032f74 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2668,7 +2668,8 @@ static void skl_compute_wm_pipe_parameters(struct drm_crtc *crtc, list_for_each_entry(plane, &dev->mode_config.plane_list, head) { struct intel_plane *intel_plane = to_intel_plane(plane); - if (intel_plane->pipe == pipe) + if (intel_plane->pipe == pipe && + plane->type == DRM_PLANE_TYPE_OVERLAY) p->plane[i++] = intel_plane->wm; } } From 27401d126b5b1c8dd4df98bbb60b09ff2b3d5e60 Mon Sep 17 00:00:00 2001 From: Thomas Daniel Date: Thu, 11 Dec 2014 12:48:35 +0000 Subject: [PATCH 0185/3023] drm/i915/bdw: Enable execlists by default where supported Execlist support in the i915 driver is now considered good enough for the feature to be enabled by default on Gen8 and later and routinely tested. Adjusted i915 parameters structure initialization to reflect this and updated the comment in intel_sanitize_enable_execlists(). There's still work to do before we can let the wider massive onto it, but there's still time left before the 3.20 cutoff. v2: Update the MODULE_PARM_DESC too. Issue: VIZ-2020 Signed-off-by: Thomas Daniel [danvet: Add note that there's still some work left to do.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_params.c | 4 ++-- drivers/gpu/drm/i915/intel_lrc.c | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index c91cb2033cc5ec..f6af6d4c775cb0 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -35,7 +35,7 @@ struct i915_params i915 __read_mostly = { .vbt_sdvo_panel_type = -1, .enable_rc6 = -1, .enable_fbc = -1, - .enable_execlists = 0, + .enable_execlists = -1, .enable_hangcheck = true, .enable_ppgtt = -1, .enable_psr = 0, @@ -122,7 +122,7 @@ MODULE_PARM_DESC(enable_ppgtt, module_param_named(enable_execlists, i915.enable_execlists, int, 0400); MODULE_PARM_DESC(enable_execlists, "Override execlists usage. " - "(-1=auto, 0=disabled [default], 1=enabled)"); + "(-1=auto [default], 0=disabled, 1=enabled)"); module_param_named(enable_psr, i915.enable_psr, int, 0600); MODULE_PARM_DESC(enable_psr, "Enable PSR (default: false)"); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 89b5577afe71ed..4dc6d4263f3d33 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -212,8 +212,7 @@ static int intel_lr_context_pin(struct intel_engine_cs *ring, * @enable_execlists: value of i915.enable_execlists module parameter. * * Only certain platforms support Execlists (the prerequisites being - * support for Logical Ring Contexts and Aliasing PPGTT or better), - * and only when enabled via module parameter. + * support for Logical Ring Contexts and Aliasing PPGTT or better). * * Return: 1 if Execlists is supported and has to be enabled. */ From d9d8e6b3c01386e5b39b70dc07156ff0e407d984 Mon Sep 17 00:00:00 2001 From: Sonika Jindal Date: Thu, 11 Dec 2014 17:58:15 +0530 Subject: [PATCH 0186/3023] drm/i915/skl: Correcting the flushing of pipe We were incorreectly bypassing the flush everytime which led to fifo underrun when more than one plane is enabled. Signed-off-by: Sonika Jindal Reviewed-by: Tvrtko Ursulin Reviewed-by: Satheeshakrishna M Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0f7ceba2032f74..8a960d19374b0a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3004,9 +3004,8 @@ static void skl_flush_wm_values(struct drm_i915_private *dev_priv, skl_ddb_entry_size(&cur_ddb->pipe[pipe])) { skl_wm_flush_pipe(dev_priv, pipe, 2); intel_wait_for_vblank(dev, pipe); + reallocated[pipe] = true; } - - reallocated[pipe] = true; } /* From 371abae844ede392066bfc21202b2e40f4a654d1 Mon Sep 17 00:00:00 2001 From: Deepak M Date: Mon, 15 Dec 2014 15:58:21 +0530 Subject: [PATCH 0187/3023] drm/i915: Parsing LFP brightness control from VBT LFP brighness control from the VBT block 43 indicates which controller is used for brightness. LFP1 brightness control method: Bit 7-4 = This field controller number of the brightnes controller. 0 = Controller 0 1 = Controller 1 2 = Controller 2 3 = Controller 3 Others = Reserved Bits 3-0 = This field specifies the brightness control pin to be used on the platform. 0 = PMIC pin is used for brightness control 1 = LPSS PWM is used for brightness control 2 = Display DDI is used for brightness control 3 = CABC method to control brightness Others = Reserved Adding the above fields in dev_priv->vbt and corresponding changes in parse_backlight() v2: Jani's review comments addressed - Move PWM definitions to intel_bios.h - Moving vbt_version to intel_vbt_data - Rename brightness to bl_ctrl_data - Logging just control_pin instead of string - Avoid adding vbt_version in dev_priv - Since only DDI option is available as of now, let control pin DDI affect dev_priv->vbt.backlight.present v3: Jani's review comments addressed - Drop control_pin - Use bdb->version - set controller to 0 instead of using control pin define - check controller bounds - remove superfluous changes in intel_parse_bios Signed-off-by: Deepak M Signed-off-by: Vandana Kannan Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_bios.c | 20 ++++++++++++++++++++ drivers/gpu/drm/i915/intel_bios.h | 11 +++++++++++ 3 files changed, 32 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index eb47990f827c41..104c288f1e6809 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1367,6 +1367,7 @@ struct intel_vbt_data { bool present; bool active_low_pwm; u8 min_brightness; /* min_brightness/255 of max */ + u8 controller; /* brightness controller number */ } backlight; /* MIPI DSI */ diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 3f178258d9f9ce..65b1fbc5eb57a7 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -314,6 +314,7 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb) { const struct bdb_lfp_backlight_data *backlight_data; const struct bdb_lfp_backlight_data_entry *entry; + const struct bdb_lfp_backlight_control_data *bl_ctrl_data; backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT); if (!backlight_data) @@ -326,6 +327,7 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb) } entry = &backlight_data->data[panel_type]; + bl_ctrl_data = &backlight_data->blc_ctl[panel_type]; dev_priv->vbt.backlight.present = entry->type == BDB_BACKLIGHT_TYPE_PWM; if (!dev_priv->vbt.backlight.present) { @@ -337,12 +339,30 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb) dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz; dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm; dev_priv->vbt.backlight.min_brightness = entry->min_brightness; + + dev_priv->vbt.backlight.controller = 0; + if (bdb->version >= 191) { + dev_priv->vbt.backlight.present = + bl_ctrl_data->pin == BLC_CONTROL_PIN_DDI; + if (!dev_priv->vbt.backlight.present) { + DRM_DEBUG_KMS("BL control pin is not DDI (pin %u)\n", + bl_ctrl_data->pin); + return; + } + if (bl_ctrl_data->controller == 1) + dev_priv->vbt.backlight.controller = + bl_ctrl_data->controller; + } + DRM_DEBUG_KMS("VBT backlight PWM modulation frequency %u Hz, " "active %s, min brightness %u, level %u\n", dev_priv->vbt.backlight.pwm_freq_hz, dev_priv->vbt.backlight.active_low_pwm ? "low" : "high", dev_priv->vbt.backlight.min_brightness, backlight_data->level[panel_type]); + + DRM_DEBUG_KMS("VBT BL controller %u\n", + dev_priv->vbt.backlight.controller); } /* Try to find sdvo panel data */ diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index a6a8710f665f5c..9a7202e5caf45a 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -402,10 +402,21 @@ struct bdb_lfp_backlight_data_entry { u8 obsolete3; } __packed; +#define BLC_CONTROL_PIN_PMIC 0 +#define BLC_CONTROL_PIN_LPSS_PWM 1 +#define BLC_CONTROL_PIN_DDI 2 +#define BLC_CONTROL_PIN_CABC 3 + +struct bdb_lfp_backlight_control_data { + u8 controller:4; + u8 pin:4; +} __packed; + struct bdb_lfp_backlight_data { u8 entry_size; struct bdb_lfp_backlight_data_entry data[16]; u8 level[16]; + struct bdb_lfp_backlight_control_data blc_ctl[16]; } __packed; struct aimdb_header { From 22606a18be1af3d703eab873cb2df83b799a683a Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Fri, 12 Dec 2014 14:26:57 +0000 Subject: [PATCH 0188/3023] drm/i915: Consolidate DDI clock reading out in a single function 2 pieces of code need to read out the DDI clock: the DDI encoder and the MST encoder .get_config() vfuncs. Until now the SKL read out code was only in the former, so let's move the pre and post SKL logic in intel_ddi_clock_get() and this this one everywhere. Signed-off-by: Damien Lespiau Reviewed-by: Dave Airlie Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 4e2e8608b46bb6..1c92ad47502b0f 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -834,7 +834,12 @@ static void hsw_ddi_clock_get(struct intel_encoder *encoder, void intel_ddi_clock_get(struct intel_encoder *encoder, struct intel_crtc_config *pipe_config) { - hsw_ddi_clock_get(encoder, pipe_config); + struct drm_device *dev = encoder->base.dev; + + if (INTEL_INFO(dev)->gen <= 8) + hsw_ddi_clock_get(encoder, pipe_config); + else + skl_ddi_clock_get(encoder, pipe_config); } static void @@ -2029,7 +2034,6 @@ void intel_ddi_get_config(struct intel_encoder *encoder, enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; struct intel_hdmi *intel_hdmi; u32 temp, flags = 0; - struct drm_device *dev = dev_priv->dev; temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); if (temp & TRANS_DDI_PHSYNC) @@ -2106,10 +2110,7 @@ void intel_ddi_get_config(struct intel_encoder *encoder, dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp; } - if (INTEL_INFO(dev)->gen <= 8) - hsw_ddi_clock_get(encoder, pipe_config); - else - skl_ddi_clock_get(encoder, pipe_config); + intel_ddi_clock_get(encoder, pipe_config); } static void intel_ddi_destroy(struct drm_encoder *encoder) From c86ea3d0ad7e60fb92e3d4a0aa4906ec2868a7cd Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Fri, 12 Dec 2014 14:26:58 +0000 Subject: [PATCH 0189/3023] drm/i915/skl: Skylake also supports DP MST I've checked that TRANS_DDI_MODE, DP_TP_CTL MST bits are identical to HSW/BDW on SKL, as well as the long vs short HPD bits. So we have a good chance to be working as well as prevous platforms. Signed-off-by: Damien Lespiau Reviewed-by: Dave Airlie Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 3fc32968252762..8e276c41d4d259 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -5085,7 +5085,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, intel_dp_aux_init(intel_dp, intel_connector); /* init MST on ports that can support it */ - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { + if (IS_HASWELL(dev) || IS_BROADWELL(dev) || INTEL_INFO(dev)->gen >= 9) { if (port == PORT_B || port == PORT_C || port == PORT_D) { intel_dp_mst_encoder_init(intel_dig_port, intel_connector->base.base.id); From b04d4a38c0691e4467fa2988b6fe481bf759daaf Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 15 Dec 2014 12:26:46 -0800 Subject: [PATCH 0190/3023] drm/cache: Use wbinvd helpers When the original drm code was written there were no centralized functions for doing a coordinated wbinvd across all CPUs. Now (since 2010) there are, so use them instead of rolling a new one. v2: On x86 UP systems the wbinvd_on_all_cpus() is defined as a static inline in smp.h. We must therefore include this file so we don't get compiler errors. This error was found by 0-DAY kernel test infrastructure. We only need this for x86. Cc: Intel GFX Signed-off-by: Ben Widawsky Reviewed-by: Chris Wilson (v1) Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_cache.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c index a6b690626a6b05..9a62d7a53553d3 100644 --- a/drivers/gpu/drm/drm_cache.c +++ b/drivers/gpu/drm/drm_cache.c @@ -32,6 +32,7 @@ #include #if defined(CONFIG_X86) +#include /* * clflushopt is an unordered instruction which needs fencing with mfence or @@ -64,12 +65,6 @@ static void drm_cache_flush_clflush(struct page *pages[], drm_clflush_page(*pages++); mb(); } - -static void -drm_clflush_ipi_handler(void *null) -{ - wbinvd(); -} #endif void @@ -82,7 +77,7 @@ drm_clflush_pages(struct page *pages[], unsigned long num_pages) return; } - if (on_each_cpu(drm_clflush_ipi_handler, NULL, 1) != 0) + if (wbinvd_on_all_cpus()) printk(KERN_ERR "Timed out waiting for cache flush.\n"); #elif defined(__powerpc__) @@ -121,7 +116,7 @@ drm_clflush_sg(struct sg_table *st) return; } - if (on_each_cpu(drm_clflush_ipi_handler, NULL, 1) != 0) + if (wbinvd_on_all_cpus()) printk(KERN_ERR "Timed out waiting for cache flush.\n"); #else printk(KERN_ERR "Architecture has no drm_cache.c support\n"); @@ -144,7 +139,7 @@ drm_clflush_virt_range(void *addr, unsigned long length) return; } - if (on_each_cpu(drm_clflush_ipi_handler, NULL, 1) != 0) + if (wbinvd_on_all_cpus()) printk(KERN_ERR "Timed out waiting for cache flush.\n"); #else printk(KERN_ERR "Architecture has no drm_cache.c support\n"); From c8bd0e49519ce1d80196e54ba2e20c3a1b7c88c0 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 12 Dec 2014 17:57:38 +0200 Subject: [PATCH 0191/3023] drm/i915: fix use after free during eDP encoder destroying MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After commit a18c0af171bfb875012da26f23df051004726973 uthor: Thierry Reding Date: Wed Dec 10 11:38:49 2014 +0100 drm: Zero out DRM object memory upon cleanup we will use the eDP encoder during destroying it. Fix this by calling drm_encoder_cleanup() at a point when the encoder is not used any more. This caused a NULL pointer dereference in pps_lock(), I can't see that it caused any other problem. All the other encoders seem to call drm_encoder_cleanup() at a safe place. Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Reviewed-by: Thierry Reding Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 8e276c41d4d259..8b31e01b054b74 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4310,7 +4310,6 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder) drm_dp_aux_unregister(&intel_dp->aux); intel_dp_mst_encoder_cleanup(intel_dig_port); - drm_encoder_cleanup(encoder); if (is_edp(intel_dp)) { cancel_delayed_work_sync(&intel_dp->panel_vdd_work); /* @@ -4326,6 +4325,7 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder) intel_dp->edp_notifier.notifier_call = NULL; } } + drm_encoder_cleanup(encoder); kfree(intel_dig_port); } From 493018dcb1c7a17f2a811db41522a3a5350304fe Mon Sep 17 00:00:00 2001 From: Brad Volkin Date: Thu, 11 Dec 2014 12:13:08 -0800 Subject: [PATCH 0192/3023] drm/i915: Implement a framework for batch buffer pools This adds a small module for managing a pool of batch buffers. The only current use case is for the command parser, as described in the kerneldoc in the patch. The code is simple, but separating it out makes it easier to change the underlying algorithms and to extend to future use cases should they arise. The interface is simple: init to create an empty pool, fini to clean it up, get to obtain a new buffer. Note that all buffers are expected to be inactive before cleaning up the pool. Locking is currently based on the caller holding the struct_mutex. We already do that in the places where we will use the batch pool for the command parser. v2: - s/BUG_ON/WARN_ON/ for locking assertions - Remove the cap on pool size - Switch from alloc/free to init/fini v3: - Idiomatic looping structure in _fini - Correct handling of purged objects - Don't return a buffer that's too much larger than needed v4: - Rebased to latest -nightly v5: - Remove _put() function and clean up comments to match v6: - Move purged check inside the loop (danvet, from v4 1/7 feedback) v7: - Use single list instead of two. (Chris W) - s/active_list/cache_list - Squashed in debug patches (Chris W) drm/i915: Add a batch pool debugfs file It provides some useful information about the buffers in the global command parser batch pool. v2: rebase on global pool instead of per-ring pools v3: rebase drm/i915: Add batch pool details to i915_gem_objects debugfs To better account for the potentially large memory consumption of the batch pool. v8: - Keep cache in LRU order (danvet, from v6 1/5 feedback) Issue: VIZ-4719 Signed-off-by: Brad Volkin Reviewed-By: Jon Bloomfield Signed-off-by: Daniel Vetter --- Documentation/DocBook/drm.tmpl | 5 + drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/i915_debugfs.c | 71 +++++++++-- drivers/gpu/drm/i915/i915_drv.h | 21 ++++ drivers/gpu/drm/i915/i915_gem.c | 1 + drivers/gpu/drm/i915/i915_gem_batch_pool.c | 135 +++++++++++++++++++++ 6 files changed, 225 insertions(+), 9 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_gem_batch_pool.c diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index f931b3decccdbf..bd1456ad846014 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -4032,6 +4032,11 @@ int num_ioctls; Batchbuffer Parsing !Pdrivers/gpu/drm/i915/i915_cmd_parser.c batch buffer command parser !Idrivers/gpu/drm/i915/i915_cmd_parser.c + + + Batchbuffer Pools +!Pdrivers/gpu/drm/i915/i915_gem_batch_pool.c batch pool +!Idrivers/gpu/drm/i915/i915_gem_batch_pool.c Logical Rings, Logical Ring Contexts and Execlists diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 3cf70a61b44f39..1849ffae61aec7 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -19,6 +19,7 @@ i915-$(CONFIG_DEBUG_FS) += i915_debugfs.o # GEM code i915-y += i915_cmd_parser.o \ + i915_gem_batch_pool.o \ i915_gem_context.o \ i915_gem_render_state.o \ i915_gem_debug.o \ diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 8d2988ae3c4600..e515aad478585b 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -360,6 +360,33 @@ static int per_file_stats(int id, void *ptr, void *data) return 0; } +#define print_file_stats(m, name, stats) \ + seq_printf(m, "%s: %u objects, %zu bytes (%zu active, %zu inactive, %zu global, %zu shared, %zu unbound)\n", \ + name, \ + stats.count, \ + stats.total, \ + stats.active, \ + stats.inactive, \ + stats.global, \ + stats.shared, \ + stats.unbound) + +static void print_batch_pool_stats(struct seq_file *m, + struct drm_i915_private *dev_priv) +{ + struct drm_i915_gem_object *obj; + struct file_stats stats; + + memset(&stats, 0, sizeof(stats)); + + list_for_each_entry(obj, + &dev_priv->mm.batch_pool.cache_list, + batch_pool_list) + per_file_stats(0, obj, &stats); + + print_file_stats(m, "batch pool", stats); +} + #define count_vmas(list, member) do { \ list_for_each_entry(vma, list, member) { \ size += i915_gem_obj_ggtt_size(vma->obj); \ @@ -441,6 +468,9 @@ static int i915_gem_object_info(struct seq_file *m, void* data) dev_priv->gtt.base.total, dev_priv->gtt.mappable_end - dev_priv->gtt.base.start); + seq_putc(m, '\n'); + print_batch_pool_stats(m, dev_priv); + seq_putc(m, '\n'); list_for_each_entry_reverse(file, &dev->filelist, lhead) { struct file_stats stats; @@ -459,15 +489,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data) */ rcu_read_lock(); task = pid_task(file->pid, PIDTYPE_PID); - seq_printf(m, "%s: %u objects, %zu bytes (%zu active, %zu inactive, %zu global, %zu shared, %zu unbound)\n", - task ? task->comm : "", - stats.count, - stats.total, - stats.active, - stats.inactive, - stats.global, - stats.shared, - stats.unbound); + print_file_stats(m, task ? task->comm : "", stats); rcu_read_unlock(); } @@ -584,6 +606,36 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data) return 0; } +static int i915_gem_batch_pool_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = m->private; + struct drm_device *dev = node->minor->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj; + int count = 0; + int ret; + + ret = mutex_lock_interruptible(&dev->struct_mutex); + if (ret) + return ret; + + seq_puts(m, "cache:\n"); + list_for_each_entry(obj, + &dev_priv->mm.batch_pool.cache_list, + batch_pool_list) { + seq_puts(m, " "); + describe_obj(m, obj); + seq_putc(m, '\n'); + count++; + } + + seq_printf(m, "total: %d\n", count); + + mutex_unlock(&dev->struct_mutex); + + return 0; +} + static int i915_gem_request_info(struct seq_file *m, void *data) { struct drm_info_node *node = m->private; @@ -4357,6 +4409,7 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_gem_hws_blt", i915_hws_info, 0, (void *)BCS}, {"i915_gem_hws_bsd", i915_hws_info, 0, (void *)VCS}, {"i915_gem_hws_vebox", i915_hws_info, 0, (void *)VECS}, + {"i915_gem_batch_pool", i915_gem_batch_pool_info, 0}, {"i915_frequency_info", i915_frequency_info, 0}, {"i915_drpc_info", i915_drpc_info, 0}, {"i915_emon_status", i915_emon_status, 0}, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 104c288f1e6809..6490fef7c84709 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1141,6 +1141,11 @@ struct intel_l3_parity { int which_slice; }; +struct i915_gem_batch_pool { + struct drm_device *dev; + struct list_head cache_list; +}; + struct i915_gem_mm { /** Memory allocator for GTT stolen memory */ struct drm_mm stolen; @@ -1154,6 +1159,13 @@ struct i915_gem_mm { */ struct list_head unbound_list; + /* + * A pool of objects to use as shadow copies of client batch buffers + * when the command parser is enabled. Prevents the client from + * modifying the batch contents after software parsing. + */ + struct i915_gem_batch_pool batch_pool; + /** Usable portion of the GTT for GEM */ unsigned long stolen_base; /* limited to low memory (32-bit) */ @@ -1885,6 +1897,8 @@ struct drm_i915_gem_object { /** Used in execbuf to temporarily hold a ref */ struct list_head obj_exec_link; + struct list_head batch_pool_list; + /** * This is set if the object is on the active lists (has pending * rendering and so a non-zero seqno), and is not set if it i s on @@ -2935,6 +2949,13 @@ void i915_destroy_error_state(struct drm_device *dev); void i915_get_extra_instdone(struct drm_device *dev, uint32_t *instdone); const char *i915_cache_level_str(struct drm_i915_private *i915, int type); +/* i915_gem_batch_pool.c */ +void i915_gem_batch_pool_init(struct drm_device *dev, + struct i915_gem_batch_pool *pool); +void i915_gem_batch_pool_fini(struct i915_gem_batch_pool *pool); +struct drm_i915_gem_object* +i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, size_t size); + /* i915_cmd_parser.c */ int i915_cmd_parser_get_version(void); int i915_cmd_parser_init_ring(struct intel_engine_cs *ring); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c26d4ccd183afa..b100cec93a5839 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4393,6 +4393,7 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj, INIT_LIST_HEAD(&obj->ring_list); INIT_LIST_HEAD(&obj->obj_exec_link); INIT_LIST_HEAD(&obj->vma_list); + INIT_LIST_HEAD(&obj->batch_pool_list); obj->ops = ops; diff --git a/drivers/gpu/drm/i915/i915_gem_batch_pool.c b/drivers/gpu/drm/i915/i915_gem_batch_pool.c new file mode 100644 index 00000000000000..6016125a4d1ec6 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_gem_batch_pool.c @@ -0,0 +1,135 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include "i915_drv.h" + +/** + * DOC: batch pool + * + * In order to submit batch buffers as 'secure', the software command parser + * must ensure that a batch buffer cannot be modified after parsing. It does + * this by copying the user provided batch buffer contents to a kernel owned + * buffer from which the hardware will actually execute, and by carefully + * managing the address space bindings for such buffers. + * + * The batch pool framework provides a mechanism for the driver to manage a + * set of scratch buffers to use for this purpose. The framework can be + * extended to support other uses cases should they arise. + */ + +/** + * i915_gem_batch_pool_init() - initialize a batch buffer pool + * @dev: the drm device + * @pool: the batch buffer pool + */ +void i915_gem_batch_pool_init(struct drm_device *dev, + struct i915_gem_batch_pool *pool) +{ + pool->dev = dev; + INIT_LIST_HEAD(&pool->cache_list); +} + +/** + * i915_gem_batch_pool_fini() - clean up a batch buffer pool + * @pool: the pool to clean up + * + * Note: Callers must hold the struct_mutex. + */ +void i915_gem_batch_pool_fini(struct i915_gem_batch_pool *pool) +{ + WARN_ON(!mutex_is_locked(&pool->dev->struct_mutex)); + + while (!list_empty(&pool->cache_list)) { + struct drm_i915_gem_object *obj = + list_first_entry(&pool->cache_list, + struct drm_i915_gem_object, + batch_pool_list); + + WARN_ON(obj->active); + + list_del_init(&obj->batch_pool_list); + drm_gem_object_unreference(&obj->base); + } +} + +/** + * i915_gem_batch_pool_get() - select a buffer from the pool + * @pool: the batch buffer pool + * @size: the minimum desired size of the returned buffer + * + * Finds or allocates a batch buffer in the pool with at least the requested + * size. The caller is responsible for any domain, active/inactive, or + * purgeability management for the returned buffer. + * + * Note: Callers must hold the struct_mutex + * + * Return: the selected batch buffer object + */ +struct drm_i915_gem_object * +i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, + size_t size) +{ + struct drm_i915_gem_object *obj = NULL; + struct drm_i915_gem_object *tmp, *next; + + WARN_ON(!mutex_is_locked(&pool->dev->struct_mutex)); + + list_for_each_entry_safe(tmp, next, + &pool->cache_list, batch_pool_list) { + + if (tmp->active) + continue; + + /* While we're looping, do some clean up */ + if (tmp->madv == __I915_MADV_PURGED) { + list_del(&tmp->batch_pool_list); + drm_gem_object_unreference(&tmp->base); + continue; + } + + /* + * Select a buffer that is at least as big as needed + * but not 'too much' bigger. A better way to do this + * might be to bucket the pool objects based on size. + */ + if (tmp->base.size >= size && + tmp->base.size <= (2 * size)) { + obj = tmp; + break; + } + } + + if (!obj) { + obj = i915_gem_alloc_object(pool->dev, size); + if (!obj) + return ERR_PTR(-ENOMEM); + + list_add_tail(&obj->batch_pool_list, &pool->cache_list); + } + else + /* Keep list in LRU order */ + list_move_tail(&obj->batch_pool_list, &pool->cache_list); + + return obj; +} From 78a423772d08eb5a048765a883b5b5a308ea0d0f Mon Sep 17 00:00:00 2001 From: Brad Volkin Date: Thu, 11 Dec 2014 12:13:09 -0800 Subject: [PATCH 0193/3023] drm/i915: Use batch pools with the command parser This patch sets up all of the tracking and copying necessary to use batch pools with the command parser and dispatches the copied (shadow) batch to the hardware. After this patch, the parser is in 'enabling' mode. Note that performance takes a hit from the copy in some cases and will likely need some work. At a rough pass, the memcpy appears to be the bottleneck. Without having done a deeper analysis, two ideas that come to mind are: 1) Copy sections of the batch at a time, as they are reached by parsing. Might improve cache locality. 2) Copy only up to the userspace-supplied batch length and memset the rest of the buffer. Reduces the number of reads. v2: - Remove setting the capacity of the pool - One global pool instead of per-ring pools - Replace batch_obj with shadow_batch_obj and hook into eb->vmas - Memset any space in the shadow batch beyond what gets copied - Rebased on execlist prep refactoring v3: - Rebase on chained batch handling - Squash in setting the secure dispatch flag - Add a note about the interaction w/secure dispatch pinning - Check for request->batch_obj == NULL in i915_gem_free_request v4: - Fix read domains for shadow_batch_obj - Remove the set_to_gtt_domain call from i915_parse_cmds - ggtt_pin/unpin in the parser block to simplify error handling - Check USES_FULL_PPGTT before setting DISPATCH_SECURE flag - Remove i915_gem_batch_pool_put calls v5: - Move 'pending_read_domains |= I915_GEM_DOMAIN_COMMAND' after the parser (danvet, from v4 0/7 feedback) Issue: VIZ-4719 Signed-off-by: Brad Volkin Reviewed-By: Jon Bloomfield Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_cmd_parser.c | 79 +++++++++++++++++----- drivers/gpu/drm/i915/i915_dma.c | 1 + drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem.c | 2 + drivers/gpu/drm/i915/i915_gem_execbuffer.c | 52 ++++++++++++-- 5 files changed, 112 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index b882bf2a238828..2a4ccac66b5aae 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -848,6 +848,56 @@ static u32 *vmap_batch(struct drm_i915_gem_object *obj) return (u32*)addr; } +/* Returns a vmap'd pointer to dest_obj, which the caller must unmap */ +static u32 *copy_batch(struct drm_i915_gem_object *dest_obj, + struct drm_i915_gem_object *src_obj) +{ + int ret = 0; + int needs_clflush = 0; + u32 *src_addr, *dest_addr = NULL; + + ret = i915_gem_obj_prepare_shmem_read(src_obj, &needs_clflush); + if (ret) { + DRM_DEBUG_DRIVER("CMD: failed to prep read\n"); + return ERR_PTR(ret); + } + + src_addr = vmap_batch(src_obj); + if (!src_addr) { + DRM_DEBUG_DRIVER("CMD: Failed to vmap batch\n"); + ret = -ENOMEM; + goto unpin_src; + } + + if (needs_clflush) + drm_clflush_virt_range((char *)src_addr, src_obj->base.size); + + ret = i915_gem_object_set_to_cpu_domain(dest_obj, true); + if (ret) { + DRM_DEBUG_DRIVER("CMD: Failed to set batch CPU domain\n"); + goto unmap_src; + } + + dest_addr = vmap_batch(dest_obj); + if (!dest_addr) { + DRM_DEBUG_DRIVER("CMD: Failed to vmap shadow batch\n"); + ret = -ENOMEM; + goto unmap_src; + } + + memcpy(dest_addr, src_addr, src_obj->base.size); + if (dest_obj->base.size > src_obj->base.size) + memset((u8 *)dest_addr + src_obj->base.size, 0, + dest_obj->base.size - src_obj->base.size); + +unmap_src: + vunmap(src_addr); +unpin_src: + i915_gem_object_unpin_pages(src_obj); + + return ret ? ERR_PTR(ret) : dest_addr; +} + /** * i915_needs_cmd_parser() - should a given ring use software command parsing? * @ring: the ring in question @@ -964,6 +1014,7 @@ static bool check_cmd(const struct intel_engine_cs *ring, * i915_parse_cmds() - parse a submitted batch buffer for privilege violations * @ring: the ring on which the batch is to execute * @batch_obj: the batch buffer in question + * @shadow_batch_obj: copy of the batch buffer in question * @batch_start_offset: byte offset in the batch at which execution starts * @is_master: is the submitting process the drm master? * @@ -975,32 +1026,28 @@ static bool check_cmd(const struct intel_engine_cs *ring, */ int i915_parse_cmds(struct intel_engine_cs *ring, struct drm_i915_gem_object *batch_obj, + struct drm_i915_gem_object *shadow_batch_obj, u32 batch_start_offset, bool is_master) { int ret = 0; u32 *cmd, *batch_base, *batch_end; struct drm_i915_cmd_descriptor default_desc = { 0 }; - int needs_clflush = 0; bool oacontrol_set = false; /* OACONTROL tracking. See check_cmd() */ - ret = i915_gem_obj_prepare_shmem_read(batch_obj, &needs_clflush); - if (ret) { - DRM_DEBUG_DRIVER("CMD: failed to prep read\n"); - return ret; + batch_base = copy_batch(shadow_batch_obj, batch_obj); + if (IS_ERR(batch_base)) { + DRM_DEBUG_DRIVER("CMD: Failed to copy batch\n"); + return PTR_ERR(batch_base); } - batch_base = vmap_batch(batch_obj); - if (!batch_base) { - DRM_DEBUG_DRIVER("CMD: Failed to vmap batch\n"); - i915_gem_object_unpin_pages(batch_obj); - return -ENOMEM; - } - - if (needs_clflush) - drm_clflush_virt_range((char *)batch_base, batch_obj->base.size); - cmd = batch_base + (batch_start_offset / sizeof(*cmd)); + + /* + * We use the source object's size because the shadow object is as + * large or larger and copy_batch() will write MI_NOPs to the extra + * space. Parsing should be faster in some cases this way. + */ batch_end = cmd + (batch_obj->base.size / sizeof(*batch_end)); while (cmd < batch_end) { @@ -1062,8 +1109,6 @@ int i915_parse_cmds(struct intel_engine_cs *ring, vunmap(batch_base); - i915_gem_object_unpin_pages(batch_obj); - return ret; } diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 887d88f4c68829..52730ed863855f 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -928,6 +928,7 @@ int i915_driver_unload(struct drm_device *dev) mutex_lock(&dev->struct_mutex); i915_gem_cleanup_ringbuffer(dev); + i915_gem_batch_pool_fini(&dev_priv->mm.batch_pool); i915_gem_context_fini(dev); mutex_unlock(&dev->struct_mutex); i915_gem_cleanup_stolen(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6490fef7c84709..25832e507d5555 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2963,6 +2963,7 @@ void i915_cmd_parser_fini_ring(struct intel_engine_cs *ring); bool i915_needs_cmd_parser(struct intel_engine_cs *ring); int i915_parse_cmds(struct intel_engine_cs *ring, struct drm_i915_gem_object *batch_obj, + struct drm_i915_gem_object *shadow_batch_obj, u32 batch_start_offset, bool is_master); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index b100cec93a5839..a7bf31a041f43d 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -5007,6 +5007,8 @@ i915_gem_load(struct drm_device *dev) dev_priv->mm.oom_notifier.notifier_call = i915_gem_shrinker_oom; register_oom_notifier(&dev_priv->mm.oom_notifier); + i915_gem_batch_pool_init(dev, &dev_priv->mm.batch_pool); + mutex_init(&dev_priv->fb_tracking.lock); } diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 3927d931ad730d..cadb04d964e034 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1283,6 +1283,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, struct drm_i915_private *dev_priv = dev->dev_private; struct eb_vmas *eb; struct drm_i915_gem_object *batch_obj; + struct drm_i915_gem_object *shadow_batch_obj = NULL; + struct drm_i915_gem_exec_object2 shadow_exec_entry; struct intel_engine_cs *ring; struct intel_context *ctx; struct i915_address_space *vm; @@ -1399,28 +1401,66 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, ret = -EINVAL; goto err; } - batch_obj->base.pending_read_domains |= I915_GEM_DOMAIN_COMMAND; if (i915_needs_cmd_parser(ring)) { + shadow_batch_obj = + i915_gem_batch_pool_get(&dev_priv->mm.batch_pool, + batch_obj->base.size); + if (IS_ERR(shadow_batch_obj)) { + ret = PTR_ERR(shadow_batch_obj); + /* Don't try to clean up the obj in the error path */ + shadow_batch_obj = NULL; + goto err; + } + + ret = i915_gem_obj_ggtt_pin(shadow_batch_obj, 4096, 0); + if (ret) + goto err; + ret = i915_parse_cmds(ring, batch_obj, + shadow_batch_obj, args->batch_start_offset, file->is_master); + i915_gem_object_ggtt_unpin(shadow_batch_obj); + if (ret) { if (ret != -EACCES) goto err; } else { + struct i915_vma *vma; + + memset(&shadow_exec_entry, 0, + sizeof(shadow_exec_entry)); + + vma = i915_gem_obj_to_ggtt(shadow_batch_obj); + vma->exec_entry = &shadow_exec_entry; + drm_gem_object_reference(&shadow_batch_obj->base); + list_add_tail(&vma->exec_list, &eb->vmas); + + shadow_batch_obj->base.pending_read_domains = + batch_obj->base.pending_read_domains; + + batch_obj = shadow_batch_obj; + /* - * XXX: Actually do this when enabling batch copy... + * Set the DISPATCH_SECURE bit to remove the NON_SECURE + * bit from MI_BATCH_BUFFER_START commands issued in the + * dispatch_execbuffer implementations. We specifically + * don't want that set when the command parser is + * enabled. * - * Set the DISPATCH_SECURE bit to remove the NON_SECURE bit - * from MI_BATCH_BUFFER_START commands issued in the - * dispatch_execbuffer implementations. We specifically don't - * want that set when the command parser is enabled. + * FIXME: with aliasing ppgtt, buffers that should only + * be in ggtt still end up in the aliasing ppgtt. remove + * this check when that is fixed. */ + if (USES_FULL_PPGTT(dev)) + flags |= I915_DISPATCH_SECURE; } } + batch_obj->base.pending_read_domains |= I915_GEM_DOMAIN_COMMAND; + /* snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure * batch" bit. Hence we need to pin secure batches into the global gtt. * hsw should have this fixed, but bdw mucks it up again. */ From b9ffd80ed659c559152c042e74741f4f60cac691 Mon Sep 17 00:00:00 2001 From: Brad Volkin Date: Thu, 11 Dec 2014 12:13:10 -0800 Subject: [PATCH 0194/3023] drm/i915: Use batch length instead of object size in command parser Previously we couldn't trust the user-supplied batch length because it came directly from userspace (i.e. untrusted code). It would have affected what commands software parsed without regard to what hardware would actually execute, leaving a potential hole. With the parser now copying the user supplied batch buffer and writing MI_NOP commands to any space after the copied region, we can safely use the batch length input. This should be a performance win as the actual batch length is frequently much smaller than the allocated object size. v2: Fix handling of non-zero batch_start_offset Issue: VIZ-4719 Signed-off-by: Brad Volkin Reviewed-By: Jon Bloomfield Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_cmd_parser.c | 48 ++++++++++++++-------- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem_execbuffer.c | 1 + 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 2a4ccac66b5aae..a698b47df33126 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -850,11 +850,19 @@ static u32 *vmap_batch(struct drm_i915_gem_object *obj) /* Returns a vmap'd pointer to dest_obj, which the caller must unmap */ static u32 *copy_batch(struct drm_i915_gem_object *dest_obj, - struct drm_i915_gem_object *src_obj) + struct drm_i915_gem_object *src_obj, + u32 batch_start_offset, + u32 batch_len) { int ret = 0; int needs_clflush = 0; - u32 *src_addr, *dest_addr = NULL; + u32 *src_base, *dest_base = NULL; + u32 *src_addr, *dest_addr; + u32 offset = batch_start_offset / sizeof(*dest_addr); + u32 end = batch_start_offset + batch_len; + + if (end > dest_obj->base.size || end > src_obj->base.size) + return ERR_PTR(-E2BIG); ret = i915_gem_obj_prepare_shmem_read(src_obj, &needs_clflush); if (ret) { @@ -862,15 +870,17 @@ static u32 *copy_batch(struct drm_i915_gem_object *dest_obj, return ERR_PTR(ret); } - src_addr = vmap_batch(src_obj); - if (!src_addr) { + src_base = vmap_batch(src_obj); + if (!src_base) { DRM_DEBUG_DRIVER("CMD: Failed to vmap batch\n"); ret = -ENOMEM; goto unpin_src; } + src_addr = src_base + offset; + if (needs_clflush) - drm_clflush_virt_range((char *)src_addr, src_obj->base.size); + drm_clflush_virt_range((char *)src_addr, batch_len); ret = i915_gem_object_set_to_cpu_domain(dest_obj, true); if (ret) { @@ -878,24 +888,27 @@ static u32 *copy_batch(struct drm_i915_gem_object *dest_obj, goto unmap_src; } - dest_addr = vmap_batch(dest_obj); - if (!dest_addr) { + dest_base = vmap_batch(dest_obj); + if (!dest_base) { DRM_DEBUG_DRIVER("CMD: Failed to vmap shadow batch\n"); ret = -ENOMEM; goto unmap_src; } - memcpy(dest_addr, src_addr, src_obj->base.size); - if (dest_obj->base.size > src_obj->base.size) - memset((u8 *)dest_addr + src_obj->base.size, 0, - dest_obj->base.size - src_obj->base.size); + dest_addr = dest_base + offset; + + if (batch_start_offset != 0) + memset((u8 *)dest_base, 0, batch_start_offset); + + memcpy(dest_addr, src_addr, batch_len); + memset((u8 *)dest_addr + batch_len, 0, dest_obj->base.size - end); unmap_src: - vunmap(src_addr); + vunmap(src_base); unpin_src: i915_gem_object_unpin_pages(src_obj); - return ret ? ERR_PTR(ret) : dest_addr; + return ret ? ERR_PTR(ret) : dest_base; } /** @@ -1016,6 +1029,7 @@ static bool check_cmd(const struct intel_engine_cs *ring, * @batch_obj: the batch buffer in question * @shadow_batch_obj: copy of the batch buffer in question * @batch_start_offset: byte offset in the batch at which execution starts + * @batch_len: length of the commands in batch_obj * @is_master: is the submitting process the drm master? * * Parses the specified batch buffer looking for privilege violations as @@ -1028,6 +1042,7 @@ int i915_parse_cmds(struct intel_engine_cs *ring, struct drm_i915_gem_object *batch_obj, struct drm_i915_gem_object *shadow_batch_obj, u32 batch_start_offset, + u32 batch_len, bool is_master) { int ret = 0; @@ -1035,7 +1050,8 @@ int i915_parse_cmds(struct intel_engine_cs *ring, struct drm_i915_cmd_descriptor default_desc = { 0 }; bool oacontrol_set = false; /* OACONTROL tracking. See check_cmd() */ - batch_base = copy_batch(shadow_batch_obj, batch_obj); + batch_base = copy_batch(shadow_batch_obj, batch_obj, + batch_start_offset, batch_len); if (IS_ERR(batch_base)) { DRM_DEBUG_DRIVER("CMD: Failed to copy batch\n"); return PTR_ERR(batch_base); @@ -1044,11 +1060,11 @@ int i915_parse_cmds(struct intel_engine_cs *ring, cmd = batch_base + (batch_start_offset / sizeof(*cmd)); /* - * We use the source object's size because the shadow object is as + * We use the batch length as size because the shadow object is as * large or larger and copy_batch() will write MI_NOPs to the extra * space. Parsing should be faster in some cases this way. */ - batch_end = cmd + (batch_obj->base.size / sizeof(*batch_end)); + batch_end = cmd + (batch_len / sizeof(*batch_end)); while (cmd < batch_end) { const struct drm_i915_cmd_descriptor *desc; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 25832e507d5555..eb4d64fecf8ab2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2965,6 +2965,7 @@ int i915_parse_cmds(struct intel_engine_cs *ring, struct drm_i915_gem_object *batch_obj, struct drm_i915_gem_object *shadow_batch_obj, u32 batch_start_offset, + u32 batch_len, bool is_master); /* i915_suspend.c */ diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index cadb04d964e034..5973e2005e894c 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1421,6 +1421,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, batch_obj, shadow_batch_obj, args->batch_start_offset, + args->batch_len, file->is_master); i915_gem_object_ggtt_unpin(shadow_batch_obj); From 0079a7df3a47bfd0b64dc6e6ef47a651263760dc Mon Sep 17 00:00:00 2001 From: Brad Volkin Date: Thu, 11 Dec 2014 12:13:11 -0800 Subject: [PATCH 0195/3023] drm/i915: Mark shadow batch buffers as purgeable By adding a new exec_entry flag, we cleanly mark the shadow objects as purgeable after they are on the active list. v2: - Move 'shadow_batch_obj->madv = I915_MADV_WILLNEED' inside _get fnc (danvet, from v4 6/7 feedback) v3: - Remove duplicate 'madv = I915_MADV_WILLNEED' (danvet, from v6 4/5) Issue: VIZ-4719 Signed-off-by: Brad Volkin Reviewed-By: Jon Bloomfield Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_batch_pool.c | 2 ++ drivers/gpu/drm/i915/i915_gem_execbuffer.c | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_batch_pool.c b/drivers/gpu/drm/i915/i915_gem_batch_pool.c index 6016125a4d1ec6..c690170a1c4fba 100644 --- a/drivers/gpu/drm/i915/i915_gem_batch_pool.c +++ b/drivers/gpu/drm/i915/i915_gem_batch_pool.c @@ -131,5 +131,7 @@ i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, /* Keep list in LRU order */ list_move_tail(&obj->batch_pool_list, &pool->cache_list); + obj->madv = I915_MADV_WILLNEED; + return obj; } diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 5973e2005e894c..86de3720527bcb 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -37,6 +37,7 @@ #define __EXEC_OBJECT_HAS_FENCE (1<<30) #define __EXEC_OBJECT_NEEDS_MAP (1<<29) #define __EXEC_OBJECT_NEEDS_BIAS (1<<28) +#define __EXEC_OBJECT_PURGEABLE (1<<27) #define BATCH_OFFSET_BIAS (256*1024) @@ -226,7 +227,12 @@ i915_gem_execbuffer_unreserve_vma(struct i915_vma *vma) if (entry->flags & __EXEC_OBJECT_HAS_PIN) vma->pin_count--; - entry->flags &= ~(__EXEC_OBJECT_HAS_FENCE | __EXEC_OBJECT_HAS_PIN); + if (entry->flags & __EXEC_OBJECT_PURGEABLE) + obj->madv = I915_MADV_DONTNEED; + + entry->flags &= ~(__EXEC_OBJECT_HAS_FENCE | + __EXEC_OBJECT_HAS_PIN | + __EXEC_OBJECT_PURGEABLE); } static void eb_destroy(struct eb_vmas *eb) @@ -1436,6 +1442,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, vma = i915_gem_obj_to_ggtt(shadow_batch_obj); vma->exec_entry = &shadow_exec_entry; + vma->exec_entry->flags = __EXEC_OBJECT_PURGEABLE; drm_gem_object_reference(&shadow_batch_obj->base); list_add_tail(&vma->exec_list, &eb->vmas); From 7174537627836119e8b960afcc7139a138e02802 Mon Sep 17 00:00:00 2001 From: Brad Volkin Date: Thu, 11 Dec 2014 12:13:12 -0800 Subject: [PATCH 0196/3023] drm/i915: Tidy up execbuffer command parsing code Move it to a separate function since the main do_execbuffer function already has so much going on. v2: - Move pin/unpin calls inside i915_parse_cmds() (Chris W, v4 7/7 feedback) Issue: VIZ-4719 Signed-off-by: Brad Volkin Reviewed-By: Jon Bloomfield Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_cmd_parser.c | 8 ++ drivers/gpu/drm/i915/i915_gem_execbuffer.c | 124 ++++++++++++--------- 2 files changed, 77 insertions(+), 55 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index a698b47df33126..0d757cd313b562 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -1050,10 +1050,17 @@ int i915_parse_cmds(struct intel_engine_cs *ring, struct drm_i915_cmd_descriptor default_desc = { 0 }; bool oacontrol_set = false; /* OACONTROL tracking. See check_cmd() */ + ret = i915_gem_obj_ggtt_pin(shadow_batch_obj, 4096, 0); + if (ret) { + DRM_DEBUG_DRIVER("CMD: Failed to pin shadow batch\n"); + return -1; + } + batch_base = copy_batch(shadow_batch_obj, batch_obj, batch_start_offset, batch_len); if (IS_ERR(batch_base)) { DRM_DEBUG_DRIVER("CMD: Failed to copy batch\n"); + i915_gem_object_ggtt_unpin(shadow_batch_obj); return PTR_ERR(batch_base); } @@ -1124,6 +1131,7 @@ int i915_parse_cmds(struct intel_engine_cs *ring, } vunmap(batch_base); + i915_gem_object_ggtt_unpin(shadow_batch_obj); return ret; } diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 86de3720527bcb..8330660af978e5 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1072,6 +1072,65 @@ i915_emit_box(struct intel_engine_cs *ring, return 0; } +static struct drm_i915_gem_object* +i915_gem_execbuffer_parse(struct intel_engine_cs *ring, + struct drm_i915_gem_exec_object2 *shadow_exec_entry, + struct eb_vmas *eb, + struct drm_i915_gem_object *batch_obj, + u32 batch_start_offset, + u32 batch_len, + bool is_master, + u32 *flags) +{ + struct drm_i915_private *dev_priv = to_i915(batch_obj->base.dev); + struct drm_i915_gem_object *shadow_batch_obj; + int ret; + + shadow_batch_obj = i915_gem_batch_pool_get(&dev_priv->mm.batch_pool, + batch_obj->base.size); + if (IS_ERR(shadow_batch_obj)) + return shadow_batch_obj; + + ret = i915_parse_cmds(ring, + batch_obj, + shadow_batch_obj, + batch_start_offset, + batch_len, + is_master); + if (ret) { + if (ret == -EACCES) + return batch_obj; + } else { + struct i915_vma *vma; + + memset(shadow_exec_entry, 0, sizeof(*shadow_exec_entry)); + + vma = i915_gem_obj_to_ggtt(shadow_batch_obj); + vma->exec_entry = shadow_exec_entry; + vma->exec_entry->flags = __EXEC_OBJECT_PURGEABLE; + drm_gem_object_reference(&shadow_batch_obj->base); + list_add_tail(&vma->exec_list, &eb->vmas); + + shadow_batch_obj->base.pending_read_domains = + batch_obj->base.pending_read_domains; + + /* + * Set the DISPATCH_SECURE bit to remove the NON_SECURE + * bit from MI_BATCH_BUFFER_START commands issued in the + * dispatch_execbuffer implementations. We specifically + * don't want that set when the command parser is + * enabled. + * + * FIXME: with aliasing ppgtt, buffers that should only + * be in ggtt still end up in the aliasing ppgtt. remove + * this check when that is fixed. + */ + if (USES_FULL_PPGTT(dev)) + *flags |= I915_DISPATCH_SECURE; + } + + return ret ? ERR_PTR(ret) : shadow_batch_obj; +} int i915_gem_ringbuffer_submission(struct drm_device *dev, struct drm_file *file, @@ -1289,7 +1348,6 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, struct drm_i915_private *dev_priv = dev->dev_private; struct eb_vmas *eb; struct drm_i915_gem_object *batch_obj; - struct drm_i915_gem_object *shadow_batch_obj = NULL; struct drm_i915_gem_exec_object2 shadow_exec_entry; struct intel_engine_cs *ring; struct intel_context *ctx; @@ -1409,62 +1467,18 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, } if (i915_needs_cmd_parser(ring)) { - shadow_batch_obj = - i915_gem_batch_pool_get(&dev_priv->mm.batch_pool, - batch_obj->base.size); - if (IS_ERR(shadow_batch_obj)) { - ret = PTR_ERR(shadow_batch_obj); - /* Don't try to clean up the obj in the error path */ - shadow_batch_obj = NULL; + batch_obj = i915_gem_execbuffer_parse(ring, + &shadow_exec_entry, + eb, + batch_obj, + args->batch_start_offset, + args->batch_len, + file->is_master, + &flags); + if (IS_ERR(batch_obj)) { + ret = PTR_ERR(batch_obj); goto err; } - - ret = i915_gem_obj_ggtt_pin(shadow_batch_obj, 4096, 0); - if (ret) - goto err; - - ret = i915_parse_cmds(ring, - batch_obj, - shadow_batch_obj, - args->batch_start_offset, - args->batch_len, - file->is_master); - i915_gem_object_ggtt_unpin(shadow_batch_obj); - - if (ret) { - if (ret != -EACCES) - goto err; - } else { - struct i915_vma *vma; - - memset(&shadow_exec_entry, 0, - sizeof(shadow_exec_entry)); - - vma = i915_gem_obj_to_ggtt(shadow_batch_obj); - vma->exec_entry = &shadow_exec_entry; - vma->exec_entry->flags = __EXEC_OBJECT_PURGEABLE; - drm_gem_object_reference(&shadow_batch_obj->base); - list_add_tail(&vma->exec_list, &eb->vmas); - - shadow_batch_obj->base.pending_read_domains = - batch_obj->base.pending_read_domains; - - batch_obj = shadow_batch_obj; - - /* - * Set the DISPATCH_SECURE bit to remove the NON_SECURE - * bit from MI_BATCH_BUFFER_START commands issued in the - * dispatch_execbuffer implementations. We specifically - * don't want that set when the command parser is - * enabled. - * - * FIXME: with aliasing ppgtt, buffers that should only - * be in ggtt still end up in the aliasing ppgtt. remove - * this check when that is fixed. - */ - if (USES_FULL_PPGTT(dev)) - flags |= I915_DISPATCH_SECURE; - } } batch_obj->base.pending_read_domains |= I915_GEM_DOMAIN_COMMAND; From c61200c2c7e42fa6481638b7c8c3b5dc89c60eb9 Mon Sep 17 00:00:00 2001 From: Jordan Justen Date: Thu, 11 Dec 2014 13:28:09 -0800 Subject: [PATCH 0197/3023] drm/i915: Add GPGPU_THREADS_DISPATCHED to the register whitelist This will allow us to read the number of dispatched compute threads for GL_ARB_pipeline_statistics_query. Signed-off-by: Jordan Justen Cc: Ben Widawsky Reviewed-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_cmd_parser.c | 4 +++- drivers/gpu/drm/i915/i915_reg.h | 23 ++++++++++++----------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 0d757cd313b562..806e812340d0d9 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -405,6 +405,7 @@ static const struct drm_i915_cmd_table hsw_blt_ring_cmds[] = { #define REG64(addr) (addr), (addr + sizeof(u32)) static const u32 gen7_render_regs[] = { + REG64(GPGPU_THREADS_DISPATCHED), REG64(HS_INVOCATION_COUNT), REG64(DS_INVOCATION_COUNT), REG64(IA_VERTICES_COUNT), @@ -1153,6 +1154,7 @@ int i915_cmd_parser_get_version(void) * hardware parsing enabled (so does not allow new use cases). * 2. Allow access to the MI_PREDICATE_SRC0 and * MI_PREDICATE_SRC1 registers. + * 3. Allow access to the GPGPU_THREADS_DISPATCHED register. */ - return 2; + return 3; } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 451d526ea5d548..1fdda4249bb18d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -463,17 +463,18 @@ */ #define BCS_SWCTRL 0x22200 -#define HS_INVOCATION_COUNT 0x2300 -#define DS_INVOCATION_COUNT 0x2308 -#define IA_VERTICES_COUNT 0x2310 -#define IA_PRIMITIVES_COUNT 0x2318 -#define VS_INVOCATION_COUNT 0x2320 -#define GS_INVOCATION_COUNT 0x2328 -#define GS_PRIMITIVES_COUNT 0x2330 -#define CL_INVOCATION_COUNT 0x2338 -#define CL_PRIMITIVES_COUNT 0x2340 -#define PS_INVOCATION_COUNT 0x2348 -#define PS_DEPTH_COUNT 0x2350 +#define GPGPU_THREADS_DISPATCHED 0x2290 +#define HS_INVOCATION_COUNT 0x2300 +#define DS_INVOCATION_COUNT 0x2308 +#define IA_VERTICES_COUNT 0x2310 +#define IA_PRIMITIVES_COUNT 0x2318 +#define VS_INVOCATION_COUNT 0x2320 +#define GS_INVOCATION_COUNT 0x2328 +#define GS_PRIMITIVES_COUNT 0x2330 +#define CL_INVOCATION_COUNT 0x2338 +#define CL_PRIMITIVES_COUNT 0x2340 +#define PS_INVOCATION_COUNT 0x2348 +#define PS_DEPTH_COUNT 0x2350 /* There are the 4 64-bit counter registers, one for each stream output */ #define GEN7_SO_NUM_PRIMS_WRITTEN(n) (0x5200 + (n) * 8) From 5a0afd4b78ec23f27f5d486ac3d102c2e8d66bd7 Mon Sep 17 00:00:00 2001 From: Deepak S Date: Sat, 13 Dec 2014 11:43:27 +0530 Subject: [PATCH 0198/3023] drm/i915/chv: Use timeout mode for RC6 on chv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Higher RC6 residency is observed using timeout mode instead of EI mode. It's Recommended to use TO Method for RC6. v2: Add comment about timeout threshold. (Tom) Signed-off-by: Deepak S Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8a960d19374b0a..4254e91456e1bb 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4689,7 +4689,8 @@ static void cherryview_enable_rps(struct drm_device *dev) I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10); I915_WRITE(GEN6_RC_SLEEP, 0); - I915_WRITE(GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */ + /* TO threshold set to 1750 us ( 0x557 * 1.28 us) */ + I915_WRITE(GEN6_RC6_THRESHOLD, 0x557); /* allows RC6 residency counter to work */ I915_WRITE(VLV_COUNTER_CONTROL, @@ -4703,7 +4704,7 @@ static void cherryview_enable_rps(struct drm_device *dev) /* 3: Enable RC6 */ if ((intel_enable_rc6(dev) & INTEL_RC6_ENABLE) && (pcbr >> VLV_PCBR_ADDR_SHIFT)) - rc6_mode = GEN6_RC_CTL_EI_MODE(1); + rc6_mode = GEN7_RC_CTL_TO_MODE; I915_WRITE(GEN6_RC_CONTROL, rc6_mode); From 98711167ce9e734dc0e41e158debb7f4c1269917 Mon Sep 17 00:00:00 2001 From: Deepak S Date: Fri, 12 Dec 2014 14:18:16 +0530 Subject: [PATCH 0199/3023] drm/i915: Skip gunit save/restore for cherryview MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With cherryview onwards, Gunit hardware itself save and restore all the Gunit registers. Skipping the "vlv_save_gunit_s0ix_state" & "vlv_restore_gunit_s0ix_state" for cherryview in S3/S0ix sequence. Signed-off-by: Deepak S Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 71be3c930a0ee4..95bc829184eb79 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1298,7 +1298,9 @@ static int vlv_suspend_complete(struct drm_i915_private *dev_priv) err = vlv_allow_gt_wake(dev_priv, false); if (err) goto err2; - vlv_save_gunit_s0ix_state(dev_priv); + + if (!IS_CHERRYVIEW(dev_priv->dev)) + vlv_save_gunit_s0ix_state(dev_priv); err = vlv_force_gfx_clock(dev_priv, false); if (err) @@ -1329,7 +1331,8 @@ static int vlv_resume_prepare(struct drm_i915_private *dev_priv, */ ret = vlv_force_gfx_clock(dev_priv, true); - vlv_restore_gunit_s0ix_state(dev_priv); + if (!IS_CHERRYVIEW(dev_priv->dev)) + vlv_restore_gunit_s0ix_state(dev_priv); err = vlv_allow_gt_wake(dev_priv, true); if (!ret) From 2f82bbdf3d4f1361c3d713c516d8aa390102374d Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Mon, 15 Dec 2014 14:58:00 +0000 Subject: [PATCH 0200/3023] drm/i915: Use true PPGTT in Gen8+ when execlists are enabled In Gen8+, full ppgtt needs execlist, otherwise the ctx switch can hang. Also remove the current restriction, a user should be able to explicitly set ppgtt=2. Note, this patch considers that execlist support has been enabled by default on Gen8. v2: Remove non-default restriction and clarify commit message (Daniel) Cc: Daniel Vetter Signed-off-by: Michel Thierry [danvet: s/comment/commit message/ in the commit message since that's what Michel meant as per our irc discussion.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index cc3056f2c7f4a6..75a29a3822089d 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -102,8 +102,6 @@ static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt) has_aliasing_ppgtt = INTEL_INFO(dev)->gen >= 6; has_full_ppgtt = INTEL_INFO(dev)->gen >= 7; - if (IS_GEN8(dev)) - has_full_ppgtt = false; /* XXX why? */ /* * We don't allow disabling PPGTT for gen9+ as it's a requirement for @@ -134,7 +132,10 @@ static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt) return 0; } - return has_aliasing_ppgtt ? 1 : 0; + if (INTEL_INFO(dev)->gen >= 8 && i915.enable_execlists) + return 2; + else + return has_aliasing_ppgtt ? 1 : 0; } From e6c1abb7392f548f47b03dac6179916cd87f501e Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Wed, 26 Nov 2014 14:21:02 +0000 Subject: [PATCH 0201/3023] drm/i915: Warn about missing context state workarounds only once Otherwise, new platforms without workarounds will hit this warning for every new context created. Cc: Tvrtko Ursulin Signed-off-by: Michel Thierry Reviewed-by: Tvrtko Ursulin Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 2 +- drivers/gpu/drm/i915/intel_ringbuffer.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 4dc6d4263f3d33..7670a0f0f62043 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1096,7 +1096,7 @@ static int intel_logical_ring_workarounds_emit(struct intel_engine_cs *ring, struct drm_i915_private *dev_priv = dev->dev_private; struct i915_workarounds *w = &dev_priv->workarounds; - if (WARN_ON(w->count == 0)) + if (WARN_ON_ONCE(w->count == 0)) return 0; ring->gpu_caches_dirty = true; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index f1ce16997a7959..3cad32a80108f3 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -679,7 +679,7 @@ static int intel_ring_workarounds_emit(struct intel_engine_cs *ring, struct drm_i915_private *dev_priv = dev->dev_private; struct i915_workarounds *w = &dev_priv->workarounds; - if (WARN_ON(w->count == 0)) + if (WARN_ON_ONCE(w->count == 0)) return 0; ring->gpu_caches_dirty = true; From e2c719b75c8c186deb86570d8466df9e9eff919b Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 15 Dec 2014 13:56:32 -0500 Subject: [PATCH 0202/3023] drm/i915: tame the chattermouth (v2) Many distro's have mechanism in place to collect and automatically file bugs for failed WARN()s. And since i915 has a lot of hw state sanity checks which result in WARN(), it generates quite a lot of noise which is somewhat disconcerting to the end user. Separate out the internal hw-is-in-the-state-I-expected checks into I915_STATE_WARN()s and allow configuration via i915.verbose_checks module param about whether this will generate a full blown stacktrace or just DRM_ERROR(). The new moduleparam defaults to true, so by default there is no change in behavior. And even when disabled, you will still get an error message logged. v2: paint the macro names blue, clarify that the default behavior remains the same as before Signed-off-by: Rob Clark Acked-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 30 ++++++ drivers/gpu/drm/i915/i915_params.c | 5 + drivers/gpu/drm/i915/intel_display.c | 134 ++++++++++++------------ drivers/gpu/drm/i915/intel_dp.c | 4 +- drivers/gpu/drm/i915/intel_runtime_pm.c | 2 +- 5 files changed, 105 insertions(+), 70 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index eb4d64fecf8ab2..f3185293bed1ca 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -72,6 +72,35 @@ #define MISSING_CASE(x) WARN(1, "Missing switch case (%lu) in %s\n", \ (long) (x), __func__); +/* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and + * WARN_ON()) for hw state sanity checks to check for unexpected conditions + * which may not necessarily be a user visible problem. This will either + * WARN() or DRM_ERROR() depending on the verbose_checks moduleparam, to + * enable distros and users to tailor their preferred amount of i915 abrt + * spam. + */ +#define I915_STATE_WARN(condition, format...) ({ \ + int __ret_warn_on = !!(condition); \ + if (unlikely(__ret_warn_on)) { \ + if (i915.verbose_state_checks) \ + __WARN_printf(format); \ + else \ + DRM_ERROR(format); \ + } \ + unlikely(__ret_warn_on); \ +}) + +#define I915_STATE_WARN_ON(condition) ({ \ + int __ret_warn_on = !!(condition); \ + if (unlikely(__ret_warn_on)) { \ + if (i915.verbose_state_checks) \ + __WARN_printf("WARN_ON(" #condition ")\n"); \ + else \ + DRM_ERROR("WARN_ON(" #condition ")\n"); \ + } \ + unlikely(__ret_warn_on); \ +}) + enum pipe { INVALID_PIPE = -1, PIPE_A = 0, @@ -2401,6 +2430,7 @@ struct i915_params { bool disable_vtd_wa; int use_mmio_flip; bool mmio_debug; + bool verbose_state_checks; }; extern struct i915_params i915 __read_mostly; diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index f6af6d4c775cb0..07252d8dc726ad 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -51,6 +51,7 @@ struct i915_params i915 __read_mostly = { .disable_vtd_wa = 0, .use_mmio_flip = 0, .mmio_debug = 0, + .verbose_state_checks = 1, }; module_param_named(modeset, i915.modeset, int, 0400); @@ -173,3 +174,7 @@ module_param_named(mmio_debug, i915.mmio_debug, bool, 0600); MODULE_PARM_DESC(mmio_debug, "Enable the MMIO debug code (default: false). This may negatively " "affect performance."); + +module_param_named(verbose_state_checks, i915.verbose_state_checks, bool, 0600); +MODULE_PARM_DESC(verbose_state_checks, + "Enable verbose logs (ie. WARN_ON()) in case of unexpected hw state conditions."); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 878c4857ff4923..0a09473e1eee8e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1024,7 +1024,7 @@ void assert_pll(struct drm_i915_private *dev_priv, reg = DPLL(pipe); val = I915_READ(reg); cur_state = !!(val & DPLL_VCO_ENABLE); - WARN(cur_state != state, + I915_STATE_WARN(cur_state != state, "PLL state assertion failure (expected %s, current %s)\n", state_string(state), state_string(cur_state)); } @@ -1040,7 +1040,7 @@ static void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state) mutex_unlock(&dev_priv->dpio_lock); cur_state = val & DSI_PLL_VCO_EN; - WARN(cur_state != state, + I915_STATE_WARN(cur_state != state, "DSI PLL state assertion failure (expected %s, current %s)\n", state_string(state), state_string(cur_state)); } @@ -1071,7 +1071,7 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv, return; cur_state = pll->get_hw_state(dev_priv, pll, &hw_state); - WARN(cur_state != state, + I915_STATE_WARN(cur_state != state, "%s assertion failure (expected %s, current %s)\n", pll->name, state_string(state), state_string(cur_state)); } @@ -1095,7 +1095,7 @@ static void assert_fdi_tx(struct drm_i915_private *dev_priv, val = I915_READ(reg); cur_state = !!(val & FDI_TX_ENABLE); } - WARN(cur_state != state, + I915_STATE_WARN(cur_state != state, "FDI TX state assertion failure (expected %s, current %s)\n", state_string(state), state_string(cur_state)); } @@ -1112,7 +1112,7 @@ static void assert_fdi_rx(struct drm_i915_private *dev_priv, reg = FDI_RX_CTL(pipe); val = I915_READ(reg); cur_state = !!(val & FDI_RX_ENABLE); - WARN(cur_state != state, + I915_STATE_WARN(cur_state != state, "FDI RX state assertion failure (expected %s, current %s)\n", state_string(state), state_string(cur_state)); } @@ -1135,7 +1135,7 @@ static void assert_fdi_tx_pll_enabled(struct drm_i915_private *dev_priv, reg = FDI_TX_CTL(pipe); val = I915_READ(reg); - WARN(!(val & FDI_TX_PLL_ENABLE), "FDI TX PLL assertion failure, should be active but is disabled\n"); + I915_STATE_WARN(!(val & FDI_TX_PLL_ENABLE), "FDI TX PLL assertion failure, should be active but is disabled\n"); } void assert_fdi_rx_pll(struct drm_i915_private *dev_priv, @@ -1148,7 +1148,7 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv, reg = FDI_RX_CTL(pipe); val = I915_READ(reg); cur_state = !!(val & FDI_RX_PLL_ENABLE); - WARN(cur_state != state, + I915_STATE_WARN(cur_state != state, "FDI RX PLL assertion failure (expected %s, current %s)\n", state_string(state), state_string(cur_state)); } @@ -1190,7 +1190,7 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv, ((val & PANEL_UNLOCK_MASK) == PANEL_UNLOCK_REGS)) locked = false; - WARN(panel_pipe == pipe && locked, + I915_STATE_WARN(panel_pipe == pipe && locked, "panel assertion failure, pipe %c regs locked\n", pipe_name(pipe)); } @@ -1206,7 +1206,7 @@ static void assert_cursor(struct drm_i915_private *dev_priv, else cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE; - WARN(cur_state != state, + I915_STATE_WARN(cur_state != state, "cursor on pipe %c assertion failure (expected %s, current %s)\n", pipe_name(pipe), state_string(state), state_string(cur_state)); } @@ -1236,7 +1236,7 @@ void assert_pipe(struct drm_i915_private *dev_priv, cur_state = !!(val & PIPECONF_ENABLE); } - WARN(cur_state != state, + I915_STATE_WARN(cur_state != state, "pipe %c assertion failure (expected %s, current %s)\n", pipe_name(pipe), state_string(state), state_string(cur_state)); } @@ -1251,7 +1251,7 @@ static void assert_plane(struct drm_i915_private *dev_priv, reg = DSPCNTR(plane); val = I915_READ(reg); cur_state = !!(val & DISPLAY_PLANE_ENABLE); - WARN(cur_state != state, + I915_STATE_WARN(cur_state != state, "plane %c assertion failure (expected %s, current %s)\n", plane_name(plane), state_string(state), state_string(cur_state)); } @@ -1271,7 +1271,7 @@ static void assert_planes_disabled(struct drm_i915_private *dev_priv, if (INTEL_INFO(dev)->gen >= 4) { reg = DSPCNTR(pipe); val = I915_READ(reg); - WARN(val & DISPLAY_PLANE_ENABLE, + I915_STATE_WARN(val & DISPLAY_PLANE_ENABLE, "plane %c assertion failure, should be disabled but not\n", plane_name(pipe)); return; @@ -1283,7 +1283,7 @@ static void assert_planes_disabled(struct drm_i915_private *dev_priv, val = I915_READ(reg); cur_pipe = (val & DISPPLANE_SEL_PIPE_MASK) >> DISPPLANE_SEL_PIPE_SHIFT; - WARN((val & DISPLAY_PLANE_ENABLE) && pipe == cur_pipe, + I915_STATE_WARN((val & DISPLAY_PLANE_ENABLE) && pipe == cur_pipe, "plane %c assertion failure, should be off on pipe %c but is still active\n", plane_name(i), pipe_name(pipe)); } @@ -1299,7 +1299,7 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv, if (INTEL_INFO(dev)->gen >= 9) { for_each_sprite(pipe, sprite) { val = I915_READ(PLANE_CTL(pipe, sprite)); - WARN(val & PLANE_CTL_ENABLE, + I915_STATE_WARN(val & PLANE_CTL_ENABLE, "plane %d assertion failure, should be off on pipe %c but is still active\n", sprite, pipe_name(pipe)); } @@ -1307,20 +1307,20 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv, for_each_sprite(pipe, sprite) { reg = SPCNTR(pipe, sprite); val = I915_READ(reg); - WARN(val & SP_ENABLE, + I915_STATE_WARN(val & SP_ENABLE, "sprite %c assertion failure, should be off on pipe %c but is still active\n", sprite_name(pipe, sprite), pipe_name(pipe)); } } else if (INTEL_INFO(dev)->gen >= 7) { reg = SPRCTL(pipe); val = I915_READ(reg); - WARN(val & SPRITE_ENABLE, + I915_STATE_WARN(val & SPRITE_ENABLE, "sprite %c assertion failure, should be off on pipe %c but is still active\n", plane_name(pipe), pipe_name(pipe)); } else if (INTEL_INFO(dev)->gen >= 5) { reg = DVSCNTR(pipe); val = I915_READ(reg); - WARN(val & DVS_ENABLE, + I915_STATE_WARN(val & DVS_ENABLE, "sprite %c assertion failure, should be off on pipe %c but is still active\n", plane_name(pipe), pipe_name(pipe)); } @@ -1328,7 +1328,7 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv, static void assert_vblank_disabled(struct drm_crtc *crtc) { - if (WARN_ON(drm_crtc_vblank_get(crtc) == 0)) + if (I915_STATE_WARN_ON(drm_crtc_vblank_get(crtc) == 0)) drm_crtc_vblank_put(crtc); } @@ -1337,12 +1337,12 @@ static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv) u32 val; bool enabled; - WARN_ON(!(HAS_PCH_IBX(dev_priv->dev) || HAS_PCH_CPT(dev_priv->dev))); + I915_STATE_WARN_ON(!(HAS_PCH_IBX(dev_priv->dev) || HAS_PCH_CPT(dev_priv->dev))); val = I915_READ(PCH_DREF_CONTROL); enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK | DREF_SUPERSPREAD_SOURCE_MASK)); - WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n"); + I915_STATE_WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n"); } static void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv, @@ -1355,7 +1355,7 @@ static void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv, reg = PCH_TRANSCONF(pipe); val = I915_READ(reg); enabled = !!(val & TRANS_ENABLE); - WARN(enabled, + I915_STATE_WARN(enabled, "transcoder assertion failed, should be off on pipe %c but is still active\n", pipe_name(pipe)); } @@ -1435,11 +1435,11 @@ static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, enum pipe pipe, int reg, u32 port_sel) { u32 val = I915_READ(reg); - WARN(dp_pipe_enabled(dev_priv, pipe, port_sel, val), + I915_STATE_WARN(dp_pipe_enabled(dev_priv, pipe, port_sel, val), "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", reg, pipe_name(pipe)); - WARN(HAS_PCH_IBX(dev_priv->dev) && (val & DP_PORT_EN) == 0 + I915_STATE_WARN(HAS_PCH_IBX(dev_priv->dev) && (val & DP_PORT_EN) == 0 && (val & DP_PIPEB_SELECT), "IBX PCH dp port still using transcoder B\n"); } @@ -1448,11 +1448,11 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, enum pipe pipe, int reg) { u32 val = I915_READ(reg); - WARN(hdmi_pipe_enabled(dev_priv, pipe, val), + I915_STATE_WARN(hdmi_pipe_enabled(dev_priv, pipe, val), "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n", reg, pipe_name(pipe)); - WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_ENABLE) == 0 + I915_STATE_WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_ENABLE) == 0 && (val & SDVO_PIPE_B_SELECT), "IBX PCH hdmi port still using transcoder B\n"); } @@ -1469,13 +1469,13 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, reg = PCH_ADPA; val = I915_READ(reg); - WARN(adpa_pipe_enabled(dev_priv, pipe, val), + I915_STATE_WARN(adpa_pipe_enabled(dev_priv, pipe, val), "PCH VGA enabled on transcoder %c, should be disabled\n", pipe_name(pipe)); reg = PCH_LVDS; val = I915_READ(reg); - WARN(lvds_pipe_enabled(dev_priv, pipe, val), + I915_STATE_WARN(lvds_pipe_enabled(dev_priv, pipe, val), "PCH LVDS enabled on transcoder %c, should be disabled\n", pipe_name(pipe)); @@ -5311,25 +5311,25 @@ static void intel_connector_check_state(struct intel_connector *connector) if (connector->mst_port) return; - WARN(connector->base.dpms == DRM_MODE_DPMS_OFF, + I915_STATE_WARN(connector->base.dpms == DRM_MODE_DPMS_OFF, "wrong connector dpms state\n"); - WARN(connector->base.encoder != &encoder->base, + I915_STATE_WARN(connector->base.encoder != &encoder->base, "active connector not linked to encoder\n"); if (encoder) { - WARN(!encoder->connectors_active, + I915_STATE_WARN(!encoder->connectors_active, "encoder->connectors_active not set\n"); encoder_enabled = encoder->get_hw_state(encoder, &pipe); - WARN(!encoder_enabled, "encoder not enabled\n"); - if (WARN_ON(!encoder->base.crtc)) + I915_STATE_WARN(!encoder_enabled, "encoder not enabled\n"); + if (I915_STATE_WARN_ON(!encoder->base.crtc)) return; crtc = encoder->base.crtc; - WARN(!crtc->enabled, "crtc not enabled\n"); - WARN(!to_intel_crtc(crtc)->active, "crtc not active\n"); - WARN(pipe != to_intel_crtc(crtc)->pipe, + I915_STATE_WARN(!crtc->enabled, "crtc not enabled\n"); + I915_STATE_WARN(!to_intel_crtc(crtc)->active, "crtc not active\n"); + I915_STATE_WARN(pipe != to_intel_crtc(crtc)->pipe, "encoder active on the wrong pipe\n"); } } @@ -7739,24 +7739,24 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) struct intel_crtc *crtc; for_each_intel_crtc(dev, crtc) - WARN(crtc->active, "CRTC for pipe %c enabled\n", + I915_STATE_WARN(crtc->active, "CRTC for pipe %c enabled\n", pipe_name(crtc->pipe)); - WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n"); - WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL enabled\n"); - WARN(I915_READ(WRPLL_CTL1) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n"); - WARN(I915_READ(WRPLL_CTL2) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n"); - WARN(I915_READ(PCH_PP_STATUS) & PP_ON, "Panel power on\n"); - WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE, + I915_STATE_WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n"); + I915_STATE_WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL enabled\n"); + I915_STATE_WARN(I915_READ(WRPLL_CTL1) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n"); + I915_STATE_WARN(I915_READ(WRPLL_CTL2) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n"); + I915_STATE_WARN(I915_READ(PCH_PP_STATUS) & PP_ON, "Panel power on\n"); + I915_STATE_WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE, "CPU PWM1 enabled\n"); if (IS_HASWELL(dev)) - WARN(I915_READ(HSW_BLC_PWM2_CTL) & BLM_PWM_ENABLE, + I915_STATE_WARN(I915_READ(HSW_BLC_PWM2_CTL) & BLM_PWM_ENABLE, "CPU PWM2 enabled\n"); - WARN(I915_READ(BLC_PWM_PCH_CTL1) & BLM_PCH_PWM_ENABLE, + I915_STATE_WARN(I915_READ(BLC_PWM_PCH_CTL1) & BLM_PCH_PWM_ENABLE, "PCH PWM1 enabled\n"); - WARN(I915_READ(UTIL_PIN_CTL) & UTIL_PIN_ENABLE, + I915_STATE_WARN(I915_READ(UTIL_PIN_CTL) & UTIL_PIN_ENABLE, "Utility pin enabled\n"); - WARN(I915_READ(PCH_GTC_CTL) & PCH_GTC_ENABLE, "PCH GTC enabled\n"); + I915_STATE_WARN(I915_READ(PCH_GTC_CTL) & PCH_GTC_ENABLE, "PCH GTC enabled\n"); /* * In theory we can still leave IRQs enabled, as long as only the HPD @@ -7764,7 +7764,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) * gen-specific and since we only disable LCPLL after we fully disable * the interrupts, the check below should be enough. */ - WARN(intel_irqs_enabled(dev_priv), "IRQs enabled\n"); + I915_STATE_WARN(intel_irqs_enabled(dev_priv), "IRQs enabled\n"); } static uint32_t hsw_read_dcomp(struct drm_i915_private *dev_priv) @@ -10640,7 +10640,7 @@ check_connector_state(struct drm_device *dev) * ->get_hw_state callbacks. */ intel_connector_check_state(connector); - WARN(&connector->new_encoder->base != connector->base.encoder, + I915_STATE_WARN(&connector->new_encoder->base != connector->base.encoder, "connector's staged encoder doesn't match current encoder\n"); } } @@ -10660,9 +10660,9 @@ check_encoder_state(struct drm_device *dev) encoder->base.base.id, encoder->base.name); - WARN(&encoder->new_crtc->base != encoder->base.crtc, + I915_STATE_WARN(&encoder->new_crtc->base != encoder->base.crtc, "encoder's stage crtc doesn't match current crtc\n"); - WARN(encoder->connectors_active && !encoder->base.crtc, + I915_STATE_WARN(encoder->connectors_active && !encoder->base.crtc, "encoder's active_connectors set, but no crtc\n"); list_for_each_entry(connector, &dev->mode_config.connector_list, @@ -10681,19 +10681,19 @@ check_encoder_state(struct drm_device *dev) if (!enabled && encoder->base.encoder_type == DRM_MODE_ENCODER_DPMST) continue; - WARN(!!encoder->base.crtc != enabled, + I915_STATE_WARN(!!encoder->base.crtc != enabled, "encoder's enabled state mismatch " "(expected %i, found %i)\n", !!encoder->base.crtc, enabled); - WARN(active && !encoder->base.crtc, + I915_STATE_WARN(active && !encoder->base.crtc, "active encoder with no crtc\n"); - WARN(encoder->connectors_active != active, + I915_STATE_WARN(encoder->connectors_active != active, "encoder's computed active state doesn't match tracked active state " "(expected %i, found %i)\n", active, encoder->connectors_active); active = encoder->get_hw_state(encoder, &pipe); - WARN(active != encoder->connectors_active, + I915_STATE_WARN(active != encoder->connectors_active, "encoder's hw state doesn't match sw tracking " "(expected %i, found %i)\n", encoder->connectors_active, active); @@ -10702,7 +10702,7 @@ check_encoder_state(struct drm_device *dev) continue; tracked_pipe = to_intel_crtc(encoder->base.crtc)->pipe; - WARN(active && pipe != tracked_pipe, + I915_STATE_WARN(active && pipe != tracked_pipe, "active encoder's pipe doesn't match" "(expected %i, found %i)\n", tracked_pipe, pipe); @@ -10727,7 +10727,7 @@ check_crtc_state(struct drm_device *dev) DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.base.id); - WARN(crtc->active && !crtc->base.enabled, + I915_STATE_WARN(crtc->active && !crtc->base.enabled, "active crtc, but not enabled in sw tracking\n"); for_each_intel_encoder(dev, encoder) { @@ -10738,10 +10738,10 @@ check_crtc_state(struct drm_device *dev) active = true; } - WARN(active != crtc->active, + I915_STATE_WARN(active != crtc->active, "crtc's computed active state doesn't match tracked active state " "(expected %i, found %i)\n", active, crtc->active); - WARN(enabled != crtc->base.enabled, + I915_STATE_WARN(enabled != crtc->base.enabled, "crtc's computed enabled state doesn't match tracked enabled state " "(expected %i, found %i)\n", enabled, crtc->base.enabled); @@ -10761,13 +10761,13 @@ check_crtc_state(struct drm_device *dev) encoder->get_config(encoder, &pipe_config); } - WARN(crtc->active != active, + I915_STATE_WARN(crtc->active != active, "crtc active state doesn't match with hw state " "(expected %i, found %i)\n", crtc->active, active); if (active && !intel_pipe_config_compare(dev, &crtc->config, &pipe_config)) { - WARN(1, "pipe state doesn't match!\n"); + I915_STATE_WARN(1, "pipe state doesn't match!\n"); intel_dump_pipe_config(crtc, &pipe_config, "[hw state]"); intel_dump_pipe_config(crtc, &crtc->config, @@ -10795,14 +10795,14 @@ check_shared_dpll_state(struct drm_device *dev) active = pll->get_hw_state(dev_priv, pll, &dpll_hw_state); - WARN(pll->active > hweight32(pll->config.crtc_mask), + I915_STATE_WARN(pll->active > hweight32(pll->config.crtc_mask), "more active pll users than references: %i vs %i\n", pll->active, hweight32(pll->config.crtc_mask)); - WARN(pll->active && !pll->on, + I915_STATE_WARN(pll->active && !pll->on, "pll in active use but not on in sw tracking\n"); - WARN(pll->on && !pll->active, + I915_STATE_WARN(pll->on && !pll->active, "pll in on but not on in use in sw tracking\n"); - WARN(pll->on != active, + I915_STATE_WARN(pll->on != active, "pll on state mismatch (expected %i, found %i)\n", pll->on, active); @@ -10812,14 +10812,14 @@ check_shared_dpll_state(struct drm_device *dev) if (crtc->active && intel_crtc_to_shared_dpll(crtc) == pll) active_crtcs++; } - WARN(pll->active != active_crtcs, + I915_STATE_WARN(pll->active != active_crtcs, "pll active crtcs mismatch (expected %i, found %i)\n", pll->active, active_crtcs); - WARN(hweight32(pll->config.crtc_mask) != enabled_crtcs, + I915_STATE_WARN(hweight32(pll->config.crtc_mask) != enabled_crtcs, "pll enabled crtcs mismatch (expected %i, found %i)\n", hweight32(pll->config.crtc_mask), enabled_crtcs); - WARN(pll->on && memcmp(&pll->config.hw_state, &dpll_hw_state, + I915_STATE_WARN(pll->on && memcmp(&pll->config.hw_state, &dpll_hw_state, sizeof(dpll_hw_state)), "pll hw state mismatch\n"); } diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 8b31e01b054b74..88d81a8b0d3580 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1558,7 +1558,7 @@ void intel_edp_panel_vdd_on(struct intel_dp *intel_dp) vdd = edp_panel_vdd_on(intel_dp); pps_unlock(intel_dp); - WARN(!vdd, "eDP port %c VDD already requested on\n", + I915_STATE_WARN(!vdd, "eDP port %c VDD already requested on\n", port_name(dp_to_dig_port(intel_dp)->port)); } @@ -1642,7 +1642,7 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) if (!is_edp(intel_dp)) return; - WARN(!intel_dp->want_panel_vdd, "eDP port %c VDD not forced on", + I915_STATE_WARN(!intel_dp->want_panel_vdd, "eDP port %c VDD not forced on", port_name(dp_to_dig_port(intel_dp)->port)); intel_dp->want_panel_vdd = false; diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 8a2bd1869fd807..6aa3a81df48566 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -633,7 +633,7 @@ static void check_power_well_state(struct drm_i915_private *dev_priv, return; mismatch: - WARN(1, "state mismatch for '%s' (always_on %d hw state %d use-count %d disable_power_well %d\n", + I915_STATE_WARN(1, "state mismatch for '%s' (always_on %d hw state %d use-count %d disable_power_well %d\n", power_well->name, power_well->always_on, enabled, power_well->count, i915.disable_power_well); } From dafffda023b04f87e695dfcf5448e4da964d2e95 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 16 Dec 2014 12:02:13 +0100 Subject: [PATCH 0203/3023] drm/info: Remove unused code Commit 28a62277e06f ("drm: Convert proc files to seq_file and introduce debugfs") converted /proc files to debugfs and in the process dropped the entry for the vblank statistics. Since that file has been gone for almost five years, there is no use to keep the code that provides the file's content around. Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_info.c | 24 ------------------------ drivers/gpu/drm/drm_internal.h | 1 - 2 files changed, 25 deletions(-) diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c index 51efebd434f302..f1b32f91d94163 100644 --- a/drivers/gpu/drm/drm_info.c +++ b/drivers/gpu/drm/drm_info.c @@ -152,30 +152,6 @@ int drm_bufs_info(struct seq_file *m, void *data) return 0; } -/** - * Called when "/proc/dri/.../vblank" is read. - */ -int drm_vblank_info(struct seq_file *m, void *data) -{ - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_device *dev = node->minor->dev; - int crtc; - - mutex_lock(&dev->struct_mutex); - for (crtc = 0; crtc < dev->num_crtcs; crtc++) { - seq_printf(m, "CRTC %d enable: %d\n", - crtc, atomic_read(&dev->vblank[crtc].refcount)); - seq_printf(m, "CRTC %d counter: %d\n", - crtc, drm_vblank_count(dev, crtc)); - seq_printf(m, "CRTC %d last wait: %d\n", - crtc, dev->vblank[crtc].last_wait); - seq_printf(m, "CRTC %d in modeset: %d\n", - crtc, dev->vblank[crtc].inmodeset); - } - mutex_unlock(&dev->struct_mutex); - return 0; -} - /** * Called when "/proc/dri/.../clients" is read. * diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 7cc0a3516871f4..12a61d70682785 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -55,7 +55,6 @@ void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpr int drm_name_info(struct seq_file *m, void *data); int drm_vm_info(struct seq_file *m, void *data); int drm_bufs_info(struct seq_file *m, void *data); -int drm_vblank_info(struct seq_file *m, void *data); int drm_clients_info(struct seq_file *m, void* data); int drm_gem_name_info(struct seq_file *m, void *data); From ef21bf73b9ae1e4b39ff984dc327f185d9c331b3 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 17 Dec 2014 16:13:17 +0100 Subject: [PATCH 0204/3023] drm/doc: Remove duplicate "by" Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter --- Documentation/DocBook/drm.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 3e212b90351075..d45b2676fbb723 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -1377,7 +1377,7 @@ int max_width, max_height; DRM_PLANE_TYPE_PRIMARY represents a "main" plane for a CRTC. Primary - planes are the planes operated upon by by CRTC modesetting and flipping + planes are the planes operated upon by CRTC modesetting and flipping operations described in . From ce38ab05931484e72f776d04bb5d27c82744dd24 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 4 Dec 2014 06:48:10 -0800 Subject: [PATCH 0205/3023] drm/i915: Organize Fence registers for future enablement. Let's be optimistic that for future platforms this will remain the same and reorg a bit. This reorg in if blocks instead of switch make life easier for future platform support addition. v2: Jani pointed out I was missing reg_830 for some gen3 platforms. So let's make this platforms subcases of Gen checks. Cc: Jani Nikula Cc: Damien Lespiau Signed-off-by: Rodrigo Vivi Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 17 +++++------- drivers/gpu/drm/i915/i915_gpu_error.c | 37 ++++++++++----------------- 2 files changed, 19 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a7bf31a041f43d..f678017c4d3127 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3277,17 +3277,12 @@ static void i915_gem_write_fence(struct drm_device *dev, int reg, "bogus fence setup with stride: 0x%x, tiling mode: %i\n", obj->stride, obj->tiling_mode); - switch (INTEL_INFO(dev)->gen) { - case 9: - case 8: - case 7: - case 6: - case 5: - case 4: i965_write_fence_reg(dev, reg, obj); break; - case 3: i915_write_fence_reg(dev, reg, obj); break; - case 2: i830_write_fence_reg(dev, reg, obj); break; - default: BUG(); - } + if (IS_GEN2(dev)) + i830_write_fence_reg(dev, reg, obj); + else if (IS_GEN3(dev)) + i915_write_fence_reg(dev, reg, obj); + else if (INTEL_INFO(dev)->gen >= 4) + i965_write_fence_reg(dev, reg, obj); /* And similarly be paranoid that no direct access to this region * is reordered to before the fence is installed. diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index f97479a2ea6f0d..010f57f3d83d64 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -764,32 +764,21 @@ static void i915_gem_record_fences(struct drm_device *dev, struct drm_i915_private *dev_priv = dev->dev_private; int i; - /* Fences */ - switch (INTEL_INFO(dev)->gen) { - case 9: - case 8: - case 7: - case 6: - for (i = 0; i < dev_priv->num_fence_regs; i++) - error->fence[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8)); - break; - case 5: - case 4: - for (i = 0; i < 16; i++) - error->fence[i] = I915_READ64(FENCE_REG_965_0 + (i * 8)); - break; - case 3: - if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) - for (i = 0; i < 8; i++) - error->fence[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4)); - case 2: + if (IS_GEN3(dev) || IS_GEN2(dev)) { for (i = 0; i < 8; i++) error->fence[i] = I915_READ(FENCE_REG_830_0 + (i * 4)); - break; - - default: - BUG(); - } + if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) + for (i = 0; i < 8; i++) + error->fence[i+8] = I915_READ(FENCE_REG_945_8 + + (i * 4)); + } else if (IS_GEN5(dev) || IS_GEN4(dev)) + for (i = 0; i < 16; i++) + error->fence[i] = I915_READ64(FENCE_REG_965_0 + + (i * 8)); + else if (INTEL_INFO(dev)->gen >= 6) + for (i = 0; i < dev_priv->num_fence_regs; i++) + error->fence[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + + (i * 8)); } From 1eb0f0061d8234ed204a1c6ed9e8bb8dcefa2789 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Wed, 3 Dec 2014 04:55:26 -0800 Subject: [PATCH 0206/3023] drm/i915: Organize PPGTT init Let's be optimistic that for future platforms memory management doesn't change that much and reuse gen8 function for PPGTT init. Cc: Damien Lespiau Signed-off-by: Rodrigo Vivi Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 75a29a3822089d..82cb5666583f74 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1165,10 +1165,8 @@ static int __hw_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt) if (INTEL_INFO(dev)->gen < 8) return gen6_ppgtt_init(ppgtt); - else if (IS_GEN8(dev) || IS_GEN9(dev)) - return gen8_ppgtt_init(ppgtt, dev_priv->gtt.base.total); else - BUG(); + return gen8_ppgtt_init(ppgtt, dev_priv->gtt.base.total); } int i915_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt) { From 74745b093889aee5887e327b0108d56ba3ab9629 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Wed, 3 Dec 2014 04:55:27 -0800 Subject: [PATCH 0207/3023] drm/i915: Organize PDP regs report for future. Let's be optimistic that for future platforms this will remain the same and reorg a bit. This reorg in if blocks instead of switch make life easier for future platform support addition. Cc: Damien Lespiau Signed-off-by: Rodrigo Vivi Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gpu_error.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 010f57f3d83d64..d172d13b020c96 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -912,9 +912,13 @@ static void i915_record_ring_state(struct drm_device *dev, ering->vm_info.gfx_mode = I915_READ(RING_MODE_GEN7(ring)); - switch (INTEL_INFO(dev)->gen) { - case 9: - case 8: + if (IS_GEN6(dev)) + ering->vm_info.pp_dir_base = + I915_READ(RING_PP_DIR_BASE_READ(ring)); + else if (IS_GEN7(dev)) + ering->vm_info.pp_dir_base = + I915_READ(RING_PP_DIR_BASE(ring)); + else if (INTEL_INFO(dev)->gen >= 8) for (i = 0; i < 4; i++) { ering->vm_info.pdp[i] = I915_READ(GEN8_RING_PDP_UDW(ring, i)); @@ -922,16 +926,6 @@ static void i915_record_ring_state(struct drm_device *dev, ering->vm_info.pdp[i] |= I915_READ(GEN8_RING_PDP_LDW(ring, i)); } - break; - case 7: - ering->vm_info.pp_dir_base = - I915_READ(RING_PP_DIR_BASE(ring)); - break; - case 6: - ering->vm_info.pp_dir_base = - I915_READ(RING_PP_DIR_BASE_READ(ring)); - break; - } } } From 563f94f6faefe8cb497245a3511b272587ebd85b Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Wed, 3 Dec 2014 04:55:28 -0800 Subject: [PATCH 0208/3023] drm/i915: Organize INSTDONE report for future. Let's be optimistic that for future platforms this will remain the same and reorg a bit. This reorg in if blocks instead of switch make life easier for future platform support addition. Cc: Damien Lespiau Signed-off-by: Rodrigo Vivi Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gpu_error.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index d172d13b020c96..be5c9908659b20 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1356,26 +1356,15 @@ void i915_get_extra_instdone(struct drm_device *dev, uint32_t *instdone) struct drm_i915_private *dev_priv = dev->dev_private; memset(instdone, 0, sizeof(*instdone) * I915_NUM_INSTDONE_REG); - switch (INTEL_INFO(dev)->gen) { - case 2: - case 3: + if (IS_GEN2(dev) || IS_GEN3(dev)) instdone[0] = I915_READ(INSTDONE); - break; - case 4: - case 5: - case 6: + else if (IS_GEN4(dev) || IS_GEN5(dev) || IS_GEN6(dev)) { instdone[0] = I915_READ(INSTDONE_I965); instdone[1] = I915_READ(INSTDONE1); - break; - default: - WARN_ONCE(1, "Unsupported platform\n"); - case 7: - case 8: - case 9: + } else if (INTEL_INFO(dev)->gen >= 7) { instdone[0] = I915_READ(GEN7_INSTDONE_1); instdone[1] = I915_READ(GEN7_SC_INSTDONE); instdone[2] = I915_READ(GEN7_SAMPLER_INSTDONE); instdone[3] = I915_READ(GEN7_ROW_INSTDONE); - break; } } From b1252bcfe53f8ced80ce4e07d761304e755594db Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Wed, 3 Dec 2014 04:55:29 -0800 Subject: [PATCH 0209/3023] drm/i915: Organize bind_vma funcs Let's be optimistic that for future platforms this will remain the same and reorg a bit. This reorg in if blocks instead of switch make life easier for future platform support addition. Cc: Damien Lespiau Signed-off-by: Rodrigo Vivi Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 82cb5666583f74..746f77fb57a314 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2243,11 +2243,7 @@ static struct i915_vma *__i915_gem_vma_create(struct drm_i915_gem_object *obj, vma->obj = obj; vma->ggtt_view = *view; - switch (INTEL_INFO(vm->dev)->gen) { - case 9: - case 8: - case 7: - case 6: + if (INTEL_INFO(vm->dev)->gen >= 6) { if (i915_is_ggtt(vm)) { vma->unbind_vma = ggtt_unbind_vma; vma->bind_vma = ggtt_bind_vma; @@ -2255,17 +2251,10 @@ static struct i915_vma *__i915_gem_vma_create(struct drm_i915_gem_object *obj, vma->unbind_vma = ppgtt_unbind_vma; vma->bind_vma = ppgtt_bind_vma; } - break; - case 5: - case 4: - case 3: - case 2: + } else { BUG_ON(!i915_is_ggtt(vm)); vma->unbind_vma = i915_ggtt_unbind_vma; vma->bind_vma = i915_ggtt_bind_vma; - break; - default: - BUG(); } list_add_tail(&vma->vma_link, &obj->vma_list); From 05acaec334fcc1132d1e48c5042e044651e0b75b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 17 Dec 2014 13:56:22 +0200 Subject: [PATCH 0210/3023] drm: Reorganize probed mode validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make drm_mode_validate_size() and drm_mode_validate_flag() deal with a single mode instead of having each iterate through the mode list. The hope is that in the future we might be able to share various mode validation functions between modeset and get_modes. Signed-off-by: Ville Syrjälä Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_modes.c | 24 +++++++++--------- drivers/gpu/drm/drm_probe_helper.c | 40 ++++++++++++++---------------- include/drm/drm_modes.h | 5 ++-- 3 files changed, 32 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 6d8b941c820041..19188667f9287d 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -907,8 +907,7 @@ EXPORT_SYMBOL(drm_mode_equal_no_clocks_no_stereo); /** * drm_mode_validate_size - make sure modes adhere to size constraints - * @dev: DRM device - * @mode_list: list of modes to check + * @mode: mode to check * @maxX: maximum width * @maxY: maximum height * @@ -916,20 +915,21 @@ EXPORT_SYMBOL(drm_mode_equal_no_clocks_no_stereo); * limitations of the DRM device/connector. If a mode is too big its status * member is updated with the appropriate validation failure code. The list * itself is not changed. + * + * Returns: + * The mode status */ -void drm_mode_validate_size(struct drm_device *dev, - struct list_head *mode_list, - int maxX, int maxY) +enum drm_mode_status +drm_mode_validate_size(const struct drm_display_mode *mode, + int maxX, int maxY) { - struct drm_display_mode *mode; + if (maxX > 0 && mode->hdisplay > maxX) + return MODE_VIRTUAL_X; - list_for_each_entry(mode, mode_list, head) { - if (maxX > 0 && mode->hdisplay > maxX) - mode->status = MODE_VIRTUAL_X; + if (maxY > 0 && mode->vdisplay > maxY) + return MODE_VIRTUAL_Y; - if (maxY > 0 && mode->vdisplay > maxY) - mode->status = MODE_VIRTUAL_Y; - } + return MODE_OK; } EXPORT_SYMBOL(drm_mode_validate_size); diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 7483a47de8e416..2161d8ed7c6583 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -58,28 +58,23 @@ static bool drm_kms_helper_poll = true; module_param_named(poll, drm_kms_helper_poll, bool, 0600); -static void drm_mode_validate_flag(struct drm_connector *connector, - int flags) +static enum drm_mode_status +drm_mode_validate_flag(const struct drm_display_mode *mode, + int flags) { - struct drm_display_mode *mode; + if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && + !(flags & DRM_MODE_FLAG_INTERLACE)) + return MODE_NO_INTERLACE; - if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE | - DRM_MODE_FLAG_3D_MASK)) - return; + if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) && + !(flags & DRM_MODE_FLAG_DBLSCAN)) + return MODE_NO_DBLESCAN; - list_for_each_entry(mode, &connector->modes, head) { - if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && - !(flags & DRM_MODE_FLAG_INTERLACE)) - mode->status = MODE_NO_INTERLACE; - if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) && - !(flags & DRM_MODE_FLAG_DBLSCAN)) - mode->status = MODE_NO_DBLESCAN; - if ((mode->flags & DRM_MODE_FLAG_3D_MASK) && - !(flags & DRM_MODE_FLAG_3D_MASK)) - mode->status = MODE_NO_STEREO; - } + if ((mode->flags & DRM_MODE_FLAG_3D_MASK) && + !(flags & DRM_MODE_FLAG_3D_MASK)) + return MODE_NO_STEREO; - return; + return MODE_OK; } static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector) @@ -164,18 +159,19 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect drm_mode_connector_list_update(connector, merge_type_bits); - if (maxX && maxY) - drm_mode_validate_size(dev, &connector->modes, maxX, maxY); - if (connector->interlace_allowed) mode_flags |= DRM_MODE_FLAG_INTERLACE; if (connector->doublescan_allowed) mode_flags |= DRM_MODE_FLAG_DBLSCAN; if (connector->stereo_allowed) mode_flags |= DRM_MODE_FLAG_3D_MASK; - drm_mode_validate_flag(connector, mode_flags); list_for_each_entry(mode, &connector->modes, head) { + mode->status = drm_mode_validate_size(mode, maxX, maxY); + + if (mode->status == MODE_OK) + mode->status = drm_mode_validate_flag(mode, mode_flags); + if (mode->status == MODE_OK && connector_funcs->mode_valid) mode->status = connector_funcs->mode_valid(connector, mode); diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index 91d0582f924e3e..6c531140d4584b 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -217,9 +217,8 @@ bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2); /* for use by the crtc helper probe functions */ -void drm_mode_validate_size(struct drm_device *dev, - struct list_head *mode_list, - int maxX, int maxY); +enum drm_mode_status drm_mode_validate_size(const struct drm_display_mode *mode, + int maxX, int maxY); void drm_mode_prune_invalid(struct drm_device *dev, struct list_head *mode_list, bool verbose); void drm_mode_sort(struct list_head *mode_list); From abc0b1447d4974963548777a5ba4a4457c82c426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 17 Dec 2014 13:56:23 +0200 Subject: [PATCH 0211/3023] drm: Perform basic sanity checks on probed modes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure the timings of probed modes at least pass some very basic sanity checks. The checks include: - clock,hdisplay,vdisplay are non zero - sync pulse fits within the blanking period - htotal,vtotal are big enough I have not checked all the drivers to see if the modes the generate might violate these constraints. I'm hoping not, because that would mean either abandoning the idea of doing this from the core code, or fixing the drivers. I'm not entirely sure about limiting the sync pulse to the blanking period. Intel hardware doesn't support such things, but some other hardware might. However at least HDMI doesn't allow having sync pulse edges within the active period, so I'm thinking the check is probably OK to have in the common code. Signed-off-by: Ville Syrjälä Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_modes.c | 32 ++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_probe_helper.c | 5 ++++- include/drm/drm_modes.h | 1 + 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 19188667f9287d..11cc4deca55b89 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -905,6 +905,38 @@ bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1, } EXPORT_SYMBOL(drm_mode_equal_no_clocks_no_stereo); +/** + * drm_mode_validate_basic - make sure the mode is somewhat sane + * @mode: mode to check + * + * Check that the mode timings are at least somewhat reasonable. + * Any hardware specific limits are left up for each driver to check. + * + * Returns: + * The mode status + */ +enum drm_mode_status +drm_mode_validate_basic(const struct drm_display_mode *mode) +{ + if (mode->clock == 0) + return MODE_CLOCK_LOW; + + if (mode->hdisplay == 0 || + mode->hsync_start < mode->hdisplay || + mode->hsync_end < mode->hsync_start || + mode->htotal < mode->hsync_end) + return MODE_H_ILLEGAL; + + if (mode->vdisplay == 0 || + mode->vsync_start < mode->vdisplay || + mode->vsync_end < mode->vsync_start || + mode->vtotal < mode->vsync_end) + return MODE_V_ILLEGAL; + + return MODE_OK; +} +EXPORT_SYMBOL(drm_mode_validate_basic); + /** * drm_mode_validate_size - make sure modes adhere to size constraints * @mode: mode to check diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 2161d8ed7c6583..2fbdcca7ca9a7e 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -167,7 +167,10 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect mode_flags |= DRM_MODE_FLAG_3D_MASK; list_for_each_entry(mode, &connector->modes, head) { - mode->status = drm_mode_validate_size(mode, maxX, maxY); + mode->status = drm_mode_validate_basic(mode); + + if (mode->status == MODE_OK) + mode->status = drm_mode_validate_size(mode, maxX, maxY); if (mode->status == MODE_OK) mode->status = drm_mode_validate_flag(mode, mode_flags); diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index 6c531140d4584b..a36a5bfce2f52b 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -217,6 +217,7 @@ bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2); /* for use by the crtc helper probe functions */ +enum drm_mode_status drm_mode_validate_basic(const struct drm_display_mode *mode); enum drm_mode_status drm_mode_validate_size(const struct drm_display_mode *mode, int maxX, int maxY); void drm_mode_prune_invalid(struct drm_device *dev, From 23e1ce89af5404c7a35dbd008ca85fb6adb16aad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 17 Dec 2014 13:56:24 +0200 Subject: [PATCH 0212/3023] drm: Do basic sanity checks for user modes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently userspace is allowed to pass in basiclly any kind of garbage to setcrtc. Try to catch the cases where the timings make no sense by passing the mode through drm_mode_validate_basic(). One concern here is that we now start to block some modes that have worked in the past. It's at least possible with when using i915 with LVDS/eDP. Previously we've just ignored everything but hdisplay/vdisplay from the user mode and just overwritten the rest with the panel fixed mode. So if someone has been passing a mode with just those populated that would now stop working. If that is a real problem, we can't add these checks to the core code and each driver would have to have its own sanity checks. So fingers crossed... Signed-off-by: Ville Syrjälä Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 6700ebafef1677..e3140c19055632 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2673,6 +2673,12 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, goto out; } + mode->status = drm_mode_validate_basic(mode); + if (mode->status != MODE_OK) { + ret = -EINVAL; + goto out; + } + drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y, From 261ea74f3689a997502f1264494f1749951a05a8 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 17 Dec 2014 16:41:40 +0100 Subject: [PATCH 0213/3023] drm: Remove stale comment The struct drm_connector_funcs kerneldoc refers to a part of struct drm_crtc_funcs that no longer exists. Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter --- include/drm/drm_crtc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index dd2c16e4333312..eb32b09b3babd0 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -455,7 +455,7 @@ struct drm_connector_state { /** * struct drm_connector_funcs - control connectors on a given device - * @dpms: set power state (see drm_crtc_funcs above) + * @dpms: set power state * @save: save connector state * @restore: restore connector state * @reset: reset connector after state has been invalidated (e.g. resume) From d9b13620fa09d2652008f96e083592c772532fd1 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 26 Nov 2014 16:57:41 +0100 Subject: [PATCH 0214/3023] drm/atomic-helper: Export both plane and modeset check helpers The default call sequence for these two parts won't fit for all drivers. So export the two pieces and explain with a bit of kerneldoc when each should be called. v2: Squash in fixup from Rob to actually add the newly exported functions to headers Cc: Rob Clark Reviewed-by: Rob Clark Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic_helper.c | 65 +++++++++++++++++++++++++---- include/drm/drm_atomic_helper.h | 4 ++ include/drm/drm_crtc.h | 8 ++++ 3 files changed, 69 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index bbdbe4721573a9..0cd71dac394e7e 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -330,7 +330,29 @@ mode_fixup(struct drm_atomic_state *state) return 0; } -static int +/** + * drm_atomic_helper_check - validate state object for modeset changes + * @dev: DRM device + * @state: the driver state object + * + * Check the state object to see if the requested state is physically possible. + * This does all the crtc and connector related computations for an atomic + * update. It computes and updates crtc_state->mode_changed, adds any additional + * connectors needed for full modesets and calls down into ->mode_fixup + * functions of the driver backend. + * + * IMPORTANT: + * + * Drivers which update ->mode_changed (e.g. in their ->atomic_check hooks if a + * plane update can't be done without a full modeset) _must_ call this function + * afterwards after that change. It is permitted to call this function multiple + * times for the same update, e.g. when the ->atomic_check functions depend upon + * the adjusted dotclock for fifo space allocation and watermark computation. + * + * RETURNS + * Zero for success or -errno + */ +int drm_atomic_helper_check_modeset(struct drm_device *dev, struct drm_atomic_state *state) { @@ -406,23 +428,23 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, return mode_fixup(state); } +EXPORT_SYMBOL(drm_atomic_helper_check_modeset); /** - * drm_atomic_helper_check - validate state object + * drm_atomic_helper_check - validate state object for modeset changes * @dev: DRM device * @state: the driver state object * * Check the state object to see if the requested state is physically possible. - * Only crtcs and planes have check callbacks, so for any additional (global) - * checking that a driver needs it can simply wrap that around this function. - * Drivers without such needs can directly use this as their ->atomic_check() - * callback. + * This does all the plane update related checks using by calling into the + * ->atomic_check hooks provided by the driver. * * RETURNS * Zero for success or -errno */ -int drm_atomic_helper_check(struct drm_device *dev, - struct drm_atomic_state *state) +int +drm_atomic_helper_check_planes(struct drm_device *dev, + struct drm_atomic_state *state) { int nplanes = dev->mode_config.num_total_plane; int ncrtcs = dev->mode_config.num_crtc; @@ -471,6 +493,33 @@ int drm_atomic_helper_check(struct drm_device *dev, } } + return ret; +} +EXPORT_SYMBOL(drm_atomic_helper_check_planes); + +/** + * drm_atomic_helper_check - validate state object + * @dev: DRM device + * @state: the driver state object + * + * Check the state object to see if the requested state is physically possible. + * Only crtcs and planes have check callbacks, so for any additional (global) + * checking that a driver needs it can simply wrap that around this function. + * Drivers without such needs can directly use this as their ->atomic_check() + * callback. + * + * RETURNS + * Zero for success or -errno + */ +int drm_atomic_helper_check(struct drm_device *dev, + struct drm_atomic_state *state) +{ + int ret; + + ret = drm_atomic_helper_check_planes(dev, state); + if (ret) + return ret; + ret = drm_atomic_helper_check_modeset(dev, state); if (ret) return ret; diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index f956b413311e15..2095917ff8c77d 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -30,6 +30,10 @@ #include +int drm_atomic_helper_check_modeset(struct drm_device *dev, + struct drm_atomic_state *state); +int drm_atomic_helper_check_planes(struct drm_device *dev, + struct drm_atomic_state *state); int drm_atomic_helper_check(struct drm_device *dev, struct drm_atomic_state *state); int drm_atomic_helper_commit(struct drm_device *dev, diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index b86329813ad3a3..4ee78212f8bf9d 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -238,6 +238,7 @@ struct drm_atomic_state; /** * struct drm_crtc_state - mutable CRTC state * @enable: whether the CRTC should be enabled, gates all other state + * @active: whether the CRTC is actively displaying (used for DPMS) * @mode_changed: for use by helpers and drivers when computing state updates * @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes * @last_vblank_count: for helpers and drivers to capture the vblank of the @@ -248,9 +249,16 @@ struct drm_atomic_state; * @event: optional pointer to a DRM event to signal upon completion of the * state update * @state: backpointer to global drm_atomic_state + * + * Note that the distinction between @enable and @active is rather subtile: + * Flipping @active while @enable is set without changing anything else may + * never return in a failure from the ->atomic_check callback. Userspace assumes + * that a DPMS On will always succeed. In other words: @enable controls resource + * assignment, @active controls the actual hardware state. */ struct drm_crtc_state { bool enable; + bool active; /* computed state bits used by helpers and drivers */ bool planes_changed : 1; From b4274fbee6fc7ca3dd1cc786456ec6fbc14f864d Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 26 Nov 2014 17:02:18 +0100 Subject: [PATCH 0215/3023] drm/atomic-helper: Again check modeset *before* plane states This essentially reverts commit 934ce1c23624526d9d784e0499190bb48113e6f4 Author: Rob Clark Date: Wed Nov 19 16:41:33 2014 -0500 drm/atomic: check mode_changed *after* atomic_check Depending upon the driver both orders (or maybe even interleaving) is required: - If ->atomic_check updates ->mode_changed then helper_check_modeset must be run afters. - If ->atomic_check depends upon accurate adjusted dotclock values for e.g. watermarks, then helper_check_modeset must be run first. The failure mode in the first case is usually a totally angry hw because the pixel format switching doesn't happen. The failure mode in the later case is usually nothing, since in most cases the old adjusted mode from the previous modeset wont be too far off to be a problem. So just underruns and perhaps even just suboptimal (from a power consumption) watermarks. Furthermore in the transitional helpers we only call ->atomic_check after the new modeset state has been fully set up (and hence computed). Given that asymmetry in expected failure modes I think it's safer to go back to the older order. So do that and give msm a special check function to compensate. Also update kerneldoc to explain this a bit. v2: Actually add the missing hunk Rob spotted. v3: Move msm_atomic_check into msm_atomic.c, requested by Rob. Cc: Rob Clark Reviewed-by: Rob Clark Tested-by: Rob Clark Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic_helper.c | 10 ++++++++-- drivers/gpu/drm/msm/msm_atomic.c | 20 ++++++++++++++++++++ drivers/gpu/drm/msm/msm_drv.c | 2 +- drivers/gpu/drm/msm/msm_drv.h | 2 ++ 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 0cd71dac394e7e..eb380ee2dc58cb 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -508,6 +508,12 @@ EXPORT_SYMBOL(drm_atomic_helper_check_planes); * Drivers without such needs can directly use this as their ->atomic_check() * callback. * + * This just wraps the two parts of the state checking for planes and modeset + * state in the default order: First it calls drm_atomic_helper_check_modeset() + * and then drm_atomic_helper_check_planes(). The assumption is that the + * ->atomic_check functions depend upon an updated adjusted_mode.clock to + * e.g. properly compute watermarks. + * * RETURNS * Zero for success or -errno */ @@ -516,11 +522,11 @@ int drm_atomic_helper_check(struct drm_device *dev, { int ret; - ret = drm_atomic_helper_check_planes(dev, state); + ret = drm_atomic_helper_check_modeset(dev, state); if (ret) return ret; - ret = drm_atomic_helper_check_modeset(dev, state); + ret = drm_atomic_helper_check_planes(dev, state); if (ret) return ret; diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index f0de412e13dc78..f8f18e882f97b9 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -81,6 +81,26 @@ static void add_fb(struct msm_commit *c, struct drm_framebuffer *fb) } +int msm_atomic_check(struct drm_device *dev, + struct drm_atomic_state *state) +{ + int ret; + + /* + * msm ->atomic_check can update ->mode_changed for pixel format + * changes, hence must be run before we check the modeset changes. + */ + ret = drm_atomic_helper_check_planes(dev, state); + if (ret) + return ret; + + ret = drm_atomic_helper_check_modeset(dev, state); + if (ret) + return ret; + + return ret; +} + /** * drm_atomic_helper_commit - commit validated state object * @dev: DRM device diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index d3b791b7ddef01..473e4d6051e9f0 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -29,7 +29,7 @@ static void msm_fb_output_poll_changed(struct drm_device *dev) static const struct drm_mode_config_funcs mode_config_funcs = { .fb_create = msm_framebuffer_create, .output_poll_changed = msm_fb_output_poll_changed, - .atomic_check = drm_atomic_helper_check, + .atomic_check = msm_atomic_check, .atomic_commit = msm_atomic_commit, }; diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 13630381843672..d408e02e4ee5bd 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -144,6 +144,8 @@ void __msm_fence_worker(struct work_struct *work); (_cb)->func = _func; \ } while (0) +int msm_atomic_check(struct drm_device *dev, + struct drm_atomic_state *state); int msm_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state, bool async); From 07cc0ef67fa873c8d21e0b626d57753bfd190095 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 27 Nov 2014 15:49:39 +0100 Subject: [PATCH 0216/3023] drm/atomic: Introduce state->obj backpointers Useful since this way we can pass around just the state objects and will get ther real object, too. Specifically this allows us to again simplify the parameters for set_crtc_for_plane. v2: msm already has it's own specific plane_reset hook, don't forget that one! v3: Fixup kerneldoc, reported by 0-day builder. Cc: Rob Clark Reviewed-by: Rob Clark (v2) Tested-by: Rob Clark (v2) Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic.c | 13 ++++--------- drivers/gpu/drm/drm_atomic_helper.c | 19 ++++++++++++++----- drivers/gpu/drm/drm_crtc_helper.c | 2 ++ drivers/gpu/drm/drm_plane_helper.c | 2 ++ drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 1 + include/drm/drm_atomic.h | 4 ++-- include/drm/drm_crtc.h | 9 +++++++++ 7 files changed, 34 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index ff5f034cc40526..cbd5e7240b6b4e 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -344,8 +344,7 @@ EXPORT_SYMBOL(drm_atomic_get_connector_state); /** * drm_atomic_set_crtc_for_plane - set crtc for plane - * @state: the incoming atomic state - * @plane: the plane whose incoming state to update + * @plane_state: the plane whose incoming state to update * @crtc: crtc to use for the plane * * Changing the assigned crtc for a plane requires us to grab the lock and state @@ -358,16 +357,12 @@ EXPORT_SYMBOL(drm_atomic_get_connector_state); * sequence must be restarted. All other errors are fatal. */ int -drm_atomic_set_crtc_for_plane(struct drm_atomic_state *state, - struct drm_plane *plane, struct drm_crtc *crtc) +drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, + struct drm_crtc *crtc) { - struct drm_plane_state *plane_state = - drm_atomic_get_plane_state(state, plane); + struct drm_plane *plane = plane_state->plane; struct drm_crtc_state *crtc_state; - if (WARN_ON(IS_ERR(plane_state))) - return PTR_ERR(plane_state); - if (plane_state->crtc) { crtc_state = drm_atomic_get_crtc_state(plane_state->state, plane_state->crtc); diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index eb380ee2dc58cb..379d37acd5b53b 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1277,7 +1277,7 @@ int drm_atomic_helper_update_plane(struct drm_plane *plane, goto fail; } - ret = drm_atomic_set_crtc_for_plane(state, plane, crtc); + ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); if (ret != 0) goto fail; drm_atomic_set_fb_for_plane(plane_state, fb); @@ -1356,7 +1356,7 @@ int drm_atomic_helper_disable_plane(struct drm_plane *plane) goto fail; } - ret = drm_atomic_set_crtc_for_plane(state, plane, NULL); + ret = drm_atomic_set_crtc_for_plane(plane_state, NULL); if (ret != 0) goto fail; drm_atomic_set_fb_for_plane(plane_state, NULL); @@ -1519,7 +1519,7 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set) crtc_state->enable = false; - ret = drm_atomic_set_crtc_for_plane(state, crtc->primary, NULL); + ret = drm_atomic_set_crtc_for_plane(primary_state, NULL); if (ret != 0) goto fail; @@ -1534,7 +1534,7 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set) crtc_state->enable = true; drm_mode_copy(&crtc_state->mode, set->mode); - ret = drm_atomic_set_crtc_for_plane(state, crtc->primary, crtc); + ret = drm_atomic_set_crtc_for_plane(primary_state, crtc); if (ret != 0) goto fail; drm_atomic_set_fb_for_plane(primary_state, set->fb); @@ -1806,7 +1806,7 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc, goto fail; } - ret = drm_atomic_set_crtc_for_plane(state, plane, crtc); + ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); if (ret != 0) goto fail; drm_atomic_set_fb_for_plane(plane_state, fb); @@ -1869,6 +1869,9 @@ void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc) { kfree(crtc->state); crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL); + + if (crtc->state) + crtc->state->crtc = crtc; } EXPORT_SYMBOL(drm_atomic_helper_crtc_reset); @@ -1928,6 +1931,9 @@ void drm_atomic_helper_plane_reset(struct drm_plane *plane) kfree(plane->state); plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL); + + if (plane->state) + plane->state->plane = plane; } EXPORT_SYMBOL(drm_atomic_helper_plane_reset); @@ -1985,6 +1991,9 @@ void drm_atomic_helper_connector_reset(struct drm_connector *connector) { kfree(connector->state); connector->state = kzalloc(sizeof(*connector->state), GFP_KERNEL); + + if (connector->state) + connector->state->connector = connector; } EXPORT_SYMBOL(drm_atomic_helper_connector_reset); diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index d552708409ded9..b1979e7bdc8862 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -946,6 +946,7 @@ int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mod crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL); if (!crtc_state) return -ENOMEM; + crtc_state->crtc = crtc; crtc_state->enable = true; crtc_state->planes_changed = true; @@ -1005,6 +1006,7 @@ int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL); if (!plane_state) return -ENOMEM; + plane_state->plane = plane; plane_state->crtc = crtc; drm_atomic_set_fb_for_plane(plane_state, crtc->primary->fb); diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index 18a1ac6ac22f39..ae61fb21ea864d 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -517,6 +517,7 @@ int drm_plane_helper_update(struct drm_plane *plane, struct drm_crtc *crtc, plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL); if (!plane_state) return -ENOMEM; + plane_state->plane = plane; plane_state->crtc = crtc; drm_atomic_set_fb_for_plane(plane_state, fb); @@ -563,6 +564,7 @@ int drm_plane_helper_disable(struct drm_plane *plane) plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL); if (!plane_state) return -ENOMEM; + plane_state->plane = plane; plane_state->crtc = NULL; drm_atomic_set_fb_for_plane(plane_state, NULL); diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index 26e5fdea6594c7..fc76f630e5b18f 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c @@ -113,6 +113,7 @@ static void mdp5_plane_reset(struct drm_plane *plane) } else { mdp5_state->zpos = 1 + drm_plane_index(plane); } + mdp5_state->base.plane = plane; plane->state = &mdp5_state->base; } diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index ad2229574dd945..e224ccfa11ca0a 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -46,8 +46,8 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state, struct drm_connector *connector); int __must_check -drm_atomic_set_crtc_for_plane(struct drm_atomic_state *state, - struct drm_plane *plane, struct drm_crtc *crtc); +drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, + struct drm_crtc *crtc); void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state, struct drm_framebuffer *fb); int __must_check diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 4ee78212f8bf9d..fd8139ca629a52 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -237,6 +237,7 @@ struct drm_atomic_state; /** * struct drm_crtc_state - mutable CRTC state + * @crtc: backpointer to the CRTC * @enable: whether the CRTC should be enabled, gates all other state * @active: whether the CRTC is actively displaying (used for DPMS) * @mode_changed: for use by helpers and drivers when computing state updates @@ -257,6 +258,8 @@ struct drm_atomic_state; * assignment, @active controls the actual hardware state. */ struct drm_crtc_state { + struct drm_crtc *crtc; + bool enable; bool active; @@ -457,11 +460,14 @@ struct drm_crtc { /** * struct drm_connector_state - mutable connector state + * @connector: backpointer to the connector * @crtc: CRTC to connect connector to, NULL if disabled * @best_encoder: can be used by helpers and drivers to select the encoder * @state: backpointer to global drm_atomic_state */ struct drm_connector_state { + struct drm_connector *connector; + struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_connector() */ struct drm_encoder *best_encoder; @@ -701,6 +707,7 @@ struct drm_connector { /** * struct drm_plane_state - mutable plane state + * @plane: backpointer to the plane * @crtc: currently bound CRTC, NULL if disabled * @fb: currently bound framebuffer * @fence: optional fence to wait for before scanning out @fb @@ -717,6 +724,8 @@ struct drm_connector { * @state: backpointer to global drm_atomic_state */ struct drm_plane_state { + struct drm_plane *plane; + struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_plane() */ struct drm_framebuffer *fb; /* do not write directly, use drm_atomic_set_fb_for_plane() */ struct fence *fence; From 3843e71f9882c9e2e965cf025f3a7d4de19ce823 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 16 Dec 2014 18:05:29 -0500 Subject: [PATCH 0217/3023] drm: allow property validation for refcnted props We can already have object properties, which technically can be fb's. Switch the property validation logic over to a get/put style interface so it can take a ref to refcnt'd objects, and then drop that ref after the driver has a chance to take it's own ref. Signed-off-by: Rob Clark Reviewed-by: Sean Paul Reviewed-by: Daniel Vetter Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 58 ++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 5213da499d39fe..5ee4b8806aca35 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -4193,12 +4193,22 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector, } EXPORT_SYMBOL(drm_mode_connector_update_edid_property); -static bool drm_property_change_is_valid(struct drm_property *property, - uint64_t value) +/* Some properties could refer to dynamic refcnt'd objects, or things that + * need special locking to handle lifetime issues (ie. to ensure the prop + * value doesn't become invalid part way through the property update due to + * race). The value returned by reference via 'obj' should be passed back + * to drm_property_change_valid_put() after the property is set (and the + * object to which the property is attached has a chance to take it's own + * reference). + */ +static bool drm_property_change_valid_get(struct drm_property *property, + uint64_t value, struct drm_mode_object **ref) { if (property->flags & DRM_MODE_PROP_IMMUTABLE) return false; + *ref = NULL; + if (drm_property_type_is(property, DRM_MODE_PROP_RANGE)) { if (value < property->values[0] || value > property->values[1]) return false; @@ -4219,19 +4229,23 @@ static bool drm_property_change_is_valid(struct drm_property *property, /* Only the driver knows */ return true; } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) { - struct drm_mode_object *obj; /* a zero value for an object property translates to null: */ if (value == 0) return true; - /* - * NOTE: use _object_find() directly to bypass restriction on - * looking up refcnt'd objects (ie. fb's). For a refcnt'd - * object this could race against object finalization, so it - * simply tells us that the object *was* valid. Which is good - * enough. - */ - obj = _object_find(property->dev, value, property->values[0]); - return obj != NULL; + + /* handle refcnt'd objects specially: */ + if (property->values[0] == DRM_MODE_OBJECT_FB) { + struct drm_framebuffer *fb; + fb = drm_framebuffer_lookup(property->dev, value); + if (fb) { + *ref = &fb->base; + return true; + } else { + return false; + } + } else { + return _object_find(property->dev, value, property->values[0]) != NULL; + } } else { int i; for (i = 0; i < property->num_values; i++) @@ -4241,6 +4255,18 @@ static bool drm_property_change_is_valid(struct drm_property *property, } } +static void drm_property_change_valid_put(struct drm_property *property, + struct drm_mode_object *ref) +{ + if (!ref) + return; + + if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) { + if (property->values[0] == DRM_MODE_OBJECT_FB) + drm_framebuffer_unreference(obj_to_fb(ref)); + } +} + /** * drm_mode_connector_property_set_ioctl - set the current value of a connector property * @dev: DRM device @@ -4429,8 +4455,8 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, struct drm_mode_object *arg_obj; struct drm_mode_object *prop_obj; struct drm_property *property; - int ret = -EINVAL; - int i; + int i, ret = -EINVAL; + struct drm_mode_object *ref; if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; @@ -4460,7 +4486,7 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, } property = obj_to_property(prop_obj); - if (!drm_property_change_is_valid(property, arg->value)) + if (!drm_property_change_valid_get(property, arg->value, &ref)) goto out; switch (arg_obj->type) { @@ -4477,6 +4503,8 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, break; } + drm_property_change_valid_put(property, ref); + out: drm_modeset_unlock_all(dev); return ret; From b17cd757a3f61e4519b70b4673f0467ec0153a10 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 16 Dec 2014 18:05:30 -0500 Subject: [PATCH 0218/3023] drm: store property instead of id in obj attachment Keep property pointer, instead of id, in per mode-object attachments. This will simplify things in later patches. Signed-off-by: Rob Clark Reviewed-by: Sean Paul Reviewed-by: Daniel Vetter Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 17 ++++++++--------- include/drm/drm_crtc.h | 7 ++++++- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 5ee4b8806aca35..2780a088051e45 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2105,12 +2105,11 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, prop_ptr = (uint32_t __user *)(unsigned long)(out_resp->props_ptr); prop_values = (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr); for (i = 0; i < connector->properties.count; i++) { - if (put_user(connector->properties.ids[i], - prop_ptr + copied)) { + struct drm_property *prop = connector->properties.properties[i]; + if (put_user(prop->base.id, prop_ptr + copied)) { ret = -EFAULT; goto out; } - if (put_user(connector->properties.values[i], prop_values + copied)) { ret = -EFAULT; @@ -3822,7 +3821,7 @@ void drm_object_attach_property(struct drm_mode_object *obj, return; } - obj->properties->ids[count] = property->base.id; + obj->properties->properties[count] = property; obj->properties->values[count] = init_val; obj->properties->count++; } @@ -3847,7 +3846,7 @@ int drm_object_property_set_value(struct drm_mode_object *obj, int i; for (i = 0; i < obj->properties->count; i++) { - if (obj->properties->ids[i] == property->base.id) { + if (obj->properties->properties[i] == property) { obj->properties->values[i] = val; return 0; } @@ -3877,7 +3876,7 @@ int drm_object_property_get_value(struct drm_mode_object *obj, int i; for (i = 0; i < obj->properties->count; i++) { - if (obj->properties->ids[i] == property->base.id) { + if (obj->properties->properties[i] == property) { *val = obj->properties->values[i]; return 0; } @@ -4413,8 +4412,8 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, prop_values_ptr = (uint64_t __user *)(unsigned long) (arg->prop_values_ptr); for (i = 0; i < props_count; i++) { - if (put_user(obj->properties->ids[i], - props_ptr + copied)) { + struct drm_property *prop = obj->properties->properties[i]; + if (put_user(prop->base.id, props_ptr + copied)) { ret = -EFAULT; goto out; } @@ -4472,7 +4471,7 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, goto out; for (i = 0; i < arg_obj->properties->count; i++) - if (arg_obj->properties->ids[i] == arg->prop_id) + if (arg_obj->properties->properties[i]->base.id == arg->prop_id) break; if (i == arg_obj->properties->count) diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index fd8139ca629a52..265f90afcac4dd 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -64,7 +64,12 @@ struct drm_mode_object { #define DRM_OBJECT_MAX_PROPERTY 24 struct drm_object_properties { int count; - uint32_t ids[DRM_OBJECT_MAX_PROPERTY]; + /* NOTE: if we ever start dynamically destroying properties (ie. + * not at drm_mode_config_cleanup() time), then we'd have to do + * a better job of detaching property from mode objects to avoid + * dangling property pointers: + */ + struct drm_property *properties[DRM_OBJECT_MAX_PROPERTY]; uint64_t values[DRM_OBJECT_MAX_PROPERTY]; }; From 22b8b13b6f436ffbb6e540f5f8039b1084a72794 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 16 Dec 2014 18:05:31 -0500 Subject: [PATCH 0219/3023] drm: get rid of direct property value access For atomic drivers, we won't use the values array but instead shunt things off to obj->atomic_get_property(). So to simplify things make all read/write of properties values go through the accessors. Signed-off-by: Rob Clark Reviewed-by: Sean Paul Reviewed-by: Daniel Vetter Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 19 +++++++++++++++---- include/drm/drm_crtc.h | 3 +++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 2780a088051e45..481bb2598b62ff 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2106,12 +2106,17 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, prop_values = (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr); for (i = 0; i < connector->properties.count; i++) { struct drm_property *prop = connector->properties.properties[i]; + uint64_t val; + + ret = drm_object_property_get_value(&connector->base, prop, &val); + if (ret) + goto out; + if (put_user(prop->base.id, prop_ptr + copied)) { ret = -EFAULT; goto out; } - if (put_user(connector->properties.values[i], - prop_values + copied)) { + if (put_user(val, prop_values + copied)) { ret = -EFAULT; goto out; } @@ -4413,12 +4418,18 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, (arg->prop_values_ptr); for (i = 0; i < props_count; i++) { struct drm_property *prop = obj->properties->properties[i]; + uint64_t val; + + ret = drm_object_property_get_value(obj, prop, &val); + if (ret) + goto out; + if (put_user(prop->base.id, props_ptr + copied)) { ret = -EFAULT; goto out; } - if (put_user(obj->properties->values[i], - prop_values_ptr + copied)) { + + if (put_user(val, prop_values_ptr + copied)) { ret = -EFAULT; goto out; } diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 265f90afcac4dd..f7c0b7bb9d5fc8 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -70,6 +70,9 @@ struct drm_object_properties { * dangling property pointers: */ struct drm_property *properties[DRM_OBJECT_MAX_PROPERTY]; + /* do not read/write values directly, but use drm_object_property_get_value() + * and drm_object_property_set_value(): + */ uint64_t values[DRM_OBJECT_MAX_PROPERTY]; }; From 140fd38dc4962ae3694f81900b51c567df1b6d33 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Mon, 15 Dec 2014 10:11:53 -0800 Subject: [PATCH 0220/3023] drm/i915: Hold runtime PM during plane commit During plane operations, we read/write some registers that only operate properly if we're not runtime suspended. At the moment we're not holding the runtime PM reference across the whole plane operation, so there's a potential for problems. This issue was already partially addressed by commit commit d6dd6843ff4a57c662dbc378b9f99a9c034b0956 Author: Paulo Zanoni Date: Fri Aug 15 15:59:32 2014 -0300 drm/i915: fix plane/cursor handling when runtime suspended which took care of holding the runtime PM reference during the pin and fence operations for plane updates. However there are still a few actual plane registers that we also need to hold the runtime PM reference for. Recent refactoring patches in preparation for atomic have rearranged the code and made it increasingly likely that the hardware will have time to suspend between the pin/fence operation and the actual register writes. Examples of such registers are the stuff touched by ivb_get_colorkey. The solution here grabs the runtime PM reference around the 'commit' operation for planes, which should cover all the relevant register reads/writes. Note that this has only been exposed with commit 6beb8c23ebcc3d3287d8a247d11b73d7d0eaa475 Author: Matt Roper Date: Mon Dec 1 15:40:14 2014 -0800 drm/i915: Consolidate plane 'prepare' functions (v2) so doesn't need to be ported to 3.19. Cc: Paulo Zanoni Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=87180 Signed-off-by: Matt Roper Testcase: igt/pm-rpm/legacy-planes Reviewed-by: Paulo Zanoni [danvet: Augment commit message with information Paulo supplied.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0a09473e1eee8e..a1dbe747a37231 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11864,6 +11864,7 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, uint32_t src_w, uint32_t src_h) { struct drm_device *dev = plane->dev; + struct drm_i915_private *dev_priv = dev->dev_private; struct drm_framebuffer *old_fb = plane->fb; struct intel_plane_state state; struct intel_plane *intel_plane = to_intel_plane(plane); @@ -11903,7 +11904,9 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, return ret; } + intel_runtime_pm_get(dev_priv); intel_plane->commit_plane(plane, &state); + intel_runtime_pm_put(dev_priv); if (fb != old_fb && old_fb) { if (intel_crtc->active) From b46004b70367974d5318caeabfd435017adf9e2a Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 17 Dec 2014 16:41:41 +0100 Subject: [PATCH 0221/3023] drm: Move IRQ related fields to proper section The .irq and .irq_enabled fields are part of the VBLANK interrupt handling infrastructure, so move them to the appropriate section within the structure. Signed-off-by: Thierry Reding Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter --- include/drm/drmP.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 8ba35c622e2202..7cd1c681a792d3 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -744,8 +744,6 @@ struct drm_device { /** \name Context support */ /*@{ */ - bool irq_enabled; /**< True if irq handler is enabled */ - int irq; __volatile__ long context_flag; /**< Context swapping flag */ int last_context; /**< Last current context */ @@ -753,6 +751,8 @@ struct drm_device { /** \name VBLANK IRQ support */ /*@{ */ + bool irq_enabled; + int irq; /* * At load time, disabling the vblank interrupt won't be allowed since From 6d11a2f00724d52b988b5fedc6e6a050e1a46389 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 17 Dec 2014 16:41:42 +0100 Subject: [PATCH 0222/3023] drm: Make drm_crtc_helper.h standalone includible The file refers to a bunch of structure declared in drm_crtc.h, so include it to make sure the drm_crtc_helper.h header can be included standalone. Signed-off-by: Thierry Reding Signed-off-by: Daniel Vetter --- include/drm/drm_crtc_helper.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index 7adbb65ea8aeaa..8608897ace1003 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h @@ -39,6 +39,8 @@ #include +#include + enum mode_set_atomic { LEAVE_ATOMIC_MODE_SET, ENTER_ATOMIC_MODE_SET, From 7552e7dd9527c41f891c87854418896eaf309c20 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 17 Dec 2014 16:41:43 +0100 Subject: [PATCH 0223/3023] drm: Include drm_crtc_helper.h in DocBook There is already a section that describes the helpers implemented by this module. Add the kerneldoc-generated structure descriptions to this section. While at it, add missing kerneldoc for the structures to avoid warnings when generating the documentation. Signed-off-by: Thierry Reding Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter --- Documentation/DocBook/drm.tmpl | 1 + include/drm/drm_crtc_helper.h | 30 +++++++++++++++++++++++++----- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index d45b2676fbb723..7af413f6aa6f25 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -2362,6 +2362,7 @@ void intel_crt_init(struct drm_device *dev) Modeset Helper Functions Reference +!Iinclude/drm/drm_crtc_helper.h !Edrivers/gpu/drm/drm_crtc_helper.c !Pdrivers/gpu/drm/drm_crtc_helper.c overview diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index 8608897ace1003..e76828d81a8bfa 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h @@ -47,9 +47,20 @@ enum mode_set_atomic { }; /** - * drm_crtc_helper_funcs - helper operations for CRTCs - * @mode_fixup: try to fixup proposed mode for this connector + * struct drm_crtc_helper_funcs - helper operations for CRTCs + * @dpms: set power state + * @prepare: prepare the CRTC, called before @mode_set + * @commit: commit changes to CRTC, called after @mode_set + * @mode_fixup: try to fixup proposed mode for this CRTC * @mode_set: set this mode + * @mode_set_nofb: set mode only (no scanout buffer attached) + * @mode_set_base: update the scanout buffer + * @mode_set_base_atomic: non-blocking mode set (used for kgdb support) + * @load_lut: load color palette + * @disable: disable CRTC when no longer in use + * @atomic_check: check for validity of an atomic state + * @atomic_begin: begin atomic update + * @atomic_flush: flush atomic update * * The helper operations are called by the mid-layer CRTC helper. */ @@ -93,9 +104,17 @@ struct drm_crtc_helper_funcs { }; /** - * drm_encoder_helper_funcs - helper operations for encoders + * struct drm_encoder_helper_funcs - helper operations for encoders + * @dpms: set power state + * @save: save connector state + * @restore: restore connector state * @mode_fixup: try to fixup proposed mode for this connector + * @prepare: part of the disable sequence, called before the CRTC modeset + * @commit: called after the CRTC modeset * @mode_set: set this mode + * @get_crtc: return CRTC that the encoder is currently attached to + * @detect: connection status detection + * @disable: disable encoder when not in use (overrides DPMS off) * * The helper operations are called by the mid-layer CRTC helper. */ @@ -121,9 +140,10 @@ struct drm_encoder_helper_funcs { }; /** - * drm_connector_helper_funcs - helper operations for connectors + * struct drm_connector_helper_funcs - helper operations for connectors * @get_modes: get mode list for this connector - * @mode_valid (optional): is this mode valid on the given connector? + * @mode_valid: is this mode valid on the given connector? (optional) + * @best_encoder: return the preferred encoder for this connector * * The helper operations are called by the mid-layer CRTC helper. */ From 40ecc694e114a06b9ed77e3e94641b0f5490693c Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 18 Dec 2014 16:01:46 -0500 Subject: [PATCH 0224/3023] drm: add atomic_set_property wrappers As we add properties for all the standard plane/crtc/connector attributes (in preperation for the atomic ioctl), we are going to want to handle core state in core (rather than per driver). Intercepting the core properties will be easier if the atomic_set_property vfuncs are not called directly, but instead have a mandatory wrapper function (which will later serve as the point to intercept core properties). v2: more verbose comments and copypasta comment fix Signed-off-by: Rob Clark Reviewed-by: Sean Paul Reviewed-by: Daniel Vetter Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic.c | 90 +++++++++++++++++++++++++++++ drivers/gpu/drm/drm_atomic_helper.c | 12 ++-- include/drm/drm_atomic.h | 9 +++ include/drm/drm_crtc.h | 3 + 4 files changed, 108 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index cbd5e7240b6b4e..6f729d1bdea2e8 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -216,6 +216,32 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state, } EXPORT_SYMBOL(drm_atomic_get_crtc_state); +/** + * drm_atomic_crtc_set_property - set property on CRTC + * @crtc: the drm CRTC to set a property on + * @state: the state object to update with the new property value + * @property: the property to set + * @val: the new property value + * + * Use this instead of calling crtc->atomic_set_property directly. + * This function handles generic/core properties and calls out to + * driver's ->atomic_set_property() for driver properties. To ensure + * consistent behavior you must call this function rather than the + * driver hook directly. + * + * RETURNS: + * Zero on success, error code on failure + */ +int drm_atomic_crtc_set_property(struct drm_crtc *crtc, + struct drm_crtc_state *state, struct drm_property *property, + uint64_t val) +{ + if (crtc->funcs->atomic_set_property) + return crtc->funcs->atomic_set_property(crtc, state, property, val); + return -EINVAL; +} +EXPORT_SYMBOL(drm_atomic_crtc_set_property); + /** * drm_atomic_get_plane_state - get plane state * @state: global atomic state object @@ -271,6 +297,32 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state, } EXPORT_SYMBOL(drm_atomic_get_plane_state); +/** + * drm_atomic_plane_set_property - set property on plane + * @plane: the drm plane to set a property on + * @state: the state object to update with the new property value + * @property: the property to set + * @val: the new property value + * + * Use this instead of calling plane->atomic_set_property directly. + * This function handles generic/core properties and calls out to + * driver's ->atomic_set_property() for driver properties. To ensure + * consistent behavior you must call this function rather than the + * driver hook directly. + * + * RETURNS: + * Zero on success, error code on failure + */ +int drm_atomic_plane_set_property(struct drm_plane *plane, + struct drm_plane_state *state, struct drm_property *property, + uint64_t val) +{ + if (plane->funcs->atomic_set_property) + return plane->funcs->atomic_set_property(plane, state, property, val); + return -EINVAL; +} +EXPORT_SYMBOL(drm_atomic_plane_set_property); + /** * drm_atomic_get_connector_state - get connector state * @state: global atomic state object @@ -342,6 +394,44 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state, } EXPORT_SYMBOL(drm_atomic_get_connector_state); +/** + * drm_atomic_connector_set_property - set property on connector. + * @connector: the drm connector to set a property on + * @state: the state object to update with the new property value + * @property: the property to set + * @val: the new property value + * + * Use this instead of calling connector->atomic_set_property directly. + * This function handles generic/core properties and calls out to + * driver's ->atomic_set_property() for driver properties. To ensure + * consistent behavior you must call this function rather than the + * driver hook directly. + * + * RETURNS: + * Zero on success, error code on failure + */ +int drm_atomic_connector_set_property(struct drm_connector *connector, + struct drm_connector_state *state, struct drm_property *property, + uint64_t val) +{ + struct drm_device *dev = connector->dev; + struct drm_mode_config *config = &dev->mode_config; + + if (property == config->dpms_property) { + /* setting DPMS property requires special handling, which + * is done in legacy setprop path for us. Disallow (for + * now?) atomic writes to DPMS property: + */ + return -EINVAL; + } else if (connector->funcs->atomic_set_property) { + return connector->funcs->atomic_set_property(connector, + state, property, val); + } else { + return -EINVAL; + } +} +EXPORT_SYMBOL(drm_atomic_connector_set_property); + /** * drm_atomic_set_crtc_for_plane - set crtc for plane * @plane_state: the plane whose incoming state to update diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 379d37acd5b53b..57e5540259cc41 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1613,8 +1613,8 @@ drm_atomic_helper_crtc_set_property(struct drm_crtc *crtc, goto fail; } - ret = crtc->funcs->atomic_set_property(crtc, crtc_state, - property, val); + ret = drm_atomic_crtc_set_property(crtc, crtc_state, + property, val); if (ret) goto fail; @@ -1672,8 +1672,8 @@ drm_atomic_helper_plane_set_property(struct drm_plane *plane, goto fail; } - ret = plane->funcs->atomic_set_property(plane, plane_state, - property, val); + ret = drm_atomic_plane_set_property(plane, plane_state, + property, val); if (ret) goto fail; @@ -1731,8 +1731,8 @@ drm_atomic_helper_connector_set_property(struct drm_connector *connector, goto fail; } - ret = connector->funcs->atomic_set_property(connector, connector_state, - property, val); + ret = drm_atomic_connector_set_property(connector, connector_state, + property, val); if (ret) goto fail; diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index e224ccfa11ca0a..51168a8b723a2d 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -38,12 +38,21 @@ void drm_atomic_state_free(struct drm_atomic_state *state); struct drm_crtc_state * __must_check drm_atomic_get_crtc_state(struct drm_atomic_state *state, struct drm_crtc *crtc); +int drm_atomic_crtc_set_property(struct drm_crtc *crtc, + struct drm_crtc_state *state, struct drm_property *property, + uint64_t val); struct drm_plane_state * __must_check drm_atomic_get_plane_state(struct drm_atomic_state *state, struct drm_plane *plane); +int drm_atomic_plane_set_property(struct drm_plane *plane, + struct drm_plane_state *state, struct drm_property *property, + uint64_t val); struct drm_connector_state * __must_check drm_atomic_get_connector_state(struct drm_atomic_state *state, struct drm_connector *connector); +int drm_atomic_connector_set_property(struct drm_connector *connector, + struct drm_connector_state *state, struct drm_property *property, + uint64_t val); int __must_check drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index f7c0b7bb9d5fc8..7f158963ef8725 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -311,6 +311,7 @@ struct drm_crtc_state { * @atomic_duplicate_state: duplicate the atomic state for this CRTC * @atomic_destroy_state: destroy an atomic state for this CRTC * @atomic_set_property: set a property on an atomic state for this CRTC + * (do not call directly, use drm_atomic_crtc_set_property()) * * The drm_crtc_funcs structure is the central CRTC management structure * in the DRM. Each CRTC controls one or more connectors (note that the name @@ -497,6 +498,7 @@ struct drm_connector_state { * @atomic_duplicate_state: duplicate the atomic state for this connector * @atomic_destroy_state: destroy an atomic state for this connector * @atomic_set_property: set a property on an atomic state for this connector + * (do not call directly, use drm_atomic_connector_set_property()) * * Each CRTC may have one or more connectors attached to it. The functions * below allow the core DRM code to control connectors, enumerate available modes, @@ -760,6 +762,7 @@ struct drm_plane_state { * @atomic_duplicate_state: duplicate the atomic state for this plane * @atomic_destroy_state: destroy an atomic state for this plane * @atomic_set_property: set a property on an atomic state for this plane + * (do not call directly, use drm_atomic_plane_set_property()) */ struct drm_plane_funcs { int (*update_plane)(struct drm_plane *plane, From ac9c925616028f1f03f631f229bca49b3a92ce9a Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 18 Dec 2014 16:01:47 -0500 Subject: [PATCH 0225/3023] drm: add atomic_get_property Since we won't be using the obj->properties->values[] array to shadow property values for atomic drivers, we are going to need a vfunc for getting prop values. Add that along w/ mandatory wrapper fxns. v2: more comments and copypasta comment typo fix Signed-off-by: Rob Clark Reviewed-by: Sean Paul Reviewed-by: Daniel Vetter Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic.c | 88 ++++++++++++++++++++++++++++++++++++ include/drm/drm_atomic.h | 9 ++++ include/drm/drm_crtc.h | 18 ++++++++ 3 files changed, 115 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 6f729d1bdea2e8..9c4e149a61e2f7 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -242,6 +242,32 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc, } EXPORT_SYMBOL(drm_atomic_crtc_set_property); +/** + * drm_atomic_crtc_get_property - get property on CRTC + * @crtc: the drm CRTC to get a property on + * @state: the state object with the property value to read + * @property: the property to get + * @val: the property value (returned by reference) + * + * Use this instead of calling crtc->atomic_get_property directly. + * This function handles generic/core properties and calls out to + * driver's ->atomic_get_property() for driver properties. To ensure + * consistent behavior you must call this function rather than the + * driver hook directly. + * + * RETURNS: + * Zero on success, error code on failure + */ +int drm_atomic_crtc_get_property(struct drm_crtc *crtc, + const struct drm_crtc_state *state, + struct drm_property *property, uint64_t *val) +{ + if (crtc->funcs->atomic_get_property) + return crtc->funcs->atomic_get_property(crtc, state, property, val); + return -EINVAL; +} +EXPORT_SYMBOL(drm_atomic_crtc_get_property); + /** * drm_atomic_get_plane_state - get plane state * @state: global atomic state object @@ -323,6 +349,32 @@ int drm_atomic_plane_set_property(struct drm_plane *plane, } EXPORT_SYMBOL(drm_atomic_plane_set_property); +/** + * drm_atomic_plane_get_property - get property on plane + * @plane: the drm plane to get a property on + * @state: the state object with the property value to read + * @property: the property to get + * @val: the property value (returned by reference) + * + * Use this instead of calling plane->atomic_get_property directly. + * This function handles generic/core properties and calls out to + * driver's ->atomic_get_property() for driver properties. To ensure + * consistent behavior you must call this function rather than the + * driver hook directly. + * + * RETURNS: + * Zero on success, error code on failure + */ +int drm_atomic_plane_get_property(struct drm_plane *plane, + const struct drm_plane_state *state, + struct drm_property *property, uint64_t *val) +{ + if (plane->funcs->atomic_get_property) + return plane->funcs->atomic_get_property(plane, state, property, val); + return -EINVAL; +} +EXPORT_SYMBOL(drm_atomic_plane_get_property); + /** * drm_atomic_get_connector_state - get connector state * @state: global atomic state object @@ -432,6 +484,42 @@ int drm_atomic_connector_set_property(struct drm_connector *connector, } EXPORT_SYMBOL(drm_atomic_connector_set_property); +/** + * drm_atomic_connector_get_property - get property on connector + * @connector: the drm connector to get a property on + * @state: the state object with the property value to read + * @property: the property to get + * @val: the property value (returned by reference) + * + * Use this instead of calling connector->atomic_get_property directly. + * This function handles generic/core properties and calls out to + * driver's ->atomic_get_property() for driver properties. To ensure + * consistent behavior you must call this function rather than the + * driver hook directly. + * + * RETURNS: + * Zero on success, error code on failure + */ +int drm_atomic_connector_get_property(struct drm_connector *connector, + const struct drm_connector_state *state, + struct drm_property *property, uint64_t *val) +{ + struct drm_device *dev = connector->dev; + struct drm_mode_config *config = &dev->mode_config; + + if (property == config->dpms_property) { + *val = connector->dpms; + } else if (connector->funcs->atomic_get_property) { + return connector->funcs->atomic_get_property(connector, + state, property, val); + } else { + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL(drm_atomic_connector_get_property); + /** * drm_atomic_set_crtc_for_plane - set crtc for plane * @plane_state: the plane whose incoming state to update diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 51168a8b723a2d..d41233ccbc9e64 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -41,18 +41,27 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state, int drm_atomic_crtc_set_property(struct drm_crtc *crtc, struct drm_crtc_state *state, struct drm_property *property, uint64_t val); +int drm_atomic_crtc_get_property(struct drm_crtc *crtc, + const struct drm_crtc_state *state, + struct drm_property *property, uint64_t *val); struct drm_plane_state * __must_check drm_atomic_get_plane_state(struct drm_atomic_state *state, struct drm_plane *plane); int drm_atomic_plane_set_property(struct drm_plane *plane, struct drm_plane_state *state, struct drm_property *property, uint64_t val); +int drm_atomic_plane_get_property(struct drm_plane *plane, + const struct drm_plane_state *state, + struct drm_property *property, uint64_t *val); struct drm_connector_state * __must_check drm_atomic_get_connector_state(struct drm_atomic_state *state, struct drm_connector *connector); int drm_atomic_connector_set_property(struct drm_connector *connector, struct drm_connector_state *state, struct drm_property *property, uint64_t val); +int drm_atomic_connector_get_property(struct drm_connector *connector, + const struct drm_connector_state *state, + struct drm_property *property, uint64_t *val); int __must_check drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 7f158963ef8725..e1f34694fcff14 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -312,6 +312,8 @@ struct drm_crtc_state { * @atomic_destroy_state: destroy an atomic state for this CRTC * @atomic_set_property: set a property on an atomic state for this CRTC * (do not call directly, use drm_atomic_crtc_set_property()) + * @atomic_get_property: get a property on an atomic state for this CRTC + * (do not call directly, use drm_atomic_crtc_get_property()) * * The drm_crtc_funcs structure is the central CRTC management structure * in the DRM. Each CRTC controls one or more connectors (note that the name @@ -371,6 +373,10 @@ struct drm_crtc_funcs { struct drm_crtc_state *state, struct drm_property *property, uint64_t val); + int (*atomic_get_property)(struct drm_crtc *crtc, + const struct drm_crtc_state *state, + struct drm_property *property, + uint64_t *val); }; /** @@ -499,6 +505,8 @@ struct drm_connector_state { * @atomic_destroy_state: destroy an atomic state for this connector * @atomic_set_property: set a property on an atomic state for this connector * (do not call directly, use drm_atomic_connector_set_property()) + * @atomic_get_property: get a property on an atomic state for this connector + * (do not call directly, use drm_atomic_connector_get_property()) * * Each CRTC may have one or more connectors attached to it. The functions * below allow the core DRM code to control connectors, enumerate available modes, @@ -532,6 +540,10 @@ struct drm_connector_funcs { struct drm_connector_state *state, struct drm_property *property, uint64_t val); + int (*atomic_get_property)(struct drm_connector *connector, + const struct drm_connector_state *state, + struct drm_property *property, + uint64_t *val); }; /** @@ -763,6 +775,8 @@ struct drm_plane_state { * @atomic_destroy_state: destroy an atomic state for this plane * @atomic_set_property: set a property on an atomic state for this plane * (do not call directly, use drm_atomic_plane_set_property()) + * @atomic_get_property: get a property on an atomic state for this plane + * (do not call directly, use drm_atomic_plane_get_property()) */ struct drm_plane_funcs { int (*update_plane)(struct drm_plane *plane, @@ -786,6 +800,10 @@ struct drm_plane_funcs { struct drm_plane_state *state, struct drm_property *property, uint64_t val); + int (*atomic_get_property)(struct drm_plane *plane, + const struct drm_plane_state *state, + struct drm_property *property, + uint64_t *val); }; enum drm_plane_type { From ccfc08655d5fd5076828f45fb09194c070f2f63a Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 18 Dec 2014 16:01:48 -0500 Subject: [PATCH 0226/3023] drm: tweak getconnector locking We need to hold connection_mutex as we read the properties. Easiest thing is just widen the scope where connection_mutex is held. Signed-off-by: Rob Clark Reviewed-by: Sean Paul Reviewed-by: Daniel Vetter Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 303c9918a2d578..2031ead208b1e1 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2031,6 +2031,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id); mutex_lock(&dev->mode_config.mutex); + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); connector = drm_connector_find(dev, out_resp->connector_id); if (!connector) { @@ -2062,14 +2063,11 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, out_resp->mm_height = connector->display_info.height_mm; out_resp->subpixel = connector->display_info.subpixel_order; out_resp->connection = connector->status; - drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); - encoder = drm_connector_get_encoder(connector); if (encoder) out_resp->encoder_id = encoder->base.id; else out_resp->encoder_id = 0; - drm_modeset_unlock(&dev->mode_config.connection_mutex); /* * This ioctl is called twice, once to determine how much space is @@ -2135,6 +2133,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, out_resp->count_encoders = encoders_count; out: + drm_modeset_unlock(&dev->mode_config.connection_mutex); mutex_unlock(&dev->mode_config.mutex); return ret; From 95cbf110756c21397946ded181cc5ea4ab568c11 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 18 Dec 2014 16:01:49 -0500 Subject: [PATCH 0227/3023] drm: refactor getproperties/getconnector Both need to iterate a mode objects properties. Split that out into a helper shared by both ioctl handlers, since this is going to become more complicated when we add atomic properties (which will need filtering from legacy userspace). Signed-off-by: Rob Clark Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 105 +++++++++++++++---------------------- 1 file changed, 42 insertions(+), 63 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 2031ead208b1e1..f5f34d0d7c206a 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1991,6 +1991,38 @@ static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *conne return connector->encoder; } +/* helper for getconnector and getproperties ioctls */ +static int get_properties(struct drm_mode_object *obj, + uint32_t __user *prop_ptr, uint64_t __user *prop_values, + uint32_t *arg_count_props) +{ + int props_count = obj->properties->count; + int i, ret, copied = 0; + + if ((*arg_count_props >= props_count) && props_count) { + copied = 0; + for (i = 0; i < props_count; i++) { + struct drm_property *prop = obj->properties->properties[i]; + uint64_t val; + + ret = drm_object_property_get_value(obj, prop, &val); + if (ret) + return ret; + + if (put_user(prop->base.id, prop_ptr + copied)) + return -EFAULT; + + if (put_user(val, prop_values + copied)) + return -EFAULT; + + copied++; + } + } + *arg_count_props = props_count; + + return 0; +} + /** * drm_mode_getconnector - get connector configuration * @dev: drm device for the ioctl @@ -2012,15 +2044,12 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, struct drm_encoder *encoder; struct drm_display_mode *mode; int mode_count = 0; - int props_count = 0; int encoders_count = 0; int ret = 0; int copied = 0; int i; struct drm_mode_modeinfo u_mode; struct drm_mode_modeinfo __user *mode_ptr; - uint32_t __user *prop_ptr; - uint64_t __user *prop_values; uint32_t __user *encoder_ptr; if (!drm_core_check_feature(dev, DRIVER_MODESET)) @@ -2039,8 +2068,6 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, goto out; } - props_count = connector->properties.count; - for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) if (connector->encoder_ids[i] != 0) encoders_count++; @@ -2091,30 +2118,12 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, } out_resp->count_modes = mode_count; - if ((out_resp->count_props >= props_count) && props_count) { - copied = 0; - prop_ptr = (uint32_t __user *)(unsigned long)(out_resp->props_ptr); - prop_values = (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr); - for (i = 0; i < connector->properties.count; i++) { - struct drm_property *prop = connector->properties.properties[i]; - uint64_t val; - - ret = drm_object_property_get_value(&connector->base, prop, &val); - if (ret) - goto out; - - if (put_user(prop->base.id, prop_ptr + copied)) { - ret = -EFAULT; - goto out; - } - if (put_user(val, prop_values + copied)) { - ret = -EFAULT; - goto out; - } - copied++; - } - } - out_resp->count_props = props_count; + ret = get_properties(&connector->base, + (uint32_t __user *)(unsigned long)(out_resp->props_ptr), + (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr), + &out_resp->count_props); + if (ret) + goto out; if ((out_resp->count_encoders >= encoders_count) && encoders_count) { copied = 0; @@ -4388,11 +4397,6 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, struct drm_mode_obj_get_properties *arg = data; struct drm_mode_object *obj; int ret = 0; - int i; - int copied = 0; - int props_count = 0; - uint32_t __user *props_ptr; - uint64_t __user *prop_values_ptr; if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; @@ -4409,36 +4413,11 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, goto out; } - props_count = obj->properties->count; - - /* This ioctl is called twice, once to determine how much space is - * needed, and the 2nd time to fill it. */ - if ((arg->count_props >= props_count) && props_count) { - copied = 0; - props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr); - prop_values_ptr = (uint64_t __user *)(unsigned long) - (arg->prop_values_ptr); - for (i = 0; i < props_count; i++) { - struct drm_property *prop = obj->properties->properties[i]; - uint64_t val; - - ret = drm_object_property_get_value(obj, prop, &val); - if (ret) - goto out; + ret = get_properties(obj, + (uint32_t __user *)(unsigned long)(arg->props_ptr), + (uint64_t __user *)(unsigned long)(arg->prop_values_ptr), + &arg->count_props); - if (put_user(prop->base.id, props_ptr + copied)) { - ret = -EFAULT; - goto out; - } - - if (put_user(val, prop_values_ptr + copied)) { - ret = -EFAULT; - goto out; - } - copied++; - } - } - arg->count_props = props_count; out: drm_modeset_unlock_all(dev); return ret; From 0e2cfc005b376ed7b5c9a9fc466b5842fcc18cc7 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 19 Dec 2014 16:21:42 +0100 Subject: [PATCH 0228/3023] drm/i915: Update DRIVER_DATE to 20141219 Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f3185293bed1ca..387eb2d4a8ab6d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -55,7 +55,7 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20141205" +#define DRIVER_DATE "20141219" #undef WARN_ON /* Many gcc seem to no see through this and fall over :( */ From ca8bfc97ca7795f86e5b25553dd19d96b252bb29 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 25 Nov 2014 16:24:59 +0100 Subject: [PATCH 0229/3023] ARM: shmobile: kzm9g_defconfig: Update AK8975 config option CONFIG_SENSORS_AK8975 was renamed to CONFIG_AK8975 in commit 2fc72cd8354e3e9c ("iio:magnetometer:ak8975 move driver out of staging") in v3.10. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/configs/kzm9g_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/kzm9g_defconfig b/arch/arm/configs/kzm9g_defconfig index 5d63fc5d2d48c9..23e8d146dc1697 100644 --- a/arch/arm/configs/kzm9g_defconfig +++ b/arch/arm/configs/kzm9g_defconfig @@ -126,8 +126,8 @@ CONFIG_DMADEVICES=y CONFIG_SH_DMAE=y CONFIG_ASYNC_TX_DMA=y CONFIG_STAGING=y -CONFIG_SENSORS_AK8975=y CONFIG_IIO=y +CONFIG_AK8975=y # CONFIG_DNOTIFY is not set CONFIG_VFAT_FS=y CONFIG_TMPFS=y From ff550a37cda1f8ef9f383b456a9403c9e636fc9e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 4 Dec 2014 03:57:36 +0000 Subject: [PATCH 0230/3023] ARM: shmobile: defconfig: cleanup by savedefconfig Current shmobile_defconfig is not created from savedefconfig. Therefore, next defconfig patch will be unreadable. this patch tidyup this issue by below command > make shmobile_defconfig > make savedefconfig > cp defconfig ${LINUX}/arch/arm/config/shmobile_defconfig Signed-off-by: Kuninori Morimoto Acked-by: Geert Uytterhoeven [horms: Resolved conflicts; in particular leaving CONFIG_CPUFREQ_DT enabled] Signed-off-by: Simon Horman --- arch/arm/configs/shmobile_defconfig | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig index 3df6ca0c1d1fec..ad52868b4c2b00 100644 --- a/arch/arm/configs/shmobile_defconfig +++ b/arch/arm/configs/shmobile_defconfig @@ -19,7 +19,6 @@ CONFIG_ARCH_R8A7791=y CONFIG_ARCH_R8A7794=y CONFIG_MACH_LAGER=y CONFIG_MACH_MARZEN=y -# CONFIG_SWP_EMULATE is not set CONFIG_CPU_BPREDICT_DISABLE=y CONFIG_PL310_ERRATA_588369=y CONFIG_ARM_ERRATA_754322=y @@ -36,6 +35,13 @@ CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_ARM_APPENDED_DTB=y CONFIG_KEXEC=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPUFREQ_DT=y CONFIG_VFP=y CONFIG_NEON=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set @@ -98,9 +104,10 @@ CONFIG_GPIO_EM=y CONFIG_GPIO_RCAR=y # CONFIG_HWMON is not set CONFIG_THERMAL=y +CONFIG_CPU_THERMAL=y CONFIG_RCAR_THERMAL=y CONFIG_REGULATOR=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_DA9210=y CONFIG_REGULATOR_GPIO=y CONFIG_MEDIA_SUPPORT=y CONFIG_MEDIA_CAMERA_SUPPORT=y @@ -154,7 +161,6 @@ CONFIG_PWM_RENESAS_TPU=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y -CONFIG_CONFIGFS_FS=y # CONFIG_MISC_FILESYSTEMS is not set CONFIG_NFS_FS=y CONFIG_NFS_V3_ACL=y @@ -166,16 +172,3 @@ CONFIG_NLS_ISO8859_1=y # CONFIG_ENABLE_WARN_DEPRECATED is not set # CONFIG_ENABLE_MUST_CHECK is not set # CONFIG_ARM_UNWIND is not set -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_GOV_COMMON=y -CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_FREQ_STAT_DETAILS=y -CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_CPU_THERMAL=y -CONFIG_CPUFREQ_DT=y -CONFIG_REGULATOR_DA9210=y From 1df3396bd09baf4093f82a49f8a1a523277fdf82 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 4 Dec 2014 03:57:50 +0000 Subject: [PATCH 0231/3023] ARM: shmobile: defconfig: add MTD_BLOCK MTD_BLOOK is needed for accessing to SPI-FLASH Signed-off-by: Kuninori Morimoto Reported-by: Cao Minh Hiep Reported-by: Bui Duc Phuc ( Fukuda ) Reported-by: Nguyen Xuan Nui Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/configs/shmobile_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig index ad52868b4c2b00..a936a2ea8621e4 100644 --- a/arch/arm/configs/shmobile_defconfig +++ b/arch/arm/configs/shmobile_defconfig @@ -56,6 +56,7 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y CONFIG_MTD=y +CONFIG_MTD_BLOCK=y CONFIG_MTD_M25P80=y CONFIG_MTD_SPI_NOR=y CONFIG_EEPROM_AT24=y From 174b7a54c925a068161222fadb45732453bd7efa Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 8 Dec 2014 12:35:24 +0100 Subject: [PATCH 0232/3023] ARM: shmobile: Enable MICREL_PHY in shmobile_defconfig commit 1c9106cb783cd227 ("ARM: shmobile: lager-reference: DTS-only board support"), dropped the MACH_LAGER Kconfig section, which did "select MICREL_PHY if SH_ETH". Hence we now have to enable MICREL_PHY explicitly in shmobile_defconfig. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/configs/shmobile_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig index a936a2ea8621e4..a9a1b0afc691da 100644 --- a/arch/arm/configs/shmobile_defconfig +++ b/arch/arm/configs/shmobile_defconfig @@ -80,6 +80,7 @@ CONFIG_SMSC911X=y # CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_WIZNET is not set CONFIG_SMSC_PHY=y +CONFIG_MICREL_PHY=y # CONFIG_INPUT_MOUSEDEV_PSAUX is not set CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set From db54d850b686c2ca81c10dd3582e98ee089a0e3a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 9 Dec 2014 12:22:49 +0100 Subject: [PATCH 0233/3023] ARM: shmobile: Enable DA9063 watchdog in multiplatform defconfig This allows to restart koelsch on watchdog timeout or manual system restart request. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/configs/shmobile_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig index a9a1b0afc691da..99e122694f5e42 100644 --- a/arch/arm/configs/shmobile_defconfig +++ b/arch/arm/configs/shmobile_defconfig @@ -108,6 +108,9 @@ CONFIG_GPIO_RCAR=y CONFIG_THERMAL=y CONFIG_CPU_THERMAL=y CONFIG_RCAR_THERMAL=y +CONFIG_WATCHDOG=y +CONFIG_DA9063_WATCHDOG=y +CONFIG_MFD_DA9063=y CONFIG_REGULATOR=y CONFIG_REGULATOR_DA9210=y CONFIG_REGULATOR_GPIO=y From 5f61ffb5cfd516c62bae69535e28b0085210b3ae Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 9 Dec 2014 12:24:59 +0100 Subject: [PATCH 0234/3023] ARM: shmobile: genmai dts: Replace status value "ok" by "okay" While the DT parsing code recognizes "ok" as a valid value for the "status" property, ePAPR v1.1 doesn't mention it in the list of valid values. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r7s72100-genmai.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/r7s72100-genmai.dts b/arch/arm/boot/dts/r7s72100-genmai.dts index 1518c5bcca33d8..a9da7a89fc4ba6 100644 --- a/arch/arm/boot/dts/r7s72100-genmai.dts +++ b/arch/arm/boot/dts/r7s72100-genmai.dts @@ -45,7 +45,7 @@ }; &mtu2 { - status = "ok"; + status = "okay"; }; &i2c2 { From 16d3b8845ef3934a0586df5662254d54785d7741 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 9 Dec 2014 12:25:00 +0100 Subject: [PATCH 0235/3023] ARM: shmobile: armadillo800eva dts: Replace status value "ok" by "okay" While the DT parsing code recognizes "ok" as a valid value for the "status" property, ePAPR v1.1 doesn't mention it in the list of valid values. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7740-armadillo800eva.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts index d4af4d86c6b03d..9bd0cb439f448d 100644 --- a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts +++ b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts @@ -172,7 +172,7 @@ pinctrl-names = "default"; phy-handle = <&phy0>; - status = "ok"; + status = "okay"; phy0: ethernet-phy@0 { reg = <0>; @@ -193,7 +193,7 @@ }; &cmt1 { - status = "ok"; + status = "okay"; }; &i2c0 { From fd7a8cbf0eec4a4f4191a22c879e2f8258257ca6 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 9 Dec 2014 12:25:01 +0100 Subject: [PATCH 0236/3023] ARM: shmobile: lager dts: Replace status value "ok" by "okay" While the DT parsing code recognizes "ok" as a valid value for the "status" property, ePAPR v1.1 doesn't mention it in the list of valid values. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7790-lager.dts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts index 636d53bb87a270..56e66bb536573c 100644 --- a/arch/arm/boot/dts/r8a7790-lager.dts +++ b/arch/arm/boot/dts/r8a7790-lager.dts @@ -355,7 +355,7 @@ phy-handle = <&phy1>; renesas,ether-link-active-low; - status = "ok"; + status = "okay"; phy1: ethernet-phy@1 { reg = <1>; @@ -366,7 +366,7 @@ }; &cmt0 { - status = "ok"; + status = "okay"; }; &mmcif1 { @@ -470,17 +470,17 @@ }; &iic0 { - status = "ok"; + status = "okay"; }; &iic1 { - status = "ok"; + status = "okay"; pinctrl-0 = <&iic1_pins>; pinctrl-names = "default"; }; &iic2 { - status = "ok"; + status = "okay"; pinctrl-0 = <&iic2_pins>; pinctrl-names = "default"; @@ -562,7 +562,7 @@ pinctrl-0 = <&vin1_pins>; pinctrl-names = "default"; - status = "ok"; + status = "okay"; port { #address-cells = <1>; From deb9eb3ea1e5fa685b53744f1ff291ee18118029 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 9 Dec 2014 12:25:02 +0100 Subject: [PATCH 0237/3023] ARM: shmobile: henninger dts: Replace status value "ok" by "okay" While the DT parsing code recognizes "ok" as a valid value for the "status" property, ePAPR v1.1 doesn't mention it in the list of valid values. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7791-henninger.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/r8a7791-henninger.dts b/arch/arm/boot/dts/r8a7791-henninger.dts index 740e38678032a7..d2ebf11f98814a 100644 --- a/arch/arm/boot/dts/r8a7791-henninger.dts +++ b/arch/arm/boot/dts/r8a7791-henninger.dts @@ -156,7 +156,7 @@ phy-handle = <&phy1>; renesas,ether-link-active-low; - status = "ok"; + status = "okay"; phy1: ethernet-phy@1 { reg = <1>; @@ -293,7 +293,7 @@ /* composite video input */ &vin0 { - status = "ok"; + status = "okay"; pinctrl-0 = <&vin0_pins>; pinctrl-names = "default"; From 815446d624f692b197ec5dde00cf341196513e03 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 9 Dec 2014 12:25:03 +0100 Subject: [PATCH 0238/3023] ARM: shmobile: koelsch dts: Replace status value "ok" by "okay" While the DT parsing code recognizes "ok" as a valid value for the "status" property, ePAPR v1.1 doesn't mention it in the list of valid values. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7791-koelsch.dts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts index 990af167c55149..e2faa62610580b 100644 --- a/arch/arm/boot/dts/r8a7791-koelsch.dts +++ b/arch/arm/boot/dts/r8a7791-koelsch.dts @@ -366,7 +366,7 @@ phy-handle = <&phy1>; renesas,ether-link-active-low; - status = "ok"; + status = "okay"; phy1: ethernet-phy@1 { reg = <1>; @@ -377,7 +377,7 @@ }; &cmt0 { - status = "ok"; + status = "okay"; }; &sata0 { @@ -563,7 +563,7 @@ /* composite video input */ &vin1 { - status = "ok"; + status = "okay"; pinctrl-0 = <&vin1_pins>; pinctrl-names = "default"; From 38e02908f3a4bf261c618893649e88bc92197566 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 9 Dec 2014 12:25:04 +0100 Subject: [PATCH 0239/3023] ARM: shmobile: alt dts: Replace status value "ok" by "okay" While the DT parsing code recognizes "ok" as a valid value for the "status" property, ePAPR v1.1 doesn't mention it in the list of valid values. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7794-alt.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/r8a7794-alt.dts b/arch/arm/boot/dts/r8a7794-alt.dts index f2cf7576bf3f5a..0d848e60507172 100644 --- a/arch/arm/boot/dts/r8a7794-alt.dts +++ b/arch/arm/boot/dts/r8a7794-alt.dts @@ -40,9 +40,9 @@ }; &cmt0 { - status = "ok"; + status = "okay"; }; &scif2 { - status = "ok"; + status = "okay"; }; From 338d1f0b5e877eae51c885da81d86b0efd6373e7 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 9 Dec 2014 12:25:05 +0100 Subject: [PATCH 0240/3023] ARM: shmobile: kzm9g-reference dts: Replace status value "ok" by "okay" While the DT parsing code recognizes "ok" as a valid value for the "status" property, ePAPR v1.1 doesn't mention it in the list of valid values. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/sh73a0-kzm9g-reference.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts b/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts index 939be1299ca6ca..863dc4c7d7f677 100644 --- a/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts +++ b/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts @@ -179,7 +179,7 @@ }; &cmt1 { - status = "ok"; + status = "okay"; }; &i2c0 { From b5c107f03b65e14a70d86654cf2427bdc7e4afe6 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 2 Dec 2014 18:35:55 +0100 Subject: [PATCH 0241/3023] ARM: shmobile: ape6evm-reference: Correct BSC bus range The address space for the r8a73a4 Bus State Controller covers the first 512 MiB, not the first 2 GiB. Correct the size in the "ranges" property to reflect this, and to no longer overlap with PCI Express Memory. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts b/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts index 84e05f713c5425..b3d8f844b57a8f 100644 --- a/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts +++ b/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts @@ -67,7 +67,7 @@ compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; - ranges = <0 0 0 0x80000000>; + ranges = <0 0 0 0x20000000>; }; }; From 9f04e56749bf6da4cb36a6bc703e584b496c26f4 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 10 Nov 2014 19:49:35 +0100 Subject: [PATCH 0242/3023] ARM: shmobile: r8a7740 dtsi: Change to using clock-indices With the addition of clock-indices in commit 8e33f91a0b84ae19 ("clk: shmobile: clk-mstp: change to using clock-indices"), we can change the DTSes to use the generic property instead of the deprecated vendor-specific property. Signed-off-by: Geert Uytterhoeven Acked-by: Kuninori Morimoto Acked-by: Laurent Pinchart Acked-by: Wolfram Sang Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7740.dtsi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/r8a7740.dtsi b/arch/arm/boot/dts/r8a7740.dtsi index a8a674bafa677f..60ca6225453678 100644 --- a/arch/arm/boot/dts/r8a7740.dtsi +++ b/arch/arm/boot/dts/r8a7740.dtsi @@ -453,7 +453,7 @@ reg = <0xe6150080 4>; clocks = <&sub_clk>, <&sub_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7740_CLK_SUBCK R8A7740_CLK_SUBCK2 >; clock-output-names = @@ -468,7 +468,7 @@ <&cpg_clocks R8A7740_CLK_HPP>, <&sub_clk>, <&cpg_clocks R8A7740_CLK_B>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7740_CLK_CEU21 R8A7740_CLK_CEU20 R8A7740_CLK_TMU0 R8A7740_CLK_LCDC1 R8A7740_CLK_IIC0 R8A7740_CLK_TMU1 R8A7740_CLK_LCDC0 @@ -489,7 +489,7 @@ <&sub_clk>, <&sub_clk>, <&sub_clk>, <&sub_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7740_CLK_SCIFA6 R8A7740_CLK_INTCA R8A7740_CLK_SCIFA7 R8A7740_CLK_DMAC1 R8A7740_CLK_DMAC2 @@ -518,7 +518,7 @@ <&cpg_clocks R8A7740_CLK_HP>, <&cpg_clocks R8A7740_CLK_HP>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7740_CLK_CMT1 R8A7740_CLK_FSI R8A7740_CLK_IIC1 R8A7740_CLK_USBF R8A7740_CLK_SDHI0 R8A7740_CLK_SDHI1 R8A7740_CLK_MMC R8A7740_CLK_GETHER R8A7740_CLK_TPU0 @@ -535,7 +535,7 @@ <&cpg_clocks R8A7740_CLK_HP>, <&cpg_clocks R8A7740_CLK_HP>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7740_CLK_USBH R8A7740_CLK_SDHI2 R8A7740_CLK_USBFUNC R8A7740_CLK_USBPHY >; From 64530fc2ce234e2ba227e24a149c73ef91dbfae5 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 10 Nov 2014 19:49:36 +0100 Subject: [PATCH 0243/3023] ARM: shmobile: r8a7779 dtsi: Change to using clock-indices With the addition of clock-indices in commit 8e33f91a0b84ae19 ("clk: shmobile: clk-mstp: change to using clock-indices"), we can change the DTSes to use the generic property instead of the deprecated vendor-specific property. Signed-off-by: Geert Uytterhoeven Acked-by: Kuninori Morimoto Acked-by: Laurent Pinchart Acked-by: Wolfram Sang Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7779.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi index ede9a29e4bc601..e3846af833e1d5 100644 --- a/arch/arm/boot/dts/r8a7779.dtsi +++ b/arch/arm/boot/dts/r8a7779.dtsi @@ -475,7 +475,7 @@ <&cpg_clocks R8A7779_CLK_P>, <&cpg_clocks R8A7779_CLK_P>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7779_CLK_HSPI R8A7779_CLK_TMU2 R8A7779_CLK_TMU1 R8A7779_CLK_TMU0 R8A7779_CLK_HSCIF1 R8A7779_CLK_HSCIF0 @@ -506,7 +506,7 @@ <&cpg_clocks R8A7779_CLK_P>, <&cpg_clocks R8A7779_CLK_S>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7779_CLK_USB01 R8A7779_CLK_USB2 R8A7779_CLK_DU R8A7779_CLK_VIN2 R8A7779_CLK_VIN1 R8A7779_CLK_VIN0 @@ -527,7 +527,7 @@ clocks = <&s4_clk>, <&s4_clk>, <&s4_clk>, <&s4_clk>, <&s4_clk>, <&s4_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7779_CLK_SDHI3 R8A7779_CLK_SDHI2 R8A7779_CLK_SDHI1 R8A7779_CLK_SDHI0 R8A7779_CLK_MMC1 R8A7779_CLK_MMC0 From b54010af0f248e238bb628ad40d0766bb9474ec6 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 10 Nov 2014 19:49:37 +0100 Subject: [PATCH 0244/3023] ARM: shmobile: r8a7790 dtsi: Change to using clock-indices With the addition of clock-indices in commit 8e33f91a0b84ae19 ("clk: shmobile: clk-mstp: change to using clock-indices"), we can change the DTSes to use the generic property instead of the deprecated vendor-specific property. Signed-off-by: Ben Dooks [geert: Extracted r8a7790-specific part, rebased, reworded] Signed-off-by: Geert Uytterhoeven Acked-by: Kuninori Morimoto Acked-by: Laurent Pinchart Acked-by: Wolfram Sang Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7790.dtsi | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index af7e255f629e32..ffeff98fa16e1c 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -1054,7 +1054,7 @@ reg = <0 0xe6150130 0 4>, <0 0xe6150030 0 4>; clocks = <&mp_clk>; #clock-cells = <1>; - renesas,clock-indices = ; + clock-indices = ; clock-output-names = "msiof0"; }; mstp1_clks: mstp1_clks@e6150134 { @@ -1065,7 +1065,7 @@ <&zs_clk>, <&zs_clk>, <&p_clk>, <&p_clk>, <&rclk_clk>, <&cp_clk>, <&zs_clk>, <&zs_clk>, <&zs_clk>, <&zs_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7790_CLK_VCP1 R8A7790_CLK_VCP0 R8A7790_CLK_VPC1 R8A7790_CLK_VPC0 R8A7790_CLK_JPU R8A7790_CLK_SSP1 R8A7790_CLK_TMU1 R8A7790_CLK_3DG R8A7790_CLK_2DDMAC @@ -1087,7 +1087,7 @@ <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>, <&zs_clk>, <&zs_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7790_CLK_SCIFA2 R8A7790_CLK_SCIFA1 R8A7790_CLK_SCIFA0 R8A7790_CLK_MSIOF2 R8A7790_CLK_SCIFB0 R8A7790_CLK_SCIFB1 R8A7790_CLK_MSIOF1 R8A7790_CLK_MSIOF3 R8A7790_CLK_SCIFB2 @@ -1106,7 +1106,7 @@ <&hp_clk>, <&mp_clk>, <&hp_clk>, <&mp_clk>, <&rclk_clk>, <&hp_clk>, <&hp_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7790_CLK_IIC2 R8A7790_CLK_TPU0 R8A7790_CLK_MMCIF1 R8A7790_CLK_SDHI3 R8A7790_CLK_SDHI2 R8A7790_CLK_SDHI1 R8A7790_CLK_SDHI0 R8A7790_CLK_MMCIF0 R8A7790_CLK_IIC0 R8A7790_CLK_PCIEC R8A7790_CLK_IIC1 R8A7790_CLK_SSUSB R8A7790_CLK_CMT1 @@ -1123,8 +1123,10 @@ reg = <0 0xe6150144 0 4>, <0 0xe615003c 0 4>; clocks = <&hp_clk>, <&hp_clk>, <&extal_clk>, <&p_clk>; #clock-cells = <1>; - renesas,clock-indices = ; + clock-indices = < + R8A7790_CLK_AUDIO_DMAC0 R8A7790_CLK_AUDIO_DMAC1 + R8A7790_CLK_THERMAL R8A7790_CLK_PWM + >; clock-output-names = "audmac0", "audmac1", "thermal", "pwm"; }; mstp7_clks: mstp7_clks@e615014c { @@ -1134,7 +1136,7 @@ <&p_clk>, <&zx_clk>, <&zx_clk>, <&zx_clk>, <&zx_clk>, <&zx_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7790_CLK_EHCI R8A7790_CLK_HSUSB R8A7790_CLK_HSCIF1 R8A7790_CLK_HSCIF0 R8A7790_CLK_SCIF1 R8A7790_CLK_SCIF0 R8A7790_CLK_DU2 R8A7790_CLK_DU1 R8A7790_CLK_DU0 @@ -1150,7 +1152,7 @@ clocks = <&zg_clk>, <&zg_clk>, <&zg_clk>, <&zg_clk>, <&p_clk>, <&zs_clk>, <&zs_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7790_CLK_VIN3 R8A7790_CLK_VIN2 R8A7790_CLK_VIN1 R8A7790_CLK_VIN0 R8A7790_CLK_ETHER R8A7790_CLK_SATA1 R8A7790_CLK_SATA0 @@ -1166,7 +1168,7 @@ <&p_clk>, <&p_clk>, <&cpg_clocks R8A7790_CLK_QSPI>, <&cp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7790_CLK_GPIO5 R8A7790_CLK_GPIO4 R8A7790_CLK_GPIO3 R8A7790_CLK_GPIO2 R8A7790_CLK_GPIO1 R8A7790_CLK_GPIO0 R8A7790_CLK_RCAN1 R8A7790_CLK_RCAN0 R8A7790_CLK_QSPI_MOD R8A7790_CLK_IICDVFS From cb0bf8512353aef2105e0ddfcc6da5bb4c91cf25 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 10 Nov 2014 19:49:38 +0100 Subject: [PATCH 0245/3023] ARM: shmobile: r8a7791 dtsi: Change to using clock-indices With the addition of clock-indices in commit 8e33f91a0b84ae19 ("clk: shmobile: clk-mstp: change to using clock-indices"), we can change the DTSes to use the generic property instead of the deprecated vendor-specific property. Signed-off-by: Ben Dooks [geert: Extracted r8a7791-specific part, rebased, reworded] Signed-off-by: Geert Uytterhoeven Acked-by: Kuninori Morimoto Acked-by: Laurent Pinchart Acked-by: Wolfram Sang Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7791.dtsi | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index 77c0beeb8d7c98..7fabea23dd6c18 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -1062,7 +1062,7 @@ reg = <0 0xe6150130 0 4>, <0 0xe6150030 0 4>; clocks = <&mp_clk>; #clock-cells = <1>; - renesas,clock-indices = ; + clock-indices = ; clock-output-names = "msiof0"; }; mstp1_clks: mstp1_clks@e6150134 { @@ -1073,7 +1073,7 @@ <&p_clk>, <&rclk_clk>, <&cp_clk>, <&zs_clk>, <&zs_clk>, <&zs_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7791_CLK_VCP0 R8A7791_CLK_VPC0 R8A7791_CLK_JPU R8A7791_CLK_SSP1 R8A7791_CLK_TMU1 R8A7791_CLK_3DG R8A7791_CLK_2DDMAC R8A7791_CLK_FDP1_1 R8A7791_CLK_FDP1_0 @@ -1093,7 +1093,7 @@ <&mp_clk>, <&mp_clk>, <&mp_clk>, <&zs_clk>, <&zs_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7791_CLK_SCIFA2 R8A7791_CLK_SCIFA1 R8A7791_CLK_SCIFA0 R8A7791_CLK_MSIOF2 R8A7791_CLK_SCIFB0 R8A7791_CLK_SCIFB1 R8A7791_CLK_MSIOF1 R8A7791_CLK_SCIFB2 @@ -1111,7 +1111,7 @@ <&mmc0_clk>, <&hp_clk>, <&mp_clk>, <&hp_clk>, <&mp_clk>, <&rclk_clk>, <&hp_clk>, <&hp_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7791_CLK_TPU0 R8A7791_CLK_SDHI2 R8A7791_CLK_SDHI1 R8A7791_CLK_SDHI0 R8A7791_CLK_MMCIF0 R8A7791_CLK_IIC0 R8A7791_CLK_PCIEC R8A7791_CLK_IIC1 R8A7791_CLK_SSUSB R8A7791_CLK_CMT1 @@ -1127,8 +1127,10 @@ reg = <0 0xe6150144 0 4>, <0 0xe615003c 0 4>; clocks = <&hp_clk>, <&hp_clk>, <&extal_clk>, <&p_clk>; #clock-cells = <1>; - renesas,clock-indices = ; + clock-indices = < + R8A7791_CLK_AUDIO_DMAC0 R8A7791_CLK_AUDIO_DMAC1 + R8A7791_CLK_THERMAL R8A7791_CLK_PWM + >; clock-output-names = "audmac0", "audmac1", "thermal", "pwm"; }; mstp7_clks: mstp7_clks@e615014c { @@ -1138,7 +1140,7 @@ <&zs_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&zx_clk>, <&zx_clk>, <&zx_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7791_CLK_EHCI R8A7791_CLK_HSUSB R8A7791_CLK_HSCIF2 R8A7791_CLK_SCIF5 R8A7791_CLK_SCIF4 R8A7791_CLK_HSCIF1 R8A7791_CLK_HSCIF0 R8A7791_CLK_SCIF3 R8A7791_CLK_SCIF2 R8A7791_CLK_SCIF1 @@ -1155,7 +1157,7 @@ clocks = <&zg_clk>, <&zg_clk>, <&zg_clk>, <&p_clk>, <&zs_clk>, <&zs_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7791_CLK_VIN2 R8A7791_CLK_VIN1 R8A7791_CLK_VIN0 R8A7791_CLK_ETHER R8A7791_CLK_SATA1 R8A7791_CLK_SATA0 >; @@ -1171,7 +1173,7 @@ <&cp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7791_CLK_GPIO7 R8A7791_CLK_GPIO6 R8A7791_CLK_GPIO5 R8A7791_CLK_GPIO4 R8A7791_CLK_GPIO3 R8A7791_CLK_GPIO2 R8A7791_CLK_GPIO1 R8A7791_CLK_GPIO0 R8A7791_CLK_RCAN1 R8A7791_CLK_RCAN0 R8A7791_CLK_QSPI_MOD R8A7791_CLK_I2C5 @@ -1221,7 +1223,7 @@ reg = <0 0xe615099c 0 4>, <0 0xe61509ac 0 4>; clocks = <&mp_clk>, <&mp_clk>, <&mp_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7791_CLK_SCIFA3 R8A7791_CLK_SCIFA4 R8A7791_CLK_SCIFA5 >; clock-output-names = "scifa3", "scifa4", "scifa5"; From 1045d0655704a16a736e001d3ae052829d5532b0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 10 Nov 2014 19:49:39 +0100 Subject: [PATCH 0246/3023] ARM: shmobile: r8a7794 dtsi: Change to using clock-indices With the addition of clock-indices in commit 8e33f91a0b84ae19 ("clk: shmobile: clk-mstp: change to using clock-indices"), we can change the DTSes to use the generic property instead of the deprecated vendor-specific property. Signed-off-by: Geert Uytterhoeven Acked-by: Kuninori Morimoto Acked-by: Laurent Pinchart Acked-by: Wolfram Sang Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7794.dtsi | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index 19c9de3f2a5ade..1801bb417cf91c 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -455,7 +455,7 @@ reg = <0 0xe6150130 0 4>, <0 0xe6150030 0 4>; clocks = <&mp_clk>; #clock-cells = <1>; - renesas,clock-indices = ; + clock-indices = ; clock-output-names = "msiof0"; }; mstp1_clks: mstp1_clks@e6150134 { @@ -465,7 +465,7 @@ <&zs_clk>, <&p_clk>, <&p_clk>, <&rclk_clk>, <&cp_clk>, <&zs_clk>, <&zs_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7794_CLK_VCP0 R8A7794_CLK_VPC0 R8A7794_CLK_TMU1 R8A7794_CLK_3DG R8A7794_CLK_2DDMAC R8A7794_CLK_FDP1_0 R8A7794_CLK_TMU3 R8A7794_CLK_TMU2 R8A7794_CLK_CMT0 @@ -481,7 +481,7 @@ clocks = <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7794_CLK_SCIFA2 R8A7794_CLK_SCIFA1 R8A7794_CLK_SCIFA0 R8A7794_CLK_MSIOF2 R8A7794_CLK_SCIFB0 R8A7794_CLK_SCIFB1 R8A7794_CLK_MSIOF1 R8A7794_CLK_SCIFB2 @@ -495,7 +495,7 @@ reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>; clocks = <&rclk_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7794_CLK_CMT1 >; clock-output-names = @@ -507,7 +507,7 @@ clocks = <&zs_clk>, <&p_clk>, <&p_clk>, <&zs_clk>, <&zs_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7794_CLK_HSCIF2 R8A7794_CLK_SCIF5 R8A7794_CLK_SCIF4 R8A7794_CLK_HSCIF1 R8A7794_CLK_HSCIF0 R8A7794_CLK_SCIF3 R8A7794_CLK_SCIF2 R8A7794_CLK_SCIF1 @@ -522,7 +522,7 @@ reg = <0 0xe6150990 0 4>, <0 0xe61509a0 0 4>; clocks = <&zg_clk>, <&zg_clk>, <&p_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7794_CLK_VIN1 R8A7794_CLK_VIN0 R8A7794_CLK_ETHER >; clock-output-names = @@ -533,7 +533,7 @@ reg = <0 0xe615099c 0 4>, <0 0xe61509ac 0 4>; clocks = <&mp_clk>, <&mp_clk>, <&mp_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7794_CLK_SCIFA3 R8A7794_CLK_SCIFA4 R8A7794_CLK_SCIFA5 >; clock-output-names = "scifa3", "scifa4", "scifa5"; From c7bab9f929e5176169de2cee529ec203ca7f1584 Mon Sep 17 00:00:00 2001 From: Shinobu Uehara Date: Fri, 5 Dec 2014 12:01:12 +0900 Subject: [PATCH 0247/3023] ARM: shmobile: r8a7794: Add USB clocks to device tree Signed-off-by: Shinobu Uehara [horms: resolved conflicts] Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7794.dtsi | 5 ++++- include/dt-bindings/clock/r8a7794-clock.h | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index 1801bb417cf91c..7fd40f37420735 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -504,16 +504,19 @@ mstp7_clks: mstp7_clks@e615014c { compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe615014c 0 4>, <0 0xe61501c4 0 4>; - clocks = <&zs_clk>, <&p_clk>, <&p_clk>, <&zs_clk>, + clocks = <&mp_clk>, <&mp_clk>, + <&zs_clk>, <&p_clk>, <&p_clk>, <&zs_clk>, <&zs_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>; #clock-cells = <1>; clock-indices = < + R8A7794_CLK_EHCI R8A7794_CLK_HSUSB R8A7794_CLK_HSCIF2 R8A7794_CLK_SCIF5 R8A7794_CLK_SCIF4 R8A7794_CLK_HSCIF1 R8A7794_CLK_HSCIF0 R8A7794_CLK_SCIF3 R8A7794_CLK_SCIF2 R8A7794_CLK_SCIF1 R8A7794_CLK_SCIF0 >; clock-output-names = + "ehci", "hsusb", "hscif2", "scif5", "scif4", "hscif1", "hscif0", "scif3", "scif2", "scif1", "scif0"; }; diff --git a/include/dt-bindings/clock/r8a7794-clock.h b/include/dt-bindings/clock/r8a7794-clock.h index aa9c286e60c0a3..94e2bbf7ddc129 100644 --- a/include/dt-bindings/clock/r8a7794-clock.h +++ b/include/dt-bindings/clock/r8a7794-clock.h @@ -57,6 +57,8 @@ #define R8A7794_CLK_PWM 23 /* MSTP7 */ +#define R8A7794_CLK_EHCI 3 +#define R8A7794_CLK_HSUSB 4 #define R8A7794_CLK_HSCIF2 13 #define R8A7794_CLK_SCIF5 14 #define R8A7794_CLK_SCIF4 15 From 5f950e62b476c62fd8a6549f3889e08e478252f3 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 5 Dec 2014 11:28:28 +0900 Subject: [PATCH 0248/3023] ARM: shmobile: dts: koelsch: Fix flash partition label and size Update the size and names of flash partitions to match the expectations of the loader which are as follows: "loader"---0x0000_0000-0x0008_0000 [loader program (readonly)] "user" ---0x0008_0000-0x0060_0000 [U-Boot + bootargs + dt + uImage (readonly)] "flash" ---0x0060_0000-0x0400_0000 [filesystem and free (read/write)] ["user"'s assumed breakdown] U-boot (0x0008_0000-0x000c_0000) 256KiB bootargs (0x000c_0000-0x0010_0000) 256KiB Device tree (0x0010_0000-0x0014_0000) 256KiB zImage (0x0014_0000-0x0060_0000) 4.75MiB Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7791-koelsch.dts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts index 990af167c55149..1e5f8d2b74b976 100644 --- a/arch/arm/boot/dts/r8a7791-koelsch.dts +++ b/arch/arm/boot/dts/r8a7791-koelsch.dts @@ -452,13 +452,13 @@ read-only; }; partition@80000 { - label = "bootenv"; - reg = <0x00080000 0x00080000>; + label = "user"; + reg = <0x00080000 0x00580000>; read-only; }; - partition@100000 { - label = "data"; - reg = <0x00100000 0x03f00000>; + partition@600000 { + label = "flash"; + reg = <0x00600000 0x03a00000>; }; }; }; From aa5404fc74c31491c8087a9ed546a94dee60aac1 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 27 Nov 2014 11:57:16 +0100 Subject: [PATCH 0249/3023] ARM: shmobile: r8a7791: Correct mask for GIC PPI interrupts R-Car M2-W (r8a7791) contains two Cortex-A15 cores, hence the second interrupt specifier cell for Private Peripheral Interrupts should use "GIC_CPU_MASK_SIMPLE(2)". Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7791.dtsi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index 7fabea23dd6c18..958a69b24ff432 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -78,7 +78,7 @@ <0 0xf1002000 0 0x1000>, <0 0xf1004000 0 0x2000>, <0 0xf1006000 0 0x2000>; - interrupts = <1 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; + interrupts = <1 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>; }; gpio0: gpio@e6050000 { @@ -186,10 +186,10 @@ timer { compatible = "arm,armv7-timer"; - interrupts = <1 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, - <1 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, - <1 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, - <1 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>; + interrupts = <1 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, + <1 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, + <1 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, + <1 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>; }; cmt0: timer@ffca0000 { From 00add867b802b3023b49433b9002fba79f042acc Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 27 Nov 2014 11:57:17 +0100 Subject: [PATCH 0250/3023] ARM: shmobile: r8a7794: Correct mask for GIC PPI interrupts R-Car E2 (r8a7794) contains two Cortex-A7 cores, hence the second interrupt specifier cell for Private Peripheral Interrupts should use "GIC_CPU_MASK_SIMPLE(2)". Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7794.dtsi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index 7fd40f37420735..e53765493346a2 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -47,7 +47,7 @@ <0 0xf1002000 0 0x1000>, <0 0xf1004000 0 0x2000>, <0 0xf1006000 0 0x2000>; - interrupts = <1 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; + interrupts = <1 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>; }; cmt0: timer@ffca0000 { @@ -84,10 +84,10 @@ timer { compatible = "arm,armv7-timer"; - interrupts = <1 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, - <1 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, - <1 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, - <1 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>; + interrupts = <1 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, + <1 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, + <1 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, + <1 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>; }; irqc0: interrupt-controller@e61c0000 { From 22a9b44fc17e83417fa890123a33164ea37fc10c Mon Sep 17 00:00:00 2001 From: Kazuya Mizuguchi Date: Mon, 8 Dec 2014 09:54:36 +0900 Subject: [PATCH 0251/3023] ARM: shmobile: r8a7794: Add USBDMAC[01] clocks to device tree Signed-off-by: Kazuya Mizuguchi [horms: merged per-clock patches] Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7794.dtsi | 7 ++++--- include/dt-bindings/clock/r8a7794-clock.h | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index e53765493346a2..13e4a8d7302933 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -493,13 +493,14 @@ mstp3_clks: mstp3_clks@e615013c { compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>; - clocks = <&rclk_clk>; + clocks = <&rclk_clk>, <&hp_clk>, <&hp_clk>; #clock-cells = <1>; clock-indices = < - R8A7794_CLK_CMT1 + R8A7794_CLK_CMT1 R8A7794_CLK_USBDMAC0 + R8A7794_CLK_USBDMAC1 >; clock-output-names = - "cmt1"; + "cmt1", "usbdmac0", "usbdmac1"; }; mstp7_clks: mstp7_clks@e615014c { compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; diff --git a/include/dt-bindings/clock/r8a7794-clock.h b/include/dt-bindings/clock/r8a7794-clock.h index 94e2bbf7ddc129..52492d85fea168 100644 --- a/include/dt-bindings/clock/r8a7794-clock.h +++ b/include/dt-bindings/clock/r8a7794-clock.h @@ -51,6 +51,8 @@ /* MSTP3 */ #define R8A7794_CLK_CMT1 29 +#define R8A7794_CLK_USBDMAC0 30 +#define R8A7794_CLK_USBDMAC1 31 /* MSTP5 */ #define R8A7794_CLK_THERMAL 22 From 9c5becce21af35e59c7313d3603af1d620fffd05 Mon Sep 17 00:00:00 2001 From: Hisashi Nakamura Date: Tue, 9 Dec 2014 09:37:12 +0900 Subject: [PATCH 0252/3023] ARM: shmobile: koelsch: Fix QSPI mode of SPI-Flash into mode3 In order to change into mode3, CPOL and CPHA bit of SPCMD register of QSPI is changed. Mode3 can avoid intermediate voltage. Signed-off-by: Hisashi Nakamura [horms: Updated changelog and re-ordered properties] Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7791-koelsch.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts index 1e5f8d2b74b976..691e4c635564ba 100644 --- a/arch/arm/boot/dts/r8a7791-koelsch.dts +++ b/arch/arm/boot/dts/r8a7791-koelsch.dts @@ -444,6 +444,8 @@ spi-max-frequency = <30000000>; spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; + spi-cpha; + spi-cpol; m25p,fast-read; partition@0 { From be2902416cc6f26d05a9b7308b78d093ad69062c Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 29 Oct 2014 16:46:56 +0900 Subject: [PATCH 0253/3023] ARM: shmobile: lager-reference: DTS-only board support Remove redundant C board code for Lager Multiplatform, everything is supported via DT these days anyway so it is fine to rely on the MACHINE_START in setup-r8a7790.c. Signed-off-by: Magnus Damm [Remove CONFIG_MACH_LAGER from shmobile_defconfig] Signed-off-by: Laurent Pinchart Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/configs/shmobile_defconfig | 1 - arch/arm/mach-shmobile/Kconfig | 5 --- arch/arm/mach-shmobile/Makefile | 1 - .../arm/mach-shmobile/board-lager-reference.c | 39 ------------------- 4 files changed, 46 deletions(-) delete mode 100644 arch/arm/mach-shmobile/board-lager-reference.c diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig index 3df6ca0c1d1fec..e4a6c5e9174ddc 100644 --- a/arch/arm/configs/shmobile_defconfig +++ b/arch/arm/configs/shmobile_defconfig @@ -17,7 +17,6 @@ CONFIG_ARCH_R8A7779=y CONFIG_ARCH_R8A7790=y CONFIG_ARCH_R8A7791=y CONFIG_ARCH_R8A7794=y -CONFIG_MACH_LAGER=y CONFIG_MACH_MARZEN=y # CONFIG_SWP_EMULATE is not set CONFIG_CPU_BPREDICT_DISABLE=y diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 1b4fafe524ffeb..859f391aa6e18e 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -74,11 +74,6 @@ config ARCH_R8A7794 comment "Renesas ARM SoCs Board Type" -config MACH_LAGER - bool "Lager board" - depends on ARCH_R8A7790 - select MICREL_PHY if SH_ETH - config MACH_MARZEN bool "MARZEN board" depends on ARCH_R8A7779 diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index b55cac0e5b2b21..85692c9a1cef9f 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -57,7 +57,6 @@ obj-$(CONFIG_ARCH_SH7372) += entry-intc.o sleep-sh7372.o # Board objects ifdef CONFIG_ARCH_SHMOBILE_MULTI -obj-$(CONFIG_MACH_LAGER) += board-lager-reference.o obj-$(CONFIG_MACH_MARZEN) += board-marzen-reference.o else obj-$(CONFIG_MACH_APE6EVM) += board-ape6evm.o diff --git a/arch/arm/mach-shmobile/board-lager-reference.c b/arch/arm/mach-shmobile/board-lager-reference.c deleted file mode 100644 index fa06bdba61df19..00000000000000 --- a/arch/arm/mach-shmobile/board-lager-reference.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Lager board support - Reference DT implementation - * - * Copyright (C) 2013 Renesas Solutions Corp. - * Copyright (C) 2013 Simon Horman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include - -#include - -#include "common.h" -#include "r8a7790.h" -#include "rcar-gen2.h" - -static const char *lager_boards_compat_dt[] __initdata = { - "renesas,lager", - "renesas,lager-reference", - NULL, -}; - -DT_MACHINE_START(LAGER_DT, "lager") - .smp = smp_ops(r8a7790_smp_ops), - .init_early = shmobile_init_delay, - .init_time = rcar_gen2_timer_init, - .init_late = shmobile_init_late, - .reserve = rcar_gen2_reserve, - .dt_compat = lager_boards_compat_dt, -MACHINE_END From a483dcbfa21f919c7666cb897e293eff785e3bee Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 29 Oct 2014 16:47:07 +0900 Subject: [PATCH 0254/3023] ARM: shmobile: lager: Remove legacy board support Lager legacy support level is same as the DT case so remove the legacy code and force people to move over to using Multiplatform and DT. Signed-off-by: Magnus Damm [Remove lager_defconfig and don't build the dtb for legacy kernels] Signed-off-by: Laurent Pinchart Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- MAINTAINERS | 1 - arch/arm/boot/dts/Makefile | 1 - arch/arm/configs/lager_defconfig | 150 ----- arch/arm/mach-shmobile/Kconfig | 7 - arch/arm/mach-shmobile/Makefile | 1 - arch/arm/mach-shmobile/Makefile.boot | 1 - arch/arm/mach-shmobile/board-lager.c | 827 --------------------------- 7 files changed, 988 deletions(-) delete mode 100644 arch/arm/configs/lager_defconfig delete mode 100644 arch/arm/mach-shmobile/board-lager.c diff --git a/MAINTAINERS b/MAINTAINERS index ddb9ac8d32b3ed..f1f41fc48bb8e4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1395,7 +1395,6 @@ F: arch/arm/configs/ape6evm_defconfig F: arch/arm/configs/armadillo800eva_defconfig F: arch/arm/configs/bockw_defconfig F: arch/arm/configs/kzm9g_defconfig -F: arch/arm/configs/lager_defconfig F: arch/arm/configs/mackerel_defconfig F: arch/arm/configs/marzen_defconfig F: arch/arm/configs/shmobile_defconfig diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 91bd5bd628576d..19cb6fcecf89d1 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -410,7 +410,6 @@ dtb-$(CONFIG_ARCH_SHMOBILE_LEGACY) += \ r8a7778-bockw.dtb \ r8a7778-bockw-reference.dtb \ r8a7779-marzen.dtb \ - r8a7790-lager.dtb \ sh7372-mackerel.dtb \ sh73a0-kzm9g.dtb \ sh73a0-kzm9g-reference.dtb diff --git a/arch/arm/configs/lager_defconfig b/arch/arm/configs/lager_defconfig deleted file mode 100644 index a82afc916a89fa..00000000000000 --- a/arch/arm/configs/lager_defconfig +++ /dev/null @@ -1,150 +0,0 @@ -CONFIG_SYSVIPC=y -CONFIG_NO_HZ=y -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=16 -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_SYSCTL_SYSCALL=y -CONFIG_EMBEDDED=y -CONFIG_PERF_EVENTS=y -CONFIG_SLAB=y -# CONFIG_LBDAF is not set -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_IOSCHED_CFQ is not set -CONFIG_ARCH_SHMOBILE_LEGACY=y -CONFIG_ARCH_R8A7790=y -CONFIG_MACH_LAGER=y -# CONFIG_SH_TIMER_TMU is not set -# CONFIG_EM_TIMER_STI is not set -CONFIG_ARM_ERRATA_430973=y -CONFIG_ARM_ERRATA_458693=y -CONFIG_ARM_ERRATA_460075=y -CONFIG_ARM_ERRATA_743622=y -CONFIG_ARM_ERRATA_754322=y -CONFIG_PCI=y -CONFIG_PCI_RCAR_GEN2=y -CONFIG_PCI_RCAR_GEN2_PCIE=y -CONFIG_HAVE_ARM_ARCH_TIMER=y -CONFIG_AEABI=y -# CONFIG_OABI_COMPAT is not set -CONFIG_FORCE_MAX_ZONEORDER=13 -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_ARM_APPENDED_DTB=y -CONFIG_KEXEC=y -CONFIG_AUTO_ZRELADDR=y -CONFIG_VFP=y -CONFIG_NEON=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_PM=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_LRO is not set -# CONFIG_INET_DIAG is not set -# CONFIG_IPV6 is not set -# CONFIG_WIRELESS is not set -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_DEVTMPFS=y -CONFIG_DEVTMPFS_MOUNT=y -CONFIG_MTD=y -CONFIG_MTD_M25P80=y -CONFIG_MTD_SPI_NOR=y -CONFIG_BLK_DEV_SD=y -CONFIG_ATA=y -CONFIG_SATA_RCAR=y -CONFIG_NETDEVICES=y -# CONFIG_NET_CORE is not set -# CONFIG_NET_VENDOR_ARC is not set -# CONFIG_NET_CADENCE is not set -# CONFIG_NET_VENDOR_BROADCOM is not set -# CONFIG_NET_VENDOR_CIRRUS is not set -# CONFIG_NET_VENDOR_FARADAY is not set -# CONFIG_NET_VENDOR_INTEL is not set -# CONFIG_NET_VENDOR_MARVELL is not set -# CONFIG_NET_VENDOR_MICREL is not set -# CONFIG_NET_VENDOR_NATSEMI is not set -CONFIG_SH_ETH=y -# CONFIG_NET_VENDOR_SEEQ is not set -# CONFIG_NET_VENDOR_SMSC is not set -# CONFIG_NET_VENDOR_STMICRO is not set -# CONFIG_NET_VENDOR_VIA is not set -# CONFIG_NET_VENDOR_WIZNET is not set -# CONFIG_WLAN is not set -# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -CONFIG_INPUT_EVDEV=y -# CONFIG_KEYBOARD_ATKBD is not set -CONFIG_KEYBOARD_GPIO=y -# CONFIG_INPUT_MOUSE is not set -# CONFIG_SERIO is not set -# CONFIG_LEGACY_PTYS is not set -CONFIG_SERIAL_SH_SCI=y -CONFIG_SERIAL_SH_SCI_NR_UARTS=10 -CONFIG_SERIAL_SH_SCI_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_I2C_GPIO=y -CONFIG_I2C_SH_MOBILE=y -CONFIG_I2C_RCAR=y -CONFIG_SPI=y -CONFIG_SPI_RSPI=y -CONFIG_SPI_SH_MSIOF=y -CONFIG_GPIO_SH_PFC=y -CONFIG_GPIOLIB=y -CONFIG_GPIO_RCAR=y -# CONFIG_HWMON is not set -CONFIG_THERMAL=y -CONFIG_RCAR_THERMAL=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y -CONFIG_REGULATOR_DA9210=y -CONFIG_REGULATOR_GPIO=y -CONFIG_MEDIA_SUPPORT=y -CONFIG_MEDIA_CAMERA_SUPPORT=y -CONFIG_V4L_PLATFORM_DRIVERS=y -CONFIG_SOC_CAMERA=y -CONFIG_SOC_CAMERA_PLATFORM=y -CONFIG_VIDEO_RCAR_VIN=y -# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set -CONFIG_VIDEO_ADV7180=y -CONFIG_DRM=y -CONFIG_DRM_RCAR_DU=y -CONFIG_SOUND=y -CONFIG_SND=y -CONFIG_SND_SOC=y -CONFIG_SND_SOC_RCAR=y -# CONFIG_USB_SUPPORT is not set -CONFIG_MMC=y -CONFIG_MMC_SDHI=y -CONFIG_MMC_SH_MMCIF=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_GPIO=y -CONFIG_RTC_CLASS=y -CONFIG_DMADEVICES=y -CONFIG_SH_DMAE=y -# CONFIG_IOMMU_SUPPORT is not set -# CONFIG_DNOTIFY is not set -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_TMPFS=y -CONFIG_CONFIGFS_FS=y -# CONFIG_MISC_FILESYSTEMS is not set -CONFIG_NFS_FS=y -CONFIG_NFS_V3_ACL=y -CONFIG_NFS_V4=y -CONFIG_NFS_V4_1=y -CONFIG_ROOT_NFS=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_ISO8859_1=y -# CONFIG_ENABLE_WARN_DEPRECATED is not set -# CONFIG_ENABLE_MUST_CHECK is not set -# CONFIG_ARM_UNWIND is not set -# CONFIG_CRYPTO_ANSI_CPRNG is not set -# CONFIG_CRYPTO_HW is not set diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 859f391aa6e18e..d4211cba351398 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -203,13 +203,6 @@ config MACH_MARZEN select REGULATOR_FIXED_VOLTAGE if REGULATOR select USE_OF -config MACH_LAGER - bool "Lager board" - depends on ARCH_R8A7790 - select USE_OF - select MICREL_PHY if SH_ETH - select SND_SOC_AK4642 if SND_SIMPLE_CARD - config MACH_KZM9G bool "KZM-A9-GT board" depends on ARCH_SH73A0 diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index 85692c9a1cef9f..3eefe7dc74b646 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -65,7 +65,6 @@ obj-$(CONFIG_MACH_MACKEREL) += board-mackerel.o obj-$(CONFIG_MACH_BOCKW) += board-bockw.o obj-$(CONFIG_MACH_BOCKW_REFERENCE) += board-bockw-reference.o obj-$(CONFIG_MACH_MARZEN) += board-marzen.o -obj-$(CONFIG_MACH_LAGER) += board-lager.o obj-$(CONFIG_MACH_ARMADILLO800EVA) += board-armadillo800eva.o obj-$(CONFIG_MACH_KZM9G) += board-kzm9g.o obj-$(CONFIG_MACH_KZM9G_REFERENCE) += board-kzm9g-reference.o diff --git a/arch/arm/mach-shmobile/Makefile.boot b/arch/arm/mach-shmobile/Makefile.boot index 57d00ed6ec0c21..02532bea530000 100644 --- a/arch/arm/mach-shmobile/Makefile.boot +++ b/arch/arm/mach-shmobile/Makefile.boot @@ -7,7 +7,6 @@ loadaddr-$(CONFIG_MACH_BOCKW) += 0x60008000 loadaddr-$(CONFIG_MACH_BOCKW_REFERENCE) += 0x60008000 loadaddr-$(CONFIG_MACH_KZM9G) += 0x41008000 loadaddr-$(CONFIG_MACH_KZM9G_REFERENCE) += 0x41008000 -loadaddr-$(CONFIG_MACH_LAGER) += 0x40008000 loadaddr-$(CONFIG_MACH_MACKEREL) += 0x40008000 loadaddr-$(CONFIG_MACH_MARZEN) += 0x60008000 diff --git a/arch/arm/mach-shmobile/board-lager.c b/arch/arm/mach-shmobile/board-lager.c deleted file mode 100644 index f8197eb6e5669a..00000000000000 --- a/arch/arm/mach-shmobile/board-lager.c +++ /dev/null @@ -1,827 +0,0 @@ -/* - * Lager board support - * - * Copyright (C) 2013-2014 Renesas Solutions Corp. - * Copyright (C) 2013 Magnus Damm - * Copyright (C) 2014 Cogent Embedded, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "common.h" -#include "irqs.h" -#include "r8a7790.h" -#include "rcar-gen2.h" - -/* - * SSI-AK4643 - * - * SW1: 1: AK4643 - * 2: CN22 - * 3: ADV7511 - * - * this command is required when playback. - * - * # amixer set "LINEOUT Mixer DACL" on - */ - -/* - * SDHI0 (CN8) - * - * JP3: pin1 - * SW20: pin1 - - * GP5_24: 1: VDD 3.3V (defult) - * 0: VDD 0.0V - * GP5_29: 1: VccQ 3.3V (defult) - * 0: VccQ 1.8V - * - */ - -/* LEDS */ -static struct gpio_led lager_leds[] = { - { - .name = "led8", - .gpio = RCAR_GP_PIN(5, 17), - .default_state = LEDS_GPIO_DEFSTATE_ON, - }, { - .name = "led7", - .gpio = RCAR_GP_PIN(4, 23), - .default_state = LEDS_GPIO_DEFSTATE_ON, - }, { - .name = "led6", - .gpio = RCAR_GP_PIN(4, 22), - .default_state = LEDS_GPIO_DEFSTATE_ON, - }, -}; - -static const struct gpio_led_platform_data lager_leds_pdata __initconst = { - .leds = lager_leds, - .num_leds = ARRAY_SIZE(lager_leds), -}; - -/* GPIO KEY */ -#define GPIO_KEY(c, g, d, ...) \ - { .code = c, .gpio = g, .desc = d, .active_low = 1, \ - .wakeup = 1, .debounce_interval = 20 } - -static struct gpio_keys_button gpio_buttons[] = { - GPIO_KEY(KEY_4, RCAR_GP_PIN(1, 28), "SW2-pin4"), - GPIO_KEY(KEY_3, RCAR_GP_PIN(1, 26), "SW2-pin3"), - GPIO_KEY(KEY_2, RCAR_GP_PIN(1, 24), "SW2-pin2"), - GPIO_KEY(KEY_1, RCAR_GP_PIN(1, 14), "SW2-pin1"), -}; - -static const struct gpio_keys_platform_data lager_keys_pdata __initconst = { - .buttons = gpio_buttons, - .nbuttons = ARRAY_SIZE(gpio_buttons), -}; - -/* Fixed 3.3V regulator to be used by MMCIF */ -static struct regulator_consumer_supply fixed3v3_power_consumers[] = -{ - REGULATOR_SUPPLY("vmmc", "sh_mmcif.1"), -}; - -/* - * SDHI regulator macro - * - ** FIXME** - * Lager board vqmmc is provided via DA9063 PMIC chip, - * and we should use ${LINK}/drivers/mfd/da9063-* driver for it. - * but, it doesn't have regulator support at this point. - * It uses gpio-regulator for vqmmc as quick-hack. - */ -#define SDHI_REGULATOR(idx, vdd_pin, vccq_pin) \ -static struct regulator_consumer_supply vcc_sdhi##idx##_consumer = \ - REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi." #idx); \ - \ -static struct regulator_init_data vcc_sdhi##idx##_init_data = { \ - .constraints = { \ - .valid_ops_mask = REGULATOR_CHANGE_STATUS, \ - }, \ - .consumer_supplies = &vcc_sdhi##idx##_consumer, \ - .num_consumer_supplies = 1, \ -}; \ - \ -static const struct fixed_voltage_config vcc_sdhi##idx##_info __initconst = {\ - .supply_name = "SDHI" #idx "Vcc", \ - .microvolts = 3300000, \ - .gpio = vdd_pin, \ - .enable_high = 1, \ - .init_data = &vcc_sdhi##idx##_init_data, \ -}; \ - \ -static struct regulator_consumer_supply vccq_sdhi##idx##_consumer = \ - REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi." #idx); \ - \ -static struct regulator_init_data vccq_sdhi##idx##_init_data = { \ - .constraints = { \ - .input_uV = 3300000, \ - .min_uV = 1800000, \ - .max_uV = 3300000, \ - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | \ - REGULATOR_CHANGE_STATUS, \ - }, \ - .consumer_supplies = &vccq_sdhi##idx##_consumer, \ - .num_consumer_supplies = 1, \ -}; \ - \ -static struct gpio vccq_sdhi##idx##_gpio = \ - { vccq_pin, GPIOF_OUT_INIT_HIGH, "vccq-sdhi" #idx }; \ - \ -static struct gpio_regulator_state vccq_sdhi##idx##_states[] = { \ - { .value = 1800000, .gpios = 0 }, \ - { .value = 3300000, .gpios = 1 }, \ -}; \ - \ -static const struct gpio_regulator_config vccq_sdhi##idx##_info __initconst = {\ - .supply_name = "vqmmc", \ - .gpios = &vccq_sdhi##idx##_gpio, \ - .nr_gpios = 1, \ - .states = vccq_sdhi##idx##_states, \ - .nr_states = ARRAY_SIZE(vccq_sdhi##idx##_states), \ - .type = REGULATOR_VOLTAGE, \ - .init_data = &vccq_sdhi##idx##_init_data, \ -}; - -SDHI_REGULATOR(0, RCAR_GP_PIN(5, 24), RCAR_GP_PIN(5, 29)); -SDHI_REGULATOR(2, RCAR_GP_PIN(5, 25), RCAR_GP_PIN(5, 30)); - -/* MMCIF */ -static const struct sh_mmcif_plat_data mmcif1_pdata __initconst = { - .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE, - .clk_ctrl2_present = true, - .ccs_unsupported = true, -}; - -static const struct resource mmcif1_resources[] __initconst = { - DEFINE_RES_MEM(0xee220000, 0x80), - DEFINE_RES_IRQ(gic_spi(170)), -}; - -/* Ether */ -static const struct sh_eth_plat_data ether_pdata __initconst = { - .phy = 0x1, - .phy_irq = irq_pin(0), - .edmac_endian = EDMAC_LITTLE_ENDIAN, - .phy_interface = PHY_INTERFACE_MODE_RMII, - .ether_link_active_low = 1, -}; - -static const struct resource ether_resources[] __initconst = { - DEFINE_RES_MEM(0xee700000, 0x400), - DEFINE_RES_IRQ(gic_spi(162)), -}; - -static const struct platform_device_info ether_info __initconst = { - .name = "r8a7790-ether", - .id = -1, - .res = ether_resources, - .num_res = ARRAY_SIZE(ether_resources), - .data = ðer_pdata, - .size_data = sizeof(ether_pdata), - .dma_mask = DMA_BIT_MASK(32), -}; - -/* SPI Flash memory (Spansion S25FL512SAGMFIG11 64Mb) */ -static struct mtd_partition spi_flash_part[] = { - /* Reserved for user loader program, read-only */ - { - .name = "loader", - .offset = 0, - .size = SZ_256K, - .mask_flags = MTD_WRITEABLE, - }, - /* Reserved for user program, read-only */ - { - .name = "user", - .offset = MTDPART_OFS_APPEND, - .size = SZ_4M, - .mask_flags = MTD_WRITEABLE, - }, - /* All else is writable (e.g. JFFS2) */ - { - .name = "flash", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL, - .mask_flags = 0, - }, -}; - -static const struct flash_platform_data spi_flash_data = { - .name = "m25p80", - .parts = spi_flash_part, - .nr_parts = ARRAY_SIZE(spi_flash_part), - .type = "s25fl512s", -}; - -static const struct rspi_plat_data qspi_pdata __initconst = { - .num_chipselect = 1, -}; - -static const struct spi_board_info spi_info[] __initconst = { - { - .modalias = "m25p80", - .platform_data = &spi_flash_data, - .mode = SPI_MODE_0 | SPI_TX_QUAD | SPI_RX_QUAD, - .max_speed_hz = 30000000, - .bus_num = 0, - .chip_select = 0, - }, -}; - -/* QSPI resource */ -static const struct resource qspi_resources[] __initconst = { - DEFINE_RES_MEM(0xe6b10000, 0x1000), - DEFINE_RES_IRQ_NAMED(gic_spi(184), "mux"), -}; - -/* VIN */ -static const struct resource vin_resources[] __initconst = { - /* VIN0 */ - DEFINE_RES_MEM(0xe6ef0000, 0x1000), - DEFINE_RES_IRQ(gic_spi(188)), - /* VIN1 */ - DEFINE_RES_MEM(0xe6ef1000, 0x1000), - DEFINE_RES_IRQ(gic_spi(189)), -}; - -static void __init lager_add_vin_device(unsigned idx, - struct rcar_vin_platform_data *pdata) -{ - struct platform_device_info vin_info = { - .name = "r8a7790-vin", - .id = idx, - .res = &vin_resources[idx * 2], - .num_res = 2, - .dma_mask = DMA_BIT_MASK(32), - .data = pdata, - .size_data = sizeof(*pdata), - }; - - BUG_ON(idx > 1); - - platform_device_register_full(&vin_info); -} - -#define LAGER_CAMERA(idx, name, addr, pdata, flag) \ -static struct i2c_board_info i2c_cam##idx##_device = { \ - I2C_BOARD_INFO(name, addr), \ -}; \ - \ -static struct rcar_vin_platform_data vin##idx##_pdata = { \ - .flags = flag, \ -}; \ - \ -static struct soc_camera_link cam##idx##_link = { \ - .bus_id = idx, \ - .board_info = &i2c_cam##idx##_device, \ - .i2c_adapter_id = 2, \ - .module_name = name, \ - .priv = pdata, \ -} - -/* Camera 0 is not currently supported due to adv7612 support missing */ -LAGER_CAMERA(1, "adv7180", 0x20, NULL, RCAR_VIN_BT656); - -static void __init lager_add_camera1_device(void) -{ - platform_device_register_data(NULL, "soc-camera-pdrv", 1, - &cam1_link, sizeof(cam1_link)); - lager_add_vin_device(1, &vin1_pdata); -} - -/* SATA1 */ -static const struct resource sata1_resources[] __initconst = { - DEFINE_RES_MEM(0xee500000, 0x2000), - DEFINE_RES_IRQ(gic_spi(106)), -}; - -static const struct platform_device_info sata1_info __initconst = { - .name = "sata-r8a7790", - .id = 1, - .res = sata1_resources, - .num_res = ARRAY_SIZE(sata1_resources), - .dma_mask = DMA_BIT_MASK(32), -}; - -/* USBHS */ -static const struct resource usbhs_resources[] __initconst = { - DEFINE_RES_MEM(0xe6590000, 0x100), - DEFINE_RES_IRQ(gic_spi(107)), -}; - -struct usbhs_private { - struct renesas_usbhs_platform_info info; - struct usb_phy *phy; -}; - -#define usbhs_get_priv(pdev) \ - container_of(renesas_usbhs_get_info(pdev), struct usbhs_private, info) - -static int usbhs_power_ctrl(struct platform_device *pdev, - void __iomem *base, int enable) -{ - struct usbhs_private *priv = usbhs_get_priv(pdev); - - if (!priv->phy) - return -ENODEV; - - if (enable) { - int retval = usb_phy_init(priv->phy); - - if (!retval) - retval = usb_phy_set_suspend(priv->phy, 0); - return retval; - } - - usb_phy_set_suspend(priv->phy, 1); - usb_phy_shutdown(priv->phy); - return 0; -} - -static int usbhs_hardware_init(struct platform_device *pdev) -{ - struct usbhs_private *priv = usbhs_get_priv(pdev); - struct usb_phy *phy; - int ret; - - /* USB0 Function - use PWEN as GPIO input to detect DIP Switch SW5 - * setting to avoid VBUS short circuit due to wrong cable. - * PWEN should be pulled up high if USB Function is selected by SW5 - */ - gpio_request_one(RCAR_GP_PIN(5, 18), GPIOF_IN, NULL); /* USB0_PWEN */ - if (!gpio_get_value(RCAR_GP_PIN(5, 18))) { - pr_warn("Error: USB Function not selected - check SW5 + SW6\n"); - ret = -ENOTSUPP; - goto error; - } - - phy = usb_get_phy_dev(&pdev->dev, 0); - if (IS_ERR(phy)) { - ret = PTR_ERR(phy); - goto error; - } - - priv->phy = phy; - return 0; - error: - gpio_free(RCAR_GP_PIN(5, 18)); - return ret; -} - -static int usbhs_hardware_exit(struct platform_device *pdev) -{ - struct usbhs_private *priv = usbhs_get_priv(pdev); - - if (!priv->phy) - return 0; - - usb_put_phy(priv->phy); - priv->phy = NULL; - - gpio_free(RCAR_GP_PIN(5, 18)); - return 0; -} - -static int usbhs_get_id(struct platform_device *pdev) -{ - return USBHS_GADGET; -} - -static u32 lager_usbhs_pipe_type[] = { - USB_ENDPOINT_XFER_CONTROL, - USB_ENDPOINT_XFER_ISOC, - USB_ENDPOINT_XFER_ISOC, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_INT, - USB_ENDPOINT_XFER_INT, - USB_ENDPOINT_XFER_INT, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, -}; - -static struct usbhs_private usbhs_priv __initdata = { - .info = { - .platform_callback = { - .power_ctrl = usbhs_power_ctrl, - .hardware_init = usbhs_hardware_init, - .hardware_exit = usbhs_hardware_exit, - .get_id = usbhs_get_id, - }, - .driver_param = { - .buswait_bwait = 4, - .pipe_type = lager_usbhs_pipe_type, - .pipe_size = ARRAY_SIZE(lager_usbhs_pipe_type), - }, - } -}; - -static void __init lager_register_usbhs(void) -{ - usb_bind_phy("renesas_usbhs", 0, "usb_phy_rcar_gen2"); - platform_device_register_resndata(NULL, - "renesas_usbhs", -1, - usbhs_resources, - ARRAY_SIZE(usbhs_resources), - &usbhs_priv.info, - sizeof(usbhs_priv.info)); -} - -/* USBHS PHY */ -static const struct rcar_gen2_phy_platform_data usbhs_phy_pdata __initconst = { - .chan0_pci = 0, /* Channel 0 is USBHS */ - .chan2_pci = 1, /* Channel 2 is PCI USB */ -}; - -static const struct resource usbhs_phy_resources[] __initconst = { - DEFINE_RES_MEM(0xe6590100, 0x100), -}; - -/* I2C */ -static struct i2c_board_info i2c2_devices[] = { - { - I2C_BOARD_INFO("ak4643", 0x12), - } -}; - -/* Sound */ -static struct resource rsnd_resources[] __initdata = { - [RSND_GEN2_SCU] = DEFINE_RES_MEM(0xec500000, 0x1000), - [RSND_GEN2_ADG] = DEFINE_RES_MEM(0xec5a0000, 0x100), - [RSND_GEN2_SSIU] = DEFINE_RES_MEM(0xec540000, 0x1000), - [RSND_GEN2_SSI] = DEFINE_RES_MEM(0xec541000, 0x1280), -}; - -static struct rsnd_ssi_platform_info rsnd_ssi[] = { - RSND_SSI(0, gic_spi(370), 0), - RSND_SSI(0, gic_spi(371), RSND_SSI_CLK_PIN_SHARE), -}; - -static struct rsnd_src_platform_info rsnd_src[2] = { - /* no member at this point */ -}; - -static struct rsnd_dai_platform_info rsnd_dai = { - .playback = { .ssi = &rsnd_ssi[0], }, - .capture = { .ssi = &rsnd_ssi[1], }, -}; - -static struct rcar_snd_info rsnd_info = { - .flags = RSND_GEN2, - .ssi_info = rsnd_ssi, - .ssi_info_nr = ARRAY_SIZE(rsnd_ssi), - .src_info = rsnd_src, - .src_info_nr = ARRAY_SIZE(rsnd_src), - .dai_info = &rsnd_dai, - .dai_info_nr = 1, -}; - -static struct asoc_simple_card_info rsnd_card_info = { - .name = "AK4643", - .card = "SSI01-AK4643", - .codec = "ak4642-codec.2-0012", - .platform = "rcar_sound", - .daifmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM, - .cpu_dai = { - .name = "rcar_sound", - }, - .codec_dai = { - .name = "ak4642-hifi", - .sysclk = 11289600, - }, -}; - -static void __init lager_add_rsnd_device(void) -{ - struct platform_device_info cardinfo = { - .name = "asoc-simple-card", - .id = -1, - .data = &rsnd_card_info, - .size_data = sizeof(struct asoc_simple_card_info), - .dma_mask = DMA_BIT_MASK(32), - }; - - i2c_register_board_info(2, i2c2_devices, - ARRAY_SIZE(i2c2_devices)); - - platform_device_register_resndata( - NULL, "rcar_sound", -1, - rsnd_resources, ARRAY_SIZE(rsnd_resources), - &rsnd_info, sizeof(rsnd_info)); - - platform_device_register_full(&cardinfo); -} - -/* SDHI0 */ -static struct sh_mobile_sdhi_info sdhi0_info __initdata = { - .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | - MMC_CAP_POWER_OFF_CARD, - .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | - TMIO_MMC_WRPROTECT_DISABLE, -}; - -static struct resource sdhi0_resources[] __initdata = { - DEFINE_RES_MEM(0xee100000, 0x200), - DEFINE_RES_IRQ(gic_spi(165)), -}; - -/* SDHI2 */ -static struct sh_mobile_sdhi_info sdhi2_info __initdata = { - .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | - MMC_CAP_POWER_OFF_CARD, - .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | - TMIO_MMC_WRPROTECT_DISABLE, -}; - -static struct resource sdhi2_resources[] __initdata = { - DEFINE_RES_MEM(0xee140000, 0x100), - DEFINE_RES_IRQ(gic_spi(167)), -}; - -/* Internal PCI1 */ -static const struct resource pci1_resources[] __initconst = { - DEFINE_RES_MEM(0xee0b0000, 0x10000), /* CFG */ - DEFINE_RES_MEM(0xee0a0000, 0x10000), /* MEM */ - DEFINE_RES_IRQ(gic_spi(112)), -}; - -static const struct platform_device_info pci1_info __initconst = { - .name = "pci-rcar-gen2", - .id = 1, - .res = pci1_resources, - .num_res = ARRAY_SIZE(pci1_resources), - .dma_mask = DMA_BIT_MASK(32), -}; - -static void __init lager_add_usb1_device(void) -{ - platform_device_register_full(&pci1_info); -} - -/* Internal PCI2 */ -static const struct resource pci2_resources[] __initconst = { - DEFINE_RES_MEM(0xee0d0000, 0x10000), /* CFG */ - DEFINE_RES_MEM(0xee0c0000, 0x10000), /* MEM */ - DEFINE_RES_IRQ(gic_spi(113)), -}; - -static const struct platform_device_info pci2_info __initconst = { - .name = "pci-rcar-gen2", - .id = 2, - .res = pci2_resources, - .num_res = ARRAY_SIZE(pci2_resources), - .dma_mask = DMA_BIT_MASK(32), -}; - -static void __init lager_add_usb2_device(void) -{ - platform_device_register_full(&pci2_info); -} - -static const struct pinctrl_map lager_pinctrl_map[] = { - /* DU (CN10: ARGB0, CN13: LVDS) */ - PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7790", "pfc-r8a7790", - "du_rgb666", "du"), - PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7790", "pfc-r8a7790", - "du_sync_1", "du"), - PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7790", "pfc-r8a7790", - "du_clk_out_0", "du"), - /* I2C2 */ - PIN_MAP_MUX_GROUP_DEFAULT("i2c-rcar.2", "pfc-r8a7790", - "i2c2", "i2c2"), - /* QSPI */ - PIN_MAP_MUX_GROUP_DEFAULT("qspi.0", "pfc-r8a7790", - "qspi_ctrl", "qspi"), - PIN_MAP_MUX_GROUP_DEFAULT("qspi.0", "pfc-r8a7790", - "qspi_data4", "qspi"), - /* SCIF0 (CN19: DEBUG SERIAL0) */ - PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.6", "pfc-r8a7790", - "scif0_data", "scif0"), - /* SCIF1 (CN20: DEBUG SERIAL1) */ - PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.7", "pfc-r8a7790", - "scif1_data", "scif1"), - /* SDHI0 */ - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7790", - "sdhi0_data4", "sdhi0"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7790", - "sdhi0_ctrl", "sdhi0"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7790", - "sdhi0_cd", "sdhi0"), - /* SDHI2 */ - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-r8a7790", - "sdhi2_data4", "sdhi2"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-r8a7790", - "sdhi2_ctrl", "sdhi2"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-r8a7790", - "sdhi2_cd", "sdhi2"), - /* SSI (CN17: sound) */ - PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7790", - "ssi0129_ctrl", "ssi"), - PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7790", - "ssi0_data", "ssi"), - PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7790", - "ssi1_data", "ssi"), - PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7790", - "audio_clk_a", "audio_clk"), - /* MMCIF1 */ - PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.1", "pfc-r8a7790", - "mmc1_data8", "mmc1"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.1", "pfc-r8a7790", - "mmc1_ctrl", "mmc1"), - /* Ether */ - PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-ether", "pfc-r8a7790", - "eth_link", "eth"), - PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-ether", "pfc-r8a7790", - "eth_mdio", "eth"), - PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-ether", "pfc-r8a7790", - "eth_rmii", "eth"), - PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-ether", "pfc-r8a7790", - "intc_irq0", "intc"), - /* VIN0 */ - PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.0", "pfc-r8a7790", - "vin0_data24", "vin0"), - PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.0", "pfc-r8a7790", - "vin0_sync", "vin0"), - PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.0", "pfc-r8a7790", - "vin0_field", "vin0"), - PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.0", "pfc-r8a7790", - "vin0_clkenb", "vin0"), - PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.0", "pfc-r8a7790", - "vin0_clk", "vin0"), - /* VIN1 */ - PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.1", "pfc-r8a7790", - "vin1_data8", "vin1"), - PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.1", "pfc-r8a7790", - "vin1_clk", "vin1"), - /* USB0 */ - PIN_MAP_MUX_GROUP_DEFAULT("renesas_usbhs", "pfc-r8a7790", - "usb0_ovc_vbus", "usb0"), - /* USB1 */ - PIN_MAP_MUX_GROUP_DEFAULT("pci-rcar-gen2.1", "pfc-r8a7790", - "usb1", "usb1"), - /* USB2 */ - PIN_MAP_MUX_GROUP_DEFAULT("pci-rcar-gen2.2", "pfc-r8a7790", - "usb2", "usb2"), -}; - -static void __init lager_add_standard_devices(void) -{ - int fixed_regulator_idx = 0; - int gpio_regulator_idx = 0; - - r8a7790_clock_init(); - - pinctrl_register_mappings(lager_pinctrl_map, - ARRAY_SIZE(lager_pinctrl_map)); - r8a7790_pinmux_init(); - - r8a7790_add_standard_devices(); - platform_device_register_data(NULL, "leds-gpio", -1, - &lager_leds_pdata, - sizeof(lager_leds_pdata)); - platform_device_register_data(NULL, "gpio-keys", -1, - &lager_keys_pdata, - sizeof(lager_keys_pdata)); - regulator_register_always_on(fixed_regulator_idx++, - "fixed-3.3V", fixed3v3_power_consumers, - ARRAY_SIZE(fixed3v3_power_consumers), 3300000); - platform_device_register_resndata(NULL, "sh_mmcif", 1, - mmcif1_resources, ARRAY_SIZE(mmcif1_resources), - &mmcif1_pdata, sizeof(mmcif1_pdata)); - - platform_device_register_full(ðer_info); - - platform_device_register_resndata(NULL, "qspi", 0, - qspi_resources, - ARRAY_SIZE(qspi_resources), - &qspi_pdata, sizeof(qspi_pdata)); - spi_register_board_info(spi_info, ARRAY_SIZE(spi_info)); - - platform_device_register_data(NULL, "reg-fixed-voltage", fixed_regulator_idx++, - &vcc_sdhi0_info, sizeof(struct fixed_voltage_config)); - platform_device_register_data(NULL, "reg-fixed-voltage", fixed_regulator_idx++, - &vcc_sdhi2_info, sizeof(struct fixed_voltage_config)); - - platform_device_register_data(NULL, "gpio-regulator", gpio_regulator_idx++, - &vccq_sdhi0_info, sizeof(struct gpio_regulator_config)); - platform_device_register_data(NULL, "gpio-regulator", gpio_regulator_idx++, - &vccq_sdhi2_info, sizeof(struct gpio_regulator_config)); - - lager_add_camera1_device(); - - platform_device_register_full(&sata1_info); - - platform_device_register_resndata(NULL, "usb_phy_rcar_gen2", - -1, usbhs_phy_resources, - ARRAY_SIZE(usbhs_phy_resources), - &usbhs_phy_pdata, - sizeof(usbhs_phy_pdata)); - lager_register_usbhs(); - lager_add_usb1_device(); - lager_add_usb2_device(); - - lager_add_rsnd_device(); - - platform_device_register_resndata(NULL, "sh_mobile_sdhi", 0, - sdhi0_resources, ARRAY_SIZE(sdhi0_resources), - &sdhi0_info, sizeof(struct sh_mobile_sdhi_info)); - platform_device_register_resndata(NULL, "sh_mobile_sdhi", 2, - sdhi2_resources, ARRAY_SIZE(sdhi2_resources), - &sdhi2_info, sizeof(struct sh_mobile_sdhi_info)); -} - -/* - * Ether LEDs on the Lager board are named LINK and ACTIVE which corresponds - * to non-default 01 setting of the Micrel KSZ8041 PHY control register 1 bits - * 14-15. We have to set them back to 01 from the default 00 value each time - * the PHY is reset. It's also important because the PHY's LED0 signal is - * connected to SoC's ETH_LINK signal and in the PHY's default mode it will - * bounce on and off after each packet, which we apparently want to avoid. - */ -static int lager_ksz8041_fixup(struct phy_device *phydev) -{ - u16 phyctrl1 = phy_read(phydev, 0x1e); - - phyctrl1 &= ~0xc000; - phyctrl1 |= 0x4000; - return phy_write(phydev, 0x1e, phyctrl1); -} - -static void __init lager_init(void) -{ - lager_add_standard_devices(); - - irq_set_irq_type(irq_pin(0), IRQ_TYPE_LEVEL_LOW); - - if (IS_ENABLED(CONFIG_PHYLIB)) - phy_register_fixup_for_id("r8a7790-ether-ff:01", - lager_ksz8041_fixup); -} - -static const char * const lager_boards_compat_dt[] __initconst = { - "renesas,lager", - NULL, -}; - -DT_MACHINE_START(LAGER_DT, "lager") - .smp = smp_ops(r8a7790_smp_ops), - .init_early = shmobile_init_delay, - .init_time = rcar_gen2_timer_init, - .init_machine = lager_init, - .init_late = shmobile_init_late, - .reserve = rcar_gen2_reserve, - .dt_compat = lager_boards_compat_dt, -MACHINE_END From e042681894b62d60f3a8704999d7700ebcdb9117 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 2 Dec 2014 18:00:56 +0200 Subject: [PATCH 0255/3023] ARM: shmobile: r8a7790: Remove legacy code All r8a7790 boards are now used with multiplatform kernels only. We can remove all the unused r8a7790 legacy device and clock registration code. Signed-off-by: Laurent Pinchart Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/Kconfig | 8 - arch/arm/mach-shmobile/Makefile | 1 - arch/arm/mach-shmobile/clock-r8a7790.c | 459 ------------------------- arch/arm/mach-shmobile/r8a7790.h | 28 -- arch/arm/mach-shmobile/setup-r8a7790.c | 284 +-------------- 5 files changed, 1 insertion(+), 779 deletions(-) delete mode 100644 arch/arm/mach-shmobile/clock-r8a7790.c diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index d4211cba351398..bb3d07504d8bce 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -128,14 +128,6 @@ config ARCH_R8A7779 select ARCH_WANT_OPTIONAL_GPIOLIB select ARM_GIC -config ARCH_R8A7790 - bool "R-Car H2 (R8A77900)" - select ARCH_RCAR_GEN2 - select ARCH_WANT_OPTIONAL_GPIOLIB - select ARM_GIC - select MIGHT_HAVE_PCI - select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE - comment "Renesas ARM SoCs Board Type" config MACH_APE6EVM diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index 3eefe7dc74b646..d53996e6da970d 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -27,7 +27,6 @@ obj-$(CONFIG_ARCH_R8A73A4) += clock-r8a73a4.o obj-$(CONFIG_ARCH_R8A7740) += clock-r8a7740.o obj-$(CONFIG_ARCH_R8A7778) += clock-r8a7778.o obj-$(CONFIG_ARCH_R8A7779) += clock-r8a7779.o -obj-$(CONFIG_ARCH_R8A7790) += clock-r8a7790.o endif # CPU reset vector handling objects diff --git a/arch/arm/mach-shmobile/clock-r8a7790.c b/arch/arm/mach-shmobile/clock-r8a7790.c deleted file mode 100644 index f9bbc5f0a9a12a..00000000000000 --- a/arch/arm/mach-shmobile/clock-r8a7790.c +++ /dev/null @@ -1,459 +0,0 @@ -/* - * r8a7790 clock framework support - * - * Copyright (C) 2013 Renesas Solutions Corp. - * Copyright (C) 2013 Magnus Damm - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#include -#include -#include -#include -#include - -#include "clock.h" -#include "common.h" -#include "r8a7790.h" -#include "rcar-gen2.h" - -/* - * MD EXTAL PLL0 PLL1 PLL3 - * 14 13 19 (MHz) *1 *1 - *--------------------------------------------------- - * 0 0 0 15 x 1 x172/2 x208/2 x106 - * 0 0 1 15 x 1 x172/2 x208/2 x88 - * 0 1 0 20 x 1 x130/2 x156/2 x80 - * 0 1 1 20 x 1 x130/2 x156/2 x66 - * 1 0 0 26 / 2 x200/2 x240/2 x122 - * 1 0 1 26 / 2 x200/2 x240/2 x102 - * 1 1 0 30 / 2 x172/2 x208/2 x106 - * 1 1 1 30 / 2 x172/2 x208/2 x88 - * - * *1 : Table 7.6 indicates VCO ouput (PLLx = VCO/2) - * see "p1 / 2" on R8A7790_CLOCK_ROOT() below - */ - -#define CPG_BASE 0xe6150000 -#define CPG_LEN 0x1000 - -#define SMSTPCR1 0xe6150134 -#define SMSTPCR2 0xe6150138 -#define SMSTPCR3 0xe615013c -#define SMSTPCR5 0xe6150144 -#define SMSTPCR7 0xe615014c -#define SMSTPCR8 0xe6150990 -#define SMSTPCR9 0xe6150994 -#define SMSTPCR10 0xe6150998 - -#define MSTPSR1 IOMEM(0xe6150038) -#define MSTPSR2 IOMEM(0xe6150040) -#define MSTPSR3 IOMEM(0xe6150048) -#define MSTPSR5 IOMEM(0xe615003c) -#define MSTPSR7 IOMEM(0xe61501c4) -#define MSTPSR8 IOMEM(0xe61509a0) -#define MSTPSR9 IOMEM(0xe61509a4) -#define MSTPSR10 IOMEM(0xe61509a8) - -#define SDCKCR 0xE6150074 -#define SD2CKCR 0xE6150078 -#define SD3CKCR 0xE615026C -#define MMC0CKCR 0xE6150240 -#define MMC1CKCR 0xE6150244 -#define SSPCKCR 0xE6150248 -#define SSPRSCKCR 0xE615024C - -static struct clk_mapping cpg_mapping = { - .phys = CPG_BASE, - .len = CPG_LEN, -}; - -static struct clk extal_clk = { - /* .rate will be updated on r8a7790_clock_init() */ - .mapping = &cpg_mapping, -}; - -static struct sh_clk_ops followparent_clk_ops = { - .recalc = followparent_recalc, -}; - -static struct clk main_clk = { - /* .parent will be set r8a7790_clock_init */ - .ops = &followparent_clk_ops, -}; - -static struct clk audio_clk_a = { -}; - -static struct clk audio_clk_b = { -}; - -static struct clk audio_clk_c = { -}; - -/* - * clock ratio of these clock will be updated - * on r8a7790_clock_init() - */ -SH_FIXED_RATIO_CLK_SET(pll1_clk, main_clk, 1, 1); -SH_FIXED_RATIO_CLK_SET(pll3_clk, main_clk, 1, 1); -SH_FIXED_RATIO_CLK_SET(lb_clk, pll1_clk, 1, 1); -SH_FIXED_RATIO_CLK_SET(qspi_clk, pll1_clk, 1, 1); - -/* fixed ratio clock */ -SH_FIXED_RATIO_CLK_SET(extal_div2_clk, extal_clk, 1, 2); -SH_FIXED_RATIO_CLK_SET(cp_clk, extal_clk, 1, 2); - -SH_FIXED_RATIO_CLK_SET(pll1_div2_clk, pll1_clk, 1, 2); -SH_FIXED_RATIO_CLK_SET(zg_clk, pll1_clk, 1, 3); -SH_FIXED_RATIO_CLK_SET(zx_clk, pll1_clk, 1, 3); -SH_FIXED_RATIO_CLK_SET(zs_clk, pll1_clk, 1, 6); -SH_FIXED_RATIO_CLK_SET(hp_clk, pll1_clk, 1, 12); -SH_FIXED_RATIO_CLK_SET(i_clk, pll1_clk, 1, 2); -SH_FIXED_RATIO_CLK_SET(b_clk, pll1_clk, 1, 12); -SH_FIXED_RATIO_CLK_SET(p_clk, pll1_clk, 1, 24); -SH_FIXED_RATIO_CLK_SET(cl_clk, pll1_clk, 1, 48); -SH_FIXED_RATIO_CLK_SET(m2_clk, pll1_clk, 1, 8); -SH_FIXED_RATIO_CLK_SET(imp_clk, pll1_clk, 1, 4); -SH_FIXED_RATIO_CLK_SET(rclk_clk, pll1_clk, 1, (48 * 1024)); -SH_FIXED_RATIO_CLK_SET(oscclk_clk, pll1_clk, 1, (12 * 1024)); - -SH_FIXED_RATIO_CLK_SET(zb3_clk, pll3_clk, 1, 4); -SH_FIXED_RATIO_CLK_SET(zb3d2_clk, pll3_clk, 1, 8); -SH_FIXED_RATIO_CLK_SET(ddr_clk, pll3_clk, 1, 8); -SH_FIXED_RATIO_CLK_SET(mp_clk, pll1_div2_clk, 1, 15); - -static struct clk *main_clks[] = { - &audio_clk_a, - &audio_clk_b, - &audio_clk_c, - &extal_clk, - &extal_div2_clk, - &main_clk, - &pll1_clk, - &pll1_div2_clk, - &pll3_clk, - &lb_clk, - &qspi_clk, - &zg_clk, - &zx_clk, - &zs_clk, - &hp_clk, - &i_clk, - &b_clk, - &p_clk, - &cl_clk, - &m2_clk, - &imp_clk, - &rclk_clk, - &oscclk_clk, - &zb3_clk, - &zb3d2_clk, - &ddr_clk, - &mp_clk, - &cp_clk, -}; - -/* SDHI (DIV4) clock */ -static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18, 24, 0, 36, 48, 10 }; - -static struct clk_div_mult_table div4_div_mult_table = { - .divisors = divisors, - .nr_divisors = ARRAY_SIZE(divisors), -}; - -static struct clk_div4_table div4_table = { - .div_mult_table = &div4_div_mult_table, -}; - -enum { - DIV4_SDH, DIV4_SD0, DIV4_SD1, DIV4_NR -}; - -static struct clk div4_clks[DIV4_NR] = { - [DIV4_SDH] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 8, 0x0dff, CLK_ENABLE_ON_INIT), - [DIV4_SD0] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 4, 0x1df0, CLK_ENABLE_ON_INIT), - [DIV4_SD1] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 0, 0x1df0, CLK_ENABLE_ON_INIT), -}; - -/* DIV6 clocks */ -enum { - DIV6_SD2, DIV6_SD3, - DIV6_MMC0, DIV6_MMC1, - DIV6_SSP, DIV6_SSPRS, - DIV6_NR -}; - -static struct clk div6_clks[DIV6_NR] = { - [DIV6_SD2] = SH_CLK_DIV6(&pll1_div2_clk, SD2CKCR, 0), - [DIV6_SD3] = SH_CLK_DIV6(&pll1_div2_clk, SD3CKCR, 0), - [DIV6_MMC0] = SH_CLK_DIV6(&pll1_div2_clk, MMC0CKCR, 0), - [DIV6_MMC1] = SH_CLK_DIV6(&pll1_div2_clk, MMC1CKCR, 0), - [DIV6_SSP] = SH_CLK_DIV6(&pll1_div2_clk, SSPCKCR, 0), - [DIV6_SSPRS] = SH_CLK_DIV6(&pll1_div2_clk, SSPRSCKCR, 0), -}; - -/* MSTP */ -enum { - MSTP1017, /* parent of SCU */ - - MSTP1031, MSTP1030, - MSTP1029, MSTP1028, MSTP1027, MSTP1026, MSTP1025, MSTP1024, MSTP1023, MSTP1022, - MSTP1015, MSTP1014, MSTP1013, MSTP1012, MSTP1011, MSTP1010, - MSTP1009, MSTP1008, MSTP1007, MSTP1006, MSTP1005, - MSTP931, MSTP930, MSTP929, MSTP928, - MSTP917, - MSTP815, MSTP814, - MSTP813, - MSTP811, MSTP810, MSTP809, MSTP808, - MSTP726, MSTP725, MSTP724, MSTP723, MSTP722, MSTP721, MSTP720, - MSTP717, MSTP716, - MSTP704, MSTP703, - MSTP522, - MSTP502, MSTP501, - MSTP315, MSTP314, MSTP313, MSTP312, MSTP311, MSTP305, MSTP304, - MSTP216, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, - MSTP124, - MSTP_NR -}; - -static struct clk mstp_clks[MSTP_NR] = { - [MSTP1031] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 31, MSTPSR10, 0), /* SCU0 */ - [MSTP1030] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 30, MSTPSR10, 0), /* SCU1 */ - [MSTP1029] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 29, MSTPSR10, 0), /* SCU2 */ - [MSTP1028] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 28, MSTPSR10, 0), /* SCU3 */ - [MSTP1027] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 27, MSTPSR10, 0), /* SCU4 */ - [MSTP1026] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 26, MSTPSR10, 0), /* SCU5 */ - [MSTP1025] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 25, MSTPSR10, 0), /* SCU6 */ - [MSTP1024] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 24, MSTPSR10, 0), /* SCU7 */ - [MSTP1023] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 23, MSTPSR10, 0), /* SCU8 */ - [MSTP1022] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 22, MSTPSR10, 0), /* SCU9 */ - [MSTP1017] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 17, MSTPSR10, 0), /* SCU */ - [MSTP1015] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 15, MSTPSR10, 0), /* SSI0 */ - [MSTP1014] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 14, MSTPSR10, 0), /* SSI1 */ - [MSTP1013] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 13, MSTPSR10, 0), /* SSI2 */ - [MSTP1012] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 12, MSTPSR10, 0), /* SSI3 */ - [MSTP1011] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 11, MSTPSR10, 0), /* SSI4 */ - [MSTP1010] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 10, MSTPSR10, 0), /* SSI5 */ - [MSTP1009] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 9, MSTPSR10, 0), /* SSI6 */ - [MSTP1008] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 8, MSTPSR10, 0), /* SSI7 */ - [MSTP1007] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 7, MSTPSR10, 0), /* SSI8 */ - [MSTP1006] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 6, MSTPSR10, 0), /* SSI9 */ - [MSTP1005] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 5, MSTPSR10, 0), /* SSI ALL */ - [MSTP931] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 31, MSTPSR9, 0), /* I2C0 */ - [MSTP930] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 30, MSTPSR9, 0), /* I2C1 */ - [MSTP929] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 29, MSTPSR9, 0), /* I2C2 */ - [MSTP928] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 28, MSTPSR9, 0), /* I2C3 */ - [MSTP917] = SH_CLK_MSTP32_STS(&qspi_clk, SMSTPCR9, 17, MSTPSR9, 0), /* QSPI */ - [MSTP815] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR8, 15, MSTPSR8, 0), /* SATA0 */ - [MSTP814] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR8, 14, MSTPSR8, 0), /* SATA1 */ - [MSTP813] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR8, 13, MSTPSR8, 0), /* Ether */ - [MSTP811] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8, 11, MSTPSR8, 0), /* VIN0 */ - [MSTP810] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8, 10, MSTPSR8, 0), /* VIN1 */ - [MSTP809] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8, 9, MSTPSR8, 0), /* VIN2 */ - [MSTP808] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8, 8, MSTPSR8, 0), /* VIN3 */ - [MSTP726] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 26, MSTPSR7, 0), /* LVDS0 */ - [MSTP725] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 25, MSTPSR7, 0), /* LVDS1 */ - [MSTP724] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 24, MSTPSR7, 0), /* DU0 */ - [MSTP723] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 23, MSTPSR7, 0), /* DU1 */ - [MSTP722] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 22, MSTPSR7, 0), /* DU2 */ - [MSTP721] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 21, MSTPSR7, 0), /* SCIF0 */ - [MSTP720] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 20, MSTPSR7, 0), /* SCIF1 */ - [MSTP717] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR7, 17, MSTPSR7, 0), /* HSCIF0 */ - [MSTP716] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR7, 16, MSTPSR7, 0), /* HSCIF1 */ - [MSTP704] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR7, 4, MSTPSR7, 0), /* HSUSB */ - [MSTP703] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR7, 3, MSTPSR7, 0), /* EHCI */ - [MSTP522] = SH_CLK_MSTP32_STS(&extal_clk, SMSTPCR5, 22, MSTPSR5, 0), /* Thermal */ - [MSTP502] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR5, 2, MSTPSR5, 0), /* Audio-DMAC low */ - [MSTP501] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR5, 1, MSTPSR5, 0), /* Audio-DMAC hi */ - [MSTP315] = SH_CLK_MSTP32_STS(&div6_clks[DIV6_MMC0], SMSTPCR3, 15, MSTPSR3, 0), /* MMC0 */ - [MSTP314] = SH_CLK_MSTP32_STS(&div4_clks[DIV4_SD0], SMSTPCR3, 14, MSTPSR3, 0), /* SDHI0 */ - [MSTP313] = SH_CLK_MSTP32_STS(&div4_clks[DIV4_SD1], SMSTPCR3, 13, MSTPSR3, 0), /* SDHI1 */ - [MSTP312] = SH_CLK_MSTP32_STS(&div6_clks[DIV6_SD2], SMSTPCR3, 12, MSTPSR3, 0), /* SDHI2 */ - [MSTP311] = SH_CLK_MSTP32_STS(&div6_clks[DIV6_SD3], SMSTPCR3, 11, MSTPSR3, 0), /* SDHI3 */ - [MSTP305] = SH_CLK_MSTP32_STS(&div6_clks[DIV6_MMC1], SMSTPCR3, 5, MSTPSR3, 0), /* MMC1 */ - [MSTP304] = SH_CLK_MSTP32_STS(&cp_clk, SMSTPCR3, 4, MSTPSR3, 0), /* TPU0 */ - [MSTP216] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 16, MSTPSR2, 0), /* SCIFB2 */ - [MSTP207] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 7, MSTPSR2, 0), /* SCIFB1 */ - [MSTP206] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 6, MSTPSR2, 0), /* SCIFB0 */ - [MSTP204] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 4, MSTPSR2, 0), /* SCIFA0 */ - [MSTP203] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 3, MSTPSR2, 0), /* SCIFA1 */ - [MSTP202] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 2, MSTPSR2, 0), /* SCIFA2 */ - [MSTP124] = SH_CLK_MSTP32_STS(&rclk_clk, SMSTPCR1, 24, MSTPSR1, 0), /* CMT0 */ -}; - -static struct clk_lookup lookups[] = { - - /* main clocks */ - CLKDEV_CON_ID("extal", &extal_clk), - CLKDEV_CON_ID("extal_div2", &extal_div2_clk), - CLKDEV_CON_ID("main", &main_clk), - CLKDEV_CON_ID("pll1", &pll1_clk), - CLKDEV_CON_ID("pll1_div2", &pll1_div2_clk), - CLKDEV_CON_ID("pll3", &pll3_clk), - CLKDEV_CON_ID("zg", &zg_clk), - CLKDEV_CON_ID("zx", &zx_clk), - CLKDEV_CON_ID("zs", &zs_clk), - CLKDEV_CON_ID("hp", &hp_clk), - CLKDEV_CON_ID("i", &i_clk), - CLKDEV_CON_ID("b", &b_clk), - CLKDEV_CON_ID("lb", &lb_clk), - CLKDEV_CON_ID("p", &p_clk), - CLKDEV_CON_ID("cl", &cl_clk), - CLKDEV_CON_ID("m2", &m2_clk), - CLKDEV_CON_ID("imp", &imp_clk), - CLKDEV_CON_ID("rclk", &rclk_clk), - CLKDEV_CON_ID("oscclk", &oscclk_clk), - CLKDEV_CON_ID("zb3", &zb3_clk), - CLKDEV_CON_ID("zb3d2", &zb3d2_clk), - CLKDEV_CON_ID("ddr", &ddr_clk), - CLKDEV_CON_ID("mp", &mp_clk), - CLKDEV_CON_ID("qspi", &qspi_clk), - CLKDEV_CON_ID("cp", &cp_clk), - - /* DIV4 */ - CLKDEV_CON_ID("sdh", &div4_clks[DIV4_SDH]), - - /* DIV6 */ - CLKDEV_CON_ID("ssp", &div6_clks[DIV6_SSP]), - CLKDEV_CON_ID("ssprs", &div6_clks[DIV6_SSPRS]), - - /* MSTP */ - CLKDEV_DEV_ID("rcar_sound", &mstp_clks[MSTP1005]), - CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), - CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), - CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP206]), - CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP207]), - CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP216]), - CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP202]), - CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP721]), - CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP720]), - CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP717]), - CLKDEV_DEV_ID("sh-sci.9", &mstp_clks[MSTP716]), - CLKDEV_DEV_ID("i2c-rcar_gen2.0", &mstp_clks[MSTP931]), - CLKDEV_DEV_ID("i2c-rcar_gen2.1", &mstp_clks[MSTP930]), - CLKDEV_DEV_ID("i2c-rcar_gen2.2", &mstp_clks[MSTP929]), - CLKDEV_DEV_ID("i2c-rcar_gen2.3", &mstp_clks[MSTP928]), - CLKDEV_DEV_ID("r8a7790-ether", &mstp_clks[MSTP813]), - CLKDEV_DEV_ID("r8a7790-vin.0", &mstp_clks[MSTP811]), - CLKDEV_DEV_ID("r8a7790-vin.1", &mstp_clks[MSTP810]), - CLKDEV_DEV_ID("r8a7790-vin.2", &mstp_clks[MSTP809]), - CLKDEV_DEV_ID("r8a7790-vin.3", &mstp_clks[MSTP808]), - CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]), - CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP502]), - CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP501]), - CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP315]), - CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), - CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), - CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP312]), - CLKDEV_DEV_ID("sh_mobile_sdhi.3", &mstp_clks[MSTP311]), - CLKDEV_DEV_ID("sh_mmcif.1", &mstp_clks[MSTP305]), - CLKDEV_DEV_ID("qspi.0", &mstp_clks[MSTP917]), - CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP704]), - CLKDEV_DEV_ID("pci-rcar-gen2.0", &mstp_clks[MSTP703]), - CLKDEV_DEV_ID("pci-rcar-gen2.1", &mstp_clks[MSTP703]), - CLKDEV_DEV_ID("pci-rcar-gen2.2", &mstp_clks[MSTP703]), - CLKDEV_DEV_ID("sata-r8a7790.0", &mstp_clks[MSTP815]), - CLKDEV_DEV_ID("sata-r8a7790.1", &mstp_clks[MSTP814]), - - /* ICK */ - CLKDEV_ICK_ID("fck", "sh-cmt-48-gen2.0", &mstp_clks[MSTP124]), - CLKDEV_ICK_ID("usbhs", "usb_phy_rcar_gen2", &mstp_clks[MSTP704]), - CLKDEV_ICK_ID("lvds.0", "rcar-du-r8a7790", &mstp_clks[MSTP726]), - CLKDEV_ICK_ID("lvds.1", "rcar-du-r8a7790", &mstp_clks[MSTP725]), - CLKDEV_ICK_ID("du.0", "rcar-du-r8a7790", &mstp_clks[MSTP724]), - CLKDEV_ICK_ID("du.1", "rcar-du-r8a7790", &mstp_clks[MSTP723]), - CLKDEV_ICK_ID("du.2", "rcar-du-r8a7790", &mstp_clks[MSTP722]), - CLKDEV_ICK_ID("clk_a", "rcar_sound", &audio_clk_a), - CLKDEV_ICK_ID("clk_b", "rcar_sound", &audio_clk_b), - CLKDEV_ICK_ID("clk_c", "rcar_sound", &audio_clk_c), - CLKDEV_ICK_ID("clk_i", "rcar_sound", &m2_clk), - CLKDEV_ICK_ID("src.0", "rcar_sound", &mstp_clks[MSTP1031]), - CLKDEV_ICK_ID("src.1", "rcar_sound", &mstp_clks[MSTP1030]), - CLKDEV_ICK_ID("src.2", "rcar_sound", &mstp_clks[MSTP1029]), - CLKDEV_ICK_ID("src.3", "rcar_sound", &mstp_clks[MSTP1028]), - CLKDEV_ICK_ID("src.4", "rcar_sound", &mstp_clks[MSTP1027]), - CLKDEV_ICK_ID("src.5", "rcar_sound", &mstp_clks[MSTP1026]), - CLKDEV_ICK_ID("src.6", "rcar_sound", &mstp_clks[MSTP1025]), - CLKDEV_ICK_ID("src.7", "rcar_sound", &mstp_clks[MSTP1024]), - CLKDEV_ICK_ID("src.8", "rcar_sound", &mstp_clks[MSTP1023]), - CLKDEV_ICK_ID("src.9", "rcar_sound", &mstp_clks[MSTP1022]), - CLKDEV_ICK_ID("ssi.0", "rcar_sound", &mstp_clks[MSTP1015]), - CLKDEV_ICK_ID("ssi.1", "rcar_sound", &mstp_clks[MSTP1014]), - CLKDEV_ICK_ID("ssi.2", "rcar_sound", &mstp_clks[MSTP1013]), - CLKDEV_ICK_ID("ssi.3", "rcar_sound", &mstp_clks[MSTP1012]), - CLKDEV_ICK_ID("ssi.4", "rcar_sound", &mstp_clks[MSTP1011]), - CLKDEV_ICK_ID("ssi.5", "rcar_sound", &mstp_clks[MSTP1010]), - CLKDEV_ICK_ID("ssi.6", "rcar_sound", &mstp_clks[MSTP1009]), - CLKDEV_ICK_ID("ssi.7", "rcar_sound", &mstp_clks[MSTP1008]), - CLKDEV_ICK_ID("ssi.8", "rcar_sound", &mstp_clks[MSTP1007]), - CLKDEV_ICK_ID("ssi.9", "rcar_sound", &mstp_clks[MSTP1006]), - -}; - -#define R8A7790_CLOCK_ROOT(e, m, p0, p1, p30, p31) \ - extal_clk.rate = e * 1000 * 1000; \ - main_clk.parent = m; \ - SH_CLK_SET_RATIO(&pll1_clk_ratio, p1 / 2, 1); \ - if (mode & MD(19)) \ - SH_CLK_SET_RATIO(&pll3_clk_ratio, p31, 1); \ - else \ - SH_CLK_SET_RATIO(&pll3_clk_ratio, p30, 1) - - -void __init r8a7790_clock_init(void) -{ - u32 mode = rcar_gen2_read_mode_pins(); - int k, ret = 0; - - switch (mode & (MD(14) | MD(13))) { - case 0: - R8A7790_CLOCK_ROOT(15, &extal_clk, 172, 208, 106, 88); - break; - case MD(13): - R8A7790_CLOCK_ROOT(20, &extal_clk, 130, 156, 80, 66); - break; - case MD(14): - R8A7790_CLOCK_ROOT(26 / 2, &extal_div2_clk, 200, 240, 122, 102); - break; - case MD(13) | MD(14): - R8A7790_CLOCK_ROOT(30 / 2, &extal_div2_clk, 172, 208, 106, 88); - break; - } - - if (mode & (MD(18))) - SH_CLK_SET_RATIO(&lb_clk_ratio, 1, 36); - else - SH_CLK_SET_RATIO(&lb_clk_ratio, 1, 24); - - if ((mode & (MD(3) | MD(2) | MD(1))) == MD(2)) - SH_CLK_SET_RATIO(&qspi_clk_ratio, 1, 16); - else - SH_CLK_SET_RATIO(&qspi_clk_ratio, 1, 20); - - for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++) - ret = clk_register(main_clks[k]); - - if (!ret) - ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table); - - if (!ret) - ret = sh_clk_div6_register(div6_clks, DIV6_NR); - - if (!ret) - ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); - - clkdev_add_table(lookups, ARRAY_SIZE(lookups)); - - if (!ret) - shmobile_clk_init(); - else - panic("failed to setup r8a7790 clocks\n"); -} diff --git a/arch/arm/mach-shmobile/r8a7790.h b/arch/arm/mach-shmobile/r8a7790.h index 388f0514d931f9..bf73a850aaede0 100644 --- a/arch/arm/mach-shmobile/r8a7790.h +++ b/arch/arm/mach-shmobile/r8a7790.h @@ -1,34 +1,6 @@ #ifndef __ASM_R8A7790_H__ #define __ASM_R8A7790_H__ -/* DMA slave IDs */ -enum { - RCAR_DMA_SLAVE_INVALID, - AUDIO_DMAC_SLAVE_SSI0_TX, - AUDIO_DMAC_SLAVE_SSI0_RX, - AUDIO_DMAC_SLAVE_SSI1_TX, - AUDIO_DMAC_SLAVE_SSI1_RX, - AUDIO_DMAC_SLAVE_SSI2_TX, - AUDIO_DMAC_SLAVE_SSI2_RX, - AUDIO_DMAC_SLAVE_SSI3_TX, - AUDIO_DMAC_SLAVE_SSI3_RX, - AUDIO_DMAC_SLAVE_SSI4_TX, - AUDIO_DMAC_SLAVE_SSI4_RX, - AUDIO_DMAC_SLAVE_SSI5_TX, - AUDIO_DMAC_SLAVE_SSI5_RX, - AUDIO_DMAC_SLAVE_SSI6_TX, - AUDIO_DMAC_SLAVE_SSI6_RX, - AUDIO_DMAC_SLAVE_SSI7_TX, - AUDIO_DMAC_SLAVE_SSI7_RX, - AUDIO_DMAC_SLAVE_SSI8_TX, - AUDIO_DMAC_SLAVE_SSI8_RX, - AUDIO_DMAC_SLAVE_SSI9_TX, - AUDIO_DMAC_SLAVE_SSI9_RX, -}; - -void r8a7790_add_standard_devices(void); -void r8a7790_clock_init(void); -void r8a7790_pinmux_init(void); void r8a7790_pm_init(void); extern struct smp_operations r8a7790_smp_ops; diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c b/arch/arm/mach-shmobile/setup-r8a7790.c index ec7d97dca4de21..3a18af4922b425 100644 --- a/arch/arm/mach-shmobile/setup-r8a7790.c +++ b/arch/arm/mach-shmobile/setup-r8a7790.c @@ -14,295 +14,14 @@ * GNU General Public License for more details. */ -#include -#include -#include -#include -#include -#include -#include -#include +#include #include #include "common.h" -#include "dma-register.h" -#include "irqs.h" #include "r8a7790.h" #include "rcar-gen2.h" -/* Audio-DMAC */ -#define AUDIO_DMAC_SLAVE(_id, _addr, t, r) \ -{ \ - .slave_id = AUDIO_DMAC_SLAVE_## _id ##_TX, \ - .addr = _addr + 0x8, \ - .chcr = CHCR_TX(XMIT_SZ_32BIT), \ - .mid_rid = t, \ -}, { \ - .slave_id = AUDIO_DMAC_SLAVE_## _id ##_RX, \ - .addr = _addr + 0xc, \ - .chcr = CHCR_RX(XMIT_SZ_32BIT), \ - .mid_rid = r, \ -} - -static const struct sh_dmae_slave_config r8a7790_audio_dmac_slaves[] = { - AUDIO_DMAC_SLAVE(SSI0, 0xec241000, 0x01, 0x02), - AUDIO_DMAC_SLAVE(SSI1, 0xec241040, 0x03, 0x04), - AUDIO_DMAC_SLAVE(SSI2, 0xec241080, 0x05, 0x06), - AUDIO_DMAC_SLAVE(SSI3, 0xec2410c0, 0x07, 0x08), - AUDIO_DMAC_SLAVE(SSI4, 0xec241100, 0x09, 0x0a), - AUDIO_DMAC_SLAVE(SSI5, 0xec241140, 0x0b, 0x0c), - AUDIO_DMAC_SLAVE(SSI6, 0xec241180, 0x0d, 0x0e), - AUDIO_DMAC_SLAVE(SSI7, 0xec2411c0, 0x0f, 0x10), - AUDIO_DMAC_SLAVE(SSI8, 0xec241200, 0x11, 0x12), - AUDIO_DMAC_SLAVE(SSI9, 0xec241240, 0x13, 0x14), -}; - -#define DMAE_CHANNEL(a, b) \ -{ \ - .offset = (a) - 0x20, \ - .dmars = (a) - 0x20 + 0x40, \ - .chclr_bit = (b), \ - .chclr_offset = 0x80 - 0x20, \ -} - -static const struct sh_dmae_channel r8a7790_audio_dmac_channels[] = { - DMAE_CHANNEL(0x8000, 0), - DMAE_CHANNEL(0x8080, 1), - DMAE_CHANNEL(0x8100, 2), - DMAE_CHANNEL(0x8180, 3), - DMAE_CHANNEL(0x8200, 4), - DMAE_CHANNEL(0x8280, 5), - DMAE_CHANNEL(0x8300, 6), - DMAE_CHANNEL(0x8380, 7), - DMAE_CHANNEL(0x8400, 8), - DMAE_CHANNEL(0x8480, 9), - DMAE_CHANNEL(0x8500, 10), - DMAE_CHANNEL(0x8580, 11), - DMAE_CHANNEL(0x8600, 12), -}; - -static struct sh_dmae_pdata r8a7790_audio_dmac_platform_data = { - .slave = r8a7790_audio_dmac_slaves, - .slave_num = ARRAY_SIZE(r8a7790_audio_dmac_slaves), - .channel = r8a7790_audio_dmac_channels, - .channel_num = ARRAY_SIZE(r8a7790_audio_dmac_channels), - .ts_low_shift = TS_LOW_SHIFT, - .ts_low_mask = TS_LOW_BIT << TS_LOW_SHIFT, - .ts_high_shift = TS_HI_SHIFT, - .ts_high_mask = TS_HI_BIT << TS_HI_SHIFT, - .ts_shift = dma_ts_shift, - .ts_shift_num = ARRAY_SIZE(dma_ts_shift), - .dmaor_init = DMAOR_DME, - .chclr_present = 1, - .chclr_bitwise = 1, -}; - -static struct resource r8a7790_audio_dmac_resources[] = { - /* Channel registers and DMAOR for low */ - DEFINE_RES_MEM(0xec700020, 0x8663 - 0x20), - DEFINE_RES_IRQ(gic_spi(346)), - DEFINE_RES_NAMED(gic_spi(320), 13, NULL, IORESOURCE_IRQ), - - /* Channel registers and DMAOR for hi */ - DEFINE_RES_MEM(0xec720020, 0x8663 - 0x20), /* hi */ - DEFINE_RES_IRQ(gic_spi(347)), - DEFINE_RES_NAMED(gic_spi(333), 13, NULL, IORESOURCE_IRQ), -}; - -#define r8a7790_register_audio_dmac(id) \ - platform_device_register_resndata( \ - NULL, "sh-dma-engine", id, \ - &r8a7790_audio_dmac_resources[id * 3], 3, \ - &r8a7790_audio_dmac_platform_data, \ - sizeof(r8a7790_audio_dmac_platform_data)) - -static const struct resource pfc_resources[] __initconst = { - DEFINE_RES_MEM(0xe6060000, 0x250), -}; - -#define r8a7790_register_pfc() \ - platform_device_register_simple("pfc-r8a7790", -1, pfc_resources, \ - ARRAY_SIZE(pfc_resources)) - -#define R8A7790_GPIO(idx) \ -static const struct resource r8a7790_gpio##idx##_resources[] __initconst = { \ - DEFINE_RES_MEM(0xe6050000 + 0x1000 * (idx), 0x50), \ - DEFINE_RES_IRQ(gic_spi(4 + (idx))), \ -}; \ - \ -static const struct gpio_rcar_config \ -r8a7790_gpio##idx##_platform_data __initconst = { \ - .gpio_base = 32 * (idx), \ - .irq_base = 0, \ - .number_of_pins = 32, \ - .pctl_name = "pfc-r8a7790", \ - .has_both_edge_trigger = 1, \ -}; \ - -R8A7790_GPIO(0); -R8A7790_GPIO(1); -R8A7790_GPIO(2); -R8A7790_GPIO(3); -R8A7790_GPIO(4); -R8A7790_GPIO(5); - -#define r8a7790_register_gpio(idx) \ - platform_device_register_resndata(NULL, "gpio_rcar", idx, \ - r8a7790_gpio##idx##_resources, \ - ARRAY_SIZE(r8a7790_gpio##idx##_resources), \ - &r8a7790_gpio##idx##_platform_data, \ - sizeof(r8a7790_gpio##idx##_platform_data)) - -static struct resource i2c_resources[] __initdata = { - /* I2C0 */ - DEFINE_RES_MEM(0xE6508000, 0x40), - DEFINE_RES_IRQ(gic_spi(287)), - /* I2C1 */ - DEFINE_RES_MEM(0xE6518000, 0x40), - DEFINE_RES_IRQ(gic_spi(288)), - /* I2C2 */ - DEFINE_RES_MEM(0xE6530000, 0x40), - DEFINE_RES_IRQ(gic_spi(286)), - /* I2C3 */ - DEFINE_RES_MEM(0xE6540000, 0x40), - DEFINE_RES_IRQ(gic_spi(290)), - -}; - -#define r8a7790_register_i2c(idx) \ - platform_device_register_simple( \ - "i2c-rcar_gen2", idx, \ - i2c_resources + (2 * idx), 2); \ - -void __init r8a7790_pinmux_init(void) -{ - r8a7790_register_pfc(); - r8a7790_register_gpio(0); - r8a7790_register_gpio(1); - r8a7790_register_gpio(2); - r8a7790_register_gpio(3); - r8a7790_register_gpio(4); - r8a7790_register_gpio(5); -} - -#define __R8A7790_SCIF(scif_type, _scscr, index, baseaddr, irq) \ -static struct plat_sci_port scif##index##_platform_data = { \ - .type = scif_type, \ - .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, \ - .scscr = _scscr, \ -}; \ - \ -static struct resource scif##index##_resources[] = { \ - DEFINE_RES_MEM(baseaddr, 0x100), \ - DEFINE_RES_IRQ(irq), \ -} - -#define R8A7790_SCIF(index, baseaddr, irq) \ - __R8A7790_SCIF(PORT_SCIF, SCSCR_RE | SCSCR_TE, \ - index, baseaddr, irq) - -#define R8A7790_SCIFA(index, baseaddr, irq) \ - __R8A7790_SCIF(PORT_SCIFA, SCSCR_RE | SCSCR_TE | SCSCR_CKE0, \ - index, baseaddr, irq) - -#define R8A7790_SCIFB(index, baseaddr, irq) \ - __R8A7790_SCIF(PORT_SCIFB, SCSCR_RE | SCSCR_TE, \ - index, baseaddr, irq) - -#define R8A7790_HSCIF(index, baseaddr, irq) \ - __R8A7790_SCIF(PORT_HSCIF, SCSCR_RE | SCSCR_TE, \ - index, baseaddr, irq) - -R8A7790_SCIFA(0, 0xe6c40000, gic_spi(144)); /* SCIFA0 */ -R8A7790_SCIFA(1, 0xe6c50000, gic_spi(145)); /* SCIFA1 */ -R8A7790_SCIFB(2, 0xe6c20000, gic_spi(148)); /* SCIFB0 */ -R8A7790_SCIFB(3, 0xe6c30000, gic_spi(149)); /* SCIFB1 */ -R8A7790_SCIFB(4, 0xe6ce0000, gic_spi(150)); /* SCIFB2 */ -R8A7790_SCIFA(5, 0xe6c60000, gic_spi(151)); /* SCIFA2 */ -R8A7790_SCIF(6, 0xe6e60000, gic_spi(152)); /* SCIF0 */ -R8A7790_SCIF(7, 0xe6e68000, gic_spi(153)); /* SCIF1 */ -R8A7790_HSCIF(8, 0xe62c0000, gic_spi(154)); /* HSCIF0 */ -R8A7790_HSCIF(9, 0xe62c8000, gic_spi(155)); /* HSCIF1 */ - -#define r8a7790_register_scif(index) \ - platform_device_register_resndata(NULL, "sh-sci", index, \ - scif##index##_resources, \ - ARRAY_SIZE(scif##index##_resources), \ - &scif##index##_platform_data, \ - sizeof(scif##index##_platform_data)) - -static const struct renesas_irqc_config irqc0_data __initconst = { - .irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */ -}; - -static const struct resource irqc0_resources[] __initconst = { - DEFINE_RES_MEM(0xe61c0000, 0x200), /* IRQC Event Detector Block_0 */ - DEFINE_RES_IRQ(gic_spi(0)), /* IRQ0 */ - DEFINE_RES_IRQ(gic_spi(1)), /* IRQ1 */ - DEFINE_RES_IRQ(gic_spi(2)), /* IRQ2 */ - DEFINE_RES_IRQ(gic_spi(3)), /* IRQ3 */ -}; - -#define r8a7790_register_irqc(idx) \ - platform_device_register_resndata(NULL, "renesas_irqc", \ - idx, irqc##idx##_resources, \ - ARRAY_SIZE(irqc##idx##_resources), \ - &irqc##idx##_data, \ - sizeof(struct renesas_irqc_config)) - -static const struct resource thermal_resources[] __initconst = { - DEFINE_RES_MEM(0xe61f0000, 0x14), - DEFINE_RES_MEM(0xe61f0100, 0x38), - DEFINE_RES_IRQ(gic_spi(69)), -}; - -#define r8a7790_register_thermal() \ - platform_device_register_simple("rcar_thermal", -1, \ - thermal_resources, \ - ARRAY_SIZE(thermal_resources)) - -static struct sh_timer_config cmt0_platform_data = { - .channels_mask = 0x60, -}; - -static struct resource cmt0_resources[] = { - DEFINE_RES_MEM(0xffca0000, 0x1004), - DEFINE_RES_IRQ(gic_spi(142)), -}; - -#define r8a7790_register_cmt(idx) \ - platform_device_register_resndata(NULL, "sh-cmt-48-gen2", \ - idx, cmt##idx##_resources, \ - ARRAY_SIZE(cmt##idx##_resources), \ - &cmt##idx##_platform_data, \ - sizeof(struct sh_timer_config)) - -void __init r8a7790_add_standard_devices(void) -{ - r8a7790_register_scif(0); - r8a7790_register_scif(1); - r8a7790_register_scif(2); - r8a7790_register_scif(3); - r8a7790_register_scif(4); - r8a7790_register_scif(5); - r8a7790_register_scif(6); - r8a7790_register_scif(7); - r8a7790_register_scif(8); - r8a7790_register_scif(9); - r8a7790_register_cmt(0); - r8a7790_register_irqc(0); - r8a7790_register_thermal(); - r8a7790_register_i2c(0); - r8a7790_register_i2c(1); - r8a7790_register_i2c(2); - r8a7790_register_i2c(3); - r8a7790_register_audio_dmac(0); - r8a7790_register_audio_dmac(1); -} - -#ifdef CONFIG_USE_OF - static const char * const r8a7790_boards_compat_dt[] __initconst = { "renesas,r8a7790", NULL, @@ -316,4 +35,3 @@ DT_MACHINE_START(R8A7790_DT, "Generic R8A7790 (Flattened Device Tree)") .reserve = rcar_gen2_reserve, .dt_compat = r8a7790_boards_compat_dt, MACHINE_END -#endif /* CONFIG_USE_OF */ From 78c11ec2e0c63262bae78c99872d4df81fb6d1e6 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 18 Oct 2013 16:00:00 +0200 Subject: [PATCH 0256/3023] ARM: shmobile: lager: Rename SCIFA[01] serial ports to ttySC[01] There's no reason to name the only two available serial ports on the board ttySC6 and ttySC7 (apart from confusing userspace, which we should try to avoid). Signed-off-by: Laurent Pinchart Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7790-lager.dts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts index 636d53bb87a270..ec843192d653dc 100644 --- a/arch/arm/boot/dts/r8a7790-lager.dts +++ b/arch/arm/boot/dts/r8a7790-lager.dts @@ -47,12 +47,12 @@ compatible = "renesas,lager", "renesas,r8a7790"; aliases { - serial6 = &scifa0; - serial7 = &scifa1; + serial0 = &scifa0; + serial1 = &scifa1; }; chosen { - bootargs = "console=ttySC6,115200 ignore_loglevel rw root=/dev/nfs ip=dhcp"; + bootargs = "console=ttySC0,115200 ignore_loglevel rw root=/dev/nfs ip=dhcp"; stdout-path = &scifa0; }; From 1f75cdac773bc9c93ad6126c01ae27bd343302b1 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 18 Oct 2013 16:00:00 +0200 Subject: [PATCH 0257/3023] ARM: shmobile: koelsch: Rename SCIF[01] serial ports to ttySC[01] There's no reason to name the only two available serial ports on the board ttySC6 and ttySC7 (apart from confusing userspace, which we should try to avoid). Signed-off-by: Laurent Pinchart Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7791-koelsch.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts index 990af167c55149..bf58c79a655480 100644 --- a/arch/arm/boot/dts/r8a7791-koelsch.dts +++ b/arch/arm/boot/dts/r8a7791-koelsch.dts @@ -48,8 +48,8 @@ compatible = "renesas,koelsch", "renesas,r8a7791"; aliases { - serial6 = &scif0; - serial7 = &scif1; + serial0 = &scif0; + serial1 = &scif1; }; chosen { From 569dd56c9971c699472d3b270e988baf7f6de8c9 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 2 Dec 2014 18:39:48 +0100 Subject: [PATCH 0258/3023] ARM: shmobile: lager dts: Drop console= bootargs parameter Since commit FIXME ("ARM: shmobile: lager: Remove legacy board support"), lager is restricted to booting from DT, so chosen/stdout-path is always used, and we can drop the "console=" parameter from chosen/bootargs. Signed-off-by: Geert Uytterhoeven Signed-off-by: Laurent Pinchart Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7790-lager.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts index ec843192d653dc..4118030f366dfa 100644 --- a/arch/arm/boot/dts/r8a7790-lager.dts +++ b/arch/arm/boot/dts/r8a7790-lager.dts @@ -52,7 +52,7 @@ }; chosen { - bootargs = "console=ttySC0,115200 ignore_loglevel rw root=/dev/nfs ip=dhcp"; + bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp"; stdout-path = &scifa0; }; From ae073881aa7d2f744fa703ae47371611780e4e44 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 10 Dec 2014 15:45:22 +0100 Subject: [PATCH 0259/3023] clk: shmobile: sh73a0 common clock framework implementation Driver for the SH73A0's clocks that are too specific to be supported by a generic driver. Signed-off-by: Ulrich Hecht Acked-by: Mike Turquette Tested-by: Geert Uytterhoeven Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- .../clock/renesas,sh73a0-cpg-clocks.txt | 35 +++ drivers/clk/shmobile/Makefile | 1 + drivers/clk/shmobile/clk-sh73a0.c | 218 ++++++++++++++++++ 3 files changed, 254 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/renesas,sh73a0-cpg-clocks.txt create mode 100644 drivers/clk/shmobile/clk-sh73a0.c diff --git a/Documentation/devicetree/bindings/clock/renesas,sh73a0-cpg-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,sh73a0-cpg-clocks.txt new file mode 100644 index 00000000000000..a8978ec94831fc --- /dev/null +++ b/Documentation/devicetree/bindings/clock/renesas,sh73a0-cpg-clocks.txt @@ -0,0 +1,35 @@ +These bindings should be considered EXPERIMENTAL for now. + +* Renesas SH73A0 Clock Pulse Generator (CPG) + +The CPG generates core clocks for the SH73A0 SoC. It includes four PLLs +and several fixed ratio dividers. + +Required Properties: + + - compatible: Must be "renesas,sh73a0-cpg-clocks" + + - reg: Base address and length of the memory resource used by the CPG + + - clocks: Reference to the parent clocks ("extal1" and "extal2") + + - #clock-cells: Must be 1 + + - clock-output-names: The names of the clocks. Supported clocks are "main", + "pll0", "pll1", "pll2", "pll3", "dsi0phy", "dsi1phy", "zg", "m3", "b", + "m1", "m2", "z", "zx", and "hp". + + +Example +------- + + cpg_clocks: cpg_clocks@e6150000 { + compatible = "renesas,sh73a0-cpg-clocks"; + reg = <0 0xe6150000 0 0x10000>; + clocks = <&extal1_clk>, <&extal2_clk>; + #clock-cells = <1>; + clock-output-names = "main", "pll0", "pll1", "pll2", + "pll3", "dsi0phy", "dsi1phy", + "zg", "m3", "b", "m1", "m2", + "z", "zx", "hp"; + }; diff --git a/drivers/clk/shmobile/Makefile b/drivers/clk/shmobile/Makefile index 960bf22d42ae15..f83980f2b9568f 100644 --- a/drivers/clk/shmobile/Makefile +++ b/drivers/clk/shmobile/Makefile @@ -5,5 +5,6 @@ obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o +obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-div6.o obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-mstp.o diff --git a/drivers/clk/shmobile/clk-sh73a0.c b/drivers/clk/shmobile/clk-sh73a0.c new file mode 100644 index 00000000000000..8574a6d91b2091 --- /dev/null +++ b/drivers/clk/shmobile/clk-sh73a0.c @@ -0,0 +1,218 @@ +/* + * sh73a0 Core CPG Clocks + * + * Copyright (C) 2014 Ulrich Hecht + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct sh73a0_cpg { + struct clk_onecell_data data; + spinlock_t lock; + void __iomem *reg; +}; + +#define CPG_FRQCRA 0x00 +#define CPG_FRQCRB 0x04 +#define CPG_SD0CKCR 0x74 +#define CPG_SD1CKCR 0x78 +#define CPG_SD2CKCR 0x7c +#define CPG_PLLECR 0xd0 +#define CPG_PLL0CR 0xd8 +#define CPG_PLL1CR 0x28 +#define CPG_PLL2CR 0x2c +#define CPG_PLL3CR 0xdc +#define CPG_CKSCR 0xc0 +#define CPG_DSI0PHYCR 0x6c +#define CPG_DSI1PHYCR 0x70 + +#define CLK_ENABLE_ON_INIT BIT(0) + +struct div4_clk { + const char *name; + const char *parent; + unsigned int reg; + unsigned int shift; +}; + +static struct div4_clk div4_clks[] = { + { "zg", "pll0", CPG_FRQCRA, 16 }, + { "m3", "pll1", CPG_FRQCRA, 12 }, + { "b", "pll1", CPG_FRQCRA, 8 }, + { "m1", "pll1", CPG_FRQCRA, 4 }, + { "m2", "pll1", CPG_FRQCRA, 0 }, + { "zx", "pll1", CPG_FRQCRB, 12 }, + { "hp", "pll1", CPG_FRQCRB, 4 }, + { NULL, 0, 0, 0 }, +}; + +static const struct clk_div_table div4_div_table[] = { + { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 }, { 5, 12 }, + { 6, 16 }, { 7, 18 }, { 8, 24 }, { 10, 36 }, { 11, 48 }, + { 12, 7 }, { 0, 0 } +}; + +static const struct clk_div_table z_div_table[] = { + /* ZSEL == 0 */ + { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 }, { 4, 1 }, { 5, 1 }, + { 6, 1 }, { 7, 1 }, { 8, 1 }, { 9, 1 }, { 10, 1 }, { 11, 1 }, + { 12, 1 }, { 13, 1 }, { 14, 1 }, { 15, 1 }, + /* ZSEL == 1 */ + { 16, 2 }, { 17, 3 }, { 18, 4 }, { 19, 6 }, { 20, 8 }, { 21, 12 }, + { 22, 16 }, { 24, 24 }, { 27, 48 }, { 0, 0 } +}; + +static struct clk * __init +sh73a0_cpg_register_clock(struct device_node *np, struct sh73a0_cpg *cpg, + const char *name) +{ + const struct clk_div_table *table = NULL; + unsigned int shift, reg, width; + const char *parent_name; + unsigned int mult = 1; + unsigned int div = 1; + + if (!strcmp(name, "main")) { + /* extal1, extal1_div2, extal2, extal2_div2 */ + u32 parent_idx = (clk_readl(cpg->reg + CPG_CKSCR) >> 28) & 3; + + parent_name = of_clk_get_parent_name(np, parent_idx >> 1); + div = (parent_idx & 1) + 1; + } else if (!strncmp(name, "pll", 3)) { + void __iomem *enable_reg = cpg->reg; + u32 enable_bit = name[3] - '0'; + + parent_name = "main"; + switch (enable_bit) { + case 0: + enable_reg += CPG_PLL0CR; + break; + case 1: + enable_reg += CPG_PLL1CR; + break; + case 2: + enable_reg += CPG_PLL2CR; + break; + case 3: + enable_reg += CPG_PLL3CR; + break; + default: + return ERR_PTR(-EINVAL); + } + if (clk_readl(cpg->reg + CPG_PLLECR) & BIT(enable_bit)) { + mult = ((clk_readl(enable_reg) >> 24) & 0x3f) + 1; + /* handle CFG bit for PLL1 and PLL2 */ + if (enable_bit == 1 || enable_bit == 2) + if (clk_readl(enable_reg) & BIT(20)) + mult *= 2; + } + } else if (!strcmp(name, "dsi0phy") || !strcmp(name, "dsi1phy")) { + u32 phy_no = name[3] - '0'; + void __iomem *dsi_reg = cpg->reg + + (phy_no ? CPG_DSI1PHYCR : CPG_DSI0PHYCR); + + parent_name = phy_no ? "dsi1pck" : "dsi0pck"; + mult = __raw_readl(dsi_reg); + if (!(mult & 0x8000)) + mult = 1; + else + mult = (mult & 0x3f) + 1; + } else if (!strcmp(name, "z")) { + parent_name = "pll0"; + table = z_div_table; + reg = CPG_FRQCRB; + shift = 24; + width = 5; + } else { + struct div4_clk *c; + + for (c = div4_clks; c->name; c++) { + if (!strcmp(name, c->name)) { + parent_name = c->parent; + table = div4_div_table; + reg = c->reg; + shift = c->shift; + width = 4; + break; + } + } + if (!c->name) + return ERR_PTR(-EINVAL); + } + + if (!table) { + return clk_register_fixed_factor(NULL, name, parent_name, 0, + mult, div); + } else { + return clk_register_divider_table(NULL, name, parent_name, 0, + cpg->reg + reg, shift, width, 0, + table, &cpg->lock); + } +} + +static void __init sh73a0_cpg_clocks_init(struct device_node *np) +{ + struct sh73a0_cpg *cpg; + struct clk **clks; + unsigned int i; + int num_clks; + + num_clks = of_property_count_strings(np, "clock-output-names"); + if (num_clks < 0) { + pr_err("%s: failed to count clocks\n", __func__); + return; + } + + cpg = kzalloc(sizeof(*cpg), GFP_KERNEL); + clks = kcalloc(num_clks, sizeof(*clks), GFP_KERNEL); + if (cpg == NULL || clks == NULL) { + /* We're leaking memory on purpose, there's no point in cleaning + * up as the system won't boot anyway. + */ + return; + } + + spin_lock_init(&cpg->lock); + + cpg->data.clks = clks; + cpg->data.clk_num = num_clks; + + cpg->reg = of_iomap(np, 0); + if (WARN_ON(cpg->reg == NULL)) + return; + + /* Set SDHI clocks to a known state */ + clk_writel(0x108, cpg->reg + CPG_SD0CKCR); + clk_writel(0x108, cpg->reg + CPG_SD1CKCR); + clk_writel(0x108, cpg->reg + CPG_SD2CKCR); + + for (i = 0; i < num_clks; ++i) { + const char *name; + struct clk *clk; + + of_property_read_string_index(np, "clock-output-names", i, + &name); + + clk = sh73a0_cpg_register_clock(np, cpg, name); + if (IS_ERR(clk)) + pr_err("%s: failed to register %s %s clock (%ld)\n", + __func__, np->name, name, PTR_ERR(clk)); + else + cpg->data.clks[i] = clk; + } + + of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data); +} +CLK_OF_DECLARE(sh73a0_cpg_clks, "renesas,sh73a0-cpg-clocks", + sh73a0_cpg_clocks_init); From 4452164e7b2ab8c4e9e978dd5508865592f13258 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 10 Dec 2014 15:45:23 +0100 Subject: [PATCH 0260/3023] ARM: shmobile: sh73a0: Add CPG register bits header Signed-off-by: Ulrich Hecht Acked-by: Laurent Pinchart Tested-by: Geert Uytterhoeven Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- include/dt-bindings/clock/sh73a0-clock.h | 79 ++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 include/dt-bindings/clock/sh73a0-clock.h diff --git a/include/dt-bindings/clock/sh73a0-clock.h b/include/dt-bindings/clock/sh73a0-clock.h new file mode 100644 index 00000000000000..1dd3eb2b7d902a --- /dev/null +++ b/include/dt-bindings/clock/sh73a0-clock.h @@ -0,0 +1,79 @@ +/* + * Copyright 2014 Ulrich Hecht + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __DT_BINDINGS_CLOCK_SH73A0_H__ +#define __DT_BINDINGS_CLOCK_SH73A0_H__ + +/* CPG */ +#define SH73A0_CLK_MAIN 0 +#define SH73A0_CLK_PLL0 1 +#define SH73A0_CLK_PLL1 2 +#define SH73A0_CLK_PLL2 3 +#define SH73A0_CLK_PLL3 4 +#define SH73A0_CLK_DSI0PHY 5 +#define SH73A0_CLK_DSI1PHY 6 +#define SH73A0_CLK_ZG 7 +#define SH73A0_CLK_M3 8 +#define SH73A0_CLK_B 9 +#define SH73A0_CLK_M1 10 +#define SH73A0_CLK_M2 11 +#define SH73A0_CLK_Z 12 +#define SH73A0_CLK_ZX 13 +#define SH73A0_CLK_HP 14 + +/* MSTP0 */ +#define SH73A0_CLK_IIC2 1 + +/* MSTP1 */ +#define SH73A0_CLK_CEU1 29 +#define SH73A0_CLK_CSI2_RX1 28 +#define SH73A0_CLK_CEU0 27 +#define SH73A0_CLK_CSI2_RX0 26 +#define SH73A0_CLK_TMU0 25 +#define SH73A0_CLK_DSITX0 18 +#define SH73A0_CLK_IIC0 16 +#define SH73A0_CLK_SGX 12 +#define SH73A0_CLK_LCDC0 0 + +/* MSTP2 */ +#define SH73A0_CLK_SCIFA7 19 +#define SH73A0_CLK_SY_DMAC 18 +#define SH73A0_CLK_MP_DMAC 17 +#define SH73A0_CLK_SCIFA5 7 +#define SH73A0_CLK_SCIFB 6 +#define SH73A0_CLK_SCIFA0 4 +#define SH73A0_CLK_SCIFA1 3 +#define SH73A0_CLK_SCIFA2 2 +#define SH73A0_CLK_SCIFA3 1 +#define SH73A0_CLK_SCIFA4 0 + +/* MSTP3 */ +#define SH73A0_CLK_SCIFA6 31 +#define SH73A0_CLK_CMT1 29 +#define SH73A0_CLK_FSI 28 +#define SH73A0_CLK_IRDA 25 +#define SH73A0_CLK_IIC1 23 +#define SH73A0_CLK_USB 22 +#define SH73A0_CLK_FLCTL 15 +#define SH73A0_CLK_SDHI0 14 +#define SH73A0_CLK_SDHI1 13 +#define SH73A0_CLK_MMCIF0 12 +#define SH73A0_CLK_SDHI2 11 +#define SH73A0_CLK_TPU0 4 +#define SH73A0_CLK_TPU1 3 +#define SH73A0_CLK_TPU2 2 +#define SH73A0_CLK_TPU3 1 +#define SH73A0_CLK_TPU4 0 + +/* MSTP4 */ +#define SH73A0_CLK_IIC3 11 +#define SH73A0_CLK_IIC4 10 +#define SH73A0_CLK_KEYSC 3 + +#endif From 00df611376e5cd84ae836d04608766096e4702e6 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 10 Dec 2014 15:45:24 +0100 Subject: [PATCH 0261/3023] ARM: shmobile: sh73a0: Common clock framework DT description Declares all sh73a0 clocks supported by the legacy clock framework. Signed-off-by: Ulrich Hecht Tested-by: Geert Uytterhoeven Acked-by: Laurent Pinchart Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/sh73a0.dtsi | 329 ++++++++++++++++++++++++++++++++++ 1 file changed, 329 insertions(+) diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi index d8def5a529da28..3f21b3257679b6 100644 --- a/arch/arm/boot/dts/sh73a0.dtsi +++ b/arch/arm/boot/dts/sh73a0.dtsi @@ -10,6 +10,7 @@ /include/ "skeleton.dtsi" +#include #include / { @@ -322,4 +323,332 @@ interrupts = <0 146 0x4>; status = "disabled"; }; + + clocks { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + /* External root clocks */ + extalr_clk: extalr_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "extalr"; + }; + extal1_clk: extal1_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <26000000>; + clock-output-names = "extal1"; + }; + extal2_clk: extal2_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-output-names = "extal2"; + }; + extcki_clk: extcki_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-output-names = "extcki"; + }; + fsiack_clk: fsiack_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + clock-output-names = "fsiack"; + }; + fsibck_clk: fsibck_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + clock-output-names = "fsibck"; + }; + + /* Special CPG clocks */ + cpg_clocks: cpg_clocks@e6150000 { + compatible = "renesas,sh73a0-cpg-clocks"; + reg = <0xe6150000 0x10000>; + clocks = <&extal1_clk>, <&extal2_clk>; + #clock-cells = <1>; + clock-output-names = "main", "pll0", "pll1", "pll2", + "pll3", "dsi0phy", "dsi1phy", + "zg", "m3", "b", "m1", "m2", + "z", "zx", "hp"; + }; + + /* Variable factor clocks (DIV6) */ + vclk1_clk: vclk1_clk@e6150008 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150008 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "vclk1"; + }; + vclk2_clk: vclk2_clk@e615000c { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe615000c 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "vclk2"; + }; + vclk3_clk: vclk3_clk@e615001c { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe615001c 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "vclk3"; + }; + zb_clk: zb_clk@e6150010 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150010 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "zb"; + }; + flctl_clk: flctl_clk@e6150014 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150014 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "flctlck"; + }; + sdhi0_clk: sdhi0_clk@e6150074 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150074 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "sdhi0ck"; + }; + sdhi1_clk: sdhi1_clk@e6150078 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150078 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "sdhi1ck"; + }; + sdhi2_clk: sdhi2_clk@e615007c { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe615007c 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "sdhi2ck"; + }; + fsia_clk: fsia_clk@e6150018 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150018 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "fsia"; + }; + fsib_clk: fsib_clk@e6150090 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150090 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "fsib"; + }; + sub_clk: sub_clk@e6150080 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150080 4>; + clocks = <&extal2_clk>; + #clock-cells = <0>; + clock-output-names = "sub"; + }; + spua_clk: spua_clk@e6150084 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150084 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "spua"; + }; + spuv_clk: spuv_clk@e6150094 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150094 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "spuv"; + }; + msu_clk: msu_clk@e6150088 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150088 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "msu"; + }; + hsi_clk: hsi_clk@e615008c { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe615008c 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "hsi"; + }; + mfg1_clk: mfg1_clk@e6150098 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150098 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "mfg1"; + }; + mfg2_clk: mfg2_clk@e615009c { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe615009c 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "mfg2"; + }; + dsit_clk: dsit_clk@e6150060 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150060 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "dsit"; + }; + dsi0p_clk: dsi0p_clk@e6150064 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150064 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "dsi0pck"; + }; + + /* Fixed factor clocks */ + main_div2_clk: main_div2_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks SH73A0_CLK_MAIN>; + #clock-cells = <0>; + clock-div = <2>; + clock-mult = <1>; + clock-output-names = "main_div2"; + }; + pll1_div2_clk: pll1_div2_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks SH73A0_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <2>; + clock-mult = <1>; + clock-output-names = "pll1_div2"; + }; + pll1_div7_clk: pll1_div7_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks SH73A0_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <7>; + clock-mult = <1>; + clock-output-names = "pll1_div7"; + }; + pll1_div13_clk: pll1_div13_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks SH73A0_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <13>; + clock-mult = <1>; + clock-output-names = "pll1_div13"; + }; + twd_clk: twd_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks SH73A0_CLK_Z>; + #clock-cells = <0>; + clock-div = <4>; + clock-mult = <1>; + clock-output-names = "twd"; + }; + + /* Gate clocks */ + mstp0_clks: mstp0_clks@e6150130 { + compatible = "renesas,sh73a0-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0xe6150130 4>, <0xe6150030 4>; + clocks = <&cpg_clocks SH73A0_CLK_HP>; + #clock-cells = <1>; + clock-indices = < + SH73A0_CLK_IIC2 + >; + clock-output-names = + "iic2"; + }; + mstp1_clks: mstp1_clks@e6150134 { + compatible = "renesas,sh73a0-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0xe6150134 4>, <0xe6150038 4>; + clocks = <&cpg_clocks SH73A0_CLK_B>, + <&cpg_clocks SH73A0_CLK_B>, + <&cpg_clocks SH73A0_CLK_B>, + <&cpg_clocks SH73A0_CLK_B>, + <&sub_clk>, <&cpg_clocks SH73A0_CLK_B>, + <&cpg_clocks SH73A0_CLK_HP>, + <&cpg_clocks SH73A0_CLK_ZG>, + <&cpg_clocks SH73A0_CLK_B>; + #clock-cells = <1>; + clock-indices = < + SH73A0_CLK_CEU1 SH73A0_CLK_CSI2_RX1 + SH73A0_CLK_CEU0 SH73A0_CLK_CSI2_RX0 + SH73A0_CLK_TMU0 SH73A0_CLK_DSITX0 + SH73A0_CLK_IIC0 SH73A0_CLK_SGX + SH73A0_CLK_LCDC0 + >; + clock-output-names = + "ceu1", "csi2_rx1", "ceu0", "csi2_rx0", + "tmu0", "dsitx0", "iic0", "sgx", "lcdc0"; + }; + mstp2_clks: mstp2_clks@e6150138 { + compatible = "renesas,sh73a0-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0xe6150138 4>, <0xe6150040 4>; + clocks = <&sub_clk>, <&cpg_clocks SH73A0_CLK_HP>, + <&cpg_clocks SH73A0_CLK_HP>, <&sub_clk>, + <&sub_clk>, <&sub_clk>, <&sub_clk>, <&sub_clk>, + <&sub_clk>, <&sub_clk>; + #clock-cells = <1>; + clock-indices = < + SH73A0_CLK_SCIFA7 SH73A0_CLK_SY_DMAC + SH73A0_CLK_MP_DMAC SH73A0_CLK_SCIFA5 + SH73A0_CLK_SCIFB SH73A0_CLK_SCIFA0 + SH73A0_CLK_SCIFA1 SH73A0_CLK_SCIFA2 + SH73A0_CLK_SCIFA3 SH73A0_CLK_SCIFA4 + >; + clock-output-names = + "scifa7", "sy_dmac", "mp_dmac", "scifa5", + "scifb", "scifa0", "scifa1", "scifa2", + "scifa3", "scifa4"; + }; + mstp3_clks: mstp3_clks@e615013c { + compatible = "renesas,sh73a0-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0xe615013c 4>, <0xe6150048 4>; + clocks = <&sub_clk>, <&extalr_clk>, + <&cpg_clocks SH73A0_CLK_HP>, <&sub_clk>, + <&cpg_clocks SH73A0_CLK_HP>, + <&cpg_clocks SH73A0_CLK_HP>, <&flctl_clk>, + <&sdhi0_clk>, <&sdhi1_clk>, + <&cpg_clocks SH73A0_CLK_HP>, <&sdhi2_clk>, + <&main_div2_clk>, <&main_div2_clk>, + <&main_div2_clk>, <&main_div2_clk>, + <&main_div2_clk>; + #clock-cells = <1>; + clock-indices = < + SH73A0_CLK_SCIFA6 SH73A0_CLK_CMT1 + SH73A0_CLK_FSI SH73A0_CLK_IRDA + SH73A0_CLK_IIC1 SH73A0_CLK_USB SH73A0_CLK_FLCTL + SH73A0_CLK_SDHI0 SH73A0_CLK_SDHI1 + SH73A0_CLK_MMCIF0 SH73A0_CLK_SDHI2 + SH73A0_CLK_TPU0 SH73A0_CLK_TPU1 + SH73A0_CLK_TPU2 SH73A0_CLK_TPU3 + SH73A0_CLK_TPU4 + >; + clock-output-names = + "scifa6", "cmt1", "fsi", "irda", "iic1", + "usb", "flctl", "sdhi0", "sdhi1", "mmcif0", "sdhi2", + "tpu0", "tpu1", "tpu2", "tpu3", "tpu4"; + }; + mstp4_clks: mstp4_clks@e6150140 { + compatible = "renesas,sh73a0-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0xe6150140 4>, <0xe615004c 4>; + clocks = <&cpg_clocks SH73A0_CLK_HP>, + <&cpg_clocks SH73A0_CLK_HP>, <&extalr_clk>; + #clock-cells = <1>; + clock-indices = < + SH73A0_CLK_IIC3 SH73A0_CLK_IIC4 + SH73A0_CLK_KEYSC + >; + clock-output-names = + "iic3", "iic4", "keysc"; + }; + }; }; From 1a9a658113c33235ca12e622d91331dd91c61035 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 10 Dec 2014 15:45:25 +0100 Subject: [PATCH 0262/3023] ARM: shmobile: kzm9g-reference: Common clock framework DT description KZM9G-specific clock overrides. Signed-off-by: Ulrich Hecht Acked-by: Laurent Pinchart Tested-by: Geert Uytterhoeven Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/sh73a0-kzm9g-reference.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts b/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts index 939be1299ca6ca..3d912ea8fef474 100644 --- a/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts +++ b/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts @@ -182,6 +182,10 @@ status = "ok"; }; +&extal2_clk { + clock-frequency = <48000000>; +}; + &i2c0 { status = "okay"; as3711@40 { From f73e1e28b5ed9bbb2358606b5abf76d3f94fe8cf Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 10 Dec 2014 15:45:26 +0100 Subject: [PATCH 0263/3023] ARM: shmobile: sh73a0: add MSTP clock assignments to DT Assigns clocks to cmt1, i2c*, mmcif, sdhi*, and scif*. Signed-off-by: Ulrich Hecht Acked-by: Laurent Pinchart Tested-by: Geert Uytterhoeven Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/sh73a0.dtsi | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi index 3f21b3257679b6..cca22ec59a2edd 100644 --- a/arch/arm/boot/dts/sh73a0.dtsi +++ b/arch/arm/boot/dts/sh73a0.dtsi @@ -56,6 +56,8 @@ renesas,channels-mask = <0x3f>; + clocks = <&mstp3_clks SH73A0_CLK_CMT1>; + clock-names = "fck"; status = "disabled"; }; @@ -145,6 +147,7 @@ 0 168 IRQ_TYPE_LEVEL_HIGH 0 169 IRQ_TYPE_LEVEL_HIGH 0 170 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp1_clks SH73A0_CLK_IIC0>; status = "disabled"; }; @@ -157,6 +160,7 @@ 0 52 IRQ_TYPE_LEVEL_HIGH 0 53 IRQ_TYPE_LEVEL_HIGH 0 54 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp3_clks SH73A0_CLK_IIC1>; status = "disabled"; }; @@ -169,6 +173,7 @@ 0 172 IRQ_TYPE_LEVEL_HIGH 0 173 IRQ_TYPE_LEVEL_HIGH 0 174 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp0_clks SH73A0_CLK_IIC2>; status = "disabled"; }; @@ -181,6 +186,7 @@ 0 184 IRQ_TYPE_LEVEL_HIGH 0 185 IRQ_TYPE_LEVEL_HIGH 0 186 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp4_clks SH73A0_CLK_IIC3>; status = "disabled"; }; @@ -193,6 +199,7 @@ 0 188 IRQ_TYPE_LEVEL_HIGH 0 189 IRQ_TYPE_LEVEL_HIGH 0 190 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp4_clks SH73A0_CLK_IIC4>; status = "disabled"; }; @@ -201,6 +208,7 @@ reg = <0xe6bd0000 0x100>; interrupts = <0 140 IRQ_TYPE_LEVEL_HIGH 0 141 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp3_clks SH73A0_CLK_MMCIF0>; reg-io-width = <4>; status = "disabled"; }; @@ -211,6 +219,7 @@ interrupts = <0 83 IRQ_TYPE_LEVEL_HIGH 0 84 IRQ_TYPE_LEVEL_HIGH 0 85 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp3_clks SH73A0_CLK_SDHI0>; cap-sd-highspeed; status = "disabled"; }; @@ -221,6 +230,7 @@ reg = <0xee120000 0x100>; interrupts = <0 88 IRQ_TYPE_LEVEL_HIGH 0 89 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp3_clks SH73A0_CLK_SDHI1>; toshiba,mmc-wrprotect-disable; cap-sd-highspeed; status = "disabled"; @@ -231,6 +241,7 @@ reg = <0xee140000 0x100>; interrupts = <0 104 IRQ_TYPE_LEVEL_HIGH 0 105 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp3_clks SH73A0_CLK_SDHI2>; toshiba,mmc-wrprotect-disable; cap-sd-highspeed; status = "disabled"; @@ -240,6 +251,8 @@ compatible = "renesas,scifa-sh73a0", "renesas,scifa"; reg = <0xe6c40000 0x100>; interrupts = <0 72 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp2_clks SH73A0_CLK_SCIFA0>; + clock-names = "sci_ick"; status = "disabled"; }; @@ -247,6 +260,8 @@ compatible = "renesas,scifa-sh73a0", "renesas,scifa"; reg = <0xe6c50000 0x100>; interrupts = <0 73 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp2_clks SH73A0_CLK_SCIFA1>; + clock-names = "sci_ick"; status = "disabled"; }; @@ -254,6 +269,8 @@ compatible = "renesas,scifa-sh73a0", "renesas,scifa"; reg = <0xe6c60000 0x100>; interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp2_clks SH73A0_CLK_SCIFA2>; + clock-names = "sci_ick"; status = "disabled"; }; @@ -261,6 +278,8 @@ compatible = "renesas,scifa-sh73a0", "renesas,scifa"; reg = <0xe6c70000 0x100>; interrupts = <0 75 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp2_clks SH73A0_CLK_SCIFA3>; + clock-names = "sci_ick"; status = "disabled"; }; @@ -268,6 +287,8 @@ compatible = "renesas,scifa-sh73a0", "renesas,scifa"; reg = <0xe6c80000 0x100>; interrupts = <0 78 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp2_clks SH73A0_CLK_SCIFA4>; + clock-names = "sci_ick"; status = "disabled"; }; @@ -275,6 +296,8 @@ compatible = "renesas,scifa-sh73a0", "renesas,scifa"; reg = <0xe6cb0000 0x100>; interrupts = <0 79 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp2_clks SH73A0_CLK_SCIFA5>; + clock-names = "sci_ick"; status = "disabled"; }; @@ -282,6 +305,8 @@ compatible = "renesas,scifa-sh73a0", "renesas,scifa"; reg = <0xe6cc0000 0x100>; interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp3_clks SH73A0_CLK_SCIFA6>; + clock-names = "sci_ick"; status = "disabled"; }; @@ -289,6 +314,8 @@ compatible = "renesas,scifa-sh73a0", "renesas,scifa"; reg = <0xe6cd0000 0x100>; interrupts = <0 143 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp2_clks SH73A0_CLK_SCIFA7>; + clock-names = "sci_ick"; status = "disabled"; }; @@ -296,6 +323,8 @@ compatible = "renesas,scifb-sh73a0", "renesas,scifb"; reg = <0xe6c30000 0x100>; interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp2_clks SH73A0_CLK_SCIFB>; + clock-names = "sci_ick"; status = "disabled"; }; From 09bd745b555c262d1e2c851777317f3adf3cf3d4 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 10 Dec 2014 15:45:27 +0100 Subject: [PATCH 0264/3023] ARM: shmobile: sh73a0: disable legacy clock initialization Disables sh73a0_clock_init() if CCF is enabled. Signed-off-by: Ulrich Hecht Acked-by: Laurent Pinchart Tested-by: Geert Uytterhoeven Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/setup-sh73a0.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c index 93ebe3430bfe70..354cab111bf17e 100644 --- a/arch/arm/mach-shmobile/setup-sh73a0.c +++ b/arch/arm/mach-shmobile/setup-sh73a0.c @@ -763,7 +763,9 @@ void __init __weak sh73a0_register_twd(void) { } void __init sh73a0_earlytimer_init(void) { shmobile_init_delay(); +#ifndef CONFIG_COMMON_CLK sh73a0_clock_init(); +#endif shmobile_earlytimer_init(); sh73a0_register_twd(); } @@ -782,8 +784,9 @@ void __init sh73a0_add_early_devices(void) void __init sh73a0_add_standard_devices_dt(void) { /* clocks are setup late during boot in the case of DT */ +#ifndef CONFIG_COMMON_CLK sh73a0_clock_init(); - +#endif of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } From 2f472ae6b1998af6d9a4ccc3f0d58781db21cafc Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 19 Nov 2014 16:26:59 +0100 Subject: [PATCH 0265/3023] ARM: shmobile: sh73a0 legacy/reference: Add missing INTCA0 clock for irqpin module This clock drives the irqpin controller modules. Before, it was assumed enabled by the bootloader or reset state. By making it available to the driver, we make sure it gets enabled when needed, and allow it to be managed by system or runtime PM. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/clock-sh73a0.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c index 6b4c1f313cc987..3855fb024fdbb1 100644 --- a/arch/arm/mach-shmobile/clock-sh73a0.c +++ b/arch/arm/mach-shmobile/clock-sh73a0.c @@ -553,6 +553,7 @@ enum { MSTP001, MSTP314, MSTP313, MSTP312, MSTP311, MSTP304, MSTP303, MSTP302, MSTP301, MSTP300, MSTP411, MSTP410, MSTP403, + MSTP508, MSTP_NR }; #define MSTP(_parent, _reg, _bit, _flags) \ @@ -597,6 +598,7 @@ static struct clk mstp_clks[MSTP_NR] = { [MSTP411] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 11, 0), /* IIC3 */ [MSTP410] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 10, 0), /* IIC4 */ [MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */ + [MSTP508] = MSTP(&div4_clks[DIV4_HP], SMSTPCR5, 8, 0), /* INTCA0 */ }; /* The lookups structure below includes duplicate entries for some clocks @@ -677,6 +679,14 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* I2C4 */ CLKDEV_DEV_ID("e6828000.i2c", &mstp_clks[MSTP410]), /* I2C4 */ CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */ + CLKDEV_DEV_ID("renesas_intc_irqpin.0", &mstp_clks[MSTP508]), /* INTCA0 */ + CLKDEV_DEV_ID("e6900000.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */ + CLKDEV_DEV_ID("renesas_intc_irqpin.1", &mstp_clks[MSTP508]), /* INTCA0 */ + CLKDEV_DEV_ID("e6900004.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */ + CLKDEV_DEV_ID("renesas_intc_irqpin.2", &mstp_clks[MSTP508]), /* INTCA0 */ + CLKDEV_DEV_ID("e6900008.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */ + CLKDEV_DEV_ID("renesas_intc_irqpin.3", &mstp_clks[MSTP508]), /* INTCA0 */ + CLKDEV_DEV_ID("e690000c.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */ /* ICK */ CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]), From 95abc9de7896bf65e67bf781d709ec453f1f5f84 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 3 Dec 2014 20:48:04 +0900 Subject: [PATCH 0266/3023] ARM: shmobile: Fix is_e2 warning Fix "is_e2" warning introduced by: 9ce3fa6 ARM: shmobile: rcar-gen2: Add CA7 arch_timer initialization for r8a7794 Only triggers on kernel configurations that have ARCH_ARM_TIMER=n. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/setup-rcar-gen2.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/arm/mach-shmobile/setup-rcar-gen2.c b/arch/arm/mach-shmobile/setup-rcar-gen2.c index 3dd6edd9bd1d3d..c35b91d9219072 100644 --- a/arch/arm/mach-shmobile/setup-rcar-gen2.c +++ b/arch/arm/mach-shmobile/setup-rcar-gen2.c @@ -52,15 +52,13 @@ void __init rcar_gen2_timer_init(void) { #if defined(CONFIG_ARM_ARCH_TIMER) || defined(CONFIG_COMMON_CLK) u32 mode = rcar_gen2_read_mode_pins(); - bool is_e2 = (bool)of_find_compatible_node(NULL, NULL, - "renesas,r8a7794"); #endif #ifdef CONFIG_ARM_ARCH_TIMER void __iomem *base; int extal_mhz = 0; u32 freq; - if (is_e2) { + if (of_machine_is_compatible("renesas,r8a7794")) { freq = 260000000 / 8; /* ZS / 8 */ /* CNTVOFF has to be initialized either from non-secure * Hypervisor mode or secure Monitor mode with SCR.NS==1. From 1dc13eee3a5c60131657482aa88c997e5fa8b50c Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 16 Dec 2014 18:39:31 +0900 Subject: [PATCH 0267/3023] ARM: shmobile: r8a7779: No TWD setup in C for Multiplatform Skip the TWD setup in C for r8a7779 Multiplatform. We should use DTS for the TWD device anyway. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/smp-r8a7779.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c index 3f761f8390430d..9fc280e24ef49c 100644 --- a/arch/arm/mach-shmobile/smp-r8a7779.c +++ b/arch/arm/mach-shmobile/smp-r8a7779.c @@ -56,7 +56,7 @@ static struct rcar_sysc_ch *r8a7779_ch_cpu[4] = { [3] = &r8a7779_ch_cpu3, }; -#ifdef CONFIG_HAVE_ARM_TWD +#if defined(CONFIG_HAVE_ARM_TWD) && !defined(CONFIG_ARCH_MULTIPLATFORM) static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, R8A7779_SCU_BASE + 0x600, 29); void __init r8a7779_register_twd(void) { From 39695882d3d642a73bca551e682426e4e3bcd158 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 17 Dec 2014 17:18:17 +0100 Subject: [PATCH 0268/3023] ARM: shmobile: r8a73a4: Multiplatform support Enable r8a73a4 Multiplatform support for the generic r8a73a4 machine vector. Signed-off-by: Ulrich Hecht Acked-by: Magnus Damm Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/Kconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 1b4fafe524ffeb..d107b9386bda58 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -51,6 +51,11 @@ config ARCH_R7S72100 bool "RZ/A1H (R7S72100)" select SYS_SUPPORTS_SH_MTU2 +config ARCH_R8A73A4 + bool "R-Mobile APE6 (R8A73A40)" + select ARCH_RMOBILE + select RENESAS_IRQC + config ARCH_R8A7740 bool "R-Mobile A1 (R8A77400)" select ARCH_RMOBILE From ce85ad47882fe375dcb3f7cce6c10ae800ac2d9c Mon Sep 17 00:00:00 2001 From: Ryo Kataoka Date: Tue, 9 Dec 2014 13:21:22 +0900 Subject: [PATCH 0269/3023] ARM: shmobile: r8a7791: Add IPMMU-SGX clock to device tree Signed-off-by: Ryo Kataoka [horms: resolved conflicts] Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7791.dtsi | 8 +++++--- include/dt-bindings/clock/r8a7791-clock.h | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index 958a69b24ff432..78d637135e77f3 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -1154,15 +1154,17 @@ mstp8_clks: mstp8_clks@e6150990 { compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe6150990 0 4>, <0 0xe61509a0 0 4>; - clocks = <&zg_clk>, <&zg_clk>, <&zg_clk>, <&p_clk>, <&zs_clk>, - <&zs_clk>; + clocks = <&zg_clk>, <&zg_clk>, <&zg_clk>, <&zg_clk>, <&p_clk>, + <&zs_clk>, <&zs_clk>; #clock-cells = <1>; clock-indices = < + R8A7791_CLK_IPMMU_SGX R8A7791_CLK_VIN2 R8A7791_CLK_VIN1 R8A7791_CLK_VIN0 R8A7791_CLK_ETHER R8A7791_CLK_SATA1 R8A7791_CLK_SATA0 >; clock-output-names = - "vin2", "vin1", "vin0", "ether", "sata1", "sata0"; + "ipmmu_sgx", "vin2", "vin1", "vin0", "ether", "sata1", + "sata0"; }; mstp9_clks: mstp9_clks@e6150994 { compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks"; diff --git a/include/dt-bindings/clock/r8a7791-clock.h b/include/dt-bindings/clock/r8a7791-clock.h index 3ea2bbc0da3f58..ee9bb94423f393 100644 --- a/include/dt-bindings/clock/r8a7791-clock.h +++ b/include/dt-bindings/clock/r8a7791-clock.h @@ -91,6 +91,7 @@ #define R8A7791_CLK_LVDS0 26 /* MSTP8 */ +#define R8A7791_CLK_IPMMU_SGX 0 #define R8A7791_CLK_VIN2 9 #define R8A7791_CLK_VIN1 10 #define R8A7791_CLK_VIN0 11 From be16cd385c08dce7efa406704b5aa420ef6d1992 Mon Sep 17 00:00:00 2001 From: Hiroyuki Yokoyama Date: Wed, 10 Dec 2014 10:21:12 +0900 Subject: [PATCH 0270/3023] ARM: shmobile: r8a7794: Add SYS-DMAC clocks to device tree Signed-off-by: Hiroyuki Yokoyama [horms: resolved conflicts] Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7794.dtsi | 7 +++++-- include/dt-bindings/clock/r8a7794-clock.h | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index 13e4a8d7302933..6d95638987e775 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -479,16 +479,19 @@ compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe6150138 0 4>, <0 0xe6150040 0 4>; clocks = <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>, - <&mp_clk>, <&mp_clk>, <&mp_clk>; + <&mp_clk>, <&mp_clk>, <&mp_clk>, + <&zs_clk>, <&zs_clk>; #clock-cells = <1>; clock-indices = < R8A7794_CLK_SCIFA2 R8A7794_CLK_SCIFA1 R8A7794_CLK_SCIFA0 R8A7794_CLK_MSIOF2 R8A7794_CLK_SCIFB0 R8A7794_CLK_SCIFB1 R8A7794_CLK_MSIOF1 R8A7794_CLK_SCIFB2 + R8A7794_CLK_SYS_DMAC1 R8A7794_CLK_SYS_DMAC0 >; clock-output-names = "scifa2", "scifa1", "scifa0", "msiof2", "scifb0", - "scifb1", "msiof1", "scifb2"; + "scifb1", "msiof1", "scifb2", + "sys-dmac1", "sys-dmac0"; }; mstp3_clks: mstp3_clks@e615013c { compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; diff --git a/include/dt-bindings/clock/r8a7794-clock.h b/include/dt-bindings/clock/r8a7794-clock.h index 52492d85fea168..c0bd14a5c6f3c7 100644 --- a/include/dt-bindings/clock/r8a7794-clock.h +++ b/include/dt-bindings/clock/r8a7794-clock.h @@ -48,6 +48,8 @@ #define R8A7794_CLK_SCIFB1 7 #define R8A7794_CLK_MSIOF1 8 #define R8A7794_CLK_SCIFB2 16 +#define R8A7794_CLK_SYS_DMAC1 18 +#define R8A7794_CLK_SYS_DMAC0 19 /* MSTP3 */ #define R8A7794_CLK_CMT1 29 From cbf41168339adcb48de6a3537f88d4e85285db99 Mon Sep 17 00:00:00 2001 From: Hisashi Nakamura Date: Wed, 10 Dec 2014 11:30:27 +0900 Subject: [PATCH 0271/3023] ARM: shmobile: lager: Fix QSPI mode of SPI-Flash into mode3 In order to change into mode3, CPOL and CPHA bit of SPCMD register of QSPI is changed. Mode3 can avoid intermediate voltage. Signed-off-by: Hisashi Nakamura [horms: Updated changelog and re-ordered properties] Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7790-lager.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts index 636d53bb87a270..bc257e8b1bf29d 100644 --- a/arch/arm/boot/dts/r8a7790-lager.dts +++ b/arch/arm/boot/dts/r8a7790-lager.dts @@ -397,6 +397,8 @@ spi-max-frequency = <30000000>; spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; + spi-cpha; + spi-cpol; m25p,fast-read; partition@0 { From 3281480b70ceb9889b71f7b8a7bf54db3c05d40e Mon Sep 17 00:00:00 2001 From: Hisashi Nakamura Date: Thu, 11 Dec 2014 12:21:14 +0900 Subject: [PATCH 0272/3023] ARM: shmobile: r8a7794: Add QSPI clock to device tree Signed-off-by: Hisashi Nakamura [horms: omitted device node and alias; only add clock] [horms: use clock-indicies instead of renesas,clock-indicies] Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7794.dtsi | 8 ++++++++ include/dt-bindings/clock/r8a7794-clock.h | 1 + 2 files changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index 6d95638987e775..068ca0981ac9f1 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -535,6 +535,14 @@ clock-output-names = "vin1", "vin0", "ether"; }; + mstp9_clks: mstp9_clks@e6150994 { + compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0 0xe6150994 0 4>, <0 0xe61509a4 0 4>; + clocks = <&cpg_clocks R8A7794_CLK_QSPI>; + #clock-cells = <1>; + clock-indices = ; + clock-output-names = "qspi_mod"; + }; mstp11_clks: mstp11_clks@e615099c { compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe615099c 0 4>, <0 0xe61509ac 0 4>; diff --git a/include/dt-bindings/clock/r8a7794-clock.h b/include/dt-bindings/clock/r8a7794-clock.h index c0bd14a5c6f3c7..fba89a49e815b3 100644 --- a/include/dt-bindings/clock/r8a7794-clock.h +++ b/include/dt-bindings/clock/r8a7794-clock.h @@ -86,6 +86,7 @@ #define R8A7794_CLK_GPIO2 10 #define R8A7794_CLK_GPIO1 11 #define R8A7794_CLK_GPIO0 12 +#define R8A7794_CLK_QSPI_MOD 17 /* MSTP11 */ #define R8A7794_CLK_SCIFA3 6 From c6ce3cdfce6c0214f178fbad73d138dd1f1b04f6 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 15 Dec 2014 14:00:34 +0900 Subject: [PATCH 0273/3023] ARM: shmobile: r8a7779: Use R8A7779_CLK_P as SCIF parent clock Use R8A7779_CLK_P as parent clock for SCIF devices on r8a7779. With this change in place the SCIF CCF handling matches the legacy clock code. Also, this matches the data sheet. Signed-off-by: Magnus Damm Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7779.dtsi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi index e3846af833e1d5..ee3bb3e9cbf174 100644 --- a/arch/arm/boot/dts/r8a7779.dtsi +++ b/arch/arm/boot/dts/r8a7779.dtsi @@ -464,12 +464,12 @@ <&cpg_clocks R8A7779_CLK_P>, <&cpg_clocks R8A7779_CLK_S>, <&cpg_clocks R8A7779_CLK_S>, - <&cpg_clocks R8A7779_CLK_S1>, - <&cpg_clocks R8A7779_CLK_S1>, - <&cpg_clocks R8A7779_CLK_S1>, - <&cpg_clocks R8A7779_CLK_S1>, - <&cpg_clocks R8A7779_CLK_S1>, - <&cpg_clocks R8A7779_CLK_S1>, + <&cpg_clocks R8A7779_CLK_P>, + <&cpg_clocks R8A7779_CLK_P>, + <&cpg_clocks R8A7779_CLK_P>, + <&cpg_clocks R8A7779_CLK_P>, + <&cpg_clocks R8A7779_CLK_P>, + <&cpg_clocks R8A7779_CLK_P>, <&cpg_clocks R8A7779_CLK_P>, <&cpg_clocks R8A7779_CLK_P>, <&cpg_clocks R8A7779_CLK_P>, From 631324cf83a04cbfcc81a21801f321679493a072 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 15 Dec 2014 13:56:08 +0900 Subject: [PATCH 0274/3023] ARM: shmobile: r8a7779: Use MSTP for SCIF clocks Hook up MSTP clocks to SCIF devices on r8a7779 to allow clock gating to work as expected. Signed-off-by: Magnus Damm Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7779.dtsi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi index ee3bb3e9cbf174..d9e1abf9debecb 100644 --- a/arch/arm/boot/dts/r8a7779.dtsi +++ b/arch/arm/boot/dts/r8a7779.dtsi @@ -200,7 +200,7 @@ compatible = "renesas,scif-r8a7779", "renesas,scif"; reg = <0xffe40000 0x100>; interrupts = <0 88 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg_clocks R8A7779_CLK_P>; + clocks = <&mstp0_clks R8A7779_CLK_SCIF0>; clock-names = "sci_ick"; status = "disabled"; }; @@ -209,7 +209,7 @@ compatible = "renesas,scif-r8a7779", "renesas,scif"; reg = <0xffe41000 0x100>; interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg_clocks R8A7779_CLK_P>; + clocks = <&mstp0_clks R8A7779_CLK_SCIF1>; clock-names = "sci_ick"; status = "disabled"; }; @@ -218,7 +218,7 @@ compatible = "renesas,scif-r8a7779", "renesas,scif"; reg = <0xffe42000 0x100>; interrupts = <0 90 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg_clocks R8A7779_CLK_P>; + clocks = <&mstp0_clks R8A7779_CLK_SCIF2>; clock-names = "sci_ick"; status = "disabled"; }; @@ -227,7 +227,7 @@ compatible = "renesas,scif-r8a7779", "renesas,scif"; reg = <0xffe43000 0x100>; interrupts = <0 91 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg_clocks R8A7779_CLK_P>; + clocks = <&mstp0_clks R8A7779_CLK_SCIF3>; clock-names = "sci_ick"; status = "disabled"; }; @@ -236,7 +236,7 @@ compatible = "renesas,scif-r8a7779", "renesas,scif"; reg = <0xffe44000 0x100>; interrupts = <0 92 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg_clocks R8A7779_CLK_P>; + clocks = <&mstp0_clks R8A7779_CLK_SCIF4>; clock-names = "sci_ick"; status = "disabled"; }; @@ -245,7 +245,7 @@ compatible = "renesas,scif-r8a7779", "renesas,scif"; reg = <0xffe45000 0x100>; interrupts = <0 93 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg_clocks R8A7779_CLK_P>; + clocks = <&mstp0_clks R8A7779_CLK_SCIF5>; clock-names = "sci_ick"; status = "disabled"; }; From cea806542f6d7ec40eea1c5f9db2065996f56627 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 16 Dec 2014 18:39:41 +0900 Subject: [PATCH 0275/3023] ARM: shmobile: r8a7779: Add TWD device to DTS Now when r8a7779 CCF is in place we can hook up the ARM Cortex-A9 TWD timer via DTS. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7779.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi index d9e1abf9debecb..5c2219b9f3eb50 100644 --- a/arch/arm/boot/dts/r8a7779.dtsi +++ b/arch/arm/boot/dts/r8a7779.dtsi @@ -12,6 +12,7 @@ /include/ "skeleton.dtsi" #include +#include #include / { @@ -62,6 +63,14 @@ <0xf0000100 0x100>; }; + timer@f0000600 { + compatible = "arm,cortex-a9-twd-timer"; + reg = <0xf0000600 0x20>; + interrupts = ; + clocks = <&cpg_clocks R8A7779_CLK_ZS>; + }; + gpio0: gpio@ffc40000 { compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar"; reg = <0xffc40000 0x2c>; From c5d82c9996f68491375de47c208a41bcb150dfad Mon Sep 17 00:00:00 2001 From: Koji Matsuoka Date: Fri, 23 May 2014 18:37:04 +0900 Subject: [PATCH 0276/3023] ARM: shmobile: r8a7794: Add I2C clocks to device tree Signed-off-by: Koji Matsuoka [horms: omitted device nodes and aliases; only add clocks] Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7794.dtsi | 12 +++++++++--- include/dt-bindings/clock/r8a7794-clock.h | 6 ++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index 068ca0981ac9f1..728d719957b8b1 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -538,10 +538,16 @@ mstp9_clks: mstp9_clks@e6150994 { compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe6150994 0 4>, <0 0xe61509a4 0 4>; - clocks = <&cpg_clocks R8A7794_CLK_QSPI>; + clocks = <&cpg_clocks R8A7794_CLK_QSPI>, <&hp_clk>, <&hp_clk>, + <&hp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>; #clock-cells = <1>; - clock-indices = ; - clock-output-names = "qspi_mod"; + clock-indices = < + R8A7794_CLK_QSPI_MOD R8A7794_CLK_I2C5 R8A7794_CLK_I2C4 + R8A7794_CLK_I2C3 R8A7794_CLK_I2C2 R8A7794_CLK_I2C1 + R8A7794_CLK_I2C0 + >; + clock-output-names = + "qspi_mod", "i2c5", "i2c4", "i2c3", "i2c2", "i2c1", "i2c0"; }; mstp11_clks: mstp11_clks@e615099c { compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; diff --git a/include/dt-bindings/clock/r8a7794-clock.h b/include/dt-bindings/clock/r8a7794-clock.h index fba89a49e815b3..94d96186ff0644 100644 --- a/include/dt-bindings/clock/r8a7794-clock.h +++ b/include/dt-bindings/clock/r8a7794-clock.h @@ -87,6 +87,12 @@ #define R8A7794_CLK_GPIO1 11 #define R8A7794_CLK_GPIO0 12 #define R8A7794_CLK_QSPI_MOD 17 +#define R8A7794_CLK_I2C5 25 +#define R8A7794_CLK_I2C4 27 +#define R8A7794_CLK_I2C3 28 +#define R8A7794_CLK_I2C2 29 +#define R8A7794_CLK_I2C1 30 +#define R8A7794_CLK_I2C0 31 /* MSTP11 */ #define R8A7794_CLK_SCIFA3 6 From 8e181633e6ca960491ac502ccd4a4aac482c3ff9 Mon Sep 17 00:00:00 2001 From: Shinobu Uehara Date: Fri, 23 May 2014 11:37:45 +0900 Subject: [PATCH 0277/3023] ARM: shmobile: r8a7794: Add SDHI clocks to device tree Signed-off-by: Shinobu Uehara [horms: omitted device nodes; only add clock] Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7794.dtsi | 20 +++++++++++++++++++- include/dt-bindings/clock/r8a7794-clock.h | 3 +++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index 728d719957b8b1..c37667633e547f 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -293,6 +293,21 @@ clock-output-names = "main", "pll0", "pll1", "pll3", "lb", "qspi", "sdh", "sd0", "z"; }; + /* Variable factor clocks */ + sd1_clk: sd2_clk@e6150078 { + compatible = "renesas,r8a7794-div6-clock", "renesas,cpg-div6-clock"; + reg = <0 0xe6150078 0 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "sd1"; + }; + sd2_clk: sd3_clk@e615007c { + compatible = "renesas,r8a7794-div6-clock", "renesas,cpg-div6-clock"; + reg = <0 0xe615007c 0 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "sd2"; + }; /* Fixed factor clocks */ pll1_div2_clk: pll1_div2_clk { @@ -496,13 +511,16 @@ mstp3_clks: mstp3_clks@e615013c { compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>; - clocks = <&rclk_clk>, <&hp_clk>, <&hp_clk>; + clocks = <&sd2_clk>, <&sd1_clk>, <&cpg_clocks R8A7794_CLK_SD0>, + <&rclk_clk>, <&hp_clk>, <&hp_clk>; #clock-cells = <1>; clock-indices = < + R8A7794_CLK_SDHI2 R8A7794_CLK_SDHI1 R8A7794_CLK_SDHI0 R8A7794_CLK_CMT1 R8A7794_CLK_USBDMAC0 R8A7794_CLK_USBDMAC1 >; clock-output-names = + "sdhi2", "sdhi1", "sdhi0", "cmt1", "usbdmac0", "usbdmac1"; }; mstp7_clks: mstp7_clks@e615014c { diff --git a/include/dt-bindings/clock/r8a7794-clock.h b/include/dt-bindings/clock/r8a7794-clock.h index 94d96186ff0644..ccd566773cee59 100644 --- a/include/dt-bindings/clock/r8a7794-clock.h +++ b/include/dt-bindings/clock/r8a7794-clock.h @@ -52,6 +52,9 @@ #define R8A7794_CLK_SYS_DMAC0 19 /* MSTP3 */ +#define R8A7794_CLK_SDHI2 11 +#define R8A7794_CLK_SDHI1 12 +#define R8A7794_CLK_SDHI0 14 #define R8A7794_CLK_CMT1 29 #define R8A7794_CLK_USBDMAC0 30 #define R8A7794_CLK_USBDMAC1 31 From deac150c2d141c16c4814972c25c2a3aacae8d57 Mon Sep 17 00:00:00 2001 From: Shinobu Uehara Date: Tue, 27 May 2014 10:39:26 +0900 Subject: [PATCH 0278/3023] ARM: shmobile: r8a7794: Add MMCIF clock to device tree Signed-off-by: Shinobu Uehara [horms: omitted device node; only add clock] Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7794.dtsi | 15 +++++++++++---- include/dt-bindings/clock/r8a7794-clock.h | 1 + 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index c37667633e547f..8f78da5ef10b60 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -308,6 +308,13 @@ #clock-cells = <0>; clock-output-names = "sd2"; }; + mmc0_clk: mmc0_clk@e6150240 { + compatible = "renesas,r8a7794-div6-clock", "renesas,cpg-div6-clock"; + reg = <0 0xe6150240 0 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "mmc0"; + }; /* Fixed factor clocks */ pll1_div2_clk: pll1_div2_clk { @@ -512,16 +519,16 @@ compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>; clocks = <&sd2_clk>, <&sd1_clk>, <&cpg_clocks R8A7794_CLK_SD0>, - <&rclk_clk>, <&hp_clk>, <&hp_clk>; + <&mmc0_clk>, <&rclk_clk>, <&hp_clk>, <&hp_clk>; #clock-cells = <1>; clock-indices = < R8A7794_CLK_SDHI2 R8A7794_CLK_SDHI1 R8A7794_CLK_SDHI0 - R8A7794_CLK_CMT1 R8A7794_CLK_USBDMAC0 - R8A7794_CLK_USBDMAC1 + R8A7794_CLK_MMCIF0 R8A7794_CLK_CMT1 + R8A7794_CLK_USBDMAC0 R8A7794_CLK_USBDMAC1 >; clock-output-names = "sdhi2", "sdhi1", "sdhi0", - "cmt1", "usbdmac0", "usbdmac1"; + "mmcif0", "cmt1", "usbdmac0", "usbdmac1"; }; mstp7_clks: mstp7_clks@e615014c { compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; diff --git a/include/dt-bindings/clock/r8a7794-clock.h b/include/dt-bindings/clock/r8a7794-clock.h index ccd566773cee59..d63323032d6ef8 100644 --- a/include/dt-bindings/clock/r8a7794-clock.h +++ b/include/dt-bindings/clock/r8a7794-clock.h @@ -55,6 +55,7 @@ #define R8A7794_CLK_SDHI2 11 #define R8A7794_CLK_SDHI1 12 #define R8A7794_CLK_SDHI0 14 +#define R8A7794_CLK_MMCIF0 15 #define R8A7794_CLK_CMT1 29 #define R8A7794_CLK_USBDMAC0 30 #define R8A7794_CLK_USBDMAC1 31 From 6cdaa63f9e2b3ea0ac57a71a43f96cf626500d35 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 17 Dec 2014 17:18:13 +0100 Subject: [PATCH 0279/3023] ARM: shmobile: ape6evm: fix compatible string for Ethernet controller It's a 9220, not a 9118. Signed-off-by: Ulrich Hecht Acked-by: Laurent Pinchart Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a73a4-ape6evm.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm.dts b/arch/arm/boot/dts/r8a73a4-ape6evm.dts index ce085fa444a12a..baca8f8c4a5c8f 100644 --- a/arch/arm/boot/dts/r8a73a4-ape6evm.dts +++ b/arch/arm/boot/dts/r8a73a4-ape6evm.dts @@ -43,7 +43,7 @@ #size-cells = <1>; ethernet@8000000 { - compatible = "smsc,lan9118", "smsc,lan9115"; + compatible = "smsc,lan9220", "smsc,lan9115"; reg = <0x08000000 0x1000>; interrupt-parent = <&irqc1>; interrupts = <8 IRQ_TYPE_LEVEL_HIGH>; From 326baa8029706ba6fbba9dd40f2310f718bfab4b Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 17 Dec 2014 17:18:14 +0100 Subject: [PATCH 0280/3023] ARM: shmobile: ape6evm: synchronize dts with reference platform This moves everything to the legacy dts that is missing there in preparation for the switch to multiplatform. Signed-off-by: Ulrich Hecht Acked-by: Laurent Pinchart Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a73a4-ape6evm.dts | 92 ++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm.dts b/arch/arm/boot/dts/r8a73a4-ape6evm.dts index baca8f8c4a5c8f..c98cd1442d7c71 100644 --- a/arch/arm/boot/dts/r8a73a4-ape6evm.dts +++ b/arch/arm/boot/dts/r8a73a4-ape6evm.dts @@ -10,14 +10,19 @@ /dts-v1/; #include "r8a73a4.dtsi" -#include +#include / { model = "APE6EVM"; compatible = "renesas,ape6evm", "renesas,r8a73a4"; + aliases { + serial0 = &scifa0; + }; + chosen { bootargs = "console=ttySC0,115200 ignore_loglevel root=/dev/nfs ip=dhcp rw"; + stdout-path = &scifa0; }; memory@40000000 { @@ -30,7 +35,27 @@ reg = <2 0x00000000 0 0x40000000>; }; - ape6evm_fixed_3v3: fixedregulator@0 { + vcc_mmc0: regulator@0 { + compatible = "regulator-fixed"; + regulator-name = "MMC0 Vcc"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-always-on; + }; + + vcc_sdhi0: regulator@1 { + compatible = "regulator-fixed"; + + regulator-name = "SDHI0 Vcc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&pfc 76 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + /* Common 3.3V rail, used by several devices on APE6EVM */ + ape6evm_fixed_3v3: regulator@2 { compatible = "regulator-fixed"; regulator-name = "3V3"; regulator-min-microvolt = <3300000>; @@ -39,8 +64,10 @@ }; lbsc { + compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; + ranges = <0 0 0 0x20000000>; ethernet@8000000 { compatible = "smsc,lan9220", "smsc,lan9115"; @@ -79,3 +106,64 @@ >; voltage-tolerance = <1>; /* 1% */ }; + +&cmt1 { + status = "okay"; +}; + +&pfc { + scifa0_pins: serial0 { + renesas,groups = "scifa0_data"; + renesas,function = "scifa0"; + }; + + mmc0_pins: mmc { + renesas,groups = "mmc0_data8", "mmc0_ctrl"; + renesas,function = "mmc0"; + }; + + sdhi0_pins: sd0 { + renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd"; + renesas,function = "sdhi0"; + }; + + sdhi1_pins: sd1 { + renesas,groups = "sdhi1_data4", "sdhi1_ctrl"; + renesas,function = "sdhi1"; + }; +}; + +&mmcif0 { + vmmc-supply = <&vcc_mmc0>; + bus-width = <8>; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins>; + status = "okay"; +}; + +&scifa0 { + pinctrl-0 = <&scifa0_pins>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&sdhi0 { + vmmc-supply = <&vcc_sdhi0>; + bus-width = <4>; + toshiba,mmc-wrprotect-disable; + pinctrl-names = "default"; + pinctrl-0 = <&sdhi0_pins>; + status = "okay"; +}; + +&sdhi1 { + vmmc-supply = <&ape6evm_fixed_3v3>; + bus-width = <4>; + broken-cd; + toshiba,mmc-wrprotect-disable; + pinctrl-names = "default"; + pinctrl-0 = <&sdhi1_pins>; + status = "okay"; +}; From b742257dd5ec574a35950ebcf4a3d77a0f01355f Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 17 Dec 2014 17:18:15 +0100 Subject: [PATCH 0281/3023] ARM: shmobile: ape6evm: Add LEDs to the device tree Signed-off-by: Ulrich Hecht Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a73a4-ape6evm.dts | 28 +++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm.dts b/arch/arm/boot/dts/r8a73a4-ape6evm.dts index c98cd1442d7c71..b939a372d40842 100644 --- a/arch/arm/boot/dts/r8a73a4-ape6evm.dts +++ b/arch/arm/boot/dts/r8a73a4-ape6evm.dts @@ -82,6 +82,34 @@ vddvario-supply = <&ape6evm_fixed_3v3>; }; }; + + leds { + compatible = "gpio-leds"; + led1 { + gpios = <&pfc 28 GPIO_ACTIVE_LOW>; + label = "GNSS_EN"; + }; + led2 { + gpios = <&pfc 126 GPIO_ACTIVE_LOW>; + label = "NFC_NRST"; + }; + led3 { + gpios = <&pfc 132 GPIO_ACTIVE_LOW>; + label = "GNSS_NRST"; + }; + led4 { + gpios = <&pfc 232 GPIO_ACTIVE_LOW>; + label = "BT_WAKEUP"; + }; + led5 { + gpios = <&pfc 250 GPIO_ACTIVE_LOW>; + label = "STROBE"; + }; + led6 { + gpios = <&pfc 288 GPIO_ACTIVE_LOW>; + label = "BBRESETOUT"; + }; + }; }; &i2c5 { From 2670ee894f477c9dfe9da7cf774c167b2ba06594 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 17 Dec 2014 17:18:16 +0100 Subject: [PATCH 0282/3023] ARM: shmobile: ape6evm: Add keypad to the device tree Signed-off-by: Ulrich Hecht Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a73a4-ape6evm.dts | 41 +++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm.dts b/arch/arm/boot/dts/r8a73a4-ape6evm.dts index b939a372d40842..6b7bc1fb842e83 100644 --- a/arch/arm/boot/dts/r8a73a4-ape6evm.dts +++ b/arch/arm/boot/dts/r8a73a4-ape6evm.dts @@ -11,6 +11,7 @@ /dts-v1/; #include "r8a73a4.dtsi" #include +#include / { model = "APE6EVM"; @@ -110,6 +111,46 @@ label = "BBRESETOUT"; }; }; + + keyboard { + compatible = "gpio-keys"; + + zero-key { + gpios = <&pfc 324 GPIO_ACTIVE_LOW>; + linux,code = ; + label = "S16"; + }; + + menu-key { + gpios = <&pfc 325 GPIO_ACTIVE_LOW>; + linux,code = ; + label = "S17"; + }; + + home-key { + gpios = <&pfc 326 GPIO_ACTIVE_LOW>; + linux,code = ; + label = "S18"; + }; + + back-key { + gpios = <&pfc 327 GPIO_ACTIVE_LOW>; + linux,code = ; + label = "S19"; + }; + + volup-key { + gpios = <&pfc 328 GPIO_ACTIVE_LOW>; + linux,code = ; + label = "S20"; + }; + + voldown-key { + gpios = <&pfc 329 GPIO_ACTIVE_LOW>; + linux,code = ; + label = "S21"; + }; + }; }; &i2c5 { From 088b1691f560afa4e5e7990fd8081546236b39cf Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 17 Dec 2014 17:18:18 +0100 Subject: [PATCH 0283/3023] ARM: shmobile: r8a73a4: Add r8a73a4-ape6evm.dtb to ARCH_SHMOBILE_MULTI Makes sure the dtb is built for multiplatform builds. Signed-off-by: Ulrich Hecht Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 91bd5bd628576d..fabc56983d24c5 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -416,6 +416,7 @@ dtb-$(CONFIG_ARCH_SHMOBILE_LEGACY) += \ sh73a0-kzm9g-reference.dtb dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += emev2-kzm9d.dtb \ r7s72100-genmai.dtb \ + r8a73a4-ape6evm.dtb \ r8a7740-armadillo800eva.dtb \ r8a7779-marzen.dtb \ r8a7790-lager.dtb \ From 09ee81da85b10e0ca876977d333c8761441ecc78 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 17 Dec 2014 01:17:25 +0200 Subject: [PATCH 0284/3023] ARM: shmobile: ape6evm: Fix LAN9220 VDDVARIO voltage The LAN9220 VDDVARIO supply is powered by a 1.8V source, not 3.3V. Fix it in the device tree. Signed-off-by: Laurent Pinchart Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a73a4-ape6evm.dts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm.dts b/arch/arm/boot/dts/r8a73a4-ape6evm.dts index 6b7bc1fb842e83..0d50bef0123449 100644 --- a/arch/arm/boot/dts/r8a73a4-ape6evm.dts +++ b/arch/arm/boot/dts/r8a73a4-ape6evm.dts @@ -55,8 +55,16 @@ enable-active-high; }; - /* Common 3.3V rail, used by several devices on APE6EVM */ - ape6evm_fixed_3v3: regulator@2 { + /* Common 1.8V and 3.3V rails, used by several devices on APE6EVM */ + ape6evm_fixed_1v8: regulator@2 { + compatible = "regulator-fixed"; + regulator-name = "1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + ape6evm_fixed_3v3: regulator@3 { compatible = "regulator-fixed"; regulator-name = "3V3"; regulator-min-microvolt = <3300000>; @@ -80,7 +88,7 @@ smsc,irq-active-high; smsc,irq-push-pull; vdd33a-supply = <&ape6evm_fixed_3v3>; - vddvario-supply = <&ape6evm_fixed_3v3>; + vddvario-supply = <&ape6evm_fixed_1v8>; }; }; From 8b00601547ca28c5c55124dceba203b5f5e2c214 Mon Sep 17 00:00:00 2001 From: Richard Kunze Date: Sun, 14 Dec 2014 20:53:39 +0100 Subject: [PATCH 0285/3023] ARM: dts: use all remaining MTD space foor rootfs of Iomega ix2-200 The original MTD partition layout for the Iomega ix2-200 leaves most of the available space unused. This patch changes the layout to use all remaining MTD space after the partitions for u-boot/u-boot-env and the kernel uimage as a "rootfs" partition. Signed-off-by: Richard Kunze Signed-off-by: Andrew Lunn --- arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts b/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts index 05291f3990d035..2a5c5a33db0c79 100644 --- a/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts +++ b/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts @@ -192,8 +192,8 @@ }; partition@400000 { - label = "uInitrd"; - reg = <0x540000 0x1000000>; + label = "rootfs"; + reg = <0x400000 0x1C00000>; }; }; From 1701308a6e2407e144cb5af729e5b51731a3957d Mon Sep 17 00:00:00 2001 From: Richard Kunze Date: Wed, 10 Dec 2014 19:40:41 +0100 Subject: [PATCH 0286/3023] ARM: dts: add gpio_poweroff support for Iomega ix2-200 Iomega ix2-200 can be powered off via GPIO 0 pin 17, this patch wires up the gpio-poweroff driver to do it. Signed-off-by: Richard Kunze Acked-by: Andrew Lunn Signed-off-by: Andrew Lunn --- arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts b/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts index 2a5c5a33db0c79..8474bffec0ca43 100644 --- a/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts +++ b/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts @@ -169,6 +169,10 @@ gpios = <&gpio1 3 GPIO_ACTIVE_LOW>; }; }; + gpio-poweroff { + compatible = "gpio-poweroff"; + gpios = <&gpio0 17 GPIO_ACTIVE_LOW>; + }; }; &nand { From 9c569b390923f10d5551aa56c9e68f132459e0cc Mon Sep 17 00:00:00 2001 From: Evgeni Dobrev Date: Tue, 16 Dec 2014 19:22:18 +0100 Subject: [PATCH 0287/3023] ARM: dts: kirkwood: enable phy driver for SATA controller on 88f6192 This patch enables the phy drivers for the SATA controller on Marvell's 88f6192. Without them it is not possible to use SATA drives attached to this processor. Signed-off-by: Evgeni Dobrev Acked-by: Andrew Lunn Signed-off-by: Andrew Lunn --- arch/arm/boot/dts/kirkwood-6192.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/kirkwood-6192.dtsi b/arch/arm/boot/dts/kirkwood-6192.dtsi index dd81508b919b87..9e6e9e2691d5d7 100644 --- a/arch/arm/boot/dts/kirkwood-6192.dtsi +++ b/arch/arm/boot/dts/kirkwood-6192.dtsi @@ -66,6 +66,8 @@ interrupts = <21>; clocks = <&gate_clk 14>, <&gate_clk 15>; clock-names = "0", "1"; + phys = <&sata_phy0>, <&sata_phy1>; + phy-names = "port0", "port1"; status = "disabled"; }; From e42dcfbba1f0ab3050a7c550a4119e2945553042 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 2 Dec 2014 18:06:52 +0100 Subject: [PATCH 0288/3023] ARM: mvebu: enable CPUFREQ_DT in mvebu_v7_defconfig This patch enables the cpufreq-dt driver in mvebu_v7_defconfig, as it is used on Armada XP platforms. Signed-off-by: Thomas Petazzoni Signed-off-by: Andrew Lunn --- arch/arm/configs/mvebu_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/mvebu_v7_defconfig b/arch/arm/configs/mvebu_v7_defconfig index 627accea72fbec..05edf4622c8def 100644 --- a/arch/arm/configs/mvebu_v7_defconfig +++ b/arch/arm/configs/mvebu_v7_defconfig @@ -26,6 +26,7 @@ CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_ARM_APPENDED_DTB=y CONFIG_ARM_ATAG_DTB_COMPAT=y CONFIG_CPU_FREQ=y +CONFIG_CPUFREQ_DT=y CONFIG_CPU_IDLE=y CONFIG_ARM_MVEBU_V7_CPUIDLE=y CONFIG_VFP=y From f74ba117dab86b35e15f8b5a8d913145f3e72ca1 Mon Sep 17 00:00:00 2001 From: Addy Ke Date: Thu, 4 Dec 2014 10:49:35 +0800 Subject: [PATCH 0289/3023] ARM: dts: rockchip: set dw_mmc max-freq 150Mhz All of mmc controllers include SDMMC, SDIO0, SDIO1, and EMMC on RK3288 are limited to 150Mhz. It was mainly caused by two reasons: - RK3288's IO pad(except DDR IO pad) is generic, which can only support the max of 150Mhz. - Mmc controller was designed at 150Mhz, and the pressure test by IC team was based on this freequency point. Signed-off-by: Addy Ke Reviewed-by: Doug Anderson Tested-by: Doug Anderson Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index fd19f00784bdc2..3aad41d873d302 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -151,6 +151,7 @@ sdmmc: dwmmc@ff0c0000 { compatible = "rockchip,rk3288-dw-mshc"; + clock-freq-min-max = <400000 150000000>; clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>; clock-names = "biu", "ciu"; fifo-depth = <0x100>; @@ -161,6 +162,7 @@ sdio0: dwmmc@ff0d0000 { compatible = "rockchip,rk3288-dw-mshc"; + clock-freq-min-max = <400000 150000000>; clocks = <&cru HCLK_SDIO0>, <&cru SCLK_SDIO0>; clock-names = "biu", "ciu"; fifo-depth = <0x100>; @@ -171,6 +173,7 @@ sdio1: dwmmc@ff0e0000 { compatible = "rockchip,rk3288-dw-mshc"; + clock-freq-min-max = <400000 150000000>; clocks = <&cru HCLK_SDIO1>, <&cru SCLK_SDIO1>; clock-names = "biu", "ciu"; fifo-depth = <0x100>; @@ -181,6 +184,7 @@ emmc: dwmmc@ff0f0000 { compatible = "rockchip,rk3288-dw-mshc"; + clock-freq-min-max = <400000 150000000>; clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>; clock-names = "biu", "ciu"; fifo-depth = <0x100>; From be95f0fa0cde56bb05ed62488a25a73a5b21b2d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Svenning=20S=C3=B8rensen?= Date: Fri, 5 Dec 2014 01:18:57 +0100 Subject: [PATCH 0290/3023] crypto: atmel_sha - remove unused shash fallback instance. The fallback is never used, so there is no point in having it. The cra_exit routine can also be removed, since all it did was releasing the fallback, along with the stub around cra_init, which just added an unused NULL argument. Signed-off-by: Svenning Soerensen Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha.c | 50 +++++--------------------------------- 1 file changed, 6 insertions(+), 44 deletions(-) diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index d94f07c78e1936..34db04addc18a4 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -102,10 +102,6 @@ struct atmel_sha_ctx { struct atmel_sha_dev *dd; unsigned long flags; - - /* fallback stuff */ - struct crypto_shash *fallback; - }; #define ATMEL_SHA_QUEUE_LENGTH 50 @@ -974,19 +970,8 @@ static int atmel_sha_digest(struct ahash_request *req) return atmel_sha_init(req) ?: atmel_sha_finup(req); } -static int atmel_sha_cra_init_alg(struct crypto_tfm *tfm, const char *alg_base) +static int atmel_sha_cra_init(struct crypto_tfm *tfm) { - struct atmel_sha_ctx *tctx = crypto_tfm_ctx(tfm); - const char *alg_name = crypto_tfm_alg_name(tfm); - - /* Allocate a fallback and abort if it failed. */ - tctx->fallback = crypto_alloc_shash(alg_name, 0, - CRYPTO_ALG_NEED_FALLBACK); - if (IS_ERR(tctx->fallback)) { - pr_err("atmel-sha: fallback driver '%s' could not be loaded.\n", - alg_name); - return PTR_ERR(tctx->fallback); - } crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), sizeof(struct atmel_sha_reqctx) + SHA_BUFFER_LEN + SHA512_BLOCK_SIZE); @@ -994,19 +979,6 @@ static int atmel_sha_cra_init_alg(struct crypto_tfm *tfm, const char *alg_base) return 0; } -static int atmel_sha_cra_init(struct crypto_tfm *tfm) -{ - return atmel_sha_cra_init_alg(tfm, NULL); -} - -static void atmel_sha_cra_exit(struct crypto_tfm *tfm) -{ - struct atmel_sha_ctx *tctx = crypto_tfm_ctx(tfm); - - crypto_free_shash(tctx->fallback); - tctx->fallback = NULL; -} - static struct ahash_alg sha_1_256_algs[] = { { .init = atmel_sha_init, @@ -1020,14 +992,12 @@ static struct ahash_alg sha_1_256_algs[] = { .cra_name = "sha1", .cra_driver_name = "atmel-sha1", .cra_priority = 100, - .cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_NEED_FALLBACK, + .cra_flags = CRYPTO_ALG_ASYNC, .cra_blocksize = SHA1_BLOCK_SIZE, .cra_ctxsize = sizeof(struct atmel_sha_ctx), .cra_alignmask = 0, .cra_module = THIS_MODULE, .cra_init = atmel_sha_cra_init, - .cra_exit = atmel_sha_cra_exit, } } }, @@ -1043,14 +1013,12 @@ static struct ahash_alg sha_1_256_algs[] = { .cra_name = "sha256", .cra_driver_name = "atmel-sha256", .cra_priority = 100, - .cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_NEED_FALLBACK, + .cra_flags = CRYPTO_ALG_ASYNC, .cra_blocksize = SHA256_BLOCK_SIZE, .cra_ctxsize = sizeof(struct atmel_sha_ctx), .cra_alignmask = 0, .cra_module = THIS_MODULE, .cra_init = atmel_sha_cra_init, - .cra_exit = atmel_sha_cra_exit, } } }, @@ -1068,14 +1036,12 @@ static struct ahash_alg sha_224_alg = { .cra_name = "sha224", .cra_driver_name = "atmel-sha224", .cra_priority = 100, - .cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_NEED_FALLBACK, + .cra_flags = CRYPTO_ALG_ASYNC, .cra_blocksize = SHA224_BLOCK_SIZE, .cra_ctxsize = sizeof(struct atmel_sha_ctx), .cra_alignmask = 0, .cra_module = THIS_MODULE, .cra_init = atmel_sha_cra_init, - .cra_exit = atmel_sha_cra_exit, } } }; @@ -1093,14 +1059,12 @@ static struct ahash_alg sha_384_512_algs[] = { .cra_name = "sha384", .cra_driver_name = "atmel-sha384", .cra_priority = 100, - .cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_NEED_FALLBACK, + .cra_flags = CRYPTO_ALG_ASYNC, .cra_blocksize = SHA384_BLOCK_SIZE, .cra_ctxsize = sizeof(struct atmel_sha_ctx), .cra_alignmask = 0x3, .cra_module = THIS_MODULE, .cra_init = atmel_sha_cra_init, - .cra_exit = atmel_sha_cra_exit, } } }, @@ -1116,14 +1080,12 @@ static struct ahash_alg sha_384_512_algs[] = { .cra_name = "sha512", .cra_driver_name = "atmel-sha512", .cra_priority = 100, - .cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_NEED_FALLBACK, + .cra_flags = CRYPTO_ALG_ASYNC, .cra_blocksize = SHA512_BLOCK_SIZE, .cra_ctxsize = sizeof(struct atmel_sha_ctx), .cra_alignmask = 0x3, .cra_module = THIS_MODULE, .cra_init = atmel_sha_cra_init, - .cra_exit = atmel_sha_cra_exit, } } }, From a861afbc931b489b3b2362f8011cccd2a071ec37 Mon Sep 17 00:00:00 2001 From: "Joshua I. James" Date: Fri, 5 Dec 2014 14:06:16 +0900 Subject: [PATCH 0291/3023] crypto: ablkcipher - fixed style errors in ablkcipher.c Fixed style errors reported by checkpatch. WARNING: Missing a blank line after declarations + u8 *end_page = (u8 *)(((unsigned long)(start + len - 1)) & PAGE_MASK); + return max(start, end_page); WARNING: line over 80 characters + scatterwalk_start(&walk->out, scatterwalk_sg_next(walk->out.sg)); WARNING: Missing a blank line after declarations + int err = ablkcipher_copy_iv(walk, tfm, alignmask); + if (err) ERROR: do not use assignment in if condition + if ((err = crypto_register_instance(tmpl, inst))) { Signed-off-by: Joshua I. James Signed-off-by: Herbert Xu --- crypto/ablkcipher.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c index 40886c489903b7..7bbc8b4ef2e993 100644 --- a/crypto/ablkcipher.c +++ b/crypto/ablkcipher.c @@ -69,6 +69,7 @@ static inline void ablkcipher_queue_write(struct ablkcipher_walk *walk, static inline u8 *ablkcipher_get_spot(u8 *start, unsigned int len) { u8 *end_page = (u8 *)(((unsigned long)(start + len - 1)) & PAGE_MASK); + return max(start, end_page); } @@ -86,7 +87,8 @@ static inline unsigned int ablkcipher_done_slow(struct ablkcipher_walk *walk, if (n == len_this_page) break; n -= len_this_page; - scatterwalk_start(&walk->out, scatterwalk_sg_next(walk->out.sg)); + scatterwalk_start(&walk->out, scatterwalk_sg_next( + walk->out.sg)); } return bsize; @@ -284,6 +286,7 @@ static int ablkcipher_walk_first(struct ablkcipher_request *req, walk->iv = req->info; if (unlikely(((unsigned long)walk->iv & alignmask))) { int err = ablkcipher_copy_iv(walk, tfm, alignmask); + if (err) return err; } @@ -589,7 +592,8 @@ static int crypto_givcipher_default(struct crypto_alg *alg, u32 type, u32 mask) if (IS_ERR(inst)) goto put_tmpl; - if ((err = crypto_register_instance(tmpl, inst))) { + err = crypto_register_instance(tmpl, inst); + if (err) { tmpl->free(inst); goto put_tmpl; } From 4fad478ae0ff7bd27c853a085555317c0dc68704 Mon Sep 17 00:00:00 2001 From: "Joshua I. James" Date: Fri, 5 Dec 2014 14:24:44 +0900 Subject: [PATCH 0292/3023] crypto: aead - fixed style error in aead.c Fixed style error identified by checkpatch. ERROR: do not use assignment in if condition + if ((err = crypto_register_instance(tmpl, inst))) { Signed-off-by: Joshua I. James Signed-off-by: Herbert Xu --- crypto/aead.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crypto/aead.c b/crypto/aead.c index 547491e35c6373..222271070b4918 100644 --- a/crypto/aead.c +++ b/crypto/aead.c @@ -448,7 +448,8 @@ static int crypto_nivaead_default(struct crypto_alg *alg, u32 type, u32 mask) if (IS_ERR(inst)) goto put_tmpl; - if ((err = crypto_register_instance(tmpl, inst))) { + err = crypto_register_instance(tmpl, inst); + if (err) { tmpl->free(inst); goto put_tmpl; } From 267c4221ff574ac70ec0b02b923b16f39b54da1a Mon Sep 17 00:00:00 2001 From: "Joshua I. James" Date: Fri, 5 Dec 2014 14:38:40 +0900 Subject: [PATCH 0293/3023] crypto: af_alg - fixed style error in af_alg.c Fixed style error identified by checkpatch. ERROR: space required before the open parenthesis '(' + switch(cmsg->cmsg_type) { Signed-off-by: Joshua I. James Signed-off-by: Herbert Xu --- crypto/af_alg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/af_alg.c b/crypto/af_alg.c index 4665b79c729ac1..8ffc174a015427 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -405,7 +405,7 @@ int af_alg_cmsg_send(struct msghdr *msg, struct af_alg_control *con) if (cmsg->cmsg_level != SOL_ALG) continue; - switch(cmsg->cmsg_type) { + switch (cmsg->cmsg_type) { case ALG_SET_IV: if (cmsg->cmsg_len < CMSG_LEN(sizeof(*con->iv))) return -EINVAL; From b516d514020f17c83267f76366691e4cc9b7bddf Mon Sep 17 00:00:00 2001 From: "Joshua I. James" Date: Fri, 5 Dec 2014 14:44:54 +0900 Subject: [PATCH 0294/3023] crypto: ahash - fixed style error in ahash.c Fixed style error identified by checkpatch. WARNING: Missing a blank line after declarations + unsigned int unaligned = alignmask + 1 - (offset & alignmask); + if (nbytes > unaligned) Signed-off-by: Joshua I. James Signed-off-by: Herbert Xu --- crypto/ahash.c | 1 + 1 file changed, 1 insertion(+) diff --git a/crypto/ahash.c b/crypto/ahash.c index f6a36a52d738b4..dd2890608aebaa 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -55,6 +55,7 @@ static int hash_walk_next(struct crypto_hash_walk *walk) if (offset & alignmask) { unsigned int unaligned = alignmask + 1 - (offset & alignmask); + if (nbytes > unaligned) nbytes = unaligned; } From 0efcb8d5b2f7af86818179810cc080b326a83e19 Mon Sep 17 00:00:00 2001 From: "Joshua I. James" Date: Fri, 5 Dec 2014 15:00:10 +0900 Subject: [PATCH 0295/3023] crypto: api - fixed style erro in algapi.c Fixed style error identified by checkpatch. WARNING: Missing a blank line after declarations + int err = crypto_remove_alg(&inst->alg, &users); + BUG_ON(err); Signed-off-by: Joshua I. James Signed-off-by: Herbert Xu --- crypto/algapi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/crypto/algapi.c b/crypto/algapi.c index 71a8143e23b133..83b04e0884b10c 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -473,6 +473,7 @@ void crypto_unregister_template(struct crypto_template *tmpl) list = &tmpl->instances; hlist_for_each_entry(inst, list, list) { int err = crypto_remove_alg(&inst->alg, &users); + BUG_ON(err); } From 905b42e559fa4952569b3444bc6c054c0103e5a0 Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Fri, 5 Dec 2014 22:40:21 +0100 Subject: [PATCH 0296/3023] crypto: drbg - panic on continuous self test error This patch adds a panic if the FIPS 140-2 self test error failed. Note, that entire code is only executed with fips_enabled (i.e. when the kernel is booted with fips=1. It is therefore not executed for 99.9% of all user base. As mathematically such failure cannot occur, this panic should never be triggered. But to comply with NISTs current requirements, an endless loop must be replaced with the panic. When the new version of FIPS 140 will be released, this entire continuous self test function will be ripped out as it will not be needed any more. This patch is functionally equivalent as implemented in ansi_cprng.c and drivers/char/random.c. Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/drbg.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index d748a1d0ca24b5..96138396ce019d 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -223,15 +223,6 @@ static inline unsigned short drbg_sec_strength(drbg_flag_t flags) * function. Thus, the function implicitly knows the size of the * buffer. * - * The FIPS test can be called in an endless loop until it returns - * true. Although the code looks like a potential for a deadlock, it - * is not the case, because returning a false cannot mathematically - * occur (except once when a reseed took place and the updated state - * would is now set up such that the generation of new value returns - * an identical one -- this is most unlikely and would happen only once). - * Thus, if this function repeatedly returns false and thus would cause - * a deadlock, the integrity of the entire kernel is lost. - * * @drbg DRBG handle * @buf output buffer of random data to be checked * @@ -258,6 +249,8 @@ static bool drbg_fips_continuous_test(struct drbg_state *drbg, return false; } ret = memcmp(drbg->prev, buf, drbg_blocklen(drbg)); + if (!ret) + panic("DRBG continuous self test failed\n"); memcpy(drbg->prev, buf, drbg_blocklen(drbg)); /* the test shall pass when the two compared values are not equal */ return ret != 0; From 25fb8638e919bc7431a73f2fb4a9713818ae2c9d Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Sun, 7 Dec 2014 23:21:42 +0100 Subject: [PATCH 0297/3023] crypto: af_alg - add setsockopt for auth tag size Use setsockopt on the tfm FD to provide the authentication tag size for an AEAD cipher. This is achieved by adding a callback function which is intended to be used by the AEAD AF_ALG implementation. The optlen argument of the setsockopt specifies the authentication tag size to be used with the AEAD tfm. Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/af_alg.c | 7 +++++++ include/crypto/if_alg.h | 1 + 2 files changed, 8 insertions(+) diff --git a/crypto/af_alg.c b/crypto/af_alg.c index 8ffc174a015427..a8ff3c44e13ca6 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -215,6 +215,13 @@ static int alg_setsockopt(struct socket *sock, int level, int optname, goto unlock; err = alg_setkey(sk, optval, optlen); + break; + case ALG_SET_AEAD_AUTHSIZE: + if (sock->state == SS_CONNECTED) + goto unlock; + if (!type->setauthsize) + goto unlock; + err = type->setauthsize(ask->private, optlen); } unlock: diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h index cd62bf4289e957..5c7b6c53e96f17 100644 --- a/include/crypto/if_alg.h +++ b/include/crypto/if_alg.h @@ -50,6 +50,7 @@ struct af_alg_type { void (*release)(void *private); int (*setkey)(void *private, const u8 *key, unsigned int keylen); int (*accept)(void *private, struct sock *sk); + int (*setauthsize)(void *private, unsigned int authsize); struct proto_ops *ops; struct module *owner; From 9372b35e11149c5314f56f939775e67d83057604 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 8 Dec 2014 16:50:35 +0800 Subject: [PATCH 0298/3023] hwrng: place mutex around read functions and buffers. There's currently a big lock around everything, and it means that we can't query sysfs (eg /sys/devices/virtual/misc/hw_random/rng_current) while the rng is reading. This is a real problem when the rng is slow, or blocked (eg. virtio_rng with qemu's default /dev/random backend) This doesn't help (it leaves the current lock untouched), just adds a lock to protect the read function and the static buffers, in preparation for transition. Signed-off-by: Rusty Russell Signed-off-by: Herbert Xu --- drivers/char/hw_random/core.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 1500cfd799a79e..2dd3144d69b1c6 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -53,7 +53,10 @@ static struct hwrng *current_rng; static struct task_struct *hwrng_fill; static LIST_HEAD(rng_list); +/* Protects rng_list and current_rng */ static DEFINE_MUTEX(rng_mutex); +/* Protects rng read functions, data_avail, rng_buffer and rng_fillbuf */ +static DEFINE_MUTEX(reading_mutex); static int data_avail; static u8 *rng_buffer, *rng_fillbuf; static unsigned short current_quality; @@ -81,7 +84,9 @@ static void add_early_randomness(struct hwrng *rng) unsigned char bytes[16]; int bytes_read; + mutex_lock(&reading_mutex); bytes_read = rng_get_data(rng, bytes, sizeof(bytes), 1); + mutex_unlock(&reading_mutex); if (bytes_read > 0) add_device_randomness(bytes, bytes_read); } @@ -128,6 +133,7 @@ static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size, int wait) { int present; + BUG_ON(!mutex_is_locked(&reading_mutex)); if (rng->read) return rng->read(rng, (void *)buffer, size, wait); @@ -160,13 +166,14 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf, goto out_unlock; } + mutex_lock(&reading_mutex); if (!data_avail) { bytes_read = rng_get_data(current_rng, rng_buffer, rng_buffer_size(), !(filp->f_flags & O_NONBLOCK)); if (bytes_read < 0) { err = bytes_read; - goto out_unlock; + goto out_unlock_reading; } data_avail = bytes_read; } @@ -174,7 +181,7 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf, if (!data_avail) { if (filp->f_flags & O_NONBLOCK) { err = -EAGAIN; - goto out_unlock; + goto out_unlock_reading; } } else { len = data_avail; @@ -186,7 +193,7 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf, if (copy_to_user(buf + ret, rng_buffer + data_avail, len)) { err = -EFAULT; - goto out_unlock; + goto out_unlock_reading; } size -= len; @@ -194,6 +201,7 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf, } mutex_unlock(&rng_mutex); + mutex_unlock(&reading_mutex); if (need_resched()) schedule_timeout_interruptible(1); @@ -208,6 +216,9 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf, out_unlock: mutex_unlock(&rng_mutex); goto out; +out_unlock_reading: + mutex_unlock(&reading_mutex); + goto out_unlock; } @@ -344,13 +355,16 @@ static int hwrng_fillfn(void *unused) while (!kthread_should_stop()) { if (!current_rng) break; + mutex_lock(&reading_mutex); rc = rng_get_data(current_rng, rng_fillbuf, rng_buffer_size(), 1); + mutex_unlock(&reading_mutex); if (rc <= 0) { pr_warn("hwrng: no data available\n"); msleep_interruptible(10000); continue; } + /* Outside lock, sure, but y'know: randomness. */ add_hwgenerator_randomness((void *)rng_fillbuf, rc, rc * current_quality * 8 >> 10); } From 1dacb395d68a14825ee48c0843335e3181aea675 Mon Sep 17 00:00:00 2001 From: Amos Kong Date: Mon, 8 Dec 2014 16:50:36 +0800 Subject: [PATCH 0299/3023] hwrng: move some code out mutex_lock for avoiding underlying deadlock In next patch, we use reference counting for each struct hwrng, changing reference count also needs to take mutex_lock. Before releasing the lock, if we try to stop a kthread that waits to take the lock to reduce the referencing count, deadlock will occur. Signed-off-by: Amos Kong Signed-off-by: Herbert Xu --- drivers/char/hw_random/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 2dd3144d69b1c6..b4c0e873d36245 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -470,12 +470,12 @@ void hwrng_unregister(struct hwrng *rng) } } if (list_empty(&rng_list)) { + mutex_unlock(&rng_mutex); unregister_miscdev(); if (hwrng_fill) kthread_stop(hwrng_fill); - } - - mutex_unlock(&rng_mutex); + } else + mutex_unlock(&rng_mutex); } EXPORT_SYMBOL_GPL(hwrng_unregister); From 3a2c0ba5ad00c018c0bef39a2224aca950aa33f2 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 8 Dec 2014 16:50:37 +0800 Subject: [PATCH 0300/3023] hwrng: use reference counts on each struct hwrng. current_rng holds one reference, and we bump it every time we want to do a read from it. This means we only hold the rng_mutex to grab or drop a reference, so accessing /sys/devices/virtual/misc/hw_random/rng_current doesn't block on read of /dev/hwrng. Using a kref is overkill (we're always under the rng_mutex), but a standard pattern. This also solves the problem that the hwrng_fillfn thread was accessing current_rng without a lock, which could change (eg. to NULL) underneath it. Signed-off-by: Rusty Russell Signed-off-by: Amos Kong Signed-off-by: Herbert Xu --- drivers/char/hw_random/core.c | 135 +++++++++++++++++++++++----------- include/linux/hw_random.h | 2 + 2 files changed, 94 insertions(+), 43 deletions(-) diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index b4c0e873d36245..089c18dc579ead 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -42,6 +42,7 @@ #include #include #include +#include #include @@ -91,6 +92,60 @@ static void add_early_randomness(struct hwrng *rng) add_device_randomness(bytes, bytes_read); } +static inline void cleanup_rng(struct kref *kref) +{ + struct hwrng *rng = container_of(kref, struct hwrng, ref); + + if (rng->cleanup) + rng->cleanup(rng); +} + +static void set_current_rng(struct hwrng *rng) +{ + BUG_ON(!mutex_is_locked(&rng_mutex)); + kref_get(&rng->ref); + current_rng = rng; +} + +static void drop_current_rng(void) +{ + BUG_ON(!mutex_is_locked(&rng_mutex)); + if (!current_rng) + return; + + /* decrease last reference for triggering the cleanup */ + kref_put(¤t_rng->ref, cleanup_rng); + current_rng = NULL; +} + +/* Returns ERR_PTR(), NULL or refcounted hwrng */ +static struct hwrng *get_current_rng(void) +{ + struct hwrng *rng; + + if (mutex_lock_interruptible(&rng_mutex)) + return ERR_PTR(-ERESTARTSYS); + + rng = current_rng; + if (rng) + kref_get(&rng->ref); + + mutex_unlock(&rng_mutex); + return rng; +} + +static void put_rng(struct hwrng *rng) +{ + /* + * Hold rng_mutex here so we serialize in case they set_current_rng + * on rng again immediately. + */ + mutex_lock(&rng_mutex); + if (rng) + kref_put(&rng->ref, cleanup_rng); + mutex_unlock(&rng_mutex); +} + static inline int hwrng_init(struct hwrng *rng) { if (rng->init) { @@ -113,12 +168,6 @@ static inline int hwrng_init(struct hwrng *rng) return 0; } -static inline void hwrng_cleanup(struct hwrng *rng) -{ - if (rng && rng->cleanup) - rng->cleanup(rng); -} - static int rng_dev_open(struct inode *inode, struct file *filp) { /* enforce read-only access to this chrdev */ @@ -154,21 +203,22 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf, ssize_t ret = 0; int err = 0; int bytes_read, len; + struct hwrng *rng; while (size) { - if (mutex_lock_interruptible(&rng_mutex)) { - err = -ERESTARTSYS; + rng = get_current_rng(); + if (IS_ERR(rng)) { + err = PTR_ERR(rng); goto out; } - - if (!current_rng) { + if (!rng) { err = -ENODEV; - goto out_unlock; + goto out; } mutex_lock(&reading_mutex); if (!data_avail) { - bytes_read = rng_get_data(current_rng, rng_buffer, + bytes_read = rng_get_data(rng, rng_buffer, rng_buffer_size(), !(filp->f_flags & O_NONBLOCK)); if (bytes_read < 0) { @@ -200,8 +250,8 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf, ret += len; } - mutex_unlock(&rng_mutex); mutex_unlock(&reading_mutex); + put_rng(rng); if (need_resched()) schedule_timeout_interruptible(1); @@ -213,12 +263,11 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf, } out: return ret ? : err; -out_unlock: - mutex_unlock(&rng_mutex); - goto out; + out_unlock_reading: mutex_unlock(&reading_mutex); - goto out_unlock; + put_rng(rng); + goto out; } @@ -257,8 +306,8 @@ static ssize_t hwrng_attr_current_store(struct device *dev, err = hwrng_init(rng); if (err) break; - hwrng_cleanup(current_rng); - current_rng = rng; + drop_current_rng(); + set_current_rng(rng); err = 0; break; } @@ -272,17 +321,15 @@ static ssize_t hwrng_attr_current_show(struct device *dev, struct device_attribute *attr, char *buf) { - int err; ssize_t ret; - const char *name = "none"; + struct hwrng *rng; - err = mutex_lock_interruptible(&rng_mutex); - if (err) - return -ERESTARTSYS; - if (current_rng) - name = current_rng->name; - ret = snprintf(buf, PAGE_SIZE, "%s\n", name); - mutex_unlock(&rng_mutex); + rng = get_current_rng(); + if (IS_ERR(rng)) + return PTR_ERR(rng); + + ret = snprintf(buf, PAGE_SIZE, "%s\n", rng ? rng->name : "none"); + put_rng(rng); return ret; } @@ -353,12 +400,16 @@ static int hwrng_fillfn(void *unused) long rc; while (!kthread_should_stop()) { - if (!current_rng) + struct hwrng *rng; + + rng = get_current_rng(); + if (IS_ERR(rng) || !rng) break; mutex_lock(&reading_mutex); - rc = rng_get_data(current_rng, rng_fillbuf, + rc = rng_get_data(rng, rng_fillbuf, rng_buffer_size(), 1); mutex_unlock(&reading_mutex); + put_rng(rng); if (rc <= 0) { pr_warn("hwrng: no data available\n"); msleep_interruptible(10000); @@ -419,14 +470,13 @@ int hwrng_register(struct hwrng *rng) err = hwrng_init(rng); if (err) goto out_unlock; - current_rng = rng; + set_current_rng(rng); } err = 0; if (!old_rng) { err = register_miscdev(); if (err) { - hwrng_cleanup(rng); - current_rng = NULL; + drop_current_rng(); goto out_unlock; } } @@ -453,22 +503,21 @@ EXPORT_SYMBOL_GPL(hwrng_register); void hwrng_unregister(struct hwrng *rng) { - int err; - mutex_lock(&rng_mutex); list_del(&rng->list); if (current_rng == rng) { - hwrng_cleanup(rng); - if (list_empty(&rng_list)) { - current_rng = NULL; - } else { - current_rng = list_entry(rng_list.prev, struct hwrng, list); - err = hwrng_init(current_rng); - if (err) - current_rng = NULL; + drop_current_rng(); + if (!list_empty(&rng_list)) { + struct hwrng *tail; + + tail = list_entry(rng_list.prev, struct hwrng, list); + + if (hwrng_init(tail) == 0) + set_current_rng(tail); } } + if (list_empty(&rng_list)) { mutex_unlock(&rng_mutex); unregister_miscdev(); diff --git a/include/linux/hw_random.h b/include/linux/hw_random.h index 914bb08cd73819..c212e71ea88625 100644 --- a/include/linux/hw_random.h +++ b/include/linux/hw_random.h @@ -14,6 +14,7 @@ #include #include +#include /** * struct hwrng - Hardware Random Number Generator driver @@ -44,6 +45,7 @@ struct hwrng { /* internal. */ struct list_head list; + struct kref ref; }; /** Register a new Hardware Random Number Generator driver. */ From a027f30d72f2c4d27d6dd9bd053205d3102de7d1 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 8 Dec 2014 16:50:38 +0800 Subject: [PATCH 0301/3023] hwrng: fix unregister race. The previous patch added one potential problem: we can still be reading from a hwrng when it's unregistered. Add a wait for zero in the hwrng_unregister path. Signed-off-by: Rusty Russell Signed-off-by: Amos Kong Signed-off-by: Herbert Xu --- drivers/char/hw_random/core.c | 12 ++++++++++++ include/linux/hw_random.h | 1 + 2 files changed, 13 insertions(+) diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 089c18dc579ead..8d609a026465a7 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -60,6 +60,7 @@ static DEFINE_MUTEX(rng_mutex); static DEFINE_MUTEX(reading_mutex); static int data_avail; static u8 *rng_buffer, *rng_fillbuf; +static DECLARE_WAIT_QUEUE_HEAD(rng_done); static unsigned short current_quality; static unsigned short default_quality; /* = 0; default to "off" */ @@ -98,6 +99,11 @@ static inline void cleanup_rng(struct kref *kref) if (rng->cleanup) rng->cleanup(rng); + + /* cleanup_done should be updated after cleanup finishes */ + smp_wmb(); + rng->cleanup_done = true; + wake_up_all(&rng_done); } static void set_current_rng(struct hwrng *rng) @@ -494,6 +500,8 @@ int hwrng_register(struct hwrng *rng) add_early_randomness(rng); } + rng->cleanup_done = false; + out_unlock: mutex_unlock(&rng_mutex); out: @@ -525,6 +533,10 @@ void hwrng_unregister(struct hwrng *rng) kthread_stop(hwrng_fill); } else mutex_unlock(&rng_mutex); + + /* Just in case rng is reading right now, wait. */ + wait_event(rng_done, rng->cleanup_done && + atomic_read(&rng->ref.refcount) == 0); } EXPORT_SYMBOL_GPL(hwrng_unregister); diff --git a/include/linux/hw_random.h b/include/linux/hw_random.h index c212e71ea88625..7832e5008959e6 100644 --- a/include/linux/hw_random.h +++ b/include/linux/hw_random.h @@ -46,6 +46,7 @@ struct hwrng { /* internal. */ struct list_head list; struct kref ref; + bool cleanup_done; }; /** Register a new Hardware Random Number Generator driver. */ From ebbbfa248389b176e2e62d8cf91814253849ccc9 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 8 Dec 2014 16:50:39 +0800 Subject: [PATCH 0302/3023] hwrng: don't double-check old_rng. Interesting anti-pattern. Signed-off-by: Rusty Russell Signed-off-by: Herbert Xu --- drivers/char/hw_random/core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 8d609a026465a7..e384ee3ed604d8 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -472,14 +472,13 @@ int hwrng_register(struct hwrng *rng) } old_rng = current_rng; + err = 0; if (!old_rng) { err = hwrng_init(rng); if (err) goto out_unlock; set_current_rng(rng); - } - err = 0; - if (!old_rng) { + err = register_miscdev(); if (err) { drop_current_rng(); From 2d2ec0642a85966b6a299bbcd94707982327ace8 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 8 Dec 2014 16:50:40 +0800 Subject: [PATCH 0303/3023] hwrng: don't init list element we're about to add to list. Another interesting anti-pattern. Signed-off-by: Rusty Russell Signed-off-by: Herbert Xu --- drivers/char/hw_random/core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index e384ee3ed604d8..6ec42252e46eb9 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -485,7 +485,6 @@ int hwrng_register(struct hwrng *rng) goto out_unlock; } } - INIT_LIST_HEAD(&rng->list); list_add_tail(&rng->list, &rng_list); if (old_rng && !rng->init) { From 0f477b655a524515ec9a263d70d51f460c05a161 Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Mon, 8 Dec 2014 12:03:42 -0800 Subject: [PATCH 0304/3023] crypto: algif - Mark sgl end at the end of data algif_skcipher sends 127 sgl buffers for encryption regardless of how many buffers acctually have data to process, where the few first with valid len and the rest with zero len. This is not very eficient. This patch marks the last one with data as the last one to process. Signed-off-by: Tadeusz Struk Signed-off-by: Herbert Xu --- crypto/algif_skcipher.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index c12207c8dde9e6..38a6757e3cccdb 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -330,6 +330,7 @@ static int skcipher_sendmsg(struct kiocb *unused, struct socket *sock, sgl = list_entry(ctx->tsgl.prev, struct skcipher_sg_list, list); sg = sgl->sg; + sg_unmark_end(sg + sgl->cur); do { i = sgl->cur; plen = min_t(int, len, PAGE_SIZE); @@ -355,6 +356,9 @@ static int skcipher_sendmsg(struct kiocb *unused, struct socket *sock, sgl->cur++; } while (len && sgl->cur < MAX_SGL_ENTS); + if (!size) + sg_mark_end(sg + sgl->cur - 1); + ctx->merge = plen & (PAGE_SIZE - 1); } @@ -401,6 +405,10 @@ static ssize_t skcipher_sendpage(struct socket *sock, struct page *page, ctx->merge = 0; sgl = list_entry(ctx->tsgl.prev, struct skcipher_sg_list, list); + if (sgl->cur) + sg_unmark_end(sgl->sg + sgl->cur - 1); + + sg_mark_end(sgl->sg + sgl->cur); get_page(page); sg_set_page(sgl->sg + sgl->cur, page, size, offset); sgl->cur++; From 82f82504b8f5f1013678bbc74e0882891114594a Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Mon, 8 Dec 2014 12:05:42 -0800 Subject: [PATCH 0305/3023] crypto: qat - Fix assumption that sg in and out will have the same nents Fixed invalid assumpion that the sgl in and sgl out will always have the same number of entries. Signed-off-by: Tadeusz Struk Signed-off-by: Herbert Xu --- drivers/crypto/qat/qat_common/qat_algs.c | 82 +++++++++++++--------- drivers/crypto/qat/qat_common/qat_crypto.h | 1 + 2 files changed, 50 insertions(+), 33 deletions(-) diff --git a/drivers/crypto/qat/qat_common/qat_algs.c b/drivers/crypto/qat/qat_common/qat_algs.c index 19eea1c832ac5e..e4e32d872902be 100644 --- a/drivers/crypto/qat/qat_common/qat_algs.c +++ b/drivers/crypto/qat/qat_common/qat_algs.c @@ -557,7 +557,8 @@ static void qat_alg_free_bufl(struct qat_crypto_instance *inst, dma_addr_t blp = qat_req->buf.blp; dma_addr_t blpout = qat_req->buf.bloutp; size_t sz = qat_req->buf.sz; - int i, bufs = bl->num_bufs; + size_t sz_out = qat_req->buf.sz_out; + int i; for (i = 0; i < bl->num_bufs; i++) dma_unmap_single(dev, bl->bufers[i].addr, @@ -567,14 +568,14 @@ static void qat_alg_free_bufl(struct qat_crypto_instance *inst, kfree(bl); if (blp != blpout) { /* If out of place operation dma unmap only data */ - int bufless = bufs - blout->num_mapped_bufs; + int bufless = blout->num_bufs - blout->num_mapped_bufs; - for (i = bufless; i < bufs; i++) { + for (i = bufless; i < blout->num_bufs; i++) { dma_unmap_single(dev, blout->bufers[i].addr, blout->bufers[i].len, DMA_BIDIRECTIONAL); } - dma_unmap_single(dev, blpout, sz, DMA_TO_DEVICE); + dma_unmap_single(dev, blpout, sz_out, DMA_TO_DEVICE); kfree(blout); } } @@ -587,19 +588,20 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst, struct qat_crypto_request *qat_req) { struct device *dev = &GET_DEV(inst->accel_dev); - int i, bufs = 0, n = sg_nents(sgl), assoc_n = sg_nents(assoc); + int i, bufs = 0, sg_nctr = 0; + int n = sg_nents(sgl), assoc_n = sg_nents(assoc); struct qat_alg_buf_list *bufl; struct qat_alg_buf_list *buflout = NULL; dma_addr_t blp; dma_addr_t bloutp = 0; struct scatterlist *sg; - size_t sz = sizeof(struct qat_alg_buf_list) + + size_t sz_out, sz = sizeof(struct qat_alg_buf_list) + ((1 + n + assoc_n) * sizeof(struct qat_alg_buf)); if (unlikely(!n)) return -EINVAL; - bufl = kmalloc_node(sz, GFP_ATOMIC, + bufl = kzalloc_node(sz, GFP_ATOMIC, dev_to_node(&GET_DEV(inst->accel_dev))); if (unlikely(!bufl)) return -ENOMEM; @@ -620,15 +622,20 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst, goto err; bufs++; } - bufl->bufers[bufs].addr = dma_map_single(dev, iv, ivlen, - DMA_BIDIRECTIONAL); - bufl->bufers[bufs].len = ivlen; - if (unlikely(dma_mapping_error(dev, bufl->bufers[bufs].addr))) - goto err; - bufs++; + if (ivlen) { + bufl->bufers[bufs].addr = dma_map_single(dev, iv, ivlen, + DMA_BIDIRECTIONAL); + bufl->bufers[bufs].len = ivlen; + if (unlikely(dma_mapping_error(dev, bufl->bufers[bufs].addr))) + goto err; + bufs++; + } for_each_sg(sgl, sg, n, i) { - int y = i + bufs; + int y = sg_nctr + bufs; + + if (!sg->length) + continue; bufl->bufers[y].addr = dma_map_single(dev, sg_virt(sg), sg->length, @@ -636,8 +643,9 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst, bufl->bufers[y].len = sg->length; if (unlikely(dma_mapping_error(dev, bufl->bufers[y].addr))) goto err; + sg_nctr++; } - bufl->num_bufs = n + bufs; + bufl->num_bufs = sg_nctr + bufs; qat_req->buf.bl = bufl; qat_req->buf.blp = blp; qat_req->buf.sz = sz; @@ -645,11 +653,15 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst, if (sgl != sglout) { struct qat_alg_buf *bufers; - buflout = kmalloc_node(sz, GFP_ATOMIC, + n = sg_nents(sglout); + sz_out = sizeof(struct qat_alg_buf_list) + + ((1 + n + assoc_n) * sizeof(struct qat_alg_buf)); + sg_nctr = 0; + buflout = kzalloc_node(sz_out, GFP_ATOMIC, dev_to_node(&GET_DEV(inst->accel_dev))); if (unlikely(!buflout)) goto err; - bloutp = dma_map_single(dev, buflout, sz, DMA_TO_DEVICE); + bloutp = dma_map_single(dev, buflout, sz_out, DMA_TO_DEVICE); if (unlikely(dma_mapping_error(dev, bloutp))) goto err; bufers = buflout->bufers; @@ -660,47 +672,51 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst, bufers[i].addr = bufl->bufers[i].addr; } for_each_sg(sglout, sg, n, i) { - int y = i + bufs; + int y = sg_nctr + bufs; + + if (!sg->length) + continue; bufers[y].addr = dma_map_single(dev, sg_virt(sg), sg->length, DMA_BIDIRECTIONAL); - buflout->bufers[y].len = sg->length; if (unlikely(dma_mapping_error(dev, bufers[y].addr))) goto err; + bufers[y].len = sg->length; + sg_nctr++; } - buflout->num_bufs = n + bufs; - buflout->num_mapped_bufs = n; + buflout->num_bufs = sg_nctr + bufs; + buflout->num_mapped_bufs = sg_nctr; qat_req->buf.blout = buflout; qat_req->buf.bloutp = bloutp; + qat_req->buf.sz_out = sz_out; } else { /* Otherwise set the src and dst to the same address */ qat_req->buf.bloutp = qat_req->buf.blp; + qat_req->buf.sz_out = 0; } return 0; err: dev_err(dev, "Failed to map buf for dma\n"); - for_each_sg(sgl, sg, n + bufs, i) { - if (!dma_mapping_error(dev, bufl->bufers[i].addr)) { + sg_nctr = 0; + for (i = 0; i < n + bufs; i++) + if (!dma_mapping_error(dev, bufl->bufers[i].addr)) dma_unmap_single(dev, bufl->bufers[i].addr, bufl->bufers[i].len, DMA_BIDIRECTIONAL); - } - } + if (!dma_mapping_error(dev, blp)) dma_unmap_single(dev, blp, sz, DMA_TO_DEVICE); kfree(bufl); if (sgl != sglout && buflout) { - for_each_sg(sglout, sg, n, i) { - int y = i + bufs; - - if (!dma_mapping_error(dev, buflout->bufers[y].addr)) - dma_unmap_single(dev, buflout->bufers[y].addr, - buflout->bufers[y].len, + n = sg_nents(sglout); + for (i = bufs; i < n + bufs; i++) + if (!dma_mapping_error(dev, buflout->bufers[i].addr)) + dma_unmap_single(dev, buflout->bufers[i].addr, + buflout->bufers[i].len, DMA_BIDIRECTIONAL); - } if (!dma_mapping_error(dev, bloutp)) - dma_unmap_single(dev, bloutp, sz, DMA_TO_DEVICE); + dma_unmap_single(dev, bloutp, sz_out, DMA_TO_DEVICE); kfree(buflout); } return -ENOMEM; diff --git a/drivers/crypto/qat/qat_common/qat_crypto.h b/drivers/crypto/qat/qat_common/qat_crypto.h index ab8468d11ddbd9..fcb323116e60ba 100644 --- a/drivers/crypto/qat/qat_common/qat_crypto.h +++ b/drivers/crypto/qat/qat_common/qat_crypto.h @@ -72,6 +72,7 @@ struct qat_crypto_request_buffs { struct qat_alg_buf_list *blout; dma_addr_t bloutp; size_t sz; + size_t sz_out; }; struct qat_crypto_request { From 338e84f3a9740ab3582c8b6bc5a1a027794dac72 Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Mon, 8 Dec 2014 12:08:49 -0800 Subject: [PATCH 0306/3023] crypto: qat - add support for cbc(aes) ablkcipher Add support for cbc(aes) ablkcipher. Signed-off-by: Tadeusz Struk Acked-by: Bruce W. Allan Signed-off-by: Herbert Xu --- drivers/crypto/qat/qat_common/icp_qat_hw.h | 2 +- drivers/crypto/qat/qat_common/qat_algs.c | 528 ++++++++++++++++----- drivers/crypto/qat/qat_common/qat_crypto.h | 15 +- 3 files changed, 433 insertions(+), 112 deletions(-) diff --git a/drivers/crypto/qat/qat_common/icp_qat_hw.h b/drivers/crypto/qat/qat_common/icp_qat_hw.h index 5031f8c10d75db..68f191b653b0ef 100644 --- a/drivers/crypto/qat/qat_common/icp_qat_hw.h +++ b/drivers/crypto/qat/qat_common/icp_qat_hw.h @@ -301,5 +301,5 @@ struct icp_qat_hw_cipher_aes256_f8 { struct icp_qat_hw_cipher_algo_blk { struct icp_qat_hw_cipher_aes256_f8 aes; -}; +} __aligned(64); #endif diff --git a/drivers/crypto/qat/qat_common/qat_algs.c b/drivers/crypto/qat/qat_common/qat_algs.c index e4e32d872902be..f32d0a58bcc082 100644 --- a/drivers/crypto/qat/qat_common/qat_algs.c +++ b/drivers/crypto/qat/qat_common/qat_algs.c @@ -63,15 +63,15 @@ #include "icp_qat_fw.h" #include "icp_qat_fw_la.h" -#define QAT_AES_HW_CONFIG_ENC(alg) \ +#define QAT_AES_HW_CONFIG_CBC_ENC(alg) \ ICP_QAT_HW_CIPHER_CONFIG_BUILD(ICP_QAT_HW_CIPHER_CBC_MODE, alg, \ - ICP_QAT_HW_CIPHER_NO_CONVERT, \ - ICP_QAT_HW_CIPHER_ENCRYPT) + ICP_QAT_HW_CIPHER_NO_CONVERT, \ + ICP_QAT_HW_CIPHER_ENCRYPT) -#define QAT_AES_HW_CONFIG_DEC(alg) \ +#define QAT_AES_HW_CONFIG_CBC_DEC(alg) \ ICP_QAT_HW_CIPHER_CONFIG_BUILD(ICP_QAT_HW_CIPHER_CBC_MODE, alg, \ - ICP_QAT_HW_CIPHER_KEY_CONVERT, \ - ICP_QAT_HW_CIPHER_DECRYPT) + ICP_QAT_HW_CIPHER_KEY_CONVERT, \ + ICP_QAT_HW_CIPHER_DECRYPT) static atomic_t active_dev; @@ -108,19 +108,31 @@ struct qat_auth_state { uint8_t data[MAX_AUTH_STATE_SIZE + 64]; } __aligned(64); -struct qat_alg_session_ctx { +struct qat_alg_aead_ctx { struct qat_alg_cd *enc_cd; - dma_addr_t enc_cd_paddr; struct qat_alg_cd *dec_cd; + dma_addr_t enc_cd_paddr; dma_addr_t dec_cd_paddr; - struct icp_qat_fw_la_bulk_req enc_fw_req_tmpl; - struct icp_qat_fw_la_bulk_req dec_fw_req_tmpl; - struct qat_crypto_instance *inst; - struct crypto_tfm *tfm; + struct icp_qat_fw_la_bulk_req enc_fw_req; + struct icp_qat_fw_la_bulk_req dec_fw_req; struct crypto_shash *hash_tfm; enum icp_qat_hw_auth_algo qat_hash_alg; + struct qat_crypto_instance *inst; + struct crypto_tfm *tfm; uint8_t salt[AES_BLOCK_SIZE]; - spinlock_t lock; /* protects qat_alg_session_ctx struct */ + spinlock_t lock; /* protects qat_alg_aead_ctx struct */ +}; + +struct qat_alg_ablkcipher_ctx { + struct icp_qat_hw_cipher_algo_blk *enc_cd; + struct icp_qat_hw_cipher_algo_blk *dec_cd; + dma_addr_t enc_cd_paddr; + dma_addr_t dec_cd_paddr; + struct icp_qat_fw_la_bulk_req enc_fw_req; + struct icp_qat_fw_la_bulk_req dec_fw_req; + struct qat_crypto_instance *inst; + struct crypto_tfm *tfm; + spinlock_t lock; /* protects qat_alg_ablkcipher_ctx struct */ }; static int get_current_node(void) @@ -144,7 +156,7 @@ static int qat_get_inter_state_size(enum icp_qat_hw_auth_algo qat_hash_alg) } static int qat_alg_do_precomputes(struct icp_qat_hw_auth_algo_blk *hash, - struct qat_alg_session_ctx *ctx, + struct qat_alg_aead_ctx *ctx, const uint8_t *auth_key, unsigned int auth_keylen) { @@ -267,8 +279,6 @@ static void qat_alg_init_common_hdr(struct icp_qat_fw_comn_req_hdr *header) header->comn_req_flags = ICP_QAT_FW_COMN_FLAGS_BUILD(QAT_COMN_CD_FLD_TYPE_64BIT_ADR, QAT_COMN_PTR_TYPE_SGL); - ICP_QAT_FW_LA_DIGEST_IN_BUFFER_SET(header->serv_specif_flags, - ICP_QAT_FW_LA_DIGEST_IN_BUFFER); ICP_QAT_FW_LA_PARTIAL_SET(header->serv_specif_flags, ICP_QAT_FW_LA_PARTIAL_NONE); ICP_QAT_FW_LA_CIPH_IV_FLD_FLAG_SET(header->serv_specif_flags, @@ -279,8 +289,9 @@ static void qat_alg_init_common_hdr(struct icp_qat_fw_comn_req_hdr *header) ICP_QAT_FW_LA_NO_UPDATE_STATE); } -static int qat_alg_init_enc_session(struct qat_alg_session_ctx *ctx, - int alg, struct crypto_authenc_keys *keys) +static int qat_alg_aead_init_enc_session(struct qat_alg_aead_ctx *ctx, + int alg, + struct crypto_authenc_keys *keys) { struct crypto_aead *aead_tfm = __crypto_aead_cast(ctx->tfm); unsigned int digestsize = crypto_aead_crt(aead_tfm)->authsize; @@ -289,7 +300,7 @@ static int qat_alg_init_enc_session(struct qat_alg_session_ctx *ctx, struct icp_qat_hw_auth_algo_blk *hash = (struct icp_qat_hw_auth_algo_blk *)((char *)enc_ctx + sizeof(struct icp_qat_hw_auth_setup) + keys->enckeylen); - struct icp_qat_fw_la_bulk_req *req_tmpl = &ctx->enc_fw_req_tmpl; + struct icp_qat_fw_la_bulk_req *req_tmpl = &ctx->enc_fw_req; struct icp_qat_fw_comn_req_hdr_cd_pars *cd_pars = &req_tmpl->cd_pars; struct icp_qat_fw_comn_req_hdr *header = &req_tmpl->comn_hdr; void *ptr = &req_tmpl->cd_ctrl; @@ -297,7 +308,7 @@ static int qat_alg_init_enc_session(struct qat_alg_session_ctx *ctx, struct icp_qat_fw_auth_cd_ctrl_hdr *hash_cd_ctrl = ptr; /* CD setup */ - cipher->aes.cipher_config.val = QAT_AES_HW_CONFIG_ENC(alg); + cipher->aes.cipher_config.val = QAT_AES_HW_CONFIG_CBC_ENC(alg); memcpy(cipher->aes.key, keys->enckey, keys->enckeylen); hash->sha.inner_setup.auth_config.config = ICP_QAT_HW_AUTH_CONFIG_BUILD(ICP_QAT_HW_AUTH_MODE1, @@ -311,6 +322,8 @@ static int qat_alg_init_enc_session(struct qat_alg_session_ctx *ctx, /* Request setup */ qat_alg_init_common_hdr(header); header->service_cmd_id = ICP_QAT_FW_LA_CMD_CIPHER_HASH; + ICP_QAT_FW_LA_DIGEST_IN_BUFFER_SET(header->serv_specif_flags, + ICP_QAT_FW_LA_DIGEST_IN_BUFFER); ICP_QAT_FW_LA_RET_AUTH_SET(header->serv_specif_flags, ICP_QAT_FW_LA_RET_AUTH_RES); ICP_QAT_FW_LA_CMP_AUTH_SET(header->serv_specif_flags, @@ -356,8 +369,9 @@ static int qat_alg_init_enc_session(struct qat_alg_session_ctx *ctx, return 0; } -static int qat_alg_init_dec_session(struct qat_alg_session_ctx *ctx, - int alg, struct crypto_authenc_keys *keys) +static int qat_alg_aead_init_dec_session(struct qat_alg_aead_ctx *ctx, + int alg, + struct crypto_authenc_keys *keys) { struct crypto_aead *aead_tfm = __crypto_aead_cast(ctx->tfm); unsigned int digestsize = crypto_aead_crt(aead_tfm)->authsize; @@ -367,7 +381,7 @@ static int qat_alg_init_dec_session(struct qat_alg_session_ctx *ctx, (struct icp_qat_hw_cipher_algo_blk *)((char *)dec_ctx + sizeof(struct icp_qat_hw_auth_setup) + roundup(crypto_shash_digestsize(ctx->hash_tfm), 8) * 2); - struct icp_qat_fw_la_bulk_req *req_tmpl = &ctx->dec_fw_req_tmpl; + struct icp_qat_fw_la_bulk_req *req_tmpl = &ctx->dec_fw_req; struct icp_qat_fw_comn_req_hdr_cd_pars *cd_pars = &req_tmpl->cd_pars; struct icp_qat_fw_comn_req_hdr *header = &req_tmpl->comn_hdr; void *ptr = &req_tmpl->cd_ctrl; @@ -379,7 +393,7 @@ static int qat_alg_init_dec_session(struct qat_alg_session_ctx *ctx, sizeof(struct icp_qat_fw_la_cipher_req_params)); /* CD setup */ - cipher->aes.cipher_config.val = QAT_AES_HW_CONFIG_DEC(alg); + cipher->aes.cipher_config.val = QAT_AES_HW_CONFIG_CBC_DEC(alg); memcpy(cipher->aes.key, keys->enckey, keys->enckeylen); hash->sha.inner_setup.auth_config.config = ICP_QAT_HW_AUTH_CONFIG_BUILD(ICP_QAT_HW_AUTH_MODE1, @@ -394,6 +408,8 @@ static int qat_alg_init_dec_session(struct qat_alg_session_ctx *ctx, /* Request setup */ qat_alg_init_common_hdr(header); header->service_cmd_id = ICP_QAT_FW_LA_CMD_HASH_CIPHER; + ICP_QAT_FW_LA_DIGEST_IN_BUFFER_SET(header->serv_specif_flags, + ICP_QAT_FW_LA_DIGEST_IN_BUFFER); ICP_QAT_FW_LA_RET_AUTH_SET(header->serv_specif_flags, ICP_QAT_FW_LA_NO_RET_AUTH_RES); ICP_QAT_FW_LA_CMP_AUTH_SET(header->serv_specif_flags, @@ -444,36 +460,91 @@ static int qat_alg_init_dec_session(struct qat_alg_session_ctx *ctx, return 0; } -static int qat_alg_init_sessions(struct qat_alg_session_ctx *ctx, - const uint8_t *key, unsigned int keylen) +static void qat_alg_ablkcipher_init_com(struct qat_alg_ablkcipher_ctx *ctx, + struct icp_qat_fw_la_bulk_req *req, + struct icp_qat_hw_cipher_algo_blk *cd, + const uint8_t *key, unsigned int keylen) { - struct crypto_authenc_keys keys; - int alg; + struct icp_qat_fw_comn_req_hdr_cd_pars *cd_pars = &req->cd_pars; + struct icp_qat_fw_comn_req_hdr *header = &req->comn_hdr; + struct icp_qat_fw_cipher_cd_ctrl_hdr *cd_ctrl = (void *)&req->cd_ctrl; - if (crypto_rng_get_bytes(crypto_default_rng, ctx->salt, AES_BLOCK_SIZE)) - return -EFAULT; + memcpy(cd->aes.key, key, keylen); + qat_alg_init_common_hdr(header); + header->service_cmd_id = ICP_QAT_FW_LA_CMD_CIPHER; + cd_pars->u.s.content_desc_params_sz = + sizeof(struct icp_qat_hw_cipher_algo_blk) >> 3; + /* Cipher CD config setup */ + cd_ctrl->cipher_key_sz = keylen >> 3; + cd_ctrl->cipher_state_sz = AES_BLOCK_SIZE >> 3; + cd_ctrl->cipher_cfg_offset = 0; + ICP_QAT_FW_COMN_CURR_ID_SET(cd_ctrl, ICP_QAT_FW_SLICE_CIPHER); + ICP_QAT_FW_COMN_NEXT_ID_SET(cd_ctrl, ICP_QAT_FW_SLICE_DRAM_WR); +} - if (crypto_authenc_extractkeys(&keys, key, keylen)) - goto bad_key; +static void qat_alg_ablkcipher_init_enc(struct qat_alg_ablkcipher_ctx *ctx, + int alg, const uint8_t *key, + unsigned int keylen) +{ + struct icp_qat_hw_cipher_algo_blk *enc_cd = ctx->enc_cd; + struct icp_qat_fw_la_bulk_req *req = &ctx->enc_fw_req; + struct icp_qat_fw_comn_req_hdr_cd_pars *cd_pars = &req->cd_pars; - switch (keys.enckeylen) { + qat_alg_ablkcipher_init_com(ctx, req, enc_cd, key, keylen); + cd_pars->u.s.content_desc_addr = ctx->enc_cd_paddr; + enc_cd->aes.cipher_config.val = QAT_AES_HW_CONFIG_CBC_ENC(alg); +} + +static void qat_alg_ablkcipher_init_dec(struct qat_alg_ablkcipher_ctx *ctx, + int alg, const uint8_t *key, + unsigned int keylen) +{ + struct icp_qat_hw_cipher_algo_blk *dec_cd = ctx->dec_cd; + struct icp_qat_fw_la_bulk_req *req = &ctx->dec_fw_req; + struct icp_qat_fw_comn_req_hdr_cd_pars *cd_pars = &req->cd_pars; + + qat_alg_ablkcipher_init_com(ctx, req, dec_cd, key, keylen); + cd_pars->u.s.content_desc_addr = ctx->dec_cd_paddr; + dec_cd->aes.cipher_config.val = QAT_AES_HW_CONFIG_CBC_DEC(alg); +} + +static int qat_alg_validate_key(int key_len, int *alg) +{ + switch (key_len) { case AES_KEYSIZE_128: - alg = ICP_QAT_HW_CIPHER_ALGO_AES128; + *alg = ICP_QAT_HW_CIPHER_ALGO_AES128; break; case AES_KEYSIZE_192: - alg = ICP_QAT_HW_CIPHER_ALGO_AES192; + *alg = ICP_QAT_HW_CIPHER_ALGO_AES192; break; case AES_KEYSIZE_256: - alg = ICP_QAT_HW_CIPHER_ALGO_AES256; + *alg = ICP_QAT_HW_CIPHER_ALGO_AES256; break; default: - goto bad_key; + return -EINVAL; } + return 0; +} - if (qat_alg_init_enc_session(ctx, alg, &keys)) +static int qat_alg_aead_init_sessions(struct qat_alg_aead_ctx *ctx, + const uint8_t *key, unsigned int keylen) +{ + struct crypto_authenc_keys keys; + int alg; + + if (crypto_rng_get_bytes(crypto_default_rng, ctx->salt, AES_BLOCK_SIZE)) + return -EFAULT; + + if (crypto_authenc_extractkeys(&keys, key, keylen)) + goto bad_key; + + if (qat_alg_validate_key(keys.enckeylen, &alg)) + goto bad_key; + + if (qat_alg_aead_init_enc_session(ctx, alg, &keys)) goto error; - if (qat_alg_init_dec_session(ctx, alg, &keys)) + if (qat_alg_aead_init_dec_session(ctx, alg, &keys)) goto error; return 0; @@ -484,22 +555,37 @@ static int qat_alg_init_sessions(struct qat_alg_session_ctx *ctx, return -EFAULT; } -static int qat_alg_setkey(struct crypto_aead *tfm, const uint8_t *key, - unsigned int keylen) +static int qat_alg_ablkcipher_init_sessions(struct qat_alg_ablkcipher_ctx *ctx, + const uint8_t *key, + unsigned int keylen) { - struct qat_alg_session_ctx *ctx = crypto_aead_ctx(tfm); + int alg; + + if (qat_alg_validate_key(keylen, &alg)) + goto bad_key; + + qat_alg_ablkcipher_init_enc(ctx, alg, key, keylen); + qat_alg_ablkcipher_init_dec(ctx, alg, key, keylen); + return 0; +bad_key: + crypto_tfm_set_flags(ctx->tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; +} + +static int qat_alg_aead_setkey(struct crypto_aead *tfm, const uint8_t *key, + unsigned int keylen) +{ + struct qat_alg_aead_ctx *ctx = crypto_aead_ctx(tfm); struct device *dev; spin_lock(&ctx->lock); if (ctx->enc_cd) { /* rekeying */ dev = &GET_DEV(ctx->inst->accel_dev); - memzero_explicit(ctx->enc_cd, sizeof(struct qat_alg_cd)); - memzero_explicit(ctx->dec_cd, sizeof(struct qat_alg_cd)); - memzero_explicit(&ctx->enc_fw_req_tmpl, - sizeof(struct icp_qat_fw_la_bulk_req)); - memzero_explicit(&ctx->dec_fw_req_tmpl, - sizeof(struct icp_qat_fw_la_bulk_req)); + memzero_explicit(ctx->enc_cd, sizeof(*ctx->enc_cd)); + memzero_explicit(ctx->dec_cd, sizeof(*ctx->dec_cd)); + memzero_explicit(&ctx->enc_fw_req, sizeof(ctx->enc_fw_req)); + memzero_explicit(&ctx->dec_fw_req, sizeof(ctx->dec_fw_req)); } else { /* new key */ int node = get_current_node(); @@ -512,16 +598,14 @@ static int qat_alg_setkey(struct crypto_aead *tfm, const uint8_t *key, dev = &GET_DEV(inst->accel_dev); ctx->inst = inst; - ctx->enc_cd = dma_zalloc_coherent(dev, - sizeof(struct qat_alg_cd), + ctx->enc_cd = dma_zalloc_coherent(dev, sizeof(*ctx->enc_cd), &ctx->enc_cd_paddr, GFP_ATOMIC); if (!ctx->enc_cd) { spin_unlock(&ctx->lock); return -ENOMEM; } - ctx->dec_cd = dma_zalloc_coherent(dev, - sizeof(struct qat_alg_cd), + ctx->dec_cd = dma_zalloc_coherent(dev, sizeof(*ctx->dec_cd), &ctx->dec_cd_paddr, GFP_ATOMIC); if (!ctx->dec_cd) { @@ -530,7 +614,7 @@ static int qat_alg_setkey(struct crypto_aead *tfm, const uint8_t *key, } } spin_unlock(&ctx->lock); - if (qat_alg_init_sessions(ctx, key, keylen)) + if (qat_alg_aead_init_sessions(ctx, key, keylen)) goto out_free_all; return 0; @@ -722,14 +806,12 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst, return -ENOMEM; } -void qat_alg_callback(void *resp) +static void qat_aead_alg_callback(struct icp_qat_fw_la_resp *qat_resp, + struct qat_crypto_request *qat_req) { - struct icp_qat_fw_la_resp *qat_resp = resp; - struct qat_crypto_request *qat_req = - (void *)(__force long)qat_resp->opaque_data; - struct qat_alg_session_ctx *ctx = qat_req->ctx; + struct qat_alg_aead_ctx *ctx = qat_req->aead_ctx; struct qat_crypto_instance *inst = ctx->inst; - struct aead_request *areq = qat_req->areq; + struct aead_request *areq = qat_req->aead_req; uint8_t stat_filed = qat_resp->comn_resp.comn_status; int res = 0, qat_res = ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(stat_filed); @@ -739,11 +821,35 @@ void qat_alg_callback(void *resp) areq->base.complete(&areq->base, res); } -static int qat_alg_dec(struct aead_request *areq) +static void qat_ablkcipher_alg_callback(struct icp_qat_fw_la_resp *qat_resp, + struct qat_crypto_request *qat_req) +{ + struct qat_alg_ablkcipher_ctx *ctx = qat_req->ablkcipher_ctx; + struct qat_crypto_instance *inst = ctx->inst; + struct ablkcipher_request *areq = qat_req->ablkcipher_req; + uint8_t stat_filed = qat_resp->comn_resp.comn_status; + int res = 0, qat_res = ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(stat_filed); + + qat_alg_free_bufl(inst, qat_req); + if (unlikely(qat_res != ICP_QAT_FW_COMN_STATUS_FLAG_OK)) + res = -EINVAL; + areq->base.complete(&areq->base, res); +} + +void qat_alg_callback(void *resp) +{ + struct icp_qat_fw_la_resp *qat_resp = resp; + struct qat_crypto_request *qat_req = + (void *)(__force long)qat_resp->opaque_data; + + qat_req->cb(qat_resp, qat_req); +} + +static int qat_alg_aead_dec(struct aead_request *areq) { struct crypto_aead *aead_tfm = crypto_aead_reqtfm(areq); struct crypto_tfm *tfm = crypto_aead_tfm(aead_tfm); - struct qat_alg_session_ctx *ctx = crypto_tfm_ctx(tfm); + struct qat_alg_aead_ctx *ctx = crypto_tfm_ctx(tfm); struct qat_crypto_request *qat_req = aead_request_ctx(areq); struct icp_qat_fw_la_cipher_req_params *cipher_param; struct icp_qat_fw_la_auth_req_params *auth_param; @@ -757,9 +863,10 @@ static int qat_alg_dec(struct aead_request *areq) return ret; msg = &qat_req->req; - *msg = ctx->dec_fw_req_tmpl; - qat_req->ctx = ctx; - qat_req->areq = areq; + *msg = ctx->dec_fw_req; + qat_req->aead_ctx = ctx; + qat_req->aead_req = areq; + qat_req->cb = qat_aead_alg_callback; qat_req->req.comn_mid.opaque_data = (uint64_t)(__force long)qat_req; qat_req->req.comn_mid.src_data_addr = qat_req->buf.blp; qat_req->req.comn_mid.dest_data_addr = qat_req->buf.bloutp; @@ -782,12 +889,12 @@ static int qat_alg_dec(struct aead_request *areq) return -EINPROGRESS; } -static int qat_alg_enc_internal(struct aead_request *areq, uint8_t *iv, - int enc_iv) +static int qat_alg_aead_enc_internal(struct aead_request *areq, uint8_t *iv, + int enc_iv) { struct crypto_aead *aead_tfm = crypto_aead_reqtfm(areq); struct crypto_tfm *tfm = crypto_aead_tfm(aead_tfm); - struct qat_alg_session_ctx *ctx = crypto_tfm_ctx(tfm); + struct qat_alg_aead_ctx *ctx = crypto_tfm_ctx(tfm); struct qat_crypto_request *qat_req = aead_request_ctx(areq); struct icp_qat_fw_la_cipher_req_params *cipher_param; struct icp_qat_fw_la_auth_req_params *auth_param; @@ -800,9 +907,10 @@ static int qat_alg_enc_internal(struct aead_request *areq, uint8_t *iv, return ret; msg = &qat_req->req; - *msg = ctx->enc_fw_req_tmpl; - qat_req->ctx = ctx; - qat_req->areq = areq; + *msg = ctx->enc_fw_req; + qat_req->aead_ctx = ctx; + qat_req->aead_req = areq; + qat_req->cb = qat_aead_alg_callback; qat_req->req.comn_mid.opaque_data = (uint64_t)(__force long)qat_req; qat_req->req.comn_mid.src_data_addr = qat_req->buf.blp; qat_req->req.comn_mid.dest_data_addr = qat_req->buf.bloutp; @@ -831,29 +939,167 @@ static int qat_alg_enc_internal(struct aead_request *areq, uint8_t *iv, return -EINPROGRESS; } -static int qat_alg_enc(struct aead_request *areq) +static int qat_alg_aead_enc(struct aead_request *areq) { - return qat_alg_enc_internal(areq, areq->iv, 0); + return qat_alg_aead_enc_internal(areq, areq->iv, 0); } -static int qat_alg_genivenc(struct aead_givcrypt_request *req) +static int qat_alg_aead_genivenc(struct aead_givcrypt_request *req) { struct crypto_aead *aead_tfm = crypto_aead_reqtfm(&req->areq); struct crypto_tfm *tfm = crypto_aead_tfm(aead_tfm); - struct qat_alg_session_ctx *ctx = crypto_tfm_ctx(tfm); + struct qat_alg_aead_ctx *ctx = crypto_tfm_ctx(tfm); __be64 seq; memcpy(req->giv, ctx->salt, AES_BLOCK_SIZE); seq = cpu_to_be64(req->seq); memcpy(req->giv + AES_BLOCK_SIZE - sizeof(uint64_t), &seq, sizeof(uint64_t)); - return qat_alg_enc_internal(&req->areq, req->giv, 1); + return qat_alg_aead_enc_internal(&req->areq, req->giv, 1); } -static int qat_alg_init(struct crypto_tfm *tfm, - enum icp_qat_hw_auth_algo hash, const char *hash_name) +static int qat_alg_ablkcipher_setkey(struct crypto_ablkcipher *tfm, + const uint8_t *key, + unsigned int keylen) { - struct qat_alg_session_ctx *ctx = crypto_tfm_ctx(tfm); + struct qat_alg_ablkcipher_ctx *ctx = crypto_ablkcipher_ctx(tfm); + struct device *dev; + + spin_lock(&ctx->lock); + if (ctx->enc_cd) { + /* rekeying */ + dev = &GET_DEV(ctx->inst->accel_dev); + memzero_explicit(ctx->enc_cd, sizeof(*ctx->enc_cd)); + memzero_explicit(ctx->dec_cd, sizeof(*ctx->dec_cd)); + memzero_explicit(&ctx->enc_fw_req, sizeof(ctx->enc_fw_req)); + memzero_explicit(&ctx->dec_fw_req, sizeof(ctx->dec_fw_req)); + } else { + /* new key */ + int node = get_current_node(); + struct qat_crypto_instance *inst = + qat_crypto_get_instance_node(node); + if (!inst) { + spin_unlock(&ctx->lock); + return -EINVAL; + } + + dev = &GET_DEV(inst->accel_dev); + ctx->inst = inst; + ctx->enc_cd = dma_zalloc_coherent(dev, sizeof(*ctx->enc_cd), + &ctx->enc_cd_paddr, + GFP_ATOMIC); + if (!ctx->enc_cd) { + spin_unlock(&ctx->lock); + return -ENOMEM; + } + ctx->dec_cd = dma_zalloc_coherent(dev, sizeof(*ctx->dec_cd), + &ctx->dec_cd_paddr, + GFP_ATOMIC); + if (!ctx->dec_cd) { + spin_unlock(&ctx->lock); + goto out_free_enc; + } + } + spin_unlock(&ctx->lock); + if (qat_alg_ablkcipher_init_sessions(ctx, key, keylen)) + goto out_free_all; + + return 0; + +out_free_all: + memzero_explicit(ctx->dec_cd, sizeof(*ctx->enc_cd)); + dma_free_coherent(dev, sizeof(*ctx->enc_cd), + ctx->dec_cd, ctx->dec_cd_paddr); + ctx->dec_cd = NULL; +out_free_enc: + memzero_explicit(ctx->enc_cd, sizeof(*ctx->dec_cd)); + dma_free_coherent(dev, sizeof(*ctx->dec_cd), + ctx->enc_cd, ctx->enc_cd_paddr); + ctx->enc_cd = NULL; + return -ENOMEM; +} + +static int qat_alg_ablkcipher_encrypt(struct ablkcipher_request *req) +{ + struct crypto_ablkcipher *atfm = crypto_ablkcipher_reqtfm(req); + struct crypto_tfm *tfm = crypto_ablkcipher_tfm(atfm); + struct qat_alg_ablkcipher_ctx *ctx = crypto_tfm_ctx(tfm); + struct qat_crypto_request *qat_req = ablkcipher_request_ctx(req); + struct icp_qat_fw_la_cipher_req_params *cipher_param; + struct icp_qat_fw_la_bulk_req *msg; + int ret, ctr = 0; + + ret = qat_alg_sgl_to_bufl(ctx->inst, NULL, req->src, req->dst, + NULL, 0, qat_req); + if (unlikely(ret)) + return ret; + + msg = &qat_req->req; + *msg = ctx->enc_fw_req; + qat_req->ablkcipher_ctx = ctx; + qat_req->ablkcipher_req = req; + qat_req->cb = qat_ablkcipher_alg_callback; + qat_req->req.comn_mid.opaque_data = (uint64_t)(__force long)qat_req; + qat_req->req.comn_mid.src_data_addr = qat_req->buf.blp; + qat_req->req.comn_mid.dest_data_addr = qat_req->buf.bloutp; + cipher_param = (void *)&qat_req->req.serv_specif_rqpars; + cipher_param->cipher_length = req->nbytes; + cipher_param->cipher_offset = 0; + memcpy(cipher_param->u.cipher_IV_array, req->info, AES_BLOCK_SIZE); + do { + ret = adf_send_message(ctx->inst->sym_tx, (uint32_t *)msg); + } while (ret == -EAGAIN && ctr++ < 10); + + if (ret == -EAGAIN) { + qat_alg_free_bufl(ctx->inst, qat_req); + return -EBUSY; + } + return -EINPROGRESS; +} + +static int qat_alg_ablkcipher_decrypt(struct ablkcipher_request *req) +{ + struct crypto_ablkcipher *atfm = crypto_ablkcipher_reqtfm(req); + struct crypto_tfm *tfm = crypto_ablkcipher_tfm(atfm); + struct qat_alg_ablkcipher_ctx *ctx = crypto_tfm_ctx(tfm); + struct qat_crypto_request *qat_req = ablkcipher_request_ctx(req); + struct icp_qat_fw_la_cipher_req_params *cipher_param; + struct icp_qat_fw_la_bulk_req *msg; + int ret, ctr = 0; + + ret = qat_alg_sgl_to_bufl(ctx->inst, NULL, req->src, req->dst, + NULL, 0, qat_req); + if (unlikely(ret)) + return ret; + + msg = &qat_req->req; + *msg = ctx->dec_fw_req; + qat_req->ablkcipher_ctx = ctx; + qat_req->ablkcipher_req = req; + qat_req->cb = qat_ablkcipher_alg_callback; + qat_req->req.comn_mid.opaque_data = (uint64_t)(__force long)qat_req; + qat_req->req.comn_mid.src_data_addr = qat_req->buf.blp; + qat_req->req.comn_mid.dest_data_addr = qat_req->buf.bloutp; + cipher_param = (void *)&qat_req->req.serv_specif_rqpars; + cipher_param->cipher_length = req->nbytes; + cipher_param->cipher_offset = 0; + memcpy(cipher_param->u.cipher_IV_array, req->info, AES_BLOCK_SIZE); + do { + ret = adf_send_message(ctx->inst->sym_tx, (uint32_t *)msg); + } while (ret == -EAGAIN && ctr++ < 10); + + if (ret == -EAGAIN) { + qat_alg_free_bufl(ctx->inst, qat_req); + return -EBUSY; + } + return -EINPROGRESS; +} + +static int qat_alg_aead_init(struct crypto_tfm *tfm, + enum icp_qat_hw_auth_algo hash, + const char *hash_name) +{ + struct qat_alg_aead_ctx *ctx = crypto_tfm_ctx(tfm); memzero_explicit(ctx, sizeof(*ctx)); ctx->hash_tfm = crypto_alloc_shash(hash_name, 0, 0); @@ -867,24 +1113,24 @@ static int qat_alg_init(struct crypto_tfm *tfm, return 0; } -static int qat_alg_sha1_init(struct crypto_tfm *tfm) +static int qat_alg_aead_sha1_init(struct crypto_tfm *tfm) { - return qat_alg_init(tfm, ICP_QAT_HW_AUTH_ALGO_SHA1, "sha1"); + return qat_alg_aead_init(tfm, ICP_QAT_HW_AUTH_ALGO_SHA1, "sha1"); } -static int qat_alg_sha256_init(struct crypto_tfm *tfm) +static int qat_alg_aead_sha256_init(struct crypto_tfm *tfm) { - return qat_alg_init(tfm, ICP_QAT_HW_AUTH_ALGO_SHA256, "sha256"); + return qat_alg_aead_init(tfm, ICP_QAT_HW_AUTH_ALGO_SHA256, "sha256"); } -static int qat_alg_sha512_init(struct crypto_tfm *tfm) +static int qat_alg_aead_sha512_init(struct crypto_tfm *tfm) { - return qat_alg_init(tfm, ICP_QAT_HW_AUTH_ALGO_SHA512, "sha512"); + return qat_alg_aead_init(tfm, ICP_QAT_HW_AUTH_ALGO_SHA512, "sha512"); } -static void qat_alg_exit(struct crypto_tfm *tfm) +static void qat_alg_aead_exit(struct crypto_tfm *tfm) { - struct qat_alg_session_ctx *ctx = crypto_tfm_ctx(tfm); + struct qat_alg_aead_ctx *ctx = crypto_tfm_ctx(tfm); struct qat_crypto_instance *inst = ctx->inst; struct device *dev; @@ -908,24 +1154,63 @@ static void qat_alg_exit(struct crypto_tfm *tfm) qat_crypto_put_instance(inst); } +static int qat_alg_ablkcipher_init(struct crypto_tfm *tfm) +{ + struct qat_alg_ablkcipher_ctx *ctx = crypto_tfm_ctx(tfm); + + memzero_explicit(ctx, sizeof(*ctx)); + spin_lock_init(&ctx->lock); + tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) + + sizeof(struct qat_crypto_request); + ctx->tfm = tfm; + return 0; +} + +static void qat_alg_ablkcipher_exit(struct crypto_tfm *tfm) +{ + struct qat_alg_ablkcipher_ctx *ctx = crypto_tfm_ctx(tfm); + struct qat_crypto_instance *inst = ctx->inst; + struct device *dev; + + if (!inst) + return; + + dev = &GET_DEV(inst->accel_dev); + if (ctx->enc_cd) { + memzero_explicit(ctx->enc_cd, + sizeof(struct icp_qat_hw_cipher_algo_blk)); + dma_free_coherent(dev, + sizeof(struct icp_qat_hw_cipher_algo_blk), + ctx->enc_cd, ctx->enc_cd_paddr); + } + if (ctx->dec_cd) { + memzero_explicit(ctx->dec_cd, + sizeof(struct icp_qat_hw_cipher_algo_blk)); + dma_free_coherent(dev, + sizeof(struct icp_qat_hw_cipher_algo_blk), + ctx->dec_cd, ctx->dec_cd_paddr); + } + qat_crypto_put_instance(inst); +} + static struct crypto_alg qat_algs[] = { { .cra_name = "authenc(hmac(sha1),cbc(aes))", .cra_driver_name = "qat_aes_cbc_hmac_sha1", .cra_priority = 4001, .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC, .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct qat_alg_session_ctx), + .cra_ctxsize = sizeof(struct qat_alg_aead_ctx), .cra_alignmask = 0, .cra_type = &crypto_aead_type, .cra_module = THIS_MODULE, - .cra_init = qat_alg_sha1_init, - .cra_exit = qat_alg_exit, + .cra_init = qat_alg_aead_sha1_init, + .cra_exit = qat_alg_aead_exit, .cra_u = { .aead = { - .setkey = qat_alg_setkey, - .decrypt = qat_alg_dec, - .encrypt = qat_alg_enc, - .givencrypt = qat_alg_genivenc, + .setkey = qat_alg_aead_setkey, + .decrypt = qat_alg_aead_dec, + .encrypt = qat_alg_aead_enc, + .givencrypt = qat_alg_aead_genivenc, .ivsize = AES_BLOCK_SIZE, .maxauthsize = SHA1_DIGEST_SIZE, }, @@ -936,18 +1221,18 @@ static struct crypto_alg qat_algs[] = { { .cra_priority = 4001, .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC, .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct qat_alg_session_ctx), + .cra_ctxsize = sizeof(struct qat_alg_aead_ctx), .cra_alignmask = 0, .cra_type = &crypto_aead_type, .cra_module = THIS_MODULE, - .cra_init = qat_alg_sha256_init, - .cra_exit = qat_alg_exit, + .cra_init = qat_alg_aead_sha256_init, + .cra_exit = qat_alg_aead_exit, .cra_u = { .aead = { - .setkey = qat_alg_setkey, - .decrypt = qat_alg_dec, - .encrypt = qat_alg_enc, - .givencrypt = qat_alg_genivenc, + .setkey = qat_alg_aead_setkey, + .decrypt = qat_alg_aead_dec, + .encrypt = qat_alg_aead_enc, + .givencrypt = qat_alg_aead_genivenc, .ivsize = AES_BLOCK_SIZE, .maxauthsize = SHA256_DIGEST_SIZE, }, @@ -958,22 +1243,44 @@ static struct crypto_alg qat_algs[] = { { .cra_priority = 4001, .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC, .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct qat_alg_session_ctx), + .cra_ctxsize = sizeof(struct qat_alg_aead_ctx), .cra_alignmask = 0, .cra_type = &crypto_aead_type, .cra_module = THIS_MODULE, - .cra_init = qat_alg_sha512_init, - .cra_exit = qat_alg_exit, + .cra_init = qat_alg_aead_sha512_init, + .cra_exit = qat_alg_aead_exit, .cra_u = { .aead = { - .setkey = qat_alg_setkey, - .decrypt = qat_alg_dec, - .encrypt = qat_alg_enc, - .givencrypt = qat_alg_genivenc, + .setkey = qat_alg_aead_setkey, + .decrypt = qat_alg_aead_dec, + .encrypt = qat_alg_aead_enc, + .givencrypt = qat_alg_aead_genivenc, .ivsize = AES_BLOCK_SIZE, .maxauthsize = SHA512_DIGEST_SIZE, }, }, +}, { + .cra_name = "cbc(aes)", + .cra_driver_name = "qat_aes_cbc", + .cra_priority = 4001, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct qat_alg_ablkcipher_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = qat_alg_ablkcipher_init, + .cra_exit = qat_alg_ablkcipher_exit, + .cra_u = { + .ablkcipher = { + .setkey = qat_alg_ablkcipher_setkey, + .decrypt = qat_alg_ablkcipher_decrypt, + .encrypt = qat_alg_ablkcipher_encrypt, + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + }, + }, } }; int qat_algs_register(void) @@ -982,8 +1289,11 @@ int qat_algs_register(void) int i; for (i = 0; i < ARRAY_SIZE(qat_algs); i++) - qat_algs[i].cra_flags = CRYPTO_ALG_TYPE_AEAD | - CRYPTO_ALG_ASYNC; + qat_algs[i].cra_flags = + (qat_algs[i].cra_type == &crypto_aead_type) ? + CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC : + CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC; + return crypto_register_algs(qat_algs, ARRAY_SIZE(qat_algs)); } return 0; diff --git a/drivers/crypto/qat/qat_common/qat_crypto.h b/drivers/crypto/qat/qat_common/qat_crypto.h index fcb323116e60ba..d503007b49e6ef 100644 --- a/drivers/crypto/qat/qat_common/qat_crypto.h +++ b/drivers/crypto/qat/qat_common/qat_crypto.h @@ -75,10 +75,21 @@ struct qat_crypto_request_buffs { size_t sz_out; }; +struct qat_crypto_request; + struct qat_crypto_request { struct icp_qat_fw_la_bulk_req req; - struct qat_alg_session_ctx *ctx; - struct aead_request *areq; + union { + struct qat_alg_aead_ctx *aead_ctx; + struct qat_alg_ablkcipher_ctx *ablkcipher_ctx; + }; + union { + struct aead_request *aead_req; + struct ablkcipher_request *ablkcipher_req; + }; struct qat_crypto_request_buffs buf; + void (*cb)(struct icp_qat_fw_la_resp *resp, + struct qat_crypto_request *req); }; + #endif From d3f6c142865badc82fa4d151766634b895d693e8 Mon Sep 17 00:00:00 2001 From: Asaf Vertz Date: Wed, 10 Dec 2014 14:55:10 +0200 Subject: [PATCH 0307/3023] crypto: ux500 - fix checkpatch errors Fixed a coding style error, code indent should use tabs where possible Signed-off-by: Asaf Vertz Signed-off-by: Herbert Xu --- drivers/crypto/ux500/cryp/cryp_core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c index f831bb952b2fd6..f087f37b2c6751 100644 --- a/drivers/crypto/ux500/cryp/cryp_core.c +++ b/drivers/crypto/ux500/cryp/cryp_core.c @@ -479,13 +479,13 @@ static void cryp_dma_setup_channel(struct cryp_device_data *device_data, .dst_addr = device_data->phybase + CRYP_DMA_TX_FIFO, .dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES, .dst_maxburst = 4, - }; + }; struct dma_slave_config cryp2mem = { .direction = DMA_DEV_TO_MEM, .src_addr = device_data->phybase + CRYP_DMA_RX_FIFO, .src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES, .src_maxburst = 4, - }; + }; dma_cap_zero(device_data->dma.mask); dma_cap_set(DMA_SLAVE, device_data->dma.mask); @@ -1774,8 +1774,8 @@ static int ux500_cryp_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(ux500_cryp_pm, ux500_cryp_suspend, ux500_cryp_resume); static const struct of_device_id ux500_cryp_match[] = { - { .compatible = "stericsson,ux500-cryp" }, - { }, + { .compatible = "stericsson,ux500-cryp" }, + { }, }; static struct platform_driver cryp_driver = { From b9024cbc937df97987b139c6cf01e59369c5756d Mon Sep 17 00:00:00 2001 From: Naveen Krishna Ch Date: Sat, 22 Nov 2014 22:41:23 +0900 Subject: [PATCH 0308/3023] arm64: dts: Add initial device tree support for exynos7 Add initial device tree nodes for exynos7 SoC and board dts file to support espresso board based on exynos7 SoC. Signed-off-by: Naveen Krishna Ch Signed-off-by: Abhilash Kesavan Reviewed-by: Thomas Abraham Tested-by: Thomas Abraham Cc: Rob Herring Cc: Catalin Marinas Signed-off-by: Kukjin Kim --- arch/arm64/boot/dts/Makefile | 1 + arch/arm64/boot/dts/exynos/Makefile | 5 + .../boot/dts/exynos/exynos7-espresso.dts | 39 ++++ arch/arm64/boot/dts/exynos/exynos7.dtsi | 183 ++++++++++++++++++ 4 files changed, 228 insertions(+) create mode 100644 arch/arm64/boot/dts/exynos/Makefile create mode 100644 arch/arm64/boot/dts/exynos/exynos7-espresso.dts create mode 100644 arch/arm64/boot/dts/exynos/exynos7.dtsi diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile index 3b8d427c398599..b4112518552ffe 100644 --- a/arch/arm64/boot/dts/Makefile +++ b/arch/arm64/boot/dts/Makefile @@ -2,6 +2,7 @@ dts-dirs += amd dts-dirs += apm dts-dirs += arm dts-dirs += cavium +dts-dirs += exynos always := $(dtb-y) subdir-y := $(dts-dirs) diff --git a/arch/arm64/boot/dts/exynos/Makefile b/arch/arm64/boot/dts/exynos/Makefile new file mode 100644 index 00000000000000..20310e5b6d6f02 --- /dev/null +++ b/arch/arm64/boot/dts/exynos/Makefile @@ -0,0 +1,5 @@ +dtb-$(CONFIG_ARCH_EXYNOS7) += exynos7-espresso.dtb + +always := $(dtb-y) +subdir-y := $(dts-dirs) +clean-files := *.dtb diff --git a/arch/arm64/boot/dts/exynos/exynos7-espresso.dts b/arch/arm64/boot/dts/exynos/exynos7-espresso.dts new file mode 100644 index 00000000000000..e2c828322687a1 --- /dev/null +++ b/arch/arm64/boot/dts/exynos/exynos7-espresso.dts @@ -0,0 +1,39 @@ +/* + * SAMSUNG Exynos7 Espresso board device tree source + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/dts-v1/; +#include "exynos7.dtsi" + +/ { + model = "Samsung Exynos7 Espresso board based on EXYNOS7"; + compatible = "samsung,exynos7-espresso", "samsung,exynos7"; + + aliases { + serial0 = &serial_2; + }; + + chosen { + linux,stdout-path = &serial_2; + }; + + memory@40000000 { + device_type = "memory"; + reg = <0x0 0x40000000 0x0 0xC0000000>; + }; +}; + +&fin_pll { + clock-frequency = <24000000>; +}; + +&serial_2 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/exynos/exynos7.dtsi b/arch/arm64/boot/dts/exynos/exynos7.dtsi new file mode 100644 index 00000000000000..6d6a4c2e4dfbb2 --- /dev/null +++ b/arch/arm64/boot/dts/exynos/exynos7.dtsi @@ -0,0 +1,183 @@ +/* + * SAMSUNG EXYNOS7 SoC device tree source + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include + +/ { + compatible = "samsung,exynos7"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x0>; + enable-method = "psci"; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x1>; + enable-method = "psci"; + }; + + cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x2>; + enable-method = "psci"; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x3>; + enable-method = "psci"; + }; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + soc: soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0 0x18000000>; + + chipid@10000000 { + compatible = "samsung,exynos4210-chipid"; + reg = <0x10000000 0x100>; + }; + + fin_pll: xxti { + compatible = "fixed-clock"; + clock-output-names = "fin_pll"; + #clock-cells = <0>; + }; + + gic: interrupt-controller@11001000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x11001000 0x1000>, + <0x11002000 0x1000>, + <0x11004000 0x2000>, + <0x11006000 0x2000>; + }; + + clock_topc: clock-controller@10570000 { + compatible = "samsung,exynos7-clock-topc"; + reg = <0x10570000 0x10000>; + #clock-cells = <1>; + }; + + clock_top0: clock-controller@105d0000 { + compatible = "samsung,exynos7-clock-top0"; + reg = <0x105d0000 0xb000>; + #clock-cells = <1>; + clocks = <&fin_pll>, <&clock_topc DOUT_SCLK_BUS0_PLL>, + <&clock_topc DOUT_SCLK_BUS1_PLL>, + <&clock_topc DOUT_SCLK_CC_PLL>, + <&clock_topc DOUT_SCLK_MFC_PLL>; + clock-names = "fin_pll", "dout_sclk_bus0_pll", + "dout_sclk_bus1_pll", "dout_sclk_cc_pll", + "dout_sclk_mfc_pll"; + }; + + clock_peric0: clock-controller@13610000 { + compatible = "samsung,exynos7-clock-peric0"; + reg = <0x13610000 0xd00>; + #clock-cells = <1>; + clocks = <&fin_pll>, <&clock_top0 DOUT_ACLK_PERIC0>, + <&clock_top0 CLK_SCLK_UART0>; + clock-names = "fin_pll", "dout_aclk_peric0_66", + "sclk_uart0"; + }; + + clock_peric1: clock-controller@14c80000 { + compatible = "samsung,exynos7-clock-peric1"; + reg = <0x14c80000 0xd00>; + #clock-cells = <1>; + clocks = <&fin_pll>, <&clock_top0 DOUT_ACLK_PERIC1>, + <&clock_top0 CLK_SCLK_UART1>, + <&clock_top0 CLK_SCLK_UART2>, + <&clock_top0 CLK_SCLK_UART3>; + clock-names = "fin_pll", "dout_aclk_peric1_66", + "sclk_uart1", "sclk_uart2", "sclk_uart3"; + }; + + clock_peris: clock-controller@10040000 { + compatible = "samsung,exynos7-clock-peris"; + reg = <0x10040000 0xd00>; + #clock-cells = <1>; + clocks = <&fin_pll>, <&clock_topc DOUT_ACLK_PERIS>; + clock-names = "fin_pll", "dout_aclk_peris_66"; + }; + + serial_0: serial@13630000 { + compatible = "samsung,exynos4210-uart"; + reg = <0x13630000 0x100>; + interrupts = <0 440 0>; + clocks = <&clock_peric0 PCLK_UART0>, + <&clock_peric0 SCLK_UART0>; + clock-names = "uart", "clk_uart_baud0"; + status = "disabled"; + }; + + serial_1: serial@14c20000 { + compatible = "samsung,exynos4210-uart"; + reg = <0x14c20000 0x100>; + interrupts = <0 456 0>; + clocks = <&clock_peric1 PCLK_UART1>, + <&clock_peric1 SCLK_UART1>; + clock-names = "uart", "clk_uart_baud0"; + status = "disabled"; + }; + + serial_2: serial@14c30000 { + compatible = "samsung,exynos4210-uart"; + reg = <0x14c30000 0x100>; + interrupts = <0 457 0>; + clocks = <&clock_peric1 PCLK_UART2>, + <&clock_peric1 SCLK_UART2>; + clock-names = "uart", "clk_uart_baud0"; + status = "disabled"; + }; + + serial_3: serial@14c40000 { + compatible = "samsung,exynos4210-uart"; + reg = <0x14c40000 0x100>; + interrupts = <0 458 0>; + clocks = <&clock_peric1 PCLK_UART3>, + <&clock_peric1 SCLK_UART3>; + clock-names = "uart", "clk_uart_baud0"; + status = "disabled"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <1 13 0xff01>, + <1 14 0xff01>, + <1 11 0xff01>, + <1 10 0xff01>; + }; + }; +}; From f17a618b1e97b7f9b6e286e8a5c54d08a55564d9 Mon Sep 17 00:00:00 2001 From: Naveen Krishna Ch Date: Sat, 22 Nov 2014 22:41:33 +0900 Subject: [PATCH 0309/3023] arm64: dts: Add initial pinctrl support to exynos7 Add initial pin configuration nodes for exynos7 SoC. Signed-off-by: Naveen Krishna Ch Signed-off-by: Abhilash Kesavan Reviewed-by: Thomas Abraham Tested-by: Thomas Abraham Acked-by: Tomasz Figa Cc: Rob Herring Cc: Catalin Marinas Cc: Linus Walleij Signed-off-by: Kukjin Kim --- .../boot/dts/exynos/exynos7-pinctrl.dtsi | 588 ++++++++++++++++++ arch/arm64/boot/dts/exynos/exynos7.dtsi | 66 ++ 2 files changed, 654 insertions(+) create mode 100644 arch/arm64/boot/dts/exynos/exynos7-pinctrl.dtsi diff --git a/arch/arm64/boot/dts/exynos/exynos7-pinctrl.dtsi b/arch/arm64/boot/dts/exynos/exynos7-pinctrl.dtsi new file mode 100644 index 00000000000000..2eef4a279131d2 --- /dev/null +++ b/arch/arm64/boot/dts/exynos/exynos7-pinctrl.dtsi @@ -0,0 +1,588 @@ +/* + * Samsung's Exynos7 SoC pin-mux and pin-config device tree source + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Samsung's Exynos7 SoC pin-mux and pin-config options are listed as + * device tree nodes in this file. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +&pinctrl_alive { + gpa0: gpa0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + interrupt-parent = <&gic>; + #interrupt-cells = <2>; + interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>, + <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>; + }; + + gpa1: gpa1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + interrupt-parent = <&gic>; + #interrupt-cells = <2>; + interrupts = <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>, + <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>; + }; + + gpa2: gpa2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpa3: gpa3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; +}; + +&pinctrl_bus0 { + gpb0: gpb0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpc0: gpc0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpc1: gpc1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpc2: gpc2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpc3: gpc3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd0: gpd0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd1: gpd1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd2: gpd2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd4: gpd4 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd5: gpd5 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd6: gpd6 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd7: gpd7 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd8: gpd8 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpg0: gpg0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpg3: gpg3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + hs_i2c10_bus: hs-i2c10-bus { + samsung,pins = "gpb0-1", "gpb0-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + hs_i2c11_bus: hs-i2c11-bus { + samsung,pins = "gpb0-3", "gpb0-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + hs_i2c2_bus: hs-i2c2-bus { + samsung,pins = "gpd0-3", "gpd0-2"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + uart0_data: uart0-data { + samsung,pins = "gpd0-0", "gpd0-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + uart0_fctl: uart0-fctl { + samsung,pins = "gpd0-2", "gpd0-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + uart2_data: uart2-data { + samsung,pins = "gpd1-4", "gpd1-5"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + hs_i2c3_bus: hs-i2c3-bus { + samsung,pins = "gpd1-3", "gpd1-2"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + uart1_data: uart1-data { + samsung,pins = "gpd1-0", "gpd1-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + uart1_fctl: uart1-fctl { + samsung,pins = "gpd1-2", "gpd1-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + hs_i2c0_bus: hs-i2c0-bus { + samsung,pins = "gpd2-1", "gpd2-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + hs_i2c1_bus: hs-i2c1-bus { + samsung,pins = "gpd2-3", "gpd2-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + hs_i2c9_bus: hs-i2c9-bus { + samsung,pins = "gpd2-7", "gpd2-6"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + pwm0_out: pwm0-out { + samsung,pins = "gpd2-4"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + pwm1_out: pwm1-out { + samsung,pins = "gpd2-5"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + pwm2_out: pwm2-out { + samsung,pins = "gpd2-6"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + pwm3_out: pwm3-out { + samsung,pins = "gpd2-7"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + hs_i2c8_bus: hs-i2c8-bus { + samsung,pins = "gpd5-3", "gpd5-2"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + uart3_data: uart3-data { + samsung,pins = "gpd5-0", "gpd5-1"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + spi2_bus: spi2-bus { + samsung,pins = "gpd5-0", "gpd5-1", "gpd5-2", "gpd5-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + spi1_bus: spi1-bus { + samsung,pins = "gpd6-2", "gpd6-3", "gpd6-4", "gpd6-5"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + spi0_bus: spi0-bus { + samsung,pins = "gpd8-0", "gpd8-1", "gpd6-0", "gpd6-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + hs_i2c4_bus: hs-i2c4-bus { + samsung,pins = "gpg3-1", "gpg3-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + hs_i2c5_bus: hs-i2c5-bus { + samsung,pins = "gpg3-3", "gpg3-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; +}; + +&pinctrl_nfc { + gpj0: gpj0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + hs_i2c6_bus: hs-i2c6-bus { + samsung,pins = "gpj0-1", "gpj0-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; +}; + +&pinctrl_touch { + gpj1: gpj1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + hs_i2c7_bus: hs-i2c7-bus { + samsung,pins = "gpj1-1", "gpj1-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; +}; + +&pinctrl_ff { + gpg4: gpg4 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + spi3_bus: spi3-bus { + samsung,pins = "gpg4-0", "gpg4-1", "gpg4-2", "gpg4-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; +}; + +&pinctrl_ese { + gpv7: gpv7 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + spi4_bus: spi4-bus { + samsung,pins = "gpv7-0", "gpv7-1", "gpv7-2", "gpv7-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; +}; + +&pinctrl_fsys0 { + gpr4: gpr4 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + sd2_clk: sd2-clk { + samsung,pins = "gpr4-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + + sd2_cmd: sd2-cmd { + samsung,pins = "gpr4-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + + sd2_cd: sd2-cd { + samsung,pins = "gpr4-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd2_bus1: sd2-bus-width1 { + samsung,pins = "gpr4-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd2_bus4: sd2-bus-width4 { + samsung,pins = "gpr4-4", "gpr4-5", "gpr4-6"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; +}; + +&pinctrl_fsys1 { + gpr0: gpr0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpr1: gpr1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpr2: gpr2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpr3: gpr3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + sd0_clk: sd0-clk { + samsung,pins = "gpr0-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + + sd0_cmd: sd0-cmd { + samsung,pins = "gpr0-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd0_ds: sd0-ds { + samsung,pins = "gpr0-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <1>; + samsung,pin-drv = <3>; + }; + + sd0_qrdy: sd0-qrdy { + samsung,pins = "gpr0-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <1>; + samsung,pin-drv = <3>; + }; + + sd0_bus1: sd0-bus-width1 { + samsung,pins = "gpr1-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd0_bus4: sd0-bus-width4 { + samsung,pins = "gpr1-1", "gpr1-2", "gpr1-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd0_bus8: sd0-bus-width8 { + samsung,pins = "gpr1-4", "gpr1-5", "gpr1-6", "gpr1-7"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd1_clk: sd1-clk { + samsung,pins = "gpr2-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <2>; + }; + + sd1_cmd: sd1-cmd { + samsung,pins = "gpr2-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <2>; + }; + + sd1_ds: sd1-ds { + samsung,pins = "gpr2-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <1>; + samsung,pin-drv = <6>; + }; + + sd1_qrdy: sd1-qrdy { + samsung,pins = "gpr2-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <1>; + samsung,pin-drv = <6>; + }; + + sd1_int: sd1-int { + samsung,pins = "gpr2-4"; + samsung,pin-function = <2>; + samsung,pin-pud = <1>; + samsung,pin-drv = <6>; + }; + + sd1_bus1: sd1-bus-width1 { + samsung,pins = "gpr3-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <2>; + }; + + sd1_bus4: sd1-bus-width4 { + samsung,pins = "gpr3-1", "gpr3-2", "gpr3-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <2>; + }; + + sd1_bus8: sd1-bus-width8 { + samsung,pins = "gpr3-4", "gpr3-5", "gpr3-6", "gpr3-7"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <2>; + }; +}; diff --git a/arch/arm64/boot/dts/exynos/exynos7.dtsi b/arch/arm64/boot/dts/exynos/exynos7.dtsi index 6d6a4c2e4dfbb2..22fb71c15c5ff4 100644 --- a/arch/arm64/boot/dts/exynos/exynos7.dtsi +++ b/arch/arm64/boot/dts/exynos/exynos7.dtsi @@ -17,6 +17,17 @@ #address-cells = <2>; #size-cells = <2>; + aliases { + pinctrl0 = &pinctrl_alive; + pinctrl1 = &pinctrl_bus0; + pinctrl2 = &pinctrl_nfc; + pinctrl3 = &pinctrl_touch; + pinctrl4 = &pinctrl_ff; + pinctrl5 = &pinctrl_ese; + pinctrl6 = &pinctrl_fsys0; + pinctrl7 = &pinctrl_fsys1; + }; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -172,6 +183,59 @@ status = "disabled"; }; + pinctrl_alive: pinctrl@10580000 { + compatible = "samsung,exynos7-pinctrl"; + reg = <0x10580000 0x1000>; + + wakeup-interrupt-controller { + compatible = "samsung,exynos7-wakeup-eint"; + interrupt-parent = <&gic>; + interrupts = <0 16 0>; + }; + }; + + pinctrl_bus0: pinctrl@13470000 { + compatible = "samsung,exynos7-pinctrl"; + reg = <0x13470000 0x1000>; + interrupts = <0 383 0>; + }; + + pinctrl_nfc: pinctrl@14cd0000 { + compatible = "samsung,exynos7-pinctrl"; + reg = <0x14cd0000 0x1000>; + interrupts = <0 473 0>; + }; + + pinctrl_touch: pinctrl@14ce0000 { + compatible = "samsung,exynos7-pinctrl"; + reg = <0x14ce0000 0x1000>; + interrupts = <0 474 0>; + }; + + pinctrl_ff: pinctrl@14c90000 { + compatible = "samsung,exynos7-pinctrl"; + reg = <0x14c90000 0x1000>; + interrupts = <0 475 0>; + }; + + pinctrl_ese: pinctrl@14ca0000 { + compatible = "samsung,exynos7-pinctrl"; + reg = <0x14ca0000 0x1000>; + interrupts = <0 476 0>; + }; + + pinctrl_fsys0: pinctrl@10e60000 { + compatible = "samsung,exynos7-pinctrl"; + reg = <0x10e60000 0x1000>; + interrupts = <0 221 0>; + }; + + pinctrl_fsys1: pinctrl@15690000 { + compatible = "samsung,exynos7-pinctrl"; + reg = <0x15690000 0x1000>; + interrupts = <0 203 0>; + }; + timer { compatible = "arm,armv8-timer"; interrupts = <1 13 0xff01>, @@ -181,3 +245,5 @@ }; }; }; + +#include "exynos7-pinctrl.dtsi" From 0a7d1d805d741a6ed36e13c1441ba1e24945e898 Mon Sep 17 00:00:00 2001 From: Abhilash Kesavan Date: Sat, 22 Nov 2014 22:41:40 +0900 Subject: [PATCH 0310/3023] arm64: dts: Add PMU DT node for exynos7 SoC Adds PMU DT node for exynos7 SoC. Signed-off-by: Abhilash Kesavan Signed-off-by: Kukjin Kim --- Documentation/devicetree/bindings/arm/samsung/pmu.txt | 1 + arch/arm64/boot/dts/exynos/exynos7.dtsi | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/samsung/pmu.txt b/Documentation/devicetree/bindings/arm/samsung/pmu.txt index 1e1979b229ffc7..67b211381f2bd6 100644 --- a/Documentation/devicetree/bindings/arm/samsung/pmu.txt +++ b/Documentation/devicetree/bindings/arm/samsung/pmu.txt @@ -10,6 +10,7 @@ Properties: - "samsung,exynos5260-pmu" - for Exynos5260 SoC. - "samsung,exynos5410-pmu" - for Exynos5410 SoC, - "samsung,exynos5420-pmu" - for Exynos5420 SoC. + - "samsung,exynos7-pmu" - for Exynos7 SoC. second value must be always "syscon". - reg : offset and length of the register set. diff --git a/arch/arm64/boot/dts/exynos/exynos7.dtsi b/arch/arm64/boot/dts/exynos/exynos7.dtsi index 22fb71c15c5ff4..8aab9f9c0cd895 100644 --- a/arch/arm64/boot/dts/exynos/exynos7.dtsi +++ b/arch/arm64/boot/dts/exynos/exynos7.dtsi @@ -243,6 +243,11 @@ <1 11 0xff01>, <1 10 0xff01>; }; + + pmu_system_controller: system-controller@105c0000 { + compatible = "samsung,exynos7-pmu", "syscon"; + reg = <0x105c0000 0x5000>; + }; }; }; From 6de6f73ce644d2274b5ff53387769ce86bd7413f Mon Sep 17 00:00:00 2001 From: Abhilash Kesavan Date: Sat, 22 Nov 2014 22:41:45 +0900 Subject: [PATCH 0311/3023] arm64: dts: Add nodes for mmc, i2c, rtc, watchdog, adc on exynos7 Add nodes for 3 mmc channels, 12 i2c channels, rtc, watchdog and adc on exynos7 SoC. Signed-off-by: Naveen Krishna Ch Signed-off-by: Abhilash Kesavan Signed-off-by: Kukjin Kim --- .../boot/dts/exynos/exynos7-espresso.dts | 45 +++ arch/arm64/boot/dts/exynos/exynos7.dtsi | 276 ++++++++++++++++++ 2 files changed, 321 insertions(+) diff --git a/arch/arm64/boot/dts/exynos/exynos7-espresso.dts b/arch/arm64/boot/dts/exynos/exynos7-espresso.dts index e2c828322687a1..5424cc450f7250 100644 --- a/arch/arm64/boot/dts/exynos/exynos7-espresso.dts +++ b/arch/arm64/boot/dts/exynos/exynos7-espresso.dts @@ -18,6 +18,8 @@ aliases { serial0 = &serial_2; + mshc0 = &mmc_0; + mshc2 = &mmc_2; }; chosen { @@ -37,3 +39,46 @@ &serial_2 { status = "okay"; }; + +&rtc { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&adc { + status = "okay"; +}; + +&mmc_0 { + status = "okay"; + num-slots = <1>; + broken-cd; + cap-mmc-highspeed; + non-removable; + card-detect-delay = <200>; + clock-frequency = <800000000>; + samsung,dw-mshc-ciu-div = <3>; + samsung,dw-mshc-sdr-timing = <0 4>; + samsung,dw-mshc-ddr-timing = <0 2>; + pinctrl-names = "default"; + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_qrdy &sd0_bus1 &sd0_bus4 &sd0_bus8>; + bus-width = <8>; +}; + +&mmc_2 { + status = "okay"; + num-slots = <1>; + cap-sd-highspeed; + card-detect-delay = <200>; + clock-frequency = <400000000>; + samsung,dw-mshc-ciu-div = <3>; + samsung,dw-mshc-sdr-timing = <2 3>; + samsung,dw-mshc-ddr-timing = <1 2>; + pinctrl-names = "default"; + pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus1 &sd2_bus4>; + bus-width = <4>; + disable-wp; +}; diff --git a/arch/arm64/boot/dts/exynos/exynos7.dtsi b/arch/arm64/boot/dts/exynos/exynos7.dtsi index 8aab9f9c0cd895..d7a37c3a6b521f 100644 --- a/arch/arm64/boot/dts/exynos/exynos7.dtsi +++ b/arch/arm64/boot/dts/exynos/exynos7.dtsi @@ -113,6 +113,27 @@ "dout_sclk_mfc_pll"; }; + clock_top1: clock-controller@105e0000 { + compatible = "samsung,exynos7-clock-top1"; + reg = <0x105e0000 0xb000>; + #clock-cells = <1>; + clocks = <&fin_pll>, <&clock_topc DOUT_SCLK_BUS0_PLL>, + <&clock_topc DOUT_SCLK_BUS1_PLL>, + <&clock_topc DOUT_SCLK_CC_PLL>, + <&clock_topc DOUT_SCLK_MFC_PLL>; + clock-names = "fin_pll", "dout_sclk_bus0_pll", + "dout_sclk_bus1_pll", "dout_sclk_cc_pll", + "dout_sclk_mfc_pll"; + }; + + clock_ccore: clock-controller@105b0000 { + compatible = "samsung,exynos7-clock-ccore"; + reg = <0x105b0000 0xd00>; + #clock-cells = <1>; + clocks = <&fin_pll>, <&clock_topc DOUT_ACLK_CCORE_133>; + clock-names = "fin_pll", "dout_aclk_ccore_133"; + }; + clock_peric0: clock-controller@13610000 { compatible = "samsung,exynos7-clock-peric0"; reg = <0x13610000 0xd00>; @@ -143,6 +164,27 @@ clock-names = "fin_pll", "dout_aclk_peris_66"; }; + clock_fsys0: clock-controller@10e90000 { + compatible = "samsung,exynos7-clock-fsys0"; + reg = <0x10e90000 0xd00>; + #clock-cells = <1>; + clocks = <&fin_pll>, <&clock_top1 DOUT_ACLK_FSYS0_200>, + <&clock_top1 DOUT_SCLK_MMC2>; + clock-names = "fin_pll", "dout_aclk_fsys0_200", + "dout_sclk_mmc2"; + }; + + clock_fsys1: clock-controller@156e0000 { + compatible = "samsung,exynos7-clock-fsys1"; + reg = <0x156e0000 0xd00>; + #clock-cells = <1>; + clocks = <&fin_pll>, <&clock_top1 DOUT_ACLK_FSYS1_200>, + <&clock_top1 DOUT_SCLK_MMC0>, + <&clock_top1 DOUT_SCLK_MMC1>; + clock-names = "fin_pll", "dout_aclk_fsys1_200", + "dout_sclk_mmc0", "dout_sclk_mmc1"; + }; + serial_0: serial@13630000 { compatible = "samsung,exynos4210-uart"; reg = <0x13630000 0x100>; @@ -236,6 +278,162 @@ interrupts = <0 203 0>; }; + hsi2c_0: hsi2c@13640000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x13640000 0x1000>; + interrupts = <0 441 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c0_bus>; + clocks = <&clock_peric0 PCLK_HSI2C0>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_1: hsi2c@13650000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x13650000 0x1000>; + interrupts = <0 442 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c1_bus>; + clocks = <&clock_peric0 PCLK_HSI2C1>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_2: hsi2c@14e60000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x14e60000 0x1000>; + interrupts = <0 459 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c2_bus>; + clocks = <&clock_peric1 PCLK_HSI2C2>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_3: hsi2c@14e70000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x14e70000 0x1000>; + interrupts = <0 460 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c3_bus>; + clocks = <&clock_peric1 PCLK_HSI2C3>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_4: hsi2c@13660000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x13660000 0x1000>; + interrupts = <0 443 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c4_bus>; + clocks = <&clock_peric0 PCLK_HSI2C4>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_5: hsi2c@13670000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x13670000 0x1000>; + interrupts = <0 444 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c5_bus>; + clocks = <&clock_peric0 PCLK_HSI2C5>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_6: hsi2c@14e00000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x14e00000 0x1000>; + interrupts = <0 461 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c6_bus>; + clocks = <&clock_peric1 PCLK_HSI2C6>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_7: hsi2c@13e10000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x13e10000 0x1000>; + interrupts = <0 462 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c7_bus>; + clocks = <&clock_peric1 PCLK_HSI2C7>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_8: hsi2c@14e20000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x14e20000 0x1000>; + interrupts = <0 463 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c8_bus>; + clocks = <&clock_peric1 PCLK_HSI2C8>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_9: hsi2c@13680000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x13680000 0x1000>; + interrupts = <0 445 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c9_bus>; + clocks = <&clock_peric0 PCLK_HSI2C9>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_10: hsi2c@13690000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x13690000 0x1000>; + interrupts = <0 446 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c10_bus>; + clocks = <&clock_peric0 PCLK_HSI2C10>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_11: hsi2c@136a0000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x136a0000 0x1000>; + interrupts = <0 447 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c11_bus>; + clocks = <&clock_peric0 PCLK_HSI2C11>; + clock-names = "hsi2c"; + status = "disabled"; + }; + timer { compatible = "arm,armv8-timer"; interrupts = <1 13 0xff01>, @@ -248,6 +446,84 @@ compatible = "samsung,exynos7-pmu", "syscon"; reg = <0x105c0000 0x5000>; }; + + rtc: rtc@10590000 { + compatible = "samsung,s3c6410-rtc"; + reg = <0x10590000 0x100>; + interrupts = <0 355 0>, <0 356 0>; + clocks = <&clock_ccore PCLK_RTC>; + clock-names = "rtc"; + status = "disabled"; + }; + + watchdog: watchdog@101d0000 { + compatible = "samsung,exynos7-wdt"; + reg = <0x101d0000 0x100>; + interrupts = <0 110 0>; + clocks = <&clock_peris PCLK_WDT>; + clock-names = "watchdog"; + samsung,syscon-phandle = <&pmu_system_controller>; + status = "disabled"; + }; + + mmc_0: mmc@15740000 { + compatible = "samsung,exynos7-dw-mshc-smu"; + interrupts = <0 201 0>; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x15740000 0x2000>; + clocks = <&clock_fsys1 ACLK_MMC0>, + <&clock_top1 CLK_SCLK_MMC0>; + clock-names = "biu", "ciu"; + fifo-depth = <0x40>; + status = "disabled"; + }; + + mmc_1: mmc@15750000 { + compatible = "samsung,exynos7-dw-mshc"; + interrupts = <0 202 0>; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x15750000 0x2000>; + clocks = <&clock_fsys1 ACLK_MMC1>, + <&clock_top1 CLK_SCLK_MMC1>; + clock-names = "biu", "ciu"; + fifo-depth = <0x40>; + status = "disabled"; + }; + + mmc_2: mmc@15560000 { + compatible = "samsung,exynos7-dw-mshc-smu"; + interrupts = <0 216 0>; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x15560000 0x2000>; + clocks = <&clock_fsys0 ACLK_MMC2>, + <&clock_top1 CLK_SCLK_MMC2>; + clock-names = "biu", "ciu"; + fifo-depth = <0x40>; + status = "disabled"; + }; + + adc: adc@13620000 { + compatible = "samsung,exynos7-adc"; + reg = <0x13620000 0x100>; + interrupts = <0 448 0>; + clocks = <&clock_peric0 PCLK_ADCIF>; + clock-names = "adc"; + #io-channel-cells = <1>; + io-channel-ranges; + status = "disabled"; + }; + + pwm: pwm@136c0000 { + compatible = "samsung,exynos4210-pwm"; + reg = <0x136c0000 0x100>; + samsung,pwm-outputs = <0>, <1>, <2>, <3>; + #pwm-cells = <3>; + clocks = <&clock_peric0 PCLK_PWM>; + clock-names = "timers"; + }; }; }; From 6f56eef1f9aba3747c811780a4768618167d5c97 Mon Sep 17 00:00:00 2001 From: Alim Akhtar Date: Sat, 22 Nov 2014 22:41:52 +0900 Subject: [PATCH 0312/3023] arm64: Enable ARMv8 based exynos7 SoC support This patch adds the necessary Kconfig entries to enable support for the ARMv8 based exynos7 SoC. It also enables RTC, WDT and Pinctrl for exynos7 SoC. Signed-off-by: Alim Akhtar Signed-off-by: Naveen Krishna Ch Signed-off-by: Abhilash Kesavan Reviewed-by: Thomas Abraham Tested-by: Thomas Abraham Cc: Rob Herring Cc: Catalin Marinas Signed-off-by: Kukjin Kim --- arch/arm64/Kconfig | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index b1f9a20a367746..15e8e7469ffde4 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -148,6 +148,23 @@ source "kernel/Kconfig.freezer" menu "Platform selection" +config ARCH_EXYNOS + bool + help + This enables support for Samsung Exynos SoC family + +config ARCH_EXYNOS7 + bool "ARMv8 based Samsung Exynos7" + select ARCH_EXYNOS + select COMMON_CLK_SAMSUNG + select HAVE_S3C2410_WATCHDOG if WATCHDOG + select HAVE_S3C_RTC if RTC_CLASS + select PINCTRL + select PINCTRL_EXYNOS + + help + This enables support for Samsung Exynos7 SoC family + config ARCH_SEATTLE bool "AMD Seattle SoC Family" help From 1a14f53271aee500da0ed450ff62ce848213c60a Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 26 Nov 2014 15:43:35 +0900 Subject: [PATCH 0313/3023] ARM: SAMSUNG: print CPU id on probe It's useful to get the CPU ID/rev printed during boot sometimes, so add a line with that information. Given that the fields have moved within the register over time, don't try to be clever and parse it -- just print the raw values for now. Signed-off-by: Olof Johansson Signed-off-by: Kukjin Kim --- arch/arm/plat-samsung/cpu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/plat-samsung/cpu.c b/arch/arm/plat-samsung/cpu.c index 360618ee39e50d..71333bb61013c6 100644 --- a/arch/arm/plat-samsung/cpu.c +++ b/arch/arm/plat-samsung/cpu.c @@ -40,10 +40,14 @@ void __init s3c64xx_init_cpu(void) } samsung_cpu_rev = 0; + + pr_info("Samsung CPU ID: 0x%08lx\n", samsung_cpu_id); } void __init s5p_init_cpu(void __iomem *cpuid_addr) { samsung_cpu_id = __raw_readl(cpuid_addr); samsung_cpu_rev = samsung_cpu_id & 0xFF; + + pr_info("Samsung CPU ID: 0x%08lx\n", samsung_cpu_id); } From 842ebf60bbad6d6e5ebaa063409fefdd2a7eb992 Mon Sep 17 00:00:00 2001 From: Andreas Faerber Date: Sat, 22 Nov 2014 23:31:30 +0900 Subject: [PATCH 0314/3023] ARM: exynos_defconfig: Enable LM90 driver multi_v7_defconfig has it as Y already, so build it in here, too, for consistency, and therefore build in HWMON as well. Signed-off-by: Andreas Faerber Reviewed-by: Javier Martinez Canillas Signed-off-by: Kukjin Kim --- arch/arm/configs/exynos_defconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig index 5ef14de00a29ba..31115712461995 100644 --- a/arch/arm/configs/exynos_defconfig +++ b/arch/arm/configs/exynos_defconfig @@ -84,7 +84,8 @@ CONFIG_DEBUG_GPIO=y CONFIG_POWER_SUPPLY=y CONFIG_BATTERY_SBS=y CONFIG_CHARGER_TPS65090=y -# CONFIG_HWMON is not set +CONFIG_HWMON=y +CONFIG_SENSORS_LM90=y CONFIG_THERMAL=y CONFIG_EXYNOS_THERMAL=y CONFIG_EXYNOS_THERMAL_CORE=y From f6b5dd4088d082b53eb135e1d6b4b213bf5ce127 Mon Sep 17 00:00:00 2001 From: Andrey Gusakov Date: Thu, 18 Dec 2014 23:41:52 +0300 Subject: [PATCH 0315/3023] ARM: shmobile: r8a7790: add MLB+ clock Add MLB+ clock to R8A7790 device tree. Signed-off-by: Andrey Gusakov [Sergei: rebased, renamed, added changelog] Signed-off-by: Sergei Shtylyov Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7790.dtsi | 13 +++++++------ include/dt-bindings/clock/r8a7790-clock.h | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index ffeff98fa16e1c..af30c2470f8550 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -1149,16 +1149,17 @@ mstp8_clks: mstp8_clks@e6150990 { compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe6150990 0 4>, <0 0xe61509a0 0 4>; - clocks = <&zg_clk>, <&zg_clk>, <&zg_clk>, <&zg_clk>, <&p_clk>, - <&zs_clk>, <&zs_clk>; + clocks = <&hp_clk>, <&zg_clk>, <&zg_clk>, <&zg_clk>, + <&zg_clk>, <&p_clk>, <&zs_clk>, <&zs_clk>; #clock-cells = <1>; clock-indices = < - R8A7790_CLK_VIN3 R8A7790_CLK_VIN2 R8A7790_CLK_VIN1 - R8A7790_CLK_VIN0 R8A7790_CLK_ETHER R8A7790_CLK_SATA1 - R8A7790_CLK_SATA0 + R8A7790_CLK_MLB R8A7790_CLK_VIN3 R8A7790_CLK_VIN2 + R8A7790_CLK_VIN1 R8A7790_CLK_VIN0 R8A7790_CLK_ETHER + R8A7790_CLK_SATA1 R8A7790_CLK_SATA0 >; clock-output-names = - "vin3", "vin2", "vin1", "vin0", "ether", "sata1", "sata0"; + "mlb", "vin3", "vin2", "vin1", "vin0", "ether", + "sata1", "sata0"; }; mstp9_clks: mstp9_clks@e6150994 { compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks"; diff --git a/include/dt-bindings/clock/r8a7790-clock.h b/include/dt-bindings/clock/r8a7790-clock.h index c27b3b5133b944..91940271cf8347 100644 --- a/include/dt-bindings/clock/r8a7790-clock.h +++ b/include/dt-bindings/clock/r8a7790-clock.h @@ -97,6 +97,7 @@ #define R8A7790_CLK_LVDS0 26 /* MSTP8 */ +#define R8A7790_CLK_MLB 2 #define R8A7790_CLK_VIN3 8 #define R8A7790_CLK_VIN2 9 #define R8A7790_CLK_VIN1 10 From 7408d3061d2f04181820902fae6e92e4a73d5cc0 Mon Sep 17 00:00:00 2001 From: Andrey Gusakov Date: Thu, 18 Dec 2014 23:43:03 +0300 Subject: [PATCH 0316/3023] ARM: shmobile: r8a7791: add MLB+ clock Add MLB+ clock to R8A7791 device tree. Signed-off-by: Andrey Gusakov [Sergei: rebased, renamed, added changelog] Signed-off-by: Sergei Shtylyov Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7791.dtsi | 10 +++++----- include/dt-bindings/clock/r8a7791-clock.h | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index 78d637135e77f3..28102265cc71f4 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -1154,17 +1154,17 @@ mstp8_clks: mstp8_clks@e6150990 { compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe6150990 0 4>, <0 0xe61509a0 0 4>; - clocks = <&zg_clk>, <&zg_clk>, <&zg_clk>, <&zg_clk>, <&p_clk>, - <&zs_clk>, <&zs_clk>; + clocks = <&hp_clk>, <&zg_clk>, <&zg_clk>, <&zg_clk>, + <&zg_clk>, <&p_clk>, <&zs_clk>, <&zs_clk>; #clock-cells = <1>; clock-indices = < - R8A7791_CLK_IPMMU_SGX + R8A7791_CLK_IPMMU_SGX R8A7791_CLK_MLB R8A7791_CLK_VIN2 R8A7791_CLK_VIN1 R8A7791_CLK_VIN0 R8A7791_CLK_ETHER R8A7791_CLK_SATA1 R8A7791_CLK_SATA0 >; clock-output-names = - "ipmmu_sgx", "vin2", "vin1", "vin0", "ether", "sata1", - "sata0"; + "ipmmu_sgx", "mlb", "vin2", "vin1", "vin0", "ether", + "sata1", "sata0"; }; mstp9_clks: mstp9_clks@e6150994 { compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks"; diff --git a/include/dt-bindings/clock/r8a7791-clock.h b/include/dt-bindings/clock/r8a7791-clock.h index ee9bb94423f393..f096f3f6c16a4c 100644 --- a/include/dt-bindings/clock/r8a7791-clock.h +++ b/include/dt-bindings/clock/r8a7791-clock.h @@ -92,6 +92,7 @@ /* MSTP8 */ #define R8A7791_CLK_IPMMU_SGX 0 +#define R8A7791_CLK_MLB 2 #define R8A7791_CLK_VIN2 9 #define R8A7791_CLK_VIN1 10 #define R8A7791_CLK_VIN0 11 From 3b2b36e5f0ba60f5a7a770ab1bae3264b8d090b8 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 9 Dec 2014 17:37:44 +0200 Subject: [PATCH 0317/3023] drm: adv7511: Remove interlaced mode check The ADV7511 supports interlaced modes fine, there's no need to reject them. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/i2c/adv7511.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/i2c/adv7511.c b/drivers/gpu/drm/i2c/adv7511.c index faf1c0c5ab2eb9..fa140e04d5fa72 100644 --- a/drivers/gpu/drm/i2c/adv7511.c +++ b/drivers/gpu/drm/i2c/adv7511.c @@ -644,9 +644,6 @@ static int adv7511_encoder_mode_valid(struct drm_encoder *encoder, if (mode->clock > 165000) return MODE_CLOCK_HIGH; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - return MODE_NO_INTERLACE; - return MODE_OK; } From 347d761c74f75d55a36350ae7505498bd56b33ec Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 11 Dec 2014 01:26:04 +0200 Subject: [PATCH 0318/3023] drm: rcar-du: Don't fail probe in case of partial encoder init error If an encoder fails to initialize the device can still be used without the failed encoder. Don't propagate the error out of the probe function but just skip the failed encoder. As a special case a deferred probe request from the encoder is still propagated out of the probe function in order not to break the deferred probing mechanism. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 28 +++++++++++++++++------ drivers/gpu/drm/rcar-du/rcar_du_kms.c | 15 ++++++++++-- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c index 34a122a3966419..7c74ecf2ca672b 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c @@ -193,32 +193,46 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu, if (renc->lvds) { dev_err(rcdu->dev, "Chaining LVDS and HDMI encoders not supported\n"); - return -EINVAL; + ret = -EINVAL; + goto done; } ret = rcar_du_hdmienc_init(rcdu, renc, enc_node); if (ret < 0) - return ret; + goto done; } else { ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs, encoder_type); if (ret < 0) - return ret; + goto done; drm_encoder_helper_add(encoder, &encoder_helper_funcs); } switch (encoder_type) { case DRM_MODE_ENCODER_LVDS: - return rcar_du_lvds_connector_init(rcdu, renc, con_node); + ret = rcar_du_lvds_connector_init(rcdu, renc, con_node); + break; case DRM_MODE_ENCODER_DAC: - return rcar_du_vga_connector_init(rcdu, renc); + ret = rcar_du_vga_connector_init(rcdu, renc); + break; case DRM_MODE_ENCODER_TMDS: - return rcar_du_hdmi_connector_init(rcdu, renc); + ret = rcar_du_hdmi_connector_init(rcdu, renc); + break; default: - return -EINVAL; + ret = -EINVAL; + break; } + +done: + if (ret < 0) { + if (encoder->name) + encoder->funcs->destroy(encoder); + devm_kfree(rcdu->dev, renc); + } + + return ret; } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index 0c5ee616b5a3aa..cc9136e8ee9cd2 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -346,8 +346,14 @@ static int rcar_du_encoders_init(struct rcar_du_device *rcdu) /* Process the output pipeline. */ ret = rcar_du_encoders_init_one(rcdu, output, &ep); if (ret < 0) { - of_node_put(ep_node); - return ret; + if (ret == -EPROBE_DEFER) { + of_node_put(ep_node); + return ret; + } + + dev_info(rcdu->dev, + "encoder initialization failed, skipping\n"); + continue; } num_encoders += ret; @@ -413,6 +419,11 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu) if (ret < 0) return ret; + if (ret == 0) { + dev_err(rcdu->dev, "error: no encoder could be initialized\n"); + return -EINVAL; + } + num_encoders = ret; /* Set the possible CRTCs and possible clones. There's always at least From 49785e25816b0567112ba599504c3b78901a7db4 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 9 Dec 2014 22:45:11 +0200 Subject: [PATCH 0319/3023] drm: rcar-du: Configure pitch for chroma plane of multiplanar formats The PnMWR register containing the plane stride must be programmed with correct stride values for both the luma and chroma planes when using a multiplanar format. Fix it. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_plane.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index 72a7cb47bd9f8a..fb3ea4f95d4aa2 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c @@ -130,6 +130,8 @@ void rcar_du_plane_update_base(struct rcar_du_plane *plane) if (plane->format->planes == 2) { index = (index + 1) % 8; + rcar_du_plane_write(rgrp, index, PnMWR, plane->pitch); + rcar_du_plane_write(rgrp, index, PnSPXR, plane->src_x); rcar_du_plane_write(rgrp, index, PnSPYR, plane->src_y * (plane->format->bpp == 16 ? 2 : 1) / 2); From 5e433b6312d9d05ac83078bfd2e6371f24d6eb46 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 26 Oct 2014 01:14:27 +0300 Subject: [PATCH 0320/3023] drm: rcar-du: Remove LVDS and HDMI encoders chaining restriction The rcar-du driver refuses connecting an LVDS output to an HDMI encoder. There is not technical reason for that restriction, remove it. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 7 ------- drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c index 7c74ecf2ca672b..243aba8d4dd270 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c @@ -190,13 +190,6 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu, } if (type == RCAR_DU_ENCODER_HDMI) { - if (renc->lvds) { - dev_err(rcdu->dev, - "Chaining LVDS and HDMI encoders not supported\n"); - ret = -EINVAL; - goto done; - } - ret = rcar_du_hdmienc_init(rcdu, renc, enc_node); if (ret < 0) goto done; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c index 359bc999a9c844..0d774a937e7964 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c @@ -21,6 +21,7 @@ #include "rcar_du_drv.h" #include "rcar_du_encoder.h" #include "rcar_du_hdmienc.h" +#include "rcar_du_lvdsenc.h" struct rcar_du_hdmienc { struct rcar_du_encoder *renc; @@ -39,9 +40,15 @@ static void rcar_du_hdmienc_dpms(struct drm_encoder *encoder, int mode) if (hdmienc->dpms == mode) return; + if (mode == DRM_MODE_DPMS_ON && hdmienc->renc->lvds) + rcar_du_lvdsenc_dpms(hdmienc->renc->lvds, encoder->crtc, mode); + if (sfuncs->dpms) sfuncs->dpms(encoder, mode); + if (mode != DRM_MODE_DPMS_ON && hdmienc->renc->lvds) + rcar_du_lvdsenc_dpms(hdmienc->renc->lvds, encoder->crtc, mode); + hdmienc->dpms = mode; } @@ -49,8 +56,16 @@ static bool rcar_du_hdmienc_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { + struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder); struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder); + /* The internal LVDS encoder has a clock frequency operating range of + * 30MHz to 150MHz. Clamp the clock accordingly. + */ + if (hdmienc->renc->lvds) + adjusted_mode->clock = clamp(adjusted_mode->clock, + 30000, 150000); + if (sfuncs->mode_fixup == NULL) return true; From 0c1c877681e73b87ef63634ed7da55a711de40a6 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 9 Dec 2014 00:21:12 +0200 Subject: [PATCH 0321/3023] drm: rcar-du: Refactor DEFR8 feature Rename the feature from RCAR_DU_FEATURE_DEFR8 to RCAR_DU_FEATURE_EXT_CTRL_REGS to cover all extended control registers in addition to the DEFR8 register. Usage of the feature is refactored to optimize runtime operation and prepare for external clock support. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 7 ++++--- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 6 ++++-- drivers/gpu/drm/rcar-du/rcar_du_drv.h | 2 +- drivers/gpu/drm/rcar-du/rcar_du_group.c | 9 +++++---- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 23cc910951f430..cf0dca13264fcd 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -139,9 +139,10 @@ void rcar_du_crtc_route_output(struct drm_crtc *crtc, */ rcrtc->outputs |= BIT(output); - /* Store RGB routing to DPAD0 for R8A7790. */ - if (rcar_du_has(rcdu, RCAR_DU_FEATURE_DEFR8) && - output == RCAR_DU_OUTPUT_DPAD0) + /* Store RGB routing to DPAD0, the hardware will be configured when + * starting the CRTC. + */ + if (output == RCAR_DU_OUTPUT_DPAD0) rcdu->dpad0_source = rcrtc->index; } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 967ae8f20233ed..4fb29b4735609f 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -56,7 +56,8 @@ static const struct rcar_du_device_info rcar_du_r8a7779_info = { }; static const struct rcar_du_device_info rcar_du_r8a7790_info = { - .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_DEFR8, + .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK + | RCAR_DU_FEATURE_EXT_CTRL_REGS, .quirks = RCAR_DU_QUIRK_ALIGN_128B | RCAR_DU_QUIRK_LVDS_LANES, .num_crtcs = 3, .routes = { @@ -83,7 +84,8 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = { }; static const struct rcar_du_device_info rcar_du_r8a7791_info = { - .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_DEFR8, + .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK + | RCAR_DU_FEATURE_EXT_CTRL_REGS, .num_crtcs = 2, .routes = { /* R8A7791 has one RGB output, one LVDS output and one diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h index 0a724669f02d46..c5b9ea6a7eaab3 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h @@ -27,7 +27,7 @@ struct rcar_du_device; struct rcar_du_lvdsenc; #define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK (1 << 0) /* Per-CRTC IRQ and clock */ -#define RCAR_DU_FEATURE_DEFR8 (1 << 1) /* Has DEFR8 register */ +#define RCAR_DU_FEATURE_EXT_CTRL_REGS (1 << 1) /* Has extended control registers */ #define RCAR_DU_QUIRK_ALIGN_128B (1 << 0) /* Align pitches to 128 bytes */ #define RCAR_DU_QUIRK_LVDS_LANES (1 << 1) /* LVDS lanes 1 and 3 inverted */ diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c index 4e7614b145db55..7b6428234252e8 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c @@ -48,9 +48,6 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp) { u32 defr8 = DEFR8_CODE | DEFR8_DEFE8; - if (!rcar_du_has(rgrp->dev, RCAR_DU_FEATURE_DEFR8)) - return; - /* The DEFR8 register for the first group also controls RGB output * routing to DPAD0 */ @@ -69,7 +66,8 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp) rcar_du_group_write(rgrp, DEFR4, DEFR4_CODE); rcar_du_group_write(rgrp, DEFR5, DEFR5_CODE | DEFR5_DEFE5); - rcar_du_group_setup_defr8(rgrp); + if (rcar_du_has(rgrp->dev, RCAR_DU_FEATURE_EXT_CTRL_REGS)) + rcar_du_group_setup_defr8(rgrp); /* Use DS1PR and DS2PR to configure planes priorities and connects the * superposition 0 to DU0 pins. DU1 pins will be configured dynamically. @@ -149,6 +147,9 @@ static int rcar_du_set_dpad0_routing(struct rcar_du_device *rcdu) { int ret; + if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_EXT_CTRL_REGS)) + return 0; + /* RGB output routing to DPAD0 is configured in the DEFR8 register of * the first group. As this function can be called with the DU0 and DU1 * CRTCs disabled, we need to enable the first group clock before From 1b30dbde8596ca8de2497c2a50d5381dfe62ee8c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 9 Dec 2014 00:24:49 +0200 Subject: [PATCH 0322/3023] drm: rcar-du: Add support for external pixel clock The DU uses the module functional clock as the default pixel clock, but supports using an externally supplied pixel clock instead. Support this by adding the external pixel clock to the DT bindings, and selecting the clock automatically at runtime based on the requested mode pixel frequency. The input clock pins to DU channels routing is configurable, but currently hardcoded to connect input clock i to channel i. Signed-off-by: Laurent Pinchart --- .../devicetree/bindings/video/renesas,du.txt | 4 ++ drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 60 +++++++++++++++++-- drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 1 + drivers/gpu/drm/rcar-du/rcar_du_group.c | 14 ++++- drivers/gpu/drm/rcar-du/rcar_du_regs.h | 4 +- 5 files changed, 74 insertions(+), 9 deletions(-) diff --git a/Documentation/devicetree/bindings/video/renesas,du.txt b/Documentation/devicetree/bindings/video/renesas,du.txt index 5102830f276017..c902323928f700 100644 --- a/Documentation/devicetree/bindings/video/renesas,du.txt +++ b/Documentation/devicetree/bindings/video/renesas,du.txt @@ -26,6 +26,10 @@ Required Properties: per LVDS encoder. The functional clocks must be named "du.x" with "x" being the channel numerical index. The LVDS clocks must be named "lvds.x" with "x" being the LVDS encoder numerical index. + - In addition to the functional and encoder clocks, all DU versions also + support externally supplied pixel clocks. Those clocks are optional. + When supplied they must be named "dclkin.x" with "x" being the input + clock numerical index. Required nodes: diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index cf0dca13264fcd..ce280bd390a9eb 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -74,33 +74,71 @@ static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc) if (ret < 0) return ret; + ret = clk_prepare_enable(rcrtc->extclock); + if (ret < 0) + goto error_clock; + ret = rcar_du_group_get(rcrtc->group); if (ret < 0) - clk_disable_unprepare(rcrtc->clock); + goto error_group; + + return 0; +error_group: + clk_disable_unprepare(rcrtc->extclock); +error_clock: + clk_disable_unprepare(rcrtc->clock); return ret; } static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc) { rcar_du_group_put(rcrtc->group); + + clk_disable_unprepare(rcrtc->extclock); clk_disable_unprepare(rcrtc->clock); } static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) { const struct drm_display_mode *mode = &rcrtc->crtc.mode; + unsigned long mode_clock = mode->clock * 1000; unsigned long clk; u32 value; + u32 escr; u32 div; - /* Dot clock */ + /* Compute the clock divisor and select the internal or external dot + * clock based on the requested frequency. + */ clk = clk_get_rate(rcrtc->clock); - div = DIV_ROUND_CLOSEST(clk, mode->clock * 1000); + div = DIV_ROUND_CLOSEST(clk, mode_clock); div = clamp(div, 1U, 64U) - 1; + escr = div | ESCR_DCLKSEL_CLKS; + + if (rcrtc->extclock) { + unsigned long extclk; + unsigned long extrate; + unsigned long rate; + u32 extdiv; + + extclk = clk_get_rate(rcrtc->extclock); + extdiv = DIV_ROUND_CLOSEST(extclk, mode_clock); + extdiv = clamp(extdiv, 1U, 64U) - 1; + + rate = clk / (div + 1); + extrate = extclk / (extdiv + 1); + + if (abs((long)extrate - (long)mode_clock) < + abs((long)rate - (long)mode_clock)) { + dev_dbg(rcrtc->group->dev->dev, + "crtc%u: using external clock\n", rcrtc->index); + escr = extdiv | ESCR_DCLKSEL_DCLKIN; + } + } rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? ESCR2 : ESCR, - ESCR_DCLKSEL_CLKS | div); + escr); rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? OTAR2 : OTAR, 0); /* Signal polarities */ @@ -543,12 +581,13 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index) struct rcar_du_crtc *rcrtc = &rcdu->crtcs[index]; struct drm_crtc *crtc = &rcrtc->crtc; unsigned int irqflags; - char clk_name[5]; + struct clk *clk; + char clk_name[9]; char *name; int irq; int ret; - /* Get the CRTC clock. */ + /* Get the CRTC clock and the optional external clock. */ if (rcar_du_has(rcdu, RCAR_DU_FEATURE_CRTC_IRQ_CLOCK)) { sprintf(clk_name, "du.%u", index); name = clk_name; @@ -562,6 +601,15 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index) return PTR_ERR(rcrtc->clock); } + sprintf(clk_name, "dclkin.%u", index); + clk = devm_clk_get(rcdu->dev, clk_name); + if (!IS_ERR(clk)) { + rcrtc->extclock = clk; + } else if (PTR_ERR(rcrtc->clock) == -EPROBE_DEFER) { + dev_info(rcdu->dev, "can't get external clock %u\n", index); + return -EPROBE_DEFER; + } + rcrtc->group = rgrp; rcrtc->mmio_offset = mmio_offsets[index]; rcrtc->index = index; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h index 984e6083699fe3..d2f89f7d2e5e3e 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h @@ -26,6 +26,7 @@ struct rcar_du_crtc { struct drm_crtc crtc; struct clk *clock; + struct clk *extclock; unsigned int mmio_offset; unsigned int index; bool started; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c index 7b6428234252e8..1bdc0ee0c2483c 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c @@ -66,9 +66,21 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp) rcar_du_group_write(rgrp, DEFR4, DEFR4_CODE); rcar_du_group_write(rgrp, DEFR5, DEFR5_CODE | DEFR5_DEFE5); - if (rcar_du_has(rgrp->dev, RCAR_DU_FEATURE_EXT_CTRL_REGS)) + if (rcar_du_has(rgrp->dev, RCAR_DU_FEATURE_EXT_CTRL_REGS)) { rcar_du_group_setup_defr8(rgrp); + /* Configure input dot clock routing. We currently hardcode the + * configuration to routing DOTCLKINn to DUn. + */ + rcar_du_group_write(rgrp, DIDSR, DIDSR_CODE | + DIDSR_LCDS_DCLKIN(2) | + DIDSR_LCDS_DCLKIN(1) | + DIDSR_LCDS_DCLKIN(0) | + DIDSR_PDCS_CLK(2, 0) | + DIDSR_PDCS_CLK(1, 0) | + DIDSR_PDCS_CLK(0, 0)); + } + /* Use DS1PR and DS2PR to configure planes priorities and connects the * superposition 0 to DU0 pins. DU1 pins will be configured dynamically. */ diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h index 73f7347f740bd1..c3639d1db28b86 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h @@ -256,8 +256,8 @@ #define DIDSR_LCDS_LVDS0(n) (2 << (8 + (n) * 2)) #define DIDSR_LCDS_LVDS1(n) (3 << (8 + (n) * 2)) #define DIDSR_LCDS_MASK(n) (3 << (8 + (n) * 2)) -#define DIDSR_PCDS_CLK(n, clk) (clk << ((n) * 2)) -#define DIDSR_PCDS_MASK(n) (3 << ((n) * 2)) +#define DIDSR_PDCS_CLK(n, clk) (clk << ((n) * 2)) +#define DIDSR_PDCS_MASK(n) (3 << ((n) * 2)) /* ----------------------------------------------------------------------------- * Display Timing Generation Registers From f67e1e058b722a2a2af4e40fa80936889f128b4c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 9 Dec 2014 00:40:59 +0200 Subject: [PATCH 0323/3023] drm: rcar-du: Output HSYNC instead of CSYNC The DU outputs by default a composite sync signal (XOR of the horizontal and vertical sync signals) on the HSYNC output pin. As this can confuse devices and isn't needed by any of the supported encoders, configure the HSYNC pin to output the horizontal sync signal. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index ce280bd390a9eb..25b762b5876502 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -144,7 +144,7 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) /* Signal polarities */ value = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? 0 : DSMR_VSL) | ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? 0 : DSMR_HSL) - | DSMR_DIPM_DE; + | DSMR_DIPM_DE | DSMR_CSPM; rcar_du_crtc_write(rcrtc, DSMR, value); /* Display timings */ From 2d60762adebfa9fabca69fc2f2f2d51d4cfd7af5 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 9 Dec 2014 01:18:36 +0200 Subject: [PATCH 0324/3023] drm: rcar-du: Enable hotplug detection on HDMI connector As HDMI support hotplug detection, enable HPD-based poll on HDMI connectors. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c index 4d7d4dd46d2603..322b7208171ab1 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c @@ -95,6 +95,7 @@ int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu, connector = &rcon->connector; connector->display_info.width_mm = 0; connector->display_info.height_mm = 0; + connector->polled = DRM_CONNECTOR_POLL_HPD; ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs, DRM_MODE_CONNECTOR_HDMIA); From 3dbf11e42108d2c8a497923df959eb82388131f8 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 9 Dec 2014 13:19:10 +0200 Subject: [PATCH 0325/3023] drm: rcar-du: Clamp DPMS states to on and off The intermediate DPMS standby and suspend states are a thing from the past. They only matter in practice for VGA CRT monitors, and are just a power saving vs. resume time optimization. Given that they have never been implemented properly in the rcar-du driver and that the Intel driver has dropped them on the vga port years ago, it's safe to only care about the on and off states. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 3 +++ drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 3 +++ drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 3 +++ 3 files changed, 9 insertions(+) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 25b762b5876502..86766cc6360a09 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -347,6 +347,9 @@ static void rcar_du_crtc_dpms(struct drm_crtc *crtc, int mode) { struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); + if (mode != DRM_MODE_DPMS_ON) + mode = DRM_MODE_DPMS_OFF; + if (rcrtc->dpms == mode) return; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c index 243aba8d4dd270..279167f783f678 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c @@ -46,6 +46,9 @@ static void rcar_du_encoder_dpms(struct drm_encoder *encoder, int mode) { struct rcar_du_encoder *renc = to_rcar_encoder(encoder); + if (mode != DRM_MODE_DPMS_ON) + mode = DRM_MODE_DPMS_OFF; + if (renc->lvds) rcar_du_lvdsenc_dpms(renc->lvds, encoder->crtc, mode); } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c index 0d774a937e7964..221f0a17fd6a62 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c @@ -37,6 +37,9 @@ static void rcar_du_hdmienc_dpms(struct drm_encoder *encoder, int mode) struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder); struct drm_encoder_slave_funcs *sfuncs = to_slave_funcs(encoder); + if (mode != DRM_MODE_DPMS_ON) + mode = DRM_MODE_DPMS_OFF; + if (hdmienc->dpms == mode) return; From 906eff7fcada4186cde54eb89572fb774ab294a0 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 9 Dec 2014 19:11:18 +0200 Subject: [PATCH 0326/3023] drm: rcar-du: Implement support for interlaced modes Accept interlaced modes on the VGA and HDMI connectors and configure the hardware accordingly. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 23 +++++++++++++++-------- drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c | 1 + drivers/gpu/drm/rcar-du/rcar_du_plane.c | 18 +++++++++++++++--- drivers/gpu/drm/rcar-du/rcar_du_regs.h | 1 + drivers/gpu/drm/rcar-du/rcar_du_vgacon.c | 1 + 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 86766cc6360a09..25c7a998fc2cf0 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -155,12 +155,15 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) mode->hsync_start - 1); rcar_du_crtc_write(rcrtc, HCR, mode->htotal - 1); - rcar_du_crtc_write(rcrtc, VDSR, mode->vtotal - mode->vsync_end - 2); - rcar_du_crtc_write(rcrtc, VDER, mode->vtotal - mode->vsync_end + - mode->vdisplay - 2); - rcar_du_crtc_write(rcrtc, VSPR, mode->vtotal - mode->vsync_end + - mode->vsync_start - 1); - rcar_du_crtc_write(rcrtc, VCR, mode->vtotal - 1); + rcar_du_crtc_write(rcrtc, VDSR, mode->crtc_vtotal - + mode->crtc_vsync_end - 2); + rcar_du_crtc_write(rcrtc, VDER, mode->crtc_vtotal - + mode->crtc_vsync_end + + mode->crtc_vdisplay - 2); + rcar_du_crtc_write(rcrtc, VSPR, mode->crtc_vtotal - + mode->crtc_vsync_end + + mode->crtc_vsync_start - 1); + rcar_du_crtc_write(rcrtc, VCR, mode->crtc_vtotal - 1); rcar_du_crtc_write(rcrtc, DESR, mode->htotal - mode->hsync_start); rcar_du_crtc_write(rcrtc, DEWR, mode->hdisplay); @@ -256,6 +259,7 @@ void rcar_du_crtc_update_planes(struct drm_crtc *crtc) static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc) { struct drm_crtc *crtc = &rcrtc->crtc; + bool interlaced; unsigned int i; if (rcrtc->started) @@ -291,7 +295,10 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc) * sync mode (with the HSYNC and VSYNC signals configured as outputs and * actively driven). */ - rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK, DSYSR_TVM_MASTER); + interlaced = rcrtc->crtc.mode.flags & DRM_MODE_FLAG_INTERLACE; + rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK | DSYSR_SCM_MASK, + (interlaced ? DSYSR_SCM_INT_VIDEO : 0) | + DSYSR_TVM_MASTER); rcar_du_group_start_stop(rcrtc->group, true); @@ -528,7 +535,7 @@ static irqreturn_t rcar_du_crtc_irq(int irq, void *arg) status = rcar_du_crtc_read(rcrtc, DSSR); rcar_du_crtc_write(rcrtc, DSRCR, status & DSRCR_MASK); - if (status & DSSR_VBK) { + if (status & DSSR_FRM) { drm_handle_vblank(rcrtc->crtc.dev, rcrtc->index); rcar_du_crtc_finish_page_flip(rcrtc); ret = IRQ_HANDLED; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c index 322b7208171ab1..ca94b029ac80ca 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c @@ -95,6 +95,7 @@ int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu, connector = &rcon->connector; connector->display_info.width_mm = 0; connector->display_info.height_mm = 0; + connector->interlace_allowed = true; connector->polled = DRM_CONNECTOR_POLL_HPD; ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs, diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index fb3ea4f95d4aa2..50f2f2b20d39fc 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c @@ -104,14 +104,22 @@ void rcar_du_plane_update_base(struct rcar_du_plane *plane) { struct rcar_du_group *rgrp = plane->group; unsigned int index = plane->hwindex; + bool interlaced; u32 mwr; - /* Memory pitch (expressed in pixels) */ + interlaced = plane->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE; + + /* Memory pitch (expressed in pixels). Must be doubled for interlaced + * operation with 32bpp formats. + */ if (plane->format->planes == 2) mwr = plane->pitch; else mwr = plane->pitch * 8 / plane->format->bpp; + if (interlaced && plane->format->bpp == 32) + mwr *= 2; + rcar_du_plane_write(rgrp, index, PnMWR, mwr); /* The Y position is expressed in raster line units and must be doubled @@ -119,12 +127,16 @@ void rcar_du_plane_update_base(struct rcar_du_plane *plane) * doubling the Y position is found in the R8A7779 datasheet, but the * rule seems to apply there as well. * + * Despite not being documented, doubling seem not to be needed when + * operating in interlaced mode. + * * Similarly, for the second plane, NV12 and NV21 formats seem to - * require a halved Y position value. + * require a halved Y position value, in both progressive and interlaced + * modes. */ rcar_du_plane_write(rgrp, index, PnSPXR, plane->src_x); rcar_du_plane_write(rgrp, index, PnSPYR, plane->src_y * - (plane->format->bpp == 32 ? 2 : 1)); + (!interlaced && plane->format->bpp == 32 ? 2 : 1)); rcar_du_plane_write(rgrp, index, PnDSA0R, plane->dma[0]); if (plane->format->planes == 2) { diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h index c3639d1db28b86..70fcbc471ebdc8 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h @@ -34,6 +34,7 @@ #define DSYSR_SCM_INT_NONE (0 << 4) #define DSYSR_SCM_INT_SYNC (2 << 4) #define DSYSR_SCM_INT_VIDEO (3 << 4) +#define DSYSR_SCM_MASK (3 << 4) #define DSMR 0x00004 #define DSMR_VSPM (1 << 28) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c index 752747a5e920e8..9d4879921cc7a9 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c @@ -64,6 +64,7 @@ int rcar_du_vga_connector_init(struct rcar_du_device *rcdu, connector = &rcon->connector; connector->display_info.width_mm = 0; connector->display_info.height_mm = 0; + connector->interlace_allowed = true; ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs, DRM_MODE_CONNECTOR_VGA); From f421258d5bf883b68b1cdaa299a8a1da3eb92e0f Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 21 Dec 2014 22:53:58 +0200 Subject: [PATCH 0327/3023] MIPS: OCTEON: add crypto helper functions Add crypto helper functions which are needed for kernel level usage. The code for these has been extracted from the EdgeRouter Pro GPL tarball. While at it, also delete duplicate definitions of the functions. Signed-off-by: Aaro Koskinen Signed-off-by: Herbert Xu --- arch/mips/cavium-octeon/Makefile | 1 + arch/mips/cavium-octeon/crypto/Makefile | 5 ++ .../mips/cavium-octeon/crypto/octeon-crypto.c | 66 +++++++++++++++++++ .../mips/cavium-octeon/crypto/octeon-crypto.h | 17 +++++ arch/mips/include/asm/octeon/octeon.h | 5 -- 5 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 arch/mips/cavium-octeon/crypto/Makefile create mode 100644 arch/mips/cavium-octeon/crypto/octeon-crypto.c create mode 100644 arch/mips/cavium-octeon/crypto/octeon-crypto.h diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile index 42f5f1a4b40a4c..69a8a8dabc2b21 100644 --- a/arch/mips/cavium-octeon/Makefile +++ b/arch/mips/cavium-octeon/Makefile @@ -16,6 +16,7 @@ obj-y := cpu.o setup.o octeon-platform.o octeon-irq.o csrc-octeon.o obj-y += dma-octeon.o obj-y += octeon-memcpy.o obj-y += executive/ +obj-y += crypto/ obj-$(CONFIG_MTD) += flash_setup.o obj-$(CONFIG_SMP) += smp.o diff --git a/arch/mips/cavium-octeon/crypto/Makefile b/arch/mips/cavium-octeon/crypto/Makefile new file mode 100644 index 00000000000000..739b80366c25c5 --- /dev/null +++ b/arch/mips/cavium-octeon/crypto/Makefile @@ -0,0 +1,5 @@ +# +# OCTEON-specific crypto modules. +# + +obj-y += octeon-crypto.o diff --git a/arch/mips/cavium-octeon/crypto/octeon-crypto.c b/arch/mips/cavium-octeon/crypto/octeon-crypto.c new file mode 100644 index 00000000000000..7c82ff463b65be --- /dev/null +++ b/arch/mips/cavium-octeon/crypto/octeon-crypto.c @@ -0,0 +1,66 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2004-2012 Cavium Networks + */ + +#include +#include +#include + +#include "octeon-crypto.h" + +/** + * Enable access to Octeon's COP2 crypto hardware for kernel use. Wrap any + * crypto operations in calls to octeon_crypto_enable/disable in order to make + * sure the state of COP2 isn't corrupted if userspace is also performing + * hardware crypto operations. Allocate the state parameter on the stack. + * Preemption must be disabled to prevent context switches. + * + * @state: Pointer to state structure to store current COP2 state in. + * + * Returns: Flags to be passed to octeon_crypto_disable() + */ +unsigned long octeon_crypto_enable(struct octeon_cop2_state *state) +{ + int status; + unsigned long flags; + + local_irq_save(flags); + status = read_c0_status(); + write_c0_status(status | ST0_CU2); + if (KSTK_STATUS(current) & ST0_CU2) { + octeon_cop2_save(&(current->thread.cp2)); + KSTK_STATUS(current) &= ~ST0_CU2; + status &= ~ST0_CU2; + } else if (status & ST0_CU2) { + octeon_cop2_save(state); + } + local_irq_restore(flags); + return status & ST0_CU2; +} +EXPORT_SYMBOL_GPL(octeon_crypto_enable); + +/** + * Disable access to Octeon's COP2 crypto hardware in the kernel. This must be + * called after an octeon_crypto_enable() before any context switch or return to + * userspace. + * + * @state: Pointer to COP2 state to restore + * @flags: Return value from octeon_crypto_enable() + */ +void octeon_crypto_disable(struct octeon_cop2_state *state, + unsigned long crypto_flags) +{ + unsigned long flags; + + local_irq_save(flags); + if (crypto_flags & ST0_CU2) + octeon_cop2_restore(state); + else + write_c0_status(read_c0_status() & ~ST0_CU2); + local_irq_restore(flags); +} +EXPORT_SYMBOL_GPL(octeon_crypto_disable); diff --git a/arch/mips/cavium-octeon/crypto/octeon-crypto.h b/arch/mips/cavium-octeon/crypto/octeon-crypto.h new file mode 100644 index 00000000000000..5ca86d4ead5268 --- /dev/null +++ b/arch/mips/cavium-octeon/crypto/octeon-crypto.h @@ -0,0 +1,17 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2012-2013 Cavium Inc., All Rights Reserved. + */ +#ifndef __LINUX_OCTEON_CRYPTO_H +#define __LINUX_OCTEON_CRYPTO_H + +#include + +extern unsigned long octeon_crypto_enable(struct octeon_cop2_state *state); +extern void octeon_crypto_disable(struct octeon_cop2_state *state, + unsigned long flags); + +#endif /* __LINUX_OCTEON_CRYPTO_H */ diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h index d781f9e6688443..6dfefd2d5cdfd7 100644 --- a/arch/mips/include/asm/octeon/octeon.h +++ b/arch/mips/include/asm/octeon/octeon.h @@ -44,11 +44,6 @@ extern int octeon_get_boot_num_arguments(void); extern const char *octeon_get_boot_argument(int arg); extern void octeon_hal_setup_reserved32(void); extern void octeon_user_io_init(void); -struct octeon_cop2_state; -extern unsigned long octeon_crypto_enable(struct octeon_cop2_state *state); -extern void octeon_crypto_disable(struct octeon_cop2_state *state, - unsigned long flags); -extern asmlinkage void octeon_cop2_restore(struct octeon_cop2_state *task); extern void octeon_init_cvmcount(void); extern void octeon_setup_delays(void); From 1e585ef51c3fdcf296d2ce5cb8c9e74b1a36cfb4 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 21 Dec 2014 22:53:59 +0200 Subject: [PATCH 0328/3023] crypto: octeon - add instruction definitions for MD5 Add instruction definitions for MD5. Based on information extracted from EdgeRouter Pro GPL source tarball. Signed-off-by: Aaro Koskinen Signed-off-by: Herbert Xu --- .../mips/cavium-octeon/crypto/octeon-crypto.h | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/arch/mips/cavium-octeon/crypto/octeon-crypto.h b/arch/mips/cavium-octeon/crypto/octeon-crypto.h index 5ca86d4ead5268..3f65bc6ccb839d 100644 --- a/arch/mips/cavium-octeon/crypto/octeon-crypto.h +++ b/arch/mips/cavium-octeon/crypto/octeon-crypto.h @@ -4,14 +4,70 @@ * for more details. * * Copyright (C) 2012-2013 Cavium Inc., All Rights Reserved. + * + * MD5 instruction definitions added by Aaro Koskinen . + * */ #ifndef __LINUX_OCTEON_CRYPTO_H #define __LINUX_OCTEON_CRYPTO_H #include +#include extern unsigned long octeon_crypto_enable(struct octeon_cop2_state *state); extern void octeon_crypto_disable(struct octeon_cop2_state *state, unsigned long flags); +/* + * Macros needed to implement MD5: + */ + +/* + * The index can be 0-1. + */ +#define write_octeon_64bit_hash_dword(value, index) \ +do { \ + __asm__ __volatile__ ( \ + "dmtc2 %[rt],0x0048+" STR(index) \ + : \ + : [rt] "d" (value)); \ +} while (0) + +/* + * The index can be 0-1. + */ +#define read_octeon_64bit_hash_dword(index) \ +({ \ + u64 __value; \ + \ + __asm__ __volatile__ ( \ + "dmfc2 %[rt],0x0048+" STR(index) \ + : [rt] "=d" (__value) \ + : ); \ + \ + __value; \ +}) + +/* + * The index can be 0-6. + */ +#define write_octeon_64bit_block_dword(value, index) \ +do { \ + __asm__ __volatile__ ( \ + "dmtc2 %[rt],0x0040+" STR(index) \ + : \ + : [rt] "d" (value)); \ +} while (0) + +/* + * The value is the final block dword (64-bit). + */ +#define octeon_md5_start(value) \ +do { \ + __asm__ __volatile__ ( \ + "dmtc2 %[rt],0x4047" \ + : \ + : [rt] "d" (value)); \ +} while (0) + #endif /* __LINUX_OCTEON_CRYPTO_H */ From 011f3c6cbb97859860e451f2a75767cd4c1ffc03 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 21 Dec 2014 22:54:00 +0200 Subject: [PATCH 0329/3023] MIPS: OCTEON: reintroduce crypto features check Reintroduce run-time check for crypto features. The old one was deleted because it was unreliable, now decide the crypto availability on early boot when the model string is constructed. Signed-off-by: Aaro Koskinen Signed-off-by: Herbert Xu --- .../mips/cavium-octeon/executive/octeon-model.c | 6 ++++++ arch/mips/include/asm/octeon/octeon-feature.h | 17 +++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/arch/mips/cavium-octeon/executive/octeon-model.c b/arch/mips/cavium-octeon/executive/octeon-model.c index e15b049b3bd710..b2104bd9ab3b7e 100644 --- a/arch/mips/cavium-octeon/executive/octeon-model.c +++ b/arch/mips/cavium-octeon/executive/octeon-model.c @@ -27,6 +27,9 @@ #include +enum octeon_feature_bits __octeon_feature_bits __read_mostly; +EXPORT_SYMBOL_GPL(__octeon_feature_bits); + /** * Read a byte of fuse data * @byte_addr: address to read @@ -103,6 +106,9 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id, else suffix = "NSP"; + if (!fus_dat2.s.nocrypto) + __octeon_feature_bits |= OCTEON_HAS_CRYPTO; + /* * Assume pass number is encoded using <5:3><2:0>. Exceptions * will be fixed later. diff --git a/arch/mips/include/asm/octeon/octeon-feature.h b/arch/mips/include/asm/octeon/octeon-feature.h index c4fe81f47f5367..8ebd3f579b848e 100644 --- a/arch/mips/include/asm/octeon/octeon-feature.h +++ b/arch/mips/include/asm/octeon/octeon-feature.h @@ -46,8 +46,6 @@ enum octeon_feature { OCTEON_FEATURE_SAAD, /* Does this Octeon support the ZIP offload engine? */ OCTEON_FEATURE_ZIP, - /* Does this Octeon support crypto acceleration using COP2? */ - OCTEON_FEATURE_CRYPTO, OCTEON_FEATURE_DORM_CRYPTO, /* Does this Octeon support PCI express? */ OCTEON_FEATURE_PCIE, @@ -86,6 +84,21 @@ enum octeon_feature { OCTEON_MAX_FEATURE }; +enum octeon_feature_bits { + OCTEON_HAS_CRYPTO = 0x0001, /* Crypto acceleration using COP2 */ +}; +extern enum octeon_feature_bits __octeon_feature_bits; + +/** + * octeon_has_crypto() - Check if this OCTEON has crypto acceleration support. + * + * Returns: Non-zero if the feature exists. Zero if the feature does not exist. + */ +static inline int octeon_has_crypto(void) +{ + return __octeon_feature_bits & OCTEON_HAS_CRYPTO; +} + /** * Determine if the current Octeon supports a specific feature. These * checks have been optimized to be fairly quick, but they should still From 1953c22f53747035b28c36dbb337ac3c10902644 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 21 Dec 2014 22:54:01 +0200 Subject: [PATCH 0330/3023] crypto: octeon - add MD5 module Add OCTEON MD5 module. Signed-off-by: Aaro Koskinen Signed-off-by: Herbert Xu --- arch/mips/cavium-octeon/crypto/Makefile | 2 + .../mips/cavium-octeon/crypto/octeon-crypto.h | 2 + arch/mips/cavium-octeon/crypto/octeon-md5.c | 216 ++++++++++++++++++ 3 files changed, 220 insertions(+) create mode 100644 arch/mips/cavium-octeon/crypto/octeon-md5.c diff --git a/arch/mips/cavium-octeon/crypto/Makefile b/arch/mips/cavium-octeon/crypto/Makefile index 739b80366c25c5..a74f76d85a2f1c 100644 --- a/arch/mips/cavium-octeon/crypto/Makefile +++ b/arch/mips/cavium-octeon/crypto/Makefile @@ -3,3 +3,5 @@ # obj-y += octeon-crypto.o + +obj-$(CONFIG_CRYPTO_MD5_OCTEON) += octeon-md5.o diff --git a/arch/mips/cavium-octeon/crypto/octeon-crypto.h b/arch/mips/cavium-octeon/crypto/octeon-crypto.h index 3f65bc6ccb839d..e2a4aece9c24a3 100644 --- a/arch/mips/cavium-octeon/crypto/octeon-crypto.h +++ b/arch/mips/cavium-octeon/crypto/octeon-crypto.h @@ -14,6 +14,8 @@ #include #include +#define OCTEON_CR_OPCODE_PRIORITY 300 + extern unsigned long octeon_crypto_enable(struct octeon_cop2_state *state); extern void octeon_crypto_disable(struct octeon_cop2_state *state, unsigned long flags); diff --git a/arch/mips/cavium-octeon/crypto/octeon-md5.c b/arch/mips/cavium-octeon/crypto/octeon-md5.c new file mode 100644 index 00000000000000..b909881ba6c141 --- /dev/null +++ b/arch/mips/cavium-octeon/crypto/octeon-md5.c @@ -0,0 +1,216 @@ +/* + * Cryptographic API. + * + * MD5 Message Digest Algorithm (RFC1321). + * + * Adapted for OCTEON by Aaro Koskinen . + * + * Based on crypto/md5.c, which is: + * + * Derived from cryptoapi implementation, originally based on the + * public domain implementation written by Colin Plumb in 1993. + * + * Copyright (c) Cryptoapi developers. + * Copyright (c) 2002 James Morris + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "octeon-crypto.h" + +/* + * We pass everything as 64-bit. OCTEON can handle misaligned data. + */ + +static void octeon_md5_store_hash(struct md5_state *ctx) +{ + u64 *hash = (u64 *)ctx->hash; + + write_octeon_64bit_hash_dword(hash[0], 0); + write_octeon_64bit_hash_dword(hash[1], 1); +} + +static void octeon_md5_read_hash(struct md5_state *ctx) +{ + u64 *hash = (u64 *)ctx->hash; + + hash[0] = read_octeon_64bit_hash_dword(0); + hash[1] = read_octeon_64bit_hash_dword(1); +} + +static void octeon_md5_transform(const void *_block) +{ + const u64 *block = _block; + + write_octeon_64bit_block_dword(block[0], 0); + write_octeon_64bit_block_dword(block[1], 1); + write_octeon_64bit_block_dword(block[2], 2); + write_octeon_64bit_block_dword(block[3], 3); + write_octeon_64bit_block_dword(block[4], 4); + write_octeon_64bit_block_dword(block[5], 5); + write_octeon_64bit_block_dword(block[6], 6); + octeon_md5_start(block[7]); +} + +static int octeon_md5_init(struct shash_desc *desc) +{ + struct md5_state *mctx = shash_desc_ctx(desc); + + mctx->hash[0] = cpu_to_le32(0x67452301); + mctx->hash[1] = cpu_to_le32(0xefcdab89); + mctx->hash[2] = cpu_to_le32(0x98badcfe); + mctx->hash[3] = cpu_to_le32(0x10325476); + mctx->byte_count = 0; + + return 0; +} + +static int octeon_md5_update(struct shash_desc *desc, const u8 *data, + unsigned int len) +{ + struct md5_state *mctx = shash_desc_ctx(desc); + const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f); + struct octeon_cop2_state state; + unsigned long flags; + + mctx->byte_count += len; + + if (avail > len) { + memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), + data, len); + return 0; + } + + memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), data, + avail); + + local_bh_disable(); + preempt_disable(); + flags = octeon_crypto_enable(&state); + octeon_md5_store_hash(mctx); + + octeon_md5_transform(mctx->block); + data += avail; + len -= avail; + + while (len >= sizeof(mctx->block)) { + octeon_md5_transform(data); + data += sizeof(mctx->block); + len -= sizeof(mctx->block); + } + + octeon_md5_read_hash(mctx); + octeon_crypto_disable(&state, flags); + preempt_enable(); + local_bh_enable(); + + memcpy(mctx->block, data, len); + + return 0; +} + +static int octeon_md5_final(struct shash_desc *desc, u8 *out) +{ + struct md5_state *mctx = shash_desc_ctx(desc); + const unsigned int offset = mctx->byte_count & 0x3f; + char *p = (char *)mctx->block + offset; + int padding = 56 - (offset + 1); + struct octeon_cop2_state state; + unsigned long flags; + + *p++ = 0x80; + + local_bh_disable(); + preempt_disable(); + flags = octeon_crypto_enable(&state); + octeon_md5_store_hash(mctx); + + if (padding < 0) { + memset(p, 0x00, padding + sizeof(u64)); + octeon_md5_transform(mctx->block); + p = (char *)mctx->block; + padding = 56; + } + + memset(p, 0, padding); + mctx->block[14] = cpu_to_le32(mctx->byte_count << 3); + mctx->block[15] = cpu_to_le32(mctx->byte_count >> 29); + octeon_md5_transform(mctx->block); + + octeon_md5_read_hash(mctx); + octeon_crypto_disable(&state, flags); + preempt_enable(); + local_bh_enable(); + + memcpy(out, mctx->hash, sizeof(mctx->hash)); + memset(mctx, 0, sizeof(*mctx)); + + return 0; +} + +static int octeon_md5_export(struct shash_desc *desc, void *out) +{ + struct md5_state *ctx = shash_desc_ctx(desc); + + memcpy(out, ctx, sizeof(*ctx)); + return 0; +} + +static int octeon_md5_import(struct shash_desc *desc, const void *in) +{ + struct md5_state *ctx = shash_desc_ctx(desc); + + memcpy(ctx, in, sizeof(*ctx)); + return 0; +} + +static struct shash_alg alg = { + .digestsize = MD5_DIGEST_SIZE, + .init = octeon_md5_init, + .update = octeon_md5_update, + .final = octeon_md5_final, + .export = octeon_md5_export, + .import = octeon_md5_import, + .descsize = sizeof(struct md5_state), + .statesize = sizeof(struct md5_state), + .base = { + .cra_name = "md5", + .cra_driver_name= "octeon-md5", + .cra_priority = OCTEON_CR_OPCODE_PRIORITY, + .cra_flags = CRYPTO_ALG_TYPE_SHASH, + .cra_blocksize = MD5_HMAC_BLOCK_SIZE, + .cra_module = THIS_MODULE, + } +}; + +static int __init md5_mod_init(void) +{ + if (!octeon_has_crypto()) + return -ENOTSUPP; + return crypto_register_shash(&alg); +} + +static void __exit md5_mod_fini(void) +{ + crypto_unregister_shash(&alg); +} + +module_init(md5_mod_init); +module_exit(md5_mod_fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MD5 Message Digest Algorithm (OCTEON)"); +MODULE_AUTHOR("Aaro Koskinen "); From d69e75deff2377b46b2b357ac3781cc93cd7ffd6 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 21 Dec 2014 22:54:02 +0200 Subject: [PATCH 0331/3023] crypto: octeon - enable OCTEON MD5 module selection Enable user to select OCTEON MD5 module. Signed-off-by: Aaro Koskinen Signed-off-by: Herbert Xu --- crypto/Kconfig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crypto/Kconfig b/crypto/Kconfig index 87bbc9c1e681cb..1618468b1fcbee 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -427,6 +427,15 @@ config CRYPTO_MD5 help MD5 message digest algorithm (RFC1321). +config CRYPTO_MD5_OCTEON + tristate "MD5 digest algorithm (OCTEON)" + depends on CPU_CAVIUM_OCTEON + select CRYPTO_MD5 + select CRYPTO_HASH + help + MD5 message digest algorithm (RFC1321) implemented + using OCTEON crypto instructions, when available. + config CRYPTO_MD5_SPARC64 tristate "MD5 digest algorithm (SPARC64)" depends on SPARC64 From 77584ee57434813b50fc85cde995a6271a5081b7 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 23 Dec 2014 16:40:17 +1100 Subject: [PATCH 0332/3023] hwrng: core - Use struct completion for cleanup_done There is no point in doing a manual completion for cleanup_done when struct completion fits in perfectly. Signed-off-by: Herbert Xu --- drivers/char/hw_random/core.c | 12 +++--------- include/linux/hw_random.h | 3 ++- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 6ec42252e46eb9..3dba2cf50241d8 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -60,7 +60,6 @@ static DEFINE_MUTEX(rng_mutex); static DEFINE_MUTEX(reading_mutex); static int data_avail; static u8 *rng_buffer, *rng_fillbuf; -static DECLARE_WAIT_QUEUE_HEAD(rng_done); static unsigned short current_quality; static unsigned short default_quality; /* = 0; default to "off" */ @@ -100,10 +99,7 @@ static inline void cleanup_rng(struct kref *kref) if (rng->cleanup) rng->cleanup(rng); - /* cleanup_done should be updated after cleanup finishes */ - smp_wmb(); - rng->cleanup_done = true; - wake_up_all(&rng_done); + complete(&rng->cleanup_done); } static void set_current_rng(struct hwrng *rng) @@ -498,7 +494,7 @@ int hwrng_register(struct hwrng *rng) add_early_randomness(rng); } - rng->cleanup_done = false; + init_completion(&rng->cleanup_done); out_unlock: mutex_unlock(&rng_mutex); @@ -532,9 +528,7 @@ void hwrng_unregister(struct hwrng *rng) } else mutex_unlock(&rng_mutex); - /* Just in case rng is reading right now, wait. */ - wait_event(rng_done, rng->cleanup_done && - atomic_read(&rng->ref.refcount) == 0); + wait_for_completion(&rng->cleanup_done); } EXPORT_SYMBOL_GPL(hwrng_unregister); diff --git a/include/linux/hw_random.h b/include/linux/hw_random.h index 7832e5008959e6..eb7b414d232bed 100644 --- a/include/linux/hw_random.h +++ b/include/linux/hw_random.h @@ -12,6 +12,7 @@ #ifndef LINUX_HWRANDOM_H_ #define LINUX_HWRANDOM_H_ +#include #include #include #include @@ -46,7 +47,7 @@ struct hwrng { /* internal. */ struct list_head list; struct kref ref; - bool cleanup_done; + struct completion cleanup_done; }; /** Register a new Hardware Random Number Generator driver. */ From 15b66cd54291186011f733cc750263f320b8a0a4 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 23 Dec 2014 16:40:18 +1100 Subject: [PATCH 0333/3023] hwrng: core - Fix current_rng init/cleanup race yet again The kref solution is still buggy because we were only focusing on the register/unregister race. The same race affects the setting of current_rng through sysfs. This patch fixes it by using kref_get_unless_zero. Signed-off-by: Herbert Xu --- drivers/char/hw_random/core.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 3dba2cf50241d8..42827fd5f38dc9 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -105,7 +105,6 @@ static inline void cleanup_rng(struct kref *kref) static void set_current_rng(struct hwrng *rng) { BUG_ON(!mutex_is_locked(&rng_mutex)); - kref_get(&rng->ref); current_rng = rng; } @@ -150,6 +149,9 @@ static void put_rng(struct hwrng *rng) static inline int hwrng_init(struct hwrng *rng) { + if (kref_get_unless_zero(&rng->ref)) + goto skip_init; + if (rng->init) { int ret; @@ -157,6 +159,11 @@ static inline int hwrng_init(struct hwrng *rng) if (ret) return ret; } + + kref_init(&rng->ref); + reinit_completion(&rng->cleanup_done); + +skip_init: add_early_randomness(rng); current_quality = rng->quality ? : default_quality; @@ -467,6 +474,9 @@ int hwrng_register(struct hwrng *rng) goto out_unlock; } + init_completion(&rng->cleanup_done); + complete(&rng->cleanup_done); + old_rng = current_rng; err = 0; if (!old_rng) { @@ -494,8 +504,6 @@ int hwrng_register(struct hwrng *rng) add_early_randomness(rng); } - init_completion(&rng->cleanup_done); - out_unlock: mutex_unlock(&rng_mutex); out: From ac3a497f13e42a99ed6fe188ebf2dcc39eb7ac20 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 23 Dec 2014 16:40:19 +1100 Subject: [PATCH 0334/3023] hwrng: core - Do not register device opportunistically Currently we only register the device when a valid RNG is added. However the way it's done is buggy because we test whether there is a current RNG to determine whether we need to register. As the current RNG may be missing due to a reinitialisation error this can lead to a reregistration of the device. As the device already has to handle a NULL current RNG anyway, let's just register the device always and remove the complexity. Signed-off-by: Herbert Xu --- drivers/char/hw_random/core.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 42827fd5f38dc9..1d342f0cb0c1b6 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -372,14 +372,14 @@ static DEVICE_ATTR(rng_available, S_IRUGO, NULL); -static void unregister_miscdev(void) +static void __exit unregister_miscdev(void) { device_remove_file(rng_miscdev.this_device, &dev_attr_rng_available); device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current); misc_deregister(&rng_miscdev); } -static int register_miscdev(void) +static int __init register_miscdev(void) { int err; @@ -484,12 +484,6 @@ int hwrng_register(struct hwrng *rng) if (err) goto out_unlock; set_current_rng(rng); - - err = register_miscdev(); - if (err) { - drop_current_rng(); - goto out_unlock; - } } list_add_tail(&rng->list, &rng_list); @@ -530,7 +524,6 @@ void hwrng_unregister(struct hwrng *rng) if (list_empty(&rng_list)) { mutex_unlock(&rng_mutex); - unregister_miscdev(); if (hwrng_fill) kthread_stop(hwrng_fill); } else @@ -540,16 +533,24 @@ void hwrng_unregister(struct hwrng *rng) } EXPORT_SYMBOL_GPL(hwrng_unregister); -static void __exit hwrng_exit(void) +static int __init hwrng_modinit(void) +{ + return register_miscdev(); +} + +static void __exit hwrng_modexit(void) { mutex_lock(&rng_mutex); BUG_ON(current_rng); kfree(rng_buffer); kfree(rng_fillbuf); mutex_unlock(&rng_mutex); + + unregister_miscdev(); } -module_exit(hwrng_exit); +module_init(hwrng_modinit); +module_exit(hwrng_modexit); MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver"); MODULE_LICENSE("GPL"); From ff77c150f71b761dcf29b9d1947df3165d2dc83e Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 23 Dec 2014 16:40:21 +1100 Subject: [PATCH 0335/3023] hwrng: core - Drop current rng in set_current_rng Rather than having callers of set_current_rng call drop_current_rng, we can do it directly in set_current_rng. Signed-off-by: Herbert Xu --- drivers/char/hw_random/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 1d342f0cb0c1b6..787ef42a77b942 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -70,6 +70,7 @@ module_param(default_quality, ushort, 0644); MODULE_PARM_DESC(default_quality, "default entropy content of hwrng per mill"); +static void drop_current_rng(void); static void start_khwrngd(void); static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size, @@ -105,6 +106,7 @@ static inline void cleanup_rng(struct kref *kref) static void set_current_rng(struct hwrng *rng) { BUG_ON(!mutex_is_locked(&rng_mutex)); + drop_current_rng(); current_rng = rng; } @@ -315,7 +317,6 @@ static ssize_t hwrng_attr_current_store(struct device *dev, err = hwrng_init(rng); if (err) break; - drop_current_rng(); set_current_rng(rng); err = 0; break; From 90ac41bd40ad0571a10826eb26d53c84bd791f29 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 23 Dec 2014 16:40:22 +1100 Subject: [PATCH 0336/3023] hwrng: core - Move hwrng_init call into set_current_rng We always do hwrng_init in set_current_rng. In fact, our current reference count system relies on this. So make this explicit by moving hwrng_init into set_current_rng. Signed-off-by: Herbert Xu --- drivers/char/hw_random/core.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 787ef42a77b942..32a8a867f7f808 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -71,6 +71,7 @@ MODULE_PARM_DESC(default_quality, "default entropy content of hwrng per mill"); static void drop_current_rng(void); +static int hwrng_init(struct hwrng *rng); static void start_khwrngd(void); static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size, @@ -103,11 +104,20 @@ static inline void cleanup_rng(struct kref *kref) complete(&rng->cleanup_done); } -static void set_current_rng(struct hwrng *rng) +static int set_current_rng(struct hwrng *rng) { + int err; + BUG_ON(!mutex_is_locked(&rng_mutex)); + + err = hwrng_init(rng); + if (err) + return err; + drop_current_rng(); current_rng = rng; + + return 0; } static void drop_current_rng(void) @@ -149,7 +159,7 @@ static void put_rng(struct hwrng *rng) mutex_unlock(&rng_mutex); } -static inline int hwrng_init(struct hwrng *rng) +static int hwrng_init(struct hwrng *rng) { if (kref_get_unless_zero(&rng->ref)) goto skip_init; @@ -310,15 +320,9 @@ static ssize_t hwrng_attr_current_store(struct device *dev, err = -ENODEV; list_for_each_entry(rng, &rng_list, list) { if (strcmp(rng->name, buf) == 0) { - if (rng == current_rng) { - err = 0; - break; - } - err = hwrng_init(rng); - if (err) - break; - set_current_rng(rng); err = 0; + if (rng != current_rng) + err = set_current_rng(rng); break; } } @@ -481,10 +485,9 @@ int hwrng_register(struct hwrng *rng) old_rng = current_rng; err = 0; if (!old_rng) { - err = hwrng_init(rng); + err = set_current_rng(rng); if (err) goto out_unlock; - set_current_rng(rng); } list_add_tail(&rng->list, &rng_list); @@ -518,8 +521,7 @@ void hwrng_unregister(struct hwrng *rng) tail = list_entry(rng_list.prev, struct hwrng, list); - if (hwrng_init(tail) == 0) - set_current_rng(tail); + set_current_rng(tail); } } From ad202c8c1563da4dda9416ca0ea1e0b94430f759 Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Tue, 23 Dec 2014 09:34:03 +0100 Subject: [PATCH 0337/3023] crypto: af_alg - zeroize key data alg_setkey should zeroize the sensitive data after use. Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/af_alg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/af_alg.c b/crypto/af_alg.c index a8ff3c44e13ca6..76d739d0821189 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -188,7 +188,7 @@ static int alg_setkey(struct sock *sk, char __user *ukey, err = type->setkey(ask->private, key, keylen); out: - sock_kfree_s(sk, key, keylen); + sock_kzfree_s(sk, key, keylen); return err; } From d9d0ac96554c21e40fd56982bc7f8f4bc557f16a Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Tue, 16 Dec 2014 11:11:45 +0200 Subject: [PATCH 0338/3023] iio: frequency: Remove 'out of memory' message This patch fixes the following checkpatch.pl warning: WARNING: Possible unnecessary 'out of memory' message Signed-off-by: Roberta Dobrescu Acked-by: Lars-Peter Clausen Reviewed-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/frequency/adf4350.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index 63a25d9e120486..2b301eba1d768f 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c @@ -387,10 +387,8 @@ static struct adf4350_platform_data *adf4350_parse_dt(struct device *dev) int ret; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) { - dev_err(dev, "could not allocate memory for platform data\n"); + if (!pdata) return NULL; - } strncpy(&pdata->name[0], np->name, SPI_NAME_SIZE - 1); From 762c4da347109398bbcc7783b7ce2496664442ed Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Tue, 16 Dec 2014 11:11:46 +0200 Subject: [PATCH 0339/3023] iio: frequency: Remove unnecessary braces around single statement block This patch fixes the following checkpatch.pl warning: WARNING: braces {} are not necessary for single statement blocks Signed-off-by: Roberta Dobrescu Acked-by: Lars-Peter Clausen Reviewed-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/frequency/adf4350.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index 2b301eba1d768f..10a0dfc3b01fa8 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c @@ -611,9 +611,8 @@ static int adf4350_remove(struct spi_device *spi) if (st->clk) clk_disable_unprepare(st->clk); - if (!IS_ERR(reg)) { + if (!IS_ERR(reg)) regulator_disable(reg); - } return 0; } From 44cf3798a3de3ebd8e5abe6c7fd5ee5c09b049de Mon Sep 17 00:00:00 2001 From: Hartmut Knaack Date: Fri, 19 Dec 2014 23:59:25 +0100 Subject: [PATCH 0340/3023] iio:pressure:bmp280: cleanup The calculations for temperature and pressure compensation were already slightly optimized in comparison to the datasheet. So, it makes sense to optimize even a bit more, making proper use of C operators: - variable t in bmp280_compensate_temp() can be eliminated by directly returning the result of the relevant equation. - make use of the += operator and eliminate an unnecessary parenthesis level in bmp280_compensate_press(). When the initialization of the ctrl_meas register fails, the error message will now mention the right register name. During probe, i2c_set_clientdata() is called, although it is not necessary. Drop it. Signed-off-by: Hartmut Knaack Reviewed-by: Vlad Dogaru Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/bmp280.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/iio/pressure/bmp280.c b/drivers/iio/pressure/bmp280.c index 47dfd347f66f88..7c623e2bd6336c 100644 --- a/drivers/iio/pressure/bmp280.c +++ b/drivers/iio/pressure/bmp280.c @@ -148,7 +148,7 @@ static s32 bmp280_compensate_temp(struct bmp280_data *data, s32 adc_temp) { int ret; - s32 var1, var2, t; + s32 var1, var2; __le16 buf[BMP280_COMP_TEMP_REG_COUNT / 2]; ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_TEMP_START, @@ -173,10 +173,7 @@ static s32 bmp280_compensate_temp(struct bmp280_data *data, ((adc_temp >> 4) - ((s32)le16_to_cpu(buf[T1])))) >> 12) * ((s32)(s16)le16_to_cpu(buf[T3]))) >> 14; - data->t_fine = var1 + var2; - t = (data->t_fine * 5 + 128) >> 8; - - return t; + return (data->t_fine * 5 + 128) >> 8; } /* @@ -203,8 +200,8 @@ static u32 bmp280_compensate_press(struct bmp280_data *data, var1 = ((s64)data->t_fine) - 128000; var2 = var1 * var1 * (s64)(s16)le16_to_cpu(buf[P6]); - var2 = var2 + ((var1 * (s64)(s16)le16_to_cpu(buf[P5])) << 17); - var2 = var2 + (((s64)(s16)le16_to_cpu(buf[P4])) << 35); + var2 += (var1 * (s64)(s16)le16_to_cpu(buf[P5])) << 17; + var2 += ((s64)(s16)le16_to_cpu(buf[P4])) << 35; var1 = ((var1 * var1 * (s64)(s16)le16_to_cpu(buf[P3])) >> 8) + ((var1 * (s64)(s16)le16_to_cpu(buf[P2])) << 12); var1 = ((((s64)1) << 47) + var1) * ((s64)le16_to_cpu(buf[P1])) >> 33; @@ -218,7 +215,7 @@ static u32 bmp280_compensate_press(struct bmp280_data *data, var2 = (((s64)(s16)le16_to_cpu(buf[P8])) * p) >> 19; p = ((p + var1 + var2) >> 8) + (((s64)(s16)le16_to_cpu(buf[P7])) << 4); - return (u32) p; + return (u32)p; } static int bmp280_read_temp(struct bmp280_data *data, @@ -330,7 +327,7 @@ static int bmp280_chip_init(struct bmp280_data *data) BMP280_MODE_NORMAL); if (ret < 0) { dev_err(&data->client->dev, - "failed to write config register\n"); + "failed to write ctrl_meas register\n"); return ret; } @@ -358,7 +355,6 @@ static int bmp280_probe(struct i2c_client *client, if (!indio_dev) return -ENOMEM; - i2c_set_clientdata(client, indio_dev); data = iio_priv(indio_dev); mutex_init(&data->lock); data->client = client; From 614e8842ddf5502f0e781f91695bfbc1e1e1d9b6 Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Mon, 15 Dec 2014 17:14:49 +0200 Subject: [PATCH 0341/3023] iio: ABI: add clarification for proximity Signed-off-by: Vlad Dogaru Acked-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index df5e69e6247c44..831db8623e4b71 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1068,7 +1068,9 @@ Description: reflectivity of infrared or ultrasound emitted. Often these sensors are unit less and as such conversion to SI units is not possible. Where it is, the units should - be meters. + be meters. If such a conversion is not possible, the reported + values should behave in the same way as a distance, i.e. lower + values indicate something is closer to the sensor. What: /sys/.../iio:deviceX/in_illuminanceY_input What: /sys/.../iio:deviceX/in_illuminanceY_raw From 7ab374a053a43050117eb452306b6cd9dcb58cfd Mon Sep 17 00:00:00 2001 From: Karol Wrona Date: Fri, 19 Dec 2014 18:39:24 +0100 Subject: [PATCH 0342/3023] iio: kfifo: Remove unused argument in iio_kfifo_allocate indio_dev was unused in function body plus some small style fix - add new lines after "if(sth) return sth" and before the last return statement. The argument was removed also in its client. Signed-off-by: Karol Wrona Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti_am335x_adc.c | 2 +- drivers/iio/industrialio-triggered-buffer.c | 2 +- drivers/iio/kfifo_buf.c | 6 ++++-- drivers/staging/iio/accel/lis3l02dq_ring.c | 2 +- drivers/staging/iio/iio_simple_dummy_buffer.c | 2 +- drivers/staging/iio/impedance-analyzer/ad5933.c | 2 +- drivers/staging/iio/meter/ade7758_ring.c | 2 +- include/linux/iio/kfifo_buf.h | 2 +- 8 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index d550ac7d23659a..5eea299518a3e8 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -250,7 +250,7 @@ static int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev, struct iio_buffer *buffer; int ret; - buffer = iio_kfifo_allocate(indio_dev); + buffer = iio_kfifo_allocate(); if (!buffer) return -ENOMEM; diff --git a/drivers/iio/industrialio-triggered-buffer.c b/drivers/iio/industrialio-triggered-buffer.c index 61a5d0404edf95..15a5341b5e7b30 100644 --- a/drivers/iio/industrialio-triggered-buffer.c +++ b/drivers/iio/industrialio-triggered-buffer.c @@ -49,7 +49,7 @@ int iio_triggered_buffer_setup(struct iio_dev *indio_dev, struct iio_buffer *buffer; int ret; - buffer = iio_kfifo_allocate(indio_dev); + buffer = iio_kfifo_allocate(); if (!buffer) { ret = -ENOMEM; goto error_ret; diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c index b20a9cfbc8edd8..7f6fad658e8331 100644 --- a/drivers/iio/kfifo_buf.c +++ b/drivers/iio/kfifo_buf.c @@ -140,18 +140,20 @@ static const struct iio_buffer_access_funcs kfifo_access_funcs = { .release = &iio_kfifo_buffer_release, }; -struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev) +struct iio_buffer *iio_kfifo_allocate(void) { struct iio_kfifo *kf; - kf = kzalloc(sizeof *kf, GFP_KERNEL); + kf = kzalloc(sizeof(*kf), GFP_KERNEL); if (!kf) return NULL; + kf->update_needed = true; iio_buffer_init(&kf->buffer); kf->buffer.access = &kfifo_access_funcs; kf->buffer.length = 2; mutex_init(&kf->user_lock); + return &kf->buffer; } EXPORT_SYMBOL(iio_kfifo_allocate); diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c index 9efc77b0ebdd4d..1fd90090a63358 100644 --- a/drivers/staging/iio/accel/lis3l02dq_ring.c +++ b/drivers/staging/iio/accel/lis3l02dq_ring.c @@ -393,7 +393,7 @@ int lis3l02dq_configure_buffer(struct iio_dev *indio_dev) int ret; struct iio_buffer *buffer; - buffer = iio_kfifo_allocate(indio_dev); + buffer = iio_kfifo_allocate(); if (!buffer) return -ENOMEM; diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c index a2d72c10211976..360a4c98072226 100644 --- a/drivers/staging/iio/iio_simple_dummy_buffer.c +++ b/drivers/staging/iio/iio_simple_dummy_buffer.c @@ -121,7 +121,7 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) struct iio_buffer *buffer; /* Allocate a buffer to use - here a kfifo */ - buffer = iio_kfifo_allocate(indio_dev); + buffer = iio_kfifo_allocate(); if (buffer == NULL) { ret = -ENOMEM; goto error_ret; diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index c50b1380b9aa3c..39f60aca083845 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -626,7 +626,7 @@ static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev) { struct iio_buffer *buffer; - buffer = iio_kfifo_allocate(indio_dev); + buffer = iio_kfifo_allocate(); if (!buffer) return -ENOMEM; diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c index 27c3ed6ca468d5..782fd9a3bc0d2c 100644 --- a/drivers/staging/iio/meter/ade7758_ring.c +++ b/drivers/staging/iio/meter/ade7758_ring.c @@ -119,7 +119,7 @@ int ade7758_configure_ring(struct iio_dev *indio_dev) struct iio_buffer *buffer; int ret = 0; - buffer = iio_kfifo_allocate(indio_dev); + buffer = iio_kfifo_allocate(); if (!buffer) { ret = -ENOMEM; return ret; diff --git a/include/linux/iio/kfifo_buf.h b/include/linux/iio/kfifo_buf.h index 25eeac762e849d..1a8d57a417387d 100644 --- a/include/linux/iio/kfifo_buf.h +++ b/include/linux/iio/kfifo_buf.h @@ -5,7 +5,7 @@ #include #include -struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev); +struct iio_buffer *iio_kfifo_allocate(void); void iio_kfifo_free(struct iio_buffer *r); #endif From 780103fef5c88a97fb9c8d0079bf326ed6147f1f Mon Sep 17 00:00:00 2001 From: Karol Wrona Date: Fri, 19 Dec 2014 18:39:25 +0100 Subject: [PATCH 0343/3023] iio: kfifo: Add resource management devm_iio_kfifo_allocate/free iio kfifo allocate/free gained their devm_ wrappers. Signed-off-by: Karol Wrona Suggested-by: Jonathan Cameron Signed-off-by: Jonathan Cameron --- Documentation/driver-model/devres.txt | 2 + drivers/iio/kfifo_buf.c | 54 +++++++++++++++++++++++++++ include/linux/iio/kfifo_buf.h | 3 ++ 3 files changed, 59 insertions(+) diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index b5ab416cd53a69..6d1e8eeb599036 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -258,6 +258,8 @@ IIO devm_iio_device_free() devm_iio_device_register() devm_iio_device_unregister() + devm_iio_kfifo_allocate() + devm_iio_kfifo_free() devm_iio_trigger_alloc() devm_iio_trigger_free() diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c index 7f6fad658e8331..b2beea01c49b3c 100644 --- a/drivers/iio/kfifo_buf.c +++ b/drivers/iio/kfifo_buf.c @@ -164,4 +164,58 @@ void iio_kfifo_free(struct iio_buffer *r) } EXPORT_SYMBOL(iio_kfifo_free); +static void devm_iio_kfifo_release(struct device *dev, void *res) +{ + iio_kfifo_free(*(struct iio_buffer **)res); +} + +static int devm_iio_kfifo_match(struct device *dev, void *res, void *data) +{ + struct iio_buffer **r = res; + + if (WARN_ON(!r || !*r)) + return 0; + + return *r == data; +} + +/** + * devm_iio_fifo_allocate - Resource-managed iio_kfifo_allocate() + * @dev: Device to allocate kfifo buffer for + * + * RETURNS: + * Pointer to allocated iio_buffer on success, NULL on failure. + */ +struct iio_buffer *devm_iio_kfifo_allocate(struct device *dev) +{ + struct iio_buffer **ptr, *r; + + ptr = devres_alloc(devm_iio_kfifo_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return NULL; + + r = iio_kfifo_allocate(); + if (r) { + *ptr = r; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return r; +} +EXPORT_SYMBOL(devm_iio_kfifo_allocate); + +/** + * devm_iio_fifo_free - Resource-managed iio_kfifo_free() + * @dev: Device the buffer belongs to + * @r: The buffer associated with the device + */ +void devm_iio_kfifo_free(struct device *dev, struct iio_buffer *r) +{ + WARN_ON(devres_release(dev, devm_iio_kfifo_release, + devm_iio_kfifo_match, r)); +} +EXPORT_SYMBOL(devm_iio_kfifo_free); + MODULE_LICENSE("GPL"); diff --git a/include/linux/iio/kfifo_buf.h b/include/linux/iio/kfifo_buf.h index 1a8d57a417387d..1683bc710d1476 100644 --- a/include/linux/iio/kfifo_buf.h +++ b/include/linux/iio/kfifo_buf.h @@ -8,4 +8,7 @@ struct iio_buffer *iio_kfifo_allocate(void); void iio_kfifo_free(struct iio_buffer *r); +struct iio_buffer *devm_iio_kfifo_allocate(struct device *dev); +void devm_iio_kfifo_free(struct device *dev, struct iio_buffer *r); + #endif From 20dd20f68f9b41534ba9ebddc4f179d0efbc3c8e Mon Sep 17 00:00:00 2001 From: Karol Wrona Date: Fri, 19 Dec 2014 18:39:26 +0100 Subject: [PATCH 0344/3023] iio: core: Get rid of misleading comment This comment did not fit here. It explains why devm_kmalloc uses dr_alloc. Generally is not needed at all. Signed-off-by: Karol Wrona Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index ee442ee482abd0..b7a39771705fc9 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -1043,7 +1043,6 @@ struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv) if (!ptr) return NULL; - /* use raw alloc_dr for kmalloc caller tracing */ iio_dev = iio_device_alloc(sizeof_priv); if (iio_dev) { *ptr = iio_dev; From 60347e71c0d1f001aab75cb2569729980e2d737a Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Mon, 15 Dec 2014 17:16:51 +0200 Subject: [PATCH 0345/3023] iio: mma9551: fix sparse warning sparse warnings: (new ones prefixed by >>) >> drivers/iio/accel/mma9551.c:554:57: sparse: mixing different enum types drivers/iio/accel/mma9551.c:554:57: int enum mma9551_tilt_axis versus drivers/iio/accel/mma9551.c:554:57: int enum mma9551_gpio_pin >> drivers/iio/accel/mma9551.c:576:57: sparse: mixing different enum types drivers/iio/accel/mma9551.c:576:57: int enum mma9551_tilt_axis versus drivers/iio/accel/mma9551.c:576:57: int enum mma9551_gpio_pin Signed-off-by: Vlad Dogaru Reported-by: kbuild test robot Reviewed-by: Irina Tirdea Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma9551.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c index 1be125bb916129..6563e267b8ae13 100644 --- a/drivers/iio/accel/mma9551.c +++ b/drivers/iio/accel/mma9551.c @@ -551,7 +551,8 @@ static int mma9551_config_incli_event(struct iio_dev *indio_dev, return 0; if (state == 0) { - ret = mma9551_gpio_config(data->client, mma_axis, + ret = mma9551_gpio_config(data->client, + (enum mma9551_gpio_pin)mma_axis, MMA9551_APPID_NONE, 0, 0); if (ret < 0) return ret; @@ -573,7 +574,8 @@ static int mma9551_config_incli_event(struct iio_dev *indio_dev, return -EINVAL; } - ret = mma9551_gpio_config(data->client, mma_axis, + ret = mma9551_gpio_config(data->client, + (enum mma9551_gpio_pin)mma_axis, MMA9551_APPID_TILT, bitnum, 0); if (ret < 0) return ret; From 450a5ff768b008817d7914e3d2db16400e571dff Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Tue, 16 Dec 2014 11:16:06 +0200 Subject: [PATCH 0346/3023] iio: trigger: Add a blank line after declarations This patch fixes the following checkpatch.pl warning: WARNING: Missing a blank line after declarations Signed-off-by: Roberta Dobrescu Reviewed-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/trigger/iio-trig-sysfs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iio/trigger/iio-trig-sysfs.c b/drivers/iio/trigger/iio-trig-sysfs.c index 254c7e906127f6..3dfab2bc6d6935 100644 --- a/drivers/iio/trigger/iio-trig-sysfs.c +++ b/drivers/iio/trigger/iio-trig-sysfs.c @@ -135,6 +135,7 @@ static int iio_sysfs_trigger_probe(int id) struct iio_sysfs_trig *t; int ret; bool foundit = false; + mutex_lock(&iio_sysfs_trig_list_mut); list_for_each_entry(t, &iio_sysfs_trig_list, l) if (id == t->id) { @@ -185,6 +186,7 @@ static int iio_sysfs_trigger_remove(int id) { bool foundit = false; struct iio_sysfs_trig *t; + mutex_lock(&iio_sysfs_trig_list_mut); list_for_each_entry(t, &iio_sysfs_trig_list, l) if (id == t->id) { From 6ed5ac50a3e0d21bc5423eea066913553c6c5320 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 15 Dec 2014 13:19:21 -0800 Subject: [PATCH 0347/3023] iio: imu: inv_mpu6050: ACPI enumeration Added changes so that the module can be enumerated via ACPI. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 6d2c115f39b4c6..f73e60b7a79611 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "inv_mpu_iio.h" /* @@ -875,6 +876,13 @@ static const struct i2c_device_id inv_mpu_id[] = { MODULE_DEVICE_TABLE(i2c, inv_mpu_id); +static const struct acpi_device_id inv_acpi_match[] = { + {"INVN6500", 0}, + { }, +}; + +MODULE_DEVICE_TABLE(acpi, inv_acpi_match); + static struct i2c_driver inv_mpu_driver = { .probe = inv_mpu_probe, .remove = inv_mpu_remove, @@ -883,6 +891,7 @@ static struct i2c_driver inv_mpu_driver = { .owner = THIS_MODULE, .name = "inv-mpu6050", .pm = INV_MPU6050_PMOPS, + .acpi_match_table = ACPI_PTR(inv_acpi_match), }, }; From e37156ec85f28b9008c7d8366ef0f936da018943 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sat, 20 Dec 2014 15:53:07 +0100 Subject: [PATCH 0348/3023] staging: iio: accel: sca3000_core.c: Remove unused function Remove the function sca3000_check_status() that is not used anywhere. This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/sca3000_core.c | 27 ------------------------ 1 file changed, 27 deletions(-) diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index 9cd04c7147c8f1..31fb2182c19826 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -223,33 +223,6 @@ static int sca3000_read_ctrl_reg(struct sca3000_state *st, return ret; } -#ifdef SCA3000_DEBUG -/** - * sca3000_check_status() check the status register - * - * Only used for debugging purposes - **/ -static int sca3000_check_status(struct device *dev) -{ - int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - - mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_STATUS, 1); - if (ret < 0) - goto error_ret; - if (st->rx[0] & SCA3000_EEPROM_CS_ERROR) - dev_err(dev, "eeprom error\n"); - if (st->rx[0] & SCA3000_SPI_FRAME_ERROR) - dev_err(dev, "Previous SPI Frame was corrupt\n"); - -error_ret: - mutex_unlock(&st->lock); - return ret; -} -#endif /* SCA3000_DEBUG */ - /** * sca3000_show_rev() - sysfs interface to read the chip revision number **/ From 95d8c4c8499f8a868af719ecfb005f55c959c73a Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Fri, 28 Nov 2014 21:32:48 +0100 Subject: [PATCH 0349/3023] arm: pxa: fix pxa27x device-tree support kconfig Remove the useless CPU_PXA27x non existing kconfig option. The true options is PXA27x, which is already selected. Reported-by: Paul Bolle Signed-off-by: Robert Jarzmik --- arch/arm/mach-pxa/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 83efe914bf7df4..5f71c06a4b5bfe 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -6,7 +6,6 @@ comment "Intel/Marvell Dev Platforms (sorted by hardware release time)" config MACH_PXA27X_DT bool "Support PXA27x platforms from device tree" - select CPU_PXA27x select POWER_SUPPLY select PXA27x select USE_OF From 3ad32229bed9953dd2085ef992adb161ed0c9194 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Mon, 24 Nov 2014 23:18:22 +0100 Subject: [PATCH 0350/3023] ARM: pxa: arbitrarily set first interrupt number As IRQ0, the legacy timer interrupt should not be used as an interrupt number, shift the interrupts by a fixed number. As we had in a special case a shift of 16 when ISA bus was used on a PXA, use that value as the first interrupt number, regardless of ISA or not. Signed-off-by: Robert Jarzmik --- arch/arm/mach-pxa/Kconfig | 5 ----- arch/arm/mach-pxa/include/mach/irqs.h | 9 ++------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 5f71c06a4b5bfe..8896e71586f5e2 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -83,14 +83,12 @@ config ARCH_VIPER select I2C_GPIO if I2C=y select ISA select PXA25x - select PXA_HAVE_ISA_IRQS config MACH_ARCOM_ZEUS bool "Arcom/Eurotech ZEUS SBC" select ARCOM_PCMCIA select ISA select PXA27x - select PXA_HAVE_ISA_IRQS config MACH_BALLOON3 bool "Balloon 3 board" @@ -690,9 +688,6 @@ config SHARPSL_PM_MAX1111 select SPI select SPI_MASTER -config PXA_HAVE_ISA_IRQS - bool - config PXA310_ULPI bool diff --git a/arch/arm/mach-pxa/include/mach/irqs.h b/arch/arm/mach-pxa/include/mach/irqs.h index 48c2fd851686aa..83e04d4e72a8b9 100644 --- a/arch/arm/mach-pxa/include/mach/irqs.h +++ b/arch/arm/mach-pxa/include/mach/irqs.h @@ -12,14 +12,9 @@ #ifndef __ASM_MACH_IRQS_H #define __ASM_MACH_IRQS_H -#ifdef CONFIG_PXA_HAVE_ISA_IRQS -#define PXA_ISA_IRQ(x) (x) -#define PXA_ISA_IRQ_NUM (16) -#else -#define PXA_ISA_IRQ_NUM (0) -#endif +#include -#define PXA_IRQ(x) (PXA_ISA_IRQ_NUM + (x)) +#define PXA_IRQ(x) (NR_IRQS_LEGACY + (x)) #define IRQ_SSP3 PXA_IRQ(0) /* SSP3 service request */ #define IRQ_MSL PXA_IRQ(1) /* MSL Interface interrupt */ From 271e80176aae4e5b481f4bb92df9768c6075bbca Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Thu, 4 Dec 2014 14:10:00 +0300 Subject: [PATCH 0351/3023] ARM: pxa: add regulator_has_full_constraints to corgi board file Add regulator_has_full_constraints() call to corgi board file to let regulator core know that we do not have any additional regulators left. This lets it substitute unprovided regulators with dummy ones. This fixes the following warnings that can be seen on corgi if regulators are enabled: ads7846 spi1.0: unable to get regulator: -517 spi spi1.0: Driver ads7846 requests probe deferral wm8731 0-001b: Failed to get supply 'AVDD': -517 wm8731 0-001b: Failed to request supplies: -517 wm8731 0-001b: ASoC: failed to probe component -517 corgi-audio corgi-audio: ASoC: failed to instantiate card -517 Cc: stable@vger.kernel.org Signed-off-by: Dmitry Eremin-Solenikov Acked-by: Mark Brown Signed-off-by: Robert Jarzmik --- arch/arm/mach-pxa/corgi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 06022b2357309c..89f790dda93e6c 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -752,6 +753,8 @@ static void __init corgi_init(void) sharpsl_nand_partitions[1].size = 53 * 1024 * 1024; platform_add_devices(devices, ARRAY_SIZE(devices)); + + regulator_has_full_constraints(); } static void __init fixup_corgi(struct tag *tags, char **cmdline) From 9bc78f32c2e430aebf6def965b316aa95e37a20c Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Thu, 4 Dec 2014 14:10:01 +0300 Subject: [PATCH 0352/3023] ARM: pxa: add regulator_has_full_constraints to poodle board file Add regulator_has_full_constraints() call to poodle board file to let regulator core know that we do not have any additional regulators left. This lets it substitute unprovided regulators with dummy ones. This fixes the following warnings that can be seen on poodle if regulators are enabled: ads7846 spi1.0: unable to get regulator: -517 spi spi1.0: Driver ads7846 requests probe deferral wm8731 0-001b: Failed to get supply 'AVDD': -517 wm8731 0-001b: Failed to request supplies: -517 wm8731 0-001b: ASoC: failed to probe component -517 Cc: stable@vger.kernel.org Signed-off-by: Dmitry Eremin-Solenikov Acked-by: Mark Brown Signed-off-by: Robert Jarzmik --- arch/arm/mach-pxa/poodle.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index 29019beae591bc..195b1121c8f1b0 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -455,6 +456,7 @@ static void __init poodle_init(void) pxa_set_i2c_info(NULL); i2c_register_board_info(0, ARRAY_AND_SIZE(poodle_i2c_devices)); poodle_init_spi(); + regulator_has_full_constraints(); } static void __init fixup_poodle(struct tag *tags, char **cmdline) From baad2dc49c5d970ea881d92981a1b76c94a7b7a1 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Thu, 4 Dec 2014 14:10:02 +0300 Subject: [PATCH 0353/3023] ARM: pxa: add regulator_has_full_constraints to spitz board file Add regulator_has_full_constraints() call to spitz board file to let regulator core know that we do not have any additional regulators left. This lets it substitute unprovided regulators with dummy ones. This fixes the following warnings that can be seen on spitz if regulators are enabled: ads7846 spi2.0: unable to get regulator: -517 spi spi2.0: Driver ads7846 requests probe deferral Cc: stable@vger.kernel.org Signed-off-by: Dmitry Eremin-Solenikov Acked-by: Mark Brown Signed-off-by: Robert Jarzmik --- arch/arm/mach-pxa/spitz.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 962a7f31f5969a..f4e2e2719580d2 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -979,6 +979,8 @@ static void __init spitz_init(void) spitz_nand_init(); spitz_i2c_init(); spitz_audio_init(); + + regulator_has_full_constraints(); } static void __init spitz_fixup(struct tag *tags, char **cmdline) From a52d209336f8fc7483a8c7f4a8a7d2a8e1692a6c Mon Sep 17 00:00:00 2001 From: Martin Vajnar Date: Wed, 24 Dec 2014 00:27:57 +0100 Subject: [PATCH 0354/3023] hx4700: regulator: declare full constraints Since the removal of CONFIG_REGULATOR_DUMMY option, the touchscreen stopped working. This patch enables the "replacement" for REGULATOR_DUMMY and allows the touchscreen to work even though there is no regulator for "vcc". Cc: stable@vger.kernel.org Signed-off-by: Martin Vajnar Signed-off-by: Robert Jarzmik --- arch/arm/mach-pxa/hx4700.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c index c66ad4edc5e35e..5fb41ad6e3bcdc 100644 --- a/arch/arm/mach-pxa/hx4700.c +++ b/arch/arm/mach-pxa/hx4700.c @@ -893,6 +893,8 @@ static void __init hx4700_init(void) mdelay(10); gpio_set_value(GPIO71_HX4700_ASIC3_nRESET, 1); mdelay(10); + + regulator_has_full_constraints(); } MACHINE_START(H4700, "HP iPAQ HX4700") From 5afdfd22e6ba2260129a2a7113ab0916339c4205 Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Thu, 25 Dec 2014 23:00:06 +0100 Subject: [PATCH 0355/3023] crypto: algif_rng - add random number generator support This patch adds the random number generator support for AF_ALG. A random number generator's purpose is to generate data without requiring the caller to provide any data. Therefore, the AF_ALG interface handler for RNGs only implements a callback handler for recvmsg. The following parameters provided with a recvmsg are processed by the RNG callback handler: * sock - to resolve the RNG context data structure accessing the RNG instance private to the socket * len - this parameter allows userspace callers to specify how many random bytes the RNG shall produce and return. As the kernel context for the RNG allocates a buffer of 128 bytes to store random numbers before copying them to userspace, the len parameter is checked that it is not larger than 128. If a caller wants more random numbers, a new request for recvmsg shall be made. The size of 128 bytes is chose because of the following considerations: * to increase the memory footprint of the kernel too much (note, that would be 128 bytes per open socket) * 128 is divisible by any typical cryptographic block size an RNG may have * A request for random numbers typically only shall supply small amount of data like for keys or IVs that should only require one invocation of the recvmsg function. Note, during instantiation of the RNG, the code checks whether the RNG implementation requires seeding. If so, the RNG is seeded with output from get_random_bytes. A fully working example using all aspects of the RNG interface is provided at http://www.chronox.de/libkcapi.html Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/algif_rng.c | 192 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 crypto/algif_rng.c diff --git a/crypto/algif_rng.c b/crypto/algif_rng.c new file mode 100644 index 00000000000000..91c06f5673dd5d --- /dev/null +++ b/crypto/algif_rng.c @@ -0,0 +1,192 @@ +/* + * algif_rng: User-space interface for random number generators + * + * This file provides the user-space API for random number generators. + * + * Copyright (C) 2014, Stephan Mueller + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU General Public License, in which case the provisions of the GPL2 + * are required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Stephan Mueller "); +MODULE_DESCRIPTION("User-space interface for random number generators"); + +struct rng_ctx { +#define MAXSIZE 128 + unsigned int len; + struct crypto_rng *drng; +}; + +static int rng_recvmsg(struct kiocb *unused, struct socket *sock, + struct msghdr *msg, size_t len, int flags) +{ + struct sock *sk = sock->sk; + struct alg_sock *ask = alg_sk(sk); + struct rng_ctx *ctx = ask->private; + int err = -EFAULT; + int genlen = 0; + u8 result[MAXSIZE]; + + if (len == 0) + return 0; + if (len > MAXSIZE) + len = MAXSIZE; + + /* + * although not strictly needed, this is a precaution against coding + * errors + */ + memset(result, 0, len); + + /* + * The enforcement of a proper seeding of an RNG is done within an + * RNG implementation. Some RNGs (DRBG, krng) do not need specific + * seeding as they automatically seed. The X9.31 DRNG will return + * an error if it was not seeded properly. + */ + genlen = crypto_rng_get_bytes(ctx->drng, result, len); + if (genlen < 0) + return genlen; + + err = memcpy_to_msg(msg, result, len); + memzero_explicit(result, genlen); + + return err ? err : len; +} + +static struct proto_ops algif_rng_ops = { + .family = PF_ALG, + + .connect = sock_no_connect, + .socketpair = sock_no_socketpair, + .getname = sock_no_getname, + .ioctl = sock_no_ioctl, + .listen = sock_no_listen, + .shutdown = sock_no_shutdown, + .getsockopt = sock_no_getsockopt, + .mmap = sock_no_mmap, + .bind = sock_no_bind, + .accept = sock_no_accept, + .setsockopt = sock_no_setsockopt, + .poll = sock_no_poll, + .sendmsg = sock_no_sendmsg, + .sendpage = sock_no_sendpage, + + .release = af_alg_release, + .recvmsg = rng_recvmsg, +}; + +static void *rng_bind(const char *name, u32 type, u32 mask) +{ + return crypto_alloc_rng(name, type, mask); +} + +static void rng_release(void *private) +{ + crypto_free_rng(private); +} + +static void rng_sock_destruct(struct sock *sk) +{ + struct alg_sock *ask = alg_sk(sk); + struct rng_ctx *ctx = ask->private; + + sock_kfree_s(sk, ctx, ctx->len); + af_alg_release_parent(sk); +} + +static int rng_accept_parent(void *private, struct sock *sk) +{ + struct rng_ctx *ctx; + struct alg_sock *ask = alg_sk(sk); + unsigned int len = sizeof(*ctx); + + ctx = sock_kmalloc(sk, len, GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ctx->len = len; + + /* + * No seeding done at that point -- if multiple accepts are + * done on one RNG instance, each resulting FD points to the same + * state of the RNG. + */ + + ctx->drng = private; + ask->private = ctx; + sk->sk_destruct = rng_sock_destruct; + + return 0; +} + +static int rng_setkey(void *private, const u8 *seed, unsigned int seedlen) +{ + /* + * Check whether seedlen is of sufficient size is done in RNG + * implementations. + */ + return crypto_rng_reset(private, (u8 *)seed, seedlen); +} + +static const struct af_alg_type algif_type_rng = { + .bind = rng_bind, + .release = rng_release, + .accept = rng_accept_parent, + .setkey = rng_setkey, + .ops = &algif_rng_ops, + .name = "rng", + .owner = THIS_MODULE +}; + +static int __init rng_init(void) +{ + return af_alg_register_type(&algif_type_rng); +} + +void __exit rng_exit(void) +{ + int err = af_alg_unregister_type(&algif_type_rng); + BUG_ON(err); +} + +module_init(rng_init); +module_exit(rng_exit); From 2f3755381da8d592656f1ef6868fa9f96c450ba9 Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Thu, 25 Dec 2014 23:00:39 +0100 Subject: [PATCH 0356/3023] crypto: algif_rng - enable RNG interface compilation Enable compilation of the RNG AF_ALG support and provide a Kconfig option to compile the RNG AF_ALG support. Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/Kconfig | 9 +++++++++ crypto/Makefile | 1 + 2 files changed, 10 insertions(+) diff --git a/crypto/Kconfig b/crypto/Kconfig index 1618468b1fcbee..50f4da44a30461 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1514,6 +1514,15 @@ config CRYPTO_USER_API_SKCIPHER This option enables the user-spaces interface for symmetric key cipher algorithms. +config CRYPTO_USER_API_RNG + tristate "User-space interface for random number generator algorithms" + depends on NET + select CRYPTO_RNG + select CRYPTO_USER_API + help + This option enables the user-spaces interface for random + number generator algorithms. + config CRYPTO_HASH_INFO bool diff --git a/crypto/Makefile b/crypto/Makefile index 1445b9100c054c..ba19465f9ad362 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -99,6 +99,7 @@ obj-$(CONFIG_CRYPTO_GHASH) += ghash-generic.o obj-$(CONFIG_CRYPTO_USER_API) += af_alg.o obj-$(CONFIG_CRYPTO_USER_API_HASH) += algif_hash.o obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o +obj-$(CONFIG_CRYPTO_USER_API_RNG) += algif_rng.o # # generic algorithms and the async_tx api From f32c4c506f9b197f24d4be4ee7283bd549e3a30f Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Tue, 30 Dec 2014 15:08:16 +0100 Subject: [PATCH 0357/3023] drm: sti: add DVO output connector Digital Video Out connector driver LCD panels. Like HDMI and HDA it create bridge, encoder and connector drm object. Add binding description. Signed-off-by: Benjamin Gaignard --- .../devicetree/bindings/gpu/st,stih4xx.txt | 29 + drivers/gpu/drm/sti/Makefile | 4 + drivers/gpu/drm/sti/sti_awg_utils.c | 184 ++++++ drivers/gpu/drm/sti/sti_awg_utils.h | 34 ++ drivers/gpu/drm/sti/sti_dvo.c | 551 ++++++++++++++++++ drivers/gpu/drm/sti/sti_tvout.c | 118 ++++ 6 files changed, 920 insertions(+) create mode 100644 drivers/gpu/drm/sti/sti_awg_utils.c create mode 100644 drivers/gpu/drm/sti/sti_awg_utils.h create mode 100644 drivers/gpu/drm/sti/sti_dvo.c diff --git a/Documentation/devicetree/bindings/gpu/st,stih4xx.txt b/Documentation/devicetree/bindings/gpu/st,stih4xx.txt index c99eb34e640b67..6b1d75f1a5297f 100644 --- a/Documentation/devicetree/bindings/gpu/st,stih4xx.txt +++ b/Documentation/devicetree/bindings/gpu/st,stih4xx.txt @@ -83,6 +83,22 @@ sti-hda: - clock-names: names of the clocks listed in clocks property in the same order. +sti-dvo: + Required properties: + must be a child of sti-tvout + - compatible: "st,stih-dvo" + - reg: Physical base address of the IP registers and length of memory mapped region. + - reg-names: names of the mapped memory regions listed in regs property in + the same order. + - clocks: from common clock binding: handle hardware IP needed clocks, the + number of clocks may depend of the SoC type. + See ../clocks/clock-bindings.txt for details. + - clock-names: names of the clocks listed in clocks property in the same + order. + - pinctrl-0: pin control handle + - pinctrl-name: names of the pin control to use + - sti,panel: phandle of the panel connected to the DVO output + sti-hqvdp: must be a child of sti-display-subsystem Required properties: @@ -198,6 +214,19 @@ Example: clock-names = "pix", "hddac"; clocks = <&clockgen_c_vcc CLK_S_PIX_HD>, <&clockgen_c_vcc CLK_S_HDDAC>; }; + + sti-dvo@8d00400 { + compatible = "st,stih407-dvo"; + reg = <0x8d00400 0x200>; + reg-names = "dvo-reg"; + clock-names = "dvo_pix", "dvo", + "main_parent", "aux_parent"; + clocks = <&clk_s_d2_flexgen CLK_PIX_DVO>, <&clk_s_d2_flexgen CLK_DVO>, + <&clk_s_d2_quadfs 0>, <&clk_s_d2_quadfs 1>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_dvo>; + sti,panel = <&panel_dvo>; + }; }; sti-hqvdp@9c000000 { diff --git a/drivers/gpu/drm/sti/Makefile b/drivers/gpu/drm/sti/Makefile index 6ba9d27c1b90b8..f0f1e4ee2d9220 100644 --- a/drivers/gpu/drm/sti/Makefile +++ b/drivers/gpu/drm/sti/Makefile @@ -12,6 +12,9 @@ stihdmi-y := sti_hdmi.o \ sti_hdmi_tx3g0c55phy.o \ sti_hdmi_tx3g4c28phy.o \ +stidvo-y := sti_dvo.o \ + sti_awg_utils.o + obj-$(CONFIG_DRM_STI) = \ sti_vtg.o \ sti_vtac.o \ @@ -20,4 +23,5 @@ obj-$(CONFIG_DRM_STI) = \ sti_tvout.o \ sticompositor.o \ sti_hqvdp.o \ + stidvo.o \ sti_drm_drv.o diff --git a/drivers/gpu/drm/sti/sti_awg_utils.c b/drivers/gpu/drm/sti/sti_awg_utils.c new file mode 100644 index 00000000000000..9fde3ee8b1a5a9 --- /dev/null +++ b/drivers/gpu/drm/sti/sti_awg_utils.c @@ -0,0 +1,184 @@ +/* + * Copyright (C) STMicroelectronics SA 2014 + * Author: Vincent Abriou for STMicroelectronics. + * License terms: GNU General Public License (GPL), version 2 + */ + +#include "sti_awg_utils.h" + +#define AWG_OPCODE_OFFSET 10 + +enum opcode { + SET, + RPTSET, + RPLSET, + SKIP, + STOP, + REPEAT, + REPLAY, + JUMP, + HOLD, +}; + +static int awg_generate_instr(enum opcode opcode, + long int arg, + long int mux_sel, + long int data_en, + struct awg_code_generation_params *fwparams) +{ + u32 instruction = 0; + u32 mux = (mux_sel << 8) & 0x1ff; + u32 data_enable = (data_en << 9) & 0x2ff; + long int arg_tmp = arg; + + /* skip, repeat and replay arg should not exceed 1023. + * If user wants to exceed this value, the instruction should be + * duplicate and arg should be adjust for each duplicated instruction. + */ + + while (arg_tmp > 0) { + arg = arg_tmp; + if (fwparams->instruction_offset >= AWG_MAX_INST) { + DRM_ERROR("too many number of instructions\n"); + return -EINVAL; + } + + switch (opcode) { + case SKIP: + /* leave 'arg' + 1 pixel elapsing without changing + * output bus */ + arg--; /* pixel adjustment */ + arg_tmp--; + + if (arg < 0) { + /* SKIP instruction not needed */ + return 0; + } + + if (arg == 0) { + /* SKIP 0 not permitted but we want to skip 1 + * pixel. So we transform SKIP into SET + * instruction */ + opcode = SET; + arg = (arg << 24) >> 24; + arg &= (0x0ff); + break; + } + + mux = 0; + data_enable = 0; + arg = (arg << 22) >> 22; + arg &= (0x3ff); + break; + case REPEAT: + case REPLAY: + if (arg == 0) { + /* REPEAT or REPLAY instruction not needed */ + return 0; + } + + mux = 0; + data_enable = 0; + arg = (arg << 22) >> 22; + arg &= (0x3ff); + break; + case JUMP: + mux = 0; + data_enable = 0; + arg |= 0x40; /* for jump instruction 7th bit is 1 */ + arg = (arg << 22) >> 22; + arg &= 0x3ff; + break; + case STOP: + arg = 0; + break; + case SET: + case RPTSET: + case RPLSET: + case HOLD: + arg = (arg << 24) >> 24; + arg &= (0x0ff); + break; + default: + DRM_ERROR("instruction %d does not exist\n", opcode); + return -EINVAL; + } + + arg_tmp = arg_tmp - arg; + + arg = ((arg + mux) + data_enable); + + instruction = ((opcode) << AWG_OPCODE_OFFSET) | arg; + fwparams->ram_code[fwparams->instruction_offset] = + instruction & (0x3fff); + fwparams->instruction_offset++; + } + return 0; +} + +int sti_awg_generate_code_data_enable_mode( + struct awg_code_generation_params *fwparams, + struct awg_timing *timing) +{ + long int val; + long int data_en; + int ret = 0; + + if (timing->trailing_lines > 0) { + /* skip trailing lines */ + val = timing->blanking_level; + data_en = 0; + ret |= awg_generate_instr(RPLSET, val, 0, data_en, fwparams); + + val = timing->trailing_lines - 1; + data_en = 0; + ret |= awg_generate_instr(REPLAY, val, 0, data_en, fwparams); + } + + if (timing->trailing_pixels > 0) { + /* skip trailing pixel */ + val = timing->blanking_level; + data_en = 0; + ret |= awg_generate_instr(RPLSET, val, 0, data_en, fwparams); + + val = timing->trailing_pixels - 1; + data_en = 0; + ret |= awg_generate_instr(SKIP, val, 0, data_en, fwparams); + } + + /* set DE signal high */ + val = timing->blanking_level; + data_en = 1; + ret |= awg_generate_instr((timing->trailing_pixels > 0) ? SET : RPLSET, + val, 0, data_en, fwparams); + + if (timing->blanking_pixels > 0) { + /* skip the number of active pixel */ + val = timing->active_pixels - 1; + data_en = 1; + ret |= awg_generate_instr(SKIP, val, 0, data_en, fwparams); + + /* set DE signal low */ + val = timing->blanking_level; + data_en = 0; + ret |= awg_generate_instr(SET, val, 0, data_en, fwparams); + } + + /* replay the sequence as many active lines defined */ + val = timing->active_lines - 1; + data_en = 0; + ret |= awg_generate_instr(REPLAY, val, 0, data_en, fwparams); + + if (timing->blanking_lines > 0) { + /* skip blanking lines */ + val = timing->blanking_level; + data_en = 0; + ret |= awg_generate_instr(RPLSET, val, 0, data_en, fwparams); + + val = timing->blanking_lines - 1; + data_en = 0; + ret |= awg_generate_instr(REPLAY, val, 0, data_en, fwparams); + } + + return ret; +} diff --git a/drivers/gpu/drm/sti/sti_awg_utils.h b/drivers/gpu/drm/sti/sti_awg_utils.h new file mode 100644 index 00000000000000..45d599bd570a3f --- /dev/null +++ b/drivers/gpu/drm/sti/sti_awg_utils.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) STMicroelectronics SA 2014 + * Author: Vincent Abriou for STMicroelectronics. + * License terms: GNU General Public License (GPL), version 2 + */ + +#ifndef _STI_AWG_UTILS_H_ +#define _STI_AWG_UTILS_H_ + +#include + +#define AWG_MAX_INST 64 + +struct awg_code_generation_params { + u32 *ram_code; + u8 instruction_offset; +}; + +struct awg_timing { + u32 total_lines; + u32 active_lines; + u32 blanking_lines; + u32 trailing_lines; + u32 total_pixels; + u32 active_pixels; + u32 blanking_pixels; + u32 trailing_pixels; + u32 blanking_level; +}; + +int sti_awg_generate_code_data_enable_mode( + struct awg_code_generation_params *fw_gen_params, + struct awg_timing *timing); +#endif diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c new file mode 100644 index 00000000000000..651afad21f92c1 --- /dev/null +++ b/drivers/gpu/drm/sti/sti_dvo.c @@ -0,0 +1,551 @@ +/* + * Copyright (C) STMicroelectronics SA 2014 + * Author: Vincent Abriou for STMicroelectronics. + * License terms: GNU General Public License (GPL), version 2 + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "sti_awg_utils.h" +#include "sti_mixer.h" + +/* DVO registers */ +#define DVO_AWG_DIGSYNC_CTRL 0x0000 +#define DVO_DOF_CFG 0x0004 +#define DVO_LUT_PROG_LOW 0x0008 +#define DVO_LUT_PROG_MID 0x000C +#define DVO_LUT_PROG_HIGH 0x0010 +#define DVO_DIGSYNC_INSTR_I 0x0100 + +#define DVO_AWG_CTRL_EN BIT(0) +#define DVO_AWG_FRAME_BASED_SYNC BIT(2) + +#define DVO_DOF_EN_LOWBYTE BIT(0) +#define DVO_DOF_EN_MIDBYTE BIT(1) +#define DVO_DOF_EN_HIGHBYTE BIT(2) +#define DVO_DOF_EN BIT(6) +#define DVO_DOF_MOD_COUNT_SHIFT 8 + +#define DVO_LUT_ZERO 0 +#define DVO_LUT_Y_G 1 +#define DVO_LUT_Y_G_DEL 2 +#define DVO_LUT_CB_B 3 +#define DVO_LUT_CB_B_DEL 4 +#define DVO_LUT_CR_R 5 +#define DVO_LUT_CR_R_DEL 6 +#define DVO_LUT_HOLD 7 + +struct dvo_config { + u32 flags; + u32 lowbyte; + u32 midbyte; + u32 highbyte; + int (*awg_fwgen_fct)( + struct awg_code_generation_params *fw_gen_params, + struct awg_timing *timing); +}; + +static struct dvo_config rgb_24bit_de_cfg = { + .flags = (0L << DVO_DOF_MOD_COUNT_SHIFT), + .lowbyte = DVO_LUT_CR_R, + .midbyte = DVO_LUT_Y_G, + .highbyte = DVO_LUT_CB_B, + .awg_fwgen_fct = sti_awg_generate_code_data_enable_mode, +}; + +/** + * STI digital video output structure + * + * @dev: driver device + * @drm_dev: pointer to drm device + * @mode: current display mode selected + * @regs: dvo registers + * @clk_pix: pixel clock for dvo + * @clk: clock for dvo + * @clk_main_parent: dvo parent clock if main path used + * @clk_aux_parent: dvo parent clock if aux path used + * @panel_node: panel node reference from device tree + * @panel: reference to the panel connected to the dvo + * @enabled: true if dvo is enabled else false + * @encoder: drm_encoder it is bound + */ +struct sti_dvo { + struct device dev; + struct drm_device *drm_dev; + struct drm_display_mode mode; + void __iomem *regs; + struct clk *clk_pix; + struct clk *clk; + struct clk *clk_main_parent; + struct clk *clk_aux_parent; + struct device_node *panel_node; + struct drm_panel *panel; + struct dvo_config *config; + bool enabled; + struct drm_encoder *encoder; +}; + +struct sti_dvo_connector { + struct drm_connector drm_connector; + struct drm_encoder *encoder; + struct sti_dvo *dvo; +}; + +#define to_sti_dvo_connector(x) \ + container_of(x, struct sti_dvo_connector, drm_connector) + +#define BLANKING_LEVEL 16 +int dvo_awg_generate_code(struct sti_dvo *dvo, u8 *ram_size, u32 *ram_code) +{ + struct drm_display_mode *mode = &dvo->mode; + struct dvo_config *config = dvo->config; + struct awg_code_generation_params fw_gen_params; + struct awg_timing timing; + + fw_gen_params.ram_code = ram_code; + fw_gen_params.instruction_offset = 0; + + timing.total_lines = mode->vtotal; + timing.active_lines = mode->vdisplay; + timing.blanking_lines = mode->vsync_start - mode->vdisplay; + timing.trailing_lines = mode->vtotal - mode->vsync_start; + timing.total_pixels = mode->htotal; + timing.active_pixels = mode->hdisplay; + timing.blanking_pixels = mode->hsync_start - mode->hdisplay; + timing.trailing_pixels = mode->htotal - mode->hsync_start; + timing.blanking_level = BLANKING_LEVEL; + + if (config->awg_fwgen_fct(&fw_gen_params, &timing)) { + DRM_ERROR("AWG firmware not properly generated\n"); + return -EINVAL; + } + + *ram_size = fw_gen_params.instruction_offset; + + return 0; +} + +/* Configure AWG, writing instructions + * + * @dvo: pointer to DVO structure + * @awg_ram_code: pointer to AWG instructions table + * @nb: nb of AWG instructions + */ +static void dvo_awg_configure(struct sti_dvo *dvo, u32 *awg_ram_code, int nb) +{ + int i; + + DRM_DEBUG_DRIVER("\n"); + + for (i = 0; i < nb; i++) + writel(awg_ram_code[i], + dvo->regs + DVO_DIGSYNC_INSTR_I + i * 4); + for (i = nb; i < AWG_MAX_INST; i++) + writel(0, dvo->regs + DVO_DIGSYNC_INSTR_I + i * 4); + + writel(DVO_AWG_CTRL_EN, dvo->regs + DVO_AWG_DIGSYNC_CTRL); +} + +static void sti_dvo_disable(struct drm_bridge *bridge) +{ + struct sti_dvo *dvo = bridge->driver_private; + + if (!dvo->enabled) + return; + + DRM_DEBUG_DRIVER("\n"); + + if (dvo->config->awg_fwgen_fct) + writel(0x00000000, dvo->regs + DVO_AWG_DIGSYNC_CTRL); + + writel(0x00000000, dvo->regs + DVO_DOF_CFG); + + if (dvo->panel) + dvo->panel->funcs->disable(dvo->panel); + + /* Disable/unprepare dvo clock */ + clk_disable_unprepare(dvo->clk_pix); + clk_disable_unprepare(dvo->clk); + + dvo->enabled = false; +} + +static void sti_dvo_pre_enable(struct drm_bridge *bridge) +{ + struct sti_dvo *dvo = bridge->driver_private; + struct dvo_config *config = dvo->config; + u32 val; + + DRM_DEBUG_DRIVER("\n"); + + if (dvo->enabled) + return; + + /* Make sure DVO is disabled */ + writel(0x00000000, dvo->regs + DVO_DOF_CFG); + writel(0x00000000, dvo->regs + DVO_AWG_DIGSYNC_CTRL); + + if (config->awg_fwgen_fct) { + u8 nb_instr; + u32 awg_ram_code[AWG_MAX_INST]; + /* Configure AWG */ + if (!dvo_awg_generate_code(dvo, &nb_instr, awg_ram_code)) + dvo_awg_configure(dvo, awg_ram_code, nb_instr); + else + return; + } + + /* Prepare/enable clocks */ + if (clk_prepare_enable(dvo->clk_pix)) + DRM_ERROR("Failed to prepare/enable dvo_pix clk\n"); + if (clk_prepare_enable(dvo->clk)) + DRM_ERROR("Failed to prepare/enable dvo clk\n"); + + if (dvo->panel) + dvo->panel->funcs->enable(dvo->panel); + + /* Set LUT */ + writel(config->lowbyte, dvo->regs + DVO_LUT_PROG_LOW); + writel(config->midbyte, dvo->regs + DVO_LUT_PROG_MID); + writel(config->highbyte, dvo->regs + DVO_LUT_PROG_HIGH); + + /* Digital output formatter config */ + val = (config->flags | DVO_DOF_EN); + writel(val, dvo->regs + DVO_DOF_CFG); + + dvo->enabled = true; +} + +static void sti_dvo_set_mode(struct drm_bridge *bridge, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct sti_dvo *dvo = bridge->driver_private; + struct sti_mixer *mixer = to_sti_mixer(dvo->encoder->crtc); + int rate = mode->clock * 1000; + struct clk *clkp; + int ret; + + DRM_DEBUG_DRIVER("\n"); + + memcpy(&dvo->mode, mode, sizeof(struct drm_display_mode)); + + /* According to the path used (main or aux), the dvo clocks should + * have a different parent clock. */ + if (mixer->id == STI_MIXER_MAIN) + clkp = dvo->clk_main_parent; + else + clkp = dvo->clk_aux_parent; + + if (clkp) { + clk_set_parent(dvo->clk_pix, clkp); + clk_set_parent(dvo->clk, clkp); + } + + /* DVO clocks = compositor clock */ + ret = clk_set_rate(dvo->clk_pix, rate); + if (ret < 0) { + DRM_ERROR("Cannot set rate (%dHz) for dvo_pix clk\n", rate); + return; + } + + ret = clk_set_rate(dvo->clk, rate); + if (ret < 0) { + DRM_ERROR("Cannot set rate (%dHz) for dvo clk\n", rate); + return; + } + + /* For now, we only support 24bit data enable (DE) synchro format */ + dvo->config = &rgb_24bit_de_cfg; +} + +static void sti_dvo_bridge_nope(struct drm_bridge *bridge) +{ + /* do nothing */ +} + +static void sti_dvo_brigde_destroy(struct drm_bridge *bridge) +{ + drm_bridge_cleanup(bridge); + kfree(bridge); +} + +static const struct drm_bridge_funcs sti_dvo_bridge_funcs = { + .pre_enable = sti_dvo_pre_enable, + .enable = sti_dvo_bridge_nope, + .disable = sti_dvo_disable, + .post_disable = sti_dvo_bridge_nope, + .mode_set = sti_dvo_set_mode, + .destroy = sti_dvo_brigde_destroy, +}; + +static int sti_dvo_connector_get_modes(struct drm_connector *connector) +{ + struct sti_dvo_connector *dvo_connector + = to_sti_dvo_connector(connector); + struct sti_dvo *dvo = dvo_connector->dvo; + + if (dvo->panel) + return dvo->panel->funcs->get_modes(dvo->panel); + + return 0; +} + +#define CLK_TOLERANCE_HZ 50 + +static int sti_dvo_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + int target = mode->clock * 1000; + int target_min = target - CLK_TOLERANCE_HZ; + int target_max = target + CLK_TOLERANCE_HZ; + int result; + struct sti_dvo_connector *dvo_connector + = to_sti_dvo_connector(connector); + struct sti_dvo *dvo = dvo_connector->dvo; + + result = clk_round_rate(dvo->clk_pix, target); + + DRM_DEBUG_DRIVER("target rate = %d => available rate = %d\n", + target, result); + + if ((result < target_min) || (result > target_max)) { + DRM_DEBUG_DRIVER("dvo pixclk=%d not supported\n", target); + return MODE_BAD; + } + + return MODE_OK; +} + +struct drm_encoder *sti_dvo_best_encoder(struct drm_connector *connector) +{ + struct sti_dvo_connector *dvo_connector + = to_sti_dvo_connector(connector); + + /* Best encoder is the one associated during connector creation */ + return dvo_connector->encoder; +} + +static struct drm_connector_helper_funcs sti_dvo_connector_helper_funcs = { + .get_modes = sti_dvo_connector_get_modes, + .mode_valid = sti_dvo_connector_mode_valid, + .best_encoder = sti_dvo_best_encoder, +}; + +static enum drm_connector_status +sti_dvo_connector_detect(struct drm_connector *connector, bool force) +{ + struct sti_dvo_connector *dvo_connector + = to_sti_dvo_connector(connector); + struct sti_dvo *dvo = dvo_connector->dvo; + + DRM_DEBUG_DRIVER("\n"); + + if (!dvo->panel) + dvo->panel = of_drm_find_panel(dvo->panel_node); + + if (dvo->panel) + if (!drm_panel_attach(dvo->panel, connector)) + return connector_status_connected; + + return connector_status_disconnected; +} + +static void sti_dvo_connector_destroy(struct drm_connector *connector) +{ + struct sti_dvo_connector *dvo_connector + = to_sti_dvo_connector(connector); + + drm_connector_unregister(connector); + drm_connector_cleanup(connector); + kfree(dvo_connector); +} + +static struct drm_connector_funcs sti_dvo_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .fill_modes = drm_helper_probe_single_connector_modes, + .detect = sti_dvo_connector_detect, + .destroy = sti_dvo_connector_destroy, +}; + +static struct drm_encoder *sti_dvo_find_encoder(struct drm_device *dev) +{ + struct drm_encoder *encoder; + + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) + return encoder; + } + + return NULL; +} + +static int sti_dvo_bind(struct device *dev, struct device *master, void *data) +{ + struct sti_dvo *dvo = dev_get_drvdata(dev); + struct drm_device *drm_dev = data; + struct drm_encoder *encoder; + struct sti_dvo_connector *connector; + struct drm_connector *drm_connector; + struct drm_bridge *bridge; + int err; + + /* Set the drm device handle */ + dvo->drm_dev = drm_dev; + + encoder = sti_dvo_find_encoder(drm_dev); + if (!encoder) + return -ENOMEM; + + connector = devm_kzalloc(dev, sizeof(*connector), GFP_KERNEL); + if (!connector) + return -ENOMEM; + + connector->dvo = dvo; + + bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL); + if (!bridge) + return -ENOMEM; + + bridge->driver_private = dvo; + drm_bridge_init(drm_dev, bridge, &sti_dvo_bridge_funcs); + + encoder->bridge = bridge; + connector->encoder = encoder; + dvo->encoder = encoder; + + drm_connector = (struct drm_connector *)connector; + + drm_connector->polled = DRM_CONNECTOR_POLL_HPD; + + drm_connector_init(drm_dev, drm_connector, + &sti_dvo_connector_funcs, DRM_MODE_CONNECTOR_LVDS); + drm_connector_helper_add(drm_connector, + &sti_dvo_connector_helper_funcs); + + err = drm_connector_register(drm_connector); + if (err) + goto err_connector; + + err = drm_mode_connector_attach_encoder(drm_connector, encoder); + if (err) { + DRM_ERROR("Failed to attach a connector to a encoder\n"); + goto err_sysfs; + } + + return 0; + +err_sysfs: + drm_connector_unregister(drm_connector); +err_connector: + drm_bridge_cleanup(bridge); + drm_connector_cleanup(drm_connector); + return -EINVAL; +} + +static void sti_dvo_unbind(struct device *dev, + struct device *master, void *data) +{ + /* do nothing */ +} + +static const struct component_ops sti_dvo_ops = { + .bind = sti_dvo_bind, + .unbind = sti_dvo_unbind, +}; + +static int sti_dvo_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct sti_dvo *dvo; + struct resource *res; + struct device_node *np = dev->of_node; + + DRM_INFO("%s\n", __func__); + + dvo = devm_kzalloc(dev, sizeof(*dvo), GFP_KERNEL); + if (!dvo) { + DRM_ERROR("Failed to allocate memory for DVO\n"); + return -ENOMEM; + } + + dvo->dev = pdev->dev; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dvo-reg"); + if (!res) { + DRM_ERROR("Invalid dvo resource\n"); + return -ENOMEM; + } + dvo->regs = devm_ioremap_nocache(dev, res->start, + resource_size(res)); + if (IS_ERR(dvo->regs)) + return PTR_ERR(dvo->regs); + + dvo->clk_pix = devm_clk_get(dev, "dvo_pix"); + if (IS_ERR(dvo->clk_pix)) { + DRM_ERROR("Cannot get dvo_pix clock\n"); + return PTR_ERR(dvo->clk_pix); + } + + dvo->clk = devm_clk_get(dev, "dvo"); + if (IS_ERR(dvo->clk)) { + DRM_ERROR("Cannot get dvo clock\n"); + return PTR_ERR(dvo->clk); + } + + dvo->clk_main_parent = devm_clk_get(dev, "main_parent"); + if (IS_ERR(dvo->clk_main_parent)) { + DRM_DEBUG_DRIVER("Cannot get main_parent clock\n"); + dvo->clk_main_parent = NULL; + } + + dvo->clk_aux_parent = devm_clk_get(dev, "aux_parent"); + if (IS_ERR(dvo->clk_aux_parent)) { + DRM_DEBUG_DRIVER("Cannot get aux_parent clock\n"); + dvo->clk_aux_parent = NULL; + } + + dvo->panel_node = of_parse_phandle(np, "sti,panel", 0); + if (!dvo->panel_node) + DRM_ERROR("No panel associated to the dvo output\n"); + + platform_set_drvdata(pdev, dvo); + + return component_add(&pdev->dev, &sti_dvo_ops); +} + +static int sti_dvo_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &sti_dvo_ops); + return 0; +} + +static struct of_device_id dvo_of_match[] = { + { .compatible = "st,stih407-dvo", }, + { /* end node */ } +}; +MODULE_DEVICE_TABLE(of, dvo_of_match); + +struct platform_driver sti_dvo_driver = { + .driver = { + .name = "sti-dvo", + .owner = THIS_MODULE, + .of_match_table = dvo_of_match, + }, + .probe = sti_dvo_probe, + .remove = sti_dvo_remove, +}; + +module_platform_driver(sti_dvo_driver); + +MODULE_AUTHOR("Benjamin Gaignard "); +MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/sti/sti_tvout.c b/drivers/gpu/drm/sti/sti_tvout.c index cb924aa2b321b3..5cc53116508eba 100644 --- a/drivers/gpu/drm/sti/sti_tvout.c +++ b/drivers/gpu/drm/sti/sti_tvout.c @@ -48,6 +48,9 @@ #define TVO_HDMI_CLIP_VALUE_R_CR 0x514 #define TVO_HDMI_SYNC_SEL 0x518 #define TVO_HDMI_DFV_OBS 0x540 +#define TVO_VIP_DVO 0x600 +#define TVO_DVO_SYNC_SEL 0x618 +#define TVO_DVO_CONFIG 0x620 #define TVO_IN_FMT_SIGNED BIT(0) #define TVO_SYNC_EXT BIT(4) @@ -98,6 +101,9 @@ #define TVO_SYNC_HD_DCS_SHIFT 8 +#define TVO_SYNC_DVO_PAD_HSYNC_SHIFT 8 +#define TVO_SYNC_DVO_PAD_VSYNC_SHIFT 16 + #define ENCODER_CRTC_MASK (BIT(0) | BIT(1)) /* enum listing the supported output data format */ @@ -113,6 +119,7 @@ struct sti_tvout { struct reset_control *reset; struct drm_encoder *hdmi; struct drm_encoder *hda; + struct drm_encoder *dvo; }; struct sti_tvout_encoder { @@ -261,6 +268,66 @@ static void tvout_vip_set_in_vid_fmt(struct sti_tvout *tvout, tvout_write(tvout, val, reg); } +/** + * Start VIP block for DVO output + * + * @tvout: pointer on tvout structure + * @main_path: true if main path has to be used in the vip configuration + * else aux path is used. + */ +static void tvout_dvo_start(struct sti_tvout *tvout, bool main_path) +{ + struct device_node *node = tvout->dev->of_node; + bool sel_input_logic_inverted = false; + u32 tvo_in_vid_format; + int val; + + dev_dbg(tvout->dev, "%s\n", __func__); + + if (main_path) { + DRM_DEBUG_DRIVER("main vip for DVO\n"); + /* Select the input sync for dvo = VTG set 4 */ + val = TVO_SYNC_MAIN_VTG_SET_4 << TVO_SYNC_DVO_PAD_VSYNC_SHIFT; + val |= TVO_SYNC_MAIN_VTG_SET_4 << TVO_SYNC_DVO_PAD_HSYNC_SHIFT; + val |= TVO_SYNC_MAIN_VTG_SET_4; + tvout_write(tvout, val, TVO_DVO_SYNC_SEL); + tvo_in_vid_format = TVO_MAIN_IN_VID_FORMAT; + } else { + DRM_DEBUG_DRIVER("aux vip for DVO\n"); + /* Select the input sync for dvo = VTG set 4 */ + val = TVO_SYNC_AUX_VTG_SET_4 << TVO_SYNC_DVO_PAD_VSYNC_SHIFT; + val |= TVO_SYNC_AUX_VTG_SET_4 << TVO_SYNC_DVO_PAD_HSYNC_SHIFT; + val |= TVO_SYNC_AUX_VTG_SET_4; + tvout_write(tvout, val, TVO_DVO_SYNC_SEL); + tvo_in_vid_format = TVO_AUX_IN_VID_FORMAT; + } + + /* Set color channel order */ + tvout_vip_set_color_order(tvout, TVO_VIP_DVO, + TVO_VIP_REORDER_CR_R_SEL, + TVO_VIP_REORDER_Y_G_SEL, + TVO_VIP_REORDER_CB_B_SEL); + + /* Set clipping mode (Limited range RGB/Y) */ + tvout_vip_set_clip_mode(tvout, TVO_VIP_DVO, + TVO_VIP_CLIP_LIMITED_RANGE_RGB_Y); + + /* Set round mode (rounded to 8-bit per component) */ + tvout_vip_set_rnd(tvout, TVO_VIP_DVO, TVO_VIP_RND_8BIT_ROUNDED); + + if (of_device_is_compatible(node, "st,stih407-tvout")) { + /* Set input video format */ + tvout_vip_set_in_vid_fmt(tvout, tvo_in_vid_format, + TVO_IN_FMT_SIGNED); + sel_input_logic_inverted = true; + } + + /* Input selection */ + tvout_vip_set_sel_input(tvout, TVO_VIP_DVO, main_path, + sel_input_logic_inverted, + STI_TVOUT_VIDEO_OUT_RGB); +} + /** * Start VIP block for HDMI output * @@ -402,6 +469,56 @@ static const struct drm_encoder_funcs sti_tvout_encoder_funcs = { .destroy = sti_tvout_encoder_destroy, }; +static void sti_dvo_encoder_commit(struct drm_encoder *encoder) +{ + struct sti_tvout *tvout = to_sti_tvout(encoder); + + tvout_dvo_start(tvout, sti_drm_crtc_is_main(encoder->crtc)); +} + +static void sti_dvo_encoder_disable(struct drm_encoder *encoder) +{ + struct sti_tvout *tvout = to_sti_tvout(encoder); + + /* Reset VIP register */ + tvout_write(tvout, 0x0, TVO_VIP_DVO); +} + +static const struct drm_encoder_helper_funcs sti_dvo_encoder_helper_funcs = { + .dpms = sti_tvout_encoder_dpms, + .mode_fixup = sti_tvout_encoder_mode_fixup, + .mode_set = sti_tvout_encoder_mode_set, + .prepare = sti_tvout_encoder_prepare, + .commit = sti_dvo_encoder_commit, + .disable = sti_dvo_encoder_disable, +}; + +static struct drm_encoder * +sti_tvout_create_dvo_encoder(struct drm_device *dev, + struct sti_tvout *tvout) +{ + struct sti_tvout_encoder *encoder; + struct drm_encoder *drm_encoder; + + encoder = devm_kzalloc(tvout->dev, sizeof(*encoder), GFP_KERNEL); + if (!encoder) + return NULL; + + encoder->tvout = tvout; + + drm_encoder = (struct drm_encoder *)encoder; + + drm_encoder->possible_crtcs = ENCODER_CRTC_MASK; + drm_encoder->possible_clones = 1 << 0; + + drm_encoder_init(dev, drm_encoder, + &sti_tvout_encoder_funcs, DRM_MODE_ENCODER_LVDS); + + drm_encoder_helper_add(drm_encoder, &sti_dvo_encoder_helper_funcs); + + return drm_encoder; +} + static void sti_hda_encoder_commit(struct drm_encoder *encoder) { struct sti_tvout *tvout = to_sti_tvout(encoder); @@ -508,6 +625,7 @@ static void sti_tvout_create_encoders(struct drm_device *dev, { tvout->hdmi = sti_tvout_create_hdmi_encoder(dev, tvout); tvout->hda = sti_tvout_create_hda_encoder(dev, tvout); + tvout->dvo = sti_tvout_create_dvo_encoder(dev, tvout); } static void sti_tvout_destroy_encoders(struct sti_tvout *tvout) From 9c1ec8e18c210092418d27278a742a2a98eafffe Mon Sep 17 00:00:00 2001 From: Chris Zhong Date: Mon, 1 Dec 2014 16:52:17 +0800 Subject: [PATCH 0358/3023] ARM: rockchip: add suspend and resume for RK3288 It's a basic version of suspend and resume for rockchip, it only support RK3288 now. Signed-off-by: Tony Xie Signed-off-by: Chris Zhong Tested-by: Doug Anderson Reviewed-by: Doug Anderson Signed-off-by: Heiko Stuebner --- arch/arm/mach-rockchip/Makefile | 1 + arch/arm/mach-rockchip/pm.c | 260 ++++++++++++++++++++++++++++++ arch/arm/mach-rockchip/pm.h | 99 ++++++++++++ arch/arm/mach-rockchip/rockchip.c | 2 + arch/arm/mach-rockchip/sleep.S | 73 +++++++++ 5 files changed, 435 insertions(+) create mode 100644 arch/arm/mach-rockchip/pm.c create mode 100644 arch/arm/mach-rockchip/pm.h create mode 100644 arch/arm/mach-rockchip/sleep.S diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile index b29d8ead4cf296..5c3a9b2de92041 100644 --- a/arch/arm/mach-rockchip/Makefile +++ b/arch/arm/mach-rockchip/Makefile @@ -1,4 +1,5 @@ CFLAGS_platsmp.o := -march=armv7-a obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip.o +obj-$(CONFIG_PM_SLEEP) += pm.o sleep.o obj-$(CONFIG_SMP) += headsmp.o platsmp.o diff --git a/arch/arm/mach-rockchip/pm.c b/arch/arm/mach-rockchip/pm.c new file mode 100644 index 00000000000000..50cb781aaa36c9 --- /dev/null +++ b/arch/arm/mach-rockchip/pm.c @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * Author: Tony Xie + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "pm.h" + +/* These enum are option of low power mode */ +enum { + ROCKCHIP_ARM_OFF_LOGIC_NORMAL = 0, + ROCKCHIP_ARM_OFF_LOGIC_DEEP = 1, +}; + +struct rockchip_pm_data { + const struct platform_suspend_ops *ops; + int (*init)(struct device_node *np); +}; + +static void __iomem *rk3288_bootram_base; +static phys_addr_t rk3288_bootram_phy; + +static struct regmap *pmu_regmap; +static struct regmap *sgrf_regmap; + +static u32 rk3288_pmu_pwr_mode_con; +static u32 rk3288_sgrf_soc_con0; + +static inline u32 rk3288_l2_config(void) +{ + u32 l2ctlr; + + asm("mrc p15, 1, %0, c9, c0, 2" : "=r" (l2ctlr)); + return l2ctlr; +} + +static void rk3288_config_bootdata(void) +{ + rkpm_bootdata_cpusp = rk3288_bootram_phy + (SZ_4K - 8); + rkpm_bootdata_cpu_code = virt_to_phys(cpu_resume); + + rkpm_bootdata_l2ctlr_f = 1; + rkpm_bootdata_l2ctlr = rk3288_l2_config(); +} + +static void rk3288_slp_mode_set(int level) +{ + u32 mode_set, mode_set1; + + regmap_read(sgrf_regmap, RK3288_SGRF_SOC_CON0, &rk3288_sgrf_soc_con0); + + regmap_read(pmu_regmap, RK3288_PMU_PWRMODE_CON, + &rk3288_pmu_pwr_mode_con); + + /* set bit 8 so that system will resume to FAST_BOOT_ADDR */ + regmap_write(sgrf_regmap, RK3288_SGRF_SOC_CON0, + SGRF_FAST_BOOT_EN | SGRF_FAST_BOOT_EN_WRITE); + + /* booting address of resuming system is from this register value */ + regmap_write(sgrf_regmap, RK3288_SGRF_FAST_BOOT_ADDR, + rk3288_bootram_phy); + + regmap_write(pmu_regmap, RK3288_PMU_WAKEUP_CFG1, + PMU_ARMINT_WAKEUP_EN); + + mode_set = BIT(PMU_GLOBAL_INT_DISABLE) | BIT(PMU_L2FLUSH_EN) | + BIT(PMU_SREF0_ENTER_EN) | BIT(PMU_SREF1_ENTER_EN) | + BIT(PMU_DDR0_GATING_EN) | BIT(PMU_DDR1_GATING_EN) | + BIT(PMU_PWR_MODE_EN) | BIT(PMU_CHIP_PD_EN) | + BIT(PMU_SCU_EN); + + mode_set1 = BIT(PMU_CLR_CORE) | BIT(PMU_CLR_CPUP); + + if (level == ROCKCHIP_ARM_OFF_LOGIC_DEEP) { + /* arm off, logic deep sleep */ + mode_set |= BIT(PMU_BUS_PD_EN) | + BIT(PMU_DDR1IO_RET_EN) | BIT(PMU_DDR0IO_RET_EN) | + BIT(PMU_OSC_24M_DIS) | BIT(PMU_PMU_USE_LF) | + BIT(PMU_ALIVE_USE_LF) | BIT(PMU_PLL_PD_EN); + + mode_set1 |= BIT(PMU_CLR_ALIVE) | BIT(PMU_CLR_BUS) | + BIT(PMU_CLR_PERI) | BIT(PMU_CLR_DMA); + } else { + /* + * arm off, logic normal + * if pmu_clk_core_src_gate_en is not set, + * wakeup will be error + */ + mode_set |= BIT(PMU_CLK_CORE_SRC_GATE_EN); + } + + regmap_write(pmu_regmap, RK3288_PMU_PWRMODE_CON, mode_set); + regmap_write(pmu_regmap, RK3288_PMU_PWRMODE_CON1, mode_set1); +} + +static void rk3288_slp_mode_set_resume(void) +{ + regmap_write(pmu_regmap, RK3288_PMU_PWRMODE_CON, + rk3288_pmu_pwr_mode_con); + + regmap_write(sgrf_regmap, RK3288_SGRF_SOC_CON0, + rk3288_sgrf_soc_con0 | SGRF_FAST_BOOT_EN_WRITE); +} + +static int rockchip_lpmode_enter(unsigned long arg) +{ + flush_cache_all(); + + cpu_do_idle(); + + pr_err("%s: Failed to suspend\n", __func__); + + return 1; +} + +static int rk3288_suspend_enter(suspend_state_t state) +{ + local_fiq_disable(); + + rk3288_slp_mode_set(ROCKCHIP_ARM_OFF_LOGIC_NORMAL); + + cpu_suspend(0, rockchip_lpmode_enter); + + rk3288_slp_mode_set_resume(); + + local_fiq_enable(); + + return 0; +} + +static int rk3288_suspend_prepare(void) +{ + return regulator_suspend_prepare(PM_SUSPEND_MEM); +} + +static void rk3288_suspend_finish(void) +{ + if (regulator_suspend_finish()) + pr_err("%s: Suspend finish failed\n", __func__); +} + +static int rk3288_suspend_init(struct device_node *np) +{ + struct device_node *sram_np; + struct resource res; + int ret; + + pmu_regmap = syscon_node_to_regmap(np); + if (IS_ERR(pmu_regmap)) { + pr_err("%s: could not find pmu regmap\n", __func__); + return PTR_ERR(pmu_regmap); + } + + sgrf_regmap = syscon_regmap_lookup_by_compatible( + "rockchip,rk3288-sgrf"); + if (IS_ERR(sgrf_regmap)) { + pr_err("%s: could not find sgrf regmap\n", __func__); + return PTR_ERR(pmu_regmap); + } + + sram_np = of_find_compatible_node(NULL, NULL, + "rockchip,rk3288-pmu-sram"); + if (!sram_np) { + pr_err("%s: could not find bootram dt node\n", __func__); + return -ENODEV; + } + + rk3288_bootram_base = of_iomap(sram_np, 0); + if (!rk3288_bootram_base) { + pr_err("%s: could not map bootram base\n", __func__); + return -ENOMEM; + } + + ret = of_address_to_resource(sram_np, 0, &res); + if (ret) { + pr_err("%s: could not get bootram phy addr\n", __func__); + return ret; + } + rk3288_bootram_phy = res.start; + + of_node_put(sram_np); + + rk3288_config_bootdata(); + + /* copy resume code and data to bootsram */ + memcpy(rk3288_bootram_base, rockchip_slp_cpu_resume, + rk3288_bootram_sz); + + return 0; +} + +static const struct platform_suspend_ops rk3288_suspend_ops = { + .enter = rk3288_suspend_enter, + .valid = suspend_valid_only_mem, + .prepare = rk3288_suspend_prepare, + .finish = rk3288_suspend_finish, +}; + +static const struct rockchip_pm_data rk3288_pm_data __initconst = { + .ops = &rk3288_suspend_ops, + .init = rk3288_suspend_init, +}; + +static const struct of_device_id rockchip_pmu_of_device_ids[] __initconst = { + { + .compatible = "rockchip,rk3288-pmu", + .data = &rk3288_pm_data, + }, + { /* sentinel */ }, +}; + +void __init rockchip_suspend_init(void) +{ + const struct rockchip_pm_data *pm_data; + const struct of_device_id *match; + struct device_node *np; + int ret; + + np = of_find_matching_node_and_match(NULL, rockchip_pmu_of_device_ids, + &match); + if (!match) { + pr_err("Failed to find PMU node\n"); + return; + } + pm_data = (struct rockchip_pm_data *) match->data; + + if (pm_data->init) { + ret = pm_data->init(np); + + if (ret) { + pr_err("%s: matches init error %d\n", __func__, ret); + return; + } + } + + suspend_set_ops(pm_data->ops); +} diff --git a/arch/arm/mach-rockchip/pm.h b/arch/arm/mach-rockchip/pm.h new file mode 100644 index 00000000000000..7d752ff39f91f4 --- /dev/null +++ b/arch/arm/mach-rockchip/pm.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * Author: Tony Xie + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef __MACH_ROCKCHIP_PM_H +#define __MACH_ROCKCHIP_PM_H + +extern unsigned long rkpm_bootdata_cpusp; +extern unsigned long rkpm_bootdata_cpu_code; +extern unsigned long rkpm_bootdata_l2ctlr_f; +extern unsigned long rkpm_bootdata_l2ctlr; +extern unsigned long rkpm_bootdata_ddr_code; +extern unsigned long rkpm_bootdata_ddr_data; +extern unsigned long rk3288_bootram_sz; + +void rockchip_slp_cpu_resume(void); +void __init rockchip_suspend_init(void); + +/****** following is rk3288 defined **********/ +#define RK3288_PMU_WAKEUP_CFG0 0x00 +#define RK3288_PMU_WAKEUP_CFG1 0x04 +#define RK3288_PMU_PWRMODE_CON 0x18 +#define RK3288_PMU_OSC_CNT 0x20 +#define RK3288_PMU_PLL_CNT 0x24 +#define RK3288_PMU_STABL_CNT 0x28 +#define RK3288_PMU_DDR0IO_PWRON_CNT 0x2c +#define RK3288_PMU_DDR1IO_PWRON_CNT 0x30 +#define RK3288_PMU_CORE_PWRDWN_CNT 0x34 +#define RK3288_PMU_CORE_PWRUP_CNT 0x38 +#define RK3288_PMU_GPU_PWRDWN_CNT 0x3c +#define RK3288_PMU_GPU_PWRUP_CNT 0x40 +#define RK3288_PMU_WAKEUP_RST_CLR_CNT 0x44 +#define RK3288_PMU_PWRMODE_CON1 0x90 + +#define RK3288_SGRF_SOC_CON0 (0x0000) +#define RK3288_SGRF_FAST_BOOT_ADDR (0x0120) +#define SGRF_FAST_BOOT_EN BIT(8) +#define SGRF_FAST_BOOT_EN_WRITE BIT(24) + +#define RK3288_CRU_MODE_CON 0x50 +#define RK3288_CRU_SEL0_CON 0x60 +#define RK3288_CRU_SEL1_CON 0x64 +#define RK3288_CRU_SEL10_CON 0x88 +#define RK3288_CRU_SEL33_CON 0xe4 +#define RK3288_CRU_SEL37_CON 0xf4 + +/* PMU_WAKEUP_CFG1 bits */ +#define PMU_ARMINT_WAKEUP_EN BIT(0) + +enum rk3288_pwr_mode_con { + PMU_PWR_MODE_EN = 0, + PMU_CLK_CORE_SRC_GATE_EN, + PMU_GLOBAL_INT_DISABLE, + PMU_L2FLUSH_EN, + PMU_BUS_PD_EN, + PMU_A12_0_PD_EN, + PMU_SCU_EN, + PMU_PLL_PD_EN, + PMU_CHIP_PD_EN, /* POWER OFF PIN ENABLE */ + PMU_PWROFF_COMB, + PMU_ALIVE_USE_LF, + PMU_PMU_USE_LF, + PMU_OSC_24M_DIS, + PMU_INPUT_CLAMP_EN, + PMU_WAKEUP_RESET_EN, + PMU_SREF0_ENTER_EN, + PMU_SREF1_ENTER_EN, + PMU_DDR0IO_RET_EN, + PMU_DDR1IO_RET_EN, + PMU_DDR0_GATING_EN, + PMU_DDR1_GATING_EN, + PMU_DDR0IO_RET_DE_REQ, + PMU_DDR1IO_RET_DE_REQ +}; + +enum rk3288_pwr_mode_con1 { + PMU_CLR_BUS = 0, + PMU_CLR_CORE, + PMU_CLR_CPUP, + PMU_CLR_ALIVE, + PMU_CLR_DMA, + PMU_CLR_PERI, + PMU_CLR_GPU, + PMU_CLR_VIDEO, + PMU_CLR_HEVC, + PMU_CLR_VIO, +}; + +#endif /* __MACH_ROCKCHIP_PM_H */ diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c index d226b71d21d5c6..2b68a1a70912d1 100644 --- a/arch/arm/mach-rockchip/rockchip.c +++ b/arch/arm/mach-rockchip/rockchip.c @@ -23,9 +23,11 @@ #include #include #include "core.h" +#include "pm.h" static void __init rockchip_dt_init(void) { + rockchip_suspend_init(); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); platform_device_register_simple("cpufreq-dt", 0, NULL, 0); } diff --git a/arch/arm/mach-rockchip/sleep.S b/arch/arm/mach-rockchip/sleep.S new file mode 100644 index 00000000000000..2eec9a341f05b0 --- /dev/null +++ b/arch/arm/mach-rockchip/sleep.S @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * Author: Tony Xie + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include + +.data +/* + * this code will be copied from + * ddr to sram for system resumeing. + * so it is ".data section". + */ +.align + +ENTRY(rockchip_slp_cpu_resume) + setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1 @ set svc, irqs off + mrc p15, 0, r1, c0, c0, 5 + and r1, r1, #0xf + cmp r1, #0 + /* olny cpu0 can continue to run, the others is halt here */ + beq cpu0run +secondary_loop: + wfe + b secondary_loop +cpu0run: + ldr r3, rkpm_bootdata_l2ctlr_f + cmp r3, #0 + beq sp_set + ldr r3, rkpm_bootdata_l2ctlr + mcr p15, 1, r3, c9, c0, 2 +sp_set: + ldr sp, rkpm_bootdata_cpusp + ldr r1, rkpm_bootdata_cpu_code + bx r1 +ENDPROC(rockchip_slp_cpu_resume) + +/* Parameters filled in by the kernel */ + +/* Flag for whether to restore L2CTLR on resume */ + .global rkpm_bootdata_l2ctlr_f +rkpm_bootdata_l2ctlr_f: + .long 0 + +/* Saved L2CTLR to restore on resume */ + .global rkpm_bootdata_l2ctlr +rkpm_bootdata_l2ctlr: + .long 0 + +/* CPU resume SP addr */ + .globl rkpm_bootdata_cpusp +rkpm_bootdata_cpusp: + .long 0 + +/* CPU resume function (physical address) */ + .globl rkpm_bootdata_cpu_code +rkpm_bootdata_cpu_code: + .long 0 + +ENTRY(rk3288_bootram_sz) + .word . - rockchip_slp_cpu_resume From 6744e2527ce7a3830023cec69bb2f91cf16b53ca Mon Sep 17 00:00:00 2001 From: Chris Zhong Date: Mon, 1 Dec 2014 16:52:18 +0800 Subject: [PATCH 0359/3023] ARM: rockchip: Add pmu-sram binding The pmu-sram is used to store resume code, suspend/resume need get the address of it. Therefore add a binding and documentation for it. Signed-off-by: Tony Xie Signed-off-by: Chris Zhong Reviewed-by: Doug Anderson Signed-off-by: Heiko Stuebner --- .../bindings/arm/rockchip/pmu-sram.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/rockchip/pmu-sram.txt diff --git a/Documentation/devicetree/bindings/arm/rockchip/pmu-sram.txt b/Documentation/devicetree/bindings/arm/rockchip/pmu-sram.txt new file mode 100644 index 00000000000000..6b42fda306ff61 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/rockchip/pmu-sram.txt @@ -0,0 +1,16 @@ +Rockchip SRAM for pmu: +------------------------------ + +The sram of pmu is used to store the function of resume from maskrom(the 1st +level loader). This is a common use of the "pmu-sram" because it keeps power +even in low power states in the system. + +Required node properties: +- compatible : should be "rockchip,rk3288-pmu-sram" +- reg : physical base address and the size of the registers window + +Example: + sram@ff720000 { + compatible = "rockchip,rk3288-pmu-sram", "mmio-sram"; + reg = <0xff720000 0x1000>; + }; From eecfe981cecd82791a72668a416727cb50935bdb Mon Sep 17 00:00:00 2001 From: Chris Zhong Date: Mon, 1 Dec 2014 16:52:19 +0800 Subject: [PATCH 0360/3023] ARM: dts: rockchip: add RK3288 suspend support add pmu sram node for suspend, add global_pwroff pinctrl. The pmu sram is used to store the resume code. global_pwroff is held low level at work, it would be pull to high when entering suspend. reference this in the board DTS file since some boards need it. Signed-off-by: Tony Xie Signed-off-by: Chris Zhong Reviewed-by: Doug Anderson Tested-by: Doug Anderson Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288.dtsi | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 3aad41d873d302..2a878a35faccd4 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -506,6 +506,11 @@ }; }; + sram@ff720000 { + compatible = "rockchip,rk3288-pmu-sram", "mmio-sram"; + reg = <0xff720000 0x1000>; + }; + pmu: power-management@ff730000 { compatible = "rockchip,rk3288-pmu", "syscon"; reg = <0xff730000 0x100>; @@ -729,6 +734,24 @@ bias-disable; }; + sleep { + global_pwroff: global-pwroff { + rockchip,pins = <0 0 RK_FUNC_1 &pcfg_pull_none>; + }; + + ddrio_pwroff: ddrio-pwroff { + rockchip,pins = <0 1 RK_FUNC_1 &pcfg_pull_none>; + }; + + ddr0_retention: ddr0-retention { + rockchip,pins = <0 2 RK_FUNC_1 &pcfg_pull_up>; + }; + + ddr1_retention: ddr1-retention { + rockchip,pins = <0 3 RK_FUNC_1 &pcfg_pull_up>; + }; + }; + i2c0 { i2c0_xfer: i2c0-xfer { rockchip,pins = <0 15 RK_FUNC_1 &pcfg_pull_none>, From 5963e106df7b601a8f23cbbaac1420e4c740ada6 Mon Sep 17 00:00:00 2001 From: Chris Zhong Date: Mon, 1 Dec 2014 16:52:20 +0800 Subject: [PATCH 0361/3023] ARM: dts: rockchip: add suspend settings for rk3288-evb-rk808 Add suspend-voltages and necessary pin-states for suspend on rk3288-evb-rk808 boards. global_pwroff would be pulled high when RK3288 entering suspend, this pin is a sleep signal for RK808, so RK808 could goto sleep mode, and some regulators would be disable. Signed-off-by: Chris Zhong Reviewed-by: Doug Anderson Tested-by: Doug Anderson Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288-evb-rk808.dts | 53 +++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/rk3288-evb-rk808.dts b/arch/arm/boot/dts/rk3288-evb-rk808.dts index d8c775e6d5fe7d..d453ddd4b476bb 100644 --- a/arch/arm/boot/dts/rk3288-evb-rk808.dts +++ b/arch/arm/boot/dts/rk3288-evb-rk808.dts @@ -31,7 +31,7 @@ interrupt-parent = <&gpio0>; interrupts = <4 IRQ_TYPE_LEVEL_LOW>; pinctrl-names = "default"; - pinctrl-0 = <&pmic_int>; + pinctrl-0 = <&pmic_int &global_pwroff>; rockchip,system-power-controller; wakeup-source; #clock-cells = <1>; @@ -50,6 +50,9 @@ regulator-min-microvolt = <750000>; regulator-max-microvolt = <1350000>; regulator-name = "vdd_arm"; + regulator-state-mem { + regulator-off-in-suspend; + }; }; vdd_gpu: DCDC_REG2 { @@ -58,12 +61,19 @@ regulator-min-microvolt = <850000>; regulator-max-microvolt = <1250000>; regulator-name = "vdd_gpu"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; }; vcc_ddr: DCDC_REG3 { regulator-always-on; regulator-boot-on; regulator-name = "vcc_ddr"; + regulator-state-mem { + regulator-on-in-suspend; + }; }; vcc_io: DCDC_REG4 { @@ -72,6 +82,10 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-name = "vcc_io"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; }; vccio_pmu: LDO_REG1 { @@ -80,6 +94,10 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-name = "vccio_pmu"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; }; vcc_tp: LDO_REG2 { @@ -88,6 +106,9 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-name = "vcc_tp"; + regulator-state-mem { + regulator-off-in-suspend; + }; }; vdd_10: LDO_REG3 { @@ -96,6 +117,10 @@ regulator-min-microvolt = <1000000>; regulator-max-microvolt = <1000000>; regulator-name = "vdd_10"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; }; vcc18_lcd: LDO_REG4 { @@ -104,6 +129,10 @@ regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-name = "vcc18_lcd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; }; vccio_sd: LDO_REG5 { @@ -112,6 +141,10 @@ regulator-min-microvolt = <1800000>; regulator-max-microvolt = <3300000>; regulator-name = "vccio_sd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; }; vdd10_lcd: LDO_REG6 { @@ -120,6 +153,10 @@ regulator-min-microvolt = <1000000>; regulator-max-microvolt = <1000000>; regulator-name = "vdd10_lcd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; }; vcc_18: LDO_REG7 { @@ -128,6 +165,10 @@ regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-name = "vcc_18"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; }; vcca_codec: LDO_REG8 { @@ -136,18 +177,28 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-name = "vcca_codec"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; }; vcc_wl: SWITCH_REG1 { regulator-always-on; regulator-boot-on; regulator-name = "vcc_wl"; + regulator-state-mem { + regulator-on-in-suspend; + }; }; vcc_lcd: SWITCH_REG2 { regulator-always-on; regulator-boot-on; regulator-name = "vcc_lcd"; + regulator-state-mem { + regulator-on-in-suspend; + }; }; }; }; From b0868df4339fabf3dee680818f3193af352aa25d Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Tue, 30 Dec 2014 20:57:53 +0200 Subject: [PATCH 0362/3023] iio: accel: kxcjk-1013: Add a blank line after declarations This patch fixes the following checkpatch.pl warning: WARNING: Missing a blank line after declarations Signed-off-by: Roberta Dobrescu Signed-off-by: Jonathan Cameron --- drivers/iio/accel/kxcjk-1013.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index a5e7d30bc36829..09902f4efc5ea2 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -1141,6 +1141,7 @@ static const char *kxcjk1013_match_acpi_device(struct device *dev, bool *is_smo8500_device) { const struct acpi_device_id *id; + id = acpi_match_device(dev->driver->acpi_match_table, dev); if (!id) return NULL; From c876109e66e11b85a057375d1fa15735813e5fd3 Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Tue, 30 Dec 2014 20:57:54 +0200 Subject: [PATCH 0363/3023] iio: accel: mma8452: Remove trailing whitespace This patch fixes the following checkpatch.pl error: ERROR: trailing whitespace Signed-off-by: Roberta Dobrescu Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma8452.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 3c12d496637686..5b80657883bb8f 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -111,7 +111,7 @@ static const int mma8452_samp_freq[8][2] = { {6, 250000}, {1, 560000} }; -/* +/* * Hardware has fullscale of -2G, -4G, -8G corresponding to raw value -2048 * The userspace interface uses m/s^2 and we declare micro units * So scale factor is given by: From 88f4c6c468b86c58adddc56bb2ff768d6dc0c890 Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Tue, 30 Dec 2014 20:57:55 +0200 Subject: [PATCH 0364/3023] iio: accel: Annotate Kconfig entries with module name information This patch fixes the following checkpatch.pl warning: WARNING: please write a paragraph that describes the config symbol fully Signed-off-by: Roberta Dobrescu Signed-off-by: Jonathan Cameron --- drivers/iio/accel/Kconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index d80616d77034b9..9f67c10291bd3c 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -43,6 +43,9 @@ config HID_SENSOR_ACCEL_3D Say yes here to build support for the HID SENSOR accelerometers 3D. + To compile this driver as a module, choose M here: the + module will be called hid-sensor-accel-3d. + config IIO_ST_ACCEL_3AXIS tristate "STMicroelectronics accelerometers 3-Axis Driver" depends on (I2C || SPI_MASTER) && SYSFS @@ -80,6 +83,9 @@ config KXSD9 Say yes here to build support for the Kionix KXSD9 accelerometer. Currently this only supports the device via an SPI interface. + To compile this driver as a module, choose M here: the module + will be called kxsd9. + config MMA8452 tristate "Freescale MMA8452Q Accelerometer Driver" depends on I2C From 4f51c9ada76811d344d52deccf9014d329300858 Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Tue, 30 Dec 2014 20:48:49 +0200 Subject: [PATCH 0365/3023] iio: light: Annotate Kconfig entry with module name information This patch fixes the following checkpatch.pl warning: WARNING: please write a paragraph that describes the config symbol fully Signed-off-by: Roberta Dobrescu Signed-off-by: Jonathan Cameron --- drivers/iio/light/Kconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 2e2ba12f55fcb6..5a3237b2aaa516 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -95,6 +95,9 @@ config HID_SENSOR_ALS Say yes here to build support for the HID SENSOR Ambient light sensor. + To compile this driver as a module, choose M here: the + module will be called hid-sensor-als. + config HID_SENSOR_PROX depends on HID_SENSOR_HUB select IIO_BUFFER From 586d48f92691976cc1932e2fdcbb3abd1bec8aa8 Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Tue, 30 Dec 2014 20:48:50 +0200 Subject: [PATCH 0366/3023] iio: light: lm3533-als: Remove space before ',' This patch fixes the following checkpatch.pl error: ERROR: space prohibited before that ',' (ctx:WxE) Signed-off-by: Roberta Dobrescu Signed-off-by: Jonathan Cameron --- drivers/iio/light/lm3533-als.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/light/lm3533-als.c b/drivers/iio/light/lm3533-als.c index ae3c71bdd6c6c6..076bc46fad034f 100644 --- a/drivers/iio/light/lm3533-als.c +++ b/drivers/iio/light/lm3533-als.c @@ -657,7 +657,7 @@ static ALS_HYSTERESIS_ATTR_RO(3); #define ILLUMINANCE_ATTR_RO(_name) \ DEVICE_ATTR(in_illuminance0_##_name, S_IRUGO, show_##_name, NULL) #define ILLUMINANCE_ATTR_RW(_name) \ - DEVICE_ATTR(in_illuminance0_##_name, S_IRUGO | S_IWUSR , \ + DEVICE_ATTR(in_illuminance0_##_name, S_IRUGO | S_IWUSR, \ show_##_name, store_##_name) /* * ALS Zone threshold-event enable From c5878d9dbb959538d09faf9ad5f359e645de4d95 Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Tue, 30 Dec 2014 20:45:43 +0200 Subject: [PATCH 0367/3023] iio: amplifiers: ad8366: Remove space before ',' This patch fixes the following checkpatch.pl error: ERROR: space prohibited before that ',' (ctx:WxW) Signed-off-by: Roberta Dobrescu Signed-off-by: Jonathan Cameron --- drivers/iio/amplifiers/ad8366.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/amplifiers/ad8366.c b/drivers/iio/amplifiers/ad8366.c index ba6f6a91dfffc6..fce25a0ac372fa 100644 --- a/drivers/iio/amplifiers/ad8366.c +++ b/drivers/iio/amplifiers/ad8366.c @@ -166,7 +166,7 @@ static int ad8366_probe(struct spi_device *spi) if (ret) goto error_disable_reg; - ad8366_write(indio_dev, 0 , 0); + ad8366_write(indio_dev, 0, 0); return 0; From ff6f46295d81fab7ef7379761ea87ba71cc13fce Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Tue, 30 Dec 2014 20:45:44 +0200 Subject: [PATCH 0368/3023] iio: amplifiers: ad8366: Use right order for type specification This patch fixes the following checkpatch.pl warning: WARNING: type 'char unsigned' should be specified in [[un]signed] [short|int|long|long long] order Signed-off-by: Roberta Dobrescu Signed-off-by: Jonathan Cameron --- drivers/iio/amplifiers/ad8366.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/amplifiers/ad8366.c b/drivers/iio/amplifiers/ad8366.c index fce25a0ac372fa..c0d364ebaea83e 100644 --- a/drivers/iio/amplifiers/ad8366.c +++ b/drivers/iio/amplifiers/ad8366.c @@ -31,7 +31,7 @@ struct ad8366_state { }; static int ad8366_write(struct iio_dev *indio_dev, - unsigned char ch_a, char unsigned ch_b) + unsigned char ch_a, unsigned char ch_b) { struct ad8366_state *st = iio_priv(indio_dev); int ret; From e904ce7e26c6ae84e8fb08b53cd466c0470445fd Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Tue, 30 Dec 2014 20:44:34 +0200 Subject: [PATCH 0369/3023] iio: frequency: ad9523: Increase sleep time in ad9523_store_eeprom This patch increases sleep time in ad9523_store_eeprom to 20ms since it isn't timing critical. It fixes the following checkpatch.pl warning: WARNING: msleep < 20ms can sleep for up to 20ms Signed-off-by: Roberta Dobrescu Signed-off-by: Jonathan Cameron --- drivers/iio/frequency/ad9523.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c index 7c5245d9f99ccc..50ed8d1ca45a61 100644 --- a/drivers/iio/frequency/ad9523.c +++ b/drivers/iio/frequency/ad9523.c @@ -445,7 +445,7 @@ static int ad9523_store_eeprom(struct iio_dev *indio_dev) tmp = 4; do { - msleep(16); + msleep(20); ret = ad9523_read(indio_dev, AD9523_EEPROM_DATA_XFER_STATUS); if (ret < 0) From 75d44ce08f3e5575c3060b04fa2abf99ba190284 Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Mon, 29 Dec 2014 11:50:16 +0200 Subject: [PATCH 0370/3023] staging: iio: dummy: fix compile error when not using buffering Commit 4ae03019923f ("staging:iio:dummy: Register same channels for device and buffer") has changed the number of parameters for iio_simple_dummy_configure_buffer() only for the IIO_SIMPLE_DUMMY_BUFFER case. Fix this by also changing the placeholder function declared in the header when buffering is not enabled. Signed-off-by: Vlad Dogaru Signed-off-by: Jonathan Cameron --- drivers/staging/iio/iio_simple_dummy.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/iio/iio_simple_dummy.h b/drivers/staging/iio/iio_simple_dummy.h index af7012618be63c..34989bf248a758 100644 --- a/drivers/staging/iio/iio_simple_dummy.h +++ b/drivers/staging/iio/iio_simple_dummy.h @@ -117,8 +117,7 @@ enum iio_simple_dummy_scan_elements { int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev); void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev); #else -static inline int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, unsigned int num_channels) +static inline int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) { return 0; }; From e0bed0774538bdb2e82d6999c8ed9556116e8559 Mon Sep 17 00:00:00 2001 From: Yingjoe Chen Date: Tue, 25 Nov 2014 09:04:00 +0100 Subject: [PATCH 0371/3023] ARM: mediatek: Add sysirq in mt6589/mt8135/mt8127 dtsi Add sysirq settings for mt6589/mt8135/mt8127 This also correct timer interrupt flag. The old setting works because boot loader already set polarity for timer interrupt. Without intpol support, the setting was not changed so gic can get the irq correctly. Signed-off-by: Yingjoe Chen Signed-off-by: Matthias Brugger --- arch/arm/boot/dts/mt6589.dtsi | 14 ++++++++++++-- arch/arm/boot/dts/mt8127.dtsi | 14 ++++++++++++-- arch/arm/boot/dts/mt8135.dtsi | 14 ++++++++++++-- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/mt6589.dtsi b/arch/arm/boot/dts/mt6589.dtsi index e3c7600ddb3811..c91b2a9ebdc323 100644 --- a/arch/arm/boot/dts/mt6589.dtsi +++ b/arch/arm/boot/dts/mt6589.dtsi @@ -19,7 +19,7 @@ / { compatible = "mediatek,mt6589"; - interrupt-parent = <&gic>; + interrupt-parent = <&sysirq>; cpus { #address-cells = <1>; @@ -76,15 +76,25 @@ timer: timer@10008000 { compatible = "mediatek,mt6577-timer"; reg = <0x10008000 0x80>; - interrupts = ; + interrupts = ; clocks = <&system_clk>, <&rtc_clk>; clock-names = "system-clk", "rtc-clk"; }; + sysirq: interrupt-controller@10200100 { + compatible = "mediatek,mt6589-sysirq", + "mediatek,mt6577-sysirq"; + interrupt-controller; + #interrupt-cells = <3>; + interrupt-parent = <&gic>; + reg = <0x10200100 0x1c>; + }; + gic: interrupt-controller@10211000 { compatible = "arm,cortex-a7-gic"; interrupt-controller; #interrupt-cells = <3>; + interrupt-parent = <&gic>; reg = <0x10211000 0x1000>, <0x10212000 0x1000>, <0x10214000 0x2000>, diff --git a/arch/arm/boot/dts/mt8127.dtsi b/arch/arm/boot/dts/mt8127.dtsi index b24c0a2f3c4405..a325404c714cc1 100644 --- a/arch/arm/boot/dts/mt8127.dtsi +++ b/arch/arm/boot/dts/mt8127.dtsi @@ -18,7 +18,7 @@ / { compatible = "mediatek,mt8127"; - interrupt-parent = <&gic>; + interrupt-parent = <&sysirq>; cpus { #address-cells = <1>; @@ -76,15 +76,25 @@ compatible = "mediatek,mt8127-timer", "mediatek,mt6577-timer"; reg = <0 0x10008000 0 0x80>; - interrupts = ; + interrupts = ; clocks = <&system_clk>, <&rtc_clk>; clock-names = "system-clk", "rtc-clk"; }; + sysirq: interrupt-controller@10200100 { + compatible = "mediatek,mt8127-sysirq", + "mediatek,mt6577-sysirq"; + interrupt-controller; + #interrupt-cells = <3>; + interrupt-parent = <&gic>; + reg = <0 0x10200100 0 0x1c>; + }; + gic: interrupt-controller@10211000 { compatible = "arm,cortex-a7-gic"; interrupt-controller; #interrupt-cells = <3>; + interrupt-parent = <&gic>; reg = <0 0x10211000 0 0x1000>, <0 0x10212000 0 0x1000>, <0 0x10214000 0 0x2000>, diff --git a/arch/arm/boot/dts/mt8135.dtsi b/arch/arm/boot/dts/mt8135.dtsi index 7d56a986358e6d..2762fd57f739ed 100644 --- a/arch/arm/boot/dts/mt8135.dtsi +++ b/arch/arm/boot/dts/mt8135.dtsi @@ -18,7 +18,7 @@ / { compatible = "mediatek,mt8135"; - interrupt-parent = <&gic>; + interrupt-parent = <&sysirq>; cpu-map { cluster0 { @@ -98,15 +98,25 @@ compatible = "mediatek,mt8135-timer", "mediatek,mt6577-timer"; reg = <0 0x10008000 0 0x80>; - interrupts = ; + interrupts = ; clocks = <&system_clk>, <&rtc_clk>; clock-names = "system-clk", "rtc-clk"; }; + sysirq: interrupt-controller@10200030 { + compatible = "mediatek,mt8135-sysirq", + "mediatek,mt6577-sysirq"; + interrupt-controller; + #interrupt-cells = <3>; + interrupt-parent = <&gic>; + reg = <0 0x10200030 0 0x1c>; + }; + gic: interrupt-controller@10211000 { compatible = "arm,cortex-a15-gic"; interrupt-controller; #interrupt-cells = <3>; + interrupt-parent = <&gic>; reg = <0 0x10211000 0 0x1000>, <0 0x10212000 0 0x1000>, <0 0x10214000 0 0x2000>, From 7bae74f04d03f81c40c8b614e94b15975dd25ff6 Mon Sep 17 00:00:00 2001 From: Eddie Huang Date: Fri, 26 Dec 2014 10:55:00 +0100 Subject: [PATCH 0372/3023] ARM: Add mediatek SoC UART support in defconfig Add mediatek SoC UART support in multi_v7_defconfig Signed-off-by: Eddie Huang Signed-off-by: Matthias Brugger --- arch/arm/configs/multi_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 2328fe752e9c5e..fd0ff955b2dd5a 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -195,6 +195,7 @@ CONFIG_SERIO_AMBAKMI=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_8250_MT6577=y CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y CONFIG_SERIAL_MESON=y From 0714947369cdb2b9b8cc24aa07264d4b61ea4fd9 Mon Sep 17 00:00:00 2001 From: Eddie Huang Date: Wed, 22 Oct 2014 15:12:00 +0200 Subject: [PATCH 0373/3023] ARM: mediatek: add UART dts for mt8127 and mt8135 This add dts support for mt8127 and mt8135 SOC UART Signed-off-by: Eddie Huang Signed-off-by: Matthias Brugger --- arch/arm/boot/dts/mt8127.dtsi | 38 +++++++++++++++++++++++++++++++++ arch/arm/boot/dts/mt8135.dtsi | 40 +++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/arch/arm/boot/dts/mt8127.dtsi b/arch/arm/boot/dts/mt8127.dtsi index a325404c714cc1..aaa786233d934e 100644 --- a/arch/arm/boot/dts/mt8127.dtsi +++ b/arch/arm/boot/dts/mt8127.dtsi @@ -64,6 +64,12 @@ clock-frequency = <32000>; #clock-cells = <0>; }; + + uart_clk: dummy26m { + compatible = "fixed-clock"; + clock-frequency = <26000000>; + #clock-cells = <0>; + }; }; soc { @@ -100,5 +106,37 @@ <0 0x10214000 0 0x2000>, <0 0x10216000 0 0x2000>; }; + + uart0: serial@11006000 { + compatible = "mediatek,mt8127-uart","mediatek,mt6577-uart"; + reg = <0 0x11002000 0 0x400>; + interrupts = ; + clocks = <&uart_clk>; + status = "disabled"; + }; + + uart1: serial@11007000 { + compatible = "mediatek,mt8127-uart","mediatek,mt6577-uart"; + reg = <0 0x11003000 0 0x400>; + interrupts = ; + clocks = <&uart_clk>; + status = "disabled"; + }; + + uart2: serial@11008000 { + compatible = "mediatek,mt8127-uart","mediatek,mt6577-uart"; + reg = <0 0x11004000 0 0x400>; + interrupts = ; + clocks = <&uart_clk>; + status = "disabled"; + }; + + uart3: serial@11009000 { + compatible = "mediatek,mt8127-uart","mediatek,mt6577-uart"; + reg = <0 0x11005000 0 0x400>; + interrupts = ; + clocks = <&uart_clk>; + status = "disabled"; + }; }; }; diff --git a/arch/arm/boot/dts/mt8135.dtsi b/arch/arm/boot/dts/mt8135.dtsi index 2762fd57f739ed..a161e99ffcc432 100644 --- a/arch/arm/boot/dts/mt8135.dtsi +++ b/arch/arm/boot/dts/mt8135.dtsi @@ -86,6 +86,13 @@ clock-frequency = <32000>; #clock-cells = <0>; }; + + uart_clk: dummy26m { + compatible = "fixed-clock"; + clock-frequency = <26000000>; + #clock-cells = <0>; + }; + }; soc { @@ -122,5 +129,38 @@ <0 0x10214000 0 0x2000>, <0 0x10216000 0 0x2000>; }; + + uart0: serial@11006000 { + compatible = "mediatek,mt8135-uart","mediatek,mt6577-uart"; + reg = <0 0x11006000 0 0x400>; + interrupts = ; + clocks = <&uart_clk>; + status = "disabled"; + }; + + uart1: serial@11007000 { + compatible = "mediatek,mt8135-uart","mediatek,mt6577-uart"; + reg = <0 0x11007000 0 0x400>; + interrupts = ; + clocks = <&uart_clk>; + status = "disabled"; + }; + + uart2: serial@11008000 { + compatible = "mediatek,mt8135-uart","mediatek,mt6577-uart"; + reg = <0 0x11008000 0 0x400>; + interrupts = ; + clocks = <&uart_clk>; + status = "disabled"; + }; + + uart3: serial@11009000 { + compatible = "mediatek,mt8135-uart","mediatek,mt6577-uart"; + reg = <0 0x11009000 0 0x400>; + interrupts = ; + clocks = <&uart_clk>; + status = "disabled"; + }; + }; }; From ab407df736c1d8263fc92a35589fb54854f627b3 Mon Sep 17 00:00:00 2001 From: Eddie Huang Date: Wed, 22 Oct 2014 15:12:00 +0200 Subject: [PATCH 0374/3023] DTS: serial: Add bindings document for the Mediatek UARTs This patch add s devicetree document for Mediatek UART. Signed-off-by: Eddie Huang Signed-off-by: Matthias Brugger --- Documentation/devicetree/bindings/serial/mtk-uart.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/serial/mtk-uart.txt b/Documentation/devicetree/bindings/serial/mtk-uart.txt index 48358a33ea7dff..0eebbfea91a483 100644 --- a/Documentation/devicetree/bindings/serial/mtk-uart.txt +++ b/Documentation/devicetree/bindings/serial/mtk-uart.txt @@ -2,6 +2,8 @@ Required properties: - compatible should contain: + * "mediatek,mt8135-uart" for MT8135 compatible UARTS + * "mediatek,mt8127-uart" for MT8127 compatible UARTS * "mediatek,mt6589-uart" for MT6589 compatible UARTS * "mediatek,mt6582-uart" for MT6582 compatible UARTS * "mediatek,mt6577-uart" for all compatible UARTS (MT6589, MT6582, MT6577) From 1471f09f9b874e3bd6a439cae7fc34261dc6f7dd Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 5 Jan 2015 10:44:09 +1100 Subject: [PATCH 0375/3023] Revert "crypto: drbg - use memzero_explicit() for clearing sensitive data" This reverts commit 421d82f5b3e75f94e31875e37d45cdf6a557c120. None of the data zeroed are on the stack so the compiler cannot optimise them away. Signed-off-by: Herbert Xu --- crypto/drbg.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index 96138396ce019d..d8ff16e5c32248 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -98,7 +98,6 @@ */ #include -#include /*************************************************************** * Backend cipher definitions available to DRBG @@ -491,9 +490,9 @@ static int drbg_ctr_df(struct drbg_state *drbg, ret = 0; out: - memzero_explicit(iv, drbg_blocklen(drbg)); - memzero_explicit(temp, drbg_statelen(drbg)); - memzero_explicit(pad, drbg_blocklen(drbg)); + memset(iv, 0, drbg_blocklen(drbg)); + memset(temp, 0, drbg_statelen(drbg)); + memset(pad, 0, drbg_blocklen(drbg)); return ret; } @@ -567,9 +566,9 @@ static int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed, ret = 0; out: - memzero_explicit(temp, drbg_statelen(drbg) + drbg_blocklen(drbg)); + memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg)); if (2 != reseed) - memzero_explicit(df_data, drbg_statelen(drbg)); + memset(df_data, 0, drbg_statelen(drbg)); return ret; } @@ -627,7 +626,7 @@ static int drbg_ctr_generate(struct drbg_state *drbg, len = ret; out: - memzero_explicit(drbg->scratchpad, drbg_blocklen(drbg)); + memset(drbg->scratchpad, 0, drbg_blocklen(drbg)); return len; } @@ -865,7 +864,7 @@ static int drbg_hash_df(struct drbg_state *drbg, } out: - memzero_explicit(tmp, drbg_blocklen(drbg)); + memset(tmp, 0, drbg_blocklen(drbg)); return ret; } @@ -909,7 +908,7 @@ static int drbg_hash_update(struct drbg_state *drbg, struct list_head *seed, ret = drbg_hash_df(drbg, drbg->C, drbg_statelen(drbg), &datalist2); out: - memzero_explicit(drbg->scratchpad, drbg_statelen(drbg)); + memset(drbg->scratchpad, 0, drbg_statelen(drbg)); return ret; } @@ -944,7 +943,7 @@ static int drbg_hash_process_addtl(struct drbg_state *drbg, drbg->scratchpad, drbg_blocklen(drbg)); out: - memzero_explicit(drbg->scratchpad, drbg_blocklen(drbg)); + memset(drbg->scratchpad, 0, drbg_blocklen(drbg)); return ret; } @@ -991,7 +990,7 @@ static int drbg_hash_hashgen(struct drbg_state *drbg, } out: - memzero_explicit(drbg->scratchpad, + memset(drbg->scratchpad, 0, (drbg_statelen(drbg) + drbg_blocklen(drbg))); return len; } @@ -1040,7 +1039,7 @@ static int drbg_hash_generate(struct drbg_state *drbg, drbg_add_buf(drbg->V, drbg_statelen(drbg), u.req, 8); out: - memzero_explicit(drbg->scratchpad, drbg_blocklen(drbg)); + memset(drbg->scratchpad, 0, drbg_blocklen(drbg)); return len; } From b0f2faa5ca02358ebfe404801e2ad604dc88c471 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 17 Dec 2014 18:18:14 +0100 Subject: [PATCH 0376/3023] ARM: sunxi: Add "allwinner,sun6i-a31s" to mach-sunxi So far the A31s is 100% compatible with the A31, still lets do the same as what we've done for the A13 / A10s and give it its own compatible string, in case we need to differentiate later. Signed-off-by: Hans de Goede [Maxime: Removed unusude CPU_OF_DECLARE_METHOD] Signed-off-by: Maxime Ripard --- Documentation/arm/sunxi/README | 1 - arch/arm/mach-sunxi/platsmp.c | 2 +- arch/arm/mach-sunxi/sunxi.c | 1 + drivers/clk/sunxi/clk-sunxi.c | 1 + 4 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/arm/sunxi/README b/Documentation/arm/sunxi/README index e68d163df33dbc..1fe2d7fd4108ff 100644 --- a/Documentation/arm/sunxi/README +++ b/Documentation/arm/sunxi/README @@ -50,7 +50,6 @@ SunXi family http://dl.linux-sunxi.org/A31/A3x_release_document/A31/IC/A31%20user%20manual%20V1.1%2020130630.pdf - Allwinner A31s (sun6i) - + Not Supported + Datasheet http://dl.linux-sunxi.org/A31/A3x_release_document/A31s/IC/A31s%20datasheet%20V1.3%2020131106.pdf + User Manual diff --git a/arch/arm/mach-sunxi/platsmp.c b/arch/arm/mach-sunxi/platsmp.c index e44d028555a497..587b0468efcc30 100644 --- a/arch/arm/mach-sunxi/platsmp.c +++ b/arch/arm/mach-sunxi/platsmp.c @@ -120,4 +120,4 @@ static struct smp_operations sun6i_smp_ops __initdata = { .smp_prepare_cpus = sun6i_smp_prepare_cpus, .smp_boot_secondary = sun6i_smp_boot_secondary, }; -CPU_METHOD_OF_DECLARE(sun6i_smp, "allwinner,sun6i-a31", &sun6i_smp_ops); +CPU_METHOD_OF_DECLARE(sun6i_a31_smp, "allwinner,sun6i-a31", &sun6i_smp_ops); diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c index 1f986758784a1d..d4bb2395d39cc2 100644 --- a/arch/arm/mach-sunxi/sunxi.c +++ b/arch/arm/mach-sunxi/sunxi.c @@ -29,6 +29,7 @@ MACHINE_END static const char * const sun6i_board_dt_compat[] = { "allwinner,sun6i-a31", + "allwinner,sun6i-a31s", NULL, }; diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 570202582dcfef..1818f404538d37 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -1226,6 +1226,7 @@ static void __init sun6i_init_clocks(struct device_node *node) ARRAY_SIZE(sun6i_critical_clocks)); } CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks); +CLK_OF_DECLARE(sun6i_a31s_clk_init, "allwinner,sun6i-a31s", sun6i_init_clocks); CLK_OF_DECLARE(sun8i_a23_clk_init, "allwinner,sun8i-a23", sun6i_init_clocks); static void __init sun9i_init_clocks(struct device_node *node) From 4c1ada872d3217c506c76f48a21decffe16c4ed4 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Thu, 1 Jan 2015 16:13:47 +0100 Subject: [PATCH 0377/3023] crypto: amcc - Remove unused function Remove the function get_dynamic_sa_offset_iv_field() that is not used anywhere. This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Herbert Xu --- drivers/crypto/amcc/crypto4xx_sa.c | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/drivers/crypto/amcc/crypto4xx_sa.c b/drivers/crypto/amcc/crypto4xx_sa.c index de8a7a48775abe..69182e2cc3ea8a 100644 --- a/drivers/crypto/amcc/crypto4xx_sa.c +++ b/drivers/crypto/amcc/crypto4xx_sa.c @@ -34,29 +34,6 @@ #include "crypto4xx_sa.h" #include "crypto4xx_core.h" -u32 get_dynamic_sa_offset_iv_field(struct crypto4xx_ctx *ctx) -{ - u32 offset; - union dynamic_sa_contents cts; - - if (ctx->direction == DIR_INBOUND) - cts.w = ((struct dynamic_sa_ctl *)(ctx->sa_in))->sa_contents; - else - cts.w = ((struct dynamic_sa_ctl *)(ctx->sa_out))->sa_contents; - offset = cts.bf.key_size - + cts.bf.inner_size - + cts.bf.outer_size - + cts.bf.spi - + cts.bf.seq_num0 - + cts.bf.seq_num1 - + cts.bf.seq_num_mask0 - + cts.bf.seq_num_mask1 - + cts.bf.seq_num_mask2 - + cts.bf.seq_num_mask3; - - return sizeof(struct dynamic_sa_ctl) + offset * 4; -} - u32 get_dynamic_sa_offset_state_ptr_field(struct crypto4xx_ctx *ctx) { u32 offset; From 28c29f5657e886cf89778622af3f6569329508df Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Fri, 2 Jan 2015 12:40:46 +0900 Subject: [PATCH 0378/3023] crypto: bfin_crc - Remove unnecessary KERN_ERR in bfin_crc.c This patch removes unnecessary KERN_ERR from bfin_crypto_crc_mod_init(). Signed-off-by: Masanari Iida Signed-off-by: Herbert Xu --- drivers/crypto/bfin_crc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/bfin_crc.c b/drivers/crypto/bfin_crc.c index 9ae149bddb6e32..33cf9eb87344d6 100644 --- a/drivers/crypto/bfin_crc.c +++ b/drivers/crypto/bfin_crc.c @@ -744,7 +744,7 @@ static int __init bfin_crypto_crc_mod_init(void) ret = platform_driver_register(&bfin_crypto_crc_driver); if (ret) { - pr_info(KERN_ERR "unable to register driver\n"); + pr_err("unable to register driver\n"); return ret; } From 985782d1241718c632839a284d07e84be3bb344c Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Thu, 27 Nov 2014 21:33:59 +0100 Subject: [PATCH 0379/3023] apf27dev: add max5821 to the dts Signed-off-by: Philippe Reynes Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx27-apf27dev.dts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/arch/arm/boot/dts/imx27-apf27dev.dts b/arch/arm/boot/dts/imx27-apf27dev.dts index da306c5dd67828..bba3f41b89ef68 100644 --- a/arch/arm/boot/dts/imx27-apf27dev.dts +++ b/arch/arm/boot/dts/imx27-apf27dev.dts @@ -59,6 +59,21 @@ linux,default-trigger = "heartbeat"; }; }; + + regulators { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + reg_max5821: regulator@0 { + compatible = "regulator-fixed"; + reg = <0>; + regulator-name = "max5821-reg"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + }; + }; }; &cspi1 { @@ -107,6 +122,12 @@ compatible = "dallas,ds1374"; reg = <0x68>; }; + + max5821@38 { + compatible = "maxim,max5821"; + reg = <0x38>; + vref-supply = <®_max5821>; + }; }; &i2c2 { From c134e09fc59381ffd445922019b72aed998bdc8f Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 28 Nov 2014 00:35:36 +0100 Subject: [PATCH 0380/3023] ARM: dts: vf610: enable watchdog for Cortex-A5 dt's During restructuring of the device tree files the watchdog was changed to be disabled by default. However, since the watchdog instance is dedicated to the Cortex-A5, enable the peripheral by default in the base device tree vf500.dtsi. Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- arch/arm/boot/dts/vf500.dtsi | 5 +++++ arch/arm/boot/dts/vfxxx.dtsi | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/vf500.dtsi b/arch/arm/boot/dts/vf500.dtsi index de67005427142f..ea0f74f6eeb3a7 100644 --- a/arch/arm/boot/dts/vf500.dtsi +++ b/arch/arm/boot/dts/vf500.dtsi @@ -169,3 +169,8 @@ &usbphy1 { interrupts = ; }; + +&wdoga5 { + interrupts = ; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi index 505969ae8093d1..712646814cc6af 100644 --- a/arch/arm/boot/dts/vfxxx.dtsi +++ b/arch/arm/boot/dts/vfxxx.dtsi @@ -184,7 +184,7 @@ status = "disabled"; }; - wdog@4003e000 { + wdoga5: wdog@4003e000 { compatible = "fsl,vf610-wdt", "fsl,imx21-wdt"; reg = <0x4003e000 0x1000>; clocks = <&clks VF610_CLK_WDT>; From eddb00fa125bb77452dd875e7d8170c8d3c4d546 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 28 Nov 2014 00:40:06 +0100 Subject: [PATCH 0381/3023] ARM: dts: vf-colibri: add CLKOUT pin to pinctrl of FEC1 On the Colibri module, the RMII clock for the Ethernet PHY is generated by the SoC. This patch adds that missing pin to the pinctrl of FEC1. Because the boot loader initializes this pin, ethernet worked even without this pin so far. Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- arch/arm/boot/dts/vf-colibri.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/vf-colibri.dtsi b/arch/arm/boot/dts/vf-colibri.dtsi index 82f5728be5c9d1..95b6ff222eee09 100644 --- a/arch/arm/boot/dts/vf-colibri.dtsi +++ b/arch/arm/boot/dts/vf-colibri.dtsi @@ -121,6 +121,7 @@ pinctrl_fec1: fec1grp { fsl,pins = < + VF610_PAD_PTA6__RMII_CLKOUT 0x30d2 VF610_PAD_PTC9__ENET_RMII1_MDC 0x30d2 VF610_PAD_PTC10__ENET_RMII1_MDIO 0x30d3 VF610_PAD_PTC11__ENET_RMII1_CRS 0x30d1 From 7194661924531d02935bc752238202299bb0dcb1 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 27 Nov 2014 10:18:19 -0200 Subject: [PATCH 0382/3023] ARM: dts: imx: Update VPU compatible strings Update the VPU compatible strings to also use "cnm,coda". Signed-off-by: Fabio Estevam Acked-by: Philipp Zabel Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx27.dtsi | 2 +- arch/arm/boot/dts/imx53.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi index 107d713e1cbecd..4b063b68db44cb 100644 --- a/arch/arm/boot/dts/imx27.dtsi +++ b/arch/arm/boot/dts/imx27.dtsi @@ -464,7 +464,7 @@ }; coda: coda@10023000 { - compatible = "fsl,imx27-vpu"; + compatible = "fsl,imx27-vpu", "cnm,codadx6"; reg = <0x10023000 0x0200>; interrupts = <53>; clocks = <&clks IMX27_CLK_VPU_BAUD_GATE>, diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi index a30bddfdbdb6e5..b96213ba067158 100644 --- a/arch/arm/boot/dts/imx53.dtsi +++ b/arch/arm/boot/dts/imx53.dtsi @@ -756,7 +756,7 @@ }; vpu: vpu@63ff4000 { - compatible = "fsl,imx53-vpu"; + compatible = "fsl,imx53-vpu", "cnm,coda7541"; reg = <0x63ff4000 0x1000>; interrupts = <9>; clocks = <&clks IMX5_CLK_VPU_REFERENCE_GATE>, From 0d018d7387bd3c2d25ca7ed1a6b3631c071cd918 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 2 Dec 2014 18:11:59 +0100 Subject: [PATCH 0383/3023] ARM: dts: vf610: add system reset controller and syscon-reboot Add the system reset controller (SRC) module and use syscon-reboot to register a restart handler which restarts the SoC using the SRC SW_RST bit. Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- arch/arm/boot/dts/vf500.dtsi | 4 ++++ arch/arm/boot/dts/vfxxx.dtsi | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/arch/arm/boot/dts/vf500.dtsi b/arch/arm/boot/dts/vf500.dtsi index ea0f74f6eeb3a7..29016090d0601b 100644 --- a/arch/arm/boot/dts/vf500.dtsi +++ b/arch/arm/boot/dts/vf500.dtsi @@ -130,6 +130,10 @@ interrupts = ; }; +&src { + interrupts = ; +}; + &uart0 { interrupts = ; }; diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi index 712646814cc6af..a55e1f9a414d6a 100644 --- a/arch/arm/boot/dts/vfxxx.dtsi +++ b/arch/arm/boot/dts/vfxxx.dtsi @@ -43,6 +43,13 @@ clock-frequency = <32768>; }; + reboot: syscon-reboot { + compatible = "syscon-reboot"; + regmap = <&src>; + offset = <0x0>; + mask = <0x1000>; + }; + soc { #address-cells = <1>; #size-cells = <1>; @@ -318,6 +325,11 @@ clocks = <&clks VF610_CLK_USBC0>; status = "disabled"; }; + + src: src@4006e000 { + compatible = "fsl,vf610-src", "syscon"; + reg = <0x4006e000 0x1000>; + }; }; aips1: aips-bus@40080000 { From d951534606661349a95b707111fdd04cecda62c8 Mon Sep 17 00:00:00 2001 From: Eric Nelson Date: Tue, 2 Dec 2014 15:37:16 -0700 Subject: [PATCH 0384/3023] ARM: dts: sabrelite: add i2c2 Signed-off-by: Eric Nelson Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-sabrelite.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi index 0a36129152e0ce..37f53f3ddcb86b 100644 --- a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi +++ b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi @@ -188,6 +188,13 @@ }; }; +&i2c2 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + status = "okay"; +}; + &iomuxc { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_hog>; @@ -265,6 +272,13 @@ >; }; + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 + MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 + >; + }; + pinctrl_pwm1: pwm1grp { fsl,pins = < MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1 From 8eedffe54e92a8e3345fad7a4463d81364d6c452 Mon Sep 17 00:00:00 2001 From: Eric Nelson Date: Tue, 2 Dec 2014 15:37:17 -0700 Subject: [PATCH 0385/3023] ARM: dts: sabrelite: add hdmi Signed-off-by: Eric Nelson Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-sabrelite.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi index 37f53f3ddcb86b..3bddc8fe8144bc 100644 --- a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi +++ b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi @@ -173,6 +173,11 @@ status = "okay"; }; +&hdmi { + ddc-i2c-bus = <&i2c2>; + status = "okay"; +}; + &i2c1 { clock-frequency = <100000>; pinctrl-names = "default"; From 0a3e41ff90a53360bb4c39e1e45f4b4ac5949fef Mon Sep 17 00:00:00 2001 From: Eric Nelson Date: Tue, 2 Dec 2014 15:37:18 -0700 Subject: [PATCH 0386/3023] ARM: dts: sabrelite: add i2c3 Signed-off-by: Eric Nelson Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-sabrelite.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi index 3bddc8fe8144bc..0b28a9d5241e5b 100644 --- a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi +++ b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi @@ -200,6 +200,13 @@ status = "okay"; }; +&i2c3 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c3>; + status = "okay"; +}; + &iomuxc { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_hog>; @@ -284,6 +291,13 @@ >; }; + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1 + MX6QDL_PAD_GPIO_16__I2C3_SDA 0x4001b8b1 + >; + }; + pinctrl_pwm1: pwm1grp { fsl,pins = < MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1 From eabb3227d912f554237bf2a0920108cb6e372eb0 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Fri, 5 Dec 2014 16:23:48 +0800 Subject: [PATCH 0387/3023] ARM: dts: imx6q: update cpufreq volt/freq table According to latest i.MX6Q datasheet Rev. 3, 02/2014, the latest cpufreq volt/freq table is as below: LDO enabled/bypassed(min value): 996MHz: VDDARM: 1.225V, VDDSOC: 1.150V; 792MHz: VDDARM: 1.150V, VDDSOC: 1.150V; 396MHz: VDDARM: 0.925V, VDDSOC: 1.150V; the 792MHz setpoint's VDDARM min voltage is updated from 1.125V to 1.150V, adding 25mV to cover board IR drop, 1.175V is the right voltage we should use. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6q.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index 85f72e6b5badeb..37ee4e58891017 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -31,7 +31,7 @@ 1200000 1275000 996000 1250000 852000 1250000 - 792000 1150000 + 792000 1175000 396000 975000 >; fsl,soc-operating-points = < From 4c61a1e75cd9247c624de8481efe85208b97ac85 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Fri, 5 Dec 2014 16:23:49 +0800 Subject: [PATCH 0388/3023] ARM: dts: imx6dl: correct cpufreq volt/freq table Currently the cpufreq volt/freq table we used is for LDO enable mode, according to latest datasheet Rev. 3, 03/2014, the volt/freq table is as below: LDO enabled(min value): 996MHz: VDDARM: 1.225V, VDDSOC: 1.150V; 792MHz: VDDARM: 1.150V, VDDSOC: 1.150V; 396MHz: VDDARM: 1.050V, VDDSOC: 1.150V; LDO bypassed(min value): 996MHz: VDDARM: 1.250V, VDDSOC: 1.150V; 792MHz: VDDARM: 1.150V, VDDSOC: 1.150V; 396MHz: VDDARM: 1.050V, VDDSOC: 1.150V; Adding 25mV to cover board IR drop, for LDO enabled mode of 996MHz, VDDARM should be 1.250V, so this patch updates it. Signed-off-by: Anson Huang Reviewed-by: Philipp Zabel Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6dl.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi index 1ac2fe7328679b..f94bf72832af89 100644 --- a/arch/arm/boot/dts/imx6dl.dtsi +++ b/arch/arm/boot/dts/imx6dl.dtsi @@ -28,7 +28,7 @@ next-level-cache = <&L2>; operating-points = < /* kHz uV */ - 996000 1275000 + 996000 1250000 792000 1175000 396000 1075000 >; From 60811cc24e6101717928ef3e27fe7bcd8f342a9f Mon Sep 17 00:00:00 2001 From: Steffen Trumtrar Date: Tue, 9 Dec 2014 09:56:52 +0100 Subject: [PATCH 0389/3023] ARM: i.MX53: dts: add sahara module The i.MX53 has a SAHARA v4 core. Add it to the dtsi. Signed-off-by: Steffen Trumtrar Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx53.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi index b96213ba067158..ff4fa7ecacd86e 100644 --- a/arch/arm/boot/dts/imx53.dtsi +++ b/arch/arm/boot/dts/imx53.dtsi @@ -765,6 +765,15 @@ resets = <&src 1>; iram = <&ocram>; }; + + sahara: crypto@63ff8000 { + compatible = "fsl,imx53-sahara"; + reg = <0x63ff8000 0x4000>; + interrupts = <19 20>; + clocks = <&clks IMX5_CLK_SAHARA_IPG_GATE>, + <&clks IMX5_CLK_SAHARA_IPG_GATE>; + clock-names = "ipg", "ahb"; + }; }; ocram: sram@f8000000 { From 44ae1244ae787dfcf767b179dbd5ca7c06c418e8 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 2 Dec 2014 18:12:00 +0100 Subject: [PATCH 0390/3023] ARM: imx_v6_v7_defconfig: add POWER_RESET_SYSCON Add POWER_RESET_SYSCON since Vybrid SoC's now make use of this driver to provide software reset capabilities through the SRC module. Also regenerated using savedefconfig which removed the config BACKLIGHT_LCD_SUPPORT which is now selected by default since commit 9c8ee3c734139 ("video: mx3fb: always enable BACKLIGHT_LCD_SUPPORT"). Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- arch/arm/configs/imx_v6_v7_defconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 7c2075a07ebadb..96ac3a7d560935 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -163,13 +163,14 @@ CONFIG_SPI_IMX=y CONFIG_GPIO_SYSFS=y CONFIG_GPIO_MC9S08DZ60=y CONFIG_GPIO_STMPE=y +CONFIG_POWER_SUPPLY=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_IMX=y +CONFIG_POWER_RESET_SYSCON=y CONFIG_SENSORS_GPIO_FAN=y CONFIG_THERMAL=y CONFIG_CPU_THERMAL=y CONFIG_IMX_THERMAL=y -CONFIG_POWER_SUPPLY=y -CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_IMX=y CONFIG_WATCHDOG=y CONFIG_IMX2_WDT=y CONFIG_MFD_DA9052_I2C=y @@ -198,7 +199,6 @@ CONFIG_SOC_CAMERA_OV2640=y CONFIG_IMX_IPUV3_CORE=y CONFIG_DRM=y CONFIG_DRM_PANEL_SIMPLE=y -CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_LCD_CLASS_DEVICE=y CONFIG_LCD_L4F00242T03=y CONFIG_LCD_PLATFORM=y From da06aae8b5cae1bd0ac5b7518c9693fe07c06488 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 28 Nov 2014 00:27:05 +0100 Subject: [PATCH 0391/3023] ARM vf610: add compatibilty strings of supported Vybrid SoC's The Vybrid SoC family (in the kernel known as vf610) is a familiy of multiple similar SoC's. The VF5xx series comes without secondary Cortex-M4 core, while the second number VFx1x indicates the presence of a L2 cache controller. Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/arm/fsl.txt | 12 ++++++++++++ arch/arm/mach-imx/mach-vf610.c | 5 ++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/arm/fsl.txt b/Documentation/devicetree/bindings/arm/fsl.txt index 4e8b7df7fc62d8..c830b5b65882b0 100644 --- a/Documentation/devicetree/bindings/arm/fsl.txt +++ b/Documentation/devicetree/bindings/arm/fsl.txt @@ -75,6 +75,18 @@ i.MX6q generic board Required root node properties: - compatible = "fsl,imx6q"; +Freescale Vybrid Platform Device Tree Bindings +---------------------------------------------- + +For the Vybrid SoC familiy all variants with DDR controller are supported, +which is the VF5xx and VF6xx series. Out of historical reasons, in most +places the kernel uses vf610 to refer to the whole familiy. + +Required root node compatible property (one of them): + - compatible = "fsl,vf500"; + - compatible = "fsl,vf510"; + - compatible = "fsl,vf600"; + - compatible = "fsl,vf610"; Freescale LS1021A Platform Device Tree Bindings ------------------------------------------------ diff --git a/arch/arm/mach-imx/mach-vf610.c b/arch/arm/mach-imx/mach-vf610.c index c11ab6a1dc87f7..2e7c75b66fe034 100644 --- a/arch/arm/mach-imx/mach-vf610.c +++ b/arch/arm/mach-imx/mach-vf610.c @@ -13,11 +13,14 @@ #include static const char * const vf610_dt_compat[] __initconst = { + "fsl,vf500", + "fsl,vf510", + "fsl,vf600", "fsl,vf610", NULL, }; -DT_MACHINE_START(VYBRID_VF610, "Freescale Vybrid VF610 (Device Tree)") +DT_MACHINE_START(VYBRID_VF610, "Freescale Vybrid VF5xx/VF6xx (Device Tree)") .l2c_aux_val = 0, .l2c_aux_mask = ~0, .dt_compat = vf610_dt_compat, From 60ad8467c1bf0cae19ccc9d142914a2288ac85e7 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 2 Dec 2014 17:59:42 +0100 Subject: [PATCH 0392/3023] ARM: imx: pllv3: add shift for frequency multiplier Add shift capabilties for the frequency multiplier (DIV_SELECT) to support Vybrid's USB PLL oddity. The PLL3 and PLL7 are the only PLL control registers which have the DIV_SELECT bit shifted by one. Be aware, there are known documentation errors in the reference manual too. Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- arch/arm/mach-imx/clk-pllv3.c | 10 +++++++--- arch/arm/mach-imx/clk-vf610.c | 4 ++-- arch/arm/mach-imx/clk.h | 1 + 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-imx/clk-pllv3.c b/arch/arm/mach-imx/clk-pllv3.c index 0ad6e5442fd8cc..641ebc50892044 100644 --- a/arch/arm/mach-imx/clk-pllv3.c +++ b/arch/arm/mach-imx/clk-pllv3.c @@ -31,6 +31,7 @@ * @base: base address of PLL registers * @powerup_set: set POWER bit to power up the PLL * @div_mask: mask of divider bits + * @div_shift: shift of divider bits * * IMX PLL clock version 3, found on i.MX6 series. Divider for pllv3 * is actually a multiplier, and always sits at bit 0. @@ -40,6 +41,7 @@ struct clk_pllv3 { void __iomem *base; bool powerup_set; u32 div_mask; + u32 div_shift; }; #define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw) @@ -97,7 +99,7 @@ static unsigned long clk_pllv3_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_pllv3 *pll = to_clk_pllv3(hw); - u32 div = readl_relaxed(pll->base) & pll->div_mask; + u32 div = (readl_relaxed(pll->base) >> pll->div_shift) & pll->div_mask; return (div == 1) ? parent_rate * 22 : parent_rate * 20; } @@ -125,8 +127,8 @@ static int clk_pllv3_set_rate(struct clk_hw *hw, unsigned long rate, return -EINVAL; val = readl_relaxed(pll->base); - val &= ~pll->div_mask; - val |= div; + val &= ~(pll->div_mask << pll->div_shift); + val |= (div << pll->div_shift); writel_relaxed(val, pll->base); return clk_pllv3_wait_lock(pll); @@ -295,6 +297,8 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, case IMX_PLLV3_SYS: ops = &clk_pllv3_sys_ops; break; + case IMX_PLLV3_USB_VF610: + pll->div_shift = 1; case IMX_PLLV3_USB: ops = &clk_pllv3_ops; pll->powerup_set = true; diff --git a/arch/arm/mach-imx/clk-vf610.c b/arch/arm/mach-imx/clk-vf610.c index 5937ddee1a99ae..cb21777c3ab635 100644 --- a/arch/arm/mach-imx/clk-vf610.c +++ b/arch/arm/mach-imx/clk-vf610.c @@ -172,11 +172,11 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) clk[VF610_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll1", "pll1_bypass_src", PLL1_CTRL, 0x1); clk[VF610_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", PLL2_CTRL, 0x1); - clk[VF610_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "pll3_bypass_src", PLL3_CTRL, 0x1); + clk[VF610_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB_VF610, "pll3", "pll3_bypass_src", PLL3_CTRL, 0x2); clk[VF610_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "pll4_bypass_src", PLL4_CTRL, 0x7f); clk[VF610_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll5", "pll5_bypass_src", PLL5_CTRL, 0x3); clk[VF610_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_AV, "pll6", "pll6_bypass_src", PLL6_CTRL, 0x7f); - clk[VF610_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "pll7_bypass_src", PLL7_CTRL, 0x1); + clk[VF610_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB_VF610, "pll7", "pll7_bypass_src", PLL7_CTRL, 0x2); clk[VF610_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", PLL1_CTRL, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT); clk[VF610_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", PLL2_CTRL, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT); diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h index 5ef82e2f8fc510..6a07903a28bc81 100644 --- a/arch/arm/mach-imx/clk.h +++ b/arch/arm/mach-imx/clk.h @@ -20,6 +20,7 @@ enum imx_pllv3_type { IMX_PLLV3_GENERIC, IMX_PLLV3_SYS, IMX_PLLV3_USB, + IMX_PLLV3_USB_VF610, IMX_PLLV3_AV, IMX_PLLV3_ENET, }; From 3d27bc5c313ef9f953d1a8eb6927307cdda3aa52 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 10 Dec 2014 17:51:42 +0800 Subject: [PATCH 0393/3023] ARM: imx: correct the hardware clock gate setting for shared nodes For those clk gates which hold share count, since its is_enabled callback is only checking the share count rather than reading the hardware register setting, in the late phase of kernel bootup, the clk_disable_unused action will NOT handle the scenario of share_count is 0 but the hardware setting is enabled, actually, U-Boot normally enables all clk gates, then those shared clk gates will be always enabled until they are used by some modules. So the problem would be: when kernel boot up, the usecount cat from clk tree is 0, but the clk gates actually is enabled in hardware register, it will confuse user and bring unnecessary power consumption. This patch adds .disable_unused callback and using hardware register check for .is_enabled callback of shared nodes to handle such scenario in late phase of kernel boot up, then the hardware status will match the clk tree info. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/mach-imx/clk-gate2.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-imx/clk-gate2.c b/arch/arm/mach-imx/clk-gate2.c index 5a75cdc81891c3..8935bff99fe7ac 100644 --- a/arch/arm/mach-imx/clk-gate2.c +++ b/arch/arm/mach-imx/clk-gate2.c @@ -96,15 +96,30 @@ static int clk_gate2_is_enabled(struct clk_hw *hw) { struct clk_gate2 *gate = to_clk_gate2(hw); - if (gate->share_count) - return !!__clk_get_enable_count(hw->clk); - else - return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx); + return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx); +} + +static void clk_gate2_disable_unused(struct clk_hw *hw) +{ + struct clk_gate2 *gate = to_clk_gate2(hw); + unsigned long flags = 0; + u32 reg; + + spin_lock_irqsave(gate->lock, flags); + + if (!gate->share_count || *gate->share_count == 0) { + reg = readl(gate->reg); + reg &= ~(3 << gate->bit_idx); + writel(reg, gate->reg); + } + + spin_unlock_irqrestore(gate->lock, flags); } static struct clk_ops clk_gate2_ops = { .enable = clk_gate2_enable, .disable = clk_gate2_disable, + .disable_unused = clk_gate2_disable_unused, .is_enabled = clk_gate2_is_enabled, }; From 88a48e297b3a3bac6022c03babfb038f1a886cea Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 18 Dec 2014 16:01:50 -0500 Subject: [PATCH 0394/3023] drm: add atomic properties Once a driver is using atomic helpers for modeset, the next step is to switch over to atomic properties. To do this, make sure that any modeset objects have their ->atomic_{get,set}_property() vfuncs suitably populated if they have custom properties (you did already remember to plug in atomic-helper func for the legacy ->set_property() vfuncs, right?), and then set DRIVER_ATOMIC bit in driver_features flag. A new cap is introduced, DRM_CLIENT_CAP_ATOMIC, for the purposes of shielding legacy userspace from atomic properties. Mostly for the benefit of legacy DDX drivers that do silly things like getting/setting each property at startup (since some of the new atomic properties will be able to trigger modeset). Signed-off-by: Rob Clark [danvet: Squash in fixup patch to check for DRM_MODE_PROP_ATOMIC instaed of the CAP define when filtering properties. Reported by Tvrtko Uruslin, acked by Rob.] Signed-off-by: Daniel Vetter --- Documentation/DocBook/drm.tmpl | 8 ++++++ drivers/gpu/drm/drm_atomic.c | 45 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_crtc.c | 31 +++++++++++++++++------ drivers/gpu/drm/drm_drv.c | 4 +++ drivers/gpu/drm/drm_ioctl.c | 10 ++++++++ include/drm/drmP.h | 4 +++ include/drm/drm_atomic.h | 3 +++ include/drm/drm_crtc.h | 2 +- include/uapi/drm/drm.h | 7 ++++++ include/uapi/drm/drm_mode.h | 7 ++++++ 10 files changed, 113 insertions(+), 8 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 4b592ffbafeec8..7fa4f9873cf7bd 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -239,6 +239,14 @@ Driver supports dedicated render nodes. + + DRIVER_ATOMIC + + Driver supports atomic properties. In this case the driver + must implement appropriate obj->atomic_get_property() vfuncs + for any modeset objects with driver specific properties. + + diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 9c4e149a61e2f7..ce3c681d60f81a 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -520,6 +520,51 @@ int drm_atomic_connector_get_property(struct drm_connector *connector, } EXPORT_SYMBOL(drm_atomic_connector_get_property); +/** + * drm_atomic_get_property - helper to read atomic property + * @obj: drm mode object whose property to read + * @property: the property to read + * @val: the read value, returned by reference + * + * RETURNS: + * Zero on success, error code on failure + */ +int drm_atomic_get_property(struct drm_mode_object *obj, + struct drm_property *property, uint64_t *val) +{ + struct drm_device *dev = property->dev; + int ret; + + switch (obj->type) { + case DRM_MODE_OBJECT_CONNECTOR: { + struct drm_connector *connector = obj_to_connector(obj); + WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); + ret = drm_atomic_connector_get_property(connector, + connector->state, property, val); + break; + } + case DRM_MODE_OBJECT_CRTC: { + struct drm_crtc *crtc = obj_to_crtc(obj); + WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); + ret = drm_atomic_crtc_get_property(crtc, + crtc->state, property, val); + break; + } + case DRM_MODE_OBJECT_PLANE: { + struct drm_plane *plane = obj_to_plane(obj); + WARN_ON(!drm_modeset_is_locked(&plane->mutex)); + ret = drm_atomic_plane_get_property(plane, + plane->state, property, val); + break; + } + default: + ret = -EINVAL; + break; + } + + return ret; +} + /** * drm_atomic_set_crtc_for_plane - set crtc for plane * @plane_state: the plane whose incoming state to update diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index f5f34d0d7c206a..3bac877228fac3 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "drm_crtc_internal.h" #include "drm_internal.h" @@ -1992,19 +1993,25 @@ static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *conne } /* helper for getconnector and getproperties ioctls */ -static int get_properties(struct drm_mode_object *obj, +static int get_properties(struct drm_mode_object *obj, bool atomic, uint32_t __user *prop_ptr, uint64_t __user *prop_values, uint32_t *arg_count_props) { - int props_count = obj->properties->count; - int i, ret, copied = 0; + int props_count; + int i, ret, copied; + + props_count = obj->properties->count; + if (!atomic) + props_count -= obj->properties->atomic_count; if ((*arg_count_props >= props_count) && props_count) { - copied = 0; - for (i = 0; i < props_count; i++) { + for (i = 0, copied = 0; copied < props_count; i++) { struct drm_property *prop = obj->properties->properties[i]; uint64_t val; + if ((prop->flags & DRM_MODE_PROP_ATOMIC) && !atomic) + continue; + ret = drm_object_property_get_value(obj, prop, &val); if (ret) return ret; @@ -2118,7 +2125,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, } out_resp->count_modes = mode_count; - ret = get_properties(&connector->base, + ret = get_properties(&connector->base, file_priv->atomic, (uint32_t __user *)(unsigned long)(out_resp->props_ptr), (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr), &out_resp->count_props); @@ -3832,6 +3839,8 @@ void drm_object_attach_property(struct drm_mode_object *obj, obj->properties->properties[count] = property; obj->properties->values[count] = init_val; obj->properties->count++; + if (property->flags & DRM_MODE_PROP_ATOMIC) + obj->properties->atomic_count++; } EXPORT_SYMBOL(drm_object_attach_property); @@ -3883,6 +3892,14 @@ int drm_object_property_get_value(struct drm_mode_object *obj, { int i; + /* read-only properties bypass atomic mechanism and still store + * their value in obj->properties->values[].. mostly to avoid + * having to deal w/ EDID and similar props in atomic paths: + */ + if (drm_core_check_feature(property->dev, DRIVER_ATOMIC) && + !(property->flags & DRM_MODE_PROP_IMMUTABLE)) + return drm_atomic_get_property(obj, property, val); + for (i = 0; i < obj->properties->count; i++) { if (obj->properties->properties[i] == property) { *val = obj->properties->values[i]; @@ -4413,7 +4430,7 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, goto out; } - ret = get_properties(obj, + ret = get_properties(obj, file_priv->atomic, (uint32_t __user *)(unsigned long)(arg->props_ptr), (uint64_t __user *)(unsigned long)(arg->prop_values_ptr), &arg->count_props); diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 4f41377b0b8096..d51213464672a9 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -40,15 +40,19 @@ unsigned int drm_debug = 0; /* 1 to enable debug output */ EXPORT_SYMBOL(drm_debug); +bool drm_atomic = 0; + MODULE_AUTHOR(CORE_AUTHOR); MODULE_DESCRIPTION(CORE_DESC); MODULE_LICENSE("GPL and additional rights"); MODULE_PARM_DESC(debug, "Enable debug output"); +MODULE_PARM_DESC(atomic, "Enable experimental atomic KMS API"); MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs] (0: never disable, <0: disable immediately)"); MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]"); MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps"); module_param_named(debug, drm_debug, int, 0600); +module_param_named_unsafe(atomic, drm_atomic, bool, 0600); static DEFINE_SPINLOCK(drm_minor_lock); static struct idr drm_minors_idr; diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 00587a1e3c83c0..adc822312f6cf6 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -345,6 +345,16 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv) return -EINVAL; file_priv->universal_planes = req->value; break; + case DRM_CLIENT_CAP_ATOMIC: + /* for now, hide behind experimental drm.atomic moduleparam */ + if (!drm_atomic) + return -EINVAL; + if (!drm_core_check_feature(dev, DRIVER_ATOMIC)) + return -EINVAL; + if (req->value > 1) + return -EINVAL; + file_priv->atomic = req->value; + break; default: return -EINVAL; } diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 8ba35c622e2202..0f7115e988a075 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -143,6 +143,7 @@ void drm_err(const char *format, ...); #define DRIVER_MODESET 0x2000 #define DRIVER_PRIME 0x4000 #define DRIVER_RENDER 0x8000 +#define DRIVER_ATOMIC 0x10000 /***********************************************************************/ /** \name Macros to make printk easier */ @@ -283,6 +284,8 @@ struct drm_file { * in the plane list */ unsigned universal_planes:1; + /* true if client understands atomic properties */ + unsigned atomic:1; struct pid *pid; kuid_t uid; @@ -950,6 +953,7 @@ extern void drm_master_put(struct drm_master **master); extern void drm_put_dev(struct drm_device *dev); extern void drm_unplug_dev(struct drm_device *dev); extern unsigned int drm_debug; +extern bool drm_atomic; /* Debugfs support */ #if defined(CONFIG_DEBUG_FS) diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index d41233ccbc9e64..231fb485abb39c 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -63,6 +63,9 @@ int drm_atomic_connector_get_property(struct drm_connector *connector, const struct drm_connector_state *state, struct drm_property *property, uint64_t *val); +int drm_atomic_get_property(struct drm_mode_object *obj, + struct drm_property *property, uint64_t *val); + int __must_check drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, struct drm_crtc *crtc); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index e1f34694fcff14..b5ab673add29b7 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -63,7 +63,7 @@ struct drm_mode_object { #define DRM_OBJECT_MAX_PROPERTY 24 struct drm_object_properties { - int count; + int count, atomic_count; /* NOTE: if we ever start dynamically destroying properties (ie. * not at drm_mode_config_cleanup() time), then we'd have to do * a better job of detaching property from mode objects to avoid diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index b0b85561364161..f7b2baf7ecb27b 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -654,6 +654,13 @@ struct drm_get_cap { */ #define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2 +/** + * DRM_CLIENT_CAP_ATOMIC + * + * If set to 1, the DRM core will expose atomic properties to userspace + */ +#define DRM_CLIENT_CAP_ATOMIC 3 + /** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */ struct drm_set_client_cap { __u64 capability; diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index aae71cb32123ee..b8f9c0f2e7fec0 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -272,6 +272,13 @@ struct drm_mode_get_connector { #define DRM_MODE_PROP_OBJECT DRM_MODE_PROP_TYPE(1) #define DRM_MODE_PROP_SIGNED_RANGE DRM_MODE_PROP_TYPE(2) +/* the PROP_ATOMIC flag is used to hide properties from userspace that + * is not aware of atomic properties. This is mostly to work around + * older userspace (DDX drivers) that read/write each prop they find, + * witout being aware that this could be triggering a lengthy modeset. + */ +#define DRM_MODE_PROP_ATOMIC 0x80000000 + struct drm_mode_property_enum { __u64 value; char name[DRM_PROP_NAME_LEN]; From 5e743737421fe9be9d7b25475427a3698e6f70a5 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 18 Dec 2014 16:01:51 -0500 Subject: [PATCH 0395/3023] drm/atomic: atomic_check functions Add functions to check core plane/crtc state. v2: comments, int-overflow checks, call from core rather than helpers to be sure drivers can't find a way to bypass core checks Signed-off-by: Rob Clark Reviewed-by: Sean Paul Reviewed-by: Daniel Vetter Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic.c | 139 +++++++++++++++++++++++++++- drivers/gpu/drm/drm_atomic_helper.c | 4 +- 2 files changed, 137 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index ce3c681d60f81a..1c472b1baeb818 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -268,6 +268,29 @@ int drm_atomic_crtc_get_property(struct drm_crtc *crtc, } EXPORT_SYMBOL(drm_atomic_crtc_get_property); +/** + * drm_atomic_crtc_check - check crtc state + * @crtc: crtc to check + * @state: crtc state to check + * + * Provides core sanity checks for crtc state. + * + * RETURNS: + * Zero on success, error code on failure + */ +static int drm_atomic_crtc_check(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + /* NOTE: we explicitly don't enforce constraints such as primary + * layer covering entire screen, since that is something we want + * to allow (on hw that supports it). For hw that does not, it + * should be checked in driver's crtc->atomic_check() vfunc. + * + * TODO: Add generic modeset state checks once we support those. + */ + return 0; +} + /** * drm_atomic_get_plane_state - get plane state * @state: global atomic state object @@ -375,6 +398,82 @@ int drm_atomic_plane_get_property(struct drm_plane *plane, } EXPORT_SYMBOL(drm_atomic_plane_get_property); +/** + * drm_atomic_plane_check - check plane state + * @plane: plane to check + * @state: plane state to check + * + * Provides core sanity checks for plane state. + * + * RETURNS: + * Zero on success, error code on failure + */ +static int drm_atomic_plane_check(struct drm_plane *plane, + struct drm_plane_state *state) +{ + unsigned int fb_width, fb_height; + unsigned int i; + + /* either *both* CRTC and FB must be set, or neither */ + if (WARN_ON(state->crtc && !state->fb)) { + DRM_DEBUG_KMS("CRTC set but no FB\n"); + return -EINVAL; + } else if (WARN_ON(state->fb && !state->crtc)) { + DRM_DEBUG_KMS("FB set but no CRTC\n"); + return -EINVAL; + } + + /* if disabled, we don't care about the rest of the state: */ + if (!state->crtc) + return 0; + + /* Check whether this plane is usable on this CRTC */ + if (!(plane->possible_crtcs & drm_crtc_mask(state->crtc))) { + DRM_DEBUG_KMS("Invalid crtc for plane\n"); + return -EINVAL; + } + + /* Check whether this plane supports the fb pixel format. */ + for (i = 0; i < plane->format_count; i++) + if (state->fb->pixel_format == plane->format_types[i]) + break; + if (i == plane->format_count) { + DRM_DEBUG_KMS("Invalid pixel format %s\n", + drm_get_format_name(state->fb->pixel_format)); + return -EINVAL; + } + + /* Give drivers some help against integer overflows */ + if (state->crtc_w > INT_MAX || + state->crtc_x > INT_MAX - (int32_t) state->crtc_w || + state->crtc_h > INT_MAX || + state->crtc_y > INT_MAX - (int32_t) state->crtc_h) { + DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n", + state->crtc_w, state->crtc_h, + state->crtc_x, state->crtc_y); + return -ERANGE; + } + + fb_width = state->fb->width << 16; + fb_height = state->fb->height << 16; + + /* Make sure source coordinates are inside the fb. */ + if (state->src_w > fb_width || + state->src_x > fb_width - state->src_w || + state->src_h > fb_height || + state->src_y > fb_height - state->src_h) { + DRM_DEBUG_KMS("Invalid source coordinates " + "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n", + state->src_w >> 16, ((state->src_w & 0xffff) * 15625) >> 10, + state->src_h >> 16, ((state->src_h & 0xffff) * 15625) >> 10, + state->src_x >> 16, ((state->src_x & 0xffff) * 15625) >> 10, + state->src_y >> 16, ((state->src_y & 0xffff) * 15625) >> 10); + return -ENOSPC; + } + + return 0; +} + /** * drm_atomic_get_connector_state - get connector state * @state: global atomic state object @@ -801,14 +900,46 @@ EXPORT_SYMBOL(drm_atomic_legacy_backoff); */ int drm_atomic_check_only(struct drm_atomic_state *state) { - struct drm_mode_config *config = &state->dev->mode_config; + struct drm_device *dev = state->dev; + struct drm_mode_config *config = &dev->mode_config; + int nplanes = config->num_total_plane; + int ncrtcs = config->num_crtc; + int i, ret = 0; DRM_DEBUG_KMS("checking %p\n", state); + for (i = 0; i < nplanes; i++) { + struct drm_plane *plane = state->planes[i]; + + if (!plane) + continue; + + ret = drm_atomic_plane_check(plane, state->plane_states[i]); + if (ret) { + DRM_DEBUG_KMS("[PLANE:%d] atomic core check failed\n", + plane->base.id); + return ret; + } + } + + for (i = 0; i < ncrtcs; i++) { + struct drm_crtc *crtc = state->crtcs[i]; + + if (!crtc) + continue; + + ret = drm_atomic_crtc_check(crtc, state->crtc_states[i]); + if (ret) { + DRM_DEBUG_KMS("[CRTC:%d] atomic core check failed\n", + crtc->base.id); + return ret; + } + } + if (config->funcs->atomic_check) - return config->funcs->atomic_check(state->dev, state); - else - return 0; + ret = config->funcs->atomic_check(state->dev, state); + + return ret; } EXPORT_SYMBOL(drm_atomic_check_only); diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 57e5540259cc41..541ba833ed36ed 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -467,7 +467,7 @@ drm_atomic_helper_check_planes(struct drm_device *dev, ret = funcs->atomic_check(plane, plane_state); if (ret) { - DRM_DEBUG_KMS("[PLANE:%d] atomic check failed\n", + DRM_DEBUG_KMS("[PLANE:%d] atomic driver check failed\n", plane->base.id); return ret; } @@ -487,7 +487,7 @@ drm_atomic_helper_check_planes(struct drm_device *dev, ret = funcs->atomic_check(crtc, state->crtc_states[i]); if (ret) { - DRM_DEBUG_KMS("[CRTC:%d] atomic check failed\n", + DRM_DEBUG_KMS("[CRTC:%d] atomic driver check failed\n", crtc->base.id); return ret; } From 356af0e154467eb6844f25631a11940b462deca0 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 18 Dec 2014 16:01:52 -0500 Subject: [PATCH 0396/3023] drm: small property creation cleanup Getting ready to add a lot more standard properties for atomic. Signed-off-by: Rob Clark Reviewed-by: Sean Paul Reviewed-by: Daniel Vetter [danvet: Realign function paramaters where the lines shrunk massively.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_crtc.c | 43 ++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 3bac877228fac3..f33863a40d42d5 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1325,33 +1325,40 @@ EXPORT_SYMBOL(drm_plane_force_disable); static int drm_mode_create_standard_connector_properties(struct drm_device *dev) { - struct drm_property *edid; - struct drm_property *dpms; - struct drm_property *dev_path; + struct drm_property *prop; /* * Standard properties (apply to all connectors) */ - edid = drm_property_create(dev, DRM_MODE_PROP_BLOB | + prop = drm_property_create(dev, DRM_MODE_PROP_BLOB | DRM_MODE_PROP_IMMUTABLE, "EDID", 0); - dev->mode_config.edid_property = edid; + if (!prop) + return -ENOMEM; + dev->mode_config.edid_property = prop; - dpms = drm_property_create_enum(dev, 0, + prop = drm_property_create_enum(dev, 0, "DPMS", drm_dpms_enum_list, ARRAY_SIZE(drm_dpms_enum_list)); - dev->mode_config.dpms_property = dpms; - - dev_path = drm_property_create(dev, - DRM_MODE_PROP_BLOB | - DRM_MODE_PROP_IMMUTABLE, - "PATH", 0); - dev->mode_config.path_property = dev_path; - - dev->mode_config.tile_property = drm_property_create(dev, - DRM_MODE_PROP_BLOB | - DRM_MODE_PROP_IMMUTABLE, - "TILE", 0); + if (!prop) + return -ENOMEM; + dev->mode_config.dpms_property = prop; + + prop = drm_property_create(dev, + DRM_MODE_PROP_BLOB | + DRM_MODE_PROP_IMMUTABLE, + "PATH", 0); + if (!prop) + return -ENOMEM; + dev->mode_config.path_property = prop; + + prop = drm_property_create(dev, + DRM_MODE_PROP_BLOB | + DRM_MODE_PROP_IMMUTABLE, + "TILE", 0); + if (!prop) + return -ENOMEM; + dev->mode_config.tile_property = prop; return 0; } From 6b4959f43a04e12d39c5700607727f2cbcfeac31 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 18 Dec 2014 16:01:53 -0500 Subject: [PATCH 0397/3023] drm/atomic: atomic plane properties Expose the core plane state as properties, so they can be updated via atomic ioctl. v2: atomic property flag Signed-off-by: Rob Clark Reviewed-by: Sean Paul Reviewed-by: Daniel Vetter Signed-off-by: Daniel Vetter --- Documentation/DocBook/drm.tmpl | 74 ++++++++++++++++++++++- drivers/gpu/drm/drm_atomic.c | 69 ++++++++++++++++++++-- drivers/gpu/drm/drm_crtc.c | 103 +++++++++++++++++++++++++++------ include/drm/drm_crtc.h | 10 ++++ 4 files changed, 230 insertions(+), 26 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 7fa4f9873cf7bd..8d8dc7124bb57b 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -2572,7 +2572,7 @@ void intel_crt_init(struct drm_device *dev) Description/Restrictions - DRM + DRM Generic “EDID†BLOB | IMMUTABLE @@ -2602,7 +2602,7 @@ void intel_crt_init(struct drm_device *dev) Contains tiling information for a connector. - Plane + Plane “type†ENUM | IMMUTABLE { "Overlay", "Primary", "Cursor" } @@ -2610,6 +2610,76 @@ void intel_crt_init(struct drm_device *dev) Plane type + “SRC_X†+ RANGE + Min=0, Max=UINT_MAX + Plane + Scanout source x coordinate in 16.16 fixed point (atomic) + + + “SRC_Y†+ RANGE + Min=0, Max=UINT_MAX + Plane + Scanout source y coordinate in 16.16 fixed point (atomic) + + + “SRC_W†+ RANGE + Min=0, Max=UINT_MAX + Plane + Scanout source width in 16.16 fixed point (atomic) + + + “SRC_H†+ RANGE + Min=0, Max=UINT_MAX + Plane + Scanout source height in 16.16 fixed point (atomic) + + + “CRTC_X†+ SIGNED_RANGE + Min=INT_MIN, Max=INT_MAX + Plane + Scanout CRTC (destination) x coordinate (atomic) + + + “CRTC_Y†+ SIGNED_RANGE + Min=INT_MIN, Max=INT_MAX + Plane + Scanout CRTC (destination) y coordinate (atomic) + + + “CRTC_W†+ RANGE + Min=0, Max=UINT_MAX + Plane + Scanout CRTC (destination) width (atomic) + + + “CRTC_H†+ RANGE + Min=0, Max=UINT_MAX + Plane + Scanout CRTC (destination) height (atomic) + + + “FB_ID†+ OBJECT + DRM_MODE_OBJECT_FB + Plane + Scanout framebuffer (atomic) + + + “CRTC_ID†+ OBJECT + DRM_MODE_OBJECT_CRTC + Plane + CRTC that plane is attached to (atomic) + + DVI-I “subconnector†ENUM diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 1c472b1baeb818..131d47f6f7a243 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -366,9 +366,41 @@ int drm_atomic_plane_set_property(struct drm_plane *plane, struct drm_plane_state *state, struct drm_property *property, uint64_t val) { - if (plane->funcs->atomic_set_property) - return plane->funcs->atomic_set_property(plane, state, property, val); - return -EINVAL; + struct drm_device *dev = plane->dev; + struct drm_mode_config *config = &dev->mode_config; + + if (property == config->prop_fb_id) { + struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, val); + drm_atomic_set_fb_for_plane(state, fb); + if (fb) + drm_framebuffer_unreference(fb); + } else if (property == config->prop_crtc_id) { + struct drm_crtc *crtc = drm_crtc_find(dev, val); + return drm_atomic_set_crtc_for_plane(state, crtc); + } else if (property == config->prop_crtc_x) { + state->crtc_x = U642I64(val); + } else if (property == config->prop_crtc_y) { + state->crtc_y = U642I64(val); + } else if (property == config->prop_crtc_w) { + state->crtc_w = val; + } else if (property == config->prop_crtc_h) { + state->crtc_h = val; + } else if (property == config->prop_src_x) { + state->src_x = val; + } else if (property == config->prop_src_y) { + state->src_y = val; + } else if (property == config->prop_src_w) { + state->src_w = val; + } else if (property == config->prop_src_h) { + state->src_h = val; + } else if (plane->funcs->atomic_set_property) { + return plane->funcs->atomic_set_property(plane, state, + property, val); + } else { + return -EINVAL; + } + + return 0; } EXPORT_SYMBOL(drm_atomic_plane_set_property); @@ -392,9 +424,36 @@ int drm_atomic_plane_get_property(struct drm_plane *plane, const struct drm_plane_state *state, struct drm_property *property, uint64_t *val) { - if (plane->funcs->atomic_get_property) + struct drm_device *dev = plane->dev; + struct drm_mode_config *config = &dev->mode_config; + + if (property == config->prop_fb_id) { + *val = (state->fb) ? state->fb->base.id : 0; + } else if (property == config->prop_crtc_id) { + *val = (state->crtc) ? state->crtc->base.id : 0; + } else if (property == config->prop_crtc_x) { + *val = I642U64(state->crtc_x); + } else if (property == config->prop_crtc_y) { + *val = I642U64(state->crtc_y); + } else if (property == config->prop_crtc_w) { + *val = state->crtc_w; + } else if (property == config->prop_crtc_h) { + *val = state->crtc_h; + } else if (property == config->prop_src_x) { + *val = state->src_x; + } else if (property == config->prop_src_y) { + *val = state->src_y; + } else if (property == config->prop_src_w) { + *val = state->src_w; + } else if (property == config->prop_src_h) { + *val = state->src_h; + } else if (plane->funcs->atomic_get_property) { return plane->funcs->atomic_get_property(plane, state, property, val); - return -EINVAL; + } else { + return -EINVAL; + } + + return 0; } EXPORT_SYMBOL(drm_atomic_plane_get_property); diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index f33863a40d42d5..46fa0945b53ef3 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1169,6 +1169,7 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, const uint32_t *formats, uint32_t format_count, enum drm_plane_type type) { + struct drm_mode_config *config = &dev->mode_config; int ret; ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE); @@ -1193,15 +1194,28 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, plane->possible_crtcs = possible_crtcs; plane->type = type; - list_add_tail(&plane->head, &dev->mode_config.plane_list); - dev->mode_config.num_total_plane++; + list_add_tail(&plane->head, &config->plane_list); + config->num_total_plane++; if (plane->type == DRM_PLANE_TYPE_OVERLAY) - dev->mode_config.num_overlay_plane++; + config->num_overlay_plane++; drm_object_attach_property(&plane->base, - dev->mode_config.plane_type_property, + config->plane_type_property, plane->type); + if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { + drm_object_attach_property(&plane->base, config->prop_fb_id, 0); + drm_object_attach_property(&plane->base, config->prop_crtc_id, 0); + drm_object_attach_property(&plane->base, config->prop_crtc_x, 0); + drm_object_attach_property(&plane->base, config->prop_crtc_y, 0); + drm_object_attach_property(&plane->base, config->prop_crtc_w, 0); + drm_object_attach_property(&plane->base, config->prop_crtc_h, 0); + drm_object_attach_property(&plane->base, config->prop_src_x, 0); + drm_object_attach_property(&plane->base, config->prop_src_y, 0); + drm_object_attach_property(&plane->base, config->prop_src_w, 0); + drm_object_attach_property(&plane->base, config->prop_src_h, 0); + } + return 0; } EXPORT_SYMBOL(drm_universal_plane_init); @@ -1323,7 +1337,7 @@ void drm_plane_force_disable(struct drm_plane *plane) } EXPORT_SYMBOL(drm_plane_force_disable); -static int drm_mode_create_standard_connector_properties(struct drm_device *dev) +static int drm_mode_create_standard_properties(struct drm_device *dev) { struct drm_property *prop; @@ -1360,20 +1374,72 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev) return -ENOMEM; dev->mode_config.tile_property = prop; - return 0; -} - -static int drm_mode_create_standard_plane_properties(struct drm_device *dev) -{ - struct drm_property *type; - - /* - * Standard properties (apply to all planes) - */ - type = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, + prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, "type", drm_plane_type_enum_list, ARRAY_SIZE(drm_plane_type_enum_list)); - dev->mode_config.plane_type_property = type; + if (!prop) + return -ENOMEM; + dev->mode_config.plane_type_property = prop; + + prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, + "SRC_X", 0, UINT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_src_x = prop; + + prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, + "SRC_Y", 0, UINT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_src_y = prop; + + prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, + "SRC_W", 0, UINT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_src_w = prop; + + prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, + "SRC_H", 0, UINT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_src_h = prop; + + prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC, + "CRTC_X", INT_MIN, INT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_crtc_x = prop; + + prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC, + "CRTC_Y", INT_MIN, INT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_crtc_y = prop; + + prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, + "CRTC_W", 0, INT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_crtc_w = prop; + + prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, + "CRTC_H", 0, INT_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_crtc_h = prop; + + prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC, + "FB_ID", DRM_MODE_OBJECT_FB); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_fb_id = prop; + + prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC, + "CRTC_ID", DRM_MODE_OBJECT_CRTC); + if (!prop) + return -ENOMEM; + dev->mode_config.prop_crtc_id = prop; return 0; } @@ -5264,8 +5330,7 @@ void drm_mode_config_init(struct drm_device *dev) idr_init(&dev->mode_config.tile_idr); drm_modeset_lock_all(dev); - drm_mode_create_standard_connector_properties(dev); - drm_mode_create_standard_plane_properties(dev); + drm_mode_create_standard_properties(dev); drm_modeset_unlock_all(dev); /* Just to be sure */ diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index b5ab673add29b7..fc4767fa723b36 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1099,6 +1099,16 @@ struct drm_mode_config { struct drm_property *tile_property; struct drm_property *plane_type_property; struct drm_property *rotation_property; + struct drm_property *prop_src_x; + struct drm_property *prop_src_y; + struct drm_property *prop_src_w; + struct drm_property *prop_src_h; + struct drm_property *prop_crtc_x; + struct drm_property *prop_crtc_y; + struct drm_property *prop_crtc_w; + struct drm_property *prop_crtc_h; + struct drm_property *prop_fb_id; + struct drm_property *prop_crtc_id; /* DVI-I properties */ struct drm_property *dvi_i_subconnector_property; From ae16c597b61ae4613b13a0c3fac302e8d8827ac7 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 18 Dec 2014 16:01:54 -0500 Subject: [PATCH 0398/3023] drm/atomic: atomic connector properties Expose the core connector state as properties so it can be updated via atomic ioctl. Signed-off-by: Rob Clark Reviewed-by: Sean Paul Reviewed-by: Daniel Vetter Signed-off-by: Daniel Vetter --- Documentation/DocBook/drm.tmpl | 11 +++++++++-- drivers/gpu/drm/drm_atomic.c | 9 +++++++-- drivers/gpu/drm/drm_crtc.c | 13 +++++++++---- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 8d8dc7124bb57b..2f4a299064251f 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -2572,8 +2572,8 @@ void intel_crt_init(struct drm_device *dev) Description/Restrictions - DRM - Generic + DRM + Connector “EDID†BLOB | IMMUTABLE 0 @@ -2602,6 +2602,13 @@ void intel_crt_init(struct drm_device *dev) Contains tiling information for a connector. + “CRTC_ID†+ OBJECT + DRM_MODE_OBJECT_CRTC + Connector + CRTC that connector is attached to (atomic) + + Plane “type†ENUM | IMMUTABLE diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 131d47f6f7a243..57cc68177f098c 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -627,7 +627,10 @@ int drm_atomic_connector_set_property(struct drm_connector *connector, struct drm_device *dev = connector->dev; struct drm_mode_config *config = &dev->mode_config; - if (property == config->dpms_property) { + if (property == config->prop_crtc_id) { + struct drm_crtc *crtc = drm_crtc_find(dev, val); + return drm_atomic_set_crtc_for_connector(state, crtc); + } else if (property == config->dpms_property) { /* setting DPMS property requires special handling, which * is done in legacy setprop path for us. Disallow (for * now?) atomic writes to DPMS property: @@ -665,7 +668,9 @@ int drm_atomic_connector_get_property(struct drm_connector *connector, struct drm_device *dev = connector->dev; struct drm_mode_config *config = &dev->mode_config; - if (property == config->dpms_property) { + if (property == config->prop_crtc_id) { + *val = (state->crtc) ? state->crtc->base.id : 0; + } else if (property == config->dpms_property) { *val = connector->dpms; } else if (connector->funcs->atomic_get_property) { return connector->funcs->atomic_get_property(connector, diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 46fa0945b53ef3..3cb1fa09ac9ef9 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -831,6 +831,7 @@ int drm_connector_init(struct drm_device *dev, const struct drm_connector_funcs *funcs, int connector_type) { + struct drm_mode_config *config = &dev->mode_config; int ret; struct ida *connector_ida = &drm_connector_enum_list[connector_type].ida; @@ -869,16 +870,20 @@ int drm_connector_init(struct drm_device *dev, /* We should add connectors at the end to avoid upsetting the connector * index too much. */ - list_add_tail(&connector->head, &dev->mode_config.connector_list); - dev->mode_config.num_connector++; + list_add_tail(&connector->head, &config->connector_list); + config->num_connector++; if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL) drm_object_attach_property(&connector->base, - dev->mode_config.edid_property, + config->edid_property, 0); drm_object_attach_property(&connector->base, - dev->mode_config.dpms_property, 0); + config->dpms_property, 0); + + if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { + drm_object_attach_property(&connector->base, config->prop_crtc_id, 0); + } connector->debugfs_entry = NULL; From d34f20d6e2f21bd3531b969dc40913181a8ae31a Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 18 Dec 2014 16:01:56 -0500 Subject: [PATCH 0399/3023] drm: Atomic modeset ioctl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The atomic modeset ioctl can be used to push any number of new values for object properties. The driver can then check the full device configuration as single unit, and try to apply the changes atomically. The ioctl simply takes a list of object IDs and property IDs and their values. Originally based on a patch from Ville Syrjälä, although it has mutated (mutilated?) enough since then that you probably shouldn't blame it on him ;-) The atomic support is hidden behind the DRM_CLIENT_CAP_ATOMIC cap (to protect legacy userspace) and drm.atomic module param (for now). v2: Check for file_priv->atomic to make sure we only allow userspace in-the-know to use atomic. Signed-off-by: Rob Clark Reviewed-by: Sean Paul Reviewed-by: Daniel Vetter Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic.c | 331 +++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_crtc.c | 4 +- drivers/gpu/drm/drm_ioctl.c | 1 + include/drm/drm_crtc.h | 10 +- include/uapi/drm/drm.h | 1 + include/uapi/drm/drm_mode.h | 23 +++ 6 files changed, 366 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 57cc68177f098c..67f64bd1058f68 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -56,6 +56,11 @@ drm_atomic_state_alloc(struct drm_device *dev) if (!state) return NULL; + /* TODO legacy paths should maybe do a better job about + * setting this appropriately? + */ + state->allow_modeset = true; + state->num_connector = ACCESS_ONCE(dev->mode_config.num_connector); state->crtcs = kcalloc(dev->mode_config.num_crtc, @@ -1003,6 +1008,22 @@ int drm_atomic_check_only(struct drm_atomic_state *state) if (config->funcs->atomic_check) ret = config->funcs->atomic_check(state->dev, state); + if (!state->allow_modeset) { + for (i = 0; i < ncrtcs; i++) { + struct drm_crtc *crtc = state->crtcs[i]; + struct drm_crtc_state *crtc_state = state->crtc_states[i]; + + if (!crtc) + continue; + + if (crtc_state->mode_changed) { + DRM_DEBUG_KMS("[CRTC:%d] requires full modeset\n", + crtc->base.id); + return -EINVAL; + } + } + } + return ret; } EXPORT_SYMBOL(drm_atomic_check_only); @@ -1068,3 +1089,313 @@ int drm_atomic_async_commit(struct drm_atomic_state *state) return config->funcs->atomic_commit(state->dev, state, true); } EXPORT_SYMBOL(drm_atomic_async_commit); + +/* + * The big monstor ioctl + */ + +static struct drm_pending_vblank_event *create_vblank_event( + struct drm_device *dev, struct drm_file *file_priv, uint64_t user_data) +{ + struct drm_pending_vblank_event *e = NULL; + unsigned long flags; + + spin_lock_irqsave(&dev->event_lock, flags); + if (file_priv->event_space < sizeof e->event) { + spin_unlock_irqrestore(&dev->event_lock, flags); + goto out; + } + file_priv->event_space -= sizeof e->event; + spin_unlock_irqrestore(&dev->event_lock, flags); + + e = kzalloc(sizeof *e, GFP_KERNEL); + if (e == NULL) { + spin_lock_irqsave(&dev->event_lock, flags); + file_priv->event_space += sizeof e->event; + spin_unlock_irqrestore(&dev->event_lock, flags); + goto out; + } + + e->event.base.type = DRM_EVENT_FLIP_COMPLETE; + e->event.base.length = sizeof e->event; + e->event.user_data = user_data; + e->base.event = &e->event.base; + e->base.file_priv = file_priv; + e->base.destroy = (void (*) (struct drm_pending_event *)) kfree; + +out: + return e; +} + +static void destroy_vblank_event(struct drm_device *dev, + struct drm_file *file_priv, struct drm_pending_vblank_event *e) +{ + unsigned long flags; + + spin_lock_irqsave(&dev->event_lock, flags); + file_priv->event_space += sizeof e->event; + spin_unlock_irqrestore(&dev->event_lock, flags); + kfree(e); +} + +static int atomic_set_prop(struct drm_atomic_state *state, + struct drm_mode_object *obj, struct drm_property *prop, + uint64_t prop_value) +{ + struct drm_mode_object *ref; + int ret; + + if (!drm_property_change_valid_get(prop, prop_value, &ref)) + return -EINVAL; + + switch (obj->type) { + case DRM_MODE_OBJECT_CONNECTOR: { + struct drm_connector *connector = obj_to_connector(obj); + struct drm_connector_state *connector_state; + + connector_state = drm_atomic_get_connector_state(state, connector); + if (IS_ERR(connector_state)) { + ret = PTR_ERR(connector_state); + break; + } + + ret = drm_atomic_connector_set_property(connector, + connector_state, prop, prop_value); + break; + } + case DRM_MODE_OBJECT_CRTC: { + struct drm_crtc *crtc = obj_to_crtc(obj); + struct drm_crtc_state *crtc_state; + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) { + ret = PTR_ERR(crtc_state); + break; + } + + ret = drm_atomic_crtc_set_property(crtc, + crtc_state, prop, prop_value); + break; + } + case DRM_MODE_OBJECT_PLANE: { + struct drm_plane *plane = obj_to_plane(obj); + struct drm_plane_state *plane_state; + + plane_state = drm_atomic_get_plane_state(state, plane); + if (IS_ERR(plane_state)) { + ret = PTR_ERR(plane_state); + break; + } + + ret = drm_atomic_plane_set_property(plane, + plane_state, prop, prop_value); + break; + } + default: + ret = -EINVAL; + break; + } + + drm_property_change_valid_put(prop, ref); + return ret; +} + +int drm_mode_atomic_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_atomic *arg = data; + uint32_t __user *objs_ptr = (uint32_t __user *)(unsigned long)(arg->objs_ptr); + uint32_t __user *count_props_ptr = (uint32_t __user *)(unsigned long)(arg->count_props_ptr); + uint32_t __user *props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr); + uint64_t __user *prop_values_ptr = (uint64_t __user *)(unsigned long)(arg->prop_values_ptr); + unsigned int copied_objs, copied_props; + struct drm_atomic_state *state; + struct drm_modeset_acquire_ctx ctx; + struct drm_plane *plane; + unsigned plane_mask = 0; + int ret = 0; + unsigned int i, j; + + /* disallow for drivers not supporting atomic: */ + if (!drm_core_check_feature(dev, DRIVER_ATOMIC)) + return -EINVAL; + + /* disallow for userspace that has not enabled atomic cap (even + * though this may be a bit overkill, since legacy userspace + * wouldn't know how to call this ioctl) + */ + if (!file_priv->atomic) + return -EINVAL; + + if (arg->flags & ~DRM_MODE_ATOMIC_FLAGS) + return -EINVAL; + + if (arg->reserved) + return -EINVAL; + + if ((arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) && + !dev->mode_config.async_page_flip) + return -EINVAL; + + /* can't test and expect an event at the same time. */ + if ((arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) && + (arg->flags & DRM_MODE_PAGE_FLIP_EVENT)) + return -EINVAL; + + drm_modeset_acquire_init(&ctx, 0); + + state = drm_atomic_state_alloc(dev); + if (!state) + return -ENOMEM; + + state->acquire_ctx = &ctx; + state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET); + +retry: + copied_objs = 0; + copied_props = 0; + + for (i = 0; i < arg->count_objs; i++) { + uint32_t obj_id, count_props; + struct drm_mode_object *obj; + + if (get_user(obj_id, objs_ptr + copied_objs)) { + ret = -EFAULT; + goto fail; + } + + obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_ANY); + if (!obj || !obj->properties) { + ret = -ENOENT; + goto fail; + } + + if (obj->type == DRM_MODE_OBJECT_PLANE) { + plane = obj_to_plane(obj); + plane_mask |= (1 << drm_plane_index(plane)); + plane->old_fb = plane->fb; + } + + if (get_user(count_props, count_props_ptr + copied_objs)) { + ret = -EFAULT; + goto fail; + } + + copied_objs++; + + for (j = 0; j < count_props; j++) { + uint32_t prop_id; + uint64_t prop_value; + struct drm_property *prop; + + if (get_user(prop_id, props_ptr + copied_props)) { + ret = -EFAULT; + goto fail; + } + + prop = drm_property_find(dev, prop_id); + if (!prop) { + ret = -ENOENT; + goto fail; + } + + if (get_user(prop_value, prop_values_ptr + copied_props)) { + ret = -EFAULT; + goto fail; + } + + ret = atomic_set_prop(state, obj, prop, prop_value); + if (ret) + goto fail; + + copied_props++; + } + } + + if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) { + int ncrtcs = dev->mode_config.num_crtc; + + for (i = 0; i < ncrtcs; i++) { + struct drm_crtc_state *crtc_state = state->crtc_states[i]; + struct drm_pending_vblank_event *e; + + if (!crtc_state) + continue; + + e = create_vblank_event(dev, file_priv, arg->user_data); + if (!e) { + ret = -ENOMEM; + goto fail; + } + + crtc_state->event = e; + } + } + + if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) { + ret = drm_atomic_check_only(state); + /* _check_only() does not free state, unlike _commit() */ + drm_atomic_state_free(state); + } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) { + ret = drm_atomic_async_commit(state); + } else { + ret = drm_atomic_commit(state); + } + + /* if succeeded, fixup legacy plane crtc/fb ptrs before dropping + * locks (ie. while it is still safe to deref plane->state). We + * need to do this here because the driver entry points cannot + * distinguish between legacy and atomic ioctls. + */ + drm_for_each_plane_mask(plane, dev, plane_mask) { + if (ret == 0) { + struct drm_framebuffer *new_fb = plane->state->fb; + if (new_fb) + drm_framebuffer_reference(new_fb); + plane->fb = new_fb; + plane->crtc = plane->state->crtc; + } else { + plane->old_fb = NULL; + } + if (plane->old_fb) { + drm_framebuffer_unreference(plane->old_fb); + plane->old_fb = NULL; + } + } + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + + return ret; + +fail: + if (ret == -EDEADLK) + goto backoff; + + if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) { + int ncrtcs = dev->mode_config.num_crtc; + + for (i = 0; i < ncrtcs; i++) { + struct drm_crtc_state *crtc_state = state->crtc_states[i]; + + if (!crtc_state) + continue; + + destroy_vblank_event(dev, file_priv, crtc_state->event); + crtc_state->event = NULL; + } + } + + drm_atomic_state_free(state); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + + return ret; + +backoff: + drm_atomic_state_clear(state); + drm_modeset_backoff(&ctx); + + goto retry; +} diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 3cb1fa09ac9ef9..20596423d52d15 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -4303,7 +4303,7 @@ EXPORT_SYMBOL(drm_mode_connector_update_edid_property); * object to which the property is attached has a chance to take it's own * reference). */ -static bool drm_property_change_valid_get(struct drm_property *property, +bool drm_property_change_valid_get(struct drm_property *property, uint64_t value, struct drm_mode_object **ref) { int i; @@ -4365,7 +4365,7 @@ static bool drm_property_change_valid_get(struct drm_property *property, return false; } -static void drm_property_change_valid_put(struct drm_property *property, +void drm_property_change_valid_put(struct drm_property *property, struct drm_mode_object *ref) { if (!ref) diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index adc822312f6cf6..a28c0abd1a38e1 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -630,6 +630,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATOMIC, drm_mode_atomic_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), }; #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index fc4767fa723b36..1dcfb685d15f27 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -902,7 +902,7 @@ struct drm_bridge { /** * struct struct drm_atomic_state - the global state object for atomic updates * @dev: parent DRM device - * @flags: state flags like async update + * @allow_modeset: allow full modeset * @planes: pointer to array of plane pointers * @plane_states: pointer to array of plane states pointers * @crtcs: pointer to array of CRTC pointers @@ -914,7 +914,7 @@ struct drm_bridge { */ struct drm_atomic_state { struct drm_device *dev; - uint32_t flags; + bool allow_modeset : 1; struct drm_plane **planes; struct drm_plane_state **plane_states; struct drm_crtc **crtcs; @@ -1346,6 +1346,10 @@ extern int drm_mode_create_scaling_mode_property(struct drm_device *dev); extern int drm_mode_create_aspect_ratio_property(struct drm_device *dev); extern int drm_mode_create_dirty_info_property(struct drm_device *dev); extern int drm_mode_create_suggested_offset_properties(struct drm_device *dev); +extern bool drm_property_change_valid_get(struct drm_property *property, + uint64_t value, struct drm_mode_object **ref); +extern void drm_property_change_valid_put(struct drm_property *property, + struct drm_mode_object *ref); extern int drm_mode_connector_attach_encoder(struct drm_connector *connector, struct drm_encoder *encoder); @@ -1437,6 +1441,8 @@ extern int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, extern int drm_mode_plane_set_obj_prop(struct drm_plane *plane, struct drm_property *property, uint64_t value); +extern int drm_mode_atomic_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); extern void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, int *bpp); diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index f7b2baf7ecb27b..01b2d6d0e35529 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -784,6 +784,7 @@ struct drm_prime_handle { #define DRM_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xB9, struct drm_mode_obj_get_properties) #define DRM_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct drm_mode_obj_set_property) #define DRM_IOCTL_MODE_CURSOR2 DRM_IOWR(0xBB, struct drm_mode_cursor2) +#define DRM_IOCTL_MODE_ATOMIC DRM_IOWR(0xBC, struct drm_mode_atomic) /** * Device specific ioctls should only be in their respective headers diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index b8f9c0f2e7fec0..ca788e01dab207 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -526,4 +526,27 @@ struct drm_mode_destroy_dumb { uint32_t handle; }; +/* page-flip flags are valid, plus: */ +#define DRM_MODE_ATOMIC_TEST_ONLY 0x0100 +#define DRM_MODE_ATOMIC_NONBLOCK 0x0200 +#define DRM_MODE_ATOMIC_ALLOW_MODESET 0x0400 + +#define DRM_MODE_ATOMIC_FLAGS (\ + DRM_MODE_PAGE_FLIP_EVENT |\ + DRM_MODE_PAGE_FLIP_ASYNC |\ + DRM_MODE_ATOMIC_TEST_ONLY |\ + DRM_MODE_ATOMIC_NONBLOCK |\ + DRM_MODE_ATOMIC_ALLOW_MODESET) + +struct drm_mode_atomic { + __u32 flags; + __u32 count_objs; + __u64 objs_ptr; + __u64 count_props_ptr; + __u64 props_ptr; + __u64 prop_values_ptr; + __u64 reserved; + __u64 user_data; +}; + #endif From a97df1ccd3c30f16385696964767adf854878021 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 18 Dec 2014 22:49:02 +0100 Subject: [PATCH 0400/3023] drm/atomic: Hide drm.ko internal interfaces This is just a bit fallout from patch polishing and moving the get_prop logic fully into the core: - Drop EXPORT_SYMBOL and make the helpers static. - Drop kerneldoc since not used by drivers. - Move the cross-file function declarations only used by drm.ko internally to an internal header. v2: keep the gist of the comments, requested by Rob. Cc: Rob Clark Reviewed-by: Rob Clark Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic.c | 54 ++++------------------------- drivers/gpu/drm/drm_crtc_internal.h | 6 ++++ drivers/gpu/drm/drm_ioctl.c | 1 + include/drm/drm_atomic.h | 12 ------- 4 files changed, 14 insertions(+), 59 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 67f64bd1058f68..1e38dfc8e462fd 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -247,21 +247,11 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc, } EXPORT_SYMBOL(drm_atomic_crtc_set_property); -/** - * drm_atomic_crtc_get_property - get property on CRTC - * @crtc: the drm CRTC to get a property on - * @state: the state object with the property value to read - * @property: the property to get - * @val: the property value (returned by reference) - * - * Use this instead of calling crtc->atomic_get_property directly. +/* * This function handles generic/core properties and calls out to * driver's ->atomic_get_property() for driver properties. To ensure * consistent behavior you must call this function rather than the * driver hook directly. - * - * RETURNS: - * Zero on success, error code on failure */ int drm_atomic_crtc_get_property(struct drm_crtc *crtc, const struct drm_crtc_state *state, @@ -271,7 +261,6 @@ int drm_atomic_crtc_get_property(struct drm_crtc *crtc, return crtc->funcs->atomic_get_property(crtc, state, property, val); return -EINVAL; } -EXPORT_SYMBOL(drm_atomic_crtc_get_property); /** * drm_atomic_crtc_check - check crtc state @@ -409,23 +398,14 @@ int drm_atomic_plane_set_property(struct drm_plane *plane, } EXPORT_SYMBOL(drm_atomic_plane_set_property); -/** - * drm_atomic_plane_get_property - get property on plane - * @plane: the drm plane to get a property on - * @state: the state object with the property value to read - * @property: the property to get - * @val: the property value (returned by reference) - * - * Use this instead of calling plane->atomic_get_property directly. +/* * This function handles generic/core properties and calls out to * driver's ->atomic_get_property() for driver properties. To ensure * consistent behavior you must call this function rather than the * driver hook directly. - * - * RETURNS: - * Zero on success, error code on failure */ -int drm_atomic_plane_get_property(struct drm_plane *plane, +static int +drm_atomic_plane_get_property(struct drm_plane *plane, const struct drm_plane_state *state, struct drm_property *property, uint64_t *val) { @@ -460,7 +440,6 @@ int drm_atomic_plane_get_property(struct drm_plane *plane, return 0; } -EXPORT_SYMBOL(drm_atomic_plane_get_property); /** * drm_atomic_plane_check - check plane state @@ -650,23 +629,14 @@ int drm_atomic_connector_set_property(struct drm_connector *connector, } EXPORT_SYMBOL(drm_atomic_connector_set_property); -/** - * drm_atomic_connector_get_property - get property on connector - * @connector: the drm connector to get a property on - * @state: the state object with the property value to read - * @property: the property to get - * @val: the property value (returned by reference) - * - * Use this instead of calling connector->atomic_get_property directly. +/* * This function handles generic/core properties and calls out to * driver's ->atomic_get_property() for driver properties. To ensure * consistent behavior you must call this function rather than the * driver hook directly. - * - * RETURNS: - * Zero on success, error code on failure */ -int drm_atomic_connector_get_property(struct drm_connector *connector, +static int +drm_atomic_connector_get_property(struct drm_connector *connector, const struct drm_connector_state *state, struct drm_property *property, uint64_t *val) { @@ -686,17 +656,7 @@ int drm_atomic_connector_get_property(struct drm_connector *connector, return 0; } -EXPORT_SYMBOL(drm_atomic_connector_get_property); -/** - * drm_atomic_get_property - helper to read atomic property - * @obj: drm mode object whose property to read - * @property: the property to read - * @val: the read value, returned by reference - * - * RETURNS: - * Zero on success, error code on failure - */ int drm_atomic_get_property(struct drm_mode_object *obj, struct drm_property *property, uint64_t *val) { diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h index a2945ee6d6755b..247dc8b625645b 100644 --- a/drivers/gpu/drm/drm_crtc_internal.h +++ b/drivers/gpu/drm/drm_crtc_internal.h @@ -36,3 +36,9 @@ int drm_mode_object_get(struct drm_device *dev, void drm_mode_object_put(struct drm_device *dev, struct drm_mode_object *object); +/* drm_atomic.c */ +int drm_atomic_get_property(struct drm_mode_object *obj, + struct drm_property *property, uint64_t *val); +int drm_mode_atomic_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); + diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index a28c0abd1a38e1..5cb40581224579 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -32,6 +32,7 @@ #include #include "drm_legacy.h" #include "drm_internal.h" +#include "drm_crtc_internal.h" #include #include diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 231fb485abb39c..51168a8b723a2d 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -41,30 +41,18 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state, int drm_atomic_crtc_set_property(struct drm_crtc *crtc, struct drm_crtc_state *state, struct drm_property *property, uint64_t val); -int drm_atomic_crtc_get_property(struct drm_crtc *crtc, - const struct drm_crtc_state *state, - struct drm_property *property, uint64_t *val); struct drm_plane_state * __must_check drm_atomic_get_plane_state(struct drm_atomic_state *state, struct drm_plane *plane); int drm_atomic_plane_set_property(struct drm_plane *plane, struct drm_plane_state *state, struct drm_property *property, uint64_t val); -int drm_atomic_plane_get_property(struct drm_plane *plane, - const struct drm_plane_state *state, - struct drm_property *property, uint64_t *val); struct drm_connector_state * __must_check drm_atomic_get_connector_state(struct drm_atomic_state *state, struct drm_connector *connector); int drm_atomic_connector_set_property(struct drm_connector *connector, struct drm_connector_state *state, struct drm_property *property, uint64_t val); -int drm_atomic_connector_get_property(struct drm_connector *connector, - const struct drm_connector_state *state, - struct drm_property *property, uint64_t *val); - -int drm_atomic_get_property(struct drm_mode_object *obj, - struct drm_property *property, uint64_t *val); int __must_check drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, From 179f158ccf15fb9425f53d589d1b48eab90449a6 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 19 Dec 2014 10:33:52 +0100 Subject: [PATCH 0401/3023] drm: Ensure universal_planes is set for atomic Atomic doesn't really work without universal planes anyway. But make sure that evil userspace doesn't pull the kernel over the table because we didn't consider a cornercase that just doesn't make sense, just for safety. v2: Just force ->universal_planes to the same value to avoid imposing restrictions on userspace. Cc: Rob Clark Reviewed-by: Rob Clark Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_ioctl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 5cb40581224579..3785d66721f2f6 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -355,6 +355,7 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv) if (req->value > 1) return -EINVAL; file_priv->atomic = req->value; + file_priv->universal_planes = req->value; break; default: return -EINVAL; From f76129d0ed2945b470adc96478d6347c58d22721 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Tue, 16 Dec 2014 12:20:57 +0100 Subject: [PATCH 0402/3023] ARM: imx: apf51dev: add gpio-backlight support Signed-off-by: Gwenhael Goavec-Merou Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx51-apf51dev.dts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/arm/boot/dts/imx51-apf51dev.dts b/arch/arm/boot/dts/imx51-apf51dev.dts index c5a9a24c280a48..93d3ea12328c50 100644 --- a/arch/arm/boot/dts/imx51-apf51dev.dts +++ b/arch/arm/boot/dts/imx51-apf51dev.dts @@ -16,6 +16,14 @@ model = "Armadeus Systems APF51Dev docking/development board"; compatible = "armadeus,imx51-apf51dev", "armadeus,imx51-apf51", "fsl,imx51"; + backlight@bl1{ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_backlight>; + compatible = "gpio-backlight"; + gpios = <&gpio3 4 GPIO_ACTIVE_HIGH>; + default-on; + }; + display@di1 { compatible = "fsl,imx-parallel-display"; interface-pix-fmt = "bgr666"; @@ -114,6 +122,12 @@ pinctrl-0 = <&pinctrl_hog>; imx51-apf51dev { + pinctrl_backlight: bl1grp { + fsl,pins = < + MX51_PAD_DI1_D1_CS__GPIO3_4 0x1F5 + >; + }; + pinctrl_hog: hoggrp { fsl,pins = < MX51_PAD_EIM_EB2__GPIO2_22 0x0C5 From c9997ba2aa6803eec44dd498d58b18e1b0784231 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 16 Dec 2014 11:02:41 -0200 Subject: [PATCH 0403/3023] ARM: dts: imx6qdl: Remove OCRAM clock from VPU node According to Documentation/devicetree/bindings/media/coda.txt: - clock-names : Should be "ahb", "per" The OCRAM clock is already provided inside the ocram node, so remove the OCRAM clock from the VPU node. Signed-off-by: Fabio Estevam Acked-by: Philipp Zabel Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl.dtsi | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi index 4fc03b7f1ceec5..f6c6a6e1cf3d13 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/imx6qdl.dtsi @@ -339,9 +339,8 @@ <0 12 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "bit", "jpeg"; clocks = <&clks IMX6QDL_CLK_VPU_AXI>, - <&clks IMX6QDL_CLK_MMDC_CH0_AXI>, - <&clks IMX6QDL_CLK_OCRAM>; - clock-names = "per", "ahb", "ocram"; + <&clks IMX6QDL_CLK_MMDC_CH0_AXI>; + clock-names = "per", "ahb"; resets = <&src 1>; iram = <&ocram>; }; From c565e146e6152f09177f214f3667f45522a90325 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 16 Dec 2014 17:30:29 -0200 Subject: [PATCH 0404/3023] ARM: dts: imx6sx-sdb: Add QSPI support imx6sx-sdb has two s25fl128s quad spi flash. Add support for them. Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6sx-sdb.dts | 39 ++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/arch/arm/boot/dts/imx6sx-sdb.dts b/arch/arm/boot/dts/imx6sx-sdb.dts index 1e6e5cc1c14cf2..cdffe8465c4652 100644 --- a/arch/arm/boot/dts/imx6sx-sdb.dts +++ b/arch/arm/boot/dts/imx6sx-sdb.dts @@ -340,6 +340,28 @@ status = "okay"; }; +&qspi2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_qspi2>; + status = "okay"; + + flash0: s25fl128s@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + compatible = "spansion,s25fl128s"; + spi-max-frequency = <66000000>; + }; + + flash1: s25fl128s@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <1>; + compatible = "spansion,s25fl128s"; + spi-max-frequency = <66000000>; + }; +}; + &ssi2 { status = "okay"; }; @@ -524,6 +546,23 @@ >; }; + pinctrl_qspi2: qspi2grp { + fsl,pins = < + MX6SX_PAD_NAND_WP_B__QSPI2_A_DATA_0 0x70f1 + MX6SX_PAD_NAND_READY_B__QSPI2_A_DATA_1 0x70f1 + MX6SX_PAD_NAND_CE0_B__QSPI2_A_DATA_2 0x70f1 + MX6SX_PAD_NAND_CE1_B__QSPI2_A_DATA_3 0x70f1 + MX6SX_PAD_NAND_CLE__QSPI2_A_SCLK 0x70f1 + MX6SX_PAD_NAND_ALE__QSPI2_A_SS0_B 0x70f1 + MX6SX_PAD_NAND_DATA01__QSPI2_B_DATA_0 0x70f1 + MX6SX_PAD_NAND_DATA00__QSPI2_B_DATA_1 0x70f1 + MX6SX_PAD_NAND_WE_B__QSPI2_B_DATA_2 0x70f1 + MX6SX_PAD_NAND_RE_B__QSPI2_B_DATA_3 0x70f1 + MX6SX_PAD_NAND_DATA02__QSPI2_B_SCLK 0x70f1 + MX6SX_PAD_NAND_DATA03__QSPI2_B_SS0_B 0x70f1 + >; + }; + pinctrl_vcc_sd3: vccsd3grp { fsl,pins = < MX6SX_PAD_KEY_COL1__GPIO2_IO_11 0x17059 From 8decfb05400d937265e1632d22967bbabc73feeb Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 16 Dec 2014 17:30:30 -0200 Subject: [PATCH 0405/3023] ARM: imx_v6_v7_defconfig: Select SPI_FSL_QUADSPI by default SPI_FSL_QUADSPI can be used by Vybrid and mx6sx, so select it by default. Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/configs/imx_v6_v7_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 96ac3a7d560935..9575af80493939 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -97,6 +97,7 @@ CONFIG_MTD_NAND=y CONFIG_MTD_NAND_GPMI_NAND=y CONFIG_MTD_NAND_MXC=y CONFIG_MTD_SPI_NOR=y +CONFIG_SPI_FSL_QUADSPI=y CONFIG_MTD_UBI=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y From 99fc5ba0bfb6df59ac22faa48406108e7203ceae Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 17 Dec 2014 12:22:09 +0800 Subject: [PATCH 0406/3023] ARM: dts: imx6sx: add i.mx6sx sabreauto board support Add basic i.MX6SoloX Sabre Auto board support, currently only debug UART and uSDHC are supported on this board. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/imx6sx-sabreauto.dts | 146 +++++++++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 arch/arm/boot/dts/imx6sx-sabreauto.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 91bd5bd628576d..c0d5c6619c9181 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -266,6 +266,7 @@ dtb-$(CONFIG_ARCH_MXC) += \ imx6q-tx6q-1020-comtft.dtb \ imx6q-tx6q-1110.dtb \ imx6sl-evk.dtb \ + imx6sx-sabreauto.dtb \ imx6sx-sdb.dtb \ ls1021a-qds.dtb \ ls1021a-twr.dtb \ diff --git a/arch/arm/boot/dts/imx6sx-sabreauto.dts b/arch/arm/boot/dts/imx6sx-sabreauto.dts new file mode 100644 index 00000000000000..e3c0b63c220567 --- /dev/null +++ b/arch/arm/boot/dts/imx6sx-sabreauto.dts @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/dts-v1/; + +#include "imx6sx.dtsi" + +/ { + model = "Freescale i.MX6 SoloX Sabre Auto Board"; + compatible = "fsl,imx6sx-sabreauto", "fsl,imx6sx"; + + memory { + reg = <0x80000000 0x80000000>; + }; + + regulators { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + vcc_sd3: regulator@0 { + compatible = "regulator-fixed"; + reg = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_vcc_sd3>; + regulator-name = "VCC_SD3"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + gpio = <&gpio2 11 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + }; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; + +&usdhc3 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc3>; + pinctrl-1 = <&pinctrl_usdhc3_100mhz>; + pinctrl-2 = <&pinctrl_usdhc3_200mhz>; + bus-width = <8>; + cd-gpios = <&gpio7 10 GPIO_ACTIVE_HIGH>; + wp-gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>; + keep-power-in-suspend; + enable-sdio-wakeup; + vmmc-supply = <&vcc_sd3>; + status = "okay"; +}; + +&usdhc4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc4>; + bus-width = <8>; + cd-gpios = <&gpio7 11 GPIO_ACTIVE_HIGH>; + no-1-8-v; + keep-power-in-suspend; + enable-sdio-wakup; + status = "okay"; +}; + +&iomuxc { + imx6x-sabreauto { + pinctrl_uart1: uart1grp { + fsl,pins = < + MX6SX_PAD_GPIO1_IO04__UART1_TX 0x1b0b1 + MX6SX_PAD_GPIO1_IO05__UART1_RX 0x1b0b1 + >; + }; + + pinctrl_usdhc3: usdhc3grp { + fsl,pins = < + MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x17059 + MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x10059 + MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x17059 + MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x17059 + MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x17059 + MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x17059 + MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x17059 + MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x17059 + MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x17059 + MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x17059 + MX6SX_PAD_KEY_COL0__GPIO2_IO_10 0x17059 /* CD */ + MX6SX_PAD_KEY_ROW0__GPIO2_IO_15 0x17059 /* WP */ + >; + }; + + pinctrl_usdhc3_100mhz: usdhc3grp-100mhz { + fsl,pins = < + MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170b9 + MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100b9 + MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170b9 + MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170b9 + MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170b9 + MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170b9 + MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x170b9 + MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x170b9 + MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x170b9 + MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x170b9 + >; + }; + + pinctrl_usdhc3_200mhz: usdhc3grp-200mhz { + fsl,pins = < + MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170f9 + MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100f9 + MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170f9 + MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170f9 + MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170f9 + MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170f9 + MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x170f9 + MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x170f9 + MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x170f9 + MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x170f9 + >; + }; + + pinctrl_usdhc4: usdhc4grp { + fsl,pins = < + MX6SX_PAD_SD4_CMD__USDHC4_CMD 0x17059 + MX6SX_PAD_SD4_CLK__USDHC4_CLK 0x10059 + MX6SX_PAD_SD4_DATA0__USDHC4_DATA0 0x17059 + MX6SX_PAD_SD4_DATA1__USDHC4_DATA1 0x17059 + MX6SX_PAD_SD4_DATA2__USDHC4_DATA2 0x17059 + MX6SX_PAD_SD4_DATA3__USDHC4_DATA3 0x17059 + MX6SX_PAD_SD4_DATA7__GPIO6_IO_21 0x17059 /* CD */ + MX6SX_PAD_SD4_DATA6__GPIO6_IO_20 0x17059 /* WP */ + >; + }; + + pinctrl_vcc_sd3: vccsd3grp { + fsl,pins = < + MX6SX_PAD_KEY_COL1__GPIO2_IO_11 0x17059 + >; + }; + }; +}; From df096fde0889a7a624fcc9616ff5ebd7446d131e Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 17 Dec 2014 12:23:19 +0800 Subject: [PATCH 0407/3023] ARM: imx: remove unnecessary setting for DSM Now we support DSM in OCRAM for all i.MX6 SoCs, the resume entry point is set in asm code of suspend-imx6.S, so no need to set the resume entry point for SRC in pre-suspend flow. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/mach-imx/pm-imx6.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c index 5d2c1bd5f5ef91..661ffcf1031e00 100644 --- a/arch/arm/mach-imx/pm-imx6.c +++ b/arch/arm/mach-imx/pm-imx6.c @@ -362,7 +362,6 @@ static int imx6q_pm_enter(suspend_state_t state) imx6q_enable_rbc(true); imx_gpc_pre_suspend(true); imx_anatop_pre_suspend(); - imx_set_cpu_jump(0, v7_cpu_resume); /* Zzz ... */ cpu_suspend(0, imx6q_suspend_finish); if (cpu_is_imx6q() || cpu_is_imx6dl()) From 05136f0897b526b9cd090c93b95bbd1b67c18cc5 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 17 Dec 2014 12:24:12 +0800 Subject: [PATCH 0408/3023] ARM: imx: support arm power off in cpuidle for i.mx6sx This patch introduces an independent cpuidle driver for i.MX6SX, and supports arm power off in idle, totally 3 levels of cpuidle are supported as below: 1. ARM WFI; 2. SOC in WAIT mode; 3. SOC in WAIT mode + ARM power off. ARM power off can save at least 5mW power. This patch also replaces imx6q_enable_rbc with imx6_enable_rbc. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/mach-imx/Makefile | 3 +- arch/arm/mach-imx/common.h | 4 ++ arch/arm/mach-imx/cpuidle-imx6sx.c | 107 +++++++++++++++++++++++++++++ arch/arm/mach-imx/cpuidle.h | 5 ++ arch/arm/mach-imx/gpc.c | 25 ++++++- arch/arm/mach-imx/mach-imx6sx.c | 2 +- arch/arm/mach-imx/pm-imx6.c | 6 +- 7 files changed, 144 insertions(+), 8 deletions(-) create mode 100644 arch/arm/mach-imx/cpuidle-imx6sx.c diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index f5ac685a29fc4d..8d1b1018090898 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -32,8 +32,7 @@ ifeq ($(CONFIG_CPU_IDLE),y) obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o -# i.MX6SX reuses i.MX6Q cpuidle driver -obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6q.o +obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6sx.o endif ifdef CONFIG_SND_IMX_SOC diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index cfcdb623d78fc5..1028b6c505c496 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -70,6 +70,10 @@ void imx_set_soc_revision(unsigned int rev); unsigned int imx_get_soc_revision(void); void imx_init_revision_from_anatop(void); struct device *imx_soc_device_init(void); +void imx6_enable_rbc(bool enable); +void imx_gpc_set_arm_power_in_lpm(bool power_off); +void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw); +void imx_gpc_set_arm_power_down_timing(u32 sw2iso, u32 sw); enum mxc_cpu_pwr_mode { WAIT_CLOCKED, /* wfi only */ diff --git a/arch/arm/mach-imx/cpuidle-imx6sx.c b/arch/arm/mach-imx/cpuidle-imx6sx.c new file mode 100644 index 00000000000000..d8a9f219e02863 --- /dev/null +++ b/arch/arm/mach-imx/cpuidle-imx6sx.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "cpuidle.h" + +static int imx6sx_idle_finish(unsigned long val) +{ + cpu_do_idle(); + + return 0; +} + +static int imx6sx_enter_wait(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + imx6q_set_lpm(WAIT_UNCLOCKED); + + switch (index) { + case 1: + cpu_do_idle(); + break; + case 2: + imx6_enable_rbc(true); + imx_gpc_set_arm_power_in_lpm(true); + imx_set_cpu_jump(0, v7_cpu_resume); + /* Need to notify there is a cpu pm operation. */ + cpu_pm_enter(); + cpu_cluster_pm_enter(); + + cpu_suspend(0, imx6sx_idle_finish); + + cpu_cluster_pm_exit(); + cpu_pm_exit(); + imx_gpc_set_arm_power_in_lpm(false); + imx6_enable_rbc(false); + break; + default: + break; + } + + imx6q_set_lpm(WAIT_CLOCKED); + + return index; +} + +static struct cpuidle_driver imx6sx_cpuidle_driver = { + .name = "imx6sx_cpuidle", + .owner = THIS_MODULE, + .states = { + /* WFI */ + ARM_CPUIDLE_WFI_STATE, + /* WAIT */ + { + .exit_latency = 50, + .target_residency = 75, + .flags = CPUIDLE_FLAG_TIME_VALID | + CPUIDLE_FLAG_TIMER_STOP, + .enter = imx6sx_enter_wait, + .name = "WAIT", + .desc = "Clock off", + }, + /* WAIT + ARM power off */ + { + /* + * ARM gating 31us * 5 + RBC clear 65us + * and some margin for SW execution, here set it + * to 300us. + */ + .exit_latency = 300, + .target_residency = 500, + .flags = CPUIDLE_FLAG_TIME_VALID, + .enter = imx6sx_enter_wait, + .name = "LOW-POWER-IDLE", + .desc = "ARM power off", + }, + }, + .state_count = 3, + .safe_state_index = 0, +}; + +int __init imx6sx_cpuidle_init(void) +{ + imx6_enable_rbc(false); + /* + * set ARM power up/down timing to the fastest, + * sw2iso and sw can be set to one 32K cycle = 31us + * except for power up sw2iso which need to be + * larger than LDO ramp up time. + */ + imx_gpc_set_arm_power_up_timing(2, 1); + imx_gpc_set_arm_power_down_timing(1, 1); + + return cpuidle_register(&imx6sx_cpuidle_driver, NULL); +} diff --git a/arch/arm/mach-imx/cpuidle.h b/arch/arm/mach-imx/cpuidle.h index 24e33670417c1d..f9140128ba0518 100644 --- a/arch/arm/mach-imx/cpuidle.h +++ b/arch/arm/mach-imx/cpuidle.h @@ -14,6 +14,7 @@ extern int imx5_cpuidle_init(void); extern int imx6q_cpuidle_init(void); extern int imx6sl_cpuidle_init(void); +extern int imx6sx_cpuidle_init(void); #else static inline int imx5_cpuidle_init(void) { @@ -27,4 +28,8 @@ static inline int imx6sl_cpuidle_init(void) { return 0; } +static inline int imx6sx_cpuidle_init(void) +{ + return 0; +} #endif diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c index 5f3602ec74fac5..745caa18ab2c0b 100644 --- a/arch/arm/mach-imx/gpc.c +++ b/arch/arm/mach-imx/gpc.c @@ -20,6 +20,10 @@ #define GPC_IMR1 0x008 #define GPC_PGC_CPU_PDN 0x2a0 +#define GPC_PGC_CPU_PUPSCR 0x2a4 +#define GPC_PGC_CPU_PDNSCR 0x2a8 +#define GPC_PGC_SW2ISO_SHIFT 0x8 +#define GPC_PGC_SW_SHIFT 0x0 #define IMR_NUM 4 @@ -27,6 +31,23 @@ static void __iomem *gpc_base; static u32 gpc_wake_irqs[IMR_NUM]; static u32 gpc_saved_imrs[IMR_NUM]; +void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw) +{ + writel_relaxed((sw2iso << GPC_PGC_SW2ISO_SHIFT) | + (sw << GPC_PGC_SW_SHIFT), gpc_base + GPC_PGC_CPU_PUPSCR); +} + +void imx_gpc_set_arm_power_down_timing(u32 sw2iso, u32 sw) +{ + writel_relaxed((sw2iso << GPC_PGC_SW2ISO_SHIFT) | + (sw << GPC_PGC_SW_SHIFT), gpc_base + GPC_PGC_CPU_PDNSCR); +} + +void imx_gpc_set_arm_power_in_lpm(bool power_off) +{ + writel_relaxed(power_off, gpc_base + GPC_PGC_CPU_PDN); +} + void imx_gpc_pre_suspend(bool arm_power_off) { void __iomem *reg_imr1 = gpc_base + GPC_IMR1; @@ -34,7 +55,7 @@ void imx_gpc_pre_suspend(bool arm_power_off) /* Tell GPC to power off ARM core when suspend */ if (arm_power_off) - writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN); + imx_gpc_set_arm_power_in_lpm(arm_power_off); for (i = 0; i < IMR_NUM; i++) { gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4); @@ -48,7 +69,7 @@ void imx_gpc_post_resume(void) int i; /* Keep ARM core powered on for other low-power modes */ - writel_relaxed(0x0, gpc_base + GPC_PGC_CPU_PDN); + imx_gpc_set_arm_power_in_lpm(false); for (i = 0; i < IMR_NUM; i++) writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4); diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c index 7a96c65772344f..66988eb6a3a4dc 100644 --- a/arch/arm/mach-imx/mach-imx6sx.c +++ b/arch/arm/mach-imx/mach-imx6sx.c @@ -90,7 +90,7 @@ static void __init imx6sx_init_irq(void) static void __init imx6sx_init_late(void) { - imx6q_cpuidle_init(); + imx6sx_cpuidle_init(); if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0); diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c index 661ffcf1031e00..46fd695203c70a 100644 --- a/arch/arm/mach-imx/pm-imx6.c +++ b/arch/arm/mach-imx/pm-imx6.c @@ -205,7 +205,7 @@ void imx6q_set_int_mem_clk_lpm(bool enable) writel_relaxed(val, ccm_base + CGPR); } -static void imx6q_enable_rbc(bool enable) +void imx6_enable_rbc(bool enable) { u32 val; @@ -359,7 +359,7 @@ static int imx6q_pm_enter(suspend_state_t state) * RBC setting, so we do NOT need to do that here. */ if (!imx6_suspend_in_ocram_fn) - imx6q_enable_rbc(true); + imx6_enable_rbc(true); imx_gpc_pre_suspend(true); imx_anatop_pre_suspend(); /* Zzz ... */ @@ -368,7 +368,7 @@ static int imx6q_pm_enter(suspend_state_t state) imx_smp_prepare(); imx_anatop_post_resume(); imx_gpc_post_resume(); - imx6q_enable_rbc(false); + imx6_enable_rbc(false); imx6q_enable_wb(false); imx6q_set_int_mem_clk_lpm(true); imx6q_set_lpm(WAIT_CLOCKED); From dd7d2be1d2b8abb3754b19e4ebe72a4293253e4e Mon Sep 17 00:00:00 2001 From: Evgeni Dobrev Date: Sun, 28 Dec 2014 11:46:54 +0100 Subject: [PATCH 0409/3023] Kirkwood: add support for Seagate BlackArmor NAS220 This patch adds support for Seagate BlackArmor NAS220. The Seagate BlackArmor NAS 220 is a NAS system based on Marvell 88f6192. It has 32MB NAND and 128MB DRAM. It has two SATA slots, one Gigabit Ethernet port, two USB 2.0 ports, two buttons and three LEDs. There is a serial port available on the CN5 connector on the board (1 - TX, 4 - RX, 6 - GND). The only functionality still not implemented is the bi-color led on the front panel (status). Pins mpp22 and mpp23 control this led. Setting mpp22 to high and mpp23 to low results in orange color. Setting mpp22 to low and mpp23 to high results in blue color. The third led is wired to show the SATA activity on the two drives. Signed-off-by: Evgeni Dobrev Acked-by: Sebastian Hesselbarth Signed-off-by: Andrew Lunn --- arch/arm/boot/dts/Makefile | 1 + .../boot/dts/kirkwood-blackarmor-nas220.dts | 173 ++++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 arch/arm/boot/dts/kirkwood-blackarmor-nas220.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 91bd5bd628576d..6dc9c17f9ff578 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -112,6 +112,7 @@ dtb-$(CONFIG_ARCH_KEYSTONE) += k2hk-evm.dtb \ k2l-evm.dtb \ k2e-evm.dtb dtb-$(CONFIG_MACH_KIRKWOOD) += kirkwood-b3.dtb \ + kirkwood-blackarmor-nas220.dtb \ kirkwood-cloudbox.dtb \ kirkwood-d2net.dtb \ kirkwood-db-88f6281.dtb \ diff --git a/arch/arm/boot/dts/kirkwood-blackarmor-nas220.dts b/arch/arm/boot/dts/kirkwood-blackarmor-nas220.dts new file mode 100644 index 00000000000000..fa02a9aff05e1c --- /dev/null +++ b/arch/arm/boot/dts/kirkwood-blackarmor-nas220.dts @@ -0,0 +1,173 @@ +/* + * Device Tree file for Seagate Blackarmor NAS220 + * + * Copyright (C) 2014 Evgeni Dobrev + * + * Licensed under GPLv2 or later. + */ + +/dts-v1/; + +#include +#include +#include "kirkwood.dtsi" +#include "kirkwood-6192.dtsi" + +/ { + model = "Seagate Blackarmor NAS220"; + compatible = "seagate,blackarmor-nas220","marvell,kirkwood-88f6192", + "marvell,kirkwood"; + + memory { /* 128 MB */ + device_type = "memory"; + reg = <0x00000000 0x8000000>; + }; + + chosen { + bootargs = "console=ttyS0,115200n8"; + stdout-path = &uart0; + }; + + gpio_poweroff { + compatible = "gpio-poweroff"; + gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + }; + + gpio_keys { + compatible = "gpio-keys"; + + button@1{ + label = "Reset"; + linux,code = ; + gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>; + }; + + button@2{ + label = "Power"; + linux,code = ; + gpios = <&gpio0 26 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + blue-power { + label = "nas220:blue:power"; + gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "default-on"; + }; + }; + + regulators { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-0 = <&pmx_power_sata0 &pmx_power_sata1>; + pinctrl-names = "default"; + + sata0_power: regulator@1 { + compatible = "regulator-fixed"; + reg = <1>; + regulator-name = "SATA0 Power"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + gpio = <&gpio0 24 GPIO_ACTIVE_LOW>; + }; + + sata1_power: regulator@2 { + compatible = "regulator-fixed"; + reg = <2>; + regulator-name = "SATA1 Power"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + gpio = <&gpio0 28 GPIO_ACTIVE_LOW>; + }; + }; +}; + +/* + * Serial port routed to connector CN5 + * + * pin 1 - TX (CPU's TX) + * pin 4 - RX (CPU's RX) + * pin 6 - GND + */ +&uart0 { + status = "okay"; +}; + +&pinctrl { + pinctrl-0 = <&pmx_button_reset &pmx_button_power>; + pinctrl-names = "default"; + + pmx_act_sata0: pmx-act-sata0 { + marvell,pins = "mpp15"; + marvell,function = "sata0"; + }; + + pmx_act_sata1: pmx-act-sata1 { + marvell,pins = "mpp16"; + marvell,function = "sata1"; + }; + + pmx_power_sata0: pmx-power-sata0 { + marvell,pins = "mpp24"; + marvell,function = "gpio"; + }; + + pmx_power_sata1: pmx-power-sata1 { + marvell,pins = "mpp28"; + marvell,function = "gpio"; + }; + + pmx_button_reset: pmx-button-reset { + marvell,pins = "mpp29"; + marvell,function = "gpio"; + }; + + pmx_button_power: pmx-button-power { + marvell,pins = "mpp26"; + marvell,function = "gpio"; + }; +}; + +&sata { + status = "okay"; + nr-ports = <2>; +}; + +&i2c0 { + status = "okay"; + + adt7476: thermal@2e { + compatible = "adi,adt7476"; + reg = <0x2e>; + }; +}; + +&nand { + status = "okay"; +}; + +&mdio { + status = "okay"; + + ethphy0: ethernet-phy@8 { + reg = <8>; + }; +}; + +ð0 { + status = "okay"; + + ethernet0-port@0 { + phy-handle = <ðphy0>; + }; +}; From 4193c0f1d8631d439cea5f78329fe70f3a6e9128 Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Mon, 29 Dec 2014 14:41:14 +0200 Subject: [PATCH 0410/3023] iio: driver for Semtech SX9500 proximity solution Supports buffering, IIO events and changing sampling frequency. Datasheet available at: http://www.semtech.com/images/datasheet/sx9500_ag.pdf Signed-off-by: Vlad Dogaru Reviewed-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/Kconfig | 17 + drivers/iio/proximity/Makefile | 1 + drivers/iio/proximity/sx9500.c | 752 +++++++++++++++++++++++++++++++++ 3 files changed, 770 insertions(+) create mode 100644 drivers/iio/proximity/sx9500.c diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig index 0c8cdf58f6a19b..41a8d8ffa0de47 100644 --- a/drivers/iio/proximity/Kconfig +++ b/drivers/iio/proximity/Kconfig @@ -17,3 +17,20 @@ config AS3935 module will be called as3935 endmenu + +menu "Proximity sensors" + +config SX9500 + tristate "SX9500 Semtech proximity sensor" + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + select REGMAP_I2C + depends on I2C + help + Say Y here to build a driver for Semtech's SX9500 capacitive + proximity/button sensor. + + To compile this driver as a module, choose M here: the + module will be called sx9500. + +endmenu diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile index 743adee1c8bff9..9818dc562abdc5 100644 --- a/drivers/iio/proximity/Makefile +++ b/drivers/iio/proximity/Makefile @@ -4,3 +4,4 @@ # When adding new entries keep the list in alphabetical order obj-$(CONFIG_AS3935) += as3935.o +obj-$(CONFIG_SX9500) += sx9500.o diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c new file mode 100644 index 00000000000000..74dff4e4a11acd --- /dev/null +++ b/drivers/iio/proximity/sx9500.c @@ -0,0 +1,752 @@ +/* + * Copyright (c) 2014 Intel Corporation + * + * Driver for Semtech's SX9500 capacitive proximity/button solution. + * Datasheet available at + * . + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define SX9500_DRIVER_NAME "sx9500" +#define SX9500_IRQ_NAME "sx9500_event" +#define SX9500_GPIO_NAME "sx9500_gpio" + +/* Register definitions. */ +#define SX9500_REG_IRQ_SRC 0x00 +#define SX9500_REG_STAT 0x01 +#define SX9500_REG_IRQ_MSK 0x03 + +#define SX9500_REG_PROX_CTRL0 0x06 +#define SX9500_REG_PROX_CTRL1 0x07 +#define SX9500_REG_PROX_CTRL2 0x08 +#define SX9500_REG_PROX_CTRL3 0x09 +#define SX9500_REG_PROX_CTRL4 0x0a +#define SX9500_REG_PROX_CTRL5 0x0b +#define SX9500_REG_PROX_CTRL6 0x0c +#define SX9500_REG_PROX_CTRL7 0x0d +#define SX9500_REG_PROX_CTRL8 0x0e + +#define SX9500_REG_SENSOR_SEL 0x20 +#define SX9500_REG_USE_MSB 0x21 +#define SX9500_REG_USE_LSB 0x22 +#define SX9500_REG_AVG_MSB 0x23 +#define SX9500_REG_AVG_LSB 0x24 +#define SX9500_REG_DIFF_MSB 0x25 +#define SX9500_REG_DIFF_LSB 0x26 +#define SX9500_REG_OFFSET_MSB 0x27 +#define SX9500_REG_OFFSET_LSB 0x28 + +#define SX9500_REG_RESET 0x7f + +/* Write this to REG_RESET to do a soft reset. */ +#define SX9500_SOFT_RESET 0xde + +#define SX9500_SCAN_PERIOD_MASK GENMASK(6, 4) +#define SX9500_SCAN_PERIOD_SHIFT 4 + +/* + * These serve for identifying IRQ source in the IRQ_SRC register, and + * also for masking the IRQs in the IRQ_MSK register. + */ +#define SX9500_CLOSE_IRQ BIT(6) +#define SX9500_FAR_IRQ BIT(5) +#define SX9500_CONVDONE_IRQ BIT(3) + +#define SX9500_PROXSTAT_SHIFT 4 + +#define SX9500_NUM_CHANNELS 4 + +struct sx9500_data { + struct mutex mutex; + struct i2c_client *client; + struct iio_trigger *trig; + struct regmap *regmap; + /* + * Last reading of the proximity status for each channel. We + * only send an event to user space when this changes. + */ + bool prox_stat[SX9500_NUM_CHANNELS]; + bool event_enabled[SX9500_NUM_CHANNELS]; + bool trigger_enabled; + u16 *buffer; +}; + +static const struct iio_event_spec sx9500_events[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_EITHER, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), + }, +}; + +#define SX9500_CHANNEL(idx) \ + { \ + .type = IIO_PROXIMITY, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .indexed = 1, \ + .channel = idx, \ + .event_spec = sx9500_events, \ + .num_event_specs = ARRAY_SIZE(sx9500_events), \ + .scan_index = idx, \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 16, \ + .storagebits = 16, \ + .shift = 0, \ + }, \ + } + +static const struct iio_chan_spec sx9500_channels[] = { + SX9500_CHANNEL(0), + SX9500_CHANNEL(1), + SX9500_CHANNEL(2), + SX9500_CHANNEL(3), + IIO_CHAN_SOFT_TIMESTAMP(4), +}; + +static const struct { + int val; + int val2; +} sx9500_samp_freq_table[] = { + {33, 333333}, + {16, 666666}, + {11, 111111}, + {8, 333333}, + {6, 666666}, + {5, 0}, + {3, 333333}, + {2, 500000}, +}; + +static const struct regmap_range sx9500_writable_reg_ranges[] = { + regmap_reg_range(SX9500_REG_IRQ_MSK, SX9500_REG_IRQ_MSK), + regmap_reg_range(SX9500_REG_PROX_CTRL0, SX9500_REG_PROX_CTRL8), + regmap_reg_range(SX9500_REG_SENSOR_SEL, SX9500_REG_SENSOR_SEL), + regmap_reg_range(SX9500_REG_OFFSET_MSB, SX9500_REG_OFFSET_LSB), + regmap_reg_range(SX9500_REG_RESET, SX9500_REG_RESET), +}; + +static const struct regmap_access_table sx9500_writeable_regs = { + .yes_ranges = sx9500_writable_reg_ranges, + .n_yes_ranges = ARRAY_SIZE(sx9500_writable_reg_ranges), +}; + +/* + * All allocated registers are readable, so we just list unallocated + * ones. + */ +static const struct regmap_range sx9500_non_readable_reg_ranges[] = { + regmap_reg_range(SX9500_REG_STAT + 1, SX9500_REG_STAT + 1), + regmap_reg_range(SX9500_REG_IRQ_MSK + 1, SX9500_REG_PROX_CTRL0 - 1), + regmap_reg_range(SX9500_REG_PROX_CTRL8 + 1, SX9500_REG_SENSOR_SEL - 1), + regmap_reg_range(SX9500_REG_OFFSET_LSB + 1, SX9500_REG_RESET - 1), +}; + +static const struct regmap_access_table sx9500_readable_regs = { + .no_ranges = sx9500_non_readable_reg_ranges, + .n_no_ranges = ARRAY_SIZE(sx9500_non_readable_reg_ranges), +}; + +static const struct regmap_range sx9500_volatile_reg_ranges[] = { + regmap_reg_range(SX9500_REG_IRQ_SRC, SX9500_REG_STAT), + regmap_reg_range(SX9500_REG_USE_MSB, SX9500_REG_OFFSET_LSB), + regmap_reg_range(SX9500_REG_RESET, SX9500_REG_RESET), +}; + +static const struct regmap_access_table sx9500_volatile_regs = { + .yes_ranges = sx9500_volatile_reg_ranges, + .n_yes_ranges = ARRAY_SIZE(sx9500_volatile_reg_ranges), +}; + +static const struct regmap_config sx9500_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = SX9500_REG_RESET, + .cache_type = REGCACHE_RBTREE, + + .wr_table = &sx9500_writeable_regs, + .rd_table = &sx9500_readable_regs, + .volatile_table = &sx9500_volatile_regs, +}; + +static int sx9500_read_proximity(struct sx9500_data *data, + const struct iio_chan_spec *chan, + int *val) +{ + int ret; + __be16 regval; + + ret = regmap_write(data->regmap, SX9500_REG_SENSOR_SEL, chan->channel); + if (ret < 0) + return ret; + + ret = regmap_bulk_read(data->regmap, SX9500_REG_USE_MSB, ®val, 2); + if (ret < 0) + return ret; + + *val = 32767 - (s16)be16_to_cpu(regval); + + return IIO_VAL_INT; +} + +static int sx9500_read_samp_freq(struct sx9500_data *data, + int *val, int *val2) +{ + int ret; + unsigned int regval; + + mutex_lock(&data->mutex); + ret = regmap_read(data->regmap, SX9500_REG_PROX_CTRL0, ®val); + mutex_unlock(&data->mutex); + + if (ret < 0) + return ret; + + regval = (regval & SX9500_SCAN_PERIOD_MASK) >> SX9500_SCAN_PERIOD_SHIFT; + *val = sx9500_samp_freq_table[regval].val; + *val2 = sx9500_samp_freq_table[regval].val2; + + return IIO_VAL_INT_PLUS_MICRO; +} + +static int sx9500_read_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + int *val, int *val2, long mask) +{ + struct sx9500_data *data = iio_priv(indio_dev); + int ret; + + switch (chan->type) { + case IIO_PROXIMITY: + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (iio_buffer_enabled(indio_dev)) + return -EBUSY; + mutex_lock(&data->mutex); + ret = sx9500_read_proximity(data, chan, val); + mutex_unlock(&data->mutex); + return ret; + case IIO_CHAN_INFO_SAMP_FREQ: + return sx9500_read_samp_freq(data, val, val2); + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int sx9500_set_samp_freq(struct sx9500_data *data, + int val, int val2) +{ + int i, ret; + + for (i = 0; i < ARRAY_SIZE(sx9500_samp_freq_table); i++) + if (val == sx9500_samp_freq_table[i].val && + val2 == sx9500_samp_freq_table[i].val2) + break; + + if (i == ARRAY_SIZE(sx9500_samp_freq_table)) + return -EINVAL; + + mutex_lock(&data->mutex); + + ret = regmap_update_bits(data->regmap, SX9500_REG_PROX_CTRL0, + SX9500_SCAN_PERIOD_MASK, + i << SX9500_SCAN_PERIOD_SHIFT); + + mutex_unlock(&data->mutex); + + return ret; +} + +static int sx9500_write_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + int val, int val2, long mask) +{ + struct sx9500_data *data = iio_priv(indio_dev); + + switch (chan->type) { + case IIO_PROXIMITY: + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + return sx9500_set_samp_freq(data, val, val2); + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static irqreturn_t sx9500_irq_handler(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct sx9500_data *data = iio_priv(indio_dev); + + if (data->trigger_enabled) + iio_trigger_poll(data->trig); + + /* + * Even if no event is enabled, we need to wake the thread to + * clear the interrupt state by reading SX9500_REG_IRQ_SRC. It + * is not possible to do that here because regmap_read takes a + * mutex. + */ + return IRQ_WAKE_THREAD; +} + +static irqreturn_t sx9500_irq_thread_handler(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct sx9500_data *data = iio_priv(indio_dev); + int ret; + unsigned int val, chan; + + mutex_lock(&data->mutex); + + ret = regmap_read(data->regmap, SX9500_REG_IRQ_SRC, &val); + if (ret < 0) { + dev_err(&data->client->dev, "i2c transfer error in irq\n"); + goto out; + } + + if (!(val & (SX9500_CLOSE_IRQ | SX9500_FAR_IRQ))) + goto out; + + ret = regmap_read(data->regmap, SX9500_REG_STAT, &val); + if (ret < 0) { + dev_err(&data->client->dev, "i2c transfer error in irq\n"); + goto out; + } + + val >>= SX9500_PROXSTAT_SHIFT; + for (chan = 0; chan < SX9500_NUM_CHANNELS; chan++) { + int dir; + u64 ev; + bool new_prox = val & BIT(chan); + + if (!data->event_enabled[chan]) + continue; + if (new_prox == data->prox_stat[chan]) + /* No change on this channel. */ + continue; + + dir = new_prox ? IIO_EV_DIR_FALLING : + IIO_EV_DIR_RISING; + ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, + chan, + IIO_EV_TYPE_THRESH, + dir); + iio_push_event(indio_dev, ev, iio_get_time_ns()); + data->prox_stat[chan] = new_prox; + } + +out: + mutex_unlock(&data->mutex); + + return IRQ_HANDLED; +} + +static int sx9500_read_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct sx9500_data *data = iio_priv(indio_dev); + + if (chan->type != IIO_PROXIMITY || type != IIO_EV_TYPE_THRESH || + dir != IIO_EV_DIR_EITHER) + return -EINVAL; + + return data->event_enabled[chan->channel]; +} + +static int sx9500_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + int state) +{ + struct sx9500_data *data = iio_priv(indio_dev); + int ret, i; + bool any_active = false; + unsigned int irqmask; + + if (chan->type != IIO_PROXIMITY || type != IIO_EV_TYPE_THRESH || + dir != IIO_EV_DIR_EITHER) + return -EINVAL; + + mutex_lock(&data->mutex); + + data->event_enabled[chan->channel] = state; + + for (i = 0; i < SX9500_NUM_CHANNELS; i++) + if (data->event_enabled[i]) { + any_active = true; + break; + } + + irqmask = SX9500_CLOSE_IRQ | SX9500_FAR_IRQ; + if (any_active) + ret = regmap_update_bits(data->regmap, SX9500_REG_IRQ_MSK, + irqmask, irqmask); + else + ret = regmap_update_bits(data->regmap, SX9500_REG_IRQ_MSK, + irqmask, 0); + + mutex_unlock(&data->mutex); + + return ret; +} + +static int sx9500_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + struct sx9500_data *data = iio_priv(indio_dev); + + mutex_lock(&data->mutex); + kfree(data->buffer); + data->buffer = kzalloc(indio_dev->scan_bytes, GFP_KERNEL); + mutex_unlock(&data->mutex); + + if (data->buffer == NULL) + return -ENOMEM; + + return 0; +} + +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( + "2.500000 3.333333 5 6.666666 8.333333 11.111111 16.666666 33.333333"); + +static struct attribute *sx9500_attributes[] = { + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group sx9500_attribute_group = { + .attrs = sx9500_attributes, +}; + +static const struct iio_info sx9500_info = { + .driver_module = THIS_MODULE, + .attrs = &sx9500_attribute_group, + .read_raw = &sx9500_read_raw, + .write_raw = &sx9500_write_raw, + .read_event_config = &sx9500_read_event_config, + .write_event_config = &sx9500_write_event_config, + .update_scan_mode = &sx9500_update_scan_mode, +}; + +static int sx9500_set_trigger_state(struct iio_trigger *trig, + bool state) +{ + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct sx9500_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->mutex); + + ret = regmap_update_bits(data->regmap, SX9500_REG_IRQ_MSK, + SX9500_CONVDONE_IRQ, + state ? SX9500_CONVDONE_IRQ : 0); + if (ret == 0) + data->trigger_enabled = state; + + mutex_unlock(&data->mutex); + + return ret; +} + +static const struct iio_trigger_ops sx9500_trigger_ops = { + .set_trigger_state = sx9500_set_trigger_state, + .owner = THIS_MODULE, +}; + +static irqreturn_t sx9500_trigger_handler(int irq, void *private) +{ + struct iio_poll_func *pf = private; + struct iio_dev *indio_dev = pf->indio_dev; + struct sx9500_data *data = iio_priv(indio_dev); + int val, bit, ret, i = 0; + + mutex_lock(&data->mutex); + + for_each_set_bit(bit, indio_dev->buffer->scan_mask, + indio_dev->masklength) { + ret = sx9500_read_proximity(data, &indio_dev->channels[bit], + &val); + if (ret < 0) + goto out; + + data->buffer[i++] = val; + } + + iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_get_time_ns()); + +out: + mutex_unlock(&data->mutex); + + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +struct sx9500_reg_default { + u8 reg; + u8 def; +}; + +static const struct sx9500_reg_default sx9500_default_regs[] = { + { + .reg = SX9500_REG_PROX_CTRL1, + /* Shield enabled, small range. */ + .def = 0x43, + }, + { + .reg = SX9500_REG_PROX_CTRL2, + /* x8 gain, 167kHz frequency, finest resolution. */ + .def = 0x77, + }, + { + .reg = SX9500_REG_PROX_CTRL3, + /* Doze enabled, 2x scan period doze, no raw filter. */ + .def = 0x40, + }, + { + .reg = SX9500_REG_PROX_CTRL4, + /* Average threshold. */ + .def = 0x30, + }, + { + .reg = SX9500_REG_PROX_CTRL5, + /* + * Debouncer off, lowest average negative filter, + * highest average postive filter. + */ + .def = 0x0f, + }, + { + .reg = SX9500_REG_PROX_CTRL6, + /* Proximity detection threshold: 280 */ + .def = 0x0e, + }, + { + .reg = SX9500_REG_PROX_CTRL7, + /* + * No automatic compensation, compensate each pin + * independently, proximity hysteresis: 32, close + * debouncer off, far debouncer off. + */ + .def = 0x00, + }, + { + .reg = SX9500_REG_PROX_CTRL8, + /* No stuck timeout, no periodic compensation. */ + .def = 0x00, + }, + { + .reg = SX9500_REG_PROX_CTRL0, + /* Scan period: 30ms, all sensors enabled. */ + .def = 0x0f, + }, +}; + +static int sx9500_init_device(struct iio_dev *indio_dev) +{ + struct sx9500_data *data = iio_priv(indio_dev); + int ret, i; + unsigned int val; + + ret = regmap_write(data->regmap, SX9500_REG_IRQ_MSK, 0); + if (ret < 0) + return ret; + + ret = regmap_write(data->regmap, SX9500_REG_RESET, + SX9500_SOFT_RESET); + if (ret < 0) + return ret; + + ret = regmap_read(data->regmap, SX9500_REG_IRQ_SRC, &val); + if (ret < 0) + return ret; + + for (i = 0; i < ARRAY_SIZE(sx9500_default_regs); i++) { + ret = regmap_write(data->regmap, + sx9500_default_regs[i].reg, + sx9500_default_regs[i].def); + if (ret < 0) + return ret; + } + + return 0; +} + +static int sx9500_gpio_probe(struct i2c_client *client, + struct sx9500_data *data) +{ + struct device *dev; + struct gpio_desc *gpio; + int ret; + + if (!client) + return -EINVAL; + + dev = &client->dev; + + /* data ready gpio interrupt pin */ + gpio = devm_gpiod_get_index(dev, SX9500_GPIO_NAME, 0); + if (IS_ERR(gpio)) { + dev_err(dev, "acpi gpio get index failed\n"); + return PTR_ERR(gpio); + } + + ret = gpiod_direction_input(gpio); + if (ret) + return ret; + + ret = gpiod_to_irq(gpio); + + dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); + + return ret; +} + +static int sx9500_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret; + struct iio_dev *indio_dev; + struct sx9500_data *data; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (indio_dev == NULL) + return -ENOMEM; + + data = iio_priv(indio_dev); + data->client = client; + mutex_init(&data->mutex); + data->trigger_enabled = false; + + data->regmap = devm_regmap_init_i2c(client, &sx9500_regmap_config); + if (IS_ERR(data->regmap)) + return PTR_ERR(data->regmap); + + sx9500_init_device(indio_dev); + + indio_dev->dev.parent = &client->dev; + indio_dev->name = SX9500_DRIVER_NAME; + indio_dev->channels = sx9500_channels; + indio_dev->num_channels = ARRAY_SIZE(sx9500_channels); + indio_dev->info = &sx9500_info; + indio_dev->modes = INDIO_DIRECT_MODE; + i2c_set_clientdata(client, indio_dev); + + if (client->irq <= 0) + client->irq = sx9500_gpio_probe(client, data); + + if (client->irq > 0) { + ret = devm_request_threaded_irq(&client->dev, client->irq, + sx9500_irq_handler, sx9500_irq_thread_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + SX9500_IRQ_NAME, indio_dev); + if (ret < 0) + return ret; + + data->trig = devm_iio_trigger_alloc(&client->dev, + "%s-dev%d", indio_dev->name, indio_dev->id); + if (!data->trig) + return -ENOMEM; + + data->trig->dev.parent = &client->dev; + data->trig->ops = &sx9500_trigger_ops; + iio_trigger_set_drvdata(data->trig, indio_dev); + + ret = iio_trigger_register(data->trig); + if (ret) + return ret; + } + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + sx9500_trigger_handler, NULL); + if (ret < 0) + goto out_trigger_unregister; + + ret = iio_device_register(indio_dev); + if (ret < 0) + goto out_buffer_cleanup; + + return 0; + +out_buffer_cleanup: + iio_triggered_buffer_cleanup(indio_dev); +out_trigger_unregister: + if (client->irq > 0) + iio_trigger_unregister(data->trig); + + return ret; +} + +static int sx9500_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct sx9500_data *data = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + if (client->irq > 0) + iio_trigger_unregister(data->trig); + kfree(data->buffer); + + return 0; +} + +static const struct acpi_device_id sx9500_acpi_match[] = { + {"SSX9500", 0}, + { }, +}; +MODULE_DEVICE_TABLE(acpi, sx9500_acpi_match); + +static const struct i2c_device_id sx9500_id[] = { + {"sx9500", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, sx9500_id); + +static struct i2c_driver sx9500_driver = { + .driver = { + .name = SX9500_DRIVER_NAME, + .acpi_match_table = ACPI_PTR(sx9500_acpi_match), + }, + .probe = sx9500_probe, + .remove = sx9500_remove, + .id_table = sx9500_id, +}; +module_i2c_driver(sx9500_driver); + +MODULE_AUTHOR("Vlad Dogaru "); +MODULE_DESCRIPTION("Driver for Semtech SX9500 proximity sensor"); +MODULE_LICENSE("GPL v2"); From 1f202725b70c3d6dc736904a0d1b77a5faed6690 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Thu, 1 Jan 2015 18:13:24 +0000 Subject: [PATCH 0411/3023] iio: inkern: add out of range error message If the DT contains an invalid channel specifier then the probe of iio_hwmon fails with the following message: iio_hwmon: probe of iio_hwmon failed with error -22 So it's better to print out the relevant channel specifier in error case to locate the problem. Signed-off-by: Stefan Wahren Signed-off-by: Jonathan Cameron --- drivers/iio/inkern.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index 21655fd1465c48..2800b80ea990a6 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -116,8 +116,11 @@ static int __of_iio_simple_xlate(struct iio_dev *indio_dev, if (!iiospec->args_count) return 0; - if (iiospec->args[0] >= indio_dev->num_channels) + if (iiospec->args[0] >= indio_dev->num_channels) { + dev_err(&indio_dev->dev, "invalid channel index %u\n", + iiospec->args[0]); return -EINVAL; + } return iiospec->args[0]; } From 4e8439779ef613135049cea77f50cf58ccc44255 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 23 Dec 2014 15:22:24 +0200 Subject: [PATCH 0412/3023] iio: imu: kmx61: Save odr_bits for later use Signed-off-by: Daniel Baluta Reviewed-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/imu/kmx61.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index 9b32f012ca0fe2..52c943d50bef42 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -465,6 +465,8 @@ static int kmx61_set_odr(struct kmx61_data *data, int val, int val2, u8 device) if (ret < 0) return ret; + data->odr_bits = odr_bits; + if (device & KMX61_ACC) { ret = kmx61_set_wake_up_odr(data, val, val2); if (ret) From a3da4fa301ae60aac688ca320fb8b46a053d6d25 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 23 Dec 2014 15:22:25 +0200 Subject: [PATCH 0413/3023] iio: imu: kmx61: Don't ignore kmx61_set_power_state errors ..except while in an error handler, where there is nothing to be done anyway. Signed-off-by: Daniel Baluta Reviewed-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/imu/kmx61.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index 52c943d50bef42..6eaecb95c2d08b 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -830,7 +830,12 @@ static int kmx61_read_raw(struct iio_dev *indio_dev, } mutex_lock(&data->lock); - kmx61_set_power_state(data, true, chan->address); + ret = kmx61_set_power_state(data, true, chan->address); + if (ret) { + mutex_unlock(&data->lock); + return ret; + } + ret = kmx61_read_measurement(data, base_reg, chan->scan_index); if (ret < 0) { kmx61_set_power_state(data, false, chan->address); @@ -839,9 +844,11 @@ static int kmx61_read_raw(struct iio_dev *indio_dev, } *val = sign_extend32(ret >> chan->scan_type.shift, chan->scan_type.realbits - 1); - kmx61_set_power_state(data, false, chan->address); + ret = kmx61_set_power_state(data, false, chan->address); mutex_unlock(&data->lock); + if (ret) + return ret; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: switch (chan->type) { From 28ff344e1d0a08d60149b859d47e1610fa5b622b Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 23 Dec 2014 15:22:26 +0200 Subject: [PATCH 0414/3023] iio: imu: kmx61: Enhance error handling This fixes parts of kmx61 error handling to make code easier to read and to be more consistent with IIO coding conventions: * prefer as single point for error handling instead of duplicating code for each function * directly return a value from a case branch instead of breaking * fix error message for writing REG_CTRL1 Also, add separate error paths for kmx61_trigger_setup/iio_triggered_buffer_setup calls. Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/imu/kmx61.c | 104 +++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 61 deletions(-) diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index 6eaecb95c2d08b..137c1d52b98e79 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -656,11 +656,7 @@ static int kmx61_setup_new_data_interrupt(struct kmx61_data *data, return ret; } - ret = kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); - if (ret) - return ret; - - return 0; + return kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); } static int kmx61_chip_update_thresholds(struct kmx61_data *data) @@ -678,12 +674,10 @@ static int kmx61_chip_update_thresholds(struct kmx61_data *data) ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_WUF_THRESH, data->wake_thresh); - if (ret < 0) { + if (ret < 0) dev_err(&data->client->dev, "Error writing reg_wuf_thresh\n"); - return ret; - } - return 0; + return ret; } static int kmx61_setup_any_motion_interrupt(struct kmx61_data *data, @@ -737,11 +731,7 @@ static int kmx61_setup_any_motion_interrupt(struct kmx61_data *data, return ret; } mode |= KMX61_ACT_STBY_BIT; - ret = kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); - if (ret) - return ret; - - return 0; + return kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); } /** @@ -924,15 +914,13 @@ static int kmx61_read_event(struct iio_dev *indio_dev, switch (info) { case IIO_EV_INFO_VALUE: *val = data->wake_thresh; - break; + return IIO_VAL_INT; case IIO_EV_INFO_PERIOD: *val = data->wake_duration; - break; + return IIO_VAL_INT; default: return -EINVAL; } - - return IIO_VAL_INT; } static int kmx61_write_event(struct iio_dev *indio_dev, @@ -950,15 +938,13 @@ static int kmx61_write_event(struct iio_dev *indio_dev, switch (info) { case IIO_EV_INFO_VALUE: data->wake_thresh = val; - break; + return IIO_VAL_INT; case IIO_EV_INFO_PERIOD: data->wake_duration = val; - break; + return IIO_VAL_INT; default: return -EINVAL; } - - return IIO_VAL_INT; } static int kmx61_read_event_config(struct iio_dev *indio_dev, @@ -978,7 +964,7 @@ static int kmx61_write_event_config(struct iio_dev *indio_dev, int state) { struct kmx61_data *data = kmx61_get_data(indio_dev); - int ret; + int ret = 0; if (state && data->ev_enable_state) return 0; @@ -987,27 +973,25 @@ static int kmx61_write_event_config(struct iio_dev *indio_dev, if (!state && data->motion_trig_on) { data->ev_enable_state = 0; - mutex_unlock(&data->lock); - return 0; + goto err_unlock; } ret = kmx61_set_power_state(data, state, KMX61_ACC); - if (ret < 0) { - mutex_unlock(&data->lock); - return ret; - } + if (ret < 0) + goto err_unlock; ret = kmx61_setup_any_motion_interrupt(data, state, KMX61_ACC); if (ret < 0) { kmx61_set_power_state(data, false, KMX61_ACC); - mutex_unlock(&data->lock); - return ret; + goto err_unlock; } data->ev_enable_state = state; + +err_unlock: mutex_unlock(&data->lock); - return 0; + return ret; } static int kmx61_acc_validate_trigger(struct iio_dev *indio_dev, @@ -1066,8 +1050,7 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, if (!state && data->ev_enable_state && data->motion_trig_on) { data->motion_trig_on = false; - mutex_unlock(&data->lock); - return 0; + goto err_unlock; } @@ -1077,10 +1060,8 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, device = KMX61_MAG; ret = kmx61_set_power_state(data, state, device); - if (ret < 0) { - mutex_unlock(&data->lock); - return ret; - } + if (ret < 0) + goto err_unlock; if (data->acc_dready_trig == trig || data->mag_dready_trig == trig) ret = kmx61_setup_new_data_interrupt(data, state, device); @@ -1088,8 +1069,7 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, ret = kmx61_setup_any_motion_interrupt(data, state, KMX61_ACC); if (ret < 0) { kmx61_set_power_state(data, false, device); - mutex_unlock(&data->lock); - return ret; + goto err_unlock; } if (data->acc_dready_trig == trig) @@ -1098,10 +1078,10 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, data->mag_dready_trig_on = state; else data->motion_trig_on = state; - +err_unlock: mutex_unlock(&data->lock); - return 0; + return ret; } static int kmx61_trig_try_reenable(struct iio_trigger *trig) @@ -1207,7 +1187,7 @@ static irqreturn_t kmx61_event_handler(int irq, void *private) ret |= KMX61_REG_CTRL1_BIT_RES; ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret); if (ret < 0) - dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); + dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INL); if (ret < 0) @@ -1409,15 +1389,17 @@ static int kmx61_probe(struct i2c_client *client, data->acc_dready_trig = kmx61_trigger_setup(data, data->acc_indio_dev, "dready"); - if (IS_ERR(data->acc_dready_trig)) - return PTR_ERR(data->acc_dready_trig); + if (IS_ERR(data->acc_dready_trig)) { + ret = PTR_ERR(data->acc_dready_trig); + goto err_chip_uninit; + } data->mag_dready_trig = kmx61_trigger_setup(data, data->mag_indio_dev, "dready"); if (IS_ERR(data->mag_dready_trig)) { ret = PTR_ERR(data->mag_dready_trig); - goto err_trigger_unregister; + goto err_trigger_unregister_acc_dready; } data->motion_trig = @@ -1425,7 +1407,7 @@ static int kmx61_probe(struct i2c_client *client, "any-motion"); if (IS_ERR(data->motion_trig)) { ret = PTR_ERR(data->motion_trig); - goto err_trigger_unregister; + goto err_trigger_unregister_mag_dready; } ret = iio_triggered_buffer_setup(data->acc_indio_dev, @@ -1435,7 +1417,7 @@ static int kmx61_probe(struct i2c_client *client, if (ret < 0) { dev_err(&data->client->dev, "Failed to setup acc triggered buffer\n"); - goto err_trigger_unregister; + goto err_trigger_unregister_motion; } ret = iio_triggered_buffer_setup(data->mag_indio_dev, @@ -1445,14 +1427,14 @@ static int kmx61_probe(struct i2c_client *client, if (ret < 0) { dev_err(&data->client->dev, "Failed to setup mag triggered buffer\n"); - goto err_trigger_unregister; + goto err_buffer_cleanup_acc; } } ret = iio_device_register(data->acc_indio_dev); if (ret < 0) { dev_err(&client->dev, "Failed to register acc iio device\n"); - goto err_buffer_cleanup; + goto err_buffer_cleanup_mag; } ret = iio_device_register(data->mag_indio_dev); @@ -1475,18 +1457,18 @@ static int kmx61_probe(struct i2c_client *client, iio_device_unregister(data->mag_indio_dev); err_iio_unregister_acc: iio_device_unregister(data->acc_indio_dev); -err_buffer_cleanup: - if (client->irq >= 0) { - iio_triggered_buffer_cleanup(data->acc_indio_dev); +err_buffer_cleanup_mag: + if (client->irq >= 0) iio_triggered_buffer_cleanup(data->mag_indio_dev); - } -err_trigger_unregister: - if (data->acc_dready_trig) - iio_trigger_unregister(data->acc_dready_trig); - if (data->mag_dready_trig) - iio_trigger_unregister(data->mag_dready_trig); - if (data->motion_trig) - iio_trigger_unregister(data->motion_trig); +err_buffer_cleanup_acc: + if (client->irq >= 0) + iio_triggered_buffer_cleanup(data->acc_indio_dev); +err_trigger_unregister_motion: + iio_trigger_unregister(data->motion_trig); +err_trigger_unregister_mag_dready: + iio_trigger_unregister(data->mag_dready_trig); +err_trigger_unregister_acc_dready: + iio_trigger_unregister(data->acc_dready_trig); err_chip_uninit: kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); return ret; From dfb12edea5577243d4ea64d93a32f575e8b1cc4c Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 23 Dec 2014 15:22:27 +0200 Subject: [PATCH 0415/3023] iio: imu: kmx61: Fixup parameters alignment Signed-off-by: Daniel Baluta Acked-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/imu/kmx61.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index 137c1d52b98e79..bf3468b982a01e 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -924,11 +924,11 @@ static int kmx61_read_event(struct iio_dev *indio_dev, } static int kmx61_write_event(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, - enum iio_event_info info, - int val, int val2) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) { struct kmx61_data *data = kmx61_get_data(indio_dev); @@ -958,10 +958,10 @@ static int kmx61_read_event_config(struct iio_dev *indio_dev, } static int kmx61_write_event_config(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, - int state) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + int state) { struct kmx61_data *data = kmx61_get_data(indio_dev); int ret = 0; From 0475c68544ddcb72905e35cb8c050c523020e2c7 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 23 Dec 2014 15:22:28 +0200 Subject: [PATCH 0416/3023] iio: imu: kmx61: Drop unused device parameter Signed-off-by: Daniel Baluta Reviewed-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/imu/kmx61.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index bf3468b982a01e..777b7f68591cab 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -681,7 +681,7 @@ static int kmx61_chip_update_thresholds(struct kmx61_data *data) } static int kmx61_setup_any_motion_interrupt(struct kmx61_data *data, - bool status, u8 device) + bool status) { u8 mode; int ret; @@ -980,7 +980,7 @@ static int kmx61_write_event_config(struct iio_dev *indio_dev, if (ret < 0) goto err_unlock; - ret = kmx61_setup_any_motion_interrupt(data, state, KMX61_ACC); + ret = kmx61_setup_any_motion_interrupt(data, state); if (ret < 0) { kmx61_set_power_state(data, false, KMX61_ACC); goto err_unlock; @@ -1066,7 +1066,7 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, if (data->acc_dready_trig == trig || data->mag_dready_trig == trig) ret = kmx61_setup_new_data_interrupt(data, state, device); else - ret = kmx61_setup_any_motion_interrupt(data, state, KMX61_ACC); + ret = kmx61_setup_any_motion_interrupt(data, state); if (ret < 0) { kmx61_set_power_state(data, false, device); goto err_unlock; From d4a4ae04d236a01a8648648a0e11777250ab2974 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 23 Dec 2014 15:22:29 +0200 Subject: [PATCH 0417/3023] iio: imu: kmx61: Use false instead of 0 for ev_enable_state Signed-off-by: Daniel Baluta Acked-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/imu/kmx61.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index 777b7f68591cab..a70a3ef9179358 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -972,7 +972,7 @@ static int kmx61_write_event_config(struct iio_dev *indio_dev, mutex_lock(&data->lock); if (!state && data->motion_trig_on) { - data->ev_enable_state = 0; + data->ev_enable_state = false; goto err_unlock; } From dbdd0e2dd9981eafe33687d0b2d089c5285ea22b Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 23 Dec 2014 15:22:30 +0200 Subject: [PATCH 0418/3023] iio: imu: kmx61: Fix device initialization when setting trigger state Signed-off-by: Daniel Baluta Acked-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/imu/kmx61.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index a70a3ef9179358..578e3dd944c9d3 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -1053,8 +1053,7 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, goto err_unlock; } - - if (data->acc_dready_trig == trig || data->motion_trig) + if (data->acc_dready_trig == trig || data->motion_trig == trig) device = KMX61_ACC; else device = KMX61_MAG; From ea04d2965874ca5753e756b335449c5322a85733 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 23 Dec 2014 15:22:31 +0200 Subject: [PATCH 0419/3023] iio: imu: kmx61: Remove unnecessary REG_INS1 read Useful in the debugging phase, not needed now. Signed-off-by: Daniel Baluta Acked-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/imu/kmx61.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index 578e3dd944c9d3..1f7c3f1f4dfddb 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -1192,8 +1192,6 @@ static irqreturn_t kmx61_event_handler(int irq, void *private) if (ret < 0) dev_err(&data->client->dev, "Error reading reg_inl\n"); - ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INS1); - return IRQ_HANDLED; } From 6a191c7025f80c328156a358871f5d947f443aa9 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 23 Dec 2014 15:22:33 +0200 Subject: [PATCH 0420/3023] iio: imu: kmx61: Use correct base when reading data We have two IIO devices and we need to adjust the base when reading data. Signed-off-by: Daniel Baluta Reviewed-by: Hartmut Knaack Signed-off-by: Jonathan Cameron --- drivers/iio/imu/kmx61.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index 1f7c3f1f4dfddb..b60b22d25615d9 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -1218,12 +1218,18 @@ static irqreturn_t kmx61_trigger_handler(int irq, void *p) struct iio_dev *indio_dev = pf->indio_dev; struct kmx61_data *data = kmx61_get_data(indio_dev); int bit, ret, i = 0; + u8 base; s16 buffer[8]; + if (indio_dev == data->acc_indio_dev) + base = KMX61_ACC_XOUT_L; + else + base = KMX61_MAG_XOUT_L; + mutex_lock(&data->lock); for_each_set_bit(bit, indio_dev->buffer->scan_mask, indio_dev->masklength) { - ret = kmx61_read_measurement(data, KMX61_ACC_XOUT_L, bit); + ret = kmx61_read_measurement(data, base, bit); if (ret < 0) { mutex_unlock(&data->lock); goto err; From a5b940fa4ac0c4d8d9e07bda17a68a042e4d1d94 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Mon, 29 Dec 2014 10:27:20 +0000 Subject: [PATCH 0421/3023] DT: mxs-lradc: fix ranges of ts properties This patch fixes off-by-one issues in the devicetree binding of mxs-lradc. According to the i.MX23 and i.MX28 reference manuals [1][2] the range of NUM_SAMPLES is 0..31, but property ave-ctrl is substracted by 1 before used. Considering all limitations the range of DELAY is 1..2047, but also property ave-delay is substracted by 1 before used. The patch has been suggested by Hartmut Knaack and Kristina Martsenko. [1] - http://cache.freescale.com/files/dsp/doc/ref_manual/IMX23RM.pdf [2] - http://cache.freescale.com/files/dsp/doc/ref_manual/MCIMX28RM.pdf Signed-off-by: Stefan Wahren Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/staging/iio/adc/mxs-lradc.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt index ee05dc3906941a..3075377875745b 100644 --- a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt +++ b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt @@ -12,9 +12,9 @@ Optional properties: property is not present, then the touchscreen is disabled. 5 wires is valid for i.MX28 SoC only. - fsl,ave-ctrl: number of samples per direction to calculate an average value. - Allowed value is 1 ... 31, default is 4 + Allowed value is 1 ... 32, default is 4 - fsl,ave-delay: delay between consecutive samples. Allowed value is - 1 ... 2047. It is used if 'fsl,ave-ctrl' > 1, counts at + 2 ... 2048. It is used if 'fsl,ave-ctrl' > 1, counts at 2 kHz and its default is 2 (= 1 ms) - fsl,settling: delay between plate switch to next sample. Allowed value is 1 ... 2047. It counts at 2 kHz and its default is From c22d2672c826a67a84fa60c17797315f4c94cedb Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Mon, 29 Dec 2014 10:27:21 +0000 Subject: [PATCH 0422/3023] iio: mxs-lradc: check ranges of ts properties The devicetree binding for mxs-lradc defines ranges for the touchscreen properties. In order to avoid unexpected behavior like division by zero, we better check these ranges during probe and abort in error case. Additionally this patch adds an important note from the reference manual about the range of sample delay. Signed-off-by: Stefan Wahren Reviewed-by: Marek Vasut Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/mxs-lradc.c | 45 ++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index 6757f107faf3ea..e0e91836eec19b 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -436,7 +436,14 @@ static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch) */ mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch)); - /* prepare the delay/loop unit according to the oversampling count */ + /* + * prepare the delay/loop unit according to the oversampling count + * + * from the datasheet: + * "The DELAY fields in HW_LRADC_DELAY0, HW_LRADC_DELAY1, + * HW_LRADC_DELAY2, and HW_LRADC_DELAY3 must be non-zero; otherwise, + * the LRADC will not trigger the delay group." + */ mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << ch) | LRADC_DELAY_TRIGGER_DELAYS(0) | LRADC_DELAY_LOOP(lradc->over_sample_cnt - 1) | @@ -1495,20 +1502,38 @@ static int mxs_lradc_probe_touchscreen(struct mxs_lradc *lradc, return -EINVAL; } - lradc->over_sample_cnt = 4; - ret = of_property_read_u32(lradc_node, "fsl,ave-ctrl", &adapt); - if (ret == 0) + if (of_property_read_u32(lradc_node, "fsl,ave-ctrl", &adapt)) { + lradc->over_sample_cnt = 4; + } else { + if (adapt < 1 || adapt > 32) { + dev_err(lradc->dev, "Invalid sample count (%u)\n", + adapt); + return -EINVAL; + } lradc->over_sample_cnt = adapt; + } - lradc->over_sample_delay = 2; - ret = of_property_read_u32(lradc_node, "fsl,ave-delay", &adapt); - if (ret == 0) + if (of_property_read_u32(lradc_node, "fsl,ave-delay", &adapt)) { + lradc->over_sample_delay = 2; + } else { + if (adapt < 2 || adapt > LRADC_DELAY_DELAY_MASK + 1) { + dev_err(lradc->dev, "Invalid sample delay (%u)\n", + adapt); + return -EINVAL; + } lradc->over_sample_delay = adapt; + } - lradc->settling_delay = 10; - ret = of_property_read_u32(lradc_node, "fsl,settling", &adapt); - if (ret == 0) + if (of_property_read_u32(lradc_node, "fsl,settling", &adapt)) { + lradc->settling_delay = 10; + } else { + if (adapt < 1 || adapt > LRADC_DELAY_DELAY_MASK) { + dev_err(lradc->dev, "Invalid settling delay (%u)\n", + adapt); + return -EINVAL; + } lradc->settling_delay = adapt; + } return 0; } From 8f5d8727a7736024f28101b922d23754c67c2cc8 Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Mon, 29 Dec 2014 11:37:48 +0200 Subject: [PATCH 0423/3023] iio: ensure scan index is unique at device register Having two or more channels with the same positive scan_index field makes no sense if the device supports buffering. Prevent this situation by failing to register such a device. Signed-off-by: Vlad Dogaru Reviewed-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-core.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index b7a39771705fc9..69feb912515a44 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -1134,6 +1134,29 @@ static const struct file_operations iio_buffer_fileops = { .compat_ioctl = iio_ioctl, }; +static int iio_check_unique_scan_index(struct iio_dev *indio_dev) +{ + int i, j; + const struct iio_chan_spec *channels = indio_dev->channels; + + if (!(indio_dev->modes & INDIO_ALL_BUFFER_MODES)) + return 0; + + for (i = 0; i < indio_dev->num_channels - 1; i++) { + if (channels[i].scan_index < 0) + continue; + for (j = i + 1; j < indio_dev->num_channels; j++) + if (channels[i].scan_index == channels[j].scan_index) { + dev_err(&indio_dev->dev, + "Duplicate scan index %d\n", + channels[i].scan_index); + return -EINVAL; + } + } + + return 0; +} + static const struct iio_buffer_setup_ops noop_ring_setup_ops; /** @@ -1148,6 +1171,10 @@ int iio_device_register(struct iio_dev *indio_dev) if (!indio_dev->dev.of_node && indio_dev->dev.parent) indio_dev->dev.of_node = indio_dev->dev.parent->of_node; + ret = iio_check_unique_scan_index(indio_dev); + if (ret < 0) + return ret; + /* configure elements for the chrdev */ indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id); From 66ad1fd025c7cb9d0d4d01de965c80871226f422 Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Sun, 21 Dec 2014 02:42:26 +0200 Subject: [PATCH 0424/3023] iio: buffer: fix custom buffer attributes copy Signed-off-by: Octavian Purdila Reviewed-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 2bd8d399f2ecce..403b72878b0b55 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -789,7 +789,7 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) buffer->buffer_group.attrs[1] = &dev_attr_enable.attr; if (buffer->attrs) memcpy(&buffer->buffer_group.attrs[2], buffer->attrs, - sizeof(*&buffer->buffer_group.attrs) * (attrcount - 2)); + sizeof(*&buffer->buffer_group.attrs) * attrcount); buffer->buffer_group.attrs[attrcount+2] = NULL; indio_dev->groups[indio_dev->groupcounter++] = &buffer->buffer_group; From 9251d14a275878879400eefae7601c3ee7ee9d71 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 25 Sep 2014 16:27:14 +0200 Subject: [PATCH 0425/3023] staging:iio:ad5933: Report temperature as raw value We shouldn't be doing the unit conversion in kernel space. Just report the raw value for the property and the scale. Userspace can do the conversion if necessary. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- .../staging/iio/impedance-analyzer/ad5933.c | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 39f60aca083845..d18a8ecc124514 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -113,7 +113,8 @@ static const struct iio_chan_spec ad5933_channels[] = { .type = IIO_TEMP, .indexed = 1, .channel = 0, - .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), .address = AD5933_REG_TEMP_DATA, .scan_index = -1, .scan_type = { @@ -520,12 +521,11 @@ static int ad5933_read_raw(struct iio_dev *indio_dev, { struct ad5933_state *st = iio_priv(indio_dev); __be16 dat; - int ret = -EINVAL; + int ret; - mutex_lock(&indio_dev->mlock); switch (m) { case IIO_CHAN_INFO_RAW: - case IIO_CHAN_INFO_PROCESSED: + mutex_lock(&indio_dev->mlock); if (iio_buffer_enabled(indio_dev)) { ret = -EBUSY; goto out; @@ -543,16 +543,16 @@ static int ad5933_read_raw(struct iio_dev *indio_dev, if (ret < 0) goto out; mutex_unlock(&indio_dev->mlock); - ret = be16_to_cpu(dat); - /* Temp in Milli degrees Celsius */ - if (ret < 8192) - *val = ret * 1000 / 32; - else - *val = (ret - 16384) * 1000 / 32; + *val = sign_extend32(be16_to_cpu(dat), 13); return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 1000; + *val2 = 5; + return IIO_VAL_FRACTIONAL_LOG2; } + return -EINVAL; out: mutex_unlock(&indio_dev->mlock); return ret; From 0a01db9d64350754f5d714d44dab81cb97a67a81 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 25 Sep 2014 16:27:15 +0200 Subject: [PATCH 0426/3023] staging:iio:ad5933: Remove platform data from state struct The platform data is only used in the probe function. No need to keep it around. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/impedance-analyzer/ad5933.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index d18a8ecc124514..e90653ff915958 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -89,7 +89,6 @@ struct ad5933_state { struct i2c_client *client; struct regulator *reg; - struct ad5933_platform_data *pdata; struct delayed_work work; unsigned long mclk_hz; unsigned char ctrl_hb; @@ -712,9 +711,7 @@ static int ad5933_probe(struct i2c_client *client, st->client = client; if (!pdata) - st->pdata = &ad5933_default_pdata; - else - st->pdata = pdata; + pdata = &ad5933_default_pdata; st->reg = devm_regulator_get(&client->dev, "vcc"); if (!IS_ERR(st->reg)) { @@ -727,10 +724,10 @@ static int ad5933_probe(struct i2c_client *client, if (voltage_uv) st->vref_mv = voltage_uv / 1000; else - st->vref_mv = st->pdata->vref_mv; + st->vref_mv = pdata->vref_mv; - if (st->pdata->ext_clk_Hz) { - st->mclk_hz = st->pdata->ext_clk_Hz; + if (pdata->ext_clk_Hz) { + st->mclk_hz = pdata->ext_clk_Hz; st->ctrl_lb = AD5933_CTRL_EXT_SYSCLK; } else { st->mclk_hz = AD5933_INT_OSC_FREQ_Hz; From 944115934436b1ff6cf773a9e9123858ea9ef3da Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Wed, 31 Dec 2014 16:23:00 -0800 Subject: [PATCH 0427/3023] drm/i915: Make sample_c messages go faster on Haswell. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Haswell significantly improved the performance of sampler_c messages, but the optimization appears to be off by default. Later platforms remove this bit, and apparently always enable the optimization. Improves performance in "Counter Strike: Global Offensive" by 18% at default settings on Iris Pro. This may break sampling of paletted formats (P8/A8P8/P8A8). It's unclear whether it affects sampling of paletted formats in general, or just the sample_c message (which is never used). While libva does have support for using paletted formats (primarily for OSDs), that support appears to have been broken for at least a year, so I couldn't observe a regression from this: I tried to get libva-intel to use paletted formats, and observe a regression...but the only thing I found that used it was mplayer's OSD (on screen display). Even without my patch, the colors were totally wrong with that, and it's according to a few distro wikis, that's been the case for over a year. If libva's code for paletted formats /is/ broken, they could always add code to disable this bit using the command validator when fixing it. Further investigation from Haihao shows that libva mplayer OSD seems to work at least on his setup (still unclear what's wron with Ken's), and that it's not affected by this patch. Quoting the discussion between Haihao and Ken: > > > If you use "-vo gl" or "-vo xv", the OSD is solid white text with a black > > > border around it. I presume that it's supposed to be white with vaapi as > > > well, but I guess I'm not entirely sure. > > > > > > It's possible that the optimization doesn't affect the palette as long as > > > you never use sample_c with the paletted textures. > > > > I verified the palette takes effect in the following way: > > > > 1. Only support P8A8 format in the driver > > > > 2. ran the above command and I saw white OSD text > > > > 3. Only support P4A4 format in the driver and don't use > > 3DSTATE_SAMPLER_PALETTE_LOAD0 to load the value to the texture palette, > > so the palette keeps unchanged. > > > > 4. ran the above command and I saw black OSD text. > > > > 5. Load the right value to the texture palette and ran the above command > > again, I saw white OSD text. > > > > Hence I think sample_c with the paletted textures is used in the driver. > > That sounds like the palette is actually working, then. Great :) > > I doubt that libva would use sample_c - sampling with a shadow comparison? > It looks like it just uses sample and sample+killpix. You are right, libva driver doesn't use sample_c message. > I'm pretty sure the sample_c optimization just uses the palette memory as > storage for some stuff, so it's quite possible it just works if you're > only using sample and sample+killpix. Thanks for the explanation, it makes sense to me. Signed-off-by: Kenneth Graunke [danvet: Add wa name from Ville's review to the comment and copypaste the explanation why we don't care about libva (already broken) from Ken. Also add conclusion from libva devs that&why this is all fine.] Reviewed-by: Ville Syrjälä Cc: "Xiang, Haihao" Cc: libva@lists.freedesktop.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 1fdda4249bb18d..0cb0067af4bb54 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6152,6 +6152,7 @@ enum punit_power_well { #define HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE (1 << 6) #define HALF_SLICE_CHICKEN3 0xe184 +#define HSW_SAMPLE_C_PERFORMANCE (1<<9) #define GEN8_CENTROID_PIXEL_OPT_DIS (1<<8) #define GEN8_SAMPLER_POWER_BYPASS_DIS (1<<1) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 4254e91456e1bb..091860432f01e0 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5972,6 +5972,10 @@ static void haswell_init_clock_gating(struct drm_device *dev) I915_WRITE(GEN7_GT_MODE, GEN6_WIZ_HASHING_MASK | GEN6_WIZ_HASHING_16x4); + /* WaSampleCChickenBitEnable:hsw */ + I915_WRITE(HALF_SLICE_CHICKEN3, + _MASKED_BIT_ENABLE(HSW_SAMPLE_C_PERFORMANCE)); + /* WaSwitchSolVfFArbitrationPriority:hsw */ I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL); From 7838a63a53f69c4cdfd450b60f0d58ed6641076e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 5 Jan 2015 14:36:59 +0100 Subject: [PATCH 0428/3023] drm/i915: Include i915_gem_evict.c kerneldoc into the drm docbook I've written these long before we've had a reasonable docbook structure, and naturally they've gone stale. Fix this up asap. Signed-off-by: Daniel Vetter --- Documentation/DocBook/drm.tmpl | 11 +++++++++++ drivers/gpu/drm/i915/i915_gem_evict.c | 8 ++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index bd1456ad846014..38f7ef3933c4c4 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -4048,6 +4048,17 @@ int num_ioctls; !Pdrivers/gpu/drm/i915/i915_gem_gtt.c Global GTT views !Idrivers/gpu/drm/i915/i915_gem_gtt.c + + Buffer Object Eviction + + This section documents the interface function for evicting buffer + objects to make space available in the virtual gpu address spaces. + Note that this is mostly orthogonal to shrinking buffer objects + caches, which has the goal to make main memory (shared with the gpu + through the unified memory architecture) available. + +!Idrivers/gpu/drm/i915/i915_gem_evict.c + diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index 886ff2ee7a282e..d104c9120c4d84 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -50,11 +50,12 @@ mark_free(struct i915_vma *vma, struct list_head *unwind) * i915_gem_evict_something - Evict vmas to make room for binding a new one * @dev: drm_device * @vm: address space to evict from - * @size: size of the desired free space + * @min_size: size of the desired free space * @alignment: alignment constraint of the desired free space * @cache_level: cache_level for the desired space - * @mappable: whether the free space must be mappable - * @nonblocking: whether evicting active objects is allowed or not + * @start: start (inclusive) of the range from which to evict objects + * @end: end (exclusive) of the range from which to evict objects + * @flags: additional flags to control the eviction algorithm * * This function will try to evict vmas until a free space satisfying the * requirements is found. Callers must check first whether any such hole exists @@ -196,7 +197,6 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm, /** * i915_gem_evict_vm - Evict all idle vmas from a vm - * * @vm: Address space to cleanse * @do_idle: Boolean directing whether to idle first. * From b9b5dce5e767a07604b5debb169472f15b4b57a7 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 23 Dec 2014 17:16:04 +0000 Subject: [PATCH 0429/3023] drm/i915: Add some extra guards in evict_vm v2: Use WARN_ONs (Daniel) Cc: Daniel Vetter Signed-off-by: Ben Widawsky Signed-off-by: Michel Thierry Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_evict.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index d104c9120c4d84..e3a49d94da3a79 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -214,6 +214,7 @@ int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle) struct i915_vma *vma, *next; int ret; + WARN_ON(!mutex_is_locked(&vm->dev->struct_mutex)); trace_i915_gem_evict_vm(vm); if (do_idle) { @@ -222,6 +223,8 @@ int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle) return ret; i915_gem_retire_requests(vm->dev); + + WARN_ON(!list_empty(&vm->active_list)); } list_for_each_entry_safe(vma, next, &vm->inactive_list, mm_list) From 43566dedde54f9729113f5f9fde77d53e75e61e9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 2 Jan 2015 16:29:29 +0530 Subject: [PATCH 0430/3023] drm/i915: Broaden application of set-domain(GTT) Previously, this was restricted to only operate on bound objects - to make pointer access through the GTT to the object coherent with writes to and from the GPU. A second usecase is drm_intel_bo_wait_rendering() which at present does not function unless the object also happens to be bound into the GGTT (on current systems that is becoming increasingly rare, especially for the typical requests from mesa). A third usecase is a future patch wishing to extend the coverage of the GTT domain to include objects not bound into the GGTT but still in its coherent cache domain. For the latter pair of requests, we need to operate on the object regardless of its bind state. v2: After discussion with Akash, we came to the conclusion that the get-pages was required in order for accurate domain tracking in the corner cases (like the shrinker) and also useful for ensuring memory coherency with earlier cached CPU mmaps in case userspace uses exotic cache bypass (non-temporal) instructions. v3: Fix the inactive object check. v4: Rebase to latest drm-intel-nightly codebase Signed-off-by: Chris Wilson Reviewed-by: Akash Goel Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 43 +++++++++++++++------------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index f678017c4d3127..a2c64a6f665c68 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -153,12 +153,6 @@ int i915_mutex_lock_interruptible(struct drm_device *dev) return 0; } -static inline bool -i915_gem_object_is_inactive(struct drm_i915_gem_object *obj) -{ - return i915_gem_obj_bound_any(obj) && !obj->active; -} - int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, struct drm_file *file) @@ -1472,18 +1466,10 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, if (ret) goto unref; - if (read_domains & I915_GEM_DOMAIN_GTT) { + if (read_domains & I915_GEM_DOMAIN_GTT) ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0); - - /* Silently promote "you're not bound, there was nothing to do" - * to success, since the client was just asking us to - * make sure everything was done. - */ - if (ret == -EINVAL) - ret = 0; - } else { + else ret = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0); - } unref: drm_gem_object_unreference(&obj->base); @@ -3699,15 +3685,10 @@ i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj, int i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) { - struct drm_i915_private *dev_priv = obj->base.dev->dev_private; - struct i915_vma *vma = i915_gem_obj_to_ggtt(obj); uint32_t old_write_domain, old_read_domains; + struct i915_vma *vma; int ret; - /* Not valid to be called on unbound objects. */ - if (vma == NULL) - return -EINVAL; - if (obj->base.write_domain == I915_GEM_DOMAIN_GTT) return 0; @@ -3716,6 +3697,19 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) return ret; i915_gem_object_retire(obj); + + /* Flush and acquire obj->pages so that we are coherent through + * direct access in memory with previous cached writes through + * shmemfs and that our cache domain tracking remains valid. + * For example, if the obj->filp was moved to swap without us + * being notified and releasing the pages, we would mistakenly + * continue to assume that the obj remained out of the CPU cached + * domain. + */ + ret = i915_gem_object_get_pages(obj); + if (ret) + return ret; + i915_gem_object_flush_cpu_write_domain(obj, false); /* Serialise direct access to this object with the barriers for @@ -3747,9 +3741,10 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) old_write_domain); /* And bump the LRU for this access */ - if (i915_gem_object_is_inactive(obj)) + vma = i915_gem_obj_to_ggtt(obj); + if (vma && drm_mm_node_allocated(&vma->node) && !obj->active) list_move_tail(&vma->mm_list, - &dev_priv->gtt.base.inactive_list); + &to_i915(obj->base.dev)->gtt.base.inactive_list); return 0; } From 1816f92363036600f2387bb8273b1e5e1f5b304e Mon Sep 17 00:00:00 2001 From: Akash Goel Date: Fri, 2 Jan 2015 16:29:30 +0530 Subject: [PATCH 0431/3023] drm/i915: Support creation of unbound wc user mappings for objects This patch provides support to create write-combining virtual mappings of GEM object. It intends to provide the same funtionality of 'mmap_gtt' interface without the constraints and contention of a limited aperture space, but requires clients handles the linear to tile conversion on their own. This is for improving the CPU write operation performance, as with such mapping, writes and reads are almost 50% faster than with mmap_gtt. Similar to the GTT mmapping, unlike the regular CPU mmapping, it avoids the cache flush after update from CPU side, when object is passed onto GPU. This type of mapping is specially useful in case of sub-region update, i.e. when only a portion of the object is to be updated. Using a CPU mmap in such cases would normally incur a clflush of the whole object, and using a GTT mmapping would likely require eviction of an active object or fence and thus stall. The write-combining CPU mmap avoids both. To ensure the cache coherency, before using this mapping, the GTT domain has been reused here. This provides the required cache flush if the object is in CPU domain or synchronization against the concurrent rendering. Although the access through an uncached mmap should automatically invalidate the cache lines, this may not be true for non-temporal write instructions and also not all pages of the object may be updated at any given point of time through this mapping. Having a call to get_pages in set_to_gtt_domain function, as added in the earlier patch 'drm/i915: Broaden application of set-domain(GTT)', would guarantee the clflush and so there will be no cachelines holding the data for the object before it is accessed through this map. The drm_i915_gem_mmap structure (for the DRM_I915_GEM_MMAP_IOCTL) has been extended with a new flags field (defaulting to 0 for existent users). In order for userspace to detect the extended ioctl, a new parameter I915_PARAM_MMAP_VERSION has been added for versioning the ioctl interface. v2: Fix error handling, invalid flag detection, renaming (ickle) v3: Rebase to latest drm-intel-nightly codebase The new mmapping is exercised by igt/gem_mmap_wc, igt/gem_concurrent_blit and igt/gem_gtt_speed. Change-Id: Ie883942f9e689525f72fe9a8d3780c3a9faa769a Signed-off-by: Akash Goel Signed-off-by: Chris Wilson Cc: Daniel Vetter Reviewed-by: Tvrtko Ursulin Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 3 +++ drivers/gpu/drm/i915/i915_gem.c | 19 +++++++++++++++++++ include/uapi/drm/i915_drm.h | 9 +++++++++ 3 files changed, 31 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 52730ed863855f..7fad6b8ac63a6e 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -143,6 +143,9 @@ static int i915_getparam(struct drm_device *dev, void *data, case I915_PARAM_HAS_COHERENT_PHYS_GTT: value = 1; break; + case I915_PARAM_MMAP_VERSION: + value = 1; + break; default: DRM_DEBUG("Unknown parameter %d\n", param->param); return -EINVAL; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a2c64a6f665c68..9cd457ae442752 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1534,6 +1534,12 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, struct drm_gem_object *obj; unsigned long addr; + if (args->flags & ~(I915_MMAP_WC)) + return -EINVAL; + + if (args->flags & I915_MMAP_WC && !cpu_has_pat) + return -ENODEV; + obj = drm_gem_object_lookup(dev, file, args->handle); if (obj == NULL) return -ENOENT; @@ -1549,6 +1555,19 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, addr = vm_mmap(obj->filp, 0, args->size, PROT_READ | PROT_WRITE, MAP_SHARED, args->offset); + if (args->flags & I915_MMAP_WC) { + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + + down_write(&mm->mmap_sem); + vma = find_vma(mm, addr); + if (vma) + vma->vm_page_prot = + pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); + else + addr = -ENOMEM; + up_write(&mm->mmap_sem); + } drm_gem_object_unreference_unlocked(obj); if (IS_ERR((void *)addr)) return addr; diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 250262265ee31c..c155a03479499d 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -341,6 +341,7 @@ typedef struct drm_i915_irq_wait { #define I915_PARAM_HAS_WT 27 #define I915_PARAM_CMD_PARSER_VERSION 28 #define I915_PARAM_HAS_COHERENT_PHYS_GTT 29 +#define I915_PARAM_MMAP_VERSION 30 typedef struct drm_i915_getparam { int param; @@ -488,6 +489,14 @@ struct drm_i915_gem_mmap { * This is a fixed-size type for 32/64 compatibility. */ __u64 addr_ptr; + + /** + * Flags for extended behaviour. + * + * Added in version 2. + */ + __u64 flags; +#define I915_MMAP_WC 0x1 }; struct drm_i915_gem_mmap_gtt { From 8325aa30f8ada22731276b19a72310150f30b3ec Mon Sep 17 00:00:00 2001 From: Dylan Reid Date: Thu, 2 Oct 2014 09:43:32 -0700 Subject: [PATCH 0432/3023] ARM: tegra: Enable the mic-detect gpio on Acer Chromebook 13 Enables the gpio-base mic detection on the Acer Chromebook 13. This gpio is set by the jack-detection chip when it notices either of the TRRS type headsets with a microphone. Signed-off-by: Dylan Reid Acked-by: Stephen Warren Signed-off-by: Thierry Reding --- arch/arm/boot/dts/tegra124-nyan-big.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/tegra124-nyan-big.dts b/arch/arm/boot/dts/tegra124-nyan-big.dts index 53181d31024713..004e8e4e1c04f0 100644 --- a/arch/arm/boot/dts/tegra124-nyan-big.dts +++ b/arch/arm/boot/dts/tegra124-nyan-big.dts @@ -1131,6 +1131,8 @@ clock-names = "pll_a", "pll_a_out0", "mclk"; nvidia,hp-det-gpios = <&gpio TEGRA_GPIO(I, 7) GPIO_ACTIVE_HIGH>; + nvidia,mic-det-gpios = + <&gpio TEGRA_GPIO(R, 7) GPIO_ACTIVE_HIGH>; }; }; From cbd54fe0b2bc39cf64ee2f50a22249ae1ddd37c9 Mon Sep 17 00:00:00 2001 From: Robert Nelson Date: Mon, 22 Dec 2014 11:29:21 -0600 Subject: [PATCH 0433/3023] ARM: dts: imx6dl-udoo: Add board support based off imx6q-udoo For more information about the Udoo boards: http://www.udoo.org/ Signed-off-by: Robert Nelson Reviewed-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/imx6dl-udoo.dts | 18 ++++ arch/arm/boot/dts/imx6q-udoo.dts | 124 +------------------------ arch/arm/boot/dts/imx6qdl-udoo.dtsi | 134 ++++++++++++++++++++++++++++ 4 files changed, 154 insertions(+), 123 deletions(-) create mode 100644 arch/arm/boot/dts/imx6dl-udoo.dts create mode 100644 arch/arm/boot/dts/imx6qdl-udoo.dtsi diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index c0d5c6619c9181..1236b8c0eb60dd 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -234,6 +234,7 @@ dtb-$(CONFIG_ARCH_MXC) += \ imx6dl-tx6dl-comtft.dtb \ imx6dl-tx6u-801x.dtb \ imx6dl-tx6u-811x.dtb \ + imx6dl-udoo.dtb \ imx6dl-wandboard.dtb \ imx6dl-wandboard-revb1.dtb \ imx6q-arm2.dtb \ diff --git a/arch/arm/boot/dts/imx6dl-udoo.dts b/arch/arm/boot/dts/imx6dl-udoo.dts new file mode 100644 index 00000000000000..e3713f00e81914 --- /dev/null +++ b/arch/arm/boot/dts/imx6dl-udoo.dts @@ -0,0 +1,18 @@ +/* + * Copyright 2013 Freescale Semiconductor, Inc. + * + * Author: Fabio Estevam + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +/dts-v1/; +#include "imx6dl.dtsi" +#include "imx6qdl-udoo.dtsi" + +/ { + model = "Udoo i.MX6 Dual-lite Board"; + compatible = "udoo,imx6dl-udoo", "fsl,imx6dl"; +}; diff --git a/arch/arm/boot/dts/imx6q-udoo.dts b/arch/arm/boot/dts/imx6q-udoo.dts index e3bff2ac00db28..c3e64ff3d54465 100644 --- a/arch/arm/boot/dts/imx6q-udoo.dts +++ b/arch/arm/boot/dts/imx6q-udoo.dts @@ -8,137 +8,15 @@ * published by the Free Software Foundation. * */ - /dts-v1/; #include "imx6q.dtsi" +#include "imx6qdl-udoo.dtsi" / { model = "Udoo i.MX6 Quad Board"; compatible = "udoo,imx6q-udoo", "fsl,imx6q"; - - chosen { - stdout-path = &uart2; - }; - - memory { - reg = <0x10000000 0x40000000>; - }; - - regulators { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; - - reg_usb_h1_vbus: regulator@0 { - compatible = "regulator-fixed"; - reg = <0>; - regulator-name = "usb_h1_vbus"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - enable-active-high; - startup-delay-us = <2>; /* USB2415 requires a POR of 1 us minimum */ - gpio = <&gpio7 12 0>; - }; - }; -}; - -&fec { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_enet>; - phy-mode = "rgmii"; - status = "okay"; -}; - -&hdmi { - ddc-i2c-bus = <&i2c2>; - status = "okay"; -}; - -&i2c2 { - clock-frequency = <100000>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_i2c2>; - status = "okay"; -}; - -&iomuxc { - imx6q-udoo { - pinctrl_enet: enetgrp { - fsl,pins = < - MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 - MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 - MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 - MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 - MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 - MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 - MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 - MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 - MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 - MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 - MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 - MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 - MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 - MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 - MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 - MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 - >; - }; - - pinctrl_i2c2: i2c2grp { - fsl,pins = < - MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 - MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 - >; - }; - - pinctrl_uart2: uart2grp { - fsl,pins = < - MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1 - MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1 - >; - }; - - pinctrl_usbh: usbhgrp { - fsl,pins = < - MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000 - MX6QDL_PAD_NANDF_CS2__CCM_CLKO2 0x130b0 - >; - }; - - pinctrl_usdhc3: usdhc3grp { - fsl,pins = < - MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 - MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 - MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 - MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 - MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 - MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 - >; - }; - }; }; &sata { status = "okay"; }; - -&uart2 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_uart2>; - status = "okay"; -}; - -&usbh1 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_usbh>; - vbus-supply = <®_usb_h1_vbus>; - clocks = <&clks 201>; - status = "okay"; -}; - -&usdhc3 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_usdhc3>; - non-removable; - status = "okay"; -}; diff --git a/arch/arm/boot/dts/imx6qdl-udoo.dtsi b/arch/arm/boot/dts/imx6qdl-udoo.dtsi new file mode 100644 index 00000000000000..1211da894ee999 --- /dev/null +++ b/arch/arm/boot/dts/imx6qdl-udoo.dtsi @@ -0,0 +1,134 @@ +/* + * Copyright 2013 Freescale Semiconductor, Inc. + * + * Author: Fabio Estevam + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +/ { + chosen { + stdout-path = &uart2; + }; + + memory { + reg = <0x10000000 0x40000000>; + }; + + regulators { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + reg_usb_h1_vbus: regulator@0 { + compatible = "regulator-fixed"; + reg = <0>; + regulator-name = "usb_h1_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + startup-delay-us = <2>; /* USB2415 requires a POR of 1 us minimum */ + gpio = <&gpio7 12 0>; + }; + }; +}; + +&fec { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet>; + phy-mode = "rgmii"; + status = "okay"; +}; + +&hdmi { + ddc-i2c-bus = <&i2c2>; + status = "okay"; +}; + +&i2c2 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + status = "okay"; +}; + +&iomuxc { + imx6q-udoo { + pinctrl_enet: enetgrp { + fsl,pins = < + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 + MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 + >; + }; + + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 + MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1 + MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1 + >; + }; + + pinctrl_usbh: usbhgrp { + fsl,pins = < + MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000 + MX6QDL_PAD_NANDF_CS2__CCM_CLKO2 0x130b0 + >; + }; + + pinctrl_usdhc3: usdhc3grp { + fsl,pins = < + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 + >; + }; + }; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + status = "okay"; +}; + +&usbh1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbh>; + vbus-supply = <®_usb_h1_vbus>; + clocks = <&clks 201>; + status = "okay"; +}; + +&usdhc3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc3>; + non-removable; + status = "okay"; +}; From c8aeb7dfe6e815906c3d9c23ce17a00e8d01b3d5 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 6 Jan 2015 20:06:16 +0800 Subject: [PATCH 0434/3023] ARM: imx: drop CPUIDLE_FLAG_TIME_VALID from cpuidle-imx6sx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As the result of commit b82b6cca4880 ("cpuidle: Invert CPUIDLE_FLAG_TIME_VALID logic"), the flag gets removed and hence we see the compile error below. CC arch/arm/mach-imx/cpuidle-imx6sx.o arch/arm/mach-imx/cpuidle-imx6sx.c:69:13: error: ‘CPUIDLE_FLAG_TIME_VALID’ undeclared here (not in a function) Since the behavior of the original flag has been the default, we can simply drop the flag now. Reported-by: kbuild test robot Signed-off-by: Shawn Guo --- arch/arm/mach-imx/cpuidle-imx6sx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/arm/mach-imx/cpuidle-imx6sx.c b/arch/arm/mach-imx/cpuidle-imx6sx.c index d8a9f219e02863..5a36722b089d60 100644 --- a/arch/arm/mach-imx/cpuidle-imx6sx.c +++ b/arch/arm/mach-imx/cpuidle-imx6sx.c @@ -66,8 +66,7 @@ static struct cpuidle_driver imx6sx_cpuidle_driver = { { .exit_latency = 50, .target_residency = 75, - .flags = CPUIDLE_FLAG_TIME_VALID | - CPUIDLE_FLAG_TIMER_STOP, + .flags = CPUIDLE_FLAG_TIMER_STOP, .enter = imx6sx_enter_wait, .name = "WAIT", .desc = "Clock off", @@ -81,7 +80,6 @@ static struct cpuidle_driver imx6sx_cpuidle_driver = { */ .exit_latency = 300, .target_residency = 500, - .flags = CPUIDLE_FLAG_TIME_VALID, .enter = imx6sx_enter_wait, .name = "LOW-POWER-IDLE", .desc = "ARM power off", From fe07e48964c6f21020eeeb7f83e35a5bf1977a65 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 6 Jan 2015 14:10:57 +0100 Subject: [PATCH 0435/3023] ARM: tegra: Regenerate defconfig based on v3.19-rc1 Removes the following entries from the default configuration: - PM: enabled by default (via PM_SLEEP -> SUSPEND) - RESOURCE_COUNTERS: removed Signed-off-by: Thierry Reding --- arch/arm/configs/tegra_defconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig index 3ea9c3377ccbd2..d199eb2491517e 100644 --- a/arch/arm/configs/tegra_defconfig +++ b/arch/arm/configs/tegra_defconfig @@ -8,7 +8,6 @@ CONFIG_CGROUPS=y CONFIG_CGROUP_DEBUG=y CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_CPUACCT=y -CONFIG_RESOURCE_COUNTERS=y CONFIG_CGROUP_SCHED=y CONFIG_RT_GROUP_SCHED=y CONFIG_BLK_DEV_INITRD=y @@ -46,7 +45,6 @@ CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y CONFIG_CPU_IDLE=y CONFIG_VFP=y CONFIG_NEON=y -CONFIG_PM=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y From bb247d1e75e6514400c1efe7e1106e29ca9490d9 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 6 Jan 2015 10:35:26 +0800 Subject: [PATCH 0436/3023] ARM: sunxi_defconfig: Enable TOUCHSCREEN_SUN4I, CPUFREQ_DT, CPU_THERMAL This patch enables TOUCHSCREEN_SUN4I, CPUFREQ_DT, and CPU_THERMAL to enable cpufreq support with passive cpu cooling (thermal throttling) by default. Signed-off-by: Chen-Yu Tsai Acked-by: Eduardo Valentin Signed-off-by: Maxime Ripard --- arch/arm/configs/sunxi_defconfig | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig index 7a342d2780a8e7..46a8688bd49ad1 100644 --- a/arch/arm/configs/sunxi_defconfig +++ b/arch/arm/configs/sunxi_defconfig @@ -9,6 +9,8 @@ CONFIG_HIGHMEM=y CONFIG_HIGHPTE=y CONFIG_ARM_APPENDED_DTB=y CONFIG_ARM_ATAG_DTB_COMPAT=y +CONFIG_CPU_FREQ=y +CONFIG_CPUFREQ_DT=y CONFIG_VFP=y CONFIG_NEON=y CONFIG_PM=y @@ -54,6 +56,8 @@ CONFIG_STMMAC_ETH=y # CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_SUN4I=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_NR_UARTS=8 @@ -71,7 +75,8 @@ CONFIG_GPIO_SYSFS=y CONFIG_POWER_SUPPLY=y CONFIG_POWER_RESET=y CONFIG_POWER_RESET_SUN6I=y -# CONFIG_HWMON is not set +CONFIG_THERMAL=y +CONFIG_CPU_THERMAL=y CONFIG_WATCHDOG=y CONFIG_SUNXI_WATCHDOG=y CONFIG_MFD_AXP20X=y From 4c3e125df0d47c2a737993f077e662a0495e23c9 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 6 Jan 2015 10:35:27 +0800 Subject: [PATCH 0437/3023] ARM: multi_v7_defconfig: Enable TOUCHSCREEN_SUN4I, CPU_THERMAL This patch enables TOUCHSCREEN_SUN4I and CPU_THERMAL to enable cpufreq support with passive cpu cooling (thermal throttling) on sunxi by default. Signed-off-by: Chen-Yu Tsai Acked-by: Eduardo Valentin Signed-off-by: Maxime Ripard --- arch/arm/configs/multi_v7_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 2328fe752e9c5e..0e7159ad269bd7 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -189,6 +189,7 @@ CONFIG_MOUSE_PS2_ELANTECH=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_ATMEL_MXT=y CONFIG_TOUCHSCREEN_STMPE=y +CONFIG_TOUCHSCREEN_SUN4I=y CONFIG_INPUT_MISC=y CONFIG_INPUT_MPU3050=y CONFIG_SERIO_AMBAKMI=y @@ -267,6 +268,7 @@ CONFIG_POWER_RESET_SUN6I=y CONFIG_SENSORS_LM90=y CONFIG_SENSORS_LM95245=y CONFIG_THERMAL=y +CONFIG_CPU_THERMAL=y CONFIG_ARMADA_THERMAL=y CONFIG_ST_THERMAL_SYSCFG=y CONFIG_ST_THERMAL_MEMMAP=y From 314fcb230cad7eea311f065f20f03ed9d08d8edf Mon Sep 17 00:00:00 2001 From: Carlo Caione Date: Tue, 23 Dec 2014 10:53:13 +0800 Subject: [PATCH 0438/3023] ARM: sunxi: Add AXP20x support in defconfig Signed-off-by: Carlo Caione Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/configs/sunxi_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig index 46a8688bd49ad1..38840a8129240f 100644 --- a/arch/arm/configs/sunxi_defconfig +++ b/arch/arm/configs/sunxi_defconfig @@ -56,6 +56,8 @@ CONFIG_STMMAC_ETH=y # CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_MISC=y +CONFIG_INPUT_AXP20X_PEK=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_SUN4I=y CONFIG_SERIAL_8250=y @@ -82,6 +84,7 @@ CONFIG_SUNXI_WATCHDOG=y CONFIG_MFD_AXP20X=y CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_AXP20X=y CONFIG_REGULATOR_GPIO=y CONFIG_USB=y CONFIG_USB_EHCI_HCD=y From fef3f0dde681a32f148b765ee8e1465fba9b3cd4 Mon Sep 17 00:00:00 2001 From: Carlo Caione Date: Tue, 23 Dec 2014 10:53:14 +0800 Subject: [PATCH 0439/3023] ARM: sunxi: Add AXP20x support multi_v7_defconfig Signed-off-by: Carlo Caione Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/configs/multi_v7_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 0e7159ad269bd7..65ca0e72882e67 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -192,6 +192,7 @@ CONFIG_TOUCHSCREEN_STMPE=y CONFIG_TOUCHSCREEN_SUN4I=y CONFIG_INPUT_MISC=y CONFIG_INPUT_MPU3050=y +CONFIG_INPUT_AXP20X_PEK=y CONFIG_SERIO_AMBAKMI=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y @@ -280,6 +281,7 @@ CONFIG_SUNXI_WATCHDOG=y CONFIG_MESON_WATCHDOG=y CONFIG_MFD_AS3722=y CONFIG_MFD_BCM590XX=y +CONFIG_MFD_AXP20X=y CONFIG_MFD_CROS_EC=y CONFIG_MFD_CROS_EC_SPI=y CONFIG_MFD_MAX77686=y @@ -292,6 +294,7 @@ CONFIG_MFD_TPS6586X=y CONFIG_MFD_TPS65910=y CONFIG_REGULATOR_AB8500=y CONFIG_REGULATOR_AS3722=y +CONFIG_REGULATOR_AXP20X=y CONFIG_REGULATOR_BCM590XX=y CONFIG_REGULATOR_GPIO=y CONFIG_MFD_SYSCON=y From dcbc9eb1919359719be0ef652afe1d90b0fa98ed Mon Sep 17 00:00:00 2001 From: Peter Seiderer Date: Sun, 8 Dec 2013 22:03:58 +0100 Subject: [PATCH 0440/3023] drm/imx: parallel-display: fix imxpd-->edid memleak If edid was allocated during bind, it must be freed again during unbind. Signed-off-by: Peter Seiderer Acked-by: Sascha Hauer Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/parallel-display.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index 796c3c1c170a11..88cf7ca1e886a5 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c @@ -257,6 +257,8 @@ static void imx_pd_unbind(struct device *dev, struct device *master, imxpd->encoder.funcs->destroy(&imxpd->encoder); imxpd->connector.funcs->destroy(&imxpd->connector); + + kfree(imxpd->edid); } static const struct component_ops imx_pd_ops = { @@ -272,6 +274,7 @@ static int imx_pd_probe(struct platform_device *pdev) static int imx_pd_remove(struct platform_device *pdev) { component_del(&pdev->dev, &imx_pd_ops); + return 0; } From f4876ffea6f310e1c7ee015687f913248a0d5f9c Mon Sep 17 00:00:00 2001 From: Peter Seiderer Date: Sun, 8 Dec 2013 22:03:57 +0100 Subject: [PATCH 0441/3023] drm/imx: imx-ldb: fix channel->edid memleak If edid was allocated during bind, it must be freed again during unbind. Signed-off-by: Peter Seiderer Acked-by: Sascha Hauer Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/imx-ldb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index c60460043e24dc..4ff62a517c755e 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c @@ -574,6 +574,8 @@ static void imx_ldb_unbind(struct device *dev, struct device *master, channel->connector.funcs->destroy(&channel->connector); channel->encoder.funcs->destroy(&channel->encoder); + + kfree(channel->edid); } } From 6457b9716bca99b95a07e85ff8b00f9bf471ac2c Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 3 Jul 2014 17:52:57 +0100 Subject: [PATCH 0442/3023] drm/imx: convert imx-drm to use the generic DRM OF helper Use the generic DRM OF helper to locate the possible CRTCs for the encoder, thereby shrinking the imx-drm driver some more. Signed-off-by: Russell King Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/imx-drm-core.c | 84 +++++++----------------------- 1 file changed, 19 insertions(+), 65 deletions(-) diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c index b250130debc87e..06cd2e516db6a9 100644 --- a/drivers/gpu/drm/imx/imx-drm-core.c +++ b/drivers/gpu/drm/imx/imx-drm-core.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "imx-drm.h" @@ -46,7 +47,6 @@ struct imx_drm_crtc { struct drm_crtc *crtc; int pipe; struct imx_drm_crtc_helper_funcs imx_drm_helper_funcs; - struct device_node *port; }; static int legacyfb_depth = 16; @@ -365,9 +365,10 @@ int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc, imx_drm_crtc->imx_drm_helper_funcs = *imx_drm_helper_funcs; imx_drm_crtc->pipe = imxdrm->pipes++; - imx_drm_crtc->port = port; imx_drm_crtc->crtc = crtc; + crtc->port = port; + imxdrm->crtc[imx_drm_crtc->pipe] = imx_drm_crtc; *new_crtc = imx_drm_crtc; @@ -408,33 +409,28 @@ int imx_drm_remove_crtc(struct imx_drm_crtc *imx_drm_crtc) } EXPORT_SYMBOL_GPL(imx_drm_remove_crtc); -/* - * Find the DRM CRTC possible mask for the connected endpoint. - * - * The encoder possible masks are defined by their position in the - * mode_config crtc_list. This means that CRTCs must not be added - * or removed once the DRM device has been fully initialised. - */ -static uint32_t imx_drm_find_crtc_mask(struct imx_drm_device *imxdrm, - struct device_node *endpoint) +int imx_drm_encoder_parse_of(struct drm_device *drm, + struct drm_encoder *encoder, struct device_node *np) { - struct device_node *port; - unsigned i; + uint32_t crtc_mask = drm_of_find_possible_crtcs(drm, np); - port = of_graph_get_remote_port(endpoint); - if (!port) - return 0; - of_node_put(port); + /* + * If we failed to find the CRTC(s) which this encoder is + * supposed to be connected to, it's because the CRTC has + * not been registered yet. Defer probing, and hope that + * the required CRTC is added later. + */ + if (crtc_mask == 0) + return -EPROBE_DEFER; - for (i = 0; i < MAX_CRTC; i++) { - struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[i]; + encoder->possible_crtcs = crtc_mask; - if (imx_drm_crtc && imx_drm_crtc->port == port) - return drm_crtc_mask(imx_drm_crtc->crtc); - } + /* FIXME: this is the mask of outputs which can clone this output. */ + encoder->possible_clones = ~0; return 0; } +EXPORT_SYMBOL_GPL(imx_drm_encoder_parse_of); static struct device_node *imx_drm_of_get_next_endpoint( const struct device_node *parent, struct device_node *prev) @@ -445,48 +441,6 @@ static struct device_node *imx_drm_of_get_next_endpoint( return node; } -int imx_drm_encoder_parse_of(struct drm_device *drm, - struct drm_encoder *encoder, struct device_node *np) -{ - struct imx_drm_device *imxdrm = drm->dev_private; - struct device_node *ep = NULL; - uint32_t crtc_mask = 0; - int i; - - for (i = 0; ; i++) { - u32 mask; - - ep = imx_drm_of_get_next_endpoint(np, ep); - if (!ep) - break; - - mask = imx_drm_find_crtc_mask(imxdrm, ep); - - /* - * If we failed to find the CRTC(s) which this encoder is - * supposed to be connected to, it's because the CRTC has - * not been registered yet. Defer probing, and hope that - * the required CRTC is added later. - */ - if (mask == 0) - return -EPROBE_DEFER; - - crtc_mask |= mask; - } - - of_node_put(ep); - if (i == 0) - return -ENOENT; - - encoder->possible_crtcs = crtc_mask; - - /* FIXME: this is the mask of outputs which can clone this output. */ - encoder->possible_clones = ~0; - - return 0; -} -EXPORT_SYMBOL_GPL(imx_drm_encoder_parse_of); - /* * @node: device tree node containing encoder input ports * @encoder: drm_encoder @@ -510,7 +464,7 @@ int imx_drm_encoder_get_mux_id(struct device_node *node, port = of_graph_get_remote_port(ep); of_node_put(port); - if (port == imx_crtc->port) { + if (port == imx_crtc->crtc->port) { ret = of_graph_parse_endpoint(ep, &endpoint); return ret ? ret : endpoint.port; } From f853f3daac748daa339bc8b64ba39db82160524a Mon Sep 17 00:00:00 2001 From: Steve Longerbeam Date: Mon, 26 Aug 2013 11:42:09 -0700 Subject: [PATCH 0443/3023] gpu: ipu-v3: Implement use counter for ipu_dc_enable(), ipu_dc_disable() The functions ipu_dc_enable() and ipu_dc_disable() enable/disable the DC globally in the IPU_CONF register, but the DC is used by multiple clients on different DC channels. So make sure to only disable/enable the DC globally based on a use counter. Signed-off-by: Steve Longerbeam Signed-off-by: Philipp Zabel --- drivers/gpu/ipu-v3/ipu-dc.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/ipu-v3/ipu-dc.c b/drivers/gpu/ipu-v3/ipu-dc.c index 2326c752d89b20..323203d0503aab 100644 --- a/drivers/gpu/ipu-v3/ipu-dc.c +++ b/drivers/gpu/ipu-v3/ipu-dc.c @@ -114,6 +114,7 @@ struct ipu_dc_priv { struct completion comp; int dc_irq; int dp_irq; + int use_count; }; static void dc_link_event(struct ipu_dc *dc, int event, int addr, int priority) @@ -232,7 +233,16 @@ EXPORT_SYMBOL_GPL(ipu_dc_init_sync); void ipu_dc_enable(struct ipu_soc *ipu) { - ipu_module_enable(ipu, IPU_CONF_DC_EN); + struct ipu_dc_priv *priv = ipu->dc_priv; + + mutex_lock(&priv->mutex); + + if (!priv->use_count) + ipu_module_enable(priv->ipu, IPU_CONF_DC_EN); + + priv->use_count++; + + mutex_unlock(&priv->mutex); } EXPORT_SYMBOL_GPL(ipu_dc_enable); @@ -294,7 +304,18 @@ EXPORT_SYMBOL_GPL(ipu_dc_disable_channel); void ipu_dc_disable(struct ipu_soc *ipu) { - ipu_module_disable(ipu, IPU_CONF_DC_EN); + struct ipu_dc_priv *priv = ipu->dc_priv; + + mutex_lock(&priv->mutex); + + priv->use_count--; + if (!priv->use_count) + ipu_module_disable(priv->ipu, IPU_CONF_DC_EN); + + if (priv->use_count < 0) + priv->use_count = 0; + + mutex_unlock(&priv->mutex); } EXPORT_SYMBOL_GPL(ipu_dc_disable); From b587833933de39e21b314e3b392ac0f1ec94a97e Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Fri, 5 Dec 2014 14:23:52 +0800 Subject: [PATCH 0444/3023] drm: imx: imx-hdmi: make checkpatch happy CHECK: Alignment should match open parenthesis + if ((hdmi->vic == 10) || (hdmi->vic == 11) || + (hdmi->vic == 12) || (hdmi->vic == 13) || CHECK: braces {} should be used on all arms of this statement + if (hdmi->hdmi_data.video_mode.mdvi) [...] + else { [...] Signed-off-by: Andy Yan Reviewed-by: Daniel Kurtz Tested-by: Russell King Acked-by: Russell King Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/imx-hdmi.c | 109 ++++++++++++++++----------------- 1 file changed, 52 insertions(+), 57 deletions(-) diff --git a/drivers/gpu/drm/imx/imx-hdmi.c b/drivers/gpu/drm/imx/imx-hdmi.c index ddc53e039530bd..3f96a5e6670d4c 100644 --- a/drivers/gpu/drm/imx/imx-hdmi.c +++ b/drivers/gpu/drm/imx/imx-hdmi.c @@ -163,7 +163,7 @@ static void hdmi_modb(struct imx_hdmi *hdmi, u8 data, u8 mask, unsigned reg) } static void hdmi_mask_writeb(struct imx_hdmi *hdmi, u8 data, unsigned int reg, - u8 shift, u8 mask) + u8 shift, u8 mask) { hdmi_modb(hdmi, data << shift, mask, reg); } @@ -327,7 +327,7 @@ static unsigned int hdmi_compute_cts(unsigned int freq, unsigned long pixel_clk, } static void hdmi_set_clk_regenerator(struct imx_hdmi *hdmi, - unsigned long pixel_clk) + unsigned long pixel_clk) { unsigned int clk_n, clk_cts; @@ -338,7 +338,7 @@ static void hdmi_set_clk_regenerator(struct imx_hdmi *hdmi, if (!clk_cts) { dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n", - __func__, pixel_clk); + __func__, pixel_clk); return; } @@ -477,13 +477,11 @@ static void imx_hdmi_update_csc_coeffs(struct imx_hdmi *hdmi) u16 coeff_b = (*csc_coeff)[1][i]; u16 coeff_c = (*csc_coeff)[2][i]; - hdmi_writeb(hdmi, coeff_a & 0xff, - HDMI_CSC_COEF_A1_LSB + i * 2); + hdmi_writeb(hdmi, coeff_a & 0xff, HDMI_CSC_COEF_A1_LSB + i * 2); hdmi_writeb(hdmi, coeff_a >> 8, HDMI_CSC_COEF_A1_MSB + i * 2); hdmi_writeb(hdmi, coeff_b & 0xff, HDMI_CSC_COEF_B1_LSB + i * 2); hdmi_writeb(hdmi, coeff_b >> 8, HDMI_CSC_COEF_B1_MSB + i * 2); - hdmi_writeb(hdmi, coeff_c & 0xff, - HDMI_CSC_COEF_C1_LSB + i * 2); + hdmi_writeb(hdmi, coeff_c & 0xff, HDMI_CSC_COEF_C1_LSB + i * 2); hdmi_writeb(hdmi, coeff_c >> 8, HDMI_CSC_COEF_C1_MSB + i * 2); } @@ -535,21 +533,22 @@ static void hdmi_video_packetize(struct imx_hdmi *hdmi) struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data; u8 val, vp_conf; - if (hdmi_data->enc_out_format == RGB - || hdmi_data->enc_out_format == YCBCR444) { - if (!hdmi_data->enc_color_depth) + if (hdmi_data->enc_out_format == RGB || + hdmi_data->enc_out_format == YCBCR444) { + if (!hdmi_data->enc_color_depth) { output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS; - else if (hdmi_data->enc_color_depth == 8) { + } else if (hdmi_data->enc_color_depth == 8) { color_depth = 4; output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS; - } else if (hdmi_data->enc_color_depth == 10) + } else if (hdmi_data->enc_color_depth == 10) { color_depth = 5; - else if (hdmi_data->enc_color_depth == 12) + } else if (hdmi_data->enc_color_depth == 12) { color_depth = 6; - else if (hdmi_data->enc_color_depth == 16) + } else if (hdmi_data->enc_color_depth == 16) { color_depth = 7; - else + } else { return; + } } else if (hdmi_data->enc_out_format == YCBCR422_8BITS) { if (!hdmi_data->enc_color_depth || hdmi_data->enc_color_depth == 8) @@ -561,8 +560,9 @@ static void hdmi_video_packetize(struct imx_hdmi *hdmi) else return; output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422; - } else + } else { return; + } /* set the packetizer registers */ val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) & @@ -623,34 +623,34 @@ static void hdmi_video_packetize(struct imx_hdmi *hdmi) } static inline void hdmi_phy_test_clear(struct imx_hdmi *hdmi, - unsigned char bit) + unsigned char bit) { hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLR_OFFSET, HDMI_PHY_TST0_TSTCLR_MASK, HDMI_PHY_TST0); } static inline void hdmi_phy_test_enable(struct imx_hdmi *hdmi, - unsigned char bit) + unsigned char bit) { hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTEN_OFFSET, HDMI_PHY_TST0_TSTEN_MASK, HDMI_PHY_TST0); } static inline void hdmi_phy_test_clock(struct imx_hdmi *hdmi, - unsigned char bit) + unsigned char bit) { hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLK_OFFSET, HDMI_PHY_TST0_TSTCLK_MASK, HDMI_PHY_TST0); } static inline void hdmi_phy_test_din(struct imx_hdmi *hdmi, - unsigned char bit) + unsigned char bit) { hdmi_writeb(hdmi, bit, HDMI_PHY_TST1); } static inline void hdmi_phy_test_dout(struct imx_hdmi *hdmi, - unsigned char bit) + unsigned char bit) { hdmi_writeb(hdmi, bit, HDMI_PHY_TST2); } @@ -666,21 +666,21 @@ static bool hdmi_phy_wait_i2c_done(struct imx_hdmi *hdmi, int msec) } static void __hdmi_phy_i2c_write(struct imx_hdmi *hdmi, unsigned short data, - unsigned char addr) + unsigned char addr) { hdmi_writeb(hdmi, 0xFF, HDMI_IH_I2CMPHY_STAT0); hdmi_writeb(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR); hdmi_writeb(hdmi, (unsigned char)(data >> 8), - HDMI_PHY_I2CM_DATAO_1_ADDR); + HDMI_PHY_I2CM_DATAO_1_ADDR); hdmi_writeb(hdmi, (unsigned char)(data >> 0), - HDMI_PHY_I2CM_DATAO_0_ADDR); + HDMI_PHY_I2CM_DATAO_0_ADDR); hdmi_writeb(hdmi, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE, - HDMI_PHY_I2CM_OPERATION_ADDR); + HDMI_PHY_I2CM_OPERATION_ADDR); hdmi_phy_wait_i2c_done(hdmi, 1000); } static int hdmi_phy_i2c_write(struct imx_hdmi *hdmi, unsigned short data, - unsigned char addr) + unsigned char addr) { __hdmi_phy_i2c_write(hdmi, data, addr); return 0; @@ -839,7 +839,7 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep, hdmi_phy_test_clear(hdmi, 1); hdmi_writeb(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2, - HDMI_PHY_I2CM_SLAVE_ADDR); + HDMI_PHY_I2CM_SLAVE_ADDR); hdmi_phy_test_clear(hdmi, 0); /* PLL/MPLL Cfg - always match on final entry */ @@ -857,9 +857,8 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep, break; if (i >= ARRAY_SIZE(curr_ctrl)) { - dev_err(hdmi->dev, - "Pixel clock %d - unsupported by HDMI\n", - hdmi->hdmi_data.video_mode.mpixelclock); + dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n", + hdmi->hdmi_data.video_mode.mpixelclock); return -EINVAL; } @@ -1223,21 +1222,21 @@ static int imx_hdmi_setup(struct imx_hdmi *hdmi, struct drm_display_mode *mode) } if ((hdmi->vic == 6) || (hdmi->vic == 7) || - (hdmi->vic == 21) || (hdmi->vic == 22) || - (hdmi->vic == 2) || (hdmi->vic == 3) || - (hdmi->vic == 17) || (hdmi->vic == 18)) + (hdmi->vic == 21) || (hdmi->vic == 22) || + (hdmi->vic == 2) || (hdmi->vic == 3) || + (hdmi->vic == 17) || (hdmi->vic == 18)) hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601; else hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709; if ((hdmi->vic == 10) || (hdmi->vic == 11) || - (hdmi->vic == 12) || (hdmi->vic == 13) || - (hdmi->vic == 14) || (hdmi->vic == 15) || - (hdmi->vic == 25) || (hdmi->vic == 26) || - (hdmi->vic == 27) || (hdmi->vic == 28) || - (hdmi->vic == 29) || (hdmi->vic == 30) || - (hdmi->vic == 35) || (hdmi->vic == 36) || - (hdmi->vic == 37) || (hdmi->vic == 38)) + (hdmi->vic == 12) || (hdmi->vic == 13) || + (hdmi->vic == 14) || (hdmi->vic == 15) || + (hdmi->vic == 25) || (hdmi->vic == 26) || + (hdmi->vic == 27) || (hdmi->vic == 28) || + (hdmi->vic == 29) || (hdmi->vic == 30) || + (hdmi->vic == 35) || (hdmi->vic == 36) || + (hdmi->vic == 37) || (hdmi->vic == 38)) hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 1; else hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0; @@ -1266,9 +1265,9 @@ static int imx_hdmi_setup(struct imx_hdmi *hdmi, struct drm_display_mode *mode) imx_hdmi_enable_video_path(hdmi); /* not for DVI mode */ - if (hdmi->hdmi_data.video_mode.mdvi) + if (hdmi->hdmi_data.video_mode.mdvi) { dev_dbg(hdmi->dev, "%s DVI mode\n", __func__); - else { + } else { dev_dbg(hdmi->dev, "%s CEA mode\n", __func__); /* HDMI Initialization Step E - Configure audio */ @@ -1525,7 +1524,7 @@ static irqreturn_t imx_hdmi_irq(int irq, void *dev_id) dev_dbg(hdmi->dev, "EVENT=plugout\n"); hdmi_modb(hdmi, HDMI_PHY_HPD, HDMI_PHY_HPD, - HDMI_PHY_POL0); + HDMI_PHY_POL0); imx_hdmi_poweroff(hdmi); } @@ -1554,7 +1553,7 @@ static int imx_hdmi_register(struct drm_device *drm, struct imx_hdmi *hdmi) DRM_MODE_ENCODER_TMDS); drm_connector_helper_add(&hdmi->connector, - &imx_hdmi_connector_helper_funcs); + &imx_hdmi_connector_helper_funcs); drm_connector_init(drm, &hdmi->connector, &imx_hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA); @@ -1642,40 +1641,36 @@ static int imx_hdmi_bind(struct device *dev, struct device *master, void *data) hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr"); if (IS_ERR(hdmi->isfr_clk)) { ret = PTR_ERR(hdmi->isfr_clk); - dev_err(hdmi->dev, - "Unable to get HDMI isfr clk: %d\n", ret); + dev_err(hdmi->dev, "Unable to get HDMI isfr clk: %d\n", ret); return ret; } ret = clk_prepare_enable(hdmi->isfr_clk); if (ret) { - dev_err(hdmi->dev, - "Cannot enable HDMI isfr clock: %d\n", ret); + dev_err(hdmi->dev, "Cannot enable HDMI isfr clock: %d\n", ret); return ret; } hdmi->iahb_clk = devm_clk_get(hdmi->dev, "iahb"); if (IS_ERR(hdmi->iahb_clk)) { ret = PTR_ERR(hdmi->iahb_clk); - dev_err(hdmi->dev, - "Unable to get HDMI iahb clk: %d\n", ret); + dev_err(hdmi->dev, "Unable to get HDMI iahb clk: %d\n", ret); goto err_isfr; } ret = clk_prepare_enable(hdmi->iahb_clk); if (ret) { - dev_err(hdmi->dev, - "Cannot enable HDMI iahb clock: %d\n", ret); + dev_err(hdmi->dev, "Cannot enable HDMI iahb clock: %d\n", ret); goto err_isfr; } /* Product and revision IDs */ dev_info(dev, - "Detected HDMI controller 0x%x:0x%x:0x%x:0x%x\n", - hdmi_readb(hdmi, HDMI_DESIGN_ID), - hdmi_readb(hdmi, HDMI_REVISION_ID), - hdmi_readb(hdmi, HDMI_PRODUCT_ID0), - hdmi_readb(hdmi, HDMI_PRODUCT_ID1)); + "Detected HDMI controller 0x%x:0x%x:0x%x:0x%x\n", + hdmi_readb(hdmi, HDMI_DESIGN_ID), + hdmi_readb(hdmi, HDMI_REVISION_ID), + hdmi_readb(hdmi, HDMI_PRODUCT_ID0), + hdmi_readb(hdmi, HDMI_PRODUCT_ID1)); initialize_hdmi_ih_mutes(hdmi); From c2c3848851a723a0e5e0fec22df395a885edf459 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Fri, 5 Dec 2014 14:24:28 +0800 Subject: [PATCH 0445/3023] drm: imx: imx-hdmi: return defer if can't get ddc i2c adapter drm driver may probe before the i2c bus, so the driver should defer probing until it is available Signed-off-by: Andy Yan Reviewed-by: Daniel Kurtz Tested-by: Russell King Acked-by: Russell King Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/imx-hdmi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/imx/imx-hdmi.c b/drivers/gpu/drm/imx/imx-hdmi.c index 3f96a5e6670d4c..3118dde3ea62ea 100644 --- a/drivers/gpu/drm/imx/imx-hdmi.c +++ b/drivers/gpu/drm/imx/imx-hdmi.c @@ -1611,10 +1611,12 @@ static int imx_hdmi_bind(struct device *dev, struct device *master, void *data) ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); if (ddc_node) { hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node); - if (!hdmi->ddc) + of_node_put(ddc_node); + if (!hdmi->ddc) { dev_dbg(hdmi->dev, "failed to read ddc node\n"); + return -EPROBE_DEFER; + } - of_node_put(ddc_node); } else { dev_dbg(hdmi->dev, "no ddc property found\n"); } From 3d1b35a3d9f3d6de690b237995d5aa858e349648 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Fri, 5 Dec 2014 14:25:05 +0800 Subject: [PATCH 0446/3023] drm: imx: imx-hdmi: convert imx-hdmi to drm_bridge mode IMX6 and Rockchip RK3288 and JZ4780 (Ingenic Xburst/MIPS) use the interface compatible Designware HDMI IP, but they also have some lightly differences, such as phy pll configuration, register width, 4K support, clk useage, and the crtc mux configuration is also platform specific. To reuse the imx hdmi driver, convert it to drm_bridge handle encoder in imx-hdmi_pltfm.c, as most of the encoder operation are platform specific such as crtc select and panel format set This patch depends on Russell King's patch: drm: imx: convert imx-drm to use the generic DRM OF helper http://driverdev.linuxdriverproject.org/pipermail/driverdev-devel/2014-July/053484.html Signed-off-by: Andy Yan Signed-off-by: Yakir Yang Tested-by: Russell King Acked-by: Russell King Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/Makefile | 2 +- drivers/gpu/drm/imx/imx-hdmi.c | 257 ++++++++++----------------- drivers/gpu/drm/imx/imx-hdmi.h | 15 ++ drivers/gpu/drm/imx/imx-hdmi_pltfm.c | 203 +++++++++++++++++++++ 4 files changed, 315 insertions(+), 162 deletions(-) create mode 100644 drivers/gpu/drm/imx/imx-hdmi_pltfm.c diff --git a/drivers/gpu/drm/imx/Makefile b/drivers/gpu/drm/imx/Makefile index 582c438d8cbdb9..63cf56ad5c6194 100644 --- a/drivers/gpu/drm/imx/Makefile +++ b/drivers/gpu/drm/imx/Makefile @@ -9,4 +9,4 @@ obj-$(CONFIG_DRM_IMX_LDB) += imx-ldb.o imx-ipuv3-crtc-objs := ipuv3-crtc.o ipuv3-plane.o obj-$(CONFIG_DRM_IMX_IPUV3) += imx-ipuv3-crtc.o -obj-$(CONFIG_DRM_IMX_HDMI) += imx-hdmi.o +obj-$(CONFIG_DRM_IMX_HDMI) += imx-hdmi.o imx-hdmi_pltfm.o diff --git a/drivers/gpu/drm/imx/imx-hdmi.c b/drivers/gpu/drm/imx/imx-hdmi.c index 3118dde3ea62ea..9f2f0feb7b7593 100644 --- a/drivers/gpu/drm/imx/imx-hdmi.c +++ b/drivers/gpu/drm/imx/imx-hdmi.c @@ -12,25 +12,20 @@ * Copyright (C) 2010, Guennadi Liakhovetski */ -#include #include #include #include #include #include -#include -#include -#include #include +#include #include #include #include #include -#include - + Using uio_dmem_genirq for platform devices In addition to statically allocated memory ranges, they may also be @@ -746,16 +746,16 @@ framework to set up sysfs files for this region. Simply leave it alone. following elements: - struct uio_info uioinfo: The same + struct uio_info uioinfo: The same structure used as the uio_pdrv_genirq platform - data - unsigned int *dynamic_region_sizes: + data + unsigned int *dynamic_region_sizes: Pointer to list of sizes of dynamic memory regions to be mapped into user space. - - unsigned int num_dynamic_regions: + + unsigned int num_dynamic_regions: Number of elements in dynamic_region_sizes array. - + The dynamic regions defined in the platform data will be appended to From 410d841a599683408a77f42f110cd17298682520 Mon Sep 17 00:00:00 2001 From: Kaixu Xia Date: Mon, 26 Jan 2015 09:22:17 -0700 Subject: [PATCH 2688/3023] coresight: fix the replicator subtype value According to the classification, the type of replicator is link, so the subtype should also be link_subtype. Signed-off-by: Kaixu Xia Signed-off-by: Mathieu Poirier Signed-off-by: Greg Kroah-Hartman --- drivers/coresight/coresight-replicator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/coresight/coresight-replicator.c b/drivers/coresight/coresight-replicator.c index a2dfcf903551b9..cdf05537d57482 100644 --- a/drivers/coresight/coresight-replicator.c +++ b/drivers/coresight/coresight-replicator.c @@ -87,7 +87,7 @@ static int replicator_probe(struct platform_device *pdev) return -ENOMEM; desc->type = CORESIGHT_DEV_TYPE_LINK; - desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_LINK_SPLIT; + desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_SPLIT; desc->ops = &replicator_cs_ops; desc->pdata = pdev->dev.platform_data; desc->dev = &pdev->dev; From adf305f77878880fa5868a7179979da93be68d83 Mon Sep 17 00:00:00 2001 From: Javi Merino Date: Thu, 15 Jan 2015 16:17:45 +0000 Subject: [PATCH 2689/3023] sysfs: fix warning when creating a sysfs group without attributes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When attempting to create a gropu without attrs, the warning prints the name of the group. However, the check for name being a NULL pointer is wrong: it uses the pointer to the name when it's NULL. Fix it to use the name if present, otherwise just put an empty string. Cc: Bruno Prémont Cc: Greg Kroah-Hartman Signed-off-by: Javi Merino Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/group.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index 7d2a860ba788f7..2554d8835b480b 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c @@ -99,7 +99,7 @@ static int internal_create_group(struct kobject *kobj, int update, return -EINVAL; if (!grp->attrs && !grp->bin_attrs) { WARN(1, "sysfs: (bin_)attrs not set by subsystem for group: %s/%s\n", - kobj->name, grp->name ? "" : grp->name); + kobj->name, grp->name ?: ""); return -EINVAL; } if (grp->name) { From 3239fd31d4b6b7e0f5629eb458bd67b719050783 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Fri, 5 Dec 2014 20:21:57 +0100 Subject: [PATCH 2690/3023] serial: of-serial: fetch line number from DT The general agreed way to specify a fixed line number for a serial console is to provide a "serial" alias in the devicetree. Start parsing this property in of_serial. Signed-off-by: Lucas Stach Acked-by: Olof Johansson Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/of_serial.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index fbb719c89a6114..7ff61e24a195cb 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c @@ -102,6 +102,11 @@ static int of_platform_serial_setup(struct platform_device *ofdev, if (of_property_read_u32(np, "fifo-size", &prop) == 0) port->fifosize = prop; + /* Check for a fixed line number */ + ret = of_alias_get_id(np, "serial"); + if (ret >= 0) + port->line = ret; + port->irq = irq_of_parse_and_map(np, 0); port->iotype = UPIO_MEM; if (of_property_read_u32(np, "reg-io-width", &prop) == 0) { From 79ce9d52ae17ff9a29edc2c71638af37f709b9cd Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Sat, 10 Jan 2015 18:08:51 +0100 Subject: [PATCH 2691/3023] tty: remove unused variable sprop sprop is unused in find_console_handle() since commit a752ee56ad84 ("tty: Update hypervisor tty drivers to use core stdout parsing code.") Signed-off-by: Fabian Frederick Signed-off-by: Greg Kroah-Hartman --- drivers/tty/ehv_bytechan.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c index 3c60923b0957b4..342b36b9ad35a1 100644 --- a/drivers/tty/ehv_bytechan.c +++ b/drivers/tty/ehv_bytechan.c @@ -112,7 +112,6 @@ static void disable_tx_interrupt(struct ehv_bc_data *bc) static int find_console_handle(void) { struct device_node *np = of_stdout; - const char *sprop = NULL; const uint32_t *iprop; /* We don't care what the aliased node is actually called. We only From 2cbf7fe2d5d32a4747c1f8ad163e886dccad930c Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 3 Feb 2015 13:18:55 +0000 Subject: [PATCH 2692/3023] i2o: move to staging The I2O layer deals with a technology that to say the least didn't catch on in the market. The only relevant products are some of the AMI MegaRAID - which supported I2O and its native mode (The native mode is faster and runs on Linux), an obscure crypto ethernet card that's now so many years out of date nobody would use it, the old DPT controllers, which speak their own dialect and have their own driver - and ermm.. thats about it. We also know the code isn't in good shape as recently a patch was proposed and queried as buggy, which in turn showed the existing code was broken already by prior "clean up" and nobody had noticed that either. It's coding style robot code nothing more. Like some forgotten corridor cleaned relentlessly by a lost Roomba but where no user has trodden in years. Move it to staging and then to /dev/null. The headers remain as they are shared with dpt_i2o. Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/Kconfig | 2 -- drivers/message/Makefile | 1 - drivers/staging/Kconfig | 2 ++ drivers/staging/Makefile | 1 + drivers/{message => staging}/i2o/Kconfig | 1 - drivers/{message => staging}/i2o/Makefile | 0 drivers/{message => staging}/i2o/README | 0 drivers/{message => staging}/i2o/README.ioctl | 0 drivers/{message => staging}/i2o/bus-osm.c | 2 +- drivers/{message => staging}/i2o/config-osm.c | 2 +- drivers/{message => staging}/i2o/core.h | 0 drivers/{message => staging}/i2o/debug.c | 2 +- drivers/{message => staging}/i2o/device.c | 2 +- drivers/{message => staging}/i2o/driver.c | 2 +- drivers/{message => staging}/i2o/exec-osm.c | 2 +- {include/linux => drivers/staging/i2o}/i2o.h | 0 drivers/{message => staging}/i2o/i2o_block.c | 2 +- drivers/{message => staging}/i2o/i2o_block.h | 0 drivers/{message => staging}/i2o/i2o_config.c | 0 drivers/{message => staging}/i2o/i2o_proc.c | 2 +- drivers/{message => staging}/i2o/i2o_scsi.c | 2 +- drivers/{message => staging}/i2o/iop.c | 2 +- drivers/{message => staging}/i2o/memory.c | 2 +- drivers/{message => staging}/i2o/pci.c | 2 +- 24 files changed, 15 insertions(+), 16 deletions(-) rename drivers/{message => staging}/i2o/Kconfig (99%) rename drivers/{message => staging}/i2o/Makefile (100%) rename drivers/{message => staging}/i2o/README (100%) rename drivers/{message => staging}/i2o/README.ioctl (100%) rename drivers/{message => staging}/i2o/bus-osm.c (99%) rename drivers/{message => staging}/i2o/config-osm.c (98%) rename drivers/{message => staging}/i2o/core.h (100%) rename drivers/{message => staging}/i2o/debug.c (99%) rename drivers/{message => staging}/i2o/device.c (99%) rename drivers/{message => staging}/i2o/driver.c (99%) rename drivers/{message => staging}/i2o/exec-osm.c (99%) rename {include/linux => drivers/staging/i2o}/i2o.h (100%) rename drivers/{message => staging}/i2o/i2o_block.c (99%) rename drivers/{message => staging}/i2o/i2o_block.h (100%) rename drivers/{message => staging}/i2o/i2o_config.c (100%) rename drivers/{message => staging}/i2o/i2o_proc.c (99%) rename drivers/{message => staging}/i2o/i2o_scsi.c (99%) rename drivers/{message => staging}/i2o/iop.c (99%) rename drivers/{message => staging}/i2o/memory.c (99%) rename drivers/{message => staging}/i2o/pci.c (99%) diff --git a/drivers/Kconfig b/drivers/Kconfig index c70d6e45dc1029..c0cc96bab9e741 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -36,8 +36,6 @@ source "drivers/message/fusion/Kconfig" source "drivers/firewire/Kconfig" -source "drivers/message/i2o/Kconfig" - source "drivers/macintosh/Kconfig" source "drivers/net/Kconfig" diff --git a/drivers/message/Makefile b/drivers/message/Makefile index 97ef5a01ad1159..755676ded67c7f 100644 --- a/drivers/message/Makefile +++ b/drivers/message/Makefile @@ -2,5 +2,4 @@ # Makefile for MPT based block devices # -obj-$(CONFIG_I2O) += i2o/ obj-$(CONFIG_FUSION) += fusion/ diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 071ac116818f54..9e52bcd5356da0 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -110,4 +110,6 @@ source "drivers/staging/clocking-wizard/Kconfig" source "drivers/staging/fbtft/Kconfig" +source "drivers/staging/i2o/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index b65ca376d9575c..6e0ac524c84d94 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -47,3 +47,4 @@ obj-$(CONFIG_CRYPTO_SKEIN) += skein/ obj-$(CONFIG_UNISYSSPAR) += unisys/ obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/ obj-$(CONFIG_FB_TFT) += fbtft/ +obj-$(CONFIG_I2O) += i2o/ diff --git a/drivers/message/i2o/Kconfig b/drivers/staging/i2o/Kconfig similarity index 99% rename from drivers/message/i2o/Kconfig rename to drivers/staging/i2o/Kconfig index 5afa0e393ecff9..286c53f4b13d8c 100644 --- a/drivers/message/i2o/Kconfig +++ b/drivers/staging/i2o/Kconfig @@ -1,4 +1,3 @@ - menuconfig I2O tristate "I2O device support" depends on PCI diff --git a/drivers/message/i2o/Makefile b/drivers/staging/i2o/Makefile similarity index 100% rename from drivers/message/i2o/Makefile rename to drivers/staging/i2o/Makefile diff --git a/drivers/message/i2o/README b/drivers/staging/i2o/README similarity index 100% rename from drivers/message/i2o/README rename to drivers/staging/i2o/README diff --git a/drivers/message/i2o/README.ioctl b/drivers/staging/i2o/README.ioctl similarity index 100% rename from drivers/message/i2o/README.ioctl rename to drivers/staging/i2o/README.ioctl diff --git a/drivers/message/i2o/bus-osm.c b/drivers/staging/i2o/bus-osm.c similarity index 99% rename from drivers/message/i2o/bus-osm.c rename to drivers/staging/i2o/bus-osm.c index c463dc2efc0949..7aa0339aea056f 100644 --- a/drivers/message/i2o/bus-osm.c +++ b/drivers/staging/i2o/bus-osm.c @@ -14,7 +14,7 @@ */ #include -#include +#include "i2o.h" #define OSM_NAME "bus-osm" #define OSM_VERSION "1.317" diff --git a/drivers/message/i2o/config-osm.c b/drivers/staging/i2o/config-osm.c similarity index 98% rename from drivers/message/i2o/config-osm.c rename to drivers/staging/i2o/config-osm.c index 3bba7aa82e58bd..519f52f9f68819 100644 --- a/drivers/message/i2o/config-osm.c +++ b/drivers/staging/i2o/config-osm.c @@ -14,7 +14,7 @@ */ #include -#include +#include "i2o.h" #include #include #include diff --git a/drivers/message/i2o/core.h b/drivers/staging/i2o/core.h similarity index 100% rename from drivers/message/i2o/core.h rename to drivers/staging/i2o/core.h diff --git a/drivers/message/i2o/debug.c b/drivers/staging/i2o/debug.c similarity index 99% rename from drivers/message/i2o/debug.c rename to drivers/staging/i2o/debug.c index ce62d8bfe1c832..7a16114ed8ea39 100644 --- a/drivers/message/i2o/debug.c +++ b/drivers/staging/i2o/debug.c @@ -1,7 +1,7 @@ #include #include #include -#include +#include "i2o.h" static void i2o_report_util_cmd(u8 cmd); static void i2o_report_exec_cmd(u8 cmd); diff --git a/drivers/message/i2o/device.c b/drivers/staging/i2o/device.c similarity index 99% rename from drivers/message/i2o/device.c rename to drivers/staging/i2o/device.c index 98348f420b52b9..2af22553dd4e8f 100644 --- a/drivers/message/i2o/device.c +++ b/drivers/staging/i2o/device.c @@ -14,7 +14,7 @@ */ #include -#include +#include "i2o.h" #include #include #include diff --git a/drivers/message/i2o/driver.c b/drivers/staging/i2o/driver.c similarity index 99% rename from drivers/message/i2o/driver.c rename to drivers/staging/i2o/driver.c index 1b18a0d1d05bdf..111c3edde035d5 100644 --- a/drivers/message/i2o/driver.c +++ b/drivers/staging/i2o/driver.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include "i2o.h" #include #include #include diff --git a/drivers/message/i2o/exec-osm.c b/drivers/staging/i2o/exec-osm.c similarity index 99% rename from drivers/message/i2o/exec-osm.c rename to drivers/staging/i2o/exec-osm.c index a3970e56ae539f..16d857d5e65541 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/staging/i2o/exec-osm.c @@ -28,7 +28,7 @@ */ #include -#include +#include "i2o.h" #include #include #include diff --git a/include/linux/i2o.h b/drivers/staging/i2o/i2o.h similarity index 100% rename from include/linux/i2o.h rename to drivers/staging/i2o/i2o.h diff --git a/drivers/message/i2o/i2o_block.c b/drivers/staging/i2o/i2o_block.c similarity index 99% rename from drivers/message/i2o/i2o_block.c rename to drivers/staging/i2o/i2o_block.c index 6fc3866965df97..0a13c64ce000b9 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/staging/i2o/i2o_block.c @@ -52,7 +52,7 @@ #include #include -#include +#include "i2o.h" #include #include diff --git a/drivers/message/i2o/i2o_block.h b/drivers/staging/i2o/i2o_block.h similarity index 100% rename from drivers/message/i2o/i2o_block.h rename to drivers/staging/i2o/i2o_block.h diff --git a/drivers/message/i2o/i2o_config.c b/drivers/staging/i2o/i2o_config.c similarity index 100% rename from drivers/message/i2o/i2o_config.c rename to drivers/staging/i2o/i2o_config.c diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/staging/i2o/i2o_proc.c similarity index 99% rename from drivers/message/i2o/i2o_proc.c rename to drivers/staging/i2o/i2o_proc.c index b7d87cd227a902..ad84f3304f3cd3 100644 --- a/drivers/message/i2o/i2o_proc.c +++ b/drivers/staging/i2o/i2o_proc.c @@ -39,7 +39,7 @@ #include #include #include -#include +#include "i2o.h" #include #include #include diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/staging/i2o/i2o_scsi.c similarity index 99% rename from drivers/message/i2o/i2o_scsi.c rename to drivers/staging/i2o/i2o_scsi.c index 8152e9fa9d95c2..1b11dcb3faea7b 100644 --- a/drivers/message/i2o/i2o_scsi.c +++ b/drivers/staging/i2o/i2o_scsi.c @@ -53,7 +53,7 @@ #include #include #include -#include +#include "i2o.h" #include #include diff --git a/drivers/message/i2o/iop.c b/drivers/staging/i2o/iop.c similarity index 99% rename from drivers/message/i2o/iop.c rename to drivers/staging/i2o/iop.c index 92752fb5b2d3d8..52334fc8b54700 100644 --- a/drivers/message/i2o/iop.c +++ b/drivers/staging/i2o/iop.c @@ -26,7 +26,7 @@ */ #include -#include +#include "i2o.h" #include #include #include diff --git a/drivers/message/i2o/memory.c b/drivers/staging/i2o/memory.c similarity index 99% rename from drivers/message/i2o/memory.c rename to drivers/staging/i2o/memory.c index 292b41e49fbd57..8f9509d275a46f 100644 --- a/drivers/message/i2o/memory.c +++ b/drivers/staging/i2o/memory.c @@ -11,7 +11,7 @@ */ #include -#include +#include "i2o.h" #include #include #include diff --git a/drivers/message/i2o/pci.c b/drivers/staging/i2o/pci.c similarity index 99% rename from drivers/message/i2o/pci.c rename to drivers/staging/i2o/pci.c index 0f9f3e1a2b6b4f..b3b8a61dd4a6d7 100644 --- a/drivers/message/i2o/pci.c +++ b/drivers/staging/i2o/pci.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include "i2o.h" #include #include "core.h" From b5d78b7f816ecfdf274e7673e79ce165d3f052cb Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 3 Feb 2015 13:18:03 +0000 Subject: [PATCH 2693/3023] staging: cptm1217: blow it all away We have a drivers/input layer for Synaptics products and nothing should now be using the staging driver. Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/cptm1217/Kconfig | 12 - drivers/staging/cptm1217/Makefile | 2 - drivers/staging/cptm1217/TODO | 5 - drivers/staging/cptm1217/clearpad_tm1217.c | 671 --------------------- drivers/staging/cptm1217/cp_tm1217.h | 8 - 7 files changed, 701 deletions(-) delete mode 100644 drivers/staging/cptm1217/Kconfig delete mode 100644 drivers/staging/cptm1217/Makefile delete mode 100644 drivers/staging/cptm1217/TODO delete mode 100644 drivers/staging/cptm1217/clearpad_tm1217.c delete mode 100644 drivers/staging/cptm1217/cp_tm1217.h diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 9e52bcd5356da0..1a2c281ea206da 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -68,8 +68,6 @@ source "drivers/staging/ft1000/Kconfig" source "drivers/staging/speakup/Kconfig" -source "drivers/staging/cptm1217/Kconfig" - source "drivers/staging/ste_rmi4/Kconfig" source "drivers/staging/nvec/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 6e0ac524c84d94..bd02e9b970de2f 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -28,7 +28,6 @@ obj-$(CONFIG_FB_XGI) += xgifb/ obj-$(CONFIG_USB_EMXX) += emxx_udc/ obj-$(CONFIG_FT1000) += ft1000/ obj-$(CONFIG_SPEAKUP) += speakup/ -obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217) += cptm1217/ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/ obj-$(CONFIG_MFD_NVEC) += nvec/ obj-$(CONFIG_ANDROID) += android/ diff --git a/drivers/staging/cptm1217/Kconfig b/drivers/staging/cptm1217/Kconfig deleted file mode 100644 index 43b1cc0a50a5e7..00000000000000 --- a/drivers/staging/cptm1217/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -config TOUCHSCREEN_CLEARPAD_TM1217 - tristate "Synaptics Clearpad TM1217" - depends on I2C - depends on GPIOLIB - depends on INPUT - help - Say Y here if you have a Synaptics Clearpad TM1217 Controller - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called clearpad_tm1217. diff --git a/drivers/staging/cptm1217/Makefile b/drivers/staging/cptm1217/Makefile deleted file mode 100644 index 8961fafa80e706..00000000000000 --- a/drivers/staging/cptm1217/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217) += clearpad_tm1217.o - diff --git a/drivers/staging/cptm1217/TODO b/drivers/staging/cptm1217/TODO deleted file mode 100644 index 303922465e4d99..00000000000000 --- a/drivers/staging/cptm1217/TODO +++ /dev/null @@ -1,5 +0,0 @@ -- Wait for the official upstream general clearpad drivers as promised over - the past few months -- Merge any device support needed from this driver into it -- Delete this driver - diff --git a/drivers/staging/cptm1217/clearpad_tm1217.c b/drivers/staging/cptm1217/clearpad_tm1217.c deleted file mode 100644 index 43046049830c31..00000000000000 --- a/drivers/staging/cptm1217/clearpad_tm1217.c +++ /dev/null @@ -1,671 +0,0 @@ -/* - * clearpad_tm1217.c - Touch Screen driver for Synaptics Clearpad - * TM1217 controller - * - * Copyright (C) 2008 Intel Corp - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; ifnot, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * Questions/Comments/Bug fixes to Ramesh Agarwal (ramesh.agarwal@intel.com) - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "cp_tm1217.h" - -#define CPTM1217_DEVICE_NAME "cptm1217" -#define CPTM1217_DRIVER_NAME CPTM1217_DEVICE_NAME - -#define MAX_TOUCH_SUPPORTED 2 -#define TOUCH_SUPPORTED 1 -#define SAMPLING_FREQ 80 /* Frequency in HZ */ -#define DELAY_BTWIN_SAMPLE (1000 / SAMPLING_FREQ) -#define WAIT_FOR_RESPONSE 5 /* 5msec just works */ -#define MAX_RETRIES 5 /* As above */ -#define INCREMENTAL_DELAY 5 /* As above */ - -/* Regster Definitions */ -#define TMA1217_DEV_STATUS 0x13 /* Device Status */ -#define TMA1217_INT_STATUS 0x14 /* Interrupt Status */ - -/* Controller can detect up to 2 possible finger touches. - * Each finger touch provides 12 bit X Y co-ordinates, the values are split - * across 2 registers, and an 8 bit Z value */ -#define TMA1217_FINGER_STATE 0x18 /* Finger State */ -#define TMA1217_FINGER1_X_HIGHER8 0x19 /* Higher 8 bit of X coordinate */ -#define TMA1217_FINGER1_Y_HIGHER8 0x1A /* Higher 8 bit of Y coordinate */ -#define TMA1217_FINGER1_XY_LOWER4 0x1B /* Lower 4 bits of X and Y */ -#define TMA1217_FINGER1_Z_VALUE 0x1D /* 8 bit Z value for finger 1 */ -#define TMA1217_FINGER2_X_HIGHER8 0x1E /* Higher 8 bit of X coordinate */ -#define TMA1217_FINGER2_Y_HIGHER8 0x1F /* Higher 8 bit of Y coordinate */ -#define TMA1217_FINGER2_XY_LOWER4 0x20 /* Lower 4 bits of X and Y */ -#define TMA1217_FINGER2_Z_VALUE 0x22 /* 8 bit Z value for finger 2 */ -#define TMA1217_DEVICE_CTRL 0x23 /* Device Control */ -#define TMA1217_INTERRUPT_ENABLE 0x24 /* Interrupt Enable */ -#define TMA1217_REPORT_MODE 0x2B /* Reporting Mode */ -#define TMA1217_MAX_X_LOWER8 0x31 /* Bit 0-7 for Max X */ -#define TMA1217_MAX_X_HIGHER4 0x32 /* Bit 8-11 for Max X */ -#define TMA1217_MAX_Y_LOWER8 0x33 /* Bit 0-7 for Max Y */ -#define TMA1217_MAX_Y_HIGHER4 0x34 /* Bit 8-11 for Max Y */ -#define TMA1217_DEVICE_CMD_RESET 0x67 /* Device CMD reg for reset */ -#define TMA1217_DEVICE_CMD_REZERO 0x69 /* Device CMD reg for rezero */ - -#define TMA1217_MANUFACTURER_ID 0x73 /* Manufacturer Id */ -#define TMA1217_PRODUCT_FAMILY 0x75 /* Product Family */ -#define TMA1217_FIRMWARE_REVISION 0x76 /* Firmware Revision */ -#define TMA1217_SERIAL_NO_HIGH 0x7C /* Bit 8-15 of device serial no. */ -#define TMA1217_SERIAL_NO_LOW 0x7D /* Bit 0-7 of device serial no. */ -#define TMA1217_PRODUCT_ID_START 0x7E /* Start address for 10 byte ID */ -#define TMA1217_DEVICE_CAPABILITY 0x8B /* Reporting capability */ - - -/* - * The touch position structure. - */ -struct touch_state { - int x; - int y; - bool button; -}; - -/* Device Specific info given by the controller */ -struct cp_dev_info { - u16 maxX; - u16 maxY; -}; - -/* Vendor related info given by the controller */ -struct cp_vendor_info { - u8 vendor_id; - u8 product_family; - u8 firmware_rev; - u16 serial_no; -}; - -/* - * Private structure to store the device details - */ -struct cp_tm1217_device { - struct i2c_client *client; - struct device *dev; - struct cp_vendor_info vinfo; - struct cp_dev_info dinfo; - struct input_dev_info { - char phys[32]; - char name[128]; - struct input_dev *input; - struct touch_state touch; - } cp_input_info[MAX_TOUCH_SUPPORTED]; - - int thread_running; - struct mutex thread_mutex; - - int gpio; -}; - - -/* The following functions are used to read/write registers on the device - * as per the RMI prorocol. Technically, a page select should be written - * before doing read/write but since the register offsets are below 0xFF - * we can use the default value of page which is 0x00 - */ -static int cp_tm1217_read(struct cp_tm1217_device *ts, - u8 *req, int size) -{ - int i, retval; - - /* Send the address */ - retval = i2c_master_send(ts->client, &req[0], 1); - if (retval != 1) { - dev_err(ts->dev, "cp_tm1217: I2C send failed\n"); - return retval; - } - msleep(WAIT_FOR_RESPONSE); - for (i = 0; i < MAX_RETRIES; i++) { - retval = i2c_master_recv(ts->client, &req[1], size); - if (retval == size) - break; - - msleep(INCREMENTAL_DELAY); - dev_dbg(ts->dev, "cp_tm1217: Retry count is %d\n", i); - } - if (retval != size) - dev_err(ts->dev, "cp_tm1217: Read from device failed\n"); - - return retval; -} - -static int cp_tm1217_write(struct cp_tm1217_device *ts, - u8 *req, int size) -{ - int retval; - - /* Send the address and the data to be written */ - retval = i2c_master_send(ts->client, &req[0], size + 1); - if (retval != size + 1) { - dev_err(ts->dev, "cp_tm1217: I2C write failed: %d\n", retval); - return retval; - } - /* Wait for the write to complete. TBD why this is required */ - msleep(WAIT_FOR_RESPONSE); - - return size; -} - -static int cp_tm1217_mask_interrupt(struct cp_tm1217_device *ts) -{ - u8 req[2]; - int retval; - - req[0] = TMA1217_INTERRUPT_ENABLE; - req[1] = 0x0; - retval = cp_tm1217_write(ts, req, 1); - if (retval != 1) - return -EIO; - - return 0; -} - -static int cp_tm1217_unmask_interrupt(struct cp_tm1217_device *ts) -{ - u8 req[2]; - int retval; - - req[0] = TMA1217_INTERRUPT_ENABLE; - req[1] = 0xa; - retval = cp_tm1217_write(ts, req, 1); - if (retval != 1) - return -EIO; - - return 0; -} - -static void process_touch(struct cp_tm1217_device *ts, int index) -{ - int retval; - struct input_dev_info *input_info = - (struct input_dev_info *)&ts->cp_input_info[index]; - u8 xy_data[6]; - - if (index == 0) - xy_data[0] = TMA1217_FINGER1_X_HIGHER8; - else - xy_data[0] = TMA1217_FINGER2_X_HIGHER8; - - retval = cp_tm1217_read(ts, xy_data, 5); - if (retval < 5) { - dev_err(ts->dev, "cp_tm1217: XY read from device failed\n"); - return; - } - - /* Note: Currently not using the Z values but may be requried in - the future. */ - input_info->touch.x = (xy_data[1] << 4) - | (xy_data[3] & 0x0F); - input_info->touch.y = (xy_data[2] << 4) - | ((xy_data[3] & 0xF0) >> 4); - input_report_abs(input_info->input, ABS_X, input_info->touch.x); - input_report_abs(input_info->input, ABS_Y, input_info->touch.y); - input_sync(input_info->input); -} - -static void cp_tm1217_get_data(struct cp_tm1217_device *ts) -{ - u8 req[2]; - int retval, i, finger_touched = 0; - - do { - req[0] = TMA1217_FINGER_STATE; - retval = cp_tm1217_read(ts, req, 1); - if (retval != 1) { - dev_err(ts->dev, - "cp_tm1217: Read from device failed\n"); - continue; - } - finger_touched = 0; - /* Start sampling until the pressure is below - threshold */ - for (i = 0; i < TOUCH_SUPPORTED; i++) { - if (req[1] & 0x3) { - finger_touched++; - if (ts->cp_input_info[i].touch.button == 0) { - /* send the button touch event */ - input_report_key( - ts->cp_input_info[i].input, - BTN_TOUCH, 1); - ts->cp_input_info[i].touch.button = 1; - } - process_touch(ts, i); - } else { - if (ts->cp_input_info[i].touch.button == 1) { - /* send the button release event */ - input_report_key( - ts->cp_input_info[i].input, - BTN_TOUCH, 0); - input_sync(ts->cp_input_info[i].input); - ts->cp_input_info[i].touch.button = 0; - } - } - req[1] = req[1] >> 2; - } - msleep(DELAY_BTWIN_SAMPLE); - } while (finger_touched > 0); -} - -static irqreturn_t cp_tm1217_sample_thread(int irq, void *handle) -{ - struct cp_tm1217_device *ts = handle; - u8 req[2]; - int retval; - - /* Chedk if another thread is already running */ - mutex_lock(&ts->thread_mutex); - if (ts->thread_running == 1) { - mutex_unlock(&ts->thread_mutex); - return IRQ_HANDLED; - } - - ts->thread_running = 1; - mutex_unlock(&ts->thread_mutex); - - /* Mask the interrupts */ - retval = cp_tm1217_mask_interrupt(ts); - - /* Read the Interrupt Status register to find the cause of the - Interrupt */ - req[0] = TMA1217_INT_STATUS; - retval = cp_tm1217_read(ts, req, 1); - if (retval != 1) - goto exit_thread; - - if (!(req[1] & 0x8)) - goto exit_thread; - - cp_tm1217_get_data(ts); - -exit_thread: - /* Unmask the interrupts before going to sleep */ - retval = cp_tm1217_unmask_interrupt(ts); - - mutex_lock(&ts->thread_mutex); - ts->thread_running = 0; - mutex_unlock(&ts->thread_mutex); - - return IRQ_HANDLED; -} - -static int cp_tm1217_init_data(struct cp_tm1217_device *ts) -{ - int retval; - u8 req[2]; - - /* Read the vendor id/ fw revision etc. Ignoring return check as this - is non critical info */ - req[0] = TMA1217_MANUFACTURER_ID; - retval = cp_tm1217_read(ts, req, 1); - ts->vinfo.vendor_id = req[1]; - - req[0] = TMA1217_PRODUCT_FAMILY; - retval = cp_tm1217_read(ts, req, 1); - ts->vinfo.product_family = req[1]; - - req[0] = TMA1217_FIRMWARE_REVISION; - retval = cp_tm1217_read(ts, req, 1); - ts->vinfo.firmware_rev = req[1]; - - req[0] = TMA1217_SERIAL_NO_HIGH; - retval = cp_tm1217_read(ts, req, 1); - ts->vinfo.serial_no = (req[1] << 8); - - req[0] = TMA1217_SERIAL_NO_LOW; - retval = cp_tm1217_read(ts, req, 1); - ts->vinfo.serial_no = ts->vinfo.serial_no | req[1]; - - req[0] = TMA1217_MAX_X_HIGHER4; - retval = cp_tm1217_read(ts, req, 1); - ts->dinfo.maxX = (req[1] & 0xF) << 8; - - req[0] = TMA1217_MAX_X_LOWER8; - retval = cp_tm1217_read(ts, req, 1); - ts->dinfo.maxX = ts->dinfo.maxX | req[1]; - - req[0] = TMA1217_MAX_Y_HIGHER4; - retval = cp_tm1217_read(ts, req, 1); - ts->dinfo.maxY = (req[1] & 0xF) << 8; - - req[0] = TMA1217_MAX_Y_LOWER8; - retval = cp_tm1217_read(ts, req, 1); - ts->dinfo.maxY = ts->dinfo.maxY | req[1]; - - return 0; - -} - -/* - * Set up a GPIO for use as the interrupt. We can't simply do this at - * boot time because the GPIO drivers themselves may not be around at - * boot/firmware set up time to do the work. Instead defer it to driver - * detection. - */ - -static int cp_tm1217_setup_gpio_irq(struct cp_tm1217_device *ts) -{ - int retval; - - /* Hook up the irq handler */ - retval = gpio_request(ts->gpio, "cp_tm1217_touch"); - if (retval < 0) { - dev_err(ts->dev, "cp_tm1217: GPIO request failed error %d\n", - retval); - return retval; - } - - retval = gpio_direction_input(ts->gpio); - if (retval < 0) { - dev_err(ts->dev, - "cp_tm1217: GPIO direction configuration failed, error %d\n", - retval); - gpio_free(ts->gpio); - return retval; - } - - retval = gpio_to_irq(ts->gpio); - if (retval < 0) { - dev_err(ts->dev, - "cp_tm1217: GPIO to IRQ failed, error %d\n", retval); - gpio_free(ts->gpio); - } - dev_dbg(ts->dev, - "cp_tm1217: Got IRQ number is %d for GPIO %d\n", - retval, ts->gpio); - return retval; -} - -static int cp_tm1217_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct cp_tm1217_device *ts; - struct input_dev *input_dev; - struct input_dev_info *input_info; - struct cp_tm1217_platform_data *pdata; - u8 req[2]; - int i, retval; - - /* No pdata is fine - we then use "normal" IRQ mode */ - - pdata = client->dev.platform_data; - - ts = kzalloc(sizeof(struct cp_tm1217_device), GFP_KERNEL); - if (!ts) - return -ENOMEM; - - ts->client = client; - ts->dev = &client->dev; - i2c_set_clientdata(client, ts); - - ts->thread_running = 0; - mutex_init(&ts->thread_mutex); - - /* Reset the Controller */ - req[0] = TMA1217_DEVICE_CMD_RESET; - req[1] = 0x1; - retval = cp_tm1217_write(ts, req, 1); - if (retval != 1) { - dev_err(ts->dev, "cp_tm1217: Controller reset failed\n"); - kfree(ts); - return -EIO; - } - - /* Clear up the interrupt status from reset. */ - req[0] = TMA1217_INT_STATUS; - retval = cp_tm1217_read(ts, req, 1); - - /* Mask all the interrupts */ - retval = cp_tm1217_mask_interrupt(ts); - if (retval) { - dev_err(ts->dev, "failed to mask interrupts, error: %d\n", - retval); - kfree(ts); - return retval; - } - - /* Read the controller information */ - cp_tm1217_init_data(ts); - - /* The following code will register multiple event devices when - multi-pointer is enabled, the code has not been tested - with MPX */ - for (i = 0; i < TOUCH_SUPPORTED; i++) { - input_dev = input_allocate_device(); - if (input_dev == NULL) { - retval = -ENOMEM; - goto fail; - } - input_info = &ts->cp_input_info[i]; - snprintf(input_info->name, sizeof(input_info->name), - "cp_tm1217_touchscreen_%d", i); - input_dev->name = input_info->name; - snprintf(input_info->phys, sizeof(input_info->phys), - "%s/input%d", dev_name(&client->dev), i); - - input_dev->phys = input_info->phys; - input_dev->id.bustype = BUS_I2C; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); - - input_set_abs_params(input_dev, ABS_X, 0, ts->dinfo.maxX, 0, 0); - input_set_abs_params(input_dev, ABS_Y, 0, ts->dinfo.maxY, 0, 0); - - retval = input_register_device(input_dev); - if (retval) { - dev_err(ts->dev, - "Input dev registration failed for %s\n", - input_dev->name); - input_free_device(input_dev); - goto fail; - } - input_info->input = input_dev; - } - - /* Setup the reporting mode to send an interrupt only when - finger arrives or departs. */ - req[0] = TMA1217_REPORT_MODE; - req[1] = 0x02; - retval = cp_tm1217_write(ts, req, 1); - - /* Setup the device to no sleep mode for now and make it configured */ - req[0] = TMA1217_DEVICE_CTRL; - req[1] = 0x84; - retval = cp_tm1217_write(ts, req, 1); - - /* Check for the status of the device */ - req[0] = TMA1217_DEV_STATUS; - retval = cp_tm1217_read(ts, req, 1); - if (req[1] != 0) { - dev_err(ts->dev, - "cp_tm1217: Device Status 0x%x != 0: config failed\n", - req[1]); - - retval = -EIO; - goto fail; - } - - if (pdata && pdata->gpio) { - ts->gpio = pdata->gpio; - retval = cp_tm1217_setup_gpio_irq(ts); - } else - retval = client->irq; - - if (retval < 0) { - dev_err(ts->dev, "cp_tm1217: GPIO request failed error %d\n", - retval); - goto fail; - } - - client->irq = retval; - - - retval = request_threaded_irq(client->irq, - NULL, cp_tm1217_sample_thread, - IRQF_TRIGGER_FALLING, "cp_tm1217_touch", ts); - if (retval < 0) { - dev_err(ts->dev, "cp_tm1217: Request IRQ error %d\n", retval); - goto fail_gpio; - } - - /* Unmask the interrupts */ - retval = cp_tm1217_unmask_interrupt(ts); - if (retval == 0) - return 0; - - free_irq(client->irq, ts); -fail_gpio: - if (ts->gpio) - gpio_free(ts->gpio); -fail: - /* Clean up before returning failure */ - for (i = 0; i < TOUCH_SUPPORTED; i++) { - if (ts->cp_input_info[i].input) - input_unregister_device(ts->cp_input_info[i].input); - } - kfree(ts); - return retval; - -} - -#ifdef CONFIG_PM_SLEEP - -/* - * cp_tm1217 suspend - * - */ -static int cp_tm1217_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct cp_tm1217_device *ts = i2c_get_clientdata(client); - u8 req[2]; - int retval; - - /* Put the controller to sleep */ - req[0] = TMA1217_DEVICE_CTRL; - retval = cp_tm1217_read(ts, req, 1); - req[1] = (req[1] & 0xF8) | 0x1; - retval = cp_tm1217_write(ts, req, 1); - - if (device_may_wakeup(&client->dev)) - enable_irq_wake(client->irq); - - return 0; -} - -/* - * cp_tm1217_resume - * - */ -static int cp_tm1217_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct cp_tm1217_device *ts = i2c_get_clientdata(client); - u8 req[2]; - int retval; - - /* Take the controller out of sleep */ - req[0] = TMA1217_DEVICE_CTRL; - retval = cp_tm1217_read(ts, req, 1); - req[1] = (req[1] & 0xF8) | 0x4; - retval = cp_tm1217_write(ts, req, 1); - - /* Restore the register settings sinc the power to the - could have been cut off */ - - /* Setup the reporting mode to send an interrupt only when - finger arrives or departs. */ - req[0] = TMA1217_REPORT_MODE; - req[1] = 0x02; - retval = cp_tm1217_write(ts, req, 1); - - /* Setup the device to no sleep mode for now and make it configured */ - req[0] = TMA1217_DEVICE_CTRL; - req[1] = 0x84; - retval = cp_tm1217_write(ts, req, 1); - - /* Setup the interrupt mask */ - retval = cp_tm1217_unmask_interrupt(ts); - - if (device_may_wakeup(&client->dev)) - disable_irq_wake(client->irq); - - return 0; -} - -#endif - -static SIMPLE_DEV_PM_OPS(cp_tm1217_pm_ops, cp_tm1217_suspend, - cp_tm1217_resume); - -/* - * cp_tm1217_remove - * - */ -static int cp_tm1217_remove(struct i2c_client *client) -{ - struct cp_tm1217_device *ts = i2c_get_clientdata(client); - int i; - - free_irq(client->irq, ts); - if (ts->gpio) - gpio_free(ts->gpio); - for (i = 0; i < TOUCH_SUPPORTED; i++) - input_unregister_device(ts->cp_input_info[i].input); - kfree(ts); - return 0; -} - -static struct i2c_device_id cp_tm1217_idtable[] = { - { CPTM1217_DEVICE_NAME, 0 }, - { } -}; - -MODULE_DEVICE_TABLE(i2c, cp_tm1217_idtable); - -static struct i2c_driver cp_tm1217_driver = { - .driver = { - .owner = THIS_MODULE, - .name = CPTM1217_DRIVER_NAME, - .pm = &cp_tm1217_pm_ops, - }, - .id_table = cp_tm1217_idtable, - .probe = cp_tm1217_probe, - .remove = cp_tm1217_remove, -}; - -module_i2c_driver(cp_tm1217_driver); - -MODULE_AUTHOR("Ramesh Agarwal "); -MODULE_DESCRIPTION("Synaptics TM1217 TouchScreen Driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/cptm1217/cp_tm1217.h b/drivers/staging/cptm1217/cp_tm1217.h deleted file mode 100644 index 30bad357a05595..00000000000000 --- a/drivers/staging/cptm1217/cp_tm1217.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __LINUX_I2C_CP_TM1217_H -#define __LINUX_I2C_CP_TM1217_H - -struct cp_tm1217_platform_data { - int gpio; /* If not set uses the IRQ resource 0 */ -}; - -#endif From 091f56be10efe8ac7c09d6368d885f41fa7eb809 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Tue, 3 Feb 2015 20:08:52 -0500 Subject: [PATCH 2694/3023] ARC: Fix earlycon build breakage Commit ffb7fcd66f14 ("ARC: Dynamically determine BASE_BAUD from DeviceTree") breaks arc:defconfig build: drivers/built-in.o: In function `of_setup_earlycon': (.init.text+0xb3e): undefined reference to `arc_early_base_baud' drivers/built-in.o: In function `setup_earlycon': (.init.text+0xcd0): undefined reference to `arc_early_base_baud' make: *** [vmlinux] Error 1 BASE_BAUD is only required for earlycon, which should depend on CONFIG_SERIAL_EARLYCON. Reported-by: Guenter Roeck Tested-by: Guenter Roeck Signed-off-by: Peter Hurley Signed-off-by: Vineet Gupta --- arch/arc/kernel/devtree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c index 5036d4c069960b..e32b54abff51fd 100644 --- a/arch/arc/kernel/devtree.c +++ b/arch/arc/kernel/devtree.c @@ -17,7 +17,7 @@ #include #include -#ifdef CONFIG_SERIAL_8250_CONSOLE +#ifdef CONFIG_SERIAL_EARLYCON static unsigned int __initdata arc_base_baud; From 083500baefd5f4c215a5a93aef2492c1aa775828 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 3 Feb 2015 16:37:45 +0100 Subject: [PATCH 2695/3023] drm: remove DRM_FORMAT_NV12MT So this has been merged originally in commit 83052d4d5cd518332440bb4ee63d68bb5f744e0f Author: Seung-Woo Kim Date: Thu Dec 15 15:40:55 2011 +0900 drm: Add multi buffer plane pixel formats which hasn't seen a lot of review really. The problem is that it's not a real pixel format, but just a different way to lay out NV12 pixels in macroblocks, i.e. a tiling format. The new way of doing this is with the soon-to-be-merged fb modifiers. This was brough up in some long irc discussion around the entire topic, as an example of where things have gone wrong. Luckily we can correct the mistake: - The kms side support for NV12MT is all dead code because format_check in drm_crtc.c never accepted NV12MT. - The gem side for the gsc support doesn't look better: The code forgets to set the pixel format and makes a big mess with the tiling mode bits, inadvertedly setting them all. Conclusion: This never really worked (at least not in upstream) and hence we can safely correct our mistake here. Cc: Seung-Woo Kim Cc: Inki Dae Cc: Kyungmin Park Cc: Rob Clark Cc: Daniel Stone Cc: Damien Lespiau Reviewed-by: Rob Clark Reviewed-by: Gustavo Padovan Acked-by: Joonyoung Shim Acked-by: Seung-Woo Kim Signed-off-by: Daniel Vetter --- drivers/gpu/drm/exynos/exynos_drm_fimc.c | 14 ++------------ drivers/gpu/drm/exynos/exynos_drm_gsc.c | 6 ------ drivers/gpu/drm/exynos/exynos_drm_plane.c | 1 - drivers/gpu/drm/exynos/exynos_mixer.c | 2 -- include/uapi/drm/drm_fourcc.h | 3 --- 5 files changed, 2 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c index 835b6af0097061..842d6b8dc3c435 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c @@ -461,7 +461,6 @@ static int fimc_src_set_fmt_order(struct fimc_context *ctx, u32 fmt) cfg |= EXYNOS_MSCTRL_C_INT_IN_3PLANE; break; case DRM_FORMAT_NV12: - case DRM_FORMAT_NV12MT: case DRM_FORMAT_NV16: cfg |= (EXYNOS_MSCTRL_ORDER2P_LSB_CBCR | EXYNOS_MSCTRL_C_INT_IN_2PLANE); @@ -511,7 +510,6 @@ static int fimc_src_set_fmt(struct device *dev, u32 fmt) case DRM_FORMAT_YVU420: case DRM_FORMAT_NV12: case DRM_FORMAT_NV21: - case DRM_FORMAT_NV12MT: cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR420; break; default: @@ -524,10 +522,7 @@ static int fimc_src_set_fmt(struct device *dev, u32 fmt) cfg = fimc_read(ctx, EXYNOS_CIDMAPARAM); cfg &= ~EXYNOS_CIDMAPARAM_R_MODE_MASK; - if (fmt == DRM_FORMAT_NV12MT) - cfg |= EXYNOS_CIDMAPARAM_R_MODE_64X32; - else - cfg |= EXYNOS_CIDMAPARAM_R_MODE_LINEAR; + cfg |= EXYNOS_CIDMAPARAM_R_MODE_LINEAR; fimc_write(ctx, cfg, EXYNOS_CIDMAPARAM); @@ -812,7 +807,6 @@ static int fimc_dst_set_fmt_order(struct fimc_context *ctx, u32 fmt) cfg |= EXYNOS_CIOCTRL_YCBCR_3PLANE; break; case DRM_FORMAT_NV12: - case DRM_FORMAT_NV12MT: case DRM_FORMAT_NV16: cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR; cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE; @@ -867,7 +861,6 @@ static int fimc_dst_set_fmt(struct device *dev, u32 fmt) case DRM_FORMAT_YUV420: case DRM_FORMAT_YVU420: case DRM_FORMAT_NV12: - case DRM_FORMAT_NV12MT: case DRM_FORMAT_NV21: cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420; break; @@ -883,10 +876,7 @@ static int fimc_dst_set_fmt(struct device *dev, u32 fmt) cfg = fimc_read(ctx, EXYNOS_CIDMAPARAM); cfg &= ~EXYNOS_CIDMAPARAM_W_MODE_MASK; - if (fmt == DRM_FORMAT_NV12MT) - cfg |= EXYNOS_CIDMAPARAM_W_MODE_64X32; - else - cfg |= EXYNOS_CIDMAPARAM_W_MODE_LINEAR; + cfg |= EXYNOS_CIDMAPARAM_W_MODE_LINEAR; fimc_write(ctx, cfg, EXYNOS_CIDMAPARAM); diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c index 0261468c8019aa..8040ed2a831f9a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c @@ -542,9 +542,6 @@ static int gsc_src_set_fmt(struct device *dev, u32 fmt) cfg |= (GSC_IN_CHROMA_ORDER_CBCR | GSC_IN_YUV420_2P); break; - case DRM_FORMAT_NV12MT: - cfg |= (GSC_IN_TILE_C_16x8 | GSC_IN_TILE_MODE); - break; default: dev_err(ippdrv->dev, "inavlid target yuv order 0x%x.\n", fmt); return -EINVAL; @@ -809,9 +806,6 @@ static int gsc_dst_set_fmt(struct device *dev, u32 fmt) cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | GSC_OUT_YUV420_2P); break; - case DRM_FORMAT_NV12MT: - cfg |= (GSC_OUT_TILE_C_16x8 | GSC_OUT_TILE_MODE); - break; default: dev_err(ippdrv->dev, "inavlid target yuv order 0x%x.\n", fmt); return -EINVAL; diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index c7045a663763f2..92d75a4eabd75c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -30,7 +30,6 @@ static const uint32_t formats[] = { DRM_FORMAT_XRGB8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_NV12, - DRM_FORMAT_NV12MT, }; /* diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 820b76234ef4c5..5da28443342df2 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -417,8 +417,6 @@ static void vp_video_buffer(struct mixer_context *ctx, int win) win_data = &ctx->win_data[win]; switch (win_data->pixel_format) { - case DRM_FORMAT_NV12MT: - tiled_mode = true; case DRM_FORMAT_NV12: crcb_mode = false; buf_num = 2; diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index 646ae5f39f42a7..a284f11a8ef594 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -109,9 +109,6 @@ #define DRM_FORMAT_NV24 fourcc_code('N', 'V', '2', '4') /* non-subsampled Cr:Cb plane */ #define DRM_FORMAT_NV42 fourcc_code('N', 'V', '4', '2') /* non-subsampled Cb:Cr plane */ -/* special NV12 tiled format */ -#define DRM_FORMAT_NV12MT fourcc_code('T', 'M', '1', '2') /* 2x2 subsampled Cr:Cb plane 64x32 macroblocks */ - /* * 3 plane YCbCr * index 0: Y plane, [7:0] Y From c47689931fff5f8882a923bbd8d8590f038fa097 Mon Sep 17 00:00:00 2001 From: Cristian Stoica Date: Tue, 27 Jan 2015 11:54:27 +0200 Subject: [PATCH 2696/3023] crypto: tcrypt - fix buflen reminder calculation - This fixes the intent of the code to limit the last scatterlist to either a full PAGE or a fraction of it, depending on the number of pages needed by buflen and the available space advertised by XBUFLEN. The original code always sets the last scatterlist to a fraction of a PAGE because the first 'if' is never executed. - Rearrange the second part of the code to remove the conditional from the loop Signed-off-by: Cristian Stoica Signed-off-by: Herbert Xu --- crypto/tcrypt.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 004349576ba13a..2b2486ad26ef22 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -250,19 +250,19 @@ static void sg_init_aead(struct scatterlist *sg, char *xbuf[XBUFSIZE], int np = (buflen + PAGE_SIZE - 1)/PAGE_SIZE; int k, rem; - np = (np > XBUFSIZE) ? XBUFSIZE : np; - rem = buflen % PAGE_SIZE; if (np > XBUFSIZE) { rem = PAGE_SIZE; np = XBUFSIZE; + } else { + rem = buflen % PAGE_SIZE; } + sg_init_table(sg, np); - for (k = 0; k < np; ++k) { - if (k == (np-1)) - sg_set_buf(&sg[k], xbuf[k], rem); - else - sg_set_buf(&sg[k], xbuf[k], PAGE_SIZE); - } + np--; + for (k = 0; k < np; k++) + sg_set_buf(&sg[k], xbuf[k], PAGE_SIZE); + + sg_set_buf(&sg[k], xbuf[k], rem); } static void test_aead_speed(const char *algo, int enc, unsigned int secs, From 424a5da6919073392c11345d1b7baa9f31c62734 Mon Sep 17 00:00:00 2001 From: Cristian Stoica Date: Wed, 28 Jan 2015 11:03:05 +0200 Subject: [PATCH 2697/3023] crypto: testmgr - limit IV copy length in aead tests The working copy of IV is the same size as the transformation's IV. It is not necessary to copy more than that from the template since iv_len is usually less than MAX_IVLEN and the rest of the copied data is garbage. Signed-off-by: Cristian Stoica Signed-off-by: Herbert Xu --- crypto/testmgr.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 758d02847308bb..f4ed6d4205e713 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -429,7 +429,7 @@ static int __test_aead(struct crypto_aead *tfm, int enc, struct scatterlist *sgout; const char *e, *d; struct tcrypt_result result; - unsigned int authsize; + unsigned int authsize, iv_len; void *input; void *output; void *assoc; @@ -500,10 +500,11 @@ static int __test_aead(struct crypto_aead *tfm, int enc, memcpy(input, template[i].input, template[i].ilen); memcpy(assoc, template[i].assoc, template[i].alen); + iv_len = crypto_aead_ivsize(tfm); if (template[i].iv) - memcpy(iv, template[i].iv, MAX_IVLEN); + memcpy(iv, template[i].iv, iv_len); else - memset(iv, 0, MAX_IVLEN); + memset(iv, 0, iv_len); crypto_aead_clear_flags(tfm, ~0); if (template[i].wk) From 96692a7305c49845e3cbf5a60cfcb207c5dc4030 Mon Sep 17 00:00:00 2001 From: Cristian Stoica Date: Wed, 28 Jan 2015 13:07:32 +0200 Subject: [PATCH 2698/3023] crypto: tcrypt - do not allocate iv on stack for aead speed tests See also: 9bac019dad8098a77cce555d929f678e22111783 Signed-off-by: Cristian Stoica Signed-off-by: Herbert Xu --- crypto/tcrypt.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 2b2486ad26ef22..4b9e23fa42045d 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -280,16 +280,20 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs, struct scatterlist *sgout; const char *e; void *assoc; - char iv[MAX_IVLEN]; + char *iv; char *xbuf[XBUFSIZE]; char *xoutbuf[XBUFSIZE]; char *axbuf[XBUFSIZE]; unsigned int *b_size; unsigned int iv_len; + iv = kzalloc(MAX_IVLEN, GFP_KERNEL); + if (!iv) + return; + if (aad_size >= PAGE_SIZE) { pr_err("associate data length (%u) too big\n", aad_size); - return; + goto out_noxbuf; } if (enc == ENCRYPT) @@ -355,7 +359,7 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs, iv_len = crypto_aead_ivsize(tfm); if (iv_len) - memset(&iv, 0xff, iv_len); + memset(iv, 0xff, iv_len); crypto_aead_clear_flags(tfm, ~0); printk(KERN_INFO "test %u (%d bit key, %d byte blocks): ", @@ -408,6 +412,7 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs, out_noaxbuf: testmgr_free_buf(xbuf); out_noxbuf: + kfree(iv); return; } From 375074cc736ab1d89a708c0a8d7baa4a70d5d476 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Fri, 24 Oct 2014 15:58:07 -0700 Subject: [PATCH 2699/3023] x86: Clean up cr4 manipulation CR4 manipulation was split, seemingly at random, between direct (write_cr4) and using a helper (set/clear_in_cr4). Unfortunately, the set_in_cr4 and clear_in_cr4 helpers also poke at the boot code, which only a small subset of users actually wanted. This patch replaces all cr4 access in functions that don't leave cr4 exactly the way they found it with new helpers cr4_set_bits, cr4_clear_bits, and cr4_set_bits_and_update_boot. Signed-off-by: Andy Lutomirski Reviewed-by: Thomas Gleixner Signed-off-by: Peter Zijlstra (Intel) Cc: Andrea Arcangeli Cc: Vince Weaver Cc: "hillf.zj" Cc: Valdis Kletnieks Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Kees Cook Cc: Linus Torvalds Link: http://lkml.kernel.org/r/495a10bdc9e67016b8fd3945700d46cfd5c12c2f.1414190806.git.luto@amacapital.net Signed-off-by: Ingo Molnar --- arch/x86/include/asm/processor.h | 33 ------------------------- arch/x86/include/asm/tlbflush.h | 37 ++++++++++++++++++++++++++++ arch/x86/include/asm/virtext.h | 3 ++- arch/x86/kernel/cpu/common.c | 10 ++++---- arch/x86/kernel/cpu/mcheck/mce.c | 3 ++- arch/x86/kernel/cpu/mcheck/p5.c | 3 ++- arch/x86/kernel/cpu/mcheck/winchip.c | 3 ++- arch/x86/kernel/cpu/perf_event.c | 7 +++--- arch/x86/kernel/i387.c | 3 ++- arch/x86/kernel/process.c | 5 ++-- arch/x86/kernel/xsave.c | 3 ++- arch/x86/kvm/vmx.c | 4 +-- arch/x86/mm/init.c | 4 +-- arch/x86/xen/enlighten.c | 4 +-- drivers/lguest/x86/core.c | 5 ++-- 15 files changed, 70 insertions(+), 57 deletions(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index a092a0cce0b759..ec1c93588cefd0 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -579,39 +579,6 @@ static inline void load_sp0(struct tss_struct *tss, #define set_iopl_mask native_set_iopl_mask #endif /* CONFIG_PARAVIRT */ -/* - * Save the cr4 feature set we're using (ie - * Pentium 4MB enable and PPro Global page - * enable), so that any CPU's that boot up - * after us can get the correct flags. - */ -extern unsigned long mmu_cr4_features; -extern u32 *trampoline_cr4_features; - -static inline void set_in_cr4(unsigned long mask) -{ - unsigned long cr4; - - mmu_cr4_features |= mask; - if (trampoline_cr4_features) - *trampoline_cr4_features = mmu_cr4_features; - cr4 = read_cr4(); - cr4 |= mask; - write_cr4(cr4); -} - -static inline void clear_in_cr4(unsigned long mask) -{ - unsigned long cr4; - - mmu_cr4_features &= ~mask; - if (trampoline_cr4_features) - *trampoline_cr4_features = mmu_cr4_features; - cr4 = read_cr4(); - cr4 &= ~mask; - write_cr4(cr4); -} - typedef struct { unsigned long seg; } mm_segment_t; diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index 04905bfc508b99..fc0c4bc356ce45 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -15,6 +15,43 @@ #define __flush_tlb_single(addr) __native_flush_tlb_single(addr) #endif +/* Set in this cpu's CR4. */ +static inline void cr4_set_bits(unsigned long mask) +{ + unsigned long cr4; + + cr4 = read_cr4(); + cr4 |= mask; + write_cr4(cr4); +} + +/* Clear in this cpu's CR4. */ +static inline void cr4_clear_bits(unsigned long mask) +{ + unsigned long cr4; + + cr4 = read_cr4(); + cr4 &= ~mask; + write_cr4(cr4); +} + +/* + * Save some of cr4 feature set we're using (e.g. Pentium 4MB + * enable and PPro Global page enable), so that any CPU's that boot + * up after us can get the correct flags. This should only be used + * during boot on the boot cpu. + */ +extern unsigned long mmu_cr4_features; +extern u32 *trampoline_cr4_features; + +static inline void cr4_set_bits_and_update_boot(unsigned long mask) +{ + mmu_cr4_features |= mask; + if (trampoline_cr4_features) + *trampoline_cr4_features = mmu_cr4_features; + cr4_set_bits(mask); +} + static inline void __native_flush_tlb(void) { native_write_cr3(native_read_cr3()); diff --git a/arch/x86/include/asm/virtext.h b/arch/x86/include/asm/virtext.h index 5da71c27cc59e4..f41e19ca717b0b 100644 --- a/arch/x86/include/asm/virtext.h +++ b/arch/x86/include/asm/virtext.h @@ -19,6 +19,7 @@ #include #include +#include /* * VMX functions: @@ -40,7 +41,7 @@ static inline int cpu_has_vmx(void) static inline void cpu_vmxoff(void) { asm volatile (ASM_VMX_VMXOFF : : : "cc"); - write_cr4(read_cr4() & ~X86_CR4_VMXE); + cr4_clear_bits(X86_CR4_VMXE); } static inline int cpu_vmx_enabled(void) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index c6049650c093f7..9d8fc49f092277 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -278,7 +278,7 @@ __setup("nosmep", setup_disable_smep); static __always_inline void setup_smep(struct cpuinfo_x86 *c) { if (cpu_has(c, X86_FEATURE_SMEP)) - set_in_cr4(X86_CR4_SMEP); + cr4_set_bits(X86_CR4_SMEP); } static __init int setup_disable_smap(char *arg) @@ -298,9 +298,9 @@ static __always_inline void setup_smap(struct cpuinfo_x86 *c) if (cpu_has(c, X86_FEATURE_SMAP)) { #ifdef CONFIG_X86_SMAP - set_in_cr4(X86_CR4_SMAP); + cr4_set_bits(X86_CR4_SMAP); #else - clear_in_cr4(X86_CR4_SMAP); + cr4_clear_bits(X86_CR4_SMAP); #endif } } @@ -1312,7 +1312,7 @@ void cpu_init(void) pr_debug("Initializing CPU#%d\n", cpu); - clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); + cr4_clear_bits(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); /* * Initialize the per-CPU GDT with the boot GDT, @@ -1393,7 +1393,7 @@ void cpu_init(void) printk(KERN_INFO "Initializing CPU#%d\n", cpu); if (cpu_feature_enabled(X86_FEATURE_VME) || cpu_has_tsc || cpu_has_de) - clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); + cr4_clear_bits(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); load_current_idt(); switch_to_new_gdt(cpu); diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index d23179900755a3..15ad3ed1a3cd3f 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -44,6 +44,7 @@ #include #include +#include #include #include @@ -1449,7 +1450,7 @@ static void __mcheck_cpu_init_generic(void) bitmap_fill(all_banks, MAX_NR_BANKS); machine_check_poll(MCP_UC | m_fl, &all_banks); - set_in_cr4(X86_CR4_MCE); + cr4_set_bits(X86_CR4_MCE); rdmsrl(MSR_IA32_MCG_CAP, cap); if (cap & MCG_CTL_P) diff --git a/arch/x86/kernel/cpu/mcheck/p5.c b/arch/x86/kernel/cpu/mcheck/p5.c index ec2663a708e40d..737b0ad4e61ae2 100644 --- a/arch/x86/kernel/cpu/mcheck/p5.c +++ b/arch/x86/kernel/cpu/mcheck/p5.c @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -65,7 +66,7 @@ void intel_p5_mcheck_init(struct cpuinfo_x86 *c) "Intel old style machine check architecture supported.\n"); /* Enable MCE: */ - set_in_cr4(X86_CR4_MCE); + cr4_set_bits(X86_CR4_MCE); printk(KERN_INFO "Intel old style machine check reporting enabled on CPU#%d.\n", smp_processor_id()); diff --git a/arch/x86/kernel/cpu/mcheck/winchip.c b/arch/x86/kernel/cpu/mcheck/winchip.c index bd5d46a32210a1..44f138296fbebd 100644 --- a/arch/x86/kernel/cpu/mcheck/winchip.c +++ b/arch/x86/kernel/cpu/mcheck/winchip.c @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -36,7 +37,7 @@ void winchip_mcheck_init(struct cpuinfo_x86 *c) lo &= ~(1<<4); /* Enable MCE */ wrmsr(MSR_IDT_FCR1, lo, hi); - set_in_cr4(X86_CR4_MCE); + cr4_set_bits(X86_CR4_MCE); printk(KERN_INFO "Winchip machine check reporting enabled on CPU#0.\n"); diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 143e5f5dc8551b..6b5acd5f4a34a1 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -1328,7 +1329,7 @@ x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) case CPU_STARTING: if (x86_pmu.attr_rdpmc) - set_in_cr4(X86_CR4_PCE); + cr4_set_bits(X86_CR4_PCE); if (x86_pmu.cpu_starting) x86_pmu.cpu_starting(cpu); break; @@ -1834,9 +1835,9 @@ static void change_rdpmc(void *info) bool enable = !!(unsigned long)info; if (enable) - set_in_cr4(X86_CR4_PCE); + cr4_set_bits(X86_CR4_PCE); else - clear_in_cr4(X86_CR4_PCE); + cr4_clear_bits(X86_CR4_PCE); } static ssize_t set_attr_rdpmc(struct device *cdev, diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index a9a4229f6161b2..87727b03196da5 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -180,7 +181,7 @@ void fpu_init(void) if (cpu_has_xmm) cr4_mask |= X86_CR4_OSXMMEXCPT; if (cr4_mask) - set_in_cr4(cr4_mask); + cr4_set_bits(cr4_mask); cr0 = read_cr0(); cr0 &= ~(X86_CR0_TS|X86_CR0_EM); /* clear TS and EM */ diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index e127ddaa2d5ad3..046e2d620bbe7b 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -28,6 +28,7 @@ #include #include #include +#include /* * per-CPU TSS segments. Threads are completely 'soft' on Linux, @@ -141,7 +142,7 @@ void flush_thread(void) static void hard_disable_TSC(void) { - write_cr4(read_cr4() | X86_CR4_TSD); + cr4_set_bits(X86_CR4_TSD); } void disable_TSC(void) @@ -158,7 +159,7 @@ void disable_TSC(void) static void hard_enable_TSC(void) { - write_cr4(read_cr4() & ~X86_CR4_TSD); + cr4_clear_bits(X86_CR4_TSD); } static void enable_TSC(void) diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 0de1fae2bdf000..34f66e58a89669 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -12,6 +12,7 @@ #include #include #include +#include #include /* @@ -453,7 +454,7 @@ static void prepare_fx_sw_frame(void) */ static inline void xstate_enable(void) { - set_in_cr4(X86_CR4_OSXSAVE); + cr4_set_bits(X86_CR4_OSXSAVE); xsetbv(XCR_XFEATURE_ENABLED_MASK, pcntxt_mask); } diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index d4c58d884838d1..db77537013d1c2 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -2812,7 +2812,7 @@ static int hardware_enable(void) /* enable and lock */ wrmsrl(MSR_IA32_FEATURE_CONTROL, old | test_bits); } - write_cr4(read_cr4() | X86_CR4_VMXE); /* FIXME: not cpu hotplug safe */ + cr4_set_bits(X86_CR4_VMXE); if (vmm_exclusive) { kvm_cpu_vmxon(phys_addr); @@ -2849,7 +2849,7 @@ static void hardware_disable(void) vmclear_local_loaded_vmcss(); kvm_cpu_vmxoff(); } - write_cr4(read_cr4() & ~X86_CR4_VMXE); + cr4_clear_bits(X86_CR4_VMXE); } static __init int adjust_vmx_controls(u32 ctl_min, u32 ctl_opt, diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 079c3b6a3ff181..d4eddbd92c287c 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -173,11 +173,11 @@ static void __init probe_page_size_mask(void) /* Enable PSE if available */ if (cpu_has_pse) - set_in_cr4(X86_CR4_PSE); + cr4_set_bits_and_update_boot(X86_CR4_PSE); /* Enable PGE if available */ if (cpu_has_pge) { - set_in_cr4(X86_CR4_PGE); + cr4_set_bits_and_update_boot(X86_CR4_PGE); __supported_pte_mask |= _PAGE_GLOBAL; } } diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 78a881b7fc415e..bd8b8459c3d059 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1494,10 +1494,10 @@ static void xen_pvh_set_cr_flags(int cpu) * set them here. For all, OSFXSR OSXMMEXCPT are set in fpu_init. */ if (cpu_has_pse) - set_in_cr4(X86_CR4_PSE); + cr4_set_bits_and_update_boot(X86_CR4_PSE); if (cpu_has_pge) - set_in_cr4(X86_CR4_PGE); + cr4_set_bits_and_update_boot(X86_CR4_PGE); } /* diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index 922a1acbf652b9..6adfd7ba4c9774 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c @@ -47,6 +47,7 @@ #include #include #include +#include #include "../lg.h" static int cpu_had_pge; @@ -452,9 +453,9 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu) static void adjust_pge(void *on) { if (on) - write_cr4(read_cr4() | X86_CR4_PGE); + cr4_set_bits(X86_CR4_PGE); else - write_cr4(read_cr4() & ~X86_CR4_PGE); + cr4_clear_bits(X86_CR4_PGE); } /*H:020 From 1e02ce4cccdcb9688386e5b8d2c9fa4660b45389 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Fri, 24 Oct 2014 15:58:08 -0700 Subject: [PATCH 2700/3023] x86: Store a per-cpu shadow copy of CR4 Context switches and TLB flushes can change individual bits of CR4. CR4 reads take several cycles, so store a shadow copy of CR4 in a per-cpu variable. To avoid wasting a cache line, I added the CR4 shadow to cpu_tlbstate, which is already touched in switch_mm. The heaviest users of the cr4 shadow will be switch_mm and __switch_to_xtra, and __switch_to_xtra is called shortly after switch_mm during context switch, so the cacheline is likely to be hot. Signed-off-by: Andy Lutomirski Reviewed-by: Thomas Gleixner Signed-off-by: Peter Zijlstra (Intel) Cc: Kees Cook Cc: Andrea Arcangeli Cc: Vince Weaver Cc: "hillf.zj" Cc: Valdis Kletnieks Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Linus Torvalds Link: http://lkml.kernel.org/r/3a54dd3353fffbf84804398e00dfdc5b7c1afd7d.1414190806.git.luto@amacapital.net Signed-off-by: Ingo Molnar --- arch/x86/include/asm/paravirt.h | 6 ++-- arch/x86/include/asm/special_insns.h | 6 ++-- arch/x86/include/asm/tlbflush.h | 52 +++++++++++++++++++++------- arch/x86/include/asm/virtext.h | 2 +- arch/x86/kernel/acpi/sleep.c | 2 +- arch/x86/kernel/cpu/common.c | 7 ++++ arch/x86/kernel/cpu/mtrr/cyrix.c | 6 ++-- arch/x86/kernel/cpu/mtrr/generic.c | 6 ++-- arch/x86/kernel/head32.c | 1 + arch/x86/kernel/head64.c | 2 ++ arch/x86/kernel/process_32.c | 2 +- arch/x86/kernel/process_64.c | 2 +- arch/x86/kernel/setup.c | 2 +- arch/x86/kvm/svm.c | 2 +- arch/x86/kvm/vmx.c | 6 ++-- arch/x86/mm/fault.c | 2 +- arch/x86/mm/init.c | 9 +++++ arch/x86/mm/tlb.c | 3 -- arch/x86/power/cpu.c | 11 +++--- arch/x86/realmode/init.c | 2 +- 20 files changed, 85 insertions(+), 46 deletions(-) diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 32444ae939ca90..965c47d254aa0f 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -80,16 +80,16 @@ static inline void write_cr3(unsigned long x) PVOP_VCALL1(pv_mmu_ops.write_cr3, x); } -static inline unsigned long read_cr4(void) +static inline unsigned long __read_cr4(void) { return PVOP_CALL0(unsigned long, pv_cpu_ops.read_cr4); } -static inline unsigned long read_cr4_safe(void) +static inline unsigned long __read_cr4_safe(void) { return PVOP_CALL0(unsigned long, pv_cpu_ops.read_cr4_safe); } -static inline void write_cr4(unsigned long x) +static inline void __write_cr4(unsigned long x) { PVOP_VCALL1(pv_cpu_ops.write_cr4, x); } diff --git a/arch/x86/include/asm/special_insns.h b/arch/x86/include/asm/special_insns.h index e820c080a4e99e..6a4b00fafb003c 100644 --- a/arch/x86/include/asm/special_insns.h +++ b/arch/x86/include/asm/special_insns.h @@ -137,17 +137,17 @@ static inline void write_cr3(unsigned long x) native_write_cr3(x); } -static inline unsigned long read_cr4(void) +static inline unsigned long __read_cr4(void) { return native_read_cr4(); } -static inline unsigned long read_cr4_safe(void) +static inline unsigned long __read_cr4_safe(void) { return native_read_cr4_safe(); } -static inline void write_cr4(unsigned long x) +static inline void __write_cr4(unsigned long x) { native_write_cr4(x); } diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index fc0c4bc356ce45..cd791948b286a1 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -15,14 +15,37 @@ #define __flush_tlb_single(addr) __native_flush_tlb_single(addr) #endif +struct tlb_state { +#ifdef CONFIG_SMP + struct mm_struct *active_mm; + int state; +#endif + + /* + * Access to this CR4 shadow and to H/W CR4 is protected by + * disabling interrupts when modifying either one. + */ + unsigned long cr4; +}; +DECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate); + +/* Initialize cr4 shadow for this CPU. */ +static inline void cr4_init_shadow(void) +{ + this_cpu_write(cpu_tlbstate.cr4, __read_cr4()); +} + /* Set in this cpu's CR4. */ static inline void cr4_set_bits(unsigned long mask) { unsigned long cr4; - cr4 = read_cr4(); - cr4 |= mask; - write_cr4(cr4); + cr4 = this_cpu_read(cpu_tlbstate.cr4); + if ((cr4 | mask) != cr4) { + cr4 |= mask; + this_cpu_write(cpu_tlbstate.cr4, cr4); + __write_cr4(cr4); + } } /* Clear in this cpu's CR4. */ @@ -30,9 +53,18 @@ static inline void cr4_clear_bits(unsigned long mask) { unsigned long cr4; - cr4 = read_cr4(); - cr4 &= ~mask; - write_cr4(cr4); + cr4 = this_cpu_read(cpu_tlbstate.cr4); + if ((cr4 & ~mask) != cr4) { + cr4 &= ~mask; + this_cpu_write(cpu_tlbstate.cr4, cr4); + __write_cr4(cr4); + } +} + +/* Read the CR4 shadow. */ +static inline unsigned long cr4_read_shadow(void) +{ + return this_cpu_read(cpu_tlbstate.cr4); } /* @@ -61,7 +93,7 @@ static inline void __native_flush_tlb_global_irq_disabled(void) { unsigned long cr4; - cr4 = native_read_cr4(); + cr4 = this_cpu_read(cpu_tlbstate.cr4); /* clear PGE */ native_write_cr4(cr4 & ~X86_CR4_PGE); /* write old PGE again and flush TLBs */ @@ -221,12 +253,6 @@ void native_flush_tlb_others(const struct cpumask *cpumask, #define TLBSTATE_OK 1 #define TLBSTATE_LAZY 2 -struct tlb_state { - struct mm_struct *active_mm; - int state; -}; -DECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate); - static inline void reset_lazy_tlbstate(void) { this_cpu_write(cpu_tlbstate.state, 0); diff --git a/arch/x86/include/asm/virtext.h b/arch/x86/include/asm/virtext.h index f41e19ca717b0b..cce9ee68e335f8 100644 --- a/arch/x86/include/asm/virtext.h +++ b/arch/x86/include/asm/virtext.h @@ -46,7 +46,7 @@ static inline void cpu_vmxoff(void) static inline int cpu_vmx_enabled(void) { - return read_cr4() & X86_CR4_VMXE; + return __read_cr4() & X86_CR4_VMXE; } /** Disable VMX if it is enabled on the current CPU diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 31368207837c2f..d1daead5fcddd5 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -78,7 +78,7 @@ int x86_acpi_suspend_lowlevel(void) header->pmode_cr0 = read_cr0(); if (__this_cpu_read(cpu_info.cpuid_level) >= 0) { - header->pmode_cr4 = read_cr4(); + header->pmode_cr4 = __read_cr4(); header->pmode_behavior |= (1 << WAKEUP_BEHAVIOR_RESTORE_CR4); } if (!rdmsr_safe(MSR_IA32_MISC_ENABLE, diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 9d8fc49f092277..07f2fc3c13a4d6 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -1293,6 +1294,12 @@ void cpu_init(void) wait_for_master_cpu(cpu); + /* + * Initialize the CR4 shadow before doing anything that could + * try to read it. + */ + cr4_init_shadow(); + /* * Load microcode on this cpu if a valid microcode is available. * This is early microcode loading procedure. diff --git a/arch/x86/kernel/cpu/mtrr/cyrix.c b/arch/x86/kernel/cpu/mtrr/cyrix.c index 9e451b0876b513..f8c81ba0b4651c 100644 --- a/arch/x86/kernel/cpu/mtrr/cyrix.c +++ b/arch/x86/kernel/cpu/mtrr/cyrix.c @@ -138,8 +138,8 @@ static void prepare_set(void) /* Save value of CR4 and clear Page Global Enable (bit 7) */ if (cpu_has_pge) { - cr4 = read_cr4(); - write_cr4(cr4 & ~X86_CR4_PGE); + cr4 = __read_cr4(); + __write_cr4(cr4 & ~X86_CR4_PGE); } /* @@ -171,7 +171,7 @@ static void post_set(void) /* Restore value of CR4 */ if (cpu_has_pge) - write_cr4(cr4); + __write_cr4(cr4); } static void cyrix_set_arr(unsigned int reg, unsigned long base, diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index 0e25a1bc5ab5cf..7d74f7b3c6ba49 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c @@ -678,8 +678,8 @@ static void prepare_set(void) __acquires(set_atomicity_lock) /* Save value of CR4 and clear Page Global Enable (bit 7) */ if (cpu_has_pge) { - cr4 = read_cr4(); - write_cr4(cr4 & ~X86_CR4_PGE); + cr4 = __read_cr4(); + __write_cr4(cr4 & ~X86_CR4_PGE); } /* Flush all TLBs via a mov %cr3, %reg; mov %reg, %cr3 */ @@ -708,7 +708,7 @@ static void post_set(void) __releases(set_atomicity_lock) /* Restore value of CR4 */ if (cpu_has_pge) - write_cr4(cr4); + __write_cr4(cr4); raw_spin_unlock(&set_atomicity_lock); } diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c index d6c1b983699576..2911ef3a9f1c7b 100644 --- a/arch/x86/kernel/head32.c +++ b/arch/x86/kernel/head32.c @@ -31,6 +31,7 @@ static void __init i386_default_early_setup(void) asmlinkage __visible void __init i386_start_kernel(void) { + cr4_init_shadow(); sanitize_boot_params(&boot_params); /* Call the subarch specific early setup function */ diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index eda1a865641e2e..3b241f0ca005fc 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -155,6 +155,8 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data) (__START_KERNEL & PGDIR_MASK))); BUILD_BUG_ON(__fix_to_virt(__end_of_fixed_addresses) <= MODULES_END); + cr4_init_shadow(); + /* Kill off the identity-map trampoline */ reset_early_page_tables(); diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 8f3ebfe710d071..603c4f99cb5a17 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -101,7 +101,7 @@ void __show_regs(struct pt_regs *regs, int all) cr0 = read_cr0(); cr2 = read_cr2(); cr3 = read_cr3(); - cr4 = read_cr4_safe(); + cr4 = __read_cr4_safe(); printk(KERN_DEFAULT "CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4); diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 5a2c02913af3bd..67fcc43577d279 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -93,7 +93,7 @@ void __show_regs(struct pt_regs *regs, int all) cr0 = read_cr0(); cr2 = read_cr2(); cr3 = read_cr3(); - cr4 = read_cr4(); + cr4 = __read_cr4(); printk(KERN_DEFAULT "FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", fs, fsindex, gs, gsindex, shadowgs); diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index ab4734e5411d76..04e6c62f1a9386 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -1178,7 +1178,7 @@ void __init setup_arch(char **cmdline_p) if (boot_cpu_data.cpuid_level >= 0) { /* A CPU has %cr4 if and only if it has CPUID */ - mmu_cr4_features = read_cr4(); + mmu_cr4_features = __read_cr4(); if (trampoline_cr4_features) *trampoline_cr4_features = mmu_cr4_features; } diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 41dd0387cccb63..496a54839968e4 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -1583,7 +1583,7 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) static int svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) { - unsigned long host_cr4_mce = read_cr4() & X86_CR4_MCE; + unsigned long host_cr4_mce = cr4_read_shadow() & X86_CR4_MCE; unsigned long old_cr4 = to_svm(vcpu)->vmcb->save.cr4; if (cr4 & X86_CR4_VMXE) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index db77537013d1c2..8dca6ccbb9cefc 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -2785,7 +2785,7 @@ static int hardware_enable(void) u64 phys_addr = __pa(per_cpu(vmxarea, cpu)); u64 old, test_bits; - if (read_cr4() & X86_CR4_VMXE) + if (cr4_read_shadow() & X86_CR4_VMXE) return -EBUSY; INIT_LIST_HEAD(&per_cpu(loaded_vmcss_on_cpu, cpu)); @@ -4255,7 +4255,7 @@ static void vmx_set_constant_host_state(struct vcpu_vmx *vmx) vmcs_writel(HOST_CR3, read_cr3()); /* 22.2.3 FIXME: shadow tables */ /* Save the most likely value for this task's CR4 in the VMCS. */ - cr4 = read_cr4(); + cr4 = cr4_read_shadow(); vmcs_writel(HOST_CR4, cr4); /* 22.2.3, 22.2.5 */ vmx->host_state.vmcs_host_cr4 = cr4; @@ -7784,7 +7784,7 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) if (test_bit(VCPU_REGS_RIP, (unsigned long *)&vcpu->arch.regs_dirty)) vmcs_writel(GUEST_RIP, vcpu->arch.regs[VCPU_REGS_RIP]); - cr4 = read_cr4(); + cr4 = cr4_read_shadow(); if (unlikely(cr4 != vmx->host_state.vmcs_host_cr4)) { vmcs_writel(HOST_CR4, cr4); vmx->host_state.vmcs_host_cr4 = cr4; diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index e3ff27a5b6348f..ede025fb46f137 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -600,7 +600,7 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code, printk(nx_warning, from_kuid(&init_user_ns, current_uid())); if (pte && pte_present(*pte) && pte_exec(*pte) && (pgd_flags(*pgd) & _PAGE_USER) && - (read_cr4() & X86_CR4_SMEP)) + (__read_cr4() & X86_CR4_SMEP)) printk(smep_warning, from_kuid(&init_user_ns, current_uid())); } diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index d4eddbd92c287c..a74aa0fd185332 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -713,6 +713,15 @@ void __init zone_sizes_init(void) free_area_init_nodes(max_zone_pfns); } +DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) = { +#ifdef CONFIG_SMP + .active_mm = &init_mm, + .state = 0, +#endif + .cr4 = ~0UL, /* fail hard if we screw up cr4 shadow initialization */ +}; +EXPORT_SYMBOL_GPL(cpu_tlbstate); + void update_cache_mode_entry(unsigned entry, enum page_cache_mode cache) { /* entry 0 MUST be WB (hardwired to speed up translations) */ diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index ee61c36d64f84d..3250f2371aea5c 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -14,9 +14,6 @@ #include #include -DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) - = { &init_mm, 0, }; - /* * Smarter SMP flushing macros. * c/o Linus Torvalds. diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c index 6ec7910f59bfe2..3e32ed5648a038 100644 --- a/arch/x86/power/cpu.c +++ b/arch/x86/power/cpu.c @@ -105,11 +105,8 @@ static void __save_processor_state(struct saved_context *ctxt) ctxt->cr0 = read_cr0(); ctxt->cr2 = read_cr2(); ctxt->cr3 = read_cr3(); -#ifdef CONFIG_X86_32 - ctxt->cr4 = read_cr4_safe(); -#else -/* CONFIG_X86_64 */ - ctxt->cr4 = read_cr4(); + ctxt->cr4 = __read_cr4_safe(); +#ifdef CONFIG_X86_64 ctxt->cr8 = read_cr8(); #endif ctxt->misc_enable_saved = !rdmsrl_safe(MSR_IA32_MISC_ENABLE, @@ -175,12 +172,12 @@ static void notrace __restore_processor_state(struct saved_context *ctxt) /* cr4 was introduced in the Pentium CPU */ #ifdef CONFIG_X86_32 if (ctxt->cr4) - write_cr4(ctxt->cr4); + __write_cr4(ctxt->cr4); #else /* CONFIG X86_64 */ wrmsrl(MSR_EFER, ctxt->efer); write_cr8(ctxt->cr8); - write_cr4(ctxt->cr4); + __write_cr4(ctxt->cr4); #endif write_cr3(ctxt->cr3); write_cr2(ctxt->cr2); diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c index bad628a620c4ef..0b7a63d9844038 100644 --- a/arch/x86/realmode/init.c +++ b/arch/x86/realmode/init.c @@ -81,7 +81,7 @@ void __init setup_real_mode(void) trampoline_header->start = (u64) secondary_startup_64; trampoline_cr4_features = &trampoline_header->cr4; - *trampoline_cr4_features = read_cr4(); + *trampoline_cr4_features = __read_cr4(); trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd); trampoline_pgd[0] = init_level4_pgt[pgd_index(__PAGE_OFFSET)].pgd; From 22c4bd9fa921c2b1b3f2420d7b9dabbe982f3059 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Fri, 24 Oct 2014 15:58:09 -0700 Subject: [PATCH 2701/3023] x86: Add a comment clarifying LDT context switching The code is correct, but only for a rather subtle reason. This confused me for quite a while when I read switch_mm, so clarify the code to avoid confusing other people, too. TBH, I wouldn't be surprised if this code was only correct by accident. Signed-off-by: Andy Lutomirski Reviewed-by: Thomas Gleixner Signed-off-by: Peter Zijlstra (Intel) Cc: Kees Cook Cc: Andrea Arcangeli Cc: Vince Weaver Cc: "hillf.zj" Cc: Valdis Kletnieks Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Linus Torvalds Link: http://lkml.kernel.org/r/0db86397f968996fb772c443c251415b0b430ddd.1414190806.git.luto@amacapital.net Signed-off-by: Ingo Molnar --- arch/x86/include/asm/mmu_context.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h index 4b75d591eb5ed1..52c18359f1dcaf 100644 --- a/arch/x86/include/asm/mmu_context.h +++ b/arch/x86/include/asm/mmu_context.h @@ -55,12 +55,14 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, /* * Load the LDT, if the LDT is different. * - * It's possible leave_mm(prev) has been called. If so, - * then prev->context.ldt could be out of sync with the - * LDT descriptor or the LDT register. This can only happen - * if prev->context.ldt is non-null, since we never free - * an LDT. But LDTs can't be shared across mms, so - * prev->context.ldt won't be equal to next->context.ldt. + * It's possible that prev->context.ldt doesn't match + * the LDT register. This can happen if leave_mm(prev) + * was called and then modify_ldt changed + * prev->context.ldt but suppressed an IPI to this CPU. + * In this case, prev->context.ldt != NULL, because we + * never free an LDT while the mm still exists. That + * means that next->context.ldt != prev->context.ldt, + * because mms never share an LDT. */ if (unlikely(prev->context.ldt != next->context.ldt)) load_LDT_nolock(&next->context); From 1e0fb9ec679c9273a641f1d6f3d25ea47baef2bb Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Fri, 24 Oct 2014 15:58:10 -0700 Subject: [PATCH 2702/3023] perf: Add pmu callbacks to track event mapping and unmapping Signed-off-by: Andy Lutomirski Signed-off-by: Peter Zijlstra (Intel) Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Kees Cook Cc: Andrea Arcangeli Cc: Vince Weaver Cc: "hillf.zj" Cc: Valdis Kletnieks Cc: Linus Torvalds Link: http://lkml.kernel.org/r/266afcba1d1f91ea5501e4e16e94bbbc1a9339b6.1414190806.git.luto@amacapital.net Signed-off-by: Ingo Molnar --- include/linux/perf_event.h | 7 +++++++ kernel/events/core.c | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 5cad0e6f35524b..33262004c31041 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -202,6 +202,13 @@ struct pmu { */ int (*event_init) (struct perf_event *event); + /* + * Notification that the event was mapped or unmapped. Called + * in the context of the mapping task. + */ + void (*event_mapped) (struct perf_event *event); /*optional*/ + void (*event_unmapped) (struct perf_event *event); /*optional*/ + #define PERF_EF_START 0x01 /* start the counter when adding */ #define PERF_EF_RELOAD 0x02 /* reload the counter when starting */ #define PERF_EF_UPDATE 0x04 /* update the counter when stopping */ diff --git a/kernel/events/core.c b/kernel/events/core.c index 7f2fbb8b5069b3..cc1487145d33e2 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -4293,6 +4293,9 @@ static void perf_mmap_open(struct vm_area_struct *vma) atomic_inc(&event->mmap_count); atomic_inc(&event->rb->mmap_count); + + if (event->pmu->event_mapped) + event->pmu->event_mapped(event); } /* @@ -4312,6 +4315,9 @@ static void perf_mmap_close(struct vm_area_struct *vma) int mmap_locked = rb->mmap_locked; unsigned long size = perf_data_size(rb); + if (event->pmu->event_unmapped) + event->pmu->event_unmapped(event); + atomic_dec(&rb->mmap_count); if (!atomic_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex)) @@ -4513,6 +4519,9 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma) vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP; vma->vm_ops = &perf_mmap_vmops; + if (event->pmu->event_mapped) + event->pmu->event_mapped(event); + return ret; } From c1317ec2b906442930318d9d6e51425c5a69e9cb Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Fri, 24 Oct 2014 15:58:11 -0700 Subject: [PATCH 2703/3023] perf: Pass the event to arch_perf_update_userpage() Signed-off-by: Andy Lutomirski Signed-off-by: Peter Zijlstra (Intel) Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Kees Cook Cc: Andrea Arcangeli Cc: Vince Weaver Cc: "hillf.zj" Cc: Valdis Kletnieks Cc: Linus Torvalds Link: http://lkml.kernel.org/r/0fea9a7fac3c1eea86cb0a5954184e74f4213666.1414190806.git.luto@amacapital.net Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event.c | 3 ++- kernel/events/core.c | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 6b5acd5f4a34a1..73e84a348de10f 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1915,7 +1915,8 @@ static struct pmu pmu = { .flush_branch_stack = x86_pmu_flush_branch_stack, }; -void arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now) +void arch_perf_update_userpage(struct perf_event *event, + struct perf_event_mmap_page *userpg, u64 now) { struct cyc2ns_data *data; diff --git a/kernel/events/core.c b/kernel/events/core.c index cc1487145d33e2..13209a90b751d1 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -4101,7 +4101,8 @@ static void perf_event_init_userpage(struct perf_event *event) rcu_read_unlock(); } -void __weak arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now) +void __weak arch_perf_update_userpage( + struct perf_event *event, struct perf_event_mmap_page *userpg, u64 now) { } @@ -4151,7 +4152,7 @@ void perf_event_update_userpage(struct perf_event *event) userpg->time_running = running + atomic64_read(&event->child_total_time_running); - arch_perf_update_userpage(userpg, now); + arch_perf_update_userpage(event, userpg, now); barrier(); ++userpg->lock; From 7911d3f7af14a614617e38245fedf98a724e46a9 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Fri, 24 Oct 2014 15:58:12 -0700 Subject: [PATCH 2704/3023] perf/x86: Only allow rdpmc if a perf_event is mapped We currently allow any process to use rdpmc. This significantly weakens the protection offered by PR_TSC_DISABLED, and it could be helpful to users attempting to exploit timing attacks. Since we can't enable access to individual counters, use a very coarse heuristic to limit access to rdpmc: allow access only when a perf_event is mmapped. This protects seccomp sandboxes. There is plenty of room to further tighen these restrictions. For example, this allows rdpmc for any x86_pmu event, but it's only useful for self-monitoring tasks. As a side effect, cap_user_rdpmc will now be false for AMD uncore events. This isn't a real regression, since .event_idx is disabled for these events anyway for the time being. Whenever that gets re-added, the cap_user_rdpmc code can be adjusted or refactored accordingly. Signed-off-by: Andy Lutomirski Signed-off-by: Peter Zijlstra (Intel) Cc: Arnaldo Carvalho de Melo Cc: Kees Cook Cc: Andrea Arcangeli Cc: Vince Weaver Cc: "hillf.zj" Cc: Valdis Kletnieks Cc: Linus Torvalds Link: http://lkml.kernel.org/r/a2bdb3cf3a1d70c26980d7c6dddfbaa69f3182bf.1414190806.git.luto@amacapital.net Signed-off-by: Ingo Molnar --- arch/x86/include/asm/mmu.h | 2 ++ arch/x86/include/asm/mmu_context.h | 16 +++++++++ arch/x86/kernel/cpu/perf_event.c | 57 ++++++++++++++++++++---------- arch/x86/kernel/cpu/perf_event.h | 2 ++ 4 files changed, 58 insertions(+), 19 deletions(-) diff --git a/arch/x86/include/asm/mmu.h b/arch/x86/include/asm/mmu.h index 876e74e8eec766..09b9620a73b484 100644 --- a/arch/x86/include/asm/mmu.h +++ b/arch/x86/include/asm/mmu.h @@ -19,6 +19,8 @@ typedef struct { struct mutex lock; void __user *vdso; + + atomic_t perf_rdpmc_allowed; /* nonzero if rdpmc is allowed */ } mm_context_t; #ifdef CONFIG_SMP diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h index 52c18359f1dcaf..89c1fece224e78 100644 --- a/arch/x86/include/asm/mmu_context.h +++ b/arch/x86/include/asm/mmu_context.h @@ -18,6 +18,18 @@ static inline void paravirt_activate_mm(struct mm_struct *prev, } #endif /* !CONFIG_PARAVIRT */ +#ifdef CONFIG_PERF_EVENTS +static inline void load_mm_cr4(struct mm_struct *mm) +{ + if (atomic_read(&mm->context.perf_rdpmc_allowed)) + cr4_set_bits(X86_CR4_PCE); + else + cr4_clear_bits(X86_CR4_PCE); +} +#else +static inline void load_mm_cr4(struct mm_struct *mm) {} +#endif + /* * Used for LDT copy/destruction. */ @@ -52,6 +64,9 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, /* Stop flush ipis for the previous mm */ cpumask_clear_cpu(cpu, mm_cpumask(prev)); + /* Load per-mm CR4 state */ + load_mm_cr4(next); + /* * Load the LDT, if the LDT is different. * @@ -87,6 +102,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, */ load_cr3(next->pgd); trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL); + load_mm_cr4(next); load_LDT_nolock(&next->context); } } diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 73e84a348de10f..bec5cff7dc8082 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -1328,8 +1329,6 @@ x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) break; case CPU_STARTING: - if (x86_pmu.attr_rdpmc) - cr4_set_bits(X86_CR4_PCE); if (x86_pmu.cpu_starting) x86_pmu.cpu_starting(cpu); break; @@ -1805,14 +1804,44 @@ static int x86_pmu_event_init(struct perf_event *event) event->destroy(event); } + if (ACCESS_ONCE(x86_pmu.attr_rdpmc)) + event->hw.flags |= PERF_X86_EVENT_RDPMC_ALLOWED; + return err; } +static void refresh_pce(void *ignored) +{ + if (current->mm) + load_mm_cr4(current->mm); +} + +static void x86_pmu_event_mapped(struct perf_event *event) +{ + if (!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED)) + return; + + if (atomic_inc_return(¤t->mm->context.perf_rdpmc_allowed) == 1) + on_each_cpu_mask(mm_cpumask(current->mm), refresh_pce, NULL, 1); +} + +static void x86_pmu_event_unmapped(struct perf_event *event) +{ + if (!current->mm) + return; + + if (!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED)) + return; + + if (atomic_dec_and_test(¤t->mm->context.perf_rdpmc_allowed)) + on_each_cpu_mask(mm_cpumask(current->mm), refresh_pce, NULL, 1); +} + static int x86_pmu_event_idx(struct perf_event *event) { int idx = event->hw.idx; - if (!x86_pmu.attr_rdpmc) + if (!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED)) return 0; if (x86_pmu.num_counters_fixed && idx >= INTEL_PMC_IDX_FIXED) { @@ -1830,16 +1859,6 @@ static ssize_t get_attr_rdpmc(struct device *cdev, return snprintf(buf, 40, "%d\n", x86_pmu.attr_rdpmc); } -static void change_rdpmc(void *info) -{ - bool enable = !!(unsigned long)info; - - if (enable) - cr4_set_bits(X86_CR4_PCE); - else - cr4_clear_bits(X86_CR4_PCE); -} - static ssize_t set_attr_rdpmc(struct device *cdev, struct device_attribute *attr, const char *buf, size_t count) @@ -1854,11 +1873,7 @@ static ssize_t set_attr_rdpmc(struct device *cdev, if (x86_pmu.attr_rdpmc_broken) return -ENOTSUPP; - if (!!val != !!x86_pmu.attr_rdpmc) { - x86_pmu.attr_rdpmc = !!val; - on_each_cpu(change_rdpmc, (void *)val, 1); - } - + x86_pmu.attr_rdpmc = !!val; return count; } @@ -1901,6 +1916,9 @@ static struct pmu pmu = { .event_init = x86_pmu_event_init, + .event_mapped = x86_pmu_event_mapped, + .event_unmapped = x86_pmu_event_unmapped, + .add = x86_pmu_add, .del = x86_pmu_del, .start = x86_pmu_start, @@ -1922,7 +1940,8 @@ void arch_perf_update_userpage(struct perf_event *event, userpg->cap_user_time = 0; userpg->cap_user_time_zero = 0; - userpg->cap_user_rdpmc = x86_pmu.attr_rdpmc; + userpg->cap_user_rdpmc = + !!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED); userpg->pmc_width = x86_pmu.cntval_bits; if (!sched_clock_stable()) diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index 4e6cdb0ddc70c8..df525d2be1e814 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h @@ -71,6 +71,8 @@ struct event_constraint { #define PERF_X86_EVENT_COMMITTED 0x8 /* event passed commit_txn */ #define PERF_X86_EVENT_PEBS_LD_HSW 0x10 /* haswell style datala, load */ #define PERF_X86_EVENT_PEBS_NA_HSW 0x20 /* haswell style datala, unknown */ +#define PERF_X86_EVENT_RDPMC_ALLOWED 0x40 /* grant rdpmc permission */ + struct amd_nb { int nb_id; /* NorthBridge id */ From a66734297f78707ce39d756b656bfae861d53f62 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Fri, 24 Oct 2014 15:58:13 -0700 Subject: [PATCH 2705/3023] perf/x86: Add /sys/devices/cpu/rdpmc=2 to allow rdpmc for all tasks While perfmon2 is a sufficiently evil library (it pokes MSRs directly) that breaking it is fair game, it's still useful, so we might as well try to support it. This allows users to write 2 to /sys/devices/cpu/rdpmc to disable all rdpmc protection so that hack like perfmon2 can continue to work. At some point, if perf_event becomes fast enough to replace perfmon2, then this can go. Signed-off-by: Andy Lutomirski Signed-off-by: Peter Zijlstra (Intel) Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Kees Cook Cc: Andrea Arcangeli Cc: Vince Weaver Cc: "hillf.zj" Cc: Valdis Kletnieks Cc: Linus Torvalds Link: http://lkml.kernel.org/r/caac3c1c707dcca48ecbc35f4def21495856f479.1414190806.git.luto@amacapital.net Signed-off-by: Ingo Molnar --- arch/x86/include/asm/mmu_context.h | 5 ++++- arch/x86/kernel/cpu/perf_event.c | 21 ++++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h index 89c1fece224e78..883f6b933fa4b6 100644 --- a/arch/x86/include/asm/mmu_context.h +++ b/arch/x86/include/asm/mmu_context.h @@ -19,9 +19,12 @@ static inline void paravirt_activate_mm(struct mm_struct *prev, #endif /* !CONFIG_PARAVIRT */ #ifdef CONFIG_PERF_EVENTS +extern struct static_key rdpmc_always_available; + static inline void load_mm_cr4(struct mm_struct *mm) { - if (atomic_read(&mm->context.perf_rdpmc_allowed)) + if (static_key_true(&rdpmc_always_available) || + atomic_read(&mm->context.perf_rdpmc_allowed)) cr4_set_bits(X86_CR4_PCE); else cr4_clear_bits(X86_CR4_PCE); diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index bec5cff7dc8082..b71a7f86d68aca 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -45,6 +45,8 @@ DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { .enabled = 1, }; +struct static_key rdpmc_always_available = STATIC_KEY_INIT_FALSE; + u64 __read_mostly hw_cache_event_ids [PERF_COUNT_HW_CACHE_MAX] [PERF_COUNT_HW_CACHE_OP_MAX] @@ -1870,10 +1872,27 @@ static ssize_t set_attr_rdpmc(struct device *cdev, if (ret) return ret; + if (val > 2) + return -EINVAL; + if (x86_pmu.attr_rdpmc_broken) return -ENOTSUPP; - x86_pmu.attr_rdpmc = !!val; + if ((val == 2) != (x86_pmu.attr_rdpmc == 2)) { + /* + * Changing into or out of always available, aka + * perf-event-bypassing mode. This path is extremely slow, + * but only root can trigger it, so it's okay. + */ + if (val == 2) + static_key_slow_inc(&rdpmc_always_available); + else + static_key_slow_dec(&rdpmc_always_available); + on_each_cpu(refresh_pce, NULL, 1); + } + + x86_pmu.attr_rdpmc = val; + return count; } From 335f1a62c5a6334c4fc92c3c448d7648408d9b83 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 4 Feb 2015 11:58:53 +0100 Subject: [PATCH 2706/3023] drm: Use static attribute groups for managing connector sysfs entries Instead of manual calls of device_create_file() and device_remove_file(), assign the static attribute groups to the device with device_create_with_groups(). The conditionally built sysfs entries are handled via is_visible callback. This simplifies the code and also avoids the possible races. Signed-off-by: Takashi Iwai Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_sysfs.c | 132 ++++++++++++++++++------------------ 1 file changed, 67 insertions(+), 65 deletions(-) diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index cc3d6d6d67e00a..5c99d3773212a9 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -339,19 +339,51 @@ static ssize_t select_subconnector_show(struct device *device, drm_get_dvi_i_select_name((int)subconnector)); } -static struct device_attribute connector_attrs[] = { - __ATTR_RO(status), - __ATTR_RO(enabled), - __ATTR_RO(dpms), - __ATTR_RO(modes), +static DEVICE_ATTR_RO(status); +static DEVICE_ATTR_RO(enabled); +static DEVICE_ATTR_RO(dpms); +static DEVICE_ATTR_RO(modes); + +static struct attribute *connector_dev_attrs[] = { + &dev_attr_status.attr, + &dev_attr_enabled.attr, + &dev_attr_dpms.attr, + &dev_attr_modes.attr, + NULL }; /* These attributes are for both DVI-I connectors and all types of tv-out. */ -static struct device_attribute connector_attrs_opt1[] = { - __ATTR_RO(subconnector), - __ATTR_RO(select_subconnector), +static DEVICE_ATTR_RO(subconnector); +static DEVICE_ATTR_RO(select_subconnector); + +static struct attribute *connector_opt_dev_attrs[] = { + &dev_attr_subconnector.attr, + &dev_attr_select_subconnector.attr, + NULL }; +static umode_t connector_opt_dev_is_visible(struct kobject *kobj, + struct attribute *attr, int idx) +{ + struct device *dev = kobj_to_dev(kobj); + struct drm_connector *connector = to_drm_connector(dev); + + /* + * In the long run it maybe a good idea to make one set of + * optionals per connector type. + */ + switch (connector->connector_type) { + case DRM_MODE_CONNECTOR_DVII: + case DRM_MODE_CONNECTOR_Composite: + case DRM_MODE_CONNECTOR_SVIDEO: + case DRM_MODE_CONNECTOR_Component: + case DRM_MODE_CONNECTOR_TV: + return attr->mode; + } + + return 0; +} + static struct bin_attribute edid_attr = { .attr.name = "edid", .attr.mode = 0444, @@ -359,6 +391,27 @@ static struct bin_attribute edid_attr = { .read = edid_show, }; +static struct bin_attribute *connector_bin_attrs[] = { + &edid_attr, + NULL +}; + +static const struct attribute_group connector_dev_group = { + .attrs = connector_dev_attrs, + .bin_attrs = connector_bin_attrs, +}; + +static const struct attribute_group connector_opt_dev_group = { + .attrs = connector_opt_dev_attrs, + .is_visible = connector_opt_dev_is_visible, +}; + +static const struct attribute_group *connector_dev_groups[] = { + &connector_dev_group, + &connector_opt_dev_group, + NULL +}; + /** * drm_sysfs_connector_add - add a connector to sysfs * @connector: connector to add @@ -371,73 +424,27 @@ static struct bin_attribute edid_attr = { int drm_sysfs_connector_add(struct drm_connector *connector) { struct drm_device *dev = connector->dev; - int attr_cnt = 0; - int opt_cnt = 0; - int i; - int ret; if (connector->kdev) return 0; - connector->kdev = device_create(drm_class, dev->primary->kdev, - 0, connector, "card%d-%s", - dev->primary->index, connector->name); + connector->kdev = + device_create_with_groups(drm_class, dev->primary->kdev, 0, + connector, connector_dev_groups, + "card%d-%s", dev->primary->index, + connector->name); DRM_DEBUG("adding \"%s\" to sysfs\n", connector->name); if (IS_ERR(connector->kdev)) { DRM_ERROR("failed to register connector device: %ld\n", PTR_ERR(connector->kdev)); - ret = PTR_ERR(connector->kdev); - goto out; - } - - /* Standard attributes */ - - for (attr_cnt = 0; attr_cnt < ARRAY_SIZE(connector_attrs); attr_cnt++) { - ret = device_create_file(connector->kdev, &connector_attrs[attr_cnt]); - if (ret) - goto err_out_files; + return PTR_ERR(connector->kdev); } - /* Optional attributes */ - /* - * In the long run it maybe a good idea to make one set of - * optionals per connector type. - */ - switch (connector->connector_type) { - case DRM_MODE_CONNECTOR_DVII: - case DRM_MODE_CONNECTOR_Composite: - case DRM_MODE_CONNECTOR_SVIDEO: - case DRM_MODE_CONNECTOR_Component: - case DRM_MODE_CONNECTOR_TV: - for (opt_cnt = 0; opt_cnt < ARRAY_SIZE(connector_attrs_opt1); opt_cnt++) { - ret = device_create_file(connector->kdev, &connector_attrs_opt1[opt_cnt]); - if (ret) - goto err_out_files; - } - break; - default: - break; - } - - ret = sysfs_create_bin_file(&connector->kdev->kobj, &edid_attr); - if (ret) - goto err_out_files; - /* Let userspace know we have a new connector */ drm_sysfs_hotplug_event(dev); return 0; - -err_out_files: - for (i = 0; i < opt_cnt; i++) - device_remove_file(connector->kdev, &connector_attrs_opt1[i]); - for (i = 0; i < attr_cnt; i++) - device_remove_file(connector->kdev, &connector_attrs[i]); - device_unregister(connector->kdev); - -out: - return ret; } /** @@ -455,16 +462,11 @@ int drm_sysfs_connector_add(struct drm_connector *connector) */ void drm_sysfs_connector_remove(struct drm_connector *connector) { - int i; - if (!connector->kdev) return; DRM_DEBUG("removing \"%s\" from sysfs\n", connector->name); - for (i = 0; i < ARRAY_SIZE(connector_attrs); i++) - device_remove_file(connector->kdev, &connector_attrs[i]); - sysfs_remove_bin_file(&connector->kdev->kobj, &edid_attr); device_unregister(connector->kdev); connector->kdev = NULL; } From c4c6f2cad9e1d4cc076bc183c3689cc9e7019c75 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 4 Feb 2015 10:52:03 +0000 Subject: [PATCH 2707/3023] KVM: MIPS: Disable HTW while in guest Ensure any hardware page table walker (HTW) is disabled while in KVM guest mode, as KVM doesn't yet set up hardware page table walking for guest mappings so the wrong mappings would get loaded, resulting in the guest hanging or crashing once it reaches userland. The HTW is disabled and re-enabled around the call to __kvm_mips_vcpu_run() which does the initial switch into guest mode and the final switch out of guest context. Additionally it is enabled for the duration of guest exits (i.e. kvm_mips_handle_exit()), getting disabled again before returning back to guest or host. In all cases the HTW is only disabled in normal kernel mode while interrupts are disabled, so that the HTW doesn't get left disabled if the process is preempted. Signed-off-by: James Hogan Cc: Paolo Bonzini Cc: Ralf Baechle Cc: Markos Chandras Cc: Gleb Natapov Cc: kvm@vger.kernel.org Cc: linux-mips@linux-mips.org Cc: # v3.17+ Signed-off-by: Paolo Bonzini --- arch/mips/kvm/mips.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c index 7082481cd1087a..9a28ea4f54f368 100644 --- a/arch/mips/kvm/mips.c +++ b/arch/mips/kvm/mips.c @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -385,8 +386,14 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) kvm_guest_enter(); + /* Disable hardware page table walking while in guest */ + htw_stop(); + r = __kvm_mips_vcpu_run(run, vcpu); + /* Re-enable HTW before enabling interrupts */ + htw_start(); + kvm_guest_exit(); local_irq_enable(); @@ -1001,6 +1008,9 @@ int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu) enum emulation_result er = EMULATE_DONE; int ret = RESUME_GUEST; + /* re-enable HTW before enabling interrupts */ + htw_start(); + /* Set a default exit reason */ run->exit_reason = KVM_EXIT_UNKNOWN; run->ready_for_interrupt_injection = 1; @@ -1135,6 +1145,9 @@ int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu) } } + /* Disable HTW before returning to guest or host */ + htw_stop(); + return ret; } From 6dfca6b37fb20f31502153b549ce5948fcd5ecef Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Wed, 4 Feb 2015 17:37:00 +0100 Subject: [PATCH 2708/3023] drm: sti: fix check for clk_pix_main copy-paste wasn't followed by editing, do it. Signed-off-by: Jassi Brar --- drivers/gpu/drm/sti/sti_hqvdp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c index f3db05dab0abb6..b0eb62de1b2ecc 100644 --- a/drivers/gpu/drm/sti/sti_hqvdp.c +++ b/drivers/gpu/drm/sti/sti_hqvdp.c @@ -1025,7 +1025,7 @@ static int sti_hqvdp_probe(struct platform_device *pdev) /* Get clock resources */ hqvdp->clk = devm_clk_get(dev, "hqvdp"); hqvdp->clk_pix_main = devm_clk_get(dev, "pix_main"); - if (IS_ERR(hqvdp->clk) || IS_ERR(hqvdp->clk)) { + if (IS_ERR(hqvdp->clk) || IS_ERR(hqvdp->clk_pix_main)) { DRM_ERROR("Cannot get clocks\n"); return -ENXIO; } From 17ba9810ec4c8f95bfde516653e81d435809eb6b Mon Sep 17 00:00:00 2001 From: Vincent Abriou Date: Wed, 4 Feb 2015 16:54:13 +0100 Subject: [PATCH 2709/3023] drm: sti: fix static checker warning in sti_awg_utils The shift and the mask done on arg value is useless since arg is null. Signed-off-by: Vincent Abriou --- drivers/gpu/drm/sti/sti_awg_utils.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/sti/sti_awg_utils.c b/drivers/gpu/drm/sti/sti_awg_utils.c index 9fde3ee8b1a5a9..6029a2e3db1dc8 100644 --- a/drivers/gpu/drm/sti/sti_awg_utils.c +++ b/drivers/gpu/drm/sti/sti_awg_utils.c @@ -60,8 +60,6 @@ static int awg_generate_instr(enum opcode opcode, * pixel. So we transform SKIP into SET * instruction */ opcode = SET; - arg = (arg << 24) >> 24; - arg &= (0x0ff); break; } From 4af6b12ad57aae1e9798df499e81e309c7f0bc26 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Mon, 2 Feb 2015 15:08:45 +0100 Subject: [PATCH 2710/3023] drm: sti: add support of ABGR8888 for gdp plane Use GDP capabilities to support DRM_FORMAT_ABGR8888 (AB24) Signed-off-by: Benjamin Gaignard --- drivers/gpu/drm/sti/sti_gdp.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index 32448d1d1e8f26..f018bb1bb2b767 100644 --- a/drivers/gpu/drm/sti/sti_gdp.c +++ b/drivers/gpu/drm/sti/sti_gdp.c @@ -14,7 +14,9 @@ #include "sti_layer.h" #include "sti_vtg.h" +#define ALPHASWITCH BIT(6) #define ENA_COLOR_FILL BIT(8) +#define BIGNOTLITTLE BIT(23) #define WAIT_NEXT_VSYNC BIT(31) /* GDP color formats */ @@ -23,6 +25,7 @@ #define GDP_RGB888_32 0x02 #define GDP_ARGB8565 0x04 #define GDP_ARGB8888 0x05 +#define GDP_ABGR8888 (GDP_ARGB8888 | BIGNOTLITTLE | ALPHASWITCH) #define GDP_ARGB1555 0x06 #define GDP_ARGB4444 0x07 #define GDP_CLUT8 0x0B @@ -104,6 +107,7 @@ struct sti_gdp { static const uint32_t gdp_supported_formats[] = { DRM_FORMAT_XRGB8888, DRM_FORMAT_ARGB8888, + DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB4444, DRM_FORMAT_ARGB1555, DRM_FORMAT_RGB565, @@ -131,6 +135,8 @@ static int sti_gdp_fourcc2format(int fourcc) return GDP_RGB888_32; case DRM_FORMAT_ARGB8888: return GDP_ARGB8888; + case DRM_FORMAT_ABGR8888: + return GDP_ABGR8888; case DRM_FORMAT_ARGB4444: return GDP_ARGB4444; case DRM_FORMAT_ARGB1555: @@ -157,6 +163,7 @@ static int sti_gdp_get_alpharange(int format) case GDP_ARGB8565: case GDP_ARGB8888: case GDP_AYCBR8888: + case GDP_ABGR8888: return GAM_GDP_ALPHARANGE_255; } return 0; From 1fa2df0c70dadba1139c9dd52c9070d00fe23c98 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Tue, 3 Feb 2015 10:37:06 +0800 Subject: [PATCH 2711/3023] staging: emxx_udc: fix the build error Fix below build error: reproduce: wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross git checkout 9239d88fc5e58a2a72bc949362f999aac9bffb29 # save the attached .config to linux build tree make.cross ARCH=arm All error/warnings: In file included from include/linux/seqlock.h:35:0, from include/linux/time.h:5, from include/linux/stat.h:18, from include/linux/module.h:10, from drivers/staging/emxx_udc/emxx_udc.c:22: drivers/staging/emxx_udc/emxx_udc.c: In function 'nbu2ss_gad_set_selfpowered': >> drivers/staging/emxx_udc/emxx_udc.c:3129:21: error: 'udc' undeclared (first use in this function) spin_lock_irqsave(&udc->lock, flags); ^ include/linux/spinlock.h:215:34: note: in definition of macro 'raw_spin_lock_irqsave' flags = _raw_spin_lock_irqsave(lock); \ ^ >> drivers/staging/emxx_udc/emxx_udc.c:3129:2: note: in expansion of macro 'spin_lock_irqsave' spin_lock_irqsave(&udc->lock, flags); ^ drivers/staging/emxx_udc/emxx_udc.c:3129:21: note: each undeclared identifier is reported only once for each function it appears in spin_lock_irqsave(&udc->lock, flags); ^ include/linux/spinlock.h:215:34: note: in definition of macro 'raw_spin_lock_irqsave' flags = _raw_spin_lock_irqsave(lock); \ ^ >> drivers/staging/emxx_udc/emxx_udc.c:3129:2: note: in expansion of macro 'spin_lock_irqsave' spin_lock_irqsave(&udc->lock, flags); ^ vim +/udc +3129 drivers/staging/emxx_udc/emxx_udc.c 33aa8d45 Magnus Damm 2014-06-06 3123 33aa8d45 Magnus Damm 2014-06-06 3124 if (pgadget == NULL) { 33aa8d45 Magnus Damm 2014-06-06 3125 ERR("%s, bad param\n", __func__); 33aa8d45 Magnus Damm 2014-06-06 3126 return -EINVAL; 33aa8d45 Magnus Damm 2014-06-06 3127 } 33aa8d45 Magnus Damm 2014-06-06 3128 33aa8d45 Magnus Damm 2014-06-06 @3129 spin_lock_irqsave(&udc->lock, flags); 9239d88f Peter Chen 2015-01-28 3130 pgadget->is_selfpowered = (is_selfpowered != 0); 33aa8d45 Magnus Damm 2014-06-06 3131 spin_unlock_irqrestore(&udc->lock, flags); 33aa8d45 Magnus Damm 2014-06-06 3132 Signed-off-by: Peter Chen Signed-off-by: Felipe Balbi --- drivers/staging/emxx_udc/emxx_udc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c index 1d3135a3325863..bd70ea05708b59 100644 --- a/drivers/staging/emxx_udc/emxx_udc.c +++ b/drivers/staging/emxx_udc/emxx_udc.c @@ -3117,6 +3117,7 @@ static int nbu2ss_gad_wakeup(struct usb_gadget *pgadget) static int nbu2ss_gad_set_selfpowered(struct usb_gadget *pgadget, int is_selfpowered) { + struct nbu2ss_udc *udc; unsigned long flags; /* INFO("=== %s()\n", __func__); */ @@ -3126,6 +3127,8 @@ static int nbu2ss_gad_set_selfpowered(struct usb_gadget *pgadget, return -EINVAL; } + udc = container_of(pgadget, struct nbu2ss_udc, gadget); + spin_lock_irqsave(&udc->lock, flags); pgadget->is_selfpowered = (is_selfpowered != 0); spin_unlock_irqrestore(&udc->lock, flags); From 251a17f5aff990ab117590df2a13ef032464c0d3 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Mon, 2 Feb 2015 14:55:38 -0800 Subject: [PATCH 2712/3023] usb: dwc2: Fix a bug in reading the endpoint directions from reg. According to the DWC2 datasheet, the HWCFG1 register stores the configured endpoint directions for endpoints 0-15 in bit positions 0-31. ========================== Endpoint Direction (EpDir) This 32-bit field uses two bits per endpoint to determine the endpoint direction. Endpoint Bits [31:30]: Endpoint 15 direction Bits [29:28]: Endpoint 14 direction .... Bits [3:2]: Endpoint 1 direction Bits[1:0]: Endpoint 0 direction (always BIDIR) ========================== The DWC2 driver is currently interpreting the contents of the register as directions for endpoints 1-15 which leads to an error in determining the configured endpoint directions in the core because the first 2 bits determine the direction of endpoint 0 and not 1. This is based on testing/next branch in Felipe's git. Signed-off-by: Roshan Pius Acked-by: John Youn Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 15aa5785090b84..6a30887082cd9d 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -3308,7 +3308,7 @@ static int s3c_hsotg_hw_cfg(struct dwc2_hsotg *hsotg) hsotg->eps_out[0] = hsotg->eps_in[0]; cfg = readl(hsotg->regs + GHWCFG1); - for (i = 1; i < hsotg->num_of_eps; i++, cfg >>= 2) { + for (i = 1, cfg >>= 2; i < hsotg->num_of_eps; i++, cfg >>= 2) { ep_type = cfg & 3; /* Direction in or both */ if (!(ep_type & 2)) { From 9298b4aad37e8c6962edcdbd0b62620adb207d03 Mon Sep 17 00:00:00 2001 From: Bin Liu Date: Tue, 3 Feb 2015 11:02:10 -0600 Subject: [PATCH 2713/3023] usb: musb: fix device hotplug behind hub The commit 889ad3b "usb: musb: try a race-free wakeup" breaks device hotplug enumeraitonn when the device is connected behind a hub while usb autosuspend is enabled. Adding finish_resume_work into runtime resume callback fixes the issue. Also resume root hub is required to resume the bus from runtime suspend, so move musb_host_resume_root_hub() back to its original location, where handles RESUME interrupt. Signed-off-by: Bin Liu Tested-by: Tony Lindgren Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_core.c | 7 +++++++ drivers/usb/musb/musb_virthub.c | 1 - 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 34cce3e38c494a..e6f4cbfeed9736 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -567,6 +567,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, musb->xceiv->otg->state = OTG_STATE_A_HOST; musb->is_active = 1; + musb_host_resume_root_hub(musb); break; case OTG_STATE_B_WAIT_ACON: musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL; @@ -2500,6 +2501,12 @@ static int musb_runtime_resume(struct device *dev) musb_restore_context(musb); first = 0; + if (musb->need_finish_resume) { + musb->need_finish_resume = 0; + schedule_delayed_work(&musb->finish_resume_work, + msecs_to_jiffies(20)); + } + return 0; } diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index 662de58630e91b..294e159f4afe82 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -72,7 +72,6 @@ void musb_host_finish_resume(struct work_struct *work) musb->xceiv->otg->state = OTG_STATE_A_HOST; spin_unlock_irqrestore(&musb->lock, flags); - musb_host_resume_root_hub(musb); } void musb_port_suspend(struct musb *musb, bool do_suspend) From f798217dfd038af981a18bbe4bc57027a08bb182 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Wed, 4 Feb 2015 17:06:37 +0000 Subject: [PATCH 2714/3023] KVM: MIPS: Don't leak FPU/DSP to guest The FPU and DSP are enabled via the CP0 Status CU1 and MX bits by kvm_mips_set_c0_status() on a guest exit, presumably in case there is active state that needs saving if pre-emption occurs. However neither of these bits are cleared again when returning to the guest. This effectively gives the guest access to the FPU/DSP hardware after the first guest exit even though it is not aware of its presence, allowing FP instructions in guest user code to intermittently actually execute instead of trapping into the guest OS for emulation. It will then read & manipulate the hardware FP registers which technically belong to the user process (e.g. QEMU), or are stale from another user process. It can also crash the guest OS by causing an FP exception, for which a guest exception handler won't have been registered. First lets save and disable the FPU (and MSA) state with lose_fpu(1) before entering the guest. This simplifies the problem, especially for when guest FPU/MSA support is added in the future, and prevents FR=1 FPU state being live when the FR bit gets cleared for the guest, which according to the architecture causes the contents of the FPU and vector registers to become UNPREDICTABLE. We can then safely remove the enabling of the FPU in kvm_mips_set_c0_status(), since there should never be any active FPU or MSA state to save at pre-emption, which should plug the FPU leak. DSP state is always live rather than being lazily restored, so for that it is simpler to just clear the MX bit again when re-entering the guest. Signed-off-by: James Hogan Cc: Paolo Bonzini Cc: Ralf Baechle Cc: Sanjay Lal Cc: Gleb Natapov Cc: kvm@vger.kernel.org Cc: linux-mips@linux-mips.org Cc: # v3.10+: 044f0f03eca0: MIPS: KVM: Deliver guest interrupts Cc: # v3.10+ Signed-off-by: Paolo Bonzini --- arch/mips/kvm/locore.S | 2 +- arch/mips/kvm/mips.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/mips/kvm/locore.S b/arch/mips/kvm/locore.S index d7279c03c517a0..4a68b176d6e4f8 100644 --- a/arch/mips/kvm/locore.S +++ b/arch/mips/kvm/locore.S @@ -434,7 +434,7 @@ __kvm_mips_return_to_guest: /* Setup status register for running guest in UM */ .set at or v1, v1, (ST0_EXL | KSU_USER | ST0_IE) - and v1, v1, ~ST0_CU0 + and v1, v1, ~(ST0_CU0 | ST0_MX) .set noat mtc0 v1, CP0_STATUS ehb diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c index 9a28ea4f54f368..e97b907840311d 100644 --- a/arch/mips/kvm/mips.c +++ b/arch/mips/kvm/mips.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -379,6 +380,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) vcpu->mmio_needed = 0; } + lose_fpu(1); + local_irq_disable(); /* Check if we have any exceptions/interrupts pending */ kvm_mips_deliver_interrupts(vcpu, @@ -986,9 +989,6 @@ static void kvm_mips_set_c0_status(void) { uint32_t status = read_c0_status(); - if (cpu_has_fpu) - status |= (ST0_CU1); - if (cpu_has_dsp) status |= (ST0_MX); From 603101708c9c9ad2bc5a183d6d10b115738098c7 Mon Sep 17 00:00:00 2001 From: Kaixu Xia Date: Mon, 26 Jan 2015 09:22:18 -0700 Subject: [PATCH 2715/3023] coresight: remove the unnecessary replicator property Now we use the device name to identify replicator instead of a unique number, so just remove it. Signed-off-by: Kaixu Xia Signed-off-by: Mathieu Poirier Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/arm/coresight.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt index d790f49066f355..a3089359aaa6e5 100644 --- a/Documentation/devicetree/bindings/arm/coresight.txt +++ b/Documentation/devicetree/bindings/arm/coresight.txt @@ -38,8 +38,6 @@ its hardware characteristcs. AMBA markee): - "arm,coresight-replicator" - * id: a unique number that will identify this replicator. - * port or ports: same as above. * Optional properties for ETM/PTMs: @@ -94,8 +92,6 @@ Example: * AMBA bus. As such no need to add "arm,primecell". */ compatible = "arm,coresight-replicator"; - /* this will show up in debugfs as "0.replicator" */ - id = <0>; ports { #address-cells = <1>; From 22394bc58543639e5135f19eee2b03d14e4a9b66 Mon Sep 17 00:00:00 2001 From: Kaixu Xia Date: Mon, 26 Jan 2015 09:22:19 -0700 Subject: [PATCH 2716/3023] coresight: fix the link between orphan connection and newly added device When founding a component that has orphan connections, we should validate if it match the newly added device. If it does not match, only then should the @still_orphan flag should be set. The tested result as follows. pre: /sys/bus/coresight/devices # echo 1 > e3c42000.etb/enable_sink /sys/bus/coresight/devices # echo 1 > e3c7c000.ptm/enable_source [ 15.527692] Unable to handle kernel NULL pointer dereference at virtual address 00000124 [ 15.555142] pgd = c2294000 [ 15.564226] [00000124] *pgd=3d393831, *pte=00000000, *ppte=00000000 [ 15.585391] Internal error: Oops: 817 [#1] PREEMPT SMP ARM [ 15.603807] CPU: 0 PID: 144 Comm: sh Not tainted 3.17.0-rc1-12634-g1222fe0-dirty #3 [ 15.629490] task: ed3803c0 ti: c213a000 task.ti: c213a000 [ 15.647627] PC is at coresight_build_paths+0x1c/0x314 [ 15.664579] LR is at coresight_build_paths+0x6c/0x314 [ 15.681526] pc : [] lr : [] psr: 20000013 [ 15.681526] sp : c213be88 ip : c02da800 fp : 00000000 [ 15.720023] r10: 00000002 r9 : ed13250c r8 : 00000001 [ 15.737549] r7 : c213bee8 r6 : ffffffea r5 : 00000000 r4 : 00000124 [ 15.759446] r3 : ed216f24 r2 : 00000001 r1 : c213bee8 r0 : 00000000 [ 15.781346] Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user post: /sys/bus/coresight/devices # echo 1 > e3c42000.etb/enable_sink /sys/bus/coresight/devices # echo 1 > e3c7c000.ptm/enable_source [ 59.934255] coresight-etb10 e3c42000.etb: ETB enabled [ 59.951317] coresight-replicator replicator0: REPLICATOR enabled [ 59.971581] coresight-funnel e3c41000.funnel: FUNNEL inport 0 enabled [ 59.993334] coresight-etm3x e3c7c000.ptm: ETM tracing enabled Signed-off-by: Kaixu Xia Signed-off-by: Mathieu Poirier Signed-off-by: Greg Kroah-Hartman --- drivers/coresight/coresight.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/coresight/coresight.c b/drivers/coresight/coresight.c index 6e0181f8442581..d6052e2cd6a70b 100644 --- a/drivers/coresight/coresight.c +++ b/drivers/coresight/coresight.c @@ -504,11 +504,12 @@ static int coresight_orphan_match(struct device *dev, void *data) /* We have found at least one orphan connection */ if (conn->child_dev == NULL) { /* Does it match this newly added device? */ - if (!strcmp(dev_name(&csdev->dev), conn->child_name)) + if (!strcmp(dev_name(&csdev->dev), conn->child_name)) { conn->child_dev = csdev; - } else { - /* Too bad, this component still has an orphan */ - still_orphan = true; + } else { + /* This component still has an orphan */ + still_orphan = true; + } } } From d786a47de97fd194d6cf4f9087543119b9b330c3 Mon Sep 17 00:00:00 2001 From: Kaixu Xia Date: Mon, 26 Jan 2015 09:22:20 -0700 Subject: [PATCH 2717/3023] coresight: remove the extra spaces There are some extra spaces, so just remove them from these lines. Signed-off-by: Kaixu Xia Signed-off-by: Mathieu Poirier Signed-off-by: Greg Kroah-Hartman --- drivers/coresight/coresight-etb10.c | 2 +- drivers/coresight/coresight.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/coresight/coresight-etb10.c b/drivers/coresight/coresight-etb10.c index a1da7020201bfb..c9acd406f0d02a 100644 --- a/drivers/coresight/coresight-etb10.c +++ b/drivers/coresight/coresight-etb10.c @@ -454,7 +454,7 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id) if (ret) return ret; - drvdata->buffer_depth = etb_get_buffer_depth(drvdata); + drvdata->buffer_depth = etb_get_buffer_depth(drvdata); clk_disable_unprepare(drvdata->clk); if (drvdata->buffer_depth < 0) diff --git a/drivers/coresight/coresight.c b/drivers/coresight/coresight.c index d6052e2cd6a70b..c5def93823570d 100644 --- a/drivers/coresight/coresight.c +++ b/drivers/coresight/coresight.c @@ -498,7 +498,7 @@ static int coresight_orphan_match(struct device *dev, void *data) * Circle throuch all the connection of that component. If we find * an orphan connection whose name matches @csdev, link it. */ - for (i = 0; i < i_csdev->nr_outport; i++) { + for (i = 0; i < i_csdev->nr_outport; i++) { conn = &i_csdev->conns[i]; /* We have found at least one orphan connection */ From 7af8792b4d3ad94774fb40f422fa245ab3755bb4 Mon Sep 17 00:00:00 2001 From: Kaixu Xia Date: Mon, 26 Jan 2015 09:22:21 -0700 Subject: [PATCH 2718/3023] coresight: fix the debug AMBA bus name The right debug AMBA bus name should be APB(Advanced Peripheral Bus), so just fix it. Signed-off-by: Kaixu Xia Signed-off-by: Mathieu Poirier Signed-off-by: Greg Kroah-Hartman --- Documentation/trace/coresight.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/trace/coresight.txt b/Documentation/trace/coresight.txt index bba7dbfc49edcd..02361552a3eac3 100644 --- a/Documentation/trace/coresight.txt +++ b/Documentation/trace/coresight.txt @@ -46,7 +46,7 @@ At typical coresight system would look like this: | | . | ! | | . | ! | ! . | | SWD/ | | . | ! | | . | ! | ! . | | JTAG *****************************************************************<-| - *************************** AMBA Debug ABP ************************ + *************************** AMBA Debug APB ************************ ***************************************************************** | . ! . ! ! . | | . * . * * . | @@ -79,7 +79,7 @@ At typical coresight system would look like this: To trace port TPIU= Trace Port Interface Unit SWD = Serial Wire Debug -While on target configuration of the components is done via the ABP bus, +While on target configuration of the components is done via the APB bus, all trace data are carried out-of-band on the ATB bus. The CTM provides a way to aggregate and distribute signals between CoreSight components. From c4546f246636ccf4cda092bcfcafcb5f5f752ec7 Mon Sep 17 00:00:00 2001 From: Kaixu Xia Date: Mon, 26 Jan 2015 09:22:22 -0700 Subject: [PATCH 2719/3023] coresight: remove the unnecessary function coresight_is_bit_set() This function coresight_is_bit_set() isn't called, so we should remove it. Signed-off-by: Kaixu Xia Signed-off-by: Mathieu Poirier Signed-off-by: Greg Kroah-Hartman --- include/linux/coresight.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/linux/coresight.h b/include/linux/coresight.h index cd6d4c384ca316..3486b9082adbcf 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -227,7 +227,6 @@ coresight_register(struct coresight_desc *desc); extern void coresight_unregister(struct coresight_device *csdev); extern int coresight_enable(struct coresight_device *csdev); extern void coresight_disable(struct coresight_device *csdev); -extern int coresight_is_bit_set(u32 val, int position, int value); extern int coresight_timeout(void __iomem *addr, u32 offset, int position, int value); #else @@ -237,8 +236,6 @@ static inline void coresight_unregister(struct coresight_device *csdev) {} static inline int coresight_enable(struct coresight_device *csdev) { return -ENOSYS; } static inline void coresight_disable(struct coresight_device *csdev) {} -static inline int coresight_is_bit_set(u32 val, int position, int value) - { return 0; } static inline int coresight_timeout(void __iomem *addr, u32 offset, int position, int value) { return 1; } #endif From 34a03c1d30f04ca7439c685c0ea9b7d79c353705 Mon Sep 17 00:00:00 2001 From: Mathieu Poirier Date: Mon, 26 Jan 2015 09:22:23 -0700 Subject: [PATCH 2720/3023] coresight: fixing CPU hwid lookup in device tree Some DT specification will represent CPU nodes with address cells greater than one, making the current code fail. Using the proper retrieval helper function ensure the correct hwid for CPUs is read properly with different address cell size. Signed-off-by: Mathieu Poirier Signed-off-by: Greg Kroah-Hartman --- drivers/coresight/of_coresight.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/coresight/of_coresight.c b/drivers/coresight/of_coresight.c index 9a5ff56f34d9b8..c3efa418a86d8e 100644 --- a/drivers/coresight/of_coresight.c +++ b/drivers/coresight/of_coresight.c @@ -117,7 +117,7 @@ struct coresight_platform_data *of_get_coresight_platform_data( struct coresight_platform_data *pdata; struct of_endpoint endpoint, rendpoint; struct device *rdev; - struct device_node *cpu; + struct device_node *dn; struct device_node *ep = NULL; struct device_node *rparent = NULL; struct device_node *rport = NULL; @@ -186,14 +186,16 @@ struct coresight_platform_data *of_get_coresight_platform_data( /* Affinity defaults to CPU0 */ pdata->cpu = 0; - cpu = of_parse_phandle(node, "cpu", 0); - if (cpu) { - const u32 *mpidr; + dn = of_parse_phandle(node, "cpu", 0); + if (dn) { + const u32 *cell; int len, index; + u64 hwid; - mpidr = of_get_property(cpu, "reg", &len); - if (mpidr && len == 4) { - index = get_logical_index(be32_to_cpup(mpidr)); + cell = of_get_property(dn, "reg", &len); + if (cell) { + hwid = of_read_number(cell, of_n_addr_cells(dn)); + index = get_logical_index(hwid); if (index != -EINVAL) pdata->cpu = index; } From 406b9f659fbc966ab47a1fe8f5c1a2e8110483ad Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Mon, 26 Jan 2015 09:22:24 -0700 Subject: [PATCH 2721/3023] coresight-etm: remove check for unknown Kconfig macro The CoreSight ETM/PTM driver contains a check for a CONFIG_CORESIGHT_SOURCE_ETM_DEFAULT_ENABLE macro. But there's no related Kconfig symbol CORESIGHT_SOURCE_ETM_DEFAULT_ENABLE. Remove that check and the single line of code it hides. Signed-off-by: Paul Bolle Signed-off-by: Mathieu Poirier Signed-off-by: Greg Kroah-Hartman --- drivers/coresight/coresight-etm3x.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/coresight/coresight-etm3x.c b/drivers/coresight/coresight-etm3x.c index 73c36696f1b686..c965f5724abdb3 100644 --- a/drivers/coresight/coresight-etm3x.c +++ b/drivers/coresight/coresight-etm3x.c @@ -34,14 +34,8 @@ #include "coresight-etm.h" -#ifdef CONFIG_CORESIGHT_SOURCE_ETM_DEFAULT_ENABLE -static int boot_enable = 1; -#else static int boot_enable; -#endif -module_param_named( - boot_enable, boot_enable, int, S_IRUGO -); +module_param_named(boot_enable, boot_enable, int, S_IRUGO); /* The number of ETM/PTM currently registered */ static int etm_count; From 5fb31cd839c21130c0b2524ceb9244e98dfe10e3 Mon Sep 17 00:00:00 2001 From: Kaixu Xia Date: Mon, 26 Jan 2015 09:22:25 -0700 Subject: [PATCH 2722/3023] coresight: fix function etm_writel_cp14() parameter order Function etm_writel_cp14() takes an offset and a value rather than the other way around, something this patch is correcting. The semantic remains the same since it is only a function stub. Signed-off-by: Kaixu Xia Signed-off-by: Mathieu Poirier Signed-off-by: Greg Kroah-Hartman --- drivers/coresight/coresight-priv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/coresight/coresight-priv.h b/drivers/coresight/coresight-priv.h index 7b3372fca4f644..62fcd98cc7cfc7 100644 --- a/drivers/coresight/coresight-priv.h +++ b/drivers/coresight/coresight-priv.h @@ -57,7 +57,7 @@ extern int etm_readl_cp14(u32 off, unsigned int *val); extern int etm_writel_cp14(u32 off, u32 val); #else static inline int etm_readl_cp14(u32 off, unsigned int *val) { return 0; } -static inline int etm_writel_cp14(u32 val, u32 off) { return 0; } +static inline int etm_writel_cp14(u32 off, u32 val) { return 0; } #endif #endif From 8adb57763e8b4f85607b000a0295747d0a338c32 Mon Sep 17 00:00:00 2001 From: Fabien Dessenne Date: Wed, 4 Feb 2015 18:12:53 +0100 Subject: [PATCH 2723/3023] drm: sti: add support of XBGR8888 for gdp plane Use GDP capabilities to support DRM_FORMAT_XBGR8888 (XB24) Signed-off-by: Fabien Dessenne --- drivers/gpu/drm/sti/sti_gdp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index f018bb1bb2b767..087906fd884685 100644 --- a/drivers/gpu/drm/sti/sti_gdp.c +++ b/drivers/gpu/drm/sti/sti_gdp.c @@ -23,6 +23,7 @@ #define GDP_RGB565 0x00 #define GDP_RGB888 0x01 #define GDP_RGB888_32 0x02 +#define GDP_XBGR8888 (GDP_RGB888_32 | BIGNOTLITTLE | ALPHASWITCH) #define GDP_ARGB8565 0x04 #define GDP_ARGB8888 0x05 #define GDP_ABGR8888 (GDP_ARGB8888 | BIGNOTLITTLE | ALPHASWITCH) @@ -106,6 +107,7 @@ struct sti_gdp { static const uint32_t gdp_supported_formats[] = { DRM_FORMAT_XRGB8888, + DRM_FORMAT_XBGR8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB4444, @@ -133,6 +135,8 @@ static int sti_gdp_fourcc2format(int fourcc) switch (fourcc) { case DRM_FORMAT_XRGB8888: return GDP_RGB888_32; + case DRM_FORMAT_XBGR8888: + return GDP_XBGR8888; case DRM_FORMAT_ARGB8888: return GDP_ARGB8888; case DRM_FORMAT_ABGR8888: From 1c2b364b225a5a93dbd1f317bd000d2fec2694be Mon Sep 17 00:00:00 2001 From: Tiejun Chen Date: Thu, 5 Feb 2015 17:22:26 +0800 Subject: [PATCH 2724/3023] kvm: remove KVM_MMIO_SIZE After f78146b0f923, "KVM: Fix page-crossing MMIO", and 87da7e66a405, "KVM: x86: fix vcpu->mmio_fragments overflow", actually KVM_MMIO_SIZE is gone. Signed-off-by: Tiejun Chen Signed-off-by: Paolo Bonzini --- arch/x86/include/asm/kvm_host.h | 2 -- include/linux/kvm_host.h | 4 ---- 2 files changed, 6 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 9dbc7435cbc203..848947ac6ade47 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -38,8 +38,6 @@ #define KVM_PRIVATE_MEM_SLOTS 3 #define KVM_MEM_SLOTS_NUM (KVM_USER_MEM_SLOTS + KVM_PRIVATE_MEM_SLOTS) -#define KVM_MMIO_SIZE 16 - #define KVM_PIO_PAGE_OFFSET 1 #define KVM_COALESCED_MMIO_PAGE_OFFSET 2 diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 32d057571bf624..8a82838034f16c 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -33,10 +33,6 @@ #include -#ifndef KVM_MMIO_SIZE -#define KVM_MMIO_SIZE 8 -#endif - /* * The bit 16 ~ bit 31 of kvm_memory_region::flags are internally used * in kvm, other bits are visible for userspace which are defined in From 460822b0b1a77db859b0320469799fa4dbe4d367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Winiarski?= Date: Tue, 3 Feb 2015 15:48:17 +0100 Subject: [PATCH 2725/3023] drm/i915: Prevent use-after-free in invalidate_range_start callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's possible for invalidate_range_start mmu notifier callback to race against userptr object release. If the gem object was released prior to obtaining the spinlock in invalidate_range_start we're hitting null pointer dereference. Testcase: igt/gem_userptr_blits/stress-mm-invalidate-close Testcase: igt/gem_userptr_blits/stress-mm-invalidate-close-overlap Cc: Chris Wilson Signed-off-by: MichaÅ‚ Winiarski Reviewed-by: Chris Wilson Cc: stable@vger.kernel.org [Jani: added code comment suggested by Chris] Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_gem_userptr.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index d182058383a9ef..1719078c763ac0 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -113,7 +113,10 @@ static void *invalidate_range__linear(struct i915_mmu_notifier *mn, continue; obj = mo->obj; - drm_gem_object_reference(&obj->base); + + if (!kref_get_unless_zero(&obj->base.refcount)) + continue; + spin_unlock(&mn->lock); cancel_userptr(obj); @@ -149,7 +152,20 @@ static void i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn, it = interval_tree_iter_first(&mn->objects, start, end); if (it != NULL) { obj = container_of(it, struct i915_mmu_object, it)->obj; - drm_gem_object_reference(&obj->base); + + /* The mmu_object is released late when destroying the + * GEM object so it is entirely possible to gain a + * reference on an object in the process of being freed + * since our serialisation is via the spinlock and not + * the struct_mutex - and consequently use it after it + * is freed and then double free it. + */ + if (!kref_get_unless_zero(&obj->base.refcount)) { + spin_unlock(&mn->lock); + serial = 0; + continue; + } + serial = mn->serial; } spin_unlock(&mn->lock); From cffe1e89dc9bf541a39d9287ced7c5addff07084 Mon Sep 17 00:00:00 2001 From: Arnaud Pouliquen Date: Thu, 5 Feb 2015 11:55:02 +0100 Subject: [PATCH 2726/3023] drm: sti: HDMI add audio infoframe Add a default audio infoframe for HDMI compliance Signed-off-by: Arnaud Pouliquen --- drivers/gpu/drm/sti/sti_hdmi.c | 179 +++++++++++++++++++++++++-------- 1 file changed, 137 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c index e840ca5de40107..1485ade98710a3 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.c +++ b/drivers/gpu/drm/sti/sti_hdmi.c @@ -42,8 +42,17 @@ #define HDMI_SW_DI_1_PKT_WORD5 0x0228 #define HDMI_SW_DI_1_PKT_WORD6 0x022C #define HDMI_SW_DI_CFG 0x0230 +#define HDMI_SW_DI_2_HEAD_WORD 0x0600 +#define HDMI_SW_DI_2_PKT_WORD0 0x0604 +#define HDMI_SW_DI_2_PKT_WORD1 0x0608 +#define HDMI_SW_DI_2_PKT_WORD2 0x060C +#define HDMI_SW_DI_2_PKT_WORD3 0x0610 +#define HDMI_SW_DI_2_PKT_WORD4 0x0614 +#define HDMI_SW_DI_2_PKT_WORD5 0x0618 +#define HDMI_SW_DI_2_PKT_WORD6 0x061C #define HDMI_IFRAME_SLOT_AVI 1 +#define HDMI_IFRAME_SLOT_AUDIO 2 #define XCAT(prefix, x, suffix) prefix ## x ## suffix #define HDMI_SW_DI_N_HEAD_WORD(x) XCAT(HDMI_SW_DI_, x, _HEAD_WORD) @@ -99,6 +108,10 @@ #define HDMI_STA_SW_RST BIT(1) +#define HDMI_INFOFRAME_HEADER_TYPE(x) (((x) & 0xff) << 0) +#define HDMI_INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) << 8) +#define HDMI_INFOFRAME_HEADER_LEN(x) (((x) & 0x0f) << 16) + struct sti_hdmi_connector { struct drm_connector drm_connector; struct drm_encoder *encoder; @@ -227,6 +240,90 @@ static void hdmi_config(struct sti_hdmi *hdmi) hdmi_write(hdmi, conf, HDMI_CFG); } +/** + * Helper to concatenate infoframe in 32 bits word + * + * @ptr: pointer on the hdmi internal structure + * @data: infoframe to write + * @size: size to write + */ +static inline unsigned int hdmi_infoframe_subpack(const u8 *ptr, size_t size) +{ + unsigned long value = 0; + size_t i; + + for (i = size; i > 0; i--) + value = (value << 8) | ptr[i - 1]; + + return value; +} + +/** + * Helper to write info frame + * + * @hdmi: pointer on the hdmi internal structure + * @data: infoframe to write + * @size: size to write + */ +static void hdmi_infoframe_write_infopack(struct sti_hdmi *hdmi, const u8 *data) +{ + const u8 *ptr = data; + u32 val, slot, mode, i; + u32 head_offset, pack_offset; + size_t size; + + switch (*ptr) { + case HDMI_INFOFRAME_TYPE_AVI: + slot = HDMI_IFRAME_SLOT_AVI; + mode = HDMI_IFRAME_FIELD; + head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AVI); + pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AVI); + size = HDMI_AVI_INFOFRAME_SIZE; + break; + + case HDMI_INFOFRAME_TYPE_AUDIO: + slot = HDMI_IFRAME_SLOT_AUDIO; + mode = HDMI_IFRAME_FRAME; + head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AUDIO); + pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AUDIO); + size = HDMI_AUDIO_INFOFRAME_SIZE; + break; + + default: + DRM_ERROR("unsupported infoframe type: %#x\n", *ptr); + return; + } + + /* Disable transmission slot for updated infoframe */ + val = hdmi_read(hdmi, HDMI_SW_DI_CFG); + val &= ~HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, slot); + hdmi_write(hdmi, val, HDMI_SW_DI_CFG); + + val = HDMI_INFOFRAME_HEADER_TYPE(*ptr++); + val |= HDMI_INFOFRAME_HEADER_VERSION(*ptr++); + val |= HDMI_INFOFRAME_HEADER_LEN(*ptr++); + writel(val, hdmi->regs + head_offset); + + /* + * Each subpack contains 4 bytes + * The First Bytes of the first subpacket must contain the checksum + * Packet size in increase by one. + */ + for (i = 0; i < size; i += sizeof(u32)) { + size_t num; + + num = min_t(size_t, size - i, sizeof(u32)); + val = hdmi_infoframe_subpack(ptr, num); + ptr += sizeof(u32); + writel(val, hdmi->regs + pack_offset + i); + } + + /* Enable transmission slot for updated infoframe */ + val = hdmi_read(hdmi, HDMI_SW_DI_CFG); + val |= HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_FIELD, slot); + hdmi_write(hdmi, val, HDMI_SW_DI_CFG); +} + /** * Prepare and configure the AVI infoframe * @@ -243,8 +340,6 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi) struct drm_display_mode *mode = &hdmi->mode; struct hdmi_avi_infoframe infoframe; u8 buffer[HDMI_INFOFRAME_SIZE(AVI)]; - u8 *frame = buffer + HDMI_INFOFRAME_HEADER_SIZE; - u32 val; int ret; DRM_DEBUG_DRIVER("\n"); @@ -266,47 +361,43 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi) return ret; } - /* Disable transmission slot for AVI infoframe */ - val = hdmi_read(hdmi, HDMI_SW_DI_CFG); - val &= ~HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, HDMI_IFRAME_SLOT_AVI); - hdmi_write(hdmi, val, HDMI_SW_DI_CFG); + hdmi_infoframe_write_infopack(hdmi, buffer); - /* Infoframe header */ - val = buffer[0]; - val |= buffer[1] << 8; - val |= buffer[2] << 16; - hdmi_write(hdmi, val, HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AVI)); - - /* Infoframe packet bytes */ - val = buffer[3]; - val |= *(frame++) << 8; - val |= *(frame++) << 16; - val |= *(frame++) << 24; - hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AVI)); - - val = *(frame++); - val |= *(frame++) << 8; - val |= *(frame++) << 16; - val |= *(frame++) << 24; - hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD1(HDMI_IFRAME_SLOT_AVI)); - - val = *(frame++); - val |= *(frame++) << 8; - val |= *(frame++) << 16; - val |= *(frame++) << 24; - hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD2(HDMI_IFRAME_SLOT_AVI)); - - val = *(frame++); - val |= *(frame) << 8; - hdmi_write(hdmi, val, HDMI_SW_DI_N_PKT_WORD3(HDMI_IFRAME_SLOT_AVI)); - - /* Enable transmission slot for AVI infoframe - * According to the hdmi specification, AVI infoframe should be - * transmitted at least once per two video fields - */ - val = hdmi_read(hdmi, HDMI_SW_DI_CFG); - val |= HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_FIELD, HDMI_IFRAME_SLOT_AVI); - hdmi_write(hdmi, val, HDMI_SW_DI_CFG); + return 0; +} + +/** + * Prepare and configure the AUDIO infoframe + * + * AUDIO infoframe are transmitted once per frame and + * contains information about HDMI transmission mode such as audio codec, + * sample size, ... + * + * @hdmi: pointer on the hdmi internal structure + * + * Return negative value if error occurs + */ +static int hdmi_audio_infoframe_config(struct sti_hdmi *hdmi) +{ + struct hdmi_audio_infoframe infofame; + u8 buffer[HDMI_INFOFRAME_SIZE(AUDIO)]; + int ret; + + ret = hdmi_audio_infoframe_init(&infofame); + if (ret < 0) { + DRM_ERROR("failed to setup audio infoframe: %d\n", ret); + return ret; + } + + infofame.channels = 2; + + ret = hdmi_audio_infoframe_pack(&infofame, buffer, sizeof(buffer)); + if (ret < 0) { + DRM_ERROR("failed to pack audio infoframe: %d\n", ret); + return ret; + } + + hdmi_infoframe_write_infopack(hdmi, buffer); return 0; } @@ -427,6 +518,10 @@ static void sti_hdmi_pre_enable(struct drm_bridge *bridge) if (hdmi_avi_infoframe_config(hdmi)) DRM_ERROR("Unable to configure AVI infoframe\n"); + /* Program AUDIO infoframe */ + if (hdmi_audio_infoframe_config(hdmi)) + DRM_ERROR("Unable to configure AUDIO infoframe\n"); + /* Sw reset */ hdmi_swreset(hdmi); } From 5d8591bc0fbaeb6deda6ee478577e9c4d9b10c2b Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Fri, 6 Feb 2015 15:09:57 +1030 Subject: [PATCH 2727/3023] module: set ksymtab/kcrctab* section addresses to 0x0 These __ksymtab*/__kcrctab* sections currently have non-zero addresses. Non-zero section addresses in a relocatable ELF confuse GDB and it ends up not relocating all symbols when add-symbol-file is used on modules which have exports. The kernel's module loader does not care about these addresses, so let's just set them to zero. Before: $ readelf -S lib/notifier-error-inject.ko | grep 'Name\| __ksymtab_gpl' [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 8] __ksymtab_gpl PROGBITS 0000000c 0001b4 000010 00 A 0 0 4 (gdb) add-symbol-file lib/notifier-error-inject.ko 0x500000 -s .bss 0x700000 add symbol table from file "lib/notifier-error-inject.ko" at .text_addr = 0x500000 .bss_addr = 0x700000 (gdb) p ¬ifier_err_inject_dir $3 = (struct dentry **) 0x0 After: $ readelf -S lib/notifier-error-inject.ko | grep 'Name\| __ksymtab_gpl' [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 8] __ksymtab_gpl PROGBITS 00000000 0001b4 000010 00 A 0 0 4 (gdb) add-symbol-file lib/notifier-error-inject.ko 0x500000 -s .bss 0x700000 add symbol table from file "lib/notifier-error-inject.ko" at .text_addr = 0x500000 .bss_addr = 0x700000 (gdb) p ¬ifier_err_inject_dir $3 = (struct dentry **) 0x700000 Signed-off-by: Rabin Vincent Signed-off-by: Rusty Russell --- scripts/module-common.lds | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/scripts/module-common.lds b/scripts/module-common.lds index 0865b3e752be8f..bec15f908fc6d9 100644 --- a/scripts/module-common.lds +++ b/scripts/module-common.lds @@ -6,14 +6,14 @@ SECTIONS { /DISCARD/ : { *(.discard) } - __ksymtab : { *(SORT(___ksymtab+*)) } - __ksymtab_gpl : { *(SORT(___ksymtab_gpl+*)) } - __ksymtab_unused : { *(SORT(___ksymtab_unused+*)) } - __ksymtab_unused_gpl : { *(SORT(___ksymtab_unused_gpl+*)) } - __ksymtab_gpl_future : { *(SORT(___ksymtab_gpl_future+*)) } - __kcrctab : { *(SORT(___kcrctab+*)) } - __kcrctab_gpl : { *(SORT(___kcrctab_gpl+*)) } - __kcrctab_unused : { *(SORT(___kcrctab_unused+*)) } - __kcrctab_unused_gpl : { *(SORT(___kcrctab_unused_gpl+*)) } - __kcrctab_gpl_future : { *(SORT(___kcrctab_gpl_future+*)) } + __ksymtab 0 : { *(SORT(___ksymtab+*)) } + __ksymtab_gpl 0 : { *(SORT(___ksymtab_gpl+*)) } + __ksymtab_unused 0 : { *(SORT(___ksymtab_unused+*)) } + __ksymtab_unused_gpl 0 : { *(SORT(___ksymtab_unused_gpl+*)) } + __ksymtab_gpl_future 0 : { *(SORT(___ksymtab_gpl_future+*)) } + __kcrctab 0 : { *(SORT(___kcrctab+*)) } + __kcrctab_gpl 0 : { *(SORT(___kcrctab_gpl+*)) } + __kcrctab_unused 0 : { *(SORT(___kcrctab_unused+*)) } + __kcrctab_unused_gpl 0 : { *(SORT(___kcrctab_unused_gpl+*)) } + __kcrctab_gpl_future 0 : { *(SORT(___kcrctab_gpl_future+*)) } } From de96d79f343321d26ff920af25fcefe6895ca544 Mon Sep 17 00:00:00 2001 From: Andrey Tsyvarev Date: Fri, 6 Feb 2015 15:09:57 +1030 Subject: [PATCH 2728/3023] kernel/module.c: Free lock-classes if parse_args failed parse_args call module parameters' .set handlers, which may use locks defined in the module. So, these classes should be freed in case parse_args returns error(e.g. due to incorrect parameter passed). Signed-off-by: Andrey Tsyvarev Signed-off-by: Rusty Russell --- kernel/module.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/module.c b/kernel/module.c index d856e96a3cce44..441ed3fc9c89cc 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -3356,6 +3356,9 @@ static int load_module(struct load_info *info, const char __user *uargs, module_bug_cleanup(mod); mutex_unlock(&module_mutex); + /* Free lock-classes: */ + lockdep_free_key_range(mod->module_core, mod->core_size); + /* we can't deallocate the module until we clear memory protection */ unset_module_init_ro_nx(mod); unset_module_core_ro_nx(mod); From ab92ebbb8e10d402f4fe73c6b3d85be72614f1fa Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 6 Feb 2015 15:09:57 +1030 Subject: [PATCH 2729/3023] module: Remove double spaces in module verification taint message The warning message when loading modules with a wrong signature has two spaces in it: "module verification failed: signature and/or required key missing" Signed-off-by: Marcel Holtmann Signed-off-by: Rusty Russell --- kernel/module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/module.c b/kernel/module.c index 441ed3fc9c89cc..2461370813b31e 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -3265,7 +3265,7 @@ static int load_module(struct load_info *info, const char __user *uargs, mod->sig_ok = info->sig_ok; if (!mod->sig_ok) { pr_notice_once("%s: module verification failed: signature " - "and/or required key missing - tainting " + "and/or required key missing - tainting " "kernel\n", mod->name); add_taint_module(mod, TAINT_UNSIGNED_MODULE, LOCKDEP_STILL_OK); } From cbed8388bfd613da631cf3c1940ba3c8a34a915b Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Fri, 23 May 2014 12:12:04 +0100 Subject: [PATCH 2730/3023] arm: realview: specify PMU types Now that we can specify which PMU variant we're likely to deal with, do so in the realview board code. This will allow us to split the ARMv6, ARMv7, and XScale PMU drivers. The Realview EB may be used with ARMv6 or ARMv7 CPUs, but luckily there's only a single ARMv7 CPU, so we can match that explicitly to determine whether or not we have an ARMv7 PMU. Signed-off-by: Mark Rutland Acked-by: Linus Walleij Cc: Arnd Bergmann Cc: Olof Johansson Cc: Russell King Signed-off-by: Olof Johansson --- arch/arm/mach-realview/realview_eb.c | 3 ++- arch/arm/mach-realview/realview_pb1176.c | 2 +- arch/arm/mach-realview/realview_pb11mp.c | 2 +- arch/arm/mach-realview/realview_pba8.c | 2 +- arch/arm/mach-realview/realview_pbx.c | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index 739d4f11309773..64c88d657f9efc 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -296,7 +297,6 @@ static struct resource pmu_resources[] = { }; static struct platform_device pmu_device = { - .name = "arm-pmu", .id = -1, .num_resources = ARRAY_SIZE(pmu_resources), .resource = pmu_resources, @@ -451,6 +451,7 @@ static void __init realview_eb_init(void) */ l2x0_init(__io_address(REALVIEW_EB11MP_L220_BASE), 0x00790000, 0xfe000fff); #endif + pmu_device.name = core_tile_a9mp() ? "armv7-pmu" : "armv6-pmu"; platform_device_register(&pmu_device); } diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c index b0e0dcaed94485..ce92c182349468 100644 --- a/arch/arm/mach-realview/realview_pb1176.c +++ b/arch/arm/mach-realview/realview_pb1176.c @@ -280,7 +280,7 @@ static struct resource pmu_resource = { }; static struct platform_device pmu_device = { - .name = "arm-pmu", + .name = "armv6-pmu", .id = -1, .num_resources = 1, .resource = &pmu_resource, diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c index 47bf55fdbf27d9..15c45e25095f58 100644 --- a/arch/arm/mach-realview/realview_pb11mp.c +++ b/arch/arm/mach-realview/realview_pb11mp.c @@ -262,7 +262,7 @@ static struct resource pmu_resources[] = { }; static struct platform_device pmu_device = { - .name = "arm-pmu", + .name = "armv6-pmu", .id = -1, .num_resources = ARRAY_SIZE(pmu_resources), .resource = pmu_resources, diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c index 4e57a8599265b6..4c64662f54370f 100644 --- a/arch/arm/mach-realview/realview_pba8.c +++ b/arch/arm/mach-realview/realview_pba8.c @@ -240,7 +240,7 @@ static struct resource pmu_resource = { }; static struct platform_device pmu_device = { - .name = "arm-pmu", + .name = "armv7-pmu", .id = -1, .num_resources = 1, .resource = &pmu_resource, diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c index d89eb40234674e..9a22b864219f32 100644 --- a/arch/arm/mach-realview/realview_pbx.c +++ b/arch/arm/mach-realview/realview_pbx.c @@ -280,7 +280,7 @@ static struct resource pmu_resources[] = { }; static struct platform_device pmu_device = { - .name = "arm-pmu", + .name = "armv7-pmu", .id = -1, .num_resources = ARRAY_SIZE(pmu_resources), .resource = pmu_resources, From f9eff219761338402b5e109bfdb2daa9f6b30b8c Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Fri, 23 May 2014 12:27:37 +0100 Subject: [PATCH 2731/3023] arm: pxa: specify PMUs are for XScale CPUs Now that we can specify which PMU variant we're likely to deal with, do so in the pxa board code. This will allow us to split the ARMv6, ARMv7, and XScale PMU drivers. Signed-off-by: Mark Rutland Acked-by: Robert Jarzmik Cc: Arnd Bergmann Cc: Daniel Mack Cc: Haojian Zhuang Cc: Olof Johansson Signed-off-by: Olof Johansson --- arch/arm/mach-pxa/devices.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c index ac7b3eabbd858e..35434662dc7c2f 100644 --- a/arch/arm/mach-pxa/devices.c +++ b/arch/arm/mach-pxa/devices.c @@ -40,7 +40,7 @@ static struct resource pxa_resource_pmu = { }; struct platform_device pxa_device_pmu = { - .name = "arm-pmu", + .name = "xscale-pmu", .id = -1, .resource = &pxa_resource_pmu, .num_resources = 1, From b22a75cf9d9dfc0193fbd1251acf1925872a5be3 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Fri, 23 May 2014 14:39:39 +0100 Subject: [PATCH 2732/3023] arm: iop: specify PMUs are for XScale CPUs Now that we can specify which PMU variant we're likely to deal with, do so in the iop board code. This will allow us to split the ARMv6, ARMv7, and XScale PMU drivers. Signed-off-by: Mark Rutland Acked-by: Linus Walleij Cc: Arnd Bergmann Cc: Olof Johansson Cc: Russell King Signed-off-by: Olof Johansson --- arch/arm/plat-iop/pmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/plat-iop/pmu.c b/arch/arm/plat-iop/pmu.c index ad9f9744a82d12..c6d979ace52491 100644 --- a/arch/arm/plat-iop/pmu.c +++ b/arch/arm/plat-iop/pmu.c @@ -24,7 +24,7 @@ static struct resource pmu_resource = { }; static struct platform_device pmu_device = { - .name = "arm-pmu", + .name = "xscale-pmu", .id = -1, .resource = &pmu_resource, .num_resources = 1, From 744503b35a467ca89546906dba16d30de8d3b171 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Fri, 23 May 2014 14:51:50 +0100 Subject: [PATCH 2733/3023] arm: shmobile: specify PMUs are for ARMv7 CPUs Now that we can specify which PMU variant we're likely to deal with, do so in the shmobile board code. This will allow us to split the ARMv6, ARMv7, and XScale PMU drivers Signed-off-by: Mark Rutland Tested-by: Simon Horman Acked-by: Simon Horman Cc: Arnd Bergmann Cc: Magnus Damm Cc: Olof Johansson Signed-off-by: Olof Johansson --- arch/arm/mach-shmobile/setup-r8a7740.c | 2 +- arch/arm/mach-shmobile/setup-sh73a0.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c index 79ad93dfdae4ee..6edde2f3fb382d 100644 --- a/arch/arm/mach-shmobile/setup-r8a7740.c +++ b/arch/arm/mach-shmobile/setup-r8a7740.c @@ -656,7 +656,7 @@ static struct resource pmu_resources[] = { }; static struct platform_device pmu_device = { - .name = "arm-pmu", + .name = "armv7-pmu", .id = -1, .num_resources = ARRAY_SIZE(pmu_resources), .resource = pmu_resources, diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c index 93ebe3430bfe70..bdfa7a56ee7d2a 100644 --- a/arch/arm/mach-shmobile/setup-sh73a0.c +++ b/arch/arm/mach-shmobile/setup-sh73a0.c @@ -563,7 +563,7 @@ static struct resource pmu_resources[] = { }; static struct platform_device pmu_device = { - .name = "arm-pmu", + .name = "armv7-pmu", .id = -1, .num_resources = ARRAY_SIZE(pmu_resources), .resource = pmu_resources, From 279806bfca71c5f7893da59a5a7e7b65250260c8 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Fri, 23 May 2014 15:13:39 +0100 Subject: [PATCH 2734/3023] arm: omap: specify PMUs are for ARMv7 CPUs Now that we can specify which PMU variant we're likely to deal with, do so in the omap board code. This will allow us to split the ARMv6, ARMv7, and XScale PMU drivers. The unnecessary include of asm/pmu.h is also removed. Signed-off-by: Mark Rutland Acked-by: Tony Lindgren Cc: Arnd Bergmann Cc: Olof Johansson Signed-off-by: Olof Johansson --- arch/arm/mach-omap2/pmu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/pmu.c b/arch/arm/mach-omap2/pmu.c index 33c8846b419358..a69e9a33cb6d1c 100644 --- a/arch/arm/mach-omap2/pmu.c +++ b/arch/arm/mach-omap2/pmu.c @@ -13,7 +13,7 @@ */ #include -#include +#include #include "soc.h" #include "omap_hwmod.h" @@ -37,7 +37,8 @@ static int __init omap2_init_pmu(unsigned oh_num, char *oh_names[]) { int i; struct omap_hwmod *oh[3]; - char *dev_name = "arm-pmu"; + char *dev_name = cpu_architecture() == CPU_ARCH_ARMv6 ? + "armv6-pmu" : "armv7-pmu"; if ((!oh_num) || (oh_num > 3)) return -EINVAL; From 41e229a91207afc326f9a83ba33c098c8362d303 Mon Sep 17 00:00:00 2001 From: Barry Song Date: Tue, 3 Feb 2015 23:38:09 +0800 Subject: [PATCH 2735/3023] ARM: sirf: drop redundant function and marco declaration with the patchset to add CSR atlas7 support, the below stuff has no user now: SIRFSOC_VA sirfsoc_map_lluart sirfsoc_map_scu the related patches missed to drop them. Signed-off-by: Barry Song Signed-off-by: Olof Johansson --- arch/arm/mach-prima2/common.h | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/arch/arm/mach-prima2/common.h b/arch/arm/mach-prima2/common.h index 07d3e5ed9264f2..3916a6665100ef 100644 --- a/arch/arm/mach-prima2/common.h +++ b/arch/arm/mach-prima2/common.h @@ -15,9 +15,6 @@ #include #include -#define SIRFSOC_VA_BASE _AC(0xFEC00000, UL) -#define SIRFSOC_VA(x) (SIRFSOC_VA_BASE + ((x) & 0x00FFF000)) - extern struct smp_operations sirfsoc_smp_ops; extern void sirfsoc_secondary_startup(void); extern void sirfsoc_cpu_die(unsigned int cpu); @@ -25,18 +22,6 @@ extern void sirfsoc_cpu_die(unsigned int cpu); extern void __init sirfsoc_of_irq_init(void); extern asmlinkage void __exception_irq_entry sirfsoc_handle_irq(struct pt_regs *regs); -#ifndef CONFIG_DEBUG_LL -static inline void sirfsoc_map_lluart(void) {} -#else -extern void __init sirfsoc_map_lluart(void); -#endif - -#ifndef CONFIG_SMP -static inline void sirfsoc_map_scu(void) {} -#else -extern void sirfsoc_map_scu(void); -#endif - #ifdef CONFIG_SUSPEND extern int sirfsoc_pm_init(void); #else From f7819512996361280b86259222456fcf15aad926 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 4 Feb 2015 18:20:58 +0100 Subject: [PATCH 2736/3023] kvm: add halt_poll_ns module parameter This patch introduces a new module parameter for the KVM module; when it is present, KVM attempts a bit of polling on every HLT before scheduling itself out via kvm_vcpu_block. This parameter helps a lot for latency-bound workloads---in particular I tested it with O_DSYNC writes with a battery-backed disk in the host. In this case, writes are fast (because the data doesn't have to go all the way to the platters) but they cannot be merged by either the host or the guest. KVM's performance here is usually around 30% of bare metal, or 50% if you use cache=directsync or cache=writethrough (these parameters avoid that the guest sends pointless flush requests, and at the same time they are not slow because of the battery-backed cache). The bad performance happens because on every halt the host CPU decides to halt itself too. When the interrupt comes, the vCPU thread is then migrated to a new physical CPU, and in general the latency is horrible because the vCPU thread has to be scheduled back in. With this patch performance reaches 60-65% of bare metal and, more important, 99% of what you get if you use idle=poll in the guest. This means that the tunable gets rid of this particular bottleneck, and more work can be done to improve performance in the kernel or QEMU. Of course there is some price to pay; every time an otherwise idle vCPUs is interrupted by an interrupt, it will poll unnecessarily and thus impose a little load on the host. The above results were obtained with a mostly random value of the parameter (500000), and the load was around 1.5-2.5% CPU usage on one of the host's core for each idle guest vCPU. The patch also adds a new stat, /sys/kernel/debug/kvm/halt_successful_poll, that can be used to tune the parameter. It counts how many HLT instructions received an interrupt during the polling period; each successful poll avoids that Linux schedules the VCPU thread out and back in, and may also avoid a likely trip to C1 and back for the physical CPU. While the VM is idle, a Linux 4 VCPU VM halts around 10 times per second. Of these halts, almost all are failed polls. During the benchmark, instead, basically all halts end within the polling period, except a more or less constant stream of 50 per second coming from vCPUs that are not running the benchmark. The wasted time is thus very low. Things may be slightly different for Windows VMs, which have a ~10 ms timer tick. The effect is also visible on Marcelo's recently-introduced latency test for the TSC deadline timer. Though of course a non-RT kernel has awful latency bounds, the latency of the timer is around 8000-10000 clock cycles compared to 20000-120000 without setting halt_poll_ns. For the TSC deadline timer, thus, the effect is both a smaller average latency and a smaller variance. Signed-off-by: Paolo Bonzini --- arch/arm/include/asm/kvm_host.h | 1 + arch/arm64/include/asm/kvm_host.h | 1 + arch/mips/include/asm/kvm_host.h | 1 + arch/mips/kvm/mips.c | 1 + arch/powerpc/include/asm/kvm_host.h | 1 + arch/powerpc/kvm/book3s.c | 1 + arch/powerpc/kvm/booke.c | 1 + arch/s390/include/asm/kvm_host.h | 1 + arch/s390/kvm/kvm-s390.c | 1 + arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/x86.c | 1 + include/trace/events/kvm.h | 19 ++++++++++++ virt/kvm/kvm_main.c | 48 ++++++++++++++++++++++++----- 13 files changed, 71 insertions(+), 7 deletions(-) diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index bde494654bccb6..6a79314bc1dfcf 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -148,6 +148,7 @@ struct kvm_vm_stat { }; struct kvm_vcpu_stat { + u32 halt_successful_poll; u32 halt_wakeup; }; diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 2c49aa4ac81859..8efde89613f262 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -165,6 +165,7 @@ struct kvm_vm_stat { }; struct kvm_vcpu_stat { + u32 halt_successful_poll; u32 halt_wakeup; }; diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h index f2c249796ea8ba..ac4fc716062b79 100644 --- a/arch/mips/include/asm/kvm_host.h +++ b/arch/mips/include/asm/kvm_host.h @@ -120,6 +120,7 @@ struct kvm_vcpu_stat { u32 resvd_inst_exits; u32 break_inst_exits; u32 flush_dcache_exits; + u32 halt_successful_poll; u32 halt_wakeup; }; diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c index e97b907840311d..c9eccf5df91203 100644 --- a/arch/mips/kvm/mips.c +++ b/arch/mips/kvm/mips.c @@ -49,6 +49,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { { "resvd_inst", VCPU_STAT(resvd_inst_exits), KVM_STAT_VCPU }, { "break_inst", VCPU_STAT(break_inst_exits), KVM_STAT_VCPU }, { "flush_dcache", VCPU_STAT(flush_dcache_exits), KVM_STAT_VCPU }, + { "halt_successful_poll", VCPU_STAT(halt_successful_poll), KVM_STAT_VCPU }, { "halt_wakeup", VCPU_STAT(halt_wakeup), KVM_STAT_VCPU }, {NULL} }; diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 7efd666a3fa780..8ef05121d3cd90 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -107,6 +107,7 @@ struct kvm_vcpu_stat { u32 emulated_inst_exits; u32 dec_exits; u32 ext_intr_exits; + u32 halt_successful_poll; u32 halt_wakeup; u32 dbell_exits; u32 gdbell_exits; diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index 888bf466d8c6bb..cfbcdc65420195 100644 --- a/arch/powerpc/kvm/book3s.c +++ b/arch/powerpc/kvm/book3s.c @@ -52,6 +52,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { { "dec", VCPU_STAT(dec_exits) }, { "ext_intr", VCPU_STAT(ext_intr_exits) }, { "queue_intr", VCPU_STAT(queue_intr) }, + { "halt_successful_poll", VCPU_STAT(halt_successful_poll), }, { "halt_wakeup", VCPU_STAT(halt_wakeup) }, { "pf_storage", VCPU_STAT(pf_storage) }, { "sp_storage", VCPU_STAT(sp_storage) }, diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 9b55dec2d6cc11..6c1316a15a2729 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c @@ -62,6 +62,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { { "inst_emu", VCPU_STAT(emulated_inst_exits) }, { "dec", VCPU_STAT(dec_exits) }, { "ext_intr", VCPU_STAT(ext_intr_exits) }, + { "halt_successful_poll", VCPU_STAT(halt_successful_poll) }, { "halt_wakeup", VCPU_STAT(halt_wakeup) }, { "doorbell", VCPU_STAT(dbell_exits) }, { "guest doorbell", VCPU_STAT(gdbell_exits) }, diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index d1ecc7fd057904..f79058e3fd98f1 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h @@ -196,6 +196,7 @@ struct kvm_vcpu_stat { u32 exit_stop_request; u32 exit_validity; u32 exit_instruction; + u32 halt_successful_poll; u32 halt_wakeup; u32 instruction_lctl; u32 instruction_lctlg; diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index b2371c0fd1f8cb..1dbab2340a6623 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -51,6 +51,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { { "exit_instruction", VCPU_STAT(exit_instruction) }, { "exit_program_interruption", VCPU_STAT(exit_program_interruption) }, { "exit_instr_and_program_int", VCPU_STAT(exit_instr_and_program) }, + { "halt_successful_poll", VCPU_STAT(halt_successful_poll) }, { "halt_wakeup", VCPU_STAT(halt_wakeup) }, { "instruction_lctlg", VCPU_STAT(instruction_lctlg) }, { "instruction_lctl", VCPU_STAT(instruction_lctl) }, diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 848947ac6ade47..a236e39cc385a4 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -655,6 +655,7 @@ struct kvm_vcpu_stat { u32 irq_window_exits; u32 nmi_window_exits; u32 halt_exits; + u32 halt_successful_poll; u32 halt_wakeup; u32 request_irq_exits; u32 irq_exits; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 1373e04e1f19b1..bd7a70be41b35f 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -145,6 +145,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { { "irq_window", VCPU_STAT(irq_window_exits) }, { "nmi_window", VCPU_STAT(nmi_window_exits) }, { "halt_exits", VCPU_STAT(halt_exits) }, + { "halt_successful_poll", VCPU_STAT(halt_successful_poll) }, { "halt_wakeup", VCPU_STAT(halt_wakeup) }, { "hypercalls", VCPU_STAT(hypercalls) }, { "request_irq", VCPU_STAT(request_irq_exits) }, diff --git a/include/trace/events/kvm.h b/include/trace/events/kvm.h index 6edf1f2028cdb0..6bfe7eec1c2c78 100644 --- a/include/trace/events/kvm.h +++ b/include/trace/events/kvm.h @@ -37,6 +37,25 @@ TRACE_EVENT(kvm_userspace_exit, __entry->errno < 0 ? -__entry->errno : __entry->reason) ); +TRACE_EVENT(kvm_vcpu_wakeup, + TP_PROTO(__u64 ns, bool waited), + TP_ARGS(ns, waited), + + TP_STRUCT__entry( + __field( __u64, ns ) + __field( bool, waited ) + ), + + TP_fast_assign( + __entry->ns = ns; + __entry->waited = waited; + ), + + TP_printk("%s time %lld ns", + __entry->waited ? "wait" : "poll", + __entry->ns) +); + #if defined(CONFIG_HAVE_KVM_IRQFD) TRACE_EVENT(kvm_set_irq, TP_PROTO(unsigned int gsi, int level, int irq_source_id), diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 0c281760a1c5f7..32449e0e9aa8a0 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -66,6 +66,9 @@ MODULE_AUTHOR("Qumranet"); MODULE_LICENSE("GPL"); +unsigned int halt_poll_ns = 0; +module_param(halt_poll_ns, uint, S_IRUGO | S_IWUSR); + /* * Ordering of locks: * @@ -1813,29 +1816,60 @@ void mark_page_dirty(struct kvm *kvm, gfn_t gfn) } EXPORT_SYMBOL_GPL(mark_page_dirty); +static int kvm_vcpu_check_block(struct kvm_vcpu *vcpu) +{ + if (kvm_arch_vcpu_runnable(vcpu)) { + kvm_make_request(KVM_REQ_UNHALT, vcpu); + return -EINTR; + } + if (kvm_cpu_has_pending_timer(vcpu)) + return -EINTR; + if (signal_pending(current)) + return -EINTR; + + return 0; +} + /* * The vCPU has executed a HLT instruction with in-kernel mode enabled. */ void kvm_vcpu_block(struct kvm_vcpu *vcpu) { + ktime_t start, cur; DEFINE_WAIT(wait); + bool waited = false; + + start = cur = ktime_get(); + if (halt_poll_ns) { + ktime_t stop = ktime_add_ns(ktime_get(), halt_poll_ns); + do { + /* + * This sets KVM_REQ_UNHALT if an interrupt + * arrives. + */ + if (kvm_vcpu_check_block(vcpu) < 0) { + ++vcpu->stat.halt_successful_poll; + goto out; + } + cur = ktime_get(); + } while (single_task_running() && ktime_before(cur, stop)); + } for (;;) { prepare_to_wait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE); - if (kvm_arch_vcpu_runnable(vcpu)) { - kvm_make_request(KVM_REQ_UNHALT, vcpu); - break; - } - if (kvm_cpu_has_pending_timer(vcpu)) - break; - if (signal_pending(current)) + if (kvm_vcpu_check_block(vcpu) < 0) break; + waited = true; schedule(); } finish_wait(&vcpu->wq, &wait); + cur = ktime_get(); + +out: + trace_kvm_vcpu_wakeup(ktime_to_ns(cur) - ktime_to_ns(start), waited); } EXPORT_SYMBOL_GPL(kvm_vcpu_block); From 04427ec57480d83f98d8a8a326b831dfa474f297 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 2 Feb 2015 14:20:28 +0100 Subject: [PATCH 2737/3023] drm/exynos: add support for 'hdmi' clock Mixed need to have hdmi clock enabled to properly perform power on/off sequences, so add handling of this clock directly to the mixer driver. Dependency between hdmi clock and mixer module has been observed on Exynos4 based boards. Suggested-by: Andrzej Hajda Reviewed-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas Signed-off-by: Marek Szyprowski Signed-off-by: Inki Dae --- Documentation/devicetree/bindings/video/exynos_mixer.txt | 1 + drivers/gpu/drm/exynos/exynos_mixer.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/video/exynos_mixer.txt b/Documentation/devicetree/bindings/video/exynos_mixer.txt index 08b394b1edbfff..3e38128f866b1f 100644 --- a/Documentation/devicetree/bindings/video/exynos_mixer.txt +++ b/Documentation/devicetree/bindings/video/exynos_mixer.txt @@ -15,6 +15,7 @@ Required properties: a) mixer: Gate of Mixer IP bus clock. b) sclk_hdmi: HDMI Special clock, one of the two possible inputs of mixer mux. + c) hdmi: Gate of HDMI IP bus clock, needed together with sclk_hdmi. Example: diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index ed44cd4f01f764..1c65a3164ce0e6 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -72,6 +72,7 @@ struct mixer_resources { spinlock_t reg_slock; struct clk *mixer; struct clk *vp; + struct clk *hdmi; struct clk *sclk_mixer; struct clk *sclk_hdmi; struct clk *mout_mixer; @@ -769,6 +770,12 @@ static int mixer_resources_init(struct mixer_context *mixer_ctx) return -ENODEV; } + mixer_res->hdmi = devm_clk_get(dev, "hdmi"); + if (IS_ERR(mixer_res->hdmi)) { + dev_err(dev, "failed to get clock 'hdmi'\n"); + return PTR_ERR(mixer_res->hdmi); + } + mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi"); if (IS_ERR(mixer_res->sclk_hdmi)) { dev_err(dev, "failed to get clock 'sclk_hdmi'\n"); @@ -1092,6 +1099,7 @@ static void mixer_poweron(struct exynos_drm_crtc *crtc) pm_runtime_get_sync(ctx->dev); clk_prepare_enable(res->mixer); + clk_prepare_enable(res->hdmi); if (ctx->vp_enabled) { clk_prepare_enable(res->vp); if (ctx->has_sclk) @@ -1131,6 +1139,7 @@ static void mixer_poweroff(struct exynos_drm_crtc *crtc) ctx->powered = false; mutex_unlock(&ctx->mixer_mutex); + clk_disable_unprepare(res->hdmi); clk_disable_unprepare(res->mixer); if (ctx->vp_enabled) { clk_disable_unprepare(res->vp); From 8dcc14f82f06fce997e35f4c77ced9d4ed192f31 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 20 Jan 2015 15:31:14 +0100 Subject: [PATCH 2738/3023] drm/exynos: IOMMU support should not be selectable by user If system provides IOMMU feature, Exynos DRM should use it by default, because the Exynos DRM subdrivers don't work correctly when Exynos IOMMU driver has been enabled and no IOMMU support has been compiled into Exynos DRM driver. Signed-off-by: Marek Szyprowski Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/Kconfig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index c072999b7e0345..7cf0b46cd48b28 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -12,10 +12,9 @@ config DRM_EXYNOS If M is selected the module will be called exynosdrm. config DRM_EXYNOS_IOMMU - bool "EXYNOS DRM IOMMU Support" + bool depends on DRM_EXYNOS && EXYNOS_IOMMU && ARM_DMA_USE_IOMMU - help - Choose this option if you want to use IOMMU feature for DRM. + default y config DRM_EXYNOS_DMABUF bool "EXYNOS DRM DMABUF" From b74ea6a97e82b8230309a95c1266ce4b97254d54 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Wed, 4 Feb 2015 14:19:33 +0900 Subject: [PATCH 2739/3023] drm/exynos: remove DRM_EXYNOS_DMABUF config The exynos drm driver has DRIVER_PRIME capability, then it's reasonable to support dmabuf as default. Remove DRM_EXYNOS_DMABUF config, it will prevent that user selects the option unnecessarily. Signed-off-by: Joonyoung Shim Reviewed-by: Gustavo Padovan Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/Kconfig | 6 ------ drivers/gpu/drm/exynos/Makefile | 3 +-- drivers/gpu/drm/exynos/exynos_drm_dmabuf.h | 5 ----- 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 7cf0b46cd48b28..627aaa04776cb3 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -16,12 +16,6 @@ config DRM_EXYNOS_IOMMU depends on DRM_EXYNOS && EXYNOS_IOMMU && ARM_DMA_USE_IOMMU default y -config DRM_EXYNOS_DMABUF - bool "EXYNOS DRM DMABUF" - depends on DRM_EXYNOS - help - Choose this option if you want to use DMABUF feature for DRM. - config DRM_EXYNOS_FIMD bool "Exynos DRM FIMD" depends on DRM_EXYNOS && !FB_S3C diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile index 33ae3652b8da69..0856891f9bbfaa 100644 --- a/drivers/gpu/drm/exynos/Makefile +++ b/drivers/gpu/drm/exynos/Makefile @@ -6,10 +6,9 @@ ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/exynos exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o \ exynos_drm_crtc.o exynos_drm_fbdev.o exynos_drm_fb.o \ exynos_drm_buf.o exynos_drm_gem.o exynos_drm_core.o \ - exynos_drm_plane.o + exynos_drm_plane.o exynos_drm_dmabuf.o exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o -exynosdrm-$(CONFIG_DRM_EXYNOS_DMABUF) += exynos_drm_dmabuf.o exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o exynosdrm-$(CONFIG_DRM_EXYNOS_DPI) += exynos_drm_dpi.o exynosdrm-$(CONFIG_DRM_EXYNOS_DSI) += exynos_drm_dsi.o diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.h b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.h index 49acfafb4fdb60..886de9ff484dd6 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.h +++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.h @@ -12,14 +12,9 @@ #ifndef _EXYNOS_DRM_DMABUF_H_ #define _EXYNOS_DRM_DMABUF_H_ -#ifdef CONFIG_DRM_EXYNOS_DMABUF struct dma_buf *exynos_dmabuf_prime_export(struct drm_device *drm_dev, struct drm_gem_object *obj, int flags); struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev, struct dma_buf *dma_buf); -#else -#define exynos_dmabuf_prime_export NULL -#define exynos_dmabuf_prime_import NULL -#endif #endif From 9865df4d76bc674e7922c8bb279beb8435b8e888 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Tue, 27 Jan 2015 20:40:45 +0900 Subject: [PATCH 2740/3023] drm/exynos: remove to use unnecessary MODULE_xxx macro The exynos_drm_dmabuf.c file doesn't include any module feature and it isn't built to module. Signed-off-by: Joonyoung Shim Reviewed-by: Gustavo Padovan Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_dmabuf.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c index 60192ed544f0d0..3833bf8ca0258b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c @@ -279,7 +279,3 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev, return ERR_PTR(ret); } - -MODULE_AUTHOR("Inki Dae "); -MODULE_DESCRIPTION("Samsung SoC DRM DMABUF Module"); -MODULE_LICENSE("GPL"); From 0f04cf8df0b20a97369cb634663fef0578cbf273 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Fri, 30 Jan 2015 16:43:01 +0900 Subject: [PATCH 2741/3023] drm/exynos: fix wrong pipe calculation for crtc We get wrong pipe value for crtc since commit 93bca243ec96 ("drm/exynos: remove struct exynos_drm_manager"). We should should increase pipe value before call exynos_drm_crtc_create. Signed-off-by: Joonyoung Shim Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 13 +++++++------ drivers/gpu/drm/exynos/exynos_drm_vidi.c | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 682806ef4d337e..39f7fa7b8d3469 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -1065,18 +1065,19 @@ static int fimd_bind(struct device *dev, struct device *master, void *data) struct drm_device *drm_dev = data; int ret; - ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe, - EXYNOS_DISPLAY_TYPE_LCD, - &fimd_crtc_ops, ctx); - if (IS_ERR(ctx->crtc)) - return PTR_ERR(ctx->crtc); - ret = fimd_ctx_initialize(ctx, drm_dev); if (ret) { DRM_ERROR("fimd_ctx_initialize failed.\n"); return ret; } + ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe, + EXYNOS_DISPLAY_TYPE_LCD, + &fimd_crtc_ops, ctx); + if (IS_ERR(ctx->crtc)) { + fimd_ctx_remove(ctx); + return PTR_ERR(ctx->crtc); + } if (ctx->display) exynos_drm_create_enc_conn(drm_dev, ctx->display); diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index 9c8300edd34843..fb68d3c997c1b5 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -548,6 +548,8 @@ static int vidi_bind(struct device *dev, struct device *master, void *data) struct drm_device *drm_dev = data; int ret; + vidi_ctx_initialize(ctx, drm_dev); + ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe, EXYNOS_DISPLAY_TYPE_VIDI, &vidi_crtc_ops, ctx); @@ -556,8 +558,6 @@ static int vidi_bind(struct device *dev, struct device *master, void *data) return PTR_ERR(ctx->crtc); } - vidi_ctx_initialize(ctx, drm_dev); - ret = exynos_drm_create_enc_conn(drm_dev, &ctx->display); if (ret) { ctx->crtc->base.funcs->destroy(&ctx->crtc->base); From 92dc7a047b02be447a51baa93deb0c0f694241a5 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Fri, 30 Jan 2015 16:43:02 +0900 Subject: [PATCH 2742/3023] drm/exynos: use driver internal struct Use driver internal struct as argument instead of struct exynos_drm_crtc except functions of exynos_drm_crtc_ops and instead of struct exynos_drm_display except functions of exynos_drm_display_ops. It can reduce unnecessary variable declaration. Signed-off-by: Joonyoung Shim Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_dp_core.c | 14 +++----- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 43 ++++++++++-------------- drivers/gpu/drm/exynos/exynos_drm_vidi.c | 19 +++++------ drivers/gpu/drm/exynos/exynos_hdmi.c | 12 +++---- drivers/gpu/drm/exynos/exynos_mixer.c | 26 ++++++-------- 5 files changed, 47 insertions(+), 67 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c index 46f149737bc8d4..bf17a60b40edc8 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.c +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c @@ -1058,10 +1058,8 @@ static void exynos_dp_phy_exit(struct exynos_dp_device *dp) phy_power_off(dp->phy); } -static void exynos_dp_poweron(struct exynos_drm_display *display) +static void exynos_dp_poweron(struct exynos_dp_device *dp) { - struct exynos_dp_device *dp = display_to_dp(display); - if (dp->dpms_mode == DRM_MODE_DPMS_ON) return; @@ -1076,13 +1074,11 @@ static void exynos_dp_poweron(struct exynos_drm_display *display) exynos_dp_phy_init(dp); exynos_dp_init_dp(dp); enable_irq(dp->irq); - exynos_dp_commit(display); + exynos_dp_commit(&dp->display); } -static void exynos_dp_poweroff(struct exynos_drm_display *display) +static void exynos_dp_poweroff(struct exynos_dp_device *dp) { - struct exynos_dp_device *dp = display_to_dp(display); - if (dp->dpms_mode != DRM_MODE_DPMS_ON) return; @@ -1110,12 +1106,12 @@ static void exynos_dp_dpms(struct exynos_drm_display *display, int mode) switch (mode) { case DRM_MODE_DPMS_ON: - exynos_dp_poweron(display); + exynos_dp_poweron(dp); break; case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: - exynos_dp_poweroff(display); + exynos_dp_poweroff(dp); break; default: break; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 39f7fa7b8d3469..925fc69af1a0c2 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -253,9 +253,8 @@ static void fimd_enable_shadow_channel_path(struct fimd_context *ctx, int win, writel(val, ctx->regs + SHADOWCON); } -static void fimd_clear_channel(struct exynos_drm_crtc *crtc) +static void fimd_clear_channel(struct fimd_context *ctx) { - struct fimd_context *ctx = crtc->ctx; int win, ch_enabled = 0; DRM_DEBUG_KMS("%s\n", __FILE__); @@ -280,7 +279,7 @@ static void fimd_clear_channel(struct exynos_drm_crtc *crtc) unsigned int state = ctx->suspended; ctx->suspended = 0; - fimd_wait_for_vblank(crtc); + fimd_wait_for_vblank(ctx->crtc); ctx->suspended = state; } } @@ -302,7 +301,7 @@ static int fimd_ctx_initialize(struct fimd_context *ctx, * If any channel is already active, iommu will throw * a PAGE FAULT when enabled. So clear any channel if enabled. */ - fimd_clear_channel(ctx->crtc); + fimd_clear_channel(ctx); ret = drm_iommu_attach_device(ctx->drm_dev, ctx->dev); if (ret) { DRM_ERROR("drm_iommu_attach failed.\n"); @@ -823,9 +822,8 @@ static void fimd_win_disable(struct exynos_drm_crtc *crtc, int zpos) win_data->enabled = false; } -static void fimd_window_suspend(struct exynos_drm_crtc *crtc) +static void fimd_window_suspend(struct fimd_context *ctx) { - struct fimd_context *ctx = crtc->ctx; struct fimd_win_data *win_data; int i; @@ -833,13 +831,12 @@ static void fimd_window_suspend(struct exynos_drm_crtc *crtc) win_data = &ctx->win_data[i]; win_data->resume = win_data->enabled; if (win_data->enabled) - fimd_win_disable(crtc, i); + fimd_win_disable(ctx->crtc, i); } } -static void fimd_window_resume(struct exynos_drm_crtc *crtc) +static void fimd_window_resume(struct fimd_context *ctx) { - struct fimd_context *ctx = crtc->ctx; struct fimd_win_data *win_data; int i; @@ -850,26 +847,24 @@ static void fimd_window_resume(struct exynos_drm_crtc *crtc) } } -static void fimd_apply(struct exynos_drm_crtc *crtc) +static void fimd_apply(struct fimd_context *ctx) { - struct fimd_context *ctx = crtc->ctx; struct fimd_win_data *win_data; int i; for (i = 0; i < WINDOWS_NR; i++) { win_data = &ctx->win_data[i]; if (win_data->enabled) - fimd_win_commit(crtc, i); + fimd_win_commit(ctx->crtc, i); else - fimd_win_disable(crtc, i); + fimd_win_disable(ctx->crtc, i); } - fimd_commit(crtc); + fimd_commit(ctx->crtc); } -static int fimd_poweron(struct exynos_drm_crtc *crtc) +static int fimd_poweron(struct fimd_context *ctx) { - struct fimd_context *ctx = crtc->ctx; int ret; if (!ctx->suspended) @@ -893,16 +888,16 @@ static int fimd_poweron(struct exynos_drm_crtc *crtc) /* if vblank was enabled status, enable it again. */ if (test_and_clear_bit(0, &ctx->irq_flags)) { - ret = fimd_enable_vblank(crtc); + ret = fimd_enable_vblank(ctx->crtc); if (ret) { DRM_ERROR("Failed to re-enable vblank [%d]\n", ret); goto enable_vblank_err; } } - fimd_window_resume(crtc); + fimd_window_resume(ctx); - fimd_apply(crtc); + fimd_apply(ctx); return 0; @@ -915,10 +910,8 @@ static int fimd_poweron(struct exynos_drm_crtc *crtc) return ret; } -static int fimd_poweroff(struct exynos_drm_crtc *crtc) +static int fimd_poweroff(struct fimd_context *ctx) { - struct fimd_context *ctx = crtc->ctx; - if (ctx->suspended) return 0; @@ -927,7 +920,7 @@ static int fimd_poweroff(struct exynos_drm_crtc *crtc) * suspend that connector. Otherwise we might try to scan from * a destroyed buffer later. */ - fimd_window_suspend(crtc); + fimd_window_suspend(ctx); clk_disable_unprepare(ctx->lcd_clk); clk_disable_unprepare(ctx->bus_clk); @@ -944,12 +937,12 @@ static void fimd_dpms(struct exynos_drm_crtc *crtc, int mode) switch (mode) { case DRM_MODE_DPMS_ON: - fimd_poweron(crtc); + fimd_poweron(crtc->ctx); break; case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: - fimd_poweroff(crtc); + fimd_poweroff(crtc->ctx); break; default: DRM_DEBUG_KMS("unspecified mode %d\n", mode); diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index fb68d3c997c1b5..b886972b5888e4 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -97,17 +97,16 @@ static const char fake_edid_info[] = { 0x00, 0x00, 0x00, 0x06 }; -static void vidi_apply(struct exynos_drm_crtc *crtc) +static void vidi_apply(struct vidi_context *ctx) { - struct vidi_context *ctx = crtc->ctx; - struct exynos_drm_crtc_ops *crtc_ops = crtc->ops; + struct exynos_drm_crtc_ops *crtc_ops = ctx->crtc->ops; struct vidi_win_data *win_data; int i; for (i = 0; i < WINDOWS_NR; i++) { win_data = &ctx->win_data[i]; if (win_data->enabled && (crtc_ops && crtc_ops->win_commit)) - crtc_ops->win_commit(crtc, i); + crtc_ops->win_commit(ctx->crtc, i); } } @@ -240,10 +239,8 @@ static void vidi_win_disable(struct exynos_drm_crtc *crtc, int zpos) /* TODO. */ } -static int vidi_power_on(struct exynos_drm_crtc *crtc, bool enable) +static int vidi_power_on(struct vidi_context *ctx, bool enable) { - struct vidi_context *ctx = crtc->ctx; - DRM_DEBUG_KMS("%s\n", __FILE__); if (enable != false && enable != true) @@ -254,9 +251,9 @@ static int vidi_power_on(struct exynos_drm_crtc *crtc, bool enable) /* if vblank was enabled status, enable it again. */ if (test_and_clear_bit(0, &ctx->irq_flags)) - vidi_enable_vblank(crtc); + vidi_enable_vblank(ctx->crtc); - vidi_apply(crtc); + vidi_apply(ctx); } else { ctx->suspended = true; } @@ -274,12 +271,12 @@ static void vidi_dpms(struct exynos_drm_crtc *crtc, int mode) switch (mode) { case DRM_MODE_DPMS_ON: - vidi_power_on(crtc, true); + vidi_power_on(ctx, true); break; case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: - vidi_power_on(crtc, false); + vidi_power_on(ctx, false); break; default: DRM_DEBUG_KMS("unspecified mode %d\n", mode); diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 98051e8e855a1f..229b3613c60b42 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -2032,9 +2032,8 @@ static void hdmi_commit(struct exynos_drm_display *display) hdmi_conf_apply(hdata); } -static void hdmi_poweron(struct exynos_drm_display *display) +static void hdmi_poweron(struct hdmi_context *hdata) { - struct hdmi_context *hdata = display_to_hdmi(display); struct hdmi_resources *res = &hdata->res; mutex_lock(&hdata->hdmi_mutex); @@ -2060,12 +2059,11 @@ static void hdmi_poweron(struct exynos_drm_display *display) clk_prepare_enable(res->sclk_hdmi); hdmiphy_poweron(hdata); - hdmi_commit(display); + hdmi_commit(&hdata->display); } -static void hdmi_poweroff(struct exynos_drm_display *display) +static void hdmi_poweroff(struct hdmi_context *hdata) { - struct hdmi_context *hdata = display_to_hdmi(display); struct hdmi_resources *res = &hdata->res; mutex_lock(&hdata->hdmi_mutex); @@ -2109,7 +2107,7 @@ static void hdmi_dpms(struct exynos_drm_display *display, int mode) switch (mode) { case DRM_MODE_DPMS_ON: - hdmi_poweron(display); + hdmi_poweron(hdata); break; case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: @@ -2128,7 +2126,7 @@ static void hdmi_dpms(struct exynos_drm_display *display, int mode) if (funcs && funcs->dpms) (*funcs->dpms)(crtc, mode); - hdmi_poweroff(display); + hdmi_poweroff(hdata); break; default: DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode); diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 1c65a3164ce0e6..75b47da6c66c49 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -1054,23 +1054,21 @@ static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc) drm_vblank_put(mixer_ctx->drm_dev, mixer_ctx->pipe); } -static void mixer_window_suspend(struct exynos_drm_crtc *crtc) +static void mixer_window_suspend(struct mixer_context *ctx) { - struct mixer_context *ctx = crtc->ctx; struct hdmi_win_data *win_data; int i; for (i = 0; i < MIXER_WIN_NR; i++) { win_data = &ctx->win_data[i]; win_data->resume = win_data->enabled; - mixer_win_disable(crtc, i); + mixer_win_disable(ctx->crtc, i); } - mixer_wait_for_vblank(crtc); + mixer_wait_for_vblank(ctx->crtc); } -static void mixer_window_resume(struct exynos_drm_crtc *crtc) +static void mixer_window_resume(struct mixer_context *ctx) { - struct mixer_context *ctx = crtc->ctx; struct hdmi_win_data *win_data; int i; @@ -1079,13 +1077,12 @@ static void mixer_window_resume(struct exynos_drm_crtc *crtc) win_data->enabled = win_data->resume; win_data->resume = false; if (win_data->enabled) - mixer_win_commit(crtc, i); + mixer_win_commit(ctx->crtc, i); } } -static void mixer_poweron(struct exynos_drm_crtc *crtc) +static void mixer_poweron(struct mixer_context *ctx) { - struct mixer_context *ctx = crtc->ctx; struct mixer_resources *res = &ctx->mixer_res; mutex_lock(&ctx->mixer_mutex); @@ -1115,12 +1112,11 @@ static void mixer_poweron(struct exynos_drm_crtc *crtc) mixer_reg_write(res, MXR_INT_EN, ctx->int_en); mixer_win_reset(ctx); - mixer_window_resume(crtc); + mixer_window_resume(ctx); } -static void mixer_poweroff(struct exynos_drm_crtc *crtc) +static void mixer_poweroff(struct mixer_context *ctx) { - struct mixer_context *ctx = crtc->ctx; struct mixer_resources *res = &ctx->mixer_res; mutex_lock(&ctx->mixer_mutex); @@ -1131,7 +1127,7 @@ static void mixer_poweroff(struct exynos_drm_crtc *crtc) mutex_unlock(&ctx->mixer_mutex); mixer_stop(ctx); - mixer_window_suspend(crtc); + mixer_window_suspend(ctx); ctx->int_en = mixer_reg_read(res, MXR_INT_EN); @@ -1154,12 +1150,12 @@ static void mixer_dpms(struct exynos_drm_crtc *crtc, int mode) { switch (mode) { case DRM_MODE_DPMS_ON: - mixer_poweron(crtc); + mixer_poweron(crtc->ctx); break; case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: - mixer_poweroff(crtc); + mixer_poweroff(crtc->ctx); break; default: DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode); From e2dc3f72eea7decdb56368f0de88bba343720828 Mon Sep 17 00:00:00 2001 From: Alban Browaeys Date: Thu, 29 Jan 2015 22:18:40 +0100 Subject: [PATCH 2743/3023] drm/exynos: fix no hdmi output The hdmi outputs black screen only even though under the hood Xorg and framebuffer console are fine : devices found and initialized, but not a pixel out. Commit 93bca243ec96 ("drm/exynos: remove struct exynos_drm_manager") changed the call order of mixer_initialize with regards to exynos_drm_crtc_create. This changes breaks hdmi out on Odroid U2 (linux-next with added Marek Szyprowski v4 hdmi patchset from linux-samsung-soc ML). Restore the previous call ordering get hdmi to ouput proper pixels: ie call mixer_initialize first then exynos_drm_crtc_create. Fixes: 93bca243ec96 ("drm/exynos: remove struct exynos_drm_manager") Signed-off-by: Alban Browaeys Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_mixer.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 75b47da6c66c49..0aa6cf447e9f4b 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -1254,18 +1254,19 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data) struct drm_device *drm_dev = data; int ret; + ret = mixer_initialize(ctx, drm_dev); + if (ret) + return ret; + ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe, EXYNOS_DISPLAY_TYPE_HDMI, &mixer_crtc_ops, ctx); if (IS_ERR(ctx->crtc)) { + mixer_ctx_remove(ctx); ret = PTR_ERR(ctx->crtc); goto free_ctx; } - ret = mixer_initialize(ctx, drm_dev); - if (ret) - goto free_ctx; - return 0; free_ctx: From 129046c6ecb662e902a241bbbcb1da4206986370 Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Fri, 30 Jan 2015 17:30:45 +0900 Subject: [PATCH 2744/3023] drm/exynos: hdmi: replace fb size with mode size from win commit For default graphic window, mixer_win_commit() sets display size register as fb size. Calling setplane with smaller fb size than mode size to default window causes distorted display result. So this patch replaces fb size with mode size for display size from the mixer_win_commit(). Signed-off-by: Seung-Woo Kim Acked-by: Joonyoung Shim Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_mixer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 0aa6cf447e9f4b..496c861f1a6168 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -583,8 +583,8 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win) /* setup display size */ if (ctx->mxr_ver == MXR_VER_128_0_0_184 && win == MIXER_DEFAULT_WIN) { - val = MXR_MXR_RES_HEIGHT(win_data->fb_height); - val |= MXR_MXR_RES_WIDTH(win_data->fb_width); + val = MXR_MXR_RES_HEIGHT(win_data->mode_height); + val |= MXR_MXR_RES_WIDTH(win_data->mode_width); mixer_reg_write(res, MXR_RESOLUTION, val); } From a5d7ac30fa9ffa923e3603309692a36e3b3b3ae1 Mon Sep 17 00:00:00 2001 From: Carlo Caione Date: Wed, 4 Feb 2015 10:23:19 +0100 Subject: [PATCH 2745/3023] drm/exynos: fix DMA_ATTR_NO_KERNEL_MAPPING usage The Exynos DRM driver doesn't follow the correct API when dealing with dma_{alloc, mmap, free}_attrs functions and the DMA_ATTR_NO_KERNEL_MAPPING attribute. When a IOMMU is not available and the DMA_ATTR_NO_KERNEL_MAPPING is used, the driver should use the pointer returned by dma_alloc_attr() as a cookie. The Exynos DRM driver directly uses the non-requested virtual kernel address returned by the DMA mapping subsystem. This just works now because the non-IOMMU codepath doesn't obey DMA_ATTR_NO_KERNEL_MAPPING but we need to fix it before fixing the DMA layer. Signed-off-by: Carlo Caione Acked-by: Marek Szyprowski Acked-by: Joonyoung Shim Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_buf.c | 6 ++--- drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 29 +++++++---------------- drivers/gpu/drm/exynos/exynos_drm_gem.h | 2 ++ 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.c b/drivers/gpu/drm/exynos/exynos_drm_buf.c index 9c8088462c26f9..24994ba10e28af 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_buf.c +++ b/drivers/gpu/drm/exynos/exynos_drm_buf.c @@ -63,11 +63,11 @@ static int lowlevel_buffer_allocate(struct drm_device *dev, return -ENOMEM; } - buf->kvaddr = (void __iomem *)dma_alloc_attrs(dev->dev, + buf->cookie = dma_alloc_attrs(dev->dev, buf->size, &buf->dma_addr, GFP_KERNEL, &buf->dma_attrs); - if (!buf->kvaddr) { + if (!buf->cookie) { DRM_ERROR("failed to allocate buffer.\n"); ret = -ENOMEM; goto err_free; @@ -132,7 +132,7 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev, buf->sgt = NULL; if (!is_drm_iommu_supported(dev)) { - dma_free_attrs(dev->dev, buf->size, buf->kvaddr, + dma_free_attrs(dev->dev, buf->size, buf->cookie, (dma_addr_t)buf->dma_addr, &buf->dma_attrs); drm_free_large(buf->pages); } else diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index e12ea90c62371e..84f8dfe1c5ec02 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -79,9 +79,9 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, struct drm_framebuffer *fb) { struct fb_info *fbi = helper->fbdev; - struct drm_device *dev = helper->dev; struct exynos_drm_gem_buf *buffer; unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3); + unsigned int nr_pages; unsigned long offset; drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); @@ -94,25 +94,14 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, return -EFAULT; } - /* map pages with kernel virtual space. */ + nr_pages = buffer->size >> PAGE_SHIFT; + + buffer->kvaddr = (void __iomem *) vmap(buffer->pages, + nr_pages, VM_MAP, + pgprot_writecombine(PAGE_KERNEL)); if (!buffer->kvaddr) { - if (is_drm_iommu_supported(dev)) { - unsigned int nr_pages = buffer->size >> PAGE_SHIFT; - - buffer->kvaddr = (void __iomem *) vmap(buffer->pages, - nr_pages, VM_MAP, - pgprot_writecombine(PAGE_KERNEL)); - } else { - phys_addr_t dma_addr = buffer->dma_addr; - if (dma_addr) - buffer->kvaddr = (void __iomem *)phys_to_virt(dma_addr); - else - buffer->kvaddr = (void __iomem *)NULL; - } - if (!buffer->kvaddr) { - DRM_ERROR("failed to map pages to kernel space.\n"); - return -EIO; - } + DRM_ERROR("failed to map pages to kernel space.\n"); + return -EIO; } /* buffer count to framebuffer always is 1 at booting time. */ @@ -313,7 +302,7 @@ static void exynos_drm_fbdev_destroy(struct drm_device *dev, struct exynos_drm_gem_obj *exynos_gem_obj = exynos_fbd->exynos_gem_obj; struct drm_framebuffer *fb; - if (is_drm_iommu_supported(dev) && exynos_gem_obj->buffer->kvaddr) + if (exynos_gem_obj->buffer->kvaddr) vunmap(exynos_gem_obj->buffer->kvaddr); /* release drm framebuffer and real buffer */ diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h index ec58fe9c40df58..308173cb4f0a0d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.h +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h @@ -22,6 +22,7 @@ /* * exynos drm gem buffer structure. * + * @cookie: cookie returned by dma_alloc_attrs * @kvaddr: kernel virtual address to allocated memory region. * *userptr: user space address. * @dma_addr: bus address(accessed by dma) to allocated memory region. @@ -35,6 +36,7 @@ * VM_PFNMAP or not. */ struct exynos_drm_gem_buf { + void *cookie; void __iomem *kvaddr; unsigned long userptr; dma_addr_t dma_addr; From 76925260a8edba2b62b1639d651b0f3072e7c01b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 28 Jan 2015 09:58:56 -0700 Subject: [PATCH 2746/3023] staging: comedi: addi_apci_1500: fix array access out of bounds error The private data 'pm', 'pt', and 'pp' array members hold the trigger mode parameters for ports A and B. Both ports are 8-bits and the arrays are 16-bits. Array index 0 defines the AND mode and index 1 the OR mode parameters for both ports. The valid triggers to start the async command are 0 to 3 which select the AND/OR mode for each port. The 'pb_trig' (the array index for port B) in apci1500_di_inttrig_start() is incorrect and results in an index of 0 or 2. Fix the calc so that the correct index (0/1) is used. Signed-off-by: H Hartley Sweeten Reported-by: Asaf Vertz Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/addi_apci_1500.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index fc7db1de0b9061..f15aa1f6b4762e 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -296,7 +296,7 @@ static int apci1500_di_inttrig_start(struct comedi_device *dev, unsigned int pa_mode = Z8536_PAB_MODE_PMS_DISABLE; unsigned int pb_mode = Z8536_PAB_MODE_PMS_DISABLE; unsigned int pa_trig = trig_num & 0x01; - unsigned int pb_trig = trig_num & 0x02; + unsigned int pb_trig = (trig_num >> 1) & 0x01; bool valid_trig = false; unsigned int val; From 14ae190aed8e711614e69d57985ad9fb6e0e8eb3 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Wed, 28 Jan 2015 23:37:01 +0100 Subject: [PATCH 2747/3023] staging: comedi: drivers: ni_atmio: Removed variables that is never used Variable ar assigned a value that is never used. I have also removed all the code that thereby serves no purpose. This was found using a static code analysis program called cppcheck Signed-off-by: Rickard Strandqvist Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_atmio.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c index 0c5ff287dcef64..301f154be8138a 100644 --- a/drivers/staging/comedi/drivers/ni_atmio.c +++ b/drivers/staging/comedi/drivers/ni_atmio.c @@ -300,7 +300,6 @@ static int ni_atmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct ni_board_struct *boardtype; - struct ni_private *devpriv; struct pnp_dev *isapnp_dev; int ret; unsigned long iobase; @@ -310,7 +309,6 @@ static int ni_atmio_attach(struct comedi_device *dev, ret = ni_alloc_private(dev); if (ret) return ret; - devpriv = dev->private; iobase = it->options[0]; irq = it->options[1]; From e876e3509701a3ff048725f44a85f7d420b4ec63 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Wed, 28 Jan 2015 23:37:40 +0100 Subject: [PATCH 2748/3023] staging: comedi: drivers: ni_mio_cs: Removed variables that is never used Variable ar assigned a value that is never used. I have also removed all the code that thereby serves no purpose. This was found using a static code analysis program called cppcheck Signed-off-by: Rickard Strandqvist Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_cs.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c index 9b201e48233eb4..b1523308ab238c 100644 --- a/drivers/staging/comedi/drivers/ni_mio_cs.c +++ b/drivers/staging/comedi/drivers/ni_mio_cs.c @@ -163,7 +163,6 @@ static int mio_cs_auto_attach(struct comedi_device *dev, { struct pcmcia_device *link = comedi_to_pcmcia_dev(dev); static const struct ni_board_struct *board; - struct ni_private *devpriv; int ret; board = ni_getboardtype(dev, link); @@ -188,8 +187,6 @@ static int mio_cs_auto_attach(struct comedi_device *dev, if (ret) return ret; - devpriv = dev->private; - return ni_E_init(dev, 0, 1); } From e9ba6ec2322319a59d60b14b65fe6fc19e9a40e4 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Thu, 29 Jan 2015 23:25:51 +0100 Subject: [PATCH 2749/3023] staging: comedi: drivers: mite: Removed variables that is never used Variable was assigned a value that was never used. I have also removed all the code that thereby serves no purpose. This was found using a static code analysis program called cppcheck Signed-off-by: Rickard Strandqvist Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/mite.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c index ffc9e61d6cdde2..1e537a5cf86286 100644 --- a/drivers/staging/comedi/drivers/mite.c +++ b/drivers/staging/comedi/drivers/mite.c @@ -494,9 +494,7 @@ EXPORT_SYMBOL_GPL(mite_bytes_read_from_memory_ub); unsigned mite_dma_tcr(struct mite_channel *mite_chan) { struct mite_struct *mite = mite_chan->mite; - int lkar; - lkar = readl(mite->mite_io_addr + MITE_LKAR(mite_chan->channel)); return readl(mite->mite_io_addr + MITE_TCR(mite_chan->channel)); } EXPORT_SYMBOL_GPL(mite_dma_tcr); From 451d61f99583fe8b82b03c3a52cc1619edd45817 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Thu, 29 Jan 2015 23:30:47 +0100 Subject: [PATCH 2750/3023] staging: comedi: drivers: addi-data: hwdrv_apci3501: Removed variables that is never used Variable was assigned a value that was never used. I have also removed all the code that thereby serves no purpose. This was found using a static code analysis program called cppcheck Signed-off-by: Rickard Strandqvist Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c index 339519a3d6b550..1f2f78186d58c1 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c @@ -93,7 +93,6 @@ static int apci3501_write_insn_timer(struct comedi_device *dev, { struct apci3501_private *devpriv = dev->private; unsigned int ul_Command1 = 0; - int i_Temp; if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) { @@ -135,7 +134,7 @@ static int apci3501_write_insn_timer(struct comedi_device *dev, } } - i_Temp = inl(dev->iobase + APCI3501_TIMER_STATUS_REG) & 0x1; + inl(dev->iobase + APCI3501_TIMER_STATUS_REG); return insn->n; } From fa0ca8e7c93442a2cb6be895cfb3f067079c4f0a Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Thu, 29 Jan 2015 23:43:36 +0100 Subject: [PATCH 2751/3023] staging: comedi: drivers: rtd520: Removed variables that is never used Variable was assigned a value that was never used. I have also removed all the code that thereby serves no purpose. This was found using a static code analysis program called cppcheck Signed-off-by: Rickard Strandqvist Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/rtd520.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 3ccdadeb371f0d..c94ad12ed446be 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -1027,8 +1027,6 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct rtd_private *devpriv = dev->private; - u32 overrun; - u16 status; /* pacer stop source: SOFTWARE */ writel(0, dev->mmio + LAS0_PACER_STOP); @@ -1036,8 +1034,6 @@ static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) writel(0, dev->mmio + LAS0_ADC_CONVERSION); writew(0, dev->mmio + LAS0_IT); devpriv->ai_count = 0; /* stop and don't transfer any more */ - status = readw(dev->mmio + LAS0_IT); - overrun = readl(dev->mmio + LAS0_OVERRUN) & 0xffff; writel(0, dev->mmio + LAS0_ADC_FIFO_CLEAR); return 0; } From ba9b6ef4058a065558b2d55b943fa10cd8540207 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Thu, 29 Jan 2015 23:34:55 +0100 Subject: [PATCH 2752/3023] staging: comedi: drivers: addi_apci_3501: Removed variables that is never used Variable was assigned a value that was never used. I have also removed all the code that thereby serves no purpose. This was found using a static code analysis program called cppcheck Signed-off-by: Rickard Strandqvist Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/addi_apci_3501.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c index a726efcea6a537..5961f195ba0bfa 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3501.c +++ b/drivers/staging/comedi/drivers/addi_apci_3501.c @@ -267,7 +267,6 @@ static irqreturn_t apci3501_interrupt(int irq, void *d) struct apci3501_private *devpriv = dev->private; unsigned int ui_Timer_AOWatchdog; unsigned long ul_Command1; - int i_temp; /* Disable Interrupt */ ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG); @@ -285,7 +284,7 @@ static irqreturn_t apci3501_interrupt(int irq, void *d) ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG); ul_Command1 = ((ul_Command1 & 0xFFFFF9FDul) | 1 << 1); outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG); - i_temp = inl(dev->iobase + APCI3501_TIMER_STATUS_REG) & 0x1; + inl(dev->iobase + APCI3501_TIMER_STATUS_REG); return IRQ_HANDLED; } From 3caef5a4cac9d7c27d7362be63e799c199111a62 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Thu, 29 Jan 2015 23:50:09 +0100 Subject: [PATCH 2753/3023] staging: comedi: drivers: usbduxsigma: Removed variables that is never used Variable was assigned a value that was never used. I have also removed all the code that thereby serves no purpose. This was found using a static code analysis program called cppcheck Signed-off-by: Rickard Strandqvist Reviewed-by: Ian Abbott Reviewed-by: Bernd Porr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbduxsigma.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 378c44923c57e9..394969b7458c19 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -214,7 +214,6 @@ static void usbduxsigma_ai_handle_urb(struct comedi_device *dev, struct usbduxsigma_private *devpriv = dev->private; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; - unsigned int dio_state; uint32_t val; int ret; int i; @@ -223,9 +222,6 @@ static void usbduxsigma_ai_handle_urb(struct comedi_device *dev, if (devpriv->ai_counter == 0) { devpriv->ai_counter = devpriv->ai_timer; - /* get the state of the dio pins to allow external trigger */ - dio_state = be32_to_cpu(devpriv->in_buf[0]); - /* get the data from the USB bus and hand it over to comedi */ for (i = 0; i < cmd->chanlist_len; i++) { /* transfer data, note first byte is the DIO state */ From f6fef5df1accf2851d4c357eddcde8bcaf8349d6 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 28 Jan 2015 18:41:45 +0000 Subject: [PATCH 2754/3023] staging: comedi: comedi_fops.c: reformat copyright header Use the usual block comment style. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 32 ++++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 68bfe92319e6b9..bb2e7961ec3c14 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1,20 +1,20 @@ /* - comedi/comedi_fops.c - comedi kernel module - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-2000 David A. Schleef - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * comedi/comedi_fops.c + * comedi kernel module + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2000 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt From dd630cdeb160fc4f219481a68771d683d59178ee Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 28 Jan 2015 18:41:46 +0000 Subject: [PATCH 2755/3023] staging: comedi: comedi_fops.c: document exported functions Add kerneldoc for exported functions `comedi_dev_put()`, `comedi_dev_get_from_minor()`, `comedi_is_subdevice_running()`, and `comedi_event()`. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 42 ++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index bb2e7961ec3c14..8f65097406d620 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -113,6 +113,18 @@ static void comedi_dev_kref_release(struct kref *kref) kfree(dev); } +/** + * comedi_dev_put - release a use of a comedi device structure + * @dev: comedi_device struct + * + * Must be called when a user of a comedi device is finished with it. + * When the last user of the comedi device calls this function, the + * comedi device is destroyed. + * + * Return 1 if the comedi device is destroyed by this call or dev is + * NULL, otherwise return 0. Callers must not assume the comedi + * device is still valid if this function returns 0. + */ int comedi_dev_put(struct comedi_device *dev) { if (dev) @@ -220,6 +232,18 @@ static struct comedi_device *comedi_dev_get_from_subdevice_minor(unsigned minor) return dev; } +/** + * comedi_dev_get_from_minor - get comedi device by minor device number + * @minor: minor device number + * + * Finds the comedi device associated by the minor device number, if any, + * and increments its reference count. The comedi device is prevented from + * being freed until a matching call is made to comedi_dev_put(). + * + * Return a pointer to the comedi device if it exists, with its usage + * reference incremented. Return NULL if no comedi device exists with the + * specified minor device number. + */ struct comedi_device *comedi_dev_get_from_minor(unsigned minor) { if (minor < COMEDI_NUM_BOARD_MINORS) @@ -600,6 +624,13 @@ static unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s) return runflags; } +/** + * comedi_is_subdevice_running - check if async command running on subdevice + * @s: comedi_subdevice struct + * + * Return true if an asynchronous comedi command is active on the comedi + * subdevice, else return false. + */ bool comedi_is_subdevice_running(struct comedi_subdevice *s) { unsigned runflags = comedi_get_subdevice_runflags(s); @@ -2584,6 +2615,17 @@ static const struct file_operations comedi_fops = { .llseek = noop_llseek, }; +/** + * comedi_event - handle events for asynchronous comedi command + * @dev: comedi_device struct + * @s: comedi_subdevice struct associated with dev + * Context: interrupt (usually), s->spin_lock spin-lock not held + * + * If an asynchronous comedi command is active on the subdevice, process + * any COMEDI_CB_... event flags that have been set, usually by an + * interrupt handler. These may change the run state of the asynchronous + * command, wake a task, and/or send a SIGIO signal. + */ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s) { struct comedi_async *async = s->async; From 18e01b24a7b60534a1871085a27bfee7d694bc55 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 28 Jan 2015 18:41:47 +0000 Subject: [PATCH 2756/3023] staging: comedi: comedi_fops.c: reformat ioctl handler comments The unlocked_ioctl handler calls a different function to handle each supported ioctl command code. Most of these have a block comment indicating which command code it handles, a brief description, and an informal description of the inputs and outputs. These block comments are formatted in various styles. Reformat them to the usual block comment style and do a bit of rewording for consistency. The comment block for the `COMEDI_CMD` ioctl is missing, so add one. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 334 ++++++++++++++------------- 1 file changed, 168 insertions(+), 166 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 8f65097406d620..5403af127d71d4 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -740,18 +740,18 @@ static int is_device_busy(struct comedi_device *dev) } /* - COMEDI_DEVCONFIG - device config ioctl - - arg: - pointer to devconfig structure - - reads: - devconfig structure at arg - - writes: - none -*/ + * COMEDI_DEVCONFIG ioctl + * attaches (and configures) or detaches a legacy device + * + * arg: + * pointer to comedi_devconfig structure (NULL if detaching) + * + * reads: + * comedi_devconfig structure (if attaching) + * + * writes: + * nothing + */ static int do_devconfig_ioctl(struct comedi_device *dev, struct comedi_devconfig __user *arg) { @@ -792,19 +792,18 @@ static int do_devconfig_ioctl(struct comedi_device *dev, } /* - COMEDI_BUFCONFIG - buffer configuration ioctl - - arg: - pointer to bufconfig structure - - reads: - bufconfig at arg - - writes: - modified bufconfig at arg - -*/ + * COMEDI_BUFCONFIG ioctl + * buffer configuration + * + * arg: + * pointer to comedi_bufconfig structure + * + * reads: + * comedi_bufconfig structure + * + * writes: + * modified comedi_bufconfig structure + */ static int do_bufconfig_ioctl(struct comedi_device *dev, struct comedi_bufconfig __user *arg) { @@ -854,19 +853,18 @@ static int do_bufconfig_ioctl(struct comedi_device *dev, } /* - COMEDI_DEVINFO - device info ioctl - - arg: - pointer to devinfo structure - - reads: - none - - writes: - devinfo structure - -*/ + * COMEDI_DEVINFO ioctl + * device info + * + * arg: + * pointer to comedi_devinfo structure + * + * reads: + * nothing + * + * writes: + * comedi_devinfo structure + */ static int do_devinfo_ioctl(struct comedi_device *dev, struct comedi_devinfo __user *arg, struct file *file) @@ -901,19 +899,18 @@ static int do_devinfo_ioctl(struct comedi_device *dev, } /* - COMEDI_SUBDINFO - subdevice info ioctl - - arg: - pointer to array of subdevice info structures - - reads: - none - - writes: - array of subdevice info structures at arg - -*/ + * COMEDI_SUBDINFO ioctl + * subdevices info + * + * arg: + * pointer to array of comedi_subdinfo structures + * + * reads: + * nothing + * + * writes: + * array of comedi_subdinfo structures + */ static int do_subdinfo_ioctl(struct comedi_device *dev, struct comedi_subdinfo __user *arg, void *file) { @@ -975,19 +972,19 @@ static int do_subdinfo_ioctl(struct comedi_device *dev, } /* - COMEDI_CHANINFO - subdevice info ioctl - - arg: - pointer to chaninfo structure - - reads: - chaninfo structure at arg - - writes: - arrays at elements of chaninfo structure - -*/ + * COMEDI_CHANINFO ioctl + * subdevice channel info + * + * arg: + * pointer to comedi_chaninfo structure + * + * reads: + * comedi_chaninfo structure + * + * writes: + * array of maxdata values to chaninfo->maxdata_list if requested + * array of range table lengths to chaninfo->range_table_list if requested + */ static int do_chaninfo_ioctl(struct comedi_device *dev, struct comedi_chaninfo __user *arg) { @@ -1035,20 +1032,19 @@ static int do_chaninfo_ioctl(struct comedi_device *dev, return 0; } - /* - COMEDI_BUFINFO - buffer information ioctl - - arg: - pointer to bufinfo structure - - reads: - bufinfo at arg - - writes: - modified bufinfo at arg - - */ +/* + * COMEDI_BUFINFO ioctl + * buffer information + * + * arg: + * pointer to comedi_bufinfo structure + * + * reads: + * comedi_bufinfo structure + * + * writes: + * modified comedi_bufinfo structure + */ static int do_bufinfo_ioctl(struct comedi_device *dev, struct comedi_bufinfo __user *arg, void *file) { @@ -1357,19 +1353,19 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, } /* - * COMEDI_INSNLIST - * synchronous instructions + * COMEDI_INSNLIST ioctl + * synchronous instruction list * - * arg: - * pointer to sync cmd structure + * arg: + * pointer to comedi_insnlist structure * - * reads: - * sync cmd struct at arg - * instruction list - * data (for writes) + * reads: + * comedi_insnlist structure + * array of comedi_insn structures from insnlist->insns pointer + * data (for writes) from insns[].data pointers * - * writes: - * data (for reads) + * writes: + * data (for reads) to insns[].data pointers */ /* arbitrary limits */ #define MAX_SAMPLES 256 @@ -1446,18 +1442,18 @@ static int do_insnlist_ioctl(struct comedi_device *dev, } /* - * COMEDI_INSN - * synchronous instructions + * COMEDI_INSN ioctl + * synchronous instruction * - * arg: - * pointer to insn + * arg: + * pointer to comedi_insn structure * - * reads: - * struct comedi_insn struct at arg - * data (for writes) + * reads: + * comedi_insn structure + * data (for writes) from insn->data pointer * - * writes: - * data (for reads) + * writes: + * data (for reads) to insn->data pointer */ static int do_insn_ioctl(struct comedi_device *dev, struct comedi_insn __user *arg, void *file) @@ -1589,6 +1585,20 @@ static int __comedi_get_user_chanlist(struct comedi_device *dev, return 0; } +/* + * COMEDI_CMD ioctl + * asynchronous acquisition command set-up + * + * arg: + * pointer to comedi_cmd structure + * + * reads: + * comedi_cmd structure + * channel/range list from cmd->chanlist pointer + * + * writes: + * possibly modified comedi_cmd structure (when -EAGAIN returned) + */ static int do_cmd_ioctl(struct comedi_device *dev, struct comedi_cmd __user *arg, void *file) { @@ -1684,20 +1694,19 @@ static int do_cmd_ioctl(struct comedi_device *dev, } /* - COMEDI_CMDTEST - command testing ioctl - - arg: - pointer to cmd structure - - reads: - cmd structure at arg - channel/range list - - writes: - modified cmd structure at arg - -*/ + * COMEDI_CMDTEST ioctl + * asynchronous aquisition command testing + * + * arg: + * pointer to comedi_cmd structure + * + * reads: + * comedi_cmd structure + * channel/range list from cmd->chanlist pointer + * + * writes: + * possibly modified comedi_cmd structure + */ static int do_cmdtest_ioctl(struct comedi_device *dev, struct comedi_cmd __user *arg, void *file) { @@ -1740,20 +1749,18 @@ static int do_cmdtest_ioctl(struct comedi_device *dev, } /* - COMEDI_LOCK - lock subdevice - - arg: - subdevice number - - reads: - none - - writes: - none - -*/ - + * COMEDI_LOCK ioctl + * lock subdevice + * + * arg: + * subdevice number + * + * reads: + * nothing + * + * writes: + * nothing + */ static int do_lock_ioctl(struct comedi_device *dev, unsigned long arg, void *file) { @@ -1776,21 +1783,18 @@ static int do_lock_ioctl(struct comedi_device *dev, unsigned long arg, } /* - COMEDI_UNLOCK - unlock subdevice - - arg: - subdevice number - - reads: - none - - writes: - none - - This function isn't protected by the semaphore, since - we already own the lock. -*/ + * COMEDI_UNLOCK ioctl + * unlock subdevice + * + * arg: + * subdevice number + * + * reads: + * nothing + * + * writes: + * nothing + */ static int do_unlock_ioctl(struct comedi_device *dev, unsigned long arg, void *file) { @@ -1813,19 +1817,18 @@ static int do_unlock_ioctl(struct comedi_device *dev, unsigned long arg, } /* - COMEDI_CANCEL - cancel acquisition ioctl - - arg: - subdevice number - - reads: - nothing - - writes: - nothing - -*/ + * COMEDI_CANCEL ioctl + * cancel asynchronous acquisition + * + * arg: + * subdevice number + * + * reads: + * nothing + * + * writes: + * nothing + */ static int do_cancel_ioctl(struct comedi_device *dev, unsigned long arg, void *file) { @@ -1847,19 +1850,18 @@ static int do_cancel_ioctl(struct comedi_device *dev, unsigned long arg, } /* - COMEDI_POLL ioctl - instructs driver to synchronize buffers - - arg: - subdevice number - - reads: - nothing - - writes: - nothing - -*/ + * COMEDI_POLL ioctl + * instructs driver to synchronize buffers + * + * arg: + * subdevice number + * + * reads: + * nothing + * + * writes: + * nothing + */ static int do_poll_ioctl(struct comedi_device *dev, unsigned long arg, void *file) { From 1a4f01b74f8c26a97e343ba8a93000781b3eb76d Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 28 Jan 2015 18:41:48 +0000 Subject: [PATCH 2757/3023] staging: comedi: range.c: reformat ioctl handler comment The unlocked_ioctl handler in "comedi_fops.c" calls a different function to handle each supported ioctl command code. Most of these have a block comment indicating which command code it handles, a brief description, and an informal description of the inputs and outputs. These block comments were formatted in various styles, but have been reformatted to use the usual block comment style. The block comment for the handler function for the `COMEDI_RANGEINFO` ioctl code is in "range.c". Reformat it to use the usual block command style to match the others. Reword it a bit for consistency. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/range.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c index 9a1dc56f21d156..00e71c7e556847 100644 --- a/drivers/staging/comedi/range.c +++ b/drivers/staging/comedi/range.c @@ -42,18 +42,18 @@ const struct comedi_lrange range_unknown = { 1, {{0, 1000000, UNIT_none} } }; EXPORT_SYMBOL_GPL(range_unknown); /* - COMEDI_RANGEINFO - range information ioctl - - arg: - pointer to rangeinfo structure - - reads: - range info structure - - writes: - n struct comedi_krange structures to rangeinfo->range_ptr -*/ + * COMEDI_RANGEINFO ioctl + * range information + * + * arg: + * pointer to comedi_rangeinfo structure + * + * reads: + * comedi_rangeinfo structure + * + * writes: + * array of comedi_krange structures to rangeinfo->range_ptr pointer + */ int do_rangeinfo_ioctl(struct comedi_device *dev, struct comedi_rangeinfo __user *arg) { From 5824ec7fe71c1da49a170fb18bfba3d1097caa39 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 28 Jan 2015 18:41:49 +0000 Subject: [PATCH 2758/3023] staging: comedi: range.c: reformat copyright comment Use the usual block comment style. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/range.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c index 00e71c7e556847..6a393b24bdd936 100644 --- a/drivers/staging/comedi/range.c +++ b/drivers/staging/comedi/range.c @@ -1,20 +1,20 @@ /* - module/range.c - comedi routines for voltage ranges - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-8 David A. Schleef - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * comedi/range.c + * comedi routines for voltage ranges + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-8 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #include #include "comedidev.h" From a2aab8b481eb85ec445c2b50cfa263236aad07bd Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 28 Jan 2015 18:41:50 +0000 Subject: [PATCH 2759/3023] staging: comedi: comedi_fops.c: reformat remaining block comments Reformat remaining block comments to use the usual block comment style. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 29 +++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 5403af127d71d4..727640e89c73ad 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -347,8 +347,7 @@ static int resize_async_buffer(struct comedi_device *dev, return -EBUSY; } - /* make sure buffer is an integral number of pages - * (we round up) */ + /* make sure buffer is an integral number of pages (we round up) */ new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK; retval = comedi_buf_alloc(dev, s, new_size); @@ -671,7 +670,7 @@ void *comedi_alloc_spriv(struct comedi_subdevice *s, size_t size) EXPORT_SYMBOL_GPL(comedi_alloc_spriv); /* - This function restores a subdevice to an idle state. + * This function restores a subdevice to an idle state. */ static void do_become_nonbusy(struct comedi_device *dev, struct comedi_subdevice *s) @@ -1162,8 +1161,10 @@ static int check_insn_config_length(struct comedi_insn *insn, if (insn->n == 6) return 0; break; - /* by default we allow the insn since we don't have checks for - * all possible cases yet */ + /* + * by default we allow the insn since we don't have checks for + * all possible cases yet + */ default: pr_warn("No check for data length of config insn id %i is implemented\n", data[0]); @@ -1314,9 +1315,11 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, if (insn->n != 2) { ret = -EINVAL; } else { - /* Most drivers ignore the base channel in + /* + * Most drivers ignore the base channel in * insn->chanspec. Fix this here if - * the subdevice has <= 32 channels. */ + * the subdevice has <= 32 channels. + */ unsigned int orig_mask = data[0]; unsigned int shift = 0; @@ -1977,8 +1980,10 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, mutex_lock(&dev->mutex); - /* Device config is special, because it must work on - * an unconfigured device. */ + /* + * Device config is special, because it must work on + * an unconfigured device. + */ if (cmd == COMEDI_DEVCONFIG) { if (minor >= COMEDI_NUM_BOARD_MINORS) { /* Device config not appropriate on non-board minors. */ @@ -1990,8 +1995,10 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, if (rc == 0) { if (arg == 0 && dev->minor >= comedi_num_legacy_minors) { - /* Successfully unconfigured a dynamically - * allocated device. Try and remove it. */ + /* + * Successfully unconfigured a dynamically + * allocated device. Try and remove it. + */ if (comedi_clear_board_dev(dev)) { mutex_unlock(&dev->mutex); comedi_free_board_dev(dev); From 00f457b5755824cb5fc91584644c1831eb6d536e Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 30 Jan 2015 09:57:17 +0000 Subject: [PATCH 2760/3023] staging: comedi: add comedi_pcmcia.h Add a new header that Comedi PCMCIA drivers can include instead of "comedidev.h". Currently, it just pulls in , and "comedidev.h", but the plan is to migrate the PCMCIA-specific stuff from "comedidev.h" here. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_pcmcia.h | 31 ++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 drivers/staging/comedi/comedi_pcmcia.h diff --git a/drivers/staging/comedi/comedi_pcmcia.h b/drivers/staging/comedi/comedi_pcmcia.h new file mode 100644 index 00000000000000..ba073af99b7dfd --- /dev/null +++ b/drivers/staging/comedi/comedi_pcmcia.h @@ -0,0 +1,31 @@ +/* + * comedi_pcmcia.h + * header file for Comedi PCMCIA drivers + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2000 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _COMEDI_PCMCIA_H +#define _COMEDI_PCMCIA_H + +#include +#include + +#include "comedidev.h" + +/* + * TODO: Move PCMCIA-specific stuff into here from "comedidev.h". + */ + +#endif /* _COMEDI_PCMCIA_H */ From a1d49aeed0035adebb874ca30336ba2160321063 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 30 Jan 2015 09:57:18 +0000 Subject: [PATCH 2761/3023] staging: comedi: comedi_pcmcia.c: include new "comedi_pcmcia.h" header Include the new "comedi_pcmcia.h" header instead of , and "comedidev.h", which will now get included indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_pcmcia.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/staging/comedi/comedi_pcmcia.c b/drivers/staging/comedi/comedi_pcmcia.c index 0529bae8e5acbb..7e784399a16feb 100644 --- a/drivers/staging/comedi/comedi_pcmcia.c +++ b/drivers/staging/comedi/comedi_pcmcia.c @@ -19,10 +19,7 @@ #include #include -#include -#include - -#include "comedidev.h" +#include "comedi_pcmcia.h" /** * comedi_to_pcmcia_dev() - comedi_device pointer to pcmcia_device pointer. From 5df18b6c05fb44d08919ca53f1fb4fb283a279da Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 30 Jan 2015 09:57:19 +0000 Subject: [PATCH 2762/3023] staging: comedi: cb_das16_cs: include new "comedi_pcmcia.h" header Include the new "../comedi_pcmcia.h" header instead of , and "../comedidev.h", which will now get included indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_das16_cs.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index 0a48d2a961d523..1079b6c72b15d8 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -38,10 +38,7 @@ Status: experimental #include #include -#include "../comedidev.h" - -#include -#include +#include "../comedi_pcmcia.h" #include "comedi_fc.h" #include "8253.h" From 0519c8f686150fc1a0676eeb0e7aee3620724c3f Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 30 Jan 2015 09:57:20 +0000 Subject: [PATCH 2763/3023] staging: comedi: das08_cs: include new "comedi_pcmcia.h" header Include the new "../comedi_pcmcia.h" header instead of , and "../comedidev.h", which will now get included indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das08_cs.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index f3ccc2ce6d49d6..93fab689016179 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -41,10 +41,7 @@ Command support does not exist, but could be added for this board. #include -#include "../comedidev.h" - -#include -#include +#include "../comedi_pcmcia.h" #include "das08.h" From a411febedebeeb61f264daa9d62b456ad1a7a072 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 30 Jan 2015 09:57:21 +0000 Subject: [PATCH 2764/3023] staging: comedi: ni_daq_700: include new "comedi_pcmcia.h" header Include the new "../comedi_pcmcia.h" header instead of , and "../comedidev.h", which will now get included indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_daq_700.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index 5e472cb7fbd7f7..8f6396edd21ce0 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -51,10 +51,7 @@ #include #include -#include "../comedidev.h" - -#include -#include +#include "../comedi_pcmcia.h" /* daqcard700 registers */ #define DIO_W 0x04 /* WO 8bit */ From 51d5483f7b7b753dfada03408c3aaf6610b46137 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 30 Jan 2015 09:57:22 +0000 Subject: [PATCH 2765/3023] staging: comedi: ni_daq_dio24: include new "comedi_pcmcia.h" header Include the new "../comedi_pcmcia.h" header instead of , , and "../comedidev.h". isn't needed and the others will now get included indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_daq_dio24.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c index 8cfabdbaa30ceb..a208cb3484375d 100644 --- a/drivers/staging/comedi/drivers/ni_daq_dio24.c +++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c @@ -32,11 +32,7 @@ the PCMCIA interface. */ #include -#include "../comedidev.h" - -#include -#include -#include +#include "../comedi_pcmcia.h" #include "8255.h" From 778edf45e666a936581cc29ad71c7d1d0efc4d92 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 30 Jan 2015 09:57:23 +0000 Subject: [PATCH 2766/3023] staging: comedi: ni_labpc_cs: include new "comedi_pcmcia.h" header Include the new "../comedi_pcmcia.h" header instead of , , and "../comedidev.h". isn't needed and the others will now get included indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_labpc_cs.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c index ece00109536cf1..746c4cd9978dea 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_cs.c +++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c @@ -55,11 +55,7 @@ NI manuals: #include -#include "../comedidev.h" - -#include -#include -#include +#include "../comedi_pcmcia.h" #include "ni_labpc.h" From 064c654465a6c48d7d7c91d59c449c85fd14e6fa Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 30 Jan 2015 09:57:24 +0000 Subject: [PATCH 2767/3023] staging: comedi: ni_mio_cs: include new "comedi_pcmcia.h" header Include the new "../comedi_pcmcia.h" header instead of , and "../comedidev.h", which will now get included indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_cs.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c index b1523308ab238c..e3d821bf2d6a01 100644 --- a/drivers/staging/comedi/drivers/ni_mio_cs.c +++ b/drivers/staging/comedi/drivers/ni_mio_cs.c @@ -37,16 +37,12 @@ See the notes in the ni_atmio.o driver. */ #include -#include "../comedidev.h" - #include +#include "../comedi_pcmcia.h" #include "ni_stc.h" #include "8255.h" -#include -#include - /* * AT specific setup */ From f0dff1a4b1fb21c499eb25969abea41dcabf9987 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 30 Jan 2015 09:57:25 +0000 Subject: [PATCH 2768/3023] staging: comedi: quatech_daqp_cs: include new "comedi_pcmcia.h" header Include the new "../comedi_pcmcia.h" header instead of , , and "../comedidev.h". isn't needed and the others will now get included indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/quatech_daqp_cs.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index dd06734f2158e2..8387fd0e4b7e12 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -48,15 +48,10 @@ Devices: [Quatech] DAQP-208 (daqp), DAQP-308 */ #include -#include "../comedidev.h" #include - -#include -#include -#include - #include +#include "../comedi_pcmcia.h" #include "comedi_fc.h" struct daqp_private { From aedd2e80c9409084b68b1c3a5a4e25ddc212d64a Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 30 Jan 2015 09:57:26 +0000 Subject: [PATCH 2769/3023] staging: comedi: comedi_pcmcia.h: move PCMCIA stuff out of comedidev.h Move the PCMCIA-specific stuff out of "comedidev.h" into "comedi_pcmcia.h". Comedi PCMCIA drivers now include "comedi_pcmcia.h" instead of "comedidev.h", which now gets pulled in indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_pcmcia.h | 28 ++++++++++++++++++++-- drivers/staging/comedi/comedidev.h | 33 -------------------------- 2 files changed, 26 insertions(+), 35 deletions(-) diff --git a/drivers/staging/comedi/comedi_pcmcia.h b/drivers/staging/comedi/comedi_pcmcia.h index ba073af99b7dfd..5d3db2b9b4a1bd 100644 --- a/drivers/staging/comedi/comedi_pcmcia.h +++ b/drivers/staging/comedi/comedi_pcmcia.h @@ -24,8 +24,32 @@ #include "comedidev.h" -/* - * TODO: Move PCMCIA-specific stuff into here from "comedidev.h". +struct pcmcia_device *comedi_to_pcmcia_dev(struct comedi_device *); + +int comedi_pcmcia_enable(struct comedi_device *, + int (*conf_check)(struct pcmcia_device *, void *)); +void comedi_pcmcia_disable(struct comedi_device *); + +int comedi_pcmcia_auto_config(struct pcmcia_device *, struct comedi_driver *); +void comedi_pcmcia_auto_unconfig(struct pcmcia_device *); + +int comedi_pcmcia_driver_register(struct comedi_driver *, + struct pcmcia_driver *); +void comedi_pcmcia_driver_unregister(struct comedi_driver *, + struct pcmcia_driver *); + +/** + * module_comedi_pcmcia_driver() - Helper macro for registering a comedi PCMCIA driver + * @__comedi_driver: comedi_driver struct + * @__pcmcia_driver: pcmcia_driver struct + * + * Helper macro for comedi PCMCIA drivers which do not do anything special + * in module init/exit. This eliminates a lot of boilerplate. Each + * module may only use this macro once, and calling it replaces + * module_init() and module_exit() */ +#define module_comedi_pcmcia_driver(__comedi_driver, __pcmcia_driver) \ + module_driver(__comedi_driver, comedi_pcmcia_driver_register, \ + comedi_pcmcia_driver_unregister, &(__pcmcia_driver)) #endif /* _COMEDI_PCMCIA_H */ diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index bc1dfc175add62..e138eb0dc374c2 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -596,37 +596,4 @@ void comedi_pci_driver_unregister(struct comedi_driver *, struct pci_driver *); module_driver(__comedi_driver, comedi_pci_driver_register, \ comedi_pci_driver_unregister, &(__pci_driver)) -/* comedi_pcmcia.c - comedi PCMCIA driver specific functions */ - -struct pcmcia_driver; -struct pcmcia_device; - -struct pcmcia_device *comedi_to_pcmcia_dev(struct comedi_device *); - -int comedi_pcmcia_enable(struct comedi_device *, - int (*conf_check)(struct pcmcia_device *, void *)); -void comedi_pcmcia_disable(struct comedi_device *); - -int comedi_pcmcia_auto_config(struct pcmcia_device *, struct comedi_driver *); -void comedi_pcmcia_auto_unconfig(struct pcmcia_device *); - -int comedi_pcmcia_driver_register(struct comedi_driver *, - struct pcmcia_driver *); -void comedi_pcmcia_driver_unregister(struct comedi_driver *, - struct pcmcia_driver *); - -/** - * module_comedi_pcmcia_driver() - Helper macro for registering a comedi PCMCIA driver - * @__comedi_driver: comedi_driver struct - * @__pcmcia_driver: pcmcia_driver struct - * - * Helper macro for comedi PCMCIA drivers which do not do anything special - * in module init/exit. This eliminates a lot of boilerplate. Each - * module may only use this macro once, and calling it replaces - * module_init() and module_exit() - */ -#define module_comedi_pcmcia_driver(__comedi_driver, __pcmcia_driver) \ - module_driver(__comedi_driver, comedi_pcmcia_driver_register, \ - comedi_pcmcia_driver_unregister, &(__pcmcia_driver)) - #endif /* _COMEDIDEV_H */ From 369ba5b8310b401bd04d73d39f57d50a06ef8c09 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Wed, 4 Feb 2015 12:02:33 -0500 Subject: [PATCH 2770/3023] staging: comedi: dt282x: condition with no effect - if identical to else The if and the else branch code are identical - so the condition has no effect on the effective code - this patch removes the condition and the duplicated code. Signed-off-by: Nicholas Mc Guire Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt282x.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 051dfb290f4f1d..db21d213585607 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -685,14 +685,7 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); - if (cmd->scan_begin_src == TRIG_FOLLOW) { - /* internal trigger */ - err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); - } else { - /* external trigger */ - /* should be level/edge, hi/lo specification here */ - err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); - } + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 4000); From d0e9ed58f46b5aa101f90834a87c4464814e1721 Mon Sep 17 00:00:00 2001 From: Bastian Plettner Date: Wed, 28 Jan 2015 20:25:02 +0100 Subject: [PATCH 2771/3023] staging: speakup: Remove unnecessary space This patch fixes the checkpath.pl warning: ERROR: space prohibited before that ',' (ctx:WxE) + MSG_FIRST_INDEX , And removes the unnecessary space. Signed-off-by: Bastian Plettner Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/i18n.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/speakup/i18n.h b/drivers/staging/speakup/i18n.h index 16a0871373d936..326d086f9d5a1e 100644 --- a/drivers/staging/speakup/i18n.h +++ b/drivers/staging/speakup/i18n.h @@ -3,7 +3,7 @@ /* Internationalization declarations */ enum msg_index_t { - MSG_FIRST_INDEX , + MSG_FIRST_INDEX, MSG_ANNOUNCEMENTS_START = MSG_FIRST_INDEX, MSG_BLANK = MSG_ANNOUNCEMENTS_START, MSG_IAM_ALIVE, From 25ef8072fbea1843c29c24cf82e6913c504db55c Mon Sep 17 00:00:00 2001 From: Simon Guo Date: Thu, 29 Jan 2015 13:33:17 +0800 Subject: [PATCH 2772/3023] STAGING: Fix pcl818.c coding style issue: code indent should use tabs where possible Correct one coding style problem(detected by checkpatch.pl) in pcl818.c. - code indent should use tabs where possible It is fixed by reformatting the comment block to usual comment style. And with the reformatting, following coding style problem is also fixed: - please, no space before tabs Signed-off-by: Simon Guo Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl818.c | 189 ++++++++++++------------ 1 file changed, 91 insertions(+), 98 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index a10ce41067ee75..47a2f7bb22f4ac 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -1,102 +1,95 @@ /* - comedi/drivers/pcl818.c - - Author: Michal Dobes - - hardware driver for Advantech cards: - card: PCL-818L, PCL-818H, PCL-818HD, PCL-818HG, PCL-818, PCL-718 - driver: pcl818l, pcl818h, pcl818hd, pcl818hg, pcl818, pcl718 -*/ -/* -Driver: pcl818 -Description: Advantech PCL-818 cards, PCL-718 -Author: Michal Dobes -Devices: [Advantech] PCL-818L (pcl818l), PCL-818H (pcl818h), - PCL-818HD (pcl818hd), PCL-818HG (pcl818hg), PCL-818 (pcl818), - PCL-718 (pcl718) -Status: works - -All cards have 16 SE/8 DIFF ADCs, one or two DACs, 16 DI and 16 DO. -Differences are only at maximal sample speed, range list and FIFO -support. -The driver support AI mode 0, 1, 3 other subdevices (AO, DI, DO) support -only mode 0. If DMA/FIFO/INT are disabled then AI support only mode 0. -PCL-818HD and PCL-818HG support 1kword FIFO. Driver support this FIFO -but this code is untested. -A word or two about DMA. Driver support DMA operations at two ways: -1) DMA uses two buffers and after one is filled then is generated - INT and DMA restart with second buffer. With this mode I'm unable run - more that 80Ksamples/secs without data dropouts on K6/233. -2) DMA uses one buffer and run in autoinit mode and the data are - from DMA buffer moved on the fly with 2kHz interrupts from RTC. - This mode is used if the interrupt 8 is available for allocation. - If not, then first DMA mode is used. With this I can run at - full speed one card (100ksamples/secs) or two cards with - 60ksamples/secs each (more is problem on account of ISA limitations). - To use this mode you must have compiled kernel with disabled - "Enhanced Real Time Clock Support". - Maybe you can have problems if you use xntpd or similar. - If you've data dropouts with DMA mode 2 then: - a) disable IDE DMA - b) switch text mode console to fb. - - Options for PCL-818L: - [0] - IO Base - [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) - [2] - DMA (0=disable, 1, 3) - [3] - 0, 10=10MHz clock for 8254 - 1= 1MHz clock for 8254 - [4] - 0, 5=A/D input -5V.. +5V - 1, 10=A/D input -10V..+10V - [5] - 0, 5=D/A output 0-5V (internal reference -5V) - 1, 10=D/A output 0-10V (internal reference -10V) - 2 =D/A output unknown (external reference) - - Options for PCL-818, PCL-818H: - [0] - IO Base - [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) - [2] - DMA (0=disable, 1, 3) - [3] - 0, 10=10MHz clock for 8254 - 1= 1MHz clock for 8254 - [4] - 0, 5=D/A output 0-5V (internal reference -5V) - 1, 10=D/A output 0-10V (internal reference -10V) - 2 =D/A output unknown (external reference) - - Options for PCL-818HD, PCL-818HG: - [0] - IO Base - [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) - [2] - DMA/FIFO (-1=use FIFO, 0=disable both FIFO and DMA, - 1=use DMA ch 1, 3=use DMA ch 3) - [3] - 0, 10=10MHz clock for 8254 - 1= 1MHz clock for 8254 - [4] - 0, 5=D/A output 0-5V (internal reference -5V) - 1, 10=D/A output 0-10V (internal reference -10V) - 2 =D/A output unknown (external reference) - - Options for PCL-718: - [0] - IO Base - [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) - [2] - DMA (0=disable, 1, 3) - [3] - 0, 10=10MHz clock for 8254 - 1= 1MHz clock for 8254 - [4] - 0=A/D Range is +/-10V - 1= +/-5V - 2= +/-2.5V - 3= +/-1V - 4= +/-0.5V - 5= user defined bipolar - 6= 0-10V - 7= 0-5V - 8= 0-2V - 9= 0-1V - 10= user defined unipolar - [5] - 0, 5=D/A outputs 0-5V (internal reference -5V) - 1, 10=D/A outputs 0-10V (internal reference -10V) - 2=D/A outputs unknown (external reference) - [6] - 0, 60=max 60kHz A/D sampling - 1,100=max 100kHz A/D sampling (PCL-718 with Option 001 installed) - -*/ + * comedi/drivers/pcl818.c + * + * Driver: pcl818 + * Description: Advantech PCL-818 cards, PCL-718 + * Author: Michal Dobes + * Devices: [Advantech] PCL-818L (pcl818l), PCL-818H (pcl818h), + * PCL-818HD (pcl818hd), PCL-818HG (pcl818hg), PCL-818 (pcl818), + * PCL-718 (pcl718) + * Status: works + * + * All cards have 16 SE/8 DIFF ADCs, one or two DACs, 16 DI and 16 DO. + * Differences are only at maximal sample speed, range list and FIFO + * support. + * The driver support AI mode 0, 1, 3 other subdevices (AO, DI, DO) support + * only mode 0. If DMA/FIFO/INT are disabled then AI support only mode 0. + * PCL-818HD and PCL-818HG support 1kword FIFO. Driver support this FIFO + * but this code is untested. + * A word or two about DMA. Driver support DMA operations at two ways: + * 1) DMA uses two buffers and after one is filled then is generated + * INT and DMA restart with second buffer. With this mode I'm unable run + * more that 80Ksamples/secs without data dropouts on K6/233. + * 2) DMA uses one buffer and run in autoinit mode and the data are + * from DMA buffer moved on the fly with 2kHz interrupts from RTC. + * This mode is used if the interrupt 8 is available for allocation. + * If not, then first DMA mode is used. With this I can run at + * full speed one card (100ksamples/secs) or two cards with + * 60ksamples/secs each (more is problem on account of ISA limitations). + * To use this mode you must have compiled kernel with disabled + * "Enhanced Real Time Clock Support". + * Maybe you can have problems if you use xntpd or similar. + * If you've data dropouts with DMA mode 2 then: + * a) disable IDE DMA + * b) switch text mode console to fb. + * + * Options for PCL-818L: + * [0] - IO Base + * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) + * [2] - DMA (0=disable, 1, 3) + * [3] - 0, 10=10MHz clock for 8254 + * 1= 1MHz clock for 8254 + * [4] - 0, 5=A/D input -5V.. +5V + * 1, 10=A/D input -10V..+10V + * [5] - 0, 5=D/A output 0-5V (internal reference -5V) + * 1, 10=D/A output 0-10V (internal reference -10V) + * 2 =D/A output unknown (external reference) + * + * Options for PCL-818, PCL-818H: + * [0] - IO Base + * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) + * [2] - DMA (0=disable, 1, 3) + * [3] - 0, 10=10MHz clock for 8254 + * 1= 1MHz clock for 8254 + * [4] - 0, 5=D/A output 0-5V (internal reference -5V) + * 1, 10=D/A output 0-10V (internal reference -10V) + * 2 =D/A output unknown (external reference) + * + * Options for PCL-818HD, PCL-818HG: + * [0] - IO Base + * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) + * [2] - DMA/FIFO (-1=use FIFO, 0=disable both FIFO and DMA, + * 1=use DMA ch 1, 3=use DMA ch 3) + * [3] - 0, 10=10MHz clock for 8254 + * 1= 1MHz clock for 8254 + * [4] - 0, 5=D/A output 0-5V (internal reference -5V) + * 1, 10=D/A output 0-10V (internal reference -10V) + * 2 =D/A output unknown (external reference) + * + * Options for PCL-718: + * [0] - IO Base + * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) + * [2] - DMA (0=disable, 1, 3) + * [3] - 0, 10=10MHz clock for 8254 + * 1= 1MHz clock for 8254 + * [4] - 0=A/D Range is +/-10V + * 1= +/-5V + * 2= +/-2.5V + * 3= +/-1V + * 4= +/-0.5V + * 5= user defined bipolar + * 6= 0-10V + * 7= 0-5V + * 8= 0-2V + * 9= 0-1V + * 10= user defined unipolar + * [5] - 0, 5=D/A outputs 0-5V (internal reference -5V) + * 1, 10=D/A outputs 0-10V (internal reference -10V) + * 2=D/A outputs unknown (external reference) + * [6] - 0, 60=max 60kHz A/D sampling + * 1,100=max 100kHz A/D sampling (PCL-718 with Option 001 installed) + * + */ #include #include From 8004a0c9b0e694c25e1ea7e058c64dff459f19f9 Mon Sep 17 00:00:00 2001 From: Simon Guo Date: Thu, 29 Jan 2015 13:34:28 +0800 Subject: [PATCH 2773/3023] STAGING: Fix pcl818.c coding style issue: line over 80 characters Correct one coding style problem(detected by checkpatch.pl) in pcl818.c. - line over 80 characters Signed-off-by: Simon Guo Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl818.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 47a2f7bb22f4ac..7e4cdea5fe59f9 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -297,9 +297,11 @@ static const struct pcl818_board boardtypes[] = { struct pcl818_private { struct comedi_isadma *dma; - unsigned int ns_min; /* manimal allowed delay between samples (in us) for actual card */ + /* manimal allowed delay between samples (in us) for actual card */ + unsigned int ns_min; int i8253_osc_base; /* 1/frequency of on board oscilator in ns */ - unsigned int act_chanlist[16]; /* MUX setting for actual AI operations */ + /* MUX setting for actual AI operations */ + unsigned int act_chanlist[16]; unsigned int act_chanlist_len; /* how long is actual MUX list */ unsigned int act_chanlist_pos; /* actual position in MUX list */ unsigned int divisor1; @@ -618,7 +620,8 @@ static int check_channel_list(struct comedi_device *dev, break; nowmustbechan = (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan; - if (nowmustbechan != CR_CHAN(chanlist[i])) { /* channel list isn't continuous :-( */ + if (nowmustbechan != CR_CHAN(chanlist[i])) { + /* channel list isn't continuous :-( */ dev_dbg(dev->class_dev, "channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n", i, CR_CHAN(chanlist[i]), nowmustbechan, @@ -1124,8 +1127,10 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->ns_min = board->ns_min; if (!board->is_818) { - if ((it->options[6] == 1) || (it->options[6] == 100)) - devpriv->ns_min = 10000; /* extended PCL718 to 100kHz DAC */ + if ((it->options[6] == 1) || (it->options[6] == 100)) { + /* extended PCL718 to 100kHz DAC */ + devpriv->ns_min = 10000; + } } pcl818_reset(dev); From 36e4d8826b317080e283e4edd08bf8d5ac706f38 Mon Sep 17 00:00:00 2001 From: Heba Aamer Date: Fri, 30 Jan 2015 00:11:36 +0200 Subject: [PATCH 2774/3023] staging: rtl8712: fix Prefer ether_addr_copy() over memcpy() This patch fixes the following checkpatch.pl warning: Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2) pahole showed that the struct used pnetdev->dev_addr is aligned to u16. Moreover mac is a simple array, pdata is a pointer that starts from an even offset. Signed-off-by: Heba Aamer Acked-by: Larry Finger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/usb_intf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index f1fd7e8d16fd32..f8b5b332e7c3dc 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -462,7 +462,7 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf, /* Use the mac address stored in the Efuse * offset = 0x12 for usb in efuse */ - memcpy(mac, &pdata[0x12], ETH_ALEN); + ether_addr_copy(mac, &pdata[0x12]); } eeprom_CustomerID = pdata[0x52]; switch (eeprom_CustomerID) { @@ -579,7 +579,7 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf, } else dev_info(&udev->dev, "r8712u: MAC Address from efuse = %pM\n", mac); - memcpy(pnetdev->dev_addr, mac, ETH_ALEN); + ether_addr_copy(pnetdev->dev_addr, mac); } /* step 6. Load the firmware asynchronously */ if (rtl871x_load_fw(padapter)) From 737fee1bf699635060caa1e940fd30153ff592de Mon Sep 17 00:00:00 2001 From: Chris Rorvick Date: Fri, 30 Jan 2015 17:45:45 -0600 Subject: [PATCH 2775/3023] staging: emxx_udc: Remove nbu2ss_drv_set_dp_info() This function is an awkward helper for nbu2ss_drv_ep_init(). Most of its logic is devoted to determining if the current endpoint is ep0, something the caller can easily do in a single line. And there is not a lot going on beyond that. Move this logic up into nbu2ss_drv_ep_init(). The result is much easier to understand and the resulting function is still viewable within a single screen. Signed-off-by: Chris Rorvick Signed-off-by: Greg Kroah-Hartman --- drivers/staging/emxx_udc/emxx_udc.c | 52 ++++++++--------------------- 1 file changed, 14 insertions(+), 38 deletions(-) diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c index eb178fcb7954d0..82c492f88c496a 100644 --- a/drivers/staging/emxx_udc/emxx_udc.c +++ b/drivers/staging/emxx_udc/emxx_udc.c @@ -3248,42 +3248,6 @@ static const char *gp_ep_name[NUM_ENDPOINTS] = { g_epd_name, }; -/*-------------------------------------------------------------------------*/ -static void __init nbu2ss_drv_set_ep_info( - struct nbu2ss_udc *udc, - struct nbu2ss_ep *ep, - const char *name) -{ - ep->udc = udc; - ep->desc = NULL; - - ep->ep.driver_data = NULL; - ep->ep.name = name; - ep->ep.ops = &nbu2ss_ep_ops; - - if (isdigit(name[2])) { - - long num; - int res; - char tempbuf[2]; - - tempbuf[0] = name[2]; - tempbuf[1] = '\0'; - res = kstrtol(tempbuf, 16, &num); - - if (num == 0) - ep->ep.maxpacket = EP0_PACKETSIZE; - else - ep->ep.maxpacket = EP_PACKETSIZE; - - } else { - ep->ep.maxpacket = EP_PACKETSIZE; - } - - list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); - INIT_LIST_HEAD(&ep->queue); -} - /*-------------------------------------------------------------------------*/ static void __init nbu2ss_drv_ep_init(struct nbu2ss_udc *udc) { @@ -3292,9 +3256,21 @@ static void __init nbu2ss_drv_ep_init(struct nbu2ss_udc *udc) INIT_LIST_HEAD(&udc->gadget.ep_list); udc->gadget.ep0 = &udc->ep[0].ep; + for (i = 0; i < NUM_ENDPOINTS; i++) { + struct nbu2ss_ep *ep = &udc->ep[i]; - for (i = 0; i < NUM_ENDPOINTS; i++) - nbu2ss_drv_set_ep_info(udc, &udc->ep[i], gp_ep_name[i]); + ep->udc = udc; + ep->desc = NULL; + + ep->ep.driver_data = NULL; + ep->ep.name = gp_ep_name[i]; + ep->ep.ops = &nbu2ss_ep_ops; + + ep->ep.maxpacket = (i == 0 ? EP0_PACKETSIZE : EP_PACKETSIZE); + + list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); + INIT_LIST_HEAD(&ep->queue); + } list_del_init(&udc->ep[0].ep.ep_list); } From e6aa864f01a10689a1e8e4c584bee6d00f4264dc Mon Sep 17 00:00:00 2001 From: Heba Aamer Date: Sat, 31 Jan 2015 04:48:00 +0200 Subject: [PATCH 2776/3023] staging: lustre: lustre: osc: modifying seq_printf statements This patch modifies the seq_printf statements in drivers/staging/lustre/lustre/osc/lproc_osc.c file. It changes it to seq_puts and seq_putc wherever applicable. Signed-off-by: Heba Aamer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/osc/lproc_osc.c | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/staging/lustre/lustre/osc/lproc_osc.c b/drivers/staging/lustre/lustre/osc/lproc_osc.c index 8e22e45e45f305..1795d3a7a02954 100644 --- a/drivers/staging/lustre/lustre/osc/lproc_osc.c +++ b/drivers/staging/lustre/lustre/osc/lproc_osc.c @@ -364,7 +364,7 @@ static int osc_checksum_type_seq_show(struct seq_file *m, void *v) else seq_printf(m, "%s ", cksum_name[i]); } - seq_printf(m, "\n"); + seq_putc(m, '\n'); return 0; } @@ -601,9 +601,9 @@ static int osc_rpc_stats_seq_show(struct seq_file *seq, void *v) seq_printf(seq, "pending read pages: %d\n", atomic_read(&cli->cl_pending_r_pages)); - seq_printf(seq, "\n\t\t\tread\t\t\twrite\n"); - seq_printf(seq, "pages per rpc rpcs %% cum %% |"); - seq_printf(seq, " rpcs %% cum %%\n"); + seq_puts(seq, "\n\t\t\tread\t\t\twrite\n"); + seq_puts(seq, "pages per rpc rpcs % cum % |"); + seq_puts(seq, " rpcs % cum %\n"); read_tot = lprocfs_oh_sum(&cli->cl_read_page_hist); write_tot = lprocfs_oh_sum(&cli->cl_write_page_hist); @@ -624,9 +624,9 @@ static int osc_rpc_stats_seq_show(struct seq_file *seq, void *v) break; } - seq_printf(seq, "\n\t\t\tread\t\t\twrite\n"); - seq_printf(seq, "rpcs in flight rpcs %% cum %% |"); - seq_printf(seq, " rpcs %% cum %%\n"); + seq_puts(seq, "\n\t\t\tread\t\t\twrite\n"); + seq_puts(seq, "rpcs in flight rpcs % cum % |"); + seq_puts(seq, " rpcs % cum %\n"); read_tot = lprocfs_oh_sum(&cli->cl_read_rpc_hist); write_tot = lprocfs_oh_sum(&cli->cl_write_rpc_hist); @@ -647,9 +647,9 @@ static int osc_rpc_stats_seq_show(struct seq_file *seq, void *v) break; } - seq_printf(seq, "\n\t\t\tread\t\t\twrite\n"); - seq_printf(seq, "offset rpcs %% cum %% |"); - seq_printf(seq, " rpcs %% cum %%\n"); + seq_puts(seq, "\n\t\t\tread\t\t\twrite\n"); + seq_puts(seq, "offset rpcs % cum % |"); + seq_puts(seq, " rpcs % cum %\n"); read_tot = lprocfs_oh_sum(&cli->cl_read_offset_hist); write_tot = lprocfs_oh_sum(&cli->cl_write_offset_hist); From 187e2a81805f4b7ba1acf118aed8937a718d894c Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 1 Feb 2015 11:59:38 +0000 Subject: [PATCH 2777/3023] staging: vt6655: move setting of PSTxDesc->buff_addr to vnt_tx_packet Keep setting of this part of the structure with the others. Only pTDInfo needs carried in the buffer structure. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/device_main.c | 2 ++ drivers/staging/vt6655/rxtx.c | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 58559fae7cf19d..9a801440d602e4 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -1217,6 +1217,8 @@ static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb) head_td->m_td1TD1.wReqCount = cpu_to_le16((u16)head_td->pTDInfo->dwReqCount); + head_td->buff_addr = cpu_to_le32(head_td->pTDInfo->skb_dma); + head_td->pTDInfo->byFlags = TD_FLAGS_NETIF_SKB; if (dma_idx == TYPE_AC0DMA) diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c index 9cade85a86c52e..07ce3fd88e70dd 100644 --- a/drivers/staging/vt6655/rxtx.c +++ b/drivers/staging/vt6655/rxtx.c @@ -1207,7 +1207,6 @@ s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType, ptdCurr->pTDInfo->dwReqCount = cbReqCount; ptdCurr->pTDInfo->dwHeaderLength = cbHeaderLength; ptdCurr->pTDInfo->skb_dma = ptdCurr->pTDInfo->buf_dma; - ptdCurr->buff_addr = cpu_to_le32(ptdCurr->pTDInfo->skb_dma); return cbHeaderLength; } From 64e4fd51421ffe750ea483f32370f60ca8435657 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 1 Feb 2015 11:59:39 +0000 Subject: [PATCH 2778/3023] staging: vt6655: parse bb vga code out of device_intr. Reordering the code and reversing the priv->byBBVGANew verses priv->byBBVGACurrent check and using dev_dbg for pr_debug. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/device_main.c | 93 ++++++++++++++++------------ 1 file changed, 54 insertions(+), 39 deletions(-) diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 9a801440d602e4..870cafd62deda2 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -1008,6 +1008,58 @@ static void device_free_tx_buf(struct vnt_private *pDevice, PSTxDesc pDesc) pTDInfo->byFlags = 0; } +static void vnt_check_bb_vga(struct vnt_private *priv) +{ + long dbm; + int i; + + if (!priv->bUpdateBBVGA) + return; + + if (priv->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) + return; + + if (!(priv->vif->bss_conf.assoc && priv->uCurrRSSI)) + return; + + RFvRSSITodBm(priv, (u8)priv->uCurrRSSI, &dbm); + + for (i = 0; i < BB_VGA_LEVEL; i++) { + if (dbm < priv->ldBmThreshold[i]) { + priv->byBBVGANew = priv->abyBBVGA[i]; + break; + } + } + + if (priv->byBBVGANew == priv->byBBVGACurrent) { + priv->uBBVGADiffCount = 1; + return; + } + + priv->uBBVGADiffCount++; + + if (priv->uBBVGADiffCount == 1) { + /* first VGA diff gain */ + BBvSetVGAGainOffset(priv, priv->byBBVGANew); + + dev_dbg(&priv->pcid->dev, + "First RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", + (int)dbm, priv->byBBVGANew, + priv->byBBVGACurrent, + (int)priv->uBBVGADiffCount); + } + + if (priv->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD) { + dev_dbg(&priv->pcid->dev, + "RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", + (int)dbm, priv->byBBVGANew, + priv->byBBVGACurrent, + (int)priv->uBBVGADiffCount); + + BBvSetVGAGainOffset(priv, priv->byBBVGANew); + } +} + static irqreturn_t device_intr(int irq, void *dev_instance) { struct vnt_private *pDevice = dev_instance; @@ -1015,7 +1067,6 @@ static irqreturn_t device_intr(int irq, void *dev_instance) unsigned long dwMIBCounter = 0; unsigned char byOrgPageSel = 0; int handled = 0; - int ii = 0; unsigned long flags; MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr); @@ -1059,44 +1110,8 @@ static irqreturn_t device_intr(int irq, void *dev_instance) if (pDevice->dwIsr & ISR_TBTT) { if (pDevice->vif && - pDevice->op_mode != NL80211_IFTYPE_ADHOC) { - if (pDevice->bUpdateBBVGA && - !(pDevice->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) && - pDevice->vif->bss_conf.assoc && - pDevice->uCurrRSSI) { - long ldBm; - - RFvRSSITodBm(pDevice, (unsigned char) pDevice->uCurrRSSI, &ldBm); - for (ii = 0; ii < BB_VGA_LEVEL; ii++) { - if (ldBm < pDevice->ldBmThreshold[ii]) { - pDevice->byBBVGANew = pDevice->abyBBVGA[ii]; - break; - } - } - if (pDevice->byBBVGANew != pDevice->byBBVGACurrent) { - pDevice->uBBVGADiffCount++; - if (pDevice->uBBVGADiffCount == 1) { - // first VGA diff gain - BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew); - pr_debug("First RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", - (int)ldBm, - pDevice->byBBVGANew, - pDevice->byBBVGACurrent, - (int)pDevice->uBBVGADiffCount); - } - if (pDevice->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD) { - pr_debug("RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", - (int)ldBm, - pDevice->byBBVGANew, - pDevice->byBBVGACurrent, - (int)pDevice->uBBVGADiffCount); - BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew); - } - } else { - pDevice->uBBVGADiffCount = 1; - } - } - } + pDevice->op_mode != NL80211_IFTYPE_ADHOC) + vnt_check_bb_vga(pDevice); pDevice->bBeaconSent = false; if (pDevice->bEnablePSMode) From d17f4c8a42256dae6aa598bdbc00eff8b38cc949 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 1 Feb 2015 11:59:40 +0000 Subject: [PATCH 2779/3023] staging: vt6655: Fix TD_FLAGS_NETIF_SKB only on TYPE_AC0DMA Allow only TD_FLAGS_NETIF_SKB on ring buffer TYPE_AC0DMA for data only transfers for correct reporting of tx rates. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/device_main.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 870cafd62deda2..4324282afe499b 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -1234,12 +1234,13 @@ static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb) head_td->buff_addr = cpu_to_le32(head_td->pTDInfo->skb_dma); - head_td->pTDInfo->byFlags = TD_FLAGS_NETIF_SKB; + if (dma_idx == TYPE_AC0DMA) { + head_td->pTDInfo->byFlags = TD_FLAGS_NETIF_SKB; - if (dma_idx == TYPE_AC0DMA) MACvTransmitAC0(priv->PortOffset); - else + } else { MACvTransmit0(priv->PortOffset); + } spin_unlock_irqrestore(&priv->lock, flags); From 6d854127268010f98c66c9e93fd278c2d76a6562 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 1 Feb 2015 11:59:41 +0000 Subject: [PATCH 2780/3023] staging: vt6655: vnt_rx_data add track rsr and new_rsr errors If not rsr & RSR_CRCOK report RX_FLAG_FAILED_FCS_CRC If not rsr & (RSR_IVLDTYP | RSR_IVLDLEN) drop packet If not NEWRSR_DECRYPTOK on new_rsr drop packet. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/dpc.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c index 11cc09014a5213..3c5b87ffdcaccb 100644 --- a/drivers/staging/vt6655/dpc.c +++ b/drivers/staging/vt6655/dpc.c @@ -91,6 +91,8 @@ static bool vnt_rx_data(struct vnt_private *priv, struct sk_buff *skb, new_rsr = skb_data + bytes_received - 3; rssi = skb_data + bytes_received - 2; rsr = skb_data + bytes_received - 1; + if (*rsr & (RSR_IVLDTYP | RSR_IVLDLEN)) + return false; RFvRSSITodBm(priv, *rssi, &rx_dbm); @@ -106,6 +108,9 @@ static bool vnt_rx_data(struct vnt_private *priv, struct sk_buff *skb, rx_status.flag = 0; rx_status.freq = hw->conf.chandef.chan->center_freq; + if (!(*rsr & RSR_CRCOK)) + rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; + hdr = (struct ieee80211_hdr *)(skb->data); fc = hdr->frame_control; @@ -113,7 +118,11 @@ static bool vnt_rx_data(struct vnt_private *priv, struct sk_buff *skb, if (ieee80211_has_protected(fc)) { if (priv->byLocalID > REV_ID_VT3253_A1) - rx_status.flag = RX_FLAG_DECRYPTED; + rx_status.flag |= RX_FLAG_DECRYPTED; + + /* Drop packet */ + if (!(*new_rsr & NEWRSR_DECRYPTOK)) + return false; } memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); From 5c9b063a0ae48acaba69ebffc43ea8214ff70c64 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 1 Feb 2015 11:59:42 +0000 Subject: [PATCH 2781/3023] staging: vt6656: vnt_fill_cts_head remove unneeded NULL check. union vnt_tx_data_head is nolonger detached from main vnt_tx_buffer structure so this check is unnecessary. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/rxtx.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index b74f672ff6965b..3b90497bc6e834 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -525,9 +525,6 @@ static u16 vnt_fill_cts_head(struct vnt_usb_send_context *tx_context, u32 cts_frame_len = 14; u16 current_rate = tx_context->tx_rate; - if (!head) - return 0; - if (tx_context->fb_option) { /* Auto Fall back */ struct vnt_cts_fb *buf = &head->cts_g_fb; From 1bdee7063533df3e2918138b42d32ca3958a85fd Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 1 Feb 2015 11:59:43 +0000 Subject: [PATCH 2782/3023] staging: vt6656: parse cts fall back out of vnt_fill_cts_head Creating new function vnt_fill_cts_fb_head for the fall back rates. The check for fb_option is now done in vnt_rxtx_cts. This fixes checkpatch warning WARNING: else is not generally useful after a break or return 559: FILE: drivers/staging/vt6656/rxtx.c:559: Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/rxtx.c | 99 +++++++++++++++++++---------------- 1 file changed, 54 insertions(+), 45 deletions(-) diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 3b90497bc6e834..33baf26de4b581 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -518,60 +518,66 @@ static u16 vnt_rxtx_rts_a_fb_head(struct vnt_usb_send_context *tx_context, return vnt_rxtx_datahead_a_fb(tx_context, &buf->data_head); } -static u16 vnt_fill_cts_head(struct vnt_usb_send_context *tx_context, - union vnt_tx_data_head *head) +static u16 vnt_fill_cts_fb_head(struct vnt_usb_send_context *tx_context, + union vnt_tx_data_head *head) { struct vnt_private *priv = tx_context->priv; + struct vnt_cts_fb *buf = &head->cts_g_fb; u32 cts_frame_len = 14; u16 current_rate = tx_context->tx_rate; - if (tx_context->fb_option) { - /* Auto Fall back */ - struct vnt_cts_fb *buf = &head->cts_g_fb; - /* Get SignalField,ServiceField,Length */ - vnt_get_phy_field(priv, cts_frame_len, - priv->top_cck_basic_rate, PK_TYPE_11B, &buf->b); - buf->duration_ba = - vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA, - tx_context->pkt_type, - current_rate); - /* Get CTSDuration_ba_f0 */ - buf->cts_duration_ba_f0 = - vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA_F0, - tx_context->pkt_type, - priv->tx_rate_fb0); - /* Get CTSDuration_ba_f1 */ - buf->cts_duration_ba_f1 = - vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA_F1, - tx_context->pkt_type, - priv->tx_rate_fb1); - /* Get CTS Frame body */ - buf->data.duration = buf->duration_ba; - buf->data.frame_control = - cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); + /* Get SignalField,ServiceField,Length */ + vnt_get_phy_field(priv, cts_frame_len, priv->top_cck_basic_rate, + PK_TYPE_11B, &buf->b); - ether_addr_copy(buf->data.ra, priv->current_net_addr); + buf->duration_ba = + vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA, + tx_context->pkt_type, + current_rate); + /* Get CTSDuration_ba_f0 */ + buf->cts_duration_ba_f0 = + vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA_F0, + tx_context->pkt_type, + priv->tx_rate_fb0); + /* Get CTSDuration_ba_f1 */ + buf->cts_duration_ba_f1 = + vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA_F1, + tx_context->pkt_type, + priv->tx_rate_fb1); + /* Get CTS Frame body */ + buf->data.duration = buf->duration_ba; + buf->data.frame_control = + cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); - return vnt_rxtx_datahead_g_fb(tx_context, &buf->data_head); - } else { - struct vnt_cts *buf = &head->cts_g; - /* Get SignalField,ServiceField,Length */ - vnt_get_phy_field(priv, cts_frame_len, - priv->top_cck_basic_rate, PK_TYPE_11B, &buf->b); - /* Get CTSDuration_ba */ - buf->duration_ba = - vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA, - tx_context->pkt_type, - current_rate); - /*Get CTS Frame body*/ - buf->data.duration = buf->duration_ba; - buf->data.frame_control = - cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); + ether_addr_copy(buf->data.ra, priv->current_net_addr); - ether_addr_copy(buf->data.ra, priv->current_net_addr); + return vnt_rxtx_datahead_g_fb(tx_context, &buf->data_head); +} - return vnt_rxtx_datahead_g(tx_context, &buf->data_head); - } +static u16 vnt_fill_cts_head(struct vnt_usb_send_context *tx_context, + union vnt_tx_data_head *head) +{ + struct vnt_private *priv = tx_context->priv; + struct vnt_cts *buf = &head->cts_g; + u32 cts_frame_len = 14; + u16 current_rate = tx_context->tx_rate; + + /* Get SignalField,ServiceField,Length */ + vnt_get_phy_field(priv, cts_frame_len, priv->top_cck_basic_rate, + PK_TYPE_11B, &buf->b); + /* Get CTSDuration_ba */ + buf->duration_ba = + vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA, + tx_context->pkt_type, + current_rate); + /*Get CTS Frame body*/ + buf->data.duration = buf->duration_ba; + buf->data.frame_control = + cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); + + ether_addr_copy(buf->data.ra, priv->current_net_addr); + + return vnt_rxtx_datahead_g(tx_context, &buf->data_head); } static u16 vnt_rxtx_rts(struct vnt_usb_send_context *tx_context, @@ -628,6 +634,9 @@ static u16 vnt_rxtx_cts(struct vnt_usb_send_context *tx_context, head = &tx_head->tx_cts.tx.mic.head; /* Fill CTS */ + if (tx_context->fb_option) + return vnt_fill_cts_fb_head(tx_context, head); + return vnt_fill_cts_head(tx_context, head); } From 2cc1a1b3eeee793e68f27efde9f0519c233b944f Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Sat, 31 Jan 2015 12:02:08 +0100 Subject: [PATCH 2783/3023] staging: unisys: use msecs_to_jiffies for conversions This is only an API consolidation to make things more readable. Instances of var * HZ / 1000 are replaced by msecs_to_jiffies(var). Signed-off-by: Nicholas Mc Guire Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/visorchipset_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 82e259dbc173bb..f606ee9e0de908 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -1594,7 +1594,7 @@ parahotplug_next_id(void) static unsigned long parahotplug_next_expiration(void) { - return jiffies + PARAHOTPLUG_TIMEOUT_MS * HZ / 1000; + return jiffies + msecs_to_jiffies(PARAHOTPLUG_TIMEOUT_MS); } /* From 048035bf8c7b752e9fe608ff3069e41c460efda5 Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Delgado Date: Mon, 2 Feb 2015 19:26:32 +0100 Subject: [PATCH 2784/3023] staging/unisys/visorutil/procobjecttree: Code Style Lines should not be over 80 characters Signed-off-by: Ricardo Ribalda Delgado Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorutil/procobjecttree.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/unisys/visorutil/procobjecttree.c b/drivers/staging/unisys/visorutil/procobjecttree.c index 195772d22c9edc..637c5ef1a76724 100644 --- a/drivers/staging/unisys/visorutil/procobjecttree.c +++ b/drivers/staging/unisys/visorutil/procobjecttree.c @@ -260,9 +260,9 @@ MYPROCOBJECT *visor_proc_CreateObject(MYPROCTYPE *type, ERRDRV("out of memory\n"); goto Away; } - obj->procDirProperties = - kzalloc((type->nProperties + 1) * sizeof(struct proc_dir_entry *), - GFP_KERNEL | __GFP_NORETRY); + obj->procDirProperties = kzalloc((type->nProperties + 1) * + sizeof(struct proc_dir_entry *), + GFP_KERNEL | __GFP_NORETRY); if (obj->procDirProperties == NULL) { ERRDRV("out of memory\n"); goto Away; @@ -276,8 +276,8 @@ MYPROCOBJECT *visor_proc_CreateObject(MYPROCTYPE *type, /* only create properties that have names */ obj->procDirProperties[i] = createProcFile(type->propertyNames[i], - obj->procDir, &proc_fops, - &obj->procDirPropertyContexts[i]); + obj->procDir, &proc_fops, + &obj->procDirPropertyContexts[i]); if (obj->procDirProperties[i] == NULL) { rc = NULL; goto Away; From 4abfc1f5fb846bbc8b151aa35eae2c2fea686e89 Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Delgado Date: Mon, 2 Feb 2015 19:55:46 +0100 Subject: [PATCH 2785/3023] staging/unisys/visorutil/procobjecttree: Replace typedef Instead of declaring a new type, define a new struct. Signed-off-by: Ricardo Ribalda Delgado Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorutil/procobjecttree.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/staging/unisys/visorutil/procobjecttree.c b/drivers/staging/unisys/visorutil/procobjecttree.c index 637c5ef1a76724..82279ca5fbe1d5 100644 --- a/drivers/staging/unisys/visorutil/procobjecttree.c +++ b/drivers/staging/unisys/visorutil/procobjecttree.c @@ -25,12 +25,12 @@ * need in order to call the callback function that supplies the /proc read * info for that file. */ -typedef struct { +struct proc_dir_entry_context { void (*show_property)(struct seq_file *, void *, int); MYPROCOBJECT *procObject; int propertyIndex; -} PROCDIRENTRYCONTEXT; +}; /** This describes the attributes of a tree rooted at * ///... @@ -86,7 +86,7 @@ struct MYPROCOBJECT_Tag { /** this is a holding area for the context information that is needed * to run the /proc callback function */ - PROCDIRENTRYCONTEXT *procDirPropertyContexts; + struct proc_dir_entry_context *procDirPropertyContexts; }; @@ -254,7 +254,8 @@ MYPROCOBJECT *visor_proc_CreateObject(MYPROCTYPE *type, goto Away; } obj->procDirPropertyContexts = - kzalloc((type->nProperties + 1) * sizeof(PROCDIRENTRYCONTEXT), + kzalloc((type->nProperties + 1) * + sizeof(struct proc_dir_entry_context), GFP_KERNEL | __GFP_NORETRY); if (obj->procDirPropertyContexts == NULL) { ERRDRV("out of memory\n"); @@ -340,7 +341,7 @@ EXPORT_SYMBOL_GPL(visor_proc_DestroyObject); static int seq_show(struct seq_file *seq, void *offset) { - PROCDIRENTRYCONTEXT *ctx = (PROCDIRENTRYCONTEXT *)(seq->private); + struct proc_dir_entry_context *ctx = seq->private; if (ctx == NULL) { ERRDRV("I don't have a freakin' clue..."); From 659688a51a0e7427be2b2e38baeaa7f30ba16bcb Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Thu, 5 Feb 2015 14:35:54 +0100 Subject: [PATCH 2786/3023] staging: unisys: Fix typo in comment Signed-off-by: Bastien Nocera Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/virthba/virthba.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/unisys/virthba/virthba.c b/drivers/staging/unisys/virthba/virthba.c index 8cd090b9ecce32..e6ecea560495fa 100644 --- a/drivers/staging/unisys/virthba/virthba.c +++ b/drivers/staging/unisys/virthba/virthba.c @@ -479,7 +479,7 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id) * instance - this virthba that has just been created is an * instance of a scsi host adapter. This scsi_host_alloc * function allocates a new Scsi_Host struct & performs basic - * initializatoin. The host is not published to the scsi + * initialization. The host is not published to the scsi * midlayer until scsi_add_host is called. */ DBGINF("calling scsi_host_alloc.\n"); From 509031dd5f5ae008ef5d4d04226ce63ca8c84354 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 1 Feb 2015 17:01:33 +0200 Subject: [PATCH 2787/3023] staging: xgifb: fix colours on big-endian machines other than powerpc XGI framebuffer supports big-endian machines, but it's currently enabled based on __powerpc__ define (which is wrong, as powerpc can be also little-endian now). Use __BIG_ENDIAN instead. This will fix wrong colours on such machines. Tested on parisc with XGI Z7. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 74a8db8223fee6..935c714f592a47 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -930,7 +930,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, + var->hsync_len; unsigned int vtotal = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; -#if defined(__powerpc__) +#if defined(__BIG_ENDIAN) u8 cr_data; #endif unsigned int drate = 0, hrate = 0; @@ -1044,7 +1044,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, xgifb_info->DstColor = 0x0000; xgifb_info->XGI310_AccelDepth = 0x00000000; xgifb_info->video_cmap_len = 256; -#if defined(__powerpc__) +#if defined(__BIG_ENDIAN) cr_data = xgifb_reg_get(XGICR, 0x4D); xgifb_reg_set(XGICR, 0x4D, (cr_data & 0xE0)); #endif @@ -1052,7 +1052,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, case 16: xgifb_info->DstColor = 0x8000; xgifb_info->XGI310_AccelDepth = 0x00010000; -#if defined(__powerpc__) +#if defined(__BIG_ENDIAN) cr_data = xgifb_reg_get(XGICR, 0x4D); xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B)); #endif @@ -1062,7 +1062,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, xgifb_info->DstColor = 0xC000; xgifb_info->XGI310_AccelDepth = 0x00020000; xgifb_info->video_cmap_len = 16; -#if defined(__powerpc__) +#if defined(__BIG_ENDIAN) cr_data = xgifb_reg_get(XGICR, 0x4D); xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15)); #endif From 7dfb6d2ec4547a6fd83571f6beeee47db9184847 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Sat, 31 Jan 2015 11:51:54 +0100 Subject: [PATCH 2788/3023] staging: rtl8712: cleanup of timeout conversions This is only an API consolidation to make things more readable. Instances of var * HZ / 1000 are replaced by msecs_to_jiffies(var). As msecs_to_jiffies will return > 0 if it is passed a value > 0 the == 0 check is not needed. Signed-off-by: Nicholas Mc Guire Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/osdep_service.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rtl8712/osdep_service.h b/drivers/staging/rtl8712/osdep_service.h index 5153ad9c2c758d..f9337135340b39 100644 --- a/drivers/staging/rtl8712/osdep_service.h +++ b/drivers/staging/rtl8712/osdep_service.h @@ -71,7 +71,7 @@ static inline void _init_timer(struct timer_list *ptimer, static inline void _set_timer(struct timer_list *ptimer, u32 delay_time) { - mod_timer(ptimer, (jiffies+(delay_time*HZ/1000))); + mod_timer(ptimer, (jiffies+msecs_to_jiffies(delay_time))); } static inline void _cancel_timer(struct timer_list *ptimer, u8 *bcancelled) @@ -101,9 +101,7 @@ static inline void sleep_schedulable(int ms) { u32 delta; - delta = (ms * HZ) / 1000;/*(ms)*/ - if (delta == 0) - delta = 1;/* 1 ms */ + delta = msecs_to_jiffies(ms);/*(ms)*/ set_current_state(TASK_INTERRUPTIBLE); if (schedule_timeout(delta) != 0) return; From 1ba2c5a8087b8760087ff29a30b0aa4ae9802bb2 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Sat, 31 Jan 2015 11:52:14 +0100 Subject: [PATCH 2789/3023] staging: rtl8712: condition with no effect removed The check for return of schedule_timeout() has no effect on the effective control flow of sleep_schedulable() so it can be dropped. Signed-off-by: Nicholas Mc Guire Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/osdep_service.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/rtl8712/osdep_service.h b/drivers/staging/rtl8712/osdep_service.h index f9337135340b39..36348d900d34b9 100644 --- a/drivers/staging/rtl8712/osdep_service.h +++ b/drivers/staging/rtl8712/osdep_service.h @@ -103,8 +103,7 @@ static inline void sleep_schedulable(int ms) delta = msecs_to_jiffies(ms);/*(ms)*/ set_current_state(TASK_INTERRUPTIBLE); - if (schedule_timeout(delta) != 0) - return; + schedule_timeout(delta); } static inline unsigned char _cancel_timer_ex(struct timer_list *ptimer) From 37257276a47696aac3ef11aa90f95cfaa723dddf Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Sat, 31 Jan 2015 12:10:07 +0100 Subject: [PATCH 2790/3023] staging: rtl8188eu: use msecs_to_jiffies for conversions This is only an API consolidation to make things more readable. Instances of var * HZ / 1000 are replaced by msecs_to_jiffies(var). Signed-off-by: Nicholas Mc Guire Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/include/osdep_service.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8188eu/include/osdep_service.h b/drivers/staging/rtl8188eu/include/osdep_service.h index 82f58f87656a6b..3a274770364b01 100644 --- a/drivers/staging/rtl8188eu/include/osdep_service.h +++ b/drivers/staging/rtl8188eu/include/osdep_service.h @@ -87,7 +87,7 @@ static inline void _init_timer(struct timer_list *ptimer, static inline void _set_timer(struct timer_list *ptimer, u32 delay_time) { - mod_timer(ptimer , (jiffies+(delay_time*HZ/1000))); + mod_timer(ptimer , (jiffies+msecs_to_jiffies(delay_time))); } #define RTW_TIMER_HDL_ARGS void *FunctionContext From 98ab6ff914b367bfd4aff30e2e94e01fb8a443af Mon Sep 17 00:00:00 2001 From: Kolbeinn Karlsson Date: Sat, 31 Jan 2015 13:14:33 -0500 Subject: [PATCH 2791/3023] Staging: rtl8192e: Fixed unnecessary line continuation. Fixed a coding style issue. Signed-off-by: Kolbeinn Karlsson Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_module.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/staging/rtl8192e/rtllib_module.c b/drivers/staging/rtl8192e/rtllib_module.c index 91e98e8e5bfc01..0cf38091f8c51c 100644 --- a/drivers/staging/rtl8192e/rtllib_module.c +++ b/drivers/staging/rtl8192e/rtllib_module.c @@ -202,9 +202,7 @@ void free_rtllib(struct net_device *dev) EXPORT_SYMBOL(free_rtllib); u32 rtllib_debug_level; -static int debug = \ - RTLLIB_DL_ERR - ; +static int debug = RTLLIB_DL_ERR; static struct proc_dir_entry *rtllib_proc; static int show_debug_level(struct seq_file *m, void *v) From b47ea4bbfefac60ba24ae4ada637f997ed694716 Mon Sep 17 00:00:00 2001 From: Andreas Ruprecht Date: Mon, 2 Feb 2015 20:24:14 +0100 Subject: [PATCH 2792/3023] staging: lustre: osc: Make osc_init() static osc_init() is marked as the module_init function in osc_request.c and is never used anywhere else. Hence, it can (and should) be declared static. sparse also complained about this with the following warning, which is fixed by this patch. andreas@workbox:~/linux-next$ make C=1 M=drivers/staging/lustre/lustre/osc/ [...] drivers/staging/lustre/lustre/osc/osc_request.c:3335:12: warning: symbol 'osc_init' was not declared. Should it be static? [...] Signed-off-by: Andreas Ruprecht Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/osc/osc_request.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index b9450b95f1c593..0adfa707a76333 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -3332,7 +3332,7 @@ extern struct lu_kmem_descr osc_caches[]; extern spinlock_t osc_ast_guard; extern struct lock_class_key osc_ast_guard_class; -int __init osc_init(void) +static int __init osc_init(void) { struct lprocfs_static_vars lvars = { NULL }; int rc; From fa55c6a4b41cd4fd240debe719b205056b04a0bf Mon Sep 17 00:00:00 2001 From: Liang Zhen Date: Sun, 1 Feb 2015 21:52:00 -0500 Subject: [PATCH 2793/3023] staging/lustre/ptlrpc: avoid list scan in ptlrpcd_check ptlrpcd_check() always scan all requests on ptlrpc_request_set and try to finish completed requests, this is low efficiency. Even worse, l_wait_event() always checks condition for twice before sleeping and one more time after waking up, which means it will call ptlrpcd_check() for three times in each loop. This patch will move completed requests at the head of list in ptlrpc_check_set(), with this change ptlrpcd_check doesn't need to scan all requests anymore. Signed-off-by: Liang Zhen Reviewed-on: http://review.whamcloud.com/11513 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5548 Reviewed-by: Bobi Jam Reviewed-by: Andreas Dilger Reviewed-by: Johann Lombardi Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/client.c | 12 +++++++++- .../staging/lustre/lustre/ptlrpc/ptlrpcd.c | 23 ++++++++----------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index dc9e406f32124b..8c1ec830712f0c 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -1497,11 +1497,13 @@ static inline int ptlrpc_set_producer(struct ptlrpc_request_set *set) int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set) { struct list_head *tmp, *next; + struct list_head comp_reqs; int force_timer_recalc = 0; if (atomic_read(&set->set_remaining) == 0) return 1; + INIT_LIST_HEAD(&comp_reqs); list_for_each_safe(tmp, next, &set->set_requests) { struct ptlrpc_request *req = list_entry(tmp, struct ptlrpc_request, @@ -1576,8 +1578,10 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set) ptlrpc_rqphase_move(req, req->rq_next_phase); } - if (req->rq_phase == RQ_PHASE_COMPLETE) + if (req->rq_phase == RQ_PHASE_COMPLETE) { + list_move_tail(&req->rq_set_chain, &comp_reqs); continue; + } if (req->rq_phase == RQ_PHASE_INTERPRET) goto interpret; @@ -1860,9 +1864,15 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set) if (req->rq_status != 0) set->set_rc = req->rq_status; ptlrpc_req_finished(req); + } else { + list_move_tail(&req->rq_set_chain, &comp_reqs); } } + /* move completed request at the head of list so it's easier for + * caller to find them */ + list_splice(&comp_reqs, &set->set_requests); + /* If we hit an error, we want to recover promptly. */ return atomic_read(&set->set_remaining) == 0 || force_timer_recalc; } diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c index cbcc541cac4312..4621b71fe0b6bc 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c @@ -306,21 +306,16 @@ static int ptlrpcd_check(struct lu_env *env, struct ptlrpcd_ctl *pc) if (atomic_read(&set->set_remaining)) rc |= ptlrpc_check_set(env, set); - if (!list_empty(&set->set_requests)) { - /* - * XXX: our set never completes, so we prune the completed - * reqs after each iteration. boy could this be smarter. - */ - list_for_each_safe(pos, tmp, &set->set_requests) { - req = list_entry(pos, struct ptlrpc_request, - rq_set_chain); - if (req->rq_phase != RQ_PHASE_COMPLETE) - continue; + /* NB: ptlrpc_check_set has already moved completed request at the + * head of seq::set_requests */ + list_for_each_safe(pos, tmp, &set->set_requests) { + req = list_entry(pos, struct ptlrpc_request, rq_set_chain); + if (req->rq_phase != RQ_PHASE_COMPLETE) + break; - list_del_init(&req->rq_set_chain); - req->rq_set = NULL; - ptlrpc_req_finished(req); - } + list_del_init(&req->rq_set_chain); + req->rq_set = NULL; + ptlrpc_req_finished(req); } if (rc == 0) { From c00266e369b945945316dad3869342d07f4be868 Mon Sep 17 00:00:00 2001 From: Alexander Boyko Date: Sun, 1 Feb 2015 21:52:01 -0500 Subject: [PATCH 2794/3023] staging/lustre/osc: split different type of IO Do not allow different type of pages at the same rpc. Signed-off-by: Alexander Boyko Signed-off-by: Vitaly Fertman Xyratex-bug-id: MRP-859 Reviewed-on: http://review.whamcloud.com/10930 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3192 Reviewed-by: Jinshan Xiong Reviewed-by: Niu Yawei Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/osc/osc_cache.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index 370e6d4896c63c..7022ed42d2d124 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -1820,6 +1820,9 @@ static int try_to_add_extent_for_io(struct client_obd *cli, int *pc, unsigned int *max_pages) { struct osc_extent *tmp; + struct osc_async_page *oap = list_first_entry(&ext->oe_pages, + struct osc_async_page, + oap_pending_item); EASSERT((ext->oe_state == OES_CACHE || ext->oe_state == OES_LOCK_DONE), ext); @@ -1829,6 +1832,10 @@ static int try_to_add_extent_for_io(struct client_obd *cli, return 0; list_for_each_entry(tmp, rpclist, oe_link) { + struct osc_async_page *oap2; + + oap2 = list_first_entry(&tmp->oe_pages, struct osc_async_page, + oap_pending_item); EASSERT(tmp->oe_owner == current, tmp); #if 0 if (overlapped(tmp, ext)) { @@ -1836,6 +1843,11 @@ static int try_to_add_extent_for_io(struct client_obd *cli, EASSERT(0, ext); } #endif + if (oap2cl_page(oap)->cp_type != oap2cl_page(oap2)->cp_type) { + CDEBUG(D_CACHE, "Do not permit different type of IO" + " for a same RPC\n"); + return 0; + } if (tmp->oe_srvlock != ext->oe_srvlock || !tmp->oe_grants != !ext->oe_grants) From 4d2c7b309d17a5609a5d4ede628d16828262ca00 Mon Sep 17 00:00:00 2001 From: Li Xi Date: Sun, 1 Feb 2015 21:52:02 -0500 Subject: [PATCH 2795/3023] staging/lustre/ldlm: high load because of negative timeout When the time of LRU resizing exceeds waiting period of recalculation, the ldlm daemon will keep on resizing without any interval of rest. That will cause high CPU load. This patch fixes the problem by setting the recalculation timestamp after LRU resizing finishes rather than before it. What is more, an interval of one second is enforced between each recalculation. Signed-off-by: Li Xi Reviewed-on: http://review.whamcloud.com/11227 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5415 Reviewed-by: Dmitry Eremin Reviewed-by: Bobi Jam Reviewed-by: Lai Siyao Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/ldlm/ldlm_pool.c | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c index 142b3dd598cbf5..d20d277dc2f764 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c @@ -470,6 +470,7 @@ static void ldlm_cli_pool_pop_slv(struct ldlm_pool *pl) static int ldlm_cli_pool_recalc(struct ldlm_pool *pl) { time_t recalc_interval_sec; + int ret; recalc_interval_sec = get_seconds() - pl->pl_recalc_time; if (recalc_interval_sec < pl->pl_recalc_period) @@ -490,16 +491,15 @@ static int ldlm_cli_pool_recalc(struct ldlm_pool *pl) */ ldlm_cli_pool_pop_slv(pl); - pl->pl_recalc_time = get_seconds(); - lprocfs_counter_add(pl->pl_stats, LDLM_POOL_TIMING_STAT, - recalc_interval_sec); spin_unlock(&pl->pl_lock); /* * Do not cancel locks in case lru resize is disabled for this ns. */ - if (!ns_connect_lru_resize(ldlm_pl2ns(pl))) - return 0; + if (!ns_connect_lru_resize(ldlm_pl2ns(pl))) { + ret = 0; + goto out; + } /* * In the time of canceling locks on client we do not need to maintain @@ -507,7 +507,19 @@ static int ldlm_cli_pool_recalc(struct ldlm_pool *pl) * It may be called when SLV has changed much, this is why we do not * take into account pl->pl_recalc_time here. */ - return ldlm_cancel_lru(ldlm_pl2ns(pl), 0, LCF_ASYNC, LDLM_CANCEL_LRUR); + ret = ldlm_cancel_lru(ldlm_pl2ns(pl), 0, LCF_ASYNC, LDLM_CANCEL_LRUR); + +out: + spin_lock(&pl->pl_lock); + /* + * Time of LRU resizing might be longer than period, + * so update after LRU resizing rather than before it. + */ + pl->pl_recalc_time = get_seconds(); + lprocfs_counter_add(pl->pl_stats, LDLM_POOL_TIMING_STAT, + recalc_interval_sec); + spin_unlock(&pl->pl_lock); + return ret; } /** @@ -591,6 +603,14 @@ int ldlm_pool_recalc(struct ldlm_pool *pl) } recalc_interval_sec = pl->pl_recalc_time - get_seconds() + pl->pl_recalc_period; + if (recalc_interval_sec <= 0) { + /* Prevent too frequent recalculation. */ + CDEBUG(D_DLMTRACE, "Negative interval(%ld), " + "too short period(%ld)", + recalc_interval_sec, + pl->pl_recalc_period); + recalc_interval_sec = 1; + } return recalc_interval_sec; } From 89975ff91e1a1a9396804976e49b794755168c6a Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Fri, 30 Jan 2015 19:47:36 -0500 Subject: [PATCH 2796/3023] staging/lustre: remove unused lustre_update.h header lustre_update.h containts various server-side structures that are not really relevant for the client. Also remove the only user of this file that does not actually need it. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lustre_update.h | 189 ------------------ drivers/staging/lustre/lustre/ptlrpc/layout.c | 1 - 2 files changed, 190 deletions(-) delete mode 100644 drivers/staging/lustre/lustre/include/lustre_update.h diff --git a/drivers/staging/lustre/lustre/include/lustre_update.h b/drivers/staging/lustre/lustre/include/lustre_update.h deleted file mode 100644 index 84defce0f6231a..00000000000000 --- a/drivers/staging/lustre/lustre/include/lustre_update.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.gnu.org/licenses/gpl-2.0.htm - * - * GPL HEADER END - */ -/* - * Copyright (c) 2013, Intel Corporation. - */ -/* - * lustre/include/lustre_update.h - * - * Author: Di Wang - */ - -#ifndef _LUSTRE_UPDATE_H -#define _LUSTRE_UPDATE_H - -#define UPDATE_BUFFER_SIZE 8192 -struct update_request { - struct dt_device *ur_dt; - struct list_head ur_list; /* attached itself to thandle */ - int ur_flags; - int ur_rc; /* request result */ - int ur_batchid; /* Current batch(trans) id */ - struct update_buf *ur_buf; /* Holding the update req */ -}; - -static inline unsigned long update_size(struct update *update) -{ - unsigned long size; - int i; - - size = cfs_size_round(offsetof(struct update, u_bufs[0])); - for (i = 0; i < UPDATE_BUF_COUNT; i++) - size += cfs_size_round(update->u_lens[i]); - - return size; -} - -static inline void *update_param_buf(struct update *update, int index, - int *size) -{ - int i; - void *ptr; - - if (index >= UPDATE_BUF_COUNT) - return NULL; - - ptr = (char *)update + cfs_size_round(offsetof(struct update, - u_bufs[0])); - for (i = 0; i < index; i++) { - LASSERT(update->u_lens[i] > 0); - ptr += cfs_size_round(update->u_lens[i]); - } - - if (size != NULL) - *size = update->u_lens[index]; - - return ptr; -} - -static inline unsigned long update_buf_size(struct update_buf *buf) -{ - unsigned long size; - int i = 0; - - size = cfs_size_round(offsetof(struct update_buf, ub_bufs[0])); - for (i = 0; i < buf->ub_count; i++) { - struct update *update; - - update = (struct update *)((char *)buf + size); - size += update_size(update); - } - LASSERT(size <= UPDATE_BUFFER_SIZE); - return size; -} - -static inline void *update_buf_get(struct update_buf *buf, int index, int *size) -{ - int count = buf->ub_count; - void *ptr; - int i = 0; - - if (index >= count) - return NULL; - - ptr = (char *)buf + cfs_size_round(offsetof(struct update_buf, - ub_bufs[0])); - for (i = 0; i < index; i++) - ptr += update_size((struct update *)ptr); - - if (size != NULL) - *size = update_size((struct update *)ptr); - - return ptr; -} - -static inline void update_init_reply_buf(struct update_reply *reply, int count) -{ - reply->ur_version = UPDATE_REPLY_V1; - reply->ur_count = count; -} - -static inline void *update_get_buf_internal(struct update_reply *reply, - int index, int *size) -{ - char *ptr; - int count = reply->ur_count; - int i; - - if (index >= count) - return NULL; - - ptr = (char *)reply + cfs_size_round(offsetof(struct update_reply, - ur_lens[count])); - for (i = 0; i < index; i++) { - LASSERT(reply->ur_lens[i] > 0); - ptr += cfs_size_round(reply->ur_lens[i]); - } - - if (size != NULL) - *size = reply->ur_lens[index]; - - return ptr; -} - -static inline void update_insert_reply(struct update_reply *reply, void *data, - int data_len, int index, int rc) -{ - char *ptr; - - ptr = update_get_buf_internal(reply, index, NULL); - LASSERT(ptr != NULL); - - *(int *)ptr = cpu_to_le32(rc); - ptr += sizeof(int); - if (data_len > 0) { - LASSERT(data != NULL); - memcpy(ptr, data, data_len); - } - reply->ur_lens[index] = data_len + sizeof(int); -} - -static inline int update_get_reply_buf(struct update_reply *reply, void **buf, - int index) -{ - char *ptr; - int size = 0; - int result; - - ptr = update_get_buf_internal(reply, index, &size); - result = *(int *)ptr; - - if (result < 0) - return result; - - LASSERT((ptr != NULL && size >= sizeof(int))); - *buf = ptr + sizeof(int); - return size - sizeof(int); -} - -static inline int update_get_reply_result(struct update_reply *reply, - void **buf, int index) -{ - void *ptr; - int size; - - ptr = update_get_buf_internal(reply, index, &size); - LASSERT(ptr != NULL && size > sizeof(int)); - return *(int *)ptr; -} - -#endif diff --git a/drivers/staging/lustre/lustre/ptlrpc/layout.c b/drivers/staging/lustre/lustre/ptlrpc/layout.c index dc5ceb55d001c7..bbef666b1d167b 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/layout.c +++ b/drivers/staging/lustre/lustre/ptlrpc/layout.c @@ -65,7 +65,6 @@ #endif /* struct ptlrpc_request, lustre_msg* */ #include "../include/lustre_req_layout.h" -#include "../include/lustre_update.h" #include "../include/lustre_acl.h" #include "../include/lustre_debug.h" From c5ce36f6b06217d6d03006a5fe2aef19918b9081 Mon Sep 17 00:00:00 2001 From: Asaf Vertz Date: Sun, 1 Feb 2015 13:28:46 +0200 Subject: [PATCH 2797/3023] staging: lustre: osc: fix space prohibited after that '!' Fixed a coding style error, space prohibited after that '!' Signed-off-by: Asaf Vertz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/osc/osc_lock.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/lustre/lustre/osc/osc_lock.c b/drivers/staging/lustre/lustre/osc/osc_lock.c index a7f08bc48166f8..44565572490464 100644 --- a/drivers/staging/lustre/lustre/osc/osc_lock.c +++ b/drivers/staging/lustre/lustre/osc/osc_lock.c @@ -100,14 +100,14 @@ static int osc_lock_invariant(struct osc_lock *ols) /* * If all the following "ergo"s are true, return 1, otherwise 0 */ - if (! ergo(olock != NULL, handle_used)) + if (!ergo(olock != NULL, handle_used)) return 0; - if (! ergo(olock != NULL, + if (!ergo(olock != NULL, olock->l_handle.h_cookie == ols->ols_handle.cookie)) return 0; - if (! ergo(handle_used, + if (!ergo(handle_used, ergo(lock != NULL && olock != NULL, lock == olock) && ergo(lock == NULL, olock == NULL))) return 0; @@ -115,18 +115,18 @@ static int osc_lock_invariant(struct osc_lock *ols) * Check that ->ols_handle and ->ols_lock are consistent, but * take into account that they are set at the different time. */ - if (! ergo(ols->ols_state == OLS_CANCELLED, + if (!ergo(ols->ols_state == OLS_CANCELLED, olock == NULL && !handle_used)) return 0; /* * DLM lock is destroyed only after we have seen cancellation * ast. */ - if (! ergo(olock != NULL && ols->ols_state < OLS_CANCELLED, + if (!ergo(olock != NULL && ols->ols_state < OLS_CANCELLED, ((olock->l_flags & LDLM_FL_DESTROYED) == 0))) return 0; - if (! ergo(ols->ols_state == OLS_GRANTED, + if (!ergo(ols->ols_state == OLS_GRANTED, olock != NULL && olock->l_req_mode == olock->l_granted_mode && ols->ols_hold)) From 13534f8f310bcc2a0ac3184a160c72a17c244684 Mon Sep 17 00:00:00 2001 From: Asaf Vertz Date: Sun, 1 Feb 2015 13:29:23 +0200 Subject: [PATCH 2798/3023] staging: lustre: lnet: fix space prohibited before that '++' Fixed a coding style error, space prohibited before that '++' Signed-off-by: Asaf Vertz Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lnet/selftest/console.c | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 3bb47fa5d5c327..1e0afc28684797 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -46,17 +46,17 @@ #include "console.h" #include "conrpc.h" -#define LST_NODE_STATE_COUNTER(nd, p) \ -do { \ - if ((nd)->nd_state == LST_NODE_ACTIVE) \ - (p)->nle_nactive ++; \ +#define LST_NODE_STATE_COUNTER(nd, p) \ +do { \ + if ((nd)->nd_state == LST_NODE_ACTIVE) \ + (p)->nle_nactive++; \ else if ((nd)->nd_state == LST_NODE_BUSY) \ - (p)->nle_nbusy ++; \ + (p)->nle_nbusy++; \ else if ((nd)->nd_state == LST_NODE_DOWN) \ - (p)->nle_ndown ++; \ - else \ - (p)->nle_nunknown ++; \ - (p)->nle_nnode ++; \ + (p)->nle_ndown++; \ + else \ + (p)->nle_nunknown++; \ + (p)->nle_nnode++; \ } while (0) lstcon_session_t console_session; @@ -223,7 +223,7 @@ lstcon_group_alloc(char *name, lstcon_group_t **grpp) static void lstcon_group_addref(lstcon_group_t *grp) { - grp->grp_ref ++; + grp->grp_ref++; } static void lstcon_group_ndlink_release(lstcon_group_t *, lstcon_ndlink_t *); @@ -298,7 +298,7 @@ lstcon_group_ndlink_find(lstcon_group_t *grp, lnet_process_id_t id, return 0; list_add_tail(&(*ndlpp)->ndl_link, &grp->grp_ndl_list); - grp->grp_nnode ++; + grp->grp_nnode++; return 0; } @@ -324,7 +324,7 @@ lstcon_group_ndlink_move(lstcon_group_t *old, list_add_tail(&ndl->ndl_hlink, &new->grp_ndl_hash[idx]); list_add_tail(&ndl->ndl_link, &new->grp_ndl_list); - new->grp_nnode ++; + new->grp_nnode++; return; } @@ -767,7 +767,7 @@ lstcon_nodes_getent(struct list_head *head, int *index_p, &nd->nd_state, sizeof(nd->nd_state))) return -EFAULT; - count ++; + count++; } if (index <= *index_p) @@ -1343,7 +1343,7 @@ lstcon_test_add(char *batch_name, int type, int loop, /* add to test list anyway, so user can check what's going on */ list_add_tail(&test->tes_link, &batch->bat_test_list); - batch->bat_ntest ++; + batch->bat_ntest++; test->tes_hdr.tsb_index = batch->bat_ntest; /* hold groups so nobody can change them */ From 2661e6c45625abd32d6447cafb8d9b99839ce408 Mon Sep 17 00:00:00 2001 From: Li Xi Date: Sun, 1 Feb 2015 21:52:03 -0500 Subject: [PATCH 2799/3023] staging/lustre/libcfs: fix illegal page access of tracefiled() After failure happens and put_pages_back() returns the pages, tracefiled() should not go on itering on the page list. Otherwise, some pages might be accessed illegally. Signed-off-by: Li Xi Signed-off-by: Jian Yu Reviewed-on: http://review.whamcloud.com/11454 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5126 Reviewed-by: Emoly Liu Reviewed-by: Niu Yawei Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/libcfs/tracefile.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/lustre/lustre/libcfs/tracefile.c b/drivers/staging/lustre/lustre/libcfs/tracefile.c index d18de048fa431c..eb65b50f832deb 100644 --- a/drivers/staging/lustre/lustre/libcfs/tracefile.c +++ b/drivers/staging/lustre/lustre/libcfs/tracefile.c @@ -1037,6 +1037,7 @@ static int tracefiled(void *arg) tage->used, rc); put_pages_back(&pc); __LASSERT(list_empty(&pc.pc_pages)); + break; } } MMSPACE_CLOSE; From 62e4941354c38c968474a909a5a89395ccff0067 Mon Sep 17 00:00:00 2001 From: Hongchao Zhang Date: Sun, 1 Feb 2015 21:52:04 -0500 Subject: [PATCH 2800/3023] staging/lustre/obdclass: fix a race in recovery in "class_export_recovery_cleanup", the check of the flag "exp->exp_req_replay_needed" should be protected by "exp_lock". Signed-off-by: Hongchao Zhang Reviewed-on: http://review.whamcloud.com/10849 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5128 Reviewed-by: Fan Yong Reviewed-by: Andreas Dilger Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/genops.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c index 736ca410aca3b5..82508210465eeb 100644 --- a/drivers/staging/lustre/lustre/obdclass/genops.c +++ b/drivers/staging/lustre/lustre/obdclass/genops.c @@ -1151,22 +1151,24 @@ void class_export_recovery_cleanup(struct obd_export *exp) exp->exp_obd->obd_stale_clients++; } spin_unlock(&obd->obd_recovery_task_lock); + + spin_lock(&exp->exp_lock); /** Cleanup req replay fields */ if (exp->exp_req_replay_needed) { - spin_lock(&exp->exp_lock); exp->exp_req_replay_needed = 0; - spin_unlock(&exp->exp_lock); + LASSERT(atomic_read(&obd->obd_req_replay_clients)); atomic_dec(&obd->obd_req_replay_clients); } + /** Cleanup lock replay data */ if (exp->exp_lock_replay_needed) { - spin_lock(&exp->exp_lock); exp->exp_lock_replay_needed = 0; - spin_unlock(&exp->exp_lock); + LASSERT(atomic_read(&obd->obd_lock_replay_clients)); atomic_dec(&obd->obd_lock_replay_clients); } + spin_unlock(&exp->exp_lock); } /* This function removes 1-3 references from the export: From af3fa7c71bf61a4ff8e9203860c24795183f9da4 Mon Sep 17 00:00:00 2001 From: Liang Zhen Date: Sun, 1 Feb 2015 21:52:06 -0500 Subject: [PATCH 2801/3023] staging/lustre/lnet: peer aliveness status and NI status A couple of changes to improve aliveness detection: - When LNet received a message, it can determine peer of this message is alive - When LNet received a message from remote network, it can determine router is alive and NI status on router is UP. Signed-off-by: Liang Zhen Reviewed-on: http://review.whamcloud.com/12453 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5485 Reviewed-by: James Simmons Reviewed-by: Isaac Huang Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/lnet/lib-lnet.h | 10 ++++++++++ drivers/staging/lustre/lnet/lnet/lib-move.c | 13 +++++++++++++ drivers/staging/lustre/lnet/lnet/router.c | 17 ++++++++++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h index 99fb52a98dac50..0038d29a37fe17 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h @@ -636,6 +636,7 @@ lnet_net2rnethash(__u32 net) } extern lnd_t the_lolnd; +extern int avoid_asym_router_failure; int lnet_cpt_of_nid_locked(lnet_nid_t nid); int lnet_cpt_of_nid(lnet_nid_t nid); @@ -851,6 +852,7 @@ int lnet_peer_buffer_credits(lnet_ni_t *ni); int lnet_router_checker_start(void); void lnet_router_checker_stop(void); +void lnet_router_ni_update_locked(lnet_peer_t *gw, __u32 net); void lnet_swap_pinginfo(lnet_ping_info_t *info); int lnet_ping_target_init(void); @@ -870,4 +872,12 @@ void lnet_peer_tables_destroy(void); int lnet_peer_tables_create(void); void lnet_debug_peer(lnet_nid_t nid); +static inline void lnet_peer_set_alive(lnet_peer_t *lp) +{ + lp->lp_last_alive = lp->lp_last_query = get_seconds(); + if (!lp->lp_alive) + lnet_notify_locked(lp, 0, 1, lp->lp_last_alive); +} + + #endif diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index ed6eec9bd2cc8b..0f53c761f1a992 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -1877,6 +1877,19 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, goto drop; } + if (lnet_isrouter(msg->msg_rxpeer)) { + lnet_peer_set_alive(msg->msg_rxpeer); + if (avoid_asym_router_failure && + LNET_NIDNET(src_nid) != LNET_NIDNET(from_nid)) { + /* received a remote message from router, update + * remote NI status on this router. + * NB: multi-hop routed message will be ignored. + */ + lnet_router_ni_update_locked(msg->msg_rxpeer, + LNET_NIDNET(src_nid)); + } + } + lnet_msg_commit(msg, cpt); if (!for_me) { diff --git a/drivers/staging/lustre/lnet/lnet/router.c b/drivers/staging/lustre/lnet/lnet/router.c index 1bbaa5bae5abff..52ec0ab7e3c396 100644 --- a/drivers/staging/lustre/lnet/lnet/router.c +++ b/drivers/staging/lustre/lnet/lnet/router.c @@ -84,7 +84,7 @@ static int check_routers_before_use; module_param(check_routers_before_use, int, 0444); MODULE_PARM_DESC(check_routers_before_use, "Assume routers are down and ping them before use"); -static int avoid_asym_router_failure = 1; +int avoid_asym_router_failure = 1; module_param(avoid_asym_router_failure, int, 0644); MODULE_PARM_DESC(avoid_asym_router_failure, "Avoid asymmetrical router failures (0 to disable)"); @@ -783,6 +783,21 @@ lnet_wait_known_routerstate(void) } } +void +lnet_router_ni_update_locked(lnet_peer_t *gw, __u32 net) +{ + lnet_route_t *rte; + + if ((gw->lp_ping_feats & LNET_PING_FEAT_NI_STATUS) != 0) { + list_for_each_entry(rte, &gw->lp_routes, lr_gwlist) { + if (rte->lr_net == net) { + rte->lr_downis = 0; + break; + } + } + } +} + static void lnet_update_ni_status_locked(void) { From c2fcdf6c427c9c2e305320d6ee82a8ca9f4fa961 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Sun, 1 Feb 2015 21:52:07 -0500 Subject: [PATCH 2802/3023] staging/lustre/llite: to configure max_cached_mb correctly If there exists MGS conf_param to reduce the memory cache max_cached_mb it will fail because dt_exp is not initialized yet. It should just go ahead and configure it because certainly it have enough free LRU slot to deduct ccc_lru_left. Signed-off-by: Jinshan Xiong Reviewed-on: http://review.whamcloud.com/11783 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3676 Reviewed-by: Bobi Jam Reviewed-by: Andreas Dilger Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/lproc_llite.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index e6a909e6faf019..aaa13bd3e8dea8 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -399,9 +399,6 @@ static ssize_t ll_max_cached_mb_seq_write(struct file *file, return -ERANGE; } - if (sbi->ll_dt_exp == NULL) - return -ENODEV; - spin_lock(&sbi->ll_lock); diff = pages_number - cache->ccc_lru_max; spin_unlock(&sbi->ll_lock); @@ -437,6 +434,11 @@ static ssize_t ll_max_cached_mb_seq_write(struct file *file, if (diff <= 0) break; + if (sbi->ll_dt_exp == NULL) { /* being initialized */ + rc = -ENODEV; + break; + } + /* difficult - have to ask OSCs to drop LRU slots. */ tmp = diff << 1; rc = obd_set_info_async(NULL, sbi->ll_dt_exp, From 081fa9dffcde7c9fc4d9fdf18fe277dfa3f675aa Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Sun, 1 Feb 2015 21:52:08 -0500 Subject: [PATCH 2803/3023] staging/lustre/llite: remove llite proc root on init failure In init_lustre_lite() ensure that /proc/fs/lustre/llite is removed in case of failure. Generally rework the cleanup code in this function. Signed-off-by: John L. Hammond Reviewed-on: http://review.whamcloud.com/6420 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3331 Reviewed-by: Bob Glossman Reviewed-by: James Simmons Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/super25.c | 141 +++++++++--------- 1 file changed, 72 insertions(+), 69 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/super25.c b/drivers/staging/lustre/lustre/llite/super25.c index 6aff155651ccdd..7c1e02a031ba17 100644 --- a/drivers/staging/lustre/lustre/llite/super25.c +++ b/drivers/staging/lustre/lustre/llite/super25.c @@ -72,21 +72,6 @@ static void ll_destroy_inode(struct inode *inode) call_rcu(&inode->i_rcu, ll_inode_destroy_callback); } -static int ll_init_inodecache(void) -{ - ll_inode_cachep = kmem_cache_create("lustre_inode_cache", - sizeof(struct ll_inode_info), - 0, SLAB_HWCACHE_ALIGN, NULL); - if (ll_inode_cachep == NULL) - return -ENOMEM; - return 0; -} - -static void ll_destroy_inodecache(void) -{ - kmem_cache_destroy(ll_inode_cachep); -} - /* exported operations */ struct super_operations lustre_super_operations = { .alloc_inode = ll_alloc_inode, @@ -104,9 +89,10 @@ void lustre_register_client_process_config(int (*cpc)(struct lustre_cfg *lcfg)); static int __init init_lustre_lite(void) { - int i, rc, seed[2]; - struct timeval tv; + struct proc_dir_entry *entry; lnet_process_id_t lnet_id; + struct timeval tv; + int i, rc, seed[2]; CLASSERT(sizeof(LUSTRE_VOLATILE_HDR) == LUSTRE_VOLATILE_HDR_LEN + 1); @@ -116,59 +102,52 @@ static int __init init_lustre_lite(void) CDEBUG(D_INFO, "Lustre client module (%p).\n", &lustre_super_operations); - rc = ll_init_inodecache(); - if (rc) - return -ENOMEM; + rc = -ENOMEM; + ll_inode_cachep = kmem_cache_create("lustre_inode_cache", + sizeof(struct ll_inode_info), + 0, SLAB_HWCACHE_ALIGN, NULL); + if (ll_inode_cachep == NULL) + goto out_cache; + ll_file_data_slab = kmem_cache_create("ll_file_data", sizeof(struct ll_file_data), 0, SLAB_HWCACHE_ALIGN, NULL); - if (ll_file_data_slab == NULL) { - ll_destroy_inodecache(); - return -ENOMEM; - } + if (ll_file_data_slab == NULL) + goto out_cache; ll_remote_perm_cachep = kmem_cache_create("ll_remote_perm_cache", sizeof(struct ll_remote_perm), 0, 0, NULL); - if (ll_remote_perm_cachep == NULL) { - kmem_cache_destroy(ll_file_data_slab); - ll_file_data_slab = NULL; - ll_destroy_inodecache(); - return -ENOMEM; - } + if (ll_remote_perm_cachep == NULL) + goto out_cache; ll_rmtperm_hash_cachep = kmem_cache_create("ll_rmtperm_hash_cache", REMOTE_PERM_HASHSIZE * sizeof(struct list_head), 0, 0, NULL); - if (ll_rmtperm_hash_cachep == NULL) { - kmem_cache_destroy(ll_remote_perm_cachep); - ll_remote_perm_cachep = NULL; - kmem_cache_destroy(ll_file_data_slab); - ll_file_data_slab = NULL; - ll_destroy_inodecache(); - return -ENOMEM; + if (ll_rmtperm_hash_cachep == NULL) + goto out_cache; + + entry = lprocfs_register("llite", proc_lustre_root, NULL, NULL); + if (IS_ERR(entry)) { + rc = PTR_ERR(entry); + CERROR("cannot register '/proc/fs/lustre/llite': rc = %d\n", + rc); + goto out_cache; } - proc_lustre_fs_root = proc_lustre_root ? - lprocfs_register("llite", proc_lustre_root, NULL, NULL) : NULL; - - lustre_register_client_fill_super(ll_fill_super); - lustre_register_kill_super_cb(ll_kill_super); - - lustre_register_client_process_config(ll_process_config); + proc_lustre_fs_root = entry; cfs_get_random_bytes(seed, sizeof(seed)); - /* Nodes with small feet have little entropy - * the NID for this node gives the most entropy in the low bits */ - for (i = 0; ; i++) { - if (LNetGetId(i, &lnet_id) == -ENOENT) { + /* Nodes with small feet have little entropy. The NID for this + * node gives the most entropy in the low bits */ + for (i = 0;; i++) { + if (LNetGetId(i, &lnet_id) == -ENOENT) break; - } - if (LNET_NETTYP(LNET_NIDNET(lnet_id.nid)) != LOLND) { + + if (LNET_NETTYP(LNET_NIDNET(lnet_id.nid)) != LOLND) seed[0] ^= LNET_NIDADDR(lnet_id.nid); - } } do_gettimeofday(&tv); @@ -177,20 +156,54 @@ static int __init init_lustre_lite(void) init_timer(&ll_capa_timer); ll_capa_timer.function = ll_capa_timer_callback; rc = ll_capa_thread_start(); - /* - * XXX normal cleanup is needed here. - */ - if (rc == 0) - rc = vvp_global_init(); + if (rc != 0) + goto out_proc; - if (rc == 0) - rc = ll_xattr_init(); + rc = vvp_global_init(); + if (rc != 0) + goto out_capa; + + rc = ll_xattr_init(); + if (rc != 0) + goto out_vvp; + + lustre_register_client_fill_super(ll_fill_super); + lustre_register_kill_super_cb(ll_kill_super); + lustre_register_client_process_config(ll_process_config); + + return 0; + +out_vvp: + vvp_global_fini(); +out_capa: + del_timer(&ll_capa_timer); + ll_capa_thread_stop(); +out_proc: + lprocfs_remove(&proc_lustre_fs_root); +out_cache: + if (ll_inode_cachep != NULL) + kmem_cache_destroy(ll_inode_cachep); + + if (ll_file_data_slab != NULL) + kmem_cache_destroy(ll_file_data_slab); + + if (ll_remote_perm_cachep != NULL) + kmem_cache_destroy(ll_remote_perm_cachep); + + if (ll_rmtperm_hash_cachep != NULL) + kmem_cache_destroy(ll_rmtperm_hash_cachep); return rc; } static void __exit exit_lustre_lite(void) { + lustre_register_client_fill_super(NULL); + lustre_register_kill_super_cb(NULL); + lustre_register_client_process_config(NULL); + + lprocfs_remove(&proc_lustre_fs_root); + ll_xattr_fini(); vvp_global_fini(); del_timer(&ll_capa_timer); @@ -199,22 +212,12 @@ static void __exit exit_lustre_lite(void) "client remaining capa count %d\n", capa_count[CAPA_SITE_CLIENT]); - lustre_register_client_fill_super(NULL); - lustre_register_kill_super_cb(NULL); - - lustre_register_client_process_config(NULL); - - ll_destroy_inodecache(); - + kmem_cache_destroy(ll_inode_cachep); kmem_cache_destroy(ll_rmtperm_hash_cachep); - ll_rmtperm_hash_cachep = NULL; kmem_cache_destroy(ll_remote_perm_cachep); - ll_remote_perm_cachep = NULL; kmem_cache_destroy(ll_file_data_slab); - if (proc_lustre_fs_root && !IS_ERR(proc_lustre_fs_root)) - lprocfs_remove(&proc_lustre_fs_root); } MODULE_AUTHOR("Sun Microsystems, Inc. "); From dbab2d8563d8a988dd4ec740ab9c06a4f86890ea Mon Sep 17 00:00:00 2001 From: Henri Doreau Date: Sun, 1 Feb 2015 21:52:09 -0500 Subject: [PATCH 2804/3023] staging/lustre/obdclass: Proper swabbing of llog_rec_tail. A variable-length structure preceeds llog_rec_tail within an llog block. Thus cr_tail shouldn't be accessed directly as a structure member but its actual location should be computed dynamically. Signed-off-by: Henri Doreau Reviewed-on: http://review.whamcloud.com/11937 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5631 Reviewed-by: jacques-Charles Lafoucriere Reviewed-by: Andreas Dilger Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/llog_swab.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/obdclass/llog_swab.c b/drivers/staging/lustre/lustre/obdclass/llog_swab.c index d3ec90e85eb986..a2d5aa105d6bf2 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_swab.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_swab.c @@ -168,7 +168,8 @@ void lustre_swab_llog_rec(struct llog_rec_hdr *rec) } case CHANGELOG_REC: { - struct llog_changelog_rec *cr = (struct llog_changelog_rec *)rec; + struct llog_changelog_rec *cr = + (struct llog_changelog_rec *)rec; __swab16s(&cr->cr.cr_namelen); __swab16s(&cr->cr.cr_flags); @@ -188,6 +189,8 @@ void lustre_swab_llog_rec(struct llog_rec_hdr *rec) } else { tail = &cr->cr_tail; } + tail = (struct llog_rec_tail *)((char *)tail + + cr->cr.cr_namelen); break; } case CHANGELOG_USER_REC: From 70c86ace9008f83f3b3b0dd995c60942e1057347 Mon Sep 17 00:00:00 2001 From: Liang Zhen Date: Sun, 1 Feb 2015 21:52:10 -0500 Subject: [PATCH 2805/3023] staging/lustre/lnet: portal spreading rotor should be unsigned Portal spreading rotor should be unsigned, otherwise lnet may get negative CPT number and access invalid addresses. Signed-off-by: Liang Zhen Reviewed-on: http://review.whamcloud.com/11936 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5639 Reviewed-by: Amir Shehata Reviewed-by: Isaac Huang Reviewed-by: Doug Oucharek Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/lnet/lib-types.h | 2 +- drivers/staging/lustre/lnet/lnet/lib-ptl.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/lustre/include/linux/lnet/lib-types.h b/drivers/staging/lustre/include/linux/lnet/lib-types.h index ba1876f57d1229..50537668f59db6 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-types.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-types.h @@ -622,7 +622,7 @@ typedef struct lnet_portal { /* Match table for each CPT */ struct lnet_match_table **ptl_mtables; /* spread rotor of incoming "PUT" */ - int ptl_rotor; + unsigned int ptl_rotor; /* # active entries for this portal */ int ptl_mt_nmaps; /* array of active entries' cpu-partition-id */ diff --git a/drivers/staging/lustre/lnet/lnet/lib-ptl.c b/drivers/staging/lustre/lnet/lnet/lib-ptl.c index 19ed696344fefe..3ba0da919b4188 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-ptl.c +++ b/drivers/staging/lustre/lnet/lnet/lib-ptl.c @@ -262,10 +262,10 @@ lnet_mt_of_match(struct lnet_match_info *info, struct lnet_msg *msg) { struct lnet_match_table *mtable; struct lnet_portal *ptl; - int nmaps; - int rotor; - int routed; - int cpt; + unsigned int nmaps; + unsigned int rotor; + unsigned int cpt; + bool routed; /* NB: called w/o lock */ LASSERT(info->mi_portal < the_lnet.ln_nportals); From d27f9b077e113b0fa46e466465233a5e51085228 Mon Sep 17 00:00:00 2001 From: Niu Yawei Date: Sun, 1 Feb 2015 21:52:12 -0500 Subject: [PATCH 2806/3023] staging/lustre/ptlrpc: hold rq_lock when modify rq_flags In after_reply(), take the rq_lock for changing the rq_resend. Signed-off-by: Niu Yawei Reviewed-on: http://review.whamcloud.com/11957 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5633 Reviewed-by: Fan Yong Reviewed-by: Johann Lombardi Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/client.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index 8c1ec830712f0c..4882dd0a448378 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -1247,7 +1247,9 @@ static int after_reply(struct ptlrpc_request *req) time_t now = get_seconds(); DEBUG_REQ(D_RPCTRACE, req, "Resending request on EINPROGRESS"); + spin_lock(&req->rq_lock); req->rq_resend = 1; + spin_unlock(&req->rq_lock); req->rq_nr_resend++; /* allocate new xid to avoid reply reconstruction */ From 4c309612ddb9107c3fdbd5233198d59708114bc4 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Sun, 1 Feb 2015 21:52:13 -0500 Subject: [PATCH 2807/3023] staging/lustre/llite: Solve a race to access lli_has_smd in read case In vvp_io_read_lock(), it used to decide if to add read lock by checking lli_has_smd. Accessing lli_has_smd is racy when an empty file is turned into raid0, therefore, it may result in read requests are issued without corresponding lock. Signed-off-by: Jinshan Xiong Reviewed-on: http://review.whamcloud.com/12139 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5062 Reviewed-by: Bobi Jam Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lclient.h | 1 + .../staging/lustre/lustre/lclient/lcommon_cl.c | 6 ++++++ drivers/staging/lustre/lustre/llite/vvp_io.c | 15 +++++---------- drivers/staging/lustre/lustre/llite/vvp_lock.c | 1 + 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lclient.h b/drivers/staging/lustre/lustre/include/lclient.h index 316500cdff7525..c5c3a8d9eaa402 100644 --- a/drivers/staging/lustre/lustre/include/lclient.h +++ b/drivers/staging/lustre/lustre/include/lclient.h @@ -325,6 +325,7 @@ void ccc_lock_fini(const struct lu_env *env, struct cl_lock_slice *slice); int ccc_lock_enqueue(const struct lu_env *env, const struct cl_lock_slice *slice, struct cl_io *io, __u32 enqflags); +int ccc_lock_use(const struct lu_env *env, const struct cl_lock_slice *slice); int ccc_lock_unuse(const struct lu_env *env, const struct cl_lock_slice *slice); int ccc_lock_wait(const struct lu_env *env, const struct cl_lock_slice *slice); int ccc_lock_fits_into(const struct lu_env *env, diff --git a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c index 24d26ab35346b8..23095bb75226b1 100644 --- a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c @@ -586,6 +586,12 @@ int ccc_lock_enqueue(const struct lu_env *env, return 0; } +int ccc_lock_use(const struct lu_env *env, const struct cl_lock_slice *slice) +{ + CLOBINVRNT(env, slice->cls_obj, ccc_object_invariant(slice->cls_obj)); + return 0; +} + int ccc_lock_unuse(const struct lu_env *env, const struct cl_lock_slice *slice) { CLOBINVRNT(env, slice->cls_obj, ccc_object_invariant(slice->cls_obj)); diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 65d610abe06e53..91bba79678cf7d 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -307,18 +307,13 @@ static int vvp_io_rw_lock(const struct lu_env *env, struct cl_io *io, static int vvp_io_read_lock(const struct lu_env *env, const struct cl_io_slice *ios) { - struct cl_io *io = ios->cis_io; - struct ll_inode_info *lli = ll_i2info(ccc_object_inode(io->ci_obj)); + struct cl_io *io = ios->cis_io; + struct cl_io_rw_common *rd = &io->u.ci_rd.rd; int result; - /* XXX: Layer violation, we shouldn't see lsm at llite level. */ - if (lli->lli_has_smd) /* lsm-less file doesn't need to lock */ - result = vvp_io_rw_lock(env, io, CLM_READ, - io->u.ci_rd.rd.crw_pos, - io->u.ci_rd.rd.crw_pos + - io->u.ci_rd.rd.crw_count - 1); - else - result = 0; + result = vvp_io_rw_lock(env, io, CLM_READ, rd->crw_pos, + rd->crw_pos + rd->crw_count - 1); + return result; } diff --git a/drivers/staging/lustre/lustre/llite/vvp_lock.c b/drivers/staging/lustre/lustre/llite/vvp_lock.c index 372633e164b9b6..f354e82d4ae7cf 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_lock.c +++ b/drivers/staging/lustre/lustre/llite/vvp_lock.c @@ -71,6 +71,7 @@ static const struct cl_lock_operations vvp_lock_ops = { .clo_fini = ccc_lock_fini, .clo_enqueue = ccc_lock_enqueue, .clo_wait = ccc_lock_wait, + .clo_use = ccc_lock_use, .clo_unuse = ccc_lock_unuse, .clo_fits_into = ccc_lock_fits_into, .clo_state = ccc_lock_state, From b7fb222b8acb13672fe37ba1da79f75263781edf Mon Sep 17 00:00:00 2001 From: wang di Date: Sun, 1 Feb 2015 21:52:14 -0500 Subject: [PATCH 2808/3023] staging/lustre/fld: refer to MDT0 for fld lookup in some cases It is possible that when fld client is trying to lookup seq on one of MDT, but the connection between the client and the MDT is not being initialized yet, especially during striped dir creation, because client will only send create req to the master MDT, then master MDT will distribute the operation to all of other MDT, instead of client distributing these requests, which will usually trigger the connection. In this case, we will send the fld request to MDT0, since it has all of location information. Signed-off-by: wang di Reviewed-on: http://review.whamcloud.com/11780 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4855 Reviewed-by: Fan Yong Reviewed-by: Mike Pershin Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/fld/fld_request.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/staging/lustre/lustre/fld/fld_request.c b/drivers/staging/lustre/lustre/fld/fld_request.c index 7801db0e79ce25..b8d17e109a961a 100644 --- a/drivers/staging/lustre/lustre/fld/fld_request.c +++ b/drivers/staging/lustre/lustre/fld/fld_request.c @@ -131,11 +131,20 @@ fld_rrb_scan(struct lu_client_fld *fld, u64 seq) else hash = 0; +again: list_for_each_entry(target, &fld->lcf_targets, ft_chain) { if (target->ft_idx == hash) return target; } + if (hash != 0) { + /* It is possible the remote target(MDT) are not connected to + * with client yet, so we will refer this to MDT0, which should + * be connected during mount */ + hash = 0; + goto again; + } + CERROR("%s: Can't find target by hash %d (seq %#llx). Targets (%d):\n", fld->lcf_name, hash, seq, fld->lcf_count); From 7dd1107ad37a89e849f4fcbdb34fce775ce56db1 Mon Sep 17 00:00:00 2001 From: Frank Zago Date: Sun, 1 Feb 2015 21:52:15 -0500 Subject: [PATCH 2809/3023] staging/lustre/libcfs: protect kkuc_groups from write access Since reg->kr_fp can be changed inside the foreach loop, kkuc_groups must be write protected, and not just read protected. This should fix the following oops, which could happen if two different threads simultaneously execute the function, and EPIPE is returned. PID: 24385 TASK: ffff88012da5f500 CPU: 1 COMMAND: "ldlm_cb00_056" #0 [ffff88012db55810] machine_kexec at ffffffff81038f3b #1 [ffff88012db55870] crash_kexec at ffffffff810c59f2 #2 [ffff88012db55940] oops_end at ffffffff8152b7f0 #3 [ffff88012db55970] no_context at ffffffff8104a00b #4 [ffff88012db559c0] __bad_area_nosemaphore at ffffffff8104a295 #5 [ffff88012db55a10] bad_area_nosemaphore at ffffffff8104a363 #6 [ffff88012db55a20] __do_page_fault at ffffffff8104aabf #7 [ffff88012db55b40] do_page_fault at ffffffff8152d73e #8 [ffff88012db55b70] page_fault at ffffffff8152aaf5 [exception RIP: fput+9] RIP: ffffffff8118a509 RSP: ffff88012db55c20 RFLAGS: 00010246 RAX: 00000000ffffffe0 RBX: ffff8800a8ea4fc0 RCX: 0000000000000000 RDX: ffffffffa03c9eb0 RSI: 0000000000000000 RDI: 0000000000000000 RBP: ffff88012db55c20 R8: 00000000ffffff0a R9: 00000000fffffffc R10: 0000000000000001 R11: 282064656c696166 R12: ffffffffa03c9c60 R13: ffff88005df240f8 R14: 0000000000000000 R15: ffff88013b4ca000 ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 #9 [ffff88012db55c28] libcfs_kkuc_group_put at ffffffffa0388044 [libcfs] [ptlrpc] Signed-off-by: frank zago Reviewed-on: http://review.whamcloud.com/11355 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5458 Reviewed-by: Patrick Farrell Reviewed-by: James Simmons Reviewed-by: Dmitry Eremin Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c index e2aa637abcf94d..d9b7c6b69db412 100644 --- a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c +++ b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c @@ -228,12 +228,12 @@ int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, if (kkuc_groups[group].next == NULL) return 0; - down_read(&kg_sem); + down_write(&kg_sem); list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { if (reg->kr_fp != NULL) rc = cb_func(reg->kr_data, cb_arg); } - up_read(&kg_sem); + up_write(&kg_sem); return rc; } From 437dfb201a55ff73954ae7455ef3d17be4b1c0f6 Mon Sep 17 00:00:00 2001 From: Yang Sheng Date: Sun, 1 Feb 2015 21:52:16 -0500 Subject: [PATCH 2810/3023] staging/lustre/llite: Add exception entry check after radix_tree We need to check for an exception entry after radix_tree lookup. Signed-off-by: Yang Sheng Signed-off-by: Oleg Drokin Reviewed-on: http://review.whamcloud.com/10709 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5162 Reviewed-by: Bob Glossman Reviewed-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index babba60a88bf5e..69a4a63e1d8f8f 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -278,7 +278,7 @@ static struct page *ll_dir_page_locate(struct inode *dir, __u64 *hash, spin_lock_irq(&mapping->tree_lock); found = radix_tree_gang_lookup(&mapping->page_tree, (void **)&page, offset, 1); - if (found > 0) { + if (found > 0 && !radix_tree_exceptional_entry(page)) { struct lu_dirpage *dp; page_cache_get(page); From c67587a74847a27965ca1c6a4362c3b39e9943e1 Mon Sep 17 00:00:00 2001 From: Lai Siyao Date: Sun, 1 Feb 2015 21:52:17 -0500 Subject: [PATCH 2811/3023] staging/lustre/llite: don't add to page cache upon failure Reading directory pages may fail on MDS, in this case client should not cache a non-up-to-date directory page, because it will cause a later read on the same page fail. Signed-off-by: Lai Siyao Signed-off-by: Oleg Drokin Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5461 Reviewed-on: http://review.whamcloud.com/11450 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 69a4a63e1d8f8f..a18201913273d0 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -183,7 +183,10 @@ static int ll_dir_filler(void *_hash, struct page *page0) op_data->op_offset = hash; rc = md_readpage(exp, op_data, page_pool, &request); ll_finish_md_op_data(op_data); - if (rc == 0) { + if (rc < 0) { + /* page0 is special, which was added into page cache early */ + delete_from_page_cache(page0); + } else if (rc == 0) { body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY); /* Checked by mdc_readpage() */ LASSERT(body != NULL); From 431b567856875536c7f574f30cd870d758aa6c2f Mon Sep 17 00:00:00 2001 From: Patrick Farrell Date: Sun, 1 Feb 2015 21:52:18 -0500 Subject: [PATCH 2812/3023] staging/lustre/clio: Do not allow group locks with gid 0 When a group lock with GID=0 is released (put_grouplock is called), an assertion in cl_put_grouplock is hit. We should not allow group lock requests with GID=0, instead we should return -EINVAL. Signed-off-by: Patrick Farrell Reviewed-on: http://review.whamcloud.com/12459 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5817 Reviewed-by: Andreas Dilger Reviewed-by: frank zago Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index ca270f49e6aa3f..7c7ef7ec908e48 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1553,6 +1553,11 @@ ll_get_grouplock(struct inode *inode, struct file *file, unsigned long arg) struct ccc_grouplock grouplock; int rc; + if (arg == 0) { + CWARN("group id for group lock must not be 0\n"); + return -EINVAL; + } + if (ll_file_nolock(file)) return -EOPNOTSUPP; From 3a09f36efd8f0c5c5d968fbbbb0967121076a25b Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 1 Feb 2015 21:52:19 -0500 Subject: [PATCH 2813/3023] staging/lustre/mdc: Initialize req in mdc_enqueue for !it case Commit ab909585b813 ("staging: lustre: Cleanup variable declarations in mdc_enqueue()") broke Lustre flock handling introducing access to uninitialized req variable, leading to bizzare crash in a later call to __req_capsule_offset with invalid pill value. Set req to NULL just for this case as in all other cases req is explicitly initialized with request packing call. Signed-off-by: Oleg Drokin CC: Srikrishan Malik Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/mdc/mdc_locks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index 8c9b4f5494e9e0..d1c224ecd2b78c 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -828,6 +828,7 @@ int mdc_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, einfo->ei_type); policy = (ldlm_policy_data_t *)lmm; res_id.name[3] = LDLM_FLOCK; + req = NULL; } else if (it->it_op & IT_OPEN) { req = mdc_intent_open_pack(exp, it, op_data, lmm, lmmsize, einfo->ei_cbdata); From 11862b36ce380211362a4845e479c8d7d220ce8c Mon Sep 17 00:00:00 2001 From: Max Perepelitsyn Date: Tue, 3 Feb 2015 14:44:28 +0600 Subject: [PATCH 2814/3023] staging: sm7xxfb: make smtc_scr_info static This symbol is never used anywhere else besides sm7xxfb.c Signed-off-by: Max Perepelitsyn Tested-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm7xxfb/sm7xxfb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c index 2ae9fd021a7ce9..72036c281088d2 100644 --- a/drivers/staging/sm7xxfb/sm7xxfb.c +++ b/drivers/staging/sm7xxfb/sm7xxfb.c @@ -111,7 +111,7 @@ static struct vesa_mode vesa_mode_table[] = { {"0x31B", 1280, 1024, 24}, }; -struct screen_info smtc_scr_info; +static struct screen_info smtc_scr_info; /* process command line options, get vga parameter */ static int __init sm7xx_vga_setup(char *options) From ceb2f735e826a410ba507948cf2a2b9d1f565181 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Tue, 3 Feb 2015 08:08:16 -0500 Subject: [PATCH 2815/3023] staging: rtl8723au: multiple condition with no effect - if identical to else A number if/else if/else branches are identical - so the condition has no effect on the effective code and can be significantly simplified - this patch removes the condition and the duplicated code. Signed-off-by: Nicholas Mc Guire Signed-off-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman --- .../rtl8723au/hal/rtl8723a_bt-coexist.c | 60 +++---------------- 1 file changed, 8 insertions(+), 52 deletions(-) diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c b/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c index 412d8cf5a52a59..73cfddd6df9aef 100644 --- a/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c +++ b/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c @@ -7255,63 +7255,19 @@ btdm_2AntTdmaDurationAdjust(struct rtw_adapter *padapter, u8 bScoHid, RTPRINT(FBT, BT_TRACE, ("[BTCoex], first run TdmaDurationAdjust()!!\n")); if (bScoHid) { if (bTxPause) { - if (maxInterval == 1) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (maxInterval == 2) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (maxInterval == 3) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } + btdm_2AntPsTdma(padapter, true, 15); + pBtdm8723->psTdmaDuAdjType = 15; } else { - if (maxInterval == 1) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (maxInterval == 2) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (maxInterval == 3) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } + btdm_2AntPsTdma(padapter, true, 11); + pBtdm8723->psTdmaDuAdjType = 11; } } else { if (bTxPause) { - if (maxInterval == 1) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (maxInterval == 2) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (maxInterval == 3) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } + btdm_2AntPsTdma(padapter, true, 7); + pBtdm8723->psTdmaDuAdjType = 7; } else { - if (maxInterval == 1) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (maxInterval == 2) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (maxInterval == 3) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } + btdm_2AntPsTdma(padapter, true, 3); + pBtdm8723->psTdmaDuAdjType = 3; } } up = 0; From 741218984e472f6a8d4ace8d28eed5b163309443 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Tue, 3 Feb 2015 20:23:33 +0530 Subject: [PATCH 2816/3023] staging: sm7xxfb: fix CamelCase since mixed case names are not encouraged in coding, so those has been changed to their corresponding lowercase version. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm7xxfb/sm7xx.h | 14 +++++++------- drivers/staging/sm7xxfb/sm7xxfb.c | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/staging/sm7xxfb/sm7xx.h b/drivers/staging/sm7xxfb/sm7xx.h index 85998615b80149..fe63cd76f1f2a7 100644 --- a/drivers/staging/sm7xxfb/sm7xx.h +++ b/drivers/staging/sm7xxfb/sm7xx.h @@ -29,14 +29,14 @@ #define dac_reg (0x3c8) #define dac_val (0x3c9) -extern void __iomem *smtc_RegBaseAddress; -#define smtc_mmiowb(dat, reg) writeb(dat, smtc_RegBaseAddress + reg) -#define smtc_mmioww(dat, reg) writew(dat, smtc_RegBaseAddress + reg) -#define smtc_mmiowl(dat, reg) writel(dat, smtc_RegBaseAddress + reg) +extern void __iomem *smtc_regbaseaddress; +#define smtc_mmiowb(dat, reg) writeb(dat, smtc_regbaseaddress + reg) +#define smtc_mmioww(dat, reg) writew(dat, smtc_regbaseaddress + reg) +#define smtc_mmiowl(dat, reg) writel(dat, smtc_regbaseaddress + reg) -#define smtc_mmiorb(reg) readb(smtc_RegBaseAddress + reg) -#define smtc_mmiorw(reg) readw(smtc_RegBaseAddress + reg) -#define smtc_mmiorl(reg) readl(smtc_RegBaseAddress + reg) +#define smtc_mmiorb(reg) readb(smtc_regbaseaddress + reg) +#define smtc_mmiorw(reg) readw(smtc_regbaseaddress + reg) +#define smtc_mmiorl(reg) readl(smtc_regbaseaddress + reg) #define SIZE_SR00_SR04 (0x04 - 0x00 + 1) #define SIZE_SR10_SR24 (0x24 - 0x10 + 1) diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c index 72036c281088d2..f8ecb698be916c 100644 --- a/drivers/staging/sm7xxfb/sm7xxfb.c +++ b/drivers/staging/sm7xxfb/sm7xxfb.c @@ -56,7 +56,7 @@ struct smtcfb_info { u32 colreg[17]; }; -void __iomem *smtc_RegBaseAddress; /* Memory Map IO starting address */ +void __iomem *smtc_regbaseaddress; /* Memory Map IO starting address */ static struct fb_var_screeninfo smtcfb_var = { .xres = 1024, @@ -711,8 +711,8 @@ static void smtc_free_fb_info(struct smtcfb_info *sfb) static void smtc_unmap_mmio(struct smtcfb_info *sfb) { - if (sfb && smtc_RegBaseAddress) - smtc_RegBaseAddress = NULL; + if (sfb && smtc_regbaseaddress) + smtc_regbaseaddress = NULL; } /* @@ -823,7 +823,7 @@ static int smtcfb_pci_probe(struct pci_dev *pdev, #else sfb->lfb = ioremap(mmio_base, 0x00800000); #endif - sfb->mmio = (smtc_RegBaseAddress = + sfb->mmio = (smtc_regbaseaddress = sfb->lfb + 0x00700000); sfb->dp_regs = sfb->lfb + 0x00408000; sfb->vp_regs = sfb->lfb + 0x0040c000; @@ -833,7 +833,7 @@ static int smtcfb_pci_probe(struct pci_dev *pdev, dev_info(&pdev->dev, "sfb->lfb=%p", sfb->lfb); } #endif - if (!smtc_RegBaseAddress) { + if (!smtc_regbaseaddress) { dev_err(&pdev->dev, "%s: unable to map memory mapped IO!", sfb->fb.fix.id); @@ -859,7 +859,7 @@ static int smtcfb_pci_probe(struct pci_dev *pdev, smem_size = SM722_VIDEOMEMORYSIZE; sfb->dp_regs = ioremap(mmio_base, 0x00a00000); sfb->lfb = sfb->dp_regs + 0x00200000; - sfb->mmio = (smtc_RegBaseAddress = + sfb->mmio = (smtc_regbaseaddress = sfb->dp_regs + 0x000c0000); sfb->vp_regs = sfb->dp_regs + 0x800; From c4d507677fe0913cb4f14338b990ae8229d37940 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Tue, 3 Feb 2015 20:23:34 +0530 Subject: [PATCH 2817/3023] staging: sm7xxfb: fix remaining CamelCase since mixed case names are not encouraged in coding, so those has been changed to their corresponding lowercase version. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm7xxfb/sm7xx.h | 30 ++++++++++---------- drivers/staging/sm7xxfb/sm7xxfb.c | 46 +++++++++++++++---------------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/drivers/staging/sm7xxfb/sm7xx.h b/drivers/staging/sm7xxfb/sm7xx.h index fe63cd76f1f2a7..7cc1896938b60b 100644 --- a/drivers/staging/sm7xxfb/sm7xx.h +++ b/drivers/staging/sm7xxfb/sm7xx.h @@ -99,27 +99,27 @@ static inline unsigned int smtc_seqr(int reg) */ struct ModeInit { - int mmSizeX; - int mmSizeY; + int mmsizex; + int mmsizey; int bpp; int hz; - unsigned char Init_MISC; - unsigned char Init_SR00_SR04[SIZE_SR00_SR04]; - unsigned char Init_SR10_SR24[SIZE_SR10_SR24]; - unsigned char Init_SR30_SR75[SIZE_SR30_SR75]; - unsigned char Init_SR80_SR93[SIZE_SR80_SR93]; - unsigned char Init_SRA0_SRAF[SIZE_SRA0_SRAF]; - unsigned char Init_GR00_GR08[SIZE_GR00_GR08]; - unsigned char Init_AR00_AR14[SIZE_AR00_AR14]; - unsigned char Init_CR00_CR18[SIZE_CR00_CR18]; - unsigned char Init_CR30_CR4D[SIZE_CR30_CR4D]; - unsigned char Init_CR90_CRA7[SIZE_CR90_CRA7]; + unsigned char init_misc; + unsigned char init_sr00_sr04[SIZE_SR00_SR04]; + unsigned char init_sr10_sr24[SIZE_SR10_SR24]; + unsigned char init_sr30_sr75[SIZE_SR30_SR75]; + unsigned char init_sr80_sr93[SIZE_SR80_SR93]; + unsigned char init_sra0_sraf[SIZE_SRA0_SRAF]; + unsigned char init_gr00_gr08[SIZE_GR00_GR08]; + unsigned char init_ar00_ar14[SIZE_AR00_AR14]; + unsigned char init_cr00_cr18[SIZE_CR00_CR18]; + unsigned char init_cr30_cr4d[SIZE_CR30_CR4D]; + unsigned char init_cr90_cra7[SIZE_CR90_CRA7]; }; /********************************************************************** SM712 Mode table. **********************************************************************/ -struct ModeInit VGAMode[] = { +struct ModeInit vgamode[] = { { /* mode#0: 640 x 480 16Bpp 60Hz */ 640, 480, 16, 60, @@ -776,4 +776,4 @@ struct ModeInit VGAMode[] = { }, }; -#define numVGAModes ARRAY_SIZE(VGAMode) +#define numvgamodes ARRAY_SIZE(vgamode) diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c index f8ecb698be916c..ebd95365ffae83 100644 --- a/drivers/staging/sm7xxfb/sm7xxfb.c +++ b/drivers/staging/sm7xxfb/sm7xxfb.c @@ -470,38 +470,38 @@ smtcfb_write(struct fb_info *info, const char __user *buf, size_t count, static void sm7xx_set_timing(struct smtcfb_info *sfb) { int i = 0, j = 0; - u32 m_nScreenStride; + u32 m_nscreenstride; dev_dbg(&sfb->pdev->dev, "sfb->width=%d sfb->height=%d sfb->fb.var.bits_per_pixel=%d sfb->hz=%d\n", sfb->width, sfb->height, sfb->fb.var.bits_per_pixel, sfb->hz); - for (j = 0; j < numVGAModes; j++) { - if (VGAMode[j].mmSizeX == sfb->width && - VGAMode[j].mmSizeY == sfb->height && - VGAMode[j].bpp == sfb->fb.var.bits_per_pixel && - VGAMode[j].hz == sfb->hz) { + for (j = 0; j < numvgamodes; j++) { + if (vgamode[j].mmsizex == sfb->width && + vgamode[j].mmsizey == sfb->height && + vgamode[j].bpp == sfb->fb.var.bits_per_pixel && + vgamode[j].hz == sfb->hz) { dev_dbg(&sfb->pdev->dev, - "VGAMode[j].mmSizeX=%d VGAMode[j].mmSizeY=%d VGAMode[j].bpp=%d VGAMode[j].hz=%d\n", - VGAMode[j].mmSizeX, VGAMode[j].mmSizeY, - VGAMode[j].bpp, VGAMode[j].hz); + "vgamode[j].mmsizex=%d vgamode[j].mmSizeY=%d vgamode[j].bpp=%d vgamode[j].hz=%d\n", + vgamode[j].mmsizex, vgamode[j].mmsizey, + vgamode[j].bpp, vgamode[j].hz); - dev_dbg(&sfb->pdev->dev, "VGAMode index=%d\n", j); + dev_dbg(&sfb->pdev->dev, "vgamode index=%d\n", j); smtc_mmiowb(0x0, 0x3c6); smtc_seqw(0, 0x1); - smtc_mmiowb(VGAMode[j].Init_MISC, 0x3c2); + smtc_mmiowb(vgamode[j].init_misc, 0x3c2); /* init SEQ register SR00 - SR04 */ for (i = 0; i < SIZE_SR00_SR04; i++) - smtc_seqw(i, VGAMode[j].Init_SR00_SR04[i]); + smtc_seqw(i, vgamode[j].init_sr00_sr04[i]); /* init SEQ register SR10 - SR24 */ for (i = 0; i < SIZE_SR10_SR24; i++) smtc_seqw(i + 0x10, - VGAMode[j].Init_SR10_SR24[i]); + vgamode[j].init_sr10_sr24[i]); /* init SEQ register SR30 - SR75 */ for (i = 0; i < SIZE_SR30_SR75; i++) @@ -509,39 +509,39 @@ static void sm7xx_set_timing(struct smtcfb_info *sfb) (i + 0x30) != 0x6a && (i + 0x30) != 0x6b) smtc_seqw(i + 0x30, - VGAMode[j].Init_SR30_SR75[i]); + vgamode[j].init_sr30_sr75[i]); /* init SEQ register SR80 - SR93 */ for (i = 0; i < SIZE_SR80_SR93; i++) smtc_seqw(i + 0x80, - VGAMode[j].Init_SR80_SR93[i]); + vgamode[j].init_sr80_sr93[i]); /* init SEQ register SRA0 - SRAF */ for (i = 0; i < SIZE_SRA0_SRAF; i++) smtc_seqw(i + 0xa0, - VGAMode[j].Init_SRA0_SRAF[i]); + vgamode[j].init_sra0_sraf[i]); /* init Graphic register GR00 - GR08 */ for (i = 0; i < SIZE_GR00_GR08; i++) - smtc_grphw(i, VGAMode[j].Init_GR00_GR08[i]); + smtc_grphw(i, vgamode[j].init_gr00_gr08[i]); /* init Attribute register AR00 - AR14 */ for (i = 0; i < SIZE_AR00_AR14; i++) - smtc_attrw(i, VGAMode[j].Init_AR00_AR14[i]); + smtc_attrw(i, vgamode[j].init_ar00_ar14[i]); /* init CRTC register CR00 - CR18 */ for (i = 0; i < SIZE_CR00_CR18; i++) - smtc_crtcw(i, VGAMode[j].Init_CR00_CR18[i]); + smtc_crtcw(i, vgamode[j].init_cr00_cr18[i]); /* init CRTC register CR30 - CR4D */ for (i = 0; i < SIZE_CR30_CR4D; i++) smtc_crtcw(i + 0x30, - VGAMode[j].Init_CR30_CR4D[i]); + vgamode[j].init_cr30_cr4d[i]); /* init CRTC register CR90 - CRA7 */ for (i = 0; i < SIZE_CR90_CRA7; i++) smtc_crtcw(i + 0x90, - VGAMode[j].Init_CR90_CRA7[i]); + vgamode[j].init_cr90_cra7[i]); } } smtc_mmiowb(0x67, 0x3c2); @@ -551,7 +551,7 @@ static void sm7xx_set_timing(struct smtcfb_info *sfb) writel(0x0, sfb->vp_regs + 0x40); /* set data width */ - m_nScreenStride = + m_nscreenstride = (sfb->width * sfb->fb.var.bits_per_pixel) / 64; switch (sfb->fb.var.bits_per_pixel) { case 8: @@ -567,7 +567,7 @@ static void sm7xx_set_timing(struct smtcfb_info *sfb) writel(0x00030000, sfb->vp_regs + 0x0); break; } - writel((u32) (((m_nScreenStride + 2) << 16) | m_nScreenStride), + writel((u32) (((m_nscreenstride + 2) << 16) | m_nscreenstride), sfb->vp_regs + 0x10); } From 9b1af46b3ae1880f7ab7b1f1598b4daf2ddec8e4 Mon Sep 17 00:00:00 2001 From: Bilel DRIRA Date: Tue, 3 Feb 2015 21:26:27 +0100 Subject: [PATCH 2818/3023] staging: ft1000: fix braces warning This patch fix checkpatch.pl WARNING: WARNING: braces {} are not necessary for single statement blocks Signed-off-by: Bilel DRIRA Signed-off-by: Greg Kroah-Hartman --- .../staging/ft1000/ft1000-pcmcia/ft1000_hw.c | 73 ++++++++----------- 1 file changed, 29 insertions(+), 44 deletions(-) diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c index 5e0cdcf26180b9..017c3b92f51bff 100644 --- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c @@ -204,11 +204,11 @@ static inline void ft1000_write_dpram_mag_16(struct net_device *dev, /* Provide mutual exclusive access while reading ASIC registers. */ spin_lock_irqsave(&info->dpram_lock, flags); ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset); - if (Index) { + if (Index) ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAL, value); - } else { + else ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAH, value); - } + spin_unlock_irqrestore(&info->dpram_lock, flags); } @@ -440,9 +440,8 @@ static int ft1000_reset_card(struct net_device *dev) tempword = ft1000_read_dpram_mag_16(dev, FT1000_MAG_DPRAM_FEFE, FT1000_MAG_DPRAM_FEFE_INDX); - if (tempword == 0xfefe) { + if (tempword == 0xfefe) break; - } mdelay(20); } @@ -621,9 +620,9 @@ static void ft1000_hbchk(u_long data) tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); /* Let's check doorbell again if fail */ - if (tempword & FT1000_DB_HB) { + if (tempword & FT1000_DB_HB) tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); - } + if (tempword & FT1000_DB_HB) { pr_info("heartbeat doorbell not clear by firmware\n"); if (info->AsicID == ELECTRABUZZ_ID) { @@ -766,9 +765,8 @@ static void ft1000_send_cmd(struct net_device *dev, u16 *ptempbuffer, int size, size += sizeof(struct pseudo_hdr); /* check for odd byte and increment to 16-bit word align value */ - if ((size & 0x0001)) { + if ((size & 0x0001)) size++; - } pr_debug("total length = %d\n", size); pr_debug("length = %d\n", ntohs(*ptempbuffer)); /* @@ -911,9 +909,8 @@ static bool ft1000_receive_cmd(struct net_device *dev, u16 *pbuffer, * Calculate pseudo header checksum */ tempword = *ppseudohdr++; - for (i = 1; i < 7; i++) { + for (i = 1; i < 7; i++) tempword ^= *ppseudohdr++; - } if ((tempword != *ppseudohdr)) { pr_debug("Pseudo header checksum mismatch\n"); /* Drop this message */ @@ -977,9 +974,8 @@ static void ft1000_proc_drvmsg(struct net_device *dev) while (tempword & FT1000_DB_DPRAM_TX) { mdelay(5); i++; - if (i == 10) { + if (i == 10) break; - } } ptr = list_entry(info->prov_list.next, @@ -1099,9 +1095,8 @@ static void ft1000_proc_drvmsg(struct net_device *dev) mdelay(10); tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); - if (tempword & FT1000_DB_DPRAM_TX) { + if (tempword & FT1000_DB_DPRAM_TX) mdelay(10); - } } if ((tempword & FT1000_DB_DPRAM_TX) == 0) { @@ -1128,9 +1123,9 @@ static void ft1000_proc_drvmsg(struct net_device *dev) ppseudo_hdr->portsrc = 0; /* Calculate new checksum */ ppseudo_hdr->checksum = *pmsg++; - for (i = 1; i < 7; i++) { + for (i = 1; i < 7; i++) ppseudo_hdr->checksum ^= *pmsg++; - } + info->DSPInfoBlk[8] = 0x7200; info->DSPInfoBlk[9] = htons(info->DSPInfoBlklen); @@ -1150,9 +1145,8 @@ static void ft1000_proc_drvmsg(struct net_device *dev) mdelay(10); tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); - if (tempword & FT1000_DB_DPRAM_TX) { + if (tempword & FT1000_DB_DPRAM_TX) mdelay(10); - } } if ((tempword & FT1000_DB_DPRAM_TX) == 0) { @@ -1178,9 +1172,9 @@ static void ft1000_proc_drvmsg(struct net_device *dev) ppseudo_hdr->portsrc = 0; /* Calculate new checksum */ ppseudo_hdr->checksum = *pmsg++; - for (i = 1; i < 7; i++) { + for (i = 1; i < 7; i++) ppseudo_hdr->checksum ^= *pmsg++; - } + pmsg = (u16 *)&tempbuffer[16]; *pmsg++ = htons(RSP_DRV_ERR_RPT_MSG); *pmsg++ = htons(0x000e); @@ -1502,9 +1496,8 @@ static void ft1000_flush_fifo(struct net_device *dev, u16 DrvErrNum) tempword = inw(dev->base_addr + FT1000_REG_MAG_DFSR); pr_debug("FT1000_REG_MAG_DFSR = 0x%x\n", tempword); } - if (DrvErrNum) { + if (DrvErrNum) pcmcia->PktIntfErr++; - } } } @@ -1561,9 +1554,9 @@ static int ft1000_copy_up_pkt(struct net_device *dev) if (skb == NULL) { pr_debug("No Network buffers available\n"); /* Read High word to complete 32 bit access */ - if (info->AsicID == MAGNEMITE_ID) { + if (info->AsicID == MAGNEMITE_ID) tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH); - } + ft1000_flush_fifo(dev, 0); info->stats.rx_errors++; return FAILURE; @@ -1667,9 +1660,8 @@ static int ft1000_copy_up_pkt(struct net_device *dev) } pr_debug("Data passed to Protocol layer:\n"); - for (i = 0; i < len + 12; i++) { + for (i = 0; i < len + 12; i++) pr_debug("Protocol Data: 0x%x\n", *ptemp++); - } skb->dev = dev; skb->protocol = eth_type_trans(skb, dev); @@ -1723,21 +1715,16 @@ static int ft1000_copy_down_pkt(struct net_device *dev, u16 *packet, u16 len) /* Check if there is room on the FIFO */ if (len > ft1000_read_fifo_len(dev)) { udelay(10); - if (len > ft1000_read_fifo_len(dev)) { + if (len > ft1000_read_fifo_len(dev)) udelay(20); - } - if (len > ft1000_read_fifo_len(dev)) { + if (len > ft1000_read_fifo_len(dev)) udelay(20); - } - if (len > ft1000_read_fifo_len(dev)) { + if (len > ft1000_read_fifo_len(dev)) udelay(20); - } - if (len > ft1000_read_fifo_len(dev)) { + if (len > ft1000_read_fifo_len(dev)) udelay(20); - } - if (len > ft1000_read_fifo_len(dev)) { + if (len > ft1000_read_fifo_len(dev)) udelay(20); - } if (len > ft1000_read_fifo_len(dev)) { pr_debug("Transmit FIFO is full - pkt drop\n"); info->stats.tx_errors++; @@ -1745,11 +1732,11 @@ static int ft1000_copy_down_pkt(struct net_device *dev, u16 *packet, u16 len) } } /* Create pseudo header and send pseudo/ip to hardware */ - if (info->AsicID == ELECTRABUZZ_ID) { + if (info->AsicID == ELECTRABUZZ_ID) pseudo.blk.length = len; - } else { + else pseudo.blk.length = ntohs(len); - } + pseudo.blk.source = DSPID; /* Need to swap to get in correct order */ pseudo.blk.destination = HOSTID; pseudo.blk.portdest = NETWORKID; /* Need to swap to get in correct order */ @@ -1762,9 +1749,8 @@ static int ft1000_copy_down_pkt(struct net_device *dev, u16 *packet, u16 len) pseudo.blk.qos_class = 0; /* Calculate pseudo header checksum */ pseudo.blk.checksum = pseudo.buff[0]; - for (i = 1; i < 7; i++) { + for (i = 1; i < 7; i++) pseudo.blk.checksum ^= pseudo.buff[i]; - } /* Production Mode */ if (info->AsicID == ELECTRABUZZ_ID) { @@ -1829,9 +1815,8 @@ static int ft1000_copy_down_pkt(struct net_device *dev, u16 *packet, u16 len) plong = (u32 *)packet; /* Write PPP type + IP Packet into Downlink FIFO */ - for (i = 0; i < (len >> 2); i++) { + for (i = 0; i < (len >> 2); i++) outl(*plong++, dev->base_addr + FT1000_REG_MAG_UFDR); - } /* Check for odd alignment */ if (len & 0x0003) { From 3d272700d73c6503138759c1de6021ee4466e4d8 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Wed, 4 Feb 2015 05:28:54 -0500 Subject: [PATCH 2819/3023] staging: rtl8188eu: odm: condition with no effect The if and the else branch code are identical - so the condition has no effect on the effective code - this patch removes the condition and the duplicated code. Signed-off-by: Nicholas Mc Guire Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/odm.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/staging/rtl8188eu/hal/odm.c b/drivers/staging/rtl8188eu/hal/odm.c index 9873998011d290..878c460f846cf7 100644 --- a/drivers/staging/rtl8188eu/hal/odm.c +++ b/drivers/staging/rtl8188eu/hal/odm.c @@ -534,13 +534,8 @@ void odm_DIGInit(struct odm_dm_struct *pDM_Odm) pDM_DigTable->RssiHighThresh = DM_DIG_THRESH_HIGH; pDM_DigTable->FALowThresh = DM_false_ALARM_THRESH_LOW; pDM_DigTable->FAHighThresh = DM_false_ALARM_THRESH_HIGH; - if (pDM_Odm->BoardType == ODM_BOARD_HIGHPWR) { - pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC; - pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC; - } else { - pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC; - pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC; - } + pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC; + pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC; pDM_DigTable->BackoffVal = DM_DIG_BACKOFF_DEFAULT; pDM_DigTable->BackoffVal_range_max = DM_DIG_BACKOFF_MAX; pDM_DigTable->BackoffVal_range_min = DM_DIG_BACKOFF_MIN; From e914024d46e3de3c5c3ce9c5b77b564ad6a264c0 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Wed, 4 Feb 2015 05:28:55 -0500 Subject: [PATCH 2820/3023] staging: rtl8188eu: odm: conditional setting with no effect The if and the else branch code are identical - so the condition has no effect on the effective code - this patch removes the condition and the duplicated code. Due to this being a fall-through-if here - the first if condition has no effect either - so it also can be removed. struct mlme_priv is thus also no longer needed here. Signed-off-by: Nicholas Mc Guire Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/odm.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/staging/rtl8188eu/hal/odm.c b/drivers/staging/rtl8188eu/hal/odm.c index 878c460f846cf7..06477e8346535c 100644 --- a/drivers/staging/rtl8188eu/hal/odm.c +++ b/drivers/staging/rtl8188eu/hal/odm.c @@ -1133,16 +1133,9 @@ static void FindMinimumRSSI(struct adapter *pAdapter) { struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter); struct dm_priv *pdmpriv = &pHalData->dmpriv; - struct mlme_priv *pmlmepriv = &pAdapter->mlmepriv; - - /* 1 1.Determine the minimum RSSI */ - if ((check_fwstate(pmlmepriv, _FW_LINKED) == false) && - (pdmpriv->EntryMinUndecoratedSmoothedPWDB == 0)) - pdmpriv->MinUndecoratedPWDBForDM = 0; - if (check_fwstate(pmlmepriv, _FW_LINKED) == true) /* Default port */ - pdmpriv->MinUndecoratedPWDBForDM = pdmpriv->EntryMinUndecoratedSmoothedPWDB; - else /* associated entry pwdb */ - pdmpriv->MinUndecoratedPWDBForDM = pdmpriv->EntryMinUndecoratedSmoothedPWDB; + + /* 1 1.Unconditionally set RSSI */ + pdmpriv->MinUndecoratedPWDBForDM = pdmpriv->EntryMinUndecoratedSmoothedPWDB; } void odm_RSSIMonitorCheckCE(struct odm_dm_struct *pDM_Odm) From e971e8de383f91c418c924afd349766f33b20501 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Wed, 4 Feb 2015 06:04:38 -0500 Subject: [PATCH 2821/3023] staging: rtl8188eu: core: switch with redundant cases A few redundant switch cases as well as a redundant if/else within one of the cases was consolidated to a single call. The cases are intentionally retained for documentation purposes. case WIFI_REASSOCREQ,WIFI_PROBEREQ,WIFI_BEACON,WIFI_ACTION all have the same effect - notably the also for WIFI_PROBEREQ where the if/else is executing the same function. These redundant cases could all be dropped and consolidated into the default but probably it is better for documentation/readability to leave them in the switch/case explicitly. Signed-off-by: Nicholas Mc Guire Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 28918201fcd778..cd12dd70dd8804 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -484,17 +484,8 @@ void mgt_dispatcher(struct adapter *padapter, struct recv_frame *precv_frame) /* fall through */ case WIFI_ASSOCREQ: case WIFI_REASSOCREQ: - _mgt_dispatcher(padapter, ptable, precv_frame); - break; case WIFI_PROBEREQ: - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - _mgt_dispatcher(padapter, ptable, precv_frame); - else - _mgt_dispatcher(padapter, ptable, precv_frame); - break; case WIFI_BEACON: - _mgt_dispatcher(padapter, ptable, precv_frame); - break; case WIFI_ACTION: _mgt_dispatcher(padapter, ptable, precv_frame); break; From 6acbd7523d93946844b79c3fe684491b0b06de6e Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Wed, 4 Feb 2015 19:44:34 +0100 Subject: [PATCH 2822/3023] staging: lustre: make obd_updatemax_lock static obd_updatemax_lock is only used in class_obd.c Signed-off-by: Fabian Frederick Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/class_obd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index 89a3fb2e56b25e..29456e1ad2250d 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -61,7 +61,7 @@ __u64 obd_alloc; EXPORT_SYMBOL(obd_alloc); __u64 obd_pages; EXPORT_SYMBOL(obd_pages); -DEFINE_SPINLOCK(obd_updatemax_lock); +static DEFINE_SPINLOCK(obd_updatemax_lock); /* The following are visible and mutable through /proc/sys/lustre/. */ unsigned int obd_alloc_fail_rate = 0; From 21fa7be013a66a5521bd2f7c83c9e357cafb091f Mon Sep 17 00:00:00 2001 From: Michael Hornung Date: Wed, 4 Feb 2015 19:54:49 +0100 Subject: [PATCH 2823/3023] staging: rtl8712: Do coding style cleanup * Fix checkpatch.pl warnings "Fix missing space after return type warning". Signed-off-by: Michael Hornung Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/drv_types.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8712/drv_types.h b/drivers/staging/rtl8712/drv_types.h index 3d0a98b6d8e580..e62543d22b8617 100644 --- a/drivers/staging/rtl8712/drv_types.h +++ b/drivers/staging/rtl8712/drv_types.h @@ -129,8 +129,8 @@ struct dvobj_priv { struct _adapter *padapter; u32 nr_endpoint; u8 ishighspeed; - uint(*inirp_init)(struct _adapter *adapter); - uint(*inirp_deinit)(struct _adapter *adapter); + uint (*inirp_init)(struct _adapter *adapter); + uint (*inirp_deinit)(struct _adapter *adapter); struct usb_device *pusbdev; }; @@ -166,7 +166,7 @@ struct _adapter { pid_t evtThread; struct task_struct *xmitThread; pid_t recvThread; - uint(*dvobj_init)(struct _adapter *adapter); + uint (*dvobj_init)(struct _adapter *adapter); void (*dvobj_deinit)(struct _adapter *adapter); struct net_device *pnetdev; int bup; From 533e80b1ea709577ec5cf73b8b566569bc711259 Mon Sep 17 00:00:00 2001 From: Chen Weixiang Date: Thu, 5 Feb 2015 21:24:41 +0800 Subject: [PATCH 2824/3023] staging: lustre: lustre: libcfs: define symbols as static This patch fixes the following warning using sparse - warning: symbol 'libcfs_debug_mb' was not declared. Should it be static? - warning: symbol 'portal_enter_debugger' was not declared. Should it be static? Signed-off-by: Chen Weixiang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/libcfs/debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/libcfs/debug.c b/drivers/staging/lustre/lustre/libcfs/debug.c index 717008867f6b2c..76c62e87a415af 100644 --- a/drivers/staging/lustre/lustre/libcfs/debug.c +++ b/drivers/staging/lustre/lustre/libcfs/debug.c @@ -57,7 +57,7 @@ module_param(libcfs_debug, int, 0644); MODULE_PARM_DESC(libcfs_debug, "Lustre kernel debug mask"); EXPORT_SYMBOL(libcfs_debug); -unsigned int libcfs_debug_mb = 0; +static unsigned int libcfs_debug_mb; module_param(libcfs_debug_mb, uint, 0644); MODULE_PARM_DESC(libcfs_debug_mb, "Total debug buffer size."); EXPORT_SYMBOL(libcfs_debug_mb); @@ -93,7 +93,7 @@ EXPORT_SYMBOL(libcfs_debug_binary); unsigned int libcfs_stack = 3 * THREAD_SIZE / 4; EXPORT_SYMBOL(libcfs_stack); -unsigned int portal_enter_debugger; +static unsigned int portal_enter_debugger; EXPORT_SYMBOL(portal_enter_debugger); unsigned int libcfs_catastrophe; From 692132b5b1c5ce97076915d4aed0c61513e18b03 Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Mon, 2 Feb 2015 23:19:20 +0100 Subject: [PATCH 2825/3023] serial: driver for ETRAX FS UART This is the last missing piece to get a kernel booting to a prompt in qemu-cris. Signed-off-by: Niklas Cassel Acked-by: Jesper Nilsson Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 10 + drivers/tty/serial/Makefile | 1 + drivers/tty/serial/etraxfs-uart.c | 996 ++++++++++++++++++++++++++++++ include/uapi/linux/serial_core.h | 3 + 4 files changed, 1010 insertions(+) create mode 100644 drivers/tty/serial/etraxfs-uart.c diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index ddcc0a4c659cb6..5d916c7a216b86 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1085,6 +1085,16 @@ config SERIAL_VT8500_CONSOLE depends on SERIAL_VT8500=y select SERIAL_CORE_CONSOLE +config SERIAL_ETRAXFS + bool "ETRAX FS serial port support" + depends on ETRAX_ARCH_V32 && OF + select SERIAL_CORE + +config SERIAL_ETRAXFS_CONSOLE + bool "ETRAX FS serial console support" + depends on SERIAL_ETRAXFS + select SERIAL_CORE_CONSOLE + config SERIAL_NETX tristate "NetX serial port support" depends on ARCH_NETX diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index 431879003ccda5..599be4b05a2688 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_SERIAL_MPSC) += mpsc.o obj-$(CONFIG_SERIAL_MESON) += meson_uart.o obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o +obj-$(CONFIG_SERIAL_ETRAXFS) += etraxfs-uart.o obj-$(CONFIG_SERIAL_SCCNXP) += sccnxp.o obj-$(CONFIG_SERIAL_SC16IS7XX) += sc16is7xx.o obj-$(CONFIG_SERIAL_JSM) += jsm/ diff --git a/drivers/tty/serial/etraxfs-uart.c b/drivers/tty/serial/etraxfs-uart.c new file mode 100644 index 00000000000000..a57301a6fe4270 --- /dev/null +++ b/drivers/tty/serial/etraxfs-uart.c @@ -0,0 +1,996 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "etraxfs-uart" +#define UART_NR CONFIG_ETRAX_SERIAL_PORTS + +#define MODIFY_REG(instance, reg, var) \ + do { \ + if (REG_RD_INT(ser, instance, reg) != \ + REG_TYPE_CONV(int, reg_ser_##reg, var)) \ + REG_WR(ser, instance, reg, var); \ + } while (0) + +struct uart_cris_port { + struct uart_port port; + + int initialized; + int irq; + + void __iomem *regi_ser; + + struct gpio_desc *dtr_pin; + struct gpio_desc *dsr_pin; + struct gpio_desc *ri_pin; + struct gpio_desc *cd_pin; + + int write_ongoing; +}; + +static struct uart_driver etraxfs_uart_driver; +static struct uart_port *console_port; +static int console_baud = 115200; +static struct uart_cris_port *etraxfs_uart_ports[UART_NR]; + +static void cris_serial_port_init(struct uart_port *port, int line); +static void etraxfs_uart_stop_rx(struct uart_port *port); +static inline void etraxfs_uart_start_tx_bottom(struct uart_port *port); + +#ifdef CONFIG_SERIAL_ETRAXFS_CONSOLE +static void +cris_console_write(struct console *co, const char *s, unsigned int count) +{ + struct uart_cris_port *up; + int i; + reg_ser_r_stat_din stat; + reg_ser_rw_tr_dma_en tr_dma_en, old; + + up = etraxfs_uart_ports[co->index]; + + if (!up) + return; + + /* Switch to manual mode. */ + tr_dma_en = old = REG_RD(ser, up->regi_ser, rw_tr_dma_en); + if (tr_dma_en.en == regk_ser_yes) { + tr_dma_en.en = regk_ser_no; + REG_WR(ser, up->regi_ser, rw_tr_dma_en, tr_dma_en); + } + + /* Send data. */ + for (i = 0; i < count; i++) { + /* LF -> CRLF */ + if (s[i] == '\n') { + do { + stat = REG_RD(ser, up->regi_ser, r_stat_din); + } while (!stat.tr_rdy); + REG_WR_INT(ser, up->regi_ser, rw_dout, '\r'); + } + /* Wait until transmitter is ready and send. */ + do { + stat = REG_RD(ser, up->regi_ser, r_stat_din); + } while (!stat.tr_rdy); + REG_WR_INT(ser, up->regi_ser, rw_dout, s[i]); + } + + /* Restore mode. */ + if (tr_dma_en.en != old.en) + REG_WR(ser, up->regi_ser, rw_tr_dma_en, old); +} + +static int __init +cris_console_setup(struct console *co, char *options) +{ + struct uart_port *port; + int baud = 115200; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + + if (co->index < 0 || co->index >= UART_NR) + co->index = 0; + port = &etraxfs_uart_ports[co->index]->port; + console_port = port; + + co->flags |= CON_CONSDEV; + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + console_baud = baud; + cris_serial_port_init(port, co->index); + uart_set_options(port, co, baud, parity, bits, flow); + + return 0; +} + +static struct tty_driver *cris_console_device(struct console *co, int *index) +{ + struct uart_driver *p = co->data; + *index = co->index; + return p->tty_driver; +} + +static struct console cris_console = { + .name = "ttyS", + .write = cris_console_write, + .device = cris_console_device, + .setup = cris_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, + .data = &etraxfs_uart_driver, +}; +#endif /* CONFIG_SERIAL_ETRAXFS_CONSOLE */ + +static struct uart_driver etraxfs_uart_driver = { + .owner = THIS_MODULE, + .driver_name = "serial", + .dev_name = "ttyS", + .major = TTY_MAJOR, + .minor = 64, + .nr = UART_NR, +#ifdef CONFIG_SERIAL_ETRAXFS_CONSOLE + .cons = &cris_console, +#endif /* CONFIG_SERIAL_ETRAXFS_CONSOLE */ +}; + +static inline int crisv32_serial_get_rts(struct uart_cris_port *up) +{ + void __iomem *regi_ser = up->regi_ser; + /* + * Return what the user has controlled rts to or + * what the pin is? (if auto_rts is used it differs during tx) + */ + reg_ser_r_stat_din rstat = REG_RD(ser, regi_ser, r_stat_din); + + return !(rstat.rts_n == regk_ser_active); +} + +/* + * A set = 0 means 3.3V on the pin, bitvalue: 0=active, 1=inactive + * 0=0V , 1=3.3V + */ +static inline void crisv32_serial_set_rts(struct uart_cris_port *up, + int set, int force) +{ + void __iomem *regi_ser = up->regi_ser; + + unsigned long flags; + reg_ser_rw_rec_ctrl rec_ctrl; + + local_irq_save(flags); + rec_ctrl = REG_RD(ser, regi_ser, rw_rec_ctrl); + + if (set) + rec_ctrl.rts_n = regk_ser_active; + else + rec_ctrl.rts_n = regk_ser_inactive; + REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl); + local_irq_restore(flags); +} + +static inline int crisv32_serial_get_cts(struct uart_cris_port *up) +{ + void __iomem *regi_ser = up->regi_ser; + reg_ser_r_stat_din rstat = REG_RD(ser, regi_ser, r_stat_din); + + return (rstat.cts_n == regk_ser_active); +} + +/* + * Send a single character for XON/XOFF purposes. We do it in this separate + * function instead of the alternative support port.x_char, in the ...start_tx + * function, so we don't mix up this case with possibly enabling transmission + * of queued-up data (in case that's disabled after *receiving* an XOFF or + * negative CTS). This function is used for both DMA and non-DMA case; see HW + * docs specifically blessing sending characters manually when DMA for + * transmission is enabled and running. We may be asked to transmit despite + * the transmitter being disabled by a ..._stop_tx call so we need to enable + * it temporarily but restore the state afterwards. + */ +static void etraxfs_uart_send_xchar(struct uart_port *port, char ch) +{ + struct uart_cris_port *up = (struct uart_cris_port *)port; + reg_ser_rw_dout dout = { .data = ch }; + reg_ser_rw_ack_intr ack_intr = { .tr_rdy = regk_ser_yes }; + reg_ser_r_stat_din rstat; + reg_ser_rw_tr_ctrl prev_tr_ctrl, tr_ctrl; + void __iomem *regi_ser = up->regi_ser; + unsigned long flags; + + /* + * Wait for tr_rdy in case a character is already being output. Make + * sure we have integrity between the register reads and the writes + * below, but don't busy-wait with interrupts off and the port lock + * taken. + */ + spin_lock_irqsave(&port->lock, flags); + do { + spin_unlock_irqrestore(&port->lock, flags); + spin_lock_irqsave(&port->lock, flags); + prev_tr_ctrl = tr_ctrl = REG_RD(ser, regi_ser, rw_tr_ctrl); + rstat = REG_RD(ser, regi_ser, r_stat_din); + } while (!rstat.tr_rdy); + + /* + * Ack an interrupt if one was just issued for the previous character + * that was output. This is required for non-DMA as the interrupt is + * used as the only indicator that the transmitter is ready and it + * isn't while this x_char is being transmitted. + */ + REG_WR(ser, regi_ser, rw_ack_intr, ack_intr); + + /* Enable the transmitter in case it was disabled. */ + tr_ctrl.stop = 0; + REG_WR(ser, regi_ser, rw_tr_ctrl, tr_ctrl); + + /* + * Finally, send the blessed character; nothing should stop it now, + * except for an xoff-detected state, which we'll handle below. + */ + REG_WR(ser, regi_ser, rw_dout, dout); + up->port.icount.tx++; + + /* There might be an xoff state to clear. */ + rstat = REG_RD(ser, up->regi_ser, r_stat_din); + + /* + * Clear any xoff state that *may* have been there to + * inhibit transmission of the character. + */ + if (rstat.xoff_detect) { + reg_ser_rw_xoff_clr xoff_clr = { .clr = 1 }; + reg_ser_rw_tr_dma_en tr_dma_en; + + REG_WR(ser, regi_ser, rw_xoff_clr, xoff_clr); + tr_dma_en = REG_RD(ser, regi_ser, rw_tr_dma_en); + + /* + * If we had an xoff state but cleared it, instead sneak in a + * disabled state for the transmitter, after the character we + * sent. Thus we keep the port disabled, just as if the xoff + * state was still in effect (or actually, as if stop_tx had + * been called, as we stop DMA too). + */ + prev_tr_ctrl.stop = 1; + + tr_dma_en.en = 0; + REG_WR(ser, regi_ser, rw_tr_dma_en, tr_dma_en); + } + + /* Restore "previous" enabled/disabled state of the transmitter. */ + REG_WR(ser, regi_ser, rw_tr_ctrl, prev_tr_ctrl); + + spin_unlock_irqrestore(&port->lock, flags); +} + +/* + * Do not spin_lock_irqsave or disable interrupts by other means here; it's + * already done by the caller. + */ +static void etraxfs_uart_start_tx(struct uart_port *port) +{ + struct uart_cris_port *up = (struct uart_cris_port *)port; + + /* we have already done below if a write is ongoing */ + if (up->write_ongoing) + return; + + /* Signal that write is ongoing */ + up->write_ongoing = 1; + + etraxfs_uart_start_tx_bottom(port); +} + +static inline void etraxfs_uart_start_tx_bottom(struct uart_port *port) +{ + struct uart_cris_port *up = (struct uart_cris_port *)port; + void __iomem *regi_ser = up->regi_ser; + reg_ser_rw_tr_ctrl tr_ctrl; + reg_ser_rw_intr_mask intr_mask; + + tr_ctrl = REG_RD(ser, regi_ser, rw_tr_ctrl); + tr_ctrl.stop = regk_ser_no; + REG_WR(ser, regi_ser, rw_tr_ctrl, tr_ctrl); + intr_mask = REG_RD(ser, regi_ser, rw_intr_mask); + intr_mask.tr_rdy = regk_ser_yes; + REG_WR(ser, regi_ser, rw_intr_mask, intr_mask); +} + +/* + * This function handles both the DMA and non-DMA case by ordering the + * transmitter to stop of after the current character. We don't need to wait + * for any such character to be completely transmitted; we do that where it + * matters, like in etraxfs_uart_set_termios. Don't busy-wait here; see + * Documentation/serial/driver: this function is called within + * spin_lock_irq{,save} and thus separate ones would be disastrous (when SMP). + * There's no documented need to set the txd pin to any particular value; + * break setting is controlled solely by etraxfs_uart_break_ctl. + */ +static void etraxfs_uart_stop_tx(struct uart_port *port) +{ + struct uart_cris_port *up = (struct uart_cris_port *)port; + void __iomem *regi_ser = up->regi_ser; + reg_ser_rw_tr_ctrl tr_ctrl; + reg_ser_rw_intr_mask intr_mask; + reg_ser_rw_tr_dma_en tr_dma_en = {0}; + reg_ser_rw_xoff_clr xoff_clr = {0}; + + /* + * For the non-DMA case, we'd get a tr_rdy interrupt that we're not + * interested in as we're not transmitting any characters. For the + * DMA case, that interrupt is already turned off, but no reason to + * waste code on conditionals here. + */ + intr_mask = REG_RD(ser, regi_ser, rw_intr_mask); + intr_mask.tr_rdy = regk_ser_no; + REG_WR(ser, regi_ser, rw_intr_mask, intr_mask); + + tr_ctrl = REG_RD(ser, regi_ser, rw_tr_ctrl); + tr_ctrl.stop = 1; + REG_WR(ser, regi_ser, rw_tr_ctrl, tr_ctrl); + + /* + * Always clear possible hardware xoff-detected state here, no need to + * unnecessary consider mctrl settings and when they change. We clear + * it here rather than in start_tx: both functions are called as the + * effect of XOFF processing, but start_tx is also called when upper + * levels tell the driver that there are more characters to send, so + * avoid adding code there. + */ + xoff_clr.clr = 1; + REG_WR(ser, regi_ser, rw_xoff_clr, xoff_clr); + + /* + * Disable transmitter DMA, so that if we're in XON/XOFF, we can send + * those single characters without also giving go-ahead for queued up + * DMA data. + */ + tr_dma_en.en = 0; + REG_WR(ser, regi_ser, rw_tr_dma_en, tr_dma_en); + + /* + * Make sure that write_ongoing is reset when stopping tx. + */ + up->write_ongoing = 0; +} + +static void etraxfs_uart_stop_rx(struct uart_port *port) +{ + struct uart_cris_port *up = (struct uart_cris_port *)port; + void __iomem *regi_ser = up->regi_ser; + reg_ser_rw_rec_ctrl rec_ctrl = REG_RD(ser, regi_ser, rw_rec_ctrl); + + rec_ctrl.en = regk_ser_no; + REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl); +} + +static void etraxfs_uart_enable_ms(struct uart_port *port) +{ +} + +static void check_modem_status(struct uart_cris_port *up) +{ +} + +static unsigned int etraxfs_uart_tx_empty(struct uart_port *port) +{ + struct uart_cris_port *up = (struct uart_cris_port *)port; + unsigned long flags; + unsigned int ret; + reg_ser_r_stat_din rstat = {0}; + + spin_lock_irqsave(&up->port.lock, flags); + + rstat = REG_RD(ser, up->regi_ser, r_stat_din); + ret = rstat.tr_empty ? TIOCSER_TEMT : 0; + + spin_unlock_irqrestore(&up->port.lock, flags); + return ret; +} +static unsigned int etraxfs_uart_get_mctrl(struct uart_port *port) +{ + struct uart_cris_port *up = (struct uart_cris_port *)port; + unsigned int ret; + + ret = 0; + if (crisv32_serial_get_rts(up)) + ret |= TIOCM_RTS; + /* DTR is active low */ + if (up->dtr_pin && !gpiod_get_raw_value(up->dtr_pin)) + ret |= TIOCM_DTR; + /* CD is active low */ + if (up->cd_pin && !gpiod_get_raw_value(up->cd_pin)) + ret |= TIOCM_CD; + /* RI is active low */ + if (up->ri_pin && !gpiod_get_raw_value(up->ri_pin)) + ret |= TIOCM_RI; + /* DSR is active low */ + if (up->dsr_pin && !gpiod_get_raw_value(up->dsr_pin)) + ret |= TIOCM_DSR; + if (crisv32_serial_get_cts(up)) + ret |= TIOCM_CTS; + return ret; +} + +static void etraxfs_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + struct uart_cris_port *up = (struct uart_cris_port *)port; + + crisv32_serial_set_rts(up, mctrl & TIOCM_RTS ? 1 : 0, 0); + /* DTR is active low */ + if (up->dtr_pin) + gpiod_set_raw_value(up->dtr_pin, mctrl & TIOCM_DTR ? 0 : 1); + /* RI is active low */ + if (up->ri_pin) + gpiod_set_raw_value(up->ri_pin, mctrl & TIOCM_RNG ? 0 : 1); + /* CD is active low */ + if (up->cd_pin) + gpiod_set_raw_value(up->cd_pin, mctrl & TIOCM_CD ? 0 : 1); +} + +static void etraxfs_uart_break_ctl(struct uart_port *port, int break_state) +{ + struct uart_cris_port *up = (struct uart_cris_port *)port; + unsigned long flags; + reg_ser_rw_tr_ctrl tr_ctrl; + reg_ser_rw_tr_dma_en tr_dma_en; + reg_ser_rw_intr_mask intr_mask; + + spin_lock_irqsave(&up->port.lock, flags); + tr_ctrl = REG_RD(ser, up->regi_ser, rw_tr_ctrl); + tr_dma_en = REG_RD(ser, up->regi_ser, rw_tr_dma_en); + intr_mask = REG_RD(ser, up->regi_ser, rw_intr_mask); + + if (break_state != 0) { /* Send break */ + /* + * We need to disable DMA (if used) or tr_rdy interrupts if no + * DMA. No need to make this conditional on use of DMA; + * disabling will be a no-op for the other mode. + */ + intr_mask.tr_rdy = regk_ser_no; + tr_dma_en.en = 0; + + /* + * Stop transmission and set the txd pin to 0 after the + * current character. The txd setting will take effect after + * any current transmission has completed. + */ + tr_ctrl.stop = 1; + tr_ctrl.txd = 0; + } else { + /* Re-enable the serial interrupt. */ + intr_mask.tr_rdy = regk_ser_yes; + + tr_ctrl.stop = 0; + tr_ctrl.txd = 1; + } + REG_WR(ser, up->regi_ser, rw_tr_ctrl, tr_ctrl); + REG_WR(ser, up->regi_ser, rw_tr_dma_en, tr_dma_en); + REG_WR(ser, up->regi_ser, rw_intr_mask, intr_mask); + + spin_unlock_irqrestore(&up->port.lock, flags); +} + +static void +transmit_chars_no_dma(struct uart_cris_port *up) +{ + int max_count; + struct circ_buf *xmit = &up->port.state->xmit; + + void __iomem *regi_ser = up->regi_ser; + reg_ser_r_stat_din rstat; + reg_ser_rw_ack_intr ack_intr = { .tr_rdy = regk_ser_yes }; + + if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { + /* No more to send, so disable the interrupt. */ + reg_ser_rw_intr_mask intr_mask; + + intr_mask = REG_RD(ser, regi_ser, rw_intr_mask); + intr_mask.tr_rdy = 0; + intr_mask.tr_empty = 0; + REG_WR(ser, regi_ser, rw_intr_mask, intr_mask); + up->write_ongoing = 0; + return; + } + + /* If the serport is fast, we send up to max_count bytes before + exiting the loop. */ + max_count = 64; + do { + reg_ser_rw_dout dout = { .data = xmit->buf[xmit->tail] }; + + REG_WR(ser, regi_ser, rw_dout, dout); + REG_WR(ser, regi_ser, rw_ack_intr, ack_intr); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1); + up->port.icount.tx++; + if (xmit->head == xmit->tail) + break; + rstat = REG_RD(ser, regi_ser, r_stat_din); + } while ((--max_count > 0) && rstat.tr_rdy); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(&up->port); +} + +static void receive_chars_no_dma(struct uart_cris_port *up) +{ + reg_ser_rs_stat_din stat_din; + reg_ser_r_stat_din rstat; + struct tty_port *port; + struct uart_icount *icount; + int max_count = 16; + char flag; + reg_ser_rw_ack_intr ack_intr = { 0 }; + + rstat = REG_RD(ser, up->regi_ser, r_stat_din); + icount = &up->port.icount; + port = &up->port.state->port; + + do { + stat_din = REG_RD(ser, up->regi_ser, rs_stat_din); + + flag = TTY_NORMAL; + ack_intr.dav = 1; + REG_WR(ser, up->regi_ser, rw_ack_intr, ack_intr); + icount->rx++; + + if (stat_din.framing_err | stat_din.par_err | stat_din.orun) { + if (stat_din.data == 0x00 && + stat_din.framing_err) { + /* Most likely a break. */ + flag = TTY_BREAK; + icount->brk++; + } else if (stat_din.par_err) { + flag = TTY_PARITY; + icount->parity++; + } else if (stat_din.orun) { + flag = TTY_OVERRUN; + icount->overrun++; + } else if (stat_din.framing_err) { + flag = TTY_FRAME; + icount->frame++; + } + } + + /* + * If this becomes important, we probably *could* handle this + * gracefully by keeping track of the unhandled character. + */ + if (!tty_insert_flip_char(port, stat_din.data, flag)) + panic("%s: No tty buffer space", __func__); + rstat = REG_RD(ser, up->regi_ser, r_stat_din); + } while (rstat.dav && (max_count-- > 0)); + spin_unlock(&up->port.lock); + tty_flip_buffer_push(port); + spin_lock(&up->port.lock); +} + +static irqreturn_t +ser_interrupt(int irq, void *dev_id) +{ + struct uart_cris_port *up = (struct uart_cris_port *)dev_id; + void __iomem *regi_ser; + int handled = 0; + + spin_lock(&up->port.lock); + + regi_ser = up->regi_ser; + + if (regi_ser) { + reg_ser_r_masked_intr masked_intr; + + masked_intr = REG_RD(ser, regi_ser, r_masked_intr); + /* + * Check what interrupts are active before taking + * actions. If DMA is used the interrupt shouldn't + * be enabled. + */ + if (masked_intr.dav) { + receive_chars_no_dma(up); + handled = 1; + } + check_modem_status(up); + + if (masked_intr.tr_rdy) { + transmit_chars_no_dma(up); + handled = 1; + } + } + spin_unlock(&up->port.lock); + return IRQ_RETVAL(handled); +} + +#ifdef CONFIG_CONSOLE_POLL +static int etraxfs_uart_get_poll_char(struct uart_port *port) +{ + reg_ser_rs_stat_din stat; + reg_ser_rw_ack_intr ack_intr = { 0 }; + struct uart_cris_port *up = (struct uart_cris_port *)port; + + do { + stat = REG_RD(ser, up->regi_ser, rs_stat_din); + } while (!stat.dav); + + /* Ack the data_avail interrupt. */ + ack_intr.dav = 1; + REG_WR(ser, up->regi_ser, rw_ack_intr, ack_intr); + + return stat.data; +} + +static void etraxfs_uart_put_poll_char(struct uart_port *port, + unsigned char c) +{ + reg_ser_r_stat_din stat; + struct uart_cris_port *up = (struct uart_cris_port *)port; + + do { + stat = REG_RD(ser, up->regi_ser, r_stat_din); + } while (!stat.tr_rdy); + REG_WR_INT(ser, up->regi_ser, rw_dout, c); +} +#endif /* CONFIG_CONSOLE_POLL */ + +static int etraxfs_uart_startup(struct uart_port *port) +{ + struct uart_cris_port *up = (struct uart_cris_port *)port; + unsigned long flags; + reg_ser_rw_intr_mask ser_intr_mask = {0}; + + ser_intr_mask.dav = regk_ser_yes; + + if (request_irq(etraxfs_uart_ports[port->line]->irq, ser_interrupt, + 0, DRV_NAME, etraxfs_uart_ports[port->line])) + panic("irq ser%d", port->line); + + spin_lock_irqsave(&up->port.lock, flags); + + REG_WR(ser, up->regi_ser, rw_intr_mask, ser_intr_mask); + + etraxfs_uart_set_mctrl(&up->port, up->port.mctrl); + + spin_unlock_irqrestore(&up->port.lock, flags); + + return 0; +} + +static void etraxfs_uart_shutdown(struct uart_port *port) +{ + struct uart_cris_port *up = (struct uart_cris_port *)port; + unsigned long flags; + + spin_lock_irqsave(&up->port.lock, flags); + + etraxfs_uart_stop_tx(port); + etraxfs_uart_stop_rx(port); + + free_irq(etraxfs_uart_ports[port->line]->irq, + etraxfs_uart_ports[port->line]); + + etraxfs_uart_set_mctrl(&up->port, up->port.mctrl); + + spin_unlock_irqrestore(&up->port.lock, flags); + +} + +static void +etraxfs_uart_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) +{ + struct uart_cris_port *up = (struct uart_cris_port *)port; + unsigned long flags; + reg_ser_rw_xoff xoff; + reg_ser_rw_xoff_clr xoff_clr = {0}; + reg_ser_rw_tr_ctrl tx_ctrl = {0}; + reg_ser_rw_tr_dma_en tx_dma_en = {0}; + reg_ser_rw_rec_ctrl rx_ctrl = {0}; + reg_ser_rw_tr_baud_div tx_baud_div = {0}; + reg_ser_rw_rec_baud_div rx_baud_div = {0}; + int baud; + + if (old && + termios->c_cflag == old->c_cflag && + termios->c_iflag == old->c_iflag) + return; + + /* Tx: 8 bit, no/even parity, 1 stop bit, no cts. */ + tx_ctrl.base_freq = regk_ser_f29_493; + tx_ctrl.en = 0; + tx_ctrl.stop = 0; + tx_ctrl.auto_rts = regk_ser_no; + tx_ctrl.txd = 1; + tx_ctrl.auto_cts = 0; + /* Rx: 8 bit, no/even parity. */ + rx_ctrl.dma_err = regk_ser_stop; + rx_ctrl.sampling = regk_ser_majority; + rx_ctrl.timeout = 1; + + rx_ctrl.rts_n = regk_ser_inactive; + + /* Common for tx and rx: 8N1. */ + tx_ctrl.data_bits = regk_ser_bits8; + rx_ctrl.data_bits = regk_ser_bits8; + tx_ctrl.par = regk_ser_even; + rx_ctrl.par = regk_ser_even; + tx_ctrl.par_en = regk_ser_no; + rx_ctrl.par_en = regk_ser_no; + + tx_ctrl.stop_bits = regk_ser_bits1; + + /* + * Change baud-rate and write it to the hardware. + * + * baud_clock = base_freq / (divisor*8) + * divisor = base_freq / (baud_clock * 8) + * base_freq is either: + * off, ext, 29.493MHz, 32.000 MHz, 32.768 MHz or 100 MHz + * 20.493MHz is used for standard baudrates + */ + + /* + * For the console port we keep the original baudrate here. Not very + * beautiful. + */ + if ((port != console_port) || old) + baud = uart_get_baud_rate(port, termios, old, 0, + port->uartclk / 8); + else + baud = console_baud; + + tx_baud_div.div = 29493000 / (8 * baud); + /* Rx uses same as tx. */ + rx_baud_div.div = tx_baud_div.div; + rx_ctrl.base_freq = tx_ctrl.base_freq; + + if ((termios->c_cflag & CSIZE) == CS7) { + /* Set 7 bit mode. */ + tx_ctrl.data_bits = regk_ser_bits7; + rx_ctrl.data_bits = regk_ser_bits7; + } + + if (termios->c_cflag & CSTOPB) { + /* Set 2 stop bit mode. */ + tx_ctrl.stop_bits = regk_ser_bits2; + } + + if (termios->c_cflag & PARENB) { + /* Enable parity. */ + tx_ctrl.par_en = regk_ser_yes; + rx_ctrl.par_en = regk_ser_yes; + } + + if (termios->c_cflag & CMSPAR) { + if (termios->c_cflag & PARODD) { + /* Set mark parity if PARODD and CMSPAR. */ + tx_ctrl.par = regk_ser_mark; + rx_ctrl.par = regk_ser_mark; + } else { + tx_ctrl.par = regk_ser_space; + rx_ctrl.par = regk_ser_space; + } + } else { + if (termios->c_cflag & PARODD) { + /* Set odd parity. */ + tx_ctrl.par = regk_ser_odd; + rx_ctrl.par = regk_ser_odd; + } + } + + if (termios->c_cflag & CRTSCTS) { + /* Enable automatic CTS handling. */ + tx_ctrl.auto_cts = regk_ser_yes; + } + + /* Make sure the tx and rx are enabled. */ + tx_ctrl.en = regk_ser_yes; + rx_ctrl.en = regk_ser_yes; + + spin_lock_irqsave(&port->lock, flags); + + tx_dma_en.en = 0; + REG_WR(ser, up->regi_ser, rw_tr_dma_en, tx_dma_en); + + /* Actually write the control regs (if modified) to the hardware. */ + uart_update_timeout(port, termios->c_cflag, port->uartclk/8); + MODIFY_REG(up->regi_ser, rw_rec_baud_div, rx_baud_div); + MODIFY_REG(up->regi_ser, rw_rec_ctrl, rx_ctrl); + + MODIFY_REG(up->regi_ser, rw_tr_baud_div, tx_baud_div); + MODIFY_REG(up->regi_ser, rw_tr_ctrl, tx_ctrl); + + tx_dma_en.en = 0; + REG_WR(ser, up->regi_ser, rw_tr_dma_en, tx_dma_en); + + xoff = REG_RD(ser, up->regi_ser, rw_xoff); + + if (up->port.state && up->port.state->port.tty && + (up->port.state->port.tty->termios.c_iflag & IXON)) { + xoff.chr = STOP_CHAR(up->port.state->port.tty); + xoff.automatic = regk_ser_yes; + } else + xoff.automatic = regk_ser_no; + + MODIFY_REG(up->regi_ser, rw_xoff, xoff); + + /* + * Make sure we don't start in an automatically shut-off state due to + * a previous early exit. + */ + xoff_clr.clr = 1; + REG_WR(ser, up->regi_ser, rw_xoff_clr, xoff_clr); + + etraxfs_uart_set_mctrl(&up->port, up->port.mctrl); + spin_unlock_irqrestore(&up->port.lock, flags); +} + +static const char * +etraxfs_uart_type(struct uart_port *port) +{ + return "CRISv32"; +} + +static void etraxfs_uart_release_port(struct uart_port *port) +{ +} + +static int etraxfs_uart_request_port(struct uart_port *port) +{ + return 0; +} + +static void etraxfs_uart_config_port(struct uart_port *port, int flags) +{ + struct uart_cris_port *up = (struct uart_cris_port *)port; + + up->port.type = PORT_CRIS; +} + +static const struct uart_ops etraxfs_uart_pops = { + .tx_empty = etraxfs_uart_tx_empty, + .set_mctrl = etraxfs_uart_set_mctrl, + .get_mctrl = etraxfs_uart_get_mctrl, + .stop_tx = etraxfs_uart_stop_tx, + .start_tx = etraxfs_uart_start_tx, + .send_xchar = etraxfs_uart_send_xchar, + .stop_rx = etraxfs_uart_stop_rx, + .enable_ms = etraxfs_uart_enable_ms, + .break_ctl = etraxfs_uart_break_ctl, + .startup = etraxfs_uart_startup, + .shutdown = etraxfs_uart_shutdown, + .set_termios = etraxfs_uart_set_termios, + .type = etraxfs_uart_type, + .release_port = etraxfs_uart_release_port, + .request_port = etraxfs_uart_request_port, + .config_port = etraxfs_uart_config_port, +#ifdef CONFIG_CONSOLE_POLL + .poll_get_char = etraxfs_uart_get_poll_char, + .poll_put_char = etraxfs_uart_put_poll_char, +#endif +}; + +static void cris_serial_port_init(struct uart_port *port, int line) +{ + struct uart_cris_port *up = (struct uart_cris_port *)port; + + if (up->initialized) + return; + up->initialized = 1; + port->line = line; + spin_lock_init(&port->lock); + port->ops = &etraxfs_uart_pops; + port->irq = up->irq; + port->iobase = (unsigned long) up->regi_ser; + port->uartclk = 29493000; + + /* + * We can't fit any more than 255 here (unsigned char), though + * actually UART_XMIT_SIZE characters could be pending output. + * At time of this writing, the definition of "fifosize" is here the + * amount of characters that can be pending output after a start_tx call + * until tx_empty returns 1: see serial_core.c:uart_wait_until_sent. + * This matters for timeout calculations unfortunately, but keeping + * larger amounts at the DMA wouldn't win much so let's just play nice. + */ + port->fifosize = 255; + port->flags = UPF_BOOT_AUTOCONF; +} + +static int etraxfs_uart_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct uart_cris_port *up; + int dev_id; + + if (!np) + return -ENODEV; + + dev_id = of_alias_get_id(np, "serial"); + if (dev_id < 0) + dev_id = 0; + + if (dev_id >= UART_NR) + return -EINVAL; + + if (etraxfs_uart_ports[dev_id]) + return -EBUSY; + + up = devm_kzalloc(&pdev->dev, sizeof(struct uart_cris_port), + GFP_KERNEL); + if (!up) + return -ENOMEM; + + up->irq = irq_of_parse_and_map(np, 0); + up->regi_ser = of_iomap(np, 0); + up->dtr_pin = devm_gpiod_get_optional(&pdev->dev, "dtr"); + up->dsr_pin = devm_gpiod_get_optional(&pdev->dev, "dsr"); + up->ri_pin = devm_gpiod_get_optional(&pdev->dev, "ri"); + up->cd_pin = devm_gpiod_get_optional(&pdev->dev, "cd"); + up->port.dev = &pdev->dev; + cris_serial_port_init(&up->port, dev_id); + + etraxfs_uart_ports[dev_id] = up; + platform_set_drvdata(pdev, &up->port); + uart_add_one_port(&etraxfs_uart_driver, &up->port); + + return 0; +} + +static int etraxfs_uart_remove(struct platform_device *pdev) +{ + struct uart_port *port; + + port = platform_get_drvdata(pdev); + uart_remove_one_port(&etraxfs_uart_driver, port); + etraxfs_uart_ports[pdev->id] = NULL; + + return 0; +} + +static const struct of_device_id etraxfs_uart_dt_ids[] = { + { .compatible = "axis,etraxfs-uart" }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, etraxfs_uart_dt_ids); + +static struct platform_driver etraxfs_uart_platform_driver = { + .driver = { + .name = DRV_NAME, + .of_match_table = of_match_ptr(etraxfs_uart_dt_ids), + }, + .probe = etraxfs_uart_probe, + .remove = etraxfs_uart_remove, +}; + +static int __init etraxfs_uart_init(void) +{ + int ret; + + ret = uart_register_driver(&etraxfs_uart_driver); + if (ret) + return ret; + + ret = platform_driver_register(&etraxfs_uart_platform_driver); + if (ret) + uart_unregister_driver(&etraxfs_uart_driver); + + return ret; +} + +static void __exit etraxfs_uart_exit(void) +{ + platform_driver_unregister(&etraxfs_uart_platform_driver); + uart_unregister_driver(&etraxfs_uart_driver); +} + +module_init(etraxfs_uart_init); +module_exit(etraxfs_uart_exit); diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h index 55da91e763bb73..b2122813f18a2a 100644 --- a/include/uapi/linux/serial_core.h +++ b/include/uapi/linux/serial_core.h @@ -255,4 +255,7 @@ /* SPRD SERIAL */ #define PORT_SPRD 111 +/* Cris v10 / v32 SoC */ +#define PORT_CRIS 112 + #endif /* _UAPILINUX_SERIAL_CORE_H */ From c09babfab7ae8c7d79a5dce9d866fbb28b82dde4 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Mon, 2 Feb 2015 15:47:07 -0500 Subject: [PATCH 2826/3023] serial: 8250: Fix UART_BUG_TXEN workaround UARTs which do not trigger THRE interrupt if the fifo is already empty when the interrupt is enabled need tx primed manually. These UARTs are identified by the UART_BUG_TXEN flag to enable the required workaround. However, the current workaround is broken; if the fifo is already empty but the shifter is still transmitting, then serial8250_tx_chars() will not be called but no further THRE interrupt will occur, and tx will stall. The appropriate check is for fifo empty (THRE), not transmitter empty (TEMT). Signed-off-by: Dick Hollenbeck [pjh: rewrote commit log] Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 46ae9fda68b631..e3b9570a1eff8a 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -1388,7 +1388,7 @@ static void serial8250_start_tx(struct uart_port *port) unsigned char lsr; lsr = serial_in(up, UART_LSR); up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; - if (lsr & UART_LSR_TEMT) + if (lsr & UART_LSR_THRE) serial8250_tx_chars(up); } } From 8e2207cdd087ebb031e9118d1fd0902c6533a5e5 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Thu, 15 Jan 2015 17:56:18 +0100 Subject: [PATCH 2827/3023] KVM: s390: floating irqs: fix user triggerable endless loop If a vm with no VCPUs is created, the injection of a floating irq leads to an endless loop in the kernel. Let's skip the search for a destination VCPU for a floating irq if no VCPUs were created. Reviewed-by: Dominik Dingel Reviewed-by: Cornelia Huck Signed-off-by: David Hildenbrand Cc: stable@vger.kernel.org # v3.15+ Signed-off-by: Christian Borntraeger --- arch/s390/kvm/interrupt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index c34e1d904ff696..073b5f387d1dd3 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c @@ -1244,6 +1244,8 @@ static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti) list_add_tail(&inti->list, &iter->list); } atomic_set(&fi->active, 1); + if (atomic_read(&kvm->online_vcpus) == 0) + goto unlock_fi; sigcpu = find_first_bit(fi->idle_mask, KVM_MAX_VCPUS); if (sigcpu == KVM_MAX_VCPUS) { do { From c23f397cc4e440742b2b27690694c9346f638800 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Thu, 29 Jan 2015 14:09:54 +0100 Subject: [PATCH 2828/3023] KVM: s390: reenable LPP facility commit 7be81a46695d ("KVM: s390/facilities: allow TOD-CLOCK steering facility bit") accidentially disabled the "load program parameter" facility bit during rebase for upstream submission (my fault). Re-add that bit. As this is only for a performance measurement helper instruction (used by KVM itself) cc stable is not necessary see http://www-01.ibm.com/support/docview.wss?uid=isg26fcd1cc32246f4c8852574ce0044734a (SA23-2260 The Load-Program-Parameter and CPU-Measurement Facilities) for details about LPP and its usecase. Signed-off-by: Christian Borntraeger Reviewed-by: David Hildenbrand Acked-by: Cornelia Huck Fixes: 7be81a46695d ("KVM: s390/facilities: allow TOD-CLOCK steering") --- arch/s390/kvm/kvm-s390.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 1dbab2340a6623..3acf08ba88e4ff 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -2074,7 +2074,7 @@ static int __init kvm_s390_init(void) return -ENOMEM; } memcpy(vfacilities, S390_lowcore.stfle_fac_list, 16); - vfacilities[0] &= 0xff82fffbf47c2000UL; + vfacilities[0] &= 0xff82fffbf4fc2000UL; vfacilities[1] &= 0x005c000000000000UL; return 0; } From f3d0bd6c7f07d2be4b429230386d49f1b1b14f1c Mon Sep 17 00:00:00 2001 From: Ekaterina Tumanova Date: Mon, 20 Oct 2014 15:24:31 +0200 Subject: [PATCH 2829/3023] s390/kernel: Update /proc/sysinfo file with Extended Name and UUID A new architecture extends STSI 3.2.2 with UUID and long names. KVM will provide the first implementation. This patch adds the additional data fields (Extended Name and UUID) from the 4KB block returned by the STSI 3.2.2 command and reflect this information in the /proc/sysinfo file accordingly. Signed-off-by: Ekaterina Tumanova Reviewed-by: David Hildenbrand Reviewed-by: Cornelia Huck Acked-by: Heiko Carstens Signed-off-by: Christian Borntraeger --- arch/s390/include/asm/sysinfo.h | 10 +++++++--- arch/s390/kernel/sysinfo.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/arch/s390/include/asm/sysinfo.h b/arch/s390/include/asm/sysinfo.h index f92428e459f8b8..9f8f2b5c8d6ce1 100644 --- a/arch/s390/include/asm/sysinfo.h +++ b/arch/s390/include/asm/sysinfo.h @@ -15,6 +15,7 @@ #define __ASM_S390_SYSINFO_H #include +#include struct sysinfo_1_1_1 { unsigned char p:1; @@ -112,10 +113,13 @@ struct sysinfo_3_2_2 { char name[8]; unsigned int caf; char cpi[16]; - char reserved_1[24]; - + char reserved_1[3]; + char ext_name_encoding; + unsigned int reserved_2; + uuid_be uuid; } vm[8]; - char reserved_544[3552]; + char reserved_3[1504]; + char ext_names[8][256]; }; extern int topology_max_mnest; diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c index 811f542b8ed4ad..cebab77c138c41 100644 --- a/arch/s390/kernel/sysinfo.c +++ b/arch/s390/kernel/sysinfo.c @@ -196,6 +196,33 @@ static void stsi_2_2_2(struct seq_file *m, struct sysinfo_2_2_2 *info) seq_printf(m, "LPAR CPUs Shared: %d\n", info->cpus_shared); } +static void print_ext_name(struct seq_file *m, int lvl, + struct sysinfo_3_2_2 *info) +{ + if (info->vm[lvl].ext_name_encoding == 0) + return; + if (info->ext_names[lvl][0] == 0) + return; + switch (info->vm[lvl].ext_name_encoding) { + case 1: /* EBCDIC */ + EBCASC(info->ext_names[lvl], sizeof(info->ext_names[lvl])); + break; + case 2: /* UTF-8 */ + break; + default: + return; + } + seq_printf(m, "VM%02d Extended Name: %-.256s\n", lvl, + info->ext_names[lvl]); +} + +static void print_uuid(struct seq_file *m, int i, struct sysinfo_3_2_2 *info) +{ + if (!memcmp(&info->vm[i].uuid, &NULL_UUID_BE, sizeof(uuid_be))) + return; + seq_printf(m, "VM%02d UUID: %pUb\n", i, &info->vm[i].uuid); +} + static void stsi_3_2_2(struct seq_file *m, struct sysinfo_3_2_2 *info) { int i; @@ -213,6 +240,8 @@ static void stsi_3_2_2(struct seq_file *m, struct sysinfo_3_2_2 *info) seq_printf(m, "VM%02d CPUs Configured: %d\n", i, info->vm[i].cpus_configured); seq_printf(m, "VM%02d CPUs Standby: %d\n", i, info->vm[i].cpus_standby); seq_printf(m, "VM%02d CPUs Reserved: %d\n", i, info->vm[i].cpus_reserved); + print_ext_name(m, i, info); + print_uuid(m, i, info); } } From 45c9b47c5883d02abab6c7c7788e3d97a2f158e1 Mon Sep 17 00:00:00 2001 From: Tony Krowiak Date: Tue, 13 Jan 2015 11:33:26 -0500 Subject: [PATCH 2830/3023] KVM: s390/CPACF: Choose crypto control block format We need to specify a different format for the crypto control block depending on whether the APXA facility is installed or not. Let's test for it by executing the PQAP(QCI) function and use either a format-1 or a format-2 crypto control block accordingly. This is a host only change for z13 and does not affect the guest view. Signed-off-by: Tony Krowiak Signed-off-by: Christian Borntraeger --- arch/s390/include/asm/kvm_host.h | 2 ++ arch/s390/kvm/kvm-s390.c | 49 ++++++++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index f79058e3fd98f1..77ae01444e982f 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h @@ -163,6 +163,7 @@ struct kvm_s390_sie_block { __u64 tecmc; /* 0x00e8 */ __u8 reservedf0[12]; /* 0x00f0 */ #define CRYCB_FORMAT1 0x00000001 +#define CRYCB_FORMAT2 0x00000003 __u32 crycbd; /* 0x00fc */ __u64 gcr[16]; /* 0x0100 */ __u64 gbea; /* 0x0180 */ @@ -516,6 +517,7 @@ struct kvm_s390_crypto_cb { __u8 reserved00[72]; /* 0x0000 */ __u8 dea_wrapping_key_mask[24]; /* 0x0048 */ __u8 aes_wrapping_key_mask[32]; /* 0x0060 */ + __u8 reserved80[128]; /* 0x0080 */ }; struct kvm_arch{ diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 3acf08ba88e4ff..deac47378f777b 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -654,6 +654,52 @@ long kvm_arch_vm_ioctl(struct file *filp, return r; } +static int kvm_s390_query_ap_config(u8 *config) +{ + u32 fcn_code = 0x04000000UL; + u32 cc; + + asm volatile( + "lgr 0,%1\n" + "lgr 2,%2\n" + ".long 0xb2af0000\n" /* PQAP(QCI) */ + "ipm %0\n" + "srl %0,28\n" + : "=r" (cc) + : "r" (fcn_code), "r" (config) + : "cc", "0", "2", "memory" + ); + + return cc; +} + +static int kvm_s390_apxa_installed(void) +{ + u8 config[128]; + int cc; + + if (test_facility(2) && test_facility(12)) { + cc = kvm_s390_query_ap_config(config); + + if (cc) + pr_err("PQAP(QCI) failed with cc=%d", cc); + else + return config[0] & 0x40; + } + + return 0; +} + +static void kvm_s390_set_crycb_format(struct kvm *kvm) +{ + kvm->arch.crypto.crycbd = (__u32)(unsigned long) kvm->arch.crypto.crycb; + + if (kvm_s390_apxa_installed()) + kvm->arch.crypto.crycbd |= CRYCB_FORMAT2; + else + kvm->arch.crypto.crycbd |= CRYCB_FORMAT1; +} + static int kvm_s390_crypto_init(struct kvm *kvm) { if (!test_vfacility(76)) @@ -664,8 +710,7 @@ static int kvm_s390_crypto_init(struct kvm *kvm) if (!kvm->arch.crypto.crycb) return -ENOMEM; - kvm->arch.crypto.crycbd = (__u32) (unsigned long) kvm->arch.crypto.crycb | - CRYCB_FORMAT1; + kvm_s390_set_crycb_format(kvm); /* Disable AES/DEA protected key functions by default */ kvm->arch.crypto.aes_kw = 0; From 9d8d578605b4fca37bd2230bbacb3ad0ee48e7e4 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 2 Feb 2015 15:42:51 +0100 Subject: [PATCH 2831/3023] KVM: s390: use facilities and cpu_id per KVM The patch introduces facilities and cpu_ids per virtual machine. Different virtual machines may want to expose different facilities and cpu ids to the guest, so let's make them per-vm instead of global. Signed-off-by: Michael Mueller Reviewed-by: Cornelia Huck Reviewed-by: David Hildenbrand Signed-off-by: Christian Borntraeger --- arch/s390/include/asm/kvm_host.h | 21 ++++++++ arch/s390/kvm/gaccess.c | 4 +- arch/s390/kvm/kvm-s390.c | 92 ++++++++++++++++++++------------ arch/s390/kvm/kvm-s390.h | 13 +++-- arch/s390/kvm/priv.c | 13 +++-- 5 files changed, 99 insertions(+), 44 deletions(-) diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index 77ae01444e982f..79dc3b0aa65fb9 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h @@ -506,6 +506,26 @@ struct s390_io_adapter { #define MAX_S390_IO_ADAPTERS ((MAX_ISC + 1) * 8) #define MAX_S390_ADAPTER_MAPS 256 +/* maximum size of facilities and facility mask is 2k bytes */ +#define S390_ARCH_FAC_LIST_SIZE_BYTE (1<<11) +#define S390_ARCH_FAC_LIST_SIZE_U64 \ + (S390_ARCH_FAC_LIST_SIZE_BYTE / sizeof(u64)) +#define S390_ARCH_FAC_MASK_SIZE_BYTE S390_ARCH_FAC_LIST_SIZE_BYTE +#define S390_ARCH_FAC_MASK_SIZE_U64 \ + (S390_ARCH_FAC_MASK_SIZE_BYTE / sizeof(u64)) + +struct s390_model_fac { + /* facilities used in SIE context */ + __u64 sie[S390_ARCH_FAC_LIST_SIZE_U64]; + /* subset enabled by kvm */ + __u64 kvm[S390_ARCH_FAC_LIST_SIZE_U64]; +}; + +struct kvm_s390_cpu_model { + struct s390_model_fac *fac; + struct cpuid cpu_id; +}; + struct kvm_s390_crypto { struct kvm_s390_crypto_cb *crycb; __u32 crycbd; @@ -536,6 +556,7 @@ struct kvm_arch{ int ipte_lock_count; struct mutex ipte_mutex; spinlock_t start_stop_lock; + struct kvm_s390_cpu_model model; struct kvm_s390_crypto crypto; u64 epoch; }; diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c index 8a1be901773055..267523cac6de78 100644 --- a/arch/s390/kvm/gaccess.c +++ b/arch/s390/kvm/gaccess.c @@ -357,8 +357,8 @@ static unsigned long guest_translate(struct kvm_vcpu *vcpu, unsigned long gva, union asce asce; ctlreg0.val = vcpu->arch.sie_block->gcr[0]; - edat1 = ctlreg0.edat && test_vfacility(8); - edat2 = edat1 && test_vfacility(78); + edat1 = ctlreg0.edat && test_kvm_facility(vcpu->kvm, 8); + edat2 = edat1 && test_kvm_facility(vcpu->kvm, 78); asce.val = get_vcpu_asce(vcpu); if (asce.r) goto real_address; diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index deac47378f777b..8c538a1a23c1d8 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include "kvm-s390.h" #include "gaccess.h" @@ -100,15 +99,20 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { { NULL } }; -unsigned long *vfacilities; -static struct gmap_notifier gmap_notifier; +/* upper facilities limit for kvm */ +unsigned long kvm_s390_fac_list_mask[] = { + 0xff82fffbf4fc2000UL, + 0x005c000000000000UL, +}; -/* test availability of vfacility */ -int test_vfacility(unsigned long nr) +unsigned long kvm_s390_fac_list_mask_size(void) { - return __test_facility(nr, (void *) vfacilities); + BUILD_BUG_ON(ARRAY_SIZE(kvm_s390_fac_list_mask) > S390_ARCH_FAC_MASK_SIZE_U64); + return ARRAY_SIZE(kvm_s390_fac_list_mask); } +static struct gmap_notifier gmap_notifier; + /* Section: not file related */ int kvm_arch_hardware_enable(void) { @@ -351,7 +355,7 @@ static int kvm_s390_vm_set_crypto(struct kvm *kvm, struct kvm_device_attr *attr) struct kvm_vcpu *vcpu; int i; - if (!test_vfacility(76)) + if (!test_kvm_facility(kvm, 76)) return -EINVAL; mutex_lock(&kvm->lock); @@ -700,9 +704,15 @@ static void kvm_s390_set_crycb_format(struct kvm *kvm) kvm->arch.crypto.crycbd |= CRYCB_FORMAT1; } +static void kvm_s390_get_cpu_id(struct cpuid *cpu_id) +{ + get_cpu_id(cpu_id); + cpu_id->version = 0xff; +} + static int kvm_s390_crypto_init(struct kvm *kvm) { - if (!test_vfacility(76)) + if (!test_kvm_facility(kvm, 76)) return 0; kvm->arch.crypto.crycb = kzalloc(sizeof(*kvm->arch.crypto.crycb), @@ -721,7 +731,7 @@ static int kvm_s390_crypto_init(struct kvm *kvm) int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) { - int rc; + int i, rc; char debug_name[16]; static unsigned long sca_offset; @@ -756,6 +766,34 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) if (!kvm->arch.dbf) goto out_nodbf; + /* + * The architectural maximum amount of facilities is 16 kbit. To store + * this amount, 2 kbyte of memory is required. Thus we need a full + * page to hold the active copy (arch.model.fac->sie) and the current + * facilities set (arch.model.fac->kvm). Its address size has to be + * 31 bits and word aligned. + */ + kvm->arch.model.fac = + (struct s390_model_fac *) get_zeroed_page(GFP_KERNEL | GFP_DMA); + if (!kvm->arch.model.fac) + goto out_nofac; + + memcpy(kvm->arch.model.fac->kvm, S390_lowcore.stfle_fac_list, + S390_ARCH_FAC_LIST_SIZE_U64); + + /* + * Apply the kvm facility mask to limit the kvm supported/tolerated + * facility list. + */ + for (i = 0; i < S390_ARCH_FAC_LIST_SIZE_U64; i++) { + if (i < kvm_s390_fac_list_mask_size()) + kvm->arch.model.fac->kvm[i] &= kvm_s390_fac_list_mask[i]; + else + kvm->arch.model.fac->kvm[i] = 0UL; + } + + kvm_s390_get_cpu_id(&kvm->arch.model.cpu_id); + if (kvm_s390_crypto_init(kvm) < 0) goto out_crypto; @@ -787,6 +825,8 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) out_nogmap: kfree(kvm->arch.crypto.crycb); out_crypto: + free_page((unsigned long)kvm->arch.model.fac); +out_nofac: debug_unregister(kvm->arch.dbf); out_nodbf: free_page((unsigned long)(kvm->arch.sca)); @@ -839,6 +879,7 @@ static void kvm_free_vcpus(struct kvm *kvm) void kvm_arch_destroy_vm(struct kvm *kvm) { kvm_free_vcpus(kvm); + free_page((unsigned long)kvm->arch.model.fac); free_page((unsigned long)(kvm->arch.sca)); debug_unregister(kvm->arch.dbf); kfree(kvm->arch.crypto.crycb); @@ -934,7 +975,7 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu) { - if (!test_vfacility(76)) + if (!test_kvm_facility(vcpu->kvm, 76)) return; vcpu->arch.sie_block->ecb3 &= ~(ECB3_AES | ECB3_DEA); @@ -973,7 +1014,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) CPUSTAT_STOPPED | CPUSTAT_GED); vcpu->arch.sie_block->ecb = 6; - if (test_vfacility(50) && test_vfacility(73)) + if (test_kvm_facility(vcpu->kvm, 50) && test_kvm_facility(vcpu->kvm, 73)) vcpu->arch.sie_block->ecb |= 0x10; vcpu->arch.sie_block->ecb2 = 8; @@ -982,7 +1023,6 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) vcpu->arch.sie_block->eca |= 1; if (sclp_has_sigpif()) vcpu->arch.sie_block->eca |= 0x10000000U; - vcpu->arch.sie_block->fac = (int) (long) vfacilities; vcpu->arch.sie_block->ictl |= ICTL_ISKE | ICTL_SSKE | ICTL_RRBE | ICTL_TPROT; @@ -993,8 +1033,10 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) } hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); vcpu->arch.ckc_timer.function = kvm_s390_idle_wakeup; - get_cpu_id(&vcpu->arch.cpu_id); - vcpu->arch.cpu_id.version = 0xff; + + vcpu->arch.cpu_id = vcpu->kvm->arch.model.cpu_id; + memcpy(vcpu->kvm->arch.model.fac->sie, vcpu->kvm->arch.model.fac->kvm, + S390_ARCH_FAC_LIST_SIZE_BYTE); kvm_s390_vcpu_crypto_setup(vcpu); @@ -1038,6 +1080,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, vcpu->arch.sie_block->scaol = (__u32)(__u64)kvm->arch.sca; set_bit(63 - id, (unsigned long *) &kvm->arch.sca->mcn); } + vcpu->arch.sie_block->fac = (int) (long) kvm->arch.model.fac->sie; spin_lock_init(&vcpu->arch.local_int.lock); vcpu->arch.local_int.float_int = &kvm->arch.float_int; @@ -2103,30 +2146,11 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, static int __init kvm_s390_init(void) { - int ret; - ret = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE); - if (ret) - return ret; - - /* - * guests can ask for up to 255+1 double words, we need a full page - * to hold the maximum amount of facilities. On the other hand, we - * only set facilities that are known to work in KVM. - */ - vfacilities = (unsigned long *) get_zeroed_page(GFP_KERNEL|GFP_DMA); - if (!vfacilities) { - kvm_exit(); - return -ENOMEM; - } - memcpy(vfacilities, S390_lowcore.stfle_fac_list, 16); - vfacilities[0] &= 0xff82fffbf4fc2000UL; - vfacilities[1] &= 0x005c000000000000UL; - return 0; + return kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE); } static void __exit kvm_s390_exit(void) { - free_page((unsigned long) vfacilities); kvm_exit(); } diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h index c22dce8a753677..985c2114d7ef3b 100644 --- a/arch/s390/kvm/kvm-s390.h +++ b/arch/s390/kvm/kvm-s390.h @@ -18,12 +18,10 @@ #include #include #include +#include typedef int (*intercept_handler_t)(struct kvm_vcpu *vcpu); -/* declare vfacilities extern */ -extern unsigned long *vfacilities; - /* Transactional Memory Execution related macros */ #define IS_TE_ENABLED(vcpu) ((vcpu->arch.sie_block->ecb & 0x10)) #define TDB_FORMAT1 1 @@ -127,6 +125,12 @@ static inline void kvm_s390_set_psw_cc(struct kvm_vcpu *vcpu, unsigned long cc) vcpu->arch.sie_block->gpsw.mask |= cc << 44; } +/* test availability of facility in a kvm intance */ +static inline int test_kvm_facility(struct kvm *kvm, unsigned long nr) +{ + return __test_facility(nr, kvm->arch.model.fac->kvm); +} + /* are cpu states controlled by user space */ static inline int kvm_s390_user_cpu_state_ctrl(struct kvm *kvm) { @@ -183,7 +187,8 @@ int kvm_s390_vcpu_setup_cmma(struct kvm_vcpu *vcpu); void kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu); /* is cmma enabled */ bool kvm_s390_cmma_enabled(struct kvm *kvm); -int test_vfacility(unsigned long nr); +unsigned long kvm_s390_fac_list_mask_size(void); +extern unsigned long kvm_s390_fac_list_mask[]; /* implemented in diag.c */ int kvm_s390_handle_diag(struct kvm_vcpu *vcpu); diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 1be578d64dfc78..bdd9b5b17e03ed 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c @@ -337,19 +337,24 @@ static int handle_io_inst(struct kvm_vcpu *vcpu) static int handle_stfl(struct kvm_vcpu *vcpu) { int rc; + unsigned int fac; vcpu->stat.instruction_stfl++; if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); + /* + * We need to shift the lower 32 facility bits (bit 0-31) from a u64 + * into a u32 memory representation. They will remain bits 0-31. + */ + fac = *vcpu->kvm->arch.model.fac->sie >> 32; rc = write_guest_lc(vcpu, offsetof(struct _lowcore, stfl_fac_list), - vfacilities, 4); + &fac, sizeof(fac)); if (rc) return rc; - VCPU_EVENT(vcpu, 5, "store facility list value %x", - *(unsigned int *) vfacilities); - trace_kvm_s390_handle_stfl(vcpu, *(unsigned int *) vfacilities); + VCPU_EVENT(vcpu, 5, "store facility list value %x", fac); + trace_kvm_s390_handle_stfl(vcpu, fac); return 0; } From 658b6eda2042c0fe0e3f8acd7ffd11fc6f280119 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 2 Feb 2015 15:49:35 +0100 Subject: [PATCH 2832/3023] KVM: s390: add cpu model support This patch enables cpu model support in kvm/s390 via the vm attribute interface. During KVM initialization, the host properties cpuid, IBC value and the facility list are stored in the architecture specific cpu model structure. During vcpu setup, these properties are taken to initialize the related SIE state. This mechanism allows to adjust the properties from user space and thus to implement different selectable cpu models. This patch uses the IBC functionality to block instructions that have not been implemented at the requested CPU type and GA level compared to the full host capability. Userspace has to initialize the cpu model before vcpu creation. A cpu model change of running vcpus is not possible. Signed-off-by: Michael Mueller Reviewed-by: Cornelia Huck Reviewed-by: David Hildenbrand Signed-off-by: Christian Borntraeger --- Documentation/virtual/kvm/devices/vm.txt | 45 ++++++++ arch/s390/include/asm/kvm_host.h | 4 +- arch/s390/include/uapi/asm/kvm.h | 21 ++++ arch/s390/kvm/kvm-s390.c | 132 +++++++++++++++++++++++ 4 files changed, 201 insertions(+), 1 deletion(-) diff --git a/Documentation/virtual/kvm/devices/vm.txt b/Documentation/virtual/kvm/devices/vm.txt index c3b17c61b7dd26..5542c4641a3c97 100644 --- a/Documentation/virtual/kvm/devices/vm.txt +++ b/Documentation/virtual/kvm/devices/vm.txt @@ -38,3 +38,48 @@ Allows userspace to query the actual limit and set a new limit for the maximum guest memory size. The limit will be rounded up to 2048 MB, 4096 GB, 8192 TB respectively, as this limit is governed by the number of page table levels. + +2. GROUP: KVM_S390_VM_CPU_MODEL +Architectures: s390 + +2.1. ATTRIBUTE: KVM_S390_VM_CPU_MACHINE (r/o) + +Allows user space to retrieve machine and kvm specific cpu related information: + +struct kvm_s390_vm_cpu_machine { + __u64 cpuid; # CPUID of host + __u32 ibc; # IBC level range offered by host + __u8 pad[4]; + __u64 fac_mask[256]; # set of cpu facilities enabled by KVM + __u64 fac_list[256]; # set of cpu facilities offered by host +} + +Parameters: address of buffer to store the machine related cpu data + of type struct kvm_s390_vm_cpu_machine* +Returns: -EFAULT if the given address is not accessible from kernel space + -ENOMEM if not enough memory is available to process the ioctl + 0 in case of success + +2.2. ATTRIBUTE: KVM_S390_VM_CPU_PROCESSOR (r/w) + +Allows user space to retrieve or request to change cpu related information for a vcpu: + +struct kvm_s390_vm_cpu_processor { + __u64 cpuid; # CPUID currently (to be) used by this vcpu + __u16 ibc; # IBC level currently (to be) used by this vcpu + __u8 pad[6]; + __u64 fac_list[256]; # set of cpu facilities currently (to be) used + # by this vcpu +} + +KVM does not enforce or limit the cpu model data in any form. Take the information +retrieved by means of KVM_S390_VM_CPU_MACHINE as hint for reasonable configuration +setups. Instruction interceptions triggered by additionally set facilitiy bits that +are not handled by KVM need to by imlemented in the VM driver code. + +Parameters: address of buffer to store/set the processor related cpu + data of type struct kvm_s390_vm_cpu_processor*. +Returns: -EBUSY in case 1 or more vcpus are already activated (only in write case) + -EFAULT if the given address is not accessible from kernel space + -ENOMEM if not enough memory is available to process the ioctl + 0 in case of success diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index 79dc3b0aa65fb9..d84559e31f3222 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h @@ -89,7 +89,8 @@ struct kvm_s390_sie_block { atomic_t cpuflags; /* 0x0000 */ __u32 : 1; /* 0x0004 */ __u32 prefix : 18; - __u32 : 13; + __u32 : 1; + __u32 ibc : 12; __u8 reserved08[4]; /* 0x0008 */ #define PROG_IN_SIE (1<<0) __u32 prog0c; /* 0x000c */ @@ -524,6 +525,7 @@ struct s390_model_fac { struct kvm_s390_cpu_model { struct s390_model_fac *fac; struct cpuid cpu_id; + unsigned short ibc; }; struct kvm_s390_crypto { diff --git a/arch/s390/include/uapi/asm/kvm.h b/arch/s390/include/uapi/asm/kvm.h index 546fc3a302e5c3..9c77e60b9a269a 100644 --- a/arch/s390/include/uapi/asm/kvm.h +++ b/arch/s390/include/uapi/asm/kvm.h @@ -59,6 +59,7 @@ struct kvm_s390_io_adapter_req { #define KVM_S390_VM_MEM_CTRL 0 #define KVM_S390_VM_TOD 1 #define KVM_S390_VM_CRYPTO 2 +#define KVM_S390_VM_CPU_MODEL 3 /* kvm attributes for mem_ctrl */ #define KVM_S390_VM_MEM_ENABLE_CMMA 0 @@ -69,6 +70,26 @@ struct kvm_s390_io_adapter_req { #define KVM_S390_VM_TOD_LOW 0 #define KVM_S390_VM_TOD_HIGH 1 +/* kvm attributes for KVM_S390_VM_CPU_MODEL */ +/* processor related attributes are r/w */ +#define KVM_S390_VM_CPU_PROCESSOR 0 +struct kvm_s390_vm_cpu_processor { + __u64 cpuid; + __u16 ibc; + __u8 pad[6]; + __u64 fac_list[256]; +}; + +/* machine related attributes are r/o */ +#define KVM_S390_VM_CPU_MACHINE 1 +struct kvm_s390_vm_cpu_machine { + __u64 cpuid; + __u32 ibc; + __u8 pad[4]; + __u64 fac_mask[256]; + __u64 fac_list[256]; +}; + /* kvm attributes for crypto */ #define KVM_S390_VM_CRYPTO_ENABLE_AES_KW 0 #define KVM_S390_VM_CRYPTO_ENABLE_DEA_KW 1 diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 8c538a1a23c1d8..0c362392756310 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -502,6 +502,106 @@ static int kvm_s390_get_tod(struct kvm *kvm, struct kvm_device_attr *attr) return ret; } +static int kvm_s390_set_processor(struct kvm *kvm, struct kvm_device_attr *attr) +{ + struct kvm_s390_vm_cpu_processor *proc; + int ret = 0; + + mutex_lock(&kvm->lock); + if (atomic_read(&kvm->online_vcpus)) { + ret = -EBUSY; + goto out; + } + proc = kzalloc(sizeof(*proc), GFP_KERNEL); + if (!proc) { + ret = -ENOMEM; + goto out; + } + if (!copy_from_user(proc, (void __user *)attr->addr, + sizeof(*proc))) { + memcpy(&kvm->arch.model.cpu_id, &proc->cpuid, + sizeof(struct cpuid)); + kvm->arch.model.ibc = proc->ibc; + memcpy(kvm->arch.model.fac->kvm, proc->fac_list, + S390_ARCH_FAC_LIST_SIZE_BYTE); + } else + ret = -EFAULT; + kfree(proc); +out: + mutex_unlock(&kvm->lock); + return ret; +} + +static int kvm_s390_set_cpu_model(struct kvm *kvm, struct kvm_device_attr *attr) +{ + int ret = -ENXIO; + + switch (attr->attr) { + case KVM_S390_VM_CPU_PROCESSOR: + ret = kvm_s390_set_processor(kvm, attr); + break; + } + return ret; +} + +static int kvm_s390_get_processor(struct kvm *kvm, struct kvm_device_attr *attr) +{ + struct kvm_s390_vm_cpu_processor *proc; + int ret = 0; + + proc = kzalloc(sizeof(*proc), GFP_KERNEL); + if (!proc) { + ret = -ENOMEM; + goto out; + } + memcpy(&proc->cpuid, &kvm->arch.model.cpu_id, sizeof(struct cpuid)); + proc->ibc = kvm->arch.model.ibc; + memcpy(&proc->fac_list, kvm->arch.model.fac->kvm, S390_ARCH_FAC_LIST_SIZE_BYTE); + if (copy_to_user((void __user *)attr->addr, proc, sizeof(*proc))) + ret = -EFAULT; + kfree(proc); +out: + return ret; +} + +static int kvm_s390_get_machine(struct kvm *kvm, struct kvm_device_attr *attr) +{ + struct kvm_s390_vm_cpu_machine *mach; + int ret = 0; + + mach = kzalloc(sizeof(*mach), GFP_KERNEL); + if (!mach) { + ret = -ENOMEM; + goto out; + } + get_cpu_id((struct cpuid *) &mach->cpuid); + mach->ibc = sclp_get_ibc(); + memcpy(&mach->fac_mask, kvm_s390_fac_list_mask, + kvm_s390_fac_list_mask_size() * sizeof(u64)); + memcpy((unsigned long *)&mach->fac_list, S390_lowcore.stfle_fac_list, + S390_ARCH_FAC_LIST_SIZE_U64); + if (copy_to_user((void __user *)attr->addr, mach, sizeof(*mach))) + ret = -EFAULT; + kfree(mach); +out: + return ret; +} + +static int kvm_s390_get_cpu_model(struct kvm *kvm, struct kvm_device_attr *attr) +{ + int ret = -ENXIO; + + switch (attr->attr) { + case KVM_S390_VM_CPU_PROCESSOR: + ret = kvm_s390_get_processor(kvm, attr); + break; + case KVM_S390_VM_CPU_MACHINE: + ret = kvm_s390_get_machine(kvm, attr); + break; + } + return ret; +} + static int kvm_s390_vm_set_attr(struct kvm *kvm, struct kvm_device_attr *attr) { int ret; @@ -513,6 +613,9 @@ static int kvm_s390_vm_set_attr(struct kvm *kvm, struct kvm_device_attr *attr) case KVM_S390_VM_TOD: ret = kvm_s390_set_tod(kvm, attr); break; + case KVM_S390_VM_CPU_MODEL: + ret = kvm_s390_set_cpu_model(kvm, attr); + break; case KVM_S390_VM_CRYPTO: ret = kvm_s390_vm_set_crypto(kvm, attr); break; @@ -535,6 +638,9 @@ static int kvm_s390_vm_get_attr(struct kvm *kvm, struct kvm_device_attr *attr) case KVM_S390_VM_TOD: ret = kvm_s390_get_tod(kvm, attr); break; + case KVM_S390_VM_CPU_MODEL: + ret = kvm_s390_get_cpu_model(kvm, attr); + break; default: ret = -ENXIO; break; @@ -571,6 +677,17 @@ static int kvm_s390_vm_has_attr(struct kvm *kvm, struct kvm_device_attr *attr) break; } break; + case KVM_S390_VM_CPU_MODEL: + switch (attr->attr) { + case KVM_S390_VM_CPU_PROCESSOR: + case KVM_S390_VM_CPU_MACHINE: + ret = 0; + break; + default: + ret = -ENXIO; + break; + } + break; case KVM_S390_VM_CRYPTO: switch (attr->attr) { case KVM_S390_VM_CRYPTO_ENABLE_AES_KW: @@ -781,6 +898,17 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) memcpy(kvm->arch.model.fac->kvm, S390_lowcore.stfle_fac_list, S390_ARCH_FAC_LIST_SIZE_U64); + /* + * If this KVM host runs *not* in a LPAR, relax the facility bits + * of the kvm facility mask by all missing facilities. This will allow + * to determine the right CPU model by means of the remaining facilities. + * Live guest migration must prohibit the migration of KVMs running in + * a LPAR to non LPAR hosts. + */ + if (!MACHINE_IS_LPAR) + for (i = 0; i < kvm_s390_fac_list_mask_size(); i++) + kvm_s390_fac_list_mask[i] &= kvm->arch.model.fac->kvm[i]; + /* * Apply the kvm facility mask to limit the kvm supported/tolerated * facility list. @@ -793,6 +921,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) } kvm_s390_get_cpu_id(&kvm->arch.model.cpu_id); + kvm->arch.model.ibc = sclp_get_ibc() & 0x0fff; if (kvm_s390_crypto_init(kvm) < 0) goto out_crypto; @@ -1034,9 +1163,12 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); vcpu->arch.ckc_timer.function = kvm_s390_idle_wakeup; + mutex_lock(&vcpu->kvm->lock); vcpu->arch.cpu_id = vcpu->kvm->arch.model.cpu_id; memcpy(vcpu->kvm->arch.model.fac->sie, vcpu->kvm->arch.model.fac->kvm, S390_ARCH_FAC_LIST_SIZE_BYTE); + vcpu->arch.sie_block->ibc = vcpu->kvm->arch.model.ibc; + mutex_unlock(&vcpu->kvm->lock); kvm_s390_vcpu_crypto_setup(vcpu); From de8e5d744051568c8aad35c1c2dcf8fd137d10c9 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Tue, 3 Feb 2015 09:35:15 +0100 Subject: [PATCH 2833/3023] KVM: Disable compat ioctl for s390 We never had a 31bit QEMU/kuli running. We would need to review several ioctls to check if this creates holes, bugs or whatever to make it work. Lets just disable compat support for KVM on s390. Signed-off-by: Christian Borntraeger Acked-by: Paolo Bonzini --- virt/kvm/Kconfig | 4 ++++ virt/kvm/kvm_main.c | 12 ++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig index 50d110654b42df..e2c876d5a03be0 100644 --- a/virt/kvm/Kconfig +++ b/virt/kvm/Kconfig @@ -43,3 +43,7 @@ config HAVE_KVM_ARCH_TLB_FLUSH_ALL config KVM_GENERIC_DIRTYLOG_READ_PROTECT bool + +config KVM_COMPAT + def_bool y + depends on COMPAT && !S390 diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 32449e0e9aa8a0..8579f1876e5a9f 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -92,7 +92,7 @@ struct dentry *kvm_debugfs_dir; static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl, unsigned long arg); -#ifdef CONFIG_COMPAT +#ifdef CONFIG_KVM_COMPAT static long kvm_vcpu_compat_ioctl(struct file *file, unsigned int ioctl, unsigned long arg); #endif @@ -2052,7 +2052,7 @@ static int kvm_vcpu_release(struct inode *inode, struct file *filp) static struct file_operations kvm_vcpu_fops = { .release = kvm_vcpu_release, .unlocked_ioctl = kvm_vcpu_ioctl, -#ifdef CONFIG_COMPAT +#ifdef CONFIG_KVM_COMPAT .compat_ioctl = kvm_vcpu_compat_ioctl, #endif .mmap = kvm_vcpu_mmap, @@ -2342,7 +2342,7 @@ static long kvm_vcpu_ioctl(struct file *filp, return r; } -#ifdef CONFIG_COMPAT +#ifdef CONFIG_KVM_COMPAT static long kvm_vcpu_compat_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) { @@ -2434,7 +2434,7 @@ static int kvm_device_release(struct inode *inode, struct file *filp) static const struct file_operations kvm_device_fops = { .unlocked_ioctl = kvm_device_ioctl, -#ifdef CONFIG_COMPAT +#ifdef CONFIG_KVM_COMPAT .compat_ioctl = kvm_device_ioctl, #endif .release = kvm_device_release, @@ -2721,7 +2721,7 @@ static long kvm_vm_ioctl(struct file *filp, return r; } -#ifdef CONFIG_COMPAT +#ifdef CONFIG_KVM_COMPAT struct compat_kvm_dirty_log { __u32 slot; __u32 padding1; @@ -2768,7 +2768,7 @@ static long kvm_vm_compat_ioctl(struct file *filp, static struct file_operations kvm_vm_fops = { .release = kvm_vm_release, .unlocked_ioctl = kvm_vm_ioctl, -#ifdef CONFIG_COMPAT +#ifdef CONFIG_KVM_COMPAT .compat_ioctl = kvm_vm_compat_ioctl, #endif .llseek = noop_llseek, From d180d2bbb66579e3bf449642b8ec2a76f4014fcd Mon Sep 17 00:00:00 2001 From: Shobhit Kumar Date: Thu, 5 Feb 2015 17:10:56 +0530 Subject: [PATCH 2834/3023] drm/i915: Correct the IOSF Dev_FN field for IOSF transfers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As per the specififcation, the SB_DevFn is the PCI_DEVFN of the target device and not the source. So PCI_DEVFN(2,0) is not correct. Further the port ID should be enough to identify devices unless they are MFD. The SB_DevFn was intended to remove ambiguity in case of these MFD devices. For non MFD devices the recommendation for the target device IP was to ignore these fields, but not all of them followed the recommendation. Some like CCK ignore these fields and hence PCI_DEVFN(2, 0) works and so does PCI_DEVFN(0, 0) as it works for DPIO. The issue came to light because of GPIONC which was not getting programmed correctly with PCI_DEVFN(2, 0). It turned out that this did not follow the recommendation and expected 0 in this field. In general the recommendation is to use SB_DevFn as PCI_DEVFN(0, 0) for all devices except target PCI devices. Signed-off-by: Shobhit Kumar Reviewed-by: Ville Syrjälä Cc: stable@vger.kernel.org Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_sideband.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_sideband.c b/drivers/gpu/drm/i915/intel_sideband.c index 3c42eeffa3cb45..693ce82819709f 100644 --- a/drivers/gpu/drm/i915/intel_sideband.c +++ b/drivers/gpu/drm/i915/intel_sideband.c @@ -82,7 +82,7 @@ u32 vlv_punit_read(struct drm_i915_private *dev_priv, u32 addr) WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); mutex_lock(&dev_priv->dpio_lock); - vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_PUNIT, + vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_PUNIT, SB_CRRDDA_NP, addr, &val); mutex_unlock(&dev_priv->dpio_lock); @@ -94,7 +94,7 @@ void vlv_punit_write(struct drm_i915_private *dev_priv, u32 addr, u32 val) WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); mutex_lock(&dev_priv->dpio_lock); - vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_PUNIT, + vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_PUNIT, SB_CRWRDA_NP, addr, &val); mutex_unlock(&dev_priv->dpio_lock); } @@ -103,7 +103,7 @@ u32 vlv_bunit_read(struct drm_i915_private *dev_priv, u32 reg) { u32 val = 0; - vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_BUNIT, + vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_BUNIT, SB_CRRDDA_NP, reg, &val); return val; @@ -111,7 +111,7 @@ u32 vlv_bunit_read(struct drm_i915_private *dev_priv, u32 reg) void vlv_bunit_write(struct drm_i915_private *dev_priv, u32 reg, u32 val) { - vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_BUNIT, + vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_BUNIT, SB_CRWRDA_NP, reg, &val); } @@ -122,7 +122,7 @@ u32 vlv_nc_read(struct drm_i915_private *dev_priv, u8 addr) WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); mutex_lock(&dev_priv->dpio_lock); - vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_NC, + vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_NC, SB_CRRDDA_NP, addr, &val); mutex_unlock(&dev_priv->dpio_lock); @@ -132,56 +132,56 @@ u32 vlv_nc_read(struct drm_i915_private *dev_priv, u8 addr) u32 vlv_gpio_nc_read(struct drm_i915_private *dev_priv, u32 reg) { u32 val = 0; - vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_GPIO_NC, + vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_GPIO_NC, SB_CRRDDA_NP, reg, &val); return val; } void vlv_gpio_nc_write(struct drm_i915_private *dev_priv, u32 reg, u32 val) { - vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_GPIO_NC, + vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_GPIO_NC, SB_CRWRDA_NP, reg, &val); } u32 vlv_cck_read(struct drm_i915_private *dev_priv, u32 reg) { u32 val = 0; - vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_CCK, + vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_CCK, SB_CRRDDA_NP, reg, &val); return val; } void vlv_cck_write(struct drm_i915_private *dev_priv, u32 reg, u32 val) { - vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_CCK, + vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_CCK, SB_CRWRDA_NP, reg, &val); } u32 vlv_ccu_read(struct drm_i915_private *dev_priv, u32 reg) { u32 val = 0; - vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_CCU, + vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_CCU, SB_CRRDDA_NP, reg, &val); return val; } void vlv_ccu_write(struct drm_i915_private *dev_priv, u32 reg, u32 val) { - vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_CCU, + vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_CCU, SB_CRWRDA_NP, reg, &val); } u32 vlv_gps_core_read(struct drm_i915_private *dev_priv, u32 reg) { u32 val = 0; - vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_GPS_CORE, + vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_GPS_CORE, SB_CRRDDA_NP, reg, &val); return val; } void vlv_gps_core_write(struct drm_i915_private *dev_priv, u32 reg, u32 val) { - vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_GPS_CORE, + vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_GPS_CORE, SB_CRWRDA_NP, reg, &val); } From ebbc7546d2099c94ff2ea940ae5ce740e512a66d Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Thu, 5 Feb 2015 18:41:48 +0200 Subject: [PATCH 2835/3023] drm/i915: Take runtime pm reference on hangcheck_info We read the coherent current seqno and actual head from ring. For hardware access we need to take runtime_pm reference. Get hardware specific values with runtime reference held and print them first to emphasize hw state vs bookkeepping. v2: Reorder output according to hw access (Chris) remove superfluous locking (Daniel) Testcase: igt/pm_rpm/debugfs-read Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=88910 Tested-by: Ding Heng (v1) Signed-off-by: Mika Kuoppala Reviewed-by: Chris Wilson Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_debugfs.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 211d4949a67586..96e811fe24ca79 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1223,8 +1223,11 @@ static int i915_frequency_info(struct seq_file *m, void *unused) static int i915_hangcheck_info(struct seq_file *m, void *unused) { struct drm_info_node *node = m->private; - struct drm_i915_private *dev_priv = to_i915(node->minor->dev); + struct drm_device *dev = node->minor->dev; + struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *ring; + u64 acthd[I915_NUM_RINGS]; + u32 seqno[I915_NUM_RINGS]; int i; if (!i915.enable_hangcheck) { @@ -1232,6 +1235,15 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) return 0; } + intel_runtime_pm_get(dev_priv); + + for_each_ring(ring, dev_priv, i) { + seqno[i] = ring->get_seqno(ring, false); + acthd[i] = intel_ring_get_active_head(ring); + } + + intel_runtime_pm_put(dev_priv); + if (delayed_work_pending(&dev_priv->gpu_error.hangcheck_work)) { seq_printf(m, "Hangcheck active, fires in %dms\n", jiffies_to_msecs(dev_priv->gpu_error.hangcheck_work.timer.expires - @@ -1242,14 +1254,14 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) for_each_ring(ring, dev_priv, i) { seq_printf(m, "%s:\n", ring->name); seq_printf(m, "\tseqno = %x [current %x]\n", - ring->hangcheck.seqno, ring->get_seqno(ring, false)); - seq_printf(m, "\taction = %d\n", ring->hangcheck.action); - seq_printf(m, "\tscore = %d\n", ring->hangcheck.score); + ring->hangcheck.seqno, seqno[i]); seq_printf(m, "\tACTHD = 0x%08llx [current 0x%08llx]\n", (long long)ring->hangcheck.acthd, - (long long)intel_ring_get_active_head(ring)); + (long long)acthd[i]); seq_printf(m, "\tmax ACTHD = 0x%08llx\n", (long long)ring->hangcheck.max_acthd); + seq_printf(m, "\tscore = %d\n", ring->hangcheck.score); + seq_printf(m, "\taction = %d\n", ring->hangcheck.action); } return 0; From 3225b2f95dbb9981be9e2002e49cd8abf0d8d01a Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Thu, 5 Feb 2015 17:45:42 +0200 Subject: [PATCH 2836/3023] drm/i915: Squelch overzealous uncore reset WARN_ON We added this WARN_ON to guard against using uninitialized forcewake domains. But forgot blissfully that not all gens have forcewake domains in the first place. v2: Move WARN_ON to fw_domains_init (Chris) Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=88911 Tested-by: Ding Heng (v1) Signed-off-by: Mika Kuoppala Reviewed-by: Chris Wilson [Jani: add comment above WARN_ON as suggested by Chris] Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_uncore.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 76b60a3538b28d..c47a3baa53d596 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -166,7 +166,8 @@ fw_domains_reset(struct drm_i915_private *dev_priv, enum forcewake_domains fw_do struct intel_uncore_forcewake_domain *d; enum forcewake_domain_id id; - WARN_ON(dev_priv->uncore.fw_domains == 0); + if (dev_priv->uncore.fw_domains == 0) + return; for_each_fw_domain_mask(d, fw_domains, dev_priv, id) fw_domain_reset(d); @@ -997,6 +998,9 @@ static void intel_uncore_fw_domains_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + if (INTEL_INFO(dev_priv->dev)->gen <= 5) + return; + if (IS_GEN9(dev)) { dev_priv->uncore.funcs.force_wake_get = fw_domains_get; dev_priv->uncore.funcs.force_wake_put = fw_domains_put; @@ -1069,6 +1073,9 @@ static void intel_uncore_fw_domains_init(struct drm_device *dev) fw_domain_init(dev_priv, FW_DOMAIN_ID_RENDER, FORCEWAKE, FORCEWAKE_ACK); } + + /* All future platforms are expected to require complex power gating */ + WARN_ON(dev_priv->uncore.fw_domains == 0); } void intel_uncore_init(struct drm_device *dev) From d44e1212230a68f9dccd1a95b5c8ca5217c62094 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 9 Feb 2015 10:02:05 +0100 Subject: [PATCH 2837/3023] KVM: x86: emulate: correct page fault error code for NoWrite instructions NoWrite instructions (e.g. cmp or test) never set the "write access" bit in the error code, even if one of the operands is treated as a destination. Fixes: c205fb7d7d4f81e46fc577b707ceb9e356af1456 Cc: Nadav Amit Signed-off-by: Paolo Bonzini --- arch/x86/kvm/emulate.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 81dcf7964701f0..a943bf0c06d0d4 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -4954,7 +4954,8 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt) rc = segmented_read(ctxt, ctxt->dst.addr.mem, &ctxt->dst.val, ctxt->dst.bytes); if (rc != X86EMUL_CONTINUE) { - if (rc == X86EMUL_PROPAGATE_FAULT && + if (!(ctxt->d & NoWrite) && + rc == X86EMUL_PROPAGATE_FAULT && ctxt->exception.vector == PF_VECTOR) ctxt->exception.error_code |= PFERR_WRITE_MASK; goto done; From 30b39f0488eb114b3523de7a6579ef8ff2c40a6e Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 5 Feb 2015 16:11:35 +0900 Subject: [PATCH 2838/3023] drm/exynos: Remove exynos_plane_dpms() call with no effect exynos_plane_dpms(DRM_MODE_DPMS_ON) calls the win_enable()'s callback from the underlying layer. However neither one of these layers implement win_enable() - FIMD, Mixer and VIDI. Thus the call to exynos_plane_dpms() is pointless. Signed-off-by: Gustavo Padovan Acked-by: Daniel Vetter Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index a85c451ba3929f..fff2e5545846c2 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -66,8 +66,6 @@ static void exynos_drm_crtc_commit(struct drm_crtc *crtc) if (exynos_crtc->ops->commit) exynos_crtc->ops->commit(exynos_crtc); - - exynos_plane_dpms(crtc->primary, DRM_MODE_DPMS_ON); } static bool From f27829a184ed3bf44b952fa299f399513bdb0a18 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Thu, 5 Feb 2015 16:11:36 +0900 Subject: [PATCH 2839/3023] drm/exynos: remove mode property of exynos crtc This was added by commit 3b8d1cf818c2 ("drm/exynos: add property for crtc mode"). Currently we can control a plane used for crtc using primary plane by universal plane feature. Stop to use non-standard property to control primary plane. Signed-off-by: Joonyoung Shim Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 60 ------------------------ drivers/gpu/drm/exynos/exynos_drm_drv.h | 8 ---- 2 files changed, 68 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index fff2e5545846c2..48ccab7fdf63e5 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -232,70 +232,12 @@ static void exynos_drm_crtc_destroy(struct drm_crtc *crtc) kfree(exynos_crtc); } -static int exynos_drm_crtc_set_property(struct drm_crtc *crtc, - struct drm_property *property, - uint64_t val) -{ - struct drm_device *dev = crtc->dev; - struct exynos_drm_private *dev_priv = dev->dev_private; - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - - if (property == dev_priv->crtc_mode_property) { - enum exynos_crtc_mode mode = val; - - if (mode == exynos_crtc->mode) - return 0; - - exynos_crtc->mode = mode; - - switch (mode) { - case CRTC_MODE_NORMAL: - exynos_drm_crtc_commit(crtc); - break; - case CRTC_MODE_BLANK: - exynos_plane_dpms(crtc->primary, DRM_MODE_DPMS_OFF); - break; - default: - break; - } - - return 0; - } - - return -EINVAL; -} - static struct drm_crtc_funcs exynos_crtc_funcs = { .set_config = drm_crtc_helper_set_config, .page_flip = exynos_drm_crtc_page_flip, .destroy = exynos_drm_crtc_destroy, - .set_property = exynos_drm_crtc_set_property, -}; - -static const struct drm_prop_enum_list mode_names[] = { - { CRTC_MODE_NORMAL, "normal" }, - { CRTC_MODE_BLANK, "blank" }, }; -static void exynos_drm_crtc_attach_mode_property(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct exynos_drm_private *dev_priv = dev->dev_private; - struct drm_property *prop; - - prop = dev_priv->crtc_mode_property; - if (!prop) { - prop = drm_property_create_enum(dev, 0, "mode", mode_names, - ARRAY_SIZE(mode_names)); - if (!prop) - return; - - dev_priv->crtc_mode_property = prop; - } - - drm_object_attach_property(&crtc->base, prop, 0); -} - struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev, int pipe, enum exynos_drm_output_type type, @@ -338,8 +280,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev, drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs); - exynos_drm_crtc_attach_mode_property(crtc); - return exynos_crtc; err_crtc: diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index d490b49f71c9ec..1aceafce7bbfd6 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -197,11 +197,6 @@ struct exynos_drm_crtc_ops { void (*te_handler)(struct exynos_drm_crtc *crtc); }; -enum exynos_crtc_mode { - CRTC_MODE_NORMAL, /* normal mode */ - CRTC_MODE_BLANK, /* The private plane of crtc is blank */ -}; - /* * Exynos specific crtc structure. * @@ -215,7 +210,6 @@ enum exynos_crtc_mode { * we can refer to the crtc to current hardware interrupt occurred through * this pipe value. * @dpms: store the crtc dpms value - * @mode: store the crtc mode value * @ops: pointer to callbacks for exynos drm specific functionality * @ctx: A pointer to the crtc's implementation specific context */ @@ -224,7 +218,6 @@ struct exynos_drm_crtc { enum exynos_drm_output_type type; unsigned int pipe; unsigned int dpms; - enum exynos_crtc_mode mode; wait_queue_head_t pending_flip_queue; atomic_t pending_flip; struct exynos_drm_crtc_ops *ops; @@ -265,7 +258,6 @@ struct exynos_drm_private { */ struct drm_crtc *crtc[MAX_CRTC]; struct drm_property *plane_zpos_property; - struct drm_property *crtc_mode_property; unsigned long da_start; unsigned long da_space_size; From d9ea62566dbda7afb63c790057f3243f51abf771 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Thu, 5 Feb 2015 16:11:37 +0900 Subject: [PATCH 2840/3023] drm/exynos: remove exynos_plane_dpms The exynos_plane_dpms function handles enabled flag of exynos plane and calls internal hw driver callback function for hw overlay on/off. But it causes state disharmory problem currently and is will be obstacle to apply atomic operation later to keep non-standard per-plane dpms state like enabled flag. Let's remove enabled flag, it just stop to recall internal callback function but hw drivers can handle it properly. And call internal callback function directly then we can remove unnecessary exynos_plane_dpms function Signed-off-by: Joonyoung Shim Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_plane.c | 33 +++++------------------ drivers/gpu/drm/exynos/exynos_drm_plane.h | 1 - 2 files changed, 6 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index 358cff67e5cef8..2dfb847d0ce015 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -145,32 +145,6 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, exynos_crtc->ops->win_mode_set(exynos_crtc, exynos_plane); } -void exynos_plane_dpms(struct drm_plane *plane, int mode) -{ - struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(plane->crtc); - - if (mode == DRM_MODE_DPMS_ON) { - if (exynos_plane->enabled) - return; - - if (exynos_crtc->ops->win_enable) - exynos_crtc->ops->win_enable(exynos_crtc, - exynos_plane->zpos); - - exynos_plane->enabled = true; - } else { - if (!exynos_plane->enabled) - return; - - if (exynos_crtc->ops->win_disable) - exynos_crtc->ops->win_disable(exynos_crtc, - exynos_plane->zpos); - - exynos_plane->enabled = false; - } -} - int exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, struct drm_framebuffer *fb, int crtc_x, int crtc_y, @@ -199,7 +173,12 @@ exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, static int exynos_disable_plane(struct drm_plane *plane) { - exynos_plane_dpms(plane, DRM_MODE_DPMS_OFF); + struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); + struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(plane->crtc); + + if (exynos_crtc->ops->win_disable) + exynos_crtc->ops->win_disable(exynos_crtc, + exynos_plane->zpos); return 0; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h index 59d40755095b3d..9d3c374e7b3ec4 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.h +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h @@ -20,7 +20,6 @@ int exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, unsigned int crtc_w, unsigned int crtc_h, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h); -void exynos_plane_dpms(struct drm_plane *plane, int mode); struct drm_plane *exynos_plane_init(struct drm_device *dev, unsigned long possible_crtcs, enum drm_plane_type type); From 936ce5cce66ce6f9b5138a1ac0fbf0c2d459a960 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Thu, 5 Feb 2015 16:11:38 +0900 Subject: [PATCH 2841/3023] drm/exynos: fix NULL pointer reference There is a case called disable_plane callback function even if plane->crtc is NULL from exynos_drm_encoder_disable and it will cause NULL pointer reference error. Signed-off-by: Joonyoung Shim Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_encoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index 7e282e3d603826..57de0bdc5a3b4e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -102,7 +102,7 @@ static void exynos_drm_encoder_disable(struct drm_encoder *encoder) /* all planes connected to this encoder should be also disabled. */ drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) { - if (plane->crtc == encoder->crtc) + if (plane->crtc && (plane->crtc == encoder->crtc)) plane->funcs->disable_plane(plane); } } From 0ca09685546fed5fc8f0535204f0626f352140f4 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 24 Nov 2014 16:54:11 +0100 Subject: [PATCH 2842/3023] drm/i915: Drop vblank wait from intel_dp_link_down Nothing in Bspec seems to indicate that we actually needs this, and it looks like can't work since by this point the pipe is off and so vblanks won't really happen any more. Note that Bspec mentions that it takes a vblank for this bit to change, but _only_ when enabling. Dropping this code quenches an annoying backtrace introduced by the more anal checking since commit 51e31d49c89055299e34b8f44d13f70e19aaaad1 Author: Daniel Vetter Date: Mon Sep 15 12:36:02 2014 +0200 drm/i915: Use generic vblank wait Note: This fixes the fallout from the above commit, but does not address the shortcomings of the IBX transcoder select workaround implementation discussed during review [1]. [1] http://mid.gmane.org/87y4o7usxf.fsf@intel.com Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=86095 Signed-off-by: Daniel Vetter Reviewed-by: Paulo Zanoni Cc: stable@vger.kernel.org # 3.19 Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_dp.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index eea9e366a109e3..d4c82d776fba81 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3521,8 +3521,6 @@ intel_dp_link_down(struct intel_dp *intel_dp) enum port port = intel_dig_port->port; struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = - to_intel_crtc(intel_dig_port->base.base.crtc); uint32_t DP = intel_dp->DP; if (WARN_ON(HAS_DDI(dev))) @@ -3547,8 +3545,6 @@ intel_dp_link_down(struct intel_dp *intel_dp) if (HAS_PCH_IBX(dev) && I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) { - struct drm_crtc *crtc = intel_dig_port->base.base.crtc; - /* Hardware workaround: leaving our transcoder select * set to transcoder B while it's off will prevent the * corresponding HDMI output on transcoder A. @@ -3559,18 +3555,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) */ DP &= ~DP_PIPEB_SELECT; I915_WRITE(intel_dp->output_reg, DP); - - /* Changes to enable or select take place the vblank - * after being written. - */ - if (WARN_ON(crtc == NULL)) { - /* We should never try to disable a port without a crtc - * attached. For paranoia keep the code around for a - * bit. */ - POSTING_READ(intel_dp->output_reg); - msleep(50); - } else - intel_wait_for_vblank(dev, intel_crtc->pipe); + POSTING_READ(intel_dp->output_reg); } DP &= ~DP_AUDIO_OUTPUT_ENABLE; From 4fe7ffb7e17ca6ad9173b8de35f260c9c8fc2f79 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Wed, 28 Jan 2015 10:57:39 -0800 Subject: [PATCH 2843/3023] genirq: Fix null pointer reference in irq_set_affinity_hint() The recent set_affinity commit by me introduced some null pointer dereferences on driver unload, because some drivers call this function with a NULL argument. This fixes the issue by just checking for null before setting the affinity mask. Fixes: e2e64a932556 ("genirq: Set initial affinity in irq_set_affinity_hint()") Reported-by: Yinghai Lu Signed-off-by: Jesse Brandeburg CC: netdev@vger.kernel.org Link: http://lkml.kernel.org/r/20150128185739.9689.84588.stgit@jbrandeb-cp2.jf.intel.com Signed-off-by: Ingo Molnar --- kernel/irq/manage.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index f038e586a4b9f5..196a06fbc122fe 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -244,7 +244,8 @@ int irq_set_affinity_hint(unsigned int irq, const struct cpumask *m) desc->affinity_hint = m; irq_put_desc_unlock(desc, flags); /* set the initial affinity to prevent every interrupt being on CPU0 */ - __irq_set_affinity(irq, m, false); + if (m) + __irq_set_affinity(irq, m, false); return 0; } EXPORT_SYMBOL_GPL(irq_set_affinity_hint); From f0a1fb10e5f79f5aaf8d7e94b9fa6bf2fa9aeebf Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 22 Jan 2015 13:42:00 +0000 Subject: [PATCH 2844/3023] drm/i915: Insert a command barrier on BLT/BSD cache flushes This looked like an odd regression from commit ec5cc0f9b019af95e4571a9fa162d94294c8d90b Author: Chris Wilson Date: Thu Jun 12 10:28:55 2014 +0100 drm/i915: Restrict GPU boost to the RCS engine but in reality it undercovered a much older coherency bug. The issue that boosting the GPU frequency on the BCS ring was masking was that we could wake the CPU up after completion of a BCS batch and inspect memory prior to the write cache being fully evicted. In order to serialise the breadcrumb interrupt (and so ensure that the CPU's view of memory is coherent) we need to perform a post-sync operation in the MI_FLUSH_DW. v2: Fix all the MI_FLUSH_DW (bsd plus the duplication in execlists). Also fix the invalidate_domains mask in gen8_emit_flush() for ring != VCS. Testcase: gpuX-rcs-gpu-read-after-write Signed-off-by: Chris Wilson Cc: stable@vger.kernel.org Acked-by: Daniel Vetter Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_lrc.c | 20 +++++++++++--------- drivers/gpu/drm/i915/intel_ringbuffer.c | 23 +++++++++++++++++++---- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index a94346fee16027..0f358c5999ec8e 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1211,15 +1211,17 @@ static int gen8_emit_flush(struct intel_ringbuffer *ringbuf, cmd = MI_FLUSH_DW + 1; - if (ring == &dev_priv->ring[VCS]) { - if (invalidate_domains & I915_GEM_GPU_DOMAINS) - cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD | - MI_FLUSH_DW_STORE_INDEX | - MI_FLUSH_DW_OP_STOREDW; - } else { - if (invalidate_domains & I915_GEM_DOMAIN_RENDER) - cmd |= MI_INVALIDATE_TLB | MI_FLUSH_DW_STORE_INDEX | - MI_FLUSH_DW_OP_STOREDW; + /* We always require a command barrier so that subsequent + * commands, such as breadcrumb interrupts, are strictly ordered + * wrt the contents of the write cache being flushed to memory + * (and thus being coherent from the CPU). + */ + cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; + + if (invalidate_domains & I915_GEM_GPU_DOMAINS) { + cmd |= MI_INVALIDATE_TLB; + if (ring == &dev_priv->ring[VCS]) + cmd |= MI_INVALIDATE_BSD; } intel_logical_ring_emit(ringbuf, cmd); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 0bd3976d88e119..e5b3c6dbd46780 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -2240,6 +2240,14 @@ static int gen6_bsd_ring_flush(struct intel_engine_cs *ring, cmd = MI_FLUSH_DW; if (INTEL_INFO(ring->dev)->gen >= 8) cmd += 1; + + /* We always require a command barrier so that subsequent + * commands, such as breadcrumb interrupts, are strictly ordered + * wrt the contents of the write cache being flushed to memory + * (and thus being coherent from the CPU). + */ + cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; + /* * Bspec vol 1c.5 - video engine command streamer: * "If ENABLED, all TLBs will be invalidated once the flush @@ -2247,8 +2255,8 @@ static int gen6_bsd_ring_flush(struct intel_engine_cs *ring, * Post-Sync Operation field is a value of 1h or 3h." */ if (invalidate & I915_GEM_GPU_DOMAINS) - cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD | - MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; + cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD; + intel_ring_emit(ring, cmd); intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); if (INTEL_INFO(ring->dev)->gen >= 8) { @@ -2344,6 +2352,14 @@ static int gen6_ring_flush(struct intel_engine_cs *ring, cmd = MI_FLUSH_DW; if (INTEL_INFO(ring->dev)->gen >= 8) cmd += 1; + + /* We always require a command barrier so that subsequent + * commands, such as breadcrumb interrupts, are strictly ordered + * wrt the contents of the write cache being flushed to memory + * (and thus being coherent from the CPU). + */ + cmd |= MI_FLUSH_DW_STORE_INDEX | MI_FLUSH_DW_OP_STOREDW; + /* * Bspec vol 1c.3 - blitter engine command streamer: * "If ENABLED, all TLBs will be invalidated once the flush @@ -2351,8 +2367,7 @@ static int gen6_ring_flush(struct intel_engine_cs *ring, * Post-Sync Operation field is a value of 1h or 3h." */ if (invalidate & I915_GEM_DOMAIN_RENDER) - cmd |= MI_INVALIDATE_TLB | MI_FLUSH_DW_STORE_INDEX | - MI_FLUSH_DW_OP_STOREDW; + cmd |= MI_INVALIDATE_TLB; intel_ring_emit(ring, cmd); intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); if (INTEL_INFO(ring->dev)->gen >= 8) { From 4ba7d93afee0a2ddef7598f460927d39f33fe98b Mon Sep 17 00:00:00 2001 From: Shobhit Kumar Date: Thu, 5 Feb 2015 17:08:45 +0530 Subject: [PATCH 2845/3023] drm/i915: Correct the base value while updating LP_OUTPUT_HOLD in MIPI_PORT_CTRL LP_OUTPUT_HOLD is only in MIPI_PORT_CTRL(PORT_A) even for PORT_C in case of dual link. In the dual link implementation, the bit is correctly set or unset for hardcoded PORT_A, but for bit update the register base value is read by using MIPI_PORT_CTRL(port) in a loop. The second iteration will read base value from PORT_C and program for PORT_A. Mostly in case of dual link all other bit values should be same, but logically we should read from PORT_A. So hardcode to read initial value from PORT_A as well. Signed-off-by: Shobhit Kumar Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_dsi.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index ef3df5e3d819fc..10ab68457ca885 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -360,12 +360,11 @@ static void intel_dsi_device_ready(struct intel_encoder *encoder) I915_WRITE(MIPI_DEVICE_READY(port), ULPS_STATE_ENTER); usleep_range(2500, 3000); - val = I915_READ(MIPI_PORT_CTRL(port)); - /* Enable MIPI PHY transparent latch * Common bit for both MIPI Port A & MIPI Port C * No similar bit in MIPI Port C reg */ + val = I915_READ(MIPI_PORT_CTRL(PORT_A)); I915_WRITE(MIPI_PORT_CTRL(PORT_A), val | LP_OUTPUT_HOLD); usleep_range(1000, 1500); @@ -543,10 +542,10 @@ static void intel_dsi_clear_device_ready(struct intel_encoder *encoder) == 0x00000), 30)) DRM_ERROR("DSI LP not going Low\n"); - val = I915_READ(MIPI_PORT_CTRL(port)); /* Disable MIPI PHY transparent latch * Common bit for both MIPI Port A & MIPI Port C */ + val = I915_READ(MIPI_PORT_CTRL(PORT_A)); I915_WRITE(MIPI_PORT_CTRL(PORT_A), val & ~LP_OUTPUT_HOLD); usleep_range(1000, 1500); From ee7e38e3d8805ba6471bddd088fae92ce5ab1ef5 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Mon, 9 Feb 2015 23:39:45 -0500 Subject: [PATCH 2846/3023] tools/power turbostat: Skip printing disabled package C-states Replaced previously open-coded Package C-state Limit decoding with table-driven decoding. In doing so, updated to match January 2015 "Intel(R) 64 and IA-23 Architectures Software Developer's Manual". In the past, turbostat would print package C-state residency columns for all package states supported by the model's architecture, even though a particular SKU may not support them, or they may be disabled by the BIOS. Now turbostat will skip printing colunns if MSRs indicate that they are not enabled. eg. many SKUs don't support PC7, and so that column will no longer be printed. Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 188 ++++++++++++++++---------- 1 file changed, 116 insertions(+), 72 deletions(-) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index a02c02f25e88a2..ba8846b309f7c7 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -53,6 +53,10 @@ unsigned int skip_c0; unsigned int skip_c1; unsigned int do_nhm_cstates; unsigned int do_snb_cstates; +unsigned int do_pc2; +unsigned int do_pc3; +unsigned int do_pc6; +unsigned int do_pc7; unsigned int do_c8_c9_c10; unsigned int do_slm_cstates; unsigned int use_c1_residency_msr; @@ -313,13 +317,13 @@ void print_header(void) if (do_ptm) outp += sprintf(outp, " PkgTmp"); - if (do_snb_cstates) + if (do_pc2) outp += sprintf(outp, " Pkg%%pc2"); - if (do_nhm_cstates && !do_slm_cstates) + if (do_pc3) outp += sprintf(outp, " Pkg%%pc3"); - if (do_nhm_cstates && !do_slm_cstates) + if (do_pc6) outp += sprintf(outp, " Pkg%%pc6"); - if (do_snb_cstates) + if (do_pc7) outp += sprintf(outp, " Pkg%%pc7"); if (do_c8_c9_c10) { outp += sprintf(outp, " Pkg%%pc8"); @@ -394,9 +398,12 @@ int dump_counters(struct thread_data *t, struct core_data *c, if (p) { outp += sprintf(outp, "package: %d\n", p->package_id); outp += sprintf(outp, "pc2: %016llX\n", p->pc2); - outp += sprintf(outp, "pc3: %016llX\n", p->pc3); - outp += sprintf(outp, "pc6: %016llX\n", p->pc6); - outp += sprintf(outp, "pc7: %016llX\n", p->pc7); + if (do_pc3) + outp += sprintf(outp, "pc3: %016llX\n", p->pc3); + if (do_pc6) + outp += sprintf(outp, "pc6: %016llX\n", p->pc6); + if (do_pc7) + outp += sprintf(outp, "pc7: %016llX\n", p->pc7); outp += sprintf(outp, "pc8: %016llX\n", p->pc8); outp += sprintf(outp, "pc9: %016llX\n", p->pc9); outp += sprintf(outp, "pc10: %016llX\n", p->pc10); @@ -528,13 +535,13 @@ int format_counters(struct thread_data *t, struct core_data *c, if (do_ptm) outp += sprintf(outp, "%8d", p->pkg_temp_c); - if (do_snb_cstates) + if (do_pc2) outp += sprintf(outp, "%8.2f", 100.0 * p->pc2/t->tsc); - if (do_nhm_cstates && !do_slm_cstates) + if (do_pc3) outp += sprintf(outp, "%8.2f", 100.0 * p->pc3/t->tsc); - if (do_nhm_cstates && !do_slm_cstates) + if (do_pc6) outp += sprintf(outp, "%8.2f", 100.0 * p->pc6/t->tsc); - if (do_snb_cstates) + if (do_pc7) outp += sprintf(outp, "%8.2f", 100.0 * p->pc7/t->tsc); if (do_c8_c9_c10) { outp += sprintf(outp, "%8.2f", 100.0 * p->pc8/t->tsc); @@ -631,9 +638,12 @@ void delta_package(struct pkg_data *new, struct pkg_data *old) { old->pc2 = new->pc2 - old->pc2; - old->pc3 = new->pc3 - old->pc3; - old->pc6 = new->pc6 - old->pc6; - old->pc7 = new->pc7 - old->pc7; + if (do_pc3) + old->pc3 = new->pc3 - old->pc3; + if (do_pc6) + old->pc6 = new->pc6 - old->pc6; + if (do_pc7) + old->pc7 = new->pc7 - old->pc7; old->pc8 = new->pc8 - old->pc8; old->pc9 = new->pc9 - old->pc9; old->pc10 = new->pc10 - old->pc10; @@ -774,9 +784,12 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data c->core_temp_c = 0; p->pc2 = 0; - p->pc3 = 0; - p->pc6 = 0; - p->pc7 = 0; + if (do_pc3) + p->pc3 = 0; + if (do_pc6) + p->pc6 = 0; + if (do_pc7) + p->pc7 = 0; p->pc8 = 0; p->pc9 = 0; p->pc10 = 0; @@ -815,9 +828,12 @@ int sum_counters(struct thread_data *t, struct core_data *c, return 0; average.packages.pc2 += p->pc2; - average.packages.pc3 += p->pc3; - average.packages.pc6 += p->pc6; - average.packages.pc7 += p->pc7; + if (do_pc3) + average.packages.pc3 += p->pc3; + if (do_pc6) + average.packages.pc6 += p->pc6; + if (do_pc7) + average.packages.pc7 += p->pc7; average.packages.pc8 += p->pc8; average.packages.pc9 += p->pc9; average.packages.pc10 += p->pc10; @@ -859,9 +875,12 @@ void compute_average(struct thread_data *t, struct core_data *c, average.cores.c7 /= topo.num_cores; average.packages.pc2 /= topo.num_packages; - average.packages.pc3 /= topo.num_packages; - average.packages.pc6 /= topo.num_packages; - average.packages.pc7 /= topo.num_packages; + if (do_pc3) + average.packages.pc3 /= topo.num_packages; + if (do_pc6) + average.packages.pc6 /= topo.num_packages; + if (do_pc7) + average.packages.pc7 /= topo.num_packages; average.packages.pc8 /= topo.num_packages; average.packages.pc9 /= topo.num_packages; @@ -961,18 +980,18 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) return 0; - if (do_nhm_cstates && !do_slm_cstates) { + if (do_pc3) if (get_msr(cpu, MSR_PKG_C3_RESIDENCY, &p->pc3)) return -9; + if (do_pc6) if (get_msr(cpu, MSR_PKG_C6_RESIDENCY, &p->pc6)) return -10; - } - if (do_snb_cstates) { + if (do_pc2) if (get_msr(cpu, MSR_PKG_C2_RESIDENCY, &p->pc2)) return -11; + if (do_pc7) if (get_msr(cpu, MSR_PKG_C7_RESIDENCY, &p->pc7)) return -12; - } if (do_c8_c9_c10) { if (get_msr(cpu, MSR_PKG_C8_RESIDENCY, &p->pc8)) return -13; @@ -1019,6 +1038,37 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) return 0; } +/* + * MSR_PKG_CST_CONFIG_CONTROL decoding for pkg_cstate_limit: + * If you change the values, note they are used both in comparisons + * (>= PCL__7) and to index pkg_cstate_limit_strings[]. + */ + +#define PCLUKN 0 /* Unknown */ +#define PCLRSV 1 /* Reserved */ +#define PCL__0 2 /* PC0 */ +#define PCL__1 3 /* PC1 */ +#define PCL__2 4 /* PC2 */ +#define PCL__3 5 /* PC3 */ +#define PCL__4 6 /* PC4 */ +#define PCL__6 7 /* PC6 */ +#define PCL_6N 8 /* PC6 No Retention */ +#define PCL_6R 9 /* PC6 Retention */ +#define PCL__7 10 /* PC7 */ +#define PCL_7S 11 /* PC7 Shrink */ +#define PCLUNL 12 /* Unlimited */ + +int pkg_cstate_limit = PCLUKN; +char *pkg_cstate_limit_strings[] = { "reserved", "unknown", "pc0", "pc1", "pc2", + "pc3", "pc4", "pc6", "pc6n", "pc6r", "pc7", "pc7s", "unlimited"}; + +int nhm_pkg_cstate_limits[8] = {PCL__0, PCL__1, PCL__3, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLUNL}; +int snb_pkg_cstate_limits[8] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCL__7, PCL_7S, PCLRSV, PCLUNL}; +int hsw_pkg_cstate_limits[8] = {PCL__0, PCL__2, PCL__3, PCL__6, PCL__7, PCL_7S, PCLRSV, PCLUNL}; +int slv_pkg_cstate_limits[8] = {PCL__0, PCL__1, PCLRSV, PCLRSV, PCL__4, PCLRSV, PCL__6, PCL__7}; +int amt_pkg_cstate_limits[8] = {PCL__0, PCL__1, PCL__2, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7}; +int phi_pkg_cstate_limits[8] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL}; + void print_verbose_header(void) { unsigned long long msr; @@ -1098,44 +1148,14 @@ void print_verbose_header(void) fprintf(stderr, "cpu0: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x%08llx", msr); - fprintf(stderr, " (%s%s%s%s%slocked: pkg-cstate-limit=%d: ", + fprintf(stderr, " (%s%s%s%s%slocked: pkg-cstate-limit=%d: %s)\n", (msr & SNB_C3_AUTO_UNDEMOTE) ? "UNdemote-C3, " : "", (msr & SNB_C1_AUTO_UNDEMOTE) ? "UNdemote-C1, " : "", (msr & NHM_C3_AUTO_DEMOTE) ? "demote-C3, " : "", (msr & NHM_C1_AUTO_DEMOTE) ? "demote-C1, " : "", (msr & (1 << 15)) ? "" : "UN", - (unsigned int)msr & 7); - - - switch(msr & 0x7) { - case 0: - fprintf(stderr, do_slm_cstates ? "no pkg states" : "pc0"); - break; - case 1: - fprintf(stderr, do_slm_cstates ? "no pkg states" : do_snb_cstates ? "pc2" : "pc0"); - break; - case 2: - fprintf(stderr, do_slm_cstates ? "invalid" : do_snb_cstates ? "pc6-noret" : "pc3"); - break; - case 3: - fprintf(stderr, do_slm_cstates ? "invalid" : "pc6"); - break; - case 4: - fprintf(stderr, do_slm_cstates ? "pc4" : "pc7"); - break; - case 5: - fprintf(stderr, do_slm_cstates ? "invalid" : do_snb_cstates ? "pc7s" : "invalid"); - break; - case 6: - fprintf(stderr, do_slm_cstates ? "pc6" : "invalid"); - break; - case 7: - fprintf(stderr, do_slm_cstates ? "pc7" : "unlimited"); - break; - default: - fprintf(stderr, "invalid"); - } - fprintf(stderr, ")\n"); + (unsigned int)msr & 7, + pkg_cstate_limit_strings[pkg_cstate_limit]); if (!do_nhm_turbo_ratio_limit) return; @@ -1516,9 +1536,14 @@ void check_permissions() * MSR_CORE_C3_RESIDENCY 0x000003fc * MSR_CORE_C6_RESIDENCY 0x000003fd * + * Side effect: + * sets global pkg_cstate_limit to decode MSR_NHM_SNB_PKG_CST_CFG_CTL */ -int has_nhm_msrs(unsigned int family, unsigned int model) +int probe_nhm_msrs(unsigned int family, unsigned int model) { + unsigned long long msr; + int *pkg_cstate_limits; + if (!genuine_intel) return 0; @@ -1531,31 +1556,46 @@ int has_nhm_msrs(unsigned int family, unsigned int model) case 0x1F: /* Core i7 and i5 Processor - Nehalem */ case 0x25: /* Westmere Client - Clarkdale, Arrandale */ case 0x2C: /* Westmere EP - Gulftown */ + case 0x2E: /* Nehalem-EX Xeon - Beckton */ + case 0x2F: /* Westmere-EX Xeon - Eagleton */ + pkg_cstate_limits = nhm_pkg_cstate_limits; + break; case 0x2A: /* SNB */ case 0x2D: /* SNB Xeon */ case 0x3A: /* IVB */ case 0x3E: /* IVB Xeon */ + pkg_cstate_limits = snb_pkg_cstate_limits; + break; case 0x3C: /* HSW */ case 0x3F: /* HSX */ case 0x45: /* HSW */ case 0x46: /* HSW */ - case 0x37: /* BYT */ - case 0x4D: /* AVN */ case 0x3D: /* BDW */ case 0x4F: /* BDX */ case 0x56: /* BDX-DE */ - case 0x2E: /* Nehalem-EX Xeon - Beckton */ - case 0x2F: /* Westmere-EX Xeon - Eagleton */ - return 1; + pkg_cstate_limits = hsw_pkg_cstate_limits; + break; + case 0x37: /* BYT */ + case 0x4D: /* AVN */ + pkg_cstate_limits = slv_pkg_cstate_limits; + break; + case 0x4C: /* AMT */ + pkg_cstate_limits = amt_pkg_cstate_limits; + break; + case 0x57: /* PHI */ + pkg_cstate_limits = phi_pkg_cstate_limits; + break; default: return 0; } + get_msr(0, MSR_NHM_SNB_PKG_CST_CFG_CTL, &msr); + + pkg_cstate_limit = pkg_cstate_limits[msr & 0x7]; + + return 1; } int has_nhm_turbo_ratio_limit(unsigned int family, unsigned int model) { - if (!has_nhm_msrs(family, model)) - return 0; - switch (model) { /* Nehalem compatible, but do not include turbo-ratio limit support */ case 0x2E: /* Nehalem-EX Xeon - Beckton */ @@ -2252,13 +2292,17 @@ void check_cpuid() do_ptm ? "" : "No ", has_epb ? "" : "No "); - do_nhm_platform_info = do_nhm_cstates = do_smi = has_nhm_msrs(family, model); + do_nhm_platform_info = do_nhm_cstates = do_smi = probe_nhm_msrs(family, model); do_snb_cstates = has_snb_msrs(family, model); + do_pc2 = do_snb_cstates && (pkg_cstate_limit >= PCL__2); + do_pc3 = (pkg_cstate_limit >= PCL__3); + do_pc6 = (pkg_cstate_limit >= PCL__6); + do_pc7 = do_snb_cstates && (pkg_cstate_limit >= PCL__7); do_c8_c9_c10 = has_hsw_msrs(family, model); do_slm_cstates = is_slm(family, model); bclk = discover_bclk(family, model); - do_nhm_turbo_ratio_limit = has_nhm_turbo_ratio_limit(family, model); + do_nhm_turbo_ratio_limit = do_nhm_platform_info && has_nhm_turbo_ratio_limit(family, model); do_ivt_turbo_ratio_limit = has_ivt_turbo_ratio_limit(family, model); rapl_probe(family, model); perf_limit_reasons_probe(family, model); @@ -2631,7 +2675,7 @@ int main(int argc, char **argv) cmdline(argc, argv); if (verbose) - fprintf(stderr, "turbostat v3.9 23-Jan, 2015" + fprintf(stderr, "turbostat v3.10 9-Feb, 2015" " - Len Brown \n"); turbostat_init(); From d8af6f5f0fca7c5271539dab0d75942ccf09d65c Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 10 Feb 2015 01:56:38 -0500 Subject: [PATCH 2847/3023] tools/power turbostat: update parameters, documentation Long format options added, though the short ones should still work. eg. the new "--Counter 0x10" is the same as the old "-C 0x10" Note this Incompatibility: Old: -v displayed verbose debug output New: -v and --version simpaly display version Additional parameters: -d and --debug display verbose debug output -h and --help display a help message Updated turbosat.8 man page accordingly. Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.8 | 68 ++++++----- tools/power/x86/turbostat/turbostat.c | 155 ++++++++++++++++---------- 2 files changed, 136 insertions(+), 87 deletions(-) diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8 index 9b950699e63d9d..feea7ad9500bbb 100644 --- a/tools/power/x86/turbostat/turbostat.8 +++ b/tools/power/x86/turbostat/turbostat.8 @@ -9,7 +9,7 @@ turbostat \- Report processor frequency and idle statistics .br .B turbostat .RB [ Options ] -.RB [ "\-i interval_sec" ] +.RB [ "\--interval seconds" ] .SH DESCRIPTION \fBturbostat \fP reports processor topology, frequency, idle power-state statistics, temperature and power on X86 processors. @@ -18,31 +18,41 @@ The first method is to supply a \fBcommand\fP, which is forked and statistics are printed upon its completion. The second method is to omit the command, -and turbodstat will print statistics every 5 seconds. -The 5-second interval can changed using the -i option. +and turbostat displays statistics every 5 seconds. +The 5-second interval can be changed using the --interval option. -Some information is not availalbe on older processors. +Some information is not available on older processors. .SS Options -The \fB-p\fP option limits output to the 1st thread in 1st core of each package. +\fB--Counter MSR#\fP shows the delta of the specified 64-bit MSR counter. .PP -The \fB-P\fP option limits output to the 1st thread in each Package. +\fB--counter MSR#\fP shows the delta of the specified 32-bit MSR counter. .PP -The \fB-S\fP option limits output to a 1-line System Summary for each interval. +\fB--Dump\fP displays the raw counter values. .PP -The \fB-v\fP option increases verbosity. +\fB--debug\fP displays additional system configuration information. Invoking this parameter +more than once may also enable internal turbostat debug information. .PP -The \fB-c MSR#\fP option includes the delta of the specified 32-bit MSR counter. +\fB--interval seconds\fP overrides the default 5-second measurement interval. .PP -The \fB-C MSR#\fP option includes the delta of the specified 64-bit MSR counter. +\fB--help\fP displays usage for the most common parameters. .PP -The \fB-m MSR#\fP option includes the the specified 32-bit MSR value. +\fB--Joules\fP displays energy in Joules, rather than dividing Joules by time to print power in Watts. .PP -The \fB-M MSR#\fP option includes the the specified 64-bit MSR value. +\fB--MSR MSR#\fP shows the specified 64-bit MSR value. .PP -The \fB-i interval_sec\fP option prints statistics every \fiinterval_sec\fP seconds. -The default is 5 seconds. +\fB--msr MSR#\fP shows the specified 32-bit MSR value. .PP -The \fBcommand\fP parameter forks \fBcommand\fP and upon its exit, +\fB--Package\fP limits output to the system summary plus the 1st thread in each Package. +.PP +\fB--processor\fP limits output to the system summary plus the 1st thread in each processor of each package. Ie. it skips hyper-threaded siblings. +.PP +\fB--Summary\fP limits output to a 1-line System Summary for each interval. +.PP +\fB--TCC temperature\fP sets the Thermal Control Circuit temperature for systems which do not export that value. This is used for making sense of the Digital Thermal Sensor outputs, as they return degrees Celsius below the TCC activation temperature. +.PP +\fB--version\fP displays the version. +.PP +The \fBcommand\fP parameter forks \fBcommand\fP, and upon its exit, displays the statistics gathered since it was forked. .PP .SH FIELD DESCRIPTIONS @@ -52,7 +62,7 @@ displays the statistics gathered since it was forked. \fBCPU\fP Linux CPU (logical processor) number. Note that multiple CPUs per core indicate support for Intel(R) Hyper-Threading Technology. \fBAVG_MHz\fP number of cycles executed divided by time elapsed. -\fB%Buzy\fP percent of the interval that the CPU retired instructions, aka. % of time in "C0" state. +\fB%Busy\fP percent of the interval that the CPU retired instructions, aka. % of time in "C0" state. \fBBzy_MHz\fP average clock rate while the CPU was busy (in "c0" state). \fBTSC_MHz\fP average MHz that the TSC ran during the entire interval. \fBCPU%c1, CPU%c3, CPU%c6, CPU%c7\fP show the percentage residency in hardware core idle states. @@ -68,7 +78,7 @@ Note that multiple CPUs per core indicate support for Intel(R) Hyper-Threading T .fi .PP .SH EXAMPLE -Without any parameters, turbostat prints out counters ever 5 seconds. +Without any parameters, turbostat displays statistics ever 5 seconds. (override interval with "-i sec" option, or specify a command for turbostat to fork). @@ -91,19 +101,19 @@ Subsequent rows show per-CPU statistics. 3 3 3 0.20 1596 3492 0 0.44 0.00 99.37 0.00 23 3 7 5 0.31 1596 3492 0 0.33 .fi -.SH VERBOSE EXAMPLE -The "-v" option adds verbosity to the output: +.SH DEBUG EXAMPLE +The "--debug" option prints additional system information before measurements: .nf -[root@ivy]# turbostat -v -turbostat v3.0 November 23, 2012 - Len Brown +turbostat version 4.0 10-Feb, 2015 - Len Brown CPUID(0): GenuineIntel 13 CPUID levels; family:model:stepping 0x6:3a:9 (6:58:9) CPUID(6): APERF, DTS, PTM, EPB -RAPL: 851 sec. Joule Counter Range +RAPL: 851 sec. Joule Counter Range, at 77 Watts cpu0: MSR_NHM_PLATFORM_INFO: 0x81010f0012300 16 * 100 = 1600 MHz max efficiency 35 * 100 = 3500 MHz TSC frequency -cpu0: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x1e008402 (UNdemote-C3, UNdemote-C1, demote-C3, demote-C1, locked: pkg-cstate-limit=2: pc6-noret) +cpu0: MSR_IA32_POWER_CTL: 0x0014005d (C1E auto-promotion: DISabled) +cpu0: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x1e008402 (UNdemote-C3, UNdemote-C1, demote-C3, demote-C1, locked: pkg-cstate-limit=2: pc6n) cpu0: MSR_NHM_TURBO_RATIO_LIMIT: 0x25262727 37 * 100 = 3700 MHz max turbo 4 active cores 38 * 100 = 3800 MHz max turbo 3 active cores @@ -112,9 +122,9 @@ cpu0: MSR_NHM_TURBO_RATIO_LIMIT: 0x25262727 cpu0: MSR_IA32_ENERGY_PERF_BIAS: 0x00000006 (balanced) cpu0: MSR_RAPL_POWER_UNIT: 0x000a1003 (0.125000 Watts, 0.000015 Joules, 0.000977 sec.) cpu0: MSR_PKG_POWER_INFO: 0x01e00268 (77 W TDP, RAPL 60 - 0 W, 0.000000 sec.) -cpu0: MSR_PKG_POWER_LIMIT: 0x830000148268 (UNlocked) +cpu0: MSR_PKG_POWER_LIMIT: 0x30000148268 (UNlocked) cpu0: PKG Limit #1: ENabled (77.000000 Watts, 1.000000 sec, clamp DISabled) -cpu0: PKG Limit #2: ENabled (96.000000 Watts, 0.000977* sec, clamp DISabled) +cpu0: PKG Limit #2: DISabled (96.000000 Watts, 0.000977* sec, clamp DISabled) cpu0: MSR_PP0_POLICY: 0 cpu0: MSR_PP0_POWER_LIMIT: 0x00000000 (UNlocked) cpu0: Cores Limit: DISabled (0.000000 Watts, 0.000977 sec, clamp DISabled) @@ -123,9 +133,9 @@ cpu0: MSR_PP1_POWER_LIMIT: 0x00000000 (UNlocked) cpu0: GFX Limit: DISabled (0.000000 Watts, 0.000977 sec, clamp DISabled) cpu0: MSR_IA32_TEMPERATURE_TARGET: 0x00691400 (105 C) cpu0: MSR_IA32_PACKAGE_THERM_STATUS: 0x884e0000 (27 C) -cpu0: MSR_IA32_THERM_STATUS: 0x88560000 (19 C +/- 1) -cpu1: MSR_IA32_THERM_STATUS: 0x88560000 (19 C +/- 1) -cpu2: MSR_IA32_THERM_STATUS: 0x88540000 (21 C +/- 1) +cpu0: MSR_IA32_THERM_STATUS: 0x88580000 (17 C +/- 1) +cpu1: MSR_IA32_THERM_STATUS: 0x885a0000 (15 C +/- 1) +cpu2: MSR_IA32_THERM_STATUS: 0x88570000 (18 C +/- 1) cpu3: MSR_IA32_THERM_STATUS: 0x884e0000 (27 C +/- 1) ... .fi @@ -195,7 +205,7 @@ in those kernels. AVG_MHz = APERF_delta/measurement_interval. This is the actual number of elapsed cycles divided by the entire sample interval -- -including idle time. Note that this calculation is resiliant +including idle time. Note that this calculation is resilient to systems lacking a non-stop TSC. TSC_MHz = TSC_delta/measurement_interval. diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index ba8846b309f7c7..3f5a9af34f471b 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -42,13 +43,11 @@ #include char *proc_stat = "/proc/stat"; -unsigned int interval_sec = 5; /* set with -i interval_sec */ -unsigned int verbose; /* set with -v */ -unsigned int rapl_verbose; /* set with -R */ -unsigned int rapl_joules; /* set with -J */ -unsigned int thermal_verbose; /* set with -T */ -unsigned int summary_only; /* set with -S */ -unsigned int dump_only; /* set with -s */ +unsigned int interval_sec = 5; +unsigned int debug; +unsigned int rapl_joules; +unsigned int summary_only; +unsigned int dump_only; unsigned int skip_c0; unsigned int skip_c1; unsigned int do_nhm_cstates; @@ -727,7 +726,7 @@ delta_thread(struct thread_data *new, struct thread_data *old, } if (old->mperf == 0) { - if (verbose > 1) fprintf(stderr, "cpu%d MPERF 0!\n", old->cpu_id); + if (debug > 1) fprintf(stderr, "cpu%d MPERF 0!\n", old->cpu_id); old->mperf = 1; /* divide by 0 protection */ } @@ -1847,7 +1846,7 @@ void rapl_probe(unsigned int family, unsigned int model) tdp = get_tdp(model); rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp; - if (verbose) + if (debug) fprintf(stderr, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp); return; @@ -1972,7 +1971,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) if (get_msr(cpu, MSR_RAPL_POWER_UNIT, &msr)) return -1; - if (verbose) { + if (debug) { fprintf(stderr, "cpu%d: MSR_RAPL_POWER_UNIT: 0x%08llx " "(%f Watts, %f Joules, %f sec.)\n", cpu, msr, rapl_power_units, rapl_energy_units, rapl_time_units); @@ -2029,7 +2028,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) print_power_limit_msr(cpu, msr, "DRAM Limit"); } if (do_rapl & RAPL_CORE_POLICY) { - if (verbose) { + if (debug) { if (get_msr(cpu, MSR_PP0_POLICY, &msr)) return -7; @@ -2037,7 +2036,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) } } if (do_rapl & RAPL_CORES) { - if (verbose) { + if (debug) { if (get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr)) return -9; @@ -2047,7 +2046,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) } } if (do_rapl & RAPL_GFX) { - if (verbose) { + if (debug) { if (get_msr(cpu, MSR_PP1_POLICY, &msr)) return -8; @@ -2208,7 +2207,7 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk target_c_local = (msr >> 16) & 0xFF; - if (verbose) + if (debug) fprintf(stderr, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n", cpu, msr, target_c_local); @@ -2238,7 +2237,7 @@ void check_cpuid() if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e) genuine_intel = 1; - if (verbose) + if (debug) fprintf(stderr, "CPUID(0): %.4s%.4s%.4s ", (char *)&ebx, (char *)&edx, (char *)&ecx); @@ -2249,7 +2248,7 @@ void check_cpuid() if (family == 6 || family == 0xf) model += ((fms >> 16) & 0xf) << 4; - if (verbose) + if (debug) fprintf(stderr, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n", max_level, family, model, stepping, family, model, stepping); @@ -2285,7 +2284,7 @@ void check_cpuid() do_ptm = eax & (1 << 6); has_epb = ecx & (1 << 3); - if (verbose) + if (debug) fprintf(stderr, "CPUID(6): %sAPERF, %sDTS, %sPTM, %sEPB\n", has_aperf ? "" : "No ", do_dts ? "" : "No ", @@ -2311,10 +2310,25 @@ void check_cpuid() } -void usage() +void help() { - errx(1, "%s: [-v][-R][-T][-p|-P|-S][-c MSR#][-C MSR#][-m MSR#][-M MSR#][-i interval_sec | command ...]\n", - progname); + fprintf(stderr, + "Usage: turbostat [OPTIONS][(--interval seconds) | COMMAND ...]\n" + "\n" + "Turbostat forks the specified COMMAND and prints statistics\n" + "when COMMAND completes.\n" + "If no COMMAND is specified, turbostat wakes every 5-seconds\n" + "to print statistics, until interrupted.\n" + "--debug run in \"debug\" mode\n" + "--interval sec Override default 5-second measurement interval\n" + "--help print this help message\n" + "--counter msr print 32-bit counter at address \"msr\"\n" + "--Counter msr print 64-bit Counter at address \"msr\"\n" + "--msr msr print 32-bit value at address \"msr\"\n" + "--MSR msr print 64-bit Value at address \"msr\"\n" + "--version print version information\n" + "\n" + "For more help, run \"man turbostat\"\n"); } @@ -2353,7 +2367,7 @@ void topology_probe() if (!summary_only && topo.num_cpus > 1) show_cpu = 1; - if (verbose > 1) + if (debug > 1) fprintf(stderr, "num_cpus %d max_cpu_num %d\n", topo.num_cpus, topo.max_cpu_num); cpus = calloc(1, (topo.max_cpu_num + 1) * sizeof(struct cpu_topology)); @@ -2388,7 +2402,7 @@ void topology_probe() int siblings; if (cpu_is_not_present(i)) { - if (verbose > 1) + if (debug > 1) fprintf(stderr, "cpu%d NOT PRESENT\n", i); continue; } @@ -2403,26 +2417,26 @@ void topology_probe() siblings = get_num_ht_siblings(i); if (siblings > max_siblings) max_siblings = siblings; - if (verbose > 1) + if (debug > 1) fprintf(stderr, "cpu %d pkg %d core %d\n", i, cpus[i].physical_package_id, cpus[i].core_id); } topo.num_cores_per_pkg = max_core_id + 1; - if (verbose > 1) + if (debug > 1) fprintf(stderr, "max_core_id %d, sizing for %d cores per package\n", max_core_id, topo.num_cores_per_pkg); if (!summary_only && topo.num_cores_per_pkg > 1) show_core = 1; topo.num_packages = max_package_id + 1; - if (verbose > 1) + if (debug > 1) fprintf(stderr, "max_package_id %d, sizing for %d packages\n", max_package_id, topo.num_packages); if (!summary_only && topo.num_packages > 1) show_pkg = 1; topo.num_threads_per_core = max_siblings; - if (verbose > 1) + if (debug > 1) fprintf(stderr, "max_siblings %d\n", max_siblings); free(cpus); @@ -2537,21 +2551,21 @@ void turbostat_init() setup_all_buffers(); - if (verbose) + if (debug) print_verbose_header(); - if (verbose) + if (debug) for_all_cpus(print_epb, ODD_COUNTERS); - if (verbose) + if (debug) for_all_cpus(print_perf_limit, ODD_COUNTERS); - if (verbose) + if (debug) for_all_cpus(print_rapl, ODD_COUNTERS); for_all_cpus(set_temperature_target, ODD_COUNTERS); - if (verbose) + if (debug) for_all_cpus(print_thermal, ODD_COUNTERS); } @@ -2616,56 +2630,82 @@ int get_and_dump_counters(void) return status; } +void print_version() { + fprintf(stderr, "turbostat version 4.0 10-Feb, 2015" + " - Len Brown \n"); +} + void cmdline(int argc, char **argv) { int opt; + int option_index = 0; + static struct option long_options[] = { + {"Counter", required_argument, 0, 'C'}, + {"counter", required_argument, 0, 'c'}, + {"Dump", no_argument, 0, 'D'}, + {"debug", no_argument, 0, 'd'}, + {"interval", required_argument, 0, 'i'}, + {"help", no_argument, 0, 'h'}, + {"Joules", no_argument, 0, 'J'}, + {"MSR", required_argument, 0, 'M'}, + {"msr", required_argument, 0, 'm'}, + {"Package", no_argument, 0, 'p'}, + {"processor", no_argument, 0, 'p'}, + {"Summary", no_argument, 0, 'S'}, + {"TCC", required_argument, 0, 'T'}, + {"version", no_argument, 0, 'v' }, + {0, 0, 0, 0 } + }; progname = argv[0]; - while ((opt = getopt(argc, argv, "+pPsSvi:c:C:m:M:RJT:")) != -1) { + while ((opt = getopt_long_only(argc, argv, "C:c:Ddhi:JM:m:PpST:v", + long_options, &option_index)) != -1) { switch (opt) { - case 'p': - show_core_only++; + case 'C': + sscanf(optarg, "%x", &extra_delta_offset64); break; - case 'P': - show_pkg_only++; + case 'c': + sscanf(optarg, "%x", &extra_delta_offset32); break; - case 's': + case 'D': dump_only++; break; - case 'S': - summary_only++; - break; - case 'v': - verbose++; + case 'd': + debug++; break; + case 'h': + default: + help(); + exit(1); case 'i': interval_sec = atoi(optarg); break; - case 'c': - sscanf(optarg, "%x", &extra_delta_offset32); + case 'J': + rapl_joules++; break; - case 'C': - sscanf(optarg, "%x", &extra_delta_offset64); + case 'M': + sscanf(optarg, "%x", &extra_msr_offset64); break; case 'm': sscanf(optarg, "%x", &extra_msr_offset32); break; - case 'M': - sscanf(optarg, "%x", &extra_msr_offset64); + case 'P': + show_pkg_only++; + break; + case 'p': + show_core_only++; break; - case 'R': - rapl_verbose++; + case 'S': + summary_only++; break; case 'T': tcc_activation_temp_override = atoi(optarg); break; - case 'J': - rapl_joules++; + case 'v': + print_version(); + exit(0); break; - - default: - usage(); } } } @@ -2674,9 +2714,8 @@ int main(int argc, char **argv) { cmdline(argc, argv); - if (verbose) - fprintf(stderr, "turbostat v3.10 9-Feb, 2015" - " - Len Brown \n"); + if (debug) + print_version(); turbostat_init(); From dab2087defcb4afb2a5574d268b87257ba0f6b22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radim=20Kr=C4=8Dm=C3=A1=C5=99?= Date: Mon, 9 Feb 2015 22:44:07 +0100 Subject: [PATCH 2848/3023] KVM: x86: fix build with !CONFIG_SMP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit isn't included directly and without CONFIG_SMP, an option that automagically pulls it can't be enabled. Reported-by: Jim Davis Signed-off-by: Radim KrÄmář Signed-off-by: Paolo Bonzini --- arch/x86/kvm/vmx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 6e112472b0b3ff..3f73bfad0349e7 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -45,6 +45,7 @@ #include #include #include +#include #include "trace.h" From 6557bada461afeaa920a189fae2cff7c8fdce39f Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 9 Feb 2015 14:24:47 -0500 Subject: [PATCH 2849/3023] KVM: ia64: drop kvm.h from installed user headers The header was deleted, so stop trying to install it. Signed-off-by: Mike Frysinger Signed-off-by: Paolo Bonzini --- arch/ia64/include/uapi/asm/Kbuild | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/ia64/include/uapi/asm/Kbuild b/arch/ia64/include/uapi/asm/Kbuild index 1b3f5eb5fcdb45..891002bbb995be 100644 --- a/arch/ia64/include/uapi/asm/Kbuild +++ b/arch/ia64/include/uapi/asm/Kbuild @@ -18,7 +18,6 @@ header-y += intrinsics.h header-y += ioctl.h header-y += ioctls.h header-y += ipcbuf.h -header-y += kvm.h header-y += kvm_para.h header-y += mman.h header-y += msgbuf.h From 88cff0f0fbcf64cb6c2fbad6cf57e2725475d0ee Mon Sep 17 00:00:00 2001 From: hujianyang Date: Tue, 10 Feb 2015 11:28:57 +0800 Subject: [PATCH 2850/3023] UBIFS: return -EINVAL if log head is empty CS node is recognized as a sign in UBIFS log replay mechanism. Log relaying during mount should find the CS node in log head at beginning and then replay the following uncommitted buds. Here is a bug in log replay path: If the log head, which is indicated by @log_lnum in mst_node, is empty, current UBIFS replay nothing and directly mount the partition without any warning. This action will put filesystem in an abnormal state, e.g. space management in LPT area is incorrect to the real space usage in main area. We reproduced this bug by fault injection: turn log head leb into all 0xFF. UBIFS driver mount the polluted partition normally. But errors occur while running fs_stress on this mount: [89068.055183] UBI error: ubi_io_read: error -74 (ECC error) while reading 59 bytes from PEB 711:33088, read 59 bytes [89068.179877] UBIFS error (pid 10517): ubifs_check_node: bad magic 0x101031, expected 0x6101831 [89068.179882] UBIFS error (pid 10517): ubifs_check_node: bad node at LEB 591:28992 [89068.179891] Not a node, first 24 bytes: [89068.179892] 00000000: 31 10 10 00 37 84 64 04 10 04 00 00 00 00 00 00 20 00 00 00 02 01 00 00 1...7.d......... ....... [89068.180282] UBIFS error (pid 10517): ubifs_read_node: expected node type 2 This patch fix the problem by checking *lnum* to guarantee the empty leb is not log head leb and return an error if the log head leb is incorrectly empty. After this, we could catch *log head empty* error in place. Signed-off-by: hujianyang Signed-off-by: Artem Bityutskiy --- fs/ubifs/replay.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c index 3187925e9879b2..9b40a1c5e160f4 100644 --- a/fs/ubifs/replay.c +++ b/fs/ubifs/replay.c @@ -1028,9 +1028,22 @@ int ubifs_replay_journal(struct ubifs_info *c) do { err = replay_log_leb(c, lnum, 0, c->sbuf); - if (err == 1) - /* We hit the end of the log */ - break; + if (err == 1) { + if (lnum != c->lhead_lnum) + /* We hit the end of the log */ + break; + + /* + * The head of the log must always start with the + * "commit start" node on a properly formatted UBIFS. + * But we found no nodes at all, which means that + * someting went wrong and we cannot proceed mounting + * the file-system. + */ + ubifs_err("no UBIFS nodes found at the log head LEB %d:%d, possibly corrupted", + lnum, 0); + err = -EINVAL; + } if (err) goto out; lnum = ubifs_next_log_lnum(c, lnum); From bea57077e44ec9c1e6d3a3c142c8a3c0289e290d Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 10 Feb 2015 15:42:03 -0500 Subject: [PATCH 2851/3023] intel_idle: support additional Broadwell model Signed-off-by: Len Brown --- drivers/idle/intel_idle.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 9cceacb92f9d38..1bc0c170f12a75 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -727,6 +727,7 @@ static const struct x86_cpu_id intel_idle_ids[] = { ICPU(0x46, idle_cpu_hsw), ICPU(0x4d, idle_cpu_avn), ICPU(0x3d, idle_cpu_bdw), + ICPU(0x47, idle_cpu_bdw), ICPU(0x4f, idle_cpu_bdw), ICPU(0x56, idle_cpu_bdw), {} From 48a0631c891ab581cc010b44655ad49ff6eb3325 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 10 Feb 2015 15:38:04 -0500 Subject: [PATCH 2852/3023] tools/power turbostat: support additional Broadwell model Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 3f5a9af34f471b..2d089cac8580b8 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -1570,6 +1570,7 @@ int probe_nhm_msrs(unsigned int family, unsigned int model) case 0x45: /* HSW */ case 0x46: /* HSW */ case 0x3D: /* BDW */ + case 0x47: /* BDW */ case 0x4F: /* BDX */ case 0x56: /* BDX-DE */ pkg_cstate_limits = hsw_pkg_cstate_limits; @@ -1808,6 +1809,7 @@ void rapl_probe(unsigned int family, unsigned int model) case 0x45: /* HSW */ case 0x46: /* HSW */ case 0x3D: /* BDW */ + case 0x47: /* BDW */ do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_GFX | RAPL_PKG_POWER_INFO; break; case 0x3F: /* HSX */ @@ -2085,6 +2087,7 @@ int has_snb_msrs(unsigned int family, unsigned int model) case 0x45: /* HSW */ case 0x46: /* HSW */ case 0x3D: /* BDW */ + case 0x47: /* BDW */ case 0x4F: /* BDX */ case 0x56: /* BDX-DE */ return 1; @@ -2631,7 +2634,7 @@ int get_and_dump_counters(void) } void print_version() { - fprintf(stderr, "turbostat version 4.0 10-Feb, 2015" + fprintf(stderr, "turbostat version 4.1 10-Feb, 2015" " - Len Brown \n"); } From d64810f56147b53e92228c31442e925576314aa2 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 11 Feb 2015 15:01:13 +1030 Subject: [PATCH 2853/3023] module: Annotate nested sleep in resolve_symbol() Because wait_event() loops are safe vs spurious wakeups we can allow the occasional sleep -- which ends up being very similar. Reported-by: Dave Jones Signed-off-by: Peter Zijlstra (Intel) Tested-by: Dave Jones Signed-off-by: Rusty Russell --- kernel/module.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel/module.c b/kernel/module.c index 2461370813b31e..d7a92682fba366 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1225,6 +1225,12 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod, const unsigned long *crc; int err; + /* + * The module_mutex should not be a heavily contended lock; + * if we get the occasional sleep here, we'll go an extra iteration + * in the wait_event_interruptible(), which is harmless. + */ + sched_annotate_sleep(); mutex_lock(&module_mutex); sym = find_symbol(name, &owner, &crc, !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true); From 9cc019b8c94fa59e02fd82f15f7b7d689e35c190 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 11 Feb 2015 15:01:13 +1030 Subject: [PATCH 2854/3023] module: Replace over-engineered nested sleep Since the introduction of the nested sleep warning; we've established that the occasional sleep inside a wait_event() is fine. wait_event() loops are invariant wrt. spurious wakeups, and the occasional sleep has a similar effect on them. As long as its occasional its harmless. Therefore replace the 'correct' but verbose wait_woken() thing with a simple annotation to shut up the warning. Signed-off-by: Peter Zijlstra (Intel) Signed-off-by: Rusty Russell --- kernel/module.c | 36 ++++++++---------------------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/kernel/module.c b/kernel/module.c index d7a92682fba366..82dc1f899e6db9 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2984,6 +2984,12 @@ static bool finished_loading(const char *name) struct module *mod; bool ret; + /* + * The module_mutex should not be a heavily contended lock; + * if we get the occasional sleep here, we'll go an extra iteration + * in the wait_event_interruptible(), which is harmless. + */ + sched_annotate_sleep(); mutex_lock(&module_mutex); mod = find_module_all(name, strlen(name), true); ret = !mod || mod->state == MODULE_STATE_LIVE @@ -3125,32 +3131,6 @@ static int may_init_module(void) return 0; } -/* - * Can't use wait_event_interruptible() because our condition - * 'finished_loading()' contains a blocking primitive itself (mutex_lock). - */ -static int wait_finished_loading(struct module *mod) -{ - DEFINE_WAIT_FUNC(wait, woken_wake_function); - int ret = 0; - - add_wait_queue(&module_wq, &wait); - for (;;) { - if (finished_loading(mod->name)) - break; - - if (signal_pending(current)) { - ret = -ERESTARTSYS; - break; - } - - wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); - } - remove_wait_queue(&module_wq, &wait); - - return ret; -} - /* * We try to place it in the list now to make sure it's unique before * we dedicate too many resources. In particular, temporary percpu @@ -3171,8 +3151,8 @@ static int add_unformed_module(struct module *mod) || old->state == MODULE_STATE_UNFORMED) { /* Wait in case it fails to load. */ mutex_unlock(&module_mutex); - - err = wait_finished_loading(mod); + err = wait_event_interruptible(module_wq, + finished_loading(mod->name)); if (err) goto out_unlocked; goto again; From 96976c3d9aff4e1387c30f6356ac01fa6f72ef46 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Date: Thu, 5 Feb 2015 21:24:04 +0530 Subject: [PATCH 2855/3023] drm/exynos: Add DECON driver This patch is based on exynos-drm-next branch of Inki Dae's tree at: git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git DECON(Display and Enhancement Controller) is the new IP in exynos7 SOC for generating video signals using pixel data. DECON driver can be used to drive 2 different interfaces on Exynos7: DECON-INT(video controller) and DECON-EXT(Mixer for HDMI) The existing FIMD driver code was used as a template to create DECON driver. Only DECON-INT is supported as of now, and DECON-EXT support will be added later. The current version of the driver supports video mode displays. Changelog v2: - Change config name, DRM_EXYNOS_DECON to DRM_EXYNOS7_DECON. Signed-off-by: Akshu Agrawal Signed-off-by: Ajay Kumar Signed-off-by: Inki Dae --- .../bindings/video/exynos7-decon.txt | 68 ++ drivers/gpu/drm/exynos/Kconfig | 13 +- drivers/gpu/drm/exynos/Makefile | 1 + drivers/gpu/drm/exynos/exynos7_drm_decon.c | 990 ++++++++++++++++++ drivers/gpu/drm/exynos/exynos_drm_drv.c | 4 + drivers/gpu/drm/exynos/exynos_drm_drv.h | 1 + include/video/exynos7_decon.h | 349 ++++++ 7 files changed, 1423 insertions(+), 3 deletions(-) create mode 100644 Documentation/devicetree/bindings/video/exynos7-decon.txt create mode 100644 drivers/gpu/drm/exynos/exynos7_drm_decon.c create mode 100644 include/video/exynos7_decon.h diff --git a/Documentation/devicetree/bindings/video/exynos7-decon.txt b/Documentation/devicetree/bindings/video/exynos7-decon.txt new file mode 100644 index 00000000000000..f5f9c8d4a55a8d --- /dev/null +++ b/Documentation/devicetree/bindings/video/exynos7-decon.txt @@ -0,0 +1,68 @@ +Device-Tree bindings for Samsung Exynos7 SoC display controller (DECON) + +DECON (Display and Enhancement Controller) is the Display Controller for the +Exynos7 series of SoCs which transfers the image data from a video memory +buffer to an external LCD interface. + +Required properties: +- compatible: value should be "samsung,exynos7-decon"; + +- reg: physical base address and length of the DECON registers set. + +- interrupt-parent: should be the phandle of the decon controller's + parent interrupt controller. + +- interrupts: should contain a list of all DECON IP block interrupts in the + order: FIFO Level, VSYNC, LCD_SYSTEM. The interrupt specifier + format depends on the interrupt controller used. + +- interrupt-names: should contain the interrupt names: "fifo", "vsync", + "lcd_sys", in the same order as they were listed in the interrupts + property. + +- pinctrl-0: pin control group to be used for this controller. + +- pinctrl-names: must contain a "default" entry. + +- clocks: must include clock specifiers corresponding to entries in the + clock-names property. + +- clock-names: list of clock names sorted in the same order as the clocks + property. Must contain "pclk_decon0", "aclk_decon0", + "decon0_eclk", "decon0_vclk". +- i80-if-timings: timing configuration for lcd i80 interface support. + +Optional Properties: +- samsung,power-domain: a phandle to DECON power domain node. +- display-timings: timing settings for DECON, as described in document [1]. + Can be used in case timings cannot be provided otherwise + or to override timings provided by the panel. + +[1]: Documentation/devicetree/bindings/video/display-timing.txt + +Example: + +SoC specific DT entry: + + decon@13930000 { + compatible = "samsung,exynos7-decon"; + interrupt-parent = <&combiner>; + reg = <0x13930000 0x1000>; + interrupt-names = "lcd_sys", "vsync", "fifo"; + interrupts = <0 188 0>, <0 189 0>, <0 190 0>; + clocks = <&clock_disp PCLK_DECON_INT>, + <&clock_disp ACLK_DECON_INT>, + <&clock_disp SCLK_DECON_INT_ECLK>, + <&clock_disp SCLK_DECON_INT_EXTCLKPLL>; + clock-names = "pclk_decon0", "aclk_decon0", "decon0_eclk", + "decon0_vclk"; + status = "disabled"; + }; + +Board specific DT entry: + + decon@13930000 { + pinctrl-0 = <&lcd_clk &pwm1_out>; + pinctrl-names = "default"; + status = "okay"; + }; diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 627aaa04776cb3..a5e74612100e4e 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -24,9 +24,16 @@ config DRM_EXYNOS_FIMD help Choose this option if you want to use Exynos FIMD for DRM. +config DRM_EXYNOS7_DECON + bool "Exynos DRM DECON" + depends on DRM_EXYNOS + select FB_MODE_HELPERS + help + Choose this option if you want to use Exynos DECON for DRM. + config DRM_EXYNOS_DPI bool "EXYNOS DRM parallel output support" - depends on DRM_EXYNOS_FIMD + depends on (DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON) select DRM_PANEL default n help @@ -34,7 +41,7 @@ config DRM_EXYNOS_DPI config DRM_EXYNOS_DSI bool "EXYNOS DRM MIPI-DSI driver support" - depends on DRM_EXYNOS_FIMD + depends on (DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON) select DRM_MIPI_DSI select DRM_PANEL default n @@ -43,7 +50,7 @@ config DRM_EXYNOS_DSI config DRM_EXYNOS_DP bool "EXYNOS DRM DP driver support" - depends on DRM_EXYNOS_FIMD && ARCH_EXYNOS && (DRM_PTN3460=n || DRM_PTN3460=y || DRM_PTN3460=DRM_EXYNOS) + depends on (DRM_EXYNOS_FIMD || DRM_EXYNOS7DECON) && ARCH_EXYNOS && (DRM_PTN3460=n || DRM_PTN3460=y || DRM_PTN3460=DRM_EXYNOS) default DRM_EXYNOS select DRM_PANEL help diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile index 0856891f9bbfaa..cc90679cfc061e 100644 --- a/drivers/gpu/drm/exynos/Makefile +++ b/drivers/gpu/drm/exynos/Makefile @@ -10,6 +10,7 @@ exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o \ exynosdrm-$(CONFIG_DRM_EXYNOS_IOMMU) += exynos_drm_iommu.o exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o +exynosdrm-$(CONFIG_DRM_EXYNOS7_DECON) += exynos7_drm_decon.o exynosdrm-$(CONFIG_DRM_EXYNOS_DPI) += exynos_drm_dpi.o exynosdrm-$(CONFIG_DRM_EXYNOS_DSI) += exynos_drm_dsi.o exynosdrm-$(CONFIG_DRM_EXYNOS_DP) += exynos_dp_core.o exynos_dp_reg.o diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c new file mode 100644 index 00000000000000..63f02e2380ae1a --- /dev/null +++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c @@ -0,0 +1,990 @@ +/* drivers/gpu/drm/exynos/exynos7_drm_decon.c + * + * Copyright (C) 2014 Samsung Electronics Co.Ltd + * Authors: + * Akshu Agarwal + * Ajay Kumar + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include