コード例 #1
0
ファイル: hid-u2fzero.c プロジェクト: avagin/linux
static int u2fzero_probe(struct hid_device *hdev,
			 const struct hid_device_id *id)
{
	struct u2fzero_device *dev;
	unsigned int minor;
	int ret;

	if (!hid_is_using_ll_driver(hdev, &usb_hid_driver))
		return -EINVAL;

	dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL);
	if (dev == NULL)
		return -ENOMEM;

	dev->buf_out = devm_kmalloc(&hdev->dev,
		sizeof(struct u2f_hid_report), GFP_KERNEL);
	if (dev->buf_out == NULL)
		return -ENOMEM;

	dev->buf_in = devm_kmalloc(&hdev->dev,
		sizeof(struct u2f_hid_msg), GFP_KERNEL);
	if (dev->buf_in == NULL)
		return -ENOMEM;

	ret = hid_parse(hdev);
	if (ret)
		return ret;

	dev->hdev = hdev;
	hid_set_drvdata(hdev, dev);
	mutex_init(&dev->lock);

	ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
	if (ret)
		return ret;

	u2fzero_fill_in_urb(dev);

	dev->present = true;

	minor = ((struct hidraw *) hdev->hidraw)->minor;

	ret = u2fzero_init_led(dev, minor);
	if (ret) {
		hid_hw_stop(hdev);
		return ret;
	}

	hid_info(hdev, "U2F Zero LED initialised\n");

	ret = u2fzero_init_hwrng(dev, minor);
	if (ret) {
		hid_hw_stop(hdev);
		return ret;
	}

	hid_info(hdev, "U2F Zero RNG initialised\n");

	return 0;
}
コード例 #2
0
ファイル: kcs_bmc.c プロジェクト: Anjali05/linux
struct kcs_bmc *kcs_bmc_alloc(struct device *dev, int sizeof_priv, u32 channel)
{
	struct kcs_bmc *kcs_bmc;

	kcs_bmc = devm_kzalloc(dev, sizeof(*kcs_bmc) + sizeof_priv, GFP_KERNEL);
	if (!kcs_bmc)
		return NULL;

	spin_lock_init(&kcs_bmc->lock);
	kcs_bmc->channel = channel;

	mutex_init(&kcs_bmc->mutex);
	init_waitqueue_head(&kcs_bmc->queue);

	kcs_bmc->data_in = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL);
	kcs_bmc->data_out = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL);
	kcs_bmc->kbuffer = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL);

	kcs_bmc->miscdev.minor = MISC_DYNAMIC_MINOR;
	kcs_bmc->miscdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s%u",
					       DEVICE_NAME, channel);
	if (!kcs_bmc->data_in || !kcs_bmc->data_out || !kcs_bmc->kbuffer ||
	    !kcs_bmc->miscdev.name)
		return NULL;
	kcs_bmc->miscdev.fops = &kcs_bmc_fops;

	return kcs_bmc;
}
コード例 #3
0
ファイル: clk.c プロジェクト: AlexShiLucky/linux
struct hisi_clock_data *hisi_clk_alloc(struct platform_device *pdev,
						int nr_clks)
{
	struct hisi_clock_data *clk_data;
	struct resource *res;
	struct clk **clk_table;

	clk_data = devm_kmalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL);
	if (!clk_data)
		return NULL;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res)
		return NULL;
	clk_data->base = devm_ioremap(&pdev->dev,
				res->start, resource_size(res));
	if (!clk_data->base)
		return NULL;

	clk_table = devm_kmalloc_array(&pdev->dev, nr_clks,
				       sizeof(*clk_table),
				       GFP_KERNEL);
	if (!clk_table)
		return NULL;

	clk_data->clk_data.clks = clk_table;
	clk_data->clk_data.clk_num = nr_clks;

	return clk_data;
}
コード例 #4
0
ファイル: crg-hi3798cv200.c プロジェクト: avagin/linux
static int hi3798cv200_crg_probe(struct platform_device *pdev)
{
	struct hisi_crg_dev *crg;

	crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL);
	if (!crg)
		return -ENOMEM;

	crg->funcs = of_device_get_match_data(&pdev->dev);
	if (!crg->funcs)
		return -ENOENT;

	crg->rstc = hisi_reset_init(pdev);
	if (!crg->rstc)
		return -ENOMEM;

	crg->clk_data = crg->funcs->register_clks(pdev);
	if (IS_ERR(crg->clk_data)) {
		hisi_reset_exit(crg->rstc);
		return PTR_ERR(crg->clk_data);
	}

	platform_set_drvdata(pdev, crg);
	return 0;
}
コード例 #5
0
ファイル: clk-scpi.c プロジェクト: 125radheyshyam/linux-1
static int scpi_clk_add(struct device *dev, struct device_node *np,
			const struct of_device_id *match)
{
	struct clk **clks;
	int idx, count;
	struct scpi_clk_data *clk_data;

	count = of_property_count_strings(np, "clock-output-names");
	if (count < 0) {
		dev_err(dev, "%s: invalid clock output count\n", np->name);
		return -EINVAL;
	}

	clk_data = devm_kmalloc(dev, sizeof(*clk_data), GFP_KERNEL);
	if (!clk_data)
		return -ENOMEM;

	clk_data->clk_num = count;
	clk_data->clk = devm_kcalloc(dev, count, sizeof(*clk_data->clk),
				     GFP_KERNEL);
	if (!clk_data->clk)
		return -ENOMEM;

	clks = devm_kcalloc(dev, count, sizeof(*clks), GFP_KERNEL);
	if (!clks)
		return -ENOMEM;

	for (idx = 0; idx < count; idx++) {
		struct scpi_clk *sclk;
		const char *name;
		u32 val;

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

		if (of_property_read_string_index(np, "clock-output-names",
						  idx, &name)) {
			dev_err(dev, "invalid clock name @ %s\n", np->name);
			return -EINVAL;
		}

		if (of_property_read_u32_index(np, "clock-indices",
					       idx, &val)) {
			dev_err(dev, "invalid clock index @ %s\n", np->name);
			return -EINVAL;
		}

		sclk->id = val;

		clks[idx] = scpi_clk_ops_init(dev, match, sclk, name);
		if (IS_ERR_OR_NULL(clks[idx]))
			dev_err(dev, "failed to register clock '%s'\n", name);
		else
			dev_dbg(dev, "Registered clock '%s'\n", name);
		clk_data->clk[idx] = sclk;
	}

	return of_clk_add_provider(np, scpi_of_clk_src_get, clk_data);
}
コード例 #6
0
static int create_sysfs_entry_channel(struct hidma_mgmt_dev *mdev, char *name,
				      int mode, int index,
				      struct kobject *parent)
{
	struct hidma_chan_attr *chattr;
	char *name_copy;

	chattr = devm_kmalloc(&mdev->pdev->dev, sizeof(*chattr), GFP_KERNEL);
	if (!chattr)
		return -ENOMEM;

	name_copy = devm_kstrdup(&mdev->pdev->dev, name, GFP_KERNEL);
	if (!name_copy)
		return -ENOMEM;

	chattr->mdev = mdev;
	chattr->index = index;
	chattr->attr.attr.name = name_copy;
	chattr->attr.attr.mode = mode;
	chattr->attr.show = show_values_channel;
	chattr->attr.store = set_values_channel;
	sysfs_attr_init(&chattr->attr.attr);

	return sysfs_create_file(parent, &chattr->attr.attr);
}
コード例 #7
0
ファイル: init.c プロジェクト: acton393/linux
int mt7601u_register_device(struct mt7601u_dev *dev)
{
	struct ieee80211_hw *hw = dev->hw;
	struct wiphy *wiphy = hw->wiphy;
	int ret;

	/* Reserve WCID 0 for mcast - thanks to this APs WCID will go to
	 * entry no. 1 like it does in the vendor driver.
	 */
	dev->wcid_mask[0] |= 1;

	/* init fake wcid for monitor interfaces */
	dev->mon_wcid = devm_kmalloc(dev->dev, sizeof(*dev->mon_wcid),
				     GFP_KERNEL);
	if (!dev->mon_wcid)
		return -ENOMEM;
	dev->mon_wcid->idx = 0xff;
	dev->mon_wcid->hw_key_idx = -1;

	SET_IEEE80211_DEV(hw, dev->dev);

	hw->queues = 4;
	ieee80211_hw_set(hw, SIGNAL_DBM);
	ieee80211_hw_set(hw, PS_NULLFUNC_STACK);
	ieee80211_hw_set(hw, SUPPORTS_HT_CCK_RATES);
	ieee80211_hw_set(hw, AMPDU_AGGREGATION);
	ieee80211_hw_set(hw, SUPPORTS_RC_TABLE);
	hw->max_rates = 1;
	hw->max_report_rates = 7;
	hw->max_rate_tries = 1;

	hw->sta_data_size = sizeof(struct mt76_sta);
	hw->vif_data_size = sizeof(struct mt76_vif);

	SET_IEEE80211_PERM_ADDR(hw, dev->macaddr);

	wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;
	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);

	ret = mt76_init_sband_2g(dev);
	if (ret)
		return ret;

	INIT_DELAYED_WORK(&dev->mac_work, mt7601u_mac_work);
	INIT_DELAYED_WORK(&dev->stat_work, mt7601u_tx_stat);

	ret = ieee80211_register_hw(hw);
	if (ret)
		return ret;

	mt7601u_init_debugfs(dev);

	return 0;
}
コード例 #8
0
int hidma_mgmt_init_sys(struct hidma_mgmt_dev *mdev)
{
	unsigned int i;
	int rc;
	int required;
	struct kobject *chanops;

	required = sizeof(*mdev->chroots) * mdev->dma_channels;
	mdev->chroots = devm_kmalloc(&mdev->pdev->dev, required, GFP_KERNEL);
	if (!mdev->chroots)
		return -ENOMEM;

	chanops = kobject_create_and_add("chanops", &mdev->pdev->dev.kobj);
	if (!chanops)
		return -ENOMEM;

	/* create each channel directory here */
	for (i = 0; i < mdev->dma_channels; i++) {
		char name[20];

		snprintf(name, sizeof(name), "chan%d", i);
		mdev->chroots[i] = kobject_create_and_add(name, chanops);
		if (!mdev->chroots[i])
			return -ENOMEM;
	}

	/* populate common parameters */
	for (i = 0; i < ARRAY_SIZE(hidma_mgmt_files); i++) {
		rc = create_sysfs_entry(mdev, hidma_mgmt_files[i].name,
					hidma_mgmt_files[i].mode);
		if (rc)
			return rc;
	}

	/* populate parameters that are per channel */
	for (i = 0; i < mdev->dma_channels; i++) {
		rc = create_sysfs_entry_channel(mdev, "priority",
						(S_IRUGO | S_IWUGO), i,
						mdev->chroots[i]);
		if (rc)
			return rc;

		rc = create_sysfs_entry_channel(mdev, "weight",
						(S_IRUGO | S_IWUGO), i,
						mdev->chroots[i]);
		if (rc)
			return rc;
	}

	return 0;
}
コード例 #9
0
/**
 * devm_kstrdup - Allocate resource managed space and
 *                copy an existing string into that.
 * @dev: Device to allocate memory for
 * @s: the string to duplicate
 * @gfp: the GFP mask used in the devm_kmalloc() call when
 *       allocating memory
 * RETURNS:
 * Pointer to allocated string on success, NULL on failure.
 */
