From ad064077b5c5157a05bb3ee4f024294138ea7643 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Wed, 5 Jun 2024 13:52:11 +0530 Subject: [PATCH 01/42] thermal: qcom: Add support to update tsens trip based on nvmem data Add support to detect higher thermal profile parts and update thermal zone trips dynamically based on nvmem cell data for tsens. Change-Id: I792c4f2736d10d68b45cc9b64c0ec08d185cf007 Signed-off-by: Manaf Meethalavalappu Pallikunhi (cherry picked from commit c360f7cb0cd4d19a3d63d79842e2cea2df99dcff) --- drivers/thermal/msm-tsens.c | 90 +++++++++++++++++++++++++++++++++++++ drivers/thermal/tsens.h | 13 ++++++ 2 files changed, 103 insertions(+) diff --git a/drivers/thermal/msm-tsens.c b/drivers/thermal/msm-tsens.c index c660a05761af..167d0fba08e3 100644 --- a/drivers/thermal/msm-tsens.c +++ b/drivers/thermal/msm-tsens.c @@ -1,10 +1,12 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ #include #include +#include #include #include #include @@ -205,10 +207,95 @@ static int get_device_tree_data(struct platform_device *pdev, return rc; } +static void tsens_thermal_zone_trip_update(struct tsens_device *tmdev, + struct thermal_zone_device *tz, + const struct thermal_trip *trip, int trip_id) +{ + int ret = 0; + u32 trip_delta = 0; + int trip_temp; + + if (trip->type == THERMAL_TRIP_CRITICAL) + return; + + if (strnstr(tz->type, "cpu", sizeof(tz->type))) + trip_delta = TSENS_ELEVATE_CPU_DELTA; + else + trip_delta = TSENS_ELEVATE_DELTA; + + trip_temp = trip->temperature + trip_delta; + if (tz->ops->set_trip_temp) { + ret = tz->ops->set_trip_temp(tz, trip_id, trip_temp); + if (ret) { + dev_err(tmdev->dev, "%s: failed to set trip%d for %s\n", + __func__, trip_id, tz->type); + return; + } + } + thermal_zone_device_update(tz, THERMAL_TRIP_CHANGED); +} + +static int tsens_nvmem_trip_update(struct tsens_device *tmdev, + struct thermal_zone_device *tz) +{ + int i, num_trips = 0; + const struct thermal_trip *trips = NULL; + + if (strnstr(tz->type, "mdmss", sizeof(tz->type)) || + !strnstr(tz->governor->name, "step_wise", + sizeof(tz->governor->name))) + return 0; + + if (!tz->ops->set_trip_temp) { + dev_err(tmdev->dev, "%s: No set_trip_temp ops support for %s\n", + __func__, tz->type); + return -EINVAL; + } + + num_trips = of_thermal_get_ntrips(tz); + trips = of_thermal_get_trip_points(tz); + for (i = 0; i < num_trips; i++) + tsens_thermal_zone_trip_update(tmdev, tz, &trips[i], i); + + return 0; +} + +static bool tsens_is_nvmem_trip_update_needed(struct tsens_device *tmdev) +{ + int ret; + u32 chipinfo, tsens_jtag; + u8 tsens_feat_id; + + if (!of_property_read_bool(tmdev->dev->of_node, "nvmem-cells")) + return false; + + ret = nvmem_cell_read_u32(tmdev->dev, "tsens_chipinfo", &chipinfo); + if (ret) { + dev_err(tmdev->dev, + "%s: Not able to read tsens_chipinfo nvmem, ret:%d\n", + __func__, ret); + return false; + } + + tsens_jtag = chipinfo & GENMASK(19, 0); + tsens_feat_id = (chipinfo >> TSENS_FEAT_OFFSET) & GENMASK(7, 0); + dev_dbg(tmdev->dev, "chipinfo:0x%x tsens_jtag: 0x%x tsens_feat_id:0x%x", + chipinfo, tsens_jtag, tsens_feat_id); + if ((tsens_jtag == TSENS_CHIP_ID0 && tsens_feat_id == TSENS_FEAT_ID3) || + (tsens_jtag == TSENS_CHIP_ID1 && tsens_feat_id == TSENS_FEAT_ID4) || + (tsens_jtag == TSENS_CHIP_ID2 && tsens_feat_id == TSENS_FEAT_ID3) || + (tsens_jtag == TSENS_CHIP_ID3 && tsens_feat_id == TSENS_FEAT_ID2)) + return true; + + return false; +} + static int tsens_thermal_zone_register(struct tsens_device *tmdev) { int i = 0, sensor_missing = 0; + tmdev->need_trip_update = tsens_is_nvmem_trip_update_needed(tmdev); + for (i = 0; i < TSENS_MAX_SENSORS; i++) { tmdev->sensor[i].tmdev = tmdev; tmdev->sensor[i].hw_id = i; @@ -222,6 +309,9 @@ static int tsens_thermal_zone_register(struct tsens_device *tmdev) sensor_missing++; continue; } + if (tmdev->need_trip_update) + tsens_nvmem_trip_update(tmdev, + tmdev->sensor[i].tzd); } else { pr_debug("Sensor not enabled:%d\n", i); } diff --git a/drivers/thermal/tsens.h b/drivers/thermal/tsens.h index ddb7e232aa67..c5479bcee61a 100644 --- a/drivers/thermal/tsens.h +++ b/drivers/thermal/tsens.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef __QCOM_TSENS_H__ @@ -35,6 +36,17 @@ #define TSENS_DRIVER_NAME "msm-tsens" +#define TSENS_FEAT_OFFSET 20 +#define TSENS_CHIP_ID0 0x197 +#define TSENS_CHIP_ID1 0x198 +#define TSENS_CHIP_ID2 0x20e +#define TSENS_CHIP_ID3 0x20f +#define TSENS_FEAT_ID2 0x2 +#define TSENS_FEAT_ID3 0x3 +#define TSENS_FEAT_ID4 0x4 +#define TSENS_ELEVATE_DELTA 10000 +#define TSENS_ELEVATE_CPU_DELTA 5000 + enum tsens_trip_type { TSENS_TRIP_CONFIGURABLE_HI = 4, TSENS_TRIP_CONFIGURABLE_LOW @@ -218,6 +230,7 @@ struct tsens_device { int trdy_fail_ctr; struct tsens_sensor zeroc; u8 zeroc_sensor_id; + bool need_trip_update; struct workqueue_struct *tsens_reinit_work; struct work_struct therm_fwk_notify; bool tsens_reinit_wa; From 525fb1b48fc85dcf0855c0a415b4deed063e85b0 Mon Sep 17 00:00:00 2001 From: Srikanth Marepalli Date: Mon, 6 May 2024 18:08:26 +0530 Subject: [PATCH 02/42] wifi: cfg80211: Increase akm_suites array size in cfg80211_crypto_settings Increase akm_suites array size in struct cfg80211_crypto_settings to 10 and advertise the capability to userspace. This allows userspace to send more than two AKMs to driver in netlink commands such as NL80211_CMD_CONNECT. This capability is needed for implementing WPA3-Personal transition mode correctly with any driver that handles roaming internally. Currently, the possible AKMs for multi-AKM connect can include PSK, PSK-SHA-256, SAE, FT-PSK and FT-SAE. Since the count is already 5, increasing the akm_suites array size to 10 should be reasonable for future usecases. Signed-off-by: Veerendranath Jakkam Link: https://lore.kernel.org/r/1653312358-12321-1-git-send-email-quic_vjakkam@quicinc.com Signed-off-by: Johannes Berg Git-commit: ecad3b0b99bff7247a11f8c7cb19ac9b0cb28b09 Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git. Change-Id: I4ce3de12ec85e11cf30d0b26e2324bc62ab5e73e CRs-Fixed: 3799177 Signed-off-by: Srikanth Marepalli --- drivers/net/wireless/quantenna/qtnfmac/commands.c | 12 ++++++++---- include/net/cfg80211.h | 12 +++++++++++- include/uapi/linux/nl80211.h | 14 ++++++++++++++ net/wireless/core.c | 6 ++++++ net/wireless/nl80211.c | 7 ++++++- 5 files changed, 45 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index 106f1a846f49..9c7f2121970d 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -222,6 +222,7 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif, struct qlink_auth_encr *aen; int ret; int i; + int n; if (!qtnf_cmd_start_ap_can_fit(vif, s)) return -E2BIG; @@ -253,8 +254,9 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif, for (i = 0; i < QLINK_MAX_NR_CIPHER_SUITES; i++) aen->ciphers_pairwise[i] = cpu_to_le32(s->crypto.ciphers_pairwise[i]); - aen->n_akm_suites = cpu_to_le32(s->crypto.n_akm_suites); - for (i = 0; i < QLINK_MAX_NR_AKM_SUITES; i++) + n = min(QLINK_MAX_NR_AKM_SUITES, s->crypto.n_akm_suites); + aen->n_akm_suites = cpu_to_le32(n); + for (i = 0; i < n; i++) aen->akm_suites[i] = cpu_to_le32(s->crypto.akm_suites[i]); aen->control_port = s->crypto.control_port; aen->control_port_no_encrypt = s->crypto.control_port_no_encrypt; @@ -2200,6 +2202,7 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif, struct qlink_auth_encr *aen; int ret; int i; + int n; u32 connect_flags = 0; cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, @@ -2256,9 +2259,10 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif, aen->ciphers_pairwise[i] = cpu_to_le32(sme->crypto.ciphers_pairwise[i]); - aen->n_akm_suites = cpu_to_le32(sme->crypto.n_akm_suites); + n = min(QLINK_MAX_NR_AKM_SUITES, sme->crypto.n_akm_suites); + aen->n_akm_suites = cpu_to_le32(n); - for (i = 0; i < QLINK_MAX_NR_AKM_SUITES; i++) + for (i = 0; i < n; i++) aen->akm_suites[i] = cpu_to_le32(sme->crypto.akm_suites[i]); aen->control_port = sme->crypto.control_port; diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index a076d8ab31ac..02003340baaa 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -903,6 +903,7 @@ struct survey_info { }; #define CFG80211_MAX_WEP_KEYS 4 +#define CFG80211_MAX_NUM_AKM_SUITES 10 /** * struct cfg80211_crypto_settings - Crypto settings @@ -937,7 +938,7 @@ struct cfg80211_crypto_settings { int n_ciphers_pairwise; u32 ciphers_pairwise[NL80211_MAX_NR_CIPHER_SUITES]; int n_akm_suites; - u32 akm_suites[NL80211_MAX_NR_AKM_SUITES]; + u32 akm_suites[CFG80211_MAX_NUM_AKM_SUITES]; bool control_port; __be16 control_port_ethertype; bool control_port_no_encrypt; @@ -4682,6 +4683,13 @@ struct wiphy_iftype_akm_suites { * supported by the driver for each vif * @tid_config_support.peer: bitmap of attributes (configurations) * supported by the driver for each peer + * @max_num_akm_suites: maximum number of AKM suites allowed for + * configuration through %NL80211_CMD_CONNECT, %NL80211_CMD_ASSOCIATE and + * %NL80211_CMD_START_AP. Set to NL80211_MAX_NR_AKM_SUITES if not set by + * driver. If set by driver minimum allowed value is + * NL80211_MAX_NR_AKM_SUITES in order to avoid compatibility issues with + * legacy userspace and maximum allowed value is + * CFG80211_MAX_NUM_AKM_SUITES. */ struct wiphy { /* assign these fields before you register the wiphy */ @@ -4833,6 +4841,8 @@ struct wiphy { u64 peer, vif; } tid_config_support; + u16 max_num_akm_suites; + char priv[0] __aligned(NETDEV_ALIGN); }; diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 05e7a411cfa0..d485d9d3e574 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -2465,6 +2465,13 @@ enum nl80211_commands { * @NL80211_ATTR_HE_6GHZ_CAPABILITY: HE 6 GHz Band Capability element (from * association request when used with NL80211_CMD_NEW_STATION). * + * @NL80211_ATTR_MAX_NUM_AKM_SUITES: U16 attribute. Indicates maximum number of + * AKM suites allowed for %NL80211_CMD_CONNECT, %NL80211_CMD_ASSOCIATE and + * %NL80211_CMD_START_AP in %NL80211_CMD_GET_WIPHY response. If this + * attribute is not present userspace shall consider maximum number of AKM + * suites allowed as %NL80211_MAX_NR_AKM_SUITES which is the legacy maximum + * number prior to the introduction of this attribute. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -2942,6 +2949,8 @@ enum nl80211_attrs { NL80211_ATTR_HE_6GHZ_CAPABILITY, + NL80211_ATTR_MAX_NUM_AKM_SUITES = 316, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -2994,6 +3003,11 @@ enum nl80211_attrs { #define NL80211_HE_MIN_CAPABILITY_LEN 16 #define NL80211_HE_MAX_CAPABILITY_LEN 54 #define NL80211_MAX_NR_CIPHER_SUITES 5 + +/* + * NL80211_MAX_NR_AKM_SUITES is obsolete when %NL80211_ATTR_MAX_NUM_AKM_SUITES + * present in %NL80211_CMD_GET_WIPHY response. + */ #define NL80211_MAX_NR_AKM_SUITES 2 #define NL80211_MIN_REMAIN_ON_CHANNEL_TIME 10 diff --git a/net/wireless/core.c b/net/wireless/core.c index 3983251f2756..e558b71acdfc 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -894,6 +894,12 @@ int wiphy_register(struct wiphy *wiphy) return -EINVAL; #endif + if (!wiphy->max_num_akm_suites) + wiphy->max_num_akm_suites = NL80211_MAX_NR_AKM_SUITES; + else if (wiphy->max_num_akm_suites < NL80211_MAX_NR_AKM_SUITES || + wiphy->max_num_akm_suites > CFG80211_MAX_NUM_AKM_SUITES) + return -EINVAL; + /* check and set up bitrates */ ieee80211_set_bitrate_flags(wiphy); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 5041036d2523..053a1f71f74e 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -656,6 +656,7 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { .type = NLA_EXACT_LEN, .len = sizeof(struct ieee80211_he_6ghz_capa), }, + [NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT }, }; /* policy for the key attributes */ @@ -2574,6 +2575,10 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, if (nl80211_put_tid_config_support(rdev, msg)) goto nla_put_failure; + if (nla_put_u16(msg, NL80211_ATTR_MAX_NUM_AKM_SUITES, + rdev->wiphy.max_num_akm_suites)) + goto nla_put_failure; + /* done */ state->split_start = 0; break; @@ -9377,7 +9382,7 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, if (len % sizeof(u32)) return -EINVAL; - if (settings->n_akm_suites > NL80211_MAX_NR_AKM_SUITES) + if (settings->n_akm_suites > rdev->wiphy.max_num_akm_suites) return -EINVAL; memcpy(settings->akm_suites, data, len); From 68cf8fb263d3b98200e3b3ae141115d753447229 Mon Sep 17 00:00:00 2001 From: Pranay Varma Kopanati Date: Mon, 17 Jun 2024 13:28:38 +0530 Subject: [PATCH 03/42] msm: eva: Adding kref count for cvp_get_inst_from_id Adding count for instance Change-Id: I4505feb478c1c682ecf6a790d7cb804f70e50a1c Signed-off-by: Pranay Varma Kopanati (cherry picked from commit b651124b92285fa644ca3aefe946f0d779b093e6) --- drivers/media/platform/msm/cvp/hfi_response_handler.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/msm/cvp/hfi_response_handler.c b/drivers/media/platform/msm/cvp/hfi_response_handler.c index db857c210f3f..e9d61e382612 100644 --- a/drivers/media/platform/msm/cvp/hfi_response_handler.c +++ b/drivers/media/platform/msm/cvp/hfi_response_handler.c @@ -467,7 +467,7 @@ retry: } } - inst = match ? inst : NULL; + inst = match && kref_get_unless_zero(&inst->kref) ? inst : NULL; mutex_unlock(&core->lock); } else { if (core->state == CVP_CORE_UNINIT) @@ -519,7 +519,7 @@ static int hfi_process_session_cvp_msg(u32 device_id, sess_msg = kmem_cache_alloc(cvp_driver->msg_cache, GFP_KERNEL); if (sess_msg == NULL) { dprintk(CVP_ERR, "%s runs out msg cache memory\n", __func__); - return -ENOMEM; + goto error_no_mem; } memcpy(&sess_msg->pkt, pkt, get_msg_size(pkt)); @@ -542,11 +542,14 @@ static int hfi_process_session_cvp_msg(u32 device_id, info->response_type = HAL_NO_RESP; + cvp_put_inst(inst); return 0; error_handle_msg: spin_unlock(&sq->lock); kmem_cache_free(cvp_driver->msg_cache, sess_msg); +error_no_mem: + cvp_put_inst(inst); return -ENOMEM; } From c6635960b223185ced4cc88c8ebebb12924e8d77 Mon Sep 17 00:00:00 2001 From: Santosh Sakore Date: Tue, 20 Aug 2024 12:31:31 +0530 Subject: [PATCH 04/42] adsprpc: Handle UAF scenario in put_args Currently, the DSP updates header buffers with unused DMA handle fds. In the put_args section, if any DMA handle FDs are present in the header buffer, the corresponding map is freed. However, since the header buffer is exposed to users in unsigned PD, users can update invalid FDs. If this invalid FD matches with any FD that is already in use, it could lead to a use-after-free (UAF) vulnerability. As a solution,add DMA handle references for DMA FDs, and the map for the FD will be freed only when a reference is found. Acked-by: Om Deore Change-Id: I19ae21230bf11fe89858b10c9069a5daccabc392 Signed-off-by: Santosh Sakore (cherry picked from commit c6e7698c0cf35551ab16d16ac5e21e2272644734) --- drivers/char/adsprpc.c | 71 +++++++++++++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 236a22608547..c13641940079 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -584,6 +584,8 @@ struct fastrpc_mmap { struct timespec64 map_end_time; bool is_filemap; /* flag to indicate map used in process init */ unsigned int ctx_refs; /* Indicates reference count for context map */ + /* Map in use for dma handle */ + unsigned int dma_handle_refs; }; enum fastrpc_perfkeys { @@ -1213,9 +1215,14 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, int fd, uintptr_t va, return 0; } hlist_for_each_entry_safe(map, n, &fl->maps, hn) { - /* Remove if only one reference map and no context map */ - if (map->refs == 1 && !map->ctx_refs && - map->raddr == va && map->raddr + map->len == va + len && + if ((fd < 0 || map->fd == fd) && + map->raddr == va && + map->raddr + map->len == va + len && + /* Remove if only one reference map and no context map */ + map->refs == 1 && + !map->ctx_refs && + /* Remove map only if it isn't being used by DSP */ + !map->dma_handle_refs && /* Remove map if not used in process initialization */ !map->is_filemap) { match = map; @@ -1254,8 +1261,9 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags) if (map->flags == ADSP_MMAP_HEAP_ADDR || map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { spin_lock(&me->hlock); - map->refs--; - if (!map->refs && !map->is_persistent && !map->ctx_refs) + if (map->refs) + map->refs--; + if (!map->refs && !map->is_persistent) hlist_del_init(&map->hn); spin_unlock(&me->hlock); if (map->refs > 0) { @@ -1270,8 +1278,13 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags) spin_unlock(&me->hlock); } } else { - map->refs--; - if (!map->refs && !map->ctx_refs) + if (map->refs) + map->refs--; + /* flags is passed as 1 during fastrpc_file_free + * (ie process exit), so that maps will be cleared + * even though references are present. + */ + if (!map->refs && !map->ctx_refs && !map->dma_handle_refs) hlist_del_init(&map->hn); if (map->refs > 0 && !flags) return; @@ -2492,12 +2505,13 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) FASTRPC_ATTR_NOVA, 0, 0, dmaflags, &ctx->maps[i]); if (!err && ctx->maps[i]) - ctx->maps[i]->ctx_refs++; + ctx->maps[i]->dma_handle_refs++; if (err) { for (j = bufs; j < i; j++) { - if (ctx->maps[j] && ctx->maps[j]->ctx_refs) - ctx->maps[j]->ctx_refs--; - fastrpc_mmap_free(ctx->maps[j], 0); + if (ctx->maps[j] && ctx->maps[j]->dma_handle_refs) { + ctx->maps[j]->dma_handle_refs--; + fastrpc_mmap_free(ctx->maps[j], 0); + } } mutex_unlock(&ctx->fl->map_mutex); goto bail; @@ -2635,13 +2649,33 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) rpra[i].buf.pv = buf; } PERF_END); + /* Since we are not holidng map_mutex during get args whole time + * it is possible that dma handle map may be removed by some invalid + * fd passed by DSP. Inside the lock check if the map present or not + */ + mutex_lock(&ctx->fl->map_mutex); for (i = bufs; i < bufs + handles; ++i) { - struct fastrpc_mmap *map = ctx->maps[i]; - if (map) { - pages[i].addr = map->phys; - pages[i].size = map->size; + struct fastrpc_mmap *mmap = NULL; + /* check if map was created */ + if (ctx->maps[i]) { + /* check if map still exist */ + if (!fastrpc_mmap_find(ctx->fl, ctx->fds[i], 0, 0, + 0, 0, &mmap)) { + if (mmap) { + pages[i].addr = mmap->phys; + pages[i].size = mmap->size; + } + + } else { + /* map already freed by some other call */ + mutex_unlock(&ctx->fl->map_mutex); + ADSPRPC_ERR("could not find map associated with dma handle fd %d\n", + ctx->fds[i]); + goto bail; + } } } + mutex_unlock(&ctx->fl->map_mutex); fdlist = (uint64_t *)&pages[bufs + handles]; crclist = (uint32_t *)&fdlist[M_FDLIST]; /* reset fds, crc and early wakeup hint memory */ @@ -2842,9 +2876,10 @@ static int put_args(uint32_t kernel, struct smq_invoke_ctx *ctx, break; if (!fastrpc_mmap_find(ctx->fl, (int)fdlist[i], 0, 0, 0, 0, &mmap)) { - if (mmap && mmap->ctx_refs) - mmap->ctx_refs--; - fastrpc_mmap_free(mmap, 0); + if (mmap && mmap->dma_handle_refs) { + mmap->dma_handle_refs = 0; + fastrpc_mmap_free(mmap, 0); + } } } mutex_unlock(&ctx->fl->map_mutex); From 762e2f518ab2ecc3c8e28f03370d57ea1c0d4073 Mon Sep 17 00:00:00 2001 From: ANANDU KRISHNAN E Date: Tue, 20 Aug 2024 17:21:05 +0530 Subject: [PATCH 05/42] msm: adsprpc: Avoid taking reference for group_info Currently, the get_current_groups API accesses group info, which increases the usage refcount. If the IOCTL using the get_current_groups API is called many times, the usage counter overflows. To avoid this, access group info without taking a reference. A reference is not required as group info is not released during the IOCTL call. Change-Id: Ib4de80cac8b36f73d8f5c6dd9824722153189285 Signed-off-by: ANANDU KRISHNAN E (cherry picked from commit de9f4fe6f82c64f7a2d06d6ecd8d1edd398bf10e) --- drivers/char/adsprpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 236a22608547..0664e70286e3 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -5806,7 +5806,7 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) static int fastrpc_get_process_gids(struct gid_list *gidlist) { - struct group_info *group_info = get_current_groups(); + struct group_info *group_info = current_cred()->group_info; int i = 0, err = 0, num_gids = group_info->ngroups + 1; unsigned int *gids = NULL; From 48d2f3a4c01f54956a655b5749daa6b25f2dc4ad Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Fri, 29 Nov 2024 17:01:56 +0530 Subject: [PATCH 06/42] firmware: qcom_scm: do not clear dump mode from shutdown Do not overwrite download mode to NO dump mode from SCM driver, it is already being done at proper place in qcom-dload-mode driver and writing it here can clean up EDL mode written from qcom-dload-mode. Fix this issue by remove writing no dump mode from SCM driver. Change-Id: Ibfe8b8484dd69ae8386b46c9a53ef42a4a475688 Signed-off-by: Mukesh Ojha --- drivers/firmware/qcom_scm.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 99593aaebacd..96b71bc4cd99 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -1248,8 +1248,6 @@ static void qcom_scm_shutdown(struct platform_device *pdev) { qcom_scm_disable_sdi(); qcom_scm_halt_spmi_pmic_arbiter(); - /* Clean shutdown, disable download mode to allow normal restart */ - qcom_scm_set_download_mode(QCOM_DOWNLOAD_NODUMP, 0); } static const struct of_device_id qcom_scm_dt_match[] = { From c963eba2380d5fe0e98befe89e27b139b12db423 Mon Sep 17 00:00:00 2001 From: Vaibhav Vashisht Date: Sun, 2 Feb 2025 02:13:05 -0800 Subject: [PATCH 07/42] Revert "msm_ipa: Install exception rule for PPPoE-MPLS" This reverts commit 752e583b65efea2b18a10ba685cf722f8f1e4198. Reason for revert: don't install pppoe exceptions rules. This change is reverted to avoid modem crash. With this change dl rules are exceeding the sram partition range and hence modem crashes. This assert/crash introduced by q6 recently to check the dl rules boundary check. Change-Id: I9220efaaa9b0bfa306758d35603cfb2dff042714 Signed-off-by: Vaibhav Vashisht --- include/uapi/linux/msm_ipa.h | 47 ++---------------------------------- 1 file changed, 2 insertions(+), 45 deletions(-) diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h index 8d2bb198379d..f63134040753 100644 --- a/include/uapi/linux/msm_ipa.h +++ b/include/uapi/linux/msm_ipa.h @@ -2,7 +2,7 @@ /* * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. * - * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _UAPI_MSM_IPA_H_ @@ -1140,48 +1140,6 @@ static inline const char *exception_type_as_str(enum ipa_exception_type t) "???"; } -/** - * Macro ipa_exception_type_pppoe - * - * This macro is for describing which field is to be looked at for - * exception path consideration. - * - * NOTE 1: The field implies an offset into the packet under - * consideration. This offset will be calculated on behalf of - * the user of this API. - * - * NOTE 2: When exceptions are generated/sent in an ipa_exception - * structure, they will considered to be from the upload - * perspective. And when appropriate, a corresponding, and - * perhaps inverted, downlink exception will be automatically - * created on the callers behalf. As an example: If a - * FIELD_UDP_SRC_PORT is sent, an uplink exception will be - * created for udp source port, and a corresponding - * FIELD_UDP_DST_PORT will be automatically created for the - * downlink. - */ -#define FIELD_IP_PROTOCOL_PPPOE (FIELD_ETHER_TYPE + 1) -#define FIELD_TCP_SRC_PORT_PPPOE (FIELD_IP_PROTOCOL_PPPOE + 1) -#define FIELD_TCP_DST_PORT_PPPOE (FIELD_TCP_SRC_PORT_PPPOE + 1) -#define FIELD_UDP_SRC_PORT_PPPOE (FIELD_TCP_DST_PORT_PPPOE + 1) -#define FIELD_UDP_DST_PORT_PPPOE (FIELD_UDP_SRC_PORT_PPPOE + 1) -#define FIELD_ETHER_TYPE_PPPOE (FIELD_UDP_DST_PORT_PPPOE + 1) -#define FIELD_PPPOE_MAX (FIELD_ETHER_TYPE_PPPOE + 1) - -/* Function to read PPPoE exception in string format */ -static inline const char *pppoe_exception_type_as_str(uint32_t t) -{ - return - (t == FIELD_IP_PROTOCOL_PPPOE) ? "pppoe_ip_protocol" : - (t == FIELD_TCP_SRC_PORT_PPPOE) ? "pppoe_tcp_src_port" : - (t == FIELD_TCP_DST_PORT_PPPOE) ? "pppoe_tcp_dst_port" : - (t == FIELD_UDP_SRC_PORT_PPPOE) ? "pppoe_udp_src_port" : - (t == FIELD_UDP_DST_PORT_PPPOE) ? "pppoe_udp_dst_port" : - (t == FIELD_ETHER_TYPE_PPPOE) ? "pppoe_ether_type" : - (t == FIELD_PPPOE_MAX) ? "pppoe_max" : - "???"; -} - #define IP_TYPE_EXCEPTION(x) \ ((x) == FIELD_IP_PROTOCOL || \ (x) == FIELD_TCP_SRC_PORT || \ @@ -1262,7 +1220,6 @@ struct ipa_field_val_equation_gen { * @payload_length: Payload length. * @ext_attrib_mask: Extended attributes. * @l2tp_udp_next_hdr: next header in L2TP tunneling - * @p_exception : exception to enable for mpls-pppoe * @field_val_equ: for finding a value at a particular offset */ struct ipa_rule_attrib { @@ -1308,7 +1265,7 @@ struct ipa_rule_attrib { __u16 payload_length; __u32 ext_attrib_mask; __u8 l2tp_udp_next_hdr; - __u8 p_exception; + __u8 padding1; struct ipa_field_val_equation_gen fld_val_eq; }; From 064a6285fcf6ad94095aa60d7fcf5c9febf6e577 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 13 Mar 2025 23:22:48 +0530 Subject: [PATCH 08/42] FROMGIT: media: venus: hfi_parser: add check to avoid out of bound access There is a possibility that init_codecs is invoked multiple times during manipulated payload from video firmware. In such case, if codecs_count can get incremented to value more than MAX_CODEC_NUM, there can be OOB access. Reset the count so that it always starts from beginning. Cc: stable@vger.kernel.org Fixes: 1a73374a04e5 ("media: venus: hfi_parser: add common capability parser") Reviewed-by: Bryan O'Donoghue CRs-Fixed: 3935643 Change-Id: I6216e773af65082e4775b415789ffd549e0bed2d Git-commit: 172bf5a9ef70a399bb227809db78442dc01d9e48 Git-repo: https://gitlab.freedesktop.org/linux-media/media-committers.git Signed-off-by: Vikash Garodia --- drivers/media/platform/qcom/venus/hfi_parser.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/qcom/venus/hfi_parser.c b/drivers/media/platform/qcom/venus/hfi_parser.c index ad22b51765d4..6a8259bcf0be 100644 --- a/drivers/media/platform/qcom/venus/hfi_parser.c +++ b/drivers/media/platform/qcom/venus/hfi_parser.c @@ -19,6 +19,8 @@ static void init_codecs(struct venus_core *core) struct venus_caps *caps = core->caps, *cap; unsigned long bit; + core->codecs_count = 0; + if (hweight_long(core->dec_codecs) + hweight_long(core->enc_codecs) > MAX_CODEC_NUM) return; From 45e1a910b657c514b5c3974f16db0b32c48cd7e8 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Tue, 5 Nov 2024 14:24:56 +0530 Subject: [PATCH 09/42] FROMGIT: media: venus: hfi: add check to handle incorrect queue size qsize represents size of shared queued between driver and video firmware. Firmware can modify this value to an invalid large value. In such situation, empty_space will be bigger than the space actually available. Since new_wr_idx is not checked, so the following code will result in an OOB write. ... qsize = qhdr->q_size if (wr_idx >= rd_idx) empty_space = qsize - (wr_idx - rd_idx) .... if (new_wr_idx < qsize) { memcpy(wr_ptr, packet, dwords << 2) --> OOB write Add check to ensure qsize is within the allocated size while reading and writing packets into the queue. Cc: stable@vger.kernel.org Fixes: d96d3f30c0f2 ("[media] media: venus: hfi: add Venus HFI files") Reviewed-by: Bryan O'Donoghue CRs-Fixed: 3935673 Change-Id: Ifb907d4a4c82f853081492e06e68180476367ed5 Git-commit: 69baf245b23e20efda0079238b27fc63ecf13de1 Git-repo: https://gitlab.freedesktop.org/linux-media/media-committers.git Signed-off-by: Vikash Garodia --- drivers/media/platform/qcom/venus/hfi_venus.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index 306082e25943..2921486c3238 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -188,6 +188,9 @@ static int venus_write_queue(struct venus_hfi_device *hdev, /* ensure rd/wr indices's are read from memory */ rmb(); + if (qsize > IFACEQ_QUEUE_SIZE / 4) + return -EINVAL; + if (wr_idx >= rd_idx) empty_space = qsize - (wr_idx - rd_idx); else @@ -256,6 +259,9 @@ static int venus_read_queue(struct venus_hfi_device *hdev, wr_idx = qhdr->write_idx; qsize = qhdr->q_size; + if (qsize > IFACEQ_QUEUE_SIZE / 4) + return -EINVAL; + /* make sure data is valid before using it */ rmb(); From d15a6a8a95bf7b73cea1e5d7f7f8f348bbc8e22c Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Tue, 5 Nov 2024 14:24:57 +0530 Subject: [PATCH 10/42] FROMGIT: media: venus: hfi: add a check to handle OOB in sfr region sfr->buf_size is in shared memory and can be modified by malicious user. OOB write is possible when the size is made higher than actual sfr data buffer. Cap the size to allocated size for such cases. Cc: stable@vger.kernel.org Fixes: d96d3f30c0f2 ("[media] media: venus: hfi: add Venus HFI files") Reviewed-by: Bryan O'Donoghue CRs-Fixed: 3947576 Change-Id: I483a5feff3dfa35dae8f444e57601d2d1d85246f Git-commit: f4b211714bcc70effa60c34d9fa613d182e3ef1e Git-repo: https://gitlab.freedesktop.org/linux-media/media-committers.git Signed-off-by: Vikash Garodia --- drivers/media/platform/qcom/venus/hfi_venus.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index 306082e25943..0b6cf86004fd 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -970,18 +970,26 @@ static void venus_sfr_print(struct venus_hfi_device *hdev) { struct device *dev = hdev->core->dev; struct hfi_sfr *sfr = hdev->sfr.kva; + u32 size; void *p; if (!sfr) return; - p = memchr(sfr->data, '\0', sfr->buf_size); + size = sfr->buf_size; + if (!size) + return; + + if (size > ALIGNED_SFR_SIZE) + size = ALIGNED_SFR_SIZE; + + p = memchr(sfr->data, '\0', size); /* * SFR isn't guaranteed to be NULL terminated since SYS_ERROR indicates * that Venus is in the process of crashing. */ if (!p) - sfr->data[sfr->buf_size - 1] = '\0'; + sfr->data[size - 1] = '\0'; dev_err_ratelimited(dev, "SFR message from FW: %s\n", sfr->data); } From b0eaa6a4e4bb039700dd752bf8779121601dda80 Mon Sep 17 00:00:00 2001 From: Sumit Kumar Date: Thu, 7 Nov 2024 11:31:17 +0530 Subject: [PATCH 11/42] msm: ep_pcie: Wake host in D3cold handling if wake is pending In below sequence where device requested for inband pme but host still proceed with #PERST assertion the ep_pcie_core_wakeup_host_internal is called to toggle wake gpio. Event Sequence: - Received a wakeup_host event in D3hot. - wakeup host internal api called -> inband pme issued - host_wake_pending set to 1 - host is in process of issuing a perst assert before the inband pme is processed - disable endpoint is called -> checks for host wake pending and and calls ep_pcie_core_wakeup_host_internal. - ep_pcie_core_wakeup_host_internal will return without doing a wakeup because of host wake pending check in it. Set the host_wake_pending flag to 0 before calling to make sure ep_pcie_core_wakeup_host_internal is executed to toggle WAKE. Change-Id: I533b7ee58ea941d9a865fc560677aa9a8daa431c Signed-off-by: Sumit Kumar --- drivers/platform/msm/ep_pcie/ep_pcie_core.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_core.c b/drivers/platform/msm/ep_pcie/ep_pcie_core.c index c8e23ac53d2f..cef10b457073 100644 --- a/drivers/platform/msm/ep_pcie/ep_pcie_core.c +++ b/drivers/platform/msm/ep_pcie/ep_pcie_core.c @@ -2179,6 +2179,11 @@ int ep_pcie_core_disable_endpoint(void) if (atomic_read(&dev->host_wake_pending)) { EP_PCIE_DBG(dev, "PCIe V%d: wake pending, init wakeup\n", dev->rev); + /* + * Clear the wake pending otherwise ep_pcie_core_wakeup_host_internal + * will return without WAKE toggle + */ + atomic_set(&dev->host_wake_pending, 0); ep_pcie_core_wakeup_host_internal(EP_PCIE_EVENT_PM_D3_COLD); } From a92f0801342cc994313500c29ffa62c0d4b49c2c Mon Sep 17 00:00:00 2001 From: Sumit Kumar Date: Mon, 7 Oct 2024 11:41:50 +0530 Subject: [PATCH 12/42] msm: mhi_dev: Handle host wakeup in M3/D0 When a MHI WAKE request (that is request to bring MHI from M3 to M0) is received while device is in D0, this request is being dropped as there is no way to notify host about this event. This is leading to failure at client drivers as they unable to wakeup mhi and perform write operation. Fix the issue by waiting for D3hot in MHI before sending the wake request: - If M0 is received while waiting, exit the function. - If D3hot/D3cold is received, send the wake request. - Else return failure. Increase the timeout value of mhi_dev_write_channel() from 2s to 2.5s to accommodate the waiting time for D state transition to D3hot/D3cold. Change-Id: Idd58bb664d31bc1e5615119284c6cba924fe17b6 Signed-off-by: Sumit Kumar --- drivers/platform/msm/mhi_dev/mhi.c | 2 +- drivers/platform/msm/mhi_dev/mhi_sm.c | 34 ++++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c index d7d9ecad8d73..141ce1157e9c 100644 --- a/drivers/platform/msm/mhi_dev/mhi.c +++ b/drivers/platform/msm/mhi_dev/mhi.c @@ -39,7 +39,7 @@ /* Wait time on the device for Host to set BHI_INTVEC */ #define MHI_BHI_INTVEC_MAX_CNT 200 #define MHI_BHI_INTVEC_WAIT_MS 50 -#define MHI_WAKEUP_TIMEOUT_CNT 20 +#define MHI_WAKEUP_TIMEOUT_CNT 25 #define MHI_MASK_CH_EV_LEN 32 #define MHI_RING_CMD_ID 0 #define MHI_RING_PRIMARY_EVT_ID 1 diff --git a/drivers/platform/msm/mhi_dev/mhi_sm.c b/drivers/platform/msm/mhi_dev/mhi_sm.c index 89190bfeadfc..ba8c9a19136e 100644 --- a/drivers/platform/msm/mhi_dev/mhi_sm.c +++ b/drivers/platform/msm/mhi_dev/mhi_sm.c @@ -12,6 +12,7 @@ #include "mhi_hwio.h" #include "mhi_sm.h" #include +#include #define MHI_SM_DBG(fmt, args...) \ mhi_log(MHI_MSG_DBG, fmt, ##args) @@ -28,6 +29,8 @@ #define PCIE_EP_TIMER_US 500000000 #define MHI_IPA_DISABLE_DELAY_MS 10 #define MHI_IPA_DISABLE_COUNTER 20 +/* Maximum wait time for D state transitions to D3hot */ +#define M3_DO_WAKEUP_TIMEOUT_MS 2500 static inline const char *mhi_sm_dev_event_str(enum mhi_dev_event state) @@ -734,7 +737,7 @@ exit: * mhi_sm_wakeup_host() - wakeup MHI-host *@event: MHI state chenge event * - * Sends wekup event to MHI-host via EP-PCIe, in case MHI is in M3 state. + * Sends wakeup event to MHI-host via EP-PCIe, in case MHI is in M3 state. * * Return: 0:success * negative: failure @@ -742,6 +745,7 @@ exit: static int mhi_sm_wakeup_host(enum mhi_dev_event event) { int res = 0; + int timeout = 0; enum ep_pcie_event pcie_event; MHI_SM_FUNC_ENTRY(); @@ -753,9 +757,33 @@ static int mhi_sm_wakeup_host(enum mhi_dev_event event) MHI_SM_ERR("Failed switching to M0 state\n"); } else if (mhi_sm_ctx->mhi_state == MHI_DEV_M3_STATE) { /* - * Check and send D3_HOT to enable waking up the host - * using inband PME. + * Handle host wakeup in M3 + D0 states. + * + * When a MHI WAKE request is received while device is in D0, + * wait for D3 and wakeup the host using inband PME. + * If the MHI state changes to M0 while waiting for D3, + * exit, since both MHI and the device are in active state. */ + if (mhi_sm_ctx->d_state == MHI_SM_EP_PCIE_D0_STATE) { + timeout = ktime_add_ms(ktime_get(), M3_DO_WAKEUP_TIMEOUT_MS); + while (1) { + /* Received M0 */ + if (mhi_sm_ctx->mhi_state == MHI_DEV_M0_STATE) + goto exit; + /* Received D3 state */ + if (mhi_sm_ctx->d_state == MHI_SM_EP_PCIE_D3_HOT_STATE || + mhi_sm_ctx->d_state == MHI_SM_EP_PCIE_D3_COLD_STATE) + goto wakeup_host; + if (ktime_after(ktime_get(), timeout)) { + MHI_SM_ERR(mhi->vf_id, + "M3, D0 wakeup host is not supported %d\n", res); + goto exit; + } + usleep_range(1000, 2000); + } + } +wakeup_host: + /* Received D3hot or D3cold, send the wakeup request */ if (mhi_sm_ctx->d_state == MHI_SM_EP_PCIE_D3_HOT_STATE) pcie_event = EP_PCIE_EVENT_PM_D3_HOT; else From 66731738f257de083021edd22726080c515bfb9a Mon Sep 17 00:00:00 2001 From: Vijayanand Jitta Date: Sun, 16 Feb 2025 23:56:49 +0530 Subject: [PATCH 13/42] iommu: Fix invalid access in av8l_fast_unmap_public KASAN has reported the following invalid access in av8l_fast_unmap_public. This is because while calculating pmd offset, base is subtracted from iova, in case if iova is less than base it would result in underflow, thereby resulting in an invalid access. BUG: KASAN: wild-memory-access in av8l_fast_unmap_public+0x60/0x88 [qcom_iommu_util] Write of size 8 at addr 007fffc084480000 by task syz.1.693/6987 Call trace: dump_backtrace+0x1b0/0x1e0 show_stack+0x2c/0x40 dump_stack_lvl+0xd0/0x128 print_report+0xe4/0x6f8 kasan_report+0xe8/0x148 kasan_check_range+0x250/0x294 __asan_memset+0x34/0x68 av8l_fast_unmap_public+0x60/0x88 fast_smmu_unmap_page+0x1cc/0x244 dma_unmap_page_attrs+0xa4/0x3a0 geni_i2c_xfer+0x4a24/0x6154 __i2c_transfer+0x488/0x147c i2c_transfer+0x174/0x21c i2cdev_ioctl_rdwr+0x22c/0x44c i2cdev_ioctl+0x628/0x700 __arm64_sys_ioctl+0x110/0x18c invoke_syscall+0x88/0x1cc el0_svc_common+0xe4/0x1b0 Fix this by adding a check and returning error when iova is less than base. Fixes: Ie6c23cb8e17 ("iommu/io-pgtable-fast: optimize statically allocated pages") Change-Id: I4e3a585d348d897e51888a898c8e64c51c9f46c3 Signed-off-by: Vijayanand Jitta Signed-off-by: Srinivasarao Pathipati --- drivers/iommu/dma-mapping-fast.c | 19 +++++++++++++--- drivers/iommu/io-pgtable-fast.c | 37 +++++++++++++++++++++++++++++--- include/linux/io-pgtable-fast.h | 5 +++-- 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/dma-mapping-fast.c b/drivers/iommu/dma-mapping-fast.c index 3dbaef99d89c..947ba3ca140d 100644 --- a/drivers/iommu/dma-mapping-fast.c +++ b/drivers/iommu/dma-mapping-fast.c @@ -244,8 +244,12 @@ static void fast_smmu_unmap_page(struct device *dev, dma_addr_t iova, } spin_lock_irqsave(&mapping->lock, flags); - av8l_fast_unmap_public(mapping->pgtbl_ops, iova, len); + + if (unlikely(!av8l_fast_unmap_public(mapping->pgtbl_ops, iova, len))) + goto fail; + __fast_smmu_free_iova(mapping, iova, len); +fail: spin_unlock_irqrestore(&mapping->lock, flags); trace_unmap(to_msm_iommu_domain(mapping->domain), iova - offset, len, @@ -385,7 +389,8 @@ static void fast_smmu_unmap_sg(struct device *dev, len = ALIGN(sg_dma_address(sg) + sg_dma_len(sg) - (start - offset), FAST_PAGE_SIZE); - av8l_fast_unmap_public(mapping->pgtbl_ops, start, len); + if (unlikely(!av8l_fast_unmap_public(mapping->pgtbl_ops, start, len))) + return; spin_lock_irqsave(&mapping->lock, flags); __fast_smmu_free_iova(mapping, start, len); @@ -653,7 +658,10 @@ static void fast_smmu_free(struct device *dev, size_t size, size = ALIGN(size, FAST_PAGE_SIZE); spin_lock_irqsave(&mapping->lock, flags); - av8l_fast_unmap_public(mapping->pgtbl_ops, dma_handle, size); + + if (unlikely(!av8l_fast_unmap_public(mapping->pgtbl_ops, dma_handle, size))) + goto fail; + __fast_smmu_free_iova(mapping, dma_handle, size); spin_unlock_irqrestore(&mapping->lock, flags); @@ -674,6 +682,11 @@ static void fast_smmu_free(struct device *dev, size_t size, if (page) dma_free_contiguous(dev, page, size); + + return; + +fail: + spin_unlock_irqrestore(&mapping->lock, flags); } static int fast_smmu_mmap_attrs(struct device *dev, struct vm_area_struct *vma, diff --git a/drivers/iommu/io-pgtable-fast.c b/drivers/iommu/io-pgtable-fast.c index a9159c012106..f07e93b33f05 100644 --- a/drivers/iommu/io-pgtable-fast.c +++ b/drivers/iommu/io-pgtable-fast.c @@ -127,7 +127,14 @@ #define PTE_SH_IDX(pte) (pte & AV8L_FAST_PTE_SH_MASK) -#define iopte_pmd_offset(pmds, base, iova) (pmds + ((iova - base) >> 12)) +#define iopte_pmd_offset(pmds, base, iova) \ +({ \ + typeof(iova) __iova = (iova); \ + typeof(base) __base = (base); \ + typeof(pmds) __pmds = (pmds); \ + (__iova < __base) ? ERR_PTR(-EINVAL) : \ + __pmds + ((__iova - __base) >> AV8L_FAST_PAGE_SHIFT); \ +}) static inline dma_addr_t av8l_dma_addr(void *addr) { @@ -202,6 +209,12 @@ void av8l_fast_clear_stale_ptes(struct io_pgtable_ops *ops, u64 base, struct io_pgtable *iop = iof_pgtable_ops_to_pgtable(ops); av8l_fast_iopte *pmdp = iopte_pmd_offset(data->pmds, data->base, base); + if (IS_ERR(pmdp)) { + pr_err("Invalid iova : 0x%lx, as it is less than base : 0x%llx\n", + iova, data->base); + return; + } + for (i = base >> AV8L_FAST_PAGE_SHIFT; i <= (end >> AV8L_FAST_PAGE_SHIFT); ++i) { if (!(*pmdp & AV8L_FAST_PTE_VALID)) { @@ -254,6 +267,12 @@ static int av8l_fast_map(struct io_pgtable_ops *ops, unsigned long iova, unsigned long i, nptes = size >> AV8L_FAST_PAGE_SHIFT; av8l_fast_iopte pte; + if (IS_ERR(ptep)) { + pr_err("Invalid iova : 0x%lx, as it is less than base : 0x%llx\n", + iova, data->base); + return -EINVAL; + } + pte = av8l_fast_prot_to_pte(data, prot); paddr &= AV8L_FAST_PTE_ADDR_MASK; for (i = 0; i < nptes; i++, paddr += SZ_4K) { @@ -286,6 +305,12 @@ __av8l_fast_unmap(struct io_pgtable_ops *ops, unsigned long iova, ptep = iopte_pmd_offset(data->pmds, data->base, iova); nptes = size >> AV8L_FAST_PAGE_SHIFT; + if (IS_ERR(ptep)) { + pr_err("Invalid iova : 0x%lx, as it is less than base : 0x%llx\n", + iova, data->base); + return 0; + } + memset(ptep, val, sizeof(*ptep) * nptes); av8l_clean_range(&iop->cfg, ptep, ptep + nptes); if (!allow_stale_tlb) @@ -295,10 +320,10 @@ __av8l_fast_unmap(struct io_pgtable_ops *ops, unsigned long iova, } /* caller must take care of tlb cache maintenance */ -void av8l_fast_unmap_public(struct io_pgtable_ops *ops, unsigned long iova, +size_t av8l_fast_unmap_public(struct io_pgtable_ops *ops, unsigned long iova, size_t size) { - __av8l_fast_unmap(ops, iova, size, true); + return __av8l_fast_unmap(ops, iova, size, true); } static size_t av8l_fast_unmap(struct io_pgtable_ops *ops, unsigned long iova, @@ -383,6 +408,12 @@ static bool av8l_fast_iova_coherent(struct io_pgtable_ops *ops, struct av8l_fast_io_pgtable *data = iof_pgtable_ops_to_data(ops); av8l_fast_iopte *ptep = iopte_pmd_offset(data->pmds, data->base, iova); + if (IS_ERR(ptep)) { + pr_err("Invalid iova : 0x%lx, as it is less than base : 0x%llx\n", + iova, data->base); + return false; + } + return ((PTE_MAIR_IDX(*ptep) == AV8L_FAST_MAIR_ATTR_IDX_CACHE) && ((PTE_SH_IDX(*ptep) == AV8L_FAST_PTE_SH_OS) || (PTE_SH_IDX(*ptep) == AV8L_FAST_PTE_SH_IS))); diff --git a/include/linux/io-pgtable-fast.h b/include/linux/io-pgtable-fast.h index 245f86fbbe46..95b05a85f61c 100644 --- a/include/linux/io-pgtable-fast.h +++ b/include/linux/io-pgtable-fast.h @@ -44,7 +44,7 @@ struct av8l_fast_io_pgtable { int av8l_fast_map_public(struct io_pgtable_ops *ops, unsigned long iova, phys_addr_t paddr, size_t size, int prot); -void av8l_fast_unmap_public(struct io_pgtable_ops *ops, unsigned long iova, +size_t av8l_fast_unmap_public(struct io_pgtable_ops *ops, unsigned long iova, size_t size); int av8l_fast_map_sg_public(struct io_pgtable_ops *ops, @@ -63,9 +63,10 @@ av8l_fast_map_public(struct io_pgtable_ops *ops, unsigned long iova, { return -EINVAL; } -static inline void av8l_fast_unmap_public(struct io_pgtable_ops *ops, +static inline size_t av8l_fast_unmap_public(struct io_pgtable_ops *ops, unsigned long iova, size_t size) { + return 0; } static inline int av8l_fast_map_sg_public(struct io_pgtable_ops *ops, From 90f5b1c30a0a376efc5a35d816618c48fea0f9b9 Mon Sep 17 00:00:00 2001 From: Sumit Kumar Date: Fri, 3 Jan 2025 17:04:10 +0530 Subject: [PATCH 14/42] msm: mhi_dev: Workqueue to handle host wakeup in M3+D0 After the change ("msm: mhi_dev: Handle host wakeup in M3/D0"), if a wakeup host request is received during M3+D0, wait for D3 hot/cold before sending the host wakeup request inside a mutex lock. Regression: In mhi_sm_dev_event_manager, the mhi_sm_ctx->mhi_state_lock mutex is held while calling mhi_sm_wakeup_host. This means waiting for mhi_sm_ctx->d_state to transition to MHI_SM_EP_PCIE_D3_HOT_STATE or MHI_SM_EP_PCIE_D3_COLD_STATE with the lock held. This prevents mhi_sm_pcie_event_manager from processing the D3 hot/cold event because it also waits for the same lock. Create a separate workqueue to wait for D3 hot/cold before waking up the host if a wakeup request is received in M3+D0. Change-Id: I1d3eff63b1968f5ded0d0c84a0fa71e893d74d45 Signed-off-by: Sumit Kumar --- drivers/platform/msm/mhi_dev/mhi_sm.c | 118 +++++++++++++++++--------- drivers/platform/msm/mhi_dev/mhi_sm.h | 1 - 2 files changed, 77 insertions(+), 42 deletions(-) diff --git a/drivers/platform/msm/mhi_dev/mhi_sm.c b/drivers/platform/msm/mhi_dev/mhi_sm.c index ba8c9a19136e..e8d9300c7812 100644 --- a/drivers/platform/msm/mhi_dev/mhi_sm.c +++ b/drivers/platform/msm/mhi_dev/mhi_sm.c @@ -32,6 +32,8 @@ /* Maximum wait time for D state transitions to D3hot */ #define M3_DO_WAKEUP_TIMEOUT_MS 2500 +static void wait_d3_and_wakeup(struct work_struct *work); +static int mhi_dev_sm_get_mhi_pcie_states(uint32_t *mstate, uint32_t *dstate); static inline const char *mhi_sm_dev_event_str(enum mhi_dev_event state) { @@ -238,6 +240,8 @@ struct mhi_sm_dev { struct mutex mhi_state_lock; bool syserr_occurred; struct workqueue_struct *mhi_sm_wq; + struct workqueue_struct *mhi_wake_wq; + struct work_struct mhi_wake_work; atomic_t pending_device_events; atomic_t pending_pcie_events; struct mhi_sm_stats stats; @@ -742,10 +746,9 @@ exit: * Return: 0:success * negative: failure */ -static int mhi_sm_wakeup_host(enum mhi_dev_event event) +static int mhi_sm_wakeup_host(void) { int res = 0; - int timeout = 0; enum ep_pcie_event pcie_event; MHI_SM_FUNC_ENTRY(); @@ -757,33 +760,10 @@ static int mhi_sm_wakeup_host(enum mhi_dev_event event) MHI_SM_ERR("Failed switching to M0 state\n"); } else if (mhi_sm_ctx->mhi_state == MHI_DEV_M3_STATE) { /* - * Handle host wakeup in M3 + D0 states. - * - * When a MHI WAKE request is received while device is in D0, - * wait for D3 and wakeup the host using inband PME. - * If the MHI state changes to M0 while waiting for D3, - * exit, since both MHI and the device are in active state. + * Check and send D3_HOT to enable waking up the host + * using inband PME if the host is in D3_HOT state, otherwise + * send D3_COLD to wake up the host. */ - if (mhi_sm_ctx->d_state == MHI_SM_EP_PCIE_D0_STATE) { - timeout = ktime_add_ms(ktime_get(), M3_DO_WAKEUP_TIMEOUT_MS); - while (1) { - /* Received M0 */ - if (mhi_sm_ctx->mhi_state == MHI_DEV_M0_STATE) - goto exit; - /* Received D3 state */ - if (mhi_sm_ctx->d_state == MHI_SM_EP_PCIE_D3_HOT_STATE || - mhi_sm_ctx->d_state == MHI_SM_EP_PCIE_D3_COLD_STATE) - goto wakeup_host; - if (ktime_after(ktime_get(), timeout)) { - MHI_SM_ERR(mhi->vf_id, - "M3, D0 wakeup host is not supported %d\n", res); - goto exit; - } - usleep_range(1000, 2000); - } - } -wakeup_host: - /* Received D3hot or D3cold, send the wakeup request */ if (mhi_sm_ctx->d_state == MHI_SM_EP_PCIE_D3_HOT_STATE) pcie_event = EP_PCIE_EVENT_PM_D3_HOT; else @@ -934,9 +914,7 @@ static void mhi_sm_dev_event_manager(struct work_struct *work) break; case MHI_DEV_EVENT_HW_ACC_WAKEUP: case MHI_DEV_EVENT_CORE_WAKEUP: - res = mhi_sm_wakeup_host(chg_event->event); - if (res) - MHI_SM_ERR("Failed to wakeup MHI host\n"); + queue_work(mhi_sm_ctx->mhi_wake_wq, &mhi_sm_ctx->mhi_wake_work); break; case MHI_DEV_EVENT_CTRL_TRIG: case MHI_DEV_EVENT_M1_STATE: @@ -1147,9 +1125,19 @@ int mhi_dev_sm_init(struct mhi_dev *mhi_dev) if (!mhi_sm_ctx->mhi_sm_wq) { MHI_SM_ERR("Failed to create singlethread_workqueue: sm_wq\n"); res = -ENOMEM; - goto fail_init_wq; + goto fail_init_sm_wq; } + if (!mhi_sm_ctx->mhi_wake_wq) + mhi_sm_ctx->mhi_wake_wq = alloc_workqueue( + "mhi_wake_wq", WQ_HIGHPRI | WQ_UNBOUND, 1); + if (!mhi_sm_ctx->mhi_wake_wq) { + MHI_SM_ERR("Failed to create singlethread_workqueue: wake_wq\n"); + res = -ENOMEM; + goto fail_init_wake_wq; + } + INIT_WORK(&mhi_sm_ctx->mhi_wake_work, wait_d3_and_wakeup); + mutex_init(&mhi_sm_ctx->mhi_state_lock); mhi_sm_ctx->mhi_dev = mhi_dev; mhi_sm_ctx->mhi_state = MHI_DEV_RESET_STATE; @@ -1162,7 +1150,10 @@ int mhi_dev_sm_init(struct mhi_dev *mhi_dev) MHI_SM_FUNC_EXIT(); return 0; -fail_init_wq: +fail_init_wake_wq: + flush_workqueue(mhi_sm_ctx->mhi_sm_wq); + destroy_workqueue(mhi_sm_ctx->mhi_sm_wq); +fail_init_sm_wq: mhi_sm_ctx = NULL; mhi_sm_debugfs_destroy(); return res; @@ -1190,20 +1181,20 @@ int mhi_dev_sm_exit(struct mhi_dev *mhi_dev) EXPORT_SYMBOL(mhi_dev_sm_exit); /** - * mhi_dev_sm_get_mhi_state() -Get current MHI state. + * mhi_dev_sm_get_mhi_pcie_states() -Get current MHI and Pcie states. * @state: return param * - * Returns the current MHI state of the state machine. + * Returns the current MHI and PCIe states of the state machine. * * Return: 0 success * -EINVAL: invalid param * -EFAULT: state machine isn't initialized */ -int mhi_dev_sm_get_mhi_state(enum mhi_dev_state *state) +static int mhi_dev_sm_get_mhi_pcie_states(uint32_t *mstate, uint32_t *dstate) { MHI_SM_FUNC_ENTRY(); - if (!state) { + if (!mstate || !dstate) { MHI_SM_ERR("Fail: Null argument\n"); return -EINVAL; } @@ -1211,15 +1202,60 @@ int mhi_dev_sm_get_mhi_state(enum mhi_dev_state *state) MHI_SM_ERR("Fail: MHI SM is not initialized\n"); return -EFAULT; } - *state = mhi_sm_ctx->mhi_state; + mutex_lock(&mhi_sm_ctx->mhi_state_lock); + *mstate = mhi_sm_ctx->mhi_state; + *dstate = mhi_sm_ctx->d_state; + mutex_unlock(&mhi_sm_ctx->mhi_state_lock); MHI_SM_DBG("state machine states are: %s and %s\n", - mhi_sm_mstate_str(*state), - mhi_sm_dstate_str(mhi_sm_ctx->d_state)); + mhi_sm_mstate_str(*mstate), + mhi_sm_dstate_str(*dstate)); MHI_SM_FUNC_EXIT(); return 0; } -EXPORT_SYMBOL(mhi_dev_sm_get_mhi_state); + +static void wait_d3_and_wakeup(struct work_struct *work) +{ + struct mhi_sm_dev *mhi_sm_ctx = container_of(work, struct mhi_sm_dev, mhi_wake_work); + enum mhi_dev_state mstate; + enum mhi_sm_ep_pcie_state dstate; + ktime_t timeout = 0; + + if (mhi_dev_sm_get_mhi_pcie_states(&mstate, &dstate)) { + MHI_SM_ERR("Unable to read states\n"); + return; + } + /* + * Handle host wakeup in M3 + D0 states. + * When a MHI WAKE request is received while device is in D0, + * wait for D3 and wakeup the host using inband PME. + * If the MHI state changes to M0 while waiting for D3, + * exit, since both MHI and the device are in active state + */ + if (dstate == MHI_SM_EP_PCIE_D0_STATE) { + timeout = ktime_add_ms(ktime_get(), M3_DO_WAKEUP_TIMEOUT_MS); + while (1) { + mhi_dev_sm_get_mhi_pcie_states(&mstate, &dstate); + if (mstate == MHI_DEV_M0_STATE) { + MHI_SM_DBG("M0 state received\n"); + return; + } + if (dstate == MHI_SM_EP_PCIE_D3_HOT_STATE || + dstate == MHI_SM_EP_PCIE_D3_COLD_STATE) { + MHI_SM_DBG("D3 state received\n"); + goto send_host_wakeup; + } + if (ktime_after(ktime_get(), timeout)) { + MHI_SM_ERR("Neither received D3 nor M0 in stipulated time\n"); + return; + } + usleep_range(1000, 2000); + } + } +send_host_wakeup: + if (dstate == MHI_SM_EP_PCIE_D3_HOT_STATE || dstate == MHI_SM_EP_PCIE_D3_COLD_STATE) + mhi_sm_wakeup_host(); +} /** * mhi_dev_sm_set_ready() -Set MHI state to ready. diff --git a/drivers/platform/msm/mhi_dev/mhi_sm.h b/drivers/platform/msm/mhi_dev/mhi_sm.h index 80ed0086472f..24e6daf46777 100644 --- a/drivers/platform/msm/mhi_dev/mhi_sm.h +++ b/drivers/platform/msm/mhi_dev/mhi_sm.h @@ -42,7 +42,6 @@ int mhi_dev_sm_init(struct mhi_dev *dev); int mhi_dev_sm_exit(struct mhi_dev *dev); int mhi_dev_sm_set_ready(void); int mhi_dev_notify_sm_event(enum mhi_dev_event event); -int mhi_dev_sm_get_mhi_state(enum mhi_dev_state *state); int mhi_dev_sm_syserr(void); void mhi_dev_sm_pcie_handler(struct ep_pcie_notify *notify); From 1227bcf0b1b2c066be7058ce091a1e0ecf2fa063 Mon Sep 17 00:00:00 2001 From: Fakruddin Vohra Date: Wed, 2 Apr 2025 10:36:06 +0530 Subject: [PATCH 15/42] mdm: ipa3: support IPoGRE new IOCTL and proc params change to support IPoGRE IOCTL for interface with QCMAP and proc context parameters. Change-Id: I13baab118eb03e18c7c53403705cbdb7611411c1 Signed-off-by: Fakruddin Vohra --- include/uapi/linux/msm_ipa.h | 125 +++++++++++++++++++++++++++++++++-- 1 file changed, 119 insertions(+), 6 deletions(-) diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h index f63134040753..5f63c7b96479 100644 --- a/include/uapi/linux/msm_ipa.h +++ b/include/uapi/linux/msm_ipa.h @@ -152,8 +152,9 @@ #define IPA_IOCTL_SET_EXT_ROUTER_MODE 95 #define IPA_IOCTL_ADD_DEL_DSCP_PCP_MAPPING 96 #define IPA_IOCTL_SEND_VLAN_MUXID_MAPPING 97 -#define IPA_IOCTL_SEND_TUNNEL_TEMPLATE_INFO 98 -#define IPA_IOCTL_QUERY_TUNNEL_FEATURE 99 +#define IPA_IOCTL_SEND_TUNNEL_TEMPLATE_INFO 98 +#define IPA_IOCTL_QUERY_TUNNEL_FEATURE 99 +#define IPA_IOCTL_ADD_IPOGRE_MAPPING 100 /** * max size of the header to be inserted */ @@ -976,8 +977,12 @@ enum ipa_eth_pdu_evt { #define IPA_ENABLE_ETH_PDU_MODE_EVENT_MAX IPA_ENABLE_ETH_PDU_MODE_EVENT_MAX }; - -#define IPA_EVENT_MAX_NUM (IPA_ENABLE_ETH_PDU_MODE_EVENT_MAX) +enum ipa_ipogre_event { + IPA_IPOGRE_NOTIFY_EVENT = IPA_ENABLE_ETH_PDU_MODE_EVENT_MAX, + IPA_IPOGRE_EVENT_MAX +#define IPA_IPOGRE_EVENT_MAX IPA_IPOGRE_EVENT_MAX +}; +#define IPA_EVENT_MAX_NUM (IPA_IPOGRE_EVENT_MAX) #define IPA_EVENT_MAX ((int)IPA_EVENT_MAX_NUM) /** @@ -1551,9 +1556,11 @@ enum ipa_hdr_proc_type { IPA_HDR_PROC_EoGRE_HEADER_REMOVE, IPA_HDR_PROC_WWAN_TO_ETHII_EX, IPA_HDR_PROC_GRE_HEADER_ADD, - IPA_HDR_PROC_GRE_HEADER_REMOVE + IPA_HDR_PROC_GRE_HEADER_REMOVE, + IPA_HDR_PROC_IPOGRE_HEADER_ADD, + IPA_HDR_PROC_IPOGRE_HEADER_REMOVE }; -#define IPA_HDR_PROC_MAX (IPA_HDR_PROC_GRE_HEADER_REMOVE + 1) +#define IPA_HDR_PROC_MAX (IPA_HDR_PROC_IPOGRE_HEADER_REMOVE + 1) /** * struct ipa_rt_rule - attributes of a routing rule @@ -1958,6 +1965,68 @@ struct ipa_ioc_eogre_info { struct IpaDscpVlanPcpMap_t map_info; }; +#define MAX_FLOW_PER_IPOGRE_TUNNEL 10 + +/** + * struct ipa_ipogre_info - + * @ipv4_src: Specifies source v4 address if GRE tunnel is ipv4 + * @ipv4_dst: Specifies destination v4 address if GRE tunnel is ipv4 + * @ipv6_src: Specifies source v6 address if GRE tunnel is ipv6 + * @ipv6_dst: Specifies destination v6 address if GRE tunnel is ipv6 + * @iptype: Specifies GRE tunnel's ip address type + * @tunnel_id: Specifies tunnel id + */ + +struct ipa_ipogre_tunnel_info { + uint32_t ipv4_src; + uint32_t ipv4_dst; + uint32_t ipv6_src[4]; + uint32_t ipv6_dst[4]; + enum ipa_ip_type iptype; + uint8_t tunnel_id; +} __packed; + +/** + * struct ipa_ipogre_info - + * @ipv4_src: Specifies source v4 address if GRE tunnel is ipv4 + * @ipv4_src_subnet: Specifies source v4 address subnet if GRE tunnel is ipv4 + * @ipv4_dst: Specifies destination v4 address if GRE tunnel is ipv4 + * @ipv4_dst_subnet: Specifies destination v4 address subnet if GRE tunnel is ipv4 + * @ipv6_src: Specifies source v6 address if GRE tunnel is ipv6 + * @ipv6_src_subnet: Specifies source v6 address subnet if GRE tunnel is ipv6 + * @ipv6_dst: Specifies destination v6 address if GRE tunnel is ipv6 + * @ipv6_dst_subnet: Specifies destination v6 address subnet if GRE tunnel is ipv6 + * @iptype: Specifies GRE tunnel's ip address type + * @protocol: Specifies protocol of the data traffic + */ + +struct ipa_ipogre_flow_info { + uint32_t ipv4_src; + uint32_t ipv4_src_subnet; + uint32_t ipv4_dst; + uint32_t ipv4_dst_subnet; + uint32_t ipv6_src[4]; + uint32_t ipv6_dst[4]; + uint32_t src_port; + uint32_t dst_port; + enum ipa_ip_type iptype; + uint8_t protocol; + uint8_t ipv6_src_subnet; + uint8_t ipv6_dst_subnet; +} __packed; + +/** + * struct ipa_ipogre_info - + * @ipogre_tunnel_info: Specifies tunnel information + * @ipogre_flow_info: Specifies flows to be offloaded + * @ipa_ipogre_num_flow: Specifies number of flow to be offloaded + */ + +struct ipa_ioc_ipogre_info { + struct ipa_ipogre_tunnel_info ipogre_tunnel_info; + struct ipa_ipogre_flow_info ipogre_flow_info[MAX_FLOW_PER_IPOGRE_TUNNEL]; + uint8_t ipa_ipogre_num_flow; +}; /** * struct ipa_eogre_header_add_procparams - * @eth_hdr_retained: Specifies if Ethernet header is retained or not @@ -2049,6 +2118,45 @@ struct ipa_gre_hdr_proc_ctx_params { struct ipa_gre_header_remove_procparams hdr_remove_param; }; +/** + * struct ipa_ipogre_header_add_procparams - + * @input_ip_version: Specifies if Input header is IPV4(0) or IPV6(1) + * @output_ip_version: Specifies if template header's outer IP is IPV4(0) + * or IPV6(1) + * @Tunnel_Id: Tunnel id associated with the header. + * @Mux_Id: Specifies mux id associated with the template header + */ +struct ipa_ipogre_header_add_procparams { + uint32_t input_ip_version : 1; + uint32_t output_ip_version : 1; + uint32_t tunnel_id : 4; + uint32_t mux_id : 8; + uint32_t reserved :18; +}; + +/** + * struct ipa_ipogre_header_remove_procparams - + * @hdr_len_remove: Specifies how much (in bytes) of the header needs + * to be removed + * @input_ip_version: Specifies if Input header is IPV4(0) or IPV6(1) + * @Tunnel_Id: Tunnel id associated with the header. + */ +struct ipa_ipogre_header_remove_procparams { + uint32_t hdr_len_remove : 8; + uint32_t input_ip_version : 1; + uint32_t tunnel_id : 4; + uint32_t reserved :19; +}; + +/** + * struct ipa_ipogre_hdr_proc_ctx_params - + * @hdr_add_param: parameters for header add + * @hdr_remove_param: parameters for header remove + */ +struct ipa_ipogre_hdr_proc_ctx_params { + struct ipa_ipogre_header_add_procparams hdr_add_param; + struct ipa_ipogre_header_remove_procparams hdr_remove_param; +}; /** * struct ipa_eth_II_to_eth_II_ex_procparams - * @input_ethhdr_negative_offset: Specifies where the ethernet hdr offset is @@ -2111,6 +2219,7 @@ struct ipa_hdr_proc_ctx_add { struct ipa_eth_II_to_eth_II_ex_procparams generic_params; struct ipa_wwan_to_eth_II_ex_procparams generic_params_v2; struct ipa_gre_hdr_proc_ctx_params gre_params; + struct ipa_ipogre_hdr_proc_ctx_params ipogre_params; }; #define IPA_L2TP_HDR_PROC_SUPPORT @@ -4221,6 +4330,10 @@ struct ipa_ioc_dscp_pcp_map_info { IPA_IOCTL_QUERY_TUNNEL_FEATURE, \ uint8_t) +#define IPA_IOC_ADD_IPoGRE_MAPPING _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_ADD_IPOGRE_MAPPING, \ + struct ipa_ioc_ipogre_info) + /* * unique magic number of the Tethering bridge ioctls */ From e11076b7dfe33a2056930f63dd20a6e5c189029a Mon Sep 17 00:00:00 2001 From: Zahir Shabbir Khan Date: Tue, 4 Mar 2025 12:03:30 +0530 Subject: [PATCH 16/42] dmaengine: msm_gpi: fix to avoid null pointer access A null pointer dereference is possible in gpi_prep_slave_sg. Client drivers will allocate buffer and initiate bus xfer through qup over i2c. I2c geni driver will queue the buffer address to TRE'S using scatter-gather. Clients can pass NULL buffer, so added null pointer check before accessing the TRE. This is leading to dereferencing null pointer issue. To solve this, add check for null in transfer ring. Change-Id: I3a25a7da0d38c58f725e0996c458b1fb64c0fe09 Signed-off-by: Anil Veshala Veshala Signed-off-by: Somesh Dey Signed-off-by: Zahir Shabbir Khan --- drivers/dma/qcom/gpi.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/dma/qcom/gpi.c b/drivers/dma/qcom/gpi.c index 44e2e7de129e..eb9aea7851ff 100644 --- a/drivers/dma/qcom/gpi.c +++ b/drivers/dma/qcom/gpi.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -2524,6 +2525,12 @@ struct dma_async_tx_descriptor *gpi_prep_slave_sg(struct dma_chan *chan, for_each_sg(sgl, sg, sg_len, i) { tre = sg_virt(sg); + if (!tre) { + kfree(gpi_desc); + GPII_ERR(gpii, gpii_chan->chid, "TRE address is null\n"); + return NULL; + } + if (sg_len == 1) { tre_type = MSM_GPI_TRE_TYPE(((struct msm_gpi_tre *)tre)); From 568fea2103684e538a8299d85837fc106bcb8373 Mon Sep 17 00:00:00 2001 From: Abhinav Parihar Date: Tue, 3 Jun 2025 13:22:30 +0530 Subject: [PATCH 17/42] msm: adsprpc: Prevent refcount increment for duplicate dmahandles When user passes same fd more than once in same remote call, it results in mapping refcount of dma handle being greater than one. Once DSP is done and passes dma handle fd in fdlist to unmap, it decrements the refcount by one and tries to delete the map. As the refcount is still greater than zero the mapping isn't deleted. This leads to stale mapping information. Avoid incrementing the map refcount when the same dmahandle is passed multiple times in a single remote call. This prevents stale mappings caused by non-zero refcounts after DSP unmaps the handle. Mapping removal should depend solely on DSP releasing all references, not on how many times the fd was passed. Change-Id: I69e98e98a6d494b5ffe0a845fd4579fe632edeeb Signed-off-by: Abhinav Parihar --- drivers/char/adsprpc.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index e8ba4bed8572..39bdf863b597 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. */ /* Uncomment this block to log an error on every VERIFY failure */ @@ -62,6 +62,7 @@ #define TZ_PIL_AUTH_QDSP6_PROC 1 #define FASTRPC_DMAHANDLE_NOMAP (16) +#define FASTRPC_MAP_DMA_HANDLE 0x20000 #define FASTRPC_ENOSUCH 39 #define DEBUGFS_SIZE 3072 @@ -1128,7 +1129,7 @@ static void fastrpc_mmap_add(struct fastrpc_mmap *map) } static int fastrpc_mmap_find(struct fastrpc_file *fl, int fd, - uintptr_t va, size_t len, int mflags, int refs, + uintptr_t va, size_t len, int mflags, bool refs, struct fastrpc_mmap **ppmap) { struct fastrpc_mmap *match = NULL, *map = NULL; @@ -1306,7 +1307,7 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags) dma_free_attrs(me->dev, map->size, (void *)map->va, (dma_addr_t)map->phys, (unsigned long)map->attr); } - } else if (map->flags == FASTRPC_DMAHANDLE_NOMAP) { + } else if (map->flags & FASTRPC_DMAHANDLE_NOMAP) { trace_fastrpc_dma_unmap(cid, map->phys, map->size); if (!IS_ERR_OR_NULL(map->table)) dma_buf_unmap_attachment(map->attach, map->table, @@ -1391,6 +1392,7 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, unsigned long flags; int err = 0, vmid, sgl_index = 0; struct scatterlist *sgl = NULL; + bool take_ref = true; if (!fl) { err = -EBADF; @@ -1404,7 +1406,9 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, } chan = &apps->channel[cid]; - if (!fastrpc_mmap_find(fl, fd, va, len, mflags, 1, ppmap)) + if (mflags & FASTRPC_MAP_DMA_HANDLE) + take_ref = false; + if (!fastrpc_mmap_find(fl, fd, va, len, mflags, take_ref, ppmap)) return 0; map = kzalloc(sizeof(*map), GFP_KERNEL); VERIFY(err, !IS_ERR_OR_NULL(map)); @@ -1442,7 +1446,7 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, if (err) goto bail; } - } else if (mflags == FASTRPC_DMAHANDLE_NOMAP) { + } else if (mflags & FASTRPC_DMAHANDLE_NOMAP) { VERIFY(err, !IS_ERR_OR_NULL(map->buf = dma_buf_get(fd))); if (err) { ADSPRPC_ERR("dma_buf_get failed for fd %d ret %ld\n", @@ -2496,10 +2500,10 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) handles = REMOTE_SCALARS_INHANDLES(sc) + REMOTE_SCALARS_OUTHANDLES(sc); mutex_lock(&ctx->fl->map_mutex); for (i = bufs; i < bufs + handles; i++) { - int dmaflags = 0; + int dmaflags = FASTRPC_MAP_DMA_HANDLE; if (ctx->attrs && (ctx->attrs[i] & FASTRPC_ATTR_NOMAP)) - dmaflags = FASTRPC_DMAHANDLE_NOMAP; + dmaflags |= FASTRPC_DMAHANDLE_NOMAP; if (ctx->fds && (ctx->fds[i] != -1)) err = fastrpc_mmap_create(ctx->fl, ctx->fds[i], FASTRPC_ATTR_NOVA, 0, 0, dmaflags, @@ -2660,7 +2664,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) if (ctx->maps[i]) { /* check if map still exist */ if (!fastrpc_mmap_find(ctx->fl, ctx->fds[i], 0, 0, - 0, 0, &mmap)) { + 0, false, &mmap)) { if (mmap) { pages[i].addr = mmap->phys; pages[i].size = mmap->size; @@ -2875,7 +2879,7 @@ static int put_args(uint32_t kernel, struct smq_invoke_ctx *ctx, if (!fdlist[i]) break; if (!fastrpc_mmap_find(ctx->fl, (int)fdlist[i], 0, 0, - 0, 0, &mmap)) { + 0, false, &mmap)) { if (mmap && mmap->dma_handle_refs) { mmap->dma_handle_refs = 0; fastrpc_mmap_free(mmap, 0); @@ -4955,7 +4959,7 @@ static int fastrpc_internal_munmap_fd(struct fastrpc_file *fl, } mutex_lock(&fl->internal_map_mutex); mutex_lock(&fl->map_mutex); - err = fastrpc_mmap_find(fl, ud->fd, ud->va, ud->len, 0, 0, &map); + err = fastrpc_mmap_find(fl, ud->fd, ud->va, ud->len, 0, false, &map); if (err) { ADSPRPC_ERR( "mapping not found to unmap fd 0x%x, va 0x%llx, len 0x%x, err %d\n", From 4f37e589d976ba56a3dd87c06409aea7a35f2746 Mon Sep 17 00:00:00 2001 From: Vishakha Malik Date: Mon, 9 Jun 2025 15:31:59 +0530 Subject: [PATCH 18/42] crypto: qcedev - fix UAF in crypto-qti driver userspace to QCEDEV_IOCTL_MAP_BUF_REQ and QCEDEV_IOCTL_UNMAP_BUF_REQ, which can have a race condition resulting in a use-after-free (UAF). Change-Id: Iff51a098bbf9746e256e40a20fc37c5404f8aa22 Signed-off-by: Vishakha Malik --- drivers/crypto/msm/qcedev_smmu.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/crypto/msm/qcedev_smmu.c b/drivers/crypto/msm/qcedev_smmu.c index 8d4844becc85..7039bce67c5c 100644 --- a/drivers/crypto/msm/qcedev_smmu.c +++ b/drivers/crypto/msm/qcedev_smmu.c @@ -329,10 +329,6 @@ int qcedev_check_and_map_buffer(void *handle, mapped_size = binfo->ion_buf.mapped_buf_size; atomic_inc(&binfo->ref_count); - /* Add buffer mapping information to regd buffer list */ - mutex_lock(&qce_hndl->registeredbufs.lock); - list_add_tail(&binfo->list, &qce_hndl->registeredbufs.list); - mutex_unlock(&qce_hndl->registeredbufs.lock); } /* Make sure the offset is within the mapped range */ @@ -344,6 +340,13 @@ int qcedev_check_and_map_buffer(void *handle, goto unmap; } + if (!found) { + /* Add buffer mapping information to regd buffer list */ + mutex_lock(&qce_hndl->registeredbufs.lock); + list_add_tail(&binfo->list, &qce_hndl->registeredbufs.list); + mutex_unlock(&qce_hndl->registeredbufs.lock); + } + /* return the mapped virtual address adjusted by offset */ *vaddr += offset; @@ -352,9 +355,6 @@ int qcedev_check_and_map_buffer(void *handle, unmap: if (!found) { qcedev_unmap_buffer(handle, mem_client, binfo); - mutex_lock(&qce_hndl->registeredbufs.lock); - list_del(&binfo->list); - mutex_unlock(&qce_hndl->registeredbufs.lock); } error: From 695a2b9f1df15cd1f562344041700997b602a861 Mon Sep 17 00:00:00 2001 From: Bibek Kumar Patro Date: Fri, 10 Jan 2025 10:53:44 +0530 Subject: [PATCH 19/42] dma-mapping-fast: Fix PMD offset calculation for non-2M aligned start aperture MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modify PMD offset calculation for domains with start apertures not 2M aligned. Currently, when this happens, the PMD offset is calculated to the next PMD, and hence each IOVA is mapped as IOVA + offset, causing the IOVA to be tagged to the wrong PA. Issue occurrence - With the following sample aperture settings by a fastmap client: qcom,iommu-dma-addr-pool = <0x87f10000 0x07f00000>; qcom,iommu-geometry = <0x87f10000 0x07f00000>; The effective IOVA range is bounded to iova_base: 0x87f10000, iova_end: 0x8FE10000, which makes the IOVA base not aligned to a 2MB boundary. While calculating PTE, this adds an extra ā€œdefault offsetā€ to the PMD base (since all PMD pages’ base addresses are 2MB aligned), which further gets added on top of the actual offset obtained by (iova - base). This causes the final PMD offset to have an additional delta, causing the IOVA to be tagged to the wrong PA. ALIGN_DOWN(base, SZ_2M) helps to remove the extra ā€œdefault offset,ā€ helping to tag the IOVA to the right PA. ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” PMD 1 base │ ā”œā”€ā”€ā”€ā”€ā”€ā”€ā–ŗā”Œā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”ā—„ā”€ā”€ │ │ ││ ││ ALIGN_DOWN(base, SZ_2M) │PGD pageā”œā”€ā” ││ old ││ │ │ │ ││offset││ │ │ │────►│└─ ││◄──── ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ │wrong│ new ││ base │iova │offsetā”€ā”˜ā”‚ā—„ā”€ā”€ā”€ā”€ │ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ right │ iova │ PMD 2 base ā””ā”€ā”€ā”€ā”€ā–ŗā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”ā—„ā”€ā”€ā”€ā”€ │ │ ALIGN_UP(base, SZ_2M) │ │ │ │ │ │ │ │ ā””ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ │PMD n base ā”Œā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” │ │ │ │ │ │ │ │ │ │ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ Change-Id: Ie320816ee91710fe06cf2337816d0fb8638ccbcb Fixes: 2e87440c3e6f ("iommu/io-pgtable-fast: optimize statically allocated pages") Signed-off-by: Bibek Kumar Patro Signed-off-by: Srinivasarao Pathipati --- drivers/iommu/io-pgtable-fast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/io-pgtable-fast.c b/drivers/iommu/io-pgtable-fast.c index f07e93b33f05..67ca5c20c521 100644 --- a/drivers/iommu/io-pgtable-fast.c +++ b/drivers/iommu/io-pgtable-fast.c @@ -133,7 +133,7 @@ typeof(base) __base = (base); \ typeof(pmds) __pmds = (pmds); \ (__iova < __base) ? ERR_PTR(-EINVAL) : \ - __pmds + ((__iova - __base) >> AV8L_FAST_PAGE_SHIFT); \ + __pmds + ((__iova - ALIGN_DOWN(__base, SZ_2M)) >> AV8L_FAST_PAGE_SHIFT); \ }) static inline dma_addr_t av8l_dma_addr(void *addr) From 112e55f2b4dc682c5e74a8734bbf82068f179465 Mon Sep 17 00:00:00 2001 From: Vedang Nagar Date: Mon, 19 May 2025 12:42:22 +0530 Subject: [PATCH 20/42] FROMLIST: media: venus: Fix OOB read due to missing payload bound check Currently, The event_seq_changed() handler processes a variable number of properties sent by the firmware. The number of properties is indicated by the firmware and used to iterate over the payload. However, the payload size is not being validated against the actual message length. This can lead to out-of-bounds memory access if the firmware provides a property count that exceeds the data available in the payload. Such a condition can result in kernel crashes or potential information leaks if memory beyond the buffer is accessed. Fix this by properly validating the remaining size of the payload before each property access and updating bounds accordingly as properties are parsed. This ensures that property parsing is safely bounded within the received message buffer and protects against malformed or malicious firmware behavior. Fixes: 09c2845e8fe4 ("[media] media: venus: hfi: add Host Firmware Interface (HFI)") Change-Id: Ife789627352a3caab24d6bd32ca286161b52758f Signed-off-by: Vedang Nagar Reviewed-by: Vikash Garodia Reviewed-by: Bryan O'Donoghue Link: https://lore.kernel.org/linux-media/20250519-venus-fixes-v4-2-3ae91d81443d@quicinc.com/ Co-developed-by: Dikshita Agarwal Signed-off-by: Dikshita Agarwal Signed-off-by: Vasantha Balla --- drivers/media/platform/qcom/venus/hfi_msgs.c | 86 +++++++++++++++----- 1 file changed, 64 insertions(+), 22 deletions(-) diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.c b/drivers/media/platform/qcom/venus/hfi_msgs.c index 5694d18b43d5..990c53398b9b 100644 --- a/drivers/media/platform/qcom/venus/hfi_msgs.c +++ b/drivers/media/platform/qcom/venus/hfi_msgs.c @@ -27,8 +27,10 @@ static void event_seq_changed(struct venus_core *core, struct venus_inst *inst, struct hfi_colour_space *colour_info; struct hfi_buffer_requirements *bufreq; struct hfi_extradata_input_crop *crop; + struct hfi_dpb_counts *dpb_count; + u32 ptype, rem_bytes; + u32 size_read = 0; u8 *data_ptr; - u32 ptype; inst->error = HFI_ERR_NONE; @@ -38,80 +40,120 @@ static void event_seq_changed(struct venus_core *core, struct venus_inst *inst, break; default: inst->error = HFI_ERR_SESSION_INVALID_PARAMETER; - goto done; + inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event); + return; } event.event_type = pkt->event_data1; num_properties_changed = pkt->event_data2; - if (!num_properties_changed) { - inst->error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES; - goto done; - } + if (!num_properties_changed) + goto error; data_ptr = (u8 *)&pkt->ext_event_data[0]; + rem_bytes = pkt->shdr.hdr.size - sizeof(*pkt); + do { + if (rem_bytes < sizeof(u32)) + goto error; ptype = *((u32 *)data_ptr); + + data_ptr += sizeof(u32); + rem_bytes -= sizeof(u32); + switch (ptype) { case HFI_PROPERTY_PARAM_FRAME_SIZE: - data_ptr += sizeof(u32); + if (rem_bytes < sizeof(struct hfi_framesize)) + goto error; + frame_sz = (struct hfi_framesize *)data_ptr; event.width = frame_sz->width; event.height = frame_sz->height; - data_ptr += sizeof(*frame_sz); + size_read = sizeof(struct hfi_framesize); break; case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT: - data_ptr += sizeof(u32); + if (rem_bytes < sizeof(struct hfi_profile_level)) + goto error; + profile_level = (struct hfi_profile_level *)data_ptr; event.profile = profile_level->profile; event.level = profile_level->level; - data_ptr += sizeof(*profile_level); + size_read = sizeof(struct hfi_profile_level); break; case HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH: - data_ptr += sizeof(u32); + if (rem_bytes < sizeof(struct hfi_bit_depth)) + goto error; + pixel_depth = (struct hfi_bit_depth *)data_ptr; event.bit_depth = pixel_depth->bit_depth; - data_ptr += sizeof(*pixel_depth); + size_read = sizeof(struct hfi_bit_depth); break; case HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT: - data_ptr += sizeof(u32); + if (rem_bytes < sizeof(struct hfi_pic_struct)) + goto error; + pic_struct = (struct hfi_pic_struct *)data_ptr; event.pic_struct = pic_struct->progressive_only; - data_ptr += sizeof(*pic_struct); + size_read = sizeof(struct hfi_pic_struct); break; case HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE: - data_ptr += sizeof(u32); + if (rem_bytes < sizeof(struct hfi_colour_space)) + goto error; + colour_info = (struct hfi_colour_space *)data_ptr; event.colour_space = colour_info->colour_space; - data_ptr += sizeof(*colour_info); + size_read = sizeof(struct hfi_colour_space); break; case HFI_PROPERTY_CONFIG_VDEC_ENTROPY: - data_ptr += sizeof(u32); + if (rem_bytes < sizeof(u32)) + goto error; + event.entropy_mode = *(u32 *)data_ptr; - data_ptr += sizeof(u32); + size_read = sizeof(u32); break; case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS: - data_ptr += sizeof(u32); + if (rem_bytes < sizeof(struct hfi_buffer_requirements)) + goto error; + bufreq = (struct hfi_buffer_requirements *)data_ptr; event.buf_count = HFI_BUFREQ_COUNT_MIN(bufreq, ver); data_ptr += sizeof(*bufreq); + event.buf_count = hfi_bufreq_get_count_min(bufreq, ver); + size_read = sizeof(struct hfi_buffer_requirements); break; case HFI_INDEX_EXTRADATA_INPUT_CROP: - data_ptr += sizeof(u32); + if (rem_bytes < sizeof(struct hfi_extradata_input_crop)) + goto error; + crop = (struct hfi_extradata_input_crop *)data_ptr; event.input_crop.left = crop->left; event.input_crop.top = crop->top; event.input_crop.width = crop->width; event.input_crop.height = crop->height; - data_ptr += sizeof(*crop); + size_read = sizeof(struct hfi_extradata_input_crop); + break; + case HFI_PROPERTY_PARAM_VDEC_DPB_COUNTS: + if (rem_bytes < sizeof(struct hfi_dpb_counts)) + goto error; + + dpb_count = (struct hfi_dpb_counts *)data_ptr; + event.buf_count = dpb_count->fw_min_cnt; + size_read = sizeof(struct hfi_dpb_counts); break; default: + size_read = 0; break; } + data_ptr += size_read; + rem_bytes -= size_read; num_properties_changed--; } while (num_properties_changed > 0); -done: + inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event); + return; + +error: + inst->error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES; inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event); } From 0d355ad3f314672e592e030d87ff065f4d39376c Mon Sep 17 00:00:00 2001 From: Wu Gao Date: Fri, 20 Jun 2025 03:32:23 -0700 Subject: [PATCH 21/42] Add configures to enable CNSS platform driver This change adds below configures to enable CNSS platform driver. CONFIG_CNSS=m CONFIG_CNSS_CRYPTO=y CONFIG_CNSS_PCI=y CONFIG_CNSS_LOGGER=m Change-Id: Ib318b617e98db65a097794a30ddca919775e0f04 Signed-off-by: Wu Gao --- arch/arm/configs/vendor/sdxlemur.config | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/configs/vendor/sdxlemur.config b/arch/arm/configs/vendor/sdxlemur.config index 2d12580404e8..0d6a262c17ea 100644 --- a/arch/arm/configs/vendor/sdxlemur.config +++ b/arch/arm/configs/vendor/sdxlemur.config @@ -51,6 +51,10 @@ CONFIG_CNSS_ASYNC=y CONFIG_CNSS_QCA6490=y CONFIG_CNSS_UTILS=y # CONFIG_CNSS_GENL is not set +CONFIG_CNSS=m +CONFIG_CNSS_CRYPTO=y +CONFIG_CNSS_PCI=y +CONFIG_CNSS_LOGGER=m CONFIG_QCOM_MEMORY_DUMP_V2=y CONFIG_PACKET=y CONFIG_UNIX=y From aa9867b1fcd45d006118fde4e6d5eba72087ac21 Mon Sep 17 00:00:00 2001 From: Vedang Nagar Date: Mon, 19 May 2025 12:42:21 +0530 Subject: [PATCH 22/42] FROMLIST: media: venus: Add a check for packet size Add a check to ensure that the packet size does not exceed the number of available words after reading the packet header from shared memory. This ensures that the size provided by the firmware is safe to process and prevent potential out-of-bounds memory access. Fixes: d96d3f30c0f2 ("[media] media: venus: hfi: add Venus HFI files") Change-Id: I561f411e0a448f8436dafdadb755deb563ce49c2 Reviewed-by: Bryan O'Donoghue Signed-off-by: Vedang Nagar Co-developed-by: Dikshita Agarwal Signed-off-by: Dikshita Agarwal Signed-off-by: Vasantha Balla --- drivers/media/platform/qcom/venus/hfi_venus.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index 1b37d77bf998..33d9d50e79cd 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -240,6 +240,7 @@ static int venus_write_queue(struct venus_hfi_device *hdev, static int venus_read_queue(struct venus_hfi_device *hdev, struct iface_queue *queue, void *pkt, u32 *tx_req) { + struct hfi_pkt_hdr *pkt_hdr = NULL; struct hfi_queue_header *qhdr; u32 dwords, new_rd_idx; u32 rd_idx, wr_idx, type, qsize; @@ -305,6 +306,9 @@ static int venus_read_queue(struct venus_hfi_device *hdev, memcpy(pkt, rd_ptr, len); memcpy(pkt + len, queue->qmem.kva, new_rd_idx << 2); } + pkt_hdr = (struct hfi_pkt_hdr *)(pkt); + if ((pkt_hdr->size >> 2) != dwords) + return -EINVAL; } else { /* bad packet received, dropping */ new_rd_idx = qhdr->write_idx; From 8a31fb44f3b961f7c2ca4f53b659ec8cbacd679a Mon Sep 17 00:00:00 2001 From: Wu Gao Date: Mon, 23 Jun 2025 03:03:28 -0700 Subject: [PATCH 23/42] cnss: Add support for building CNSS as a loadable module Add support for building CNSS as a loadable module. When CONFIG_CNSS=m is specified, CONFIG_CNSS_MODULE will be defined instead of CONFIG_CNSS. Change-Id: I367c2321836d124d30f08dae14bbe763acaf6c03 Signed-off-by: Wu Gao --- drivers/net/wireless/cnss/Makefile | 10 ++++++---- include/net/cnss.h | 2 -- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/cnss/Makefile b/drivers/net/wireless/cnss/Makefile index c1ca4c3821e6..567ef214d7dd 100644 --- a/drivers/net/wireless/cnss/Makefile +++ b/drivers/net/wireless/cnss/Makefile @@ -3,7 +3,9 @@ # Makefile for CNSS platform driver # -obj-$(CONFIG_CNSS_PCI) += cnss_pci.o -obj-$(CONFIG_CNSS_SDIO) += cnss_sdio.o -obj-$(CONFIG_CNSS) += cnss_common.o -obj-$(CONFIG_CNSS_LOGGER) += logger/ +obj-$(CONFIG_CNSS) += cnss.o + +cnss-$(CONFIG_CNSS_PCI) += cnss_pci.o +cnss-$(CONFIG_CNSS_SDIO) += cnss_sdio.o +cnss-y += cnss_common.o +obj-$(CONFIG_CNSS_LOGGER) += logger/ diff --git a/include/net/cnss.h b/include/net/cnss.h index 9c99bdc2032d..77bc3157c2aa 100644 --- a/include/net/cnss.h +++ b/include/net/cnss.h @@ -10,7 +10,6 @@ #include #include -#ifdef CONFIG_CNSS #define MAX_FIRMWARE_SIZE (1 * 1024 * 1024) #define CNSS_MAX_FILE_NAME 20 #define PINCTRL_SLEEP 0 @@ -177,7 +176,6 @@ int cnss_pm_runtime_request(struct device *dev, enum cnss_runtime_request request); void cnss_set_cc_source(enum cnss_cc_src cc_source); enum cnss_cc_src cnss_get_cc_source(void); -#endif void cnss_pm_wake_lock_init(struct wakeup_source **ws, const char *name); void cnss_pm_wake_lock(struct wakeup_source *ws); From 83ec139d771c45f957ac336ca31910a5eeecee51 Mon Sep 17 00:00:00 2001 From: Wu Gao Date: Mon, 23 Jun 2025 03:02:26 -0700 Subject: [PATCH 24/42] cnss: Dump stack by stack_trace_print The kernel API - show_stack isn't used after kernel updated, this function uses stack_trace_print to dump stack. Change-Id: Ib793946b3b66b271e05794bea3610ffb3684c44e Signed-off-by: Wu Gao --- drivers/net/wireless/cnss/cnss_common.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/cnss/cnss_common.c b/drivers/net/wireless/cnss/cnss_common.c index dbdd13e0abca..534f81f320a6 100644 --- a/drivers/net/wireless/cnss/cnss_common.c +++ b/drivers/net/wireless/cnss/cnss_common.c @@ -242,13 +242,21 @@ int cnss_set_cpus_allowed_ptr(struct task_struct *task, ulong cpu) } EXPORT_SYMBOL(cnss_set_cpus_allowed_ptr); -/* wlan prop driver cannot invoke show_stack - * function directly, so to invoke this function it - * call wcnss_dump_stack function - */ +#define ENTRIES_COUNT 32 void cnss_dump_stack(struct task_struct *task) { - show_stack(task, NULL); + const int cnss_spaces = 4; + unsigned long cnss_entries[ENTRIES_COUNT] = {0}; + struct stack_trace cnss_trace = { + .nr_entries = 0, + .skip = 0, + .entries = &cnss_entries[0], + .max_entries = ENTRIES_COUNT, + }; + + save_stack_trace_tsk(task, &cnss_trace); + stack_trace_print(cnss_entries, cnss_trace.nr_entries, + cnss_spaces); } EXPORT_SYMBOL(cnss_dump_stack); From f4fc88f0890494d32aa0ffa9bce883e61f6fe0c7 Mon Sep 17 00:00:00 2001 From: Wu Gao Date: Tue, 15 Jul 2025 02:53:03 -0700 Subject: [PATCH 25/42] cnss: Init reserved memory device If IOMMU is supported and enabled, it required to define IOMMU and init reversed memory device. Change-Id: I2bbd2f42333dca8a6bf7e608ce50e2c08fc0e8ba Signed-off-by: Wu Gao --- drivers/net/wireless/cnss/cnss_pci.c | 40 ++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/drivers/net/wireless/cnss/cnss_pci.c b/drivers/net/wireless/cnss/cnss_pci.c index 9d588b5ed6d8..623149274fa3 100644 --- a/drivers/net/wireless/cnss/cnss_pci.c +++ b/drivers/net/wireless/cnss/cnss_pci.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include #include @@ -1618,6 +1620,43 @@ static void cnss_pcie_reset_platform_ops(struct device *dev) dev->platform_data = NULL; } +#if IS_ENABLED(CONFIG_ARCH_QCOM) +/** + * cnss_pci_of_reserved_mem_device_init() - Assign reserved memory region + * to given PCI device + * @pdev: context pointer of pdev + * + * This function shall call corresponding of_reserved_mem_device* API to + * assign reserved memory region to PCI device based on where the memory is + * defined and attached to (platform device of_node or PCI device of_node) + * in device tree. + * + * Return: 0 for success, negative value for error + */ +static int cnss_pci_of_reserved_mem_device_init(struct pci_dev *pdev) +{ + struct device *dev_pci = &pdev->dev; + int ret; + + /* Use of_reserved_mem_device_init_by_idx() if reserved memory is + * attached to platform device of_node. + */ + ret = of_reserved_mem_device_init(dev_pci); + if (ret) + pr_err("Failed to init reserved mem device, err = %d\n", + ret); + if (dev_pci->cma_area) + pr_debug("CMA area is %s\n", cma_get_name(dev_pci->cma_area)); + + return ret; +} +#else +static int cnss_pci_of_reserved_mem_device_init(struct pci_dev *pdev) +{ + return 0; +} +#endif + static int cnss_wlan_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -1634,6 +1673,7 @@ static int cnss_wlan_pci_probe(struct pci_dev *pdev, atomic_set(&penv->fw_available, 0); penv->device_id = pdev->device; + cnss_pci_of_reserved_mem_device_init(pdev); if (penv->smmu_iova_len) { ret = cnss_smmu_init(&pdev->dev); if (ret) { From 6b26ef81599afa1718f318388f100391a4d27400 Mon Sep 17 00:00:00 2001 From: Arunteja Reddy Gopireddy Date: Tue, 2 Sep 2025 17:32:05 +0530 Subject: [PATCH 26/42] msm: cvp: Fix for kernel address exposure vulnerability to user Driver allocates an object for session structure and then passes this address to user after modifing this address a bit using hash32_ptr function. This function does not hash the address properly and user can retrieve the kernel address back from the hashed value. Change-Id: I8a91a5e67a1019a848051ce7b325be921ace967d Signed-off-by: Arunteja Reddy Gopireddy --- drivers/media/platform/msm/cvp/cvp.c | 6 +- drivers/media/platform/msm/cvp/cvp_hfi.c | 56 +++++++++++++--- .../platform/msm/cvp/hfi_packetization.c | 19 ++++-- .../platform/msm/cvp/hfi_response_handler.c | 4 +- drivers/media/platform/msm/cvp/msm_cvp.c | 66 +++++++++++++++---- drivers/media/platform/msm/cvp/msm_cvp.h | 3 + drivers/media/platform/msm/cvp/msm_cvp_buf.c | 26 ++++---- .../media/platform/msm/cvp/msm_cvp_common.c | 45 ++++++++----- drivers/media/platform/msm/cvp/msm_cvp_core.c | 5 +- .../media/platform/msm/cvp/msm_cvp_internal.h | 4 ++ drivers/media/platform/msm/cvp/msm_cvp_synx.c | 3 +- 11 files changed, 173 insertions(+), 64 deletions(-) diff --git a/drivers/media/platform/msm/cvp/cvp.c b/drivers/media/platform/msm/cvp/cvp.c index 87adb4fbd975..76f7444a43b8 100644 --- a/drivers/media/platform/msm/cvp/cvp.c +++ b/drivers/media/platform/msm/cvp/cvp.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. - * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include @@ -135,6 +135,8 @@ static int msm_cvp_initialize_core(struct platform_device *pdev, INIT_LIST_HEAD(&core->instances); mutex_init(&core->lock); mutex_init(&core->clk_lock); + mutex_init(&core->idr_mtx); + idr_init(&core->sess_idr); core->state = CVP_CORE_UNINIT; for (i = SYS_MSG_INDEX(SYS_MSG_START); @@ -506,6 +508,8 @@ static int msm_cvp_remove(struct platform_device *pdev) msm_cvp_free_platform_resources(&core->resources); sysfs_remove_group(&pdev->dev.kobj, &msm_cvp_core_attr_group); dev_set_drvdata(&pdev->dev, NULL); + idr_destroy(&core->sess_idr); + mutex_destroy(&core->idr_mtx); mutex_destroy(&core->lock); mutex_destroy(&core->clk_lock); kfree(core); diff --git a/drivers/media/platform/msm/cvp/cvp_hfi.c b/drivers/media/platform/msm/cvp/cvp_hfi.c index 22340456d275..df430d2235f7 100644 --- a/drivers/media/platform/msm/cvp/cvp_hfi.c +++ b/drivers/media/platform/msm/cvp/cvp_hfi.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include @@ -29,6 +30,7 @@ #include "cvp_hfi_helper.h" #include "cvp_hfi_io.h" #include "msm_cvp_dsp.h" +#include "msm_cvp.h" #define FIRMWARE_SIZE 0X00A00000 #define REG_ADDR_OFFSET_BITMASK 0x000FFFFF @@ -469,6 +471,7 @@ static int __dsp_suspend(struct iris_hfi_device *device, bool force, u32 flags) { int rc; struct cvp_hal_session *temp; + struct msm_cvp_inst *inst = NULL; if (msm_cvp_dsp_disable) return 0; @@ -480,9 +483,10 @@ static int __dsp_suspend(struct iris_hfi_device *device, bool force, u32 flags) /* don't suspend if cvp session is not paused */ if (!(temp->flags & SESSION_PAUSE)) { + inst = (struct msm_cvp_inst *)temp->session_id; dprintk(CVP_DSP, "%s: cvp session %x not paused\n", - __func__, hash32_ptr(temp)); + __func__, inst->sess_id); return -EBUSY; } } @@ -2224,12 +2228,17 @@ static void __session_clean(struct cvp_hal_session *session) { struct cvp_hal_session *temp, *next; struct iris_hfi_device *device; + struct msm_cvp_core *core = NULL; + struct msm_cvp_inst *inst = NULL; + void *tmp = NULL; if (!session || !session->device) { dprintk(CVP_WARN, "%s: invalid params\n", __func__); return; } device = session->device; + core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list); + inst = (struct msm_cvp_inst *) session->session_id; dprintk(CVP_SESS, "deleted the session: %pK\n", session); /* * session might have been removed from the device list in @@ -2241,6 +2250,13 @@ static void __session_clean(struct cvp_hal_session *session) break; } } + /* Remove the IDR id assigned to this session */ + mutex_lock(&core->idr_mtx); + tmp = idr_remove(&core->sess_idr, inst->sess_id); + if (tmp != session) + dprintk(CVP_WARN, "%s: session\n", __func__); + mutex_unlock(&core->idr_mtx); + /* Poison the session handle with zeros */ *session = (struct cvp_hal_session){ {0} }; kfree(session); @@ -2278,6 +2294,9 @@ static int iris_hfi_session_init(void *device, void *session_id, struct cvp_hfi_cmd_sys_session_init_packet pkt; struct iris_hfi_device *dev; struct cvp_hal_session *s; + struct msm_cvp_core *core; + struct msm_cvp_inst *inst; + int id = 0; if (!device || !new_session) { dprintk(CVP_ERR, "%s - invalid input\n", __func__); @@ -2285,6 +2304,8 @@ static int iris_hfi_session_init(void *device, void *session_id, } dev = device; + core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list); + inst = session_id; mutex_lock(&dev->lock); s = kzalloc(sizeof(*s), GFP_KERNEL); @@ -2295,15 +2316,35 @@ static int iris_hfi_session_init(void *device, void *session_id, s->session_id = session_id; s->device = dev; + + mutex_lock(&core->idr_mtx); + idr_preload(GFP_KERNEL); + + /* Need to think if we can use core->lock or dev->lock or need a + * different new lock for this? + */ + id = idr_alloc(&core->sess_idr, (void *)s, 0x7FFF0000, INT_MAX, GFP_NOWAIT); + idr_preload_end(); + mutex_unlock(&core->idr_mtx); + if (id < 0) { + dprintk(CVP_ERR, + "%s: idr allocation failed for session %pK of inst %pK\n", + __func__, s, session_id); + goto err_session_init_fail; + } + dprintk(CVP_SESS, - "%s: inst %pK, session %pK\n", __func__, session_id, s); + "%s: inst %pK, session %pK, idr_id = 0x%x\n", __func__, session_id, s, id); list_add_tail(&s->list, &dev->sess_head); __set_default_sys_properties(device); + inst->sess_id = id; + if (call_hfi_pkt_op(dev, session_init, &pkt, s)) { dprintk(CVP_ERR, "session_init: failed to create packet\n"); + inst->sess_id = 0x0000DEAD; goto err_session_init_fail; } @@ -2317,6 +2358,7 @@ static int iris_hfi_session_init(void *device, void *session_id, err_session_init_fail: if (s) __session_clean(s); + inst->sess_id = 0; *new_session = NULL; mutex_unlock(&dev->lock); return -EINVAL; @@ -2878,9 +2920,11 @@ static struct cvp_hal_session *__get_session(struct iris_hfi_device *device, u32 session_id) { struct cvp_hal_session *temp = NULL; + struct msm_cvp_inst *inst = NULL; list_for_each_entry(temp, &device->sess_head, list) { - if (session_id == hash32_ptr(temp)) + inst = (struct msm_cvp_inst *)temp->session_id; + if (session_id == inst->sess_id) return temp; } @@ -3059,6 +3103,7 @@ static int __response_handler(struct iris_hfi_device *device) /* Process the packet types that we're interested in */ process_system_msg(info, device, raw_packet); + /* This session_id is a double pointer to the idr_id of session */ session_id = get_session_id(info); /* * hfi_process_msg_packet provides a session_id that's a hashed @@ -3070,11 +3115,6 @@ static int __response_handler(struct iris_hfi_device *device) if (session_id) { struct cvp_hal_session *session = NULL; - if (upper_32_bits((uintptr_t)*session_id) != 0) { - dprintk(CVP_ERR, - "Upper 32-bits != 0 for sess_id=%pK\n", - *session_id); - } session = __get_session(device, (u32)(uintptr_t)*session_id); if (!session) { diff --git a/drivers/media/platform/msm/cvp/hfi_packetization.c b/drivers/media/platform/msm/cvp/hfi_packetization.c index 107e2d744fff..edb6caaf1d34 100644 --- a/drivers/media/platform/msm/cvp/hfi_packetization.c +++ b/drivers/media/platform/msm/cvp/hfi_packetization.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include "hfi_packetization.h" @@ -208,7 +209,7 @@ inline int cvp_create_pkt_cmd_sys_session_init( pkt->size = sizeof(struct cvp_hfi_cmd_sys_session_init_packet); pkt->packet_type = HFI_CMD_SYS_SESSION_INIT; - pkt->session_id = hash32_ptr(session); + pkt->session_id = inst->sess_id; pkt->session_type = inst->prop.type; pkt->session_kmask = inst->prop.kernel_mask; pkt->session_prio = inst->prop.priority; @@ -266,13 +267,14 @@ int cvp_create_pkt_cmd_session_cmd(struct cvp_hal_session_cmd_pkt *pkt, int pkt_type, struct cvp_hal_session *session) { int rc = 0; + struct msm_cvp_inst *inst = session->session_id; if (!pkt) return -EINVAL; pkt->size = sizeof(struct cvp_hal_session_cmd_pkt); pkt->packet_type = pkt_type; - pkt->session_id = hash32_ptr(session); + pkt->session_id = inst->sess_id; return rc; } @@ -305,13 +307,14 @@ int cvp_create_pkt_cmd_session_set_buffers( { int rc = 0; struct cvp_hfi_cmd_session_set_buffers_packet *pkt; + struct msm_cvp_inst *inst = session->session_id; - if (!cmd || !session) + if (!cmd || !session || !inst) return -EINVAL; pkt = (struct cvp_hfi_cmd_session_set_buffers_packet *)cmd; pkt->packet_type = HFI_CMD_SESSION_CVP_SET_BUFFERS; - pkt->session_id = hash32_ptr(session); + pkt->session_id = inst->sess_id; pkt->buf_type.iova = iova; pkt->buf_type.size = size; pkt->size = sizeof(struct cvp_hfi_cmd_session_set_buffers_packet); @@ -324,13 +327,14 @@ int cvp_create_pkt_cmd_session_release_buffers( struct cvp_hal_session *session) { struct cvp_session_release_buffers_packet *pkt; + struct msm_cvp_inst *inst = session->session_id; - if (!cmd || !session) + if (!cmd || !session || !inst) return -EINVAL; pkt = (struct cvp_session_release_buffers_packet *)cmd; pkt->packet_type = HFI_CMD_SESSION_CVP_RELEASE_BUFFERS; - pkt->session_id = hash32_ptr(session); + pkt->session_id = inst->sess_id; pkt->num_buffers = 1; pkt->buffer_type = 0; pkt->size = sizeof(struct cvp_session_release_buffers_packet) + @@ -347,6 +351,7 @@ int cvp_create_pkt_cmd_session_send( int def_idx; struct cvp_hal_session_cmd_pkt *ptr = (struct cvp_hal_session_cmd_pkt *)in_pkt; + struct msm_cvp_inst *inst = session->session_id; if (!out_pkt || !in_pkt || !session) return -EINVAL; @@ -354,7 +359,7 @@ int cvp_create_pkt_cmd_session_send( if (ptr->size > MAX_HFI_PKT_SIZE * sizeof(unsigned int)) goto error_hfi_packet; - if (ptr->session_id != hash32_ptr(session)) + if (ptr->session_id != inst->sess_id) goto error_hfi_packet; def_idx = get_pkt_index(ptr); diff --git a/drivers/media/platform/msm/cvp/hfi_response_handler.c b/drivers/media/platform/msm/cvp/hfi_response_handler.c index 311f94106534..3c58c5d90b92 100644 --- a/drivers/media/platform/msm/cvp/hfi_response_handler.c +++ b/drivers/media/platform/msm/cvp/hfi_response_handler.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include @@ -462,7 +462,7 @@ static struct msm_cvp_inst *cvp_get_inst_from_id(struct msm_cvp_core *core, retry: if (mutex_trylock(&core->lock)) { list_for_each_entry(inst, &core->instances, list) { - if (hash32_ptr(inst->session) == session_id) { + if (inst->sess_id == session_id) { match = true; break; } diff --git a/drivers/media/platform/msm/cvp/msm_cvp.c b/drivers/media/platform/msm/cvp/msm_cvp.c index fefc06d6aee2..239ceb89acfa 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp.c +++ b/drivers/media/platform/msm/cvp/msm_cvp.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include "msm_cvp.h" @@ -14,6 +15,47 @@ struct cvp_power_level { unsigned long bw_sum; }; +void *get_sessObj_from_idr(struct msm_cvp_inst *inst) +{ + void *sessObj = NULL; + struct msm_cvp_core *core = NULL; + + if (!inst || !inst->core) { + dprintk(CVP_ERR, "%s: invalid params\n", __func__); + return NULL; + } + + core = inst->core; + mutex_lock(&core->idr_mtx); + sessObj = idr_find(&core->sess_idr, inst->sess_id); + mutex_unlock(&core->idr_mtx); + if (!sessObj) + dprintk(CVP_ERR, "%s: Could not find the sess obj for given idr id\n", + __func__); + + return sessObj; +} + +u32 get_sessId_from_idr(void *session) +{ + void *ptr = NULL; + u32 sess_id = -1; + struct msm_cvp_core *core = NULL; + + core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list); + if (!session || !core) + return -EINVAL; + mutex_lock(&core->idr_mtx); + idr_for_each_entry(&core->sess_idr, ptr, sess_id) { + if (ptr == session) { + mutex_unlock(&core->idr_mtx); + return sess_id; + } + } + mutex_unlock(&core->idr_mtx); + return sess_id; +} + static int msm_cvp_get_session_info(struct msm_cvp_inst *inst, struct cvp_kmd_session_info *session) { @@ -30,7 +72,7 @@ static int msm_cvp_get_session_info(struct msm_cvp_inst *inst, return -ECONNRESET; s->cur_cmd_type = CVP_KMD_GET_SESSION_INFO; - session->session_id = hash32_ptr(inst->session); + session->session_id = inst->sess_id; dprintk(CVP_SESS, "%s: id 0x%x\n", __func__, session->session_id); s->cur_cmd_type = 0; @@ -1227,7 +1269,7 @@ static int msm_cvp_session_stop(struct msm_cvp_inst *inst, sq->state = QUEUE_STOP; pr_info(CVP_DBG_TAG "Stop session: %pK session_id = %d\n", - "sess", inst, hash32_ptr(inst->session)); + "sess", inst, inst->sess_id); spin_unlock(&sq->lock); wake_up_all(&inst->session_queue.wq); @@ -1251,7 +1293,7 @@ int msm_cvp_session_queue_stop(struct msm_cvp_inst *inst) sq->state = QUEUE_STOP; dprintk(CVP_SESS, "Stop session queue: %pK session_id = %d\n", - inst, hash32_ptr(inst->session)); + inst, inst->sess_id); spin_unlock(&sq->lock); wake_up_all(&inst->session_queue.wq); @@ -1551,7 +1593,7 @@ static void cvp_clean_fence_queue(struct msm_cvp_inst *inst, int synx_state) ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1); dprintk(CVP_SYNX, "%s: (%#x) flush frame %llu %llu wait_list\n", - __func__, hash32_ptr(inst->session), ktid, f->frame_id); + __func__, inst->sess_id, ktid, f->frame_id); list_del_init(&f->list); msm_cvp_unmap_frame(inst, f->pkt->client_data.kdata); @@ -1564,7 +1606,7 @@ static void cvp_clean_fence_queue(struct msm_cvp_inst *inst, int synx_state) ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1); dprintk(CVP_SYNX, "%s: (%#x)flush frame %llu %llu sched_list\n", - __func__, hash32_ptr(inst->session), ktid, f->frame_id); + __func__, inst->sess_id, ktid, f->frame_id); cvp_cancel_synx(inst, CVP_INPUT_SYNX, f, synx_state); } @@ -1612,14 +1654,14 @@ static int cvp_flush_all(struct msm_cvp_inst *inst) return -ECONNRESET; dprintk(CVP_SESS, "session %llx (%#x)flush all starts\n", - inst, hash32_ptr(inst->session)); + inst, inst->sess_id); q = &inst->fence_cmd_queue; hdev = inst->core->device; cvp_clean_fence_queue(inst, SYNX_STATE_SIGNALED_CANCEL); dprintk(CVP_SESS, "%s: (%#x) send flush to fw\n", - __func__, hash32_ptr(inst->session)); + __func__, inst->sess_id); /* Send flush to FW */ rc = call_hfi_op(hdev, session_flush, (void *)inst->session); @@ -1636,7 +1678,7 @@ static int cvp_flush_all(struct msm_cvp_inst *inst) __func__, rc); dprintk(CVP_SESS, "%s: (%#x) received flush from fw\n", - __func__, hash32_ptr(inst->session)); + __func__, inst->sess_id); exit: rc = cvp_drain_fence_sched_list(inst); @@ -1859,10 +1901,10 @@ int msm_cvp_session_deinit(struct msm_cvp_inst *inst) return -EINVAL; } dprintk(CVP_SESS, "%s: inst %pK (%#x)\n", __func__, - inst, hash32_ptr(inst->session)); + inst, inst->sess_id); - session = (struct cvp_hal_session *)inst->session; - if (!session) + session = (struct cvp_hal_session *)get_sessObj_from_idr(inst); + if (!session || session != inst->session) return rc; rc = msm_cvp_comm_try_state(inst, MSM_CVP_CLOSE_DONE); @@ -1883,7 +1925,7 @@ int msm_cvp_session_init(struct msm_cvp_inst *inst) } dprintk(CVP_SESS, "%s: inst %pK (%#x)\n", __func__, - inst, hash32_ptr(inst->session)); + inst, inst->sess_id); /* set default frequency */ inst->clk_data.core_id = 0; diff --git a/drivers/media/platform/msm/cvp/msm_cvp.h b/drivers/media/platform/msm/cvp/msm_cvp.h index b21864b46f1c..b8ae6068de35 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp.h +++ b/drivers/media/platform/msm/cvp/msm_cvp.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #ifndef _MSM_CVP_H_ @@ -34,4 +35,6 @@ int msm_cvp_session_init(struct msm_cvp_inst *inst); int msm_cvp_session_deinit(struct msm_cvp_inst *inst); int msm_cvp_session_queue_stop(struct msm_cvp_inst *inst); int cvp_stop_clean_fence_queue(struct msm_cvp_inst *inst); +void *get_sessObj_from_idr(struct msm_cvp_inst *inst); +u32 get_sessId_from_idr(void *session); #endif diff --git a/drivers/media/platform/msm/cvp/msm_cvp_buf.c b/drivers/media/platform/msm/cvp/msm_cvp_buf.c index 995c111edb7d..c16eed33efd3 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp_buf.c +++ b/drivers/media/platform/msm/cvp/msm_cvp_buf.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. - * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include "msm_cvp_common.h" @@ -14,7 +14,7 @@ do { \ clear_bit(idx, &inst->dma_cache.usage_bitmap); \ dprintk(CVP_MEM, "clear %x bit %d dma_cache bitmap 0x%llx\n", \ - hash32_ptr(inst->session), smem->bitmap_index, \ + inst->sess_id, smem->bitmap_index, \ inst->dma_cache.usage_bitmap); \ } while (0) @@ -22,7 +22,7 @@ do { \ set_bit(idx, &inst->dma_cache.usage_bitmap); \ dprintk(CVP_MEM, "Set %x bit %d dma_cache bitmap 0x%llx\n", \ - hash32_ptr(inst->session), idx, \ + inst->sess_id, idx, \ inst->dma_cache.usage_bitmap); \ } while (0) @@ -36,7 +36,7 @@ void print_smem(u32 tag, const char *str, struct msm_cvp_inst *inst, if (smem->dma_buf) { dprintk(tag, "%s: %x : %s size %d flags %#x iova %#x idx %d ref %d", - str, hash32_ptr(inst->session), smem->dma_buf->name, + str, inst->sess_id, smem->dma_buf->name, smem->size, smem->flags, smem->device_addr, smem->bitmap_index, smem->refcount); } @@ -51,13 +51,13 @@ static void print_internal_buffer(u32 tag, const char *str, if (cbuf->smem->dma_buf) { dprintk(tag, "%s: %x : fd %d off %d %s size %d iova %#x", - str, hash32_ptr(inst->session), cbuf->fd, + str, inst->sess_id, cbuf->fd, cbuf->offset, cbuf->smem->dma_buf->name, cbuf->size, cbuf->smem->device_addr); } else { dprintk(tag, "%s: %x : idx %2d fd %d off %d size %d iova %#x", - str, hash32_ptr(inst->session), cbuf->fd, + str, inst->sess_id, cbuf->fd, cbuf->offset, cbuf->size, cbuf->smem->device_addr); } } @@ -77,7 +77,7 @@ void print_client_buffer(u32 tag, const char *str, dprintk(tag, "%s: %x : idx %2d fd %d off %d size %d type %d flags 0x%x\n", - str, hash32_ptr(inst->session), cbuf->index, cbuf->fd, + str, inst->sess_id, cbuf->index, cbuf->fd, cbuf->offset, cbuf->size, cbuf->type, cbuf->flags); } @@ -154,7 +154,7 @@ int msm_cvp_map_buf_dsp(struct msm_cvp_inst *inst, struct cvp_kmd_buffer *buf) } if (buf->index) { - rc = cvp_dsp_register_buffer(hash32_ptr(session), buf->fd, + rc = cvp_dsp_register_buffer(inst->sess_id, buf->fd, smem->dma_buf->size, buf->size, buf->offset, buf->index, (uint32_t)smem->device_addr); if (rc) { @@ -227,7 +227,7 @@ int msm_cvp_unmap_buf_dsp(struct msm_cvp_inst *inst, struct cvp_kmd_buffer *buf) } if (buf->index) { - rc = cvp_dsp_deregister_buffer(hash32_ptr(session), buf->fd, + rc = cvp_dsp_deregister_buffer(inst->sess_id, buf->fd, cbuf->smem->dma_buf->size, buf->size, buf->offset, buf->index, (uint32_t)cbuf->smem->device_addr); if (rc) { @@ -545,7 +545,7 @@ void msm_cvp_unmap_frame(struct msm_cvp_inst *inst, u64 ktid) ktid &= (FENCE_BIT - 1); dprintk(CVP_MEM, "%s: (%#x) unmap frame %llu\n", - __func__, hash32_ptr(inst->session), ktid); + __func__, inst->sess_id, ktid); found = false; mutex_lock(&inst->frames.lock); @@ -587,7 +587,7 @@ int msm_cvp_unmap_user_persist(struct msm_cvp_inst *inst, smem = pbuf->smem; dprintk(CVP_MEM, "unmap persist: %x %d %d %#x", - hash32_ptr(inst->session), pbuf->fd, + inst->sess_id, pbuf->fd, pbuf->size, smem->device_addr); if (smem->bitmap_index >= MAX_DMABUF_NUMS) { @@ -785,7 +785,7 @@ int msm_cvp_session_deinit_buffers(struct msm_cvp_inst *inst) list_for_each_entry_safe(cbuf, dummy, &inst->cvpdspbufs.list, list) { print_internal_buffer(CVP_MEM, "remove dspbufs", inst, cbuf); - rc = cvp_dsp_deregister_buffer(hash32_ptr(session), + rc = cvp_dsp_deregister_buffer(inst->sess_id, cbuf->fd, cbuf->smem->dma_buf->size, cbuf->size, cbuf->offset, cbuf->index, (uint32_t)cbuf->smem->device_addr); @@ -955,7 +955,7 @@ int cvp_release_arp_buffers(struct msm_cvp_inst *inst) if (buf->ownership == DRIVER) { dprintk(CVP_MEM, "%s: %x : fd %d %s size %d", - "free arp", hash32_ptr(inst->session), buf->fd, + "free arp", inst->sess_id, buf->fd, smem->dma_buf->name, buf->size); msm_cvp_smem_free(smem); kmem_cache_free(cvp_driver->smem_cache, smem); diff --git a/drivers/media/platform/msm/cvp/msm_cvp_common.c b/drivers/media/platform/msm/cvp/msm_cvp_common.c index 69787e51cc3d..22c8aa9441ad 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp_common.c +++ b/drivers/media/platform/msm/cvp/msm_cvp_common.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include @@ -195,23 +196,31 @@ struct msm_cvp_inst *cvp_get_inst_validate(struct msm_cvp_core *core, { int rc = 0; struct cvp_hfi_device *hdev; - struct msm_cvp_inst *s; + struct msm_cvp_inst *inst; + void *sessObj = NULL; - s = cvp_get_inst(core, session_id); - if (!s) { - dprintk(CVP_ERR, "%s session doesn't exit\n", + inst = cvp_get_inst(core, session_id); + if (!inst) { + dprintk(CVP_ERR, "%s Inst doesn't exit\n", __builtin_return_address(0)); return NULL; } - hdev = s->core->device; - rc = call_hfi_op(hdev, validate_session, s->session, __func__); - if (rc) { - cvp_put_inst(s); - s = NULL; + sessObj = get_sessObj_from_idr(inst); + if (!sessObj || sessObj != inst->session) { + dprintk(CVP_ERR, + "Either sessionObj is null or not matching with inst->session\n"); + return NULL; } - return s; + hdev = inst->core->device; + rc = call_hfi_op(hdev, validate_session, sessObj, __func__); + if (rc) { + cvp_put_inst(inst); + inst = NULL; + } + + return inst; } static void cvp_handle_session_cmd_done(enum hal_command_response cmd, @@ -486,7 +495,7 @@ static void handle_session_init_done(enum hal_command_response cmd, void *data) } dprintk(CVP_SESS, "%s: cvp session %#x\n", __func__, - hash32_ptr(inst->session)); + inst->sess_id); signal_session_msg_receipt(cmd, inst); cvp_put_inst(inst); @@ -568,7 +577,7 @@ static void handle_session_error(enum hal_command_response cmd, void *data) hdev = inst->core->device; dprintk(CVP_ERR, "Session error received for inst %pK session %x\n", - inst, hash32_ptr(inst->session)); + inst, inst->sess_id); if (response->status == CVP_ERR_MAX_CLIENTS) { dprintk(CVP_WARN, "Too many clients, rejecting %pK", inst); @@ -901,7 +910,7 @@ static int msm_comm_session_abort(struct msm_cvp_inst *inst) abort_completion = SESSION_MSG_INDEX(HAL_SESSION_ABORT_DONE); dprintk(CVP_WARN, "%s: inst %pK session %x\n", __func__, - inst, hash32_ptr(inst->session)); + inst, inst->sess_id); rc = call_hfi_op(hdev, session_abort, (void *)inst->session); if (rc) { dprintk(CVP_ERR, @@ -914,7 +923,7 @@ static int msm_comm_session_abort(struct msm_cvp_inst *inst) inst->core->resources.msm_cvp_hw_rsp_timeout)); if (!rc) { dprintk(CVP_ERR, "%s: inst %pK session %x abort timed out\n", - __func__, inst, hash32_ptr(inst->session)); + __func__, inst, inst->sess_id); call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data); dump_hfi_queue(hdev->hfi_device_data); msm_cvp_comm_generate_sys_error(inst); @@ -1268,7 +1277,7 @@ int msm_cvp_comm_try_state(struct msm_cvp_inst *inst, int state) } dprintk(CVP_SESS, "Trying to move inst: %pK (%#x) from: %#x to %#x\n", - inst, hash32_ptr(inst->session), inst->state, state); + inst, inst->sess_id, inst->state, state); mutex_lock(&inst->sync_lock); if (inst->state == MSM_CVP_CORE_INVALID) { @@ -1281,7 +1290,7 @@ int msm_cvp_comm_try_state(struct msm_cvp_inst *inst, int state) flipped_state = get_flipped_state(inst->state, state); dprintk(CVP_SESS, "inst: %pK (%#x) flipped_state = %#x %x\n", - inst, hash32_ptr(inst->session), flipped_state, state); + inst, inst->sess_id, flipped_state, state); switch (flipped_state) { case MSM_CVP_CORE_UNINIT_DONE: case MSM_CVP_CORE_INIT: @@ -1491,7 +1500,7 @@ int msm_cvp_comm_kill_session(struct msm_cvp_inst *inst) return 0; } dprintk(CVP_WARN, "%s: inst %pK, session %x state %d\n", __func__, - inst, hash32_ptr(inst->session), inst->state); + inst, inst->sess_id, inst->state); /* * We're internally forcibly killing the session, if fw is aware of * the session send session_abort to firmware to clean up and release @@ -1503,7 +1512,7 @@ int msm_cvp_comm_kill_session(struct msm_cvp_inst *inst) if (rc) { dprintk(CVP_ERR, "%s: inst %pK session %x abort failed\n", - __func__, inst, hash32_ptr(inst->session)); + __func__, inst, inst->sess_id); change_cvp_inst_state(inst, MSM_CVP_CORE_INVALID); } else { change_cvp_inst_state(inst, MSM_CVP_CORE_UNINIT); diff --git a/drivers/media/platform/msm/cvp/msm_cvp_core.c b/drivers/media/platform/msm/cvp/msm_cvp_core.c index 5347eade1782..b98d43730988 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp_core.c +++ b/drivers/media/platform/msm/cvp/msm_cvp_core.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include @@ -165,7 +166,7 @@ void *msm_cvp_open(int core_id, int session_type) list_for_each_entry(inst, &core->instances, list) dprintk(CVP_ERR, "inst %pK, cmd %d id %d\n", inst, inst->cur_cmd_type, - hash32_ptr(inst->session)); + inst->sess_id); mutex_unlock(&core->lock); return NULL; @@ -369,7 +370,7 @@ int msm_cvp_destroy(struct msm_cvp_inst *inst) synx_uninitialize(inst->synx_session_id); pr_info(CVP_DBG_TAG "Closed cvp instance: %pK session_id = %d\n", - "sess", inst, hash32_ptr(inst->session)); + "sess", inst, inst->sess_id); if (inst->cur_cmd_type) dprintk(CVP_ERR, "deleted instance has pending cmd %d\n", inst->cur_cmd_type); diff --git a/drivers/media/platform/msm/cvp/msm_cvp_internal.h b/drivers/media/platform/msm/cvp/msm_cvp_internal.h index 533e16cfce56..31495ad77d35 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp_internal.h +++ b/drivers/media/platform/msm/cvp/msm_cvp_internal.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #ifndef _MSM_CVP_INTERNAL_H_ @@ -290,6 +291,8 @@ struct msm_cvp_core { unsigned long curr_freq; struct cvp_cycle_info dyn_clk; atomic64_t kernel_trans_id; + struct idr sess_idr; + struct mutex idr_mtx; }; struct msm_cvp_inst { @@ -301,6 +304,7 @@ struct msm_cvp_inst { struct cvp_session_queue session_queue_fence; struct cvp_session_event event_handler; void *session; + u32 sess_id; enum instance_state state; struct msm_cvp_list freqs; struct msm_cvp_list persistbufs; diff --git a/drivers/media/platform/msm/cvp/msm_cvp_synx.c b/drivers/media/platform/msm/cvp/msm_cvp_synx.c index f70fb4013058..4580c582174b 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp_synx.c +++ b/drivers/media/platform/msm/cvp/msm_cvp_synx.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include "msm_cvp_common.h" @@ -20,7 +21,7 @@ void cvp_dump_fence_queue(struct msm_cvp_inst *inst) ssid = inst->synx_session_id; mutex_lock(&q->lock); dprintk(CVP_WARN, "inst %x fence q mode %d, ssid %d\n", - hash32_ptr(inst->session), q->mode, ssid.client_id); + inst->sess_id, q->mode, ssid.client_id); dprintk(CVP_WARN, "fence cmdq wait list:\n"); list_for_each_entry(f, &q->wait_list, list) { From 2c3bda25f8d797fe3b81218180bc8778e06b74b9 Mon Sep 17 00:00:00 2001 From: kamasali Satyanarayan Date: Mon, 29 Sep 2025 11:09:54 +0530 Subject: [PATCH 27/42] reverting enum-conversion, Handle CPU state and all USB patches 6e3e74dd047d kbuild: Move -Wenum-enum-conversion to W=2 b046ab16424e kbuild: Move -Wenum-{compare-conditional,enum-conversion} into W=1 reverting Handle CPU state 95e4f62df23f hrtimers: Handle CPU state correctly on hotplug reverting all USB patches 7a6d6b68db12 HID: usbhid: Eliminate recurrent out-of-bounds bug in usbhid_parse() b2ce37d86db3 usb: Flush altsetting 0 endpoints before reinitializating them after reset. 095cc0b5888a usb: renesas_usbhs: Reorder clock handling and power management in probe 768668e159f3 usb: usbtmc: Fix timeout value in get_stb 90da5d987601 usb: storage: Ignore UAS driver for SanDisk 3.2 Gen2 storage device 5db9d2c508ca usb: quirks: Add NO_LPM quirk for SanDisk Extreme 55AE 4f72a8dc6f67 usb: usbtmc: Fix erroneous generic_read ioctl return 85934459bc46 usb: usbtmc: Fix erroneous wait_srq ioctl return 8d9a5eaeedcd usb: usbtmc: Fix erroneous get_stb ioctl error returns 388842c35d4d USB: usbtmc: use interruptible sleep in usbtmc_read 9dda1e2a666a usb: typec: ucsi: displayport: Fix NULL pointer access 64d5ed26bff6 usb: typec: tcpm: delay SNK_TRY_WAIT_DEBOUNCE to SRC_TRYWAIT transition 30a7a793602c usb: uhci-platform: Make the clock really optional d086cca921fd usb: chipidea: ci_hdrc_imx: implement usb_phy_init() error handling b8feb22ee559 usb: chipidea: ci_hdrc_imx: use dev_err_probe() 33f2c60835a7 usb: chipidea: imx: refine the error handling for hsic 8604f111147d usb: chipidea: imx: change hsic power regulator as optional a777ccfb9ba8 usb: gadget: aspeed: Add NULL pointer check in ast_vhub_init_dev() f34551a48742 usb: host: max3421-hcd: Add missing spi_device_id table 79af6c0fa861 USB: VLI disk crashes if LPM is used 919025be9a6b usb: quirks: Add delay init quirk for SanDisk 3.2Gen1 Flash Drive ab0ffd23f312 usb: quirks: add DELAY_INIT quirk for Silicon Motion Flash Drive 015c39f38e69 usb: dwc3: gadget: check that event count does not exceed event buffer length 7109b8db9cdd USB: OHCI: Add quirk for LS7A OHCI controller (rev 0x02) eebfb64c624f usb: cdns3: Fix deadlock when using NCM gadget ec0f123f4d1a USB: serial: simple: add OWON HDS200 series oscilloscope support d75e4f33e713 USB: serial: option: add Sierra Wireless EM9291 244455a70c8a USB: serial: ftdi_sio: add support for Abacus Electrics Optical Probe 5d53a1329c80 USB: storage: quirk for ADATA Portable HDD CH94 bd4c12b86cfe usb: dwc3: support continuous runtime PM with dual role 2175d3c126c9 USB: serial: option: match on interface class for Telit FN990B f26a86f8292c USB: serial: option: fix Telit Cinterion FE990A name 57f6ae8b882f USB: serial: option: add Telit Cinterion FE990B compositions abb9f684f822 USB: serial: ftdi_sio: add support for Altera USB Blaster 3 eb00272aa51b Revert "usb: xhci: Add timeout argument in address_device USB HCD callback" 4364e0f8cfea Revert "usb: xhci: Fix NULL pointer dereference on certain command aborts" e722515dab1c xhci: pci: Fix indentation in the PCI device ID definitions 19b391884047 usb: gadget: Check bmAttributes only if configuration is valid 9af1d5c4d586 usb: gadget: Fix setting self-powered state on suspend 7367e87b6e9e usb: gadget: Set self-powered based on MaxPower and bmAttributes 094b49dec326 usb: typec: tcpci_rt1711h: Unmask alert interrupts to fix functionality b654e4c757bd usb: typec: ucsi: increase timeout for PPM reset operations dcd592ab9dd8 usb: atm: cxacru: fix a flaw in existing endpoint checks 4cd847a7b630 usb: renesas_usbhs: Flush the notify_hotplug_work a5c8be5903ec usb: quirks: Add DELAY_INIT and NO_LPM for Prolific Mass Storage Card Reader 97f8c815703e usb: renesas_usbhs: Use devm_usb_get_phy() d1968edada56 usb: renesas_usbhs: Call clk_put() 727dee085794 USB: gadget: f_midi: f_midi_complete to call queue_work 89019ab7a64f usb/gadget: f_midi: Replace tasklet with work ec42b4a0eba5 usb/gadget: f_midi: convert tasklets to use new tasklet_setup() API 19aad69c2b06 usb: dwc3: Fix timeout issue during controller enter/exit from halt state 935e842f9824 usb: dwc3: Increase DWC3 controller halt timeout 039cc7d94dc3 USB: serial: option: drop MeiG Smart defines 6621ddcdda35 USB: serial: option: fix Telit Cinterion FN990A name b95bd1248bbb USB: serial: option: add Telit Cinterion FN990B compositions 2b038768422d USB: serial: option: add MeiG Smart SLM828 7cfb70e97f09 usb: cdc-acm: Fix handling of oversized fragments a4e1ae5c0533 usb: cdc-acm: Check control transfer buffer size before access 42b30501715d USB: cdc-acm: Fill in Renesas R-Car D3 USB Download mode quirk 49f077106fa0 USB: hub: Ignore non-compliant devices with too many configs or interfaces 3a983390d14e usb: gadget: f_midi: fix MIDI Streaming descriptor lengths a0a18484cecb USB: Add USB_QUIRK_NO_LPM quirk for sony xperia xz1 smartphone a120aad69e5c USB: quirks: add USB_QUIRK_NO_LPM quirk for Teclast dist 2b8a7cfefdb2 USB: pci-quirks: Fix HCCPARAMS register error for LS7A EHCI 1c231617ac1c usb: dwc2: gadget: remove of_node reference upon udc_stop 3d921d29d48a usb: gadget: udc: renesas_usb3: Fix compiler warning 27a15815af04 usb: roles: set switch registered flag early on cc4e1d76a125 usb: gadget: f_tcm: Don't prepare BOT write request twice 54e7215ed1ab usb: gadget: f_tcm: ep_autoconfig with fullspeed endpoint 6e10b792fbf2 usb: gadget: f_tcm: Decrement command ref count on cleanup 5e051636b411 usb: gadget: f_tcm: Translate error to sense fd8bfaeba4a8 usb: xhci: Fix NULL pointer dereference on certain command aborts 7032df572eda usb: xhci: Add timeout argument in address_device USB HCD callback 7cb72dc08ed8 usb: gadget: f_tcm: Don't free command immediately 3b269db6feb2 usb: typec: tcpm: set SRC_SEND_CAPABILITIES timeout to PD_T_SENDER_RESPONSE 4b7032d01ea1 Partial revert of xhci: use pm_ptr() instead #ifdef for CONFIG_PM conditionals 1f91ebde6e35 xhci: use pm_ptr() instead of #ifdef for CONFIG_PM conditionals 76e7577bb89b Revert "usb: gadget: u_serial: Disable ep before setting port to null to fix the crash caused by port being null" fa4c7472469d USB: serial: quatech2: fix null-ptr-deref in qt2_process_read_urb() bfe60030fcd9 usb: gadget: f_fs: Remove WARN_ON in functionfs_bind b24a6afa564f usb: fix reference leak in usb_new_device() 7369c8ffc225 USB: core: Disable LPM only for non-suspended ports 01af472c23bf USB: usblp: return error when setting unsupported protocol f5f33fb57aae usb: gadget: u_serial: Disable ep before setting port to null to fix the crash caused by port being null faa0eeaf3625 USB: serial: cp210x: add Phoenix Contact UPS Device a5754f733185 usb-storage: Add max sectors quirk for Nokia 208 dffc4f7d2eca USB: serial: option: add Neoway N723-EA support f8d57de3c801 USB: serial: option: add MeiG Smart SRM815 Change-Id: Ie41f23710250fa57ccaee49aeeb96b0c3535b680 Signed-off-by: kamasali Satyanarayan --- drivers/hid/hid-hyperv.c | 5 +- drivers/hid/usbhid/hid-core.c | 25 ++++---- drivers/usb/atm/cxacru.c | 13 ++-- drivers/usb/cdns3/gadget.c | 2 - drivers/usb/chipidea/ci_hdrc_imx.c | 42 +++++++------ drivers/usb/class/cdc-acm.c | 28 +++------ drivers/usb/class/usblp.c | 7 +-- drivers/usb/class/usbtmc.c | 63 ++++++++------------ drivers/usb/core/hub.c | 33 ++-------- drivers/usb/core/port.c | 7 +-- drivers/usb/core/quirks.c | 22 ------- drivers/usb/dwc2/gadget.c | 1 - drivers/usb/dwc3/core.c | 11 +--- drivers/usb/dwc3/gadget.c | 43 +------------- drivers/usb/gadget/composite.c | 17 ++---- drivers/usb/gadget/function/f_fs.c | 2 +- drivers/usb/gadget/function/f_hid.c | 12 ++-- drivers/usb/gadget/function/f_midi.c | 22 ++++--- drivers/usb/gadget/function/f_tcm.c | 54 ++++++++++++----- drivers/usb/gadget/udc/aspeed-vhub/dev.c | 3 - drivers/usb/gadget/udc/renesas_usb3.c | 2 +- drivers/usb/host/max3421-hcd.c | 7 --- drivers/usb/host/ohci-pci.c | 23 ------- drivers/usb/host/pci-quirks.c | 9 --- drivers/usb/host/uhci-platform.c | 2 +- drivers/usb/host/xhci-pci.c | 8 +-- drivers/usb/renesas_usbhs/common.c | 56 ++++------------- drivers/usb/renesas_usbhs/mod_gadget.c | 2 +- drivers/usb/roles/class.c | 5 +- drivers/usb/serial/cp210x.c | 1 - drivers/usb/serial/ftdi_sio.c | 16 ----- drivers/usb/serial/ftdi_sio_ids.h | 18 ------ drivers/usb/serial/option.c | 76 +++++++----------------- drivers/usb/serial/quatech2.c | 2 +- drivers/usb/serial/usb-serial-simple.c | 7 --- drivers/usb/storage/unusual_devs.h | 7 --- drivers/usb/storage/unusual_uas.h | 14 ----- drivers/usb/typec/tcpm/tcpci_rt1711h.c | 11 ---- drivers/usb/typec/tcpm/tcpm.c | 4 +- drivers/usb/typec/ucsi/displayport.c | 2 - drivers/usb/typec/ucsi/ucsi.c | 2 +- include/linux/hid.h | 3 +- include/linux/hrtimer.h | 1 - include/linux/usb.h | 3 +- include/linux/usb/hcd.h | 2 + kernel/time/hrtimer.c | 11 +--- scripts/Makefile.extrawarn | 5 -- 47 files changed, 199 insertions(+), 512 deletions(-) diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c index f9eb7ebec76f..5928e934d734 100644 --- a/drivers/hid/hid-hyperv.c +++ b/drivers/hid/hid-hyperv.c @@ -197,8 +197,7 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, if (!input_device->hid_desc) goto cleanup; - input_device->report_desc_size = le16_to_cpu( - desc->rpt_desc.wDescriptorLength); + input_device->report_desc_size = desc->desc[0].wDescriptorLength; if (input_device->report_desc_size == 0) { input_device->dev_info_status = -EINVAL; goto cleanup; @@ -214,7 +213,7 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, memcpy(input_device->report_desc, ((unsigned char *)desc) + desc->bLength, - le16_to_cpu(desc->rpt_desc.wDescriptorLength)); + desc->desc[0].wDescriptorLength); /* Send the ack */ memset(&ack, 0, sizeof(struct mousevsc_prt_msg)); diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 6e5770b8cc4c..8537fcdb456d 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -984,11 +984,12 @@ static int usbhid_parse(struct hid_device *hid) struct usb_host_interface *interface = intf->cur_altsetting; struct usb_device *dev = interface_to_usbdev (intf); struct hid_descriptor *hdesc; - struct hid_class_descriptor *hcdesc; u32 quirks = 0; unsigned int rsize = 0; char *rdesc; - int ret; + int ret, n; + int num_descriptors; + size_t offset = offsetof(struct hid_descriptor, desc); quirks = hid_lookup_quirk(hid); @@ -1010,19 +1011,20 @@ static int usbhid_parse(struct hid_device *hid) return -ENODEV; } - if (!hdesc->bNumDescriptors || - hdesc->bLength != sizeof(*hdesc) + - (hdesc->bNumDescriptors - 1) * sizeof(*hcdesc)) { - dbg_hid("hid descriptor invalid, bLen=%hhu bNum=%hhu\n", - hdesc->bLength, hdesc->bNumDescriptors); + if (hdesc->bLength < sizeof(struct hid_descriptor)) { + dbg_hid("hid descriptor is too short\n"); return -EINVAL; } hid->version = le16_to_cpu(hdesc->bcdHID); hid->country = hdesc->bCountryCode; - if (hdesc->rpt_desc.bDescriptorType == HID_DT_REPORT) - rsize = le16_to_cpu(hdesc->rpt_desc.wDescriptorLength); + num_descriptors = min_t(int, hdesc->bNumDescriptors, + (hdesc->bLength - offset) / sizeof(struct hid_class_descriptor)); + + for (n = 0; n < num_descriptors; n++) + if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT) + rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength); if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) { dbg_hid("weird size of report descriptor (%u)\n", rsize); @@ -1050,11 +1052,6 @@ static int usbhid_parse(struct hid_device *hid) goto err; } - if (hdesc->bNumDescriptors > 1) - hid_warn(intf, - "%u unsupported optional hid class descriptors\n", - (int)(hdesc->bNumDescriptors - 1)); - hid->quirks |= quirks; return 0; diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index a4d863f6cda7..51d42c69fb5e 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -1135,10 +1135,7 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, struct cxacru_data *instance; struct usb_device *usb_dev = interface_to_usbdev(intf); struct usb_host_endpoint *cmd_ep = usb_dev->ep_in[CXACRU_EP_CMD]; - static const u8 ep_addrs[] = { - CXACRU_EP_CMD + USB_DIR_IN, - CXACRU_EP_CMD + USB_DIR_OUT, - 0}; + struct usb_endpoint_descriptor *in, *out; int ret; /* instance init */ @@ -1186,11 +1183,13 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, } if (usb_endpoint_xfer_int(&cmd_ep->desc)) - ret = usb_check_int_endpoints(intf, ep_addrs); + ret = usb_find_common_endpoints(intf->cur_altsetting, + NULL, NULL, &in, &out); else - ret = usb_check_bulk_endpoints(intf, ep_addrs); + ret = usb_find_common_endpoints(intf->cur_altsetting, + &in, &out, NULL, NULL); - if (!ret) { + if (ret) { usb_err(usbatm_instance, "cxacru_bind: interface has incorrect endpoints\n"); ret = -ENODEV; goto fail; diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c index 88c3c3a1e189..61283e7e602a 100644 --- a/drivers/usb/cdns3/gadget.c +++ b/drivers/usb/cdns3/gadget.c @@ -1920,7 +1920,6 @@ static int cdns3_gadget_ep_disable(struct usb_ep *ep) "%s is already disabled\n", priv_ep->name)) return 0; - local_bh_disable(); spin_lock_irqsave(&priv_dev->lock, flags); trace_cdns3_gadget_ep_disable(priv_ep); @@ -1977,7 +1976,6 @@ static int cdns3_gadget_ep_disable(struct usb_ep *ep) priv_ep->flags &= ~EP_ENABLED; spin_unlock_irqrestore(&priv_dev->lock, flags); - local_bh_enable(); return ret; } diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index d4566b5ec348..0fe545815c5c 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c @@ -340,11 +340,11 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) pdata.flags |= CI_HDRC_IMX_IS_HSIC; data->usbmisc_data->hsic = 1; data->pinctrl = devm_pinctrl_get(dev); - if (PTR_ERR(data->pinctrl) == -ENODEV) - data->pinctrl = NULL; - else if (IS_ERR(data->pinctrl)) - return dev_err_probe(dev, PTR_ERR(data->pinctrl), - "pinctrl get failed\n"); + if (IS_ERR(data->pinctrl)) { + dev_err(dev, "pinctrl get failed, err=%ld\n", + PTR_ERR(data->pinctrl)); + return PTR_ERR(data->pinctrl); + } pinctrl_hsic_idle = pinctrl_lookup_state(data->pinctrl, "idle"); if (IS_ERR(pinctrl_hsic_idle)) { @@ -369,14 +369,17 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) return PTR_ERR(data->pinctrl_hsic_active); } - data->hsic_pad_regulator = - devm_regulator_get_optional(dev, "hsic"); - if (PTR_ERR(data->hsic_pad_regulator) == -ENODEV) { + data->hsic_pad_regulator = devm_regulator_get(dev, "hsic"); + if (PTR_ERR(data->hsic_pad_regulator) == -EPROBE_DEFER) { + return -EPROBE_DEFER; + } else if (PTR_ERR(data->hsic_pad_regulator) == -ENODEV) { /* no pad regualator is needed */ data->hsic_pad_regulator = NULL; - } else if (IS_ERR(data->hsic_pad_regulator)) - return dev_err_probe(dev, PTR_ERR(data->hsic_pad_regulator), - "Get HSIC pad regulator error\n"); + } else if (IS_ERR(data->hsic_pad_regulator)) { + dev_err(dev, "Get HSIC pad regulator error: %ld\n", + PTR_ERR(data->hsic_pad_regulator)); + return PTR_ERR(data->hsic_pad_regulator); + } if (data->hsic_pad_regulator) { ret = regulator_enable(data->hsic_pad_regulator); @@ -417,11 +420,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI) { pdata.flags |= CI_HDRC_OVERRIDE_PHY_CONTROL; data->override_phy_control = true; - ret = usb_phy_init(pdata.usb_phy); - if (ret) { - dev_err(dev, "Failed to init phy\n"); - goto err_clk; - } + usb_phy_init(pdata.usb_phy); } if (pdata.flags & CI_HDRC_SUPPORTS_RUNTIME_PM) @@ -430,7 +429,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) ret = imx_usbmisc_init(data->usbmisc_data); if (ret) { dev_err(dev, "usbmisc init failed, ret=%d\n", ret); - goto phy_shutdown; + goto err_clk; } data->ci_pdev = ci_hdrc_add_device(dev, @@ -438,8 +437,10 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) &pdata); if (IS_ERR(data->ci_pdev)) { ret = PTR_ERR(data->ci_pdev); - dev_err_probe(dev, ret, "ci_hdrc_add_device failed\n"); - goto phy_shutdown; + if (ret != -EPROBE_DEFER) + dev_err(dev, "ci_hdrc_add_device failed, err=%d\n", + ret); + goto err_clk; } ret = imx_usbmisc_init_post(data->usbmisc_data); @@ -459,9 +460,6 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) disable_device: ci_hdrc_remove_device(data->ci_pdev); -phy_shutdown: - if (data->override_phy_control) - usb_phy_shutdown(data->phy); err_clk: imx_disable_unprepare_clks(dev); disable_hsic_regulator: diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 59a354822413..8b9740142152 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -359,7 +359,7 @@ static void acm_process_notification(struct acm *acm, unsigned char *buf) static void acm_ctrl_irq(struct urb *urb) { struct acm *acm = urb->context; - struct usb_cdc_notification *dr; + struct usb_cdc_notification *dr = urb->transfer_buffer; unsigned int current_size = urb->actual_length; unsigned int expected_size, copy_size, alloc_size; int retval; @@ -386,25 +386,14 @@ static void acm_ctrl_irq(struct urb *urb) usb_mark_last_busy(acm->dev); - if (acm->nb_index == 0) { - /* - * The first chunk of a message must contain at least the - * notification header with the length field, otherwise we - * can't get an expected_size. - */ - if (current_size < sizeof(struct usb_cdc_notification)) { - dev_dbg(&acm->control->dev, "urb too short\n"); - goto exit; - } - dr = urb->transfer_buffer; - } else { + if (acm->nb_index) dr = (struct usb_cdc_notification *)acm->notification_buffer; - } + /* size = notification-header + (optional) data */ expected_size = sizeof(struct usb_cdc_notification) + le16_to_cpu(dr->wLength); - if (acm->nb_index != 0 || current_size < expected_size) { + if (current_size < expected_size) { /* notification is transmitted fragmented, reassemble */ if (acm->nb_size < expected_size) { u8 *new_buffer; @@ -1744,16 +1733,13 @@ static const struct usb_device_id acm_ids[] = { { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ }, - { USB_DEVICE(0x045b, 0x023c), /* Renesas R-Car H3 USB Download mode */ + { USB_DEVICE(0x045b, 0x023c), /* Renesas USB Download mode */ .driver_info = DISABLE_ECHO, /* Don't echo banner */ }, - { USB_DEVICE(0x045b, 0x0247), /* Renesas R-Car D3 USB Download mode */ + { USB_DEVICE(0x045b, 0x0248), /* Renesas USB Download mode */ .driver_info = DISABLE_ECHO, /* Don't echo banner */ }, - { USB_DEVICE(0x045b, 0x0248), /* Renesas R-Car M3-N USB Download mode */ - .driver_info = DISABLE_ECHO, /* Don't echo banner */ - }, - { USB_DEVICE(0x045b, 0x024D), /* Renesas R-Car E3 USB Download mode */ + { USB_DEVICE(0x045b, 0x024D), /* Renesas USB Download mode */ .driver_info = DISABLE_ECHO, /* Don't echo banner */ }, { USB_DEVICE(0x0e8d, 0x0003), /* FIREFLY, MediaTek Inc; andrey.arapov@gmail.com */ diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 759f567538e2..f27b4aecff3d 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -1337,12 +1337,11 @@ static int usblp_set_protocol(struct usblp *usblp, int protocol) if (protocol < USBLP_FIRST_PROTOCOL || protocol > USBLP_LAST_PROTOCOL) return -EINVAL; - alts = usblp->protocol[protocol].alt_setting; - if (alts < 0) - return -EINVAL; - /* Don't unnecessarily set the interface if there's a single alt. */ if (usblp->intf->num_altsetting > 1) { + alts = usblp->protocol[protocol].alt_setting; + if (alts < 0) + return -EINVAL; r = usb_set_interface(usblp->dev, usblp->ifnum, alts); if (r < 0) { printk(KERN_ERR "usblp: can't set desired altsetting %d on interface %d\n", diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index d8ed205e6b43..00345a51f18d 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -485,8 +485,6 @@ static int usbtmc488_ioctl_read_stb(struct usbtmc_file_data *file_data, u8 tag; __u8 stb; int rv; - long wait_rv; - unsigned long expire; dev_dbg(dev, "Enter ioctl_read_stb iin_ep_present: %d\n", data->iin_ep_present); @@ -529,18 +527,16 @@ static int usbtmc488_ioctl_read_stb(struct usbtmc_file_data *file_data, } if (data->iin_ep_present) { - expire = msecs_to_jiffies(file_data->timeout); - wait_rv = wait_event_interruptible_timeout( + rv = wait_event_interruptible_timeout( data->waitq, atomic_read(&data->iin_data_valid) != 0, - expire); - if (wait_rv < 0) { - dev_dbg(dev, "wait interrupted %ld\n", wait_rv); - rv = wait_rv; + file_data->timeout); + if (rv < 0) { + dev_dbg(dev, "wait interrupted %d\n", rv); goto exit; } - if (wait_rv == 0) { + if (rv == 0) { dev_dbg(dev, "wait timed out\n"); rv = -ETIMEDOUT; goto exit; @@ -560,8 +556,6 @@ static int usbtmc488_ioctl_read_stb(struct usbtmc_file_data *file_data, rv = put_user(stb, (__u8 __user *)arg); dev_dbg(dev, "stb:0x%02x received %d\n", (unsigned int)stb, rv); - rv = 0; - exit: /* bump interrupt bTag */ data->iin_bTag += 1; @@ -578,9 +572,9 @@ static int usbtmc488_ioctl_wait_srq(struct usbtmc_file_data *file_data, { struct usbtmc_device_data *data = file_data->data; struct device *dev = &data->intf->dev; + int rv; u32 timeout; unsigned long expire; - long wait_rv; if (!data->iin_ep_present) { dev_dbg(dev, "no interrupt endpoint present\n"); @@ -594,24 +588,25 @@ static int usbtmc488_ioctl_wait_srq(struct usbtmc_file_data *file_data, mutex_unlock(&data->io_mutex); - wait_rv = wait_event_interruptible_timeout( - data->waitq, - atomic_read(&file_data->srq_asserted) != 0 || - atomic_read(&file_data->closing), - expire); + rv = wait_event_interruptible_timeout( + data->waitq, + atomic_read(&file_data->srq_asserted) != 0 || + atomic_read(&file_data->closing), + expire); mutex_lock(&data->io_mutex); /* Note! disconnect or close could be called in the meantime */ if (atomic_read(&file_data->closing) || data->zombie) - return -ENODEV; + rv = -ENODEV; - if (wait_rv < 0) { - dev_dbg(dev, "%s - wait interrupted %ld\n", __func__, wait_rv); - return wait_rv; + if (rv < 0) { + /* dev can be invalid now! */ + pr_debug("%s - wait interrupted %d\n", __func__, rv); + return rv; } - if (wait_rv == 0) { + if (rv == 0) { dev_dbg(dev, "%s - wait timed out\n", __func__); return -ETIMEDOUT; } @@ -805,7 +800,6 @@ static ssize_t usbtmc_generic_read(struct usbtmc_file_data *file_data, unsigned long expire; int bufcount = 1; int again = 0; - long wait_rv; /* mutex already locked */ @@ -918,24 +912,19 @@ static ssize_t usbtmc_generic_read(struct usbtmc_file_data *file_data, if (!(flags & USBTMC_FLAG_ASYNC)) { dev_dbg(dev, "%s: before wait time %lu\n", __func__, expire); - wait_rv = wait_event_interruptible_timeout( + retval = wait_event_interruptible_timeout( file_data->wait_bulk_in, usbtmc_do_transfer(file_data), expire); - dev_dbg(dev, "%s: wait returned %ld\n", - __func__, wait_rv); + dev_dbg(dev, "%s: wait returned %d\n", + __func__, retval); - if (wait_rv < 0) { - retval = wait_rv; + if (retval <= 0) { + if (retval == 0) + retval = -ETIMEDOUT; goto error; } - - if (wait_rv == 0) { - retval = -ETIMEDOUT; - goto error; - } - } urb = usb_get_from_anchor(&file_data->in_anchor); @@ -1361,10 +1350,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, if (!buffer) return -ENOMEM; - retval = mutex_lock_interruptible(&data->io_mutex); - if (retval < 0) - goto exit_nolock; - + mutex_lock(&data->io_mutex); if (data->zombie) { retval = -ENODEV; goto exit; @@ -1487,7 +1473,6 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, exit: mutex_unlock(&data->io_mutex); -exit_nolock: kfree(buffer); return retval; } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 44e7c2c39320..5dab663b7628 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1793,17 +1793,6 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) desc = intf->cur_altsetting; hdev = interface_to_usbdev(intf); - /* - * The USB 2.0 spec prohibits hubs from having more than one - * configuration or interface, and we rely on this prohibition. - * Refuse to accept a device that violates it. - */ - if (hdev->descriptor.bNumConfigurations > 1 || - hdev->actconfig->desc.bNumInterfaces > 1) { - dev_err(&intf->dev, "Invalid hub with more than one config or interface\n"); - return -EINVAL; - } - /* * Set default autosuspend delay as 0 to speedup bus suspend, * based on the below considerations: @@ -2604,13 +2593,13 @@ int usb_new_device(struct usb_device *udev) err = sysfs_create_link(&udev->dev.kobj, &port_dev->dev.kobj, "port"); if (err) - goto out_del_dev; + goto fail; err = sysfs_create_link(&port_dev->dev.kobj, &udev->dev.kobj, "device"); if (err) { sysfs_remove_link(&udev->dev.kobj, "port"); - goto out_del_dev; + goto fail; } if (!test_and_set_bit(port1, hub->child_usage_bits)) @@ -2622,8 +2611,6 @@ int usb_new_device(struct usb_device *udev) pm_runtime_put_sync_autosuspend(&udev->dev); return err; -out_del_dev: - device_del(&udev->dev); fail: usb_set_device_state(udev, USB_STATE_NOTATTACHED); pm_runtime_disable(&udev->dev); @@ -5831,7 +5818,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev) struct usb_hub *parent_hub; struct usb_hcd *hcd = bus_to_hcd(udev->bus); struct usb_device_descriptor descriptor = udev->descriptor; - struct usb_interface *intf; struct usb_host_bos *bos; int i, j, ret = 0; int port1 = udev->portnum; @@ -5893,18 +5879,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev) if (!udev->actconfig) goto done; - /* - * Some devices can't handle setting default altsetting 0 with a - * Set-Interface request. Disable host-side endpoints of those - * interfaces here. Enable and reset them back after host has set - * its internal endpoint structures during usb_hcd_alloc_bandwith() - */ - for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { - intf = udev->actconfig->interface[i]; - if (intf->cur_altsetting->desc.bAlternateSetting == 0) - usb_disable_interface(udev, intf, true); - } - mutex_lock(hcd->bandwidth_mutex); ret = usb_hcd_alloc_bandwidth(udev, udev->actconfig, NULL, NULL); if (ret < 0) { @@ -5936,11 +5910,12 @@ static int usb_reset_and_verify_device(struct usb_device *udev) */ for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { struct usb_host_config *config = udev->actconfig; + struct usb_interface *intf = config->interface[i]; struct usb_interface_descriptor *desc; - intf = config->interface[i]; desc = &intf->cur_altsetting->desc; if (desc->bAlternateSetting == 0) { + usb_disable_interface(udev, intf, true); usb_enable_interface(udev, intf, true); ret = 0; } else { diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index f01b0103fe12..86e8585a5512 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -294,11 +294,10 @@ static int usb_port_runtime_suspend(struct device *dev) static void usb_port_shutdown(struct device *dev) { struct usb_port *port_dev = to_usb_port(dev); - struct usb_device *udev = port_dev->child; - if (udev && !udev->port_is_suspended) { - usb_disable_usb2_hardware_lpm(udev); - usb_unlocked_disable_lpm(udev); + if (port_dev->child) { + usb_disable_usb2_hardware_lpm(port_dev->child); + usb_unlocked_disable_lpm(port_dev->child); } } diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 98b1c457a091..a158bf40373b 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -338,10 +338,6 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x0638, 0x0a13), .driver_info = USB_QUIRK_STRING_FETCH_255 }, - /* Prolific Single-LUN Mass Storage Card Reader */ - { USB_DEVICE(0x067b, 0x2731), .driver_info = USB_QUIRK_DELAY_INIT | - USB_QUIRK_NO_LPM }, - /* Saitek Cyborg Gold Joystick */ { USB_DEVICE(0x06a3, 0x0006), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, @@ -366,12 +362,6 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x0781, 0x5583), .driver_info = USB_QUIRK_NO_LPM }, { USB_DEVICE(0x0781, 0x5591), .driver_info = USB_QUIRK_NO_LPM }, - /* SanDisk Corp. SanDisk 3.2Gen1 */ - { USB_DEVICE(0x0781, 0x55a3), .driver_info = USB_QUIRK_DELAY_INIT }, - - /* SanDisk Extreme 55AE */ - { USB_DEVICE(0x0781, 0x55ae), .driver_info = USB_QUIRK_NO_LPM }, - /* Realforce 87U Keyboard */ { USB_DEVICE(0x0853, 0x011b), .driver_info = USB_QUIRK_NO_LPM }, @@ -386,9 +376,6 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x0904, 0x6103), .driver_info = USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL }, - /* Silicon Motion Flash Drive */ - { USB_DEVICE(0x090c, 0x1000), .driver_info = USB_QUIRK_DELAY_INIT }, - /* Sound Devices USBPre2 */ { USB_DEVICE(0x0926, 0x0202), .driver_info = USB_QUIRK_ENDPOINT_BLACKLIST }, @@ -443,9 +430,6 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x0c45, 0x7056), .driver_info = USB_QUIRK_IGNORE_REMOTE_WAKEUP }, - /* Sony Xperia XZ1 Compact (lilac) smartphone in fastboot mode */ - { USB_DEVICE(0x0fce, 0x0dde), .driver_info = USB_QUIRK_NO_LPM }, - /* Action Semiconductor flash disk */ { USB_DEVICE(0x10d6, 0x2200), .driver_info = USB_QUIRK_STRING_FETCH_255 }, @@ -536,16 +520,10 @@ static const struct usb_device_id usb_quirk_list[] = { /* Blackmagic Design UltraStudio SDI */ { USB_DEVICE(0x1edb, 0xbd4f), .driver_info = USB_QUIRK_NO_LPM }, - /* Teclast disk */ - { USB_DEVICE(0x1f75, 0x0917), .driver_info = USB_QUIRK_NO_LPM }, - /* Hauppauge HVR-950q */ { USB_DEVICE(0x2040, 0x7200), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, - /* VLI disk */ - { USB_DEVICE(0x2109, 0x0711), .driver_info = USB_QUIRK_NO_LPM }, - /* Raydium Touchscreen */ { USB_DEVICE(0x2386, 0x3114), .driver_info = USB_QUIRK_NO_LPM }, diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 74d2dbf9a535..abc2271799e0 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -4548,7 +4548,6 @@ static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget) spin_lock_irqsave(&hsotg->lock, flags); hsotg->driver = NULL; - hsotg->gadget.dev.of_node = NULL; hsotg->gadget.speed = USB_SPEED_UNKNOWN; hsotg->enabled = 0; diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index a262ccd1cf92..7caa6aacf9d4 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -122,19 +122,17 @@ static void __dwc3_set_mode(struct work_struct *work) if (dwc->dr_mode != USB_DR_MODE_OTG) return; - pm_runtime_get_sync(dwc->dev); - if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_OTG) dwc3_otg_update(dwc, 0); if (!dwc->desired_dr_role) - goto out; + return; if (dwc->desired_dr_role == dwc->current_dr_role) - goto out; + return; if (dwc->desired_dr_role == DWC3_GCTL_PRTCAP_OTG && dwc->edev) - goto out; + return; switch (dwc->current_dr_role) { case DWC3_GCTL_PRTCAP_HOST: @@ -198,9 +196,6 @@ static void __dwc3_set_mode(struct work_struct *work) break; } -out: - pm_runtime_mark_last_busy(dwc->dev); - pm_runtime_put_autosuspend(dwc->dev); } void dwc3_set_mode(struct dwc3 *dwc, u32 mode) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 76316205483b..6caedef5575d 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1966,39 +1966,11 @@ static void dwc3_stop_active_transfers(struct dwc3 *dwc) static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend) { u32 reg; - u32 timeout = 2000; - u32 saved_config = 0; + u32 timeout = 500; if (pm_runtime_suspended(dwc->dev)) return 0; - /* - * When operating in USB 2.0 speeds (HS/FS), ensure that - * GUSB2PHYCFG.ENBLSLPM and GUSB2PHYCFG.SUSPHY are cleared before starting - * or stopping the controller. This resolves timeout issues that occur - * during frequent role switches between host and device modes. - * - * Save and clear these settings, then restore them after completing the - * controller start or stop sequence. - * - * This solution was discovered through experimentation as it is not - * mentioned in the dwc3 programming guide. It has been tested on an - * Exynos platforms. - */ - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); - if (reg & DWC3_GUSB2PHYCFG_SUSPHY) { - saved_config |= DWC3_GUSB2PHYCFG_SUSPHY; - reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; - } - - if (reg & DWC3_GUSB2PHYCFG_ENBLSLPM) { - saved_config |= DWC3_GUSB2PHYCFG_ENBLSLPM; - reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; - } - - if (saved_config) - dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); - reg = dwc3_readl(dwc->regs, DWC3_DCTL); if (is_on) { if (dwc->revision <= DWC3_REVISION_187A) { @@ -2026,17 +1998,10 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend) dwc3_writel(dwc->regs, DWC3_DCTL, reg); do { - usleep_range(1000, 2000); reg = dwc3_readl(dwc->regs, DWC3_DSTS); reg &= DWC3_DSTS_DEVCTRLHLT; } while (--timeout && !(!is_on ^ !reg)); - if (saved_config) { - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); - reg |= saved_config; - dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); - } - if (!timeout) return -ETIMEDOUT; @@ -3652,12 +3617,6 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt) if (!count) return IRQ_NONE; - if (count > evt->length) { - dev_err_ratelimited(dwc->dev, "invalid count(%u) > evt->length(%u)\n", - count, evt->length); - return IRQ_NONE; - } - evt->count = count; evt->flags |= DWC3_EVENT_PENDING; diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 4b2e9df97b11..3596ff37b9ef 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -915,11 +915,10 @@ static int set_config(struct usb_composite_dev *cdev, else power = min(power, 900U); done: - if (power > USB_SELF_POWER_VBUS_MAX_DRAW || - (c && !(c->bmAttributes & USB_CONFIG_ATT_SELFPOWER))) - usb_gadget_clear_selfpowered(gadget); - else + if (power <= USB_SELF_POWER_VBUS_MAX_DRAW) usb_gadget_set_selfpowered(gadget); + else + usb_gadget_clear_selfpowered(gadget); usb_gadget_vbus_draw(gadget, power); if (result >= 0 && cdev->delayed_status) @@ -2366,10 +2365,7 @@ void composite_suspend(struct usb_gadget *gadget) cdev->suspended = 1; - if (cdev->config && - cdev->config->bmAttributes & USB_CONFIG_ATT_SELFPOWER) - usb_gadget_set_selfpowered(gadget); - + usb_gadget_set_selfpowered(gadget); usb_gadget_vbus_draw(gadget, 2); } @@ -2398,11 +2394,8 @@ void composite_resume(struct usb_gadget *gadget) else maxpower = min(maxpower, 900U); - if (maxpower > USB_SELF_POWER_VBUS_MAX_DRAW || - !(cdev->config->bmAttributes & USB_CONFIG_ATT_SELFPOWER)) + if (maxpower > USB_SELF_POWER_VBUS_MAX_DRAW) usb_gadget_clear_selfpowered(gadget); - else - usb_gadget_set_selfpowered(gadget); usb_gadget_vbus_draw(gadget, maxpower); } diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 9b5f9d503ff0..53658162b148 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -1875,7 +1875,7 @@ static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev) ENTER(); - if ((ffs->state != FFS_ACTIVE + if (WARN_ON(ffs->state != FFS_ACTIVE || test_and_set_bit(FFS_FL_BOUND, &ffs->flags))) return -EBADFD; diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c index 77354626252c..571560d689c8 100644 --- a/drivers/usb/gadget/function/f_hid.c +++ b/drivers/usb/gadget/function/f_hid.c @@ -114,8 +114,8 @@ static struct hid_descriptor hidg_desc = { .bcdHID = cpu_to_le16(0x0101), .bCountryCode = 0x00, .bNumDescriptors = 0x1, - /*.rpt_desc.bDescriptorType = DYNAMIC */ - /*.rpt_desc.wDescriptorLength = DYNAMIC */ + /*.desc[0].bDescriptorType = DYNAMIC */ + /*.desc[0].wDescriptorLenght = DYNAMIC */ }; /* Super-Speed Support */ @@ -730,8 +730,8 @@ static int hidg_setup(struct usb_function *f, struct hid_descriptor hidg_desc_copy = hidg_desc; VDBG(cdev, "USB_REQ_GET_DESCRIPTOR: HID\n"); - hidg_desc_copy.rpt_desc.bDescriptorType = HID_DT_REPORT; - hidg_desc_copy.rpt_desc.wDescriptorLength = + hidg_desc_copy.desc[0].bDescriptorType = HID_DT_REPORT; + hidg_desc_copy.desc[0].wDescriptorLength = cpu_to_le16(hidg->report_desc_length); length = min_t(unsigned short, length, @@ -972,8 +972,8 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f) * We can use hidg_desc struct here but we should not relay * that its content won't change after returning from this function. */ - hidg_desc.rpt_desc.bDescriptorType = HID_DT_REPORT; - hidg_desc.rpt_desc.wDescriptorLength = + hidg_desc.desc[0].bDescriptorType = HID_DT_REPORT; + hidg_desc.desc[0].wDescriptorLength = cpu_to_le16(hidg->report_desc_length); hidg_hs_in_ep_desc.bEndpointAddress = diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c index b741cdcd0128..6745919144b8 100644 --- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c @@ -87,7 +87,7 @@ struct f_midi { struct snd_rawmidi_substream *out_substream[MAX_PORTS]; unsigned long out_triggered; - struct work_struct work; + struct tasklet_struct tasklet; unsigned int in_ports; unsigned int out_ports; int index; @@ -282,7 +282,7 @@ f_midi_complete(struct usb_ep *ep, struct usb_request *req) /* Our transmit completed. See if there's more to go. * f_midi_transmit eats req, don't queue it again. */ req->length = 0; - queue_work(system_highpri_wq, &midi->work); + f_midi_transmit(midi); return; } break; @@ -698,11 +698,9 @@ drop_out: f_midi_drop_out_substreams(midi); } -static void f_midi_in_work(struct work_struct *work) +static void f_midi_in_tasklet(unsigned long data) { - struct f_midi *midi; - - midi = container_of(work, struct f_midi, work); + struct f_midi *midi = (struct f_midi *) data; f_midi_transmit(midi); } @@ -739,7 +737,7 @@ static void f_midi_in_trigger(struct snd_rawmidi_substream *substream, int up) VDBG(midi, "%s() %d\n", __func__, up); midi->in_ports_array[substream->number].active = up; if (up) - queue_work(system_highpri_wq, &midi->work); + tasklet_hi_schedule(&midi->tasklet); } static int f_midi_out_open(struct snd_rawmidi_substream *substream) @@ -877,7 +875,7 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f) int status, n, jack = 1, i = 0, endpoint_descriptor_index = 0; midi->gadget = cdev->gadget; - INIT_WORK(&midi->work, f_midi_in_work); + tasklet_init(&midi->tasklet, f_midi_in_tasklet, (unsigned long) midi); status = f_midi_register_card(midi); if (status < 0) goto fail_register; @@ -999,11 +997,11 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f) } /* configure the endpoint descriptors ... */ - ms_out_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->out_ports); - ms_out_desc.bNumEmbMIDIJack = midi->out_ports; + ms_out_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->in_ports); + ms_out_desc.bNumEmbMIDIJack = midi->in_ports; - ms_in_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->in_ports); - ms_in_desc.bNumEmbMIDIJack = midi->in_ports; + ms_in_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->out_ports); + ms_in_desc.bNumEmbMIDIJack = midi->out_ports; /* ... and add them to the list */ endpoint_descriptor_index = i; diff --git a/drivers/usb/gadget/function/f_tcm.c b/drivers/usb/gadget/function/f_tcm.c index 90fe33f9e095..41a10bcc2efc 100644 --- a/drivers/usb/gadget/function/f_tcm.c +++ b/drivers/usb/gadget/function/f_tcm.c @@ -245,6 +245,7 @@ static int bot_send_write_request(struct usbg_cmd *cmd) { struct f_uas *fu = cmd->fu; struct se_cmd *se_cmd = &cmd->se_cmd; + struct usb_gadget *gadget = fuas_to_gadget(fu); int ret; init_completion(&cmd->write_complete); @@ -255,6 +256,22 @@ static int bot_send_write_request(struct usbg_cmd *cmd) return -EINVAL; } + if (!gadget->sg_supported) { + cmd->data_buf = kmalloc(se_cmd->data_length, GFP_KERNEL); + if (!cmd->data_buf) + return -ENOMEM; + + fu->bot_req_out->buf = cmd->data_buf; + } else { + fu->bot_req_out->buf = NULL; + fu->bot_req_out->num_sgs = se_cmd->t_data_nents; + fu->bot_req_out->sg = se_cmd->t_data_sg; + } + + fu->bot_req_out->complete = usbg_data_write_cmpl; + fu->bot_req_out->length = se_cmd->data_length; + fu->bot_req_out->context = cmd; + ret = usbg_prepare_w_request(cmd, fu->bot_req_out); if (ret) goto cleanup; @@ -954,7 +971,6 @@ static void usbg_data_write_cmpl(struct usb_ep *ep, struct usb_request *req) return; cleanup: - target_put_sess_cmd(se_cmd); transport_generic_free_cmd(&cmd->se_cmd, 0); } @@ -1047,7 +1063,8 @@ static void usbg_cmd_work(struct work_struct *work) out: transport_send_check_condition_and_sense(se_cmd, - TCM_UNSUPPORTED_SCSI_OPCODE, 0); + TCM_UNSUPPORTED_SCSI_OPCODE, 1); + transport_generic_free_cmd(&cmd->se_cmd, 0); } static struct usbg_cmd *usbg_get_cmd(struct f_uas *fu, @@ -1176,7 +1193,8 @@ static void bot_cmd_work(struct work_struct *work) out: transport_send_check_condition_and_sense(se_cmd, - TCM_UNSUPPORTED_SCSI_OPCODE, 0); + TCM_UNSUPPORTED_SCSI_OPCODE, 1); + transport_generic_free_cmd(&cmd->se_cmd, 0); } static int bot_submit_command(struct f_uas *fu, @@ -1999,39 +2017,43 @@ static int tcm_bind(struct usb_configuration *c, struct usb_function *f) bot_intf_desc.bInterfaceNumber = iface; uasp_intf_desc.bInterfaceNumber = iface; fu->iface = iface; - ep = usb_ep_autoconfig(gadget, &uasp_fs_bi_desc); + ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_bi_desc, + &uasp_bi_ep_comp_desc); if (!ep) goto ep_fail; fu->ep_in = ep; - ep = usb_ep_autoconfig(gadget, &uasp_fs_bo_desc); + ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_bo_desc, + &uasp_bo_ep_comp_desc); if (!ep) goto ep_fail; fu->ep_out = ep; - ep = usb_ep_autoconfig(gadget, &uasp_fs_status_desc); + ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_status_desc, + &uasp_status_in_ep_comp_desc); if (!ep) goto ep_fail; fu->ep_status = ep; - ep = usb_ep_autoconfig(gadget, &uasp_fs_cmd_desc); + ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_cmd_desc, + &uasp_cmd_comp_desc); if (!ep) goto ep_fail; fu->ep_cmd = ep; /* Assume endpoint addresses are the same for both speeds */ - uasp_bi_desc.bEndpointAddress = uasp_fs_bi_desc.bEndpointAddress; - uasp_bo_desc.bEndpointAddress = uasp_fs_bo_desc.bEndpointAddress; + uasp_bi_desc.bEndpointAddress = uasp_ss_bi_desc.bEndpointAddress; + uasp_bo_desc.bEndpointAddress = uasp_ss_bo_desc.bEndpointAddress; uasp_status_desc.bEndpointAddress = - uasp_fs_status_desc.bEndpointAddress; - uasp_cmd_desc.bEndpointAddress = uasp_fs_cmd_desc.bEndpointAddress; + uasp_ss_status_desc.bEndpointAddress; + uasp_cmd_desc.bEndpointAddress = uasp_ss_cmd_desc.bEndpointAddress; - uasp_ss_bi_desc.bEndpointAddress = uasp_fs_bi_desc.bEndpointAddress; - uasp_ss_bo_desc.bEndpointAddress = uasp_fs_bo_desc.bEndpointAddress; - uasp_ss_status_desc.bEndpointAddress = - uasp_fs_status_desc.bEndpointAddress; - uasp_ss_cmd_desc.bEndpointAddress = uasp_fs_cmd_desc.bEndpointAddress; + uasp_fs_bi_desc.bEndpointAddress = uasp_ss_bi_desc.bEndpointAddress; + uasp_fs_bo_desc.bEndpointAddress = uasp_ss_bo_desc.bEndpointAddress; + uasp_fs_status_desc.bEndpointAddress = + uasp_ss_status_desc.bEndpointAddress; + uasp_fs_cmd_desc.bEndpointAddress = uasp_ss_cmd_desc.bEndpointAddress; ret = usb_assign_descriptors(f, uasp_fs_function_desc, uasp_hs_function_desc, uasp_ss_function_desc, diff --git a/drivers/usb/gadget/udc/aspeed-vhub/dev.c b/drivers/usb/gadget/udc/aspeed-vhub/dev.c index 89d7d3b24718..4008e7a51188 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/dev.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/dev.c @@ -542,9 +542,6 @@ int ast_vhub_init_dev(struct ast_vhub *vhub, unsigned int idx) d->vhub = vhub; d->index = idx; d->name = devm_kasprintf(parent, GFP_KERNEL, "port%d", idx+1); - if (!d->name) - return -ENOMEM; - d->regs = vhub->regs + 0x100 + 0x10 * idx; ast_vhub_init_ep0(vhub, &d->ep0, d); diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index 2952e5feb2ee..e04acf2dfa65 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c @@ -306,7 +306,7 @@ struct renesas_usb3_request { struct list_head queue; }; -#define USB3_EP_NAME_SIZE 16 +#define USB3_EP_NAME_SIZE 8 struct renesas_usb3_ep { struct usb_ep ep; struct renesas_usb3 *usb3; diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c index 5a21777197e9..0a5e0e644982 100644 --- a/drivers/usb/host/max3421-hcd.c +++ b/drivers/usb/host/max3421-hcd.c @@ -1956,12 +1956,6 @@ max3421_remove(struct spi_device *spi) return 0; } -static const struct spi_device_id max3421_spi_ids[] = { - { "max3421" }, - { }, -}; -MODULE_DEVICE_TABLE(spi, max3421_spi_ids); - static const struct of_device_id max3421_of_match_table[] = { { .compatible = "maxim,max3421", }, {}, @@ -1971,7 +1965,6 @@ MODULE_DEVICE_TABLE(of, max3421_of_match_table); static struct spi_driver max3421_driver = { .probe = max3421_probe, .remove = max3421_remove, - .id_table = max3421_spi_ids, .driver = { .name = "max3421-hcd", .of_match_table = of_match_ptr(max3421_of_match_table), diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index f9719ee5ba9e..f4e13a3fddee 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -165,25 +165,6 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd) return 0; } -static int ohci_quirk_loongson(struct usb_hcd *hcd) -{ - struct pci_dev *pdev = to_pci_dev(hcd->self.controller); - - /* - * Loongson's LS7A OHCI controller (rev 0x02) has a - * flaw. MMIO register with offset 0x60/64 is treated - * as legacy PS2-compatible keyboard/mouse interface. - * Since OHCI only use 4KB BAR resource, LS7A OHCI's - * 32KB BAR is wrapped around (the 2nd 4KB BAR space - * is the same as the 1st 4KB internally). So add 4KB - * offset (0x1000) to the OHCI registers as a quirk. - */ - if (pdev->revision == 0x2) - hcd->regs += SZ_4K; /* SZ_4K = 0x1000 */ - - return 0; -} - static int ohci_quirk_qemu(struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci(hcd); @@ -243,10 +224,6 @@ static const struct pci_device_id ohci_pci_quirks[] = { PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399), .driver_data = (unsigned long)ohci_quirk_amd700, }, - { - PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, 0x7a24), - .driver_data = (unsigned long)ohci_quirk_loongson, - }, { .vendor = PCI_VENDOR_ID_APPLE, .device = 0x003f, diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 7c98941d1108..f6d04491df60 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -945,15 +945,6 @@ static void quirk_usb_disable_ehci(struct pci_dev *pdev) * booting from USB disk or using a usb keyboard */ hcc_params = readl(base + EHCI_HCC_PARAMS); - - /* LS7A EHCI controller doesn't have extended capabilities, the - * EECP (EHCI Extended Capabilities Pointer) field of HCCPARAMS - * register should be 0x0 but it reads as 0xa0. So clear it to - * avoid error messages on boot. - */ - if (pdev->vendor == PCI_VENDOR_ID_LOONGSON && pdev->device == 0x7a14) - hcc_params &= ~(0xffL << 8); - offset = (hcc_params >> 8) & 0xff; while (offset && --count) { pci_read_config_dword(pdev, offset, &cap); diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c index c0834bac4c95..be9e9db7cad1 100644 --- a/drivers/usb/host/uhci-platform.c +++ b/drivers/usb/host/uhci-platform.c @@ -122,7 +122,7 @@ static int uhci_hcd_platform_probe(struct platform_device *pdev) } /* Get and enable clock if any specified */ - uhci->clk = devm_clk_get_optional(&pdev->dev, NULL); + uhci->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(uhci->clk)) { ret = PTR_ERR(uhci->clk); goto err_rmr; diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 8056be6a368a..b5ebbb9092f1 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -26,8 +26,8 @@ #define SPARSE_CNTL_ENABLE 0xC12C /* Device for a quirk */ -#define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73 -#define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000 +#define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73 +#define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000 #define PCI_DEVICE_ID_FRESCO_LOGIC_FL1009 0x1009 #define PCI_DEVICE_ID_FRESCO_LOGIC_FL1100 0x1100 #define PCI_DEVICE_ID_FRESCO_LOGIC_FL1400 0x1400 @@ -36,8 +36,8 @@ #define PCI_DEVICE_ID_EJ168 0x7023 #define PCI_DEVICE_ID_EJ188 0x7052 -#define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI 0x8c31 -#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31 +#define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI 0x8c31 +#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31 #define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_XHCI 0x9cb1 #define PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI 0x22b5 #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI 0xa12f diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index c395f5e23f8b..a3c30b609433 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -313,10 +313,8 @@ static int usbhsc_clk_get(struct device *dev, struct usbhs_priv *priv) priv->clks[1] = of_clk_get(dev_of_node(dev), 1); if (PTR_ERR(priv->clks[1]) == -ENOENT) priv->clks[1] = NULL; - else if (IS_ERR(priv->clks[1])) { - clk_put(priv->clks[0]); + else if (IS_ERR(priv->clks[1])) return PTR_ERR(priv->clks[1]); - } return 0; } @@ -680,29 +678,10 @@ static int usbhs_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&priv->notify_hotplug_work, usbhsc_notify_hotplug); spin_lock_init(usbhs_priv_to_lock(priv)); - /* - * Acquire clocks and enable power management (PM) early in the - * probe process, as the driver accesses registers during - * initialization. Ensure the device is active before proceeding. - */ - pm_runtime_enable(dev); - - ret = usbhsc_clk_get(dev, priv); - if (ret) - goto probe_pm_disable; - - ret = pm_runtime_resume_and_get(dev); - if (ret) - goto probe_clk_put; - - ret = usbhsc_clk_prepare_enable(priv); - if (ret) - goto probe_pm_put; - /* call pipe and module init */ ret = usbhs_pipe_probe(priv); if (ret < 0) - goto probe_clk_dis_unprepare; + return ret; ret = usbhs_fifo_probe(priv); if (ret < 0) @@ -719,6 +698,10 @@ static int usbhs_probe(struct platform_device *pdev) if (ret) goto probe_fail_rst; + ret = usbhsc_clk_get(dev, priv); + if (ret) + goto probe_fail_clks; + /* * deviece reset here because * USB device might be used in boot loader. @@ -734,7 +717,7 @@ static int usbhs_probe(struct platform_device *pdev) dev_warn(dev, "USB function not selected (GPIO %d)\n", priv->dparam.enable_gpio); ret = -ENOTSUPP; - goto probe_assert_rest; + goto probe_end_mod_exit; } } @@ -748,19 +731,14 @@ static int usbhs_probe(struct platform_device *pdev) ret = usbhs_platform_call(priv, hardware_init, pdev); if (ret < 0) { dev_err(dev, "platform init failed.\n"); - goto probe_assert_rest; + goto probe_end_mod_exit; } /* reset phy for connection */ usbhs_platform_call(priv, phy_reset, pdev); - /* - * Disable the clocks that were enabled earlier in the probe path, - * and let the driver handle the clocks beyond this point. - */ - usbhsc_clk_disable_unprepare(priv); - pm_runtime_put(dev); - + /* power control */ + pm_runtime_enable(dev); if (!usbhs_get_dparam(priv, runtime_pwctrl)) { usbhsc_power_ctrl(priv, 1); usbhs_mod_autonomy_mode(priv); @@ -777,7 +755,9 @@ static int usbhs_probe(struct platform_device *pdev) return ret; -probe_assert_rest: +probe_end_mod_exit: + usbhsc_clk_put(priv); +probe_fail_clks: reset_control_assert(priv->rsts); probe_fail_rst: usbhs_mod_remove(priv); @@ -785,14 +765,6 @@ probe_end_fifo_exit: usbhs_fifo_remove(priv); probe_end_pipe_exit: usbhs_pipe_remove(priv); -probe_clk_dis_unprepare: - usbhsc_clk_disable_unprepare(priv); -probe_pm_put: - pm_runtime_put(dev); -probe_clk_put: - usbhsc_clk_put(priv); -probe_pm_disable: - pm_runtime_disable(dev); dev_info(dev, "probe failed (%d)\n", ret); @@ -805,8 +777,6 @@ static int usbhs_remove(struct platform_device *pdev) dev_dbg(&pdev->dev, "usb remove\n"); - flush_delayed_work(&priv->notify_hotplug_work); - /* power off */ if (!usbhs_get_dparam(priv, runtime_pwctrl)) usbhsc_power_ctrl(priv, 0); diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 5a4605bbaa8b..53489cafecc1 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -1094,7 +1094,7 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) goto usbhs_mod_gadget_probe_err_gpriv; } - gpriv->transceiver = devm_usb_get_phy(dev, USB_PHY_TYPE_UNDEFINED); + gpriv->transceiver = usb_get_phy(USB_PHY_TYPE_UNDEFINED); dev_info(dev, "%stransceiver found\n", !IS_ERR(gpriv->transceiver) ? "" : "no "); diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index 4e00a185a4b6..aa4fb7a66dce 100644 --- a/drivers/usb/roles/class.c +++ b/drivers/usb/roles/class.c @@ -317,15 +317,14 @@ usb_role_switch_register(struct device *parent, sw->dev.type = &usb_role_dev_type; dev_set_name(&sw->dev, "%s-role-switch", dev_name(parent)); - sw->registered = true; - ret = device_register(&sw->dev); if (ret) { - sw->registered = false; put_device(&sw->dev); return ERR_PTR(ret); } + sw->registered = true; + /* TODO: Symlinks for the host port and the device controller. */ return sw; diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 39c9d1f857fc..5353fa7e5969 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -224,7 +224,6 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */ { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */ { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */ - { USB_DEVICE(0x1B93, 0x1013) }, /* Phoenix Contact UPS Device */ { USB_DEVICE(0x1BA4, 0x0002) }, /* Silicon Labs 358x factory default */ { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */ { USB_DEVICE(0x1D6F, 0x0010) }, /* Seluxit ApS RF Dongle */ diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index d13b8e35ce33..bfb0be4e70d5 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1057,22 +1057,6 @@ static const struct usb_device_id id_table_combined[] = { .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, /* GMC devices */ { USB_DEVICE(GMC_VID, GMC_Z216C_PID) }, - /* Altera USB Blaster 3 */ - { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_6022_PID, 1) }, - { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_6025_PID, 2) }, - { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_6026_PID, 2) }, - { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_6026_PID, 3) }, - { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_6029_PID, 2) }, - { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602A_PID, 2) }, - { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602A_PID, 3) }, - { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602C_PID, 1) }, - { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602D_PID, 1) }, - { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602D_PID, 2) }, - { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602E_PID, 1) }, - { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602E_PID, 2) }, - { USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602E_PID, 3) }, - /* Abacus Electrics */ - { USB_DEVICE(FTDI_VID, ABACUS_OPTICAL_PROBE_PID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 9c95ca876bae..b2aec1106678 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -435,11 +435,6 @@ #define LINX_FUTURE_1_PID 0xF44B /* Linx future device */ #define LINX_FUTURE_2_PID 0xF44C /* Linx future device */ -/* - * Abacus Electrics - */ -#define ABACUS_OPTICAL_PROBE_PID 0xf458 /* ABACUS ELECTRICS Optical Probe */ - /* * Oceanic product ids */ @@ -1610,16 +1605,3 @@ */ #define GMC_VID 0x1cd7 #define GMC_Z216C_PID 0x0217 /* GMC Z216C Adapter IR-USB */ - -/* - * Altera USB Blaster 3 (http://www.altera.com). - */ -#define ALTERA_VID 0x09fb -#define ALTERA_UB3_6022_PID 0x6022 -#define ALTERA_UB3_6025_PID 0x6025 -#define ALTERA_UB3_6026_PID 0x6026 -#define ALTERA_UB3_6029_PID 0x6029 -#define ALTERA_UB3_602A_PID 0x602a -#define ALTERA_UB3_602C_PID 0x602c -#define ALTERA_UB3_602D_PID 0x602d -#define ALTERA_UB3_602E_PID 0x602e diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 08d70256e72e..3ae4ac4d9857 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -611,7 +611,6 @@ static void option_instat_callback(struct urb *urb); /* Sierra Wireless products */ #define SIERRA_VENDOR_ID 0x1199 #define SIERRA_PRODUCT_EM9191 0x90d3 -#define SIERRA_PRODUCT_EM9291 0x90e3 /* UNISOC (Spreadtrum) products */ #define UNISOC_VENDOR_ID 0x1782 @@ -620,6 +619,15 @@ static void option_instat_callback(struct urb *urb); /* Luat Air72*U series based on UNISOC UIS8910 uses UNISOC's vendor ID */ #define LUAT_PRODUCT_AIR720U 0x4e00 +/* MeiG Smart Technology products */ +#define MEIGSMART_VENDOR_ID 0x2dee +/* MeiG Smart SRM825L based on Qualcomm 315 */ +#define MEIGSMART_PRODUCT_SRM825L 0x4d22 +/* MeiG Smart SLM320 based on UNISOC UIS8910 */ +#define MEIGSMART_PRODUCT_SLM320 0x4d41 +/* MeiG Smart SLM770A based on ASR1803 */ +#define MEIGSMART_PRODUCT_SLM770A 0x4d57 + /* Device flags */ /* Highest interface number which can be used with NCTRL() and RSVD() */ @@ -1359,23 +1367,23 @@ static const struct usb_device_id option_ids[] = { .driver_info = NCTRL(2) | RSVD(3) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1063, 0xff), /* Telit LN920 (ECM) */ .driver_info = NCTRL(0) | RSVD(1) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1070, 0xff), /* Telit FN990A (rmnet) */ + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1070, 0xff), /* Telit FN990 (rmnet) */ .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1071, 0xff), /* Telit FN990A (MBIM) */ + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1071, 0xff), /* Telit FN990 (MBIM) */ .driver_info = NCTRL(0) | RSVD(1) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1072, 0xff), /* Telit FN990A (RNDIS) */ + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1072, 0xff), /* Telit FN990 (RNDIS) */ .driver_info = NCTRL(2) | RSVD(3) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1073, 0xff), /* Telit FN990A (ECM) */ + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1073, 0xff), /* Telit FN990 (ECM) */ .driver_info = NCTRL(0) | RSVD(1) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1075, 0xff), /* Telit FN990A (PCIe) */ + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1075, 0xff), /* Telit FN990 (PCIe) */ .driver_info = RSVD(0) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1080, 0xff), /* Telit FE990A (rmnet) */ + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1080, 0xff), /* Telit FE990 (rmnet) */ .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1081, 0xff), /* Telit FE990A (MBIM) */ + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1081, 0xff), /* Telit FE990 (MBIM) */ .driver_info = NCTRL(0) | RSVD(1) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1082, 0xff), /* Telit FE990A (RNDIS) */ + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1082, 0xff), /* Telit FE990 (RNDIS) */ .driver_info = NCTRL(2) | RSVD(3) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1083, 0xff), /* Telit FE990A (ECM) */ + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1083, 0xff), /* Telit FE990 (ECM) */ .driver_info = NCTRL(0) | RSVD(1) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a0, 0xff), /* Telit FN20C04 (rmnet) */ .driver_info = RSVD(0) | NCTRL(3) }, @@ -1389,44 +1397,12 @@ static const struct usb_device_id option_ids[] = { .driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10aa, 0xff), /* Telit FN920C04 (MBIM) */ .driver_info = NCTRL(3) | RSVD(4) | RSVD(5) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b0, 0xff, 0xff, 0x30), /* Telit FE990B (rmnet) */ - .driver_info = NCTRL(5) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b0, 0xff, 0xff, 0x40) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b0, 0xff, 0xff, 0x60) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b1, 0xff, 0xff, 0x30), /* Telit FE990B (MBIM) */ - .driver_info = NCTRL(6) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b1, 0xff, 0xff, 0x40) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b1, 0xff, 0xff, 0x60) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b2, 0xff, 0xff, 0x30), /* Telit FE990B (RNDIS) */ - .driver_info = NCTRL(6) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b2, 0xff, 0xff, 0x40) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b2, 0xff, 0xff, 0x60) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b3, 0xff, 0xff, 0x30), /* Telit FE990B (ECM) */ - .driver_info = NCTRL(6) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b3, 0xff, 0xff, 0x40) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10b3, 0xff, 0xff, 0x60) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c0, 0xff), /* Telit FE910C04 (rmnet) */ .driver_info = RSVD(0) | NCTRL(3) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c4, 0xff), /* Telit FE910C04 (rmnet) */ .driver_info = RSVD(0) | NCTRL(3) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c8, 0xff), /* Telit FE910C04 (rmnet) */ .driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d0, 0xff, 0xff, 0x30), /* Telit FN990B (rmnet) */ - .driver_info = NCTRL(5) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d0, 0xff, 0xff, 0x40) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d0, 0xff, 0xff, 0x60) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d1, 0xff, 0xff, 0x30), /* Telit FN990B (MBIM) */ - .driver_info = NCTRL(6) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d1, 0xff, 0xff, 0x40) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d1, 0xff, 0xff, 0x60) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d2, 0xff, 0xff, 0x30), /* Telit FN990B (RNDIS) */ - .driver_info = NCTRL(6) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d2, 0xff, 0xff, 0x40) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d2, 0xff, 0xff, 0x60) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d3, 0xff, 0xff, 0x30), /* Telit FN990B (ECM) */ - .driver_info = NCTRL(6) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d3, 0xff, 0xff, 0x40) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d3, 0xff, 0xff, 0x60) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910), .driver_info = NCTRL(0) | RSVD(1) | RSVD(3) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM), @@ -2371,14 +2347,6 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a05, 0xff) }, /* Fibocom FM650-CN (NCM mode) */ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a06, 0xff) }, /* Fibocom FM650-CN (RNDIS mode) */ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a07, 0xff) }, /* Fibocom FM650-CN (MBIM mode) */ - { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d41, 0xff, 0, 0) }, /* MeiG Smart SLM320 */ - { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d57, 0xff, 0, 0) }, /* MeiG Smart SLM770A */ - { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0, 0) }, /* MeiG Smart SRM815 */ - { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0x10, 0x02) }, /* MeiG Smart SLM828 */ - { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0x10, 0x03) }, /* MeiG Smart SLM828 */ - { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0xff, 0x30) }, /* MeiG Smart SRM815 and SRM825L */ - { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0xff, 0x40) }, /* MeiG Smart SRM825L */ - { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0xff, 0x60) }, /* MeiG Smart SRM825L */ { USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) }, /* LongSung M5710 */ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */ @@ -2433,15 +2401,17 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x30) }, { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x40) }, { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0, 0) }, - { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9291, 0xff, 0xff, 0x30) }, - { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9291, 0xff, 0xff, 0x40) }, { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, LUAT_PRODUCT_AIR720U, 0xff, 0, 0) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SLM320, 0xff, 0, 0) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SLM770A, 0xff, 0, 0) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x30) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x60) }, { USB_DEVICE_INTERFACE_CLASS(0x1bbb, 0x0530, 0xff), /* TCL IK512 MBIM */ .driver_info = NCTRL(1) }, { USB_DEVICE_INTERFACE_CLASS(0x1bbb, 0x0640, 0xff), /* TCL IK512 ECM */ .driver_info = NCTRL(3) }, - { USB_DEVICE_INTERFACE_CLASS(0x2949, 0x8700, 0xff) }, /* Neoway N723-EA */ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 5501898dfcfb..d172e8642d4a 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -555,7 +555,7 @@ static void qt2_process_read_urb(struct urb *urb) newport = *(ch + 3); - if (newport >= serial->num_ports) { + if (newport > serial->num_ports) { dev_err(&port->dev, "%s - port change to invalid port: %i\n", __func__, newport); diff --git a/drivers/usb/serial/usb-serial-simple.c b/drivers/usb/serial/usb-serial-simple.c index bac5ab6377ae..24b8772a345e 100644 --- a/drivers/usb/serial/usb-serial-simple.c +++ b/drivers/usb/serial/usb-serial-simple.c @@ -101,11 +101,6 @@ DEVICE(nokia, NOKIA_IDS); { USB_DEVICE(0x09d7, 0x0100) } /* NovAtel FlexPack GPS */ DEVICE_N(novatel_gps, NOVATEL_IDS, 3); -/* OWON electronic test and measurement equipment driver */ -#define OWON_IDS() \ - { USB_DEVICE(0x5345, 0x1234) } /* HDS200 oscilloscopes and others */ -DEVICE(owon, OWON_IDS); - /* Siemens USB/MPI adapter */ #define SIEMENS_IDS() \ { USB_DEVICE(0x908, 0x0004) } @@ -140,7 +135,6 @@ static struct usb_serial_driver * const serial_drivers[] = { &motorola_tetra_device, &nokia_device, &novatel_gps_device, - &owon_device, &siemens_mpi_device, &suunto_device, &vivopay_device, @@ -160,7 +154,6 @@ static const struct usb_device_id id_table[] = { MOTOROLA_TETRA_IDS(), NOKIA_IDS(), NOVATEL_IDS(), - OWON_IDS(), SIEMENS_IDS(), SUUNTO_IDS(), VIVOPAY_IDS(), diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index a6dc2faae85d..606a68bd8059 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -255,13 +255,6 @@ UNUSUAL_DEV( 0x0421, 0x06aa, 0x1110, 0x1110, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_MAX_SECTORS_64 ), -/* Added by Lubomir Rintel , a very fine chap */ -UNUSUAL_DEV( 0x0421, 0x06c2, 0x0000, 0x0406, - "Nokia", - "Nokia 208", - USB_SC_DEVICE, USB_PR_DEVICE, NULL, - US_FL_MAX_SECTORS_64 ), - #ifdef NO_SDDR09 UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, "Microtech", diff --git a/drivers/usb/storage/unusual_uas.h b/drivers/usb/storage/unusual_uas.h index ff296434d601..a4513dd931b2 100644 --- a/drivers/usb/storage/unusual_uas.h +++ b/drivers/usb/storage/unusual_uas.h @@ -52,13 +52,6 @@ UNUSUAL_DEV(0x059f, 0x1061, 0x0000, 0x9999, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_REPORT_OPCODES | US_FL_NO_SAME), -/* Reported-by: Zhihong Zhou */ -UNUSUAL_DEV(0x0781, 0x55e8, 0x0000, 0x9999, - "SanDisk", - "", - USB_SC_DEVICE, USB_PR_DEVICE, NULL, - US_FL_IGNORE_UAS), - /* Reported-by: Hongling Zeng */ UNUSUAL_DEV(0x090c, 0x2000, 0x0000, 0x9999, "Hiksemi", @@ -90,13 +83,6 @@ UNUSUAL_DEV(0x0bc2, 0x331a, 0x0000, 0x9999, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_REPORT_LUNS), -/* Reported-by: Oliver Neukum */ -UNUSUAL_DEV(0x125f, 0xa94a, 0x0160, 0x0160, - "ADATA", - "Portable HDD CH94", - USB_SC_DEVICE, USB_PR_DEVICE, NULL, - US_FL_NO_ATA_1X), - /* Reported-by: Benjamin Tissoires */ UNUSUAL_DEV(0x13fd, 0x3940, 0x0000, 0x9999, "Initio Corporation", diff --git a/drivers/usb/typec/tcpm/tcpci_rt1711h.c b/drivers/usb/typec/tcpm/tcpci_rt1711h.c index 76ab5eb6d7f2..b56a0880a044 100644 --- a/drivers/usb/typec/tcpm/tcpci_rt1711h.c +++ b/drivers/usb/typec/tcpm/tcpci_rt1711h.c @@ -217,11 +217,6 @@ static int rt1711h_probe(struct i2c_client *client, { int ret; struct rt1711h_chip *chip; - const u16 alert_mask = TCPC_ALERT_TX_SUCCESS | TCPC_ALERT_TX_DISCARDED | - TCPC_ALERT_TX_FAILED | TCPC_ALERT_RX_HARD_RST | - TCPC_ALERT_RX_STATUS | TCPC_ALERT_POWER_STATUS | - TCPC_ALERT_CC_STATUS | TCPC_ALERT_RX_BUF_OVF | - TCPC_ALERT_FAULT; ret = rt1711h_check_revision(client); if (ret < 0) { @@ -263,12 +258,6 @@ static int rt1711h_probe(struct i2c_client *client, dev_name(chip->dev), chip); if (ret < 0) return ret; - - /* Enable alert interrupts */ - ret = rt1711h_write16(chip, TCPC_ALERT_MASK, alert_mask); - if (ret < 0) - return ret; - enable_irq_wake(client->irq); return 0; diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index ae2d03c3ec1e..446d09d89860 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -3009,7 +3009,7 @@ static void run_state_machine(struct tcpm_port *port) port->caps_count = 0; port->pd_capable = true; tcpm_set_state_cond(port, SRC_SEND_CAPABILITIES_TIMEOUT, - PD_T_SENDER_RESPONSE); + PD_T_SEND_SOURCE_CAP); } break; case SRC_SEND_CAPABILITIES_TIMEOUT: @@ -3761,7 +3761,7 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1, case SNK_TRY_WAIT_DEBOUNCE: if (!tcpm_port_is_sink(port)) { port->max_wait = 0; - tcpm_set_state(port, SRC_TRYWAIT, PD_T_PD_DEBOUNCE); + tcpm_set_state(port, SRC_TRYWAIT, 0); } break; case SRC_TRY_WAIT: diff --git a/drivers/usb/typec/ucsi/displayport.c b/drivers/usb/typec/ucsi/displayport.c index 79692b13a873..f67c5a304155 100644 --- a/drivers/usb/typec/ucsi/displayport.c +++ b/drivers/usb/typec/ucsi/displayport.c @@ -272,8 +272,6 @@ void ucsi_displayport_remove_partner(struct typec_altmode *alt) if (!dp) return; - cancel_work_sync(&dp->work); - dp->data.conf = 0; dp->data.status = 0; dp->initialized = false; diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index fa2860a1bcf7..6da0ce066785 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -25,7 +25,7 @@ * difficult to estimate the time it takes for the system to process the command * before it is actually passed to the PPM. */ -#define UCSI_TIMEOUT_MS 10000 +#define UCSI_TIMEOUT_MS 5000 /* * UCSI_SWAP_TIMEOUT_MS - Timeout for role swap requests diff --git a/include/linux/hid.h b/include/linux/hid.h index ec0efababc79..115224aefa94 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -671,9 +671,8 @@ struct hid_descriptor { __le16 bcdHID; __u8 bCountryCode; __u8 bNumDescriptors; - struct hid_class_descriptor rpt_desc; - struct hid_class_descriptor opt_descs[]; + struct hid_class_descriptor desc[1]; } __attribute__ ((packed)); #define HID_DEVICE(b, g, ven, prod) \ diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 14b4c6c2e8dc..1bb58485b2e2 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -528,7 +528,6 @@ extern void __init hrtimers_init(void); extern void sysrq_timer_list_show(void); int hrtimers_prepare_cpu(unsigned int cpu); -int hrtimers_cpu_starting(unsigned int cpu); #ifdef CONFIG_HOTPLUG_CPU int hrtimers_dead_cpu(unsigned int cpu); #else diff --git a/include/linux/usb.h b/include/linux/usb.h index 32d43a9ab817..484608d419f5 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -713,12 +713,13 @@ struct usb_device { unsigned long active_duration; +#ifdef CONFIG_PM unsigned long connect_time; unsigned do_remote_wakeup:1; unsigned reset_resume:1; unsigned port_is_suspended:1; - +#endif struct wusb_dev *wusb_dev; int slot_id; enum usb_device_removable removable; diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 91e9db289303..ca8ec43770a9 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -498,7 +498,9 @@ extern void usb_hcd_pci_shutdown(struct pci_dev *dev); extern int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *dev); +#ifdef CONFIG_PM extern const struct dev_pm_ops usb_hcd_pci_pm_ops; +#endif #endif /* CONFIG_USB_PCI */ /* pci-ish (pdev null is ok) buffer alloc/mapping support */ diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index f2296351f294..d03a8e81deb9 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -2066,15 +2066,6 @@ int hrtimers_prepare_cpu(unsigned int cpu) } cpu_base->cpu = cpu; - hrtimer_cpu_base_init_expiry_lock(cpu_base); - return 0; -} - -int hrtimers_cpu_starting(unsigned int cpu) -{ - struct hrtimer_cpu_base *cpu_base = this_cpu_ptr(&hrtimer_bases); - - /* Clear out any left over state from a CPU down operation */ cpu_base->active_bases = 0; cpu_base->hres_active = 0; cpu_base->hang_detected = 0; @@ -2082,6 +2073,7 @@ int hrtimers_cpu_starting(unsigned int cpu) cpu_base->softirq_next_timer = NULL; cpu_base->expires_next = KTIME_MAX; cpu_base->softirq_expires_next = KTIME_MAX; + hrtimer_cpu_base_init_expiry_lock(cpu_base); return 0; } @@ -2167,7 +2159,6 @@ int hrtimers_dead_cpu(unsigned int scpu) void __init hrtimers_init(void) { hrtimers_prepare_cpu(smp_processor_id()); - hrtimers_cpu_starting(smp_processor_id()); open_softirq(HRTIMER_SOFTIRQ, hrtimer_run_softirq); } diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn index c85fd32b70da..6a78afc6f13b 100644 --- a/scripts/Makefile.extrawarn +++ b/scripts/Makefile.extrawarn @@ -36,10 +36,6 @@ KBUILD_CFLAGS += $(call cc-option, -Wstringop-truncation) KBUILD_CFLAGS += -Wno-missing-field-initializers KBUILD_CFLAGS += -Wno-sign-compare -ifdef CONFIG_CC_IS_CLANG -KBUILD_CFLAGS += -Wno-enum-enum-conversion -endif - KBUILD_CPPFLAGS += -DKBUILD_EXTRA_WARN1 else @@ -55,7 +51,6 @@ KBUILD_CFLAGS += -Wno-format-zero-length KBUILD_CFLAGS += $(call cc-disable-warning, pointer-to-enum-cast) KBUILD_CFLAGS += $(call cc-disable-warning, unaligned-access) KBUILD_CFLAGS += $(call cc-disable-warning, cast-function-type-strict) -KBUILD_CFLAGS += -Wno-enum-compare-conditional endif endif From 40b465c13e9d2e2e0fa91637031535f321e81458 Mon Sep 17 00:00:00 2001 From: Akash Kumar Date: Wed, 10 Sep 2025 10:08:06 +0530 Subject: [PATCH 28/42] usb: gadget: uvc: Modify UVC_NUM_REQUESTS Modify UVC_NUM_REQUESTS to resolve uvc drop frame problem. Increase UVC_NUM_REQUESTS to 64 from 4 to prevent uvc drop frame problem caused by unavailability of free UVC buffers, ensuring smoother video playback. Change-Id: I0babb3eca4c62140205bd549ef7904b7e893e7bd Signed-off-by: Akash Kumar --- drivers/usb/gadget/function/uvc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index 1473d25ff17a..9961d7d04546 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -65,7 +65,7 @@ extern unsigned int uvc_gadget_trace_param; * Driver specific constants */ -#define UVC_NUM_REQUESTS 4 +#define UVC_NUM_REQUESTS 64 #define UVC_MAX_REQUEST_SIZE 64 #define UVC_MAX_EVENTS 4 From 158551277b6a006d567e0f5a19dfa2d11cac6f46 Mon Sep 17 00:00:00 2001 From: Ruixuan Gu Date: Mon, 29 Sep 2025 14:43:35 +0800 Subject: [PATCH 29/42] netfilter: fix NATTYPE refresh timeout issue nattype timer is refreshed with wrong expires value Change-Id: I07473c0b21ac966c190b24b76bc93423680c2866 Signed-off-by: Ruixuan Gu --- net/ipv4/netfilter/ipt_NATTYPE.c | 15 +++++++++------ net/netfilter/nf_conntrack_core.c | 8 ++++++-- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/net/ipv4/netfilter/ipt_NATTYPE.c b/net/ipv4/netfilter/ipt_NATTYPE.c index fae7cad3f89f..484c0c111e4a 100644 --- a/net/ipv4/netfilter/ipt_NATTYPE.c +++ b/net/ipv4/netfilter/ipt_NATTYPE.c @@ -53,8 +53,8 @@ static void nattype_nte_debug_print(const struct ipt_nattype *nte, &nte->range.min_addr.ip, ntohs(nte->range.min_proto.all), ntohs(nte->nat_port), &nte->dest_addr, ntohs(nte->dest_port)); - DEBUGP("Timeout[%lx], Expires[%lx]\n", nte->timeout_value, - nte->timeout.expires); + DEBUGP("Timeout[%lx], Expires[%lx], Current[%lx]\n", nte->timeout_value, + nte->timeout.expires, jiffies); } /* netfilter NATTYPE nattype_free() @@ -80,8 +80,9 @@ bool nattype_refresh_timer_impl(unsigned long nat_type, spin_unlock_bh(&nattype_lock); return false; } + DEBUGP("%s: timeout_value=%lx, jiffies=%lx", __func__, timeout_value, jiffies); if (del_timer(&nte->timeout)) { - nte->timeout.expires = timeout_value; + nte->timeout.expires = timeout_value + jiffies - nfct_time_stamp; add_timer(&nte->timeout); spin_unlock_bh(&nattype_lock); nattype_nte_debug_print(nte, "refresh"); @@ -293,7 +294,7 @@ static unsigned int nattype_nat(struct sk_buff *skb, * found the entry. */ if (!nattype_refresh_timer((unsigned long)nte, - jiffies + nte->timeout_value)) + nfct_time_stamp + nte->timeout_value)) break; /* netfilter @@ -326,6 +327,7 @@ static unsigned int nattype_forward(struct sk_buff *skb, const struct ipt_nattype_info *info = par->targinfo; u16 nat_port; enum ip_conntrack_dir dir; + unsigned long timeout_value; if (xt_hooknum(par) != NF_INET_POST_ROUTING) return XT_CONTINUE; @@ -358,7 +360,7 @@ static unsigned int nattype_forward(struct sk_buff *skb, * found the entry. */ if (!nattype_refresh_timer((unsigned long)nte, - ct->timeout)) + ct->timeout)) break; /* netfilter NATTYPE @@ -431,7 +433,8 @@ static unsigned int nattype_forward(struct sk_buff *skb, * entry as this one is timed out and will be removed * from the list shortly. */ - if (!nattype_refresh_timer((unsigned long)nte2, jiffies + nte2->timeout_value)) + timeout_value = nfct_time_stamp + nte2->timeout_value; + if (!nattype_refresh_timer((unsigned long)nte2, timeout_value)) break; /* netfilter NATTYPE diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index e999b6d8da11..effa09102d3c 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -1853,8 +1853,12 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, /* Refresh the NAT type entry. */ #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) nattype_ref_timer = rcu_dereference(nattype_refresh_timer); - if (nattype_ref_timer) - nattype_ref_timer(ct->nattype_entry, ct->timeout); + if (nattype_ref_timer) { + if (nf_ct_is_confirmed(ct)) + nattype_ref_timer(ct->nattype_entry, ct->timeout); + else + nattype_ref_timer(ct->nattype_entry, extra_jiffies + nfct_time_stamp); + } #endif acct: From 537b2272231efe4e739220bf4333eacc2bcf6ad6 Mon Sep 17 00:00:00 2001 From: Prashanth K Date: Wed, 10 Sep 2025 14:52:27 +0530 Subject: [PATCH 30/42] UPSTREAM: usb: dwc3: Wait for EndXfer command completion DWC3 programming guide mentions that when operating in USB2.0 speeds, if GUSB2PHYCFG[6] or GUSB2PHYCFG[8] is set, it must be cleared prior to issuing commands and may be set again after the command completes. But currently while issuing EndXfer command without CmdIOC set, we wait for 1ms after GUSB2PHYCFG is restored. This results in cases where EndXfer command doesn't get completed and causes SMMU faults since requests are unmapped afterwards. Hence restore GUSB2PHYCFG after waiting for EndXfer command completion. Cc: stable@vger.kernel.org Fixes: 1d26ba0944d3 ("usb: dwc3: Wait unconditionally after issuing EndXfer command") Acked-by: Thinh Nguyen Link: https://lore.kernel.org/r/20240924093208.2524531-1-quic_prashk@quicinc.com Signed-off-by: Prashanth K Signed-off-by: Greg Kroah-Hartman Git-commit: c96e31252110a84dcc44412e8a7b456b33c3e298 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git. Change-Id: I4015b2190d984ffa10e89348cd375ab355e28531 Signed-off-by: Prashanth K Signed-off-by: Akash Kumar --- drivers/usb/dwc3/gadget.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 2a92adf569c8..ff1072ce09ac 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -491,6 +491,10 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd, dwc3_gadget_ep_get_transfer_index(dep); } + if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_ENDTRANSFER && + !(cmd & DWC3_DEPCMD_CMDIOC)) + mdelay(1); + if (saved_config) { reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); reg |= saved_config; @@ -3705,9 +3709,6 @@ int dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt) else dep->flags |= DWC3_EP_END_TRANSFER_PENDING; - if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A) - udelay(100); - return ret; } EXPORT_SYMBOL(dwc3_stop_active_transfer); From 43caee68715247ac5a44c967381a12a94f64d1d3 Mon Sep 17 00:00:00 2001 From: Pradeep P V K Date: Thu, 18 Sep 2025 18:25:47 +0530 Subject: [PATCH 31/42] mtd: msm_qpic_nand: check for page_erased bit along with op_err Due to a hardware bug in ECC-Engine, ECC-Engine couldn't able to set OP_ERR bit in flash_status regesiter whenever an erased page encounters bitflips. Due to this, ECC-Engine is trying to correct the bitflips on an erased page and leading to data corruption. So, a check for PAGE_ERASED bit is added prior to OP_ERR bit for an erased page detection logic. Change-Id: I570625123fe828450dade06570f782ebe93d39f1 Signed-off-by: Pradeep P V K Signed-off-by: Pradeep P V K Signed-off-by: Ram Kumar Dwivedi --- drivers/mtd/devices/msm_qpic_nand.c | 64 ++++++++++++++++++++++++++--- drivers/mtd/devices/msm_qpic_nand.h | 6 ++- 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/devices/msm_qpic_nand.c b/drivers/mtd/devices/msm_qpic_nand.c index 329e7ebbd191..0b7a478bb612 100644 --- a/drivers/mtd/devices/msm_qpic_nand.c +++ b/drivers/mtd/devices/msm_qpic_nand.c @@ -2,7 +2,7 @@ /* * Copyright (C) 2007 Google, Inc. * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include "msm_qpic_nand.h" @@ -1944,7 +1944,7 @@ free_dma: if (last_pos < ecc_bytes_percw_in_bits) num_zero_bits++; - if (num_zero_bits > 4) { + if (num_zero_bits > MAX_ECC_BIT_FLIPS) { *erased_page = false; goto free_mem; } @@ -1956,7 +1956,7 @@ free_dma: ecc_temp += chip->ecc_parity_bytes; } - if ((n == cwperpage) && (num_zero_bits <= 4)) + if ((n == cwperpage) && (num_zero_bits <= MAX_ECC_BIT_FLIPS)) *erased_page = true; free_mem: kfree(ecc); @@ -2163,6 +2163,33 @@ static int msm_nand_read_pagescope(struct mtd_info *mtd, loff_t from, goto free_dma; /* Check for flash status errors */ pageerr = rawerr = 0; + + /* + * PAGE_ERASED bit will set only if all + * CODEWORD_ERASED bit of all codewords + * of the page is set. + * + * PAGE_ERASED bit is a 'logical and' of all + * CODEWORD_ERASED bit of all codewords i.e. + * even if one codeword is detected as not + * an erased codeword, PAGE_ERASED bit will unset. + */ + for (n = rw_params.start_sector; n < cwperpage; n++) { + if ((dma_buffer->result[n].erased_cw_status & + (1 << PAGE_ERASED)) && + (dma_buffer->result[n].buffer_status & + NUM_ERRORS)) { + err = msm_nand_is_erased_page_ps(mtd, + from, ops, + &rw_params, + &erased_page); + if (err) + goto free_dma; + if (erased_page) + rawerr = -EIO; + break; + } + } for (n = rw_params.start_sector; n < cwperpage; n++) { if (dma_buffer->result[n].flash_status & (FS_OP_ERR | FS_MPU_ERR)) { @@ -2554,7 +2581,7 @@ free_dma: if (last_pos < ecc_bytes_percw_in_bits) num_zero_bits++; - if (num_zero_bits > 4) { + if (num_zero_bits > MAX_ECC_BIT_FLIPS) { *erased_page = false; goto free_mem; } @@ -2566,7 +2593,7 @@ free_dma: ecc_temp += chip->ecc_parity_bytes; } - if ((n == cwperpage) && (num_zero_bits <= 4)) + if ((n == cwperpage) && (num_zero_bits <= MAX_ECC_BIT_FLIPS)) *erased_page = true; free_mem: kfree(ecc); @@ -2760,6 +2787,33 @@ static int msm_nand_read_oob(struct mtd_info *mtd, loff_t from, goto free_dma; /* Check for flash status errors */ pageerr = rawerr = 0; + + /* + * PAGE_ERASED bit will set only if all + * CODEWORD_ERASED bit of all codewords + * of the page is set. + * + * PAGE_ERASED bit is a 'logical and' of all + * CODEWORD_ERASED bit of all codewords i.e. + * even if one codeword is detected as not + * an erased codeword, PAGE_ERASED bit will unset. + */ + for (n = rw_params.start_sector; n < cwperpage; n++) { + if ((dma_buffer->result[n].erased_cw_status & + (1 << PAGE_ERASED)) && + (dma_buffer->result[n].buffer_status & + NUM_ERRORS)) { + err = msm_nand_is_erased_page(mtd, + from, ops, + &rw_params, + &erased_page); + if (err) + goto free_dma; + if (erased_page) + rawerr = -EIO; + break; + } + } for (n = rw_params.start_sector; n < cwperpage; n++) { if (dma_buffer->result[n].flash_status & (FS_OP_ERR | FS_MPU_ERR)) { diff --git a/drivers/mtd/devices/msm_qpic_nand.h b/drivers/mtd/devices/msm_qpic_nand.h index cc1df16f5b3d..0297ad9697c4 100644 --- a/drivers/mtd/devices/msm_qpic_nand.h +++ b/drivers/mtd/devices/msm_qpic_nand.h @@ -154,7 +154,10 @@ #define RESET_ERASED_DET (1 << AUTO_DETECT_RES) #define ACTIVE_ERASED_DET (0 << AUTO_DETECT_RES) #define CLR_ERASED_PAGE_DET (RESET_ERASED_DET | MASK_ECC) -#define SET_ERASED_PAGE_DET (ACTIVE_ERASED_DET | MASK_ECC) +#define SET_ERASED_PAGE_DET (ACTIVE_ERASED_DET | MASK_ECC | SET_N_MAX_ZEROS) +#define N_MAX_ZEROS 2 +#define MAX_ECC_BIT_FLIPS 4 +#define SET_N_MAX_ZEROS (MAX_ECC_BIT_FLIPS << N_MAX_ZEROS) #define MSM_NAND_ERASED_CW_DETECT_STATUS(info) MSM_NAND_REG(info, 0x300EC) #define PAGE_ALL_ERASED 7 @@ -163,6 +166,7 @@ #define CODEWORD_ERASED 4 #define ERASED_PAGE ((1 << PAGE_ALL_ERASED) | (1 << PAGE_ERASED)) #define ERASED_CW ((1 << CODEWORD_ALL_ERASED) | (1 << CODEWORD_ERASED)) +#define NUM_ERRORS 0x1f #define MSM_NAND_CTRL(info) MSM_NAND_REG(info, 0x30F00) #define BAM_MODE_EN 0 From 96f3098bef83a0a81d5abca00df27cc043073fa6 Mon Sep 17 00:00:00 2001 From: Pradeep P V K Date: Fri, 5 Jun 2020 18:38:21 +0530 Subject: [PATCH 32/42] mtd: msm_qpic_nand: Use flash device ECC capability for erase page Page codeword's ECC data is used to determine if the page is actually erased or not. On an erased page, this data is all 0xFF. The acceptable bitflips on this ECC data is flash device dependent. So, always check against flash device ECC capability value for erase page determination. Change-Id: Ib3889f91c871b5f131fe8bc960ffa68ac11e0633 Signed-off-by: Pradeep P V K Signed-off-by: Pradeep P V K Signed-off-by: Ram Kumar Dwivedi --- drivers/mtd/devices/msm_qpic_nand.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/devices/msm_qpic_nand.c b/drivers/mtd/devices/msm_qpic_nand.c index 0b7a478bb612..eb45e4908968 100644 --- a/drivers/mtd/devices/msm_qpic_nand.c +++ b/drivers/mtd/devices/msm_qpic_nand.c @@ -1944,7 +1944,7 @@ free_dma: if (last_pos < ecc_bytes_percw_in_bits) num_zero_bits++; - if (num_zero_bits > MAX_ECC_BIT_FLIPS) { + if (num_zero_bits > info->flash_dev.ecc_capability) { *erased_page = false; goto free_mem; } @@ -1955,8 +1955,8 @@ free_dma: num_zero_bits = last_pos = next_pos = 0; ecc_temp += chip->ecc_parity_bytes; } - - if ((n == cwperpage) && (num_zero_bits <= MAX_ECC_BIT_FLIPS)) + if ((n == cwperpage) && + (num_zero_bits <= info->flash_dev.ecc_capability)) *erased_page = true; free_mem: kfree(ecc); @@ -2581,7 +2581,7 @@ free_dma: if (last_pos < ecc_bytes_percw_in_bits) num_zero_bits++; - if (num_zero_bits > MAX_ECC_BIT_FLIPS) { + if (num_zero_bits > info->flash_dev.ecc_capability) { *erased_page = false; goto free_mem; } @@ -2593,7 +2593,8 @@ free_dma: ecc_temp += chip->ecc_parity_bytes; } - if ((n == cwperpage) && (num_zero_bits <= MAX_ECC_BIT_FLIPS)) + if ((n == cwperpage) && + (num_zero_bits <= info->flash_dev.ecc_capability)) *erased_page = true; free_mem: kfree(ecc); From 0308b8b14b58779a0ad4f1b12e6fea36200d0944 Mon Sep 17 00:00:00 2001 From: Akash Kumar Date: Mon, 13 Oct 2025 15:54:38 +0530 Subject: [PATCH 33/42] usb: gadget: uvc: Add grey and I420 YUV UVC format support uvc_formats[] needs to be updated with bitsperpixel,fcc tuple so that these formats can be passed by user space to S_FMT ioctl. user space must use streaming/uncompressed/u/guidFormat to specify the guid. user space must use streaming/uncompressed/u/bBitsPerPixel to set the bitsperpixel. In this case they are 8 and 12 respectively for grey and yuv420. GUID for these formats taken from drivers/media/usb/uvc/uvc_driver.c V4L2_PIX_FMT_GREY: { 'Y', '8', ' ', ' ', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} (bitsperpixel) : 8 V4L2_PIX_FMT_YUV420: { 'I', '4', '2', '0', 0x00, 0x00, 0x10, 0x00, \ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} (bitsperpixel) : 12 Change-Id: I6c164e4d77d4af03223f16a088ee743fbf0878b9 Signed-off-by: Akash Kumar --- drivers/usb/gadget/function/uvc_v4l2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c index 495f0ec663ea..93d0d0d2f75f 100644 --- a/drivers/usb/gadget/function/uvc_v4l2.c +++ b/drivers/usb/gadget/function/uvc_v4l2.c @@ -58,6 +58,8 @@ struct uvc_format { static struct uvc_format uvc_formats[] = { { 16, V4L2_PIX_FMT_YUYV }, { 0, V4L2_PIX_FMT_MJPEG }, + { 12, V4L2_PIX_FMT_YUV420 }, + { 8, V4L2_PIX_FMT_GREY }, }; static int From c5a324ce0b79d0f5c6770c902852693ff72ab3b8 Mon Sep 17 00:00:00 2001 From: Kaushik Yalla Date: Thu, 9 Oct 2025 02:28:35 -0700 Subject: [PATCH 34/42] kgsl: Add buffer overflow check for perfcounter dynamic list Add buffer overflow check to ensure dynamic list updates do not exceed allocated buffer size, returning an error if overflow would occur. Change-Id: I5ef8ff91fda3879250cb848761fa01674fc59cf7 Signed-off-by: Shiv Kumar Signed-off-by: Kaushik Yalla Signed-off-by: Chandra Vamsi Yekkaluri --- drivers/gpu/msm/adreno_a6xx.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index 048e33de599c..93bebbdb24fc 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include @@ -2523,6 +2524,7 @@ int a6xx_perfcounter_update(struct adreno_device *adreno_dev, struct cpu_gpu_lock *lock = ptr; u32 *data = ptr + sizeof(*lock); int i, offset = 0; + u32 pending_pairs = 2; /* No of pairs to add: and */ if (cpu_gpu_lock(lock)) { cpu_gpu_unlock(lock); @@ -2546,6 +2548,13 @@ int a6xx_perfcounter_update(struct adreno_device *adreno_dev, offset += 2; } + /* Ensure there is enough space in the reglist buffer for new pairs */ + if ((offset + (pending_pairs * 2)) >= + (adreno_dev->pwrup_reglist->size / sizeof(u32))) { + cpu_gpu_unlock(lock); + return -ENOSPC; + } + /* * For all targets A6XX_RBBM_PERFCTR_CNTL needs to be the last entry, * so overwrite the existing A6XX_RBBM_PERFCNTL_CTRL and add it back to From 5cef717354325b214141c9c5b4a0f88d90589cf4 Mon Sep 17 00:00:00 2001 From: Akash Kumar Date: Thu, 30 Oct 2025 16:07:18 +0530 Subject: [PATCH 35/42] UPSTREAM: usb: gadget: configfs: Add frame-based frame format support Add support for frame-based frame format, which can be used to support multiple formats like H264 or H265, in addition to MJPEG and YUV frames. The frame-based format is set to H264 by default, but it can be updated to other formats by modifying the GUID through the guid configfs attribute. Different structures are used for all three formats, as H264 has a different structure compared to MJPEG and uncompressed formats. These structures will be passed to the frame make function based on the active format, using a common frame structure with additional parameters needed only for frame-based formats. These parameters are handled at runtime in the UVC driver. Signed-off-by: Akash Kumar Link: https://lore.kernel.org/r/20240927152138.31416-1-quic_akakum@quicinc.com Signed-off-by: Greg Kroah-Hartman Git-commit: 7b5a58952fc3b51905c2963647485565df1e5e26 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git. Change-Id: Iffef14deba1f7e22c74b89b72a252f23802549d4 Signed-off-by: Akash Kumar --- .../ABI/testing/configfs-usb-gadget-uvc | 65 ++++ drivers/usb/gadget/function/f_uvc.c | 10 +- drivers/usb/gadget/function/uvc_configfs.c | 349 +++++++++++++++++- drivers/usb/gadget/function/uvc_v4l2.c | 1 + include/uapi/linux/usb/video.h | 58 +++ 5 files changed, 469 insertions(+), 14 deletions(-) diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uvc b/Documentation/ABI/testing/configfs-usb-gadget-uvc index 809765bd9573..5d4180aaf18e 100644 --- a/Documentation/ABI/testing/configfs-usb-gadget-uvc +++ b/Documentation/ABI/testing/configfs-usb-gadget-uvc @@ -265,6 +265,71 @@ Description: Specific uncompressed frame descriptors bmCapabilities - still image support, fixed frame-rate support +What: /config/usb-gadget/gadget/functions/uvc.name/streaming/framebased +Date: Oct 2025 +KernelVersion: 5.4 +Description: Framebased format descriptors + +What: /config/usb-gadget/gadget/functions/uvc.name/streaming/framebased/name +Date: Oct 2025 +KernelVersion: 5.4 +Description: Specific framebased format descriptors + + ================== ======================================= + bFormatIndex unique id for this format descriptor; + only defined after parent header is + linked into the streaming class; + read-only + bmaControls this format's data for bmaControls in + the streaming header + bmInterlaceFlags specifies interlace information, + read-only + bAspectRatioY the X dimension of the picture aspect + ratio, read-only + bAspectRatioX the Y dimension of the picture aspect + ratio, read-only + bDefaultFrameIndex optimum frame index for this stream + bBitsPerPixel number of bits per pixel used to + specify color in the decoded video + frame + guidFormat globally unique id used to identify + stream-encoding format + ================== ======================================= + +What: /config/usb-gadget/gadget/functions/uvc.name/streaming/framebased/name/name +Date: Sept 2024 +KernelVersion: 5.15 +Description: Specific framebased frame descriptors + + ========================= ===================================== + bFrameIndex unique id for this framedescriptor; + only defined after parent format is + linked into the streaming header; + read-only + dwFrameInterval indicates how frame interval can be + programmed; a number of values + separated by newline can be specified + dwDefaultFrameInterval the frame interval the device would + like to use as default + dwBytesPerLine Specifies the number of bytes per line + + of video for packed fixed frame size + formats, allowing the receiver to + perform stride alignment of the video. + If the bVariableSize value (above) is + TRUE (1), or if the format does not + permit such alignment, this value shall + be set to zero (0). + dwMaxBitRate the maximum bit rate at the shortest + frame interval in bps + dwMinBitRate the minimum bit rate at the longest + frame interval in bps + wHeight height of decoded bitmap frame in px + wWidth width of decoded bitmam frame in px + bmCapabilities still image support, fixed frame-rate + support + ========================= ===================================== + What: /config/usb-gadget/gadget/functions/uvc.name/streaming/header Date: Dec 2014 KernelVersion: 4.0 diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index 094a88ff9a67..b4c08b4ed602 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c @@ -808,9 +808,9 @@ static struct usb_function_instance *uvc_alloc_inst(void) cd->wObjectiveFocalLengthMax = cpu_to_le16(0); cd->wOcularFocalLength = cpu_to_le16(0); cd->bControlSize = 3; - cd->bmControls[0] = 2; - cd->bmControls[1] = 0; - cd->bmControls[2] = 0; + cd->bmControls[0] = 62; + cd->bmControls[1] = 126; + cd->bmControls[2] = 10; pd = &opts->uvc_processing; pd->bLength = UVC_DT_PROCESSING_UNIT_SIZE(2); @@ -820,8 +820,8 @@ static struct usb_function_instance *uvc_alloc_inst(void) pd->bSourceID = 1; pd->wMaxMultiplier = cpu_to_le16(16*1024); pd->bControlSize = 2; - pd->bmControls[0] = 1; - pd->bmControls[1] = 0; + pd->bmControls[0] = 91; + pd->bmControls[1] = 23; pd->iProcessing = 0; pd->bmVideoStandards = 0; diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c index 00fb58e50a15..5480a2988fe4 100644 --- a/drivers/usb/gadget/function/uvc_configfs.c +++ b/drivers/usb/gadget/function/uvc_configfs.c @@ -762,16 +762,19 @@ static const struct uvcg_config_group_type uvcg_control_grp_type = { /* ----------------------------------------------------------------------------- * streaming/uncompressed * streaming/mjpeg + * streaming/framebased */ static const char * const uvcg_format_names[] = { "uncompressed", "mjpeg", + "framebased" }; enum uvcg_format_type { UVCG_UNCOMPRESSED = 0, UVCG_MJPEG, + UVCG_FRAMEBASED, }; struct uvcg_format { @@ -1080,6 +1083,7 @@ struct uvcg_frame { u32 dw_max_video_frame_buffer_size; u32 dw_default_frame_interval; u8 b_frame_interval_type; + u32 dw_bytes_perline; } __attribute__((packed)) frame; u32 *dw_frame_interval; }; @@ -1190,6 +1194,7 @@ UVCG_FRAME_ATTR(dw_min_bit_rate, dwMinBitRate, 32); UVCG_FRAME_ATTR(dw_max_bit_rate, dwMaxBitRate, 32); UVCG_FRAME_ATTR(dw_max_video_frame_buffer_size, dwMaxVideoFrameBufferSize, 32); UVCG_FRAME_ATTR(dw_default_frame_interval, dwDefaultFrameInterval, 32); +UVCG_FRAME_ATTR(dw_bytes_perline, dwBytesPerLine, 32); #undef UVCG_FRAME_ATTR @@ -1324,7 +1329,7 @@ end: UVC_ATTR(uvcg_frame_, dw_frame_interval, dwFrameInterval); -static struct configfs_attribute *uvcg_frame_attrs[] = { +static struct configfs_attribute *uvcg_frame_attrs1[] = { &uvcg_frame_attr_b_frame_index, &uvcg_frame_attr_bm_capabilities, &uvcg_frame_attr_w_width, @@ -1337,12 +1342,32 @@ static struct configfs_attribute *uvcg_frame_attrs[] = { NULL, }; -static const struct config_item_type uvcg_frame_type = { +static struct configfs_attribute *uvcg_frame_attrs2[] = { + &uvcg_frame_attr_b_frame_index, + &uvcg_frame_attr_bm_capabilities, + &uvcg_frame_attr_w_width, + &uvcg_frame_attr_w_height, + &uvcg_frame_attr_dw_min_bit_rate, + &uvcg_frame_attr_dw_max_bit_rate, + &uvcg_frame_attr_dw_max_video_frame_buffer_size, + &uvcg_frame_attr_dw_default_frame_interval, + &uvcg_frame_attr_dw_frame_interval, + &uvcg_frame_attr_dw_bytes_perline, + NULL, +}; + +static const struct config_item_type uvcg_frame_type1 = { .ct_item_ops = &uvcg_config_item_ops, - .ct_attrs = uvcg_frame_attrs, + .ct_attrs = uvcg_frame_attrs1, .ct_owner = THIS_MODULE, }; +static const struct config_item_type uvcg_frame_type2 = { + .ct_item_ops = &uvcg_config_item_ops, + .ct_attrs = uvcg_frame_attrs2, + .ct_owner = THIS_MODULE, +}; + static struct config_item *uvcg_frame_make(struct config_group *group, const char *name) { @@ -1363,6 +1388,7 @@ static struct config_item *uvcg_frame_make(struct config_group *group, h->frame.dw_max_bit_rate = 55296000; h->frame.dw_max_video_frame_buffer_size = 460800; h->frame.dw_default_frame_interval = 666666; + h->frame.dw_bytes_perline = 0; opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; opts = to_f_uvc_opts(opts_item); @@ -1375,6 +1401,9 @@ static struct config_item *uvcg_frame_make(struct config_group *group, } else if (fmt->type == UVCG_MJPEG) { h->frame.b_descriptor_subtype = UVC_VS_FRAME_MJPEG; h->fmt_type = UVCG_MJPEG; + } else if (fmt->type == UVCG_FRAMEBASED) { + h->frame.b_descriptor_subtype = UVC_VS_FRAME_FRAME_BASED; + h->fmt_type = UVCG_FRAMEBASED; } else { mutex_unlock(&opts->lock); kfree(h); @@ -1383,7 +1412,10 @@ static struct config_item *uvcg_frame_make(struct config_group *group, ++fmt->num_frames; mutex_unlock(&opts->lock); - config_item_init_type_name(&h->item, name, &uvcg_frame_type); + if (fmt->type == UVCG_FRAMEBASED) + config_item_init_type_name(&h->item, name, &uvcg_frame_type2); + else + config_item_init_type_name(&h->item, name, &uvcg_frame_type1); return &h->item; } @@ -1413,9 +1445,6 @@ static void uvcg_format_set_indices(struct config_group *fmt) list_for_each_entry(ci, &fmt->cg_children, ci_entry) { struct uvcg_frame *frm; - if (ci->ci_type != &uvcg_frame_type) - continue; - frm = to_uvcg_frame(ci); frm->frame.b_frame_index = i++; } @@ -1856,6 +1885,260 @@ static const struct uvcg_config_group_type uvcg_mjpeg_grp_type = { .name = "mjpeg", }; +/* ----------------------------------------------------------------------------- + * streaming/framebased/ + */ + +struct uvcg_framebased { + struct uvcg_format fmt; + struct uvc_format_framebased desc; +}; + +static inline struct uvcg_framebased *to_uvcg_framebased(struct config_item *item) +{ + return container_of(to_uvcg_format(item), struct uvcg_framebased, fmt); +} + +static struct configfs_group_operations uvcg_framebased_group_ops = { + .make_item = uvcg_frame_make, + .drop_item = uvcg_frame_drop, +}; + +#define UVCG_FRAMEBASED_ATTR_RO(cname, aname, bits) \ + static ssize_t uvcg_framebased_##cname##_show(struct config_item *item, \ + char *page) \ +{ \ + struct uvcg_framebased *u = to_uvcg_framebased(item); \ + struct f_uvc_opts *opts; \ + struct config_item *opts_item; \ + struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \ + int result; \ + \ + mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ + \ + opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent; \ + opts = to_f_uvc_opts(opts_item); \ + \ + mutex_lock(&opts->lock); \ + result = scnprintf(page, PAGE_SIZE, "%u\n", le##bits##_to_cpu(u->desc.aname));\ + mutex_unlock(&opts->lock); \ + \ + mutex_unlock(su_mutex); \ + return result; \ +} \ + \ +UVC_ATTR_RO(uvcg_framebased_, cname, aname) + +#define UVCG_FRAMEBASED_ATTR(cname, aname, bits) \ + static ssize_t uvcg_framebased_##cname##_show(struct config_item *item, \ + char *page) \ +{ \ + struct uvcg_framebased *u = to_uvcg_framebased(item); \ + struct f_uvc_opts *opts; \ + struct config_item *opts_item; \ + struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \ + int result; \ + \ + mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ + \ + opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\ + opts = to_f_uvc_opts(opts_item); \ + \ + mutex_lock(&opts->lock); \ + result = scnprintf(page, PAGE_SIZE, "%u\n", le##bits##_to_cpu(u->desc.aname));\ + mutex_unlock(&opts->lock); \ + \ + mutex_unlock(su_mutex); \ + return result; \ +} \ + \ +static ssize_t \ +uvcg_framebased_##cname##_store(struct config_item *item, \ + const char *page, size_t len) \ +{ \ + struct uvcg_framebased *u = to_uvcg_framebased(item); \ + struct f_uvc_opts *opts; \ + struct config_item *opts_item; \ + struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \ + int ret; \ + u8 num; \ + \ + mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ + \ + opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\ + opts = to_f_uvc_opts(opts_item); \ + \ + mutex_lock(&opts->lock); \ + if (u->fmt.linked || opts->refcnt) { \ + ret = -EBUSY; \ + goto end; \ + } \ + \ + ret = kstrtou8(page, 0, &num); \ + if (ret) \ + goto end; \ + \ + if (num > 255) { \ + ret = -EINVAL; \ + goto end; \ + } \ + u->desc.aname = num; \ + ret = len; \ +end: \ + mutex_unlock(&opts->lock); \ + mutex_unlock(su_mutex); \ + return ret; \ +} \ + \ +UVC_ATTR(uvcg_framebased_, cname, aname) + +UVCG_FRAMEBASED_ATTR_RO(b_format_index, bFormatIndex, 8); +UVCG_FRAMEBASED_ATTR_RO(b_bits_per_pixel, bBitsPerPixel, 8); +UVCG_FRAMEBASED_ATTR(b_default_frame_index, bDefaultFrameIndex, 8); +UVCG_FRAMEBASED_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, 8); +UVCG_FRAMEBASED_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, 8); +UVCG_FRAMEBASED_ATTR_RO(bm_interface_flags, bmInterfaceFlags, 8); + +#undef UVCG_FRAMEBASED_ATTR +#undef UVCG_FRAMEBASED_ATTR_RO + +static ssize_t uvcg_framebased_guid_format_show(struct config_item *item, + char *page) +{ + struct uvcg_framebased *ch = to_uvcg_framebased(item); + struct f_uvc_opts *opts; + struct config_item *opts_item; + struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex; + + mutex_lock(su_mutex); /* for navigating configfs hierarchy */ + + opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent; + opts = to_f_uvc_opts(opts_item); + + mutex_lock(&opts->lock); + memcpy(page, ch->desc.guidFormat, sizeof(ch->desc.guidFormat)); + mutex_unlock(&opts->lock); + + mutex_unlock(su_mutex); + + return sizeof(ch->desc.guidFormat); +} + +static ssize_t uvcg_framebased_guid_format_store(struct config_item *item, + const char *page, size_t len) +{ + struct uvcg_framebased *ch = to_uvcg_framebased(item); + struct f_uvc_opts *opts; + struct config_item *opts_item; + struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex; + int ret; + + mutex_lock(su_mutex); /* for navigating configfs hierarchy */ + + opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent; + opts = to_f_uvc_opts(opts_item); + + mutex_lock(&opts->lock); + if (ch->fmt.linked || opts->refcnt) { + ret = -EBUSY; + goto end; + } + + memcpy(ch->desc.guidFormat, page, + min(sizeof(ch->desc.guidFormat), len)); + ret = sizeof(ch->desc.guidFormat); + +end: + mutex_unlock(&opts->lock); + mutex_unlock(su_mutex); + return ret; +} + +UVC_ATTR(uvcg_framebased_, guid_format, guidFormat); + + static inline ssize_t +uvcg_framebased_bma_controls_show(struct config_item *item, char *page) +{ + struct uvcg_framebased *u = to_uvcg_framebased(item); + + return uvcg_format_bma_controls_show(&u->fmt, page); +} + + static inline ssize_t +uvcg_framebased_bma_controls_store(struct config_item *item, + const char *page, size_t len) +{ + struct uvcg_framebased *u = to_uvcg_framebased(item); + + return uvcg_format_bma_controls_store(&u->fmt, page, len); +} + +UVC_ATTR(uvcg_framebased_, bma_controls, bmaControls); + +static struct configfs_attribute *uvcg_framebased_attrs[] = { + &uvcg_framebased_attr_b_format_index, + &uvcg_framebased_attr_b_default_frame_index, + &uvcg_framebased_attr_b_bits_per_pixel, + &uvcg_framebased_attr_b_aspect_ratio_x, + &uvcg_framebased_attr_b_aspect_ratio_y, + &uvcg_framebased_attr_bm_interface_flags, + &uvcg_framebased_attr_bma_controls, + &uvcg_framebased_attr_guid_format, + NULL, +}; + +static const struct config_item_type uvcg_framebased_type = { + .ct_item_ops = &uvcg_config_item_ops, + .ct_group_ops = &uvcg_framebased_group_ops, + .ct_attrs = uvcg_framebased_attrs, + .ct_owner = THIS_MODULE, +}; + +static struct config_group *uvcg_framebased_make(struct config_group *group, + const char *name) +{ + static char guid[] = { /*Declear frame based as H264 format*/ + 'H', '2', '6', '4', 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 + }; + struct uvcg_framebased *h; + + h = kzalloc(sizeof(*h), GFP_KERNEL); + if (!h) + return ERR_PTR(-ENOMEM); + + h->desc.bLength = UVC_DT_FORMAT_FRAMEBASED_SIZE; + h->desc.bDescriptorType = USB_DT_CS_INTERFACE; + h->desc.bDescriptorSubType = UVC_VS_FORMAT_FRAME_BASED; + memcpy(h->desc.guidFormat, guid, sizeof(guid)); + h->desc.bBitsPerPixel = 0; + h->desc.bDefaultFrameIndex = 1; + h->desc.bAspectRatioX = 0; + h->desc.bAspectRatioY = 0; + h->desc.bmInterfaceFlags = 0; + h->desc.bCopyProtect = 0; + h->desc.bVariableSize = 1; + + h->fmt.type = UVCG_FRAMEBASED; + config_group_init_type_name(&h->fmt.group, name, + &uvcg_framebased_type); + + return &h->fmt.group; +} + +static struct configfs_group_operations uvcg_framebased_grp_ops = { + .make_group = uvcg_framebased_make, +}; + +static const struct uvcg_config_group_type uvcg_framebased_grp_type = { + .type = { + .ct_item_ops = &uvcg_config_item_ops, + .ct_group_ops = &uvcg_framebased_grp_ops, + .ct_owner = THIS_MODULE, + }, + .name = "framebased", +}; + /* ----------------------------------------------------------------------------- * streaming/color_matching/default */ @@ -2001,6 +2284,7 @@ static int __uvcg_iter_strm_cls(struct uvcg_streaming_header *h, if (ret) return ret; grp = &f->fmt->group; + j = 0; list_for_each_entry(item, &grp->cg_children, ci_entry) { frm = to_uvcg_frame(item); ret = fun(frm, priv2, priv3, j++, UVCG_FRAME); @@ -2049,6 +2333,11 @@ static int __uvcg_cnt_strm(void *priv1, void *priv2, void *priv3, int n, container_of(fmt, struct uvcg_mjpeg, fmt); *size += sizeof(m->desc); + } else if (fmt->type == UVCG_FRAMEBASED) { + struct uvcg_framebased *f = + container_of(fmt, struct uvcg_framebased, fmt); + + *size += sizeof(f->desc); } else { return -EINVAL; } @@ -2059,6 +2348,11 @@ static int __uvcg_cnt_strm(void *priv1, void *priv2, void *priv3, int n, int sz = sizeof(frm->dw_frame_interval); *size += sizeof(frm->frame); + /* + * framebased has duplicate member with uncompressed and + * mjpeg, so minus it + */ + *size -= sizeof(u32); *size += frm->frame.b_frame_interval_type * sz; } break; @@ -2069,6 +2363,27 @@ static int __uvcg_cnt_strm(void *priv1, void *priv2, void *priv3, int n, return 0; } +static int __uvcg_copy_framebased_desc(void *dest, struct uvcg_frame *frm, + int sz) +{ + struct uvc_frame_framebased *desc = dest; + + desc->bLength = frm->frame.b_length; + desc->bDescriptorType = frm->frame.b_descriptor_type; + desc->bDescriptorSubType = frm->frame.b_descriptor_subtype; + desc->bFrameIndex = frm->frame.b_frame_index; + desc->bmCapabilities = frm->frame.bm_capabilities; + desc->wWidth = frm->frame.w_width; + desc->wHeight = frm->frame.w_height; + desc->dwMinBitRate = frm->frame.dw_min_bit_rate; + desc->dwMaxBitRate = frm->frame.dw_max_bit_rate; + desc->dwDefaultFrameInterval = frm->frame.dw_default_frame_interval; + desc->bFrameIntervalType = frm->frame.b_frame_interval_type; + desc->dwBytesPerLine = frm->frame.dw_bytes_perline; + + return 0; +} + /* * Fill an array of streaming descriptors. * @@ -2123,6 +2438,15 @@ static int __uvcg_fill_strm(void *priv1, void *priv2, void *priv3, int n, m->desc.bNumFrameDescriptors = fmt->num_frames; memcpy(*dest, &m->desc, sizeof(m->desc)); *dest += sizeof(m->desc); + } else if (fmt->type == UVCG_FRAMEBASED) { + struct uvcg_framebased *f = + container_of(fmt, struct uvcg_framebased, + fmt); + + f->desc.bFormatIndex = n + 1; + f->desc.bNumFrameDescriptors = fmt->num_frames; + memcpy(*dest, &f->desc, sizeof(f->desc)); + *dest += sizeof(f->desc); } else { return -EINVAL; } @@ -2132,8 +2456,11 @@ static int __uvcg_fill_strm(void *priv1, void *priv2, void *priv3, int n, struct uvcg_frame *frm = priv1; struct uvc_descriptor_header *h = *dest; - sz = sizeof(frm->frame); - memcpy(*dest, &frm->frame, sz); + sz = sizeof(frm->frame) - 4; + if (frm->fmt_type != UVCG_FRAMEBASED) + memcpy(*dest, &frm->frame, sz); + else + __uvcg_copy_framebased_desc(*dest, frm, sz); *dest += sz; sz = frm->frame.b_frame_interval_type * sizeof(*frm->dw_frame_interval); @@ -2145,6 +2472,9 @@ static int __uvcg_fill_strm(void *priv1, void *priv2, void *priv3, int n, else if (frm->fmt_type == UVCG_MJPEG) h->bLength = UVC_DT_FRAME_MJPEG_SIZE( frm->frame.b_frame_interval_type); + else if (frm->fmt_type == UVCG_FRAMEBASED) + h->bLength = UVC_DT_FRAME_FRAMEBASED_SIZE( + frm->frame.b_frame_interval_type); } break; } @@ -2357,6 +2687,7 @@ static const struct uvcg_config_group_type uvcg_streaming_grp_type = { &uvcg_streaming_header_grp_type, &uvcg_uncompressed_grp_type, &uvcg_mjpeg_grp_type, + &uvcg_framebased_grp_type, &uvcg_color_matching_grp_type, &uvcg_streaming_class_grp_type, NULL, diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c index 93d0d0d2f75f..49f1f2ad134e 100644 --- a/drivers/usb/gadget/function/uvc_v4l2.c +++ b/drivers/usb/gadget/function/uvc_v4l2.c @@ -58,6 +58,7 @@ struct uvc_format { static struct uvc_format uvc_formats[] = { { 16, V4L2_PIX_FMT_YUYV }, { 0, V4L2_PIX_FMT_MJPEG }, + { 0, V4L2_PIX_FMT_H264 }, { 12, V4L2_PIX_FMT_YUV420 }, { 8, V4L2_PIX_FMT_GREY }, }; diff --git a/include/uapi/linux/usb/video.h b/include/uapi/linux/usb/video.h index c58854fb7d94..c79b6049d9d7 100644 --- a/include/uapi/linux/usb/video.h +++ b/include/uapi/linux/usb/video.h @@ -597,5 +597,63 @@ struct UVC_FRAME_MJPEG(n) { \ __le32 dwFrameInterval[n]; \ } __attribute__ ((packed)) +/* Frame Based Payload - 3.1.1. Frame Based Video Format Descriptor */ +struct uvc_format_framebased { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + __u8 bFormatIndex; + __u8 bNumFrameDescriptors; + __u8 guidFormat[16]; + __u8 bBitsPerPixel; + __u8 bDefaultFrameIndex; + __u8 bAspectRatioX; + __u8 bAspectRatioY; + __u8 bmInterfaceFlags; + __u8 bCopyProtect; + __u8 bVariableSize; +} __attribute__((__packed__)); + +#define UVC_DT_FORMAT_FRAMEBASED_SIZE 28 + +/* Frame Based Payload - 3.1.2. Frame Based Video Frame Descriptor */ +struct uvc_frame_framebased { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + __u8 bFrameIndex; + __u8 bmCapabilities; + __u16 wWidth; + __u16 wHeight; + __u32 dwMinBitRate; + __u32 dwMaxBitRate; + __u32 dwDefaultFrameInterval; + __u8 bFrameIntervalType; + __u32 dwBytesPerLine; + __u32 dwFrameInterval[]; +} __attribute__((__packed__)); + +#define UVC_DT_FRAME_FRAMEBASED_SIZE(n) (26+4*(n)) + +#define UVC_FRAME_FRAMEBASED(n) \ + uvc_frame_framebased_##n + +#define DECLARE_UVC_FRAME_FRAMEBASED(n) \ + struct UVC_FRAME_FRAMEBASED(n) { \ + __u8 bLength; \ + __u8 bDescriptorType; \ + __u8 bDescriptorSubType; \ + __u8 bFrameIndex; \ + __u8 bmCapabilities; \ + __u16 wWidth; \ + __u16 wHeight; \ + __u32 dwMinBitRate; \ + __u32 dwMaxBitRate; \ + __u32 dwDefaultFrameInterval; \ + __u8 bFrameIntervalType; \ + __u32 dwBytesPerLine; \ + __u32 dwFrameInterval[n]; \ + } __attribute__ ((packed)) + #endif /* __LINUX_USB_VIDEO_H */ From a3e616cc0d3d7a59818c35acfa7f8829def160b0 Mon Sep 17 00:00:00 2001 From: Desireddy Suresh Kumar Reddy Date: Fri, 9 Feb 2024 16:49:34 +0530 Subject: [PATCH 36/42] net: bridge: Fix for co-located mode Issue point: 1.qca-hyfi-bridge calls the HyFi-hooks for enabling the co-located mode. a. hyfi_bridge_get_dst and br_get_dst_hook functions are passed as arguments in a rcu_assign_pointer function. b. br_get_dst_hook implementations should be available in the br_dev_xmit kernel function. But currently br_get_dst_hook implementations are missing in br_dev_xmit. Fix: 1. For enabling co-located-agent-mode and ieee1905-packet-transfer this HyFi-hook (br_get_dst_hook) are made available in br_dev_xmit function. a. Added the br_get_dst_hook and get_dst_hook in the required files(net/bridge/br_input.c & net/bridge/br_device.c) Change-Id: Iac43ea347c83276971816029a940818e99752710 Signed-off-by: Desireddy Suresh Kumar Reddy --- include/linux/if_bridge.h | 4 ++++ net/bridge/br_device.c | 27 ++++++++++++++++++++++++--- net/bridge/br_input.c | 19 ++++++++++++++++++- 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h index 9e2ad3b81690..e06623fa5b80 100644 --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h @@ -162,5 +162,9 @@ extern br_notify_hook_t __rcu *br_notify_hook; typedef int (br_multicast_handle_hook_t)(const struct net_bridge_port *src, struct sk_buff *skb); extern br_multicast_handle_hook_t __rcu *br_multicast_handle_hook; +typedef struct net_bridge_port *br_get_dst_hook_t( + const struct net_bridge_port *src, + struct sk_buff **skb); +extern br_get_dst_hook_t __rcu *br_get_dst_hook; #endif #endif diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 00438505c175..ec4dee64357b 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -34,6 +34,10 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) const struct nf_br_ops *nf_ops; const unsigned char *dest; u16 vid = 0; +#ifdef CONFIG_HYFI_BRIDGE_HOOKS + struct net_bridge_port *pdst; + br_get_dst_hook_t *get_dst_hook; +#endif if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) { kfree_skb(skb); @@ -82,6 +86,10 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) br_do_suppress_nd(skb, br, vid, NULL, msg); } +#ifdef CONFIG_HYFI_BRIDGE_HOOKS + get_dst_hook = rcu_dereference(br_get_dst_hook); +#endif + dest = eth_hdr(skb)->h_dest; if (is_broadcast_ether_addr(dest)) { br_flood(br, skb, BR_PKT_BROADCAST, false, true); @@ -107,11 +115,24 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) br_multicast_flood(mdst, skb, false, true); else br_flood(br, skb, BR_PKT_MULTICAST, false, true); - } else if ((dst = br_fdb_find_rcu(br, dest, vid)) != NULL) { - br_forward(dst->dst, skb, false, true); } else { - br_flood(br, skb, BR_PKT_UNICAST, false, true); +#ifdef CONFIG_HYFI_BRIDGE_HOOKS + pdst = __br_get(get_dst_hook, NULL, NULL, &skb); + if (pdst) { + if (!skb) + goto out; + br_forward(pdst, skb, false, true); + } else +#endif + { + dst = br_fdb_find_rcu(br, dest, vid); + if (dst) + br_forward(dst->dst, skb, false, true); + else + br_flood(br, skb, BR_PKT_UNICAST, false, true); + } } + out: rcu_read_unlock(); return NETDEV_TX_OK; diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index ace461e94830..02dbaf13f591 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -33,6 +33,11 @@ br_netif_receive_skb(struct net *net, struct sock *sk, struct sk_buff *skb) /* Hook for external Multicast handler */ br_multicast_handle_hook_t __rcu *br_multicast_handle_hook __read_mostly; EXPORT_SYMBOL(br_multicast_handle_hook); + +/* Hook for external forwarding logic */ +br_get_dst_hook_t __rcu *br_get_dst_hook __read_mostly; +EXPORT_SYMBOL_GPL(br_get_dst_hook); + #endif int br_pass_frame_up(struct sk_buff *skb) @@ -94,6 +99,8 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb struct net_bridge *br; #ifdef CONFIG_HYFI_BRIDGE_HOOKS br_multicast_handle_hook_t *multicast_handle_hook; + struct net_bridge_port *pdst = NULL; + br_get_dst_hook_t *get_dst_hook = rcu_dereference(br_get_dst_hook); #endif u16 vid = 0; @@ -168,7 +175,17 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb } break; case BR_PKT_UNICAST: - dst = br_fdb_find_rcu(br, eth_hdr(skb)->h_dest, vid); +#ifdef CONFIG_HYFI_BRIDGE_HOOKS + pdst = __br_get(get_dst_hook, NULL, p, &skb); + if (pdst) { + if (!skb) + goto out; + } else +#endif + { + dst = br_fdb_find_rcu(br, eth_hdr(skb)->h_dest, vid); + } + break; default: break; } From 3a1ebfc377d01f5123dd9509ba774666b38c7e0a Mon Sep 17 00:00:00 2001 From: Manoj Sekar Date: Mon, 26 Jun 2023 22:26:28 +0530 Subject: [PATCH 37/42] bridge: port structure members from 5.4 kernel port bridge related structure members from 5.4 kernel to 5.15 kernel required for EasyMesh Kernel modules. Change-Id: I74c934a0a6c96782f4e6c4ff99e26ab1b8b39168 Signed-off-by: Manoj Sekar --- net/bridge/br_private.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index c7130fff57a0..023ecc1f4494 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -195,6 +195,9 @@ struct net_bridge_fdb_entry { struct net_bridge_fdb_key key; struct hlist_node fdb_node; + unsigned char is_local:1, + is_static:1; + unsigned long flags; unsigned char offloaded:1; From 895cfcbb7afc51c581db9fb91146e95f8fd5d676 Mon Sep 17 00:00:00 2001 From: Manoj Sekar Date: Mon, 26 Jun 2023 20:31:54 +0530 Subject: [PATCH 38/42] net: Add netdevice notification for bridge activity This modification allows programs to get notified whenever a device is added to or removed from a bridge. This will be used by NSS Qdisc for updating bridge shaper configuration. Change-Id: I70e63c5b219d7ab022400741b2dc789cfef71ead Signed-off-by: Manoj Sekar --- include/linux/netdevice.h | 2 ++ net/bridge/br_if.c | 3 +++ net/core/dev.c | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 7d048d775eff..04fde5ea195b 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2554,6 +2554,8 @@ enum netdev_cmd { NETDEV_CVLAN_FILTER_DROP_INFO, NETDEV_SVLAN_FILTER_PUSH_INFO, NETDEV_SVLAN_FILTER_DROP_INFO, + NETDEV_BR_JOIN, + NETDEV_BR_LEAVE, }; const char *netdev_cmd_to_name(enum netdev_cmd cmd); diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index ea0ddd513cc1..a5565b7dfb06 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -695,6 +695,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev, br_set_gso_limits(br); kobject_uevent(&p->kobj, KOBJ_ADD); + call_netdevice_notifiers(NETDEV_BR_JOIN, dev); return 0; @@ -732,6 +733,8 @@ int br_del_if(struct net_bridge *br, struct net_device *dev) if (!p || p->br != br) return -EINVAL; + call_netdevice_notifiers(NETDEV_BR_LEAVE, dev); + /* Since more than one interface can be attached to a bridge, * there still maybe an alternate path for netconsole to use; * therefore there is no reason for a NETDEV_RELEASE event. diff --git a/net/core/dev.c b/net/core/dev.c index aad29ac5ac15..d4d84160b795 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1521,7 +1521,7 @@ const char *netdev_cmd_to_name(enum netdev_cmd cmd) N(UDP_TUNNEL_DROP_INFO) N(CHANGE_TX_QUEUE_LEN) N(CVLAN_FILTER_PUSH_INFO) N(CVLAN_FILTER_DROP_INFO) N(SVLAN_FILTER_PUSH_INFO) N(SVLAN_FILTER_DROP_INFO) - N(PRE_CHANGEADDR) + N(PRE_CHANGEADDR) N(BR_JOIN) N(BR_LEAVE) } #undef N return "UNKNOWN_NETDEV_EVENT"; From 491b8e69beb7e7813819d801a01a694bb95c3432 Mon Sep 17 00:00:00 2001 From: Shiv Kumar Date: Wed, 10 Sep 2025 21:55:15 +0530 Subject: [PATCH 39/42] kgsl: gmu: Use num_vma for safe GMU VMAs array access Use num_vma to bound GMU VMAs array access instead of GMU_MEM_TYPE_MAX, preventing out-of-bounds reads when the array size is less than the enum maximum. Change-Id: Iffb587e5eb3fa70356872eb0f56d065d1b58f27c Signed-off-by: Shiv Kumar Signed-off-by: Sushmita Gollena Signed-off-by: Nagababu Pamarthi --- drivers/gpu/msm/adreno_a6xx_gmu.c | 9 ++++++--- drivers/gpu/msm/adreno_a6xx_gmu.h | 2 ++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c index 8a4ea1752b24..07b1e1d24f45 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu.c +++ b/drivers/gpu/msm/adreno_a6xx_gmu.c @@ -593,7 +593,7 @@ static int find_vma_block(struct a6xx_gmu_device *gmu, u32 addr, u32 size) { int i; - for (i = 0; i < GMU_MEM_TYPE_MAX; i++) { + for (i = 0; i < gmu->num_vmas; i++) { struct gmu_vma_entry *vma = &gmu->vma[i]; if ((addr >= vma->start) && @@ -2685,10 +2685,13 @@ int a6xx_gmu_probe(struct kgsl_device *device, if (ret) goto error; - if (adreno_is_a650_family(adreno_dev)) + if (adreno_is_a650_family(adreno_dev)) { gmu->vma = a6xx_gmu_vma; - else + gmu->num_vmas = ARRAY_SIZE(a6xx_gmu_vma); + } else { gmu->vma = a6xx_gmu_vma_legacy; + gmu->num_vmas = ARRAY_SIZE(a6xx_gmu_vma_legacy); + } /* Map and reserve GMU CSRs registers */ ret = a6xx_gmu_reg_probe(adreno_dev); diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.h b/drivers/gpu/msm/adreno_a6xx_gmu.h index d39597683ec9..b671771c46b4 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu.h +++ b/drivers/gpu/msm/adreno_a6xx_gmu.h @@ -187,6 +187,8 @@ struct a6xx_gmu_device { /** @global_entries: To keep track of number of gmu buffers */ u32 global_entries; struct gmu_vma_entry *vma; + /** @num_vmas: Number of entries in the @vma array */ + u32 num_vmas; unsigned int log_wptr_retention; /** @cm3_fault: whether gmu received a cm3 fault interrupt */ atomic_t cm3_fault; From 1d2451ca457a90a44a73618195247bdadee66381 Mon Sep 17 00:00:00 2001 From: Pulkit Singh Tak Date: Tue, 30 Dec 2025 11:39:53 +0530 Subject: [PATCH 40/42] msm: eva: OOB write issue in fence processing Added check for number of fences from user in kernel space before fence processing. Change-Id: I58f7899a811245a33357f19678557cb35b6a3736 Signed-off-by: Pulkit Singh Tak --- drivers/media/platform/msm/cvp/msm_cvp.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/media/platform/msm/cvp/msm_cvp.c b/drivers/media/platform/msm/cvp/msm_cvp.c index 239ceb89acfa..346f21641519 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp.c +++ b/drivers/media/platform/msm/cvp/msm_cvp.c @@ -741,6 +741,13 @@ static int msm_cvp_session_process_hfi_fence(struct msm_cvp_inst *inst, f->output_index = kfc->output_index; } + if (f->num_fences >= (MAX_HFI_FENCE_SIZE / 2)) { + dprintk(CVP_ERR, "%s: Max number of fences exceeded! Max number supported: %d", + __func__, (MAX_HFI_FENCE_SIZE / 2)); + cvp_free_fence_data(f); + msm_cvp_unmap_frame(inst, pkt->client_data.kdata); + goto exit; + } dprintk(CVP_SYNX, "%s: frameID %llu ktid %llu\n", __func__, f->frame_id, pkt->client_data.kdata); From 365834436c0aa0f53cd5a0901deebf652859cfef Mon Sep 17 00:00:00 2001 From: kamasali Satyanarayan Date: Mon, 12 Jan 2026 14:13:47 +0530 Subject: [PATCH 41/42] reverting all USB patches ac91ada020c1 usb: xhci: plat: Facilitate using autosuspend for xhci plat devices e9d2ab8795d1 usb: mon: Increase BUFF_MAX to 64 MiB to support multi-MB URBs 3248107d0094 usb: gadget: f_hid: Fix zero length packet transfer a3f918b791cd usb: gadget: f_ncm: Fix MAC assignment NCM ethernet b00d2572c16e usb: gadget: f_fs: Fix epfile null pointer access after ep enable. 428c8047526a xhci: dbc: enable back DbC in resume if it was enabled before suspend 02a089cf4042 usb/core/quirks: Add Huawei ME906S to wakeup quirk 2b24cd3ab1c7 USB: serial: option: add Telit FN920C04 ECM compositions e9639d4237e8 USB: serial: option: add Quectel RG255C 84c73088ec0d USB: serial: option: add UNISOC UIS7720 0ba8541351bf usb: vhci-hcd: Prevent suspending virtually attached devices b86de42c4276 usb: gadget: configfs: Correctly set use_os_string at bind a88df3897031 usb: phy: twl6030: Fix incorrect type for ret 89838fe5c6c0 usb: host: max3421-hcd: Fix error pointer dereference in probe cleanup a1f24c2e911a USB: serial: option: add SIMCom 8230C compositions f5fcec379ef4 usb: core: Add 0x prefix to quirks debug output ea748ebb9084 USB: gadget: dummy-hcd: Fix locking bug in RT-enabled kernels 6070c741cc5c usb: gadget: dummy_hcd: remove usage of list iterator past the loop body 2f28d51cf862 USB: serial: option: add Telit Cinterion LE910C4-WWX new compositions b896501ea175 USB: serial: option: add Telit Cinterion FN990A w/audio compositions 6ddde3e46176 usb: hub: Fix flushing of delayed work used for post resume purposes ef49d17eac00 usb: xhci: Fix slot_id resource race conflict 07dad577076f usb: musb: omap2430: fix device leak at unbind 2cbf9f514ed1 usb: typec: fusb302: cache PD RX state 0e35cac65aae cdc-acm: fix race between initial clearing halt and open 46ce8549441c USB: cdc-acm: do not log successful probe on later errors b25dad547b44 usb: hub: Don't try to recover devices lost during warm reset. 1bd9246548a1 usb: hub: avoid warm port reset during USB3 disconnect 0c1699135dc6 usb: dwc3: Ignore late xferNotReady event to prevent halt timeout f93fb614d3f4 USB: storage: Ignore driver CD mode for Realtek multi-mode Wi-Fi dongles a648cc7c4946 usb: storage: realtek_cr: Use correct byte order for bcs->Residue eb2223e2c8a5 USB: storage: Add unusual-devs entry for Novatek NTK96550-based camera deef90c5a489 usb: quirks: Add DELAY_INIT quick for another SanDisk 3.2Gen1 Flash Drive 57df8e2a67f7 usb: dwc3: meson-g12a: fix device leaks at unbind 22ac4969dc37 usb: gadget: udc: renesas_usb3: fix device leak at unbind c280a4427add usb: atm: cxacru: Merge cxacru_upload_firmware() into cxacru_heavy_init() c41fef8b2dfe usb: core: usb_submit_urb: downgrade type check 608ab9ff2118 usb: xhci: Avoid showing errors during surprise removal 0913e9234c0f usb: xhci: Set avg_trb_len = 8 for EP0 during Address Device Command fcd65f353012 usb: xhci: Avoid showing warnings for dying controller c698f6d03d17 usb: xhci: print xhci->xhc_state when queue_command failed dba96dfa5a0f usb: gadget : fix use-after-free in composite_dev_cleanup() 1db292bca68e USB: serial: option: add Foxconn T99W709 651a71f931f8 usb: chipidea: udc: fix sleeping function called from invalid context d12d31cd5bdb usb: early: xhci-dbc: Fix early_ioremap leak e5d396f42d75 usb: phy: mxs: disconnect line when USB charger is attached 4eb4ad451e3f usb: chipidea: add USB PHY event f2b6a88c1cbd usb: chipidea: introduce CI_HDRC_CONTROLLER_VBUS_EVENT glue layer use 770809a95864 usb: chipidea: udc: protect usb interrupt enable 4fbf6bb0f97c usb: chipidea: udc: add new API ci_hdrc_gadget_connect c72cd4c92e06 usb: hub: Fix flushing and scheduling of delayed work that tunes runtime pm 042959e9b479 usb: hub: fix detection of high tier USB3 devices behind suspended hubs c7e68db993c2 xhci: Disable stream for xHC controller with XHCI_BROKEN_STREAMS 3451944a8cde usb: dwc3: qcom: Don't leave BCR asserted 4ea93e0eb91f usb: musb: fix gadget state on disconnect 78b41148cfea usb: gadget: configfs: Fix OOB read on empty string write bc5c5490062a USB: serial: ftdi_sio: add support for NDI EMGUIDE GEMINI aad2f69c55be USB: serial: option: add Foxconn T99W640 d5e3bcff9b43 USB: serial: option: add Telit Cinterion FE910C04 (ECM) composition 18d58a467ccf usb: gadget: u_serial: Fix race condition in TTY wakeup 749d9076735f usb: typec: displayport: Fix potential deadlock 0722035aef27 Logitech C-270 even more broken c93bc959788e usb: typec: altmodes/displayport: do not index invalid pin_assignments e0359c66c1be usb: typec: displayport: Receive DP Status Update NAK request exit dp altmode df6701168a28 usb: cdc-wdm: avoid setting WDM_READ for ZLP-s 13d8f52c88fa usb: Add checks for snprintf() calls in usb_alloc_dev() 0861b9cb2ff5 usb: potential integer overflow in usbg_make_tpg() Change-Id: I9ebeadf2e42fc9b870af3d93a65724819e9d41ae Signed-off-by: kamasali Satyanarayan --- drivers/usb/atm/cxacru.c | 172 ++++++++++++----------- drivers/usb/chipidea/ci.h | 18 +-- drivers/usb/chipidea/udc.c | 89 +++++------- drivers/usb/class/cdc-acm.c | 13 +- drivers/usb/class/cdc-wdm.c | 23 +-- drivers/usb/core/hub.c | 60 +------- drivers/usb/core/hub.h | 1 - drivers/usb/core/quirks.c | 8 +- drivers/usb/core/urb.c | 2 +- drivers/usb/core/usb.c | 14 +- drivers/usb/dwc3/dwc3-meson-g12a.c | 3 - drivers/usb/dwc3/dwc3-qcom.c | 8 +- drivers/usb/dwc3/gadget.c | 9 -- drivers/usb/early/xhci-dbc.c | 4 - drivers/usb/gadget/composite.c | 5 - drivers/usb/gadget/configfs.c | 4 - drivers/usb/gadget/function/f_fs.c | 8 +- drivers/usb/gadget/function/f_hid.c | 4 +- drivers/usb/gadget/function/f_ncm.c | 3 +- drivers/usb/gadget/function/f_tcm.c | 4 +- drivers/usb/gadget/function/u_serial.c | 6 +- drivers/usb/gadget/udc/dummy_hcd.c | 25 ++-- drivers/usb/gadget/udc/renesas_usb3.c | 1 - drivers/usb/host/max3421-hcd.c | 2 +- drivers/usb/host/xhci-dbgcap.c | 9 +- drivers/usb/host/xhci-hub.c | 3 +- drivers/usb/host/xhci-mem.c | 24 ++-- drivers/usb/host/xhci-plat.c | 4 +- drivers/usb/host/xhci-ring.c | 19 +-- drivers/usb/host/xhci.c | 24 +--- drivers/usb/host/xhci.h | 3 +- drivers/usb/mon/mon_bin.c | 14 +- drivers/usb/musb/musb_gadget.c | 2 - drivers/usb/musb/omap2430.c | 10 +- drivers/usb/phy/phy-mxs-usb.c | 4 +- drivers/usb/phy/phy-twl6030-usb.c | 3 +- drivers/usb/serial/ftdi_sio.c | 2 - drivers/usb/serial/ftdi_sio_ids.h | 3 - drivers/usb/serial/option.c | 40 ------ drivers/usb/storage/realtek_cr.c | 2 +- drivers/usb/storage/unusual_devs.h | 29 ---- drivers/usb/typec/altmodes/displayport.c | 5 +- drivers/usb/typec/tcpm/fusb302.c | 8 -- drivers/usb/usbip/vhci_hcd.c | 22 --- include/linux/usb/chipidea.h | 1 - include/linux/usb/typec_dp.h | 1 - 46 files changed, 231 insertions(+), 487 deletions(-) diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 58e5bc574e6a..a4d863f6cda7 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -984,6 +984,94 @@ cleanup: return ret; } +static void cxacru_upload_firmware(struct cxacru_data *instance, + const struct firmware *fw, + const struct firmware *bp) +{ + int ret; + struct usbatm_data *usbatm = instance->usbatm; + struct usb_device *usb_dev = usbatm->usb_dev; + __le16 signature[] = { usb_dev->descriptor.idVendor, + usb_dev->descriptor.idProduct }; + __le32 val; + + usb_dbg(usbatm, "%s\n", __func__); + + /* FirmwarePllFClkValue */ + val = cpu_to_le32(instance->modem_type->pll_f_clk); + ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLFCLK_ADDR, (u8 *) &val, 4); + if (ret) { + usb_err(usbatm, "FirmwarePllFClkValue failed: %d\n", ret); + return; + } + + /* FirmwarePllBClkValue */ + val = cpu_to_le32(instance->modem_type->pll_b_clk); + ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLBCLK_ADDR, (u8 *) &val, 4); + if (ret) { + usb_err(usbatm, "FirmwarePllBClkValue failed: %d\n", ret); + return; + } + + /* Enable SDRAM */ + val = cpu_to_le32(SDRAM_ENA); + ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SDRAMEN_ADDR, (u8 *) &val, 4); + if (ret) { + usb_err(usbatm, "Enable SDRAM failed: %d\n", ret); + return; + } + + /* Firmware */ + usb_info(usbatm, "loading firmware\n"); + ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, FW_ADDR, fw->data, fw->size); + if (ret) { + usb_err(usbatm, "Firmware upload failed: %d\n", ret); + return; + } + + /* Boot ROM patch */ + if (instance->modem_type->boot_rom_patch) { + usb_info(usbatm, "loading boot ROM patch\n"); + ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_ADDR, bp->data, bp->size); + if (ret) { + usb_err(usbatm, "Boot ROM patching failed: %d\n", ret); + return; + } + } + + /* Signature */ + ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SIG_ADDR, (u8 *) signature, 4); + if (ret) { + usb_err(usbatm, "Signature storing failed: %d\n", ret); + return; + } + + usb_info(usbatm, "starting device\n"); + if (instance->modem_type->boot_rom_patch) { + val = cpu_to_le32(BR_ADDR); + ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_STACK_ADDR, (u8 *) &val, 4); + } else { + ret = cxacru_fw(usb_dev, FW_GOTO_MEM, 0x0, 0x0, FW_ADDR, NULL, 0); + } + if (ret) { + usb_err(usbatm, "Passing control to firmware failed: %d\n", ret); + return; + } + + /* Delay to allow firmware to start up. */ + msleep_interruptible(1000); + + usb_clear_halt(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_CMD)); + usb_clear_halt(usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_CMD)); + usb_clear_halt(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_DATA)); + usb_clear_halt(usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_DATA)); + + ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0); + if (ret < 0) { + usb_err(usbatm, "modem failed to initialize: %d\n", ret); + return; + } +} static int cxacru_find_firmware(struct cxacru_data *instance, char *phase, const struct firmware **fw_p) @@ -1010,14 +1098,8 @@ static int cxacru_heavy_init(struct usbatm_data *usbatm_instance, { const struct firmware *fw, *bp; struct cxacru_data *instance = usbatm_instance->driver_data; - struct usbatm_data *usbatm = instance->usbatm; - struct usb_device *usb_dev = usbatm->usb_dev; - __le16 signature[] = { usb_dev->descriptor.idVendor, - usb_dev->descriptor.idProduct }; - __le32 val; - int ret; + int ret = cxacru_find_firmware(instance, "fw", &fw); - ret = cxacru_find_firmware(instance, "fw", &fw); if (ret) { usb_warn(usbatm_instance, "firmware (cxacru-fw.bin) unavailable (system misconfigured?)\n"); return ret; @@ -1032,82 +1114,8 @@ static int cxacru_heavy_init(struct usbatm_data *usbatm_instance, } } - /* FirmwarePllFClkValue */ - val = cpu_to_le32(instance->modem_type->pll_f_clk); - ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLFCLK_ADDR, (u8 *) &val, 4); - if (ret) { - usb_err(usbatm, "FirmwarePllFClkValue failed: %d\n", ret); - goto done; - } + cxacru_upload_firmware(instance, fw, bp); - /* FirmwarePllBClkValue */ - val = cpu_to_le32(instance->modem_type->pll_b_clk); - ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLBCLK_ADDR, (u8 *) &val, 4); - if (ret) { - usb_err(usbatm, "FirmwarePllBClkValue failed: %d\n", ret); - goto done; - } - - /* Enable SDRAM */ - val = cpu_to_le32(SDRAM_ENA); - ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SDRAMEN_ADDR, (u8 *) &val, 4); - if (ret) { - usb_err(usbatm, "Enable SDRAM failed: %d\n", ret); - goto done; - } - - /* Firmware */ - usb_info(usbatm, "loading firmware\n"); - ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, FW_ADDR, fw->data, fw->size); - if (ret) { - usb_err(usbatm, "Firmware upload failed: %d\n", ret); - goto done; - } - - /* Boot ROM patch */ - if (instance->modem_type->boot_rom_patch) { - usb_info(usbatm, "loading boot ROM patch\n"); - ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_ADDR, bp->data, bp->size); - if (ret) { - usb_err(usbatm, "Boot ROM patching failed: %d\n", ret); - goto done; - } - } - - /* Signature */ - ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SIG_ADDR, (u8 *) signature, 4); - if (ret) { - usb_err(usbatm, "Signature storing failed: %d\n", ret); - goto done; - } - - usb_info(usbatm, "starting device\n"); - if (instance->modem_type->boot_rom_patch) { - val = cpu_to_le32(BR_ADDR); - ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_STACK_ADDR, (u8 *) &val, 4); - } else { - ret = cxacru_fw(usb_dev, FW_GOTO_MEM, 0x0, 0x0, FW_ADDR, NULL, 0); - } - if (ret) { - usb_err(usbatm, "Passing control to firmware failed: %d\n", ret); - goto done; - } - - /* Delay to allow firmware to start up. */ - msleep_interruptible(1000); - - usb_clear_halt(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_CMD)); - usb_clear_halt(usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_CMD)); - usb_clear_halt(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_DATA)); - usb_clear_halt(usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_DATA)); - - ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0); - if (ret < 0) { - usb_err(usbatm, "modem failed to initialize: %d\n", ret); - goto done; - } - -done: if (instance->modem_type->boot_rom_patch) release_firmware(bp); release_firmware(fw); diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h index 3a22bc727bb9..ff61f88fc867 100644 --- a/drivers/usb/chipidea/ci.h +++ b/drivers/usb/chipidea/ci.h @@ -277,19 +277,8 @@ static inline int ci_role_start(struct ci_hdrc *ci, enum ci_role role) return -ENXIO; ret = ci->roles[role]->start(ci); - if (ret) - return ret; - - ci->role = role; - - if (ci->usb_phy) { - if (role == CI_ROLE_HOST) - usb_phy_set_event(ci->usb_phy, USB_EVENT_ID); - else - /* in device mode but vbus is invalid*/ - usb_phy_set_event(ci->usb_phy, USB_EVENT_NONE); - } - + if (!ret) + ci->role = role; return ret; } @@ -303,9 +292,6 @@ static inline void ci_role_stop(struct ci_hdrc *ci) ci->role = CI_ROLE_END; ci->roles[role]->stop(ci); - - if (ci->usb_phy) - usb_phy_set_event(ci->usb_phy, USB_EVENT_NONE); } static inline enum usb_role ci_role_to_usb_role(struct ci_hdrc *ci) diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index d483a957804b..a6ce6b89b271 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1533,68 +1533,44 @@ static const struct usb_ep_ops usb_ep_ops = { /****************************************************************************** * GADGET block *****************************************************************************/ -/** - * ci_hdrc_gadget_connect: caller makes sure gadget driver is binded - */ -static void ci_hdrc_gadget_connect(struct usb_gadget *_gadget, int is_active) -{ - struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget); - - if (is_active) { - pm_runtime_get_sync(&_gadget->dev); - hw_device_reset(ci); - spin_lock_irq(&ci->lock); - if (ci->driver) { - hw_device_state(ci, ci->ep0out->qh.dma); - usb_gadget_set_state(_gadget, USB_STATE_POWERED); - spin_unlock_irq(&ci->lock); - usb_udc_vbus_handler(_gadget, true); - } else { - spin_unlock_irq(&ci->lock); - } - } else { - usb_udc_vbus_handler(_gadget, false); - if (ci->driver) - ci->driver->disconnect(&ci->gadget); - hw_device_state(ci, 0); - if (ci->platdata->notify_event) - ci->platdata->notify_event(ci, - CI_HDRC_CONTROLLER_STOPPED_EVENT); - _gadget_stop_activity(&ci->gadget); - pm_runtime_put_sync(&_gadget->dev); - usb_gadget_set_state(_gadget, USB_STATE_NOTATTACHED); - } -} - static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active) { struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget); unsigned long flags; - int ret = 0; + int gadget_ready = 0; spin_lock_irqsave(&ci->lock, flags); ci->vbus_active = is_active; + if (ci->driver) + gadget_ready = 1; spin_unlock_irqrestore(&ci->lock, flags); if (ci->usb_phy) usb_phy_set_charger_state(ci->usb_phy, is_active ? USB_CHARGER_PRESENT : USB_CHARGER_ABSENT); - if (ci->platdata->notify_event) - ret = ci->platdata->notify_event(ci, - CI_HDRC_CONTROLLER_VBUS_EVENT); - - if (ci->usb_phy) { - if (is_active) - usb_phy_set_event(ci->usb_phy, USB_EVENT_VBUS); - else - usb_phy_set_event(ci->usb_phy, USB_EVENT_NONE); + if (gadget_ready) { + if (is_active) { + pm_runtime_get_sync(&_gadget->dev); + hw_device_reset(ci); + hw_device_state(ci, ci->ep0out->qh.dma); + usb_gadget_set_state(_gadget, USB_STATE_POWERED); + usb_udc_vbus_handler(_gadget, true); + } else { + usb_udc_vbus_handler(_gadget, false); + if (ci->driver) + ci->driver->disconnect(&ci->gadget); + hw_device_state(ci, 0); + if (ci->platdata->notify_event) + ci->platdata->notify_event(ci, + CI_HDRC_CONTROLLER_STOPPED_EVENT); + _gadget_stop_activity(&ci->gadget); + pm_runtime_put_sync(&_gadget->dev); + usb_gadget_set_state(_gadget, USB_STATE_NOTATTACHED); + } } - if (ci->driver) - ci_hdrc_gadget_connect(_gadget, is_active); - - return ret; + return 0; } static int ci_udc_wakeup(struct usb_gadget *_gadget) @@ -1818,10 +1794,18 @@ static int ci_udc_start(struct usb_gadget *gadget, return retval; } - if (ci->vbus_active) - ci_hdrc_gadget_connect(gadget, 1); - else + pm_runtime_get_sync(&ci->gadget.dev); + if (ci->vbus_active) { + hw_device_reset(ci); + } else { usb_udc_vbus_handler(&ci->gadget, false); + pm_runtime_put_sync(&ci->gadget.dev); + return retval; + } + + retval = hw_device_state(ci, ci->ep0out->qh.dma); + if (retval) + pm_runtime_put_sync(&ci->gadget.dev); return retval; } @@ -1851,7 +1835,6 @@ static int ci_udc_stop(struct usb_gadget *gadget) unsigned long flags; spin_lock_irqsave(&ci->lock, flags); - ci->driver = NULL; if (ci->vbus_active) { hw_device_state(ci, 0); @@ -1864,6 +1847,7 @@ static int ci_udc_stop(struct usb_gadget *gadget) pm_runtime_put(&ci->gadget.dev); } + ci->driver = NULL; spin_unlock_irqrestore(&ci->lock, flags); ci_udc_stop_for_otg_fsm(ci); @@ -1906,9 +1890,6 @@ static irqreturn_t udc_irq(struct ci_hdrc *ci) if (USBi_PCI & intr) { ci->gadget.speed = hw_port_is_high_speed(ci) ? USB_SPEED_HIGH : USB_SPEED_FULL; - if (ci->usb_phy) - usb_phy_set_event(ci->usb_phy, - USB_EVENT_ENUMERATED); if (ci->suspended) { if (ci->driver->resume) { spin_unlock(&ci->lock); diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 4730089a771b..59a354822413 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1520,6 +1520,8 @@ skip_countries: acm->nb_index = 0; acm->nb_size = 0; + dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor); + acm->line.dwDTERate = cpu_to_le32(9600); acm->line.bDataBits = 8; acm_set_line(acm, &acm->line); @@ -1527,12 +1529,6 @@ skip_countries: usb_driver_claim_interface(&acm_driver, data_interface, acm); usb_set_intfdata(data_interface, acm); - if (quirks & CLEAR_HALT_CONDITIONS) { - /* errors intentionally ignored */ - usb_clear_halt(usb_dev, acm->in); - usb_clear_halt(usb_dev, acm->out); - } - tty_dev = tty_port_register_device(&acm->port, acm_tty_driver, minor, &control_interface->dev); if (IS_ERR(tty_dev)) { @@ -1540,7 +1536,10 @@ skip_countries: goto alloc_fail6; } - dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor); + if (quirks & CLEAR_HALT_CONDITIONS) { + usb_clear_halt(usb_dev, acm->in); + usb_clear_halt(usb_dev, acm->out); + } return 0; alloc_fail6: diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 6afb941dd267..bc925394e881 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -89,6 +89,7 @@ struct wdm_device { u16 wMaxCommand; u16 wMaxPacketSize; __le16 inum; + int reslength; int length; int read; int count; @@ -200,11 +201,6 @@ static void wdm_in_callback(struct urb *urb) if (desc->rerr == 0 && status != -EPIPE) desc->rerr = status; - if (length == 0) { - dev_dbg(&desc->intf->dev, "received ZLP\n"); - goto skip_zlp; - } - if (length + desc->length > desc->wMaxCommand) { /* The buffer would overflow */ set_bit(WDM_OVERFLOW, &desc->flags); @@ -213,18 +209,18 @@ static void wdm_in_callback(struct urb *urb) if (!test_bit(WDM_OVERFLOW, &desc->flags)) { memmove(desc->ubuf + desc->length, desc->inbuf, length); desc->length += length; + desc->reslength = length; } } skip_error: if (desc->rerr) { /* - * If there was a ZLP or an error, userspace may decide to not - * read any data after poll'ing. + * Since there was an error, userspace may decide to not read + * any data after poll'ing. * We should respond to further attempts from the device to send * data, so that we can get unstuck. */ -skip_zlp: schedule_work(&desc->service_outs_intr); } else { set_bit(WDM_READ, &desc->flags); @@ -575,6 +571,15 @@ retry: goto retry; } + if (!desc->reslength) { /* zero length read */ + dev_dbg(&desc->intf->dev, "zero length - clearing WDM_READ\n"); + clear_bit(WDM_READ, &desc->flags); + rv = service_outstanding_interrupt(desc); + spin_unlock_irq(&desc->iuspin); + if (rv < 0) + goto err; + goto retry; + } cntr = desc->length; spin_unlock_irq(&desc->iuspin); } @@ -834,7 +839,7 @@ static void service_interrupt_work(struct work_struct *work) spin_lock_irq(&desc->iuspin); service_outstanding_interrupt(desc); - if (!desc->resp_count && (desc->length || desc->rerr)) { + if (!desc->resp_count) { set_bit(WDM_READ, &desc->flags); wake_up(&desc->wait); } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 1b477936fa17..44e7c2c39320 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -52,12 +52,6 @@ #define USB_TP_TRANSMISSION_DELAY_MAX 65535 /* ns */ #define USB_PING_RESPONSE_TIME 400 /* ns */ -/* - * Give SS hubs 200ms time after wake to train downstream links before - * assuming no port activity and allowing hub to runtime suspend back. - */ -#define USB_SS_PORT_U0_WAKE_TIME 200 /* ms */ - /* Protect struct usb_device->state and ->children members * Note: Both are also protected by ->dev.sem, except that ->state can * change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */ @@ -1058,7 +1052,6 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) goto init2; goto init3; } - kref_get(&hub->kref); /* The superspeed hub except for root hub has to use Hub Depth @@ -1307,17 +1300,6 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) device_unlock(&hdev->dev); } - if (type == HUB_RESUME && hub_is_superspeed(hub->hdev)) { - /* give usb3 downstream links training time after hub resume */ - usb_autopm_get_interface_no_resume( - to_usb_interface(hub->intfdev)); - - queue_delayed_work(system_power_efficient_wq, - &hub->post_resume_work, - msecs_to_jiffies(USB_SS_PORT_U0_WAKE_TIME)); - return; - } - kref_put(&hub->kref, hub_release); } @@ -1336,14 +1318,6 @@ static void hub_init_func3(struct work_struct *ws) hub_activate(hub, HUB_INIT3); } -static void hub_post_resume(struct work_struct *ws) -{ - struct usb_hub *hub = container_of(ws, struct usb_hub, post_resume_work.work); - - usb_autopm_put_interface_async(to_usb_interface(hub->intfdev)); - kref_put(&hub->kref, hub_release); -} - enum hub_quiescing_type { HUB_DISCONNECT, HUB_PRE_RESET, HUB_SUSPEND }; @@ -1369,7 +1343,6 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type) /* Stop hub_wq and related activity */ del_timer_sync(&hub->irq_urb_retry); - flush_delayed_work(&hub->post_resume_work); usb_kill_urb(hub->urb); if (hub->has_indicators) cancel_delayed_work_sync(&hub->leds); @@ -1916,7 +1889,6 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) hub->hdev = hdev; INIT_DELAYED_WORK(&hub->leds, led_work); INIT_DELAYED_WORK(&hub->init_work, NULL); - INIT_DELAYED_WORK(&hub->post_resume_work, hub_post_resume); INIT_WORK(&hub->events, hub_event); spin_lock_init(&hub->irq_urb_lock); timer_setup(&hub->irq_urb_retry, hub_retry_irq_urb, 0); @@ -2784,8 +2756,6 @@ static unsigned hub_is_wusb(struct usb_hub *hub) #define SET_CONFIG_TRIES (2 * (use_both_schemes + 1)) #define USE_NEW_SCHEME(i, scheme) ((i) / 2 == (int)(scheme)) -#define DETECT_DISCONNECT_TRIES 5 - #define HUB_ROOT_RESET_TIME 60 /* times are in msec */ #define HUB_SHORT_RESET_TIME 10 #define HUB_BH_RESET_TIME 50 @@ -5420,8 +5390,6 @@ static void port_event(struct usb_hub *hub, int port1) struct usb_device *udev = port_dev->child; struct usb_device *hdev = hub->hdev; u16 portstatus, portchange; - int i = 0; - int err; connect_change = test_bit(port1, hub->change_bits); clear_bit(port1, hub->event_bits); @@ -5498,30 +5466,17 @@ static void port_event(struct usb_hub *hub, int port1) connect_change = 1; /* - * Avoid trying to recover a USB3 SS.Inactive port with a warm reset if - * the device was disconnected. A 12ms disconnect detect timer in - * SS.Inactive state transitions the port to RxDetect automatically. - * SS.Inactive link error state is common during device disconnect. + * Warm reset a USB3 protocol port if it's in + * SS.Inactive state. */ - while (hub_port_warm_reset_required(hub, port1, portstatus)) { - if ((i++ < DETECT_DISCONNECT_TRIES) && udev) { - u16 unused; - - msleep(20); - hub_port_status(hub, port1, &portstatus, &unused); - dev_dbg(&port_dev->dev, "Wait for inactive link disconnect detect\n"); - continue; - } else if (!udev || !(portstatus & USB_PORT_STAT_CONNECTION) + if (hub_port_warm_reset_required(hub, port1, portstatus)) { + dev_dbg(&port_dev->dev, "do warm reset\n"); + if (!udev || !(portstatus & USB_PORT_STAT_CONNECTION) || udev->state == USB_STATE_NOTATTACHED) { - dev_dbg(&port_dev->dev, "do warm reset, port only\n"); - err = hub_port_reset(hub, port1, NULL, - HUB_BH_RESET_TIME, true); - if (!udev && err == -ENOTCONN) - connect_change = 0; - else if (err < 0) + if (hub_port_reset(hub, port1, NULL, + HUB_BH_RESET_TIME, true) < 0) hub_port_disable(hub, port1, 1); } else { - dev_dbg(&port_dev->dev, "do warm reset, full device\n"); usb_unlock_port(port_dev); usb_lock_device(udev); usb_reset_device(udev); @@ -5529,7 +5484,6 @@ static void port_event(struct usb_hub *hub, int port1) usb_lock_port(port_dev); connect_change = 0; } - break; } if (connect_change) diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index de29ce856953..1c455800f7d3 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h @@ -69,7 +69,6 @@ struct usb_hub { u8 indicator[USB_MAXCHILDREN]; struct delayed_work leds; struct delayed_work init_work; - struct delayed_work post_resume_work; struct work_struct events; spinlock_t irq_urb_lock; struct timer_list irq_urb_retry; diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index aa6c9a6810b9..98b1c457a091 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -224,8 +224,7 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x046a, 0x0023), .driver_info = USB_QUIRK_RESET_RESUME }, /* Logitech HD Webcam C270 */ - { USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME | - USB_QUIRK_NO_LPM}, + { USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME }, /* Logitech HD Pro Webcams C920, C920-C, C922, C925e and C930e */ { USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT }, @@ -368,7 +367,6 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x0781, 0x5591), .driver_info = USB_QUIRK_NO_LPM }, /* SanDisk Corp. SanDisk 3.2Gen1 */ - { USB_DEVICE(0x0781, 0x5596), .driver_info = USB_QUIRK_DELAY_INIT }, { USB_DEVICE(0x0781, 0x55a3), .driver_info = USB_QUIRK_DELAY_INIT }, /* SanDisk Extreme 55AE */ @@ -462,8 +460,6 @@ static const struct usb_device_id usb_quirk_list[] = { /* Huawei 4G LTE module */ { USB_DEVICE(0x12d1, 0x15bb), .driver_info = USB_QUIRK_DISCONNECT_SUSPEND }, - { USB_DEVICE(0x12d1, 0x15c1), .driver_info = - USB_QUIRK_DISCONNECT_SUSPEND }, { USB_DEVICE(0x12d1, 0x15c3), .driver_info = USB_QUIRK_DISCONNECT_SUSPEND }, @@ -730,7 +726,7 @@ void usb_detect_quirks(struct usb_device *udev) udev->quirks ^= usb_detect_dynamic_quirks(udev); if (udev->quirks) - dev_dbg(&udev->dev, "USB quirks for this device: 0x%x\n", + dev_dbg(&udev->dev, "USB quirks for this device: %x\n", udev->quirks); #ifdef CONFIG_USB_DEFAULT_PERSIST diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index e60f4ef06e3d..850d0fffe1c6 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -490,7 +490,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) /* Check that the pipe's type matches the endpoint's type */ if (usb_pipe_type_check(urb->dev, urb->pipe)) - dev_warn_once(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n", + dev_WARN(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n", usb_pipetype(urb->pipe), pipetypes[xfertype]); /* Check against a simple/standard policy */ diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 571ab8e0c759..502d911f71fa 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -717,16 +717,15 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, dev_set_name(&dev->dev, "usb%d", bus->busnum); root_hub = 1; } else { - int n; - /* match any labeling on the hubs; it's one-based */ if (parent->devpath[0] == '0') { - n = snprintf(dev->devpath, sizeof(dev->devpath), "%d", port1); + snprintf(dev->devpath, sizeof dev->devpath, + "%d", port1); /* Root ports are not counted in route string */ dev->route = 0; } else { - n = snprintf(dev->devpath, sizeof(dev->devpath), "%s.%d", - parent->devpath, port1); + snprintf(dev->devpath, sizeof dev->devpath, + "%s.%d", parent->devpath, port1); /* Route string assumes hubs have less than 16 ports */ if (port1 < 15) dev->route = parent->route + @@ -735,11 +734,6 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, dev->route = parent->route + (15 << ((parent->level - 1)*4)); } - if (n >= sizeof(dev->devpath)) { - usb_put_hcd(bus_to_hcd(bus)); - usb_put_dev(dev); - return NULL; - } dev->dev.parent = &parent->dev; dev_set_name(&dev->dev, "%d-%s", bus->busnum, dev->devpath); diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c b/drivers/usb/dwc3/dwc3-meson-g12a.c index 9bb1edb81d6e..8a3ec1a951fe 100644 --- a/drivers/usb/dwc3/dwc3-meson-g12a.c +++ b/drivers/usb/dwc3/dwc3-meson-g12a.c @@ -529,9 +529,6 @@ static int dwc3_meson_g12a_remove(struct platform_device *pdev) usb_role_switch_unregister(priv->role_switch); - put_device(priv->switch_desc.udc); - put_device(priv->switch_desc.usb2_port); - of_platform_depopulate(dev); for (i = 0 ; i < PHY_COUNT ; ++i) { diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index 8be05c7fc98b..742be1e07a01 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -615,13 +615,13 @@ static int dwc3_qcom_probe(struct platform_device *pdev) ret = reset_control_deassert(qcom->resets); if (ret) { dev_err(&pdev->dev, "failed to deassert resets, err=%d\n", ret); - return ret; + goto reset_assert; } ret = dwc3_qcom_clk_init(qcom, of_clk_get_parent_count(np)); if (ret) { dev_err(dev, "failed to get clocks\n"); - return ret; + goto reset_assert; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -700,6 +700,8 @@ clk_disable: clk_disable_unprepare(qcom->clks[i]); clk_put(qcom->clks[i]); } +reset_assert: + reset_control_assert(qcom->resets); return ret; } @@ -723,6 +725,8 @@ static int dwc3_qcom_remove(struct platform_device *pdev) } qcom->num_clocks = 0; + reset_control_assert(qcom->resets); + pm_runtime_allow(dev); pm_runtime_disable(dev); diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 73608332d78d..76316205483b 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2937,15 +2937,6 @@ static void dwc3_gadget_endpoint_transfer_in_progress(struct dwc3_ep *dep, static void dwc3_gadget_endpoint_transfer_not_ready(struct dwc3_ep *dep, const struct dwc3_event_depevt *event) { - /* - * During a device-initiated disconnect, a late xferNotReady event can - * be generated after the End Transfer command resets the event filter, - * but before the controller is halted. Ignore it to prevent a new - * transfer from starting. - */ - if (!dep->dwc->connected) - return; - dwc3_gadget_endpoint_frame_from_event(dep, event); (void) __dwc3_gadget_start_isoc(dep); } diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c index 7673ded077a4..5a462a1d1896 100644 --- a/drivers/usb/early/xhci-dbc.c +++ b/drivers/usb/early/xhci-dbc.c @@ -678,10 +678,6 @@ int __init early_xdbc_setup_hardware(void) xdbc.table_base = NULL; xdbc.out_buf = NULL; - - early_iounmap(xdbc.xhci_base, xdbc.xhci_length); - xdbc.xhci_base = NULL; - xdbc.xhci_length = 0; } return ret; diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 55597a898f40..4b2e9df97b11 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -2241,11 +2241,6 @@ int composite_os_desc_req_prepare(struct usb_composite_dev *cdev, if (!cdev->os_desc_req->buf) { ret = -ENOMEM; usb_ep_free_request(ep0, cdev->os_desc_req); - /* - * Set os_desc_req to NULL so that composite_dev_cleanup() - * will not try to free it again. - */ - cdev->os_desc_req = NULL; goto end; } cdev->os_desc_req->context = cdev; diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index e3f200f05a4e..cfae163e6502 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -888,8 +888,6 @@ static ssize_t os_desc_qw_sign_store(struct config_item *item, const char *page, struct gadget_info *gi = os_desc_item_to_gadget_info(item); int res, l; - if (!len) - return len; l = min((int)len, OS_STRING_QW_SIGN_LEN >> 1); if (page[l - 1] == '\n') --l; @@ -1391,8 +1389,6 @@ static int configfs_composite_bind(struct usb_gadget *gadget, cdev->use_os_string = true; cdev->b_vendor_code = gi->b_vendor_code; memcpy(cdev->qw_sign, gi->qw_sign, OS_STRING_QW_SIGN_LEN); - } else { - cdev->use_os_string = false; } if (gadget_is_otg(gadget) && !otg_desc[0]) { diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index e0a35dc19e45..9b5f9d503ff0 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -2012,12 +2012,7 @@ static int ffs_func_eps_enable(struct ffs_function *func) ep = func->eps; epfile = ffs->epfiles; count = ffs->eps_count; - if (!epfile) { - ret = -ENOMEM; - goto done; - } - - while (count--) { + while(count--) { ep->ep->driver_data = ep; ret = config_ep_by_speed(func->gadget, &func->function, ep->ep); @@ -2041,7 +2036,6 @@ static int ffs_func_eps_enable(struct ffs_function *func) } wake_up_interruptible(&ffs->wait); -done: spin_unlock_irqrestore(&func->ffs->eps_lock, flags); return ret; diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c index cea9157ea2b4..77354626252c 100644 --- a/drivers/usb/gadget/function/f_hid.c +++ b/drivers/usb/gadget/function/f_hid.c @@ -496,7 +496,7 @@ try_again: } req->status = 0; - req->zero = 1; + req->zero = 0; req->length = count; req->complete = f_hidg_req_complete; req->context = hidg; @@ -767,7 +767,7 @@ stall: return -EOPNOTSUPP; respond: - req->zero = 1; + req->zero = 0; req->length = length; status = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); if (status < 0) diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c index b1e569337382..ca50257b9538 100644 --- a/drivers/usb/gadget/function/f_ncm.c +++ b/drivers/usb/gadget/function/f_ncm.c @@ -1472,8 +1472,6 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f) ncm_opts->bound = true; - ncm_string_defs[1].s = ncm->ethaddr; - us = usb_gstrings_attach(cdev, ncm_strings, ARRAY_SIZE(ncm_string_defs)); if (IS_ERR(us)) { @@ -1737,6 +1735,7 @@ static struct usb_function *ncm_alloc(struct usb_function_instance *fi) mutex_unlock(&opts->lock); return ERR_PTR(-EINVAL); } + ncm_string_defs[STRING_MAC_IDX].s = ncm->ethaddr; spin_lock_init(&ncm->lock); ncm_reset_values(ncm); diff --git a/drivers/usb/gadget/function/f_tcm.c b/drivers/usb/gadget/function/f_tcm.c index 48d02c5ff849..90fe33f9e095 100644 --- a/drivers/usb/gadget/function/f_tcm.c +++ b/drivers/usb/gadget/function/f_tcm.c @@ -1320,14 +1320,14 @@ static struct se_portal_group *usbg_make_tpg(struct se_wwn *wwn, struct usbg_tport *tport = container_of(wwn, struct usbg_tport, tport_wwn); struct usbg_tpg *tpg; - u16 tpgt; + unsigned long tpgt; int ret; struct f_tcm_opts *opts; unsigned i; if (strstr(name, "tpgt_") != name) return ERR_PTR(-EINVAL); - if (kstrtou16(name + 5, 0, &tpgt)) + if (kstrtoul(name + 5, 0, &tpgt) || tpgt > UINT_MAX) return ERR_PTR(-EINVAL); ret = -ENODEV; mutex_lock(&tpg_instances_lock); diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c index fc67797a0095..d432f96ec419 100644 --- a/drivers/usb/gadget/function/u_serial.c +++ b/drivers/usb/gadget/function/u_serial.c @@ -286,8 +286,8 @@ __acquires(&port->port_lock) break; } - if (do_tty_wake) - tty_port_tty_wakeup(&port->port); + if (do_tty_wake && port->port.tty) + tty_wakeup(port->port.tty); return status; } @@ -564,7 +564,7 @@ static int gs_start_io(struct gs_port *port) gs_start_tx(port); /* Unblock any pending writes into our circular buffer, in case * we didn't in gs_start_tx() */ - tty_port_tty_wakeup(&port->port); + tty_wakeup(port->port.tty); } else { /* Free reqs only if we are still connected */ if (port->port_usb) { diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c index 55f40902bfd4..730f15fd92c2 100644 --- a/drivers/usb/gadget/udc/dummy_hcd.c +++ b/drivers/usb/gadget/udc/dummy_hcd.c @@ -748,7 +748,7 @@ static int dummy_dequeue(struct usb_ep *_ep, struct usb_request *_req) struct dummy *dum; int retval = -EINVAL; unsigned long flags; - struct dummy_request *req = NULL, *iter; + struct dummy_request *req = NULL; if (!_ep || !_req) return retval; @@ -758,26 +758,25 @@ static int dummy_dequeue(struct usb_ep *_ep, struct usb_request *_req) if (!dum->driver) return -ESHUTDOWN; - spin_lock_irqsave(&dum->lock, flags); - list_for_each_entry(iter, &ep->queue, queue) { - if (&iter->req != _req) - continue; - list_del_init(&iter->queue); - _req->status = -ECONNRESET; - req = iter; - retval = 0; - break; + local_irq_save(flags); + spin_lock(&dum->lock); + list_for_each_entry(req, &ep->queue, queue) { + if (&req->req == _req) { + list_del_init(&req->queue); + _req->status = -ECONNRESET; + retval = 0; + break; + } } + spin_unlock(&dum->lock); if (retval == 0) { dev_dbg(udc_dev(dum), "dequeued req %p from %s, len %d buf %p\n", req, _ep->name, _req->length, _req->buf); - spin_unlock(&dum->lock); usb_gadget_giveback_request(_ep, _req); - spin_lock(&dum->lock); } - spin_unlock_irqrestore(&dum->lock, flags); + local_irq_restore(flags); return retval; } diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index 90114c09a711..2952e5feb2ee 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c @@ -2551,7 +2551,6 @@ static int renesas_usb3_remove(struct platform_device *pdev) struct renesas_usb3 *usb3 = platform_get_drvdata(pdev); debugfs_remove_recursive(usb3->dentry); - put_device(usb3->host_dev); device_remove_file(&pdev->dev, &dev_attr_role); cancel_work_sync(&usb3->role_work); diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c index cfdbe90f867e..5a21777197e9 100644 --- a/drivers/usb/host/max3421-hcd.c +++ b/drivers/usb/host/max3421-hcd.c @@ -1925,7 +1925,7 @@ error: if (hcd) { kfree(max3421_hcd->tx); kfree(max3421_hcd->rx); - if (!IS_ERR_OR_NULL(max3421_hcd->spi_thread)) + if (max3421_hcd->spi_thread) kthread_stop(max3421_hcd->spi_thread); usb_put_hcd(hcd); } diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c index 4e65ebbaa09b..93e2cca5262d 100644 --- a/drivers/usb/host/xhci-dbgcap.c +++ b/drivers/usb/host/xhci-dbgcap.c @@ -975,15 +975,8 @@ int xhci_dbc_suspend(struct xhci_hcd *xhci) if (!dbc) return 0; - switch (dbc->state) { - case DS_ENABLED: - case DS_CONNECTED: - case DS_CONFIGURED: + if (dbc->state == DS_CONFIGURED) dbc->resume_required = 1; - break; - default: - break; - } xhci_dbc_stop(xhci); diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 2c9015f2a7d3..66cb9f08bff1 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -628,7 +628,8 @@ static int xhci_enter_test_mode(struct xhci_hcd *xhci, if (!xhci->devs[i]) continue; - retval = xhci_disable_and_free_slot(xhci, i); + retval = xhci_disable_slot(xhci, i); + xhci_free_virt_device(xhci, i); if (retval) xhci_err(xhci, "Failed to disable slot %d, %d. Enter test mode anyway\n", i, retval); diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 4f4c4cae99c4..b3ee977fab99 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -879,20 +879,21 @@ free_tts: * will be manipulated by the configure endpoint, allocate device, or update * hub functions while this function is removing the TT entries from the list. */ -void xhci_free_virt_device(struct xhci_hcd *xhci, struct xhci_virt_device *dev, - int slot_id) +void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id) { + struct xhci_virt_device *dev; int i; int old_active_eps = 0; /* Slot ID 0 is reserved */ - if (slot_id == 0 || !dev) + if (slot_id == 0 || !xhci->devs[slot_id]) return; - /* If device ctx array still points to _this_ device, clear it */ - if (dev->out_ctx && - xhci->dcbaa->dev_context_ptrs[slot_id] == cpu_to_le64(dev->out_ctx->dma)) - xhci->dcbaa->dev_context_ptrs[slot_id] = 0; + dev = xhci->devs[slot_id]; + + xhci->dcbaa->dev_context_ptrs[slot_id] = 0; + if (!dev) + return; trace_xhci_free_virt_device(dev); @@ -931,9 +932,8 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, struct xhci_virt_device *dev, if (dev->udev && dev->udev->slot_id) dev->udev->slot_id = 0; - if (xhci->devs[slot_id] == dev) - xhci->devs[slot_id] = NULL; - kfree(dev); + kfree(xhci->devs[slot_id]); + xhci->devs[slot_id] = NULL; } /* @@ -975,7 +975,7 @@ static void xhci_free_virt_devices_depth_first(struct xhci_hcd *xhci, int slot_i out: /* we are now at a leaf device */ xhci_debugfs_remove_slot(xhci, slot_id); - xhci_free_virt_device(xhci, vdev, slot_id); + xhci_free_virt_device(xhci, slot_id); } int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, @@ -1214,8 +1214,6 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud ep0_ctx->deq = cpu_to_le64(dev->eps[0].ring->first_seg->dma | dev->eps[0].ring->cycle_state); - ep0_ctx->tx_info = cpu_to_le32(EP_AVG_TRB_LENGTH(8)); - trace_xhci_setup_addressable_virt_device(dev); /* Steps 7 and 8 were done in xhci_alloc_virt_device() */ diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 85a39a4b85ce..fa320006b04d 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -222,7 +222,6 @@ static int xhci_plat_probe(struct platform_device *pdev) } pm_runtime_set_active(&pdev->dev); - pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_enable(&pdev->dev); pm_runtime_get_noresume(&pdev->dev); @@ -334,8 +333,7 @@ static int xhci_plat_probe(struct platform_device *pdev) if (ret) goto disable_usb_phy; - if (HCC_MAX_PSA(xhci->hcc_params) >= 4 && - !(xhci->quirks & XHCI_BROKEN_STREAMS)) + if (HCC_MAX_PSA(xhci->hcc_params) >= 4) xhci->shared_hcd->can_do_streams = 1; ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 845bbf3d7a7b..086c567ca7d0 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -971,15 +971,12 @@ static void xhci_kill_endpoint_urbs(struct xhci_hcd *xhci, */ void xhci_hc_died(struct xhci_hcd *xhci) { - bool notify; int i, j; if (xhci->xhc_state & XHCI_STATE_DYING) return; - notify = !(xhci->xhc_state & XHCI_STATE_REMOVING); - if (notify) - xhci_err(xhci, "xHCI host controller not responding, assume dead\n"); + xhci_err(xhci, "xHCI host controller not responding, assume dead\n"); xhci->xhc_state |= XHCI_STATE_DYING; xhci_cleanup_command_queue(xhci); @@ -993,7 +990,7 @@ void xhci_hc_died(struct xhci_hcd *xhci) } /* inform usb core hc died if PCI remove isn't already handling it */ - if (notify) + if (!(xhci->xhc_state & XHCI_STATE_REMOVING)) usb_hc_died(xhci_to_hcd(xhci)); } @@ -1256,8 +1253,7 @@ static void xhci_handle_cmd_enable_slot(struct xhci_hcd *xhci, int slot_id, command->slot_id = 0; } -static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id, - u32 cmd_comp_code) +static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id) { struct xhci_virt_device *virt_dev; struct xhci_slot_ctx *slot_ctx; @@ -1272,10 +1268,6 @@ static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id, if (xhci->quirks & XHCI_EP_LIMIT_QUIRK) /* Delete default control endpoint resources */ xhci_free_device_endpoint_resources(xhci, virt_dev, true); - if (cmd_comp_code == COMP_SUCCESS) { - xhci->dcbaa->dev_context_ptrs[slot_id] = 0; - xhci->devs[slot_id] = NULL; - } } static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id, @@ -1515,7 +1507,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, xhci_handle_cmd_enable_slot(xhci, slot_id, cmd, cmd_comp_code); break; case TRB_DISABLE_SLOT: - xhci_handle_cmd_disable_slot(xhci, slot_id, cmd_comp_code); + xhci_handle_cmd_disable_slot(xhci, slot_id); break; case TRB_CONFIG_EP: if (!cmd->completion) @@ -4082,8 +4074,7 @@ static int queue_command(struct xhci_hcd *xhci, struct xhci_command *cmd, if ((xhci->xhc_state & XHCI_STATE_DYING) || (xhci->xhc_state & XHCI_STATE_HALTED)) { - xhci_dbg(xhci, "xHCI dying or halted, can't queue_command. state: 0x%x\n", - xhci->xhc_state); + xhci_dbg(xhci, "xHCI dying or halted, can't queue_command\n"); return -ESHUTDOWN; } diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index ba0223d5f4a1..dfc406be0856 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -118,8 +118,7 @@ int xhci_halt(struct xhci_hcd *xhci) ret = xhci_handshake(&xhci->op_regs->status, STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC); if (ret) { - if (!(xhci->xhc_state & XHCI_STATE_DYING)) - xhci_warn(xhci, "Host halt failed, %d\n", ret); + xhci_warn(xhci, "Host halt failed, %d\n", ret); return ret; } xhci->xhc_state |= XHCI_STATE_HALTED; @@ -176,8 +175,7 @@ int xhci_reset(struct xhci_hcd *xhci, u64 timeout_us) state = readl(&xhci->op_regs->status); if (state == ~(u32)0) { - if (!(xhci->xhc_state & XHCI_STATE_DYING)) - xhci_warn(xhci, "Host not accessible, reset failed.\n"); + xhci_warn(xhci, "Host not accessible, reset failed.\n"); return -ENODEV; } @@ -3947,7 +3945,7 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) xhci_disable_slot(xhci, udev->slot_id); spin_lock_irqsave(&xhci->lock, flags); - xhci_free_virt_device(xhci, virt_dev, udev->slot_id); + xhci_free_virt_device(xhci, udev->slot_id); spin_unlock_irqrestore(&xhci->lock, flags); } @@ -3996,16 +3994,6 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id) return ret; } -int xhci_disable_and_free_slot(struct xhci_hcd *xhci, u32 slot_id) -{ - struct xhci_virt_device *vdev = xhci->devs[slot_id]; - int ret; - - ret = xhci_disable_slot(xhci, slot_id); - xhci_free_virt_device(xhci, vdev, slot_id); - return ret; -} - /* * Checks if we have enough host controller resources for the default control * endpoint. @@ -4111,7 +4099,8 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) return 1; disable_slot: - xhci_disable_and_free_slot(xhci, udev->slot_id); + xhci_disable_slot(xhci, udev->slot_id); + xhci_free_virt_device(xhci, udev->slot_id); return 0; } @@ -4240,7 +4229,8 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, dev_warn(&udev->dev, "Device not responding to setup %s.\n", act); mutex_unlock(&xhci->mutex); - ret = xhci_disable_and_free_slot(xhci, udev->slot_id); + ret = xhci_disable_slot(xhci, udev->slot_id); + xhci_free_virt_device(xhci, udev->slot_id); if (!ret) { if (xhci_alloc_dev(hcd, udev) == 1) xhci_setup_addressable_virt_dev(xhci, udev); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 1cb97df1e8b0..421bc7ad413e 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1992,7 +1992,7 @@ void xhci_dbg_trace(struct xhci_hcd *xhci, void (*trace)(struct va_format *), /* xHCI memory management */ void xhci_mem_cleanup(struct xhci_hcd *xhci); int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags); -void xhci_free_virt_device(struct xhci_hcd *xhci, struct xhci_virt_device *dev, int slot_id); +void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id); int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, struct usb_device *udev, gfp_t flags); int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udev); void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci, @@ -2082,7 +2082,6 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev); int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, struct usb_tt *tt, gfp_t mem_flags); int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id); -int xhci_disable_and_free_slot(struct xhci_hcd *xhci, u32 slot_id); int xhci_ext_cap_init(struct xhci_hcd *xhci); int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup); diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index 93998d328d9a..35483217b1f6 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c @@ -68,20 +68,18 @@ * The magic limit was calculated so that it allows the monitoring * application to pick data once in two ticks. This way, another application, * which presumably drives the bus, gets to hog CPU, yet we collect our data. - * - * Originally, for a 480 Mbit/s bus this required a buffer of about 1 MB. For - * modern 20 Gbps buses, this value increases to over 50 MB. The maximum - * buffer size is set to 64 MiB to accommodate this. + * If HZ is 100, a 480 mbit/s bus drives 614 KB every jiffy. USB has an + * enormous overhead built into the bus protocol, so we need about 1000 KB. * * This is still too much for most cases, where we just snoop a few * descriptor fetches for enumeration. So, the default is a "reasonable" - * amount for typical, low-throughput use cases. + * amount for systems with HZ=250 and incomplete bus saturation. * * XXX What about multi-megabyte URBs which take minutes to transfer? */ -#define BUFF_MAX CHUNK_ALIGN(64*1024*1024) -#define BUFF_DFL CHUNK_ALIGN(300*1024) -#define BUFF_MIN CHUNK_ALIGN(8*1024) +#define BUFF_MAX CHUNK_ALIGN(1200*1024) +#define BUFF_DFL CHUNK_ALIGN(300*1024) +#define BUFF_MIN CHUNK_ALIGN(8*1024) /* * The per-event API header (2 per URB). diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index efb70b5c9e8e..b8fc818c154a 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1910,7 +1910,6 @@ static int musb_gadget_stop(struct usb_gadget *g) * gadget driver here and have everything work; * that currently misbehaves. */ - usb_gadget_set_state(g, USB_STATE_NOTATTACHED); /* Force check of devctl register for PM runtime */ schedule_delayed_work(&musb->irq_work, 0); @@ -2019,7 +2018,6 @@ void musb_g_disconnect(struct musb *musb) case OTG_STATE_B_PERIPHERAL: case OTG_STATE_B_IDLE: musb->xceiv->otg->state = OTG_STATE_B_IDLE; - usb_gadget_set_state(&musb->g, USB_STATE_NOTATTACHED); break; case OTG_STATE_B_SRP_INIT: break; diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 76b7ac1103ab..8def19fc5025 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -476,13 +476,13 @@ static int omap2430_probe(struct platform_device *pdev) ARRAY_SIZE(musb_resources)); if (ret) { dev_err(&pdev->dev, "failed to add resources\n"); - goto err_put_control_otghs; + goto err2; } ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); if (ret) { dev_err(&pdev->dev, "failed to add platform_data\n"); - goto err_put_control_otghs; + goto err2; } pm_runtime_enable(glue->dev); @@ -497,9 +497,7 @@ static int omap2430_probe(struct platform_device *pdev) err3: pm_runtime_disable(glue->dev); -err_put_control_otghs: - if (!IS_ERR(glue->control_otghs)) - put_device(glue->control_otghs); + err2: platform_device_put(musb); @@ -513,8 +511,6 @@ static int omap2430_remove(struct platform_device *pdev) platform_device_unregister(glue->musb); pm_runtime_disable(glue->dev); - if (!IS_ERR(glue->control_otghs)) - put_device(glue->control_otghs); return 0; } diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c index 7c81ccaaf2e9..6dfecbd47d7a 100644 --- a/drivers/usb/phy/phy-mxs-usb.c +++ b/drivers/usb/phy/phy-mxs-usb.c @@ -394,7 +394,6 @@ static bool mxs_phy_is_otg_host(struct mxs_phy *mxs_phy) static void mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool on) { bool vbus_is_on = false; - enum usb_phy_events last_event = mxs_phy->phy.last_event; /* If the SoCs don't need to disconnect line without vbus, quit */ if (!(mxs_phy->data->flags & MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS)) @@ -406,8 +405,7 @@ static void mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool on) vbus_is_on = mxs_phy_get_vbus_status(mxs_phy); - if (on && ((!vbus_is_on && !mxs_phy_is_otg_host(mxs_phy)) - || (last_event == USB_EVENT_VBUS))) + if (on && !vbus_is_on && !mxs_phy_is_otg_host(mxs_phy)) __mxs_phy_disconnect_line(mxs_phy, true); else __mxs_phy_disconnect_line(mxs_phy, false); diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c index 607c3f18356a..9337c30f0743 100644 --- a/drivers/usb/phy/phy-twl6030-usb.c +++ b/drivers/usb/phy/phy-twl6030-usb.c @@ -328,8 +328,9 @@ static int twl6030_set_vbus(struct phy_companion *comparator, bool enabled) static int twl6030_usb_probe(struct platform_device *pdev) { + u32 ret; struct twl6030_usb *twl; - int status, err, ret; + int status, err; struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index ee01061b413c..d13b8e35ce33 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -781,8 +781,6 @@ static const struct usb_device_id id_table_combined[] = { .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, { USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID), .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, - { USB_DEVICE(FTDI_NDI_VID, FTDI_NDI_EMGUIDE_GEMINI_PID), - .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, { USB_DEVICE(NOVITUS_VID, NOVITUS_BONO_E_PID) }, { USB_DEVICE(FTDI_VID, RTSYSTEMS_USB_VX8_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 324065cc352c..9c95ca876bae 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -197,9 +197,6 @@ #define FTDI_NDI_FUTURE_3_PID 0xDA73 /* NDI future device #3 */ #define FTDI_NDI_AURORA_SCU_PID 0xDA74 /* NDI Aurora SCU */ -#define FTDI_NDI_VID 0x23F2 -#define FTDI_NDI_EMGUIDE_GEMINI_PID 0x0003 /* NDI Emguide Gemini */ - /* * ChamSys Limited (www.chamsys.co.uk) USB wing/interface product IDs */ diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 4a93bfbe4c6c..08d70256e72e 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -273,7 +273,6 @@ static void option_instat_callback(struct urb *urb); #define QUECTEL_PRODUCT_EM05CN 0x0312 #define QUECTEL_PRODUCT_EM05G_GR 0x0313 #define QUECTEL_PRODUCT_EM05G_RS 0x0314 -#define QUECTEL_PRODUCT_RG255C 0x0316 #define QUECTEL_PRODUCT_EM12 0x0512 #define QUECTEL_PRODUCT_RM500Q 0x0800 #define QUECTEL_PRODUCT_RM520N 0x0801 @@ -618,7 +617,6 @@ static void option_instat_callback(struct urb *urb); #define UNISOC_VENDOR_ID 0x1782 /* TOZED LT70-C based on UNISOC SL8563 uses UNISOC's vendor ID */ #define TOZED_PRODUCT_LT70C 0x4055 -#define UNISOC_PRODUCT_UIS7720 0x4064 /* Luat Air72*U series based on UNISOC UIS8910 uses UNISOC's vendor ID */ #define LUAT_PRODUCT_AIR720U 0x4e00 @@ -1272,9 +1270,6 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500K, 0xff, 0x00, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RG650V, 0xff, 0xff, 0x30) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RG650V, 0xff, 0, 0) }, - { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RG255C, 0xff, 0xff, 0x30) }, - { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RG255C, 0xff, 0, 0) }, - { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RG255C, 0xff, 0xff, 0x40) }, { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) }, { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) }, @@ -1327,18 +1322,7 @@ static const struct usb_device_id option_ids[] = { .driver_info = NCTRL(0) | RSVD(3) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1033, 0xff), /* Telit LE910C1-EUX (ECM) */ .driver_info = NCTRL(0) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1034, 0xff), /* Telit LE910C4-WWX (rmnet) */ - .driver_info = RSVD(2) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1035, 0xff) }, /* Telit LE910C4-WWX (ECM) */ - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1036, 0xff) }, /* Telit LE910C4-WWX */ - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1037, 0xff), /* Telit LE910C4-WWX (rmnet) */ - .driver_info = NCTRL(0) | NCTRL(1) | RSVD(4) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1038, 0xff), /* Telit LE910C4-WWX (rmnet) */ - .driver_info = NCTRL(0) | RSVD(3) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x103b, 0xff), /* Telit LE910C4-WWX */ - .driver_info = NCTRL(0) | NCTRL(1) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x103c, 0xff), /* Telit LE910C4-WWX */ - .driver_info = NCTRL(0) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG0), .driver_info = RSVD(0) | RSVD(1) | NCTRL(2) | RSVD(3) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG1), @@ -1385,12 +1369,6 @@ static const struct usb_device_id option_ids[] = { .driver_info = NCTRL(0) | RSVD(1) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1075, 0xff), /* Telit FN990A (PCIe) */ .driver_info = RSVD(0) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1077, 0xff), /* Telit FN990A (rmnet + audio) */ - .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1078, 0xff), /* Telit FN990A (MBIM + audio) */ - .driver_info = NCTRL(0) | RSVD(1) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1079, 0xff), /* Telit FN990A (RNDIS + audio) */ - .driver_info = NCTRL(2) | RSVD(3) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1080, 0xff), /* Telit FE990A (rmnet) */ .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1081, 0xff), /* Telit FE990A (MBIM) */ @@ -1403,14 +1381,10 @@ static const struct usb_device_id option_ids[] = { .driver_info = RSVD(0) | NCTRL(3) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a2, 0xff), /* Telit FN920C04 (MBIM) */ .driver_info = NCTRL(4) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a3, 0xff), /* Telit FN920C04 (ECM) */ - .driver_info = NCTRL(4) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a4, 0xff), /* Telit FN20C04 (rmnet) */ .driver_info = RSVD(0) | NCTRL(3) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a7, 0xff), /* Telit FN920C04 (MBIM) */ .driver_info = NCTRL(4) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a8, 0xff), /* Telit FN920C04 (ECM) */ - .driver_info = NCTRL(4) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a9, 0xff), /* Telit FN20C04 (rmnet) */ .driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10aa, 0xff), /* Telit FN920C04 (MBIM) */ @@ -1441,9 +1415,6 @@ static const struct usb_device_id option_ids[] = { .driver_info = NCTRL(5) }, { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d0, 0xff, 0xff, 0x40) }, { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d0, 0xff, 0xff, 0x60) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10c7, 0xff, 0xff, 0x30), /* Telit FE910C04 (ECM) */ - .driver_info = NCTRL(4) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10c7, 0xff, 0xff, 0x40) }, { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d1, 0xff, 0xff, 0x30), /* Telit FN990B (MBIM) */ .driver_info = NCTRL(6) }, { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d1, 0xff, 0xff, 0x40) }, @@ -2123,12 +2094,6 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x9003, 0xff) }, /* Simcom SIM7500/SIM7600 MBIM mode */ { USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x9011, 0xff), /* Simcom SIM7500/SIM7600 RNDIS mode */ .driver_info = RSVD(7) }, - { USB_DEVICE(0x1e0e, 0x9071), /* Simcom SIM8230 RMNET mode */ - .driver_info = RSVD(3) | RSVD(4) }, - { USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x9078, 0xff), /* Simcom SIM8230 ECM mode */ - .driver_info = RSVD(5) }, - { USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x907b, 0xff), /* Simcom SIM8230 RNDIS mode */ - .driver_info = RSVD(5) }, { USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x9205, 0xff) }, /* Simcom SIM7070/SIM7080/SIM7090 AT+ECM mode */ { USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x9206, 0xff) }, /* Simcom SIM7070/SIM7080/SIM7090 AT-only mode */ { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200), @@ -2378,10 +2343,6 @@ static const struct usb_device_id option_ids[] = { .driver_info = RSVD(3) }, { USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe145, 0xff), /* Foxconn T99W651 RNDIS */ .driver_info = RSVD(5) | RSVD(6) }, - { USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe15f, 0xff), /* Foxconn T99W709 */ - .driver_info = RSVD(5) }, - { USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe167, 0xff), /* Foxconn T99W640 MBIM */ - .driver_info = RSVD(3) }, { USB_DEVICE(0x1508, 0x1001), /* Fibocom NL668 (IOT version) */ .driver_info = RSVD(4) | RSVD(5) | RSVD(6) }, { USB_DEVICE(0x1782, 0x4d10) }, /* Fibocom L610 (AT mode) */ @@ -2475,7 +2436,6 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9291, 0xff, 0xff, 0x30) }, { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9291, 0xff, 0xff, 0x40) }, { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) }, - { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, UNISOC_PRODUCT_UIS7720, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, LUAT_PRODUCT_AIR720U, 0xff, 0, 0) }, { USB_DEVICE_INTERFACE_CLASS(0x1bbb, 0x0530, 0xff), /* TCL IK512 MBIM */ .driver_info = NCTRL(1) }, diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c index a026c6cb6e68..0c423916d7bf 100644 --- a/drivers/usb/storage/realtek_cr.c +++ b/drivers/usb/storage/realtek_cr.c @@ -252,7 +252,7 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun, return USB_STOR_TRANSPORT_ERROR; } - residue = le32_to_cpu(bcs->Residue); + residue = bcs->Residue; if (bcs->Tag != us->tag) return USB_STOR_TRANSPORT_ERROR; diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 509e4e155f41..a6dc2faae85d 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -934,13 +934,6 @@ UNUSUAL_DEV( 0x05e3, 0x0723, 0x9451, 0x9451, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_SANE_SENSE ), -/* Added by MaĆ«l GUERIN */ -UNUSUAL_DEV( 0x0603, 0x8611, 0x0000, 0xffff, - "Novatek", - "NTK96550-based camera", - USB_SC_SCSI, USB_PR_BULK, NULL, - US_FL_BULK_IGNORE_TAG ), - /* * Reported by Hanno Boeck * Taken from the Lycoris Kernel @@ -1490,28 +1483,6 @@ UNUSUAL_DEV( 0x0bc2, 0x3332, 0x0000, 0x9999, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_WP_DETECT ), -/* - * Reported by Zenm Chen - * Ignore driver CD mode, otherwise usb_modeswitch may fail to switch - * the device into Wi-Fi mode. - */ -UNUSUAL_DEV( 0x0bda, 0x1a2b, 0x0000, 0xffff, - "Realtek", - "DISK", - USB_SC_DEVICE, USB_PR_DEVICE, NULL, - US_FL_IGNORE_DEVICE ), - -/* - * Reported by Zenm Chen - * Ignore driver CD mode, otherwise usb_modeswitch may fail to switch - * the device into Wi-Fi mode. - */ -UNUSUAL_DEV( 0x0bda, 0xa192, 0x0000, 0xffff, - "Realtek", - "DISK", - USB_SC_DEVICE, USB_PR_DEVICE, NULL, - US_FL_IGNORE_DEVICE ), - UNUSUAL_DEV( 0x0d49, 0x7310, 0x0000, 0x9999, "Maxtor", "USB to SATA", diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c index 464fd15e12ad..a2a1baabca93 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -288,9 +288,6 @@ static int dp_altmode_vdm(struct typec_altmode *alt, break; case CMDT_RSP_NAK: switch (cmd) { - case DP_CMD_STATUS_UPDATE: - dp->state = DP_STATE_EXIT; - break; case DP_CMD_CONFIGURE: dp->data.conf = 0; ret = dp_altmode_configured(dp); @@ -491,7 +488,7 @@ static ssize_t pin_assignment_show(struct device *dev, assignments = get_current_pin_assignments(dp); - for (i = 0; assignments && i < DP_PIN_ASSIGN_MAX; assignments >>= 1, i++) { + for (i = 0; assignments; assignments >>= 1, i++) { if (assignments & 1) { if (i == cur) len += sprintf(buf + len, "[%s] ", diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c index 9d242c5213e1..5e661bae3997 100644 --- a/drivers/usb/typec/tcpm/fusb302.c +++ b/drivers/usb/typec/tcpm/fusb302.c @@ -104,7 +104,6 @@ struct fusb302_chip { bool vconn_on; bool vbus_on; bool charge_on; - bool pd_rx_on; bool vbus_present; enum typec_cc_polarity cc_polarity; enum typec_cc_status cc1; @@ -842,11 +841,6 @@ static int tcpm_set_pd_rx(struct tcpc_dev *dev, bool on) int ret = 0; mutex_lock(&chip->lock); - if (chip->pd_rx_on == on) { - fusb302_log(chip, "pd is already %s", on ? "on" : "off"); - goto done; - } - ret = fusb302_pd_rx_flush(chip); if (ret < 0) { fusb302_log(chip, "cannot flush pd rx buffer, ret=%d", ret); @@ -869,8 +863,6 @@ static int tcpm_set_pd_rx(struct tcpc_dev *dev, bool on) on ? "on" : "off", ret); goto done; } - - chip->pd_rx_on = on; fusb302_log(chip, "pd := %s", on ? "on" : "off"); done: mutex_unlock(&chip->lock); diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c index d31b7e5895ce..ee8fa558e3ed 100644 --- a/drivers/usb/usbip/vhci_hcd.c +++ b/drivers/usb/usbip/vhci_hcd.c @@ -765,17 +765,6 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag ctrlreq->wValue, vdev->rhport); vdev->udev = usb_get_dev(urb->dev); - /* - * NOTE: A similar operation has been done via - * USB_REQ_GET_DESCRIPTOR handler below, which is - * supposed to always precede USB_REQ_SET_ADDRESS. - * - * It's not entirely clear if operating on a different - * usb_device instance here is a real possibility, - * otherwise this call and vdev->udev assignment above - * should be dropped. - */ - dev_pm_syscore_device(&vdev->udev->dev, true); usb_put_dev(old); spin_lock(&vdev->ud.lock); @@ -796,17 +785,6 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag "Not yet?:Get_Descriptor to device 0 (get max pipe size)\n"); vdev->udev = usb_get_dev(urb->dev); - /* - * Set syscore PM flag for the virtually attached - * devices to ensure they will not enter suspend on - * the client side. - * - * Note this doesn't have any impact on the physical - * devices attached to the host system on the server - * side, hence there is no need to undo the operation - * on disconnect. - */ - dev_pm_syscore_device(&vdev->udev->dev, true); usb_put_dev(old); goto out; diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h index 54167a2d28ea..edd89b7c8f18 100644 --- a/include/linux/usb/chipidea.h +++ b/include/linux/usb/chipidea.h @@ -67,7 +67,6 @@ struct ci_hdrc_platform_data { #define CI_HDRC_CONTROLLER_STOPPED_EVENT 1 #define CI_HDRC_IMX_HSIC_ACTIVE_EVENT 2 #define CI_HDRC_IMX_HSIC_SUSPEND_EVENT 3 -#define CI_HDRC_CONTROLLER_VBUS_EVENT 4 int (*notify_event) (struct ci_hdrc *ci, unsigned event); struct regulator *reg_vbus; struct usb_otg_caps ci_otg_caps; diff --git a/include/linux/usb/typec_dp.h b/include/linux/usb/typec_dp.h index afb73b3e0b80..296909ea04f2 100644 --- a/include/linux/usb/typec_dp.h +++ b/include/linux/usb/typec_dp.h @@ -56,7 +56,6 @@ enum { DP_PIN_ASSIGN_D, DP_PIN_ASSIGN_E, DP_PIN_ASSIGN_F, /* Not supported after v1.0b */ - DP_PIN_ASSIGN_MAX, }; /* DisplayPort alt mode specific commands */ From 7e703907b400cad6f1ca69cc0746a5f6a6d18d6e Mon Sep 17 00:00:00 2001 From: Gaurav Singh Date: Wed, 14 Jan 2026 06:28:33 -0800 Subject: [PATCH 42/42] msm:kgsl: Prevent sign extension on alignments Currently we allow alignments from userland which eventually can be sign extended which cause havoc down in the memory management routines. Fix the issue by changing the return type of kgsl_memdesc_get_align in case we use it differently in the future and expliticly start with a unsigned type for bit shifts. Change-Id: I03ad7e260434a5b5a3ea08c006128bc59cbcd617 Signed-off-by: Scott Bauer Signed-off-by: Gaurav Singh --- drivers/gpu/msm/kgsl.c | 10 +++++----- drivers/gpu/msm/kgsl.h | 4 +++- drivers/gpu/msm/kgsl_debugfs.c | 3 ++- drivers/gpu/msm/kgsl_iommu.c | 5 ++--- drivers/gpu/msm/kgsl_sharedmem.h | 3 ++- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index ff7e3e5468ea..d10d6dbac3db 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2008-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include @@ -4054,9 +4054,9 @@ static unsigned long _gpu_set_svm_region(struct kgsl_process_private *private, return addr; } -static unsigned long get_align(struct kgsl_mem_entry *entry) +unsigned long kgsl_get_align(struct kgsl_memdesc *memdesc) { - int bit = kgsl_memdesc_get_align(&entry->memdesc); + u32 bit = kgsl_memdesc_get_align(memdesc); if (bit >= ilog2(SZ_2M)) return SZ_2M; @@ -4065,7 +4065,7 @@ static unsigned long get_align(struct kgsl_mem_entry *entry) else if (bit >= ilog2(SZ_64K)) return SZ_64K; - return SZ_4K; + return PAGE_SIZE; } static unsigned long set_svm_area(struct file *file, @@ -4098,7 +4098,7 @@ static unsigned long get_svm_unmapped_area(struct file *file, { struct kgsl_device_private *dev_priv = file->private_data; struct kgsl_process_private *private = dev_priv->process_priv; - unsigned long align = get_align(entry); + unsigned long align = kgsl_get_align(&entry->memdesc); unsigned long ret, iova; u64 start = 0, end = 0; struct vm_area_struct *vma; diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h index 0f0721522574..4698aacf94cf 100644 --- a/drivers/gpu/msm/kgsl.h +++ b/drivers/gpu/msm/kgsl.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2008-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #ifndef __KGSL_H #define __KGSL_H @@ -473,6 +473,8 @@ void kgsl_mmu_remove_global(struct kgsl_device *device, struct kgsl_memdesc *memdesc); /* Helper functions */ +unsigned long kgsl_get_align(struct kgsl_memdesc *memdesc); + int kgsl_request_irq(struct platform_device *pdev, const char *name, irq_handler_t handler, void *data); diff --git a/drivers/gpu/msm/kgsl_debugfs.c b/drivers/gpu/msm/kgsl_debugfs.c index a90636a16f82..1298f6247c9e 100644 --- a/drivers/gpu/msm/kgsl_debugfs.c +++ b/drivers/gpu/msm/kgsl_debugfs.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2002,2008-2021, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include @@ -146,7 +147,7 @@ static const char *memtype_str(int memtype) static char get_alignflag(const struct kgsl_memdesc *m) { - int align = kgsl_memdesc_get_align(m); + u32 align = kgsl_memdesc_get_align(m); if (align >= ilog2(SZ_1M)) return 'L'; diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index 690ffe008811..25a5750e452a 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2011-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include @@ -2229,8 +2229,7 @@ static int kgsl_iommu_get_gpuaddr(struct kgsl_pagetable *pagetable, size = kgsl_memdesc_footprint(memdesc); - align = max_t(uint64_t, 1 << kgsl_memdesc_get_align(memdesc), - PAGE_SIZE); + align = kgsl_get_align(memdesc); if (memdesc->flags & KGSL_MEMFLAGS_FORCE_32BIT) { start = pt->compat_va_start; diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h index 389fd86078ff..1f55ffcfb265 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.h +++ b/drivers/gpu/msm/kgsl_sharedmem.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #ifndef __KGSL_SHAREDMEM_H #define __KGSL_SHAREDMEM_H @@ -157,7 +158,7 @@ void kgsl_free_globals(struct kgsl_device *device); * * Returns the alignment requested, as power of 2 exponent. */ -static inline int +static inline u32 kgsl_memdesc_get_align(const struct kgsl_memdesc *memdesc) { return MEMFLAGS(memdesc->flags, KGSL_MEMALIGN_MASK,