net/hinic: set link down and up
[dpdk.git] / drivers / net / hinic / base / hinic_pmd_niccfg.c
index 0a20ade..9f23fdd 100644 (file)
                        buf_in, in_size,                        \
                        buf_out, out_size, 0)
 
+
+#define TCAM_SET       0x1
+#define TCAM_CLEAR     0x2
+
+struct hinic_port_qfilter_info {
+       struct hinic_mgmt_msg_head mgmt_msg_head;
+
+       u16 func_id;
+       u8 normal_type_enable;
+       u8 filter_type_enable;
+       u8 filter_enable;
+       u8 filter_type;
+       u8 qid;
+       u8 fdir_flag;
+       u32 key;
+};
+
 /**
  * hinic_init_function_table - Initialize function table.
  *
@@ -249,6 +266,61 @@ int hinic_get_default_mac(void *hwdev, u8 *mac_addr)
        return 0;
 }
 
+/**
+*  hinic_update_mac - Update mac address to hardware.
+*
+* @param hwdev
+*   The hardware interface of a nic device.
+* @param old_mac
+*   Old mac address.
+* @param new_mac
+*   New mac address.
+* @param vlan_id
+*   Set 0 for mac_vlan table initialization.
+* @param func_id
+*   Global function id of NIC.
+*
+* @return
+*   0 on success.
+*   negative error value otherwise.
+*/
+int hinic_update_mac(void *hwdev, u8 *old_mac, u8 *new_mac, u16 vlan_id,
+                    u16 func_id)
+{
+       struct hinic_port_mac_update mac_info;
+       u16 out_size = sizeof(mac_info);
+       int err;
+
+       if (!hwdev || !old_mac || !new_mac) {
+               PMD_DRV_LOG(ERR, "Hwdev, old_mac or new_mac is NULL\n");
+               return -EINVAL;
+       }
+
+       memset(&mac_info, 0, sizeof(mac_info));
+       mac_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+       mac_info.func_id = func_id;
+       mac_info.vlan_id = vlan_id;
+       memcpy(mac_info.old_mac, old_mac, ETH_ALEN);
+       memcpy(mac_info.new_mac, new_mac, ETH_ALEN);
+
+       err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_UPDATE_MAC,
+                                    &mac_info, sizeof(mac_info),
+                                    &mac_info, &out_size);
+       if (err || !out_size ||
+           (mac_info.mgmt_msg_head.status &&
+            mac_info.mgmt_msg_head.status != HINIC_PF_SET_VF_ALREADY)) {
+               PMD_DRV_LOG(ERR, "Failed to update MAC, err: %d, status: 0x%x, out size: 0x%x\n",
+                           err, mac_info.mgmt_msg_head.status, out_size);
+               return -EINVAL;
+       }
+       if (mac_info.mgmt_msg_head.status == HINIC_PF_SET_VF_ALREADY) {
+               PMD_DRV_LOG(WARNING, "PF has already set vf mac, Ignore update operation.\n");
+               return HINIC_PF_SET_VF_ALREADY;
+       }
+
+       return 0;
+}
+
 /**
  * hinic_set_port_mtu -  Set MTU to port.
  *
@@ -289,6 +361,142 @@ int hinic_set_port_mtu(void *hwdev, u32 new_mtu)
        return 0;
 }
 
+/**
+ * hinic_add_remove_vlan - Add or remove vlan id to vlan elb table.
+ *
+ * @param hwdev
+ *   The hardware interface of a nic device.
+ * @param vlan_id
+ *   Vlan id.
+ * @param func_id
+ *   Global function id of NIC.
+ * @param add
+ *   Add or remove operation.
+ *
+ * @return
+ *   0 on success.
+ *   negative error value otherwise.
+ */
+int hinic_add_remove_vlan(void *hwdev, u16 vlan_id, u16 func_id, bool add)
+{
+       struct hinic_vlan_config vlan_info;
+       u16 out_size = sizeof(vlan_info);
+       u8 cmd;
+       int err;
+
+       if (!hwdev) {
+               PMD_DRV_LOG(ERR, "Hwdev is NULL");
+               return -EINVAL;
+       }
+
+       cmd = add ? HINIC_PORT_CMD_ADD_VLAN : HINIC_PORT_CMD_DEL_VLAN;
+
+       memset(&vlan_info, 0, sizeof(vlan_info));
+       vlan_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+       vlan_info.func_id = func_id;
+       vlan_info.vlan_id = vlan_id;
+
+       err = l2nic_msg_to_mgmt_sync(hwdev, cmd, &vlan_info,
+                                    sizeof(vlan_info), &vlan_info,
+                                    &out_size);
+       if (err || !out_size || vlan_info.mgmt_msg_head.status) {
+               PMD_DRV_LOG(ERR,
+                       "Failed to %s vlan, err: %d, status: 0x%x, out size: 0x%x\n",
+                       add ? "add" : "remove", err,
+                       vlan_info.mgmt_msg_head.status, out_size);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/**
+ * hinic_config_vlan_filter - Enable or Disable vlan filter.
+ *
+ * @param hwdev
+ *   The hardware interface of a nic device.
+ * @param vlan_filter_ctrl
+ *   Enable or Disable.
+ *
+ * @return
+ *   0 on success.
+ *   negative error value otherwise.
+ */
+int hinic_config_vlan_filter(void *hwdev, u32 vlan_filter_ctrl)
+{
+       struct hinic_hwdev *nic_hwdev = (struct hinic_hwdev *)hwdev;
+       struct hinic_vlan_filter vlan_filter;
+       u16 out_size = sizeof(vlan_filter);
+       int err;
+
+       if (!hwdev)
+               return -EINVAL;
+
+       memset(&vlan_filter, 0, sizeof(vlan_filter));
+       vlan_filter.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+       vlan_filter.func_id = hinic_global_func_id(nic_hwdev);
+       vlan_filter.vlan_filter_ctrl = vlan_filter_ctrl;
+
+       err = l2nic_msg_to_mgmt_sync(nic_hwdev, HINIC_PORT_CMD_SET_VLAN_FILTER,
+                                    &vlan_filter, sizeof(vlan_filter),
+                                    &vlan_filter, &out_size);
+       if (vlan_filter.mgmt_msg_head.status == HINIC_MGMT_CMD_UNSUPPORTED) {
+               err = HINIC_MGMT_CMD_UNSUPPORTED;
+       } else if ((err == HINIC_MBOX_VF_CMD_ERROR) &&
+               (HINIC_IS_VF(nic_hwdev))) {
+               err = HINIC_MGMT_CMD_UNSUPPORTED;
+       } else if (err || !out_size || vlan_filter.mgmt_msg_head.status) {
+               PMD_DRV_LOG(ERR,
+                       "Failed to config vlan filter, vlan_filter_ctrl: 0x%x, err: %d, status: 0x%x, out size: 0x%x\n",
+                       vlan_filter_ctrl, err,
+                       vlan_filter.mgmt_msg_head.status, out_size);
+               err = -EINVAL;
+       }
+
+       return err;
+}
+
+/**
+ * hinic_set_rx_vlan_offload - Enable or Disable vlan offload.
+ *
+ * @param hwdev
+ *   The hardware interface of a nic device.
+ * @param en
+ *   Enable or Disable.
+ *
+ * @return
+ *   0 on success.
+ *   negative error value otherwise.
+ */
+int hinic_set_rx_vlan_offload(void *hwdev, u8 en)
+{
+       struct hinic_vlan_offload vlan_cfg;
+       u16 out_size = sizeof(vlan_cfg);
+       int err;
+
+       if (!hwdev) {
+               PMD_DRV_LOG(ERR, "Hwdev is NULL");
+               return -EINVAL;
+       }
+
+       memset(&vlan_cfg, 0, sizeof(vlan_cfg));
+       vlan_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+       vlan_cfg.func_id = hinic_global_func_id(hwdev);
+       vlan_cfg.vlan_rx_offload = en;
+
+       err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_VLAN_OFFLOAD,
+                                       &vlan_cfg, sizeof(vlan_cfg),
+                                       &vlan_cfg, &out_size);
+       if (err || !out_size || vlan_cfg.mgmt_msg_head.status) {
+               PMD_DRV_LOG(ERR,
+                       "Failed to set rx vlan offload, err: %d, status: 0x%x, out size: 0x%x\n",
+                       err, vlan_cfg.mgmt_msg_head.status, out_size);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 /**
  * hinic_get_link_status - Get link status from hardware.
  *
@@ -1404,6 +1612,44 @@ int hinic_get_link_mode(void *hwdev, u32 *supported, u32 *advertised)
        return 0;
 }
 
+/**
+ * hinic_set_xsfp_tx_status - Enable or disable the fiber in
+ * tx direction when set link up or down.
+ *
+ * @param hwdev
+ *   The hardware interface of a nic device.
+ * @param enable
+ *   Enable or Disable.
+ *
+ * @return
+ *   0 on success.
+ *   negative error value otherwise.
+ */
+int hinic_set_xsfp_tx_status(void *hwdev, bool enable)
+{
+       struct hinic_set_xsfp_status xsfp_status;
+       u16 out_size = sizeof(struct hinic_set_xsfp_status);
+       int err;
+
+       memset(&xsfp_status, 0, sizeof(xsfp_status));
+       xsfp_status.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+       xsfp_status.port_id = hinic_global_func_id(hwdev);
+       xsfp_status.xsfp_tx_dis = ((enable == 0) ? 1 : 0);
+
+       err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_XSFP_STATUS,
+               &xsfp_status, sizeof(struct hinic_set_xsfp_status),
+               &xsfp_status, &out_size);
+       if (err || !out_size || xsfp_status.mgmt_msg_head.status) {
+               PMD_DRV_LOG(ERR,
+                       "Failed to %s port xsfp status, err: %d, status: 0x%x, out size: 0x%x\n",
+                       enable ? "Disable" : "Enable", err,
+                       xsfp_status.mgmt_msg_head.status, out_size);
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
 /**
  * hinic_flush_qp_res - Flush tx && rx chip resources in case of set vport
  * fake failed when device start.
@@ -1471,3 +1717,191 @@ int hinic_vf_get_default_cos(struct hinic_hwdev *hwdev, u8 *cos_id)
 
        return 0;
 }
+
+/**
+ * hinic_set_fdir_filter - Set fdir filter for control path
+ * packet to notify firmware.
+ *
+ * @param hwdev
+ *   The hardware interface of a nic device.
+ * @param filter_type
+ *   Packet type to filter.
+ * @param qid
+ *   Rx qid to filter.
+ * @param type_enable
+ *   The status of pkt type filter.
+ * @param enable
+ *   Fdir function Enable or Disable.
+ * @return
+ *   0 on success,
+ *   negative error value otherwise.
+ */
+int hinic_set_fdir_filter(void *hwdev, u8 filter_type, u8 qid, u8 type_enable,
+                         bool enable)
+{
+       struct hinic_port_qfilter_info port_filer_cmd;
+       u16 out_size = sizeof(port_filer_cmd);
+       int err;
+
+       if (!hwdev)
+               return -EINVAL;
+
+       memset(&port_filer_cmd, 0, sizeof(port_filer_cmd));
+       port_filer_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+       port_filer_cmd.func_id = hinic_global_func_id(hwdev);
+       port_filer_cmd.filter_enable = (u8)enable;
+       port_filer_cmd.filter_type = filter_type;
+       port_filer_cmd.qid = qid;
+       port_filer_cmd.filter_type_enable = type_enable;
+       port_filer_cmd.fdir_flag = 0;
+
+       err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_Q_FILTER,
+                       &port_filer_cmd, sizeof(port_filer_cmd),
+                       &port_filer_cmd, &out_size);
+       if (err || !out_size || port_filer_cmd.mgmt_msg_head.status) {
+               PMD_DRV_LOG(ERR, "Set port Q filter failed, err: %d, status: 0x%x, out size: 0x%x, type: 0x%x,"
+                       " enable: 0x%x, qid: 0x%x, filter_type_enable: 0x%x\n",
+                       err, port_filer_cmd.mgmt_msg_head.status, out_size,
+                       filter_type, enable, qid, type_enable);
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+/**
+ * hinic_set_normal_filter - Set fdir filter for IO path packet.
+ *
+ * @param hwdev
+ *   The hardware interface of a nic device.
+ * @param qid
+ *   Rx qid to filter.
+ * @param normal_type_enable
+ *   IO path packet function Enable or Disable
+ * @param key
+ *   IO path packet filter key value, such as DIP from pkt.
+ * @param enable
+ *   Fdir function Enable or Disable.
+ * @param flag
+ *   Filter flag, such as dip or others.
+ * @return
+ *   0 on success,
+ *   negative error value otherwise.
+ */
+int hinic_set_normal_filter(void *hwdev, u8 qid, u8 normal_type_enable,
+                               u32 key, bool enable, u8 flag)
+{
+       struct hinic_port_qfilter_info port_filer_cmd;
+       u16 out_size = sizeof(port_filer_cmd);
+       int err;
+
+       if (!hwdev)
+               return -EINVAL;
+
+       memset(&port_filer_cmd, 0, sizeof(port_filer_cmd));
+       port_filer_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+       port_filer_cmd.func_id = hinic_global_func_id(hwdev);
+       port_filer_cmd.filter_enable = (u8)enable;
+       port_filer_cmd.qid = qid;
+       port_filer_cmd.normal_type_enable = normal_type_enable;
+       port_filer_cmd.fdir_flag = flag; /* fdir flag: support dip */
+       port_filer_cmd.key = key;
+
+       err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_Q_FILTER,
+                       &port_filer_cmd, sizeof(port_filer_cmd),
+                       &port_filer_cmd, &out_size);
+       if (err || !out_size || port_filer_cmd.mgmt_msg_head.status) {
+               PMD_DRV_LOG(ERR, "Set normal filter failed, err: %d, status: 0x%x, out size: 0x%x, fdir_flag: 0x%x,"
+                       " enable: 0x%x, qid: 0x%x, normal_type_enable: 0x%x, key:0x%x\n",
+                       err, port_filer_cmd.mgmt_msg_head.status, out_size,
+                       flag, enable, qid, normal_type_enable, key);
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+/**
+ * hinic_set_fdir_tcam - Set fdir filter for control packet
+ * by tcam table to notify hardware.
+ *
+ * @param hwdev
+ *   The hardware interface of a nic device.
+ * @param type_mask
+ *   Index of TCAM.
+ * @param filter_rule
+ *   TCAM rule for control packet, such as lacp or bgp.
+ * @param filter_action
+ *   TCAM action for control packet, such as accept or drop.
+ * @return
+ *   0 on success,
+ *   negative error value otherwise.
+ */
+int hinic_set_fdir_tcam(void *hwdev, u16 type_mask,
+                       struct tag_pa_rule *filter_rule,
+                       struct tag_pa_action *filter_action)
+{
+       struct hinic_fdir_tcam_info port_tcam_cmd;
+       u16 out_size = sizeof(port_tcam_cmd);
+       int err;
+
+       if (!hwdev)
+               return -EINVAL;
+
+       memset(&port_tcam_cmd, 0, sizeof(port_tcam_cmd));
+       port_tcam_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+       port_tcam_cmd.tcam_index = type_mask;
+       port_tcam_cmd.flag = TCAM_SET;
+       memcpy((void *)&port_tcam_cmd.filter_rule,
+               (void *)filter_rule, sizeof(struct tag_pa_rule));
+       memcpy((void *)&port_tcam_cmd.filter_action,
+               (void *)filter_action, sizeof(struct tag_pa_action));
+
+       err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_TCAM_FILTER,
+                       &port_tcam_cmd, sizeof(port_tcam_cmd),
+                       &port_tcam_cmd, &out_size);
+       if (err || !out_size || port_tcam_cmd.mgmt_msg_head.status) {
+               PMD_DRV_LOG(ERR, "Set tcam table failed, err: %d, status: 0x%x, out size: 0x%x\n",
+                       err, port_tcam_cmd.mgmt_msg_head.status, out_size);
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+/**
+ * hinic_clear_fdir_tcam - Clear fdir filter TCAM table for control packet.
+ *
+ * @param hwdev
+ *   The hardware interface of a nic device.
+ * @param type_mask
+ *   Index of TCAM.
+ * @return
+ *   0 on success,
+ *   negative error value otherwise.
+ */
+int hinic_clear_fdir_tcam(void *hwdev, u16 type_mask)
+{
+       struct hinic_fdir_tcam_info port_tcam_cmd;
+       u16 out_size = sizeof(port_tcam_cmd);
+       int err;
+
+       if (!hwdev)
+               return -EINVAL;
+
+       memset(&port_tcam_cmd, 0, sizeof(port_tcam_cmd));
+       port_tcam_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+       port_tcam_cmd.tcam_index = type_mask;
+       port_tcam_cmd.flag = TCAM_CLEAR;
+
+       err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_TCAM_FILTER,
+                       &port_tcam_cmd, sizeof(port_tcam_cmd),
+                       &port_tcam_cmd, &out_size);
+       if (err || !out_size || port_tcam_cmd.mgmt_msg_head.status) {
+               PMD_DRV_LOG(ERR, "Clear tcam table failed, err: %d, status: 0x%x, out size: 0x%x\n",
+                       err, port_tcam_cmd.mgmt_msg_head.status, out_size);
+               return -EFAULT;
+       }
+
+       return 0;
+}