char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp)
{
	size_t size;
	char *buf;

	if (!s)
		return NULL;

	size = strlen(s) + 1;
	buf = devm_kmalloc(dev, size, gfp);
	if (buf)
		memcpy(buf, s, size);
	return buf;
}
コード例 #10
0
ファイル: i2c.c プロジェクト: asmalldev/linux
static void fdp_nci_i2c_read_device_properties(struct device *dev,
					       u8 *clock_type, u32 *clock_freq,
					       u8 **fw_vsc_cfg)
{
	int r;
	u8 len;

	r = device_property_read_u8(dev, FDP_DP_CLOCK_TYPE_NAME, clock_type);
	if (r) {
		dev_dbg(dev, "Using default clock type");
		*clock_type = 0;
	}

	r = device_property_read_u32(dev, FDP_DP_CLOCK_FREQ_NAME, clock_freq);
	if (r) {
		dev_dbg(dev, "Using default clock frequency\n");
		*clock_freq = 26000;
	}

	if (device_property_present(dev, FDP_DP_FW_VSC_CFG_NAME)) {
		r = device_property_read_u8(dev, FDP_DP_FW_VSC_CFG_NAME,
					    &len);

		if (r || len <= 0)
			goto vsc_read_err;

		/* Add 1 to the length to inclue the length byte itself */
		len++;

		*fw_vsc_cfg = devm_kmalloc(dev,
					   len * sizeof(**fw_vsc_cfg),
					   GFP_KERNEL);

		r = device_property_read_u8_array(dev, FDP_DP_FW_VSC_CFG_NAME,
						  *fw_vsc_cfg, len);

		if (r) {
			devm_kfree(dev, fw_vsc_cfg);
			goto vsc_read_err;
		}
	} else {
vsc_read_err:
		dev_dbg(dev, "FW vendor specific commands not present\n");
		*fw_vsc_cfg = NULL;
	}

	dev_dbg(dev, "Clock type: %d, clock frequency: %d, VSC: %s",
		*clock_type, *clock_freq, *fw_vsc_cfg != NULL ? "yes" : "no");
}
コード例 #11
0
ファイル: rvu_cgx.c プロジェクト: AlexShiLucky/linux
static int rvu_map_cgx_lmac_pf(struct rvu *rvu)
{
	struct npc_pkind *pkind = &rvu->hw->pkind;
	int cgx_cnt_max = rvu->cgx_cnt_max;
	int cgx, lmac_cnt, lmac;
	int pf = PF_CGXMAP_BASE;
	int size, free_pkind;

	if (!cgx_cnt_max)
		return 0;

	if (cgx_cnt_max > 0xF || MAX_LMAC_PER_CGX > 0xF)
		return -EINVAL;

	/* Alloc map table
	 * An additional entry is required since PF id starts from 1 and
	 * hence entry at offset 0 is invalid.
	 */
	size = (cgx_cnt_max * MAX_LMAC_PER_CGX + 1) * sizeof(u8);
	rvu->pf2cgxlmac_map = devm_kmalloc(rvu->dev, size, GFP_KERNEL);
	if (!rvu->pf2cgxlmac_map)
		return -ENOMEM;

	/* Initialize all entries with an invalid cgx and lmac id */
	memset(rvu->pf2cgxlmac_map, 0xFF, size);

	/* Reverse map table */
	rvu->cgxlmac2pf_map = devm_kzalloc(rvu->dev,
				  cgx_cnt_max * MAX_LMAC_PER_CGX * sizeof(u16),
				  GFP_KERNEL);
	if (!rvu->cgxlmac2pf_map)
		return -ENOMEM;

	rvu->cgx_mapped_pfs = 0;
	for (cgx = 0; cgx < cgx_cnt_max; cgx++) {
		if (!rvu_cgx_pdata(cgx, rvu))
			continue;
		lmac_cnt = cgx_get_lmac_cnt(rvu_cgx_pdata(cgx, rvu));
		for (lmac = 0; lmac < lmac_cnt; lmac++, pf++) {
			rvu->pf2cgxlmac_map[pf] = cgxlmac_id_to_bmap(cgx, lmac);
			rvu->cgxlmac2pf_map[CGX_OFFSET(cgx) + lmac] = 1 << pf;
			free_pkind = rvu_alloc_rsrc(&pkind->rsrc);
			pkind->pfchan_map[free_pkind] = ((pf) & 0x3F) << 16;
			rvu->cgx_mapped_pfs++;
		}
	}
	return 0;
}
コード例 #12
0
ファイル: ehci-s5p.c プロジェクト: ShedrockN4/wiliteneo
static int s5p_ehci_clk_get(struct s5p_ehci_hcd *s5p_ehci, struct device *dev)
{
	const char *clk_id;
	const char **s5p_ehci_clk_names;
	struct clk *clk;
	int size;
	int i;

	clk_id = "usbhost";
	clk = devm_clk_get(dev, clk_id);
	if (IS_ERR_OR_NULL(clk)) {
		dev_info(dev, "IP clock gating is N/A\n");
		s5p_ehci->clk = NULL;
		/* fallback to separate clock control */
		s5p_ehci_clk_names = s5p_ehci->drvdata->clk_names;
		size = s5p_ehci->drvdata->clk_size;
		s5p_ehci->clocks = (struct clk **) devm_kmalloc(dev,
				size * sizeof(struct clk *),
				GFP_KERNEL);
		if (!s5p_ehci->clocks)
			return -ENOMEM;

		for (i = 0; s5p_ehci_clk_names[i] != NULL; i++) {
			clk_id = s5p_ehci_clk_names[i];
			clk = devm_clk_get(dev, clk_id);
			if (IS_ERR_OR_NULL(clk))
				goto err;

			s5p_ehci->clocks[i] = clk;
		}

		s5p_ehci->clocks[i] = NULL;

	} else {
		s5p_ehci->clk = clk;
	}

	return 0;

err:
	dev_err(dev, "couldn't get %s clock\n", clk_id);

	return -EINVAL;
}
コード例 #13
0
/**
 * devm_kvasprintf - Allocate resource managed space
 *			for the formatted string.
 * @dev: Device to allocate memory for
 * @gfp: the GFP mask used in the devm_kmalloc() call when
 *       allocating memory
 * @fmt: the formatted string to duplicate
 * @ap: the list of tokens to be placed in the formatted string
 * RETURNS:
 * Pointer to allocated string on success, NULL on failure.
 */
char *devm_kvasprintf(struct device *dev, gfp_t gfp, const char *fmt,
		      va_list ap)
{
	unsigned int len;
	char *p;
	va_list aq;

	va_copy(aq, ap);
	len = vsnprintf(NULL, 0, fmt, aq);
	va_end(aq);

	p = devm_kmalloc(dev, len+1, gfp);
	if (!p)
		return NULL;

	vsnprintf(p, len+1, fmt, ap);

	return p;
}
コード例 #14
0
static int tc_cfg_probe(struct platform_device *pdev)
{
    pr_info("%s.\n",__FUNCTION__);

    tc_cfg_reg = devm_kmalloc(&pdev->dev,sizeof(struct at_case_type), GFP_ATOMIC);
    if(NULL == tc_cfg_reg){
         return -ENOMEM;
    }

    tc_cfg_reg->test_name   = "tc_cfg_reg";
    tc_cfg_reg->test_params = 0;
    tc_cfg_reg->test_pri    = AT_CASE_PRI_HIG;
    tc_cfg_reg->prepare     = tc_cfg_reg_prepare;
    tc_cfg_reg->begin       = tc_cfg_reg_beg;
    tc_cfg_reg->stop        = tc_cfg_reg_stop;

    //at_core_register_test_case(tc_cfg_reg);

    return 0;
}
コード例 #15
0
static int create_sysfs_entry(struct hidma_mgmt_dev *dev, char *name, int mode)
{
	struct device_attribute *attrs;
	char *name_copy;

	attrs = devm_kmalloc(&dev->pdev->dev,
			     sizeof(struct device_attribute), GFP_KERNEL);
	if (!attrs)
		return -ENOMEM;

	name_copy = devm_kstrdup(&dev->pdev->dev, name, GFP_KERNEL);
	if (!name_copy)
		return -ENOMEM;

	attrs->attr.name = name_copy;
	attrs->attr.mode = mode;
	attrs->show = show_values;
	attrs->store = set_values;
	sysfs_attr_init(&attrs->attr);

	return device_create_file(&dev->pdev->dev, attrs);
}
コード例 #16
0
static int armada_xp_pinctrl_probe(struct platform_device *pdev)
{
	struct mvebu_pinctrl_soc_info *soc = &armada_xp_pinctrl_info;
	const struct of_device_id *match =
		of_match_device(armada_xp_pinctrl_of_match, &pdev->dev);
	int nregs;

	if (!match)
		return -ENODEV;

	soc->variant = (unsigned) match->data & 0xff;

	switch (soc->variant) {
	case V_MV78230:
		soc->controls = mv78230_mpp_controls;
		soc->ncontrols = ARRAY_SIZE(mv78230_mpp_controls);
		soc->modes = armada_xp_mpp_modes;
		/* We don't necessarily want the full list of the
		 * armada_xp_mpp_modes, but only the first 'n' ones
		 * that are available on this SoC */
		soc->nmodes = mv78230_mpp_controls[0].npins;
		soc->gpioranges = mv78230_mpp_gpio_ranges;
		soc->ngpioranges = ARRAY_SIZE(mv78230_mpp_gpio_ranges);
		break;
	case V_MV78260:
		soc->controls = mv78260_mpp_controls;
		soc->ncontrols = ARRAY_SIZE(mv78260_mpp_controls);
		soc->modes = armada_xp_mpp_modes;
		/* We don't necessarily want the full list of the
		 * armada_xp_mpp_modes, but only the first 'n' ones
		 * that are available on this SoC */
		soc->nmodes = mv78260_mpp_controls[0].npins;
		soc->gpioranges = mv78260_mpp_gpio_ranges;
		soc->ngpioranges = ARRAY_SIZE(mv78260_mpp_gpio_ranges);
		break;
	case V_MV78460:
		soc->controls = mv78460_mpp_controls;
		soc->ncontrols = ARRAY_SIZE(mv78460_mpp_controls);
		soc->modes = armada_xp_mpp_modes;
		/* We don't necessarily want the full list of the
		 * armada_xp_mpp_modes, but only the first 'n' ones
		 * that are available on this SoC */
		soc->nmodes = mv78460_mpp_controls[0].npins;
		soc->gpioranges = mv78460_mpp_gpio_ranges;
		soc->ngpioranges = ARRAY_SIZE(mv78460_mpp_gpio_ranges);
		break;
	case V_98DX3236:
	case V_98DX3336:
	case V_98DX4251:
		/* fall-through */
		soc->controls = mv98dx3236_mpp_controls;
		soc->ncontrols = ARRAY_SIZE(mv98dx3236_mpp_controls);
		soc->modes = mv98dx3236_mpp_modes;
		soc->nmodes = mv98dx3236_mpp_controls[0].npins;
		soc->gpioranges = mv98dx3236_mpp_gpio_ranges;
		soc->ngpioranges = ARRAY_SIZE(mv98dx3236_mpp_gpio_ranges);
		break;
	}

	nregs = DIV_ROUND_UP(soc->nmodes, MVEBU_MPPS_PER_REG);

	mpp_saved_regs = devm_kmalloc(&pdev->dev, nregs * sizeof(u32),
				      GFP_KERNEL);
	if (!mpp_saved_regs)
		return -ENOMEM;

	pdev->dev.platform_data = soc;

	return mvebu_pinctrl_simple_mmio_probe(pdev);
}
コード例 #17
0
static int ipmi_powernv_probe(struct platform_device *pdev)
{
	struct ipmi_smi_powernv *ipmi;
	struct device *dev;
	u32 prop;
	int rc;

	if (!pdev || !pdev->dev.of_node)
		return -ENODEV;

	dev = &pdev->dev;

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

	spin_lock_init(&ipmi->msg_lock);

	rc = of_property_read_u32(dev->of_node, "ibm,ipmi-interface-id",
			&prop);
	if (rc) {
		dev_warn(dev, "No interface ID property\n");
		goto err_free;
	}
	ipmi->interface_id = prop;

	rc = of_property_read_u32(dev->of_node, "interrupts", &prop);
	if (rc) {
		dev_warn(dev, "No interrupts property\n");
		goto err_free;
	}

	ipmi->irq = irq_of_parse_and_map(dev->of_node, 0);
	if (!ipmi->irq) {
		dev_info(dev, "Unable to map irq from device tree\n");
		ipmi->irq = opal_event_request(prop);
	}

	if (request_irq(ipmi->irq, ipmi_opal_event, IRQ_TYPE_LEVEL_HIGH,
				"opal-ipmi", ipmi)) {
		dev_warn(dev, "Unable to request irq\n");
		goto err_dispose;
	}

	ipmi->opal_msg = devm_kmalloc(dev,
			sizeof(*ipmi->opal_msg) + IPMI_MAX_MSG_LENGTH,
			GFP_KERNEL);
	if (!ipmi->opal_msg) {
		rc = -ENOMEM;
		goto err_unregister;
	}

	/* todo: query actual ipmi_device_id */
	rc = ipmi_register_smi(&ipmi_powernv_smi_handlers, ipmi,
			&ipmi->ipmi_id, dev, 0);
	if (rc) {
		dev_warn(dev, "IPMI SMI registration failed (%d)\n", rc);
		goto err_free_msg;
	}

	dev_set_drvdata(dev, ipmi);
	return 0;

err_free_msg:
	devm_kfree(dev, ipmi->opal_msg);
err_unregister:
	free_irq(ipmi->irq, ipmi);
err_dispose:
	irq_dispose_mapping(ipmi->irq);
err_free:
	devm_kfree(dev, ipmi);
	return rc;
}
コード例 #18
0
ファイル: hid-huion.c プロジェクト: AkyZero/wrapfs-latest
/**
 * Enable fully-functional tablet mode and determine device parameters.
 *
 * @hdev:	HID device
 */
