in xillybus/xillybus_core.c [690:1005]
static ssize_t xillybus_read(struct file *filp, char __user *userbuf,
size_t count, loff_t *f_pos)
{
ssize_t rc;
unsigned long flags;
int bytes_done = 0;
int no_time_left = 0;
long deadline, left_to_sleep;
struct xilly_channel *channel = filp->private_data;
int empty, reached_eof, exhausted, ready;
/* Initializations are there only to silence warnings */
int howmany = 0, bufpos = 0, bufidx = 0, bufferdone = 0;
int waiting_bufidx;
if (channel->endpoint->fatal_error)
return -EIO;
deadline = jiffies + 1 + XILLY_RX_TIMEOUT;
rc = mutex_lock_interruptible(&channel->wr_mutex);
if (rc)
return rc;
while (1) { /* Note that we may drop mutex within this loop */
int bytes_to_do = count - bytes_done;
spin_lock_irqsave(&channel->wr_spinlock, flags);
empty = channel->wr_empty;
ready = !empty || channel->wr_ready;
if (!empty) {
bufidx = channel->wr_host_buf_idx;
bufpos = channel->wr_host_buf_pos;
howmany = ((channel->wr_buffers[bufidx]->end_offset
+ 1) << channel->log2_element_size)
- bufpos;
/* Update wr_host_* to its post-operation state */
if (howmany > bytes_to_do) {
bufferdone = 0;
howmany = bytes_to_do;
channel->wr_host_buf_pos += howmany;
} else {
bufferdone = 1;
channel->wr_host_buf_pos = 0;
if (bufidx == channel->wr_fpga_buf_idx) {
channel->wr_empty = 1;
channel->wr_sleepy = 1;
channel->wr_ready = 0;
}
if (bufidx >= (channel->num_wr_buffers - 1))
channel->wr_host_buf_idx = 0;
else
channel->wr_host_buf_idx++;
}
}
/*
* Marking our situation after the possible changes above,
* for use after releasing the spinlock.
*
* empty = empty before change
* exhasted = empty after possible change
*/
reached_eof = channel->wr_empty &&
(channel->wr_host_buf_idx == channel->wr_eof);
channel->wr_hangup = reached_eof;
exhausted = channel->wr_empty;
waiting_bufidx = channel->wr_host_buf_idx;
spin_unlock_irqrestore(&channel->wr_spinlock, flags);
if (!empty) { /* Go on, now without the spinlock */
if (bufpos == 0) /* Position zero means it's virgin */
dma_sync_single_for_cpu(channel->endpoint->dev,
channel->wr_buffers[bufidx]->dma_addr,
channel->wr_buf_size,
DMA_FROM_DEVICE);
if (copy_to_user(
userbuf,
channel->wr_buffers[bufidx]->addr
+ bufpos, howmany))
rc = -EFAULT;
userbuf += howmany;
bytes_done += howmany;
if (bufferdone) {
dma_sync_single_for_device(channel->endpoint->dev,
channel->wr_buffers[bufidx]->dma_addr,
channel->wr_buf_size,
DMA_FROM_DEVICE);
/*
* Tell FPGA the buffer is done with. It's an
* atomic operation to the FPGA, so what
* happens with other channels doesn't matter,
* and the certain channel is protected with
* the channel-specific mutex.
*/
iowrite32(1 | (channel->chan_num << 1) |
(bufidx << 12),
channel->endpoint->registers +
fpga_buf_ctrl_reg);
}
if (rc) {
mutex_unlock(&channel->wr_mutex);
return rc;
}
}
/* This includes a zero-count return = EOF */
if ((bytes_done >= count) || reached_eof)
break;
if (!exhausted)
continue; /* More in RAM buffer(s)? Just go on. */
if ((bytes_done > 0) &&
(no_time_left ||
(channel->wr_synchronous && channel->wr_allow_partial)))
break;
/*
* Nonblocking read: The "ready" flag tells us that the FPGA
* has data to send. In non-blocking mode, if it isn't on,
* just return. But if there is, we jump directly to the point
* where we ask for the FPGA to send all it has, and wait
* until that data arrives. So in a sense, we *do* block in
* nonblocking mode, but only for a very short time.
*/
if (!no_time_left && (filp->f_flags & O_NONBLOCK)) {
if (bytes_done > 0)
break;
if (ready)
goto desperate;
rc = -EAGAIN;
break;
}
if (!no_time_left || (bytes_done > 0)) {
/*
* Note that in case of an element-misaligned read
* request, offsetlimit will include the last element,
* which will be partially read from.
*/
int offsetlimit = ((count - bytes_done) - 1) >>
channel->log2_element_size;
int buf_elements = channel->wr_buf_size >>
channel->log2_element_size;
/*
* In synchronous mode, always send an offset limit.
* Just don't send a value too big.
*/
if (channel->wr_synchronous) {
/* Don't request more than one buffer */
if (channel->wr_allow_partial &&
(offsetlimit >= buf_elements))
offsetlimit = buf_elements - 1;
/* Don't request more than all buffers */
if (!channel->wr_allow_partial &&
(offsetlimit >=
(buf_elements * channel->num_wr_buffers)))
offsetlimit = buf_elements *
channel->num_wr_buffers - 1;
}
/*
* In asynchronous mode, force early flush of a buffer
* only if that will allow returning a full count. The
* "offsetlimit < ( ... )" rather than "<=" excludes
* requesting a full buffer, which would obviously
* cause a buffer transmission anyhow
*/
if (channel->wr_synchronous ||
(offsetlimit < (buf_elements - 1))) {
mutex_lock(&channel->endpoint->register_mutex);
iowrite32(offsetlimit,
channel->endpoint->registers +
fpga_buf_offset_reg);
iowrite32(1 | (channel->chan_num << 1) |
(2 << 24) | /* 2 = offset limit */
(waiting_bufidx << 12),
channel->endpoint->registers +
fpga_buf_ctrl_reg);
mutex_unlock(&channel->endpoint->
register_mutex);
}
}
/*
* If partial completion is disallowed, there is no point in
* timeout sleeping. Neither if no_time_left is set and
* there's no data.
*/
if (!channel->wr_allow_partial ||
(no_time_left && (bytes_done == 0))) {
/*
* This do-loop will run more than once if another
* thread reasserted wr_sleepy before we got the mutex
* back, so we try again.
*/
do {
mutex_unlock(&channel->wr_mutex);
if (wait_event_interruptible(
channel->wr_wait,
(!channel->wr_sleepy)))
goto interrupted;
if (mutex_lock_interruptible(
&channel->wr_mutex))
goto interrupted;
} while (channel->wr_sleepy);
continue;
interrupted: /* Mutex is not held if got here */
if (channel->endpoint->fatal_error)
return -EIO;
if (bytes_done)
return bytes_done;
if (filp->f_flags & O_NONBLOCK)
return -EAGAIN; /* Don't admit snoozing */
return -EINTR;
}
left_to_sleep = deadline - ((long) jiffies);
/*
* If our time is out, skip the waiting. We may miss wr_sleepy
* being deasserted but hey, almost missing the train is like
* missing it.
*/
if (left_to_sleep > 0) {
left_to_sleep =
wait_event_interruptible_timeout(
channel->wr_wait,
(!channel->wr_sleepy),
left_to_sleep);
if (left_to_sleep > 0) /* wr_sleepy deasserted */
continue;
if (left_to_sleep < 0) { /* Interrupt */
mutex_unlock(&channel->wr_mutex);
if (channel->endpoint->fatal_error)
return -EIO;
if (bytes_done)
return bytes_done;
return -EINTR;
}
}
desperate:
no_time_left = 1; /* We're out of sleeping time. Desperate! */
if (bytes_done == 0) {
/*
* Reaching here means that we allow partial return,
* that we've run out of time, and that we have
* nothing to return.
* So tell the FPGA to send anything it has or gets.
*/
iowrite32(1 | (channel->chan_num << 1) |
(3 << 24) | /* Opcode 3, flush it all! */
(waiting_bufidx << 12),
channel->endpoint->registers +
fpga_buf_ctrl_reg);
}
/*
* Reaching here means that we *do* have data in the buffer,
* but the "partial" flag disallows returning less than
* required. And we don't have as much. So loop again,
* which is likely to end up blocking indefinitely until
* enough data has arrived.
*/
}
mutex_unlock(&channel->wr_mutex);
if (channel->endpoint->fatal_error)
return -EIO;
if (rc)
return rc;
return bytes_done;
}