net/hinic: add device initialization
[dpdk.git] / drivers / net / hinic / hinic_pmd_rx.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2017 Huawei Technologies Co., Ltd
3  */
4
5 #include <rte_ether.h>
6 #include <rte_mbuf.h>
7
8 #include "base/hinic_compat.h"
9 #include "base/hinic_pmd_hwdev.h"
10 #include "base/hinic_pmd_wq.h"
11 #include "base/hinic_pmd_niccfg.h"
12 #include "base/hinic_pmd_nicio.h"
13 #include "hinic_pmd_ethdev.h"
14 #include "hinic_pmd_rx.h"
15
16
17 void hinic_destroy_rq(struct hinic_hwdev *hwdev, u16 q_id)
18 {
19         struct hinic_nic_io *nic_io = hwdev->nic_io;
20         struct hinic_qp *qp = &nic_io->qps[q_id];
21         struct hinic_rq *rq = &qp->rq;
22
23         if (qp->rq.wq == NULL)
24                 return;
25
26         dma_free_coherent_volatile(hwdev, HINIC_PAGE_SIZE,
27                                    (volatile void *)rq->pi_virt_addr,
28                                    rq->pi_dma_addr);
29         hinic_wq_free(nic_io->hwdev, qp->rq.wq);
30         qp->rq.wq = NULL;
31 }
32
33 static void hinic_rx_free_cqe(struct hinic_rxq *rxq)
34 {
35         size_t cqe_mem_size;
36
37         cqe_mem_size = sizeof(struct hinic_rq_cqe) * rxq->q_depth;
38         dma_free_coherent(rxq->nic_dev->hwdev, cqe_mem_size,
39                           rxq->cqe_start_vaddr, rxq->cqe_start_paddr);
40         rxq->cqe_start_vaddr = NULL;
41 }
42
43 void hinic_free_rx_resources(struct hinic_rxq *rxq)
44 {
45         if (rxq->rx_info == NULL)
46                 return;
47
48         hinic_rx_free_cqe(rxq);
49         kfree(rxq->rx_info);
50         rxq->rx_info = NULL;
51 }
52
53 void hinic_free_all_rx_resources(struct rte_eth_dev *eth_dev)
54 {
55         u16 q_id;
56         struct hinic_nic_dev *nic_dev =
57                                 HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
58
59         for (q_id = 0; q_id < nic_dev->num_rq; q_id++) {
60                 eth_dev->data->rx_queues[q_id] = NULL;
61
62                 if (nic_dev->rxqs[q_id] == NULL)
63                         continue;
64
65                 hinic_free_all_rx_skbs(nic_dev->rxqs[q_id]);
66                 hinic_free_rx_resources(nic_dev->rxqs[q_id]);
67                 kfree(nic_dev->rxqs[q_id]);
68                 nic_dev->rxqs[q_id] = NULL;
69         }
70 }
71
72 static void
73 hinic_add_rq_to_rx_queue_list(struct hinic_nic_dev *nic_dev, u16 queue_id)
74 {
75         u8 rss_queue_count = nic_dev->num_rss;
76
77         RTE_ASSERT(rss_queue_count <= (RTE_DIM(nic_dev->rx_queue_list) - 1));
78
79         nic_dev->rx_queue_list[rss_queue_count] = queue_id;
80         nic_dev->num_rss++;
81 }
82
83 /**
84  * hinic_setup_num_qps - determine num_qps from rss_tmpl_id
85  * @nic_dev: pointer to the private ethernet device
86  * Return: 0 on Success, error code otherwise.
87  **/
88 static int hinic_setup_num_qps(struct hinic_nic_dev *nic_dev)
89 {
90         int err, i;
91
92         if (!(nic_dev->flags & ETH_MQ_RX_RSS_FLAG)) {
93                 nic_dev->flags &= ~ETH_MQ_RX_RSS_FLAG;
94                 nic_dev->num_rss = 0;
95                 if (nic_dev->num_rq > 1) {
96                         /* get rss template id */
97                         err = hinic_rss_template_alloc(nic_dev->hwdev,
98                                                        &nic_dev->rss_tmpl_idx);
99                         if (err) {
100                                 PMD_DRV_LOG(WARNING, "Alloc rss template failed");
101                                 return err;
102                         }
103                         nic_dev->flags |= ETH_MQ_RX_RSS_FLAG;
104                         for (i = 0; i < nic_dev->num_rq; i++)
105                                 hinic_add_rq_to_rx_queue_list(nic_dev, i);
106                 }
107         }
108
109         return 0;
110 }
111
112 static void hinic_destroy_num_qps(struct hinic_nic_dev *nic_dev)
113 {
114         if (nic_dev->flags & ETH_MQ_RX_RSS_FLAG) {
115                 if (hinic_rss_template_free(nic_dev->hwdev,
116                                             nic_dev->rss_tmpl_idx))
117                         PMD_DRV_LOG(WARNING, "Free rss template failed");
118
119                 nic_dev->flags &= ~ETH_MQ_RX_RSS_FLAG;
120         }
121 }
122
123 static int hinic_config_mq_rx_rss(struct hinic_nic_dev *nic_dev, bool on)
124 {
125         int ret = 0;
126
127         if (on) {
128                 ret = hinic_setup_num_qps(nic_dev);
129                 if (ret)
130                         PMD_DRV_LOG(ERR, "Setup num_qps failed");
131         } else {
132                 hinic_destroy_num_qps(nic_dev);
133         }
134
135         return ret;
136 }
137
138 int hinic_config_mq_mode(struct rte_eth_dev *dev, bool on)
139 {
140         struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
141         struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
142         int ret = 0;
143
144         switch (dev_conf->rxmode.mq_mode) {
145         case ETH_MQ_RX_RSS:
146                 ret = hinic_config_mq_rx_rss(nic_dev, on);
147                 break;
148         default:
149                 break;
150         }
151
152         return ret;
153 }
154
155 void hinic_free_all_rx_skbs(struct hinic_rxq *rxq)
156 {
157         struct hinic_nic_dev *nic_dev = rxq->nic_dev;
158         struct hinic_rx_info *rx_info;
159         int free_wqebbs =
160                 hinic_get_rq_free_wqebbs(nic_dev->hwdev, rxq->q_id) + 1;
161         volatile struct hinic_rq_cqe *rx_cqe;
162         u16 ci;
163
164         while (free_wqebbs++ < rxq->q_depth) {
165                 ci = hinic_get_rq_local_ci(nic_dev->hwdev, rxq->q_id);
166
167                 rx_cqe = &rxq->rx_cqe[ci];
168
169                 /* clear done bit */
170                 rx_cqe->status = 0;
171
172                 rx_info = &rxq->rx_info[ci];
173                 rte_pktmbuf_free(rx_info->mbuf);
174                 rx_info->mbuf = NULL;
175
176                 hinic_update_rq_local_ci(nic_dev->hwdev, rxq->q_id, 1);
177         }
178 }