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 2013 Nexenta Systems, Inc. All rights reserved.
24 * Copyright 2012 Alexey Zaytsev <alexey.zaytsev@gmail.com>
25 * Copyright (c) 2016 by Delphix. All rights reserved.
26 */
27
28 /* Based on the NetBSD virtio driver by Minoura Makoto. */
29 /*
30 * Copyright (c) 2010 Minoura Makoto.
31 * All rights reserved.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 *
42 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
43 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
967
968 /* Notify all handlers */
969 for (i = 0; i < vhc->nhandlers; i++) {
970 vhc->vq_handlers[i].vh_func((void *)sc,
971 vhc->vq_handlers[i].vh_priv);
972 }
973
974 return (DDI_INTR_CLAIMED);
975 }
976
977 /*
978 * config_handler and vq_handlers may be allocated on stack.
979 * Take precautions not to loose them.
980 */
981 static int
982 virtio_register_intx(struct virtio_softc *sc,
983 struct virtio_int_handler *config_handler,
984 struct virtio_int_handler vq_handlers[])
985 {
986 int vq_handler_count;
987 int config_handler_count = 0;
988 int actual;
989 struct virtio_handler_container *vhc;
990 int ret = DDI_FAILURE;
991
992 /* Walk the handler table to get the number of handlers. */
993 for (vq_handler_count = 0;
994 vq_handlers && vq_handlers[vq_handler_count].vh_func;
995 vq_handler_count++)
996 ;
997
998 if (config_handler != NULL)
999 config_handler_count = 1;
1000
1001 vhc = kmem_zalloc(sizeof (struct virtio_handler_container) +
1002 sizeof (struct virtio_int_handler) * vq_handler_count, KM_SLEEP);
1003
1004 vhc->nhandlers = vq_handler_count;
1005 (void) memcpy(vhc->vq_handlers, vq_handlers,
1006 sizeof (struct virtio_int_handler) * vq_handler_count);
1007
1008 if (config_handler != NULL) {
1009 (void) memcpy(&vhc->config_handler, config_handler,
1010 sizeof (struct virtio_int_handler));
1011 }
1012
1013 /* Just a single entry for a single interrupt. */
1014 sc->sc_intr_htable = kmem_zalloc(sizeof (ddi_intr_handle_t), KM_SLEEP);
1015
1016 ret = ddi_intr_alloc(sc->sc_dev, sc->sc_intr_htable,
1017 DDI_INTR_TYPE_FIXED, 0, 1, &actual, DDI_INTR_ALLOC_NORMAL);
1018 if (ret != DDI_SUCCESS) {
1019 dev_err(sc->sc_dev, CE_WARN,
1020 "Failed to allocate a fixed interrupt: %d", ret);
1021 goto out_int_alloc;
1022 }
1023
1029 dev_err(sc->sc_dev, CE_WARN, "ddi_intr_get_pri failed");
1030 goto out_prio;
1031 }
1032
1033 ret = ddi_intr_add_handler(sc->sc_intr_htable[0],
1034 virtio_intx_dispatch, sc, vhc);
1035 if (ret != DDI_SUCCESS) {
1036 dev_err(sc->sc_dev, CE_WARN, "ddi_intr_add_handler failed");
1037 goto out_add_handlers;
1038 }
1039
1040 sc->sc_int_type = DDI_INTR_TYPE_FIXED;
1041
1042 return (DDI_SUCCESS);
1043
1044 out_add_handlers:
1045 out_prio:
1046 (void) ddi_intr_free(sc->sc_intr_htable[0]);
1047 out_int_alloc:
1048 kmem_free(sc->sc_intr_htable, sizeof (ddi_intr_handle_t));
1049 kmem_free(vhc, sizeof (struct virtio_int_handler) *
1050 (vq_handler_count + config_handler_count));
1051 return (ret);
1052 }
1053
1054 /*
1055 * We find out if we support MSI during this, and the register layout
1056 * depends on the MSI (doh). Don't acces the device specific bits in
1057 * BAR 0 before calling it!
1058 */
1059 int
1060 virtio_register_ints(struct virtio_softc *sc,
1061 struct virtio_int_handler *config_handler,
1062 struct virtio_int_handler vq_handlers[])
1063 {
1064 int ret;
1065 int intr_types;
1066
1067 /* Default offset until MSI-X is enabled, if ever. */
1068 sc->sc_config_offset = VIRTIO_CONFIG_DEVICE_CONFIG_NOMSIX;
1069
1070 /* Determine which types of interrupts are supported */
|
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 2013 Nexenta Systems, Inc. All rights reserved.
14 * Copyright 2012 Alexey Zaytsev <alexey.zaytsev@gmail.com>
15 * Copyright (c) 2016 by Delphix. All rights reserved.
16 * Copyright 2017 Joyent, Inc.
17 */
18
19 /* Based on the NetBSD virtio driver by Minoura Makoto. */
20 /*
21 * Copyright (c) 2010 Minoura Makoto.
22 * All rights reserved.
23 *
24 * Redistribution and use in source and binary forms, with or without
25 * modification, are permitted provided that the following conditions
26 * are met:
27 * 1. Redistributions of source code must retain the above copyright
28 * notice, this list of conditions and the following disclaimer.
29 * 2. Redistributions in binary form must reproduce the above copyright
30 * notice, this list of conditions and the following disclaimer in the
31 * documentation and/or other materials provided with the distribution.
32 *
33 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
34 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
35 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
36 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
958
959 /* Notify all handlers */
960 for (i = 0; i < vhc->nhandlers; i++) {
961 vhc->vq_handlers[i].vh_func((void *)sc,
962 vhc->vq_handlers[i].vh_priv);
963 }
964
965 return (DDI_INTR_CLAIMED);
966 }
967
968 /*
969 * config_handler and vq_handlers may be allocated on stack.
970 * Take precautions not to loose them.
971 */
972 static int
973 virtio_register_intx(struct virtio_softc *sc,
974 struct virtio_int_handler *config_handler,
975 struct virtio_int_handler vq_handlers[])
976 {
977 int vq_handler_count;
978 int actual;
979 struct virtio_handler_container *vhc;
980 size_t vhc_sz;
981 int ret = DDI_FAILURE;
982
983 /* Walk the handler table to get the number of handlers. */
984 for (vq_handler_count = 0;
985 vq_handlers && vq_handlers[vq_handler_count].vh_func;
986 vq_handler_count++)
987 ;
988
989 vhc_sz = sizeof (struct virtio_handler_container) +
990 sizeof (struct virtio_int_handler) * vq_handler_count;
991 vhc = kmem_zalloc(vhc_sz, KM_SLEEP);
992
993 vhc->nhandlers = vq_handler_count;
994 (void) memcpy(vhc->vq_handlers, vq_handlers,
995 sizeof (struct virtio_int_handler) * vq_handler_count);
996
997 if (config_handler != NULL) {
998 (void) memcpy(&vhc->config_handler, config_handler,
999 sizeof (struct virtio_int_handler));
1000 }
1001
1002 /* Just a single entry for a single interrupt. */
1003 sc->sc_intr_htable = kmem_zalloc(sizeof (ddi_intr_handle_t), KM_SLEEP);
1004
1005 ret = ddi_intr_alloc(sc->sc_dev, sc->sc_intr_htable,
1006 DDI_INTR_TYPE_FIXED, 0, 1, &actual, DDI_INTR_ALLOC_NORMAL);
1007 if (ret != DDI_SUCCESS) {
1008 dev_err(sc->sc_dev, CE_WARN,
1009 "Failed to allocate a fixed interrupt: %d", ret);
1010 goto out_int_alloc;
1011 }
1012
1018 dev_err(sc->sc_dev, CE_WARN, "ddi_intr_get_pri failed");
1019 goto out_prio;
1020 }
1021
1022 ret = ddi_intr_add_handler(sc->sc_intr_htable[0],
1023 virtio_intx_dispatch, sc, vhc);
1024 if (ret != DDI_SUCCESS) {
1025 dev_err(sc->sc_dev, CE_WARN, "ddi_intr_add_handler failed");
1026 goto out_add_handlers;
1027 }
1028
1029 sc->sc_int_type = DDI_INTR_TYPE_FIXED;
1030
1031 return (DDI_SUCCESS);
1032
1033 out_add_handlers:
1034 out_prio:
1035 (void) ddi_intr_free(sc->sc_intr_htable[0]);
1036 out_int_alloc:
1037 kmem_free(sc->sc_intr_htable, sizeof (ddi_intr_handle_t));
1038 kmem_free(vhc, vhc_sz);
1039 return (ret);
1040 }
1041
1042 /*
1043 * We find out if we support MSI during this, and the register layout
1044 * depends on the MSI (doh). Don't acces the device specific bits in
1045 * BAR 0 before calling it!
1046 */
1047 int
1048 virtio_register_ints(struct virtio_softc *sc,
1049 struct virtio_int_handler *config_handler,
1050 struct virtio_int_handler vq_handlers[])
1051 {
1052 int ret;
1053 int intr_types;
1054
1055 /* Default offset until MSI-X is enabled, if ever. */
1056 sc->sc_config_offset = VIRTIO_CONFIG_DEVICE_CONFIG_NOMSIX;
1057
1058 /* Determine which types of interrupts are supported */
|