]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/smbus/smbconf.c
Filter TCP connections to SO_REUSEPORT_LB listen sockets by NUMA domain
[FreeBSD/FreeBSD.git] / sys / dev / smbus / smbconf.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 1998, 2001 Nicolas Souchu
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  *
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/lock.h>
36 #include <sys/module.h>
37 #include <sys/mutex.h>
38 #include <sys/bus.h>
39
40 #include <dev/smbus/smbconf.h>
41 #include <dev/smbus/smbus.h>
42 #include "smbus_if.h"
43
44 /*
45  * smbus_intr()
46  */
47 void
48 smbus_intr(device_t bus, u_char devaddr, char low, char high, int error)
49 {
50         struct smbus_softc *sc = device_get_softc(bus);
51
52         /* call owner's intr routine */
53         mtx_lock(&sc->lock);
54         if (sc->owner)
55                 SMBUS_INTR(sc->owner, devaddr, low, high, error);
56         mtx_unlock(&sc->lock);
57 }
58
59 /*
60  * smbus_error()
61  *
62  * Converts an smbus error to a unix error.
63  */
64 int
65 smbus_error(int smb_error)
66 {
67         int error = 0;
68
69         if (smb_error == SMB_ENOERR)
70                 return (0);
71
72         if (smb_error & (SMB_ENOTSUPP))
73                 error = ENODEV;
74         else if (smb_error & (SMB_ENOACK))
75                 error = ENXIO;
76         else if (smb_error & (SMB_ETIMEOUT))
77                 error = EWOULDBLOCK;
78         else if (smb_error & (SMB_EBUSY))
79                 error = EBUSY;
80         else if (smb_error & (SMB_EABORT | SMB_EBUSERR | SMB_ECOLLI))
81                 error = EIO;
82         else
83                 error = EINVAL;
84
85         return (error);
86 }
87
88 static int
89 smbus_poll(struct smbus_softc *sc, int how)
90 {
91         int error;
92
93         switch (how) {
94         case SMB_WAIT | SMB_INTR:               
95                 error = msleep(sc, &sc->lock, SMBPRI|PCATCH, "smbreq", 0);
96                 break;
97
98         case SMB_WAIT | SMB_NOINTR:
99                 error = msleep(sc, &sc->lock, SMBPRI, "smbreq", 0);
100                 break;
101
102         default:
103                 error = EWOULDBLOCK;
104                 break;
105         }
106
107         return (error);
108 }
109
110 /*
111  * smbus_request_bus()
112  *
113  * Allocate the device to perform transfers.
114  *
115  * how  : SMB_WAIT or SMB_DONTWAIT
116  */
117 int
118 smbus_request_bus(device_t bus, device_t dev, int how)
119 {
120         struct smbus_softc *sc = device_get_softc(bus);
121         device_t parent;
122         int error;
123
124         /* first, ask the underlying layers if the request is ok */
125         parent = device_get_parent(bus);
126         mtx_lock(&sc->lock);
127         do {
128                 mtx_unlock(&sc->lock);
129                 error = SMBUS_CALLBACK(parent, SMB_REQUEST_BUS, &how);
130                 mtx_lock(&sc->lock);
131
132                 if (error)
133                         error = smbus_poll(sc, how);
134         } while (error == EWOULDBLOCK);
135
136         while (error == 0) {
137                 if (sc->owner && sc->owner != dev)
138                         error = smbus_poll(sc, how);
139                 else {
140                         sc->owner = dev;
141                         break;
142                 }
143
144                 /* free any allocated resource */
145                 if (error) {
146                         mtx_unlock(&sc->lock);
147                         SMBUS_CALLBACK(parent, SMB_RELEASE_BUS, &how);
148                         return (error);
149                 }
150         }
151         mtx_unlock(&sc->lock);
152
153         return (error);
154 }
155
156 /*
157  * smbus_release_bus()
158  *
159  * Release the device allocated with smbus_request_dev()
160  */
161 int
162 smbus_release_bus(device_t bus, device_t dev)
163 {
164         struct smbus_softc *sc = device_get_softc(bus);
165         int error;
166
167         /* first, ask the underlying layers if the release is ok */
168         error = SMBUS_CALLBACK(device_get_parent(bus), SMB_RELEASE_BUS, NULL);
169
170         if (error)
171                 return (error);
172
173         mtx_lock(&sc->lock);
174         if (sc->owner == dev) {
175                 sc->owner = NULL;
176
177                 /* wakeup waiting processes */
178                 wakeup(sc);
179         } else
180                 error = EACCES;
181         mtx_unlock(&sc->lock);
182
183         return (error);
184 }