Esempio n. 1
0
static int init_nvram_block(int index)
{
    unsigned long from;
    int i, j, len;
    char *p, *q;

    i = index;

    RANV_PRINT("--> nvram_init %d\n", index);
    RANV_CHECK_INDEX(-1);

    if (fb[index].valid)
        return -EINVAL;

    //read crc from flash
    from = fb[i].flash_offset;
    len = sizeof(fb[i].env.crc);
    ra_mtd_read_nm(RALINK_NVRAM_MTDNAME, from, len, (unsigned char *)&fb[i].env.crc);

    //read data from flash
    from = from + len;
    len = fb[i].flash_max_len - len;
    fb[i].env.data = (char *)kmalloc(len, GFP_KERNEL);
    if (!fb[i].env.data)
        return -ENOMEM;

    ra_mtd_read_nm(RALINK_NVRAM_MTDNAME, from, len, (unsigned char *)fb[i].env.data);

    //check crc
    if (nv_crc32(0, fb[i].env.data, len) != fb[i].env.crc) {
        RANV_PRINT("Bad CRC %x, ignore values in flash.\n", (unsigned int)fb[i].env.crc);
        memset(fb[index].env.data, 0, len);
        //kfree(fb[i].env.data);
        fb[i].valid = 1;
        fb[i].dirty = 0;
        return -1;
    }

    //parse env to cache
    p = fb[i].env.data;
    for (j = 0; j < MAX_CACHE_ENTRY; j++) {
        if (NULL == (q = strchr(p, '='))) {
            RANV_PRINT("parsed failed - cannot find '='\n");
            break;
        }
        *q = '\0'; //strip '='
        fb[i].cache[j].name = kstrdup(p, GFP_KERNEL);
        //printk("  %d '%s'->", i, p);

        p = q + 1; //value
        if (NULL == (q = strchr(p, '\0'))) {
            RANV_PRINT("parsed failed - cannot find '\\0'\n");
            break;
        }
        fb[i].cache[j].value = kstrdup(p, GFP_KERNEL);
        //printk("'%s'\n", p);

        p = q + 1; //next entry
        if (p - fb[i].env.data + 1 >= len) {
            //end of block
            break;
        }
        if (*p == '\0') {
            //end of env
            break;
        }
    }
    if (j == MAX_CACHE_ENTRY)
        RANV_PRINT("run out of env cache, please increase MAX_CACHE_ENTRY\n");

    fb[i].valid = 1;
    fb[i].dirty = 0;

    return 0;
}
Esempio n. 2
0
Proc*
setupseg(int core)
{
	Mach *m = machp();
	Segment *s;
	uintptr_t  ka;
	Proc *p;
	static Pgrp *kpgrp;
	Segment *tseg;
	int sno;

	// XXX: we're going to need this for locality domains.
	USED(core);

	p = newproc();
	p->psstate = 0;
	p->procmode = 0640;
	p->kp = 1;
	p->noswap = 1;

	p->scallnr = m->externup->scallnr;
	memmove(p->arg, m->externup->arg, sizeof(m->externup->arg));
	p->nerrlab = 0;
	p->slash = m->externup->slash;
	p->dot = m->externup->dot;
	if(p->dot)
		incref(p->dot);

	memmove(p->note, m->externup->note, sizeof(p->note));
	p->nnote = m->externup->nnote;
	p->notified = 0;
	p->lastnote = m->externup->lastnote;
	p->notify = m->externup->notify;
	p->ureg = 0;
	p->dbgreg = 0;

	kstrdup(&p->user, eve);
	if(kpgrp == 0)
		kpgrp = newpgrp();
	p->pgrp = kpgrp;
	incref(kpgrp);

	memset(p->time, 0, sizeof(p->time));
	p->time[TReal] = sys->ticks;

	procpriority(p, PriKproc, 0);


	// XXX: kluge 4 pages of address space for this.
	// how will it expand up? gives us <50 kprocs as is.

	/*
	  * we create the color and core at allocation time, not execution.  This
	  *  is probably not the best idea but it's a start.
	  */

	sno = 0;

	// XXX: now that we are asmalloc we are no long proc.
	/* Stack */
	ka = (uintptr_t)KADDR(asmalloc(0, BIGPGSZ, AsmMEMORY, 1));
	tseg = newseg(SG_STACK|SG_READ|SG_WRITE, ka, 1);
	tseg = p->seg[sno++];

	ka = (uintptr_t)KADDR(asmalloc(0, BIGPGSZ, AsmMEMORY, 1));
	s = newseg(SG_TEXT|SG_READ|SG_EXEC, ka, 1);
	p->seg[sno++] = s;
//	s->color = acpicorecolor(core);

	/* Data. Shared. */
	// XXX; Now that the address space is all funky how are we going to handle shared data segments?
	ka = (uintptr_t)KADDR(asmalloc(0, BIGPGSZ, AsmMEMORY, 2));
	s = newseg(SG_DATA|SG_READ|SG_WRITE, ka, 1);
	p->seg[sno++] = s;
	s->color = tseg->color;

	/* BSS. Uses asm from data map. */
	p->seg[sno++] = newseg(SG_BSS|SG_READ|SG_WRITE, ka+BIGPGSZ, 1);
	p->seg[sno++]->color= tseg->color;


	nixprepage(-1);

	return p;
}
Esempio n. 3
0
/**
 * netlbl_cfg_cipsov4_map_add - Add a new CIPSOv4 DOI mapping
 * @doi: the CIPSO DOI
 * @domain: the domain mapping to add
 * @addr: IP address
 * @mask: IP address mask
 * @audit_info: NetLabel audit information
 *
 * Description:
 * Add a new NetLabel/LSM domain mapping for the given CIPSO DOI to the NetLabel
 * subsystem.  A @domain value of NULL adds a new default domain mapping.
 * Returns zero on success, negative values on failure.
 *
 */
int netlbl_cfg_cipsov4_map_add(u32 doi,
			       const char *domain,
			       const struct in_addr *addr,
			       const struct in_addr *mask,
			       struct netlbl_audit *audit_info)
{
	int ret_val = -ENOMEM;
	struct cipso_v4_doi *doi_def;
	struct netlbl_dom_map *entry;
	struct netlbl_domaddr_map *addrmap = NULL;
	struct netlbl_domaddr4_map *addrinfo = NULL;

	doi_def = cipso_v4_doi_getdef(doi);
	if (doi_def == NULL)
		return -ENOENT;

	entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
	if (entry == NULL)
		return -ENOMEM;
	if (domain != NULL) {
		entry->domain = kstrdup(domain, GFP_ATOMIC);
		if (entry->domain == NULL)
			goto cfg_cipsov4_map_add_failure;
	}

	if (addr == NULL && mask == NULL) {
		entry->type_def.cipsov4 = doi_def;
		entry->type = NETLBL_NLTYPE_CIPSOV4;
	} else if (addr != NULL && mask != NULL) {
		addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
		if (addrmap == NULL)
			goto cfg_cipsov4_map_add_failure;
		INIT_LIST_HEAD(&addrmap->list4);
		INIT_LIST_HEAD(&addrmap->list6);

		addrinfo = kzalloc(sizeof(*addrinfo), GFP_ATOMIC);
		if (addrinfo == NULL)
			goto cfg_cipsov4_map_add_failure;
		addrinfo->type_def.cipsov4 = doi_def;
		addrinfo->type = NETLBL_NLTYPE_CIPSOV4;
		addrinfo->list.addr = addr->s_addr & mask->s_addr;
		addrinfo->list.mask = mask->s_addr;
		addrinfo->list.valid = 1;
		ret_val = netlbl_af4list_add(&addrinfo->list, &addrmap->list4);
		if (ret_val != 0)
			goto cfg_cipsov4_map_add_failure;

		entry->type_def.addrsel = addrmap;
		entry->type = NETLBL_NLTYPE_ADDRSELECT;
	} else {
		ret_val = -EINVAL;
		goto cfg_cipsov4_map_add_failure;
	}

	ret_val = netlbl_domhsh_add(entry, audit_info);
	if (ret_val != 0)
		goto cfg_cipsov4_map_add_failure;

	return 0;

cfg_cipsov4_map_add_failure:
	cipso_v4_doi_putdef(doi_def);
	kfree(entry->domain);
	kfree(entry);
	kfree(addrmap);
	kfree(addrinfo);
	return ret_val;
}
static int __devinit gpio_regulator_probe(struct platform_device *pdev)
{
	struct gpio_regulator_config *config = pdev->dev.platform_data;
	struct gpio_regulator_data *drvdata;
	int ptr, ret, state;

	drvdata = kzalloc(sizeof(struct gpio_regulator_data), GFP_KERNEL);
	if (drvdata == NULL) {
		dev_err(&pdev->dev, "Failed to allocate device data\n");
		return -ENOMEM;
	}

	drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL);
	if (drvdata->desc.name == NULL) {
		dev_err(&pdev->dev, "Failed to allocate supply name\n");
		ret = -ENOMEM;
		goto err;
	}

	drvdata->gpios = kmemdup(config->gpios,
				 config->nr_gpios * sizeof(struct gpio),
				 GFP_KERNEL);
	if (drvdata->gpios == NULL) {
		dev_err(&pdev->dev, "Failed to allocate gpio data\n");
		ret = -ENOMEM;
		goto err_name;
	}

	drvdata->states = kmemdup(config->states,
				  config->nr_states *
					 sizeof(struct gpio_regulator_state),
				  GFP_KERNEL);
	if (drvdata->states == NULL) {
		dev_err(&pdev->dev, "Failed to allocate state data\n");
		ret = -ENOMEM;
		goto err_memgpio;
	}
	drvdata->nr_states = config->nr_states;

	drvdata->desc.owner = THIS_MODULE;

	/* handle regulator type*/
	switch (config->type) {
	case REGULATOR_VOLTAGE:
		drvdata->desc.type = REGULATOR_VOLTAGE;
		drvdata->desc.ops = &gpio_regulator_voltage_ops;
		drvdata->desc.n_voltages = config->nr_states;
		break;
	case REGULATOR_CURRENT:
		drvdata->desc.type = REGULATOR_CURRENT;
		drvdata->desc.ops = &gpio_regulator_current_ops;
		break;
	default:
		dev_err(&pdev->dev, "No regulator type set\n");
		ret = -EINVAL;
		goto err_memgpio;
		break;
	}

	drvdata->enable_gpio = config->enable_gpio;
	drvdata->startup_delay = config->startup_delay;

	if (gpio_is_valid(config->enable_gpio)) {
		drvdata->enable_high = config->enable_high;

		ret = gpio_request(config->enable_gpio, config->supply_name);
		if (ret) {
			dev_err(&pdev->dev,
			   "Could not obtain regulator enable GPIO %d: %d\n",
						config->enable_gpio, ret);
			goto err_memstate;
		}

		/* set output direction without changing state
		 * to prevent glitch
		 */
		if (config->enabled_at_boot) {
			drvdata->is_enabled = true;
			ret = gpio_direction_output(config->enable_gpio,
						    config->enable_high);
		} else {
			drvdata->is_enabled = false;
			ret = gpio_direction_output(config->enable_gpio,
						    !config->enable_high);
		}

		if (ret) {
			dev_err(&pdev->dev,
			   "Could not configure regulator enable GPIO %d direction: %d\n",
						config->enable_gpio, ret);
			goto err_enablegpio;
		}
	} else {
		/* Regulator without GPIO control is considered
		 * always enabled
		 */
		drvdata->is_enabled = true;
	}

	drvdata->nr_gpios = config->nr_gpios;
	ret = gpio_request_array(drvdata->gpios, drvdata->nr_gpios);
	if (ret) {
		dev_err(&pdev->dev,
		   "Could not obtain regulator setting GPIOs: %d\n", ret);
		goto err_enablegpio;
	}

	/* build initial state from gpio init data. */
	state = 0;
	for (ptr = 0; ptr < drvdata->nr_gpios; ptr++) {
		if (config->gpios[ptr].flags & GPIOF_OUT_INIT_HIGH)
			state |= (1 << ptr);
	}
	drvdata->state = state;

	drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev,
					  config->init_data, drvdata, NULL);
	if (IS_ERR(drvdata->dev)) {
		ret = PTR_ERR(drvdata->dev);
		dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret);
		goto err_stategpio;
	}

	platform_set_drvdata(pdev, drvdata);

	return 0;

err_stategpio:
	gpio_free_array(drvdata->gpios, drvdata->nr_gpios);
err_enablegpio:
	if (gpio_is_valid(config->enable_gpio))
		gpio_free(config->enable_gpio);
err_memstate:
	kfree(drvdata->states);
err_memgpio:
	kfree(drvdata->gpios);
err_name:
	kfree(drvdata->desc.name);
err:
	kfree(drvdata);
	return ret;
}
        else if(!strncmp(buff,"l",1))
                *std |= V4L2_STD_SECAM_L;
        else if(!strncmp(buff,"lc",2))
                *std |= V4L2_STD_SECAM_LC;
        else
                pr_info("invaild command.\n");
}
static ssize_t si2176_store(struct class *cls, struct class_attribute *attr, const char *buf, size_t count)
{
        int n = 0;
        unsigned char ret =0;
        char *buf_orig, *ps, *token;
        char *parm[4];
        unsigned int addr = 0, val = 0;
        v4l2_std_id  std;
        buf_orig = kstrdup(buf, GFP_KERNEL);
        ps = buf_orig;
        while (1) {
                token = strsep(&ps, " \n");
                if (token == NULL)
                        break;
                if (*token == '\0')
                        continue;
                parm[n++] = token;
        }

        if (!strncmp(parm[0],"rs",strlen("rs")))
        {
                if (n != 2)
                {
                        pr_err("read: invalid parameter\n");
Esempio n. 6
0
/**
 * parse_opts - parse mount options into rdma options structure
 * @params: options string passed from mount
 * @opts: rdma transport-specific structure to parse options into
 *
 * Returns 0 upon success, -ERRNO upon failure
 */
static int parse_opts(char *params, struct p9_rdma_opts *opts)
{
	char *p;
	substring_t args[MAX_OPT_ARGS];
	int option;
	char *options, *tmp_options;

	opts->port = P9_PORT;
	opts->sq_depth = P9_RDMA_SQ_DEPTH;
	opts->rq_depth = P9_RDMA_RQ_DEPTH;
	opts->timeout = P9_RDMA_TIMEOUT;
	opts->privport = 0;

	if (!params)
		return 0;

	tmp_options = kstrdup(params, GFP_KERNEL);
	if (!tmp_options) {
		p9_debug(P9_DEBUG_ERROR,
			 "failed to allocate copy of option string\n");
		return -ENOMEM;
	}
	options = tmp_options;

	while ((p = strsep(&options, ",")) != NULL) {
		int token;
		int r;
		if (!*p)
			continue;
		token = match_token(p, tokens, args);
		if ((token != Opt_err) && (token != Opt_privport)) {
			r = match_int(&args[0], &option);
			if (r < 0) {
				p9_debug(P9_DEBUG_ERROR,
					 "integer field, but no integer?\n");
				continue;
			}
		}
		switch (token) {
		case Opt_port:
			opts->port = option;
			break;
		case Opt_sq_depth:
			opts->sq_depth = option;
			break;
		case Opt_rq_depth:
			opts->rq_depth = option;
			break;
		case Opt_timeout:
			opts->timeout = option;
			break;
		case Opt_privport:
			opts->privport = 1;
			break;
		default:
			continue;
		}
	}
	/* RQ must be at least as large as the SQ */
	opts->rq_depth = max(opts->rq_depth, opts->sq_depth);
	kfree(tmp_options);
	return 0;
}
Esempio n. 7
0
static void __init tegra_ventana_init(void)
{
#if defined(CONFIG_TOUCHSCREEN_PANJIT_I2C) || \
	defined(CONFIG_TOUCHSCREEN_ATMEL_MT_T9)
	struct board_info BoardInfo;
#endif

	tegra_common_init();
	tegra_clk_init_from_table(ventana_clk_init_table);
	ventana_pinmux_init();
	ventana_i2c_init();
	snprintf(usb_serial_num, sizeof(usb_serial_num), "%llx", tegra_chip_uid());
	andusb_plat.serial_number = kstrdup(usb_serial_num, GFP_KERNEL);
	tegra_i2s_device1.dev.platform_data = &tegra_audio_pdata[0];
	tegra_i2s_device2.dev.platform_data = &tegra_audio_pdata[1];
	tegra_spdif_device.dev.platform_data = &tegra_spdif_pdata;
	if (is_tegra_debug_uartport_hs() == true)
		platform_device_register(&tegra_uartd_device);
	else
		platform_device_register(&debug_uart);
	tegra_das_device.dev.platform_data = &tegra_das_pdata;
	tegra_ehci2_device.dev.platform_data
		= &ventana_ehci2_ulpi_platform_data;
	platform_add_devices(ventana_devices, ARRAY_SIZE(ventana_devices));

	ventana_sdhci_init();
	ventana_charge_init();
	ventana_regulator_init();

#if defined(CONFIG_TOUCHSCREEN_PANJIT_I2C) || \
	defined(CONFIG_TOUCHSCREEN_ATMEL_MT_T9)

	tegra_get_board_info(&BoardInfo);

	/* boards with sku > 0 have atmel touch panels */
	if (BoardInfo.sku) {
		pr_info("Initializing Atmel touch driver\n");
		ventana_touch_init_atmel();
	} else {
		pr_info("Initializing Panjit touch driver\n");
		ventana_touch_init_panjit();
	}
#endif

#ifdef CONFIG_KEYBOARD_GPIO
	ventana_keys_init();
#endif
#ifdef CONFIG_KEYBOARD_TEGRA
	ventana_kbc_init();
#endif

	ventana_wired_jack_init();
	ventana_usb_init();
	ventana_gps_init();
	ventana_panel_init();
	ventana_sensors_init();
	ventana_bt_rfkill();
	ventana_power_off_init();
	ventana_emc_init();
#ifdef CONFIG_BT_BLUESLEEP
	tegra_setup_bluesleep();
#endif
}
Esempio n. 8
0
static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
{
	struct fixed_voltage_config *config = pdev->dev.platform_data;
	struct fixed_voltage_data *drvdata;
	int ret;

	drvdata = kzalloc(sizeof(struct fixed_voltage_data), GFP_KERNEL);
	if (drvdata == NULL) {
		dev_err(&pdev->dev, "Failed to allocate device data\n");
		ret = -ENOMEM;
		goto err;
	}

	drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL);
	if (drvdata->desc.name == NULL) {
		dev_err(&pdev->dev, "Failed to allocate supply name\n");
		ret = -ENOMEM;
		goto err;
	}
	drvdata->desc.type = REGULATOR_VOLTAGE;
	drvdata->desc.owner = THIS_MODULE;
	drvdata->desc.ops = &fixed_voltage_ops;
	drvdata->desc.n_voltages = 1;

	drvdata->microvolts = config->microvolts;
	drvdata->gpio = config->gpio;
	drvdata->startup_delay = config->startup_delay;

	if (gpio_is_valid(config->gpio)) {
		drvdata->enable_high = config->enable_high;

		/* FIXME: Remove below print warning
		 *
		 * config->gpio must be set to -EINVAL by platform code if
		 * GPIO control is not required. However, early adopters
		 * not requiring GPIO control may forget to initialize
		 * config->gpio to -EINVAL. This will cause GPIO 0 to be used
		 * for GPIO control.
		 *
		 * This warning will be removed once there are a couple of users
		 * for this driver.
		 */
		if (!config->gpio)
			dev_warn(&pdev->dev,
				"using GPIO 0 for regulator enable control\n");

		ret = gpio_request(config->gpio, config->supply_name);
		if (ret) {
			dev_err(&pdev->dev,
			   "Could not obtain regulator enable GPIO %d: %d\n",
							config->gpio, ret);
			goto err_name;
		}

		/* set output direction without changing state
		 * to prevent glitch
		 */
		drvdata->is_enabled = config->enabled_at_boot;
		ret = drvdata->is_enabled ?
				config->enable_high : !config->enable_high;

		ret = gpio_direction_output(config->gpio, ret);
		if (ret) {
			dev_err(&pdev->dev,
			   "Could not configure regulator enable GPIO %d direction: %d\n",
							config->gpio, ret);
			goto err_gpio;
		}

	} else {
		/* Regulator without GPIO control is considered
		 * always enabled
		 */
		drvdata->is_enabled = true;
	}

	drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev,
					  config->init_data, drvdata);
	if (IS_ERR(drvdata->dev)) {
		ret = PTR_ERR(drvdata->dev);
		dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret);
		goto err_gpio;
	}

	platform_set_drvdata(pdev, drvdata);

	dev_dbg(&pdev->dev, "%s supplying %duV\n", drvdata->desc.name,
		drvdata->microvolts);

	return 0;

err_gpio:
	if (gpio_is_valid(config->gpio))
		gpio_free(config->gpio);
err_name:
	kfree(drvdata->desc.name);
err:
	kfree(drvdata);
	return ret;
}
Esempio n. 9
0
static int32_t
acpiwrite(Chan *c, void *a, int32_t n, int64_t off)
{
	Mach *m = machp();
	Cmdtab *ct;
	Cmdbuf *cb;
	Reg *r;
	uint rno, fun, dev, bus, i;

	if(c->qid.path == Qio){
		if(reg == nil)
			error("region not configured");
		return regio(reg, a, n, off, 1);
	}
	if(c->qid.path != Qctl)
		error(Eperm);

	cb = parsecmd(a, n);
	if(waserror()){
		free(cb);
		nexterror();
	}
	ct = lookupcmd(cb, ctls, nelem(ctls));
	DBG("acpi ctl %s\n", cb->f[0]);
	switch(ct->index){
	case CMregion:
		r = reg;
		if(r == nil){
			r = smalloc(sizeof(Reg));
			r->name = nil;
		}
		kstrdup(&r->name, cb->f[1]);
		r->spc = acpiregid(cb->f[2]);
		if(r->spc < 0){
			free(r);
			reg = nil;
			error("bad region type");
		}
		if(r->spc == Rpcicfg || r->spc == Rpcibar){
			rno = r->base>>Rpciregshift & Rpciregmask;
			fun = r->base>>Rpcifunshift & Rpcifunmask;
			dev = r->base>>Rpcidevshift & Rpcidevmask;
			bus = r->base>>Rpcibusshift & Rpcibusmask;
			r->tbdf = MKBUS(BusPCI, bus, dev, fun);
			r->base = rno;	/* register ~ our base addr */
		}
		r->base = strtoull(cb->f[3], nil, 0);
		r->len = strtoull(cb->f[4], nil, 0);
		r->accsz = strtoul(cb->f[5], nil, 0);
		if(r->accsz < 1 || r->accsz > 4){
			free(r);
			reg = nil;
			error("bad region access size");
		}
		reg = r;
		DBG("region %s %s %llux %llux sz%d",
			r->name, acpiregstr(r->spc), r->base, r->len, r->accsz);
		break;
	case CMgpe:
		i = strtoul(cb->f[1], nil, 0);
		if(i >= ngpes)
			error("gpe out of range");
		kstrdup(&gpes[i].obj, cb->f[2]);
		DBG("gpe %d %s\n", i, gpes[i].obj);
		setgpeen(i, 1);
		break;
	default:
		panic("acpi: unknown ctl");
	}
Esempio n. 10
0
File: super.c Progetto: avagin/linux
static int ovl_parse_opt(char *opt, struct ovl_config *config)
{
	char *p;
	int err;
	bool metacopy_opt = false, redirect_opt = false;

	config->redirect_mode = kstrdup(ovl_redirect_mode_def(), GFP_KERNEL);
	if (!config->redirect_mode)
		return -ENOMEM;

	while ((p = ovl_next_opt(&opt)) != NULL) {
		int token;
		substring_t args[MAX_OPT_ARGS];

		if (!*p)
			continue;

		token = match_token(p, ovl_tokens, args);
		switch (token) {
		case OPT_UPPERDIR:
			kfree(config->upperdir);
			config->upperdir = match_strdup(&args[0]);
			if (!config->upperdir)
				return -ENOMEM;
			break;

		case OPT_LOWERDIR:
			kfree(config->lowerdir);
			config->lowerdir = match_strdup(&args[0]);
			if (!config->lowerdir)
				return -ENOMEM;
			break;

		case OPT_WORKDIR:
			kfree(config->workdir);
			config->workdir = match_strdup(&args[0]);
			if (!config->workdir)
				return -ENOMEM;
			break;

		case OPT_DEFAULT_PERMISSIONS:
			config->default_permissions = true;
			break;

		case OPT_REDIRECT_DIR:
			kfree(config->redirect_mode);
			config->redirect_mode = match_strdup(&args[0]);
			if (!config->redirect_mode)
				return -ENOMEM;
			redirect_opt = true;
			break;

		case OPT_INDEX_ON:
			config->index = true;
			break;

		case OPT_INDEX_OFF:
			config->index = false;
			break;

		case OPT_NFS_EXPORT_ON:
			config->nfs_export = true;
			break;

		case OPT_NFS_EXPORT_OFF:
			config->nfs_export = false;
			break;

		case OPT_XINO_ON:
			config->xino = OVL_XINO_ON;
			break;

		case OPT_XINO_OFF:
			config->xino = OVL_XINO_OFF;
			break;

		case OPT_XINO_AUTO:
			config->xino = OVL_XINO_AUTO;
			break;

		case OPT_METACOPY_ON:
			config->metacopy = true;
			metacopy_opt = true;
			break;

		case OPT_METACOPY_OFF:
			config->metacopy = false;
			break;

		default:
			pr_err("overlayfs: unrecognized mount option \"%s\" or missing value\n", p);
			return -EINVAL;
		}
	}

	/* Workdir is useless in non-upper mount */
	if (!config->upperdir && config->workdir) {
		pr_info("overlayfs: option \"workdir=%s\" is useless in a non-upper mount, ignore\n",
			config->workdir);
		kfree(config->workdir);
		config->workdir = NULL;
	}

	err = ovl_parse_redirect_mode(config, config->redirect_mode);
	if (err)
		return err;

	/*
	 * This is to make the logic below simpler.  It doesn't make any other
	 * difference, since config->redirect_dir is only used for upper.
	 */
	if (!config->upperdir && config->redirect_follow)
		config->redirect_dir = true;

	/* Resolve metacopy -> redirect_dir dependency */
	if (config->metacopy && !config->redirect_dir) {
		if (metacopy_opt && redirect_opt) {
			pr_err("overlayfs: conflicting options: metacopy=on,redirect_dir=%s\n",
			       config->redirect_mode);
			return -EINVAL;
		}
		if (redirect_opt) {
			/*
			 * There was an explicit redirect_dir=... that resulted
			 * in this conflict.
			 */
			pr_info("overlayfs: disabling metacopy due to redirect_dir=%s\n",
				config->redirect_mode);
			config->metacopy = false;
		} else {
			/* Automatically enable redirect otherwise. */
			config->redirect_follow = config->redirect_dir = true;
		}
	}

	return 0;
}
Esempio n. 11
0
/*
 * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise.
 */
int nand_onfi_detect(struct nand_chip *chip)
{
	struct mtd_info *mtd = nand_to_mtd(chip);
	struct nand_onfi_params *p;
	struct onfi_params *onfi;
	int onfi_version = 0;
	char id[4];
	int i, ret, val;

	/* Try ONFI for unknown chip or LP */
	ret = nand_readid_op(chip, 0x20, id, sizeof(id));
	if (ret || strncmp(id, "ONFI", 4))
		return 0;

	/* ONFI chip: allocate a buffer to hold its parameter page */
	p = kzalloc((sizeof(*p) * 3), GFP_KERNEL);
	if (!p)
		return -ENOMEM;

	ret = nand_read_param_page_op(chip, 0, NULL, 0);
	if (ret) {
		ret = 0;
		goto free_onfi_param_page;
	}

	for (i = 0; i < 3; i++) {
		ret = nand_read_data_op(chip, &p[i], sizeof(*p), true);
		if (ret) {
			ret = 0;
			goto free_onfi_param_page;
		}

		if (onfi_crc16(ONFI_CRC_BASE, (u8 *)&p[i], 254) ==
				le16_to_cpu(p->crc)) {
			if (i)
				memcpy(p, &p[i], sizeof(*p));
			break;
		}
	}

	if (i == 3) {
		const void *srcbufs[3] = {p, p + 1, p + 2};

		pr_warn("Could not find a valid ONFI parameter page, trying bit-wise majority to recover it\n");
		nand_bit_wise_majority(srcbufs, ARRAY_SIZE(srcbufs), p,
				       sizeof(*p));

		if (onfi_crc16(ONFI_CRC_BASE, (u8 *)p, 254) !=
				le16_to_cpu(p->crc)) {
			pr_err("ONFI parameter recovery failed, aborting\n");
			goto free_onfi_param_page;
		}
	}

	if (chip->manufacturer.desc && chip->manufacturer.desc->ops &&
	    chip->manufacturer.desc->ops->fixup_onfi_param_page)
		chip->manufacturer.desc->ops->fixup_onfi_param_page(chip, p);

	/* Check version */
	val = le16_to_cpu(p->revision);
	if (val & ONFI_VERSION_2_3)
		onfi_version = 23;
	else if (val & ONFI_VERSION_2_2)
		onfi_version = 22;
	else if (val & ONFI_VERSION_2_1)
		onfi_version = 21;
	else if (val & ONFI_VERSION_2_0)
		onfi_version = 20;
	else if (val & ONFI_VERSION_1_0)
		onfi_version = 10;

	if (!onfi_version) {
		pr_info("unsupported ONFI version: %d\n", val);
		goto free_onfi_param_page;
	}

	sanitize_string(p->manufacturer, sizeof(p->manufacturer));
	sanitize_string(p->model, sizeof(p->model));
	chip->parameters.model = kstrdup(p->model, GFP_KERNEL);
	if (!chip->parameters.model) {
		ret = -ENOMEM;
		goto free_onfi_param_page;
	}

	mtd->writesize = le32_to_cpu(p->byte_per_page);

	/*
	 * pages_per_block and blocks_per_lun may not be a power-of-2 size
	 * (don't ask me who thought of this...). MTD assumes that these
	 * dimensions will be power-of-2, so just truncate the remaining area.
	 */
	mtd->erasesize = 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1);
	mtd->erasesize *= mtd->writesize;

	mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);

	/* See erasesize comment */
	chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1);
	chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count;
	chip->bits_per_cell = p->bits_per_cell;

	chip->max_bb_per_die = le16_to_cpu(p->bb_per_lun);
	chip->blocks_per_die = le32_to_cpu(p->blocks_per_lun);

	if (le16_to_cpu(p->features) & ONFI_FEATURE_16_BIT_BUS)
		chip->options |= NAND_BUSWIDTH_16;

	if (p->ecc_bits != 0xff) {
		chip->ecc_strength_ds = p->ecc_bits;
		chip->ecc_step_ds = 512;
	} else if (onfi_version >= 21 &&
		(le16_to_cpu(p->features) & ONFI_FEATURE_EXT_PARAM_PAGE)) {

		/*
		 * The nand_flash_detect_ext_param_page() uses the
		 * Change Read Column command which maybe not supported
		 * by the chip->legacy.cmdfunc. So try to update the
		 * chip->legacy.cmdfunc now. We do not replace user supplied
		 * command function.
		 */
		nand_legacy_adjust_cmdfunc(chip);

		/* The Extended Parameter Page is supported since ONFI 2.1. */
		if (nand_flash_detect_ext_param_page(chip, p))
			pr_warn("Failed to detect ONFI extended param page\n");
	} else {
		pr_warn("Could not retrieve ONFI ECC requirements\n");
	}

	/* Save some parameters from the parameter page for future use */
	if (le16_to_cpu(p->opt_cmd) & ONFI_OPT_CMD_SET_GET_FEATURES) {
		chip->parameters.supports_set_get_features = true;
		bitmap_set(chip->parameters.get_feature_list,
			   ONFI_FEATURE_ADDR_TIMING_MODE, 1);
		bitmap_set(chip->parameters.set_feature_list,
			   ONFI_FEATURE_ADDR_TIMING_MODE, 1);
	}

	onfi = kzalloc(sizeof(*onfi), GFP_KERNEL);
	if (!onfi) {
		ret = -ENOMEM;
		goto free_model;
	}

	onfi->version = onfi_version;
	onfi->tPROG = le16_to_cpu(p->t_prog);
	onfi->tBERS = le16_to_cpu(p->t_bers);
	onfi->tR = le16_to_cpu(p->t_r);
	onfi->tCCS = le16_to_cpu(p->t_ccs);
	onfi->async_timing_mode = le16_to_cpu(p->async_timing_mode);
	onfi->vendor_revision = le16_to_cpu(p->vendor_revision);
	memcpy(onfi->vendor, p->vendor, sizeof(p->vendor));
	chip->parameters.onfi = onfi;

	/* Identification done, free the full ONFI parameter page and exit */
	kfree(p);

	return 1;

