Commit b950c8c5 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/bios: move ACPI _ROM handling



Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 2dd4d163
Loading
Loading
Loading
Loading
+0 −54
Original line number Diff line number Diff line
@@ -49,7 +49,6 @@ static struct nouveau_dsm_priv {
	bool optimus_flags_detected;
	bool optimus_skip_dsm;
	acpi_handle dhandle;
	acpi_handle rom_handle;
} nouveau_dsm_priv;

bool nouveau_is_optimus(void) {
@@ -385,59 +384,6 @@ void nouveau_unregister_dsm_handler(void) {}
void nouveau_switcheroo_optimus_dsm(void) {}
#endif

/* retrieve the ROM in 4k blocks */
static int nouveau_rom_call(acpi_handle rom_handle, uint8_t *bios,
			    int offset, int len)
{
	acpi_status status;
	union acpi_object rom_arg_elements[2], *obj;
	struct acpi_object_list rom_arg;
	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};

	rom_arg.count = 2;
	rom_arg.pointer = &rom_arg_elements[0];

	rom_arg_elements[0].type = ACPI_TYPE_INTEGER;
	rom_arg_elements[0].integer.value = offset;

	rom_arg_elements[1].type = ACPI_TYPE_INTEGER;
	rom_arg_elements[1].integer.value = len;

	status = acpi_evaluate_object(rom_handle, NULL, &rom_arg, &buffer);
	if (ACPI_FAILURE(status)) {
		pr_info("failed to evaluate ROM got %s\n",
			acpi_format_exception(status));
		return -ENODEV;
	}
	obj = (union acpi_object *)buffer.pointer;
	len = min(len, (int)obj->buffer.length);
	memcpy(bios+offset, obj->buffer.pointer, len);
	kfree(buffer.pointer);
	return len;
}

bool nouveau_acpi_rom_supported(struct device *dev)
{
	acpi_status status;
	acpi_handle dhandle, rom_handle;

	dhandle = ACPI_HANDLE(dev);
	if (!dhandle)
		return false;

	status = acpi_get_handle(dhandle, "_ROM", &rom_handle);
	if (ACPI_FAILURE(status))
		return false;

	nouveau_dsm_priv.rom_handle = rom_handle;
	return true;
}

int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len)
{
	return nouveau_rom_call(nouveau_dsm_priv.rom_handle, bios, offset, len);
}

void *
nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector)
{
+0 −4
Original line number Diff line number Diff line
@@ -10,8 +10,6 @@ bool nouveau_is_v1_dsm(void);
void nouveau_register_dsm_handler(void);
void nouveau_unregister_dsm_handler(void);
void nouveau_switcheroo_optimus_dsm(void);
int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len);
bool nouveau_acpi_rom_supported(struct device *);
void *nouveau_acpi_edid(struct drm_device *, struct drm_connector *);
#else
static inline bool nouveau_is_optimus(void) { return false; };
@@ -19,8 +17,6 @@ static inline bool nouveau_is_v1_dsm(void) { return false; };
static inline void nouveau_register_dsm_handler(void) {}
static inline void nouveau_unregister_dsm_handler(void) {}
static inline void nouveau_switcheroo_optimus_dsm(void) {}
static inline bool nouveau_acpi_rom_supported(struct device *dev) { return false; }
static inline int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) { return -EINVAL; }
static inline void *nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) { return NULL; }
#endif

+47 −18
Original line number Diff line number Diff line
@@ -22,22 +22,39 @@
 */
#include "priv.h"

#if defined(CONFIG_ACPI) && defined(CONFIG_X86)
int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len);
bool nouveau_acpi_rom_supported(struct device *);
#else
static inline bool
nouveau_acpi_rom_supported(struct device *dev)
static int
acpi_read_bios(acpi_handle rom_handle, u8 *bios, u32 offset, u32 length)
{
	return false;
}
#if defined(CONFIG_ACPI) && defined(CONFIG_X86)
	acpi_status status;
	union acpi_object rom_arg_elements[2], *obj;
	struct acpi_object_list rom_arg;
	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};

static inline int
nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len)
{
	return -EINVAL;
	rom_arg.count = 2;
	rom_arg.pointer = &rom_arg_elements[0];

	rom_arg_elements[0].type = ACPI_TYPE_INTEGER;
	rom_arg_elements[0].integer.value = offset;

	rom_arg_elements[1].type = ACPI_TYPE_INTEGER;
	rom_arg_elements[1].integer.value = length;

	status = acpi_evaluate_object(rom_handle, NULL, &rom_arg, &buffer);
	if (ACPI_FAILURE(status)) {
		pr_info("failed to evaluate ROM got %s\n",
			acpi_format_exception(status));
		return -ENODEV;
	}
	obj = (union acpi_object *)buffer.pointer;
	length = min(length, obj->buffer.length);
	memcpy(bios+offset, obj->buffer.pointer, length);
	kfree(buffer.pointer);
	return length;
#else
	return -EINVAL;
#endif
}

/* 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
@@ -51,7 +68,7 @@ acpi_read_fast(void *data, u32 offset, u32 length, struct nvkm_bios *bios)
	u32 fetch = limit - start;

	if (nvbios_extend(bios, limit) >= 0) {
		int ret = nouveau_acpi_get_bios_chunk(bios->data, start, fetch);
		int ret = acpi_read_bios(data, bios->data, start, fetch);
		if (ret == fetch)
			return fetch;
	}
@@ -73,9 +90,8 @@ acpi_read_slow(void *data, u32 offset, u32 length, struct nvkm_bios *bios)

	if (nvbios_extend(bios, limit) >= 0) {
		while (start + fetch < limit) {
			int ret = nouveau_acpi_get_bios_chunk(bios->data,
							      start + fetch,
							      0x1000);
			int ret = acpi_read_bios(data, bios->data,
						 start + fetch, 0x1000);
			if (ret != 0x1000)
				break;
			fetch += 0x1000;
@@ -88,9 +104,22 @@ acpi_read_slow(void *data, u32 offset, u32 length, struct nvkm_bios *bios)
static void *
acpi_init(struct nvkm_bios *bios, const char *name)
{
	if (!nouveau_acpi_rom_supported(bios->subdev.device->dev))
#if defined(CONFIG_ACPI) && defined(CONFIG_X86)
	acpi_status status;
	acpi_handle dhandle, rom_handle;

	dhandle = ACPI_HANDLE(bios->subdev.device->dev);
	if (!dhandle)
		return ERR_PTR(-ENODEV);

	status = acpi_get_handle(dhandle, "_ROM", &rom_handle);
	if (ACPI_FAILURE(status))
		return ERR_PTR(-ENODEV);
	return NULL;

	return rom_handle;
#else
	return ERR_PTR(-ENODEV);
#endif
}

const struct nvbios_source