net/hinic: add start/stop and queue ops
[dpdk.git] / drivers / net / hinic / hinic_pmd_tx.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2017 Huawei Technologies Co., Ltd
3  */
4
5 #include <rte_mbuf.h>
6 #include <rte_tcp.h>
7 #include <rte_sctp.h>
8 #include <rte_udp.h>
9 #include <rte_ip.h>
10
11 #include "base/hinic_compat.h"
12 #include "base/hinic_pmd_hwdev.h"
13 #include "base/hinic_pmd_hwif.h"
14 #include "base/hinic_pmd_wq.h"
15 #include "base/hinic_pmd_nicio.h"
16 #include "hinic_pmd_ethdev.h"
17 #include "hinic_pmd_tx.h"
18
19
20 void hinic_free_all_tx_skbs(struct hinic_txq *txq)
21 {
22         u16 ci;
23         struct hinic_nic_dev *nic_dev = txq->nic_dev;
24         struct hinic_tx_info *tx_info;
25         int free_wqebbs = hinic_get_sq_free_wqebbs(nic_dev->hwdev,
26                                                    txq->q_id) + 1;
27
28         while (free_wqebbs < txq->q_depth) {
29                 ci = hinic_get_sq_local_ci(nic_dev->hwdev, txq->q_id);
30
31                 tx_info = &txq->tx_info[ci];
32
33                 if (unlikely(tx_info->cpy_mbuf != NULL)) {
34                         rte_pktmbuf_free(tx_info->cpy_mbuf);
35                         tx_info->cpy_mbuf = NULL;
36                 }
37
38                 rte_pktmbuf_free(tx_info->mbuf);
39                 hinic_update_sq_local_ci(nic_dev->hwdev, txq->q_id,
40                                          tx_info->wqebb_cnt);
41
42                 free_wqebbs += tx_info->wqebb_cnt;
43                 tx_info->mbuf = NULL;
44         }
45 }
46
47 void hinic_free_all_tx_resources(struct rte_eth_dev *eth_dev)
48 {
49         u16 q_id;
50         struct hinic_nic_dev *nic_dev =
51                                 HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
52
53         for (q_id = 0; q_id < nic_dev->num_sq; q_id++) {
54                 eth_dev->data->tx_queues[q_id] = NULL;
55
56                 if (nic_dev->txqs[q_id] == NULL)
57                         continue;
58
59                 /* stop tx queue free tx mbuf */
60                 hinic_free_all_tx_skbs(nic_dev->txqs[q_id]);
61                 hinic_free_tx_resources(nic_dev->txqs[q_id]);
62
63                 /* free txq */
64                 kfree(nic_dev->txqs[q_id]);
65                 nic_dev->txqs[q_id] = NULL;
66         }
67 }
68
69 void hinic_free_all_tx_mbuf(struct rte_eth_dev *eth_dev)
70 {
71         u16 q_id;
72         struct hinic_nic_dev *nic_dev =
73                                 HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
74
75         for (q_id = 0; q_id < nic_dev->num_sq; q_id++)
76                 /* stop tx queue free tx mbuf */
77                 hinic_free_all_tx_skbs(nic_dev->txqs[q_id]);
78 }
79
80 int hinic_setup_tx_resources(struct hinic_txq *txq)
81 {
82         u64 tx_info_sz;
83
84         tx_info_sz = txq->q_depth * sizeof(*txq->tx_info);
85         txq->tx_info = kzalloc_aligned(tx_info_sz, GFP_KERNEL);
86         if (!txq->tx_info)
87                 return -ENOMEM;
88
89         return HINIC_OK;
90 }
91
92 void hinic_free_tx_resources(struct hinic_txq *txq)
93 {
94         if (txq->tx_info == NULL)
95                 return;
96
97         kfree(txq->tx_info);
98         txq->tx_info = NULL;
99 }
100
101 int hinic_create_sq(struct hinic_hwdev *hwdev, u16 q_id, u16 sq_depth)
102 {
103         int err;
104         struct hinic_nic_io *nic_io = hwdev->nic_io;
105         struct hinic_qp *qp = &nic_io->qps[q_id];
106         struct hinic_sq *sq = &qp->sq;
107         void __iomem *db_addr;
108         volatile u32 *ci_addr;
109
110         sq->sq_depth = sq_depth;
111         nic_io->sq_depth = sq_depth;
112
113         /* alloc wq */
114         err = hinic_wq_allocate(nic_io->hwdev, &nic_io->sq_wq[q_id],
115                                 HINIC_SQ_WQEBB_SHIFT, nic_io->sq_depth);
116         if (err) {
117                 PMD_DRV_LOG(ERR, "Failed to allocate WQ for SQ");
118                 return err;
119         }
120
121         /* alloc sq doorbell space */
122         err = hinic_alloc_db_addr(nic_io->hwdev, &db_addr);
123         if (err) {
124                 PMD_DRV_LOG(ERR, "Failed to init db addr");
125                 goto alloc_db_err;
126         }
127
128         /* clear hardware ci */
129         ci_addr = (volatile u32 *)HINIC_CI_VADDR(nic_io->ci_vaddr_base, q_id);
130         *ci_addr = 0;
131
132         sq->q_id = q_id;
133         sq->wq = &nic_io->sq_wq[q_id];
134         sq->owner = 1;
135         sq->cons_idx_addr = (volatile u16 *)ci_addr;
136         sq->db_addr = db_addr;
137
138         return HINIC_OK;
139
140 alloc_db_err:
141         hinic_wq_free(nic_io->hwdev, &nic_io->sq_wq[q_id]);
142
143         return err;
144 }
145
146 void hinic_destroy_sq(struct hinic_hwdev *hwdev, u16 q_id)
147 {
148         struct hinic_nic_io *nic_io;
149         struct hinic_qp *qp;
150
151         nic_io = hwdev->nic_io;
152         qp = &nic_io->qps[q_id];
153
154         if (qp->sq.wq == NULL)
155                 return;
156
157         hinic_free_db_addr(nic_io->hwdev, qp->sq.db_addr);
158         hinic_wq_free(nic_io->hwdev, qp->sq.wq);
159         qp->sq.wq = NULL;
160 }