Merge tag 'wireless-next-2023-11-27' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-block.git] / drivers / scsi / snic / snic_res.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright 2014 Cisco Systems, Inc.  All rights reserved.
3
4 #include <linux/errno.h>
5 #include <linux/types.h>
6 #include <linux/pci.h>
7
8 #include "wq_enet_desc.h"
9 #include "cq_enet_desc.h"
10 #include "vnic_resource.h"
11 #include "vnic_dev.h"
12 #include "vnic_wq.h"
13 #include "vnic_cq.h"
14 #include "vnic_intr.h"
15 #include "vnic_stats.h"
16 #include "snic.h"
17
18 int
19 snic_get_vnic_config(struct snic *snic)
20 {
21         struct vnic_snic_config *c = &snic->config;
22         int ret;
23
24 #define GET_CONFIG(m) \
25         do { \
26                 ret = svnic_dev_spec(snic->vdev, \
27                                      offsetof(struct vnic_snic_config, m), \
28                                      sizeof(c->m), \
29                                      &c->m); \
30                 if (ret) { \
31                         SNIC_HOST_ERR(snic->shost, \
32                                       "Error getting %s, %d\n", #m, ret); \
33                         return ret; \
34                 } \
35         } while (0)
36
37         GET_CONFIG(wq_enet_desc_count);
38         GET_CONFIG(maxdatafieldsize);
39         GET_CONFIG(intr_timer);
40         GET_CONFIG(intr_timer_type);
41         GET_CONFIG(flags);
42         GET_CONFIG(io_throttle_count);
43         GET_CONFIG(port_down_timeout);
44         GET_CONFIG(port_down_io_retries);
45         GET_CONFIG(luns_per_tgt);
46         GET_CONFIG(xpt_type);
47         GET_CONFIG(hid);
48
49         c->wq_enet_desc_count = min_t(u32,
50                                       VNIC_SNIC_WQ_DESCS_MAX,
51                                       max_t(u32,
52                                             VNIC_SNIC_WQ_DESCS_MIN,
53                                             c->wq_enet_desc_count));
54
55         c->wq_enet_desc_count = ALIGN(c->wq_enet_desc_count, 16);
56
57         c->maxdatafieldsize = min_t(u32,
58                                     VNIC_SNIC_MAXDATAFIELDSIZE_MAX,
59                                     max_t(u32,
60                                           VNIC_SNIC_MAXDATAFIELDSIZE_MIN,
61                                           c->maxdatafieldsize));
62
63         c->io_throttle_count = min_t(u32,
64                                      VNIC_SNIC_IO_THROTTLE_COUNT_MAX,
65                                      max_t(u32,
66                                            VNIC_SNIC_IO_THROTTLE_COUNT_MIN,
67                                            c->io_throttle_count));
68
69         c->port_down_timeout = min_t(u32,
70                                      VNIC_SNIC_PORT_DOWN_TIMEOUT_MAX,
71                                      c->port_down_timeout);
72
73         c->port_down_io_retries = min_t(u32,
74                                      VNIC_SNIC_PORT_DOWN_IO_RETRIES_MAX,
75                                      c->port_down_io_retries);
76
77         c->luns_per_tgt = min_t(u32,
78                                 VNIC_SNIC_LUNS_PER_TARGET_MAX,
79                                 max_t(u32,
80                                       VNIC_SNIC_LUNS_PER_TARGET_MIN,
81                                       c->luns_per_tgt));
82
83         c->intr_timer = min_t(u32, VNIC_INTR_TIMER_MAX, c->intr_timer);
84
85         SNIC_INFO("vNIC resources wq %d\n", c->wq_enet_desc_count);
86         SNIC_INFO("vNIC mtu %d intr timer %d\n",
87                   c->maxdatafieldsize,
88                   c->intr_timer);
89
90         SNIC_INFO("vNIC flags 0x%x luns per tgt %d\n",
91                   c->flags,
92                   c->luns_per_tgt);
93
94         SNIC_INFO("vNIC io throttle count %d\n", c->io_throttle_count);
95         SNIC_INFO("vNIC port down timeout %d port down io retries %d\n",
96                   c->port_down_timeout,
97                   c->port_down_io_retries);
98
99         SNIC_INFO("vNIC back end type = %d\n", c->xpt_type);
100         SNIC_INFO("vNIC hid = %d\n", c->hid);
101
102         return 0;
103 }
104
105 void
106 snic_get_res_counts(struct snic *snic)
107 {
108         snic->wq_count = svnic_dev_get_res_count(snic->vdev, RES_TYPE_WQ);
109         SNIC_BUG_ON(snic->wq_count == 0);
110         snic->cq_count = svnic_dev_get_res_count(snic->vdev, RES_TYPE_CQ);
111         SNIC_BUG_ON(snic->cq_count == 0);
112         snic->intr_count = svnic_dev_get_res_count(snic->vdev,
113                                                   RES_TYPE_INTR_CTRL);
114         SNIC_BUG_ON(snic->intr_count == 0);
115 }
116
117 void
118 snic_free_vnic_res(struct snic *snic)
119 {
120         unsigned int i;
121
122         for (i = 0; i < snic->wq_count; i++)
123                 svnic_wq_free(&snic->wq[i]);
124
125         for (i = 0; i < snic->cq_count; i++)
126                 svnic_cq_free(&snic->cq[i]);
127
128         for (i = 0; i < snic->intr_count; i++)
129                 svnic_intr_free(&snic->intr[i]);
130 }
131
132 int
133 snic_alloc_vnic_res(struct snic *snic)
134 {
135         enum vnic_dev_intr_mode intr_mode;
136         unsigned int mask_on_assertion;
137         unsigned int intr_offset;
138         unsigned int err_intr_enable;
139         unsigned int err_intr_offset;
140         unsigned int i;
141         int ret;
142
143         intr_mode = svnic_dev_get_intr_mode(snic->vdev);
144
145         SNIC_INFO("vNIC interrupt mode: %s\n",
146                   ((intr_mode == VNIC_DEV_INTR_MODE_INTX) ?
147                    "Legacy PCI INTx" :
148                    ((intr_mode == VNIC_DEV_INTR_MODE_MSI) ?
149                     "MSI" :
150                     ((intr_mode == VNIC_DEV_INTR_MODE_MSIX) ?
151                      "MSI-X" : "Unknown"))));
152
153         /* only MSI-X is supported */
154         SNIC_BUG_ON(intr_mode != VNIC_DEV_INTR_MODE_MSIX);
155
156         SNIC_INFO("wq %d cq %d intr %d\n", snic->wq_count,
157                   snic->cq_count,
158                   snic->intr_count);
159
160
161         /* Allocate WQs used for SCSI IOs */
162         for (i = 0; i < snic->wq_count; i++) {
163                 ret = svnic_wq_alloc(snic->vdev,
164                                      &snic->wq[i],
165                                      i,
166                                      snic->config.wq_enet_desc_count,
167                                      sizeof(struct wq_enet_desc));
168                 if (ret)
169                         goto error_cleanup;
170         }
171
172         /* CQ for each WQ */
173         for (i = 0; i < snic->wq_count; i++) {
174                 ret = svnic_cq_alloc(snic->vdev,
175                                      &snic->cq[i],
176                                      i,
177                                      snic->config.wq_enet_desc_count,
178                                      sizeof(struct cq_enet_wq_desc));
179                 if (ret)
180                         goto error_cleanup;
181         }
182
183         SNIC_BUG_ON(snic->cq_count != 2 * snic->wq_count);
184         /* CQ for FW TO host */
185         for (i = snic->wq_count; i < snic->cq_count; i++) {
186                 ret = svnic_cq_alloc(snic->vdev,
187                                      &snic->cq[i],
188                                      i,
189                                      (snic->config.wq_enet_desc_count * 3),
190                                      sizeof(struct snic_fw_req));
191                 if (ret)
192                         goto error_cleanup;
193         }
194
195         for (i = 0; i < snic->intr_count; i++) {
196                 ret = svnic_intr_alloc(snic->vdev, &snic->intr[i], i);
197                 if (ret)
198                         goto error_cleanup;
199         }
200
201         /*
202          * Init WQ Resources.
203          * WQ[0 to n] points to CQ[0 to n-1]
204          * firmware to host comm points to CQ[n to m+1]
205          */
206         err_intr_enable = 1;
207         err_intr_offset = snic->err_intr_offset;
208
209         for (i = 0; i < snic->wq_count; i++) {
210                 svnic_wq_init(&snic->wq[i],
211                               i,
212                               err_intr_enable,
213                               err_intr_offset);
214         }
215
216         for (i = 0; i < snic->cq_count; i++) {
217                 intr_offset = i;
218
219                 svnic_cq_init(&snic->cq[i],
220                               0 /* flow_control_enable */,
221                               1 /* color_enable */,
222                               0 /* cq_head */,
223                               0 /* cq_tail */,
224                               1 /* cq_tail_color */,
225                               1 /* interrupt_enable */,
226                               1 /* cq_entry_enable */,
227                               0 /* cq_message_enable */,
228                               intr_offset,
229                               0 /* cq_message_addr */);
230         }
231
232         /*
233          * Init INTR resources
234          * Assumption : snic is always in MSI-X mode
235          */
236         SNIC_BUG_ON(intr_mode != VNIC_DEV_INTR_MODE_MSIX);
237         mask_on_assertion = 1;
238
239         for (i = 0; i < snic->intr_count; i++) {
240                 svnic_intr_init(&snic->intr[i],
241                                 snic->config.intr_timer,
242                                 snic->config.intr_timer_type,
243                                 mask_on_assertion);
244         }
245
246         /* init the stats memory by making the first call here */
247         ret = svnic_dev_stats_dump(snic->vdev, &snic->stats);
248         if (ret) {
249                 SNIC_HOST_ERR(snic->shost,
250                               "svnic_dev_stats_dump failed - x%x\n",
251                               ret);
252                 goto error_cleanup;
253         }
254
255         /* Clear LIF stats */
256         svnic_dev_stats_clear(snic->vdev);
257         ret = 0;
258
259         return ret;
260
261 error_cleanup:
262         snic_free_vnic_res(snic);
263
264         return ret;
265 }
266
267 void
268 snic_log_q_error(struct snic *snic)
269 {
270         unsigned int i;
271         u32 err_status;
272
273         for (i = 0; i < snic->wq_count; i++) {
274                 err_status = ioread32(&snic->wq[i].ctrl->error_status);
275                 if (err_status)
276                         SNIC_HOST_ERR(snic->shost,
277                                       "WQ[%d] error status %d\n",
278                                       i,
279                                       err_status);
280         }
281 } /* end of snic_log_q_error */