aboutsummaryrefslogtreecommitdiff
path: root/drivers/staging/heci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/heci')
-rw-r--r--drivers/staging/heci/Kconfig1
-rw-r--r--drivers/staging/heci/heci.h1
-rw-r--r--drivers/staging/heci/heci_data_structures.h1
-rw-r--r--drivers/staging/heci/heci_init.c14
-rw-r--r--drivers/staging/heci/heci_interface.c17
-rw-r--r--drivers/staging/heci/heci_interface.h2
-rw-r--r--drivers/staging/heci/heci_main.c50
-rw-r--r--drivers/staging/heci/interrupt.c28
-rw-r--r--drivers/staging/heci/io_heci.c47
9 files changed, 109 insertions, 52 deletions
diff --git a/drivers/staging/heci/Kconfig b/drivers/staging/heci/Kconfig
index ae8d588d3a2..c7206f8bcd9 100644
--- a/drivers/staging/heci/Kconfig
+++ b/drivers/staging/heci/Kconfig
@@ -1,5 +1,6 @@
config HECI
tristate "Intel Management Engine Interface (MEI) Support"
+ depends on PCI
---help---
The Intel Management Engine Interface (Intel MEI) driver allows
applications to access the Active Management Technology
diff --git a/drivers/staging/heci/heci.h b/drivers/staging/heci/heci.h
index 14192e0cc22..48f120dc3b2 100644
--- a/drivers/staging/heci/heci.h
+++ b/drivers/staging/heci/heci.h
@@ -41,7 +41,6 @@
#ifndef _HECI_H_
#define _HECI_H_
-#include <linux/version.h>
#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/pci.h>
diff --git a/drivers/staging/heci/heci_data_structures.h b/drivers/staging/heci/heci_data_structures.h
index 575e8f8e88a..ff30386d097 100644
--- a/drivers/staging/heci/heci_data_structures.h
+++ b/drivers/staging/heci/heci_data_structures.h
@@ -41,7 +41,6 @@
#ifndef _HECI_DATA_STRUCTURES_H_
#define _HECI_DATA_STRUCTURES_H_
-#include <linux/version.h>
#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/pci.h>
diff --git a/drivers/staging/heci/heci_init.c b/drivers/staging/heci/heci_init.c
index a8a0da910cf..31fd891c099 100644
--- a/drivers/staging/heci/heci_init.c
+++ b/drivers/staging/heci/heci_init.c
@@ -249,7 +249,7 @@ int heci_hw_init(struct iamt_heci_device *dev)
if ((dev->host_hw_state & H_IS) == H_IS) {
/* acknowledge interrupt and stop interupts */
- heci_set_csr_register(dev);
+ heci_csr_clear_his(dev);
}
dev->recvd_msg = 0;
DBG("reset in start the heci device.\n");
@@ -354,7 +354,7 @@ void heci_reset(struct iamt_heci_device *dev, int interrupts)
dev->host_hw_state &= ~H_RST;
dev->host_hw_state |= H_IG;
- write_heci_register(dev, H_CSR, dev->host_hw_state);
+ heci_set_csr_register(dev);
DBG("currently saved host_hw_state = 0x%08x.\n",
dev->host_hw_state);
@@ -998,8 +998,12 @@ int heci_disconnect_host_client(struct iamt_heci_device *dev,
if ((!dev) || (!file_ext))
return -ENODEV;
- if (file_ext->state != HECI_FILE_DISCONNECTING)
+ spin_lock_bh(&dev->device_lock);
+ if (file_ext->state != HECI_FILE_DISCONNECTING) {
+ spin_unlock_bh(&dev->device_lock);
return 0;
+ }
+ spin_unlock_bh(&dev->device_lock);
priv_cb = kzalloc(sizeof(struct heci_cb_private), GFP_KERNEL);
if (!priv_cb)
@@ -1012,6 +1016,7 @@ int heci_disconnect_host_client(struct iamt_heci_device *dev,
if (dev->host_buffer_is_empty) {
dev->host_buffer_is_empty = 0;
if (heci_disconnect(dev, file_ext)) {
+ mdelay(10); /* Wait for hardware disconnection ready */
list_add_tail(&priv_cb->cb_list,
&dev->ctrl_rd_list.heci_cb.cb_list);
} else {
@@ -1030,6 +1035,8 @@ int heci_disconnect_host_client(struct iamt_heci_device *dev,
err = wait_event_timeout(dev->wait_recvd_msg,
(HECI_FILE_DISCONNECTED == file_ext->state),
timeout * HZ);
+
+ spin_lock_bh(&dev->device_lock);
if (HECI_FILE_DISCONNECTED == file_ext->state) {
rets = 0;
DBG("successfully disconnected from fw client.\n");
@@ -1044,7 +1051,6 @@ int heci_disconnect_host_client(struct iamt_heci_device *dev,
DBG("failed to disconnect from fw client.\n");
}
- spin_lock_bh(&dev->device_lock);
heci_flush_list(&dev->ctrl_rd_list, file_ext);
heci_flush_list(&dev->ctrl_wr_list, file_ext);
spin_unlock_bh(&dev->device_lock);
diff --git a/drivers/staging/heci/heci_interface.c b/drivers/staging/heci/heci_interface.c
index c5f51a7ddf2..03e1df1a88a 100644
--- a/drivers/staging/heci/heci_interface.c
+++ b/drivers/staging/heci/heci_interface.c
@@ -44,12 +44,15 @@
/**
- * heci_set_csr_register - write H_CSR register to the heci device
+ * heci_set_csr_register - write H_CSR register to the heci device,
+ * and ignore the H_IS bit for it is write-one-to-zero.
*
* @dev: device object for our driver
*/
void heci_set_csr_register(struct iamt_heci_device *dev)
{
+ if ((dev->host_hw_state & H_IS) == H_IS)
+ dev->host_hw_state &= ~H_IS;
write_heci_register(dev, H_CSR, dev->host_hw_state);
dev->host_hw_state = read_heci_register(dev, H_CSR);
}
@@ -76,6 +79,16 @@ void heci_csr_disable_interrupts(struct iamt_heci_device *dev)
heci_set_csr_register(dev);
}
+/**
+ * heci_csr_clear_his - clear H_IS bit in H_CSR
+ *
+ * @dev: device object for our driver
+ */
+void heci_csr_clear_his(struct iamt_heci_device *dev)
+{
+ write_heci_register(dev, H_CSR, dev->host_hw_state);
+ dev->host_hw_state = read_heci_register(dev, H_CSR);
+}
/**
* _host_get_filled_slots - get number of device filled buffer slots
@@ -185,7 +198,7 @@ int heci_write_message(struct iamt_heci_device *dev,
}
dev->host_hw_state |= H_IG;
- write_heci_register(dev, H_CSR, dev->host_hw_state);
+ heci_set_csr_register(dev);
dev->me_hw_state = read_heci_register(dev, ME_CSR_HA);
if ((dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA)
return 0;
diff --git a/drivers/staging/heci/heci_interface.h b/drivers/staging/heci/heci_interface.h
index 37336ebc0a5..34db7e52b8e 100644
--- a/drivers/staging/heci/heci_interface.h
+++ b/drivers/staging/heci/heci_interface.h
@@ -42,7 +42,6 @@
#ifndef _HECI_INTERFACE_H_
#define _HECI_INTERFACE_H_
-#include <linux/version.h>
#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/pci.h>
@@ -134,6 +133,7 @@ enum client_disconnect_status_types{
void heci_set_csr_register(struct iamt_heci_device *dev);
void heci_csr_enable_interrupts(struct iamt_heci_device *dev);
void heci_csr_disable_interrupts(struct iamt_heci_device *dev);
+void heci_csr_clear_his(struct iamt_heci_device *dev);
void heci_read_slots(struct iamt_heci_device *dev,
unsigned char *buffer, unsigned long buffer_length);
diff --git a/drivers/staging/heci/heci_main.c b/drivers/staging/heci/heci_main.c
index 00e44c78142..ddf48227e35 100644
--- a/drivers/staging/heci/heci_main.c
+++ b/drivers/staging/heci/heci_main.c
@@ -751,7 +751,9 @@ static int heci_open(struct inode *inode, struct file *file)
(1 << (file_ext->host_client_id % 8));
spin_unlock_bh(&dev->device_lock);
spin_lock(&file_ext->file_lock);
+ spin_lock_bh(&dev->device_lock);
file_ext->state = HECI_FILE_INITIALIZING;
+ spin_unlock_bh(&dev->device_lock);
file_ext->sm_state = 0;
file->private_data = file_ext;
@@ -785,8 +787,10 @@ static int heci_release(struct inode *inode, struct file *file)
if (file_ext != &dev->iamthif_file_ext) {
spin_lock(&file_ext->file_lock);
+ spin_lock_bh(&dev->device_lock);
if (file_ext->state == HECI_FILE_CONNECTED) {
file_ext->state = HECI_FILE_DISCONNECTING;
+ spin_unlock_bh(&dev->device_lock);
spin_unlock(&file_ext->file_lock);
DBG("disconnecting client host client = %d, "
"ME client = %d\n",
@@ -794,8 +798,8 @@ static int heci_release(struct inode *inode, struct file *file)
file_ext->me_client_id);
rets = heci_disconnect_host_client(dev, file_ext);
spin_lock(&file_ext->file_lock);
+ spin_lock_bh(&dev->device_lock);
}
- spin_lock_bh(&dev->device_lock);
heci_flush_queues(dev, file_ext);
DBG("remove client host client = %d, ME client = %d\n",
file_ext->host_client_id,
@@ -954,11 +958,11 @@ static ssize_t heci_read(struct file *file, char __user *ubuf,
goto out;
}
- spin_lock(&file_ext->read_io_lock);
err = heci_start_read(dev, if_num, file_ext);
+ spin_lock_bh(&file_ext->read_io_lock);
if (err != 0 && err != -EBUSY) {
DBG("heci start read failure with status = %d\n", err);
- spin_unlock(&file_ext->read_io_lock);
+ spin_unlock_bh(&file_ext->read_io_lock);
rets = err;
goto out;
}
@@ -966,10 +970,10 @@ static ssize_t heci_read(struct file *file, char __user *ubuf,
&& !waitqueue_active(&file_ext->rx_wait)) {
if (file->f_flags & O_NONBLOCK) {
rets = -EAGAIN;
- spin_unlock(&file_ext->read_io_lock);
+ spin_unlock_bh(&file_ext->read_io_lock);
goto out;
}
- spin_unlock(&file_ext->read_io_lock);
+ spin_unlock_bh(&file_ext->read_io_lock);
if (wait_event_interruptible(file_ext->rx_wait,
(HECI_READ_COMPLETE == file_ext->reading_state
@@ -983,26 +987,29 @@ static ssize_t heci_read(struct file *file, char __user *ubuf,
return -ERESTARTSYS;
}
+ spin_lock_bh(&dev->device_lock);
if (HECI_FILE_INITIALIZING == file_ext->state ||
HECI_FILE_DISCONNECTED == file_ext->state ||
HECI_FILE_DISCONNECTING == file_ext->state) {
+ spin_unlock_bh(&dev->device_lock);
rets = -EBUSY;
goto out;
}
- spin_lock(&file_ext->read_io_lock);
+ spin_unlock_bh(&dev->device_lock);
+ spin_lock_bh(&file_ext->read_io_lock);
}
priv_cb = file_ext->read_cb;
if (!priv_cb) {
- spin_unlock(&file_ext->read_io_lock);
+ spin_unlock_bh(&file_ext->read_io_lock);
return -ENODEV;
}
if (file_ext->reading_state != HECI_READ_COMPLETE) {
- spin_unlock(&file_ext->read_io_lock);
+ spin_unlock_bh(&file_ext->read_io_lock);
return 0;
}
- spin_unlock(&file_ext->read_io_lock);
+ spin_unlock_bh(&file_ext->read_io_lock);
/* now copy the data to user space */
copy_buffer:
DBG("priv_cb->response_buffer size - %d\n",
@@ -1040,11 +1047,11 @@ free:
list_del(&priv_cb_pos->cb_list);
spin_unlock_bh(&dev->device_lock);
heci_free_cb_private(priv_cb);
- spin_lock(&file_ext->read_io_lock);
+ spin_lock_bh(&file_ext->read_io_lock);
file_ext->reading_state = HECI_IDLE;
file_ext->read_cb = NULL;
file_ext->read_pending = 0;
- spin_unlock(&file_ext->read_io_lock);
+ spin_unlock_bh(&file_ext->read_io_lock);
out: DBG("end heci read rets= %d\n", rets);
return rets;
}
@@ -1088,7 +1095,7 @@ static ssize_t heci_write(struct file *file, const char __user *ubuf,
if (file_ext == &dev->iamthif_file_ext) {
priv_write_cb = find_pthi_read_list_entry(dev, file);
if ((priv_write_cb != NULL) &&
- (((currtime - priv_write_cb->read_time) >
+ (((currtime - priv_write_cb->read_time) >=
IAMTHIF_READ_TIMER) ||
(file_ext->reading_state == HECI_READ_COMPLETE))) {
(*offset) = 0;
@@ -1106,11 +1113,11 @@ static ssize_t heci_write(struct file *file, const char __user *ubuf,
list_del(&priv_write_cb->cb_list);
heci_free_cb_private(priv_write_cb);
priv_write_cb = NULL;
- spin_lock(&file_ext->read_io_lock);
+ spin_lock_bh(&file_ext->read_io_lock);
file_ext->reading_state = HECI_IDLE;
file_ext->read_cb = NULL;
file_ext->read_pending = 0;
- spin_unlock(&file_ext->read_io_lock);
+ spin_unlock_bh(&file_ext->read_io_lock);
}
} else if (file_ext->reading_state == HECI_IDLE &&
file_ext->read_pending == 0)
@@ -1140,9 +1147,12 @@ static ssize_t heci_write(struct file *file, const char __user *ubuf,
spin_lock(&file_ext->file_lock);
file_ext->sm_state = 0;
if ((length == 4) &&
- ((memcmp(heci_wd_state_independence_msg[0], ubuf, 4) == 0) ||
- (memcmp(heci_wd_state_independence_msg[1], ubuf, 4) == 0) ||
- (memcmp(heci_wd_state_independence_msg[2], ubuf, 4) == 0)))
+ ((memcmp(heci_wd_state_independence_msg[0],
+ priv_write_cb->request_buffer.data, 4) == 0) ||
+ (memcmp(heci_wd_state_independence_msg[1],
+ priv_write_cb->request_buffer.data, 4) == 0) ||
+ (memcmp(heci_wd_state_independence_msg[2],
+ priv_write_cb->request_buffer.data, 4) == 0)))
file_ext->sm_state |= HECI_WD_STATE_INDEPENDENCE_MSG_SENT;
spin_unlock(&file_ext->file_lock);
@@ -1222,6 +1232,7 @@ static ssize_t heci_write(struct file *file, const char __user *ubuf,
priv_write_cb->request_buffer.size = length;
spin_lock(&file_ext->write_io_lock);
+ spin_lock_bh(&dev->device_lock);
DBG("host client = %d, ME client = %d\n",
file_ext->host_client_id, file_ext->me_client_id);
if (file_ext->state != HECI_FILE_CONNECTED) {
@@ -1229,7 +1240,7 @@ static ssize_t heci_write(struct file *file, const char __user *ubuf,
DBG("host client = %d, is not connected to ME client = %d",
file_ext->host_client_id,
file_ext->me_client_id);
-
+ spin_unlock_bh(&dev->device_lock);
goto unlock;
}
for (i = 0; i < dev->num_heci_me_clients; i++) {
@@ -1240,15 +1251,16 @@ static ssize_t heci_write(struct file *file, const char __user *ubuf,
BUG_ON(dev->me_clients[i].client_id != file_ext->me_client_id);
if (i == dev->num_heci_me_clients) {
rets = -ENODEV;
+ spin_unlock_bh(&dev->device_lock);
goto unlock;
}
if (length > dev->me_clients[i].props.max_msg_length || length <= 0) {
rets = -EINVAL;
+ spin_unlock_bh(&dev->device_lock);
goto unlock;
}
priv_write_cb->file_private = file_ext;
- spin_lock_bh(&dev->device_lock);
if (flow_ctrl_creds(dev, file_ext) &&
dev->host_buffer_is_empty) {
spin_unlock_bh(&dev->device_lock);
diff --git a/drivers/staging/heci/interrupt.c b/drivers/staging/heci/interrupt.c
index aacd2624398..2a3a01a62bb 100644
--- a/drivers/staging/heci/interrupt.c
+++ b/drivers/staging/heci/interrupt.c
@@ -92,6 +92,9 @@ irqreturn_t heci_isr_interrupt(int irq, void *dev_id)
/* disable interrupts */
heci_csr_disable_interrupts(dev);
+ /* clear H_IS bit in H_CSR */
+ heci_csr_clear_his(dev);
+
/*
* Our device interrupted, schedule work the heci_bh_handler
* to handle the interrupt processing. This needs to be a
@@ -100,10 +103,8 @@ irqreturn_t heci_isr_interrupt(int irq, void *dev_id)
PREPARE_WORK(&dev->work, heci_bh_handler);
DBG("schedule work the heci_bh_handler.\n");
err = schedule_work(&dev->work);
- if (!err) {
- printk(KERN_ERR "heci: schedule the heci_bh_handler"
- " failed error=%x\n", err);
- }
+ if (!err)
+ DBG("heci_bh_handler was already on the workqueue.\n");
return IRQ_HANDLED;
}
@@ -251,13 +252,14 @@ end:
/* acknowledge interrupt and disable interrupts */
heci_csr_disable_interrupts(dev);
+ /* clear H_IS bit in H_CSR */
+ heci_csr_clear_his(dev);
+
PREPARE_WORK(&dev->work, heci_bh_handler);
DBG("schedule work the heci_bh_handler.\n");
rets = schedule_work(&dev->work);
- if (!rets) {
- printk(KERN_ERR "heci: schedule the heci_bh_handler"
- " failed error=%x\n", rets);
- }
+ if (!rets)
+ DBG("heci_bh_handler was already queued.\n");
} else {
heci_csr_enable_interrupts(dev);
}
@@ -622,7 +624,7 @@ static int heci_bh_read_client_message(struct io_heci_list *complete_list,
priv_cb_pos->file_private;
if ((file_ext != NULL) &&
(_heci_bh_state_ok(file_ext, heci_hdr))) {
- spin_lock(&file_ext->read_io_lock);
+ spin_lock_bh(&file_ext->read_io_lock);
file_ext->reading_state = HECI_READING;
buffer = (unsigned char *)
(priv_cb_pos->response_buffer.data +
@@ -636,7 +638,7 @@ static int heci_bh_read_client_message(struct io_heci_list *complete_list,
priv_cb_pos->information) {
DBG("message overflow.\n");
list_del(&priv_cb_pos->cb_list);
- spin_unlock(&file_ext->read_io_lock);
+ spin_unlock_bh(&file_ext->read_io_lock);
return -ENOMEM;
}
if (buffer) {
@@ -647,7 +649,7 @@ static int heci_bh_read_client_message(struct io_heci_list *complete_list,
if (heci_hdr->msg_complete) {
file_ext->status = 0;
list_del(&priv_cb_pos->cb_list);
- spin_unlock(&file_ext->read_io_lock);
+ spin_unlock_bh(&file_ext->read_io_lock);
DBG("completed read host client = %d,"
"ME client = %d, "
"data length = %lu\n",
@@ -662,7 +664,7 @@ static int heci_bh_read_client_message(struct io_heci_list *complete_list,
list_add_tail(&priv_cb_pos->cb_list,
&complete_list->heci_cb.cb_list);
} else {
- spin_unlock(&file_ext->read_io_lock);
+ spin_unlock_bh(&file_ext->read_io_lock);
}
break;
@@ -1054,7 +1056,7 @@ static int heci_bh_write_handler(struct io_heci_list *cmpl_list,
list_del(&priv_cb_pos->cb_list);
if ((HECI_WRITING == file_ext->writing_state) &&
(priv_cb_pos->major_file_operations ==
- HECI_WRITING) &&
+ HECI_WRITE) &&
(file_ext != &dev->iamthif_file_ext)) {
DBG("HECI WRITE COMPLETE\n");
file_ext->writing_state =
diff --git a/drivers/staging/heci/io_heci.c b/drivers/staging/heci/io_heci.c
index f7544a7bbbe..1a6faf88e16 100644
--- a/drivers/staging/heci/io_heci.c
+++ b/drivers/staging/heci/io_heci.c
@@ -111,7 +111,7 @@ int heci_ioctl_get_version(struct iamt_heci_device *dev, int if_num,
rets = file_ext->status;
/* now copy the data to user space */
- if (copy_to_user(k_msg.data, res_msg.data, res_msg.size)) {
+ if (copy_to_user((void __user *)k_msg.data, res_msg.data, res_msg.size)) {
rets = -EFAULT;
goto end;
}
@@ -188,7 +188,7 @@ int heci_ioctl_connect_client(struct iamt_heci_device *dev, int if_num,
/* copy the message to kernel space -
* use a pointer already copied into kernel space
*/
- if (copy_from_user(req_msg.data, k_msg.data, k_msg.size)) {
+ if (copy_from_user(req_msg.data, (void __user *)k_msg.data, k_msg.size)) {
rets = -EFAULT;
goto end;
}
@@ -266,7 +266,8 @@ int heci_ioctl_connect_client(struct iamt_heci_device *dev, int if_num,
spin_unlock_bh(&dev->device_lock);
/* now copy the data to user space */
- if (copy_to_user(k_msg.data, res_msg.data, res_msg.size)) {
+ if (copy_to_user((void __user *)k_msg.data,
+ res_msg.data, res_msg.size)) {
rets = -EFAULT;
goto end;
}
@@ -276,14 +277,16 @@ int heci_ioctl_connect_client(struct iamt_heci_device *dev, int if_num,
}
goto end;
}
+ spin_unlock_bh(&dev->device_lock);
+
spin_lock(&file_ext->file_lock);
+ spin_lock_bh(&dev->device_lock);
if (file_ext->state != HECI_FILE_CONNECTING) {
rets = -ENODEV;
- spin_unlock(&file_ext->file_lock);
spin_unlock_bh(&dev->device_lock);
+ spin_unlock(&file_ext->file_lock);
goto end;
}
- spin_unlock(&file_ext->file_lock);
/* prepare the output buffer */
client = (struct heci_client *) res_msg.data;
client->max_msg_length = dev->me_clients[i].props.max_msg_length;
@@ -294,6 +297,7 @@ int heci_ioctl_connect_client(struct iamt_heci_device *dev, int if_num,
if (!heci_connect(dev, file_ext)) {
rets = -ENODEV;
spin_unlock_bh(&dev->device_lock);
+ spin_unlock(&file_ext->file_lock);
goto end;
} else {
file_ext->timer_count = HECI_CONNECT_TIMEOUT;
@@ -311,16 +315,20 @@ int heci_ioctl_connect_client(struct iamt_heci_device *dev, int if_num,
&dev->ctrl_wr_list.heci_cb.cb_list);
}
spin_unlock_bh(&dev->device_lock);
+ spin_unlock(&file_ext->file_lock);
err = wait_event_timeout(dev->wait_recvd_msg,
(HECI_FILE_CONNECTED == file_ext->state
|| HECI_FILE_DISCONNECTED == file_ext->state),
timeout * HZ);
+ spin_lock_bh(&dev->device_lock);
if (HECI_FILE_CONNECTED == file_ext->state) {
+ spin_unlock_bh(&dev->device_lock);
DBG("successfully connected to FW client.\n");
rets = file_ext->status;
/* now copy the data to user space */
- if (copy_to_user(k_msg.data, res_msg.data, res_msg.size)) {
+ if (copy_to_user((void __user *)k_msg.data,
+ res_msg.data, res_msg.size)) {
rets = -EFAULT;
goto end;
}
@@ -332,6 +340,7 @@ int heci_ioctl_connect_client(struct iamt_heci_device *dev, int if_num,
} else {
DBG("failed to connect to FW client.file_ext->state = %d.\n",
file_ext->state);
+ spin_unlock_bh(&dev->device_lock);
if (!err) {
DBG("wait_event_interruptible_timeout failed on client"
" connect message fw response message.\n");
@@ -394,7 +403,8 @@ int heci_ioctl_wd(struct iamt_heci_device *dev, int if_num,
/* copy the message to kernel space - use a pointer already
* copied into kernel space
*/
- if (copy_from_user(req_msg.data, k_msg.data, req_msg.size)) {
+ if (copy_from_user(req_msg.data,
+ (void __user *)k_msg.data, req_msg.size)) {
rets = -EFAULT;
goto end;
}
@@ -464,7 +474,7 @@ int heci_ioctl_bypass_wd(struct iamt_heci_device *dev, int if_num,
return -EMSGSIZE;
}
spin_unlock(&file_ext->file_lock);
- if (copy_from_user(&flag, k_msg.data, 1)) {
+ if (copy_from_user(&flag, (void __user *)k_msg.data, 1)) {
rets = -EFAULT;
goto end;
}
@@ -631,28 +641,39 @@ int heci_start_read(struct iamt_heci_device *dev, int if_num,
DBG("received wrong function input param.\n");
return -ENODEV;
}
- if (file_ext->state != HECI_FILE_CONNECTED)
- return -ENODEV;
spin_lock_bh(&dev->device_lock);
+ if (file_ext->state != HECI_FILE_CONNECTED) {
+ spin_unlock_bh(&dev->device_lock);
+ return -ENODEV;
+ }
+
if (dev->heci_state != HECI_ENABLED) {
spin_unlock_bh(&dev->device_lock);
return -ENODEV;
}
spin_unlock_bh(&dev->device_lock);
DBG("check if read is pending.\n");
+ spin_lock_bh(&file_ext->read_io_lock);
if ((file_ext->read_pending) || (file_ext->read_cb != NULL)) {
DBG("read is pending.\n");
+ spin_unlock_bh(&file_ext->read_io_lock);
return -EBUSY;
}
+ spin_unlock_bh(&file_ext->read_io_lock);
+
priv_cb = kzalloc(sizeof(struct heci_cb_private), GFP_KERNEL);
if (!priv_cb)
return -ENOMEM;
+ spin_lock_bh(&file_ext->read_io_lock);
DBG("allocation call back success\n"
"host client = %d, ME client = %d\n",
file_ext->host_client_id, file_ext->me_client_id);
+ spin_unlock_bh(&file_ext->read_io_lock);
+
spin_lock_bh(&dev->device_lock);
+ spin_lock_bh(&file_ext->read_io_lock);
for (i = 0; i < dev->num_heci_me_clients; i++) {
if (dev->me_clients[i].client_id == file_ext->me_client_id)
break;
@@ -660,6 +681,7 @@ int heci_start_read(struct iamt_heci_device *dev, int if_num,
}
BUG_ON(dev->me_clients[i].client_id != file_ext->me_client_id);
+ spin_unlock_bh(&file_ext->read_io_lock);
if (i == dev->num_heci_me_clients) {
rets = -ENODEV;
goto unlock;
@@ -678,12 +700,14 @@ int heci_start_read(struct iamt_heci_device *dev, int if_num,
/* make sure information is zero before we start */
priv_cb->information = 0;
priv_cb->file_private = (void *) file_ext;
- file_ext->read_cb = priv_cb;
spin_lock_bh(&dev->device_lock);
+ spin_lock_bh(&file_ext->read_io_lock);
+ file_ext->read_cb = priv_cb;
if (dev->host_buffer_is_empty) {
dev->host_buffer_is_empty = 0;
if (!heci_send_flow_control(dev, file_ext)) {
rets = -ENODEV;
+ spin_unlock_bh(&file_ext->read_io_lock);
goto unlock;
} else {
list_add_tail(&priv_cb->cb_list,
@@ -693,6 +717,7 @@ int heci_start_read(struct iamt_heci_device *dev, int if_num,
list_add_tail(&priv_cb->cb_list,
&dev->ctrl_wr_list.heci_cb.cb_list);
}
+ spin_unlock_bh(&file_ext->read_io_lock);
spin_unlock_bh(&dev->device_lock);
return rets;
unlock: