2 * Copyright 2007 Ben Skeggs
3 * Copyright 2007 Stephane Marchesin
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 #include "nv_include.h"
28 static void NVDumpLockupInfo(NVPtr pNv)
30 struct nouveau_channel_priv *chan = nouveau_channel(pNv->chan);
33 start = ((*chan->get - chan->dma.base) >> 2) - 20;
37 xf86DrvMsg(0, X_INFO, "Fifo dump (lockup 0x%04x,0x%04x):\n",
38 (*chan->get - chan->dma.base) >> 2, chan->dma.put);
39 for(i = start; i < chan->dma.put + 10; i++)
40 xf86DrvMsg(0, X_INFO, "[0x%04x] 0x%08x\n", i, chan->pushbuf[i]);
41 xf86DrvMsg(0, X_INFO, "End of fifo dump\n");
45 NVLockedUp(ScrnInfoPtr pScrn)
47 NVPtr pNv = NVPTR(pScrn);
48 struct nouveau_channel_priv *chan = nouveau_channel(pNv->chan);
50 /* avoid re-entering FatalError on shutdown */
55 NVDumpLockupInfo(pNv);
57 FatalError("DMA queue hang: dmaPut=%x, current=%x, status=%x\n",
58 chan->dma.put, (*chan->get - chan->dma.base) >> 2,
59 pNv->PGRAPH[NV_PGRAPH_STATUS/4]);
63 NVChannelHangNotify(struct nouveau_channel *chan)
65 ScrnInfoPtr pScrn = chan->user_private;
69 void NVSync(ScrnInfoPtr pScrn)
71 NVPtr pNv = NVPTR(pScrn);
72 struct nouveau_channel *chan = pNv->chan;
73 struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
74 struct nouveau_grobj *gr = pNv->Nv2D ? pNv->Nv2D : pNv->NvImageBlit;
75 int t_start, timeout = 2000;
80 /* Wait for entire FIFO to be processed */
81 t_start = GetTimeInMillis();
82 while((GetTimeInMillis() - t_start) < timeout &&
83 (((*nvchan->get - nvchan->dma.base) >> 2)!= nvchan->dma.put));
84 if ((GetTimeInMillis() - t_start) >= timeout) {
89 /* Wait for nvchannel to go completely idle */
90 nouveau_notifier_reset(pNv->notify0, 0);
91 BEGIN_RING(chan, gr, 0x104, 1);
93 BEGIN_RING(chan, gr, 0x100, 1);
96 if (nouveau_notifier_wait_status(pNv->notify0, 0,
97 NV_NOTIFY_STATE_STATUS_COMPLETED,
102 static void NVInitDmaCB(ScrnInfoPtr pScrn)
104 NVPtr pNv = NVPTR(pScrn);
105 unsigned int cb_location;
109 /* I'm not bothering to check for failures here, the DRM will fall back
110 * on defaults if anything's wrong (ie. out of AGP, invalid sizes)
112 /* WARNING: on ppc at least, putting cmdbuf in MEM_FB results in DMA hangs */
114 cb_location = NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI_ACCEPTABLE;
116 cb_location = NOUVEAU_MEM_FB;
118 if((s = (char *)xf86GetOptValString(pNv->Options, OPTION_CMDBUF_LOCATION))) {
119 if(!xf86NameCmp(s, "AGP"))
120 cb_location = NOUVEAU_MEM_AGP;
121 else if (!xf86NameCmp(s, "VRAM"))
122 cb_location = NOUVEAU_MEM_FB;
123 else if (!xf86NameCmp(s, "PCI"))
124 cb_location = NOUVEAU_MEM_PCI;
126 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid value \"%s\" for CBLocation\n", s);
128 nouveau_device_set_param(pNv->dev, NOUVEAU_SETPARAM_CMDBUF_LOCATION,
131 /* CBSize == size of space reserved for *all* FIFOs in MiB */
132 if (xf86GetOptValInteger(pNv->Options, OPTION_CMDBUF_SIZE, &cb_size))
133 nouveau_device_set_param(pNv->dev, NOUVEAU_SETPARAM_CMDBUF_SIZE,
138 NVInitDma(ScrnInfoPtr pScrn)
140 NVPtr pNv = NVPTR(pScrn);
145 ret = nouveau_channel_alloc(pNv->dev, NvDmaFB, NvDmaTT, &pNv->chan);
147 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
148 "Error creating GPU channel: %d\n", ret);
151 pNv->chan->user_private = pScrn;
152 pNv->chan->hang_notify = NVChannelHangNotify;
154 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
155 "Opened GPU channel %d\n", pNv->chan->id);