summaryrefslogtreecommitdiff
path: root/wiki/Chat_log/20181018-mm-chatlog
blob: 894fc25ff4950b4bbfbd10c7e4a6028a56171096 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
Multimedia-chat-meeting-2018-10-18

11:02 < pinchartl> welcome to the multimedia meeting
11:02 < pinchartl> Topic 1. Status Check for the Multimedia Tasks
11:02 < pinchartl> * Jacopo
11:02 < pinchartl> Since last meeting:
11:02 < pinchartl> - Mostly review (v4l2-mux, gmsl v3, some other media related patches)
11:02 < pinchartl> - Slides and talk preparation for ELC-E
11:02 < pinchartl> - Some patches to periupport
11:02 < pinchartl> Until next meeting:
11:02 < pinchartl> - ELC-E
11:02 < pinchartl> - Get an E3 from Laurent and start looking into the CSI-2 issue
11:02 < pinchartl> - Resume adv748x work (dynamic channel configuration)
11:02 < pinchartl> Issues and Blockers: None
11:02 < pinchartl> jmondi: any comment ?
11:03 < jmondi> not really
11:03 < pinchartl> thanks
11:03 < pinchartl> * Kieran
11:03 < pinchartl> Since last meeting:
11:03 < pinchartl> - GMSL rebase for renesas-drivers (conflicts with async/fwnode/csi2 changes)
11:03 < pinchartl> - VIN circular locking dependency report
11:03 < pinchartl> - Working on partition algorithm phases and overlaps
11:03 < pinchartl> Until next meeting:
11:03 < pinchartl> - ELCE
11:03 < pinchartl> - Aim to get pa-phase work out
11:03 < pinchartl> - Look at KUnit for testing! Looks interesting (to me?)
11:03 < pinchartl> Issues and blockers: None
11:03 < pinchartl> kbingham: any comment ?
11:03 < kbingham> Nope :)
11:03 < pinchartl> thanks
11:03 < pinchartl> * Laurent
11:03 < pinchartl> Since last meeting:
11:03 < pinchartl> - More patch review
11:03 < pinchartl> - Submitted multimedia additional tasks for Q4
11:03 < pinchartl> - Miscellaneous DU fixes
11:03 < pinchartl> - BSP upport (periupport updates)
11:03 < pinchartl> - FCNL reserved memory areas discussions (see Marek's ATF work)
11:03 < pinchartl> Until next meeting:
11:03 < pinchartl> - More patch review
11:03 < pinchartl> - Finalize multimedia additional tasks for Q4
11:03 < pinchartl> - Attend ELC-E, Linux media summit and peripericon
11:03 < pinchartl> - Get GMSL patches merged
11:03 < pinchartl> Issues and blockers: None
11:03 < pinchartl> any question ?
11:04 < pinchartl> ah, and I forgot to mention that I've reviewed the DS90x9xx patches (FPD-Link III serializers and deserializers)
11:05 < kbingham> Well yes, I could have put some FPD-Link III in my "since last meeting" section too :)
11:05 < pinchartl> I'll add that
11:05 < pinchartl> * Morimoto-san
11:05 < pinchartl> Since last meeting:
11:05 < pinchartl> - Continued work on TDM sound on StarterKit + KingFisher
11:05 < pinchartl>   - Solved codec driver issue on cold-boot, it needed clock switching.
11:05 < pinchartl>   - Solved codec kctrl settings issue, few register needed clocks.
11:05 < pinchartl>   - Solved clock switching, used gpio-mux-clock.
11:05 < pinchartl>   - Solved TDM issues, SSI driver needed few bugfix patches.
11:05 < pinchartl> All patches have been posted to the ALSA mailing list.
11:05 < pinchartl> Until next meeting:
11:05 < pinchartl> - Continue work on TDM sound on StarterKit + KingFisher
11:05 < pinchartl> Expanded sound card and BUSIF detail control are needed, will work on them 
11:05 < pinchartl> next.
11:05 < pinchartl> morimoto: any comment ?
11:05 < morimoto> No comment, but I would say I'm looking forward to see you in ELCE :)
11:06 < pinchartl> :-)
11:06 < pinchartl> I think we all are
11:06 < pinchartl> * Niklas
11:06 < pinchartl> Since last meeting:
11:06 < pinchartl> - [PATCH v2 0/3] rcar-vin: add support for UDS (Up Down Scaler)
11:06 < pinchartl> - [PATCH v2 0/5] i2c: adv748x: add support for CSI-2 TXA to work in 1-, 2- and 
11:06 < pinchartl> 4-lane mode
11:06 < pinchartl> - [PATCH] v4l2-ioctl: fix CROPCAP type handling
11:06 < pinchartl> - Tested CEC patches for Koelsch and it now works
11:06 < pinchartl> Until next meeting:
11:06 < pinchartl> - Post v3 of adv748x 1-, 2- and 4-lane mode
11:06 < pinchartl> - Attend multimedia summit during ELCE
11:06 < pinchartl> Issues and blockers: None
11:06 < pinchartl> neg isn't here
11:06 < pinchartl> * Simon
11:06 < pinchartl> Since last meeting:
11:06 < pinchartl> - E3 Audio now working, patches posted
11:06 < pinchartl> Until next meeting:
11:06 < pinchartl> - Follow up on above as necessary
11:06 < pinchartl> Issues and blockers: None
11:06 < pinchartl> horms: any comment ?
11:06 < neg> I'm back just in time it seems :-) No comment
11:07 < pinchartl> neg: welcome back !
11:07 < neg> thanks, sorry for the conflict
11:08 < horms> pinchartl: none, I had issues with E3 Audio. Morimoto's guidance helped me fix them. No problems at this time
11:08 < horms> Let me know if you want any upporting done :)
11:08 < morimoto> horms: good to know :)
11:08 < pinchartl> sure :-)
11:09 < pinchartl> I'm marking patches as 'MM upstreaming candidates' in periupport, feel free to pick them if you want
11:09 < pinchartl> there's nothing particularly urgent so far
11:09 < pinchartl> the pinctrl and DT integration commits are good candidates for non-urgent upporting
11:11 < pinchartl> Ulrich isn't here, did he say he would miss this meeting ? the last I heard was "prepare for stay in the Philippines until Dec 10" two weeks ago, but I don't know if that means holidays or working under the sun
11:11 < wsa> pinchartl: same question here
11:11 < pinchartl> wsa: I thus assume you don't know the answer :-)
11:11 < pinchartl> geertu: damm: any info ?
11:12 < geertu> pinchartl: I don't know.
11:12 < pinchartl> ok
11:13 < geertu> His "tips-and-tricks to use free Wifi effectively" may not be applicable to the Philippines ;-)
11:13 < pinchartl> :-D
11:13 < pinchartl> on the topic of periupport
11:14 < pinchartl> morimoto: in the bsp370 ticket file, you have marked lots of commits with a reference to previous BSP releases
11:14 < pinchartl> if I update a commit in the v4.14 file, should I update the corresponding commit in bsp370, or leave the reference ?
11:15 < morimoto> uhm
11:15 < morimoto> Basically there are no conflict commits between v4.14 vs bsp370
11:15 < morimoto> But, you had it ?
11:16 < pinchartl> it's not a matter of conflicts
11:16 < pinchartl> for instance
11:16 < morimoto> sorry, not conflicts, duplicate
11:16 < pinchartl> commit 543637cb084774608dc67144be0ac0ae9e534350
11:16 < pinchartl> is
11:16 < pinchartl> in bsp370
11:16 < pinchartl> N,543637cb084774608dc67144be0ac0ae9e534350|requested upport with f7cac36f6d7862f93a12cfb8d4d0d9b47f132179 of BSPv3.6.0
11:17 < pinchartl> what should I do with that ?
11:17 < pinchartl> not touch it because it's marked N ?
11:17 < morimoto> Ahh, please ignore "N" commit.
11:17 < morimoto> Mainly, we need latest ticket only. so, bsp370
11:18 < morimoto> is important to Renesas
11:19 < pinchartl> hmmmm...
11:19 < wsa> Yet, 'N' is all the Ebisu upporting for example (enablement of SCIF, I2C, for example)
11:19 < wsa> we surely want that, or?
11:19 < morimoto> on bsp370 ?
11:20 < morimoto> pinchartl: sorry, what is wrong ?
11:20 < pinchartl> another example
11:20 < pinchartl> in bsp370
11:20 < pinchartl> N,068d08088b263a2c037656ea9668f8bb2be3d046|requested upport with 6ea68fc0ce880bdfa511b45b8e7ace42303c71e5 of BSPv3.6.0
11:21 < pinchartl> and in v4.14
11:21 < pinchartl> M,6ea68fc0ce880bdfa511b45b8e7ace42303c71e5
11:21 < pinchartl> have you marked it as N in bsp370 because you expect it to be upported from v4.14 ?
11:22 < morimoto> Oops, I misunderstood...
11:23 < morimoto> BSP team is thinking that they avoid duplicate request
11:23 < morimoto> It seems
11:24 < morimoto> We need to avoid N, and care about M/H on both v4.14 and bsp370
11:24 < morimoto> Renesas inside doesn't matter about "N", but counting how many patch are upported
11:24 < morimoto> (= for L/M/H)
11:25 < pinchartl> ok
11:25 < horms> Ok, so for KPI N is irrelevant
11:25 < horms> I asked this a bit earlier, but is there a plan to produce bsp380 ?
11:25 < pinchartl> wouldn't it have been better to mark the commit as N in v4.14 and as M bsp370 ?
11:25 < pinchartl> that way the latest BSP ticket file would contain most of the work to be done
11:26 < morimoto> pinchartl: it is good idea. thanks
11:26 < pinchartl> similarly to when you post a v2 of a patch, v1 is marked as superseded and everybody forgets about it
11:27 < pinchartl> so how should we handle this ? does anyone have a magic script to reconcile everything ? :-)
11:28 < morimoto> I can't use magic :(
11:28 < horms> is it against company policy?
11:29 < morimoto> horms: is it question to me ?
11:29 < horms> morimoto: sorry, it was a joke about magic.
11:29 < pinchartl> I'll try to write a script to handle this
11:30 < pinchartl> morimoto: thanks for the feedback
11:30 < morimoto> horms: yeah, it is joke my side too :)
11:30 < pinchartl> Topic 2. Discussions
11:30 < horms> morimoto:)
11:30 < pinchartl> Marex: you've requested a discussion about FCNL
11:30 < pinchartl> we've already discussed the topic, is there something you would like to add ?
11:32 < morimoto> pinchartl: Marex: I think you had question about it to BSP team, but 1) they don't know detail, because it is used by 3rd party 2) related guy already go back to home today. So please send me question mail, I can forward it to BSP/3rd party, and feedback to you.
11:34 < wsa> horms: what is KPI?
11:34 < pinchartl> while waiting for Marex, does anyone have any other topic they would like to discuss ?
11:34 < pinchartl> wsa: Key Performance Indicator
11:34 < Marex> pinchartl: let
11:34 < wsa> thanks
11:35 < morimoto> wsa: KPI = key performance indicator
11:35 < Marex> pinchartl: let's postpone FCNL until we have DT support in ATF ? :)
11:35 < Marex> pinchartl: and until the FCNL is sorted out in Linux too ?
11:35 < neg> I would only like to ask if anyone wish me to prepare or bring something specail to facilitate MM work during ELCE. As we talked about E3 testing maybe there is something else?
11:35 < Marex> morimoto: would Takuya Sakata-san be willing to discuss ATF with me ? :)
11:36 < morimoto> hmm.. I don't know him...
11:36 < morimoto> discuss by what ? mail ?
11:36 < Marex> morimoto: jupp, email
11:36 < Marex> morimoto: I'd like to send him some ATF patches
11:36 < Marex> morimoto: OK, I'll just send him the patches :)
11:37 < wsa> pinchartl: I think I can brush up my 'transfer upporting info from ticket x to ticket y' script to transfer the old prio if the new one is 'N'
11:37 < morimoto> Marex: OK, please do
11:37 < pinchartl> Marex: but please keep FCNL support in your ATF patch series
11:38 < Marex> pinchartl: but the bindings are not fleshed out yet and I don't want them to become ABI
11:39 < pinchartl> wsa: that would be nice, as I was thinking about writing such a script :-) my idea is roughly if (new prio == N and comment == reference to old commit) { copy old commit prio and comment to new commit; set old prio to N and comment to reference new commit }
11:39 < pinchartl> wsa: do you think you could do that ?
11:39 < pinchartl> it would be useful to commit the script to the repo too
11:40 < pinchartl> Marex: you don't have to upstream it yet, but I'd like the patches to be included in the series, in order to make sure that the proposal will work
11:40 < pinchartl> would that be OK with you ?
11:40 < Marex> I do keep the patch, it's not like I threw it away
11:40 < wsa> pinchartl: I'll try
11:41 < wsa> and let you all know :)
11:41 < pinchartl> Marex: thanks :-)
11:41 < pinchartl> wsa: thanks
11:41  * Marex wonders if we can generate FDT at compile time ... :-)
11:41 < Marex> I guess we can
11:41 < pinchartl> Marex: interesting idea
11:41 < Marex> pinchartl: we can ...
11:42 < pinchartl> so if there's no more discussion topic,
11:42 < pinchartl> Topic 3. Additional Tasks for Q4
11:42 < pinchartl> The following additional tasks have been submitted and approved, they are now going through the usual process. SoWs should be sent in the near future, with a 12/M due date.
11:42 < pinchartl> * ADV748x Dynamic Routing (Jacopo)
11:42 < pinchartl> * M3-N rotation bug fix (Kieran)
11:42 < pinchartl> * Fix RGB output routing on D3 and E3 (Laurent)
11:42 < pinchartl> * Upporting and addition of pixel format (Niklas)
11:42 < geertu> Marex: if we know the parameters at compile-time, we can
11:42 < pinchartl> any question/comment ?
11:43 < neg> Looks good to me
11:43 < Marex> geertu: but then why should it be part of ATF ? We can have the bootrom load the DT
11:43 < jmondi> fine with me, thanks
11:44 < kbingham> Sounds OK to me.
11:44 < geertu> Marex: ATF programs the DRAMC
11:44 < Marex> geertu: but the programming of that is given to ATF by the integrator
11:44 < pinchartl> next, Topic 4. Face to Face Meeting in Edinburgh
11:44 < Marex> geertu: it's literally a few C macros
11:45 < pinchartl> I don't think we should spend time discussing status updates there, as there will not be much
11:45 < pinchartl> are there any particular topic that team members would like to discuss face to face ?
11:45 < kbingham> There's going to be a v4l2 codec meeting at ELCE
11:45 < pinchartl> correct
11:46 < kbingham> But from previous attempts at suggesting codec work - I assume renesas has little interest?
11:46 < neg> Potential plan and for unified DU and VIN test suite :-)
11:46 < kbingham> ^ Plus automated testing, + unit testing :)
11:47 < morimoto> interesting topic for test team
11:47 < pinchartl> kbingham: I wouldn't expect Renesas to have any new interest all of a sudden, but if you can think about a strategy to make them change their mind, I'd love to discuss that
11:50 < kbingham> pinchartl, well that depends on what their concerns are regarding the codecs. Whether it's keeping firmware out - or just completley hiding the implementation altogether. But once there is a standard API for codecs - It would be silly not to use it - and it seems unfortunate not to be part of those early designs
11:50 < pinchartl> I would like to also briefly discuss the GMSL and FPD-Link plans
11:50 < kbingham> Yes :)
11:51 < pinchartl> kbingham: I'll add codecs to the agenda, we can then spend some time discussing how to report the ongoing V4L2 codecs API developments to Renesas
11:51 < pinchartl> any other topic ?
11:52 < jmondi> not from here, thanks
11:52 < kbingham> Dont think so ...
11:53 < neg> not from me
11:53 < morimoto> not from me too
11:53 < morimoto> s/too/either/
11:55 < pinchartl> ok, thanks
11:55 < pinchartl> in that case
11:55 < pinchartl> Topic 5. Next Meeting
11:55 < pinchartl> two weeks from now ?
11:56 < pinchartl> three weeks from now ?
11:56 < pinchartl> four weeks from now ? :-)
11:56 < pinchartl> geertu: wsa: ^^
11:56 < morimoto> * PeriPeri: chat: Chat meeting 18Q4-B
11:56 < morimoto>  
11:56 < morimoto> 	date: 2018-11-08
11:56 < morimoto>  
11:56 < morimoto> 	I/O:    08:00 BST / 09:00 CEST / 10:00 EEST / 16:00 JST
11:56 < morimoto> 	Core:   08:30 BST / 09:30 CEST / 10:30 EEST / 16:30 JST
11:56 < morimoto> 	MM:     09:00 BST / 10:00 CEST / 11:00 EEST / 17:00 JST
11:56 < wsa> geertu already wrote 8.11. and I think this is good
11:56 < morimoto>  
11:56 < wsa> let's check what we agreed with dammsan
11:57 < geertu> pinchartl: That's the date from Morimoto-san's calendar
11:57 < wsa> we agreed that with dammsan
11:57 < pinchartl> ok, 3 weeks from now
11:57 < pinchartl> wsa: indeed
11:58 < pinchartl> that's all for today
11:58 < pinchartl> I propose adjourning the meeting
11:58 < pinchartl> does anyone second ?
11:58 < wsa> ack
11:59 < morimoto> 2nd
11:59 < pinchartl> meeting adjourned, thank you all for attending !
0 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148
/*
 * Copyright (C) 2006 Ben Skeggs.
 *
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial
 * portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

/*
 * Authors:
 *   Ben Skeggs <darktama@iinet.net.au>
 */

#include "drmP.h"
#include "drm.h"
#include "nouveau_drv.h"
#include "nouveau_drm.h"

/* NVidia uses context objects to drive drawing operations.

   Context objects can be selected into 8 subchannels in the FIFO,
   and then used via DMA command buffers.

   A context object is referenced by a user defined handle (CARD32). The HW
   looks up graphics objects in a hash table in the instance RAM.

   An entry in the hash table consists of 2 CARD32. The first CARD32 contains
   the handle, the second one a bitfield, that contains the address of the
   object in instance RAM.

   The format of the second CARD32 seems to be:

   NV4 to NV30:

   15: 0  instance_addr >> 4
   17:16  engine (here uses 1 = graphics)
   28:24  channel id (here uses 0)
   31	  valid (use 1)

   NV40:

   15: 0  instance_addr >> 4   (maybe 19-0)
   21:20  engine (here uses 1 = graphics)
   I'm unsure about the other bits, but using 0 seems to work.

   The key into the hash table depends on the object handle and channel id and
   is given as:
*/
static uint32_t
nouveau_ramht_hash_handle(struct drm_device *dev, int channel, uint32_t handle)
{
	struct drm_nouveau_private *dev_priv=dev->dev_private;
	uint32_t hash = 0;
	int i;

	DRM_DEBUG("ch%d handle=0x%08x\n", channel, handle);

	for (i=32;i>0;i-=dev_priv->ramht_bits) {
		hash ^= (handle & ((1 << dev_priv->ramht_bits) - 1));
		handle >>= dev_priv->ramht_bits;
	}
	if (dev_priv->card_type < NV_50)
		hash ^= channel << (dev_priv->ramht_bits - 4);
	hash <<= 3;

	DRM_DEBUG("hash=0x%08x\n", hash);
	return hash;
}

