diff --git a/Makefile.rhelver b/Makefile.rhelver index 5f1c58fe9d267..bb63aef0444c6 100644 --- a/Makefile.rhelver +++ b/Makefile.rhelver @@ -12,7 +12,7 @@ RHEL_MINOR = 10 # # Use this spot to avoid future merge conflicts. # Do not trim this comment. -RHEL_RELEASE = 553.36.1 +RHEL_RELEASE = 553.40.1 # # ZSTREAM diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index 48f6b77fdece9..8cc612ca57d1d 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c @@ -975,6 +975,7 @@ void do_sve_acc(unsigned int esr, struct pt_regs *regs) fpsimd_bind_task_to_cpu(); } else { fpsimd_to_sve(current); + fpsimd_flush_task_state(current); } put_cpu_fpsimd_context(); diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h index 15948089980af..6652630be19e6 100644 --- a/arch/s390/include/asm/pci.h +++ b/arch/s390/include/asm/pci.h @@ -108,9 +108,10 @@ struct zpci_bus { struct list_head resources; struct list_head bus_next; struct resource bus_resource; - int pchid; + int topo; /* TID if topo_is_tid, PCHID otherwise */ int domain_nr; - bool multifunction; + u8 multifunction : 1; + u8 topo_is_tid : 1; enum pci_bus_speed max_bus_speed; }; @@ -129,6 +130,8 @@ struct zpci_dev { u16 vfn; /* virtual function number */ u16 pchid; /* physical channel ID */ u16 maxstbl; /* Maximum store block size */ + u16 rid; /* RID as supplied by firmware */ + u16 tid; /* Topology for which RID is valid */ u8 pfgid; /* function group ID */ u8 pft; /* pci function type */ u8 port; @@ -139,7 +142,8 @@ struct zpci_dev { u8 is_physfn : 1; u8 util_str_avail : 1; u8 irqs_registered : 1; - u8 reserved : 2; + u8 tid_avail : 1; + u8 reserved : 1; unsigned int devfn; /* DEVFN part of the RID*/ struct mutex lock; @@ -215,12 +219,14 @@ extern struct airq_iv *zpci_aif_sbv; ----------------------------------------------------------------------------- */ /* Base stuff */ struct zpci_dev *zpci_create_device(u32 fid, u32 fh, enum zpci_state state); +int zpci_add_device(struct zpci_dev *zdev); int zpci_enable_device(struct zpci_dev *); int zpci_disable_device(struct zpci_dev *); int zpci_scan_configured_device(struct zpci_dev *zdev, u32 fh); int zpci_deconfigure_device(struct zpci_dev *zdev); void zpci_device_reserved(struct zpci_dev *zdev); bool zpci_is_device_configured(struct zpci_dev *zdev); +int zpci_scan_devices(void); int zpci_hot_reset_device(struct zpci_dev *zdev); int zpci_register_ioat(struct zpci_dev *, u8, u64, u64, u64, u8 *); @@ -231,7 +237,7 @@ void zpci_update_fh(struct zpci_dev *zdev, u32 fh); /* CLP */ int rhel8_clp_rescan_pci_devices_simple(void); int clp_setup_writeback_mio(void); -int clp_scan_pci_devices(void); +int clp_scan_pci_devices(struct list_head *scan_list); int clp_query_pci_fn(struct zpci_dev *zdev); int clp_enable_fh(struct zpci_dev *zdev, u32 *fh, u8 nr_dma_as); int clp_disable_fh(struct zpci_dev *zdev, u32 *fh); diff --git a/arch/s390/include/asm/pci_clp.h b/arch/s390/include/asm/pci_clp.h index d6189ed14f848..883aba330fea3 100644 --- a/arch/s390/include/asm/pci_clp.h +++ b/arch/s390/include/asm/pci_clp.h @@ -107,7 +107,8 @@ struct clp_req_query_pci { struct clp_rsp_query_pci { struct clp_rsp_hdr hdr; u16 vfn; /* virtual fn number */ - u16 : 3; + u16 : 2; + u16 tid_avail : 1; u16 rid_avail : 1; u16 is_physfn : 1; u16 reserved1 : 1; @@ -127,8 +128,9 @@ struct clp_rsp_query_pci { u64 edma; /* end dma as */ #define ZPCI_RID_MASK_DEVFN 0x00ff u16 rid; /* BUS/DEVFN PCI address */ - u16 reserved0; - u32 reserved[10]; + u32 reserved0; + u16 tid; + u32 reserved[9]; u32 uid; /* user defined id */ u8 util_str[CLP_UTIL_STR_LEN]; /* utility string */ u32 reserved2[16]; diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 162ca752cec90..661c4e000c5bf 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -859,8 +860,9 @@ int zpci_hot_reset_device(struct zpci_dev *zdev) * @fh: Current Function Handle of the device to be created * @state: Initial state after creation either Standby or Configured * - * Creates a new zpci device and adds it to its, possibly newly created, zbus - * as well as zpci_list. + * Allocates a new struct zpci_dev and queries the platform for its details. + * If successful the device can subsequently be added to the zPCI subsystem + * using zpci_add_device(). * * Returns: the zdev on success or an error pointer otherwise */ @@ -869,7 +871,6 @@ struct zpci_dev *zpci_create_device(u32 fid, u32 fh, enum zpci_state state) struct zpci_dev *zdev; int rc; - zpci_dbg(1, "add fid:%x, fh:%x, c:%d\n", fid, fh, state); zdev = kzalloc(sizeof(*zdev), GFP_KERNEL); if (!zdev) return ERR_PTR(-ENOMEM); @@ -884,10 +885,33 @@ struct zpci_dev *zpci_create_device(u32 fid, u32 fh, enum zpci_state state) goto error; zdev->state = state; - kref_init(&zdev->kref); mutex_init(&zdev->lock); mutex_init(&zdev->kzdev_lock); + return zdev; + +error: + zpci_dbg(0, "crt fid:%x, rc:%d\n", fid, rc); + kfree(zdev); + return ERR_PTR(rc); +} + +/** + * zpci_add_device() - Add a previously created zPCI device to the zPCI subsystem + * @zdev: The zPCI device to be added + * + * A struct zpci_dev is added to the zPCI subsystem and to a virtual PCI bus creating + * a new one as necessary. A hotplug slot is created and events start to be handled. + * If successful from this point on zpci_zdev_get() and zpci_zdev_put() must be used. + * If adding the struct zpci_dev fails the device was not added and should be freed. + * + * Return: 0 on success, or an error code otherwise + */ +int zpci_add_device(struct zpci_dev *zdev) +{ + int rc; + + zpci_dbg(1, "add fid:%x, fh:%x, c:%d\n", zdev->fid, zdev->fh, zdev->state); rc = zpci_init_iommu(zdev); if (rc) goto error; @@ -896,18 +920,17 @@ struct zpci_dev *zpci_create_device(u32 fid, u32 fh, enum zpci_state state) if (rc) goto error_destroy_iommu; + kref_init(&zdev->kref); spin_lock(&zpci_list_lock); list_add_tail(&zdev->entry, &zpci_list); spin_unlock(&zpci_list_lock); - - return zdev; + return 0; error_destroy_iommu: zpci_destroy_iommu(zdev); error: - zpci_dbg(0, "add fid:%x, rc:%d\n", fid, rc); - kfree(zdev); - return ERR_PTR(rc); + zpci_dbg(0, "add fid:%x, rc:%d\n", zdev->fid, rc); + return rc; } bool zpci_is_device_configured(struct zpci_dev *zdev) @@ -1168,6 +1191,50 @@ bool zpci_is_enabled(void) return s390_pci_initialized; } +static int zpci_cmp_rid(void *priv, struct list_head *a, + struct list_head *b) +{ + struct zpci_dev *za = container_of(a, struct zpci_dev, entry); + struct zpci_dev *zb = container_of(b, struct zpci_dev, entry); + + /* + * PCI functions without RID available maintain original order + * between themselves but sort before those with RID. + */ + if (za->rid == zb->rid) + return za->rid_available > zb->rid_available; + /* + * PCI functions with RID sort by RID ascending. + */ + return za->rid > zb->rid; +} + +static void zpci_add_devices(struct list_head *scan_list) +{ + struct zpci_dev *zdev, *tmp; + + list_sort(NULL, scan_list, &zpci_cmp_rid); + list_for_each_entry_safe(zdev, tmp, scan_list, entry) { + list_del_init(&zdev->entry); + if (zpci_add_device(zdev)) + kfree(zdev); + } +} + +int zpci_scan_devices(void) +{ + LIST_HEAD(scan_list); + int rc; + + rc = clp_scan_pci_devices(&scan_list); + if (rc) + return rc; + + zpci_add_devices(&scan_list); + zpci_bus_scan_busses(); + return 0; +} + static int __init pci_base_init(void) { int rc; @@ -1201,10 +1268,9 @@ static int __init pci_base_init(void) if (rc) goto out_dma; - rc = clp_scan_pci_devices(); + rc = zpci_scan_devices(); if (rc) goto out_find; - zpci_bus_scan_busses(); s390_pci_initialized = 1; return 0; diff --git a/arch/s390/pci/pci_bus.c b/arch/s390/pci/pci_bus.c index 32245b970a0cf..67e51bb93e8ee 100644 --- a/arch/s390/pci/pci_bus.c +++ b/arch/s390/pci/pci_bus.c @@ -173,9 +173,16 @@ void zpci_bus_scan_busses(void) mutex_unlock(&zbus_list_lock); } +static bool zpci_bus_is_multifunction_root(struct zpci_dev *zdev) +{ + return !s390_pci_no_rid && zdev->rid_available && + zpci_is_device_configured(zdev) && + !zdev->vfn; +} + /* zpci_bus_create_pci_bus - Create the PCI bus associated with this zbus * @zbus: the zbus holding the zdevices - * @fr: PCI root function that will determine the bus's domain, and bus speeed + * @fr: PCI root function that will determine the bus's domain, and bus speed * @ops: the pci operations * * The PCI function @fr determines the domain (its UID), multifunction property @@ -193,7 +200,7 @@ static int zpci_bus_create_pci_bus(struct zpci_bus *zbus, struct zpci_dev *fr, s return domain; zbus->domain_nr = domain; - zbus->multifunction = fr->rid_available; + zbus->multifunction = zpci_bus_is_multifunction_root(fr); zbus->max_bus_speed = fr->max_bus_speed; /* @@ -237,13 +244,15 @@ static void zpci_bus_put(struct zpci_bus *zbus) kref_put(&zbus->kref, zpci_bus_release); } -static struct zpci_bus *zpci_bus_get(int pchid) +static struct zpci_bus *zpci_bus_get(int topo, bool topo_is_tid) { struct zpci_bus *zbus; mutex_lock(&zbus_list_lock); list_for_each_entry(zbus, &zbus_list, bus_next) { - if (pchid == zbus->pchid) { + if (!zbus->multifunction) + continue; + if (topo_is_tid == zbus->topo_is_tid && topo == zbus->topo) { kref_get(&zbus->kref); goto out_unlock; } @@ -254,7 +263,7 @@ static struct zpci_bus *zpci_bus_get(int pchid) return zbus; } -static struct zpci_bus *zpci_bus_alloc(int pchid) +static struct zpci_bus *zpci_bus_alloc(int topo, bool topo_is_tid) { struct zpci_bus *zbus; @@ -262,7 +271,8 @@ static struct zpci_bus *zpci_bus_alloc(int pchid) if (!zbus) return NULL; - zbus->pchid = pchid; + zbus->topo = topo; + zbus->topo_is_tid = topo_is_tid; INIT_LIST_HEAD(&zbus->bus_next); mutex_lock(&zbus_list_lock); list_add_tail(&zbus->bus_next, &zbus_list); @@ -297,19 +307,22 @@ static int zpci_bus_add_device(struct zpci_bus *zbus, struct zpci_dev *zdev) { int rc = -EINVAL; + if (zbus->multifunction) { + if (!zdev->rid_available) { + WARN_ONCE(1, "rid_available not set for multifunction\n"); + return rc; + } + zdev->devfn = zdev->rid & ZPCI_RID_MASK_DEVFN; + } + if (zbus->function[zdev->devfn]) { pr_err("devfn %04x is already assigned\n", zdev->devfn); return rc; } - zdev->zbus = zbus; zbus->function[zdev->devfn] = zdev; zpci_nb_devices++; - if (zbus->multifunction && !zdev->rid_available) { - WARN_ONCE(1, "rid_available not set for multifunction\n"); - goto error; - } rc = zpci_init_slot(zdev); if (rc) goto error; @@ -326,8 +339,9 @@ static int zpci_bus_add_device(struct zpci_bus *zbus, struct zpci_dev *zdev) int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops) { + bool topo_is_tid = zdev->tid_avail; struct zpci_bus *zbus = NULL; - int rc = -EBADF; + int topo, rc = -EBADF; if (zpci_nb_devices == ZPCI_NR_DEVICES) { pr_warn("Adding PCI function %08x failed because the configured limit of %d is reached\n", @@ -335,14 +349,10 @@ int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops) return -ENOSPC; } - if (zdev->devfn >= ZPCI_FUNCTIONS_PER_BUS) - return -EINVAL; - - if (!s390_pci_no_rid && zdev->rid_available) - zbus = zpci_bus_get(zdev->pchid); - + topo = topo_is_tid ? zdev->tid : zdev->pchid; + zbus = zpci_bus_get(topo, topo_is_tid); if (!zbus) { - zbus = zpci_bus_alloc(zdev->pchid); + zbus = zpci_bus_alloc(topo, topo_is_tid); if (!zbus) return -ENOMEM; } diff --git a/arch/s390/pci/pci_clp.c b/arch/s390/pci/pci_clp.c index 34759316747b6..060523557b8e3 100644 --- a/arch/s390/pci/pci_clp.c +++ b/arch/s390/pci/pci_clp.c @@ -163,10 +163,13 @@ static int clp_store_query_pci_fn(struct zpci_dev *zdev, zdev->port = response->port; zdev->uid = response->uid; zdev->fmb_length = sizeof(u32) * response->fmb_len; - zdev->rid_available = response->rid_avail; zdev->is_physfn = response->is_physfn; - if (!s390_pci_no_rid && zdev->rid_available) - zdev->devfn = response->rid & ZPCI_RID_MASK_DEVFN; + zdev->rid_available = response->rid_avail; + if (zdev->rid_available) + zdev->rid = response->rid; + zdev->tid_avail = response->tid_avail; + if (zdev->tid_avail) + zdev->tid = response->tid; memcpy(zdev->pfip, response->pfip, sizeof(zdev->pfip)); if (response->util_str_avail) { @@ -406,6 +409,7 @@ static int clp_find_pci(struct clp_req_rsp_list_pci *rrb, u32 fid, static void __clp_add(struct clp_fh_list_entry *entry, void *data) { + struct list_head *scan_list = data; struct zpci_dev *zdev; if (!entry->vendor_id) @@ -416,10 +420,11 @@ static void __clp_add(struct clp_fh_list_entry *entry, void *data) zpci_zdev_put(zdev); return; } - zpci_create_device(entry->fid, entry->fh, entry->config_state); + zdev = zpci_create_device(entry->fid, entry->fh, entry->config_state); + list_add_tail(&zdev->entry, scan_list); } -int clp_scan_pci_devices(void) +int clp_scan_pci_devices(struct list_head *scan_list) { struct clp_req_rsp_list_pci *rrb; int rc; @@ -428,7 +433,7 @@ int clp_scan_pci_devices(void) if (!rrb) return -ENOMEM; - rc = clp_list_pci(rrb, NULL, __clp_add); + rc = clp_list_pci(rrb, scan_list, __clp_add); clp_free_block(rrb); return rc; diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c index b9324ca2eb940..dcebe41181954 100644 --- a/arch/s390/pci/pci_event.c +++ b/arch/s390/pci/pci_event.c @@ -272,18 +272,19 @@ static void __zpci_event_error(struct zpci_ccdf_err *ccdf) goto no_pdev; switch (ccdf->pec) { - case 0x003a: /* Service Action or Error Recovery Successful */ + case 0x002a: /* Error event concerns FMB */ + case 0x002b: + case 0x002c: + break; + case 0x0040: /* Service Action or Error Recovery Failed */ + case 0x003b: + zpci_event_io_failure(pdev, pci_channel_io_perm_failure); + break; + default: /* PCI function left in the error state attempt to recover */ ers_res = zpci_event_attempt_error_recovery(pdev); if (ers_res != PCI_ERS_RESULT_RECOVERED) zpci_event_io_failure(pdev, pci_channel_io_perm_failure); break; - default: - /* - * Mark as frozen not permanently failed because the device - * could be subsequently recovered by the platform. - */ - zpci_event_io_failure(pdev, pci_channel_io_frozen); - break; } pci_dev_put(pdev); no_pdev: @@ -327,6 +328,10 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) zdev = zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_CONFIGURED); if (IS_ERR(zdev)) break; + if (zpci_add_device(zdev)) { + kfree(zdev); + break; + } } else { /* the configuration request may be stale */ if (zdev->state != ZPCI_FN_STATE_STANDBY) @@ -336,10 +341,17 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) zpci_scan_configured_device(zdev, ccdf->fh); break; case 0x0302: /* Reserved -> Standby */ - if (!zdev) - zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_STANDBY); - else + if (!zdev) { + zdev = zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_STANDBY); + if (IS_ERR(zdev)) + break; + if (zpci_add_device(zdev)) { + kfree(zdev); + break; + } + } else { zpci_update_fh(zdev, ccdf->fh); + } break; case 0x0303: /* Deconfiguration requested */ if (zdev) { @@ -368,7 +380,7 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) break; case 0x0306: /* 0x308 or 0x302 for multiple devices */ zpci_remove_reserved_devices(); - clp_scan_pci_devices(); + zpci_scan_devices(); break; case 0x0308: /* Standby -> Reserved */ if (!zdev) diff --git a/arch/s390/pci/pci_irq.c b/arch/s390/pci/pci_irq.c index 192f3b104ae4a..6beaafe8ef171 100644 --- a/arch/s390/pci/pci_irq.c +++ b/arch/s390/pci/pci_irq.c @@ -269,32 +269,20 @@ static void zpci_floating_irq_handler(struct airq_struct *airq, } } -int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) +static int __alloc_airq(struct zpci_dev *zdev, int msi_vecs, + unsigned long *bit) { - struct zpci_dev *zdev = to_zpci(pdev); - unsigned int hwirq, msi_vecs, cpu; - unsigned long bit; - struct msi_desc *msi; - struct msi_msg msg; - int rc, irq; - - zdev->aisb = -1UL; - zdev->msi_first_bit = -1U; - if (type == PCI_CAP_ID_MSI && nvec > 1) - return 1; - msi_vecs = min_t(unsigned int, nvec, zdev->max_msi); - if (irq_delivery == DIRECTED) { /* Allocate cpu vector bits */ - bit = airq_iv_alloc(zpci_ibv[0], msi_vecs); - if (bit == -1UL) + *bit = airq_iv_alloc(zpci_ibv[0], msi_vecs); + if (*bit == -1UL) return -EIO; } else { /* Allocate adapter summary indicator bit */ - bit = airq_iv_alloc_bit(zpci_sbv); - if (bit == -1UL) + *bit = airq_iv_alloc_bit(zpci_sbv); + if (*bit == -1UL) return -EIO; - zdev->aisb = bit; + zdev->aisb = *bit; /* Create adapter interrupt vector */ zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA | AIRQ_IV_BITLOCK, NULL); @@ -302,58 +290,101 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) return -ENOMEM; /* Wire up shortcut pointer */ - zpci_ibv[bit] = zdev->aibv; + zpci_ibv[*bit] = zdev->aibv; /* Each function has its own interrupt vector */ - bit = 0; + *bit = 0; + } + return 0; +} + +int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) +{ + unsigned int hwirq, msi_vecs, irqs_per_msi, i, cpu; + struct zpci_dev *zdev = to_zpci(pdev); + unsigned long bit; + struct msi_desc *msi; + struct msi_msg msg; + int rc, irq; + + zdev->aisb = -1UL; + zdev->msi_first_bit = -1U; + + msi_vecs = min_t(unsigned int, nvec, zdev->max_msi); + if (msi_vecs < nvec) { + pr_info("%s requested %d irqs, allocate system limit of %d", + pci_name(pdev), nvec, zdev->max_msi); } - /* Request MSI interrupts */ + rc = __alloc_airq(zdev, msi_vecs, &bit); + if (rc < 0) + return rc; + + /* + * Request MSI interrupts: + * When using MSI, nvec_used interrupt sources and their irq + * descriptors are controlled through one msi descriptor. + * Thus the outer loop over msi descriptors shall run only once, + * while two inner loops iterate over the interrupt vectors. + * When using MSI-X, each interrupt vector/irq descriptor + * is bound to exactly one msi descriptor (nvec_used is one). + * So the inner loops are executed once, while the outer iterates + * over the MSI-X descriptors. + */ + hwirq = bit; for_each_pci_msi_entry(msi, pdev) { - rc = -EIO; if (hwirq - bit >= msi_vecs) break; - irq = __irq_alloc_descs(-1, 0, 1, 0, THIS_MODULE, - (irq_delivery == DIRECTED) ? - msi->affinity : NULL); + irqs_per_msi = min_t(unsigned int, msi_vecs, msi->nvec_used); + irq = __irq_alloc_descs(-1, 0, irqs_per_msi, 0, THIS_MODULE, + (irq_delivery == DIRECTED) ? + msi->affinity : NULL); if (irq < 0) return -ENOMEM; - rc = irq_set_msi_desc(irq, msi); - if (rc) - return rc; - irq_set_chip_and_handler(irq, &zpci_irq_chip, - handle_percpu_irq); + + for (i = 0; i < irqs_per_msi; i++) { + rc = irq_set_msi_desc_off(irq, i, msi); + if (rc) + return rc; + irq_set_chip_and_handler(irq + i, &zpci_irq_chip, + handle_percpu_irq); + } + msg.data = hwirq - bit; if (irq_delivery == DIRECTED) { msg.address_lo = zdev->msi_addr & 0xff0000ff; msg.address_lo |= msi->affinity ? (cpumask_first(&msi->affinity->mask) << 8) : 0; for_each_possible_cpu(cpu) { - airq_iv_set_data(zpci_ibv[cpu], hwirq, irq); + for (i = 0; i < irqs_per_msi; i++) + airq_iv_set_data(zpci_ibv[cpu], + hwirq + i, irq + i); } } else { msg.address_lo = zdev->msi_addr & 0xffffffff; - airq_iv_set_data(zdev->aibv, hwirq, irq); + for (i = 0; i < irqs_per_msi; i++) + airq_iv_set_data(zdev->aibv, hwirq + i, irq + i); } msg.address_hi = zdev->msi_addr >> 32; pci_write_msi_msg(irq, &msg); - hwirq++; + hwirq += irqs_per_msi; } zdev->msi_first_bit = bit; - zdev->msi_nr_irqs = msi_vecs; + zdev->msi_nr_irqs = hwirq - bit; rc = zpci_set_irq(zdev); if (rc) return rc; - return (msi_vecs == nvec) ? 0 : msi_vecs; + return (zdev->msi_nr_irqs == nvec) ? 0 : zdev->msi_nr_irqs; } void arch_teardown_msi_irqs(struct pci_dev *pdev) { struct zpci_dev *zdev = to_zpci(pdev); struct msi_desc *msi; + unsigned int i; int rc; /* Disable interrupts */ @@ -365,12 +396,18 @@ void arch_teardown_msi_irqs(struct pci_dev *pdev) for_each_pci_msi_entry(msi, pdev) { if (!msi->irq) continue; - if (msi->msi_attrib.is_msix) + if (msi->msi_attrib.is_msix) { __pci_msix_desc_mask_irq(msi, 1); - else - __pci_msi_desc_mask_irq(msi, 1, 1); - irq_set_msi_desc(msi->irq, NULL); - irq_free_desc(msi->irq); + irq_set_msi_desc(msi->irq, NULL); + irq_free_desc(msi->irq); + } + else { + __pci_msi_desc_mask_irq(msi, 1, msi->nvec_used); + for (i = 0; i < msi->nvec_used; i++) { + irq_set_msi_desc(msi->irq + i, NULL); + irq_free_desc(msi->irq + i); + } + } msi->msg.address_lo = 0; msi->msg.address_hi = 0; msi->msg.data = 0; diff --git a/ciq/ciq_backports/kernel-4.18.0-553.37.1.el8_10/751ecf6a.failed b/ciq/ciq_backports/kernel-4.18.0-553.37.1.el8_10/751ecf6a.failed new file mode 100644 index 0000000000000..476e77f3781ad --- /dev/null +++ b/ciq/ciq_backports/kernel-4.18.0-553.37.1.el8_10/751ecf6a.failed @@ -0,0 +1,251 @@ +arm64/sve: Discard stale CPU state when handling SVE traps + +jira LE-2349 +cve CVE-2024-50275 +Rebuild_History Non-Buildable kernel-4.18.0-553.37.1.el8_10 +commit-author Mark Brown +commit 751ecf6afd6568adc98f2a6052315552c0483d18 +Empty-Commit: Cherry-Pick Conflicts during history rebuild. +Will be included in final tarball splat. Ref for failed cherry-pick at: +ciq/ciq_backports/kernel-4.18.0-553.37.1.el8_10/751ecf6a.failed + +The logic for handling SVE traps manipulates saved FPSIMD/SVE state +incorrectly, and a race with preemption can result in a task having +TIF_SVE set and TIF_FOREIGN_FPSTATE clear even though the live CPU state +is stale (e.g. with SVE traps enabled). This has been observed to result +in warnings from do_sve_acc() where SVE traps are not expected while +TIF_SVE is set: + +| if (test_and_set_thread_flag(TIF_SVE)) +| WARN_ON(1); /* SVE access shouldn't have trapped */ + +Warnings of this form have been reported intermittently, e.g. + + https://lore.kernel.org/linux-arm-kernel/CA+G9fYtEGe_DhY2Ms7+L7NKsLYUomGsgqpdBj+QwDLeSg=JhGg@mail.gmail.com/ + https://lore.kernel.org/linux-arm-kernel/000000000000511e9a060ce5a45c@google.com/ + +The race can occur when the SVE trap handler is preempted before and +after manipulating the saved FPSIMD/SVE state, starting and ending on +the same CPU, e.g. + +| void do_sve_acc(unsigned long esr, struct pt_regs *regs) +| { +| // Trap on CPU 0 with TIF_SVE clear, SVE traps enabled +| // task->fpsimd_cpu is 0. +| // per_cpu_ptr(&fpsimd_last_state, 0) is task. +| +| ... +| +| // Preempted; migrated from CPU 0 to CPU 1. +| // TIF_FOREIGN_FPSTATE is set. +| +| get_cpu_fpsimd_context(); +| +| if (test_and_set_thread_flag(TIF_SVE)) +| WARN_ON(1); /* SVE access shouldn't have trapped */ +| +| sve_init_regs() { +| if (!test_thread_flag(TIF_FOREIGN_FPSTATE)) { +| ... +| } else { +| fpsimd_to_sve(current); +| current->thread.fp_type = FP_STATE_SVE; +| } +| } +| +| put_cpu_fpsimd_context(); +| +| // Preempted; migrated from CPU 1 to CPU 0. +| // task->fpsimd_cpu is still 0 +| // If per_cpu_ptr(&fpsimd_last_state, 0) is still task then: +| // - Stale HW state is reused (with SVE traps enabled) +| // - TIF_FOREIGN_FPSTATE is cleared +| // - A return to userspace skips HW state restore +| } + +Fix the case where the state is not live and TIF_FOREIGN_FPSTATE is set +by calling fpsimd_flush_task_state() to detach from the saved CPU +state. This ensures that a subsequent context switch will not reuse the +stale CPU state, and will instead set TIF_FOREIGN_FPSTATE, forcing the +new state to be reloaded from memory prior to a return to userspace. + +Fixes: cccb78ce89c4 ("arm64/sve: Rework SVE access trap to convert state in registers") + Reported-by: Mark Rutland + Signed-off-by: Mark Brown + Cc: stable@vger.kernel.org + Reviewed-by: Mark Rutland +Link: https://lore.kernel.org/r/20241030-arm64-fpsimd-foreign-flush-v1-1-bd7bd66905a2@kernel.org + Signed-off-by: Will Deacon +(cherry picked from commit 751ecf6afd6568adc98f2a6052315552c0483d18) + Signed-off-by: Jonathan Maple + +# Conflicts: +# arch/arm64/kernel/fpsimd.c +diff --cc arch/arm64/kernel/fpsimd.c +index 48f6b77fdece,6d21971ae559..000000000000 +--- a/arch/arm64/kernel/fpsimd.c ++++ b/arch/arm64/kernel/fpsimd.c +@@@ -934,6 -1218,159 +934,162 @@@ void fpsimd_release_task(struct task_st + + #endif /* CONFIG_ARM64_SVE */ + +++<<<<<<< HEAD +++======= ++ #ifdef CONFIG_ARM64_SME ++ ++ /* ++ * Ensure that task->thread.sme_state is allocated and sufficiently large. ++ * ++ * This function should be used only in preparation for replacing ++ * task->thread.sme_state with new data. The memory is always zeroed ++ * here to prevent stale data from showing through: this is done in ++ * the interest of testability and predictability, the architecture ++ * guarantees that when ZA is enabled it will be zeroed. ++ */ ++ void sme_alloc(struct task_struct *task, bool flush) ++ { ++ if (task->thread.sme_state) { ++ if (flush) ++ memset(task->thread.sme_state, 0, ++ sme_state_size(task)); ++ return; ++ } ++ ++ /* This could potentially be up to 64K. */ ++ task->thread.sme_state = ++ kzalloc(sme_state_size(task), GFP_KERNEL); ++ } ++ ++ static void sme_free(struct task_struct *task) ++ { ++ kfree(task->thread.sme_state); ++ task->thread.sme_state = NULL; ++ } ++ ++ void cpu_enable_sme(const struct arm64_cpu_capabilities *__always_unused p) ++ { ++ /* Set priority for all PEs to architecturally defined minimum */ ++ write_sysreg_s(read_sysreg_s(SYS_SMPRI_EL1) & ~SMPRI_EL1_PRIORITY_MASK, ++ SYS_SMPRI_EL1); ++ ++ /* Allow SME in kernel */ ++ write_sysreg(read_sysreg(CPACR_EL1) | CPACR_EL1_SMEN_EL1EN, CPACR_EL1); ++ isb(); ++ ++ /* Ensure all bits in SMCR are set to known values */ ++ write_sysreg_s(0, SYS_SMCR_EL1); ++ ++ /* Allow EL0 to access TPIDR2 */ ++ write_sysreg(read_sysreg(SCTLR_EL1) | SCTLR_ELx_ENTP2, SCTLR_EL1); ++ isb(); ++ } ++ ++ void cpu_enable_sme2(const struct arm64_cpu_capabilities *__always_unused p) ++ { ++ /* This must be enabled after SME */ ++ BUILD_BUG_ON(ARM64_SME2 <= ARM64_SME); ++ ++ /* Allow use of ZT0 */ ++ write_sysreg_s(read_sysreg_s(SYS_SMCR_EL1) | SMCR_ELx_EZT0_MASK, ++ SYS_SMCR_EL1); ++ } ++ ++ void cpu_enable_fa64(const struct arm64_cpu_capabilities *__always_unused p) ++ { ++ /* This must be enabled after SME */ ++ BUILD_BUG_ON(ARM64_SME_FA64 <= ARM64_SME); ++ ++ /* Allow use of FA64 */ ++ write_sysreg_s(read_sysreg_s(SYS_SMCR_EL1) | SMCR_ELx_FA64_MASK, ++ SYS_SMCR_EL1); ++ } ++ ++ void __init sme_setup(void) ++ { ++ struct vl_info *info = &vl_info[ARM64_VEC_SME]; ++ int min_bit, max_bit; ++ ++ if (!system_supports_sme()) ++ return; ++ ++ /* ++ * SME doesn't require any particular vector length be ++ * supported but it does require at least one. We should have ++ * disabled the feature entirely while bringing up CPUs but ++ * let's double check here. The bitmap is SVE_VQ_MAP sized for ++ * sharing with SVE. ++ */ ++ WARN_ON(bitmap_empty(info->vq_map, SVE_VQ_MAX)); ++ ++ min_bit = find_last_bit(info->vq_map, SVE_VQ_MAX); ++ info->min_vl = sve_vl_from_vq(__bit_to_vq(min_bit)); ++ ++ max_bit = find_first_bit(info->vq_map, SVE_VQ_MAX); ++ info->max_vl = sve_vl_from_vq(__bit_to_vq(max_bit)); ++ ++ WARN_ON(info->min_vl > info->max_vl); ++ ++ /* ++ * For the default VL, pick the maximum supported value <= 32 ++ * (256 bits) if there is one since this is guaranteed not to ++ * grow the signal frame when in streaming mode, otherwise the ++ * minimum available VL will be used. ++ */ ++ set_sme_default_vl(find_supported_vector_length(ARM64_VEC_SME, 32)); ++ ++ pr_info("SME: minimum available vector length %u bytes per vector\n", ++ info->min_vl); ++ pr_info("SME: maximum available vector length %u bytes per vector\n", ++ info->max_vl); ++ pr_info("SME: default vector length %u bytes per vector\n", ++ get_sme_default_vl()); ++ } ++ ++ void sme_suspend_exit(void) ++ { ++ u64 smcr = 0; ++ ++ if (!system_supports_sme()) ++ return; ++ ++ if (system_supports_fa64()) ++ smcr |= SMCR_ELx_FA64; ++ if (system_supports_sme2()) ++ smcr |= SMCR_ELx_EZT0; ++ ++ write_sysreg_s(smcr, SYS_SMCR_EL1); ++ write_sysreg_s(0, SYS_SMPRI_EL1); ++ } ++ ++ #endif /* CONFIG_ARM64_SME */ ++ ++ static void sve_init_regs(void) ++ { ++ /* ++ * Convert the FPSIMD state to SVE, zeroing all the state that ++ * is not shared with FPSIMD. If (as is likely) the current ++ * state is live in the registers then do this there and ++ * update our metadata for the current task including ++ * disabling the trap, otherwise update our in-memory copy. ++ * We are guaranteed to not be in streaming mode, we can only ++ * take a SVE trap when not in streaming mode and we can't be ++ * in streaming mode when taking a SME trap. ++ */ ++ if (!test_thread_flag(TIF_FOREIGN_FPSTATE)) { ++ unsigned long vq_minus_one = ++ sve_vq_from_vl(task_get_sve_vl(current)) - 1; ++ sve_set_vq(vq_minus_one); ++ sve_flush_live(true, vq_minus_one); ++ fpsimd_bind_task_to_cpu(); ++ } else { ++ fpsimd_to_sve(current); ++ current->thread.fp_type = FP_STATE_SVE; ++ fpsimd_flush_task_state(current); ++ } ++ } ++ +++>>>>>>> 751ecf6afd65 (arm64/sve: Discard stale CPU state when handling SVE traps) + /* + * Trapped SVE access + * +* Unmerged path arch/arm64/kernel/fpsimd.c diff --git a/ciq/ciq_backports/kernel-4.18.0-553.37.1.el8_10/rebuild.details.txt b/ciq/ciq_backports/kernel-4.18.0-553.37.1.el8_10/rebuild.details.txt new file mode 100644 index 0000000000000..40de4bda1694c --- /dev/null +++ b/ciq/ciq_backports/kernel-4.18.0-553.37.1.el8_10/rebuild.details.txt @@ -0,0 +1,23 @@ +Rebuild_History BUILDABLE +Rebuilding Kernel from rpm changelog with Fuzz Limit: 87.50% +Number of commits in upstream range v4.18~1..master: 524209 +Number of commits in rpm: 11 +Number of commits matched with upstream: 5 (45.45%) +Number of commits in upstream but not in rpm: 524204 +Number of commits NOT found in upstream: 6 (54.55%) + +Rebuilding Kernel on Branch rocky8_10_rebuild_kernel-4.18.0-553.37.1.el8_10 for kernel-4.18.0-553.37.1.el8_10 +Clean Cherry Picks: 4 (80.00%) +Empty Cherry Picks: 1 (20.00%) +_______________________________ + +__EMPTY COMMITS__________________________ +751ecf6afd6568adc98f2a6052315552c0483d18 arm64/sve: Discard stale CPU state when handling SVE traps + +__CHANGES NOT IN UPSTREAM________________ +Adding prod certs and changed cert date to 20210620 +Adding Rocky secure boot certs +Fixing vmlinuz removal +Fixing UEFI CA path +Porting to 8.10, debranding and Rocky branding +Fixing pesign_key_name values diff --git a/ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/0467cdde.failed b/ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/0467cdde.failed new file mode 100644 index 0000000000000..87d91282c167a --- /dev/null +++ b/ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/0467cdde.failed @@ -0,0 +1,219 @@ +s390/pci: Sort PCI functions prior to creating virtual busses + +jira LE-2349 +Rebuild_History Non-Buildable kernel-4.18.0-553.40.1.el8_10 +commit-author Niklas Schnelle +commit 0467cdde8c4320bbfdb31a8cff1277b202f677fc +Empty-Commit: Cherry-Pick Conflicts during history rebuild. +Will be included in final tarball splat. Ref for failed cherry-pick at: +ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/0467cdde.failed + +Instead of relying on the observed but not architected firmware behavior +that PCI functions from the same card are listed in ascending RID order +in clp_list_pci() ensure this by sorting. To allow for sorting separate +the initial clp_list_pci() and creation of the virtual PCI busses. + +Note that fundamentally in our per-PCI function hotplug design non RID +order of discovery is still possible. For example when the two PFs of +a two port NIC are hotplugged after initial boot and in descending RID +order. In this case the virtual PCI bus would be created by the second +PF using that PF's UID as domain number instead of that of the first PF. +Thus the domain number would then change from the UID of the second PF +to that of the first PF on reboot but there is really nothing we can do +about that since changing domain numbers at runtime seems even worse. +This only impacts the domain number as the RIDs are consistent and thus +even with just the second PF visible it will show up in the correct +position on the virtual bus. + + Reviewed-by: Gerd Bayer + Signed-off-by: Niklas Schnelle + Signed-off-by: Heiko Carstens +(cherry picked from commit 0467cdde8c4320bbfdb31a8cff1277b202f677fc) + Signed-off-by: Jonathan Maple + +# Conflicts: +# arch/s390/pci/pci.c +diff --cc arch/s390/pci/pci.c +index 162ca752cec9,b7efa96776ea..000000000000 +--- a/arch/s390/pci/pci.c ++++ b/arch/s390/pci/pci.c +@@@ -27,6 -27,9 +27,12 @@@ + #include + #include + #include +++<<<<<<< HEAD +++======= ++ #include ++ #include ++ #include +++>>>>>>> 0467cdde8c43 (s390/pci: Sort PCI functions prior to creating virtual busses) + + #include + #include +@@@ -885,9 -801,23 +890,22 @@@ struct zpci_dev *zpci_create_device(u3 + zdev->state = state; + + kref_init(&zdev->kref); + - mutex_init(&zdev->state_lock); + - mutex_init(&zdev->fmb_lock); + + mutex_init(&zdev->lock); + mutex_init(&zdev->kzdev_lock); + ++ return zdev; ++ ++ error: ++ zpci_dbg(0, "crt fid:%x, rc:%d\n", fid, rc); ++ kfree(zdev); ++ return ERR_PTR(rc); ++ } ++ ++ int zpci_add_device(struct zpci_dev *zdev) ++ { ++ int rc; ++ ++ zpci_dbg(1, "add fid:%x, fh:%x, c:%d\n", zdev->fid, zdev->fh, zdev->state); + rc = zpci_init_iommu(zdev); + if (rc) + goto error; +@@@ -1197,14 -1165,9 +1256,17 @@@ static int __init pci_base_init(void + if (rc) + goto out_irq; + +++<<<<<<< HEAD + + rc = zpci_dma_init(); + + if (rc) + + goto out_dma; + + + + rc = clp_scan_pci_devices(); +++======= ++ rc = zpci_scan_devices(); +++>>>>>>> 0467cdde8c43 (s390/pci: Sort PCI functions prior to creating virtual busses) + if (rc) + goto out_find; +- zpci_bus_scan_busses(); + + s390_pci_initialized = 1; + return 0; +diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h +index 15948089980a..25dae71f4671 100644 +--- a/arch/s390/include/asm/pci.h ++++ b/arch/s390/include/asm/pci.h +@@ -129,6 +129,7 @@ struct zpci_dev { + u16 vfn; /* virtual function number */ + u16 pchid; /* physical channel ID */ + u16 maxstbl; /* Maximum store block size */ ++ u16 rid; /* RID as supplied by firmware */ + u8 pfgid; /* function group ID */ + u8 pft; /* pci function type */ + u8 port; +@@ -215,12 +216,14 @@ extern struct airq_iv *zpci_aif_sbv; + ----------------------------------------------------------------------------- */ + /* Base stuff */ + struct zpci_dev *zpci_create_device(u32 fid, u32 fh, enum zpci_state state); ++int zpci_add_device(struct zpci_dev *zdev); + int zpci_enable_device(struct zpci_dev *); + int zpci_disable_device(struct zpci_dev *); + int zpci_scan_configured_device(struct zpci_dev *zdev, u32 fh); + int zpci_deconfigure_device(struct zpci_dev *zdev); + void zpci_device_reserved(struct zpci_dev *zdev); + bool zpci_is_device_configured(struct zpci_dev *zdev); ++int zpci_scan_devices(void); + + int zpci_hot_reset_device(struct zpci_dev *zdev); + int zpci_register_ioat(struct zpci_dev *, u8, u64, u64, u64, u8 *); +@@ -231,7 +234,7 @@ void zpci_update_fh(struct zpci_dev *zdev, u32 fh); + /* CLP */ + int rhel8_clp_rescan_pci_devices_simple(void); + int clp_setup_writeback_mio(void); +-int clp_scan_pci_devices(void); ++int clp_scan_pci_devices(struct list_head *scan_list); + int clp_query_pci_fn(struct zpci_dev *zdev); + int clp_enable_fh(struct zpci_dev *zdev, u32 *fh, u8 nr_dma_as); + int clp_disable_fh(struct zpci_dev *zdev, u32 *fh); +* Unmerged path arch/s390/pci/pci.c +diff --git a/arch/s390/pci/pci_clp.c b/arch/s390/pci/pci_clp.c +index 34759316747b..0e3a6b839ce9 100644 +--- a/arch/s390/pci/pci_clp.c ++++ b/arch/s390/pci/pci_clp.c +@@ -163,8 +163,10 @@ static int clp_store_query_pci_fn(struct zpci_dev *zdev, + zdev->port = response->port; + zdev->uid = response->uid; + zdev->fmb_length = sizeof(u32) * response->fmb_len; +- zdev->rid_available = response->rid_avail; + zdev->is_physfn = response->is_physfn; ++ zdev->rid_available = response->rid_avail; ++ if (zdev->rid_available) ++ zdev->rid = response->rid; + if (!s390_pci_no_rid && zdev->rid_available) + zdev->devfn = response->rid & ZPCI_RID_MASK_DEVFN; + +@@ -406,6 +408,7 @@ static int clp_find_pci(struct clp_req_rsp_list_pci *rrb, u32 fid, + + static void __clp_add(struct clp_fh_list_entry *entry, void *data) + { ++ struct list_head *scan_list = data; + struct zpci_dev *zdev; + + if (!entry->vendor_id) +@@ -416,10 +419,11 @@ static void __clp_add(struct clp_fh_list_entry *entry, void *data) + zpci_zdev_put(zdev); + return; + } +- zpci_create_device(entry->fid, entry->fh, entry->config_state); ++ zdev = zpci_create_device(entry->fid, entry->fh, entry->config_state); ++ list_add_tail(&zdev->entry, scan_list); + } + +-int clp_scan_pci_devices(void) ++int clp_scan_pci_devices(struct list_head *scan_list) + { + struct clp_req_rsp_list_pci *rrb; + int rc; +@@ -428,7 +432,7 @@ int clp_scan_pci_devices(void) + if (!rrb) + return -ENOMEM; + +- rc = clp_list_pci(rrb, NULL, __clp_add); ++ rc = clp_list_pci(rrb, scan_list, __clp_add); + + clp_free_block(rrb); + return rc; +diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c +index b3961f1016ea..74edb6fb6582 100644 +--- a/arch/s390/pci/pci_event.c ++++ b/arch/s390/pci/pci_event.c +@@ -328,6 +328,7 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) + zdev = zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_CONFIGURED); + if (IS_ERR(zdev)) + break; ++ zpci_add_device(zdev); + } else { + /* the configuration request may be stale */ + if (zdev->state != ZPCI_FN_STATE_STANDBY) +@@ -337,10 +338,14 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) + zpci_scan_configured_device(zdev, ccdf->fh); + break; + case 0x0302: /* Reserved -> Standby */ +- if (!zdev) +- zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_STANDBY); +- else ++ if (!zdev) { ++ zdev = zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_STANDBY); ++ if (IS_ERR(zdev)) ++ break; ++ zpci_add_device(zdev); ++ } else { + zpci_update_fh(zdev, ccdf->fh); ++ } + break; + case 0x0303: /* Deconfiguration requested */ + if (zdev) { +@@ -369,7 +374,7 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) + break; + case 0x0306: /* 0x308 or 0x302 for multiple devices */ + zpci_remove_reserved_devices(); +- clp_scan_pci_devices(); ++ zpci_scan_devices(); + break; + case 0x0308: /* Standby -> Reserved */ + if (!zdev) diff --git a/ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/126034fa.failed b/ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/126034fa.failed new file mode 100644 index 0000000000000..705f5ce810716 --- /dev/null +++ b/ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/126034fa.failed @@ -0,0 +1,162 @@ +s390/pci: Use topology ID for multi-function devices + +jira LE-2349 +Rebuild_History Non-Buildable kernel-4.18.0-553.40.1.el8_10 +commit-author Niklas Schnelle +commit 126034faaac5f356822c4a9bebfa75664da11056 +Empty-Commit: Cherry-Pick Conflicts during history rebuild. +Will be included in final tarball splat. Ref for failed cherry-pick at: +ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/126034fa.failed + +The newly introduced topology ID (TID) field in the CLP Query PCI +Function explicitly identifies groups of PCI functions whose RIDs belong +to the same (sub-)topology. When available use the TID instead of the +PCHID to match zPCI busses/domains for multi-function devices. Note that +currently only a single PCI bus per TID is supported. This change is +required because in future machines the PCHID will not identify a PCI +card but a specific port in the case of some multi-port NICs while from +a PCI point of view the entire card is a subtopology. + + Reviewed-by: Gerd Bayer + Signed-off-by: Niklas Schnelle + Signed-off-by: Heiko Carstens +(cherry picked from commit 126034faaac5f356822c4a9bebfa75664da11056) + Signed-off-by: Jonathan Maple + +# Conflicts: +# arch/s390/include/asm/pci.h +diff --cc arch/s390/include/asm/pci.h +index 15948089980a,e107eda7af86..000000000000 +--- a/arch/s390/include/asm/pci.h ++++ b/arch/s390/include/asm/pci.h +@@@ -129,6 -131,8 +130,11 @@@ struct zpci_dev + u16 vfn; /* virtual function number */ + u16 pchid; /* physical channel ID */ + u16 maxstbl; /* Maximum store block size */ +++<<<<<<< HEAD +++======= ++ u16 rid; /* RID as supplied by firmware */ ++ u16 tid; /* Topology for which RID is valid */ +++>>>>>>> 126034faaac5 (s390/pci: Use topology ID for multi-function devices) + u8 pfgid; /* function group ID */ + u8 pft; /* pci function type */ + u8 port; +@@@ -139,10 -143,10 +145,11 @@@ + u8 is_physfn : 1; + u8 util_str_avail : 1; + u8 irqs_registered : 1; +- u8 reserved : 2; ++ u8 tid_avail : 1; ++ u8 reserved : 1; + unsigned int devfn; /* DEVFN part of the RID*/ + + + struct mutex lock; + u8 pfip[CLP_PFIP_NR_SEGMENTS]; /* pci function internal path */ + u32 uid; /* user defined id */ + u8 util_str[CLP_UTIL_STR_LEN]; /* utility string */ +* Unmerged path arch/s390/include/asm/pci.h +diff --git a/arch/s390/include/asm/pci_clp.h b/arch/s390/include/asm/pci_clp.h +index d6189ed14f84..883aba330fea 100644 +--- a/arch/s390/include/asm/pci_clp.h ++++ b/arch/s390/include/asm/pci_clp.h +@@ -107,7 +107,8 @@ struct clp_req_query_pci { + struct clp_rsp_query_pci { + struct clp_rsp_hdr hdr; + u16 vfn; /* virtual fn number */ +- u16 : 3; ++ u16 : 2; ++ u16 tid_avail : 1; + u16 rid_avail : 1; + u16 is_physfn : 1; + u16 reserved1 : 1; +@@ -127,8 +128,9 @@ struct clp_rsp_query_pci { + u64 edma; /* end dma as */ + #define ZPCI_RID_MASK_DEVFN 0x00ff + u16 rid; /* BUS/DEVFN PCI address */ +- u16 reserved0; +- u32 reserved[10]; ++ u32 reserved0; ++ u16 tid; ++ u32 reserved[9]; + u32 uid; /* user defined id */ + u8 util_str[CLP_UTIL_STR_LEN]; /* utility string */ + u32 reserved2[16]; +diff --git a/arch/s390/pci/pci_bus.c b/arch/s390/pci/pci_bus.c +index 32245b970a0c..0daefa365cf4 100644 +--- a/arch/s390/pci/pci_bus.c ++++ b/arch/s390/pci/pci_bus.c +@@ -237,13 +237,13 @@ static void zpci_bus_put(struct zpci_bus *zbus) + kref_put(&zbus->kref, zpci_bus_release); + } + +-static struct zpci_bus *zpci_bus_get(int pchid) ++static struct zpci_bus *zpci_bus_get(int topo, bool topo_is_tid) + { + struct zpci_bus *zbus; + + mutex_lock(&zbus_list_lock); + list_for_each_entry(zbus, &zbus_list, bus_next) { +- if (pchid == zbus->pchid) { ++ if (topo_is_tid == zbus->topo_is_tid && topo == zbus->topo) { + kref_get(&zbus->kref); + goto out_unlock; + } +@@ -254,7 +254,7 @@ static struct zpci_bus *zpci_bus_get(int pchid) + return zbus; + } + +-static struct zpci_bus *zpci_bus_alloc(int pchid) ++static struct zpci_bus *zpci_bus_alloc(int topo, bool topo_is_tid) + { + struct zpci_bus *zbus; + +@@ -262,7 +262,8 @@ static struct zpci_bus *zpci_bus_alloc(int pchid) + if (!zbus) + return NULL; + +- zbus->pchid = pchid; ++ zbus->topo = topo; ++ zbus->topo_is_tid = topo_is_tid; + INIT_LIST_HEAD(&zbus->bus_next); + mutex_lock(&zbus_list_lock); + list_add_tail(&zbus->bus_next, &zbus_list); +@@ -326,8 +327,9 @@ static int zpci_bus_add_device(struct zpci_bus *zbus, struct zpci_dev *zdev) + + int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops) + { ++ bool topo_is_tid = zdev->tid_avail; + struct zpci_bus *zbus = NULL; +- int rc = -EBADF; ++ int topo, rc = -EBADF; + + if (zpci_nb_devices == ZPCI_NR_DEVICES) { + pr_warn("Adding PCI function %08x failed because the configured limit of %d is reached\n", +@@ -338,11 +340,12 @@ int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops) + if (zdev->devfn >= ZPCI_FUNCTIONS_PER_BUS) + return -EINVAL; + ++ topo = topo_is_tid ? zdev->tid : zdev->pchid; + if (!s390_pci_no_rid && zdev->rid_available) +- zbus = zpci_bus_get(zdev->pchid); ++ zbus = zpci_bus_get(topo, topo_is_tid); + + if (!zbus) { +- zbus = zpci_bus_alloc(zdev->pchid); ++ zbus = zpci_bus_alloc(topo, topo_is_tid); + if (!zbus) + return -ENOMEM; + } +diff --git a/arch/s390/pci/pci_clp.c b/arch/s390/pci/pci_clp.c +index 34759316747b..384fdd16c2ea 100644 +--- a/arch/s390/pci/pci_clp.c ++++ b/arch/s390/pci/pci_clp.c +@@ -167,6 +167,9 @@ static int clp_store_query_pci_fn(struct zpci_dev *zdev, + zdev->is_physfn = response->is_physfn; + if (!s390_pci_no_rid && zdev->rid_available) + zdev->devfn = response->rid & ZPCI_RID_MASK_DEVFN; ++ zdev->tid_avail = response->tid_avail; ++ if (zdev->tid_avail) ++ zdev->tid = response->tid; + + memcpy(zdev->pfip, response->pfip, sizeof(zdev->pfip)); + if (response->util_str_avail) { diff --git a/ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/25f39d3d.failed b/ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/25f39d3d.failed new file mode 100644 index 0000000000000..193077f6c969c --- /dev/null +++ b/ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/25f39d3d.failed @@ -0,0 +1,107 @@ +s390/pci: Ignore RID for isolated VFs + +jira LE-2349 +Rebuild_History Non-Buildable kernel-4.18.0-553.40.1.el8_10 +commit-author Niklas Schnelle +commit 25f39d3dcb48bbc824a77d16b3d977f0f3713cfe +Empty-Commit: Cherry-Pick Conflicts during history rebuild. +Will be included in final tarball splat. Ref for failed cherry-pick at: +ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/25f39d3d.failed + +Ensure that VFs used in isolation, that is with their parent PF not +visible to the configuration but with their RID exposed, are treated +compatibly with existing isolated VF use cases without exposed RID +including RoCE Express VFs. This allows creating configurations where +one LPAR manages PFs while their child VFs are used by other LPARs. This +gives the LPAR managing the PFs a role analogous to that of the +hypervisor in a typical use case of passing child VFs to guests. + +Instead of creating a multifunction struct zpci_bus whenever a PCI +function with RID exposed is discovered only create such a bus for +configured physical functions and only consider multifunction busses +when searching for an existing bus. Additionally only set zdev->devfn to +the devfn part of the RID once the function is added to a multifunction +bus. + +This also fixes probing of more than 7 such isolated VFs from the same +physical bus. This is because common PCI code in pci_scan_slot() only +looks for more functions when pdev->multifunction is set which somewhat +counter intutively is not the case for VFs. + +Note that PFs are looked at before their child VFs is guaranteed because +we sort the zpci_list by RID ascending. + + Reviewed-by: Gerd Bayer + Signed-off-by: Niklas Schnelle + Signed-off-by: Heiko Carstens +(cherry picked from commit 25f39d3dcb48bbc824a77d16b3d977f0f3713cfe) + Signed-off-by: Jonathan Maple + +# Conflicts: +# arch/s390/pci/pci_bus.c +# arch/s390/pci/pci_clp.c +diff --cc arch/s390/pci/pci_bus.c +index 32245b970a0c,1b74a000ff64..000000000000 +--- a/arch/s390/pci/pci_bus.c ++++ b/arch/s390/pci/pci_bus.c +@@@ -243,7 -245,9 +250,13 @@@ static struct zpci_bus *zpci_bus_get(in + + mutex_lock(&zbus_list_lock); + list_for_each_entry(zbus, &zbus_list, bus_next) { +++<<<<<<< HEAD + + if (pchid == zbus->pchid) { +++======= ++ if (!zbus->multifunction) ++ continue; ++ if (topo_is_tid == zbus->topo_is_tid && topo == zbus->topo) { +++>>>>>>> 25f39d3dcb48 (s390/pci: Ignore RID for isolated VFs) + kref_get(&zbus->kref); + goto out_unlock; + } +@@@ -335,14 -344,10 +351,19 @@@ int zpci_bus_device_register(struct zpc + return -ENOSPC; + } + +++<<<<<<< HEAD + + if (zdev->devfn >= ZPCI_FUNCTIONS_PER_BUS) + + return -EINVAL; + + + + if (!s390_pci_no_rid && zdev->rid_available) + + zbus = zpci_bus_get(zdev->pchid); + + +++======= ++ topo = topo_is_tid ? zdev->tid : zdev->pchid; ++ zbus = zpci_bus_get(topo, topo_is_tid); +++>>>>>>> 25f39d3dcb48 (s390/pci: Ignore RID for isolated VFs) + if (!zbus) { + - zbus = zpci_bus_alloc(topo, topo_is_tid); + + zbus = zpci_bus_alloc(zdev->pchid); + if (!zbus) + return -ENOMEM; + } +diff --cc arch/s390/pci/pci_clp.c +index 34759316747b,74dac6da03d5..000000000000 +--- a/arch/s390/pci/pci_clp.c ++++ b/arch/s390/pci/pci_clp.c +@@@ -163,10 -164,13 +163,18 @@@ static int clp_store_query_pci_fn(struc + zdev->port = response->port; + zdev->uid = response->uid; + zdev->fmb_length = sizeof(u32) * response->fmb_len; + - zdev->is_physfn = response->is_physfn; + zdev->rid_available = response->rid_avail; +++<<<<<<< HEAD + + zdev->is_physfn = response->is_physfn; + + if (!s390_pci_no_rid && zdev->rid_available) + + zdev->devfn = response->rid & ZPCI_RID_MASK_DEVFN; +++======= ++ if (zdev->rid_available) ++ zdev->rid = response->rid; ++ zdev->tid_avail = response->tid_avail; ++ if (zdev->tid_avail) ++ zdev->tid = response->tid; +++>>>>>>> 25f39d3dcb48 (s390/pci: Ignore RID for isolated VFs) + + memcpy(zdev->pfip, response->pfip, sizeof(zdev->pfip)); + if (response->util_str_avail) { +* Unmerged path arch/s390/pci/pci_bus.c +* Unmerged path arch/s390/pci/pci_clp.c diff --git a/ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/48796104.failed b/ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/48796104.failed new file mode 100644 index 0000000000000..2a6590445f87d --- /dev/null +++ b/ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/48796104.failed @@ -0,0 +1,184 @@ +s390/pci: Fix leak of struct zpci_dev when zpci_add_device() fails + +jira LE-2349 +Rebuild_History Non-Buildable kernel-4.18.0-553.40.1.el8_10 +commit-author Niklas Schnelle +commit 48796104c864cf4dafa80bd8c2ce88f9c92a65ea +Empty-Commit: Cherry-Pick Conflicts during history rebuild. +Will be included in final tarball splat. Ref for failed cherry-pick at: +ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/48796104.failed + +Prior to commit 0467cdde8c43 ("s390/pci: Sort PCI functions prior to +creating virtual busses") the IOMMU was initialized and the device was +registered as part of zpci_create_device() with the struct zpci_dev +freed if either resulted in an error. With that commit this was moved +into a separate function called zpci_add_device(). + +While this new function logs when adding failed, it expects the caller +not to use and to free the struct zpci_dev on error. This difference +between it and zpci_create_device() was missed while changing the +callers and the incompletely initialized struct zpci_dev may get used in +zpci_scan_configured_device in the error path. This then leads to +a crash due to the device not being registered with the zbus. It was +also not freed in this case. Fix this by handling the error return of +zpci_add_device(). Since in this case the zdev was not added to the +zpci_list it can simply be discarded and freed. Also make this more +explicit by moving the kref_init() into zpci_add_device() and document +that zpci_zdev_get()/zpci_zdev_put() must be used after adding. + + Cc: stable@vger.kernel.org +Fixes: 0467cdde8c43 ("s390/pci: Sort PCI functions prior to creating virtual busses") + Reviewed-by: Gerd Bayer + Reviewed-by: Matthew Rosato + Signed-off-by: Niklas Schnelle + Signed-off-by: Heiko Carstens +(cherry picked from commit 48796104c864cf4dafa80bd8c2ce88f9c92a65ea) + Signed-off-by: Jonathan Maple + +# Conflicts: +# arch/s390/pci/pci.c +# arch/s390/pci/pci_event.c +diff --cc arch/s390/pci/pci.c +index 162ca752cec9,6a011d040dfe..000000000000 +--- a/arch/s390/pci/pci.c ++++ b/arch/s390/pci/pci.c +@@@ -884,10 -801,34 +885,41 @@@ struct zpci_dev *zpci_create_device(u3 + goto error; + zdev->state = state; + +++<<<<<<< HEAD + + kref_init(&zdev->kref); + + mutex_init(&zdev->lock); + + mutex_init(&zdev->kzdev_lock); + + +++======= ++ mutex_init(&zdev->state_lock); ++ mutex_init(&zdev->fmb_lock); ++ mutex_init(&zdev->kzdev_lock); ++ ++ return zdev; ++ ++ error: ++ zpci_dbg(0, "crt fid:%x, rc:%d\n", fid, rc); ++ kfree(zdev); ++ return ERR_PTR(rc); ++ } ++ ++ /** ++ * zpci_add_device() - Add a previously created zPCI device to the zPCI subsystem ++ * @zdev: The zPCI device to be added ++ * ++ * A struct zpci_dev is added to the zPCI subsystem and to a virtual PCI bus creating ++ * a new one as necessary. A hotplug slot is created and events start to be handled. ++ * If successful from this point on zpci_zdev_get() and zpci_zdev_put() must be used. ++ * If adding the struct zpci_dev fails the device was not added and should be freed. ++ * ++ * Return: 0 on success, or an error code otherwise ++ */ ++ int zpci_add_device(struct zpci_dev *zdev) ++ { ++ int rc; ++ ++ zpci_dbg(1, "add fid:%x, fh:%x, c:%d\n", zdev->fid, zdev->fh, zdev->state); +++>>>>>>> 48796104c864 (s390/pci: Fix leak of struct zpci_dev when zpci_add_device() fails) + rc = zpci_init_iommu(zdev); + if (rc) + goto error; +@@@ -1168,6 -1105,50 +1201,53 @@@ bool zpci_is_enabled(void + return s390_pci_initialized; + } + +++<<<<<<< HEAD +++======= ++ static int zpci_cmp_rid(void *priv, const struct list_head *a, ++ const struct list_head *b) ++ { ++ struct zpci_dev *za = container_of(a, struct zpci_dev, entry); ++ struct zpci_dev *zb = container_of(b, struct zpci_dev, entry); ++ ++ /* ++ * PCI functions without RID available maintain original order ++ * between themselves but sort before those with RID. ++ */ ++ if (za->rid == zb->rid) ++ return za->rid_available > zb->rid_available; ++ /* ++ * PCI functions with RID sort by RID ascending. ++ */ ++ return za->rid > zb->rid; ++ } ++ ++ static void zpci_add_devices(struct list_head *scan_list) ++ { ++ struct zpci_dev *zdev, *tmp; ++ ++ list_sort(NULL, scan_list, &zpci_cmp_rid); ++ list_for_each_entry_safe(zdev, tmp, scan_list, entry) { ++ list_del_init(&zdev->entry); ++ if (zpci_add_device(zdev)) ++ kfree(zdev); ++ } ++ } ++ ++ int zpci_scan_devices(void) ++ { ++ LIST_HEAD(scan_list); ++ int rc; ++ ++ rc = clp_scan_pci_devices(&scan_list); ++ if (rc) ++ return rc; ++ ++ zpci_add_devices(&scan_list); ++ zpci_bus_scan_busses(); ++ return 0; ++ } ++ +++>>>>>>> 48796104c864 (s390/pci: Fix leak of struct zpci_dev when zpci_add_device() fails) + static int __init pci_base_init(void) + { + int rc; +diff --cc arch/s390/pci/pci_event.c +index b3961f1016ea,7f7b732b3f3e..000000000000 +--- a/arch/s390/pci/pci_event.c ++++ b/arch/s390/pci/pci_event.c +@@@ -328,6 -340,10 +328,13 @@@ static void __zpci_event_availability(s + zdev = zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_CONFIGURED); + if (IS_ERR(zdev)) + break; +++<<<<<<< HEAD +++======= ++ if (zpci_add_device(zdev)) { ++ kfree(zdev); ++ break; ++ } +++>>>>>>> 48796104c864 (s390/pci: Fix leak of struct zpci_dev when zpci_add_device() fails) + } else { + /* the configuration request may be stale */ + if (zdev->state != ZPCI_FN_STATE_STANDBY) +@@@ -337,10 -353,17 +344,22 @@@ + zpci_scan_configured_device(zdev, ccdf->fh); + break; + case 0x0302: /* Reserved -> Standby */ +++<<<<<<< HEAD + + if (!zdev) + + zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_STANDBY); + + else +++======= ++ if (!zdev) { ++ zdev = zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_STANDBY); ++ if (IS_ERR(zdev)) ++ break; ++ if (zpci_add_device(zdev)) { ++ kfree(zdev); ++ break; ++ } ++ } else { +++>>>>>>> 48796104c864 (s390/pci: Fix leak of struct zpci_dev when zpci_add_device() fails) + zpci_update_fh(zdev, ccdf->fh); + - } + break; + case 0x0303: /* Deconfiguration requested */ + if (zdev) { +* Unmerged path arch/s390/pci/pci.c +* Unmerged path arch/s390/pci/pci_event.c diff --git a/ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/5fd11b96.failed b/ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/5fd11b96.failed new file mode 100644 index 0000000000000..b7f17d96ee3cf --- /dev/null +++ b/ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/5fd11b96.failed @@ -0,0 +1,60 @@ +s390/pci: Refactor arch_setup_msi_irqs() + +jira LE-2349 +Rebuild_History Non-Buildable kernel-4.18.0-553.40.1.el8_10 +commit-author Gerd Bayer +commit 5fd11b96b43708f2f6e3964412c301c1bd20ec0f +Empty-Commit: Cherry-Pick Conflicts during history rebuild. +Will be included in final tarball splat. Ref for failed cherry-pick at: +ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/5fd11b96.failed + +Factor out adapter interrupt allocation from arch_setup_msi_irqs() in +preparation for enabling registration of multiple MSIs. Code movement +only, no change of functionality intended. + + Signed-off-by: Gerd Bayer + Reviewed-by: Niklas Schnelle + Signed-off-by: Vasily Gorbik +(cherry picked from commit 5fd11b96b43708f2f6e3964412c301c1bd20ec0f) + Signed-off-by: Jonathan Maple + +# Conflicts: +# arch/s390/pci/pci_irq.c +diff --cc arch/s390/pci/pci_irq.c +index 192f3b104ae4,979f776b09b8..000000000000 +--- a/arch/s390/pci/pci_irq.c ++++ b/arch/s390/pci/pci_irq.c +@@@ -269,25 -268,13 +269,29 @@@ static void zpci_floating_irq_handler(s + } + } + +- int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) ++ static int __alloc_airq(struct zpci_dev *zdev, int msi_vecs, ++ unsigned long *bit) + { +++<<<<<<< HEAD + + struct zpci_dev *zdev = to_zpci(pdev); + + unsigned int hwirq, msi_vecs, cpu; + + unsigned long bit; + + struct msi_desc *msi; + + struct msi_msg msg; + + int rc, irq; + + + + zdev->aisb = -1UL; + + zdev->msi_first_bit = -1U; + + if (type == PCI_CAP_ID_MSI && nvec > 1) + + return 1; + + msi_vecs = min_t(unsigned int, nvec, zdev->max_msi); + + +++======= +++>>>>>>> 5fd11b96b437 (s390/pci: Refactor arch_setup_msi_irqs()) + if (irq_delivery == DIRECTED) { + /* Allocate cpu vector bits */ +- bit = airq_iv_alloc(zpci_ibv[0], msi_vecs); +- if (bit == -1UL) ++ *bit = airq_iv_alloc(zpci_ibv[0], msi_vecs); ++ if (*bit == -1UL) + return -EIO; + } else { + /* Allocate adapter summary indicator bit */ +* Unmerged path arch/s390/pci/pci_irq.c diff --git a/ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/ab42fcb5.failed b/ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/ab42fcb5.failed new file mode 100644 index 0000000000000..8702acf312720 --- /dev/null +++ b/ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/ab42fcb5.failed @@ -0,0 +1,172 @@ +s390/pci: Allow allocation of more than 1 MSI interrupt + +jira LE-2349 +Rebuild_History Non-Buildable kernel-4.18.0-553.40.1.el8_10 +commit-author Gerd Bayer +commit ab42fcb511fd9d241bbab7cc3ca04e34e9fc0666 +Empty-Commit: Cherry-Pick Conflicts during history rebuild. +Will be included in final tarball splat. Ref for failed cherry-pick at: +ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/ab42fcb5.failed + +On a PCI adapter that provides up to 8 MSI interrupt sources the s390 +implementation of PCI interrupts rejected to accommodate them, although +the underlying hardware is able to support that. + +For MSI-X it is sufficient to allocate a single irq_desc per msi_desc, +but for MSI multiple irq descriptors are attached to and controlled by +a single msi descriptor. Add the appropriate loops to maintain multiple +irq descriptors and tie/untie them to/from the appropriate AIBV bit, if +a device driver allocates more than 1 MSI interrupt. + +Common PCI code passes on requests to allocate a number of interrupt +vectors based on the device drivers' demand and the PCI functions' +capabilities. However, the root-complex of s390 systems support just a +limited number of interrupt vectors per PCI function. +Produce a kernel log message to inform about any architecture-specific +capping that might be done. + +With this change, we had a PCI adapter successfully raising +interrupts to its device driver via all 8 sources. + +Fixes: a384c8924a8b ("s390/PCI: Fix single MSI only check") + Signed-off-by: Gerd Bayer + Reviewed-by: Niklas Schnelle + Signed-off-by: Vasily Gorbik +(cherry picked from commit ab42fcb511fd9d241bbab7cc3ca04e34e9fc0666) + Signed-off-by: Jonathan Maple + +# Conflicts: +# arch/s390/pci/pci_irq.c +diff --cc arch/s390/pci/pci_irq.c +index 192f3b104ae4,84482a921332..000000000000 +--- a/arch/s390/pci/pci_irq.c ++++ b/arch/s390/pci/pci_irq.c +@@@ -302,34 -289,81 +302,83 @@@ int arch_setup_msi_irqs(struct pci_dev + return -ENOMEM; + + /* Wire up shortcut pointer */ + - zpci_ibv[*bit] = zdev->aibv; + + zpci_ibv[bit] = zdev->aibv; + /* Each function has its own interrupt vector */ + - *bit = 0; + + bit = 0; + } +++<<<<<<< HEAD +++======= ++ return 0; ++ } ++ ++ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) ++ { ++ unsigned int hwirq, msi_vecs, irqs_per_msi, i, cpu; ++ struct zpci_dev *zdev = to_zpci(pdev); ++ struct msi_desc *msi; ++ struct msi_msg msg; ++ unsigned long bit; ++ int cpu_addr; ++ int rc, irq; ++ ++ zdev->aisb = -1UL; ++ zdev->msi_first_bit = -1U; ++ ++ msi_vecs = min_t(unsigned int, nvec, zdev->max_msi); ++ if (msi_vecs < nvec) { ++ pr_info("%s requested %d irqs, allocate system limit of %d", ++ pci_name(pdev), nvec, zdev->max_msi); ++ } + +- /* Request MSI interrupts */ ++ rc = __alloc_airq(zdev, msi_vecs, &bit); ++ if (rc < 0) ++ return rc; +++>>>>>>> ab42fcb511fd (s390/pci: Allow allocation of more than 1 MSI interrupt) ++ ++ /* ++ * Request MSI interrupts: ++ * When using MSI, nvec_used interrupt sources and their irq ++ * descriptors are controlled through one msi descriptor. ++ * Thus the outer loop over msi descriptors shall run only once, ++ * while two inner loops iterate over the interrupt vectors. ++ * When using MSI-X, each interrupt vector/irq descriptor ++ * is bound to exactly one msi descriptor (nvec_used is one). ++ * So the inner loops are executed once, while the outer iterates ++ * over the MSI-X descriptors. ++ */ + hwirq = bit; +++<<<<<<< HEAD + + for_each_pci_msi_entry(msi, pdev) { + + rc = -EIO; +++======= ++ msi_for_each_desc(msi, &pdev->dev, MSI_DESC_NOTASSOCIATED) { +++>>>>>>> ab42fcb511fd (s390/pci: Allow allocation of more than 1 MSI interrupt) + if (hwirq - bit >= msi_vecs) + break; +- irq = __irq_alloc_descs(-1, 0, 1, 0, THIS_MODULE, +- (irq_delivery == DIRECTED) ? +- msi->affinity : NULL); ++ irqs_per_msi = min_t(unsigned int, msi_vecs, msi->nvec_used); ++ irq = __irq_alloc_descs(-1, 0, irqs_per_msi, 0, THIS_MODULE, ++ (irq_delivery == DIRECTED) ? ++ msi->affinity : NULL); + if (irq < 0) + return -ENOMEM; +- rc = irq_set_msi_desc(irq, msi); +- if (rc) +- return rc; +- irq_set_chip_and_handler(irq, &zpci_irq_chip, +- handle_percpu_irq); ++ ++ for (i = 0; i < irqs_per_msi; i++) { ++ rc = irq_set_msi_desc_off(irq, i, msi); ++ if (rc) ++ return rc; ++ irq_set_chip_and_handler(irq + i, &zpci_irq_chip, ++ handle_percpu_irq); ++ } ++ + msg.data = hwirq - bit; + if (irq_delivery == DIRECTED) { + - if (msi->affinity) + - cpu = cpumask_first(&msi->affinity->mask); + - else + - cpu = 0; + - cpu_addr = smp_cpu_get_cpu_address(cpu); + - + msg.address_lo = zdev->msi_addr & 0xff0000ff; + - msg.address_lo |= (cpu_addr << 8); + - + + msg.address_lo |= msi->affinity ? + + (cpumask_first(&msi->affinity->mask) << 8) : 0; + for_each_possible_cpu(cpu) { +- airq_iv_set_data(zpci_ibv[cpu], hwirq, irq); ++ for (i = 0; i < irqs_per_msi; i++) ++ airq_iv_set_data(zpci_ibv[cpu], ++ hwirq + i, irq + i); + } + } else { + msg.address_lo = zdev->msi_addr & 0xffffffff; +@@@ -362,15 -398,11 +413,23 @@@ void arch_teardown_msi_irqs(struct pci_ + return; + + /* Release MSI interrupts */ +++<<<<<<< HEAD + + for_each_pci_msi_entry(msi, pdev) { + + if (!msi->irq) + + continue; + + if (msi->msi_attrib.is_msix) + + __pci_msix_desc_mask_irq(msi, 1); + + else + + __pci_msi_desc_mask_irq(msi, 1, 1); + + irq_set_msi_desc(msi->irq, NULL); + + irq_free_desc(msi->irq); +++======= ++ msi_for_each_desc(msi, &pdev->dev, MSI_DESC_ASSOCIATED) { ++ for (i = 0; i < msi->nvec_used; i++) { ++ irq_set_msi_desc(msi->irq + i, NULL); ++ irq_free_desc(msi->irq + i); ++ } +++>>>>>>> ab42fcb511fd (s390/pci: Allow allocation of more than 1 MSI interrupt) + msi->msg.address_lo = 0; + msi->msg.address_hi = 0; + msi->msg.data = 0; +* Unmerged path arch/s390/pci/pci_irq.c diff --git a/ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/rebuild.details.txt b/ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/rebuild.details.txt new file mode 100644 index 0000000000000..af45eb90e83e6 --- /dev/null +++ b/ciq/ciq_backports/kernel-4.18.0-553.40.1.el8_10/rebuild.details.txt @@ -0,0 +1,28 @@ +Rebuild_History BUILDABLE +Rebuilding Kernel from rpm changelog with Fuzz Limit: 87.50% +Number of commits in upstream range v4.18~1..master: 524209 +Number of commits in rpm: 17 +Number of commits matched with upstream: 11 (64.71%) +Number of commits in upstream but not in rpm: 524198 +Number of commits NOT found in upstream: 6 (35.29%) + +Rebuilding Kernel on Branch rocky8_10_rebuild_kernel-4.18.0-553.40.1.el8_10 for kernel-4.18.0-553.40.1.el8_10 +Clean Cherry Picks: 5 (45.45%) +Empty Cherry Picks: 6 (54.55%) +_______________________________ + +__EMPTY COMMITS__________________________ +0467cdde8c4320bbfdb31a8cff1277b202f677fc s390/pci: Sort PCI functions prior to creating virtual busses +126034faaac5f356822c4a9bebfa75664da11056 s390/pci: Use topology ID for multi-function devices +25f39d3dcb48bbc824a77d16b3d977f0f3713cfe s390/pci: Ignore RID for isolated VFs +48796104c864cf4dafa80bd8c2ce88f9c92a65ea s390/pci: Fix leak of struct zpci_dev when zpci_add_device() fails +5fd11b96b43708f2f6e3964412c301c1bd20ec0f s390/pci: Refactor arch_setup_msi_irqs() +ab42fcb511fd9d241bbab7cc3ca04e34e9fc0666 s390/pci: Allow allocation of more than 1 MSI interrupt + +__CHANGES NOT IN UPSTREAM________________ +Adding prod certs and changed cert date to 20210620 +Adding Rocky secure boot certs +Fixing vmlinuz removal +Fixing UEFI CA path +Porting to 8.10, debranding and Rocky branding +Fixing pesign_key_name values diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 9b50e5a0975da..1807b332ba87a 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -368,7 +368,7 @@ static int uvc_parse_format(struct uvc_device *dev, * Parse the frame descriptors. Only uncompressed, MJPEG and frame * based formats have frame descriptors. */ - while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && + while (ftype && buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && buffer[2] == ftype) { frame = &format->frame[format->nframes]; if (ftype != UVC_VS_FRAME_FRAME_BASED) diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 105369cfb87f1..3c03c15b6e0e0 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -64,6 +64,8 @@ #define LAN7801_USB_PRODUCT_ID (0x7801) #define LAN78XX_EEPROM_MAGIC (0x78A5) #define LAN78XX_OTP_MAGIC (0x78F3) +#define AT29M2AF_USB_VENDOR_ID (0x07C9) +#define AT29M2AF_USB_PRODUCT_ID (0x0012) #define MII_READ 1 #define MII_WRITE 0 @@ -4174,6 +4176,10 @@ static const struct usb_device_id products[] = { /* LAN7801 USB Gigabit Ethernet Device */ USB_DEVICE(LAN78XX_USB_VENDOR_ID, LAN7801_USB_PRODUCT_ID), }, + { + /* ATM2-AF USB Gigabit Ethernet Device */ + USB_DEVICE(AT29M2AF_USB_VENDOR_ID, AT29M2AF_USB_PRODUCT_ID), + }, {}, }; MODULE_DEVICE_TABLE(usb, products); diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index ad0c118258ae3..f5ceae755ffb6 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -347,12 +347,13 @@ static void scsi_host_dev_release(struct device *dev) if (shost->shost_state == SHOST_CREATED) { /* - * Free the shost_dev device name here if scsi_host_alloc() - * and scsi_host_put() have been called but neither + * Free the shost_dev device name and remove the proc host dir + * here if scsi_host_{alloc,put}() have been called but neither * scsi_host_add() nor scsi_remove_host() has been called. * This avoids that the memory allocated for the shost_dev - * name is leaked. + * name as well as the proc dir structure are leaked. */ + scsi_proc_hostdir_rm(shost->hostt); kfree(dev_name(&shost->shost_dev)); } diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index df4b83b99698c..847517a4a97d0 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -379,21 +379,46 @@ static int scsi_vpd_inquiry(struct scsi_device *sdev, unsigned char *buffer, return result + 4; } +enum scsi_vpd_parameters { + SCSI_VPD_HEADER_SIZE = 4, + SCSI_VPD_LIST_SIZE = 36, +}; + static int scsi_get_vpd_size(struct scsi_device *sdev, u8 page) { - unsigned char vpd_header[SCSI_VPD_HEADER_SIZE] __aligned(4); + unsigned char vpd[SCSI_VPD_LIST_SIZE] __aligned(4); int result; if (sdev->no_vpd_size) return SCSI_DEFAULT_VPD_LEN; + /* + * Fetch the supported pages VPD and validate that the requested page + * number is present. + */ + if (page != 0) { + result = scsi_vpd_inquiry(sdev, vpd, 0, sizeof(vpd)); + if (result < SCSI_VPD_HEADER_SIZE) + return 0; + + if (result > sizeof(vpd)) { + dev_warn_once(&sdev->sdev_gendev, + "%s: long VPD page 0 length: %d bytes\n", + __func__, result); + result = sizeof(vpd); + } + + result -= SCSI_VPD_HEADER_SIZE; + if (!memchr(&vpd[SCSI_VPD_HEADER_SIZE], page, result)) + return 0; + } /* * Fetch the VPD page header to find out how big the page * is. This is done to prevent problems on legacy devices * which can not handle allocation lengths as large as * potentially requested by the caller. */ - result = scsi_vpd_inquiry(sdev, vpd_header, page, sizeof(vpd_header)); + result = scsi_vpd_inquiry(sdev, vpd, page, SCSI_VPD_HEADER_SIZE); if (result < 0) return 0; diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 3e0f7b7903ed1..dd07e0f60888a 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -273,6 +273,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask, error = filemap_fdatawait(inode->i_mapping); if (error) goto out; + truncate_inode_pages(inode->i_mapping, 0); if (new_flags & GFS2_DIF_JDATA) gfs2_ordered_del_inode(ip); } diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index bb693ae81f39d..cc6ee23dcbbae 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -7121,8 +7121,15 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata) } else if (!nfs4_update_lock_stateid(lsp, &data->res.stateid)) goto out_restart; break; - case -NFS4ERR_BAD_STATEID: case -NFS4ERR_OLD_STATEID: + if (data->arg.new_lock_owner != 0 && + nfs4_refresh_open_old_stateid(&data->arg.open_stateid, + lsp->ls_state)) + goto out_restart; + if (nfs4_refresh_lock_old_stateid(&data->arg.lock_stateid, lsp)) + goto out_restart; + fallthrough; + case -NFS4ERR_BAD_STATEID: case -NFS4ERR_STALE_STATEID: case -NFS4ERR_EXPIRED: if (data->arg.new_lock_owner != 0) { diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index eea2257fed10e..74245b8a5190a 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -101,10 +101,6 @@ struct scsi_vpd { unsigned char data[]; }; -enum scsi_vpd_parameters { - SCSI_VPD_HEADER_SIZE = 4, -}; - struct scsi_device { struct Scsi_Host *host; struct request_queue *request_queue; diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 4a4fb4b951eae..9f360a1bd5870 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -1392,7 +1392,9 @@ static int iucv_sock_recvmsg(struct socket *sock, struct msghdr *msg, return -EOPNOTSUPP; /* receive/dequeue next skb: - * the function understands MSG_PEEK and, thus, does not dequeue skb */ + * the function understands MSG_PEEK and, thus, does not dequeue skb + * only refcount is increased. + */ skb = skb_recv_datagram(sk, flags, &err); if (!skb) { if (sk->sk_shutdown & RCV_SHUTDOWN) @@ -1408,9 +1410,8 @@ static int iucv_sock_recvmsg(struct socket *sock, struct msghdr *msg, cskb = skb; if (skb_copy_datagram_msg(cskb, offset, msg, copied)) { - if (!(flags & MSG_PEEK)) - skb_queue_head(&sk->sk_receive_queue, skb); - return -EFAULT; + err = -EFAULT; + goto err_out; } /* SOCK_SEQPACKET: set MSG_TRUNC if recv buf size is too small */ @@ -1427,11 +1428,8 @@ static int iucv_sock_recvmsg(struct socket *sock, struct msghdr *msg, err = put_cmsg(msg, SOL_IUCV, SCM_IUCV_TRGCLS, sizeof(IUCV_SKB_CB(skb)->class), (void *)&IUCV_SKB_CB(skb)->class); - if (err) { - if (!(flags & MSG_PEEK)) - skb_queue_head(&sk->sk_receive_queue, skb); - return err; - } + if (err) + goto err_out; /* Mark read part of skb as used */ if (!(flags & MSG_PEEK)) { @@ -1487,8 +1485,18 @@ static int iucv_sock_recvmsg(struct socket *sock, struct msghdr *msg, /* SOCK_SEQPACKET: return real length if MSG_TRUNC is set */ if (sk->sk_type == SOCK_SEQPACKET && (flags & MSG_TRUNC)) copied = rlen; + if (flags & MSG_PEEK) + skb_unref(skb); return copied; + +err_out: + if (!(flags & MSG_PEEK)) + skb_queue_head(&sk->sk_receive_queue, skb); + else + skb_unref(skb); + + return err; } static inline __poll_t iucv_accept_poll(struct sock *parent)