aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2010-12-08 10:57:25 +0000
committerAlan Cox <alan@linux.intel.com>2010-12-08 10:57:25 +0000
commit31071084b5a35310b8431ffdfb40958d636e40f4 (patch)
tree777c512c65b431cb66768d43265ecbb0d1d683a5
parent4cb7ec5fa88378127682a7b0fa2dcffdc70bbed8 (diff)
downloadmrst-s0i3-test-31071084b5a35310b8431ffdfb40958d636e40f4.tar.gz
mrst-s0i3-test-31071084b5a35310b8431ffdfb40958d636e40f4.tar.xz
mrst-s0i3-test-31071084b5a35310b8431ffdfb40958d636e40f4.zip
Signed-off-by: Mark A. Allyn <mark.a.allyn@intel.com>
-rw-r--r--drivers/staging/sep/sep_driver.c724
1 files changed, 649 insertions, 75 deletions
diff --git a/drivers/staging/sep/sep_driver.c b/drivers/staging/sep/sep_driver.c
index 0cd7114e4e2..2991fe7651d 100644
--- a/drivers/staging/sep/sep_driver.c
+++ b/drivers/staging/sep/sep_driver.c
@@ -275,21 +275,57 @@ static void *sep_shared_bus_to_virt(struct sep_device *sep,
return sep->shared_addr + (bus_address - sep->shared_bus);
}
-/**
- * sep_try_open - attempt to open a SEP device
- * @sep: device to attempt to open
- *
- * Atomically attempt to get ownership of a SEP device.
- * Returns 1 if the device was opened, 0 on failure.
- */
-
-static int sep_try_open(struct sep_device *sep)
+/*
+ open function for the singleton driver
+ @inode_ptr struct inode *
+ @file_ptr struct file *
+*/
+static int sep_singleton_open(struct inode *inode_ptr, struct file *file_ptr)
{
- if (!test_and_set_bit(0, &sep->in_use))
- return 1;
- return 0;
+ /*-----------------
+ CODE
+ ---------------------*/
+
+ int error = 0;
+
+ struct sep_device *sep;
+
+ if (sep_dev == NULL)
+ return -ENODEV;
+
+ /* get the sep device structure and use it for the
+ private_data field in filp for other methods */
+ sep = container_of(inode_ptr->i_cdev, struct sep_device,
+ sep_singleton_cdev);
+ file_ptr->private_data = sep;
+
+ dev_dbg(&sep->pdev->dev, "Singleton open for pid %d\n",
+ current->pid);
+
+ dev_dbg(&sep->pdev->dev, "calling test and set for singleton 0\n");
+ if (test_and_set_bit(0, &sep->singleton_access_flag)) {
+ dev_warn(&sep->pdev->dev,
+ "sep singleton is not available for open; busy\n");
+ error = -EBUSY;
+ goto end_function;
+ }
+
+ /* count up number of users opening device
+ which prevents someone else from attempting
+ to remove device (rmmod) */
+ mutex_lock(&sep_mutex);
+ sep->in_use += 1;
+ mutex_unlock(&sep_mutex);
+
+
+ dev_dbg(&sep->pdev->dev,
+ "sep_singleton_open end\n");
+end_function:
+
+ return error;
}
+
/**
* sep_open - device open method
* @inode: inode of sep device
@@ -304,27 +340,35 @@ static int sep_try_open(struct sep_device *sep)
static int sep_open(struct inode *inode, struct file *filp)
{
+ struct sep_device *sep;
+
if (sep_dev == NULL)
return -ENODEV;
- /* check the blocking mode */
- if (filp->f_flags & O_NDELAY) {
- if (sep_try_open(sep_dev) == 0)
- return -EAGAIN;
- } else
- if (wait_event_interruptible(sep_event, sep_try_open(sep_dev)) < 0)
- return -EINTR;
-
- /* Bind to the device, we only have one which makes it easy */
- filp->private_data = sep_dev;
- /* release data pool allocations */
- sep_dev->data_pool_bytes_allocated = 0;
+ /* get the sep device structure and use it for the
+ private_data field in filp for other methods */
+ sep = container_of(inode->i_cdev, struct sep_device, sep_cdev);
+ filp->private_data = sep;
+
+ dev_dbg(&sep->pdev->dev, "Open for pid %d\n", current->pid);
+
+ /* count up number of users opening device
+ which prevents someone else from attempting
+ to remove device (rmmod) */
+ mutex_lock(&sep_mutex);
+ sep->in_use += 1;
+ mutex_unlock(&sep_mutex);
+
+ /* Note that anyone is allowed to open device and
+ that blocking, if necessary, will take place
+ at transaction level (when the sep is actally
+ doing something */
+
return 0;
}
-
/**
- * sep_release - close a SEP device
+ * sep_singleton_release - close a SEP singleton device
* @inode: inode of SEP device
* @filp: file handle being closed
*
@@ -333,19 +377,438 @@ static int sep_open(struct inode *inode, struct file *filp)
* final reference to the open handle is dropped.
*/
-static int sep_release(struct inode *inode, struct file *filp)
+static int sep_singleton_release(struct inode *inode, struct file *filp)
{
- struct sep_device *sep = filp->private_data;
-#if 0 /*!SEP_DRIVER_POLLING_MODE */
- /* close IMR */
- sep_write_reg(sep, HW_HOST_IMR_REG_ADDR, 0x7FFF);
- /* release IRQ line */
- free_irq(SEP_DIRVER_IRQ_NUM, sep);
+ struct sep_device *sep = filp->private_data;
+
+ dev_dbg(&sep->pdev->dev, "Singleton release for pid %d\n",
+ current->pid);
+
+ /* decrement the number of processes having this device
+ open */
+ mutex_lock(&sep_mutex);
+ sep->in_use -= 1;
+ mutex_unlock(&sep_mutex);
+
+ clear_bit(0, &sep->singleton_access_flag);
+
+ return 0;
+}
+
+/**
+ * sep_request_daemonopen - request daemon open method
+ * @inode: inode of sep device
+ * @filp: file handle to sep device
+ *
+ * Open method for the SEP request daemon. Called when
+ * request daemon in userspace opens
+ * the SEP device node.
+ *
+ * Returns zero on success otherwise an error code.
+ */
+
+static int sep_request_daemon_open(struct inode *inode, struct file *filp)
+{
+ struct sep_device *sep;
+ int error = 0;
+
+ if (sep_dev == NULL)
+ return -ENODEV;
+
+ /* get the sep device structure and use it for the
+ private_data field in filp for other methods */
+ sep = container_of(inode->i_cdev, struct sep_device, sep_daemon_cdev);
+ filp->private_data = sep;
+
+ dev_dbg(&sep->pdev->dev, "Request daemon open for pid %d\n",
+ current->pid);
+
+ /* There is supposed to be only one request daemon */
+ dev_dbg(&sep->pdev->dev, "calling test and set for req_dmon open 0\n");
+ if (test_and_set_bit(0, &sep->request_daemon_open)) {
+ dev_warn(&sep->pdev->dev,
+ "request daemon is not available for open; busy\n");
+ error = -EBUSY;
+ goto end_function;
+ }
+
+ /* count up number of users opening device
+ which prevents someone else from attempting
+ to remove device (rmmod) */
+ mutex_lock(&sep_mutex);
+ sep->in_use += 1;
+ mutex_unlock(&sep_mutex);
+
+end_function:
+
+ return error;
+}
+
+
+/**
+ * sep_request_daemon_release - close a SEP daemon
+ * @inode: inode of SEP device
+ * @filp: file handle being closed
+ *
+ * Called on the final close of a SEP daemon.
+ */
+
+static int sep_request_daemon_release(struct inode *inode, struct file *filp)
+{
+ struct sep_device *sep = filp->private_data;
+
+ dev_dbg(&sep->pdev->dev, "Reques daemon release for pid %d\n",
+ current->pid);
+
+ /* clear the request_daemon_open flag */
+ clear_bit(0, &sep->request_daemon_open);
+
+ /* decrement the number of processes having this device
+ open */
+ mutex_lock(&sep_mutex);
+ sep->in_use -= 1;
+ mutex_unlock(&sep_mutex);
+
+ return 0;
+}
+
+/*
+ This function raises interrupt to SEPm that signals that is has a
+ new command from HOST
+ @sep: struct sep_device *
+*/
+static int sep_req_daemon_send_reply_command_handler(struct sep_device *sep)
+{
+ /* error */
+ int error = 0;
+
+
+ dev_dbg(&sep->pdev->dev,
+ "sep_req_daemon_send_reply_command_handler start\n");
+
+ error = 0;
+
+ sep_dump_message(sep);
+
+ /* update both counters counter */
+ /* logk while activity with counters */
+ spin_lock_irqsave(&snd_rply_lck, snd_rply_lck_flag);
+ sep->send_ct++;
+ sep->reply_ct++;
+
+ /* send the interrupt to SEP */
+ sep_write_reg(sep, HW_HOST_HOST_SEP_GPR2_REG_ADDR,
+ sep->send_ct);
+
+ /* update host to sep counter */
+ sep->send_ct++;
+
+ /* done with counters */
+ spin_unlock_irqrestore(&snd_rply_lck, snd_rply_lck_flag);
+
+ dev_dbg(&sep->pdev->dev,
+ "sep_req_daemon_send_reply send_ct %lx reply_ct %lx\n",
+ sep->send_ct, sep->reply_ct);
+
+ dev_dbg(&sep->pdev->dev,
+ "sep_req_daemon_send_reply_command_handler end\n");
+
+ return error;
+}
+
+
+/*
+ this function handles the request for freeing dma table for synhronic actions
+ @sep: pointere to struct sep_device
+*/
+
+static int sep_free_dma_table_data_handler(struct sep_device *sep)
+{
+ /* counter */
+ int count = 0;
+
+ /* dcb counter */
+ int dcb_counter = 0;
+
+ /* pointer to the current dma_resource struct */
+ struct sep_dma_resource *dma_resource;
+
+ /*-------------------------
+ CODE
+ -----------------------------*/
+
+ dev_dbg(&sep->pdev->dev,
+ "sep_free_dma_table_data_handler start\n");
+
+
+ for (dcb_counter = 0; dcb_counter < sep->nr_dcb_creat;
+ dcb_counter++) {
+
+ dma_resource = &sep->dma_res_arr[dcb_counter];
+
+ /* unmap and free input map array */
+ if (dma_resource->in_map_array) {
+
+ for (count = 0; count < dma_resource->in_num_pages;
+ count++) {
+
+ dma_unmap_page(&sep->pdev->dev,
+ dma_resource->in_map_array[count].dma_addr,
+ dma_resource->in_map_array[count].size,
+ DMA_TO_DEVICE/*DMA_BIDIRECTIONAL*/);
+ }
+
+ kfree(dma_resource->in_map_array);
+ }
+
+ /* unmap output map array, DON'T free it yet */
+ if (dma_resource->out_map_array) {
+ for (count = 0; count < dma_resource->out_num_pages;
+ count++) {
+
+ dma_unmap_page(&sep->pdev->dev,
+ dma_resource->out_map_array[count].dma_addr,
+ dma_resource->out_map_array[count].size,
+ DMA_FROM_DEVICE/*DMA_BIDIRECTIONAL*/);
+ }
+
+ kfree(dma_resource->out_map_array);
+ }
+
+ /* free page cache for output */
+ if (dma_resource->in_page_array) {
+ for (count = 0; count < dma_resource->in_num_pages;
+ count++) {
+
+ flush_dcache_page(dma_resource->in_page_array[count]);
+ page_cache_release(dma_resource->in_page_array[count]);
+ }
+
+ kfree(dma_resource->in_page_array);
+
+ }
+
+ if (dma_resource->out_page_array) {
+ for (count = 0; count < dma_resource->out_num_pages;
+ count++) {
+
+ if (!PageReserved(dma_resource->out_page_array[count]))
+ SetPageDirty(dma_resource->out_page_array[count]);
+
+ flush_dcache_page(dma_resource->out_page_array[count]);
+ page_cache_release(dma_resource->out_page_array[count]);
+ }
+
+ kfree(dma_resource->out_page_array);
+ }
+
+ /* reset all the values */
+ dma_resource->in_page_array = 0;
+ dma_resource->out_page_array = 0;
+ dma_resource->in_num_pages = 0;
+ dma_resource->out_num_pages = 0;
+ dma_resource->in_map_array = 0;
+ dma_resource->out_map_array = 0;
+ dma_resource->in_map_num_entries = 0;
+ dma_resource->out_map_num_entries = 0;
+
+ }
+
+ sep->nr_dcb_creat = 0;
+ sep->num_lli_tables_created = 0;
+
+ dev_dbg(&sep->pdev->dev,
+ "sep_free_dma_table_data_handler end\n");
+
+ return 0;
+}
+
+
+/*
+ This API handles the end transaction request
+ @sep: struct sep_device * for sep
+ @file_ptr: struct file * for file
+*/
+static int sep_req_daemon_end_transaction_handler(
+ struct sep_device *sep, struct file *file_ptr)
+{
+ /*----------------------------
+ CODE
+ -----------------------------*/
+
+ dev_dbg(&sep->pdev->dev,
+ "sep_req_daemon_end_transaction_handler start\n");
+
+ dev_dbg(&sep->pdev->dev,
+ "sep_req_daemon_end_transaction_handler end\n");
+
+ return 0;
+}
+
+static int sep_request_daemon_mmap(struct file *filp,
+ struct vm_area_struct *vma)
+{
+ /* device */
+ struct sep_device *sep = filp->private_data;
+
+ /* physical addr */
+ dma_addr_t phys_addr;
+
+ /* error */
+ int error = 0;
+
+ /*-----------------------
+ CODE
+ -------------------------*/
+
+ dev_dbg(&sep->pdev->dev, "daemon mmap start\n");
+
+ /* check that the size of the mapped range is as the size of the message
+ shared area */
+ if ((vma->vm_end - vma->vm_start) > SEP_DRIVER_MMMAP_AREA_SIZE) {
+ dev_warn(&sep->pdev->dev,
+ "mmap requested more than allowed\n");
+ error = -EAGAIN;
+ goto end_function;
+ }
+
+ /* get physical address */
+ phys_addr = sep->shared_bus;
+
+ dev_dbg(&sep->pdev->dev,
+ "phys_addr is %08x\n",
+ (u32)phys_addr);
+
+ if (remap_pfn_range(vma, vma->vm_start, phys_addr >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
+
+ dev_warn(&sep->pdev->dev,
+ "remap_page_range failed\n");
+ error = -EAGAIN;
+ goto end_function;
+ }
+
+end_function:
+
+ dev_dbg(&sep->pdev->dev, "daemon mmap end\n");
+
+ return error;
+}
+
+/* sep_request_daemon_poll
+ @sep: struct sep_device * for current sep device
+ @filp: struct file * for open file
+ @wait: poll_table * for poll
+*/
+static unsigned int sep_request_daemon_poll(struct file *filp,
+ poll_table *wait)
+{
+ u32 mask = 0;
+
+ /* GPR2 register */
+ u32 retVal2;
+
+ struct sep_device *sep = filp->private_data;
+
+ /*----------------------------------------------
+ CODE
+ -------------------------------------------------*/
+ dev_dbg(&sep->pdev->dev,
+ "daemon poll: start\n");
+
+ dev_dbg(&sep->pdev->dev, "daemon poll: calling poll wait sep_event\n");
+
+ poll_wait(filp, &sep->event_request_daemon, wait);
+
+ dev_dbg(&sep->pdev->dev, "daemon poll: exit poll wait sep_event\n");
+
+ dev_dbg(&sep->pdev->dev,
+ "daemon poll: send_ct is %lx reply ct is %lx\n",
+ sep->send_ct, sep->reply_ct);
+
+ /* check if the data is ready */
+ if (sep->send_ct == sep->reply_ct) {
+
+ retVal2 = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
+
+ dev_dbg(&sep->pdev->dev,
+ "daemon poll: data check (GPR2) is %x\n", retVal2);
+
+ /* check if PRINT request */
+ if ((retVal2 >> 30) & 0x1) {
+
+ dev_dbg(&sep->pdev->dev,
+ "daemon poll: PRINTF request in\n");
+ mask |= POLLIN;
+ goto end_function;
+ }
+
+ /* check if NVS request */
+ if (retVal2 >> 31) {
+
+ dev_dbg(&sep->pdev->dev,
+ "daemon poll: NVS request in\n");
+ mask |= POLLPRI | POLLWRNORM;
+ }
+ }
+
+ else {
+
+ dev_dbg(&sep->pdev->dev,
+ "daemon poll: no reply received; returning 0\n");
+ mask = 0;
+ }
+
+#if SEP_DRIVER_POLLING_MODE
+ /* in case not a request and we're running -goto sleep and wake up
+ application process */
+ if (sep->send_ct != sep->reply_ct) {
+
+ dev_dbg(&sep->pdev->dev,
+ "daemon poll: wake up task\n");
+
+ wake_up(&sep->event);
+ }
#endif
- /* Ensure any blocked open progresses */
- clear_bit(0, &sep->in_use);
- wake_up(&sep_event);
+
+end_function:
+
+ dev_dbg(&sep->pdev->dev,
+ "daemon poll: exit\n");
+ return mask;
+}
+
+/**
+ * sep_release - close a SEP device
+ * @inode: inode of SEP device
+ * @filp: file handle being closed
+ *
+ * Called on the final close of a SEP device.
+ */
+
+static int sep_release(struct inode *inode, struct file *filp)
+{
+ struct sep_device *sep = filp->private_data;
+
+ dev_dbg(&sep->pdev->dev, "Release for pid %d\n", current->pid);
+
+ /* decrement the number of processes having this device
+ open */
+ mutex_lock(&sep_mutex);
+ sep->in_use -= 1;
+
+ /* is this the process that has a transaction open? */
+ dev_dbg(&sep->pdev->dev, "waking up event and mmap_event\n");
+ if (sep->pid_doing_transaction == current->pid) {
+ clear_bit(SEP_MMAP_LOCK_BIT, &sep->in_use_flags);
+ clear_bit(SEP_SEND_MSG_LOCK_BIT, &sep->in_use_flags);
+ sep_free_dma_table_data_handler(sep);
+ wake_up(&sep->event);
+ sep->pid_doing_transaction = 0;
+ }
+
+ mutex_unlock(&sep_mutex);
return 0;
}
@@ -356,91 +819,202 @@ static int sep_mmap(struct file *filp, struct vm_area_struct *vma)
{
dma_addr_t bus_addr;
struct sep_device *sep = filp->private_data;
+ unsigned long error = 0;
+
+ dev_dbg(&sep->pdev->dev, "mmap start\n");
+
- dbg("-------->SEP Driver: mmap start\n");
+ dev_dbg(&sep->pdev->dev, "calling wait on event_mmap, tsetbit"
+ " SEP_MMAP_LOCK_BIT in_use_flags 0\n");
+ /* Set the transaction busy (own the device) */
+ wait_event_interruptible(sep->event,
+ test_and_set_bit(SEP_MMAP_LOCK_BIT,
+ &sep->in_use_flags) == 0);
+
+ if (signal_pending(current)) {
+ error = -EINTR;
+ goto end_function_with_error;
+ }
+ sep->pid_doing_transaction = current->pid;
+
+ /* zero the pools and the number of data pool alocation pointers */
+ sep->data_pool_bytes_allocated = 0;
+ sep->num_of_data_allocations = 0;
/* check that the size of the mapped range is as the size of the message
shared area */
if ((vma->vm_end - vma->vm_start) > SEP_DRIVER_MMMAP_AREA_SIZE) {
- edbg("SEP Driver mmap requested size is more than allowed\n");
- printk(KERN_WARNING "SEP Driver mmap requested size is more than allowed\n");
- printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n", vma->vm_end);
- printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n", vma->vm_start);
- return -EAGAIN;
+ dev_warn(&sep->pdev->dev,
+ "mmap requested size is more than allowed\n");
+ dev_warn(&sep->pdev->dev,
+ "vma->vm_end is %08lx\n", vma->vm_end);
+ dev_warn(&sep->pdev->dev,
+ "vma->vm_end is %08lx\n", vma->vm_start);
+ error = -EAGAIN;
+ goto end_function_with_error;
}
- edbg("SEP Driver:sep->shared_addr is %p\n", sep->shared_addr);
+ dev_dbg(&sep->pdev->dev,
+ "shared_addr is %p\n", sep->shared_addr);
/* get bus address */
bus_addr = sep->shared_bus;
- edbg("SEP Driver: phys_addr is %08llx\n", (unsigned long long)bus_addr);
+ dev_dbg(&sep->pdev->dev,
+ "phys_addr is %08llx\n", (unsigned long long)bus_addr);
- if (remap_pfn_range(vma, vma->vm_start, bus_addr >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
- edbg("SEP Driver remap_page_range failed\n");
- printk(KERN_WARNING "SEP Driver remap_page_range failed\n");
- return -EAGAIN;
+ if (remap_pfn_range(vma, vma->vm_start, bus_addr >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
+ dev_warn(&sep->pdev->dev,
+ "SEP Driver remap_page_range failed\n");
+ error = -EAGAIN;
+ goto end_function_with_error;
}
- dbg("SEP Driver:<-------- mmap end\n");
+ dev_dbg(&sep->pdev->dev, "mmap end\n");
+ goto end_function;
- return 0;
+end_function_with_error:
+
+ /* clear the bit */
+ clear_bit(SEP_MMAP_LOCK_BIT, &sep->in_use_flags);
+ sep->pid_doing_transaction = 0;
+
+ /* raise event for stuck contextes */
+
+ dev_warn(&sep->pdev->dev, "mmap error - waking up event\n");
+ wake_up(&sep->event);
+
+end_function:
+
+ return error;
}
/*-----------------------------------------------
poll function
*----------------------------------------------*/
-static unsigned int sep_poll(struct file *filp, poll_table * wait)
+static unsigned int sep_poll(struct file *filp, poll_table *wait)
{
- unsigned long count;
- unsigned int mask = 0;
- unsigned long retval = 0; /* flow id */
+ u32 count = 0;
+ u32 mask = 0;
+ u32 retval = 0;
+ u32 retval2 = 0;
+
struct sep_device *sep = filp->private_data;
- dbg("---------->SEP Driver poll: start\n");
+ dev_dbg(&sep->pdev->dev, "poll: start\n");
+ /* am I the process that own the transaction? */
+ if (current->pid != sep->pid_doing_transaction) {
+ dev_warn(&sep->pdev->dev, "poll; wrong pid\n");
+ mask = POLLERR;
+ goto end_function;
+ }
+
+ /* check if send command or send_reply were activated previously */
+ if (!test_bit(SEP_SEND_MSG_LOCK_BIT, &sep->in_use_flags)) {
+ dev_warn(&sep->pdev->dev, "poll; lock bit set\n");
+ mask = POLLERR;
+ goto end_function;
+ }
#if SEP_DRIVER_POLLING_MODE
- while (sep->send_ct != (retval & 0x7FFFFFFF)) {
+ dev_dbg(&sep->pdev->dev, "poll: waiting for send_ct and gpr2\n");
+ while ((retval2 == 0x0) &&
+ (sep->send_ct != (retVal & 0x3FFFFFFF))) {
+
retval = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
- for (count = 0; count < 10 * 4; count += 4)
- edbg("Poll Debug Word %lu of the message is %lu\n", count, *((unsigned long *) (sep->shared_addr + SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES + count)));
+ retval2 = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
}
+ spin_lock_irqsave(&snd_rply_lck, snd_rply_lck_flag);
sep->reply_ct++;
-#else
- /* add the event to the polling wait table */
- poll_wait(filp, &sep_event, wait);
+ spin_unlock_irqrestore(&snd_rply_lck, snd_rply_lck_flag);
#endif
- edbg("sep->send_ct is %lu\n", sep->send_ct);
- edbg("sep->reply_ct is %lu\n", sep->reply_ct);
+ /* add the event to the polling wait table */
+ dev_dbg(&sep->pdev->dev, "poll: calling wait sep_event\n");
- /* check if the data is ready */
- if (sep->send_ct == sep->reply_ct) {
- for (count = 0; count < 12 * 4; count += 4)
- edbg("Sep Mesg Word %lu of the message is %lu\n", count, *((unsigned long *) (sep->shared_addr + count)));
+ poll_wait(filp, &sep->event, wait);
- for (count = 0; count < 10 * 4; count += 4)
- edbg("Debug Data Word %lu of the message is %lu\n", count, *((unsigned long *) (sep->shared_addr + 0x1800 + count)));
+ dev_dbg(&sep->pdev->dev, "poll: exit wait sep_event\n");
+
+ dev_dbg(&sep->pdev->dev, "poll: send_ct is %lx reply ct is %lx\n",
+ sep->send_ct, sep->reply_ct);
+
+ /* check if error occured during poll */
+ retval2 = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
+
+ if (retval2 != 0x0) {
+
+ dev_warn(&sep->pdev->dev, "poll; poll error %x\n",
+ retval2);
+ mask |= POLLERR;
+ goto end_function;
+ }
+
+ if (sep->send_ct == sep->reply_ct) {
retval = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
- edbg("retval is %lu\n", retval);
+ dev_dbg(&sep->pdev->dev, "poll: data ready check (GPR2) %x\n",
+ retval);
+
+ /* check if printf request */
+ if ((retval >> 30) & 0x1) {
+
+ dev_dbg(&sep->pdev->dev, "poll: sep printf request\n");
+ wake_up(&sep->event_request_daemon);
+ goto end_function;
+
+ }
+
/* check if the this is sep reply or request */
if (retval >> 31) {
- edbg("SEP Driver: sep request in\n");
- /* request */
- mask |= POLLOUT | POLLWRNORM;
+
+ dev_dbg(&sep->pdev->dev, "poll: sep request\n");
+ wake_up(&sep->event_request_daemon);
+
} else {
- edbg("SEP Driver: sep reply in\n");
+
+ dev_dbg(&sep->pdev->dev, "poll: normal return\n");
+
+ /* clear the bit-in case it must be set
+ again by send_reply_comand */
+
+ clear_bit(SEP_SEND_MSG_LOCK_BIT, &sep->in_use_flags);
+
+ sep_dump_message(sep);
+
+ for (count = 0; count < 10 * 4; count += 4)
+ dev_dbg(&sep->pdev->dev,
+ "poll; debug word %d is %x\n",
+ count,
+ *((u32 *)(sep->shared_addr + count +
+ 0x1800)));
+
+ dev_dbg(&sep->pdev->dev,
+ "poll; sep reply POLLIN | POLLRDNORM\n");
+
mask |= POLLIN | POLLRDNORM;
+
}
+
+ }
+
+ else {
+
+ dev_dbg(&sep->pdev->dev,
+ "poll; no reply received; returning mask of 0\n");
+ mask = 0;
}
- dbg("SEP Driver:<-------- poll exit\n");
+
+end_function:
+
+ dev_dbg(&sep->pdev->dev, "poll: end\n");
return mask;
}