View | Details | Raw Unified | Return to bug 201734 | Differences between
and this patch

Collapse All | Expand All

(-)b/sys/dev/etherswitch/miiproxy.c (-57 / +57 lines)
Lines 65-99 struct mdioproxy_softc { Link Here
65
};
65
};
66
66
67
/*
67
/*
68
 * The rendevous data structures and functions allow two device endpoints to
68
 * The rendezvous data structures and functions allow two device endpoints to
69
 * match up, so that the proxy endpoint can be associated with a target
69
 * match up, so that the proxy endpoint can be associated with a target
70
 * endpoint.  The proxy has to know the device name of the target that it
70
 * endpoint.  The proxy has to know the device name of the target that it
71
 * wants to associate with, for example through a hint.  The rendevous code
71
 * wants to associate with, for example through a hint.  The rendezvous code
72
 * makes no assumptions about the devices that want to meet.
72
 * makes no assumptions about the devices that want to meet.
73
 */
73
 */
74
struct rendevous_entry;
74
struct rendezvous_entry;
75
75
76
enum rendevous_op {
76
enum rendezvous_op {
77
	RENDEVOUS_ATTACH,
77
	RENDEZVOUS_ATTACH,
78
	RENDEVOUS_DETACH
78
	RENDEZVOUS_DETACH
79
};
79
};
80
80
81
typedef int (*rendevous_callback_t)(enum rendevous_op,
81
typedef int (*rendezvous_callback_t)(enum rendezvous_op,
82
    struct rendevous_entry *);
82
    struct rendezvous_entry *);
83
83
84
static SLIST_HEAD(rendevoushead, rendevous_entry) rendevoushead =
84
static SLIST_HEAD(rendezvoushead, rendezvous_entry) rendezvoushead =
85
    SLIST_HEAD_INITIALIZER(rendevoushead);
85
    SLIST_HEAD_INITIALIZER(rendezvoushead);
86
86
87
struct rendevous_endpoint {
87
struct rendezvous_endpoint {
88
	device_t		device;
88
	device_t		device;
89
	const char		*name;
89
	const char		*name;
90
	rendevous_callback_t	callback;
90
	rendezvous_callback_t	callback;
91
};
91
};
92
92
93
struct rendevous_entry {
93
struct rendezvous_entry {
94
	SLIST_ENTRY(rendevous_entry)	entries;
94
	SLIST_ENTRY(rendezvous_entry)	entries;
95
	struct rendevous_endpoint	proxy;
95
	struct rendezvous_endpoint	proxy;
96
	struct rendevous_endpoint	target;
96
	struct rendezvous_endpoint	target;
97
};
97
};
98
98
99
/*
99
/*
Lines 101-115 struct rendevous_entry { Link Here
101
 * returns an error, undo the attachment.
101
 * returns an error, undo the attachment.
102
 */
102
 */
