Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bc70732f authored by Igor Mitsyanko's avatar Igor Mitsyanko Committed by Kalle Valo
Browse files

qtnfmac: send EAPOL frames via control path



Use control path to send EAPOL frames to make sure they are
sent with higher priority with aggregation disabled.

Signed-off-by: default avatarIgor Mitsyanko <igor.mitsyanko.os@quantenna.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 72b3270e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ struct qtnf_bus {
	struct napi_struct mux_napi;
	struct net_device mux_dev;
	struct workqueue_struct *workqueue;
	struct workqueue_struct *hprio_workqueue;
	struct work_struct fw_work;
	struct work_struct event_work;
	struct mutex bus_lock; /* lock during command/event processing */
+11 −6
Original line number Diff line number Diff line
@@ -144,6 +144,7 @@ int qtnf_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
{
	struct net_device *netdev =  wdev->netdev;
	struct qtnf_vif *vif;
	struct sk_buff *skb;

	if (WARN_ON(!netdev))
		return -EFAULT;
@@ -157,6 +158,11 @@ int qtnf_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
	if (netif_carrier_ok(netdev))
		netif_carrier_off(netdev);

	while ((skb = skb_dequeue(&vif->high_pri_tx_queue)))
		dev_kfree_skb_any(skb);

	cancel_work_sync(&vif->high_pri_tx_work);

	if (netdev->reg_state == NETREG_REGISTERED)
		unregister_netdevice(netdev);

@@ -424,13 +430,13 @@ qtnf_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
	*cookie = short_cookie;

	if (params->offchan)
		flags |= QLINK_MGMT_FRAME_TX_FLAG_OFFCHAN;
		flags |= QLINK_FRAME_TX_FLAG_OFFCHAN;

	if (params->no_cck)
		flags |= QLINK_MGMT_FRAME_TX_FLAG_NO_CCK;
		flags |= QLINK_FRAME_TX_FLAG_NO_CCK;

	if (params->dont_wait_for_ack)
		flags |= QLINK_MGMT_FRAME_TX_FLAG_ACK_NOWAIT;
		flags |= QLINK_FRAME_TX_FLAG_ACK_NOWAIT;

	/* If channel is not specified, pass "freq = 0" to tell device
	 * firmware to use current channel.
@@ -445,9 +451,8 @@ qtnf_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
		 le16_to_cpu(mgmt_frame->frame_control), mgmt_frame->da,
		 params->len, short_cookie, flags);

	return qtnf_cmd_send_mgmt_frame(vif, short_cookie, flags,
					freq,
					params->buf, params->len);
	return qtnf_cmd_send_frame(vif, short_cookie, flags,
				   freq, params->buf, params->len);
}

static int
+5 −5
Original line number Diff line number Diff line
@@ -381,11 +381,11 @@ int qtnf_cmd_send_register_mgmt(struct qtnf_vif *vif, u16 frame_type, bool reg)
	return ret;
}

int qtnf_cmd_send_mgmt_frame(struct qtnf_vif *vif, u32 cookie, u16 flags,
int qtnf_cmd_send_frame(struct qtnf_vif *vif, u32 cookie, u16 flags,
			u16 freq, const u8 *buf, size_t len)
{
	struct sk_buff *cmd_skb;
	struct qlink_cmd_mgmt_frame_tx *cmd;
	struct qlink_cmd_frame_tx *cmd;
	int ret;

	if (sizeof(*cmd) + len > QTNF_MAX_CMD_BUF_SIZE) {
@@ -395,14 +395,14 @@ int qtnf_cmd_send_mgmt_frame(struct qtnf_vif *vif, u32 cookie, u16 flags,
	}

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

	qtnf_bus_lock(vif->mac->bus);

	cmd = (struct qlink_cmd_mgmt_frame_tx *)cmd_skb->data;
	cmd = (struct qlink_cmd_frame_tx *)cmd_skb->data;
	cmd->cookie = cpu_to_le32(cookie);
	cmd->freq = cpu_to_le16(freq);
	cmd->flags = cpu_to_le16(flags);
+2 −2
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ int qtnf_cmd_send_start_ap(struct qtnf_vif *vif,
			   const struct cfg80211_ap_settings *s);
int qtnf_cmd_send_stop_ap(struct qtnf_vif *vif);
int qtnf_cmd_send_register_mgmt(struct qtnf_vif *vif, u16 frame_type, bool reg);
int qtnf_cmd_send_mgmt_frame(struct qtnf_vif *vif, u32 cookie, u16 flags,
int qtnf_cmd_send_frame(struct qtnf_vif *vif, u32 cookie, u16 flags,
			u16 freq, const u8 *buf, size_t len);
int qtnf_cmd_send_mgmt_set_appie(struct qtnf_vif *vif, u8 frame_type,
				 const u8 *buf, size_t len);
+42 −3
Original line number Diff line number Diff line
@@ -368,6 +368,23 @@ static void qtnf_mac_scan_timeout(struct work_struct *work)
	qtnf_mac_scan_finish(mac, true);
}

static void qtnf_vif_send_data_high_pri(struct work_struct *work)
{
	struct qtnf_vif *vif =
		container_of(work, struct qtnf_vif, high_pri_tx_work);
	struct sk_buff *skb;

	if (!vif->netdev ||
	    vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED)
		return;

	while ((skb = skb_dequeue(&vif->high_pri_tx_queue))) {
		qtnf_cmd_send_frame(vif, 0, QLINK_FRAME_TX_FLAG_8023,
				    0, skb->data, skb->len);
		dev_kfree_skb_any(skb);
	}
}

static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus,
					     unsigned int macid)
{
@@ -395,7 +412,8 @@ static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus,
		vif->mac = mac;
		vif->vifid = i;
		qtnf_sta_list_init(&vif->sta_list);

		INIT_WORK(&vif->high_pri_tx_work, qtnf_vif_send_data_high_pri);
		skb_queue_head_init(&vif->high_pri_tx_queue);
		vif->stats64 = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
		if (!vif->stats64)
			pr_warn("VIF%u.%u: per cpu stats allocation failed\n",
@@ -598,6 +616,13 @@ int qtnf_core_attach(struct qtnf_bus *bus)
		goto error;
	}

	bus->hprio_workqueue = alloc_workqueue("QTNF_HPRI", WQ_HIGHPRI, 0);
	if (!bus->hprio_workqueue) {
		pr_err("failed to alloc high prio workqueue\n");
		ret = -ENOMEM;
		goto error;
	}

	INIT_WORK(&bus->event_work, qtnf_event_work_handler);

	ret = qtnf_cmd_send_init_fw(bus);
@@ -607,7 +632,6 @@ int qtnf_core_attach(struct qtnf_bus *bus)
	}

	bus->fw_state = QTNF_FW_STATE_ACTIVE;

	ret = qtnf_cmd_get_hw_info(bus);
	if (ret) {
		pr_err("failed to get HW info: %d\n", ret);
@@ -642,7 +666,6 @@ int qtnf_core_attach(struct qtnf_bus *bus)

error:
	qtnf_core_detach(bus);

	return ret;
}
EXPORT_SYMBOL_GPL(qtnf_core_attach);
@@ -664,6 +687,13 @@ void qtnf_core_detach(struct qtnf_bus *bus)
	if (bus->workqueue) {
		flush_workqueue(bus->workqueue);
		destroy_workqueue(bus->workqueue);
		bus->workqueue = NULL;
	}

	if (bus->hprio_workqueue) {
		flush_workqueue(bus->hprio_workqueue);
		destroy_workqueue(bus->hprio_workqueue);
		bus->hprio_workqueue = NULL;
	}

	qtnf_trans_free(bus);
@@ -800,6 +830,15 @@ void qtnf_update_tx_stats(struct net_device *ndev, const struct sk_buff *skb)
}
EXPORT_SYMBOL_GPL(qtnf_update_tx_stats);

void qtnf_packet_send_hi_pri(struct sk_buff *skb)
{
	struct qtnf_vif *vif = qtnf_netdev_get_priv(skb->dev);

	skb_queue_tail(&vif->high_pri_tx_queue, skb);
	queue_work(vif->mac->bus->hprio_workqueue, &vif->high_pri_tx_work);
}
EXPORT_SYMBOL_GPL(qtnf_packet_send_hi_pri);

MODULE_AUTHOR("Quantenna Communications");
MODULE_DESCRIPTION("Quantenna 802.11 wireless LAN FullMAC driver.");
MODULE_LICENSE("GPL");
Loading