From b42d6885fe98bce64113e637d361612d511db98a Mon Sep 17 00:00:00 2001 From: Qi Zhang Date: Mon, 25 Mar 2019 13:44:22 +0800 Subject: [PATCH] net/ice/base: add more APIs in switch module Add below APIs in switch module 1. ice_aq_get_vsi_params - get VSI context info 2. ice_aq_add_update_mir_rule - add/update mirror rule 3. ice_aq_delete_mir_rule - delete mirror rule 4. ice_aq_set_storm_ctrl - set storm control configuration 5. ice_aq_get_storm_ctrl - get storm control configuration PMD can use these APIs to enable mirror rule and storm control related features. Signed-off-by: Paul M Stillwell Jr Signed-off-by: Qi Zhang Reviewed-by: Qiming Yang Reviewed-by: Wenzhuo Lu --- drivers/net/ice/base/ice_adminq_cmd.h | 136 +++++++++++++++ drivers/net/ice/base/ice_switch.c | 228 ++++++++++++++++++++++++++ drivers/net/ice/base/ice_switch.h | 29 ++++ 3 files changed, 393 insertions(+) diff --git a/drivers/net/ice/base/ice_adminq_cmd.h b/drivers/net/ice/base/ice_adminq_cmd.h index 056a9fbefb..724657af6b 100644 --- a/drivers/net/ice/base/ice_adminq_cmd.h +++ b/drivers/net/ice/base/ice_adminq_cmd.h @@ -177,6 +177,13 @@ struct ice_aqc_clear_pxe { }; +/* Configure No-Drop Policy Command (direct 0x0112) */ +struct ice_aqc_config_no_drop_policy { + u8 opts; +#define ICE_AQC_FORCE_NO_DROP BIT(0) + u8 rsvd[15]; +}; + /* Get switch configuration (0x0200) */ struct ice_aqc_get_sw_cfg { /* Reserved for command and copy of request flags for response */ @@ -350,6 +357,19 @@ struct ice_aqc_add_update_free_vsi_resp { }; +struct ice_aqc_get_vsi_resp { + __le16 vsi_num; + u8 vf_id; + /* The vsi_flags field uses the ICE_AQ_VSI_TYPE_* defines for values. + * These are found above in struct ice_aqc_add_get_update_free_vsi. + */ + u8 vsi_flags; + __le16 vsi_used; + __le16 vsi_free; + __le32 addr_high; + __le32 addr_low; +}; + struct ice_aqc_vsi_props { __le16 valid_sections; @@ -506,6 +526,110 @@ struct ice_aqc_vsi_props { }; +/* Add/update mirror rule - direct (0x0260) */ +#define ICE_AQC_RULE_ID_VALID_S 7 +#define ICE_AQC_RULE_ID_VALID_M (0x1 << ICE_AQC_RULE_ID_VALID_S) +#define ICE_AQC_RULE_ID_S 0 +#define ICE_AQC_RULE_ID_M (0x3F << ICE_AQC_RULE_ID_S) + +/* Following defines to be used while processing caller specified mirror list + * of VSI indexes. + */ +/* Action: Byte.bit (1.7) + * 0 = Remove VSI from mirror rule + * 1 = Add VSI to mirror rule + */ +#define ICE_AQC_RULE_ACT_S 15 +#define ICE_AQC_RULE_ACT_M (0x1 << ICE_AQC_RULE_ACT_S) +/* Action: 1.2:0.0 = Mirrored VSI */ +#define ICE_AQC_RULE_MIRRORED_VSI_S 0 +#define ICE_AQC_RULE_MIRRORED_VSI_M (0x7FF << ICE_AQC_RULE_MIRRORED_VSI_S) + +/* This is to be used by add/update mirror rule Admin Queue command. + * In case of add mirror rule - if rule ID is specified as + * INVAL_MIRROR_RULE_ID, new rule ID is allocated from shared pool. + * If specified rule_id is valid, then it is used. If specified rule_id + * is in use then new mirroring rule is added. + */ +#define ICE_INVAL_MIRROR_RULE_ID 0xFFFF + +struct ice_aqc_add_update_mir_rule { + __le16 rule_id; + + __le16 rule_type; +#define ICE_AQC_RULE_TYPE_S 0 +#define ICE_AQC_RULE_TYPE_M (0x7 << ICE_AQC_RULE_TYPE_S) + /* VPORT ingress/egress */ +#define ICE_AQC_RULE_TYPE_VPORT_INGRESS 0x1 +#define ICE_AQC_RULE_TYPE_VPORT_EGRESS 0x2 + /* Physical port ingress mirroring. + * All traffic received by this port + */ +#define ICE_AQC_RULE_TYPE_PPORT_INGRESS 0x6 + /* Physical port egress mirroring. All traffic sent by this port */ +#define ICE_AQC_RULE_TYPE_PPORT_EGRESS 0x7 + + /* Number of mirrored entries. + * The values are in the command buffer + */ + __le16 num_entries; + + /* Destination VSI */ + __le16 dest; + __le32 addr_high; + __le32 addr_low; +}; + +/* Delete mirror rule - direct(0x0261) */ +struct ice_aqc_delete_mir_rule { + __le16 rule_id; + __le16 rsvd; + + /* Byte.bit: 20.0 = Keep allocation. If set VSI stays part of + * the PF allocated resources, otherwise it is returned to the + * shared pool + */ +#define ICE_AQC_FLAG_KEEP_ALLOCD_S 0 +#define ICE_AQC_FLAG_KEEP_ALLOCD_M (0x1 << ICE_AQC_FLAG_KEEP_ALLOCD_S) + __le16 flags; + + u8 reserved[10]; +}; + +/* Set/Get storm config - (direct 0x0280, 0x0281) */ +/* This structure holds get storm configuration response and same structure + * is used to perform set_storm_cfg + */ +struct ice_aqc_storm_cfg { + __le32 bcast_thresh_size; + __le32 mcast_thresh_size; + /* Bit 18:0 - Traffic upper threshold size + * Bit 31:19 - Reserved + */ +#define ICE_AQ_THRESHOLD_S 0 +#define ICE_AQ_THRESHOLD_M (0x7FFFF << ICE_AQ_THRESHOLD_S) + + __le32 storm_ctrl_ctrl; + /* Bit 0: MDIPW - Drop Multicast packets in previous window + * Bit 1: MDICW - Drop multicast packets in current window + * Bit 2: BDIPW - Drop broadcast packets in previous window + * Bit 3: BDICW - Drop broadcast packets in current window + */ +#define ICE_AQ_STORM_CTRL_MDIPW_DROP_MULTICAST BIT(0) +#define ICE_AQ_STORM_CTRL_MDICW_DROP_MULTICAST BIT(1) +#define ICE_AQ_STORM_CTRL_BDIPW_DROP_MULTICAST BIT(2) +#define ICE_AQ_STORM_CTRL_BDICW_DROP_MULTICAST BIT(3) + /* Bit 7:5 : Reserved */ + /* Bit 27:8 : Interval - BSC/MSC Time-interval specification: The + * interval size for applying ingress broadcast or multicast storm + * control. + */ +#define ICE_AQ_STORM_BSC_MSC_TIME_INTERVAL_S 8 +#define ICE_AQ_STORM_BSC_MSC_TIME_INTERVAL_M \ + (0xFFFFF << ICE_AQ_STORM_BSC_MSC_TIME_INTERVAL_S) + __le32 reserved; +}; + #define ICE_MAX_NUM_RECIPES 64 @@ -1771,6 +1895,9 @@ struct ice_aq_desc { struct ice_aqc_manage_mac_read mac_read; struct ice_aqc_manage_mac_write mac_write; struct ice_aqc_clear_pxe clear_pxe; + struct ice_aqc_config_no_drop_policy no_drop; + struct ice_aqc_add_update_mir_rule add_update_rule; + struct ice_aqc_delete_mir_rule del_rule; struct ice_aqc_list_caps get_cap; struct ice_aqc_get_phy_caps get_phy; struct ice_aqc_set_phy_cfg set_phy; @@ -1778,6 +1905,7 @@ struct ice_aq_desc { struct ice_aqc_set_port_id_led set_port_id_led; struct ice_aqc_get_sw_cfg get_sw_conf; struct ice_aqc_sw_rules sw_rules; + struct ice_aqc_storm_cfg storm_conf; struct ice_aqc_get_topo get_topo; struct ice_aqc_sched_elem_cmd sched_elem_cmd; struct ice_aqc_query_txsched_res query_sched_res; @@ -1795,6 +1923,7 @@ struct ice_aq_desc { struct ice_aqc_txqs_cleanup txqs_cleanup; struct ice_aqc_add_get_update_free_vsi vsi_cmd; struct ice_aqc_add_update_free_vsi_resp add_update_free_vsi_res; + struct ice_aqc_get_vsi_resp get_vsi_resp; struct ice_aqc_download_pkg download_pkg; struct ice_aqc_get_pkg_info_list get_pkg_info_list; struct ice_aqc_fw_logging fw_logging; @@ -1912,6 +2041,13 @@ enum ice_adminq_opc { ice_aqc_opc_get_vsi_params = 0x0212, ice_aqc_opc_free_vsi = 0x0213, + /* Mirroring rules - add/update, delete */ + ice_aqc_opc_add_update_mir_rule = 0x0260, + ice_aqc_opc_del_mir_rule = 0x0261, + + /* storm configuration */ + ice_aqc_opc_set_storm_cfg = 0x0280, + ice_aqc_opc_get_storm_cfg = 0x0281, /* switch rules population commands */ diff --git a/drivers/net/ice/base/ice_switch.c b/drivers/net/ice/base/ice_switch.c index e6fc9fceeb..34637c1be1 100644 --- a/drivers/net/ice/base/ice_switch.c +++ b/drivers/net/ice/base/ice_switch.c @@ -566,7 +566,174 @@ ice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx, return ice_aq_update_vsi(hw, vsi_ctx, cd); } +/** + * ice_aq_get_vsi_params + * @hw: pointer to the HW struct + * @vsi_ctx: pointer to a VSI context struct + * @cd: pointer to command details structure or NULL + * + * Get VSI context info from hardware (0x0212) + */ +enum ice_status +ice_aq_get_vsi_params(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, + struct ice_sq_cd *cd) +{ + struct ice_aqc_add_get_update_free_vsi *cmd; + struct ice_aqc_get_vsi_resp *resp; + struct ice_aq_desc desc; + enum ice_status status; + cmd = &desc.params.vsi_cmd; + resp = &desc.params.get_vsi_resp; + + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_vsi_params); + + cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID); + + status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info, + sizeof(vsi_ctx->info), cd); + if (!status) { + vsi_ctx->vsi_num = LE16_TO_CPU(resp->vsi_num) & + ICE_AQ_VSI_NUM_M; + vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used); + vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free); + } + + return status; +} + +/** + * ice_aq_add_update_mir_rule - add/update a mirror rule + * @hw: pointer to the HW struct + * @rule_type: Rule Type + * @dest_vsi: VSI number to which packets will be mirrored + * @count: length of the list + * @mr_buf: buffer for list of mirrored VSI numbers + * @cd: pointer to command details structure or NULL + * @rule_id: Rule ID + * + * Add/Update Mirror Rule (0x260). + */ +enum ice_status +ice_aq_add_update_mir_rule(struct ice_hw *hw, u16 rule_type, u16 dest_vsi, + u16 count, struct ice_mir_rule_buf *mr_buf, + struct ice_sq_cd *cd, u16 *rule_id) +{ + struct ice_aqc_add_update_mir_rule *cmd; + struct ice_aq_desc desc; + enum ice_status status; + __le16 *mr_list = NULL; + u16 buf_size = 0; + + switch (rule_type) { + case ICE_AQC_RULE_TYPE_VPORT_INGRESS: + case ICE_AQC_RULE_TYPE_VPORT_EGRESS: + /* Make sure count and mr_buf are set for these rule_types */ + if (!(count && mr_buf)) + return ICE_ERR_PARAM; + + buf_size = count * sizeof(__le16); + mr_list = (__le16 *)ice_malloc(hw, buf_size); + if (!mr_list) + return ICE_ERR_NO_MEMORY; + break; + case ICE_AQC_RULE_TYPE_PPORT_INGRESS: + case ICE_AQC_RULE_TYPE_PPORT_EGRESS: + /* Make sure count and mr_buf are not set for these + * rule_types + */ + if (count || mr_buf) + return ICE_ERR_PARAM; + break; + default: + ice_debug(hw, ICE_DBG_SW, + "Error due to unsupported rule_type %u\n", rule_type); + return ICE_ERR_OUT_OF_RANGE; + } + + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_update_mir_rule); + + /* Pre-process 'mr_buf' items for add/update of virtual port + * ingress/egress mirroring (but not physical port ingress/egress + * mirroring) + */ + if (mr_buf) { + int i; + + for (i = 0; i < count; i++) { + u16 id; + + id = mr_buf[i].vsi_idx & ICE_AQC_RULE_MIRRORED_VSI_M; + + /* Validate specified VSI number, make sure it is less + * than ICE_MAX_VSI, if not return with error. + */ + if (id >= ICE_MAX_VSI) { + ice_debug(hw, ICE_DBG_SW, + "Error VSI index (%u) out-of-range\n", + id); + ice_free(hw, mr_list); + return ICE_ERR_OUT_OF_RANGE; + } + + /* add VSI to mirror rule */ + if (mr_buf[i].add) + mr_list[i] = + CPU_TO_LE16(id | ICE_AQC_RULE_ACT_M); + else /* remove VSI from mirror rule */ + mr_list[i] = CPU_TO_LE16(id); + } + } + + cmd = &desc.params.add_update_rule; + if ((*rule_id) != ICE_INVAL_MIRROR_RULE_ID) + cmd->rule_id = CPU_TO_LE16(((*rule_id) & ICE_AQC_RULE_ID_M) | + ICE_AQC_RULE_ID_VALID_M); + cmd->rule_type = CPU_TO_LE16(rule_type & ICE_AQC_RULE_TYPE_M); + cmd->num_entries = CPU_TO_LE16(count); + cmd->dest = CPU_TO_LE16(dest_vsi); + + status = ice_aq_send_cmd(hw, &desc, mr_list, buf_size, cd); + if (!status) + *rule_id = LE16_TO_CPU(cmd->rule_id) & ICE_AQC_RULE_ID_M; + + ice_free(hw, mr_list); + + return status; +} + +/** + * ice_aq_delete_mir_rule - delete a mirror rule + * @hw: pointer to the HW struct + * @rule_id: Mirror rule ID (to be deleted) + * @keep_allocd: if set, the VSI stays part of the PF allocated res, + * otherwise it is returned to the shared pool + * @cd: pointer to command details structure or NULL + * + * Delete Mirror Rule (0x261). + */ +enum ice_status +ice_aq_delete_mir_rule(struct ice_hw *hw, u16 rule_id, bool keep_allocd, + struct ice_sq_cd *cd) +{ + struct ice_aqc_delete_mir_rule *cmd; + struct ice_aq_desc desc; + + /* rule_id should be in the range 0...63 */ + if (rule_id >= ICE_MAX_NUM_MIRROR_RULES) + return ICE_ERR_OUT_OF_RANGE; + + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_del_mir_rule); + + cmd = &desc.params.del_rule; + rule_id |= ICE_AQC_RULE_ID_VALID_M; + cmd->rule_id = CPU_TO_LE16(rule_id); + + if (keep_allocd) + cmd->flags = CPU_TO_LE16(ICE_AQC_FLAG_KEEP_ALLOCD_M); + + return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); +} /** * ice_aq_alloc_free_vsi_list @@ -626,6 +793,67 @@ ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id, return status; } +/** + * ice_aq_set_storm_ctrl - Sets storm control configuration + * @hw: pointer to the HW struct + * @bcast_thresh: represents the upper threshold for broadcast storm control + * @mcast_thresh: represents the upper threshold for multicast storm control + * @ctl_bitmask: storm control control knobs + * + * Sets the storm control configuration (0x0280) + */ +enum ice_status +ice_aq_set_storm_ctrl(struct ice_hw *hw, u32 bcast_thresh, u32 mcast_thresh, + u32 ctl_bitmask) +{ + struct ice_aqc_storm_cfg *cmd; + struct ice_aq_desc desc; + + cmd = &desc.params.storm_conf; + + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_storm_cfg); + + cmd->bcast_thresh_size = CPU_TO_LE32(bcast_thresh & ICE_AQ_THRESHOLD_M); + cmd->mcast_thresh_size = CPU_TO_LE32(mcast_thresh & ICE_AQ_THRESHOLD_M); + cmd->storm_ctrl_ctrl = CPU_TO_LE32(ctl_bitmask); + + return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); +} + +/** + * ice_aq_get_storm_ctrl - gets storm control configuration + * @hw: pointer to the HW struct + * @bcast_thresh: represents the upper threshold for broadcast storm control + * @mcast_thresh: represents the upper threshold for multicast storm control + * @ctl_bitmask: storm control control knobs + * + * Gets the storm control configuration (0x0281) + */ +enum ice_status +ice_aq_get_storm_ctrl(struct ice_hw *hw, u32 *bcast_thresh, u32 *mcast_thresh, + u32 *ctl_bitmask) +{ + enum ice_status status; + struct ice_aq_desc desc; + + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_storm_cfg); + + status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); + if (!status) { + struct ice_aqc_storm_cfg *resp = &desc.params.storm_conf; + + if (bcast_thresh) + *bcast_thresh = LE32_TO_CPU(resp->bcast_thresh_size) & + ICE_AQ_THRESHOLD_M; + if (mcast_thresh) + *mcast_thresh = LE32_TO_CPU(resp->mcast_thresh_size) & + ICE_AQ_THRESHOLD_M; + if (ctl_bitmask) + *ctl_bitmask = LE32_TO_CPU(resp->storm_ctrl_ctrl); + } + + return status; +} /** * ice_aq_sw_rules - add/update/remove switch rules diff --git a/drivers/net/ice/base/ice_switch.h b/drivers/net/ice/base/ice_switch.h index b28e55a4fe..ebcfaa1200 100644 --- a/drivers/net/ice/base/ice_switch.h +++ b/drivers/net/ice/base/ice_switch.h @@ -29,6 +29,19 @@ struct ice_vsi_ctx { struct LIST_HEAD_TYPE rss_list_head; }; +/* This is to be used by add/update mirror rule Admin Queue command */ +struct ice_mir_rule_buf { + u16 vsi_idx; /* VSI index */ + + /* For each VSI, user can specify whether corresponding VSI + * should be added/removed to/from mirror rule + * + * add mirror rule: this should always be TRUE. + * update mirror rule: add(true) or remove(false) VSI to/from + * mirror rule + */ + u8 add; +}; /* Switch recipe ID enum values are specific to hardware */ enum ice_sw_lkup_type { @@ -290,6 +303,22 @@ ice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx, struct ice_sq_cd *cd); struct ice_vsi_ctx *ice_get_vsi_ctx(struct ice_hw *hw, u16 vsi_handle); void ice_clear_all_vsi_ctx(struct ice_hw *hw); +enum ice_status +ice_aq_get_vsi_params(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, + struct ice_sq_cd *cd); +enum ice_status +ice_aq_add_update_mir_rule(struct ice_hw *hw, u16 rule_type, u16 dest_vsi, + u16 count, struct ice_mir_rule_buf *mr_buf, + struct ice_sq_cd *cd, u16 *rule_id); +enum ice_status +ice_aq_delete_mir_rule(struct ice_hw *hw, u16 rule_id, bool keep_allocd, + struct ice_sq_cd *cd); +enum ice_status +ice_aq_get_storm_ctrl(struct ice_hw *hw, u32 *bcast_thresh, u32 *mcast_thresh, + u32 *ctl_bitmask); +enum ice_status +ice_aq_set_storm_ctrl(struct ice_hw *hw, u32 bcast_thresh, u32 mcast_thresh, + u32 ctl_bitmask); /* Switch config */ enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw);