}
info->cmdring.last_ptr = xgi_find_pcie_virt(info, pCmdInfo->hw_addr);
+#ifdef XGI_HAVE_FENCE
drm_fence_flush_old(info->dev, 0, info->next_sequence);
+#endif /* XGI_HAVE_FENCE */
return 0;
}
xgi_PCI_IDS
};
+#ifdef XGI_HAVE_FENCE
extern struct drm_fence_driver xgi_fence_driver;
+#endif /* XGI_HAVE_FENCE */
int xgi_bootstrap(struct drm_device *, void *, struct drm_file *);
DRM_IOCTL_DEF(DRM_XGI_FREE, xgi_free_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_XGI_SUBMIT_CMDLIST, xgi_submit_cmdlist, DRM_AUTH),
DRM_IOCTL_DEF(DRM_XGI_STATE_CHANGE, xgi_state_change_ioctl, DRM_AUTH|DRM_MASTER),
+ DRM_IOCTL_DEF(DRM_XGI_SET_FENCE, xgi_set_fence_ioctl, DRM_AUTH),
+ DRM_IOCTL_DEF(DRM_XGI_WAIT_FENCE, xgi_wait_fence_ioctl, DRM_AUTH),
};
static const int xgi_max_ioctl = DRM_ARRAY_SIZE(xgi_ioctls);
static void xgi_reclaim_buffers_locked(struct drm_device * dev,
struct drm_file * filp);
static irqreturn_t xgi_kern_isr(DRM_IRQ_ARGS);
+static int xgi_kern_isr_postinstall(struct drm_device * dev);
static struct drm_driver driver = {
.lastclose = xgi_driver_lastclose,
.dma_quiescent = NULL,
.irq_preinstall = NULL,
- .irq_postinstall = NULL,
+ .irq_postinstall = xgi_kern_isr_postinstall,
.irq_uninstall = NULL,
.irq_handler = xgi_kern_isr,
.reclaim_buffers = drm_core_reclaim_buffers,
.remove = __devexit_p(drm_cleanup_pci),
},
+#ifdef XGI_HAVE_FENCE
.fence_driver = &xgi_fence_driver,
+#endif /* XGI_HAVE_FENCE */
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
DRM_WRITE32(info->mmio_map,
0x2800 + M2REG_AUTO_LINK_SETTING_ADDRESS,
cpu_to_le32(M2REG_AUTO_LINK_SETTING_COMMAND | irq_bits));
+#ifdef XGI_HAVE_FENCE
xgi_fence_handler(dev);
+#endif /* XGI_HAVE_FENCE */
+ DRM_WAKEUP(&info->fence_queue);
return IRQ_HANDLED;
} else {
return IRQ_NONE;
}
+int xgi_kern_isr_postinstall(struct drm_device * dev)
+{
+ struct xgi_info *info = dev->dev_private;
+
+ DRM_INIT_WAITQUEUE(&info->fence_queue);
+ return 0;
+}
+
+
int xgi_driver_load(struct drm_device *dev, unsigned long flags)
{
struct xgi_info *info = drm_alloc(sizeof(*info), DRM_MEM_DRIVER);
struct xgi_cmdring_info cmdring;
DRM_SPINTYPE fence_lock;
+ wait_queue_head_t fence_queue;
unsigned complete_sequence;
unsigned next_sequence;
};
extern void xgi_enable_ge(struct xgi_info * info);
extern void xgi_disable_ge(struct xgi_info * info);
+/* TTM-style fences.
+ */
+#ifdef XGI_HAVE_FENCE
extern void xgi_poke_flush(struct drm_device * dev, uint32_t class);
extern int xgi_fence_emit_sequence(struct drm_device * dev, uint32_t class,
uint32_t flags, uint32_t * sequence, uint32_t * native_type);
extern void xgi_fence_handler(struct drm_device * dev);
extern int xgi_fence_has_irq(struct drm_device *dev, uint32_t class,
uint32_t flags);
+#endif /* XGI_HAVE_FENCE */
+
+
+/* Non-TTM-style fences.
+ */
+extern int xgi_set_fence_ioctl(struct drm_device * dev, void * data,
+ struct drm_file * filp);
+extern int xgi_wait_fence_ioctl(struct drm_device * dev, void * data,
+ struct drm_file * filp);
extern int xgi_alloc_ioctl(struct drm_device * dev, void * data,
struct drm_file * filp);
#include "xgi_misc.h"
#include "xgi_cmdlist.h"
+static int xgi_low_level_fence_emit(struct drm_device *dev, u32 *sequence)
+{
+ struct xgi_info *const info = dev->dev_private;
+
+ if (info == NULL) {
+ DRM_ERROR("called with no initialization\n");
+ return -EINVAL;
+ }
+
+ DRM_SPINLOCK(&info->fence_lock);
+ info->next_sequence++;
+ if (info->next_sequence > BEGIN_BEGIN_IDENTIFICATION_MASK) {
+ info->next_sequence = 1;
+ }
+
+ *sequence = (u32) info->next_sequence;
+ DRM_SPINUNLOCK(&info->fence_lock);
+
+
+ xgi_emit_irq(info);
+ return 0;
+}
+
+#define GET_BEGIN_ID(i) (le32_to_cpu(DRM_READ32((i)->mmio_map, 0x2820)) \
+ & BEGIN_BEGIN_IDENTIFICATION_MASK)
+
+static int xgi_low_level_fence_wait(struct drm_device *dev, unsigned *sequence)
+{
+ struct xgi_info *const info = dev->dev_private;
+ unsigned int cur_fence;
+ int ret = 0;
+
+ if (info == NULL) {
+ DRM_ERROR("called with no initialization\n");
+ return -EINVAL;
+ }
+
+ /* Assume that the user has missed the current sequence number
+ * by about a day rather than she wants to wait for years
+ * using fences.
+ */
+ DRM_WAIT_ON(ret, info->fence_queue, 3 * DRM_HZ,
+ ((((cur_fence = GET_BEGIN_ID(info))
+ - *sequence) & BEGIN_BEGIN_IDENTIFICATION_MASK)
+ <= (1 << 18)));
+
+ info->complete_sequence = cur_fence;
+ *sequence = cur_fence;
+
+ return ret;
+}
+
+
+int xgi_set_fence_ioctl(struct drm_device * dev, void * data,
+ struct drm_file * filp)
+{
+ (void) filp;
+ return xgi_low_level_fence_emit(dev, (u32 *) data);
+}
+
+
+int xgi_wait_fence_ioctl(struct drm_device * dev, void * data,
+ struct drm_file * filp)
+{
+ (void) filp;
+ return xgi_low_level_fence_wait(dev, (u32 *) data);
+}
+
+
+#ifdef XGI_HAVE_FENCE
static void xgi_fence_poll(struct drm_device * dev, uint32_t class,
uint32_t waiting_types)
{
uint32_t flags, uint32_t * sequence,
uint32_t * native_type)
{
- struct xgi_info * info = dev->dev_private;
+ int err;
- if ((info == NULL) || (class != 0))
- return -EINVAL;
-
-
- DRM_SPINLOCK(&info->fence_lock);
- info->next_sequence++;
- if (info->next_sequence > BEGIN_BEGIN_IDENTIFICATION_MASK) {
- info->next_sequence = 1;
- }
- DRM_SPINUNLOCK(&info->fence_lock);
+ (void) flags;
+ if (class != 0)
+ return -EINVAL;
- xgi_emit_irq(info);
+ err = xgi_low_level_fence_emit(dev, sequence);
+ if (err)
+ return err;
- *sequence = (uint32_t) info->next_sequence;
*native_type = DRM_FENCE_TYPE_EXE;
-
return 0;
}
.wait = NULL
};
+#endif /* XGI_HAVE_FENCE */
#define DRM_XGI_FREE 2
#define DRM_XGI_SUBMIT_CMDLIST 3
#define DRM_XGI_STATE_CHANGE 4
+#define DRM_XGI_SET_FENCE 5
+#define DRM_XGI_WAIT_FENCE 6
#define XGI_IOCTL_BOOTSTRAP DRM_IOWR(DRM_COMMAND_BASE + DRM_XGI_BOOTSTRAP, struct xgi_bootstrap)
#define XGI_IOCTL_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_XGI_ALLOC, struct xgi_mem_alloc)
#define XGI_IOCTL_FREE DRM_IOW(DRM_COMMAND_BASE + DRM_XGI_FREE, __u32)
#define XGI_IOCTL_SUBMIT_CMDLIST DRM_IOW(DRM_COMMAND_BASE + DRM_XGI_SUBMIT_CMDLIST, struct xgi_cmd_info)
#define XGI_IOCTL_STATE_CHANGE DRM_IOW(DRM_COMMAND_BASE + DRM_XGI_STATE_CHANGE, struct xgi_state_info)
+#define XGI_IOCTL_SET_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_XGI_SET_FENCE, u32)
+#define XGI_IOCTL_WAIT_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_XGI_WAIT_FENCE, u32)
#endif /* _XGI_DRM_H_ */