Commit 0756e913 authored by Mikhail Karpenko's avatar Mikhail Karpenko Committed by Kalle Valo
Browse files

qtnfmac: add support for getting/setting transmit power



Add new command for getting/setting current transmit power
and propagate requests from user space to firmware.

Signed-off-by: default avatarMikhail Karpenko <mkarpenko@quantenna.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 239ce8a7
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -897,6 +897,45 @@ static int qtnf_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
	return ret;
}

static int qtnf_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
			     int *dbm)
{
	struct qtnf_vif *vif = qtnf_netdev_get_priv(wdev->netdev);
	int ret;

	ret = qtnf_cmd_get_tx_power(vif, dbm);
	if (ret)
		pr_err("MAC%u: failed to get Tx power\n", vif->mac->macid);

	return ret;
}

static int qtnf_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
			     enum nl80211_tx_power_setting type, int mbm)
{
	struct qtnf_vif *vif;
	int ret;

	if (wdev) {
		vif = qtnf_netdev_get_priv(wdev->netdev);
	} else {
		struct qtnf_wmac *mac = wiphy_priv(wiphy);

		vif = qtnf_mac_get_base_vif(mac);
		if (!vif) {
			pr_err("MAC%u: primary VIF is not configured\n",
			       mac->macid);
			return -EFAULT;
		}
	}

	ret = qtnf_cmd_set_tx_power(vif, type, mbm);
	if (ret)
		pr_err("MAC%u: failed to set Tx power\n", vif->mac->macid);

	return ret;
}

#ifdef CONFIG_PM
static int qtnf_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wowlan)
{
@@ -991,6 +1030,8 @@ static struct cfg80211_ops qtn_cfg80211_ops = {
	.start_radar_detection	= qtnf_start_radar_detection,
	.set_mac_acl		= qtnf_set_mac_acl,
	.set_power_mgmt		= qtnf_set_power_mgmt,
	.get_tx_power		= qtnf_get_tx_power,
	.set_tx_power		= qtnf_set_tx_power,
#ifdef CONFIG_PM
	.suspend		= qtnf_suspend,
	.resume			= qtnf_resume,
+65 −0
Original line number Diff line number Diff line
@@ -2643,6 +2643,71 @@ out:
	return ret;
}

int qtnf_cmd_get_tx_power(const struct qtnf_vif *vif, int *dbm)
{
	struct qtnf_bus *bus = vif->mac->bus;
	const struct qlink_resp_txpwr *resp;
	struct sk_buff *resp_skb = NULL;
	struct qlink_cmd_txpwr *cmd;
	struct sk_buff *cmd_skb;
	int ret = 0;

	cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
					    QLINK_CMD_TXPWR, sizeof(*cmd));
	if (!cmd_skb)
		return -ENOMEM;

	cmd = (struct qlink_cmd_txpwr *)cmd_skb->data;
	cmd->op_type = QLINK_TXPWR_GET;

	qtnf_bus_lock(bus);

	ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb,
				       sizeof(*resp), NULL);
	if (ret)
		goto out;

	resp = (const struct qlink_resp_txpwr *)resp_skb->data;
	*dbm = MBM_TO_DBM(le32_to_cpu(resp->txpwr));

out:
	qtnf_bus_unlock(bus);
	consume_skb(resp_skb);

	return ret;
}

int qtnf_cmd_set_tx_power(const struct qtnf_vif *vif,
			  enum nl80211_tx_power_setting type, int mbm)
{
	struct qtnf_bus *bus = vif->mac->bus;
	const struct qlink_resp_txpwr *resp;
	struct sk_buff *resp_skb = NULL;
	struct qlink_cmd_txpwr *cmd;
	struct sk_buff *cmd_skb;
	int ret = 0;

	cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid,
					    QLINK_CMD_TXPWR, sizeof(*cmd));
	if (!cmd_skb)
		return -ENOMEM;

	cmd = (struct qlink_cmd_txpwr *)cmd_skb->data;
	cmd->op_type = QLINK_TXPWR_SET;
	cmd->txpwr_setting = type;
	cmd->txpwr = cpu_to_le32(mbm);

	qtnf_bus_lock(bus);

	ret = qtnf_cmd_send_with_reply(bus, cmd_skb, &resp_skb,
				       sizeof(*resp), NULL);

	qtnf_bus_unlock(bus);
	consume_skb(resp_skb);

	return ret;
}

int qtnf_cmd_send_wowlan_set(const struct qtnf_vif *vif,
			     const struct cfg80211_wowlan *wowl)
{
+3 −0
Original line number Diff line number Diff line
@@ -70,6 +70,9 @@ int qtnf_cmd_start_cac(const struct qtnf_vif *vif,
int qtnf_cmd_set_mac_acl(const struct qtnf_vif *vif,
			 const struct cfg80211_acl_data *params);
int qtnf_cmd_send_pm_set(const struct qtnf_vif *vif, u8 pm_mode, int timeout);
int qtnf_cmd_get_tx_power(const struct qtnf_vif *vif, int *dbm);
int qtnf_cmd_set_tx_power(const struct qtnf_vif *vif,
			  enum nl80211_tx_power_setting type, int mbm);
int qtnf_cmd_send_wowlan_set(const struct qtnf_vif *vif,
			     const struct cfg80211_wowlan *wowl);

+42 −0
Original line number Diff line number Diff line
@@ -217,6 +217,8 @@ struct qlink_sta_info_state {
 *	command is supported only if device reports QLINK_HW_SUPPORTS_REG_UPDATE
 *	capability.
 * @QLINK_CMD_START_CAC: start radar detection procedure on a specified channel.
 * @QLINK_CMD_TXPWR: get or set current channel transmit power for
 *	the specified MAC.
 */
enum qlink_cmd_type {
	QLINK_CMD_FW_INIT		= 0x0001,
@@ -254,6 +256,7 @@ enum qlink_cmd_type {
	QLINK_CMD_PM_SET		= 0x0062,
	QLINK_CMD_WOWLAN_SET		= 0x0063,
	QLINK_CMD_EXTERNAL_AUTH		= 0x0066,
	QLINK_CMD_TXPWR			= 0x0067,
};

/**
@@ -718,6 +721,32 @@ struct qlink_cmd_pm_set {
	u8 pm_mode;
} __packed;

/**
 * enum qlink_txpwr_op - transmit power operation type
 * @QLINK_TXPWR_SET: set tx power
 * @QLINK_TXPWR_GET: get current tx power setting
 */
enum qlink_txpwr_op {
	QLINK_TXPWR_SET,
	QLINK_TXPWR_GET
};

/**
 * struct qlink_cmd_txpwr - get or set current transmit power
 *
 * @txpwr: new transmit power setting, in mBm
 * @txpwr_setting: transmit power setting type, one of
 *	&enum nl80211_tx_power_setting
 * @op_type: type of operation, one of &enum qlink_txpwr_op
 */
struct qlink_cmd_txpwr {
	struct qlink_cmd chdr;
	__le32 txpwr;
	u8 txpwr_setting;
	u8 op_type;
	u8 rsvd[2];
} __packed;

/**
 * enum qlink_wowlan_trigger
 *
@@ -944,6 +973,19 @@ struct qlink_resp_channel_get {
	struct qlink_chandef chan;
} __packed;

/**
 * struct qlink_resp_txpwr - response for QLINK_CMD_TXPWR command
 *
 * This response is intended for QLINK_TXPWR_GET operation and does not
 * contain any meaningful information in case of QLINK_TXPWR_SET operation.
 *
 * @txpwr: current transmit power setting, in mBm
 */
struct qlink_resp_txpwr {
	struct qlink_resp rhdr;
	__le32 txpwr;
} __packed;

/* QLINK Events messages related definitions
 */