diff --git a/pcie-wb/wishbone.c b/pcie-wb/wishbone.c index aef2fd2d2ad805963d61468246264e3d13efdb4a..eae964840106c17ffbcb6d8365c0eac0681fa599 100644 --- a/pcie-wb/wishbone.c +++ b/pcie-wb/wishbone.c @@ -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);