Ejemplo n.º 1
0
static void if_usb_setup_firmware(struct lbs_private *priv)
{
	struct if_usb_card *cardp = priv->card;
	struct cmd_ds_set_boot2_ver b2_cmd;
	struct cmd_ds_802_11_fw_wake_method wake_method;

	b2_cmd.hdr.size = cpu_to_le16(sizeof(b2_cmd));
	b2_cmd.action = 0;
	b2_cmd.version = cardp->boot2_version;

	if (lbs_cmd_with_response(priv, CMD_SET_BOOT2_VER, &b2_cmd))
		lbs_deb_usb("Setting boot2 version failed\n");

	priv->wol_gpio = 2; /* Wake via GPIO2... */
	priv->wol_gap = 20; /* ... after 20ms    */
	lbs_host_sleep_cfg(priv, EHS_WAKE_ON_UNICAST_DATA);

	wake_method.hdr.size = cpu_to_le16(sizeof(wake_method));
	wake_method.action = cpu_to_le16(CMD_ACT_GET);
	if (lbs_cmd_with_response(priv, CMD_802_11_FW_WAKE_METHOD, &wake_method)) {
		lbs_pr_info("Firmware does not seem to support PS mode\n");
	} else {
		if (le16_to_cpu(wake_method.method) == CMD_WAKE_METHOD_COMMAND_INT) {
			lbs_deb_usb("Firmware seems to support PS with wake-via-command\n");
			priv->ps_supported = 1;
		} else {
			/* The versions which boot up this way don't seem to
			   work even if we set it to the command interrupt */
			lbs_pr_info("Firmware doesn't wake via command interrupt; disabling PS mode\n");
		}
	}
}
Ejemplo n.º 2
0
static int lbs_ethtool_get_eeprom(struct net_device *dev,
                                  struct ethtool_eeprom *eeprom, u8 * bytes)
{
	struct lbs_private *priv = dev->ml_priv;
	struct cmd_ds_802_11_eeprom_access cmd;
	int ret;

	if (eeprom->offset + eeprom->len > LBS_EEPROM_LEN ||
	    eeprom->len > LBS_EEPROM_READ_LEN) {
		ret = -EINVAL;
		goto out;
	}

	cmd.hdr.size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) -
		LBS_EEPROM_READ_LEN + eeprom->len);
	cmd.action = cpu_to_le16(CMD_ACT_GET);
	cmd.offset = cpu_to_le16(eeprom->offset);
	cmd.len    = cpu_to_le16(eeprom->len);
	ret = lbs_cmd_with_response(priv, CMD_802_11_EEPROM_ACCESS, &cmd);
	if (!ret)
		memcpy(bytes, cmd.value, eeprom->len);

out:
        return ret;
}
Ejemplo n.º 3
0
int lbs_start_iface(struct lbs_private *priv)
{
	struct cmd_ds_802_11_mac_address cmd;
	int ret;

	if (priv->power_restore) {
		ret = priv->power_restore(priv);
		if (ret)
			return ret;
	}

	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
	cmd.action = cpu_to_le16(CMD_ACT_SET);
	memcpy(cmd.macadd, priv->current_addr, ETH_ALEN);

	ret = lbs_cmd_with_response(priv, CMD_802_11_MAC_ADDRESS, &cmd);
	if (ret) {
		lbs_deb_net("set MAC address failed\n");
		goto err;
	}

	lbs_update_channel(priv);

	priv->iface_running = true;
	return 0;

err:
	if (priv->power_save)
		priv->power_save(priv);
	return ret;
}
Ejemplo n.º 4
0
static int __lbs_mesh_config_send(struct lbs_private *priv,
				  struct cmd_ds_mesh_config *cmd,
				  uint16_t action, uint16_t type)
{
	int ret;
	u16 command = CMD_MESH_CONFIG_OLD;

	lbs_deb_enter(LBS_DEB_CMD);

	/*
	 * Command id is 0xac for v10 FW along with mesh interface
	 * id in bits 14-13-12.
	 */
	if (priv->mesh_tlv == TLV_TYPE_MESH_ID)
		command = CMD_MESH_CONFIG |
			  (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET);

	cmd->hdr.command = cpu_to_le16(command);
	cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config));
	cmd->hdr.result = 0;

	cmd->type = cpu_to_le16(type);
	cmd->action = cpu_to_le16(action);

	ret = lbs_cmd_with_response(priv, command, cmd);

	lbs_deb_leave(LBS_DEB_CMD);
	return ret;
}
Ejemplo n.º 5
0
/**
 * lbs_mesh_bt_add_del - Add or delete Mesh Blinding Table entries
 *
 * @priv:	A pointer to &struct lbs_private structure
 * @add:	TRUE to add the entry, FALSE to delete it
 * @addr1:	Destination address to blind or unblind
 *
 * returns:	0 on success, error on failure
 */
int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1)
{
	struct cmd_ds_bt_access cmd;
	int ret = 0;

	lbs_deb_enter(LBS_DEB_CMD);

	BUG_ON(addr1 == NULL);

	memset(&cmd, 0, sizeof(cmd));
	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
	memcpy(cmd.addr1, addr1, ETH_ALEN);
	if (add) {
		cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_ADD);
		lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr",
			addr1, ETH_ALEN);
	} else {
		cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_DEL);
		lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr",
			addr1, ETH_ALEN);
	}

	ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);

	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
	return ret;
}
Ejemplo n.º 6
0
static ssize_t lbs_threshold_read(uint16_t tlv_type, uint16_t event_mask,
				  struct file *file, char __user *userbuf,
				  size_t count, loff_t *ppos)
{
	struct cmd_ds_802_11_subscribe_event *subscribed;
	struct mrvl_ie_thresholds *got;
	struct lbs_private *priv = file->private_data;
	ssize_t ret = 0;
	size_t pos = 0;
	char *buf;
	u8 value;
	u8 freq;
	int events = 0;

	buf = (char *)get_zeroed_page(GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

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

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

	ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, subscribed);
	if (ret)
		goto out_cmd;

	got = lbs_tlv_find(tlv_type, subscribed->tlv, sizeof(subscribed->tlv));
	if (got) {
		value = got->value;
		freq  = got->freq;
		events = le16_to_cpu(subscribed->events);

		pos += snprintf(buf, len, "%d %d %d\n", value, freq,
				!!(events & event_mask));
	}

	ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);

 out_cmd:
	kfree(subscribed);

 out_page:
	free_page((unsigned long)buf);
	return ret;
}
Ejemplo n.º 7
0
Archivo: mesh.c Proyecto: mdamt/linux
static int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
		    struct cmd_ds_mesh_access *cmd)
{
	int ret;

	cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS);
	cmd->hdr.size = cpu_to_le16(sizeof(*cmd));
	cmd->hdr.result = 0;

	cmd->action = cpu_to_le16(cmd_action);

	ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd);

	return ret;
}
Ejemplo n.º 8
0
/**
 * lbs_mesh_bt_reset - Reset/clear the mesh blinding table
 *
 * @priv:	A pointer to &struct lbs_private structure
 *
 * returns:	0 on success, error on failure
 */
int lbs_mesh_bt_reset(struct lbs_private *priv)
{
	struct cmd_ds_bt_access cmd;
	int ret = 0;

	lbs_deb_enter(LBS_DEB_CMD);

	memset(&cmd, 0, sizeof(cmd));
	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
	cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_RESET);

	ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);

	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
	return ret;
}
Ejemplo n.º 9
0
/**
 * lbs_cmd_fwt_access - Access the mesh forwarding table
 *
 * @priv:	A pointer to &struct lbs_private structure
 * @cmd_action:	The forwarding table action to perform
 * @cmd:	The pre-filled FWT_ACCESS command
 *
 * returns:	0 on success and 'cmd' will be filled with the
 *		firmware's response
 */
int lbs_cmd_fwt_access(struct lbs_private *priv, u16 cmd_action,
			struct cmd_ds_fwt_access *cmd)
{
	int ret;

	lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);

	cmd->hdr.command = cpu_to_le16(CMD_FWT_ACCESS);
	cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access));
	cmd->hdr.result = 0;
	cmd->action = cpu_to_le16(cmd_action);

	ret = lbs_cmd_with_response(priv, CMD_FWT_ACCESS, cmd);

	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
	return 0;
}
Ejemplo n.º 10
0
int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
		    struct cmd_ds_mesh_access *cmd)
{
	int ret;

	lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);

	cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS);
	cmd->hdr.size = cpu_to_le16(sizeof(*cmd));
	cmd->hdr.result = 0;

	cmd->action = cpu_to_le16(cmd_action);

	ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd);

	lbs_deb_leave(LBS_DEB_CMD);
	return ret;
}
Ejemplo n.º 11
0
/**
 * lbs_mesh_bt_get_inverted - Gets the inverted status of the mesh
 * blinding table
 *
 * Normally the firmware "blinds" or ignores traffic from mesh nodes in the
 * table, but an inverted table allows *only* traffic from nodes listed in
 * the table.
 *
 * @priv:	A pointer to &struct lbs_private structure
 * @inverted:  	On success, TRUE if the blinding table is inverted,
 *		FALSE if it is not inverted
 *
 * returns:	0 on success, error on failure
 */
int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted)
{
	struct cmd_ds_bt_access cmd;
	int ret = 0;

	lbs_deb_enter(LBS_DEB_CMD);

	BUG_ON(inverted == NULL);

	memset(&cmd, 0, sizeof(cmd));
	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
	cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_GET_INVERT);

	ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
	if (ret == 0)
		*inverted = !!cmd.id;

	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
	return ret;
}
Ejemplo n.º 12
0
/**
 * lbs_mesh_bt_get_entry - List an entry in the mesh blinding table
 *
 * @priv:	A pointer to &struct lbs_private structure
 * @id:		The ID of the entry to list
 * @addr1:	MAC address associated with the table entry
 *
 * returns: 	   	0 on success, error on failure
 */
int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1)
{
	struct cmd_ds_bt_access cmd;
	int ret = 0;

	lbs_deb_enter(LBS_DEB_CMD);

	BUG_ON(addr1 == NULL);

	memset(&cmd, 0, sizeof(cmd));
	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
	cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_SET_INVERT);
	cmd.id = cpu_to_le32(id);

	ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
	if (ret == 0)
		memcpy(addr1, cmd.addr1, sizeof(cmd.addr1));

	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
	return ret;
}
Ejemplo n.º 13
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;
	ssize_t buf_size;
	int value, freq, new_mask;
	uint16_t curr_mask;
	char *buf;
	int ret;

	buf = (char *)get_zeroed_page(GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	buf_size = min(count, len - 1);
	if (copy_from_user(buf, userbuf, buf_size)) {
		ret = -EFAULT;
		goto out_page;
	}
	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:
	free_page((unsigned long)buf);
	return ret;
}