free_model:
	kfree(chip->parameters.model);
free_onfi_param_page:
	kfree(p);

	return ret;
}
Esempio n. 12
0
File: super.c Progetto: avagin/linux
static struct ovl_entry *ovl_get_lowerstack(struct super_block *sb,
					    struct ovl_fs *ofs)
{
	int err;
	char *lowertmp, *lower;
	struct path *stack = NULL;
	unsigned int stacklen, numlower = 0, i;
	bool remote = false;
	struct ovl_entry *oe;

	err = -ENOMEM;
	lowertmp = kstrdup(ofs->config.lowerdir, GFP_KERNEL);
	if (!lowertmp)
		goto out_err;

	err = -EINVAL;
	stacklen = ovl_split_lowerdirs(lowertmp);
	if (stacklen > OVL_MAX_STACK) {
		pr_err("overlayfs: too many lower directories, limit is %d\n",
		       OVL_MAX_STACK);
		goto out_err;
	} else if (!ofs->config.upperdir && stacklen == 1) {
		pr_err("overlayfs: at least 2 lowerdir are needed while upperdir nonexistent\n");
		goto out_err;
	} else if (!ofs->config.upperdir && ofs->config.nfs_export &&
		   ofs->config.redirect_follow) {
		pr_warn("overlayfs: NFS export requires \"redirect_dir=nofollow\" on non-upper mount, falling back to nfs_export=off.\n");
		ofs->config.nfs_export = false;
	}

	err = -ENOMEM;
	stack = kcalloc(stacklen, sizeof(struct path), GFP_KERNEL);
	if (!stack)
		goto out_err;

	err = -EINVAL;
	lower = lowertmp;
	for (numlower = 0; numlower < stacklen; numlower++) {
		err = ovl_lower_dir(lower, &stack[numlower], ofs,
				    &sb->s_stack_depth, &remote);
		if (err)
			goto out_err;

		lower = strchr(lower, '\0') + 1;
	}

	err = -EINVAL;
	sb->s_stack_depth++;
	if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) {
		pr_err("overlayfs: maximum fs stacking depth exceeded\n");
		goto out_err;
	}

	err = ovl_get_lower_layers(ofs, stack, numlower);
	if (err)
		goto out_err;

	err = -ENOMEM;
	oe = ovl_alloc_entry(numlower);
	if (!oe)
		goto out_err;

	for (i = 0; i < numlower; i++) {
		oe->lowerstack[i].dentry = dget(stack[i].dentry);
		oe->lowerstack[i].layer = &ofs->lower_layers[i];
	}

	if (remote)
		sb->s_d_op = &ovl_reval_dentry_operations;
	else
		sb->s_d_op = &ovl_dentry_operations;

out:
	for (i = 0; i < numlower; i++)
		path_put(&stack[i]);
	kfree(stack);
	kfree(lowertmp);

	return oe;

out_err:
	oe = ERR_PTR(err);
	goto out;
}
Esempio n. 13
0
/*
 * This function is used to initialize the context with right values. In this
 * method, we can make all the detection we want, and modify the asus_laptop
 * struct
 */
static int asus_laptop_get_info(struct asus_laptop *asus)
{
	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
	union acpi_object *model = NULL;
	unsigned long long bsts_result, hwrs_result;
	char *string = NULL;
	acpi_status status;

	/*
	 * Get DSDT headers early enough to allow for differentiating between
	 * models, but late enough to allow acpi_bus_register_driver() to fail
	 * before doing anything ACPI-specific. Should we encounter a machine,
	 * which needs special handling (i.e. its hotkey device has a different
	 * HID), this bit will be moved.
	 */
	status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus->dsdt_info);
	if (ACPI_FAILURE(status))
		pr_warning("Couldn't get the DSDT table header\n");

	/* We have to write 0 on init this far for all ASUS models */
	if (write_acpi_int_ret(asus->handle, "INIT", 0, &buffer)) {
		pr_err("Hotkey initialization failed\n");
		return -ENODEV;
	}

	/* This needs to be called for some laptops to init properly */
	status =
	    acpi_evaluate_integer(asus->handle, "BSTS", NULL, &bsts_result);
	if (ACPI_FAILURE(status))
		pr_warning("Error calling BSTS\n");
	else if (bsts_result)
		pr_notice("BSTS called, 0x%02x returned\n",
		       (uint) bsts_result);

	/* This too ... */
	if (write_acpi_int(asus->handle, "CWAP", wapf))
		pr_err("Error calling CWAP(%d)\n", wapf);
	/*
	 * Try to match the object returned by INIT to the specific model.
	 * Handle every possible object (or the lack of thereof) the DSDT
	 * writers might throw at us. When in trouble, we pass NULL to
	 * asus_model_match() and try something completely different.
	 */
	if (buffer.pointer) {
		model = buffer.pointer;
		switch (model->type) {
		case ACPI_TYPE_STRING:
			string = model->string.pointer;
			break;
		case ACPI_TYPE_BUFFER:
			string = model->buffer.pointer;
			break;
		default:
			string = "";
			break;
		}
	}
	asus->name = kstrdup(string, GFP_KERNEL);
	if (!asus->name)
		return -ENOMEM;

	if (*string)
		pr_notice("  %s model detected\n", string);

	/*
	 * The HWRS method return informations about the hardware.
	 * 0x80 bit is for WLAN, 0x100 for Bluetooth.
	 * The significance of others is yet to be found.
	 */
	status =
	    acpi_evaluate_integer(asus->handle, "HRWS", NULL, &hwrs_result);
	if (!ACPI_FAILURE(status))
		pr_notice("  HRWS returned %x", (int)hwrs_result);

	if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL))
		asus->have_rsts = true;

	/* Scheduled for removal */
	ASUS_HANDLE_INIT(lcd_switch);
	ASUS_HANDLE_INIT(display_get);

	kfree(model);

	return AE_OK;
}
Esempio n. 14
0
File: dir.c Progetto: Flipkart/linux
/**
 * kernfs_rename_ns - move and rename a kernfs_node
 * @kn: target node
 * @new_parent: new parent to put @sd under
 * @new_name: new name
 * @new_ns: new namespace tag
 */
