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

Commit 3df2cd36 authored by Vladimir Kondratiev's avatar Vladimir Kondratiev Committed by John W. Linville
Browse files

wil6210: multiple connect - initial support



Enable multiple (up to 8 - HW/FW limitation) simultaneous connections.
Each connection has its own CID (connection ID) that describes chip's
beam-forming entity. Tx Vring should refer to correct CID for frame to reach
its destination.

Signed-off-by: default avatarVladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 59f7c0a9
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -110,15 +110,19 @@ static int wil_cfg80211_get_station(struct wiphy *wiphy,
{
	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
	int rc;

	int cid = wil_find_cid(wil, mac);
	struct wmi_notify_req_cmd cmd = {
		.cid = 0,
		.cid = cid,
		.interval_usec = 0,
	};

	if (memcmp(mac, wil->dst_addr[0], ETH_ALEN))
	wil_info(wil, "%s(%pM) CID %d\n", __func__, mac, cid);
	if (cid < 0)
		return -ENOENT;

	/* WMI_NOTIFY_REQ_DONE_EVENTID handler fills wil->stats.bf_mcs */
	/* TODO: keep stats per CID */
	rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd),
		      WMI_NOTIFY_REQ_DONE_EVENTID, NULL, 0, 20);
	if (rc)
+45 −0
Original line number Diff line number Diff line
@@ -71,8 +71,13 @@ static int wil_vring_debugfs_show(struct seq_file *s, void *data)
	for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) {
		struct vring *vring = &(wil->vring_tx[i]);
		if (vring->va) {
			int cid = wil->vring2cid_tid[i][0];
			int tid = wil->vring2cid_tid[i][1];
			char name[10];
			snprintf(name, sizeof(name), "tx_%2d", i);

			seq_printf(s, "\n%pM CID %d TID %d\n",
				   wil->sta[cid].addr, cid, tid);
			wil_print_vring(s, wil, name, vring, '_', 'H');
		}
	}
@@ -592,6 +597,45 @@ static const struct file_operations fops_temp = {
	.llseek		= seq_lseek,
};

/*---------Station matrix------------*/

static int wil_sta_debugfs_show(struct seq_file *s, void *data)
{
	struct wil6210_priv *wil = s->private;
	int i;

	for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
		struct wil_sta_info *p = &wil->sta[i];
		char *status = "unknown";
		switch (p->status) {
		case wil_sta_unused:
			status = "unused   ";
			break;
		case wil_sta_conn_pending:
			status = "pending  ";
			break;
		case wil_sta_connected:
			status = "connected";
			break;
		}
		seq_printf(s, "[%d] %pM %s\n", i, p->addr, status);
	}

	return 0;
}

static int wil_sta_seq_open(struct inode *inode, struct file *file)
{
	return single_open(file, wil_sta_debugfs_show, inode->i_private);
}

static const struct file_operations fops_sta = {
	.open		= wil_sta_seq_open,
	.release	= single_release,
	.read		= seq_read,
	.llseek		= seq_lseek,
};

/*----------------*/
int wil6210_debugfs_init(struct wil6210_priv *wil)
{
@@ -603,6 +647,7 @@ int wil6210_debugfs_init(struct wil6210_priv *wil)

	debugfs_create_file("mbox", S_IRUGO, dbg, wil, &fops_mbox);
	debugfs_create_file("vrings", S_IRUGO, dbg, wil, &fops_vring);
	debugfs_create_file("stations", S_IRUGO, dbg, wil, &fops_sta);
	debugfs_create_file("desc", S_IRUGO, dbg, wil, &fops_txdesc);
	debugfs_create_u32("desc_index", S_IRUGO | S_IWUSR, dbg,
			   &dbg_txdesc_index);
+23 −1
Original line number Diff line number Diff line
@@ -113,14 +113,20 @@ static void wil_connect_worker(struct work_struct *work)

	rc = wil_vring_init_tx(wil, 0, WIL6210_TX_RING_SIZE, cid, 0);
	wil->pending_connect_cid = -1;
	if (rc == 0)
	if (rc == 0) {
		wil->sta[cid].status = wil_sta_connected;
		wil_link_on(wil);
	} else {
		wil->sta[cid].status = wil_sta_unused;
	}
}

int wil_priv_init(struct wil6210_priv *wil)
{
	wil_dbg_misc(wil, "%s()\n", __func__);

	memset(wil->sta, 0, sizeof(wil->sta));

	mutex_init(&wil->mutex);
	mutex_init(&wil->wmi_mutex);

@@ -370,3 +376,19 @@ int wil_down(struct wil6210_priv *wil)

	return rc;
}

int wil_find_cid(struct wil6210_priv *wil, const u8 *mac)
{
	int i;
	int rc = -ENOENT;

	for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
		if ((wil->sta[i].status != wil_sta_unused) &&
		    (0 == memcmp(wil->sta[i].addr, mac, ETH_ALEN))) {
			rc = i;
			break;
		}
	}

	return rc;
}
+39 −8
Original line number Diff line number Diff line
@@ -613,6 +613,9 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
	}
	vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr);

	wil->vring2cid_tid[id][0] = cid;
	wil->vring2cid_tid[id][1] = tid;

	return 0;
 out_free:
	wil_vring_free(wil, vring, 1);
@@ -634,10 +637,27 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
static struct vring *wil_find_tx_vring(struct wil6210_priv *wil,
				       struct sk_buff *skb)
{
	struct vring *v = &wil->vring_tx[0];
	int i;
	struct ethhdr *eth = (void *)skb->data;
	int cid = wil_find_cid(wil, eth->h_dest);

	if (cid < 0)
		return NULL;

	if (v->va)
	/* TODO: fix for multiple TID */
	for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) {
		if (wil->vring2cid_tid[i][0] == cid) {
			struct vring *v = &wil->vring_tx[i];
			wil_dbg_txrx(wil, "%s(%pM) -> [%d]\n",
				     __func__, eth->h_dest, i);
			if (v->va) {
				return v;
			} else {
				wil_dbg_txrx(wil, "vring[%d] not valid\n", i);
				return NULL;
			}
		}
	}

	return NULL;
}
@@ -740,9 +760,6 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
	}
	_d = &(vring->va[i].tx);

	/* FIXME FW can accept only unicast frames for the peer */
	memcpy(skb->data, wil->dst_addr[vring_index], ETH_ALEN);

	pa = dma_map_single(dev, skb->data,
			skb_headlen(skb), DMA_TO_DEVICE);

@@ -836,6 +853,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{
	struct wil6210_priv *wil = ndev_to_wil(ndev);
	struct ethhdr *eth = (void *)skb->data;
	struct vring *vring;
	int rc;

@@ -854,9 +872,22 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
	}

	/* find vring */
	if (is_unicast_ether_addr(eth->h_dest)) {
		vring = wil_find_tx_vring(wil, skb);
	} else {
		int i = 0;
		/* TODO: duplicate for all CID's */
		vring = &wil->vring_tx[i];
		if (vring->va) {
			int cid = wil->vring2cid_tid[i][0];
			/* FIXME FW can accept only unicast frames */
			memcpy(skb->data, wil->sta[cid].addr, ETH_ALEN);
		} else {
			vring = NULL;
		}
	}
	if (!vring) {
		wil_err(wil, "No Tx VRING available\n");
		wil_err(wil, "No Tx VRING found for %pM\n", eth->h_dest);
		goto drop;
	}
	/* set up vring entry */
+21 −1
Original line number Diff line number Diff line
@@ -226,6 +226,24 @@ struct wil6210_stats {
	u16 peer_tx_sector;
};

enum wil_sta_status {
	wil_sta_unused = 0,
	wil_sta_conn_pending = 1,
	wil_sta_connected = 2,
};
/**
 * struct wil_sta_info - data for peer
 *
 * Peer identified by its CID (connection ID)
 * NIC performs beam forming for each peer;
 * if no beam forming done, frame exchange is not
 * possible.
 */
struct wil_sta_info {
	u8 addr[ETH_ALEN];
	enum wil_sta_status status;
};

struct wil6210_priv {
	struct pci_dev *pdev;
	int n_msi;
@@ -267,7 +285,8 @@ struct wil6210_priv {
	/* DMA related */
	struct vring vring_rx;
	struct vring vring_tx[WIL6210_MAX_TX_RINGS];
	u8 dst_addr[WIL6210_MAX_TX_RINGS][ETH_ALEN];
	u8 vring2cid_tid[WIL6210_MAX_TX_RINGS][2]; /* [0] - CID, [1] - TID */
	struct wil_sta_info sta[WIL6210_MAX_CID];
	/* scan */
	struct cfg80211_scan_request *scan_request;

@@ -334,6 +353,7 @@ void wil_link_off(struct wil6210_priv *wil);
int wil_up(struct wil6210_priv *wil);
int wil_down(struct wil6210_priv *wil);
void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r);
int wil_find_cid(struct wil6210_priv *wil, const u8 *mac);

void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr);
void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr);
Loading