CHAR/MISC patches for 3.6-rc1
Here's the "big" pull request for 3.6-rc1 for the char/misc drivers. It's really just a few updates to the mei driver, plus 4 other tiny patches, nothing big at all. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.18 (GNU/Linux) iEYEABECAAYFAlARf9IACgkQMUfUDdst+ymMWwCeJD2h/CN1UDRP+7zqxcEmQ70N 9oMAoJrZnvbqTIGmq7zZAMITO9zCbWqi =Kke0 -----END PGP SIGNATURE----- Merge tag 'char-misc-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc Pull char/misc patches from Greg Kroah-Hartman: "Here's the "big" pull request for 3.6-rc1 for the char/misc drivers. It's really just a few updates to the mei driver, plus 4 other tiny patches, nothing big at all. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>" * tag 'char-misc-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: mei: use module_pci_driver powerpc/BSR: cleanup the error path of bsr_init mei: mei_irq_thread_write_handler - line break fix mei: streamline the _mei_irq_thread_close/ioctol functions mei: introduce mei_data2slots wrapper mei: mei_wd_host_init: update the comment mei: remove write only wariable wd_due_counter mei: mei_device can be const for mei register access functions mei: revamp host buffer interface function mei: don't query HCSR for host buffer depth mei: group wd_interface_reg with watchdog variables within struct mei_device mei: mei_irq_thread_write_handler check for overflow mei: make mei_write_message more readable mei: check for error codes that mei_flow_ctrl_creds retuns misc: at25: Parse dt settings misc: hpilo: increase number of max supported channels mei: mei.txt: minor grammar fixes
This commit is contained in:
commit
b84382f514
|
@ -0,0 +1,21 @@
|
||||||
|
Atmel AT25 eeprom
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible : "atmel,at25".
|
||||||
|
- reg : chip select number
|
||||||
|
- spi-max-frequency : max spi frequency to use
|
||||||
|
|
||||||
|
- at25,byte-len : total eeprom size in bytes
|
||||||
|
- at25,addr-mode : addr-mode flags, as defined in include/linux/spi/eeprom.h
|
||||||
|
- at25,page-size : size of the eeprom page
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
at25@0 {
|
||||||
|
compatible = "atmel,at25";
|
||||||
|
reg = <0>
|
||||||
|
spi-max-frequency = <5000000>;
|
||||||
|
|
||||||
|
at25,byte-len = <0x8000>;
|
||||||
|
at25,addr-mode = <2>;
|
||||||
|
at25,page-size = <64>;
|
||||||
|
};
|
|
@ -50,25 +50,25 @@ Intel MEI Driver
|
||||||
The driver exposes a misc device called /dev/mei.
|
The driver exposes a misc device called /dev/mei.
|
||||||
|
|
||||||
An application maintains communication with an Intel ME feature while
|
An application maintains communication with an Intel ME feature while
|
||||||
/dev/mei is open. The binding to a specific features is performed by calling
|
/dev/mei is open. The binding to a specific feature is performed by calling
|
||||||
MEI_CONNECT_CLIENT_IOCTL, which passes the desired UUID.
|
MEI_CONNECT_CLIENT_IOCTL, which passes the desired UUID.
|
||||||
The number of instances of an Intel ME feature that can be opened
|
The number of instances of an Intel ME feature that can be opened
|
||||||
at the same time depends on the Intel ME feature, but most of the
|
at the same time depends on the Intel ME feature, but most of the
|
||||||
features allow only a single instance.
|
features allow only a single instance.
|
||||||
|
|
||||||
The Intel AMT Host Interface (Intel AMTHI) feature supports multiple
|
The Intel AMT Host Interface (Intel AMTHI) feature supports multiple
|
||||||
simultaneous user applications. Therefore, the Intel MEI driver handles
|
simultaneous user connected applications. The Intel MEI driver
|
||||||
this internally by maintaining request queues for the applications.
|
handles this internally by maintaining request queues for the applications.
|
||||||
|
|
||||||
The driver is oblivious to data that is passed between firmware feature
|
The driver is transparent to data that are passed between firmware feature
|
||||||
and host application.
|
and host application.
|
||||||
|
|
||||||
Because some of the Intel ME features can change the system
|
Because some of the Intel ME features can change the system
|
||||||
configuration, the driver by default allows only a privileged
|
configuration, the driver by default allows only a privileged
|
||||||
user to access it.
|
user to access it.
|
||||||
|
|
||||||
A code snippet for an application communicating with
|
A code snippet for an application communicating with Intel AMTHI client:
|
||||||
Intel AMTHI client:
|
|
||||||
struct mei_connect_client_data data;
|
struct mei_connect_client_data data;
|
||||||
fd = open(MEI_DEVICE);
|
fd = open(MEI_DEVICE);
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ The Intel AMT Watchdog is composed of two parts:
|
||||||
2) Intel MEI driver - connects to the watchdog feature, configures the
|
2) Intel MEI driver - connects to the watchdog feature, configures the
|
||||||
watchdog and sends the heartbeats.
|
watchdog and sends the heartbeats.
|
||||||
|
|
||||||
The Intel MEI driver uses the kernel watchdog to configure the Intel AMT
|
The Intel MEI driver uses the kernel watchdog API to configure the Intel AMT
|
||||||
Watchdog and to send heartbeats to it. The default timeout of the
|
Watchdog and to send heartbeats to it. The default timeout of the
|
||||||
watchdog is 120 seconds.
|
watchdog is 120 seconds.
|
||||||
|
|
||||||
|
|
|
@ -297,7 +297,6 @@ static int __init bsr_init(void)
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
dev_t bsr_dev;
|
dev_t bsr_dev;
|
||||||
int ret = -ENODEV;
|
int ret = -ENODEV;
|
||||||
int result;
|
|
||||||
|
|
||||||
np = of_find_compatible_node(NULL, NULL, "ibm,bsr");
|
np = of_find_compatible_node(NULL, NULL, "ibm,bsr");
|
||||||
if (!np)
|
if (!np)
|
||||||
|
@ -306,13 +305,14 @@ static int __init bsr_init(void)
|
||||||
bsr_class = class_create(THIS_MODULE, "bsr");
|
bsr_class = class_create(THIS_MODULE, "bsr");
|
||||||
if (IS_ERR(bsr_class)) {
|
if (IS_ERR(bsr_class)) {
|
||||||
printk(KERN_ERR "class_create() failed for bsr_class\n");
|
printk(KERN_ERR "class_create() failed for bsr_class\n");
|
||||||
|
ret = PTR_ERR(bsr_class);
|
||||||
goto out_err_1;
|
goto out_err_1;
|
||||||
}
|
}
|
||||||
bsr_class->dev_attrs = bsr_dev_attrs;
|
bsr_class->dev_attrs = bsr_dev_attrs;
|
||||||
|
|
||||||
result = alloc_chrdev_region(&bsr_dev, 0, BSR_MAX_DEVS, "bsr");
|
ret = alloc_chrdev_region(&bsr_dev, 0, BSR_MAX_DEVS, "bsr");
|
||||||
bsr_major = MAJOR(bsr_dev);
|
bsr_major = MAJOR(bsr_dev);
|
||||||
if (result < 0) {
|
if (ret < 0) {
|
||||||
printk(KERN_ERR "alloc_chrdev_region() failed for bsr\n");
|
printk(KERN_ERR "alloc_chrdev_region() failed for bsr\n");
|
||||||
goto out_err_2;
|
goto out_err_2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
#include <linux/spi/spi.h>
|
#include <linux/spi/spi.h>
|
||||||
#include <linux/spi/eeprom.h>
|
#include <linux/spi/eeprom.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE: this is an *EEPROM* driver. The vagaries of product naming
|
* NOTE: this is an *EEPROM* driver. The vagaries of product naming
|
||||||
|
@ -305,25 +305,54 @@ static ssize_t at25_mem_write(struct memory_accessor *mem, const char *buf,
|
||||||
static int at25_probe(struct spi_device *spi)
|
static int at25_probe(struct spi_device *spi)
|
||||||
{
|
{
|
||||||
struct at25_data *at25 = NULL;
|
struct at25_data *at25 = NULL;
|
||||||
const struct spi_eeprom *chip;
|
struct spi_eeprom chip;
|
||||||
|
struct device_node *np = spi->dev.of_node;
|
||||||
int err;
|
int err;
|
||||||
int sr;
|
int sr;
|
||||||
int addrlen;
|
int addrlen;
|
||||||
|
|
||||||
/* Chip description */
|
/* Chip description */
|
||||||
chip = spi->dev.platform_data;
|
if (!spi->dev.platform_data) {
|
||||||
if (!chip) {
|
if (np) {
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
memset(&chip, 0, sizeof(chip));
|
||||||
|
strncpy(chip.name, np->name, 10);
|
||||||
|
|
||||||
|
err = of_property_read_u32(np, "at25,byte-len", &val);
|
||||||
|
if (err) {
|
||||||
|
dev_dbg(&spi->dev, "invalid chip dt description\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
chip.byte_len = val;
|
||||||
|
|
||||||
|
err = of_property_read_u32(np, "at25,addr-mode", &val);
|
||||||
|
if (err) {
|
||||||
|
dev_dbg(&spi->dev, "invalid chip dt description\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
chip.flags = (u16)val;
|
||||||
|
|
||||||
|
err = of_property_read_u32(np, "at25,page-size", &val);
|
||||||
|
if (err) {
|
||||||
|
dev_dbg(&spi->dev, "invalid chip dt description\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
chip.page_size = (u16)val;
|
||||||
|
} else {
|
||||||
dev_dbg(&spi->dev, "no chip description\n");
|
dev_dbg(&spi->dev, "no chip description\n");
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
} else
|
||||||
|
chip = *(struct spi_eeprom *)spi->dev.platform_data;
|
||||||
|
|
||||||
/* For now we only support 8/16/24 bit addressing */
|
/* For now we only support 8/16/24 bit addressing */
|
||||||
if (chip->flags & EE_ADDR1)
|
if (chip.flags & EE_ADDR1)
|
||||||
addrlen = 1;
|
addrlen = 1;
|
||||||
else if (chip->flags & EE_ADDR2)
|
else if (chip.flags & EE_ADDR2)
|
||||||
addrlen = 2;
|
addrlen = 2;
|
||||||
else if (chip->flags & EE_ADDR3)
|
else if (chip.flags & EE_ADDR3)
|
||||||
addrlen = 3;
|
addrlen = 3;
|
||||||
else {
|
else {
|
||||||
dev_dbg(&spi->dev, "unsupported address type\n");
|
dev_dbg(&spi->dev, "unsupported address type\n");
|
||||||
|
@ -348,7 +377,7 @@ static int at25_probe(struct spi_device *spi)
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_init(&at25->lock);
|
mutex_init(&at25->lock);
|
||||||
at25->chip = *chip;
|
at25->chip = chip;
|
||||||
at25->spi = spi_dev_get(spi);
|
at25->spi = spi_dev_get(spi);
|
||||||
dev_set_drvdata(&spi->dev, at25);
|
dev_set_drvdata(&spi->dev, at25);
|
||||||
at25->addrlen = addrlen;
|
at25->addrlen = addrlen;
|
||||||
|
@ -369,7 +398,7 @@ static int at25_probe(struct spi_device *spi)
|
||||||
at25->mem.read = at25_mem_read;
|
at25->mem.read = at25_mem_read;
|
||||||
|
|
||||||
at25->bin.size = at25->chip.byte_len;
|
at25->bin.size = at25->chip.byte_len;
|
||||||
if (!(chip->flags & EE_READONLY)) {
|
if (!(chip.flags & EE_READONLY)) {
|
||||||
at25->bin.write = at25_bin_write;
|
at25->bin.write = at25_bin_write;
|
||||||
at25->bin.attr.mode |= S_IWUSR;
|
at25->bin.attr.mode |= S_IWUSR;
|
||||||
at25->mem.write = at25_mem_write;
|
at25->mem.write = at25_mem_write;
|
||||||
|
@ -379,8 +408,8 @@ static int at25_probe(struct spi_device *spi)
|
||||||
if (err)
|
if (err)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (chip->setup)
|
if (chip.setup)
|
||||||
chip->setup(&at25->mem, chip->context);
|
chip.setup(&at25->mem, chip.context);
|
||||||
|
|
||||||
dev_info(&spi->dev, "%Zd %s %s eeprom%s, pagesize %u\n",
|
dev_info(&spi->dev, "%Zd %s %s eeprom%s, pagesize %u\n",
|
||||||
(at25->bin.size < 1024)
|
(at25->bin.size < 1024)
|
||||||
|
@ -388,7 +417,7 @@ static int at25_probe(struct spi_device *spi)
|
||||||
: (at25->bin.size / 1024),
|
: (at25->bin.size / 1024),
|
||||||
(at25->bin.size < 1024) ? "Byte" : "KByte",
|
(at25->bin.size < 1024) ? "Byte" : "KByte",
|
||||||
at25->chip.name,
|
at25->chip.name,
|
||||||
(chip->flags & EE_READONLY) ? " (readonly)" : "",
|
(chip.flags & EE_READONLY) ? " (readonly)" : "",
|
||||||
at25->chip.page_size);
|
at25->chip.page_size);
|
||||||
return 0;
|
return 0;
|
||||||
fail:
|
fail:
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
static struct class *ilo_class;
|
static struct class *ilo_class;
|
||||||
static unsigned int ilo_major;
|
static unsigned int ilo_major;
|
||||||
|
static unsigned int max_ccb = MIN_CCB;
|
||||||
static char ilo_hwdev[MAX_ILO_DEV];
|
static char ilo_hwdev[MAX_ILO_DEV];
|
||||||
|
|
||||||
static inline int get_entry_id(int entry)
|
static inline int get_entry_id(int entry)
|
||||||
|
@ -424,7 +425,7 @@ static void ilo_set_reset(struct ilo_hwinfo *hw)
|
||||||
* Mapped memory is zeroed on ilo reset, so set a per ccb flag
|
* Mapped memory is zeroed on ilo reset, so set a per ccb flag
|
||||||
* to indicate that this ccb needs to be closed and reopened.
|
* to indicate that this ccb needs to be closed and reopened.
|
||||||
*/
|
*/
|
||||||
for (slot = 0; slot < MAX_CCB; slot++) {
|
for (slot = 0; slot < max_ccb; slot++) {
|
||||||
if (!hw->ccb_alloc[slot])
|
if (!hw->ccb_alloc[slot])
|
||||||
continue;
|
continue;
|
||||||
set_channel_reset(&hw->ccb_alloc[slot]->driver_ccb);
|
set_channel_reset(&hw->ccb_alloc[slot]->driver_ccb);
|
||||||
|
@ -535,7 +536,7 @@ static int ilo_close(struct inode *ip, struct file *fp)
|
||||||
struct ilo_hwinfo *hw;
|
struct ilo_hwinfo *hw;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
slot = iminor(ip) % MAX_CCB;
|
slot = iminor(ip) % max_ccb;
|
||||||
hw = container_of(ip->i_cdev, struct ilo_hwinfo, cdev);
|
hw = container_of(ip->i_cdev, struct ilo_hwinfo, cdev);
|
||||||
|
|
||||||
spin_lock(&hw->open_lock);
|
spin_lock(&hw->open_lock);
|
||||||
|
@ -566,7 +567,7 @@ static int ilo_open(struct inode *ip, struct file *fp)
|
||||||
struct ilo_hwinfo *hw;
|
struct ilo_hwinfo *hw;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
slot = iminor(ip) % MAX_CCB;
|
slot = iminor(ip) % max_ccb;
|
||||||
hw = container_of(ip->i_cdev, struct ilo_hwinfo, cdev);
|
hw = container_of(ip->i_cdev, struct ilo_hwinfo, cdev);
|
||||||
|
|
||||||
/* new ccb allocation */
|
/* new ccb allocation */
|
||||||
|
@ -663,7 +664,7 @@ static irqreturn_t ilo_isr(int irq, void *data)
|
||||||
ilo_set_reset(hw);
|
ilo_set_reset(hw);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < MAX_CCB; i++) {
|
for (i = 0; i < max_ccb; i++) {
|
||||||
if (!hw->ccb_alloc[i])
|
if (!hw->ccb_alloc[i])
|
||||||
continue;
|
continue;
|
||||||
if (pending & (1 << i))
|
if (pending & (1 << i))
|
||||||
|
@ -697,14 +698,14 @@ static int __devinit ilo_map_device(struct pci_dev *pdev, struct ilo_hwinfo *hw)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* map the adapter shared memory region */
|
/* map the adapter shared memory region */
|
||||||
hw->ram_vaddr = pci_iomap(pdev, 2, MAX_CCB * ILOHW_CCB_SZ);
|
hw->ram_vaddr = pci_iomap(pdev, 2, max_ccb * ILOHW_CCB_SZ);
|
||||||
if (hw->ram_vaddr == NULL) {
|
if (hw->ram_vaddr == NULL) {
|
||||||
dev_err(&pdev->dev, "Error mapping shared mem\n");
|
dev_err(&pdev->dev, "Error mapping shared mem\n");
|
||||||
goto mmio_free;
|
goto mmio_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* map the doorbell aperture */
|
/* map the doorbell aperture */
|
||||||
hw->db_vaddr = pci_iomap(pdev, 3, MAX_CCB * ONE_DB_SIZE);
|
hw->db_vaddr = pci_iomap(pdev, 3, max_ccb * ONE_DB_SIZE);
|
||||||
if (hw->db_vaddr == NULL) {
|
if (hw->db_vaddr == NULL) {
|
||||||
dev_err(&pdev->dev, "Error mapping doorbell\n");
|
dev_err(&pdev->dev, "Error mapping doorbell\n");
|
||||||
goto ram_free;
|
goto ram_free;
|
||||||
|
@ -727,7 +728,7 @@ static void ilo_remove(struct pci_dev *pdev)
|
||||||
clear_device(ilo_hw);
|
clear_device(ilo_hw);
|
||||||
|
|
||||||
minor = MINOR(ilo_hw->cdev.dev);
|
minor = MINOR(ilo_hw->cdev.dev);
|
||||||
for (i = minor; i < minor + MAX_CCB; i++)
|
for (i = minor; i < minor + max_ccb; i++)
|
||||||
device_destroy(ilo_class, MKDEV(ilo_major, i));
|
device_destroy(ilo_class, MKDEV(ilo_major, i));
|
||||||
|
|
||||||
cdev_del(&ilo_hw->cdev);
|
cdev_del(&ilo_hw->cdev);
|
||||||
|
@ -737,7 +738,7 @@ static void ilo_remove(struct pci_dev *pdev)
|
||||||
pci_release_regions(pdev);
|
pci_release_regions(pdev);
|
||||||
pci_disable_device(pdev);
|
pci_disable_device(pdev);
|
||||||
kfree(ilo_hw);
|
kfree(ilo_hw);
|
||||||
ilo_hwdev[(minor / MAX_CCB)] = 0;
|
ilo_hwdev[(minor / max_ccb)] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __devinit ilo_probe(struct pci_dev *pdev,
|
static int __devinit ilo_probe(struct pci_dev *pdev,
|
||||||
|
@ -746,6 +747,11 @@ static int __devinit ilo_probe(struct pci_dev *pdev,
|
||||||
int devnum, minor, start, error;
|
int devnum, minor, start, error;
|
||||||
struct ilo_hwinfo *ilo_hw;
|
struct ilo_hwinfo *ilo_hw;
|
||||||
|
|
||||||
|
if (max_ccb > MAX_CCB)
|
||||||
|
max_ccb = MAX_CCB;
|
||||||
|
else if (max_ccb < MIN_CCB)
|
||||||
|
max_ccb = MIN_CCB;
|
||||||
|
|
||||||
/* find a free range for device files */
|
/* find a free range for device files */
|
||||||
for (devnum = 0; devnum < MAX_ILO_DEV; devnum++) {
|
for (devnum = 0; devnum < MAX_ILO_DEV; devnum++) {
|
||||||
if (ilo_hwdev[devnum] == 0) {
|
if (ilo_hwdev[devnum] == 0) {
|
||||||
|
@ -795,14 +801,14 @@ static int __devinit ilo_probe(struct pci_dev *pdev,
|
||||||
|
|
||||||
cdev_init(&ilo_hw->cdev, &ilo_fops);
|
cdev_init(&ilo_hw->cdev, &ilo_fops);
|
||||||
ilo_hw->cdev.owner = THIS_MODULE;
|
ilo_hw->cdev.owner = THIS_MODULE;
|
||||||
start = devnum * MAX_CCB;
|
start = devnum * max_ccb;
|
||||||
error = cdev_add(&ilo_hw->cdev, MKDEV(ilo_major, start), MAX_CCB);
|
error = cdev_add(&ilo_hw->cdev, MKDEV(ilo_major, start), max_ccb);
|
||||||
if (error) {
|
if (error) {
|
||||||
dev_err(&pdev->dev, "Could not add cdev\n");
|
dev_err(&pdev->dev, "Could not add cdev\n");
|
||||||
goto remove_isr;
|
goto remove_isr;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (minor = 0 ; minor < MAX_CCB; minor++) {
|
for (minor = 0 ; minor < max_ccb; minor++) {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
dev = device_create(ilo_class, &pdev->dev,
|
dev = device_create(ilo_class, &pdev->dev,
|
||||||
MKDEV(ilo_major, minor), NULL,
|
MKDEV(ilo_major, minor), NULL,
|
||||||
|
@ -879,11 +885,14 @@ static void __exit ilo_exit(void)
|
||||||
class_destroy(ilo_class);
|
class_destroy(ilo_class);
|
||||||
}
|
}
|
||||||
|
|
||||||
MODULE_VERSION("1.2");
|
MODULE_VERSION("1.3");
|
||||||
MODULE_ALIAS(ILO_NAME);
|
MODULE_ALIAS(ILO_NAME);
|
||||||
MODULE_DESCRIPTION(ILO_NAME);
|
MODULE_DESCRIPTION(ILO_NAME);
|
||||||
MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>");
|
MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
|
||||||
|
module_param(max_ccb, uint, 0444);
|
||||||
|
MODULE_PARM_DESC(max_ccb, "Maximum number of HP iLO channels to attach (8)");
|
||||||
|
|
||||||
module_init(ilo_init);
|
module_init(ilo_init);
|
||||||
module_exit(ilo_exit);
|
module_exit(ilo_exit);
|
||||||
|
|
|
@ -14,7 +14,9 @@
|
||||||
#define ILO_NAME "hpilo"
|
#define ILO_NAME "hpilo"
|
||||||
|
|
||||||
/* max number of open channel control blocks per device, hw limited to 32 */
|
/* max number of open channel control blocks per device, hw limited to 32 */
|
||||||
#define MAX_CCB 8
|
#define MAX_CCB 24
|
||||||
|
/* min number of open channel control blocks per device, hw limited to 32 */
|
||||||
|
#define MIN_CCB 8
|
||||||
/* max number of supported devices */
|
/* max number of supported devices */
|
||||||
#define MAX_ILO_DEV 1
|
#define MAX_ILO_DEV 1
|
||||||
/* max number of files */
|
/* max number of files */
|
||||||
|
|
|
@ -162,6 +162,9 @@ int mei_hw_init(struct mei_device *dev)
|
||||||
if ((dev->host_hw_state & H_IS) == H_IS)
|
if ((dev->host_hw_state & H_IS) == H_IS)
|
||||||
mei_reg_write(dev, H_CSR, dev->host_hw_state);
|
mei_reg_write(dev, H_CSR, dev->host_hw_state);
|
||||||
|
|
||||||
|
/* Doesn't change in runtime */
|
||||||
|
dev->hbuf_depth = (dev->host_hw_state & H_CBD) >> 24;
|
||||||
|
|
||||||
dev->recvd_msg = false;
|
dev->recvd_msg = false;
|
||||||
dev_dbg(&dev->pdev->dev, "reset in start the mei device.\n");
|
dev_dbg(&dev->pdev->dev, "reset in start the mei device.\n");
|
||||||
|
|
||||||
|
@ -303,7 +306,6 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
|
||||||
dev->iamthif_cl.host_client_id);
|
dev->iamthif_cl.host_client_id);
|
||||||
|
|
||||||
mei_reset_iamthif_params(dev);
|
mei_reset_iamthif_params(dev);
|
||||||
dev->wd_due_counter = 0;
|
|
||||||
dev->extra_write_index = 0;
|
dev->extra_write_index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,16 +58,18 @@ void mei_disable_interrupts(struct mei_device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _host_get_filled_slots - gets number of device filled buffer slots
|
* mei_hbuf_filled_slots - gets number of device filled buffer slots
|
||||||
*
|
*
|
||||||
* @device: the device structure
|
* @device: the device structure
|
||||||
*
|
*
|
||||||
* returns number of filled slots
|
* returns number of filled slots
|
||||||
*/
|
*/
|
||||||
static unsigned char _host_get_filled_slots(const struct mei_device *dev)
|
static unsigned char mei_hbuf_filled_slots(struct mei_device *dev)
|
||||||
{
|
{
|
||||||
char read_ptr, write_ptr;
|
char read_ptr, write_ptr;
|
||||||
|
|
||||||
|
dev->host_hw_state = mei_hcsr_read(dev);
|
||||||
|
|
||||||
read_ptr = (char) ((dev->host_hw_state & H_CBRP) >> 8);
|
read_ptr = (char) ((dev->host_hw_state & H_CBRP) >> 8);
|
||||||
write_ptr = (char) ((dev->host_hw_state & H_CBWP) >> 16);
|
write_ptr = (char) ((dev->host_hw_state & H_CBWP) >> 16);
|
||||||
|
|
||||||
|
@ -75,43 +77,33 @@ static unsigned char _host_get_filled_slots(const struct mei_device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mei_host_buffer_is_empty - checks if host buffer is empty.
|
* mei_hbuf_is_empty - checks if host buffer is empty.
|
||||||
*
|
*
|
||||||
* @dev: the device structure
|
* @dev: the device structure
|
||||||
*
|
*
|
||||||
* returns 1 if empty, 0 - otherwise.
|
* returns true if empty, false - otherwise.
|
||||||
*/
|
*/
|
||||||
int mei_host_buffer_is_empty(struct mei_device *dev)
|
bool mei_hbuf_is_empty(struct mei_device *dev)
|
||||||
{
|
{
|
||||||
unsigned char filled_slots;
|
return mei_hbuf_filled_slots(dev) == 0;
|
||||||
|
|
||||||
dev->host_hw_state = mei_hcsr_read(dev);
|
|
||||||
filled_slots = _host_get_filled_slots(dev);
|
|
||||||
|
|
||||||
if (filled_slots == 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mei_count_empty_write_slots - counts write empty slots.
|
* mei_hbuf_empty_slots - counts write empty slots.
|
||||||
*
|
*
|
||||||
* @dev: the device structure
|
* @dev: the device structure
|
||||||
*
|
*
|
||||||
* returns -1(ESLOTS_OVERFLOW) if overflow, otherwise empty slots count
|
* returns -1(ESLOTS_OVERFLOW) if overflow, otherwise empty slots count
|
||||||
*/
|
*/
|
||||||
int mei_count_empty_write_slots(struct mei_device *dev)
|
int mei_hbuf_empty_slots(struct mei_device *dev)
|
||||||
{
|
{
|
||||||
unsigned char buffer_depth, filled_slots, empty_slots;
|
unsigned char filled_slots, empty_slots;
|
||||||
|
|
||||||
dev->host_hw_state = mei_hcsr_read(dev);
|
filled_slots = mei_hbuf_filled_slots(dev);
|
||||||
buffer_depth = (unsigned char) ((dev->host_hw_state & H_CBD) >> 24);
|
empty_slots = dev->hbuf_depth - filled_slots;
|
||||||
filled_slots = _host_get_filled_slots(dev);
|
|
||||||
empty_slots = buffer_depth - filled_slots;
|
|
||||||
|
|
||||||
/* check for overflow */
|
/* check for overflow */
|
||||||
if (filled_slots > buffer_depth)
|
if (filled_slots > dev->hbuf_depth)
|
||||||
return -EOVERFLOW;
|
return -EOVERFLOW;
|
||||||
|
|
||||||
return empty_slots;
|
return empty_slots;
|
||||||
|
@ -127,52 +119,39 @@ int mei_count_empty_write_slots(struct mei_device *dev)
|
||||||
*
|
*
|
||||||
* This function returns -EIO if write has failed
|
* This function returns -EIO if write has failed
|
||||||
*/
|
*/
|
||||||
int mei_write_message(struct mei_device *dev,
|
int mei_write_message(struct mei_device *dev, struct mei_msg_hdr *header,
|
||||||
struct mei_msg_hdr *header,
|
unsigned char *buf, unsigned long length)
|
||||||
unsigned char *write_buffer,
|
|
||||||
unsigned long write_length)
|
|
||||||
{
|
{
|
||||||
u32 temp_msg = 0;
|
unsigned long rem, dw_cnt;
|
||||||
unsigned long bytes_written = 0;
|
u32 *reg_buf = (u32 *)buf;
|
||||||
unsigned char buffer_depth, filled_slots, empty_slots;
|
int i;
|
||||||
unsigned long dw_to_write;
|
int empty_slots;
|
||||||
|
|
||||||
dev->host_hw_state = mei_hcsr_read(dev);
|
|
||||||
|
|
||||||
dev_dbg(&dev->pdev->dev,
|
|
||||||
"host_hw_state = 0x%08x.\n",
|
|
||||||
dev->host_hw_state);
|
|
||||||
|
|
||||||
dev_dbg(&dev->pdev->dev,
|
dev_dbg(&dev->pdev->dev,
|
||||||
"mei_write_message header=%08x.\n",
|
"mei_write_message header=%08x.\n",
|
||||||
*((u32 *) header));
|
*((u32 *) header));
|
||||||
|
|
||||||
buffer_depth = (unsigned char) ((dev->host_hw_state & H_CBD) >> 24);
|
empty_slots = mei_hbuf_empty_slots(dev);
|
||||||
filled_slots = _host_get_filled_slots(dev);
|
dev_dbg(&dev->pdev->dev, "empty slots = %hu.\n", empty_slots);
|
||||||
empty_slots = buffer_depth - filled_slots;
|
|
||||||
dev_dbg(&dev->pdev->dev,
|
|
||||||
"filled = %hu, empty = %hu.\n",
|
|
||||||
filled_slots, empty_slots);
|
|
||||||
|
|
||||||
dw_to_write = ((write_length + 3) / 4);
|
dw_cnt = mei_data2slots(length);
|
||||||
|
if (empty_slots < 0 || dw_cnt > empty_slots)
|
||||||
if (dw_to_write > empty_slots)
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
mei_reg_write(dev, H_CB_WW, *((u32 *) header));
|
mei_reg_write(dev, H_CB_WW, *((u32 *) header));
|
||||||
|
|
||||||
while (write_length >= 4) {
|
for (i = 0; i < length / 4; i++)
|
||||||
mei_reg_write(dev, H_CB_WW,
|
mei_reg_write(dev, H_CB_WW, reg_buf[i]);
|
||||||
*(u32 *) (write_buffer + bytes_written));
|
|
||||||
bytes_written += 4;
|
rem = length & 0x3;
|
||||||
write_length -= 4;
|
if (rem > 0) {
|
||||||
}
|
u32 reg = 0;
|
||||||
|
memcpy(®, &buf[length - rem], rem);
|
||||||
if (write_length > 0) {
|
mei_reg_write(dev, H_CB_WW, reg);
|
||||||
memcpy(&temp_msg, &write_buffer[bytes_written], write_length);
|
|
||||||
mei_reg_write(dev, H_CB_WW, temp_msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dev->host_hw_state = mei_hcsr_read(dev);
|
||||||
dev->host_hw_state |= H_IG;
|
dev->host_hw_state |= H_IG;
|
||||||
mei_hcsr_set(dev);
|
mei_hcsr_set(dev);
|
||||||
dev->me_hw_state = mei_mecsr_read(dev);
|
dev->me_hw_state = mei_mecsr_read(dev);
|
||||||
|
|
|
@ -41,14 +41,28 @@ int mei_write_message(struct mei_device *dev,
|
||||||
unsigned char *write_buffer,
|
unsigned char *write_buffer,
|
||||||
unsigned long write_length);
|
unsigned long write_length);
|
||||||
|
|
||||||
int mei_host_buffer_is_empty(struct mei_device *dev);
|
bool mei_hbuf_is_empty(struct mei_device *dev);
|
||||||
|
|
||||||
|
int mei_hbuf_empty_slots(struct mei_device *dev);
|
||||||
|
|
||||||
|
static inline size_t mei_hbuf_max_data(const struct mei_device *dev)
|
||||||
|
{
|
||||||
|
return dev->hbuf_depth * sizeof(u32) - sizeof(struct mei_msg_hdr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get slots (dwords) from a message length + header (bytes) */
|
||||||
|
static inline unsigned char mei_data2slots(size_t length)
|
||||||
|
{
|
||||||
|
return DIV_ROUND_UP(sizeof(struct mei_msg_hdr) + length, 4);
|
||||||
|
}
|
||||||
|
|
||||||
int mei_count_full_read_slots(struct mei_device *dev);
|
int mei_count_full_read_slots(struct mei_device *dev);
|
||||||
|
|
||||||
int mei_count_empty_write_slots(struct mei_device *dev);
|
|
||||||
|
|
||||||
int mei_flow_ctrl_creds(struct mei_device *dev, struct mei_cl *cl);
|
int mei_flow_ctrl_creds(struct mei_device *dev, struct mei_cl *cl);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int mei_wd_send(struct mei_device *dev);
|
int mei_wd_send(struct mei_device *dev);
|
||||||
int mei_wd_stop(struct mei_device *dev, bool preserve);
|
int mei_wd_stop(struct mei_device *dev, bool preserve);
|
||||||
int mei_wd_host_init(struct mei_device *dev);
|
int mei_wd_host_init(struct mei_device *dev);
|
||||||
|
|
|
@ -267,8 +267,7 @@ static int _mei_irq_thread_iamthif_read(struct mei_device *dev, s32 *slots)
|
||||||
+ sizeof(struct hbm_flow_control))) {
|
+ sizeof(struct hbm_flow_control))) {
|
||||||
return -EMSGSIZE;
|
return -EMSGSIZE;
|
||||||
}
|
}
|
||||||
*slots -= (sizeof(struct mei_msg_hdr) +
|
*slots -= mei_data2slots(sizeof(struct hbm_flow_control));
|
||||||
sizeof(struct hbm_flow_control) + 3) / 4;
|
|
||||||
if (mei_send_flow_control(dev, &dev->iamthif_cl)) {
|
if (mei_send_flow_control(dev, &dev->iamthif_cl)) {
|
||||||
dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n");
|
dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
@ -280,7 +279,7 @@ static int _mei_irq_thread_iamthif_read(struct mei_device *dev, s32 *slots)
|
||||||
dev->iamthif_msg_buf_index = 0;
|
dev->iamthif_msg_buf_index = 0;
|
||||||
dev->iamthif_msg_buf_size = 0;
|
dev->iamthif_msg_buf_size = 0;
|
||||||
dev->iamthif_stall_timer = IAMTHIF_STALL_TIMER;
|
dev->iamthif_stall_timer = IAMTHIF_STALL_TIMER;
|
||||||
dev->mei_host_buffer_is_empty = mei_host_buffer_is_empty(dev);
|
dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,10 +299,11 @@ static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots,
|
||||||
struct mei_cl *cl,
|
struct mei_cl *cl,
|
||||||
struct mei_io_list *cmpl_list)
|
struct mei_io_list *cmpl_list)
|
||||||
{
|
{
|
||||||
if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
|
if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
|
||||||
sizeof(struct hbm_client_disconnect_request))) {
|
sizeof(struct hbm_client_disconnect_request)))
|
||||||
*slots -= (sizeof(struct mei_msg_hdr) +
|
return -EBADMSG;
|
||||||
sizeof(struct hbm_client_disconnect_request) + 3) / 4;
|
|
||||||
|
*slots -= mei_data2slots(sizeof(struct hbm_client_disconnect_request));
|
||||||
|
|
||||||
if (mei_disconnect(dev, cl)) {
|
if (mei_disconnect(dev, cl)) {
|
||||||
cl->status = 0;
|
cl->status = 0;
|
||||||
|
@ -319,10 +319,6 @@ static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots,
|
||||||
&dev->ctrl_rd_list.mei_cb.cb_list);
|
&dev->ctrl_rd_list.mei_cb.cb_list);
|
||||||
cl->timer_count = MEI_CONNECT_TIMEOUT;
|
cl->timer_count = MEI_CONNECT_TIMEOUT;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
/* return the cancel routine */
|
|
||||||
return -EBADMSG;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -575,10 +571,9 @@ static void mei_client_disconnect_request(struct mei_device *dev,
|
||||||
disconnect_req->me_addr);
|
disconnect_req->me_addr);
|
||||||
cl_pos->state = MEI_FILE_DISCONNECTED;
|
cl_pos->state = MEI_FILE_DISCONNECTED;
|
||||||
cl_pos->timer_count = 0;
|
cl_pos->timer_count = 0;
|
||||||
if (cl_pos == &dev->wd_cl) {
|
if (cl_pos == &dev->wd_cl)
|
||||||
dev->wd_due_counter = 0;
|
|
||||||
dev->wd_pending = false;
|
dev->wd_pending = false;
|
||||||
} else if (cl_pos == &dev->iamthif_cl)
|
else if (cl_pos == &dev->iamthif_cl)
|
||||||
dev->iamthif_timer = 0;
|
dev->iamthif_timer = 0;
|
||||||
|
|
||||||
/* prepare disconnect response */
|
/* prepare disconnect response */
|
||||||
|
@ -842,8 +837,8 @@ static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots,
|
||||||
return -EBADMSG;
|
return -EBADMSG;
|
||||||
}
|
}
|
||||||
|
|
||||||
*slots -= (sizeof(struct mei_msg_hdr) +
|
*slots -= mei_data2slots(sizeof(struct hbm_flow_control));
|
||||||
sizeof(struct hbm_flow_control) + 3) / 4;
|
|
||||||
if (mei_send_flow_control(dev, cl)) {
|
if (mei_send_flow_control(dev, cl)) {
|
||||||
cl->status = -ENODEV;
|
cl->status = -ENODEV;
|
||||||
cb_pos->information = 0;
|
cb_pos->information = 0;
|
||||||
|
@ -872,11 +867,15 @@ static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
|
||||||
struct mei_cl *cl,
|
struct mei_cl *cl,
|
||||||
struct mei_io_list *cmpl_list)
|
struct mei_io_list *cmpl_list)
|
||||||
{
|
{
|
||||||
if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
|
if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
|
||||||
sizeof(struct hbm_client_connect_request))) {
|
sizeof(struct hbm_client_connect_request))) {
|
||||||
|
/* return the cancel routine */
|
||||||
|
list_del(&cb_pos->cb_list);
|
||||||
|
return -EBADMSG;
|
||||||
|
}
|
||||||
|
|
||||||
cl->state = MEI_FILE_CONNECTING;
|
cl->state = MEI_FILE_CONNECTING;
|
||||||
*slots -= (sizeof(struct mei_msg_hdr) +
|
*slots -= mei_data2slots(sizeof(struct hbm_client_connect_request));
|
||||||
sizeof(struct hbm_client_connect_request) + 3) / 4;
|
|
||||||
if (mei_connect(dev, cl)) {
|
if (mei_connect(dev, cl)) {
|
||||||
cl->status = -ENODEV;
|
cl->status = -ENODEV;
|
||||||
cb_pos->information = 0;
|
cb_pos->information = 0;
|
||||||
|
@ -887,12 +886,6 @@ static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
|
||||||
&dev->ctrl_rd_list.mei_cb.cb_list);
|
&dev->ctrl_rd_list.mei_cb.cb_list);
|
||||||
cl->timer_count = MEI_CONNECT_TIMEOUT;
|
cl->timer_count = MEI_CONNECT_TIMEOUT;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
/* return the cancel routine */
|
|
||||||
list_del(&cb_pos->cb_list);
|
|
||||||
return -EBADMSG;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -932,8 +925,7 @@ static int _mei_irq_thread_cmpl(struct mei_device *dev, s32 *slots,
|
||||||
cb_pos->information);
|
cb_pos->information);
|
||||||
dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n",
|
dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n",
|
||||||
mei_hdr->length);
|
mei_hdr->length);
|
||||||
*slots -= (sizeof(struct mei_msg_hdr) +
|
*slots -= mei_data2slots(mei_hdr->length);
|
||||||
mei_hdr->length + 3) / 4;
|
|
||||||
if (mei_write_message(dev, mei_hdr,
|
if (mei_write_message(dev, mei_hdr,
|
||||||
(unsigned char *)
|
(unsigned char *)
|
||||||
(cb_pos->request_buffer.data +
|
(cb_pos->request_buffer.data +
|
||||||
|
@ -951,7 +943,7 @@ static int _mei_irq_thread_cmpl(struct mei_device *dev, s32 *slots,
|
||||||
list_move_tail(&cb_pos->cb_list,
|
list_move_tail(&cb_pos->cb_list,
|
||||||
&dev->write_waiting_list.mei_cb.cb_list);
|
&dev->write_waiting_list.mei_cb.cb_list);
|
||||||
}
|
}
|
||||||
} else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) {
|
} else if (*slots == dev->hbuf_depth) {
|
||||||
/* buffer is still empty */
|
/* buffer is still empty */
|
||||||
mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
|
mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
|
||||||
mei_hdr->host_addr = cl->host_client_id;
|
mei_hdr->host_addr = cl->host_client_id;
|
||||||
|
@ -960,9 +952,7 @@ static int _mei_irq_thread_cmpl(struct mei_device *dev, s32 *slots,
|
||||||
(*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
|
(*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
|
||||||
mei_hdr->msg_complete = 0;
|
mei_hdr->msg_complete = 0;
|
||||||
mei_hdr->reserved = 0;
|
mei_hdr->reserved = 0;
|
||||||
|
*slots -= mei_data2slots(mei_hdr->length);
|
||||||
(*slots) -= (sizeof(struct mei_msg_hdr) +
|
|
||||||
mei_hdr->length + 3) / 4;
|
|
||||||
if (mei_write_message(dev, mei_hdr,
|
if (mei_write_message(dev, mei_hdr,
|
||||||
(unsigned char *)
|
(unsigned char *)
|
||||||
(cb_pos->request_buffer.data +
|
(cb_pos->request_buffer.data +
|
||||||
|
@ -1021,8 +1011,7 @@ static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
|
||||||
mei_hdr->msg_complete = 1;
|
mei_hdr->msg_complete = 1;
|
||||||
mei_hdr->reserved = 0;
|
mei_hdr->reserved = 0;
|
||||||
|
|
||||||
*slots -= (sizeof(struct mei_msg_hdr) +
|
*slots -= mei_data2slots(mei_hdr->length);
|
||||||
mei_hdr->length + 3) / 4;
|
|
||||||
|
|
||||||
if (mei_write_message(dev, mei_hdr,
|
if (mei_write_message(dev, mei_hdr,
|
||||||
(dev->iamthif_msg_buf +
|
(dev->iamthif_msg_buf +
|
||||||
|
@ -1046,7 +1035,7 @@ static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
|
||||||
&dev->write_waiting_list.mei_cb.cb_list);
|
&dev->write_waiting_list.mei_cb.cb_list);
|
||||||
|
|
||||||
}
|
}
|
||||||
} else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) {
|
} else if (*slots == dev->hbuf_depth) {
|
||||||
/* buffer is still empty */
|
/* buffer is still empty */
|
||||||
mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
|
mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
|
||||||
mei_hdr->host_addr = cl->host_client_id;
|
mei_hdr->host_addr = cl->host_client_id;
|
||||||
|
@ -1056,8 +1045,7 @@ static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
|
||||||
mei_hdr->msg_complete = 0;
|
mei_hdr->msg_complete = 0;
|
||||||
mei_hdr->reserved = 0;
|
mei_hdr->reserved = 0;
|
||||||
|
|
||||||
*slots -= (sizeof(struct mei_msg_hdr) +
|
*slots -= mei_data2slots(mei_hdr->length);
|
||||||
mei_hdr->length + 3) / 4;
|
|
||||||
|
|
||||||
if (mei_write_message(dev, mei_hdr,
|
if (mei_write_message(dev, mei_hdr,
|
||||||
(dev->iamthif_msg_buf +
|
(dev->iamthif_msg_buf +
|
||||||
|
@ -1199,17 +1187,19 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
|
||||||
struct mei_io_list *list;
|
struct mei_io_list *list;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!mei_host_buffer_is_empty(dev)) {
|
if (!mei_hbuf_is_empty(dev)) {
|
||||||
dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n");
|
dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*slots = mei_count_empty_write_slots(dev);
|
*slots = mei_hbuf_empty_slots(dev);
|
||||||
|
if (*slots <= 0)
|
||||||
|
return -EMSGSIZE;
|
||||||
|
|
||||||
/* complete all waiting for write CB */
|
/* complete all waiting for write CB */
|
||||||
dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n");
|
dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n");
|
||||||
|
|
||||||
list = &dev->write_waiting_list;
|
list = &dev->write_waiting_list;
|
||||||
list_for_each_entry_safe(pos, next,
|
list_for_each_entry_safe(pos, next, &list->mei_cb.cb_list, cb_list) {
|
||||||
&list->mei_cb.cb_list, cb_list) {
|
|
||||||
cl = (struct mei_cl *)pos->file_private;
|
cl = (struct mei_cl *)pos->file_private;
|
||||||
if (cl == NULL)
|
if (cl == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1219,8 +1209,7 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
|
||||||
if (MEI_WRITING == cl->writing_state &&
|
if (MEI_WRITING == cl->writing_state &&
|
||||||
(pos->major_file_operations == MEI_WRITE) &&
|
(pos->major_file_operations == MEI_WRITE) &&
|
||||||
(cl != &dev->iamthif_cl)) {
|
(cl != &dev->iamthif_cl)) {
|
||||||
dev_dbg(&dev->pdev->dev,
|
dev_dbg(&dev->pdev->dev, "MEI WRITE COMPLETE\n");
|
||||||
"MEI WRITE COMPLETE\n");
|
|
||||||
cl->writing_state = MEI_WRITE_COMPLETE;
|
cl->writing_state = MEI_WRITE_COMPLETE;
|
||||||
list_add_tail(&pos->cb_list,
|
list_add_tail(&pos->cb_list,
|
||||||
&cmpl_list->mei_cb.cb_list);
|
&cmpl_list->mei_cb.cb_list);
|
||||||
|
@ -1228,8 +1217,7 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
|
||||||
if (cl == &dev->iamthif_cl) {
|
if (cl == &dev->iamthif_cl) {
|
||||||
dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n");
|
dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n");
|
||||||
if (dev->iamthif_flow_control_pending) {
|
if (dev->iamthif_flow_control_pending) {
|
||||||
ret = _mei_irq_thread_iamthif_read(
|
ret = _mei_irq_thread_iamthif_read(dev, slots);
|
||||||
dev, slots);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1257,22 +1245,15 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
|
||||||
mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
|
mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
|
||||||
if (mei_wd_send(dev))
|
if (mei_wd_send(dev))
|
||||||
dev_dbg(&dev->pdev->dev, "wd send failed.\n");
|
dev_dbg(&dev->pdev->dev, "wd send failed.\n");
|
||||||
else
|
else if (mei_flow_ctrl_reduce(dev, &dev->wd_cl))
|
||||||
if (mei_flow_ctrl_reduce(dev, &dev->wd_cl))
|
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
dev->wd_pending = false;
|
dev->wd_pending = false;
|
||||||
|
|
||||||
if (dev->wd_timeout) {
|
if (dev->wd_timeout)
|
||||||
*slots -= (sizeof(struct mei_msg_hdr) +
|
*slots -= mei_data2slots(MEI_START_WD_DATA_SIZE);
|
||||||
MEI_START_WD_DATA_SIZE + 3) / 4;
|
else
|
||||||
dev->wd_due_counter = 2;
|
*slots -= mei_data2slots(MEI_START_WD_DATA_SIZE);
|
||||||
} else {
|
|
||||||
*slots -= (sizeof(struct mei_msg_hdr) +
|
|
||||||
MEI_WD_PARAMS_SIZE + 3) / 4;
|
|
||||||
dev->wd_due_counter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dev->stop)
|
if (dev->stop)
|
||||||
|
@ -1326,16 +1307,13 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (cl != &dev->iamthif_cl) {
|
if (cl != &dev->iamthif_cl) {
|
||||||
if (!mei_flow_ctrl_creds(dev, cl)) {
|
if (mei_flow_ctrl_creds(dev, cl) <= 0) {
|
||||||
dev_dbg(&dev->pdev->dev,
|
dev_dbg(&dev->pdev->dev,
|
||||||
"No flow control"
|
"No flow control credentials for client %d, not sending.\n",
|
||||||
" credentials for client"
|
|
||||||
" %d, not sending.\n",
|
|
||||||
cl->host_client_id);
|
cl->host_client_id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ret = _mei_irq_thread_cmpl(dev, slots,
|
ret = _mei_irq_thread_cmpl(dev, slots, pos,
|
||||||
pos,
|
|
||||||
cl, cmpl_list);
|
cl, cmpl_list);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1343,19 +1321,14 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
|
||||||
} else if (cl == &dev->iamthif_cl) {
|
} else if (cl == &dev->iamthif_cl) {
|
||||||
/* IAMTHIF IOCTL */
|
/* IAMTHIF IOCTL */
|
||||||
dev_dbg(&dev->pdev->dev, "complete amthi write cb.\n");
|
dev_dbg(&dev->pdev->dev, "complete amthi write cb.\n");
|
||||||
if (!mei_flow_ctrl_creds(dev, cl)) {
|
if (mei_flow_ctrl_creds(dev, cl) <= 0) {
|
||||||
dev_dbg(&dev->pdev->dev,
|
dev_dbg(&dev->pdev->dev,
|
||||||
"No flow control"
|
"No flow control credentials for amthi client %d.\n",
|
||||||
" credentials for amthi"
|
|
||||||
" client %d.\n",
|
|
||||||
cl->host_client_id);
|
cl->host_client_id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ret = _mei_irq_thread_cmpl_iamthif(dev,
|
ret = _mei_irq_thread_cmpl_iamthif(dev, slots, pos,
|
||||||
slots,
|
cl, cmpl_list);
|
||||||
pos,
|
|
||||||
cl,
|
|
||||||
cmpl_list);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -1555,7 +1528,7 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
|
||||||
end:
|
end:
|
||||||
dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
|
dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
|
||||||
dev->host_hw_state = mei_hcsr_read(dev);
|
dev->host_hw_state = mei_hcsr_read(dev);
|
||||||
dev->mei_host_buffer_is_empty = mei_host_buffer_is_empty(dev);
|
dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev);
|
||||||
|
|
||||||
bus_message_received = false;
|
bus_message_received = false;
|
||||||
if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {
|
if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {
|
||||||
|
|
|
@ -481,12 +481,8 @@ int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
|
||||||
if (ret && dev->mei_host_buffer_is_empty) {
|
if (ret && dev->mei_host_buffer_is_empty) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
dev->mei_host_buffer_is_empty = false;
|
dev->mei_host_buffer_is_empty = false;
|
||||||
if (cb->request_buffer.size >
|
if (cb->request_buffer.size > mei_hbuf_max_data(dev)) {
|
||||||
(((dev->host_hw_state & H_CBD) >> 24) * sizeof(u32))
|
mei_hdr.length = mei_hbuf_max_data(dev);
|
||||||
-sizeof(struct mei_msg_hdr)) {
|
|
||||||
mei_hdr.length =
|
|
||||||
(((dev->host_hw_state & H_CBD) >> 24) *
|
|
||||||
sizeof(u32)) - sizeof(struct mei_msg_hdr);
|
|
||||||
mei_hdr.msg_complete = 0;
|
mei_hdr.msg_complete = 0;
|
||||||
} else {
|
} else {
|
||||||
mei_hdr.length = cb->request_buffer.size;
|
mei_hdr.length = cb->request_buffer.size;
|
||||||
|
|
|
@ -714,13 +714,8 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
|
||||||
if (rets && dev->mei_host_buffer_is_empty) {
|
if (rets && dev->mei_host_buffer_is_empty) {
|
||||||
rets = 0;
|
rets = 0;
|
||||||
dev->mei_host_buffer_is_empty = false;
|
dev->mei_host_buffer_is_empty = false;
|
||||||
if (length > ((((dev->host_hw_state & H_CBD) >> 24) *
|
if (length > mei_hbuf_max_data(dev)) {
|
||||||
sizeof(u32)) - sizeof(struct mei_msg_hdr))) {
|
mei_hdr.length = mei_hbuf_max_data(dev);
|
||||||
|
|
||||||
mei_hdr.length =
|
|
||||||
(((dev->host_hw_state & H_CBD) >> 24) *
|
|
||||||
sizeof(u32)) -
|
|
||||||
sizeof(struct mei_msg_hdr);
|
|
||||||
mei_hdr.msg_complete = 0;
|
mei_hdr.msg_complete = 0;
|
||||||
} else {
|
} else {
|
||||||
mei_hdr.length = length;
|
mei_hdr.length = length;
|
||||||
|
@ -1187,44 +1182,7 @@ static struct pci_driver mei_driver = {
|
||||||
.driver.pm = MEI_PM_OPS,
|
.driver.pm = MEI_PM_OPS,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
module_pci_driver(mei_driver);
|
||||||
* mei_init_module - Driver Registration Routine
|
|
||||||
*
|
|
||||||
* mei_init_module is the first routine called when the driver is
|
|
||||||
* loaded. All it does is to register with the PCI subsystem.
|
|
||||||
*
|
|
||||||
* returns 0 on success, <0 on failure.
|
|
||||||
*/
|
|
||||||
static int __init mei_init_module(void)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
pr_debug("loading.\n");
|
|
||||||
/* init pci module */
|
|
||||||
ret = pci_register_driver(&mei_driver);
|
|
||||||
if (ret < 0)
|
|
||||||
pr_err("error registering driver.\n");
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
module_init(mei_init_module);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* mei_exit_module - Driver Exit Cleanup Routine
|
|
||||||
*
|
|
||||||
* mei_exit_module is called just before the driver is removed
|
|
||||||
* from memory.
|
|
||||||
*/
|
|
||||||
static void __exit mei_exit_module(void)
|
|
||||||
{
|
|
||||||
pci_unregister_driver(&mei_driver);
|
|
||||||
|
|
||||||
pr_debug("unloaded successfully.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
module_exit(mei_exit_module);
|
|
||||||
|
|
||||||
|
|
||||||
MODULE_AUTHOR("Intel Corporation");
|
MODULE_AUTHOR("Intel Corporation");
|
||||||
MODULE_DESCRIPTION("Intel(R) Management Engine Interface");
|
MODULE_DESCRIPTION("Intel(R) Management Engine Interface");
|
||||||
|
|
|
@ -167,7 +167,10 @@ struct mei_io_list {
|
||||||
struct mei_cl_cb mei_cb;
|
struct mei_cl_cb mei_cb;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* MEI private device struct */
|
/**
|
||||||
|
* struct mei_deive - MEI private device struct
|
||||||
|
* @hbuf_depth - depth of host(write) buffer
|
||||||
|
*/
|
||||||
struct mei_device {
|
struct mei_device {
|
||||||
struct pci_dev *pdev; /* pointer to pci device struct */
|
struct pci_dev *pdev; /* pointer to pci device struct */
|
||||||
/*
|
/*
|
||||||
|
@ -205,6 +208,7 @@ struct mei_device {
|
||||||
*/
|
*/
|
||||||
u32 host_hw_state;
|
u32 host_hw_state;
|
||||||
u32 me_hw_state;
|
u32 me_hw_state;
|
||||||
|
u8 hbuf_depth;
|
||||||
/*
|
/*
|
||||||
* waiting queue for receive message from FW
|
* waiting queue for receive message from FW
|
||||||
*/
|
*/
|
||||||
|
@ -237,15 +241,14 @@ struct mei_device {
|
||||||
bool mei_host_buffer_is_empty;
|
bool mei_host_buffer_is_empty;
|
||||||
|
|
||||||
struct mei_cl wd_cl;
|
struct mei_cl wd_cl;
|
||||||
|
bool wd_interface_reg;
|
||||||
bool wd_pending;
|
bool wd_pending;
|
||||||
bool wd_stopped;
|
bool wd_stopped;
|
||||||
bool wd_bypass; /* if false, don't refresh watchdog ME client */
|
bool wd_bypass; /* if false, don't refresh watchdog ME client */
|
||||||
u16 wd_timeout; /* seconds ((wd_data[1] << 8) + wd_data[0]) */
|
u16 wd_timeout; /* seconds ((wd_data[1] << 8) + wd_data[0]) */
|
||||||
u16 wd_due_counter;
|
|
||||||
unsigned char wd_data[MEI_START_WD_DATA_SIZE];
|
unsigned char wd_data[MEI_START_WD_DATA_SIZE];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct file *iamthif_file_object;
|
struct file *iamthif_file_object;
|
||||||
struct mei_cl iamthif_cl;
|
struct mei_cl iamthif_cl;
|
||||||
struct mei_cl_cb *iamthif_current_cb;
|
struct mei_cl_cb *iamthif_current_cb;
|
||||||
|
@ -259,8 +262,6 @@ struct mei_device {
|
||||||
bool iamthif_flow_control_pending;
|
bool iamthif_flow_control_pending;
|
||||||
bool iamthif_ioctl;
|
bool iamthif_ioctl;
|
||||||
bool iamthif_canceled;
|
bool iamthif_canceled;
|
||||||
|
|
||||||
bool wd_interface_reg;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -361,7 +362,8 @@ int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid);
|
||||||
*
|
*
|
||||||
* returns register value (u32)
|
* returns register value (u32)
|
||||||
*/
|
*/
|
||||||
static inline u32 mei_reg_read(struct mei_device *dev, unsigned long offset)
|
static inline u32 mei_reg_read(const struct mei_device *dev,
|
||||||
|
unsigned long offset)
|
||||||
{
|
{
|
||||||
return ioread32(dev->mem_addr + offset);
|
return ioread32(dev->mem_addr + offset);
|
||||||
}
|
}
|
||||||
|
@ -373,7 +375,7 @@ static inline u32 mei_reg_read(struct mei_device *dev, unsigned long offset)
|
||||||
* @offset: offset from which to write the data
|
* @offset: offset from which to write the data
|
||||||
* @value: register value to write (u32)
|
* @value: register value to write (u32)
|
||||||
*/
|
*/
|
||||||
static inline void mei_reg_write(struct mei_device *dev,
|
static inline void mei_reg_write(const struct mei_device *dev,
|
||||||
unsigned long offset, u32 value)
|
unsigned long offset, u32 value)
|
||||||
{
|
{
|
||||||
iowrite32(value, dev->mem_addr + offset);
|
iowrite32(value, dev->mem_addr + offset);
|
||||||
|
@ -386,7 +388,7 @@ static inline void mei_reg_write(struct mei_device *dev,
|
||||||
*
|
*
|
||||||
* returns the byte read.
|
* returns the byte read.
|
||||||
*/
|
*/
|
||||||
static inline u32 mei_hcsr_read(struct mei_device *dev)
|
static inline u32 mei_hcsr_read(const struct mei_device *dev)
|
||||||
{
|
{
|
||||||
return mei_reg_read(dev, H_CSR);
|
return mei_reg_read(dev, H_CSR);
|
||||||
}
|
}
|
||||||
|
@ -398,7 +400,7 @@ static inline u32 mei_hcsr_read(struct mei_device *dev)
|
||||||
*
|
*
|
||||||
* returns ME_CSR_HA register value (u32)
|
* returns ME_CSR_HA register value (u32)
|
||||||
*/
|
*/
|
||||||
static inline u32 mei_mecsr_read(struct mei_device *dev)
|
static inline u32 mei_mecsr_read(const struct mei_device *dev)
|
||||||
{
|
{
|
||||||
return mei_reg_read(dev, ME_CSR_HA);
|
return mei_reg_read(dev, ME_CSR_HA);
|
||||||
}
|
}
|
||||||
|
@ -410,7 +412,7 @@ static inline u32 mei_mecsr_read(struct mei_device *dev)
|
||||||
*
|
*
|
||||||
* returns ME_CB_RW register value (u32)
|
* returns ME_CB_RW register value (u32)
|
||||||
*/
|
*/
|
||||||
static inline u32 mei_mecbrw_read(struct mei_device *dev)
|
static inline u32 mei_mecbrw_read(const struct mei_device *dev)
|
||||||
{
|
{
|
||||||
return mei_reg_read(dev, ME_CB_RW);
|
return mei_reg_read(dev, ME_CB_RW);
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,11 +53,12 @@ static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* host_init_wd - mei initialization wd.
|
* mei_wd_host_init - connect to the watchdog client
|
||||||
*
|
*
|
||||||
* @dev: the device structure
|
* @dev: the device structure
|
||||||
* returns -ENENT if wd client cannot be found
|
* returns -ENENT if wd client cannot be found
|
||||||
* -EIO if write has failed
|
* -EIO if write has failed
|
||||||
|
* 0 on success
|
||||||
*/
|
*/
|
||||||
int mei_wd_host_init(struct mei_device *dev)
|
int mei_wd_host_init(struct mei_device *dev)
|
||||||
{
|
{
|
||||||
|
@ -137,7 +138,6 @@ int mei_wd_stop(struct mei_device *dev, bool preserve)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
dev->wd_timeout = 0;
|
dev->wd_timeout = 0;
|
||||||
dev->wd_due_counter = 0;
|
|
||||||
memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_PARAMS_SIZE);
|
memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_PARAMS_SIZE);
|
||||||
dev->stop = true;
|
dev->stop = true;
|
||||||
|
|
||||||
|
@ -357,8 +357,6 @@ void mei_watchdog_register(struct mei_device *dev)
|
||||||
{
|
{
|
||||||
dev_dbg(&dev->pdev->dev, "dev->wd_timeout =%d.\n", dev->wd_timeout);
|
dev_dbg(&dev->pdev->dev, "dev->wd_timeout =%d.\n", dev->wd_timeout);
|
||||||
|
|
||||||
dev->wd_due_counter = !!dev->wd_timeout;
|
|
||||||
|
|
||||||
if (watchdog_register_device(&amt_wd_dev)) {
|
if (watchdog_register_device(&amt_wd_dev)) {
|
||||||
dev_err(&dev->pdev->dev,
|
dev_err(&dev->pdev->dev,
|
||||||
"wd: unable to register watchdog device.\n");
|
"wd: unable to register watchdog device.\n");
|
||||||
|
|
Loading…
Reference in New Issue