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

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
......@@ -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
......
......@@ -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)
......
......@@ -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 @@ static int qtnf_pcie_data_tx(struct qtnf_bus *bus, struct sk_buff *skb)
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;
}
......
......@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment