Exemple #1
0
/*
 * Proc regrdwr file write handler.
 *
 * This function is called when the 'regrdwr' file is opened for writing
 *
 * This function can be used to write to a register.
 */
static ssize_t
mwifiex_regrdwr_write(struct file *file,
		      const char __user *ubuf, size_t count, loff_t *ppos)
{
	char *buf;
	int ret;
	u32 reg_type = 0, reg_offset = 0, reg_value = UINT_MAX;

	buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
	if (IS_ERR(buf))
		return PTR_ERR(buf);

	sscanf(buf, "%u %x %x", &reg_type, &reg_offset, &reg_value);

	if (reg_type == 0 || reg_offset == 0) {
		ret = -EINVAL;
		goto done;
	} else {
		saved_reg_type = reg_type;
		saved_reg_offset = reg_offset;
		saved_reg_value = reg_value;
		ret = count;
	}
done:
	kfree(buf);
	return ret;
}
Exemple #2
0
static ssize_t cec_error_inj_write(struct file *file,
	const char __user *ubuf, size_t count, loff_t *ppos)
{
	struct seq_file *sf = file->private_data;
	struct cec_adapter *adap = sf->private;
	char *buf;
	char *line;
	char *p;

	buf = memdup_user_nul(ubuf, min_t(size_t, PAGE_SIZE, count));
	if (IS_ERR(buf))
		return PTR_ERR(buf);
	p = buf;
	while (p && *p) {
		p = skip_spaces(p);
		line = strsep(&p, "\n");
		if (!*line || *line == '#')
			continue;
		if (!adap->ops->error_inj_parse_line(adap, line)) {
			kfree(buf);
			return -EINVAL;
		}
	}
	kfree(buf);
	return count;
}
Exemple #3
0
/*
 * Proc rdeeprom file write handler.
 *
 * This function is called when the 'rdeeprom' file is opened for writing
 *
 * This function can be used to write to a RDEEPROM location.
 */
static ssize_t
mwifiex_rdeeprom_write(struct file *file,
		       const char __user *ubuf, size_t count, loff_t *ppos)
{
	char *buf;
	int ret = 0;
	int offset = -1, bytes = -1;

	buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
	if (IS_ERR(buf))
		return PTR_ERR(buf);

	sscanf(buf, "%d %d", &offset, &bytes);

	if (offset == -1 || bytes == -1) {
		ret = -EINVAL;
		goto done;
	} else {
		saved_offset = offset;
		saved_bytes = bytes;
		ret = count;
	}
done:
	kfree(buf);
	return ret;
}
Exemple #4
0
static ssize_t display_crc_ctl_write(struct file *file, const char __user *ubuf,
				     size_t len, loff_t *offp)
{
	struct seq_file *m = file->private_data;
	struct drm_i915_private *dev_priv = m->private;
	char *tmpbuf;
	int ret;

	if (len == 0)
		return 0;

	if (len > PAGE_SIZE - 1) {
		DRM_DEBUG_DRIVER("expected <%lu bytes into pipe crc control\n",
				 PAGE_SIZE);
		return -E2BIG;
	}

	tmpbuf = memdup_user_nul(ubuf, len);
	if (IS_ERR(tmpbuf))
		return PTR_ERR(tmpbuf);

	ret = display_crc_ctl_parse(dev_priv, tmpbuf, len);

	kfree(tmpbuf);
	if (ret < 0)
		return ret;

	*offp += len;
	return len;
}
Exemple #5
0
/* Copy in a whole string from userspace into kernelspace. */
static char * copyin_string(char __user *user, size_t len)
{
	if ((ssize_t)len < 0 || (ssize_t)(len + 1) < 0)
		return ERR_PTR(-EINVAL);

	return memdup_user_nul(user, len);
}
Exemple #6
0
static ssize_t sel_write_avc_cache_threshold(struct file *file,
					     const char __user *buf,
					     size_t count, loff_t *ppos)

{
	char *page;
	ssize_t ret;
	unsigned int new_value;

	ret = task_has_security(current, SECURITY__SETSECPARAM);
	if (ret)
		return ret;

	if (count >= PAGE_SIZE)
		return -ENOMEM;

	/* No partial writes. */
	if (*ppos != 0)
		return -EINVAL;

	page = memdup_user_nul(buf, count);
	if (IS_ERR(page))
		return PTR_ERR(page);

	ret = -EINVAL;
	if (sscanf(page, "%u", &new_value) != 1)
		goto out;

	avc_cache_threshold = new_value;

	ret = count;
out:
	kfree(page);
	return ret;
}
Exemple #7
0
static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf,
				      size_t count, loff_t *ppos)
{
	char *page;
	ssize_t length;
	unsigned int new_value;

	length = task_has_security(current, SECURITY__SETCHECKREQPROT);
	if (length)
		return length;

	if (count >= PAGE_SIZE)
		return -ENOMEM;

	/* No partial writes. */
	if (*ppos != 0)
		return -EINVAL;

	page = memdup_user_nul(buf, count);
	if (IS_ERR(page))
		return PTR_ERR(page);

	length = -EINVAL;
	if (sscanf(page, "%u", &new_value) != 1)
		goto out;

	selinux_checkreqprot = new_value ? 1 : 0;
	length = count;
out:
	kfree(page);
	return length;
}
Exemple #8
0
static ssize_t lbs_wrrf_write(struct file *file,
				    const char __user *userbuf,
				    size_t count, loff_t *ppos)
{

	struct lbs_private *priv = file->private_data;
	ssize_t res;
	u32 offset, value;
	char *buf;

	buf = memdup_user_nul(userbuf, min(count, len - 1));
	if (IS_ERR(buf))
		return PTR_ERR(buf);

	res = sscanf(buf, "%x %x", &offset, &value);
	if (res != 2) {
		res = -EFAULT;
		goto out_unlock;
	}

	res = lbs_set_reg(priv, CMD_RF_REG_ACCESS, offset, value);
	mdelay(10);

	if (!res)
		res = count;
out_unlock:
	kfree(buf);
	return res;
}
Exemple #9
0
/*---write channel 1..4 to rxon for it, 0 to rxoff---*/
static ssize_t wil_write_file_rxon(struct file *file, const char __user *buf,
				   size_t len, loff_t *ppos)
{
	struct wil6210_priv *wil = file->private_data;
	int rc;
	long channel;
	bool on;

	char *kbuf = memdup_user_nul(buf, len);

	if (IS_ERR(kbuf))
		return PTR_ERR(kbuf);
	rc = kstrtol(kbuf, 0, &channel);
	kfree(kbuf);
	if (rc)
		return rc;

	if ((channel < 0) || (channel > 4)) {
		wil_err(wil, "Invalid channel %ld\n", channel);
		return -EINVAL;
	}
	on = !!channel;

	if (on) {
		rc = wmi_set_channel(wil, (int)channel);
		if (rc)
			return rc;
	}

	rc = wmi_rxon(wil, on);
	if (rc)
		return rc;

	return len;
}
Exemple #10
0
/* Proc hscfg file write handler
 * This function can be used to configure the host sleep parameters.
 */
static ssize_t
mwifiex_hscfg_write(struct file *file, const char __user *ubuf,
		    size_t count, loff_t *ppos)
{
	struct mwifiex_private *priv = (void *)file->private_data;
	char *buf;
	int ret, arg_num;
	struct mwifiex_ds_hs_cfg hscfg;
	int conditions = HS_CFG_COND_DEF;
	u32 gpio = HS_CFG_GPIO_DEF, gap = HS_CFG_GAP_DEF;

	buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
	if (IS_ERR(buf))
		return PTR_ERR(buf);

	arg_num = sscanf(buf, "%d %x %x", &conditions, &gpio, &gap);

	memset(&hscfg, 0, sizeof(struct mwifiex_ds_hs_cfg));

	if (arg_num > 3) {
		mwifiex_dbg(priv->adapter, ERROR,
			    "Too many arguments\n");
		ret = -EINVAL;
		goto done;
	}

	if (arg_num >= 1 && arg_num < 3)
		mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET,
				      MWIFIEX_SYNC_CMD, &hscfg);

	if (arg_num) {
		if (conditions == HS_CFG_CANCEL) {
			mwifiex_cancel_hs(priv, MWIFIEX_ASYNC_CMD);
			ret = count;
			goto done;
		}
		hscfg.conditions = conditions;
	}
	if (arg_num >= 2)
		hscfg.gpio = gpio;
	if (arg_num == 3)
		hscfg.gap = gap;

	hscfg.is_invoke_hostcmd = false;
	mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET,
			      MWIFIEX_SYNC_CMD, &hscfg);

	mwifiex_enable_hs(priv->adapter);
	priv->adapter->hs_enabling = false;
	ret = count;
done:
	kfree(buf);
	return ret;
}
Exemple #11
0
static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
			      size_t count, loff_t *ppos)
{
	char *page = NULL;
	ssize_t length;
	int new_value;
	unsigned index = file_inode(filep)->i_ino & SEL_INO_MASK;
	const char *name = filep->f_path.dentry->d_name.name;

	mutex_lock(&sel_mutex);

	length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
			      SECCLASS_SECURITY, SECURITY__SETBOOL,
			      NULL);
	if (length)
		goto out;

	length = -EINVAL;
	if (index >= bool_num || strcmp(name, bool_pending_names[index]))
		goto out;

	length = -ENOMEM;
	if (count >= PAGE_SIZE)
		goto out;

	/* No partial writes. */
	length = -EINVAL;
	if (*ppos != 0)
		goto out;

	page = memdup_user_nul(buf, count);
	if (IS_ERR(page)) {
		length = PTR_ERR(page);
		page = NULL;
		goto out;
	}

	length = -EINVAL;
	if (sscanf(page, "%d", &new_value) != 1)
		goto out;

	if (new_value)
		new_value = 1;

	bool_pending_values[index] = new_value;
	length = count;

out:
	mutex_unlock(&sel_mutex);
	kfree(page);
	return length;
}
Exemple #12
0
static ssize_t lbs_rdrf_write(struct file *file,
				    const char __user *userbuf,
				    size_t count, loff_t *ppos)
{
	struct lbs_private *priv = file->private_data;
	char *buf;

	buf = memdup_user_nul(userbuf, min(count, len - 1));
	if (IS_ERR(buf))
		return PTR_ERR(buf);

	priv->rf_offset = simple_strtoul(buf, NULL, 16);
	kfree(buf);
	return count;
}
Exemple #13
0
/* Copy in a whole string from userspace into kernelspace. */
static int copyin_string(char __user *user, size_t len, char **ptr)
{
	char *tmp;

	if ((ssize_t)len < 0 || (ssize_t)(len + 1) < 0)
		return -EINVAL;

	tmp = memdup_user_nul(user, len);
	if (IS_ERR(tmp))
		return PTR_ERR(tmp);

	*ptr = tmp;

	return 0;
}
Exemple #14
0
/**
 * lbs_debugfs_write - proc write function
 *
 * @f:		file pointer
 * @buf:	pointer to data buffer
 * @cnt:	data number to write
 * @ppos:	file position
 *
 * returns:	amount of data written
 */
static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf,
			    size_t cnt, loff_t *ppos)
{
	int r, i;
	char *pdata;
	char *p;
	char *p0;
	char *p1;
	char *p2;
	struct debug_data *d = f->private_data;

	if (cnt == 0)
		return 0;

	pdata = memdup_user_nul(buf, cnt);
	if (IS_ERR(pdata))
		return PTR_ERR(pdata);

	p0 = pdata;
	for (i = 0; i < num_of_items; i++) {
		do {
			p = strstr(p0, d[i].name);
			if (p == NULL)
				break;
			p1 = strchr(p, '\n');
			if (p1 == NULL)
				break;
			p0 = p1++;
			p2 = strchr(p, '=');
			if (!p2)
				break;
			p2++;
			r = simple_strtoul(p2, NULL, 0);
			if (d[i].size == 1)
				*((u8 *) d[i].addr) = (u8) r;
			else if (d[i].size == 2)
				*((u16 *) d[i].addr) = (u16) r;
			else if (d[i].size == 4)
				*((u32 *) d[i].addr) = (u32) r;
			else if (d[i].size == 8)
				*((u64 *) d[i].addr) = (u64) r;
			break;
		} while (1);
	}
	kfree(pdata);

	return (ssize_t)cnt;
}
Exemple #15
0
static ssize_t sel_commit_bools_write(struct file *filep,
				      const char __user *buf,
				      size_t count, loff_t *ppos)
{
	char *page = NULL;
	ssize_t length;
	int new_value;

	mutex_lock(&sel_mutex);

	length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
			      SECCLASS_SECURITY, SECURITY__SETBOOL,
			      NULL);
	if (length)
		goto out;

	length = -ENOMEM;
	if (count >= PAGE_SIZE)
		goto out;

	/* No partial writes. */
	length = -EINVAL;
	if (*ppos != 0)
		goto out;

	page = memdup_user_nul(buf, count);
	if (IS_ERR(page)) {
		length = PTR_ERR(page);
		page = NULL;
		goto out;
	}

	length = -EINVAL;
	if (sscanf(page, "%d", &new_value) != 1)
		goto out;

	length = 0;
	if (new_value && bool_pending_values)
		length = security_set_bools(bool_num, bool_pending_values);

	if (!length)
		length = count;