static int huion_tablet_enable(struct hid_device *hdev)
{
	int rc;
	struct usb_device *usb_dev = hid_to_usb_dev(hdev);
	struct huion_drvdata *drvdata = hid_get_drvdata(hdev);
	__le16 buf[6];

	/*
	 * Read string descriptor containing tablet parameters. The specific
	 * string descriptor and data were discovered by sniffing the Windows
	 * driver traffic.
	 * NOTE: This enables fully-functional tablet mode.
	 */
	rc = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
				USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
				(USB_DT_STRING << 8) + 0x64,
				0x0409, buf, sizeof(buf),
				USB_CTRL_GET_TIMEOUT);
	if (rc == -EPIPE)
		hid_warn(hdev, "device parameters not found\n");
	else if (rc < 0)
		hid_warn(hdev, "failed to get device parameters: %d\n", rc);
	else if (rc != sizeof(buf))
		hid_warn(hdev, "invalid device parameters\n");
	else {
		s32 params[HUION_PH_ID_NUM];
		s32 resolution;
		__u8 *p;
		s32 v;

		/* Extract device parameters */
		params[HUION_PH_ID_X_LM] = le16_to_cpu(buf[1]);
		params[HUION_PH_ID_Y_LM] = le16_to_cpu(buf[2]);
		params[HUION_PH_ID_PRESSURE_LM] = le16_to_cpu(buf[4]);
		resolution = le16_to_cpu(buf[5]);
		if (resolution == 0) {
			params[HUION_PH_ID_X_PM] = 0;
			params[HUION_PH_ID_Y_PM] = 0;
		} else {
			params[HUION_PH_ID_X_PM] = params[HUION_PH_ID_X_LM] *
							1000 / resolution;
			params[HUION_PH_ID_Y_PM] = params[HUION_PH_ID_Y_LM] *
							1000 / resolution;
		}

		/* Allocate fixed report descriptor */
		drvdata->rdesc = devm_kmalloc(&hdev->dev,
					sizeof(huion_tablet_rdesc_template),
					GFP_KERNEL);
		if (drvdata->rdesc == NULL) {
			hid_err(hdev, "failed to allocate fixed rdesc\n");
			return -ENOMEM;
		}
		drvdata->rsize = sizeof(huion_tablet_rdesc_template);

		/* Format fixed report descriptor */
		memcpy(drvdata->rdesc, huion_tablet_rdesc_template,
			drvdata->rsize);
		for (p = drvdata->rdesc;
		     p <= drvdata->rdesc + drvdata->rsize - 4;) {
			if (p[0] == 0xFE && p[1] == 0xED && p[2] == 0x1D &&
			    p[3] < sizeof(params)) {
				v = params[p[3]];
				put_unaligned(cpu_to_le32(v), (s32 *)p);
				p += 4;
			} else {
				p++;
			}
		}
	}

	return 0;
}
コード例 #19
0
ファイル: ipmi_powernv.c プロジェクト: 383530895/linux
static int ipmi_powernv_probe(struct platform_device *pdev)
{
	struct ipmi_smi_powernv *ipmi;
	struct device *dev;
	u32 prop;
	int rc;

	if (!pdev || !pdev->dev.of_node)
		return -ENODEV;

	dev = &pdev->dev;

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

	spin_lock_init(&ipmi->msg_lock);

	rc = of_property_read_u32(dev->of_node, "ibm,ipmi-interface-id",
			&prop);
	if (rc) {
		dev_warn(dev, "No interface ID property\n");
		goto err_free;
	}
	ipmi->interface_id = prop;

	rc = of_property_read_u32(dev->of_node, "interrupts", &prop);
	if (rc) {
		dev_warn(dev, "No interrupts property\n");
		goto err_free;
	}

	ipmi->event = 1ull << prop;
	ipmi->event_nb.notifier_call = ipmi_opal_event;

	rc = opal_notifier_register(&ipmi->event_nb);
	if (rc) {
		dev_warn(dev, "OPAL notifier registration failed (%d)\n", rc);
		goto err_free;
	}

	ipmi->opal_msg = devm_kmalloc(dev,
			sizeof(*ipmi->opal_msg) + IPMI_MAX_MSG_LENGTH,
			GFP_KERNEL);
	if (!ipmi->opal_msg) {
		rc = -ENOMEM;
		goto err_unregister;
	}

	/* todo: query actual ipmi_device_id */
	rc = ipmi_register_smi(&ipmi_powernv_smi_handlers, ipmi,
			&ipmi->ipmi_id, dev, 0);
	if (rc) {
		dev_warn(dev, "IPMI SMI registration failed (%d)\n", rc);
		goto err_free_msg;
	}

	dev_set_drvdata(dev, ipmi);
	return 0;

err_free_msg:
	devm_kfree(dev, ipmi->opal_msg);
err_unregister:
	opal_notifier_unregister(&ipmi->event_nb);
err_free:
	devm_kfree(dev, ipmi);
	return rc;
}
コード例 #20
0
ファイル: ishtp-hid-client.c プロジェクト: AshishNamdev/linux
/**
 * process_recv() - Received and parse incoming packet
 * @hid_ishtp_cl:	Client instance to get stats
 * @recv_buf:		Raw received host interface message
 * @data_len:		length of the message
 *
 * Parse the incoming packet. If it is a response packet then it will update
 * per instance flags and wake up the caller waiting to for the response.
 */
