summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/nvgpu/gk20a/cde_gk20a.c3
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.c57
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.h8
-rw-r--r--drivers/gpu/nvgpu/gk20a/gr_ctx_gk20a.c3
-rw-r--r--drivers/gpu/nvgpu/gk20a/gr_gk20a.c5
-rw-r--r--drivers/gpu/nvgpu/gk20a/pmu_gk20a.c14
-rw-r--r--drivers/gpu/nvgpu/gk20a/pmu_gk20a.h2
-rw-r--r--drivers/gpu/nvgpu/gm206/acr_gm206.c5
-rw-r--r--drivers/gpu/nvgpu/gm206/bios_gm206.c5
-rw-r--r--drivers/gpu/nvgpu/gm20b/acr_gm20b.c18
-rw-r--r--drivers/gpu/nvgpu/nvgpu_common.c67
-rw-r--r--drivers/gpu/nvgpu/nvgpu_common.h7
12 files changed, 109 insertions, 85 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/cde_gk20a.c b/drivers/gpu/nvgpu/gk20a/cde_gk20a.c
index 844718a7..ca785b19 100644
--- a/drivers/gpu/nvgpu/gk20a/cde_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/cde_gk20a.c
@@ -32,6 +32,7 @@
32#include "gr_gk20a.h" 32#include "gr_gk20a.h"
33#include "debug_gk20a.h" 33#include "debug_gk20a.h"
34#include "semaphore_gk20a.h" 34#include "semaphore_gk20a.h"
35#include "nvgpu_common.h"
35 36
36#include "hw_ccsr_gk20a.h" 37#include "hw_ccsr_gk20a.h"
37#include "hw_pbdma_gk20a.h" 38#include "hw_pbdma_gk20a.h"
@@ -1179,7 +1180,7 @@ static int gk20a_cde_load(struct gk20a_cde_ctx *cde_ctx)
1179 int err = 0; 1180 int err = 0;
1180 u64 vaddr; 1181 u64 vaddr;
1181 1182
1182 img = gk20a_request_firmware(g, "gpu2cde.bin"); 1183 img = nvgpu_request_firmware(g, "gpu2cde.bin", 0);
1183 if (!img) { 1184 if (!img) {
1184 dev_err(cde_ctx->dev, "cde: could not fetch the firmware"); 1185 dev_err(cde_ctx->dev, "cde: could not fetch the firmware");
1185 return -ENOSYS; 1186 return -ENOSYS;
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c
index 51384933..721c44e3 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/gk20a.c
@@ -22,7 +22,6 @@
22#include <linux/string.h> 22#include <linux/string.h>
23#include <linux/cdev.h> 23#include <linux/cdev.h>
24#include <linux/delay.h> 24#include <linux/delay.h>
25#include <linux/firmware.h>
26#include <linux/interrupt.h> 25#include <linux/interrupt.h>
27#include <linux/irq.h> 26#include <linux/irq.h>
28#include <linux/export.h> 27#include <linux/export.h>
@@ -706,8 +705,6 @@ void gk20a_remove_support(struct device *dev)
706 if (g->sim.remove_support) 705 if (g->sim.remove_support)
707 g->sim.remove_support(&g->sim); 706 g->sim.remove_support(&g->sim);
708 707
709 release_firmware(g->pmu_fw);
710
711 /* free mappings to registers, etc */ 708 /* free mappings to registers, etc */
712 709
713 if (g->regs) { 710 if (g->regs) {
@@ -2047,60 +2044,6 @@ int gk20a_init_gpu_characteristics(struct gk20a *g)
2047 return 0; 2044 return 0;
2048} 2045}
2049 2046
2050static const struct firmware *
2051do_request_firmware(struct device *dev, const char *prefix, const char *fw_name)
2052{
2053 const struct firmware *fw;
2054 char *fw_path = NULL;
2055 int path_len, err;
2056
2057 if (prefix) {
2058 path_len = strlen(prefix) + strlen(fw_name);
2059 path_len += 2; /* for the path separator and zero terminator*/
2060
2061 fw_path = kzalloc(sizeof(*fw_path) * path_len, GFP_KERNEL);
2062 if (!fw_path)
2063 return NULL;
2064
2065 sprintf(fw_path, "%s/%s", prefix, fw_name);
2066 fw_name = fw_path;
2067 }
2068
2069 err = request_firmware(&fw, fw_name, dev);
2070 kfree(fw_path);
2071 if (err)
2072 return NULL;
2073 return fw;
2074}
2075
2076/* This is a simple wrapper around request_firmware that takes 'fw_name' and
2077 * applies an IP specific relative path prefix to it. The caller is
2078 * responsible for calling release_firmware later. */
2079const struct firmware *
2080gk20a_request_firmware(struct gk20a *g, const char *fw_name)
2081{
2082 struct device *dev = g->dev;
2083 const struct firmware *fw;
2084
2085 /* current->fs is NULL when calling from SYS_EXIT.
2086 Add a check here to prevent crash in request_firmware */
2087 if (!current->fs || !fw_name)
2088 return NULL;
2089
2090 BUG_ON(!g->ops.name);
2091 fw = do_request_firmware(dev, g->ops.name, fw_name);
2092
2093#ifdef CONFIG_TEGRA_GK20A
2094 /* TO BE REMOVED - Support loading from legacy SOC specific path. */
2095 if (!fw) {
2096 struct gk20a_platform *platform = gk20a_get_platform(dev);
2097 fw = do_request_firmware(dev, platform->soc_name, fw_name);
2098 }
2099#endif
2100
2101 return fw;
2102}
2103
2104int gk20a_read_ptimer(struct gk20a *g, u64 *value) 2047int gk20a_read_ptimer(struct gk20a *g, u64 *value)
2105{ 2048{
2106 const unsigned int max_iterations = 3; 2049 const unsigned int max_iterations = 3;
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h
index 1cccaebe..2b55dd26 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/gk20a.h
@@ -762,11 +762,6 @@ struct gk20a {
762#ifdef CONFIG_DEBUG_FS 762#ifdef CONFIG_DEBUG_FS
763 struct railgate_stats pstats; 763 struct railgate_stats pstats;
764#endif 764#endif
765 /* Save pmu fw here so that it lives cross suspend/resume.
766 pmu suspend destroys all pmu sw/hw states. Loading pmu
767 fw in resume crashes when the resume is from sys_exit. */
768 const struct firmware *pmu_fw;
769
770 u32 gr_idle_timeout_default; 765 u32 gr_idle_timeout_default;
771#if LINUX_VERSION_CODE < KERNEL_VERSION(4,4,0) 766#if LINUX_VERSION_CODE < KERNEL_VERSION(4,4,0)
772 u32 timeouts_enabled; 767 u32 timeouts_enabled;
@@ -1178,9 +1173,6 @@ int gk20a_do_unidle(void);
1178int __gk20a_do_idle(struct device *dev, bool force_reset); 1173int __gk20a_do_idle(struct device *dev, bool force_reset);
1179int __gk20a_do_unidle(struct device *dev); 1174int __gk20a_do_unidle(struct device *dev);
1180 1175
1181const struct firmware *
1182gk20a_request_firmware(struct gk20a *g, const char *fw_name);
1183
1184#define NVGPU_GPU_ARCHITECTURE_SHIFT 4 1176#define NVGPU_GPU_ARCHITECTURE_SHIFT 4
1185 1177
1186/* constructs unique and compact GPUID from nvgpu_gpu_characteristics 1178/* constructs unique and compact GPUID from nvgpu_gpu_characteristics
diff --git a/drivers/gpu/nvgpu/gk20a/gr_ctx_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_ctx_gk20a.c
index 5b76eee2..5a1152d5 100644
--- a/drivers/gpu/nvgpu/gk20a/gr_ctx_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/gr_ctx_gk20a.c
@@ -24,6 +24,7 @@
24#include "gk20a.h" 24#include "gk20a.h"
25#include "gr_ctx_gk20a.h" 25#include "gr_ctx_gk20a.h"
26#include "hw_gr_gk20a.h" 26#include "hw_gr_gk20a.h"
27#include "nvgpu_common.h"
27 28
28static int gr_gk20a_alloc_load_netlist_u32(u32 *src, u32 len, 29static int gr_gk20a_alloc_load_netlist_u32(u32 *src, u32 len,
29 struct u32_list_gk20a *u32_list) 30 struct u32_list_gk20a *u32_list)
@@ -135,7 +136,7 @@ static int gr_gk20a_init_ctx_vars_fw(struct gk20a *g, struct gr_gk20a *gr)
135 continue; 136 continue;
136 } 137 }
137 138
138 netlist_fw = gk20a_request_firmware(g, name); 139 netlist_fw = nvgpu_request_firmware(g, name, 0);
139 if (!netlist_fw) { 140 if (!netlist_fw) {
140 gk20a_warn(d, "failed to load netlist %s", name); 141 gk20a_warn(d, "failed to load netlist %s", name);
141 continue; 142 continue;
diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
index 883cacdc..9a201cb6 100644
--- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
@@ -34,6 +34,7 @@
34#include "gk20a.h" 34#include "gk20a.h"
35#include "kind_gk20a.h" 35#include "kind_gk20a.h"
36#include "gr_ctx_gk20a.h" 36#include "gr_ctx_gk20a.h"
37#include "nvgpu_common.h"
37 38
38#include "hw_ccsr_gk20a.h" 39#include "hw_ccsr_gk20a.h"
39#include "hw_ctxsw_prog_gk20a.h" 40#include "hw_ctxsw_prog_gk20a.h"
@@ -2124,7 +2125,7 @@ int gr_gk20a_init_ctxsw_ucode(struct gk20a *g)
2124 u32 ucode_size; 2125 u32 ucode_size;
2125 int err = 0; 2126 int err = 0;
2126 2127
2127 fecs_fw = gk20a_request_firmware(g, GK20A_FECS_UCODE_IMAGE); 2128 fecs_fw = nvgpu_request_firmware(g, GK20A_FECS_UCODE_IMAGE, 0);
2128 if (!fecs_fw) { 2129 if (!fecs_fw) {
2129 gk20a_err(d, "failed to load fecs ucode!!"); 2130 gk20a_err(d, "failed to load fecs ucode!!");
2130 return -ENOENT; 2131 return -ENOENT;
@@ -2134,7 +2135,7 @@ int gr_gk20a_init_ctxsw_ucode(struct gk20a *g)
2134 fecs_boot_image = (void *)(fecs_fw->data + 2135 fecs_boot_image = (void *)(fecs_fw->data +
2135 sizeof(struct gk20a_ctxsw_bootloader_desc)); 2136 sizeof(struct gk20a_ctxsw_bootloader_desc));
2136 2137
2137 gpccs_fw = gk20a_request_firmware(g, GK20A_GPCCS_UCODE_IMAGE); 2138 gpccs_fw = nvgpu_request_firmware(g, GK20A_GPCCS_UCODE_IMAGE, 0);
2138 if (!gpccs_fw) { 2139 if (!gpccs_fw) {
2139 release_firmware(fecs_fw); 2140 release_firmware(fecs_fw);
2140 gk20a_err(d, "failed to load gpccs ucode!!"); 2141 gk20a_err(d, "failed to load gpccs ucode!!");
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
index ca9f2e15..fc95b5bc 100644
--- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
@@ -30,6 +30,7 @@
30#include "hw_mc_gk20a.h" 30#include "hw_mc_gk20a.h"
31#include "hw_pwr_gk20a.h" 31#include "hw_pwr_gk20a.h"
32#include "hw_top_gk20a.h" 32#include "hw_top_gk20a.h"
33#include "nvgpu_common.h"
33 34
34#ifdef CONFIG_ARCH_TEGRA_18x_SOC 35#ifdef CONFIG_ARCH_TEGRA_18x_SOC
35#include "nvgpu_gpuid_t18x.h" 36#include "nvgpu_gpuid_t18x.h"
@@ -2883,6 +2884,8 @@ void gk20a_remove_pmu_support(struct pmu_gk20a *pmu)
2883 2884
2884 if (gk20a_alloc_initialized(&pmu->dmem)) 2885 if (gk20a_alloc_initialized(&pmu->dmem))
2885 gk20a_alloc_destroy(&pmu->dmem); 2886 gk20a_alloc_destroy(&pmu->dmem);
2887
2888 release_firmware(pmu->fw);
2886} 2889}
2887 2890
2888static int gk20a_init_pmu_reset_enable_hw(struct gk20a *g) 2891static int gk20a_init_pmu_reset_enable_hw(struct gk20a *g)
@@ -2904,18 +2907,18 @@ static int gk20a_prepare_ucode(struct gk20a *g)
2904 struct mm_gk20a *mm = &g->mm; 2907 struct mm_gk20a *mm = &g->mm;
2905 struct vm_gk20a *vm = &mm->pmu.vm; 2908 struct vm_gk20a *vm = &mm->pmu.vm;
2906 2909
2907 if (g->pmu_fw) 2910 if (pmu->fw)
2908 return gk20a_init_pmu(pmu); 2911 return gk20a_init_pmu(pmu);
2909 2912
2910 g->pmu_fw = gk20a_request_firmware(g, GK20A_PMU_UCODE_IMAGE); 2913 pmu->fw = nvgpu_request_firmware(g, GK20A_PMU_UCODE_IMAGE, 0);
2911 if (!g->pmu_fw) { 2914 if (!pmu->fw) {
2912 gk20a_err(d, "failed to load pmu ucode!!"); 2915 gk20a_err(d, "failed to load pmu ucode!!");
2913 return err; 2916 return err;
2914 } 2917 }
2915 2918
2916 gk20a_dbg_fn("firmware loaded"); 2919 gk20a_dbg_fn("firmware loaded");
2917 2920
2918 pmu->desc = (struct pmu_ucode_desc *)g->pmu_fw->data; 2921 pmu->desc = (struct pmu_ucode_desc *)pmu->fw->data;
2919 pmu->ucode_image = (u32 *)((u8 *)pmu->desc + 2922 pmu->ucode_image = (u32 *)((u8 *)pmu->desc +
2920 pmu->desc->descriptor_size); 2923 pmu->desc->descriptor_size);
2921 2924
@@ -2930,7 +2933,8 @@ static int gk20a_prepare_ucode(struct gk20a *g)
2930 return gk20a_init_pmu(pmu); 2933 return gk20a_init_pmu(pmu);
2931 2934
2932 err_release_fw: 2935 err_release_fw:
2933 release_firmware(g->pmu_fw); 2936 release_firmware(pmu->fw);
2937 pmu->fw = NULL;
2934 2938
2935 return err; 2939 return err;
2936} 2940}
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h
index fe82eca4..b28fd597 100644
--- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h
@@ -738,6 +738,8 @@ struct pmu_gk20a {
738 u32 falcon_id; 738 u32 falcon_id;
739 u32 aelpg_param[5]; 739 u32 aelpg_param[5];
740 u32 override_done; 740 u32 override_done;
741
742 const struct firmware *fw;
741}; 743};
742 744
743int gk20a_init_pmu_support(struct gk20a *g); 745int gk20a_init_pmu_support(struct gk20a *g);
diff --git a/drivers/gpu/nvgpu/gm206/acr_gm206.c b/drivers/gpu/nvgpu/gm206/acr_gm206.c
index 39b30ea6..872ff601 100644
--- a/drivers/gpu/nvgpu/gm206/acr_gm206.c
+++ b/drivers/gpu/nvgpu/gm206/acr_gm206.c
@@ -25,6 +25,7 @@
25#include "hw_pwr_gm206.h" 25#include "hw_pwr_gm206.h"
26#include "acr.h" 26#include "acr.h"
27#include "acr_gm206.h" 27#include "acr_gm206.h"
28#include "nvgpu_common.h"
28 29
29/*Defines*/ 30/*Defines*/
30#define gm206_dbg_pmu(fmt, arg...) \ 31#define gm206_dbg_pmu(fmt, arg...) \
@@ -226,7 +227,9 @@ static int gm206_bootstrap_hs_flcn(struct gk20a *g)
226 227
227 if (!acr_fw) { 228 if (!acr_fw) {
228 /*First time init case*/ 229 /*First time init case*/
229 acr_fw = gk20a_request_firmware(g, GM20B_HSBIN_PMU_UCODE_IMAGE); 230 acr_fw = nvgpu_request_firmware(g,
231 GM20B_HSBIN_PMU_UCODE_IMAGE,
232 NVGPU_REQUEST_FIRMWARE_NO_SOC);
230 if (!acr_fw) { 233 if (!acr_fw) {
231 gk20a_err(dev_from_gk20a(g), "pmu ucode get fail"); 234 gk20a_err(dev_from_gk20a(g), "pmu ucode get fail");
232 return -ENOENT; 235 return -ENOENT;
diff --git a/drivers/gpu/nvgpu/gm206/bios_gm206.c b/drivers/gpu/nvgpu/gm206/bios_gm206.c
index 6a509b04..a8f3f1d5 100644
--- a/drivers/gpu/nvgpu/gm206/bios_gm206.c
+++ b/drivers/gpu/nvgpu/gm206/bios_gm206.c
@@ -24,6 +24,7 @@
24#include "hw_xve_gm206.h" 24#include "hw_xve_gm206.h"
25#include "hw_top_gm206.h" 25#include "hw_top_gm206.h"
26#include "bios_gm206.h" 26#include "bios_gm206.h"
27#include "nvgpu_common.h"
27 28
28#define BIT_HEADER_ID 0xb8ff 29#define BIT_HEADER_ID 0xb8ff
29#define BIT_HEADER_SIGNATURE 0x00544942 30#define BIT_HEADER_SIGNATURE 0x00544942
@@ -739,7 +740,9 @@ static int gm206_bios_init(struct gk20a *g)
739 740
740 snprintf(rom_name, sizeof(rom_name), BIOS_OVERLAY_NAME, pdev->device); 741 snprintf(rom_name, sizeof(rom_name), BIOS_OVERLAY_NAME, pdev->device);
741 gk20a_dbg_info("checking for VBIOS overlay %s", rom_name); 742 gk20a_dbg_info("checking for VBIOS overlay %s", rom_name);
742 bios_fw = gk20a_request_firmware(g, rom_name); 743 bios_fw = nvgpu_request_firmware(g, rom_name,
744 NVGPU_REQUEST_FIRMWARE_NO_WARN |
745 NVGPU_REQUEST_FIRMWARE_NO_SOC);
743 if (bios_fw) { 746 if (bios_fw) {
744 gk20a_dbg_info("using VBIOS overlay"); 747 gk20a_dbg_info("using VBIOS overlay");
745 g->bios.size = bios_fw->size - ROM_FILE_PAYLOAD_OFFSET; 748 g->bios.size = bios_fw->size - ROM_FILE_PAYLOAD_OFFSET;
diff --git a/drivers/gpu/nvgpu/gm20b/acr_gm20b.c b/drivers/gpu/nvgpu/gm20b/acr_gm20b.c
index c4a188ff..310a3bc8 100644
--- a/drivers/gpu/nvgpu/gm20b/acr_gm20b.c
+++ b/drivers/gpu/nvgpu/gm20b/acr_gm20b.c
@@ -18,7 +18,7 @@
18#include <linux/debugfs.h> 18#include <linux/debugfs.h>
19#include <linux/dma-mapping.h> 19#include <linux/dma-mapping.h>
20#include <linux/io.h> 20#include <linux/io.h>
21#include "../../../../arch/arm/mach-tegra/iomap.h" 21#include "nvgpu_common.h"
22 22
23#include <linux/platform/tegra/mc.h> 23#include <linux/platform/tegra/mc.h>
24 24
@@ -118,7 +118,7 @@ static int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img)
118 struct lsf_ucode_desc *lsf_desc; 118 struct lsf_ucode_desc *lsf_desc;
119 int err; 119 int err;
120 gm20b_dbg_pmu("requesting PMU ucode in GM20B\n"); 120 gm20b_dbg_pmu("requesting PMU ucode in GM20B\n");
121 pmu_fw = gk20a_request_firmware(g, GM20B_PMU_UCODE_IMAGE); 121 pmu_fw = nvgpu_request_firmware(g, GM20B_PMU_UCODE_IMAGE, 0);
122 if (!pmu_fw) { 122 if (!pmu_fw) {
123 gk20a_err(dev_from_gk20a(g), "failed to load pmu ucode!!"); 123 gk20a_err(dev_from_gk20a(g), "failed to load pmu ucode!!");
124 return -ENOENT; 124 return -ENOENT;
@@ -127,13 +127,13 @@ static int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img)
127 gm20b_dbg_pmu("Loaded PMU ucode in for blob preparation"); 127 gm20b_dbg_pmu("Loaded PMU ucode in for blob preparation");
128 128
129 gm20b_dbg_pmu("requesting PMU ucode desc in GM20B\n"); 129 gm20b_dbg_pmu("requesting PMU ucode desc in GM20B\n");
130 pmu_desc = gk20a_request_firmware(g, GM20B_PMU_UCODE_DESC); 130 pmu_desc = nvgpu_request_firmware(g, GM20B_PMU_UCODE_DESC, 0);
131 if (!pmu_desc) { 131 if (!pmu_desc) {
132 gk20a_err(dev_from_gk20a(g), "failed to load pmu ucode desc!!"); 132 gk20a_err(dev_from_gk20a(g), "failed to load pmu ucode desc!!");
133 err = -ENOENT; 133 err = -ENOENT;
134 goto release_img_fw; 134 goto release_img_fw;
135 } 135 }
136 pmu_sig = gk20a_request_firmware(g, GM20B_PMU_UCODE_SIG); 136 pmu_sig = nvgpu_request_firmware(g, GM20B_PMU_UCODE_SIG, 0);
137 if (!pmu_sig) { 137 if (!pmu_sig) {
138 gk20a_err(dev_from_gk20a(g), "failed to load pmu sig!!"); 138 gk20a_err(dev_from_gk20a(g), "failed to load pmu sig!!");
139 err = -ENOENT; 139 err = -ENOENT;
@@ -181,7 +181,7 @@ static int fecs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img)
181 const struct firmware *fecs_sig; 181 const struct firmware *fecs_sig;
182 int err; 182 int err;
183 183
184 fecs_sig = gk20a_request_firmware(g, GM20B_FECS_UCODE_SIG); 184 fecs_sig = nvgpu_request_firmware(g, GM20B_FECS_UCODE_SIG, 0);
185 if (!fecs_sig) { 185 if (!fecs_sig) {
186 gk20a_err(dev_from_gk20a(g), "failed to load fecs sig"); 186 gk20a_err(dev_from_gk20a(g), "failed to load fecs sig");
187 return -ENOENT; 187 return -ENOENT;
@@ -251,7 +251,7 @@ static int gpccs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img)
251 if (g->ops.securegpccs == false) 251 if (g->ops.securegpccs == false)
252 return -ENOENT; 252 return -ENOENT;
253 253
254 gpccs_sig = gk20a_request_firmware(g, T18x_GPCCS_UCODE_SIG); 254 gpccs_sig = nvgpu_request_firmware(g, T18x_GPCCS_UCODE_SIG, 0);
255 if (!gpccs_sig) { 255 if (!gpccs_sig) {
256 gk20a_err(dev_from_gk20a(g), "failed to load gpccs sig"); 256 gk20a_err(dev_from_gk20a(g), "failed to load gpccs sig");
257 return -ENOENT; 257 return -ENOENT;
@@ -1071,7 +1071,7 @@ static int gm20b_bootstrap_hs_flcn(struct gk20a *g)
1071 1071
1072 if (!acr_fw) { 1072 if (!acr_fw) {
1073 /*First time init case*/ 1073 /*First time init case*/
1074 acr_fw = gk20a_request_firmware(g, GM20B_HSBIN_PMU_UCODE_IMAGE); 1074 acr_fw = nvgpu_request_firmware(g, GM20B_HSBIN_PMU_UCODE_IMAGE, 0);
1075 if (!acr_fw) { 1075 if (!acr_fw) {
1076 gk20a_err(dev_from_gk20a(g), "pmu ucode get fail"); 1076 gk20a_err(dev_from_gk20a(g), "pmu ucode get fail");
1077 return -ENOENT; 1077 return -ENOENT;
@@ -1382,8 +1382,8 @@ int pmu_exec_gen_bl(struct gk20a *g, void *desc, u8 b_wait_for_halt)
1382 gm20b_dbg_pmu(""); 1382 gm20b_dbg_pmu("");
1383 1383
1384 if (!hsbl_fw) { 1384 if (!hsbl_fw) {
1385 hsbl_fw = gk20a_request_firmware(g, 1385 hsbl_fw = nvgpu_request_firmware(g,
1386 GM20B_HSBIN_PMU_BL_UCODE_IMAGE); 1386 GM20B_HSBIN_PMU_BL_UCODE_IMAGE, 0);
1387 if (!hsbl_fw) { 1387 if (!hsbl_fw) {
1388 gk20a_err(dev_from_gk20a(g), "pmu ucode load fail"); 1388 gk20a_err(dev_from_gk20a(g), "pmu ucode load fail");
1389 return -ENOENT; 1389 return -ENOENT;
diff --git a/drivers/gpu/nvgpu/nvgpu_common.c b/drivers/gpu/nvgpu/nvgpu_common.c
index bdc07e50..fac818a2 100644
--- a/drivers/gpu/nvgpu/nvgpu_common.c
+++ b/drivers/gpu/nvgpu/nvgpu_common.c
@@ -15,9 +15,11 @@
15 */ 15 */
16 16
17#include <linux/dma-mapping.h> 17#include <linux/dma-mapping.h>
18#include <linux/firmware.h>
18 19
19#include "gk20a/gk20a_scale.h" 20#include "gk20a/gk20a_scale.h"
20#include "gk20a/gk20a.h" 21#include "gk20a/gk20a.h"
22#include "nvgpu_common.h"
21 23
22#define EMC3D_DEFAULT_RATIO 750 24#define EMC3D_DEFAULT_RATIO 750
23 25
@@ -152,3 +154,68 @@ int nvgpu_probe(struct gk20a *g,
152 154
153 return 0; 155 return 0;
154} 156}
157
158static const struct firmware *do_request_firmware(struct device *dev,
159 const char *prefix, const char *fw_name, int flags)
160{
161 const struct firmware *fw;
162 char *fw_path = NULL;
163 int path_len, err;
164
165 if (prefix) {
166 path_len = strlen(prefix) + strlen(fw_name);
167 path_len += 2; /* for the path separator and zero terminator*/
168
169 fw_path = kzalloc(sizeof(*fw_path) * path_len, GFP_KERNEL);
170 if (!fw_path)
171 return NULL;
172
173 sprintf(fw_path, "%s/%s", prefix, fw_name);
174 fw_name = fw_path;
175 }
176
177#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
178 err = request_firmware(&fw, fw_name, dev);
179#else
180 if (flags & NVGPU_REQUEST_FIRMWARE_NO_WARN)
181 err = request_firmware_direct(&fw, fw_name, dev);
182 else
183 err = request_firmware(&fw, fw_name, dev);
184#endif
185
186 kfree(fw_path);
187 if (err)
188 return NULL;
189 return fw;
190}
191
192/* This is a simple wrapper around request_firmware that takes 'fw_name' and
193 * applies an IP specific relative path prefix to it. The caller is
194 * responsible for calling release_firmware later. */
195const struct firmware *nvgpu_request_firmware(struct gk20a *g,
196 const char *fw_name,
197 int flags)
198{
199 struct device *dev = g->dev;
200 const struct firmware *fw;
201
202 /* current->fs is NULL when calling from SYS_EXIT.
203 Add a check here to prevent crash in request_firmware */
204 if (!current->fs || !fw_name)
205 return NULL;
206
207 BUG_ON(!g->ops.name);
208 fw = do_request_firmware(dev, g->ops.name, fw_name, flags);
209
210#ifdef CONFIG_TEGRA_GK20A
211 /* TO BE REMOVED - Support loading from legacy SOC specific path. */
212 if (!fw && !(flags & NVGPU_REQUEST_FIRMWARE_NO_SOC)) {
213 struct gk20a_platform *platform = gk20a_get_platform(dev);
214 fw = do_request_firmware(dev,
215 platform->soc_name, fw_name, flags);
216 }
217#endif
218
219 return fw;
220}
221
diff --git a/drivers/gpu/nvgpu/nvgpu_common.h b/drivers/gpu/nvgpu/nvgpu_common.h
index c9914089..8c159012 100644
--- a/drivers/gpu/nvgpu/nvgpu_common.h
+++ b/drivers/gpu/nvgpu/nvgpu_common.h
@@ -24,4 +24,11 @@ int nvgpu_probe(struct gk20a *g,
24 const char *interface_name, 24 const char *interface_name,
25 struct class *class); 25 struct class *class);
26 26
27#define NVGPU_REQUEST_FIRMWARE_NO_WARN BIT(0)
28#define NVGPU_REQUEST_FIRMWARE_NO_SOC BIT(1)
29
30const struct firmware *nvgpu_request_firmware(struct gk20a *g,
31 const char *fw_name,
32 int flags);
33
27#endif 34#endif