int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,
		     const char *new_name, const void *new_ns)
{
	struct kernfs_node *old_parent;
	const char *old_name = NULL;
	int error;

	/* can't move or rename root */
	if (!kn->parent)
		return -EINVAL;

	mutex_lock(&kernfs_mutex);

	error = -ENOENT;
	if (!kernfs_active(kn) || !kernfs_active(new_parent))
		goto out;

	error = 0;
	if ((kn->parent == new_parent) && (kn->ns == new_ns) &&
	    (strcmp(kn->name, new_name) == 0))
		goto out;	/* nothing to rename */

	error = -EEXIST;
	if (kernfs_find_ns(new_parent, new_name, new_ns))
		goto out;

	/* rename kernfs_node */
	if (strcmp(kn->name, new_name) != 0) {
		error = -ENOMEM;
		new_name = kstrdup(new_name, GFP_KERNEL);
		if (!new_name)
			goto out;
	} else {
		new_name = NULL;
	}

	/*
	 * Move to the appropriate place in the appropriate directories rbtree.
	 */
	kernfs_unlink_sibling(kn);
	kernfs_get(new_parent);

	/* rename_lock protects ->parent and ->name accessors */
	spin_lock_irq(&kernfs_rename_lock);

	old_parent = kn->parent;
	kn->parent = new_parent;

	kn->ns = new_ns;
	if (new_name) {
		if (!(kn->flags & KERNFS_STATIC_NAME))
			old_name = kn->name;
		kn->flags &= ~KERNFS_STATIC_NAME;
		kn->name = new_name;
	}

	spin_unlock_irq(&kernfs_rename_lock);

	kn->hash = kernfs_name_hash(kn->name, kn->ns);
	kernfs_link_sibling(kn);

	kernfs_put(old_parent);
	kfree(old_name);

	error = 0;
 out:
	mutex_unlock(&kernfs_mutex);
	return error;
}
Esempio n. 15
0
static long
conswrite(Chan *c, void *va, long n, vlong off)
{
	char buf[256];
	long l, bp;
	char *a;
	Mach *mp;
	int id, fd;
	Chan *swc;
	ulong offset;
	Cmdbuf *cb;
	Cmdtab *ct;

	a = va;
	offset = off;

	switch((ulong)c->qid.path){
	case Qcons:
		/*
		 * Can't page fault in putstrn, so copy the data locally.
		 */
		l = n;
		while(l > 0){
			bp = l;
			if(bp > sizeof buf)
				bp = sizeof buf;
			memmove(buf, a, bp);
			putstrn0(buf, bp, 1);
			a += bp;
			l -= bp;
		}
		break;

	case Qconsctl:
		error(Egreg);

	case Qtime:
		if(!iseve())
			error(Eperm);
		return writetime(a, n);

	case Qbintime:
		if(!iseve())
			error(Eperm);
		return writebintime(a, n);

	case Qhostowner:
		return hostownerwrite(a, n);

	case Qhostdomain:
		return hostdomainwrite(a, n);

	case Quser:
		return userwrite(a, n);

	case Qnull:
		break;

	case Qconfig:
		error(Eperm);
		break;

	case Qreboot:
		if(!iseve())
			error(Eperm);
		cb = parsecmd(a, n);

		if(waserror()) {
			free(cb);
			nexterror();
		}
		ct = lookupcmd(cb, rebootmsg, nelem(rebootmsg));
		switch(ct->index) {
		case CMhalt:
			reboot(nil, 0, 0);
			break;
		case CMreboot:
			rebootcmd(cb->nf-1, cb->f+1);
			break;
		case CMpanic:
			*(ulong*)0=0;
			panic("/dev/reboot");
		case CMrdb:
			if(consdebug == nil)
				consdebug = rdb;
			consdebug();
			break;
		}
		poperror();
		free(cb);
		break;

	case Qsysstat:
		for(id = 0; id < 32; id++) {
			if(active.machs & (1<<id)) {
				mp = MACHP(id);
				mp->cs = 0;
				mp->intr = 0;
				mp->syscall = 0;
				mp->pfault = 0;
				mp->tlbfault = 0;
				mp->tlbpurge = 0;
			}
		}
		break;

	case Qswap:
		if(n >= sizeof buf)
			error(Egreg);
		memmove(buf, va, n);	/* so we can NUL-terminate */
		buf[n] = 0;
		/* start a pager if not already started */
		if(strncmp(buf, "start", 5) == 0){
			kickpager();
			break;
		}
		if(!iseve())
			error(Eperm);
		if(buf[0]<'0' || '9'<buf[0])
			error(Ebadarg);
		fd = strtoul(buf, 0, 0);
		swc = fdtochan(fd, -1, 1, 1);
		setswapchan(swc);
		break;

	case Qsysname:
		if(offset != 0)
			error(Ebadarg);
		if(n <= 0 || n >= sizeof buf)
			error(Ebadarg);
		strncpy(buf, a, n);
		buf[n] = 0;
		if(buf[n-1] == '\n')
			buf[n-1] = 0;
		kstrdup(&sysname, buf);
		break;
	
	case Qmordor:
		error("one does not simply write into mordor");
		return 0;

	default:
		print("conswrite: %#llux\n", c->qid.path);
		error(Egreg);
	}
	return n;
}
Esempio n. 16
0
static Atable*
acpimadt(uint8_t *p, int len)
{
	uint8_t *pe;
	Apicst *st, *l, **stl;
	int stlen, id;

	apics = mallocz(sizeof(Madt), 1);
	apics->lapicpa = l32get(p+36);
	apics->pcat = l32get(p+40);
	apics->st = nil;
	stl = &apics->st;
	pe = p + len;
	for(p += 44; p < pe; p += stlen){
		st = mallocz(sizeof(Apicst), 1);
		st->type = p[0];
		st->next = nil;
		stlen = p[1];
		switch(st->type){
		case ASlapic:
			st->lapic.pid = p[2];
			st->lapic.id = p[3];
			if(l32get(p+4) == 0){
				free(st);
				st = nil;
			}
			break;
		case ASioapic:
			st->ioapic.id = id = p[2];
			st->ioapic.addr = l32get(p+4);
			st->ioapic.ibase = l32get(p+8);
			/* iosapic overrides any ioapic entry for the same id */
			for(l = apics->st; l != nil; l = l->next)
				if(l->type == ASiosapic && l->iosapic.id == id){
					st->ioapic = l->iosapic;
					/* we leave it linked; could be removed */
					break;
				}
			break;
		case ASintovr:
			st->intovr.irq = p[3];
			st->intovr.intr = l32get(p+4);
			st->intovr.flags = l16get(p+8);
			break;
		case ASnmi:
			st->nmi.flags = l16get(p+2);
			st->nmi.intr = l32get(p+4);
			break;
		case ASlnmi:
			st->lnmi.pid = p[2];
			st->lnmi.flags = l16get(p+3);
			st->lnmi.lint = p[5];
			break;
		case ASladdr:
			/* This is for 64 bits, perhaps we should not
			 * honor it on 32 bits.
			 */
			apics->lapicpa = l64get(p+8);
			break;
		case ASiosapic:
			id = st->iosapic.id = p[2];
			st->iosapic.ibase = l32get(p+4);
			st->iosapic.addr = l64get(p+8);
			/* iosapic overrides any ioapic entry for the same id */
			for(l = apics->st; l != nil; l = l->next)
				if(l->type == ASioapic && l->ioapic.id == id){
					l->ioapic = st->iosapic;
					free(st);
					st = nil;
					break;
				}
			break;
		case ASlsapic:
			st->lsapic.pid = p[2];
			st->lsapic.id = p[3];
			st->lsapic.eid = p[4];
			st->lsapic.puid = l32get(p+12);
			if(l32get(p+8) == 0){
				free(st);
				st = nil;
			}else
				kstrdup(&st->lsapic.puids, (char*)p+16);
			break;
		case ASintsrc:
			st->intsrc.flags = l16get(p+2);
			st->type = p[4];
			st->intsrc.pid = p[5];
			st->intsrc.peid = p[6];
			st->intsrc.iosv = p[7];
			st->intsrc.intr = l32get(p+8);
			st->intsrc.any = l32get(p+12);
			break;
		case ASlx2apic:
			st->lx2apic.id = l32get(p+4);
			st->lx2apic.puid = l32get(p+12);
			if(l32get(p+8) == 0){
				free(st);
				st = nil;
			}
			break;
		case ASlx2nmi:
			st->lx2nmi.flags = l16get(p+2);
			st->lx2nmi.puid = l32get(p+4);
			st->lx2nmi.intr = p[8];
			break;
		default:
			print("unknown APIC structure\n");
			free(st);
			st = nil;
		}
		if(st != nil){
			*stl = st;
			stl = &st->next;
		}
	}

	dumpmadt(apics);
	return nil;	/* can be unmapped once parsed */
}
Esempio n. 17
0
static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
{
	struct f2fs_sb_info *sbi;
	struct f2fs_super_block *raw_super = NULL;
	struct buffer_head *raw_super_buf;
	struct inode *root;
	long err = -EINVAL;
	bool retry = true, need_fsck = false;
	char *options = NULL;
	int i;

try_onemore:
	/* allocate memory for f2fs-specific super block info */
	sbi = kzalloc(sizeof(struct f2fs_sb_info), GFP_KERNEL);
	if (!sbi)
		return -ENOMEM;

	/* set a block size */
	if (unlikely(!sb_set_blocksize(sb, F2FS_BLKSIZE))) {
		f2fs_msg(sb, KERN_ERR, "unable to set blocksize");
		goto free_sbi;
	}

	err = read_raw_super_block(sb, &raw_super, &raw_super_buf);
	if (err)
		goto free_sbi;

	sb->s_fs_info = sbi;
	/* init some FS parameters */
	sbi->active_logs = NR_CURSEG_TYPE;

	set_opt(sbi, BG_GC);
	set_opt(sbi, INLINE_DATA);

#ifdef CONFIG_F2FS_FS_XATTR
	set_opt(sbi, XATTR_USER);
#endif
#ifdef CONFIG_F2FS_FS_POSIX_ACL
	set_opt(sbi, POSIX_ACL);
#endif
	/* parse mount options */
	options = kstrdup((const char *)data, GFP_KERNEL);
	if (data && !options) {
		err = -ENOMEM;
		goto free_sb_buf;
	}

	err = parse_options(sb, options);
	if (err)
		goto free_options;

	sb->s_maxbytes = max_file_size(le32_to_cpu(raw_super->log_blocksize));
	sb->s_max_links = F2FS_LINK_MAX;
	get_random_bytes(&sbi->s_next_generation, sizeof(u32));

	sb->s_op = &f2fs_sops;
	sb->s_xattr = f2fs_xattr_handlers;
	sb->s_export_op = &f2fs_export_ops;
	sb->s_magic = F2FS_SUPER_MAGIC;
	sb->s_time_gran = 1;
	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
		(test_opt(sbi, POSIX_ACL) ? MS_POSIXACL : 0);
	memcpy(sb->s_uuid, raw_super->uuid, sizeof(raw_super->uuid));

	/* init f2fs-specific super block info */
	sbi->sb = sb;
	sbi->raw_super = raw_super;
	sbi->raw_super_buf = raw_super_buf;
	mutex_init(&sbi->gc_mutex);
	mutex_init(&sbi->writepages);
	mutex_init(&sbi->cp_mutex);
	init_rwsem(&sbi->node_write);
	clear_sbi_flag(sbi, SBI_POR_DOING);
	spin_lock_init(&sbi->stat_lock);

	init_rwsem(&sbi->read_io.io_rwsem);
	sbi->read_io.sbi = sbi;
	sbi->read_io.bio = NULL;
	for (i = 0; i < NR_PAGE_TYPE; i++) {
		init_rwsem(&sbi->write_io[i].io_rwsem);
		sbi->write_io[i].sbi = sbi;
		sbi->write_io[i].bio = NULL;
	}

	init_rwsem(&sbi->cp_rwsem);
	init_waitqueue_head(&sbi->cp_wait);
	init_sb_info(sbi);

	/* get an inode for meta space */
	sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi));
	if (IS_ERR(sbi->meta_inode)) {
		f2fs_msg(sb, KERN_ERR, "Failed to read F2FS meta data inode");
		err = PTR_ERR(sbi->meta_inode);
		goto free_options;
	}

	err = get_valid_checkpoint(sbi);
	if (err) {
		f2fs_msg(sb, KERN_ERR, "Failed to get valid F2FS checkpoint");
		goto free_meta_inode;
	}

	/* sanity checking of checkpoint */
	err = -EINVAL;
	if (sanity_check_ckpt(sbi)) {
		f2fs_msg(sb, KERN_ERR, "Invalid F2FS checkpoint");
		goto free_cp;
	}

	sbi->total_valid_node_count =
				le32_to_cpu(sbi->ckpt->valid_node_count);
	sbi->total_valid_inode_count =
				le32_to_cpu(sbi->ckpt->valid_inode_count);
	sbi->user_block_count = le64_to_cpu(sbi->ckpt->user_block_count);
	sbi->total_valid_block_count =
				le64_to_cpu(sbi->ckpt->valid_block_count);
	sbi->last_valid_block_count = sbi->total_valid_block_count;
	sbi->alloc_valid_block_count = 0;
	INIT_LIST_HEAD(&sbi->dir_inode_list);
	spin_lock_init(&sbi->dir_inode_lock);

	init_extent_cache_info(sbi);

	init_ino_entry_info(sbi);

	/* setup f2fs internal modules */
	err = build_segment_manager(sbi);
	if (err) {
		f2fs_msg(sb, KERN_ERR,
			"Failed to initialize F2FS segment manager");
		goto free_sm;
	}
	err = build_node_manager(sbi);
	if (err) {
		f2fs_msg(sb, KERN_ERR,
			"Failed to initialize F2FS node manager");
		goto free_nm;
	}

	build_gc_manager(sbi);

	/* get an inode for node space */
	sbi->node_inode = f2fs_iget(sb, F2FS_NODE_INO(sbi));
	if (IS_ERR(sbi->node_inode)) {
		f2fs_msg(sb, KERN_ERR, "Failed to read node inode");
		err = PTR_ERR(sbi->node_inode);
		goto free_nm;
	}

	/* if there are nt orphan nodes free them */
	recover_orphan_inodes(sbi);

	/* read root inode and dentry */
	root = f2fs_iget(sb, F2FS_ROOT_INO(sbi));
	if (IS_ERR(root)) {
		f2fs_msg(sb, KERN_ERR, "Failed to read root inode");
		err = PTR_ERR(root);
		goto free_node_inode;
	}
	if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
		iput(root);
		err = -EINVAL;
		goto free_node_inode;
	}

	sb->s_root = d_make_root(root); /* allocate root dentry */
	if (!sb->s_root) {
		err = -ENOMEM;
		goto free_root_inode;
	}

	err = f2fs_build_stats(sbi);
	if (err)
		goto free_root_inode;

	if (f2fs_proc_root)
		sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);

	if (sbi->s_proc)
		proc_create_data("segment_info", S_IRUGO, sbi->s_proc,
				 &f2fs_seq_segment_info_fops, sb);

	if (test_opt(sbi, DISCARD)) {
		struct request_queue *q = bdev_get_queue(sb->s_bdev);
		if (!blk_queue_discard(q))
			f2fs_msg(sb, KERN_WARNING,
					"mounting with \"discard\" option, but "
					"the device does not support discard");
	}

	sbi->s_kobj.kset = f2fs_kset;
	init_completion(&sbi->s_kobj_unregister);
	err = kobject_init_and_add(&sbi->s_kobj, &f2fs_ktype, NULL,
							"%s", sb->s_id);
	if (err)
		goto free_proc;

	/* recover fsynced data */
	if (!test_opt(sbi, DISABLE_ROLL_FORWARD)) {
		/*
		 * mount should be failed, when device has readonly mode, and
		 * previous checkpoint was not done by clean system shutdown.
		 */
		if (bdev_read_only(sb->s_bdev) &&
				!is_set_ckpt_flags(sbi->ckpt, CP_UMOUNT_FLAG)) {
			err = -EROFS;
			goto free_kobj;
		}

		if (need_fsck)
			set_sbi_flag(sbi, SBI_NEED_FSCK);

		err = recover_fsync_data(sbi);
		if (err) {
			need_fsck = true;
			f2fs_msg(sb, KERN_ERR,
				"Cannot recover all fsync data errno=%ld", err);
			goto free_kobj;
		}
	}

	/*
	 * If filesystem is not mounted as read-only then
	 * do start the gc_thread.
	 */
	if (test_opt(sbi, BG_GC) && !f2fs_readonly(sb)) {
		/* After POR, we can run background GC thread.*/
		err = start_gc_thread(sbi);
		if (err)
			goto free_kobj;
	}
	kfree(options);
	return 0;

free_kobj:
	kobject_del(&sbi->s_kobj);
free_proc:
	if (sbi->s_proc) {
		remove_proc_entry("segment_info", sbi->s_proc);
		remove_proc_entry(sb->s_id, f2fs_proc_root);
	}
	f2fs_destroy_stats(sbi);
free_root_inode:
	dput(sb->s_root);
	sb->s_root = NULL;
free_node_inode:
	iput(sbi->node_inode);
free_nm:
	destroy_node_manager(sbi);
free_sm:
	destroy_segment_manager(sbi);
free_cp:
	kfree(sbi->ckpt);
free_meta_inode:
	make_bad_inode(sbi->meta_inode);
	iput(sbi->meta_inode);
free_options:
	kfree(options);
free_sb_buf:
	brelse(raw_super_buf);
free_sbi:
	kfree(sbi);

	/* give only one another chance */
	if (retry) {
		retry = false;
		shrink_dcache_sb(sb);
		goto try_onemore;
	}
	return err;
}
Esempio n. 18
0
static int __devinit anatop_regulator_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct device_node *np = dev->of_node;
	struct regulator_desc *rdesc;
	struct regulator_dev *rdev;
	struct anatop_regulator *sreg;
	struct regulator_init_data *initdata;
	struct anatop *anatopmfd = dev_get_drvdata(pdev->dev.parent);
	struct regulator_config config = { };
	int ret = 0;

	initdata = of_get_regulator_init_data(dev, np);
	sreg = devm_kzalloc(dev, sizeof(*sreg), GFP_KERNEL);
	if (!sreg)
		return -ENOMEM;
	sreg->initdata = initdata;
	sreg->name = kstrdup(of_get_property(np, "regulator-name", NULL),
			     GFP_KERNEL);
	rdesc = &sreg->rdesc;
	memset(rdesc, 0, sizeof(*rdesc));
	rdesc->name = sreg->name;
	rdesc->ops = &anatop_rops;
	rdesc->type = REGULATOR_VOLTAGE;
	rdesc->owner = THIS_MODULE;
	sreg->mfd = anatopmfd;
	ret = of_property_read_u32(np, "anatop-reg-offset",
				   &sreg->control_reg);
	if (ret) {
		dev_err(dev, "no anatop-reg-offset property set\n");
		goto anatop_probe_end;
	}
	ret = of_property_read_u32(np, "anatop-vol-bit-width",
				   &sreg->vol_bit_width);
	if (ret) {
		dev_err(dev, "no anatop-vol-bit-width property set\n");
		goto anatop_probe_end;
	}
	ret = of_property_read_u32(np, "anatop-vol-bit-shift",
				   &sreg->vol_bit_shift);
	if (ret) {
		dev_err(dev, "no anatop-vol-bit-shift property set\n");
		goto anatop_probe_end;
	}
	ret = of_property_read_u32(np, "anatop-min-bit-val",
				   &sreg->min_bit_val);
	if (ret) {
		dev_err(dev, "no anatop-min-bit-val property set\n");
		goto anatop_probe_end;
	}
	ret = of_property_read_u32(np, "anatop-min-voltage",
				   &sreg->min_voltage);
	if (ret) {
		dev_err(dev, "no anatop-min-voltage property set\n");
		goto anatop_probe_end;
	}
	ret = of_property_read_u32(np, "anatop-max-voltage",
				   &sreg->max_voltage);
	if (ret) {
		dev_err(dev, "no anatop-max-voltage property set\n");
		goto anatop_probe_end;
	}

	rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage)
		/ 25000 + 1;
	rdesc->min_uV = sreg->min_voltage;
	rdesc->uV_step = 25000;

	config.dev = &pdev->dev;
	config.init_data = initdata;
	config.driver_data = sreg;
	config.of_node = pdev->dev.of_node;

	/* register regulator */
	rdev = regulator_register(rdesc, &config);
	if (IS_ERR(rdev)) {
		dev_err(dev, "failed to register %s\n",
			rdesc->name);
		ret = PTR_ERR(rdev);
		goto anatop_probe_end;
	}

	platform_set_drvdata(pdev, rdev);

anatop_probe_end:
	if (ret)
		kfree(sreg->name);

	return ret;
}
Esempio n. 19
0
/**
 * instructor - Piazza answer-editing thread.
 *
 * Each instructor thread should, for NCYCLES iterations, choose a random
 * Piazza question and then update the answer.  The answer should always
 * consist of a lowercase alphabetic character repeated 10 times, e.g.,
 *
 *    "aaaaaaaaaa"
 *
 * and each update should increment all ten characters (cycling back to a's
 * from z's if a question is updated enough times).
 *
 * After each update, (including the first update, in which you should create
 * the question and initialize the answer to all a's), the instructor should
 * print the answer string using piazza_print().
 *
 * TODO: Implement this.
 */
static void
instructor(void *p, unsigned long which)
{
  (void)p;
  (void)which;

  int i, n;
  char letter, *pos;

  for (i = 0; i < NCYCLES; ++i) {
    // Choose a random Piazza question.
    n = random() % NANSWERS;

    // If first instructor to see the question, initalize answers
    lock_acquire(creation_lock[n]);
    if (questions[n] == NULL) {
      questions[n] = kmalloc(sizeof(struct piazza_question));
      questions[n]->mutex = lock_create("mutex");
      questions[n]->readerQ = cv_create("readerQ");
      questions[n]->writerQ = cv_create("writerQ");
      questions[n]->readers = 0;
      questions[n]->writers = 0;
      questions[n]->active_writer = 0;

      const char *answer = "aaaaaaaaaa"; //TODO: have const here?
      questions[n]->pq_answer = kstrdup(answer);      

      lock_release(creation_lock[n]);

      // Print submitted answer
      piazza_print(n);
    }

    // Not the first instructor
    else{
      lock_release(creation_lock[n]);

      // Set up writer lock
      lock_acquire(questions[n]->mutex);
      questions[n]->writers++;
      while(!((questions[n]->readers == 0) && (questions[n]->active_writer == 0)))
        cv_wait(questions[n]->writerQ, questions[n]->mutex);
      questions[n]->active_writer++;
      lock_release(questions[n]->mutex);

      /* Start write */
      pos = questions[n]->pq_answer;
      letter = *pos;

      // Update answer
      if(letter != 'z'){
        while (*(pos) == letter) {
          (*pos)++;
          pos++;
        }        
      }

      // Loop answer back to A's
      else{
        while (*(pos) == letter) {
          *pos = 'a';
          pos++;
        }
      }
    
      // Print submitted answer
      piazza_print(n);

      /* End write */

      // Clean up writer lock
      lock_acquire(questions[n]->mutex);
      questions[n]->active_writer--;
      questions[n]->writers--;
      if(questions[n]->writers==0)
        cv_broadcast(questions[n]->readerQ, questions[n]->mutex);
      else
        cv_signal(questions[n]->writerQ, questions[n]->mutex);
      lock_release(questions[n]->mutex);
    }
  }
  // Exiting thread
  lock_acquire(thread_count_lock);
  if(++finished_thread_count == NSTUDENTS + NINSTRUCTORS){
    lock_release(thread_count_lock);
    V(driver_sem);
  }
  else
    lock_release(thread_count_lock);
}
Esempio n. 20
0
/**
 * e1000e_check_options - Range Checking for Command Line Parameters
 * @adapter: board private structure
 *
 * This routine checks all command line parameters for valid user
 * input.  If an invalid value is given, or if no user specified
 * value exists, a default value is used.  The final value is stored
 * in a variable in the adapter structure.
 **/
void e1000e_check_options(struct e1000_adapter *adapter)
{
	struct e1000_hw *hw = &adapter->hw;
	int bd = adapter->bd_number;

	if (bd >= E1000_MAX_NIC) {
		dev_notice(&adapter->pdev->dev,
			   "Warning: no configuration for board #%i\n", bd);
		dev_notice(&adapter->pdev->dev,
			   "Using defaults for all values\n");
	}

	{ /* Transmit Interrupt Delay */
		static const struct e1000_option opt = {
			.type = range_option,
			.name = "Transmit Interrupt Delay",
			.err  = "using default of "
				__MODULE_STRING(DEFAULT_TIDV),
			.def  = DEFAULT_TIDV,
			.arg  = { .r = { .min = MIN_TXDELAY,
					 .max = MAX_TXDELAY } }
		};

		if (num_TxIntDelay > bd) {
			adapter->tx_int_delay = TxIntDelay[bd];
			e1000_validate_option(&adapter->tx_int_delay, &opt,
					      adapter);
		} else {
			adapter->tx_int_delay = opt.def;
		}
	}
	{ /* Transmit Absolute Interrupt Delay */
		static const struct e1000_option opt = {
			.type = range_option,
			.name = "Transmit Absolute Interrupt Delay",
			.err  = "using default of "
				__MODULE_STRING(DEFAULT_TADV),
			.def  = DEFAULT_TADV,
			.arg  = { .r = { .min = MIN_TXABSDELAY,
					 .max = MAX_TXABSDELAY } }
		};

		if (num_TxAbsIntDelay > bd) {
			adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
			e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
					      adapter);
		} else {
			adapter->tx_abs_int_delay = opt.def;
		}
	}
	{ /* Receive Interrupt Delay */
		static struct e1000_option opt = {
			.type = range_option,
			.name = "Receive Interrupt Delay",
			.err  = "using default of "
				__MODULE_STRING(DEFAULT_RDTR),
			.def  = DEFAULT_RDTR,
			.arg  = { .r = { .min = MIN_RXDELAY,
					 .max = MAX_RXDELAY } }
		};

		if (num_RxIntDelay > bd) {
			adapter->rx_int_delay = RxIntDelay[bd];
			e1000_validate_option(&adapter->rx_int_delay, &opt,
					      adapter);
		} else {
			adapter->rx_int_delay = opt.def;
		}
	}
	{ /* Receive Absolute Interrupt Delay */
		static const struct e1000_option opt = {
			.type = range_option,
			.name = "Receive Absolute Interrupt Delay",
			.err  = "using default of "
				__MODULE_STRING(DEFAULT_RADV),
			.def  = DEFAULT_RADV,
			.arg  = { .r = { .min = MIN_RXABSDELAY,
					 .max = MAX_RXABSDELAY } }
		};

		if (num_RxAbsIntDelay > bd) {
			adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
			e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
					      adapter);
		} else {
			adapter->rx_abs_int_delay = opt.def;
		}
	}
	{ /* Interrupt Throttling Rate */
		static const struct e1000_option opt = {
			.type = range_option,
			.name = "Interrupt Throttling Rate (ints/sec)",
			.err  = "using default of "
				__MODULE_STRING(DEFAULT_ITR),
			.def  = DEFAULT_ITR,
			.arg  = { .r = { .min = MIN_ITR,
					 .max = MAX_ITR } }
		};

		if (num_InterruptThrottleRate > bd) {
			adapter->itr = InterruptThrottleRate[bd];

			/* Make sure a message is printed for non-special
			 * values. And in case of an invalid option, display
			 * warning, use default and go through itr/itr_setting
			 * adjustment logic below
			 */
			if ((adapter->itr > 4) &&
			    e1000_validate_option(&adapter->itr, &opt, adapter))
				adapter->itr = opt.def;
		} else {
			/* If no option specified, use default value and go
			 * through the logic below to adjust itr/itr_setting
			 */
			adapter->itr = opt.def;

			/* Make sure a message is printed for non-special
			 * default values
			 */
			if (adapter->itr > 4)
				dev_info(&adapter->pdev->dev,
					 "%s set to default %d\n", opt.name,
					 adapter->itr);
		}

		adapter->itr_setting = adapter->itr;
		switch (adapter->itr) {
		case 0:
			dev_info(&adapter->pdev->dev, "%s turned off\n",
				 opt.name);
			break;
		case 1:
			dev_info(&adapter->pdev->dev,
				 "%s set to dynamic mode\n", opt.name);
			adapter->itr = 20000;
			break;
		case 3:
			dev_info(&adapter->pdev->dev,
				 "%s set to dynamic conservative mode\n",
				 opt.name);
			adapter->itr = 20000;
			break;
		case 4:
			dev_info(&adapter->pdev->dev,
				 "%s set to simplified (2000-8000 ints) mode\n",
				 opt.name);
			break;
		default:
			/* Save the setting, because the dynamic bits
			 * change itr.
			 *
			 * Clear the lower two bits because
			 * they are used as control.
			 */
			adapter->itr_setting &= ~3;
			break;
		}
	}
	{ /* Interrupt Mode */
		static struct e1000_option opt = {
			.type = range_option,
			.name = "Interrupt Mode",
#ifndef CONFIG_PCI_MSI
			.err  = "defaulting to 0 (legacy)",
			.def  = E1000E_INT_MODE_LEGACY,
			.arg  = { .r = { .min = 0,
					 .max = 0 } }
#endif
		};

#ifdef CONFIG_PCI_MSI
		if (adapter->flags & FLAG_HAS_MSIX) {
			opt.err = kstrdup("defaulting to 2 (MSI-X)",
					  GFP_KERNEL);
			opt.def = E1000E_INT_MODE_MSIX;
			opt.arg.r.max = E1000E_INT_MODE_MSIX;
		} else {
			opt.err = kstrdup("defaulting to 1 (MSI)", GFP_KERNEL);
			opt.def = E1000E_INT_MODE_MSI;
			opt.arg.r.max = E1000E_INT_MODE_MSI;
		}

		if (!opt.err) {
			dev_err(&adapter->pdev->dev,
				"Failed to allocate memory\n");
			return;
		}
#endif

		if (num_IntMode > bd) {
			unsigned int int_mode = IntMode[bd];
			e1000_validate_option(&int_mode, &opt, adapter);
			adapter->int_mode = int_mode;
		} else {
			adapter->int_mode = opt.def;
		}

#ifdef CONFIG_PCI_MSI
		kfree(opt.err);
#endif
	}
	{ /* Smart Power Down */
		static const struct e1000_option opt = {
			.type = enable_option,
			.name = "PHY Smart Power Down",
			.err  = "defaulting to Disabled",
			.def  = OPTION_DISABLED
		};

		if (num_SmartPowerDownEnable > bd) {
			unsigned int spd = SmartPowerDownEnable[bd];
			e1000_validate_option(&spd, &opt, adapter);
			if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN)
			    && spd)
				adapter->flags |= FLAG_SMART_POWER_DOWN;
		}
	}
	{ /* CRC Stripping */
		static const struct e1000_option opt = {
			.type = enable_option,
			.name = "CRC Stripping",
			.err  = "defaulting to Enabled",
			.def  = OPTION_ENABLED
		};

		if (num_CrcStripping > bd) {
			unsigned int crc_stripping = CrcStripping[bd];
			e1000_validate_option(&crc_stripping, &opt, adapter);
			if (crc_stripping == OPTION_ENABLED) {
				adapter->flags2 |= FLAG2_CRC_STRIPPING;
				adapter->flags2 |= FLAG2_DFLT_CRC_STRIPPING;
			}
		} else {
			adapter->flags2 |= FLAG2_CRC_STRIPPING;
			adapter->flags2 |= FLAG2_DFLT_CRC_STRIPPING;
		}
	}
	{ /* Kumeran Lock Loss Workaround */
		static const struct e1000_option opt = {
			.type = enable_option,
			.name = "Kumeran Lock Loss Workaround",
			.err  = "defaulting to Enabled",
			.def  = OPTION_ENABLED
		};

		if (num_KumeranLockLoss > bd) {
			unsigned int kmrn_lock_loss = KumeranLockLoss[bd];
			e1000_validate_option(&kmrn_lock_loss, &opt, adapter);
			if (hw->mac.type == e1000_ich8lan)
				e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw,
								kmrn_lock_loss);
		} else {
			if (hw->mac.type == e1000_ich8lan)
				e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw,
								       opt.def);
		}
	}
	{ /* Write-protect NVM */
		static const struct e1000_option opt = {
			.type = enable_option,
			.name = "Write-protect NVM",
			.err  = "defaulting to Enabled",
			.def  = OPTION_ENABLED
		};

		if (adapter->flags & FLAG_IS_ICH) {
			if (num_WriteProtectNVM > bd) {
				unsigned int write_protect_nvm = WriteProtectNVM[bd];
				e1000_validate_option(&write_protect_nvm, &opt,
						      adapter);
				if (write_protect_nvm)
					adapter->flags |= FLAG_READ_ONLY_NVM;
			} else {
				if (opt.def)
					adapter->flags |= FLAG_READ_ONLY_NVM;
			}
		}
	}
}
Esempio n. 21
0
File: domain.c Progetto: Lyude/linux
static ssize_t boot_acl_store(struct device *dev, struct device_attribute *attr,
			      const char *buf, size_t count)
{
	struct tb *tb = container_of(dev, struct tb, dev);
	char *str, *s, *uuid_str;
	ssize_t ret = 0;
	uuid_t *acl;
	int i = 0;

	/*
	 * Make sure the value is not bigger than tb->nboot_acl * UUID
	 * length + commas and optional "\n". Also the smallest allowable
	 * string is tb->nboot_acl * ",".
	 */
	if (count > (UUID_STRING_LEN + 1) * tb->nboot_acl + 1)
		return -EINVAL;
	if (count < tb->nboot_acl - 1)
		return -EINVAL;

	str = kstrdup(buf, GFP_KERNEL);
	if (!str)
		return -ENOMEM;

	acl = kcalloc(tb->nboot_acl, sizeof(uuid_t), GFP_KERNEL);
	if (!acl) {
		ret = -ENOMEM;
		goto err_free_str;
	}

	uuid_str = strim(str);
	while ((s = strsep(&uuid_str, ",")) != NULL && i < tb->nboot_acl) {
		size_t len = strlen(s);

		if (len) {
			if (len != UUID_STRING_LEN) {
				ret = -EINVAL;
				goto err_free_acl;
			}
			ret = uuid_parse(s, &acl[i]);
			if (ret)
				goto err_free_acl;
		}

		i++;
	}

	if (s || i < tb->nboot_acl) {
		ret = -EINVAL;
		goto err_free_acl;
	}

	pm_runtime_get_sync(&tb->dev);

	if (mutex_lock_interruptible(&tb->lock)) {
		ret = -ERESTARTSYS;
		goto err_rpm_put;
	}
	ret = tb->cm_ops->set_boot_acl(tb, acl, tb->nboot_acl);
	if (!ret) {
		/* Notify userspace about the change */
		kobject_uevent(&tb->dev.kobj, KOBJ_CHANGE);
	}
	mutex_unlock(&tb->lock);

err_rpm_put:
	pm_runtime_mark_last_busy(&tb->dev);
	pm_runtime_put_autosuspend(&tb->dev);
err_free_acl:
	kfree(acl);
err_free_str:
	kfree(str);

	return ret ?: count;
}
Esempio n. 22
0
static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
{
	struct crypto_attr_type *algt;
	struct akcipher_instance *inst;
	struct pkcs1pad_inst_ctx *ctx;
	struct crypto_akcipher_spawn *spawn;
	struct akcipher_alg *rsa_alg;
	const char *rsa_alg_name;
	const char *hash_name;
	int err;

	algt = crypto_get_attr_type(tb);
	if (IS_ERR(algt))
		return PTR_ERR(algt);

	if ((algt->type ^ CRYPTO_ALG_TYPE_AKCIPHER) & algt->mask)
		return -EINVAL;

	rsa_alg_name = crypto_attr_alg_name(tb[1]);
	if (IS_ERR(rsa_alg_name))
		return PTR_ERR(rsa_alg_name);

	hash_name = crypto_attr_alg_name(tb[2]);
	if (IS_ERR(hash_name))
		hash_name = NULL;

	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
	if (!inst)
		return -ENOMEM;

	ctx = akcipher_instance_ctx(inst);
	spawn = &ctx->spawn;
	ctx->hash_name = hash_name ? kstrdup(hash_name, GFP_KERNEL) : NULL;

	crypto_set_spawn(&spawn->base, akcipher_crypto_instance(inst));
	err = crypto_grab_akcipher(spawn, rsa_alg_name, 0,
			crypto_requires_sync(algt->type, algt->mask));
	if (err)
		goto out_free_inst;

	rsa_alg = crypto_spawn_akcipher_alg(spawn);

	err = -ENAMETOOLONG;

	if (!hash_name) {
		if (snprintf(inst->alg.base.cra_name,
			     CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
			     rsa_alg->base.cra_name) >=
					CRYPTO_MAX_ALG_NAME ||
		    snprintf(inst->alg.base.cra_driver_name,
			     CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
			     rsa_alg->base.cra_driver_name) >=
					CRYPTO_MAX_ALG_NAME)
		goto out_drop_alg;
	} else {
		if (snprintf(inst->alg.base.cra_name,
			     CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s,%s)",
			     rsa_alg->base.cra_name, hash_name) >=
				CRYPTO_MAX_ALG_NAME ||
		    snprintf(inst->alg.base.cra_driver_name,
			     CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s,%s)",
			     rsa_alg->base.cra_driver_name, hash_name) >=
					CRYPTO_MAX_ALG_NAME)
		goto out_free_hash;
	}

	inst->alg.base.cra_flags = rsa_alg->base.cra_flags & CRYPTO_ALG_ASYNC;
	inst->alg.base.cra_priority = rsa_alg->base.cra_priority;
	inst->alg.base.cra_ctxsize = sizeof(struct pkcs1pad_ctx);

	inst->alg.init = pkcs1pad_init_tfm;
	inst->alg.exit = pkcs1pad_exit_tfm;

	inst->alg.encrypt = pkcs1pad_encrypt;
	inst->alg.decrypt = pkcs1pad_decrypt;
	inst->alg.sign = pkcs1pad_sign;
	inst->alg.verify = pkcs1pad_verify;
	inst->alg.set_pub_key = pkcs1pad_set_pub_key;
	inst->alg.set_priv_key = pkcs1pad_set_priv_key;
	inst->alg.max_size = pkcs1pad_get_max_size;
	inst->alg.reqsize = sizeof(struct pkcs1pad_request) + rsa_alg->reqsize;

	inst->free = pkcs1pad_free;

	err = akcipher_register_instance(tmpl, inst);
	if (err)
		goto out_free_hash;

	return 0;

