Commit 8f571c4c authored by David S. Miller's avatar David S. Miller

Merge branch 'hns3-next'

Huazhong Tan says:

====================
net: hns3: updates for -next

This series adds support for pushing link status to VFs for
the HNS3 ethernet driver.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c329e5af 01305e16
...@@ -172,4 +172,7 @@ struct hclgevf_mbx_arq_ring { ...@@ -172,4 +172,7 @@ struct hclgevf_mbx_arq_ring {
(arq.tail = (arq.tail + 1) % HCLGE_MBX_MAX_ARQ_MSG_NUM) (arq.tail = (arq.tail + 1) % HCLGE_MBX_MAX_ARQ_MSG_NUM)
#define hclge_mbx_head_ptr_move_arq(arq) \ #define hclge_mbx_head_ptr_move_arq(arq) \
(arq.head = (arq.head + 1) % HCLGE_MBX_MAX_ARQ_MSG_NUM) (arq.head = (arq.head + 1) % HCLGE_MBX_MAX_ARQ_MSG_NUM)
/* PF immediately push link status to VFs when link status changed */
#define HCLGE_MBX_PUSH_LINK_STATUS_EN BIT(0)
#endif #endif
...@@ -2880,6 +2880,28 @@ static int hclge_get_mac_phy_link(struct hclge_dev *hdev, int *link_status) ...@@ -2880,6 +2880,28 @@ static int hclge_get_mac_phy_link(struct hclge_dev *hdev, int *link_status)
return hclge_get_mac_link_status(hdev, link_status); return hclge_get_mac_link_status(hdev, link_status);
} }
static void hclge_push_link_status(struct hclge_dev *hdev)
{
struct hclge_vport *vport;
int ret;
u16 i;
for (i = 0; i < pci_num_vf(hdev->pdev); i++) {
vport = &hdev->vport[i + HCLGE_VF_VPORT_START_NUM];
if (!test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state) ||
vport->vf_info.link_state != IFLA_VF_LINK_STATE_AUTO)
continue;
ret = hclge_push_vf_link_status(vport);
if (ret) {
dev_err(&hdev->pdev->dev,
"failed to push link status to vf%u, ret = %d\n",
i, ret);
}
}
}
static void hclge_update_link_status(struct hclge_dev *hdev) static void hclge_update_link_status(struct hclge_dev *hdev)
{ {
struct hnae3_handle *rhandle = &hdev->vport[0].roce; struct hnae3_handle *rhandle = &hdev->vport[0].roce;
...@@ -2908,6 +2930,7 @@ static void hclge_update_link_status(struct hclge_dev *hdev) ...@@ -2908,6 +2930,7 @@ static void hclge_update_link_status(struct hclge_dev *hdev)
rclient->ops->link_status_change(rhandle, state); rclient->ops->link_status_change(rhandle, state);
hdev->hw.mac.link = state; hdev->hw.mac.link = state;
hclge_push_link_status(hdev);
} }
clear_bit(HCLGE_STATE_LINK_UPDATING, &hdev->state); clear_bit(HCLGE_STATE_LINK_UPDATING, &hdev->state);
...@@ -3246,14 +3269,24 @@ static int hclge_set_vf_link_state(struct hnae3_handle *handle, int vf, ...@@ -3246,14 +3269,24 @@ static int hclge_set_vf_link_state(struct hnae3_handle *handle, int vf,
{ {
struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back; struct hclge_dev *hdev = vport->back;
int link_state_old;
int ret;
vport = hclge_get_vf_vport(hdev, vf); vport = hclge_get_vf_vport(hdev, vf);
if (!vport) if (!vport)
return -EINVAL; return -EINVAL;
link_state_old = vport->vf_info.link_state;
vport->vf_info.link_state = link_state; vport->vf_info.link_state = link_state;
return 0; ret = hclge_push_vf_link_status(vport);
if (ret) {
vport->vf_info.link_state = link_state_old;
dev_err(&hdev->pdev->dev,
"failed to push vf%d link status, ret = %d\n", vf, ret);
}
return ret;
} }
static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval) static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval)
......
...@@ -1089,4 +1089,5 @@ void hclge_report_hw_error(struct hclge_dev *hdev, ...@@ -1089,4 +1089,5 @@ void hclge_report_hw_error(struct hclge_dev *hdev,
enum hnae3_hw_error_type type); enum hnae3_hw_error_type type);
void hclge_inform_vf_promisc_info(struct hclge_vport *vport); void hclge_inform_vf_promisc_info(struct hclge_vport *vport);
void hclge_dbg_dump_rst_info(struct hclge_dev *hdev); void hclge_dbg_dump_rst_info(struct hclge_dev *hdev);
int hclge_push_vf_link_status(struct hclge_vport *vport);
#endif #endif
...@@ -490,16 +490,14 @@ static void hclge_get_vf_media_type(struct hclge_vport *vport, ...@@ -490,16 +490,14 @@ static void hclge_get_vf_media_type(struct hclge_vport *vport,
resp_msg->len = HCLGE_VF_MEDIA_TYPE_LENGTH; resp_msg->len = HCLGE_VF_MEDIA_TYPE_LENGTH;
} }
static int hclge_get_link_info(struct hclge_vport *vport, int hclge_push_vf_link_status(struct hclge_vport *vport)
struct hclge_mbx_vf_to_pf_cmd *mbx_req)
{ {
#define HCLGE_VF_LINK_STATE_UP 1U #define HCLGE_VF_LINK_STATE_UP 1U
#define HCLGE_VF_LINK_STATE_DOWN 0U #define HCLGE_VF_LINK_STATE_DOWN 0U
struct hclge_dev *hdev = vport->back; struct hclge_dev *hdev = vport->back;
u16 link_status; u16 link_status;
u8 msg_data[8]; u8 msg_data[9];
u8 dest_vfid;
u16 duplex; u16 duplex;
/* mac.link can only be 0 or 1 */ /* mac.link can only be 0 or 1 */
...@@ -520,11 +518,11 @@ static int hclge_get_link_info(struct hclge_vport *vport, ...@@ -520,11 +518,11 @@ static int hclge_get_link_info(struct hclge_vport *vport,
memcpy(&msg_data[0], &link_status, sizeof(u16)); memcpy(&msg_data[0], &link_status, sizeof(u16));
memcpy(&msg_data[2], &hdev->hw.mac.speed, sizeof(u32)); memcpy(&msg_data[2], &hdev->hw.mac.speed, sizeof(u32));
memcpy(&msg_data[6], &duplex, sizeof(u16)); memcpy(&msg_data[6], &duplex, sizeof(u16));
dest_vfid = mbx_req->mbx_src_vfid; msg_data[8] = HCLGE_MBX_PUSH_LINK_STATUS_EN;
/* send this requested info to VF */ /* send this requested info to VF */
return hclge_send_mbx_msg(vport, msg_data, sizeof(msg_data), return hclge_send_mbx_msg(vport, msg_data, sizeof(msg_data),
HCLGE_MBX_LINK_STAT_CHANGE, dest_vfid); HCLGE_MBX_LINK_STAT_CHANGE, vport->vport_id);
} }
static void hclge_get_link_mode(struct hclge_vport *vport, static void hclge_get_link_mode(struct hclge_vport *vport,
...@@ -794,7 +792,7 @@ void hclge_mbx_handler(struct hclge_dev *hdev) ...@@ -794,7 +792,7 @@ void hclge_mbx_handler(struct hclge_dev *hdev)
hclge_get_vf_tcinfo(vport, &resp_msg); hclge_get_vf_tcinfo(vport, &resp_msg);
break; break;
case HCLGE_MBX_GET_LINK_STATUS: case HCLGE_MBX_GET_LINK_STATUS:
ret = hclge_get_link_info(vport, req); ret = hclge_push_vf_link_status(vport);
if (ret) if (ret)
dev_err(&hdev->pdev->dev, dev_err(&hdev->pdev->dev,
"failed to inform link stat to VF, ret = %d\n", "failed to inform link stat to VF, ret = %d\n",
......
...@@ -2340,10 +2340,11 @@ static void hclgevf_periodic_service_task(struct hclgevf_dev *hdev) ...@@ -2340,10 +2340,11 @@ static void hclgevf_periodic_service_task(struct hclgevf_dev *hdev)
if (!(hdev->serv_processed_cnt % HCLGEVF_STATS_TIMER_INTERVAL)) if (!(hdev->serv_processed_cnt % HCLGEVF_STATS_TIMER_INTERVAL))
hclgevf_tqps_update_stats(handle); hclgevf_tqps_update_stats(handle);
/* request the link status from the PF. PF would be able to tell VF /* VF does not need to request link status when this bit is set, because
* about such updates in future so we might remove this later * PF will push its link status to VFs when link status changed.
*/ */
hclgevf_request_link_info(hdev); if (!test_bit(HCLGEVF_STATE_PF_PUSH_LINK_STATUS, &hdev->state))
hclgevf_request_link_info(hdev);
hclgevf_update_link_mode(hdev); hclgevf_update_link_mode(hdev);
...@@ -2657,6 +2658,7 @@ static int hclgevf_ae_start(struct hnae3_handle *handle) ...@@ -2657,6 +2658,7 @@ static int hclgevf_ae_start(struct hnae3_handle *handle)
struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
clear_bit(HCLGEVF_STATE_DOWN, &hdev->state); clear_bit(HCLGEVF_STATE_DOWN, &hdev->state);
clear_bit(HCLGEVF_STATE_PF_PUSH_LINK_STATUS, &hdev->state);
hclgevf_reset_tqp_stats(handle); hclgevf_reset_tqp_stats(handle);
......
...@@ -152,6 +152,7 @@ enum hclgevf_states { ...@@ -152,6 +152,7 @@ enum hclgevf_states {
HCLGEVF_STATE_LINK_UPDATING, HCLGEVF_STATE_LINK_UPDATING,
HCLGEVF_STATE_PROMISC_CHANGED, HCLGEVF_STATE_PROMISC_CHANGED,
HCLGEVF_STATE_RST_FAIL, HCLGEVF_STATE_RST_FAIL,
HCLGEVF_STATE_PF_PUSH_LINK_STATUS,
}; };
struct hclgevf_mac { struct hclgevf_mac {
......
...@@ -276,6 +276,7 @@ void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev) ...@@ -276,6 +276,7 @@ void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev)
u8 duplex; u8 duplex;
u32 speed; u32 speed;
u32 tail; u32 tail;
u8 flag;
u8 idx; u8 idx;
/* we can safely clear it now as we are at start of the async message /* we can safely clear it now as we are at start of the async message
...@@ -300,11 +301,16 @@ void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev) ...@@ -300,11 +301,16 @@ void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev)
link_status = msg_q[1]; link_status = msg_q[1];
memcpy(&speed, &msg_q[2], sizeof(speed)); memcpy(&speed, &msg_q[2], sizeof(speed));
duplex = (u8)msg_q[4]; duplex = (u8)msg_q[4];
flag = (u8)msg_q[5];
/* update upper layer with new link link status */ /* update upper layer with new link link status */
hclgevf_update_link_status(hdev, link_status); hclgevf_update_link_status(hdev, link_status);
hclgevf_update_speed_duplex(hdev, speed, duplex); hclgevf_update_speed_duplex(hdev, speed, duplex);
if (flag & HCLGE_MBX_PUSH_LINK_STATUS_EN)
set_bit(HCLGEVF_STATE_PF_PUSH_LINK_STATUS,
&hdev->state);
break; break;
case HCLGE_MBX_LINK_STAT_MODE: case HCLGE_MBX_LINK_STAT_MODE:
idx = (u8)msg_q[1]; idx = (u8)msg_q[1];
......
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