xref: /src/sys/dev/smartpqi/smartpqi_main.c (revision 0fc6c3f731a2cca3120798806c330a3081c9424b)
1 /*-
2  * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25 
26 
27 /*
28  * Driver for the Microchip Smart storage controllers
29  */
30 
31 #include "smartpqi_includes.h"
32 #include "smartpqi_controllers.h"
33 
34 CTASSERT(BSD_SUCCESS == PQI_STATUS_SUCCESS);
35 
36 /*
37  * Logging levels global
38 */
39 unsigned long logging_level  = PQISRC_LOG_LEVEL;
40 
41 /*
42  * Function to identify the installed adapter.
43  */
44 static struct pqi_ident *
pqi_find_ident(device_t dev)45 pqi_find_ident(device_t dev)
46 {
47 	struct pqi_ident *m;
48 	u_int16_t vendid, devid, sub_vendid, sub_devid;
49 	static long AllowWildcards = 0xffffffff;
50 	int result;
51 
52 #ifdef DEVICE_HINT
53 	if (AllowWildcards == 0xffffffff)
54 	{
55 		result = resource_long_value("smartpqi", 0, "allow_wildcards", &AllowWildcards);
56 
57 		/* the default case if the hint is not found is to allow wildcards */
58 		if (result != DEVICE_HINT_SUCCESS) {
59 			AllowWildcards = 1;
60 		}
61 	}
62 
63 #endif
64 
65 	vendid = pci_get_vendor(dev);
66 	devid = pci_get_device(dev);
67 	sub_vendid = pci_get_subvendor(dev);
68 	sub_devid = pci_get_subdevice(dev);
69 
70 	for (m = pqi_identifiers; m->vendor != 0; m++) {
71 		if ((m->vendor == vendid) && (m->device == devid) &&
72 			(m->subvendor == sub_vendid) &&
73 			(m->subdevice == sub_devid)) {
74 			return (m);
75 		}
76 	}
77 
78 	for (m = pqi_family_identifiers; m->vendor != 0; m++) {
79 		if ((m->vendor == vendid) && (m->device == devid)) {
80 			if (AllowWildcards != 0)
81 			{
82 				DBG_NOTE("Controller device ID matched using wildcards\n");
83 				return (m);
84 			}
85 			else
86 			{
87 				DBG_NOTE("Controller not probed because device ID wildcards are disabled\n")
88 				return (NULL);
89 			}
90 		}
91 	}
92 
93 	return (NULL);
94 }
95 
96 /*
97  * Determine whether this is one of our supported adapters.
98  */
99 static int
smartpqi_probe(device_t dev)100 smartpqi_probe(device_t dev)
101 {
102 	struct pqi_ident *id;
103 
104 	if ((id = pqi_find_ident(dev)) != NULL) {
105 		device_set_desc(dev, id->desc);
106 		return(BUS_PROBE_VENDOR);
107 	}
108 
109 	return(ENXIO);
110 }
111 
112 /*
113  * Store Bus/Device/Function in softs
114  */
115 void
pqisrc_save_controller_info(struct pqisrc_softstate * softs)116 pqisrc_save_controller_info(struct pqisrc_softstate *softs)
117 {
118 	device_t dev = softs->os_specific.pqi_dev;
119 
120 	softs->bus_id = (uint32_t)pci_get_bus(dev);
121 	softs->device_id = (uint32_t)pci_get_device(dev);
122 	softs->func_id = (uint32_t)pci_get_function(dev);
123 }
124 
125 
read_device_hint_resource(struct pqisrc_softstate * softs,char * keyword,uint32_t * value)126 static void read_device_hint_resource(struct pqisrc_softstate *softs,
127 		char *keyword,  uint32_t *value)
128 {
129 	DBG_FUNC("IN\n");
130 
131 	long result = 0;
132 
133 	device_t dev = softs->os_specific.pqi_dev;
134 
135 	if (resource_long_value("smartpqi", device_get_unit(dev), keyword, &result) == DEVICE_HINT_SUCCESS) {
136 		if (result) {
137 			/* set resource to 1 for disabling the
138 			 * firmware feature in device hint file. */
139 			*value = 0;
140 
141 		}
142 		else {
143 			/* set resource to 0 for enabling the
144 			 * firmware feature in device hint file. */
145 			*value = 1;
146 		}
147 	}
148 	else {
149 		/* Enabled by default */
150 		*value = 1;
151 	}
152 
153 	DBG_NOTE("SmartPQI Device Hint: %s, Is it enabled = %u\n", keyword, *value);
154 
155 	DBG_FUNC("OUT\n");
156 }
157 
read_device_hint_decimal_value(struct pqisrc_softstate * softs,char * keyword,uint32_t * value)158 static void read_device_hint_decimal_value(struct pqisrc_softstate *softs,
159 		char *keyword, uint32_t *value)
160 {
161 	DBG_FUNC("IN\n");
162 
163 	long result = 0;
164 
165 	device_t dev = softs->os_specific.pqi_dev;
166 
167 	if (resource_long_value("smartpqi", device_get_unit(dev), keyword, &result) == DEVICE_HINT_SUCCESS) {
168 		/* Nothing to do here. Value reads
169 		 * directly from Device.Hint file */
170 		*value = result;
171 	}
172 	else {
173 		/* Set to max to determine the value */
174 		*value = 0XFFFF;
175 	}
176 
177 	DBG_FUNC("OUT\n");
178 }
179 
smartpqi_read_all_device_hint_file_entries(struct pqisrc_softstate * softs)180 static void smartpqi_read_all_device_hint_file_entries(struct pqisrc_softstate *softs)
181 {
182 	uint32_t value = 0;
183 
184 	DBG_FUNC("IN\n");
185 
186 	/* hint.smartpqi.0.stream_disable =  "0" */
187 	read_device_hint_resource(softs, STREAM_DETECTION, &value);
188 	softs->hint.stream_status = value;
189 
190 	/* hint.smartpqi.0.sata_unique_wwn_disable =  "0" */
191 	read_device_hint_resource(softs, SATA_UNIQUE_WWN, &value);
192 	softs->hint.sata_unique_wwn_status = value;
193 
194 	/* hint.smartpqi.0.aio_raid1_write_disable =  "0" */
195 	read_device_hint_resource(softs, AIO_RAID1_WRITE_BYPASS, &value);
196 	softs->hint.aio_raid1_write_status = value;
197 
198 	/* hint.smartpqi.0.aio_raid5_write_disable =  "0" */
199 	read_device_hint_resource(softs, AIO_RAID5_WRITE_BYPASS, &value);
200 	softs->hint.aio_raid5_write_status = value;
201 
202 	/* hint.smartpqi.0.aio_raid6_write_disable =  "0" */
203 	read_device_hint_resource(softs, AIO_RAID6_WRITE_BYPASS, &value);
204 	softs->hint.aio_raid6_write_status = value;
205 
206 	/* hint.smartpqi.0.queue_depth =  "0" */
207 	read_device_hint_decimal_value(softs, ADAPTER_QUEUE_DEPTH, &value);
208 	softs->hint.queue_depth = value;
209 
210 	/* hint.smartpqi.0.sg_count =  "0" */
211 	read_device_hint_decimal_value(softs, SCATTER_GATHER_COUNT, &value);
212 	softs->hint.sg_segments = value;
213 
214 	DBG_FUNC("IN\n");
215 }
216 
217 /* Get the driver parameter tunables. */
218 static void
smartpqi_get_tunables(void)219 smartpqi_get_tunables(void)
220 {
221    /*
222     * Temp variable used to get the value from loader.conf.
223     * Initializing it with the current logging level value.
224     */
225 	unsigned long logging_level_temp = PQISRC_LOG_LEVEL;
226 
227 	TUNABLE_ULONG_FETCH("hw.smartpqi.debug_level", &logging_level_temp);
228 
229    DBG_SET_LOGGING_LEVEL(logging_level_temp);
230 }
231 
232 /*
233  * Allocate resources for our device, set up the bus interface.
234  * Initialize the PQI related functionality, scan devices, register sim to
235  * upper layer, create management interface device node etc.
236  */
237 static int
smartpqi_attach(device_t dev)238 smartpqi_attach(device_t dev)
239 {
240 	struct pqisrc_softstate *softs;
241 	struct pqi_ident *id = NULL;
242 	int error = BSD_SUCCESS;
243 	u_int32_t command = 0, i = 0;
244 	int card_index = device_get_unit(dev);
245 	rcb_t *rcbp = NULL;
246 
247 	/*
248 	 * Initialize softc.
249 	 */
250 	softs = device_get_softc(dev);
251 
252 	if (!softs) {
253 		printf("Could not get softc\n");
254 		error = EINVAL;
255 		goto out;
256 	}
257 	memset(softs, 0, sizeof(*softs));
258 	softs->os_specific.pqi_dev = dev;
259 
260     smartpqi_get_tunables();
261 
262 	DBG_FUNC("IN\n");
263 
264 	/* assume failure is 'not configured' */
265 	error = ENXIO;
266 
267 	/*
268 	 * Verify that the adapter is correctly set up in PCI space.
269 	 */
270 	pci_enable_busmaster(softs->os_specific.pqi_dev);
271 	command = pci_read_config(softs->os_specific.pqi_dev, PCIR_COMMAND, 2);
272 	if ((command & PCIM_CMD_MEMEN) == 0) {
273 		DBG_ERR("memory window not available command = %d\n", command);
274 		error = ENXIO;
275 		goto out;
276 	}
277 
278 	/*
279 	 * Detect the hardware interface version, set up the bus interface
280 	 * indirection.
281 	 */
282 	id = pqi_find_ident(dev);
283 	if (!id) {
284 		DBG_ERR("NULL return value from pqi_find_ident\n");
285 		goto out;
286 	}
287 
288 	softs->os_specific.pqi_hwif = id->hwif;
289 
290 	switch(softs->os_specific.pqi_hwif) {
291 		case PQI_HWIF_SRCV:
292 			DBG_INFO("set hardware up for PMC SRCv for %p\n", softs);
293 			break;
294 		default:
295 			softs->os_specific.pqi_hwif = PQI_HWIF_UNKNOWN;
296 			DBG_ERR("unknown hardware type\n");
297 			error = ENXIO;
298 			goto out;
299 	}
300 
301 	pqisrc_save_controller_info(softs);
302 
303 	/*
304 	 * Allocate the PCI register window.
305 	 */
306 	softs->os_specific.pqi_regs_rid0 = PCIR_BAR(0);
307 	if ((softs->os_specific.pqi_regs_res0 =
308 		bus_alloc_resource_any(softs->os_specific.pqi_dev, SYS_RES_MEMORY,
309 		&softs->os_specific.pqi_regs_rid0, RF_ACTIVE)) == NULL) {
310 		DBG_ERR("couldn't allocate register window 0\n");
311 		/* assume failure is 'out of memory' */
312 		error = ENOMEM;
313 		goto out;
314 	}
315 
316 	bus_get_resource_start(softs->os_specific.pqi_dev, SYS_RES_MEMORY,
317 		softs->os_specific.pqi_regs_rid0);
318 
319 	softs->pci_mem_handle.pqi_btag = rman_get_bustag(softs->os_specific.pqi_regs_res0);
320 	softs->pci_mem_handle.pqi_bhandle = rman_get_bushandle(softs->os_specific.pqi_regs_res0);
321 	/* softs->pci_mem_base_vaddr = (uintptr_t)rman_get_virtual(softs->os_specific.pqi_regs_res0); */
322 	softs->pci_mem_base_vaddr = (char *)rman_get_virtual(softs->os_specific.pqi_regs_res0);
323 
324 	/*
325 	 * Allocate the parent bus DMA tag appropriate for our PCI interface.
326 	 *
327 	 * Note that some of these controllers are 64-bit capable.
328 	 */
329 	if (bus_dma_tag_create(bus_get_dma_tag(dev), 	/* parent */
330 				PAGE_SIZE, 0,		/* algnmnt, boundary */
331 				BUS_SPACE_MAXADDR,/* lowaddr */
332 				BUS_SPACE_MAXADDR, 	/* highaddr */
333 				NULL, NULL, 		/* filter, filterarg */
334 				BUS_SPACE_MAXSIZE,	/* maxsize */
335 				BUS_SPACE_UNRESTRICTED,	/* nsegments */
336 				BUS_SPACE_MAXSIZE,	/* maxsegsize */
337 				0,			/* flags */
338 				NULL, NULL,		/* No locking needed */
339 				&softs->os_specific.pqi_parent_dmat)) {
340 		DBG_ERR("can't allocate parent DMA tag\n");
341 		/* assume failure is 'out of memory' */
342 		error = ENOMEM;
343 		goto dma_out;
344 	}
345 
346 	softs->os_specific.sim_registered = FALSE;
347 	softs->os_name = "FreeBSD ";
348 
349 	smartpqi_read_all_device_hint_file_entries(softs);
350 
351 	/* Initialize the PQI library */
352 	error = pqisrc_init(softs);
353 	if (error != PQI_STATUS_SUCCESS) {
354 		DBG_ERR("Failed to initialize pqi lib error = %d\n", error);
355 		error = ENXIO;
356 		goto out;
357 	}
358 	else {
359 		error = BSD_SUCCESS;
360 	}
361 
362         mtx_init(&softs->os_specific.cam_lock, "cam_lock", NULL, MTX_DEF);
363         softs->os_specific.mtx_init = TRUE;
364         mtx_init(&softs->os_specific.map_lock, "map_lock", NULL, MTX_DEF);
365 
366 	callout_init(&softs->os_specific.wellness_periodic, 1);
367 	callout_init(&softs->os_specific.heartbeat_timeout_id, 1);
368 
369         /*
370          * Create DMA tag for mapping buffers into controller-addressable space.
371          */
372         if (bus_dma_tag_create(softs->os_specific.pqi_parent_dmat,/* parent */
373 				1, 0,			/* algnmnt, boundary */
374 				BUS_SPACE_MAXADDR,	/* lowaddr */
375 				BUS_SPACE_MAXADDR,	/* highaddr */
376 				NULL, NULL,		/* filter, filterarg */
377 				(bus_size_t)softs->pqi_cap.max_sg_elem*PAGE_SIZE,/* maxsize */
378 				softs->pqi_cap.max_sg_elem,	/* nsegments */
379 				BUS_SPACE_MAXSIZE,	/* maxsegsize */
380 				BUS_DMA_ALLOCNOW,		/* flags */
381 				busdma_lock_mutex,		/* lockfunc */
382 				&softs->os_specific.map_lock,	/* lockfuncarg*/
383 				&softs->os_specific.pqi_buffer_dmat)) {
384 		DBG_ERR("can't allocate buffer DMA tag for pqi_buffer_dmat\n");
385 		return (ENOMEM);
386         }
387 
388 	rcbp = &softs->rcb[1];
389 	for( i = 1;  i <= softs->pqi_cap.max_outstanding_io; i++, rcbp++ ) {
390 		if ((error = bus_dmamap_create(softs->os_specific.pqi_buffer_dmat, 0, &rcbp->cm_datamap)) != 0) {
391 			DBG_ERR("Cant create datamap for buf @"
392 			"rcbp = %p maxio = %u error = %d\n",
393 			rcbp, softs->pqi_cap.max_outstanding_io, error);
394 			goto dma_out;
395 		}
396 	}
397 
398 	os_start_heartbeat_timer((void *)softs); /* Start the heart-beat timer */
399 	callout_reset(&softs->os_specific.wellness_periodic, 120 * hz,
400 			os_wellness_periodic, softs);
401 
402 	error = pqisrc_scan_devices(softs);
403 	if (error != PQI_STATUS_SUCCESS) {
404 		DBG_ERR("Failed to scan lib error = %d\n", error);
405 		error = ENXIO;
406 		goto out;
407 	}
408 	else {
409 		error = BSD_SUCCESS;
410 	}
411 
412 	error = register_sim(softs, card_index);
413 	if (error) {
414 		DBG_ERR("Failed to register sim index = %d error = %d\n",
415 			card_index, error);
416 		goto out;
417 	}
418 
419 	smartpqi_target_rescan(softs);
420 
421 	TASK_INIT(&softs->os_specific.event_task, 0, pqisrc_event_worker,softs);
422 
423 	error = create_char_dev(softs, card_index);
424 	if (error) {
425 		DBG_ERR("Failed to register character device index=%d r=%d\n",
426 			card_index, error);
427 		goto out;
428 	}
429 
430 	goto out;
431 
432 dma_out:
433 	if (softs->os_specific.pqi_regs_res0 != NULL)
434 		bus_release_resource(softs->os_specific.pqi_dev, SYS_RES_MEMORY,
435 			softs->os_specific.pqi_regs_rid0,
436 			softs->os_specific.pqi_regs_res0);
437 out:
438 	DBG_FUNC("OUT error = %d\n", error);
439 
440 	return(error);
441 }
442 
443 /*
444  * Deallocate resources for our device.
445  */
446 static int
smartpqi_detach(device_t dev)447 smartpqi_detach(device_t dev)
448 {
449 	struct pqisrc_softstate *softs = device_get_softc(dev);
450 	int rval = BSD_SUCCESS;
451 
452 	DBG_FUNC("IN\n");
453 
454 	if (softs == NULL)
455 		return ENXIO;
456 
457 	/* kill the periodic event */
458 	callout_drain(&softs->os_specific.wellness_periodic);
459 	/* Kill the heart beat event */
460 	callout_drain(&softs->os_specific.heartbeat_timeout_id);
461 
462 	if (!pqisrc_ctrl_offline(softs)) {
463 		rval = pqisrc_flush_cache(softs, PQISRC_NONE_CACHE_FLUSH_ONLY);
464 		if (rval != PQI_STATUS_SUCCESS) {
465 			DBG_ERR("Unable to flush adapter cache! rval = %d\n", rval);
466 			rval = EIO;
467 		} else {
468 			rval = BSD_SUCCESS;
469 		}
470 	}
471 
472 	destroy_char_dev(softs);
473 	pqisrc_uninit(softs);
474 	deregister_sim(softs);
475 	pci_release_msi(dev);
476 
477 	DBG_FUNC("OUT\n");
478 
479 	return rval;
480 }
481 
482 /*
483  * Bring the controller to a quiescent state, ready for system suspend.
484  */
485 static int
smartpqi_suspend(device_t dev)486 smartpqi_suspend(device_t dev)
487 {
488 	struct pqisrc_softstate *softs = device_get_softc(dev);
489 
490 	DBG_FUNC("IN\n");
491 
492 	if (softs == NULL)
493 		return ENXIO;
494 
495 	DBG_INFO("Suspending the device %p\n", softs);
496 	softs->os_specific.pqi_state |= SMART_STATE_SUSPEND;
497 
498 	DBG_FUNC("OUT\n");
499 
500 	return BSD_SUCCESS;
501 }
502 
503 /*
504  * Bring the controller back to a state ready for operation.
505  */
506 static int
smartpqi_resume(device_t dev)507 smartpqi_resume(device_t dev)
508 {
509 	struct pqisrc_softstate *softs = device_get_softc(dev);
510 
511 	DBG_FUNC("IN\n");
512 
513 	if (softs == NULL)
514 		return ENXIO;
515 
516 	softs->os_specific.pqi_state &= ~SMART_STATE_SUSPEND;
517 
518 	DBG_FUNC("OUT\n");
519 
520 	return BSD_SUCCESS;
521 }
522 
523 /*
524  * Do whatever is needed during a system shutdown.
525  */
526 static int
smartpqi_shutdown(device_t dev)527 smartpqi_shutdown(device_t dev)
528 {
529 	struct pqisrc_softstate *softs = device_get_softc(dev);
530 	int bsd_status = BSD_SUCCESS;
531 	int pqi_status;
532 
533 	DBG_FUNC("IN\n");
534 
535 	if (softs == NULL)
536 		return ENXIO;
537 
538 	if (pqisrc_ctrl_offline(softs))
539 		return BSD_SUCCESS;
540 
541 	pqi_status = pqisrc_flush_cache(softs, PQISRC_SHUTDOWN);
542 	if (pqi_status != PQI_STATUS_SUCCESS) {
543 		DBG_ERR("Unable to flush adapter cache! rval = %d\n", pqi_status);
544 		bsd_status = EIO;
545 	}
546 
547 	DBG_FUNC("OUT\n");
548 
549 	return bsd_status;
550 }
551 
552 
553 /*
554  * PCI bus interface.
555  */
556 static device_method_t pqi_methods[] = {
557 	/* Device interface */
558 	DEVMETHOD(device_probe,		smartpqi_probe),
559 	DEVMETHOD(device_attach,	smartpqi_attach),
560 	DEVMETHOD(device_detach,	smartpqi_detach),
561 	DEVMETHOD(device_suspend,	smartpqi_suspend),
562 	DEVMETHOD(device_resume,	smartpqi_resume),
563 	DEVMETHOD(device_shutdown,	smartpqi_shutdown),
564 	DEVMETHOD_END
565 };
566 
567 static driver_t smartpqi_pci_driver = {
568 	"smartpqi",
569 	pqi_methods,
570 	sizeof(struct pqisrc_softstate)
571 };
572 
573 DRIVER_MODULE(smartpqi, pci, smartpqi_pci_driver, 0, 0);
574 
575 MODULE_DEPEND(smartpqi, pci, 1, 1, 1);
576