out:
	mutex_unlock(&sel_mutex);
	kfree(page);
	return length;
}
Exemple #16
0
static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
				 size_t count, loff_t *ppos)

{
	char *page = NULL;
	ssize_t length;
	int new_value;

	if (count >= PAGE_SIZE)
		return -ENOMEM;

	/* No partial writes. */
	if (*ppos != 0)
		return -EINVAL;

	page = memdup_user_nul(buf, count);
	if (IS_ERR(page))
		return PTR_ERR(page);

	length = -EINVAL;
	if (sscanf(page, "%d", &new_value) != 1)
		goto out;

	new_value = !!new_value;

	if (new_value != selinux_enforcing) {
		length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
				      SECCLASS_SECURITY, SECURITY__SETENFORCE,
				      NULL);
		if (length)
			goto out;
		audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS,
			"enforcing=%d old_enforcing=%d auid=%u ses=%u",
			new_value, selinux_enforcing,
			from_kuid(&init_user_ns, audit_get_loginuid(current)),
			audit_get_sessionid(current));
		selinux_enforcing = new_value;
		if (selinux_enforcing)
			avc_ss_reset(0);
		selnl_notify_setenforce(selinux_enforcing);
		selinux_status_update_setenforce(selinux_enforcing);
	}
	length = count;
out:
	kfree(page);
	return length;
}
Exemple #17
0
/* Proc memrw file write handler.
 * This function is called when the 'memrw' file is opened for writing
 * This function can be used to write to a memory location.
 */
static ssize_t
mwifiex_memrw_write(struct file *file, const char __user *ubuf, size_t count,
		    loff_t *ppos)
{
	int ret;
	char cmd;
	struct mwifiex_ds_mem_rw mem_rw;
	u16 cmd_action;
	struct mwifiex_private *priv = (void *)file->private_data;
	char *buf;

	buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
	if (IS_ERR(buf))
		return PTR_ERR(buf);

	ret = sscanf(buf, "%c %x %x", &cmd, &mem_rw.addr, &mem_rw.value);
	if (ret != 3) {
		ret = -EINVAL;
		goto done;
	}

	if ((cmd == 'r') || (cmd == 'R')) {
		cmd_action = HostCmd_ACT_GEN_GET;
		mem_rw.value = 0;
	} else if ((cmd == 'w') || (cmd == 'W')) {
		cmd_action = HostCmd_ACT_GEN_SET;
	} else {
		ret = -EINVAL;
		goto done;
	}

	memcpy(&priv->mem_rw, &mem_rw, sizeof(mem_rw));
	if (mwifiex_send_cmd(priv, HostCmd_CMD_MEM_ACCESS, cmd_action, 0,
			     &mem_rw, true))
		ret = -1;
	else
		ret = count;

done:
	kfree(buf);
	return ret;
}
Exemple #18
0
static ssize_t lbs_host_sleep_write(struct file *file,
				const char __user *user_buf, size_t count,
				loff_t *ppos)
{
	struct lbs_private *priv = file->private_data;
	ssize_t ret;
	int host_sleep;
	char *buf;

	buf = memdup_user_nul(user_buf, min(count, len - 1));
	if (IS_ERR(buf))
		return PTR_ERR(buf);

	ret = sscanf(buf, "%d", &host_sleep);
	if (ret != 1) {
		ret = -EINVAL;
		goto out_unlock;
	}

	if (host_sleep == 0)
		ret = lbs_set_host_sleep(priv, 0);
	else if (host_sleep == 1) {
		if (priv->wol_criteria == EHS_REMOVE_WAKEUP) {
			netdev_info(priv->dev,
				    "wake parameters not configured\n");
			ret = -EINVAL;
			goto out_unlock;
		}
		ret = lbs_set_host_sleep(priv, 1);
	} else {
		netdev_err(priv->dev, "invalid option\n");
		ret = -EINVAL;
	}

	if (!ret)
		ret = count;

out_unlock:
	kfree(buf);
	return ret;
}
Exemple #19
0
static ssize_t crc_control_write(struct file *file, const char __user *ubuf,
				 size_t len, loff_t *offp)
{
	struct seq_file *m = file->private_data;
	struct drm_crtc *crtc = m->private;
	struct drm_crtc_crc *crc = &crtc->crc;
	char *source;

	if (len == 0)
		return 0;

	if (len > PAGE_SIZE - 1) {
		DRM_DEBUG_KMS("Expected < %lu bytes into crtc crc control\n",
			      PAGE_SIZE);
		return -E2BIG;
	}

	source = memdup_user_nul(ubuf, len);
	if (IS_ERR(source))
		return PTR_ERR(source);

	if (source[len] == '\n')
		source[len] = '\0';

	spin_lock_irq(&crc->lock);

	if (crc->opened) {
		spin_unlock_irq(&crc->lock);
		kfree(source);
		return -EBUSY;
	}

	kfree(crc->source);
	crc->source = source;

	spin_unlock_irq(&crc->lock);

	*offp += len;
	return len;
}
Exemple #20
0
static ssize_t sel_write_disable(struct file *file, const char __user *buf,
				 size_t count, loff_t *ppos)

{
	char *page;
	ssize_t length;
	int new_value;

	if (count >= PAGE_SIZE)
		return -ENOMEM;

	/* No partial writes. */
	if (*ppos != 0)
		return -EINVAL;

	page = memdup_user_nul(buf, count);
	if (IS_ERR(page))
		return PTR_ERR(page);

	length = -EINVAL;
	if (sscanf(page, "%d", &new_value) != 1)
		goto out;

	if (new_value) {
		length = selinux_disable();
		if (length)
			goto out;
		audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS,
			"selinux=0 auid=%u ses=%u",
			from_kuid(&init_user_ns, audit_get_loginuid(current)),
			audit_get_sessionid(current));
	}

	length = count;
out:
	kfree(page);
	return length;
}
Exemple #21
0
/* Proc debug_mask file read handler.
 * This function is called when the 'debug_mask' file is opened for reading
 * This function can be used read driver debugging mask value.
 */
static ssize_t
mwifiex_debug_mask_write(struct file *file, const char __user *ubuf,
			 size_t count, loff_t *ppos)
{
	int ret;
	unsigned long debug_mask;
	struct mwifiex_private *priv = (void *)file->private_data;
	char *buf;

	buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
	if (IS_ERR(buf))
		return PTR_ERR(buf);

	if (kstrtoul(buf, 0, &debug_mask)) {
		ret = -EINVAL;
		goto done;
	}

	priv->adapter->debug_mask = debug_mask;
	ret = count;
done:
	kfree(buf);
	return ret;
}
Exemple #22
0
static ssize_t lbs_sleepparams_write(struct file *file,
				const char __user *user_buf, size_t count,
				loff_t *ppos)
{
	struct lbs_private *priv = file->private_data;
	ssize_t ret;
	struct sleep_params sp;
	int p1, p2, p3, p4, p5, p6;
	char *buf;

	buf = memdup_user_nul(user_buf, min(count, len - 1));
	if (IS_ERR(buf))
		return PTR_ERR(buf);

	ret = sscanf(buf, "%d %d %d %d %d %d", &p1, &p2, &p3, &p4, &p5, &p6);
	if (ret != 6) {
		ret = -EINVAL;
		goto out_unlock;
	}
	sp.sp_error = p1;
	sp.sp_offset = p2;
	sp.sp_stabletime = p3;
	sp.sp_calcontrol = p4;
	sp.sp_extsleepclk = p5;
	sp.sp_reserved = p6;

	ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_SET, &sp);
	if (!ret)
		ret = count;
	else if (ret > 0)
		ret = -EINVAL;

out_unlock:
	kfree(buf);
	return ret;
}
Exemple #23
0
/*
 * command the cache
 */
static ssize_t cachefiles_daemon_write(struct file *file,
				       const char __user *_data,
				       size_t datalen,
				       loff_t *pos)
{
	const struct cachefiles_daemon_cmd *cmd;
	struct cachefiles_cache *cache = file->private_data;
	ssize_t ret;
	char *data, *args, *cp;

	//_enter(",,%zu,", datalen);

	ASSERT(cache);

	if (test_bit(CACHEFILES_DEAD, &cache->flags))
		return -EIO;

	if (datalen < 0 || datalen > PAGE_SIZE - 1)
		return -EOPNOTSUPP;

	/* drag the command string into the kernel so we can parse it */
	data = memdup_user_nul(_data, datalen);
	if (IS_ERR(data))
		return PTR_ERR(data);

	ret = -EINVAL;
	if (memchr(data, '\0', datalen))
		goto error;

	/* strip any newline */
	cp = memchr(data, '\n', datalen);
	if (cp) {
		if (cp == data)
			goto error;

		*cp = '\0';
	}

	/* parse the command */
	ret = -EOPNOTSUPP;

	for (args = data; *args; args++)
		if (isspace(*args))
			break;
	if (*args) {
		if (args == data)
			goto error;
		*args = '\0';
		args = skip_spaces(++args);
	}

	/* run the appropriate command handler */
	for (cmd = cachefiles_daemon_cmds; cmd->name[0]; cmd++)
		if (strcmp(cmd->name, data) == 0)
			goto found_command;

error:
	kfree(data);
	//_leave(" = %zd", ret);
	return ret;

found_command:
	mutex_lock(&cache->daemon_mutex);

	ret = -EIO;
	if (!test_bit(CACHEFILES_DEAD, &cache->flags))
		ret = cmd->handler(cache, args);

	mutex_unlock(&cache->daemon_mutex);

	if (ret == 0)
		ret = datalen;
	goto error;
}
Exemple #24
0
static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask,
				   struct file *file,
				   const char __user *userbuf, size_t count,
				   loff_t *ppos)
{
	struct cmd_ds_802_11_subscribe_event *events;
	struct mrvl_ie_thresholds *tlv;
	struct lbs_private *priv = file->private_data;
	int value, freq, new_mask;
	uint16_t curr_mask;
	char *buf;
	int ret;

	buf = memdup_user_nul(userbuf, min(count, len - 1));
	if (IS_ERR(buf))
		return PTR_ERR(buf);

	ret = sscanf(buf, "%d %d %d", &value, &freq, &new_mask);
	if (ret != 3) {
		ret = -EINVAL;
		goto out_page;
	}
	events = kzalloc(sizeof(*events), GFP_KERNEL);
	if (!events) {
		ret = -ENOMEM;
		goto out_page;
	}

	events->hdr.size = cpu_to_le16(sizeof(*events));
	events->action = cpu_to_le16(CMD_ACT_GET);

	ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events);
	if (ret)
		goto out_events;

	curr_mask = le16_to_cpu(events->events);

	if (new_mask)
		new_mask = curr_mask | event_mask;
	else
		new_mask = curr_mask & ~event_mask;

	/* Now everything is set and we can send stuff down to the firmware */

	tlv = (void *)events->tlv;

	events->action = cpu_to_le16(CMD_ACT_SET);
	events->events = cpu_to_le16(new_mask);
	tlv->header.type = cpu_to_le16(tlv_type);
	tlv->header.len = cpu_to_le16(sizeof(*tlv) - sizeof(tlv->header));
	tlv->value = value;
	if (tlv_type != TLV_TYPE_BCNMISS)
		tlv->freq = freq;

	/* The command header, the action, the event mask, and one TLV */
	events->hdr.size = cpu_to_le16(sizeof(events->hdr) + 4 + sizeof(*tlv));

	ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events);

	if (!ret)
		ret = count;
 out_events:
	kfree(events);
 out_page:
	kfree(buf);
	return ret;
}