xref: /illumos-gate/usr/src/uts/common/io/scsi/adapters/smartpqi/smartpqi_main.c (revision 1edba515a3484e0f74b638b203d462b3112ac84d)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2023 Tintri by DDN, Inc. All rights reserved.
14  * Copyright 2021 RackTop Systems, Inc.
15  */
16 
17 /*
18  * Driver attach/detach routines are found here.
19  */
20 
21 /* ---- Private header files ---- */
22 #include <smartpqi.h>
23 
24 void	*pqi_state;
25 
26 /* ---- Autoconfigure forward declarations ---- */
27 static int smartpqi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
28 static int smartpqi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
29 static int smartpqi_quiesce(dev_info_t *dip);
30 
31 static struct cb_ops smartpqi_cb_ops = {
32 	.cb_open =		scsi_hba_open,
33 	.cb_close =		scsi_hba_close,
34 	.cb_strategy =		nodev,
35 	.cb_print =		nodev,
36 	.cb_dump =		nodev,
37 	.cb_read =		nodev,
38 	.cb_write =		nodev,
39 	.cb_ioctl =		scsi_hba_ioctl,
40 	.cb_devmap =		nodev,
41 	.cb_mmap =		nodev,
42 	.cb_segmap =		nodev,
43 	.cb_chpoll =		nochpoll,
44 	.cb_prop_op =		ddi_prop_op,
45 	.cb_str =		NULL,
46 	.cb_flag =		D_MP,
47 	.cb_rev =		CB_REV,
48 	.cb_aread =		nodev,
49 	.cb_awrite =		nodev
50 };
51 
52 static struct dev_ops smartpqi_ops = {
53 	.devo_rev =		DEVO_REV,
54 	.devo_refcnt =		0,
55 	.devo_getinfo =		nodev,
56 	.devo_identify =	nulldev,
57 	.devo_probe =		nulldev,
58 	.devo_attach =		smartpqi_attach,
59 	.devo_detach =		smartpqi_detach,
60 	.devo_reset =		nodev,
61 	.devo_cb_ops =		&smartpqi_cb_ops,
62 	.devo_bus_ops =		NULL,
63 	.devo_power =		nodev,
64 	.devo_quiesce =		smartpqi_quiesce
65 };
66 
67 static struct modldrv smartpqi_modldrv = {
68 	.drv_modops =		&mod_driverops,
69 	.drv_linkinfo =		SMARTPQI_MOD_STRING,
70 	.drv_dev_ops =		&smartpqi_ops
71 };
72 
73 static struct modlinkage smartpqi_modlinkage = {
74 	.ml_rev =		MODREV_1,
75 	.ml_linkage =		{ &smartpqi_modldrv, NULL }
76 };
77 
78 /*
79  * This is used for data I/O DMA memory allocation. (full 64-bit DMA
80  * physical addresses are supported.)
81  *
82  * We believe that the device probably doesn't have any limitations,
83  * but previous generations of this hardware used a 32-bit DMA counter.
84  * Absent better guidance, we choose the same.  (Note that the Linux
85  * driver from the vendor imposes no DMA limitations.)
86  */
87 ddi_dma_attr_t smartpqi_dma_attrs = {
88 	.dma_attr_version =	DMA_ATTR_V0,
89 	.dma_attr_addr_lo =	0x0ull,
90 	.dma_attr_addr_hi =	0xffffffffffffffffull,
91 	.dma_attr_count_max =	0x00ffffffull,
92 	.dma_attr_align =	4096,
93 	.dma_attr_burstsizes =	0x78,
94 	.dma_attr_minxfer =	1,
95 	.dma_attr_maxxfer =	0x00ffffffull,
96 	.dma_attr_seg =		0xffffffffull,
97 	.dma_attr_sgllen =	PQI_MAX_SCATTER_GATHER,
98 	.dma_attr_granular =	512,
99 	.dma_attr_flags =	0,
100 };
101 
102 ddi_device_acc_attr_t smartpqi_dev_attr = {
103 	DDI_DEVICE_ATTR_V1,
104 	DDI_STRUCTURE_LE_ACC,
105 	DDI_STRICTORDER_ACC,
106 	DDI_DEFAULT_ACC
107 };
108 
109 int
110 _init(void)
111 {
112 	int	ret;
113 
114 	if ((ret = ddi_soft_state_init(&pqi_state,
115 	    sizeof (struct pqi_state), SMARTPQI_INITIAL_SOFT_SPACE)) !=
116 	    0) {
117 		return (ret);
118 	}
119 
120 	if ((ret = scsi_hba_init(&smartpqi_modlinkage)) != 0) {
121 		ddi_soft_state_fini(&pqi_state);
122 		return (ret);
123 	}
124 
125 	if ((ret = mod_install(&smartpqi_modlinkage)) != 0) {
126 		scsi_hba_fini(&smartpqi_modlinkage);
127 		ddi_soft_state_fini(&pqi_state);
128 	}
129 
130 	return (ret);
131 }
132 
133 int
134 _fini(void)
135 {
136 	int	ret;
137 
138 	if ((ret = mod_remove(&smartpqi_modlinkage)) == 0) {
139 		scsi_hba_fini(&smartpqi_modlinkage);
140 		ddi_soft_state_fini(&pqi_state);
141 	}
142 	return (ret);
143 }
144 
145 int
146 _info(struct modinfo *modinfop)
147 {
148 	return (mod_info(&smartpqi_modlinkage, modinfop));
149 }
150 
151 static int
152 smartpqi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
153 {
154 	int		instance;
155 	pqi_state_t	*s	= NULL;
156 	int		mem_bar	= IO_SPACE;
157 	mem_len_pair_t	m;
158 
159 	switch (cmd) {
160 	case DDI_ATTACH:
161 		break;
162 
163 	case DDI_RESUME:
164 	default:
165 		return (DDI_FAILURE);
166 	}
167 
168 	instance = ddi_get_instance(dip);
169 
170 	/* ---- allocate softc structure ---- */
171 	if (ddi_soft_state_zalloc(pqi_state, instance) != DDI_SUCCESS)
172 		return (DDI_FAILURE);
173 
174 	if ((s = ddi_get_soft_state(pqi_state, instance)) == NULL)
175 		goto fail;
176 
177 	scsi_size_clean(dip);
178 
179 	s->s_dip = dip;
180 	s->s_instance = instance;
181 	s->s_intr_ready = B_FALSE;
182 	s->s_offline = B_FALSE;
183 	list_create(&s->s_devnodes, sizeof (struct pqi_device),
184 	    offsetof(struct pqi_device, pd_list));
185 	list_create(&s->s_special_device.pd_cmd_list, sizeof (struct pqi_cmd),
186 	    offsetof(struct pqi_cmd, pc_list));
187 
188 	/* ---- Initialize mutex used in interrupt handler ---- */
189 	mutex_init(&s->s_mutex, NULL, MUTEX_DRIVER,
190 	    DDI_INTR_PRI(s->s_intr_pri));
191 	mutex_init(&s->s_io_mutex, NULL, MUTEX_DRIVER, NULL);
192 	mutex_init(&s->s_intr_mutex, NULL, MUTEX_DRIVER, NULL);
193 	mutex_init(&s->s_special_device.pd_mutex, NULL, MUTEX_DRIVER, NULL);
194 	cv_init(&s->s_quiescedvar, NULL, CV_DRIVER, NULL);
195 	cv_init(&s->s_io_condvar, NULL, CV_DRIVER, NULL);
196 
197 	m = pqi_alloc_mem_len(256);
198 	(void) snprintf(m.mem, m.len, "smartpqi_cache%d", instance);
199 	s->s_cmd_cache = kmem_cache_create(m.mem, sizeof (struct pqi_cmd), 0,
200 	    pqi_cache_constructor, pqi_cache_destructor, NULL, s, NULL, 0);
201 
202 	(void) snprintf(m.mem, m.len, "pqi_events_taskq%d", instance);
203 	s->s_events_taskq = ddi_taskq_create(s->s_dip, m.mem, 1,
204 	    TASKQ_DEFAULTPRI, 0);
205 	(void) snprintf(m.mem, m.len, "pqi_complete_taskq%d", instance);
206 	s->s_complete_taskq = ddi_taskq_create(s->s_dip, m.mem, 4,
207 	    TASKQ_DEFAULTPRI, 0);
208 	pqi_free_mem_len(&m);
209 
210 	s->s_debug_level = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
211 	    DDI_PROP_DONTPASS, "debug", 0);
212 
213 	if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
214 	    "disable-mpxio", 0) != 0) {
215 		s->s_disable_mpxio = B_TRUE;
216 	}
217 	if (smartpqi_register_intrs(s) == FALSE) {
218 		dev_err(s->s_dip, CE_WARN, "unable to register interrupts");
219 		goto fail;
220 	}
221 
222 	s->s_msg_dma_attr = smartpqi_dma_attrs;
223 	s->s_reg_acc_attr = smartpqi_dev_attr;
224 
225 	if (ddi_regs_map_setup(dip, mem_bar, (caddr_t *)&s->s_reg, 0,
226 	    /* sizeof (pqi_ctrl_regs_t) */ 0x8000, &s->s_reg_acc_attr,
227 	    &s->s_datap) != DDI_SUCCESS) {
228 		dev_err(s->s_dip, CE_WARN, "map setup failed");
229 		goto fail;
230 	}
231 
232 	if (pqi_check_firmware(s) == B_FALSE) {
233 		dev_err(s->s_dip, CE_WARN, "firmware issue");
234 		goto fail;
235 	}
236 	if (pqi_prep_full(s) == B_FALSE) {
237 		goto fail;
238 	}
239 	if (smartpqi_register_hba(s) == FALSE) {
240 		dev_err(s->s_dip, CE_WARN, "unable to register SCSI interface");
241 		goto fail;
242 	}
243 	ddi_report_dev(s->s_dip);
244 
245 	return (DDI_SUCCESS);
246 
247 fail:
248 	(void) smartpqi_detach(s->s_dip, 0);
249 	return (DDI_FAILURE);
250 }
251 
252 static int
253 smartpqi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd __unused)
254 {
255 	int		instance;
256 	pqi_state_t	*s;
257 	pqi_device_t	*devp;
258 
259 	instance = ddi_get_instance(dip);
260 	if ((s = ddi_get_soft_state(pqi_state, instance)) != NULL) {
261 
262 		if (s->s_watchdog != 0) {
263 			(void) untimeout(s->s_watchdog);
264 			s->s_watchdog = 0;
265 		}
266 
267 		if (s->s_error_dma != NULL) {
268 			pqi_free_single(s, s->s_error_dma);
269 			s->s_error_dma = NULL;
270 		}
271 		if (s->s_adminq_dma != NULL) {
272 			pqi_free_single(s, s->s_adminq_dma);
273 			s->s_adminq_dma = NULL;
274 		}
275 		if (s->s_queue_dma != NULL) {
276 			pqi_free_single(s, s->s_queue_dma);
277 			s->s_queue_dma = NULL;
278 		}
279 
280 		/* ---- Safe to always call ---- */
281 		pqi_free_io_resource(s);
282 
283 		if (s->s_cmd_cache != NULL) {
284 			kmem_cache_destroy(s->s_cmd_cache);
285 			s->s_cmd_cache = NULL;
286 		}
287 
288 		if (s->s_events_taskq != NULL) {
289 			ddi_taskq_destroy(s->s_events_taskq);
290 			s->s_events_taskq = NULL;
291 		}
292 		if (s->s_complete_taskq != NULL) {
293 			ddi_taskq_destroy(s->s_complete_taskq);
294 			s->s_complete_taskq = NULL;
295 		}
296 
297 		while ((devp = list_head(&s->s_devnodes)) != NULL) {
298 			/* ---- Better not be any active commands ---- */
299 			ASSERT(list_is_empty(&devp->pd_cmd_list));
300 
301 			ddi_devid_free_guid(devp->pd_guid);
302 			if (devp->pd_pip != NULL)
303 				(void) mdi_pi_free(devp->pd_pip, 0);
304 			if (devp->pd_pip_offlined)
305 				(void) mdi_pi_free(devp->pd_pip_offlined, 0);
306 			list_destroy(&devp->pd_cmd_list);
307 			mutex_destroy(&devp->pd_mutex);
308 			list_remove(&s->s_devnodes, devp);
309 			kmem_free(devp, sizeof (*devp));
310 		}
311 		list_destroy(&s->s_devnodes);
312 		mutex_destroy(&s->s_mutex);
313 		mutex_destroy(&s->s_io_mutex);
314 		mutex_destroy(&s->s_intr_mutex);
315 
316 		cv_destroy(&s->s_quiescedvar);
317 		smartpqi_unregister_hba(s);
318 		smartpqi_unregister_intrs(s);
319 
320 		if (s->s_time_of_day != 0) {
321 			(void) untimeout(s->s_time_of_day);
322 			s->s_time_of_day = 0;
323 		}
324 
325 		ddi_soft_state_free(pqi_state, instance);
326 		ddi_prop_remove_all(dip);
327 	}
328 
329 	return (DDI_SUCCESS);
330 }
331 
332 static int
333 smartpqi_quiesce(dev_info_t *dip)
334 {
335 	pqi_state_t	*s;
336 	int		instance;
337 
338 	/*
339 	 * ddi_get_soft_state is lock-free, so is safe to call from
340 	 * quiesce.  Furthermore, pqi_hba_reset uses only the safe
341 	 * drv_usecwait() and register accesses.
342 	 */
343 	instance = ddi_get_instance(dip);
344 	if ((s = ddi_get_soft_state(pqi_state, instance)) != NULL) {
345 		if (pqi_hba_reset(s)) {
346 			return (DDI_SUCCESS);
347 		}
348 	}
349 	/* If we couldn't quiesce for any reason, play it safe and reboot. */
350 	return (DDI_FAILURE);
351 }
352