xref: /openbmc/linux/drivers/gpu/drm/i915/gvt/firmware.c (revision 8730046c)
1 /*
2  * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
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 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  *
23  * Authors:
24  *    Zhi Wang <zhi.a.wang@intel.com>
25  *
26  * Contributors:
27  *    Changbin Du <changbin.du@intel.com>
28  *
29  */
30 
31 #include <linux/firmware.h>
32 #include <linux/crc32.h>
33 
34 #include "i915_drv.h"
35 #include "gvt.h"
36 #include "i915_pvinfo.h"
37 
38 #define FIRMWARE_VERSION (0x0)
39 
40 struct gvt_firmware_header {
41 	u64 magic;
42 	u32 crc32;		/* protect the data after this field */
43 	u32 version;
44 	u64 cfg_space_size;
45 	u64 cfg_space_offset;	/* offset in the file */
46 	u64 mmio_size;
47 	u64 mmio_offset;	/* offset in the file */
48 	unsigned char data[1];
49 };
50 
51 #define RD(offset) (readl(mmio + offset.reg))
52 #define WR(v, offset) (writel(v, mmio + offset.reg))
53 
54 static void bdw_forcewake_get(void __iomem *mmio)
55 {
56 	WR(_MASKED_BIT_DISABLE(0xffff), FORCEWAKE_MT);
57 
58 	RD(ECOBUS);
59 
60 	if (wait_for((RD(FORCEWAKE_ACK_HSW) & FORCEWAKE_KERNEL) == 0, 50))
61 		gvt_err("fail to wait forcewake idle\n");
62 
63 	WR(_MASKED_BIT_ENABLE(FORCEWAKE_KERNEL), FORCEWAKE_MT);
64 
65 	if (wait_for((RD(FORCEWAKE_ACK_HSW) & FORCEWAKE_KERNEL), 50))
66 		gvt_err("fail to wait forcewake ack\n");
67 
68 	if (wait_for((RD(GEN6_GT_THREAD_STATUS_REG) &
69 		      GEN6_GT_THREAD_STATUS_CORE_MASK) == 0, 50))
70 		gvt_err("fail to wait c0 wake up\n");
71 }
72 
73 #undef RD
74 #undef WR
75 
76 #define dev_to_drm_minor(d) dev_get_drvdata((d))
77 
78 static ssize_t
79 gvt_firmware_read(struct file *filp, struct kobject *kobj,
80 	     struct bin_attribute *attr, char *buf,
81 	     loff_t offset, size_t count)
82 {
83 	memcpy(buf, attr->private + offset, count);
84 	return count;
85 }
86 
87 static struct bin_attribute firmware_attr = {
88 	.attr = {.name = "gvt_firmware", .mode = (S_IRUSR)},
89 	.read = gvt_firmware_read,
90 	.write = NULL,
91 	.mmap = NULL,
92 };
93 
94 static int expose_firmware_sysfs(struct intel_gvt *gvt,
95 					void __iomem *mmio)
96 {
97 	struct intel_gvt_device_info *info = &gvt->device_info;
98 	struct pci_dev *pdev = gvt->dev_priv->drm.pdev;
99 	struct intel_gvt_mmio_info *e;
100 	struct gvt_firmware_header *h;
101 	void *firmware;
102 	void *p;
103 	unsigned long size;
104 	int i;
105 	int ret;
106 
107 	size = sizeof(*h) + info->mmio_size + info->cfg_space_size - 1;
108 	firmware = vmalloc(size);
109 	if (!firmware)
110 		return -ENOMEM;
111 
112 	h = firmware;
113 
114 	h->magic = VGT_MAGIC;
115 	h->version = FIRMWARE_VERSION;
116 	h->cfg_space_size = info->cfg_space_size;
117 	h->cfg_space_offset = offsetof(struct gvt_firmware_header, data);
118 	h->mmio_size = info->mmio_size;
119 	h->mmio_offset = h->cfg_space_offset + h->cfg_space_size;
120 
121 	p = firmware + h->cfg_space_offset;
122 
123 	for (i = 0; i < h->cfg_space_size; i += 4)
124 		pci_read_config_dword(pdev, i, p + i);
125 
126 	memcpy(gvt->firmware.cfg_space, p, info->cfg_space_size);
127 
128 	p = firmware + h->mmio_offset;
129 
130 	hash_for_each(gvt->mmio.mmio_info_table, i, e, node) {
131 		int j;
132 
133 		for (j = 0; j < e->length; j += 4)
134 			*(u32 *)(p + e->offset + j) =
135 				readl(mmio + e->offset + j);
136 	}
137 
138 	memcpy(gvt->firmware.mmio, p, info->mmio_size);
139 
140 	firmware_attr.size = size;
141 	firmware_attr.private = firmware;
142 
143 	ret = device_create_bin_file(&pdev->dev, &firmware_attr);
144 	if (ret) {
145 		vfree(firmware);
146 		return ret;
147 	}
148 	return 0;
149 }
150 
151 static void clean_firmware_sysfs(struct intel_gvt *gvt)
152 {
153 	struct pci_dev *pdev = gvt->dev_priv->drm.pdev;
154 
155 	device_remove_bin_file(&pdev->dev, &firmware_attr);
156 	vfree(firmware_attr.private);
157 }
158 
159 /**
160  * intel_gvt_free_firmware - free GVT firmware
161  * @gvt: intel gvt device
162  *
163  */
164 void intel_gvt_free_firmware(struct intel_gvt *gvt)
165 {
166 	if (!gvt->firmware.firmware_loaded)
167 		clean_firmware_sysfs(gvt);
168 
169 	kfree(gvt->firmware.cfg_space);
170 	kfree(gvt->firmware.mmio);
171 }
172 
173 static int verify_firmware(struct intel_gvt *gvt,
174 			   const struct firmware *fw)
175 {
176 	struct intel_gvt_device_info *info = &gvt->device_info;
177 	struct drm_i915_private *dev_priv = gvt->dev_priv;
178 	struct pci_dev *pdev = dev_priv->drm.pdev;
179 	struct gvt_firmware_header *h;
180 	unsigned long id, crc32_start;
181 	const void *mem;
182 	const char *item;
183 	u64 file, request;
184 
185 	h = (struct gvt_firmware_header *)fw->data;
186 
187 	crc32_start = offsetof(struct gvt_firmware_header, crc32) + 4;
188 	mem = fw->data + crc32_start;
189 
190 #define VERIFY(s, a, b) do { \
191 	item = (s); file = (u64)(a); request = (u64)(b); \
192 	if ((a) != (b)) \
193 		goto invalid_firmware; \
194 } while (0)
195 
196 	VERIFY("magic number", h->magic, VGT_MAGIC);
197 	VERIFY("version", h->version, FIRMWARE_VERSION);
198 	VERIFY("crc32", h->crc32, crc32_le(0, mem, fw->size - crc32_start));
199 	VERIFY("cfg space size", h->cfg_space_size, info->cfg_space_size);
200 	VERIFY("mmio size", h->mmio_size, info->mmio_size);
201 
202 	mem = (fw->data + h->cfg_space_offset);
203 
204 	id = *(u16 *)(mem + PCI_VENDOR_ID);
205 	VERIFY("vender id", id, pdev->vendor);
206 
207 	id = *(u16 *)(mem + PCI_DEVICE_ID);
208 	VERIFY("device id", id, pdev->device);
209 
210 	id = *(u8 *)(mem + PCI_REVISION_ID);
211 	VERIFY("revision id", id, pdev->revision);
212 
213 #undef VERIFY
214 	return 0;
215 
216 invalid_firmware:
217 	gvt_dbg_core("Invalid firmware: %s [file] 0x%llx [request] 0x%llx\n",
218 		     item, file, request);
219 	return -EINVAL;
220 }
221 
222 #define GVT_FIRMWARE_PATH "i915/gvt"
223 
224 /**
225  * intel_gvt_load_firmware - load GVT firmware
226  * @gvt: intel gvt device
227  *
228  */
229 int intel_gvt_load_firmware(struct intel_gvt *gvt)
230 {
231 	struct intel_gvt_device_info *info = &gvt->device_info;
232 	struct drm_i915_private *dev_priv = gvt->dev_priv;
233 	struct pci_dev *pdev = dev_priv->drm.pdev;
234 	struct intel_gvt_firmware *firmware = &gvt->firmware;
235 	struct gvt_firmware_header *h;
236 	const struct firmware *fw;
237 	char *path;
238 	void __iomem *mmio;
239 	void *mem;
240 	int ret;
241 
242 	path = kmalloc(PATH_MAX, GFP_KERNEL);
243 	if (!path)
244 		return -ENOMEM;
245 
246 	mem = kmalloc(info->cfg_space_size, GFP_KERNEL);
247 	if (!mem) {
248 		kfree(path);
249 		return -ENOMEM;
250 	}
251 
252 	firmware->cfg_space = mem;
253 
254 	mem = kmalloc(info->mmio_size, GFP_KERNEL);
255 	if (!mem) {
256 		kfree(path);
257 		kfree(firmware->cfg_space);
258 		return -ENOMEM;
259 	}
260 
261 	firmware->mmio = mem;
262 
263 	mmio = pci_iomap(pdev, info->mmio_bar, info->mmio_size);
264 	if (!mmio) {
265 		kfree(path);
266 		kfree(firmware->cfg_space);
267 		kfree(firmware->mmio);
268 		return -EINVAL;
269 	}
270 
271 	if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv))
272 		bdw_forcewake_get(mmio);
273 
274 	sprintf(path, "%s/vid_0x%04x_did_0x%04x_rid_0x%04x.golden_hw_state",
275 		 GVT_FIRMWARE_PATH, pdev->vendor, pdev->device,
276 		 pdev->revision);
277 
278 	gvt_dbg_core("request hw state firmware %s...\n", path);
279 
280 	ret = request_firmware(&fw, path, &dev_priv->drm.pdev->dev);
281 	kfree(path);
282 
283 	if (ret)
284 		goto expose_firmware;
285 
286 	gvt_dbg_core("success.\n");
287 
288 	ret = verify_firmware(gvt, fw);
289 	if (ret)
290 		goto out_free_fw;
291 
292 	gvt_dbg_core("verified.\n");
293 
294 	h = (struct gvt_firmware_header *)fw->data;
295 
296 	memcpy(firmware->cfg_space, fw->data + h->cfg_space_offset,
297 	       h->cfg_space_size);
298 	memcpy(firmware->mmio, fw->data + h->mmio_offset,
299 	       h->mmio_size);
300 
301 	release_firmware(fw);
302 	firmware->firmware_loaded = true;
303 	pci_iounmap(pdev, mmio);
304 	return 0;
305 
306 out_free_fw:
307 	release_firmware(fw);
308 expose_firmware:
309 	expose_firmware_sysfs(gvt, mmio);
310 	pci_iounmap(pdev, mmio);
311 	return 0;
312 }
313