mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-04 16:15:11 +00:00
staging: visoruislib driver used to handle requests from virtpci
The visoruislib module is a support library, used to handle requests from virtpci. Signed-off-by: Ken Cox <jkc@redhat.com> Cc: Ben Romer <sparmaintainer@unisys.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
7b2a2d8383
commit
bac8a4d5d2
9 changed files with 3195 additions and 1 deletions
|
@ -13,5 +13,6 @@ source "drivers/staging/unisys/visorutil/Kconfig"
|
||||||
source "drivers/staging/unisys/visorchannel/Kconfig"
|
source "drivers/staging/unisys/visorchannel/Kconfig"
|
||||||
source "drivers/staging/unisys/visorchipset/Kconfig"
|
source "drivers/staging/unisys/visorchipset/Kconfig"
|
||||||
source "drivers/staging/unisys/channels/Kconfig"
|
source "drivers/staging/unisys/channels/Kconfig"
|
||||||
|
source "drivers/staging/unisys/uislib/Kconfig"
|
||||||
|
|
||||||
endif # UNISYSSPAR
|
endif # UNISYSSPAR
|
||||||
|
|
|
@ -5,4 +5,4 @@ obj-$(CONFIG_UNISYS_VISORUTIL) += visorutil/
|
||||||
obj-$(CONFIG_UNISYS_VISORCHANNEL) += visorchannel/
|
obj-$(CONFIG_UNISYS_VISORCHANNEL) += visorchannel/
|
||||||
obj-$(CONFIG_UNISYS_VISORCHIPSET) += visorchipset/
|
obj-$(CONFIG_UNISYS_VISORCHIPSET) += visorchipset/
|
||||||
obj-$(CONFIG_UNISYS_CHANNELSTUB) += channels/
|
obj-$(CONFIG_UNISYS_CHANNELSTUB) += channels/
|
||||||
|
obj-$(CONFIG_UNISYS_UISLIB) += uislib/
|
||||||
|
|
30
drivers/staging/unisys/include/sparstop.h
Normal file
30
drivers/staging/unisys/include/sparstop.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/* sparstop.h
|
||||||
|
*
|
||||||
|
* Copyright © 2010 - 2013 UNISYS CORPORATION
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||||
|
* NON INFRINGEMENT. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SPARSTOP_H__
|
||||||
|
#define __SPARSTOP_H__
|
||||||
|
|
||||||
|
#include "timskmod.h"
|
||||||
|
#include "version.h"
|
||||||
|
#include <linux/ctype.h>
|
||||||
|
|
||||||
|
typedef void (*SPARSTOP_COMPLETE_FUNC) (void *context, int status);
|
||||||
|
|
||||||
|
int sp_stop(void *context, SPARSTOP_COMPLETE_FUNC get_complete_func);
|
||||||
|
void test_remove_stop_device(void);
|
||||||
|
|
||||||
|
#endif
|
10
drivers/staging/unisys/uislib/Kconfig
Normal file
10
drivers/staging/unisys/uislib/Kconfig
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#
|
||||||
|
# Unisys uislib configuration
|
||||||
|
#
|
||||||
|
|
||||||
|
config UNISYS_UISLIB
|
||||||
|
tristate "Unisys uislib driver"
|
||||||
|
depends on UNISYSSPAR && UNISYS_VISORCHIPSET && UNISYS_CHANNELSTUB
|
||||||
|
---help---
|
||||||
|
If you say Y here, you will enable the Unisys uislib driver.
|
||||||
|
|
17
drivers/staging/unisys/uislib/Makefile
Normal file
17
drivers/staging/unisys/uislib/Makefile
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#
|
||||||
|
# Makefile for Unisys uislib
|
||||||
|
#
|
||||||
|
|
||||||
|
obj-$(CONFIG_UNISYS_UISLIB) += visoruislib.o
|
||||||
|
|
||||||
|
visoruislib-y := uislib.o uisqueue.o uisthread.o uisutils.o
|
||||||
|
|
||||||
|
ccflags-y += -Idrivers/staging/unisys/include
|
||||||
|
ccflags-y += -Idrivers/staging/unisys/channels
|
||||||
|
ccflags-y += -Idrivers/staging/unisys/visorchipset
|
||||||
|
ccflags-y += -Idrivers/staging/unisys/sparstopdriver
|
||||||
|
ccflags-y += -Idrivers/staging/unisys/common-spar/include
|
||||||
|
ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels
|
||||||
|
|
||||||
|
ccflags-y += -DCONFIG_SPAR_GUEST -DGUESTDRIVERBUILD -DNOAUTOVERSION
|
||||||
|
|
2536
drivers/staging/unisys/uislib/uislib.c
Normal file
2536
drivers/staging/unisys/uislib/uislib.c
Normal file
File diff suppressed because it is too large
Load diff
166
drivers/staging/unisys/uislib/uisqueue.c
Normal file
166
drivers/staging/unisys/uislib/uisqueue.c
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
/* uisqueue.c
|
||||||
|
*
|
||||||
|
* Copyright © 2010 - 2013 UNISYS CORPORATION
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||||
|
* NON INFRINGEMENT. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* @ALL_INSPECTED */
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
|
||||||
|
#include "uisutils.h"
|
||||||
|
|
||||||
|
#include "chanstub.h"
|
||||||
|
|
||||||
|
/* this is shorter than using __FILE__ (full path name) in
|
||||||
|
* debug/info/error messages */
|
||||||
|
#define CURRENT_FILE_PC UISLIB_PC_uisqueue_c
|
||||||
|
#define __MYFILE__ "uisqueue.c"
|
||||||
|
|
||||||
|
#define RETVOID do { goto Away; } while (0)
|
||||||
|
#define RETINT(x) do { rc = (x); goto Away; } while (0)
|
||||||
|
#define RETPTR(x) do { rc = (x); goto Away; } while (0)
|
||||||
|
#define RETBOOL(x) do { rc = (x); goto Away; } while (0)
|
||||||
|
|
||||||
|
#define CHECK_CACHE_ALIGN 0
|
||||||
|
|
||||||
|
/*****************************************************/
|
||||||
|
/* Exported functions */
|
||||||
|
/*****************************************************/
|
||||||
|
unsigned long long
|
||||||
|
uisqueue_InterlockedOr(volatile unsigned long long *Target,
|
||||||
|
unsigned long long Set)
|
||||||
|
{
|
||||||
|
unsigned long long i;
|
||||||
|
unsigned long long j;
|
||||||
|
|
||||||
|
j = *Target;
|
||||||
|
do {
|
||||||
|
i = j;
|
||||||
|
j = uislibcmpxchg64((unsigned long long *) Target,
|
||||||
|
i, i | Set, sizeof(*(Target)));
|
||||||
|
|
||||||
|
} while (i != j);
|
||||||
|
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(uisqueue_InterlockedOr);
|
||||||
|
|
||||||
|
unsigned long long
|
||||||
|
uisqueue_InterlockedAnd(volatile unsigned long long *Target,
|
||||||
|
unsigned long long Set)
|
||||||
|
{
|
||||||
|
unsigned long long i;
|
||||||
|
unsigned long long j;
|
||||||
|
|
||||||
|
j = *Target;
|
||||||
|
do {
|
||||||
|
i = j;
|
||||||
|
j = uislibcmpxchg64((unsigned long long *) Target,
|
||||||
|
i, i & Set, sizeof(*(Target)));
|
||||||
|
|
||||||
|
} while (i != j);
|
||||||
|
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(uisqueue_InterlockedAnd);
|
||||||
|
|
||||||
|
static U8
|
||||||
|
do_locked_client_insert(struct uisqueue_info *queueinfo,
|
||||||
|
unsigned int whichqueue,
|
||||||
|
void *pSignal,
|
||||||
|
spinlock_t *lock,
|
||||||
|
unsigned char issueInterruptIfEmpty,
|
||||||
|
U64 interruptHandle, U8 *channelId)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
unsigned char queueWasEmpty;
|
||||||
|
unsigned int locked = 0;
|
||||||
|
unsigned int acquired = 0;
|
||||||
|
U8 rc = 0;
|
||||||
|
|
||||||
|
spin_lock_irqsave(lock, flags);
|
||||||
|
locked = 1;
|
||||||
|
|
||||||
|
if (!ULTRA_CHANNEL_CLIENT_ACQUIRE_OS(queueinfo->chan, channelId, NULL))
|
||||||
|
RETINT(0);
|
||||||
|
|
||||||
|
acquired = 1;
|
||||||
|
|
||||||
|
queueWasEmpty = SignalQueueIsEmpty(queueinfo->chan, whichqueue);
|
||||||
|
if (!SignalInsert(queueinfo->chan, whichqueue, pSignal))
|
||||||
|
RETINT(0);
|
||||||
|
ULTRA_CHANNEL_CLIENT_RELEASE_OS(queueinfo->chan, channelId, NULL);
|
||||||
|
acquired = 0;
|
||||||
|
spin_unlock_irqrestore(lock, flags);
|
||||||
|
locked = 0;
|
||||||
|
|
||||||
|
queueinfo->packets_sent++;
|
||||||
|
|
||||||
|
RETINT(1);
|
||||||
|
|
||||||
|
Away:
|
||||||
|
if (acquired) {
|
||||||
|
ULTRA_CHANNEL_CLIENT_RELEASE_OS(queueinfo->chan, channelId,
|
||||||
|
NULL);
|
||||||
|
acquired = 0;
|
||||||
|
}
|
||||||
|
if (locked) {
|
||||||
|
spin_unlock_irqrestore((spinlock_t *) lock, flags);
|
||||||
|
locked = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
uisqueue_put_cmdrsp_with_lock_client(struct uisqueue_info *queueinfo,
|
||||||
|
struct uiscmdrsp *cmdrsp,
|
||||||
|
unsigned int whichqueue,
|
||||||
|
void *insertlock,
|
||||||
|
unsigned char issueInterruptIfEmpty,
|
||||||
|
U64 interruptHandle,
|
||||||
|
char oktowait, U8 *channelId)
|
||||||
|
{
|
||||||
|
while (!do_locked_client_insert(queueinfo, whichqueue, cmdrsp,
|
||||||
|
(spinlock_t *) insertlock,
|
||||||
|
issueInterruptIfEmpty,
|
||||||
|
interruptHandle, channelId)) {
|
||||||
|
if (oktowait != OK_TO_WAIT) {
|
||||||
|
LOGERR("****FAILED SignalInsert failed; cannot wait; insert aborted\n");
|
||||||
|
return 0; /* failed to queue */
|
||||||
|
}
|
||||||
|
/* try again */
|
||||||
|
LOGERR("****FAILED SignalInsert failed; waiting to try again\n");
|
||||||
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
|
schedule_timeout(msecs_to_jiffies(10));
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(uisqueue_put_cmdrsp_with_lock_client);
|
||||||
|
|
||||||
|
/* uisqueue_get_cmdrsp gets the cmdrsp entry at the head of the queue
|
||||||
|
* returns NULL if queue is empty */
|
||||||
|
int
|
||||||
|
uisqueue_get_cmdrsp(struct uisqueue_info *queueinfo,
|
||||||
|
void *cmdrsp, unsigned int whichqueue)
|
||||||
|
{
|
||||||
|
if (!SignalRemove(queueinfo->chan, whichqueue, cmdrsp))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
queueinfo->packets_received++;
|
||||||
|
|
||||||
|
return 1; /* Success */
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(uisqueue_get_cmdrsp);
|
85
drivers/staging/unisys/uislib/uisthread.c
Normal file
85
drivers/staging/unisys/uislib/uisthread.c
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
/* uisthread.c
|
||||||
|
*
|
||||||
|
* Copyright © 2010 - 2013 UNISYS CORPORATION
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||||
|
* NON INFRINGEMENT. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* @ALL_INSPECTED */
|
||||||
|
#include <asm/processor.h>
|
||||||
|
#include <linux/signal.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/kthread.h>
|
||||||
|
#include "uniklog.h"
|
||||||
|
#include "uisutils.h"
|
||||||
|
#include "uisthread.h"
|
||||||
|
|
||||||
|
#define KILL(a, b, c) kill_pid(find_vpid(a), b, c)
|
||||||
|
|
||||||
|
/* this is shorter than using __FILE__ (full path name) in
|
||||||
|
* debug/info/error messages
|
||||||
|
*/
|
||||||
|
#define CURRENT_FILE_PC UISLIB_PC_uisthread_c
|
||||||
|
#define __MYFILE__ "uisthread.c"
|
||||||
|
|
||||||
|
/*****************************************************/
|
||||||
|
/* Exported functions */
|
||||||
|
/*****************************************************/
|
||||||
|
|
||||||
|
/* returns 0 for failure, 1 for success */
|
||||||
|
int
|
||||||
|
uisthread_start(struct uisthread_info *thrinfo,
|
||||||
|
int (*threadfn)(void *), void *thrcontext, char *name)
|
||||||
|
{
|
||||||
|
thrinfo->should_stop = 0;
|
||||||
|
/* used to stop the thread */
|
||||||
|
init_completion(&thrinfo->has_stopped);
|
||||||
|
thrinfo->task = kthread_create(threadfn, thrcontext, name, NULL);
|
||||||
|
if (thrinfo->task == NULL) {
|
||||||
|
thrinfo->id = 0;
|
||||||
|
return 0; /* failure */
|
||||||
|
}
|
||||||
|
thrinfo->id = thrinfo->task->pid;
|
||||||
|
wake_up_process(thrinfo->task);
|
||||||
|
LOGINF("started thread pid:%d\n", thrinfo->id);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(uisthread_start);
|
||||||
|
|
||||||
|
void
|
||||||
|
uisthread_stop(struct uisthread_info *thrinfo)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int stopped = 0;
|
||||||
|
if (thrinfo->id == 0)
|
||||||
|
return; /* thread not running */
|
||||||
|
|
||||||
|
LOGINF("uisthread_stop stopping id:%d\n", thrinfo->id);
|
||||||
|
thrinfo->should_stop = 1;
|
||||||
|
ret = KILL(thrinfo->id, SIGHUP, 1);
|
||||||
|
if (ret) {
|
||||||
|
LOGERR("unable to signal thread %d\n", ret);
|
||||||
|
} else {
|
||||||
|
/* give up if the thread has NOT died in 1 minute */
|
||||||
|
if (wait_for_completion_timeout(&thrinfo->has_stopped, 60 * HZ))
|
||||||
|
stopped = 1;
|
||||||
|
else
|
||||||
|
LOGERR("timed out trying to signal thread\n");
|
||||||
|
}
|
||||||
|
if (stopped) {
|
||||||
|
LOGINF("uisthread_stop stopped id:%d\n", thrinfo->id);
|
||||||
|
thrinfo->id = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(uisthread_stop);
|
349
drivers/staging/unisys/uislib/uisutils.c
Normal file
349
drivers/staging/unisys/uislib/uisutils.c
Normal file
|
@ -0,0 +1,349 @@
|
||||||
|
/* uisutils.c
|
||||||
|
*
|
||||||
|
* Copyright © 2010 - 2013 UNISYS CORPORATION
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||||
|
* NON INFRINGEMENT. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <commontypes.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/list.h>
|
||||||
|
#include "uniklog.h"
|
||||||
|
#include "uisutils.h"
|
||||||
|
#include "version.h"
|
||||||
|
#include "vbushelper.h"
|
||||||
|
#include "guidutils.h"
|
||||||
|
#include <linux/skbuff.h>
|
||||||
|
#ifdef CONFIG_HIGHMEM
|
||||||
|
#include <linux/highmem.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* this is shorter than using __FILE__ (full path name) in
|
||||||
|
* debug/info/error messages
|
||||||
|
*/
|
||||||
|
#define CURRENT_FILE_PC UISLIB_PC_uisutils_c
|
||||||
|
#define __MYFILE__ "uisutils.c"
|
||||||
|
|
||||||
|
/* exports */
|
||||||
|
atomic_t UisUtils_Registered_Services = ATOMIC_INIT(0);
|
||||||
|
/* num registrations via
|
||||||
|
* uisctrl_register_req_handler() or
|
||||||
|
* uisctrl_register_req_handler_ex() */
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************/
|
||||||
|
/* Utility functions */
|
||||||
|
/*****************************************************/
|
||||||
|
|
||||||
|
int
|
||||||
|
util_add_proc_line_ex(int *total, char **buffer, int *buffer_remaining,
|
||||||
|
char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
DBGINF("buffer = 0x%p : *buffer = 0x%p.\n", buffer, *buffer);
|
||||||
|
va_start(args, format);
|
||||||
|
len = vsnprintf(*buffer, *buffer_remaining, format, args);
|
||||||
|
if (len >= *buffer_remaining) {
|
||||||
|
*buffer += *buffer_remaining;
|
||||||
|
*total += *buffer_remaining;
|
||||||
|
*buffer_remaining = 0;
|
||||||
|
LOGERR("bytes remaining is too small!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*buffer_remaining -= len;
|
||||||
|
*buffer += len;
|
||||||
|
*total += len;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(util_add_proc_line_ex);
|
||||||
|
|
||||||
|
int
|
||||||
|
uisctrl_register_req_handler(int type, void *fptr,
|
||||||
|
ULTRA_VBUS_DEVICEINFO *chipset_DriverInfo)
|
||||||
|
{
|
||||||
|
LOGINF("type = %d, fptr = 0x%p.\n", type, fptr);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 2:
|
||||||
|
if (fptr) {
|
||||||
|
if (!VirtControlChanFunc)
|
||||||
|
atomic_inc(&UisUtils_Registered_Services);
|
||||||
|
VirtControlChanFunc = fptr;
|
||||||
|
} else {
|
||||||
|
if (VirtControlChanFunc)
|
||||||
|
atomic_dec(&UisUtils_Registered_Services);
|
||||||
|
VirtControlChanFunc = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
LOGERR("invalid type %d.\n", type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (chipset_DriverInfo)
|
||||||
|
BusDeviceInfo_Init(chipset_DriverInfo,
|
||||||
|
"chipset", "uislib",
|
||||||
|
VERSION, NULL, __DATE__, __TIME__);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(uisctrl_register_req_handler);
|
||||||
|
|
||||||
|
int
|
||||||
|
uisctrl_register_req_handler_ex(GUID switchTypeGuid,
|
||||||
|
const char *switch_type_name,
|
||||||
|
int (*controlfunc)(struct io_msgs *),
|
||||||
|
unsigned long min_channel_bytes,
|
||||||
|
int (*Server_Channel_Ok)(unsigned long
|
||||||
|
channelBytes),
|
||||||
|
int (*Server_Channel_Init)
|
||||||
|
(void *x, unsigned char *clientStr,
|
||||||
|
U32 clientStrLen, U64 bytes),
|
||||||
|
ULTRA_VBUS_DEVICEINFO *chipset_DriverInfo)
|
||||||
|
{
|
||||||
|
char s[99];
|
||||||
|
ReqHandlerInfo_t *pReqHandlerInfo;
|
||||||
|
int rc = 0; /* assume failure */
|
||||||
|
LOGINF("type=%s, controlfunc=0x%p.\n",
|
||||||
|
GUID_format1(&switchTypeGuid, s), controlfunc);
|
||||||
|
if (!controlfunc) {
|
||||||
|
LOGERR("%s: controlfunc must be supplied\n",
|
||||||
|
GUID_format1(&switchTypeGuid, s));
|
||||||
|
goto Away;
|
||||||
|
}
|
||||||
|
if (!Server_Channel_Ok) {
|
||||||
|
LOGERR("%s: Server_Channel_Ok must be supplied\n",
|
||||||
|
GUID_format1(&switchTypeGuid, s));
|
||||||
|
goto Away;
|
||||||
|
}
|
||||||
|
if (!Server_Channel_Init) {
|
||||||
|
LOGERR("%s: Server_Channel_Init must be supplied\n",
|
||||||
|
GUID_format1(&switchTypeGuid, s));
|
||||||
|
goto Away;
|
||||||
|
}
|
||||||
|
pReqHandlerInfo = ReqHandlerAdd(switchTypeGuid,
|
||||||
|
switch_type_name,
|
||||||
|
controlfunc,
|
||||||
|
min_channel_bytes,
|
||||||
|
Server_Channel_Ok, Server_Channel_Init);
|
||||||
|
if (!pReqHandlerInfo) {
|
||||||
|
LOGERR("failed to add %s to server list\n",
|
||||||
|
GUID_format1(&switchTypeGuid, s));
|
||||||
|
goto Away;
|
||||||
|
}
|
||||||
|
|
||||||
|
atomic_inc(&UisUtils_Registered_Services);
|
||||||
|
rc = 1; /* success */
|
||||||
|
Away:
|
||||||
|
if (rc) {
|
||||||
|
if (chipset_DriverInfo)
|
||||||
|
BusDeviceInfo_Init(chipset_DriverInfo,
|
||||||
|
"chipset", "uislib",
|
||||||
|
VERSION, NULL,
|
||||||
|
__DATE__, __TIME__);
|
||||||
|
} else
|
||||||
|
LOGERR("failed to register type %s.\n",
|
||||||
|
GUID_format1(&switchTypeGuid, s));
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(uisctrl_register_req_handler_ex);
|
||||||
|
|
||||||
|
int
|
||||||
|
uisctrl_unregister_req_handler_ex(GUID switchTypeGuid)
|
||||||
|
{
|
||||||
|
char s[99];
|
||||||
|
int rc = 0; /* assume failure */
|
||||||
|
LOGINF("type=%s.\n", GUID_format1(&switchTypeGuid, s));
|
||||||
|
if (ReqHandlerDel(switchTypeGuid) < 0) {
|
||||||
|
LOGERR("failed to remove %s from server list\n",
|
||||||
|
GUID_format1(&switchTypeGuid, s));
|
||||||
|
goto Away;
|
||||||
|
}
|
||||||
|
atomic_dec(&UisUtils_Registered_Services);
|
||||||
|
rc = 1; /* success */
|
||||||
|
Away:
|
||||||
|
if (!rc)
|
||||||
|
LOGERR("failed to unregister type %s.\n",
|
||||||
|
GUID_format1(&switchTypeGuid, s));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(uisctrl_unregister_req_handler_ex);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* unsigned int util_copy_fragsinfo_from_skb(unsigned char *calling_ctx,
|
||||||
|
* void *skb_in,
|
||||||
|
* unsigned int firstfraglen,
|
||||||
|
* unsigned int frags_max,
|
||||||
|
* struct phys_info frags[])
|
||||||
|
*
|
||||||
|
* calling_ctx - input - a string that is displayed to show
|
||||||
|
* who called * this func
|
||||||
|
* void *skb_in - skb whose frag info we're copying type is hidden so we
|
||||||
|
* don't need to include skbbuff in uisutils.h which is
|
||||||
|
* included in non-networking code.
|
||||||
|
* unsigned int firstfraglen - input - length of first fragment in skb
|
||||||
|
* unsigned int frags_max - input - max len of frags array
|
||||||
|
* struct phys_info frags[] - output - frags array filled in on output
|
||||||
|
* return value indicates number of
|
||||||
|
* entries filled in frags
|
||||||
|
*/
|
||||||
|
unsigned int
|
||||||
|
util_copy_fragsinfo_from_skb(unsigned char *calling_ctx, void *skb_in,
|
||||||
|
unsigned int firstfraglen, unsigned int frags_max,
|
||||||
|
struct phys_info frags[])
|
||||||
|
{
|
||||||
|
unsigned int count = 0, ii, size, offset = 0, numfrags;
|
||||||
|
struct sk_buff *skb = skb_in;
|
||||||
|
|
||||||
|
numfrags = skb_shinfo(skb)->nr_frags;
|
||||||
|
|
||||||
|
while (firstfraglen) {
|
||||||
|
if (count == frags_max) {
|
||||||
|
LOGERR("%s frags array too small: max:%d count:%d\n",
|
||||||
|
calling_ctx, frags_max, count);
|
||||||
|
return -1; /* failure */
|
||||||
|
}
|
||||||
|
frags[count].pi_pfn =
|
||||||
|
page_to_pfn(virt_to_page(skb->data + offset));
|
||||||
|
frags[count].pi_off =
|
||||||
|
(unsigned long) (skb->data + offset) & PI_PAGE_MASK;
|
||||||
|
size =
|
||||||
|
min(firstfraglen,
|
||||||
|
(unsigned int) (PI_PAGE_SIZE - frags[count].pi_off));
|
||||||
|
/* can take smallest of firstfraglen(what's left) OR
|
||||||
|
* bytes left in the page
|
||||||
|
*/
|
||||||
|
frags[count].pi_len = size;
|
||||||
|
firstfraglen -= size;
|
||||||
|
offset += size;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if (numfrags) {
|
||||||
|
if ((count + numfrags) > frags_max) {
|
||||||
|
LOGERR("**** FAILED %s frags array too small: max:%d count+nr_frags:%d\n",
|
||||||
|
calling_ctx, frags_max, count + numfrags);
|
||||||
|
return -1; /* failure */
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ii = 0; ii < numfrags; ii++) {
|
||||||
|
count = add_physinfo_entries(page_to_pfn(skb_frag_page(&skb_shinfo(skb)->frags[ii])), /* pfn */
|
||||||
|
skb_shinfo(skb)->frags[ii].
|
||||||
|
page_offset,
|
||||||
|
skb_shinfo(skb)->frags[ii].
|
||||||
|
size, count, frags_max,
|
||||||
|
frags);
|
||||||
|
if (count == 0) {
|
||||||
|
LOGERR("**** FAILED to add physinfo entries\n");
|
||||||
|
return -1; /* failure */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (skb_shinfo(skb)->frag_list) {
|
||||||
|
struct sk_buff *skbinlist;
|
||||||
|
int c;
|
||||||
|
for (skbinlist = skb_shinfo(skb)->frag_list; skbinlist;
|
||||||
|
skbinlist = skbinlist->next) {
|
||||||
|
|
||||||
|
c = util_copy_fragsinfo_from_skb("recursive", skbinlist,
|
||||||
|
skbinlist->len -
|
||||||
|
skbinlist->data_len,
|
||||||
|
frags_max - count,
|
||||||
|
&frags[count]);
|
||||||
|
if (c == -1) {
|
||||||
|
LOGERR("**** FAILED recursive call failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
count += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(util_copy_fragsinfo_from_skb);
|
||||||
|
|
||||||
|
static LIST_HEAD(ReqHandlerInfo_list); /* list of ReqHandlerInfo_t */
|
||||||
|
static DEFINE_SPINLOCK(ReqHandlerInfo_list_lock);
|
||||||
|
|
||||||
|
ReqHandlerInfo_t *
|
||||||
|
ReqHandlerAdd(GUID switchTypeGuid,
|
||||||
|
const char *switch_type_name,
|
||||||
|
int (*controlfunc)(struct io_msgs *),
|
||||||
|
unsigned long min_channel_bytes,
|
||||||
|
int (*Server_Channel_Ok)(unsigned long channelBytes),
|
||||||
|
int (*Server_Channel_Init)
|
||||||
|
(void *x, unsigned char *clientStr, U32 clientStrLen, U64 bytes))
|
||||||
|
{
|
||||||
|
ReqHandlerInfo_t *rc = NULL;
|
||||||
|
|
||||||
|
rc = UISMALLOC(sizeof(*rc), GFP_ATOMIC);
|
||||||
|
if (!rc)
|
||||||
|
return NULL;
|
||||||
|
memset(rc, 0, sizeof(*rc));
|
||||||
|
rc->switchTypeGuid = switchTypeGuid;
|
||||||
|
rc->controlfunc = controlfunc;
|
||||||
|
rc->min_channel_bytes = min_channel_bytes;
|
||||||
|
rc->Server_Channel_Ok = Server_Channel_Ok;
|
||||||
|
rc->Server_Channel_Init = Server_Channel_Init;
|
||||||
|
if (switch_type_name)
|
||||||
|
strncpy(rc->switch_type_name, switch_type_name,
|
||||||
|
sizeof(rc->switch_type_name) - 1);
|
||||||
|
spin_lock(&ReqHandlerInfo_list_lock);
|
||||||
|
list_add_tail(&(rc->list_link), &ReqHandlerInfo_list);
|
||||||
|
spin_unlock(&ReqHandlerInfo_list_lock);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReqHandlerInfo_t *
|
||||||
|
ReqHandlerFind(GUID switchTypeGuid)
|
||||||
|
{
|
||||||
|
struct list_head *lelt, *tmp;
|
||||||
|
ReqHandlerInfo_t *entry = NULL;
|
||||||
|
spin_lock(&ReqHandlerInfo_list_lock);
|
||||||
|
list_for_each_safe(lelt, tmp, &ReqHandlerInfo_list) {
|
||||||
|
entry = list_entry(lelt, ReqHandlerInfo_t, list_link);
|
||||||
|
if (memcmp
|
||||||
|
(&entry->switchTypeGuid, &switchTypeGuid,
|
||||||
|
sizeof(GUID)) == 0) {
|
||||||
|
spin_unlock(&ReqHandlerInfo_list_lock);
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spin_unlock(&ReqHandlerInfo_list_lock);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ReqHandlerDel(GUID switchTypeGuid)
|
||||||
|
{
|
||||||
|
struct list_head *lelt, *tmp;
|
||||||
|
ReqHandlerInfo_t *entry = NULL;
|
||||||
|
int rc = -1;
|
||||||
|
spin_lock(&ReqHandlerInfo_list_lock);
|
||||||
|
list_for_each_safe(lelt, tmp, &ReqHandlerInfo_list) {
|
||||||
|
entry = list_entry(lelt, ReqHandlerInfo_t, list_link);
|
||||||
|
if (memcmp
|
||||||
|
(&entry->switchTypeGuid, &switchTypeGuid,
|
||||||
|
sizeof(GUID)) == 0) {
|
||||||
|
list_del(lelt);
|
||||||
|
UISFREE(entry, sizeof(*entry));
|
||||||
|
rc++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spin_unlock(&ReqHandlerInfo_list_lock);
|
||||||
|
return rc;
|
||||||
|
}
|
Loading…
Reference in a new issue