out_free_hash:
	kfree(ctx->hash_name);
out_drop_alg:
	crypto_drop_akcipher(spawn);
out_free_inst:
	kfree(inst);
	return err;
}
Esempio n. 23
0
static int blk_trace_synthesize_old_trace(struct trace_iterator *iter)
{
	struct trace_seq *s = &iter->seq;
	struct blk_io_trace *t = (struct blk_io_trace *)iter->ent;
	const int offset = offsetof(struct blk_io_trace, sector);
	struct blk_io_trace old = {
		.magic	  = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION,
		.time     = iter->ts,
	};

	if (!trace_seq_putmem(s, &old, offset))
		return 0;
	return trace_seq_putmem(s, &t->sector,
				sizeof(old) - offset + t->pdu_len);
}

static enum print_line_t
blk_trace_event_print_binary(struct trace_iterator *iter, int flags)
{
	return blk_trace_synthesize_old_trace(iter) ?
			TRACE_TYPE_HANDLED : TRACE_TYPE_PARTIAL_LINE;
}

static enum print_line_t blk_tracer_print_line(struct trace_iterator *iter)
{
	if (!(blk_tracer_flags.val & TRACE_BLK_OPT_CLASSIC))
		return TRACE_TYPE_UNHANDLED;

	return print_one_line(iter, true);
}

static int blk_tracer_set_flag(u32 old_flags, u32 bit, int set)
{
	/* don't output context-info for blk_classic output */
	if (bit == TRACE_BLK_OPT_CLASSIC) {
		if (set)
			trace_flags &= ~TRACE_ITER_CONTEXT_INFO;
		else
			trace_flags |= TRACE_ITER_CONTEXT_INFO;
	}
	return 0;
}

static struct tracer blk_tracer __read_mostly = {
	.name		= "blk",
	.init		= blk_tracer_init,
	.reset		= blk_tracer_reset,
	.start		= blk_tracer_start,
	.stop		= blk_tracer_stop,
	.print_header	= blk_tracer_print_header,
	.print_line	= blk_tracer_print_line,
	.flags		= &blk_tracer_flags,
	.set_flag	= blk_tracer_set_flag,
};

static struct trace_event trace_blk_event = {
	.type		= TRACE_BLK,
	.trace		= blk_trace_event_print,
	.binary		= blk_trace_event_print_binary,
};

static int __init init_blk_tracer(void)
{
	if (!register_ftrace_event(&trace_blk_event)) {
		pr_warning("Warning: could not register block events\n");
		return 1;
	}

	if (register_tracer(&blk_tracer) != 0) {
		pr_warning("Warning: could not register the block tracer\n");
		unregister_ftrace_event(&trace_blk_event);
		return 1;
	}

	return 0;
}

device_initcall(init_blk_tracer);

static int blk_trace_remove_queue(struct request_queue *q)
{
	struct blk_trace *bt;

	bt = xchg(&q->blk_trace, NULL);
	if (bt == NULL)
		return -EINVAL;

	if (atomic_dec_and_test(&blk_probes_ref))
		blk_unregister_tracepoints();

	blk_trace_free(bt);
	return 0;
}

/*
 * Setup everything required to start tracing
 */
static int blk_trace_setup_queue(struct request_queue *q,
				 struct block_device *bdev)
{
	struct blk_trace *old_bt, *bt = NULL;
	int ret = -ENOMEM;

	bt = kzalloc(sizeof(*bt), GFP_KERNEL);
	if (!bt)
		return -ENOMEM;

	bt->msg_data = __alloc_percpu(BLK_TN_MAX_MSG, __alignof__(char));
	if (!bt->msg_data)
		goto free_bt;

	bt->dev = bdev->bd_dev;
	bt->act_mask = (u16)-1;

	blk_trace_setup_lba(bt, bdev);

	old_bt = xchg(&q->blk_trace, bt);
	if (old_bt != NULL) {
		(void)xchg(&q->blk_trace, old_bt);
		ret = -EBUSY;
		goto free_bt;
	}

	if (atomic_inc_return(&blk_probes_ref) == 1)
		blk_register_tracepoints();
	return 0;

free_bt:
	blk_trace_free(bt);
	return ret;
}

/*
 * sysfs interface to enable and configure tracing
 */

static ssize_t sysfs_blk_trace_attr_show(struct device *dev,
					 struct device_attribute *attr,
					 char *buf);
static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
					  struct device_attribute *attr,
					  const char *buf, size_t count);
#define BLK_TRACE_DEVICE_ATTR(_name) \
	DEVICE_ATTR(_name, S_IRUGO | S_IWUSR, \
		    sysfs_blk_trace_attr_show, \
		    sysfs_blk_trace_attr_store)

static BLK_TRACE_DEVICE_ATTR(enable);
static BLK_TRACE_DEVICE_ATTR(act_mask);
static BLK_TRACE_DEVICE_ATTR(pid);
static BLK_TRACE_DEVICE_ATTR(start_lba);
static BLK_TRACE_DEVICE_ATTR(end_lba);

static struct attribute *blk_trace_attrs[] = {
	&dev_attr_enable.attr,
	&dev_attr_act_mask.attr,
	&dev_attr_pid.attr,
	&dev_attr_start_lba.attr,
	&dev_attr_end_lba.attr,
	NULL
};

struct attribute_group blk_trace_attr_group = {
	.name  = "trace",
	.attrs = blk_trace_attrs,
};

static const struct {
	int mask;
	const char *str;
} mask_maps[] = {
	{ BLK_TC_READ,		"read"		},
	{ BLK_TC_WRITE,		"write"		},
	{ BLK_TC_FLUSH,		"flush"		},
	{ BLK_TC_SYNC,		"sync"		},
	{ BLK_TC_QUEUE,		"queue"		},
	{ BLK_TC_REQUEUE,	"requeue"	},
	{ BLK_TC_ISSUE,		"issue"		},
	{ BLK_TC_COMPLETE,	"complete"	},
	{ BLK_TC_FS,		"fs"		},
	{ BLK_TC_PC,		"pc"		},
	{ BLK_TC_AHEAD,		"ahead"		},
	{ BLK_TC_META,		"meta"		},
	{ BLK_TC_DISCARD,	"discard"	},
	{ BLK_TC_DRV_DATA,	"drv_data"	},
	{ BLK_TC_FUA,		"fua"		},
};

static int blk_trace_str2mask(const char *str)
{
	int i;
	int mask = 0;
	char *buf, *s, *token;

	buf = kstrdup(str, GFP_KERNEL);
	if (buf == NULL)
		return -ENOMEM;
	s = strstrip(buf);

	while (1) {
		token = strsep(&s, ",");
		if (token == NULL)
			break;

		if (*token == '\0')
			continue;

		for (i = 0; i < ARRAY_SIZE(mask_maps); i++) {
			if (strcasecmp(token, mask_maps[i].str) == 0) {
				mask |= mask_maps[i].mask;
				break;
			}
		}
		if (i == ARRAY_SIZE(mask_maps)) {
			mask = -EINVAL;
			break;
		}
	}
	kfree(buf);

	return mask;
}

static ssize_t blk_trace_mask2str(char *buf, int mask)
{
	int i;
	char *p = buf;

	for (i = 0; i < ARRAY_SIZE(mask_maps); i++) {
		if (mask & mask_maps[i].mask) {
			p += sprintf(p, "%s%s",
				    (p == buf) ? "" : ",", mask_maps[i].str);
		}
	}
	*p++ = '\n';

	return p - buf;
}

static struct request_queue *blk_trace_get_queue(struct block_device *bdev)
{
	if (bdev->bd_disk == NULL)
		return NULL;

	return bdev_get_queue(bdev);
}

static ssize_t sysfs_blk_trace_attr_show(struct device *dev,
					 struct device_attribute *attr,
					 char *buf)
{
	struct hd_struct *p = dev_to_part(dev);
	struct request_queue *q;
	struct block_device *bdev;
	ssize_t ret = -ENXIO;

	lock_kernel();
	bdev = bdget(part_devt(p));
	if (bdev == NULL)
		goto out_unlock_kernel;

	q = blk_trace_get_queue(bdev);
	if (q == NULL)
		goto out_bdput;

	mutex_lock(&bdev->bd_mutex);

	if (attr == &dev_attr_enable) {
		ret = sprintf(buf, "%u\n", !!q->blk_trace);
		goto out_unlock_bdev;
	}

	if (q->blk_trace == NULL)
		ret = sprintf(buf, "disabled\n");
	else if (attr == &dev_attr_act_mask)
		ret = blk_trace_mask2str(buf, q->blk_trace->act_mask);
	else if (attr == &dev_attr_pid)
		ret = sprintf(buf, "%u\n", q->blk_trace->pid);
	else if (attr == &dev_attr_start_lba)
		ret = sprintf(buf, "%llu\n", q->blk_trace->start_lba);
	else if (attr == &dev_attr_end_lba)
		ret = sprintf(buf, "%llu\n", q->blk_trace->end_lba);

out_unlock_bdev:
	mutex_unlock(&bdev->bd_mutex);
out_bdput:
	bdput(bdev);
out_unlock_kernel:
	unlock_kernel();
	return ret;
}

