diff options
author | Dan Williams <dan.j.williams@intel.com> | 2009-09-08 17:55:21 -0700 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2009-09-08 17:55:21 -0700 |
commit | bbb20089a3275a19e475dbc21320c3742e3ca423 (patch) | |
tree | 216fdc1cbef450ca688135c5b8969169482d9a48 /drivers/staging/heci | |
parent | 3e48e656903e9fd8bc805c6a2c4264d7808d315b (diff) | |
parent | 657a77fa7284d8ae28dfa48f1dc5d919bf5b2843 (diff) | |
download | op-kernel-dev-bbb20089a3275a19e475dbc21320c3742e3ca423.zip op-kernel-dev-bbb20089a3275a19e475dbc21320c3742e3ca423.tar.gz |
Merge branch 'dmaengine' into async-tx-next
Conflicts:
crypto/async_tx/async_xor.c
drivers/dma/ioat/dma_v2.h
drivers/dma/ioat/pci.c
drivers/md/raid5.c
Diffstat (limited to 'drivers/staging/heci')
-rw-r--r-- | drivers/staging/heci/heci.h | 1 | ||||
-rw-r--r-- | drivers/staging/heci/heci_data_structures.h | 1 | ||||
-rw-r--r-- | drivers/staging/heci/heci_init.c | 14 | ||||
-rw-r--r-- | drivers/staging/heci/heci_interface.c | 17 | ||||
-rw-r--r-- | drivers/staging/heci/heci_interface.h | 2 | ||||
-rw-r--r-- | drivers/staging/heci/heci_main.c | 50 | ||||
-rw-r--r-- | drivers/staging/heci/interrupt.c | 28 | ||||
-rw-r--r-- | drivers/staging/heci/io_heci.c | 47 |
8 files changed, 108 insertions, 52 deletions
diff --git a/drivers/staging/heci/heci.h b/drivers/staging/heci/heci.h index 14192e0..48f120d 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 575e8f8..ff30386 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 a8a0da9..31fd891 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 c5f51a7..03e1df1 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 37336eb..34db7e5 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 00e44c7..ddf4822 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 aacd262..2a3a01a 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 f7544a7..1a6faf8 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: |