From bdb4a62bdedcd3b584a5d11a4992832b4b803282 Mon Sep 17 00:00:00 2001 From: BlackMesa123 Date: Tue, 23 Oct 2018 14:34:52 +0200 Subject: [PATCH] A530FXXU3BRI1 Signed-off-by: BlackMesa123 --- .../configs/exynos7885-jackpot2lte_defconfig | 6 +- .../configs/exynos7885-jackpotlte_defconfig | 6 +- .../exynos7885-jackpotltecan_defconfig | 6 +- .../exynos7885-jackpotltekor_defconfig | 6 +- drivers/ccic/ccic_sysfs.c | 41 +++ drivers/gpu/arm/tMIx/r9p0/mali_base_kernel.h | 14 + .../gpu/arm/tMIx/r9p0/mali_kbase_context.c | 6 + .../gpu/arm/tMIx/r9p0/mali_kbase_core_linux.c | 36 ++- drivers/gpu/arm/tMIx/r9p0/mali_kbase_defs.h | 15 ++ drivers/gpu/arm/tMIx/r9p0/mali_kbase_ioctl.h | 29 ++- drivers/gpu/arm/tMIx/r9p0/mali_kbase_mem.c | 244 +++++++++++++----- drivers/gpu/arm/tMIx/r9p0/mali_kbase_mem.h | 50 ++-- .../gpu/arm/tMIx/r9p0/mali_kbase_mem_linux.c | 197 +------------- .../gpu/arm/tMIx/r9p0/mali_kbase_mem_linux.h | 33 +++ .../gpu/arm/tMIx/r9p0/mali_kbase_mem_pool.c | 14 - .../gpu/arm/tMIx/r9p0/mali_kbase_softjobs.c | 18 ++ .../gud/gud-exynos7885/MobiCoreDriver/admin.c | 11 +- .../gud-exynos7885/MobiCoreDriver/build_tag.h | 2 +- .../gud-exynos7885/MobiCoreDriver/client.c | 20 +- .../gud-exynos7885/MobiCoreDriver/clientlib.c | 25 +- .../gud-exynos7885/MobiCoreDriver/fastcall.c | 94 ++++++- .../gud/gud-exynos7885/MobiCoreDriver/iwp.c | 10 +- .../gud-exynos7885/MobiCoreDriver/logging.c | 11 +- .../gud/gud-exynos7885/MobiCoreDriver/main.c | 50 +++- .../gud/gud-exynos7885/MobiCoreDriver/main.h | 9 +- .../gud/gud-exynos7885/MobiCoreDriver/mcp.c | 8 +- .../gud-exynos7885/MobiCoreDriver/scheduler.c | 7 +- .../gud-exynos7885/MobiCoreDriver/session.c | 22 +- .../MobiCoreDriver/teeclientapi.c | 16 +- .../gud/gud-exynos7885/MobiCoreDriver/user.c | 19 +- drivers/misc/samsung/scsc/mxman.c | 80 +++--- drivers/misc/samsung/scsc/mxproc.c | 14 +- .../misc/samsung/scsc/scsc_logring_debugfs.c | 2 +- drivers/misc/samsung/scsc/scsc_mx_module.c | 8 +- drivers/net/wireless/scsc/cfg80211_ops.c | 5 - drivers/net/wireless/scsc/dev.h | 1 + drivers/net/wireless/scsc/ioctl.c | 53 ++-- drivers/net/wireless/scsc/mgt.c | 69 +++-- drivers/net/wireless/scsc/mgt.h | 3 +- drivers/net/wireless/scsc/mlme.c | 64 ++++- drivers/net/wireless/scsc/nl80211_vendor.c | 5 +- drivers/net/wireless/scsc/rx.c | 20 +- drivers/net/wireless/scsc/sap_dbg.c | 2 +- drivers/usb/gadget/function/u_ether.c | 3 +- include/scsc/scsc_release.h | 1 + net/ipv4/inet_fragment.c | 10 +- net/ipv4/tcp_input.c | 19 +- 47 files changed, 859 insertions(+), 525 deletions(-) diff --git a/arch/arm64/configs/exynos7885-jackpot2lte_defconfig b/arch/arm64/configs/exynos7885-jackpot2lte_defconfig index c7183a12e30a..badcceca1751 100644 --- a/arch/arm64/configs/exynos7885-jackpot2lte_defconfig +++ b/arch/arm64/configs/exynos7885-jackpot2lte_defconfig @@ -4938,7 +4938,7 @@ CONFIG_CRYPTO_ABLK_HELPER=y # Authenticated Encryption with Associated Data # # CONFIG_CRYPTO_CCM is not set -# CONFIG_CRYPTO_GCM is not set +CONFIG_CRYPTO_GCM=y # CONFIG_CRYPTO_CHACHA20POLY1305 is not set CONFIG_CRYPTO_SEQIV=y CONFIG_CRYPTO_ECHAINIV=y @@ -4969,7 +4969,7 @@ CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_CRC32C=y # CONFIG_CRYPTO_CRC32 is not set # CONFIG_CRYPTO_CRCT10DIF is not set -# CONFIG_CRYPTO_GHASH is not set +CONFIG_CRYPTO_GHASH=y # CONFIG_CRYPTO_POLY1305 is not set # CONFIG_CRYPTO_MD4 is not set CONFIG_CRYPTO_MD5=y @@ -4980,7 +4980,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_SHA256=y -# CONFIG_CRYPTO_SHA512 is not set +CONFIG_CRYPTO_SHA512=y # CONFIG_CRYPTO_TGR192 is not set # CONFIG_CRYPTO_WP512 is not set diff --git a/arch/arm64/configs/exynos7885-jackpotlte_defconfig b/arch/arm64/configs/exynos7885-jackpotlte_defconfig index e832b68ec7e8..d48fefa05578 100644 --- a/arch/arm64/configs/exynos7885-jackpotlte_defconfig +++ b/arch/arm64/configs/exynos7885-jackpotlte_defconfig @@ -4938,7 +4938,7 @@ CONFIG_CRYPTO_ABLK_HELPER=y # Authenticated Encryption with Associated Data # # CONFIG_CRYPTO_CCM is not set -# CONFIG_CRYPTO_GCM is not set +CONFIG_CRYPTO_GCM=y # CONFIG_CRYPTO_CHACHA20POLY1305 is not set CONFIG_CRYPTO_SEQIV=y CONFIG_CRYPTO_ECHAINIV=y @@ -4969,7 +4969,7 @@ CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_CRC32C=y # CONFIG_CRYPTO_CRC32 is not set # CONFIG_CRYPTO_CRCT10DIF is not set -# CONFIG_CRYPTO_GHASH is not set +CONFIG_CRYPTO_GHASH=y # CONFIG_CRYPTO_POLY1305 is not set # CONFIG_CRYPTO_MD4 is not set CONFIG_CRYPTO_MD5=y @@ -4980,7 +4980,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_SHA256=y -# CONFIG_CRYPTO_SHA512 is not set +CONFIG_CRYPTO_SHA512=y # CONFIG_CRYPTO_TGR192 is not set # CONFIG_CRYPTO_WP512 is not set diff --git a/arch/arm64/configs/exynos7885-jackpotltecan_defconfig b/arch/arm64/configs/exynos7885-jackpotltecan_defconfig index 5e27e10b8240..2094b526ff76 100644 --- a/arch/arm64/configs/exynos7885-jackpotltecan_defconfig +++ b/arch/arm64/configs/exynos7885-jackpotltecan_defconfig @@ -4938,7 +4938,7 @@ CONFIG_CRYPTO_ABLK_HELPER=y # Authenticated Encryption with Associated Data # # CONFIG_CRYPTO_CCM is not set -# CONFIG_CRYPTO_GCM is not set +CONFIG_CRYPTO_GCM=y # CONFIG_CRYPTO_CHACHA20POLY1305 is not set CONFIG_CRYPTO_SEQIV=y CONFIG_CRYPTO_ECHAINIV=y @@ -4969,7 +4969,7 @@ CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_CRC32C=y # CONFIG_CRYPTO_CRC32 is not set # CONFIG_CRYPTO_CRCT10DIF is not set -# CONFIG_CRYPTO_GHASH is not set +CONFIG_CRYPTO_GHASH=y # CONFIG_CRYPTO_POLY1305 is not set # CONFIG_CRYPTO_MD4 is not set CONFIG_CRYPTO_MD5=y @@ -4980,7 +4980,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_SHA256=y -# CONFIG_CRYPTO_SHA512 is not set +CONFIG_CRYPTO_SHA512=y # CONFIG_CRYPTO_TGR192 is not set # CONFIG_CRYPTO_WP512 is not set diff --git a/arch/arm64/configs/exynos7885-jackpotltekor_defconfig b/arch/arm64/configs/exynos7885-jackpotltekor_defconfig index 9659bfeb1611..0129489bdcad 100755 --- a/arch/arm64/configs/exynos7885-jackpotltekor_defconfig +++ b/arch/arm64/configs/exynos7885-jackpotltekor_defconfig @@ -4955,7 +4955,7 @@ CONFIG_CRYPTO_ABLK_HELPER=y # Authenticated Encryption with Associated Data # # CONFIG_CRYPTO_CCM is not set -# CONFIG_CRYPTO_GCM is not set +CONFIG_CRYPTO_GCM=y # CONFIG_CRYPTO_CHACHA20POLY1305 is not set CONFIG_CRYPTO_SEQIV=y CONFIG_CRYPTO_ECHAINIV=y @@ -4986,7 +4986,7 @@ CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_CRC32C=y # CONFIG_CRYPTO_CRC32 is not set # CONFIG_CRYPTO_CRCT10DIF is not set -# CONFIG_CRYPTO_GHASH is not set +CONFIG_CRYPTO_GHASH=y # CONFIG_CRYPTO_POLY1305 is not set # CONFIG_CRYPTO_MD4 is not set CONFIG_CRYPTO_MD5=y @@ -4997,7 +4997,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_SHA256=y -# CONFIG_CRYPTO_SHA512 is not set +CONFIG_CRYPTO_SHA512=y # CONFIG_CRYPTO_TGR192 is not set # CONFIG_CRYPTO_WP512 is not set diff --git a/drivers/ccic/ccic_sysfs.c b/drivers/ccic/ccic_sysfs.c index 51ab1cad7d64..78839507656e 100644 --- a/drivers/ccic/ccic_sysfs.c +++ b/drivers/ccic/ccic_sysfs.c @@ -537,6 +537,46 @@ static ssize_t ccic_send_role_swap_message(struct device *dev, } static DEVICE_ATTR(role_swap, 0220, NULL, ccic_send_role_swap_message); #endif +static ssize_t ccic_acc_device_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ +#ifdef CONFIG_CCIC_S2MM005 + struct s2mm005_data *usbpd_data = dev_get_drvdata(dev); + + if (!usbpd_data) { + pr_err("%s usbpd_data is null!!\n", __func__); + return -ENODEV; + } + pr_info("%s 0x%04x\n", __func__, usbpd_data->Device_Version); + + return sprintf(buf, "%04x\n", usbpd_data->Device_Version); +#else + struct s2mu004_usbpd_data *pdic_data = dev_get_drvdata(dev); + struct usbpd_data *pd_data; + struct usbpd_manager_data *manager; + + if (!pdic_data) { + pr_err("%s s2mu004_data is null!!\n", __func__); + return -ENODEV; + } + + pd_data = dev_get_drvdata(pdic_data->dev); + if (!pd_data) { + pr_err("%s usbpd_data is null!!\n", __func__); + return -ENODEV; + } + + manager = &pd_data->manager; + if (!manager) { + pr_err("%s manager_data is null!!\n", __func__); + return -ENODEV; + } + pr_info("%s 0x%04x\n", __func__, manager->Device_Version); + + return sprintf(buf, "%04x\n", manager->Device_Version); +#endif +} +static DEVICE_ATTR(acc_device_version, 0444, ccic_acc_device_version_show,NULL); static ssize_t ccic_usbpd_ids_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -635,6 +675,7 @@ static struct attribute *ccic_attributes[] = { &dev_attr_attention.attr, &dev_attr_role_swap.attr, #endif + &dev_attr_acc_device_version.attr, &dev_attr_usbpd_ids.attr, &dev_attr_usbpd_type.attr, &dev_attr_water.attr, diff --git a/drivers/gpu/arm/tMIx/r9p0/mali_base_kernel.h b/drivers/gpu/arm/tMIx/r9p0/mali_base_kernel.h index 86046f7ac608..bb998dc1d110 100644 --- a/drivers/gpu/arm/tMIx/r9p0/mali_base_kernel.h +++ b/drivers/gpu/arm/tMIx/r9p0/mali_base_kernel.h @@ -411,6 +411,16 @@ struct base_mem_aliasing_info { * @id: Unique ID provided by the caller, this is used * to pair allocation and free requests. * Zero is not a valid value. + * @bin_id: The JIT allocation bin, used in conjunction with + * @max_allocations to limit the number of each + * type of JIT allocation. + * @max_allocations: The maximum number of allocations allowed within + * the bin specified by @bin_id. Should be the same + * for all JIT allocations within the same bin. + * @padding: Expansion space - should be initialised to zero + * @usage_id: A hint about which allocation should be reused. + * The kernel should attempt to use a previous + * allocation with the same usage_id */ struct base_jit_alloc_info { u64 gpu_alloc_addr; @@ -418,6 +428,10 @@ struct base_jit_alloc_info { u64 commit_pages; u64 extent; u8 id; + u8 bin_id; + u8 max_allocations; + u8 padding[3]; + u16 usage_id; }; /** diff --git a/drivers/gpu/arm/tMIx/r9p0/mali_kbase_context.c b/drivers/gpu/arm/tMIx/r9p0/mali_kbase_context.c index afaeacaca4a6..52c4b4b21a90 100644 --- a/drivers/gpu/arm/tMIx/r9p0/mali_kbase_context.c +++ b/drivers/gpu/arm/tMIx/r9p0/mali_kbase_context.c @@ -178,6 +178,10 @@ kbase_create_context(struct kbase_device *kbdev, bool is_compat) setup_timer(&kctx->soft_job_timeout, kbasep_soft_job_timeout_worker, (uintptr_t)kctx); + + get_task_struct(current); + kctx->task = current; + /* MALI_SEC_INTEGRATION */ if (kbdev->vendor_callbacks->create_context) kbdev->vendor_callbacks->create_context(kctx); @@ -353,6 +357,8 @@ void kbase_destroy_context(struct kbase_context *kctx) kbase_mem_pool_term(&kctx->lp_mem_pool); WARN_ON(atomic_read(&kctx->nonmapped_pages) != 0); + put_task_struct(kctx->task); + /* MALI_SEC_INTEGRATION */ if (kbdev->vendor_callbacks->destroy_context) kbdev->vendor_callbacks->destroy_context(kctx); diff --git a/drivers/gpu/arm/tMIx/r9p0/mali_kbase_core_linux.c b/drivers/gpu/arm/tMIx/r9p0/mali_kbase_core_linux.c index 8a2f2ed03c60..3c9131ea60c7 100644 --- a/drivers/gpu/arm/tMIx/r9p0/mali_kbase_core_linux.c +++ b/drivers/gpu/arm/tMIx/r9p0/mali_kbase_core_linux.c @@ -394,7 +394,7 @@ static int kbase_open(struct inode *inode, struct file *filp) } debugfs_create_file("infinite_cache", 0644, kctx->kctx_dentry, - kctx, &kbase_infinite_cache_fops); + kctx, &kbase_infinite_cache_fops); mutex_init(&kctx->mem_profile_lock); @@ -677,10 +677,37 @@ static int kbase_api_get_ddk_version(struct kbase_context *kctx, return len; } +/* Defaults for legacy JIT init ioctl */ +#define DEFAULT_MAX_JIT_ALLOCATIONS 255 +#define JIT_LEGACY_TRIM_LEVEL (0) /* No trimming */ + +static int kbase_api_mem_jit_init_old(struct kbase_context *kctx, + struct kbase_ioctl_mem_jit_init_old *jit_init) +{ + kctx->jit_version = 1; + + return kbase_region_tracker_init_jit(kctx, jit_init->va_pages, + DEFAULT_MAX_JIT_ALLOCATIONS, + JIT_LEGACY_TRIM_LEVEL); +} + static int kbase_api_mem_jit_init(struct kbase_context *kctx, struct kbase_ioctl_mem_jit_init *jit_init) { - return kbase_region_tracker_init_jit(kctx, jit_init->va_pages); + int i; + + kctx->jit_version = 2; + + for (i = 0; i < sizeof(jit_init->padding); i++) { + /* Ensure all padding bytes are 0 for potential future + * extension + */ + if (jit_init->padding[i]) + return -EINVAL; + } + + return kbase_region_tracker_init_jit(kctx, jit_init->va_pages, + jit_init->max_allocations, jit_init->trim_level); } static int kbase_api_mem_sync(struct kbase_context *kctx, @@ -1046,6 +1073,11 @@ static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) kbase_api_get_ddk_version, struct kbase_ioctl_get_ddk_version); break; + case KBASE_IOCTL_MEM_JIT_INIT_OLD: + KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_MEM_JIT_INIT_OLD, + kbase_api_mem_jit_init_old, + struct kbase_ioctl_mem_jit_init_old); + break; case KBASE_IOCTL_MEM_JIT_INIT: KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_MEM_JIT_INIT, kbase_api_mem_jit_init, diff --git a/drivers/gpu/arm/tMIx/r9p0/mali_kbase_defs.h b/drivers/gpu/arm/tMIx/r9p0/mali_kbase_defs.h index 156f25f51af2..9efd77c2b855 100644 --- a/drivers/gpu/arm/tMIx/r9p0/mali_kbase_defs.h +++ b/drivers/gpu/arm/tMIx/r9p0/mali_kbase_defs.h @@ -1431,6 +1431,7 @@ struct kbase_sub_alloc { struct kbase_context { struct file *filp; + struct task_struct *task; struct kbase_device *kbdev; u32 id; /* System wide unique id */ unsigned long api_version; @@ -1597,6 +1598,17 @@ struct kbase_context { /* JIT allocation management */ struct kbase_va_region *jit_alloc[256]; + /* Maximum number of JIT allocations allowed at once */ + u8 jit_max_allocations; + /* Current number of in-flight JIT allocations */ + u8 jit_current_allocations; + /* Current number of in-flight JIT allocations per bin */ + u8 jit_current_allocations_per_bin[256]; + /* JIT version number: + * 1: client used KBASE_IOCTL_MEM_JIT_INIT_OLD + * 2: client used KBASE_IOCTL_MEM_JIT_INIT + */ + u8 jit_version; struct list_head jit_active_head; struct list_head jit_pool_head; struct list_head jit_destroy_head; @@ -1620,6 +1632,9 @@ struct kbase_context { /* Current age count, used to determine age for newly submitted atoms */ u32 age_count; + + /* Level of JIT allocation trimming to perform on free (0 - 100%) */ + u8 trim_level; }; /** diff --git a/drivers/gpu/arm/tMIx/r9p0/mali_kbase_ioctl.h b/drivers/gpu/arm/tMIx/r9p0/mali_kbase_ioctl.h index 1b10c026eab1..3a06e71a9d05 100644 --- a/drivers/gpu/arm/tMIx/r9p0/mali_kbase_ioctl.h +++ b/drivers/gpu/arm/tMIx/r9p0/mali_kbase_ioctl.h @@ -33,8 +33,11 @@ extern "C" { #define KBASE_IOCTL_TYPE 0x80 +/* 11.1 introduced a new jit ioctl giving control over the maximum number of + * JIT allocations and trim level to be applied on free. + */ #define BASE_UK_VERSION_MAJOR 11 -#define BASE_UK_VERSION_MINOR 0 +#define BASE_UK_VERSION_MINOR 1 #ifdef ANDROID /* Android's definition of ioctl is incorrect, specifying the type argument as @@ -270,16 +273,40 @@ struct kbase_ioctl_get_ddk_version { #define KBASE_IOCTL_GET_DDK_VERSION \ _IOW(KBASE_IOCTL_TYPE, 13, struct kbase_ioctl_get_ddk_version) +/** + * struct kbase_ioctl_mem_jit_init_old - Initialise the JIT memory allocator + * + * @va_pages: Number of VA pages to reserve for JIT + * + * Note that depending on the VA size of the application and GPU, the value + * specified in @va_pages may be ignored. + * + * New code should use KBASE_IOCTL_MEM_JIT_INIT instead, this is kept for + * backwards compatibility. + */ +struct kbase_ioctl_mem_jit_init_old { + __u64 va_pages; +}; + +#define KBASE_IOCTL_MEM_JIT_INIT_OLD \ + _IOW(KBASE_IOCTL_TYPE, 14, struct kbase_ioctl_mem_jit_init_old) + /** * struct kbase_ioctl_mem_jit_init - Initialise the JIT memory allocator * * @va_pages: Number of VA pages to reserve for JIT + * @max_allocations: Maximum number of concurrent allocations + * @trim_level: Level of JIT allocation trimming to perform on free (0 - 100%) + * @padding: Currently unused, must be zero * * Note that depending on the VA size of the application and GPU, the value * specified in @va_pages may be ignored. */ struct kbase_ioctl_mem_jit_init { __u64 va_pages; + __u8 max_allocations; + __u8 trim_level; + __u8 padding[6]; }; #define KBASE_IOCTL_MEM_JIT_INIT \ diff --git a/drivers/gpu/arm/tMIx/r9p0/mali_kbase_mem.c b/drivers/gpu/arm/tMIx/r9p0/mali_kbase_mem.c index 6ebb89c66e77..c22b31880350 100644 --- a/drivers/gpu/arm/tMIx/r9p0/mali_kbase_mem.c +++ b/drivers/gpu/arm/tMIx/r9p0/mali_kbase_mem.c @@ -650,22 +650,17 @@ int kbase_region_tracker_init(struct kbase_context *kctx) return err; } -int kbase_region_tracker_init_jit(struct kbase_context *kctx, u64 jit_va_pages) -{ #ifdef CONFIG_64BIT +static int kbase_region_tracker_init_jit_64(struct kbase_context *kctx, + u64 jit_va_pages) +{ + struct kbase_va_region *same_va; struct kbase_va_region *custom_va_reg; u64 same_va_bits; u64 total_va_size; int err; - /* - * Nothing to do for 32-bit clients, JIT uses the existing - * custom VA zone. - */ - if (kbase_ctx_flag(kctx, KCTX_COMPAT)) - return 0; - #if defined(CONFIG_ARM64) same_va_bits = VA_BITS; #elif defined(CONFIG_X86_64) @@ -736,9 +731,27 @@ int kbase_region_tracker_init_jit(struct kbase_context *kctx, u64 jit_va_pages) fail_unlock: kbase_gpu_vm_unlock(kctx); return err; -#else - return 0; +} #endif + +int kbase_region_tracker_init_jit(struct kbase_context *kctx, u64 jit_va_pages, + u8 max_allocations, u8 trim_level) +{ + if (trim_level > 100) + return -EINVAL; + + kctx->jit_max_allocations = max_allocations; + kctx->trim_level = trim_level; + +#ifdef CONFIG_64BIT + if (!kbase_ctx_flag(kctx, KCTX_COMPAT)) + return kbase_region_tracker_init_jit_64(kctx, jit_va_pages); +#endif + /* + * Nothing to do for 32-bit clients, JIT uses the existing + * custom VA zone. + */ + return 0; } int kbase_mem_init(struct kbase_device *kbdev) @@ -836,6 +849,8 @@ struct kbase_va_region *kbase_alloc_free_region(struct kbase_context *kctx, u64 new_reg->start_pfn = start_pfn; new_reg->nr_pages = nr_pages; + INIT_LIST_HEAD(&new_reg->jit_node); + return new_reg; } @@ -1283,6 +1298,11 @@ int kbase_mem_free_region(struct kbase_context *kctx, struct kbase_va_region *re KBASE_DEBUG_ASSERT(NULL != reg); lockdep_assert_held(&kctx->reg_lock); + if (reg->flags & KBASE_REG_JIT) { + dev_warn(reg->kctx->kbdev->dev, "Attempt to free JIT memory!\n"); + return -EINVAL; + } + /* * Unlink the physical allocation before unmaking it evictable so * that the allocation isn't grown back to its last backed size @@ -1446,7 +1466,6 @@ int kbase_alloc_phy_pages_helper( size_t nr_pages_requested) { int new_page_count __maybe_unused; - size_t old_page_count = alloc->nents; size_t nr_left = nr_pages_requested; int res; struct kbase_context *kctx; @@ -1474,7 +1493,7 @@ int kbase_alloc_phy_pages_helper( * allocation is visible to the OOM killer */ kbase_process_page_usage_inc(kctx, nr_pages_requested); - tp = alloc->pages + old_page_count; + tp = alloc->pages + alloc->nents; #ifdef CONFIG_MALI_2MB_ALLOC /* Check if we have enough pages requested so we can allocate a large @@ -1584,15 +1603,6 @@ int kbase_alloc_phy_pages_helper( goto alloc_failed; } - /* - * Request a zone cache update, this scans only the new pages an - * appends their information to the zone cache. if the update - * fails then clear the cache so we fall-back to doing things - * page by page. - */ - if (kbase_zone_cache_update(alloc, old_page_count) != 0) - kbase_zone_cache_clear(alloc); - KBASE_TLSTREAM_AUX_PAGESALLOC( kctx->id, (u64)new_page_count); @@ -1606,7 +1616,7 @@ int kbase_alloc_phy_pages_helper( if (nr_left != nr_pages_requested) kbase_mem_pool_free_pages(&kctx->lp_mem_pool, nr_pages_requested - nr_left, - alloc->pages + old_page_count, + alloc->pages + alloc->nents, false, false); @@ -1671,15 +1681,6 @@ int kbase_free_phy_pages_helper( start_free++; } - /* - * Clear the zone cache, we don't expect JIT allocations to be - * shrunk in parts so there is no point trying to optimize for that - * by scanning for the changes caused by freeing this memory and - * updating the existing cache entries. - */ - kbase_zone_cache_clear(alloc); - - while (nr_pages_to_free) { if (is_huge_head(*start_free)) { /* This is a 2MB entry, so free all the 512 pages that @@ -2139,7 +2140,7 @@ static void kbase_jit_destroy_worker(struct work_struct *work) list_del(®->jit_node); mutex_unlock(&kctx->jit_evict_lock); - + reg->flags &= ~KBASE_REG_JIT; kbase_gpu_vm_lock(kctx); kbase_mem_free_region(kctx, reg); kbase_gpu_vm_unlock(kctx); @@ -2156,6 +2157,10 @@ int kbase_jit_init(struct kbase_context *kctx) INIT_LIST_HEAD(&kctx->jit_pending_alloc); INIT_LIST_HEAD(&kctx->jit_atoms_head); + kctx->jit_max_allocations = 0; + kctx->jit_current_allocations = 0; + kctx->trim_level = 0; + return 0; } @@ -2163,44 +2168,107 @@ struct kbase_va_region *kbase_jit_allocate(struct kbase_context *kctx, struct base_jit_alloc_info *info) { struct kbase_va_region *reg = NULL; - struct kbase_va_region *walker; - struct kbase_va_region *temp; - size_t current_diff = SIZE_MAX; int ret; + if (kctx->jit_current_allocations >= kctx->jit_max_allocations) { + /* Too many current allocations */ + return NULL; + } + if (info->max_allocations > 0 && + kctx->jit_current_allocations_per_bin[info->bin_id] >= + info->max_allocations) { + /* Too many current allocations in this bin */ + return NULL; + } + mutex_lock(&kctx->jit_evict_lock); /* * Scan the pool for an existing allocation which meets our * requirements and remove it. */ - list_for_each_entry_safe(walker, temp, &kctx->jit_pool_head, jit_node) { + if (info->usage_id != 0) { + /* First scan for an allocation with the same usage ID */ + struct kbase_va_region *walker; + struct kbase_va_region *temp; + size_t current_diff = SIZE_MAX; + + list_for_each_entry_safe(walker, temp, &kctx->jit_pool_head, + jit_node) { + + if (walker->jit_usage_id == info->usage_id && + walker->nr_pages == info->va_pages && + walker->jit_bin_id == info->bin_id) { + size_t min_size, max_size, diff; + + /* + * The JIT allocations VA requirements have been + * met, it's suitable but other allocations + * might be a better fit. + */ + min_size = min_t(size_t, + walker->gpu_alloc->nents, + info->commit_pages); + max_size = max_t(size_t, + walker->gpu_alloc->nents, + info->commit_pages); + diff = max_size - min_size; + + if (current_diff > diff) { + current_diff = diff; + reg = walker; + } - if (walker->nr_pages >= info->va_pages) { - size_t min_size, max_size, diff; + /* The allocation is an exact match */ + if (current_diff == 0) + break; - /* - * The JIT allocations VA requirements have been - * meet, it's suitable but other allocations - * might be a better fit. - */ - min_size = min_t(size_t, walker->gpu_alloc->nents, - info->commit_pages); - max_size = max_t(size_t, walker->gpu_alloc->nents, - info->commit_pages); - diff = max_size - min_size; - - if (current_diff > diff) { - current_diff = diff; - reg = walker; } - - /* The allocation is an exact match, stop looking */ - if (current_diff == 0) - break; } } + if (!reg) { + /* No allocation with the same usage ID, or usage IDs not in + * use. Search for an allocation we can reuse. + */ + struct kbase_va_region *walker; + struct kbase_va_region *temp; + size_t current_diff = SIZE_MAX; + + list_for_each_entry_safe(walker, temp, &kctx->jit_pool_head, + jit_node) { + + if (walker->nr_pages == info->va_pages && + walker->jit_bin_id == info->bin_id) { + size_t min_size, max_size, diff; + + /* + * The JIT allocations VA requirements have been + * met, it's suitable but other allocations + * might be a better fit. + */ + min_size = min_t(size_t, + walker->gpu_alloc->nents, + info->commit_pages); + max_size = max_t(size_t, + walker->gpu_alloc->nents, + info->commit_pages); + diff = max_size - min_size; + + if (current_diff > diff) { + current_diff = diff; + reg = walker; + } + + /* The allocation is an exact match, so stop + * looking. + */ + if (current_diff == 0) + break; + } + } + } + if (reg) { /* * Remove the found region from the pool and add it to the @@ -2266,11 +2334,19 @@ struct kbase_va_region *kbase_jit_allocate(struct kbase_context *kctx, if (!reg) goto out_unlocked; + reg->flags |= KBASE_REG_JIT; + mutex_lock(&kctx->jit_evict_lock); list_add(®->jit_node, &kctx->jit_active_head); mutex_unlock(&kctx->jit_evict_lock); } + kctx->jit_current_allocations++; + kctx->jit_current_allocations_per_bin[info->bin_id]++; + + reg->jit_usage_id = info->usage_id; + reg->jit_bin_id = info->bin_id; + return reg; update_failed: @@ -2289,13 +2365,57 @@ struct kbase_va_region *kbase_jit_allocate(struct kbase_context *kctx, void kbase_jit_free(struct kbase_context *kctx, struct kbase_va_region *reg) { - /* The physical backing of memory in the pool is always reclaimable */ + u64 old_pages; + + /* Get current size of JIT region */ + old_pages = kbase_reg_current_backed_size(reg); + if (reg->initial_commit < old_pages) { + /* Free trim_level % of region, but don't go below initial + * commit size + */ + u64 new_size = MAX(reg->initial_commit, + div_u64(old_pages * (100 - kctx->trim_level), 100)); + u64 delta = old_pages - new_size; + + if (delta) { + down_write(&kctx->task->mm->mmap_sem); + kbase_mem_shrink_cpu_mapping(kctx, reg, old_pages-delta, + old_pages); + up_write(&kctx->task->mm->mmap_sem); + + kbase_mem_shrink_gpu_mapping(kctx, reg, old_pages-delta, + old_pages); + + kbase_free_phy_pages_helper(reg->cpu_alloc, delta); + if (reg->cpu_alloc != reg->gpu_alloc) + kbase_free_phy_pages_helper(reg->gpu_alloc, + delta); + } + } + + kctx->jit_current_allocations--; + kctx->jit_current_allocations_per_bin[reg->jit_bin_id]--; + + kbase_mem_evictable_mark_reclaim(reg->gpu_alloc); + kbase_gpu_vm_lock(kctx); - kbase_mem_evictable_make(reg->gpu_alloc); + reg->flags |= KBASE_REG_DONT_NEED; + kbase_mem_shrink_cpu_mapping(kctx, reg, 0, reg->gpu_alloc->nents); kbase_gpu_vm_unlock(kctx); + /* + * Add the allocation to the eviction list and the jit pool, after this + * point the shrink can reclaim it, or it may be reused. + */ + mutex_lock(&kctx->jit_evict_lock); + + /* This allocation can't already be on a list. */ + WARN_ON(!list_empty(®->gpu_alloc->evict_node)); + list_add(®->gpu_alloc->evict_node, &kctx->evict_list); + list_move(®->jit_node, &kctx->jit_pool_head); + mutex_unlock(&kctx->jit_evict_lock); } @@ -2337,8 +2457,10 @@ bool kbase_jit_evict(struct kbase_context *kctx) } mutex_unlock(&kctx->jit_evict_lock); - if (reg) + if (reg) { + reg->flags &= ~KBASE_REG_JIT; kbase_mem_free_region(kctx, reg); + } return (reg != NULL); } @@ -2363,6 +2485,7 @@ void kbase_jit_term(struct kbase_context *kctx) struct kbase_va_region, jit_node); list_del(&walker->jit_node); mutex_unlock(&kctx->jit_evict_lock); + walker->flags &= ~KBASE_REG_JIT; kbase_mem_free_region(kctx, walker); mutex_lock(&kctx->jit_evict_lock); } @@ -2373,6 +2496,7 @@ void kbase_jit_term(struct kbase_context *kctx) struct kbase_va_region, jit_node); list_del(&walker->jit_node); mutex_unlock(&kctx->jit_evict_lock); + walker->flags &= ~KBASE_REG_JIT; kbase_mem_free_region(kctx, walker); mutex_lock(&kctx->jit_evict_lock); } diff --git a/drivers/gpu/arm/tMIx/r9p0/mali_kbase_mem.h b/drivers/gpu/arm/tMIx/r9p0/mali_kbase_mem.h index 6fee02f37dc3..103b735a88d2 100644 --- a/drivers/gpu/arm/tMIx/r9p0/mali_kbase_mem.h +++ b/drivers/gpu/arm/tMIx/r9p0/mali_kbase_mem.h @@ -136,8 +136,6 @@ struct kbase_mem_phy_alloc { unsigned long properties; - struct list_head zone_cache; - /* member in union valid based on @a type */ union { #ifdef CONFIG_UMP @@ -246,6 +244,7 @@ struct kbase_va_region { u64 start_pfn; /* The PFN in GPU space */ size_t nr_pages; + size_t initial_commit; /* Free region */ #define KBASE_REG_FREE (1ul << 0) /* CPU write access */ @@ -296,6 +295,9 @@ struct kbase_va_region { * Do not remove, use the next unreserved bit for new flags */ #define KBASE_REG_RESERVED_BIT_22 (1ul << 22) +/* Memory is handled by JIT - user space should not be able to free it */ +#define KBASE_REG_JIT (1ul << 24) + #define KBASE_REG_ZONE_SAME_VA KBASE_REG_ZONE(0) /* only used with 32-bit clients */ @@ -332,6 +334,12 @@ struct kbase_va_region { /* List head used to store the region in the JIT allocation pool */ struct list_head jit_node; + + /* The last JIT usage ID for this region */ + u16 jit_usage_id; + /* The JIT bin this allocation came from */ + u8 jit_bin_id; + }; /* Common functions */ @@ -413,7 +421,6 @@ static inline struct kbase_mem_phy_alloc *kbase_alloc_create(size_t nr_pages, en alloc->pages = (void *)(alloc + 1); INIT_LIST_HEAD(&alloc->mappings); alloc->type = type; - INIT_LIST_HEAD(&alloc->zone_cache); if (type == KBASE_MEM_TYPE_IMPORTED_USER_BUF) alloc->imported.user_buf.dma_addrs = @@ -448,7 +455,6 @@ static inline int kbase_reg_prepare_native(struct kbase_va_region *reg, reg->gpu_alloc = kbase_mem_phy_alloc_get(reg->cpu_alloc); } - INIT_LIST_HEAD(®->jit_node); reg->flags &= ~KBASE_REG_FREE; return 0; } @@ -662,8 +668,9 @@ void kbase_mem_pool_trim(struct kbase_mem_pool *pool, size_t new_size); struct page *kbase_mem_alloc_page(struct kbase_mem_pool *pool); int kbase_region_tracker_init(struct kbase_context *kctx); -int kbase_region_tracker_init_jit(struct kbase_context *kctx, u64 jit_va_pages); void kbase_region_tracker_term(struct kbase_context *kctx); +int kbase_region_tracker_init_jit(struct kbase_context *kctx, u64 jit_va_pages, + u8 max_allocations, u8 trim_level); struct kbase_va_region *kbase_region_tracker_find_region_enclosing_address(struct kbase_context *kctx, u64 gpu_addr); @@ -1117,36 +1124,9 @@ bool kbase_sticky_resource_release(struct kbase_context *kctx, void kbase_sticky_resource_term(struct kbase_context *kctx); /** - * kbase_zone_cache_update - Update the memory zone cache after new pages have - * been added. - * @alloc: The physical memory allocation to build the cache for. - * @start_offset: Offset to where the new pages start. - * - * Updates an existing memory zone cache, updating the counters for the - * various zones. - * If the memory allocation doesn't already have a zone cache assume that - * one isn't created and thus don't do anything. - * - * Return: Zero cache was updated, negative error code on error. - */ -int kbase_zone_cache_update(struct kbase_mem_phy_alloc *alloc, - size_t start_offset); - -/** - * kbase_zone_cache_build - Build the memory zone cache. - * @alloc: The physical memory allocation to build the cache for. - * - * Create a new zone cache for the provided physical memory allocation if - * one doesn't already exist, if one does exist then just return. - * - * Return: Zero if the zone cache was created, negative error code on error. - */ -int kbase_zone_cache_build(struct kbase_mem_phy_alloc *alloc); - -/** - * kbase_zone_cache_clear - Clear the memory zone cache. - * @alloc: The physical memory allocation to clear the cache on. + * kbase_mem_evictable_mark_reclaim - Mark the pages as reclaimable. + * @alloc: The physical allocation */ -void kbase_zone_cache_clear(struct kbase_mem_phy_alloc *alloc); +void kbase_mem_evictable_mark_reclaim(struct kbase_mem_phy_alloc *alloc); #endif /* _KBASE_MEM_H_ */ diff --git a/drivers/gpu/arm/tMIx/r9p0/mali_kbase_mem_linux.c b/drivers/gpu/arm/tMIx/r9p0/mali_kbase_mem_linux.c index 01aa5c2b0f0e..2b8cc75a775b 100644 --- a/drivers/gpu/arm/tMIx/r9p0/mali_kbase_mem_linux.c +++ b/drivers/gpu/arm/tMIx/r9p0/mali_kbase_mem_linux.c @@ -61,39 +61,6 @@ static int kbase_tracking_page_setup(struct kbase_context *kctx, struct vm_area_struct *vma); -/** - * kbase_mem_shrink_cpu_mapping - Shrink the CPU mapping(s) of an allocation - * @kctx: Context the region belongs to - * @reg: The GPU region - * @new_pages: The number of pages after the shrink - * @old_pages: The number of pages before the shrink - * - * Shrink (or completely remove) all CPU mappings which reference the shrunk - * part of the allocation. - * - * Note: Caller must be holding the processes mmap_sem lock. - */ -static void kbase_mem_shrink_cpu_mapping(struct kbase_context *kctx, - struct kbase_va_region *reg, - u64 new_pages, u64 old_pages); - -/** - * kbase_mem_shrink_gpu_mapping - Shrink the GPU mapping of an allocation - * @kctx: Context the region belongs to - * @reg: The GPU region or NULL if there isn't one - * @new_pages: The number of pages after the shrink - * @old_pages: The number of pages before the shrink - * - * Return: 0 on success, negative -errno on error - * - * Unmap the shrunk pages from the GPU mapping. Note that the size of the region - * itself is unmodified as we still need to reserve the VA, only the page tables - * will be modified by this function. - */ -static int kbase_mem_shrink_gpu_mapping(struct kbase_context *kctx, - struct kbase_va_region *reg, - u64 new_pages, u64 old_pages); - struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx, u64 va_pages, u64 commit_pages, u64 extent, u64 *flags, u64 *gpu_va) @@ -181,6 +148,8 @@ struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx, goto no_mem; } + reg->initial_commit = commit_pages; + kbase_gpu_vm_lock(kctx); /* mmap needed to setup VA? */ @@ -473,134 +442,14 @@ void kbase_mem_evictable_deinit(struct kbase_context *kctx) unregister_shrinker(&kctx->reclaim); } -struct kbase_mem_zone_cache_entry { - /* List head used to link the cache entry to the memory allocation. */ - struct list_head zone_node; - /* The zone the cacheline is for. */ - struct zone *zone; - /* The number of pages in the allocation which belong to this zone. */ - u64 count; -}; - -static bool kbase_zone_cache_builder(struct kbase_mem_phy_alloc *alloc, - size_t start_offset) -{ - struct kbase_mem_zone_cache_entry *cache = NULL; - size_t i; - int ret = 0; - - for (i = start_offset; i < alloc->nents; i++) { - struct page *p = phys_to_page(as_phys_addr_t(alloc->pages[i])); - struct zone *zone = page_zone(p); - bool create = true; - - if (cache && (cache->zone == zone)) { - /* - * Fast path check as most of the time adjacent - * pages come from the same zone. - */ - create = false; - } else { - /* - * Slow path check, walk all the cache entries to see - * if we already know about this zone. - */ - list_for_each_entry(cache, &alloc->zone_cache, zone_node) { - if (cache->zone == zone) { - create = false; - break; - } - } - } - - /* This zone wasn't found in the cache, create an entry for it */ - if (create) { - cache = kmalloc(sizeof(*cache), GFP_KERNEL); - if (!cache) { - ret = -ENOMEM; - goto bail; - } - cache->zone = zone; - cache->count = 0; - list_add(&cache->zone_node, &alloc->zone_cache); - } - - cache->count++; - } - return 0; - -bail: - return ret; -} - -int kbase_zone_cache_update(struct kbase_mem_phy_alloc *alloc, - size_t start_offset) -{ - /* - * Bail if the zone cache is empty, only update the cache if it - * existed in the first place. - */ - if (list_empty(&alloc->zone_cache)) - return 0; - - return kbase_zone_cache_builder(alloc, start_offset); -} - -int kbase_zone_cache_build(struct kbase_mem_phy_alloc *alloc) -{ - /* Bail if the zone cache already exists */ - if (!list_empty(&alloc->zone_cache)) - return 0; - - return kbase_zone_cache_builder(alloc, 0); -} - -void kbase_zone_cache_clear(struct kbase_mem_phy_alloc *alloc) -{ - struct kbase_mem_zone_cache_entry *walker; - - while (!list_empty(&alloc->zone_cache)) { - walker = list_first_entry(&alloc->zone_cache, - struct kbase_mem_zone_cache_entry, - zone_node); - list_del(&walker->zone_node); - kfree(walker); - } -} - /** * kbase_mem_evictable_mark_reclaim - Mark the pages as reclaimable. * @alloc: The physical allocation */ -static void kbase_mem_evictable_mark_reclaim(struct kbase_mem_phy_alloc *alloc) +void kbase_mem_evictable_mark_reclaim(struct kbase_mem_phy_alloc *alloc) { struct kbase_context *kctx = alloc->imported.kctx; - struct kbase_mem_zone_cache_entry *zone_cache; int __maybe_unused new_page_count; - int err; - - /* Attempt to build a zone cache of tracking */ - err = kbase_zone_cache_build(alloc); - if (err == 0) { - /* Bulk update all the zones */ - list_for_each_entry(zone_cache, &alloc->zone_cache, zone_node) { - zone_page_state_add(zone_cache->count, - zone_cache->zone, NR_SLAB_RECLAIMABLE); - } - } else { - /* Fall-back to page by page updates */ - int i; - - for (i = 0; i < alloc->nents; i++) { - struct page *p; - struct zone *zone; - - p = phys_to_page(as_phys_addr_t(alloc->pages[i])); - zone = page_zone(p); - - zone_page_state_add(1, zone, NR_SLAB_RECLAIMABLE); - } - } kbase_process_page_usage_dec(kctx, alloc->nents); new_page_count = kbase_atomic_sub_pages(alloc->nents, @@ -620,41 +469,17 @@ static void kbase_mem_evictable_unmark_reclaim(struct kbase_mem_phy_alloc *alloc) { struct kbase_context *kctx = alloc->imported.kctx; - struct kbase_mem_zone_cache_entry *zone_cache; int __maybe_unused new_page_count; - int err; new_page_count = kbase_atomic_add_pages(alloc->nents, &kctx->used_pages); kbase_atomic_add_pages(alloc->nents, &kctx->kbdev->memdev.used_pages); /* Increase mm counters so that the allocation is accounted for - * against the process and thus is visible to the OOM killer, - * then remove it from the reclaimable accounting. */ + * against the process and thus is visible to the OOM killer. + */ kbase_process_page_usage_inc(kctx, alloc->nents); - /* Attempt to build a zone cache of tracking */ - err = kbase_zone_cache_build(alloc); - if (err == 0) { - /* Bulk update all the zones */ - list_for_each_entry(zone_cache, &alloc->zone_cache, zone_node) { - zone_page_state_add(-zone_cache->count, - zone_cache->zone, NR_SLAB_RECLAIMABLE); - } - } else { - /* Fall-back to page by page updates */ - int i; - - for (i = 0; i < alloc->nents; i++) { - struct page *p; - struct zone *zone; - - p = phys_to_page(as_phys_addr_t(alloc->pages[i])); - zone = page_zone(p); - zone_page_state_add(-1, zone, NR_SLAB_RECLAIMABLE); - } - } - KBASE_TLSTREAM_AUX_PAGESALLOC( kctx->id, (u64)new_page_count); @@ -816,8 +641,8 @@ int kbase_mem_flags_change(struct kbase_context *kctx, u64 gpu_addr, unsigned in #ifdef CONFIG_UMP case KBASE_MEM_TYPE_IMPORTED_UMP: ret = kbase_mmu_update_pages(kctx, reg->start_pfn, - kbase_get_gpu_phy_pages(reg), - reg->gpu_alloc->nents, reg->flags); + kbase_get_gpu_phy_pages(reg), + reg->gpu_alloc->nents, reg->flags); break; #endif #ifdef CONFIG_DMA_SHARED_BUFFER @@ -1621,7 +1446,7 @@ int kbase_mem_grow_gpu_mapping(struct kbase_context *kctx, return ret; } -static void kbase_mem_shrink_cpu_mapping(struct kbase_context *kctx, +void kbase_mem_shrink_cpu_mapping(struct kbase_context *kctx, struct kbase_va_region *reg, u64 new_pages, u64 old_pages) { @@ -1636,7 +1461,7 @@ static void kbase_mem_shrink_cpu_mapping(struct kbase_context *kctx, (old_pages - new_pages)<vm_flags & VM_READ)) - vma->vm_flags &= ~VM_MAYREAD; + vma->vm_flags &= ~VM_MAYREAD; if (!(vma->vm_flags & VM_WRITE)) - vma->vm_flags &= ~VM_MAYWRITE; + vma->vm_flags &= ~VM_MAYWRITE; if (0 == nr_pages) { err = -EINVAL; diff --git a/drivers/gpu/arm/tMIx/r9p0/mali_kbase_mem_linux.h b/drivers/gpu/arm/tMIx/r9p0/mali_kbase_mem_linux.h index 90ec6c280bb6..5cd1c8ffab1d 100644 --- a/drivers/gpu/arm/tMIx/r9p0/mali_kbase_mem_linux.h +++ b/drivers/gpu/arm/tMIx/r9p0/mali_kbase_mem_linux.h @@ -247,4 +247,37 @@ void kbase_va_free(struct kbase_context *kctx, struct kbase_hwc_dma_mapping *han extern const struct vm_operations_struct kbase_vm_ops; +/** + * kbase_mem_shrink_cpu_mapping - Shrink the CPU mapping(s) of an allocation + * @kctx: Context the region belongs to + * @reg: The GPU region + * @new_pages: The number of pages after the shrink + * @old_pages: The number of pages before the shrink + * + * Shrink (or completely remove) all CPU mappings which reference the shrunk + * part of the allocation. + * + * Note: Caller must be holding the processes mmap_sem lock. + */ +void kbase_mem_shrink_cpu_mapping(struct kbase_context *kctx, + struct kbase_va_region *reg, + u64 new_pages, u64 old_pages); + +/** + * kbase_mem_shrink_gpu_mapping - Shrink the GPU mapping of an allocation + * @kctx: Context the region belongs to + * @reg: The GPU region or NULL if there isn't one + * @new_pages: The number of pages after the shrink + * @old_pages: The number of pages before the shrink + * + * Return: 0 on success, negative -errno on error + * + * Unmap the shrunk pages from the GPU mapping. Note that the size of the region + * itself is unmodified as we still need to reserve the VA, only the page tables + * will be modified by this function. + */ +int kbase_mem_shrink_gpu_mapping(struct kbase_context *kctx, + struct kbase_va_region *reg, + u64 new_pages, u64 old_pages); + #endif /* _KBASE_MEM_LINUX_H_ */ diff --git a/drivers/gpu/arm/tMIx/r9p0/mali_kbase_mem_pool.c b/drivers/gpu/arm/tMIx/r9p0/mali_kbase_mem_pool.c index 69ad6927428c..49b94d7a2d4a 100644 --- a/drivers/gpu/arm/tMIx/r9p0/mali_kbase_mem_pool.c +++ b/drivers/gpu/arm/tMIx/r9p0/mali_kbase_mem_pool.c @@ -77,8 +77,6 @@ static void kbase_mem_pool_add_locked(struct kbase_mem_pool *pool, list_add(&p->lru, &pool->page_list); pool->cur_size++; - zone_page_state_add(1, page_zone(p), NR_SLAB_RECLAIMABLE); - pool_dbg(pool, "added page\n"); } @@ -92,14 +90,8 @@ static void kbase_mem_pool_add(struct kbase_mem_pool *pool, struct page *p) static void kbase_mem_pool_add_list_locked(struct kbase_mem_pool *pool, struct list_head *page_list, size_t nr_pages) { - struct page *p; - lockdep_assert_held(&pool->pool_lock); - list_for_each_entry(p, page_list, lru) { - zone_page_state_add(1, page_zone(p), NR_SLAB_RECLAIMABLE); - } - list_splice(page_list, &pool->page_list); pool->cur_size += nr_pages; @@ -127,8 +119,6 @@ static struct page *kbase_mem_pool_remove_locked(struct kbase_mem_pool *pool) list_del_init(&p->lru); pool->cur_size--; - zone_page_state_add(-1, page_zone(p), NR_SLAB_RECLAIMABLE); - pool_dbg(pool, "removed page\n"); return p; @@ -649,10 +639,6 @@ void kbase_mem_pool_free_pages(struct kbase_mem_pool *pool, size_t nr_pages, p = phys_to_page(as_phys_addr_t(pages[i])); - if (reclaimed) - zone_page_state_add(-1, page_zone(p), - NR_SLAB_RECLAIMABLE); - kbase_mem_pool_free_page(pool, p); pages[i] = as_tagged(0); } diff --git a/drivers/gpu/arm/tMIx/r9p0/mali_kbase_softjobs.c b/drivers/gpu/arm/tMIx/r9p0/mali_kbase_softjobs.c index 2518a8a6ab1e..c2a5b036268f 100644 --- a/drivers/gpu/arm/tMIx/r9p0/mali_kbase_softjobs.c +++ b/drivers/gpu/arm/tMIx/r9p0/mali_kbase_softjobs.c @@ -917,6 +917,24 @@ static int kbase_jit_allocate_prepare(struct kbase_jd_atom *katom) goto free_info; } + if (kctx->jit_version == 1) { + /* Old JIT didn't have usage_id, max_allocations, bin_id + * or padding, so force them to zero + */ + info->usage_id = 0; + info->max_allocations = 0; + info->bin_id = 0; + memset(info->padding, 0, sizeof(info->padding)); + } else { + int i; + + /* Check padding is all zeroed */ + for (i = 0; i < sizeof(info->padding); i++) { + if (info->padding[i] != 0) + goto free_info; + } + } + katom->softjob_data = info; katom->jit_blocked = false; diff --git a/drivers/gud/gud-exynos7885/MobiCoreDriver/admin.c b/drivers/gud/gud-exynos7885/MobiCoreDriver/admin.c index d376629eb9ae..34ac883aad0a 100644 --- a/drivers/gud/gud-exynos7885/MobiCoreDriver/admin.c +++ b/drivers/gud/gud-exynos7885/MobiCoreDriver/admin.c @@ -39,7 +39,7 @@ #include "client.h" #include "admin.h" -static struct admin_ctx { +static struct { struct mutex admin_tgid_mutex; /* Lock for admin_tgid below */ pid_t admin_tgid; int (*tee_start_cb)(void); @@ -306,7 +306,7 @@ static int request_send(u32 command, const struct mc_uuid_t *uuid, bool is_gp, if (ret) request_cancel(); - mc_dev_devel("request_send ret=%d", ret); + mc_dev_devel("%s ret=%d", __func__, ret); return ret; } @@ -344,7 +344,7 @@ static int request_receive(void *address, u32 size) int ret = 0; ret = wait_for_completion_interruptible( - &g_request.server_complete); + &g_request.server_complete); if (!ret) break; /* We may have to freeze now */ @@ -508,6 +508,9 @@ static void mc_admin_sendcrashdump(void) { int ret = 0; + /* Prevent daemon reconnection */ + admin_ctx.last_start_ret = -EHOSTUNREACH; + /* Lock communication channel */ channel_lock(); @@ -1080,7 +1083,7 @@ int mc_admin_init(struct cdev *cdev, int (*tee_start_cb)(void), /* Register the call back for starting the secure world */ admin_ctx.tee_start_cb = tee_start_cb; admin_ctx.tee_stop_cb = tee_stop_cb; - admin_ctx.last_start_ret = 1; + admin_ctx.last_start_ret = TEE_START_NOT_TRIGGERED; return 0; } diff --git a/drivers/gud/gud-exynos7885/MobiCoreDriver/build_tag.h b/drivers/gud/gud-exynos7885/MobiCoreDriver/build_tag.h index 749266710ff1..5cc01eb0d833 100644 --- a/drivers/gud/gud-exynos7885/MobiCoreDriver/build_tag.h +++ b/drivers/gud/gud-exynos7885/MobiCoreDriver/build_tag.h @@ -13,5 +13,5 @@ */ #ifndef MOBICORE_COMPONENT_BUILD_TAG #define MOBICORE_COMPONENT_BUILD_TAG \ - "t-base-EXYNOS64-Android-400A-V012-20170726_155303_34988_66846" + "t-base-EXYNOS64-Android-400A-V012-20180515_143127_49104_78462" #endif diff --git a/drivers/gud/gud-exynos7885/MobiCoreDriver/client.c b/drivers/gud/gud-exynos7885/MobiCoreDriver/client.c index 380cd08802e3..bc856cc40c4e 100644 --- a/drivers/gud/gud-exynos7885/MobiCoreDriver/client.c +++ b/drivers/gud/gud-exynos7885/MobiCoreDriver/client.c @@ -260,7 +260,7 @@ static struct cwsm *cwsm_create(struct tee_client *client, goto err_cwsm; } - /* Intialise maps */ + /* Initialise maps */ memset(&map, 0, sizeof(map)); tee_mmu_buffer(cwsm->mmu, &map); /* FIXME Flags must be stored in MMU (needs recent trunk change) */ @@ -342,9 +342,9 @@ static inline struct cwsm *cwsm_find(struct tee_client *client, mc_dev_devel("candidate buf %llx size %llu flags %x", candidate->memref.buffer, candidate->memref.size, candidate->memref.flags); - if ((candidate->memref.buffer == memref->buffer) && - (candidate->memref.size == memref->size) && - (candidate->memref.flags == memref->flags)) { + if (candidate->memref.buffer == memref->buffer && + candidate->memref.size == memref->size && + candidate->memref.flags == memref->flags) { cwsm = candidate; cwsm_get(cwsm); mc_dev_devel("match"); @@ -1189,7 +1189,7 @@ int client_cbuf_create(struct tee_client *client, u32 len, uintptr_t *addr, if (!client) return -EINVAL; - if (!len || (len > BUFFER_LENGTH_MAX)) + if (!len || len > BUFFER_LENGTH_MAX) return -EINVAL; order = get_order(len); @@ -1277,7 +1277,7 @@ static struct cbuf *cbuf_get_by_addr(struct tee_client *client, uintptr_t addr) if (!start) break; - if ((addr >= start) && (addr < end)) { + if (addr >= start && addr < end) { cbuf = candidate; break; } @@ -1313,13 +1313,14 @@ int client_cbuf_free(struct tee_client *client, uintptr_t addr) } bool client_gp_operation_add(struct tee_client *client, - struct client_gp_operation *operation) { + struct client_gp_operation *operation) +{ struct client_gp_operation *op; bool found = false; mutex_lock(&client->quick_lock); list_for_each_entry(op, &client->operations, list) - if ((op->started == operation->started) && op->cancelled) { + if (op->started == operation->started && op->cancelled) { found = true; break; } @@ -1339,7 +1340,8 @@ bool client_gp_operation_add(struct tee_client *client, } void client_gp_operation_remove(struct tee_client *client, - struct client_gp_operation *operation) { + struct client_gp_operation *operation) +{ mutex_lock(&client->quick_lock); list_del(&operation->list); mutex_unlock(&client->quick_lock); diff --git a/drivers/gud/gud-exynos7885/MobiCoreDriver/clientlib.c b/drivers/gud/gud-exynos7885/MobiCoreDriver/clientlib.c index f3354766146f..4331c74f46da 100644 --- a/drivers/gud/gud-exynos7885/MobiCoreDriver/clientlib.c +++ b/drivers/gud/gud-exynos7885/MobiCoreDriver/clientlib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016 TRUSTONIC LIMITED + * Copyright (c) 2013-2017 TRUSTONIC LIMITED * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -108,23 +108,33 @@ static void clientlib_client_put(void) enum mc_result mc_open_device(u32 device_id) { enum mc_result mc_result = MC_DRV_OK; + int ret; /* Check parameters */ if (!is_valid_device(device_id)) return MC_DRV_ERR_UNKNOWN_DEVICE; mutex_lock(&dev_mutex); + /* Make sure TEE was started */ + ret = mc_wait_tee_start(); + if (ret) { + mc_dev_err("TEE failed to start, now or in the past"); + mc_result = MC_DRV_ERR_INVALID_DEVICE_FILE; + goto end; + } + if (!open_count) client = client_create(true); if (client) { open_count++; - mc_dev_devel("Successfully opened the device"); + mc_dev_devel("successfully opened the device"); } else { mc_result = MC_DRV_ERR_INVALID_DEVICE_FILE; - mc_dev_devel("Could not open device"); + mc_dev_err("could not open device"); } +end: mutex_unlock(&dev_mutex); return mc_result; } @@ -276,8 +286,13 @@ enum mc_result mc_wait_notification(struct mc_session_handle *session, return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN; /* Call core api */ - ret = convert(client_waitnotif_session(client, session->session_id, - timeout, false)); + do { + ret = convert(client_waitnotif_session(client, + session->session_id, + timeout, false)); + } while ((MC_INFINITE_TIMEOUT == timeout) && + (MC_DRV_ERR_INTERRUPTED_BY_SIGNAL == ret)); + clientlib_client_put(); return ret; } diff --git a/drivers/gud/gud-exynos7885/MobiCoreDriver/fastcall.c b/drivers/gud/gud-exynos7885/MobiCoreDriver/fastcall.c index a45661a15f8a..8674d928c17b 100644 --- a/drivers/gud/gud-exynos7885/MobiCoreDriver/fastcall.c +++ b/drivers/gud/gud-exynos7885/MobiCoreDriver/fastcall.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017 TRUSTONIC LIMITED + * Copyright (c) 2013-2018 TRUSTONIC LIMITED * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -47,6 +47,10 @@ void mc_set_schedule_policy(int core); int __mc_switch_core(int cpu); #endif +#if KERNEL_VERSION(3, 15, 0) > LINUX_VERSION_CODE +#define MIN_NICE -20 +#endif + struct fastcall_work { #ifdef MC_FASTCALL_WORKER_THREAD struct kthread_work work; @@ -239,16 +243,17 @@ void mc_set_schedule_policy(int core) #ifdef MC_FASTCALL_WORKER_THREAD #ifdef CONFIG_SECURE_OS_BOOSTER_API /* ExySp: for sos performance */ -static void mc_cpu_offline(int cpu) +static int mc_cpu_offline(int cpu) { int i; + int ret = 0; mutex_lock(&core_switch_lock); core_status &= ~(0x1 << cpu); if (active_cpu != cpu) { mc_dev_devel("not active CPU, no action taken"); mutex_unlock(&core_switch_lock); - return; + return ret; } /* Chose the first online CPU and switch! */ @@ -257,13 +262,14 @@ static void mc_cpu_offline(int cpu) mc_dev_devel("CPU %d is dying, switching to %d", cpu, i); mc_set_schedule_policy(DEFAULT_LITTLE_CORE); - __mc_switch_core(i); + ret = __mc_switch_core(i); break; } mc_dev_devel("Skipping CPU %d\n", cpu); } mutex_unlock(&core_switch_lock); + return ret; } void mc_cpu_online(int cpu) @@ -276,13 +282,13 @@ void mc_cpu_online(int cpu) mutex_unlock(&core_switch_lock); } #else -static void mc_cpu_offline(int cpu) +static int mc_cpu_offline(int cpu) { int i; if (active_cpu != cpu) { mc_dev_devel("not active CPU, no action taken\n"); - return; + return 0; } /* Chose the first online CPU and switch! */ @@ -290,15 +296,17 @@ static void mc_cpu_offline(int cpu) if (cpu != i) { mc_dev_devel("CPU %d is dying, switching to %d\n", cpu, i); - mc_switch_core(i); - break; + return mc_switch_core(i); } mc_dev_devel("Skipping CPU %d", cpu); } + + return 0; } #endif +#if KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE static int mobicore_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -330,6 +338,13 @@ static int mobicore_cpu_callback(struct notifier_block *nfb, static struct notifier_block mobicore_cpu_notifer = { .notifier_call = mobicore_cpu_callback, }; +#else +static int nq_cpu_down_prep(unsigned int cpu) +{ + mc_dev_info("CPU #%d is going to die", cpu); + return mc_cpu_offline(cpu); +} +#endif #endif /* MC_FASTCALL_WORKER_THREAD */ static cpumask_t mc_exec_core_switch(union mc_fc_generic *mc_fc_generic) @@ -376,8 +391,23 @@ static ssize_t debug_coreswitch_write(struct file *file, return buffer_len; } +static ssize_t debug_coreswitch_read(struct file *file, char __user *buffer, + size_t buffer_len, loff_t *ppos) +{ + char cpu_str[8]; + int ret = 0; + + ret = snprintf(cpu_str, sizeof(cpu_str), "%d\n", mc_active_core()); + if (ret < 0) + return -EINVAL; + + return simple_read_from_buffer(buffer, buffer_len, ppos, + cpu_str, ret); +} + static const struct file_operations mc_debug_coreswitch_ops = { .write = debug_coreswitch_write, + .read = debug_coreswitch_read, }; #else /* TBASE_CORE_SWITCHER */ static inline cpumask_t mc_exec_core_switch(union mc_fc_generic *mc_fc_generic) @@ -386,6 +416,18 @@ static inline cpumask_t mc_exec_core_switch(union mc_fc_generic *mc_fc_generic) } #endif /* !TBASE_CORE_SWITCHER */ +#ifdef MC_SMC_FASTCALL +static inline int nq_set_cpus_allowed(struct task_struct *p, cpumask_t new_mask) +{ + return 0; +} +#else /* MC_SMC_FASTCALL */ +static inline int nq_set_cpus_allowed(struct task_struct *p, cpumask_t new_mask) +{ + return set_cpus_allowed_ptr(p, &new_mask); +} +#endif /* ! MC_SMC_FASTCALL */ + #ifdef MC_FASTCALL_WORKER_THREAD static void fastcall_work_func(struct kthread_work *work) #else @@ -410,8 +452,7 @@ static void fastcall_work_func(struct work_struct *work) #ifdef MC_FASTCALL_WORKER_THREAD cpumask_t new_msk = mc_exec_core_switch(mc_fc_generic); - /* ExySp */ - set_cpus_allowed_ptr(fastcall_thread, &new_msk); + nq_set_cpus_allowed(fastcall_thread, new_msk); #else mc_exec_core_switch(mc_fc_generic); #endif @@ -448,11 +489,19 @@ static bool mc_fastcall(void *data) .data = data, }; +#if KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE + if (!kthread_queue_work(&fastcall_worker, &fc_work.work)) + return false; + + /* If work is queued or executing, wait for it to finish execution */ + kthread_flush_work(&fc_work.work); +#else if (!queue_kthread_work(&fastcall_worker, &fc_work.work)) return false; /* If work is queued or executing, wait for it to finish execution */ flush_kthread_work(&fc_work.work); +#endif #else struct fastcall_work fc_work = { .data = data, @@ -469,7 +518,6 @@ static bool mc_fastcall(void *data) int mc_fastcall_init(void) { - cpumask_t new_msk = CPU_MASK_CPU0; int ret = mc_clock_init(); if (ret) @@ -485,12 +533,25 @@ int mc_fastcall_init(void) return ret; } + set_user_nice(fastcall_thread, MIN_NICE); + /* this thread MUST run on CPU 0 at startup */ - set_cpus_allowed_ptr(fastcall_thread, &new_msk); + nq_set_cpus_allowed(fastcall_thread, CPU_MASK_CPU0); wake_up_process(fastcall_thread); #ifdef TBASE_CORE_SWITCHER +#if KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE ret = register_cpu_notifier(&mobicore_cpu_notifer); +#else + ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, + "tee/trustonic:online", + NULL, nq_cpu_down_prep); +#endif + if (ret < 0) { + mc_dev_err("cpu online callback setup failed: %d", ret); + return ret; + } + /* Create debugfs structs entry */ debugfs_create_file("active_cpu", 0600, g_ctx.debug_dir, NULL, &mc_debug_coreswitch_ops); @@ -502,7 +563,7 @@ int mc_fastcall_init(void) mutex_init(&core_switch_lock); #endif - return ret; + return 0; } void mc_fastcall_exit(void) @@ -510,7 +571,11 @@ void mc_fastcall_exit(void) #ifdef MC_FASTCALL_WORKER_THREAD if (!IS_ERR_OR_NULL(fastcall_thread)) { #ifdef TBASE_CORE_SWITCHER +#if KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE unregister_cpu_notifier(&mobicore_cpu_notifer); +#else + cpuhp_remove_state_nocalls(CPUHP_AP_ONLINE_DYN); +#endif #endif kthread_stop(fastcall_thread); fastcall_thread = NULL; @@ -700,6 +765,9 @@ int mc_switch_core(int cpu) s32 ret = 0; union mc_fc_swich_core fc_switch_core; + if (cpu >= nr_cpu_ids) + return -EINVAL; + if (!cpu_online(cpu)) return 1; diff --git a/drivers/gud/gud-exynos7885/MobiCoreDriver/iwp.c b/drivers/gud/gud-exynos7885/MobiCoreDriver/iwp.c index 2c066f293014..db9a99ad6f62 100755 --- a/drivers/gud/gud-exynos7885/MobiCoreDriver/iwp.c +++ b/drivers/gud/gud-exynos7885/MobiCoreDriver/iwp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016 TRUSTONIC LIMITED + * Copyright (c) 2013-2018 TRUSTONIC LIMITED * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -82,8 +82,8 @@ static void iwp_notif_handler(u32 id, u32 payload) mc_dev_devel("candidate->slot [%08x]", candidate->slot); /* If id is SID_CANCEL_OPERATION, there is pseudo session */ - if ((candidate->slot == payload) && - ((id != SID_CANCEL_OPERATION) || (candidate->sid == id))) { + if (candidate->slot == payload && + (id != SID_CANCEL_OPERATION || candidate->sid == id)) { iwp_session = candidate; break; } @@ -513,7 +513,7 @@ int iwp_open_session( /* Temporary slot is not needed any more */ iws_slot_put(temp_slot); /* Treat remote errors as errors, just use a specific errno */ - if (!ret && (iws->status != TEEC_SUCCESS)) { + if (!ret && iws->status != TEEC_SUCCESS) { gp_ret->origin = iws->return_origin; gp_ret->value = iws->status; ret = -ECHILD; @@ -620,7 +620,7 @@ int iwp_invoke_command( iwp_iws_set_refs(iws, maps); ret = iwp_cmd(iwp_session, SID_INVOKE_COMMAND); /* Treat remote errors as errors, just use a specific errno */ - if (!ret && (iws->status != TEEC_SUCCESS)) + if (!ret && iws->status != TEEC_SUCCESS) ret = -ECHILD; iwp_iws_to_operation(iws, operation); diff --git a/drivers/gud/gud-exynos7885/MobiCoreDriver/logging.c b/drivers/gud/gud-exynos7885/MobiCoreDriver/logging.c index a23c8d3c5391..f6335ea09223 100644 --- a/drivers/gud/gud-exynos7885/MobiCoreDriver/logging.c +++ b/drivers/gud/gud-exynos7885/MobiCoreDriver/logging.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017 TRUSTONIC LIMITED + * Copyright (c) 2013-2018 TRUSTONIC LIMITED * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -73,9 +73,7 @@ static struct logging_ctx { char line[LOG_LINE_SIZE + 1];/* Log Line buffer */ u32 line_len; /* Log Line buffer current length */ #if KERNEL_VERSION(4, 4, 0) > LINUX_VERSION_CODE - /* ExySp */ - //u32 enabled; /* Log can be disabled via debugfs */ - bool enabled; /* Log can be disabled via debugfs */ + u32 enabled; /* Log can be disabled via debugfs */ #else bool enabled; /* Log can be disabled via debugfs */ #endif @@ -113,8 +111,7 @@ static inline void log_char(char ch, u16 source) return; } - if ((log_ctx.line_len >= LOG_LINE_SIZE) || - (source != log_ctx.prev_source)) + if (log_ctx.line_len >= LOG_LINE_SIZE || source != log_ctx.prev_source) log_eol(source); log_ctx.line[log_ctx.line_len++] = ch; @@ -199,7 +196,7 @@ static void log_worker(struct work_struct *work) void mc_logging_run(void) { if (log_ctx.enabled && !log_ctx.dead && - (log_ctx.trace_buf->head != log_ctx.tail)) + log_ctx.trace_buf->head != log_ctx.tail) schedule_work(&log_ctx.work); } diff --git a/drivers/gud/gud-exynos7885/MobiCoreDriver/main.c b/drivers/gud/gud-exynos7885/MobiCoreDriver/main.c index 2da152e62de4..b8d308e39a89 100644 --- a/drivers/gud/gud-exynos7885/MobiCoreDriver/main.c +++ b/drivers/gud/gud-exynos7885/MobiCoreDriver/main.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -54,7 +55,11 @@ struct mc_device_ctx g_ctx = { .mcd = &device }; -static struct main_ctx { +static struct { + /* TEE start return code */ + struct mutex start_mutex; + /* TEE start return code */ + int start_ret; #ifdef MC_PM_RUNTIME /* Whether hibernation succeeded */ bool did_hibernate; @@ -133,7 +138,7 @@ ssize_t debug_generic_read(struct file *file, char __user *user_buf, kasnprintf_buf_reset(buf); goto end; } - } + } ret = simple_read_from_buffer(user_buf, count, ppos, buf->buf, buf->off); @@ -141,7 +146,7 @@ ssize_t debug_generic_read(struct file *file, char __user *user_buf, end: mutex_unlock(&buf->mutex); return ret; - } +} int debug_generic_open(struct inode *inode, struct file *file) { @@ -297,6 +302,7 @@ static int suspend_notifier(struct notifier_block *nb, unsigned long event, if (main_ctx.did_hibernate) { /* Really did hibernate */ clients_kill_sessions(); + main_ctx.start_ret = TEE_START_NOT_TRIGGERED; return mobicore_start(); } @@ -318,6 +324,10 @@ static int mobicore_start(void) #endif int ret; + mutex_lock(&main_ctx.start_mutex); + if (main_ctx.start_ret != TEE_START_NOT_TRIGGERED) + goto got_ret; + ret = mc_logging_start(); if (ret) { mc_dev_err("Log start failed"); @@ -452,7 +462,8 @@ static int mobicore_start(void) if (ret) goto err_create_dev_user; - return 0; + main_ctx.start_ret = 0; + goto got_ret; err_create_dev_user: #ifdef MC_PM_RUNTIME @@ -474,7 +485,10 @@ static int mobicore_start(void) err_nq: mc_logging_stop(); err_log: - return ret; + main_ctx.start_ret = ret; +got_ret: + mutex_unlock(&main_ctx.start_mutex); + return main_ctx.start_ret; } static void mobicore_stop(void) @@ -492,6 +506,22 @@ static void mobicore_stop(void) nq_stop(); } +int mc_wait_tee_start(void) +{ + int ret; + + mutex_lock(&main_ctx.start_mutex); + while (main_ctx.start_ret == TEE_START_NOT_TRIGGERED) { + mutex_unlock(&main_ctx.start_mutex); + ssleep(1); + mutex_lock(&main_ctx.start_mutex); + } + + ret = main_ctx.start_ret; + mutex_unlock(&main_ctx.start_mutex); + return ret; +} + static ssize_t debug_sessions_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -625,6 +655,8 @@ static int mobicore_probe(struct platform_device *pdev) atomic_set(&g_ctx.c_mmus, 0); atomic_set(&g_ctx.c_maps, 0); atomic_set(&g_ctx.c_slots, 0); + main_ctx.start_ret = TEE_START_NOT_TRIGGERED; + mutex_init(&main_ctx.start_mutex); mutex_init(&main_ctx.struct_counters_buf_mutex); /* Create debugfs info entry */ debugfs_create_file("structs_counters", 0400, g_ctx.debug_dir, NULL, @@ -678,6 +710,12 @@ static int mobicore_probe(struct platform_device *pdev) if (err) goto err_admin; +#ifndef MC_DELAYED_TEE_START + err = mobicore_start(); +#endif + if (err) + goto err_start; + /* * ExySp: for sos performance * migrate secure OS to a non-booting little core @@ -686,6 +724,8 @@ static int mobicore_probe(struct platform_device *pdev) return 0; +err_start: + device_admin_exit(); err_admin: mc_scheduler_exit(); err_sched: diff --git a/drivers/gud/gud-exynos7885/MobiCoreDriver/main.h b/drivers/gud/gud-exynos7885/MobiCoreDriver/main.h index fb482654976f..3d468c0b10a7 100644 --- a/drivers/gud/gud-exynos7885/MobiCoreDriver/main.h +++ b/drivers/gud/gud-exynos7885/MobiCoreDriver/main.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017 TRUSTONIC LIMITED + * Copyright (c) 2013-2018 TRUSTONIC LIMITED * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -41,6 +41,8 @@ #define TEEC_TT_LOGIN_KERNEL 0x80000000 +#define TEE_START_NOT_TRIGGERED 1 + /* MobiCore Driver Kernel Module context data. */ struct mc_device_ctx { struct device *mcd; @@ -82,13 +84,16 @@ extern struct mc_device_ctx g_ctx; /* Debug stuff */ struct kasnprintf_buf { - struct mutex mutex; /* Protect buf/size/off access */ + struct mutex mutex; /* Protect buf/size/off access */ gfp_t gfp; void *buf; int size; int off; }; +/* Wait for TEE to start and get status */ +int mc_wait_tee_start(void); + extern __printf(2, 3) int kasnprintf(struct kasnprintf_buf *buf, const char *fmt, ...); ssize_t debug_generic_read(struct file *file, char __user *user_buf, diff --git a/drivers/gud/gud-exynos7885/MobiCoreDriver/mcp.c b/drivers/gud/gud-exynos7885/MobiCoreDriver/mcp.c index 95e67d81a295..53bfa01d6d49 100644 --- a/drivers/gud/gud-exynos7885/MobiCoreDriver/mcp.c +++ b/drivers/gud/gud-exynos7885/MobiCoreDriver/mcp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017 TRUSTONIC LIMITED + * Copyright (c) 2013-2018 TRUSTONIC LIMITED * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -269,7 +269,7 @@ static inline int wait_mcp_notification(void) /* If SWd halted, exit now */ if (!mc_fc_info(MC_EXT_INFO_ID_MCI_VERSION, &status, NULL) && - (status == MC_STATUS_HALT)) + status == MC_STATUS_HALT) break; } @@ -414,7 +414,7 @@ static int mcp_cmd(union mcp_message *cmd, } if (err) { - if ((cmd_id == MC_MCP_CMD_CLOSE_SESSION) && (err == -EAGAIN)) + if (cmd_id == MC_MCP_CMD_CLOSE_SESSION && err == -EAGAIN) mc_dev_devel("%s: try again", mcp_cmd_to_string(cmd_id)); else @@ -683,7 +683,7 @@ static inline void session_notif_handler(struct mcp_session *session, u32 id, */ if (!nq_session_is_gp(&session->nq_session) || !session->exit_code || - (payload != ERR_SID_NOT_ACTIVE)) + payload != ERR_SID_NOT_ACTIVE) session->exit_code = payload; mutex_unlock(&session->exit_code_lock); diff --git a/drivers/gud/gud-exynos7885/MobiCoreDriver/scheduler.c b/drivers/gud/gud-exynos7885/MobiCoreDriver/scheduler.c index dafd02fd2bb3..a13df5de9256 100644 --- a/drivers/gud/gud-exynos7885/MobiCoreDriver/scheduler.c +++ b/drivers/gud/gud-exynos7885/MobiCoreDriver/scheduler.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016 TRUSTONIC LIMITED + * Copyright (c) 2013-2018 TRUSTONIC LIMITED * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -136,8 +136,8 @@ static int tee_scheduler(void *arg) } else { bool infinite_timeout = timeout_ms < 0; - if ((timeout_ms < 0) || - (timeout_ms > DEFAULT_TIMEOUT_MS)) + if (timeout_ms < 0 || + timeout_ms > DEFAULT_TIMEOUT_MS) timeout_ms = DEFAULT_TIMEOUT_MS; if (!wait_for_completion_timeout( @@ -189,6 +189,7 @@ static int tee_scheduler(void *arg) nq_retrieve_last(&session_id, &payload); timeslice = SCHEDULING_FREQ; + /* Call SWd scheduler */ ret = mc_fc_nsiq(session_id, payload); } diff --git a/drivers/gud/gud-exynos7885/MobiCoreDriver/session.c b/drivers/gud/gud-exynos7885/MobiCoreDriver/session.c index 3a47b1b4c775..9928918a3d66 100644 --- a/drivers/gud/gud-exynos7885/MobiCoreDriver/session.c +++ b/drivers/gud/gud-exynos7885/MobiCoreDriver/session.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017 TRUSTONIC LIMITED + * Copyright (c) 2013-2018 TRUSTONIC LIMITED * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -303,8 +303,8 @@ static int check_prepare_identity(const struct mc_identity *identity, /* Copy login type */ mcp_identity->login_type = identity->login_type; - if ((identity->login_type == LOGIN_PUBLIC) || - (identity->login_type == TEEC_TT_LOGIN_KERNEL)) + if (identity->login_type == LOGIN_PUBLIC || + identity->login_type == TEEC_TT_LOGIN_KERNEL) return 0; /* Mobicore doesn't support GP client authentication. */ @@ -314,16 +314,16 @@ static int check_prepare_identity(const struct mc_identity *identity, } /* Fill in uid field */ - if ((identity->login_type == LOGIN_USER) || - (identity->login_type == LOGIN_USER_APPLICATION)) { + if (identity->login_type == LOGIN_USER || + identity->login_type == LOGIN_USER_APPLICATION) { /* Set euid and ruid of the process. */ mcp_id->uid.euid = __kuid_val(task_euid(task)); mcp_id->uid.ruid = __kuid_val(task_uid(task)); } /* Check gid field */ - if ((identity->login_type == LOGIN_GROUP) || - (identity->login_type == LOGIN_GROUP_APPLICATION)) { + if (identity->login_type == LOGIN_GROUP || + identity->login_type == LOGIN_GROUP_APPLICATION) { const struct cred *cred = __task_cred(task); /* @@ -707,10 +707,10 @@ int session_unmap(struct tee_session *session, mutex_lock(&session->wsms_lock); /* Look for buffer in the session WSMs array */ for (i = 0; i < MC_MAP_MAX; i++) - if ((session->wsms[i].in_use) && - (buf->va == session->wsms[i].va) && - (buf->len == session->wsms[i].len) && - (buf->sva == session->wsms[i].sva)) + if (session->wsms[i].in_use && + buf->va == session->wsms[i].va && + buf->len == session->wsms[i].len && + buf->sva == session->wsms[i].sva) break; if (i == MC_MAP_MAX) { diff --git a/drivers/gud/gud-exynos7885/MobiCoreDriver/teeclientapi.c b/drivers/gud/gud-exynos7885/MobiCoreDriver/teeclientapi.c index c625e483c779..fcb2e0a2f882 100644 --- a/drivers/gud/gud-exynos7885/MobiCoreDriver/teeclientapi.c +++ b/drivers/gud/gud-exynos7885/MobiCoreDriver/teeclientapi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017 TRUSTONIC LIMITED + * Copyright (c) 2013-2018 TRUSTONIC LIMITED * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -179,6 +179,7 @@ static u32 _teec_convert_error(int errno) u32 teec_initialize_context(const char *name, struct teec_context *context) { struct tee_client *client; + int ret; (void)name; mc_dev_devel("== %s() ==============", __func__); @@ -188,10 +189,17 @@ u32 teec_initialize_context(const char *name, struct teec_context *context) return TEEC_ERROR_BAD_PARAMETERS; } + /* Make sure TEE was started */ + ret = mc_wait_tee_start(); + if (ret) { + mc_dev_err("TEE failed to start, now or in the past"); + return TEEC_ERROR_BAD_STATE; + } + /* Create client */ client = client_create(true); if (!client) - return -ENOMEM; + return TEEC_ERROR_OUT_OF_MEMORY; /* Store client in context */ context->imp.client = client; @@ -288,13 +296,13 @@ u32 teec_open_session(struct teec_context *context, ret = client_gp_open_session(client, &session->imp.session_id, &tauuid, &gp_op, &identity, &gp_ret, -1); - if (!ret || (ret != EAGAIN)) + if (!ret || ret != EAGAIN) break; msleep(1000); } while (--timeout); - if (ret || (gp_ret.value != TEEC_SUCCESS)) { + if (ret || gp_ret.value != TEEC_SUCCESS) { mc_dev_devel("client_gp_open_session failed(%08x) %08x", ret, gp_ret.value); if (ret) diff --git a/drivers/gud/gud-exynos7885/MobiCoreDriver/user.c b/drivers/gud/gud-exynos7885/MobiCoreDriver/user.c index 1850c6e5520c..b96677415eee 100644 --- a/drivers/gud/gud-exynos7885/MobiCoreDriver/user.c +++ b/drivers/gud/gud-exynos7885/MobiCoreDriver/user.c @@ -12,12 +12,12 @@ * GNU General Public License for more details. */ -#include #include #include #include #include #include /* struct vm_area_struct */ +#include #include "public/mc_user.h" @@ -142,7 +142,7 @@ static long user_ioctl(struct file *file, unsigned int id, unsigned long arg) ret = client_open_session(client, &session.sid, &session.uuid, session.tci, session.tcilen, session.is_gp_uuid, - &session.identity, session.client_fd); + &session.identity, -1); if (ret) break; @@ -163,8 +163,7 @@ static long user_ioctl(struct file *file, unsigned int id, unsigned long arg) ret = client_open_trustlet(client, &trustlet.sid, trustlet.spid, trustlet.buffer, trustlet.tlen, - trustlet.tci, trustlet.tcilen, - trustlet.client_fd); + trustlet.tci, trustlet.tcilen, -1); if (ret) break; @@ -206,8 +205,7 @@ static long user_ioctl(struct file *file, unsigned int id, unsigned long arg) break; } - ret = client_map_session_wsms(client, map.sid, &map.buf, - map.client_fd); + ret = client_map_session_wsms(client, map.sid, &map.buf, -1); if (ret) break; @@ -291,8 +289,7 @@ static long user_ioctl(struct file *file, unsigned int id, unsigned long arg) ret = client_gp_register_shared_mem(client, &shared_mem.memref, - &shared_mem.ret, - shared_mem.client_fd); + &shared_mem.ret, -1); if (copy_to_user(uarg, &shared_mem, sizeof(shared_mem))) { ret = -EFAULT; @@ -322,8 +319,7 @@ static long user_ioctl(struct file *file, unsigned int id, unsigned long arg) ret = client_gp_open_session(client, &session.session_id, &session.uuid, &session.operation, &session.identity, - &session.ret, - session.client_fd); + &session.ret, -1); if (copy_to_user(uarg, &session, sizeof(session))) { ret = -EFAULT; @@ -353,8 +349,7 @@ static long user_ioctl(struct file *file, unsigned int id, unsigned long arg) ret = client_gp_invoke_command(client, command.session_id, command.command_id, &command.operation, - &command.ret, - command.client_fd); + &command.ret, -1); if (copy_to_user(uarg, &command, sizeof(command))) { ret = -EFAULT; diff --git a/drivers/misc/samsung/scsc/mxman.c b/drivers/misc/samsung/scsc/mxman.c index 75aaaf809820..3d58d4cf61b3 100755 --- a/drivers/misc/samsung/scsc/mxman.c +++ b/drivers/misc/samsung/scsc/mxman.c @@ -311,41 +311,6 @@ static int send_mm_msg_stop_blocking(struct mxman *mxman) return 0; } -static void write_m_test_fw_version_file(struct mxman *mxman) -{ - struct file *fp = NULL; - char *filepath = "/data/misc/conn/.wifiver.info"; - char buf[256]; - char *build_id = 0; - - if (mxman) - build_id = mxman->fw_build_id; - - fp = filp_open(filepath, O_WRONLY|O_CREAT, 0644); - - if (IS_ERR(fp)) { - SCSC_TAG_INFO(MXMAN, "version file wasn't opened\n"); - return; - } else if (fp == NULL) { - SCSC_TAG_INFO(MXMAN, "%s doesn't open.\n", filepath); - return; - } -#ifdef CONFIG_SCSC_BUILD_TYPE - snprintf(buf, sizeof(buf), "drv_ver: %d.%d.%d (build type: %s) N (f/w: %s)\n", - SCSC_RELEASE_PRODUCT, SCSC_RELEASE_ITERATION, SCSC_RELEASE_CANDIDATE, CONFIG_SCSC_BUILD_TYPE, - build_id ? build_id : "unknown"); -#else - snprintf(buf, sizeof(buf), "drv_ver: %d.%d.%d N (f/w: %s)\n", - SCSC_RELEASE_PRODUCT, SCSC_RELEASE_ITERATION, SCSC_RELEASE_CANDIDATE, - build_id ? build_id : "unknown"); -#endif - - kernel_write(fp, buf, strlen(buf), 0); - filp_close(fp, NULL); - - SCSC_TAG_DEBUG(MXMAN, "Succeed to write firmware/host information to .wifiver.info\n"); -} - static void write_m_test_chip_version_file(struct mxman *mxman) { struct file *fp = NULL; @@ -415,13 +380,12 @@ static void mxman_print_versions(struct mxman *mxman) SCSC_TAG_INFO(MXMAN, "%s", buf); SCSC_TAG_INFO(MXMAN, "WLBT FW: %s\n", mxman->fw_build_id); + SCSC_TAG_INFO(MXMAN, "WLBT Driver: %d.%d.%d.%d\n", + SCSC_RELEASE_PRODUCT, SCSC_RELEASE_ITERATION, SCSC_RELEASE_CANDIDATE, SCSC_RELEASE_POINT); #ifdef CONFIG_SCSC_BUILD_TYPE SCSC_TAG_INFO(MXMAN, "WLBT Driver Build Type: %s\n", CONFIG_SCSC_BUILD_TYPE); #endif - /* write .wifiver.info */ - write_m_test_fw_version_file(mxman); - /* write .cid.info */ write_m_test_chip_version_file(mxman); } @@ -1225,16 +1189,18 @@ static void mxman_failure_work(struct work_struct *work) process_panic_record(mxman); SCSC_TAG_INFO(MXMAN, "Trying to schedule coredump\n"); #ifdef CONFIG_SCSC_BUILD_TYPE - SCSC_TAG_INFO(MXMAN, "scsc_release %d.%d.%d, Kernel build type: %s\n", + SCSC_TAG_INFO(MXMAN, "scsc_release %d.%d.%d.%d, Kernel build type: %s\n", SCSC_RELEASE_PRODUCT, SCSC_RELEASE_ITERATION, SCSC_RELEASE_CANDIDATE, + SCSC_RELEASE_POINT, CONFIG_SCSC_BUILD_TYPE); #else - SCSC_TAG_INFO(MXMAN, "scsc_release %d.%d.%d\n", + SCSC_TAG_INFO(MXMAN, "scsc_release %d.%d.%d.%d\n", SCSC_RELEASE_PRODUCT, SCSC_RELEASE_ITERATION, - SCSC_RELEASE_CANDIDATE); + SCSC_RELEASE_CANDIDATE, + SCSC_RELEASE_POINT); #endif /* schedule coredump and wait for it to finish */ @@ -1828,6 +1794,21 @@ static int _mx_exec(char *prog, int wait_exec) } #ifdef CONFIG_SCSC_PRINTK + +static int __stat(const char *file) +{ + struct kstat stat; + mm_segment_t fs; + int r; + + fs = get_fs(); + set_fs(get_ds()); + r = vfs_stat(file, &stat); + set_fs(fs); + + return r; +} + int mx140_log_dump(void) { int r; @@ -1837,6 +1818,15 @@ int mx140_log_dump(void) if (r) { SCSC_TAG_ERR(MXMAN, "mx_logger_dump.sh path error\n"); } else { + /* + * Test presence of script before invoking, to suppress + * unnecessary error message if not installed. + */ + r = __stat(mxlbin); + if (r) { + SCSC_TAG_DEBUG(MXMAN, "%s not installed\n", mxlbin); + return r; + } SCSC_TAG_INFO(MXMAN, "Invoking mx_logger_dump.sh UHM\n"); r = _mx_exec(mxlbin, UMH_WAIT_EXEC); if (r) @@ -1881,11 +1871,11 @@ EXPORT_SYMBOL(mxman_get_fw_version); void mxman_get_driver_version(char *version, size_t ver_sz) { #ifdef CONFIG_SCSC_BUILD_TYPE - snprintf(version, ver_sz - 1, "drv_ver: %d.%d.%d (build type: %s)", - SCSC_RELEASE_PRODUCT, SCSC_RELEASE_ITERATION, SCSC_RELEASE_CANDIDATE, CONFIG_SCSC_BUILD_TYPE); + snprintf(version, ver_sz - 1, "drv_ver: %d.%d.%d.%d (build type: %s)", + SCSC_RELEASE_PRODUCT, SCSC_RELEASE_ITERATION, SCSC_RELEASE_CANDIDATE, SCSC_RELEASE_POINT, CONFIG_SCSC_BUILD_TYPE); #else - snprintf(version, ver_sz - 1, "drv_ver: %d.%d.%d", - SCSC_RELEASE_PRODUCT, SCSC_RELEASE_ITERATION, SCSC_RELEASE_CANDIDATE); + snprintf(version, ver_sz - 1, "drv_ver: %d.%d.%d.%d", + SCSC_RELEASE_PRODUCT, SCSC_RELEASE_ITERATION, SCSC_RELEASE_CANDIDATE, SCSC_RELEASE_POINT); #endif } EXPORT_SYMBOL(mxman_get_driver_version); diff --git a/drivers/misc/samsung/scsc/mxproc.c b/drivers/misc/samsung/scsc/mxproc.c index 85db07c137d5..f45f64510c00 100644 --- a/drivers/misc/samsung/scsc/mxproc.c +++ b/drivers/misc/samsung/scsc/mxproc.c @@ -384,9 +384,9 @@ int mxproc_create_ctrl_proc_dir(struct mxproc *mxproc, struct mxman *mxman) mxproc->mxman = mxman; mxproc->procfs_ctrl_dir = parent; mxproc->procfs_ctrl_dir_num = proc_count; - MX_PROCFS_ADD_FILE(mxproc, mx_fail, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); - MX_PROCFS_ADD_FILE(mxproc, mx_freeze, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH |S_IWOTH); - MX_PROCFS_ADD_FILE(mxproc, mx_panic, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + MX_PROCFS_ADD_FILE(mxproc, mx_fail, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); + MX_PROCFS_ADD_FILE(mxproc, mx_freeze, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); + MX_PROCFS_ADD_FILE(mxproc, mx_panic, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); MX_PROCFS_ADD_FILE(mxproc, mx_suspend, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); MX_PROCFS_ADD_FILE(mxproc, mx_suspend_count, parent, S_IRUSR | S_IRGRP | S_IROTH); MX_PROCFS_ADD_FILE(mxproc, mx_recovery_count, parent, S_IRUSR | S_IRGRP | S_IROTH); @@ -471,12 +471,12 @@ static ssize_t mx_procfs_mx_release_read(struct file *file, char __user *user_bu memset(buf, '\0', sizeof(buf)); #ifdef CONFIG_SCSC_BUILD_TYPE - bytes = snprintf(buf, sizeof(buf), "Release: %d.%d.%d (build type: %s) (f/w: %s)\n", - SCSC_RELEASE_PRODUCT, SCSC_RELEASE_ITERATION, SCSC_RELEASE_CANDIDATE, CONFIG_SCSC_BUILD_TYPE, + bytes = snprintf(buf, sizeof(buf), "Release: %d.%d.%d.%d (build type: %s) (f/w: %s)\n", + SCSC_RELEASE_PRODUCT, SCSC_RELEASE_ITERATION, SCSC_RELEASE_CANDIDATE, SCSC_RELEASE_POINT, CONFIG_SCSC_BUILD_TYPE, build_id ? build_id : "unknown"); #else - bytes = snprintf(buf, sizeof(buf), "Release: %d.%d.%d (f/w: %s)\n", - SCSC_RELEASE_PRODUCT, SCSC_RELEASE_ITERATION, SCSC_RELEASE_CANDIDATE, + bytes = snprintf(buf, sizeof(buf), "Release: %d.%d.%d.%d (f/w: %s)\n", + SCSC_RELEASE_PRODUCT, SCSC_RELEASE_ITERATION, SCSC_RELEASE_CANDIDATE, SCSC_RELEASE_POINT, build_id ? build_id : "unknown"); #endif if (bytes > sizeof(buf)) diff --git a/drivers/misc/samsung/scsc/scsc_logring_debugfs.c b/drivers/misc/samsung/scsc/scsc_logring_debugfs.c index cddaac9d139f..97a9f8a11868 100644 --- a/drivers/misc/samsung/scsc/scsc_logring_debugfs.c +++ b/drivers/misc/samsung/scsc/scsc_logring_debugfs.c @@ -634,7 +634,7 @@ void __init *samlog_debugfs_init(const char *root_name, void *rb) if (!di->statfile) goto no_statfile; - di->samwritefile = debugfs_create_file(SCSC_SAMWRITE_FNAME, 0222, + di->samwritefile = debugfs_create_file(SCSC_SAMWRITE_FNAME, 0220, di->bufdir, NULL, &samwrite_fops); if (!di->samwritefile) diff --git a/drivers/misc/samsung/scsc/scsc_mx_module.c b/drivers/misc/samsung/scsc/scsc_mx_module.c index b043f5e522fb..bebc520ea55e 100755 --- a/drivers/misc/samsung/scsc/scsc_mx_module.c +++ b/drivers/misc/samsung/scsc/scsc_mx_module.c @@ -100,16 +100,18 @@ static struct scsc_mif_abs_driver mx_module_mif_if = { static int __init scsc_mx_module_init(void) { #ifdef CONFIG_SCSC_BUILD_TYPE - SCSC_TAG_INFO(MXMAN, SCSC_MX_CORE_MODDESC " scsc_release %d.%d.%d (build type: %s\n)", + SCSC_TAG_INFO(MXMAN, SCSC_MX_CORE_MODDESC " scsc_release %d.%d.%d.%d (build type: %s\n)", SCSC_RELEASE_PRODUCT, SCSC_RELEASE_ITERATION, SCSC_RELEASE_CANDIDATE, + SCSC_RELEASE_POINT, CONFIG_SCSC_BUILD_TYPE); #else - SCSC_TAG_INFO(MXMAN, SCSC_MX_CORE_MODDESC " scsc_release %d.%d.%d\n", + SCSC_TAG_INFO(MXMAN, SCSC_MX_CORE_MODDESC " scsc_release %d.%d.%d.%d\n", SCSC_RELEASE_PRODUCT, SCSC_RELEASE_ITERATION, - SCSC_RELEASE_CANDIDATE); + SCSC_RELEASE_CANDIDATE, + SCSC_RELEASE_POINT); #endif scsc_mif_abs_register(&mx_module_mif_if); diff --git a/drivers/net/wireless/scsc/cfg80211_ops.c b/drivers/net/wireless/scsc/cfg80211_ops.c index fb4c2884d92b..e3506ab60c10 100755 --- a/drivers/net/wireless/scsc/cfg80211_ops.c +++ b/drivers/net/wireless/scsc/cfg80211_ops.c @@ -917,11 +917,6 @@ int slsi_connect(struct wiphy *wiphy, struct net_device *dev, r = slsi_set_boost(sdev, dev); if (r != 0) SLSI_NET_ERR(dev, "Rssi Boost set failed: %d\n", r); - r = slsi_set_uapsd_qos_info(sdev, dev); - if (r != 0) { - SLSI_NET_ERR(dev, "qosInfo MIB write failed: %d\n", r); - goto exit_with_vif; - } /* add_info_elements with Probe Req IEs. Proceed even if confirm fails for add_info as it would * still work if the fw pre-join scan does not include the vendor IEs diff --git a/drivers/net/wireless/scsc/dev.h b/drivers/net/wireless/scsc/dev.h index 5b0fb7910eff..c0976be03d06 100755 --- a/drivers/net/wireless/scsc/dev.h +++ b/drivers/net/wireless/scsc/dev.h @@ -832,6 +832,7 @@ struct slsi_dev { struct scsc_service *service; struct slsi_chip_info_mib chip_info_mib; struct slsi_plat_info_mib plat_info_mib; + u16 reg_dom_version; #ifdef CONFIG_SCSC_WLAN_MUTEX_DEBUG struct slsi_mutex netdev_add_remove_mutex; diff --git a/drivers/net/wireless/scsc/ioctl.c b/drivers/net/wireless/scsc/ioctl.c index 6dd0edf99819..8be2d89a925b 100755 --- a/drivers/net/wireless/scsc/ioctl.c +++ b/drivers/net/wireless/scsc/ioctl.c @@ -1,6 +1,6 @@ /**************************************************************************** * - * Copyright (c) 2012 - 2017 Samsung Electronics Co., Ltd. All rights reserved + * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved * ****************************************************************************/ @@ -401,9 +401,10 @@ static ssize_t slsi_p2p_ecsa(struct net_device *dev, char *command) return result; } -static ssize_t slsi_p2p_go_vendor_ies_write(struct slsi_dev *sdev, struct net_device *dev, u8 *ie, size_t ie_len, u16 purpose) +static ssize_t slsi_ap_vendor_ies_write(struct slsi_dev *sdev, struct net_device *dev, u8 *ie, + size_t ie_len, u16 purpose) { - u8 *go_vendor_ie = NULL; + u8 *vendor_ie = NULL; int result = 0; struct netdev_vif *ndev_vif; @@ -414,32 +415,32 @@ static ssize_t slsi_p2p_go_vendor_ies_write(struct slsi_dev *sdev, struct net_de * same which comes before adding GO VIF */ if (!ndev_vif->activated) { - SLSI_DBG1(sdev, SLSI_CFG80211, "P2P GO vif not activated\n"); + SLSI_DBG1(sdev, SLSI_CFG80211, "vif not activated\n"); result = 0; goto exit; } - if (ndev_vif->iftype != NL80211_IFTYPE_P2P_GO) { - SLSI_ERR(sdev, "No P2P interface present\n"); + if (!(ndev_vif->iftype == NL80211_IFTYPE_P2P_GO || ndev_vif->iftype == NL80211_IFTYPE_AP)) { + SLSI_ERR(sdev, "Not AP or P2P interface. interfaceType:%d\n", ndev_vif->iftype); result = -EINVAL; goto exit; } - go_vendor_ie = kmalloc(ie_len, GFP_KERNEL); - if (go_vendor_ie == NULL) { + vendor_ie = kmalloc(ie_len, GFP_KERNEL); + if (!vendor_ie) { SLSI_ERR(sdev, "kmalloc failed\n"); result = -ENOMEM; goto exit; - } - memcpy(go_vendor_ie, ie, ie_len); + } + memcpy(vendor_ie, ie, ie_len); slsi_clear_cached_ies(&ndev_vif->ap.add_info_ies, &ndev_vif->ap.add_info_ies_len); - result = slsi_ap_prepare_add_info_ies(ndev_vif, go_vendor_ie, ie_len); + result = slsi_ap_prepare_add_info_ies(ndev_vif, vendor_ie, ie_len); if (result == 0) result = slsi_mlme_add_info_elements(sdev, dev, purpose, ndev_vif->ap.add_info_ies, ndev_vif->ap.add_info_ies_len); slsi_clear_cached_ies(&ndev_vif->ap.add_info_ies, &ndev_vif->ap.add_info_ies_len); - kfree(go_vendor_ie); + kfree(vendor_ie); exit: SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex); @@ -456,7 +457,7 @@ static ssize_t slsi_set_ap_p2p_wps_ie(struct net_device *dev, char *command, int enum if_type { IF_TYPE_NONE, IF_TYPE_P2P_DEVICE, - IF_TYPE_P2P_INTERFACE + IF_TYPE_AP_P2P } iftype = IF_TYPE_NONE; enum frame_type { FRAME_TYPE_NONE, @@ -482,8 +483,9 @@ static ssize_t slsi_set_ap_p2p_wps_ie(struct net_device *dev, char *command, int } offset = offset + readbyte + 1; params_len = params_len - offset; - SLSI_NET_DBG2(dev, SLSI_NETDEV, "command = %s, frametype=%d, iftype = %d, total buf_len=%d, params_len=%d\n", command, frametype, iftype, buf_len, params_len); - + SLSI_NET_DBG2(dev, SLSI_NETDEV, + "command=%s, frametype=%d, iftype=%d, total buf_len=%d, params_len=%d\n", + command, frametype, iftype, buf_len, params_len); /* check the net device interface type */ if (iftype == IF_TYPE_P2P_DEVICE) { u8 *probe_resp_ie = NULL; /* params+offset; */ @@ -503,18 +505,15 @@ static ssize_t slsi_set_ap_p2p_wps_ie(struct net_device *dev, char *command, int SLSI_NET_DBG2(dev, SLSI_NETDEV, "P2P Device: probe_resp_ie is NOT NULL\n"); return slsi_p2p_dev_probe_rsp_ie(sdev, dev, probe_resp_ie, params_len); - } else if (iftype == IF_TYPE_P2P_INTERFACE) { - SLSI_NET_DBG2(dev, SLSI_NETDEV, "P2P GO case"); - if (frametype == FRAME_TYPE_BEACON) { - SLSI_DBG1(sdev, SLSI_MLME, "P2P GO beacon IEs update\n"); - return slsi_p2p_go_vendor_ies_write(sdev, dev, params+offset, params_len, FAPI_PURPOSE_BEACON); - } else if (frametype == FRAME_TYPE_PROBE_RESPONSE) { - SLSI_DBG1(sdev, SLSI_MLME, "P2P GO proberesp IEs update\n"); - return slsi_p2p_go_vendor_ies_write(sdev, dev, params+offset, params_len, FAPI_PURPOSE_PROBE_RESPONSE); - } else if (frametype == FRAME_TYPE_ASSOC_RESPONSE) { - SLSI_DBG1(sdev, SLSI_MLME, "P2P GO Association Response IEs update\n"); - return slsi_p2p_go_vendor_ies_write(sdev, dev, params+offset, params_len, FAPI_PURPOSE_ASSOCIATION_RESPONSE); - } + } else if (iftype == IF_TYPE_AP_P2P) { + if (frametype == FRAME_TYPE_BEACON) + return slsi_ap_vendor_ies_write(sdev, dev, params + offset, params_len, FAPI_PURPOSE_BEACON); + else if (frametype == FRAME_TYPE_PROBE_RESPONSE) + return slsi_ap_vendor_ies_write(sdev, dev, params + offset, params_len, + FAPI_PURPOSE_PROBE_RESPONSE); + else if (frametype == FRAME_TYPE_ASSOC_RESPONSE) + return slsi_ap_vendor_ies_write(sdev, dev, params + offset, params_len, + FAPI_PURPOSE_ASSOCIATION_RESPONSE); } exit: return result; diff --git a/drivers/net/wireless/scsc/mgt.c b/drivers/net/wireless/scsc/mgt.c index e9e9d233fad9..eaa9d8e51f00 100755 --- a/drivers/net/wireless/scsc/mgt.c +++ b/drivers/net/wireless/scsc/mgt.c @@ -41,6 +41,9 @@ #define SLSI_MIB_MAX_CLIENT (10) #define SLSI_REG_PARAM_START_INDEX (1) +/* temp until it gets integrated into mib.h by Autogen */ +#define SLSI_PSID_UNIFI_REG_DOM_VERSION 8019 + static char *mib_file_t = "wlan_t.hcf"; module_param(mib_file_t, charp, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(mib_file_t, "mib data filename"); @@ -218,6 +221,46 @@ static void slsi_print_platform_id(struct slsi_dev *sdev) mx140_file_release_conf(sdev->maxwell_core, e); } +static void write_wifi_version_info_file(struct slsi_dev *sdev) +{ + struct file *fp = NULL; + char *filepath = "/data/misc/conn/.wifiver.info"; + char buf[256]; + char build_id_fw[128]; + char build_id_drv[64]; + + fp = filp_open(filepath, O_WRONLY | O_CREAT | O_TRUNC, 0644); + + if (IS_ERR(fp)) { + SLSI_WARN(sdev, "version file wasn't found\n"); + return; + } else if (!fp) { + SLSI_WARN(sdev, "%s doesn't exist.\n", filepath); + return; + } + + mxman_get_fw_version(build_id_fw, 128); + mxman_get_driver_version(build_id_drv, 64); + + /* WARNING: + * Please do not change the format of the following string + * as it can have fatal consequences. + * The framework parser for the version may depend on this + * exact formatting. + */ + snprintf(buf, sizeof(buf), "%s (f/w_ver: %s)\nregDom_ver: %d.%d\n", + build_id_drv, + build_id_fw, + ((sdev->reg_dom_version >> 8) & 0xFF), (sdev->reg_dom_version & 0xFF)); + + kernel_write(fp, buf, strlen(buf), 0); + + if (fp) + filp_close(fp, NULL); + + SLSI_INFO(sdev, "Succeed to write firmware/host information to .wifiver.info\n"); +} + #define SLSI_SM_WLAN_SERVICE_RECOVERY_COMPLETED_TIMEOUT 20000 int slsi_start(struct slsi_dev *sdev) { @@ -351,9 +394,11 @@ int slsi_start(struct slsi_dev *sdev) wiphy_apply_custom_regulatory(sdev->wiphy, sdev->device_config.domain_info.regdomain); } } - /* Do nothing for unifiDefaultCountry == world_domain */ + /* write .wifiver.info */ + write_wifi_version_info_file(sdev); + #ifdef CONFIG_SCSC_WLAN_AP_INFO_FILE /* writing .softap.info in /data/misc/conn */ fp = filp_open(filepath, O_WRONLY | O_CREAT, 0666); /* 0666 required by framework */ @@ -831,6 +876,7 @@ static int slsi_mib_initial_get(struct slsi_dev *sdev) { SLSI_PSID_UNIFI_VHT_CAPABILITIES, {0, 0} }, { SLSI_PSID_UNIFI24_G40_MHZ_CHANNELS, {0, 0} }, { SLSI_PSID_UNIFI_HARDWARE_PLATFORM, {0, 0} }, + { SLSI_PSID_UNIFI_REG_DOM_VERSION, {0, 0} }, #ifdef CONFIG_SCSC_WLAN_WIFI_SHARING { SLSI_PSID_UNIFI_WI_FI_SHARING5_GHZ_CHANNEL, {0, 0} }, #endif @@ -946,6 +992,12 @@ static int slsi_mib_initial_get(struct slsi_dev *sdev) } else { SLSI_WARN(sdev, "Error reading Hardware platform\n"); } + if (values[++mib_index].type != SLSI_MIB_TYPE_NONE) { /* REG_DOM_VERSION */ + SLSI_CHECK_TYPE(sdev, values[mib_index].type, SLSI_MIB_TYPE_UINT); + sdev->reg_dom_version = values[mib_index].u.uintValue; + } else { + SLSI_WARN(sdev, "Error reading Reg domain version\n"); + } #ifdef CONFIG_SCSC_WLAN_WIFI_SHARING if (values[++mib_index].type == SLSI_MIB_TYPE_OCTET) { /* 5Ghz Allowed Channels */ if (values[mib_index].u.octetValue.dataLength >= 8) { @@ -2878,21 +2930,6 @@ int slsi_auto_chan_select_scan(struct slsi_dev *sdev, int n_channels, struct iee return r; } -int slsi_set_uapsd_qos_info(struct slsi_dev *sdev, struct net_device *dev) -{ - int error = 0; - - SLSI_MUTEX_LOCK(sdev->device_config_mutex); - SLSI_DBG1(sdev, SLSI_MLME, "Configured QoS Info :0x%x\n", sdev->device_config.qos_info); - if (sdev->device_config.qos_info != -1) { - error = slsi_set_uint_mib(sdev, dev, SLSI_PSID_UNIFI_STATION_QOS_INFO, sdev->device_config.qos_info); - if (error) - SLSI_ERR(sdev, "Err setting qos info . error = %d\n", error); - } - SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); - return error; -} - int slsi_set_boost(struct slsi_dev *sdev, struct net_device *dev) { int error = 0; diff --git a/drivers/net/wireless/scsc/mgt.h b/drivers/net/wireless/scsc/mgt.h index 5173329e46fd..9e586e0e1446 100755 --- a/drivers/net/wireless/scsc/mgt.h +++ b/drivers/net/wireless/scsc/mgt.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright (c) 2012 - 2017 Samsung Electronics Co., Ltd. All rights reserved + * Copyright (c) 2012 - 2018 Samsung Electronics Co., Ltd. All rights reserved * *****************************************************************************/ @@ -402,7 +402,6 @@ struct ieee80211_channel *slsi_find_scan_channel(struct slsi_dev *sdev, struct i int slsi_auto_chan_select_scan(struct slsi_dev *sdev, int chan_count, struct ieee80211_channel *channels[]); int slsi_set_uint_mib(struct slsi_dev *dev, struct net_device *ndev, u16 psid, int value); int slsi_update_regd_rules(struct slsi_dev *sdev, bool country_check); -int slsi_set_uapsd_qos_info(struct slsi_dev *sdev, struct net_device *dev); int slsi_set_boost(struct slsi_dev *sdev, struct net_device *dev); int slsi_p2p_init(struct slsi_dev *sdev, struct netdev_vif *ndev_vif); void slsi_p2p_deinit(struct slsi_dev *sdev, struct netdev_vif *ndev_vif); diff --git a/drivers/net/wireless/scsc/mlme.c b/drivers/net/wireless/scsc/mlme.c index fc71320aff95..ef1bdf8beb0f 100755 --- a/drivers/net/wireless/scsc/mlme.c +++ b/drivers/net/wireless/scsc/mlme.c @@ -1932,13 +1932,16 @@ static const u8 *slsi_mlme_connect_get_sec_ie(struct cfg80211_connect_params *sm return ptr; } -/* If is_copy is true copy the required IEs from connect_ie to ie_dest. else calculate the required ie length */ -static int slsi_mlme_connect_info_elems_ie_prep(const u8 *connect_ie, const size_t connect_ie_len, - bool is_copy, u8 *ie_dest, int ie_dest_len) +/* If is_copy is true copy the required IEs from connect_ie to ie_dest. else + * calculate the required ie length*/ +static int slsi_mlme_connect_info_elems_ie_prep(struct slsi_dev *sdev, const u8 *connect_ie, + const size_t connect_ie_len, bool is_copy, u8 *ie_dest, int ie_dest_len) { const u8 *ie_pos = NULL; int info_elem_length = 0; u16 curr_ie_len; + u8 *wmm_ie = NULL; + u8 *ie_dest_start = ie_dest; if (is_copy && (!ie_dest || ie_dest_len == 0)) return -EINVAL; @@ -1951,7 +1954,8 @@ static int slsi_mlme_connect_info_elems_ie_prep(const u8 *connect_ie, const size if (ie_dest_len >= curr_ie_len) { memcpy(ie_dest, ie_pos, curr_ie_len); ie_dest += curr_ie_len; - ie_dest_len -= curr_ie_len; /* free space available in ie_dest for next ie */ + /* free space avail in ie_dest for next ie*/ + ie_dest_len -= curr_ie_len; } else { SLSI_ERR_NODEV("interwork ie extract error (ie_copy_l:%d, c_ie_l:%d):\n", ie_dest_len, curr_ie_len); return -EINVAL; @@ -1964,7 +1968,8 @@ static int slsi_mlme_connect_info_elems_ie_prep(const u8 *connect_ie, const size /* vendor specific IEs will be the last elements. */ ie_pos = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, connect_ie, connect_ie_len); if (ie_pos) { - curr_ie_len = connect_ie_len - (ie_pos - connect_ie); /* length of all the vendor specific IEs */ + /* length of all the vendor specific IEs */ + curr_ie_len = connect_ie_len - (ie_pos - connect_ie); if (is_copy) { if (ie_dest_len >= curr_ie_len) { memcpy(ie_dest, ie_pos, curr_ie_len); @@ -1977,6 +1982,51 @@ static int slsi_mlme_connect_info_elems_ie_prep(const u8 *connect_ie, const size } else { info_elem_length += curr_ie_len; } + if (sdev->device_config.qos_info != -1 && is_copy) { + ie_pos = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WMM, ie_dest_start, + ie_dest_len); + while (ie_pos) { + if (ie_pos[6] == 0 && ie_pos[7] == 1) { + wmm_ie = (u8 *)ie_pos; + break; + } + ie_pos += ie_pos[1]; + ie_pos = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, 2, ie_pos, + ie_dest_len - (ie_pos - ie_dest_start)); + } + } + } + + if (sdev->device_config.qos_info != -1) { + if (wmm_ie) { + if (is_copy) { + wmm_ie[8] &= 0xF0; + wmm_ie[8] |= sdev->device_config.qos_info & 0x0F; + } + } else { + if (is_copy) { + if (ie_dest_len >= 9) { + int pos = 0; + + ie_dest[pos++] = 0xdd; + ie_dest[pos++] = 0x07; + ie_dest[pos++] = 0x00; + ie_dest[pos++] = 0x50; + ie_dest[pos++] = 0xf2; + ie_dest[pos++] = 0x02; + ie_dest[pos++] = 0x00; + ie_dest[pos++] = 0x01; + ie_dest[pos++] = sdev->device_config.qos_info & 0x0F; + ie_dest += pos; + ie_dest_len -= pos; + } else { + SLSI_ERR_NODEV("Fail new WMMIE req 9 but left:%d\n", ie_dest_len); + return -EINVAL; + } + } else { + info_elem_length += 9; + } + } } return info_elem_length; @@ -1991,7 +2041,7 @@ static int slsi_mlme_connect_info_elements(struct slsi_dev *sdev, struct net_dev int r = 0; u8 *p; - info_elem_length = slsi_mlme_connect_info_elems_ie_prep(sme->ie, sme->ie_len, false, NULL, 0); + info_elem_length = slsi_mlme_connect_info_elems_ie_prep(sdev, sme->ie, sme->ie_len, false, NULL, 0); /* NO IE required in MLME-ADD-INFO-ELEMENTS */ if (info_elem_length <= 0) @@ -2010,7 +2060,7 @@ static int slsi_mlme_connect_info_elements(struct slsi_dev *sdev, struct net_dev return -EINVAL; } - (void)slsi_mlme_connect_info_elems_ie_prep(sme->ie, sme->ie_len, true, p, info_elem_length); + (void)slsi_mlme_connect_info_elems_ie_prep(sdev, sme->ie, sme->ie_len, true, p, info_elem_length); /* backup ies */ if (SLSI_IS_VIF_INDEX_WLAN(ndev_vif)) { diff --git a/drivers/net/wireless/scsc/nl80211_vendor.c b/drivers/net/wireless/scsc/nl80211_vendor.c index 71273ca8cd68..f4d8ab810d74 100644 --- a/drivers/net/wireless/scsc/nl80211_vendor.c +++ b/drivers/net/wireless/scsc/nl80211_vendor.c @@ -2888,7 +2888,10 @@ static int slsi_lls_get_stats(struct wiphy *wiphy, struct wireless_dev *wdev, co SLSI_WARN(sdev, "not supported in WlanLite mode\n"); return -EOPNOTSUPP; } - + if(!sdev) { + SLSI_ERR(sdev, "sdev is Null\n"); + return -EINVAL; + } SLSI_MUTEX_LOCK(sdev->device_config_mutex); /* In case of lower layer failure do not read LLS MIBs */ if (sdev->mlme_blocked) diff --git a/drivers/net/wireless/scsc/rx.c b/drivers/net/wireless/scsc/rx.c index 80477e4b86e2..480dc33f7f40 100755 --- a/drivers/net/wireless/scsc/rx.c +++ b/drivers/net/wireless/scsc/rx.c @@ -617,7 +617,6 @@ void __slsi_rx_blockack_ind(struct slsi_dev *sdev, struct net_device *dev, struc fapi_get_u16(skb, u.ma_blockack_ind.direction)); peer = slsi_get_peer_from_mac(sdev, dev, fapi_get_buff(skb, u.ma_blockack_ind.peer_qsta_address)); - WARN_ON(!peer); if (peer) { /* Buffering of frames before the mlme_connected_ind */ @@ -636,6 +635,8 @@ void __slsi_rx_blockack_ind(struct slsi_dev *sdev, struct net_device *dev, struc fapi_get_u16(skb, u.ma_blockack_ind.reason_code), fapi_get_u16(skb, u.ma_blockack_ind.direction) ); + } else { + SLSI_NET_DBG1(dev, SLSI_MLME, "no Peer found, cannot handle BA indication\n"); } slsi_kfree_skb(skb); @@ -771,6 +772,7 @@ enum slsi_wlan_vendor_attr_roam_auth { SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR, SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK, SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK, + SLSI_WLAN_VENDOR_ATTR_ROAM_BEACON_IE, /* keep last */ SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST, SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX = @@ -781,9 +783,9 @@ int slsi_send_roam_vendor_event(struct slsi_dev *sdev, const u8 *bssid, const u8 *req_ie, size_t req_ie_len, const u8 *resp_ie, size_t resp_ie_len, + const u8 *beacon_ie, size_t beacon_ie_len, bool authorized) { - int length = ETH_ALEN + 32 + req_ie_len + resp_ie_len; bool is_secured_bss; struct sk_buff *skb = NULL; @@ -793,9 +795,9 @@ int slsi_send_roam_vendor_event(struct slsi_dev *sdev, SLSI_DBG2(sdev, SLSI_MLME, "authorized:%d, is_secured_bss:%d\n", authorized, is_secured_bss); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) - skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, length, SLSI_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH, GFP_KERNEL); + skb = cfg80211_vendor_event_alloc(sdev->wiphy, NULL, NLMSG_DEFAULT_SIZE, SLSI_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH, GFP_KERNEL); #else - skb = cfg80211_vendor_event_alloc(sdev->wiphy, length, SLSI_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH, GFP_KERNEL); + skb = cfg80211_vendor_event_alloc(sdev->wiphy, NLMSG_DEFAULT_SIZE, SLSI_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH, GFP_KERNEL); #endif if (!skb) { SLSI_ERR_NODEV("Failed to allocate skb for VENDOR Roam event\n"); @@ -804,8 +806,10 @@ int slsi_send_roam_vendor_event(struct slsi_dev *sdev, if (nla_put(skb, SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID, ETH_ALEN, bssid) || nla_put(skb, SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, 1, &authorized) || (req_ie && nla_put(skb, SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE, req_ie_len, req_ie)) || - (resp_ie && nla_put(skb, SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE, resp_ie_len, resp_ie))) { - SLSI_ERR_NODEV("Failed nla_put 1\n"); + (resp_ie && nla_put(skb, SLSI_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE, resp_ie_len, resp_ie)) || + (beacon_ie && nla_put(skb, SLSI_WLAN_VENDOR_ATTR_ROAM_BEACON_IE, beacon_ie_len, beacon_ie))) { + SLSI_ERR_NODEV("Failed nla_put ,req_ie_len=%d,resp_ie_len=%d,beacon_ie_len=%d\n", + req_ie_len, resp_ie_len, beacon_ie_len); slsi_kfree_skb(skb); return -EINVAL; } @@ -934,7 +938,9 @@ void slsi_rx_roamed_ind(struct slsi_dev *sdev, struct net_device *dev, struct sk GFP_KERNEL); #ifdef CONFIG_SCSC_WLAN_KEY_MGMT_OFFLOAD if (slsi_send_roam_vendor_event(sdev, peer->address, assoc_ie, assoc_ie_len, - assoc_rsp_ie, assoc_rsp_ie_len, !temporal_keys_required) != 0) { + assoc_rsp_ie, assoc_rsp_ie_len, + ndev_vif->sta.sta_bss->ies->data, ndev_vif->sta.sta_bss->ies->len, + !temporal_keys_required) != 0) { SLSI_NET_ERR(dev, "Could not send Roam vendor event up"); } #endif diff --git a/drivers/net/wireless/scsc/sap_dbg.c b/drivers/net/wireless/scsc/sap_dbg.c index 07ef49da9d95..d564a9fa33c6 100644 --- a/drivers/net/wireless/scsc/sap_dbg.c +++ b/drivers/net/wireless/scsc/sap_dbg.c @@ -47,7 +47,7 @@ static void slsi_rx_debug(struct slsi_dev *sdev, struct net_device *dev, struct switch (id) { case DEBUG_FAULT_IND: - SLSI_WARN(sdev, "FAULT_IND: |cpu %s|id 0x%04X|arg 0x%08X|count %d|timestamp %10u|\n", + SLSI_WARN(sdev, "WF_FW_INFO: |cpu %s|id 0x%04X|arg 0x%08X|count %d|timestamp %10u|\n", ((fapi_get_u16(skb, u.debug_fault_ind.cpu) == 0x8000) ? "MAC" : (fapi_get_u16(skb, u.debug_fault_ind.cpu) == 0x4000) ? "PHY" : "???"), fapi_get_u16(skb, u.debug_fault_ind.faultid), diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c index e8f22a7ad4e4..bfea58744688 100644 --- a/drivers/usb/gadget/function/u_ether.c +++ b/drivers/usb/gadget/function/u_ether.c @@ -1548,7 +1548,8 @@ void gether_free_request(struct gether *link) struct eth_dev *dev = link->ioport; struct usb_request *req; - printk("usb: %s : \n", __func__); + printk("usb: %s\n", __func__); + flush_work(&dev->work); while (!list_empty(&dev->tx_reqs)) { req = container_of(dev->tx_reqs.next, diff --git a/include/scsc/scsc_release.h b/include/scsc/scsc_release.h index 6adc5f943393..fd67d3d9ea42 100644 --- a/include/scsc/scsc_release.h +++ b/include/scsc/scsc_release.h @@ -13,6 +13,7 @@ #define SCSC_RELEASE_ITERATION 41 #define SCSC_RELEASE_CANDIDATE 1 +#define SCSC_RELEASE_POINT 3 #endif diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index fe144dae7372..a3058021990e 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c @@ -363,11 +363,6 @@ static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf, { struct inet_frag_queue *q; - if (frag_mem_limit(nf) > nf->high_thresh) { - inet_frag_schedule_worker(f); - return NULL; - } - q = kmem_cache_zalloc(f->frags_cachep, GFP_ATOMIC); if (!q) return NULL; @@ -404,6 +399,11 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, struct inet_frag_queue *q; int depth = 0; + if (!nf->high_thresh || frag_mem_limit(nf) > nf->high_thresh) { + inet_frag_schedule_worker(f); + return NULL; + } + if (frag_mem_limit(nf) > nf->low_thresh) inet_frag_schedule_worker(f); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index db3199ac3039..1c53a78ae068 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5324,6 +5324,7 @@ tcp_collapse(struct sock *sk, struct sk_buff_head *list, static void tcp_collapse_ofo_queue(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); + u32 range_truesize, sum_tiny = 0; struct sk_buff *skb = skb_peek(&tp->out_of_order_queue); struct sk_buff *head; u32 start, end; @@ -5333,6 +5334,7 @@ static void tcp_collapse_ofo_queue(struct sock *sk) start = TCP_SKB_CB(skb)->seq; end = TCP_SKB_CB(skb)->end_seq; + range_truesize = skb->truesize; head = skb; for (;;) { @@ -5347,14 +5349,24 @@ static void tcp_collapse_ofo_queue(struct sock *sk) if (!skb || after(TCP_SKB_CB(skb)->seq, end) || before(TCP_SKB_CB(skb)->end_seq, start)) { - tcp_collapse(sk, &tp->out_of_order_queue, - head, skb, start, end); + /* Do not attempt collapsing tiny skbs */ + if (range_truesize != head->truesize || + end - start >= SKB_WITH_OVERHEAD(SK_MEM_QUANTUM)) { + tcp_collapse(sk, &tp->out_of_order_queue, + head, skb, start, end); + } else { + sum_tiny += range_truesize; + if (sum_tiny > sk->sk_rcvbuf >> 3) + return; + } + head = skb; if (!skb) break; /* Start new segment */ start = TCP_SKB_CB(skb)->seq; end = TCP_SKB_CB(skb)->end_seq; + range_truesize = skb->truesize; } else { if (before(TCP_SKB_CB(skb)->seq, start)) start = TCP_SKB_CB(skb)->seq; @@ -5413,6 +5425,9 @@ static int tcp_prune_queue(struct sock *sk) else if (tcp_under_memory_pressure(sk)) tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U * tp->advmss); + if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) + return 0; + tcp_collapse_ofo_queue(sk); if (!skb_queue_empty(&sk->sk_receive_queue)) tcp_collapse(sk, &sk->sk_receive_queue,