summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/common/linux/driver_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/common/linux/driver_common.c')
-rw-r--r--drivers/gpu/nvgpu/common/linux/driver_common.c292
1 files changed, 292 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/driver_common.c b/drivers/gpu/nvgpu/common/linux/driver_common.c
new file mode 100644
index 00000000..9e567c27
--- /dev/null
+++ b/drivers/gpu/nvgpu/common/linux/driver_common.c
@@ -0,0 +1,292 @@
1/*
2 * Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <linux/dma-mapping.h>
18#include <uapi/linux/nvgpu.h>
19
20#include <nvgpu/kmem.h>
21#include <nvgpu/nvgpu_common.h>
22#include <nvgpu/soc.h>
23#include <nvgpu/bug.h>
24#include <nvgpu/enabled.h>
25#include <nvgpu/debug.h>
26
27#include "scale.h"
28#include "gk20a/gk20a.h"
29#include "platform_gk20a.h"
30#include "module.h"
31#include "os_linux.h"
32#include "sysfs.h"
33#include "ioctl.h"
34
35#define EMC3D_DEFAULT_RATIO 750
36
37static void nvgpu_init_vars(struct gk20a *g)
38{
39 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
40 struct device *dev = dev_from_gk20a(g);
41 struct gk20a_platform *platform = dev_get_drvdata(dev);
42
43 nvgpu_cond_init(&l->sw_irq_stall_last_handled_wq);
44 nvgpu_cond_init(&l->sw_irq_nonstall_last_handled_wq);
45 gk20a_init_gr(g);
46
47 init_rwsem(&l->busy_lock);
48 nvgpu_rwsem_init(&g->deterministic_busy);
49
50 nvgpu_spinlock_init(&g->mc_enable_lock);
51
52 nvgpu_mutex_init(&platform->railgate_lock);
53 nvgpu_mutex_init(&g->dbg_sessions_lock);
54 nvgpu_mutex_init(&g->client_lock);
55 nvgpu_mutex_init(&g->poweron_lock);
56 nvgpu_mutex_init(&g->poweroff_lock);
57
58 l->regs_saved = l->regs;
59 l->bar1_saved = l->bar1;
60
61 g->emc3d_ratio = EMC3D_DEFAULT_RATIO;
62
63 /* Set DMA parameters to allow larger sgt lists */
64 dev->dma_parms = &l->dma_parms;
65 dma_set_max_seg_size(dev, UINT_MAX);
66
67 nvgpu_init_list_node(&g->pending_sema_waits);
68 nvgpu_raw_spinlock_init(&g->pending_sema_waits_lock);
69
70 nvgpu_init_list_node(&g->profiler_objects);
71
72 nvgpu_init_list_node(&g->boardobj_head);
73 nvgpu_init_list_node(&g->boardobjgrp_head);
74}
75
76static void nvgpu_init_timeout(struct gk20a *g)
77{
78 struct gk20a_platform *platform = dev_get_drvdata(dev_from_gk20a(g));
79
80 g->gr_idle_timeout_default = CONFIG_GK20A_DEFAULT_TIMEOUT;
81 if (nvgpu_platform_is_silicon(g))
82 g->timeouts_enabled = true;
83 else if (nvgpu_platform_is_fpga(g)) {
84 g->gr_idle_timeout_default = GK20A_TIMEOUT_FPGA;
85 g->timeouts_enabled = true;
86 }
87 g->ch_wdt_timeout_ms = platform->ch_wdt_timeout_ms;
88}
89
90static void nvgpu_init_timeslice(struct gk20a *g)
91{
92 g->runlist_interleave = true;
93
94 g->timeslice_low_priority_us = 1300;
95 g->timeslice_medium_priority_us = 2600;
96 g->timeslice_high_priority_us = 5200;
97
98 g->min_timeslice_us = 1000;
99 g->max_timeslice_us = 50000;
100}
101
102static void nvgpu_init_pm_vars(struct gk20a *g)
103{
104 struct gk20a_platform *platform = dev_get_drvdata(dev_from_gk20a(g));
105
106 /*
107 * Set up initial power settings. For non-slicon platforms, disable
108 * power features and for silicon platforms, read from platform data
109 */
110 g->slcg_enabled =
111 nvgpu_platform_is_silicon(g) ? platform->enable_slcg : false;
112 g->blcg_enabled =
113 nvgpu_platform_is_silicon(g) ? platform->enable_blcg : false;
114 g->elcg_enabled =
115 nvgpu_platform_is_silicon(g) ? platform->enable_elcg : false;
116 g->elpg_enabled =
117 nvgpu_platform_is_silicon(g) ? platform->enable_elpg : false;
118 g->aelpg_enabled =
119 nvgpu_platform_is_silicon(g) ? platform->enable_aelpg : false;
120 g->mscg_enabled =
121 nvgpu_platform_is_silicon(g) ? platform->enable_mscg : false;
122 g->can_elpg =
123 nvgpu_platform_is_silicon(g) ? platform->can_elpg_init : false;
124
125 __nvgpu_set_enabled(g, NVGPU_GPU_CAN_ELCG,
126 nvgpu_platform_is_silicon(g) ? platform->can_elcg : false);
127 __nvgpu_set_enabled(g, NVGPU_GPU_CAN_SLCG,
128 nvgpu_platform_is_silicon(g) ? platform->can_slcg : false);
129 __nvgpu_set_enabled(g, NVGPU_GPU_CAN_BLCG,
130 nvgpu_platform_is_silicon(g) ? platform->can_blcg : false);
131
132 g->default_pri_timeout = platform->default_pri_timeout;
133 g->aggressive_sync_destroy = platform->aggressive_sync_destroy;
134 g->aggressive_sync_destroy_thresh = platform->aggressive_sync_destroy_thresh;
135 g->has_syncpoints = platform->has_syncpoints;
136 g->ptimer_src_freq = platform->ptimer_src_freq;
137 g->support_pmu = support_gk20a_pmu(dev_from_gk20a(g));
138 g->can_railgate = platform->can_railgate_init;
139 g->railgate_delay = platform->railgate_delay_init;
140 __nvgpu_set_enabled(g, NVGPU_PMU_PERFMON, platform->enable_perfmon);
141
142 /* set default values to aelpg parameters */
143 g->pmu.aelpg_param[0] = APCTRL_SAMPLING_PERIOD_PG_DEFAULT_US;
144 g->pmu.aelpg_param[1] = APCTRL_MINIMUM_IDLE_FILTER_DEFAULT_US;
145 g->pmu.aelpg_param[2] = APCTRL_MINIMUM_TARGET_SAVING_DEFAULT_US;
146 g->pmu.aelpg_param[3] = APCTRL_POWER_BREAKEVEN_DEFAULT_US;
147 g->pmu.aelpg_param[4] = APCTRL_CYCLES_PER_SAMPLE_MAX_DEFAULT;
148
149 __nvgpu_set_enabled(g, NVGPU_SUPPORT_ASPM, !platform->disable_aspm);
150}
151
152static void nvgpu_init_vbios_vars(struct gk20a *g)
153{
154 struct gk20a_platform *platform = dev_get_drvdata(dev_from_gk20a(g));
155
156 __nvgpu_set_enabled(g, NVGPU_PMU_RUN_PREOS, platform->run_preos);
157 g->vbios_min_version = platform->vbios_min_version;
158}
159
160static void nvgpu_init_mm_vars(struct gk20a *g)
161{
162 struct gk20a_platform *platform = dev_get_drvdata(dev_from_gk20a(g));
163
164 g->mm.bypass_smmu = platform->bypass_smmu;
165 g->mm.disable_bigpage = platform->disable_bigpage;
166 __nvgpu_set_enabled(g, NVGPU_MM_HONORS_APERTURE,
167 platform->honors_aperture);
168 __nvgpu_set_enabled(g, NVGPU_MM_UNIFIED_MEMORY,
169 platform->unified_memory);
170 __nvgpu_set_enabled(g, NVGPU_MM_UNIFY_ADDRESS_SPACES,
171 platform->unify_address_spaces);
172 __nvgpu_set_enabled(g, NVGPU_MM_CE_TSG_REQUIRED,
173 platform->tsg_required);
174
175 nvgpu_mutex_init(&g->mm.tlb_lock);
176 nvgpu_mutex_init(&g->mm.priv_lock);
177}
178
179int nvgpu_probe(struct gk20a *g,
180 const char *debugfs_symlink,
181 const char *interface_name,
182 struct class *class)
183{
184 struct device *dev = dev_from_gk20a(g);
185 struct gk20a_platform *platform = dev_get_drvdata(dev);
186 int err = 0;
187
188 nvgpu_init_vars(g);
189 nvgpu_init_timeout(g);
190 nvgpu_init_timeslice(g);
191 nvgpu_init_pm_vars(g);
192 nvgpu_init_vbios_vars(g);
193
194 /* Initialize the platform interface. */
195 err = platform->probe(dev);
196 if (err) {
197 if (err == -EPROBE_DEFER)
198 nvgpu_info(g, "platform probe failed");
199 else
200 nvgpu_err(g, "platform probe failed");
201 return err;
202 }
203
204 /* platform probe can defer do user init only if probe succeeds */
205 err = gk20a_user_init(dev, interface_name, class);
206 if (err)
207 return err;
208
209
210 /* Initialise scaling */
211 if (IS_ENABLED(CONFIG_GK20A_DEVFREQ))
212 gk20a_scale_init(dev);
213
214 if (platform->late_probe) {
215 err = platform->late_probe(dev);
216 if (err) {
217 nvgpu_err(g, "late probe failed");
218 return err;
219 }
220 }
221
222 nvgpu_init_mm_vars(g);
223
224 nvgpu_create_sysfs(dev);
225 gk20a_debug_init(g, debugfs_symlink);
226
227 g->dbg_regops_tmp_buf = nvgpu_kzalloc(g, SZ_4K);
228 if (!g->dbg_regops_tmp_buf) {
229 nvgpu_err(g, "couldn't allocate regops tmp buf");
230 return -ENOMEM;
231 }
232 g->dbg_regops_tmp_buf_ops =
233 SZ_4K / sizeof(g->dbg_regops_tmp_buf[0]);
234
235 g->remove_support = gk20a_remove_support;
236
237 nvgpu_ref_init(&g->refcount);
238
239 return 0;
240}
241
242/**
243 * cyclic_delta - Returns delta of cyclic integers a and b.
244 *
245 * @a - First integer
246 * @b - Second integer
247 *
248 * Note: if a is ahead of b, delta is positive.
249 */
250static int cyclic_delta(int a, int b)
251{
252 return a - b;
253}
254
255/**
256 * nvgpu_wait_for_deferred_interrupts - Wait for interrupts to complete
257 *
258 * @g - The GPU to wait on.
259 *
260 * Waits until all interrupt handlers that have been scheduled to run have
261 * completed.
262 */
263void nvgpu_wait_for_deferred_interrupts(struct gk20a *g)
264{
265 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
266 int stall_irq_threshold = atomic_read(&l->hw_irq_stall_count);
267 int nonstall_irq_threshold = atomic_read(&l->hw_irq_nonstall_count);
268
269 /* wait until all stalling irqs are handled */
270 NVGPU_COND_WAIT(&l->sw_irq_stall_last_handled_wq,
271 cyclic_delta(stall_irq_threshold,
272 atomic_read(&l->sw_irq_stall_last_handled))
273 <= 0, 0);
274
275 /* wait until all non-stalling irqs are handled */
276 NVGPU_COND_WAIT(&l->sw_irq_nonstall_last_handled_wq,
277 cyclic_delta(nonstall_irq_threshold,
278 atomic_read(&l->sw_irq_nonstall_last_handled))
279 <= 0, 0);
280}
281
282static void nvgpu_free_gk20a(struct gk20a *g)
283{
284 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
285
286 kfree(l);
287}
288
289void nvgpu_init_gk20a(struct gk20a *g)
290{
291 g->free = nvgpu_free_gk20a;
292}