From ad7eb306e3528ac98851528d4d6379b68b08d985 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E9=99=88=E6=81=92=E6=98=8E?= Date: Tue, 29 May 2012 16:27:08 +0800 Subject: [PATCH] Revert "vpu_service: replace spin_lock by mutex and use irq_thread to handle irq" This reverts commit d21aa293426f5dfdb1fd9173d3b4a8c64078bb1c. --- arch/arm/plat-rk/vpu_service.c | 160 ++++++++++++++------------------- 1 file changed, 69 insertions(+), 91 deletions(-) diff --git a/arch/arm/plat-rk/vpu_service.c b/arch/arm/plat-rk/vpu_service.c index 1e950b602a55..f4c333f3fe6e 100644 --- a/arch/arm/plat-rk/vpu_service.c +++ b/arch/arm/plat-rk/vpu_service.c @@ -136,12 +136,11 @@ typedef struct vpu_device { unsigned long iobaseaddr; unsigned int iosize; volatile u32 *hwregs; - atomic_t isr_codec; - atomic_t isr_pp; } vpu_device; typedef struct vpu_service_info { - struct mutex lock; + spinlock_t lock; + spinlock_t lock_power; struct timer_list timer; /* timer for power off */ struct list_head waiting; /* link to link_reg in struct vpu_reg */ struct list_head running; /* link to link_reg in struct vpu_reg */ @@ -275,9 +274,9 @@ static void vpu_service_power_off(void) { int total_running; - mutex_lock(&service.lock); + spin_lock_bh(&service.lock_power); if (!service.enabled) { - mutex_unlock(&service.lock); + spin_unlock_bh(&service.lock_power); return; } @@ -303,7 +302,7 @@ static void vpu_service_power_off(void) clk_disable(aclk_vepu); clk_disable(clk_vpu); printk("done\n"); - mutex_unlock(&service.lock); + spin_unlock_bh(&service.lock_power); } static void vpu_service_power_off_work_func(unsigned long data) @@ -312,11 +311,20 @@ static void vpu_service_power_off_work_func(unsigned long data) vpu_service_power_off(); } +static void vpu_service_power_maintain(void) +{ + if (service.enabled) { + mod_timer(&service.timer, jiffies + POWER_OFF_DELAY); + } else { + pr_err("error: maintain power when power is off!\n"); + } +} + static void vpu_service_power_on(void) { clk_enable(clk_vpu); /* notify vpu on without lock. */ - mutex_lock(&service.lock); + spin_lock_bh(&service.lock_power); if (!service.enabled) { service.enabled = true; printk("vpu: power on\n"); @@ -333,15 +341,19 @@ static void vpu_service_power_on(void) #endif udelay(10); clk_enable(aclk_ddr_vepu); + mod_timer(&service.timer, jiffies + POWER_OFF_DELAY); + spin_unlock_bh(&service.lock_power); + } else { + spin_unlock_bh(&service.lock_power); + vpu_service_power_maintain(); } - mod_timer(&service.timer, jiffies + POWER_OFF_DELAY); - mutex_unlock(&service.lock); clk_disable(clk_vpu); } static vpu_reg *reg_init(vpu_session *session, void __user *src, unsigned long size) { + unsigned long flag; vpu_reg *reg = kmalloc(sizeof(vpu_reg), GFP_KERNEL); if (NULL == reg) { pr_err("error: kmalloc fail in reg_init\n"); @@ -360,10 +372,10 @@ static vpu_reg *reg_init(vpu_session *session, void __user *src, unsigned long s return NULL; } - mutex_lock(&service.lock); + spin_lock_irqsave(&service.lock, flag); list_add_tail(®->status_link, &service.waiting); list_add_tail(®->session_link, &session->waiting); - mutex_unlock(&service.lock); + spin_unlock_irqrestore(&service.lock, flag); return reg; } @@ -517,13 +529,14 @@ void reg_copy_to_hw(vpu_reg *reg) static void try_set_reg(void) { + unsigned long flag; // first get reg from reg list - mutex_lock(&service.lock); + spin_lock_irqsave(&service.lock, flag); if (!list_empty(&service.waiting)) { int can_set = 0; vpu_reg *reg = list_entry(service.waiting.next, vpu_reg, status_link); - mod_timer(&service.timer, jiffies + POWER_OFF_DELAY); + vpu_service_power_maintain(); switch (reg->type) { case VPU_ENC : { if ((NULL == service.reg_codec) && (NULL == service.reg_pproc)) @@ -555,7 +568,7 @@ static void try_set_reg(void) reg_copy_to_hw(reg); } } - mutex_unlock(&service.lock); + spin_unlock_irqrestore(&service.lock, flag); } static int return_reg(vpu_reg *reg, u32 __user *dst) @@ -646,6 +659,7 @@ static long vpu_service_ioctl(struct file *filp, unsigned int cmd, unsigned long case VPU_IOC_GET_REG : { vpu_request req; vpu_reg *reg; + unsigned long flag; if (copy_from_user(&req, (void __user *)arg, sizeof(vpu_request))) { pr_err("error: VPU_IOC_GET_REG copy_from_user failed\n"); return -EFAULT; @@ -664,7 +678,7 @@ static long vpu_service_ioctl(struct file *filp, unsigned int cmd, unsigned long ret = -ETIMEDOUT; } } - mutex_lock(&service.lock); + spin_lock_irqsave(&service.lock, flag); if (ret < 0) { int task_running = atomic_read(&session->task_running); vpu_service_dump(); @@ -676,15 +690,15 @@ static long vpu_service_ioctl(struct file *filp, unsigned int cmd, unsigned long printk("done\n"); } vpu_service_session_clear(session); - mutex_unlock(&service.lock); + spin_unlock_irqrestore(&service.lock, flag); return ret; } - mutex_unlock(&service.lock); + spin_unlock_irqrestore(&service.lock, flag); } - mutex_lock(&service.lock); + spin_lock_irqsave(&service.lock, flag); reg = list_entry(session->done.next, vpu_reg, session_link); return_reg(reg, (u32 __user *)req.req); - mutex_unlock(&service.lock); + spin_unlock_irqrestore(&service.lock, flag); break; } default : { @@ -778,6 +792,7 @@ err: static int vpu_service_open(struct inode *inode, struct file *filp) { + unsigned long flag; vpu_session *session = (vpu_session *)kmalloc(sizeof(vpu_session), GFP_KERNEL); if (NULL == session) { pr_err("error: unable to allocate memory for vpu_session."); @@ -792,10 +807,10 @@ static int vpu_service_open(struct inode *inode, struct file *filp) INIT_LIST_HEAD(&session->list_session); init_waitqueue_head(&session->wait); atomic_set(&session->task_running, 0); - mutex_lock(&service.lock); + spin_lock_irqsave(&service.lock, flag); list_add_tail(&session->list_session, &service.session); filp->private_data = (void *)session; - mutex_unlock(&service.lock); + spin_unlock_irqrestore(&service.lock, flag); pr_debug("dev opened\n"); return nonseekable_open(inode, filp); @@ -804,6 +819,7 @@ static int vpu_service_open(struct inode *inode, struct file *filp) static int vpu_service_release(struct inode *inode, struct file *filp) { int task_running; + unsigned long flag; vpu_session *session = (vpu_session *)filp->private_data; if (NULL == session) return -EINVAL; @@ -815,14 +831,14 @@ static int vpu_service_release(struct inode *inode, struct file *filp) } wake_up_interruptible_sync(&session->wait); - mutex_lock(&service.lock); + spin_lock_irqsave(&service.lock, flag); /* remove this filp from the asynchronusly notified filp's */ //vpu_service_fasync(-1, filp, 0); list_del_init(&session->list_session); vpu_service_session_clear(session); kfree(session); filp->private_data = NULL; - mutex_unlock(&service.lock); + spin_unlock_irqrestore(&service.lock, flag); pr_debug("dev closed\n"); return 0; @@ -1061,39 +1077,6 @@ static void get_hw_info(void) enc->busWidth = (configReg >> 12) & 15; } -static irqreturn_t vdpu_isr_thread(int irq, void *dev_id) -{ - vpu_device *dev = (vpu_device *) dev_id; - - pr_debug("vdpu_isr_thread dec %d pp %d\n", atomic_read(&dev->isr_codec), atomic_read(&dev->isr_pp)); - - if (likely(atomic_read(&dev->isr_codec))) { - atomic_sub(1, &dev->isr_codec); - pr_debug("DEC IRQ thread proc!\n"); - mutex_lock(&service.lock); - if (NULL == service.reg_codec) { - pr_err("error: dec isr with no task waiting\n"); - } else { - reg_from_run_to_done(service.reg_codec); - } - mutex_unlock(&service.lock); - } - - if (atomic_read(&dev->isr_pp)) { - atomic_sub(1, &dev->isr_pp); - pr_debug("PP IRQ thread proc!\n"); - mutex_lock(&service.lock); - if (NULL == service.reg_pproc) { - pr_err("error: pp isr with no task waiting\n"); - } else { - reg_from_run_to_done(service.reg_pproc); - } - mutex_unlock(&service.lock); - } - try_set_reg(); - return IRQ_HANDLED; -} - static irqreturn_t vdpu_isr(int irq, void *dev_id) { vpu_device *dev = (vpu_device *) dev_id; @@ -1113,34 +1096,26 @@ static irqreturn_t vdpu_isr(int irq, void *dev_id) /* clear dec IRQ */ writel(irq_status_dec & (~DEC_INTERRUPT_BIT), dev->hwregs + DEC_INTERRUPT_REGISTER); pr_debug("DEC IRQ received!\n"); - atomic_add(1, &dev->isr_codec); + spin_lock(&service.lock); + if (NULL == service.reg_codec) { + pr_err("error: dec isr with no task waiting\n"); + } else { + reg_from_run_to_done(service.reg_codec); + } + spin_unlock(&service.lock); } if (irq_status_pp & PP_INTERRUPT_BIT) { /* clear pp IRQ */ writel(irq_status_pp & (~DEC_INTERRUPT_BIT), dev->hwregs + PP_INTERRUPT_REGISTER); pr_debug("PP IRQ received!\n"); - atomic_add(1, &dev->isr_pp); - } - return IRQ_WAKE_THREAD; -} - -static irqreturn_t vepu_isr_thread(int irq, void *dev_id) -{ - struct vpu_device *dev = (struct vpu_device *) dev_id; - - pr_debug("enc_isr_thread\n"); - - if (likely(atomic_read(&dev->isr_codec))) { - atomic_sub(1, &dev->isr_codec); - pr_debug("ENC IRQ thread proc!\n"); - mutex_lock(&service.lock); - if (NULL == service.reg_codec) { - pr_err("error: enc isr with no task waiting\n"); + spin_lock(&service.lock); + if (NULL == service.reg_pproc) { + pr_err("error: pp isr with no task waiting\n"); } else { - reg_from_run_to_done(service.reg_codec); + reg_from_run_to_done(service.reg_pproc); } - mutex_unlock(&service.lock); + spin_unlock(&service.lock); } try_set_reg(); return IRQ_HANDLED; @@ -1157,9 +1132,16 @@ static irqreturn_t vepu_isr(int irq, void *dev_id) /* clear enc IRQ */ writel(irq_status & (~ENC_INTERRUPT_BIT), dev->hwregs + ENC_INTERRUPT_REGISTER); pr_debug("ENC IRQ received!\n"); - atomic_add(1, &dev->isr_codec); + spin_lock(&service.lock); + if (NULL == service.reg_codec) { + pr_err("error: enc isr with no task waiting\n"); + } else { + reg_from_run_to_done(service.reg_codec); + } + spin_unlock(&service.lock); } - return IRQ_WAKE_THREAD; + try_set_reg(); + return IRQ_HANDLED; } static int __init vpu_service_proc_init(void); @@ -1171,18 +1153,15 @@ static int __init vpu_service_init(void) dec_dev.iobaseaddr = RK29_VCODEC_PHYS + DEC_PHY_OFFSET; dec_dev.iosize = DEC_IO_SIZE; - atomic_set(&dec_dev.isr_codec, 0); - atomic_set(&dec_dev.isr_pp, 0); enc_dev.iobaseaddr = RK29_VCODEC_PHYS; enc_dev.iosize = ENC_IO_SIZE; - atomic_set(&enc_dev.isr_codec, 0); - atomic_set(&enc_dev.isr_pp, 0); INIT_LIST_HEAD(&service.waiting); INIT_LIST_HEAD(&service.running); INIT_LIST_HEAD(&service.done); INIT_LIST_HEAD(&service.session); - mutex_init(&service.lock); + spin_lock_init(&service.lock); + spin_lock_init(&service.lock_power); service.reg_codec = NULL; service.reg_pproc = NULL; atomic_set(&service.total_running, 0); @@ -1201,13 +1180,13 @@ static int __init vpu_service_init(void) } /* get the IRQ line */ - ret = request_threaded_irq(IRQ_VDPU, vdpu_isr, vdpu_isr_thread, IRQF_SHARED, "vdpu", (void *)&dec_dev); + ret = request_irq(IRQ_VDPU, vdpu_isr, IRQF_SHARED, "vdpu", (void *)&dec_dev); if (ret) { pr_err("error: can't request vdpu irq %d\n", IRQ_VDPU); goto err_req_vdpu_irq; } - ret = request_threaded_irq(IRQ_VEPU, vepu_isr, vepu_isr_thread, IRQF_SHARED, "vepu", (void *)&enc_dev); + ret = request_irq(IRQ_VEPU, vepu_isr, IRQF_SHARED, "vepu", (void *)&enc_dev); if (ret) { pr_err("error: can't request vepu irq %d\n", IRQ_VEPU); goto err_req_vepu_irq; @@ -1222,7 +1201,6 @@ static int __init vpu_service_init(void) platform_device_register(&vpu_service_device); platform_driver_probe(&vpu_service_driver, NULL); get_hw_info(); - del_timer(&service.timer); vpu_service_power_off(); pr_info("init success\n"); @@ -1236,7 +1214,6 @@ err_req_vepu_irq: err_req_vdpu_irq: pr_info("init failed\n"); err_reserve_io: - del_timer(&service.timer); vpu_service_power_off(); vpu_service_release_io(); vpu_put_clk(); @@ -1266,6 +1243,7 @@ module_exit(vpu_service_exit); static int proc_vpu_service_show(struct seq_file *s, void *v) { unsigned int i, n; + unsigned long flag; vpu_reg *reg, *reg_tmp; vpu_session *session, *session_tmp; @@ -1273,16 +1251,16 @@ static int proc_vpu_service_show(struct seq_file *s, void *v) seq_printf(s, "\nENC Registers:\n"); n = enc_dev.iosize >> 2; for (i = 0; i < n; i++) { - seq_printf(s, "\tswreg%.3d = %08X\n", i, readl(enc_dev.hwregs + i)); + seq_printf(s, "\tswreg%d = %08X\n", i, readl(enc_dev.hwregs + i)); } seq_printf(s, "\nDEC Registers:\n"); n = dec_dev.iosize >> 2; for (i = 0; i < n; i++) { - seq_printf(s, "\tswreg%.3d = %08X\n", i, readl(dec_dev.hwregs + i)); + seq_printf(s, "\tswreg%d = %08X\n", i, readl(dec_dev.hwregs + i)); } seq_printf(s, "\nvpu service status:\n"); - mutex_lock(&service.lock); + spin_lock_irqsave(&service.lock, flag); list_for_each_entry_safe(session, session_tmp, &service.session, list_session) { seq_printf(s, "session pid %d type %d:\n", session->pid, session->type); //seq_printf(s, "waiting reg set %d\n"); @@ -1296,7 +1274,7 @@ static int proc_vpu_service_show(struct seq_file *s, void *v) seq_printf(s, "done register set\n"); } } - mutex_unlock(&service.lock); + spin_unlock_irqrestore(&service.lock, flag); return 0; } -- 2.34.1