103
static int
103
static int
104
rendevous_attach(struct rendevous_entry *e, struct rendevous_endpoint *ep)
104
rendezvous_attach(struct rendezvous_entry *e, struct rendezvous_endpoint *ep)
105
{
105
{
106
	int error;
106
	int error;
107
107
108
	error = e->proxy.callback(RENDEVOUS_ATTACH, e);
108
	error = e->proxy.callback(RENDEZVOUS_ATTACH, e);
109
	if (error == 0) {
109
	if (error == 0) {
110
		error = e->target.callback(RENDEVOUS_ATTACH, e);
110
		error = e->target.callback(RENDEZVOUS_ATTACH, e);
111
		if (error != 0) {
111
		if (error != 0) {
112
			e->proxy.callback(RENDEVOUS_DETACH, e);
112
			e->proxy.callback(RENDEZVOUS_DETACH, e);
113
			ep->device = NULL;
113
			ep->device = NULL;
114
			ep->callback = NULL;
114
			ep->callback = NULL;
115
		}
115
		}
Lines 118-144 rendevous_attach(struct rendevous_entry *e, struct rendevous_endpoint *ep) Link Here
118
}
118
}
119
119
120
/*
120
/*
121
 * Create an entry for the proxy in the rendevous list.  The name parameter
121
 * Create an entry for the proxy in the rendezvous list.  The name parameter
122
 * indicates the name of the device that is the target endpoint for this
122
 * indicates the name of the device that is the target endpoint for this
123
 * rendevous.  The callback will be invoked as soon as the target is
123
 * rendezvous.  The callback will be invoked as soon as the target is
124
 * registered: either immediately if the target registered itself earlier,
124
 * registered: either immediately if the target registered itself earlier,
125
 * or once the target registers.  Returns ENXIO if the target has not yet
125
 * or once the target registers.  Returns ENXIO if the target has not yet
126
 * registered.
126
 * registered.
127
 */
127
 */
128
static int
128
static int
129
rendevous_register_proxy(device_t dev, const char *name,
129
rendezvous_register_proxy(device_t dev, const char *name,
130
    rendevous_callback_t callback)
130
    rendezvous_callback_t callback)
131
{
131
{
132
	struct rendevous_entry *e;
132
	struct rendezvous_entry *e;
133
133
134
	KASSERT(callback != NULL, ("callback must be set"));
134
	KASSERT(callback != NULL, ("callback must be set"));
135
	SLIST_FOREACH(e, &rendevoushead, entries) {
135
	SLIST_FOREACH(e, &rendezvoushead, entries) {
136
		if (strcmp(name, e->target.name) == 0) {
136
		if (strcmp(name, e->target.name) == 0) {
137
			/* the target is already attached */
137
			/* the target is already attached */
138
			e->proxy.name = device_get_nameunit(dev);
138
			e->proxy.name = device_get_nameunit(dev);
139
		    	e->proxy.device = dev;
139
		    	e->proxy.device = dev;
140
		    	e->proxy.callback = callback;
140
		    	e->proxy.callback = callback;
141
			return (rendevous_attach(e, &e->proxy));
141
			return (rendezvous_attach(e, &e->proxy));
142
		}
142
		}
143
	}
143
	}
144
	e = malloc(sizeof(*e), M_MIIPROXY, M_WAITOK | M_ZERO);
144
	e = malloc(sizeof(*e), M_MIIPROXY, M_WAITOK | M_ZERO);
Lines 146-179 rendevous_register_proxy(device_t dev, const char *name, Link Here
146
    	e->proxy.device = dev;
146
    	e->proxy.device = dev;
147
    	e->proxy.callback = callback;
147
    	e->proxy.callback = callback;
148
	e->target.name = name;
148
	e->target.name = name;
149
	SLIST_INSERT_HEAD(&rendevoushead, e, entries);
149
	SLIST_INSERT_HEAD(&rendezvoushead, e, entries);
150
	return (ENXIO);
150
	return (ENXIO);
151
}
151
}
152
152
153
/*
153
/*
154
 * Create an entry in the rendevous list for the target.
154
 * Create an entry in the rendezvous list for the target.
155
 * Returns ENXIO if the proxy has not yet registered.
155
 * Returns ENXIO if the proxy has not yet registered.
156
 */
156
 */
157
static int
157
static int
158
rendevous_register_target(device_t dev, rendevous_callback_t callback)
158
rendezvous_register_target(device_t dev, rendezvous_callback_t callback)
159
{
159
{
160
	struct rendevous_entry *e;
160
	struct rendezvous_entry *e;
161
	const char *name;
161
	const char *name;
162
	
162
	
163
	KASSERT(callback != NULL, ("callback must be set"));
163
	KASSERT(callback != NULL, ("callback must be set"));
164
	name = device_get_nameunit(dev);
164
	name = device_get_nameunit(dev);
165
	SLIST_FOREACH(e, &rendevoushead, entries) {
165
	SLIST_FOREACH(e, &rendezvoushead, entries) {
166
		if (strcmp(name, e->target.name) == 0) {
166
		if (strcmp(name, e->target.name) == 0) {
167
			e->target.device = dev;
167
			e->target.device = dev;
168
			e->target.callback = callback;
168
			e->target.callback = callback;
169
			return (rendevous_attach(e, &e->target));
169
			return (rendezvous_attach(e, &e->target));
170
		}
170
		}
171
	}
171
	}
172
	e = malloc(sizeof(*e), M_MIIPROXY, M_WAITOK | M_ZERO);
172
	e = malloc(sizeof(*e), M_MIIPROXY, M_WAITOK | M_ZERO);
173
	e->target.name = name;
173
	e->target.name = name;
174
    	e->target.device = dev;
174
    	e->target.device = dev;
175
	e->target.callback = callback;
175
	e->target.callback = callback;
176
	SLIST_INSERT_HEAD(&rendevoushead, e, entries);
176
	SLIST_INSERT_HEAD(&rendezvoushead, e, entries);
177
	return (ENXIO);
177
	return (ENXIO);
178
}
178
}
179
179
Lines 181-200 rendevous_register_target(device_t dev, rendevous_callback_t callback) Link Here
181
 * Remove the registration for the proxy.
181
 * Remove the registration for the proxy.
182
 */
182
 */
183
static int
183
static int
184
rendevous_unregister_proxy(device_t dev)
184
rendezvous_unregister_proxy(device_t dev)
185
{
185
{
186
	struct rendevous_entry *e;
186
	struct rendezvous_entry *e;
187
	int error = 0;
187
	int error = 0;
188
	
188
	
189
	SLIST_FOREACH(e, &rendevoushead, entries) {
189
	SLIST_FOREACH(e, &rendezvoushead, entries) {
190
		if (e->proxy.device == dev) {
190
		if (e->proxy.device == dev) {
191
			if (e->target.device == NULL) {
191
			if (e->target.device == NULL) {
192
				SLIST_REMOVE(&rendevoushead, e, rendevous_entry, entries);
192
				SLIST_REMOVE(&rendezvoushead, e, rendezvous_entry, entries);
193
				free(e, M_MIIPROXY);
193
				free(e, M_MIIPROXY);
194
				return (0);
194
				return (0);
195
			} else {
195
			} else {
196
				e->proxy.callback(RENDEVOUS_DETACH, e);
196
				e->proxy.callback(RENDEZVOUS_DETACH, e);
197
				e->target.callback(RENDEVOUS_DETACH, e);
197
				e->target.callback(RENDEZVOUS_DETACH, e);
198
			}
198
			}
199
			e->proxy.device = NULL;
199
			e->proxy.device = NULL;
200
			e->proxy.callback = NULL;
200
			e->proxy.callback = NULL;
Lines 208-227 rendevous_unregister_proxy(device_t dev) Link Here
208
 * Remove the registration for the target.
208
 * Remove the registration for the target.
209
 */
209
 */
210
static int
210
static int
211
rendevous_unregister_target(device_t dev)
211
rendezvous_unregister_target(device_t dev)
212
{
212
{
213
	struct rendevous_entry *e;
213
	struct rendezvous_entry *e;
214
	int error = 0;
214
	int error = 0;
215
	
215
	
216
	SLIST_FOREACH(e, &rendevoushead, entries) {
216
	SLIST_FOREACH(e, &rendezvoushead, entries) {
217
		if (e->target.device == dev) {
217
		if (e->target.device == dev) {
218
			if (e->proxy.device == NULL) {
218
			if (e->proxy.device == NULL) {
219
				SLIST_REMOVE(&rendevoushead, e, rendevous_entry, entries);
219
				SLIST_REMOVE(&rendezvoushead, e, rendezvous_entry, entries);
220
				free(e, M_MIIPROXY);
220
				free(e, M_MIIPROXY);
221
				return (0);
221
				return (0);
222
			} else {
222
			} else {
223
				e->proxy.callback(RENDEVOUS_DETACH, e);
223
				e->proxy.callback(RENDEZVOUS_DETACH, e);
224
				e->target.callback(RENDEVOUS_DETACH, e);
224
				e->target.callback(RENDEZVOUS_DETACH, e);
225
			}
225
			}
226
			e->target.device = NULL;
226
			e->target.device = NULL;
227
			e->target.callback = NULL;
227
			e->target.callback = NULL;
Lines 237-251 rendevous_unregister_target(device_t dev) Link Here
237
 */
237
 */
238
238
239
static int
239
static int
240
miiproxy_rendevous_callback(enum rendevous_op op, struct rendevous_entry *rendevous)
240
miiproxy_rendezvous_callback(enum rendezvous_op op, struct rendezvous_entry *rendezvous)
241
{
241
{
242
	struct miiproxy_softc *sc = device_get_softc(rendevous->proxy.device);
242
	struct miiproxy_softc *sc = device_get_softc(rendezvous->proxy.device);
243
243
244
	switch (op) {
244
	switch (op) {
245
	case RENDEVOUS_ATTACH:
245
	case RENDEZVOUS_ATTACH:
246
		sc->mdio = device_get_parent(rendevous->target.device);
246
		sc->mdio = device_get_parent(rendezvous->target.device);
247
		break;
247
		break;
248
	case RENDEVOUS_DETACH:
248
	case RENDEZVOUS_DETACH:
249
		sc->mdio = NULL;
249
		sc->mdio = NULL;
250
		break;
250
		break;
251
	}
251
	}
Lines 266-272 miiproxy_attach(device_t dev) Link Here
266
266
267
	/*
267
	/*
268
	 * The ethernet interface needs to call mii_attach_proxy() to pass
268
	 * The ethernet interface needs to call mii_attach_proxy() to pass
269
	 * the relevant parameters for rendevous with the MDIO target.
269
	 * the relevant parameters for rendezvous with the MDIO target.
270
	 */
270
	 */
271
	return (bus_generic_attach(dev));
271
	return (bus_generic_attach(dev));
272
}
272
}
Lines 275-281 static int Link Here
275
miiproxy_detach(device_t dev)
275
miiproxy_detach(device_t dev)
276
{
276
{
277
277
278
	rendevous_unregister_proxy(dev);
278
	rendezvous_unregister_proxy(dev);
279
	bus_generic_detach(dev);
279
	bus_generic_detach(dev);
280
	return (0);
280
	return (0);
281
}
281
}
Lines 325-331 miiproxy_mediainit(device_t dev) Link Here
325
 * Functions for the MDIO target device driver.
325
 * Functions for the MDIO target device driver.
326
 */
326
 */
327
static int
327
static int
328
mdioproxy_rendevous_callback(enum rendevous_op op, struct rendevous_entry *rendevous)
328
mdioproxy_rendezvous_callback(enum rendezvous_op op, struct rendezvous_entry *rendezvous)
329
{
329
{
330
	return (0);
330
	return (0);
331
}
331
}
Lines 352-358 static int Link Here
352
mdioproxy_attach(device_t dev)
352
mdioproxy_attach(device_t dev)
353
{
353
{
354
354
355
	rendevous_register_target(dev, mdioproxy_rendevous_callback);
355
	rendezvous_register_target(dev, mdioproxy_rendezvous_callback);
356
	return (bus_generic_attach(dev));
356
	return (bus_generic_attach(dev));
357
}
357
}
358
358
Lines 360-366 static int Link Here
360
mdioproxy_detach(device_t dev)
360
mdioproxy_detach(device_t dev)
361
{
361
{
362
362
363
	rendevous_unregister_target(dev);
363
	rendezvous_unregister_target(dev);
364
	bus_generic_detach(dev);
364
	bus_generic_detach(dev);
365
	return (0);
365
	return (0);
366
}
366
}
Lines 394-400 mii_attach_proxy(device_t dev) Link Here
394
	sc = device_get_softc(miiproxy);
394
	sc = device_get_softc(miiproxy);
395
	sc->parent = dev;
395
	sc->parent = dev;
396
	sc->proxy = miiproxy;
396
	sc->proxy = miiproxy;
397
	if (rendevous_register_proxy(miiproxy, name, miiproxy_rendevous_callback) != 0) {
397
	if (rendezvous_register_proxy(miiproxy, name, miiproxy_rendezvous_callback) != 0) {
398
		device_printf(dev, "can't attach proxy\n");
398
		device_printf(dev, "can't attach proxy\n");
399
		return (NULL);
399
		return (NULL);
400
	}
400
	}

Return to bug 201734