xref: /illumos-gate/usr/src/uts/i86pc/io/ioat/ioat.c (revision f6f4cb8ada400367a1921f6b93fb9e02f53ac5e6)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <sys/errno.h>
28 #include <sys/types.h>
29 #include <sys/conf.h>
30 #include <sys/kmem.h>
31 #include <sys/ddi.h>
32 #include <sys/stat.h>
33 #include <sys/sunddi.h>
34 #include <sys/file.h>
35 #include <sys/open.h>
36 #include <sys/modctl.h>
37 #include <sys/ddi_impldefs.h>
38 #include <sys/sysmacros.h>
39 
40 #include <sys/ioat.h>
41 
42 static int ioat_open(dev_t *devp, int flag, int otyp, cred_t *cred);
43 static int ioat_close(dev_t devp, int flag, int otyp, cred_t *cred);
44 static int ioat_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
45 static int ioat_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
46 static int ioat_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
47     void **result);
48 
49 static 	struct cb_ops ioat_cb_ops = {
50 	ioat_open,		/* cb_open */
51 	ioat_close,		/* cb_close */
52 	nodev,			/* cb_strategy */
53 	nodev,			/* cb_print */
54 	nodev,			/* cb_dump */
55 	nodev,			/* cb_read */
56 	nodev,			/* cb_write */
57 	ioat_ioctl,		/* cb_ioctl */
58 	nodev,			/* cb_devmap */
59 	nodev,			/* cb_mmap */
60 	nodev,			/* cb_segmap */
61 	nochpoll,		/* cb_chpoll */
62 	ddi_prop_op,		/* cb_prop_op */
63 	NULL,			/* cb_stream */
64 	D_NEW | D_MP | D_64BIT | D_DEVMAP,	/* cb_flag */
65 	CB_REV
66 };
67 
68 static struct dev_ops ioat_dev_ops = {
69 	DEVO_REV,		/* devo_rev */
70 	0,			/* devo_refcnt */
71 	ioat_getinfo,		/* devo_getinfo */
72 	nulldev,		/* devo_identify */
73 	nulldev,		/* devo_probe */
74 	ioat_attach,		/* devo_attach */
75 	ioat_detach,		/* devo_detach */
76 	nodev,			/* devo_reset */
77 	&ioat_cb_ops,		/* devo_cb_ops */
78 	NULL,			/* devo_bus_ops */
79 	NULL			/* power */
80 };
81 
82 static struct modldrv ioat_modldrv = {
83 	&mod_driverops,		/* Type of module.  This one is a driver */
84 	"ioat driver",		/* Name of the module. */
85 	&ioat_dev_ops,		/* driver ops */
86 };
87 
88 static struct modlinkage ioat_modlinkage = {
89 	MODREV_1,
90 	(void *) &ioat_modldrv,
91 	NULL
92 };
93 
94 
95 void *ioat_statep;
96 
97 static int ioat_chip_init(ioat_state_t *state);
98 static void ioat_chip_fini(ioat_state_t *state);
99 static int ioat_drv_init(ioat_state_t *state);
100 static void ioat_drv_fini(ioat_state_t *state);
101 static uint_t ioat_isr(caddr_t parm);
102 static void ioat_intr_enable(ioat_state_t *state);
103 static void ioat_intr_disable(ioat_state_t *state);
104 void ioat_detach_finish(ioat_state_t *state);
105 
106 
107 ddi_device_acc_attr_t ioat_acc_attr = {
108 	DDI_DEVICE_ATTR_V0,		/* devacc_attr_version */
109 	DDI_NEVERSWAP_ACC,		/* devacc_attr_endian_flags */
110 	DDI_STORECACHING_OK_ACC,	/* devacc_attr_dataorder */
111 	DDI_DEFAULT_ACC			/* devacc_attr_access */
112 };
113 
114 /* dcopy callback interface */
115 dcopy_device_cb_t ioat_cb = {
116 	DCOPY_DEVICECB_V0,
117 	0,		/* reserved */
118 	ioat_channel_alloc,
119 	ioat_channel_free,
120 	ioat_cmd_alloc,
121 	ioat_cmd_free,
122 	ioat_cmd_post,
123 	ioat_cmd_poll,
124 	ioat_unregister_complete
125 };
126 
127 /*
128  * _init()
129  */
130 int
131 _init(void)
132 {
133 	int e;
134 
135 	e = ddi_soft_state_init(&ioat_statep, sizeof (ioat_state_t), 1);
136 	if (e != 0) {
137 		return (e);
138 	}
139 
140 	e = mod_install(&ioat_modlinkage);
141 	if (e != 0) {
142 		ddi_soft_state_fini(&ioat_statep);
143 		return (e);
144 	}
145 
146 	return (0);
147 }
148 
149 /*
150  * _info()
151  */
152 int
153 _info(struct modinfo *modinfop)
154 {
155 	return (mod_info(&ioat_modlinkage, modinfop));
156 }
157 
158 /*
159  * _fini()
160  */
161 int
162 _fini(void)
163 {
164 	int e;
165 
166 	e = mod_remove(&ioat_modlinkage);
167 	if (e != 0) {
168 		return (e);
169 	}
170 
171 	ddi_soft_state_fini(&ioat_statep);
172 
173 	return (0);
174 }
175 
176 /*
177  * ioat_attach()
178  */
179 static int
180 ioat_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
181 {
182 	ioat_state_t *state;
183 	int instance;
184 	int e;
185 
186 
187 	switch (cmd) {
188 	case DDI_ATTACH:
189 		break;
190 
191 	case DDI_RESUME:
192 		instance = ddi_get_instance(dip);
193 		state = ddi_get_soft_state(ioat_statep, instance);
194 		if (state == NULL) {
195 			return (DDI_FAILURE);
196 		}
197 		e = ioat_channel_resume(state);
198 		if (e != DDI_SUCCESS) {
199 			return (DDI_FAILURE);
200 		}
201 		ioat_intr_enable(state);
202 		return (DDI_SUCCESS);
203 
204 	default:
205 		return (DDI_FAILURE);
206 	}
207 
208 	instance = ddi_get_instance(dip);
209 	e = ddi_soft_state_zalloc(ioat_statep, instance);
210 	if (e != DDI_SUCCESS) {
211 		return (DDI_FAILURE);
212 	}
213 	state = ddi_get_soft_state(ioat_statep, instance);
214 	if (state == NULL) {
215 		goto attachfail_get_soft_state;
216 	}
217 
218 	state->is_dip = dip;
219 	state->is_instance = instance;
220 
221 	/* setup the registers, save away some device info */
222 	e = ioat_chip_init(state);
223 	if (e != DDI_SUCCESS) {
224 		goto attachfail_chip_init;
225 	}
226 
227 	/* initialize driver state, must be after chip init */
228 	e = ioat_drv_init(state);
229 	if (e != DDI_SUCCESS) {
230 		goto attachfail_drv_init;
231 	}
232 
233 	/* create the minor node (for the ioctl) */
234 	e = ddi_create_minor_node(dip, "ioat", S_IFCHR, instance, DDI_PSEUDO,
235 	    0);
236 	if (e != DDI_SUCCESS) {
237 		goto attachfail_minor_node;
238 	}
239 
240 	/* Enable device interrupts */
241 	ioat_intr_enable(state);
242 
243 	/* Report that driver was loaded */
244 	ddi_report_dev(dip);
245 
246 	/* register with dcopy */
247 	e = dcopy_device_register(state, &state->is_deviceinfo,
248 	    &state->is_device_handle);
249 	if (e != DCOPY_SUCCESS) {
250 		goto attachfail_register;
251 	}
252 
253 	return (DDI_SUCCESS);
254 
255 attachfail_register:
256 	ioat_intr_disable(state);
257 	ddi_remove_minor_node(dip, NULL);
258 attachfail_minor_node:
259 	ioat_drv_fini(state);
260 attachfail_drv_init:
261 	ioat_chip_fini(state);
262 attachfail_chip_init:
263 attachfail_get_soft_state:
264 	(void) ddi_soft_state_free(ioat_statep, instance);
265 
266 	return (DDI_FAILURE);
267 }
268 
269 /*
270  * ioat_detach()
271  */
272 static int
273 ioat_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
274 {
275 	ioat_state_t *state;
276 	int instance;
277 	int e;
278 
279 
280 	instance = ddi_get_instance(dip);
281 	state = ddi_get_soft_state(ioat_statep, instance);
282 	if (state == NULL) {
283 		return (DDI_FAILURE);
284 	}
285 
286 	switch (cmd) {
287 	case DDI_DETACH:
288 		break;
289 
290 	case DDI_SUSPEND:
291 		ioat_channel_suspend(state);
292 		return (DDI_SUCCESS);
293 
294 	default:
295 		return (DDI_FAILURE);
296 	}
297 
298 	/*
299 	 * try to unregister from dcopy.  Since this driver doesn't follow the
300 	 * traditional parent/child model, we may still be in use so we can't
301 	 * detach yet.
302 	 */
303 	e = dcopy_device_unregister(&state->is_device_handle);
304 	if (e != DCOPY_SUCCESS) {
305 		if (e == DCOPY_PENDING) {
306 			cmn_err(CE_NOTE, "device busy, performing asynchronous"
307 			    " detach\n");
308 		}
309 		return (DDI_FAILURE);
310 	}
311 
312 	ioat_detach_finish(state);
313 
314 	return (DDI_SUCCESS);
315 }
316 
317 /*
318  * ioat_getinfo()
319  */
320 /*ARGSUSED*/
321 static int
322 ioat_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
323 {
324 	ioat_state_t *state;
325 	int instance;
326 	dev_t dev;
327 	int e;
328 
329 
330 	dev = (dev_t)arg;
331 	instance = getminor(dev);
332 
333 	switch (cmd) {
334 	case DDI_INFO_DEVT2DEVINFO:
335 		state = ddi_get_soft_state(ioat_statep, instance);
336 		if (state == NULL) {
337 			return (DDI_FAILURE);
338 		}
339 		*result = (void *)state->is_dip;
340 		e = DDI_SUCCESS;
341 		break;
342 
343 	case DDI_INFO_DEVT2INSTANCE:
344 		*result = (void *)(uintptr_t)instance;
345 		e = DDI_SUCCESS;
346 		break;
347 
348 	default:
349 		e = DDI_FAILURE;
350 		break;
351 	}
352 
353 	return (e);
354 }
355 
356 
357 /*
358  * ioat_open()
359  */
360 /*ARGSUSED*/
361 static int
362 ioat_open(dev_t *devp, int flag, int otyp, cred_t *cred)
363 {
364 	ioat_state_t *state;
365 	int instance;
366 
367 	instance = getminor(*devp);
368 	state = ddi_get_soft_state(ioat_statep, instance);
369 	if (state == NULL) {
370 		return (ENXIO);
371 	}
372 
373 	return (0);
374 }
375 
376 
377 /*
378  * ioat_close()
379  */
380 /*ARGSUSED*/
381 static int
382 ioat_close(dev_t devp, int flag, int otyp, cred_t *cred)
383 {
384 	return (0);
385 }
386 
387 
388 /*
389  * ioat_chip_init()
390  */
391 static int
392 ioat_chip_init(ioat_state_t *state)
393 {
394 	ddi_device_acc_attr_t attr;
395 	int e;
396 
397 
398 	attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
399 	attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
400 	attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
401 
402 	e =  ddi_regs_map_setup(state->is_dip, 1, (caddr_t *)&state->is_genregs,
403 	    0, 0, &attr, &state->is_reg_handle);
404 	if (e != DDI_SUCCESS) {
405 		goto chipinitfail_regsmap;
406 	}
407 
408 	/* save away ioat chip info */
409 	state->is_num_channels = (uint_t)ddi_get8(state->is_reg_handle,
410 	    &state->is_genregs[IOAT_CHANCNT]);
411 
412 	/*
413 	 * If we get a bogus value, something is wrong with the H/W, fail to
414 	 * attach.
415 	 */
416 	if (state->is_num_channels == 0) {
417 		goto chipinitfail_numchan;
418 	}
419 
420 	state->is_maxxfer = (uint_t)ddi_get8(state->is_reg_handle,
421 	    &state->is_genregs[IOAT_XFERCAP]);
422 	state->is_chanoff = (uintptr_t)ddi_get16(state->is_reg_handle,
423 	    (uint16_t *)&state->is_genregs[IOAT_PERPORT_OFF]);
424 	state->is_cbver = (uint_t)ddi_get8(state->is_reg_handle,
425 	    &state->is_genregs[IOAT_CBVER]);
426 	state->is_intrdelay = (uint_t)ddi_get16(state->is_reg_handle,
427 	    (uint16_t *)&state->is_genregs[IOAT_INTRDELAY]);
428 	state->is_status = (uint_t)ddi_get16(state->is_reg_handle,
429 	    (uint16_t *)&state->is_genregs[IOAT_CSSTATUS]);
430 	state->is_capabilities = (uint_t)ddi_get32(state->is_reg_handle,
431 	    (uint32_t *)&state->is_genregs[IOAT_DMACAPABILITY]);
432 
433 	if (state->is_cbver & 0x10) {
434 		state->is_ver = IOAT_CBv1;
435 	} else if (state->is_cbver & 0x20) {
436 		state->is_ver = IOAT_CBv2;
437 	} else {
438 		goto chipinitfail_version;
439 	}
440 
441 	return (DDI_SUCCESS);
442 
443 chipinitfail_version:
444 chipinitfail_numchan:
445 	ddi_regs_map_free(&state->is_reg_handle);
446 chipinitfail_regsmap:
447 	return (DDI_FAILURE);
448 }
449 
450 
451 /*
452  * ioat_chip_fini()
453  */
454 static void
455 ioat_chip_fini(ioat_state_t *state)
456 {
457 	ddi_regs_map_free(&state->is_reg_handle);
458 }
459 
460 
461 /*
462  * ioat_drv_init()
463  */
464 static int
465 ioat_drv_init(ioat_state_t *state)
466 {
467 	ddi_acc_handle_t handle;
468 	int e;
469 
470 
471 	mutex_init(&state->is_mutex, NULL, MUTEX_DRIVER, NULL);
472 
473 	state->is_deviceinfo.di_dip = state->is_dip;
474 	state->is_deviceinfo.di_num_dma = state->is_num_channels;
475 	state->is_deviceinfo.di_maxxfer = state->is_maxxfer;
476 	state->is_deviceinfo.di_capabilities = state->is_capabilities;
477 	state->is_deviceinfo.di_cb = &ioat_cb;
478 
479 	e = pci_config_setup(state->is_dip, &handle);
480 	if (e != DDI_SUCCESS) {
481 		goto drvinitfail_config_setup;
482 	}
483 
484 	/* read in Vendor ID */
485 	state->is_deviceinfo.di_id = (uint64_t)pci_config_get16(handle, 0);
486 	state->is_deviceinfo.di_id = state->is_deviceinfo.di_id << 16;
487 
488 	/* read in Device ID */
489 	state->is_deviceinfo.di_id |= (uint64_t)pci_config_get16(handle, 2);
490 	state->is_deviceinfo.di_id = state->is_deviceinfo.di_id << 32;
491 
492 	/* Add in chipset version */
493 	state->is_deviceinfo.di_id |= (uint64_t)state->is_cbver;
494 	pci_config_teardown(&handle);
495 
496 	e = ddi_intr_hilevel(state->is_dip, 0);
497 	if (e != 0) {
498 		cmn_err(CE_WARN, "hilevel interrupt not supported\n");
499 		goto drvinitfail_hilevel;
500 	}
501 
502 	/* we don't support MSIs for v2 yet */
503 	e = ddi_add_intr(state->is_dip, 0, NULL, NULL, ioat_isr,
504 	    (caddr_t)state);
505 	if (e != DDI_SUCCESS) {
506 		goto drvinitfail_add_intr;
507 	}
508 
509 	e = ddi_get_iblock_cookie(state->is_dip, 0, &state->is_iblock_cookie);
510 	if (e != DDI_SUCCESS) {
511 		goto drvinitfail_iblock_cookie;
512 	}
513 
514 	e = ioat_channel_init(state);
515 	if (e != DDI_SUCCESS) {
516 		goto drvinitfail_channel_init;
517 	}
518 
519 	return (DDI_SUCCESS);
520 
521 drvinitfail_channel_init:
522 drvinitfail_iblock_cookie:
523 	ddi_remove_intr(state->is_dip, 0, state->is_iblock_cookie);
524 drvinitfail_add_intr:
525 drvinitfail_hilevel:
526 drvinitfail_config_setup:
527 	mutex_destroy(&state->is_mutex);
528 
529 	return (DDI_FAILURE);
530 }
531 
532 
533 /*
534  * ioat_drv_fini()
535  */
536 static void
537 ioat_drv_fini(ioat_state_t *state)
538 {
539 	ioat_channel_fini(state);
540 	ddi_remove_intr(state->is_dip, 0, state->is_iblock_cookie);
541 	mutex_destroy(&state->is_mutex);
542 }
543 
544 
545 /*
546  * ioat_unregister_complete()
547  */
548 void
549 ioat_unregister_complete(void *device_private, int status)
550 {
551 	ioat_state_t *state;
552 
553 
554 	state = device_private;
555 
556 	if (status != DCOPY_SUCCESS) {
557 		cmn_err(CE_WARN, "asynchronous detach aborted\n");
558 		return;
559 	}
560 
561 	cmn_err(CE_CONT, "detach completing\n");
562 	ioat_detach_finish(state);
563 }
564 
565 
566 /*
567  * ioat_detach_finish()
568  */
569 void
570 ioat_detach_finish(ioat_state_t *state)
571 {
572 	ioat_intr_disable(state);
573 	ddi_remove_minor_node(state->is_dip, NULL);
574 	ioat_drv_fini(state);
575 	ioat_chip_fini(state);
576 	(void) ddi_soft_state_free(ioat_statep, state->is_instance);
577 }
578 
579 
580 /*
581  * ioat_intr_enable()
582  */
583 static void
584 ioat_intr_enable(ioat_state_t *state)
585 {
586 	uint32_t intr_status;
587 
588 
589 	/* Clear any pending interrupts */
590 	intr_status = ddi_get32(state->is_reg_handle,
591 	    (uint32_t *)&state->is_genregs[IOAT_ATTNSTATUS]);
592 	if (intr_status != 0) {
593 		ddi_put32(state->is_reg_handle,
594 		    (uint32_t *)&state->is_genregs[IOAT_ATTNSTATUS],
595 		    intr_status);
596 	}
597 
598 	/* Enable interrupts on the device */
599 	ddi_put8(state->is_reg_handle, &state->is_genregs[IOAT_INTRCTL],
600 	    IOAT_INTRCTL_MASTER_EN);
601 }
602 
603 
604 /*
605  * ioat_intr_disable()
606  */
607 static void
608 ioat_intr_disable(ioat_state_t *state)
609 {
610 	/*
611 	 * disable interrupts on the device. A read of the interrupt control
612 	 * register clears the enable bit.
613 	 */
614 	(void) ddi_get8(state->is_reg_handle,
615 	    &state->is_genregs[IOAT_INTRCTL]);
616 }
617 
618 
619 /*
620  * ioat_isr()
621  */
622 static uint_t
623 ioat_isr(caddr_t parm)
624 {
625 	uint32_t intr_status;
626 	ioat_state_t *state;
627 	uint8_t intrctrl;
628 	uint32_t chan;
629 	uint_t r;
630 	int i;
631 
632 	state = (ioat_state_t *)parm;
633 
634 	intrctrl = ddi_get8(state->is_reg_handle,
635 	    &state->is_genregs[IOAT_INTRCTL]);
636 	/* master interrupt enable should always be set */
637 	ASSERT(intrctrl & IOAT_INTRCTL_MASTER_EN);
638 
639 	/* If the interrupt status bit isn't set, it's not ours */
640 	if (!(intrctrl & IOAT_INTRCTL_INTR_STAT)) {
641 		/* re-set master interrupt enable (since it clears on read) */
642 		ddi_put8(state->is_reg_handle,
643 		    &state->is_genregs[IOAT_INTRCTL], intrctrl);
644 		return (DDI_INTR_UNCLAIMED);
645 	}
646 
647 	/* see which channels generated the interrupt */
648 	intr_status = ddi_get32(state->is_reg_handle,
649 	    (uint32_t *)&state->is_genregs[IOAT_ATTNSTATUS]);
650 
651 	/* call the intr handler for the channels */
652 	r = DDI_INTR_UNCLAIMED;
653 	chan = 1;
654 	for (i = 0; i < state->is_num_channels; i++) {
655 		if (intr_status & chan) {
656 			ioat_channel_intr(&state->is_channel[i]);
657 			r = DDI_INTR_CLAIMED;
658 		}
659 		chan = chan << 1;
660 	}
661 
662 	/*
663 	 * if interrupt status bit was set, there should have been an
664 	 * attention status bit set too.
665 	 */
666 	ASSERT(r == DDI_INTR_CLAIMED);
667 
668 	/* re-set master interrupt enable (since it clears on read) */
669 	ddi_put8(state->is_reg_handle, &state->is_genregs[IOAT_INTRCTL],
670 	    intrctrl);
671 
672 	return (r);
673 }
674