diff options
Diffstat (limited to 'drivers/net/bnx2x/bnx2x_sp.c')
-rw-r--r-- | drivers/net/bnx2x/bnx2x_sp.c | 476 |
1 files changed, 344 insertions, 132 deletions
diff --git a/drivers/net/bnx2x/bnx2x_sp.c b/drivers/net/bnx2x/bnx2x_sp.c index f6322a15ed4d..358c33997536 100644 --- a/drivers/net/bnx2x/bnx2x_sp.c +++ b/drivers/net/bnx2x/bnx2x_sp.c @@ -4195,15 +4195,29 @@ static int bnx2x_queue_comp_cmd(struct bnx2x *bp, if (!test_and_clear_bit(cmd, &cur_pending)) { BNX2X_ERR("Bad MC reply %d for queue %d in state %d " - "pending 0x%lx, next_state %d\n", cmd, o->cid, + "pending 0x%lx, next_state %d\n", cmd, + o->cids[BNX2X_PRIMARY_CID_INDEX], o->state, cur_pending, o->next_state); return -EINVAL; } + if (o->next_tx_only >= o->max_cos) + /* >= becuase tx only must always be smaller than cos since the + * primary connection suports COS 0 + */ + BNX2X_ERR("illegal value for next tx_only: %d. max cos was %d", + o->next_tx_only, o->max_cos); + DP(BNX2X_MSG_SP, "Completing command %d for queue %d, " - "setting state to %d\n", cmd, o->cid, o->next_state); + "setting state to %d\n", cmd, + o->cids[BNX2X_PRIMARY_CID_INDEX], o->next_state); + + if (o->next_tx_only) /* print num tx-only if any exist */ + DP(BNX2X_MSG_SP, "primary cid %d: num tx-only cons %d", + o->cids[BNX2X_PRIMARY_CID_INDEX], o->next_tx_only); o->state = o->next_state; + o->num_tx_only = o->next_tx_only; o->next_state = BNX2X_Q_STATE_MAX; /* It's important that o->state and o->next_state are @@ -4230,135 +4244,193 @@ static void bnx2x_q_fill_setup_data_e2(struct bnx2x *bp, CLIENT_INIT_RX_DATA_TPA_EN_IPV6; } -static void bnx2x_q_fill_setup_data_cmn(struct bnx2x *bp, - struct bnx2x_queue_state_params *cmd_params, - struct client_init_ramrod_data *data) -{ - struct bnx2x_queue_sp_obj *o = cmd_params->q_obj; - struct bnx2x_queue_setup_params *params = &cmd_params->params.setup; - - - /* general */ - data->general.client_id = o->cl_id; - - if (test_bit(BNX2X_Q_FLG_STATS, ¶ms->flags)) { - data->general.statistics_counter_id = - params->gen_params.stat_id; - data->general.statistics_en_flg = 1; - data->general.statistics_zero_flg = - test_bit(BNX2X_Q_FLG_ZERO_STATS, ¶ms->flags); +static void bnx2x_q_fill_init_general_data(struct bnx2x *bp, + struct bnx2x_queue_sp_obj *o, + struct bnx2x_general_setup_params *params, + struct client_init_general_data *gen_data, + unsigned long *flags) +{ + gen_data->client_id = o->cl_id; + + if (test_bit(BNX2X_Q_FLG_STATS, flags)) { + gen_data->statistics_counter_id = + params->stat_id; + gen_data->statistics_en_flg = 1; + gen_data->statistics_zero_flg = + test_bit(BNX2X_Q_FLG_ZERO_STATS, flags); } else - data->general.statistics_counter_id = + gen_data->statistics_counter_id = DISABLE_STATISTIC_COUNTER_ID_VALUE; - data->general.is_fcoe_flg = test_bit(BNX2X_Q_FLG_FCOE, ¶ms->flags); - data->general.activate_flg = test_bit(BNX2X_Q_FLG_ACTIVE, - ¶ms->flags); - data->general.sp_client_id = params->gen_params.spcl_id; - data->general.mtu = cpu_to_le16(params->gen_params.mtu); - data->general.func_id = o->func_id; + gen_data->is_fcoe_flg = test_bit(BNX2X_Q_FLG_FCOE, flags); + gen_data->activate_flg = test_bit(BNX2X_Q_FLG_ACTIVE, flags); + gen_data->sp_client_id = params->spcl_id; + gen_data->mtu = cpu_to_le16(params->mtu); + gen_data->func_id = o->func_id; - data->general.cos = params->txq_params.cos; + gen_data->cos = params->cos; - data->general.traffic_type = - test_bit(BNX2X_Q_FLG_FCOE, ¶ms->flags) ? + gen_data->traffic_type = + test_bit(BNX2X_Q_FLG_FCOE, flags) ? LLFC_TRAFFIC_TYPE_FCOE : LLFC_TRAFFIC_TYPE_NW; - /* Rx data */ - data->rx.tpa_en = test_bit(BNX2X_Q_FLG_TPA, ¶ms->flags) * + DP(BNX2X_MSG_SP, "flags: active %d, cos %d, stats en %d", + gen_data->activate_flg, gen_data->cos, gen_data->statistics_en_flg); +} + +static void bnx2x_q_fill_init_tx_data(struct bnx2x_queue_sp_obj *o, + struct bnx2x_txq_setup_params *params, + struct client_init_tx_data *tx_data, + unsigned long *flags) +{ + tx_data->enforce_security_flg = + test_bit(BNX2X_Q_FLG_TX_SEC, flags); + tx_data->default_vlan = + cpu_to_le16(params->default_vlan); + tx_data->default_vlan_flg = + test_bit(BNX2X_Q_FLG_DEF_VLAN, flags); + tx_data->tx_switching_flg = + test_bit(BNX2X_Q_FLG_TX_SWITCH, flags); + tx_data->anti_spoofing_flg = + test_bit(BNX2X_Q_FLG_ANTI_SPOOF, flags); + tx_data->tx_status_block_id = params->fw_sb_id; + tx_data->tx_sb_index_number = params->sb_cq_index; + tx_data->tss_leading_client_id = params->tss_leading_cl_id; + + tx_data->tx_bd_page_base.lo = + cpu_to_le32(U64_LO(params->dscr_map)); + tx_data->tx_bd_page_base.hi = + cpu_to_le32(U64_HI(params->dscr_map)); + + /* Don't configure any Tx switching mode during queue SETUP */ + tx_data->state = 0; +} + +static void bnx2x_q_fill_init_pause_data(struct bnx2x_queue_sp_obj *o, + struct rxq_pause_params *params, + struct client_init_rx_data *rx_data) +{ + /* flow control data */ + rx_data->cqe_pause_thr_low = cpu_to_le16(params->rcq_th_lo); + rx_data->cqe_pause_thr_high = cpu_to_le16(params->rcq_th_hi); + rx_data->bd_pause_thr_low = cpu_to_le16(params->bd_th_lo); + rx_data->bd_pause_thr_high = cpu_to_le16(params->bd_th_hi); + rx_data->sge_pause_thr_low = cpu_to_le16(params->sge_th_lo); + rx_data->sge_pause_thr_high = cpu_to_le16(params->sge_th_hi); + rx_data->rx_cos_mask = cpu_to_le16(params->pri_map); +} + +static void bnx2x_q_fill_init_rx_data(struct bnx2x_queue_sp_obj *o, + struct bnx2x_rxq_setup_params *params, + struct client_init_rx_data *rx_data, + unsigned long *flags) +{ + /* Rx data */ + rx_data->tpa_en = test_bit(BNX2X_Q_FLG_TPA, flags) * CLIENT_INIT_RX_DATA_TPA_EN_IPV4; - data->rx.vmqueue_mode_en_flg = 0; + rx_data->vmqueue_mode_en_flg = 0; - data->rx.cache_line_alignment_log_size = - params->rxq_params.cache_line_log; - data->rx.enable_dynamic_hc = - test_bit(BNX2X_Q_FLG_DHC, ¶ms->flags); - data->rx.max_sges_for_packet = params->rxq_params.max_sges_pkt; - data->rx.client_qzone_id = params->rxq_params.cl_qzone_id; - data->rx.max_agg_size = cpu_to_le16(params->rxq_params.tpa_agg_sz); + rx_data->cache_line_alignment_log_size = + params->cache_line_log; + rx_data->enable_dynamic_hc = + test_bit(BNX2X_Q_FLG_DHC, flags); + rx_data->max_sges_for_packet = params->max_sges_pkt; + rx_data->client_qzone_id = params->cl_qzone_id; + rx_data->max_agg_size = cpu_to_le16(params->tpa_agg_sz); /* Always start in DROP_ALL mode */ - data->rx.state = cpu_to_le16(CLIENT_INIT_RX_DATA_UCAST_DROP_ALL | + rx_data->state = cpu_to_le16(CLIENT_INIT_RX_DATA_UCAST_DROP_ALL | CLIENT_INIT_RX_DATA_MCAST_DROP_ALL); /* We don't set drop flags */ - data->rx.drop_ip_cs_err_flg = 0; - data->rx.drop_tcp_cs_err_flg = 0; - data->rx.drop_ttl0_flg = 0; - data->rx.drop_udp_cs_err_flg = 0; - data->rx.inner_vlan_removal_enable_flg = - test_bit(BNX2X_Q_FLG_VLAN, ¶ms->flags); - data->rx.outer_vlan_removal_enable_flg = - test_bit(BNX2X_Q_FLG_OV, ¶ms->flags); - data->rx.status_block_id = params->rxq_params.fw_sb_id; - data->rx.rx_sb_index_number = params->rxq_params.sb_cq_index; - data->rx.max_tpa_queues = params->rxq_params.max_tpa_queues; - data->rx.max_bytes_on_bd = cpu_to_le16(params->rxq_params.buf_sz); - data->rx.sge_buff_size = cpu_to_le16(params->rxq_params.sge_buf_sz); - data->rx.bd_page_base.lo = - cpu_to_le32(U64_LO(params->rxq_params.dscr_map)); - data->rx.bd_page_base.hi = - cpu_to_le32(U64_HI(params->rxq_params.dscr_map)); - data->rx.sge_page_base.lo = - cpu_to_le32(U64_LO(params->rxq_params.sge_map)); - data->rx.sge_page_base.hi = - cpu_to_le32(U64_HI(params->rxq_params.sge_map)); - data->rx.cqe_page_base.lo = - cpu_to_le32(U64_LO(params->rxq_params.rcq_map)); - data->rx.cqe_page_base.hi = - cpu_to_le32(U64_HI(params->rxq_params.rcq_map)); - data->rx.is_leading_rss = test_bit(BNX2X_Q_FLG_LEADING_RSS, - ¶ms->flags); - - if (test_bit(BNX2X_Q_FLG_MCAST, ¶ms->flags)) { - data->rx.approx_mcast_engine_id = o->func_id; - data->rx.is_approx_mcast = 1; + rx_data->drop_ip_cs_err_flg = 0; + rx_data->drop_tcp_cs_err_flg = 0; + rx_data->drop_ttl0_flg = 0; + rx_data->drop_udp_cs_err_flg = 0; + rx_data->inner_vlan_removal_enable_flg = + test_bit(BNX2X_Q_FLG_VLAN, flags); + rx_data->outer_vlan_removal_enable_flg = + test_bit(BNX2X_Q_FLG_OV, flags); + rx_data->status_block_id = params->fw_sb_id; + rx_data->rx_sb_index_number = params->sb_cq_index; + rx_data->max_tpa_queues = params->max_tpa_queues; + rx_data->max_bytes_on_bd = cpu_to_le16(params->buf_sz); + rx_data->sge_buff_size = cpu_to_le16(params->sge_buf_sz); + rx_data->bd_page_base.lo = + cpu_to_le32(U64_LO(params->dscr_map)); + rx_data->bd_page_base.hi = + cpu_to_le32(U64_HI(params->dscr_map)); + rx_data->sge_page_base.lo = + cpu_to_le32(U64_LO(params->sge_map)); + rx_data->sge_page_base.hi = + cpu_to_le32(U64_HI(params->sge_map)); + rx_data->cqe_page_base.lo = + cpu_to_le32(U64_LO(params->rcq_map)); + rx_data->cqe_page_base.hi = + cpu_to_le32(U64_HI(params->rcq_map)); + rx_data->is_leading_rss = test_bit(BNX2X_Q_FLG_LEADING_RSS, flags); + + if (test_bit(BNX2X_Q_FLG_MCAST, flags)) { + rx_data->approx_mcast_engine_id = o->func_id; + rx_data->is_approx_mcast = 1; } - data->rx.rss_engine_id = params->rxq_params.rss_engine_id; - - /* flow control data */ - data->rx.cqe_pause_thr_low = cpu_to_le16(params->pause.rcq_th_lo); - data->rx.cqe_pause_thr_high = cpu_to_le16(params->pause.rcq_th_hi); - data->rx.bd_pause_thr_low = cpu_to_le16(params->pause.bd_th_lo); - data->rx.bd_pause_thr_high = cpu_to_le16(params->pause.bd_th_hi); - data->rx.sge_pause_thr_low = cpu_to_le16(params->pause.sge_th_lo); - data->rx.sge_pause_thr_high = cpu_to_le16(params->pause.sge_th_hi); - data->rx.rx_cos_mask = cpu_to_le16(params->pause.pri_map); + rx_data->rss_engine_id = params->rss_engine_id; /* silent vlan removal */ - data->rx.silent_vlan_removal_flg = - test_bit(BNX2X_Q_FLG_SILENT_VLAN_REM, ¶ms->flags); - data->rx.silent_vlan_value = - cpu_to_le16(params->rxq_params.silent_removal_value); - data->rx.silent_vlan_mask = - cpu_to_le16(params->rxq_params.silent_removal_mask); - - /* Tx data */ - data->tx.enforce_security_flg = - test_bit(BNX2X_Q_FLG_TX_SEC, ¶ms->flags); - data->tx.default_vlan = - cpu_to_le16(params->txq_params.default_vlan); - data->tx.default_vlan_flg = - test_bit(BNX2X_Q_FLG_DEF_VLAN, ¶ms->flags); - data->tx.tx_switching_flg = - test_bit(BNX2X_Q_FLG_TX_SWITCH, ¶ms->flags); - data->tx.anti_spoofing_flg = - test_bit(BNX2X_Q_FLG_ANTI_SPOOF, ¶ms->flags); - data->tx.tx_status_block_id = params->txq_params.fw_sb_id; - data->tx.tx_sb_index_number = params->txq_params.sb_cq_index; - data->tx.tss_leading_client_id = params->txq_params.tss_leading_cl_id; - - data->tx.tx_bd_page_base.lo = - cpu_to_le32(U64_LO(params->txq_params.dscr_map)); - data->tx.tx_bd_page_base.hi = - cpu_to_le32(U64_HI(params->txq_params.dscr_map)); + rx_data->silent_vlan_removal_flg = + test_bit(BNX2X_Q_FLG_SILENT_VLAN_REM, flags); + rx_data->silent_vlan_value = + cpu_to_le16(params->silent_removal_value); + rx_data->silent_vlan_mask = + cpu_to_le16(params->silent_removal_mask); - /* Don't configure any Tx switching mode during queue SETUP */ - data->tx.state = 0; } +/* initialize the general, tx and rx parts of a queue object */ +static void bnx2x_q_fill_setup_data_cmn(struct bnx2x *bp, + struct bnx2x_queue_state_params *cmd_params, + struct client_init_ramrod_data *data) +{ + bnx2x_q_fill_init_general_data(bp, cmd_params->q_obj, + &cmd_params->params.setup.gen_params, + &data->general, + &cmd_params->params.setup.flags); + + bnx2x_q_fill_init_tx_data(cmd_params->q_obj, + &cmd_params->params.setup.txq_params, + &data->tx, + &cmd_params->params.setup.flags); + + bnx2x_q_fill_init_rx_data(cmd_params->q_obj, + &cmd_params->params.setup.rxq_params, + &data->rx, + &cmd_params->params.setup.flags); + + bnx2x_q_fill_init_pause_data(cmd_params->q_obj, + &cmd_params->params.setup.pause_params, + &data->rx); +} + +/* initialize the general and tx parts of a tx-only queue object */ +static void bnx2x_q_fill_setup_tx_only(struct bnx2x *bp, + struct bnx2x_queue_state_params *cmd_params, + struct tx_queue_init_ramrod_data *data) +{ + bnx2x_q_fill_init_general_data(bp, cmd_params->q_obj, + &cmd_params->params.tx_only.gen_params, + &data->general, + &cmd_params->params.tx_only.flags); + + bnx2x_q_fill_init_tx_data(cmd_params->q_obj, + &cmd_params->params.tx_only.txq_params, + &data->tx, + &cmd_params->params.tx_only.flags); + + DP(BNX2X_MSG_SP, "cid %d, tx bd page lo %x hi %x",cmd_params->q_obj->cids[0], + data->tx.tx_bd_page_base.lo, data->tx.tx_bd_page_base.hi); +} /** * bnx2x_q_init - init HW/FW queue @@ -4377,6 +4449,7 @@ static inline int bnx2x_q_init(struct bnx2x *bp, struct bnx2x_queue_sp_obj *o = params->q_obj; struct bnx2x_queue_init_params *init = ¶ms->params.init; u16 hc_usec; + u8 cos; /* Tx HC configuration */ if (test_bit(BNX2X_Q_TYPE_HAS_TX, &o->type) && @@ -4401,7 +4474,12 @@ static inline int bnx2x_q_init(struct bnx2x *bp, } /* Set CDU context validation values */ - bnx2x_set_ctx_validation(bp, init->cxt, o->cid); + for (cos = 0; cos < o->max_cos; cos++) { + DP(BNX2X_MSG_SP, "setting context validation. cid %d, cos %d", + o->cids[cos], cos); + DP(BNX2X_MSG_SP, "context pointer %p", init->cxts[cos]); + bnx2x_set_ctx_validation(bp, init->cxts[cos], o->cids[cos]); + } /* As no ramrod is sent, complete the command immediately */ o->complete_cmd(bp, o, BNX2X_Q_CMD_INIT); @@ -4429,7 +4507,8 @@ static inline int bnx2x_q_send_setup_e1x(struct bnx2x *bp, mb(); - return bnx2x_sp_post(bp, ramrod, o->cid, U64_HI(data_mapping), + return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX], + U64_HI(data_mapping), U64_LO(data_mapping), ETH_CONNECTION_TYPE); } @@ -4449,9 +4528,57 @@ static inline int bnx2x_q_send_setup_e2(struct bnx2x *bp, bnx2x_q_fill_setup_data_cmn(bp, params, rdata); bnx2x_q_fill_setup_data_e2(bp, params, rdata); - mb(); - return bnx2x_sp_post(bp, ramrod, o->cid, U64_HI(data_mapping), + return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX], + U64_HI(data_mapping), + U64_LO(data_mapping), ETH_CONNECTION_TYPE); +} + +static inline int bnx2x_q_send_setup_tx_only(struct bnx2x *bp, + struct bnx2x_queue_state_params *params) +{ + struct bnx2x_queue_sp_obj *o = params->q_obj; + struct tx_queue_init_ramrod_data *rdata = + (struct tx_queue_init_ramrod_data *)o->rdata; + dma_addr_t data_mapping = o->rdata_mapping; + int ramrod = RAMROD_CMD_ID_ETH_TX_QUEUE_SETUP; + struct bnx2x_queue_setup_tx_only_params *tx_only_params = + ¶ms->params.tx_only; + u8 cid_index = tx_only_params->cid_index; + + + if (cid_index >= o->max_cos) { + BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n", + o->cl_id, cid_index); + return -EINVAL; + } + + DP(BNX2X_MSG_SP, "parameters received: cos: %d sp-id: %d", + tx_only_params->gen_params.cos, + tx_only_params->gen_params.spcl_id); + + /* Clear the ramrod data */ + memset(rdata, 0, sizeof(*rdata)); + + /* Fill the ramrod data */ + bnx2x_q_fill_setup_tx_only(bp, params, rdata); + + DP(BNX2X_MSG_SP, "sending tx-only ramrod: cid %d, client-id %d," + "sp-client id %d, cos %d", + o->cids[cid_index], + rdata->general.client_id, + rdata->general.sp_client_id, rdata->general.cos); + + /* + * No need for an explicit memory barrier here as long we would + * need to ensure the ordering of writing to the SPQ element + * and updating of the SPQ producer which involves a memory + * read and we will have to put a full memory barrier there + * (inside bnx2x_sp_post()). + */ + + return bnx2x_sp_post(bp, ramrod, o->cids[cid_index], + U64_HI(data_mapping), U64_LO(data_mapping), ETH_CONNECTION_TYPE); } @@ -4521,17 +4648,27 @@ static inline int bnx2x_q_send_update(struct bnx2x *bp, struct client_update_ramrod_data *rdata = (struct client_update_ramrod_data *)o->rdata; dma_addr_t data_mapping = o->rdata_mapping; + struct bnx2x_queue_update_params *update_params = + ¶ms->params.update; + u8 cid_index = update_params->cid_index; + + if (cid_index >= o->max_cos) { + BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n", + o->cl_id, cid_index); + return -EINVAL; + } + /* Clear the ramrod data */ memset(rdata, 0, sizeof(*rdata)); /* Fill the ramrod data */ - bnx2x_q_fill_update_data(bp, o, ¶ms->params.update, rdata); + bnx2x_q_fill_update_data(bp, o, update_params, rdata); mb(); - return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_UPDATE, o->cid, - U64_HI(data_mapping), + return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_UPDATE, + o->cids[cid_index], U64_HI(data_mapping), U64_LO(data_mapping), ETH_CONNECTION_TYPE); } @@ -4588,7 +4725,8 @@ static inline int bnx2x_q_send_halt(struct bnx2x *bp, { struct bnx2x_queue_sp_obj *o = params->q_obj; - return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, o->cid, 0, o->cl_id, + return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, + o->cids[BNX2X_PRIMARY_CID_INDEX], 0, o->cl_id, ETH_CONNECTION_TYPE); } @@ -4596,18 +4734,32 @@ static inline int bnx2x_q_send_cfc_del(struct bnx2x *bp, struct bnx2x_queue_state_params *params) { struct bnx2x_queue_sp_obj *o = params->q_obj; + u8 cid_idx = params->params.cfc_del.cid_index; - return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_CFC_DEL, o->cid, 0, 0, - NONE_CONNECTION_TYPE); + if (cid_idx >= o->max_cos) { + BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n", + o->cl_id, cid_idx); + return -EINVAL; + } + + return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_CFC_DEL, + o->cids[cid_idx], 0, 0, NONE_CONNECTION_TYPE); } static inline int bnx2x_q_send_terminate(struct bnx2x *bp, struct bnx2x_queue_state_params *params) { struct bnx2x_queue_sp_obj *o = params->q_obj; + u8 cid_index = params->params.terminate.cid_index; - return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_TERMINATE, o->cid, 0, 0, - ETH_CONNECTION_TYPE); + if (cid_index >= o->max_cos) { + BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n", + o->cl_id, cid_index); + return -EINVAL; + } + + return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_TERMINATE, + o->cids[cid_index], 0, 0, ETH_CONNECTION_TYPE); } static inline int bnx2x_q_send_empty(struct bnx2x *bp, @@ -4615,7 +4767,8 @@ static inline int bnx2x_q_send_empty(struct bnx2x *bp, { struct bnx2x_queue_sp_obj *o = params->q_obj; - return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_EMPTY, o->cid, 0, 0, + return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_EMPTY, + o->cids[BNX2X_PRIMARY_CID_INDEX], 0, 0, ETH_CONNECTION_TYPE); } @@ -4625,6 +4778,8 @@ static inline int bnx2x_queue_send_cmd_cmn(struct bnx2x *bp, switch (params->cmd) { case BNX2X_Q_CMD_INIT: return bnx2x_q_init(bp, params); + case BNX2X_Q_CMD_SETUP_TX_ONLY: + return bnx2x_q_send_setup_tx_only(bp, params); case BNX2X_Q_CMD_DEACTIVATE: return bnx2x_q_send_deactivate(bp, params); case BNX2X_Q_CMD_ACTIVATE: @@ -4654,6 +4809,7 @@ static int bnx2x_queue_send_cmd_e1x(struct bnx2x *bp, case BNX2X_Q_CMD_SETUP: return bnx2x_q_send_setup_e1x(bp, params); case BNX2X_Q_CMD_INIT: + case BNX2X_Q_CMD_SETUP_TX_ONLY: case BNX2X_Q_CMD_DEACTIVATE: case BNX2X_Q_CMD_ACTIVATE: case BNX2X_Q_CMD_UPDATE: @@ -4676,6 +4832,7 @@ static int bnx2x_queue_send_cmd_e2(struct bnx2x *bp, case BNX2X_Q_CMD_SETUP: return bnx2x_q_send_setup_e2(bp, params); case BNX2X_Q_CMD_INIT: + case BNX2X_Q_CMD_SETUP_TX_ONLY: case BNX2X_Q_CMD_DEACTIVATE: case BNX2X_Q_CMD_ACTIVATE: case BNX2X_Q_CMD_UPDATE: @@ -4713,6 +4870,9 @@ static int bnx2x_queue_chk_transition(struct bnx2x *bp, { enum bnx2x_q_state state = o->state, next_state = BNX2X_Q_STATE_MAX; enum bnx2x_queue_cmd cmd = params->cmd; + struct bnx2x_queue_update_params *update_params = + ¶ms->params.update; + u8 next_tx_only = o->num_tx_only; switch (state) { case BNX2X_Q_STATE_RESET: @@ -4738,13 +4898,42 @@ static int bnx2x_queue_chk_transition(struct bnx2x *bp, (cmd == BNX2X_Q_CMD_UPDATE_TPA)) next_state = BNX2X_Q_STATE_ACTIVE; + else if (cmd == BNX2X_Q_CMD_SETUP_TX_ONLY) { + next_state = BNX2X_Q_STATE_MULTI_COS; + next_tx_only = 1; + } + else if (cmd == BNX2X_Q_CMD_HALT) next_state = BNX2X_Q_STATE_STOPPED; else if (cmd == BNX2X_Q_CMD_UPDATE) { - struct bnx2x_queue_update_params *update_params = - ¶ms->params.update; + /* If "active" state change is requested, update the + * state accordingly. + */ + if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, + &update_params->update_flags) && + !test_bit(BNX2X_Q_UPDATE_ACTIVATE, + &update_params->update_flags)) + next_state = BNX2X_Q_STATE_INACTIVE; + else + next_state = BNX2X_Q_STATE_ACTIVE; + } + break; + case BNX2X_Q_STATE_MULTI_COS: + if (cmd == BNX2X_Q_CMD_TERMINATE) + next_state = BNX2X_Q_STATE_MCOS_TERMINATED; + + else if (cmd == BNX2X_Q_CMD_SETUP_TX_ONLY) { + next_state = BNX2X_Q_STATE_MULTI_COS; + next_tx_only = o->num_tx_only + 1; + } + + else if ((cmd == BNX2X_Q_CMD_EMPTY) || + (cmd == BNX2X_Q_CMD_UPDATE_TPA)) + next_state = BNX2X_Q_STATE_MULTI_COS; + + else if (cmd == BNX2X_Q_CMD_UPDATE) { /* If "active" state change is requested, update the * state accordingly. */ @@ -4754,7 +4943,17 @@ static int bnx2x_queue_chk_transition(struct bnx2x *bp, &update_params->update_flags)) next_state = BNX2X_Q_STATE_INACTIVE; else + next_state = BNX2X_Q_STATE_MULTI_COS; + } + + break; + case BNX2X_Q_STATE_MCOS_TERMINATED: + if (cmd == BNX2X_Q_CMD_CFC_DEL) { + next_tx_only = o->num_tx_only - 1; + if (next_tx_only == 0) next_state = BNX2X_Q_STATE_ACTIVE; + else + next_state = BNX2X_Q_STATE_MULTI_COS; } break; @@ -4770,18 +4969,18 @@ static int bnx2x_queue_chk_transition(struct bnx2x *bp, next_state = BNX2X_Q_STATE_STOPPED; else if (cmd == BNX2X_Q_CMD_UPDATE) { - struct bnx2x_queue_update_params *update_params = - ¶ms->params.update; - /* If "active" state change is requested, update the * state accordingly. */ if (test_bit(BNX2X_Q_UPDATE_ACTIVATE_CHNG, &update_params->update_flags) && test_bit(BNX2X_Q_UPDATE_ACTIVATE, - &update_params->update_flags)) - next_state = BNX2X_Q_STATE_ACTIVE; - else + &update_params->update_flags)){ + if (o->num_tx_only == 0) + next_state = BNX2X_Q_STATE_ACTIVE; + else /* tx only queues exist for this queue */ + next_state = BNX2X_Q_STATE_MULTI_COS; + } else next_state = BNX2X_Q_STATE_INACTIVE; } @@ -4805,6 +5004,7 @@ static int bnx2x_queue_chk_transition(struct bnx2x *bp, DP(BNX2X_MSG_SP, "Good state transition: %d(%d)->%d\n", state, cmd, next_state); o->next_state = next_state; + o->next_tx_only = next_tx_only; return 0; } @@ -4815,12 +5015,17 @@ static int bnx2x_queue_chk_transition(struct bnx2x *bp, void bnx2x_init_queue_obj(struct bnx2x *bp, struct bnx2x_queue_sp_obj *obj, - u8 cl_id, u32 cid, u8 func_id, void *rdata, + u8 cl_id, u32 *cids, u8 cid_cnt, u8 func_id, + void *rdata, dma_addr_t rdata_mapping, unsigned long type) { memset(obj, 0, sizeof(*obj)); - obj->cid = cid; + /* We support only BNX2X_MULTI_TX_COS Tx CoS at the moment */ + BUG_ON(BNX2X_MULTI_TX_COS < cid_cnt); + + memcpy(obj->cids, cids, sizeof(obj->cids[0]) * cid_cnt); + obj->max_cos = cid_cnt; obj->cl_id = cl_id; obj->func_id = func_id; obj->rdata = rdata; @@ -4840,6 +5045,13 @@ void bnx2x_init_queue_obj(struct bnx2x *bp, obj->set_pending = bnx2x_queue_set_pending; } +void bnx2x_queue_set_cos_cid(struct bnx2x *bp, + struct bnx2x_queue_sp_obj *obj, + u32 cid, u8 index) +{ + obj->cids[index] = cid; +} + /********************** Function state object *********************************/ static int bnx2x_func_wait_comp(struct bnx2x *bp, |