Commit 6383c0b3 authored by Ariel Elior's avatar Ariel Elior Committed by David S. Miller

bnx2x: Multiple concurrent l2 traffic classes

Overview:
 Support mapping of priorities to traffic classes and
 traffic classes to transmission queues ranges in the net device.
 The queue ranges are (count, offset) pairs relating to the txq
 array.
 This can be done via DCBX negotiation or by kernel.
 As a result Enhanced Transmission Selection (ETS) and Priority Flow
 Control (PFC) are supported between L2 network traffic classes.

 Mapping:
 This patch uses the netdev_set_num_tc, netdev_set_prio_tc_map and
 netdev_set_tc_queue functions to map priorities to traffic classes
 and traffic classes to transmission queue ranges.
 This mapping is performed by bnx2x_setup_tc function which is
 connected to the ndo_setup_tc.
 This function is always called at nic load where by default it
 maps all priorities to tc 0, and it may also be called by the
 kernel or by the bnx2x upon DCBX negotiation to modify the mapping.

 rtnl lock:
 When the ndo_setup_tc is called at nic load or by kernel the rtnl
 lock is already taken. However, when DCBX negotiation takes place
 the lock is not taken. The work is therefore scheduled to be
 handled by the sp_rtnl task.

 Fastpath:
 The fastpath structure of the bnx2x which was previously used
 to hold the information of one tx queue and one rx queue was
 redesigned to represent multiple tx queues, one for each traffic
 class.
 The transmission queue supplied in the skb by the kernel can no
 longer be interpreted as a straightforward index into the fastpath
 structure array, but it must rather be decoded to the appropriate
 fastpath index and the tc within that fastpath.

 Slowpath:
 The bnx2x's queue object was redesigned to accommodate multiple
 transmission queues. The queue object's state machine was enhanced
 to allow opening multiple transmission-only connections on top of
 the regular tx-rx connection.

 Firmware:
 This feature relies on the tx-only queue feature introduced in the
 bnx2x 7.0.23 firmware and the FW likewise must have the bnx2x multi
 cos support.
Signed-off-by: default avatarAriel Elior <ariele@broadcom.com>
Signed-off-by: default avatarEilon Greenstein <eilong@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7be08a72
This diff is collapsed.
This diff is collapsed.
......@@ -439,6 +439,9 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode);
/* hard_xmit callback */
netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev);
/* setup_tc callback */
int bnx2x_setup_tc(struct net_device *dev, u8 num_tc);
/* select_queue callback */
u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb);
......@@ -454,7 +457,7 @@ void bnx2x_update_rx_prod(struct bnx2x *bp, struct bnx2x_fastpath *fp,
u16 bd_prod, u16 rx_comp_prod, u16 rx_sge_prod);
/* NAPI poll Tx part */
int bnx2x_tx_int(struct bnx2x_fastpath *fp);
int bnx2x_tx_int(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata);
/* suspend/resume callbacks */
int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state);
......@@ -715,21 +718,22 @@ static inline u16 bnx2x_ack_int(struct bnx2x *bp)
return bnx2x_igu_ack_int(bp);
}
static inline int bnx2x_has_tx_work_unload(struct bnx2x_fastpath *fp)
static inline int bnx2x_has_tx_work_unload(struct bnx2x_fp_txdata *txdata)
{
/* Tell compiler that consumer and producer can change */
barrier();
return fp->tx_pkt_prod != fp->tx_pkt_cons;
return txdata->tx_pkt_prod != txdata->tx_pkt_cons;
}
static inline u16 bnx2x_tx_avail(struct bnx2x_fastpath *fp)
static inline u16 bnx2x_tx_avail(struct bnx2x *bp,
struct bnx2x_fp_txdata *txdata)
{
s16 used;
u16 prod;
u16 cons;
prod = fp->tx_bd_prod;
cons = fp->tx_bd_cons;
prod = txdata->tx_bd_prod;
cons = txdata->tx_bd_cons;
/* NUM_TX_RINGS = number of "next-page" entries
It will be used as a threshold */
......@@ -737,21 +741,30 @@ static inline u16 bnx2x_tx_avail(struct bnx2x_fastpath *fp)
#ifdef BNX2X_STOP_ON_ERROR
WARN_ON(used < 0);
WARN_ON(used > fp->bp->tx_ring_size);
WARN_ON((fp->bp->tx_ring_size - used) > MAX_TX_AVAIL);
WARN_ON(used > bp->tx_ring_size);
WARN_ON((bp->tx_ring_size - used) > MAX_TX_AVAIL);
#endif
return (s16)(fp->bp->tx_ring_size) - used;
return (s16)(bp->tx_ring_size) - used;
}
static inline int bnx2x_has_tx_work(struct bnx2x_fastpath *fp)
static inline int bnx2x_tx_queue_has_work(struct bnx2x_fp_txdata *txdata)
{
u16 hw_cons;
/* Tell compiler that status block fields can change */
barrier();
hw_cons = le16_to_cpu(*fp->tx_cons_sb);
return hw_cons != fp->tx_pkt_cons;
hw_cons = le16_to_cpu(*txdata->tx_cons_sb);
return hw_cons != txdata->tx_pkt_cons;
}
static inline bool bnx2x_has_tx_work(struct bnx2x_fastpath *fp)
{
u8 cos;
for_each_cos_in_tx_queue(fp, cos)
if (bnx2x_tx_queue_has_work(&fp->txdata[cos]))
return true;
return false;
}
static inline int bnx2x_has_rx_work(struct bnx2x_fastpath *fp)
......@@ -963,7 +976,10 @@ static inline int bnx2x_func_start(struct bnx2x *bp)
/* Function parameters */
start_params->mf_mode = bp->mf_mode;
start_params->sd_vlan_tag = bp->mf_ov;
if (CHIP_IS_E1x(bp))
start_params->network_cos_mode = OVERRIDE_COS;
else
start_params->network_cos_mode = STATIC_COS;
return bnx2x_func_state_change(bp, &func_params);
}
......@@ -1023,39 +1039,41 @@ static inline void bnx2x_free_tpa_pool(struct bnx2x *bp,
}
}
static inline void bnx2x_init_tx_ring_one(struct bnx2x_fastpath *fp)
static inline void bnx2x_init_tx_ring_one(struct bnx2x_fp_txdata *txdata)
{
int i;
for (i = 1; i <= NUM_TX_RINGS; i++) {
struct eth_tx_next_bd *tx_next_bd =
&fp->tx_desc_ring[TX_DESC_CNT * i - 1].next_bd;
&txdata->tx_desc_ring[TX_DESC_CNT * i - 1].next_bd;
tx_next_bd->addr_hi =
cpu_to_le32(U64_HI(fp->tx_desc_mapping +
cpu_to_le32(U64_HI(txdata->tx_desc_mapping +
BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
tx_next_bd->addr_lo =
cpu_to_le32(U64_LO(fp->tx_desc_mapping +
cpu_to_le32(U64_LO(txdata->tx_desc_mapping +
BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
}
SET_FLAG(fp->tx_db.data.header.header, DOORBELL_HDR_DB_TYPE, 1);
fp->tx_db.data.zero_fill1 = 0;
fp->tx_db.data.prod = 0;
SET_FLAG(txdata->tx_db.data.header.header, DOORBELL_HDR_DB_TYPE, 1);
txdata->tx_db.data.zero_fill1 = 0;
txdata->tx_db.data.prod = 0;
fp->tx_pkt_prod = 0;
fp->tx_pkt_cons = 0;
fp->tx_bd_prod = 0;
fp->tx_bd_cons = 0;
fp->tx_pkt = 0;
txdata->tx_pkt_prod = 0;
txdata->tx_pkt_cons = 0;
txdata->tx_bd_prod = 0;
txdata->tx_bd_cons = 0;
txdata->tx_pkt = 0;
}
static inline void bnx2x_init_tx_rings(struct bnx2x *bp)
{
int i;
u8 cos;
for_each_tx_queue(bp, i)
bnx2x_init_tx_ring_one(&bp->fp[i]);
for_each_cos_in_tx_queue(&bp->fp[i], cos)
bnx2x_init_tx_ring_one(&bp->fp[i].txdata[cos]);
}
static inline void bnx2x_set_next_page_rx_bd(struct bnx2x_fastpath *fp)
......@@ -1257,12 +1275,23 @@ static inline u32 bnx2x_rx_ustorm_prods_offset(struct bnx2x_fastpath *fp)
return USTORM_RX_PRODS_E1X_OFFSET(BP_PORT(bp), fp->cl_id);
}
static inline void bnx2x_init_txdata(struct bnx2x *bp,
struct bnx2x_fp_txdata *txdata, u32 cid, int txq_index,
__le16 *tx_cons_sb)
{
txdata->cid = cid;
txdata->txq_index = txq_index;
txdata->tx_cons_sb = tx_cons_sb;
DP(BNX2X_MSG_SP, "created tx data cid %d, txq %d",
txdata->cid, txdata->txq_index);
}
#ifdef BCM_CNIC
static inline u8 bnx2x_cnic_eth_cl_id(struct bnx2x *bp, u8 cl_idx)
{
return bp->cnic_base_cl_id + cl_idx +
(bp->pf_num >> 1) * NONE_ETH_CONTEXT_USE;
(bp->pf_num >> 1) * NON_ETH_CONTEXT_USE;
}
static inline u8 bnx2x_cnic_fw_sb_id(struct bnx2x *bp)
......@@ -1293,10 +1322,13 @@ static inline void bnx2x_init_fcoe_fp(struct bnx2x *bp)
bnx2x_fcoe(bp, cid) = BNX2X_FCOE_ETH_CID;
bnx2x_fcoe(bp, fw_sb_id) = DEF_SB_ID;
bnx2x_fcoe(bp, igu_sb_id) = bp->igu_dsb_id;
bnx2x_fcoe(bp, bp) = bp;
bnx2x_fcoe(bp, index) = FCOE_IDX;
bnx2x_fcoe(bp, rx_cons_sb) = BNX2X_FCOE_L2_RX_INDEX;
bnx2x_fcoe(bp, tx_cons_sb) = BNX2X_FCOE_L2_TX_INDEX;
bnx2x_init_txdata(bp, &bnx2x_fcoe(bp, txdata[0]),
fp->cid, FCOE_TXQ_IDX(bp), BNX2X_FCOE_L2_TX_INDEX);
DP(BNX2X_MSG_SP, "created fcoe tx data (fp index %d)", fp->index);
/* qZone id equals to FW (per path) client id */
bnx2x_fcoe(bp, cl_qzone_id) = bnx2x_fp_qzone_id(fp);
/* init shortcut */
......@@ -1306,9 +1338,13 @@ static inline void bnx2x_init_fcoe_fp(struct bnx2x *bp)
/* Configure Queue State object */
__set_bit(BNX2X_Q_TYPE_HAS_RX, &q_type);
__set_bit(BNX2X_Q_TYPE_HAS_TX, &q_type);
bnx2x_init_queue_obj(bp, &fp->q_obj, fp->cl_id, fp->cid, BP_FUNC(bp),
bnx2x_sp(bp, q_rdata), bnx2x_sp_mapping(bp, q_rdata),
q_type);
/* No multi-CoS for FCoE L2 client */
BUG_ON(fp->max_cos != 1);
bnx2x_init_queue_obj(bp, &fp->q_obj, fp->cl_id, &fp->cid, 1,
BP_FUNC(bp), bnx2x_sp(bp, q_rdata),
bnx2x_sp_mapping(bp, q_rdata), q_type);
DP(NETIF_MSG_IFUP, "queue[%d]: bnx2x_init_sb(%p,%p) cl_id %d fw_sb %d "
"igu_sb %d\n",
......@@ -1318,15 +1354,16 @@ static inline void bnx2x_init_fcoe_fp(struct bnx2x *bp)
#endif
static inline int bnx2x_clean_tx_queue(struct bnx2x *bp,
struct bnx2x_fastpath *fp)
struct bnx2x_fp_txdata *txdata)
{
int cnt = 1000;
while (bnx2x_has_tx_work_unload(fp)) {
while (bnx2x_has_tx_work_unload(txdata)) {
if (!cnt) {
BNX2X_ERR("timeout waiting for queue[%d]: "
"fp->tx_pkt_prod(%d) != fp->tx_pkt_cons(%d)\n",
fp->index, fp->tx_pkt_prod, fp->tx_pkt_cons);
"txdata->tx_pkt_prod(%d) != txdata->tx_pkt_cons(%d)\n",
txdata->txq_index, txdata->tx_pkt_prod,
txdata->tx_pkt_cons);
#ifdef BNX2X_STOP_ON_ERROR
bnx2x_panic();
return -EBUSY;
......
......@@ -653,6 +653,26 @@ static inline void bnx2x_update_drv_flags(struct bnx2x *bp, u32 flags, u32 set)
}
}
static inline void bnx2x_dcbx_update_tc_mapping(struct bnx2x *bp)
{
u8 prio, cos;
for (cos = 0; cos < bp->dcbx_port_params.ets.num_of_cos; cos++) {
for (prio = 0; prio < BNX2X_MAX_PRIORITY; prio++) {
if (bp->dcbx_port_params.ets.cos_params[cos].pri_bitmask
& (1 << prio)) {
bp->prio_to_cos[prio] = cos;
}
}
}
/* setup tc must be called under rtnl lock, but we can't take it here
* as we are handling an attetntion on a work queue which must be
* flushed at some rtnl-locked contexts (e.g. if down)
*/
if (!test_and_set_bit(BNX2X_SP_RTNL_SETUP_TC, &bp->sp_rtnl_state))
schedule_delayed_work(&bp->sp_rtnl_task, 0);
}
void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
{
switch (state) {
......@@ -690,6 +710,11 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
#endif
bnx2x_dcbx_stop_hw_tx(bp);
/* reconfigure the netdevice with the results of the new
* dcbx negotiation.
*/
bnx2x_dcbx_update_tc_mapping(bp);
return;
}
case BNX2X_DCBX_STATE_TX_PAUSED:
......
......@@ -1616,6 +1616,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode)
unsigned char *packet;
struct bnx2x_fastpath *fp_rx = &bp->fp[0];
struct bnx2x_fastpath *fp_tx = &bp->fp[0];
struct bnx2x_fp_txdata *txdata = &fp_tx->txdata[0];
u16 tx_start_idx, tx_idx;
u16 rx_start_idx, rx_idx;
u16 pkt_prod, bd_prod, rx_comp_cons;
......@@ -1670,17 +1671,17 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode)
/* send the loopback packet */
num_pkts = 0;
tx_start_idx = le16_to_cpu(*fp_tx->tx_cons_sb);
tx_start_idx = le16_to_cpu(*txdata->tx_cons_sb);
rx_start_idx = le16_to_cpu(*fp_rx->rx_cons_sb);
pkt_prod = fp_tx->tx_pkt_prod++;
tx_buf = &fp_tx->tx_buf_ring[TX_BD(pkt_prod)];
tx_buf->first_bd = fp_tx->tx_bd_prod;
pkt_prod = txdata->tx_pkt_prod++;
tx_buf = &txdata->tx_buf_ring[TX_BD(pkt_prod)];
tx_buf->first_bd = txdata->tx_bd_prod;
tx_buf->skb = skb;
tx_buf->flags = 0;
bd_prod = TX_BD(fp_tx->tx_bd_prod);
tx_start_bd = &fp_tx->tx_desc_ring[bd_prod].start_bd;
bd_prod = TX_BD(txdata->tx_bd_prod);
tx_start_bd = &txdata->tx_desc_ring[bd_prod].start_bd;
tx_start_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
tx_start_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
tx_start_bd->nbd = cpu_to_le16(2); /* start + pbd */
......@@ -1697,27 +1698,27 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode)
/* turn on parsing and get a BD */
bd_prod = TX_BD(NEXT_TX_IDX(bd_prod));
pbd_e1x = &fp_tx->tx_desc_ring[bd_prod].parse_bd_e1x;
pbd_e2 = &fp_tx->tx_desc_ring[bd_prod].parse_bd_e2;
pbd_e1x = &txdata->tx_desc_ring[bd_prod].parse_bd_e1x;
pbd_e2 = &txdata->tx_desc_ring[bd_prod].parse_bd_e2;
memset(pbd_e2, 0, sizeof(struct eth_tx_parse_bd_e2));
memset(pbd_e1x, 0, sizeof(struct eth_tx_parse_bd_e1x));
wmb();
fp_tx->tx_db.data.prod += 2;
txdata->tx_db.data.prod += 2;
barrier();
DOORBELL(bp, fp_tx->index, fp_tx->tx_db.raw);
DOORBELL(bp, txdata->cid, txdata->tx_db.raw);
mmiowb();
barrier();
num_pkts++;
fp_tx->tx_bd_prod += 2; /* start + pbd */
txdata->tx_bd_prod += 2; /* start + pbd */
udelay(100);
tx_idx = le16_to_cpu(*fp_tx->tx_cons_sb);
tx_idx = le16_to_cpu(*txdata->tx_cons_sb);
if (tx_idx != tx_start_idx + num_pkts)
goto test_loopback_exit;
......@@ -1731,7 +1732,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode)
* bnx2x_tx_int()), as both are taking netif_tx_lock().
*/
local_bh_disable();
bnx2x_tx_int(fp_tx);
bnx2x_tx_int(bp, txdata);
local_bh_enable();
}
......
......@@ -2545,7 +2545,7 @@ struct host_func_stats {
#define BCM_5710_FW_MAJOR_VERSION 7
#define BCM_5710_FW_MINOR_VERSION 0
#define BCM_5710_FW_REVISION_VERSION 20
#define BCM_5710_FW_REVISION_VERSION 23
#define BCM_5710_FW_ENGINEERING_VERSION 0
#define BCM_5710_FW_COMPILE_FLAGS 1
......
......@@ -128,11 +128,10 @@ enum {
MODE_MF_NIV = 0x00000800,
MODE_E3_A0 = 0x00001000,
MODE_E3_B0 = 0x00002000,
MODE_COS_BC = 0x00004000,
MODE_COS3 = 0x00008000,
MODE_COS6 = 0x00010000,
MODE_LITTLE_ENDIAN = 0x00020000,
MODE_BIG_ENDIAN = 0x00040000,
MODE_COS3 = 0x00004000,
MODE_COS6 = 0x00008000,
MODE_LITTLE_ENDIAN = 0x00010000,
MODE_BIG_ENDIAN = 0x00020000,
};
/* Init Blocks */
......@@ -179,7 +178,7 @@ enum {
#define BNX2X_TOE_Q 3
#define BNX2X_TOE_ACK_Q 6
#define BNX2X_ISCSI_Q 9
#define BNX2X_ISCSI_ACK_Q 8
#define BNX2X_ISCSI_ACK_Q 11
#define BNX2X_FCOE_Q 10
/* Vnics per mode */
......@@ -257,14 +256,16 @@ static inline void bnx2x_map_q_cos(struct bnx2x *bp, u32 q_num, u32 new_cos)
}
/* Configures the QM according to the specified per-traffic-type COSes */
static inline void bnx2x_dcb_config_qm(struct bnx2x *bp,
static inline void bnx2x_dcb_config_qm(struct bnx2x *bp, enum cos_mode mode,
struct priority_cos *traffic_cos)
{
bnx2x_map_q_cos(bp, BNX2X_FCOE_Q,
traffic_cos[LLFC_TRAFFIC_TYPE_FCOE].cos);
bnx2x_map_q_cos(bp, BNX2X_ISCSI_Q,
traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos);
if (INIT_MODE_FLAGS(bp) & MODE_COS_BC) {
bnx2x_map_q_cos(bp, BNX2X_ISCSI_ACK_Q,
traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos);
if (mode != STATIC_COS) {
/* required only in backward compatible COS mode */
bnx2x_map_q_cos(bp, BNX2X_ETH_Q,
traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
......@@ -272,8 +273,6 @@ static inline void bnx2x_dcb_config_qm(struct bnx2x *bp,
traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
bnx2x_map_q_cos(bp, BNX2X_TOE_ACK_Q,
traffic_cos[LLFC_TRAFFIC_TYPE_NW].cos);
bnx2x_map_q_cos(bp, BNX2X_ISCSI_ACK_Q,
traffic_cos[LLFC_TRAFFIC_TYPE_ISCSI].cos);
}
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -721,6 +721,8 @@ enum bnx2x_q_state {
BNX2X_Q_STATE_RESET,
BNX2X_Q_STATE_INITIALIZED,
BNX2X_Q_STATE_ACTIVE,
BNX2X_Q_STATE_MULTI_COS,
BNX2X_Q_STATE_MCOS_TERMINATED,
BNX2X_Q_STATE_INACTIVE,
BNX2X_Q_STATE_STOPPED,
BNX2X_Q_STATE_TERMINATED,
......@@ -732,6 +734,7 @@ enum bnx2x_q_state {
enum bnx2x_queue_cmd {
BNX2X_Q_CMD_INIT,
BNX2X_Q_CMD_SETUP,
BNX2X_Q_CMD_SETUP_TX_ONLY,
BNX2X_Q_CMD_DEACTIVATE,
BNX2X_Q_CMD_ACTIVATE,
BNX2X_Q_CMD_UPDATE,
......@@ -774,6 +777,13 @@ enum bnx2x_q_type {
BNX2X_Q_TYPE_HAS_TX,
};
#define BNX2X_PRIMARY_CID_INDEX 0
#define BNX2X_MULTI_TX_COS_E1X 1
#define BNX2X_MULTI_TX_COS_E2_E3A0 2
#define BNX2X_MULTI_TX_COS_E3B0 3
#define BNX2X_MULTI_TX_COS BNX2X_MULTI_TX_COS_E3B0
struct bnx2x_queue_init_params {
struct {
unsigned long flags;
......@@ -790,7 +800,20 @@ struct bnx2x_queue_init_params {
} rx;
/* CID context in the host memory */
struct eth_context *cxt;
struct eth_context *cxts[BNX2X_MULTI_TX_COS];
/* maximum number of cos supported by hardware */
u8 max_cos;
};
struct bnx2x_queue_terminate_params {
/* index within the tx_only cids of this queue object */
u8 cid_index;
};
struct bnx2x_queue_cfc_del_params {
/* index within the tx_only cids of this queue object */
u8 cid_index;
};
struct bnx2x_queue_update_params {
......@@ -798,6 +821,8 @@ struct bnx2x_queue_update_params {
u16 def_vlan;
u16 silent_removal_value;
u16 silent_removal_mask;
/* index within the tx_only cids of this queue object */
u8 cid_index;
};
struct rxq_pause_params {
......@@ -817,6 +842,7 @@ struct bnx2x_general_setup_params {
u8 spcl_id;
u16 mtu;
u8 cos;
};
struct bnx2x_rxq_setup_params {
......@@ -863,13 +889,20 @@ struct bnx2x_txq_setup_params {
};
struct bnx2x_queue_setup_params {
struct rxq_pause_params pause;
struct bnx2x_general_setup_params gen_params;
struct bnx2x_rxq_setup_params rxq_params;
struct bnx2x_txq_setup_params txq_params;
struct bnx2x_rxq_setup_params rxq_params;
struct rxq_pause_params pause_params;
unsigned long flags;
};
struct bnx2x_queue_setup_tx_only_params {
struct bnx2x_general_setup_params gen_params;
struct bnx2x_txq_setup_params txq_params;
unsigned long flags;
/* index within the tx_only cids of this queue object */
u8 cid_index;
};
struct bnx2x_queue_state_params {
struct bnx2x_queue_sp_obj *q_obj;
......@@ -878,21 +911,36 @@ struct bnx2x_queue_state_params {
enum bnx2x_queue_cmd cmd;
/* may have RAMROD_COMP_WAIT set only */
unsigned long ramrod_flags;
unsigned long ramrod_flags;
/* Params according to the current command */
union {
struct bnx2x_queue_update_params update;
struct bnx2x_queue_setup_params setup;
struct bnx2x_queue_init_params init;
struct bnx2x_queue_update_params update;
struct bnx2x_queue_setup_params setup;
struct bnx2x_queue_init_params init;
struct bnx2x_queue_setup_tx_only_params tx_only;
struct bnx2x_queue_terminate_params terminate;
struct bnx2x_queue_cfc_del_params cfc_del;
} params;
};
struct bnx2x_queue_sp_obj {
u32 cid;
u32 cids[BNX2X_MULTI_TX_COS];
u8 cl_id;
u8 func_id;
/*
* number of traffic classes supported by queue.
* The primary connection of the queue suppotrs the first traffic
* class. Any further traffic class is suppoted by a tx-only
* connection.
*
* Therefore max_cos is also a number of valid entries in the cids
* array.
*/
u8 max_cos;
u8 num_tx_only, next_tx_only;
enum bnx2x_q_state state, next_state;
/* bits from enum bnx2x_q_type */
......@@ -1106,9 +1154,9 @@ int bnx2x_func_state_change(struct bnx2x *bp,
/******************* Queue State **************/
void bnx2x_init_queue_obj(struct bnx2x *bp,
struct bnx2x_queue_sp_obj *obj, u8 cl_id, u32 cid,
u8 func_id, void *rdata, dma_addr_t rdata_mapping,
unsigned long type);
struct bnx2x_queue_sp_obj *obj, u8 cl_id, u32 *cids,
u8 cid_cnt, u8 func_id, void *rdata,
dma_addr_t rdata_mapping, unsigned long type);
int bnx2x_queue_state_change(struct bnx2x *bp,
struct bnx2x_queue_state_params *params);
......
......@@ -1185,7 +1185,7 @@ static void bnx2x_stats_update(struct bnx2x *bp)
if (netif_msg_timer(bp)) {
struct bnx2x_eth_stats *estats = &bp->eth_stats;
int i;
int i, cos;
netdev_dbg(bp->dev, "brb drops %u brb truncate %u\n",
estats->brb_drop_lo, estats->brb_truncate_lo);
......@@ -1206,20 +1206,32 @@ static void bnx2x_stats_update(struct bnx2x *bp)
for_each_eth_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
struct bnx2x_fp_txdata *txdata;
struct bnx2x_eth_q_stats *qstats = &fp->eth_q_stats;
struct netdev_queue *txq =
netdev_get_tx_queue(bp->dev, i);
printk(KERN_DEBUG "%s: tx avail(%4u) *tx_cons_sb(%u)"
" tx pkt(%lu) tx calls (%lu)"
" %s (Xoff events %u)\n",
fp->name, bnx2x_tx_avail(fp),
le16_to_cpu(*fp->tx_cons_sb),
bnx2x_hilo(&qstats->
total_unicast_packets_transmitted_hi),
fp->tx_pkt,
(netif_tx_queue_stopped(txq) ? "Xoff" : "Xon"),
qstats->driver_xoff);
struct netdev_queue *txq;
printk(KERN_DEBUG "%s: tx pkt(%lu) (Xoff events %u)",
fp->name, bnx2x_hilo(
&qstats->total_unicast_packets_transmitted_hi),
qstats->driver_xoff);
for_each_cos_in_tx_queue(fp, cos) {
txdata = &fp->txdata[cos];
txq = netdev_get_tx_queue(bp->dev,
FP_COS_TO_TXQ(fp, cos));
printk(KERN_DEBUG "%d: tx avail(%4u)"
" *tx_cons_sb(%u)"
" tx calls (%lu)"
" %s\n",
cos,
bnx2x_tx_avail(bp, txdata),
le16_to_cpu(*txdata->tx_cons_sb),
txdata->tx_pkt,
(netif_tx_queue_stopped(txq) ?
"Xoff" : "Xon")
);
}
}
}
......
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