0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include <linux/pci.h>
0027
0028 #include <drm/drm_drv.h>
0029
0030 #include "qxl_drv.h"
0031
0032 static irqreturn_t qxl_irq_handler(int irq, void *arg)
0033 {
0034 struct drm_device *dev = (struct drm_device *) arg;
0035 struct qxl_device *qdev = to_qxl(dev);
0036 uint32_t pending;
0037
0038 pending = xchg(&qdev->ram_header->int_pending, 0);
0039
0040 if (!pending)
0041 return IRQ_NONE;
0042
0043 atomic_inc(&qdev->irq_received);
0044
0045 if (pending & QXL_INTERRUPT_DISPLAY) {
0046 atomic_inc(&qdev->irq_received_display);
0047 wake_up_all(&qdev->display_event);
0048 qxl_queue_garbage_collect(qdev, false);
0049 }
0050 if (pending & QXL_INTERRUPT_CURSOR) {
0051 atomic_inc(&qdev->irq_received_cursor);
0052 wake_up_all(&qdev->cursor_event);
0053 }
0054 if (pending & QXL_INTERRUPT_IO_CMD) {
0055 atomic_inc(&qdev->irq_received_io_cmd);
0056 wake_up_all(&qdev->io_cmd_event);
0057 }
0058 if (pending & QXL_INTERRUPT_ERROR) {
0059
0060
0061
0062
0063 qdev->irq_received_error++;
0064 DRM_WARN("driver is in bug mode\n");
0065 }
0066 if (pending & QXL_INTERRUPT_CLIENT_MONITORS_CONFIG) {
0067 schedule_work(&qdev->client_monitors_config_work);
0068 }
0069 qdev->ram_header->int_mask = QXL_INTERRUPT_MASK;
0070 outb(0, qdev->io_base + QXL_IO_UPDATE_IRQ);
0071 return IRQ_HANDLED;
0072 }
0073
0074 static void qxl_client_monitors_config_work_func(struct work_struct *work)
0075 {
0076 struct qxl_device *qdev = container_of(work, struct qxl_device,
0077 client_monitors_config_work);
0078
0079 qxl_display_read_client_monitors_config(qdev);
0080 }
0081
0082 int qxl_irq_init(struct qxl_device *qdev)
0083 {
0084 struct drm_device *ddev = &qdev->ddev;
0085 struct pci_dev *pdev = to_pci_dev(ddev->dev);
0086 int ret;
0087
0088 init_waitqueue_head(&qdev->display_event);
0089 init_waitqueue_head(&qdev->cursor_event);
0090 init_waitqueue_head(&qdev->io_cmd_event);
0091 init_waitqueue_head(&qdev->release_event);
0092 INIT_WORK(&qdev->client_monitors_config_work,
0093 qxl_client_monitors_config_work_func);
0094 atomic_set(&qdev->irq_received, 0);
0095 atomic_set(&qdev->irq_received_display, 0);
0096 atomic_set(&qdev->irq_received_cursor, 0);
0097 atomic_set(&qdev->irq_received_io_cmd, 0);
0098 qdev->irq_received_error = 0;
0099 ret = request_irq(pdev->irq, qxl_irq_handler, IRQF_SHARED, ddev->driver->name, ddev);
0100 qdev->ram_header->int_mask = QXL_INTERRUPT_MASK;
0101 if (unlikely(ret != 0)) {
0102 DRM_ERROR("Failed installing irq: %d\n", ret);
0103 return 1;
0104 }
0105 return 0;
0106 }