Commit f6b8c321 authored by Sebastian Andrzej Siewior's avatar Sebastian Andrzej Siewior Committed by Stefan Rauch

wishbone: Let write callback talk to slave directly and process MSI.

After handle_write_cfg(, WBA_ERR, ) the function wakes a worker which
will talk to the hardware and process the MSI. This worker can be
delayed if the system is busy leading to latency spikes during the
communication.

The detour via the worker can be avoided and the request can be
completed within the write request. Doing it within handle_write_cfg()
could be possible because wishbone_process_msi() is using its own buffer
for communication and only the locking is in the way.
It looks safer and simpler to simply wait until all locks are released
and process the MSI afterwards if needed.
This also mimics the previous workflow except that there is less delay
now.

Don't schedule the worker from handle_write_cfg() but process the MSI
request directly from the write callback if needed.
Signed-off-by: 's avatarSebastian Andrzej Siewior <bigeasy@linutronix.de>
Reviewed-by: 's avatarKurt Kanzenbach <kurt@linutronix.de>
parent 9ba271b6
......@@ -256,9 +256,10 @@ static wb_data_t handle_read_cfg(struct etherbone_master_context* context, wb_ad
}
/* Must be called with both context_mutex and device_mutex held */
static void handle_write_cfg(struct etherbone_master_context* context, wb_addr_t addr, wb_data_t data)
static bool handle_write_cfg(struct etherbone_master_context* context, wb_addr_t addr, wb_data_t data)
{
struct wishbone *wb = context->wishbone;
bool need_process = false;
switch (addr) {
case 36:
......@@ -276,24 +277,26 @@ static void handle_write_cfg(struct etherbone_master_context* context, wb_addr_t
context->msi_pending = 0;
wb->msi_pending = 0;
wb->wops->reply(wb, data&1, context->msi_data);
wishbone_slave_ready(wb);
need_process = true;
}
break;
}
return need_process;
}
/* Must be called with context_mutex held */
static void etherbone_master_process(struct etherbone_master_context* context)
static bool etherbone_master_process(struct etherbone_master_context* context)
{
struct wishbone *wb;
const struct wishbone_operations *wops;
unsigned int size, left, i, record_len;
bool need_process_msi = false;
unsigned char *buf;
if (context->state == header) {
if (context->received < 8) {
/* no-op */
return;
return need_process_msi;
}
context->buf[0] = 0x4E;
......@@ -353,7 +356,7 @@ static void etherbone_master_process(struct etherbone_master_context* context)
for (j = wcount; j > 0; --j) {
eb_from_cpu(buf+i, 0);
i = RING_INDEX(i + sizeof(wb_data_t));
handle_write_cfg(context, base_address, eb_to_cpu(buf+i));
need_process_msi |= handle_write_cfg(context, base_address, eb_to_cpu(buf+i));
base_address += increment;
}
} else {
......@@ -403,6 +406,8 @@ static void etherbone_master_process(struct etherbone_master_context* context)
}
context->processed = RING_POS(context->processed + size - left);
return need_process_msi;
}
static int char_master_open(struct inode *inode, struct file *filep)
......@@ -539,6 +544,7 @@ static ssize_t char_master_aio_write(struct kiocb *iocb, const struct iovec *iov
struct file *filep = iocb->ki_filp;
struct etherbone_master_context *context = filep->private_data;
unsigned int len, iov_len, ring_len, buf_len;
bool need_process_msi;
iov_len = iov_length(iov, nr_segs);
if (unlikely(iov_len == 0)) return 0;
......@@ -561,9 +567,11 @@ static ssize_t char_master_aio_write(struct kiocb *iocb, const struct iovec *iov
context->received = RING_POS(context->received + len);
/* Process buffers */
etherbone_master_process(context);
need_process_msi = etherbone_master_process(context);
mutex_unlock(&context->context_mutex);
if (need_process_msi)
wishbone_process_msi(context->wishbone);
/* Wake-up polling descriptors */
wake_up_interruptible(&context->waitq);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment