static void rtas_flash_firmware(int reboot_type)
{
    unsigned long image_size;
    struct flash_block_list *f, *next, *flist;
    unsigned long rtas_block_list;
    int i, status, update_token;

    if (rtas_firmware_flash_list == NULL)
        return;		/* nothing to do */

    if (reboot_type != SYS_RESTART) {
        printk(KERN_ALERT "FLASH: firmware flash requires a reboot\n");
        printk(KERN_ALERT "FLASH: the firmware image will NOT be flashed\n");
        return;
    }

    update_token = rtas_token("ibm,update-flash-64-and-reboot");
    if (update_token == RTAS_UNKNOWN_SERVICE) {
        printk(KERN_ALERT "FLASH: ibm,update-flash-64-and-reboot "
               "is not available -- not a service partition?\n");
        printk(KERN_ALERT "FLASH: firmware will not be flashed\n");
        return;
    }

    /*
     * Just before starting the firmware flash, cancel the event scan work
     * to avoid any soft lockup issues.
     */
    rtas_cancel_event_scan();

    /*
     * NOTE: the "first" block must be under 4GB, so we create
     * an entry with no data blocks in the reserved buffer in
     * the kernel data segment.
     */
    spin_lock(&rtas_data_buf_lock);
    flist = (struct flash_block_list *)&rtas_data_buf[0];
    flist->num_blocks = 0;
    flist->next = rtas_firmware_flash_list;
    rtas_block_list = virt_to_abs(flist);
    if (rtas_block_list >= 4UL*1024*1024*1024) {
        printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n");
        spin_unlock(&rtas_data_buf_lock);
        return;
    }

    printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n");
    /* Update the block_list in place. */
    rtas_firmware_flash_list = NULL; /* too hard to backout on error */
    image_size = 0;
    for (f = flist; f; f = next) {
        /* Translate data addrs to absolute */
        for (i = 0; i < f->num_blocks; i++) {
            f->blocks[i].data = (char *)virt_to_abs(f->blocks[i].data);
            image_size += f->blocks[i].length;
        }
        next = f->next;
        /* Don't translate NULL pointer for last entry */
        if (f->next)
            f->next = (struct flash_block_list *)virt_to_abs(f->next);
        else
            f->next = NULL;
        /* make num_blocks into the version/length field */
        f->num_blocks = (FLASH_BLOCK_LIST_VERSION << 56) | ((f->num_blocks+1)*16);
    }

    printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size);
    printk(KERN_ALERT "FLASH: performing flash and reboot\n");
    rtas_progress("Flashing        \n", 0x0);
    rtas_progress("Please Wait...  ", 0x0);
    printk(KERN_ALERT "FLASH: this will take several minutes.  Do not power off!\n");
    status = rtas_call(update_token, 1, 1, NULL, rtas_block_list);
    switch (status) {	/* should only get "bad" status */
    case 0:
        printk(KERN_ALERT "FLASH: success\n");
        break;
    case -1:
        printk(KERN_ALERT "FLASH: hardware error.  Firmware may not be not flashed\n");
        break;
    case -3:
        printk(KERN_ALERT "FLASH: image is corrupt or not correct for this platform.  Firmware not flashed\n");
        break;
    case -4:
        printk(KERN_ALERT "FLASH: flash failed when partially complete.  System may not reboot\n");
        break;
    default:
        printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status);
        break;
    }
    spin_unlock(&rtas_data_buf_lock);
}
static int __init rtas_flash_init(void)
{
    int rc;

    if (rtas_token("ibm,update-flash-64-and-reboot") ==
            RTAS_UNKNOWN_SERVICE) {
        printk(KERN_ERR "rtas_flash: no firmware flash support\n");
        return 1;
    }

    firmware_flash_pde = create_flash_pde("powerpc/rtas/"
                                          FIRMWARE_FLASH_NAME,
                                          &rtas_flash_operations);
    if (firmware_flash_pde == NULL) {
        rc = -ENOMEM;
        goto cleanup;
    }

    rc = initialize_flash_pde_data("ibm,update-flash-64-and-reboot",
                                   sizeof(struct rtas_update_flash_t),
                                   firmware_flash_pde);
    if (rc != 0)
        goto cleanup;

    firmware_update_pde = create_flash_pde("powerpc/rtas/"
                                           FIRMWARE_UPDATE_NAME,
                                           &rtas_flash_operations);
    if (firmware_update_pde == NULL) {
        rc = -ENOMEM;
        goto cleanup;
    }

    rc = initialize_flash_pde_data("ibm,update-flash-64-and-reboot",
                                   sizeof(struct rtas_update_flash_t),
                                   firmware_update_pde);
    if (rc != 0)
        goto cleanup;

    validate_pde = create_flash_pde("powerpc/rtas/" VALIDATE_FLASH_NAME,
                                    &validate_flash_operations);
    if (validate_pde == NULL) {
        rc = -ENOMEM;
        goto cleanup;
    }

    rc = initialize_flash_pde_data("ibm,validate-flash-image",
                                   sizeof(struct rtas_validate_flash_t),
                                   validate_pde);
    if (rc != 0)
        goto cleanup;

    manage_pde = create_flash_pde("powerpc/rtas/" MANAGE_FLASH_NAME,
                                  &manage_flash_operations);
    if (manage_pde == NULL) {
        rc = -ENOMEM;
        goto cleanup;
    }

    rc = initialize_flash_pde_data("ibm,manage-flash-image",
                                   sizeof(struct rtas_manage_flash_t),
                                   manage_pde);
    if (rc != 0)
        goto cleanup;

    rtas_flash_term_hook = rtas_flash_firmware;

    flash_block_cache = kmem_cache_create("rtas_flash_cache",
                                          RTAS_BLK_SIZE, RTAS_BLK_SIZE, 0,
                                          rtas_block_ctor);
    if (!flash_block_cache) {
        printk(KERN_ERR "%s: failed to create block cache\n",
               __func__);
        rc = -ENOMEM;
        goto cleanup;
    }
    return 0;

cleanup:
    remove_flash_pde(firmware_flash_pde);
    remove_flash_pde(firmware_update_pde);
    remove_flash_pde(validate_pde);
    remove_flash_pde(manage_pde);

    return rc;
}
Beispiel #3
0
int rtas_ibm_suspend_me(u64 handle, int *vasi_return)
{
	long state;
	long rc;
	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
	struct rtas_suspend_me_data data;
	DECLARE_COMPLETION_ONSTACK(done);
	cpumask_var_t offline_mask;
	int cpuret;

	if (!rtas_service_present("ibm,suspend-me"))
		return -ENOSYS;

	/* Make sure the state is valid */
	rc = plpar_hcall(H_VASI_STATE, retbuf, handle);

	state = retbuf[0];

	if (rc) {
		printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned %ld\n",rc);
		return rc;
	} else if (state == H_VASI_ENABLED) {
		*vasi_return = RTAS_NOT_SUSPENDABLE;
		return 0;
	} else if (state != H_VASI_SUSPENDING) {
		printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned state %ld\n",
		       state);
		*vasi_return = -1;
		return 0;
	}

	if (!alloc_cpumask_var(&offline_mask, GFP_TEMPORARY))
		return -ENOMEM;

	atomic_set(&data.working, 0);
	atomic_set(&data.done, 0);
	atomic_set(&data.error, 0);
	data.token = rtas_token("ibm,suspend-me");
	data.complete = &done;

	/* All present CPUs must be online */
	cpumask_andnot(offline_mask, cpu_present_mask, cpu_online_mask);
	cpuret = rtas_online_cpus_mask(offline_mask);
	if (cpuret) {
		pr_err("%s: Could not bring present CPUs online.\n", __func__);
		atomic_set(&data.error, cpuret);
		goto out;
	}

	stop_topology_update();

	/* Call function on all CPUs.  One of us will make the
	 * rtas call
	 */
	if (on_each_cpu(rtas_percpu_suspend_me, &data, 0))
		atomic_set(&data.error, -EINVAL);

	wait_for_completion(&done);

	if (atomic_read(&data.error) != 0)
		printk(KERN_ERR "Error doing global join\n");

	start_topology_update();

	/* Take down CPUs not online prior to suspend */
	cpuret = rtas_offline_cpus_mask(offline_mask);
	if (cpuret)
		pr_warn("%s: Could not restore CPUs to offline state.\n",
				__func__);

out:
	free_cpumask_var(offline_mask);
	return atomic_read(&data.error);
}
Beispiel #4
0
struct device_node *dlpar_configure_connector(u32 drc_index)
{
	struct device_node *dn;
	struct device_node *first_dn = NULL;
	struct device_node *last_dn = NULL;
	struct property *property;
	struct property *last_property = NULL;
	struct cc_workarea *ccwa;
	int cc_token;
	int rc;

	cc_token = rtas_token("ibm,configure-connector");
	if (cc_token == RTAS_UNKNOWN_SERVICE)
		return NULL;

	spin_lock(&rtas_data_buf_lock);
	ccwa = (struct cc_workarea *)&rtas_data_buf[0];
	ccwa->drc_index = drc_index;
	ccwa->zero = 0;

	rc = rtas_call(cc_token, 2, 1, NULL, rtas_data_buf, NULL);
	while (rc) {
		switch (rc) {
		case NEXT_SIBLING:
			dn = dlpar_parse_cc_node(ccwa);
			if (!dn)
				goto cc_error;

			dn->parent = last_dn->parent;
			last_dn->sibling = dn;
			last_dn = dn;
			break;

		case NEXT_CHILD:
			dn = dlpar_parse_cc_node(ccwa);
			if (!dn)
				goto cc_error;

			if (!first_dn)
				first_dn = dn;
			else {
				dn->parent = last_dn;
				if (last_dn)
					last_dn->child = dn;
			}

			last_dn = dn;
			break;

		case NEXT_PROPERTY:
			property = dlpar_parse_cc_property(ccwa);
			if (!property)
				goto cc_error;

			if (!last_dn->properties)
				last_dn->properties = property;
			else
				last_property->next = property;

			last_property = property;
			break;

		case PREV_PARENT:
			last_dn = last_dn->parent;
			break;

		case CALL_AGAIN:
			break;

		case MORE_MEMORY:
		case ERR_CFG_USE:
		default:
			printk(KERN_ERR "Unexpected Error (%d) "
			       "returned from configure-connector\n", rc);
			goto cc_error;
		}

		rc = rtas_call(cc_token, 2, 1, NULL, rtas_data_buf, NULL);
	}

	spin_unlock(&rtas_data_buf_lock);
	return first_dn;

cc_error:
	if (first_dn)
		dlpar_free_cc_nodes(first_dn);
	spin_unlock(&rtas_data_buf_lock);
	return NULL;
}
/* Check for an eeh failure at the given token address.
 * The given value has been read and it should be 1's (0xff, 0xffff or
 * 0xffffffff).
 *
 * Probe to determine if an error actually occurred.  If not return val.
 * Otherwise panic.
 */
unsigned long eeh_check_failure(void *token, unsigned long val)
{
	unsigned long addr;
	struct pci_dev *dev;
	struct device_node *dn;
	unsigned long ret, rets[2];

	/* IO BAR access could get us here...or if we manually force EEH
	 * operation on even if the hardware won't support it.
	 */
	if (!eeh_implemented || ibm_read_slot_reset_state == RTAS_UNKNOWN_SERVICE)
		return val;

	/* Finding the phys addr + pci device is quite expensive.
	 * However, the RTAS call is MUCH slower.... :(
	 */
	addr = eeh_token_to_phys((unsigned long)token);
	dev = pci_find_dev_by_addr(addr);
	if (!dev) {
		printk("EEH: no pci dev found for addr=0x%lx\n", addr);
		return val;
	}
	dn = pci_device_to_OF_node(dev);
	if (!dn) {
		printk("EEH: no pci dn found for addr=0x%lx\n", addr);
		return val;
	}

	/* Access to IO BARs might get this far and still not want checking. */
	if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) || dn->eeh_mode & EEH_MODE_NOCHECK)
		return val;


	/* Now test for an EEH failure.  This is VERY expensive.
	 * Note that the eeh_config_addr may be a parent device
	 * in the case of a device behind a bridge, or it may be
	 * function zero of a multi-function device.
	 * In any case they must share a common PHB.
	 */
	if (dn->eeh_config_addr) {
		ret = rtas_call(ibm_read_slot_reset_state, 3, 3, rets,
				dn->eeh_config_addr, BUID_HI(dn->phb->buid), BUID_LO(dn->phb->buid));
		if (ret == 0 && rets[1] == 1 && rets[0] >= 2) {
			unsigned char   slot_err_buf[RTAS_ERROR_LOG_MAX];
			unsigned long   slot_err_ret;

			memset(slot_err_buf, 0, RTAS_ERROR_LOG_MAX);
			slot_err_ret = rtas_call(rtas_token("ibm,slot-error-detail"),
						 8, 1, dn->eeh_config_addr,
						 BUID_HI(dn->phb->buid), BUID_LO(dn->phb->buid),
						 NULL, 0, __pa(slot_err_buf), RTAS_ERROR_LOG_MAX,
						 2 /* Permanent Error */);
			if (slot_err_ret == 0)
				log_error(slot_err_buf, ERR_TYPE_RTAS_LOG, 1 /* Fatal */);

			panic("EEH:  MMIO failure (%ld) on device:\n  %s %s\n",
			      rets[0], dev->slot_name, dev->name);
		}
	}
	eeh_false_positives++;
	return val;	/* good case */

}
Beispiel #6
0
int rtas_service_present(const char *service)
{
	return rtas_token(service) != RTAS_UNKNOWN_SERVICE;
}
Beispiel #7
0
struct device_node *dlpar_configure_connector(__be32 drc_index,
					      struct device_node *parent)
{
	struct device_node *dn;
	struct device_node *first_dn = NULL;
	struct device_node *last_dn = NULL;
	struct property *property;
	struct property *last_property = NULL;
	struct cc_workarea *ccwa;
	char *data_buf;
	const char *parent_path = parent->full_name;
	int cc_token;
	int rc = -1;

	cc_token = rtas_token("ibm,configure-connector");
	if (cc_token == RTAS_UNKNOWN_SERVICE)
		return NULL;

	data_buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
	if (!data_buf)
		return NULL;

	ccwa = (struct cc_workarea *)&data_buf[0];
	ccwa->drc_index = drc_index;
	ccwa->zero = 0;

	do {
		/* Since we release the rtas_data_buf lock between configure
		 * connector calls we want to re-populate the rtas_data_buffer
		 * with the contents of the previous call.
		 */
		spin_lock(&rtas_data_buf_lock);

		memcpy(rtas_data_buf, data_buf, RTAS_DATA_BUF_SIZE);
		rc = rtas_call(cc_token, 2, 1, NULL, rtas_data_buf, NULL);
		memcpy(data_buf, rtas_data_buf, RTAS_DATA_BUF_SIZE);

		spin_unlock(&rtas_data_buf_lock);

		switch (rc) {
		case COMPLETE:
			break;

		case NEXT_SIBLING:
			dn = dlpar_parse_cc_node(ccwa, parent_path);
			if (!dn)
				goto cc_error;

			dn->parent = last_dn->parent;
			last_dn->sibling = dn;
			last_dn = dn;
			break;

		case NEXT_CHILD:
			if (first_dn)
				parent_path = last_dn->full_name;

			dn = dlpar_parse_cc_node(ccwa, parent_path);
			if (!dn)
				goto cc_error;

			if (!first_dn) {
				dn->parent = parent;
				first_dn = dn;
			} else {
				dn->parent = last_dn;
				if (last_dn)
					last_dn->child = dn;
			}

			last_dn = dn;
			break;

		case NEXT_PROPERTY:
			property = dlpar_parse_cc_property(ccwa);
			if (!property)
				goto cc_error;

			if (!last_dn->properties)
				last_dn->properties = property;
			else
				last_property->next = property;

			last_property = property;
			break;

		case PREV_PARENT:
			last_dn = last_dn->parent;
			parent_path = last_dn->parent->full_name;
			break;

		case CALL_AGAIN:
			break;

		case MORE_MEMORY:
		case ERR_CFG_USE:
		default:
			printk(KERN_ERR "Unexpected Error (%d) "
			       "returned from configure-connector\n", rc);
			goto cc_error;
		}
	} while (rc);

cc_error:
	kfree(data_buf);

	if (rc) {
		if (first_dn)
			dlpar_free_cc_nodes(first_dn);

		return NULL;
	}

	return first_dn;
}
Beispiel #8
0
/* Call this when done with the data returned by FWNMI_get_errinfo.
 * It will release the saved data area for other CPUs in the
 * partition to receive FWNMI errors.
 */
static void fwnmi_release_errinfo(void)
{
	int ret = rtas_call(rtas_token("ibm,nmi-interlock"), 0, 1, NULL);
	if (ret != 0)
		printk(KERN_ERR "FWNMI: nmi-interlock failed: %d\n", ret);
}
Beispiel #9
0
static int rtasd(void *unused)
{
	unsigned int err_type;
	int cpu = 0;
	int event_scan = rtas_token("event-scan");
	cpumask_t all = CPU_MASK_ALL;
	int rc;

	daemonize("rtasd");

	if (event_scan == RTAS_UNKNOWN_SERVICE || get_eventscan_parms() == -1)
		goto error;

	rtas_log_buf = vmalloc(rtas_error_log_buffer_max*LOG_NUMBER);
	if (!rtas_log_buf) {
		printk(KERN_ERR "rtasd: no memory\n");
		goto error;
	}

	/* We can use rtas_log_buf now */
	no_more_logging = 0;

	printk(KERN_ERR "RTAS daemon started\n");

	DEBUG("will sleep for %d jiffies\n", (HZ*60/rtas_event_scan_rate) / 2);

	/* See if we have any error stored in NVRAM */
	memset(logdata, 0, rtas_error_log_max);

	rc = nvram_read_error_log(logdata, rtas_error_log_max, &err_type);
	if (!rc) {
		if (err_type != ERR_FLAG_ALREADY_LOGGED) {
			pSeries_log_error(logdata, err_type | ERR_FLAG_BOOT, 0);
		}
	}

	/* First pass. */
	lock_cpu_hotplug();
	for_each_online_cpu(cpu) {
		DEBUG("scheduling on %d\n", cpu);
		set_cpus_allowed(current, cpumask_of_cpu(cpu));
		DEBUG("watchdog scheduled on cpu %d\n", smp_processor_id());

		do_event_scan(event_scan);
		set_current_state(TASK_INTERRUPTIBLE);
		schedule_timeout(HZ);
	}
	unlock_cpu_hotplug();

	if (surveillance_timeout != -1) {
		DEBUG("enabling surveillance\n");
		enable_surveillance(surveillance_timeout);
		DEBUG("surveillance enabled\n");
	}

	lock_cpu_hotplug();
	cpu = first_cpu_const(mk_cpumask_const(cpu_online_map));
	for (;;) {
		set_cpus_allowed(current, cpumask_of_cpu(cpu));
		do_event_scan(event_scan);
		set_cpus_allowed(current, all);

		/* Drop hotplug lock, and sleep for a bit (at least
		 * one second since some machines have problems if we
		 * call event-scan too quickly). */
		unlock_cpu_hotplug();
		set_current_state(TASK_INTERRUPTIBLE);
		schedule_timeout((HZ*60/rtas_event_scan_rate) / 2);
		lock_cpu_hotplug();

		cpu = next_cpu_const(cpu, mk_cpumask_const(cpu_online_map));
		if (cpu == NR_CPUS)
			cpu = first_cpu_const(mk_cpumask_const(cpu_online_map));
	}

error:
	/* Should delete proc entries */
	return -EINVAL;
}
Beispiel #10
0
static int update_dt_node(__be32 phandle, s32 scope)
{
	struct update_props_workarea *upwa;
	struct device_node *dn;
	struct property *prop = NULL;
	int i, rc, rtas_rc;
	char *prop_data;
	char *rtas_buf;
	int update_properties_token;
	u32 nprops;
	u32 vd;

	update_properties_token = rtas_token("ibm,update-properties");
	if (update_properties_token == RTAS_UNKNOWN_SERVICE)
		return -EINVAL;

	rtas_buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
	if (!rtas_buf)
		return -ENOMEM;

	dn = of_find_node_by_phandle(be32_to_cpu(phandle));
	if (!dn) {
		kfree(rtas_buf);
		return -ENOENT;
	}

	upwa = (struct update_props_workarea *)&rtas_buf[0];
	upwa->phandle = phandle;

	do {
		rtas_rc = mobility_rtas_call(update_properties_token, rtas_buf,
					scope);
		if (rtas_rc < 0)
			break;

		prop_data = rtas_buf + sizeof(*upwa);
		nprops = be32_to_cpu(upwa->nprops);

		/* On the first call to ibm,update-properties for a node the
		 * the first property value descriptor contains an empty
		 * property name, the property value length encoded as u32,
		 * and the property value is the node path being updated.
		 */
		if (*prop_data == 0) {
			prop_data++;
			vd = be32_to_cpu(*(__be32 *)prop_data);
			prop_data += vd + sizeof(vd);
			nprops--;
		}

		for (i = 0; i < nprops; i++) {
			char *prop_name;

			prop_name = prop_data;
			prop_data += strlen(prop_name) + 1;
			vd = be32_to_cpu(*(__be32 *)prop_data);
			prop_data += sizeof(vd);

			switch (vd) {
			case 0x00000000:
				/* name only property, nothing to do */
				break;

			case 0x80000000:
				prop = of_find_property(dn, prop_name, NULL);
				of_remove_property(dn, prop);
				prop = NULL;
				break;

			default:
				rc = update_dt_property(dn, &prop, prop_name,
							vd, prop_data);
				if (rc) {
					printk(KERN_ERR "Could not update %s"
					       " property\n", prop_name);
				}

				prop_data += vd;
			}
		}
	} while (rtas_rc == 1);

	of_node_put(dn);
	kfree(rtas_buf);
	return 0;
}
static int update_dt_node(u32 phandle)
{
	struct update_props_workarea *upwa;
	struct device_node *dn;
	struct property *prop = NULL;
	int i, rc;
	char *prop_data;
	char *rtas_buf;
	int update_properties_token;

	update_properties_token = rtas_token("ibm,update-properties");
	if (update_properties_token == RTAS_UNKNOWN_SERVICE)
		return -EINVAL;

	rtas_buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
	if (!rtas_buf)
		return -ENOMEM;

	dn = of_find_node_by_phandle(phandle);
	if (!dn) {
		kfree(rtas_buf);
		return -ENOENT;
	}

	upwa = (struct update_props_workarea *)&rtas_buf[0];
	upwa->phandle = phandle;

	do {
		rc = mobility_rtas_call(update_properties_token, rtas_buf);
		if (rc < 0)
			break;

		prop_data = rtas_buf + sizeof(*upwa);

		for (i = 0; i < upwa->nprops; i++) {
			char *prop_name;
			u32 vd;

			prop_name = prop_data + 1;
			prop_data += strlen(prop_name) + 1;
			vd = *prop_data++;

			switch (vd) {
			case 0x00000000:
				/* name only property, nothing to do */
				break;

			case 0x80000000:
				prop = of_find_property(dn, prop_name, NULL);
				prom_remove_property(dn, prop);
				prop = NULL;
				break;

			default:
				rc = update_dt_property(dn, &prop, prop_name,
							vd, prop_data);
				if (rc) {
					printk(KERN_ERR "Could not update %s"
					       " property\n", prop_name);
				}

				prop_data += vd;
			}
		}
	} while (rc == 1);

	of_node_put(dn);
	kfree(rtas_buf);
	return 0;
}
Beispiel #12
0
void
xics_init_IRQ( void )
{
	int i;
	unsigned long intr_size = 0;
	struct device_node *np;
	uint *ireg, ilen, indx=0;

	ppc64_boot_msg(0x20, "XICS Init");

	ibm_get_xive = rtas_token("ibm,get-xive");
	ibm_set_xive = rtas_token("ibm,set-xive");
	ibm_int_on  = rtas_token("ibm,int-on");
	ibm_int_off = rtas_token("ibm,int-off");

	np = find_type_devices("PowerPC-External-Interrupt-Presentation");
	if (!np) {
		printk(KERN_WARNING "Can't find Interrupt Presentation\n");
		udbg_printf("Can't find Interrupt Presentation\n");
		while (1);
	}
nextnode:
	ireg = (uint *)get_property(np, "ibm,interrupt-server-ranges", 0);
	if (ireg) {
		/*
		 * set node starting index for this node
		 */
		indx = *ireg;
	}

	ireg = (uint *)get_property(np, "reg", &ilen);
	if (!ireg) {
		printk(KERN_WARNING "Can't find Interrupt Reg Property\n");
		udbg_printf("Can't find Interrupt Reg Property\n");
		while (1);
	}
	
	while (ilen) {
		inodes[indx].addr = (unsigned long long)*ireg++ << 32;
		ilen -= sizeof(uint);
		inodes[indx].addr |= *ireg++;
		ilen -= sizeof(uint);
		inodes[indx].size = (unsigned long long)*ireg++ << 32;
		ilen -= sizeof(uint);
		inodes[indx].size |= *ireg++;
		ilen -= sizeof(uint);
		indx++;
		if (indx >= NR_CPUS) break;
	}

	np = np->next;
	if ((indx < NR_CPUS) && np) goto nextnode;

	/* Find the server numbers for the boot cpu. */
	for (np = find_type_devices("cpu"); np; np = np->next) {
		ireg = (uint *)get_property(np, "reg", &ilen);
		if (ireg && ireg[0] == hard_smp_processor_id()) {
			ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
			i = ilen / sizeof(int);
			if (ireg && i > 0) {
				default_server = ireg[0];
				default_distrib_server = ireg[i-1]; /* take last element */
			}
			break;
		}
	}

	intr_base = inodes[0].addr;
	intr_size = (ulong)inodes[0].size;

	np = find_type_devices("interrupt-controller");
	if (!np) {
		printk(KERN_WARNING "xics:  no ISA Interrupt Controller\n");
		xics_irq_8259_cascade_real = -1;
		xics_irq_8259_cascade = -1;
	} else {
		ireg = (uint *) get_property(np, "interrupts", 0);
		if (!ireg) {
			printk(KERN_WARNING "Can't find ISA Interrupts Property\n");
			udbg_printf("Can't find ISA Interrupts Property\n");
			while (1);
		}
		xics_irq_8259_cascade_real = *ireg;
		xics_irq_8259_cascade = virt_irq_create_mapping(xics_irq_8259_cascade_real);
	}

	if (systemcfg->platform == PLATFORM_PSERIES) {
#ifdef CONFIG_SMP
		for (i = 0; i < systemcfg->processorCount; ++i) {
			xics_info.per_cpu[i] =
			  __ioremap((ulong)inodes[get_hard_smp_processor_id(i)].addr, 
				  (ulong)inodes[get_hard_smp_processor_id(i)].size, _PAGE_NO_CACHE);
		}
#else
		xics_info.per_cpu[0] = __ioremap((ulong)intr_base, intr_size, _PAGE_NO_CACHE);
#endif /* CONFIG_SMP */
#ifdef CONFIG_PPC_PSERIES
	/* actually iSeries does not use any of xics...but it has link dependencies
	 * for now, except this new one...
	 */
	} else if (systemcfg->platform == PLATFORM_PSERIES_LPAR) {
		ops = &pSeriesLP_ops;
#endif
	}

	xics_8259_pic.enable = i8259_pic.enable;
	xics_8259_pic.disable = i8259_pic.disable;
	for (i = 0; i < 16; ++i)
		irq_desc[i].handler = &xics_8259_pic;
	for (; i < NR_IRQS; ++i)
		irq_desc[i].handler = &xics_pic;

	ops->cppr_info(0, 0xff);
	iosync();
	if (xics_irq_8259_cascade != -1) {
		if (request_irq(xics_irq_8259_cascade + XICS_IRQ_OFFSET, no_action,
				0, "8259 cascade", 0))
			printk(KERN_ERR "xics_init_IRQ: couldn't get 8259 cascade\n");
		i8259_init();
	}

#ifdef CONFIG_SMP
	real_irq_to_virt_map[XICS_IPI] = virt_irq_to_real_map[XICS_IPI] = XICS_IPI;
	request_irq(XICS_IPI + XICS_IRQ_OFFSET, xics_ipi_action, 0, "IPI", 0);
	irq_desc[XICS_IPI+XICS_IRQ_OFFSET].status |= IRQ_PER_CPU;
#endif
	ppc64_boot_msg(0x21, "XICS Done");
}
Beispiel #13
0
static int rtasd(void *unused)
{
	int cpu = 0;
	int error;
	int first_pass = 1;
	int event_scan = rtas_token("event-scan");

	if (event_scan == RTAS_UNKNOWN_SERVICE || get_eventscan_parms() == -1)
		goto error;

	rtas_log_buf = vmalloc(rtas_error_log_max*LOG_NUMBER);
	if (!rtas_log_buf) {
		printk(KERN_ERR "rtasd: no memory\n");
		goto error;
	}

	DEBUG("will sleep for %d jiffies\n", (HZ*60/rtas_event_scan_rate) / 2);

	daemonize("rtasd");

#if 0
	/* Rusty unreal time task */
	current->policy = SCHED_FIFO;
	current->nice = sys_sched_get_priority_max(SCHED_FIFO) + 1;
#endif

repeat:
	for (cpu = 0; cpu < NR_CPUS; cpu++) {
		if (!cpu_online(cpu))
			continue;

		DEBUG("scheduling on %d\n", cpu);
		set_cpus_allowed(current, cpumask_of_cpu(cpu));
		DEBUG("watchdog scheduled on cpu %d\n", smp_processor_id());

		do {
			memset(logdata, 0, rtas_error_log_max);
			error = rtas_call(event_scan, 4, 1, NULL,
					EVENT_SCAN_ALL_EVENTS, 0,
					__pa(logdata), rtas_error_log_max);
			if (error == -1) {
				printk(KERN_ERR "event-scan failed\n");
				break;
			}

			if (error == 0)
				log_rtas(logdata);

		} while(error == 0);

		/*
		 * Check all cpus for pending events quickly, sleeping for
		 * at least one second since some machines have problems
		 * if we call event-scan too quickly
		 */
		set_current_state(TASK_INTERRUPTIBLE);
		schedule_timeout(first_pass ? HZ : (HZ*60/rtas_event_scan_rate) / 2);
	}

	if (first_pass && surveillance_requested) {
		DEBUG("enabling surveillance\n");
		if (enable_surveillance())
			goto error_vfree;
		DEBUG("surveillance enabled\n");
	}

	first_pass = 0;
	goto repeat;

error_vfree:
	vfree(rtas_log_buf);
error:
	/* Should delete proc entries */
	return -EINVAL;
}
Beispiel #14
0
/* Call this when done with the data returned by FWNMI_get_errinfo.
 * It will release the saved data area for other CPUs in the
 * partition to receive FWNMI errors.
 */
static void FWNMI_release_errinfo(void)
{
	unsigned long ret = rtas_call(rtas_token("ibm,nmi-interlock"), 0, 1, NULL);
	if (ret != 0)
		printk("FWNMI: nmi-interlock failed: %ld\n", ret);
}
Beispiel #15
0
static int rtasd(void *unused)
{
	int cpu = 0;
	int error;
	int first_pass = 1;
	int event_scan = rtas_token("event-scan");

	if (event_scan == RTAS_UNKNOWN_SERVICE || get_eventscan_parms() == -1)
		goto error;

	rtas_log_buf = vmalloc(rtas_error_log_max*LOG_NUMBER);
	if (!rtas_log_buf) {
		printk(KERN_ERR "rtasd: no memory\n");
		goto error;
	}

	DEBUG("will sleep for %d jiffies\n", (HZ*60/rtas_event_scan_rate) / 2);

	daemonize();
	sigfillset(&current->blocked);
	sprintf(current->comm, "rtasd");

	/* Rusty unreal time task */
	current->policy = SCHED_FIFO;
	current->nice = sys_sched_get_priority_max(SCHED_FIFO) + 1;

	cpu = 0;
	current->cpus_allowed = 1UL << cpu_logical_map(cpu);
	schedule();

	while(1) {
		do {
			memset(logdata, 0, rtas_error_log_max);
			error = rtas_call(event_scan, 4, 1, NULL,
					EVENT_SCAN_ALL_EVENTS, 0,
					__pa(logdata), rtas_error_log_max);
			if (error == -1) {
				printk(KERN_ERR "event-scan failed\n");
				break;
			}

			if (error == 0)
				log_rtas(logdata);

		} while(error == 0);

		DEBUG("watchdog scheduled on cpu %d\n", smp_processor_id());

		cpu++;
		if (cpu >= smp_num_cpus) {

			if (first_pass && surveillance_requested) {
				DEBUG("enabling surveillance\n");
				if (enable_surveillance())
					goto error_vfree;
				DEBUG("surveillance enabled\n");
			}

			first_pass = 0;
			cpu = 0;
		}

		current->cpus_allowed = 1UL << cpu_logical_map(cpu);

		/* Check all cpus for pending events before sleeping*/
                set_current_state(TASK_INTERRUPTIBLE);
                schedule_timeout(first_pass ? HZ : (HZ*60/rtas_event_scan_rate) / 2);
	}

error_vfree:
	vfree(rtas_log_buf);
error:
	/* Should delete proc entries */
	return -EINVAL;
}
Beispiel #16
0
void rtas_power_off(void)
{
	int ret = rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1);
	printf("RTAS power-off returned %d\n", ret);
}
Beispiel #17
0
void rtas_progress(char *s, unsigned short hex)
{
	struct device_node *root;
	int width;
	const __be32 *p;
	char *os;
	static int display_character, set_indicator;
	static int display_width, display_lines, form_feed;
	static const int *row_width;
	static DEFINE_SPINLOCK(progress_lock);
	static int current_line;
	static int pending_newline = 0;  /* did last write end with unprinted newline? */

	if (!rtas.base)
		return;

	if (display_width == 0) {
		display_width = 0x10;
		if ((root = of_find_node_by_path("/rtas"))) {
			if ((p = of_get_property(root,
					"ibm,display-line-length", NULL)))
				display_width = be32_to_cpu(*p);
			if ((p = of_get_property(root,
					"ibm,form-feed", NULL)))
				form_feed = be32_to_cpu(*p);
			if ((p = of_get_property(root,
					"ibm,display-number-of-lines", NULL)))
				display_lines = be32_to_cpu(*p);
			row_width = of_get_property(root,
					"ibm,display-truncation-length", NULL);
			of_node_put(root);
		}
		display_character = rtas_token("display-character");
		set_indicator = rtas_token("set-indicator");
	}

	if (display_character == RTAS_UNKNOWN_SERVICE) {
		/* use hex display if available */
		if (set_indicator != RTAS_UNKNOWN_SERVICE)
			rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex);
		return;
	}

	spin_lock(&progress_lock);

	/*
	 * Last write ended with newline, but we didn't print it since
	 * it would just clear the bottom line of output. Print it now
	 * instead.
	 *
	 * If no newline is pending and form feed is supported, clear the
	 * display with a form feed; otherwise, print a CR to start output
	 * at the beginning of the line.
	 */
	if (pending_newline) {
		rtas_call(display_character, 1, 1, NULL, '\r');
		rtas_call(display_character, 1, 1, NULL, '\n');
		pending_newline = 0;
	} else {
		current_line = 0;
		if (form_feed)
			rtas_call(display_character, 1, 1, NULL,
				  (char)form_feed);
		else
			rtas_call(display_character, 1, 1, NULL, '\r');
	}
 
	if (row_width)
		width = row_width[current_line];
	else
		width = display_width;
	os = s;
	while (*os) {
		if (*os == '\n' || *os == '\r') {
			/* If newline is the last character, save it
			 * until next call to avoid bumping up the
			 * display output.
			 */
			if (*os == '\n' && !os[1]) {
				pending_newline = 1;
				current_line++;
				if (current_line > display_lines-1)
					current_line = display_lines-1;
				spin_unlock(&progress_lock);
				return;
			}
 
			/* RTAS wants CR-LF, not just LF */
 
			if (*os == '\n') {
				rtas_call(display_character, 1, 1, NULL, '\r');
				rtas_call(display_character, 1, 1, NULL, '\n');
			} else {
				/* CR might be used to re-draw a line, so we'll
				 * leave it alone and not add LF.
				 */
				rtas_call(display_character, 1, 1, NULL, *os);
			}
 
			if (row_width)
				width = row_width[current_line];
			else
				width = display_width;
		} else {
			width--;
			rtas_call(display_character, 1, 1, NULL, *os);
		}
 
		os++;
 
		/* if we overwrite the screen length */
		if (width <= 0)
			while ((*os != 0) && (*os != '\n') && (*os != '\r'))
				os++;
	}
 
	spin_unlock(&progress_lock);
}
Beispiel #18
0
static void
rtas_flash_firmware(void)
{
	unsigned long image_size;
	struct flash_block_list *f, *next, *flist;
	unsigned long rtas_block_list;
	int i, status, update_token;

	update_token = rtas_token("ibm,update-flash-64-and-reboot");
	if (update_token == RTAS_UNKNOWN_SERVICE) {
		printk(KERN_ALERT "FLASH: ibm,update-flash-64-and-reboot is not available -- not a service partition?\n");
		printk(KERN_ALERT "FLASH: firmware will not be flashed\n");
		return;
	}

	/* NOTE: the "first" block list is a global var with no data
	 * blocks in the kernel data segment.  We do this because
	 * we want to ensure this block_list addr is under 4GB.
	 */
	rtas_firmware_flash_list.num_blocks = 0;
	flist = (struct flash_block_list *)&rtas_firmware_flash_list;
	rtas_block_list = virt_to_abs(flist);
	if (rtas_block_list >= 4UL*1024*1024*1024) {
		printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n");
		return;
	}

	printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n");
	/* Update the block_list in place. */
	image_size = 0;
	for (f = flist; f; f = next) {
		/* Translate data addrs to absolute */
		for (i = 0; i < f->num_blocks; i++) {
			f->blocks[i].data = (char *)virt_to_abs(f->blocks[i].data);
			image_size += f->blocks[i].length;
		}
		next = f->next;
		/* Don't translate NULL pointer for last entry */
		if (f->next)
			f->next = (struct flash_block_list *)virt_to_abs(f->next);
		else
			f->next = NULL;
		/* make num_blocks into the version/length field */
		f->num_blocks = (FLASH_BLOCK_LIST_VERSION << 56) | ((f->num_blocks+1)*16);
	}

	printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size);
	printk(KERN_ALERT "FLASH: performing flash and reboot\n");
	ppc_md.progress("Flashing        \n", 0x0);
	ppc_md.progress("Please Wait...  ", 0x0);
	printk(KERN_ALERT "FLASH: this will take several minutes.  Do not power off!\n");
	status = rtas_call(update_token, 1, 1, NULL, rtas_block_list);
	switch (status) {	/* should only get "bad" status */
	    case 0:
		printk(KERN_ALERT "FLASH: success\n");
		break;
	    case -1:
		printk(KERN_ALERT "FLASH: hardware error.  Firmware may not be not flashed\n");
		break;
	    case -3:
		printk(KERN_ALERT "FLASH: image is corrupt or not correct for this platform.  Firmware not flashed\n");
		break;
	    case -4:
		printk(KERN_ALERT "FLASH: flash failed when partially complete.  System may not reboot\n");
		break;
	    default:
		printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status);
		break;
	}
}
/******************************************************************
 * Find all PHBs in the system and initialize a set of data 
 * structures to represent them.
 ******************************************************************/
unsigned long __init
find_and_init_phbs(void)
{
        struct device_node *Pci_Node;
        struct pci_controller *phb;
        unsigned int root_addr_size_words = 0, this_addr_size_words = 0;
	unsigned int this_addr_count = 0, range_stride;
        unsigned int *ui_ptr = NULL, *ranges;
        char *model;
	struct pci_range64 range;
	struct resource *res;
	unsigned int memno, rlen, i, index;
	unsigned int *opprop;
	int has_isa = 0;
        PPCDBG(PPCDBG_PHBINIT, "find_and_init_phbs\n"); 

	read_pci_config = rtas_token("read-pci-config");
	write_pci_config = rtas_token("write-pci-config");
	ibm_read_pci_config = rtas_token("ibm,read-pci-config");
	ibm_write_pci_config = rtas_token("ibm,write-pci-config");

	if (naca->interrupt_controller == IC_OPEN_PIC) {
		opprop = (unsigned int *)get_property(find_path_device("/"),
				"platform-open-pic", NULL);
	}

	/* Get the root address word size. */
	ui_ptr = (unsigned int *) get_property(find_path_device("/"), 
					       "#size-cells", NULL);
	if (ui_ptr) {
		root_addr_size_words = *ui_ptr;
	} else {
		PPCDBG(PPCDBG_PHBINIT, "\tget #size-cells failed.\n"); 
		return(-1);
	}

	if (find_type_devices("isa")) {
		has_isa = 1;
		PPCDBG(PPCDBG_PHBINIT, "\tFound an ISA bus.\n"); 
	}

	index = 0;

	/******************************************************************
	* Find all PHB devices and create an object for them.
	******************************************************************/
	for (Pci_Node = find_devices("pci"); Pci_Node != NULL; Pci_Node = Pci_Node->next) {
		model = (char *) get_property(Pci_Node, "model", NULL);
		if (model != NULL)  {
			phb = alloc_phb(Pci_Node, model, root_addr_size_words);
			if (phb == NULL) return(-1);
		}
		else {
         		continue;
		}
		
		/* Get this node's address word size. */
		ui_ptr = (unsigned int *) get_property(Pci_Node, "#size-cells", NULL);
		if (ui_ptr)
			this_addr_size_words = *ui_ptr;
		else
			this_addr_size_words = 1;
		/* Get this node's address word count. */
		ui_ptr = (unsigned int *) get_property(Pci_Node, "#address-cells", NULL);
		if (ui_ptr)
			this_addr_count = *ui_ptr;
		else
			this_addr_count = 3;
		
		range_stride = this_addr_count + root_addr_size_words + this_addr_size_words;
	      
		memno = 0;
		phb->io_base_phys = 0;
         
		ranges = (unsigned int *) get_property(Pci_Node, "ranges", &rlen);
		PPCDBG(PPCDBG_PHBINIT, "\trange_stride = 0x%lx, rlen = 0x%x\n", range_stride, rlen);
                
		for (i = 0; i < (rlen/sizeof(*ranges)); i+=range_stride) {
		  	/* Put the PCI addr part of the current element into a 
			 * '64' struct. 
			 */
		  	range = *((struct pci_range64 *)(ranges + i));

			/* If this is a '32' element, map into a 64 struct. */
			if ((range_stride * sizeof(int)) == 
			   sizeof(struct pci_range32)) {
				range.parent_addr = 
					(unsigned long)(*(ranges + i + 3));
				range.size = 
					(((unsigned long)(*(ranges + i + 4)))<<32) | 
					(*(ranges + i + 5));
			} else {
				range.parent_addr = 
					(((unsigned long)(*(ranges + i + 3)))<<32) | 
					(*(ranges + i + 4));
				range.size = 
					(((unsigned long)(*(ranges + i + 5)))<<32) | 
					(*(ranges + i + 6));
			}
			
			PPCDBG(PPCDBG_PHBINIT, "\trange.parent_addr    = 0x%lx\n", 
			       range.parent_addr);
			PPCDBG(PPCDBG_PHBINIT, "\trange.child_addr.hi  = 0x%lx\n", 
			       range.child_addr.a_hi);
			PPCDBG(PPCDBG_PHBINIT, "\trange.child_addr.mid = 0x%lx\n", 
			       range.child_addr.a_mid);
			PPCDBG(PPCDBG_PHBINIT, "\trange.child_addr.lo  = 0x%lx\n", 
			       range.child_addr.a_lo);
			PPCDBG(PPCDBG_PHBINIT, "\trange.size           = 0x%lx\n", 
			       range.size);

			res = NULL;
		        switch ((range.child_addr.a_hi >> 24) & 0x3) {
			case 1:		/* I/O space */
				PPCDBG(PPCDBG_PHBINIT, "\tIO Space\n");
				phb->io_base_phys = range.parent_addr;
				res = &phb->io_resource;
				res->name = Pci_Node->full_name;
				res->flags = IORESOURCE_IO;
				phb->io_base_virt = __ioremap(phb->io_base_phys, range.size, _PAGE_NO_CACHE);
				if (!pci_io_base) {
					pci_io_base = (unsigned long)phb->io_base_virt;
					if (has_isa)
						isa_io_base = pci_io_base;
				}
				res->start = ((((unsigned long) range.child_addr.a_mid) << 32) | (range.child_addr.a_lo));
				res->start += (unsigned long)phb->io_base_virt - pci_io_base;
				res->end =   res->start + range.size - 1;
				res->parent = NULL;
				res->sibling = NULL;
				res->child = NULL;
				phb->pci_io_offset = range.parent_addr - 
					((((unsigned long)
					   range.child_addr.a_mid) << 32) | 
					 (range.child_addr.a_lo));
				PPCDBG(PPCDBG_PHBINIT, "\tpci_io_offset  = 0x%lx\n", 
				       phb->pci_io_offset);
			  	break;
			case 2:		/* mem space */
				PPCDBG(PPCDBG_PHBINIT, "\tMem Space\n");
				phb->pci_mem_offset = range.parent_addr - 
					((((unsigned long)
					   range.child_addr.a_mid) << 32) | 
					 (range.child_addr.a_lo));
				PPCDBG(PPCDBG_PHBINIT, "\tpci_mem_offset = 0x%lx\n", 
				       phb->pci_mem_offset);
				if (memno < sizeof(phb->mem_resources)/sizeof(phb->mem_resources[0])) {
					res = &(phb->mem_resources[memno]);
					++memno;
					res->name = Pci_Node->full_name;
					res->flags = IORESOURCE_MEM;
					res->start = range.parent_addr;
					res->end =   range.parent_addr + range.size - 1;
					res->parent = NULL;
					res->sibling = NULL;
					res->child = NULL;
				}
			  	break;
			}
		}
		PPCDBG(PPCDBG_PHBINIT, "\tphb->io_base_phys   = 0x%lx\n", 
		       phb->io_base_phys); 
		PPCDBG(PPCDBG_PHBINIT, "\tphb->pci_mem_offset = 0x%lx\n", 
		       phb->pci_mem_offset); 

		if (naca->interrupt_controller == IC_OPEN_PIC) {
			int addr = root_addr_size_words * (index + 2) - 1;
			openpic_setup_ISU(index, opprop[addr]); 
		}
		index++;
	}
	pci_devs_phb_init();
	return 0;	 /*Success */
}