HCLGE_MBX_GET_QID_IN_PF,        /* (VF -> PF) get queue id in pf */
        HCLGE_MBX_LINK_STAT_MODE,       /* (PF -> VF) link mode has changed */
        HCLGE_MBX_GET_LINK_MODE,        /* (VF -> PF) get the link mode of pf */
+       HLCGE_MBX_PUSH_VLAN_INFO,       /* (PF -> VF) push port base vlan */
        HCLGE_MBX_GET_MEDIA_TYPE,       /* (VF -> PF) get media type */
 
        HCLGE_MBX_GET_VF_FLR_STATUS = 200, /* (M7 -> PF) get vf reset status */
        HCLGE_MBX_VLAN_FILTER = 0,      /* set vlan filter */
        HCLGE_MBX_VLAN_TX_OFF_CFG,      /* set tx side vlan offload */
        HCLGE_MBX_VLAN_RX_OFF_CFG,      /* set rx side vlan offload */
+       HCLGE_MBX_PORT_BASE_VLAN_CFG,   /* set port based vlan configuration */
+       HCLGE_MBX_GET_PORT_BASE_VLAN_STATE,     /* get port based vlan state */
 };
 
 #define HCLGE_MBX_MAX_MSG_SIZE 16
 
                return ret;
        }
 
-       return -EOPNOTSUPP;
+       if (!test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state)) {
+               return hclge_update_port_base_vlan_cfg(vport, state,
+                                                      &vlan_info);
+       } else {
+               ret = hclge_push_vf_port_base_vlan_info(&hdev->vport[0],
+                                                       (u8)vfid, state,
+                                                       vlan, qos,
+                                                       ntohs(proto));
+               return ret;
+       }
 }
 
 int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto,
 
 void hclge_uninit_vport_vlan_table(struct hclge_dev *hdev);
 int hclge_update_port_base_vlan_cfg(struct hclge_vport *vport, u16 state,
                                    struct hclge_vlan_info *vlan_info);
+int hclge_push_vf_port_base_vlan_info(struct hclge_vport *vport, u8 vfid,
+                                     u16 state, u16 vlan_tag, u16 qos,
+                                     u16 vlan_proto);
 #endif
 
        return 0;
 }
 
+int hclge_push_vf_port_base_vlan_info(struct hclge_vport *vport, u8 vfid,
+                                     u16 state, u16 vlan_tag, u16 qos,
+                                     u16 vlan_proto)
+{
+#define MSG_DATA_SIZE  8
+
+       u8 msg_data[MSG_DATA_SIZE];
+
+       memcpy(&msg_data[0], &state, sizeof(u16));
+       memcpy(&msg_data[2], &vlan_proto, sizeof(u16));
+       memcpy(&msg_data[4], &qos, sizeof(u16));
+       memcpy(&msg_data[6], &vlan_tag, sizeof(u16));
+
+       return hclge_send_mbx_msg(vport, msg_data, sizeof(msg_data),
+                                 HLCGE_MBX_PUSH_VLAN_INFO, vfid);
+}
+
 static int hclge_set_vf_vlan_cfg(struct hclge_vport *vport,
-                                struct hclge_mbx_vf_to_pf_cmd *mbx_req,
-                                bool gen_resp)
+                                struct hclge_mbx_vf_to_pf_cmd *mbx_req)
 {
        int status = 0;
 
                bool en = mbx_req->msg[2] ? true : false;
 
                status = hclge_en_hw_strip_rxvtag(handle, en);
+       } else if (mbx_req->msg[1] == HCLGE_MBX_PORT_BASE_VLAN_CFG) {
+               struct hclge_vlan_info *vlan_info;
+               u16 *state;
+
+               state = (u16 *)&mbx_req->msg[2];
+               vlan_info = (struct hclge_vlan_info *)&mbx_req->msg[4];
+               status = hclge_update_port_base_vlan_cfg(vport, *state,
+                                                        vlan_info);
+       } else if (mbx_req->msg[1] == HCLGE_MBX_GET_PORT_BASE_VLAN_STATE) {
+               u8 state;
+
+               state = vport->port_base_vlan_cfg.state;
+               status = hclge_gen_resp_to_vf(vport, mbx_req, 0, &state,
+                                             sizeof(u8));
        }
 
-       if (gen_resp)
-               status = hclge_gen_resp_to_vf(vport, mbx_req, status, NULL, 0);
-
        return status;
 }
 
                                        ret);
                        break;
                case HCLGE_MBX_SET_VLAN:
-                       ret = hclge_set_vf_vlan_cfg(vport, req, false);
+                       ret = hclge_set_vf_vlan_cfg(vport, req);
                        if (ret)
                                dev_err(&hdev->pdev->dev,
                                        "PF failed(%d) to config VF's VLAN\n",
 
        return 0;
 }
 
+static int hclgevf_get_port_base_vlan_filter_state(struct hclgevf_dev *hdev)
+{
+       struct hnae3_handle *nic = &hdev->nic;
+       u8 resp_msg;
+       int ret;
+
+       ret = hclgevf_send_mbx_msg(hdev, HCLGE_MBX_SET_VLAN,
+                                  HCLGE_MBX_GET_PORT_BASE_VLAN_STATE,
+                                  NULL, 0, true, &resp_msg, sizeof(u8));
+       if (ret) {
+               dev_err(&hdev->pdev->dev,
+                       "VF request to get port based vlan state failed %d",
+                       ret);
+               return ret;
+       }
+
+       nic->port_base_vlan_state = resp_msg;
+
+       return 0;
+}
+
 static int hclgevf_get_queue_info(struct hclgevf_dev *hdev)
 {
 #define HCLGEVF_TQPS_RSS_INFO_LEN      6
 {
        int ret;
 
+       /* get current port based vlan state from PF */
+       ret = hclgevf_get_port_base_vlan_filter_state(hdev);
+       if (ret)
+               return ret;
+
        /* get queue configuration from PF */
        ret = hclgevf_get_queue_info(hdev);
        if (ret)
        }
 }
 
+void hclgevf_update_port_base_vlan_info(struct hclgevf_dev *hdev, u16 state,
+                                       u8 *port_base_vlan_info, u8 data_size)
+{
+       struct hnae3_handle *nic = &hdev->nic;
+
+       rtnl_lock();
+       hclgevf_notify_client(hdev, HNAE3_DOWN_CLIENT);
+       rtnl_unlock();
+
+       /* send msg to PF and wait update port based vlan info */
+       hclgevf_send_mbx_msg(hdev, HCLGE_MBX_SET_VLAN,
+                            HCLGE_MBX_PORT_BASE_VLAN_CFG,
+                            port_base_vlan_info, data_size,
+                            false, NULL, 0);
+
+       if (state == HNAE3_PORT_BASE_VLAN_DISABLE)
+               nic->port_base_vlan_state = HNAE3_PORT_BASE_VLAN_DISABLE;
+       else
+               nic->port_base_vlan_state = HNAE3_PORT_BASE_VLAN_ENABLE;
+
+       rtnl_lock();
+       hclgevf_notify_client(hdev, HNAE3_UP_CLIENT);
+       rtnl_unlock();
+}
+
 static const struct hnae3_ae_ops hclgevf_ops = {
        .init_ae_dev = hclgevf_init_ae_dev,
        .uninit_ae_dev = hclgevf_uninit_ae_dev,
 
                                 u8 duplex);
 void hclgevf_reset_task_schedule(struct hclgevf_dev *hdev);
 void hclgevf_mbx_task_schedule(struct hclgevf_dev *hdev);
+void hclgevf_update_port_base_vlan_info(struct hclgevf_dev *hdev, u16 state,
+                                       u8 *port_base_vlan_info, u8 data_size);
 #endif
 
                case HCLGE_MBX_LINK_STAT_CHANGE:
                case HCLGE_MBX_ASSERTING_RESET:
                case HCLGE_MBX_LINK_STAT_MODE:
+               case HLCGE_MBX_PUSH_VLAN_INFO:
                        /* set this mbx event as pending. This is required as we
                         * might loose interrupt event when mbx task is busy
                         * handling. This shall be cleared when mbx task just
 void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev)
 {
        enum hnae3_reset_type reset_type;
-       u16 link_status;
-       u16 *msg_q;
+       u16 link_status, state;
+       u16 *msg_q, *vlan_info;
        u8 duplex;
        u32 speed;
        u32 tail;
                        hclgevf_reset_task_schedule(hdev);
 
                        break;
+               case HLCGE_MBX_PUSH_VLAN_INFO:
+                       state = le16_to_cpu(msg_q[1]);
+                       vlan_info = &msg_q[1];
+                       hclgevf_update_port_base_vlan_info(hdev, state,
+                                                          (u8 *)vlan_info, 8);
+                       break;
                default:
                        dev_err(&hdev->pdev->dev,
                                "fetched unsupported(%d) message from arq\n",