Exemple #1
0
static void
nouveau_bios_shadow_acpi(struct nouveau_bios *bios)
{
	struct pci_dev *pdev = nv_device(bios)->pdev;
	int ret, cnt, i;

	if (!nouveau_acpi_rom_supported(pdev)) {
		bios->data = NULL;
		return;
	}

	bios->size = 0;
	bios->data = kmalloc(4096, GFP_KERNEL);
	if (bios->data) {
		if (nouveau_acpi_get_bios_chunk(bios->data, 0, 4096) == 4096)
			bios->size = bios->data[2] * 512;
		kfree(bios->data);
	}

	if (!bios->size)
		return;

	bios->data = kmalloc(bios->size, GFP_KERNEL);
	if (bios->data) {
		/* disobey the acpi spec - much faster on at least w530 ... */
		ret = nouveau_acpi_get_bios_chunk(bios->data, 0, bios->size);
		if (ret != bios->size ||
		    nvbios_checksum(bios->data, bios->size)) {
			/* ... that didn't work, ok, i'll be good now */
			for (i = 0; i < bios->size; i += cnt) {
				cnt = min((bios->size - i), (u32)4096);
				ret = nouveau_acpi_get_bios_chunk(bios->data, i, cnt);
				if (ret != cnt)
					break;
			}
		}
	}
}
Exemple #2
0
/* This version of the shadow function disobeys the ACPI spec and tries
 * to fetch in units of more than 4KiB at a time.  This is a LOT faster
 * on some systems, such as Lenovo W530.
 */
static u32
acpi_read_fast(void *data, u32 offset, u32 length, struct nvkm_bios *bios)
{
	u32 limit = (offset + length + 0xfff) & ~0xfff;
	u32 start = offset & ~0x00000fff;
	u32 fetch = limit - start;

	if (nvbios_extend(bios, limit) > 0) {
		int ret = nouveau_acpi_get_bios_chunk(bios->data, start, fetch);
		if (ret == fetch)
			return fetch;
	}

	return 0;
}
Exemple #3
0
/* Other systems, such as the one in fdo#55948, will report a success
 * but only return 4KiB of data.  The common bios fetching logic will
 * detect an invalid image, and fall back to this version of the read
 * function.
 */
static u32
acpi_read_slow(void *data, u32 offset, u32 length, struct nvkm_bios *bios)
{
	u32 limit = (offset + length + 0xfff) & ~0xfff;
	u32 start = offset & ~0xfff;
	u32 fetch = 0;

	if (nvbios_extend(bios, limit) > 0) {
		while (start + fetch < limit) {
			int ret = nouveau_acpi_get_bios_chunk(bios->data,
							      start + fetch,
							      0x1000);
			if (ret != 0x1000)
				break;
			fetch += 0x1000;
		}
	}

	return fetch;
}