aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/Kconfig2
-rw-r--r--drivers/misc/apds990x.c4
-rw-r--r--drivers/misc/arm-charlcd.c1
-rw-r--r--drivers/misc/atmel-ssc.c5
-rw-r--r--drivers/misc/bh1770glc.c2
-rw-r--r--drivers/misc/carma/Kconfig6
-rw-r--r--drivers/misc/carma/carma-fpga-program.c105
-rw-r--r--drivers/misc/carma/carma-fpga.c99
-rw-r--r--drivers/misc/cs5535-mfgpt.c1
-rw-r--r--drivers/misc/cxl/context.c26
-rw-r--r--drivers/misc/cxl/cxl.h24
-rw-r--r--drivers/misc/cxl/fault.c8
-rw-r--r--drivers/misc/cxl/file.c6
-rw-r--r--drivers/misc/cxl/irq.c144
-rw-r--r--drivers/misc/cxl/native.c26
-rw-r--r--drivers/misc/cxl/pci.c2
-rw-r--r--drivers/misc/cxl/sysfs.c10
-rw-r--r--drivers/misc/eeprom/at24.c35
-rw-r--r--drivers/misc/eeprom/at25.c34
-rw-r--r--drivers/misc/eeprom/eeprom_93cx6.c62
-rw-r--r--drivers/misc/eeprom/sunxi_sid.c1
-rw-r--r--drivers/misc/enclosure.c44
-rw-r--r--drivers/misc/fuse/Makefile1
-rw-r--r--drivers/misc/genwqe/card_dev.c2
-rw-r--r--drivers/misc/genwqe/card_utils.c2
-rw-r--r--drivers/misc/lis3lv02d/lis3lv02d_i2c.c4
-rw-r--r--drivers/misc/mei/amthif.c34
-rw-r--r--drivers/misc/mei/bus.c4
-rw-r--r--drivers/misc/mei/client.c2
-rw-r--r--drivers/misc/mei/debugfs.c8
-rw-r--r--drivers/misc/mei/hbm.c23
-rw-r--r--drivers/misc/mei/hbm.h4
-rw-r--r--drivers/misc/mei/hw-me-regs.h12
-rw-r--r--drivers/misc/mei/hw-me.c49
-rw-r--r--drivers/misc/mei/hw-me.h10
-rw-r--r--drivers/misc/mei/hw-txe.c7
-rw-r--r--drivers/misc/mei/init.c38
-rw-r--r--drivers/misc/mei/interrupt.c12
-rw-r--r--drivers/misc/mei/main.c43
-rw-r--r--drivers/misc/mei/mei_dev.h43
-rw-r--r--drivers/misc/mei/nfc.c52
-rw-r--r--drivers/misc/mei/pci-me.c20
-rw-r--r--drivers/misc/mei/pci-txe.c9
-rw-r--r--drivers/misc/mei/wd.c9
-rw-r--r--drivers/misc/mic/card/mic_virtio.c14
-rw-r--r--drivers/misc/mic/card/mic_x100.c1
-rw-r--r--drivers/misc/mic/host/mic_debugfs.c18
-rw-r--r--drivers/misc/pch_phub.c2
-rw-r--r--drivers/misc/ti-st/st_kim.c1
-rw-r--r--drivers/misc/vexpress-syscfg.c60
-rw-r--r--drivers/misc/vmw_vmci/vmci_queue_pair.c17
51 files changed, 794 insertions, 354 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index bbeb4516facf..006242c8bca0 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -75,7 +75,7 @@ config ATMEL_TCB_CLKSRC
config ATMEL_TCB_CLKSRC_BLOCK
int
depends on ATMEL_TCB_CLKSRC
- prompt "TC Block" if ARCH_AT91RM9200 || ARCH_AT91SAM9260 || CPU_AT32AP700X
+ prompt "TC Block" if CPU_AT32AP700X
default 0
range 0 1
help
diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c
index 868a30a1b417..3739ffa9cdf1 100644
--- a/drivers/misc/apds990x.c
+++ b/drivers/misc/apds990x.c
@@ -609,7 +609,7 @@ static int apds990x_detect(struct apds990x_chip *chip)
return ret;
}
-#if defined(CONFIG_PM) || defined(CONFIG_PM_RUNTIME)
+#ifdef CONFIG_PM
static int apds990x_chip_on(struct apds990x_chip *chip)
{
int err = regulator_bulk_enable(ARRAY_SIZE(chip->regs),
@@ -1237,7 +1237,7 @@ static int apds990x_resume(struct device *dev)
}
#endif
-#ifdef CONFIG_PM_RUNTIME
+#ifdef CONFIG_PM
static int apds990x_runtime_suspend(struct device *dev)
{
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
diff --git a/drivers/misc/arm-charlcd.c b/drivers/misc/arm-charlcd.c
index c72e96b523ed..c65b5ea5d5ef 100644
--- a/drivers/misc/arm-charlcd.c
+++ b/drivers/misc/arm-charlcd.c
@@ -375,7 +375,6 @@ static const struct of_device_id charlcd_match[] = {
static struct platform_driver charlcd_driver = {
.driver = {
.name = DRIVERNAME,
- .owner = THIS_MODULE,
.pm = &charlcd_pm_ops,
.of_match_table = of_match_ptr(charlcd_match),
},
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index 60843a275abd..e11a0bd6c66e 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -57,7 +57,7 @@ struct ssc_device *ssc_request(unsigned int ssc_num)
ssc->user++;
spin_unlock(&user_lock);
- clk_prepare_enable(ssc->clk);
+ clk_prepare(ssc->clk);
return ssc;
}
@@ -77,7 +77,7 @@ void ssc_free(struct ssc_device *ssc)
spin_unlock(&user_lock);
if (disable_clk)
- clk_disable_unprepare(ssc->clk);
+ clk_unprepare(ssc->clk);
}
EXPORT_SYMBOL(ssc_free);
@@ -220,7 +220,6 @@ static int ssc_remove(struct platform_device *pdev)
static struct platform_driver ssc_driver = {
.driver = {
.name = "ssc",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(atmel_ssc_dt_ids),
},
.id_table = atmel_ssc_devtypes,
diff --git a/drivers/misc/bh1770glc.c b/drivers/misc/bh1770glc.c
index 7b55f8a152d4..b756381b8250 100644
--- a/drivers/misc/bh1770glc.c
+++ b/drivers/misc/bh1770glc.c
@@ -1358,7 +1358,7 @@ static int bh1770_resume(struct device *dev)
}
#endif
-#ifdef CONFIG_PM_RUNTIME
+#ifdef CONFIG_PM
static int bh1770_runtime_suspend(struct device *dev)
{
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
diff --git a/drivers/misc/carma/Kconfig b/drivers/misc/carma/Kconfig
index c90370ed712b..295882bfb14e 100644
--- a/drivers/misc/carma/Kconfig
+++ b/drivers/misc/carma/Kconfig
@@ -1,7 +1,6 @@
config CARMA_FPGA
tristate "CARMA DATA-FPGA Access Driver"
- depends on FSL_SOC && PPC_83xx && MEDIA_SUPPORT && HAS_DMA && FSL_DMA
- select VIDEOBUF_DMA_SG
+ depends on FSL_SOC && PPC_83xx && HAS_DMA && FSL_DMA
default n
help
Say Y here to include support for communicating with the data
@@ -9,8 +8,7 @@ config CARMA_FPGA
config CARMA_FPGA_PROGRAM
tristate "CARMA DATA-FPGA Programmer"
- depends on FSL_SOC && PPC_83xx && MEDIA_SUPPORT && HAS_DMA && FSL_DMA
- select VIDEOBUF_DMA_SG
+ depends on FSL_SOC && PPC_83xx && HAS_DMA && FSL_DMA
default n
help
Say Y here to include support for programming the data processing
diff --git a/drivers/misc/carma/carma-fpga-program.c b/drivers/misc/carma/carma-fpga-program.c
index 339b252fcedd..06166ac000e0 100644
--- a/drivers/misc/carma/carma-fpga-program.c
+++ b/drivers/misc/carma/carma-fpga-program.c
@@ -19,6 +19,7 @@
#include <linux/fsldma.h>
#include <linux/interrupt.h>
#include <linux/highmem.h>
+#include <linux/vmalloc.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
@@ -30,8 +31,6 @@
#include <linux/fs.h>
#include <linux/io.h>
-#include <media/videobuf-dma-sg.h>
-
/* MPC8349EMDS specific get_immrbase() */
#include <sysdev/fsl_soc.h>
@@ -67,14 +66,79 @@ struct fpga_dev {
/* FPGA Bitfile */
struct mutex lock;
- struct videobuf_dmabuf vb;
- bool vb_allocated;
+ void *vaddr;
+ struct scatterlist *sglist;
+ int sglen;
+ int nr_pages;
+ bool buf_allocated;
/* max size and written bytes */
size_t fw_size;
size_t bytes;
};
+static int fpga_dma_init(struct fpga_dev *priv, int nr_pages)
+{
+ struct page *pg;
+ int i;
+
+ priv->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT);
+ if (NULL == priv->vaddr) {
+ pr_debug("vmalloc_32(%d pages) failed\n", nr_pages);
+ return -ENOMEM;
+ }
+
+ pr_debug("vmalloc is at addr 0x%08lx, size=%d\n",
+ (unsigned long)priv->vaddr,
+ nr_pages << PAGE_SHIFT);
+
+ memset(priv->vaddr, 0, nr_pages << PAGE_SHIFT);
+ priv->nr_pages = nr_pages;
+
+ priv->sglist = vzalloc(priv->nr_pages * sizeof(*priv->sglist));
+ if (NULL == priv->sglist)
+ goto vzalloc_err;
+
+ sg_init_table(priv->sglist, priv->nr_pages);
+ for (i = 0; i < priv->nr_pages; i++) {
+ pg = vmalloc_to_page(priv->vaddr + i * PAGE_SIZE);
+ if (NULL == pg)
+ goto vmalloc_to_page_err;
+ sg_set_page(&priv->sglist[i], pg, PAGE_SIZE, 0);
+ }
+ return 0;
+
+vmalloc_to_page_err:
+ vfree(priv->sglist);
+ priv->sglist = NULL;
+vzalloc_err:
+ vfree(priv->vaddr);
+ priv->vaddr = NULL;
+ return -ENOMEM;
+}
+
+static int fpga_dma_map(struct fpga_dev *priv)
+{
+ priv->sglen = dma_map_sg(priv->dev, priv->sglist,
+ priv->nr_pages, DMA_TO_DEVICE);
+
+ if (0 == priv->sglen) {
+ pr_warn("%s: dma_map_sg failed\n", __func__);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static int fpga_dma_unmap(struct fpga_dev *priv)
+{
+ if (!priv->sglen)
+ return 0;
+
+ dma_unmap_sg(priv->dev, priv->sglist, priv->sglen, DMA_TO_DEVICE);
+ priv->sglen = 0;
+ return 0;
+}
+
/*
* FPGA Bitfile Helpers
*/
@@ -87,8 +151,9 @@ struct fpga_dev {
*/
static void fpga_drop_firmware_data(struct fpga_dev *priv)
{
- videobuf_dma_free(&priv->vb);
- priv->vb_allocated = false;
+ vfree(priv->sglist);
+ vfree(priv->vaddr);
+ priv->buf_allocated = false;
priv->bytes = 0;
}
@@ -427,7 +492,7 @@ static noinline int fpga_program_cpu(struct fpga_dev *priv)
dev_dbg(priv->dev, "enabled the controller\n");
/* Write each chunk of the FPGA bitfile to FPGA programmer */
- ret = fpga_program_block(priv, priv->vb.vaddr, priv->bytes);
+ ret = fpga_program_block(priv, priv->vaddr, priv->bytes);
if (ret)
goto out_disable_controller;
@@ -463,7 +528,6 @@ out_disable_controller:
*/
static noinline int fpga_program_dma(struct fpga_dev *priv)
{
- struct videobuf_dmabuf *vb = &priv->vb;
struct dma_chan *chan = priv->chan;
struct dma_async_tx_descriptor *tx;
size_t num_pages, len, avail = 0;
@@ -505,7 +569,7 @@ static noinline int fpga_program_dma(struct fpga_dev *priv)
}
/* Map the buffer for DMA */
- ret = videobuf_dma_map(priv->dev, &priv->vb);
+ ret = fpga_dma_map(priv);
if (ret) {
dev_err(priv->dev, "Unable to map buffer for DMA\n");
goto out_free_table;
@@ -525,7 +589,7 @@ static noinline int fpga_program_dma(struct fpga_dev *priv)
goto out_dma_unmap;
}
- ret = fsl_dma_external_start(chan, 1)
+ ret = fsl_dma_external_start(chan, 1);
if (ret) {
dev_err(priv->dev, "DMA external control setup failed\n");
goto out_dma_unmap;
@@ -534,7 +598,7 @@ static noinline int fpga_program_dma(struct fpga_dev *priv)
/* setup and submit the DMA transaction */
tx = dmaengine_prep_dma_sg(chan, table.sgl, num_pages,
- vb->sglist, vb->sglen, 0);
+ priv->sglist, priv->sglen, 0);
if (!tx) {
dev_err(priv->dev, "Unable to prep DMA transaction\n");
ret = -ENOMEM;
@@ -572,7 +636,7 @@ static noinline int fpga_program_dma(struct fpga_dev *priv)
out_disable_controller:
fpga_programmer_disable(priv);
out_dma_unmap:
- videobuf_dma_unmap(priv->dev, vb);
+ fpga_dma_unmap(priv);
out_free_table:
sg_free_table(&table);
out_return:
@@ -702,12 +766,12 @@ static int fpga_open(struct inode *inode, struct file *filp)
priv->bytes = 0;
/* Check if we have already allocated a buffer */
- if (priv->vb_allocated)
+ if (priv->buf_allocated)
return 0;
/* Allocate a buffer to hold enough data for the bitfile */
nr_pages = DIV_ROUND_UP(priv->fw_size, PAGE_SIZE);
- ret = videobuf_dma_init_kernel(&priv->vb, DMA_TO_DEVICE, nr_pages);
+ ret = fpga_dma_init(priv, nr_pages);
if (ret) {
dev_err(priv->dev, "unable to allocate data buffer\n");
mutex_unlock(&priv->lock);
@@ -715,7 +779,7 @@ static int fpga_open(struct inode *inode, struct file *filp)
return ret;
}
- priv->vb_allocated = true;
+ priv->buf_allocated = true;
return 0;
}
@@ -738,7 +802,7 @@ static ssize_t fpga_write(struct file *filp, const char __user *buf,
return -ENOSPC;
count = min_t(size_t, priv->fw_size - priv->bytes, count);
- if (copy_from_user(priv->vb.vaddr + priv->bytes, buf, count))
+ if (copy_from_user(priv->vaddr + priv->bytes, buf, count))
return -EFAULT;
priv->bytes += count;
@@ -749,20 +813,19 @@ static ssize_t fpga_read(struct file *filp, char __user *buf, size_t count,
loff_t *f_pos)
{
struct fpga_dev *priv = filp->private_data;
- return simple_read_from_buffer(buf, count, ppos,
- priv->vb.vaddr, priv->bytes);
+ return simple_read_from_buffer(buf, count, f_pos,
+ priv->vaddr, priv->bytes);
}
static loff_t fpga_llseek(struct file *filp, loff_t offset, int origin)
{
struct fpga_dev *priv = filp->private_data;
- loff_t newpos;
/* only read-only opens are allowed to seek */
if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
return -EINVAL;
- return fixed_size_llseek(file, offset, origin, priv->fw_size);
+ return fixed_size_llseek(filp, offset, origin, priv->fw_size);
}
static const struct file_operations fpga_fops = {
@@ -953,7 +1016,6 @@ static int fpga_of_probe(struct platform_device *op)
priv->dev = &op->dev;
mutex_init(&priv->lock);
init_completion(&priv->completion);
- videobuf_dma_init(&priv->vb);
dev_set_drvdata(priv->dev, priv);
dma_cap_zero(mask);
@@ -1091,7 +1153,6 @@ static struct platform_driver fpga_of_driver = {
.driver = {
.name = drv_name,
.of_match_table = fpga_of_match,
- .owner = THIS_MODULE,
},
};
diff --git a/drivers/misc/carma/carma-fpga.c b/drivers/misc/carma/carma-fpga.c
index 55e913b7eb11..68cdfe151bdb 100644
--- a/drivers/misc/carma/carma-fpga.c
+++ b/drivers/misc/carma/carma-fpga.c
@@ -98,6 +98,7 @@
#include <linux/seq_file.h>
#include <linux/highmem.h>
#include <linux/debugfs.h>
+#include <linux/vmalloc.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/poll.h>
@@ -105,8 +106,6 @@
#include <linux/kref.h>
#include <linux/io.h>
-#include <media/videobuf-dma-sg.h>
-
/* system controller registers */
#define SYS_IRQ_SOURCE_CTL 0x24
#define SYS_IRQ_OUTPUT_EN 0x28
@@ -142,7 +141,10 @@ struct fpga_info {
struct data_buf {
struct list_head entry;
- struct videobuf_dmabuf vb;
+ void *vaddr;
+ struct scatterlist *sglist;
+ int sglen;
+ int nr_pages;
size_t size;
};
@@ -207,6 +209,68 @@ static void fpga_device_release(struct kref *ref)
* Data Buffer Allocation Helpers
*/
+static int carma_dma_init(struct data_buf *buf, int nr_pages)
+{
+ struct page *pg;
+ int i;
+
+ buf->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT);
+ if (NULL == buf->vaddr) {
+ pr_debug("vmalloc_32(%d pages) failed\n", nr_pages);
+ return -ENOMEM;
+ }
+
+ pr_debug("vmalloc is at addr 0x%08lx, size=%d\n",
+ (unsigned long)buf->vaddr,
+ nr_pages << PAGE_SHIFT);
+
+ memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT);
+ buf->nr_pages = nr_pages;
+
+ buf->sglist = vzalloc(buf->nr_pages * sizeof(*buf->sglist));
+ if (NULL == buf->sglist)
+ goto vzalloc_err;
+
+ sg_init_table(buf->sglist, buf->nr_pages);
+ for (i = 0; i < buf->nr_pages; i++) {
+ pg = vmalloc_to_page(buf->vaddr + i * PAGE_SIZE);
+ if (NULL == pg)
+ goto vmalloc_to_page_err;
+ sg_set_page(&buf->sglist[i], pg, PAGE_SIZE, 0);
+ }
+ return 0;
+
+vmalloc_to_page_err:
+ vfree(buf->sglist);
+ buf->sglist = NULL;
+vzalloc_err:
+ vfree(buf->vaddr);
+ buf->vaddr = NULL;
+ return -ENOMEM;
+}
+
+static int carma_dma_map(struct device *dev, struct data_buf *buf)
+{
+ buf->sglen = dma_map_sg(dev, buf->sglist,
+ buf->nr_pages, DMA_FROM_DEVICE);
+
+ if (0 == buf->sglen) {
+ pr_warn("%s: dma_map_sg failed\n", __func__);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static int carma_dma_unmap(struct device *dev, struct data_buf *buf)
+{
+ if (!buf->sglen)
+ return 0;
+
+ dma_unmap_sg(dev, buf->sglist, buf->sglen, DMA_FROM_DEVICE);
+ buf->sglen = 0;
+ return 0;
+}
+
/**
* data_free_buffer() - free a single data buffer and all allocated memory
* @buf: the buffer to free
@@ -221,7 +285,8 @@ static void data_free_buffer(struct data_buf *buf)
return;
/* free all memory */
- videobuf_dma_free(&buf->vb);
+ vfree(buf->sglist);
+ vfree(buf->vaddr);
kfree(buf);
}
@@ -230,7 +295,7 @@ static void data_free_buffer(struct data_buf *buf)
* @bytes: the number of bytes required
*
* This allocates all space needed for a data buffer. It must be mapped before
- * use in a DMA transaction using videobuf_dma_map().
+ * use in a DMA transaction using carma_dma_map().
*
* Returns NULL on failure
*/
@@ -252,9 +317,8 @@ static struct data_buf *data_alloc_buffer(const size_t bytes)
INIT_LIST_HEAD(&buf->entry);
buf->size = bytes;
- /* allocate the videobuf */
- videobuf_dma_init(&buf->vb);
- ret = videobuf_dma_init_kernel(&buf->vb, DMA_FROM_DEVICE, nr_pages);
+ /* allocate the buffer */
+ ret = carma_dma_init(buf, nr_pages);
if (ret)
goto out_free_buf;
@@ -285,13 +349,13 @@ static void data_free_buffers(struct fpga_device *priv)
list_for_each_entry_safe(buf, tmp, &priv->free, entry) {
list_del_init(&buf->entry);
- videobuf_dma_unmap(priv->dev, &buf->vb);
+ carma_dma_unmap(priv->dev, buf);
data_free_buffer(buf);
}
list_for_each_entry_safe(buf, tmp, &priv->used, entry) {
list_del_init(&buf->entry);
- videobuf_dma_unmap(priv->dev, &buf->vb);
+ carma_dma_unmap(priv->dev, buf);
data_free_buffer(buf);
}
@@ -330,7 +394,7 @@ static int data_alloc_buffers(struct fpga_device *priv)
break;
/* map it for DMA */
- ret = videobuf_dma_map(priv->dev, &buf->vb);
+ ret = carma_dma_map(priv->dev, buf);
if (ret) {
data_free_buffer(buf);
break;
@@ -634,8 +698,8 @@ static int data_submit_dma(struct fpga_device *priv, struct data_buf *buf)
dma_addr_t dst, src;
unsigned long dma_flags = 0;
- dst_sg = buf->vb.sglist;
- dst_nents = buf->vb.sglen;
+ dst_sg = buf->sglist;
+ dst_nents = buf->sglen;
src_sg = priv->corl_table.sgl;
src_nents = priv->corl_nents;
@@ -1134,7 +1198,7 @@ static ssize_t data_read(struct file *filp, char __user *ubuf, size_t count,
spin_unlock_irq(&priv->lock);
/* Buffers are always mapped: unmap it */
- videobuf_dma_unmap(priv->dev, &dbuf->vb);
+ carma_dma_unmap(priv->dev, dbuf);
/* save the buffer for later */
reader->buf = dbuf;
@@ -1143,7 +1207,7 @@ static ssize_t data_read(struct file *filp, char __user *ubuf, size_t count,
have_buffer:
/* Get the number of bytes available */
avail = dbuf->size - reader->buf_start;
- data = dbuf->vb.vaddr + reader->buf_start;
+ data = dbuf->vaddr + reader->buf_start;
/* Get the number of bytes we can transfer */
count = min(count, avail);
@@ -1171,7 +1235,7 @@ have_buffer:
* If it fails, we pretend that the read never happed and return
* -EFAULT to userspace. The read will be retried.
*/
- ret = videobuf_dma_map(priv->dev, &dbuf->vb);
+ ret = carma_dma_map(priv->dev, dbuf);
if (ret) {
dev_err(priv->dev, "unable to remap buffer for DMA\n");
return -EFAULT;
@@ -1203,7 +1267,7 @@ out_unlock:
spin_unlock_irq(&priv->lock);
if (drop_buffer) {
- videobuf_dma_unmap(priv->dev, &dbuf->vb);
+ carma_dma_unmap(priv->dev, dbuf);
data_free_buffer(dbuf);
}
@@ -1433,7 +1497,6 @@ static struct platform_driver data_of_driver = {
.driver = {
.name = drv_name,
.of_match_table = data_of_match,
- .owner = THIS_MODULE,
},
};
diff --git a/drivers/misc/cs5535-mfgpt.c b/drivers/misc/cs5535-mfgpt.c
index effd8c6b2b94..347f08f2fd48 100644
--- a/drivers/misc/cs5535-mfgpt.c
+++ b/drivers/misc/cs5535-mfgpt.c
@@ -365,7 +365,6 @@ done:
static struct platform_driver cs5535_mfgpt_driver = {
.driver = {
.name = DRV_NAME,
- .owner = THIS_MODULE,
},
.probe = cs5535_mfgpt_probe,
};
diff --git a/drivers/misc/cxl/context.c b/drivers/misc/cxl/context.c
index cca472109135..51fd6b524371 100644
--- a/drivers/misc/cxl/context.c
+++ b/drivers/misc/cxl/context.c
@@ -34,7 +34,8 @@ struct cxl_context *cxl_context_alloc(void)
/*
* Initialises a CXL context.
*/
-int cxl_context_init(struct cxl_context *ctx, struct cxl_afu *afu, bool master)
+int cxl_context_init(struct cxl_context *ctx, struct cxl_afu *afu, bool master,
+ struct address_space *mapping)
{
int i;
@@ -42,6 +43,8 @@ int cxl_context_init(struct cxl_context *ctx, struct cxl_afu *afu, bool master)
ctx->afu = afu;
ctx->master = master;
ctx->pid = NULL; /* Set in start work ioctl */
+ mutex_init(&ctx->mapping_lock);
+ ctx->mapping = mapping;
/*
* Allocate the segment table before we put it in the IDR so that we
@@ -82,12 +85,12 @@ int cxl_context_init(struct cxl_context *ctx, struct cxl_afu *afu, bool master)
* Allocating IDR! We better make sure everything's setup that
* dereferences from it.
*/
+ mutex_lock(&afu->contexts_lock);
idr_preload(GFP_KERNEL);
- spin_lock(&afu->contexts_lock);
i = idr_alloc(&ctx->afu->contexts_idr, ctx, 0,
ctx->afu->num_procs, GFP_NOWAIT);
- spin_unlock(&afu->contexts_lock);
idr_preload_end();
+ mutex_unlock(&afu->contexts_lock);
if (i < 0)
return i;
@@ -147,6 +150,12 @@ static void __detach_context(struct cxl_context *ctx)
afu_release_irqs(ctx);
flush_work(&ctx->fault_work); /* Only needed for dedicated process */
wake_up_all(&ctx->wq);
+
+ /* Release Problem State Area mapping */
+ mutex_lock(&ctx->mapping_lock);
+ if (ctx->mapping)
+ unmap_mapping_range(ctx->mapping, 0, 0, 1);
+ mutex_unlock(&ctx->mapping_lock);
}
/*
@@ -168,21 +177,22 @@ void cxl_context_detach_all(struct cxl_afu *afu)
struct cxl_context *ctx;
int tmp;
- rcu_read_lock();
- idr_for_each_entry(&afu->contexts_idr, ctx, tmp)
+ mutex_lock(&afu->contexts_lock);
+ idr_for_each_entry(&afu->contexts_idr, ctx, tmp) {
/*
* Anything done in here needs to be setup before the IDR is
* created and torn down after the IDR removed
*/
__detach_context(ctx);
- rcu_read_unlock();
+ }
+ mutex_unlock(&afu->contexts_lock);
}
void cxl_context_free(struct cxl_context *ctx)
{
- spin_lock(&ctx->afu->contexts_lock);
+ mutex_lock(&ctx->afu->contexts_lock);
idr_remove(&ctx->afu->contexts_idr, ctx->pe);
- spin_unlock(&ctx->afu->contexts_lock);
+ mutex_unlock(&ctx->afu->contexts_lock);
synchronize_rcu();
free_page((u64)ctx->sstp);
diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h
index 3d2b8677ec8a..28078f8894a5 100644
--- a/drivers/misc/cxl/cxl.h
+++ b/drivers/misc/cxl/cxl.h
@@ -336,6 +336,8 @@ struct cxl_sste {
struct cxl_afu {
irq_hw_number_t psl_hwirq;
irq_hw_number_t serr_hwirq;
+ char *err_irq_name;
+ char *psl_irq_name;
unsigned int serr_virq;
void __iomem *p1n_mmio;
void __iomem *p2n_mmio;
@@ -349,7 +351,7 @@ struct cxl_afu {
struct device *chardev_s, *chardev_m, *chardev_d;
struct idr contexts_idr;
struct dentry *debugfs;
- spinlock_t contexts_lock;
+ struct mutex contexts_lock;
struct mutex spa_mutex;
spinlock_t afu_cntl_lock;
@@ -379,6 +381,12 @@ struct cxl_afu {
bool enabled;
};
+
+struct cxl_irq_name {
+ struct list_head list;
+ char *name;
+};
+
/*
* This is a cxl context. If the PSL is in dedicated mode, there will be one
* of these per AFU. If in AFU directed there can be lots of these.
@@ -390,6 +398,10 @@ struct cxl_context {
phys_addr_t psn_phys;
u64 psn_size;
+ /* Used to unmap any mmaps when force detaching */
+ struct address_space *mapping;
+ struct mutex mapping_lock;
+
spinlock_t sste_lock; /* Protects segment table entries */
struct cxl_sste *sstp;
u64 sstp0, sstp1;
@@ -403,6 +415,7 @@ struct cxl_context {
unsigned long *irq_bitmap; /* Accessed from IRQ context */
struct cxl_irq_ranges irqs;
+ struct list_head irq_names;
u64 fault_addr;
u64 fault_dsisr;
u64 afu_err;
@@ -444,6 +457,7 @@ struct cxl {
struct dentry *trace;
struct dentry *psl_err_chk;
struct dentry *debugfs;
+ char *irq_name;
struct bin_attribute cxl_attr;
int adapter_num;
int user_irqs;
@@ -563,9 +577,6 @@ int _cxl_afu_deactivate_mode(struct cxl_afu *afu, int mode);
int cxl_afu_deactivate_mode(struct cxl_afu *afu);
int cxl_afu_select_best_mode(struct cxl_afu *afu);
-unsigned int cxl_map_irq(struct cxl *adapter, irq_hw_number_t hwirq,
- irq_handler_t handler, void *cookie);
-void cxl_unmap_irq(unsigned int virq, void *cookie);
int cxl_register_psl_irq(struct cxl_afu *afu);
void cxl_release_psl_irq(struct cxl_afu *afu);
int cxl_register_psl_err_irq(struct cxl *adapter);
@@ -592,7 +603,8 @@ int cxl_alloc_sst(struct cxl_context *ctx);
void init_cxl_native(void);
struct cxl_context *cxl_context_alloc(void);
-int cxl_context_init(struct cxl_context *ctx, struct cxl_afu *afu, bool master);
+int cxl_context_init(struct cxl_context *ctx, struct cxl_afu *afu, bool master,
+ struct address_space *mapping);
void cxl_context_free(struct cxl_context *ctx);
int cxl_context_iomap(struct cxl_context *ctx, struct vm_area_struct *vma);
@@ -612,7 +624,7 @@ int cxl_attach_process(struct cxl_context *ctx, bool kernel, u64 wed,
u64 amr);
int cxl_detach_process(struct cxl_context *ctx);
-int cxl_get_irq(struct cxl_context *ctx, struct cxl_irq_info *info);
+int cxl_get_irq(struct cxl_afu *afu, struct cxl_irq_info *info);
int cxl_ack_irq(struct cxl_context *ctx, u64 tfc, u64 psl_reset_mask);
int cxl_check_error(struct cxl_afu *afu);
diff --git a/drivers/misc/cxl/fault.c b/drivers/misc/cxl/fault.c
index c99e896604ee..f8684bca2d79 100644
--- a/drivers/misc/cxl/fault.c
+++ b/drivers/misc/cxl/fault.c
@@ -133,7 +133,7 @@ static void cxl_handle_page_fault(struct cxl_context *ctx,
{
unsigned flt = 0;
int result;
- unsigned long access, flags;
+ unsigned long access, flags, inv_flags = 0;
if ((result = copro_handle_mm_fault(mm, dar, dsisr, &flt))) {
pr_devel("copro_handle_mm_fault failed: %#x\n", result);
@@ -149,8 +149,12 @@ static void cxl_handle_page_fault(struct cxl_context *ctx,
access |= _PAGE_RW;
if ((!ctx->kernel) || ~(dar & (1ULL << 63)))
access |= _PAGE_USER;
+
+ if (dsisr & DSISR_NOHPTE)
+ inv_flags |= HPTE_NOHPTE_UPDATE;
+
local_irq_save(flags);
- hash_page_mm(mm, dar, access, 0x300);
+ hash_page_mm(mm, dar, access, 0x300, inv_flags);
local_irq_restore(flags);
pr_devel("Page fault successfully handled for pe: %i!\n", ctx->pe);
diff --git a/drivers/misc/cxl/file.c b/drivers/misc/cxl/file.c
index 378b099e7c0b..e9f2f10dbb37 100644
--- a/drivers/misc/cxl/file.c
+++ b/drivers/misc/cxl/file.c
@@ -77,7 +77,7 @@ static int __afu_open(struct inode *inode, struct file *file, bool master)
goto err_put_afu;
}
- if ((rc = cxl_context_init(ctx, afu, master)))
+ if ((rc = cxl_context_init(ctx, afu, master, inode->i_mapping)))
goto err_put_afu;
pr_devel("afu_open pe: %i\n", ctx->pe);
@@ -113,6 +113,10 @@ static int afu_release(struct inode *inode, struct file *file)
__func__, ctx->pe);
cxl_context_detach(ctx);
+ mutex_lock(&ctx->mapping_lock);
+ ctx->mapping = NULL;
+ mutex_unlock(&ctx->mapping_lock);
+
put_device(&ctx->afu->dev);
/*
diff --git a/drivers/misc/cxl/irq.c b/drivers/misc/cxl/irq.c
index 336020c8e1af..c294925f73ee 100644
--- a/drivers/misc/cxl/irq.c
+++ b/drivers/misc/cxl/irq.c
@@ -92,20 +92,13 @@ static irqreturn_t schedule_cxl_fault(struct cxl_context *ctx, u64 dsisr, u64 da
return IRQ_HANDLED;
}
-static irqreturn_t cxl_irq(int irq, void *data)
+static irqreturn_t cxl_irq(int irq, void *data, struct cxl_irq_info *irq_info)
{
struct cxl_context *ctx = data;
- struct cxl_irq_info irq_info;
u64 dsisr, dar;
- int result;
-
- if ((result = cxl_get_irq(ctx, &irq_info))) {
- WARN(1, "Unable to get CXL IRQ Info: %i\n", result);
- return IRQ_HANDLED;
- }
- dsisr = irq_info.dsisr;
- dar = irq_info.dar;
+ dsisr = irq_info->dsisr;
+ dar = irq_info->dar;
pr_devel("CXL interrupt %i for afu pe: %i DSISR: %#llx DAR: %#llx\n", irq, ctx->pe, dsisr, dar);
@@ -149,9 +142,9 @@ static irqreturn_t cxl_irq(int irq, void *data)
if (dsisr & CXL_PSL_DSISR_An_UR)
pr_devel("CXL interrupt: AURP PTE not found\n");
if (dsisr & CXL_PSL_DSISR_An_PE)
- return handle_psl_slice_error(ctx, dsisr, irq_info.errstat);
+ return handle_psl_slice_error(ctx, dsisr, irq_info->errstat);
if (dsisr & CXL_PSL_DSISR_An_AE) {
- pr_devel("CXL interrupt: AFU Error %.llx\n", irq_info.afu_err);
+ pr_devel("CXL interrupt: AFU Error %.llx\n", irq_info->afu_err);
if (ctx->pending_afu_err) {
/*
@@ -163,10 +156,10 @@ static irqreturn_t cxl_irq(int irq, void *data)
*/
dev_err_ratelimited(&ctx->afu->dev, "CXL AFU Error "
"undelivered to pe %i: %.llx\n",
- ctx->pe, irq_info.afu_err);
+ ctx->pe, irq_info->afu_err);
} else {
spin_lock(&ctx->lock);
- ctx->afu_err = irq_info.afu_err;
+ ctx->afu_err = irq_info->afu_err;
ctx->pending_afu_err = 1;
spin_unlock(&ctx->lock);
@@ -182,24 +175,43 @@ static irqreturn_t cxl_irq(int irq, void *data)
return IRQ_HANDLED;
}
+static irqreturn_t fail_psl_irq(struct cxl_afu *afu, struct cxl_irq_info *irq_info)
+{
+ if (irq_info->dsisr & CXL_PSL_DSISR_TRANS)
+ cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_AE);
+ else
+ cxl_p2n_write(afu, CXL_PSL_TFC_An, CXL_PSL_TFC_An_A);
+
+ return IRQ_HANDLED;
+}
+
static irqreturn_t cxl_irq_multiplexed(int irq, void *data)
{
struct cxl_afu *afu = data;
struct cxl_context *ctx;
+ struct cxl_irq_info irq_info;
int ph = cxl_p2n_read(afu, CXL_PSL_PEHandle_An) & 0xffff;
int ret;
+ if ((ret = cxl_get_irq(afu, &irq_info))) {
+ WARN(1, "Unable to get CXL IRQ Info: %i\n", ret);
+ return fail_psl_irq(afu, &irq_info);
+ }
+
rcu_read_lock();
ctx = idr_find(&afu->contexts_idr, ph);
if (ctx) {
- ret = cxl_irq(irq, ctx);
+ ret = cxl_irq(irq, ctx, &irq_info);
rcu_read_unlock();
return ret;
}
rcu_read_unlock();
- WARN(1, "Unable to demultiplex CXL PSL IRQ\n");
- return IRQ_HANDLED;
+ WARN(1, "Unable to demultiplex CXL PSL IRQ for PE %i DSISR %.16llx DAR"
+ " %.16llx\n(Possible AFU HW issue - was a term/remove acked"
+ " with outstanding transactions?)\n", ph, irq_info.dsisr,
+ irq_info.dar);
+ return fail_psl_irq(afu, &irq_info);
}
static irqreturn_t cxl_irq_afu(int irq, void *data)
@@ -243,7 +255,7 @@ static irqreturn_t cxl_irq_afu(int irq, void *data)
}
unsigned int cxl_map_irq(struct cxl *adapter, irq_hw_number_t hwirq,
- irq_handler_t handler, void *cookie)
+ irq_handler_t handler, void *cookie, const char *name)
{
unsigned int virq;
int result;
@@ -259,7 +271,7 @@ unsigned int cxl_map_irq(struct cxl *adapter, irq_hw_number_t hwirq,
pr_devel("hwirq %#lx mapped to virq %u\n", hwirq, virq);
- result = request_irq(virq, handler, 0, "cxl", cookie);
+ result = request_irq(virq, handler, 0, name, cookie);
if (result) {
dev_warn(&adapter->dev, "cxl_map_irq: request_irq failed: %i\n", result);
return 0;
@@ -278,14 +290,15 @@ static int cxl_register_one_irq(struct cxl *adapter,
irq_handler_t handler,
void *cookie,
irq_hw_number_t *dest_hwirq,
- unsigned int *dest_virq)
+ unsigned int *dest_virq,
+ const char *name)
{
int hwirq, virq;
if ((hwirq = cxl_alloc_one_irq(adapter)) < 0)
return hwirq;
- if (!(virq = cxl_map_irq(adapter, hwirq, handler, cookie)))
+ if (!(virq = cxl_map_irq(adapter, hwirq, handler, cookie, name)))
goto err;
*dest_hwirq = hwirq;
@@ -302,10 +315,19 @@ int cxl_register_psl_err_irq(struct cxl *adapter)
{
int rc;
+ adapter->irq_name = kasprintf(GFP_KERNEL, "cxl-%s-err",
+ dev_name(&adapter->dev));
+ if (!adapter->irq_name)
+ return -ENOMEM;
+
if ((rc = cxl_register_one_irq(adapter, cxl_irq_err, adapter,
&adapter->err_hwirq,
- &adapter->err_virq)))
+ &adapter->err_virq,
+ adapter->irq_name))) {
+ kfree(adapter->irq_name);
+ adapter->irq_name = NULL;
return rc;
+ }
cxl_p1_write(adapter, CXL_PSL_ErrIVTE, adapter->err_hwirq & 0xffff);
@@ -317,6 +339,7 @@ void cxl_release_psl_err_irq(struct cxl *adapter)
cxl_p1_write(adapter, CXL_PSL_ErrIVTE, 0x0000000000000000);
cxl_unmap_irq(adapter->err_virq, adapter);
cxl_release_one_irq(adapter, adapter->err_hwirq);
+ kfree(adapter->irq_name);
}
int cxl_register_serr_irq(struct cxl_afu *afu)
@@ -324,10 +347,18 @@ int cxl_register_serr_irq(struct cxl_afu *afu)
u64 serr;
int rc;
+ afu->err_irq_name = kasprintf(GFP_KERNEL, "cxl-%s-err",
+ dev_name(&afu->dev));
+ if (!afu->err_irq_name)
+ return -ENOMEM;
+
if ((rc = cxl_register_one_irq(afu->adapter, cxl_slice_irq_err, afu,
&afu->serr_hwirq,
- &afu->serr_virq)))
+ &afu->serr_virq, afu->err_irq_name))) {
+ kfree(afu->err_irq_name);
+ afu->err_irq_name = NULL;
return rc;
+ }
serr = cxl_p1n_read(afu, CXL_PSL_SERR_An);
serr = (serr & 0x00ffffffffff0000ULL) | (afu->serr_hwirq & 0xffff);
@@ -341,24 +372,50 @@ void cxl_release_serr_irq(struct cxl_afu *afu)
cxl_p1n_write(afu, CXL_PSL_SERR_An, 0x0000000000000000);
cxl_unmap_irq(afu->serr_virq, afu);
cxl_release_one_irq(afu->adapter, afu->serr_hwirq);
+ kfree(afu->err_irq_name);
}
int cxl_register_psl_irq(struct cxl_afu *afu)
{
- return cxl_register_one_irq(afu->adapter, cxl_irq_multiplexed, afu,
- &afu->psl_hwirq, &afu->psl_virq);
+ int rc;
+
+ afu->psl_irq_name = kasprintf(GFP_KERNEL, "cxl-%s",
+ dev_name(&afu->dev));
+ if (!afu->psl_irq_name)
+ return -ENOMEM;
+
+ if ((rc = cxl_register_one_irq(afu->adapter, cxl_irq_multiplexed, afu,
+ &afu->psl_hwirq, &afu->psl_virq,
+ afu->psl_irq_name))) {
+ kfree(afu->psl_irq_name);
+ afu->psl_irq_name = NULL;
+ }
+ return rc;
}
void cxl_release_psl_irq(struct cxl_afu *afu)
{
cxl_unmap_irq(afu->psl_virq, afu);
cxl_release_one_irq(afu->adapter, afu->psl_hwirq);
+ kfree(afu->psl_irq_name);
+}
+
+void afu_irq_name_free(struct cxl_context *ctx)
+{
+ struct cxl_irq_name *irq_name, *tmp;
+
+ list_for_each_entry_safe(irq_name, tmp, &ctx->irq_names, list) {
+ kfree(irq_name->name);
+ list_del(&irq_name->list);
+ kfree(irq_name);
+ }
}
int afu_register_irqs(struct cxl_context *ctx, u32 count)
{
irq_hw_number_t hwirq;
- int rc, r, i;
+ int rc, r, i, j = 1;
+ struct cxl_irq_name *irq_name;
if ((rc = cxl_alloc_irq_ranges(&ctx->irqs, ctx->afu->adapter, count)))
return rc;
@@ -372,15 +429,47 @@ int afu_register_irqs(struct cxl_context *ctx, u32 count)
sizeof(*ctx->irq_bitmap), GFP_KERNEL);
if (!ctx->irq_bitmap)
return -ENOMEM;
+
+ /*
+ * Allocate names first. If any fail, bail out before allocating
+ * actual hardware IRQs.
+ */
+ INIT_LIST_HEAD(&ctx->irq_names);
+ for (r = 1; r < CXL_IRQ_RANGES; r++) {
+ for (i = 0; i < ctx->irqs.range[r]; hwirq++, i++) {
+ irq_name = kmalloc(sizeof(struct cxl_irq_name),
+ GFP_KERNEL);
+ if (!irq_name)
+ goto out;
+ irq_name->name = kasprintf(GFP_KERNEL, "cxl-%s-pe%i-%i",
+ dev_name(&ctx->afu->dev),
+ ctx->pe, j);
+ if (!irq_name->name) {
+ kfree(irq_name);
+ goto out;
+ }
+ /* Add to tail so next look get the correct order */
+ list_add_tail(&irq_name->list, &ctx->irq_names);
+ j++;
+ }
+ }
+
+ /* We've allocated all memory now, so let's do the irq allocations */
+ irq_name = list_first_entry(&ctx->irq_names, struct cxl_irq_name, list);
for (r = 1; r < CXL_IRQ_RANGES; r++) {
hwirq = ctx->irqs.offset[r];
for (i = 0; i < ctx->irqs.range[r]; hwirq++, i++) {
cxl_map_irq(ctx->afu->adapter, hwirq,
- cxl_irq_afu, ctx);
+ cxl_irq_afu, ctx, irq_name->name);
+ irq_name = list_next_entry(irq_name, list);
}
}
return 0;
+
+out:
+ afu_irq_name_free(ctx);
+ return -ENOMEM;
}
void afu_release_irqs(struct cxl_context *ctx)
@@ -398,5 +487,6 @@ void afu_release_irqs(struct cxl_context *ctx)
}
}
+ afu_irq_name_free(ctx);
cxl_release_irq_ranges(&ctx->irqs, ctx->afu->adapter);
}
diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c
index d47532e8f4f1..f2b37b41a0da 100644
--- a/drivers/misc/cxl/native.c
+++ b/drivers/misc/cxl/native.c
@@ -277,6 +277,7 @@ static int do_process_element_cmd(struct cxl_context *ctx,
u64 cmd, u64 pe_state)
{
u64 state;
+ unsigned long timeout = jiffies + (HZ * CXL_TIMEOUT);
WARN_ON(!ctx->afu->enabled);
@@ -286,6 +287,10 @@ static int do_process_element_cmd(struct cxl_context *ctx,
smp_mb();
cxl_p1n_write(ctx->afu, CXL_PSL_LLCMD_An, cmd | ctx->pe);
while (1) {
+ if (time_after_eq(jiffies, timeout)) {
+ dev_warn(&ctx->afu->dev, "WARNING: Process Element Command timed out!\n");
+ return -EBUSY;
+ }
state = be64_to_cpup(ctx->afu->sw_command_status);
if (state == ~0ULL) {
pr_err("cxl: Error adding process element to AFU\n");
@@ -610,13 +615,6 @@ static inline int detach_process_native_dedicated(struct cxl_context *ctx)
return 0;
}
-/*
- * TODO: handle case when this is called inside a rcu_read_lock() which may
- * happen when we unbind the driver (ie. cxl_context_detach_all()) . Terminate
- * & remove use a mutex lock and schedule which will not good with lock held.
- * May need to write do_process_element_cmd() that handles outstanding page
- * faults synchronously.
- */
static inline int detach_process_native_afu_directed(struct cxl_context *ctx)
{
if (!ctx->pe_inserted)
@@ -637,18 +635,18 @@ int cxl_detach_process(struct cxl_context *ctx)
return detach_process_native_afu_directed(ctx);
}
-int cxl_get_irq(struct cxl_context *ctx, struct cxl_irq_info *info)
+int cxl_get_irq(struct cxl_afu *afu, struct cxl_irq_info *info)
{
u64 pidtid;
- info->dsisr = cxl_p2n_read(ctx->afu, CXL_PSL_DSISR_An);
- info->dar = cxl_p2n_read(ctx->afu, CXL_PSL_DAR_An);
- info->dsr = cxl_p2n_read(ctx->afu, CXL_PSL_DSR_An);
- pidtid = cxl_p2n_read(ctx->afu, CXL_PSL_PID_TID_An);
+ info->dsisr = cxl_p2n_read(afu, CXL_PSL_DSISR_An);
+ info->dar = cxl_p2n_read(afu, CXL_PSL_DAR_An);
+ info->dsr = cxl_p2n_read(afu, CXL_PSL_DSR_An);
+ pidtid = cxl_p2n_read(afu, CXL_PSL_PID_TID_An);
info->pid = pidtid >> 32;
info->tid = pidtid & 0xffffffff;
- info->afu_err = cxl_p2n_read(ctx->afu, CXL_AFU_ERR_An);
- info->errstat = cxl_p2n_read(ctx->afu, CXL_PSL_ErrStat_An);
+ info->afu_err = cxl_p2n_read(afu, CXL_AFU_ERR_An);
+ info->errstat = cxl_p2n_read(afu, CXL_PSL_ErrStat_An);
return 0;
}
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c
index 10c98ab7f46e..0f2cc9f8b4db 100644
--- a/drivers/misc/cxl/pci.c
+++ b/drivers/misc/cxl/pci.c
@@ -502,7 +502,7 @@ static struct cxl_afu *cxl_alloc_afu(struct cxl *adapter, int slice)
afu->dev.release = cxl_release_afu;
afu->slice = slice;
idr_init(&afu->contexts_idr);
- spin_lock_init(&afu->contexts_lock);
+ mutex_init(&afu->contexts_lock);
spin_lock_init(&afu->afu_cntl_lock);
mutex_init(&afu->spa_mutex);
diff --git a/drivers/misc/cxl/sysfs.c b/drivers/misc/cxl/sysfs.c
index ce7ec06d87d1..461bdbd5d483 100644
--- a/drivers/misc/cxl/sysfs.c
+++ b/drivers/misc/cxl/sysfs.c
@@ -121,7 +121,7 @@ static ssize_t reset_store_afu(struct device *device,
int rc;
/* Not safe to reset if it is currently in use */
- spin_lock(&afu->contexts_lock);
+ mutex_lock(&afu->contexts_lock);
if (!idr_is_empty(&afu->contexts_idr)) {
rc = -EBUSY;
goto err;
@@ -132,7 +132,7 @@ static ssize_t reset_store_afu(struct device *device,
rc = count;
err:
- spin_unlock(&afu->contexts_lock);
+ mutex_unlock(&afu->contexts_lock);
return rc;
}
@@ -247,7 +247,7 @@ static ssize_t mode_store(struct device *device, struct device_attribute *attr,
int rc = -EBUSY;
/* can't change this if we have a user */
- spin_lock(&afu->contexts_lock);
+ mutex_lock(&afu->contexts_lock);
if (!idr_is_empty(&afu->contexts_idr))
goto err;
@@ -271,7 +271,7 @@ static ssize_t mode_store(struct device *device, struct device_attribute *attr,
afu->current_mode = 0;
afu->num_procs = 0;
- spin_unlock(&afu->contexts_lock);
+ mutex_unlock(&afu->contexts_lock);
if ((rc = _cxl_afu_deactivate_mode(afu, old_mode)))
return rc;
@@ -280,7 +280,7 @@ static ssize_t mode_store(struct device *device, struct device_attribute *attr,
return count;
err:
- spin_unlock(&afu->contexts_lock);
+ mutex_unlock(&afu->contexts_lock);
return rc;
}
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index d87f77f790d6..2d3db81be099 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -56,6 +56,7 @@ struct at24_data {
struct at24_platform_data chip;
struct memory_accessor macc;
int use_smbus;
+ int use_smbus_write;
/*
* Lock protects against activities from other Linux tasks,
@@ -324,7 +325,7 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf,
{
struct i2c_client *client;
struct i2c_msg msg;
- ssize_t status;
+ ssize_t status = 0;
unsigned long timeout, write_time;
unsigned next_page;
@@ -365,9 +366,18 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf,
timeout = jiffies + msecs_to_jiffies(write_timeout);
do {
write_time = jiffies;
- if (at24->use_smbus) {
- status = i2c_smbus_write_i2c_block_data(client,
- offset, count, buf);
+ if (at24->use_smbus_write) {
+ switch (at24->use_smbus_write) {
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ status = i2c_smbus_write_i2c_block_data(client,
+ offset, count, buf);
+ break;
+ case I2C_SMBUS_BYTE_DATA:
+ status = i2c_smbus_write_byte_data(client,
+ offset, buf[0]);
+ break;
+ }
+
if (status == 0)
status = count;
} else {
@@ -487,6 +497,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
struct at24_platform_data chip;
bool writable;
int use_smbus = 0;
+ int use_smbus_write = 0;
struct at24_data *at24;
int err;
unsigned i, num_addresses;
@@ -546,6 +557,18 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
}
}
+ /* Use I2C operations unless we're stuck with SMBus extensions. */
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ if (i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) {
+ use_smbus_write = I2C_SMBUS_I2C_BLOCK_DATA;
+ } else if (i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) {
+ use_smbus_write = I2C_SMBUS_BYTE_DATA;
+ chip.page_size = 1;
+ }
+ }
+
if (chip.flags & AT24_FLAG_TAKE8ADDR)
num_addresses = 8;
else
@@ -559,6 +582,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
mutex_init(&at24->lock);
at24->use_smbus = use_smbus;
+ at24->use_smbus_write = use_smbus_write;
at24->chip = chip;
at24->num_addresses = num_addresses;
@@ -576,8 +600,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
writable = !(chip.flags & AT24_FLAG_READONLY);
if (writable) {
- if (!use_smbus || i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) {
+ if (!use_smbus || use_smbus_write) {
unsigned write_max = chip.page_size;
diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index 634f72929e12..0a1af93ec638 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -18,7 +18,7 @@
#include <linux/spi/spi.h>
#include <linux/spi/eeprom.h>
-#include <linux/of.h>
+#include <linux/property.h>
/*
* NOTE: this is an *EEPROM* driver. The vagaries of product naming
@@ -301,35 +301,33 @@ static ssize_t at25_mem_write(struct memory_accessor *mem, const char *buf,
/*-------------------------------------------------------------------------*/
-static int at25_np_to_chip(struct device *dev,
- struct device_node *np,
- struct spi_eeprom *chip)
+static int at25_fw_to_chip(struct device *dev, struct spi_eeprom *chip)
{
u32 val;
memset(chip, 0, sizeof(*chip));
- strncpy(chip->name, np->name, sizeof(chip->name));
+ strncpy(chip->name, "at25", sizeof(chip->name));
- if (of_property_read_u32(np, "size", &val) == 0 ||
- of_property_read_u32(np, "at25,byte-len", &val) == 0) {
+ if (device_property_read_u32(dev, "size", &val) == 0 ||
+ device_property_read_u32(dev, "at25,byte-len", &val) == 0) {
chip->byte_len = val;
} else {
dev_err(dev, "Error: missing \"size\" property\n");
return -ENODEV;
}
- if (of_property_read_u32(np, "pagesize", &val) == 0 ||
- of_property_read_u32(np, "at25,page-size", &val) == 0) {
+ if (device_property_read_u32(dev, "pagesize", &val) == 0 ||
+ device_property_read_u32(dev, "at25,page-size", &val) == 0) {
chip->page_size = (u16)val;
} else {
dev_err(dev, "Error: missing \"pagesize\" property\n");
return -ENODEV;
}
- if (of_property_read_u32(np, "at25,addr-mode", &val) == 0) {
+ if (device_property_read_u32(dev, "at25,addr-mode", &val) == 0) {
chip->flags = (u16)val;
} else {
- if (of_property_read_u32(np, "address-width", &val)) {
+ if (device_property_read_u32(dev, "address-width", &val)) {
dev_err(dev,
"Error: missing \"address-width\" property\n");
return -ENODEV;
@@ -350,7 +348,7 @@ static int at25_np_to_chip(struct device *dev,
val);
return -ENODEV;
}
- if (of_find_property(np, "read-only", NULL))
+ if (device_property_present(dev, "read-only"))
chip->flags |= EE_READONLY;
}
return 0;
@@ -360,21 +358,15 @@ static int at25_probe(struct spi_device *spi)
{
struct at25_data *at25 = NULL;
struct spi_eeprom chip;
- struct device_node *np = spi->dev.of_node;
int err;
int sr;
int addrlen;
/* Chip description */
if (!spi->dev.platform_data) {
- if (np) {
- err = at25_np_to_chip(&spi->dev, np, &chip);
- if (err)
- return err;
- } else {
- dev_err(&spi->dev, "Error: no chip description\n");
- return -ENODEV;
- }
+ err = at25_fw_to_chip(&spi->dev, &chip);
+ if (err)
+ return err;
} else
chip = *(struct spi_eeprom *)spi->dev.platform_data;
diff --git a/drivers/misc/eeprom/eeprom_93cx6.c b/drivers/misc/eeprom/eeprom_93cx6.c
index 0ff4b02177be..0cf2c9d676be 100644
--- a/drivers/misc/eeprom/eeprom_93cx6.c
+++ b/drivers/misc/eeprom/eeprom_93cx6.c
@@ -170,7 +170,7 @@ static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom,
}
/**
- * eeprom_93cx6_read - Read multiple words from eeprom
+ * eeprom_93cx6_read - Read a word from eeprom
* @eeprom: Pointer to eeprom structure
* @word: Word index from where we should start reading
* @data: target pointer where the information will have to be stored
@@ -235,6 +235,66 @@ void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word,
EXPORT_SYMBOL_GPL(eeprom_93cx6_multiread);
/**
+ * eeprom_93cx6_readb - Read a byte from eeprom
+ * @eeprom: Pointer to eeprom structure
+ * @word: Byte index from where we should start reading
+ * @data: target pointer where the information will have to be stored
+ *
+ * This function will read a byte of the eeprom data
+ * into the given data pointer.
+ */
+void eeprom_93cx6_readb(struct eeprom_93cx6 *eeprom, const u8 byte,
+ u8 *data)
+{
+ u16 command;
+ u16 tmp;
+
+ /*
+ * Initialize the eeprom register
+ */
+ eeprom_93cx6_startup(eeprom);
+
+ /*
+ * Select the read opcode and the byte to be read.
+ */
+ command = (PCI_EEPROM_READ_OPCODE << (eeprom->width + 1)) | byte;
+ eeprom_93cx6_write_bits(eeprom, command,
+ PCI_EEPROM_WIDTH_OPCODE + eeprom->width + 1);
+
+ /*
+ * Read the requested 8 bits.
+ */
+ eeprom_93cx6_read_bits(eeprom, &tmp, 8);
+ *data = tmp & 0xff;
+
+ /*
+ * Cleanup eeprom register.
+ */
+ eeprom_93cx6_cleanup(eeprom);
+}
+EXPORT_SYMBOL_GPL(eeprom_93cx6_readb);
+
+/**
+ * eeprom_93cx6_multireadb - Read multiple bytes from eeprom
+ * @eeprom: Pointer to eeprom structure
+ * @byte: Index from where we should start reading
+ * @data: target pointer where the information will have to be stored
+ * @words: Number of bytes that should be read.
+ *
+ * This function will read all requested bytes from the eeprom,
+ * this is done by calling eeprom_93cx6_readb() multiple times.
+ */
+void eeprom_93cx6_multireadb(struct eeprom_93cx6 *eeprom, const u8 byte,
+ u8 *data, const u16 bytes)
+{
+ unsigned int i;
+
+ for (i = 0; i < bytes; i++)
+ eeprom_93cx6_readb(eeprom, byte + i, &data[i]);
+}
+EXPORT_SYMBOL_GPL(eeprom_93cx6_multireadb);
+
+/**
* eeprom_93cx6_wren - set the write enable state
* @eeprom: Pointer to eeprom structure
* @enable: true to enable writes, otherwise disable writes
diff --git a/drivers/misc/eeprom/sunxi_sid.c b/drivers/misc/eeprom/sunxi_sid.c
index 3f2b625b2032..8385177ff32b 100644
--- a/drivers/misc/eeprom/sunxi_sid.c
+++ b/drivers/misc/eeprom/sunxi_sid.c
@@ -146,7 +146,6 @@ static struct platform_driver sunxi_sid_driver = {
.remove = sunxi_sid_remove,
.driver = {
.name = DRV_NAME,
- .owner = THIS_MODULE,
.of_match_table = sunxi_sid_of_match,
},
};
diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c
index 2cf2bbc0b927..180a5442fd4b 100644
--- a/drivers/misc/enclosure.c
+++ b/drivers/misc/enclosure.c
@@ -187,6 +187,7 @@ void enclosure_unregister(struct enclosure_device *edev)
EXPORT_SYMBOL_GPL(enclosure_unregister);
#define ENCLOSURE_NAME_SIZE 64
+#define COMPONENT_NAME_SIZE 64
static void enclosure_link_name(struct enclosure_component *cdev, char *name)
{
@@ -246,6 +247,29 @@ static void enclosure_component_release(struct device *dev)
put_device(dev->parent);
}
+static struct enclosure_component *
+enclosure_component_find_by_name(struct enclosure_device *edev,
+ const char *name)
+{
+ int i;
+ const char *cname;
+ struct enclosure_component *ecomp;
+
+ if (!edev || !name || !name[0])
+ return NULL;
+
+ for (i = 0; i < edev->components; i++) {
+ ecomp = &edev->component[i];
+ cname = dev_name(&ecomp->cdev);
+ if (ecomp->number != -1 &&
+ cname && cname[0] &&
+ !strcmp(cname, name))
+ return ecomp;
+ }
+
+ return NULL;
+}
+
static const struct attribute_group *enclosure_component_groups[];
/**
@@ -269,7 +293,8 @@ enclosure_component_register(struct enclosure_device *edev,
{
struct enclosure_component *ecomp;
struct device *cdev;
- int err;
+ int err, i;
+ char newname[COMPONENT_NAME_SIZE];
if (number >= edev->components)
return ERR_PTR(-EINVAL);
@@ -283,9 +308,20 @@ enclosure_component_register(struct enclosure_device *edev,
ecomp->number = number;
cdev = &ecomp->cdev;
cdev->parent = get_device(&edev->edev);
- if (name && name[0])
- dev_set_name(cdev, "%s", name);
- else
+
+ if (name && name[0]) {
+ /* Some hardware (e.g. enclosure in RX300 S6) has components
+ * with non unique names. Registering duplicates in sysfs
+ * will lead to warnings during bootup. So make the names
+ * unique by appending consecutive numbers -1, -2, ... */
+ i = 1;
+ snprintf(newname, COMPONENT_NAME_SIZE,
+ "%s", name);
+ while (enclosure_component_find_by_name(edev, newname))
+ snprintf(newname, COMPONENT_NAME_SIZE,
+ "%s-%i", name, i++);
+ dev_set_name(cdev, "%s", newname);
+ } else
dev_set_name(cdev, "%u", number);
cdev->release = enclosure_component_release;
diff --git a/drivers/misc/fuse/Makefile b/drivers/misc/fuse/Makefile
deleted file mode 100644
index 0679c4febc89..000000000000
--- a/drivers/misc/fuse/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_ARCH_TEGRA) += tegra/
diff --git a/drivers/misc/genwqe/card_dev.c b/drivers/misc/genwqe/card_dev.c
index 5918586f2f76..c49d244265ec 100644
--- a/drivers/misc/genwqe/card_dev.c
+++ b/drivers/misc/genwqe/card_dev.c
@@ -395,7 +395,7 @@ static void genwqe_vma_open(struct vm_area_struct *vma)
static void genwqe_vma_close(struct vm_area_struct *vma)
{
unsigned long vsize = vma->vm_end - vma->vm_start;
- struct inode *inode = vma->vm_file->f_dentry->d_inode;
+ struct inode *inode = file_inode(vma->vm_file);
struct dma_mapping *dma_map;
struct genwqe_dev *cd = container_of(inode->i_cdev, struct genwqe_dev,
cdev_genwqe);
diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c
index 7cb3b7e41739..1ca94e6fa8fb 100644
--- a/drivers/misc/genwqe/card_utils.c
+++ b/drivers/misc/genwqe/card_utils.c
@@ -590,6 +590,8 @@ int genwqe_user_vmap(struct genwqe_dev *cd, struct dma_mapping *m, void *uaddr,
m->nr_pages,
1, /* write by caller */
m->page_list); /* ptrs to pages */
+ if (rc < 0)
+ goto fail_get_user_pages;
/* assumption: get_user_pages can be killed by signals. */
if (rc < m->nr_pages) {
diff --git a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
index d324f8a97b88..63fe096d4462 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
+++ b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
@@ -235,7 +235,7 @@ static int lis3lv02d_i2c_resume(struct device *dev)
}
#endif /* CONFIG_PM_SLEEP */
-#ifdef CONFIG_PM_RUNTIME
+#ifdef CONFIG_PM
static int lis3_i2c_runtime_suspend(struct device *dev)
{
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
@@ -253,7 +253,7 @@ static int lis3_i2c_runtime_resume(struct device *dev)
lis3lv02d_poweron(lis3);
return 0;
}
-#endif /* CONFIG_PM_RUNTIME */
+#endif /* CONFIG_PM */
static const struct i2c_device_id lis3lv02d_id[] = {
{"lis3lv02d", LIS3LV02D},
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index 6cdce8477f57..79f53941779d 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -262,6 +262,7 @@ out:
static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
{
struct mei_msg_hdr mei_hdr;
+ struct mei_cl *cl;
int ret;
if (!dev || !cb)
@@ -277,8 +278,9 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
dev->iamthif_msg_buf_size = cb->request_buffer.size;
memcpy(dev->iamthif_msg_buf, cb->request_buffer.data,
cb->request_buffer.size);
+ cl = &dev->iamthif_cl;
- ret = mei_cl_flow_ctrl_creds(&dev->iamthif_cl);
+ ret = mei_cl_flow_ctrl_creds(cl);
if (ret < 0)
return ret;
@@ -292,8 +294,8 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
mei_hdr.msg_complete = 1;
}
- mei_hdr.host_addr = dev->iamthif_cl.host_client_id;
- mei_hdr.me_addr = dev->iamthif_cl.me_client_id;
+ mei_hdr.host_addr = cl->host_client_id;
+ mei_hdr.me_addr = cl->me_client_id;
mei_hdr.reserved = 0;
mei_hdr.internal = 0;
dev->iamthif_msg_buf_index += mei_hdr.length;
@@ -302,7 +304,7 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
return ret;
if (mei_hdr.msg_complete) {
- if (mei_cl_flow_ctrl_reduce(&dev->iamthif_cl))
+ if (mei_cl_flow_ctrl_reduce(cl))
return -EIO;
dev->iamthif_flow_control_pending = true;
dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
@@ -360,8 +362,7 @@ int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb)
void mei_amthif_run_next_cmd(struct mei_device *dev)
{
struct mei_cl_cb *cb;
- struct mei_cl_cb *next;
- int status;
+ int ret;
if (!dev)
return;
@@ -376,16 +377,14 @@ void mei_amthif_run_next_cmd(struct mei_device *dev)
dev_dbg(dev->dev, "complete amthif cmd_list cb.\n");
- list_for_each_entry_safe(cb, next, &dev->amthif_cmd_list.list, list) {
- list_del(&cb->list);
- if (!cb->cl)
- continue;
- status = mei_amthif_send_cmd(dev, cb);
- if (status)
- dev_warn(dev->dev, "amthif write failed status = %d\n",
- status);
- break;
- }
+ cb = list_first_entry_or_null(&dev->amthif_cmd_list.list,
+ typeof(*cb), list);
+ if (!cb)
+ return;
+ list_del(&cb->list);
+ ret = mei_amthif_send_cmd(dev, cb);
+ if (ret)
+ dev_warn(dev->dev, "amthif write failed status = %d\n", ret);
}
@@ -536,9 +535,6 @@ int mei_amthif_irq_read_msg(struct mei_device *dev,
cb = dev->iamthif_current_cb;
dev->iamthif_current_cb = NULL;
- if (!cb->cl)
- return -ENODEV;
-
dev->iamthif_stall_timer = 0;
cb->buf_idx = dev->iamthif_msg_buf_index;
cb->read_time = jiffies;
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 4d20d60ca38d..b3a72bca5242 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -140,7 +140,7 @@ static struct device_type mei_cl_device_type = {
.release = mei_cl_dev_release,
};
-static struct mei_cl *mei_bus_find_mei_cl_by_uuid(struct mei_device *dev,
+struct mei_cl *mei_cl_bus_find_cl_by_uuid(struct mei_device *dev,
uuid_le uuid)
{
struct mei_cl *cl;
@@ -160,7 +160,7 @@ struct mei_cl_device *mei_cl_add_device(struct mei_device *dev,
struct mei_cl *cl;
int status;
- cl = mei_bus_find_mei_cl_by_uuid(dev, uuid);
+ cl = mei_cl_bus_find_cl_by_uuid(dev, uuid);
if (cl == NULL)
return NULL;
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index bc9ba5359bc6..1382d551d7ed 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -146,7 +146,7 @@ static void __mei_io_list_flush(struct mei_cl_cb *list,
/* enable removing everything if no cl is specified */
list_for_each_entry_safe(cb, next, &list->list, list) {
- if (!cl || (cb->cl && mei_cl_cmp_id(cl, cb->cl))) {
+ if (!cl || mei_cl_cmp_id(cl, cb->cl)) {
list_del(&cb->list);
if (free)
mei_io_cb_free(cb);
diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c
index ce1566715f80..b60b4263cf0f 100644
--- a/drivers/misc/mei/debugfs.c
+++ b/drivers/misc/mei/debugfs.c
@@ -34,7 +34,7 @@ static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf,
int pos = 0;
int ret;
-#define HDR " |id|addr| UUID |con|msg len|sb|\n"
+#define HDR " |id|fix| UUID |con|msg len|sb|\n"
mutex_lock(&dev->device_lock);
@@ -56,12 +56,8 @@ static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf,
list_for_each_entry(me_cl, &dev->me_clients, list) {
- /* skip me clients that cannot be connected */
- if (me_cl->props.max_number_of_connections == 0)
- continue;
-
pos += scnprintf(buf + pos, bufsz - pos,
- "%2d|%2d|%4d|%pUl|%3d|%7d|%2d|\n",
+ "%2d|%2d|%3d|%pUl|%3d|%7d|%2d|\n",
i++, me_cl->client_id,
me_cl->props.fixed_address,
&me_cl->props.protocol_name,
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index 49a2653d91a5..239d7f5d6a92 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -562,17 +562,17 @@ int mei_hbm_cl_disconnect_rsp(struct mei_device *dev, struct mei_cl *cl)
* mei_hbm_cl_disconnect_res - update the client state according
* disconnect response
*
+ * @dev: the device structure
* @cl: mei host client
* @cmd: disconnect client response host bus message
*/
-static void mei_hbm_cl_disconnect_res(struct mei_cl *cl,
+static void mei_hbm_cl_disconnect_res(struct mei_device *dev, struct mei_cl *cl,
struct mei_hbm_cl_cmd *cmd)
{
struct hbm_client_connect_response *rs =
(struct hbm_client_connect_response *)cmd;
- dev_dbg(cl->dev->dev, "hbm: disconnect response cl:host=%02d me=%02d status=%d\n",
- rs->me_addr, rs->host_addr, rs->status);
+ cl_dbg(dev, cl, "hbm: disconnect response status=%d\n", rs->status);
if (rs->status == MEI_CL_DISCONN_SUCCESS)
cl->state = MEI_FILE_DISCONNECTED;
@@ -598,17 +598,17 @@ int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl)
* mei_hbm_cl_connect_res - update the client state according
* connection response
*
+ * @dev: the device structure
* @cl: mei host client
* @cmd: connect client response host bus message
*/
-static void mei_hbm_cl_connect_res(struct mei_cl *cl,
+static void mei_hbm_cl_connect_res(struct mei_device *dev, struct mei_cl *cl,
struct mei_hbm_cl_cmd *cmd)
{
struct hbm_client_connect_response *rs =
(struct hbm_client_connect_response *)cmd;
- dev_dbg(cl->dev->dev, "hbm: connect response cl:host=%02d me=%02d status=%s\n",
- rs->me_addr, rs->host_addr,
+ cl_dbg(dev, cl, "hbm: connect response status=%s\n",
mei_cl_conn_status_str(rs->status));
if (rs->status == MEI_CL_CONN_SUCCESS)
@@ -637,11 +637,6 @@ static void mei_hbm_cl_res(struct mei_device *dev,
list_for_each_entry_safe(cb, next, &dev->ctrl_rd_list.list, list) {
cl = cb->cl;
- /* this should not happen */
- if (WARN_ON(!cl)) {
- list_del_init(&cb->list);
- continue;
- }
if (cb->fop_type != fop_type)
continue;
@@ -657,10 +652,10 @@ static void mei_hbm_cl_res(struct mei_device *dev,
switch (fop_type) {
case MEI_FOP_CONNECT:
- mei_hbm_cl_connect_res(cl, rs);
+ mei_hbm_cl_connect_res(dev, cl, rs);
break;
case MEI_FOP_DISCONNECT:
- mei_hbm_cl_disconnect_res(cl, rs);
+ mei_hbm_cl_disconnect_res(dev, cl, rs);
break;
default:
return;
@@ -811,8 +806,6 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
return -EPROTO;
}
- dev->hbm_state = MEI_HBM_STARTED;
-
if (mei_hbm_enum_clients_req(dev)) {
dev_err(dev->dev, "hbm: start: failed to send enumeration request\n");
return -EIO;
diff --git a/drivers/misc/mei/hbm.h b/drivers/misc/mei/hbm.h
index b7cd3d857fd5..2544db7d1649 100644
--- a/drivers/misc/mei/hbm.h
+++ b/drivers/misc/mei/hbm.h
@@ -26,17 +26,17 @@ struct mei_cl;
*
* @MEI_HBM_IDLE : protocol not started
* @MEI_HBM_STARTING : start request message was sent
- * @MEI_HBM_STARTED : start reply message was received
* @MEI_HBM_ENUM_CLIENTS : enumeration request was sent
* @MEI_HBM_CLIENT_PROPERTIES : acquiring clients properties
+ * @MEI_HBM_STARTED : enumeration was completed
* @MEI_HBM_STOPPED : stopping exchange
*/
enum mei_hbm_state {
MEI_HBM_IDLE = 0,
MEI_HBM_STARTING,
- MEI_HBM_STARTED,
MEI_HBM_ENUM_CLIENTS,
MEI_HBM_CLIENT_PROPERTIES,
+ MEI_HBM_STARTED,
MEI_HBM_STOPPED,
};
diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
index c5feafdd58a8..9eb7ed70ace2 100644
--- a/drivers/misc/mei/hw-me-regs.h
+++ b/drivers/misc/mei/hw-me-regs.h
@@ -117,14 +117,18 @@
#define MEI_DEV_ID_WPT_LP 0x9CBA /* Wildcat Point LP */
#define MEI_DEV_ID_WPT_LP_2 0x9CBB /* Wildcat Point LP 2 */
-/* Host Firmware Status Registers in PCI Config Space */
-#define PCI_CFG_HFS_1 0x40
-#define PCI_CFG_HFS_2 0x48
-
/*
* MEI HW Section
*/
+/* Host Firmware Status Registers in PCI Config Space */
+#define PCI_CFG_HFS_1 0x40
+#define PCI_CFG_HFS_2 0x48
+#define PCI_CFG_HFS_3 0x60
+#define PCI_CFG_HFS_4 0x64
+#define PCI_CFG_HFS_5 0x68
+#define PCI_CFG_HFS_6 0x6C
+
/* MEI registers */
/* H_CB_WW - Host Circular Buffer (CB) Write Window register */
#define H_CB_WW 0
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 4f2fd6fc1e23..ff2755062b44 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -270,10 +270,10 @@ static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
static void mei_me_host_set_ready(struct mei_device *dev)
{
struct mei_me_hw *hw = to_me_hw(dev);
+ u32 hcsr = mei_hcsr_read(hw);
- hw->host_hw_state = mei_hcsr_read(hw);
- hw->host_hw_state |= H_IE | H_IG | H_RDY;
- mei_hcsr_set(hw, hw->host_hw_state);
+ hcsr |= H_IE | H_IG | H_RDY;
+ mei_hcsr_set(hw, hcsr);
}
/**
@@ -285,9 +285,9 @@ static void mei_me_host_set_ready(struct mei_device *dev)
static bool mei_me_host_is_ready(struct mei_device *dev)
{
struct mei_me_hw *hw = to_me_hw(dev);
+ u32 hcsr = mei_hcsr_read(hw);
- hw->host_hw_state = mei_hcsr_read(hw);
- return (hw->host_hw_state & H_RDY) == H_RDY;
+ return (hcsr & H_RDY) == H_RDY;
}
/**
@@ -299,9 +299,9 @@ static bool mei_me_host_is_ready(struct mei_device *dev)
static bool mei_me_hw_is_ready(struct mei_device *dev)
{
struct mei_me_hw *hw = to_me_hw(dev);
+ u32 mecsr = mei_me_mecsr_read(hw);
- hw->me_hw_state = mei_me_mecsr_read(hw);
- return (hw->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA;
+ return (mecsr & ME_RDY_HRA) == ME_RDY_HRA;
}
/**
@@ -356,12 +356,13 @@ static int mei_me_hw_start(struct mei_device *dev)
static unsigned char mei_hbuf_filled_slots(struct mei_device *dev)
{
struct mei_me_hw *hw = to_me_hw(dev);
+ u32 hcsr;
char read_ptr, write_ptr;
- hw->host_hw_state = mei_hcsr_read(hw);
+ hcsr = mei_hcsr_read(hw);
- read_ptr = (char) ((hw->host_hw_state & H_CBRP) >> 8);
- write_ptr = (char) ((hw->host_hw_state & H_CBWP) >> 16);
+ read_ptr = (char) ((hcsr & H_CBRP) >> 8);
+ write_ptr = (char) ((hcsr & H_CBWP) >> 16);
return (unsigned char) (write_ptr - read_ptr);
}
@@ -474,13 +475,14 @@ static int mei_me_write_message(struct mei_device *dev,
static int mei_me_count_full_read_slots(struct mei_device *dev)
{
struct mei_me_hw *hw = to_me_hw(dev);
+ u32 me_csr;
char read_ptr, write_ptr;
unsigned char buffer_depth, filled_slots;
- hw->me_hw_state = mei_me_mecsr_read(hw);
- buffer_depth = (unsigned char)((hw->me_hw_state & ME_CBD_HRA) >> 24);
- read_ptr = (char) ((hw->me_hw_state & ME_CBRP_HRA) >> 8);
- write_ptr = (char) ((hw->me_hw_state & ME_CBWP_HRA) >> 16);
+ me_csr = mei_me_mecsr_read(hw);
+ buffer_depth = (unsigned char)((me_csr & ME_CBD_HRA) >> 24);
+ read_ptr = (char) ((me_csr & ME_CBRP_HRA) >> 8);
+ write_ptr = (char) ((me_csr & ME_CBWP_HRA) >> 16);
filled_slots = (unsigned char) (write_ptr - read_ptr);
/* check for overflow */
@@ -833,6 +835,14 @@ static bool mei_me_fw_type_sps(struct pci_dev *pdev)
.fw_status.status[0] = PCI_CFG_HFS_1, \
.fw_status.status[1] = PCI_CFG_HFS_2
+#define MEI_CFG_PCH8_HFS \
+ .fw_status.count = 6, \
+ .fw_status.status[0] = PCI_CFG_HFS_1, \
+ .fw_status.status[1] = PCI_CFG_HFS_2, \
+ .fw_status.status[2] = PCI_CFG_HFS_3, \
+ .fw_status.status[3] = PCI_CFG_HFS_4, \
+ .fw_status.status[4] = PCI_CFG_HFS_5, \
+ .fw_status.status[5] = PCI_CFG_HFS_6
/* ICH Legacy devices */
const struct mei_cfg mei_me_legacy_cfg = {
@@ -856,9 +866,14 @@ const struct mei_cfg mei_me_pch_cpt_pbg_cfg = {
MEI_CFG_FW_NM,
};
-/* PCH Lynx Point with quirk for SPS Firmware exclusion */
-const struct mei_cfg mei_me_lpt_cfg = {
- MEI_CFG_PCH_HFS,
+/* PCH8 Lynx Point and newer devices */
+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 = {
+ MEI_CFG_PCH8_HFS,
MEI_CFG_FW_SPS,
};
diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h
index e6a59a62573a..d6567af44377 100644
--- a/drivers/misc/mei/hw-me.h
+++ b/drivers/misc/mei/hw-me.h
@@ -51,18 +51,11 @@ struct mei_cfg {
*
* @cfg: per device generation config and ops
* @mem_addr: io memory address
- * @host_hw_state: cached host state
- * @me_hw_state: cached me (fw) state
* @pg_state: power gating state
*/
struct mei_me_hw {
const struct mei_cfg *cfg;
void __iomem *mem_addr;
- /*
- * hw states of host and fw(ME)
- */
- u32 host_hw_state;
- u32 me_hw_state;
enum mei_pg_state pg_state;
};
@@ -72,7 +65,8 @@ 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_lpt_cfg;
+extern const struct mei_cfg mei_me_pch8_cfg;
+extern const struct mei_cfg mei_me_pch8_sps_cfg;
struct mei_device *mei_me_dev_init(struct pci_dev *pdev,
const struct mei_cfg *cfg);
diff --git a/drivers/misc/mei/hw-txe.c b/drivers/misc/mei/hw-txe.c
index c5e1902e493f..618ea721aca8 100644
--- a/drivers/misc/mei/hw-txe.c
+++ b/drivers/misc/mei/hw-txe.c
@@ -700,11 +700,10 @@ static int mei_txe_write(struct mei_device *dev,
mei_txe_input_ready_interrupt_enable(dev);
if (!mei_txe_is_input_ready(dev)) {
- struct mei_fw_status fw_status;
+ char fw_sts_str[MEI_FW_STATUS_STR_SZ];
- mei_fw_status(dev, &fw_status);
- dev_err(dev->dev, "Input is not ready " FW_STS_FMT "\n",
- FW_STS_PRM(fw_status));
+ mei_fw_status_str(dev, fw_sts_str, MEI_FW_STATUS_STR_SZ);
+ dev_err(dev->dev, "Input is not ready %s\n", fw_sts_str);
return -EAGAIN;
}
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index 7901d076c127..9306219d5675 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -54,6 +54,35 @@ const char *mei_pg_state_str(enum mei_pg_state state)
#undef MEI_PG_STATE
}
+/**
+ * mei_fw_status2str - convert fw status registers to printable string
+ *
+ * @fw_status: firmware status
+ * @buf: string buffer at minimal size MEI_FW_STATUS_STR_SZ
+ * @len: buffer len must be >= MEI_FW_STATUS_STR_SZ
+ *
+ * Return: number of bytes written or -EINVAL if buffer is to small
+ */
+ssize_t mei_fw_status2str(struct mei_fw_status *fw_status,
+ char *buf, size_t len)
+{
+ ssize_t cnt = 0;
+ int i;
+
+ buf[0] = '\0';
+
+ if (len < MEI_FW_STATUS_STR_SZ)
+ return -EINVAL;
+
+ for (i = 0; i < fw_status->count; i++)
+ cnt += scnprintf(buf + cnt, len - cnt, "%08X ",
+ fw_status->status[i]);
+
+ /* drop last space */
+ buf[cnt] = '\0';
+ return cnt;
+}
+EXPORT_SYMBOL_GPL(mei_fw_status2str);
/**
* mei_cancel_work - Cancel mei background jobs
@@ -86,12 +115,11 @@ int mei_reset(struct mei_device *dev)
state != MEI_DEV_DISABLED &&
state != MEI_DEV_POWER_DOWN &&
state != MEI_DEV_POWER_UP) {
- struct mei_fw_status fw_status;
+ char fw_sts_str[MEI_FW_STATUS_STR_SZ];
- mei_fw_status(dev, &fw_status);
- dev_warn(dev->dev,
- "unexpected reset: dev_state = %s " FW_STS_FMT "\n",
- mei_dev_state_str(state), FW_STS_PRM(fw_status));
+ mei_fw_status_str(dev, fw_sts_str, MEI_FW_STATUS_STR_SZ);
+ dev_warn(dev->dev, "unexpected reset: dev_state = %s fw status = %s\n",
+ mei_dev_state_str(state), fw_sts_str);
}
/* we're already in reset, cancel the init timer
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 20c6c511f438..711cddfa9c99 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -44,8 +44,6 @@ void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *compl_list)
list_for_each_entry_safe(cb, next, &compl_list->list, list) {
cl = cb->cl;
list_del(&cb->list);
- if (!cl)
- continue;
dev_dbg(dev->dev, "completing call back.\n");
if (cl == &dev->iamthif_cl)
@@ -105,7 +103,7 @@ static int mei_cl_irq_read_msg(struct mei_device *dev,
list_for_each_entry_safe(cb, next, &dev->read_list.list, list) {
cl = cb->cl;
- if (!cl || !mei_cl_is_reading(cl, mei_hdr))
+ if (!mei_cl_is_reading(cl, mei_hdr))
continue;
cl->reading_state = MEI_READING;
@@ -449,8 +447,6 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
list = &dev->write_waiting_list;
list_for_each_entry_safe(cb, next, &list->list, list) {
cl = cb->cl;
- if (cl == NULL)
- continue;
cl->status = 0;
list_del(&cb->list);
@@ -489,10 +485,6 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
dev_dbg(dev->dev, "complete control write list cb.\n");
list_for_each_entry_safe(cb, next, &dev->ctrl_wr_list.list, list) {
cl = cb->cl;
- if (!cl) {
- list_del(&cb->list);
- return -ENODEV;
- }
switch (cb->fop_type) {
case MEI_FOP_DISCONNECT:
/* send disconnect message */
@@ -530,8 +522,6 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
dev_dbg(dev->dev, "complete write list cb.\n");
list_for_each_entry_safe(cb, next, &dev->write_list.list, list) {
cl = cb->cl;
- if (cl == NULL)
- continue;
if (cl == &dev->iamthif_cl)
ret = mei_amthif_irq_write(cl, cb, cmpl_list);
else
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index beedc91f03a6..ae56ba6ca0e3 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -631,6 +631,44 @@ out:
return mask;
}
+/**
+ * fw_status_show - mei device attribute show method
+ *
+ * @device: device pointer
+ * @attr: attribute pointer
+ * @buf: char out buffer
+ *
+ * Return: number of the bytes printed into buf or error
+ */
+static ssize_t fw_status_show(struct device *device,
+ struct device_attribute *attr, char *buf)
+{
+ struct mei_device *dev = dev_get_drvdata(device);
+ struct mei_fw_status fw_status;
+ int err, i;
+ ssize_t cnt = 0;
+
+ mutex_lock(&dev->device_lock);
+ err = mei_fw_status(dev, &fw_status);
+ mutex_unlock(&dev->device_lock);
+ if (err) {
+ dev_err(device, "read fw_status error = %d\n", err);
+ return err;
+ }
+
+ for (i = 0; i < fw_status.count; i++)
+ cnt += scnprintf(buf + cnt, PAGE_SIZE - cnt, "%08X\n",
+ fw_status.status[i]);
+ return cnt;
+}
+static DEVICE_ATTR_RO(fw_status);
+
+static struct attribute *mei_attrs[] = {
+ &dev_attr_fw_status.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(mei);
+
/*
* file operations structure will be used for mei char device.
*/
@@ -710,8 +748,9 @@ int mei_register(struct mei_device *dev, struct device *parent)
goto err_dev_add;
}
- clsdev = device_create(mei_class, parent, devno,
- NULL, "mei%d", dev->minor);
+ clsdev = device_create_with_groups(mei_class, parent, devno,
+ dev, mei_groups,
+ "mei%d", dev->minor);
if (IS_ERR(clsdev)) {
dev_err(parent, "unable to create device %d:%d\n",
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 71744b16cc8c..3dad74a8d496 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -152,7 +152,10 @@ struct mei_msg_data {
};
/* Maximum number of processed FW status registers */
-#define MEI_FW_STATUS_MAX 2
+#define MEI_FW_STATUS_MAX 6
+/* Minimal buffer for FW status string (8 bytes in dw + space or '\0') */
+#define MEI_FW_STATUS_STR_SZ (MEI_FW_STATUS_MAX * (8 + 1))
+
/*
* struct mei_fw_status - storage of FW status data
@@ -349,6 +352,7 @@ void mei_cl_bus_rx_event(struct mei_cl *cl);
void mei_cl_bus_remove_devices(struct mei_device *dev);
int mei_cl_bus_init(void);
void mei_cl_bus_exit(void);
+struct mei_cl *mei_cl_bus_find_cl_by_uuid(struct mei_device *dev, uuid_le uuid);
/**
@@ -530,9 +534,9 @@ struct mei_device {
* Power Gating support
*/
enum mei_pg_event pg_event;
-#ifdef CONFIG_PM_RUNTIME
+#ifdef CONFIG_PM
struct dev_pm_domain pg_domain;
-#endif /* CONFIG_PM_RUNTIME */
+#endif /* CONFIG_PM */
unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE];
u32 rd_msg_hdr;
@@ -804,11 +808,6 @@ static inline int mei_fw_status(struct mei_device *dev,
return dev->ops->fw_status(dev, fw_status);
}
-#define FW_STS_FMT "%08X %08X"
-#define FW_STS_PRM(fw_status) \
- (fw_status).count > 0 ? (fw_status).status[0] : 0xDEADBEEF, \
- (fw_status).count > 1 ? (fw_status).status[1] : 0xDEADBEEF
-
bool mei_hbuf_acquire(struct mei_device *dev);
bool mei_write_is_idle(struct mei_device *dev);
@@ -832,4 +831,32 @@ void mei_deregister(struct mei_device *dev);
(hdr)->host_addr, (hdr)->me_addr, \
(hdr)->length, (hdr)->internal, (hdr)->msg_complete
+ssize_t mei_fw_status2str(struct mei_fw_status *fw_sts, char *buf, size_t len);
+/**
+ * mei_fw_status_str - fetch and convert fw status registers to printable string
+ *
+ * @dev: the device structure
+ * @buf: string buffer at minimal size MEI_FW_STATUS_STR_SZ
+ * @len: buffer len must be >= MEI_FW_STATUS_STR_SZ
+ *
+ * Return: number of bytes written or < 0 on failure
+ */
+static inline ssize_t mei_fw_status_str(struct mei_device *dev,
+ char *buf, size_t len)
+{
+ struct mei_fw_status fw_status;
+ int ret;
+
+ buf[0] = '\0';
+
+ ret = mei_fw_status(dev, &fw_status);
+ if (ret)
+ return ret;
+
+ ret = mei_fw_status2str(&fw_status, buf, MEI_FW_STATUS_STR_SZ);
+
+ return ret;
+}
+
+
#endif
diff --git a/drivers/misc/mei/nfc.c b/drivers/misc/mei/nfc.c
index 622654323177..60ca9240368e 100644
--- a/drivers/misc/mei/nfc.c
+++ b/drivers/misc/mei/nfc.c
@@ -117,8 +117,6 @@ struct mei_nfc_dev {
u16 recv_req_id;
};
-static struct mei_nfc_dev nfc_dev;
-
/* UUIDs for NFC F/W clients */
const uuid_le mei_nfc_guid = UUID_LE(0x0bb17a78, 0x2a8e, 0x4c50,
0x94, 0xd4, 0x50, 0x26,
@@ -138,6 +136,9 @@ static const uuid_le mei_nfc_info_guid = UUID_LE(0xd2de1625, 0x382d, 0x417d,
static void mei_nfc_free(struct mei_nfc_dev *ndev)
{
+ if (!ndev)
+ return;
+
if (ndev->cl) {
list_del(&ndev->cl->device_link);
mei_cl_unlink(ndev->cl);
@@ -150,7 +151,7 @@ static void mei_nfc_free(struct mei_nfc_dev *ndev)
kfree(ndev->cl_info);
}
- memset(ndev, 0, sizeof(struct mei_nfc_dev));
+ kfree(ndev);
}
static int mei_nfc_build_bus_name(struct mei_nfc_dev *ndev)
@@ -319,9 +320,10 @@ err:
static int mei_nfc_enable(struct mei_cl_device *cldev)
{
struct mei_device *dev;
- struct mei_nfc_dev *ndev = &nfc_dev;
+ struct mei_nfc_dev *ndev;
int ret;
+ ndev = (struct mei_nfc_dev *)cldev->priv_data;
dev = ndev->cl->dev;
ret = mei_nfc_connect(ndev);
@@ -479,15 +481,25 @@ err:
int mei_nfc_host_init(struct mei_device *dev)
{
- struct mei_nfc_dev *ndev = &nfc_dev;
+ struct mei_nfc_dev *ndev;
struct mei_cl *cl_info, *cl = NULL;
struct mei_me_client *me_cl;
int ret;
- /* already initialized */
- if (ndev->cl_info)
+
+ /* in case of internal reset bail out
+ * as the device is already setup
+ */
+ cl = mei_cl_bus_find_cl_by_uuid(dev, mei_nfc_guid);
+ if (cl)
return 0;
+ ndev = kzalloc(sizeof(struct mei_nfc_dev), GFP_KERNEL);
+ if (!ndev) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
ndev->cl_info = mei_cl_allocate(dev);
ndev->cl = mei_cl_allocate(dev);
@@ -550,9 +562,31 @@ err:
void mei_nfc_host_exit(struct mei_device *dev)
{
- struct mei_nfc_dev *ndev = &nfc_dev;
+ struct mei_nfc_dev *ndev;
+ struct mei_cl *cl;
+ struct mei_cl_device *cldev;
+
+ cl = mei_cl_bus_find_cl_by_uuid(dev, mei_nfc_guid);
+ if (!cl)
+ return;
+
+ cldev = cl->device;
+ if (!cldev)
+ return;
- cancel_work_sync(&ndev->init_work);
+ ndev = (struct mei_nfc_dev *)cldev->priv_data;
+ if (ndev)
+ cancel_work_sync(&ndev->init_work);
+
+ cldev->priv_data = NULL;
+
+ mutex_lock(&dev->device_lock);
+ /* Need to remove the device here
+ * since mei_nfc_free will unlink the clients
+ */
+ mei_cl_remove_device(cldev);
+ mei_nfc_free(ndev);
+ mutex_unlock(&dev->device_lock);
}
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index f3225b1643ab..bd3039ab8f98 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -76,12 +76,12 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
{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_lpt_cfg)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_W, mei_me_lpt_cfg)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_LP, mei_me_pch_cfg)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_LPT_HR, mei_me_lpt_cfg)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP, mei_me_pch_cfg)},
- {MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP_2, 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)},
/* required last entry */
{0, }
@@ -89,13 +89,13 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, mei_me_pci_tbl);
-#ifdef CONFIG_PM_RUNTIME
+#ifdef CONFIG_PM
static inline void mei_me_set_pm_domain(struct mei_device *dev);
static inline void mei_me_unset_pm_domain(struct mei_device *dev);
#else
static inline void mei_me_set_pm_domain(struct mei_device *dev) {}
static inline void mei_me_unset_pm_domain(struct mei_device *dev) {}
-#endif /* CONFIG_PM_RUNTIME */
+#endif /* CONFIG_PM */
/**
* mei_me_quirk_probe - probe for devices that doesn't valid ME interface
@@ -357,7 +357,7 @@ static int mei_me_pci_resume(struct device *device)
}
#endif /* CONFIG_PM_SLEEP */
-#ifdef CONFIG_PM_RUNTIME
+#ifdef CONFIG_PM
static int mei_me_pm_runtime_idle(struct device *device)
{
struct pci_dev *pdev = to_pci_dev(device);
@@ -453,9 +453,7 @@ static inline void mei_me_unset_pm_domain(struct mei_device *dev)
/* stop using pm callbacks if any */
dev->dev->pm_domain = NULL;
}
-#endif /* CONFIG_PM_RUNTIME */
-#ifdef CONFIG_PM
static const struct dev_pm_ops mei_me_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(mei_me_pci_suspend,
mei_me_pci_resume)
diff --git a/drivers/misc/mei/pci-txe.c b/drivers/misc/mei/pci-txe.c
index bee1c6fb7e75..c86e2ddbe30a 100644
--- a/drivers/misc/mei/pci-txe.c
+++ b/drivers/misc/mei/pci-txe.c
@@ -37,18 +37,19 @@
static const struct pci_device_id mei_txe_pci_tbl[] = {
{PCI_VDEVICE(INTEL, 0x0F18)}, /* Baytrail */
+ {PCI_VDEVICE(INTEL, 0x2298)}, /* Cherrytrail */
{0, }
};
MODULE_DEVICE_TABLE(pci, mei_txe_pci_tbl);
-#ifdef CONFIG_PM_RUNTIME
+#ifdef CONFIG_PM
static inline void mei_txe_set_pm_domain(struct mei_device *dev);
static inline void mei_txe_unset_pm_domain(struct mei_device *dev);
#else
static inline void mei_txe_set_pm_domain(struct mei_device *dev) {}
static inline void mei_txe_unset_pm_domain(struct mei_device *dev) {}
-#endif /* CONFIG_PM_RUNTIME */
+#endif /* CONFIG_PM */
static void mei_txe_pci_iounmap(struct pci_dev *pdev, struct mei_txe_hw *hw)
{
@@ -295,7 +296,7 @@ static int mei_txe_pci_resume(struct device *device)
}
#endif /* CONFIG_PM_SLEEP */
-#ifdef CONFIG_PM_RUNTIME
+#ifdef CONFIG_PM
static int mei_txe_pm_runtime_idle(struct device *device)
{
struct pci_dev *pdev = to_pci_dev(device);
@@ -401,9 +402,7 @@ static inline void mei_txe_unset_pm_domain(struct mei_device *dev)
/* stop using pm callbacks if any */
dev->dev->pm_domain = NULL;
}
-#endif /* CONFIG_PM_RUNTIME */
-#ifdef CONFIG_PM
static const struct dev_pm_ops mei_txe_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(mei_txe_pci_suspend,
mei_txe_pci_resume)
diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c
index b836dfffceb5..b1d892cea94d 100644
--- a/drivers/misc/mei/wd.c
+++ b/drivers/misc/mei/wd.c
@@ -270,15 +270,18 @@ static int mei_wd_ops_stop(struct watchdog_device *wd_dev)
static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
{
struct mei_device *dev;
+ struct mei_cl *cl;
int ret;
dev = watchdog_get_drvdata(wd_dev);
if (!dev)
return -ENODEV;
+ cl = &dev->wd_cl;
+
mutex_lock(&dev->device_lock);
- if (dev->wd_cl.state != MEI_FILE_CONNECTED) {
+ if (cl->state != MEI_FILE_CONNECTED) {
dev_err(dev->dev, "wd: not connected.\n");
ret = -ENODEV;
goto end;
@@ -286,12 +289,12 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
dev->wd_state = MEI_WD_RUNNING;
- ret = mei_cl_flow_ctrl_creds(&dev->wd_cl);
+ ret = mei_cl_flow_ctrl_creds(cl);
if (ret < 0)
goto end;
+
/* Check if we can send the ping to HW*/
if (ret && mei_hbuf_acquire(dev)) {
-
dev_dbg(dev->dev, "wd: sending ping\n");
ret = mei_wd_send(dev);
diff --git a/drivers/misc/mic/card/mic_virtio.c b/drivers/misc/mic/card/mic_virtio.c
index e64794730e21..e486a0c26267 100644
--- a/drivers/misc/mic/card/mic_virtio.c
+++ b/drivers/misc/mic/card/mic_virtio.c
@@ -68,7 +68,7 @@ static inline struct device *mic_dev(struct mic_vdev *mvdev)
}
/* This gets the device's feature bits. */
-static u32 mic_get_features(struct virtio_device *vdev)
+static u64 mic_get_features(struct virtio_device *vdev)
{
unsigned int i, bits;
u32 features = 0;
@@ -76,8 +76,7 @@ static u32 mic_get_features(struct virtio_device *vdev)
u8 __iomem *in_features = mic_vq_features(desc);
int feature_len = ioread8(&desc->feature_len);
- bits = min_t(unsigned, feature_len,
- sizeof(vdev->features)) * 8;
+ bits = min_t(unsigned, feature_len, sizeof(features)) * 8;
for (i = 0; i < bits; i++)
if (ioread8(&in_features[i / 8]) & (BIT(i % 8)))
features |= BIT(i);
@@ -85,7 +84,7 @@ static u32 mic_get_features(struct virtio_device *vdev)
return features;
}
-static void mic_finalize_features(struct virtio_device *vdev)
+static int mic_finalize_features(struct virtio_device *vdev)
{
unsigned int i, bits;
struct mic_device_desc __iomem *desc = to_micvdev(vdev)->desc;
@@ -97,14 +96,19 @@ static void mic_finalize_features(struct virtio_device *vdev)
/* Give virtio_ring a chance to accept features. */
vring_transport_features(vdev);
+ /* Make sure we don't have any features > 32 bits! */
+ BUG_ON((u32)vdev->features != vdev->features);
+
memset_io(out_features, 0, feature_len);
bits = min_t(unsigned, feature_len,
sizeof(vdev->features)) * 8;
for (i = 0; i < bits; i++) {
- if (test_bit(i, vdev->features))
+ if (__virtio_test_bit(vdev, i))
iowrite8(ioread8(&out_features[i / 8]) | (1 << (i % 8)),
&out_features[i / 8]);
}
+
+ return 0;
}
/*
diff --git a/drivers/misc/mic/card/mic_x100.c b/drivers/misc/mic/card/mic_x100.c
index 9d57545d64f6..e98e537d68e3 100644
--- a/drivers/misc/mic/card/mic_x100.c
+++ b/drivers/misc/mic/card/mic_x100.c
@@ -255,7 +255,6 @@ static struct platform_driver __refdata mic_platform_driver = {
.shutdown = mic_platform_shutdown,
.driver = {
.name = mic_driver_name,
- .owner = THIS_MODULE,
},
};
diff --git a/drivers/misc/mic/host/mic_debugfs.c b/drivers/misc/mic/host/mic_debugfs.c
index 028ba5d6fd1c..687e9aacf3bb 100644
--- a/drivers/misc/mic/host/mic_debugfs.c
+++ b/drivers/misc/mic/host/mic_debugfs.c
@@ -326,21 +326,27 @@ static int mic_vdev_info_show(struct seq_file *s, void *unused)
}
avail = vrh->vring.avail;
seq_printf(s, "avail flags 0x%x idx %d\n",
- avail->flags, avail->idx & (num - 1));
+ vringh16_to_cpu(vrh, avail->flags),
+ vringh16_to_cpu(vrh, avail->idx) & (num - 1));
seq_printf(s, "avail flags 0x%x idx %d\n",
- avail->flags, avail->idx);
+ vringh16_to_cpu(vrh, avail->flags),
+ vringh16_to_cpu(vrh, avail->idx));
for (j = 0; j < num; j++)
seq_printf(s, "avail ring[%d] %d\n",
j, avail->ring[j]);
used = vrh->vring.used;
seq_printf(s, "used flags 0x%x idx %d\n",
- used->flags, used->idx & (num - 1));
+ vringh16_to_cpu(vrh, used->flags),
+ vringh16_to_cpu(vrh, used->idx) & (num - 1));
seq_printf(s, "used flags 0x%x idx %d\n",
- used->flags, used->idx);
+ vringh16_to_cpu(vrh, used->flags),
+ vringh16_to_cpu(vrh, used->idx));
for (j = 0; j < num; j++)
seq_printf(s, "used ring[%d] id %d len %d\n",
- j, used->ring[j].id,
- used->ring[j].len);
+ j, vringh32_to_cpu(vrh,
+ used->ring[j].id),
+ vringh32_to_cpu(vrh,
+ used->ring[j].len));
}
}
mutex_unlock(&mdev->mic_mutex);
diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c
index 956597321d2a..9a17a9bab8d6 100644
--- a/drivers/misc/pch_phub.c
+++ b/drivers/misc/pch_phub.c
@@ -158,6 +158,7 @@ static void pch_phub_read_modify_write_reg(struct pch_phub_reg *chip,
iowrite32(((ioread32(reg_addr) & ~mask)) | data, reg_addr);
}
+#ifdef CONFIG_PM
/* pch_phub_save_reg_conf - saves register configuration */
static void pch_phub_save_reg_conf(struct pci_dev *pdev)
{
@@ -280,6 +281,7 @@ static void pch_phub_restore_reg_conf(struct pci_dev *pdev)
if ((chip->ioh_type == 2) || (chip->ioh_type == 4))
iowrite32(chip->funcsel_reg, p + FUNCSEL_REG_OFFSET);
}
+#endif
/**
* pch_phub_read_serial_rom() - Reading Serial ROM
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
index 21c2337bad68..e4b7ee4f57b8 100644
--- a/drivers/misc/ti-st/st_kim.c
+++ b/drivers/misc/ti-st/st_kim.c
@@ -858,7 +858,6 @@ static struct platform_driver kim_platform_driver = {
.resume = kim_resume,
.driver = {
.name = "kim",
- .owner = THIS_MODULE,
},
};
diff --git a/drivers/misc/vexpress-syscfg.c b/drivers/misc/vexpress-syscfg.c
index b3a812384a6f..c344483fa7d6 100644
--- a/drivers/misc/vexpress-syscfg.c
+++ b/drivers/misc/vexpress-syscfg.c
@@ -145,7 +145,7 @@ static struct regmap_config vexpress_syscfg_regmap_config = {
static struct regmap *vexpress_syscfg_regmap_init(struct device *dev,
void *context)
{
- struct platform_device *pdev = to_platform_device(dev);
+ int err;
struct vexpress_syscfg *syscfg = context;
struct vexpress_syscfg_func *func;
struct property *prop;
@@ -155,32 +155,18 @@ static struct regmap *vexpress_syscfg_regmap_init(struct device *dev,
u32 site, position, dcc;
int i;
- if (dev->of_node) {
- int err = vexpress_config_get_topo(dev->of_node, &site,
+ err = vexpress_config_get_topo(dev->of_node, &site,
&position, &dcc);
+ if (err)
+ return ERR_PTR(err);
- if (err)
- return ERR_PTR(err);
-
- prop = of_find_property(dev->of_node,
- "arm,vexpress-sysreg,func", NULL);
- if (!prop)
- return ERR_PTR(-EINVAL);
-
- num = prop->length / sizeof(u32) / 2;
- val = prop->value;
- } else {
- if (pdev->num_resources != 1 ||
- pdev->resource[0].flags != IORESOURCE_BUS)
- return ERR_PTR(-EFAULT);
-
- site = pdev->resource[0].start;
- if (site == VEXPRESS_SITE_MASTER)
- site = vexpress_config_get_master();
- position = 0;
- dcc = 0;
- num = 1;
- }
+ prop = of_find_property(dev->of_node,
+ "arm,vexpress-sysreg,func", NULL);
+ if (!prop)
+ return ERR_PTR(-EINVAL);
+
+ num = prop->length / sizeof(u32) / 2;
+ val = prop->value;
/*
* "arm,vexpress-energy" function used to be described
@@ -207,13 +193,8 @@ static struct regmap *vexpress_syscfg_regmap_init(struct device *dev,
for (i = 0; i < num; i++) {
u32 function, device;
- if (dev->of_node) {
- function = be32_to_cpup(val++);
- device = be32_to_cpup(val++);
- } else {
- function = pdev->resource[0].end;
- device = pdev->id;
- }
+ function = be32_to_cpup(val++);
+ device = be32_to_cpup(val++);
dev_dbg(dev, "func %p: %u/%u/%u/%u/%u\n",
func, site, position, dcc,
@@ -265,17 +246,6 @@ static struct vexpress_config_bridge_ops vexpress_syscfg_bridge_ops = {
};
-/* Non-DT hack, to be gone... */
-static struct device *vexpress_syscfg_bridge;
-
-int vexpress_syscfg_device_register(struct platform_device *pdev)
-{
- pdev->dev.parent = vexpress_syscfg_bridge;
-
- return platform_device_register(pdev);
-}
-
-
static int vexpress_syscfg_probe(struct platform_device *pdev)
{
struct vexpress_syscfg *syscfg;
@@ -303,10 +273,6 @@ static int vexpress_syscfg_probe(struct platform_device *pdev)
if (IS_ERR(bridge))
return PTR_ERR(bridge);
- /* Non-DT case */
- if (!pdev->dev.of_node)
- vexpress_syscfg_bridge = bridge;
-
return 0;
}
diff --git a/drivers/misc/vmw_vmci/vmci_queue_pair.c b/drivers/misc/vmw_vmci/vmci_queue_pair.c
index 1b7b303085d2..7aaaf51e1596 100644
--- a/drivers/misc/vmw_vmci/vmci_queue_pair.c
+++ b/drivers/misc/vmw_vmci/vmci_queue_pair.c
@@ -27,6 +27,7 @@
#include <linux/uio.h>
#include <linux/wait.h>
#include <linux/vmalloc.h>
+#include <linux/skbuff.h>
#include "vmci_handle_array.h"
#include "vmci_queue_pair.h"
@@ -429,11 +430,11 @@ static int __qp_memcpy_from_queue(void *dest,
to_copy = size - bytes_copied;
if (is_iovec) {
- struct iovec *iov = (struct iovec *)dest;
+ struct msghdr *msg = dest;
int err;
/* The iovec will track bytes_copied internally. */
- err = memcpy_toiovec(iov, (u8 *)va + page_offset,
+ err = memcpy_to_msg(msg, (u8 *)va + page_offset,
to_copy);
if (err != 0) {
if (kernel_if->host)
@@ -3264,13 +3265,13 @@ EXPORT_SYMBOL_GPL(vmci_qpair_enquev);
* of bytes dequeued or < 0 on error.
*/
ssize_t vmci_qpair_dequev(struct vmci_qp *qpair,
- void *iov,
+ struct msghdr *msg,
size_t iov_size,
int buf_type)
{
ssize_t result;
- if (!qpair || !iov)
+ if (!qpair)
return VMCI_ERROR_INVALID_ARGS;
qp_lock(qpair);
@@ -3279,7 +3280,7 @@ ssize_t vmci_qpair_dequev(struct vmci_qp *qpair,
result = qp_dequeue_locked(qpair->produce_q,
qpair->consume_q,
qpair->consume_q_size,
- iov, iov_size,
+ msg, iov_size,
qp_memcpy_from_queue_iov,
true);
@@ -3308,13 +3309,13 @@ EXPORT_SYMBOL_GPL(vmci_qpair_dequev);
* of bytes peeked or < 0 on error.
*/
ssize_t vmci_qpair_peekv(struct vmci_qp *qpair,
- void *iov,
+ struct msghdr *msg,
size_t iov_size,
int buf_type)
{
ssize_t result;
- if (!qpair || !iov)
+ if (!qpair)
return VMCI_ERROR_INVALID_ARGS;
qp_lock(qpair);
@@ -3323,7 +3324,7 @@ ssize_t vmci_qpair_peekv(struct vmci_qp *qpair,
result = qp_dequeue_locked(qpair->produce_q,
qpair->consume_q,
qpair->consume_q_size,
- iov, iov_size,
+ msg, iov_size,
qp_memcpy_from_queue_iov,
false);