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