diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-09-25 09:39:33 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-09-25 09:39:33 -0700 |
| commit | 547463efb935dec67c476f90917a0ff4baf6d0b5 (patch) | |
| tree | 1959fb847274893c3f1c432b0fd92874686fe27c /drivers | |
| parent | 80e466f0c8acc545159a1f1fcca62512bf848413 (diff) | |
| parent | 5b76268dac968612f7283d59b539036de955b7d9 (diff) | |
| download | lwn-547463efb935dec67c476f90917a0ff4baf6d0b5.tar.gz lwn-547463efb935dec67c476f90917a0ff4baf6d0b5.zip | |
Merge tag 's390-7.3-4' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 fixes from Heiko Carstens:
- Fix several bugs in PCI error recovery SCLP reporting: don't report
success on skipped recovery, report errors when no pdev is
associated, add missing device lock, and fix struct pci_dev reference
leak in zpci_report_status()
- Fix several bugs in CIO code: fix use of invalid SCHIB data, guard
PMCW field accesses, check device number valid bit in PMWC before
accessing other fields, and fix NULL pointer dereference in
ccw_device_get_util_str()
- Fix virtual vs physical address confusion in channel measurement
facility code on kernels with CONFIG_RANDOMIZE_IDENTITY_BASE=y
- Fix couple of bugs in s390dbf: fix copy of failed static debug areas,
skip view registration on failure, and reject NULL pointer in
debug_dump()
- Fix sriov_numvfs attribute name in zPCI documentation
- Fix typos in comments
* tag 's390-7.3-4' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
s390/cio: Fix NULL pointer dereference in ccw_device_get_util_str()
s390/debug: Fix NULL pointer dereference in debug_info_copy()
s390/debug: Do not register views for failed static debug areas
s390/debug: Reject NULL debug info in debug_dump()
s390/cmf: Fix virtual vs physical address confusion
s390/pci: Don't report recovery success on skipped recovery
s390/pci: Report SCLP status on error events when no pdev is associated
s390/pci: Fix missing device lock in zpci_report_status()
s390/pci: Fix leak of struct pci_dev reference in zpci_report_status()
s390/cio: Guard PMCW field accesses with dnv check
s390/cio: Check pmcw.dnv before pmcw.ena in I/O entry points
s390/cio: Fix cio_update_schib() to not cache invalid schib
s390/pci/docs: Fix sriov_numvfs attribute name
s390: Fix typos in comments
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/s390/block/dasd_3990_erp.c | 6 | ||||
| -rw-r--r-- | drivers/s390/block/dasd_eckd.c | 4 | ||||
| -rw-r--r-- | drivers/s390/char/raw3270.c | 2 | ||||
| -rw-r--r-- | drivers/s390/char/vmlogrdr.c | 2 | ||||
| -rw-r--r-- | drivers/s390/cio/chp.c | 3 | ||||
| -rw-r--r-- | drivers/s390/cio/cio.c | 11 | ||||
| -rw-r--r-- | drivers/s390/cio/cio.h | 5 | ||||
| -rw-r--r-- | drivers/s390/cio/cmf.c | 2 | ||||
| -rw-r--r-- | drivers/s390/cio/device.c | 9 | ||||
| -rw-r--r-- | drivers/s390/cio/device_fsm.c | 3 | ||||
| -rw-r--r-- | drivers/s390/cio/device_ops.c | 23 | ||||
| -rw-r--r-- | drivers/s390/cio/vfio_ccw_fsm.c | 2 |
12 files changed, 53 insertions, 19 deletions
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index 736459477c19..121cb9ae5c67 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c @@ -103,7 +103,7 @@ dasd_3990_erp_int_req(struct dasd_ccw_req * erp) /* first time set initial retry counter and erp_function */ /* and retry once without blocking queue */ - /* (this enables easier enqueing of the cqr) */ + /* (this enables easier enqueuing of the cqr) */ if (erp->function != dasd_3990_erp_int_req) { erp->retries = 256; @@ -302,7 +302,7 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense) /* first time set initial retry counter and erp_function */ /* and retry once without waiting for state change pending */ - /* interrupt (this enables easier enqueing of the cqr) */ + /* interrupt (this enables easier enqueuing of the cqr) */ if (erp->function != dasd_3990_erp_action_4) { DBF_DEV_EVENT(DBF_INFO, device, "%s", @@ -1078,7 +1078,7 @@ dasd_3990_erp_bus_out(struct dasd_ccw_req * erp) /* first time set initial retry counter and erp_function */ /* and retry once without blocking queue */ - /* (this enables easier enqueing of the cqr) */ + /* (this enables easier enqueuing of the cqr) */ if (erp->function != dasd_3990_erp_bus_out) { erp->retries = 256; erp->function = dasd_3990_erp_bus_out; diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 8d976dd58a6c..9d1b11020b4e 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -2060,7 +2060,7 @@ dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav, } /* - * Valide storage server of current device. + * Valid storage server of current device. */ static int dasd_eckd_validate_server(struct dasd_device *device, unsigned long flags) @@ -5672,7 +5672,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_raw(struct dasd_device *startdev, char *dst; /* - * raw track access needs to be mutiple of 64k and on 64k boundary + * raw track access needs to be multiple of 64k and on 64k boundary * For read requests we can fix an incorrect alignment by padding * the request with dummy pages. */ diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index aa9c4d81225c..6861bf27d15f 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -420,7 +420,7 @@ struct raw3270_ua { /* Query Reply structure for Usable Area */ char flags0; char flags1; short w; /* Width of usable area */ - short h; /* Heigth of usavle area */ + short h; /* Height of usavle area */ char units; /* 0x00:in; 0x01:mm */ int xr; int yr; diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c index 383e7e2bd69f..005735a89920 100644 --- a/drivers/s390/char/vmlogrdr.c +++ b/drivers/s390/char/vmlogrdr.c @@ -444,7 +444,7 @@ static int vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv) spin_unlock_bh(&priv->priv_lock); /* An rc of 5 indicates that the record was bigger than * the buffer, which is OK for us. A 9 indicates that the - * record was purged befor we could receive it. + * record was purged before we could receive it. */ if (rc == 5) rc = 0; diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index c890f21a82ce..eaf0527bff6c 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c @@ -78,6 +78,9 @@ u8 chp_get_sch_opm(struct subchannel *sch) int opm; int i; + if (!sch->schib.pmcw.dnv) + return 0; + opm = 0; chp_id_init(&chpid); for (i = 0; i < 8; i++) { diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 70dc8cc76594..e1c62eb60cca 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -453,7 +453,8 @@ EXPORT_SYMBOL_GPL(cio_commit_config); /** * cio_update_schib - Perform stsch and update schib if subchannel is valid. * @sch: subchannel on which to perform stsch - * Return zero on success, -ENODEV otherwise. + * Return zero on success, -ENODEV if the subchannel is not operational, + * -EACCES if the subchannel has no valid device. */ int cio_update_schib(struct subchannel *sch) { @@ -462,10 +463,12 @@ int cio_update_schib(struct subchannel *sch) if (stsch(sch->schid, &schib)) return -ENODEV; - memcpy(&sch->schib, &schib, sizeof(schib)); - - if (!css_sch_is_valid(&schib)) + if (!css_sch_is_valid(&schib)) { + memset(&sch->schib, 0, sizeof(sch->schib)); return -EACCES; + } + + memcpy(&sch->schib, &schib, sizeof(schib)); return 0; } diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h index bad142c536e1..6d28a62bc67a 100644 --- a/drivers/s390/cio/cio.h +++ b/drivers/s390/cio/cio.h @@ -7,6 +7,7 @@ #include <linux/mod_devicetable.h> #include <asm/chpid.h> #include <asm/cio.h> +#include <asm/dma-types.h> #include <asm/fcx.h> #include <asm/schid.h> #include <asm/tpi.h> @@ -49,7 +50,7 @@ struct pmcw { /* Target SCHIB configuration. */ struct schib_config { - u64 mba; + dma64_t mba; u32 intparm; u16 mbi; u32 isc:3; @@ -66,7 +67,7 @@ struct schib_config { struct schib { struct pmcw pmcw; /* path management control word */ union scsw scsw; /* subchannel status word */ - __u64 mba; /* measurement block address */ + dma64_t mba; /* measurement block address */ __u8 mda[4]; /* model dependent area */ } __attribute__ ((packed,aligned(4))); diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index 92ab3d546fe4..66b14fedbd18 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c @@ -183,7 +183,7 @@ static int set_schib(struct ccw_device *cdev, u32 mme, int mbfc, sch->config.mbfc = mbfc; /* address can be either a block address or a block index */ if (mbfc) - sch->config.mba = address; + sch->config.mba = address ? virt_to_dma64((void *)address) : 0; else sch->config.mbi = address; diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index fb591118ecb2..68dd4a62975d 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -922,7 +922,7 @@ static int ccw_device_move_to_sch(struct ccw_device *cdev, if (!sch_is_pseudo_sch(old_sch)) { spin_lock_irq(&old_sch->lock); - old_enabled = old_sch->schib.pmcw.ena; + old_enabled = old_sch->schib.pmcw.dnv && old_sch->schib.pmcw.ena; rc = 0; if (old_enabled) rc = cio_disable_subchannel(old_sch); @@ -941,7 +941,7 @@ static int ccw_device_move_to_sch(struct ccw_device *cdev, CIO_MSG_EVENT(0, "device_move(0.%x.%04x,0.%x.%04x)=%d\n", cdev->private->dev_id.ssid, cdev->private->dev_id.devno, sch->schid.ssid, - sch->schib.pmcw.dev, rc); + sch->schid.sch_no, rc); if (old_enabled) { /* Try to re-enable the old subchannel. */ spin_lock_irq(&old_sch->lock); @@ -1207,7 +1207,7 @@ static void io_subchannel_quiesce(struct subchannel *sch) cdev = sch_get_cdev(sch); if (cio_is_console(sch->schid)) goto out_unlock; - if (!sch->schib.pmcw.ena) + if (!sch->schib.pmcw.dnv || !sch->schib.pmcw.ena) goto out_unlock; ret = cio_disable_subchannel(sch); if (ret != -EBUSY) @@ -1254,7 +1254,8 @@ static int recovery_check(struct device *dev, void *data) switch (cdev->private->state) { case DEV_STATE_ONLINE: sch = to_subchannel(cdev->dev.parent); - if ((sch->schib.pmcw.pam & sch->opm) == sch->vpm) + if (sch->schib.pmcw.dnv && + (sch->schib.pmcw.pam & sch->opm) == sch->vpm) break; fallthrough; case DEV_STATE_DISCONNECTED: diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index ab419d40a8a7..b5686c25c83c 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -170,6 +170,9 @@ __recover_lost_chpids(struct subchannel *sch, int old_lpm) int mask, i; struct chp_id chpid; + if (!sch->schib.pmcw.dnv) + return; + chp_id_init(&chpid); for (i = 0; i<8; i++) { mask = 0x80 >> i; diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index 61c07b4a0fe8..1f7e83fd5087 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -142,6 +142,8 @@ int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm) if (!cdev || !cdev->dev.parent) return -ENODEV; sch = to_subchannel(cdev->dev.parent); + if (!sch->schib.pmcw.dnv) + return -ENODEV; if (!sch->schib.pmcw.ena) return -EINVAL; if (cdev->private->state == DEV_STATE_NOT_OPER) @@ -198,6 +200,8 @@ int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa, if (!cdev || !cdev->dev.parent) return -ENODEV; sch = to_subchannel(cdev->dev.parent); + if (!sch->schib.pmcw.dnv) + return -ENODEV; if (!sch->schib.pmcw.ena) return -EINVAL; if (cdev->private->state == DEV_STATE_NOT_OPER) @@ -379,6 +383,8 @@ int ccw_device_halt(struct ccw_device *cdev, unsigned long intparm) if (!cdev || !cdev->dev.parent) return -ENODEV; sch = to_subchannel(cdev->dev.parent); + if (!sch->schib.pmcw.dnv) + return -ENODEV; if (!sch->schib.pmcw.ena) return -EINVAL; if (cdev->private->state == DEV_STATE_NOT_OPER) @@ -413,6 +419,8 @@ int ccw_device_resume(struct ccw_device *cdev) if (!cdev || !cdev->dev.parent) return -ENODEV; sch = to_subchannel(cdev->dev.parent); + if (!sch->schib.pmcw.dnv) + return -ENODEV; if (!sch->schib.pmcw.ena) return -EINVAL; if (cdev->private->state == DEV_STATE_NOT_OPER) @@ -482,6 +490,8 @@ struct channel_path_desc_fmt0 *ccw_device_get_chp_desc(struct ccw_device *cdev, struct chp_id chpid; sch = to_subchannel(cdev->dev.parent); + if (!sch->schib.pmcw.dnv) + return NULL; chp_id_init(&chpid); chpid.id = sch->schib.pmcw.chpid[chp_idx]; return chp_get_chp_desc(chpid); @@ -502,9 +512,13 @@ u8 *ccw_device_get_util_str(struct ccw_device *cdev, int chp_idx) struct chp_id chpid; u8 *util_str; + if (!sch->schib.pmcw.dnv) + return NULL; chp_id_init(&chpid); chpid.id = sch->schib.pmcw.chpid[chp_idx]; chp = chpid_to_chp(chpid); + if (!chp) + return NULL; util_str = kmalloc(sizeof(chp->desc_fmt3.util_str), GFP_KERNEL); if (!util_str) @@ -548,6 +562,8 @@ int ccw_device_tm_start_timeout_key(struct ccw_device *cdev, struct tcw *tcw, int rc; sch = to_subchannel(cdev->dev.parent); + if (!sch->schib.pmcw.dnv) + return -ENODEV; if (!sch->schib.pmcw.ena) return -EINVAL; if (cdev->private->state == DEV_STATE_VERIFY) { @@ -652,6 +668,9 @@ int ccw_device_get_mdc(struct ccw_device *cdev, u8 mask) struct chp_id chpid; int mdc = 0, i; + if (!sch->schib.pmcw.dnv) + return 0; + /* Adjust requested path mask to excluded varied off paths. */ if (mask) mask &= sch->lpm; @@ -694,6 +713,8 @@ int ccw_device_tm_intrg(struct ccw_device *cdev) { struct subchannel *sch = to_subchannel(cdev->dev.parent); + if (!sch->schib.pmcw.dnv) + return -ENODEV; if (!sch->schib.pmcw.ena) return -EINVAL; if (cdev->private->state != DEV_STATE_ONLINE) @@ -786,6 +807,8 @@ int ccw_device_get_chpid(struct ccw_device *cdev, int chp_idx, u8 *chpid) if ((chp_idx < 0) || (chp_idx > 7)) return -EINVAL; + if (!sch->schib.pmcw.dnv) + return -ENODEV; mask = 0x80 >> chp_idx; if (!(sch->schib.pmcw.pim & mask)) return -ENODEV; diff --git a/drivers/s390/cio/vfio_ccw_fsm.c b/drivers/s390/cio/vfio_ccw_fsm.c index 5fd94e9d5c61..9a000b0231d6 100644 --- a/drivers/s390/cio/vfio_ccw_fsm.c +++ b/drivers/s390/cio/vfio_ccw_fsm.c @@ -399,7 +399,7 @@ static void fsm_close(struct vfio_ccw_private *private, spin_lock_irq(&sch->lock); - if (!sch->schib.pmcw.ena) + if (!sch->schib.pmcw.dnv || !sch->schib.pmcw.ena) goto err_unlock; ret = cio_disable_subchannel(sch); |
