unsigned int afu_poll(struct file *file, struct poll_table_struct *poll) { struct cxl_context *ctx = file->private_data; int mask = 0; unsigned long flags; poll_wait(file, &ctx->wq, poll); pr_devel("afu_poll wait done pe: %i\n", ctx->pe); spin_lock_irqsave(&ctx->lock, flags); if (ctx_event_pending(ctx)) mask |= POLLIN | POLLRDNORM; else if (ctx->status == CLOSED) /* Only error on closed when there are no futher events pending */ mask |= POLLERR; spin_unlock_irqrestore(&ctx->lock, flags); pr_devel("afu_poll pe: %i returning %#x\n", ctx->pe, mask); return mask; }
static ssize_t afu_read(struct file *file, char __user *buf, size_t count, loff_t *off) { struct cxl_context *ctx = file->private_data; struct cxl_event event; unsigned long flags; int rc; DEFINE_WAIT(wait); if (count < CXL_READ_MIN_SIZE) return -EINVAL; spin_lock_irqsave(&ctx->lock, flags); for (;;) { prepare_to_wait(&ctx->wq, &wait, TASK_INTERRUPTIBLE); if (ctx_event_pending(ctx)) break; if (file->f_flags & O_NONBLOCK) { rc = -EAGAIN; goto out; } if (signal_pending(current)) { rc = -ERESTARTSYS; goto out; } spin_unlock_irqrestore(&ctx->lock, flags); pr_devel("afu_read going to sleep...\n"); schedule(); pr_devel("afu_read woken up\n"); spin_lock_irqsave(&ctx->lock, flags); } finish_wait(&ctx->wq, &wait); memset(&event, 0, sizeof(event)); event.header.process_element = ctx->pe; event.header.size = sizeof(struct cxl_event_header); if (ctx->pending_irq) { pr_devel("afu_read delivering AFU interrupt\n"); event.header.size += sizeof(struct cxl_event_afu_interrupt); event.header.type = CXL_EVENT_AFU_INTERRUPT; event.irq.irq = find_first_bit(ctx->irq_bitmap, ctx->irq_count) + 1; clear_bit(event.irq.irq - 1, ctx->irq_bitmap); if (bitmap_empty(ctx->irq_bitmap, ctx->irq_count)) ctx->pending_irq = false; } else if (ctx->pending_fault) { pr_devel("afu_read delivering data storage fault\n"); event.header.size += sizeof(struct cxl_event_data_storage); event.header.type = CXL_EVENT_DATA_STORAGE; event.fault.addr = ctx->fault_addr; event.fault.dsisr = ctx->fault_dsisr; ctx->pending_fault = false; } else if (ctx->pending_afu_err) { pr_devel("afu_read delivering afu error\n"); event.header.size += sizeof(struct cxl_event_afu_error); event.header.type = CXL_EVENT_AFU_ERROR; event.afu_error.error = ctx->afu_err; ctx->pending_afu_err = false; } else if (ctx->status == CLOSED) { pr_devel("afu_read fatal error\n"); spin_unlock_irqrestore(&ctx->lock, flags); return -EIO; } else WARN(1, "afu_read must be buggy\n"); spin_unlock_irqrestore(&ctx->lock, flags); if (copy_to_user(buf, &event, event.header.size)) return -EFAULT; return event.header.size; out: finish_wait(&ctx->wq, &wait); spin_unlock_irqrestore(&ctx->lock, flags); return rc; }