static int
nouveau_ramht_entry_valid(struct drm_device *dev, struct nouveau_gpuobj *ramht,
			  uint32_t offset)
{
	struct drm_nouveau_private *dev_priv=dev->dev_private;
	uint32_t ctx = INSTANCE_RD(ramht, (offset + 4)/4);

	if (dev_priv->card_type < NV_40)
		return ((ctx & NV_RAMHT_CONTEXT_VALID) != 0);
	return (ctx != 0);
}

static int
nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
{
	struct drm_nouveau_private *dev_priv=dev->dev_private;
	struct nouveau_channel *chan = dev_priv->fifos[ref->channel];
	struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL;
	struct nouveau_gpuobj *gpuobj = ref->gpuobj;
	uint32_t ctx, co, ho;

	if (!ramht) {
		DRM_ERROR("No hash table!\n");
		return -EINVAL;
	}

	if (dev_priv->card_type < NV_40) {
		ctx = NV_RAMHT_CONTEXT_VALID | (ref->instance >> 4) |
		      (ref->channel   << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) |
		      (gpuobj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT);
	} else
	if (dev_priv->card_type < NV_50) {
		ctx = (ref->instance >> 4) |
		      (ref->channel   << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) |
		      (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT);
	} else {
		ctx = (ref->instance  >> 4) |
		      (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT);
	}

	co = ho = nouveau_ramht_hash_handle(dev, ref->channel, ref->handle);
	do {
		if (!nouveau_ramht_entry_valid(dev, ramht, co)) {
			DRM_DEBUG("insert ch%d 0x%08x: h=0x%08x, c=0x%08x\n",
				  ref->channel, co, ref->handle, ctx);
			INSTANCE_WR(ramht, (co + 0)/4, ref->handle);
			INSTANCE_WR(ramht, (co + 4)/4, ctx);

			list_add_tail(&ref->list, &chan->ramht_refs);
			return 0;
		}
		DRM_DEBUG("collision ch%d 0x%08x: h=0x%08x\n",
			  ref->channel, co, INSTANCE_RD(ramht, co/4));

		co += 8;
		if (co >= dev_priv->ramht_size) {
			DRM_INFO("no space left after collision\n");
			co = 0;
			/* exit as it seems to cause crash with nouveau_demo and
			 * 0xdead0001 object */
			break;
		}
	} while (co != ho);

	DRM_ERROR("RAMHT space exhausted. ch=%d\n", ref->channel);
	return -ENOMEM;
}

