You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'char-misc-4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver updates from Greg KH: "Here's the "big" char and misc driver update for 4.9-rc1. Lots of little things here, all over the driver tree for subsystems that flow through me. Nothing major that I can discern, full details are in the shortlog. All have been in the linux-next tree with no reported issues" * tag 'char-misc-4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (144 commits) drivers/misc/hpilo: Changes to support new security states in iLO5 FW at25: fix debug and error messaging misc/genwqe: ensure zero initialization vme: fake: remove unexpected unlock in fake_master_set() vme: fake: mark symbols static where possible spmi: pmic-arb: Return an error code if sanity check fails Drivers: hv: get rid of id in struct vmbus_channel Drivers: hv: make VMBus bus ids persistent mcb: Add a dma_device to mcb_device mcb: Enable PCI bus mastering by default mei: stop the stall timer worker if not needed clk: probe common clock drivers earlier vme: fake: fix build for 64-bit dma_addr_t ttyprintk: Neaten and simplify printing mei: me: add kaby point device ids coresight: tmc: mark symbols static where possible coresight: perf: deal with error condition properly Drivers: hv: hv_util: Avoid dynamic allocation in time synch fpga manager: Add hardware dependency to Zynq driver Drivers: hv: utils: Support TimeSync version 4.0 protocol samples. ...
This commit is contained in:
@@ -429,34 +429,6 @@ config ARM_CHARLCD
|
||||
line and the Linux version on the second line, but that's
|
||||
still useful.
|
||||
|
||||
config BMP085
|
||||
tristate
|
||||
depends on SYSFS
|
||||
|
||||
config BMP085_I2C
|
||||
tristate "BMP085 digital pressure sensor on I2C"
|
||||
select BMP085
|
||||
select REGMAP_I2C
|
||||
depends on I2C && SYSFS
|
||||
help
|
||||
Say Y here if you want to support Bosch Sensortec's digital pressure
|
||||
sensor hooked to an I2C bus.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called bmp085-i2c.
|
||||
|
||||
config BMP085_SPI
|
||||
tristate "BMP085 digital pressure sensor on SPI"
|
||||
select BMP085
|
||||
select REGMAP_SPI
|
||||
depends on SPI_MASTER && SYSFS
|
||||
help
|
||||
Say Y here if you want to support Bosch Sensortec's digital pressure
|
||||
sensor hooked to an SPI bus.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called bmp085-spi.
|
||||
|
||||
config PCH_PHUB
|
||||
tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) PHUB"
|
||||
select GENERIC_NET_UTILS
|
||||
|
||||
@@ -9,9 +9,6 @@ obj-$(CONFIG_AD525X_DPOT_SPI) += ad525x_dpot-spi.o
|
||||
obj-$(CONFIG_INTEL_MID_PTI) += pti.o
|
||||
obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o
|
||||
obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o
|
||||
obj-$(CONFIG_BMP085) += bmp085.o
|
||||
obj-$(CONFIG_BMP085_I2C) += bmp085-i2c.o
|
||||
obj-$(CONFIG_BMP085_SPI) += bmp085-spi.o
|
||||
obj-$(CONFIG_DUMMY_IRQ) += dummy-irq.o
|
||||
obj-$(CONFIG_ICS932S401) += ics932s401.o
|
||||
obj-$(CONFIG_LKDTM) += lkdtm.o
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Bosch Sensortec GmbH
|
||||
* Copyright (c) 2012 Unixphere AB
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/err.h>
|
||||
#include "bmp085.h"
|
||||
|
||||
#define BMP085_I2C_ADDRESS 0x77
|
||||
|
||||
static const unsigned short normal_i2c[] = { BMP085_I2C_ADDRESS,
|
||||
I2C_CLIENT_END };
|
||||
|
||||
static int bmp085_i2c_detect(struct i2c_client *client,
|
||||
struct i2c_board_info *info)
|
||||
{
|
||||
if (client->addr != BMP085_I2C_ADDRESS)
|
||||
return -ENODEV;
|
||||
|
||||
return bmp085_detect(&client->dev);
|
||||
}
|
||||
|
||||
static int bmp085_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
int err;
|
||||
struct regmap *regmap = devm_regmap_init_i2c(client,
|
||||
&bmp085_regmap_config);
|
||||
|
||||
if (IS_ERR(regmap)) {
|
||||
err = PTR_ERR(regmap);
|
||||
dev_err(&client->dev, "Failed to init regmap: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return bmp085_probe(&client->dev, regmap, client->irq);
|
||||
}
|
||||
|
||||
static int bmp085_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
return bmp085_remove(&client->dev);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id bmp085_id[] = {
|
||||
{ BMP085_NAME, 0 },
|
||||
{ "bmp180", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, bmp085_id);
|
||||
|
||||
static struct i2c_driver bmp085_i2c_driver = {
|
||||
.driver = {
|
||||
.name = BMP085_NAME,
|
||||
},
|
||||
.id_table = bmp085_id,
|
||||
.probe = bmp085_i2c_probe,
|
||||
.remove = bmp085_i2c_remove,
|
||||
|
||||
.detect = bmp085_i2c_detect,
|
||||
.address_list = normal_i2c
|
||||
};
|
||||
|
||||
module_i2c_driver(bmp085_i2c_driver);
|
||||
|
||||
MODULE_AUTHOR("Eric Andersson <eric.andersson@unixphere.com>");
|
||||
MODULE_DESCRIPTION("BMP085 I2C bus driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Bosch Sensortec GmbH
|
||||
* Copyright (c) 2012 Unixphere AB
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/err.h>
|
||||
#include "bmp085.h"
|
||||
|
||||
static int bmp085_spi_probe(struct spi_device *client)
|
||||
{
|
||||
int err;
|
||||
struct regmap *regmap;
|
||||
|
||||
client->bits_per_word = 8;
|
||||
err = spi_setup(client);
|
||||
if (err < 0) {
|
||||
dev_err(&client->dev, "spi_setup failed!\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
regmap = devm_regmap_init_spi(client, &bmp085_regmap_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
err = PTR_ERR(regmap);
|
||||
dev_err(&client->dev, "Failed to init regmap: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return bmp085_probe(&client->dev, regmap, client->irq);
|
||||
}
|
||||
|
||||
static int bmp085_spi_remove(struct spi_device *client)
|
||||
{
|
||||
return bmp085_remove(&client->dev);
|
||||
}
|
||||
|
||||
static const struct of_device_id bmp085_of_match[] = {
|
||||
{ .compatible = "bosch,bmp085", },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bmp085_of_match);
|
||||
|
||||
static const struct spi_device_id bmp085_id[] = {
|
||||
{ "bmp180", 0 },
|
||||
{ "bmp181", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, bmp085_id);
|
||||
|
||||
static struct spi_driver bmp085_spi_driver = {
|
||||
.driver = {
|
||||
.name = BMP085_NAME,
|
||||
.of_match_table = bmp085_of_match
|
||||
},
|
||||
.id_table = bmp085_id,
|
||||
.probe = bmp085_spi_probe,
|
||||
.remove = bmp085_spi_remove
|
||||
};
|
||||
|
||||
module_spi_driver(bmp085_spi_driver);
|
||||
|
||||
MODULE_AUTHOR("Eric Andersson <eric.andersson@unixphere.com>");
|
||||
MODULE_DESCRIPTION("BMP085 SPI bus driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Bosch Sensortec GmbH
|
||||
* Copyright (c) 2012 Unixphere AB
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef _BMP085_H
|
||||
#define _BMP085_H
|
||||
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define BMP085_NAME "bmp085"
|
||||
|
||||
extern struct regmap_config bmp085_regmap_config;
|
||||
|
||||
int bmp085_probe(struct device *dev, struct regmap *regmap, int irq);
|
||||
int bmp085_remove(struct device *dev);
|
||||
int bmp085_detect(struct device *dev);
|
||||
|
||||
#endif
|
||||
@@ -121,9 +121,8 @@ static int at25_ee_read(void *priv, unsigned int offset,
|
||||
* this chip is clocked very slowly
|
||||
*/
|
||||
status = spi_sync(at25->spi, &m);
|
||||
dev_dbg(&at25->spi->dev,
|
||||
"read %Zd bytes at %d --> %d\n",
|
||||
count, offset, (int) status);
|
||||
dev_dbg(&at25->spi->dev, "read %zu bytes at %d --> %zd\n",
|
||||
count, offset, status);
|
||||
|
||||
mutex_unlock(&at25->lock);
|
||||
return status;
|
||||
@@ -167,8 +166,7 @@ static int at25_ee_write(void *priv, unsigned int off, void *val, size_t count)
|
||||
*cp = AT25_WREN;
|
||||
status = spi_write(at25->spi, cp, 1);
|
||||
if (status < 0) {
|
||||
dev_dbg(&at25->spi->dev, "WREN --> %d\n",
|
||||
(int) status);
|
||||
dev_dbg(&at25->spi->dev, "WREN --> %d\n", status);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -196,9 +194,8 @@ static int at25_ee_write(void *priv, unsigned int off, void *val, size_t count)
|
||||
memcpy(cp, buf, segment);
|
||||
status = spi_write(at25->spi, bounce,
|
||||
segment + at25->addrlen + 1);
|
||||
dev_dbg(&at25->spi->dev,
|
||||
"write %u bytes at %u --> %d\n",
|
||||
segment, offset, (int) status);
|
||||
dev_dbg(&at25->spi->dev, "write %u bytes at %u --> %d\n",
|
||||
segment, offset, status);
|
||||
if (status < 0)
|
||||
break;
|
||||
|
||||
@@ -225,8 +222,7 @@ static int at25_ee_write(void *priv, unsigned int off, void *val, size_t count)
|
||||
|
||||
if ((sr < 0) || (sr & AT25_SR_nRDY)) {
|
||||
dev_err(&at25->spi->dev,
|
||||
"write %d bytes offset %d, "
|
||||
"timeout after %u msecs\n",
|
||||
"write %u bytes offset %u, timeout after %u msecs\n",
|
||||
segment, offset,
|
||||
jiffies_to_msecs(jiffies -
|
||||
(timeout - EE_TIMEOUT)));
|
||||
@@ -368,9 +364,7 @@ static int at25_probe(struct spi_device *spi)
|
||||
return PTR_ERR(at25->nvmem);
|
||||
|
||||
dev_info(&spi->dev, "%d %s %s eeprom%s, pagesize %u\n",
|
||||
(chip.byte_len < 1024)
|
||||
? chip.byte_len
|
||||
: (chip.byte_len / 1024),
|
||||
(chip.byte_len < 1024) ? chip.byte_len : (chip.byte_len / 1024),
|
||||
(chip.byte_len < 1024) ? "Byte" : "KByte",
|
||||
at25->chip.name,
|
||||
(chip.flags & EE_READONLY) ? " (readonly)" : "",
|
||||
|
||||
@@ -1350,6 +1350,19 @@ static struct pci_driver genwqe_driver = {
|
||||
.err_handler = &genwqe_err_handler,
|
||||
};
|
||||
|
||||
/**
|
||||
* genwqe_devnode() - Set default access mode for genwqe devices.
|
||||
*
|
||||
* Default mode should be rw for everybody. Do not change default
|
||||
* device name.
|
||||
*/
|
||||
static char *genwqe_devnode(struct device *dev, umode_t *mode)
|
||||
{
|
||||
if (mode)
|
||||
*mode = 0666;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* genwqe_init_module() - Driver registration and initialization
|
||||
*/
|
||||
@@ -1363,6 +1376,8 @@ static int __init genwqe_init_module(void)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
class_genwqe->devnode = genwqe_devnode;
|
||||
|
||||
debugfs_genwqe = debugfs_create_dir(GENWQE_DEVNAME, NULL);
|
||||
if (!debugfs_genwqe) {
|
||||
rc = -ENOMEM;
|
||||
|
||||
@@ -1048,8 +1048,6 @@ static int setup_ddcb_queue(struct genwqe_dev *cd, struct ddcb_queue *queue)
|
||||
"[%s] **err: could not allocate DDCB **\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(queue->ddcb_vaddr, 0, queue_size);
|
||||
|
||||
queue->ddcb_req = kzalloc(sizeof(struct ddcb_requ *) *
|
||||
queue->ddcb_max, GFP_KERNEL);
|
||||
if (!queue->ddcb_req) {
|
||||
|
||||
@@ -220,8 +220,8 @@ void *__genwqe_alloc_consistent(struct genwqe_dev *cd, size_t size,
|
||||
if (get_order(size) > MAX_ORDER)
|
||||
return NULL;
|
||||
|
||||
return dma_alloc_coherent(&cd->pci_dev->dev, size, dma_handle,
|
||||
GFP_KERNEL);
|
||||
return dma_zalloc_coherent(&cd->pci_dev->dev, size, dma_handle,
|
||||
GFP_KERNEL);
|
||||
}
|
||||
|
||||
void __genwqe_free_consistent(struct genwqe_dev *cd, size_t size,
|
||||
|
||||
+13
-4
@@ -688,7 +688,8 @@ static void ilo_unmap_device(struct pci_dev *pdev, struct ilo_hwinfo *hw)
|
||||
|
||||
static int ilo_map_device(struct pci_dev *pdev, struct ilo_hwinfo *hw)
|
||||
{
|
||||
int error = -ENOMEM;
|
||||
int bar;
|
||||
unsigned long off;
|
||||
|
||||
/* map the memory mapped i/o registers */
|
||||
hw->mmio_vaddr = pci_iomap(pdev, 1, 0);
|
||||
@@ -698,7 +699,15 @@ static int ilo_map_device(struct pci_dev *pdev, struct ilo_hwinfo *hw)
|
||||
}
|
||||
|
||||
/* map the adapter shared memory region */
|
||||
hw->ram_vaddr = pci_iomap(pdev, 2, max_ccb * ILOHW_CCB_SZ);
|
||||
if (pdev->subsystem_device == 0x00E4) {
|
||||
bar = 5;
|
||||
/* Last 8k is reserved for CCBs */
|
||||
off = pci_resource_len(pdev, bar) - 0x2000;
|
||||
} else {
|
||||
bar = 2;
|
||||
off = 0;
|
||||
}
|
||||
hw->ram_vaddr = pci_iomap_range(pdev, bar, off, max_ccb * ILOHW_CCB_SZ);
|
||||
if (hw->ram_vaddr == NULL) {
|
||||
dev_err(&pdev->dev, "Error mapping shared mem\n");
|
||||
goto mmio_free;
|
||||
@@ -717,7 +726,7 @@ ram_free:
|
||||
mmio_free:
|
||||
pci_iounmap(pdev, hw->mmio_vaddr);
|
||||
out:
|
||||
return error;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void ilo_remove(struct pci_dev *pdev)
|
||||
@@ -899,7 +908,7 @@ static void __exit ilo_exit(void)
|
||||
class_destroy(ilo_class);
|
||||
}
|
||||
|
||||
MODULE_VERSION("1.4.1");
|
||||
MODULE_VERSION("1.5.0");
|
||||
MODULE_ALIAS(ILO_NAME);
|
||||
MODULE_DESCRIPTION(ILO_NAME);
|
||||
MODULE_AUTHOR("David Altobelli <david.altobelli@hpe.com>");
|
||||
|
||||
+76
-267
@@ -47,7 +47,6 @@ const uuid_le mei_amthif_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d,
|
||||
void mei_amthif_reset_params(struct mei_device *dev)
|
||||
{
|
||||
/* reset iamthif parameters. */
|
||||
dev->iamthif_current_cb = NULL;
|
||||
dev->iamthif_canceled = false;
|
||||
dev->iamthif_state = MEI_IAMTHIF_IDLE;
|
||||
dev->iamthif_stall_timer = 0;
|
||||
@@ -67,8 +66,12 @@ int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl)
|
||||
struct mei_cl *cl = &dev->iamthif_cl;
|
||||
int ret;
|
||||
|
||||
if (mei_cl_is_connected(cl))
|
||||
return 0;
|
||||
mutex_lock(&dev->device_lock);
|
||||
|
||||
if (mei_cl_is_connected(cl)) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev->iamthif_state = MEI_IAMTHIF_IDLE;
|
||||
|
||||
@@ -77,179 +80,37 @@ int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl)
|
||||
ret = mei_cl_link(cl);
|
||||
if (ret < 0) {
|
||||
dev_err(dev->dev, "amthif: failed cl_link %d\n", ret);
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = mei_cl_connect(cl, me_cl, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_amthif_read - read data from AMTHIF client
|
||||
*
|
||||
* @dev: the device structure
|
||||
* @file: pointer to file object
|
||||
* @ubuf: pointer to user data in user space
|
||||
* @length: data length to read
|
||||
* @offset: data read offset
|
||||
*
|
||||
* Locking: called under "dev->device_lock" lock
|
||||
*
|
||||
* Return:
|
||||
* returned data length on success,
|
||||
* zero if no data to read,
|
||||
* negative on failure.
|
||||
*/
|
||||
int mei_amthif_read(struct mei_device *dev, struct file *file,
|
||||
char __user *ubuf, size_t length, loff_t *offset)
|
||||
{
|
||||
struct mei_cl *cl = file->private_data;
|
||||
struct mei_cl_cb *cb;
|
||||
int rets;
|
||||
int wait_ret;
|
||||
|
||||
dev_dbg(dev->dev, "checking amthif data\n");
|
||||
cb = mei_cl_read_cb(cl, file);
|
||||
|
||||
/* Check for if we can block or not*/
|
||||
if (cb == NULL && file->f_flags & O_NONBLOCK)
|
||||
return -EAGAIN;
|
||||
|
||||
|
||||
dev_dbg(dev->dev, "waiting for amthif data\n");
|
||||
while (cb == NULL) {
|
||||
/* unlock the Mutex */
|
||||
mutex_unlock(&dev->device_lock);
|
||||
|
||||
wait_ret = wait_event_interruptible(cl->rx_wait,
|
||||
!list_empty(&cl->rd_completed) ||
|
||||
!mei_cl_is_connected(cl));
|
||||
|
||||
/* Locking again the Mutex */
|
||||
mutex_lock(&dev->device_lock);
|
||||
|
||||
if (wait_ret)
|
||||
return -ERESTARTSYS;
|
||||
|
||||
if (!mei_cl_is_connected(cl)) {
|
||||
rets = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cb = mei_cl_read_cb(cl, file);
|
||||
}
|
||||
|
||||
if (cb->status) {
|
||||
rets = cb->status;
|
||||
dev_dbg(dev->dev, "read operation failed %d\n", rets);
|
||||
goto free;
|
||||
}
|
||||
|
||||
dev_dbg(dev->dev, "Got amthif data\n");
|
||||
/* if the whole message will fit remove it from the list */
|
||||
if (cb->buf_idx >= *offset && length >= (cb->buf_idx - *offset))
|
||||
list_del_init(&cb->list);
|
||||
else if (cb->buf_idx <= *offset) {
|
||||
/* end of the message has been reached */
|
||||
list_del_init(&cb->list);
|
||||
rets = 0;
|
||||
goto free;
|
||||
}
|
||||
/* else means that not full buffer will be read and do not
|
||||
* remove message from deletion list
|
||||
*/
|
||||
|
||||
dev_dbg(dev->dev, "amthif cb->buf.size - %zu cb->buf_idx - %zu\n",
|
||||
cb->buf.size, cb->buf_idx);
|
||||
|
||||
/* length is being truncated to PAGE_SIZE, however,
|
||||
* the buf_idx may point beyond */
|
||||
length = min_t(size_t, length, (cb->buf_idx - *offset));
|
||||
|
||||
if (copy_to_user(ubuf, cb->buf.data + *offset, length)) {
|
||||
dev_dbg(dev->dev, "failed to copy data to userland\n");
|
||||
rets = -EFAULT;
|
||||
} else {
|
||||
rets = length;
|
||||
if ((*offset + length) < cb->buf_idx) {
|
||||
*offset += length;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
free:
|
||||
dev_dbg(dev->dev, "free amthif cb memory.\n");
|
||||
*offset = 0;
|
||||
mei_io_cb_free(cb);
|
||||
out:
|
||||
return rets;
|
||||
mutex_unlock(&dev->device_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_amthif_read_start - queue message for sending read credential
|
||||
*
|
||||
* @cl: host client
|
||||
* @file: file pointer of message recipient
|
||||
* @fp: file pointer of message recipient
|
||||
*
|
||||
* Return: 0 on success, <0 on failure.
|
||||
*/
|
||||
static int mei_amthif_read_start(struct mei_cl *cl, const struct file *file)
|
||||
static int mei_amthif_read_start(struct mei_cl *cl, const struct file *fp)
|
||||
{
|
||||
struct mei_device *dev = cl->dev;
|
||||
struct mei_cl_cb *cb;
|
||||
int rets;
|
||||
|
||||
cb = mei_io_cb_init(cl, MEI_FOP_READ, file);
|
||||
if (!cb) {
|
||||
rets = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
cb = mei_cl_enqueue_ctrl_wr_cb(cl, mei_cl_mtu(cl), MEI_FOP_READ, fp);
|
||||
if (!cb)
|
||||
return -ENOMEM;
|
||||
|
||||
rets = mei_io_cb_alloc_buf(cb, mei_cl_mtu(cl));
|
||||
if (rets)
|
||||
goto err;
|
||||
|
||||
list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
|
||||
cl->rx_flow_ctrl_creds++;
|
||||
|
||||
dev->iamthif_state = MEI_IAMTHIF_READING;
|
||||
dev->iamthif_fp = cb->fp;
|
||||
dev->iamthif_current_cb = cb;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
mei_io_cb_free(cb);
|
||||
return rets;
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_amthif_send_cmd - send amthif command to the ME
|
||||
*
|
||||
* @cl: the host client
|
||||
* @cb: mei call back struct
|
||||
*
|
||||
* Return: 0 on success, <0 on failure.
|
||||
*/
|
||||
static int mei_amthif_send_cmd(struct mei_cl *cl, struct mei_cl_cb *cb)
|
||||
{
|
||||
struct mei_device *dev;
|
||||
int ret;
|
||||
|
||||
if (!cl->dev || !cb)
|
||||
return -ENODEV;
|
||||
|
||||
dev = cl->dev;
|
||||
|
||||
dev->iamthif_state = MEI_IAMTHIF_WRITING;
|
||||
dev->iamthif_current_cb = cb;
|
||||
dev->iamthif_fp = cb->fp;
|
||||
dev->iamthif_canceled = false;
|
||||
|
||||
ret = mei_cl_write(cl, cb, false);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (cb->completed)
|
||||
cb->status = mei_amthif_read_start(cl, cb->fp);
|
||||
cl->fp = cb->fp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -265,20 +126,32 @@ int mei_amthif_run_next_cmd(struct mei_device *dev)
|
||||
{
|
||||
struct mei_cl *cl = &dev->iamthif_cl;
|
||||
struct mei_cl_cb *cb;
|
||||
int ret;
|
||||
|
||||
dev->iamthif_canceled = false;
|
||||
dev->iamthif_state = MEI_IAMTHIF_IDLE;
|
||||
dev->iamthif_fp = NULL;
|
||||
|
||||
dev_dbg(dev->dev, "complete amthif cmd_list cb.\n");
|
||||
|
||||
cb = list_first_entry_or_null(&dev->amthif_cmd_list.list,
|
||||
typeof(*cb), list);
|
||||
if (!cb)
|
||||
if (!cb) {
|
||||
dev->iamthif_state = MEI_IAMTHIF_IDLE;
|
||||
cl->fp = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_del_init(&cb->list);
|
||||
return mei_amthif_send_cmd(cl, cb);
|
||||
dev->iamthif_state = MEI_IAMTHIF_WRITING;
|
||||
cl->fp = cb->fp;
|
||||
|
||||
ret = mei_cl_write(cl, cb, false);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (cb->completed)
|
||||
cb->status = mei_amthif_read_start(cl, cb->fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -299,8 +172,7 @@ int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb)
|
||||
/*
|
||||
* The previous request is still in processing, queue this one.
|
||||
*/
|
||||
if (dev->iamthif_state > MEI_IAMTHIF_IDLE &&
|
||||
dev->iamthif_state < MEI_IAMTHIF_READ_COMPLETE)
|
||||
if (dev->iamthif_state != MEI_IAMTHIF_IDLE)
|
||||
return 0;
|
||||
|
||||
return mei_amthif_run_next_cmd(dev);
|
||||
@@ -309,7 +181,6 @@ int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb)
|
||||
/**
|
||||
* mei_amthif_poll - the amthif poll function
|
||||
*
|
||||
* @dev: the device structure
|
||||
* @file: pointer to file structure
|
||||
* @wait: pointer to poll_table structure
|
||||
*
|
||||
@@ -317,26 +188,19 @@ int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb)
|
||||
*
|
||||
* Locking: called under "dev->device_lock" lock
|
||||
*/
|
||||
|
||||
unsigned int mei_amthif_poll(struct mei_device *dev,
|
||||
struct file *file, poll_table *wait)
|
||||
unsigned int mei_amthif_poll(struct file *file, poll_table *wait)
|
||||
{
|
||||
struct mei_cl *cl = file->private_data;
|
||||
struct mei_cl_cb *cb = mei_cl_read_cb(cl, file);
|
||||
unsigned int mask = 0;
|
||||
|
||||
poll_wait(file, &dev->iamthif_cl.rx_wait, wait);
|
||||
|
||||
if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE &&
|
||||
dev->iamthif_fp == file) {
|
||||
|
||||
poll_wait(file, &cl->rx_wait, wait);
|
||||
if (cb)
|
||||
mask |= POLLIN | POLLRDNORM;
|
||||
mei_amthif_run_next_cmd(dev);
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* mei_amthif_irq_write - write iamthif command in irq thread context.
|
||||
*
|
||||
@@ -393,7 +257,6 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl,
|
||||
return 0;
|
||||
|
||||
dev_dbg(dev->dev, "completed amthif read.\n ");
|
||||
dev->iamthif_current_cb = NULL;
|
||||
dev->iamthif_stall_timer = 0;
|
||||
|
||||
return 0;
|
||||
@@ -409,115 +272,63 @@ void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb)
|
||||
{
|
||||
struct mei_device *dev = cl->dev;
|
||||
|
||||
if (cb->fop_type == MEI_FOP_WRITE) {
|
||||
dev_dbg(dev->dev, "completing amthif call back.\n");
|
||||
switch (cb->fop_type) {
|
||||
case MEI_FOP_WRITE:
|
||||
if (!cb->status) {
|
||||
dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER;
|
||||
mei_schedule_stall_timer(dev);
|
||||
mei_io_cb_free(cb);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* in case of error enqueue the write cb to complete read list
|
||||
* so it can be propagated to the reader
|
||||
*/
|
||||
list_add_tail(&cb->list, &cl->rd_completed);
|
||||
wake_up_interruptible(&cl->rx_wait);
|
||||
return;
|
||||
}
|
||||
dev->iamthif_state = MEI_IAMTHIF_IDLE;
|
||||
cl->fp = NULL;
|
||||
if (!dev->iamthif_canceled) {
|
||||
/*
|
||||
* in case of error enqueue the write cb to complete
|
||||
* read list so it can be propagated to the reader
|
||||
*/
|
||||
list_add_tail(&cb->list, &cl->rd_completed);
|
||||
wake_up_interruptible(&cl->rx_wait);
|
||||
} else {
|
||||
mei_io_cb_free(cb);
|
||||
}
|
||||
break;
|
||||
case MEI_FOP_READ:
|
||||
if (!dev->iamthif_canceled) {
|
||||
list_add_tail(&cb->list, &cl->rd_completed);
|
||||
dev_dbg(dev->dev, "amthif read completed\n");
|
||||
wake_up_interruptible(&cl->rx_wait);
|
||||
} else {
|
||||
mei_io_cb_free(cb);
|
||||
}
|
||||
|
||||
if (!dev->iamthif_canceled) {
|
||||
dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE;
|
||||
dev->iamthif_stall_timer = 0;
|
||||
list_add_tail(&cb->list, &cl->rd_completed);
|
||||
dev_dbg(dev->dev, "amthif read completed\n");
|
||||
} else {
|
||||
mei_amthif_run_next_cmd(dev);
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
dev_dbg(dev->dev, "completing amthif call back.\n");
|
||||
wake_up_interruptible(&cl->rx_wait);
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_clear_list - removes all callbacks associated with file
|
||||
* from mei_cb_list
|
||||
*
|
||||
* @dev: device structure.
|
||||
* @file: file structure
|
||||
* @mei_cb_list: callbacks list
|
||||
*
|
||||
* mei_clear_list is called to clear resources associated with file
|
||||
* when application calls close function or Ctrl-C was pressed
|
||||
*
|
||||
* Return: true if callback removed from the list, false otherwise
|
||||
*/
|
||||
static bool mei_clear_list(struct mei_device *dev,
|
||||
const struct file *file, struct list_head *mei_cb_list)
|
||||
static void mei_clear_list(const struct file *file,
|
||||
struct list_head *mei_cb_list)
|
||||
{
|
||||
struct mei_cl *cl = &dev->iamthif_cl;
|
||||
struct mei_cl_cb *cb, *next;
|
||||
bool removed = false;
|
||||
|
||||
/* list all list member */
|
||||
list_for_each_entry_safe(cb, next, mei_cb_list, list) {
|
||||
/* check if list member associated with a file */
|
||||
if (file == cb->fp) {
|
||||
/* check if cb equal to current iamthif cb */
|
||||
if (dev->iamthif_current_cb == cb) {
|
||||
dev->iamthif_current_cb = NULL;
|
||||
/* send flow control to iamthif client */
|
||||
mei_hbm_cl_flow_control_req(dev, cl);
|
||||
}
|
||||
/* free all allocated buffers */
|
||||
list_for_each_entry_safe(cb, next, mei_cb_list, list)
|
||||
if (file == cb->fp)
|
||||
mei_io_cb_free(cb);
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_clear_lists - removes all callbacks associated with file
|
||||
*
|
||||
* @dev: device structure
|
||||
* @file: file structure
|
||||
*
|
||||
* mei_clear_lists is called to clear resources associated with file
|
||||
* when application calls close function or Ctrl-C was pressed
|
||||
*
|
||||
* Return: true if callback removed from the list, false otherwise
|
||||
*/
|
||||
static bool mei_clear_lists(struct mei_device *dev, const struct file *file)
|
||||
{
|
||||
bool removed = false;
|
||||
struct mei_cl *cl = &dev->iamthif_cl;
|
||||
|
||||
/* remove callbacks associated with a file */
|
||||
mei_clear_list(dev, file, &dev->amthif_cmd_list.list);
|
||||
if (mei_clear_list(dev, file, &cl->rd_completed))
|
||||
removed = true;
|
||||
|
||||
mei_clear_list(dev, file, &dev->ctrl_rd_list.list);
|
||||
|
||||
if (mei_clear_list(dev, file, &dev->ctrl_wr_list.list))
|
||||
removed = true;
|
||||
|
||||
if (mei_clear_list(dev, file, &dev->write_waiting_list.list))
|
||||
removed = true;
|
||||
|
||||
if (mei_clear_list(dev, file, &dev->write_list.list))
|
||||
removed = true;
|
||||
|
||||
/* check if iamthif_current_cb not NULL */
|
||||
if (dev->iamthif_current_cb && !removed) {
|
||||
/* check file and iamthif current cb association */
|
||||
if (dev->iamthif_current_cb->fp == file) {
|
||||
/* remove cb */
|
||||
mei_io_cb_free(dev->iamthif_current_cb);
|
||||
dev->iamthif_current_cb = NULL;
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -530,23 +341,21 @@ static bool mei_clear_lists(struct mei_device *dev, const struct file *file)
|
||||
*/
|
||||
int mei_amthif_release(struct mei_device *dev, struct file *file)
|
||||
{
|
||||
struct mei_cl *cl = file->private_data;
|
||||
|
||||
if (dev->iamthif_open_count > 0)
|
||||
dev->iamthif_open_count--;
|
||||
|
||||
if (dev->iamthif_fp == file &&
|
||||
dev->iamthif_state != MEI_IAMTHIF_IDLE) {
|
||||
if (cl->fp == file && dev->iamthif_state != MEI_IAMTHIF_IDLE) {
|
||||
|
||||
dev_dbg(dev->dev, "amthif canceled iamthif state %d\n",
|
||||
dev->iamthif_state);
|
||||
dev->iamthif_canceled = true;
|
||||
if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE) {
|
||||
dev_dbg(dev->dev, "run next amthif iamthif cb\n");
|
||||
mei_amthif_run_next_cmd(dev);
|
||||
}
|
||||
}
|
||||
|
||||
if (mei_clear_lists(dev, file))
|
||||
dev->iamthif_state = MEI_IAMTHIF_IDLE;
|
||||
mei_clear_list(file, &dev->amthif_cmd_list.list);
|
||||
mei_clear_list(file, &cl->rd_completed);
|
||||
mei_clear_list(file, &dev->ctrl_rd_list.list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -126,7 +126,8 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
|
||||
goto out;
|
||||
|
||||
/* wait on event only if there is no other waiter */
|
||||
if (list_empty(&cl->rd_completed) && !waitqueue_active(&cl->rx_wait)) {
|
||||
/* synchronized under device mutex */
|
||||
if (!waitqueue_active(&cl->rx_wait)) {
|
||||
|
||||
mutex_unlock(&bus->device_lock);
|
||||
|
||||
@@ -142,7 +143,7 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
|
||||
mutex_lock(&bus->device_lock);
|
||||
|
||||
if (!mei_cl_is_connected(cl)) {
|
||||
rets = -EBUSY;
|
||||
rets = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@@ -234,7 +235,7 @@ static void mei_cl_bus_event_work(struct work_struct *work)
|
||||
/* Prepare for the next read */
|
||||
if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) {
|
||||
mutex_lock(&bus->device_lock);
|
||||
mei_cl_read_start(cldev->cl, 0, NULL);
|
||||
mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
|
||||
mutex_unlock(&bus->device_lock);
|
||||
}
|
||||
}
|
||||
@@ -324,7 +325,7 @@ int mei_cldev_register_event_cb(struct mei_cl_device *cldev,
|
||||
|
||||
if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) {
|
||||
mutex_lock(&bus->device_lock);
|
||||
ret = mei_cl_read_start(cldev->cl, 0, NULL);
|
||||
ret = mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
|
||||
mutex_unlock(&bus->device_lock);
|
||||
if (ret && ret != -EBUSY)
|
||||
return ret;
|
||||
@@ -983,12 +984,10 @@ void mei_cl_bus_rescan_work(struct work_struct *work)
|
||||
container_of(work, struct mei_device, bus_rescan_work);
|
||||
struct mei_me_client *me_cl;
|
||||
|
||||
mutex_lock(&bus->device_lock);
|
||||
me_cl = mei_me_cl_by_uuid(bus, &mei_amthif_guid);
|
||||
if (me_cl)
|
||||
mei_amthif_host_init(bus, me_cl);
|
||||
mei_me_cl_put(me_cl);
|
||||
mutex_unlock(&bus->device_lock);
|
||||
|
||||
mei_cl_bus_rescan(bus);
|
||||
}
|
||||
|
||||
+92
-112
@@ -358,8 +358,9 @@ void mei_io_cb_free(struct mei_cl_cb *cb)
|
||||
*
|
||||
* Return: mei_cl_cb pointer or NULL;
|
||||
*/
|
||||
struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, enum mei_cb_file_ops type,
|
||||
const struct file *fp)
|
||||
static struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl,
|
||||
enum mei_cb_file_ops type,
|
||||
const struct file *fp)
|
||||
{
|
||||
struct mei_cl_cb *cb;
|
||||
|
||||
@@ -419,31 +420,6 @@ static inline void mei_io_list_free(struct mei_cl_cb *list, struct mei_cl *cl)
|
||||
__mei_io_list_flush(list, cl, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_io_cb_alloc_buf - allocate callback buffer
|
||||
*
|
||||
* @cb: io callback structure
|
||||
* @length: size of the buffer
|
||||
*
|
||||
* Return: 0 on success
|
||||
* -EINVAL if cb is NULL
|
||||
* -ENOMEM if allocation failed
|
||||
*/
|
||||
int mei_io_cb_alloc_buf(struct mei_cl_cb *cb, size_t length)
|
||||
{
|
||||
if (!cb)
|
||||
return -EINVAL;
|
||||
|
||||
if (length == 0)
|
||||
return 0;
|
||||
|
||||
cb->buf.data = kmalloc(length, GFP_KERNEL);
|
||||
if (!cb->buf.data)
|
||||
return -ENOMEM;
|
||||
cb->buf.size = length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_cl_alloc_cb - a convenient wrapper for allocating read cb
|
||||
*
|
||||
@@ -455,23 +431,58 @@ int mei_io_cb_alloc_buf(struct mei_cl_cb *cb, size_t length)
|
||||
* Return: cb on success and NULL on failure
|
||||
*/
|
||||
struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length,
|
||||
enum mei_cb_file_ops type,
|
||||
enum mei_cb_file_ops fop_type,
|
||||
const struct file *fp)
|
||||
{
|
||||
struct mei_cl_cb *cb;
|
||||
|
||||
cb = mei_io_cb_init(cl, type, fp);
|
||||
cb = mei_io_cb_init(cl, fop_type, fp);
|
||||
if (!cb)
|
||||
return NULL;
|
||||
|
||||
if (mei_io_cb_alloc_buf(cb, length)) {
|
||||
if (length == 0)
|
||||
return cb;
|
||||
|
||||
cb->buf.data = kmalloc(length, GFP_KERNEL);
|
||||
if (!cb->buf.data) {
|
||||
mei_io_cb_free(cb);
|
||||
return NULL;
|
||||
}
|
||||
cb->buf.size = length;
|
||||
|
||||
return cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_cl_enqueue_ctrl_wr_cb - a convenient wrapper for allocating
|
||||
* and enqueuing of the control commands cb
|
||||
*
|
||||
* @cl: host client
|
||||
* @length: size of the buffer
|
||||
* @type: operation type
|
||||
* @fp: associated file pointer (might be NULL)
|
||||
*
|
||||
* Return: cb on success and NULL on failure
|
||||
* Locking: called under "dev->device_lock" lock
|
||||
*/
|
||||
struct mei_cl_cb *mei_cl_enqueue_ctrl_wr_cb(struct mei_cl *cl, size_t length,
|
||||
enum mei_cb_file_ops fop_type,
|
||||
const struct file *fp)
|
||||
{
|
||||
struct mei_cl_cb *cb;
|
||||
|
||||
/* for RX always allocate at least client's mtu */
|
||||
if (length)
|
||||
length = max_t(size_t, length, mei_cl_mtu(cl));
|
||||
|
||||
cb = mei_cl_alloc_cb(cl, length, fop_type, fp);
|
||||
if (!cb)
|
||||
return NULL;
|
||||
|
||||
list_add_tail(&cb->list, &cl->dev->ctrl_wr_list.list);
|
||||
return cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_cl_read_cb - find this cl's callback in the read list
|
||||
* for a specific file
|
||||
@@ -754,7 +765,8 @@ void mei_cl_set_disconnected(struct mei_cl *cl)
|
||||
mei_io_list_flush(&dev->ctrl_rd_list, cl);
|
||||
mei_io_list_flush(&dev->ctrl_wr_list, cl);
|
||||
mei_cl_wake_all(cl);
|
||||
cl->mei_flow_ctrl_creds = 0;
|
||||
cl->rx_flow_ctrl_creds = 0;
|
||||
cl->tx_flow_ctrl_creds = 0;
|
||||
cl->timer_count = 0;
|
||||
|
||||
if (!cl->me_cl)
|
||||
@@ -764,7 +776,7 @@ void mei_cl_set_disconnected(struct mei_cl *cl)
|
||||
cl->me_cl->connect_count--;
|
||||
|
||||
if (cl->me_cl->connect_count == 0)
|
||||
cl->me_cl->mei_flow_ctrl_creds = 0;
|
||||
cl->me_cl->tx_flow_ctrl_creds = 0;
|
||||
|
||||
mei_me_cl_put(cl->me_cl);
|
||||
cl->me_cl = NULL;
|
||||
@@ -814,6 +826,7 @@ static int mei_cl_send_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb)
|
||||
|
||||
list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
|
||||
cl->timer_count = MEI_CONNECT_TIMEOUT;
|
||||
mei_schedule_stall_timer(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -867,13 +880,11 @@ static int __mei_cl_disconnect(struct mei_cl *cl)
|
||||
|
||||
cl->state = MEI_FILE_DISCONNECTING;
|
||||
|
||||
cb = mei_io_cb_init(cl, MEI_FOP_DISCONNECT, NULL);
|
||||
rets = cb ? 0 : -ENOMEM;
|
||||
if (rets)
|
||||
cb = mei_cl_enqueue_ctrl_wr_cb(cl, 0, MEI_FOP_DISCONNECT, NULL);
|
||||
if (!cb) {
|
||||
rets = -ENOMEM;
|
||||
goto out;
|
||||
|
||||
cl_dbg(dev, cl, "add disconnect cb to control write list\n");
|
||||
list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
|
||||
}
|
||||
|
||||
if (mei_hbuf_acquire(dev)) {
|
||||
rets = mei_cl_send_disconnect(cl, cb);
|
||||
@@ -1001,6 +1012,7 @@ static int mei_cl_send_connect(struct mei_cl *cl, struct mei_cl_cb *cb)
|
||||
|
||||
list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
|
||||
cl->timer_count = MEI_CONNECT_TIMEOUT;
|
||||
mei_schedule_stall_timer(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1042,14 +1054,14 @@ int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,
|
||||
*
|
||||
* @cl: host client
|
||||
* @me_cl: me client
|
||||
* @file: pointer to file structure
|
||||
* @fp: pointer to file structure
|
||||
*
|
||||
* Locking: called under "dev->device_lock" lock
|
||||
*
|
||||
* Return: 0 on success, <0 on failure.
|
||||
*/
|
||||
int mei_cl_connect(struct mei_cl *cl, struct mei_me_client *me_cl,
|
||||
const struct file *file)
|
||||
const struct file *fp)
|
||||
{
|
||||
struct mei_device *dev;
|
||||
struct mei_cl_cb *cb;
|
||||
@@ -1076,12 +1088,11 @@ int mei_cl_connect(struct mei_cl *cl, struct mei_me_client *me_cl,
|
||||
goto nortpm;
|
||||
}
|
||||
|
||||
cb = mei_io_cb_init(cl, MEI_FOP_CONNECT, file);
|
||||
rets = cb ? 0 : -ENOMEM;
|
||||
if (rets)
|
||||
cb = mei_cl_enqueue_ctrl_wr_cb(cl, 0, MEI_FOP_CONNECT, fp);
|
||||
if (!cb) {
|
||||
rets = -ENOMEM;
|
||||
goto out;
|
||||
|
||||
list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
|
||||
}
|
||||
|
||||
/* run hbuf acquire last so we don't have to undo */
|
||||
if (!mei_cl_is_other_connecting(cl) && mei_hbuf_acquire(dev)) {
|
||||
@@ -1159,50 +1170,42 @@ err:
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* mei_cl_flow_ctrl_creds - checks flow_control credits for cl.
|
||||
* mei_cl_tx_flow_ctrl_creds - checks flow_control credits for cl.
|
||||
*
|
||||
* @cl: host client
|
||||
* @fp: the file pointer associated with the pointer
|
||||
*
|
||||
* Return: 1 if mei_flow_ctrl_creds >0, 0 - otherwise.
|
||||
* Return: 1 if tx_flow_ctrl_creds >0, 0 - otherwise.
|
||||
*/
|
||||
static int mei_cl_flow_ctrl_creds(struct mei_cl *cl, const struct file *fp)
|
||||
static int mei_cl_tx_flow_ctrl_creds(struct mei_cl *cl)
|
||||
{
|
||||
int rets;
|
||||
|
||||
if (WARN_ON(!cl || !cl->me_cl))
|
||||
return -EINVAL;
|
||||
|
||||
if (cl->mei_flow_ctrl_creds > 0)
|
||||
if (cl->tx_flow_ctrl_creds > 0)
|
||||
return 1;
|
||||
|
||||
if (mei_cl_is_fixed_address(cl)) {
|
||||
rets = mei_cl_read_start(cl, mei_cl_mtu(cl), fp);
|
||||
if (rets && rets != -EBUSY)
|
||||
return rets;
|
||||
if (mei_cl_is_fixed_address(cl))
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mei_cl_is_single_recv_buf(cl)) {
|
||||
if (cl->me_cl->mei_flow_ctrl_creds > 0)
|
||||
if (cl->me_cl->tx_flow_ctrl_creds > 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_cl_flow_ctrl_reduce - reduces flow_control.
|
||||
* mei_cl_tx_flow_ctrl_creds_reduce - reduces transmit flow control credits
|
||||
* for a client
|
||||
*
|
||||
* @cl: private data of the file object
|
||||
* @cl: host client
|
||||
*
|
||||
* Return:
|
||||
* 0 on success
|
||||
* -EINVAL when ctrl credits are <= 0
|
||||
*/
|
||||
static int mei_cl_flow_ctrl_reduce(struct mei_cl *cl)
|
||||
static int mei_cl_tx_flow_ctrl_creds_reduce(struct mei_cl *cl)
|
||||
{
|
||||
if (WARN_ON(!cl || !cl->me_cl))
|
||||
return -EINVAL;
|
||||
@@ -1211,13 +1214,13 @@ static int mei_cl_flow_ctrl_reduce(struct mei_cl *cl)
|
||||
return 0;
|
||||
|
||||
if (mei_cl_is_single_recv_buf(cl)) {
|
||||
if (WARN_ON(cl->me_cl->mei_flow_ctrl_creds <= 0))
|
||||
if (WARN_ON(cl->me_cl->tx_flow_ctrl_creds <= 0))
|
||||
return -EINVAL;
|
||||
cl->me_cl->mei_flow_ctrl_creds--;
|
||||
cl->me_cl->tx_flow_ctrl_creds--;
|
||||
} else {
|
||||
if (WARN_ON(cl->mei_flow_ctrl_creds <= 0))
|
||||
if (WARN_ON(cl->tx_flow_ctrl_creds <= 0))
|
||||
return -EINVAL;
|
||||
cl->mei_flow_ctrl_creds--;
|
||||
cl->tx_flow_ctrl_creds--;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1292,7 +1295,7 @@ int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb,
|
||||
* mei_cl_notify_request - send notification stop/start request
|
||||
*
|
||||
* @cl: host client
|
||||
* @file: associate request with file
|
||||
* @fp: associate request with file
|
||||
* @request: 1 for start or 0 for stop
|
||||
*
|
||||
* Locking: called under "dev->device_lock" lock
|
||||
@@ -1300,7 +1303,7 @@ int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb,
|
||||
* Return: 0 on such and error otherwise.
|
||||
*/
|
||||
int mei_cl_notify_request(struct mei_cl *cl,
|
||||
const struct file *file, u8 request)
|
||||
const struct file *fp, u8 request)
|
||||
{
|
||||
struct mei_device *dev;
|
||||
struct mei_cl_cb *cb;
|
||||
@@ -1325,7 +1328,7 @@ int mei_cl_notify_request(struct mei_cl *cl,
|
||||
}
|
||||
|
||||
fop_type = mei_cl_notify_req2fop(request);
|
||||
cb = mei_io_cb_init(cl, fop_type, file);
|
||||
cb = mei_cl_enqueue_ctrl_wr_cb(cl, 0, fop_type, fp);
|
||||
if (!cb) {
|
||||
rets = -ENOMEM;
|
||||
goto out;
|
||||
@@ -1336,9 +1339,7 @@ int mei_cl_notify_request(struct mei_cl *cl,
|
||||
rets = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
|
||||
} else {
|
||||
list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
|
||||
list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
|
||||
}
|
||||
|
||||
mutex_unlock(&dev->device_lock);
|
||||
@@ -1435,25 +1436,6 @@ out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_cl_is_read_fc_cb - check if read cb is waiting for flow control
|
||||
* for given host client
|
||||
*
|
||||
* @cl: host client
|
||||
*
|
||||
* Return: true, if found at least one cb.
|
||||
*/
|
||||
static bool mei_cl_is_read_fc_cb(struct mei_cl *cl)
|
||||
{
|
||||
struct mei_device *dev = cl->dev;
|
||||
struct mei_cl_cb *cb;
|
||||
|
||||
list_for_each_entry(cb, &dev->ctrl_wr_list.list, list)
|
||||
if (cb->fop_type == MEI_FOP_READ && cb->cl == cl)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_cl_read_start - the start read client message function.
|
||||
*
|
||||
@@ -1477,26 +1459,22 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length, const struct file *fp)
|
||||
if (!mei_cl_is_connected(cl))
|
||||
return -ENODEV;
|
||||
|
||||
/* HW currently supports only one pending read */
|
||||
if (!list_empty(&cl->rd_pending) || mei_cl_is_read_fc_cb(cl))
|
||||
return -EBUSY;
|
||||
|
||||
if (!mei_me_cl_is_active(cl->me_cl)) {
|
||||
cl_err(dev, cl, "no such me client\n");
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
/* always allocate at least client max message */
|
||||
length = max_t(size_t, length, mei_cl_mtu(cl));
|
||||
cb = mei_cl_alloc_cb(cl, length, MEI_FOP_READ, fp);
|
||||
if (mei_cl_is_fixed_address(cl) || cl == &dev->iamthif_cl)
|
||||
return 0;
|
||||
|
||||
/* HW currently supports only one pending read */
|
||||
if (cl->rx_flow_ctrl_creds)
|
||||
return -EBUSY;
|
||||
|
||||
cb = mei_cl_enqueue_ctrl_wr_cb(cl, length, MEI_FOP_READ, fp);
|
||||
if (!cb)
|
||||
return -ENOMEM;
|
||||
|
||||
if (mei_cl_is_fixed_address(cl)) {
|
||||
list_add_tail(&cb->list, &cl->rd_pending);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rets = pm_runtime_get(dev->dev);
|
||||
if (rets < 0 && rets != -EINPROGRESS) {
|
||||
pm_runtime_put_noidle(dev->dev);
|
||||
@@ -1504,16 +1482,15 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length, const struct file *fp)
|
||||
goto nortpm;
|
||||
}
|
||||
|
||||
rets = 0;
|
||||
if (mei_hbuf_acquire(dev)) {
|
||||
rets = mei_hbm_cl_flow_control_req(dev, cl);
|
||||
if (rets < 0)
|
||||
goto out;
|
||||
|
||||
list_add_tail(&cb->list, &cl->rd_pending);
|
||||
} else {
|
||||
rets = 0;
|
||||
list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
|
||||
list_move_tail(&cb->list, &cl->rd_pending);
|
||||
}
|
||||
cl->rx_flow_ctrl_creds++;
|
||||
|
||||
out:
|
||||
cl_dbg(dev, cl, "rpm: autosuspend\n");
|
||||
@@ -1557,7 +1534,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
|
||||
|
||||
first_chunk = cb->buf_idx == 0;
|
||||
|
||||
rets = first_chunk ? mei_cl_flow_ctrl_creds(cl, cb->fp) : 1;
|
||||
rets = first_chunk ? mei_cl_tx_flow_ctrl_creds(cl) : 1;
|
||||
if (rets < 0)
|
||||
return rets;
|
||||
|
||||
@@ -1605,7 +1582,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
|
||||
cb->completed = mei_hdr.msg_complete == 1;
|
||||
|
||||
if (first_chunk) {
|
||||
if (mei_cl_flow_ctrl_reduce(cl))
|
||||
if (mei_cl_tx_flow_ctrl_creds_reduce(cl))
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -1663,7 +1640,7 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
|
||||
mei_hdr.msg_complete = 0;
|
||||
mei_hdr.internal = cb->internal;
|
||||
|
||||
rets = mei_cl_flow_ctrl_creds(cl, cb->fp);
|
||||
rets = mei_cl_tx_flow_ctrl_creds(cl);
|
||||
if (rets < 0)
|
||||
goto err;
|
||||
|
||||
@@ -1691,7 +1668,7 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
|
||||
if (rets)
|
||||
goto err;
|
||||
|
||||
rets = mei_cl_flow_ctrl_reduce(cl);
|
||||
rets = mei_cl_tx_flow_ctrl_creds_reduce(cl);
|
||||
if (rets)
|
||||
goto err;
|
||||
|
||||
@@ -1761,6 +1738,9 @@ void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb)
|
||||
|
||||
case MEI_FOP_READ:
|
||||
list_add_tail(&cb->list, &cl->rd_completed);
|
||||
if (!mei_cl_is_fixed_address(cl) &&
|
||||
!WARN_ON(!cl->rx_flow_ctrl_creds))
|
||||
cl->rx_flow_ctrl_creds--;
|
||||
if (!mei_cl_bus_rx_event(cl))
|
||||
wake_up_interruptible(&cl->rx_wait);
|
||||
break;
|
||||
|
||||
@@ -82,11 +82,7 @@ static inline u8 mei_me_cl_ver(const struct mei_me_client *me_cl)
|
||||
/*
|
||||
* MEI IO Functions
|
||||
*/
|
||||
struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, enum mei_cb_file_ops type,
|
||||
const struct file *fp);
|
||||
void mei_io_cb_free(struct mei_cl_cb *priv_cb);
|
||||
int mei_io_cb_alloc_buf(struct mei_cl_cb *cb, size_t length);
|
||||
|
||||
|
||||
/**
|
||||
* mei_io_list_init - Sets up a queue list.
|
||||
@@ -118,6 +114,9 @@ void mei_cl_read_cb_flush(const struct mei_cl *cl, const struct file *fp);
|
||||
struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length,
|
||||
enum mei_cb_file_ops type,
|
||||
const struct file *fp);
|
||||
struct mei_cl_cb *mei_cl_enqueue_ctrl_wr_cb(struct mei_cl *cl, size_t length,
|
||||
enum mei_cb_file_ops type,
|
||||
const struct file *fp);
|
||||
int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp);
|
||||
|
||||
/*
|
||||
|
||||
+26
-23
@@ -161,6 +161,7 @@ void mei_hbm_cl_hdr(struct mei_cl *cl, u8 hbm_cmd, void *buf, size_t len)
|
||||
* @dev: the device structure
|
||||
* @cl: client
|
||||
* @hbm_cmd: host bus message command
|
||||
* @buf: message buffer
|
||||
* @len: buffer length
|
||||
*
|
||||
* Return: 0 on success, <0 on failure.
|
||||
@@ -276,6 +277,7 @@ int mei_hbm_start_req(struct mei_device *dev)
|
||||
|
||||
dev->hbm_state = MEI_HBM_STARTING;
|
||||
dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
|
||||
mei_schedule_stall_timer(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -311,6 +313,7 @@ static int mei_hbm_enum_clients_req(struct mei_device *dev)
|
||||
}
|
||||
dev->hbm_state = MEI_HBM_ENUM_CLIENTS;
|
||||
dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
|
||||
mei_schedule_stall_timer(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -339,7 +342,7 @@ static int mei_hbm_me_cl_add(struct mei_device *dev,
|
||||
|
||||
me_cl->props = res->client_properties;
|
||||
me_cl->client_id = res->me_addr;
|
||||
me_cl->mei_flow_ctrl_creds = 0;
|
||||
me_cl->tx_flow_ctrl_creds = 0;
|
||||
|
||||
mei_me_cl_add(dev, me_cl);
|
||||
|
||||
@@ -561,6 +564,7 @@ static int mei_hbm_prop_req(struct mei_device *dev, unsigned long start_idx)
|
||||
}
|
||||
|
||||
dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
|
||||
mei_schedule_stall_timer(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -636,23 +640,22 @@ int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl)
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_hbm_add_single_flow_creds - adds single buffer credentials.
|
||||
* mei_hbm_add_single_tx_flow_ctrl_creds - adds single buffer credentials.
|
||||
*
|
||||
* @dev: the device structure
|
||||
* @flow: flow control.
|
||||
* @fctrl: flow control response bus message
|
||||
*
|
||||
* Return: 0 on success, < 0 otherwise
|
||||
*/
|
||||
static int mei_hbm_add_single_flow_creds(struct mei_device *dev,
|
||||
struct hbm_flow_control *flow)
|
||||
static int mei_hbm_add_single_tx_flow_ctrl_creds(struct mei_device *dev,
|
||||
struct hbm_flow_control *fctrl)
|
||||
{
|
||||
struct mei_me_client *me_cl;
|
||||
int rets;
|
||||
|
||||
me_cl = mei_me_cl_by_id(dev, flow->me_addr);
|
||||
me_cl = mei_me_cl_by_id(dev, fctrl->me_addr);
|
||||
if (!me_cl) {
|
||||
dev_err(dev->dev, "no such me client %d\n",
|
||||
flow->me_addr);
|
||||
dev_err(dev->dev, "no such me client %d\n", fctrl->me_addr);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@@ -661,9 +664,9 @@ static int mei_hbm_add_single_flow_creds(struct mei_device *dev,
|
||||
goto out;
|
||||
}
|
||||
|
||||
me_cl->mei_flow_ctrl_creds++;
|
||||
me_cl->tx_flow_ctrl_creds++;
|
||||
dev_dbg(dev->dev, "recv flow ctrl msg ME %d (single) creds = %d.\n",
|
||||
flow->me_addr, me_cl->mei_flow_ctrl_creds);
|
||||
fctrl->me_addr, me_cl->tx_flow_ctrl_creds);
|
||||
|
||||
rets = 0;
|
||||
out:
|
||||
@@ -675,24 +678,24 @@ out:
|
||||
* mei_hbm_cl_flow_control_res - flow control response from me
|
||||
*
|
||||
* @dev: the device structure
|
||||
* @flow_control: flow control response bus message
|
||||
* @fctrl: flow control response bus message
|
||||
*/
|
||||
static void mei_hbm_cl_flow_control_res(struct mei_device *dev,
|
||||
struct hbm_flow_control *flow_control)
|
||||
static void mei_hbm_cl_tx_flow_ctrl_creds_res(struct mei_device *dev,
|
||||
struct hbm_flow_control *fctrl)
|
||||
{
|
||||
struct mei_cl *cl;
|
||||
|
||||
if (!flow_control->host_addr) {
|
||||
if (!fctrl->host_addr) {
|
||||
/* single receive buffer */
|
||||
mei_hbm_add_single_flow_creds(dev, flow_control);
|
||||
mei_hbm_add_single_tx_flow_ctrl_creds(dev, fctrl);
|
||||
return;
|
||||
}
|
||||
|
||||
cl = mei_hbm_cl_find_by_cmd(dev, flow_control);
|
||||
cl = mei_hbm_cl_find_by_cmd(dev, fctrl);
|
||||
if (cl) {
|
||||
cl->mei_flow_ctrl_creds++;
|
||||
cl->tx_flow_ctrl_creds++;
|
||||
cl_dbg(dev, cl, "flow control creds = %d.\n",
|
||||
cl->mei_flow_ctrl_creds);
|
||||
cl->tx_flow_ctrl_creds);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -871,10 +874,10 @@ static int mei_hbm_fw_disconnect_req(struct mei_device *dev,
|
||||
cl->state = MEI_FILE_DISCONNECTING;
|
||||
cl->timer_count = 0;
|
||||
|
||||
cb = mei_io_cb_init(cl, MEI_FOP_DISCONNECT_RSP, NULL);
|
||||
cb = mei_cl_enqueue_ctrl_wr_cb(cl, 0, MEI_FOP_DISCONNECT_RSP,
|
||||
NULL);
|
||||
if (!cb)
|
||||
return -ENOMEM;
|
||||
list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1022,7 +1025,7 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
|
||||
|
||||
struct mei_hbm_cl_cmd *cl_cmd;
|
||||
struct hbm_client_connect_request *disconnect_req;
|
||||
struct hbm_flow_control *flow_control;
|
||||
struct hbm_flow_control *fctrl;
|
||||
|
||||
/* read the message to our buffer */
|
||||
BUG_ON(hdr->length >= sizeof(dev->rd_msg_buf));
|
||||
@@ -1102,8 +1105,8 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
|
||||
case MEI_FLOW_CONTROL_CMD:
|
||||
dev_dbg(dev->dev, "hbm: client flow control response: message received.\n");
|
||||
|
||||
flow_control = (struct hbm_flow_control *) mei_msg;
|
||||
mei_hbm_cl_flow_control_res(dev, flow_control);
|
||||
fctrl = (struct hbm_flow_control *)mei_msg;
|
||||
mei_hbm_cl_tx_flow_ctrl_creds_res(dev, fctrl);
|
||||
break;
|
||||
|
||||
case MEI_PG_ISOLATION_ENTRY_RES_CMD:
|
||||
|
||||
@@ -125,6 +125,9 @@
|
||||
#define MEI_DEV_ID_BXT_M 0x1A9A /* Broxton M */
|
||||
#define MEI_DEV_ID_APL_I 0x5A9A /* Apollo Lake I */
|
||||
|
||||
#define MEI_DEV_ID_KBP 0xA2BA /* Kaby Point */
|
||||
#define MEI_DEV_ID_KBP_2 0xA2BB /* Kaby Point 2 */
|
||||
|
||||
/*
|
||||
* MEI HW Section
|
||||
*/
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include "mei_dev.h"
|
||||
#include "hbm.h"
|
||||
@@ -1063,6 +1064,8 @@ static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
|
||||
}
|
||||
}
|
||||
|
||||
pm_runtime_set_active(dev->dev);
|
||||
|
||||
hcsr = mei_hcsr_read(dev);
|
||||
/* H_RST may be found lit before reset is started,
|
||||
* for example if preceding reset flow hasn't completed.
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/irqreturn.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <linux/mei.h>
|
||||
|
||||
@@ -935,6 +936,8 @@ static int mei_txe_hw_start(struct mei_device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
pm_runtime_set_active(dev->dev);
|
||||
|
||||
/* enable input ready interrupts:
|
||||
* SEC_IPC_HOST_INT_MASK.IPC_INPUT_READY_INT_MASK
|
||||
*/
|
||||
|
||||
@@ -94,7 +94,7 @@ void mei_cancel_work(struct mei_device *dev)
|
||||
cancel_work_sync(&dev->reset_work);
|
||||
cancel_work_sync(&dev->bus_rescan_work);
|
||||
|
||||
cancel_delayed_work(&dev->timer_work);
|
||||
cancel_delayed_work_sync(&dev->timer_work);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mei_cancel_work);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user