static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf,
			 size_t data_len)
{
	struct hostif_msg *recv_msg;
	unsigned char *payload;
	struct device_info *dev_info;
	int i, j;
	size_t	payload_len, total_len, cur_pos;
	int report_type;
	struct report_list *reports_list;
	char *reports;
	size_t report_len;
	struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data;
	int curr_hid_dev = client_data->cur_hid_dev;

	if (data_len < sizeof(struct hostif_msg_hdr)) {
		dev_err(&client_data->cl_device->dev,
			"[hid-ish]: error, received %u which is less than data header %u\n",
			(unsigned int)data_len,
			(unsigned int)sizeof(struct hostif_msg_hdr));
		++client_data->bad_recv_cnt;
		ish_hw_reset(hid_ishtp_cl->dev);
		return;
	}

	payload = recv_buf + sizeof(struct hostif_msg_hdr);
	total_len = data_len;
	cur_pos = 0;

	do {
		recv_msg = (struct hostif_msg *)(recv_buf + cur_pos);
		payload_len = recv_msg->hdr.size;

		/* Sanity checks */
		if (cur_pos + payload_len + sizeof(struct hostif_msg) >
				total_len) {
			++client_data->bad_recv_cnt;
			report_bad_packet(hid_ishtp_cl, recv_msg, cur_pos,
					  payload_len);
			ish_hw_reset(hid_ishtp_cl->dev);
			break;
		}

		hid_ishtp_trace(client_data,  "%s %d\n",
				__func__, recv_msg->hdr.command & CMD_MASK);

		switch (recv_msg->hdr.command & CMD_MASK) {
		case HOSTIF_DM_ENUM_DEVICES:
			if ((!(recv_msg->hdr.command & ~CMD_MASK) ||
					client_data->init_done)) {
				++client_data->bad_recv_cnt;
				report_bad_packet(hid_ishtp_cl, recv_msg,
						  cur_pos,
						  payload_len);
				ish_hw_reset(hid_ishtp_cl->dev);
				break;
			}
			client_data->hid_dev_count = (unsigned int)*payload;
			if (!client_data->hid_devices)
				client_data->hid_devices = devm_kzalloc(
						&client_data->cl_device->dev,
						client_data->hid_dev_count *
						sizeof(struct device_info),
						GFP_KERNEL);
			if (!client_data->hid_devices) {
				dev_err(&client_data->cl_device->dev,
				"Mem alloc failed for hid device info\n");
				wake_up_interruptible(&client_data->init_wait);
				break;
			}
			for (i = 0; i < client_data->hid_dev_count; ++i) {
				if (1 + sizeof(struct device_info) * i >=
						payload_len) {
					dev_err(&client_data->cl_device->dev,
						"[hid-ish]: [ENUM_DEVICES]: content size %lu is bigger than payload_len %u\n",
						1 + sizeof(struct device_info)
						* i,
						(unsigned int)payload_len);
				}

				if (1 + sizeof(struct device_info) * i >=
						data_len)
					break;

				dev_info = (struct device_info *)(payload + 1 +
					sizeof(struct device_info) * i);
				if (client_data->hid_devices)
					memcpy(client_data->hid_devices + i,
					       dev_info,
					       sizeof(struct device_info));
			}

			client_data->enum_devices_done = true;
			wake_up_interruptible(&client_data->init_wait);

			break;

		case HOSTIF_GET_HID_DESCRIPTOR:
			if ((!(recv_msg->hdr.command & ~CMD_MASK) ||
					client_data->init_done)) {
				++client_data->bad_recv_cnt;
				report_bad_packet(hid_ishtp_cl, recv_msg,
						  cur_pos,
						  payload_len);
				ish_hw_reset(hid_ishtp_cl->dev);
				break;
			}
			if (!client_data->hid_descr[curr_hid_dev])
				client_data->hid_descr[curr_hid_dev] =
				devm_kmalloc(&client_data->cl_device->dev,
					     payload_len, GFP_KERNEL);
			if (client_data->hid_descr[curr_hid_dev]) {
				memcpy(client_data->hid_descr[curr_hid_dev],
				       payload, payload_len);
				client_data->hid_descr_size[curr_hid_dev] =
					payload_len;
				client_data->hid_descr_done = true;
			}
			wake_up_interruptible(&client_data->init_wait);

			break;

		case HOSTIF_GET_REPORT_DESCRIPTOR:
			if ((!(recv_msg->hdr.command & ~CMD_MASK) ||
					client_data->init_done)) {
				++client_data->bad_recv_cnt;
				report_bad_packet(hid_ishtp_cl, recv_msg,
						  cur_pos,
						  payload_len);
				ish_hw_reset(hid_ishtp_cl->dev);
				break;
			}
			if (!client_data->report_descr[curr_hid_dev])
				client_data->report_descr[curr_hid_dev] =
				devm_kmalloc(&client_data->cl_device->dev,
					     payload_len, GFP_KERNEL);
			if (client_data->report_descr[curr_hid_dev])  {
				memcpy(client_data->report_descr[curr_hid_dev],
				       payload,
				       payload_len);
				client_data->report_descr_size[curr_hid_dev] =
					payload_len;
				client_data->report_descr_done = true;
			}
			wake_up_interruptible(&client_data->init_wait);

			break;

		case HOSTIF_GET_FEATURE_REPORT:
			report_type = HID_FEATURE_REPORT;
			goto	do_get_report;

		case HOSTIF_GET_INPUT_REPORT:
			report_type = HID_INPUT_REPORT;
do_get_report:
			/* Get index of device that matches this id */
			for (i = 0; i < client_data->num_hid_devices; ++i) {
				if (recv_msg->hdr.device_id ==
					client_data->hid_devices[i].dev_id)
					if (client_data->hid_sensor_hubs[i]) {
						hid_input_report(
						client_data->hid_sensor_hubs[
									i],
						report_type, payload,
						payload_len, 0);
						ishtp_hid_wakeup(
						client_data->hid_sensor_hubs[
							i]);
						break;
					}
			}
			break;

		case HOSTIF_SET_FEATURE_REPORT:
			/* Get index of device that matches this id */
			for (i = 0; i < client_data->num_hid_devices; ++i) {
				if (recv_msg->hdr.device_id ==
					client_data->hid_devices[i].dev_id)
					if (client_data->hid_sensor_hubs[i]) {
						ishtp_hid_wakeup(
						client_data->hid_sensor_hubs[
							i]);
						break;
					}
			}
			break;

		case HOSTIF_PUBLISH_INPUT_REPORT:
			report_type = HID_INPUT_REPORT;
			for (i = 0; i < client_data->num_hid_devices; ++i)
				if (recv_msg->hdr.device_id ==
					client_data->hid_devices[i].dev_id)
					if (client_data->hid_sensor_hubs[i])
						hid_input_report(
						client_data->hid_sensor_hubs[
									i],
						report_type, payload,
						payload_len, 0);
			break;

		case HOSTIF_PUBLISH_INPUT_REPORT_LIST:
			report_type = HID_INPUT_REPORT;
			reports_list = (struct report_list *)payload;
			reports = (char *)reports_list->reports;

			for (j = 0; j < reports_list->num_of_reports; j++) {
				recv_msg = (struct hostif_msg *)(reports +
					sizeof(uint16_t));
				report_len = *(uint16_t *)reports;
				payload = reports + sizeof(uint16_t) +
					sizeof(struct hostif_msg_hdr);
				payload_len = report_len -
					sizeof(struct hostif_msg_hdr);

				for (i = 0; i < client_data->num_hid_devices;
				     ++i)
					if (recv_msg->hdr.device_id ==
					client_data->hid_devices[i].dev_id &&
					client_data->hid_sensor_hubs[i]) {
						hid_input_report(
						client_data->hid_sensor_hubs[
									i],
						report_type,
						payload, payload_len,
						0);
					}

				reports += sizeof(uint16_t) + report_len;
			}
			break;
		default:
			++client_data->bad_recv_cnt;
			report_bad_packet(hid_ishtp_cl, recv_msg, cur_pos,
					  payload_len);
			ish_hw_reset(hid_ishtp_cl->dev);
			break;

		}

		if (!cur_pos && cur_pos + payload_len +
				sizeof(struct hostif_msg) < total_len)
			++client_data->multi_packet_cnt;

		cur_pos += payload_len + sizeof(struct hostif_msg);
		payload += payload_len + sizeof(struct hostif_msg);

	} while (cur_pos < total_len);
}
コード例 #21
0
ファイル: s2mps11.c プロジェクト: Abioy/ktsan
static int s2mps11_pmic_probe(struct platform_device *pdev)
{
	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
	struct sec_platform_data *pdata = NULL;
	struct of_regulator_match *rdata = NULL;
	struct regulator_config config = { };
	struct s2mps11_info *s2mps11;
	int i, ret = 0;
	const struct regulator_desc *regulators;

	s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info),
				GFP_KERNEL);
	if (!s2mps11)
		return -ENOMEM;

	s2mps11->dev_type = platform_get_device_id(pdev)->driver_data;
	switch (s2mps11->dev_type) {
	case S2MPS11X:
		s2mps11->rdev_num = ARRAY_SIZE(s2mps11_regulators);
		regulators = s2mps11_regulators;
		break;
	case S2MPS13X:
		s2mps11->rdev_num = ARRAY_SIZE(s2mps13_regulators);
		regulators = s2mps13_regulators;
		break;
	case S2MPS14X:
		s2mps11->rdev_num = ARRAY_SIZE(s2mps14_regulators);
		regulators = s2mps14_regulators;
		break;
	case S2MPU02:
		s2mps11->rdev_num = ARRAY_SIZE(s2mpu02_regulators);
		regulators = s2mpu02_regulators;
		break;
	default:
		dev_err(&pdev->dev, "Invalid device type: %u\n",
				    s2mps11->dev_type);
		return -EINVAL;
	};

	s2mps11->ext_control_gpio = devm_kmalloc(&pdev->dev,
			sizeof(*s2mps11->ext_control_gpio) * s2mps11->rdev_num,
			GFP_KERNEL);
	if (!s2mps11->ext_control_gpio)
		return -ENOMEM;
	/*
	 * 0 is a valid GPIO so initialize all GPIO-s to negative value
	 * to indicate that external control won't be used for this regulator.
	 */
	for (i = 0; i < s2mps11->rdev_num; i++)
		s2mps11->ext_control_gpio[i] = -EINVAL;

	if (!iodev->dev->of_node) {
		if (iodev->pdata) {
			pdata = iodev->pdata;
			goto common_reg;
		} else {
			dev_err(pdev->dev.parent,
				"Platform data or DT node not supplied\n");
			return -ENODEV;
		}
	}

	rdata = kzalloc(sizeof(*rdata) * s2mps11->rdev_num, GFP_KERNEL);
	if (!rdata)
		return -ENOMEM;

	for (i = 0; i < s2mps11->rdev_num; i++)
		rdata[i].name = regulators[i].name;

	ret = s2mps11_pmic_dt_parse(pdev, rdata, s2mps11);
	if (ret)
		goto out;