static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
					  struct device_attribute *attr,
					  const char *buf, size_t count)
{
	struct block_device *bdev;
	struct request_queue *q;
	struct hd_struct *p;
	u64 value;
	ssize_t ret = -EINVAL;

	if (count == 0)
		goto out;

	if (attr == &dev_attr_act_mask) {
		if (sscanf(buf, "%llx", &value) != 1) {
			/* Assume it is a list of trace category names */
			ret = blk_trace_str2mask(buf);
			if (ret < 0)
				goto out;
			value = ret;
		}
	} else if (sscanf(buf, "%llu", &value) != 1)
		goto out;

	ret = -ENXIO;

	lock_kernel();
	p = dev_to_part(dev);
	bdev = bdget(part_devt(p));
	if (bdev == NULL)
		goto out_unlock_kernel;

	q = blk_trace_get_queue(bdev);
	if (q == NULL)
		goto out_bdput;

	mutex_lock(&bdev->bd_mutex);

	if (attr == &dev_attr_enable) {
		if (value)
			ret = blk_trace_setup_queue(q, bdev);
		else
			ret = blk_trace_remove_queue(q);
		goto out_unlock_bdev;
	}

	ret = 0;
	if (q->blk_trace == NULL)
		ret = blk_trace_setup_queue(q, bdev);

	if (ret == 0) {
		if (attr == &dev_attr_act_mask)
			q->blk_trace->act_mask = value;
		else if (attr == &dev_attr_pid)
			q->blk_trace->pid = value;
		else if (attr == &dev_attr_start_lba)
			q->blk_trace->start_lba = value;
		else if (attr == &dev_attr_end_lba)
			q->blk_trace->end_lba = value;
	}

out_unlock_bdev:
	mutex_unlock(&bdev->bd_mutex);
out_bdput:
	bdput(bdev);
out_unlock_kernel:
	unlock_kernel();
out:
	return ret ? ret : count;
}

int blk_trace_init_sysfs(struct device *dev)
{
	return sysfs_create_group(&dev->kobj, &blk_trace_attr_group);
}

void blk_trace_remove_sysfs(struct device *dev)
{
	sysfs_remove_group(&dev->kobj, &blk_trace_attr_group);
}
static int msm_ahci_parse_clock_info(struct msm_ahci_host *host)
{
	int ret = 0;
	int cnt;
	int i;
	struct device *dev = host->ahci_pdev->dev.parent;
	struct device_node *np = dev->of_node;
	char *name;
	u32 *clkfreq = NULL;
	struct msm_ahci_clk_info *clki;

	if (!np)
		goto out;

	INIT_LIST_HEAD(&host->clk_list_head);

	cnt = of_property_count_strings(np, "clock-names");
	if (!cnt || (cnt == -EINVAL)) {
		dev_info(dev, "%s: Unable to find clocks, assuming enabled\n",
				__func__);
	} else if (cnt < 0) {
		dev_err(dev, "%s: count clock strings failed, err %d\n",
				__func__, cnt);
		ret = cnt;
	}

	if (cnt <= 0)
		goto out;

	clkfreq = kzalloc(cnt * sizeof(*clkfreq), GFP_KERNEL);
	if (!clkfreq) {
		ret = -ENOMEM;
		dev_err(dev, "%s: memory alloc failed\n", __func__);
		goto out;
	}

	ret = of_property_read_u32_array(np,
			"max-clock-frequency-hz", clkfreq, cnt);
	if (ret && (ret != -EINVAL)) {
		dev_err(dev, "%s: invalid max-clock-frequency-hz property, %d\n",
				__func__, ret);
		goto out;
	}

	for (i = 0; i < cnt; i++) {
		ret = of_property_read_string_index(np,
				"clock-names", i, (const char **)&name);
		if (ret)
			goto out;

		clki = devm_kzalloc(dev, sizeof(*clki), GFP_KERNEL);
		if (!clki) {
			ret = -ENOMEM;
			goto out;
		}

		clki->max_freq = clkfreq[i];
		clki->name = kstrdup(name, GFP_KERNEL);
		list_add_tail(&clki->list, &host->clk_list_head);
	}
out:
	kfree(clkfreq);
	return ret;
}
Esempio n. 25
0
void
kforkexecac(Proc *p, int core, char *ufile, char **argv)
{
	Mach *m = machp();
	Khdr hdr;
	Tos *tos;
	Chan *chan;
	int argc, i, n, sno;
	char *a, *elem, *file, *args;
	int32_t hdrsz, magic, textsz, datasz, bsssz;
	uintptr_t textlim, datalim, bsslim, entry, tbase, tsize, dbase, dsize, bbase, bsize, sbase, ssize, stack;
	Mach *mp;
	//	static Pgrp *kpgrp;

	panic("kexec not done\n");
	// XXX: since this is kernel code we can't do attachimage,
	// we should be reading the file into kernel memory.
	// this only matters if we are using ufile.
	// YYY: look at dev reboot for help.

	file = nil;
	elem = nil;
	chan = nil;
	mp = nil;

	USED(chan);

	if(waserror()){
		DBG("kforkexecac: failing: %s\n", m->externup->errstr);
		if(file)
			free(file);
		if(elem)
			free(elem);
		if(chan)
			cclose(chan);
		if(core > 0 && mp != nil)
			mp->proc = nil;
		if(core != 0)
			p->ac = nil;
		nexterror();
	}

	if(core != 0)
		p->ac = getac(p, core);

	argc = 0;
	if(ufile != nil){
		panic("ufile not implemented yet");
		file = validnamedup(ufile, 1);
		DBG("kforkexecac: up %#p file %s\n", m->externup, file);
		chan = namec(file, Aopen, OEXEC, 0);
		kstrdup(&elem, m->externup->genbuf);

		hdrsz = chan->dev->read(chan, &hdr, sizeof(Khdr), 0);
		DBG("wrote ufile\n");

		if(hdrsz < 2)
			error(Ebadexec);
	}else{
		/* somebody already wrote in our text segment */
		for(sno = 0; sno < NSEG; sno++)
			if(p->seg[sno] != nil)
				if((p->seg[sno]->type & SG_EXEC) != 0)
					break;
		if(sno == NSEG)
			error("kforkexecac: no text segment!");
		hdr = *(Khdr*)p->seg[sno]->base;
		hdrsz = sizeof(Khdr);
	}

//	p = (char*)&hdr;
	magic = l2be(hdr.magic);
	DBG("badexec3\n");

	if(hdrsz != sizeof(Khdr) || magic != AOUT_MAGIC)
		error(Ebadexec);
	if(magic & HDR_MAGIC){
		entry = vl2be(hdr.hdr[0]);
		hdrsz = sizeof(Khdr);
	}
	else{
		entry = l2be(hdr.entry);
		hdrsz = sizeof(Exec);
	}

	textsz = l2be(hdr.text);
	datasz = l2be(hdr.data);
	bsssz = l2be(hdr.bss);

	panic("aki broke it before it even got working.");
/* TODO(aki): figure out what to do with this.
	tbase = p->seg[TSEG]->base;
	tsize = tbase - p->seg[TSEG]->top;
	dbase = p->seg[DSEG]->base;
	dsize = dbase - p->seg[DSEG]->top;
	bbase = p->seg[BSEG]->base;
	bsize = bbase - p->seg[BSEG]->top;
	sbase = p->seg[SSEG]->base;
	ssize = sbase - p->seg[SSEG]->top;
*/

	// XXX: we are no longer contiguous.
	textlim = ROUNDUP(hdrsz+textsz, BIGPGSZ);
	// XXX: we are going to be at least two pages here.
	datalim = BIGPGROUND(datasz);
	bsslim = BIGPGROUND(datalim+bsssz);

	// XXX: this is pretty fragile
	memmove((void*)dbase, (void*)(entry+textsz), datasz);
	DBG("writing data dbase %#p tbase %#p textsz %ld datasz %ld\n", dbase, tbase, textsz, datasz);
//	memmove((void*)dbase, (void*)"testing data", 13);
	/*
	 * Check the binary header for consistency,
	 * e.g. the entry point is within the text segment and
	 * the segments don't overlap each other.
	 */
	// XXX: max instruction size on amd64 is 15 bytes provide a check for consistency.
	DBG("kexec: entry %#p tbase %#p hdrsz %ld  textsz %ld\n", entry, tbase, hdrsz, textsz);
	if(entry < tbase+hdrsz || entry >= tbase+hdrsz+textsz)
		error(Ebadexec);
	// XXX: what about the kernel stack we are making here?
	DBG("kexec: testing if sizes overflow limits\n");
	if(textsz >= textlim || datasz > datalim || bsssz > bsslim)
		error(Ebadexec);
	DBG("kexec: do the top of the segments overflow limits?\n");
	if(textlim >= tbase+tsize || datalim >= dbase+dsize || bsslim >= bbase+bsize)
		error(Ebadexec);

	DBG("kexec: is bss below data?\n");
	if(bsslim < datalim)
		error(Ebadexec);
	/*
	Interesting thought, the previously allocated segments for
	data and text are shared and constant.  The BSS and the stack
	are not.  What you really want is the ability to make an
	executable text and data and then create child executables on
	top of that.  This will lower external fragmentation and allow
	a bunch of communicating shared memory processes (ie.  go) in
	kernel space.

	Fundamentally this means that the allocation of the text and
	the data should be separate from the bss and the stack.  This
	will require that you change the linkers as well to allow the
	separation of data and bss sections.
	*/

	/*
	 * Stack is a pointer into the temporary stack
	 * segment, and will move as items are pushed.
	 */

	 // need to work something out here with the stack.
	stack = sbase+ssize-sizeof(Tos);


	 /*
	  * XXX: When we are linking this how do we set the tos? We will need to change trap right?
	  */
	tos = (Tos*)stack;
	tos->cyclefreq = m->cyclefreq;
	cycles((uint64_t*)&tos->pcycles);
	tos->pcycles = -tos->pcycles;
	tos->kcycles = tos->pcycles;
	tos->clock = 0;

	DBG("kexec: argument processing\n");
	if(0)
	for(i = 0;; i++, argv++){
		a = *(char**)validaddr(argv, sizeof(char**), 0);
		if(a == nil)
			break;
		a = validaddr(a, 1, 0);
		n = ((char*)vmemchr(a, 0, 0x7fffffff) - a) + 1;

		if(argc > 0 && i == 0)
			continue;

		stack -= n;
		if(stack < sbase+ssize-4096)
			error(Enovmem);
		args = UINT2PTR(stack);
		memmove(args, a, n);
		args[n-1] = 0;
		argc++;
	}
	// DBG("kexec: ensuring we have argc\n");
	if(0)
	if(argc < 1)
		error(Ebadexec);

	a = args = UINT2PTR(stack);
	stack = sysexecstack(stack, argc);
	// XXX: look through math on this. look at ../../9/port/ exec.c
	// YYY: this looks like a Jimism for 9k.
	// DBG("kexec: ensuring the stack \n");
	if(0)
	if(stack-(argc+1)*sizeof(char**)-BIGPGSZ < sbase+ssize-4096)
		error(Ebadexec);

	argv = (char**)stack;
	*--argv = nil;
	// XXX: replace USTKTOP with a new variable representing the top of stack.
	if(0)
	for(i = 0; i < argc; i++){
		*--argv = args + (USTKTOP-sbase+ssize);
		args += strlen(args) + 1;
	}

	DBG("argsing\n");
	n = args - a;
	if(0)
	if(n <= 0)
		error(Egreg);
	if(n > 128)
		n = 128;
	DBG("kexec: allocating args\n");
	// XXX: hangs in smalloc, not sure why.
//	args = smalloc(n);
//	if(waserror()){
//		DBG("erroring\n");
//		free(args);
//		nexterror();
//	}
//	DBG("kexec: moving args\n");
//	memmove(args, a, n);
//	if(0)
//	while(n > 0 && (args[n-1] & 0xc0) == 0x80)
//		n--;
//	args[n-1] = '\0';

	kstrdup(&p->text, "kexecproc");
	p->args = nil;
	//elem;
//	elem = nil;
//	p->args = args;
//	p->nargs = n;
	poperror();				/* p (m->externup->args) */





/*
	qlock(&p->debug);

	sysprocsetup(p);
	qunlock(&p->debug);
*/

	// why is this sched and not ureg?
	p->sched.pc = entry;
	// the real question here is how do you set up the stack?
	p->sched.sp = PTR2UINT(stack-BY2SE);
	p->sched.sp = STACKALIGN(p->sched.sp);


	// XXX: what does it imply if you have a kproc that runs on an ac?
	if(core > 0){
		DBG("kexec: coring %d\n", core);
		mp = p->ac;
		mp->icc->flushtlb = 1;
		mp->icc->rc = ICCOK;

		DBG("kexec: exotic proc on cpu%d\n", mp->machno);
		qlock(&p->debug);
		if(waserror()){
			DBG("kexec: had error");
			qunlock(&p->debug);
			nexterror();
		}
		p->nicc++;
		p->state = Exotic;
		p->psstate = 0;
		DBG("kexec: unlocking");
		qunlock(&p->debug);
		poperror();
		mfence();
		mp->icc->fn = (void*)entry;
		sched();
	}else{
		DBG("kexec: readying\n");
		ready(p);
		p->newtlb = 1;
		mmuflush();
	}
	DBG("kforkexecac up %#p done\n"
		"textsz %lx datasz %lx bsssz %lx hdrsz %lx\n"
		"textlim %ullx datalim %ullx bsslim %ullx\n", m->externup,
		textsz, datasz, bsssz, hdrsz, textlim, datalim, bsslim);
}
Esempio n. 26
0
static int ufshcd_populate_vreg(struct device *dev, const char *name,
		struct ufs_vreg **out_vreg)
{
	int ret = 0;
	char prop_name[MAX_PROP_SIZE];
	struct ufs_vreg *vreg = NULL;
	struct device_node *np = dev->of_node;

	if (!np) {
		dev_err(dev, "%s: non DT initialization\n", __func__);
		goto out;
	}

	snprintf(prop_name, MAX_PROP_SIZE, "%s-supply", name);
	if (!of_parse_phandle(np, prop_name, 0)) {
		dev_info(dev, "%s: Unable to find %s regulator, assuming enabled\n",
				__func__, prop_name);
		goto out;
	}

	vreg = devm_kzalloc(dev, sizeof(*vreg), GFP_KERNEL);
	if (!vreg)
		return -ENOMEM;

	vreg->name = kstrdup(name, GFP_KERNEL);

	/* if fixed regulator no need further initialization */
	snprintf(prop_name, MAX_PROP_SIZE, "%s-fixed-regulator", name);
	if (of_property_read_bool(np, prop_name))
		goto out;

	snprintf(prop_name, MAX_PROP_SIZE, "%s-max-microamp", name);
	ret = of_property_read_u32(np, prop_name, &vreg->max_uA);
	if (ret) {
		dev_err(dev, "%s: unable to find %s err %d\n",
				__func__, prop_name, ret);
		goto out;
	}

	vreg->min_uA = 0;
	if (!strcmp(name, "vcc")) {
		if (of_property_read_bool(np, "vcc-supply-1p8")) {
			vreg->min_uV = UFS_VREG_VCC_1P8_MIN_UV;
			vreg->max_uV = UFS_VREG_VCC_1P8_MAX_UV;
		} else {
			vreg->min_uV = UFS_VREG_VCC_MIN_UV;
			vreg->max_uV = UFS_VREG_VCC_MAX_UV;
		}
	} else if (!strcmp(name, "vccq")) {
		vreg->min_uV = UFS_VREG_VCCQ_MIN_UV;
		vreg->max_uV = UFS_VREG_VCCQ_MAX_UV;
	} else if (!strcmp(name, "vccq2")) {
		vreg->min_uV = UFS_VREG_VCCQ2_MIN_UV;
		vreg->max_uV = UFS_VREG_VCCQ2_MAX_UV;
	}

	goto out;

out:
	if (!ret)
		*out_vreg = vreg;
	return ret;
}
Esempio n. 27
0
/**
 * netlbl_cfg_unlbl_map_add - Add a new unlabeled mapping
 * @domain: the domain mapping to add
 * @family: address family
 * @addr: IP address
 * @mask: IP address mask
 * @audit_info: NetLabel audit information
 *
 * Description:
 * Adds a new unlabeled NetLabel/LSM domain mapping.  A @domain value of NULL
 * causes a new default domain mapping to be added.  Returns zero on success,
 * negative values on failure.
 *
 */
int netlbl_cfg_unlbl_map_add(const char *domain,
			     u16 family,
			     const void *addr,
			     const void *mask,
			     struct netlbl_audit *audit_info)
{
	int ret_val = -ENOMEM;
	struct netlbl_dom_map *entry;
	struct netlbl_domaddr_map *addrmap = NULL;
	struct netlbl_domaddr4_map *map4 = NULL;
	struct netlbl_domaddr6_map *map6 = NULL;
	const struct in_addr *addr4, *mask4;
	const struct in6_addr *addr6, *mask6;

	entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
	if (entry == NULL)
		return -ENOMEM;
	if (domain != NULL) {
		entry->domain = kstrdup(domain, GFP_ATOMIC);
		if (entry->domain == NULL)
			goto cfg_unlbl_map_add_failure;
	}

	if (addr == NULL && mask == NULL)
		entry->type = NETLBL_NLTYPE_UNLABELED;
	else if (addr != NULL && mask != NULL) {
		addrmap = kzalloc(sizeof(*addrmap), GFP_ATOMIC);
		if (addrmap == NULL)
			goto cfg_unlbl_map_add_failure;
		INIT_LIST_HEAD(&addrmap->list4);
		INIT_LIST_HEAD(&addrmap->list6);

		switch (family) {
		case AF_INET:
			addr4 = addr;
			mask4 = mask;
			map4 = kzalloc(sizeof(*map4), GFP_ATOMIC);
			if (map4 == NULL)
				goto cfg_unlbl_map_add_failure;
			map4->type = NETLBL_NLTYPE_UNLABELED;
			map4->list.addr = addr4->s_addr & mask4->s_addr;
			map4->list.mask = mask4->s_addr;
			map4->list.valid = 1;
			ret_val = netlbl_af4list_add(&map4->list,
						     &addrmap->list4);
			if (ret_val != 0)
				goto cfg_unlbl_map_add_failure;
			break;
		case AF_INET6:
			addr6 = addr;
			mask6 = mask;
			map6 = kzalloc(sizeof(*map6), GFP_ATOMIC);
			if (map6 == NULL)
				goto cfg_unlbl_map_add_failure;
			map6->type = NETLBL_NLTYPE_UNLABELED;
			ipv6_addr_copy(&map6->list.addr, addr6);
			map6->list.addr.s6_addr32[0] &= mask6->s6_addr32[0];
			map6->list.addr.s6_addr32[1] &= mask6->s6_addr32[1];
			map6->list.addr.s6_addr32[2] &= mask6->s6_addr32[2];
			map6->list.addr.s6_addr32[3] &= mask6->s6_addr32[3];
			ipv6_addr_copy(&map6->list.mask, mask6);
			map6->list.valid = 1;
			ret_val = netlbl_af4list_add(&map4->list,
						     &addrmap->list4);
			if (ret_val != 0)
				goto cfg_unlbl_map_add_failure;
			break;
		default:
			goto cfg_unlbl_map_add_failure;
			break;
		}

		entry->type_def.addrsel = addrmap;
		entry->type = NETLBL_NLTYPE_ADDRSELECT;
	} else {
		ret_val = -EINVAL;
		goto cfg_unlbl_map_add_failure;
	}

	ret_val = netlbl_domhsh_add(entry, audit_info);
	if (ret_val != 0)
		goto cfg_unlbl_map_add_failure;

	return 0;

cfg_unlbl_map_add_failure:
	kfree(entry->domain);
	kfree(entry);
	kfree(addrmap);
	kfree(map4);
	kfree(map6);
	return ret_val;
}
Esempio n. 28
0
static int ufshcd_parse_clock_info(struct ufs_hba *hba)
{
	int ret = 0;
	int cnt;
	int i;
	struct device *dev = hba->dev;
	struct device_node *np = dev->of_node;
	char *name;
	u32 *clkfreq = NULL;
	struct ufs_clk_info *clki;
	int len = 0;
	size_t sz = 0;

	if (!np)
		goto out;

	INIT_LIST_HEAD(&hba->clk_list_head);

	cnt = of_property_count_strings(np, "clock-names");
	if (!cnt || (cnt == -EINVAL)) {
		dev_info(dev, "%s: Unable to find clocks, assuming enabled\n",
				__func__);
	} else if (cnt < 0) {
		dev_err(dev, "%s: count clock strings failed, err %d\n",
				__func__, cnt);
		ret = cnt;
	}

	if (cnt <= 0)
		goto out;

	if (!of_get_property(np, "freq-table-hz", &len)) {
		dev_info(dev, "freq-table-hz property not specified\n");
		goto out;
	}

	if (len <= 0)
		goto out;

	sz = len / sizeof(*clkfreq);
	if (sz != 2 * cnt) {
		dev_err(dev, "%s len mismatch\n", "freq-table-hz");
		ret = -EINVAL;
		goto out;
	}

	clkfreq = devm_kzalloc(dev, sz * sizeof(*clkfreq),
			GFP_KERNEL);
	if (!clkfreq) {
		ret = -ENOMEM;
		goto out;
	}

	ret = of_property_read_u32_array(np, "freq-table-hz",
			clkfreq, sz);
	if (ret && (ret != -EINVAL)) {
		dev_err(dev, "%s: error reading array %d\n",
				"freq-table-hz", ret);
		return ret;
	}

	for (i = 0; i < sz; i += 2) {
		ret = of_property_read_string_index(np,
				"clock-names", i/2, (const char **)&name);
		if (ret)
			goto out;

		clki = devm_kzalloc(dev, sizeof(*clki), GFP_KERNEL);
		if (!clki) {
			ret = -ENOMEM;
			goto out;
		}

		clki->min_freq = clkfreq[i];
		clki->max_freq = clkfreq[i+1];
		clki->name = kstrdup(name, GFP_KERNEL);
		dev_dbg(dev, "%s: min %u max %u name %s\n", "freq-table-hz",
				clki->min_freq, clki->max_freq, clki->name);
		list_add_tail(&clki->list, &hba->clk_list_head);
	}
out:
	return ret;
}
Esempio n. 29
0
/*
 *  create the first process
 */
void
userinit(void)
{
	Proc *p;
	Segment *s;
	KMap *k;
	Page *pg;

	/* no processes yet */
	up = nil;

	p = newproc();
	p->pgrp = newpgrp();
	p->egrp = smalloc(sizeof(Egrp));
	p->egrp->ref = 1;
	p->fgrp = dupfgrp(nil);
	p->rgrp = newrgrp();
	p->procmode = 0640;

	kstrdup(&eve, "");
	kstrdup(&p->text, "*init*");
	kstrdup(&p->user, eve);

	/*
	 * Kernel Stack
	 */
	p->sched.pc = PTR2UINT(init0);
	p->sched.sp = PTR2UINT(p->kstack+KSTACK-sizeof(up->s.args)-sizeof(uintptr));
	p->sched.sp = STACKALIGN(p->sched.sp);

	/*
	 * User Stack
	 *
	 * Technically, newpage can't be called here because it
	 * should only be called when in a user context as it may
	 * try to sleep if there are no pages available, but that
	 * shouldn't be the case here.
	 */
	s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
	p->seg[SSEG] = s;
	pg = newpage(1, 0, USTKTOP-BY2PG);
	segpage(s, pg);
	k = kmap(pg);
	bootargs(VA(k));
	kunmap(k);

	/*
	 * Text
	 */
	s = newseg(SG_TEXT, UTZERO, 1);
	s->flushme++;
	p->seg[TSEG] = s;
	pg = newpage(1, 0, UTZERO);
	memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
	segpage(s, pg);
	k = kmap(s->map[0]->pages[0]);
	memmove(UINT2PTR(VA(k)), initcode, sizeof initcode);
	kunmap(k);

	ready(p);
}
Esempio n. 30
0
/**
 * gigaset_handle_modem_response() - process received modem response
 * @cs:		device descriptor structure.
 *
 * Called by asyncdata/isocdata if a block of data received from the
 * device must be processed as a modem command response. The data is
 * already in the cs structure.
 */
void gigaset_handle_modem_response(struct cardstate *cs)
{
	unsigned char *argv[MAX_REC_PARAMS + 1];
	int params;
	int i, j;
	const struct resp_type_t *rt;
	const struct zsau_resp_t *zr;
	int curarg;
	unsigned long flags;
	unsigned next, tail, head;
	struct event_t *event;
	int resp_code;
	int param_type;
	int abort;
	size_t len;
	int cid;
	int rawstring;

	len = cs->cbytes;
	if (!len) {
		/* ignore additional LFs/CRs (M10x config mode or cx100) */
		gig_dbg(DEBUG_MCMD, "skipped EOL [%02X]", cs->respdata[0]);
		return;
	}
	cs->respdata[len] = 0;
	argv[0] = cs->respdata;
	params = 1;
	if (cs->at_state.getstring) {
		/* getstring only allowed without cid at the moment */
		cs->at_state.getstring = 0;
		rawstring = 1;
		cid = 0;
	} else {
		/* parse line */
		for (i = 0; i < len; i++)
			switch (cs->respdata[i]) {
			case ';':
			case ',':
			case '=':
				if (params > MAX_REC_PARAMS) {
					dev_warn(cs->dev,
						 "too many parameters in response\n");
					/* need last parameter (might be CID) */
					params--;
				}
				argv[params++] = cs->respdata + i + 1;
			}

		rawstring = 0;
		cid = params > 1 ? cid_of_response(argv[params - 1]) : 0;
		if (cid < 0) {
			gigaset_add_event(cs, &cs->at_state, RSP_INVAL,
					  NULL, 0, NULL);
			return;
		}

		for (j = 1; j < params; ++j)
			argv[j][-1] = 0;

		gig_dbg(DEBUG_EVENT, "CMD received: %s", argv[0]);
		if (cid) {
			--params;
			gig_dbg(DEBUG_EVENT, "CID: %s", argv[params]);
		}
		gig_dbg(DEBUG_EVENT, "available params: %d", params - 1);
		for (j = 1; j < params; j++)
			gig_dbg(DEBUG_EVENT, "param %d: %s", j, argv[j]);
	}

	spin_lock_irqsave(&cs->ev_lock, flags);
	head = cs->ev_head;
	tail = cs->ev_tail;

	abort = 1;
	curarg = 0;
	while (curarg < params) {
		next = (tail + 1) % MAX_EVENTS;
		if (unlikely(next == head)) {
			dev_err(cs->dev, "event queue full\n");
			break;
		}

		event = cs->events + tail;
		event->at_state = NULL;
		event->cid = cid;
		event->ptr = NULL;
		event->arg = NULL;
		tail = next;

		if (rawstring) {
			resp_code = RSP_STRING;
			param_type = RT_STRING;
		} else {
			for (rt = resp_type; rt->response; ++rt)
				if (!strcmp(argv[curarg], rt->response))
					break;

			if (!rt->response) {
				event->type = RSP_NONE;
				gig_dbg(DEBUG_EVENT,
					"unknown modem response: '%s'\n",
					argv[curarg]);
				break;
			}

			resp_code = rt->resp_code;
			param_type = rt->type;
			++curarg;
		}

		event->type = resp_code;

		switch (param_type) {
		case RT_NOTHING:
			break;
		case RT_RING:
			if (!cid) {
				dev_err(cs->dev,
					"received RING without CID!\n");
				event->type = RSP_INVAL;
				abort = 1;
			} else {
				event->cid = 0;
				event->parameter = cid;
				abort = 0;
			}
			break;
		case RT_ZSAU:
			if (curarg >= params) {
				event->parameter = ZSAU_NONE;
				break;
			}
			for (zr = zsau_resp; zr->str; ++zr)
				if (!strcmp(argv[curarg], zr->str))
					break;
			event->parameter = zr->code;
			if (!zr->str)
				dev_warn(cs->dev,
					 "%s: unknown parameter %s after ZSAU\n",
					 __func__, argv[curarg]);
			++curarg;
			break;
		case RT_STRING:
			if (curarg < params) {
				event->ptr = kstrdup(argv[curarg], GFP_ATOMIC);
				if (!event->ptr)
					dev_err(cs->dev, "out of memory\n");
				++curarg;
			}
			gig_dbg(DEBUG_EVENT, "string==%s",
				event->ptr ? (char *) event->ptr : "NULL");
			break;
		case RT_ZCAU:
			event->parameter = -1;
			if (curarg + 1 < params) {
				u8 type, value;

				i = kstrtou8(argv[curarg++], 16, &type);
				j = kstrtou8(argv[curarg++], 16, &value);
				if (i == 0 && j == 0)
					event->parameter = (type << 8) | value;
			} else
				curarg = params - 1;
			break;
		case RT_NUMBER:
			if (curarg >= params ||
			    kstrtoint(argv[curarg++], 10, &event->parameter))
				event->parameter = -1;
			gig_dbg(DEBUG_EVENT, "parameter==%d", event->parameter);
			break;
		}

		if (resp_code == RSP_ZDLE)
			cs->dle = event->parameter;

		if (abort)
			break;
	}

	cs->ev_tail = tail;
	spin_unlock_irqrestore(&cs->ev_lock, flags);

	if (curarg != params)
		gig_dbg(DEBUG_EVENT,
			"invalid number of processed parameters: %d/%d",
			curarg, params);
}