1*3af888c1Sjakllsch /* $NetBSD: dmover_backend.c,v 1.9 2011/05/14 18:24:47 jakllsch Exp $ */
25d06c0e8Sthorpej
35d06c0e8Sthorpej /*
45d06c0e8Sthorpej * Copyright (c) 2002 Wasabi Systems, Inc.
55d06c0e8Sthorpej * All rights reserved.
65d06c0e8Sthorpej *
75d06c0e8Sthorpej * Written by Jason R. Thorpe for Wasabi Systems, Inc.
85d06c0e8Sthorpej *
95d06c0e8Sthorpej * Redistribution and use in source and binary forms, with or without
105d06c0e8Sthorpej * modification, are permitted provided that the following conditions
115d06c0e8Sthorpej * are met:
125d06c0e8Sthorpej * 1. Redistributions of source code must retain the above copyright
135d06c0e8Sthorpej * notice, this list of conditions and the following disclaimer.
145d06c0e8Sthorpej * 2. Redistributions in binary form must reproduce the above copyright
155d06c0e8Sthorpej * notice, this list of conditions and the following disclaimer in the
165d06c0e8Sthorpej * documentation and/or other materials provided with the distribution.
175d06c0e8Sthorpej * 3. All advertising materials mentioning features or use of this software
185d06c0e8Sthorpej * must display the following acknowledgement:
195d06c0e8Sthorpej * This product includes software developed for the NetBSD Project by
205d06c0e8Sthorpej * Wasabi Systems, Inc.
215d06c0e8Sthorpej * 4. The name of Wasabi Systems, Inc. may not be used to endorse
225d06c0e8Sthorpej * or promote products derived from this software without specific prior
235d06c0e8Sthorpej * written permission.
245d06c0e8Sthorpej *
255d06c0e8Sthorpej * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
265d06c0e8Sthorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
275d06c0e8Sthorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
285d06c0e8Sthorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
295d06c0e8Sthorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
305d06c0e8Sthorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
315d06c0e8Sthorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
325d06c0e8Sthorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
335d06c0e8Sthorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
345d06c0e8Sthorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
355d06c0e8Sthorpej * POSSIBILITY OF SUCH DAMAGE.
365d06c0e8Sthorpej */
375d06c0e8Sthorpej
385d06c0e8Sthorpej /*
395d06c0e8Sthorpej * dmover_backend.c: Backend management functions for dmover-api.
405d06c0e8Sthorpej */
415d06c0e8Sthorpej
425d06c0e8Sthorpej #include <sys/cdefs.h>
43*3af888c1Sjakllsch __KERNEL_RCSID(0, "$NetBSD: dmover_backend.c,v 1.9 2011/05/14 18:24:47 jakllsch Exp $");
445d06c0e8Sthorpej
455d06c0e8Sthorpej #include <sys/param.h>
4688ab7da9Sad #include <sys/mutex.h>
475d06c0e8Sthorpej #include <sys/systm.h>
48*3af888c1Sjakllsch #include <sys/once.h>
495d06c0e8Sthorpej
505d06c0e8Sthorpej #include <dev/dmover/dmovervar.h>
515d06c0e8Sthorpej
525d06c0e8Sthorpej TAILQ_HEAD(, dmover_backend) dmover_backend_list;
5388ab7da9Sad kmutex_t dmover_backend_list_lock;
54*3af888c1Sjakllsch static bool initialized;
555d06c0e8Sthorpej
56*3af888c1Sjakllsch static int
initialize(void)575d06c0e8Sthorpej initialize(void)
585d06c0e8Sthorpej {
595d06c0e8Sthorpej
60*3af888c1Sjakllsch KASSERT(initialized == false);
61*3af888c1Sjakllsch
625d06c0e8Sthorpej TAILQ_INIT(&dmover_backend_list);
63598ab03aSad mutex_init(&dmover_backend_list_lock, MUTEX_DEFAULT, IPL_VM);
645d06c0e8Sthorpej
655d06c0e8Sthorpej /* Initialize the other bits of dmover. */
665d06c0e8Sthorpej dmover_session_initialize();
675d06c0e8Sthorpej dmover_request_initialize();
685d06c0e8Sthorpej dmover_process_initialize();
695d06c0e8Sthorpej
70*3af888c1Sjakllsch initialized = true;
71*3af888c1Sjakllsch
72*3af888c1Sjakllsch return 0;
735d06c0e8Sthorpej }
745d06c0e8Sthorpej
755d06c0e8Sthorpej /*
765d06c0e8Sthorpej * dmover_backend_register: [back-end interface function]
775d06c0e8Sthorpej *
785d06c0e8Sthorpej * Register a back-end with dmover-api.
795d06c0e8Sthorpej */
805d06c0e8Sthorpej void
dmover_backend_register(struct dmover_backend * dmb)815d06c0e8Sthorpej dmover_backend_register(struct dmover_backend *dmb)
825d06c0e8Sthorpej {
83*3af888c1Sjakllsch static ONCE_DECL(control);
845d06c0e8Sthorpej
85*3af888c1Sjakllsch RUN_ONCE(&control, initialize);
86*3af888c1Sjakllsch
87*3af888c1Sjakllsch KASSERT(initialized == true);
885d06c0e8Sthorpej
895d06c0e8Sthorpej LIST_INIT(&dmb->dmb_sessions);
905d06c0e8Sthorpej dmb->dmb_nsessions = 0;
915d06c0e8Sthorpej
925d06c0e8Sthorpej TAILQ_INIT(&dmb->dmb_pendreqs);
935d06c0e8Sthorpej dmb->dmb_npendreqs = 0;
945d06c0e8Sthorpej
9588ab7da9Sad mutex_enter(&dmover_backend_list_lock);
965d06c0e8Sthorpej TAILQ_INSERT_TAIL(&dmover_backend_list, dmb, dmb_list);
9788ab7da9Sad mutex_exit(&dmover_backend_list_lock);
985d06c0e8Sthorpej }
995d06c0e8Sthorpej
1005d06c0e8Sthorpej /*
1015d06c0e8Sthorpej * dmover_backend_unregister: [back-end interface function]
1025d06c0e8Sthorpej *
1035d06c0e8Sthorpej * Un-register a back-end from dmover-api.
1045d06c0e8Sthorpej */
1055d06c0e8Sthorpej void
dmover_backend_unregister(struct dmover_backend * dmb)1065d06c0e8Sthorpej dmover_backend_unregister(struct dmover_backend *dmb)
1075d06c0e8Sthorpej {
1085d06c0e8Sthorpej
109*3af888c1Sjakllsch KASSERT(initialized == true);
1105d06c0e8Sthorpej
1115d06c0e8Sthorpej /* XXX */
1125d06c0e8Sthorpej if (dmb->dmb_nsessions)
1135d06c0e8Sthorpej panic("dmover_backend_unregister");
1145d06c0e8Sthorpej
11588ab7da9Sad mutex_enter(&dmover_backend_list_lock);
1165d06c0e8Sthorpej TAILQ_REMOVE(&dmover_backend_list, dmb, dmb_list);
11788ab7da9Sad mutex_exit(&dmover_backend_list_lock);
1185d06c0e8Sthorpej }
1195d06c0e8Sthorpej
1205d06c0e8Sthorpej /*
1215d06c0e8Sthorpej * dmover_backend_alloc:
1225d06c0e8Sthorpej *
1235d06c0e8Sthorpej * Allocate and return a back-end on behalf of a session.
1245d06c0e8Sthorpej */
1255d06c0e8Sthorpej int
dmover_backend_alloc(struct dmover_session * dses,const char * type)1265d06c0e8Sthorpej dmover_backend_alloc(struct dmover_session *dses, const char *type)
1275d06c0e8Sthorpej {
1285d06c0e8Sthorpej struct dmover_backend *dmb, *best_dmb = NULL;
1295d06c0e8Sthorpej const struct dmover_algdesc *algdesc, *best_algdesc = NULL;
1305d06c0e8Sthorpej
131*3af888c1Sjakllsch if (__predict_false(initialized == false)) {
1325d06c0e8Sthorpej return (ESRCH);
1335d06c0e8Sthorpej }
1345d06c0e8Sthorpej
13588ab7da9Sad mutex_enter(&dmover_backend_list_lock);
1365d06c0e8Sthorpej
1375d06c0e8Sthorpej /* First, find a back-end that can handle the session parts. */
1385d06c0e8Sthorpej for (dmb = TAILQ_FIRST(&dmover_backend_list); dmb != NULL;
1395d06c0e8Sthorpej dmb = TAILQ_NEXT(dmb, dmb_list)) {
1405d06c0e8Sthorpej /*
1415d06c0e8Sthorpej * First, check to see if the back-end supports the
1425d06c0e8Sthorpej * function we wish to perform.
1435d06c0e8Sthorpej */
1445d06c0e8Sthorpej algdesc = dmover_algdesc_lookup(dmb->dmb_algdescs,
1455d06c0e8Sthorpej dmb->dmb_nalgdescs, type);
1465d06c0e8Sthorpej if (algdesc == NULL)
1475d06c0e8Sthorpej continue;
1485d06c0e8Sthorpej
1495d06c0e8Sthorpej if (best_dmb == NULL) {
1505d06c0e8Sthorpej best_dmb = dmb;
1515d06c0e8Sthorpej best_algdesc = algdesc;
1525d06c0e8Sthorpej continue;
1535d06c0e8Sthorpej }
1545d06c0e8Sthorpej
1555d06c0e8Sthorpej /*
1565d06c0e8Sthorpej * XXX All the stuff from here on should be shot in
1575d06c0e8Sthorpej * XXX the head. Instead, we should build a list
1585d06c0e8Sthorpej * XXX of candidates, and select the best back-end
1595d06c0e8Sthorpej * XXX when a request is scheduled for processing.
1605d06c0e8Sthorpej */
1615d06c0e8Sthorpej
1625d06c0e8Sthorpej if (dmb->dmb_speed >= best_dmb->dmb_speed) {
1635d06c0e8Sthorpej /*
1645d06c0e8Sthorpej * If the current best match is slower than
1655d06c0e8Sthorpej * this back-end, then this one is the new
1665d06c0e8Sthorpej * best match.
1675d06c0e8Sthorpej */
1685d06c0e8Sthorpej if (dmb->dmb_speed > best_dmb->dmb_speed) {
1695d06c0e8Sthorpej best_dmb = dmb;
1705d06c0e8Sthorpej best_algdesc = algdesc;
1715d06c0e8Sthorpej continue;
1725d06c0e8Sthorpej }
1735d06c0e8Sthorpej
1745d06c0e8Sthorpej /*
1755d06c0e8Sthorpej * If this back-end has fewer sessions allocated
1765d06c0e8Sthorpej * to it than the current best match, then this
1775d06c0e8Sthorpej * one is now the best match.
1785d06c0e8Sthorpej */
1795d06c0e8Sthorpej if (best_dmb->dmb_nsessions > dmb->dmb_nsessions) {
1805d06c0e8Sthorpej best_dmb = dmb;
1815d06c0e8Sthorpej best_algdesc = algdesc;
1825d06c0e8Sthorpej continue;
1835d06c0e8Sthorpej }
1845d06c0e8Sthorpej }
1855d06c0e8Sthorpej }
1865d06c0e8Sthorpej if (best_dmb == NULL) {
18788ab7da9Sad mutex_exit(&dmover_backend_list_lock);
1885d06c0e8Sthorpej return (ESRCH);
1895d06c0e8Sthorpej }
1905d06c0e8Sthorpej
1915d06c0e8Sthorpej KASSERT(best_algdesc != NULL);
1925d06c0e8Sthorpej
1935d06c0e8Sthorpej /* Plug the back-end into the static (XXX) assignment. */
1945d06c0e8Sthorpej dses->__dses_assignment.das_backend = best_dmb;
1955d06c0e8Sthorpej dses->__dses_assignment.das_algdesc = best_algdesc;
1965d06c0e8Sthorpej
1974c104c6cSbriggs dses->dses_ninputs = best_algdesc->dad_ninputs;
1985d06c0e8Sthorpej
1995d06c0e8Sthorpej LIST_INSERT_HEAD(&best_dmb->dmb_sessions, dses, __dses_list);
2005d06c0e8Sthorpej best_dmb->dmb_nsessions++;
2015d06c0e8Sthorpej
20288ab7da9Sad mutex_exit(&dmover_backend_list_lock);
2035d06c0e8Sthorpej
2045d06c0e8Sthorpej return (0);
2055d06c0e8Sthorpej }
2065d06c0e8Sthorpej
2075d06c0e8Sthorpej /*
2085d06c0e8Sthorpej * dmover_backend_release:
2095d06c0e8Sthorpej *
2105d06c0e8Sthorpej * Release the back-end from the specified session.
2115d06c0e8Sthorpej */
2125d06c0e8Sthorpej void
dmover_backend_release(struct dmover_session * dses)2135d06c0e8Sthorpej dmover_backend_release(struct dmover_session *dses)
2145d06c0e8Sthorpej {
2155d06c0e8Sthorpej struct dmover_backend *dmb;
2165d06c0e8Sthorpej
21788ab7da9Sad mutex_enter(&dmover_backend_list_lock);
2185d06c0e8Sthorpej
2195d06c0e8Sthorpej /* XXX Clear out the static assignment. */
2205d06c0e8Sthorpej dmb = dses->__dses_assignment.das_backend;
2215d06c0e8Sthorpej dses->__dses_assignment.das_backend = NULL;
2225d06c0e8Sthorpej dses->__dses_assignment.das_algdesc = NULL;
2235d06c0e8Sthorpej
2245d06c0e8Sthorpej LIST_REMOVE(dses, __dses_list);
2255d06c0e8Sthorpej dmb->dmb_nsessions--;
2265d06c0e8Sthorpej
22788ab7da9Sad mutex_exit(&dmover_backend_list_lock);
2285d06c0e8Sthorpej }
229