common_reg:
	platform_set_drvdata(pdev, s2mps11);

	config.dev = &pdev->dev;
	config.regmap = iodev->regmap_pmic;
	config.driver_data = s2mps11;
	config.ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
	config.ena_gpio_initialized = true;
	for (i = 0; i < s2mps11->rdev_num; i++) {
		struct regulator_dev *regulator;

		if (pdata) {
			config.init_data = pdata->regulators[i].initdata;
			config.of_node = pdata->regulators[i].reg_node;
		} else {
			config.init_data = rdata[i].init_data;
			config.of_node = rdata[i].of_node;
		}
		config.ena_gpio = s2mps11->ext_control_gpio[i];

		regulator = devm_regulator_register(&pdev->dev,
						&regulators[i], &config);
		if (IS_ERR(regulator)) {
			ret = PTR_ERR(regulator);
			dev_err(&pdev->dev, "regulator init failed for %d\n",
				i);
			goto out;
		}

		if (gpio_is_valid(s2mps11->ext_control_gpio[i])) {
			ret = s2mps14_pmic_enable_ext_control(s2mps11,
					regulator);
			if (ret < 0) {
				dev_err(&pdev->dev,
						"failed to enable GPIO control over %s: %d\n",
						regulator->desc->name, ret);
				goto out;
			}
		}
	}

