diff options
99 files changed, 921 insertions, 679 deletions
@@ -121,6 +121,7 @@ Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@gmail.com> Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@imgtec.com> Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@mips.com> <dev.kurt@vandijck-laurijssen.be> <kurt.van.dijck@eia.be> +Dikshita Agarwal <dikshita@qti.qualcomm.com> <dikshita@codeaurora.org> Dmitry Baryshkov <dbaryshkov@gmail.com> Dmitry Baryshkov <dbaryshkov@gmail.com> <[dbaryshkov@gmail.com]> Dmitry Baryshkov <dbaryshkov@gmail.com> <dmitry_baryshkov@mentor.com> @@ -150,6 +151,7 @@ Gao Xiang <xiang@kernel.org> <gaoxiang25@huawei.com> Gao Xiang <xiang@kernel.org> <hsiangkao@aol.com> Gao Xiang <xiang@kernel.org> <hsiangkao@linux.alibaba.com> Gao Xiang <xiang@kernel.org> <hsiangkao@redhat.com> +Georgi Djakov <djakov@kernel.org> <georgi.djakov@linaro.org> Gerald Schaefer <gerald.schaefer@linux.ibm.com> <geraldsc@de.ibm.com> Gerald Schaefer <gerald.schaefer@linux.ibm.com> <gerald.schaefer@de.ibm.com> Gerald Schaefer <gerald.schaefer@linux.ibm.com> <geraldsc@linux.vnet.ibm.com> @@ -441,6 +443,7 @@ Vasily Averin <vasily.averin@linux.dev> <vvs@openvz.org> Vasily Averin <vasily.averin@linux.dev> <vvs@parallels.com> Vasily Averin <vasily.averin@linux.dev> <vvs@sw.ru> Valentin Schneider <vschneid@redhat.com> <valentin.schneider@arm.com> +Vikash Garodia <quic_vgarodia@quicinc.com> <vgarodia@codeaurora.org> Vinod Koul <vkoul@kernel.org> <vinod.koul@intel.com> Vinod Koul <vkoul@kernel.org> <vinod.koul@linux.intel.com> Vinod Koul <vkoul@kernel.org> <vkoul@infradead.org> diff --git a/Documentation/ABI/testing/sysfs-class-power b/Documentation/ABI/testing/sysfs-class-power index e434fc523291..7c81f0a25a48 100644 --- a/Documentation/ABI/testing/sysfs-class-power +++ b/Documentation/ABI/testing/sysfs-class-power @@ -437,7 +437,8 @@ What: /sys/class/power_supply/<supply_name>/present Date: May 2007 Contact: linux-pm@vger.kernel.org Description: - Reports whether a battery is present or not in the system. + Reports whether a battery is present or not in the system. If the + property does not exist, the battery is considered to be present. Access: Read diff --git a/Documentation/devicetree/bindings/power/supply/richtek,rt9467-charger.yaml b/Documentation/devicetree/bindings/power/supply/richtek,rt9467.yaml index 92c570643d2c..3723717dc1f6 100644 --- a/Documentation/devicetree/bindings/power/supply/richtek,rt9467-charger.yaml +++ b/Documentation/devicetree/bindings/power/supply/richtek,rt9467.yaml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) %YAML 1.2 --- -$id: http://devicetree.org/schemas/power/supply/richtek,rt9467-charger.yaml# +$id: http://devicetree.org/schemas/power/supply/richtek,rt9467.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: Richtek RT9467 Switching Battery Charger with Power Path Management @@ -25,7 +25,7 @@ description: | properties: compatible: - const: richtek,rt9467-charger + const: richtek,rt9467 reg: maxItems: 1 @@ -65,7 +65,7 @@ examples: #size-cells = <0>; charger@5b { - compatible = "richtek,rt9467-charger"; + compatible = "richtek,rt9467"; reg = <0x5b>; wakeup-source; interrupts-extended = <&gpio_intc 32 IRQ_TYPE_LEVEL_LOW>; diff --git a/Documentation/devicetree/bindings/sound/apple,mca.yaml b/Documentation/devicetree/bindings/sound/apple,mca.yaml index 40e3a202f443..5c6ec08c7d24 100644 --- a/Documentation/devicetree/bindings/sound/apple,mca.yaml +++ b/Documentation/devicetree/bindings/sound/apple,mca.yaml @@ -23,6 +23,7 @@ properties: - enum: - apple,t6000-mca - apple,t8103-mca + - apple,t8112-mca - const: apple,mca reg: diff --git a/Documentation/devicetree/bindings/sound/microchip,sama7g5-pdmc.yaml b/Documentation/devicetree/bindings/sound/microchip,sama7g5-pdmc.yaml index c4cf1e5ab84b..9b40268537cb 100644 --- a/Documentation/devicetree/bindings/sound/microchip,sama7g5-pdmc.yaml +++ b/Documentation/devicetree/bindings/sound/microchip,sama7g5-pdmc.yaml @@ -67,6 +67,12 @@ properties: maxItems: 4 uniqueItems: true + microchip,startup-delay-us: + description: | + Specifies the delay in microseconds that needs to be applied after + enabling the PDMC microphones to avoid unwanted noise due to microphones + not being ready. + required: - compatible - reg diff --git a/MAINTAINERS b/MAINTAINERS index b0db911207ba..a76f37363e67 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9790,13 +9790,6 @@ L: netdev@vger.kernel.org S: Supported F: drivers/net/ethernet/ibm/ibmvnic.* -IBM Power Virtual Accelerator Switchboard -L: linuxppc-dev@lists.ozlabs.org -S: Supported -F: arch/powerpc/include/asm/vas.h -F: arch/powerpc/platforms/powernv/copy-paste.h -F: arch/powerpc/platforms/powernv/vas* - IBM Power Virtual Ethernet Device Driver M: Nick Child <nnac123@linux.ibm.com> L: netdev@vger.kernel.org diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 2c9cdf1d8761..a6c4407d3ec8 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -236,7 +236,7 @@ config PPC select HAVE_KPROBES select HAVE_KPROBES_ON_FTRACE select HAVE_KRETPROBES - select HAVE_LD_DEAD_CODE_DATA_ELIMINATION + select HAVE_LD_DEAD_CODE_DATA_ELIMINATION if HAVE_OBJTOOL_MCOUNT select HAVE_LIVEPATCH if HAVE_DYNAMIC_FTRACE_WITH_REGS select HAVE_MOD_ARCH_SPECIFIC select HAVE_NMI if PERF_EVENTS || (PPC64 && PPC_BOOK3S) diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index f128c7cf9c1d..ee86753e444e 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -124,6 +124,7 @@ SECTIONS * included with the main text sections, so put it by itself. */ *(.sfpr); + *(.text.asan.* .text.tsan.*) MEM_KEEP(init.text) MEM_KEEP(exit.text) } :text diff --git a/arch/x86/include/asm/string_64.h b/arch/x86/include/asm/string_64.h index 888731ccf1f6..c1e14cee0722 100644 --- a/arch/x86/include/asm/string_64.h +++ b/arch/x86/include/asm/string_64.h @@ -85,25 +85,6 @@ char *strcpy(char *dest, const char *src); char *strcat(char *dest, const char *src); int strcmp(const char *cs, const char *ct); -#if (defined(CONFIG_KASAN) && !defined(__SANITIZE_ADDRESS__)) -/* - * For files that not instrumented (e.g. mm/slub.c) we - * should use not instrumented version of mem* functions. - */ - -#undef memcpy -#define memcpy(dst, src, len) __memcpy(dst, src, len) -#undef memmove -#define memmove(dst, src, len) __memmove(dst, src, len) -#undef memset -#define memset(s, c, n) __memset(s, c, n) - -#ifndef __NO_FORTIFY -#define __NO_FORTIFY /* FORTIFY_SOURCE uses __builtin_memcpy, etc. */ -#endif - -#endif - #ifdef CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE #define __HAVE_ARCH_MEMCPY_FLUSHCACHE 1 void __memcpy_flushcache(void *dst, const void *src, size_t cnt); diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index cc5b2e22b42a..f3d7c1da299f 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -1207,13 +1207,13 @@ __power_supply_register(struct device *parent, struct power_supply *psy; int rc; + if (!desc || !desc->name || !desc->properties || !desc->num_properties) + return ERR_PTR(-EINVAL); + if (!parent) pr_warn("%s: Expected proper parent device for '%s'\n", __func__, desc->name); - if (!desc || !desc->name || !desc->properties || !desc->num_properties) - return ERR_PTR(-EINVAL); - if (psy_has_property(desc, POWER_SUPPLY_PROP_USB_TYPE) && (!desc->usb_types || !desc->num_usb_types)) return ERR_PTR(-EINVAL); diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index cbc3b62cd9e5..d904625afd40 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -4,7 +4,7 @@ * * Debug traces for zfcp. * - * Copyright IBM Corp. 2002, 2020 + * Copyright IBM Corp. 2002, 2023 */ #define KMSG_COMPONENT "zfcp" @@ -146,6 +146,48 @@ void zfcp_dbf_hba_fsf_fces(char *tag, const struct zfcp_fsf_req *req, u64 wwpn, } /** + * zfcp_dbf_hba_fsf_reqid - trace only the tag and a request ID + * @tag: tag documenting the source + * @level: trace level + * @adapter: adapter instance the request ID belongs to + * @req_id: the request ID to trace + */ +void zfcp_dbf_hba_fsf_reqid(const char *const tag, const int level, + struct zfcp_adapter *const adapter, + const u64 req_id) +{ + struct zfcp_dbf *const dbf = adapter->dbf; + struct zfcp_dbf_hba *const rec = &dbf->hba_buf; + struct zfcp_dbf_hba_res *const res = &rec->u.res; + unsigned long flags; + + if (unlikely(!debug_level_enabled(dbf->hba, level))) + return; + + spin_lock_irqsave(&dbf->hba_lock, flags); + memset(rec, 0, sizeof(*rec)); + + memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); + + rec->id = ZFCP_DBF_HBA_RES; + rec->fsf_req_id = req_id; + rec->fsf_req_status = ~0u; + rec->fsf_cmd = ~0u; + rec->fsf_seq_no = ~0u; + + res->req_issued = ~0ull; + res->prot_status = ~0u; + memset(res->prot_status_qual, 0xff, sizeof(res->prot_status_qual)); + res->fsf_status = ~0u; + memset(res->fsf_status_qual, 0xff, sizeof(res->fsf_status_qual)); + res->port_handle = ~0u; + res->lun_handle = ~0u; + + debug_event(dbf->hba, level, rec, sizeof(*rec)); + spin_unlock_irqrestore(&dbf->hba_lock, flags); +} + +/** * zfcp_dbf_hba_fsf_uss - trace event for an unsolicited status buffer * @tag: tag indicating which kind of unsolicited status has been received * @req: request providing the unsolicited status @@ -649,7 +691,7 @@ void zfcp_dbf_scsi_common(char *tag, int level, struct scsi_device *sdev, rec->scsi_id = sc->device->id; rec->scsi_lun = (u32)sc->device->lun; rec->scsi_lun_64_hi = (u32)(sc->device->lun >> 32); - rec->host_scribble = (unsigned long)sc->host_scribble; + rec->host_scribble = (u64)sc->host_scribble; memcpy(rec->scsi_opcode, sc->cmnd, min_t(int, sc->cmd_len, ZFCP_DBF_SCSI_OPCODE)); diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 94de55304a02..6c761299a22f 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -129,7 +129,7 @@ struct zfcp_erp_action { struct scsi_device *sdev; u32 status; /* recovery status */ enum zfcp_erp_steps step; /* active step of this erp action */ - unsigned long fsf_req_id; + u64 fsf_req_id; struct timer_list timer; }; @@ -163,7 +163,7 @@ struct zfcp_adapter { struct Scsi_Host *scsi_host; /* Pointer to mid-layer */ struct list_head port_list; /* remote port list */ rwlock_t port_list_lock; /* port list lock */ - unsigned long req_no; /* unique FSF req number */ + u64 req_no; /* unique FSF req number */ struct zfcp_reqlist *req_list; u32 fsf_req_seq_no; /* FSF cmnd seq number */ rwlock_t abort_lock; /* Protects against SCSI @@ -325,7 +325,7 @@ static inline u64 zfcp_scsi_dev_lun(struct scsi_device *sdev) */ struct zfcp_fsf_req { struct list_head list; - unsigned long req_id; + u64 req_id; struct zfcp_adapter *adapter; struct zfcp_qdio_req qdio_req; struct completion completion; diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index c302cbb18a55..9f5152b42b0e 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -4,7 +4,7 @@ * * External function declarations. * - * Copyright IBM Corp. 2002, 2020 + * Copyright IBM Corp. 2002, 2023 */ #ifndef ZFCP_EXT_H @@ -46,6 +46,9 @@ extern void zfcp_dbf_hba_fsf_res(char *, int, struct zfcp_fsf_req *); extern void zfcp_dbf_hba_fsf_fces(char *tag, const struct zfcp_fsf_req *req, u64 wwpn, u32 fc_security_old, u32 fc_security_new); +extern void zfcp_dbf_hba_fsf_reqid(const char *const tag, const int level, + struct zfcp_adapter *const adapter, + const u64 req_id); extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_hba_def_err(struct zfcp_adapter *, u64, u16, void **); extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32); diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index ab3ea529cca7..ceed1b6f7cb6 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -4,7 +4,7 @@ * * Implementation of FSF commands. * - * Copyright IBM Corp. 2002, 2020 + * Copyright IBM Corp. 2002, 2023 */ #define KMSG_COMPONENT "zfcp" @@ -884,7 +884,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) const bool is_srb = zfcp_fsf_req_is_status_read_buffer(req); struct zfcp_adapter *adapter = req->adapter; struct zfcp_qdio *qdio = adapter->qdio; - unsigned long req_id = req->req_id; + u64 req_id = req->req_id; zfcp_reqlist_add(adapter->req_list, req); @@ -892,8 +892,11 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) req->issued = get_tod_clock(); if (zfcp_qdio_send(qdio, &req->qdio_req)) { del_timer_sync(&req->timer); + /* lookup request again, list might have changed */ - zfcp_reqlist_find_rm(adapter->req_list, req_id); + if (zfcp_reqlist_find_rm(adapter->req_list, req_id) == NULL) + zfcp_dbf_hba_fsf_reqid("fsrsrmf", 1, adapter, req_id); + zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1"); return -EIO; } @@ -1042,7 +1045,7 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *scmnd) struct scsi_device *sdev = scmnd->device; struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio; - unsigned long old_req_id = (unsigned long) scmnd->host_scribble; + u64 old_req_id = (u64) scmnd->host_scribble; spin_lock_irq(&qdio->req_q_lock); if (zfcp_qdio_sbal_get(qdio)) @@ -1065,7 +1068,7 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *scmnd) req->handler = zfcp_fsf_abort_fcp_command_handler; req->qtcb->header.lun_handle = zfcp_sdev->lun_handle; req->qtcb->header.port_handle = zfcp_sdev->port->handle; - req->qtcb->bottom.support.req_handle = (u64) old_req_id; + req->qtcb->bottom.support.req_handle = old_req_id; zfcp_fsf_start_timer(req, ZFCP_FSF_SCSI_ER_TIMEOUT); if (!zfcp_fsf_req_send(req)) { @@ -1919,7 +1922,7 @@ int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port) { struct zfcp_qdio *qdio = wka_port->adapter->qdio; struct zfcp_fsf_req *req; - unsigned long req_id = 0; + u64 req_id = 0; int retval = -EIO; spin_lock_irq(&qdio->req_q_lock); @@ -1978,7 +1981,7 @@ int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port) { struct zfcp_qdio *qdio = wka_port->adapter->qdio; struct zfcp_fsf_req *req; - unsigned long req_id = 0; + u64 req_id = 0; int retval = -EIO; spin_lock_irq(&qdio->req_q_lock); @@ -2587,6 +2590,7 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd) goto out; } + BUILD_BUG_ON(sizeof(scsi_cmnd->host_scribble) < sizeof(req->req_id)); scsi_cmnd->host_scribble = (unsigned char *) req->req_id; io = &req->qtcb->bottom.io; @@ -2732,7 +2736,7 @@ void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx) struct qdio_buffer *sbal = qdio->res_q[sbal_idx]; struct qdio_buffer_element *sbale; struct zfcp_fsf_req *fsf_req; - unsigned long req_id; + u64 req_id; int idx; for (idx = 0; idx < QDIO_MAX_ELEMENTS_PER_BUFFER; idx++) { @@ -2747,7 +2751,7 @@ void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx) * corruption and must stop the machine immediately. */ zfcp_qdio_siosl(adapter); - panic("error: unknown req_id (%lx) on adapter %s.\n", + panic("error: unknown req_id (%llx) on adapter %s.\n", req_id, dev_name(&adapter->ccw_device->dev)); } diff --git a/drivers/s390/scsi/zfcp_qdio.h b/drivers/s390/scsi/zfcp_qdio.h index 390706867df3..90134d9b69a7 100644 --- a/drivers/s390/scsi/zfcp_qdio.h +++ b/drivers/s390/scsi/zfcp_qdio.h @@ -115,7 +115,7 @@ zfcp_qdio_sbale_curr(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req) */ static inline void zfcp_qdio_req_init(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req, - unsigned long req_id, u8 sbtype, void *data, u32 len) + u64 req_id, u8 sbtype, void *data, u32 len) { struct qdio_buffer_element *sbale; int count = min(atomic_read(&qdio->req_q_free), diff --git a/drivers/s390/scsi/zfcp_reqlist.h b/drivers/s390/scsi/zfcp_reqlist.h index 9b8ff249e31c..59fbb1b128cb 100644 --- a/drivers/s390/scsi/zfcp_reqlist.h +++ b/drivers/s390/scsi/zfcp_reqlist.h @@ -5,14 +5,16 @@ * Data structure and helper functions for tracking pending FSF * requests. * - * Copyright IBM Corp. 2009, 2016 + * Copyright IBM Corp. 2009, 2023 */ #ifndef ZFCP_REQLIST_H #define ZFCP_REQLIST_H +#include <linux/types.h> + /* number of hash buckets */ -#define ZFCP_REQ_LIST_BUCKETS 128 +#define ZFCP_REQ_LIST_BUCKETS 128u /** * struct zfcp_reqlist - Container for request list (reqlist) @@ -24,7 +26,7 @@ struct zfcp_reqlist { struct list_head buckets[ZFCP_REQ_LIST_BUCKETS]; }; -static inline int zfcp_reqlist_hash(unsigned long req_id) +static inline size_t zfcp_reqlist_hash(u64 req_id) { return req_id % ZFCP_REQ_LIST_BUCKETS; } @@ -37,7 +39,7 @@ static inline int zfcp_reqlist_hash(unsigned long req_id) */ static inline struct zfcp_reqlist *zfcp_reqlist_alloc(void) { - unsigned int i; + size_t i; struct zfcp_reqlist *rl; rl = kzalloc(sizeof(struct zfcp_reqlist), GFP_KERNEL); @@ -60,7 +62,7 @@ static inline struct zfcp_reqlist *zfcp_reqlist_alloc(void) */ static inline int zfcp_reqlist_isempty(struct zfcp_reqlist *rl) { - unsigned int i; + size_t i; for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++) if (!list_empty(&rl->buckets[i])) @@ -81,10 +83,10 @@ static inline void zfcp_reqlist_free(struct zfcp_reqlist *rl) } static inline struct zfcp_fsf_req * -_zfcp_reqlist_find(struct zfcp_reqlist *rl, unsigned long req_id) +_zfcp_reqlist_find(struct zfcp_reqlist *rl, u64 req_id) { struct zfcp_fsf_req *req; - unsigned int i; + size_t i; i = zfcp_reqlist_hash(req_id); list_for_each_entry(req, &rl->buckets[i], list) @@ -102,7 +104,7 @@ _zfcp_reqlist_find(struct zfcp_reqlist *rl, unsigned long req_id) * or NULL if there is no known FSF request with this id. */ static inline struct zfcp_fsf_req * -zfcp_reqlist_find(struct zfcp_reqlist *rl, unsigned long req_id) +zfcp_reqlist_find(struct zfcp_reqlist *rl, u64 req_id) { unsigned long flags; struct zfcp_fsf_req *req; @@ -127,7 +129,7 @@ zfcp_reqlist_find(struct zfcp_reqlist *rl, unsigned long req_id) * NULL if it has not been found. */ static inline struct zfcp_fsf_req * -zfcp_reqlist_find_rm(struct zfcp_reqlist *rl, unsigned long req_id) +zfcp_reqlist_find_rm(struct zfcp_reqlist *rl, u64 req_id) { unsigned long flags; struct zfcp_fsf_req *req; @@ -154,7 +156,7 @@ zfcp_reqlist_find_rm(struct zfcp_reqlist *rl, unsigned long req_id) static inline void zfcp_reqlist_add(struct zfcp_reqlist *rl, struct zfcp_fsf_req *req) { - unsigned int i; + size_t i; unsigned long flags; i = zfcp_reqlist_hash(req->req_id); @@ -172,7 +174,7 @@ static inline void zfcp_reqlist_add(struct zfcp_reqlist *rl, static inline void zfcp_reqlist_move(struct zfcp_reqlist *rl, struct list_head *list) { - unsigned int i; + size_t i; unsigned long flags; spin_lock_irqsave(&rl->lock, flags); @@ -200,7 +202,7 @@ zfcp_reqlist_apply_for_all(struct zfcp_reqlist *rl, { struct zfcp_fsf_req *req; unsigned long flags; - unsigned int i; + size_t i; spin_lock_irqsave(&rl->lock, flags); for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++) diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 526ac240d9fe..3dbf4b21d127 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -170,7 +170,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) (struct zfcp_adapter *) scsi_host->hostdata[0]; struct zfcp_fsf_req *old_req, *abrt_req; unsigned long flags; - unsigned long old_reqid = (unsigned long) scpnt->host_scribble; + u64 old_reqid = (u64) scpnt->host_scribble; int retval = SUCCESS, ret; int retry = 3; char *dbf_tag; diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h index 3687b5c0cf90..d8fc7beafa20 100644 --- a/drivers/scsi/cxgbi/libcxgbi.h +++ b/drivers/scsi/cxgbi/libcxgbi.h @@ -24,7 +24,6 @@ #include <linux/scatterlist.h> #include <linux/skbuff.h> #include <linux/vmalloc.h> -#include <linux/version.h> #include <scsi/scsi_device.h> #include <scsi/libiscsi_tcp.h> diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 12346e2297fd..f7f62e56afca 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -181,6 +181,7 @@ void scsi_remove_host(struct Scsi_Host *shost) scsi_forget_host(shost); mutex_unlock(&shost->scan_mutex); scsi_proc_host_rm(shost); + scsi_proc_hostdir_rm(shost->hostt); /* * New SCSI devices cannot be attached anymore because of the SCSI host @@ -340,6 +341,7 @@ static void scsi_host_dev_release(struct device *dev) struct Scsi_Host *shost = dev_to_shost(dev); struct device *parent = dev->parent; + /* In case scsi_remove_host() has not been called. */ scsi_proc_hostdir_rm(shost->hostt); /* Wait for functions invoked through call_rcu(&scmd->rcu, ...) */ @@ -356,7 +358,7 @@ static void scsi_host_dev_release(struct device *dev) /* * Free the shost_dev device name here if scsi_host_alloc() * and scsi_host_put() have been called but neither - * scsi_host_add() nor scsi_host_remove() has been called. + * scsi_host_add() nor scsi_remove_host() has been called. * This avoids that the memory allocated for the shost_dev * name is leaked. */ diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 198d3f20d682..c74053f0b72f 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -1516,23 +1516,22 @@ static void ipr_process_ccn(struct ipr_cmnd *ipr_cmd) } /** - * strip_and_pad_whitespace - Strip and pad trailing whitespace. - * @i: index into buffer - * @buf: string to modify + * strip_whitespace - Strip and pad trailing whitespace. + * @i: size of buffer + * @buf: string to modify * - * This function will strip all trailing whitespace, pad the end - * of the string with a single space, and NULL terminate the string. + * This function will strip all trailing whitespace and + * NUL terminate the string. * - * Return value: - * new length of string **/ -static int strip_and_pad_whitespace(int i, char *buf) +static void strip_whitespace(int i, char *buf) { + if (i < 1) + return; + i--; while (i && buf[i] == ' ') i--; - buf[i+1] = ' '; - buf[i+2] = '\0'; - return i + 2; + buf[i+1] = '\0'; } /** @@ -1547,19 +1546,21 @@ static int strip_and_pad_whitespace(int i, char *buf) static void ipr_log_vpd_compact(char *prefix, struct ipr_hostrcb *hostrcb, struct ipr_vpd *vpd) { - char buffer[IPR_VENDOR_ID_LEN + IPR_PROD_ID_LEN + IPR_SERIAL_NUM_LEN + 3]; - int i = 0; + char vendor_id[IPR_VENDOR_ID_LEN + 1]; + char product_id[IPR_PROD_ID_LEN + 1]; + char sn[IPR_SERIAL_NUM_LEN + 1]; - memcpy(buffer, vpd->vpids.vendor_id, IPR_VENDOR_ID_LEN); - i = strip_and_pad_whitespace(IPR_VENDOR_ID_LEN - 1, buffer); + memcpy(vendor_id, vpd->vpids.vendor_id, IPR_VENDOR_ID_LEN); + strip_whitespace(IPR_VENDOR_ID_LEN, vendor_id); - memcpy(&buffer[i], vpd->vpids.product_id, IPR_PROD_ID_LEN); - i = strip_and_pad_whitespace(i + IPR_PROD_ID_LEN - 1, buffer); + memcpy(product_id, vpd->vpids.product_id, IPR_PROD_ID_LEN); + strip_whitespace(IPR_PROD_ID_LEN, product_id); - memcpy(&buffer[i], vpd->sn, IPR_SERIAL_NUM_LEN); - buffer[IPR_SERIAL_NUM_LEN + i] = '\0'; + memcpy(sn, vpd->sn, IPR_SERIAL_NUM_LEN); + strip_whitespace(IPR_SERIAL_NUM_LEN, sn); - ipr_hcam_err(hostrcb, "%s VPID/SN: %s\n", prefix, buffer); + ipr_hcam_err(hostrcb, "%s VPID/SN: %s %s %s\n", prefix, + vendor_id, product_id, sn); } /** @@ -9495,11 +9496,10 @@ static pci_ers_result_t ipr_pci_error_detected(struct pci_dev *pdev, * This function takes care of initilizing the adapter to the point * where it can accept new commands. * Return value: - * 0 on success / -EIO on failure + * none **/ -static int ipr_probe_ioa_part2(struct ipr_ioa_cfg *ioa_cfg) +static void ipr_probe_ioa_part2(struct ipr_ioa_cfg *ioa_cfg) { - int rc = 0; unsigned long host_lock_flags = 0; ENTER; @@ -9515,7 +9515,6 @@ static int ipr_probe_ioa_part2(struct ipr_ioa_cfg *ioa_cfg) spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags); LEAVE; - return rc; } /** @@ -10558,12 +10557,7 @@ static int ipr_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) return rc; ioa_cfg = pci_get_drvdata(pdev); - rc = ipr_probe_ioa_part2(ioa_cfg); - - if (rc) { - __ipr_remove(pdev); - return rc; - } + ipr_probe_ioa_part2(ioa_cfg); rc = scsi_add_host(ioa_cfg->host, &pdev->dev); diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 76c3434f8976..22f2e046e8eb 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -2541,7 +2541,7 @@ lpfc_sriov_hw_max_virtfn_show(struct device *dev, /** * lpfc_enable_bbcr_set: Sets an attribute value. - * @phba: pointer the the adapter structure. + * @phba: pointer to the adapter structure. * @val: integer attribute value. * * Description: @@ -2632,7 +2632,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ * takes a default argument, a minimum and maximum argument. * * lpfc_##attr##_init: Initializes an attribute. - * @phba: pointer the the adapter structure. + * @phba: pointer to the adapter structure. * @val: integer attribute value. * * Validates the min and max values then sets the adapter config field @@ -2665,7 +2665,7 @@ lpfc_##attr##_init(struct lpfc_hba *phba, uint val) \ * into a function with the name lpfc_hba_queue_depth_set * * lpfc_##attr##_set: Sets an attribute value. - * @phba: pointer the the adapter structure. + * @phba: pointer to the adapter structure. * @val: integer attribute value. * * Description: @@ -2794,7 +2794,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ * lpfc_##attr##_init: validates the min and max values then sets the * adapter config field accordingly, or uses the default if out of range * and prints an error message. - * @phba: pointer the the adapter structure. + * @phba: pointer to the adapter structure. * @val: integer attribute value. * * Returns: @@ -2826,7 +2826,7 @@ lpfc_##attr##_init(struct lpfc_vport *vport, uint val) \ * lpfc_##attr##_set: validates the min and max values then sets the * adapter config field if in the valid range. prints error message * and does not set the parameter if invalid. - * @phba: pointer the the adapter structure. + * @phba: pointer to the adapter structure. * @val: integer attribute value. * * Returns: diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 569639dc8b2c..35b252f1ef73 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -8886,7 +8886,7 @@ reject_out: * @rrq: Pointer to the rrq struct. * * Build a ELS RRQ command and send it to the target. If the issue_iocb is - * Successful the the completion handler will clear the RRQ. + * successful, the completion handler will clear the RRQ. * * Return codes * 0 - Successfully sent rrq els iocb. @@ -10287,7 +10287,7 @@ lpfc_els_rcv_fpin(struct lpfc_vport *vport, void *p, u32 fpin_length) /* Send every descriptor individually to the upper layer */ if (deliver) fc_host_fpin_rcv(lpfc_shost_from_vport(vport), - fpin_length, (char *)fpin); + fpin_length, (char *)fpin, 0); desc_cnt++; } } diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index a6df0a5b4006..66cd0b1dbbd0 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -2459,7 +2459,7 @@ static void lpfc_sli4_fcf_pri_list_del(struct lpfc_hba *phba, * @phba: pointer to lpfc hba data structure. * @fcf_index: the index of the fcf record to update * This routine acquires the hbalock and then set the LPFC_FCF_FLOGI_FAILED - * flag so the the round robin slection for the particular priority level + * flag so the round robin selection for the particular priority level * will try a different fcf record that does not have this bit set. * If the fcf record is re-read for any reason this flag is cleared brfore * adding it to the priority list. diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 6eb4085a3a22..61958a24a43d 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -5502,7 +5502,7 @@ lpfc_sli4_async_link_evt(struct lpfc_hba *phba, bf_set(lpfc_mbx_read_top_link_spd, la, (bf_get(lpfc_acqe_link_speed, acqe_link))); - /* Fake the the following irrelvant fields */ + /* Fake the following irrelevant fields */ bf_set(lpfc_mbx_read_top_topology, la, LPFC_TOPOLOGY_PT_PT); bf_set(lpfc_mbx_read_top_alpa_granted, la, 0); bf_set(lpfc_mbx_read_top_il, la, 0); @@ -12549,7 +12549,7 @@ lpfc_cpu_affinity_check(struct lpfc_hba *phba, int vectors) /* Mark CPU as IRQ not assigned by the kernel */ cpup->flag |= LPFC_CPU_MAP_UNASSIGN; - /* If so, find a new_cpup thats on the the SAME + /* If so, find a new_cpup that is on the SAME * phys_id as cpup. start_cpu will start where we * left off so all unassigned entries don't get assgined * the IRQ of the first entry. diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 9858b1743769..0dfdc0c4c08c 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -2509,7 +2509,7 @@ lpfc_sli4_dump_page_a0(struct lpfc_hba *phba, struct lpfcMboxq *mbox) * information via a READ_FCF mailbox command. This mailbox command also is used * to indicate where received unsolicited frames from this FCF will be sent. By * default this routine will set up the FCF to forward all unsolicited frames - * the the RQ ID passed in the @phba. This can be overridden by the caller for + * to the RQ ID passed in the @phba. This can be overridden by the caller for * more complicated setups. **/ void @@ -2577,7 +2577,7 @@ lpfc_reg_fcfi(struct lpfc_hba *phba, struct lpfcMboxq *mbox) * information via a READ_FCF mailbox command. This mailbox command also is used * to indicate where received unsolicited frames from this FCF will be sent. By * default this routine will set up the FCF to forward all unsolicited frames - * the the RQ ID passed in the @phba. This can be overridden by the caller for + * to the RQ ID passed in the @phba. This can be overridden by the caller for * more complicated setups. **/ void diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index f7cfac0da9b6..7517dd55fe91 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -1469,7 +1469,7 @@ lpfc_nvmet_cleanup_io_context(struct lpfc_hba *phba) if (!infop) return; - /* Cycle the the entire CPU context list for every MRQ */ + /* Cycle the entire CPU context list for every MRQ */ for (i = 0; i < phba->cfg_nvmet_mrq; i++) { for_each_present_cpu(j) { infop = lpfc_get_ctx_list(phba, j, i); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index edbd81c3b643..c5b69f313af3 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -20804,7 +20804,7 @@ lpfc_log_fw_write_cmpl(struct lpfc_hba *phba, u32 shdr_status, * the offset after the write object mailbox has completed. @size is used to * determine the end of the object and whether the eof bit should be set. * - * Return 0 is successful and offset will contain the the new offset to use + * Return 0 is successful and offset will contain the new offset to use * for the next write. * Return negative value for error cases. **/ diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index def4c5e15cd8..23de2603e71f 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -29,7 +29,6 @@ #include <linux/types.h> #include <linux/uaccess.h> #include <linux/utsname.h> -#include <linux/version.h> #include <linux/workqueue.h> #include <asm/unaligned.h> #include <scsi/scsi.h> @@ -955,19 +954,16 @@ struct scmd_priv { * @chain_buf_count: Chain buffer count * @chain_buf_pool: Chain buffer pool * @chain_sgl_list: Chain SGL list - * @chain_bitmap_sz: Chain buffer allocator bitmap size * @chain_bitmap: Chain buffer allocator bitmap * @chain_buf_lock: Chain buffer list lock * @bsg_cmds: Command tracker for BSG command * @host_tm_cmds: Command tracker for task management commands * @dev_rmhs_cmds: Command tracker for device removal commands * @evtack_cmds: Command tracker for event ack commands - * @devrem_bitmap_sz: Device removal bitmap size * @devrem_bitmap: Device removal bitmap - * @dev_handle_bitmap_sz: Device handle bitmap size + * @dev_handle_bitmap_bits: Number of bits in device handle bitmap * @removepend_bitmap: Remove pending bitmap * @delayed_rmhs_list: Delayed device removal list - * @evtack_cmds_bitmap_sz: Event Ack bitmap size * @evtack_cmds_bitmap: Event Ack bitmap * @delayed_evtack_cmds_list: Delayed event acknowledgment list * @ts_update_counter: Timestamp update counter @@ -1128,7 +1124,6 @@ struct mpi3mr_ioc { u32 chain_buf_count; struct dma_pool *chain_buf_pool; struct chain_element *chain_sgl_list; - u16 chain_bitmap_sz; void *chain_bitmap; spinlock_t chain_buf_lock; @@ -1136,12 +1131,10 @@ struct mpi3mr_ioc { struct mpi3mr_drv_cmd host_tm_cmds; struct mpi3mr_drv_cmd dev_rmhs_cmds[MPI3MR_NUM_DEVRMCMD]; struct mpi3mr_drv_cmd evtack_cmds[MPI3MR_NUM_EVTACKCMD]; - u16 devrem_bitmap_sz; void *devrem_bitmap; - u16 dev_handle_bitmap_sz; + u16 dev_handle_bitmap_bits; void *removepend_bitmap; struct list_head delayed_rmhs_list; - u16 evtack_cmds_bitmap_sz; void *evtack_cmds_bitmap; struct list_head delayed_evtack_cmds_list; diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c index 9baac224b213..bff637702397 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_app.c +++ b/drivers/scsi/mpi3mr/mpi3mr_app.c @@ -293,7 +293,6 @@ out: static long mpi3mr_get_all_tgt_info(struct mpi3mr_ioc *mrioc, struct bsg_job *job) { - long rval = -EINVAL; u16 num_devices = 0, i = 0, size; unsigned long flags; struct mpi3mr_tgt_dev *tgtdev; @@ -304,7 +303,7 @@ static long mpi3mr_get_all_tgt_info(struct mpi3mr_ioc *mrioc, if (job->request_payload.payload_len < sizeof(u32)) { dprint_bsg_err(mrioc, "%s: invalid size argument\n", __func__); - return rval; + return -EINVAL; } spin_lock_irqsave(&mrioc->tgtdev_lock, flags); @@ -312,7 +311,7 @@ static long mpi3mr_get_all_tgt_info(struct mpi3mr_ioc *mrioc, num_devices++; spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); - if ((job->request_payload.payload_len == sizeof(u32)) || + if ((job->request_payload.payload_len <= sizeof(u64)) || list_empty(&mrioc->tgtdev_list)) { sg_copy_from_buffer(job->request_payload.sg_list, job->request_payload.sg_cnt, @@ -320,14 +319,14 @@ static long mpi3mr_get_all_tgt_info(struct mpi3mr_ioc *mrioc, return 0; } - kern_entrylen = (num_devices - 1) * sizeof(*devmap_info); - size = sizeof(*alltgt_info) + kern_entrylen; + kern_entrylen = num_devices * sizeof(*devmap_info); + size = sizeof(u64) + kern_entrylen; alltgt_info = kzalloc(size, GFP_KERNEL); if (!alltgt_info) return -ENOMEM; devmap_info = alltgt_info->dmi; - memset((u8 *)devmap_info, 0xFF, (kern_entrylen + sizeof(*devmap_info))); + memset((u8 *)devmap_info, 0xFF, kern_entrylen); spin_lock_irqsave(&mrioc->tgtdev_lock, flags); list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list) { if (i < num_devices) { @@ -344,25 +343,18 @@ static long mpi3mr_get_all_tgt_info(struct mpi3mr_ioc *mrioc, num_devices = i; spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags); - memcpy(&alltgt_info->num_devices, &num_devices, sizeof(num_devices)); + alltgt_info->num_devices = num_devices; - usr_entrylen = (job->request_payload.payload_len - sizeof(u32)) / sizeof(*devmap_info); + usr_entrylen = (job->request_payload.payload_len - sizeof(u64)) / + sizeof(*devmap_info); usr_entrylen *= sizeof(*devmap_info); min_entrylen = min(usr_entrylen, kern_entrylen); - if (min_entrylen && (!memcpy(&alltgt_info->dmi, devmap_info, min_entrylen))) { - dprint_bsg_err(mrioc, "%s:%d: device map info copy failed\n", - __func__, __LINE__); - rval = -EFAULT; - goto out; - } sg_copy_from_buffer(job->request_payload.sg_list, job->request_payload.sg_cnt, - alltgt_info, job->request_payload.payload_len); - rval = 0; -out: + alltgt_info, (min_entrylen + sizeof(u64))); kfree(alltgt_info); - return rval; + return 0; } /** * mpi3mr_get_change_count - Get topology change count diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c index 286a44506578..758f7ca9e0ee 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c @@ -1128,7 +1128,6 @@ static int mpi3mr_issue_and_process_mur(struct mpi3mr_ioc *mrioc, static int mpi3mr_revalidate_factsdata(struct mpi3mr_ioc *mrioc) { - u16 dev_handle_bitmap_sz; void *removepend_bitmap; if (mrioc->facts.reply_sz > mrioc->reply_sz) { @@ -1160,25 +1159,23 @@ mpi3mr_revalidate_factsdata(struct mpi3mr_ioc *mrioc) "\tcontroller while sas transport support is enabled at the\n" "\tdriver, please reboot the system or reload the driver\n"); - dev_handle_bitmap_sz = mrioc->facts.max_devhandle / 8; - if (mrioc->facts.max_devhandle % 8) - dev_handle_bitmap_sz++; - if (dev_handle_bitmap_sz > mrioc->dev_handle_bitmap_sz) { - removepend_bitmap = krealloc(mrioc->removepend_bitmap, - dev_handle_bitmap_sz, GFP_KERNEL); + if (mrioc->facts.max_devhandle > mrioc->dev_handle_bitmap_bits) { + removepend_bitmap = bitmap_zalloc(mrioc->facts.max_devhandle, + GFP_KERNEL); if (!removepend_bitmap) { ioc_err(mrioc, - "failed to increase removepend_bitmap sz from: %d to %d\n", - mrioc->dev_handle_bitmap_sz, dev_handle_bitmap_sz); + "failed to increase removepend_bitmap bits from %d to %d\n", + mrioc->dev_handle_bitmap_bits, + mrioc->facts.max_devhandle); return -EPERM; } - memset(removepend_bitmap + mrioc->dev_handle_bitmap_sz, 0, - dev_handle_bitmap_sz - mrioc->dev_handle_bitmap_sz); + bitmap_free(mrioc->removepend_bitmap); mrioc->removepend_bitmap = removepend_bitmap; ioc_info(mrioc, - "increased dev_handle_bitmap_sz from %d to %d\n", - mrioc->dev_handle_bitmap_sz, dev_handle_bitmap_sz); - mrioc->dev_handle_bitmap_sz = dev_handle_bitmap_sz; + "increased bits of dev_handle_bitmap from %d to %d\n", + mrioc->dev_handle_bitmap_bits, + mrioc->facts.max_devhandle); + mrioc->dev_handle_bitmap_bits = mrioc->facts.max_devhandle; } return 0; @@ -2957,27 +2954,18 @@ static int mpi3mr_alloc_reply_sense_bufs(struct mpi3mr_ioc *mrioc) if (!mrioc->pel_abort_cmd.reply) goto out_failed; - mrioc->dev_handle_bitmap_sz = mrioc->facts.max_devhandle / 8; - if (mrioc->facts.max_devhandle % 8) - mrioc->dev_handle_bitmap_sz++; - mrioc->removepend_bitmap = kzalloc(mrioc->dev_handle_bitmap_sz, - GFP_KERNEL); + mrioc->dev_handle_bitmap_bits = mrioc->facts.max_devhandle; + mrioc->removepend_bitmap = bitmap_zalloc(mrioc->dev_handle_bitmap_bits, + GFP_KERNEL); if (!mrioc->removepend_bitmap) goto out_failed; - mrioc->devrem_bitmap_sz = MPI3MR_NUM_DEVRMCMD / 8; - if (MPI3MR_NUM_DEVRMCMD % 8) - mrioc->devrem_bitmap_sz++; - mrioc->devrem_bitmap = kzalloc(mrioc->devrem_bitmap_sz, - GFP_KERNEL); + mrioc->devrem_bitmap = bitmap_zalloc(MPI3MR_NUM_DEVRMCMD, GFP_KERNEL); if (!mrioc->devrem_bitmap) goto out_failed; - mrioc->evtack_cmds_bitmap_sz = MPI3MR_NUM_EVTACKCMD / 8; - if (MPI3MR_NUM_EVTACKCMD % 8) - mrioc->evtack_cmds_bitmap_sz++; - mrioc->evtack_cmds_bitmap = kzalloc(mrioc->evtack_cmds_bitmap_sz, - GFP_KERNEL); + mrioc->evtack_cmds_bitmap = bitmap_zalloc(MPI3MR_NUM_EVTACKCMD, + GFP_KERNEL); if (!mrioc->evtack_cmds_bitmap) goto out_failed; @@ -3415,10 +3403,7 @@ static int mpi3mr_alloc_chain_bufs(struct mpi3mr_ioc *mrioc) if (!mrioc->chain_sgl_list[i].addr) goto out_failed; } - mrioc->chain_bitmap_sz = num_chains / 8; - if (num_chains % 8) - mrioc->chain_bitmap_sz++; - mrioc->chain_bitmap = kzalloc(mrioc->chain_bitmap_sz, GFP_KERNEL); + mrioc->chain_bitmap = bitmap_zalloc(num_chains, GFP_KERNEL); if (!mrioc->chain_bitmap) goto out_failed; return retval; @@ -4189,10 +4174,11 @@ void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc) for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) memset(mrioc->evtack_cmds[i].reply, 0, sizeof(*mrioc->evtack_cmds[i].reply)); - memset(mrioc->removepend_bitmap, 0, mrioc->dev_handle_bitmap_sz); - memset(mrioc->devrem_bitmap, 0, mrioc->devrem_bitmap_sz); - memset(mrioc->evtack_cmds_bitmap, 0, - mrioc->evtack_cmds_bitmap_sz); + bitmap_clear(mrioc->removepend_bitmap, 0, + mrioc->dev_handle_bitmap_bits); + bitmap_clear(mrioc->devrem_bitmap, 0, MPI3MR_NUM_DEVRMCMD); + bitmap_clear(mrioc->evtack_cmds_bitmap, 0, + MPI3MR_NUM_EVTACKCMD); } for (i = 0; i < mrioc->num_queues; i++) { @@ -4318,16 +4304,16 @@ void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc) mrioc->evtack_cmds[i].reply = NULL; } - kfree(mrioc->removepend_bitmap); + bitmap_free(mrioc->removepend_bitmap); mrioc->removepend_bitmap = NULL; - kfree(mrioc->devrem_bitmap); + bitmap_free(mrioc->devrem_bitmap); mrioc->devrem_bitmap = NULL; - kfree(mrioc->evtack_cmds_bitmap); + bitmap_free(mrioc->evtack_cmds_bitmap); mrioc->evtack_cmds_bitmap = NULL; - kfree(mrioc->chain_bitmap); + bitmap_free(mrioc->chain_bitmap); mrioc->chain_bitmap = NULL; kfree(mrioc->transport_cmds.reply); @@ -4886,9 +4872,10 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc, mpi3mr_flush_delayed_cmd_lists(mrioc); mpi3mr_flush_drv_cmds(mrioc); - memset(mrioc->devrem_bitmap, 0, mrioc->devrem_bitmap_sz); - memset(mrioc->removepend_bitmap, 0, mrioc->dev_handle_bitmap_sz); - memset(mrioc->evtack_cmds_bitmap, 0, mrioc->evtack_cmds_bitmap_sz); + bitmap_clear(mrioc->devrem_bitmap, 0, MPI3MR_NUM_DEVRMCMD); + bitmap_clear(mrioc->removepend_bitmap, 0, + mrioc->dev_handle_bitmap_bits); + bitmap_clear(mrioc->evtack_cmds_bitmap, 0, MPI3MR_NUM_EVTACKCMD); mpi3mr_flush_host_io(mrioc); mpi3mr_cleanup_fwevt_list(mrioc); mpi3mr_invalidate_devhandles(mrioc); diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index 3306de7170f6..6eaeba41072c 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -4952,6 +4952,10 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id) mpi3mr_init_drv_cmd(&mrioc->dev_rmhs_cmds[i], MPI3MR_HOSTTAG_DEVRMCMD_MIN + i); + for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) + mpi3mr_init_drv_cmd(&mrioc->evtack_cmds[i], + MPI3MR_HOSTTAG_EVTACKCMD_MIN + i); + if (pdev->revision) mrioc->enable_segqueue = true; diff --git a/drivers/scsi/mpi3mr/mpi3mr_transport.c b/drivers/scsi/mpi3mr/mpi3mr_transport.c index 3fc897336b5e..3b61815979da 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_transport.c +++ b/drivers/scsi/mpi3mr/mpi3mr_transport.c @@ -1280,7 +1280,7 @@ void mpi3mr_sas_host_add(struct mpi3mr_ioc *mrioc) if (mrioc->sas_hba.enclosure_handle) { if (!(mpi3mr_cfg_get_enclosure_pg0(mrioc, &ioc_status, - &encl_pg0, sizeof(dev_pg0), + &encl_pg0, sizeof(encl_pg0), MPI3_ENCLOS_PGAD_FORM_HANDLE, mrioc->sas_hba.enclosure_handle)) && (ioc_status == MPI3_IOCSTATUS_SUCCESS)) diff --git a/drivers/scsi/qedi/qedi_dbg.h b/drivers/scsi/qedi/qedi_dbg.h index 37d084086fd4..fdda12ef13b0 100644 --- a/drivers/scsi/qedi/qedi_dbg.h +++ b/drivers/scsi/qedi/qedi_dbg.h @@ -11,7 +11,6 @@ #include <linux/kernel.h> #include <linux/compiler.h> #include <linux/string.h> -#include <linux/version.h> #include <linux/pci.h> #include <linux/delay.h> #include <scsi/scsi_transport.h> diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 46e8b38603f0..030625ebb4e6 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -45,7 +45,7 @@ qla27xx_process_purex_fpin(struct scsi_qla_host *vha, struct purex_item *item) ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x508f, pkt, pkt_size); - fc_host_fpin_rcv(vha->host, pkt_size, (char *)pkt); + fc_host_fpin_rcv(vha->host, pkt_size, (char *)pkt, 0); } const char *const port_state_str[] = { diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index abe93ec8b7d0..b7c569a42aa4 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -229,6 +229,7 @@ int scsi_execute_cmd(struct scsi_device *sdev, const unsigned char *cmd, scmd->cmd_len = COMMAND_SIZE(cmd[0]); memcpy(scmd->cmnd, cmd, scmd->cmd_len); scmd->allowed = retries; + scmd->flags |= args->scmd_flags; req->timeout = timeout; req->rq_flags |= RQF_QUIET; diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 0965f8a7134f..f12e9467ebb4 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -137,6 +137,7 @@ static const struct { { FCH_EVT_PORT_FABRIC, "port_fabric" }, { FCH_EVT_LINK_UNKNOWN, "link_unknown" }, { FCH_EVT_LINK_FPIN, "link_FPIN" }, + { FCH_EVT_LINK_FPIN_ACK, "link_FPIN_ACK" }, { FCH_EVT_VENDOR_UNIQUE, "vendor_unique" }, }; fc_enum_name_search(host_event_code, fc_host_event_code, @@ -894,17 +895,20 @@ fc_fpin_congn_stats_update(struct Scsi_Host *shost, * @shost: host the FPIN was received on * @fpin_len: length of FPIN payload, in bytes * @fpin_buf: pointer to FPIN payload - * + * @event_acknowledge: 1, if LLDD handles this event. * Notes: * This routine assumes no locks are held on entry. */ void -fc_host_fpin_rcv(struct Scsi_Host *shost, u32 fpin_len, char *fpin_buf) +fc_host_fpin_rcv(struct Scsi_Host *shost, u32 fpin_len, char *fpin_buf, + u8 event_acknowledge) { struct fc_els_fpin *fpin = (struct fc_els_fpin *)fpin_buf; struct fc_tlv_desc *tlv; u32 desc_cnt = 0, bytes_remain; u32 dtag; + enum fc_host_event_code event_code = + event_acknowledge ? FCH_EVT_LINK_FPIN_ACK : FCH_EVT_LINK_FPIN; /* Update Statistics */ tlv = (struct fc_tlv_desc *)&fpin->fpin_desc[0]; @@ -934,7 +938,7 @@ fc_host_fpin_rcv(struct Scsi_Host *shost, u32 fpin_len, char *fpin_buf) } fc_host_post_fc_event(shost, fc_get_event_number(), - FCH_EVT_LINK_FPIN, fpin_len, fpin_buf, 0); + event_code, fpin_len, fpin_buf, 0); } EXPORT_SYMBOL(fc_host_fpin_rcv); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index a38c71511bc9..4f28dd617eca 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -121,7 +121,6 @@ static void scsi_disk_release(struct device *cdev); static DEFINE_IDA(sd_index_ida); -static struct kmem_cache *sd_cdb_cache; static mempool_t *sd_page_pool; static struct lock_class_key sd_bio_compl_lkclass; @@ -2252,23 +2251,20 @@ static void sd_config_protection(struct scsi_disk *sdkp) { struct scsi_device *sdp = sdkp->device; - if (!sdkp->first_scan) - return; - sd_dif_config_host(sdkp); if (!sdkp->protection_type) return; if (!scsi_host_dif_capable(sdp->host, sdkp->protection_type)) { - sd_printk(KERN_NOTICE, sdkp, - "Disabling DIF Type %u protection\n", - sdkp->protection_type); + sd_first_printk(KERN_NOTICE, sdkp, + "Disabling DIF Type %u protection\n", + sdkp->protection_type); sdkp->protection_type = 0; } - sd_printk(KERN_NOTICE, sdkp, "Enabling DIF Type %u protection\n", - sdkp->protection_type); + sd_first_printk(KERN_NOTICE, sdkp, "Enabling DIF Type %u protection\n", + sdkp->protection_type); } static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp, @@ -3851,19 +3847,11 @@ static int __init init_sd(void) if (err) goto err_out; - sd_cdb_cache = kmem_cache_create("sd_ext_cdb", SD_EXT_CDB_SIZE, - 0, 0, NULL); - if (!sd_cdb_cache) { - printk(KERN_ERR "sd: can't init extended cdb cache\n"); - err = -ENOMEM; - goto err_out_class; - } - sd_page_pool = mempool_create_page_pool(SD_MEMPOOL_SIZE, 0); if (!sd_page_pool) { printk(KERN_ERR "sd: can't init discard page pool\n"); err = -ENOMEM; - goto err_out_cache; + goto err_out_class; } err = scsi_register_driver(&sd_template.gendrv); @@ -3874,10 +3862,6 @@ static int __init init_sd(void) err_out_driver: mempool_destroy(sd_page_pool); - -err_out_cache: - kmem_cache_destroy(sd_cdb_cache); - err_out_class: class_unregister(&sd_disk_class); err_out: @@ -3899,7 +3883,6 @@ static void __exit exit_sd(void) scsi_unregister_driver(&sd_template.gendrv); mempool_destroy(sd_page_pool); - kmem_cache_destroy(sd_cdb_cache); class_unregister(&sd_disk_class); diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c index 968993ee6d5d..1df847b5f747 100644 --- a/drivers/scsi/sd_dif.c +++ b/drivers/scsi/sd_dif.c @@ -39,8 +39,10 @@ void sd_dif_config_host(struct scsi_disk *sdkp) dif = 0; dix = 1; } - if (!dix) + if (!dix) { + blk_integrity_unregister(disk); return; + } memset(&bi, 0, sizeof(bi)); @@ -72,9 +74,9 @@ void sd_dif_config_host(struct scsi_disk *sdkp) bi.tag_size = sizeof(u16); } - sd_printk(KERN_NOTICE, sdkp, - "Enabling DIX %s, application tag size %u bytes\n", - bi.profile->name, bi.tag_size); + sd_first_printk(KERN_NOTICE, sdkp, + "Enabling DIX %s, application tag size %u bytes\n", + bi.profile->name, bi.tag_size); out: blk_integrity_register(disk, &bi); } diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c index 869ca9c7f23f..b11a9162e73a 100644 --- a/drivers/scsi/ses.c +++ b/drivers/scsi/ses.c @@ -439,8 +439,8 @@ int ses_match_host(struct enclosure_device *edev, void *data) } #endif /* 0 */ -static void ses_process_descriptor(struct enclosure_component *ecomp, - unsigned char *desc) +static int ses_process_descriptor(struct enclosure_component *ecomp, + unsigned char *desc, int max_desc_len) { int eip = desc[0] & 0x10; int invalid = desc[0] & 0x80; @@ -451,22 +451,32 @@ static void ses_process_descriptor(struct enclosure_component *ecomp, unsigned char *d; if (invalid) - return; + return 0; switch (proto) { case SCSI_PROTOCOL_FCP: if (eip) { + if (max_desc_len <= 7) + return 1; d = desc + 4; slot = d[3]; } break; case SCSI_PROTOCOL_SAS: + if (eip) { + if (max_desc_len <= 27) + return 1; d = desc + 4; slot = d[3]; d = desc + 8; - } else + } else { + if (max_desc_len <= 23) + return 1; d = desc + 4; + } + + /* only take the phy0 addr */ addr = (u64)d[12] << 56 | (u64)d[13] << 48 | @@ -483,6 +493,8 @@ static void ses_process_descriptor(struct enclosure_component *ecomp, } ecomp->slot = slot; scomp->addr = addr; + + return 0; } struct efd { @@ -555,7 +567,7 @@ static void ses_enclosure_data_process(struct enclosure_device *edev, /* skip past overall descriptor */ desc_ptr += len + 4; } - if (ses_dev->page10) + if (ses_dev->page10 && ses_dev->page10_len > 9) addl_desc_ptr = ses_dev->page10 + 8; type_ptr = ses_dev->page1_types; components = 0; @@ -563,17 +575,22 @@ static void ses_enclosure_data_process(struct enclosure_device *edev, for (j = 0; j < type_ptr[1]; j++) { char *name = NULL; struct enclosure_component *ecomp; + int max_desc_len; if (desc_ptr) { - if (desc_ptr >= buf + page7_len) { + if (desc_ptr + 3 >= buf + page7_len) { desc_ptr = NULL; } else { len = (desc_ptr[2] << 8) + desc_ptr[3]; desc_ptr += 4; - /* Add trailing zero - pushes into - * reserved space */ - desc_ptr[len] = '\0'; - name = desc_ptr; + if (desc_ptr + len > buf + page7_len) + desc_ptr = NULL; + else { + /* Add trailing zero - pushes into + * reserved space */ + desc_ptr[len] = '\0'; + name = desc_ptr; + } } } if (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE || @@ -589,10 +606,14 @@ static void ses_enclosure_data_process(struct enclosure_device *edev, ecomp = &edev->component[components++]; if (!IS_ERR(ecomp)) { - if (addl_desc_ptr) - ses_process_descriptor( - ecomp, - addl_desc_ptr); + if (addl_desc_ptr) { + max_desc_len = ses_dev->page10_len - + (addl_desc_ptr - ses_dev->page10); + if (ses_process_descriptor(ecomp, + addl_desc_ptr, + max_desc_len)) + addl_desc_ptr = NULL; + } if (create) enclosure_component_register( ecomp); @@ -609,9 +630,11 @@ static void ses_enclosure_data_process(struct enclosure_device *edev, /* these elements are optional */ type_ptr[0] == ENCLOSURE_COMPONENT_SCSI_TARGET_PORT || type_ptr[0] == ENCLOSURE_COMPONENT_SCSI_INITIATOR_PORT || - type_ptr[0] == ENCLOSURE_COMPONENT_CONTROLLER_ELECTRONICS)) + type_ptr[0] == ENCLOSURE_COMPONENT_CONTROLLER_ELECTRONICS)) { addl_desc_ptr += addl_desc_ptr[1] + 2; - + if (addl_desc_ptr + 1 >= ses_dev->page10 + ses_dev->page10_len) + addl_desc_ptr = NULL; + } } } kfree(buf); @@ -710,6 +733,12 @@ static int ses_intf_add(struct device *cdev, type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE) components += type_ptr[1]; } + + if (components == 0) { + sdev_printk(KERN_WARNING, sdev, "enclosure has no enumerated components\n"); + goto err_free; + } + ses_dev->page1 = buf; ses_dev->page1_len = len; buf = NULL; @@ -833,7 +862,8 @@ static void ses_intf_remove_enclosure(struct scsi_device *sdev) kfree(ses_dev->page2); kfree(ses_dev); - kfree(edev->component[0].scratch); + if (edev->components) + kfree(edev->component[0].scratch); put_device(&edev->edev); enclosure_unregister(edev); diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 276a82b2e5ee..172d25fef740 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -1409,6 +1409,13 @@ static int ufshcd_devfreq_target(struct device *dev, struct ufs_clk_info *clki; unsigned long irq_flags; + /* + * Skip devfreq if UFS initialization is not finished. + * Otherwise ufs could be in a inconsistent state. + */ + if (!smp_load_acquire(&hba->logical_unit_scan_finished)) + return 0; + if (!ufshcd_is_clkscaling_supported(hba)) return -EINVAL; @@ -8392,22 +8399,6 @@ static int ufshcd_add_lus(struct ufs_hba *hba) if (ret) goto out; - /* Initialize devfreq after UFS device is detected */ - if (ufshcd_is_clkscaling_supported(hba)) { - memcpy(&hba->clk_scaling.saved_pwr_info.info, - &hba->pwr_info, - sizeof(struct ufs_pa_layer_attr)); - hba->clk_scaling.saved_pwr_info.is_valid = true; - hba->clk_scaling.is_allowed = true; - - ret = ufshcd_devfreq_init(hba); - if (ret) - goto out; - - hba->clk_scaling.is_enabled = true; - ufshcd_init_clk_scaling_sysfs(hba); - } - ufs_bsg_probe(hba); ufshpb_init(hba); scsi_scan_host(hba->host); @@ -8538,7 +8529,9 @@ static int ufshcd_device_init(struct ufs_hba *hba, bool init_dev_params) return ret; if (is_mcq_supported(hba) && !hba->scsi_host_added) { ret = ufshcd_alloc_mcq(hba); - if (ret) { + if (!ret) { + ufshcd_config_mcq(hba); + } else { /* Continue with SDB mode */ use_mcq_mode = false; dev_err(hba->dev, "MCQ mode is disabled, err=%d\n", @@ -8550,10 +8543,10 @@ static int ufshcd_device_init(struct ufs_hba *hba, bool init_dev_params) return ret; } hba->scsi_host_added = true; - } - /* MCQ may be disabled if ufshcd_alloc_mcq() fails */ - if (is_mcq_supported(hba) && use_mcq_mode) + } else if (is_mcq_supported(hba)) { + /* UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH is set */ ufshcd_config_mcq(hba); + } } ufshcd_tune_unipro_params(hba); @@ -8677,6 +8670,12 @@ out: if (ret) { pm_runtime_put_sync(hba->dev); ufshcd_hba_exit(hba); + } else { + /* + * Make sure that when reader code sees UFS initialization has finished, + * all initialization steps have really been executed. + */ + smp_store_release(&hba->logical_unit_scan_finished, true); } } @@ -9143,34 +9142,15 @@ static int ufshcd_execute_start_stop(struct scsi_device *sdev, enum ufs_dev_pwr_mode pwr_mode, struct scsi_sense_hdr *sshdr) { - unsigned char cdb[6] = { START_STOP, 0, 0, 0, pwr_mode << 4, 0 }; - struct request *req; - struct scsi_cmnd *scmd; - int ret; - - req = scsi_alloc_request(sdev->request_queue, REQ_OP_DRV_IN, - BLK_MQ_REQ_PM); - if (IS_ERR(req)) - return PTR_ERR(req); - - scmd = blk_mq_rq_to_pdu(req); - scmd->cmd_len = COMMAND_SIZE(cdb[0]); - memcpy(scmd->cmnd, cdb, scmd->cmd_len); - scmd->allowed = 0/*retries*/; - scmd->flags |= SCMD_FAIL_IF_RECOVERING; - req->timeout = 1 * HZ; - req->rq_flags |= RQF_PM | RQF_QUIET; - - blk_execute_rq(req, /*at_head=*/true); - - if (sshdr) - scsi_normalize_sense(scmd->sense_buffer, scmd->sense_len, - sshdr); - ret = scmd->result; - - blk_mq_free_request(req); + const unsigned char cdb[6] = { START_STOP, 0, 0, 0, pwr_mode << 4, 0 }; + const struct scsi_exec_args args = { + .sshdr = sshdr, + .req_flags = BLK_MQ_REQ_PM, + .scmd_flags = SCMD_FAIL_IF_RECOVERING, + }; - return ret; + return scsi_execute_cmd(sdev, cdb, REQ_OP_DRV_IN, /*buffer=*/NULL, + /*bufflen=*/0, /*timeout=*/HZ, /*retries=*/0, &args); } /** @@ -10336,12 +10316,30 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) */ ufshcd_set_ufs_dev_active(hba); + /* Initialize devfreq */ + if (ufshcd_is_clkscaling_supported(hba)) { + memcpy(&hba->clk_scaling.saved_pwr_info.info, + &hba->pwr_info, + sizeof(struct ufs_pa_layer_attr)); + hba->clk_scaling.saved_pwr_info.is_valid = true; + hba->clk_scaling.is_allowed = true; + + err = ufshcd_devfreq_init(hba); + if (err) + goto rpm_put_sync; + + hba->clk_scaling.is_enabled = true; + ufshcd_init_clk_scaling_sysfs(hba); + } + async_schedule(ufshcd_async_scan, hba); ufs_sysfs_add_nodes(hba->dev); device_enable_async_suspend(dev); return 0; +rpm_put_sync: + pm_runtime_put_sync(dev); free_tmf_queue: blk_mq_destroy_queue(hba->tmf_queue); blk_put_queue(hba->tmf_queue); diff --git a/drivers/ufs/host/Kconfig b/drivers/ufs/host/Kconfig index 663881437921..8793e3433580 100644 --- a/drivers/ufs/host/Kconfig +++ b/drivers/ufs/host/Kconfig @@ -48,7 +48,7 @@ config SCSI_UFS_CDNS_PLATFORM config SCSI_UFS_DWC_TC_PLATFORM tristate "DesignWare platform support using a G210 Test Chip" - depends on SCSI_UFSHCD_PLATFORM + depends on OF && SCSI_UFSHCD_PLATFORM help Synopsys Test Chip is a PHY for prototyping purposes. diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c index 21d9b047539f..73e217260390 100644 --- a/drivers/ufs/host/ufs-mediatek.c +++ b/drivers/ufs/host/ufs-mediatek.c @@ -1613,6 +1613,7 @@ static int ufs_mtk_system_resume(struct device *dev) } #endif +#ifdef CONFIG_PM static int ufs_mtk_runtime_suspend(struct device *dev) { struct ufs_hba *hba = dev_get_drvdata(dev); @@ -1635,6 +1636,7 @@ static int ufs_mtk_runtime_resume(struct device *dev) return ufshcd_runtime_resume(dev); } +#endif static const struct dev_pm_ops ufs_mtk_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(ufs_mtk_system_suspend, diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index b7a36ebd0f2f..e2eff66eefab 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -667,11 +667,21 @@ static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses, int match_target_ip(struct TCP_Server_Info *server, const char *share, size_t share_len, bool *result); - -int cifs_dfs_query_info_nonascii_quirk(const unsigned int xid, - struct cifs_tcon *tcon, - struct cifs_sb_info *cifs_sb, - const char *dfs_link_path); +int cifs_inval_name_dfs_link_error(const unsigned int xid, + struct cifs_tcon *tcon, + struct cifs_sb_info *cifs_sb, + const char *full_path, + bool *islink); +#else +static inline int cifs_inval_name_dfs_link_error(const unsigned int xid, + struct cifs_tcon *tcon, + struct cifs_sb_info *cifs_sb, + const char *full_path, + bool *islink) +{ + *islink = false; + return 0; +} #endif static inline int cifs_create_options(struct cifs_sb_info *cifs_sb, int options) @@ -684,5 +694,6 @@ static inline int cifs_create_options(struct cifs_sb_info *cifs_sb, int options) struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon); void cifs_put_tcon_super(struct super_block *sb); +int cifs_wait_for_server_reconnect(struct TCP_Server_Info *server, bool retry); #endif /* _CIFSPROTO_H */ diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index a24e4ddf8043..a43c78396dd8 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -72,7 +72,6 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) struct cifs_ses *ses; struct TCP_Server_Info *server; struct nls_table *nls_codepage; - int retries; /* * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for @@ -102,45 +101,9 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) } spin_unlock(&tcon->tc_lock); - retries = server->nr_targets; - - /* - * Give demultiplex thread up to 10 seconds to each target available for - * reconnect -- should be greater than cifs socket timeout which is 7 - * seconds. - */ - while (server->tcpStatus == CifsNeedReconnect) { - rc = wait_event_interruptible_timeout(server->response_q, - (server->tcpStatus != CifsNeedReconnect), - 10 * HZ); - if (rc < 0) { - cifs_dbg(FYI, "%s: aborting reconnect due to a received signal by the process\n", - __func__); - return -ERESTARTSYS; - } - - /* are we still trying to reconnect? */ - spin_lock(&server->srv_lock); - if (server->tcpStatus != CifsNeedReconnect) { - spin_unlock(&server->srv_lock); - break; - } - spin_unlock(&server->srv_lock); - - if (retries && --retries) - continue; - - /* - * on "soft" mounts we wait once. Hard mounts keep - * retrying until process is killed or server comes - * back on-line - */ - if (!tcon->retry) { - cifs_dbg(FYI, "gave up waiting on reconnect in smb_init\n"); - return -EHOSTDOWN; - } - retries = server->nr_targets; - } + rc = cifs_wait_for_server_reconnect(server, tcon->retry); + if (rc) + return rc; spin_lock(&ses->chan_lock); if (!cifs_chan_needs_reconnect(ses, server) && !tcon->need_reconnect) { diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index ec020d860be3..5233f14f0636 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1294,7 +1294,8 @@ cifs_match_ipaddr(struct sockaddr *srcaddr, struct sockaddr *rhs) case AF_INET6: { struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr; struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs; - return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr); + return (ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr) + && saddr6->sin6_scope_id == vaddr6->sin6_scope_id); } default: WARN_ON(1); @@ -1343,32 +1344,8 @@ match_port(struct TCP_Server_Info *server, struct sockaddr *addr) static bool match_server_address(struct TCP_Server_Info *server, struct sockaddr *addr) { - switch (addr->sa_family) { - case AF_INET: { - struct sockaddr_in *addr4 = (struct sockaddr_in *)addr; - struct sockaddr_in *srv_addr4 = - (struct sockaddr_in *)&server->dstaddr; - - if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr) - return false; - break; - } - case AF_INET6: { - struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr; - struct sockaddr_in6 *srv_addr6 = - (struct sockaddr_in6 *)&server->dstaddr; - - if (!ipv6_addr_equal(&addr6->sin6_addr, - &srv_addr6->sin6_addr)) - return false; - if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id) - return false; - break; - } - default: - WARN_ON(1); - return false; /* don't expect to be here */ - } + if (!cifs_match_ipaddr(addr, (struct sockaddr *)&server->dstaddr)) + return false; return true; } diff --git a/fs/cifs/file.c b/fs/cifs/file.c index ebfcaae8c437..4d4a2d82636d 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -52,6 +52,8 @@ static void cifs_undirty_folios(struct inode *inode, loff_t start, unsigned int end = (start + len - 1) / PAGE_SIZE; xas_for_each_marked(&xas, folio, end, PAGECACHE_TAG_DIRTY) { + if (xas_retry(&xas, folio)) + continue; xas_pause(&xas); rcu_read_unlock(); folio_lock(folio); @@ -81,6 +83,8 @@ void cifs_pages_written_back(struct inode *inode, loff_t start, unsigned int len end = (start + len - 1) / PAGE_SIZE; xas_for_each(&xas, folio, end) { + if (xas_retry(&xas, folio)) + continue; if (!folio_test_writeback(folio)) { WARN_ONCE(1, "bad %x @%llx page %lx %lx\n", len, start, folio_index(folio), end); @@ -112,6 +116,8 @@ void cifs_pages_write_failed(struct inode *inode, loff_t start, unsigned int len end = (start + len - 1) / PAGE_SIZE; xas_for_each(&xas, folio, end) { + if (xas_retry(&xas, folio)) + continue; if (!folio_test_writeback(folio)) { WARN_ONCE(1, "bad %x @%llx page %lx %lx\n", len, start, folio_index(folio), end); @@ -2839,6 +2845,7 @@ err_xid: free_xid(xid); if (rc == 0) { wbc->nr_to_write = count; + rc = len; } else if (is_retryable_error(rc)) { cifs_pages_write_redirty(inode, start, len); } else { @@ -3605,7 +3612,7 @@ static ssize_t __cifs_writev( ctx->nr_pinned_pages = rc; ctx->bv = (void *)ctx->iter.bvec; - ctx->bv_need_unpin = iov_iter_extract_will_pin(&ctx->iter); + ctx->bv_need_unpin = iov_iter_extract_will_pin(from); } else if ((iov_iter_is_bvec(from) || iov_iter_is_kvec(from)) && !is_sync_kiocb(iocb)) { /* @@ -4141,7 +4148,7 @@ static ssize_t __cifs_readv( ctx->nr_pinned_pages = rc; ctx->bv = (void *)ctx->iter.bvec; - ctx->bv_need_unpin = iov_iter_extract_will_pin(&ctx->iter); + ctx->bv_need_unpin = iov_iter_extract_will_pin(to); ctx->should_dirty = true; } else if ((iov_iter_is_bvec(to) || iov_iter_is_kvec(to)) && !is_sync_kiocb(iocb)) { diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 2905734eb289..a0d286ee723d 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -21,6 +21,7 @@ #include "cifsfs.h" #ifdef CONFIG_CIFS_DFS_UPCALL #include "dns_resolve.h" +#include "dfs_cache.h" #endif #include "fs_context.h" #include "cached_dir.h" @@ -1198,4 +1199,114 @@ int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; return 0; } + +/* + * Handle weird Windows SMB server behaviour. It responds with + * STATUS_OBJECT_NAME_INVALID code to SMB2 QUERY_INFO request for + * "\<server>\<dfsname>\<linkpath>" DFS reference, where <dfsname> contains + * non-ASCII unicode symbols. + */ +int cifs_inval_name_dfs_link_error(const unsigned int xid, + struct cifs_tcon *tcon, + struct cifs_sb_info *cifs_sb, + const char *full_path, + bool *islink) +{ + struct cifs_ses *ses = tcon->ses; + size_t len; + char *path; + char *ref_path; + + *islink = false; + + /* + * Fast path - skip check when @full_path doesn't have a prefix path to + * look up or tcon is not DFS. + */ + if (strlen(full_path) < 2 || !cifs_sb || + (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) || + !is_tcon_dfs(tcon) || !ses->server->origin_fullpath) + return 0; + + /* + * Slow path - tcon is DFS and @full_path has prefix path, so attempt + * to get a referral to figure out whether it is an DFS link. + */ + len = strnlen(tcon->tree_name, MAX_TREE_SIZE + 1) + strlen(full_path) + 1; + path = kmalloc(len, GFP_KERNEL); + if (!path) + return -ENOMEM; + + scnprintf(path, len, "%s%s", tcon->tree_name, full_path); + ref_path = dfs_cache_canonical_path(path + 1, cifs_sb->local_nls, + cifs_remap(cifs_sb)); + kfree(path); + + if (IS_ERR(ref_path)) { + if (PTR_ERR(ref_path) != -EINVAL) + return PTR_ERR(ref_path); + } else { + struct dfs_info3_param *refs = NULL; + int num_refs = 0; + + /* + * XXX: we are not using dfs_cache_find() here because we might + * end filling all the DFS cache and thus potentially + * removing cached DFS targets that the client would eventually + * need during failover. + */ + if (ses->server->ops->get_dfs_refer && + !ses->server->ops->get_dfs_refer(xid, ses, ref_path, &refs, + &num_refs, cifs_sb->local_nls, + cifs_remap(cifs_sb))) + *islink = refs[0].server_type == DFS_TYPE_LINK; + free_dfs_info_array(refs, num_refs); + kfree(ref_path); + } + return 0; +} #endif + +int cifs_wait_for_server_reconnect(struct TCP_Server_Info *server, bool retry) +{ + int timeout = 10; + int rc; + + spin_lock(&server->srv_lock); + if (server->tcpStatus != CifsNeedReconnect) { + spin_unlock(&server->srv_lock); + return 0; + } + timeout *= server->nr_targets; + spin_unlock(&server->srv_lock); + + /* + * Give demultiplex thread up to 10 seconds to each target available for + * reconnect -- should be greater than cifs socket timeout which is 7 + * seconds. + * + * On "soft" mounts we wait once. Hard mounts keep retrying until + * process is killed or server comes back on-line. + */ + do { + rc = wait_event_interruptible_timeout(server->response_q, + (server->tcpStatus != CifsNeedReconnect), + timeout * HZ); + if (rc < 0) { + cifs_dbg(FYI, "%s: aborting reconnect due to received signal\n", + __func__); + return -ERESTARTSYS; + } + + /* are we still trying to reconnect? */ + spin_lock(&server->srv_lock); + if (server->tcpStatus != CifsNeedReconnect) { + spin_unlock(&server->srv_lock); + return 0; + } + spin_unlock(&server->srv_lock); + } while (retry); + + cifs_dbg(FYI, "%s: gave up waiting on reconnect\n", __func__); + return -EHOSTDOWN; +} diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c index 37b4cd59245d..9b956294e864 100644 --- a/fs/cifs/smb2inode.c +++ b/fs/cifs/smb2inode.c @@ -527,12 +527,13 @@ int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const char *full_path, struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse) { - int rc; __u32 create_options = 0; struct cifsFileInfo *cfile; struct cached_fid *cfid = NULL; struct kvec err_iov[3] = {}; int err_buftype[3] = {}; + bool islink; + int rc, rc2; *adjust_tz = false; *reparse = false; @@ -580,15 +581,15 @@ int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, SMB2_OP_QUERY_INFO, cfile, NULL, NULL, NULL, NULL); goto out; - } else if (rc != -EREMOTE && IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) && - hdr->Status == STATUS_OBJECT_NAME_INVALID) { - /* - * Handle weird Windows SMB server behaviour. It responds with - * STATUS_OBJECT_NAME_INVALID code to SMB2 QUERY_INFO request - * for "\<server>\<dfsname>\<linkpath>" DFS reference, - * where <dfsname> contains non-ASCII unicode symbols. - */ - rc = -EREMOTE; + } else if (rc != -EREMOTE && hdr->Status == STATUS_OBJECT_NAME_INVALID) { + rc2 = cifs_inval_name_dfs_link_error(xid, tcon, cifs_sb, + full_path, &islink); + if (rc2) { + rc = rc2; + goto out; + } + if (islink) + rc = -EREMOTE; } if (rc == -EREMOTE && IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) && cifs_sb && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)) diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index f79b075f2992..6dfb865ee9d7 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -796,7 +796,6 @@ static int smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const char *full_path) { - int rc; __le16 *utf16_path; __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; int err_buftype = CIFS_NO_BUFFER; @@ -804,6 +803,8 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon, struct kvec err_iov = {}; struct cifs_fid fid; struct cached_fid *cfid; + bool islink; + int rc, rc2; rc = open_cached_dir(xid, tcon, full_path, cifs_sb, true, &cfid); if (!rc) { @@ -833,15 +834,17 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon, if (unlikely(!hdr || err_buftype == CIFS_NO_BUFFER)) goto out; - /* - * Handle weird Windows SMB server behaviour. It responds with - * STATUS_OBJECT_NAME_INVALID code to SMB2 QUERY_INFO request - * for "\<server>\<dfsname>\<linkpath>" DFS reference, - * where <dfsname> contains non-ASCII unicode symbols. - */ - if (rc != -EREMOTE && IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) && - hdr->Status == STATUS_OBJECT_NAME_INVALID) - rc = -EREMOTE; + + if (rc != -EREMOTE && hdr->Status == STATUS_OBJECT_NAME_INVALID) { + rc2 = cifs_inval_name_dfs_link_error(xid, tcon, cifs_sb, + full_path, &islink); + if (rc2) { + rc = rc2; + goto out; + } + if (islink) + rc = -EREMOTE; + } if (rc == -EREMOTE && IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) && cifs_sb && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)) rc = -EOPNOTSUPP; diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index ca9d7110ddcb..0e53265e1462 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -139,66 +139,6 @@ out: return; } -static int wait_for_server_reconnect(struct TCP_Server_Info *server, - __le16 smb2_command, bool retry) -{ - int timeout = 10; - int rc; - - spin_lock(&server->srv_lock); - if (server->tcpStatus != CifsNeedReconnect) { - spin_unlock(&server->srv_lock); - return 0; - } - timeout *= server->nr_targets; - spin_unlock(&server->srv_lock); - - /* - * Return to caller for TREE_DISCONNECT and LOGOFF and CLOSE - * here since they are implicitly done when session drops. - */ - switch (smb2_command) { - /* - * BB Should we keep oplock break and add flush to exceptions? - */ - case SMB2_TREE_DISCONNECT: - case SMB2_CANCEL: - case SMB2_CLOSE: - case SMB2_OPLOCK_BREAK: - return -EAGAIN; - } - - /* - * Give demultiplex thread up to 10 seconds to each target available for - * reconnect -- should be greater than cifs socket timeout which is 7 - * seconds. - * - * On "soft" mounts we wait once. Hard mounts keep retrying until - * process is killed or server comes back on-line. - */ - do { - rc = wait_event_interruptible_timeout(server->response_q, - (server->tcpStatus != CifsNeedReconnect), - timeout * HZ); - if (rc < 0) { - cifs_dbg(FYI, "%s: aborting reconnect due to received signal\n", - __func__); - return -ERESTARTSYS; - } - - /* are we still trying to reconnect? */ - spin_lock(&server->srv_lock); - if (server->tcpStatus != CifsNeedReconnect) { - spin_unlock(&server->srv_lock); - return 0; - } - spin_unlock(&server->srv_lock); - } while (retry); - - cifs_dbg(FYI, "%s: gave up waiting on reconnect\n", __func__); - return -EHOSTDOWN; -} - static int smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon, struct TCP_Server_Info *server) @@ -243,7 +183,27 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon, (!tcon->ses->server) || !server) return -EIO; - rc = wait_for_server_reconnect(server, smb2_command, tcon->retry); + spin_lock(&server->srv_lock); + if (server->tcpStatus == CifsNeedReconnect) { + /* + * Return to caller for TREE_DISCONNECT and LOGOFF and CLOSE + * here since they are implicitly done when session drops. + */ + switch (smb2_command) { + /* + * BB Should we keep oplock break and add flush to exceptions? + */ + case SMB2_TREE_DISCONNECT: + case SMB2_CANCEL: + case SMB2_CLOSE: + case SMB2_OPLOCK_BREAK: + spin_unlock(&server->srv_lock); + return -EAGAIN; + } + } + spin_unlock(&server->srv_lock); + + rc = cifs_wait_for_server_reconnect(server, tcon->retry); if (rc) return rc; diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c index 55b6e319a61d..0362ebd4fa0f 100644 --- a/fs/cifs/smbdirect.c +++ b/fs/cifs/smbdirect.c @@ -837,7 +837,7 @@ static int smbd_post_send_iter(struct smbd_connection *info, int data_length; struct smbd_request *request; struct smbd_data_transfer *packet; - int new_credits; + int new_credits = 0; wait_credit: /* Wait for send credits. A SMBD packet needs one credit */ diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index e3d168911dbe..006ef68d7ff6 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c @@ -183,7 +183,7 @@ static void *cramfs_blkdev_read(struct super_block *sb, unsigned int offset, unsigned int len) { struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping; - struct file_ra_state ra; + struct file_ra_state ra = {}; struct page *pages[BLKS_PER_BUF]; unsigned i, blocknr, buffer; unsigned long devsize; diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 122ed89ebf9f..1986b4f18a90 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -295,11 +295,11 @@ static void hfsplus_put_super(struct super_block *sb) hfsplus_sync_fs(sb, 1); } + iput(sbi->alloc_file); + iput(sbi->hidden_dir); hfs_btree_close(sbi->attr_tree); hfs_btree_close(sbi->cat_tree); hfs_btree_close(sbi->ext_tree); - iput(sbi->alloc_file); - iput(sbi->hidden_dir); kfree(sbi->s_vhdr_buf); kfree(sbi->s_backup_vhdr_buf); unload_nls(sbi->nls); diff --git a/fs/netfs/iterator.c b/fs/netfs/iterator.c index f00d43b8ac0a..e9a45dea748a 100644 --- a/fs/netfs/iterator.c +++ b/fs/netfs/iterator.c @@ -134,7 +134,7 @@ static ssize_t netfs_extract_user_to_sg(struct iov_iter *iter, npages = DIV_ROUND_UP(off + len, PAGE_SIZE); sg_max -= npages; - for (; npages < 0; npages--) { + for (; npages > 0; npages--) { struct page *page = *pages; size_t seg = min_t(size_t, PAGE_SIZE - off, len); diff --git a/fs/ocfs2/move_extents.c b/fs/ocfs2/move_extents.c index 192cad0662d8..b1e32ec4a9d4 100644 --- a/fs/ocfs2/move_extents.c +++ b/fs/ocfs2/move_extents.c @@ -105,14 +105,6 @@ static int __ocfs2_move_extent(handle_t *handle, */ replace_rec.e_flags = ext_flags & ~OCFS2_EXT_REFCOUNTED; - ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), - context->et.et_root_bh, - OCFS2_JOURNAL_ACCESS_WRITE); - if (ret) { - mlog_errno(ret); - goto out; - } - ret = ocfs2_split_extent(handle, &context->et, path, index, &replace_rec, context->meta_ac, &context->dealloc); @@ -121,8 +113,6 @@ static int __ocfs2_move_extent(handle_t *handle, goto out; } - ocfs2_journal_dirty(handle, context->et.et_root_bh); - context->new_phys_cpos = new_p_cpos; /* @@ -444,7 +434,7 @@ static int ocfs2_find_victim_alloc_group(struct inode *inode, bg = (struct ocfs2_group_desc *)gd_bh->b_data; if (vict_blkno < (le64_to_cpu(bg->bg_blkno) + - le16_to_cpu(bg->bg_bits))) { + (le16_to_cpu(bg->bg_bits) << bits_per_unit))) { *ret_bh = gd_bh; *vict_bit = (vict_blkno - blkno) >> @@ -559,6 +549,7 @@ static void ocfs2_probe_alloc_group(struct inode *inode, struct buffer_head *bh, last_free_bits++; if (last_free_bits == move_len) { + i -= move_len; *goal_bit = i; *phys_cpos = base_cpos + i; break; @@ -1030,18 +1021,19 @@ int ocfs2_ioctl_move_extents(struct file *filp, void __user *argp) context->range = ⦥ + /* + * ok, the default theshold for the defragmentation + * is 1M, since our maximum clustersize was 1M also. + * any thought? + */ + if (!range.me_threshold) + range.me_threshold = 1024 * 1024; + + if (range.me_threshold > i_size_read(inode)) + range.me_threshold = i_size_read(inode); + if (range.me_flags & OCFS2_MOVE_EXT_FL_AUTO_DEFRAG) { context->auto_defrag = 1; - /* - * ok, the default theshold for the defragmentation - * is 1M, since our maximum clustersize was 1M also. - * any thought? - */ - if (!range.me_threshold) - range.me_threshold = 1024 * 1024; - - if (range.me_threshold > i_size_read(inode)) - range.me_threshold = i_size_read(inode); if (range.me_flags & OCFS2_MOVE_EXT_FL_PART_DEFRAG) context->partial = 1; diff --git a/include/linux/rmap.h b/include/linux/rmap.h index a4570da03e58..b87d01660412 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h @@ -94,7 +94,7 @@ enum ttu_flags { TTU_SPLIT_HUGE_PMD = 0x4, /* split huge PMD if any */ TTU_IGNORE_MLOCK = 0x8, /* ignore mlock */ TTU_SYNC = 0x10, /* avoid racy checks with PVMW_SYNC */ - TTU_IGNORE_HWPOISON = 0x20, /* corrupted page is recoverable */ + TTU_HWPOISON = 0x20, /* do convert pte to hwpoison entry */ TTU_BATCH_FLUSH = 0x40, /* Batch TLB flushes where possible * and caller guarantees they will * do a final flush if necessary */ diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 7e95ec45138f..de310f21406c 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -462,6 +462,7 @@ struct scsi_exec_args { unsigned int sense_len; /* sense buffer len */ struct scsi_sense_hdr *sshdr; /* decoded sense header */ blk_mq_req_flags_t req_flags; /* BLK_MQ_REQ flags */ + int scmd_flags; /* SCMD flags */ int *resid; /* residual length */ }; diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 3dcda19d3520..483513c57597 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -496,6 +496,7 @@ enum fc_host_event_code { FCH_EVT_PORT_FABRIC = 0x204, FCH_EVT_LINK_UNKNOWN = 0x500, FCH_EVT_LINK_FPIN = 0x501, + FCH_EVT_LINK_FPIN_ACK = 0x502, FCH_EVT_VENDOR_UNIQUE = 0xffff, }; @@ -856,7 +857,8 @@ void fc_host_post_fc_event(struct Scsi_Host *shost, u32 event_number, * Note: when calling fc_host_post_fc_event(), vendor_id may be * specified as 0. */ -void fc_host_fpin_rcv(struct Scsi_Host *shost, u32 fpin_len, char *fpin_buf); +void fc_host_fpin_rcv(struct Scsi_Host *shost, u32 fpin_len, char *fpin_buf, + u8 event_acknowledge); struct fc_vport *fc_vport_create(struct Scsi_Host *shost, int channel, struct fc_vport_identifiers *); int fc_vport_terminate(struct fc_vport *vport); diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 3203d35bc8c1..0814ed143864 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -190,6 +190,8 @@ struct snd_soc_component_driver { bool use_dai_pcm_id; /* use DAI link PCM ID as PCM device number */ int be_pcm_base; /* base device ID for all BE PCMs */ + unsigned int start_dma_last; + #ifdef CONFIG_DEBUG_FS const char *debugfs_prefix; #endif diff --git a/include/uapi/scsi/scsi_bsg_mpi3mr.h b/include/uapi/scsi/scsi_bsg_mpi3mr.h index fdc3517f9e19..907d345f04f9 100644 --- a/include/uapi/scsi/scsi_bsg_mpi3mr.h +++ b/include/uapi/scsi/scsi_bsg_mpi3mr.h @@ -455,12 +455,6 @@ struct mpi3mr_bsg_packet { } cmd; }; - -/* MPI3: NVMe Encasulation related definitions */ -#ifndef MPI3_NVME_ENCAP_CMD_MAX -#define MPI3_NVME_ENCAP_CMD_MAX (1) -#endif - struct mpi3_nvme_encapsulated_request { __le16 host_tag; __u8 ioc_use_only02; @@ -474,7 +468,7 @@ struct mpi3_nvme_encapsulated_request { __le16 flags; __le32 data_length; __le32 reserved14[3]; - __le32 command[MPI3_NVME_ENCAP_CMD_MAX]; + __le32 command[]; }; struct mpi3_nvme_encapsulated_error_reply { diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index 431c3afb2ce0..25aab8ec4f86 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -979,6 +979,7 @@ struct ufs_hba { struct completion *uic_async_done; enum ufshcd_state ufshcd_state; + bool logical_unit_scan_finished; u32 eh_flags; u32 intr_mask; u16 ee_ctrl_mask; diff --git a/kernel/panic.c b/kernel/panic.c index 487f5b03bf83..5cfea8302d23 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -212,9 +212,6 @@ static void panic_print_sys_info(bool console_flush) return; } - if (panic_print & PANIC_PRINT_ALL_CPU_BT) - trigger_all_cpu_backtrace(); - if (panic_print & PANIC_PRINT_TASK_INFO) show_state(); @@ -244,6 +241,30 @@ void check_panic_on_warn(const char *origin) origin, limit); } +/* + * Helper that triggers the NMI backtrace (if set in panic_print) + * and then performs the secondary CPUs shutdown - we cannot have + * the NMI backtrace after the CPUs are off! + */ +static void panic_other_cpus_shutdown(bool crash_kexec) +{ + if (panic_print & PANIC_PRINT_ALL_CPU_BT) + trigger_all_cpu_backtrace(); + + /* + * Note that smp_send_stop() is the usual SMP shutdown function, + * which unfortunately may not be hardened to work in a panic + * situation. If we want to do crash dump after notifier calls + * and kmsg_dump, we will need architecture dependent extra + * bits in addition to stopping other CPUs, hence we rely on + * crash_smp_send_stop() for that. + */ + if (!crash_kexec) + smp_send_stop(); + else + crash_smp_send_stop(); +} + /** * panic - halt the system * @fmt: The text string to print @@ -334,23 +355,10 @@ void panic(const char *fmt, ...) * * Bypass the panic_cpu check and call __crash_kexec directly. */ - if (!_crash_kexec_post_notifiers) { + if (!_crash_kexec_post_notifiers) __crash_kexec(NULL); - /* - * Note smp_send_stop is the usual smp shutdown function, which - * unfortunately means it may not be hardened to work in a - * panic situation. - */ - smp_send_stop(); - } else { - /* - * If we want to do crash dump after notifier calls and - * kmsg_dump, we will need architecture dependent extra - * works in addition to stopping other CPUs. - */ - crash_smp_send_stop(); - } + panic_other_cpus_shutdown(_crash_kexec_post_notifiers); /* * Run any panic handlers, including those that might need to diff --git a/kernel/umh.c b/kernel/umh.c index 2a4708277335..60aa9e764a38 100644 --- a/kernel/umh.c +++ b/kernel/umh.c @@ -32,9 +32,6 @@ #include <trace/events/module.h> -#define CAP_BSET (void *)1 -#define CAP_PI (void *)2 - static kernel_cap_t usermodehelper_bset = CAP_FULL_SET; static kernel_cap_t usermodehelper_inheritable = CAP_FULL_SET; static DEFINE_SPINLOCK(umh_sysctl_lock); @@ -512,16 +509,11 @@ static int proc_cap_handler(struct ctl_table *table, int write, /* * convert from the global kernel_cap_t to the ulong array to print to * userspace if this is a read. + * + * Legacy format: capabilities are exposed as two 32-bit values */ + cap = table->data; spin_lock(&umh_sysctl_lock); - if (table->data == CAP_BSET) - cap = &usermodehelper_bset; - else if (table->data == CAP_PI) - cap = &usermodehelper_inheritable; - else - BUG(); - - /* Legacy format: capabilities are exposed as two 32-bit values */ cap_array[0] = (u32) cap->val; cap_array[1] = cap->val >> 32; spin_unlock(&umh_sysctl_lock); @@ -555,14 +547,14 @@ static int proc_cap_handler(struct ctl_table *table, int write, struct ctl_table usermodehelper_table[] = { { .procname = "bset", - .data = CAP_BSET, + .data = &usermodehelper_bset, .maxlen = 2 * sizeof(unsigned long), .mode = 0600, .proc_handler = proc_cap_handler, }, { .procname = "inheritable", - .data = CAP_PI, + .data = &usermodehelper_inheritable, .maxlen = 2 * sizeof(unsigned long), .mode = 0600, .proc_handler = proc_cap_handler, diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan index be6ee6020290..fdca89c05745 100644 --- a/lib/Kconfig.kasan +++ b/lib/Kconfig.kasan @@ -49,6 +49,15 @@ menuconfig KASAN if KASAN +config CC_HAS_KASAN_MEMINTRINSIC_PREFIX + def_bool (CC_IS_CLANG && $(cc-option,-fsanitize=kernel-address -mllvm -asan-kernel-mem-intrinsic-prefix=1)) || \ + (CC_IS_GCC && $(cc-option,-fsanitize=kernel-address --param asan-kernel-mem-intrinsic-prefix=1)) + # Don't define it if we don't need it: compilation of the test uses + # this variable to decide how the compiler should treat builtins. + depends on !KASAN_HW_TAGS + help + The compiler is able to prefix memintrinsics with __asan or __hwasan. + choice prompt "KASAN mode" default KASAN_GENERIC diff --git a/lib/parser.c b/lib/parser.c index 2b5e2b480253..f4eafb9d74e6 100644 --- a/lib/parser.c +++ b/lib/parser.c @@ -133,7 +133,7 @@ EXPORT_SYMBOL(match_token); * as a number in that base. * * Return: On success, sets @result to the integer represented by the - * string and returns 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure. + * string and returns 0. Returns -EINVAL or -ERANGE on failure. */ static int match_number(substring_t *s, int *result, int base) { @@ -165,7 +165,7 @@ static int match_number(substring_t *s, int *result, int base) * as a number in that base. * * Return: On success, sets @result to the integer represented by the - * string and returns 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure. + * string and returns 0. Returns -EINVAL or -ERANGE on failure. */ static int match_u64int(substring_t *s, u64 *result, int base) { @@ -189,7 +189,7 @@ static int match_u64int(substring_t *s, u64 *result, int base) * Description: Attempts to parse the &substring_t @s as a decimal integer. * * Return: On success, sets @result to the integer represented by the string - * and returns 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure. + * and returns 0. Returns -EINVAL or -ERANGE on failure. */ int match_int(substring_t *s, int *result) { @@ -205,7 +205,7 @@ EXPORT_SYMBOL(match_int); * Description: Attempts to parse the &substring_t @s as a decimal integer. * * Return: On success, sets @result to the integer represented by the string - * and returns 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure. + * and returns 0. Returns -EINVAL or -ERANGE on failure. */ int match_uint(substring_t *s, unsigned int *result) { @@ -228,7 +228,7 @@ EXPORT_SYMBOL(match_uint); * integer. * * Return: On success, sets @result to the integer represented by the string - * and returns 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure. + * and returns 0. Returns -EINVAL or -ERANGE on failure. */ int match_u64(substring_t *s, u64 *result) { @@ -244,7 +244,7 @@ EXPORT_SYMBOL(match_u64); * Description: Attempts to parse the &substring_t @s as an octal integer. * * Return: On success, sets @result to the integer represented by the string - * and returns 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure. + * and returns 0. Returns -EINVAL or -ERANGE on failure. */ int match_octal(substring_t *s, int *result) { @@ -260,7 +260,7 @@ EXPORT_SYMBOL(match_octal); * Description: Attempts to parse the &substring_t @s as a hexadecimal integer. * * Return: On success, sets @result to the integer represented by the string - * and returns 0. Returns -ENOMEM, -EINVAL, or -ERANGE on failure. + * and returns 0. Returns -EINVAL or -ERANGE on failure. */ int match_hex(substring_t *s, int *result) { diff --git a/lib/zlib_deflate/defutil.h b/lib/zlib_deflate/defutil.h index 385333b22ec6..4ea40f5a279f 100644 --- a/lib/zlib_deflate/defutil.h +++ b/lib/zlib_deflate/defutil.h @@ -420,9 +420,11 @@ static inline void flush_pending( z_streamp strm ) { + unsigned len; deflate_state *s = (deflate_state *) strm->state; - unsigned len = s->pending; + bi_flush(s); + len = s->pending; if (len > strm->avail_out) len = strm->avail_out; if (len == 0) return; diff --git a/mm/damon/paddr.c b/mm/damon/paddr.c index 607bb69e526c..6c655d9b5639 100644 --- a/mm/damon/paddr.c +++ b/mm/damon/paddr.c @@ -250,12 +250,11 @@ static unsigned long damon_pa_pageout(struct damon_region *r, struct damos *s) folio_put(folio); continue; } - if (folio_test_unevictable(folio)) { + if (folio_test_unevictable(folio)) folio_putback_lru(folio); - } else { + else list_add(&folio->lru, &folio_list); - folio_put(folio); - } + folio_put(folio); } applied = reclaim_pages(&folio_list); cond_resched(); diff --git a/mm/kasan/Makefile b/mm/kasan/Makefile index d4837bff3b60..7634dd2a6128 100644 --- a/mm/kasan/Makefile +++ b/mm/kasan/Makefile @@ -35,7 +35,14 @@ CFLAGS_shadow.o := $(CC_FLAGS_KASAN_RUNTIME) CFLAGS_hw_tags.o := $(CC_FLAGS_KASAN_RUNTIME) CFLAGS_sw_tags.o := $(CC_FLAGS_KASAN_RUNTIME) -CFLAGS_KASAN_TEST := $(CFLAGS_KASAN) -fno-builtin $(call cc-disable-warning, vla) +CFLAGS_KASAN_TEST := $(CFLAGS_KASAN) $(call cc-disable-warning, vla) +ifndef CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX +# If compiler instruments memintrinsics by prefixing them with __asan/__hwasan, +# we need to treat them normally (as builtins), otherwise the compiler won't +# recognize them as instrumentable. If it doesn't instrument them, we need to +# pass -fno-builtin, so the compiler doesn't inline them. +CFLAGS_KASAN_TEST += -fno-builtin +endif CFLAGS_kasan_test.o := $(CFLAGS_KASAN_TEST) CFLAGS_kasan_test_module.o := $(CFLAGS_KASAN_TEST) diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h index 9377b0789edc..a61eeee3095a 100644 --- a/mm/kasan/kasan.h +++ b/mm/kasan/kasan.h @@ -666,4 +666,8 @@ void __hwasan_storeN_noabort(unsigned long addr, size_t size); void __hwasan_tag_memory(unsigned long addr, u8 tag, unsigned long size); +void *__hwasan_memset(void *addr, int c, size_t len); +void *__hwasan_memmove(void *dest, const void *src, size_t len); +void *__hwasan_memcpy(void *dest, const void *src, size_t len); + #endif /* __MM_KASAN_KASAN_H */ diff --git a/mm/kasan/kasan_test.c b/mm/kasan/kasan_test.c index 74cd80c12b25..627eaf1ee1db 100644 --- a/mm/kasan/kasan_test.c +++ b/mm/kasan/kasan_test.c @@ -165,6 +165,15 @@ static void kasan_test_exit(struct kunit *test) kunit_skip((test), "Test requires " #config "=n"); \ } while (0) +#define KASAN_TEST_NEEDS_CHECKED_MEMINTRINSICS(test) do { \ + if (IS_ENABLED(CONFIG_KASAN_HW_TAGS)) \ + break; /* No compiler instrumentation. */ \ + if (IS_ENABLED(CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX)) \ + break; /* Should always be instrumented! */ \ + if (IS_ENABLED(CONFIG_GENERIC_ENTRY)) \ + kunit_skip((test), "Test requires checked mem*()"); \ +} while (0) + static void kmalloc_oob_right(struct kunit *test) { char *ptr; @@ -454,6 +463,8 @@ static void kmalloc_oob_16(struct kunit *test) u64 words[2]; } *ptr1, *ptr2; + KASAN_TEST_NEEDS_CHECKED_MEMINTRINSICS(test); + /* This test is specifically crafted for the generic mode. */ KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC); @@ -476,6 +487,8 @@ static void kmalloc_uaf_16(struct kunit *test) u64 words[2]; } *ptr1, *ptr2; + KASAN_TEST_NEEDS_CHECKED_MEMINTRINSICS(test); + ptr1 = kmalloc(sizeof(*ptr1), GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr1); @@ -498,6 +511,8 @@ static void kmalloc_oob_memset_2(struct kunit *test) char *ptr; size_t size = 128 - KASAN_GRANULE_SIZE; + KASAN_TEST_NEEDS_CHECKED_MEMINTRINSICS(test); + ptr = kmalloc(size, GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); @@ -511,6 +526,8 @@ static void kmalloc_oob_memset_4(struct kunit *test) char *ptr; size_t size = 128 - KASAN_GRANULE_SIZE; + KASAN_TEST_NEEDS_CHECKED_MEMINTRINSICS(test); + ptr = kmalloc(size, GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); @@ -524,6 +541,8 @@ static void kmalloc_oob_memset_8(struct kunit *test) char *ptr; size_t size = 128 - KASAN_GRANULE_SIZE; + KASAN_TEST_NEEDS_CHECKED_MEMINTRINSICS(test); + ptr = kmalloc(size, GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); @@ -537,6 +556,8 @@ static void kmalloc_oob_memset_16(struct kunit *test) char *ptr; size_t size = 128 - KASAN_GRANULE_SIZE; + KASAN_TEST_NEEDS_CHECKED_MEMINTRINSICS(test); + ptr = kmalloc(size, GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); @@ -550,6 +571,8 @@ static void kmalloc_oob_in_memset(struct kunit *test) char *ptr; size_t size = 128 - KASAN_GRANULE_SIZE; + KASAN_TEST_NEEDS_CHECKED_MEMINTRINSICS(test); + ptr = kmalloc(size, GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); @@ -566,6 +589,8 @@ static void kmalloc_memmove_negative_size(struct kunit *test) size_t size = 64; size_t invalid_size = -2; + KASAN_TEST_NEEDS_CHECKED_MEMINTRINSICS(test); + /* * Hardware tag-based mode doesn't check memmove for negative size. * As a result, this test introduces a side-effect memory corruption, @@ -590,6 +615,8 @@ static void kmalloc_memmove_invalid_size(struct kunit *test) size_t size = 64; size_t invalid_size = size; + KASAN_TEST_NEEDS_CHECKED_MEMINTRINSICS(test); + ptr = kmalloc(size, GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); @@ -618,6 +645,8 @@ static void kmalloc_uaf_memset(struct kunit *test) char *ptr; size_t size = 33; + KASAN_TEST_NEEDS_CHECKED_MEMINTRINSICS(test); + /* * Only generic KASAN uses quarantine, which is required to avoid a * kernel memory corruption this test causes. diff --git a/mm/kasan/shadow.c b/mm/kasan/shadow.c index 3703983a8e55..c8b86f3273b5 100644 --- a/mm/kasan/shadow.c +++ b/mm/kasan/shadow.c @@ -38,11 +38,14 @@ bool __kasan_check_write(const volatile void *p, unsigned int size) } EXPORT_SYMBOL(__kasan_check_write); -#ifndef CONFIG_GENERIC_ENTRY +#if !defined(CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX) && !defined(CONFIG_GENERIC_ENTRY) /* * CONFIG_GENERIC_ENTRY relies on compiler emitted mem*() calls to not be * instrumented. KASAN enabled toolchains should emit __asan_mem*() functions * for the sites they want to instrument. + * + * If we have a compiler that can instrument meminstrinsics, never override + * these, so that non-instrumented files can safely consider them as builtins. */ #undef memset void *memset(void *addr, int c, size_t len) @@ -107,6 +110,17 @@ void *__asan_memcpy(void *dest, const void *src, size_t len) } EXPORT_SYMBOL(__asan_memcpy); +#ifdef CONFIG_KASAN_SW_TAGS +void *__hwasan_memset(void *addr, int c, size_t len) __alias(__asan_memset); +EXPORT_SYMBOL(__hwasan_memset); +#ifdef __HAVE_ARCH_MEMMOVE +void *__hwasan_memmove(void *dest, const void *src, size_t len) __alias(__asan_memmove); +EXPORT_SYMBOL(__hwasan_memmove); +#endif +void *__hwasan_memcpy(void *dest, const void *src, size_t len) __alias(__asan_memcpy); +EXPORT_SYMBOL(__hwasan_memcpy); +#endif + void kasan_poison(const void *addr, size_t size, u8 value, bool init) { void *shadow_start, *shadow_end; diff --git a/mm/memory-failure.c b/mm/memory-failure.c index a1ede7bdce95..fae9baf3be16 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -1069,7 +1069,7 @@ static int me_pagecache_dirty(struct page_state *ps, struct page *p) * cache and swap cache(ie. page is freshly swapped in). So it could be * referenced concurrently by 2 types of PTEs: * normal PTEs and swap PTEs. We try to handle them consistently by calling - * try_to_unmap(TTU_IGNORE_HWPOISON) to convert the normal PTEs to swap PTEs, + * try_to_unmap(!TTU_HWPOISON) to convert the normal PTEs to swap PTEs, * and then * - clear dirty bit to prevent IO * - remove from LRU @@ -1486,7 +1486,7 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn, int flags, struct page *hpage) { struct folio *folio = page_folio(hpage); - enum ttu_flags ttu = TTU_IGNORE_MLOCK | TTU_SYNC; + enum ttu_flags ttu = TTU_IGNORE_MLOCK | TTU_SYNC | TTU_HWPOISON; struct address_space *mapping; LIST_HEAD(tokill); bool unmap_success; @@ -1516,7 +1516,7 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn, if (PageSwapCache(p)) { pr_err("%#lx: keeping poisoned page in swap cache\n", pfn); - ttu |= TTU_IGNORE_HWPOISON; + ttu &= ~TTU_HWPOISON; } /* @@ -1531,7 +1531,7 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn, if (page_mkclean(hpage)) { SetPageDirty(hpage); } else { - ttu |= TTU_IGNORE_HWPOISON; + ttu &= ~TTU_HWPOISON; pr_info("%#lx: corrupted page was clean: dropped without side effects\n", pfn); } diff --git a/mm/migrate.c b/mm/migrate.c index 37865f85df6d..98f1c11197a8 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -1035,11 +1035,16 @@ out: * destination folio. This is safe because nobody is using them * except us. */ +union migration_ptr { + struct anon_vma *anon_vma; + struct address_space *mapping; +}; static void __migrate_folio_record(struct folio *dst, unsigned long page_was_mapped, struct anon_vma *anon_vma) { - dst->mapping = (void *)anon_vma; + union migration_ptr ptr = { .anon_vma = anon_vma }; + dst->mapping = ptr.mapping; dst->private = (void *)page_was_mapped; } @@ -1047,7 +1052,8 @@ static void __migrate_folio_extract(struct folio *dst, int *page_was_mappedp, struct anon_vma **anon_vmap) { - *anon_vmap = (void *)dst->mapping; + union migration_ptr ptr = { .mapping = dst->mapping }; + *anon_vmap = ptr.anon_vma; *page_was_mappedp = (unsigned long)dst->private; dst->mapping = NULL; dst->private = NULL; diff --git a/mm/mmap.c b/mm/mmap.c index 20f21f0949dd..740b54be3ed4 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -973,7 +973,7 @@ struct vm_area_struct *vma_merge(struct vma_iterator *vmi, struct mm_struct *mm, vma_end = addr; adjust = mid; adj_next = -(vma->vm_end - addr); - err = dup_anon_vma(res, adjust); + err = dup_anon_vma(adjust, prev); } else { vma = next; /* case 3 */ vma_start = addr; diff --git a/mm/rmap.c b/mm/rmap.c index 15ae24585fc4..8632e02661ac 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -1602,7 +1602,7 @@ static bool try_to_unmap_one(struct folio *folio, struct vm_area_struct *vma, /* Update high watermark before we lower rss */ update_hiwater_rss(mm); - if (PageHWPoison(subpage) && !(flags & TTU_IGNORE_HWPOISON)) { + if (PageHWPoison(subpage) && (flags & TTU_HWPOISON)) { pteval = swp_entry_to_pte(make_hwpoison_entry(subpage)); if (folio_test_hugetlb(folio)) { hugetlb_count_sub(folio_nr_pages(folio), mm); diff --git a/rust/bindgen_parameters b/rust/bindgen_parameters index be4963bf7203..552d9a85925b 100644 --- a/rust/bindgen_parameters +++ b/rust/bindgen_parameters @@ -6,6 +6,7 @@ --opaque-type local_apic # Packed type cannot transitively contain a `#[repr(align)]` type. +--opaque-type alt_instr --opaque-type x86_msi_data --opaque-type x86_msi_addr_lo diff --git a/scripts/Makefile.kasan b/scripts/Makefile.kasan index b9e94c5e7097..c186110ffa20 100644 --- a/scripts/Makefile.kasan +++ b/scripts/Makefile.kasan @@ -1,5 +1,14 @@ # SPDX-License-Identifier: GPL-2.0 + +ifdef CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX +# Safe for compiler to generate meminstrinsic calls in uninstrumented files. +CFLAGS_KASAN_NOSANITIZE := +else +# Don't let compiler generate memintrinsic calls in uninstrumented files +# because they are instrumented. CFLAGS_KASAN_NOSANITIZE := -fno-builtin +endif + KASAN_SHADOW_OFFSET ?= $(CONFIG_KASAN_SHADOW_OFFSET) cc-param = $(call cc-option, -mllvm -$(1), $(call cc-option, --param $(1))) @@ -38,6 +47,11 @@ endif CFLAGS_KASAN += $(call cc-param,asan-stack=$(stack_enable)) +# Instrument memcpy/memset/memmove calls by using instrumented __asan_mem*() +# instead. With compilers that don't support this option, compiler-inserted +# memintrinsics won't be checked by KASAN on GENERIC_ENTRY architectures. +CFLAGS_KASAN += $(call cc-param,asan-kernel-mem-intrinsic-prefix=1) + endif # CONFIG_KASAN_GENERIC ifdef CONFIG_KASAN_SW_TAGS @@ -54,6 +68,9 @@ CFLAGS_KASAN := -fsanitize=kernel-hwaddress \ $(call cc-param,hwasan-inline-all-checks=0) \ $(instrumentation_flags) +# Instrument memcpy/memset/memmove calls by using instrumented __hwasan_mem*(). +CFLAGS_KASAN += $(call cc-param,hwasan-kernel-mem-intrinsic-prefix=1) + endif # CONFIG_KASAN_SW_TAGS export CFLAGS_KASAN CFLAGS_KASAN_NOSANITIZE diff --git a/scripts/coccicheck b/scripts/coccicheck index 2956fce8fa4f..e52cb43fede6 100755 --- a/scripts/coccicheck +++ b/scripts/coccicheck @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # SPDX-License-Identifier: GPL-2.0 # Linux kernel coccicheck # @@ -18,7 +18,7 @@ fi SPATCH_VERSION=$($SPATCH --version | head -1 | awk '{print $3}') USE_JOBS="no" -$SPATCH --help | grep "\-\-jobs" > /dev/null && USE_JOBS="yes" +$SPATCH --help | grep -e "--jobs" > /dev/null && USE_JOBS="yes" # The verbosity may be set by the environmental parameter V= # as for example with 'make V=1 coccicheck' diff --git a/scripts/coccinelle/api/atomic_as_refcounter.cocci b/scripts/coccinelle/api/atomic_as_refcounter.cocci index e63d52408b86..bbe5b2932933 100644 --- a/scripts/coccinelle/api/atomic_as_refcounter.cocci +++ b/scripts/coccinelle/api/atomic_as_refcounter.cocci @@ -55,7 +55,7 @@ identifier fname6 =~ ".*call_rcu.*"; p1 << r1.p1; p2 << r1.p2; @@ -msg = "atomic_dec_and_test variation before object free at line %s." +msg = "WARNING: atomic_dec_and_test variation before object free at line %s." coccilib.report.print_report(p1[0], msg % (p2[0].line)) @r4 exists@ @@ -88,7 +88,7 @@ fname@p2(y, ...); p1 << r4.p1; p2 << r4.p2; @@ -msg = "atomic_dec_and_test variation before object free at line %s." +msg = "WARNING: atomic_dec_and_test variation before object free at line %s." coccilib.report.print_report(p1[0], msg % (p2[0].line)) @r2 exists@ @@ -107,7 +107,7 @@ atomic64_add_unless(&(a)->x,-1,1)@p1 @script:python depends on report@ p1 << r2.p1; @@ -msg = "atomic_add_unless" +msg = "WARNING: atomic_add_unless" coccilib.report.print_report(p1[0], msg) @r3 exists@ @@ -126,5 +126,5 @@ x = atomic64_add_return@p1(-1, ...); @script:python depends on report@ p1 << r3.p1; @@ -msg = "x = atomic_add_return(-1, ...)" +msg = "WARNING: x = atomic_add_return(-1, ...)" coccilib.report.print_report(p1[0], msg) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e103bb3693c0..3c629f4ae080 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -9260,6 +9260,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0a62, "Dell Precision 5560", ALC289_FIXUP_DUAL_SPK), SND_PCI_QUIRK(0x1028, 0x0a9d, "Dell Latitude 5430", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0a9e, "Dell Latitude 5430", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x0ac9, "Dell Precision 3260", ALC295_FIXUP_CHROME_BOOK), SND_PCI_QUIRK(0x1028, 0x0b19, "Dell XPS 15 9520", ALC289_FIXUP_DUAL_SPK), SND_PCI_QUIRK(0x1028, 0x0b1a, "Dell Precision 5570", ALC289_FIXUP_DUAL_SPK), SND_PCI_QUIRK(0x1028, 0x0b37, "Dell Inspiron 16 Plus 7620 2-in-1", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS), @@ -11617,6 +11618,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x069f, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), + SND_PCI_QUIRK(0x103c, 0x870c, "HP", ALC897_FIXUP_HP_HSMIC_VERB), SND_PCI_QUIRK(0x103c, 0x8719, "HP", ALC897_FIXUP_HP_HSMIC_VERB), SND_PCI_QUIRK(0x103c, 0x873e, "HP", ALC671_FIXUP_HP_HEADSET_MIC2), SND_PCI_QUIRK(0x103c, 0x877e, "HP 288 Pro G6", ALC671_FIXUP_HP_HEADSET_MIC2), diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c index 9a30f6d35d13..24b978234000 100644 --- a/sound/pci/ice1712/aureon.c +++ b/sound/pci/ice1712/aureon.c @@ -1892,13 +1892,10 @@ static int aureon_add_controls(struct snd_ice1712 *ice) unsigned char id; snd_ice1712_save_gpio_status(ice); id = aureon_cs8415_get(ice, CS8415_ID); + snd_ice1712_restore_gpio_status(ice); if (id != 0x41) dev_info(ice->card->dev, "No CS8415 chip. Skipping CS8415 controls.\n"); - else if ((id & 0x0F) != 0x01) - dev_info(ice->card->dev, - "Detected unsupported CS8415 rev. (%c)\n", - (char)((id & 0x0F) + 'A' - 1)); else { for (i = 0; i < ARRAY_SIZE(cs8415_controls); i++) { struct snd_kcontrol *kctl; @@ -1909,7 +1906,6 @@ static int aureon_add_controls(struct snd_ice1712 *ice) kctl->id.device = ice->pcm->device; } } - snd_ice1712_restore_gpio_status(ice); } return 0; diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c index 36314753923b..4a69ce702360 100644 --- a/sound/soc/amd/yc/acp6x-mach.c +++ b/sound/soc/amd/yc/acp6x-mach.c @@ -255,6 +255,20 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "15NBC1011"), } }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16z-n000"), + } + }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + DMI_MATCH(DMI_BOARD_NAME, "8A43"), + } + }, {} }; diff --git a/sound/soc/apple/mca.c b/sound/soc/apple/mca.c index 24381c42eb54..64750db9b963 100644 --- a/sound/soc/apple/mca.c +++ b/sound/soc/apple/mca.c @@ -101,7 +101,6 @@ #define SERDES_CONF_UNK3 BIT(14) #define SERDES_CONF_NO_DATA_FEEDBACK BIT(15) #define SERDES_CONF_SYNC_SEL GENMASK(18, 16) -#define SERDES_CONF_SOME_RST BIT(19) #define REG_TX_SERDES_BITSTART 0x08 #define REG_RX_SERDES_BITSTART 0x0c #define REG_TX_SERDES_SLOTMASK 0x0c @@ -203,15 +202,24 @@ static void mca_fe_early_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + mca_modify(cl, serdes_conf, SERDES_CONF_SYNC_SEL, + FIELD_PREP(SERDES_CONF_SYNC_SEL, 0)); + mca_modify(cl, serdes_conf, SERDES_CONF_SYNC_SEL, + FIELD_PREP(SERDES_CONF_SYNC_SEL, 7)); mca_modify(cl, serdes_unit + REG_SERDES_STATUS, SERDES_STATUS_EN | SERDES_STATUS_RST, SERDES_STATUS_RST); - mca_modify(cl, serdes_conf, SERDES_CONF_SOME_RST, - SERDES_CONF_SOME_RST); - readl_relaxed(cl->base + serdes_conf); - mca_modify(cl, serdes_conf, SERDES_STATUS_RST, 0); - WARN_ON(readl_relaxed(cl->base + REG_SERDES_STATUS) & + /* + * Experiments suggest that it takes at most ~1 us + * for the bit to clear, so wait 2 us for good measure. + */ + udelay(2); + WARN_ON(readl_relaxed(cl->base + serdes_unit + REG_SERDES_STATUS) & SERDES_STATUS_RST); + mca_modify(cl, serdes_conf, SERDES_CONF_SYNC_SEL, + FIELD_PREP(SERDES_CONF_SYNC_SEL, 0)); + mca_modify(cl, serdes_conf, SERDES_CONF_SYNC_SEL, + FIELD_PREP(SERDES_CONF_SYNC_SEL, cl->no + 1)); break; default: break; @@ -942,10 +950,17 @@ static int mca_pcm_new(struct snd_soc_component *component, chan = mca_request_dma_channel(cl, i); if (IS_ERR_OR_NULL(chan)) { + mca_pcm_free(component, rtd->pcm); + + if (chan && PTR_ERR(chan) == -EPROBE_DEFER) + return PTR_ERR(chan); + dev_err(component->dev, "unable to obtain DMA channel (stream %d cluster %d): %pe\n", i, cl->no, chan); - mca_pcm_free(component, rtd->pcm); - return -EINVAL; + + if (!chan) + return -EINVAL; + return PTR_ERR(chan); } cl->dma_chans[i] = chan; diff --git a/sound/soc/atmel/mchp-pdmc.c b/sound/soc/atmel/mchp-pdmc.c index cf4084dcbd5e..1aed3baa9369 100644 --- a/sound/soc/atmel/mchp-pdmc.c +++ b/sound/soc/atmel/mchp-pdmc.c @@ -114,6 +114,7 @@ struct mchp_pdmc { struct clk *gclk; u32 pdmcen; u32 suspend_irq; + u32 startup_delay_us; int mic_no; int sinc_order; bool audio_filter_en; @@ -425,6 +426,7 @@ static const struct snd_soc_component_driver mchp_pdmc_dai_component = { .open = &mchp_pdmc_open, .close = &mchp_pdmc_close, .legacy_dai_naming = 1, + .start_dma_last = 1, }; static const unsigned int mchp_pdmc_1mic[] = {1}; @@ -632,6 +634,29 @@ static int mchp_pdmc_hw_params(struct snd_pcm_substream *substream, return 0; } +static void mchp_pdmc_noise_filter_workaround(struct mchp_pdmc *dd) +{ + u32 tmp, steps = 16; + + /* + * PDMC doesn't wait for microphones' startup time thus the acquisition + * may start before the microphones are ready leading to poc noises at + * the beginning of capture. To avoid this, we need to wait 50ms (in + * normal startup procedure) or 150 ms (worst case after resume from sleep + * states) after microphones are enabled and then clear the FIFOs (by + * reading the RHR 16 times) and possible interrupts before continuing. + * Also, for this to work the DMA needs to be started after interrupts + * are enabled. + */ + usleep_range(dd->startup_delay_us, dd->startup_delay_us + 5); + + while (steps--) + regmap_read(dd->regmap, MCHP_PDMC_RHR, &tmp); + + /* Clear interrupts. */ + regmap_read(dd->regmap, MCHP_PDMC_ISR, &tmp); +} + static int mchp_pdmc_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { @@ -644,15 +669,17 @@ static int mchp_pdmc_trigger(struct snd_pcm_substream *substream, switch (cmd) { case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_START: - /* Enable overrun and underrun error interrupts */ - regmap_write(dd->regmap, MCHP_PDMC_IER, dd->suspend_irq | - MCHP_PDMC_IR_RXOVR | MCHP_PDMC_IR_RXUDR); - dd->suspend_irq = 0; - fallthrough; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: snd_soc_component_update_bits(cpu, MCHP_PDMC_MR, MCHP_PDMC_MR_PDMCEN_MASK, dd->pdmcen); + + mchp_pdmc_noise_filter_workaround(dd); + + /* Enable interrupts. */ + regmap_write(dd->regmap, MCHP_PDMC_IER, dd->suspend_irq | + MCHP_PDMC_IR_RXOVR | MCHP_PDMC_IR_RXUDR); + dd->suspend_irq = 0; break; case SNDRV_PCM_TRIGGER_SUSPEND: regmap_read(dd->regmap, MCHP_PDMC_IMR, &dd->suspend_irq); @@ -796,6 +823,7 @@ static bool mchp_pdmc_readable_reg(struct device *dev, unsigned int reg) case MCHP_PDMC_CFGR: case MCHP_PDMC_IMR: case MCHP_PDMC_ISR: + case MCHP_PDMC_RHR: case MCHP_PDMC_VER: return true; default: @@ -817,6 +845,17 @@ static bool mchp_pdmc_writeable_reg(struct device *dev, unsigned int reg) } } +static bool mchp_pdmc_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MCHP_PDMC_ISR: + case MCHP_PDMC_RHR: + return true; + default: + return false; + } +} + static bool mchp_pdmc_precious_reg(struct device *dev, unsigned int reg) { switch (reg) { @@ -836,6 +875,7 @@ static const struct regmap_config mchp_pdmc_regmap_config = { .readable_reg = mchp_pdmc_readable_reg, .writeable_reg = mchp_pdmc_writeable_reg, .precious_reg = mchp_pdmc_precious_reg, + .volatile_reg = mchp_pdmc_volatile_reg, .cache_type = REGCACHE_FLAT, }; @@ -918,6 +958,9 @@ static int mchp_pdmc_dt_init(struct mchp_pdmc *dd) dd->channel_mic_map[i].clk_edge = edge; } + dd->startup_delay_us = 150000; + of_property_read_u32(np, "microchip,startup-delay-us", &dd->startup_delay_us); + return 0; } diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index 1430642c8433..785b9d01d8af 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c @@ -98,6 +98,9 @@ static struct snd_soc_dai_link at91sam9g20ek_dai = { .init = at91sam9g20ek_wm8731_init, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP, +#ifndef ENABLE_MIC_INPUT + .playback_only = true, +#endif SND_SOC_DAILINK_REG(pcm), }; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index bd72c426a93d..07747565c3b5 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -2103,6 +2103,7 @@ config SND_SOC_WSA883X config SND_SOC_ZL38060 tristate "Microsemi ZL38060 Connected Home Audio Processor" depends on SPI_MASTER + depends on GPIOLIB select REGMAP help Support for ZL38060 Connected Home Audio Processor from Microsemi, diff --git a/sound/soc/codecs/adau7118.c b/sound/soc/codecs/adau7118.c index bbb097249887..a663d37e5776 100644 --- a/sound/soc/codecs/adau7118.c +++ b/sound/soc/codecs/adau7118.c @@ -444,22 +444,6 @@ static const struct snd_soc_component_driver adau7118_component_driver = { .endianness = 1, }; -static void adau7118_regulator_disable(void *data) -{ - struct adau7118_data *st = data; - int ret; - /* - * If we fail to disable DVDD, don't bother in trying IOVDD. We - * actually don't want to be left in the situation where DVDD - * is enabled and IOVDD is disabled. - */ - ret = regulator_disable(st->dvdd); - if (ret) - return; - - regulator_disable(st->iovdd); -} - static int adau7118_regulator_setup(struct adau7118_data *st) { st->iovdd = devm_regulator_get(st->dev, "iovdd"); @@ -481,8 +465,7 @@ static int adau7118_regulator_setup(struct adau7118_data *st) regcache_cache_only(st->map, true); } - return devm_add_action_or_reset(st->dev, adau7118_regulator_disable, - st); + return 0; } static int adau7118_parset_dt(const struct adau7118_data *st) diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c index c55b033d89da..4a4f09f924bc 100644 --- a/sound/soc/codecs/da7219-aad.c +++ b/sound/soc/codecs/da7219-aad.c @@ -339,11 +339,39 @@ static void da7219_aad_hptest_work(struct work_struct *work) SND_JACK_HEADSET | SND_JACK_LINEOUT); } +static void da7219_aad_jack_det_work(struct work_struct *work) +{ + struct da7219_aad_priv *da7219_aad = + container_of(work, struct da7219_aad_priv, jack_det_work); + struct snd_soc_component *component = da7219_aad->component; + u8 srm_st; + + mutex_lock(&da7219_aad->jack_det_mutex); + + srm_st = snd_soc_component_read(component, DA7219_PLL_SRM_STS) & DA7219_PLL_SRM_STS_MCLK; + msleep(da7219_aad->gnd_switch_delay * ((srm_st == 0x0) ? 2 : 1) - 4); + /* Enable ground switch */ + snd_soc_component_update_bits(component, 0xFB, 0x01, 0x01); + + mutex_unlock(&da7219_aad->jack_det_mutex); +} + /* * IRQ */ +static irqreturn_t da7219_aad_pre_irq_thread(int irq, void *data) +{ + + struct da7219_aad_priv *da7219_aad = data; + + if (!da7219_aad->jack_inserted) + schedule_work(&da7219_aad->jack_det_work); + + return IRQ_WAKE_THREAD; +} + static irqreturn_t da7219_aad_irq_thread(int irq, void *data) { struct da7219_aad_priv *da7219_aad = data; @@ -351,14 +379,9 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data) struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); u8 events[DA7219_AAD_IRQ_REG_MAX]; - u8 statusa, srm_st; + u8 statusa; int i, report = 0, mask = 0; - srm_st = snd_soc_component_read(component, DA7219_PLL_SRM_STS) & DA7219_PLL_SRM_STS_MCLK; - msleep(da7219_aad->gnd_switch_delay * ((srm_st == 0x0) ? 2 : 1) - 4); - /* Enable ground switch */ - snd_soc_component_update_bits(component, 0xFB, 0x01, 0x01); - /* Read current IRQ events */ regmap_bulk_read(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A, events, DA7219_AAD_IRQ_REG_MAX); @@ -377,6 +400,9 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data) events[DA7219_AAD_IRQ_REG_A], events[DA7219_AAD_IRQ_REG_B], statusa); + if (!da7219_aad->jack_inserted) + cancel_work_sync(&da7219_aad->jack_det_work); + if (statusa & DA7219_JACK_INSERTION_STS_MASK) { /* Jack Insertion */ if (events[DA7219_AAD_IRQ_REG_A] & @@ -940,8 +966,9 @@ int da7219_aad_init(struct snd_soc_component *component) INIT_WORK(&da7219_aad->btn_det_work, da7219_aad_btn_det_work); INIT_WORK(&da7219_aad->hptest_work, da7219_aad_hptest_work); + INIT_WORK(&da7219_aad->jack_det_work, da7219_aad_jack_det_work); - ret = request_threaded_irq(da7219_aad->irq, NULL, + ret = request_threaded_irq(da7219_aad->irq, da7219_aad_pre_irq_thread, da7219_aad_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT, "da7219-aad", da7219_aad); diff --git a/sound/soc/codecs/da7219-aad.h b/sound/soc/codecs/da7219-aad.h index 21fdf53095cc..be87ee47edde 100644 --- a/sound/soc/codecs/da7219-aad.h +++ b/sound/soc/codecs/da7219-aad.h @@ -11,6 +11,7 @@ #define __DA7219_AAD_H #include <linux/timer.h> +#include <linux/mutex.h> #include <sound/soc.h> #include <sound/jack.h> #include <sound/da7219-aad.h> @@ -196,6 +197,9 @@ struct da7219_aad_priv { struct work_struct btn_det_work; struct work_struct hptest_work; + struct work_struct jack_det_work; + + struct mutex jack_det_mutex; struct snd_soc_jack *jack; bool micbias_resume_enable; diff --git a/sound/soc/codecs/mt6358.c b/sound/soc/codecs/mt6358.c index 93f35e8d26fc..b54610b27906 100644 --- a/sound/soc/codecs/mt6358.c +++ b/sound/soc/codecs/mt6358.c @@ -560,6 +560,9 @@ static int mt6358_put_wov(struct snd_kcontrol *kcontrol, struct mt6358_priv *priv = snd_soc_component_get_drvdata(c); int enabled = ucontrol->value.integer.value[0]; + if (enabled < 0 || enabled > 1) + return -EINVAL; + if (priv->wov_enabled != enabled) { if (enabled) mt6358_enable_wov_phase2(priv); @@ -567,6 +570,8 @@ static int mt6358_put_wov(struct snd_kcontrol *kcontrol, mt6358_disable_wov_phase2(priv); priv->wov_enabled = enabled; + + return 1; } return 0; @@ -632,9 +637,6 @@ static const char * const hp_in_mux_map[] = { "Audio Playback", "Test Mode", "HP Impedance", - "undefined1", - "undefined2", - "undefined3", }; static int hp_in_mux_map_value[] = { @@ -643,9 +645,6 @@ static int hp_in_mux_map_value[] = { HP_MUX_HP, HP_MUX_TEST_MODE, HP_MUX_HP_IMPEDANCE, - HP_MUX_OPEN, - HP_MUX_OPEN, - HP_MUX_OPEN, }; static SOC_VALUE_ENUM_SINGLE_DECL(hpl_in_mux_map_enum, diff --git a/sound/soc/codecs/sma1303.c b/sound/soc/codecs/sma1303.c index 727c01facf52..fa4b0a60f8a9 100644 --- a/sound/soc/codecs/sma1303.c +++ b/sound/soc/codecs/sma1303.c @@ -569,7 +569,7 @@ static int sma1303_aif_in_event(struct snd_soc_dapm_widget *w, ret += sma1303_regmap_update_bits(sma1303, SMA1303_11_SYSTEM_CTRL2, SMA1303_LR_DATA_SW_MASK, - SMA1303_LR_DATA_SW_NORMAL, + SMA1303_LR_DATA_SW_SWAP, &temp); if (temp == true) change = true; diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 71a11d747622..4fe448295a90 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -227,6 +227,20 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { .callback = sof_rt5682_quirk_cb, .matches = { DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Rex"), + DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98360_ALC5682I_I2S"), + }, + .driver_data = (void *)(SOF_RT5682_MCLK_EN | + SOF_RT5682_SSP_CODEC(2) | + SOF_SPEAKER_AMP_PRESENT | + SOF_MAX98360A_SPEAKER_AMP_PRESENT | + SOF_RT5682_SSP_AMP(0) | + SOF_RT5682_NUM_HDMIDEV(4) + ), + }, + { + .callback = sof_rt5682_quirk_cb, + .matches = { + DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Rex"), }, .driver_data = (void *)(SOF_RT5682_MCLK_EN | SOF_RT5682_SSP_CODEC(2) | @@ -1106,6 +1120,15 @@ static const struct platform_device_id board_ids[] = { SOF_RT5682_NUM_HDMIDEV(4)), }, { + .name = "mtl_mx98360_rt5682", + .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | + SOF_RT5682_SSP_CODEC(0) | + SOF_SPEAKER_AMP_PRESENT | + SOF_MAX98360A_SPEAKER_AMP_PRESENT | + SOF_RT5682_SSP_AMP(1) | + SOF_RT5682_NUM_HDMIDEV(4)), + }, + { .name = "jsl_rt5682", .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | SOF_RT5682_MCLK_24MHZ | diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c index b1a66a0f6818..7911c3af8071 100644 --- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c @@ -15,6 +15,11 @@ static const struct snd_soc_acpi_codecs mtl_max98357a_amp = { .codecs = {"MX98357A"} }; +static const struct snd_soc_acpi_codecs mtl_max98360a_amp = { + .num_codecs = 1, + .codecs = {"MX98360A"} +}; + static const struct snd_soc_acpi_codecs mtl_rt5682_rt5682s_hp = { .num_codecs = 2, .codecs = {"10EC5682", "RTL5682"}, @@ -28,6 +33,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = { .quirk_data = &mtl_max98357a_amp, .sof_tplg_filename = "sof-mtl-max98357a-rt5682.tplg", }, + { + .comp_ids = &mtl_rt5682_rt5682s_hp, + .drv_name = "mtl_mx98360_rt5682", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &mtl_max98360a_amp, + .sof_tplg_filename = "sof-mtl-max98360a-rt5682.tplg", + }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_mtl_machines); diff --git a/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c b/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c index 6a9ace4180d3..8645ab686970 100644 --- a/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c +++ b/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c @@ -141,16 +141,13 @@ static int mt8183_i2s_hd_set(struct snd_kcontrol *kcontrol, struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); struct mtk_afe_i2s_priv *i2s_priv; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - int hd_en; + int hd_en, change; if (ucontrol->value.enumerated.item[0] >= e->items) return -EINVAL; hd_en = ucontrol->value.integer.value[0]; - dev_info(afe->dev, "%s(), kcontrol name %s, hd_en %d\n", - __func__, kcontrol->id.name, hd_en); - i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name); if (!i2s_priv) { @@ -158,9 +155,10 @@ static int mt8183_i2s_hd_set(struct snd_kcontrol *kcontrol, return -EINVAL; } + change = i2s_priv->low_jitter_en != hd_en; i2s_priv->low_jitter_en = hd_en; - return 0; + return change; } static const struct snd_kcontrol_new mtk_dai_i2s_controls[] = { @@ -276,9 +274,6 @@ static int mtk_apll_event(struct snd_soc_dapm_widget *w, struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); - dev_info(cmpnt->dev, "%s(), name %s, event 0x%x\n", - __func__, w->name, event); - switch (event) { case SND_SOC_DAPM_PRE_PMU: if (strcmp(w->name, APLL1_W_NAME) == 0) @@ -307,9 +302,6 @@ static int mtk_mclk_en_event(struct snd_soc_dapm_widget *w, struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); struct mtk_afe_i2s_priv *i2s_priv; - dev_info(cmpnt->dev, "%s(), name %s, event 0x%x\n", - __func__, w->name, event); - i2s_priv = get_i2s_priv_by_name(afe, w->name); if (!i2s_priv) { @@ -715,11 +707,6 @@ static int mtk_dai_i2s_config(struct mtk_base_afe *afe, unsigned int i2s_con = 0, fmt_con = I2S_FMT_I2S << I2S_FMT_SFT; int ret = 0; - dev_info(afe->dev, "%s(), id %d, rate %d, format %d\n", - __func__, - i2s_id, - rate, format); - if (i2s_priv) { i2s_priv->rate = rate; @@ -810,8 +797,6 @@ static int mtk_dai_i2s_set_sysclk(struct snd_soc_dai *dai, return -EINVAL; } - dev_info(afe->dev, "%s(), freq %d\n", __func__, freq); - apll = mt8183_get_apll_by_rate(afe, freq); apll_rate = mt8183_get_apll_rate(afe, apll); diff --git a/sound/soc/mediatek/mt8188/mt8188-dai-etdm.c b/sound/soc/mediatek/mt8188/mt8188-dai-etdm.c index 071841903c62..7a37752d4244 100644 --- a/sound/soc/mediatek/mt8188/mt8188-dai-etdm.c +++ b/sound/soc/mediatek/mt8188/mt8188-dai-etdm.c @@ -679,7 +679,6 @@ static int mt8188_etdm_clk_src_sel_put(struct snd_kcontrol *kcontrol, unsigned int old_val; unsigned int mask; unsigned int reg; - unsigned int shift; if (source >= e->items) return -EINVAL; @@ -687,27 +686,22 @@ static int mt8188_etdm_clk_src_sel_put(struct snd_kcontrol *kcontrol, if (!strcmp(kcontrol->id.name, "ETDM_OUT1_Clock_Source")) { reg = ETDM_OUT1_CON4; mask = ETDM_OUT_CON4_CLOCK_MASK; - shift = ETDM_OUT_CON4_CLOCK_SHIFT; val = FIELD_PREP(ETDM_OUT_CON4_CLOCK_MASK, source); } else if (!strcmp(kcontrol->id.name, "ETDM_OUT2_Clock_Source")) { reg = ETDM_OUT2_CON4; mask = ETDM_OUT_CON4_CLOCK_MASK; - shift = ETDM_OUT_CON4_CLOCK_SHIFT; val = FIELD_PREP(ETDM_OUT_CON4_CLOCK_MASK, source); } else if (!strcmp(kcontrol->id.name, "ETDM_OUT3_Clock_Source")) { reg = ETDM_OUT3_CON4; mask = ETDM_OUT_CON4_CLOCK_MASK; - shift = ETDM_OUT_CON4_CLOCK_SHIFT; val = FIELD_PREP(ETDM_OUT_CON4_CLOCK_MASK, source); } else if (!strcmp(kcontrol->id.name, "ETDM_IN1_Clock_Source")) { reg = ETDM_IN1_CON2; mask = ETDM_IN_CON2_CLOCK_MASK; - shift = ETDM_IN_CON2_CLOCK_SHIFT; val = FIELD_PREP(ETDM_IN_CON2_CLOCK_MASK, source); } else if (!strcmp(kcontrol->id.name, "ETDM_IN2_Clock_Source")) { reg = ETDM_IN2_CON2; mask = ETDM_IN_CON2_CLOCK_MASK; - shift = ETDM_IN_CON2_CLOCK_SHIFT; val = FIELD_PREP(ETDM_IN_CON2_CLOCK_MASK, source); } else { return -EINVAL; @@ -715,8 +709,6 @@ static int mt8188_etdm_clk_src_sel_put(struct snd_kcontrol *kcontrol, regmap_read(afe->regmap, reg, &old_val); old_val &= mask; - old_val >>= shift; - if (old_val == val) return 0; @@ -2506,6 +2498,9 @@ static void mt8188_dai_etdm_parse_of(struct mtk_base_afe *afe) /* etdm in only */ for (i = 0; i < 2; i++) { + dai_id = ETDM_TO_DAI_ID(i); + etdm_data = afe_priv->dai_priv[dai_id]; + snprintf(prop, sizeof(prop), "mediatek,%s-chn-disabled", of_afe_etdms[i].name); diff --git a/sound/soc/mediatek/mt8192/mt8192-dai-adda.c b/sound/soc/mediatek/mt8192/mt8192-dai-adda.c index f8c73e8624df..4919535e2759 100644 --- a/sound/soc/mediatek/mt8192/mt8192-dai-adda.c +++ b/sound/soc/mediatek/mt8192/mt8192-dai-adda.c @@ -303,9 +303,6 @@ static int mtk_adda_ul_event(struct snd_soc_dapm_widget *w, struct mt8192_afe_private *afe_priv = afe->platform_priv; int mtkaif_dmic = afe_priv->mtkaif_dmic; - dev_info(afe->dev, "%s(), name %s, event 0x%x, mtkaif_dmic %d\n", - __func__, w->name, event, mtkaif_dmic); - switch (event) { case SND_SOC_DAPM_PRE_PMU: mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA, 1); @@ -345,10 +342,6 @@ static int mtk_adda_ch34_ul_event(struct snd_soc_dapm_widget *w, int mtkaif_dmic = afe_priv->mtkaif_dmic_ch34; int mtkaif_adda6_only = afe_priv->mtkaif_adda6_only; - dev_info(afe->dev, - "%s(), name %s, event 0x%x, mtkaif_dmic %d, mtkaif_adda6_only %d\n", - __func__, w->name, event, mtkaif_dmic, mtkaif_adda6_only); - switch (event) { case SND_SOC_DAPM_PRE_PMU: mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA_CH34, @@ -538,9 +531,6 @@ static int mtk_adda_dl_event(struct snd_soc_dapm_widget *w, struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); - dev_info(afe->dev, "%s(), name %s, event 0x%x\n", - __func__, w->name, event); - switch (event) { case SND_SOC_DAPM_PRE_PMU: mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA, 0); @@ -564,9 +554,6 @@ static int mtk_adda_ch34_dl_event(struct snd_soc_dapm_widget *w, struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); - dev_info(afe->dev, "%s(), name %s, event 0x%x\n", - __func__, w->name, event); - switch (event) { case SND_SOC_DAPM_PRE_PMU: mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA_CH34, @@ -604,19 +591,21 @@ static int stf_positive_gain_set(struct snd_kcontrol *kcontrol, struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); struct mt8192_afe_private *afe_priv = afe->platform_priv; int gain_db = ucontrol->value.integer.value[0]; + bool change = false; afe_priv->stf_positive_gain_db = gain_db; if (gain_db >= 0 && gain_db <= 24) { - regmap_update_bits(afe->regmap, - AFE_SIDETONE_GAIN, - POSITIVE_GAIN_MASK_SFT, - (gain_db / 6) << POSITIVE_GAIN_SFT); + regmap_update_bits_check(afe->regmap, + AFE_SIDETONE_GAIN, + POSITIVE_GAIN_MASK_SFT, + (gain_db / 6) << POSITIVE_GAIN_SFT, + &change); } else { - dev_warn(afe->dev, "%s(), gain_db %d invalid\n", - __func__, gain_db); + return -EINVAL; } - return 0; + + return change; } static int mt8192_adda_dmic_get(struct snd_kcontrol *kcontrol, @@ -637,15 +626,17 @@ static int mt8192_adda_dmic_set(struct snd_kcontrol *kcontrol, struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); struct mt8192_afe_private *afe_priv = afe->platform_priv; int dmic_on; + bool change; dmic_on = ucontrol->value.integer.value[0]; - dev_info(afe->dev, "%s(), kcontrol name %s, dmic_on %d\n", - __func__, kcontrol->id.name, dmic_on); + change = (afe_priv->mtkaif_dmic != dmic_on) || + (afe_priv->mtkaif_dmic_ch34 != dmic_on); afe_priv->mtkaif_dmic = dmic_on; afe_priv->mtkaif_dmic_ch34 = dmic_on; - return 0; + + return change; } static int mt8192_adda6_only_get(struct snd_kcontrol *kcontrol, @@ -666,20 +657,20 @@ static int mt8192_adda6_only_set(struct snd_kcontrol *kcontrol, struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); struct mt8192_afe_private *afe_priv = afe->platform_priv; int mtkaif_adda6_only; + bool change; mtkaif_adda6_only = ucontrol->value.integer.value[0]; - dev_info(afe->dev, "%s(), kcontrol name %s, mtkaif_adda6_only %d\n", - __func__, kcontrol->id.name, mtkaif_adda6_only); - + change = afe_priv->mtkaif_adda6_only != mtkaif_adda6_only; afe_priv->mtkaif_adda6_only = mtkaif_adda6_only; - return 0; + + return change; } static const struct snd_kcontrol_new mtk_adda_controls[] = { SOC_SINGLE("Sidetone_Gain", AFE_SIDETONE_GAIN, SIDE_TONE_GAIN_SFT, SIDE_TONE_GAIN_MASK, 0), - SOC_SINGLE_EXT("Sidetone_Positive_Gain_dB", SND_SOC_NOPM, 0, 100, 0, + SOC_SINGLE_EXT("Sidetone_Positive_Gain_dB", SND_SOC_NOPM, 0, 24, 0, stf_positive_gain_get, stf_positive_gain_set), SOC_SINGLE("ADDA_DL_GAIN", AFE_ADDA_DL_SRC2_CON1, DL_2_GAIN_CTL_PRE_SFT, DL_2_GAIN_CTL_PRE_MASK, 0), @@ -750,9 +741,6 @@ static int mtk_stf_event(struct snd_soc_dapm_widget *w, regmap_read(afe->regmap, AFE_SIDETONE_CON1, ®_value); - dev_info(afe->dev, "%s(), name %s, event 0x%x, ul_rate 0x%x, AFE_SIDETONE_CON1 0x%x\n", - __func__, w->name, event, ul_rate, reg_value); - switch (event) { case SND_SOC_DAPM_PRE_PMU: /* set side tone gain = 0 */ @@ -1163,12 +1151,6 @@ static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream, unsigned int rate = params_rate(params); int id = dai->id; - dev_info(afe->dev, "%s(), id %d, stream %d, rate %d\n", - __func__, - id, - substream->stream, - rate); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { unsigned int dl_src2_con0 = 0; unsigned int dl_src2_con1 = 0; @@ -1441,8 +1423,6 @@ int mt8192_dai_adda_register(struct mtk_base_afe *afe) struct mtk_base_afe_dai *dai; struct mt8192_afe_private *afe_priv = afe->platform_priv; - dev_info(afe->dev, "%s()\n", __func__); - dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); if (!dai) return -ENOMEM; diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c b/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c index c2e268054773..f2c9a1fdbe0d 100644 --- a/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c +++ b/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c @@ -2567,6 +2567,9 @@ static void mt8195_dai_etdm_parse_of(struct mtk_base_afe *afe) /* etdm in only */ for (i = 0; i < 2; i++) { + dai_id = ETDM_TO_DAI_ID(i); + etdm_data = afe_priv->dai_priv[dai_id]; + ret = snprintf(prop, sizeof(prop), "mediatek,%s-chn-disabled", of_afe_etdms[i].name); diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 7bc4421835d7..0b8926600d90 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -39,10 +39,10 @@ struct rsnd_adg { int clkin_size; int clkout_size; u32 ckr; - u32 rbga; - u32 rbgb; + u32 brga; + u32 brgb; - int rbg_rate[ADG_HZ_SIZE]; /* RBGA / RBGB */ + int brg_rate[ADG_HZ_SIZE]; /* BRGA / BRGB */ }; #define for_each_rsnd_clkin(pos, adg, i) \ @@ -75,7 +75,7 @@ static const char * const clkout_name_gen2[] = { [CLKOUT3] = "audio_clkout3", }; -static u32 rsnd_adg_calculate_rbgx(unsigned long div) +static u32 rsnd_adg_calculate_brgx(unsigned long div) { int i; @@ -131,8 +131,8 @@ static void __rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv, adg->clkin_rate[CLKA], /* 0000: CLKA */ adg->clkin_rate[CLKB], /* 0001: CLKB */ adg->clkin_rate[CLKC], /* 0010: CLKC */ - adg->rbg_rate[ADG_HZ_441], /* 0011: RBGA */ - adg->rbg_rate[ADG_HZ_48], /* 0100: RBGB */ + adg->brg_rate[ADG_HZ_441], /* 0011: BRGA */ + adg->brg_rate[ADG_HZ_48], /* 0100: BRGB */ }; min = ~0; @@ -323,10 +323,10 @@ int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate) /* * find divided clock from BRGA/BRGB */ - if (rate == adg->rbg_rate[ADG_HZ_441]) + if (rate == adg->brg_rate[ADG_HZ_441]) return 0x10; - if (rate == adg->rbg_rate[ADG_HZ_48]) + if (rate == adg->brg_rate[ADG_HZ_48]) return 0x20; return -EIO; @@ -358,13 +358,13 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate) ckr = 0x80000000; /* BRGB output = 48kHz */ rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr | ckr); - rsnd_mod_write(adg_mod, BRRA, adg->rbga); - rsnd_mod_write(adg_mod, BRRB, adg->rbgb); + rsnd_mod_write(adg_mod, BRRA, adg->brga); + rsnd_mod_write(adg_mod, BRRB, adg->brgb); dev_dbg(dev, "CLKOUT is based on BRG%c (= %dHz)\n", (ckr) ? 'B' : 'A', - (ckr) ? adg->rbg_rate[ADG_HZ_48] : - adg->rbg_rate[ADG_HZ_441]); + (ckr) ? adg->brg_rate[ADG_HZ_48] : + adg->brg_rate[ADG_HZ_441]); return 0; } @@ -484,7 +484,7 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv) struct device *dev = rsnd_priv_to_dev(priv); struct device_node *np = dev->of_node; struct property *prop; - u32 ckr, rbgx, rbga, rbgb; + u32 ckr, brgx, brga, brgb; u32 rate, div; u32 req_rate[ADG_HZ_SIZE] = {}; uint32_t count = 0; @@ -501,8 +501,8 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv) }; ckr = 0; - rbga = 2; /* default 1/6 */ - rbgb = 2; /* default 1/6 */ + brga = 2; /* default 1/6 */ + brgb = 2; /* default 1/6 */ /* * ADG supports BRRA/BRRB output only @@ -543,30 +543,30 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv) if (0 == rate) /* not used */ continue; - /* RBGA */ - if (!adg->rbg_rate[ADG_HZ_441] && (0 == rate % 44100)) { + /* BRGA */ + if (!adg->brg_rate[ADG_HZ_441] && (0 == rate % 44100)) { div = 6; if (req_Hz[ADG_HZ_441]) div = rate / req_Hz[ADG_HZ_441]; - rbgx = rsnd_adg_calculate_rbgx(div); - if (BRRx_MASK(rbgx) == rbgx) { - rbga = rbgx; - adg->rbg_rate[ADG_HZ_441] = rate / div; + brgx = rsnd_adg_calculate_brgx(div); + if (BRRx_MASK(brgx) == brgx) { + brga = brgx; + adg->brg_rate[ADG_HZ_441] = rate / div; ckr |= brg_table[i] << 20; if (req_Hz[ADG_HZ_441]) parent_clk_name = __clk_get_name(clk); } } - /* RBGB */ - if (!adg->rbg_rate[ADG_HZ_48] && (0 == rate % 48000)) { + /* BRGB */ + if (!adg->brg_rate[ADG_HZ_48] && (0 == rate % 48000)) { div = 6; if (req_Hz[ADG_HZ_48]) div = rate / req_Hz[ADG_HZ_48]; - rbgx = rsnd_adg_calculate_rbgx(div); - if (BRRx_MASK(rbgx) == rbgx) { - rbgb = rbgx; - adg->rbg_rate[ADG_HZ_48] = rate / div; + brgx = rsnd_adg_calculate_brgx(div); + if (BRRx_MASK(brgx) == brgx) { + brgb = brgx; + adg->brg_rate[ADG_HZ_48] = rate / div; ckr |= brg_table[i] << 16; if (req_Hz[ADG_HZ_48]) parent_clk_name = __clk_get_name(clk); @@ -620,8 +620,8 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv) rsnd_adg_get_clkout_end: adg->ckr = ckr; - adg->rbga = rbga; - adg->rbgb = rbgb; + adg->brga = brga; + adg->brgb = brgb; return 0; @@ -663,9 +663,9 @@ void rsnd_adg_clk_dbg_info(struct rsnd_priv *priv, struct seq_file *m) __clk_get_name(clk), clk, clk_get_rate(clk)); dbg_msg(dev, m, "BRGCKR = 0x%08x, BRRA/BRRB = 0x%x/0x%x\n", - adg->ckr, adg->rbga, adg->rbgb); - dbg_msg(dev, m, "BRGA (for 44100 base) = %d\n", adg->rbg_rate[ADG_HZ_441]); - dbg_msg(dev, m, "BRGB (for 48000 base) = %d\n", adg->rbg_rate[ADG_HZ_48]); + adg->ckr, adg->brga, adg->brgb); + dbg_msg(dev, m, "BRGA (for 44100 base) = %d\n", adg->brg_rate[ADG_HZ_441]); + dbg_msg(dev, m, "BRGB (for 48000 base) = %d\n", adg->brg_rate[ADG_HZ_48]); /* * Actual CLKOUT will be exchanged in rsnd_adg_ssi_clk_try_start() diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 005b179a770a..5eb056b942ce 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1088,22 +1088,39 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - int ret = -EINVAL, _ret = 0; + struct snd_soc_component *component; + int ret = -EINVAL, _ret = 0, start_dma_last = 0, i; int rollback = 0; switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + /* Do we need to start dma last? */ + for_each_rtd_components(rtd, i, component) { + if (component->driver->start_dma_last) { + start_dma_last = 1; + break; + } + } + ret = snd_soc_link_trigger(substream, cmd, 0); if (ret < 0) goto start_err; - ret = snd_soc_pcm_component_trigger(substream, cmd, 0); - if (ret < 0) - goto start_err; + if (start_dma_last) { + ret = snd_soc_pcm_dai_trigger(substream, cmd, 0); + if (ret < 0) + goto start_err; + + ret = snd_soc_pcm_component_trigger(substream, cmd, 0); + } else { + ret = snd_soc_pcm_component_trigger(substream, cmd, 0); + if (ret < 0) + goto start_err; - ret = snd_soc_pcm_dai_trigger(substream, cmd, 0); + ret = snd_soc_pcm_dai_trigger(substream, cmd, 0); + } start_err: if (ret < 0) rollback = 1; |