static void
nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_channel *chan = dev_priv->fifos[ref->channel];
	struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL;
	uint32_t co, ho;

	if (!ramht) {
		DRM_ERROR("No hash table!\n");
		return;
	}

	co = ho = nouveau_ramht_hash_handle(dev, ref->channel, ref->handle);
	do {
		if (nouveau_ramht_entry_valid(dev, ramht, co) &&
		    (ref->handle == INSTANCE_RD(ramht, (co/4)))) {
			DRM_DEBUG("remove ch%d 0x%08x: h=0x%08x, c=0x%08x\n",
				  ref->channel, co, ref->handle,
				  INSTANCE_RD(ramht, (co + 4)));
			INSTANCE_WR(ramht, (co + 0)/4, 0x00000000);
			INSTANCE_WR(ramht, (co + 4)/4, 0x00000000);

			list_del(&ref->list);
			return;
		}

		co += 8;
		if (co >= dev_priv->ramht_size)
			co = 0;
	} while (co != ho);

	DRM_ERROR("RAMHT entry not found. ch=%d, handle=0x%08x\n",
		  ref->channel, ref->handle);
}

int
nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
		   int size, int align, uint32_t flags,
		   struct nouveau_gpuobj **gpuobj_ret)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_engine *engine = &dev_priv->Engine;
	struct nouveau_gpuobj *gpuobj;
	struct mem_block *pramin = NULL;
	int ret;

	DRM_DEBUG("ch%d size=%d align=%d flags=0x%08x\n",
		  chan ? chan->id : -1, size, align, flags);

	if (!dev_priv || !gpuobj_ret || *gpuobj_ret != NULL)
		return -EINVAL;

	gpuobj = drm_calloc(1, sizeof(*gpuobj), DRM_MEM_DRIVER);
	if (!gpuobj)
		return -ENOMEM;
	DRM_DEBUG("gpuobj %p\n", gpuobj);
	gpuobj->flags = flags;
	gpuobj->im_channel = chan ? chan->id : -1;

	list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);

	/* Choose between global instmem heap, and per-channel private
	 * instmem heap.  On <NV50 allow requests for private instmem
	 * to be satisfied from global heap if no per-channel area
	 * available.
	 */
	if (chan) {
		if (chan->ramin_heap) {
			DRM_DEBUG("private heap\n");
			pramin = chan->ramin_heap;
		} else
		if (dev_priv->card_type < NV_50) {
			DRM_DEBUG("global heap fallback\n");
			pramin = dev_priv->ramin_heap;
		}
	} else {
		DRM_DEBUG("global heap\n");
		pramin = dev_priv->ramin_heap;
	}

	if (!pramin) {
		DRM_ERROR("No PRAMIN heap!\n");
		return -EINVAL;
	}

	if (!chan && (ret = engine->instmem.populate(dev, gpuobj, &size))) {
		nouveau_gpuobj_del(dev, &gpuobj);
		return ret;
	}

	/* Allocate a chunk of the PRAMIN aperture */
	gpuobj->im_pramin = nouveau_mem_alloc_block(pramin, size,
						    drm_order(align),
						    (struct drm_file *)-2);
	if (!gpuobj->im_pramin) {
		nouveau_gpuobj_del(dev, &gpuobj);
		return -ENOMEM;
	}
	gpuobj->im_pramin->flags = NOUVEAU_MEM_INSTANCE;

	if (!chan && (ret = engine->instmem.bind(dev, gpuobj))) {
		nouveau_gpuobj_del(dev, &gpuobj);
		return ret;
	}

	if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {
		int i;

		for (i = 0; i < gpuobj->im_pramin->size; i += 4)
			INSTANCE_WR(gpuobj, i/4, 0);
	}

	*gpuobj_ret = gpuobj;
	return 0;
}