out:
	kfree(rdata);

	return ret;
}
コード例 #22
0
ファイル: bman_portal.c プロジェクト: AshishNamdev/linux
static int bman_portal_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct device_node *node = dev->of_node;
	struct bm_portal_config *pcfg;
	struct resource *addr_phys[2];
	void __iomem *va;
	int irq, cpu;

	pcfg = devm_kmalloc(dev, sizeof(*pcfg), GFP_KERNEL);
	if (!pcfg)
		return -ENOMEM;

	pcfg->dev = dev;

	addr_phys[0] = platform_get_resource(pdev, IORESOURCE_MEM,
					     DPAA_PORTAL_CE);
	if (!addr_phys[0]) {
		dev_err(dev, "Can't get %s property 'reg::CE'\n",
			node->full_name);
		return -ENXIO;
	}

	addr_phys[1] = platform_get_resource(pdev, IORESOURCE_MEM,
					     DPAA_PORTAL_CI);
	if (!addr_phys[1]) {
		dev_err(dev, "Can't get %s property 'reg::CI'\n",
			node->full_name);
		return -ENXIO;
	}

	pcfg->cpu = -1;

	irq = platform_get_irq(pdev, 0);
	if (irq <= 0) {
		dev_err(dev, "Can't get %s IRQ'\n", node->full_name);
		return -ENXIO;
	}
	pcfg->irq = irq;

	va = ioremap_prot(addr_phys[0]->start, resource_size(addr_phys[0]), 0);
	if (!va) {
		dev_err(dev, "ioremap::CE failed\n");
		goto err_ioremap1;
	}

	pcfg->addr_virt[DPAA_PORTAL_CE] = va;

	va = ioremap_prot(addr_phys[1]->start, resource_size(addr_phys[1]),
			  _PAGE_GUARDED | _PAGE_NO_CACHE);
	if (!va) {
		dev_err(dev, "ioremap::CI failed\n");
		goto err_ioremap2;
	}

	pcfg->addr_virt[DPAA_PORTAL_CI] = va;

	spin_lock(&bman_lock);
	cpu = cpumask_next_zero(-1, &portal_cpus);
	if (cpu >= nr_cpu_ids) {
		/* unassigned portal, skip init */
		spin_unlock(&bman_lock);
		return 0;
	}

	cpumask_set_cpu(cpu, &portal_cpus);
	spin_unlock(&bman_lock);
	pcfg->cpu = cpu;

	if (!init_pcfg(pcfg)) {
		dev_err(dev, "portal init failed\n");
		goto err_portal_init;
	}

	/* clear irq affinity if assigned cpu is offline */
	if (!cpu_online(cpu))
		bman_offline_cpu(cpu);

	return 0;

err_portal_init:
	iounmap(pcfg->addr_virt[DPAA_PORTAL_CI]);
err_ioremap2:
	iounmap(pcfg->addr_virt[DPAA_PORTAL_CE]);
err_ioremap1:
	return -ENXIO;
}