Exemplo n.º 1
0
/* Get pm1x_cnt and pm1x_evt information for ACPI sleep */
static void __init
acpi_fadt_parse_sleep_info(struct acpi_table_fadt *fadt)
{
	struct acpi_table_facs *facs = NULL;
	uint64_t facs_pa;

	acpi_fadt_copy_address(pm1a_cnt, pm1a_control, pm1_control);
	acpi_fadt_copy_address(pm1b_cnt, pm1b_control, pm1_control);
	acpi_fadt_copy_address(pm1a_evt, pm1a_event, pm1_event);
	acpi_fadt_copy_address(pm1b_evt, pm1b_event, pm1_event);

	printk(KERN_INFO PREFIX
	       "ACPI SLEEP INFO: pm1x_cnt[%"PRIx64",%"PRIx64"], "
	       "pm1x_evt[%"PRIx64",%"PRIx64"]\n",
	       acpi_sinfo.pm1a_cnt_blk.address,
	       acpi_sinfo.pm1b_cnt_blk.address,
	       acpi_sinfo.pm1a_evt_blk.address,
	       acpi_sinfo.pm1b_evt_blk.address);

	/* Now FACS... */
	if (fadt->header.revision >= FADT2_REVISION_ID)
		facs_pa = fadt->Xfacs;
	else
		facs_pa = (uint64_t)fadt->facs;

	facs = (struct acpi_table_facs *)
		__acpi_map_table(facs_pa, sizeof(struct acpi_table_facs));
	if (!facs)
		goto bad;

	if (strncmp(facs->signature, "FACS", 4)) {
		printk(KERN_ERR PREFIX "Invalid FACS signature %.4s\n",
			facs->signature);
		goto bad;
	}

	if (facs->length < 24) {
		printk(KERN_ERR PREFIX "Invalid FACS table length: 0x%x",
			facs->length);
		goto bad;
	}

	if (facs->length < 64)
		printk(KERN_WARNING PREFIX
			"FACS is shorter than ACPI spec allow: 0x%x",
			facs->length);

	acpi_sinfo.wakeup_vector = facs_pa + 
		offsetof(struct acpi_table_facs, firmware_waking_vector);
	acpi_sinfo.vector_width = 32;

	printk(KERN_INFO PREFIX
	       "                 wakeup_vec[%"PRIx64"], vec_size[%x]\n",
	       acpi_sinfo.wakeup_vector, acpi_sinfo.vector_width);
	return;
bad:
	memset(&acpi_sinfo, 0, sizeof(acpi_sinfo));
}
Exemplo n.º 2
0
/* Get pm1x_cnt and pm1x_evt information for ACPI sleep */
static void __init
acpi_fadt_parse_sleep_info(struct acpi_table_fadt *fadt)
{
	struct acpi_table_facs *facs = NULL;
	uint64_t facs_pa;

	if (fadt->header.revision >= 5 &&
	    fadt->header.length >= ACPI_FADT_V5_SIZE) {
		acpi_sinfo.sleep_control = fadt->sleep_control;
		acpi_sinfo.sleep_status = fadt->sleep_status;

		printk(KERN_INFO PREFIX
		       "v5 SLEEP INFO: control[%d:%"PRIx64"],"
		       " status[%d:%"PRIx64"]\n",
		       acpi_sinfo.sleep_control.space_id,
		       acpi_sinfo.sleep_control.address,
		       acpi_sinfo.sleep_status.space_id,
		       acpi_sinfo.sleep_status.address);

		if ((fadt->sleep_control.address &&
		     (fadt->sleep_control.bit_offset ||
		      fadt->sleep_control.bit_width !=
		      fadt->sleep_control.access_width * 8)) ||
		    (fadt->sleep_status.address &&
		     (fadt->sleep_status.bit_offset ||
		      fadt->sleep_status.bit_width !=
		      fadt->sleep_status.access_width * 8))) {
			printk(KERN_WARNING PREFIX
			       "Invalid sleep control/status register data:"
			       " %#x:%#x:%#x %#x:%#x:%#x\n",
			       fadt->sleep_control.bit_offset,
			       fadt->sleep_control.bit_width,
			       fadt->sleep_control.access_width,
			       fadt->sleep_status.bit_offset,
			       fadt->sleep_status.bit_width,
			       fadt->sleep_status.access_width);
			fadt->sleep_control.address = 0;
			fadt->sleep_status.address = 0;
		}
	}

	if (fadt->flags & ACPI_FADT_HW_REDUCED)
		goto bad;

	acpi_fadt_copy_address(pm1a_cnt, pm1a_control, pm1_control);
	acpi_fadt_copy_address(pm1b_cnt, pm1b_control, pm1_control);
	acpi_fadt_copy_address(pm1a_evt, pm1a_event, pm1_event);
	acpi_fadt_copy_address(pm1b_evt, pm1b_event, pm1_event);

	printk(KERN_INFO PREFIX
	       "SLEEP INFO: pm1x_cnt[%"PRIx64",%"PRIx64"], "
	       "pm1x_evt[%"PRIx64",%"PRIx64"]\n",
	       acpi_sinfo.pm1a_cnt_blk.address,
	       acpi_sinfo.pm1b_cnt_blk.address,
	       acpi_sinfo.pm1a_evt_blk.address,
	       acpi_sinfo.pm1b_evt_blk.address);

	/* Now FACS... */
	facs_pa = ((fadt->header.revision >= FADT2_REVISION_ID)
		   ? fadt->Xfacs : (uint64_t)fadt->facs);
	if (fadt->facs && ((uint64_t)fadt->facs != facs_pa)) {
		printk(KERN_WARNING PREFIX
		       "32/64X FACS address mismatch in FADT - "
		       "%08x/%016"PRIx64", using 32\n",
		       fadt->facs, facs_pa);
		facs_pa = (uint64_t)fadt->facs;
	}
	if (!facs_pa)
		goto bad;

	facs = (struct acpi_table_facs *)
		__acpi_map_table(facs_pa, sizeof(struct acpi_table_facs));
	if (!facs)
		goto bad;

	if (strncmp(facs->signature, "FACS", 4)) {
		printk(KERN_ERR PREFIX "Invalid FACS signature %.4s\n",
			facs->signature);
		goto bad;
	}

	if (facs->length < 24) {
		printk(KERN_ERR PREFIX "Invalid FACS table length: %#x",
			facs->length);
		goto bad;
	}

	if (facs->length < 64)
		printk(KERN_WARNING PREFIX
			"FACS is shorter than ACPI spec allow: %#x",
			facs->length);

	acpi_sinfo.wakeup_vector = facs_pa + 
		offsetof(struct acpi_table_facs, firmware_waking_vector);
	acpi_sinfo.vector_width = 32;

	printk(KERN_INFO PREFIX
	       "            wakeup_vec[%"PRIx64"], vec_size[%x]\n",
	       acpi_sinfo.wakeup_vector, acpi_sinfo.vector_width);
	return;
bad:
	memset(&acpi_sinfo, 0,
	       offsetof(struct acpi_sleep_info, sleep_control));
	memset(&acpi_sinfo.sleep_status + 1, 0,
	       (long)(&acpi_sinfo + 1) - (long)(&acpi_sinfo.sleep_status + 1));
}