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

qtnfmac: add interface ID to each packet



Add interface ID information to the tail of each transmitted packet
so that firmware can know to which interface the packet belongs to.
This is only needed if device supports HW switch capability.

Signed-off-by: default avatarIgor Mitsyanko <igor.mitsyanko.os@quantenna.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent decfc5c7
Loading
Loading
Loading
Loading
+17 −4
Original line number Diff line number Diff line
@@ -12,6 +12,16 @@

#define QTNF_MAX_MAC		3

#define HBM_FRAME_META_MAGIC_PATTERN_S	0xAB
#define HBM_FRAME_META_MAGIC_PATTERN_E	0xBA

struct qtnf_frame_meta_info {
	u8 magic_s;
	u8 ifidx;
	u8 macid;
	u8 magic_e;
} __packed;

enum qtnf_fw_state {
	QTNF_FW_STATE_DETACHED,
	QTNF_FW_STATE_BOOT_DONE,
@@ -31,8 +41,10 @@ struct qtnf_bus_ops {
	int (*control_tx)(struct qtnf_bus *, struct sk_buff *);

	/* data xfer methods */
	int (*data_tx)(struct qtnf_bus *, struct sk_buff *);
	int (*data_tx)(struct qtnf_bus *bus, struct sk_buff *skb,
		       unsigned int macid, unsigned int vifid);
	void (*data_tx_timeout)(struct qtnf_bus *, struct net_device *);
	void (*data_tx_use_meta_set)(struct qtnf_bus *bus, bool use_meta);
	void (*data_rx_start)(struct qtnf_bus *);
	void (*data_rx_stop)(struct qtnf_bus *);
};
@@ -42,7 +54,7 @@ struct qtnf_bus {
	enum qtnf_fw_state fw_state;
	u32 chip;
	u32 chiprev;
	const struct qtnf_bus_ops *bus_ops;
	struct qtnf_bus_ops *bus_ops;
	struct qtnf_wmac *mac[QTNF_MAX_MAC];
	struct qtnf_qlink_transport trans;
	struct qtnf_hw_info hw_info;
@@ -100,9 +112,10 @@ static inline void qtnf_bus_stop(struct qtnf_bus *bus)
	bus->bus_ops->stop(bus);
}

static inline int qtnf_bus_data_tx(struct qtnf_bus *bus, struct sk_buff *skb)
static inline int qtnf_bus_data_tx(struct qtnf_bus *bus, struct sk_buff *skb,
				   unsigned int macid, unsigned int vifid)
{
	return bus->bus_ops->data_tx(bus, skb);
	return bus->bus_ops->data_tx(bus, skb, macid, vifid);
}

static inline void
+10 −9
Original line number Diff line number Diff line
@@ -22,13 +22,6 @@ MODULE_PARM_DESC(slave_radar, "set 0 to disable radar detection in slave mode");

static struct dentry *qtnf_debugfs_dir;

struct qtnf_frame_meta_info {
	u8 magic_s;
	u8 ifidx;
	u8 macid;
	u8 magic_e;
} __packed;

struct qtnf_wmac *qtnf_core_get_mac(const struct qtnf_bus *bus, u8 macid)
{
	struct qtnf_wmac *mac = NULL;
@@ -121,7 +114,7 @@ qtnf_netdev_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
		return NETDEV_TX_OK;
	}

	return qtnf_bus_data_tx(mac->bus, skb);
	return qtnf_bus_data_tx(mac->bus, skb, mac->macid, vif->vifid);
}

/* Netdev handler for getting stats.
@@ -481,6 +474,9 @@ int qtnf_core_net_attach(struct qtnf_wmac *mac, struct qtnf_vif *vif,
	dev->tx_queue_len = 100;
	dev->ethtool_ops = &qtnf_ethtool_ops;

	if (mac->bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE)
		dev->needed_tailroom = sizeof(struct qtnf_frame_meta_info);

	qdev_vif = netdev_priv(dev);
	*((void **)qdev_vif) = vif;

@@ -723,6 +719,10 @@ int qtnf_core_attach(struct qtnf_bus *bus)
		goto error;
	}

	if ((bus->hw_info.hw_capab & QLINK_HW_CAPAB_HW_BRIDGE) &&
	    bus->bus_ops->data_tx_use_meta_set)
		bus->bus_ops->data_tx_use_meta_set(bus, true);

	if (bus->hw_info.num_mac > QTNF_MAX_MAC) {
		pr_err("no support for number of MACs=%u\n",
		       bus->hw_info.num_mac);
@@ -790,7 +790,8 @@ EXPORT_SYMBOL_GPL(qtnf_core_detach);

static inline int qtnf_is_frame_meta_magic_valid(struct qtnf_frame_meta_info *m)
{
	return m->magic_s == 0xAB && m->magic_e == 0xBA;
	return m->magic_s == HBM_FRAME_META_MAGIC_PATTERN_S &&
		m->magic_e == HBM_FRAME_META_MAGIC_PATTERN_E;
}

struct net_device *qtnf_classify_skb(struct qtnf_bus *bus, struct sk_buff *skb)
+44 −3
Original line number Diff line number Diff line
@@ -532,7 +532,7 @@ static int qtnf_tx_queue_ready(struct qtnf_pcie_pearl_state *ps)
	return 1;
}

static int qtnf_pcie_data_tx(struct qtnf_bus *bus, struct sk_buff *skb)
static int qtnf_pcie_skb_send(struct qtnf_bus *bus, struct sk_buff *skb)
{
	struct qtnf_pcie_pearl_state *ps = get_bus_priv(bus);
	struct qtnf_pcie_bus_priv *priv = &ps->base;
@@ -608,6 +608,38 @@ tx_done:
	return NETDEV_TX_OK;
}

static int qtnf_pcie_data_tx(struct qtnf_bus *bus, struct sk_buff *skb,
			     unsigned int macid, unsigned int vifid)
{
	return qtnf_pcie_skb_send(bus, skb);
}

static int qtnf_pcie_data_tx_meta(struct qtnf_bus *bus, struct sk_buff *skb,
				  unsigned int macid, unsigned int vifid)
{
	struct qtnf_frame_meta_info *meta;
	int tail_need = sizeof(*meta) - skb_tailroom(skb);
	int ret;

	if (tail_need > 0 && pskb_expand_head(skb, 0, tail_need, GFP_ATOMIC)) {
		skb->dev->stats.tx_dropped++;
		dev_kfree_skb_any(skb);
		return NETDEV_TX_OK;
	}

	meta = skb_put(skb, sizeof(*meta));
	meta->magic_s = HBM_FRAME_META_MAGIC_PATTERN_S;
	meta->magic_e = HBM_FRAME_META_MAGIC_PATTERN_E;
	meta->macid = macid;
	meta->ifidx = vifid;

	ret = qtnf_pcie_skb_send(bus, skb);
	if (unlikely(ret == NETDEV_TX_BUSY))
		__skb_trim(skb, skb->len - sizeof(*meta));

	return ret;
}

static irqreturn_t qtnf_pcie_pearl_interrupt(int irq, void *data)
{
	struct qtnf_bus *bus = (struct qtnf_bus *)data;
@@ -796,13 +828,22 @@ static void qtnf_pcie_data_rx_stop(struct qtnf_bus *bus)
	qtnf_disable_hdp_irqs(ps);
}

static const struct qtnf_bus_ops qtnf_pcie_pearl_bus_ops = {
static void qtnf_pearl_tx_use_meta_info_set(struct qtnf_bus *bus, bool use_meta)
{
	if (use_meta)
		bus->bus_ops->data_tx = qtnf_pcie_data_tx_meta;
	else
		bus->bus_ops->data_tx = qtnf_pcie_data_tx;
}

static struct qtnf_bus_ops qtnf_pcie_pearl_bus_ops = {
	/* control path methods */
	.control_tx	= qtnf_pcie_control_tx,

	/* data path methods */
	.data_tx		= qtnf_pcie_data_tx,
	.data_tx_timeout	= qtnf_pcie_data_tx_timeout,
	.data_tx_use_meta_set	= qtnf_pearl_tx_use_meta_info_set,
	.data_rx_start		= qtnf_pcie_data_rx_start,
	.data_rx_stop		= qtnf_pcie_data_rx_stop,
};
@@ -905,7 +946,7 @@ static int qtnf_ep_fw_send(struct pci_dev *pdev, uint32_t size,
	memcpy(pdata, pblk, len);
	hdr->crc = cpu_to_le32(~crc32(0, pdata, len));

	ret = qtnf_pcie_data_tx(bus, skb);
	ret = qtnf_pcie_skb_send(bus, skb);

	return (ret == NETDEV_TX_OK) ? len : 0;
}
+3 −2
Original line number Diff line number Diff line
@@ -497,7 +497,8 @@ static int qtnf_tx_queue_ready(struct qtnf_pcie_topaz_state *ts)
	return 1;
}

static int qtnf_pcie_data_tx(struct qtnf_bus *bus, struct sk_buff *skb)
static int qtnf_pcie_data_tx(struct qtnf_bus *bus, struct sk_buff *skb,
			     unsigned int macid, unsigned int vifid)
{
	struct qtnf_pcie_topaz_state *ts = (void *)get_bus_priv(bus);
	struct qtnf_pcie_bus_priv *priv = &ts->base;
@@ -740,7 +741,7 @@ static void qtnf_pcie_data_rx_stop(struct qtnf_bus *bus)
	napi_disable(&bus->mux_napi);
}

static const struct qtnf_bus_ops qtnf_pcie_topaz_bus_ops = {
static struct qtnf_bus_ops qtnf_pcie_topaz_bus_ops = {
	/* control path methods */
	.control_tx	= qtnf_pcie_control_tx,