int
nouveau_gpuobj_early_init(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;

	DRM_DEBUG("\n");

	INIT_LIST_HEAD(&dev_priv->gpuobj_list);

	return 0;
}

int
nouveau_gpuobj_init(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	int ret;

	DRM_DEBUG("\n");

	if (dev_priv->card_type < NV_50) {
		if ((ret = nouveau_gpuobj_new_fake(dev, dev_priv->ramht_offset,
						   ~0, dev_priv->ramht_size,
						   NVOBJ_FLAG_ZERO_ALLOC |
						   NVOBJ_FLAG_ALLOW_NO_REFS,
						   &dev_priv->ramht, NULL)))
			return ret;
	}

	return 0;
}

void
nouveau_gpuobj_takedown(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;

	DRM_DEBUG("\n");

	nouveau_gpuobj_del(dev, &dev_priv->ramht);
}

void
nouveau_gpuobj_late_takedown(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_gpuobj *gpuobj = NULL;
	struct list_head *entry, *tmp;

	DRM_DEBUG("\n");

	list_for_each_safe(entry, tmp, &dev_priv->gpuobj_list) {
		gpuobj = list_entry(entry, struct nouveau_gpuobj, list);

		DRM_ERROR("gpuobj %p still exists at takedown, refs=%d\n",
			  gpuobj, gpuobj->refcount);
		gpuobj->refcount = 0;
		nouveau_gpuobj_del(dev, &gpuobj);
	}
}

int
nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_engine *engine = &dev_priv->Engine;
	struct nouveau_gpuobj *gpuobj;

	DRM_DEBUG("gpuobj %p\n", pgpuobj ? *pgpuobj : NULL);

	if (!dev_priv || !pgpuobj || !(*pgpuobj))
		return -EINVAL;
	gpuobj = *pgpuobj;

	if (gpuobj->refcount != 0) {
		DRM_ERROR("gpuobj refcount is %d\n", gpuobj->refcount);
		return -EINVAL;
	}

	if (gpuobj->dtor)
		gpuobj->dtor(dev, gpuobj);

	if (gpuobj->im_backing) {
		if (gpuobj->flags & NVOBJ_FLAG_FAKE)
			drm_free(gpuobj->im_backing,
				 sizeof(*gpuobj->im_backing), DRM_MEM_DRIVER);
		else
			engine->instmem.clear(dev, gpuobj);
	}

	if (gpuobj->im_pramin) {
		if (gpuobj->flags & NVOBJ_FLAG_FAKE)
			drm_free(gpuobj->im_pramin, sizeof(*gpuobj->im_pramin),
				 DRM_MEM_DRIVER);
		else
			nouveau_mem_free_block(gpuobj->im_pramin);
	}

	list_del(&gpuobj->list);

	*pgpuobj = NULL;
	drm_free(gpuobj, sizeof(*gpuobj), DRM_MEM_DRIVER);
	return 0;
}

static int
nouveau_gpuobj_instance_get(struct drm_device *dev,
			    struct nouveau_channel *chan,
			    struct nouveau_gpuobj *gpuobj, uint32_t *inst)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_gpuobj *cpramin;

	/* <NV50 use PRAMIN address everywhere */
	if (dev_priv->card_type < NV_50) {
		*inst = gpuobj->im_pramin->start;
		return 0;
	}

	if (chan && gpuobj->im_channel != chan->id) {
		DRM_ERROR("Channel mismatch: obj %d, ref %d\n",
			  gpuobj->im_channel, chan->id);
		return -EINVAL;
	}

	/* NV50 channel-local instance */
	if (chan > 0) {
		cpramin = chan->ramin->gpuobj;
		*inst = gpuobj->im_pramin->start - cpramin->im_pramin->start;
		return 0;
	}

	/* NV50 global (VRAM) instance */
	if (gpuobj->im_channel < 0) {
		/* ...from global heap */
		if (!gpuobj->im_backing) {
			DRM_ERROR("AII, no VRAM backing gpuobj\n");
			return -EINVAL;
		}
		*inst = gpuobj->im_backing->start;
		return 0;
	} else {
		/* ...from local heap */
		cpramin = dev_priv->fifos[gpuobj->im_channel]->ramin->gpuobj;
		*inst = cpramin->im_backing->start +
			(gpuobj->im_pramin->start - cpramin->im_pramin->start);
		return 0;
	}

	return -EINVAL;
}

int
nouveau_gpuobj_ref_add(struct drm_device *dev, struct nouveau_channel *chan,
		       uint32_t handle, struct nouveau_gpuobj *gpuobj,
		       struct nouveau_gpuobj_ref **ref_ret)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_gpuobj_ref *ref;
	uint32_t instance;
	int ret;

	DRM_DEBUG("ch%d h=0x%08x gpuobj=%p\n",
		  chan ? chan->id : -1, handle, gpuobj);

	if (!dev_priv || !gpuobj || (ref_ret && *ref_ret != NULL))
		return -EINVAL;

	if (!chan && !ref_ret)
		return -EINVAL;

	ret = nouveau_gpuobj_instance_get(dev, chan, gpuobj, &instance);
	if (ret)
		return ret;

	ref = drm_calloc(1, sizeof(*ref), DRM_MEM_DRIVER);
	if (!ref)
		return -ENOMEM;
	ref->gpuobj   = gpuobj;
	ref->channel  = chan ? chan->id : -1;