Signed-off-by: Luca Ellero <[email protected]>
---
drivers/staging/ced1401/ced_ioc.c | 217 +++++++++++++++++++++++--------------
1 file changed, 134 insertions(+), 83 deletions(-)
diff --git a/drivers/staging/ced1401/ced_ioc.c
b/drivers/staging/ced1401/ced_ioc.c
index c4df70d..40ab438 100644
--- a/drivers/staging/ced1401/ced_ioc.c
+++ b/drivers/staging/ced1401/ced_ioc.c
@@ -63,8 +63,11 @@ static void ced_flush_in_buff(struct ced_data *ced)
{
dev_dbg(&ced->interface->dev, "%s: current_state=%d\n",
__func__, ced->current_state);
- if (ced->current_state == U14ERR_TIME) /* Do nothing if hardware in
trouble */
+
+ /* Do nothing if hardware in trouble */
+ if (ced->current_state == U14ERR_TIME)
return;
+
/* Kill off any pending I/O */
/* CharRead_Cancel(pDevObject); */
spin_lock_irq(&ced->char_in_lock);
@@ -84,9 +87,11 @@ static int ced_put_chars(struct ced_data *ced, const char
*ch,
unsigned int count)
{
int ret;
+
spin_lock_irq(&ced->char_out_lock); /* get the output spin lock */
if ((OUTBUF_SZ - ced->num_output) >= count) {
unsigned int u;
+
for (u = 0; u < count; u++) {
ced->output_buffer[ced->out_buff_put++] = ch[u];
if (ced->out_buff_put >= OUTBUF_SZ)
@@ -94,7 +99,9 @@ static int ced_put_chars(struct ced_data *ced, const char *ch,
}
ced->num_output += count;
spin_unlock_irq(&ced->char_out_lock);
- ret = ced_send_chars(ced); /* ...give a chance to
transmit data */
+
+ /* ...give a chance to transmit data */
+ ret = ced_send_chars(ced);
} else {
ret = U14ERR_NOOUT; /* no room at the out (ha-ha) */
spin_unlock_irq(&ced->char_out_lock);
@@ -140,6 +147,7 @@ int ced_send_string(struct ced_data *ced, const char __user
*data,
int ced_send_char(struct ced_data *ced, char c)
{
int ret;
+
mutex_lock(&ced->io_mutex); /* Protect disconnect from new i/o */
ret = ced_put_chars(ced, &c, 1);
dev_dbg(&ced->interface->dev, "ced_send_char >%c< (0x%02x)\n", c, c);
@@ -177,6 +185,7 @@ int ced_send_char(struct ced_data *ced, char c)
int ced_get_state(struct ced_data *ced, __u32 *state, __u32 *error)
{
int got;
+
dev_dbg(&ced->interface->dev, "%s: entry\n", __func__);
*state = 0xFFFFFFFF; /* Start off with invalid state */
@@ -192,6 +201,7 @@ int ced_get_state(struct ced_data *ced, __u32 *state, __u32
*error)
*error = 0;
} else {
int device;
+
dev_dbg(&ced->interface->dev,
"%s: Success, state: 0x%x, 0x%x\n",
__func__, ced->stat_buf[0], ced->stat_buf[1]);
@@ -233,23 +243,32 @@ int ced_read_write_cancel(struct ced_data *ced)
int ntStatus = STATUS_SUCCESS;
bool bResult = false;
unsigned int i;
- /* We can fill this in when we know how we will implement the staged
transfer stuff */
+
+ /* We can fill this in when we know how we */
+ /* will implement the staged transfer stuff */
spin_lock_irq(&ced->staged_lock);
- if (ced->staged_urb_pending) { /* anything to be cancelled? May need
more... */
+ /* anything to be cancelled? May need more... */
+ if (ced->staged_urb_pending) {
dev_info(&ced->interface - dev,
"ced_read_write_cancel about to cancel Urb\n");
/* Clear the staging done flag */
/* KeClearEvent(&ced->StagingDoneEvent); */
USB_ASSERT(ced->pStagedIrp != NULL);
- /* Release the spinlock first otherwise the completion routine
may hang */
- /* on the spinlock while this function hands waiting for the
event. */
+ /* Release the spinlock first otherwise the completion */
+ /* routine may hang on the spinlock while this function */
+ /* hands waiting for the event. */
spin_unlock_irq(&ced->staged_lock);
- bResult = IoCancelIrp(ced->pStagedIrp); /* Actually do the
cancel */
+
+ /* Actually do the cancel */
+ bResult = IoCancelIrp(ced->pStagedIrp);
+
if (bResult) {
LARGE_INTEGER timeout;
- timeout.QuadPart = -10000000; /* Use a timeout of 1
second */
+
+ /* Use a timeout of 1 second */
+ timeout.QuadPart = -10000000;
dev_info(&ced->interface - dev,
"%s: about to wait till done\n", __func__);
ntStatus =
@@ -261,9 +280,11 @@ int ced_read_write_cancel(struct ced_data *ced)
"%s: cancellation failed\n", __func__);
ntStatus = U14ERR_FAIL;
}
- USB_KdPrint(DBGLVL_DEFAULT,
- ("ced_read_write_cancel ntStatus = 0x%x decimal
%d\n",
- ntStatus, ntStatus));
+ USB_KdPrint(
+ DBGLVL_DEFAULT,
+ ("ced_read_write_cancel ntStatus = 0x%x decimal %d\n",
+ ntStatus,
+ ntStatus));
} else
spin_unlock_irq(&ced->staged_lock);
@@ -283,6 +304,7 @@ static int ced_in_self_test(struct ced_data *ced, unsigned
int *stat)
{
unsigned int state, error;
int ret = ced_get_state(ced, &state, &error); /* see if in self-test */
+
if (ret == U14ERR_NOERROR) /* if all still OK */
ret = (state == (unsigned int)-1) || /* TX problem or... */
((state & 0xff) == 0x80); /* ...self test */
@@ -311,6 +333,7 @@ static int ced_in_self_test(struct ced_data *ced, unsigned
int *stat)
static bool ced_is_1401(struct ced_data *ced)
{
int ret;
+
dev_dbg(&ced->interface->dev, "%s\n", __func__);
ced_draw_down(ced); /* wait for, then kill outstanding Urbs */
@@ -334,11 +357,13 @@ static bool ced_is_1401(struct ced_data *ced)
ced->dma_flag = MODE_CHAR; /* Clear DMA mode flag regardless! */
if (ret == 0) { /* if all is OK still */
unsigned int state;
+
ret = ced_in_self_test(ced, &state); /* see if likely in */
- /* self test */
+ /* self test */
if (ret > 0) { /* do we need to wait for self-test? */
/* when to give up */
unsigned long timeout = jiffies + 30 * HZ;
+
while ((ret > 0) && time_before(jiffies, timeout)) {
schedule(); /* let other stuff run */
@@ -377,9 +402,11 @@ static bool ced_quick_check(struct ced_data *ced, bool
test_buff,
bool ret = false; /* assume it will fail and we will reset */
bool short_test;
- short_test = ((ced->dma_flag == MODE_CHAR) && /* no DMA running */
- (!ced->force_reset) && /* Not had a real reset forced */
- (ced->current_state >= U14ERR_STD)); /* No 1401 errors
stored */
+ short_test = ((ced->dma_flag == MODE_CHAR) && /* no DMA running */
+ /* Not had a real reset forced */
+ (!ced->force_reset) &&
+ /* No 1401 errors stored */
+ (ced->current_state >= U14ERR_STD));
dev_dbg(&ced->interface->dev,
"%s: DMAFlag:%d, state:%d, force:%d, testBuff:%d, short:%d\n",
@@ -387,18 +414,26 @@ static bool ced_quick_check(struct ced_data *ced, bool
test_buff,
test_buff, short_test);
if ((test_buff) && /* Buffer check requested, and... */
- (ced->num_input || ced->num_output)) { /* ...characters were
in the buffer? */
- short_test = false; /* Then do the full test */
- dev_dbg(&ced->interface->dev,
- "%s: will reset as buffers not empty\n", __func__);
+ /* ...characters were in the buffer? */
+ (ced->num_input || ced->num_output)) {
+ short_test = false; /* Then do the full test */
+ dev_dbg(&ced->interface->dev,
+ "%s: will reset as buffers not empty\n",
+ __func__);
}
- if (short_test || !can_reset) { /* Still OK to try the short test? */
- /* Always test if no reset - we want state
update */
+ /* Still OK to try the short test? */
+ /* Always test if no reset - we want state update */
+ if (short_test || !can_reset) {
+
unsigned int state, error;
+
dev_dbg(&ced->interface->dev, "%s: ced_get_state\n", __func__);
- if (ced_get_state(ced, &state, &error) == U14ERR_NOERROR) {
/* Check on the 1401 state */
- if ((state & 0xFF) == 0) /* If call worked,
check the status value */
+
+ /* Check on the 1401 state */
+ if (ced_get_state(ced, &state, &error) == U14ERR_NOERROR) {
+ /* If call worked, check the status value */
+ if ((state & 0xFF) == 0)
ret = true; /* If that was zero, all is OK, */
/* no reset needed */
}
@@ -424,7 +459,7 @@ int ced_reset(struct ced_data *ced)
mutex_lock(&ced->io_mutex); /* Protect disconnect from new i/o */
dev_dbg(&ced->interface->dev, "%s: About to call ced_quick_check\n",
__func__);
- ced_quick_check(ced, true, true); /* Check 1401, reset if not OK
*/
+ ced_quick_check(ced, true, true); /* Check 1401, reset if not OK */
mutex_unlock(&ced->io_mutex);
return U14ERR_NOERROR;
}
@@ -437,6 +472,7 @@ int ced_reset(struct ced_data *ced)
int ced_get_char(struct ced_data *ced)
{
int ret = U14ERR_NOIN; /* assume we will get nothing */
+
mutex_lock(&ced->io_mutex); /* Protect disconnect from new i/o */
dev_dbg(&ced->interface->dev, "%s\n", __func__);
@@ -475,6 +511,7 @@ int ced_get_string(struct ced_data *ced, char __user *user,
int n)
{
int available; /* character in the buffer */
int ret = U14ERR_NOIN;
+
if (n <= 0)
return -ENOMEM;
@@ -492,6 +529,7 @@ int ced_get_string(struct ced_data *ced, char __user *user,
int n)
int got = 0;
int n_copy_to_user; /* number to copy to user */
char data;
+
do {
data = ced->input_buffer[ced->in_buff_get++];
if (data == CR_CHAR) /* replace CR with zero */
@@ -507,7 +545,7 @@ int ced_get_string(struct ced_data *ced, char __user *user,
int n)
if (data) { /* do we need null */
buffer[got] = (char)0; /* make it tidy */
if (got < n) /* if space in user buffer... */
- ++n_copy_to_user; /* ...copy the 0 as
well. */
+ ++n_copy_to_user; /* ...copy the 0 as well. */
}
ced->num_input -= got;
@@ -534,6 +572,7 @@ int ced_get_string(struct ced_data *ced, char __user *user,
int n)
int ced_stat_1401(struct ced_data *ced)
{
int ret;
+
mutex_lock(&ced->io_mutex); /* Protect disconnect from new i/o */
ced_allowi(ced); /* make sure we allow pending chars */
ced_send_chars(ced); /* in both directions */
@@ -563,6 +602,7 @@ int ced_line_count(struct ced_data *ced)
unsigned int index = ced->in_buff_get;
/* Position for search end */
unsigned int end = ced->in_buff_put;
+
do {
if (ced->input_buffer[index++] == CR_CHAR)
++ret; /* inc count if CR */
@@ -618,6 +658,7 @@ int ced_clear_area(struct ced_data *ced, int area)
} else {
/* to save typing */
struct transarea *ta = &ced->trans_def[area];
+
if (!ta->used) /* if not used... */
ret = U14ERR_NOTSET; /* ...nothing to be done */
else {
@@ -703,12 +744,11 @@ static int ced_set_area(struct ced_data *ced, int area,
char __user *buf,
unsigned long start = ((unsigned long)buf) & PAGE_MASK;
unsigned int offset = ((unsigned long)buf) & (PAGE_SIZE - 1);
int len = (length + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
-
struct transarea *ta = &ced->trans_def[area]; /* to save typing */
struct page **pages = NULL; /* space for page tables */
int n_pages = 0; /* and number of pages */
-
int ret = ced_clear_area(ced, area); /* see if OK to use this area */
+
if ((ret != U14ERR_NOTSET) && /* if not area unused and... */
(ret != U14ERR_NOERROR)) /* ...not all OK, then... */
return ret; /* ...we cannot use this area */
@@ -807,6 +847,7 @@ int ced_set_transfer(struct ced_data *ced,
int ced_unset_transfer(struct ced_data *ced, int area)
{
int ret;
+
mutex_lock(&ced->io_mutex);
ret = ced_clear_area(ced, area);
mutex_unlock(&ced->io_mutex);
@@ -825,6 +866,7 @@ int ced_set_event(struct ced_data *ced, struct
transfer_event __user *ute)
{
int ret = U14ERR_NOERROR;
struct transfer_event te;
+ struct transarea *ta;
/* get a local copy of the data */
if (copy_from_user(&te, ute, sizeof(te)))
@@ -832,27 +874,27 @@ int ced_set_event(struct ced_data *ced, struct
transfer_event __user *ute)
if (te.wAreaNum >= MAX_TRANSAREAS) /* the area must exist */
return U14ERR_BADAREA;
- else {
- struct transarea *ta = &ced->trans_def[te.wAreaNum];
- /* make sure we have no competitor */
- mutex_lock(&ced->io_mutex);
- spin_lock_irq(&ced->staged_lock);
+ ta = &ced->trans_def[te.wAreaNum];
- if (ta->used) { /* area must be in use */
- ta->event_st = te.dwStart; /* set area regions */
+ /* make sure we have no competitor */
+ mutex_lock(&ced->io_mutex);
+ spin_lock_irq(&ced->staged_lock);
- /* set size (0 cancels it) */
- ta->event_sz = te.dwLength;
+ if (ta->used) { /* area must be in use */
+ ta->event_st = te.dwStart; /* set area regions */
+
+ /* set size (0 cancels it) */
+ ta->event_sz = te.dwLength;
+
+ /* set the direction */
+ ta->event_to_host = te.wFlags & 1;
+ ta->wake_up = 0; /* zero the wake up count */
+ } else
+ ret = U14ERR_NOTSET;
+ spin_unlock_irq(&ced->staged_lock);
+ mutex_unlock(&ced->io_mutex);
- /* set the direction */
- ta->event_to_host = te.wFlags & 1;
- ta->wake_up = 0; /* zero the wake up count */
- } else
- ret = U14ERR_NOTSET;
- spin_unlock_irq(&ced->staged_lock);
- mutex_unlock(&ced->io_mutex);
- }
return ret ==
U14ERR_NOERROR ? (te.iSetEvent ? 1 : U14ERR_NOERROR) : ret;
}
@@ -866,59 +908,62 @@ int ced_set_event(struct ced_data *ced, struct
transfer_event __user *ute)
int ced_wait_event(struct ced_data *ced, int area, int time_out)
{
int ret;
+ int wait;
+ struct transarea *ta;
+
if ((unsigned)area >= MAX_TRANSAREAS)
return U14ERR_BADAREA;
- else {
- int wait;
- struct transarea *ta = &ced->trans_def[area];
- /* convert timeout to jiffies */
- time_out = (time_out * HZ + 999) / 1000;
+ ta = &ced->trans_def[area];
- /* We cannot wait holding the mutex, but we check the flags */
- /* while holding it. This may well be pointless as another */
- /* thread could get in between releasing it and the wait */
- /* call. However, this would have to clear the wake_up flag. */
- /* However, the !ta->used may help us in this case. */
+ /* convert timeout to jiffies */
+ time_out = (time_out * HZ + 999) / 1000;
- /* make sure we have no competitor */
- mutex_lock(&ced->io_mutex);
- if (!ta->used || !ta->event_sz) /* check something to */
- /* wait for... */
- return U14ERR_NOTSET; /* ...else we do nothing */
- mutex_unlock(&ced->io_mutex);
+ /* We cannot wait holding the mutex, but we check the flags */
+ /* while holding it. This may well be pointless as another */
+ /* thread could get in between releasing it and the wait */
+ /* call. However, this would have to clear the wake_up flag. */
+ /* However, the !ta->used may help us in this case. */
- if (time_out)
- wait =
- wait_event_interruptible_timeout(ta->event,
- ta->wake_up
- || !ta->used,
- time_out);
- else
- wait =
- wait_event_interruptible(ta->event, ta->wake_up
- || !ta->used);
- if (wait)
- ret = -ERESTARTSYS; /* oops - we have had a SIGNAL */
- else
- ret = ta->wake_up; /* else the wakeup count */
+ /* make sure we have no competitor */
+ mutex_lock(&ced->io_mutex);
+ if (!ta->used || !ta->event_sz) /* check something to */
+ /* wait for... */
+ return U14ERR_NOTSET; /* ...else we do nothing */
+ mutex_unlock(&ced->io_mutex);
+
+ if (time_out)
+ wait =
+ wait_event_interruptible_timeout(ta->event,
+ ta->wake_up
+ || !ta->used,
+ time_out);
+ else
+ wait =
+ wait_event_interruptible(ta->event, ta->wake_up
+ || !ta->used);
+ if (wait)
+ ret = -ERESTARTSYS; /* oops - we have had a SIGNAL */
+ else
+ ret = ta->wake_up; /* else the wakeup count */
+
+ spin_lock_irq(&ced->staged_lock);
+ ta->wake_up = 0; /* clear the flag */
+ spin_unlock_irq(&ced->staged_lock);
- spin_lock_irq(&ced->staged_lock);
- ta->wake_up = 0; /* clear the flag */
- spin_unlock_irq(&ced->staged_lock);
- }
return ret;
}
/****************************************************************************
** ced_test_event
-** Test the event to see if a ced_wait_event would return immediately. Returns
the
-** number of times a block completed since the last call, or 0 if none or a
+** Test the event to see if a ced_wait_event would return immediately. Returns
+** the number of times a block completed since the last call, or 0 if none or a
** negative error.
****************************************************************************/
int ced_test_event(struct ced_data *ced, int area)
{
int ret;
+
if ((unsigned)area >= MAX_TRANSAREAS)
ret = U14ERR_BADAREA;
else {
@@ -998,6 +1043,7 @@ int ced_kill_io(struct ced_data *ced)
int ced_state_of_1401(struct ced_data *ced)
{
int ret;
+
mutex_lock(&ced->io_mutex);
ced_quick_check(ced, false, false); /* get state up to date, no reset */
@@ -1018,6 +1064,7 @@ int ced_state_of_1401(struct ced_data *ced)
int ced_start_self_test(struct ced_data *ced)
{
int got;
+
mutex_lock(&ced->io_mutex);
dev_dbg(&ced->interface->dev, "%s\n", __func__);
@@ -1050,6 +1097,7 @@ int ced_check_self_test(struct ced_data *ced,
TGET_SELFTEST __user *ugst)
unsigned int state, error;
int ret;
TGET_SELFTEST gst; /* local work space */
+
memset(&gst, 0, sizeof(gst)); /* clear out the space (sets code 0) */
mutex_lock(&ced->io_mutex);
@@ -1087,6 +1135,7 @@ int ced_check_self_test(struct ced_data *ced,
TGET_SELFTEST __user *ugst)
"Self-test error code %d\n", gst.code);
} else { /* No error, check for timeout */
unsigned long now = jiffies; /* get current time */
+
if (time_after(now, ced->self_test_time)) {
gst.code = -2; /* Flag the timeout */
dev_dbg(&ced->interface->dev,
@@ -1253,8 +1302,8 @@ int ced_dbg_poke(struct ced_data *ced, TDBGBLOCK __user
*udb)
/****************************************************************************
** ced_dbg_ramp_data
**
-** Execute the diagnostic ramp data operation. Parameters are in the CSBLOCK
struct
-** in order address, default, enable mask, size and repeats.
+** Execute the diagnostic ramp data operation. Parameters are in the CSBLOCK
+** struct in order address, default, enable mask, size and repeats.
****************************************************************************/
int ced_dbg_ramp_data(struct ced_data *ced, TDBGBLOCK __user *udb)
{
@@ -1426,6 +1475,7 @@ int ced_get_circ_block(struct ced_data *ced, TCIRCBLOCK
__user *ucb)
if (area < MAX_TRANSAREAS) { /* The area number must be OK */
/* Pointer to relevant info */
struct transarea *ta = &ced->trans_def[area];
+
spin_lock_irq(&ced->staged_lock); /* Lock others out */
if ((ta->used) && (ta->circular) && /* Must be circular area */
@@ -1486,7 +1536,8 @@ int ced_free_circ_block(struct ced_data *ced, TCIRCBLOCK
__user *ucb)
bool waiting = false;
if ((ta->blocks[0].size >= size) && /* Got anything? */
- (ta->blocks[0].offset == start)) { /* Must be legal
data */
+ /* Must be legal data */
+ (ta->blocks[0].offset == start)) {
ta->blocks[0].size -= size;
ta->blocks[0].offset += size;
--
1.7.10.4
_______________________________________________
devel mailing list
[email protected]
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel