net: hns3: Change PF to add ring-vect binding & resetQ to mailbox

This patch is required to support ring-vector binding and reset
of TQPs requested by the VF driver to the PF driver. Mailbox
handler is added with corresponding VF commands/messages to
handle the request.

Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
Signed-off-by: lipeng <lipeng321@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Salil Mehta 2017-12-14 18:03:08 +00:00 committed by David S. Miller
parent dde1a86e93
commit 84e095d64e
3 changed files with 159 additions and 92 deletions

View file

@ -3256,49 +3256,48 @@ err:
return ret;
}
int hclge_map_vport_ring_to_vector(struct hclge_vport *vport, int vector_id,
struct hnae3_ring_chain_node *ring_chain)
int hclge_bind_ring_with_vector(struct hclge_vport *vport,
int vector_id, bool en,
struct hnae3_ring_chain_node *ring_chain)
{
struct hclge_dev *hdev = vport->back;
struct hclge_ctrl_vector_chain_cmd *req;
struct hnae3_ring_chain_node *node;
struct hclge_desc desc;
int ret;
struct hclge_ctrl_vector_chain_cmd *req
= (struct hclge_ctrl_vector_chain_cmd *)desc.data;
enum hclge_cmd_status status;
enum hclge_opcode_type op;
u16 tqp_type_and_id;
int i;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_ADD_RING_TO_VECTOR, false);
req = (struct hclge_ctrl_vector_chain_cmd *)desc.data;
op = en ? HCLGE_OPC_ADD_RING_TO_VECTOR : HCLGE_OPC_DEL_RING_TO_VECTOR;
hclge_cmd_setup_basic_desc(&desc, op, false);
req->int_vector_id = vector_id;
i = 0;
for (node = ring_chain; node; node = node->next) {
u16 type_and_id = 0;
hnae_set_field(type_and_id, HCLGE_INT_TYPE_M, HCLGE_INT_TYPE_S,
tqp_type_and_id = le16_to_cpu(req->tqp_type_and_id[i]);
hnae_set_field(tqp_type_and_id, HCLGE_INT_TYPE_M,
HCLGE_INT_TYPE_S,
hnae_get_bit(node->flag, HNAE3_RING_TYPE_B));
hnae_set_field(type_and_id, HCLGE_TQP_ID_M, HCLGE_TQP_ID_S,
node->tqp_index);
hnae_set_field(type_and_id, HCLGE_INT_GL_IDX_M,
HCLGE_INT_GL_IDX_S,
hnae_get_bit(node->flag, HNAE3_RING_TYPE_B));
req->tqp_type_and_id[i] = cpu_to_le16(type_and_id);
req->vfid = vport->vport_id;
hnae_set_field(tqp_type_and_id, HCLGE_TQP_ID_M,
HCLGE_TQP_ID_S, node->tqp_index);
req->tqp_type_and_id[i] = cpu_to_le16(tqp_type_and_id);
if (++i >= HCLGE_VECTOR_ELEMENTS_PER_CMD) {
req->int_cause_num = HCLGE_VECTOR_ELEMENTS_PER_CMD;
req->vfid = vport->vport_id;
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
status = hclge_cmd_send(&hdev->hw, &desc, 1);
if (status) {
dev_err(&hdev->pdev->dev,
"Map TQP fail, status is %d.\n",
ret);
return ret;
status);
return -EIO;
}
i = 0;
hclge_cmd_setup_basic_desc(&desc,
HCLGE_OPC_ADD_RING_TO_VECTOR,
op,
false);
req->int_vector_id = vector_id;
}
@ -3306,21 +3305,21 @@ int hclge_map_vport_ring_to_vector(struct hclge_vport *vport, int vector_id,
if (i > 0) {
req->int_cause_num = i;
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
req->vfid = vport->vport_id;
status = hclge_cmd_send(&hdev->hw, &desc, 1);
if (status) {
dev_err(&hdev->pdev->dev,
"Map TQP fail, status is %d.\n", ret);
return ret;
"Map TQP fail, status is %d.\n", status);
return -EIO;
}
}
return 0;
}
static int hclge_map_handle_ring_to_vector(
struct hnae3_handle *handle, int vector,
struct hnae3_ring_chain_node *ring_chain)
static int hclge_map_ring_to_vector(struct hnae3_handle *handle,
int vector,
struct hnae3_ring_chain_node *ring_chain)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
@ -3329,24 +3328,20 @@ static int hclge_map_handle_ring_to_vector(
vector_id = hclge_get_vector_index(hdev, vector);
if (vector_id < 0) {
dev_err(&hdev->pdev->dev,
"Get vector index fail. ret =%d\n", vector_id);
"Get vector index fail. vector_id =%d\n", vector_id);
return vector_id;
}
return hclge_map_vport_ring_to_vector(vport, vector_id, ring_chain);
return hclge_bind_ring_with_vector(vport, vector_id, true, ring_chain);
}
static int hclge_unmap_ring_from_vector(
struct hnae3_handle *handle, int vector,
struct hnae3_ring_chain_node *ring_chain)
static int hclge_unmap_ring_frm_vector(struct hnae3_handle *handle,
int vector,
struct hnae3_ring_chain_node *ring_chain)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
struct hclge_ctrl_vector_chain_cmd *req;
struct hnae3_ring_chain_node *node;
struct hclge_desc desc;
int i, vector_id;
int ret;
int vector_id, ret;
vector_id = hclge_get_vector_index(hdev, vector);
if (vector_id < 0) {
@ -3355,54 +3350,17 @@ static int hclge_unmap_ring_from_vector(
return vector_id;
}
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_DEL_RING_TO_VECTOR, false);
req = (struct hclge_ctrl_vector_chain_cmd *)desc.data;
req->int_vector_id = vector_id;
i = 0;
for (node = ring_chain; node; node = node->next) {
u16 type_and_id = 0;
hnae_set_field(type_and_id, HCLGE_INT_TYPE_M, HCLGE_INT_TYPE_S,
hnae_get_bit(node->flag, HNAE3_RING_TYPE_B));
hnae_set_field(type_and_id, HCLGE_TQP_ID_M, HCLGE_TQP_ID_S,
node->tqp_index);
hnae_set_field(type_and_id, HCLGE_INT_GL_IDX_M,
HCLGE_INT_GL_IDX_S,
hnae_get_bit(node->flag, HNAE3_RING_TYPE_B));
req->tqp_type_and_id[i] = cpu_to_le16(type_and_id);
req->vfid = vport->vport_id;
if (++i >= HCLGE_VECTOR_ELEMENTS_PER_CMD) {
req->int_cause_num = HCLGE_VECTOR_ELEMENTS_PER_CMD;
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
dev_err(&hdev->pdev->dev,
"Unmap TQP fail, status is %d.\n",
ret);
return ret;
}
i = 0;
hclge_cmd_setup_basic_desc(&desc,
HCLGE_OPC_DEL_RING_TO_VECTOR,
false);
req->int_vector_id = vector_id;
}
ret = hclge_bind_ring_with_vector(vport, vector_id, false, ring_chain);
if (ret) {
dev_err(&handle->pdev->dev,
"Unmap ring from vector fail. vectorid=%d, ret =%d\n",
vector_id,
ret);
return ret;
}
if (i > 0) {
req->int_cause_num = i;
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
dev_err(&hdev->pdev->dev,
"Unmap TQP fail, status is %d.\n", ret);
return ret;
}
}
/* Free this MSIX or MSI vector */
hclge_free_vector(hdev, vector_id);
return 0;
}
@ -4423,7 +4381,7 @@ static int hclge_get_reset_status(struct hclge_dev *hdev, u16 queue_id)
return hnae_get_bit(req->ready_to_reset, HCLGE_TQP_RESET_B);
}
static void hclge_reset_tqp(struct hnae3_handle *handle, u16 queue_id)
void hclge_reset_tqp(struct hnae3_handle *handle, u16 queue_id)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
@ -4995,8 +4953,8 @@ static const struct hnae3_ae_ops hclge_ops = {
.uninit_ae_dev = hclge_uninit_ae_dev,
.init_client_instance = hclge_init_client_instance,
.uninit_client_instance = hclge_uninit_client_instance,
.map_ring_to_vector = hclge_map_handle_ring_to_vector,
.unmap_ring_from_vector = hclge_unmap_ring_from_vector,
.map_ring_to_vector = hclge_map_ring_to_vector,
.unmap_ring_from_vector = hclge_unmap_ring_frm_vector,
.get_vector = hclge_get_vector,
.set_promisc_mode = hclge_set_promisc_mode,
.set_loopback = hclge_set_loopback,

View file

@ -539,8 +539,10 @@ int hclge_cfg_func_mta_filter(struct hclge_dev *hdev,
u8 func_id,
bool enable);
struct hclge_vport *hclge_get_vport(struct hnae3_handle *handle);
int hclge_map_vport_ring_to_vector(struct hclge_vport *vport, int vector,
struct hnae3_ring_chain_node *ring_chain);
int hclge_bind_ring_with_vector(struct hclge_vport *vport,
int vector_id, bool en,
struct hnae3_ring_chain_node *ring_chain);
static inline int hclge_get_queue_id(struct hnae3_queue *queue)
{
struct hclge_tqp *tqp = container_of(queue, struct hclge_tqp, q);
@ -556,4 +558,5 @@ int hclge_buffer_alloc(struct hclge_dev *hdev);
int hclge_rss_init_hw(struct hclge_dev *hdev);
void hclge_mbx_handler(struct hclge_dev *hdev);
void hclge_reset_tqp(struct hnae3_handle *handle, u16 queue_id);
#endif

View file

@ -79,6 +79,91 @@ static int hclge_send_mbx_msg(struct hclge_vport *vport, u8 *msg, u16 msg_len,
return status;
}
static void hclge_free_vector_ring_chain(struct hnae3_ring_chain_node *head)
{
struct hnae3_ring_chain_node *chain_tmp, *chain;
chain = head->next;
while (chain) {
chain_tmp = chain->next;
kzfree(chain);
chain = chain_tmp;
}
}
/* hclge_get_ring_chain_from_mbx: get ring type & tqpid from mailbox message
* msg[0]: opcode
* msg[1]: <not relevant to this function>
* msg[2]: ring_num
* msg[3]: first ring type (TX|RX)
* msg[4]: first tqp id
* msg[5] ~ msg[14]: other ring type and tqp id
*/
static int hclge_get_ring_chain_from_mbx(
struct hclge_mbx_vf_to_pf_cmd *req,
struct hnae3_ring_chain_node *ring_chain,
struct hclge_vport *vport)
{
#define HCLGE_RING_NODE_VARIABLE_NUM 3
#define HCLGE_RING_MAP_MBX_BASIC_MSG_NUM 3
struct hnae3_ring_chain_node *cur_chain, *new_chain;
int ring_num;
int i;
ring_num = req->msg[2];
hnae_set_bit(ring_chain->flag, HNAE3_RING_TYPE_B, req->msg[3]);
ring_chain->tqp_index =
hclge_get_queue_id(vport->nic.kinfo.tqp[req->msg[4]]);
cur_chain = ring_chain;
for (i = 1; i < ring_num; i++) {
new_chain = kzalloc(sizeof(*new_chain), GFP_KERNEL);
if (!new_chain)
goto err;
hnae_set_bit(new_chain->flag, HNAE3_RING_TYPE_B,
req->msg[HCLGE_RING_NODE_VARIABLE_NUM * i +
HCLGE_RING_MAP_MBX_BASIC_MSG_NUM]);
new_chain->tqp_index =
hclge_get_queue_id(vport->nic.kinfo.tqp
[req->msg[HCLGE_RING_NODE_VARIABLE_NUM * i +
HCLGE_RING_MAP_MBX_BASIC_MSG_NUM + 1]]);
cur_chain->next = new_chain;
cur_chain = new_chain;
}
return 0;
err:
hclge_free_vector_ring_chain(ring_chain);
return -ENOMEM;
}
static int hclge_map_unmap_ring_to_vf_vector(struct hclge_vport *vport, bool en,
struct hclge_mbx_vf_to_pf_cmd *req)
{
struct hnae3_ring_chain_node ring_chain;
int vector_id = req->msg[1];
int ret;
memset(&ring_chain, 0, sizeof(ring_chain));
ret = hclge_get_ring_chain_from_mbx(req, &ring_chain, vport);
if (ret)
return ret;
ret = hclge_bind_ring_with_vector(vport, vector_id, en, &ring_chain);
if (ret)
return ret;
hclge_free_vector_ring_chain(&ring_chain);
return 0;
}
static int hclge_set_vf_promisc_mode(struct hclge_vport *vport,
struct hclge_mbx_vf_to_pf_cmd *req)
{
@ -224,6 +309,16 @@ static int hclge_get_link_info(struct hclge_vport *vport,
HCLGE_MBX_LINK_STAT_CHANGE, dest_vfid);
}
static void hclge_reset_vf_queue(struct hclge_vport *vport,
struct hclge_mbx_vf_to_pf_cmd *mbx_req)
{
u16 queue_id;
memcpy(&queue_id, &mbx_req->msg[2], sizeof(queue_id));
hclge_reset_tqp(&vport->nic, queue_id);
}
void hclge_mbx_handler(struct hclge_dev *hdev)
{
struct hclge_cmq_ring *crq = &hdev->hw.cmq.crq;
@ -241,6 +336,14 @@ void hclge_mbx_handler(struct hclge_dev *hdev)
vport = &hdev->vport[req->mbx_src_vfid];
switch (req->msg[0]) {
case HCLGE_MBX_MAP_RING_TO_VECTOR:
ret = hclge_map_unmap_ring_to_vf_vector(vport, true,
req);
break;
case HCLGE_MBX_UNMAP_RING_TO_VECTOR:
ret = hclge_map_unmap_ring_to_vf_vector(vport, false,
req);
break;
case HCLGE_MBX_SET_PROMISC_MODE:
ret = hclge_set_vf_promisc_mode(vport, req);
if (ret)
@ -290,6 +393,9 @@ void hclge_mbx_handler(struct hclge_dev *hdev)
"PF fail(%d) to get link stat for VF\n",
ret);
break;
case HCLGE_MBX_QUEUE_RESET:
hclge_reset_vf_queue(vport, req);
break;
default:
dev_err(&hdev->pdev->dev,
"un-supported mailbox message, code = %d\n",