diff options
Diffstat (limited to 'drivers/misc')
35 files changed, 871 insertions, 342 deletions
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index b0b766416306..d84819dc2468 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -60,6 +60,7 @@ lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o lkdtm-$(CONFIG_LKDTM) += lkdtm_bugs.o lkdtm-$(CONFIG_LKDTM) += lkdtm_heap.o lkdtm-$(CONFIG_LKDTM) += lkdtm_perms.o +lkdtm-$(CONFIG_LKDTM) += lkdtm_refcount.o lkdtm-$(CONFIG_LKDTM) += lkdtm_rodata_objcopy.o lkdtm-$(CONFIG_LKDTM) += lkdtm_usercopy.o diff --git a/drivers/misc/apds9802als.c b/drivers/misc/apds9802als.c index c6cc3dc8ae1f..d8ac036f01ab 100644 --- a/drivers/misc/apds9802als.c +++ b/drivers/misc/apds9802als.c @@ -197,7 +197,7 @@ static struct attribute *mid_att_als[] = { NULL }; -static struct attribute_group m_als_gr = { +static const struct attribute_group m_als_gr = { .name = "apds9802als", .attrs = mid_att_als }; @@ -298,7 +298,7 @@ static UNIVERSAL_DEV_PM_OPS(apds9802als_pm_ops, apds9802als_suspend, #define APDS9802ALS_PM_OPS NULL #endif /* CONFIG_PM */ -static struct i2c_device_id apds9802als_id[] = { +static const struct i2c_device_id apds9802als_id[] = { { DRIVER_NAME, 0 }, { } }; diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c index 84e5b949399e..c9f07032c2fc 100644 --- a/drivers/misc/apds990x.c +++ b/drivers/misc/apds990x.c @@ -1051,7 +1051,7 @@ static struct attribute *sysfs_attrs_ctrl[] = { NULL }; -static struct attribute_group apds990x_attribute_group[] = { +static const struct attribute_group apds990x_attribute_group[] = { {.attrs = sysfs_attrs_ctrl }, }; diff --git a/drivers/misc/aspeed-lpc-snoop.c b/drivers/misc/aspeed-lpc-snoop.c index 593905565b74..cb78c98bc78d 100644 --- a/drivers/misc/aspeed-lpc-snoop.c +++ b/drivers/misc/aspeed-lpc-snoop.c @@ -20,6 +20,7 @@ #include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/regmap.h> @@ -51,6 +52,13 @@ #define HICRB_ENSNP0D BIT(14) #define HICRB_ENSNP1D BIT(15) +struct aspeed_lpc_snoop_model_data { + /* The ast2400 has bits 14 and 15 as reserved, whereas the ast2500 + * can use them. + */ + unsigned int has_hicrb_ensnp; +}; + struct aspeed_lpc_snoop { struct regmap *regmap; int irq; @@ -123,10 +131,13 @@ static int aspeed_lpc_snoop_config_irq(struct aspeed_lpc_snoop *lpc_snoop, } static int aspeed_lpc_enable_snoop(struct aspeed_lpc_snoop *lpc_snoop, - int channel, u16 lpc_port) + struct device *dev, + int channel, u16 lpc_port) { int rc = 0; u32 hicr5_en, snpwadr_mask, snpwadr_shift, hicrb_en; + const struct aspeed_lpc_snoop_model_data *model_data = + of_device_get_match_data(dev); /* Create FIFO datastructure */ rc = kfifo_alloc(&lpc_snoop->snoop_fifo[channel], @@ -155,7 +166,9 @@ static int aspeed_lpc_enable_snoop(struct aspeed_lpc_snoop *lpc_snoop, regmap_update_bits(lpc_snoop->regmap, HICR5, hicr5_en, hicr5_en); regmap_update_bits(lpc_snoop->regmap, SNPWADR, snpwadr_mask, lpc_port << snpwadr_shift); - regmap_update_bits(lpc_snoop->regmap, HICRB, hicrb_en, hicrb_en); + if (model_data->has_hicrb_ensnp) + regmap_update_bits(lpc_snoop->regmap, HICRB, + hicrb_en, hicrb_en); return rc; } @@ -213,14 +226,14 @@ static int aspeed_lpc_snoop_probe(struct platform_device *pdev) if (rc) return rc; - rc = aspeed_lpc_enable_snoop(lpc_snoop, 0, port); + rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 0, port); if (rc) return rc; /* Configuration of 2nd snoop channel port is optional */ if (of_property_read_u32_index(dev->of_node, "snoop-ports", 1, &port) == 0) { - rc = aspeed_lpc_enable_snoop(lpc_snoop, 1, port); + rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 1, port); if (rc) aspeed_lpc_disable_snoop(lpc_snoop, 0); } @@ -239,8 +252,19 @@ static int aspeed_lpc_snoop_remove(struct platform_device *pdev) return 0; } +static const struct aspeed_lpc_snoop_model_data ast2400_model_data = { + .has_hicrb_ensnp = 0, +}; + +static const struct aspeed_lpc_snoop_model_data ast2500_model_data = { + .has_hicrb_ensnp = 1, +}; + static const struct of_device_id aspeed_lpc_snoop_match[] = { - { .compatible = "aspeed,ast2500-lpc-snoop" }, + { .compatible = "aspeed,ast2400-lpc-snoop", + .data = &ast2400_model_data }, + { .compatible = "aspeed,ast2500-lpc-snoop", + .data = &ast2500_model_data }, { }, }; diff --git a/drivers/misc/bh1770glc.c b/drivers/misc/bh1770glc.c index 38fcfe219d1c..9c62bf064f77 100644 --- a/drivers/misc/bh1770glc.c +++ b/drivers/misc/bh1770glc.c @@ -1175,7 +1175,7 @@ static struct attribute *sysfs_attrs[] = { NULL }; -static struct attribute_group bh1770_attribute_group = { +static const struct attribute_group bh1770_attribute_group = { .attrs = sysfs_attrs }; diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c index 1a138c83f877..a0c44d16bf30 100644 --- a/drivers/misc/cxl/api.c +++ b/drivers/misc/cxl/api.c @@ -336,6 +336,10 @@ int cxl_start_context(struct cxl_context *ctx, u64 wed, mmput(ctx->mm); } + /* + * Increment driver use count. Enables global TLBIs for hash + * and callbacks to handle the segment table + */ cxl_ctx_get(); if ((rc = cxl_ops->attach_process(ctx, kernel, wed, 0))) { diff --git a/drivers/misc/cxl/fault.c b/drivers/misc/cxl/fault.c index 6eed7d03e2b5..f17f72ea0545 100644 --- a/drivers/misc/cxl/fault.c +++ b/drivers/misc/cxl/fault.c @@ -138,6 +138,22 @@ int cxl_handle_mm_fault(struct mm_struct *mm, u64 dsisr, u64 dar) int result; unsigned long access, flags, inv_flags = 0; + /* + * Add the fault handling cpu to task mm cpumask so that we + * can do a safe lockless page table walk when inserting the + * hash page table entry. This function get called with a + * valid mm for user space addresses. Hence using the if (mm) + * check is sufficient here. + */ + if (mm && !cpumask_test_cpu(smp_processor_id(), mm_cpumask(mm))) { + cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm)); + /* + * We need to make sure we walk the table only after + * we update the cpumask. The other side of the barrier + * is explained in serialize_against_pte_lookup() + */ + smp_mb(); + } if ((result = copro_handle_mm_fault(mm, dar, dsisr, &flt))) { pr_devel("copro_handle_mm_fault failed: %#x\n", result); return result; diff --git a/drivers/misc/cxl/file.c b/drivers/misc/cxl/file.c index 0761271d68c5..4bfad9f6dc9f 100644 --- a/drivers/misc/cxl/file.c +++ b/drivers/misc/cxl/file.c @@ -95,7 +95,6 @@ static int __afu_open(struct inode *inode, struct file *file, bool master) pr_devel("afu_open pe: %i\n", ctx->pe); file->private_data = ctx; - cxl_ctx_get(); /* indicate success */ rc = 0; @@ -225,6 +224,12 @@ static long afu_ioctl_start_work(struct cxl_context *ctx, if (ctx->mm) mmput(ctx->mm); + /* + * Increment driver use count. Enables global TLBIs for hash + * and callbacks to handle the segment table + */ + cxl_ctx_get(); + trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr); if ((rc = cxl_ops->attach_process(ctx, false, work.work_element_descriptor, @@ -233,6 +238,7 @@ static long afu_ioctl_start_work(struct cxl_context *ctx, cxl_adapter_context_put(ctx->afu->adapter); put_pid(ctx->pid); ctx->pid = NULL; + cxl_ctx_put(); cxl_context_mm_count_put(ctx); goto out; } diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index d18b3d9292fd..3ba04f371380 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c @@ -1279,7 +1279,7 @@ ssize_t cxl_pci_afu_read_err_buffer(struct cxl_afu *afu, char *buf, } /* use bounce buffer for copy */ - tbuf = (void *)__get_free_page(GFP_TEMPORARY); + tbuf = (void *)__get_free_page(GFP_KERNEL); if (!tbuf) return -ENOMEM; diff --git a/drivers/misc/ds1682.c b/drivers/misc/ds1682.c index 28bb495f0cf1..7231260ac287 100644 --- a/drivers/misc/ds1682.c +++ b/drivers/misc/ds1682.c @@ -173,7 +173,7 @@ static ssize_t ds1682_eeprom_write(struct file *filp, struct kobject *kobj, return count; } -static struct bin_attribute ds1682_eeprom_attr = { +static const struct bin_attribute ds1682_eeprom_attr = { .attr = { .name = "eeprom", .mode = S_IRUGO | S_IWUSR, diff --git a/drivers/misc/eeprom/eeprom.c b/drivers/misc/eeprom/eeprom.c index 2fad790db3bf..60e3d91b5e03 100644 --- a/drivers/misc/eeprom/eeprom.c +++ b/drivers/misc/eeprom/eeprom.c @@ -114,7 +114,7 @@ static ssize_t eeprom_read(struct file *filp, struct kobject *kobj, return count; } -static struct bin_attribute eeprom_attr = { +static const struct bin_attribute eeprom_attr = { .attr = { .name = "eeprom", .mode = S_IRUGO, diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c index 94cc035aa841..38766968bfa2 100644 --- a/drivers/misc/eeprom/eeprom_93xx46.c +++ b/drivers/misc/eeprom/eeprom_93xx46.c @@ -377,8 +377,6 @@ static int eeprom_93xx46_probe_dt(struct spi_device *spi) struct device_node *np = spi->dev.of_node; struct eeprom_93xx46_platform_data *pd; u32 tmp; - int gpio; - enum of_gpio_flags of_flags; int ret; pd = devm_kzalloc(&spi->dev, sizeof(*pd), GFP_KERNEL); @@ -403,22 +401,14 @@ static int eeprom_93xx46_probe_dt(struct spi_device *spi) if (of_property_read_bool(np, "read-only")) pd->flags |= EE_READONLY; - gpio = of_get_named_gpio_flags(np, "select-gpios", 0, &of_flags); - if (gpio_is_valid(gpio)) { - unsigned long flags = - of_flags == OF_GPIO_ACTIVE_LOW ? GPIOF_ACTIVE_LOW : 0; + pd->select = devm_gpiod_get_optional(&spi->dev, "select", + GPIOD_OUT_LOW); + if (IS_ERR(pd->select)) + return PTR_ERR(pd->select); - ret = devm_gpio_request_one(&spi->dev, gpio, flags, - "eeprom_93xx46_select"); - if (ret) - return ret; - - pd->select = gpio_to_desc(gpio); - pd->prepare = select_assert; - pd->finish = select_deassert; - - gpiod_direction_output(pd->select, 0); - } + pd->prepare = select_assert; + pd->finish = select_deassert; + gpiod_direction_output(pd->select, 0); if (of_id->data) { const struct eeprom_93xx46_devtype_data *data = of_id->data; diff --git a/drivers/misc/eeprom/idt_89hpesx.c b/drivers/misc/eeprom/idt_89hpesx.c index ab0df6a17690..34a5a41578d7 100644 --- a/drivers/misc/eeprom/idt_89hpesx.c +++ b/drivers/misc/eeprom/idt_89hpesx.c @@ -77,7 +77,7 @@ #include <linux/sysfs.h> #include <linux/debugfs.h> #include <linux/mod_devicetable.h> -#include <linux/of.h> +#include <linux/property.h> #include <linux/i2c.h> #include <linux/pci_ids.h> #include <linux/delay.h> @@ -1089,101 +1089,85 @@ static void idt_set_defval(struct idt_89hpesx_dev *pdev) pdev->eeaddr = 0; } -#ifdef CONFIG_OF static const struct i2c_device_id ee_ids[]; + /* * idt_ee_match_id() - check whether the node belongs to compatible EEPROMs */ -static const struct i2c_device_id *idt_ee_match_id(struct device_node *node) +static const struct i2c_device_id *idt_ee_match_id(struct fwnode_handle *fwnode) { const struct i2c_device_id *id = ee_ids; + const char *compatible, *p; char devname[I2C_NAME_SIZE]; + int ret; - /* Retrieve the device name without manufacturer name */ - if (of_modalias_node(node, devname, sizeof(devname))) + ret = fwnode_property_read_string(fwnode, "compatible", &compatible); + if (ret) return NULL; + p = strchr(compatible, ','); + strlcpy(devname, p ? p + 1 : compatible, sizeof(devname)); /* Search through the device name */ - while (id->name[0]) { - if (strcmp(devname, id->name) == 0) - return id; - id++; - } - return NULL; + while (id->name[0]) { + if (strcmp(devname, id->name) == 0) + return id; + id++; + } + return NULL; } /* - * idt_get_ofdata() - get IDT i2c-device parameters from device tree + * idt_get_fw_data() - get IDT i2c-device parameters from device tree * @pdev: Pointer to the driver data */ -static void idt_get_ofdata(struct idt_89hpesx_dev *pdev) +static void idt_get_fw_data(struct idt_89hpesx_dev *pdev) { - const struct device_node *node = pdev->client->dev.of_node; struct device *dev = &pdev->client->dev; + struct fwnode_handle *fwnode; + const struct i2c_device_id *ee_id = NULL; + u32 eeprom_addr; + int ret; - /* Read dts node parameters */ - if (node) { - const struct i2c_device_id *ee_id = NULL; - struct device_node *child; - const __be32 *addr_be; - int len; - - /* Walk through all child nodes looking for compatible one */ - for_each_available_child_of_node(node, child) { - ee_id = idt_ee_match_id(child); - if (IS_ERR_OR_NULL(ee_id)) { - dev_warn(dev, "Skip unsupported child node %s", - child->full_name); - continue; - } else - break; - } - - /* If there is no child EEPROM device, then set zero size */ - if (!ee_id) { - idt_set_defval(pdev); - return; - } + device_for_each_child_node(dev, fwnode) { + ee_id = idt_ee_match_id(fwnode); + if (IS_ERR_OR_NULL(ee_id)) { + dev_warn(dev, "Skip unsupported EEPROM device"); + continue; + } else + break; + } - /* Retrieve EEPROM size */ - pdev->eesize = (u32)ee_id->driver_data; - - /* Get custom EEPROM address from 'reg' attribute */ - addr_be = of_get_property(child, "reg", &len); - if (!addr_be || (len < sizeof(*addr_be))) { - dev_warn(dev, "No reg on %s, use default address %d", - child->full_name, EEPROM_DEF_ADDR); - pdev->inieecmd = 0; - pdev->eeaddr = EEPROM_DEF_ADDR << 1; - } else { - pdev->inieecmd = EEPROM_USA; - pdev->eeaddr = be32_to_cpup(addr_be) << 1; - } + /* If there is no fwnode EEPROM device, then set zero size */ + if (!ee_id) { + dev_warn(dev, "No fwnode, EEPROM access disabled"); + idt_set_defval(pdev); + return; + } - /* Check EEPROM 'read-only' flag */ - if (of_get_property(child, "read-only", NULL)) - pdev->eero = true; - else /* if (!of_get_property(node, "read-only", NULL)) */ - pdev->eero = false; + /* Retrieve EEPROM size */ + pdev->eesize = (u32)ee_id->driver_data; - dev_dbg(dev, "EEPROM of %u bytes found by %hhu", - pdev->eesize, pdev->eeaddr); + /* Get custom EEPROM address from 'reg' attribute */ + ret = fwnode_property_read_u32(fwnode, "reg", &eeprom_addr); + if (ret || (eeprom_addr == 0)) { + dev_warn(dev, "No EEPROM reg found, use default address 0x%x", + EEPROM_DEF_ADDR); + pdev->inieecmd = 0; + pdev->eeaddr = EEPROM_DEF_ADDR << 1; } else { - dev_warn(dev, "No dts node, EEPROM access disabled"); - idt_set_defval(pdev); + pdev->inieecmd = EEPROM_USA; + pdev->eeaddr = eeprom_addr << 1; } -} -#else -static void idt_get_ofdata(struct idt_89hpesx_dev *pdev) -{ - struct device *dev = &pdev->client->dev; - dev_warn(dev, "OF table is unsupported, EEPROM access disabled"); + /* Check EEPROM 'read-only' flag */ + if (fwnode_property_read_bool(fwnode, "read-only")) + pdev->eero = true; + else /* if (!fwnode_property_read_bool(node, "read-only")) */ + pdev->eero = false; - /* Nothing we can do, just set the default values */ - idt_set_defval(pdev); + dev_info(dev, "EEPROM of %d bytes found by 0x%x", + pdev->eesize, pdev->eeaddr); } -#endif /* CONFIG_OF */ /* * idt_create_pdev() - create and init data structure of the driver @@ -1203,8 +1187,8 @@ static struct idt_89hpesx_dev *idt_create_pdev(struct i2c_client *client) pdev->client = client; i2c_set_clientdata(client, pdev); - /* Read OF nodes information */ - idt_get_ofdata(pdev); + /* Read firmware nodes information */ + idt_get_fw_data(pdev); /* Initialize basic CSR CMD field - use full DWORD-sized r/w ops */ pdev->inicsrcmd = CSR_DWE; diff --git a/drivers/misc/eeprom/max6875.c b/drivers/misc/eeprom/max6875.c index e4dd93b2518c..0e32709d1022 100644 --- a/drivers/misc/eeprom/max6875.c +++ b/drivers/misc/eeprom/max6875.c @@ -124,7 +124,7 @@ static ssize_t max6875_read(struct file *filp, struct kobject *kobj, return count; } -static struct bin_attribute user_eeprom_attr = { +static const struct bin_attribute user_eeprom_attr = { .attr = { .name = "eeprom", .mode = S_IRUGO, diff --git a/drivers/misc/hmc6352.c b/drivers/misc/hmc6352.c index 90520d76633f..eeb7eef62174 100644 --- a/drivers/misc/hmc6352.c +++ b/drivers/misc/hmc6352.c @@ -132,7 +132,7 @@ static int hmc6352_remove(struct i2c_client *client) return 0; } -static struct i2c_device_id hmc6352_id[] = { +static const struct i2c_device_id hmc6352_id[] = { { "hmc6352", 0 }, { } }; diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c index fea8ff40440f..097e3092c158 100644 --- a/drivers/misc/hpilo.c +++ b/drivers/misc/hpilo.c @@ -857,7 +857,7 @@ out: return error; } -static struct pci_device_id ilo_devices[] = { +static const struct pci_device_id ilo_devices[] = { { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB204) }, { PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3307) }, { } diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c index 8758d033db23..ec0832278170 100644 --- a/drivers/misc/ioc4.c +++ b/drivers/misc/ioc4.c @@ -454,7 +454,7 @@ ioc4_remove(struct pci_dev *pdev) kfree(idd); } -static struct pci_device_id ioc4_id_table[] = { +static const struct pci_device_id ioc4_id_table[] = { {PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC4, PCI_ANY_ID, PCI_ANY_ID, 0x0b4000, 0xFFFFFF}, {0} diff --git a/drivers/misc/isl29020.c b/drivers/misc/isl29020.c index 4a9c50a43afb..e3bd3c1d2574 100644 --- a/drivers/misc/isl29020.c +++ b/drivers/misc/isl29020.c @@ -145,7 +145,7 @@ static struct attribute *mid_att_als[] = { NULL }; -static struct attribute_group m_als_gr = { +static const struct attribute_group m_als_gr = { .name = "isl29020", .attrs = mid_att_als }; @@ -188,7 +188,7 @@ static int isl29020_remove(struct i2c_client *client) return 0; } -static struct i2c_device_id isl29020_id[] = { +static const struct i2c_device_id isl29020_id[] = { { "isl29020", 0 }, { } }; diff --git a/drivers/misc/lis3lv02d/lis3lv02d.c b/drivers/misc/lis3lv02d/lis3lv02d.c index e389b0b5278d..8d53609861d8 100644 --- a/drivers/misc/lis3lv02d/lis3lv02d.c +++ b/drivers/misc/lis3lv02d/lis3lv02d.c @@ -856,7 +856,7 @@ static struct attribute *lis3lv02d_attributes[] = { NULL }; -static struct attribute_group lis3lv02d_attribute_group = { +static const struct attribute_group lis3lv02d_attribute_group = { .attrs = lis3lv02d_attributes }; diff --git a/drivers/misc/lkdtm.h b/drivers/misc/lkdtm.h index 3b4976396ec4..bfb6c45b6130 100644 --- a/drivers/misc/lkdtm.h +++ b/drivers/misc/lkdtm.h @@ -14,20 +14,17 @@ void lkdtm_EXCEPTION(void); void lkdtm_LOOP(void); void lkdtm_OVERFLOW(void); void lkdtm_CORRUPT_STACK(void); +void lkdtm_CORRUPT_STACK_STRONG(void); void lkdtm_UNALIGNED_LOAD_STORE_WRITE(void); void lkdtm_SOFTLOCKUP(void); void lkdtm_HARDLOCKUP(void); void lkdtm_SPINLOCKUP(void); void lkdtm_HUNG_TASK(void); -void lkdtm_REFCOUNT_SATURATE_INC(void); -void lkdtm_REFCOUNT_SATURATE_ADD(void); -void lkdtm_REFCOUNT_ZERO_DEC(void); -void lkdtm_REFCOUNT_ZERO_INC(void); -void lkdtm_REFCOUNT_ZERO_SUB(void); -void lkdtm_REFCOUNT_ZERO_ADD(void); void lkdtm_CORRUPT_LIST_ADD(void); void lkdtm_CORRUPT_LIST_DEL(void); void lkdtm_CORRUPT_USER_DS(void); +void lkdtm_STACK_GUARD_PAGE_LEADING(void); +void lkdtm_STACK_GUARD_PAGE_TRAILING(void); /* lkdtm_heap.c */ void lkdtm_OVERWRITE_ALLOCATION(void); @@ -49,6 +46,27 @@ void lkdtm_EXEC_RODATA(void); void lkdtm_EXEC_USERSPACE(void); void lkdtm_ACCESS_USERSPACE(void); +/* lkdtm_refcount.c */ +void lkdtm_REFCOUNT_INC_OVERFLOW(void); +void lkdtm_REFCOUNT_ADD_OVERFLOW(void); +void lkdtm_REFCOUNT_INC_NOT_ZERO_OVERFLOW(void); +void lkdtm_REFCOUNT_ADD_NOT_ZERO_OVERFLOW(void); +void lkdtm_REFCOUNT_DEC_ZERO(void); +void lkdtm_REFCOUNT_DEC_NEGATIVE(void); +void lkdtm_REFCOUNT_DEC_AND_TEST_NEGATIVE(void); +void lkdtm_REFCOUNT_SUB_AND_TEST_NEGATIVE(void); +void lkdtm_REFCOUNT_INC_ZERO(void); +void lkdtm_REFCOUNT_ADD_ZERO(void); +void lkdtm_REFCOUNT_INC_SATURATED(void); +void lkdtm_REFCOUNT_DEC_SATURATED(void); +void lkdtm_REFCOUNT_ADD_SATURATED(void); +void lkdtm_REFCOUNT_INC_NOT_ZERO_SATURATED(void); +void lkdtm_REFCOUNT_ADD_NOT_ZERO_SATURATED(void); +void lkdtm_REFCOUNT_DEC_AND_TEST_SATURATED(void); +void lkdtm_REFCOUNT_SUB_AND_TEST_SATURATED(void); +void lkdtm_REFCOUNT_TIMING(void); +void lkdtm_ATOMIC_TIMING(void); + /* lkdtm_rodata.c */ void lkdtm_rodata_do_nothing(void); diff --git a/drivers/misc/lkdtm_bugs.c b/drivers/misc/lkdtm_bugs.c index d9028ef50fbe..9e0b4f959987 100644 --- a/drivers/misc/lkdtm_bugs.c +++ b/drivers/misc/lkdtm_bugs.c @@ -6,9 +6,9 @@ */ #include "lkdtm.h" #include <linux/list.h> -#include <linux/refcount.h> #include <linux/sched.h> #include <linux/sched/signal.h> +#include <linux/sched/task_stack.h> #include <linux/uaccess.h> struct lkdtm_list { @@ -85,16 +85,31 @@ void lkdtm_OVERFLOW(void) static noinline void __lkdtm_CORRUPT_STACK(void *stack) { - memset(stack, 'a', 64); + memset(stack, '\xff', 64); } +/* This should trip the stack canary, not corrupt the return address. */ noinline void lkdtm_CORRUPT_STACK(void) { /* Use default char array length that triggers stack protection. */ - char data[8]; + char data[8] __aligned(sizeof(void *)); + + __lkdtm_CORRUPT_STACK(&data); + + pr_info("Corrupted stack containing char array ...\n"); +} + +/* Same as above but will only get a canary with -fstack-protector-strong */ +noinline void lkdtm_CORRUPT_STACK_STRONG(void) +{ + union { + unsigned short shorts[4]; + unsigned long *ptr; + } data __aligned(sizeof(void *)); + __lkdtm_CORRUPT_STACK(&data); - pr_info("Corrupted stack with '%16s'...\n", data); + pr_info("Corrupted stack containing union ...\n"); } void lkdtm_UNALIGNED_LOAD_STORE_WRITE(void) @@ -137,88 +152,6 @@ void lkdtm_HUNG_TASK(void) schedule(); } -void lkdtm_REFCOUNT_SATURATE_INC(void) -{ - refcount_t over = REFCOUNT_INIT(UINT_MAX - 1); - - pr_info("attempting good refcount decrement\n"); - refcount_dec(&over); - refcount_inc(&over); - - pr_info("attempting bad refcount inc overflow\n"); - refcount_inc(&over); - refcount_inc(&over); - if (refcount_read(&over) == UINT_MAX) - pr_err("Correctly stayed saturated, but no BUG?!\n"); - else - pr_err("Fail: refcount wrapped\n"); -} - -void lkdtm_REFCOUNT_SATURATE_ADD(void) -{ - refcount_t over = REFCOUNT_INIT(UINT_MAX - 1); - - pr_info("attempting good refcount decrement\n"); - refcount_dec(&over); - refcount_inc(&over); - - pr_info("attempting bad refcount add overflow\n"); - refcount_add(2, &over); - if (refcount_read(&over) == UINT_MAX) - pr_err("Correctly stayed saturated, but no BUG?!\n"); - else - pr_err("Fail: refcount wrapped\n"); -} - -void lkdtm_REFCOUNT_ZERO_DEC(void) -{ - refcount_t zero = REFCOUNT_INIT(1); - - pr_info("attempting bad refcount decrement to zero\n"); - refcount_dec(&zero); - if (refcount_read(&zero) == 0) - pr_err("Stayed at zero, but no BUG?!\n"); - else - pr_err("Fail: refcount went crazy\n"); -} - -void lkdtm_REFCOUNT_ZERO_SUB(void) -{ - refcount_t zero = REFCOUNT_INIT(1); - - pr_info("attempting bad refcount subtract past zero\n"); - if (!refcount_sub_and_test(2, &zero)) - pr_info("wrap attempt was noticed\n"); - if (refcount_read(&zero) == 1) - pr_err("Correctly stayed above 0, but no BUG?!\n"); - else - pr_err("Fail: refcount wrapped\n"); -} - -void lkdtm_REFCOUNT_ZERO_INC(void) -{ - refcount_t zero = REFCOUNT_INIT(0); - - pr_info("attempting bad refcount increment from zero\n"); - refcount_inc(&zero); - if (refcount_read(&zero) == 0) - pr_err("Stayed at zero, but no BUG?!\n"); - else - pr_err("Fail: refcount went past zero\n"); -} - -void lkdtm_REFCOUNT_ZERO_ADD(void) -{ - refcount_t zero = REFCOUNT_INIT(0); - - pr_info("attempting bad refcount addition from zero\n"); - refcount_add(2, &zero); - if (refcount_read(&zero) == 0) - pr_err("Stayed at zero, but no BUG?!\n"); - else - pr_err("Fail: refcount went past zero\n"); -} - void lkdtm_CORRUPT_LIST_ADD(void) { /* @@ -282,6 +215,7 @@ void lkdtm_CORRUPT_LIST_DEL(void) pr_err("list_del() corruption not detected!\n"); } +/* Test if unbalanced set_fs(KERNEL_DS)/set_fs(USER_DS) check exists. */ void lkdtm_CORRUPT_USER_DS(void) { pr_info("setting bad task size limit\n"); @@ -290,3 +224,31 @@ void lkdtm_CORRUPT_USER_DS(void) /* Make sure we do not keep running with a KERNEL_DS! */ force_sig(SIGKILL, current); } + +/* Test that VMAP_STACK is actually allocating with a leading guard page */ +void lkdtm_STACK_GUARD_PAGE_LEADING(void) +{ + const unsigned char *stack = task_stack_page(current); + const unsigned char *ptr = stack - 1; + volatile unsigned char byte; + + pr_info("attempting bad read from page below current stack\n"); + + byte = *ptr; + + pr_err("FAIL: accessed page before stack!\n"); +} + +/* Test that VMAP_STACK is actually allocating with a trailing guard page */ +void lkdtm_STACK_GUARD_PAGE_TRAILING(void) +{ + const unsigned char *stack = task_stack_page(current); + const unsigned char *ptr = stack + THREAD_SIZE; + volatile unsigned char byte; + + pr_info("attempting bad read from page above current stack\n"); + + byte = *ptr; + + pr_err("FAIL: accessed page after stack!\n"); +} diff --git a/drivers/misc/lkdtm_core.c b/drivers/misc/lkdtm_core.c index 42d2b8e31e6b..981b3ef71e47 100644 --- a/drivers/misc/lkdtm_core.c +++ b/drivers/misc/lkdtm_core.c @@ -201,6 +201,9 @@ struct crashtype crashtypes[] = { CRASHTYPE(CORRUPT_LIST_DEL), CRASHTYPE(CORRUPT_USER_DS), CRASHTYPE(CORRUPT_STACK), + CRASHTYPE(CORRUPT_STACK_STRONG), + CRASHTYPE(STACK_GUARD_PAGE_LEADING), + CRASHTYPE(STACK_GUARD_PAGE_TRAILING), CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE), CRASHTYPE(OVERWRITE_ALLOCATION), CRASHTYPE(WRITE_AFTER_FREE), @@ -221,12 +224,25 @@ struct crashtype crashtypes[] = { CRASHTYPE(WRITE_RO), CRASHTYPE(WRITE_RO_AFTER_INIT), CRASHTYPE(WRITE_KERN), - CRASHTYPE(REFCOUNT_SATURATE_INC), - CRASHTYPE(REFCOUNT_SATURATE_ADD), - CRASHTYPE(REFCOUNT_ZERO_DEC), - CRASHTYPE(REFCOUNT_ZERO_INC), - CRASHTYPE(REFCOUNT_ZERO_SUB), - CRASHTYPE(REFCOUNT_ZERO_ADD), + CRASHTYPE(REFCOUNT_INC_OVERFLOW), + CRASHTYPE(REFCOUNT_ADD_OVERFLOW), + CRASHTYPE(REFCOUNT_INC_NOT_ZERO_OVERFLOW), + CRASHTYPE(REFCOUNT_ADD_NOT_ZERO_OVERFLOW), + CRASHTYPE(REFCOUNT_DEC_ZERO), + CRASHTYPE(REFCOUNT_DEC_NEGATIVE), + CRASHTYPE(REFCOUNT_DEC_AND_TEST_NEGATIVE), + CRASHTYPE(REFCOUNT_SUB_AND_TEST_NEGATIVE), + CRASHTYPE(REFCOUNT_INC_ZERO), + CRASHTYPE(REFCOUNT_ADD_ZERO), + CRASHTYPE(REFCOUNT_INC_SATURATED), + CRASHTYPE(REFCOUNT_DEC_SATURATED), + CRASHTYPE(REFCOUNT_ADD_SATURATED), + CRASHTYPE(REFCOUNT_INC_NOT_ZERO_SATURATED), + CRASHTYPE(REFCOUNT_ADD_NOT_ZERO_SATURATED), + CRASHTYPE(REFCOUNT_DEC_AND_TEST_SATURATED), + CRASHTYPE(REFCOUNT_SUB_AND_TEST_SATURATED), + CRASHTYPE(REFCOUNT_TIMING), + CRASHTYPE(ATOMIC_TIMING), CRASHTYPE(USERCOPY_HEAP_SIZE_TO), CRASHTYPE(USERCOPY_HEAP_SIZE_FROM), CRASHTYPE(USERCOPY_HEAP_FLAG_TO), diff --git a/drivers/misc/lkdtm_refcount.c b/drivers/misc/lkdtm_refcount.c new file mode 100644 index 000000000000..2b99d448e7fd --- /dev/null +++ b/drivers/misc/lkdtm_refcount.c @@ -0,0 +1,400 @@ +/* + * This is for all the tests related to refcount bugs (e.g. overflow, + * underflow, reaching zero untested, etc). + */ +#include "lkdtm.h" +#include <linux/refcount.h> + +#ifdef CONFIG_REFCOUNT_FULL +#define REFCOUNT_MAX (UINT_MAX - 1) +#define REFCOUNT_SATURATED UINT_MAX +#else +#define REFCOUNT_MAX INT_MAX +#define REFCOUNT_SATURATED (INT_MIN / 2) +#endif + +static void overflow_check(refcount_t *ref) +{ + switch (refcount_read(ref)) { + case REFCOUNT_SATURATED: + pr_info("Overflow detected: saturated\n"); + break; + case REFCOUNT_MAX: + pr_warn("Overflow detected: unsafely reset to max\n"); + break; + default: + pr_err("Fail: refcount wrapped to %d\n", refcount_read(ref)); + } +} + +/* + * A refcount_inc() above the maximum value of the refcount implementation, + * should at least saturate, and at most also WARN. + */ +void lkdtm_REFCOUNT_INC_OVERFLOW(void) +{ + refcount_t over = REFCOUNT_INIT(REFCOUNT_MAX - 1); + + pr_info("attempting good refcount_inc() without overflow\n"); + refcount_dec(&over); + refcount_inc(&over); + + pr_info("attempting bad refcount_inc() overflow\n"); + refcount_inc(&over); + refcount_inc(&over); + + overflow_check(&over); +} + +/* refcount_add() should behave just like refcount_inc() above. */ +void lkdtm_REFCOUNT_ADD_OVERFLOW(void) +{ + refcount_t over = REFCOUNT_INIT(REFCOUNT_MAX - 1); + + pr_info("attempting good refcount_add() without overflow\n"); + refcount_dec(&over); + refcount_dec(&over); + refcount_dec(&over); + refcount_dec(&over); + refcount_add(4, &over); + + pr_info("attempting bad refcount_add() overflow\n"); + refcount_add(4, &over); + + overflow_check(&over); +} + +/* refcount_inc_not_zero() should behave just like refcount_inc() above. */ +void lkdtm_REFCOUNT_INC_NOT_ZERO_OVERFLOW(void) +{ + refcount_t over = REFCOUNT_INIT(REFCOUNT_MAX); + + pr_info("attempting bad refcount_inc_not_zero() overflow\n"); + if (!refcount_inc_not_zero(&over)) + pr_warn("Weird: refcount_inc_not_zero() reported zero\n"); + + overflow_check(&over); +} + +/* refcount_add_not_zero() should behave just like refcount_inc() above. */ +void lkdtm_REFCOUNT_ADD_NOT_ZERO_OVERFLOW(void) +{ + refcount_t over = REFCOUNT_INIT(REFCOUNT_MAX); + + pr_info("attempting bad refcount_add_not_zero() overflow\n"); + if (!refcount_add_not_zero(6, &over)) + pr_warn("Weird: refcount_add_not_zero() reported zero\n"); + + overflow_check(&over); +} + +static void check_zero(refcount_t *ref) +{ + switch (refcount_read(ref)) { + case REFCOUNT_SATURATED: + pr_info("Zero detected: saturated\n"); + break; + case REFCOUNT_MAX: + pr_warn("Zero detected: unsafely reset to max\n"); + break; + case 0: + pr_warn("Still at zero: refcount_inc/add() must not inc-from-0\n"); + break; + default: + pr_err("Fail: refcount went crazy: %d\n", refcount_read(ref)); + } +} + +/* + * A refcount_dec(), as opposed to a refcount_dec_and_test(), when it hits + * zero it should either saturate (when inc-from-zero isn't protected) + * or stay at zero (when inc-from-zero is protected) and should WARN for both. + */ +void lkdtm_REFCOUNT_DEC_ZERO(void) +{ + refcount_t zero = REFCOUNT_INIT(2); + + pr_info("attempting good refcount_dec()\n"); + refcount_dec(&zero); + + pr_info("attempting bad refcount_dec() to zero\n"); + refcount_dec(&zero); + + check_zero(&zero); +} + +static void check_negative(refcount_t *ref, int start) +{ + /* + * CONFIG_REFCOUNT_FULL refuses to move a refcount at all on an + * over-sub, so we have to track our starting position instead of + * looking only at zero-pinning. + */ + if (refcount_read(ref) == start) { + pr_warn("Still at %d: refcount_inc/add() must not inc-from-0\n", + start); + return; + } + + switch (refcount_read(ref)) { + case REFCOUNT_SATURATED: + pr_info("Negative detected: saturated\n"); + break; + case REFCOUNT_MAX: + pr_warn("Negative detected: unsafely reset to max\n"); + break; + default: + pr_err("Fail: refcount went crazy: %d\n", refcount_read(ref)); + } +} + +/* A refcount_dec() going negative should saturate and may WARN. */ +void lkdtm_REFCOUNT_DEC_NEGATIVE(void) +{ + refcount_t neg = REFCOUNT_INIT(0); + + pr_info("attempting bad refcount_dec() below zero\n"); + refcount_dec(&neg); + + check_negative(&neg, 0); +} + +/* + * A refcount_dec_and_test() should act like refcount_dec() above when + * going negative. + */ +void lkdtm_REFCOUNT_DEC_AND_TEST_NEGATIVE(void) +{ + refcount_t neg = REFCOUNT_INIT(0); + + pr_info("attempting bad refcount_dec_and_test() below zero\n"); + if (refcount_dec_and_test(&neg)) + pr_warn("Weird: refcount_dec_and_test() reported zero\n"); + + check_negative(&neg, 0); +} + +/* + * A refcount_sub_and_test() should act like refcount_dec_and_test() + * above when going negative. + */ +void lkdtm_REFCOUNT_SUB_AND_TEST_NEGATIVE(void) +{ + refcount_t neg = REFCOUNT_INIT(3); + + pr_info("attempting bad refcount_sub_and_test() below zero\n"); + if (refcount_sub_and_test(5, &neg)) + pr_warn("Weird: refcount_sub_and_test() reported zero\n"); + + check_negative(&neg, 3); +} + +static void check_from_zero(refcount_t *ref) +{ + switch (refcount_read(ref)) { + case 0: + pr_info("Zero detected: stayed at zero\n"); + break; + case REFCOUNT_SATURATED: + pr_info("Zero detected: saturated\n"); + break; + case REFCOUNT_MAX: + pr_warn("Zero detected: unsafely reset to max\n"); + break; + default: + pr_info("Fail: zero not detected, incremented to %d\n", + refcount_read(ref)); + } +} + +/* + * A refcount_inc() from zero should pin to zero or saturate and may WARN. + * Only CONFIG_REFCOUNT_FULL provides this protection currently. + */ +void lkdtm_REFCOUNT_INC_ZERO(void) +{ + refcount_t zero = REFCOUNT_INIT(0); + + pr_info("attempting safe refcount_inc_not_zero() from zero\n"); + if (!refcount_inc_not_zero(&zero)) { + pr_info("Good: zero detected\n"); + if (refcount_read(&zero) == 0) + pr_info("Correctly stayed at zero\n"); + else + pr_err("Fail: refcount went past zero!\n"); + } else { + pr_err("Fail: Zero not detected!?\n"); + } + + pr_info("attempting bad refcount_inc() from zero\n"); + refcount_inc(&zero); + + check_from_zero(&zero); +} + +/* + * A refcount_add() should act like refcount_inc() above when starting + * at zero. + */ +void lkdtm_REFCOUNT_ADD_ZERO(void) +{ + refcount_t zero = REFCOUNT_INIT(0); + + pr_info("attempting safe refcount_add_not_zero() from zero\n"); + if (!refcount_add_not_zero(3, &zero)) { + pr_info("Good: zero detected\n"); + if (refcount_read(&zero) == 0) + pr_info("Correctly stayed at zero\n"); + else + pr_err("Fail: refcount went past zero\n"); + } else { + pr_err("Fail: Zero not detected!?\n"); + } + + pr_info("attempting bad refcount_add() from zero\n"); + refcount_add(3, &zero); + + check_from_zero(&zero); +} + +static void check_saturated(refcount_t *ref) +{ + switch (refcount_read(ref)) { + case REFCOUNT_SATURATED: + pr_info("Saturation detected: still saturated\n"); + break; + case REFCOUNT_MAX: + pr_warn("Saturation detected: unsafely reset to max\n"); + break; + default: + pr_err("Fail: refcount went crazy: %d\n", refcount_read(ref)); + } +} + +/* + * A refcount_inc() from a saturated value should at most warn about + * being saturated already. + */ +void lkdtm_REFCOUNT_INC_SATURATED(void) +{ + refcount_t sat = REFCOUNT_INIT(REFCOUNT_SATURATED); + + pr_info("attempting bad refcount_inc() from saturated\n"); + refcount_inc(&sat); + + check_saturated(&sat); +} + +/* Should act like refcount_inc() above from saturated. */ +void lkdtm_REFCOUNT_DEC_SATURATED(void) +{ + refcount_t sat = REFCOUNT_INIT(REFCOUNT_SATURATED); + + pr_info("attempting bad refcount_dec() from saturated\n"); + refcount_dec(&sat); + + check_saturated(&sat); +} + +/* Should act like refcount_inc() above from saturated. */ +void lkdtm_REFCOUNT_ADD_SATURATED(void) +{ + refcount_t sat = REFCOUNT_INIT(REFCOUNT_SATURATED); + + pr_info("attempting bad refcount_dec() from saturated\n"); + refcount_add(8, &sat); + + check_saturated(&sat); +} + +/* Should act like refcount_inc() above from saturated. */ +void lkdtm_REFCOUNT_INC_NOT_ZERO_SATURATED(void) +{ + refcount_t sat = REFCOUNT_INIT(REFCOUNT_SATURATED); + + pr_info("attempting bad refcount_inc_not_zero() from saturated\n"); + if (!refcount_inc_not_zero(&sat)) + pr_warn("Weird: refcount_inc_not_zero() reported zero\n"); + + check_saturated(&sat); +} + +/* Should act like refcount_inc() above from saturated. */ +void lkdtm_REFCOUNT_ADD_NOT_ZERO_SATURATED(void) +{ + refcount_t sat = REFCOUNT_INIT(REFCOUNT_SATURATED); + + pr_info("attempting bad refcount_add_not_zero() from saturated\n"); + if (!refcount_add_not_zero(7, &sat)) + pr_warn("Weird: refcount_add_not_zero() reported zero\n"); + + check_saturated(&sat); +} + +/* Should act like refcount_inc() above from saturated. */ +void lkdtm_REFCOUNT_DEC_AND_TEST_SATURATED(void) +{ + refcount_t sat = REFCOUNT_INIT(REFCOUNT_SATURATED); + + pr_info("attempting bad refcount_dec_and_test() from saturated\n"); + if (refcount_dec_and_test(&sat)) + pr_warn("Weird: refcount_dec_and_test() reported zero\n"); + + check_saturated(&sat); +} + +/* Should act like refcount_inc() above from saturated. */ +void lkdtm_REFCOUNT_SUB_AND_TEST_SATURATED(void) +{ + refcount_t sat = REFCOUNT_INIT(REFCOUNT_SATURATED); + + pr_info("attempting bad refcount_sub_and_test() from saturated\n"); + if (refcount_sub_and_test(8, &sat)) + pr_warn("Weird: refcount_sub_and_test() reported zero\n"); + + check_saturated(&sat); +} + +/* Used to time the existing atomic_t when used for reference counting */ +void lkdtm_ATOMIC_TIMING(void) +{ + unsigned int i; + atomic_t count = ATOMIC_INIT(1); + + for (i = 0; i < INT_MAX - 1; i++) + atomic_inc(&count); + + for (i = INT_MAX; i > 0; i--) + if (atomic_dec_and_test(&count)) + break; + + if (i != 1) + pr_err("atomic timing: out of sync up/down cycle: %u\n", i - 1); + else + pr_info("atomic timing: done\n"); +} + +/* + * This can be compared to ATOMIC_TIMING when implementing fast refcount + * protections. Looking at the number of CPU cycles tells the real story + * about performance. For example: + * cd /sys/kernel/debug/provoke-crash + * perf stat -B -- cat <(echo REFCOUNT_TIMING) > DIRECT + */ +void lkdtm_REFCOUNT_TIMING(void) +{ + unsigned int i; + refcount_t count = REFCOUNT_INIT(1); + + for (i = 0; i < INT_MAX - 1; i++) + refcount_inc(&count); + + for (i = INT_MAX; i > 0; i--) + if (refcount_dec_and_test(&count)) + break; + + if (i != 1) + pr_err("refcount: out of sync up/down cycle: %u\n", i - 1); + else + pr_info("refcount timing: done\n"); +} diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 40c79089e548..1ac10cb64d6e 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -845,7 +845,7 @@ static void mei_cl_bus_dev_release(struct device *dev) kfree(cldev); } -static struct device_type mei_cl_device_type = { +static const struct device_type mei_cl_device_type = { .release = mei_cl_bus_dev_release, }; diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index 71216affcab1..10dcf4ff99a5 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -1354,10 +1354,10 @@ static bool mei_me_fw_type_sps(struct pci_dev *pdev) .quirk_probe = mei_me_fw_type_sps -#define MEI_CFG_LEGACY_HFS \ +#define MEI_CFG_ICH_HFS \ .fw_status.count = 0 -#define MEI_CFG_ICH_HFS \ +#define MEI_CFG_ICH10_HFS \ .fw_status.count = 1, \ .fw_status.status[0] = PCI_CFG_HFS_1 @@ -1376,38 +1376,61 @@ static bool mei_me_fw_type_sps(struct pci_dev *pdev) .fw_status.status[5] = PCI_CFG_HFS_6 /* ICH Legacy devices */ -const struct mei_cfg mei_me_legacy_cfg = { - MEI_CFG_LEGACY_HFS, +static const struct mei_cfg mei_me_ich_cfg = { + MEI_CFG_ICH_HFS, }; /* ICH devices */ -const struct mei_cfg mei_me_ich_cfg = { - MEI_CFG_ICH_HFS, +static const struct mei_cfg mei_me_ich10_cfg = { + MEI_CFG_ICH10_HFS, }; /* PCH devices */ -const struct mei_cfg mei_me_pch_cfg = { +static const struct mei_cfg mei_me_pch_cfg = { MEI_CFG_PCH_HFS, }; - /* PCH Cougar Point and Patsburg with quirk for Node Manager exclusion */ -const struct mei_cfg mei_me_pch_cpt_pbg_cfg = { +static const struct mei_cfg mei_me_pch_cpt_pbg_cfg = { MEI_CFG_PCH_HFS, MEI_CFG_FW_NM, }; /* PCH8 Lynx Point and newer devices */ -const struct mei_cfg mei_me_pch8_cfg = { +static const struct mei_cfg mei_me_pch8_cfg = { MEI_CFG_PCH8_HFS, }; /* PCH8 Lynx Point with quirk for SPS Firmware exclusion */ -const struct mei_cfg mei_me_pch8_sps_cfg = { +static const struct mei_cfg mei_me_pch8_sps_cfg = { MEI_CFG_PCH8_HFS, MEI_CFG_FW_SPS, }; +/* + * mei_cfg_list - A list of platform platform specific configurations. + * Note: has to be synchronized with enum mei_cfg_idx. + */ +static const struct mei_cfg *const mei_cfg_list[] = { + [MEI_ME_UNDEF_CFG] = NULL, + [MEI_ME_ICH_CFG] = &mei_me_ich_cfg, + [MEI_ME_ICH10_CFG] = &mei_me_ich10_cfg, + [MEI_ME_PCH_CFG] = &mei_me_pch_cfg, + [MEI_ME_PCH_CPT_PBG_CFG] = &mei_me_pch_cpt_pbg_cfg, + [MEI_ME_PCH8_CFG] = &mei_me_pch8_cfg, + [MEI_ME_PCH8_SPS_CFG] = &mei_me_pch8_sps_cfg, +}; + +const struct mei_cfg *mei_me_get_cfg(kernel_ulong_t idx) +{ + BUILD_BUG_ON(ARRAY_SIZE(mei_cfg_list) != MEI_ME_NUM_CFG); + + if (idx >= MEI_ME_NUM_CFG) + return NULL; + + return mei_cfg_list[idx]; +}; + /** * mei_me_dev_init - allocates and initializes the mei device structure * diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h index cf64847a35b9..67892533576e 100644 --- a/drivers/misc/mei/hw-me.h +++ b/drivers/misc/mei/hw-me.h @@ -41,8 +41,7 @@ struct mei_cfg { #define MEI_PCI_DEVICE(dev, cfg) \ .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, \ - .driver_data = (kernel_ulong_t)&(cfg) - + .driver_data = (kernel_ulong_t)(cfg), #define MEI_ME_RPM_TIMEOUT 500 /* ms */ @@ -63,12 +62,36 @@ struct mei_me_hw { #define to_me_hw(dev) (struct mei_me_hw *)((dev)->hw) -extern const struct mei_cfg mei_me_legacy_cfg; -extern const struct mei_cfg mei_me_ich_cfg; -extern const struct mei_cfg mei_me_pch_cfg; -extern const struct mei_cfg mei_me_pch_cpt_pbg_cfg; -extern const struct mei_cfg mei_me_pch8_cfg; -extern const struct mei_cfg mei_me_pch8_sps_cfg; +/** + * enum mei_cfg_idx - indices to platform specific configurations. + * + * Note: has to be synchronized with mei_cfg_list[] + * + * @MEI_ME_UNDEF_CFG: Lower sentinel. + * @MEI_ME_ICH_CFG: I/O Controller Hub legacy devices. + * @MEI_ME_ICH10_CFG: I/O Controller Hub platforms Gen10 + * @MEI_ME_PCH_CFG: Platform Controller Hub platforms (Up to Gen8). + * @MEI_ME_PCH_CPT_PBG_CFG:Platform Controller Hub workstations + * with quirk for Node Manager exclusion. + * @MEI_ME_PCH8_CFG: Platform Controller Hub Gen8 and newer + * client platforms. + * @MEI_ME_PCH8_SPS_CFG: Platform Controller Hub Gen8 and newer + * servers platforms with quirk for + * SPS firmware exclusion. + * @MEI_ME_NUM_CFG: Upper Sentinel. + */ +enum mei_cfg_idx { + MEI_ME_UNDEF_CFG, + MEI_ME_ICH_CFG, + MEI_ME_ICH10_CFG, + MEI_ME_PCH_CFG, + MEI_ME_PCH_CPT_PBG_CFG, + MEI_ME_PCH8_CFG, + MEI_ME_PCH8_SPS_CFG, + MEI_ME_NUM_CFG, +}; + +const struct mei_cfg *mei_me_get_cfg(kernel_ulong_t idx); struct mei_device *mei_me_dev_init(struct pci_dev *pdev, const struct mei_cfg *cfg); diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index bac33311f55a..4ff40d319676 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -43,57 +43,58 @@ /* mei_pci_tbl - PCI Device ID Table */ static const struct pci_device_id mei_me_pci_tbl[] = { - {MEI_PCI_DEVICE(MEI_DEV_ID_82946GZ, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_82G35, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_82Q965, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_82G965, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_82GM965, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_82GME965, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_82Q35, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_82G33, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_82Q33, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_82X38, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_3200, mei_me_legacy_cfg)}, - - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_6, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_7, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_8, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_9, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_10, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9M_1, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9M_2, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9M_3, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9M_4, mei_me_legacy_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH10_1, mei_me_ich_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH10_2, mei_me_ich_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH10_3, mei_me_ich_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_ICH10_4, mei_me_ich_cfg)}, - - {MEI_PCI_DEVICE(MEI_DEV_ID_IBXPK_1, mei_me_pch_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_IBXPK_2, mei_me_pch_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_CPT_1, mei_me_pch_cpt_pbg_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_PBG_1, mei_me_pch_cpt_pbg_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_PPT_1, mei_me_pch_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_PPT_2, mei_me_pch_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_PPT_3, mei_me_pch_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_H, mei_me_pch8_sps_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_W, mei_me_pch8_sps_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_LP, mei_me_pch8_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_HR, mei_me_pch8_sps_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP, mei_me_pch8_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP_2, mei_me_pch8_cfg)}, - - {MEI_PCI_DEVICE(MEI_DEV_ID_SPT, mei_me_pch8_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, mei_me_pch8_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, mei_me_pch8_sps_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, mei_me_pch8_sps_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_LBG, mei_me_pch8_cfg)}, - - {MEI_PCI_DEVICE(MEI_DEV_ID_BXT_M, mei_me_pch8_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_APL_I, mei_me_pch8_cfg)}, - - {MEI_PCI_DEVICE(MEI_DEV_ID_KBP, mei_me_pch8_cfg)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_KBP_2, mei_me_pch8_cfg)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_82946GZ, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_82G35, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_82Q965, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_82G965, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_82GM965, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_82GME965, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_82Q35, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_82G33, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_82Q33, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_82X38, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_3200, MEI_ME_ICH_CFG)}, + + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_6, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_7, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_8, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_9, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9_10, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9M_1, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9M_2, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9M_3, MEI_ME_ICH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH9M_4, MEI_ME_ICH_CFG)}, + + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH10_1, MEI_ME_ICH10_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH10_2, MEI_ME_ICH10_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH10_3, MEI_ME_ICH10_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_ICH10_4, MEI_ME_ICH10_CFG)}, + + {MEI_PCI_DEVICE(MEI_DEV_ID_IBXPK_1, MEI_ME_PCH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_IBXPK_2, MEI_ME_PCH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_CPT_1, MEI_ME_PCH_CPT_PBG_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_PBG_1, MEI_ME_PCH_CPT_PBG_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_PPT_1, MEI_ME_PCH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_PPT_2, MEI_ME_PCH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_PPT_3, MEI_ME_PCH_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_H, MEI_ME_PCH8_SPS_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_W, MEI_ME_PCH8_SPS_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_LP, MEI_ME_PCH8_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_HR, MEI_ME_PCH8_SPS_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP, MEI_ME_PCH8_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP_2, MEI_ME_PCH8_CFG)}, + + {MEI_PCI_DEVICE(MEI_DEV_ID_SPT, MEI_ME_PCH8_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, MEI_ME_PCH8_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, MEI_ME_PCH8_SPS_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, MEI_ME_PCH8_SPS_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH8_CFG)}, + + {MEI_PCI_DEVICE(MEI_DEV_ID_BXT_M, MEI_ME_PCH8_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_APL_I, MEI_ME_PCH8_CFG)}, + + {MEI_PCI_DEVICE(MEI_DEV_ID_KBP, MEI_ME_PCH8_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_KBP_2, MEI_ME_PCH8_CFG)}, /* required last entry */ {0, } @@ -138,12 +139,15 @@ static bool mei_me_quirk_probe(struct pci_dev *pdev, */ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - const struct mei_cfg *cfg = (struct mei_cfg *)(ent->driver_data); + const struct mei_cfg *cfg; struct mei_device *dev; struct mei_me_hw *hw; unsigned int irqflags; int err; + cfg = mei_me_get_cfg(ent->driver_data); + if (!cfg) + return -ENODEV; if (!mei_me_quirk_probe(pdev, cfg)) return -ENODEV; @@ -491,6 +495,7 @@ static struct pci_driver mei_me_driver = { .remove = mei_me_remove, .shutdown = mei_me_shutdown, .driver.pm = MEI_ME_PM_OPS, + .driver.probe_type = PROBE_PREFER_ASYNCHRONOUS, }; module_pci_driver(mei_me_driver); diff --git a/drivers/misc/mic/scif/scif_dma.c b/drivers/misc/mic/scif/scif_dma.c index 64d5760d069a..63d6246d6dff 100644 --- a/drivers/misc/mic/scif/scif_dma.c +++ b/drivers/misc/mic/scif/scif_dma.c @@ -200,16 +200,6 @@ static void scif_mmu_notifier_release(struct mmu_notifier *mn, schedule_work(&scif_info.misc_work); } -static void scif_mmu_notifier_invalidate_page(struct mmu_notifier *mn, - struct mm_struct *mm, - unsigned long address) -{ - struct scif_mmu_notif *mmn; - - mmn = container_of(mn, struct scif_mmu_notif, ep_mmu_notifier); - scif_rma_destroy_tcw(mmn, address, PAGE_SIZE); -} - static void scif_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn, struct mm_struct *mm, unsigned long start, @@ -235,7 +225,6 @@ static void scif_mmu_notifier_invalidate_range_end(struct mmu_notifier *mn, static const struct mmu_notifier_ops scif_mmu_notifier_ops = { .release = scif_mmu_notifier_release, .clear_flush_young = NULL, - .invalidate_page = scif_mmu_notifier_invalidate_page, .invalidate_range_start = scif_mmu_notifier_invalidate_range_start, .invalidate_range_end = scif_mmu_notifier_invalidate_range_end}; diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c index e42bdc90fa27..540845651b8c 100644 --- a/drivers/misc/pch_phub.c +++ b/drivers/misc/pch_phub.c @@ -659,7 +659,7 @@ static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(pch_mac, S_IRUGO | S_IWUSR, show_pch_mac, store_pch_mac); -static struct bin_attribute pch_bin_attr = { +static const struct bin_attribute pch_bin_attr = { .attr = { .name = "pch_firmware", .mode = S_IRUGO | S_IWUSR, @@ -891,7 +891,7 @@ static int pch_phub_resume(struct pci_dev *pdev) #define pch_phub_resume NULL #endif /* CONFIG_PM */ -static struct pci_device_id pch_phub_pcidev_id[] = { +static const struct pci_device_id pch_phub_pcidev_id[] = { { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH1_PHUB), 1, }, { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7213_PHUB), 2, }, { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_mPHUB), 3, }, diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index 09c10f426b64..deb203026496 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -72,6 +72,11 @@ static DEFINE_IDA(pci_endpoint_test_ida); #define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \ miscdev) + +static bool no_msi; +module_param(no_msi, bool, 0444); +MODULE_PARM_DESC(no_msi, "Disable MSI interrupt in pci_endpoint_test"); + enum pci_barno { BAR_0, BAR_1, @@ -90,9 +95,15 @@ struct pci_endpoint_test { /* mutex to protect the ioctls */ struct mutex mutex; struct miscdevice miscdev; + enum pci_barno test_reg_bar; + size_t alignment; }; -static int bar_size[] = { 4, 512, 1024, 16384, 131072, 1048576 }; +struct pci_endpoint_test_data { + enum pci_barno test_reg_bar; + size_t alignment; + bool no_msi; +}; static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test, u32 offset) @@ -141,11 +152,15 @@ static bool pci_endpoint_test_bar(struct pci_endpoint_test *test, int j; u32 val; int size; + struct pci_dev *pdev = test->pdev; if (!test->bar[barno]) return false; - size = bar_size[barno]; + size = pci_resource_len(pdev, barno); + + if (barno == test->test_reg_bar) + size = 0x4; for (j = 0; j < size; j += 4) pci_endpoint_test_bar_writel(test, barno, j, 0xA0A0A0A0); @@ -202,16 +217,32 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size) dma_addr_t dst_phys_addr; struct pci_dev *pdev = test->pdev; struct device *dev = &pdev->dev; + void *orig_src_addr; + dma_addr_t orig_src_phys_addr; + void *orig_dst_addr; + dma_addr_t orig_dst_phys_addr; + size_t offset; + size_t alignment = test->alignment; u32 src_crc32; u32 dst_crc32; - src_addr = dma_alloc_coherent(dev, size, &src_phys_addr, GFP_KERNEL); - if (!src_addr) { + orig_src_addr = dma_alloc_coherent(dev, size + alignment, + &orig_src_phys_addr, GFP_KERNEL); + if (!orig_src_addr) { dev_err(dev, "failed to allocate source buffer\n"); ret = false; goto err; } + if (alignment && !IS_ALIGNED(orig_src_phys_addr, alignment)) { + src_phys_addr = PTR_ALIGN(orig_src_phys_addr, alignment); + offset = src_phys_addr - orig_src_phys_addr; + src_addr = orig_src_addr + offset; + } else { + src_phys_addr = orig_src_phys_addr; + src_addr = orig_src_addr; + } + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR, lower_32_bits(src_phys_addr)); @@ -221,11 +252,21 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size) get_random_bytes(src_addr, size); src_crc32 = crc32_le(~0, src_addr, size); - dst_addr = dma_alloc_coherent(dev, size, &dst_phys_addr, GFP_KERNEL); - if (!dst_addr) { + orig_dst_addr = dma_alloc_coherent(dev, size + alignment, + &orig_dst_phys_addr, GFP_KERNEL); + if (!orig_dst_addr) { dev_err(dev, "failed to allocate destination address\n"); ret = false; - goto err_src_addr; + goto err_orig_src_addr; + } + + if (alignment && !IS_ALIGNED(orig_dst_phys_addr, alignment)) { + dst_phys_addr = PTR_ALIGN(orig_dst_phys_addr, alignment); + offset = dst_phys_addr - orig_dst_phys_addr; + dst_addr = orig_dst_addr + offset; + } else { + dst_phys_addr = orig_dst_phys_addr; + dst_addr = orig_dst_addr; } pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR, @@ -245,10 +286,12 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size) if (dst_crc32 == src_crc32) ret = true; - dma_free_coherent(dev, size, dst_addr, dst_phys_addr); + dma_free_coherent(dev, size + alignment, orig_dst_addr, + orig_dst_phys_addr); -err_src_addr: - dma_free_coherent(dev, size, src_addr, src_phys_addr); +err_orig_src_addr: + dma_free_coherent(dev, size + alignment, orig_src_addr, + orig_src_phys_addr); err: return ret; @@ -262,15 +305,29 @@ static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size) dma_addr_t phys_addr; struct pci_dev *pdev = test->pdev; struct device *dev = &pdev->dev; + void *orig_addr; + dma_addr_t orig_phys_addr; + size_t offset; + size_t alignment = test->alignment; u32 crc32; - addr = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL); - if (!addr) { + orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr, + GFP_KERNEL); + if (!orig_addr) { dev_err(dev, "failed to allocate address\n"); ret = false; goto err; } + if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) { + phys_addr = PTR_ALIGN(orig_phys_addr, alignment); + offset = phys_addr - orig_phys_addr; + addr = orig_addr + offset; + } else { + phys_addr = orig_phys_addr; + addr = orig_addr; + } + get_random_bytes(addr, size); crc32 = crc32_le(~0, addr, size); @@ -293,7 +350,7 @@ static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size) if (reg & STATUS_READ_SUCCESS) ret = true; - dma_free_coherent(dev, size, addr, phys_addr); + dma_free_coherent(dev, size + alignment, orig_addr, orig_phys_addr); err: return ret; @@ -306,15 +363,29 @@ static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size) dma_addr_t phys_addr; struct pci_dev *pdev = test->pdev; struct device *dev = &pdev->dev; + void *orig_addr; + dma_addr_t orig_phys_addr; + size_t offset; + size_t alignment = test->alignment; u32 crc32; - addr = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL); - if (!addr) { + orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr, + GFP_KERNEL); + if (!orig_addr) { dev_err(dev, "failed to allocate destination address\n"); ret = false; goto err; } + if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) { + phys_addr = PTR_ALIGN(orig_phys_addr, alignment); + offset = phys_addr - orig_phys_addr; + addr = orig_addr + offset; + } else { + phys_addr = orig_phys_addr; + addr = orig_addr; + } + pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR, lower_32_bits(phys_addr)); pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR, @@ -331,7 +402,7 @@ static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size) if (crc32 == pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_CHECKSUM)) ret = true; - dma_free_coherent(dev, size, addr, phys_addr); + dma_free_coherent(dev, size + alignment, orig_addr, orig_phys_addr); err: return ret; } @@ -383,13 +454,15 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, { int i; int err; - int irq; + int irq = 0; int id; char name[20]; enum pci_barno bar; void __iomem *base; struct device *dev = &pdev->dev; struct pci_endpoint_test *test; + struct pci_endpoint_test_data *data; + enum pci_barno test_reg_bar = BAR_0; struct miscdevice *misc_device; if (pci_is_bridge(pdev)) @@ -399,7 +472,17 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, if (!test) return -ENOMEM; + test->test_reg_bar = 0; + test->alignment = 0; test->pdev = pdev; + + data = (struct pci_endpoint_test_data *)ent->driver_data; + if (data) { + test_reg_bar = data->test_reg_bar; + test->alignment = data->alignment; + no_msi = data->no_msi; + } + init_completion(&test->irq_raised); mutex_init(&test->mutex); @@ -417,9 +500,11 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, pci_set_master(pdev); - irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI); - if (irq < 0) - dev_err(dev, "failed to get MSI interrupts\n"); + if (!no_msi) { + irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI); + if (irq < 0) + dev_err(dev, "failed to get MSI interrupts\n"); + } err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler, IRQF_SHARED, DRV_MODULE_NAME, test); @@ -441,14 +526,15 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, base = pci_ioremap_bar(pdev, bar); if (!base) { dev_err(dev, "failed to read BAR%d\n", bar); - WARN_ON(bar == BAR_0); + WARN_ON(bar == test_reg_bar); } test->bar[bar] = base; } - test->base = test->bar[0]; + test->base = test->bar[test_reg_bar]; if (!test->base) { - dev_err(dev, "Cannot perform PCI test without BAR0\n"); + dev_err(dev, "Cannot perform PCI test without BAR%d\n", + test_reg_bar); goto err_iounmap; } diff --git a/drivers/misc/sgi-gru/grutlbpurge.c b/drivers/misc/sgi-gru/grutlbpurge.c index e936d43895d2..9918eda0e05f 100644 --- a/drivers/misc/sgi-gru/grutlbpurge.c +++ b/drivers/misc/sgi-gru/grutlbpurge.c @@ -247,17 +247,6 @@ static void gru_invalidate_range_end(struct mmu_notifier *mn, gru_dbg(grudev, "gms %p, start 0x%lx, end 0x%lx\n", gms, start, end); } -static void gru_invalidate_page(struct mmu_notifier *mn, struct mm_struct *mm, - unsigned long address) -{ - struct gru_mm_struct *gms = container_of(mn, struct gru_mm_struct, - ms_notifier); - - STAT(mmu_invalidate_page); - gru_flush_tlb_range(gms, address, PAGE_SIZE); - gru_dbg(grudev, "gms %p, address 0x%lx\n", gms, address); -} - static void gru_release(struct mmu_notifier *mn, struct mm_struct *mm) { struct gru_mm_struct *gms = container_of(mn, struct gru_mm_struct, @@ -269,7 +258,6 @@ static void gru_release(struct mmu_notifier *mn, struct mm_struct *mm) static const struct mmu_notifier_ops gru_mmuops = { - .invalidate_page = gru_invalidate_page, .invalidate_range_start = gru_invalidate_range_start, .invalidate_range_end = gru_invalidate_range_end, .release = gru_release, diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c index d1185b78cf9a..fc0415771c00 100644 --- a/drivers/misc/sram.c +++ b/drivers/misc/sram.c @@ -196,15 +196,15 @@ static int sram_reserve_regions(struct sram_dev *sram, struct resource *res) ret = of_address_to_resource(child, 0, &child_res); if (ret < 0) { dev_err(sram->dev, - "could not get address for node %s\n", - child->full_name); + "could not get address for node %pOF\n", + child); goto err_chunks; } if (child_res.start < res->start || child_res.end > res->end) { dev_err(sram->dev, - "reserved block %s outside the sram area\n", - child->full_name); + "reserved block %pOF outside the sram area\n", + child); ret = -EINVAL; goto err_chunks; } @@ -230,8 +230,8 @@ static int sram_reserve_regions(struct sram_dev *sram, struct resource *res) ret = of_property_read_string(child, "label", &label); if (ret && ret != -EINVAL) { dev_err(sram->dev, - "%s has invalid label name\n", - child->full_name); + "%pOF has invalid label name\n", + child); goto err_chunks; } if (!label) diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index e74413f882ab..b77aacafc3fc 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c @@ -660,7 +660,7 @@ static struct attribute *uim_attrs[] = { NULL, }; -static struct attribute_group uim_attr_grp = { +static const struct attribute_group uim_attr_grp = { .attrs = uim_attrs, }; diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c index a37a42f67088..e5f108713dd8 100644 --- a/drivers/misc/tifm_7xx1.c +++ b/drivers/misc/tifm_7xx1.c @@ -415,7 +415,7 @@ static void tifm_7xx1_remove(struct pci_dev *dev) tifm_free_adapter(fm); } -static struct pci_device_id tifm_7xx1_pci_tbl [] = { +static const struct pci_device_id tifm_7xx1_pci_tbl[] = { { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11_FM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* xx21 - the one I have */ { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX12_FM, PCI_ANY_ID, diff --git a/drivers/misc/vmw_vmci/vmci_queue_pair.c b/drivers/misc/vmw_vmci/vmci_queue_pair.c index 06c4974ee8dd..8af5c2672f71 100644 --- a/drivers/misc/vmw_vmci/vmci_queue_pair.c +++ b/drivers/misc/vmw_vmci/vmci_queue_pair.c @@ -2235,14 +2235,8 @@ int vmci_qp_broker_detach(struct vmci_handle handle, struct vmci_ctx *context) handle.context, handle.resource, result); - if (entry->vmci_page_files) - qp_host_unregister_user_memory(entry->produce_q, - entry-> - consume_q); - else - qp_host_unregister_user_memory(entry->produce_q, - entry-> - consume_q); + qp_host_unregister_user_memory(entry->produce_q, + entry->consume_q); } |