1/* uisutils.c
2 *
3 * Copyright (C) 2010 - 2013 UNISYS CORPORATION
4 * All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or (at
9 * your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
14 * NON INFRINGEMENT.  See the GNU General Public License for more
15 * details.
16 */
17
18#include <linux/string.h>
19#include <linux/slab.h>
20#include <linux/types.h>
21#include <linux/uuid.h>
22#include <linux/spinlock.h>
23#include <linux/list.h>
24#include "uisutils.h"
25#include "version.h"
26#include "vbushelper.h"
27#include <linux/skbuff.h>
28#ifdef CONFIG_HIGHMEM
29#include <linux/highmem.h>
30#endif
31
32/* this is shorter than using __FILE__ (full path name) in
33 * debug/info/error messages
34 */
35#define CURRENT_FILE_PC UISLIB_PC_uisutils_c
36#define __MYFILE__ "uisutils.c"
37
38/* exports */
39atomic_t uisutils_registered_services = ATOMIC_INIT(0);
40					/* num registrations via
41					 * uisctrl_register_req_handler() or
42					 * uisctrl_register_req_handler_ex() */
43
44/*****************************************************/
45/* Utility functions                                 */
46/*****************************************************/
47
48int
49uisutil_add_proc_line_ex(int *total, char **buffer, int *buffer_remaining,
50			 char *format, ...)
51{
52	va_list args;
53	int len;
54
55	va_start(args, format);
56	len = vsnprintf(*buffer, *buffer_remaining, format, args);
57	va_end(args);
58	if (len >= *buffer_remaining) {
59		*buffer += *buffer_remaining;
60		*total += *buffer_remaining;
61		*buffer_remaining = 0;
62		return -1;
63	}
64	*buffer_remaining -= len;
65	*buffer += len;
66	*total += len;
67	return len;
68}
69EXPORT_SYMBOL_GPL(uisutil_add_proc_line_ex);
70
71int
72uisctrl_register_req_handler(int type, void *fptr,
73			     struct ultra_vbus_deviceinfo *chipset_driver_info)
74{
75	switch (type) {
76	case 2:
77		if (fptr) {
78			if (!virt_control_chan_func)
79				atomic_inc(&uisutils_registered_services);
80			virt_control_chan_func = fptr;
81		} else {
82			if (virt_control_chan_func)
83				atomic_dec(&uisutils_registered_services);
84			virt_control_chan_func = NULL;
85		}
86		break;
87
88	default:
89		return 0;
90	}
91	if (chipset_driver_info)
92		bus_device_info_init(chipset_driver_info, "chipset", "uislib",
93				     VERSION, NULL);
94
95	return 1;
96}
97EXPORT_SYMBOL_GPL(uisctrl_register_req_handler);
98
99/*
100 * unsigned int uisutil_copy_fragsinfo_from_skb(unsigned char *calling_ctx,
101 *					     void *skb_in,
102 *					     unsigned int firstfraglen,
103 *					     unsigned int frags_max,
104 *					     struct phys_info frags[])
105 *
106 *	calling_ctx - input -   a string that is displayed to show
107 *				who called * this func
108 *	void *skb_in -  skb whose frag info we're copying type is hidden so we
109 *			don't need to include skbbuff in uisutils.h which is
110 *			included in non-networking code.
111 *	unsigned int firstfraglen - input - length of first fragment in skb
112 *	unsigned int frags_max - input - max len of frags array
113 *	struct phys_info frags[] - output - frags array filled in on output
114 *					    return value indicates number of
115 *					    entries filled in frags
116 */
117
118static LIST_HEAD(req_handler_info_list); /* list of struct req_handler_info */
119static DEFINE_SPINLOCK(req_handler_info_list_lock);
120
121struct req_handler_info *
122req_handler_find(uuid_le switch_uuid)
123{
124	struct list_head *lelt, *tmp;
125	struct req_handler_info *entry = NULL;
126
127	spin_lock(&req_handler_info_list_lock);
128	list_for_each_safe(lelt, tmp, &req_handler_info_list) {
129		entry = list_entry(lelt, struct req_handler_info, list_link);
130		if (uuid_le_cmp(entry->switch_uuid, switch_uuid) == 0) {
131			spin_unlock(&req_handler_info_list_lock);
132			return entry;
133		}
134	}
135	spin_unlock(&req_handler_info_list_lock);
136	return NULL;
137}
138