Merge tag 'char-misc-4.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver updates from Greg KH: "Here is the big char/misc driver update for 4.14-rc1. Lots of different stuff in here, it's been an active development cycle for some reason. Highlights are: - updated binder driver, this brings binder up to date with what shipped in the Android O release, plus some more changes that happened since then that are in the Android development trees. - coresight updates and fixes - mux driver file renames to be a bit "nicer" - intel_th driver updates - normal set of hyper-v updates and changes - small fpga subsystem and driver updates - lots of const code changes all over the driver trees - extcon driver updates - fmc driver subsystem upadates - w1 subsystem minor reworks and new features and drivers added - spmi driver updates Plus a smattering of other minor driver updates and fixes. All of these have been in linux-next with no reported issues for a while" * tag 'char-misc-4.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (244 commits) ANDROID: binder: don't queue async transactions to thread. ANDROID: binder: don't enqueue death notifications to thread todo. ANDROID: binder: Don't BUG_ON(!spin_is_locked()). ANDROID: binder: Add BINDER_GET_NODE_DEBUG_INFO ioctl ANDROID: binder: push new transactions to waiting threads. ANDROID: binder: remove proc waitqueue android: binder: Add page usage in binder stats android: binder: fixup crash introduced by moving buffer hdr drivers: w1: add hwmon temp support for w1_therm drivers: w1: refactor w1_slave_show to make the temp reading functionality separate drivers: w1: add hwmon support structures eeprom: idt_89hpesx: Support both ACPI and OF probing mcb: Fix an error handling path in 'chameleon_parse_cells()' MCB: add support for SC31 to mcb-lpc mux: make device_type const char: virtio: constify attribute_group structures. Documentation/ABI: document the nvmem sysfs files lkdtm: fix spelling mistake: "incremeted" -> "incremented" perf: cs-etm: Fix ETMv4 CONFIGR entry in perf.data file nvmem: include linux/err.h from header ...
Este cometimento está contido em:
@@ -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
|
||||
|
||||
|
@@ -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 },
|
||||
{ }
|
||||
};
|
||||
|
@@ -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 },
|
||||
};
|
||||
|
||||
|
@@ -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 },
|
||||
{ },
|
||||
};
|
||||
|
||||
|
@@ -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
|
||||
};
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
dev_dbg(dev, "EEPROM of %u bytes found by %hhu",
|
||||
pdev->eesize, pdev->eeaddr);
|
||||
} else {
|
||||
dev_warn(dev, "No dts node, EEPROM access disabled");
|
||||
idt_set_defval(pdev);
|
||||
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;
|
||||
}
|
||||
}
|
||||
#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");
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* Nothing we can do, just set the default values */
|
||||
idt_set_defval(pdev);
|
||||
/* Retrieve EEPROM size */
|
||||
pdev->eesize = (u32)ee_id->driver_data;
|
||||
|
||||
/* 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 {
|
||||
pdev->inieecmd = EEPROM_USA;
|
||||
pdev->eeaddr = eeprom_addr << 1;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
|
@@ -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,
|
||||
|
@@ -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 },
|
||||
{ }
|
||||
};
|
||||
|
@@ -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) },
|
||||
{ }
|
||||
|
@@ -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}
|
||||
|
@@ -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 },
|
||||
{ }
|
||||
};
|
||||
|
@@ -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
|
||||
};
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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 with '%16s'...\n", 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 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");
|
||||
}
|
||||
|
@@ -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),
|
||||
|
400
drivers/misc/lkdtm_refcount.c
Ficheiro normal
400
drivers/misc/lkdtm_refcount.c
Ficheiro normal
@@ -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");
|
||||
}
|
@@ -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,
|
||||
};
|
||||
|
||||
|
@@ -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,
|
||||
};
|
||||
|
||||
/* ICH devices */
|
||||
const struct mei_cfg mei_me_ich_cfg = {
|
||||
static const struct mei_cfg mei_me_ich_cfg = {
|
||||
MEI_CFG_ICH_HFS,
|
||||
};
|
||||
|
||||
/* ICH devices */
|
||||
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
|
||||
*
|
||||
|
@@ -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);
|
||||
|
@@ -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_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_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_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_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_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_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_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_BXT_M, mei_me_pch8_cfg)},
|
||||
{MEI_PCI_DEVICE(MEI_DEV_ID_APL_I, 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_KBP, mei_me_pch8_cfg)},
|
||||
{MEI_PCI_DEVICE(MEI_DEV_ID_KBP_2, 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);
|
||||
|
@@ -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, },
|
||||
|
@@ -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)
|
||||
|
@@ -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,
|
||||
};
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
Criar uma nova questão referindo esta
Bloquear um utilizador