m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcin Chrzanowski <marcin.j.chrzanowski@gmail.com>2018-05-26 21:01:28 +0200
committerMarcin Chrzanowski <marcin.j.chrzanowski@gmail.com>2018-05-26 21:01:28 +0200
commit0e125c3e6d2fafd6c2460e1859c29b9ece8b5eed (patch)
tree6e531c8c5317f0de19b71fcd7e38dc0235ebf57a
parent911ab1a4ad24fb3c4f6df5c4798a8f2656c09af7 (diff)
Fix synchronization
-rw-r--r--harddoomdev.c199
-rw-r--r--harddoomdev.h4
-rw-r--r--pci.c19
-rw-r--r--private_data.h10
-rw-r--r--surface.c20
5 files changed, 174 insertions, 78 deletions
diff --git a/harddoomdev.c b/harddoomdev.c
index 823e868..26eb34e 100644
--- a/harddoomdev.c
+++ b/harddoomdev.c
@@ -6,6 +6,8 @@
#include "private_data.h"
#include "util.h"
+#define PING_FREQUENCY 0x80
+
void doomdev_write(void __iomem *iomem, size_t addr, uint32_t data)
{
iowrite32(data, iomem + addr);
@@ -21,11 +23,44 @@ void write_command(void __iomem *iomem, uint32_t command)
doomdev_write(iomem, HARDDOOM_FIFO_SEND, command);
}
-void send_command(void __iomem *iomem, uint32_t command)
+void enable_intr(void __iomem *iomem, uint32_t intr)
+{
+ uint32_t interrupts;
+
+ interrupts = doomdev_read(iomem, HARDDOOM_INTR_ENABLE);
+ doomdev_write(iomem, HARDDOOM_INTR_ENABLE, interrupts | intr);
+}
+
+void disable_intr(void __iomem *iomem, uint32_t intr)
{
- while (doomdev_read(iomem, HARDDOOM_FIFO_FREE) == 0) {}
+ uint32_t interrupts;
- write_command(iomem, command);
+ interrupts = doomdev_read(iomem, HARDDOOM_INTR_ENABLE);
+ doomdev_write(iomem, HARDDOOM_INTR_ENABLE, interrupts & (~intr));
+}
+
+void send_command(struct doom_data *doom_data, uint32_t command)
+{
+ uint32_t free;
+
+ free = doomdev_read(doom_data->iomem, HARDDOOM_FIFO_FREE);
+ if (free == 0) {
+ deactivate_intr(doom_data->iomem, HARDDOOM_INTR_PONG_ASYNC);
+ }
+
+ if (free == 0) {
+ enable_intr(doom_data->iomem, HARDDOOM_INTR_PONG_ASYNC);
+ down(&doom_data->pong_async_sem);
+ }
+
+ if (doom_data->cmd_counter > PING_FREQUENCY) {
+ doom_data->cmd_counter = 0;
+ write_command(doom_data->iomem, HARDDOOM_CMD_PING_ASYNC);
+ } else {
+ doom_data->cmd_counter++;
+ }
+
+ write_command(doom_data->iomem, command);
}
uint32_t get_interrupts(void __iomem *iomem)
@@ -33,134 +68,157 @@ uint32_t get_interrupts(void __iomem *iomem)
return doomdev_read(iomem, HARDDOOM_INTR);
}
+uint32_t get_enabled_interrupts(void __iomem *iomem)
+{
+ return doomdev_read(iomem, HARDDOOM_INTR_ENABLE);
+}
+
void deactivate_intr(void __iomem *iomem, uint32_t intr)
{
doomdev_write(iomem, HARDDOOM_INTR, intr);
}
-void ping_sync(void __iomem *iomem)
+void ping_sync(struct doom_data *doom_data)
{
- send_command(iomem, HARDDOOM_CMD_PING_SYNC);
+ send_command(doom_data, HARDDOOM_CMD_PING_SYNC);
}
-void set_surf_src_pt(void __iomem *iomem, dma_addr_t page_table)
+void set_surf_src_pt(struct doom_data *doom_data, dma_addr_t page_table)
{
- send_command(iomem, HARDDOOM_CMD_SURF_SRC_PT(page_table));
+ send_command(doom_data, HARDDOOM_CMD_SURF_SRC_PT(page_table));
}
-void set_surf_dst_pt(void __iomem *iomem, dma_addr_t page_table)
+void set_surf_dst_pt(struct doom_data *doom_data, dma_addr_t page_table)
{
- send_command(iomem, HARDDOOM_CMD_SURF_DST_PT(page_table));
+ send_command(doom_data, HARDDOOM_CMD_SURF_DST_PT(page_table));
}
-void set_surf_dims(void __iomem *iomem, uint32_t width, uint32_t height)
+void set_surf_dims(struct doom_data *doom_data, uint32_t width, uint32_t height)
{
- send_command(iomem, HARDDOOM_CMD_SURF_DIMS(width, height));
+ send_command(doom_data, HARDDOOM_CMD_SURF_DIMS(width, height));
}
-void set_xy_a(void __iomem *iomem, uint16_t x, uint16_t y)
+void set_xy_a(struct doom_data *doom_data, uint16_t x, uint16_t y)
{
- send_command(iomem, HARDDOOM_CMD_XY_A(x, y));
+ send_command(doom_data, HARDDOOM_CMD_XY_A(x, y));
}
-void set_xy_b(void __iomem *iomem, uint16_t x, uint16_t y)
+void set_xy_b(struct doom_data *doom_data, uint16_t x, uint16_t y)
{
- send_command(iomem, HARDDOOM_CMD_XY_B(x, y));
+ send_command(doom_data, HARDDOOM_CMD_XY_B(x, y));
}
-void set_fill_color(void __iomem *iomem, uint8_t color)
+void set_fill_color(struct doom_data *doom_data, uint8_t color)
{
- send_command(iomem, HARDDOOM_CMD_FILL_COLOR(color));
+ send_command(doom_data, HARDDOOM_CMD_FILL_COLOR(color));
}
-void set_texture_pt(void __iomem *iomem, dma_addr_t page_table_dev)
+void set_texture_pt(struct doom_data *doom_data, dma_addr_t page_table_dev)
{
- send_command(iomem, HARDDOOM_CMD_TEXTURE_PT(page_table_dev));
+ send_command(doom_data, HARDDOOM_CMD_TEXTURE_PT(page_table_dev));
}
-void set_texture_dims(void __iomem *iomem, uint32_t size, uint16_t height)
+void set_texture_dims(struct doom_data *doom_data, uint32_t size, uint16_t height)
{
- send_command(iomem, HARDDOOM_CMD_TEXTURE_DIMS(size,height));
+ send_command(doom_data, HARDDOOM_CMD_TEXTURE_DIMS(size,height));
}
-void set_ustart(void __iomem *iomem, uint32_t ustart)
+void set_flat(struct doom_data *doom_data, dma_addr_t flat_dev)
{
- send_command(iomem, HARDDOOM_CMD_USTART(ustart));
+ send_command(doom_data, HARDDOOM_CMD_FLAT_ADDR(flat_dev));
}
-void set_ustep(void __iomem *iomem, uint32_t ustep)
+void set_ustart(struct doom_data *doom_data, uint32_t ustart)
{
- send_command(iomem, HARDDOOM_CMD_USTEP(ustep));
+ send_command(doom_data, HARDDOOM_CMD_USTART(ustart));
}
-void set_draw_params(void __iomem *iomem, uint8_t flags)
+void set_ustep(struct doom_data *doom_data, uint32_t ustep)
{
- send_command(iomem, HARDDOOM_CMD_DRAW_PARAMS(flags));
+ send_command(doom_data, HARDDOOM_CMD_USTEP(ustep));
}
-void fill_rect(struct surface_data *surface_data, struct doomdev_fill_rect rect)
+void set_vstart(struct doom_data *doom_data, uint32_t vstart)
{
- void __iomem *iomem;
-
- iomem = surface_data->doom_data->iomem;
+ send_command(doom_data, HARDDOOM_CMD_VSTART(vstart));
+}
- set_surf_dst_pt(iomem, surface_data->page_table_dev);
- set_surf_dims(iomem, surface_data->width, surface_data->height);
- set_xy_a(iomem, rect.pos_dst_x, rect.pos_dst_y);
- set_fill_color(iomem, rect.color);
+void set_vstep(struct doom_data *doom_data, uint32_t vstep)
+{
+ send_command(doom_data, HARDDOOM_CMD_VSTEP(vstep));
+}
- send_command(iomem, HARDDOOM_CMD_FILL_RECT(rect.width, rect.height));
+void set_draw_params(struct doom_data *doom_data, uint8_t flags)
+{
+ send_command(doom_data, HARDDOOM_CMD_DRAW_PARAMS(flags));
}
-void draw_line(struct surface_data *surface_data, struct doomdev_line line)
+void fill_rect(struct surface_data *surface_data, struct doomdev_fill_rect rect)
{
- void __iomem *iomem;
+ set_surf_dst_pt(surface_data->doom_data, surface_data->page_table_dev);
+ set_surf_dims(surface_data->doom_data, surface_data->width, surface_data->height);
+ set_xy_a(surface_data->doom_data, rect.pos_dst_x, rect.pos_dst_y);
+ set_fill_color(surface_data->doom_data, rect.color);
- iomem = surface_data->doom_data->iomem;
+ send_command(surface_data->doom_data, HARDDOOM_CMD_FILL_RECT(rect.width, rect.height));
+}
- set_surf_dst_pt(iomem, surface_data->page_table_dev);
- set_surf_dims(iomem, surface_data->width, surface_data->height);
- set_xy_a(iomem, line.pos_a_x, line.pos_a_y);
- set_xy_b(iomem, line.pos_b_x, line.pos_b_y);
- set_fill_color(iomem, line.color);
+void draw_line(struct surface_data *surface_data, struct doomdev_line line)
+{
+ set_surf_dst_pt(surface_data->doom_data, surface_data->page_table_dev);
+ set_surf_dims(surface_data->doom_data, surface_data->width, surface_data->height);
+ set_xy_a(surface_data->doom_data, line.pos_a_x, line.pos_a_y);
+ set_xy_b(surface_data->doom_data, line.pos_b_x, line.pos_b_y);
+ set_fill_color(surface_data->doom_data, line.color);
- send_command(iomem, HARDDOOM_CMD_DRAW_LINE);
+ send_command(surface_data->doom_data, HARDDOOM_CMD_DRAW_LINE);
}
void copy_rect(struct surface_data *dst_data, struct surface_data *src_data,
struct doomdev_copy_rect rect)
{
- void __iomem *iomem;
-
- iomem = dst_data->doom_data->iomem;
+ set_surf_dst_pt(dst_data->doom_data, dst_data->page_table_dev);
+ set_surf_src_pt(dst_data->doom_data, src_data->page_table_dev);
+ set_surf_dims(dst_data->doom_data, dst_data->width, dst_data->height);
+ set_xy_a(dst_data->doom_data, rect.pos_dst_x, rect.pos_dst_y);
+ set_xy_b(dst_data->doom_data, rect.pos_src_x, rect.pos_src_y);
- set_surf_dst_pt(iomem, dst_data->page_table_dev);
- set_surf_src_pt(iomem, src_data->page_table_dev);
- set_surf_dims(iomem, dst_data->width, dst_data->height);
- set_xy_a(iomem, rect.pos_dst_x, rect.pos_dst_y);
- set_xy_b(iomem, rect.pos_src_x, rect.pos_src_y);
-
- send_command(iomem, HARDDOOM_CMD_COPY_RECT(rect.width, rect.height));
+ send_command(dst_data->doom_data, HARDDOOM_CMD_COPY_RECT(rect.width, rect.height));
}
void draw_column(struct surface_data *surface_data,
struct texture_data *texture_data, struct doomdev_column column)
{
- void __iomem *iomem;
-
- iomem = surface_data->doom_data->iomem;
-
- set_surf_dst_pt(iomem, surface_data->page_table_dev);
- set_surf_dims(iomem, surface_data->width, surface_data->height);
- set_texture_pt(iomem, texture_data->page_table_dev);
- set_texture_dims(iomem, texture_data->size, texture_data->height);
- set_xy_a(iomem, column.x, column.y1);
- set_xy_b(iomem, column.x, column.y2);
- set_ustart(iomem, column.ustart);
- set_ustep(iomem, column.ustep);
- set_draw_params(iomem, 0);
+ set_surf_dst_pt(surface_data->doom_data, surface_data->page_table_dev);
+ set_surf_dims(surface_data->doom_data, surface_data->width, surface_data->height);
+ set_texture_pt(surface_data->doom_data, texture_data->page_table_dev);
+ set_texture_dims(surface_data->doom_data, texture_data->size, texture_data->height);
+ set_xy_a(surface_data->doom_data, column.x, column.y1);
+ set_xy_b(surface_data->doom_data, column.x, column.y2);
+ set_ustart(surface_data->doom_data, column.ustart);
+ set_ustep(surface_data->doom_data, column.ustep);
+ set_draw_params(surface_data->doom_data, 0);
+
+ send_command(surface_data->doom_data,
+ HARDDOOM_CMD_DRAW_COLUMN(column.texture_offset));
+}
- send_command(iomem, HARDDOOM_CMD_DRAW_COLUMN(column.texture_offset));
+void draw_span(struct surface_data *surface_data, struct flat_data *flat_data,
+ struct doomdev_span span)
+{
+ set_surf_dst_pt(surface_data->doom_data, surface_data->page_table_dev);
+ set_surf_dims(surface_data->doom_data, surface_data->width,
+ surface_data->height);
+ set_flat(surface_data->doom_data, flat_data->flat_dev);
+ set_xy_a(surface_data->doom_data, span.x1, span.y);
+ set_xy_b(surface_data->doom_data, span.x2, span.y);
+ set_ustart(surface_data->doom_data, span.ustart);
+ set_ustep(surface_data->doom_data, span.ustep);
+ set_vstart(surface_data->doom_data, span.vstart);
+ set_vstep(surface_data->doom_data, span.vstep);
+ set_draw_params(surface_data->doom_data, 0);
+
+ send_command(surface_data->doom_data, HARDDOOM_CMD_DRAW_SPAN);
}
uint32_t doomdev_read_stat(void __iomem *iomem, size_t stat)
@@ -188,7 +246,8 @@ void start_dev(struct pci_dev *dev)
load_microcode(iomem);
doomdev_write(iomem, HARDDOOM_RESET, 0xffffffe);
- doomdev_write(iomem, HARDDOOM_INTR, HARDDOOM_INTR_MASK);
+ doomdev_write(iomem, HARDDOOM_INTR,
+ HARDDOOM_INTR_MASK ^ HARDDOOM_INTR_PONG_ASYNC);
doomdev_write(iomem, HARDDOOM_INTR_ENABLE, HARDDOOM_INTR_MASK);
doomdev_write(iomem, HARDDOOM_ENABLE,
HARDDOOM_ENABLE_ALL ^ HARDDOOM_ENABLE_FETCH_CMD);
diff --git a/harddoomdev.h b/harddoomdev.h
index 929d5f2..ab7a398 100644
--- a/harddoomdev.h
+++ b/harddoomdev.h
@@ -10,8 +10,10 @@ void start_dev(struct pci_dev *dev);
void shutdown_dev(struct pci_dev *dev);
uint32_t get_interrupts(void __iomem *iomem);
+uint32_t get_enabled_interrupts(void __iomem *iomem);
void deactivate_intr(void __iomem *iomem, uint32_t intr);
-void ping_sync(void __iomem *iomem);
+void disable_intr(void __iomem *iomem, uint32_t intr);
+void ping_sync(struct doom_data *doom_data);
void draw_line(struct surface_data *surface_data, struct doomdev_line line);
void fill_rect(struct surface_data *surface_data, struct doomdev_fill_rect rect);
diff --git a/pci.c b/pci.c
index 3c45d9b..69783d6 100644
--- a/pci.c
+++ b/pci.c
@@ -15,14 +15,25 @@ void handle_pong_sync(struct doom_data *doom_data)
up(&doom_data->pong_sem);
}
+void handle_pong_async(struct doom_data *doom_data)
+{
+ up(&doom_data->pong_async_sem);
+ disable_intr(doom_data->iomem, HARDDOOM_INTR_PONG_ASYNC);
+}
+
irqreturn_t doom_irq(int irq, void *dev)
{
uint32_t interrupts;
struct doom_data *doom_data;
+ void __iomem *iomem;
+
doom_data = dev;
+ iomem = doom_data->iomem;
- interrupts = get_interrupts(doom_data->iomem);
+ interrupts = ioread32(iomem + HARDDOOM_INTR) & ioread32(iomem + HARDDOOM_INTR_ENABLE);
+ iowrite32(interrupts, iomem + HARDDOOM_INTR);
+
if (!interrupts) {
return IRQ_NONE;
}
@@ -32,7 +43,9 @@ irqreturn_t doom_irq(int irq, void *dev)
interrupts &= ~HARDDOOM_INTR_PONG_SYNC;
}
- deactivate_intr(doom_data->iomem, HARDDOOM_INTR_MASK);
+ if (interrupts & HARDDOOM_INTR_PONG_ASYNC) {
+ handle_pong_async(doom_data);
+ }
return IRQ_HANDLED;
}
@@ -61,6 +74,8 @@ int init_pci(struct pci_dev *dev)
mutex_init(&doom_data->cmd_mutex);
mutex_init(&doom_data->ping_mutex);
sema_init(&doom_data->pong_sem, 0);
+ sema_init(&doom_data->pong_async_sem, 0);
+ doom_data->cmd_counter = 0;
ORFAIL(request_irq(dev->irq, doom_irq, IRQF_SHARED,
"doom", doom_data), error_irq);
diff --git a/private_data.h b/private_data.h
index ae1bf3e..fed5b60 100644
--- a/private_data.h
+++ b/private_data.h
@@ -12,6 +12,9 @@ struct doom_data {
struct mutex cmd_mutex;
struct mutex ping_mutex;
struct semaphore pong_sem;
+ struct semaphore pong_async_sem;
+
+ uint16_t cmd_counter;
};
struct surface_data {
@@ -42,4 +45,11 @@ struct texture_data {
dma_addr_t page_table_dev;
};
+struct flat_data {
+ struct doom_data *doom_data;
+
+ uint8_t *flat_cpu;
+ dma_addr_t flat_dev;
+};
+
#endif
diff --git a/surface.c b/surface.c
index a54ca6f..688223a 100644
--- a/surface.c
+++ b/surface.c
@@ -17,7 +17,7 @@ long draw_lines(struct file *filp, unsigned long arg)
struct doomdev_surf_ioctl_draw_lines *param;
struct doomdev_line *lines;
int i;
-
+
surface_data = filp->private_data;
param = (struct doomdev_surf_ioctl_draw_lines *) arg;
lines = (struct doomdev_line *) param->lines_ptr;
@@ -86,6 +86,8 @@ long copy_rects(struct file *filp, unsigned long arg)
mutex_unlock(&dst_data->doom_data->cmd_mutex);
+ fdput(src_fds);
+
return param->rects_num;
}
@@ -125,6 +127,8 @@ long draw_columns(struct file *filp, unsigned long arg)
mutex_unlock(&surface_data->doom_data->cmd_mutex);
+ fdput(texture_fds);
+
return param->columns_num;
}
@@ -159,9 +163,8 @@ ssize_t surface_read(struct file *filp, char __user *buf, size_t count,
count = surface_data->surface_size - *offset;
}
- mutex_lock(&surface_data->doom_data->ping_mutex);
- ping_sync(surface_data->doom_data->iomem);
-
+ mutex_lock(&surface_data->doom_data->cmd_mutex);
+ ping_sync(surface_data->doom_data);
down(&surface_data->doom_data->pong_sem);
not_written = copy_to_user(buf, surface_data->surface_cpu + (*offset),
@@ -169,7 +172,7 @@ ssize_t surface_read(struct file *filp, char __user *buf, size_t count,
*offset += count - not_written;
- mutex_unlock(&surface_data->doom_data->ping_mutex);
+ mutex_unlock(&surface_data->doom_data->cmd_mutex);
return count - not_written;
}
@@ -212,6 +215,11 @@ int surface_release(struct inode *inode, struct file *filp)
surface_data = filp->private_data;
+ mutex_lock(&surface_data->doom_data->ping_mutex);
+ ping_sync(surface_data->doom_data);
+ down(&surface_data->doom_data->pong_sem);
+ mutex_unlock(&surface_data->doom_data->ping_mutex);
+
free_surface_buffer(surface_data);
kfree(surface_data);
@@ -346,6 +354,8 @@ int new_surface(struct file *filp, struct doomdev_ioctl_create_surface *params)
fd_s.file->f_mode |= FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
+ fdput(fd_s);
+
return fd;
error_fdget: