diff options
Diffstat (limited to 'drivers/infiniband/hw/bnxt_re/qplib_fp.c')
-rw-r--r-- | drivers/infiniband/hw/bnxt_re/qplib_fp.c | 384 |
1 files changed, 199 insertions, 185 deletions
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c index 43d08b5e9085..f05500bcdcf1 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c | |||
@@ -284,7 +284,7 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) | |||
284 | { | 284 | { |
285 | struct bnxt_qplib_rcfw *rcfw = res->rcfw; | 285 | struct bnxt_qplib_rcfw *rcfw = res->rcfw; |
286 | struct cmdq_create_qp1 req; | 286 | struct cmdq_create_qp1 req; |
287 | struct creq_create_qp1_resp *resp; | 287 | struct creq_create_qp1_resp resp; |
288 | struct bnxt_qplib_pbl *pbl; | 288 | struct bnxt_qplib_pbl *pbl; |
289 | struct bnxt_qplib_q *sq = &qp->sq; | 289 | struct bnxt_qplib_q *sq = &qp->sq; |
290 | struct bnxt_qplib_q *rq = &qp->rq; | 290 | struct bnxt_qplib_q *rq = &qp->rq; |
@@ -394,31 +394,12 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) | |||
394 | 394 | ||
395 | req.pd_id = cpu_to_le32(qp->pd->id); | 395 | req.pd_id = cpu_to_le32(qp->pd->id); |
396 | 396 | ||
397 | resp = (struct creq_create_qp1_resp *) | 397 | rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, |
398 | bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, | 398 | (void *)&resp, NULL, 0); |
399 | NULL, 0); | 399 | if (rc) |
400 | if (!resp) { | ||
401 | dev_err(&res->pdev->dev, "QPLIB: FP: CREATE_QP1 send failed"); | ||
402 | rc = -EINVAL; | ||
403 | goto fail; | ||
404 | } | ||
405 | if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) { | ||
406 | /* Cmd timed out */ | ||
407 | dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_QP1 timed out"); | ||
408 | rc = -ETIMEDOUT; | ||
409 | goto fail; | ||
410 | } | ||
411 | if (resp->status || | ||
412 | le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) { | ||
413 | dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_QP1 failed "); | ||
414 | dev_err(&rcfw->pdev->dev, | ||
415 | "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x", | ||
416 | resp->status, le16_to_cpu(req.cookie), | ||
417 | le16_to_cpu(resp->cookie)); | ||
418 | rc = -EINVAL; | ||
419 | goto fail; | 400 | goto fail; |
420 | } | 401 | |
421 | qp->id = le32_to_cpu(resp->xid); | 402 | qp->id = le32_to_cpu(resp.xid); |
422 | qp->cur_qp_state = CMDQ_MODIFY_QP_NEW_STATE_RESET; | 403 | qp->cur_qp_state = CMDQ_MODIFY_QP_NEW_STATE_RESET; |
423 | sq->flush_in_progress = false; | 404 | sq->flush_in_progress = false; |
424 | rq->flush_in_progress = false; | 405 | rq->flush_in_progress = false; |
@@ -442,7 +423,7 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) | |||
442 | struct bnxt_qplib_rcfw *rcfw = res->rcfw; | 423 | struct bnxt_qplib_rcfw *rcfw = res->rcfw; |
443 | struct sq_send *hw_sq_send_hdr, **hw_sq_send_ptr; | 424 | struct sq_send *hw_sq_send_hdr, **hw_sq_send_ptr; |
444 | struct cmdq_create_qp req; | 425 | struct cmdq_create_qp req; |
445 | struct creq_create_qp_resp *resp; | 426 | struct creq_create_qp_resp resp; |
446 | struct bnxt_qplib_pbl *pbl; | 427 | struct bnxt_qplib_pbl *pbl; |
447 | struct sq_psn_search **psn_search_ptr; | 428 | struct sq_psn_search **psn_search_ptr; |
448 | unsigned long int psn_search, poff = 0; | 429 | unsigned long int psn_search, poff = 0; |
@@ -627,31 +608,12 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) | |||
627 | } | 608 | } |
628 | req.pd_id = cpu_to_le32(qp->pd->id); | 609 | req.pd_id = cpu_to_le32(qp->pd->id); |
629 | 610 | ||
630 | resp = (struct creq_create_qp_resp *) | 611 | rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, |
631 | bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, | 612 | (void *)&resp, NULL, 0); |
632 | NULL, 0); | 613 | if (rc) |
633 | if (!resp) { | ||
634 | dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_QP send failed"); | ||
635 | rc = -EINVAL; | ||
636 | goto fail; | ||
637 | } | ||
638 | if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) { | ||
639 | /* Cmd timed out */ | ||
640 | dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_QP timed out"); | ||
641 | rc = -ETIMEDOUT; | ||
642 | goto fail; | ||
643 | } | ||
644 | if (resp->status || | ||
645 | le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) { | ||
646 | dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_QP failed "); | ||
647 | dev_err(&rcfw->pdev->dev, | ||
648 | "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x", | ||
649 | resp->status, le16_to_cpu(req.cookie), | ||
650 | le16_to_cpu(resp->cookie)); | ||
651 | rc = -EINVAL; | ||
652 | goto fail; | 614 | goto fail; |
653 | } | 615 | |
654 | qp->id = le32_to_cpu(resp->xid); | 616 | qp->id = le32_to_cpu(resp.xid); |
655 | qp->cur_qp_state = CMDQ_MODIFY_QP_NEW_STATE_RESET; | 617 | qp->cur_qp_state = CMDQ_MODIFY_QP_NEW_STATE_RESET; |
656 | sq->flush_in_progress = false; | 618 | sq->flush_in_progress = false; |
657 | rq->flush_in_progress = false; | 619 | rq->flush_in_progress = false; |
@@ -769,10 +731,11 @@ int bnxt_qplib_modify_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) | |||
769 | { | 731 | { |
770 | struct bnxt_qplib_rcfw *rcfw = res->rcfw; | 732 | struct bnxt_qplib_rcfw *rcfw = res->rcfw; |
771 | struct cmdq_modify_qp req; | 733 | struct cmdq_modify_qp req; |
772 | struct creq_modify_qp_resp *resp; | 734 | struct creq_modify_qp_resp resp; |
773 | u16 cmd_flags = 0, pkey; | 735 | u16 cmd_flags = 0, pkey; |
774 | u32 temp32[4]; | 736 | u32 temp32[4]; |
775 | u32 bmask; | 737 | u32 bmask; |
738 | int rc; | ||
776 | 739 | ||
777 | RCFW_CMD_PREP(req, MODIFY_QP, cmd_flags); | 740 | RCFW_CMD_PREP(req, MODIFY_QP, cmd_flags); |
778 | 741 | ||
@@ -862,27 +825,10 @@ int bnxt_qplib_modify_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) | |||
862 | 825 | ||
863 | req.vlan_pcp_vlan_dei_vlan_id = cpu_to_le16(qp->vlan_id); | 826 | req.vlan_pcp_vlan_dei_vlan_id = cpu_to_le16(qp->vlan_id); |
864 | 827 | ||
865 | resp = (struct creq_modify_qp_resp *) | 828 | rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, |
866 | bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, | 829 | (void *)&resp, NULL, 0); |
867 | NULL, 0); | 830 | if (rc) |
868 | if (!resp) { | 831 | return rc; |
869 | dev_err(&rcfw->pdev->dev, "QPLIB: FP: MODIFY_QP send failed"); | ||
870 | return -EINVAL; | ||
871 | } | ||
872 | if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) { | ||
873 | /* Cmd timed out */ | ||
874 | dev_err(&rcfw->pdev->dev, "QPLIB: FP: MODIFY_QP timed out"); | ||
875 | return -ETIMEDOUT; | ||
876 | } | ||
877 | if (resp->status || | ||
878 | le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) { | ||
879 | dev_err(&rcfw->pdev->dev, "QPLIB: FP: MODIFY_QP failed "); | ||
880 | dev_err(&rcfw->pdev->dev, | ||
881 | "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x", | ||
882 | resp->status, le16_to_cpu(req.cookie), | ||
883 | le16_to_cpu(resp->cookie)); | ||
884 | return -EINVAL; | ||
885 | } | ||
886 | qp->cur_qp_state = qp->state; | 832 | qp->cur_qp_state = qp->state; |
887 | return 0; | 833 | return 0; |
888 | } | 834 | } |
@@ -891,37 +837,26 @@ int bnxt_qplib_query_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) | |||
891 | { | 837 | { |
892 | struct bnxt_qplib_rcfw *rcfw = res->rcfw; | 838 | struct bnxt_qplib_rcfw *rcfw = res->rcfw; |
893 | struct cmdq_query_qp req; | 839 | struct cmdq_query_qp req; |
894 | struct creq_query_qp_resp *resp; | 840 | struct creq_query_qp_resp resp; |
841 | struct bnxt_qplib_rcfw_sbuf *sbuf; | ||
895 | struct creq_query_qp_resp_sb *sb; | 842 | struct creq_query_qp_resp_sb *sb; |
896 | u16 cmd_flags = 0; | 843 | u16 cmd_flags = 0; |
897 | u32 temp32[4]; | 844 | u32 temp32[4]; |
898 | int i; | 845 | int i, rc = 0; |
899 | 846 | ||
900 | RCFW_CMD_PREP(req, QUERY_QP, cmd_flags); | 847 | RCFW_CMD_PREP(req, QUERY_QP, cmd_flags); |
901 | 848 | ||
849 | sbuf = bnxt_qplib_rcfw_alloc_sbuf(rcfw, sizeof(*sb)); | ||
850 | if (!sbuf) | ||
851 | return -ENOMEM; | ||
852 | sb = sbuf->sb; | ||
853 | |||
902 | req.qp_cid = cpu_to_le32(qp->id); | 854 | req.qp_cid = cpu_to_le32(qp->id); |
903 | req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS; | 855 | req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS; |
904 | resp = (struct creq_query_qp_resp *) | 856 | rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, |
905 | bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, | 857 | (void *)sbuf, 0); |
906 | (void **)&sb, 0); | 858 | if (rc) |
907 | if (!resp) { | 859 | goto bail; |
908 | dev_err(&rcfw->pdev->dev, "QPLIB: FP: QUERY_QP send failed"); | ||
909 | return -EINVAL; | ||
910 | } | ||
911 | if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) { | ||
912 | /* Cmd timed out */ | ||
913 | dev_err(&rcfw->pdev->dev, "QPLIB: FP: QUERY_QP timed out"); | ||
914 | return -ETIMEDOUT; | ||
915 | } | ||
916 | if (resp->status || | ||
917 | le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) { | ||
918 | dev_err(&rcfw->pdev->dev, "QPLIB: FP: QUERY_QP failed "); | ||
919 | dev_err(&rcfw->pdev->dev, | ||
920 | "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x", | ||
921 | resp->status, le16_to_cpu(req.cookie), | ||
922 | le16_to_cpu(resp->cookie)); | ||
923 | return -EINVAL; | ||
924 | } | ||
925 | /* Extract the context from the side buffer */ | 860 | /* Extract the context from the side buffer */ |
926 | qp->state = sb->en_sqd_async_notify_state & | 861 | qp->state = sb->en_sqd_async_notify_state & |
927 | CREQ_QUERY_QP_RESP_SB_STATE_MASK; | 862 | CREQ_QUERY_QP_RESP_SB_STATE_MASK; |
@@ -976,7 +911,9 @@ int bnxt_qplib_query_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) | |||
976 | qp->dest_qpn = le32_to_cpu(sb->dest_qp_id); | 911 | qp->dest_qpn = le32_to_cpu(sb->dest_qp_id); |
977 | memcpy(qp->smac, sb->src_mac, 6); | 912 | memcpy(qp->smac, sb->src_mac, 6); |
978 | qp->vlan_id = le16_to_cpu(sb->vlan_pcp_vlan_dei_vlan_id); | 913 | qp->vlan_id = le16_to_cpu(sb->vlan_pcp_vlan_dei_vlan_id); |
979 | return 0; | 914 | bail: |
915 | bnxt_qplib_rcfw_free_sbuf(rcfw, sbuf); | ||
916 | return rc; | ||
980 | } | 917 | } |
981 | 918 | ||
982 | static void __clean_cq(struct bnxt_qplib_cq *cq, u64 qp) | 919 | static void __clean_cq(struct bnxt_qplib_cq *cq, u64 qp) |
@@ -1021,34 +958,18 @@ int bnxt_qplib_destroy_qp(struct bnxt_qplib_res *res, | |||
1021 | { | 958 | { |
1022 | struct bnxt_qplib_rcfw *rcfw = res->rcfw; | 959 | struct bnxt_qplib_rcfw *rcfw = res->rcfw; |
1023 | struct cmdq_destroy_qp req; | 960 | struct cmdq_destroy_qp req; |
1024 | struct creq_destroy_qp_resp *resp; | 961 | struct creq_destroy_qp_resp resp; |
1025 | unsigned long flags; | 962 | unsigned long flags; |
1026 | u16 cmd_flags = 0; | 963 | u16 cmd_flags = 0; |
964 | int rc; | ||
1027 | 965 | ||
1028 | RCFW_CMD_PREP(req, DESTROY_QP, cmd_flags); | 966 | RCFW_CMD_PREP(req, DESTROY_QP, cmd_flags); |
1029 | 967 | ||
1030 | req.qp_cid = cpu_to_le32(qp->id); | 968 | req.qp_cid = cpu_to_le32(qp->id); |
1031 | resp = (struct creq_destroy_qp_resp *) | 969 | rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, |
1032 | bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, | 970 | (void *)&resp, NULL, 0); |
1033 | NULL, 0); | 971 | if (rc) |
1034 | if (!resp) { | 972 | return rc; |
1035 | dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_QP send failed"); | ||
1036 | return -EINVAL; | ||
1037 | } | ||
1038 | if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) { | ||
1039 | /* Cmd timed out */ | ||
1040 | dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_QP timed out"); | ||
1041 | return -ETIMEDOUT; | ||
1042 | } | ||
1043 | if (resp->status || | ||
1044 | le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) { | ||
1045 | dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_QP failed "); | ||
1046 | dev_err(&rcfw->pdev->dev, | ||
1047 | "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x", | ||
1048 | resp->status, le16_to_cpu(req.cookie), | ||
1049 | le16_to_cpu(resp->cookie)); | ||
1050 | return -EINVAL; | ||
1051 | } | ||
1052 | 973 | ||
1053 | /* Must walk the associated CQs to nullified the QP ptr */ | 974 | /* Must walk the associated CQs to nullified the QP ptr */ |
1054 | spin_lock_irqsave(&qp->scq->hwq.lock, flags); | 975 | spin_lock_irqsave(&qp->scq->hwq.lock, flags); |
@@ -1162,8 +1083,12 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, | |||
1162 | rc = -EINVAL; | 1083 | rc = -EINVAL; |
1163 | goto done; | 1084 | goto done; |
1164 | } | 1085 | } |
1165 | if (HWQ_CMP((sq->hwq.prod + 1), &sq->hwq) == | 1086 | |
1166 | HWQ_CMP(sq->hwq.cons, &sq->hwq)) { | 1087 | if (bnxt_qplib_queue_full(sq)) { |
1088 | dev_err(&sq->hwq.pdev->dev, | ||
1089 | "QPLIB: prod = %#x cons = %#x qdepth = %#x delta = %#x", | ||
1090 | sq->hwq.prod, sq->hwq.cons, sq->hwq.max_elements, | ||
1091 | sq->q_full_delta); | ||
1167 | rc = -ENOMEM; | 1092 | rc = -ENOMEM; |
1168 | goto done; | 1093 | goto done; |
1169 | } | 1094 | } |
@@ -1373,6 +1298,9 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, | |||
1373 | } | 1298 | } |
1374 | 1299 | ||
1375 | sq->hwq.prod++; | 1300 | sq->hwq.prod++; |
1301 | |||
1302 | qp->wqe_cnt++; | ||
1303 | |||
1376 | done: | 1304 | done: |
1377 | return rc; | 1305 | return rc; |
1378 | } | 1306 | } |
@@ -1411,8 +1339,7 @@ int bnxt_qplib_post_recv(struct bnxt_qplib_qp *qp, | |||
1411 | rc = -EINVAL; | 1339 | rc = -EINVAL; |
1412 | goto done; | 1340 | goto done; |
1413 | } | 1341 | } |
1414 | if (HWQ_CMP((rq->hwq.prod + 1), &rq->hwq) == | 1342 | if (bnxt_qplib_queue_full(rq)) { |
1415 | HWQ_CMP(rq->hwq.cons, &rq->hwq)) { | ||
1416 | dev_err(&rq->hwq.pdev->dev, | 1343 | dev_err(&rq->hwq.pdev->dev, |
1417 | "QPLIB: FP: QP (0x%x) RQ is full!", qp->id); | 1344 | "QPLIB: FP: QP (0x%x) RQ is full!", qp->id); |
1418 | rc = -EINVAL; | 1345 | rc = -EINVAL; |
@@ -1483,7 +1410,7 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq) | |||
1483 | { | 1410 | { |
1484 | struct bnxt_qplib_rcfw *rcfw = res->rcfw; | 1411 | struct bnxt_qplib_rcfw *rcfw = res->rcfw; |
1485 | struct cmdq_create_cq req; | 1412 | struct cmdq_create_cq req; |
1486 | struct creq_create_cq_resp *resp; | 1413 | struct creq_create_cq_resp resp; |
1487 | struct bnxt_qplib_pbl *pbl; | 1414 | struct bnxt_qplib_pbl *pbl; |
1488 | u16 cmd_flags = 0; | 1415 | u16 cmd_flags = 0; |
1489 | int rc; | 1416 | int rc; |
@@ -1525,30 +1452,12 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq) | |||
1525 | (cq->cnq_hw_ring_id & CMDQ_CREATE_CQ_CNQ_ID_MASK) << | 1452 | (cq->cnq_hw_ring_id & CMDQ_CREATE_CQ_CNQ_ID_MASK) << |
1526 | CMDQ_CREATE_CQ_CNQ_ID_SFT); | 1453 | CMDQ_CREATE_CQ_CNQ_ID_SFT); |
1527 | 1454 | ||
1528 | resp = (struct creq_create_cq_resp *) | 1455 | rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, |
1529 | bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, | 1456 | (void *)&resp, NULL, 0); |
1530 | NULL, 0); | 1457 | if (rc) |
1531 | if (!resp) { | ||
1532 | dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_CQ send failed"); | ||
1533 | return -EINVAL; | ||
1534 | } | ||
1535 | if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) { | ||
1536 | /* Cmd timed out */ | ||
1537 | dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_CQ timed out"); | ||
1538 | rc = -ETIMEDOUT; | ||
1539 | goto fail; | ||
1540 | } | ||
1541 | if (resp->status || | ||
1542 | le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) { | ||
1543 | dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_CQ failed "); | ||
1544 | dev_err(&rcfw->pdev->dev, | ||
1545 | "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x", | ||
1546 | resp->status, le16_to_cpu(req.cookie), | ||
1547 | le16_to_cpu(resp->cookie)); | ||
1548 | rc = -EINVAL; | ||
1549 | goto fail; | 1458 | goto fail; |
1550 | } | 1459 | |
1551 | cq->id = le32_to_cpu(resp->xid); | 1460 | cq->id = le32_to_cpu(resp.xid); |
1552 | cq->dbr_base = res->dpi_tbl.dbr_bar_reg_iomem; | 1461 | cq->dbr_base = res->dpi_tbl.dbr_bar_reg_iomem; |
1553 | cq->period = BNXT_QPLIB_QUEUE_START_PERIOD; | 1462 | cq->period = BNXT_QPLIB_QUEUE_START_PERIOD; |
1554 | init_waitqueue_head(&cq->waitq); | 1463 | init_waitqueue_head(&cq->waitq); |
@@ -1566,33 +1475,17 @@ int bnxt_qplib_destroy_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq) | |||
1566 | { | 1475 | { |
1567 | struct bnxt_qplib_rcfw *rcfw = res->rcfw; | 1476 | struct bnxt_qplib_rcfw *rcfw = res->rcfw; |
1568 | struct cmdq_destroy_cq req; | 1477 | struct cmdq_destroy_cq req; |
1569 | struct creq_destroy_cq_resp *resp; | 1478 | struct creq_destroy_cq_resp resp; |
1570 | u16 cmd_flags = 0; | 1479 | u16 cmd_flags = 0; |
1480 | int rc; | ||
1571 | 1481 | ||
1572 | RCFW_CMD_PREP(req, DESTROY_CQ, cmd_flags); | 1482 | RCFW_CMD_PREP(req, DESTROY_CQ, cmd_flags); |
1573 | 1483 | ||
1574 | req.cq_cid = cpu_to_le32(cq->id); | 1484 | req.cq_cid = cpu_to_le32(cq->id); |
1575 | resp = (struct creq_destroy_cq_resp *) | 1485 | rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, |
1576 | bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, | 1486 | (void *)&resp, NULL, 0); |
1577 | NULL, 0); | 1487 | if (rc) |
1578 | if (!resp) { | 1488 | return rc; |
1579 | dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_CQ send failed"); | ||
1580 | return -EINVAL; | ||
1581 | } | ||
1582 | if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) { | ||
1583 | /* Cmd timed out */ | ||
1584 | dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_CQ timed out"); | ||
1585 | return -ETIMEDOUT; | ||
1586 | } | ||
1587 | if (resp->status || | ||
1588 | le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) { | ||
1589 | dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_CQ failed "); | ||
1590 | dev_err(&rcfw->pdev->dev, | ||
1591 | "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x", | ||
1592 | resp->status, le16_to_cpu(req.cookie), | ||
1593 | le16_to_cpu(resp->cookie)); | ||
1594 | return -EINVAL; | ||
1595 | } | ||
1596 | bnxt_qplib_free_hwq(res->pdev, &cq->hwq); | 1489 | bnxt_qplib_free_hwq(res->pdev, &cq->hwq); |
1597 | return 0; | 1490 | return 0; |
1598 | } | 1491 | } |
@@ -1664,14 +1557,113 @@ static int __flush_rq(struct bnxt_qplib_q *rq, struct bnxt_qplib_qp *qp, | |||
1664 | return rc; | 1557 | return rc; |
1665 | } | 1558 | } |
1666 | 1559 | ||
1560 | /* Note: SQE is valid from sw_sq_cons up to cqe_sq_cons (exclusive) | ||
1561 | * CQE is track from sw_cq_cons to max_element but valid only if VALID=1 | ||
1562 | */ | ||
1563 | static int do_wa9060(struct bnxt_qplib_qp *qp, struct bnxt_qplib_cq *cq, | ||
1564 | u32 cq_cons, u32 sw_sq_cons, u32 cqe_sq_cons) | ||
1565 | { | ||
1566 | struct bnxt_qplib_q *sq = &qp->sq; | ||
1567 | struct bnxt_qplib_swq *swq; | ||
1568 | u32 peek_sw_cq_cons, peek_raw_cq_cons, peek_sq_cons_idx; | ||
1569 | struct cq_base *peek_hwcqe, **peek_hw_cqe_ptr; | ||
1570 | struct cq_req *peek_req_hwcqe; | ||
1571 | struct bnxt_qplib_qp *peek_qp; | ||
1572 | struct bnxt_qplib_q *peek_sq; | ||
1573 | int i, rc = 0; | ||
1574 | |||
1575 | /* Normal mode */ | ||
1576 | /* Check for the psn_search marking before completing */ | ||
1577 | swq = &sq->swq[sw_sq_cons]; | ||
1578 | if (swq->psn_search && | ||
1579 | le32_to_cpu(swq->psn_search->flags_next_psn) & 0x80000000) { | ||
1580 | /* Unmark */ | ||
1581 | swq->psn_search->flags_next_psn = cpu_to_le32 | ||
1582 | (le32_to_cpu(swq->psn_search->flags_next_psn) | ||
1583 | & ~0x80000000); | ||
1584 | dev_dbg(&cq->hwq.pdev->dev, | ||
1585 | "FP: Process Req cq_cons=0x%x qp=0x%x sq cons sw=0x%x cqe=0x%x marked!\n", | ||
1586 | cq_cons, qp->id, sw_sq_cons, cqe_sq_cons); | ||
1587 | sq->condition = true; | ||
1588 | sq->send_phantom = true; | ||
1589 | |||
1590 | /* TODO: Only ARM if the previous SQE is ARMALL */ | ||
1591 | bnxt_qplib_arm_cq(cq, DBR_DBR_TYPE_CQ_ARMALL); | ||
1592 | |||
1593 | rc = -EAGAIN; | ||
1594 | goto out; | ||
1595 | } | ||
1596 | if (sq->condition) { | ||
1597 | /* Peek at the completions */ | ||
1598 | peek_raw_cq_cons = cq->hwq.cons; | ||
1599 | peek_sw_cq_cons = cq_cons; | ||
1600 | i = cq->hwq.max_elements; | ||
1601 | while (i--) { | ||
1602 | peek_sw_cq_cons = HWQ_CMP((peek_sw_cq_cons), &cq->hwq); | ||
1603 | peek_hw_cqe_ptr = (struct cq_base **)cq->hwq.pbl_ptr; | ||
1604 | peek_hwcqe = &peek_hw_cqe_ptr[CQE_PG(peek_sw_cq_cons)] | ||
1605 | [CQE_IDX(peek_sw_cq_cons)]; | ||
1606 | /* If the next hwcqe is VALID */ | ||
1607 | if (CQE_CMP_VALID(peek_hwcqe, peek_raw_cq_cons, | ||
1608 | cq->hwq.max_elements)) { | ||
1609 | /* If the next hwcqe is a REQ */ | ||
1610 | if ((peek_hwcqe->cqe_type_toggle & | ||
1611 | CQ_BASE_CQE_TYPE_MASK) == | ||
1612 | CQ_BASE_CQE_TYPE_REQ) { | ||
1613 | peek_req_hwcqe = (struct cq_req *) | ||
1614 | peek_hwcqe; | ||
1615 | peek_qp = (struct bnxt_qplib_qp *) | ||
1616 | ((unsigned long) | ||
1617 | le64_to_cpu | ||
1618 | (peek_req_hwcqe->qp_handle)); | ||
1619 | peek_sq = &peek_qp->sq; | ||
1620 | peek_sq_cons_idx = HWQ_CMP(le16_to_cpu( | ||
1621 | peek_req_hwcqe->sq_cons_idx) - 1 | ||
1622 | , &sq->hwq); | ||
1623 | /* If the hwcqe's sq's wr_id matches */ | ||
1624 | if (peek_sq == sq && | ||
1625 | sq->swq[peek_sq_cons_idx].wr_id == | ||
1626 | BNXT_QPLIB_FENCE_WRID) { | ||
1627 | /* | ||
1628 | * Unbreak only if the phantom | ||
1629 | * comes back | ||
1630 | */ | ||
1631 | dev_dbg(&cq->hwq.pdev->dev, | ||
1632 | "FP:Got Phantom CQE"); | ||
1633 | sq->condition = false; | ||
1634 | sq->single = true; | ||
1635 | rc = 0; | ||
1636 | goto out; | ||
1637 | } | ||
1638 | } | ||
1639 | /* Valid but not the phantom, so keep looping */ | ||
1640 | } else { | ||
1641 | /* Not valid yet, just exit and wait */ | ||
1642 | rc = -EINVAL; | ||
1643 | goto out; | ||
1644 | } | ||
1645 | peek_sw_cq_cons++; | ||
1646 | peek_raw_cq_cons++; | ||
1647 | } | ||
1648 | dev_err(&cq->hwq.pdev->dev, | ||
1649 | "Should not have come here! cq_cons=0x%x qp=0x%x sq cons sw=0x%x hw=0x%x", | ||
1650 | cq_cons, qp->id, sw_sq_cons, cqe_sq_cons); | ||
1651 | rc = -EINVAL; | ||
1652 | } | ||
1653 | out: | ||
1654 | return rc; | ||
1655 | } | ||
1656 | |||
1667 | static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq, | 1657 | static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq, |
1668 | struct cq_req *hwcqe, | 1658 | struct cq_req *hwcqe, |
1669 | struct bnxt_qplib_cqe **pcqe, int *budget) | 1659 | struct bnxt_qplib_cqe **pcqe, int *budget, |
1660 | u32 cq_cons, struct bnxt_qplib_qp **lib_qp) | ||
1670 | { | 1661 | { |
1671 | struct bnxt_qplib_qp *qp; | 1662 | struct bnxt_qplib_qp *qp; |
1672 | struct bnxt_qplib_q *sq; | 1663 | struct bnxt_qplib_q *sq; |
1673 | struct bnxt_qplib_cqe *cqe; | 1664 | struct bnxt_qplib_cqe *cqe; |
1674 | u32 sw_cons, cqe_cons; | 1665 | u32 sw_sq_cons, cqe_sq_cons; |
1666 | struct bnxt_qplib_swq *swq; | ||
1675 | int rc = 0; | 1667 | int rc = 0; |
1676 | 1668 | ||
1677 | qp = (struct bnxt_qplib_qp *)((unsigned long) | 1669 | qp = (struct bnxt_qplib_qp *)((unsigned long) |
@@ -1683,13 +1675,13 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq, | |||
1683 | } | 1675 | } |
1684 | sq = &qp->sq; | 1676 | sq = &qp->sq; |
1685 | 1677 | ||
1686 | cqe_cons = HWQ_CMP(le16_to_cpu(hwcqe->sq_cons_idx), &sq->hwq); | 1678 | cqe_sq_cons = HWQ_CMP(le16_to_cpu(hwcqe->sq_cons_idx), &sq->hwq); |
1687 | if (cqe_cons > sq->hwq.max_elements) { | 1679 | if (cqe_sq_cons > sq->hwq.max_elements) { |
1688 | dev_err(&cq->hwq.pdev->dev, | 1680 | dev_err(&cq->hwq.pdev->dev, |
1689 | "QPLIB: FP: CQ Process req reported "); | 1681 | "QPLIB: FP: CQ Process req reported "); |
1690 | dev_err(&cq->hwq.pdev->dev, | 1682 | dev_err(&cq->hwq.pdev->dev, |
1691 | "QPLIB: sq_cons_idx 0x%x which exceeded max 0x%x", | 1683 | "QPLIB: sq_cons_idx 0x%x which exceeded max 0x%x", |
1692 | cqe_cons, sq->hwq.max_elements); | 1684 | cqe_sq_cons, sq->hwq.max_elements); |
1693 | return -EINVAL; | 1685 | return -EINVAL; |
1694 | } | 1686 | } |
1695 | /* If we were in the middle of flushing the SQ, continue */ | 1687 | /* If we were in the middle of flushing the SQ, continue */ |
@@ -1698,53 +1690,74 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq, | |||
1698 | 1690 | ||
1699 | /* Require to walk the sq's swq to fabricate CQEs for all previously | 1691 | /* Require to walk the sq's swq to fabricate CQEs for all previously |
1700 | * signaled SWQEs due to CQE aggregation from the current sq cons | 1692 | * signaled SWQEs due to CQE aggregation from the current sq cons |
1701 | * to the cqe_cons | 1693 | * to the cqe_sq_cons |
1702 | */ | 1694 | */ |
1703 | cqe = *pcqe; | 1695 | cqe = *pcqe; |
1704 | while (*budget) { | 1696 | while (*budget) { |
1705 | sw_cons = HWQ_CMP(sq->hwq.cons, &sq->hwq); | 1697 | sw_sq_cons = HWQ_CMP(sq->hwq.cons, &sq->hwq); |
1706 | if (sw_cons == cqe_cons) | 1698 | if (sw_sq_cons == cqe_sq_cons) |
1699 | /* Done */ | ||
1707 | break; | 1700 | break; |
1701 | |||
1702 | swq = &sq->swq[sw_sq_cons]; | ||
1708 | memset(cqe, 0, sizeof(*cqe)); | 1703 | memset(cqe, 0, sizeof(*cqe)); |
1709 | cqe->opcode = CQ_BASE_CQE_TYPE_REQ; | 1704 | cqe->opcode = CQ_BASE_CQE_TYPE_REQ; |
1710 | cqe->qp_handle = (u64)(unsigned long)qp; | 1705 | cqe->qp_handle = (u64)(unsigned long)qp; |
1711 | cqe->src_qp = qp->id; | 1706 | cqe->src_qp = qp->id; |
1712 | cqe->wr_id = sq->swq[sw_cons].wr_id; | 1707 | cqe->wr_id = swq->wr_id; |
1713 | cqe->type = sq->swq[sw_cons].type; | 1708 | if (cqe->wr_id == BNXT_QPLIB_FENCE_WRID) |
1709 | goto skip; | ||
1710 | cqe->type = swq->type; | ||
1714 | 1711 | ||
1715 | /* For the last CQE, check for status. For errors, regardless | 1712 | /* For the last CQE, check for status. For errors, regardless |
1716 | * of the request being signaled or not, it must complete with | 1713 | * of the request being signaled or not, it must complete with |
1717 | * the hwcqe error status | 1714 | * the hwcqe error status |
1718 | */ | 1715 | */ |
1719 | if (HWQ_CMP((sw_cons + 1), &sq->hwq) == cqe_cons && | 1716 | if (HWQ_CMP((sw_sq_cons + 1), &sq->hwq) == cqe_sq_cons && |
1720 | hwcqe->status != CQ_REQ_STATUS_OK) { | 1717 | hwcqe->status != CQ_REQ_STATUS_OK) { |
1721 | cqe->status = hwcqe->status; | 1718 | cqe->status = hwcqe->status; |
1722 | dev_err(&cq->hwq.pdev->dev, | 1719 | dev_err(&cq->hwq.pdev->dev, |
1723 | "QPLIB: FP: CQ Processed Req "); | 1720 | "QPLIB: FP: CQ Processed Req "); |
1724 | dev_err(&cq->hwq.pdev->dev, | 1721 | dev_err(&cq->hwq.pdev->dev, |
1725 | "QPLIB: wr_id[%d] = 0x%llx with status 0x%x", | 1722 | "QPLIB: wr_id[%d] = 0x%llx with status 0x%x", |
1726 | sw_cons, cqe->wr_id, cqe->status); | 1723 | sw_sq_cons, cqe->wr_id, cqe->status); |
1727 | cqe++; | 1724 | cqe++; |
1728 | (*budget)--; | 1725 | (*budget)--; |
1729 | sq->flush_in_progress = true; | 1726 | sq->flush_in_progress = true; |
1730 | /* Must block new posting of SQ and RQ */ | 1727 | /* Must block new posting of SQ and RQ */ |
1731 | qp->state = CMDQ_MODIFY_QP_NEW_STATE_ERR; | 1728 | qp->state = CMDQ_MODIFY_QP_NEW_STATE_ERR; |
1729 | sq->condition = false; | ||
1730 | sq->single = false; | ||
1732 | } else { | 1731 | } else { |
1733 | if (sq->swq[sw_cons].flags & | 1732 | if (swq->flags & SQ_SEND_FLAGS_SIGNAL_COMP) { |
1734 | SQ_SEND_FLAGS_SIGNAL_COMP) { | 1733 | /* Before we complete, do WA 9060 */ |
1734 | if (do_wa9060(qp, cq, cq_cons, sw_sq_cons, | ||
1735 | cqe_sq_cons)) { | ||
1736 | *lib_qp = qp; | ||
1737 | goto out; | ||
1738 | } | ||
1735 | cqe->status = CQ_REQ_STATUS_OK; | 1739 | cqe->status = CQ_REQ_STATUS_OK; |
1736 | cqe++; | 1740 | cqe++; |
1737 | (*budget)--; | 1741 | (*budget)--; |
1738 | } | 1742 | } |
1739 | } | 1743 | } |
1744 | skip: | ||
1740 | sq->hwq.cons++; | 1745 | sq->hwq.cons++; |
1746 | if (sq->single) | ||
1747 | break; | ||
1741 | } | 1748 | } |
1749 | out: | ||
1742 | *pcqe = cqe; | 1750 | *pcqe = cqe; |
1743 | if (!*budget && HWQ_CMP(sq->hwq.cons, &sq->hwq) != cqe_cons) { | 1751 | if (HWQ_CMP(sq->hwq.cons, &sq->hwq) != cqe_sq_cons) { |
1744 | /* Out of budget */ | 1752 | /* Out of budget */ |
1745 | rc = -EAGAIN; | 1753 | rc = -EAGAIN; |
1746 | goto done; | 1754 | goto done; |
1747 | } | 1755 | } |
1756 | /* | ||
1757 | * Back to normal completion mode only after it has completed all of | ||
1758 | * the WC for this CQE | ||
1759 | */ | ||
1760 | sq->single = false; | ||
1748 | if (!sq->flush_in_progress) | 1761 | if (!sq->flush_in_progress) |
1749 | goto done; | 1762 | goto done; |
1750 | flush: | 1763 | flush: |
@@ -2074,7 +2087,7 @@ static int bnxt_qplib_cq_process_cutoff(struct bnxt_qplib_cq *cq, | |||
2074 | } | 2087 | } |
2075 | 2088 | ||
2076 | int bnxt_qplib_poll_cq(struct bnxt_qplib_cq *cq, struct bnxt_qplib_cqe *cqe, | 2089 | int bnxt_qplib_poll_cq(struct bnxt_qplib_cq *cq, struct bnxt_qplib_cqe *cqe, |
2077 | int num_cqes) | 2090 | int num_cqes, struct bnxt_qplib_qp **lib_qp) |
2078 | { | 2091 | { |
2079 | struct cq_base *hw_cqe, **hw_cqe_ptr; | 2092 | struct cq_base *hw_cqe, **hw_cqe_ptr; |
2080 | unsigned long flags; | 2093 | unsigned long flags; |
@@ -2099,7 +2112,8 @@ int bnxt_qplib_poll_cq(struct bnxt_qplib_cq *cq, struct bnxt_qplib_cqe *cqe, | |||
2099 | case CQ_BASE_CQE_TYPE_REQ: | 2112 | case CQ_BASE_CQE_TYPE_REQ: |
2100 | rc = bnxt_qplib_cq_process_req(cq, | 2113 | rc = bnxt_qplib_cq_process_req(cq, |
2101 | (struct cq_req *)hw_cqe, | 2114 | (struct cq_req *)hw_cqe, |
2102 | &cqe, &budget); | 2115 | &cqe, &budget, |
2116 | sw_cons, lib_qp); | ||
2103 | break; | 2117 | break; |
2104 | case CQ_BASE_CQE_TYPE_RES_RC: | 2118 | case CQ_BASE_CQE_TYPE_RES_RC: |
2105 | rc = bnxt_qplib_cq_process_res_rc(cq, | 2119 | rc = bnxt_qplib_cq_process_res_rc(cq, |