Commit 2b04a661 authored by David S. Miller's avatar David S. Miller

Merge branch 'cxgb4-add-mirror-action-support-for-TC-MATCHALL'

Rahul Lakkireddy says:

====================
cxgb4: add mirror action support for TC-MATCHALL

This series of patches add support to mirror all ingress traffic
for TC-MATCHALL ingress offload.

Patch 1 adds support to dynamically create a mirror Virtual Interface
(VI) that accepts all mirror ingress traffic when mirror action is
set in TC-MATCHALL offload.

Patch 2 adds support to allocate mirror Rxqs and setup RSS for the
mirror VI.

Patch 3 adds support to replicate all the main VI configuration to
mirror VI. This includes replicating MTU, promiscuous mode,
all-multicast mode, and enabled netdev Rx feature offloads.

v3:
- Replace mirror VI refcount_t with normal u32 variable in all patches.
- Add back calling cxgb4_port_mirror_start() in cxgb_open(), which
  was there in v1, but got missed in v2 during refactoring, in patch
  3.

v2:
- Add mutex to protect all mirror VI data, instead of just
  mirror Rxqs, in patch 1 and 2.
- Remove the un-needed mirror Rxq mutex in patch 2.
- Simplify the replication code by refactoring t4_set_rxmode()
  to handle mirror VI, instead of duplicating the t4_set_rxmode()
  calls in multiple places in patch 3.
====================
Reviewed-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 75603a31 696c278f
...@@ -679,6 +679,12 @@ struct port_info { ...@@ -679,6 +679,12 @@ struct port_info {
u8 rx_cchan; u8 rx_cchan;
bool tc_block_shared; bool tc_block_shared;
/* Mirror VI information */
u16 viid_mirror;
u16 nmirrorqsets;
u32 vi_mirror_count;
struct mutex vi_mirror_mutex; /* Sync access to Mirror VI info */
}; };
struct dentry; struct dentry;
...@@ -705,6 +711,13 @@ enum { ...@@ -705,6 +711,13 @@ enum {
ULP_CRYPTO_KTLS_INLINE = 1 << 3, ULP_CRYPTO_KTLS_INLINE = 1 << 3,
}; };
#define CXGB4_MIRROR_RXQ_DEFAULT_DESC_NUM 1024
#define CXGB4_MIRROR_RXQ_DEFAULT_DESC_SIZE 64
#define CXGB4_MIRROR_RXQ_DEFAULT_INTR_USEC 5
#define CXGB4_MIRROR_RXQ_DEFAULT_PKT_CNT 8
#define CXGB4_MIRROR_FLQ_DEFAULT_DESC_NUM 72
struct rx_sw_desc; struct rx_sw_desc;
struct sge_fl { /* SGE free-buffer queue state */ struct sge_fl { /* SGE free-buffer queue state */
...@@ -954,12 +967,15 @@ struct sge { ...@@ -954,12 +967,15 @@ struct sge {
struct sge_eohw_txq *eohw_txq; struct sge_eohw_txq *eohw_txq;
struct sge_ofld_rxq *eohw_rxq; struct sge_ofld_rxq *eohw_rxq;
struct sge_eth_rxq *mirror_rxq[NCHAN];
u16 max_ethqsets; /* # of available Ethernet queue sets */ u16 max_ethqsets; /* # of available Ethernet queue sets */
u16 ethqsets; /* # of active Ethernet queue sets */ u16 ethqsets; /* # of active Ethernet queue sets */
u16 ethtxq_rover; /* Tx queue to clean up next */ u16 ethtxq_rover; /* Tx queue to clean up next */
u16 ofldqsets; /* # of active ofld queue sets */ u16 ofldqsets; /* # of active ofld queue sets */
u16 nqs_per_uld; /* # of Rx queues per ULD */ u16 nqs_per_uld; /* # of Rx queues per ULD */
u16 eoqsets; /* # of ETHOFLD queues */ u16 eoqsets; /* # of ETHOFLD queues */
u16 mirrorqsets; /* # of Mirror queues */
u16 timer_val[SGE_NTIMERS]; u16 timer_val[SGE_NTIMERS];
u8 counter_val[SGE_NCOUNTERS]; u8 counter_val[SGE_NCOUNTERS];
...@@ -1857,6 +1873,8 @@ int t4_init_rss_mode(struct adapter *adap, int mbox); ...@@ -1857,6 +1873,8 @@ int t4_init_rss_mode(struct adapter *adap, int mbox);
int t4_init_portinfo(struct port_info *pi, int mbox, int t4_init_portinfo(struct port_info *pi, int mbox,
int port, int pf, int vf, u8 mac[]); int port, int pf, int vf, u8 mac[]);
int t4_port_init(struct adapter *adap, int mbox, int pf, int vf); int t4_port_init(struct adapter *adap, int mbox, int pf, int vf);
int t4_init_port_mirror(struct port_info *pi, u8 mbox, u8 port, u8 pf, u8 vf,
u16 *mirror_viid);
void t4_fatal_err(struct adapter *adapter); void t4_fatal_err(struct adapter *adapter);
unsigned int t4_chip_rss_size(struct adapter *adapter); unsigned int t4_chip_rss_size(struct adapter *adapter);
int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid, int t4_config_rss_range(struct adapter *adapter, int mbox, unsigned int viid,
...@@ -1966,8 +1984,8 @@ int t4_free_vi(struct adapter *adap, unsigned int mbox, ...@@ -1966,8 +1984,8 @@ int t4_free_vi(struct adapter *adap, unsigned int mbox,
unsigned int pf, unsigned int vf, unsigned int pf, unsigned int vf,
unsigned int viid); unsigned int viid);
int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid, int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid,
int mtu, int promisc, int all_multi, int bcast, int vlanex, unsigned int viid_mirror, int mtu, int promisc, int all_multi,
bool sleep_ok); int bcast, int vlanex, bool sleep_ok);
int t4_free_raw_mac_filt(struct adapter *adap, unsigned int viid, int t4_free_raw_mac_filt(struct adapter *adap, unsigned int viid,
const u8 *addr, const u8 *mask, unsigned int idx, const u8 *addr, const u8 *mask, unsigned int idx,
u8 lookup_type, u8 port_id, bool sleep_ok); u8 lookup_type, u8 port_id, bool sleep_ok);
...@@ -2141,6 +2159,8 @@ int cxgb_open(struct net_device *dev); ...@@ -2141,6 +2159,8 @@ int cxgb_open(struct net_device *dev);
int cxgb_close(struct net_device *dev); int cxgb_close(struct net_device *dev);
void cxgb4_enable_rx(struct adapter *adap, struct sge_rspq *q); void cxgb4_enable_rx(struct adapter *adap, struct sge_rspq *q);
void cxgb4_quiesce_rx(struct sge_rspq *q); void cxgb4_quiesce_rx(struct sge_rspq *q);
int cxgb4_port_mirror_alloc(struct net_device *dev);
void cxgb4_port_mirror_free(struct net_device *dev);
#ifdef CONFIG_CHELSIO_TLS_DEVICE #ifdef CONFIG_CHELSIO_TLS_DEVICE
int cxgb4_set_ktls_feature(struct adapter *adap, bool enable); int cxgb4_set_ktls_feature(struct adapter *adap, bool enable);
#endif #endif
......
...@@ -2742,6 +2742,58 @@ do { \ ...@@ -2742,6 +2742,58 @@ do { \
} }
r -= eth_entries; r -= eth_entries;
for_each_port(adap, j) {
struct port_info *pi = adap2pinfo(adap, j);
const struct sge_eth_rxq *rx;
mutex_lock(&pi->vi_mirror_mutex);
if (!pi->vi_mirror_count) {
mutex_unlock(&pi->vi_mirror_mutex);
continue;
}
if (r >= DIV_ROUND_UP(pi->nmirrorqsets, 4)) {
r -= DIV_ROUND_UP(pi->nmirrorqsets, 4);
mutex_unlock(&pi->vi_mirror_mutex);
continue;
}
rx = &s->mirror_rxq[j][r * 4];
n = min(4, pi->nmirrorqsets - 4 * r);
S("QType:", "Mirror-Rxq");
S("Interface:",
rx[i].rspq.netdev ? rx[i].rspq.netdev->name : "N/A");
R("RspQ ID:", rspq.abs_id);
R("RspQ size:", rspq.size);
R("RspQE size:", rspq.iqe_len);
R("RspQ CIDX:", rspq.cidx);
R("RspQ Gen:", rspq.gen);
S3("u", "Intr delay:", qtimer_val(adap, &rx[i].rspq));
S3("u", "Intr pktcnt:", s->counter_val[rx[i].rspq.pktcnt_idx]);
R("FL ID:", fl.cntxt_id);
R("FL size:", fl.size - 8);
R("FL pend:", fl.pend_cred);
R("FL avail:", fl.avail);
R("FL PIDX:", fl.pidx);
R("FL CIDX:", fl.cidx);
RL("RxPackets:", stats.pkts);
RL("RxCSO:", stats.rx_cso);
RL("VLANxtract:", stats.vlan_ex);
RL("LROmerged:", stats.lro_merged);
RL("LROpackets:", stats.lro_pkts);
RL("RxDrops:", stats.rx_drops);
RL("RxBadPkts:", stats.bad_rx_pkts);
RL("FLAllocErr:", fl.alloc_failed);
RL("FLLrgAlcErr:", fl.large_alloc_failed);
RL("FLMapErr:", fl.mapping_err);
RL("FLLow:", fl.low);
RL("FLStarving:", fl.starving);
mutex_unlock(&pi->vi_mirror_mutex);
goto out;
}
if (!adap->tc_mqprio) if (!adap->tc_mqprio)
goto skip_mqprio; goto skip_mqprio;
...@@ -3098,9 +3150,10 @@ do { \ ...@@ -3098,9 +3150,10 @@ do { \
return 0; return 0;
} }
static int sge_queue_entries(const struct adapter *adap) static int sge_queue_entries(struct adapter *adap)
{ {
int i, tot_uld_entries = 0, eohw_entries = 0, eosw_entries = 0; int i, tot_uld_entries = 0, eohw_entries = 0, eosw_entries = 0;
int mirror_rxq_entries = 0;
if (adap->tc_mqprio) { if (adap->tc_mqprio) {
struct cxgb4_tc_port_mqprio *port_mqprio; struct cxgb4_tc_port_mqprio *port_mqprio;
...@@ -3123,6 +3176,15 @@ static int sge_queue_entries(const struct adapter *adap) ...@@ -3123,6 +3176,15 @@ static int sge_queue_entries(const struct adapter *adap)
mutex_unlock(&adap->tc_mqprio->mqprio_mutex); mutex_unlock(&adap->tc_mqprio->mqprio_mutex);
} }
for_each_port(adap, i) {
struct port_info *pi = adap2pinfo(adap, i);
mutex_lock(&pi->vi_mirror_mutex);
if (pi->vi_mirror_count)
mirror_rxq_entries += DIV_ROUND_UP(pi->nmirrorqsets, 4);
mutex_unlock(&pi->vi_mirror_mutex);
}
if (!is_uld(adap)) if (!is_uld(adap))
goto lld_only; goto lld_only;
...@@ -3137,7 +3199,7 @@ static int sge_queue_entries(const struct adapter *adap) ...@@ -3137,7 +3199,7 @@ static int sge_queue_entries(const struct adapter *adap)
mutex_unlock(&uld_mutex); mutex_unlock(&uld_mutex);
lld_only: lld_only:
return DIV_ROUND_UP(adap->sge.ethqsets, 4) + return DIV_ROUND_UP(adap->sge.ethqsets, 4) + mirror_rxq_entries +
eohw_entries + eosw_entries + tot_uld_entries + eohw_entries + eosw_entries + tot_uld_entries +
DIV_ROUND_UP(MAX_CTRL_QUEUES, 4) + 1; DIV_ROUND_UP(MAX_CTRL_QUEUES, 4) + 1;
} }
......
...@@ -372,6 +372,7 @@ void cxgb4_process_flow_actions(struct net_device *in, ...@@ -372,6 +372,7 @@ void cxgb4_process_flow_actions(struct net_device *in,
case FLOW_ACTION_DROP: case FLOW_ACTION_DROP:
fs->action = FILTER_DROP; fs->action = FILTER_DROP;
break; break;
case FLOW_ACTION_MIRRED:
case FLOW_ACTION_REDIRECT: { case FLOW_ACTION_REDIRECT: {
struct net_device *out = act->dev; struct net_device *out = act->dev;
struct port_info *pi = netdev_priv(out); struct port_info *pi = netdev_priv(out);
...@@ -529,7 +530,8 @@ static bool valid_pedit_action(struct net_device *dev, ...@@ -529,7 +530,8 @@ static bool valid_pedit_action(struct net_device *dev,
int cxgb4_validate_flow_actions(struct net_device *dev, int cxgb4_validate_flow_actions(struct net_device *dev,
struct flow_action *actions, struct flow_action *actions,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack,
u8 matchall_filter)
{ {
struct flow_action_entry *act; struct flow_action_entry *act;
bool act_redir = false; bool act_redir = false;
...@@ -546,11 +548,19 @@ int cxgb4_validate_flow_actions(struct net_device *dev, ...@@ -546,11 +548,19 @@ int cxgb4_validate_flow_actions(struct net_device *dev,
case FLOW_ACTION_DROP: case FLOW_ACTION_DROP:
/* Do nothing */ /* Do nothing */
break; break;
case FLOW_ACTION_MIRRED:
case FLOW_ACTION_REDIRECT: { case FLOW_ACTION_REDIRECT: {
struct adapter *adap = netdev2adap(dev); struct adapter *adap = netdev2adap(dev);
struct net_device *n_dev, *target_dev; struct net_device *n_dev, *target_dev;
unsigned int i;
bool found = false; bool found = false;
unsigned int i;
if (act->id == FLOW_ACTION_MIRRED &&
!matchall_filter) {
NL_SET_ERR_MSG_MOD(extack,
"Egress mirror action is only supported for tc-matchall");
return -EOPNOTSUPP;
}
target_dev = act->dev; target_dev = act->dev;
for_each_port(adap, i) { for_each_port(adap, i) {
...@@ -689,7 +699,7 @@ int cxgb4_flow_rule_replace(struct net_device *dev, struct flow_rule *rule, ...@@ -689,7 +699,7 @@ int cxgb4_flow_rule_replace(struct net_device *dev, struct flow_rule *rule,
u8 inet_family; u8 inet_family;
int fidx, ret; int fidx, ret;
if (cxgb4_validate_flow_actions(dev, &rule->action, extack)) if (cxgb4_validate_flow_actions(dev, &rule->action, extack, 0))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (cxgb4_validate_flow_match(dev, rule)) if (cxgb4_validate_flow_match(dev, rule))
......
...@@ -113,7 +113,8 @@ void cxgb4_process_flow_actions(struct net_device *in, ...@@ -113,7 +113,8 @@ void cxgb4_process_flow_actions(struct net_device *in,
struct ch_filter_specification *fs); struct ch_filter_specification *fs);
int cxgb4_validate_flow_actions(struct net_device *dev, int cxgb4_validate_flow_actions(struct net_device *dev,
struct flow_action *actions, struct flow_action *actions,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack,
u8 matchall_filter);
int cxgb4_tc_flower_replace(struct net_device *dev, int cxgb4_tc_flower_replace(struct net_device *dev,
struct flow_cls_offload *cls); struct flow_cls_offload *cls);
......
...@@ -188,6 +188,49 @@ static void cxgb4_matchall_free_tc(struct net_device *dev) ...@@ -188,6 +188,49 @@ static void cxgb4_matchall_free_tc(struct net_device *dev)
tc_port_matchall->egress.state = CXGB4_MATCHALL_STATE_DISABLED; tc_port_matchall->egress.state = CXGB4_MATCHALL_STATE_DISABLED;
} }
static int cxgb4_matchall_mirror_alloc(struct net_device *dev,
struct tc_cls_matchall_offload *cls)
{
struct netlink_ext_ack *extack = cls->common.extack;
struct cxgb4_tc_port_matchall *tc_port_matchall;
struct port_info *pi = netdev2pinfo(dev);
struct adapter *adap = netdev2adap(dev);
struct flow_action_entry *act;
int ret;
u32 i;
tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id];
flow_action_for_each(i, act, &cls->rule->action) {
if (act->id == FLOW_ACTION_MIRRED) {
ret = cxgb4_port_mirror_alloc(dev);
if (ret) {
NL_SET_ERR_MSG_MOD(extack,
"Couldn't allocate mirror");
return ret;
}
tc_port_matchall->ingress.viid_mirror = pi->viid_mirror;
break;
}
}
return 0;
}
static void cxgb4_matchall_mirror_free(struct net_device *dev)
{
struct cxgb4_tc_port_matchall *tc_port_matchall;
struct port_info *pi = netdev2pinfo(dev);
struct adapter *adap = netdev2adap(dev);
tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id];
if (!tc_port_matchall->ingress.viid_mirror)
return;
cxgb4_port_mirror_free(dev);
tc_port_matchall->ingress.viid_mirror = 0;
}
static int cxgb4_matchall_alloc_filter(struct net_device *dev, static int cxgb4_matchall_alloc_filter(struct net_device *dev,
struct tc_cls_matchall_offload *cls) struct tc_cls_matchall_offload *cls)
{ {
...@@ -211,6 +254,10 @@ static int cxgb4_matchall_alloc_filter(struct net_device *dev, ...@@ -211,6 +254,10 @@ static int cxgb4_matchall_alloc_filter(struct net_device *dev,
return -ENOMEM; return -ENOMEM;
} }
ret = cxgb4_matchall_mirror_alloc(dev, cls);
if (ret)
return ret;
tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id]; tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id];
fs = &tc_port_matchall->ingress.fs; fs = &tc_port_matchall->ingress.fs;
memset(fs, 0, sizeof(*fs)); memset(fs, 0, sizeof(*fs));
...@@ -229,11 +276,15 @@ static int cxgb4_matchall_alloc_filter(struct net_device *dev, ...@@ -229,11 +276,15 @@ static int cxgb4_matchall_alloc_filter(struct net_device *dev,
ret = cxgb4_set_filter(dev, fidx, fs); ret = cxgb4_set_filter(dev, fidx, fs);
if (ret) if (ret)
return ret; goto out_free;
tc_port_matchall->ingress.tid = fidx; tc_port_matchall->ingress.tid = fidx;
tc_port_matchall->ingress.state = CXGB4_MATCHALL_STATE_ENABLED; tc_port_matchall->ingress.state = CXGB4_MATCHALL_STATE_ENABLED;
return 0; return 0;
out_free:
cxgb4_matchall_mirror_free(dev);
return ret;
} }
static int cxgb4_matchall_free_filter(struct net_device *dev) static int cxgb4_matchall_free_filter(struct net_device *dev)
...@@ -250,6 +301,8 @@ static int cxgb4_matchall_free_filter(struct net_device *dev) ...@@ -250,6 +301,8 @@ static int cxgb4_matchall_free_filter(struct net_device *dev)
if (ret) if (ret)
return ret; return ret;
cxgb4_matchall_mirror_free(dev);
tc_port_matchall->ingress.packets = 0; tc_port_matchall->ingress.packets = 0;
tc_port_matchall->ingress.bytes = 0; tc_port_matchall->ingress.bytes = 0;
tc_port_matchall->ingress.last_used = 0; tc_port_matchall->ingress.last_used = 0;
...@@ -279,7 +332,7 @@ int cxgb4_tc_matchall_replace(struct net_device *dev, ...@@ -279,7 +332,7 @@ int cxgb4_tc_matchall_replace(struct net_device *dev,
ret = cxgb4_validate_flow_actions(dev, ret = cxgb4_validate_flow_actions(dev,
&cls_matchall->rule->action, &cls_matchall->rule->action,
extack); extack, 1);
if (ret) if (ret)
return ret; return ret;
......
...@@ -21,6 +21,7 @@ struct cxgb4_matchall_ingress_entry { ...@@ -21,6 +21,7 @@ struct cxgb4_matchall_ingress_entry {
enum cxgb4_matchall_state state; /* Current MATCHALL offload state */ enum cxgb4_matchall_state state; /* Current MATCHALL offload state */
u32 tid; /* Index to hardware filter entry */ u32 tid; /* Index to hardware filter entry */
struct ch_filter_specification fs; /* Filter entry */ struct ch_filter_specification fs; /* Filter entry */
u16 viid_mirror; /* Identifier for allocated Mirror VI */
u64 bytes; /* # of bytes hitting the filter */ u64 bytes; /* # of bytes hitting the filter */
u64 packets; /* # of packets hitting the filter */ u64 packets; /* # of packets hitting the filter */
u64 last_used; /* Last updated jiffies time */ u64 last_used; /* Last updated jiffies time */
......
...@@ -7711,6 +7711,7 @@ int t4_free_vi(struct adapter *adap, unsigned int mbox, unsigned int pf, ...@@ -7711,6 +7711,7 @@ int t4_free_vi(struct adapter *adap, unsigned int mbox, unsigned int pf,
* @adap: the adapter * @adap: the adapter
* @mbox: mailbox to use for the FW command * @mbox: mailbox to use for the FW command
* @viid: the VI id * @viid: the VI id
* @viid_mirror: the mirror VI id
* @mtu: the new MTU or -1 * @mtu: the new MTU or -1
* @promisc: 1 to enable promiscuous mode, 0 to disable it, -1 no change * @promisc: 1 to enable promiscuous mode, 0 to disable it, -1 no change
* @all_multi: 1 to enable all-multi mode, 0 to disable it, -1 no change * @all_multi: 1 to enable all-multi mode, 0 to disable it, -1 no change
...@@ -7721,10 +7722,11 @@ int t4_free_vi(struct adapter *adap, unsigned int mbox, unsigned int pf, ...@@ -7721,10 +7722,11 @@ int t4_free_vi(struct adapter *adap, unsigned int mbox, unsigned int pf,
* Sets Rx properties of a virtual interface. * Sets Rx properties of a virtual interface.
*/ */
int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid, int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid,
int mtu, int promisc, int all_multi, int bcast, int vlanex, unsigned int viid_mirror, int mtu, int promisc, int all_multi,
bool sleep_ok) int bcast, int vlanex, bool sleep_ok)
{ {
struct fw_vi_rxmode_cmd c; struct fw_vi_rxmode_cmd c, c_mirror;
int ret;
/* convert to FW values */ /* convert to FW values */
if (mtu < 0) if (mtu < 0)
...@@ -7749,7 +7751,24 @@ int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid, ...@@ -7749,7 +7751,24 @@ int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid,
FW_VI_RXMODE_CMD_ALLMULTIEN_V(all_multi) | FW_VI_RXMODE_CMD_ALLMULTIEN_V(all_multi) |
FW_VI_RXMODE_CMD_BROADCASTEN_V(bcast) | FW_VI_RXMODE_CMD_BROADCASTEN_V(bcast) |
FW_VI_RXMODE_CMD_VLANEXEN_V(vlanex)); FW_VI_RXMODE_CMD_VLANEXEN_V(vlanex));
return t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), NULL, sleep_ok);
if (viid_mirror) {
memcpy(&c_mirror, &c, sizeof(c_mirror));
c_mirror.op_to_viid =
cpu_to_be32(FW_CMD_OP_V(FW_VI_RXMODE_CMD) |
FW_CMD_REQUEST_F | FW_CMD_WRITE_F |
FW_VI_RXMODE_CMD_VIID_V(viid_mirror));
}
ret = t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), NULL, sleep_ok);
if (ret)
return ret;
if (viid_mirror)
ret = t4_wr_mbox_meat(adap, mbox, &c_mirror, sizeof(c_mirror),
NULL, sleep_ok);
return ret;
} }
/** /**
...@@ -9711,6 +9730,22 @@ int t4_port_init(struct adapter *adap, int mbox, int pf, int vf) ...@@ -9711,6 +9730,22 @@ int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
return 0; return 0;
} }
int t4_init_port_mirror(struct port_info *pi, u8 mbox, u8 port, u8 pf, u8 vf,
u16 *mirror_viid)
{
int ret;
ret = t4_alloc_vi(pi->adapter, mbox, port, pf, vf, 1, NULL, NULL,
NULL, NULL);
if (ret < 0)
return ret;
if (mirror_viid)
*mirror_viid = ret;
return 0;
}
/** /**
* t4_read_cimq_cfg - read CIM queue configuration * t4_read_cimq_cfg - read CIM queue configuration
* @adap: the adapter * @adap: the adapter
......
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